Re: [PATCH v12 2/5] clk: imx: add fractional PLL output clock

2018-11-09 Thread Stephen Boyd
Quoting kbuild test robot (2018-11-09 02:18:24)
> Hi Lucas,
> 
> I love your patch! Yet something to improve:
> 
> [auto build test ERROR on shawnguo/for-next]
> [also build test ERROR on v4.20-rc1 next-20181109]
> [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/Abel-Vesa/Add-i-MX8MQ-clock-driver/20181109-063930
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git 
> for-next
> config: arm-multi_v5_defconfig (attached as .config)
> compiler: arm-linux-gnueabi-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
> GCC_VERSION=7.2.0 make.cross ARCH=arm 
> 
> All errors (new ones prefixed by >>):
> 
>drivers/clk/imx/clk-frac-pll.o: In function `clk_pll_recalc_rate':
> >> clk-frac-pll.c:(.text+0x74): undefined reference to `__aeabi_uldivmod'
>drivers/clk/imx/clk-frac-pll.o: In function `clk_pll_round_rate':
>clk-frac-pll.c:(.text+0xbc): undefined reference to `__aeabi_uldivmod'
> 

Why does the code do essentially:

u64 val;

do_div(val, div);
val /= div2;

That should be using do_div() twice it seems.



Re: [PATCH v12 2/5] clk: imx: add fractional PLL output clock

2018-11-09 Thread Stephen Boyd
Quoting kbuild test robot (2018-11-09 02:18:24)
> Hi Lucas,
> 
> I love your patch! Yet something to improve:
> 
> [auto build test ERROR on shawnguo/for-next]
> [also build test ERROR on v4.20-rc1 next-20181109]
> [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/Abel-Vesa/Add-i-MX8MQ-clock-driver/20181109-063930
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git 
> for-next
> config: arm-multi_v5_defconfig (attached as .config)
> compiler: arm-linux-gnueabi-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
> GCC_VERSION=7.2.0 make.cross ARCH=arm 
> 
> All errors (new ones prefixed by >>):
> 
>drivers/clk/imx/clk-frac-pll.o: In function `clk_pll_recalc_rate':
> >> clk-frac-pll.c:(.text+0x74): undefined reference to `__aeabi_uldivmod'
>drivers/clk/imx/clk-frac-pll.o: In function `clk_pll_round_rate':
>clk-frac-pll.c:(.text+0xbc): undefined reference to `__aeabi_uldivmod'
> 

Why does the code do essentially:

u64 val;

do_div(val, div);
val /= div2;

That should be using do_div() twice it seems.



Re: [PATCH v12 2/5] clk: imx: add fractional PLL output clock

2018-11-09 Thread kbuild test robot
Hi Lucas,

I love your patch! Yet something to improve:

[auto build test ERROR on shawnguo/for-next]
[also build test ERROR on v4.20-rc1 next-20181109]
[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/Abel-Vesa/Add-i-MX8MQ-clock-driver/20181109-063930
base:   https://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git 
for-next
config: arm-multi_v5_defconfig (attached as .config)
compiler: arm-linux-gnueabi-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
GCC_VERSION=7.2.0 make.cross ARCH=arm 

All errors (new ones prefixed by >>):

   drivers/clk/imx/clk-frac-pll.o: In function `clk_pll_recalc_rate':
>> clk-frac-pll.c:(.text+0x74): undefined reference to `__aeabi_uldivmod'
   drivers/clk/imx/clk-frac-pll.o: In function `clk_pll_round_rate':
   clk-frac-pll.c:(.text+0xbc): undefined reference to `__aeabi_uldivmod'

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


.config.gz
Description: application/gzip


Re: [PATCH v12 2/5] clk: imx: add fractional PLL output clock

2018-11-09 Thread kbuild test robot
Hi Lucas,

I love your patch! Yet something to improve:

[auto build test ERROR on shawnguo/for-next]
[also build test ERROR on v4.20-rc1 next-20181109]
[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/Abel-Vesa/Add-i-MX8MQ-clock-driver/20181109-063930
base:   https://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git 
for-next
config: arm-multi_v5_defconfig (attached as .config)
compiler: arm-linux-gnueabi-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
GCC_VERSION=7.2.0 make.cross ARCH=arm 

All errors (new ones prefixed by >>):

   drivers/clk/imx/clk-frac-pll.o: In function `clk_pll_recalc_rate':
>> clk-frac-pll.c:(.text+0x74): undefined reference to `__aeabi_uldivmod'
   drivers/clk/imx/clk-frac-pll.o: In function `clk_pll_round_rate':
   clk-frac-pll.c:(.text+0xbc): undefined reference to `__aeabi_uldivmod'

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


.config.gz
Description: application/gzip


[PATCH v12 2/5] clk: imx: add fractional PLL output clock

2018-11-07 Thread Abel Vesa
From: Lucas Stach 

This is a new fractional clock type introduced on i.MX8.

The description of this fractional clock can be found here:

https://www.nxp.com/docs/en/reference-manual/IMX8MDQLQRM.pdf#page=834

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
Reviewed-by: Sascha Hauer 
---
 drivers/clk/imx/Makefile   |   1 +
 drivers/clk/imx/clk-frac-pll.c | 221 +
 drivers/clk/imx/clk.h  |   3 +
 3 files changed, 225 insertions(+)
 create mode 100644 drivers/clk/imx/clk-frac-pll.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 8c3baa7..4893c1f 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -6,6 +6,7 @@ obj-y += \
clk-cpu.o \
clk-fixup-div.o \
clk-fixup-mux.o \
+   clk-frac-pll.o \
clk-gate-exclusive.o \
clk-gate2.o \
clk-pllv1.o \
diff --git a/drivers/clk/imx/clk-frac-pll.c b/drivers/clk/imx/clk-frac-pll.c
new file mode 100644
index 000..a800093
--- /dev/null
+++ b/drivers/clk/imx/clk-frac-pll.c
@@ -0,0 +1,221 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 NXP.
+ *
+ * This driver supports the fractional plls found in the imx8m SOCs
+ *
+ * Documentation for this fractional pll can be found at:
+ *   https://www.nxp.com/docs/en/reference-manual/IMX8MDQLQRM.pdf#page=834
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define PLL_CFG0   0x0
+#define PLL_CFG1   0x4
+
+#define PLL_LOCK_STATUSBIT(31)
+#define PLL_PD_MASKBIT(19)
+#define PLL_BYPASS_MASKBIT(14)
+#define PLL_NEWDIV_VAL BIT(12)
+#define PLL_NEWDIV_ACK BIT(11)
+#define PLL_FRAC_DIV_MASK  GENMASK(30, 7)
+#define PLL_INT_DIV_MASK   GENMASK(6, 0)
+#define PLL_OUTPUT_DIV_MASKGENMASK(4, 0)
+#define PLL_FRAC_DENOM 0x100
+
+#define PLL_FRAC_LOCK_TIMEOUT  1
+#define PLL_FRAC_ACK_TIMEOUT   50
+
+struct clk_frac_pll {
+   struct clk_hw   hw;
+   void __iomem*base;
+};
+
+#define to_clk_frac_pll(_hw) container_of(_hw, struct clk_frac_pll, hw)
+
+static int clk_wait_lock(struct clk_frac_pll *pll)
+{
+   u32 val;
+
+   return readl_poll_timeout(pll->base, val, val & PLL_LOCK_STATUS, 0,
+   PLL_FRAC_LOCK_TIMEOUT);
+}
+
+static int clk_wait_ack(struct clk_frac_pll *pll)
+{
+   u32 val;
+
+   /* return directly if the pll is in powerdown or in bypass */
+   if (readl_relaxed(pll->base) & (PLL_PD_MASK | PLL_BYPASS_MASK))
+   return 0;
+
+   /* Wait for the pll's divfi and divff to be reloaded */
+   return readl_poll_timeout(pll->base, val, val & PLL_NEWDIV_ACK, 0,
+   PLL_FRAC_ACK_TIMEOUT);
+}
+
+static int clk_pll_prepare(struct clk_hw *hw)
+{
+   struct clk_frac_pll *pll = to_clk_frac_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   val &= ~PLL_PD_MASK;
+   writel_relaxed(val, pll->base + PLL_CFG0);
+
+   return clk_wait_lock(pll);
+}
+
+static void clk_pll_unprepare(struct clk_hw *hw)
+{
+   struct clk_frac_pll *pll = to_clk_frac_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   val |= PLL_PD_MASK;
+   writel_relaxed(val, pll->base + PLL_CFG0);
+}
+
+static int clk_pll_is_prepared(struct clk_hw *hw)
+{
+   struct clk_frac_pll *pll = to_clk_frac_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   return (val & PLL_PD_MASK) ? 0 : 1;
+}
+
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
+unsigned long parent_rate)
+{
+   struct clk_frac_pll *pll = to_clk_frac_pll(hw);
+   u32 val, divff, divfi, divq;
+   u64 temp64 = parent_rate;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   divq = ((val & PLL_OUTPUT_DIV_MASK) + 1) * 2;
+   val = readl_relaxed(pll->base + PLL_CFG1);
+   divff = FIELD_GET(PLL_FRAC_DIV_MASK, val);
+   divfi = val & PLL_INT_DIV_MASK;
+
+   temp64 *= 8;
+   temp64 *= divff;
+   do_div(temp64, PLL_FRAC_DENOM);
+   temp64 /= divq;
+
+   return parent_rate * 8 * (divfi + 1) / divq + (unsigned long)temp64;
+}
+
+static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+  unsigned long *prate)
+{
+   u64 parent_rate = *prate;
+   u32 divff, divfi;
+   u64 temp64;
+
+   parent_rate *= 8;
+   rate *= 2;
+   divfi = rate / parent_rate;
+   temp64 = rate - divfi * parent_rate;
+   temp64 *= PLL_FRAC_DENOM;
+   do_div(temp64, parent_rate);
+   divff = temp64;
+
+   temp64 = parent_rate;
+   temp64 *= divff;
+   do_div(temp64, PLL_FRAC_DENOM);
+
+   return (parent_rate * divfi + temp64) / 2;
+}
+
+/*
+ * To simplify the clock calculation, we can keep the 'PLL_OUTPUT_VAL' at zero
+ * (means the PLL 

[PATCH v12 2/5] clk: imx: add fractional PLL output clock

2018-11-07 Thread Abel Vesa
From: Lucas Stach 

This is a new fractional clock type introduced on i.MX8.

The description of this fractional clock can be found here:

https://www.nxp.com/docs/en/reference-manual/IMX8MDQLQRM.pdf#page=834

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
Reviewed-by: Sascha Hauer 
---
 drivers/clk/imx/Makefile   |   1 +
 drivers/clk/imx/clk-frac-pll.c | 221 +
 drivers/clk/imx/clk.h  |   3 +
 3 files changed, 225 insertions(+)
 create mode 100644 drivers/clk/imx/clk-frac-pll.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 8c3baa7..4893c1f 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -6,6 +6,7 @@ obj-y += \
clk-cpu.o \
clk-fixup-div.o \
clk-fixup-mux.o \
+   clk-frac-pll.o \
clk-gate-exclusive.o \
clk-gate2.o \
clk-pllv1.o \
diff --git a/drivers/clk/imx/clk-frac-pll.c b/drivers/clk/imx/clk-frac-pll.c
new file mode 100644
index 000..a800093
--- /dev/null
+++ b/drivers/clk/imx/clk-frac-pll.c
@@ -0,0 +1,221 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 NXP.
+ *
+ * This driver supports the fractional plls found in the imx8m SOCs
+ *
+ * Documentation for this fractional pll can be found at:
+ *   https://www.nxp.com/docs/en/reference-manual/IMX8MDQLQRM.pdf#page=834
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define PLL_CFG0   0x0
+#define PLL_CFG1   0x4
+
+#define PLL_LOCK_STATUSBIT(31)
+#define PLL_PD_MASKBIT(19)
+#define PLL_BYPASS_MASKBIT(14)
+#define PLL_NEWDIV_VAL BIT(12)
+#define PLL_NEWDIV_ACK BIT(11)
+#define PLL_FRAC_DIV_MASK  GENMASK(30, 7)
+#define PLL_INT_DIV_MASK   GENMASK(6, 0)
+#define PLL_OUTPUT_DIV_MASKGENMASK(4, 0)
+#define PLL_FRAC_DENOM 0x100
+
+#define PLL_FRAC_LOCK_TIMEOUT  1
+#define PLL_FRAC_ACK_TIMEOUT   50
+
+struct clk_frac_pll {
+   struct clk_hw   hw;
+   void __iomem*base;
+};
+
+#define to_clk_frac_pll(_hw) container_of(_hw, struct clk_frac_pll, hw)
+
+static int clk_wait_lock(struct clk_frac_pll *pll)
+{
+   u32 val;
+
+   return readl_poll_timeout(pll->base, val, val & PLL_LOCK_STATUS, 0,
+   PLL_FRAC_LOCK_TIMEOUT);
+}
+
+static int clk_wait_ack(struct clk_frac_pll *pll)
+{
+   u32 val;
+
+   /* return directly if the pll is in powerdown or in bypass */
+   if (readl_relaxed(pll->base) & (PLL_PD_MASK | PLL_BYPASS_MASK))
+   return 0;
+
+   /* Wait for the pll's divfi and divff to be reloaded */
+   return readl_poll_timeout(pll->base, val, val & PLL_NEWDIV_ACK, 0,
+   PLL_FRAC_ACK_TIMEOUT);
+}
+
+static int clk_pll_prepare(struct clk_hw *hw)
+{
+   struct clk_frac_pll *pll = to_clk_frac_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   val &= ~PLL_PD_MASK;
+   writel_relaxed(val, pll->base + PLL_CFG0);
+
+   return clk_wait_lock(pll);
+}
+
+static void clk_pll_unprepare(struct clk_hw *hw)
+{
+   struct clk_frac_pll *pll = to_clk_frac_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   val |= PLL_PD_MASK;
+   writel_relaxed(val, pll->base + PLL_CFG0);
+}
+
+static int clk_pll_is_prepared(struct clk_hw *hw)
+{
+   struct clk_frac_pll *pll = to_clk_frac_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   return (val & PLL_PD_MASK) ? 0 : 1;
+}
+
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
+unsigned long parent_rate)
+{
+   struct clk_frac_pll *pll = to_clk_frac_pll(hw);
+   u32 val, divff, divfi, divq;
+   u64 temp64 = parent_rate;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   divq = ((val & PLL_OUTPUT_DIV_MASK) + 1) * 2;
+   val = readl_relaxed(pll->base + PLL_CFG1);
+   divff = FIELD_GET(PLL_FRAC_DIV_MASK, val);
+   divfi = val & PLL_INT_DIV_MASK;
+
+   temp64 *= 8;
+   temp64 *= divff;
+   do_div(temp64, PLL_FRAC_DENOM);
+   temp64 /= divq;
+
+   return parent_rate * 8 * (divfi + 1) / divq + (unsigned long)temp64;
+}
+
+static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+  unsigned long *prate)
+{
+   u64 parent_rate = *prate;
+   u32 divff, divfi;
+   u64 temp64;
+
+   parent_rate *= 8;
+   rate *= 2;
+   divfi = rate / parent_rate;
+   temp64 = rate - divfi * parent_rate;
+   temp64 *= PLL_FRAC_DENOM;
+   do_div(temp64, parent_rate);
+   divff = temp64;
+
+   temp64 = parent_rate;
+   temp64 *= divff;
+   do_div(temp64, PLL_FRAC_DENOM);
+
+   return (parent_rate * divfi + temp64) / 2;
+}
+
+/*
+ * To simplify the clock calculation, we can keep the 'PLL_OUTPUT_VAL' at zero
+ * (means the PLL