Re: [PATCH 4/6] clk: ingenic: Add JZ47xx TCU clocks driver

2018-01-01 Thread kbuild test robot
Hi Paul,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on tip/irq/core]
[also build test ERROR on v4.15-rc6 next-20171222]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Paul-Cercueil/Ingenic-JZ47xx-TCU-drivers/20180101-184936
config: mips-qi_lb60_defconfig (attached as .config)
compiler: mipsel-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=mips 

All errors (new ones prefixed by >>):

   drivers/clk//ingenic/tcu.c: In function 'ingenic_tcu_init':
>> drivers/clk//ingenic/tcu.c:293:29: error: 'nb_clocks' undeclared (first use 
>> in this function); did you mean 'nb_clks'?
 tcu->clocks.clks = kcalloc(nb_clocks, sizeof(struct clk *), GFP_KERNEL);
^
nb_clks
   drivers/clk//ingenic/tcu.c:293:29: note: each undeclared identifier is 
reported only once for each function it appears in

vim +293 drivers/clk//ingenic/tcu.c

   267  
   268  static void __init ingenic_tcu_init(struct device_node *np,
   269  enum ingenic_version id)
   270  {
   271  struct ingenic_tcu *tcu;
   272  size_t i, nb_clks;
   273  int ret = -ENOMEM;
   274  
   275  if (id >= ID_JZ4770)
   276  nb_clks = (JZ4770_CLK_LAST - JZ4740_CLK_TIMER0) + 1;
   277  else
   278  nb_clks = (JZ4740_CLK_LAST - JZ4740_CLK_TIMER0) + 1;
   279  
   280  tcu = kzalloc(sizeof(*tcu), GFP_KERNEL);
   281  if (!tcu) {
   282  pr_err("%s: cannot allocate memory\n", __func__);
   283  return;
   284  }
   285  
   286  tcu->map = syscon_node_to_regmap(np->parent);
   287  if (IS_ERR(tcu->map)) {
   288  pr_err("%s: failed to map TCU registers\n", __func__);
   289  goto err_free_tcu;
   290  }
   291  
   292  tcu->clocks.clk_num = nb_clks;
 > 293  tcu->clocks.clks = kcalloc(nb_clocks, sizeof(struct clk *), 
 > GFP_KERNEL);
   294  if (!tcu->clocks.clks) {
   295  pr_err("%s: cannot allocate memory\n", __func__);
   296  goto err_free_tcu;
   297  }
   298  
   299  for (i = 0; i < nb_clks; i++) {
   300  ret = ingenic_tcu_register_clock(tcu, i,
   301  &ingenic_tcu_clk_info[JZ4740_CLK_TIMER0 
+ i]);
   302  if (ret) {
   303  pr_err("%s: cannot register clocks\n", 
__func__);
   304  goto err_unregister;
   305  }
   306  }
   307  
   308  ret = of_clk_add_provider(np, of_clk_src_onecell_get, 
&tcu->clocks);
   309  if (ret) {
   310  pr_err("%s: cannot add OF clock provider\n", __func__);
   311  goto err_unregister;
   312  }
   313  
   314  return;
   315  
   316  err_unregister:
   317  for (i = 0; i < tcu->clocks.clk_num; i++)
   318  if (tcu->clocks.clks[i])
   319  clk_unregister(tcu->clocks.clks[i]);
   320  kfree(tcu->clocks.clks);
   321  err_free_tcu:
   322  kfree(tcu);
   323  }
   324  

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip


Re: [PATCH 4/6] clk: ingenic: Add JZ47xx TCU clocks driver

2017-12-29 Thread Paul Cercueil


[...]


+   tcu->clocks.clk_num = nb_clks;
+	tcu->clocks.clks = kcalloc(nb_clocks, sizeof(struct clk *), 
GFP_KERNEL);

+   if (!tcu->clocks.clks) {
+   pr_err("%s: cannot allocate memory\n", __func__);
+   goto err_free_tcu;
+   }


Facepalm. A quick edit from kzalloc to kcalloc and I managed to break 
it.

It should be nb_clks not nb_clocks. I'll fix that in the V2.

-Paul



[PATCH 4/6] clk: ingenic: Add JZ47xx TCU clocks driver

2017-12-29 Thread Paul Cercueil
The TCU (Timer Counter Unit) of the Ingenic JZ47xx SoCs features 8
channels, each one having its own clock, that can be started and
stopped, reparented, and reclocked.

This driver only modifies the bits of the registers of the TCU that are
related to clocks control. It provides one clock per TCU channel (plus
one for the watchdog and one for the OS timer) that can be used by other
drivers.

Signed-off-by: Paul Cercueil 
---
 .../bindings/clock/ingenic,tcu-clocks.txt  |  35 +++
 drivers/clk/ingenic/Makefile   |   2 +-
 drivers/clk/ingenic/tcu.c  | 341 +
 3 files changed, 377 insertions(+), 1 deletion(-)
 create mode 100644 
Documentation/devicetree/bindings/clock/ingenic,tcu-clocks.txt
 create mode 100644 drivers/clk/ingenic/tcu.c

diff --git a/Documentation/devicetree/bindings/clock/ingenic,tcu-clocks.txt 
b/Documentation/devicetree/bindings/clock/ingenic,tcu-clocks.txt
new file mode 100644
index ..ed1468a6aa27
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ingenic,tcu-clocks.txt
@@ -0,0 +1,35 @@
+Ingenic SoC TCU binding
+
+The TCU is the Timer/Counter Unit present in all Ingenic SoCs. It features 8
+channels, each one having its own clock, that can be started and stopped,
+reparented, and reclocked.
+
+Required properties:
+- compatible : One of:
+  * ingenic,jz4740-tcu-clocks,
+  * ingenic,jz4770-tcu-clocks,
+  * ingenic,jz4780-tcu-clocks.
+- clocks : List of phandle & clock specifiers for clocks external to the TCU.
+  The "pclk", "rtc" and "ext" clocks should be provided.
+- clock-names : List of name strings for the external clocks.
+- #clock-cells: Should be 1.
+  Clock consumers specify this argument to identify a clock. The valid values
+  may be found in .
+
+Example:
+
+/ {
+   regmap {
+   compatible = "simple-mfd", "syscon";
+   reg = <0x10002000 0x1000>;
+
+   tcu: clocks {
+   compatible = "ingenic,jz4740-tcu-clocks";
+
+   clocks = <&ext>, <&rtc>, <&pclk>;
+   clock-names = "ext", "rtc", "pclk";
+
+   #clock-cells = <1>;
+   };
+   };
+};
diff --git a/drivers/clk/ingenic/Makefile b/drivers/clk/ingenic/Makefile
index cd47b0664c2b..e373118a3726 100644
--- a/drivers/clk/ingenic/Makefile
+++ b/drivers/clk/ingenic/Makefile
@@ -1,3 +1,3 @@
-obj-y  += cgu.o
+obj-y  += cgu.o tcu.o
 obj-$(CONFIG_MACH_JZ4740)  += jz4740-cgu.o
 obj-$(CONFIG_MACH_JZ4780)  += jz4780-cgu.o
diff --git a/drivers/clk/ingenic/tcu.c b/drivers/clk/ingenic/tcu.c
new file mode 100644
index ..a1b189984d17
--- /dev/null
+++ b/drivers/clk/ingenic/tcu.c
@@ -0,0 +1,341 @@
+/*
+ * Ingenic JZ47xx SoC TCU clocks driver
+ *
+ * Copyright (C) 2016 Paul Cercueil 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+enum ingenic_version {
+   ID_JZ4740,
+   ID_JZ4770,
+   ID_JZ4780,
+};
+
+struct ingenic_tcu {
+   struct device_node *np;
+   struct regmap *map;
+
+   struct clk_onecell_data clocks;
+};
+
+struct ingenic_tcu_clk_info {
+   struct clk_init_data init_data;
+   u8 gate_bit;
+   u8 tcsr_reg;
+};
+
+struct ingenic_tcu_clk {
+   struct clk_hw hw;
+
+   struct ingenic_tcu *tcu;
+   const struct ingenic_tcu_clk_info *info;
+
+   unsigned int idx;
+};
+
+#define to_tcu_clk(_hw) container_of(_hw, struct ingenic_tcu_clk, hw)
+
+static int ingenic_tcu_enable(struct clk_hw *hw)
+{
+   struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw);
+   const struct ingenic_tcu_clk_info *info = tcu_clk->info;
+   struct ingenic_tcu *tcu = tcu_clk->tcu;
+
+   regmap_write(tcu->map, REG_TSCR, BIT(info->gate_bit));
+   return 0;
+}
+
+static void ingenic_tcu_disable(struct clk_hw *hw)
+{
+   struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw);
+   struct ingenic_tcu *tcu = tcu_clk->tcu;
+   const struct ingenic_tcu_clk_info *info = tcu_clk->info;
+
+   regmap_write(tcu->map, REG_TSSR, BIT(info->gate_bit));
+}
+
+static int ingenic_tcu_is_enabled(struct clk_hw *hw)
+{
+   struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw);
+   struct ingenic_tcu *tcu = tcu_clk->tcu;
+   const struct ingenic_tcu_clk_info *info = tcu_clk->info;
+   unsigned int value;
+
+   regmap_read(tcu->map, REG_TSR, &value);
+
+   return !(value & BIT(info->gate_bit));
+}
+
+static u8 ingenic_tcu_get_parent(struct clk_hw *hw)
+{
+   struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw);
+   struct ingenic_tcu *tcu = tcu_clk->tcu;
+   const struct ingenic_t