[PATCH v5 0/2] pinctrl: imx: Add driver for i.MX8MQ

2018-06-22 Thread Abel Vesa
This is the fifth version for the patch series sent by Lucas.

https://www.spinics.net/lists/devicetree/msg212752.html

Fourth version can be found here:

https://lkml.org/lkml/2018/6/20/478

Changes since v4:
 * implemented all Aisheng's review comments

Changes since v3:
 * dropped the SION generic pinconf changes
 * added examples to the bindings doc

Changes since v2:
 * switch back to the 'fsl,pins' and hardcoded the config values
inside the dts.
 * updated documentation accordingly

Abel Vesa (1):
  dt-bindings: add binding for i.MX8MQ IOMUXC

Lucas Stach (1):
  pinctrl: imx: add driver for i.MX8MQ

 .../bindings/pinctrl/fsl,imx8mq-pinctrl.txt|  32 ++
 drivers/pinctrl/freescale/Kconfig  |   7 +
 drivers/pinctrl/freescale/Makefile |   1 +
 drivers/pinctrl/freescale/pinctrl-imx8mq.c | 351 +
 4 files changed, 391 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt
 create mode 100644 drivers/pinctrl/freescale/pinctrl-imx8mq.c

-- 
2.7.4



[PATCH v5 1/2] dt-bindings: add binding for i.MX8MQ IOMUXC

2018-06-22 Thread Abel Vesa
This adds the binding for the i.MX8MQ pin controller, in the same
fashion as earlier i.MX SoCs.

Signed-off-by: Abel Vesa 
Acked-by: Dong Aisheng 
---
 .../bindings/pinctrl/fsl,imx8mq-pinctrl.txt| 32 ++
 1 file changed, 32 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt

diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt 
b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt
new file mode 100644
index 000..e1c405d
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt
@@ -0,0 +1,32 @@
+* Freescale IMX8MQ IOMUX Controller
+
+Please refer to fsl,imx-pinctrl.txt and pinctrl-bindings.txt in this directory
+for common binding part and usage.
+
+Required properties:
+- compatible: "fsl,imx8mq-iomuxc"
+- fsl,pins: each entry consists of 6 integers and represents the mux and config
+  setting for one pin.  The first 5 integers  are specified using a PIN_FUNC_ID macro, which can be found in
+  imx8mq-pinfunc.h under device tree source folder.  The last integer CONFIG is
+  the pad setting value like pull-up on this pin.  Please refer to i.MX8M Quad
+  Reference Manual for detailed CONFIG settings.
+
+Examples:
+
+&uart1 {
+   pinctrl-names = "default";
+   pinctrl-0 = <&pinctrl_uart1>;
+};
+
+iomuxc: iomuxc@3033 {
+compatible = "fsl,imx8mq-iomuxc";
+reg = <0x0 0x3033 0x0 0x1>;
+
+pinctrl_uart1: uart1grp {
+fsl,pins = <
+MX8MQ_IOMUXC_UART1_RXD_UART1_DCE_RX 0x49
+MX8MQ_IOMUXC_UART1_TXD_UART1_DCE_TX 0x49
+>;
+};
+};
-- 
2.7.4



[PATCH v5 2/2] pinctrl: imx: add driver for i.MX8MQ

2018-06-22 Thread Abel Vesa
From: Lucas Stach 

The i.MX8MQ pincontrol works in a similar way to the earlier i.MX SoCs.
This driver builds on top of the imx specific pinconf handling.

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
Acked-by: Dong Aisheng 
---
 drivers/pinctrl/freescale/Kconfig  |   7 +
 drivers/pinctrl/freescale/Makefile |   1 +
 drivers/pinctrl/freescale/pinctrl-imx8mq.c | 351 +
 3 files changed, 359 insertions(+)
 create mode 100644 drivers/pinctrl/freescale/pinctrl-imx8mq.c

diff --git a/drivers/pinctrl/freescale/Kconfig 
b/drivers/pinctrl/freescale/Kconfig
index 0d8ba1e..dccf64c 100644
--- a/drivers/pinctrl/freescale/Kconfig
+++ b/drivers/pinctrl/freescale/Kconfig
@@ -117,6 +117,13 @@ config PINCTRL_IMX7ULP
help
  Say Y here to enable the imx7ulp pinctrl driver
 
+config PINCTRL_IMX8MQ
+   bool "IMX8MQ pinctrl driver"
+   depends on SOC_IMX8MQ
+   select PINCTRL_IMX
+   help
+ Say Y here to enable the imx8mq pinctrl driver
+
 config PINCTRL_VF610
bool "Freescale Vybrid VF610 pinctrl driver"
depends on SOC_VF610
diff --git a/drivers/pinctrl/freescale/Makefile 
b/drivers/pinctrl/freescale/Makefile
index 368be8c..73175b3 100644
--- a/drivers/pinctrl/freescale/Makefile
+++ b/drivers/pinctrl/freescale/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_PINCTRL_IMX6SX)  += pinctrl-imx6sx.o
 obj-$(CONFIG_PINCTRL_IMX6UL)   += pinctrl-imx6ul.o
 obj-$(CONFIG_PINCTRL_IMX7D)+= pinctrl-imx7d.o
 obj-$(CONFIG_PINCTRL_IMX7ULP)  += pinctrl-imx7ulp.o
+obj-$(CONFIG_PINCTRL_IMX8MQ)   += pinctrl-imx8mq.o
 obj-$(CONFIG_PINCTRL_VF610)+= pinctrl-vf610.o
 obj-$(CONFIG_PINCTRL_MXS)  += pinctrl-mxs.o
 obj-$(CONFIG_PINCTRL_IMX23)+= pinctrl-imx23.o
diff --git a/drivers/pinctrl/freescale/pinctrl-imx8mq.c 
b/drivers/pinctrl/freescale/pinctrl-imx8mq.c
new file mode 100644
index 000..8d39af5
--- /dev/null
+++ b/drivers/pinctrl/freescale/pinctrl-imx8mq.c
@@ -0,0 +1,351 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017-2018 NXP
+ * Copyright (C) 2018 Pengutronix, Lucas Stach 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "pinctrl-imx.h"
+
+enum imx8mq_pads {
+   MX8MQ_PAD_RESERVE0 = 0,
+   MX8MQ_PAD_RESERVE1 = 1,
+   MX8MQ_PAD_RESERVE2 = 2,
+   MX8MQ_PAD_RESERVE3 = 3,
+   MX8MQ_PAD_RESERVE4 = 4,
+   MX8MQ_IOMUXC_PMIC_STBY_REQ_CCMSRCGPCMIX = 5,
+   MX8MQ_IOMUXC_PMIC_ON_REQ_SNVSMIX = 6,
+   MX8MQ_IOMUXC_ONOFF_SNVSMIX = 7,
+   MX8MQ_IOMUXC_POR_B_SNVSMIX = 8,
+   MX8MQ_IOMUXC_RTC_RESET_B_SNVSMIX = 9,
+   MX8MQ_IOMUXC_GPIO1_IO00 = 10,
+   MX8MQ_IOMUXC_GPIO1_IO01 = 11,
+   MX8MQ_IOMUXC_GPIO1_IO02 = 12,
+   MX8MQ_IOMUXC_GPIO1_IO03 = 13,
+   MX8MQ_IOMUXC_GPIO1_IO04 = 14,
+   MX8MQ_IOMUXC_GPIO1_IO05 = 15,
+   MX8MQ_IOMUXC_GPIO1_IO06 = 16,
+   MX8MQ_IOMUXC_GPIO1_IO07 = 17,
+   MX8MQ_IOMUXC_GPIO1_IO08 = 18,
+   MX8MQ_IOMUXC_GPIO1_IO09 = 19,
+   MX8MQ_IOMUXC_GPIO1_IO10 = 20,
+   MX8MQ_IOMUXC_GPIO1_IO11 = 21,
+   MX8MQ_IOMUXC_GPIO1_IO12 = 22,
+   MX8MQ_IOMUXC_GPIO1_IO13 = 23,
+   MX8MQ_IOMUXC_GPIO1_IO14 = 24,
+   MX8MQ_IOMUXC_GPIO1_IO15 = 25,
+   MX8MQ_IOMUXC_ENET_MDC = 26,
+   MX8MQ_IOMUXC_ENET_MDIO = 27,
+   MX8MQ_IOMUXC_ENET_TD3 = 28,
+   MX8MQ_IOMUXC_ENET_TD2 = 29,
+   MX8MQ_IOMUXC_ENET_TD1 = 30,
+   MX8MQ_IOMUXC_ENET_TD0 = 31,
+   MX8MQ_IOMUXC_ENET_TX_CTL = 32,
+   MX8MQ_IOMUXC_ENET_TXC = 33,
+   MX8MQ_IOMUXC_ENET_RX_CTL = 34,
+   MX8MQ_IOMUXC_ENET_RXC = 35,
+   MX8MQ_IOMUXC_ENET_RD0 = 36,
+   MX8MQ_IOMUXC_ENET_RD1 = 37,
+   MX8MQ_IOMUXC_ENET_RD2 = 38,
+   MX8MQ_IOMUXC_ENET_RD3 = 39,
+   MX8MQ_IOMUXC_SD1_CLK = 40,
+   MX8MQ_IOMUXC_SD1_CMD = 41,
+   MX8MQ_IOMUXC_SD1_DATA0 = 42,
+   MX8MQ_IOMUXC_SD1_DATA1 = 43,
+   MX8MQ_IOMUXC_SD1_DATA2 = 44,
+   MX8MQ_IOMUXC_SD1_DATA3 = 45,
+   MX8MQ_IOMUXC_SD1_DATA4 = 46,
+   MX8MQ_IOMUXC_SD1_DATA5 = 47,
+   MX8MQ_IOMUXC_SD1_DATA6 = 48,
+   MX8MQ_IOMUXC_SD1_DATA7 = 49,
+   MX8MQ_IOMUXC_SD1_RESET_B = 50,
+   MX8MQ_IOMUXC_SD1_STROBE = 51,
+   MX8MQ_IOMUXC_SD2_CD_B = 52,
+   MX8MQ_IOMUXC_SD2_CLK = 53,
+   MX8MQ_IOMUXC_SD2_CMD = 54,
+   MX8MQ_IOMUXC_SD2_DATA0 = 55,
+   MX8MQ_IOMUXC_SD2_DATA1 = 56,
+   MX8MQ_IOMUXC_SD2_DATA2 = 57,
+   MX8MQ_IOMUXC_SD2_DATA3 = 58,
+   MX8MQ_IOMUXC_SD2_RESET_B = 59,
+   MX8MQ_IOMUXC_SD2_WP = 60,
+   MX8MQ_IOMUXC_NAND_ALE = 61,
+   MX8MQ_IOMUXC_NAND_CE0_B = 62,
+   MX8MQ_IOMUXC_NAND_CE1_B = 63,
+   MX8MQ_IOMUXC_NAND_CE2_B = 64,
+   MX8MQ_IOMUXC_NAND_CE3_B = 65,
+   MX8MQ_IOMUXC_NAND_CLE = 66,
+   MX8MQ_IOMUXC_NAND_DATA00 = 67,
+   MX8MQ_IOMUXC_NAND_DATA01 = 68,
+   MX8MQ_IOMUXC_NAND_DATA02 = 69,
+   MX8MQ_IOMUXC_NAND_DATA03 = 70,
+   MX8MQ_IOMUXC_NAND_DATA04 = 71,
+ 

Re: [PATCH v6 3/5] clk: imx: add SCCG PLL type

2018-08-28 Thread Abel Vesa
On Fri, Aug 24, 2018 at 09:40:11AM +0200, Sascha Hauer wrote:
> +Cc Andrey Smirnov who made me aware of this issue.
> 
> On Wed, Aug 22, 2018 at 04:48:21PM +0300, Abel Vesa wrote:
> > From: Lucas Stach 
> > 
> > The SCCG is a new PLL type introduced on i.MX8. Add support for this.
> > The driver currently misses the PLL lock check, as the preliminary
> > documentation mentions lock configurations, but is quiet about where
> > to find the actual lock status signal.
> > 
> > Signed-off-by: Lucas Stach 
> > Signed-off-by: Abel Vesa 
> > ---
> > +static int clk_pll1_set_rate(struct clk_hw *hw, unsigned long rate,
> > +   unsigned long parent_rate)
> > +{
> > +   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
> > +   u32 val;
> > +   u32 divf;
> > +
> > +   divf = rate / (parent_rate * 2);
> > +
> > +   val = readl_relaxed(pll->base + PLL_CFG2);
> > +   val &= ~(PLL_DIVF_MASK << PLL_DIVF1_SHIFT);
> > +   val |= (divf - 1) << PLL_DIVF1_SHIFT;
> > +   writel_relaxed(val, pll->base + PLL_CFG2);
> > +
> > +   /* FIXME: PLL lock check */
> 
> Shouldn't be too hard to add, no?

Added to the next version which I intend to send today.

> 
> > +
> > +   return 0;
> > +}
> > +
> > +static int clk_pll1_prepare(struct clk_hw *hw)
> > +{
> > +   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
> > +   u32 val;
> > +
> > +   val = readl_relaxed(pll->base);
> > +   val &= ~(1 << PLL_PD);
> > +   writel_relaxed(val, pll->base);
> 
> pll->base + PLL_CFG0 please.

Same as above.

> 
> > +static const struct clk_ops clk_sccg_pll1_ops = {
> > +   .is_prepared= clk_pll1_is_prepared,
> > +   .recalc_rate= clk_pll1_recalc_rate,
> > +   .round_rate = clk_pll1_round_rate,
> > +   .set_rate   = clk_pll1_set_rate,
> > +};
> > +
> > +static const struct clk_ops clk_sccg_pll2_ops = {
> > +   .prepare= clk_pll1_prepare,
> > +   .unprepare  = clk_pll1_unprepare,
> > +   .recalc_rate= clk_pll2_recalc_rate,
> > +   .round_rate = clk_pll2_round_rate,
> > +   .set_rate   = clk_pll2_set_rate,
> > +};
> 
> So these are two PLLs that share the same enable register. Doing the
> prepare/unprepare for only one PLL can lead to all kinds of trouble.
> Finding a good abstraction the properly handles this case with the
> clock framework is probably also not easy.
> 
> I could imagine we'll need to track the enable state on both PLLs and
> only if both are disabled we disable it in hardware.
> 
> With the current code we disable the PLLs when all consumers are
> reparented to pll1, which probably has bad effects.
> 

So it took me a while to understand exactly why this needs to stay like it is.

The PLL1 is never used by any device, instead it is used as a source for PLL2.

But because the interlink between the two of them is too complicated,
the PLLs 1 and 2 need to be separate clocks.

As for the disabling, it's safe to disable just the second one because,
as mentioned above, the first PLL is never used alone by a device.

If there isn't anything else here to discuss, I would like to send the next
version of this patchset with all the other comments taken care of.

Abel

> Sascha
> 
> -- 
> Pengutronix e.K.   | |
> Industrial Linux Solutions | 
> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.pengutronix.de%2F&data=02%7C01%7Cabel.vesa%40nxp.com%7C5e9c7c6f9e464ed522f108d60994d471%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C636706932168087639&sdata=XbfFq5z%2FRtkq6yGgwSyk6dNCZVuXOzY%2Fiygmwle3C2I%3D&reserved=0
>   |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0|
> Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |

-- 

[PATCH v3 0/4] Add i.MX8MQ clock driver

2018-08-09 Thread Abel Vesa
This is basically just a resend of the following patchset:

https://www.spinics.net/lists/linux-clk/msg23141.html

I've just updated the patchset and implemented Shawn's
and Aisheng's comments.

I hope I haven't missed any of their comments.

Lucas Stach (4):
  dt-bindings: add binding for i.MX8MQ CCM
  clk: imx: add fractional PLL output clock
  clk: imx: add SCCG PLL type
  clk: imx: add clock driver for i.MX8MQ CCM

 .../devicetree/bindings/clock/imx8mq-clock.txt |  20 +
 drivers/clk/imx/Makefile   |   5 +-
 drivers/clk/imx/clk-frac-pll.c | 230 ++
 drivers/clk/imx/clk-imx8mq.c   | 856 +
 drivers/clk/imx/clk-sccg-pll.c | 231 ++
 drivers/clk/imx/clk.h  |  48 ++
 include/dt-bindings/clock/imx8mq-clock.h   | 629 +++
 7 files changed, 2018 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/imx8mq-clock.txt
 create mode 100644 drivers/clk/imx/clk-frac-pll.c
 create mode 100644 drivers/clk/imx/clk-imx8mq.c
 create mode 100644 drivers/clk/imx/clk-sccg-pll.c
 create mode 100644 include/dt-bindings/clock/imx8mq-clock.h

-- 
2.7.4



[PATCH v3 2/4] clk: imx: add fractional PLL output clock

2018-08-09 Thread Abel Vesa
From: Lucas Stach 

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

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/Makefile   |   1 +
 drivers/clk/imx/clk-frac-pll.c | 230 +
 drivers/clk/imx/clk.h  |   3 +
 3 files changed, 234 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..c80c6ed
--- /dev/null
+++ b/drivers/clk/imx/clk-frac-pll.c
@@ -0,0 +1,230 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 NXP.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+#define PLL_CFG0   0x0
+#define PLL_CFG1   0x4
+
+#define PLL_LOCK_STATUSBIT(31)
+#define PLL_PD 19
+#define PLL_PD_MASKBIT(PLL_PD)
+#define PLL_BYPASS 14
+#define PLL_BYPASS_MASKBIT(PLL_BYPASS)
+#define PLL_NEWDIV_VAL BIT(12)
+#define PLL_NEWDIV_ACK BIT(11)
+#define PLL_FRAC_DIV_MASK  0xff
+#define PLL_INT_DIV_MASK   0x7f
+#define PLL_OUTPUT_DIV_MASK0x1f
+#define PLL_FRAC_DENOM 0x100
+
+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)
+{
+   unsigned long timeout = jiffies + msecs_to_jiffies(10);
+   u32 val;
+
+   /* Wait for PLL to lock */
+   do {
+   if (readl_relaxed(pll->base) & PLL_LOCK_STATUS)
+   break;
+   if (time_after(jiffies, timeout))
+   break;
+   } while (1);
+
+   return readl_poll_timeout(pll->base, val,
+   val & PLL_LOCK_STATUS, 0, 1000);
+}
+
+static int clk_wait_ack(struct clk_frac_pll *pll)
+{
+   unsigned long timeout = jiffies + msecs_to_jiffies(50);
+   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 */
+   do {
+   if (readl_relaxed(pll->base) & PLL_NEWDIV_ACK)
+   break;
+   if (time_after(jiffies, timeout))
+   break;
+   } while (1);
+
+   return readl_poll_timeout(pll->base, val,
+   val & PLL_NEWDIV_ACK, 0, 1000);
+}
+
+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;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   divq = ((val & PLL_OUTPUT_DIV_MASK) + 1) * 2;
+   val = readl_relaxed(pll->base + PLL_CFG1);
+   divff = (val >> 7) & PLL_FRAC_DIV_MASK;
+   divfi = (val & PLL_INT_DIV_MASK);
+
+   temp64 = (u64)parent_rate * 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)
+{
+   unsigned long parent_rate = *prate;
+   u32 divff, divfi;
+   u64 temp64;
+
+   parent_rate *= 8;
+   rate *= 2;
+   divfi = rate / parent_rate;
+   temp64 = (u64)(rate - divfi * parent_rate);
+   temp64 *= PLL_FRAC_DENOM;
+   do_div(

[PATCH v3 1/4] dt-bindings: add binding for i.MX8MQ CCM

2018-08-09 Thread Abel Vesa
From: Lucas Stach 

This adds the binding for the i.MX8MQ Clock Controller Module.

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
---
 .../devicetree/bindings/clock/imx8mq-clock.txt |  20 +
 include/dt-bindings/clock/imx8mq-clock.h   | 629 +
 2 files changed, 649 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/imx8mq-clock.txt
 create mode 100644 include/dt-bindings/clock/imx8mq-clock.h

diff --git a/Documentation/devicetree/bindings/clock/imx8mq-clock.txt 
b/Documentation/devicetree/bindings/clock/imx8mq-clock.txt
new file mode 100644
index 000..52de826
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/imx8mq-clock.txt
@@ -0,0 +1,20 @@
+* Clock bindings for NXP i.MX8M Quad
+
+Required properties:
+- compatible: Should be "fsl,imx8mq-ccm"
+- reg: Address and length of the register set
+- #clock-cells: Should be <1>
+- clocks: list of clock specifiers, must contain an entry for each required
+  entry in clock-names
+- clock-names: should include the following entries:
+- "ckil"
+- "osc_25m"
+- "osc_27m"
+- "clk_ext1"
+- "clk_ext2"
+- "clk_ext3"
+- "clk_ext4"
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell.  See include/dt-bindings/clock/imx8mq-clock.h
+for the full list of i.MX8M Quad clock IDs.
diff --git a/include/dt-bindings/clock/imx8mq-clock.h 
b/include/dt-bindings/clock/imx8mq-clock.h
new file mode 100644
index 000..7f88062
--- /dev/null
+++ b/include/dt-bindings/clock/imx8mq-clock.h
@@ -0,0 +1,629 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_IMX8MQ_H
+#define __DT_BINDINGS_CLOCK_IMX8MQ_H
+
+#define IMX8MQ_CLK_DUMMY   0
+#define IMX8MQ_CLK_32K 1
+#define IMX8MQ_CLK_25M 2
+#define IMX8MQ_CLK_27M 3
+#define IMX8MQ_CLK_EXT14
+#define IMX8MQ_CLK_EXT25
+#define IMX8MQ_CLK_EXT36
+#define IMX8MQ_CLK_EXT47
+
+/* ANAMIX PLL clocks */
+/* FRAC PLLs */
+/* ARM PLL */
+#define IMX8MQ_ARM_PLL_REF_SEL 8
+#define IMX8MQ_ARM_PLL_REF_DIV 9
+#define IMX8MQ_ARM_PLL 10
+#define IMX8MQ_ARM_PLL_BYPASS  11
+#define IMX8MQ_ARM_PLL_OUT 12
+
+/* GPU PLL */
+#define IMX8MQ_GPU_PLL_REF_SEL 13
+#define IMX8MQ_GPU_PLL_REF_DIV 14
+#define IMX8MQ_GPU_PLL 15
+#define IMX8MQ_GPU_PLL_BYPASS  16
+#define IMX8MQ_GPU_PLL_OUT 17
+
+/* VPU PLL */
+#define IMX8MQ_VPU_PLL_REF_SEL 18
+#define IMX8MQ_VPU_PLL_REF_DIV 19
+#define IMX8MQ_VPU_PLL 20
+#define IMX8MQ_VPU_PLL_BYPASS  21
+#define IMX8MQ_VPU_PLL_OUT 22
+
+/* AUDIO PLL1 */
+#define IMX8MQ_AUDIO_PLL1_REF_SEL  23
+#define IMX8MQ_AUDIO_PLL1_REF_DIV  24
+#define IMX8MQ_AUDIO_PLL1  25
+#define IMX8MQ_AUDIO_PLL1_BYPASS   26
+#define IMX8MQ_AUDIO_PLL1_OUT  27
+
+/* AUDIO PLL2 */
+#define IMX8MQ_AUDIO_PLL2_REF_SEL  28
+#define IMX8MQ_AUDIO_PLL2_REF_DIV  29
+#define IMX8MQ_AUDIO_PLL2  30
+#define IMX8MQ_AUDIO_PLL2_BYPASS   31
+#define IMX8MQ_AUDIO_PLL2_OUT  32
+
+/* VIDEO PLL1 */
+#define IMX8MQ_VIDEO_PLL1_REF_SEL  33
+#define IMX8MQ_VIDEO_PLL1_REF_DIV  34
+#define IMX8MQ_VIDEO_PLL1  35
+#define IMX8MQ_VIDEO_PLL1_BYPASS   36
+#define IMX8MQ_VIDEO_PLL1_OUT  37
+
+/* SYS1 PLL */
+#define IMX8MQ_SYS1_PLL1_REF_SEL   38
+#define IMX8MQ_SYS1_PLL1_REF_DIV   39
+#define IMX8MQ_SYS1_PLL1   40
+#define IMX8MQ_SYS1_PLL1_OUT   41
+#define IMX8MQ_SYS1_PLL1_OUT_DIV   42
+#define IMX8MQ_SYS1_PLL2   43
+#define IMX8MQ_SYS1_PLL2_DIV   44
+#define IMX8MQ_SYS1_PLL2_OUT   45
+
+/* SYS2 PLL */
+#define IMX8MQ_SYS2_PLL1_REF_SEL   46
+#define IMX8MQ_SYS2_PLL1_REF_DIV   47
+#define IMX8MQ_SYS2_PLL1   48
+#define IMX8MQ_SYS2_PLL1_OUT   49
+#define IMX8MQ_SYS2_PLL1_OUT_DIV   50
+#define IMX8MQ_SYS2_PLL2   51
+#define IMX8MQ_SYS2_PLL2_DIV   52
+#define IMX8MQ_SYS2_PLL2_OUT   53
+
+/* SYS3 PLL */
+#define IMX8MQ_SYS3_PLL1_REF_SEL   54
+#define IMX8MQ_SYS3_PLL1_REF_DIV   55
+#define IMX8MQ_SYS3_PLL1   56
+#define IMX8MQ_SYS3_PLL1_OUT   57
+#define IMX8MQ_SYS3_PLL1_OUT_DIV   58
+#define IMX8MQ_SYS3_PLL2   59
+#define IMX8MQ_SYS3_PLL2_DIV   60
+#define IMX8MQ_SYS3_PLL2_OUT   61
+
+/* DRAM PLL */
+#define IMX8MQ_DRAM_PLL1_REF_SEL   62
+#define IMX8MQ_DRAM_PLL1_REF_DIV   63
+#define IMX8MQ_DRAM_PLL1   64
+#define IMX8MQ_DRAM_PLL1_OUT   6

[PATCH v3 3/4] clk: imx: add SCCG PLL type

2018-08-09 Thread Abel Vesa
From: Lucas Stach 

The SCCG is a new PLL type introduced on i.MX8. Add support for this.
The driver currently misses the PLL lock check, as the preliminary
documentation mentions lock configurations, but is quiet about where
to find the actual lock status signal.

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/Makefile   |   3 +-
 drivers/clk/imx/clk-sccg-pll.c | 231 +
 drivers/clk/imx/clk.h  |   9 ++
 3 files changed, 242 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/imx/clk-sccg-pll.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 4893c1f..b87513c 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -12,7 +12,8 @@ obj-y += \
clk-pllv1.o \
clk-pllv2.o \
clk-pllv3.o \
-   clk-pfd.o
+   clk-pfd.o \
+   clk-sccg-pll.o
 
 obj-$(CONFIG_SOC_IMX1)   += clk-imx1.o
 obj-$(CONFIG_SOC_IMX21)  += clk-imx21.o
diff --git a/drivers/clk/imx/clk-sccg-pll.c b/drivers/clk/imx/clk-sccg-pll.c
new file mode 100644
index 000..886ae03
--- /dev/null
+++ b/drivers/clk/imx/clk-sccg-pll.c
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2018 NXP.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+/* PLL CFGs */
+#define PLL_CFG0   0x0
+#define PLL_CFG1   0x4
+#define PLL_CFG2   0x8
+
+#define PLL_DIVF1_SHIFT13
+#define PLL_DIVF2_SHIFT7
+#define PLL_DIVF_MASK  0x3f
+
+#define PLL_DIVR1_SHIFT25
+#define PLL_DIVR2_SHIFT19
+#define PLL_DIVR1_MASK 0x3
+#define PLL_DIVR2_MASK 0x3f
+#define PLL_REF_SHIFT  0
+#define PLL_REF_MASK   0x3
+
+#define PLL_LOCK   31
+#define PLL_PD 7
+
+#define OSC_25M2500
+#define OSC_27M2700
+
+struct clk_sccg_pll {
+   struct clk_hw   hw;
+   void __iomem*base;
+};
+
+#define to_clk_sccg_pll(_hw) container_of(_hw, struct clk_sccg_pll, hw)
+
+static int clk_pll1_is_prepared(struct clk_hw *hw)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   return (val & (1 << PLL_PD)) ? 0 : 1;
+}
+
+static unsigned long clk_pll1_recalc_rate(struct clk_hw *hw,
+unsigned long parent_rate)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val, divf;
+
+   val = readl_relaxed(pll->base + PLL_CFG2);
+   divf = (val >> PLL_DIVF1_SHIFT) & PLL_DIVF_MASK;
+
+   return parent_rate * 2 * (divf + 1);
+}
+
+static long clk_pll1_round_rate(struct clk_hw *hw, unsigned long rate,
+  unsigned long *prate)
+{
+   unsigned long parent_rate = *prate;
+   u32 div;
+
+   div = rate / (parent_rate * 2);
+
+   return parent_rate * div * 2;
+}
+
+static int clk_pll1_set_rate(struct clk_hw *hw, unsigned long rate,
+   unsigned long parent_rate)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+   u32 divf;
+
+   divf = rate / (parent_rate * 2);
+
+   val = readl_relaxed(pll->base + PLL_CFG2);
+   val &= ~(PLL_DIVF_MASK << PLL_DIVF1_SHIFT);
+   val |= (divf - 1) << PLL_DIVF1_SHIFT;
+   writel_relaxed(val, pll->base + PLL_CFG2);
+
+   /* FIXME: PLL lock check */
+
+   return 0;
+}
+
+static int clk_pll1_prepare(struct clk_hw *hw)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base);
+   val &= ~(1 << PLL_PD);
+   writel_relaxed(val, pll->base);
+
+   /* FIXME: PLL lock check */
+
+   return 0;
+}
+
+static void clk_pll1_unprepare(struct clk_hw *hw)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base);
+   val |= (1 << PLL_PD);
+   writel_relaxed(val, pll->base);
+}
+
+static unsigned long clk_pll2_recalc_rate(struct clk_hw *hw,
+unsigned long parent_rate)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val, ref, divr1, divf1, divr2, divf2;
+   u64 temp64;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   switch ((val >> PLL_REF_SHIFT) & PLL_REF_MASK) {
+   case 0:
+   ref = OSC_25M;
+   break;
+   case 1:
+   ref = OSC_27M;
+   break;
+   default:
+   ref = OSC_25M;
+   break;
+   }
+
+   val = readl_relaxed(pll->base + PLL_CFG2);
+   divr1 = (val >> PLL_DIVR1_SHIFT) & PLL_DIVR1_MASK;
+   divr2 = (val >> PLL_DIVR2_SHIFT) & PLL_DIVR2_MASK;
+   divf1 = (val >> PLL_DIVF1_SHIFT) & PLL_DIVF_MASK;
+   divf2 = (val >> PLL_DIVF2_SHIFT) & PLL_DIVF_MASK;
+
+   temp6

[PATCH v3 4/4] clk: imx: add clock driver for i.MX8MQ CCM

2018-08-09 Thread Abel Vesa
From: Lucas Stach 

Add driver for the Clock Control Module found on i.MX8MQ.

This is largely based on the downstream driver from Anson Huang and
Bai Ping at NXP, with only some small adaptions to mainline from me.

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/Makefile |   1 +
 drivers/clk/imx/clk-imx8mq.c | 856 +++
 drivers/clk/imx/clk.h|  36 ++
 3 files changed, 893 insertions(+)
 create mode 100644 drivers/clk/imx/clk-imx8mq.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index b87513c..e2c5de9 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -29,3 +29,4 @@ obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o
 obj-$(CONFIG_SOC_IMX6UL) += clk-imx6ul.o
 obj-$(CONFIG_SOC_IMX7D)  += clk-imx7d.o
 obj-$(CONFIG_SOC_VF610)  += clk-vf610.o
+obj-$(CONFIG_SOC_IMX8MQ)  += clk-imx8mq.o
diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c
new file mode 100644
index 000..6b9cba1
--- /dev/null
+++ b/drivers/clk/imx/clk-imx8mq.c
@@ -0,0 +1,856 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2018 NXP.
+ * Copyright (C) 2017 Pengutronix, Lucas Stach 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+static u32 share_count_sai1;
+static u32 share_count_sai2;
+static u32 share_count_sai3;
+static u32 share_count_sai4;
+static u32 share_count_sai5;
+static u32 share_count_sai6;
+static u32 share_count_dcss;
+static u32 share_count_nand;
+
+static struct clk *clks[IMX8MQ_CLK_END];
+
+static const char *pll_ref_sels[] = { "osc_25m", "osc_27m", "dummy", "dummy", 
};
+static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
+static const char *gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
+static const char *vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", };
+static const char *audio_pll1_bypass_sels[] = {"audio_pll1", 
"audio_pll1_ref_sel", };
+static const char *audio_pll2_bypass_sels[] = {"audio_pll2", 
"audio_pll2_ref_sel", };
+static const char *video_pll1_bypass_sels[] = {"video_pll1", 
"video_pll1_ref_sel", };
+
+static const char *sys1_pll1_out_sels[] = {"sys1_pll1", "sys1_pll1_ref_sel", };
+static const char *sys2_pll1_out_sels[] = {"sys2_pll1", "sys1_pll1_ref_sel", };
+static const char *sys3_pll1_out_sels[] = {"sys3_pll1", "sys3_pll1_ref_sel", };
+static const char *dram_pll1_out_sels[] = {"dram_pll1", "dram_pll1_ref_sel", };
+static const char *video2_pll1_out_sels[] = {"video2_pll1", 
"video2_pll1_ref_sel", };
+
+static const char *sys1_pll2_out_sels[] = {"sys1_pll2_div", 
"sys1_pll1_ref_sel", };
+static const char *sys2_pll2_out_sels[] = {"sys2_pll2_div", 
"sys2_pll1_ref_sel", };
+static const char *sys3_pll2_out_sels[] = {"sys3_pll2_div", 
"sys2_pll1_ref_sel", };
+static const char *dram_pll2_out_sels[] = {"dram_pll2_div", 
"dram_pll1_ref_sel", };
+static const char *video2_pll2_out_sels[] = {"video2_pll2_div", 
"video2_pll1_ref_sel", };
+
+/* CCM ROOT */
+static const char *imx8mq_a53_sels[] = {"osc_25m", "arm_pll_out", 
"sys2_pll_500m", "sys2_pll_1000m",
+   "sys1_pll_800m", "sys1_pll_400m", 
"audio_pll1_out", "sys3_pll2_out", };
+
+static const char *imx8mq_vpu_sels[] = {"osc_25m", "arm_pll_out", 
"sys2_pll_500m", "sys2_pll_1000m",
+   "sys1_pll_800m", "sys1_pll_400m", 
"audio_pll1_out", "vpu_pll_out", };
+
+static const char *imx8mq_gpu_core_sels[] = {"osc_25m", "gpu_pll_out", 
"sys1_pll_800m", "sys3_pll2_out",
+"sys2_pll_1000m", 
"audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mq_gpu_shader_sels[] = {"osc_25m", "gpu_pll_out", 
"sys1_pll_800m", "sys3_pll2_out",
+  "sys2_pll_1000m", 
"audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mq_main_axi_sels[] = {"osc_25m", "sys2_pll_333m", 
"sys1_pll_800m", "sys2_pll_250m",
+"sys2_pll_1000m", 
"audio_pll1_out", "video_pll1_out", "sys1_pll_100m",};
+
+static const ch

Re: [RESEND v5 4/5] clk: imx: add imx composite clock

2018-08-22 Thread Abel Vesa
On Tue, Aug 21, 2018 at 08:58:30AM +0200, Sascha Hauer wrote:
> On Mon, Aug 20, 2018 at 10:16:06AM +0300, Abel Vesa wrote:
> > +
> > +   val |= (u32)value << divider->shift;
> > +   val |= (u32)value << PCG_DIV_SHIFT;
> > +   clk_writel(val, divider->reg);
> > +
> > +   spin_unlock_irqrestore(divider->lock, flags);
> > +
> > +   return 0;
> > +}
> 
> Have you tested this works? I thought those are two cascaded dividers
> and you program both to the same value. Normally you would have to
> calculate individual values for each divider which together give you the
> desired output rate.
>

My bad. Haven't properly tested it since there is no actual driver that calls
set_rate on any of those clocks at this point. Sorry about that. I'll send
another version today, where I've implemented it as I should've done from the
start and I've tested it by explicitly calling the set_rate and read the value
with clk_get_rate to make sure it's fine.
 
> Sascha
> 
> -- 
> Pengutronix e.K.   | |
> Industrial Linux Solutions | 
> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.pengutronix.de%2F&data=02%7C01%7Cabel.vesa%40nxp.com%7C722eb3cdb15849a9d19608d6073382e4%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C636704315167487036&sdata=Q29pmTcLbqNPjotCFjZ%2BldD%2FBlbYpm6fN%2BzguHixwfA%3D&reserved=0
>   |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0|
> Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |

-- 

[PATCH v6 0/5] Add i.MX8MQ clock driver

2018-08-22 Thread Abel Vesa
Fifth version can be found here:

https://lkml.org/lkml/2018/8/20/83

Changes since v5:
 * Fixed the predivider and divider register values as
   reported by Sascha.
 * Changed the commit message of the 4th patch to match
   with what the commit is adding

Changes since v4:
 * Implemented divider ops and used clk-composite as suggested
   by Sascha Hauer.

Changes since v3:
 * Added a composite clock type to get rid of some complexity
   from clk-imx8mq. This new composite clock type will also be
   used by all the imx8 socs that will follow.
 * Added back the reviewed-by tag.

Abel Vesa (1):
  clk: imx: add imx composite clock

Lucas Stach (4):
  dt-bindings: add binding for i.MX8MQ CCM
  clk: imx: add fractional PLL output clock
  clk: imx: add SCCG PLL type
  clk: imx: add clock driver for i.MX8MQ CCM

 .../devicetree/bindings/clock/imx8mq-clock.txt |  20 +
 drivers/clk/imx/Makefile   |   6 +-
 drivers/clk/imx/clk-composite.c| 157 +
 drivers/clk/imx/clk-frac-pll.c | 230 
 drivers/clk/imx/clk-imx8mq.c   | 631 +
 drivers/clk/imx/clk-sccg-pll.c | 231 
 drivers/clk/imx/clk.h  |  57 ++
 include/dt-bindings/clock/imx8mq-clock.h   | 410 +
 8 files changed, 1741 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/imx8mq-clock.txt
 create mode 100644 drivers/clk/imx/clk-composite.c
 create mode 100644 drivers/clk/imx/clk-frac-pll.c
 create mode 100644 drivers/clk/imx/clk-imx8mq.c
 create mode 100644 drivers/clk/imx/clk-sccg-pll.c
 create mode 100644 include/dt-bindings/clock/imx8mq-clock.h

-- 
2.7.4



[PATCH v6 1/5] dt-bindings: add binding for i.MX8MQ CCM

2018-08-22 Thread Abel Vesa
From: Lucas Stach 

This adds the binding for the i.MX8MQ Clock Controller Module.

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
Reviewed-by: Rob Herring 
---
 .../devicetree/bindings/clock/imx8mq-clock.txt |  20 +
 include/dt-bindings/clock/imx8mq-clock.h   | 410 +
 2 files changed, 430 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/imx8mq-clock.txt
 create mode 100644 include/dt-bindings/clock/imx8mq-clock.h

diff --git a/Documentation/devicetree/bindings/clock/imx8mq-clock.txt 
b/Documentation/devicetree/bindings/clock/imx8mq-clock.txt
new file mode 100644
index 000..52de826
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/imx8mq-clock.txt
@@ -0,0 +1,20 @@
+* Clock bindings for NXP i.MX8M Quad
+
+Required properties:
+- compatible: Should be "fsl,imx8mq-ccm"
+- reg: Address and length of the register set
+- #clock-cells: Should be <1>
+- clocks: list of clock specifiers, must contain an entry for each required
+  entry in clock-names
+- clock-names: should include the following entries:
+- "ckil"
+- "osc_25m"
+- "osc_27m"
+- "clk_ext1"
+- "clk_ext2"
+- "clk_ext3"
+- "clk_ext4"
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell.  See include/dt-bindings/clock/imx8mq-clock.h
+for the full list of i.MX8M Quad clock IDs.
diff --git a/include/dt-bindings/clock/imx8mq-clock.h 
b/include/dt-bindings/clock/imx8mq-clock.h
new file mode 100644
index 000..0d19bd9
--- /dev/null
+++ b/include/dt-bindings/clock/imx8mq-clock.h
@@ -0,0 +1,410 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_IMX8MQ_H
+#define __DT_BINDINGS_CLOCK_IMX8MQ_H
+
+#define IMX8MQ_CLK_DUMMY   0
+#define IMX8MQ_CLK_32K 1
+#define IMX8MQ_CLK_25M 2
+#define IMX8MQ_CLK_27M 3
+#define IMX8MQ_CLK_EXT14
+#define IMX8MQ_CLK_EXT25
+#define IMX8MQ_CLK_EXT36
+#define IMX8MQ_CLK_EXT47
+
+/* ANAMIX PLL clocks */
+/* FRAC PLLs */
+/* ARM PLL */
+#define IMX8MQ_ARM_PLL_REF_SEL 8
+#define IMX8MQ_ARM_PLL_REF_DIV 9
+#define IMX8MQ_ARM_PLL 10
+#define IMX8MQ_ARM_PLL_BYPASS  11
+#define IMX8MQ_ARM_PLL_OUT 12
+
+/* GPU PLL */
+#define IMX8MQ_GPU_PLL_REF_SEL 13
+#define IMX8MQ_GPU_PLL_REF_DIV 14
+#define IMX8MQ_GPU_PLL 15
+#define IMX8MQ_GPU_PLL_BYPASS  16
+#define IMX8MQ_GPU_PLL_OUT 17
+
+/* VPU PLL */
+#define IMX8MQ_VPU_PLL_REF_SEL 18
+#define IMX8MQ_VPU_PLL_REF_DIV 19
+#define IMX8MQ_VPU_PLL 20
+#define IMX8MQ_VPU_PLL_BYPASS  21
+#define IMX8MQ_VPU_PLL_OUT 22
+
+/* AUDIO PLL1 */
+#define IMX8MQ_AUDIO_PLL1_REF_SEL  23
+#define IMX8MQ_AUDIO_PLL1_REF_DIV  24
+#define IMX8MQ_AUDIO_PLL1  25
+#define IMX8MQ_AUDIO_PLL1_BYPASS   26
+#define IMX8MQ_AUDIO_PLL1_OUT  27
+
+/* AUDIO PLL2 */
+#define IMX8MQ_AUDIO_PLL2_REF_SEL  28
+#define IMX8MQ_AUDIO_PLL2_REF_DIV  29
+#define IMX8MQ_AUDIO_PLL2  30
+#define IMX8MQ_AUDIO_PLL2_BYPASS   31
+#define IMX8MQ_AUDIO_PLL2_OUT  32
+
+/* VIDEO PLL1 */
+#define IMX8MQ_VIDEO_PLL1_REF_SEL  33
+#define IMX8MQ_VIDEO_PLL1_REF_DIV  34
+#define IMX8MQ_VIDEO_PLL1  35
+#define IMX8MQ_VIDEO_PLL1_BYPASS   36
+#define IMX8MQ_VIDEO_PLL1_OUT  37
+
+/* SYS1 PLL */
+#define IMX8MQ_SYS1_PLL1_REF_SEL   38
+#define IMX8MQ_SYS1_PLL1_REF_DIV   39
+#define IMX8MQ_SYS1_PLL1   40
+#define IMX8MQ_SYS1_PLL1_OUT   41
+#define IMX8MQ_SYS1_PLL1_OUT_DIV   42
+#define IMX8MQ_SYS1_PLL2   43
+#define IMX8MQ_SYS1_PLL2_DIV   44
+#define IMX8MQ_SYS1_PLL2_OUT   45
+
+/* SYS2 PLL */
+#define IMX8MQ_SYS2_PLL1_REF_SEL   46
+#define IMX8MQ_SYS2_PLL1_REF_DIV   47
+#define IMX8MQ_SYS2_PLL1   48
+#define IMX8MQ_SYS2_PLL1_OUT   49
+#define IMX8MQ_SYS2_PLL1_OUT_DIV   50
+#define IMX8MQ_SYS2_PLL2   51
+#define IMX8MQ_SYS2_PLL2_DIV   52
+#define IMX8MQ_SYS2_PLL2_OUT   53
+
+/* SYS3 PLL */
+#define IMX8MQ_SYS3_PLL1_REF_SEL   54
+#define IMX8MQ_SYS3_PLL1_REF_DIV   55
+#define IMX8MQ_SYS3_PLL1   56
+#define IMX8MQ_SYS3_PLL1_OUT   57
+#define IMX8MQ_SYS3_PLL1_OUT_DIV   58
+#define IMX8MQ_SYS3_PLL2   59
+#define IMX8MQ_SYS3_PLL2_DIV   60
+#define IMX8MQ_SYS3_PLL2_OUT   61
+
+/* DRAM PLL */
+#define IMX8MQ_DRAM_PLL1_REF_SEL   62
+#define IMX8MQ_DRAM_PLL1_REF_DIV   63
+#define IMX8MQ_DRAM_PLL1   64
+#define IMX8MQ

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

2018-08-22 Thread Abel Vesa
From: Lucas Stach 

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

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/Makefile   |   1 +
 drivers/clk/imx/clk-frac-pll.c | 230 +
 drivers/clk/imx/clk.h  |   3 +
 3 files changed, 234 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..c80c6ed
--- /dev/null
+++ b/drivers/clk/imx/clk-frac-pll.c
@@ -0,0 +1,230 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 NXP.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+#define PLL_CFG0   0x0
+#define PLL_CFG1   0x4
+
+#define PLL_LOCK_STATUSBIT(31)
+#define PLL_PD 19
+#define PLL_PD_MASKBIT(PLL_PD)
+#define PLL_BYPASS 14
+#define PLL_BYPASS_MASKBIT(PLL_BYPASS)
+#define PLL_NEWDIV_VAL BIT(12)
+#define PLL_NEWDIV_ACK BIT(11)
+#define PLL_FRAC_DIV_MASK  0xff
+#define PLL_INT_DIV_MASK   0x7f
+#define PLL_OUTPUT_DIV_MASK0x1f
+#define PLL_FRAC_DENOM 0x100
+
+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)
+{
+   unsigned long timeout = jiffies + msecs_to_jiffies(10);
+   u32 val;
+
+   /* Wait for PLL to lock */
+   do {
+   if (readl_relaxed(pll->base) & PLL_LOCK_STATUS)
+   break;
+   if (time_after(jiffies, timeout))
+   break;
+   } while (1);
+
+   return readl_poll_timeout(pll->base, val,
+   val & PLL_LOCK_STATUS, 0, 1000);
+}
+
+static int clk_wait_ack(struct clk_frac_pll *pll)
+{
+   unsigned long timeout = jiffies + msecs_to_jiffies(50);
+   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 */
+   do {
+   if (readl_relaxed(pll->base) & PLL_NEWDIV_ACK)
+   break;
+   if (time_after(jiffies, timeout))
+   break;
+   } while (1);
+
+   return readl_poll_timeout(pll->base, val,
+   val & PLL_NEWDIV_ACK, 0, 1000);
+}
+
+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;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   divq = ((val & PLL_OUTPUT_DIV_MASK) + 1) * 2;
+   val = readl_relaxed(pll->base + PLL_CFG1);
+   divff = (val >> 7) & PLL_FRAC_DIV_MASK;
+   divfi = (val & PLL_INT_DIV_MASK);
+
+   temp64 = (u64)parent_rate * 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)
+{
+   unsigned long parent_rate = *prate;
+   u32 divff, divfi;
+   u64 temp64;
+
+   parent_rate *= 8;
+   rate *= 2;
+   divfi = rate / parent_rate;
+   temp64 = (u64)(rate - divfi * parent_rate);
+   temp64 *= PLL_FRAC_DENOM;
+   do_div(

[PATCH v6 3/5] clk: imx: add SCCG PLL type

2018-08-22 Thread Abel Vesa
From: Lucas Stach 

The SCCG is a new PLL type introduced on i.MX8. Add support for this.
The driver currently misses the PLL lock check, as the preliminary
documentation mentions lock configurations, but is quiet about where
to find the actual lock status signal.

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/Makefile   |   3 +-
 drivers/clk/imx/clk-sccg-pll.c | 231 +
 drivers/clk/imx/clk.h  |   9 ++
 3 files changed, 242 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/imx/clk-sccg-pll.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 4893c1f..b87513c 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -12,7 +12,8 @@ obj-y += \
clk-pllv1.o \
clk-pllv2.o \
clk-pllv3.o \
-   clk-pfd.o
+   clk-pfd.o \
+   clk-sccg-pll.o
 
 obj-$(CONFIG_SOC_IMX1)   += clk-imx1.o
 obj-$(CONFIG_SOC_IMX21)  += clk-imx21.o
diff --git a/drivers/clk/imx/clk-sccg-pll.c b/drivers/clk/imx/clk-sccg-pll.c
new file mode 100644
index 000..886ae03
--- /dev/null
+++ b/drivers/clk/imx/clk-sccg-pll.c
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2018 NXP.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+/* PLL CFGs */
+#define PLL_CFG0   0x0
+#define PLL_CFG1   0x4
+#define PLL_CFG2   0x8
+
+#define PLL_DIVF1_SHIFT13
+#define PLL_DIVF2_SHIFT7
+#define PLL_DIVF_MASK  0x3f
+
+#define PLL_DIVR1_SHIFT25
+#define PLL_DIVR2_SHIFT19
+#define PLL_DIVR1_MASK 0x3
+#define PLL_DIVR2_MASK 0x3f
+#define PLL_REF_SHIFT  0
+#define PLL_REF_MASK   0x3
+
+#define PLL_LOCK   31
+#define PLL_PD 7
+
+#define OSC_25M2500
+#define OSC_27M2700
+
+struct clk_sccg_pll {
+   struct clk_hw   hw;
+   void __iomem*base;
+};
+
+#define to_clk_sccg_pll(_hw) container_of(_hw, struct clk_sccg_pll, hw)
+
+static int clk_pll1_is_prepared(struct clk_hw *hw)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   return (val & (1 << PLL_PD)) ? 0 : 1;
+}
+
+static unsigned long clk_pll1_recalc_rate(struct clk_hw *hw,
+unsigned long parent_rate)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val, divf;
+
+   val = readl_relaxed(pll->base + PLL_CFG2);
+   divf = (val >> PLL_DIVF1_SHIFT) & PLL_DIVF_MASK;
+
+   return parent_rate * 2 * (divf + 1);
+}
+
+static long clk_pll1_round_rate(struct clk_hw *hw, unsigned long rate,
+  unsigned long *prate)
+{
+   unsigned long parent_rate = *prate;
+   u32 div;
+
+   div = rate / (parent_rate * 2);
+
+   return parent_rate * div * 2;
+}
+
+static int clk_pll1_set_rate(struct clk_hw *hw, unsigned long rate,
+   unsigned long parent_rate)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+   u32 divf;
+
+   divf = rate / (parent_rate * 2);
+
+   val = readl_relaxed(pll->base + PLL_CFG2);
+   val &= ~(PLL_DIVF_MASK << PLL_DIVF1_SHIFT);
+   val |= (divf - 1) << PLL_DIVF1_SHIFT;
+   writel_relaxed(val, pll->base + PLL_CFG2);
+
+   /* FIXME: PLL lock check */
+
+   return 0;
+}
+
+static int clk_pll1_prepare(struct clk_hw *hw)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base);
+   val &= ~(1 << PLL_PD);
+   writel_relaxed(val, pll->base);
+
+   /* FIXME: PLL lock check */
+
+   return 0;
+}
+
+static void clk_pll1_unprepare(struct clk_hw *hw)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base);
+   val |= (1 << PLL_PD);
+   writel_relaxed(val, pll->base);
+}
+
+static unsigned long clk_pll2_recalc_rate(struct clk_hw *hw,
+unsigned long parent_rate)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val, ref, divr1, divf1, divr2, divf2;
+   u64 temp64;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   switch ((val >> PLL_REF_SHIFT) & PLL_REF_MASK) {
+   case 0:
+   ref = OSC_25M;
+   break;
+   case 1:
+   ref = OSC_27M;
+   break;
+   default:
+   ref = OSC_25M;
+   break;
+   }
+
+   val = readl_relaxed(pll->base + PLL_CFG2);
+   divr1 = (val >> PLL_DIVR1_SHIFT) & PLL_DIVR1_MASK;
+   divr2 = (val >> PLL_DIVR2_SHIFT) & PLL_DIVR2_MASK;
+   divf1 = (val >> PLL_DIVF1_SHIFT) & PLL_DIVF_MASK;
+   divf2 = (val >> PLL_DIVF2_SHIFT) & PLL_DIVF_MASK;
+
+   temp6

[PATCH v6 5/5] clk: imx: add clock driver for i.MX8MQ CCM

2018-08-22 Thread Abel Vesa
From: Lucas Stach 

Add driver for the Clock Control Module found on i.MX8MQ.

This is largely based on the downstream driver from Anson Huang and
Bai Ping at NXP, with only some small adaptions to mainline from me.

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/Makefile |   1 +
 drivers/clk/imx/clk-imx8mq.c | 631 +++
 drivers/clk/imx/clk.h|  36 +++
 3 files changed, 668 insertions(+)
 create mode 100644 drivers/clk/imx/clk-imx8mq.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 4fabb0a..64e695c 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -30,3 +30,4 @@ obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o
 obj-$(CONFIG_SOC_IMX6UL) += clk-imx6ul.o
 obj-$(CONFIG_SOC_IMX7D)  += clk-imx7d.o
 obj-$(CONFIG_SOC_VF610)  += clk-vf610.o
+obj-$(CONFIG_SOC_IMX8MQ) += clk-imx8mq.o
diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c
new file mode 100644
index 000..d3a9e31
--- /dev/null
+++ b/drivers/clk/imx/clk-imx8mq.c
@@ -0,0 +1,631 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 NXP.
+ * Copyright (C) 2017 Pengutronix, Lucas Stach 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+static u32 share_count_sai1;
+static u32 share_count_sai2;
+static u32 share_count_sai3;
+static u32 share_count_sai4;
+static u32 share_count_sai5;
+static u32 share_count_sai6;
+static u32 share_count_dcss;
+static u32 share_count_nand;
+
+static struct clk *clks[IMX8MQ_CLK_END];
+
+static const char *pll_ref_sels[] = { "osc_25m", "osc_27m", "dummy", "dummy", 
};
+static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
+static const char *gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
+static const char *vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", };
+static const char *audio_pll1_bypass_sels[] = {"audio_pll1", 
"audio_pll1_ref_sel", };
+static const char *audio_pll2_bypass_sels[] = {"audio_pll2", 
"audio_pll2_ref_sel", };
+static const char *video_pll1_bypass_sels[] = {"video_pll1", 
"video_pll1_ref_sel", };
+
+static const char *sys1_pll1_out_sels[] = {"sys1_pll1", "sys1_pll1_ref_sel", };
+static const char *sys2_pll1_out_sels[] = {"sys2_pll1", "sys1_pll1_ref_sel", };
+static const char *sys3_pll1_out_sels[] = {"sys3_pll1", "sys3_pll1_ref_sel", };
+static const char *dram_pll1_out_sels[] = {"dram_pll1", "dram_pll1_ref_sel", };
+static const char *video2_pll1_out_sels[] = {"video2_pll1", 
"video2_pll1_ref_sel", };
+
+static const char *sys1_pll2_out_sels[] = {"sys1_pll2_div", 
"sys1_pll1_ref_sel", };
+static const char *sys2_pll2_out_sels[] = {"sys2_pll2_div", 
"sys2_pll1_ref_sel", };
+static const char *sys3_pll2_out_sels[] = {"sys3_pll2_div", 
"sys2_pll1_ref_sel", };
+static const char *dram_pll2_out_sels[] = {"dram_pll2_div", 
"dram_pll1_ref_sel", };
+static const char *video2_pll2_out_sels[] = {"video2_pll2_div", 
"video2_pll1_ref_sel", };
+
+/* CCM ROOT */
+static const char *imx8mq_a53_sels[] = {"osc_25m", "arm_pll_out", 
"sys2_pll_500m", "sys2_pll_1000m",
+   "sys1_pll_800m", "sys1_pll_400m", 
"audio_pll1_out", "sys3_pll2_out", };
+
+static const char *imx8mq_vpu_sels[] = {"osc_25m", "arm_pll_out", 
"sys2_pll_500m", "sys2_pll_1000m",
+   "sys1_pll_800m", "sys1_pll_400m", 
"audio_pll1_out", "vpu_pll_out", };
+
+static const char *imx8mq_gpu_core_sels[] = {"osc_25m", "gpu_pll_out", 
"sys1_pll_800m", "sys3_pll2_out",
+"sys2_pll_1000m", 
"audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mq_gpu_shader_sels[] = {"osc_25m", "gpu_pll_out", 
"sys1_pll_800m", "sys3_pll2_out",
+  "sys2_pll_1000m", 
"audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mq_main_axi_sels[] = {"osc_25m", "sys2_pll_333m", 
"sys1_pll_800m", "sys2_pll_250m",
+"sys2_pll_1000m", 
"audio_pll1_out", "video_pll1_out", "sys1_pll_100m",};
+
+static const ch

[PATCH v6 4/5] clk: imx: add imx composite clock

2018-08-22 Thread Abel Vesa
Since a lot of clocks on imx8 are formed by a mux, gate, predivider and
divider, the idea here is to combine all of those into one composite clock,
but we need to deal with both predivider and divider at the same time and
therefore we add the imx_clk_composite_divider_ops and register the composite
clock with those.

Signed-off-by: Abel Vesa 
Suggested-by: Sascha Hauer 
---
 drivers/clk/imx/Makefile|   1 +
 drivers/clk/imx/clk-composite.c | 157 
 drivers/clk/imx/clk.h   |   9 +++
 3 files changed, 167 insertions(+)
 create mode 100644 drivers/clk/imx/clk-composite.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index b87513c..4fabb0a 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -3,6 +3,7 @@
 obj-y += \
clk.o \
clk-busy.o \
+   clk-composite.o \
clk-cpu.o \
clk-fixup-div.o \
clk-fixup-mux.o \
diff --git a/drivers/clk/imx/clk-composite.c b/drivers/clk/imx/clk-composite.c
new file mode 100644
index 000..a5c0080
--- /dev/null
+++ b/drivers/clk/imx/clk-composite.c
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 NXP
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+#define PCG_PREDIV_SHIFT   16
+#define PCG_PREDIV_WIDTH   3
+
+#define PCG_DIV_SHIFT  0
+#define PCG_DIV_WIDTH  6
+
+#define PCG_PCS_SHIFT  24
+#define PCG_PCS_MASK   0x7
+
+#define PCG_CGC_SHIFT  28
+
+static unsigned long imx_clk_composite_divider_recalc_rate(struct clk_hw *hw,
+   unsigned long parent_rate)
+{
+   struct clk_divider *divider = to_clk_divider(hw);
+   unsigned long prediv_rate;
+   unsigned int prediv_value;
+   unsigned int div_value;
+
+   prediv_value = clk_readl(divider->reg) >> divider->shift;
+   prediv_value &= clk_div_mask(divider->width);
+
+   prediv_rate = divider_recalc_rate(hw, parent_rate, prediv_value,
+   divider->table, divider->flags,
+   divider->width);
+
+   div_value = clk_readl(divider->reg) >> PCG_DIV_SHIFT;
+   div_value &= clk_div_mask(PCG_DIV_WIDTH);
+
+   return divider_recalc_rate(hw, prediv_rate, div_value, divider->table,
+  divider->flags, PCG_DIV_WIDTH);
+}
+
+static long imx_clk_composite_divider_round_rate(struct clk_hw *hw,
+   unsigned long rate,
+   unsigned long *prate)
+{
+   struct clk_divider *divider = to_clk_divider(hw);
+   unsigned long prediv_rate;
+
+   prediv_rate = divider_round_rate(hw, rate, prate, divider->table,
+ divider->width, divider->flags);
+   return divider_round_rate(hw, rate, &prediv_rate, divider->table,
+ PCG_DIV_WIDTH, divider->flags);
+}
+
+static int imx_clk_composite_divider_set_rate(struct clk_hw *hw,
+   unsigned long rate,
+   unsigned long parent_rate)
+{
+   struct clk_divider *divider = to_clk_divider(hw);
+   unsigned long prediv_rate;
+   unsigned long flags = 0;
+   int prediv_value;
+   int div_value;
+   u32 val;
+
+   prediv_value = divider_get_val(rate, parent_rate, NULL,
+   PCG_PREDIV_WIDTH, CLK_DIVIDER_ROUND_CLOSEST);
+   if (prediv_value < 0)
+   return prediv_value;
+
+   prediv_rate = DIV_ROUND_UP_ULL((u64)parent_rate, prediv_value + 1);
+
+   div_value = divider_get_val(rate, prediv_rate, NULL,
+   PCG_DIV_WIDTH, CLK_DIVIDER_ROUND_CLOSEST);
+   if (div_value < 0)
+   return div_value;
+
+   spin_lock_irqsave(divider->lock, flags);
+
+   val = clk_readl(divider->reg);
+   val &= ~((clk_div_mask(divider->width) << divider->shift) |
+   (clk_div_mask(PCG_DIV_WIDTH) << PCG_DIV_SHIFT));
+
+   val |= (u32)prediv_value << divider->shift;
+   val |= (u32)div_value << PCG_DIV_SHIFT;
+   clk_writel(val, divider->reg);
+
+   spin_unlock_irqrestore(divider->lock, flags);
+
+   return 0;
+}
+
+static const struct clk_ops imx_clk_composite_divider_ops = {
+   .recalc_rate = imx_clk_composite_divider_recalc_rate,
+   .round_rate = imx_clk_composite_divider_round_rate,
+   .set_rate = imx_clk_composite_divider_set_rate,
+};
+
+struct clk *imx_clk_composite_flags(const char *name,
+   const char **parent_names,
+   int num_parents, void __iomem *reg,
+   un

Re: [PATCH] arm: ftrace: Adds support for CONFIG_DYNAMIC_FTRACE_WITH_REGS

2017-05-12 Thread Abel Vesa
On Fri, May 12, 2017 at 09:38:37PM +0100, abelv...@gmail.com wrote:
> From: Abel Vesa 
To be ignored, wrong git config. Will send another one without the From line.
> 
> The DYNAMIC_FTRACE_WITH_REGS configuration makes it possible for a ftrace
> operation to specify if registers need to saved/restored by the ftrace 
> handler.
> This is needed by kgraft and possibly other ftrace-based tools, and the ARM
> architecture is currently lacking this feature. It would also be the first 
> step
> to support the "Kprobes-on-ftrace" optimization on ARM.
> 
> This patch introduces a new ftrace handler that stores the registers on the
> stack before calling the next stage. The registers are restored from the stack
> before going back to the instrumented function.
> 
> A side-effect of this patch is to activate the support for 
> ftrace_modify_call()
> as it defines ARCH_SUPPORTS_FTRACE_OPS for the ARM architecture.
> 
> Signed-off-by: Abel Vesa 
> ---
>  arch/arm/Kconfig   |   1 +
>  arch/arm/include/asm/ftrace.h  |   4 ++
>  arch/arm/kernel/entry-ftrace.S | 100 
> +
>  arch/arm/kernel/ftrace.c   |  37 +++
>  4 files changed, 142 insertions(+)
> 
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 4c1a35f..730d456 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -56,6 +56,7 @@ config ARM
>   select HAVE_DMA_API_DEBUG
>   select HAVE_DMA_CONTIGUOUS if MMU
>   select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL) && !CPU_ENDIAN_BE32 && MMU
> + select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE
>   select HAVE_EFFICIENT_UNALIGNED_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) 
> && MMU
>   select HAVE_EXIT_THREAD
>   select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
> diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
> index 22b7311..f379881 100644
> --- a/arch/arm/include/asm/ftrace.h
> +++ b/arch/arm/include/asm/ftrace.h
> @@ -1,6 +1,10 @@
>  #ifndef _ASM_ARM_FTRACE
>  #define _ASM_ARM_FTRACE
>  
> +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
> +#define ARCH_SUPPORTS_FTRACE_OPS 1
> +#endif
> +
>  #ifdef CONFIG_FUNCTION_TRACER
>  #define MCOUNT_ADDR  ((unsigned long)(__gnu_mcount_nc))
>  #define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */
> diff --git a/arch/arm/kernel/entry-ftrace.S b/arch/arm/kernel/entry-ftrace.S
> index c73c403..efcd9f2 100644
> --- a/arch/arm/kernel/entry-ftrace.S
> +++ b/arch/arm/kernel/entry-ftrace.S
> @@ -92,12 +92,95 @@
>  2:   mcount_exit
>  .endm
>  
> +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
> +
> +.macro __ftrace_regs_caller
> +
> + sub sp, sp, #8  @ space for PC and CPSR OLD_R0,
> + @ OLD_R0 will overwrite previous LR
> +
> + add ip, sp, #12 @ move in IP the value of SP as it was
> + @ before the push {lr} of the mcount mechanism
> +
> + str lr, [sp, #0]@ store LR instead of PC
> +
> + ldr lr, [sp, #8]@ get previous LR
> +
> + str r0, [sp, #8]@ write r0 as OLD_R0 over previous LR
> +
> + stmdb   sp!, {ip, lr}
> + stmdb   sp!, {r0-r11, lr}
> +
> + @ stack content at this point:
> + @ 0  4  48   52   5660   6468   72
> + @ R0 | R1 | ... | LR | SP + 4 | previous LR | LR | PSR | OLD_R0 |
> +
> + mov r3, sp  @ struct pt_regs*
> +
> + ldr r2, =function_trace_op
> + ldr r2, [r2]@ pointer to the current
> + @ function tracing op
> +
> + ldr r1, [sp, #S_LR] @ lr of instrumented func
> +
> + ldr lr, [sp, #S_PC] @ get LR
> +
> + mcount_adjust_addr  r0, lr  @ instrumented function
> +
> + .globl ftrace_regs_call
> +ftrace_regs_call:
> + bl  ftrace_stub
> +
> +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
> + .globl ftrace_graph_regs_call
> +ftrace_graph_regs_call:
> + mov r0, r0
> +#endif
> +
> + @ pop saved regs
> + ldmia   sp!, {r0-r12}   @ restore r0 through r12
> + ldr ip, [sp, #8]@ restore PC
> + ldr lr, [sp, #4]@ restore LR
> + ldr sp, [sp, #0]@ restore SP
> + mov pc, ip  @ return
> +.endm
> +
> +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
> +.macro __ftrace_graph_regs_caller
> +
> + sub r0, fp, #4  @ lr of instrumented routine (parent)
> +
> +   

[PATCH] arm: ftrace: Adds support for CONFIG_DYNAMIC_FTRACE_WITH_REGS

2017-05-12 Thread Abel Vesa
The DYNAMIC_FTRACE_WITH_REGS configuration makes it possible for a ftrace
operation to specify if registers need to saved/restored by the ftrace handler.
This is needed by kgraft and possibly other ftrace-based tools, and the ARM
architecture is currently lacking this feature. It would also be the first step
to support the "Kprobes-on-ftrace" optimization on ARM.

This patch introduces a new ftrace handler that stores the registers on the
stack before calling the next stage. The registers are restored from the stack
before going back to the instrumented function.

A side-effect of this patch is to activate the support for ftrace_modify_call()
as it defines ARCH_SUPPORTS_FTRACE_OPS for the ARM architecture.

Signed-off-by: Abel Vesa 
---
 arch/arm/Kconfig   |   1 +
 arch/arm/include/asm/ftrace.h  |   4 ++
 arch/arm/kernel/entry-ftrace.S | 100 +
 arch/arm/kernel/ftrace.c   |  37 +++
 4 files changed, 142 insertions(+)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 4c1a35f..730d456 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -56,6 +56,7 @@ config ARM
select HAVE_DMA_API_DEBUG
select HAVE_DMA_CONTIGUOUS if MMU
select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL) && !CPU_ENDIAN_BE32 && MMU
+   select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE
select HAVE_EFFICIENT_UNALIGNED_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) 
&& MMU
select HAVE_EXIT_THREAD
select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
index 22b7311..f379881 100644
--- a/arch/arm/include/asm/ftrace.h
+++ b/arch/arm/include/asm/ftrace.h
@@ -1,6 +1,10 @@
 #ifndef _ASM_ARM_FTRACE
 #define _ASM_ARM_FTRACE
 
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+#define ARCH_SUPPORTS_FTRACE_OPS 1
+#endif
+
 #ifdef CONFIG_FUNCTION_TRACER
 #define MCOUNT_ADDR((unsigned long)(__gnu_mcount_nc))
 #define MCOUNT_INSN_SIZE   4 /* sizeof mcount call */
diff --git a/arch/arm/kernel/entry-ftrace.S b/arch/arm/kernel/entry-ftrace.S
index c73c403..efcd9f2 100644
--- a/arch/arm/kernel/entry-ftrace.S
+++ b/arch/arm/kernel/entry-ftrace.S
@@ -92,12 +92,95 @@
 2: mcount_exit
 .endm
 
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+
+.macro __ftrace_regs_caller
+
+   sub sp, sp, #8  @ space for PC and CPSR OLD_R0,
+   @ OLD_R0 will overwrite previous LR
+
+   add ip, sp, #12 @ move in IP the value of SP as it was
+   @ before the push {lr} of the mcount mechanism
+
+   str lr, [sp, #0]@ store LR instead of PC
+
+   ldr lr, [sp, #8]@ get previous LR
+
+   str r0, [sp, #8]@ write r0 as OLD_R0 over previous LR
+
+   stmdb   sp!, {ip, lr}
+   stmdb   sp!, {r0-r11, lr}
+
+   @ stack content at this point:
+   @ 0  4  48   52   5660   6468   72
+   @ R0 | R1 | ... | LR | SP + 4 | previous LR | LR | PSR | OLD_R0 |
+
+   mov r3, sp  @ struct pt_regs*
+
+   ldr r2, =function_trace_op
+   ldr r2, [r2]@ pointer to the current
+   @ function tracing op
+
+   ldr r1, [sp, #S_LR] @ lr of instrumented func
+
+   ldr lr, [sp, #S_PC] @ get LR
+
+   mcount_adjust_addr  r0, lr  @ instrumented function
+
+   .globl ftrace_regs_call
+ftrace_regs_call:
+   bl  ftrace_stub
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+   .globl ftrace_graph_regs_call
+ftrace_graph_regs_call:
+   mov r0, r0
+#endif
+
+   @ pop saved regs
+   ldmia   sp!, {r0-r12}   @ restore r0 through r12
+   ldr ip, [sp, #8]@ restore PC
+   ldr lr, [sp, #4]@ restore LR
+   ldr sp, [sp, #0]@ restore SP
+   mov pc, ip  @ return
+.endm
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+.macro __ftrace_graph_regs_caller
+
+   sub r0, fp, #4  @ lr of instrumented routine (parent)
+
+   @ called from __ftrace_regs_caller
+   ldr r1, [sp, #S_PC] @ instrumented routine (func)
+   mcount_adjust_addr  r1, r1
+
+   mov r2, fp  @ frame pointer
+   bl  prepare_ftrace_return
+
+   @ pop registers saved in ftrace_regs_caller
+   ldmia   sp!, {r0-r12}   @ restore r0 through r12
+   ldr ip, [sp, #8]@ restore PC
+   ldr lr, [sp, #4]@ restore LR
+   ldr sp, [sp, #0]@ restore SP
+   mov pc, ip  @ return
+
+.endm
+#endif
+#endif
+
 .macro __ftrace_caller suffix
mcount_enter
 
mcount_get_lr

[PATCH] clk: imx7d: Add USB clock information

2018-03-27 Thread Abel Vesa
From: Peter Chen 

Add USB clock information, the pll_usb_main_clk is USB_PLL at CCM
which is the output of USBOTG2 PHY.

Signed-off-by: Peter Chen 
Signed-off-by: Irina Tirdea 
Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/clk-imx7d.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c
index 89bfa75..39d110b 100644
--- a/drivers/clk/imx/clk-imx7d.c
+++ b/drivers/clk/imx/clk-imx7d.c
@@ -801,7 +801,7 @@ static void __init imx7d_clocks_init(struct device_node 
*ccm_node)
clks[IMX7D_OCOTP_CLK] = imx_clk_gate4("ocotp_clk", "ipg_root_clk", base 
+ 0x4230, 0);
clks[IMX7D_SNVS_CLK] = imx_clk_gate4("snvs_clk", "ipg_root_clk", base + 
0x4250, 0);
clks[IMX7D_CAAM_CLK] = imx_clk_gate4("caam_clk", "ipg_root_clk", base + 
0x4240, 0);
-   clks[IMX7D_USB_HSIC_ROOT_CLK] = imx_clk_gate4("usb_hsic_root_clk", 
"usb_hsic_post_div", base + 0x4420, 0);
+   clks[IMX7D_USB_HSIC_ROOT_CLK] = imx_clk_gate4("usb_hsic_root_clk", 
"usb_hsic_post_div", base + 0x4690, 0);
clks[IMX7D_SDMA_CORE_CLK] = imx_clk_gate4("sdma_root_clk", 
"ahb_root_clk", base + 0x4480, 0);
clks[IMX7D_PCIE_CTRL_ROOT_CLK] = imx_clk_gate4("pcie_ctrl_root_clk", 
"pcie_ctrl_post_div", base + 0x4600, 0);
clks[IMX7D_PCIE_PHY_ROOT_CLK] = imx_clk_gate4("pcie_phy_root_clk", 
"pcie_phy_post_div", base + 0x4600, 0);
@@ -867,6 +867,9 @@ static void __init imx7d_clocks_init(struct device_node 
*ccm_node)
clks[IMX7D_CSI_MCLK_ROOT_CLK] = imx_clk_gate4("csi_mclk_root_clk", 
"csi_mclk_post_div", base + 0x4490, 0);
clks[IMX7D_AUDIO_MCLK_ROOT_CLK] = imx_clk_gate4("audio_mclk_root_clk", 
"audio_mclk_post_div", base + 0x4790, 0);
clks[IMX7D_WRCLK_ROOT_CLK] = imx_clk_gate4("wrclk_root_clk", 
"wrclk_post_div", base + 0x47a0, 0);
+   clks[IMX7D_USB_CTRL_CLK] = imx_clk_gate4("usb_ctrl_clk", 
"ahb_root_clk", base + 0x4680, 0);
+   clks[IMX7D_USB_PHY1_CLK] = imx_clk_gate4("usb_phy1_clk", 
"pll_usb1_main_clk", base + 0x46a0, 0);
+   clks[IMX7D_USB_PHY2_CLK] = imx_clk_gate4("usb_phy2_clk", 
"pll_usb_main_clk", base + 0x46b0, 0);
clks[IMX7D_ADC_ROOT_CLK] = imx_clk_gate4("adc_root_clk", 
"ipg_root_clk", base + 0x4200, 0);
 
clks[IMX7D_GPT_3M_CLK] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8);
@@ -892,6 +895,10 @@ static void __init imx7d_clocks_init(struct device_node 
*ccm_node)
/* set uart module clock's parent clock source that must be great then 
80MHz */
clk_set_parent(clks[IMX7D_UART1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]);
 
+   /* Set clock rate for USBPHY, the USB_PLL at CCM is from USBOTG2 */
+   clks[IMX7D_USB1_MAIN_480M_CLK] = 
imx_clk_fixed_factor("pll_usb1_main_clk", "osc", 20, 1);
+   clks[IMX7D_USB_MAIN_480M_CLK] = 
imx_clk_fixed_factor("pll_usb_main_clk", "osc", 20, 1);
+
imx_register_uart_clocks(uart_clks);
 
 }
-- 
2.7.4



[PATCH] clk: imx7d: Correct dram pll type

2018-03-27 Thread Abel Vesa
From: Anson Huang 

DRAM PLL is a audio/video type PLL, need to correct
it to get correct ops of PLL.

There is a test_div placed before DRAM PLL's gate, so
add this test div clk.

Signed-off-by: Anson Huang 
Signed-off-by: Irina Tirdea 
Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/clk-imx7d.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c
index 89bfa75..45c83b6 100644
--- a/drivers/clk/imx/clk-imx7d.c
+++ b/drivers/clk/imx/clk-imx7d.c
@@ -441,11 +441,13 @@ static void __init imx7d_clocks_init(struct device_node 
*ccm_node)
clk_set_parent(clks[IMX7D_PLL_VIDEO_MAIN_BYPASS], 
clks[IMX7D_PLL_VIDEO_MAIN]);
 
clks[IMX7D_PLL_ARM_MAIN_CLK] = imx_clk_gate("pll_arm_main_clk", 
"pll_arm_main_bypass", base + 0x60, 13);
-   clks[IMX7D_PLL_DRAM_MAIN_CLK] = imx_clk_gate("pll_dram_main_clk", 
"pll_dram_main_bypass", base + 0x70, 13);
+   clks[IMX7D_PLL_DRAM_MAIN_CLK] = imx_clk_gate("pll_dram_main_clk", 
"pll_dram_test_div", base + 0x70, 13);
clks[IMX7D_PLL_SYS_MAIN_CLK] = imx_clk_gate("pll_sys_main_clk", 
"pll_sys_main_bypass", base + 0xb0, 13);
clks[IMX7D_PLL_AUDIO_MAIN_CLK] = imx_clk_gate("pll_audio_main_clk", 
"pll_audio_main_bypass", base + 0xf0, 13);
clks[IMX7D_PLL_VIDEO_MAIN_CLK] = imx_clk_gate("pll_video_main_clk", 
"pll_video_main_bypass", base + 0x130, 13);
 
+   clks[IMX7D_PLL_DRAM_TEST_DIV]  = clk_register_divider_table(NULL, 
"pll_dram_test_div", "pll_dram_main_bypass",
+   CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 
0x70, 21, 2, 0, test_div_table, &imx_ccm_lock);
clks[IMX7D_PLL_AUDIO_TEST_DIV]  = clk_register_divider_table(NULL, 
"pll_audio_test_div", "pll_audio_main_clk",
CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, base + 
0xf0, 19, 2, 0, test_div_table, &imx_ccm_lock);
clks[IMX7D_PLL_AUDIO_POST_DIV] = clk_register_divider_table(NULL, 
"pll_audio_post_div", "pll_audio_test_div",
-- 
2.7.4



[PATCH] clk: imx7d: Correct ahb clk parent select

2018-03-27 Thread Abel Vesa
From: Anson Huang 

Design team change the ahb's clk parent options but
did NOT update the DOC accordingly in time, so the
AHB/IPG's clk rate in clk tree is incorrect, AHB is
67.5MHz and IPG is 33.75MHz, but using scope to
monitor them, they are actually 135MHz and 67.5MHz,
update the clk parent option to make clk tree info
correct.

Signed-off-by: Anson Huang 
Signed-off-by: Irina Tirdea 
Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/clk-imx7d.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c
index 89bfa75..4d020dd 100644
--- a/drivers/clk/imx/clk-imx7d.c
+++ b/drivers/clk/imx/clk-imx7d.c
@@ -74,7 +74,7 @@ static const char *nand_usdhc_bus_sel[] = { "osc", 
"pll_sys_pfd2_270m_clk",
 
 static const char *ahb_channel_sel[] = { "osc", "pll_sys_pfd2_270m_clk",
"pll_dram_533m_clk", "pll_sys_pfd0_392m_clk",
-   "pll_enet_125m_clk", "pll_usb_main_clk", "pll_audio_post_div",
+   "pll_enet_250m_clk", "pll_usb_main_clk", "pll_audio_post_div",
"pll_video_post_div", };
 
 static const char *dram_phym_sel[] = { "pll_dram_main_clk",
-- 
2.7.4



[PATCH] clk: imx7d: Move clks_init_on before any clock operations

2018-03-27 Thread Abel Vesa
From: Dong Aisheng 

For init on clocks we should move it at the first place in imx7d_clocks_init()
before any clock operations, else the clock operation may fail in case the clock
is still not on.

Acked-by: Ranjani Vaidyanathan 
Signed-off-by: Dong Aisheng 
Signed-off-by: Irina Tirdea 
Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/clk-imx7d.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c
index 89bfa75..9b17805 100644
--- a/drivers/clk/imx/clk-imx7d.c
+++ b/drivers/clk/imx/clk-imx7d.c
@@ -433,13 +433,6 @@ static void __init imx7d_clocks_init(struct device_node 
*ccm_node)
clks[IMX7D_PLL_AUDIO_MAIN_BYPASS] = 
imx_clk_mux_flags("pll_audio_main_bypass", base + 0xf0, 16, 1, 
pll_audio_bypass_sel, ARRAY_SIZE(pll_audio_bypass_sel), CLK_SET_RATE_PARENT);
clks[IMX7D_PLL_VIDEO_MAIN_BYPASS] = 
imx_clk_mux_flags("pll_video_main_bypass", base + 0x130, 16, 1, 
pll_video_bypass_sel, ARRAY_SIZE(pll_video_bypass_sel), CLK_SET_RATE_PARENT);
 
-   clk_set_parent(clks[IMX7D_PLL_ARM_MAIN_BYPASS], 
clks[IMX7D_PLL_ARM_MAIN]);
-   clk_set_parent(clks[IMX7D_PLL_DRAM_MAIN_BYPASS], 
clks[IMX7D_PLL_DRAM_MAIN]);
-   clk_set_parent(clks[IMX7D_PLL_SYS_MAIN_BYPASS], 
clks[IMX7D_PLL_SYS_MAIN]);
-   clk_set_parent(clks[IMX7D_PLL_ENET_MAIN_BYPASS], 
clks[IMX7D_PLL_ENET_MAIN]);
-   clk_set_parent(clks[IMX7D_PLL_AUDIO_MAIN_BYPASS], 
clks[IMX7D_PLL_AUDIO_MAIN]);
-   clk_set_parent(clks[IMX7D_PLL_VIDEO_MAIN_BYPASS], 
clks[IMX7D_PLL_VIDEO_MAIN]);
-
clks[IMX7D_PLL_ARM_MAIN_CLK] = imx_clk_gate("pll_arm_main_clk", 
"pll_arm_main_bypass", base + 0x60, 13);
clks[IMX7D_PLL_DRAM_MAIN_CLK] = imx_clk_gate("pll_dram_main_clk", 
"pll_dram_main_bypass", base + 0x70, 13);
clks[IMX7D_PLL_SYS_MAIN_CLK] = imx_clk_gate("pll_sys_main_clk", 
"pll_sys_main_bypass", base + 0xb0, 13);
@@ -886,6 +879,13 @@ static void __init imx7d_clocks_init(struct device_node 
*ccm_node)
for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
clk_prepare_enable(clks[clks_init_on[i]]);
 
+   clk_set_parent(clks[IMX7D_PLL_ARM_MAIN_BYPASS], 
clks[IMX7D_PLL_ARM_MAIN]);
+   clk_set_parent(clks[IMX7D_PLL_DRAM_MAIN_BYPASS], 
clks[IMX7D_PLL_DRAM_MAIN]);
+   clk_set_parent(clks[IMX7D_PLL_SYS_MAIN_BYPASS], 
clks[IMX7D_PLL_SYS_MAIN]);
+   clk_set_parent(clks[IMX7D_PLL_ENET_MAIN_BYPASS], 
clks[IMX7D_PLL_ENET_MAIN]);
+   clk_set_parent(clks[IMX7D_PLL_AUDIO_MAIN_BYPASS], 
clks[IMX7D_PLL_AUDIO_MAIN]);
+   clk_set_parent(clks[IMX7D_PLL_VIDEO_MAIN_BYPASS], 
clks[IMX7D_PLL_VIDEO_MAIN]);
+
/* use old gpt clk setting, gpt1 root clk must be twice as gpt counter 
freq */
clk_set_parent(clks[IMX7D_GPT1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]);
 
-- 
2.7.4



[PATCH v2] clk: imx: Set CLK_SET_RATE_GATE for gate and divider clocks

2018-04-11 Thread Abel Vesa
From: Shawn Guo 

Add flag CLK_SET_RATE_GATE for i.MX gate and divider clocks on which the
client drivers usually make clk_set_rate() call, so that the call will fail
when clock is still on instead of standing the risk of running into glitch
issue. Rate cannot be changed when the clock is enabled due to the glitchy
multiplexers.

Signed-off-by: Shawn Guo 
[initial patch from imx internal repo]
Signed-off-by: Abel Vesa 
[carried over from 3.14 and also applied the flag to newer functions]
---

Changes since v1:
 - changed ownership as per initial patch

 drivers/clk/imx/clk.h | 15 +--
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index 8076ec0..753ebc4 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -96,7 +96,8 @@ static inline struct clk *imx_clk_fixed_factor(const char 
*name,
 static inline struct clk *imx_clk_divider(const char *name, const char *parent,
void __iomem *reg, u8 shift, u8 width)
 {
-   return clk_register_divider(NULL, name, parent, CLK_SET_RATE_PARENT,
+   return clk_register_divider(NULL, name, parent,
+   CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE,
reg, shift, width, 0, &imx_ccm_lock);
 }
 
@@ -140,7 +141,8 @@ static inline struct clk *imx_clk_gate_dis(const char 
*name, const char *parent,
 static inline struct clk *imx_clk_gate2(const char *name, const char *parent,
void __iomem *reg, u8 shift)
 {
-   return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
+   return clk_register_gate2(NULL, name, parent,
+   CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, reg,
shift, 0x3, 0, &imx_ccm_lock, NULL);
 }
 
@@ -155,7 +157,8 @@ static inline struct clk *imx_clk_gate2_shared(const char 
*name,
const char *parent, void __iomem *reg, u8 shift,
unsigned int *share_count)
 {
-   return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
+   return clk_register_gate2(NULL, name, parent,
+   CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, reg,
shift, 0x3, 0, &imx_ccm_lock, share_count);
 }
 
@@ -164,8 +167,8 @@ static inline struct clk *imx_clk_gate2_shared2(const char 
*name,
unsigned int *share_count)
 {
return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT |
- CLK_OPS_PARENT_ENABLE, reg, shift, 0x3, 0,
- &imx_ccm_lock, share_count);
+   CLK_SET_RATE_GATE | CLK_OPS_PARENT_ENABLE,
+   reg, shift, 0x3, 0, &imx_ccm_lock, share_count);
 }
 
 static inline struct clk *imx_clk_gate2_cgr(const char *name,
@@ -187,7 +190,7 @@ static inline struct clk *imx_clk_gate4(const char *name, 
const char *parent,
void __iomem *reg, u8 shift)
 {
return clk_register_gate2(NULL, name, parent,
-   CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+   CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE | CLK_OPS_PARENT_ENABLE,
reg, shift, 0x3, 0, &imx_ccm_lock, NULL);
 }
 
-- 
2.7.4



[PATCH 1/4] arm: imx: Update clk driver API

2018-03-22 Thread Abel Vesa
This adds the following new wrappers:
 - imx_clk_gate2_flag
 - imx_clk_set_parent

It also updates the flags for the old wrappers.

Signed-off-by: Anson Huang 
Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/clk.h | 42 +++---
 1 file changed, 31 insertions(+), 11 deletions(-)

diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index d69c4bb..466c37f3 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -4,6 +4,7 @@
 
 #include 
 #include 
+#include 
 
 extern spinlock_t imx_ccm_lock;
 
@@ -54,6 +55,15 @@ struct clk * imx_obtain_fixed_clock(
 struct clk *imx_clk_gate_exclusive(const char *name, const char *parent,
 void __iomem *reg, u8 shift, u32 exclusive_mask);
 
+static inline void imx_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+   int ret = clk_set_parent(clk, parent);
+
+   if (ret)
+   pr_err("failed to set parent of clk %s to %s: %d\n",
+   __clk_get_name(clk), __clk_get_name(parent), ret);
+}
+
 struct clk *imx_clk_pfd(const char *name, const char *parent_name,
void __iomem *reg, u8 idx);
 
@@ -96,7 +106,8 @@ static inline struct clk *imx_clk_fixed_factor(const char 
*name,
 static inline struct clk *imx_clk_divider(const char *name, const char *parent,
void __iomem *reg, u8 shift, u8 width)
 {
-   return clk_register_divider(NULL, name, parent, CLK_SET_RATE_PARENT,
+   return clk_register_divider(NULL, name, parent,
+   CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE,
reg, shift, width, 0, &imx_ccm_lock);
 }
 
@@ -112,7 +123,7 @@ static inline struct clk *imx_clk_divider2(const char 
*name, const char *parent,
void __iomem *reg, u8 shift, u8 width)
 {
return clk_register_divider(NULL, name, parent,
-   CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+   CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE | CLK_OPS_PARENT_ENABLE,
reg, shift, width, 0, &imx_ccm_lock);
 }
 
@@ -133,7 +144,15 @@ static inline struct clk *imx_clk_gate_dis(const char 
*name, const char *parent,
 static inline struct clk *imx_clk_gate2(const char *name, const char *parent,
void __iomem *reg, u8 shift)
 {
-   return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
+   return clk_register_gate2(NULL, name, parent,
+   CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, reg,
+   shift, 0x3, 0, &imx_ccm_lock, NULL);
+}
+
+static inline struct clk *imx_clk_gate2_flags(const char *name, const char 
*parent,
+   void __iomem *reg, u8 shift, unsigned long flags)
+{
+   return clk_register_gate2(NULL, name, parent, flags, reg,
shift, 0x3, 0, &imx_ccm_lock, NULL);
 }
 
@@ -141,7 +160,8 @@ static inline struct clk *imx_clk_gate2_shared(const char 
*name,
const char *parent, void __iomem *reg, u8 shift,
unsigned int *share_count)
 {
-   return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
+   return clk_register_gate2(NULL, name, parent,
+   CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, reg,
shift, 0x3, 0, &imx_ccm_lock, share_count);
 }
 
@@ -150,8 +170,8 @@ static inline struct clk *imx_clk_gate2_shared2(const char 
*name,
unsigned int *share_count)
 {
return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT |
- CLK_OPS_PARENT_ENABLE, reg, shift, 0x3, 0,
- &imx_ccm_lock, share_count);
+   CLK_SET_RATE_GATE | CLK_OPS_PARENT_ENABLE,
+   reg, shift, 0x3, 0, &imx_ccm_lock, share_count);
 }
 
 static inline struct clk *imx_clk_gate2_cgr(const char *name,
@@ -173,7 +193,7 @@ static inline struct clk *imx_clk_gate4(const char *name, 
const char *parent,
void __iomem *reg, u8 shift)
 {
return clk_register_gate2(NULL, name, parent,
-   CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+   CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE | CLK_OPS_PARENT_ENABLE,
reg, shift, 0x3, 0, &imx_ccm_lock, NULL);
 }
 
@@ -181,8 +201,8 @@ static inline struct clk *imx_clk_mux(const char *name, 
void __iomem *reg,
u8 shift, u8 width, const char **parents, int num_parents)
 {
return clk_register_mux(NULL, name, parents, num_parents,
-   CLK_SET_RATE_NO_REPARENT, reg, shift,
-   width, 0, &imx_ccm_lock);
+   CLK_SET_RATE_NO_REPARENT | CLK_SET_PARENT_GATE,
+   reg, shift, width, 0, &imx_ccm_lock);
 }
 
 static inline struct clk *imx_clk_mux2(const char *name, void __iomem *reg,
@@ -198,8 +218,8 @@ static inline struct clk *imx_clk_mux_flags(

[PATCH 3/4] arm: imx: Correct ahb clk parent select

2018-03-22 Thread Abel Vesa
From: Anson Huang 

Design team change the ahb's clk parent options but did NOT update the DOC
accordingly in time, so the AHB/IPG's clk rate in clk tree is incorrect, AHB is
67.5MHz and IPG is 33.75MHz, but using scope to monitor them, they are actually
135MHz and 67.5MHz, update the clk parent option to make clk tree info correct.

Signed-off-by: Anson Huang 
Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/clk-imx7d.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c
index d786f98..3553b68 100644
--- a/drivers/clk/imx/clk-imx7d.c
+++ b/drivers/clk/imx/clk-imx7d.c
@@ -74,7 +74,7 @@ static const char *nand_usdhc_bus_sel[] = { "osc", 
"pll_sys_pfd2_270m_clk",
 
 static const char *ahb_channel_sel[] = { "osc", "pll_sys_pfd2_270m_clk",
"pll_dram_533m_clk", "pll_sys_pfd0_392m_clk",
-   "pll_enet_125m_clk", "pll_usb_main_clk", "pll_audio_post_div",
+   "pll_enet_250m_clk", "pll_usb_main_clk", "pll_audio_post_div",
"pll_video_post_div", };
 
 static const char *dram_phym_sel[] = { "pll_dram_main_clk",
-- 
2.7.4



[PATCH 0/4] arm: imx: Clock related updates

2018-03-22 Thread Abel Vesa
This is part of the imx upstreaming effort. All the changes are related imx
generic clk API and imx7d clk driver. The imx clk API updates will also be used
by the new imx SOCs that will follow.

Abel Vesa (1):
  arm: imx: Update clk driver API

Anson Huang (3):
  arm: imx: Correct dram pll type
  arm: imx: Correct ahb clk parent select
  arm: imx: Update clk driver for imx7d

 drivers/clk/imx/clk-imx7d.c | 127 +++-
 drivers/clk/imx/clk.h   |  42 +++
 2 files changed, 98 insertions(+), 71 deletions(-)

-- 
2.7.4



[PATCH 4/4] arm: imx: Update clk driver for imx7d

2018-03-22 Thread Abel Vesa
From: Anson Huang 

This patch updates the imx7d clk driver to make use of the new imx clk API.

Signed-off-by: Anson Huang 
Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/clk-imx7d.c | 28 ++--
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c
index 3553b68..255563b 100644
--- a/drivers/clk/imx/clk-imx7d.c
+++ b/drivers/clk/imx/clk-imx7d.c
@@ -433,13 +433,6 @@ static void __init imx7d_clocks_init(struct device_node 
*ccm_node)
clks[IMX7D_PLL_AUDIO_MAIN_BYPASS] = 
imx_clk_mux_flags("pll_audio_main_bypass", base + 0xf0, 16, 1, 
pll_audio_bypass_sel, ARRAY_SIZE(pll_audio_bypass_sel), CLK_SET_RATE_PARENT);
clks[IMX7D_PLL_VIDEO_MAIN_BYPASS] = 
imx_clk_mux_flags("pll_video_main_bypass", base + 0x130, 16, 1, 
pll_video_bypass_sel, ARRAY_SIZE(pll_video_bypass_sel), CLK_SET_RATE_PARENT);
 
-   clk_set_parent(clks[IMX7D_PLL_ARM_MAIN_BYPASS], 
clks[IMX7D_PLL_ARM_MAIN]);
-   clk_set_parent(clks[IMX7D_PLL_DRAM_MAIN_BYPASS], 
clks[IMX7D_PLL_DRAM_MAIN]);
-   clk_set_parent(clks[IMX7D_PLL_SYS_MAIN_BYPASS], 
clks[IMX7D_PLL_SYS_MAIN]);
-   clk_set_parent(clks[IMX7D_PLL_ENET_MAIN_BYPASS], 
clks[IMX7D_PLL_ENET_MAIN]);
-   clk_set_parent(clks[IMX7D_PLL_AUDIO_MAIN_BYPASS], 
clks[IMX7D_PLL_AUDIO_MAIN]);
-   clk_set_parent(clks[IMX7D_PLL_VIDEO_MAIN_BYPASS], 
clks[IMX7D_PLL_VIDEO_MAIN]);
-
clks[IMX7D_PLL_ARM_MAIN_CLK] = imx_clk_gate("pll_arm_main_clk", 
"pll_arm_main_bypass", base + 0x60, 13);
clks[IMX7D_PLL_DRAM_MAIN_CLK] = imx_clk_gate("pll_dram_main_clk", 
"pll_dram_test_div", base + 0x70, 13);
clks[IMX7D_PLL_SYS_MAIN_CLK] = imx_clk_gate("pll_sys_main_clk", 
"pll_sys_main_bypass", base + 0xb0, 13);
@@ -525,7 +518,7 @@ static void __init imx7d_clocks_init(struct device_node 
*ccm_node)
clks[IMX7D_PCIE_CTRL_ROOT_SRC] = imx_clk_mux2("pcie_ctrl_src", base + 
0xa180, 24, 3, pcie_ctrl_sel, ARRAY_SIZE(pcie_ctrl_sel));
clks[IMX7D_PCIE_PHY_ROOT_SRC] = imx_clk_mux2("pcie_phy_src", base + 
0xa200, 24, 3, pcie_phy_sel, ARRAY_SIZE(pcie_phy_sel));
clks[IMX7D_EPDC_PIXEL_ROOT_SRC] = imx_clk_mux2("epdc_pixel_src", base + 
0xa280, 24, 3, epdc_pixel_sel, ARRAY_SIZE(epdc_pixel_sel));
-   clks[IMX7D_LCDIF_PIXEL_ROOT_SRC] = imx_clk_mux2("lcdif_pixel_src", base 
+ 0xa300, 24, 3, lcdif_pixel_sel, ARRAY_SIZE(lcdif_pixel_sel));
+   clks[IMX7D_LCDIF_PIXEL_ROOT_SRC] = imx_clk_mux_flags("lcdif_pixel_src", 
base + 0xa300, 24, 3, lcdif_pixel_sel, ARRAY_SIZE(lcdif_pixel_sel), 
CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE);
clks[IMX7D_MIPI_DSI_ROOT_SRC] = imx_clk_mux2("mipi_dsi_src", base + 
0xa380, 24, 3,  mipi_dsi_sel, ARRAY_SIZE(mipi_dsi_sel));
clks[IMX7D_MIPI_CSI_ROOT_SRC] = imx_clk_mux2("mipi_csi_src", base + 
0xa400, 24, 3, mipi_csi_sel, ARRAY_SIZE(mipi_csi_sel));
clks[IMX7D_MIPI_DPHY_ROOT_SRC] = imx_clk_mux2("mipi_dphy_src", base + 
0xa480, 24, 3, mipi_dphy_sel, ARRAY_SIZE(mipi_dphy_sel));
@@ -719,13 +712,13 @@ static void __init imx7d_clocks_init(struct device_node 
*ccm_node)
clks[IMX7D_CLKO1_ROOT_PRE_DIV] = imx_clk_divider2("clko1_pre_div", 
"clko1_cg", base + 0xbd80, 16, 3);
clks[IMX7D_CLKO2_ROOT_PRE_DIV] = imx_clk_divider2("clko2_pre_div", 
"clko2_cg", base + 0xbe00, 16, 3);
 
-   clks[IMX7D_ARM_A7_ROOT_DIV] = imx_clk_divider2("arm_a7_div", 
"arm_a7_cg", base + 0x8000, 0, 3);
+   clks[IMX7D_ARM_A7_ROOT_DIV] = imx_clk_divider_flags("arm_a7_div", 
"arm_a7_cg", base + 0x8000, 0, 3, CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE);
clks[IMX7D_ARM_M4_ROOT_DIV] = imx_clk_divider2("arm_m4_div", 
"arm_m4_cg", base + 0x8080, 0, 3);
-   clks[IMX7D_MAIN_AXI_ROOT_DIV] = imx_clk_divider2("axi_post_div", 
"axi_pre_div", base + 0x8800, 0, 6);
+   clks[IMX7D_MAIN_AXI_ROOT_DIV] = imx_clk_divider_flags("axi_post_div", 
"axi_pre_div", base + 0x8800, 0, 6, CLK_OPS_PARENT_ENABLE);
clks[IMX7D_DISP_AXI_ROOT_DIV] = imx_clk_divider2("disp_axi_post_div", 
"disp_axi_pre_div", base + 0x8880, 0, 6);
clks[IMX7D_ENET_AXI_ROOT_DIV] = imx_clk_divider2("enet_axi_post_div", 
"enet_axi_pre_div", base + 0x8900, 0, 6);
clks[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = 
imx_clk_divider2("nand_usdhc_root_clk", "nand_usdhc_pre_div", base + 0x8980, 0, 
6);
-   clks[IMX7D_AHB_CHANNEL_ROOT_DIV] = imx_clk_divider2("ahb_root_clk", 
"ahb_pre_div", base + 0x9000, 0, 6);
+   clks[IMX7D_AHB_CHANNEL_ROOT_CLK] = 
imx_clk_divider_flags("ahb_root_clk", "ahb_pre_div", base + 0x9000, 0, 6, 
CLK_OPS_PARENT_ENABLE);
clks[IMX7D_IPG_

[PATCH 2/4] arm: imx: Correct dram pll type

2018-03-22 Thread Abel Vesa
From: Anson Huang 

DRAM PLL is a audio/video type PLL, need to correct it to get correct ops of
PLL.

There is a test_div placed before DRAM PLL's gate, so add this test div clk.

Signed-off-by: Anson Huang 
Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/clk-imx7d.c | 97 -
 1 file changed, 52 insertions(+), 45 deletions(-)

diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c
index 80dc211..d786f98 100644
--- a/drivers/clk/imx/clk-imx7d.c
+++ b/drivers/clk/imx/clk-imx7d.c
@@ -51,20 +51,20 @@ static const char *arm_a7_sel[] = { "osc", 
"pll_arm_main_clk",
 
 static const char *arm_m4_sel[] = { "osc", "pll_sys_main_240m_clk",
"pll_enet_250m_clk", "pll_sys_pfd2_270m_clk",
-   "pll_dram_533m_clk", "pll_audio_post_div", "pll_video_main_clk",
+   "pll_dram_533m_clk", "pll_audio_post_div", "pll_video_post_div",
"pll_usb_main_clk", };
 
 static const char *axi_sel[] = { "osc", "pll_sys_pfd1_332m_clk",
"pll_dram_533m_clk", "pll_enet_250m_clk", "pll_sys_pfd5_clk",
-   "pll_audio_post_div", "pll_video_main_clk", "pll_sys_pfd7_clk", };
+   "pll_audio_post_div", "pll_video_post_div", "pll_sys_pfd7_clk", };
 
 static const char *disp_axi_sel[] = { "osc", "pll_sys_pfd1_332m_clk",
"pll_dram_533m_clk", "pll_enet_250m_clk", "pll_sys_pfd6_clk",
-   "pll_sys_pfd7_clk", "pll_audio_post_div", "pll_video_main_clk", };
+   "pll_sys_pfd7_clk", "pll_audio_post_div", "pll_video_post_div", };
 
 static const char *enet_axi_sel[] = { "osc", "pll_sys_pfd2_270m_clk",
"pll_dram_533m_clk", "pll_enet_250m_clk",
-   "pll_sys_main_240m_clk", "pll_audio_post_div", "pll_video_main_clk",
+   "pll_sys_main_240m_clk", "pll_audio_post_div", "pll_video_post_div",
"pll_sys_pfd4_clk", };
 
 static const char *nand_usdhc_bus_sel[] = { "osc", "pll_sys_pfd2_270m_clk",
@@ -75,7 +75,7 @@ static const char *nand_usdhc_bus_sel[] = { "osc", 
"pll_sys_pfd2_270m_clk",
 static const char *ahb_channel_sel[] = { "osc", "pll_sys_pfd2_270m_clk",
"pll_dram_533m_clk", "pll_sys_pfd0_392m_clk",
"pll_enet_125m_clk", "pll_usb_main_clk", "pll_audio_post_div",
-   "pll_video_main_clk", };
+   "pll_video_post_div", };
 
 static const char *dram_phym_sel[] = { "pll_dram_main_clk",
"dram_phym_alt_clk", };
@@ -86,7 +86,7 @@ static const char *dram_sel[] = { "pll_dram_main_clk",
 static const char *dram_phym_alt_sel[] = { "osc", "pll_dram_533m_clk",
"pll_sys_main_clk", "pll_enet_500m_clk",
"pll_usb_main_clk", "pll_sys_pfd7_clk", "pll_audio_post_div",
-   "pll_video_main_clk", };
+   "pll_video_post_div", };
 
 static const char *dram_alt_sel[] = { "osc", "pll_dram_533m_clk",
"pll_sys_main_clk", "pll_enet_500m_clk",
@@ -108,62 +108,62 @@ static const char *pcie_phy_sel[] = { "osc", 
"pll_enet_100m_clk",
 
 static const char *epdc_pixel_sel[] = { "osc", "pll_sys_pfd1_332m_clk",
"pll_dram_533m_clk", "pll_sys_main_clk", "pll_sys_pfd5_clk",
-   "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", "pll_video_main_clk", };
+   "pll_sys_pfd6_clk", "pll_sys_pfd7_clk", "pll_video_post_div", };
 
 static const char *lcdif_pixel_sel[] = { "osc", "pll_sys_pfd5_clk",
"pll_dram_533m_clk", "ext_clk_3", "pll_sys_pfd4_clk",
-   "pll_sys_pfd2_270m_clk", "pll_video_main_clk",
+   "pll_sys_pfd2_270m_clk", "pll_video_post_div",
"pll_usb_main_clk", };
 
 static const char *mipi_dsi_sel[] = { "osc", "pll_sys_pfd5_clk",
"pll_sys_pfd3_clk", "pll_sys_main_clk", "pll_sys_pfd0_196m_clk",
-   "pll_dram_533m_clk", "pll_video_main_clk", "pll_audio_post_div", };
+   "pll_dram_533m_clk", "pll_video_post_div", "pll_audio_post_div", };
 
 static const char *mipi_csi_sel[] = { "osc", "pll_sys_pfd4_clk",
"pll_sys_pfd3_clk", "pll_sys

Re: [PATCH 2/4] arm: imx: Correct dram pll type

2018-03-22 Thread Abel Vesa
Hi Fabio,

On Thu, Mar 22, 2018 at 09:31:03AM -0300, Fabio Estevam wrote:
> 
> This has already been applied in linux-next as commit:
> 
> commit b716aad97eb5 ("clk: imx: imx7d: correct video pll clock tree)

OK. Will create the patchset again without this one.

> 
> Nit: the prefix in the Subject lines of all these patches should not
> be "arm:imx".
> 
> "clk: imx: imx7d" is better suited to reflect the subsystem that thes
> patches touch.

Will change this too.

Which repo/branch should this patchset be created against ?

-- 

Return checks for clock calls

2018-03-23 Thread Abel Vesa
Hi Shawn, Fabio,

I'm trying to get the imx clks changes upstreamed. To that end, I reached this
old commit that adds some wrappers over the generic clk API. Here is the commit
message:

ARM: imx6: add return check for clock calls

There are a bunch of clk_enable_prepare, clk_set_parent and clk_set_rate
calls in imx6 clock driver's initialization.  They are called without
retunr check.  If there is something going wrong with the calls, they
will just fail silently.

The patch creates a set of helper functions imx_clk_enable_prepare,
imx_clk_set_parent and imx_clk_set_rate, and use them instead from clock
initialization to check the return and print error message to tell
failures if any.

Signed-off-by: Shawn Guo 

And it adds the imx_clk_set_parent, imx_clk_prepare_enable and
imx_clk_set_rate which basically just print an error message if the generic
functions have failed.

The only plus of these wrappers is that we at least see that the generic
functions have failed, but the behaviour is not changed in any way.

Question is, do we want this upstreamed considering that we need to replace the
calls throughout all the older imx socs ?

Abel

[PATCH] clk: imx: Set CLK_SET_RATE_GATE for gate and divider clocks

2018-03-23 Thread Abel Vesa
Add flag CLK_SET_RATE_GATE for i.MX gate and divider clocks on which the
client drivers usually make clk_set_rate() call, so that the call will fail
when clock is still on instead of standing the risk of running into glitch
issue. Rate cannot be changed when the clock is enabled due to the glitchy
multiplexers.

Signed-off-by: Shawn Guo 
[initial patch from imx internal repo]
Signed-off-by: Abel Vesa 
[carried over from 3.14 and also applied the flag to newer functions]
---
 drivers/clk/imx/clk.h | 15 +--
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index d69c4bb..4411719 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -96,7 +96,8 @@ static inline struct clk *imx_clk_fixed_factor(const char 
*name,
 static inline struct clk *imx_clk_divider(const char *name, const char *parent,
void __iomem *reg, u8 shift, u8 width)
 {
-   return clk_register_divider(NULL, name, parent, CLK_SET_RATE_PARENT,
+   return clk_register_divider(NULL, name, parent,
+   CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE,
reg, shift, width, 0, &imx_ccm_lock);
 }
 
@@ -133,7 +134,8 @@ static inline struct clk *imx_clk_gate_dis(const char 
*name, const char *parent,
 static inline struct clk *imx_clk_gate2(const char *name, const char *parent,
void __iomem *reg, u8 shift)
 {
-   return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
+   return clk_register_gate2(NULL, name, parent,
+   CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, reg,
shift, 0x3, 0, &imx_ccm_lock, NULL);
 }
 
@@ -141,7 +143,8 @@ static inline struct clk *imx_clk_gate2_shared(const char 
*name,
const char *parent, void __iomem *reg, u8 shift,
unsigned int *share_count)
 {
-   return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
+   return clk_register_gate2(NULL, name, parent,
+   CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, reg,
shift, 0x3, 0, &imx_ccm_lock, share_count);
 }
 
@@ -150,8 +153,8 @@ static inline struct clk *imx_clk_gate2_shared2(const char 
*name,
unsigned int *share_count)
 {
return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT |
- CLK_OPS_PARENT_ENABLE, reg, shift, 0x3, 0,
- &imx_ccm_lock, share_count);
+   CLK_SET_RATE_GATE | CLK_OPS_PARENT_ENABLE,
+   reg, shift, 0x3, 0, &imx_ccm_lock, share_count);
 }
 
 static inline struct clk *imx_clk_gate2_cgr(const char *name,
@@ -173,7 +176,7 @@ static inline struct clk *imx_clk_gate4(const char *name, 
const char *parent,
void __iomem *reg, u8 shift)
 {
return clk_register_gate2(NULL, name, parent,
-   CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+   CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE | CLK_OPS_PARENT_ENABLE,
reg, shift, 0x3, 0, &imx_ccm_lock, NULL);
 }
 
-- 
2.7.4



[PATCH v14 0/5] Add i.MX8MQ clock driver

2018-11-29 Thread Abel Vesa
Here is a link to the 13th version:
https://lkml.org/lkml/2018/11/13/1020

Changes since v13:
 * included changes suggested by Stephen Boyd

Abel Vesa (2):
  clk: imx: Add imx composite clock
  clk: imx: Add clock driver for i.MX8MQ CCM

Lucas Stach (3):
  dt-bindings: Add binding for i.MX8MQ CCM
  clk: imx: Add fractional PLL output clock
  clk: imx: Add SCCG PLL type

 .../devicetree/bindings/clock/imx8mq-clock.txt |  20 +
 drivers/clk/imx/Makefile   |   6 +-
 drivers/clk/imx/clk-composite-8m.c | 178 +++
 drivers/clk/imx/clk-frac-pll.c | 223 
 drivers/clk/imx/clk-imx8mq.c   | 589 +
 drivers/clk/imx/clk-sccg-pll.c | 256 +
 drivers/clk/imx/clk.h  |  64 +++
 include/dt-bindings/clock/imx8mq-clock.h   | 395 ++
 8 files changed, 1730 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/imx8mq-clock.txt
 create mode 100644 drivers/clk/imx/clk-composite-8m.c
 create mode 100644 drivers/clk/imx/clk-frac-pll.c
 create mode 100644 drivers/clk/imx/clk-imx8mq.c
 create mode 100644 drivers/clk/imx/clk-sccg-pll.c
 create mode 100644 include/dt-bindings/clock/imx8mq-clock.h

-- 
2.7.4



[PATCH v14 2/5] clk: imx: Add fractional PLL output clock

2018-11-29 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 | 223 +
 drivers/clk/imx/clk.h  |   3 +
 3 files changed, 227 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..9872620
--- /dev/null
+++ b/drivers/clk/imx/clk-frac-pll.c
@@ -0,0 +1,223 @@
+// 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 
+
+#include "clk.h"
+
+#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);
+   do_div(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;
+}
+
+/*
+

[PATCH v14 5/5] clk: imx: Add clock driver for i.MX8MQ CCM

2018-11-29 Thread Abel Vesa
Add driver for the Clock Control Module found on i.MX8MQ.

Signed-off-by: Anson Huang 
Signed-off-by: Bai Ping 
Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
Reviewed-by: Sascha Hauer 
---
 drivers/clk/imx/Makefile |   1 +
 drivers/clk/imx/clk-imx8mq.c | 589 +++
 drivers/clk/imx/clk.h|  36 +++
 3 files changed, 626 insertions(+)
 create mode 100644 drivers/clk/imx/clk-imx8mq.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 237444b..6952f05 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -29,4 +29,5 @@ obj-$(CONFIG_SOC_IMX6SLL) += clk-imx6sll.o
 obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o
 obj-$(CONFIG_SOC_IMX6UL) += clk-imx6ul.o
 obj-$(CONFIG_SOC_IMX7D)  += clk-imx7d.o
+obj-$(CONFIG_SOC_IMX8MQ) += clk-imx8mq.o
 obj-$(CONFIG_SOC_VF610)  += clk-vf610.o
diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c
new file mode 100644
index 000..26b57f4
--- /dev/null
+++ b/drivers/clk/imx/clk-imx8mq.c
@@ -0,0 +1,589 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 NXP.
+ * Copyright (C) 2017 Pengutronix, Lucas Stach 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+static u32 share_count_sai1;
+static u32 share_count_sai2;
+static u32 share_count_sai3;
+static u32 share_count_sai4;
+static u32 share_count_sai5;
+static u32 share_count_sai6;
+static u32 share_count_dcss;
+static u32 share_count_nand;
+
+static struct clk *clks[IMX8MQ_CLK_END];
+
+static const char *pll_ref_sels[] = { "osc_25m", "osc_27m", "dummy", "dummy", 
};
+static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
+static const char *gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
+static const char *vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", };
+static const char *audio_pll1_bypass_sels[] = {"audio_pll1", 
"audio_pll1_ref_sel", };
+static const char *audio_pll2_bypass_sels[] = {"audio_pll2", 
"audio_pll2_ref_sel", };
+static const char *video_pll1_bypass_sels[] = {"video_pll1", 
"video_pll1_ref_sel", };
+
+static const char *sys1_pll1_out_sels[] = {"sys1_pll1", "sys1_pll1_ref_sel", };
+static const char *sys2_pll1_out_sels[] = {"sys2_pll1", "sys1_pll1_ref_sel", };
+static const char *sys3_pll1_out_sels[] = {"sys3_pll1", "sys3_pll1_ref_sel", };
+static const char *dram_pll1_out_sels[] = {"dram_pll1", "dram_pll1_ref_sel", };
+
+static const char *sys1_pll2_out_sels[] = {"sys1_pll2_div", 
"sys1_pll1_ref_sel", };
+static const char *sys2_pll2_out_sels[] = {"sys2_pll2_div", 
"sys2_pll1_ref_sel", };
+static const char *sys3_pll2_out_sels[] = {"sys3_pll2_div", 
"sys2_pll1_ref_sel", };
+static const char *dram_pll2_out_sels[] = {"dram_pll2_div", 
"dram_pll1_ref_sel", };
+
+/* CCM ROOT */
+static const char *imx8mq_a53_sels[] = {"osc_25m", "arm_pll_out", 
"sys2_pll_500m", "sys2_pll_1000m",
+   "sys1_pll_800m", "sys1_pll_400m", 
"audio_pll1_out", "sys3_pll2_out", };
+
+static const char *imx8mq_vpu_sels[] = {"osc_25m", "arm_pll_out", 
"sys2_pll_500m", "sys2_pll_1000m",
+   "sys1_pll_800m", "sys1_pll_400m", 
"audio_pll1_out", "vpu_pll_out", };
+
+static const char *imx8mq_gpu_core_sels[] = {"osc_25m", "gpu_pll_out", 
"sys1_pll_800m", "sys3_pll2_out",
+"sys2_pll_1000m", 
"audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mq_gpu_shader_sels[] = {"osc_25m", "gpu_pll_out", 
"sys1_pll_800m", "sys3_pll2_out",
+  "sys2_pll_1000m", 
"audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mq_main_axi_sels[] = {"osc_25m", "sys2_pll_333m", 
"sys1_pll_800m", "sys2_pll_250m",
+"sys2_pll_1000m", 
"audio_pll1_out", "video_pll1_out", "sys1_pll_100m",};
+
+static const char *imx8mq_enet_axi_sels[] = {"osc_25m", "sys1_pll_266m", 
"sys1_pll_800m", "sys2_pll_250m",
+"sys2_pll_200m", "audio_pll1_out", 
"video_pll1_out", "sys3_pll2_out&q

[PATCH v14 1/5] dt-bindings: Add binding for i.MX8MQ CCM

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

This adds the binding for the i.MX8MQ Clock Controller Module.

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
Reviewed-by: Rob Herring 
---
 .../devicetree/bindings/clock/imx8mq-clock.txt |  20 ++
 include/dt-bindings/clock/imx8mq-clock.h   | 395 +
 2 files changed, 415 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/imx8mq-clock.txt
 create mode 100644 include/dt-bindings/clock/imx8mq-clock.h

diff --git a/Documentation/devicetree/bindings/clock/imx8mq-clock.txt 
b/Documentation/devicetree/bindings/clock/imx8mq-clock.txt
new file mode 100644
index 000..52de826
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/imx8mq-clock.txt
@@ -0,0 +1,20 @@
+* Clock bindings for NXP i.MX8M Quad
+
+Required properties:
+- compatible: Should be "fsl,imx8mq-ccm"
+- reg: Address and length of the register set
+- #clock-cells: Should be <1>
+- clocks: list of clock specifiers, must contain an entry for each required
+  entry in clock-names
+- clock-names: should include the following entries:
+- "ckil"
+- "osc_25m"
+- "osc_27m"
+- "clk_ext1"
+- "clk_ext2"
+- "clk_ext3"
+- "clk_ext4"
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell.  See include/dt-bindings/clock/imx8mq-clock.h
+for the full list of i.MX8M Quad clock IDs.
diff --git a/include/dt-bindings/clock/imx8mq-clock.h 
b/include/dt-bindings/clock/imx8mq-clock.h
new file mode 100644
index 000..b53be41
--- /dev/null
+++ b/include/dt-bindings/clock/imx8mq-clock.h
@@ -0,0 +1,395 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_IMX8MQ_H
+#define __DT_BINDINGS_CLOCK_IMX8MQ_H
+
+#define IMX8MQ_CLK_DUMMY   0
+#define IMX8MQ_CLK_32K 1
+#define IMX8MQ_CLK_25M 2
+#define IMX8MQ_CLK_27M 3
+#define IMX8MQ_CLK_EXT14
+#define IMX8MQ_CLK_EXT25
+#define IMX8MQ_CLK_EXT36
+#define IMX8MQ_CLK_EXT47
+
+/* ANAMIX PLL clocks */
+/* FRAC PLLs */
+/* ARM PLL */
+#define IMX8MQ_ARM_PLL_REF_SEL 8
+#define IMX8MQ_ARM_PLL_REF_DIV 9
+#define IMX8MQ_ARM_PLL 10
+#define IMX8MQ_ARM_PLL_BYPASS  11
+#define IMX8MQ_ARM_PLL_OUT 12
+
+/* GPU PLL */
+#define IMX8MQ_GPU_PLL_REF_SEL 13
+#define IMX8MQ_GPU_PLL_REF_DIV 14
+#define IMX8MQ_GPU_PLL 15
+#define IMX8MQ_GPU_PLL_BYPASS  16
+#define IMX8MQ_GPU_PLL_OUT 17
+
+/* VPU PLL */
+#define IMX8MQ_VPU_PLL_REF_SEL 18
+#define IMX8MQ_VPU_PLL_REF_DIV 19
+#define IMX8MQ_VPU_PLL 20
+#define IMX8MQ_VPU_PLL_BYPASS  21
+#define IMX8MQ_VPU_PLL_OUT 22
+
+/* AUDIO PLL1 */
+#define IMX8MQ_AUDIO_PLL1_REF_SEL  23
+#define IMX8MQ_AUDIO_PLL1_REF_DIV  24
+#define IMX8MQ_AUDIO_PLL1  25
+#define IMX8MQ_AUDIO_PLL1_BYPASS   26
+#define IMX8MQ_AUDIO_PLL1_OUT  27
+
+/* AUDIO PLL2 */
+#define IMX8MQ_AUDIO_PLL2_REF_SEL  28
+#define IMX8MQ_AUDIO_PLL2_REF_DIV  29
+#define IMX8MQ_AUDIO_PLL2  30
+#define IMX8MQ_AUDIO_PLL2_BYPASS   31
+#define IMX8MQ_AUDIO_PLL2_OUT  32
+
+/* VIDEO PLL1 */
+#define IMX8MQ_VIDEO_PLL1_REF_SEL  33
+#define IMX8MQ_VIDEO_PLL1_REF_DIV  34
+#define IMX8MQ_VIDEO_PLL1  35
+#define IMX8MQ_VIDEO_PLL1_BYPASS   36
+#define IMX8MQ_VIDEO_PLL1_OUT  37
+
+/* SYS1 PLL */
+#define IMX8MQ_SYS1_PLL1_REF_SEL   38
+#define IMX8MQ_SYS1_PLL1_REF_DIV   39
+#define IMX8MQ_SYS1_PLL1   40
+#define IMX8MQ_SYS1_PLL1_OUT   41
+#define IMX8MQ_SYS1_PLL1_OUT_DIV   42
+#define IMX8MQ_SYS1_PLL2   43
+#define IMX8MQ_SYS1_PLL2_DIV   44
+#define IMX8MQ_SYS1_PLL2_OUT   45
+
+/* SYS2 PLL */
+#define IMX8MQ_SYS2_PLL1_REF_SEL   46
+#define IMX8MQ_SYS2_PLL1_REF_DIV   47
+#define IMX8MQ_SYS2_PLL1   48
+#define IMX8MQ_SYS2_PLL1_OUT   49
+#define IMX8MQ_SYS2_PLL1_OUT_DIV   50
+#define IMX8MQ_SYS2_PLL2   51
+#define IMX8MQ_SYS2_PLL2_DIV   52
+#define IMX8MQ_SYS2_PLL2_OUT   53
+
+/* SYS3 PLL */
+#define IMX8MQ_SYS3_PLL1_REF_SEL   54
+#define IMX8MQ_SYS3_PLL1_REF_DIV   55
+#define IMX8MQ_SYS3_PLL1   56
+#define IMX8MQ_SYS3_PLL1_OUT   57
+#define IMX8MQ_SYS3_PLL1_OUT_DIV   58
+#define IMX8MQ_SYS3_PLL2   59
+#define IMX8MQ_SYS3_PLL2_DIV   60
+#define IMX8MQ_SYS3_PLL2_OUT   61
+
+/* DRAM PLL */
+#define IMX8MQ_DRAM_PLL1_REF_SEL   62
+#define IMX8MQ_DRAM_PLL1_REF_DIV   63
+#define IMX8MQ_DRAM_PLL1   64
+#define IMX8MQ

[PATCH v14 3/5] clk: imx: Add SCCG PLL type

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

The SCCG is a new PLL type introduced on i.MX8.

The description of this SCCG 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   |   3 +-
 drivers/clk/imx/clk-sccg-pll.c | 256 +
 drivers/clk/imx/clk.h  |   9 ++
 3 files changed, 267 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/imx/clk-sccg-pll.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 4893c1f..b87513c 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -12,7 +12,8 @@ obj-y += \
clk-pllv1.o \
clk-pllv2.o \
clk-pllv3.o \
-   clk-pfd.o
+   clk-pfd.o \
+   clk-sccg-pll.o
 
 obj-$(CONFIG_SOC_IMX1)   += clk-imx1.o
 obj-$(CONFIG_SOC_IMX21)  += clk-imx21.o
diff --git a/drivers/clk/imx/clk-sccg-pll.c b/drivers/clk/imx/clk-sccg-pll.c
new file mode 100644
index 000..ee7752b
--- /dev/null
+++ b/drivers/clk/imx/clk-sccg-pll.c
@@ -0,0 +1,256 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2018 NXP.
+ *
+ * This driver supports the SCCG plls found in the imx8m SOCs
+ *
+ * Documentation for this SCCG pll can be found at:
+ *   https://www.nxp.com/docs/en/reference-manual/IMX8MDQLQRM.pdf#page=834
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+/* PLL CFGs */
+#define PLL_CFG0   0x0
+#define PLL_CFG1   0x4
+#define PLL_CFG2   0x8
+
+#define PLL_DIVF1_MASK GENMASK(18, 13)
+#define PLL_DIVF2_MASK GENMASK(12, 7)
+#define PLL_DIVR1_MASK GENMASK(27, 25)
+#define PLL_DIVR2_MASK GENMASK(24, 19)
+#define PLL_REF_MASK   GENMASK(2, 0)
+
+#define PLL_LOCK_MASK  BIT(31)
+#define PLL_PD_MASKBIT(7)
+
+#define OSC_25M2500
+#define OSC_27M2700
+
+#define PLL_SCCG_LOCK_TIMEOUT  70
+
+struct clk_sccg_pll {
+   struct clk_hw   hw;
+   void __iomem*base;
+};
+
+#define to_clk_sccg_pll(_hw) container_of(_hw, struct clk_sccg_pll, hw)
+
+static int clk_pll_wait_lock(struct clk_sccg_pll *pll)
+{
+   u32 val;
+
+   return readl_poll_timeout(pll->base, val, val & PLL_LOCK_MASK, 0,
+   PLL_SCCG_LOCK_TIMEOUT);
+}
+
+static int clk_pll1_is_prepared(struct clk_hw *hw)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   return (val & PLL_PD_MASK) ? 0 : 1;
+}
+
+static unsigned long clk_pll1_recalc_rate(struct clk_hw *hw,
+unsigned long parent_rate)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val, divf;
+
+   val = readl_relaxed(pll->base + PLL_CFG2);
+   divf = FIELD_GET(PLL_DIVF1_MASK, val);
+
+   return parent_rate * 2 * (divf + 1);
+}
+
+static long clk_pll1_round_rate(struct clk_hw *hw, unsigned long rate,
+  unsigned long *prate)
+{
+   unsigned long parent_rate = *prate;
+   u32 div;
+
+   if (!parent_rate)
+   return 0;
+
+   div = rate / (parent_rate * 2);
+
+   return parent_rate * div * 2;
+}
+
+static int clk_pll1_set_rate(struct clk_hw *hw, unsigned long rate,
+   unsigned long parent_rate)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+   u32 divf;
+
+   if (!parent_rate)
+   return -EINVAL;
+
+   divf = rate / (parent_rate * 2);
+
+   val = readl_relaxed(pll->base + PLL_CFG2);
+   val &= ~PLL_DIVF1_MASK;
+   val |= FIELD_PREP(PLL_DIVF1_MASK, divf - 1);
+   writel_relaxed(val, pll->base + PLL_CFG2);
+
+   return clk_pll_wait_lock(pll);
+}
+
+static int clk_pll1_prepare(struct clk_hw *hw)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   val &= ~PLL_PD_MASK;
+   writel_relaxed(val, pll->base + PLL_CFG0);
+
+   return clk_pll_wait_lock(pll);
+}
+
+static void clk_pll1_unprepare(struct clk_hw *hw)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   val |= PLL_PD_MASK;
+   writel_relaxed(val, pll->base + PLL_CFG0);
+
+}
+
+static unsigned long clk_pll2_recalc_rate(struct clk_hw *hw,
+unsigned long parent_rate)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val, ref, divr1, divf1, divr2, divf2;
+   u64 temp64;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   switch (FIELD_GET(PLL_REF_MASK, val)) {
+   case 0:
+   ref = OSC_25M;
+   

[PATCH v14 4/5] clk: imx: Add imx composite clock

2018-11-29 Thread Abel Vesa
Since a lot of clocks on imx8m are formed by a mux, gate, predivider and
divider, the idea here is to combine all of those into one composite clock,
but we need to deal with both predivider and divider at the same time and
therefore we add the imx8m_clk_composite_divider_ops and register
the composite clock with those.

Signed-off-by: Abel Vesa 
Suggested-by: Sascha Hauer 
Reviewed-by: Sascha Hauer 
---
 drivers/clk/imx/Makefile   |   1 +
 drivers/clk/imx/clk-composite-8m.c | 178 +
 drivers/clk/imx/clk.h  |  16 
 3 files changed, 195 insertions(+)
 create mode 100644 drivers/clk/imx/clk-composite-8m.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index b87513c..237444b 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -3,6 +3,7 @@
 obj-y += \
clk.o \
clk-busy.o \
+   clk-composite-8m.o \
clk-cpu.o \
clk-fixup-div.o \
clk-fixup-mux.o \
diff --git a/drivers/clk/imx/clk-composite-8m.c 
b/drivers/clk/imx/clk-composite-8m.c
new file mode 100644
index 000..6d9d371
--- /dev/null
+++ b/drivers/clk/imx/clk-composite-8m.c
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 NXP
+ */
+
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+#define PCG_PREDIV_SHIFT   16
+#define PCG_PREDIV_WIDTH   3
+#define PCG_PREDIV_MAX 8
+
+#define PCG_DIV_SHIFT  0
+#define PCG_DIV_WIDTH  6
+#define PCG_DIV_MAX64
+
+#define PCG_PCS_SHIFT  24
+#define PCG_PCS_MASK   0x7
+
+#define PCG_CGC_SHIFT  28
+
+static unsigned long imx8m_clk_composite_divider_recalc_rate(struct clk_hw *hw,
+   unsigned long parent_rate)
+{
+   struct clk_divider *divider = to_clk_divider(hw);
+   unsigned long prediv_rate;
+   unsigned int prediv_value;
+   unsigned int div_value;
+
+   prediv_value = readl(divider->reg) >> divider->shift;
+   prediv_value &= clk_div_mask(divider->width);
+
+   prediv_rate = divider_recalc_rate(hw, parent_rate, prediv_value,
+   NULL, divider->flags,
+   divider->width);
+
+   div_value = readl(divider->reg) >> PCG_DIV_SHIFT;
+   div_value &= clk_div_mask(PCG_DIV_WIDTH);
+
+   return divider_recalc_rate(hw, prediv_rate, div_value, NULL,
+  divider->flags, PCG_DIV_WIDTH);
+}
+
+static int imx8m_clk_composite_compute_dividers(unsigned long rate,
+   unsigned long parent_rate,
+   int *prediv, int *postdiv)
+{
+   int div1, div2;
+   int error = INT_MAX;
+   int ret = -EINVAL;
+
+   *prediv = 1;
+   *postdiv = 1;
+
+   for (div1 = 1; div1 <= PCG_PREDIV_MAX; div1++) {
+   for (div2 = 1; div2 <= PCG_DIV_MAX; div2++) {
+   int new_error = ((parent_rate / div1) / div2) - rate;
+
+   if (abs(new_error) < abs(error)) {
+   *prediv = div1;
+   *postdiv = div2;
+   error = new_error;
+   ret = 0;
+   }
+   }
+   }
+   return ret;
+}
+
+static long imx8m_clk_composite_divider_round_rate(struct clk_hw *hw,
+   unsigned long rate,
+   unsigned long *prate)
+{
+   int prediv_value;
+   int div_value;
+
+   imx8m_clk_composite_compute_dividers(rate, *prate,
+   &prediv_value, &div_value);
+   rate = DIV_ROUND_UP(*prate, prediv_value);
+
+   return DIV_ROUND_UP(rate, div_value);
+
+}
+
+static int imx8m_clk_composite_divider_set_rate(struct clk_hw *hw,
+   unsigned long rate,
+   unsigned long parent_rate)
+{
+   struct clk_divider *divider = to_clk_divider(hw);
+   unsigned long flags = 0;
+   int prediv_value;
+   int div_value;
+   int ret = 0;
+   u32 val;
+
+   ret = imx8m_clk_composite_compute_dividers(rate, parent_rate,
+   &prediv_value, &div_value);
+   if (ret)
+   return -EINVAL;
+
+   spin_lock_irqsave(divider->lock, flags);
+
+   val = readl(divider->reg);
+   val &= ~((clk_div_mask(divider->width) << divider->shift) |
+   (clk_div_mask(PCG_DIV_WIDTH) << PCG_DIV_SHIFT));
+
+   val |= (u32)(prediv_value  - 1) << divider->shift;
+   val |= (u32)(div_value - 1) << PCG_DIV_SHIFT;
+   writel(val, divider

[PATCH] clk: imx: Use do_div in SCCG due to 64-bit divisor

2018-11-29 Thread Abel Vesa
On arm32, a division with a 64-bit divisor has to be done through
do_div() function otherwise there is a link failure like:

drivers/clk/imx/clk-frac-pll.o: In function `clk_pll_round_rate':
clk-frac-pll.c:(.text+0x54): undefined reference to `__aeabi_uldivmod'
make: *** [Makefile:1040: vmlinux] Error 1

Fixes: 9fd680d0fafd ("clk: imx: add fractional PLL output clock")
Signed-off-by: Abel Vesa 
Reported-by: Stephen Rothwell 
---
 drivers/clk/imx/clk-frac-pll.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/imx/clk-frac-pll.c b/drivers/clk/imx/clk-frac-pll.c
index 9872620..8b13df9 100644
--- a/drivers/clk/imx/clk-frac-pll.c
+++ b/drivers/clk/imx/clk-frac-pll.c
@@ -116,12 +116,13 @@ 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;
+   u64 divff, divfi;
+   u64 temp64 = rate;
 
parent_rate *= 8;
rate *= 2;
-   divfi = rate / parent_rate;
+   do_div(temp64, parent_rate);
+   divfi = temp64;
temp64 = rate - divfi * parent_rate;
temp64 *= PLL_FRAC_DENOM;
do_div(temp64, parent_rate);
-- 
2.7.4



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

2018-11-13 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..a3732be
--- /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);
+   do_div(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 calcu

[PATCH v13 1/5] dt-bindings: add binding for i.MX8MQ CCM

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

This adds the binding for the i.MX8MQ Clock Controller Module.

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
Reviewed-by: Rob Herring 
---
 .../devicetree/bindings/clock/imx8mq-clock.txt |  20 ++
 include/dt-bindings/clock/imx8mq-clock.h   | 395 +
 2 files changed, 415 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/imx8mq-clock.txt
 create mode 100644 include/dt-bindings/clock/imx8mq-clock.h

diff --git a/Documentation/devicetree/bindings/clock/imx8mq-clock.txt 
b/Documentation/devicetree/bindings/clock/imx8mq-clock.txt
new file mode 100644
index 000..52de826
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/imx8mq-clock.txt
@@ -0,0 +1,20 @@
+* Clock bindings for NXP i.MX8M Quad
+
+Required properties:
+- compatible: Should be "fsl,imx8mq-ccm"
+- reg: Address and length of the register set
+- #clock-cells: Should be <1>
+- clocks: list of clock specifiers, must contain an entry for each required
+  entry in clock-names
+- clock-names: should include the following entries:
+- "ckil"
+- "osc_25m"
+- "osc_27m"
+- "clk_ext1"
+- "clk_ext2"
+- "clk_ext3"
+- "clk_ext4"
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell.  See include/dt-bindings/clock/imx8mq-clock.h
+for the full list of i.MX8M Quad clock IDs.
diff --git a/include/dt-bindings/clock/imx8mq-clock.h 
b/include/dt-bindings/clock/imx8mq-clock.h
new file mode 100644
index 000..b53be41
--- /dev/null
+++ b/include/dt-bindings/clock/imx8mq-clock.h
@@ -0,0 +1,395 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_IMX8MQ_H
+#define __DT_BINDINGS_CLOCK_IMX8MQ_H
+
+#define IMX8MQ_CLK_DUMMY   0
+#define IMX8MQ_CLK_32K 1
+#define IMX8MQ_CLK_25M 2
+#define IMX8MQ_CLK_27M 3
+#define IMX8MQ_CLK_EXT14
+#define IMX8MQ_CLK_EXT25
+#define IMX8MQ_CLK_EXT36
+#define IMX8MQ_CLK_EXT47
+
+/* ANAMIX PLL clocks */
+/* FRAC PLLs */
+/* ARM PLL */
+#define IMX8MQ_ARM_PLL_REF_SEL 8
+#define IMX8MQ_ARM_PLL_REF_DIV 9
+#define IMX8MQ_ARM_PLL 10
+#define IMX8MQ_ARM_PLL_BYPASS  11
+#define IMX8MQ_ARM_PLL_OUT 12
+
+/* GPU PLL */
+#define IMX8MQ_GPU_PLL_REF_SEL 13
+#define IMX8MQ_GPU_PLL_REF_DIV 14
+#define IMX8MQ_GPU_PLL 15
+#define IMX8MQ_GPU_PLL_BYPASS  16
+#define IMX8MQ_GPU_PLL_OUT 17
+
+/* VPU PLL */
+#define IMX8MQ_VPU_PLL_REF_SEL 18
+#define IMX8MQ_VPU_PLL_REF_DIV 19
+#define IMX8MQ_VPU_PLL 20
+#define IMX8MQ_VPU_PLL_BYPASS  21
+#define IMX8MQ_VPU_PLL_OUT 22
+
+/* AUDIO PLL1 */
+#define IMX8MQ_AUDIO_PLL1_REF_SEL  23
+#define IMX8MQ_AUDIO_PLL1_REF_DIV  24
+#define IMX8MQ_AUDIO_PLL1  25
+#define IMX8MQ_AUDIO_PLL1_BYPASS   26
+#define IMX8MQ_AUDIO_PLL1_OUT  27
+
+/* AUDIO PLL2 */
+#define IMX8MQ_AUDIO_PLL2_REF_SEL  28
+#define IMX8MQ_AUDIO_PLL2_REF_DIV  29
+#define IMX8MQ_AUDIO_PLL2  30
+#define IMX8MQ_AUDIO_PLL2_BYPASS   31
+#define IMX8MQ_AUDIO_PLL2_OUT  32
+
+/* VIDEO PLL1 */
+#define IMX8MQ_VIDEO_PLL1_REF_SEL  33
+#define IMX8MQ_VIDEO_PLL1_REF_DIV  34
+#define IMX8MQ_VIDEO_PLL1  35
+#define IMX8MQ_VIDEO_PLL1_BYPASS   36
+#define IMX8MQ_VIDEO_PLL1_OUT  37
+
+/* SYS1 PLL */
+#define IMX8MQ_SYS1_PLL1_REF_SEL   38
+#define IMX8MQ_SYS1_PLL1_REF_DIV   39
+#define IMX8MQ_SYS1_PLL1   40
+#define IMX8MQ_SYS1_PLL1_OUT   41
+#define IMX8MQ_SYS1_PLL1_OUT_DIV   42
+#define IMX8MQ_SYS1_PLL2   43
+#define IMX8MQ_SYS1_PLL2_DIV   44
+#define IMX8MQ_SYS1_PLL2_OUT   45
+
+/* SYS2 PLL */
+#define IMX8MQ_SYS2_PLL1_REF_SEL   46
+#define IMX8MQ_SYS2_PLL1_REF_DIV   47
+#define IMX8MQ_SYS2_PLL1   48
+#define IMX8MQ_SYS2_PLL1_OUT   49
+#define IMX8MQ_SYS2_PLL1_OUT_DIV   50
+#define IMX8MQ_SYS2_PLL2   51
+#define IMX8MQ_SYS2_PLL2_DIV   52
+#define IMX8MQ_SYS2_PLL2_OUT   53
+
+/* SYS3 PLL */
+#define IMX8MQ_SYS3_PLL1_REF_SEL   54
+#define IMX8MQ_SYS3_PLL1_REF_DIV   55
+#define IMX8MQ_SYS3_PLL1   56
+#define IMX8MQ_SYS3_PLL1_OUT   57
+#define IMX8MQ_SYS3_PLL1_OUT_DIV   58
+#define IMX8MQ_SYS3_PLL2   59
+#define IMX8MQ_SYS3_PLL2_DIV   60
+#define IMX8MQ_SYS3_PLL2_OUT   61
+
+/* DRAM PLL */
+#define IMX8MQ_DRAM_PLL1_REF_SEL   62
+#define IMX8MQ_DRAM_PLL1_REF_DIV   63
+#define IMX8MQ_DRAM_PLL1   64
+#define IMX8MQ

[PATCH v13 0/5] Add i.MX8MQ clock driver

2018-11-13 Thread Abel Vesa
Here is a link to the 12th version:
https://lkml.org/lkml/2018/11/7/642

Changes since v12:
 * replaced the division in clk_pll_recalc_rate in clk-frac
   with do_div as suggested by Stephen

Abel Vesa (2):
  clk: imx: Add imx composite clock
  clk: imx: Add clock driver for i.MX8MQ CCM

Lucas Stach (3):
  dt-bindings: add binding for i.MX8MQ CCM
  clk: imx: add fractional PLL output clock
  clk: imx: Add SCCG PLL type

 .../devicetree/bindings/clock/imx8mq-clock.txt |  20 +
 drivers/clk/imx/Makefile   |   6 +-
 drivers/clk/imx/clk-composite-8m.c | 178 +++
 drivers/clk/imx/clk-frac-pll.c | 221 
 drivers/clk/imx/clk-imx8mq.c   | 589 +
 drivers/clk/imx/clk-sccg-pll.c | 256 +
 drivers/clk/imx/clk.h  |  64 +++
 include/dt-bindings/clock/imx8mq-clock.h   | 395 ++
 8 files changed, 1728 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/imx8mq-clock.txt
 create mode 100644 drivers/clk/imx/clk-composite-8m.c
 create mode 100644 drivers/clk/imx/clk-frac-pll.c
 create mode 100644 drivers/clk/imx/clk-imx8mq.c
 create mode 100644 drivers/clk/imx/clk-sccg-pll.c
 create mode 100644 include/dt-bindings/clock/imx8mq-clock.h

-- 
2.7.4



[PATCH v13 3/5] clk: imx: Add SCCG PLL type

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

The SCCG is a new PLL type introduced on i.MX8.

The description of this SCCG 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   |   3 +-
 drivers/clk/imx/clk-sccg-pll.c | 256 +
 drivers/clk/imx/clk.h  |   9 ++
 3 files changed, 267 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/imx/clk-sccg-pll.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 4893c1f..b87513c 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -12,7 +12,8 @@ obj-y += \
clk-pllv1.o \
clk-pllv2.o \
clk-pllv3.o \
-   clk-pfd.o
+   clk-pfd.o \
+   clk-sccg-pll.o
 
 obj-$(CONFIG_SOC_IMX1)   += clk-imx1.o
 obj-$(CONFIG_SOC_IMX21)  += clk-imx21.o
diff --git a/drivers/clk/imx/clk-sccg-pll.c b/drivers/clk/imx/clk-sccg-pll.c
new file mode 100644
index 000..4666b96
--- /dev/null
+++ b/drivers/clk/imx/clk-sccg-pll.c
@@ -0,0 +1,256 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2018 NXP.
+ *
+ * This driver supports the SCCG plls found in the imx8m SOCs
+ *
+ * Documentation for this SCCG pll can be found at:
+ *   https://www.nxp.com/docs/en/reference-manual/IMX8MDQLQRM.pdf#page=834
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+/* PLL CFGs */
+#define PLL_CFG0   0x0
+#define PLL_CFG1   0x4
+#define PLL_CFG2   0x8
+
+#define PLL_DIVF1_MASK GENMASK(18, 13)
+#define PLL_DIVF2_MASK GENMASK(12, 7)
+#define PLL_DIVR1_MASK GENMASK(27, 25)
+#define PLL_DIVR2_MASK GENMASK(24, 19)
+#define PLL_REF_MASK   GENMASK(2, 0)
+
+#define PLL_LOCK_MASK  BIT(31)
+#define PLL_PD_MASKBIT(7)
+
+#define OSC_25M2500
+#define OSC_27M2700
+
+#define PLL_SCCG_LOCK_TIMEOUT  70
+
+struct clk_sccg_pll {
+   struct clk_hw   hw;
+   void __iomem*base;
+};
+
+#define to_clk_sccg_pll(_hw) container_of(_hw, struct clk_sccg_pll, hw)
+
+static int clk_pll_wait_lock(struct clk_sccg_pll *pll)
+{
+   u32 val;
+
+   return readl_poll_timeout(pll->base, val, val & PLL_LOCK_MASK, 0,
+   PLL_SCCG_LOCK_TIMEOUT);
+}
+
+static int clk_pll1_is_prepared(struct clk_hw *hw)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   return (val & PLL_PD_MASK) ? 0 : 1;
+}
+
+static unsigned long clk_pll1_recalc_rate(struct clk_hw *hw,
+unsigned long parent_rate)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val, divf;
+
+   val = readl_relaxed(pll->base + PLL_CFG2);
+   divf = FIELD_GET(PLL_DIVF1_MASK, val);
+
+   return parent_rate * 2 * (divf + 1);
+}
+
+static long clk_pll1_round_rate(struct clk_hw *hw, unsigned long rate,
+  unsigned long *prate)
+{
+   unsigned long parent_rate = *prate;
+   u32 div;
+
+   if (!parent_rate)
+   return 0;
+
+   div = rate / (parent_rate * 2);
+
+   return parent_rate * div * 2;
+}
+
+static int clk_pll1_set_rate(struct clk_hw *hw, unsigned long rate,
+   unsigned long parent_rate)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+   u32 divf;
+
+   if (!parent_rate)
+   return -EINVAL;
+
+   divf = rate / (parent_rate * 2);
+
+   val = readl_relaxed(pll->base + PLL_CFG2);
+   val &= ~PLL_DIVF1_MASK;
+   val |= FIELD_PREP(PLL_DIVF1_MASK, divf - 1);
+   writel_relaxed(val, pll->base + PLL_CFG2);
+
+   return clk_pll_wait_lock(pll);
+}
+
+static int clk_pll1_prepare(struct clk_hw *hw)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   val &= ~PLL_PD_MASK;
+   writel_relaxed(val, pll->base + PLL_CFG0);
+
+   return clk_pll_wait_lock(pll);
+}
+
+static void clk_pll1_unprepare(struct clk_hw *hw)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   val |= PLL_PD_MASK;
+   writel_relaxed(val, pll->base + PLL_CFG0);
+
+}
+
+static unsigned long clk_pll2_recalc_rate(struct clk_hw *hw,
+unsigned long parent_rate)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val, ref, divr1, divf1, divr2, divf2;
+   u64 temp64;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   switch (FIELD_GET(PLL_REF_MASK, val)) {
+   case 0:
+   ref = OSC_25M;
+   

[PATCH v13 5/5] clk: imx: Add clock driver for i.MX8MQ CCM

2018-11-13 Thread Abel Vesa
Add driver for the Clock Control Module found on i.MX8MQ.

Signed-off-by: Anson Huang 
Signed-off-by: Bai Ping 
Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
Reviewed-by: Sascha Hauer 
---
 drivers/clk/imx/Makefile |   1 +
 drivers/clk/imx/clk-imx8mq.c | 589 +++
 drivers/clk/imx/clk.h|  36 +++
 3 files changed, 626 insertions(+)
 create mode 100644 drivers/clk/imx/clk-imx8mq.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 237444b..6952f05 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -29,4 +29,5 @@ obj-$(CONFIG_SOC_IMX6SLL) += clk-imx6sll.o
 obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o
 obj-$(CONFIG_SOC_IMX6UL) += clk-imx6ul.o
 obj-$(CONFIG_SOC_IMX7D)  += clk-imx7d.o
+obj-$(CONFIG_SOC_IMX8MQ) += clk-imx8mq.o
 obj-$(CONFIG_SOC_VF610)  += clk-vf610.o
diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c
new file mode 100644
index 000..26b57f4
--- /dev/null
+++ b/drivers/clk/imx/clk-imx8mq.c
@@ -0,0 +1,589 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 NXP.
+ * Copyright (C) 2017 Pengutronix, Lucas Stach 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+static u32 share_count_sai1;
+static u32 share_count_sai2;
+static u32 share_count_sai3;
+static u32 share_count_sai4;
+static u32 share_count_sai5;
+static u32 share_count_sai6;
+static u32 share_count_dcss;
+static u32 share_count_nand;
+
+static struct clk *clks[IMX8MQ_CLK_END];
+
+static const char *pll_ref_sels[] = { "osc_25m", "osc_27m", "dummy", "dummy", 
};
+static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
+static const char *gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
+static const char *vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", };
+static const char *audio_pll1_bypass_sels[] = {"audio_pll1", 
"audio_pll1_ref_sel", };
+static const char *audio_pll2_bypass_sels[] = {"audio_pll2", 
"audio_pll2_ref_sel", };
+static const char *video_pll1_bypass_sels[] = {"video_pll1", 
"video_pll1_ref_sel", };
+
+static const char *sys1_pll1_out_sels[] = {"sys1_pll1", "sys1_pll1_ref_sel", };
+static const char *sys2_pll1_out_sels[] = {"sys2_pll1", "sys1_pll1_ref_sel", };
+static const char *sys3_pll1_out_sels[] = {"sys3_pll1", "sys3_pll1_ref_sel", };
+static const char *dram_pll1_out_sels[] = {"dram_pll1", "dram_pll1_ref_sel", };
+
+static const char *sys1_pll2_out_sels[] = {"sys1_pll2_div", 
"sys1_pll1_ref_sel", };
+static const char *sys2_pll2_out_sels[] = {"sys2_pll2_div", 
"sys2_pll1_ref_sel", };
+static const char *sys3_pll2_out_sels[] = {"sys3_pll2_div", 
"sys2_pll1_ref_sel", };
+static const char *dram_pll2_out_sels[] = {"dram_pll2_div", 
"dram_pll1_ref_sel", };
+
+/* CCM ROOT */
+static const char *imx8mq_a53_sels[] = {"osc_25m", "arm_pll_out", 
"sys2_pll_500m", "sys2_pll_1000m",
+   "sys1_pll_800m", "sys1_pll_400m", 
"audio_pll1_out", "sys3_pll2_out", };
+
+static const char *imx8mq_vpu_sels[] = {"osc_25m", "arm_pll_out", 
"sys2_pll_500m", "sys2_pll_1000m",
+   "sys1_pll_800m", "sys1_pll_400m", 
"audio_pll1_out", "vpu_pll_out", };
+
+static const char *imx8mq_gpu_core_sels[] = {"osc_25m", "gpu_pll_out", 
"sys1_pll_800m", "sys3_pll2_out",
+"sys2_pll_1000m", 
"audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mq_gpu_shader_sels[] = {"osc_25m", "gpu_pll_out", 
"sys1_pll_800m", "sys3_pll2_out",
+  "sys2_pll_1000m", 
"audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mq_main_axi_sels[] = {"osc_25m", "sys2_pll_333m", 
"sys1_pll_800m", "sys2_pll_250m",
+"sys2_pll_1000m", 
"audio_pll1_out", "video_pll1_out", "sys1_pll_100m",};
+
+static const char *imx8mq_enet_axi_sels[] = {"osc_25m", "sys1_pll_266m", 
"sys1_pll_800m", "sys2_pll_250m",
+"sys2_pll_200m", "audio_pll1_out", 
"video_pll1_out", "sys3_pll2_out&q

[PATCH v13 4/5] clk: imx: Add imx composite clock

2018-11-13 Thread Abel Vesa
Since a lot of clocks on imx8m are formed by a mux, gate, predivider and
divider, the idea here is to combine all of those into one composite clock,
but we need to deal with both predivider and divider at the same time and
therefore we add the imx8m_clk_composite_divider_ops and register
the composite clock with those.

Signed-off-by: Abel Vesa 
Suggested-by: Sascha Hauer 
Reviewed-by: Sascha Hauer 
---
 drivers/clk/imx/Makefile   |   1 +
 drivers/clk/imx/clk-composite-8m.c | 178 +
 drivers/clk/imx/clk.h  |  16 
 3 files changed, 195 insertions(+)
 create mode 100644 drivers/clk/imx/clk-composite-8m.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index b87513c..237444b 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -3,6 +3,7 @@
 obj-y += \
clk.o \
clk-busy.o \
+   clk-composite-8m.o \
clk-cpu.o \
clk-fixup-div.o \
clk-fixup-mux.o \
diff --git a/drivers/clk/imx/clk-composite-8m.c 
b/drivers/clk/imx/clk-composite-8m.c
new file mode 100644
index 000..bcd31d8
--- /dev/null
+++ b/drivers/clk/imx/clk-composite-8m.c
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 NXP
+ */
+
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+#define PCG_PREDIV_SHIFT   16
+#define PCG_PREDIV_WIDTH   3
+#define PCG_PREDIV_MAX 8
+
+#define PCG_DIV_SHIFT  0
+#define PCG_DIV_WIDTH  6
+#define PCG_DIV_MAX64
+
+#define PCG_PCS_SHIFT  24
+#define PCG_PCS_MASK   0x7
+
+#define PCG_CGC_SHIFT  28
+
+static unsigned long imx8m_clk_composite_divider_recalc_rate(struct clk_hw *hw,
+   unsigned long parent_rate)
+{
+   struct clk_divider *divider = to_clk_divider(hw);
+   unsigned long prediv_rate;
+   unsigned int prediv_value;
+   unsigned int div_value;
+
+   prediv_value = readl(divider->reg) >> divider->shift;
+   prediv_value &= clk_div_mask(divider->width);
+
+   prediv_rate = divider_recalc_rate(hw, parent_rate, prediv_value,
+   NULL, divider->flags,
+   divider->width);
+
+   div_value = readl(divider->reg) >> PCG_DIV_SHIFT;
+   div_value &= clk_div_mask(PCG_DIV_WIDTH);
+
+   return divider_recalc_rate(hw, prediv_rate, div_value, NULL,
+  divider->flags, PCG_DIV_WIDTH);
+}
+
+static int imx8m_clk_composite_compute_dividers(unsigned long rate,
+   unsigned long parent_rate,
+   int *prediv, int *postdiv)
+{
+   int div1, div2;
+   int error = INT_MAX;
+   int ret = -EINVAL;
+
+   *prediv = 1;
+   *postdiv = 1;
+
+   for (div1 = 1; div1 <= PCG_PREDIV_MAX; div1++) {
+   for (div2 = 1; div2 <= PCG_DIV_MAX; div2++) {
+   int new_error = ((parent_rate / div1) / div2) - rate;
+
+   if (abs(new_error) < abs(error)) {
+   *prediv = div1;
+   *postdiv = div2;
+   error = new_error;
+   ret = 0;
+   }
+   }
+   }
+   return ret;
+}
+
+static long imx8m_clk_composite_divider_round_rate(struct clk_hw *hw,
+   unsigned long rate,
+   unsigned long *prate)
+{
+   int prediv_value;
+   int div_value;
+
+   imx8m_clk_composite_compute_dividers(rate, *prate,
+   &prediv_value, &div_value);
+   rate = DIV_ROUND_UP(*prate, prediv_value);
+
+   return DIV_ROUND_UP(rate, div_value);
+
+}
+
+static int imx8m_clk_composite_divider_set_rate(struct clk_hw *hw,
+   unsigned long rate,
+   unsigned long parent_rate)
+{
+   struct clk_divider *divider = to_clk_divider(hw);
+   unsigned long flags = 0;
+   int prediv_value;
+   int div_value;
+   int ret = 0;
+   u32 val;
+
+   ret = imx8m_clk_composite_compute_dividers(rate, parent_rate,
+   &prediv_value, &div_value);
+   if (ret)
+   return -EINVAL;
+
+   spin_lock_irqsave(divider->lock, flags);
+
+   val = readl(divider->reg);
+   val &= ~((clk_div_mask(divider->width) << divider->shift) |
+   (clk_div_mask(PCG_DIV_WIDTH) << PCG_DIV_SHIFT));
+
+   val |= (u32)(prediv_value  - 1) << divider->shift;
+   val |= (u32)(div_value - 1) << PCG_DIV_SHIFT;
+   writel(val, divider

[PATCH v5 0/6] Add basic support for i.MX8MQ SoC and i.MX8MQ EVK board

2018-12-09 Thread Abel Vesa
Took this from Lucas since he's busy with some other work for the moment and
I thought we might be able to get this ready for the merge window.

Basically is just a respin with a minor fix for a comment from Rob.

Lucas, thanks for all the effort with this.

Changes since v5:
 * replaced the name of the node peripherals with soc in dts file

Baruch Siach (2):
  arm64: dts: imx8mq: add watchdog devices
  arm64: dts: imx8mq-evk: enable watchdog

Lucas Stach (4):
  arm64: add basic Kconfig symbols for i.MX8
  arm64: add basic DTS for i.MX8MQ
  arm64: add support for i.MX8M EVK board
  MAINTAINERS: add i.MX8 DT path to i.MX architecture

 Documentation/devicetree/bindings/arm/fsl.txt  |   8 +
 MAINTAINERS|   1 +
 arch/arm64/Kconfig.platforms   |  14 +
 arch/arm64/boot/dts/freescale/Makefile |   2 +
 arch/arm64/boot/dts/freescale/imx8mq-evk.dts   | 303 
 arch/arm64/boot/dts/freescale/imx8mq-pinfunc.h | 623 +
 arch/arm64/boot/dts/freescale/imx8mq.dtsi  | 416 +
 7 files changed, 1367 insertions(+)
 create mode 100644 arch/arm64/boot/dts/freescale/imx8mq-evk.dts
 create mode 100644 arch/arm64/boot/dts/freescale/imx8mq-pinfunc.h
 create mode 100644 arch/arm64/boot/dts/freescale/imx8mq.dtsi

-- 
2.7.4



[PATCH v5 1/6] arm64: add basic Kconfig symbols for i.MX8

2018-12-09 Thread Abel Vesa
From: Lucas Stach 

Add basic Kconfig symbols to make the MXC architecture available
in the ARM64 world.

Signed-off-by: Lucas Stach 
Reviewed-by: Fabio Estevam 
---
 arch/arm64/Kconfig.platforms | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 28f0521..7e1545a 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -142,6 +142,20 @@ config ARCH_MVEBU
   - Armada 7K SoC Family
   - Armada 8K SoC Family
 
+config ARCH_MXC
+   bool "ARMv8 based NXP i.MX SoC family"
+   help
+ This enables support for the ARMv8 based SoCs in the
+ NXP i.MX family.
+
+config SOC_IMX8MQ
+   bool "i.MX8MQ support"
+   depends on ARCH_MXC
+   select ARM64_ERRATUM_843419
+   select ARM64_ERRATUM_845719
+   help
+ This enables support for the i.MX8MQ SoC.
+
 config ARCH_QCOM
bool "Qualcomm Platforms"
select GPIOLIB
-- 
2.7.4



[PATCH v5 4/6] MAINTAINERS: add i.MX8 DT path to i.MX architecture

2018-12-09 Thread Abel Vesa
From: Lucas Stach 

Shawn agreed to take patches for the i.MX8 parts through his tree.

Signed-off-by: Lucas Stach 
Reviewed-by: Dong Aisheng 
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 3625a8d..b41ebff 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1530,6 +1530,7 @@ F:arch/arm/mach-imx/
 F: arch/arm/mach-mxs/
 F: arch/arm/boot/dts/imx*
 F: arch/arm/configs/imx*_defconfig
+F: arch/arm64/boot/dts/freescale/imx*
 F: drivers/clk/imx/
 F: drivers/firmware/imx/
 F: drivers/soc/imx/
-- 
2.7.4



[PATCH v5 2/6] arm64: add basic DTS for i.MX8MQ

2018-12-09 Thread Abel Vesa
From: Lucas Stach 

This adds the basic DTS for the i.MX8MQ.
For now only the following peripherals are supported:
- IOMUXC (pin controller)
- CCM (clock controller)
- GPIO
- UART
- uSDHC (SD/eMMC controller)
- FEC (ethernet controller)
- i2c

This is enough to get a very basic board support up and running.

One known limitation is that the driver for the GPC interrupt
controller is still missing, rendering the CPU sleep states unusable
as there is nothing waking them up anymore.

Signed-off-by: Lucas Stach 
Reviewed-by: Dong Aisheng 
---
 Documentation/devicetree/bindings/arm/fsl.txt  |   4 +
 arch/arm64/boot/dts/freescale/imx8mq-pinfunc.h | 623 +
 arch/arm64/boot/dts/freescale/imx8mq.dtsi  | 392 
 3 files changed, 1019 insertions(+)
 create mode 100644 arch/arm64/boot/dts/freescale/imx8mq-pinfunc.h
 create mode 100644 arch/arm64/boot/dts/freescale/imx8mq.dtsi

diff --git a/Documentation/devicetree/bindings/arm/fsl.txt 
b/Documentation/devicetree/bindings/arm/fsl.txt
index 1ac461ae..9f4aba2 100644
--- a/Documentation/devicetree/bindings/arm/fsl.txt
+++ b/Documentation/devicetree/bindings/arm/fsl.txt
@@ -131,6 +131,10 @@ i.MX7ULP generic board
 Required root node properties:
 - compatible = "fsl,imx7ulp";
 
+i.MX8MQ generic board
+Required root node properties:
+- compatible = "fsl,imx8mq";
+
 Freescale Vybrid Platform Device Tree Bindings
 --
 
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-pinfunc.h 
b/arch/arm64/boot/dts/freescale/imx8mq-pinfunc.h
new file mode 100644
index 000..b94b020
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mq-pinfunc.h
@@ -0,0 +1,623 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ */
+
+#ifndef __DTS_IMX8MQ_PINFUNC_H
+#define __DTS_IMX8MQ_PINFUNC_H
+
+/*
+ * The pin function ID is a tuple of
+ * 
+ */
+
+#define MX8MQ_IOMUXC_PMIC_STBY_REQ_CCMSRCGPCMIX_PMIC_STBY_REQ   
0x014 0x27C 0x000 0x0 0x0
+#define MX8MQ_IOMUXC_PMIC_ON_REQ_SNVSMIX_PMIC_ON_REQ
0x018 0x280 0x000 0x0 0x0
+#define MX8MQ_IOMUXC_ONOFF_SNVSMIX_ONOFF
0x01C 0x284 0x000 0x0 0x0
+#define MX8MQ_IOMUXC_POR_B_SNVSMIX_POR_B
0x020 0x288 0x000 0x0 0x0
+#define MX8MQ_IOMUXC_RTC_RESET_B_SNVSMIX_RTC_RESET_B
0x024 0x28C 0x000 0x0 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO00_GPIO1_IO0   
0x028 0x290 0x000 0x0 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO00_CCMSRCGPCMIX_ENET_PHY_REF_CLK_ROOT  
0x028 0x290 0x4C0 0x1 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO00_ANAMIX_REF_CLK_32K  
0x028 0x290 0x000 0x5 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO00_CCMSRCGPCMIX_EXT_CLK1   
0x028 0x290 0x000 0x6 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO00_SJC_FAIL
0x028 0x290 0x000 0x7 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO01_GPIO1_IO1   
0x02C 0x294 0x000 0x0 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO01_PWM1_OUT
0x02C 0x294 0x000 0x1 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO01_ANAMIX_REF_CLK_24M  
0x02C 0x294 0x4BC 0x5 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO01_CCMSRCGPCMIX_EXT_CLK2   
0x02C 0x294 0x000 0x6 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO01_SJC_ACTIVE  
0x02C 0x294 0x000 0x7 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO02_GPIO1_IO2   
0x030 0x298 0x000 0x0 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B
0x030 0x298 0x000 0x1 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO02_WDOG1_WDOG_ANY  
0x030 0x298 0x000 0x5 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO02_SJC_DE_B
0x030 0x298 0x000 0x7 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO03_GPIO1_IO3   
0x034 0x29C 0x000 0x0 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO03_USDHC1_VSELECT  
0x034 0x29C 0x000 0x1 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO03_SDMA1_EXT_EVENT0
0x034 0x29C 0x000 0x5 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO03_ANAMIX_XTAL_OK  
0x034 0x29C 0x000 0x6 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO03_SJC_DONE
0x034 0x29C 0x000 0x7 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO04_GPIO1_IO4   
0x038 0x2A0 0x000 0x0 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT  
0x038 0x2A0 0x000 0x1 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO04_SDMA1_EXT_EVENT1
0x038 0x2A0 0x000 0x5 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO04_ANAMIX_XTAL_OK_LV   
0x038 0x2A0 0x000 0x6 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO04_USDHC1_TEST_TRIG
0x038 0x2A0 0x000 0x7 0x0
+#define MX8MQ_IOMUXC_GPIO1_IO05_

[PATCH v5 5/6] arm64: dts: imx8mq: add watchdog devices

2018-12-09 Thread Abel Vesa
From: Baruch Siach 

Signed-off-by: Baruch Siach 
Signed-off-by: Lucas Stach 
---
 arch/arm64/boot/dts/freescale/imx8mq.dtsi | 24 
 1 file changed, 24 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi 
b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
index 3703bca..8e9d6d5 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
@@ -228,6 +228,30 @@
  "clk_ext1", "clk_ext2",
  "clk_ext3", "clk_ext4";
};
+
+   wdog1: watchdog@3028 {
+   compatible = "fsl,imx8mq-wdt", "fsl,imx21-wdt";
+   reg = <0x3028 0x1>;
+   interrupts = ;
+   clocks = <&clk IMX8MQ_CLK_WDOG1_ROOT>;
+   status = "disabled";
+   };
+
+   wdog2: watchdog@3029 {
+   compatible = "fsl,imx8mq-wdt", "fsl,imx21-wdt";
+   reg = <0x3029 0x1>;
+   interrupts = ;
+   clocks = <&clk IMX8MQ_CLK_WDOG2_ROOT>;
+   status = "disabled";
+   };
+
+   wdog3: watchdog@302a {
+   compatible = "fsl,imx8mq-wdt", "fsl,imx21-wdt";
+   reg = <0x302a 0x1>;
+   interrupts = ;
+   clocks = <&clk IMX8MQ_CLK_WDOG3_ROOT>;
+   status = "disabled";
+   };
};
 
bus@3040 { /* AIPS2 */
-- 
2.7.4



[PATCH v5 3/6] arm64: add support for i.MX8M EVK board

2018-12-09 Thread Abel Vesa
From: Lucas Stach 

This is the evaluation kit board for the i.MX8M. The current level of
support yields a working console and is able to boot userspace from
SD card or Network.

Signed-off-by: Lucas Stach 
Reviewed-by: Fabio Estevam  (v1)
Reviewed-by: Rob Herring  (v3)
Tested-by: Tested-by: Baruch Siach  (v1)
Reviewed-by: Dong Aisheng 
---
 Documentation/devicetree/bindings/arm/fsl.txt |   4 +
 arch/arm64/boot/dts/freescale/Makefile|   2 +
 arch/arm64/boot/dts/freescale/imx8mq-evk.dts  | 290 ++
 3 files changed, 296 insertions(+)
 create mode 100644 arch/arm64/boot/dts/freescale/imx8mq-evk.dts

diff --git a/Documentation/devicetree/bindings/arm/fsl.txt 
b/Documentation/devicetree/bindings/arm/fsl.txt
index 9f4aba2..71b78ff 100644
--- a/Documentation/devicetree/bindings/arm/fsl.txt
+++ b/Documentation/devicetree/bindings/arm/fsl.txt
@@ -105,6 +105,10 @@ i.MX7ULP Evaluation Kit
 Required root node properties:
 - compatible = "fsl,imx7ulp-evk", "fsl,imx7ulp";
 
+i.MX8MQ Evaluation Kit
+Required root node properties:
+- compatible = "fsl,imx8mq-evk", "fsl,imx8mq";
+
 Generic i.MX boards
 ---
 
diff --git a/arch/arm64/boot/dts/freescale/Makefile 
b/arch/arm64/boot/dts/freescale/Makefile
index 7748e6d..0001361 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -18,3 +18,5 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2088a-qds.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2088a-rdb.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-qds.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-rdb.dtb
+
+dtb-$(CONFIG_SOC_IMX8MQ) += imx8mq-evk.dtb
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts 
b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
new file mode 100644
index 000..04ce13f
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
@@ -0,0 +1,290 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2017 NXP
+ * Copyright (C) 2017-2018 Pengutronix, Lucas Stach 
+ */
+
+/dts-v1/;
+
+#include "imx8mq.dtsi"
+
+/ {
+   model = "NXP i.MX8MQ EVK";
+   compatible = "fsl,imx8mq-evk", "fsl,imx8mq";
+
+   chosen {
+   stdout-path = &uart1;
+   };
+
+   memory@4000 {
+   device_type = "memory";
+   reg = <0x 0x4000 0 0xc000>;
+   };
+
+   reg_usdhc2_vmmc: regulator-vsd-3v3 {
+   pinctrl-names = "default";
+   pinctrl-0 = <&pinctrl_reg_usdhc2>;
+   compatible = "regulator-fixed";
+   regulator-name = "VSD_3V3";
+   regulator-min-microvolt = <330>;
+   regulator-max-microvolt = <330>;
+   gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+   enable-active-high;
+   };
+};
+
+&fec1 {
+   pinctrl-names = "default";
+   pinctrl-0 = <&pinctrl_fec1>;
+   phy-mode = "rgmii-id";
+   status = "okay";
+};
+
+&i2c1 {
+   clock-frequency = <10>;
+   pinctrl-names = "default";
+   pinctrl-0 = <&pinctrl_i2c1>;
+   status = "okay";
+
+   pmic@8 {
+   compatible = "fsl,pfuze100";
+   reg = <0x8>;
+
+   regulators {
+   sw1a_reg: sw1ab {
+   regulator-min-microvolt = <825000>;
+   regulator-max-microvolt = <110>;
+   };
+
+   sw1c_reg: sw1c {
+   regulator-min-microvolt = <825000>;
+   regulator-max-microvolt = <110>;
+   };
+
+   sw2_reg: sw2 {
+   regulator-min-microvolt = <110>;
+   regulator-max-microvolt = <110>;
+   regulator-always-on;
+   };
+
+   sw3a_reg: sw3ab {
+   regulator-min-microvolt = <825000>;
+   regulator-max-microvolt = <110>;
+   regulator-always-on;
+   };
+
+   sw4_reg: sw4 {
+   regulator-min-microvolt = <180>;
+   regulator-max-microvolt = <180>;
+   regulator-always-on;
+   };
+
+   swbst_reg: swbst {
+   regulator-min-microvolt = <500>;
+   regulator-max-microvolt = <515>;
+   };
+
+   snvs_reg: vsnvs {
+   regulator-min-microvolt = <100>;
+   regulator-max-microvolt = <300>;
+   regulator-always-on;
+   };
+
+   vref_reg: vrefddr {
+   regulator-always-on;
+  

[PATCH v5 6/6] arm64: dts: imx8mq-evk: enable watchdog

2018-12-09 Thread Abel Vesa
From: Baruch Siach 

The external nWDOG signal connects to the EVK board reset circuit.

Tested on the i.MX8MQ EVK rev B3.

Signed-off-by: Baruch Siach 
Signed-off-by: Lucas Stach 
---
 arch/arm64/boot/dts/freescale/imx8mq-evk.dts | 13 +
 1 file changed, 13 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts 
b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
index 04ce13f..64a 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
@@ -160,6 +160,13 @@
status = "okay";
 };
 
+&wdog1 {
+   pinctrl-names = "default";
+   pinctrl-0 = <&pinctrl_wdog>;
+   fsl,ext-reset-output;
+   status = "okay";
+};
+
 &iomuxc {
pinctrl_fec1: fec1grp {
fsl,pins = <
@@ -287,4 +294,10 @@
MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT  0xc1
>;
};
+
+   pinctrl_wdog: wdog1grp {
+   fsl,pins = <
+   MX8MQ_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B0xc6
+   >;
+   };
 };
-- 
2.7.4



[PATCH v15 4/5] clk: imx: Add imx composite clock

2018-12-01 Thread Abel Vesa
Since a lot of clocks on imx8m are formed by a mux, gate, predivider and
divider, the idea here is to combine all of those into one composite clock,
but we need to deal with both predivider and divider at the same time and
therefore we add the imx8m_clk_composite_divider_ops and register
the composite clock with those.

Signed-off-by: Abel Vesa 
Suggested-by: Sascha Hauer 
Reviewed-by: Sascha Hauer 
---
 drivers/clk/imx/Makefile   |   1 +
 drivers/clk/imx/clk-composite-8m.c | 178 +
 drivers/clk/imx/clk.h  |  16 
 3 files changed, 195 insertions(+)
 create mode 100644 drivers/clk/imx/clk-composite-8m.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index b87513c..237444b 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -3,6 +3,7 @@
 obj-y += \
clk.o \
clk-busy.o \
+   clk-composite-8m.o \
clk-cpu.o \
clk-fixup-div.o \
clk-fixup-mux.o \
diff --git a/drivers/clk/imx/clk-composite-8m.c 
b/drivers/clk/imx/clk-composite-8m.c
new file mode 100644
index 000..6d9d371
--- /dev/null
+++ b/drivers/clk/imx/clk-composite-8m.c
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 NXP
+ */
+
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+#define PCG_PREDIV_SHIFT   16
+#define PCG_PREDIV_WIDTH   3
+#define PCG_PREDIV_MAX 8
+
+#define PCG_DIV_SHIFT  0
+#define PCG_DIV_WIDTH  6
+#define PCG_DIV_MAX64
+
+#define PCG_PCS_SHIFT  24
+#define PCG_PCS_MASK   0x7
+
+#define PCG_CGC_SHIFT  28
+
+static unsigned long imx8m_clk_composite_divider_recalc_rate(struct clk_hw *hw,
+   unsigned long parent_rate)
+{
+   struct clk_divider *divider = to_clk_divider(hw);
+   unsigned long prediv_rate;
+   unsigned int prediv_value;
+   unsigned int div_value;
+
+   prediv_value = readl(divider->reg) >> divider->shift;
+   prediv_value &= clk_div_mask(divider->width);
+
+   prediv_rate = divider_recalc_rate(hw, parent_rate, prediv_value,
+   NULL, divider->flags,
+   divider->width);
+
+   div_value = readl(divider->reg) >> PCG_DIV_SHIFT;
+   div_value &= clk_div_mask(PCG_DIV_WIDTH);
+
+   return divider_recalc_rate(hw, prediv_rate, div_value, NULL,
+  divider->flags, PCG_DIV_WIDTH);
+}
+
+static int imx8m_clk_composite_compute_dividers(unsigned long rate,
+   unsigned long parent_rate,
+   int *prediv, int *postdiv)
+{
+   int div1, div2;
+   int error = INT_MAX;
+   int ret = -EINVAL;
+
+   *prediv = 1;
+   *postdiv = 1;
+
+   for (div1 = 1; div1 <= PCG_PREDIV_MAX; div1++) {
+   for (div2 = 1; div2 <= PCG_DIV_MAX; div2++) {
+   int new_error = ((parent_rate / div1) / div2) - rate;
+
+   if (abs(new_error) < abs(error)) {
+   *prediv = div1;
+   *postdiv = div2;
+   error = new_error;
+   ret = 0;
+   }
+   }
+   }
+   return ret;
+}
+
+static long imx8m_clk_composite_divider_round_rate(struct clk_hw *hw,
+   unsigned long rate,
+   unsigned long *prate)
+{
+   int prediv_value;
+   int div_value;
+
+   imx8m_clk_composite_compute_dividers(rate, *prate,
+   &prediv_value, &div_value);
+   rate = DIV_ROUND_UP(*prate, prediv_value);
+
+   return DIV_ROUND_UP(rate, div_value);
+
+}
+
+static int imx8m_clk_composite_divider_set_rate(struct clk_hw *hw,
+   unsigned long rate,
+   unsigned long parent_rate)
+{
+   struct clk_divider *divider = to_clk_divider(hw);
+   unsigned long flags = 0;
+   int prediv_value;
+   int div_value;
+   int ret = 0;
+   u32 val;
+
+   ret = imx8m_clk_composite_compute_dividers(rate, parent_rate,
+   &prediv_value, &div_value);
+   if (ret)
+   return -EINVAL;
+
+   spin_lock_irqsave(divider->lock, flags);
+
+   val = readl(divider->reg);
+   val &= ~((clk_div_mask(divider->width) << divider->shift) |
+   (clk_div_mask(PCG_DIV_WIDTH) << PCG_DIV_SHIFT));
+
+   val |= (u32)(prediv_value  - 1) << divider->shift;
+   val |= (u32)(div_value - 1) << PCG_DIV_SHIFT;
+   writel(val, divider

[PATCH v15 5/5] clk: imx: Add clock driver for i.MX8MQ CCM

2018-12-01 Thread Abel Vesa
Add driver for the Clock Control Module found on i.MX8MQ.

Signed-off-by: Anson Huang 
Signed-off-by: Bai Ping 
Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
Reviewed-by: Sascha Hauer 
---
 drivers/clk/imx/Makefile |   1 +
 drivers/clk/imx/clk-imx8mq.c | 589 +++
 drivers/clk/imx/clk.h|  36 +++
 3 files changed, 626 insertions(+)
 create mode 100644 drivers/clk/imx/clk-imx8mq.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 237444b..6952f05 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -29,4 +29,5 @@ obj-$(CONFIG_SOC_IMX6SLL) += clk-imx6sll.o
 obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o
 obj-$(CONFIG_SOC_IMX6UL) += clk-imx6ul.o
 obj-$(CONFIG_SOC_IMX7D)  += clk-imx7d.o
+obj-$(CONFIG_SOC_IMX8MQ) += clk-imx8mq.o
 obj-$(CONFIG_SOC_VF610)  += clk-vf610.o
diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c
new file mode 100644
index 000..26b57f4
--- /dev/null
+++ b/drivers/clk/imx/clk-imx8mq.c
@@ -0,0 +1,589 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 NXP.
+ * Copyright (C) 2017 Pengutronix, Lucas Stach 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+static u32 share_count_sai1;
+static u32 share_count_sai2;
+static u32 share_count_sai3;
+static u32 share_count_sai4;
+static u32 share_count_sai5;
+static u32 share_count_sai6;
+static u32 share_count_dcss;
+static u32 share_count_nand;
+
+static struct clk *clks[IMX8MQ_CLK_END];
+
+static const char *pll_ref_sels[] = { "osc_25m", "osc_27m", "dummy", "dummy", 
};
+static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
+static const char *gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
+static const char *vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", };
+static const char *audio_pll1_bypass_sels[] = {"audio_pll1", 
"audio_pll1_ref_sel", };
+static const char *audio_pll2_bypass_sels[] = {"audio_pll2", 
"audio_pll2_ref_sel", };
+static const char *video_pll1_bypass_sels[] = {"video_pll1", 
"video_pll1_ref_sel", };
+
+static const char *sys1_pll1_out_sels[] = {"sys1_pll1", "sys1_pll1_ref_sel", };
+static const char *sys2_pll1_out_sels[] = {"sys2_pll1", "sys1_pll1_ref_sel", };
+static const char *sys3_pll1_out_sels[] = {"sys3_pll1", "sys3_pll1_ref_sel", };
+static const char *dram_pll1_out_sels[] = {"dram_pll1", "dram_pll1_ref_sel", };
+
+static const char *sys1_pll2_out_sels[] = {"sys1_pll2_div", 
"sys1_pll1_ref_sel", };
+static const char *sys2_pll2_out_sels[] = {"sys2_pll2_div", 
"sys2_pll1_ref_sel", };
+static const char *sys3_pll2_out_sels[] = {"sys3_pll2_div", 
"sys2_pll1_ref_sel", };
+static const char *dram_pll2_out_sels[] = {"dram_pll2_div", 
"dram_pll1_ref_sel", };
+
+/* CCM ROOT */
+static const char *imx8mq_a53_sels[] = {"osc_25m", "arm_pll_out", 
"sys2_pll_500m", "sys2_pll_1000m",
+   "sys1_pll_800m", "sys1_pll_400m", 
"audio_pll1_out", "sys3_pll2_out", };
+
+static const char *imx8mq_vpu_sels[] = {"osc_25m", "arm_pll_out", 
"sys2_pll_500m", "sys2_pll_1000m",
+   "sys1_pll_800m", "sys1_pll_400m", 
"audio_pll1_out", "vpu_pll_out", };
+
+static const char *imx8mq_gpu_core_sels[] = {"osc_25m", "gpu_pll_out", 
"sys1_pll_800m", "sys3_pll2_out",
+"sys2_pll_1000m", 
"audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mq_gpu_shader_sels[] = {"osc_25m", "gpu_pll_out", 
"sys1_pll_800m", "sys3_pll2_out",
+  "sys2_pll_1000m", 
"audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mq_main_axi_sels[] = {"osc_25m", "sys2_pll_333m", 
"sys1_pll_800m", "sys2_pll_250m",
+"sys2_pll_1000m", 
"audio_pll1_out", "video_pll1_out", "sys1_pll_100m",};
+
+static const char *imx8mq_enet_axi_sels[] = {"osc_25m", "sys1_pll_266m", 
"sys1_pll_800m", "sys2_pll_250m",
+"sys2_pll_200m", "audio_pll1_out", 
"video_pll1_out", "sys3_pll2_out&q

[PATCH v15 0/5] Add i.MX8MQ clock driver

2018-12-01 Thread Abel Vesa
Unfortunately, there was a problem with some divisions by 64-bit values
in the Fractional PLL which led to a link failuire on arm32.
That has been fixed now without any kind of functionality changes.

Though the v14 has made it to clk-next, due to the arm32 build failure,
this patch series had to be dropped until the failure gets fixed.

Stephen, please take this in one more time and sorry for all the trouble
caused by this series. Thanks for all the support.

Here is a link to the 14th version:

https://lkml.org/lkml/2018/11/29/767

Changes since v14:
 * fixed all the divisions by 64-bit by replacing with do_divs in clk-frac-pll

Abel Vesa (2):
  clk: imx: Add imx composite clock
  clk: imx: Add clock driver for i.MX8MQ CCM

Lucas Stach (3):
  dt-bindings: Add binding for i.MX8MQ CCM
  clk: imx: Add fractional PLL output clock
  clk: imx: Add SCCG PLL type

 .../devicetree/bindings/clock/imx8mq-clock.txt |  20 +
 drivers/clk/imx/Makefile   |   6 +-
 drivers/clk/imx/clk-composite-8m.c | 178 +++
 drivers/clk/imx/clk-frac-pll.c | 232 
 drivers/clk/imx/clk-imx8mq.c   | 589 +
 drivers/clk/imx/clk-sccg-pll.c | 256 +
 drivers/clk/imx/clk.h  |  64 +++
 include/dt-bindings/clock/imx8mq-clock.h   | 395 ++
 8 files changed, 1739 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/imx8mq-clock.txt
 create mode 100644 drivers/clk/imx/clk-composite-8m.c
 create mode 100644 drivers/clk/imx/clk-frac-pll.c
 create mode 100644 drivers/clk/imx/clk-imx8mq.c
 create mode 100644 drivers/clk/imx/clk-sccg-pll.c
 create mode 100644 include/dt-bindings/clock/imx8mq-clock.h

-- 
2.7.4



[PATCH v15 3/5] clk: imx: Add SCCG PLL type

2018-12-01 Thread Abel Vesa
From: Lucas Stach 

The SCCG is a new PLL type introduced on i.MX8.

The description of this SCCG 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   |   3 +-
 drivers/clk/imx/clk-sccg-pll.c | 256 +
 drivers/clk/imx/clk.h  |   9 ++
 3 files changed, 267 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/imx/clk-sccg-pll.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 4893c1f..b87513c 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -12,7 +12,8 @@ obj-y += \
clk-pllv1.o \
clk-pllv2.o \
clk-pllv3.o \
-   clk-pfd.o
+   clk-pfd.o \
+   clk-sccg-pll.o
 
 obj-$(CONFIG_SOC_IMX1)   += clk-imx1.o
 obj-$(CONFIG_SOC_IMX21)  += clk-imx21.o
diff --git a/drivers/clk/imx/clk-sccg-pll.c b/drivers/clk/imx/clk-sccg-pll.c
new file mode 100644
index 000..ee7752b
--- /dev/null
+++ b/drivers/clk/imx/clk-sccg-pll.c
@@ -0,0 +1,256 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2018 NXP.
+ *
+ * This driver supports the SCCG plls found in the imx8m SOCs
+ *
+ * Documentation for this SCCG pll can be found at:
+ *   https://www.nxp.com/docs/en/reference-manual/IMX8MDQLQRM.pdf#page=834
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+/* PLL CFGs */
+#define PLL_CFG0   0x0
+#define PLL_CFG1   0x4
+#define PLL_CFG2   0x8
+
+#define PLL_DIVF1_MASK GENMASK(18, 13)
+#define PLL_DIVF2_MASK GENMASK(12, 7)
+#define PLL_DIVR1_MASK GENMASK(27, 25)
+#define PLL_DIVR2_MASK GENMASK(24, 19)
+#define PLL_REF_MASK   GENMASK(2, 0)
+
+#define PLL_LOCK_MASK  BIT(31)
+#define PLL_PD_MASKBIT(7)
+
+#define OSC_25M2500
+#define OSC_27M2700
+
+#define PLL_SCCG_LOCK_TIMEOUT  70
+
+struct clk_sccg_pll {
+   struct clk_hw   hw;
+   void __iomem*base;
+};
+
+#define to_clk_sccg_pll(_hw) container_of(_hw, struct clk_sccg_pll, hw)
+
+static int clk_pll_wait_lock(struct clk_sccg_pll *pll)
+{
+   u32 val;
+
+   return readl_poll_timeout(pll->base, val, val & PLL_LOCK_MASK, 0,
+   PLL_SCCG_LOCK_TIMEOUT);
+}
+
+static int clk_pll1_is_prepared(struct clk_hw *hw)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   return (val & PLL_PD_MASK) ? 0 : 1;
+}
+
+static unsigned long clk_pll1_recalc_rate(struct clk_hw *hw,
+unsigned long parent_rate)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val, divf;
+
+   val = readl_relaxed(pll->base + PLL_CFG2);
+   divf = FIELD_GET(PLL_DIVF1_MASK, val);
+
+   return parent_rate * 2 * (divf + 1);
+}
+
+static long clk_pll1_round_rate(struct clk_hw *hw, unsigned long rate,
+  unsigned long *prate)
+{
+   unsigned long parent_rate = *prate;
+   u32 div;
+
+   if (!parent_rate)
+   return 0;
+
+   div = rate / (parent_rate * 2);
+
+   return parent_rate * div * 2;
+}
+
+static int clk_pll1_set_rate(struct clk_hw *hw, unsigned long rate,
+   unsigned long parent_rate)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+   u32 divf;
+
+   if (!parent_rate)
+   return -EINVAL;
+
+   divf = rate / (parent_rate * 2);
+
+   val = readl_relaxed(pll->base + PLL_CFG2);
+   val &= ~PLL_DIVF1_MASK;
+   val |= FIELD_PREP(PLL_DIVF1_MASK, divf - 1);
+   writel_relaxed(val, pll->base + PLL_CFG2);
+
+   return clk_pll_wait_lock(pll);
+}
+
+static int clk_pll1_prepare(struct clk_hw *hw)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   val &= ~PLL_PD_MASK;
+   writel_relaxed(val, pll->base + PLL_CFG0);
+
+   return clk_pll_wait_lock(pll);
+}
+
+static void clk_pll1_unprepare(struct clk_hw *hw)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   val |= PLL_PD_MASK;
+   writel_relaxed(val, pll->base + PLL_CFG0);
+
+}
+
+static unsigned long clk_pll2_recalc_rate(struct clk_hw *hw,
+unsigned long parent_rate)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val, ref, divr1, divf1, divr2, divf2;
+   u64 temp64;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   switch (FIELD_GET(PLL_REF_MASK, val)) {
+   case 0:
+   ref = OSC_25M;
+   

[PATCH v15 2/5] clk: imx: Add fractional PLL output clock

2018-12-01 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 | 232 +
 drivers/clk/imx/clk.h  |   3 +
 3 files changed, 236 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..0026c39
--- /dev/null
+++ b/drivers/clk/imx/clk-frac-pll.c
@@ -0,0 +1,232 @@
+// 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 
+
+#include "clk.h"
+
+#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;
+   u64 rate;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   divq = (FIELD_GET(PLL_OUTPUT_DIV_MASK, val) + 1) * 2;
+   val = readl_relaxed(pll->base + PLL_CFG1);
+   divff = FIELD_GET(PLL_FRAC_DIV_MASK, val);
+   divfi = FIELD_GET(PLL_INT_DIV_MASK, val);
+
+   temp64 *= 8;
+   temp64 *= divff;
+   do_div(temp64, PLL_FRAC_DENOM);
+   do_div(temp64, divq);
+
+   rate = parent_rate * 8 * (divfi + 1);
+   do_div(rate, divq);
+   rate += temp64;
+
+   return rate;
+}
+
+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;
+   temp64 = rate;
+   do_div(temp64, parent_rate);
+   divfi = temp64;
+   temp64 = rate - divfi * parent_rate;
+   temp64 *= PLL_FRAC_DENOM;
+   do_div(temp64, parent_rate);
+   divff = temp64;
+
+   temp64 = parent_rat

[PATCH v15 1/5] dt-bindings: Add binding for i.MX8MQ CCM

2018-12-01 Thread Abel Vesa
From: Lucas Stach 

This adds the binding for the i.MX8MQ Clock Controller Module.

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
Reviewed-by: Rob Herring 
---
 .../devicetree/bindings/clock/imx8mq-clock.txt |  20 ++
 include/dt-bindings/clock/imx8mq-clock.h   | 395 +
 2 files changed, 415 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/imx8mq-clock.txt
 create mode 100644 include/dt-bindings/clock/imx8mq-clock.h

diff --git a/Documentation/devicetree/bindings/clock/imx8mq-clock.txt 
b/Documentation/devicetree/bindings/clock/imx8mq-clock.txt
new file mode 100644
index 000..52de826
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/imx8mq-clock.txt
@@ -0,0 +1,20 @@
+* Clock bindings for NXP i.MX8M Quad
+
+Required properties:
+- compatible: Should be "fsl,imx8mq-ccm"
+- reg: Address and length of the register set
+- #clock-cells: Should be <1>
+- clocks: list of clock specifiers, must contain an entry for each required
+  entry in clock-names
+- clock-names: should include the following entries:
+- "ckil"
+- "osc_25m"
+- "osc_27m"
+- "clk_ext1"
+- "clk_ext2"
+- "clk_ext3"
+- "clk_ext4"
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell.  See include/dt-bindings/clock/imx8mq-clock.h
+for the full list of i.MX8M Quad clock IDs.
diff --git a/include/dt-bindings/clock/imx8mq-clock.h 
b/include/dt-bindings/clock/imx8mq-clock.h
new file mode 100644
index 000..b53be41
--- /dev/null
+++ b/include/dt-bindings/clock/imx8mq-clock.h
@@ -0,0 +1,395 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_IMX8MQ_H
+#define __DT_BINDINGS_CLOCK_IMX8MQ_H
+
+#define IMX8MQ_CLK_DUMMY   0
+#define IMX8MQ_CLK_32K 1
+#define IMX8MQ_CLK_25M 2
+#define IMX8MQ_CLK_27M 3
+#define IMX8MQ_CLK_EXT14
+#define IMX8MQ_CLK_EXT25
+#define IMX8MQ_CLK_EXT36
+#define IMX8MQ_CLK_EXT47
+
+/* ANAMIX PLL clocks */
+/* FRAC PLLs */
+/* ARM PLL */
+#define IMX8MQ_ARM_PLL_REF_SEL 8
+#define IMX8MQ_ARM_PLL_REF_DIV 9
+#define IMX8MQ_ARM_PLL 10
+#define IMX8MQ_ARM_PLL_BYPASS  11
+#define IMX8MQ_ARM_PLL_OUT 12
+
+/* GPU PLL */
+#define IMX8MQ_GPU_PLL_REF_SEL 13
+#define IMX8MQ_GPU_PLL_REF_DIV 14
+#define IMX8MQ_GPU_PLL 15
+#define IMX8MQ_GPU_PLL_BYPASS  16
+#define IMX8MQ_GPU_PLL_OUT 17
+
+/* VPU PLL */
+#define IMX8MQ_VPU_PLL_REF_SEL 18
+#define IMX8MQ_VPU_PLL_REF_DIV 19
+#define IMX8MQ_VPU_PLL 20
+#define IMX8MQ_VPU_PLL_BYPASS  21
+#define IMX8MQ_VPU_PLL_OUT 22
+
+/* AUDIO PLL1 */
+#define IMX8MQ_AUDIO_PLL1_REF_SEL  23
+#define IMX8MQ_AUDIO_PLL1_REF_DIV  24
+#define IMX8MQ_AUDIO_PLL1  25
+#define IMX8MQ_AUDIO_PLL1_BYPASS   26
+#define IMX8MQ_AUDIO_PLL1_OUT  27
+
+/* AUDIO PLL2 */
+#define IMX8MQ_AUDIO_PLL2_REF_SEL  28
+#define IMX8MQ_AUDIO_PLL2_REF_DIV  29
+#define IMX8MQ_AUDIO_PLL2  30
+#define IMX8MQ_AUDIO_PLL2_BYPASS   31
+#define IMX8MQ_AUDIO_PLL2_OUT  32
+
+/* VIDEO PLL1 */
+#define IMX8MQ_VIDEO_PLL1_REF_SEL  33
+#define IMX8MQ_VIDEO_PLL1_REF_DIV  34
+#define IMX8MQ_VIDEO_PLL1  35
+#define IMX8MQ_VIDEO_PLL1_BYPASS   36
+#define IMX8MQ_VIDEO_PLL1_OUT  37
+
+/* SYS1 PLL */
+#define IMX8MQ_SYS1_PLL1_REF_SEL   38
+#define IMX8MQ_SYS1_PLL1_REF_DIV   39
+#define IMX8MQ_SYS1_PLL1   40
+#define IMX8MQ_SYS1_PLL1_OUT   41
+#define IMX8MQ_SYS1_PLL1_OUT_DIV   42
+#define IMX8MQ_SYS1_PLL2   43
+#define IMX8MQ_SYS1_PLL2_DIV   44
+#define IMX8MQ_SYS1_PLL2_OUT   45
+
+/* SYS2 PLL */
+#define IMX8MQ_SYS2_PLL1_REF_SEL   46
+#define IMX8MQ_SYS2_PLL1_REF_DIV   47
+#define IMX8MQ_SYS2_PLL1   48
+#define IMX8MQ_SYS2_PLL1_OUT   49
+#define IMX8MQ_SYS2_PLL1_OUT_DIV   50
+#define IMX8MQ_SYS2_PLL2   51
+#define IMX8MQ_SYS2_PLL2_DIV   52
+#define IMX8MQ_SYS2_PLL2_OUT   53
+
+/* SYS3 PLL */
+#define IMX8MQ_SYS3_PLL1_REF_SEL   54
+#define IMX8MQ_SYS3_PLL1_REF_DIV   55
+#define IMX8MQ_SYS3_PLL1   56
+#define IMX8MQ_SYS3_PLL1_OUT   57
+#define IMX8MQ_SYS3_PLL1_OUT_DIV   58
+#define IMX8MQ_SYS3_PLL2   59
+#define IMX8MQ_SYS3_PLL2_DIV   60
+#define IMX8MQ_SYS3_PLL2_OUT   61
+
+/* DRAM PLL */
+#define IMX8MQ_DRAM_PLL1_REF_SEL   62
+#define IMX8MQ_DRAM_PLL1_REF_DIV   63
+#define IMX8MQ_DRAM_PLL1   64
+#define IMX8MQ

[PATCH v6 2/2] pinctrl: imx: add driver for i.MX8MQ

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

The i.MX8MQ pincontrol works in a similar way to the earlier i.MX SoCs.
This driver builds on top of the imx specific pinconf handling.

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
Acked-by: Dong Aisheng 
---
 drivers/pinctrl/freescale/Kconfig  |   7 +
 drivers/pinctrl/freescale/Makefile |   1 +
 drivers/pinctrl/freescale/pinctrl-imx8mq.c | 351 +
 3 files changed, 359 insertions(+)
 create mode 100644 drivers/pinctrl/freescale/pinctrl-imx8mq.c

diff --git a/drivers/pinctrl/freescale/Kconfig 
b/drivers/pinctrl/freescale/Kconfig
index 0d8ba1e..dccf64c 100644
--- a/drivers/pinctrl/freescale/Kconfig
+++ b/drivers/pinctrl/freescale/Kconfig
@@ -117,6 +117,13 @@ config PINCTRL_IMX7ULP
help
  Say Y here to enable the imx7ulp pinctrl driver
 
+config PINCTRL_IMX8MQ
+   bool "IMX8MQ pinctrl driver"
+   depends on SOC_IMX8MQ
+   select PINCTRL_IMX
+   help
+ Say Y here to enable the imx8mq pinctrl driver
+
 config PINCTRL_VF610
bool "Freescale Vybrid VF610 pinctrl driver"
depends on SOC_VF610
diff --git a/drivers/pinctrl/freescale/Makefile 
b/drivers/pinctrl/freescale/Makefile
index 368be8c..73175b3 100644
--- a/drivers/pinctrl/freescale/Makefile
+++ b/drivers/pinctrl/freescale/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_PINCTRL_IMX6SX)  += pinctrl-imx6sx.o
 obj-$(CONFIG_PINCTRL_IMX6UL)   += pinctrl-imx6ul.o
 obj-$(CONFIG_PINCTRL_IMX7D)+= pinctrl-imx7d.o
 obj-$(CONFIG_PINCTRL_IMX7ULP)  += pinctrl-imx7ulp.o
+obj-$(CONFIG_PINCTRL_IMX8MQ)   += pinctrl-imx8mq.o
 obj-$(CONFIG_PINCTRL_VF610)+= pinctrl-vf610.o
 obj-$(CONFIG_PINCTRL_MXS)  += pinctrl-mxs.o
 obj-$(CONFIG_PINCTRL_IMX23)+= pinctrl-imx23.o
diff --git a/drivers/pinctrl/freescale/pinctrl-imx8mq.c 
b/drivers/pinctrl/freescale/pinctrl-imx8mq.c
new file mode 100644
index 000..8d39af5
--- /dev/null
+++ b/drivers/pinctrl/freescale/pinctrl-imx8mq.c
@@ -0,0 +1,351 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017-2018 NXP
+ * Copyright (C) 2018 Pengutronix, Lucas Stach 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "pinctrl-imx.h"
+
+enum imx8mq_pads {
+   MX8MQ_PAD_RESERVE0 = 0,
+   MX8MQ_PAD_RESERVE1 = 1,
+   MX8MQ_PAD_RESERVE2 = 2,
+   MX8MQ_PAD_RESERVE3 = 3,
+   MX8MQ_PAD_RESERVE4 = 4,
+   MX8MQ_IOMUXC_PMIC_STBY_REQ_CCMSRCGPCMIX = 5,
+   MX8MQ_IOMUXC_PMIC_ON_REQ_SNVSMIX = 6,
+   MX8MQ_IOMUXC_ONOFF_SNVSMIX = 7,
+   MX8MQ_IOMUXC_POR_B_SNVSMIX = 8,
+   MX8MQ_IOMUXC_RTC_RESET_B_SNVSMIX = 9,
+   MX8MQ_IOMUXC_GPIO1_IO00 = 10,
+   MX8MQ_IOMUXC_GPIO1_IO01 = 11,
+   MX8MQ_IOMUXC_GPIO1_IO02 = 12,
+   MX8MQ_IOMUXC_GPIO1_IO03 = 13,
+   MX8MQ_IOMUXC_GPIO1_IO04 = 14,
+   MX8MQ_IOMUXC_GPIO1_IO05 = 15,
+   MX8MQ_IOMUXC_GPIO1_IO06 = 16,
+   MX8MQ_IOMUXC_GPIO1_IO07 = 17,
+   MX8MQ_IOMUXC_GPIO1_IO08 = 18,
+   MX8MQ_IOMUXC_GPIO1_IO09 = 19,
+   MX8MQ_IOMUXC_GPIO1_IO10 = 20,
+   MX8MQ_IOMUXC_GPIO1_IO11 = 21,
+   MX8MQ_IOMUXC_GPIO1_IO12 = 22,
+   MX8MQ_IOMUXC_GPIO1_IO13 = 23,
+   MX8MQ_IOMUXC_GPIO1_IO14 = 24,
+   MX8MQ_IOMUXC_GPIO1_IO15 = 25,
+   MX8MQ_IOMUXC_ENET_MDC = 26,
+   MX8MQ_IOMUXC_ENET_MDIO = 27,
+   MX8MQ_IOMUXC_ENET_TD3 = 28,
+   MX8MQ_IOMUXC_ENET_TD2 = 29,
+   MX8MQ_IOMUXC_ENET_TD1 = 30,
+   MX8MQ_IOMUXC_ENET_TD0 = 31,
+   MX8MQ_IOMUXC_ENET_TX_CTL = 32,
+   MX8MQ_IOMUXC_ENET_TXC = 33,
+   MX8MQ_IOMUXC_ENET_RX_CTL = 34,
+   MX8MQ_IOMUXC_ENET_RXC = 35,
+   MX8MQ_IOMUXC_ENET_RD0 = 36,
+   MX8MQ_IOMUXC_ENET_RD1 = 37,
+   MX8MQ_IOMUXC_ENET_RD2 = 38,
+   MX8MQ_IOMUXC_ENET_RD3 = 39,
+   MX8MQ_IOMUXC_SD1_CLK = 40,
+   MX8MQ_IOMUXC_SD1_CMD = 41,
+   MX8MQ_IOMUXC_SD1_DATA0 = 42,
+   MX8MQ_IOMUXC_SD1_DATA1 = 43,
+   MX8MQ_IOMUXC_SD1_DATA2 = 44,
+   MX8MQ_IOMUXC_SD1_DATA3 = 45,
+   MX8MQ_IOMUXC_SD1_DATA4 = 46,
+   MX8MQ_IOMUXC_SD1_DATA5 = 47,
+   MX8MQ_IOMUXC_SD1_DATA6 = 48,
+   MX8MQ_IOMUXC_SD1_DATA7 = 49,
+   MX8MQ_IOMUXC_SD1_RESET_B = 50,
+   MX8MQ_IOMUXC_SD1_STROBE = 51,
+   MX8MQ_IOMUXC_SD2_CD_B = 52,
+   MX8MQ_IOMUXC_SD2_CLK = 53,
+   MX8MQ_IOMUXC_SD2_CMD = 54,
+   MX8MQ_IOMUXC_SD2_DATA0 = 55,
+   MX8MQ_IOMUXC_SD2_DATA1 = 56,
+   MX8MQ_IOMUXC_SD2_DATA2 = 57,
+   MX8MQ_IOMUXC_SD2_DATA3 = 58,
+   MX8MQ_IOMUXC_SD2_RESET_B = 59,
+   MX8MQ_IOMUXC_SD2_WP = 60,
+   MX8MQ_IOMUXC_NAND_ALE = 61,
+   MX8MQ_IOMUXC_NAND_CE0_B = 62,
+   MX8MQ_IOMUXC_NAND_CE1_B = 63,
+   MX8MQ_IOMUXC_NAND_CE2_B = 64,
+   MX8MQ_IOMUXC_NAND_CE3_B = 65,
+   MX8MQ_IOMUXC_NAND_CLE = 66,
+   MX8MQ_IOMUXC_NAND_DATA00 = 67,
+   MX8MQ_IOMUXC_NAND_DATA01 = 68,
+   MX8MQ_IOMUXC_NAND_DATA02 = 69,
+   MX8MQ_IOMUXC_NAND_DATA03 = 70,
+   MX8MQ_IOMUXC_NAND_DATA04 = 71,
+ 

[PATCH v6 0/2] pinctrl: imx: Add driver for i.MX8MQ

2018-07-02 Thread Abel Vesa
This is the sixth version for the patch series sent by Lucas.

https://www.spinics.net/lists/devicetree/msg212752.html

Fifth version can be found here:

https://lkml.org/lkml/2018/6/22/501

Changes since v5:
 * implemented Rob's review comments related to bindings

Changes since v4:
 * implemented all Aisheng's review comments

Changes since v3:
 * dropped the SION generic pinconf changes
 * added examples to the bindings doc

Changes since v2:
 * switch back to the 'fsl,pins' and hardcoded the config values
inside the dts.
 * updated documentation accordingly

Abel Vesa (1):
  dt-bindings: add binding for i.MX8MQ IOMUXC

Lucas Stach (1):
  pinctrl: imx: add driver for i.MX8MQ

 .../bindings/pinctrl/fsl,imx8mq-pinctrl.txt|  36 +++
 drivers/pinctrl/freescale/Kconfig  |   7 +
 drivers/pinctrl/freescale/Makefile |   1 +
 drivers/pinctrl/freescale/pinctrl-imx8mq.c | 351 +
 4 files changed, 395 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt
 create mode 100644 drivers/pinctrl/freescale/pinctrl-imx8mq.c

-- 
2.7.4



[PATCH v6 1/2] dt-bindings: add binding for i.MX8MQ IOMUXC

2018-07-02 Thread Abel Vesa
This adds the binding for the i.MX8MQ pin controller, in the same
fashion as earlier i.MX SoCs.

Signed-off-by: Abel Vesa 
Acked-by: Dong Aisheng 
---
 .../bindings/pinctrl/fsl,imx8mq-pinctrl.txt| 36 ++
 1 file changed, 36 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt

diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt 
b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt
new file mode 100644
index 000..66de750
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt
@@ -0,0 +1,36 @@
+* Freescale IMX8MQ IOMUX Controller
+
+Please refer to fsl,imx-pinctrl.txt and pinctrl-bindings.txt in this directory
+for common binding part and usage.
+
+Required properties:
+- compatible: "fsl,imx8mq-iomuxc"
+- reg: should contain the base physical address and size of the iomuxc
+  registers.
+
+Required properties in sub-nodes:
+- fsl,pins: each entry consists of 6 integers and represents the mux and config
+  setting for one pin.  The first 5 integers  are specified using a PIN_FUNC_ID macro, which can be found in
+  imx8mq-pinfunc.h under device tree source folder.  The last integer CONFIG is
+  the pad setting value like pull-up on this pin.  Please refer to i.MX8M Quad
+  Reference Manual for detailed CONFIG settings.
+
+Examples:
+
+&uart1 {
+   pinctrl-names = "default";
+   pinctrl-0 = <&pinctrl_uart1>;
+};
+
+iomuxc: pinctrl@3033 {
+compatible = "fsl,imx8mq-iomuxc";
+reg = <0x0 0x3033 0x0 0x1>;
+
+pinctrl_uart1: uart1grp {
+fsl,pins = <
+MX8MQ_IOMUXC_UART1_RXD_UART1_DCE_RX 0x49
+MX8MQ_IOMUXC_UART1_TXD_UART1_DCE_TX 0x49
+>;
+};
+};
-- 
2.7.4



[PATCH v3 3/3] pinctrl: imx: add driver for i.MX8MQ

2018-06-20 Thread Abel Vesa
From: Lucas Stach 

The i.MX8MQ pincontrol works in a similar way to the earlier i.MX SoCs.
This driver builds on top of the generic pinconf handling introduced
with the i.MX7ULP pinctrl driver.

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
---
 drivers/pinctrl/freescale/Kconfig  |   7 +
 drivers/pinctrl/freescale/Makefile |   1 +
 drivers/pinctrl/freescale/pinctrl-imx8mq.c | 356 +
 3 files changed, 364 insertions(+)
 create mode 100644 drivers/pinctrl/freescale/pinctrl-imx8mq.c

diff --git a/drivers/pinctrl/freescale/Kconfig 
b/drivers/pinctrl/freescale/Kconfig
index 0d8ba1e..dccf64c 100644
--- a/drivers/pinctrl/freescale/Kconfig
+++ b/drivers/pinctrl/freescale/Kconfig
@@ -117,6 +117,13 @@ config PINCTRL_IMX7ULP
help
  Say Y here to enable the imx7ulp pinctrl driver
 
+config PINCTRL_IMX8MQ
+   bool "IMX8MQ pinctrl driver"
+   depends on SOC_IMX8MQ
+   select PINCTRL_IMX
+   help
+ Say Y here to enable the imx8mq pinctrl driver
+
 config PINCTRL_VF610
bool "Freescale Vybrid VF610 pinctrl driver"
depends on SOC_VF610
diff --git a/drivers/pinctrl/freescale/Makefile 
b/drivers/pinctrl/freescale/Makefile
index 368be8c..73175b3 100644
--- a/drivers/pinctrl/freescale/Makefile
+++ b/drivers/pinctrl/freescale/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_PINCTRL_IMX6SX)  += pinctrl-imx6sx.o
 obj-$(CONFIG_PINCTRL_IMX6UL)   += pinctrl-imx6ul.o
 obj-$(CONFIG_PINCTRL_IMX7D)+= pinctrl-imx7d.o
 obj-$(CONFIG_PINCTRL_IMX7ULP)  += pinctrl-imx7ulp.o
+obj-$(CONFIG_PINCTRL_IMX8MQ)   += pinctrl-imx8mq.o
 obj-$(CONFIG_PINCTRL_VF610)+= pinctrl-vf610.o
 obj-$(CONFIG_PINCTRL_MXS)  += pinctrl-mxs.o
 obj-$(CONFIG_PINCTRL_IMX23)+= pinctrl-imx23.o
diff --git a/drivers/pinctrl/freescale/pinctrl-imx8mq.c 
b/drivers/pinctrl/freescale/pinctrl-imx8mq.c
new file mode 100644
index 000..be2c9c2
--- /dev/null
+++ b/drivers/pinctrl/freescale/pinctrl-imx8mq.c
@@ -0,0 +1,356 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ * Copyright (C) 2018 Pengutronix, Lucas Stach 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "pinctrl-imx.h"
+
+enum imx8mq_pads {
+   MX8MQ_PAD_RESERVE0 = 0,
+   MX8MQ_PAD_RESERVE1 = 1,
+   MX8MQ_PAD_RESERVE2 = 2,
+   MX8MQ_PAD_RESERVE3 = 3,
+   MX8MQ_PAD_RESERVE4 = 4,
+   MX8MQ_IOMUXC_PMIC_STBY_REQ_CCMSRCGPCMIX = 5,
+   MX8MQ_IOMUXC_PMIC_ON_REQ_SNVSMIX = 6,
+   MX8MQ_IOMUXC_ONOFF_SNVSMIX = 7,
+   MX8MQ_IOMUXC_POR_B_SNVSMIX = 8,
+   MX8MQ_IOMUXC_RTC_RESET_B_SNVSMIX = 9,
+   MX8MQ_IOMUXC_GPIO1_IO00 = 10,
+   MX8MQ_IOMUXC_GPIO1_IO01 = 11,
+   MX8MQ_IOMUXC_GPIO1_IO02 = 12,
+   MX8MQ_IOMUXC_GPIO1_IO03 = 13,
+   MX8MQ_IOMUXC_GPIO1_IO04 = 14,
+   MX8MQ_IOMUXC_GPIO1_IO05 = 15,
+   MX8MQ_IOMUXC_GPIO1_IO06 = 16,
+   MX8MQ_IOMUXC_GPIO1_IO07 = 17,
+   MX8MQ_IOMUXC_GPIO1_IO08 = 18,
+   MX8MQ_IOMUXC_GPIO1_IO09 = 19,
+   MX8MQ_IOMUXC_GPIO1_IO10 = 20,
+   MX8MQ_IOMUXC_GPIO1_IO11 = 21,
+   MX8MQ_IOMUXC_GPIO1_IO12 = 22,
+   MX8MQ_IOMUXC_GPIO1_IO13 = 23,
+   MX8MQ_IOMUXC_GPIO1_IO14 = 24,
+   MX8MQ_IOMUXC_GPIO1_IO15 = 25,
+   MX8MQ_IOMUXC_ENET_MDC = 26,
+   MX8MQ_IOMUXC_ENET_MDIO = 27,
+   MX8MQ_IOMUXC_ENET_TD3 = 28,
+   MX8MQ_IOMUXC_ENET_TD2 = 29,
+   MX8MQ_IOMUXC_ENET_TD1 = 30,
+   MX8MQ_IOMUXC_ENET_TD0 = 31,
+   MX8MQ_IOMUXC_ENET_TX_CTL = 32,
+   MX8MQ_IOMUXC_ENET_TXC = 33,
+   MX8MQ_IOMUXC_ENET_RX_CTL = 34,
+   MX8MQ_IOMUXC_ENET_RXC = 35,
+   MX8MQ_IOMUXC_ENET_RD0 = 36,
+   MX8MQ_IOMUXC_ENET_RD1 = 37,
+   MX8MQ_IOMUXC_ENET_RD2 = 38,
+   MX8MQ_IOMUXC_ENET_RD3 = 39,
+   MX8MQ_IOMUXC_SD1_CLK = 40,
+   MX8MQ_IOMUXC_SD1_CMD = 41,
+   MX8MQ_IOMUXC_SD1_DATA0 = 42,
+   MX8MQ_IOMUXC_SD1_DATA1 = 43,
+   MX8MQ_IOMUXC_SD1_DATA2 = 44,
+   MX8MQ_IOMUXC_SD1_DATA3 = 45,
+   MX8MQ_IOMUXC_SD1_DATA4 = 46,
+   MX8MQ_IOMUXC_SD1_DATA5 = 47,
+   MX8MQ_IOMUXC_SD1_DATA6 = 48,
+   MX8MQ_IOMUXC_SD1_DATA7 = 49,
+   MX8MQ_IOMUXC_SD1_RESET_B = 50,
+   MX8MQ_IOMUXC_SD1_STROBE = 51,
+   MX8MQ_IOMUXC_SD2_CD_B = 52,
+   MX8MQ_IOMUXC_SD2_CLK = 53,
+   MX8MQ_IOMUXC_SD2_CMD = 54,
+   MX8MQ_IOMUXC_SD2_DATA0 = 55,
+   MX8MQ_IOMUXC_SD2_DATA1 = 56,
+   MX8MQ_IOMUXC_SD2_DATA2 = 57,
+   MX8MQ_IOMUXC_SD2_DATA3 = 58,
+   MX8MQ_IOMUXC_SD2_RESET_B = 59,
+   MX8MQ_IOMUXC_SD2_WP = 60,
+   MX8MQ_IOMUXC_NAND_ALE = 61,
+   MX8MQ_IOMUXC_NAND_CE0_B = 62,
+   MX8MQ_IOMUXC_NAND_CE1_B = 63,
+   MX8MQ_IOMUXC_NAND_CE2_B = 64,
+   MX8MQ_IOMUXC_NAND_CE3_B = 65,
+   MX8MQ_IOMUXC_NAND_CLE = 66,
+   MX8MQ_IOMUXC_NAND_DATA00 = 67,
+   MX8MQ_IOMUXC_NAND_DATA01 = 68,
+   MX8MQ_IOMUXC_NAND_DATA02 = 69,
+   MX8MQ_IOMUXC_NAND_DATA03 = 70,
+  

[PATCH v3 1/3] dt-bindings: add binding for i.MX8MQ IOMUXC

2018-06-20 Thread Abel Vesa
This adds the binding for the i.MX8MQ pin controller, in the same
fashion as earlier i.MX SoCs.

Signed-off-by: Abel Vesa 
---
 .../devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt  | 13 +
 1 file changed, 13 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt

diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt 
b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt
new file mode 100644
index 000..5cf7f8a
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt
@@ -0,0 +1,13 @@
+* Freescale IMX8MQ IOMUX Controller
+
+Please refer to fsl,imx-pinctrl.txt and pinctrl-bindings.txt in this directory
+for common binding part and usage.
+
+Required properties:
+- compatible: "fsl,imx8mq-iomuxc"
+- fsl,pins: each entry consists of 6 integers and represents the mux and config
+  setting for one pin.  The first 5 integers  are specified using a PIN_FUNC_ID macro, which can be found in
+  imx8mq-pinfunc.h under device tree source folder.  The last integer CONFIG is
+  the pad setting value like pull-up on this pin.  Please refer to i.MX8M Quad
+  Reference Manual for detailed CONFIG settings.
-- 
2.7.4



[PATCH v3 2/3] pinctrl: imx: allow to configure SION with generic pinconf

2018-06-20 Thread Abel Vesa
From: Lucas Stach 

The SION bit force enables the input buffer, overriding the configuration
driven by the muxed module. It is not located in the pad config register,
but in the mux register and thus needs special handling.

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
---
 drivers/pinctrl/freescale/pinctrl-imx.c | 19 +++
 drivers/pinctrl/freescale/pinctrl-imx.h |  4 
 2 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c 
b/drivers/pinctrl/freescale/pinctrl-imx.c
index 1c6bb15..335edc9 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx.c
@@ -26,10 +26,6 @@
 #include "../pinmux.h"
 #include "pinctrl-imx.h"
 
-/* The bits in CONFIG cell defined in binding doc*/
-#define IMX_NO_PAD_CTL 0x8000  /* no pin config need */
-#define IMX_PAD_SION 0x4000/* set SION */
-
 static inline const struct group_desc *imx_pinctrl_find_group_by_name(
struct pinctrl_dev *pctldev,
const char *name)
@@ -514,18 +510,17 @@ static int imx_pinctrl_parse_groups(struct device_node 
*np,
pin->mux_mode = be32_to_cpu(*list++);
pin->input_val = be32_to_cpu(*list++);
 
-   if (info->generic_pinconf) {
+   if (info->generic_pinconf)
/* generic pin config decoded */
pin->config = config;
-   } else {
+   else
/* legacy pin config read from devicetree */
-   config = be32_to_cpu(*list++);
+   pin->config = be32_to_cpu(*list++);
 
-   /* SION bit is in mux register */
-   if (config & IMX_PAD_SION)
-   pin->mux_mode |= IOMUXC_CONFIG_SION;
-   pin->config = config & ~IMX_PAD_SION;
-   }
+   /* SION bit is in mux register */
+   if (pin->config & IMX_PAD_SION)
+   pin->mux_mode |= IOMUXC_CONFIG_SION;
+   pin->config = pin->config & ~IMX_PAD_SION;
 
dev_dbg(ipctl->dev, "%s: 0x%x 0x%08lx", info->pins[pin_id].name,
pin->mux_mode, pin->config);
diff --git a/drivers/pinctrl/freescale/pinctrl-imx.h 
b/drivers/pinctrl/freescale/pinctrl-imx.h
index 4b8225c..44567a6 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx.h
+++ b/drivers/pinctrl/freescale/pinctrl-imx.h
@@ -14,6 +14,10 @@
 #include 
 #include 
 
+/* The bits in CONFIG cell defined in binding doc*/
+#define IMX_NO_PAD_CTL 0x8000  /* no pin config need */
+#define IMX_PAD_SION 0x4000/* set SION */
+
 struct platform_device;
 
 extern struct pinmux_ops imx_pmx_ops;
-- 
2.7.4



[PATCH v3 0/3] pinctrl: imx: Add driver for i.MX8MQ

2018-06-20 Thread Abel Vesa
This is the third version for the patch series sent by Lucas.

https://www.spinics.net/lists/devicetree/msg212752.html

Changes since v2:
 * switch back to the 'fsl,pins' and hardcoded the config values
inside the dts.
 * updated documentation accordingly

Abel Vesa (1):
  dt-bindings: add binding for i.MX8MQ IOMUXC

Lucas Stach (2):
  pinctrl: imx: allow to configure SION with generic pinconf
  pinctrl: imx: add driver for i.MX8MQ

 .../bindings/pinctrl/fsl,imx8mq-pinctrl.txt|  13 +
 drivers/pinctrl/freescale/Kconfig  |   7 +
 drivers/pinctrl/freescale/Makefile |   1 +
 drivers/pinctrl/freescale/pinctrl-imx.c|  19 +-
 drivers/pinctrl/freescale/pinctrl-imx.h|   4 +
 drivers/pinctrl/freescale/pinctrl-imx8mq.c | 356 +
 6 files changed, 388 insertions(+), 12 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt
 create mode 100644 drivers/pinctrl/freescale/pinctrl-imx8mq.c

-- 
2.7.4



Re: [PATCH v3 2/3] pinctrl: imx: allow to configure SION with generic pinconf

2018-06-20 Thread Abel Vesa
On Wed, Jun 20, 2018 at 10:16:42AM +0200, Lucas Stach wrote:
> Hi Abel,
> 
> as this series switches back to using the raw padcfg values in DT
> instead of generic pinconf (which I think is the right move), we can
> drop this patch from the series.
> 

Cool, will drop it in the next version.

Thanks,
Abel

> Regards,
> Lucas
> 
> Am Mittwoch, den 20.06.2018, 10:24 +0300 schrieb Abel Vesa:
> > > From: Lucas Stach 
> > 
> > The SION bit force enables the input buffer, overriding the configuration
> > driven by the muxed module. It is not located in the pad config register,
> > but in the mux register and thus needs special handling.
> > 
> > > Signed-off-by: Lucas Stach 
> > > Signed-off-by: Abel Vesa 
> > ---
> >  drivers/pinctrl/freescale/pinctrl-imx.c | 19 +++
> >  drivers/pinctrl/freescale/pinctrl-imx.h |  4 
> >  2 files changed, 11 insertions(+), 12 deletions(-)
> > 
> > diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c 
> > b/drivers/pinctrl/freescale/pinctrl-imx.c
> > index 1c6bb15..335edc9 100644
> > --- a/drivers/pinctrl/freescale/pinctrl-imx.c
> > +++ b/drivers/pinctrl/freescale/pinctrl-imx.c
> > @@ -26,10 +26,6 @@
> >  #include "../pinmux.h"
> >  #include "pinctrl-imx.h"
> >  
> > -/* The bits in CONFIG cell defined in binding doc*/
> > > > -#define IMX_NO_PAD_CTL 0x8000  /* no pin config need */
> > > -#define IMX_PAD_SION 0x4000  /* set SION */
> > -
> >  static inline const struct group_desc *imx_pinctrl_find_group_by_name(
> > >   struct pinctrl_dev *pctldev,
> > >   const char *name)
> > @@ -514,18 +510,17 @@ static int imx_pinctrl_parse_groups(struct 
> > device_node *np,
> > >   pin->mux_mode = be32_to_cpu(*list++);
> > >   pin->input_val = be32_to_cpu(*list++);
> >  
> > > - if (info->generic_pinconf) {
> > > + if (info->generic_pinconf)
> > >   /* generic pin config decoded */
> > >   pin->config = config;
> > > - } else {
> > > + else
> > >   /* legacy pin config read from devicetree */
> > > - config = be32_to_cpu(*list++);
> > > + pin->config = be32_to_cpu(*list++);
> >  
> > > - /* SION bit is in mux register */
> > > - if (config & IMX_PAD_SION)
> > > - pin->mux_mode |= IOMUXC_CONFIG_SION;
> > > - pin->config = config & ~IMX_PAD_SION;
> > > - }
> > > + /* SION bit is in mux register */
> > > + if (pin->config & IMX_PAD_SION)
> > > + pin->mux_mode |= IOMUXC_CONFIG_SION;
> > > + pin->config = pin->config & ~IMX_PAD_SION;
> >  
> > >   dev_dbg(ipctl->dev, "%s: 0x%x 0x%08lx", info->pins[pin_id].name,
> > >   pin->mux_mode, pin->config);
> > diff --git a/drivers/pinctrl/freescale/pinctrl-imx.h 
> > b/drivers/pinctrl/freescale/pinctrl-imx.h
> > index 4b8225c..44567a6 100644
> > --- a/drivers/pinctrl/freescale/pinctrl-imx.h
> > +++ b/drivers/pinctrl/freescale/pinctrl-imx.h
> > @@ -14,6 +14,10 @@
> >  #include 
> >  #include 
> >  
> > +/* The bits in CONFIG cell defined in binding doc*/
> > > > +#define IMX_NO_PAD_CTL 0x8000  /* no pin config need */
> > > +#define IMX_PAD_SION 0x4000  /* set SION */
> > +
> >  struct platform_device;
> >  
> >  extern struct pinmux_ops imx_pmx_ops;

-- 

[PATCH v4 1/2] dt-bindings: add binding for i.MX8MQ IOMUXC

2018-06-20 Thread Abel Vesa
This adds the binding for the i.MX8MQ pin controller, in the same
fashion as earlier i.MX SoCs.

Signed-off-by: Abel Vesa 
---
 .../bindings/pinctrl/fsl,imx8mq-pinctrl.txt| 29 ++
 1 file changed, 29 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt

diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt 
b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt
new file mode 100644
index 000..f11a3f0
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt
@@ -0,0 +1,29 @@
+* Freescale IMX8MQ IOMUX Controller
+
+Please refer to fsl,imx-pinctrl.txt and pinctrl-bindings.txt in this directory
+for common binding part and usage.
+
+Required properties:
+- compatible: "fsl,imx8mq-iomuxc"
+- fsl,pins: each entry consists of 6 integers and represents the mux and config
+  setting for one pin.  The first 5 integers  are specified using a PIN_FUNC_ID macro, which can be found in
+  imx8mq-pinfunc.h under device tree source folder.  The last integer CONFIG is
+  the pad setting value like pull-up on this pin.  Please refer to i.MX8M Quad
+  Reference Manual for detailed CONFIG settings.
+
+Examples:
+
+&uart1 {
+   pinctrl-names = "default";
+   pinctrl-0 = <&pinctrl_uart1>;
+};
+
+&iomuxc {
+   pinctrl_uart1: uart1grp {
+   fsl,pins = <
+   MX8MQ_IOMUXC_UART1_RXD_UART1_DCE_RX 0x49
+   MX8MQ_IOMUXC_UART1_TXD_UART1_DCE_TX 0x49
+   >;
+   };
+};
-- 
2.7.4



[PATCH v4 2/2] pinctrl: imx: add driver for i.MX8MQ

2018-06-20 Thread Abel Vesa
From: Lucas Stach 

The i.MX8MQ pincontrol works in a similar way to the earlier i.MX SoCs.
This driver builds on top of the generic pinconf handling introduced
with the i.MX7ULP pinctrl driver.

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
---
 drivers/pinctrl/freescale/Kconfig  |   7 +
 drivers/pinctrl/freescale/Makefile |   1 +
 drivers/pinctrl/freescale/pinctrl-imx8mq.c | 356 +
 3 files changed, 364 insertions(+)
 create mode 100644 drivers/pinctrl/freescale/pinctrl-imx8mq.c

diff --git a/drivers/pinctrl/freescale/Kconfig 
b/drivers/pinctrl/freescale/Kconfig
index 0d8ba1e..dccf64c 100644
--- a/drivers/pinctrl/freescale/Kconfig
+++ b/drivers/pinctrl/freescale/Kconfig
@@ -117,6 +117,13 @@ config PINCTRL_IMX7ULP
help
  Say Y here to enable the imx7ulp pinctrl driver
 
+config PINCTRL_IMX8MQ
+   bool "IMX8MQ pinctrl driver"
+   depends on SOC_IMX8MQ
+   select PINCTRL_IMX
+   help
+ Say Y here to enable the imx8mq pinctrl driver
+
 config PINCTRL_VF610
bool "Freescale Vybrid VF610 pinctrl driver"
depends on SOC_VF610
diff --git a/drivers/pinctrl/freescale/Makefile 
b/drivers/pinctrl/freescale/Makefile
index 368be8c..73175b3 100644
--- a/drivers/pinctrl/freescale/Makefile
+++ b/drivers/pinctrl/freescale/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_PINCTRL_IMX6SX)  += pinctrl-imx6sx.o
 obj-$(CONFIG_PINCTRL_IMX6UL)   += pinctrl-imx6ul.o
 obj-$(CONFIG_PINCTRL_IMX7D)+= pinctrl-imx7d.o
 obj-$(CONFIG_PINCTRL_IMX7ULP)  += pinctrl-imx7ulp.o
+obj-$(CONFIG_PINCTRL_IMX8MQ)   += pinctrl-imx8mq.o
 obj-$(CONFIG_PINCTRL_VF610)+= pinctrl-vf610.o
 obj-$(CONFIG_PINCTRL_MXS)  += pinctrl-mxs.o
 obj-$(CONFIG_PINCTRL_IMX23)+= pinctrl-imx23.o
diff --git a/drivers/pinctrl/freescale/pinctrl-imx8mq.c 
b/drivers/pinctrl/freescale/pinctrl-imx8mq.c
new file mode 100644
index 000..be2c9c2
--- /dev/null
+++ b/drivers/pinctrl/freescale/pinctrl-imx8mq.c
@@ -0,0 +1,356 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ * Copyright (C) 2018 Pengutronix, Lucas Stach 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "pinctrl-imx.h"
+
+enum imx8mq_pads {
+   MX8MQ_PAD_RESERVE0 = 0,
+   MX8MQ_PAD_RESERVE1 = 1,
+   MX8MQ_PAD_RESERVE2 = 2,
+   MX8MQ_PAD_RESERVE3 = 3,
+   MX8MQ_PAD_RESERVE4 = 4,
+   MX8MQ_IOMUXC_PMIC_STBY_REQ_CCMSRCGPCMIX = 5,
+   MX8MQ_IOMUXC_PMIC_ON_REQ_SNVSMIX = 6,
+   MX8MQ_IOMUXC_ONOFF_SNVSMIX = 7,
+   MX8MQ_IOMUXC_POR_B_SNVSMIX = 8,
+   MX8MQ_IOMUXC_RTC_RESET_B_SNVSMIX = 9,
+   MX8MQ_IOMUXC_GPIO1_IO00 = 10,
+   MX8MQ_IOMUXC_GPIO1_IO01 = 11,
+   MX8MQ_IOMUXC_GPIO1_IO02 = 12,
+   MX8MQ_IOMUXC_GPIO1_IO03 = 13,
+   MX8MQ_IOMUXC_GPIO1_IO04 = 14,
+   MX8MQ_IOMUXC_GPIO1_IO05 = 15,
+   MX8MQ_IOMUXC_GPIO1_IO06 = 16,
+   MX8MQ_IOMUXC_GPIO1_IO07 = 17,
+   MX8MQ_IOMUXC_GPIO1_IO08 = 18,
+   MX8MQ_IOMUXC_GPIO1_IO09 = 19,
+   MX8MQ_IOMUXC_GPIO1_IO10 = 20,
+   MX8MQ_IOMUXC_GPIO1_IO11 = 21,
+   MX8MQ_IOMUXC_GPIO1_IO12 = 22,
+   MX8MQ_IOMUXC_GPIO1_IO13 = 23,
+   MX8MQ_IOMUXC_GPIO1_IO14 = 24,
+   MX8MQ_IOMUXC_GPIO1_IO15 = 25,
+   MX8MQ_IOMUXC_ENET_MDC = 26,
+   MX8MQ_IOMUXC_ENET_MDIO = 27,
+   MX8MQ_IOMUXC_ENET_TD3 = 28,
+   MX8MQ_IOMUXC_ENET_TD2 = 29,
+   MX8MQ_IOMUXC_ENET_TD1 = 30,
+   MX8MQ_IOMUXC_ENET_TD0 = 31,
+   MX8MQ_IOMUXC_ENET_TX_CTL = 32,
+   MX8MQ_IOMUXC_ENET_TXC = 33,
+   MX8MQ_IOMUXC_ENET_RX_CTL = 34,
+   MX8MQ_IOMUXC_ENET_RXC = 35,
+   MX8MQ_IOMUXC_ENET_RD0 = 36,
+   MX8MQ_IOMUXC_ENET_RD1 = 37,
+   MX8MQ_IOMUXC_ENET_RD2 = 38,
+   MX8MQ_IOMUXC_ENET_RD3 = 39,
+   MX8MQ_IOMUXC_SD1_CLK = 40,
+   MX8MQ_IOMUXC_SD1_CMD = 41,
+   MX8MQ_IOMUXC_SD1_DATA0 = 42,
+   MX8MQ_IOMUXC_SD1_DATA1 = 43,
+   MX8MQ_IOMUXC_SD1_DATA2 = 44,
+   MX8MQ_IOMUXC_SD1_DATA3 = 45,
+   MX8MQ_IOMUXC_SD1_DATA4 = 46,
+   MX8MQ_IOMUXC_SD1_DATA5 = 47,
+   MX8MQ_IOMUXC_SD1_DATA6 = 48,
+   MX8MQ_IOMUXC_SD1_DATA7 = 49,
+   MX8MQ_IOMUXC_SD1_RESET_B = 50,
+   MX8MQ_IOMUXC_SD1_STROBE = 51,
+   MX8MQ_IOMUXC_SD2_CD_B = 52,
+   MX8MQ_IOMUXC_SD2_CLK = 53,
+   MX8MQ_IOMUXC_SD2_CMD = 54,
+   MX8MQ_IOMUXC_SD2_DATA0 = 55,
+   MX8MQ_IOMUXC_SD2_DATA1 = 56,
+   MX8MQ_IOMUXC_SD2_DATA2 = 57,
+   MX8MQ_IOMUXC_SD2_DATA3 = 58,
+   MX8MQ_IOMUXC_SD2_RESET_B = 59,
+   MX8MQ_IOMUXC_SD2_WP = 60,
+   MX8MQ_IOMUXC_NAND_ALE = 61,
+   MX8MQ_IOMUXC_NAND_CE0_B = 62,
+   MX8MQ_IOMUXC_NAND_CE1_B = 63,
+   MX8MQ_IOMUXC_NAND_CE2_B = 64,
+   MX8MQ_IOMUXC_NAND_CE3_B = 65,
+   MX8MQ_IOMUXC_NAND_CLE = 66,
+   MX8MQ_IOMUXC_NAND_DATA00 = 67,
+   MX8MQ_IOMUXC_NAND_DATA01 = 68,
+   MX8MQ_IOMUXC_NAND_DATA02 = 69,
+   MX8MQ_IOMUXC_NAND_DATA03 = 70,
+  

[PATCH v4 0/2] pinctrl: imx: Add driver for i.MX8MQ

2018-06-20 Thread Abel Vesa
This is the fourth version for the patch series sent by Lucas.

https://www.spinics.net/lists/devicetree/msg212752.html

Third version can be found here:

https://lkml.org/lkml/2018/6/20/343

Changes since v3:
 * dropped the SION generic pinconf changes
 * added examples to the bindings doc

Changes since v2:
 * switch back to the 'fsl,pins' and hardcoded the config values
inside the dts.
 * updated documentation accordingly

Abel Vesa (1):
  dt-bindings: add binding for i.MX8MQ IOMUXC

Lucas Stach (1):
  pinctrl: imx: add driver for i.MX8MQ

 .../bindings/pinctrl/fsl,imx8mq-pinctrl.txt|  29 ++
 drivers/pinctrl/freescale/Kconfig  |   7 +
 drivers/pinctrl/freescale/Makefile |   1 +
 drivers/pinctrl/freescale/pinctrl-imx8mq.c | 356 +
 4 files changed, 393 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/pinctrl/fsl,imx8mq-pinctrl.txt
 create mode 100644 drivers/pinctrl/freescale/pinctrl-imx8mq.c

-- 
2.7.4



[PATCH] cpu/hotplug: Non-SMP machines do not make use of booted_once

2018-08-14 Thread Abel Vesa
Following commit breaks the non-SMP builds.

[0cc3cd21657be04cb0] cpu/hotplug: Boot HT siblings at least once

Signed-off-by: Abel Vesa 
---
 kernel/cpu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/kernel/cpu.c b/kernel/cpu.c
index 099fb20cd7be..f06c513c5c42 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -2272,6 +2272,8 @@ void __init boot_cpu_init(void)
  */
 void __init boot_cpu_hotplug_init(void)
 {
+#ifdef CONFIG_SMP
this_cpu_write(cpuhp_state.booted_once, true);
+#endif
this_cpu_write(cpuhp_state.state, CPUHP_ONLINE);
 }
-- 
2.18.0



[PATCH v4 1/5] dt-bindings: add binding for i.MX8MQ CCM

2018-08-16 Thread Abel Vesa
From: Lucas Stach 

This adds the binding for the i.MX8MQ Clock Controller Module.

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
Reviewed-by: Rob Herring 
---
 .../devicetree/bindings/clock/imx8mq-clock.txt |  20 +
 include/dt-bindings/clock/imx8mq-clock.h   | 410 +
 2 files changed, 430 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/imx8mq-clock.txt
 create mode 100644 include/dt-bindings/clock/imx8mq-clock.h

diff --git a/Documentation/devicetree/bindings/clock/imx8mq-clock.txt 
b/Documentation/devicetree/bindings/clock/imx8mq-clock.txt
new file mode 100644
index 000..52de826
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/imx8mq-clock.txt
@@ -0,0 +1,20 @@
+* Clock bindings for NXP i.MX8M Quad
+
+Required properties:
+- compatible: Should be "fsl,imx8mq-ccm"
+- reg: Address and length of the register set
+- #clock-cells: Should be <1>
+- clocks: list of clock specifiers, must contain an entry for each required
+  entry in clock-names
+- clock-names: should include the following entries:
+- "ckil"
+- "osc_25m"
+- "osc_27m"
+- "clk_ext1"
+- "clk_ext2"
+- "clk_ext3"
+- "clk_ext4"
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell.  See include/dt-bindings/clock/imx8mq-clock.h
+for the full list of i.MX8M Quad clock IDs.
diff --git a/include/dt-bindings/clock/imx8mq-clock.h 
b/include/dt-bindings/clock/imx8mq-clock.h
new file mode 100644
index 000..0d19bd9
--- /dev/null
+++ b/include/dt-bindings/clock/imx8mq-clock.h
@@ -0,0 +1,410 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_IMX8MQ_H
+#define __DT_BINDINGS_CLOCK_IMX8MQ_H
+
+#define IMX8MQ_CLK_DUMMY   0
+#define IMX8MQ_CLK_32K 1
+#define IMX8MQ_CLK_25M 2
+#define IMX8MQ_CLK_27M 3
+#define IMX8MQ_CLK_EXT14
+#define IMX8MQ_CLK_EXT25
+#define IMX8MQ_CLK_EXT36
+#define IMX8MQ_CLK_EXT47
+
+/* ANAMIX PLL clocks */
+/* FRAC PLLs */
+/* ARM PLL */
+#define IMX8MQ_ARM_PLL_REF_SEL 8
+#define IMX8MQ_ARM_PLL_REF_DIV 9
+#define IMX8MQ_ARM_PLL 10
+#define IMX8MQ_ARM_PLL_BYPASS  11
+#define IMX8MQ_ARM_PLL_OUT 12
+
+/* GPU PLL */
+#define IMX8MQ_GPU_PLL_REF_SEL 13
+#define IMX8MQ_GPU_PLL_REF_DIV 14
+#define IMX8MQ_GPU_PLL 15
+#define IMX8MQ_GPU_PLL_BYPASS  16
+#define IMX8MQ_GPU_PLL_OUT 17
+
+/* VPU PLL */
+#define IMX8MQ_VPU_PLL_REF_SEL 18
+#define IMX8MQ_VPU_PLL_REF_DIV 19
+#define IMX8MQ_VPU_PLL 20
+#define IMX8MQ_VPU_PLL_BYPASS  21
+#define IMX8MQ_VPU_PLL_OUT 22
+
+/* AUDIO PLL1 */
+#define IMX8MQ_AUDIO_PLL1_REF_SEL  23
+#define IMX8MQ_AUDIO_PLL1_REF_DIV  24
+#define IMX8MQ_AUDIO_PLL1  25
+#define IMX8MQ_AUDIO_PLL1_BYPASS   26
+#define IMX8MQ_AUDIO_PLL1_OUT  27
+
+/* AUDIO PLL2 */
+#define IMX8MQ_AUDIO_PLL2_REF_SEL  28
+#define IMX8MQ_AUDIO_PLL2_REF_DIV  29
+#define IMX8MQ_AUDIO_PLL2  30
+#define IMX8MQ_AUDIO_PLL2_BYPASS   31
+#define IMX8MQ_AUDIO_PLL2_OUT  32
+
+/* VIDEO PLL1 */
+#define IMX8MQ_VIDEO_PLL1_REF_SEL  33
+#define IMX8MQ_VIDEO_PLL1_REF_DIV  34
+#define IMX8MQ_VIDEO_PLL1  35
+#define IMX8MQ_VIDEO_PLL1_BYPASS   36
+#define IMX8MQ_VIDEO_PLL1_OUT  37
+
+/* SYS1 PLL */
+#define IMX8MQ_SYS1_PLL1_REF_SEL   38
+#define IMX8MQ_SYS1_PLL1_REF_DIV   39
+#define IMX8MQ_SYS1_PLL1   40
+#define IMX8MQ_SYS1_PLL1_OUT   41
+#define IMX8MQ_SYS1_PLL1_OUT_DIV   42
+#define IMX8MQ_SYS1_PLL2   43
+#define IMX8MQ_SYS1_PLL2_DIV   44
+#define IMX8MQ_SYS1_PLL2_OUT   45
+
+/* SYS2 PLL */
+#define IMX8MQ_SYS2_PLL1_REF_SEL   46
+#define IMX8MQ_SYS2_PLL1_REF_DIV   47
+#define IMX8MQ_SYS2_PLL1   48
+#define IMX8MQ_SYS2_PLL1_OUT   49
+#define IMX8MQ_SYS2_PLL1_OUT_DIV   50
+#define IMX8MQ_SYS2_PLL2   51
+#define IMX8MQ_SYS2_PLL2_DIV   52
+#define IMX8MQ_SYS2_PLL2_OUT   53
+
+/* SYS3 PLL */
+#define IMX8MQ_SYS3_PLL1_REF_SEL   54
+#define IMX8MQ_SYS3_PLL1_REF_DIV   55
+#define IMX8MQ_SYS3_PLL1   56
+#define IMX8MQ_SYS3_PLL1_OUT   57
+#define IMX8MQ_SYS3_PLL1_OUT_DIV   58
+#define IMX8MQ_SYS3_PLL2   59
+#define IMX8MQ_SYS3_PLL2_DIV   60
+#define IMX8MQ_SYS3_PLL2_OUT   61
+
+/* DRAM PLL */
+#define IMX8MQ_DRAM_PLL1_REF_SEL   62
+#define IMX8MQ_DRAM_PLL1_REF_DIV   63
+#define IMX8MQ_DRAM_PLL1   64
+#define IMX8MQ

[PATCH v4 0/5] Add i.MX8MQ clock driver

2018-08-16 Thread Abel Vesa
Third version can be found here:

https://www.spinics.net/lists/arm-kernel/msg671015.html

Changes since v3:
 * Added a composite clock type to get rid of some complexity
   from clk-imx8mq. This new composite clock type will also be
   used by all the imx8 socs that will follow.
 * Added back the reviewed-by tag.

Abel Vesa (1):
  clk: imx: add imx composite clock

Lucas Stach (4):
  dt-bindings: add binding for i.MX8MQ CCM
  clk: imx: add fractional PLL output clock
  clk: imx: add SCCG PLL type
  clk: imx: add clock driver for i.MX8MQ CCM

 .../devicetree/bindings/clock/imx8mq-clock.txt |  20 +
 drivers/clk/imx/Makefile   |   6 +-
 drivers/clk/imx/clk-composite.c| 471 +++
 drivers/clk/imx/clk-frac-pll.c | 230 
 drivers/clk/imx/clk-imx8mq.c   | 631 +
 drivers/clk/imx/clk-sccg-pll.c | 231 
 drivers/clk/imx/clk.h  |  57 ++
 include/dt-bindings/clock/imx8mq-clock.h   | 410 +
 8 files changed, 2055 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/imx8mq-clock.txt
 create mode 100644 drivers/clk/imx/clk-composite.c
 create mode 100644 drivers/clk/imx/clk-frac-pll.c
 create mode 100644 drivers/clk/imx/clk-imx8mq.c
 create mode 100644 drivers/clk/imx/clk-sccg-pll.c
 create mode 100644 include/dt-bindings/clock/imx8mq-clock.h

-- 
2.7.4



[PATCH v4 3/5] clk: imx: add SCCG PLL type

2018-08-16 Thread Abel Vesa
From: Lucas Stach 

The SCCG is a new PLL type introduced on i.MX8. Add support for this.
The driver currently misses the PLL lock check, as the preliminary
documentation mentions lock configurations, but is quiet about where
to find the actual lock status signal.

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/Makefile   |   3 +-
 drivers/clk/imx/clk-sccg-pll.c | 231 +
 drivers/clk/imx/clk.h  |   9 ++
 3 files changed, 242 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/imx/clk-sccg-pll.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 4893c1f..b87513c 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -12,7 +12,8 @@ obj-y += \
clk-pllv1.o \
clk-pllv2.o \
clk-pllv3.o \
-   clk-pfd.o
+   clk-pfd.o \
+   clk-sccg-pll.o
 
 obj-$(CONFIG_SOC_IMX1)   += clk-imx1.o
 obj-$(CONFIG_SOC_IMX21)  += clk-imx21.o
diff --git a/drivers/clk/imx/clk-sccg-pll.c b/drivers/clk/imx/clk-sccg-pll.c
new file mode 100644
index 000..886ae03
--- /dev/null
+++ b/drivers/clk/imx/clk-sccg-pll.c
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2018 NXP.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+/* PLL CFGs */
+#define PLL_CFG0   0x0
+#define PLL_CFG1   0x4
+#define PLL_CFG2   0x8
+
+#define PLL_DIVF1_SHIFT13
+#define PLL_DIVF2_SHIFT7
+#define PLL_DIVF_MASK  0x3f
+
+#define PLL_DIVR1_SHIFT25
+#define PLL_DIVR2_SHIFT19
+#define PLL_DIVR1_MASK 0x3
+#define PLL_DIVR2_MASK 0x3f
+#define PLL_REF_SHIFT  0
+#define PLL_REF_MASK   0x3
+
+#define PLL_LOCK   31
+#define PLL_PD 7
+
+#define OSC_25M2500
+#define OSC_27M2700
+
+struct clk_sccg_pll {
+   struct clk_hw   hw;
+   void __iomem*base;
+};
+
+#define to_clk_sccg_pll(_hw) container_of(_hw, struct clk_sccg_pll, hw)
+
+static int clk_pll1_is_prepared(struct clk_hw *hw)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   return (val & (1 << PLL_PD)) ? 0 : 1;
+}
+
+static unsigned long clk_pll1_recalc_rate(struct clk_hw *hw,
+unsigned long parent_rate)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val, divf;
+
+   val = readl_relaxed(pll->base + PLL_CFG2);
+   divf = (val >> PLL_DIVF1_SHIFT) & PLL_DIVF_MASK;
+
+   return parent_rate * 2 * (divf + 1);
+}
+
+static long clk_pll1_round_rate(struct clk_hw *hw, unsigned long rate,
+  unsigned long *prate)
+{
+   unsigned long parent_rate = *prate;
+   u32 div;
+
+   div = rate / (parent_rate * 2);
+
+   return parent_rate * div * 2;
+}
+
+static int clk_pll1_set_rate(struct clk_hw *hw, unsigned long rate,
+   unsigned long parent_rate)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+   u32 divf;
+
+   divf = rate / (parent_rate * 2);
+
+   val = readl_relaxed(pll->base + PLL_CFG2);
+   val &= ~(PLL_DIVF_MASK << PLL_DIVF1_SHIFT);
+   val |= (divf - 1) << PLL_DIVF1_SHIFT;
+   writel_relaxed(val, pll->base + PLL_CFG2);
+
+   /* FIXME: PLL lock check */
+
+   return 0;
+}
+
+static int clk_pll1_prepare(struct clk_hw *hw)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base);
+   val &= ~(1 << PLL_PD);
+   writel_relaxed(val, pll->base);
+
+   /* FIXME: PLL lock check */
+
+   return 0;
+}
+
+static void clk_pll1_unprepare(struct clk_hw *hw)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base);
+   val |= (1 << PLL_PD);
+   writel_relaxed(val, pll->base);
+}
+
+static unsigned long clk_pll2_recalc_rate(struct clk_hw *hw,
+unsigned long parent_rate)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val, ref, divr1, divf1, divr2, divf2;
+   u64 temp64;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   switch ((val >> PLL_REF_SHIFT) & PLL_REF_MASK) {
+   case 0:
+   ref = OSC_25M;
+   break;
+   case 1:
+   ref = OSC_27M;
+   break;
+   default:
+   ref = OSC_25M;
+   break;
+   }
+
+   val = readl_relaxed(pll->base + PLL_CFG2);
+   divr1 = (val >> PLL_DIVR1_SHIFT) & PLL_DIVR1_MASK;
+   divr2 = (val >> PLL_DIVR2_SHIFT) & PLL_DIVR2_MASK;
+   divf1 = (val >> PLL_DIVF1_SHIFT) & PLL_DIVF_MASK;
+   divf2 = (val >> PLL_DIVF2_SHIFT) & PLL_DIVF_MASK;
+
+   temp6

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

2018-08-16 Thread Abel Vesa
From: Lucas Stach 

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

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/Makefile   |   1 +
 drivers/clk/imx/clk-frac-pll.c | 230 +
 drivers/clk/imx/clk.h  |   3 +
 3 files changed, 234 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..c80c6ed
--- /dev/null
+++ b/drivers/clk/imx/clk-frac-pll.c
@@ -0,0 +1,230 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 NXP.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+#define PLL_CFG0   0x0
+#define PLL_CFG1   0x4
+
+#define PLL_LOCK_STATUSBIT(31)
+#define PLL_PD 19
+#define PLL_PD_MASKBIT(PLL_PD)
+#define PLL_BYPASS 14
+#define PLL_BYPASS_MASKBIT(PLL_BYPASS)
+#define PLL_NEWDIV_VAL BIT(12)
+#define PLL_NEWDIV_ACK BIT(11)
+#define PLL_FRAC_DIV_MASK  0xff
+#define PLL_INT_DIV_MASK   0x7f
+#define PLL_OUTPUT_DIV_MASK0x1f
+#define PLL_FRAC_DENOM 0x100
+
+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)
+{
+   unsigned long timeout = jiffies + msecs_to_jiffies(10);
+   u32 val;
+
+   /* Wait for PLL to lock */
+   do {
+   if (readl_relaxed(pll->base) & PLL_LOCK_STATUS)
+   break;
+   if (time_after(jiffies, timeout))
+   break;
+   } while (1);
+
+   return readl_poll_timeout(pll->base, val,
+   val & PLL_LOCK_STATUS, 0, 1000);
+}
+
+static int clk_wait_ack(struct clk_frac_pll *pll)
+{
+   unsigned long timeout = jiffies + msecs_to_jiffies(50);
+   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 */
+   do {
+   if (readl_relaxed(pll->base) & PLL_NEWDIV_ACK)
+   break;
+   if (time_after(jiffies, timeout))
+   break;
+   } while (1);
+
+   return readl_poll_timeout(pll->base, val,
+   val & PLL_NEWDIV_ACK, 0, 1000);
+}
+
+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;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   divq = ((val & PLL_OUTPUT_DIV_MASK) + 1) * 2;
+   val = readl_relaxed(pll->base + PLL_CFG1);
+   divff = (val >> 7) & PLL_FRAC_DIV_MASK;
+   divfi = (val & PLL_INT_DIV_MASK);
+
+   temp64 = (u64)parent_rate * 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)
+{
+   unsigned long parent_rate = *prate;
+   u32 divff, divfi;
+   u64 temp64;
+
+   parent_rate *= 8;
+   rate *= 2;
+   divfi = rate / parent_rate;
+   temp64 = (u64)(rate - divfi * parent_rate);
+   temp64 *= PLL_FRAC_DENOM;
+   do_div(

[PATCH v4 4/5] clk: imx: add imx composite clock

2018-08-16 Thread Abel Vesa
Since a lot of clocks on imx8 are formed by a mux, gate, predivider and
divider, the idea here is to combine all of those into one more complex
clock type, therefore moving the complexity inside the composite clock and
outside of the SoC specific clock driver.

Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/Makefile|   1 +
 drivers/clk/imx/clk-composite.c | 471 
 drivers/clk/imx/clk.h   |   9 +
 3 files changed, 481 insertions(+)
 create mode 100644 drivers/clk/imx/clk-composite.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index b87513c..4fabb0a 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -3,6 +3,7 @@
 obj-y += \
clk.o \
clk-busy.o \
+   clk-composite.o \
clk-cpu.o \
clk-fixup-div.o \
clk-fixup-mux.o \
diff --git a/drivers/clk/imx/clk-composite.c b/drivers/clk/imx/clk-composite.c
new file mode 100644
index 000..751dabf
--- /dev/null
+++ b/drivers/clk/imx/clk-composite.c
@@ -0,0 +1,471 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 NXP
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+#define PCG_PREDIV_SHIFT   16
+#define PCG_PREDIV_WIDTH   3
+
+#define PCG_DIV_SHIFT  0
+#define PCG_DIV_WIDTH  6
+
+#define PCG_PCS_SHIFT  24
+#define PCG_PCS_MASK   0x7
+
+#define PCG_CGC_SHIFT  28
+
+#define to_clk_imx_composite(_hw) \
+   container_of(_hw, struct imx_clk_composite, hw)
+
+struct imx_clk_composite {
+   struct clk_hw   hw;
+   struct clk_ops  ops;
+
+   struct clk_hw   *mux_hw;
+   struct clk_hw   *prediv_hw;
+   struct clk_hw   *div_hw;
+   struct clk_hw   *gate_hw;
+
+   const struct clk_ops*mux_ops;
+   const struct clk_ops*prediv_ops;
+   const struct clk_ops*div_ops;
+   const struct clk_ops*gate_ops;
+};
+
+static u8 clk_imx_composite_get_parent(struct clk_hw *hw)
+{
+   struct imx_clk_composite *clk = to_clk_imx_composite(hw);
+   const struct clk_ops *mux_ops = clk->mux_ops;
+   struct clk_hw *mux_hw = clk->mux_hw;
+
+   __clk_hw_set_clk(mux_hw, hw);
+
+   return mux_ops->get_parent(mux_hw);
+}
+
+static int clk_imx_composite_set_parent(struct clk_hw *hw, u8 index)
+{
+   struct imx_clk_composite *clk = to_clk_imx_composite(hw);
+   const struct clk_ops *mux_ops = clk->mux_ops;
+   struct clk_hw *mux_hw = clk->mux_hw;
+
+   __clk_hw_set_clk(mux_hw, hw);
+
+   return mux_ops->set_parent(mux_hw, index);
+}
+
+static unsigned long clk_imx_composite_recalc_rate(struct clk_hw *hw,
+   unsigned long parent_rate)
+{
+   struct imx_clk_composite *clk = to_clk_imx_composite(hw);
+   const struct clk_ops *div_ops = clk->div_ops;
+   struct clk_hw *div_hw = clk->div_hw;
+
+   __clk_hw_set_clk(div_hw, hw);
+
+   return div_ops->recalc_rate(div_hw, parent_rate);
+}
+
+static int clk_imx_composite_determine_rate(struct clk_hw *hw,
+   struct clk_rate_request *req)
+{
+   struct imx_clk_composite *clk = to_clk_imx_composite(hw);
+   const struct clk_ops *div_ops = clk->div_ops;
+   const struct clk_ops *mux_ops = clk->mux_ops;
+   struct clk_hw *div_hw = clk->div_hw;
+   struct clk_hw *mux_hw = clk->mux_hw;
+   struct clk_hw *parent;
+   unsigned long parent_rate;
+   long tmp_rate, best_rate = 0;
+   unsigned long rate_diff;
+   unsigned long best_rate_diff = ULONG_MAX;
+   long rate;
+   int i;
+
+   if (div_hw && div_ops && div_ops->determine_rate) {
+   __clk_hw_set_clk(div_hw, hw);
+   return div_ops->determine_rate(div_hw, req);
+   } else if (div_hw && div_ops && div_ops->round_rate &&
+  mux_hw && mux_ops && mux_ops->set_parent) {
+   req->best_parent_hw = NULL;
+
+   if (clk_hw_get_flags(hw) & CLK_SET_RATE_NO_REPARENT) {
+   parent = clk_hw_get_parent(mux_hw);
+   req->best_parent_hw = parent;
+   req->best_parent_rate = clk_hw_get_rate(parent);
+
+   rate = div_ops->round_rate(div_hw, req->rate,
+   &req->best_parent_rate);
+   if (rate < 0)
+   return rate;
+
+   req->rate = rate;
+   return 0;
+   }
+
+   for (i = 0; i < clk_hw_get_num_parents(mux_hw); i++) {
+   parent = clk_hw_get_parent_by_index(mux_hw, i);
+   if (!parent)
+

[PATCH v4 5/5] clk: imx: add clock driver for i.MX8MQ CCM

2018-08-16 Thread Abel Vesa
From: Lucas Stach 

Add driver for the Clock Control Module found on i.MX8MQ.

This is largely based on the downstream driver from Anson Huang and
Bai Ping at NXP, with only some small adaptions to mainline from me.

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/Makefile |   1 +
 drivers/clk/imx/clk-imx8mq.c | 631 +++
 drivers/clk/imx/clk.h|  36 +++
 3 files changed, 668 insertions(+)
 create mode 100644 drivers/clk/imx/clk-imx8mq.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 4fabb0a..64e695c 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -30,3 +30,4 @@ obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o
 obj-$(CONFIG_SOC_IMX6UL) += clk-imx6ul.o
 obj-$(CONFIG_SOC_IMX7D)  += clk-imx7d.o
 obj-$(CONFIG_SOC_VF610)  += clk-vf610.o
+obj-$(CONFIG_SOC_IMX8MQ) += clk-imx8mq.o
diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c
new file mode 100644
index 000..d3a9e31
--- /dev/null
+++ b/drivers/clk/imx/clk-imx8mq.c
@@ -0,0 +1,631 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 NXP.
+ * Copyright (C) 2017 Pengutronix, Lucas Stach 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+static u32 share_count_sai1;
+static u32 share_count_sai2;
+static u32 share_count_sai3;
+static u32 share_count_sai4;
+static u32 share_count_sai5;
+static u32 share_count_sai6;
+static u32 share_count_dcss;
+static u32 share_count_nand;
+
+static struct clk *clks[IMX8MQ_CLK_END];
+
+static const char *pll_ref_sels[] = { "osc_25m", "osc_27m", "dummy", "dummy", 
};
+static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
+static const char *gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
+static const char *vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", };
+static const char *audio_pll1_bypass_sels[] = {"audio_pll1", 
"audio_pll1_ref_sel", };
+static const char *audio_pll2_bypass_sels[] = {"audio_pll2", 
"audio_pll2_ref_sel", };
+static const char *video_pll1_bypass_sels[] = {"video_pll1", 
"video_pll1_ref_sel", };
+
+static const char *sys1_pll1_out_sels[] = {"sys1_pll1", "sys1_pll1_ref_sel", };
+static const char *sys2_pll1_out_sels[] = {"sys2_pll1", "sys1_pll1_ref_sel", };
+static const char *sys3_pll1_out_sels[] = {"sys3_pll1", "sys3_pll1_ref_sel", };
+static const char *dram_pll1_out_sels[] = {"dram_pll1", "dram_pll1_ref_sel", };
+static const char *video2_pll1_out_sels[] = {"video2_pll1", 
"video2_pll1_ref_sel", };
+
+static const char *sys1_pll2_out_sels[] = {"sys1_pll2_div", 
"sys1_pll1_ref_sel", };
+static const char *sys2_pll2_out_sels[] = {"sys2_pll2_div", 
"sys2_pll1_ref_sel", };
+static const char *sys3_pll2_out_sels[] = {"sys3_pll2_div", 
"sys2_pll1_ref_sel", };
+static const char *dram_pll2_out_sels[] = {"dram_pll2_div", 
"dram_pll1_ref_sel", };
+static const char *video2_pll2_out_sels[] = {"video2_pll2_div", 
"video2_pll1_ref_sel", };
+
+/* CCM ROOT */
+static const char *imx8mq_a53_sels[] = {"osc_25m", "arm_pll_out", 
"sys2_pll_500m", "sys2_pll_1000m",
+   "sys1_pll_800m", "sys1_pll_400m", 
"audio_pll1_out", "sys3_pll2_out", };
+
+static const char *imx8mq_vpu_sels[] = {"osc_25m", "arm_pll_out", 
"sys2_pll_500m", "sys2_pll_1000m",
+   "sys1_pll_800m", "sys1_pll_400m", 
"audio_pll1_out", "vpu_pll_out", };
+
+static const char *imx8mq_gpu_core_sels[] = {"osc_25m", "gpu_pll_out", 
"sys1_pll_800m", "sys3_pll2_out",
+"sys2_pll_1000m", 
"audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mq_gpu_shader_sels[] = {"osc_25m", "gpu_pll_out", 
"sys1_pll_800m", "sys3_pll2_out",
+  "sys2_pll_1000m", 
"audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mq_main_axi_sels[] = {"osc_25m", "sys2_pll_333m", 
"sys1_pll_800m", "sys2_pll_250m",
+"sys2_pll_1000m", 
"audio_pll1_out", "video_pll1_out", "sys1_pll_100m",};
+
+static const ch

[PATCH v5 0/5] Add i.MX8MQ clock driver

2018-08-17 Thread Abel Vesa
Fourth version can be found here:

https://lore.kernel.org/patchwork/cover/974998/

Changes since v4:
 * Implemented divider ops and used clk-composite as suggested
   by Sascha Hauer.

Changes since v3:
 * Added a composite clock type to get rid of some complexity
   from clk-imx8mq. This new composite clock type will also be
   used by all the imx8 socs that will follow.
 * Added back the reviewed-by tag.

Abel Vesa (1):
  clk: imx: add imx composite clock

Lucas Stach (4):
  dt-bindings: add binding for i.MX8MQ CCM
  clk: imx: add fractional PLL output clock
  clk: imx: add SCCG PLL type
  clk: imx: add clock driver for i.MX8MQ CCM

 .../devicetree/bindings/clock/imx8mq-clock.txt |  20 +
 drivers/clk/imx/Makefile   |   6 +-
 drivers/clk/imx/clk-composite.c| 126 
 drivers/clk/imx/clk-frac-pll.c | 230 
 drivers/clk/imx/clk-imx8mq.c   | 631 +
 drivers/clk/imx/clk-sccg-pll.c | 231 
 drivers/clk/imx/clk.h  |  57 ++
 include/dt-bindings/clock/imx8mq-clock.h   | 410 +
 8 files changed, 1710 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/imx8mq-clock.txt
 create mode 100644 drivers/clk/imx/clk-composite.c
 create mode 100644 drivers/clk/imx/clk-frac-pll.c
 create mode 100644 drivers/clk/imx/clk-imx8mq.c
 create mode 100644 drivers/clk/imx/clk-sccg-pll.c
 create mode 100644 include/dt-bindings/clock/imx8mq-clock.h

-- 
2.7.4



[PATCH v5 1/5] dt-bindings: add binding for i.MX8MQ CCM

2018-08-17 Thread Abel Vesa
From: Lucas Stach 

This adds the binding for the i.MX8MQ Clock Controller Module.

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
Reviewed-by: Rob Herring 
---
 .../devicetree/bindings/clock/imx8mq-clock.txt |  20 +
 include/dt-bindings/clock/imx8mq-clock.h   | 410 +
 2 files changed, 430 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/imx8mq-clock.txt
 create mode 100644 include/dt-bindings/clock/imx8mq-clock.h

diff --git a/Documentation/devicetree/bindings/clock/imx8mq-clock.txt 
b/Documentation/devicetree/bindings/clock/imx8mq-clock.txt
new file mode 100644
index 000..52de826
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/imx8mq-clock.txt
@@ -0,0 +1,20 @@
+* Clock bindings for NXP i.MX8M Quad
+
+Required properties:
+- compatible: Should be "fsl,imx8mq-ccm"
+- reg: Address and length of the register set
+- #clock-cells: Should be <1>
+- clocks: list of clock specifiers, must contain an entry for each required
+  entry in clock-names
+- clock-names: should include the following entries:
+- "ckil"
+- "osc_25m"
+- "osc_27m"
+- "clk_ext1"
+- "clk_ext2"
+- "clk_ext3"
+- "clk_ext4"
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell.  See include/dt-bindings/clock/imx8mq-clock.h
+for the full list of i.MX8M Quad clock IDs.
diff --git a/include/dt-bindings/clock/imx8mq-clock.h 
b/include/dt-bindings/clock/imx8mq-clock.h
new file mode 100644
index 000..0d19bd9
--- /dev/null
+++ b/include/dt-bindings/clock/imx8mq-clock.h
@@ -0,0 +1,410 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_IMX8MQ_H
+#define __DT_BINDINGS_CLOCK_IMX8MQ_H
+
+#define IMX8MQ_CLK_DUMMY   0
+#define IMX8MQ_CLK_32K 1
+#define IMX8MQ_CLK_25M 2
+#define IMX8MQ_CLK_27M 3
+#define IMX8MQ_CLK_EXT14
+#define IMX8MQ_CLK_EXT25
+#define IMX8MQ_CLK_EXT36
+#define IMX8MQ_CLK_EXT47
+
+/* ANAMIX PLL clocks */
+/* FRAC PLLs */
+/* ARM PLL */
+#define IMX8MQ_ARM_PLL_REF_SEL 8
+#define IMX8MQ_ARM_PLL_REF_DIV 9
+#define IMX8MQ_ARM_PLL 10
+#define IMX8MQ_ARM_PLL_BYPASS  11
+#define IMX8MQ_ARM_PLL_OUT 12
+
+/* GPU PLL */
+#define IMX8MQ_GPU_PLL_REF_SEL 13
+#define IMX8MQ_GPU_PLL_REF_DIV 14
+#define IMX8MQ_GPU_PLL 15
+#define IMX8MQ_GPU_PLL_BYPASS  16
+#define IMX8MQ_GPU_PLL_OUT 17
+
+/* VPU PLL */
+#define IMX8MQ_VPU_PLL_REF_SEL 18
+#define IMX8MQ_VPU_PLL_REF_DIV 19
+#define IMX8MQ_VPU_PLL 20
+#define IMX8MQ_VPU_PLL_BYPASS  21
+#define IMX8MQ_VPU_PLL_OUT 22
+
+/* AUDIO PLL1 */
+#define IMX8MQ_AUDIO_PLL1_REF_SEL  23
+#define IMX8MQ_AUDIO_PLL1_REF_DIV  24
+#define IMX8MQ_AUDIO_PLL1  25
+#define IMX8MQ_AUDIO_PLL1_BYPASS   26
+#define IMX8MQ_AUDIO_PLL1_OUT  27
+
+/* AUDIO PLL2 */
+#define IMX8MQ_AUDIO_PLL2_REF_SEL  28
+#define IMX8MQ_AUDIO_PLL2_REF_DIV  29
+#define IMX8MQ_AUDIO_PLL2  30
+#define IMX8MQ_AUDIO_PLL2_BYPASS   31
+#define IMX8MQ_AUDIO_PLL2_OUT  32
+
+/* VIDEO PLL1 */
+#define IMX8MQ_VIDEO_PLL1_REF_SEL  33
+#define IMX8MQ_VIDEO_PLL1_REF_DIV  34
+#define IMX8MQ_VIDEO_PLL1  35
+#define IMX8MQ_VIDEO_PLL1_BYPASS   36
+#define IMX8MQ_VIDEO_PLL1_OUT  37
+
+/* SYS1 PLL */
+#define IMX8MQ_SYS1_PLL1_REF_SEL   38
+#define IMX8MQ_SYS1_PLL1_REF_DIV   39
+#define IMX8MQ_SYS1_PLL1   40
+#define IMX8MQ_SYS1_PLL1_OUT   41
+#define IMX8MQ_SYS1_PLL1_OUT_DIV   42
+#define IMX8MQ_SYS1_PLL2   43
+#define IMX8MQ_SYS1_PLL2_DIV   44
+#define IMX8MQ_SYS1_PLL2_OUT   45
+
+/* SYS2 PLL */
+#define IMX8MQ_SYS2_PLL1_REF_SEL   46
+#define IMX8MQ_SYS2_PLL1_REF_DIV   47
+#define IMX8MQ_SYS2_PLL1   48
+#define IMX8MQ_SYS2_PLL1_OUT   49
+#define IMX8MQ_SYS2_PLL1_OUT_DIV   50
+#define IMX8MQ_SYS2_PLL2   51
+#define IMX8MQ_SYS2_PLL2_DIV   52
+#define IMX8MQ_SYS2_PLL2_OUT   53
+
+/* SYS3 PLL */
+#define IMX8MQ_SYS3_PLL1_REF_SEL   54
+#define IMX8MQ_SYS3_PLL1_REF_DIV   55
+#define IMX8MQ_SYS3_PLL1   56
+#define IMX8MQ_SYS3_PLL1_OUT   57
+#define IMX8MQ_SYS3_PLL1_OUT_DIV   58
+#define IMX8MQ_SYS3_PLL2   59
+#define IMX8MQ_SYS3_PLL2_DIV   60
+#define IMX8MQ_SYS3_PLL2_OUT   61
+
+/* DRAM PLL */
+#define IMX8MQ_DRAM_PLL1_REF_SEL   62
+#define IMX8MQ_DRAM_PLL1_REF_DIV   63
+#define IMX8MQ_DRAM_PLL1   64
+#define IMX8MQ

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

2018-08-17 Thread Abel Vesa
From: Lucas Stach 

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

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/Makefile   |   1 +
 drivers/clk/imx/clk-frac-pll.c | 230 +
 drivers/clk/imx/clk.h  |   3 +
 3 files changed, 234 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..c80c6ed
--- /dev/null
+++ b/drivers/clk/imx/clk-frac-pll.c
@@ -0,0 +1,230 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 NXP.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+#define PLL_CFG0   0x0
+#define PLL_CFG1   0x4
+
+#define PLL_LOCK_STATUSBIT(31)
+#define PLL_PD 19
+#define PLL_PD_MASKBIT(PLL_PD)
+#define PLL_BYPASS 14
+#define PLL_BYPASS_MASKBIT(PLL_BYPASS)
+#define PLL_NEWDIV_VAL BIT(12)
+#define PLL_NEWDIV_ACK BIT(11)
+#define PLL_FRAC_DIV_MASK  0xff
+#define PLL_INT_DIV_MASK   0x7f
+#define PLL_OUTPUT_DIV_MASK0x1f
+#define PLL_FRAC_DENOM 0x100
+
+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)
+{
+   unsigned long timeout = jiffies + msecs_to_jiffies(10);
+   u32 val;
+
+   /* Wait for PLL to lock */
+   do {
+   if (readl_relaxed(pll->base) & PLL_LOCK_STATUS)
+   break;
+   if (time_after(jiffies, timeout))
+   break;
+   } while (1);
+
+   return readl_poll_timeout(pll->base, val,
+   val & PLL_LOCK_STATUS, 0, 1000);
+}
+
+static int clk_wait_ack(struct clk_frac_pll *pll)
+{
+   unsigned long timeout = jiffies + msecs_to_jiffies(50);
+   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 */
+   do {
+   if (readl_relaxed(pll->base) & PLL_NEWDIV_ACK)
+   break;
+   if (time_after(jiffies, timeout))
+   break;
+   } while (1);
+
+   return readl_poll_timeout(pll->base, val,
+   val & PLL_NEWDIV_ACK, 0, 1000);
+}
+
+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;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   divq = ((val & PLL_OUTPUT_DIV_MASK) + 1) * 2;
+   val = readl_relaxed(pll->base + PLL_CFG1);
+   divff = (val >> 7) & PLL_FRAC_DIV_MASK;
+   divfi = (val & PLL_INT_DIV_MASK);
+
+   temp64 = (u64)parent_rate * 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)
+{
+   unsigned long parent_rate = *prate;
+   u32 divff, divfi;
+   u64 temp64;
+
+   parent_rate *= 8;
+   rate *= 2;
+   divfi = rate / parent_rate;
+   temp64 = (u64)(rate - divfi * parent_rate);
+   temp64 *= PLL_FRAC_DENOM;
+   do_div(

[PATCH v5 4/5] clk: imx: add imx composite clock

2018-08-17 Thread Abel Vesa
Since a lot of clocks on imx8 are formed by a mux, gate, predivider and
divider, the idea here is to combine all of those into one more complex
clock type, therefore moving the complexity inside the composite clock and
outside of the SoC specific clock driver.

Signed-off-by: Abel Vesa 
Suggested-by: Sascha Hauer 
---
 drivers/clk/imx/Makefile|   1 +
 drivers/clk/imx/clk-composite.c | 126 
 drivers/clk/imx/clk.h   |   9 +++
 3 files changed, 136 insertions(+)
 create mode 100644 drivers/clk/imx/clk-composite.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index b87513c..4fabb0a 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -3,6 +3,7 @@
 obj-y += \
clk.o \
clk-busy.o \
+   clk-composite.o \
clk-cpu.o \
clk-fixup-div.o \
clk-fixup-mux.o \
diff --git a/drivers/clk/imx/clk-composite.c b/drivers/clk/imx/clk-composite.c
new file mode 100644
index 000..717c6f1
--- /dev/null
+++ b/drivers/clk/imx/clk-composite.c
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 NXP
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+#define PCG_PREDIV_SHIFT   16
+#define PCG_PREDIV_WIDTH   3
+
+#define PCG_DIV_SHIFT  0
+#define PCG_DIV_WIDTH  6
+
+#define PCG_PCS_SHIFT  24
+#define PCG_PCS_MASK   0x7
+
+#define PCG_CGC_SHIFT  28
+
+static unsigned long imx_clk_composite_divider_recalc_rate(struct clk_hw *hw,
+   unsigned long parent_rate)
+{
+   return clk_divider_ops.recalc_rate(hw, parent_rate);
+}
+
+static long imx_clk_composite_divider_round_rate(struct clk_hw *hw,
+   unsigned long rate,
+   unsigned long *prate)
+{
+   return clk_divider_ops.round_rate(hw, rate, prate);
+}
+
+static int imx_clk_composite_divider_set_rate(struct clk_hw *hw,
+   unsigned long rate,
+   unsigned long parent_rate)
+{
+   struct clk_divider *divider = to_clk_divider(hw);
+   int value;
+   unsigned long flags = 0;
+   u32 val;
+
+   value = divider_get_val(rate, parent_rate, NULL,
+   PCG_PREDIV_WIDTH, CLK_DIVIDER_ROUND_CLOSEST);
+   if (value < 0)
+   return value;
+
+   spin_lock_irqsave(divider->lock, flags);
+
+   val = clk_readl(divider->reg);
+   val &= ~((clk_div_mask(divider->width) << divider->shift) |
+   (clk_div_mask(PCG_DIV_WIDTH) << PCG_DIV_SHIFT));
+
+   val |= (u32)value << divider->shift;
+   val |= (u32)value << PCG_DIV_SHIFT;
+   clk_writel(val, divider->reg);
+
+   spin_unlock_irqrestore(divider->lock, flags);
+
+   return 0;
+}
+
+static const struct clk_ops imx_clk_composite_divider_ops = {
+   .recalc_rate = imx_clk_composite_divider_recalc_rate,
+   .round_rate = imx_clk_composite_divider_round_rate,
+   .set_rate = imx_clk_composite_divider_set_rate,
+};
+
+struct clk *imx_clk_composite_flags(const char *name,
+   const char **parent_names,
+   int num_parents, void __iomem *reg,
+   unsigned long flags)
+{
+   struct clk_hw *mux_hw = NULL, *div_hw = NULL, *gate_hw = NULL;
+   struct clk_divider *div = NULL;
+   struct clk_gate *gate = NULL;
+   struct clk_mux *mux = NULL;
+   struct clk *clk;
+
+   mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+   if (!mux)
+   return ERR_PTR(-ENOMEM);
+   mux_hw = &mux->hw;
+   mux->reg = reg;
+   mux->shift = PCG_PCS_SHIFT;
+   mux->mask = PCG_PCS_MASK;
+
+   div = kzalloc(sizeof(*div), GFP_KERNEL);
+   if (!div) {
+   kfree(mux);
+   return ERR_PTR(-ENOMEM);
+   }
+   div_hw = &div->hw;
+   div->reg = reg;
+   div->shift = PCG_PREDIV_SHIFT;
+   div->width = PCG_PREDIV_WIDTH;
+   div->lock = &imx_ccm_lock;
+   div->flags = CLK_DIVIDER_ROUND_CLOSEST;
+
+   gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+   if (!gate) {
+   kfree(mux);
+   kfree(div);
+   return ERR_PTR(-ENOMEM);
+   }
+   gate_hw = &gate->hw;
+   gate->reg = reg;
+   gate->bit_idx = PCG_CGC_SHIFT;
+
+   flags |= CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE;
+
+   clk = clk_register_composite(NULL, name, parent_names, num_parents,
+   mux_hw, &clk_mux_ops, div_hw,
+   &imx_clk_composite_divider_ops, gate_hw,
+   &cl

[PATCH v5 3/5] clk: imx: add SCCG PLL type

2018-08-17 Thread Abel Vesa
From: Lucas Stach 

The SCCG is a new PLL type introduced on i.MX8. Add support for this.
The driver currently misses the PLL lock check, as the preliminary
documentation mentions lock configurations, but is quiet about where
to find the actual lock status signal.

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/Makefile   |   3 +-
 drivers/clk/imx/clk-sccg-pll.c | 231 +
 drivers/clk/imx/clk.h  |   9 ++
 3 files changed, 242 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/imx/clk-sccg-pll.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 4893c1f..b87513c 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -12,7 +12,8 @@ obj-y += \
clk-pllv1.o \
clk-pllv2.o \
clk-pllv3.o \
-   clk-pfd.o
+   clk-pfd.o \
+   clk-sccg-pll.o
 
 obj-$(CONFIG_SOC_IMX1)   += clk-imx1.o
 obj-$(CONFIG_SOC_IMX21)  += clk-imx21.o
diff --git a/drivers/clk/imx/clk-sccg-pll.c b/drivers/clk/imx/clk-sccg-pll.c
new file mode 100644
index 000..886ae03
--- /dev/null
+++ b/drivers/clk/imx/clk-sccg-pll.c
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2018 NXP.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+/* PLL CFGs */
+#define PLL_CFG0   0x0
+#define PLL_CFG1   0x4
+#define PLL_CFG2   0x8
+
+#define PLL_DIVF1_SHIFT13
+#define PLL_DIVF2_SHIFT7
+#define PLL_DIVF_MASK  0x3f
+
+#define PLL_DIVR1_SHIFT25
+#define PLL_DIVR2_SHIFT19
+#define PLL_DIVR1_MASK 0x3
+#define PLL_DIVR2_MASK 0x3f
+#define PLL_REF_SHIFT  0
+#define PLL_REF_MASK   0x3
+
+#define PLL_LOCK   31
+#define PLL_PD 7
+
+#define OSC_25M2500
+#define OSC_27M2700
+
+struct clk_sccg_pll {
+   struct clk_hw   hw;
+   void __iomem*base;
+};
+
+#define to_clk_sccg_pll(_hw) container_of(_hw, struct clk_sccg_pll, hw)
+
+static int clk_pll1_is_prepared(struct clk_hw *hw)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   return (val & (1 << PLL_PD)) ? 0 : 1;
+}
+
+static unsigned long clk_pll1_recalc_rate(struct clk_hw *hw,
+unsigned long parent_rate)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val, divf;
+
+   val = readl_relaxed(pll->base + PLL_CFG2);
+   divf = (val >> PLL_DIVF1_SHIFT) & PLL_DIVF_MASK;
+
+   return parent_rate * 2 * (divf + 1);
+}
+
+static long clk_pll1_round_rate(struct clk_hw *hw, unsigned long rate,
+  unsigned long *prate)
+{
+   unsigned long parent_rate = *prate;
+   u32 div;
+
+   div = rate / (parent_rate * 2);
+
+   return parent_rate * div * 2;
+}
+
+static int clk_pll1_set_rate(struct clk_hw *hw, unsigned long rate,
+   unsigned long parent_rate)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+   u32 divf;
+
+   divf = rate / (parent_rate * 2);
+
+   val = readl_relaxed(pll->base + PLL_CFG2);
+   val &= ~(PLL_DIVF_MASK << PLL_DIVF1_SHIFT);
+   val |= (divf - 1) << PLL_DIVF1_SHIFT;
+   writel_relaxed(val, pll->base + PLL_CFG2);
+
+   /* FIXME: PLL lock check */
+
+   return 0;
+}
+
+static int clk_pll1_prepare(struct clk_hw *hw)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base);
+   val &= ~(1 << PLL_PD);
+   writel_relaxed(val, pll->base);
+
+   /* FIXME: PLL lock check */
+
+   return 0;
+}
+
+static void clk_pll1_unprepare(struct clk_hw *hw)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base);
+   val |= (1 << PLL_PD);
+   writel_relaxed(val, pll->base);
+}
+
+static unsigned long clk_pll2_recalc_rate(struct clk_hw *hw,
+unsigned long parent_rate)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val, ref, divr1, divf1, divr2, divf2;
+   u64 temp64;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   switch ((val >> PLL_REF_SHIFT) & PLL_REF_MASK) {
+   case 0:
+   ref = OSC_25M;
+   break;
+   case 1:
+   ref = OSC_27M;
+   break;
+   default:
+   ref = OSC_25M;
+   break;
+   }
+
+   val = readl_relaxed(pll->base + PLL_CFG2);
+   divr1 = (val >> PLL_DIVR1_SHIFT) & PLL_DIVR1_MASK;
+   divr2 = (val >> PLL_DIVR2_SHIFT) & PLL_DIVR2_MASK;
+   divf1 = (val >> PLL_DIVF1_SHIFT) & PLL_DIVF_MASK;
+   divf2 = (val >> PLL_DIVF2_SHIFT) & PLL_DIVF_MASK;
+
+   temp6

[PATCH v5 5/5] clk: imx: add clock driver for i.MX8MQ CCM

2018-08-17 Thread Abel Vesa
From: Lucas Stach 

Add driver for the Clock Control Module found on i.MX8MQ.

This is largely based on the downstream driver from Anson Huang and
Bai Ping at NXP, with only some small adaptions to mainline from me.

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/Makefile |   1 +
 drivers/clk/imx/clk-imx8mq.c | 631 +++
 drivers/clk/imx/clk.h|  36 +++
 3 files changed, 668 insertions(+)
 create mode 100644 drivers/clk/imx/clk-imx8mq.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 4fabb0a..64e695c 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -30,3 +30,4 @@ obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o
 obj-$(CONFIG_SOC_IMX6UL) += clk-imx6ul.o
 obj-$(CONFIG_SOC_IMX7D)  += clk-imx7d.o
 obj-$(CONFIG_SOC_VF610)  += clk-vf610.o
+obj-$(CONFIG_SOC_IMX8MQ) += clk-imx8mq.o
diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c
new file mode 100644
index 000..d3a9e31
--- /dev/null
+++ b/drivers/clk/imx/clk-imx8mq.c
@@ -0,0 +1,631 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 NXP.
+ * Copyright (C) 2017 Pengutronix, Lucas Stach 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+static u32 share_count_sai1;
+static u32 share_count_sai2;
+static u32 share_count_sai3;
+static u32 share_count_sai4;
+static u32 share_count_sai5;
+static u32 share_count_sai6;
+static u32 share_count_dcss;
+static u32 share_count_nand;
+
+static struct clk *clks[IMX8MQ_CLK_END];
+
+static const char *pll_ref_sels[] = { "osc_25m", "osc_27m", "dummy", "dummy", 
};
+static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
+static const char *gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
+static const char *vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", };
+static const char *audio_pll1_bypass_sels[] = {"audio_pll1", 
"audio_pll1_ref_sel", };
+static const char *audio_pll2_bypass_sels[] = {"audio_pll2", 
"audio_pll2_ref_sel", };
+static const char *video_pll1_bypass_sels[] = {"video_pll1", 
"video_pll1_ref_sel", };
+
+static const char *sys1_pll1_out_sels[] = {"sys1_pll1", "sys1_pll1_ref_sel", };
+static const char *sys2_pll1_out_sels[] = {"sys2_pll1", "sys1_pll1_ref_sel", };
+static const char *sys3_pll1_out_sels[] = {"sys3_pll1", "sys3_pll1_ref_sel", };
+static const char *dram_pll1_out_sels[] = {"dram_pll1", "dram_pll1_ref_sel", };
+static const char *video2_pll1_out_sels[] = {"video2_pll1", 
"video2_pll1_ref_sel", };
+
+static const char *sys1_pll2_out_sels[] = {"sys1_pll2_div", 
"sys1_pll1_ref_sel", };
+static const char *sys2_pll2_out_sels[] = {"sys2_pll2_div", 
"sys2_pll1_ref_sel", };
+static const char *sys3_pll2_out_sels[] = {"sys3_pll2_div", 
"sys2_pll1_ref_sel", };
+static const char *dram_pll2_out_sels[] = {"dram_pll2_div", 
"dram_pll1_ref_sel", };
+static const char *video2_pll2_out_sels[] = {"video2_pll2_div", 
"video2_pll1_ref_sel", };
+
+/* CCM ROOT */
+static const char *imx8mq_a53_sels[] = {"osc_25m", "arm_pll_out", 
"sys2_pll_500m", "sys2_pll_1000m",
+   "sys1_pll_800m", "sys1_pll_400m", 
"audio_pll1_out", "sys3_pll2_out", };
+
+static const char *imx8mq_vpu_sels[] = {"osc_25m", "arm_pll_out", 
"sys2_pll_500m", "sys2_pll_1000m",
+   "sys1_pll_800m", "sys1_pll_400m", 
"audio_pll1_out", "vpu_pll_out", };
+
+static const char *imx8mq_gpu_core_sels[] = {"osc_25m", "gpu_pll_out", 
"sys1_pll_800m", "sys3_pll2_out",
+"sys2_pll_1000m", 
"audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mq_gpu_shader_sels[] = {"osc_25m", "gpu_pll_out", 
"sys1_pll_800m", "sys3_pll2_out",
+  "sys2_pll_1000m", 
"audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mq_main_axi_sels[] = {"osc_25m", "sys2_pll_333m", 
"sys1_pll_800m", "sys2_pll_250m",
+"sys2_pll_1000m", 
"audio_pll1_out", "video_pll1_out", "sys1_pll_100m",};
+
+static const ch

[RESEND v5 2/5] clk: imx: add fractional PLL output clock

2018-08-20 Thread Abel Vesa
From: Lucas Stach 

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

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/Makefile   |   1 +
 drivers/clk/imx/clk-frac-pll.c | 230 +
 drivers/clk/imx/clk.h  |   3 +
 3 files changed, 234 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..c80c6ed
--- /dev/null
+++ b/drivers/clk/imx/clk-frac-pll.c
@@ -0,0 +1,230 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 NXP.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+#define PLL_CFG0   0x0
+#define PLL_CFG1   0x4
+
+#define PLL_LOCK_STATUSBIT(31)
+#define PLL_PD 19
+#define PLL_PD_MASKBIT(PLL_PD)
+#define PLL_BYPASS 14
+#define PLL_BYPASS_MASKBIT(PLL_BYPASS)
+#define PLL_NEWDIV_VAL BIT(12)
+#define PLL_NEWDIV_ACK BIT(11)
+#define PLL_FRAC_DIV_MASK  0xff
+#define PLL_INT_DIV_MASK   0x7f
+#define PLL_OUTPUT_DIV_MASK0x1f
+#define PLL_FRAC_DENOM 0x100
+
+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)
+{
+   unsigned long timeout = jiffies + msecs_to_jiffies(10);
+   u32 val;
+
+   /* Wait for PLL to lock */
+   do {
+   if (readl_relaxed(pll->base) & PLL_LOCK_STATUS)
+   break;
+   if (time_after(jiffies, timeout))
+   break;
+   } while (1);
+
+   return readl_poll_timeout(pll->base, val,
+   val & PLL_LOCK_STATUS, 0, 1000);
+}
+
+static int clk_wait_ack(struct clk_frac_pll *pll)
+{
+   unsigned long timeout = jiffies + msecs_to_jiffies(50);
+   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 */
+   do {
+   if (readl_relaxed(pll->base) & PLL_NEWDIV_ACK)
+   break;
+   if (time_after(jiffies, timeout))
+   break;
+   } while (1);
+
+   return readl_poll_timeout(pll->base, val,
+   val & PLL_NEWDIV_ACK, 0, 1000);
+}
+
+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;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   divq = ((val & PLL_OUTPUT_DIV_MASK) + 1) * 2;
+   val = readl_relaxed(pll->base + PLL_CFG1);
+   divff = (val >> 7) & PLL_FRAC_DIV_MASK;
+   divfi = (val & PLL_INT_DIV_MASK);
+
+   temp64 = (u64)parent_rate * 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)
+{
+   unsigned long parent_rate = *prate;
+   u32 divff, divfi;
+   u64 temp64;
+
+   parent_rate *= 8;
+   rate *= 2;
+   divfi = rate / parent_rate;
+   temp64 = (u64)(rate - divfi * parent_rate);
+   temp64 *= PLL_FRAC_DENOM;
+   do_div(

[RESEND v5 3/5] clk: imx: add SCCG PLL type

2018-08-20 Thread Abel Vesa
From: Lucas Stach 

The SCCG is a new PLL type introduced on i.MX8. Add support for this.
The driver currently misses the PLL lock check, as the preliminary
documentation mentions lock configurations, but is quiet about where
to find the actual lock status signal.

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/Makefile   |   3 +-
 drivers/clk/imx/clk-sccg-pll.c | 231 +
 drivers/clk/imx/clk.h  |   9 ++
 3 files changed, 242 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/imx/clk-sccg-pll.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 4893c1f..b87513c 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -12,7 +12,8 @@ obj-y += \
clk-pllv1.o \
clk-pllv2.o \
clk-pllv3.o \
-   clk-pfd.o
+   clk-pfd.o \
+   clk-sccg-pll.o
 
 obj-$(CONFIG_SOC_IMX1)   += clk-imx1.o
 obj-$(CONFIG_SOC_IMX21)  += clk-imx21.o
diff --git a/drivers/clk/imx/clk-sccg-pll.c b/drivers/clk/imx/clk-sccg-pll.c
new file mode 100644
index 000..886ae03
--- /dev/null
+++ b/drivers/clk/imx/clk-sccg-pll.c
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2018 NXP.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+/* PLL CFGs */
+#define PLL_CFG0   0x0
+#define PLL_CFG1   0x4
+#define PLL_CFG2   0x8
+
+#define PLL_DIVF1_SHIFT13
+#define PLL_DIVF2_SHIFT7
+#define PLL_DIVF_MASK  0x3f
+
+#define PLL_DIVR1_SHIFT25
+#define PLL_DIVR2_SHIFT19
+#define PLL_DIVR1_MASK 0x3
+#define PLL_DIVR2_MASK 0x3f
+#define PLL_REF_SHIFT  0
+#define PLL_REF_MASK   0x3
+
+#define PLL_LOCK   31
+#define PLL_PD 7
+
+#define OSC_25M2500
+#define OSC_27M2700
+
+struct clk_sccg_pll {
+   struct clk_hw   hw;
+   void __iomem*base;
+};
+
+#define to_clk_sccg_pll(_hw) container_of(_hw, struct clk_sccg_pll, hw)
+
+static int clk_pll1_is_prepared(struct clk_hw *hw)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   return (val & (1 << PLL_PD)) ? 0 : 1;
+}
+
+static unsigned long clk_pll1_recalc_rate(struct clk_hw *hw,
+unsigned long parent_rate)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val, divf;
+
+   val = readl_relaxed(pll->base + PLL_CFG2);
+   divf = (val >> PLL_DIVF1_SHIFT) & PLL_DIVF_MASK;
+
+   return parent_rate * 2 * (divf + 1);
+}
+
+static long clk_pll1_round_rate(struct clk_hw *hw, unsigned long rate,
+  unsigned long *prate)
+{
+   unsigned long parent_rate = *prate;
+   u32 div;
+
+   div = rate / (parent_rate * 2);
+
+   return parent_rate * div * 2;
+}
+
+static int clk_pll1_set_rate(struct clk_hw *hw, unsigned long rate,
+   unsigned long parent_rate)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+   u32 divf;
+
+   divf = rate / (parent_rate * 2);
+
+   val = readl_relaxed(pll->base + PLL_CFG2);
+   val &= ~(PLL_DIVF_MASK << PLL_DIVF1_SHIFT);
+   val |= (divf - 1) << PLL_DIVF1_SHIFT;
+   writel_relaxed(val, pll->base + PLL_CFG2);
+
+   /* FIXME: PLL lock check */
+
+   return 0;
+}
+
+static int clk_pll1_prepare(struct clk_hw *hw)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base);
+   val &= ~(1 << PLL_PD);
+   writel_relaxed(val, pll->base);
+
+   /* FIXME: PLL lock check */
+
+   return 0;
+}
+
+static void clk_pll1_unprepare(struct clk_hw *hw)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val;
+
+   val = readl_relaxed(pll->base);
+   val |= (1 << PLL_PD);
+   writel_relaxed(val, pll->base);
+}
+
+static unsigned long clk_pll2_recalc_rate(struct clk_hw *hw,
+unsigned long parent_rate)
+{
+   struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+   u32 val, ref, divr1, divf1, divr2, divf2;
+   u64 temp64;
+
+   val = readl_relaxed(pll->base + PLL_CFG0);
+   switch ((val >> PLL_REF_SHIFT) & PLL_REF_MASK) {
+   case 0:
+   ref = OSC_25M;
+   break;
+   case 1:
+   ref = OSC_27M;
+   break;
+   default:
+   ref = OSC_25M;
+   break;
+   }
+
+   val = readl_relaxed(pll->base + PLL_CFG2);
+   divr1 = (val >> PLL_DIVR1_SHIFT) & PLL_DIVR1_MASK;
+   divr2 = (val >> PLL_DIVR2_SHIFT) & PLL_DIVR2_MASK;
+   divf1 = (val >> PLL_DIVF1_SHIFT) & PLL_DIVF_MASK;
+   divf2 = (val >> PLL_DIVF2_SHIFT) & PLL_DIVF_MASK;
+
+   temp6

[RESEND v5 1/5] dt-bindings: add binding for i.MX8MQ CCM

2018-08-20 Thread Abel Vesa
From: Lucas Stach 

This adds the binding for the i.MX8MQ Clock Controller Module.

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
Reviewed-by: Rob Herring 
---
 .../devicetree/bindings/clock/imx8mq-clock.txt |  20 +
 include/dt-bindings/clock/imx8mq-clock.h   | 410 +
 2 files changed, 430 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/imx8mq-clock.txt
 create mode 100644 include/dt-bindings/clock/imx8mq-clock.h

diff --git a/Documentation/devicetree/bindings/clock/imx8mq-clock.txt 
b/Documentation/devicetree/bindings/clock/imx8mq-clock.txt
new file mode 100644
index 000..52de826
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/imx8mq-clock.txt
@@ -0,0 +1,20 @@
+* Clock bindings for NXP i.MX8M Quad
+
+Required properties:
+- compatible: Should be "fsl,imx8mq-ccm"
+- reg: Address and length of the register set
+- #clock-cells: Should be <1>
+- clocks: list of clock specifiers, must contain an entry for each required
+  entry in clock-names
+- clock-names: should include the following entries:
+- "ckil"
+- "osc_25m"
+- "osc_27m"
+- "clk_ext1"
+- "clk_ext2"
+- "clk_ext3"
+- "clk_ext4"
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell.  See include/dt-bindings/clock/imx8mq-clock.h
+for the full list of i.MX8M Quad clock IDs.
diff --git a/include/dt-bindings/clock/imx8mq-clock.h 
b/include/dt-bindings/clock/imx8mq-clock.h
new file mode 100644
index 000..0d19bd9
--- /dev/null
+++ b/include/dt-bindings/clock/imx8mq-clock.h
@@ -0,0 +1,410 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_IMX8MQ_H
+#define __DT_BINDINGS_CLOCK_IMX8MQ_H
+
+#define IMX8MQ_CLK_DUMMY   0
+#define IMX8MQ_CLK_32K 1
+#define IMX8MQ_CLK_25M 2
+#define IMX8MQ_CLK_27M 3
+#define IMX8MQ_CLK_EXT14
+#define IMX8MQ_CLK_EXT25
+#define IMX8MQ_CLK_EXT36
+#define IMX8MQ_CLK_EXT47
+
+/* ANAMIX PLL clocks */
+/* FRAC PLLs */
+/* ARM PLL */
+#define IMX8MQ_ARM_PLL_REF_SEL 8
+#define IMX8MQ_ARM_PLL_REF_DIV 9
+#define IMX8MQ_ARM_PLL 10
+#define IMX8MQ_ARM_PLL_BYPASS  11
+#define IMX8MQ_ARM_PLL_OUT 12
+
+/* GPU PLL */
+#define IMX8MQ_GPU_PLL_REF_SEL 13
+#define IMX8MQ_GPU_PLL_REF_DIV 14
+#define IMX8MQ_GPU_PLL 15
+#define IMX8MQ_GPU_PLL_BYPASS  16
+#define IMX8MQ_GPU_PLL_OUT 17
+
+/* VPU PLL */
+#define IMX8MQ_VPU_PLL_REF_SEL 18
+#define IMX8MQ_VPU_PLL_REF_DIV 19
+#define IMX8MQ_VPU_PLL 20
+#define IMX8MQ_VPU_PLL_BYPASS  21
+#define IMX8MQ_VPU_PLL_OUT 22
+
+/* AUDIO PLL1 */
+#define IMX8MQ_AUDIO_PLL1_REF_SEL  23
+#define IMX8MQ_AUDIO_PLL1_REF_DIV  24
+#define IMX8MQ_AUDIO_PLL1  25
+#define IMX8MQ_AUDIO_PLL1_BYPASS   26
+#define IMX8MQ_AUDIO_PLL1_OUT  27
+
+/* AUDIO PLL2 */
+#define IMX8MQ_AUDIO_PLL2_REF_SEL  28
+#define IMX8MQ_AUDIO_PLL2_REF_DIV  29
+#define IMX8MQ_AUDIO_PLL2  30
+#define IMX8MQ_AUDIO_PLL2_BYPASS   31
+#define IMX8MQ_AUDIO_PLL2_OUT  32
+
+/* VIDEO PLL1 */
+#define IMX8MQ_VIDEO_PLL1_REF_SEL  33
+#define IMX8MQ_VIDEO_PLL1_REF_DIV  34
+#define IMX8MQ_VIDEO_PLL1  35
+#define IMX8MQ_VIDEO_PLL1_BYPASS   36
+#define IMX8MQ_VIDEO_PLL1_OUT  37
+
+/* SYS1 PLL */
+#define IMX8MQ_SYS1_PLL1_REF_SEL   38
+#define IMX8MQ_SYS1_PLL1_REF_DIV   39
+#define IMX8MQ_SYS1_PLL1   40
+#define IMX8MQ_SYS1_PLL1_OUT   41
+#define IMX8MQ_SYS1_PLL1_OUT_DIV   42
+#define IMX8MQ_SYS1_PLL2   43
+#define IMX8MQ_SYS1_PLL2_DIV   44
+#define IMX8MQ_SYS1_PLL2_OUT   45
+
+/* SYS2 PLL */
+#define IMX8MQ_SYS2_PLL1_REF_SEL   46
+#define IMX8MQ_SYS2_PLL1_REF_DIV   47
+#define IMX8MQ_SYS2_PLL1   48
+#define IMX8MQ_SYS2_PLL1_OUT   49
+#define IMX8MQ_SYS2_PLL1_OUT_DIV   50
+#define IMX8MQ_SYS2_PLL2   51
+#define IMX8MQ_SYS2_PLL2_DIV   52
+#define IMX8MQ_SYS2_PLL2_OUT   53
+
+/* SYS3 PLL */
+#define IMX8MQ_SYS3_PLL1_REF_SEL   54
+#define IMX8MQ_SYS3_PLL1_REF_DIV   55
+#define IMX8MQ_SYS3_PLL1   56
+#define IMX8MQ_SYS3_PLL1_OUT   57
+#define IMX8MQ_SYS3_PLL1_OUT_DIV   58
+#define IMX8MQ_SYS3_PLL2   59
+#define IMX8MQ_SYS3_PLL2_DIV   60
+#define IMX8MQ_SYS3_PLL2_OUT   61
+
+/* DRAM PLL */
+#define IMX8MQ_DRAM_PLL1_REF_SEL   62
+#define IMX8MQ_DRAM_PLL1_REF_DIV   63
+#define IMX8MQ_DRAM_PLL1   64
+#define IMX8MQ

[RESEND v5 0/5] Add i.MX8MQ clock driver

2018-08-20 Thread Abel Vesa
Resent this time on the right list (linux-clk instead of linux-gpio).

Fourth version can be found here:

https://lore.kernel.org/patchwork/cover/974998/

Changes since v4:
 * Implemented divider ops and used clk-composite as suggested
   by Sascha Hauer.

Changes since v3:
 * Added a composite clock type to get rid of some complexity
   from clk-imx8mq. This new composite clock type will also be
   used by all the imx8 socs that will follow.
 * Added back the reviewed-by tag.

Abel Vesa (1):
  clk: imx: add imx composite clock

Lucas Stach (4):
  dt-bindings: add binding for i.MX8MQ CCM
  clk: imx: add fractional PLL output clock
  clk: imx: add SCCG PLL type
  clk: imx: add clock driver for i.MX8MQ CCM

 .../devicetree/bindings/clock/imx8mq-clock.txt |  20 +
 drivers/clk/imx/Makefile   |   6 +-
 drivers/clk/imx/clk-composite.c| 126 
 drivers/clk/imx/clk-frac-pll.c | 230 
 drivers/clk/imx/clk-imx8mq.c   | 631 +
 drivers/clk/imx/clk-sccg-pll.c | 231 
 drivers/clk/imx/clk.h  |  57 ++
 include/dt-bindings/clock/imx8mq-clock.h   | 410 +
 8 files changed, 1710 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/imx8mq-clock.txt
 create mode 100644 drivers/clk/imx/clk-composite.c
 create mode 100644 drivers/clk/imx/clk-frac-pll.c
 create mode 100644 drivers/clk/imx/clk-imx8mq.c
 create mode 100644 drivers/clk/imx/clk-sccg-pll.c
 create mode 100644 include/dt-bindings/clock/imx8mq-clock.h

-- 
2.7.4



[RESEND v5 4/5] clk: imx: add imx composite clock

2018-08-20 Thread Abel Vesa
Since a lot of clocks on imx8 are formed by a mux, gate, predivider and
divider, the idea here is to combine all of those into one more complex
clock type, therefore moving the complexity inside the composite clock and
outside of the SoC specific clock driver.

Signed-off-by: Abel Vesa 
Suggested-by: Sascha Hauer 
---
 drivers/clk/imx/Makefile|   1 +
 drivers/clk/imx/clk-composite.c | 126 
 drivers/clk/imx/clk.h   |   9 +++
 3 files changed, 136 insertions(+)
 create mode 100644 drivers/clk/imx/clk-composite.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index b87513c..4fabb0a 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -3,6 +3,7 @@
 obj-y += \
clk.o \
clk-busy.o \
+   clk-composite.o \
clk-cpu.o \
clk-fixup-div.o \
clk-fixup-mux.o \
diff --git a/drivers/clk/imx/clk-composite.c b/drivers/clk/imx/clk-composite.c
new file mode 100644
index 000..717c6f1
--- /dev/null
+++ b/drivers/clk/imx/clk-composite.c
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 NXP
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+#define PCG_PREDIV_SHIFT   16
+#define PCG_PREDIV_WIDTH   3
+
+#define PCG_DIV_SHIFT  0
+#define PCG_DIV_WIDTH  6
+
+#define PCG_PCS_SHIFT  24
+#define PCG_PCS_MASK   0x7
+
+#define PCG_CGC_SHIFT  28
+
+static unsigned long imx_clk_composite_divider_recalc_rate(struct clk_hw *hw,
+   unsigned long parent_rate)
+{
+   return clk_divider_ops.recalc_rate(hw, parent_rate);
+}
+
+static long imx_clk_composite_divider_round_rate(struct clk_hw *hw,
+   unsigned long rate,
+   unsigned long *prate)
+{
+   return clk_divider_ops.round_rate(hw, rate, prate);
+}
+
+static int imx_clk_composite_divider_set_rate(struct clk_hw *hw,
+   unsigned long rate,
+   unsigned long parent_rate)
+{
+   struct clk_divider *divider = to_clk_divider(hw);
+   int value;
+   unsigned long flags = 0;
+   u32 val;
+
+   value = divider_get_val(rate, parent_rate, NULL,
+   PCG_PREDIV_WIDTH, CLK_DIVIDER_ROUND_CLOSEST);
+   if (value < 0)
+   return value;
+
+   spin_lock_irqsave(divider->lock, flags);
+
+   val = clk_readl(divider->reg);
+   val &= ~((clk_div_mask(divider->width) << divider->shift) |
+   (clk_div_mask(PCG_DIV_WIDTH) << PCG_DIV_SHIFT));
+
+   val |= (u32)value << divider->shift;
+   val |= (u32)value << PCG_DIV_SHIFT;
+   clk_writel(val, divider->reg);
+
+   spin_unlock_irqrestore(divider->lock, flags);
+
+   return 0;
+}
+
+static const struct clk_ops imx_clk_composite_divider_ops = {
+   .recalc_rate = imx_clk_composite_divider_recalc_rate,
+   .round_rate = imx_clk_composite_divider_round_rate,
+   .set_rate = imx_clk_composite_divider_set_rate,
+};
+
+struct clk *imx_clk_composite_flags(const char *name,
+   const char **parent_names,
+   int num_parents, void __iomem *reg,
+   unsigned long flags)
+{
+   struct clk_hw *mux_hw = NULL, *div_hw = NULL, *gate_hw = NULL;
+   struct clk_divider *div = NULL;
+   struct clk_gate *gate = NULL;
+   struct clk_mux *mux = NULL;
+   struct clk *clk;
+
+   mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+   if (!mux)
+   return ERR_PTR(-ENOMEM);
+   mux_hw = &mux->hw;
+   mux->reg = reg;
+   mux->shift = PCG_PCS_SHIFT;
+   mux->mask = PCG_PCS_MASK;
+
+   div = kzalloc(sizeof(*div), GFP_KERNEL);
+   if (!div) {
+   kfree(mux);
+   return ERR_PTR(-ENOMEM);
+   }
+   div_hw = &div->hw;
+   div->reg = reg;
+   div->shift = PCG_PREDIV_SHIFT;
+   div->width = PCG_PREDIV_WIDTH;
+   div->lock = &imx_ccm_lock;
+   div->flags = CLK_DIVIDER_ROUND_CLOSEST;
+
+   gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+   if (!gate) {
+   kfree(mux);
+   kfree(div);
+   return ERR_PTR(-ENOMEM);
+   }
+   gate_hw = &gate->hw;
+   gate->reg = reg;
+   gate->bit_idx = PCG_CGC_SHIFT;
+
+   flags |= CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE;
+
+   clk = clk_register_composite(NULL, name, parent_names, num_parents,
+   mux_hw, &clk_mux_ops, div_hw,
+   &imx_clk_composite_divider_ops, gate_hw,
+   &cl

[RESEND v5 5/5] clk: imx: add clock driver for i.MX8MQ CCM

2018-08-20 Thread Abel Vesa
From: Lucas Stach 

Add driver for the Clock Control Module found on i.MX8MQ.

This is largely based on the downstream driver from Anson Huang and
Bai Ping at NXP, with only some small adaptions to mainline from me.

Signed-off-by: Lucas Stach 
Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/Makefile |   1 +
 drivers/clk/imx/clk-imx8mq.c | 631 +++
 drivers/clk/imx/clk.h|  36 +++
 3 files changed, 668 insertions(+)
 create mode 100644 drivers/clk/imx/clk-imx8mq.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 4fabb0a..64e695c 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -30,3 +30,4 @@ obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o
 obj-$(CONFIG_SOC_IMX6UL) += clk-imx6ul.o
 obj-$(CONFIG_SOC_IMX7D)  += clk-imx7d.o
 obj-$(CONFIG_SOC_VF610)  += clk-vf610.o
+obj-$(CONFIG_SOC_IMX8MQ) += clk-imx8mq.o
diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c
new file mode 100644
index 000..d3a9e31
--- /dev/null
+++ b/drivers/clk/imx/clk-imx8mq.c
@@ -0,0 +1,631 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2018 NXP.
+ * Copyright (C) 2017 Pengutronix, Lucas Stach 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+static u32 share_count_sai1;
+static u32 share_count_sai2;
+static u32 share_count_sai3;
+static u32 share_count_sai4;
+static u32 share_count_sai5;
+static u32 share_count_sai6;
+static u32 share_count_dcss;
+static u32 share_count_nand;
+
+static struct clk *clks[IMX8MQ_CLK_END];
+
+static const char *pll_ref_sels[] = { "osc_25m", "osc_27m", "dummy", "dummy", 
};
+static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
+static const char *gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
+static const char *vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", };
+static const char *audio_pll1_bypass_sels[] = {"audio_pll1", 
"audio_pll1_ref_sel", };
+static const char *audio_pll2_bypass_sels[] = {"audio_pll2", 
"audio_pll2_ref_sel", };
+static const char *video_pll1_bypass_sels[] = {"video_pll1", 
"video_pll1_ref_sel", };
+
+static const char *sys1_pll1_out_sels[] = {"sys1_pll1", "sys1_pll1_ref_sel", };
+static const char *sys2_pll1_out_sels[] = {"sys2_pll1", "sys1_pll1_ref_sel", };
+static const char *sys3_pll1_out_sels[] = {"sys3_pll1", "sys3_pll1_ref_sel", };
+static const char *dram_pll1_out_sels[] = {"dram_pll1", "dram_pll1_ref_sel", };
+static const char *video2_pll1_out_sels[] = {"video2_pll1", 
"video2_pll1_ref_sel", };
+
+static const char *sys1_pll2_out_sels[] = {"sys1_pll2_div", 
"sys1_pll1_ref_sel", };
+static const char *sys2_pll2_out_sels[] = {"sys2_pll2_div", 
"sys2_pll1_ref_sel", };
+static const char *sys3_pll2_out_sels[] = {"sys3_pll2_div", 
"sys2_pll1_ref_sel", };
+static const char *dram_pll2_out_sels[] = {"dram_pll2_div", 
"dram_pll1_ref_sel", };
+static const char *video2_pll2_out_sels[] = {"video2_pll2_div", 
"video2_pll1_ref_sel", };
+
+/* CCM ROOT */
+static const char *imx8mq_a53_sels[] = {"osc_25m", "arm_pll_out", 
"sys2_pll_500m", "sys2_pll_1000m",
+   "sys1_pll_800m", "sys1_pll_400m", 
"audio_pll1_out", "sys3_pll2_out", };
+
+static const char *imx8mq_vpu_sels[] = {"osc_25m", "arm_pll_out", 
"sys2_pll_500m", "sys2_pll_1000m",
+   "sys1_pll_800m", "sys1_pll_400m", 
"audio_pll1_out", "vpu_pll_out", };
+
+static const char *imx8mq_gpu_core_sels[] = {"osc_25m", "gpu_pll_out", 
"sys1_pll_800m", "sys3_pll2_out",
+"sys2_pll_1000m", 
"audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mq_gpu_shader_sels[] = {"osc_25m", "gpu_pll_out", 
"sys1_pll_800m", "sys3_pll2_out",
+  "sys2_pll_1000m", 
"audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mq_main_axi_sels[] = {"osc_25m", "sys2_pll_333m", 
"sys1_pll_800m", "sys2_pll_250m",
+"sys2_pll_1000m", 
"audio_pll1_out", "video_pll1_out", "sys1_pll_100m",};
+
+static const ch

[PATCH 0/3] i.MX8MQ build dependency fixes

2018-12-13 Thread Abel Vesa
These patches will probably have to be take through different
trees, but the order has to be kept otherwise this won't work.

I can resend as separate patches (if necessary) as long as we can
get them in together.

Abel Vesa (3):
  arm64: Remove CONFIG_SOC_IMX8MQ and use ARCH_MXC instead
  clk: imx: Build imx8mq clocks on arm64 only
  arm64: Add i.MX8 boot necesarry configs to defconfig

 arch/arm64/Kconfig.platforms   |  8 
 arch/arm64/boot/dts/freescale/Makefile |  2 +-
 arch/arm64/configs/defconfig   |  5 +
 drivers/clk/imx/Makefile   | 11 ++-
 drivers/phy/freescale/Kconfig  |  2 +-
 drivers/pinctrl/freescale/Kconfig  |  2 +-
 drivers/soc/imx/Kconfig|  2 +-
 7 files changed, 15 insertions(+), 17 deletions(-)

-- 
2.7.4



[PATCH 2/3] clk: imx: Build imx8mq clocks on arm64 only

2018-12-13 Thread Abel Vesa
The composite-8m, frac and sccg clocks are not used by any arm32 IMX SoC,
therefore build them only on arm64. CONFIG_ARCH_MXC is arm64 only,
use that.

Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/Makefile | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 62a1882..cc95744 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -3,13 +3,11 @@
 obj-y += \
clk.o \
clk-busy.o \
-   clk-composite-8m.o \
clk-cpu.o \
clk-composite-7ulp.o \
clk-divider-gate.o \
clk-fixup-div.o \
clk-fixup-mux.o \
-   clk-frac-pll.o \
clk-gate-exclusive.o \
clk-gate2.o \
clk-pfd.o \
@@ -17,8 +15,7 @@ obj-y += \
clk-pllv1.o \
clk-pllv2.o \
clk-pllv3.o \
-   clk-pllv4.o \
-   clk-sccg-pll.o
+   clk-pllv4.o
 
 obj-$(CONFIG_SOC_IMX1)   += clk-imx1.o
 obj-$(CONFIG_SOC_IMX21)  += clk-imx21.o
@@ -36,4 +33,7 @@ obj-$(CONFIG_SOC_IMX7D)  += clk-imx7d.o
 obj-$(CONFIG_SOC_IMX7ULP) += clk-imx7ulp.o
 obj-$(CONFIG_SOC_VF610)  += clk-vf610.o
 
-obj-$(CONFIG_ARCH_MXC) += clk-imx8mq.o
+obj-$(CONFIG_ARCH_MXC) += clk-imx8mq.o \
+   clk-composite-8m.o \
+   clk-frac-pll.o \
+   clk-sccg-pll.o
-- 
2.7.4



[PATCH 1/3] arm64: Remove CONFIG_SOC_IMX8MQ and use ARCH_MXC instead

2018-12-13 Thread Abel Vesa
To keep aligned with arm64, remove the unnecessary SOC_IMX8MQ and use
ARCH_MXC instead.

Signed-off-by: Abel Vesa 
---
 arch/arm64/Kconfig.platforms   | 8 
 arch/arm64/boot/dts/freescale/Makefile | 2 +-
 drivers/clk/imx/Makefile   | 3 ++-
 drivers/phy/freescale/Kconfig  | 2 +-
 drivers/pinctrl/freescale/Kconfig  | 2 +-
 drivers/soc/imx/Kconfig| 2 +-
 6 files changed, 6 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 7e1545a..318dbb9 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -148,14 +148,6 @@ config ARCH_MXC
  This enables support for the ARMv8 based SoCs in the
  NXP i.MX family.
 
-config SOC_IMX8MQ
-   bool "i.MX8MQ support"
-   depends on ARCH_MXC
-   select ARM64_ERRATUM_843419
-   select ARM64_ERRATUM_845719
-   help
- This enables support for the i.MX8MQ SoC.
-
 config ARCH_QCOM
bool "Qualcomm Platforms"
select GPIOLIB
diff --git a/arch/arm64/boot/dts/freescale/Makefile 
b/arch/arm64/boot/dts/freescale/Makefile
index 0001361..f9be242 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -19,4 +19,4 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2088a-rdb.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-qds.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-rdb.dtb
 
-dtb-$(CONFIG_SOC_IMX8MQ) += imx8mq-evk.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mq-evk.dtb
diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 5c0b11e..62a1882 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -34,5 +34,6 @@ obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o
 obj-$(CONFIG_SOC_IMX6UL) += clk-imx6ul.o
 obj-$(CONFIG_SOC_IMX7D)  += clk-imx7d.o
 obj-$(CONFIG_SOC_IMX7ULP) += clk-imx7ulp.o
-obj-$(CONFIG_SOC_IMX8MQ) += clk-imx8mq.o
 obj-$(CONFIG_SOC_VF610)  += clk-vf610.o
+
+obj-$(CONFIG_ARCH_MXC) += clk-imx8mq.o
diff --git a/drivers/phy/freescale/Kconfig b/drivers/phy/freescale/Kconfig
index f050bd4..923c0ef 100644
--- a/drivers/phy/freescale/Kconfig
+++ b/drivers/phy/freescale/Kconfig
@@ -2,4 +2,4 @@ config PHY_FSL_IMX8MQ_USB
tristate "Freescale i.MX8M USB3 PHY"
depends on OF && HAS_IOMEM
select GENERIC_PHY
-   default SOC_IMX8MQ
+   default ARCH_MXC
diff --git a/drivers/pinctrl/freescale/Kconfig 
b/drivers/pinctrl/freescale/Kconfig
index 2d6db43..9874a16 100644
--- a/drivers/pinctrl/freescale/Kconfig
+++ b/drivers/pinctrl/freescale/Kconfig
@@ -123,7 +123,7 @@ config PINCTRL_IMX7ULP
 
 config PINCTRL_IMX8MQ
bool "IMX8MQ pinctrl driver"
-   depends on SOC_IMX8MQ
+   depends on ARCH_MXC
select PINCTRL_IMX
help
  Say Y here to enable the imx8mq pinctrl driver
diff --git a/drivers/soc/imx/Kconfig b/drivers/soc/imx/Kconfig
index 2112d18..7ffbb6b 100644
--- a/drivers/soc/imx/Kconfig
+++ b/drivers/soc/imx/Kconfig
@@ -2,7 +2,7 @@ menu "i.MX SoC drivers"
 
 config IMX_GPCV2_PM_DOMAINS
bool "i.MX GPCv2 PM domains"
-   depends on SOC_IMX7D || SOC_IMX8MQ || (COMPILE_TEST && OF)
+   depends on SOC_IMX7D || ARCH_MXC || (COMPILE_TEST && OF)
depends on PM
select PM_GENERIC_DOMAINS
default y if SOC_IMX7D
-- 
2.7.4



[PATCH 3/3] arm64: Add i.MX8 boot necesarry configs to defconfig

2018-12-13 Thread Abel Vesa
The CONFIG_ARCH_MXC will enable all the i.MX8 SoC.
Also add the FEC config for ethernet support, the serial
and the pinctrl for i.MX8MQ.

Signed-off-by: Abel Vesa 
---
 arch/arm64/configs/defconfig | 5 +
 1 file changed, 5 insertions(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 5c2b1f6..a129e5e 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -45,6 +45,7 @@ CONFIG_ARCH_HISI=y
 CONFIG_ARCH_MEDIATEK=y
 CONFIG_ARCH_MESON=y
 CONFIG_ARCH_MVEBU=y
+CONFIG_ARCH_MXC=y
 CONFIG_ARCH_QCOM=y
 CONFIG_ARCH_ROCKCHIP=y
 CONFIG_ARCH_SEATTLE=y
@@ -226,6 +227,7 @@ CONFIG_NET_XGENE=y
 CONFIG_ATL1C=m
 CONFIG_MACB=y
 CONFIG_THUNDER_NIC_PF=y
+CONFIG_FEC=y
 CONFIG_HIX5HD2_GMAC=y
 CONFIG_HNS_DSAF=y
 CONFIG_HNS_ENET=y
@@ -300,6 +302,8 @@ CONFIG_SERIAL_MESON_CONSOLE=y
 CONFIG_SERIAL_SAMSUNG=y
 CONFIG_SERIAL_SAMSUNG_CONSOLE=y
 CONFIG_SERIAL_TEGRA=y
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
 CONFIG_SERIAL_SH_SCI=y
 CONFIG_SERIAL_MSM=y
 CONFIG_SERIAL_MSM_CONSOLE=y
@@ -346,6 +350,7 @@ CONFIG_SPI_SPIDEV=m
 CONFIG_SPMI=y
 CONFIG_PINCTRL_SINGLE=y
 CONFIG_PINCTRL_MAX77620=y
+CONFIG_PINCTRL_IMX8MQ=y
 CONFIG_PINCTRL_IPQ8074=y
 CONFIG_PINCTRL_MSM8916=y
 CONFIG_PINCTRL_MSM8994=y
-- 
2.7.4



Re: [PATCH 0/3] i.MX8MQ build dependency fixes

2018-12-13 Thread Abel Vesa
On 18-12-13 13:17:40, Abel Vesa wrote:
> These patches will probably have to be take through different
> trees, but the order has to be kept otherwise this won't work.
> 
> I can resend as separate patches (if necessary) as long as we can
> get them in together.
> 

Please ignore this patch series.
Seems ARCH_MXC is a poor choice. Needs a proper look.

Sorry about that.

> Abel Vesa (3):
>   arm64: Remove CONFIG_SOC_IMX8MQ and use ARCH_MXC instead
>   clk: imx: Build imx8mq clocks on arm64 only
>   arm64: Add i.MX8 boot necesarry configs to defconfig
> 
>  arch/arm64/Kconfig.platforms   |  8 
>  arch/arm64/boot/dts/freescale/Makefile |  2 +-
>  arch/arm64/configs/defconfig   |  5 +
>  drivers/clk/imx/Makefile   | 11 ++-
>  drivers/phy/freescale/Kconfig  |  2 +-
>  drivers/pinctrl/freescale/Kconfig  |  2 +-
>  drivers/soc/imx/Kconfig|  2 +-
>  7 files changed, 15 insertions(+), 17 deletions(-)
> 
> -- 
> 2.7.4
> 

Re: [PATCH 1/3] arm64: Remove CONFIG_SOC_IMX8MQ and use ARCH_MXC instead

2018-12-13 Thread Abel Vesa
On 18-12-13 15:35:27, Lucas Stach wrote:
> Am Donnerstag, den 13.12.2018, 13:17 + schrieb Abel Vesa:
> > To keep aligned with arm64, remove the unnecessary SOC_IMX8MQ and use
> > ARCH_MXC instead.
> > 
> > Signed-off-by: Abel Vesa 
> > ---
> >  arch/arm64/Kconfig.platforms   | 8 
> >  arch/arm64/boot/dts/freescale/Makefile | 2 +-
> >  drivers/clk/imx/Makefile   | 3 ++-
> >  drivers/phy/freescale/Kconfig  | 2 +-
> >  drivers/pinctrl/freescale/Kconfig  | 2 +-
> >  drivers/soc/imx/Kconfig| 2 +-
> >  6 files changed, 6 insertions(+), 13 deletions(-)
> > 
> > diff --git a/arch/arm64/Kconfig.platforms
> > b/arch/arm64/Kconfig.platforms
> > index 7e1545a..318dbb9 100644
> > --- a/arch/arm64/Kconfig.platforms
> > +++ b/arch/arm64/Kconfig.platforms
> > @@ -148,14 +148,6 @@ config ARCH_MXC
> >       This enables support for the ARMv8 based SoCs in the
> >       NXP i.MX family.
> >  
> > -config SOC_IMX8MQ
> > -   bool "i.MX8MQ support"
> > -   depends on ARCH_MXC
> > -   select ARM64_ERRATUM_843419
> > -   select ARM64_ERRATUM_845719
> > -   help
> > -     This enables support for the i.MX8MQ SoC.
> > -
> 
> NACK on this one. Having a single place where stuff that is absolutely
> critical for proper SoC operation can be selected is very useful and
> avoids hard to debug issues due to slightly wrong configs in the long
> run.

As mentioned in the cover letter, please ignore this patch set entirely.
The ARCH_MXC is actually used on arm32 too, so it won't work.

I'm working on a patchset that will add the Kconfig into 
drivers/clk/imx/ and in it will add CLK_IMX8MQ. That will
fix the clock dependency since the CLK_IMX8MQ will depend on
ARCH_MXC and ARM64. I believe the CLK_IMX8QXP will follow
the same pattern.

As for the SOC_IMX8MQ, all the other vendors have one single
config for all the arm64 platforms. TBH, to control every SoC
independently it's a little bit of an overkill.

But maybe I'm the only one who thinks so.

> 
> Regards,
> Lucas
> 
> >  config ARCH_QCOM
> >     bool "Qualcomm Platforms"
> >     select GPIOLIB
> > diff --git a/arch/arm64/boot/dts/freescale/Makefile
> > b/arch/arm64/boot/dts/freescale/Makefile
> > index 0001361..f9be242 100644
> > --- a/arch/arm64/boot/dts/freescale/Makefile
> > +++ b/arch/arm64/boot/dts/freescale/Makefile
> > @@ -19,4 +19,4 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2088a-
> > rdb.dtb
> >  dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-qds.dtb
> >  dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-rdb.dtb
> >  
> > -dtb-$(CONFIG_SOC_IMX8MQ) += imx8mq-evk.dtb
> > +dtb-$(CONFIG_ARCH_MXC) += imx8mq-evk.dtb
> > diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
> > index 5c0b11e..62a1882 100644
> > --- a/drivers/clk/imx/Makefile
> > +++ b/drivers/clk/imx/Makefile
> > @@ -34,5 +34,6 @@ obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o
> >  obj-$(CONFIG_SOC_IMX6UL) += clk-imx6ul.o
> >  obj-$(CONFIG_SOC_IMX7D)  += clk-imx7d.o
> >  obj-$(CONFIG_SOC_IMX7ULP) += clk-imx7ulp.o
> > -obj-$(CONFIG_SOC_IMX8MQ) += clk-imx8mq.o
> >  obj-$(CONFIG_SOC_VF610)  += clk-vf610.o
> > +
> > +obj-$(CONFIG_ARCH_MXC) += clk-imx8mq.o
> > diff --git a/drivers/phy/freescale/Kconfig
> > b/drivers/phy/freescale/Kconfig
> > index f050bd4..923c0ef 100644
> > --- a/drivers/phy/freescale/Kconfig
> > +++ b/drivers/phy/freescale/Kconfig
> > @@ -2,4 +2,4 @@ config PHY_FSL_IMX8MQ_USB
> >     tristate "Freescale i.MX8M USB3 PHY"
> >     depends on OF && HAS_IOMEM
> >     select GENERIC_PHY
> > -   default SOC_IMX8MQ
> > +   default ARCH_MXC
> > diff --git a/drivers/pinctrl/freescale/Kconfig
> > b/drivers/pinctrl/freescale/Kconfig
> > index 2d6db43..9874a16 100644
> > --- a/drivers/pinctrl/freescale/Kconfig
> > +++ b/drivers/pinctrl/freescale/Kconfig
> > @@ -123,7 +123,7 @@ config PINCTRL_IMX7ULP
> >  
> >  config PINCTRL_IMX8MQ
> >     bool "IMX8MQ pinctrl driver"
> > -   depends on SOC_IMX8MQ
> > +   depends on ARCH_MXC
> >     select PINCTRL_IMX
> >     help
> >       Say Y here to enable the imx8mq pinctrl driver
> > diff --git a/drivers/soc/imx/Kconfig b/drivers/soc/imx/Kconfig
> > index 2112d18..7ffbb6b 100644
> > --- a/drivers/soc/imx/Kconfig
> > +++ b/drivers/soc/imx/Kconfig
> > @@ -2,7 +2,7 @@ menu "i.MX SoC drivers"
> >  
> >  config IMX_GPCV2_PM_DOMAINS
> >     bool "i.MX GPCv2 PM domains"
> > -   depends on SOC_IMX7D || SOC_IMX8MQ || (COMPILE_TEST && OF)
> > +   depends on SOC_IMX7D || ARCH_MXC || (COMPILE_TEST && OF)
> >     depends on PM
> >     select PM_GENERIC_DOMAINS
> >     default y if SOC_IMX7D

[PATCH] clk: imx: Make the i.MX8MQ CCM clock driver CLK_IMX8MQ dependant

2018-12-13 Thread Abel Vesa
Remove the dependency between the i.MX8MQ CCM clock driver
and the CONFIG_SOC_IMX8MQ and use CONFIG_CLK_IMX8MQ instead.
CONFIG_CLK_IMX8MQ depends on ARCH_MXC && ARM64.

Signed-off-by: Abel Vesa 
---
 drivers/clk/Kconfig  | 1 +
 drivers/clk/imx/Kconfig  | 5 +
 drivers/clk/imx/Makefile | 3 ++-
 3 files changed, 8 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/imx/Kconfig

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 2dc12bf..833353c 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -293,6 +293,7 @@ config COMMON_CLK_BD718XX
 source "drivers/clk/actions/Kconfig"
 source "drivers/clk/bcm/Kconfig"
 source "drivers/clk/hisilicon/Kconfig"
+source "drivers/clk/imx/Kconfig"
 source "drivers/clk/imgtec/Kconfig"
 source "drivers/clk/ingenic/Kconfig"
 source "drivers/clk/keystone/Kconfig"
diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig
new file mode 100644
index 000..98ede6a
--- /dev/null
+++ b/drivers/clk/imx/Kconfig
@@ -0,0 +1,5 @@
+config CLK_IMX8MQ
+   bool "IMX8MQ CCM Clock Driver"
+   depends on ARCH_MXC && ARM64
+   help
+   Build the driver for i.MX8MQ CCM Clock Driver
diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 5c0b11e..01e5f55 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -34,5 +34,6 @@ obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o
 obj-$(CONFIG_SOC_IMX6UL) += clk-imx6ul.o
 obj-$(CONFIG_SOC_IMX7D)  += clk-imx7d.o
 obj-$(CONFIG_SOC_IMX7ULP) += clk-imx7ulp.o
-obj-$(CONFIG_SOC_IMX8MQ) += clk-imx8mq.o
 obj-$(CONFIG_SOC_VF610)  += clk-vf610.o
+
+obj-$(CONFIG_CLK_IMX8MQ) += clk-imx8mq.o
-- 
2.7.4



Re: [PATCH 0/3] clk: imx: Make all the parent_names arrays be const pointers

2018-12-17 Thread Abel Vesa
On 18-12-17 10:40:52, Stephen Boyd wrote:
> Quoting Abel Vesa (2018-12-17 03:35:40)
> > On 18-12-14 13:08:37, Stephen Boyd wrote:
> > > Quoting Abel Vesa (2018-12-14 07:30:08)
> > > > This is mainly to shut up the checkpatch.pl script warnings about the
> > > > "static const char *" needing to be "static const char * const".
> > > > 
> > > > Abel Vesa (3):
> > > >   clk: imx: Make parent_names const pointer in composite-8m
> > > >   clk: imx: Make parents const pointer in mux wrappers
> > > >   clk: imx8mq: Make parent names arrays const pointers
> > > > 
> > > 
> > > I still see warnings though so there seems to be some more work to do.
> > > 
> > > drivers/clk/imx/clk-imx8mq.c:401:89: warning: passing argument 5 of 
> > > 'imx_clk_mux2' discards 'const' qualifier from pointer target type 
> > > [-Wdiscarded-qualifiers]
> > >   clks[IMX8MQ_CLK_GPU_SHADER_SRC] = imx_clk_mux2("gpu_shader_src", base + 
> > > 0x8200, 24, 3, imx8mq_gpu_shader_sels,  
> > > ARRAY_SIZE(imx8mq_gpu_shader_sels));
> > > 
> > Hmm, I guess you applied this on top of clk-imx8mq, right ?
> > This change is against linux-next. The actual problem is the imx_clk_mux2
> > which looks like this on branch clk-imx8mq:
> 
> Yes. It would be great if you could indicate where patches are
> generated. In fact, I see that 'git format-patch' now has an option to
> do just this!
> 
>   git format-patch --base=commit
> 

Sorry about that. Will do that in the future.

> > 
> > static inline struct clk *imx_clk_mux2(const char *name, void __iomem *reg, 
> >  
> > u8 shift, u8 width, const char **parents, int num_parents)  
> >  
> > 
> > but it looks like this on linux-next (which is exactly the same on 
> > clk-next):
> > 
> > static inline struct clk *imx_clk_mux2(const char *name, void __iomem *reg, 
> >  
> > u8 shift, u8 width, const char * const *parents,
> >  
> > int num_parents)
> >  
> 
> Hrmm ok. I'll have to rejigger things and I probably won't be getting to
> it until early next year.
> 

I can rebase it on clk-imx8mq and resend if you want.

Re: [PATCH 1/3] arm64: Remove CONFIG_SOC_IMX8MQ and use ARCH_MXC instead

2018-12-14 Thread Abel Vesa
On 18-12-14 10:22:11, Lucas Stach wrote:
> Hi Shawn,
> 
> Am Freitag, den 14.12.2018, 09:12 +0800 schrieb Shawn Guo:
> > On Thu, Dec 13, 2018 at 02:51:50PM +, Abel Vesa wrote:
> > ...
> > > > > diff --git a/arch/arm64/Kconfig.platforms
> > > > > b/arch/arm64/Kconfig.platforms
> > > > > index 7e1545a..318dbb9 100644
> > > > > --- a/arch/arm64/Kconfig.platforms
> > > > > +++ b/arch/arm64/Kconfig.platforms
> > > > > @@ -148,14 +148,6 @@ config ARCH_MXC
> > > > > > > > >     This enables support for the ARMv8 based SoCs in the
> > > > > > > > >     NXP i.MX family.
> > > > >  
> > > > > -config SOC_IMX8MQ
> > > > > > > > > - bool "i.MX8MQ support"
> > > > > > > > > - depends on ARCH_MXC
> > > > > > > > > - select ARM64_ERRATUM_843419
> > > > > > > > > - select ARM64_ERRATUM_845719
> > > > > > > > > - help
> > > > > > > > > -   This enables support for the i.MX8MQ SoC.
> > > > > -
> > > > 
> > > > NACK on this one. Having a single place where stuff that is absolutely
> > > > critical for proper SoC operation can be selected is very useful and
> > > > avoids hard to debug issues due to slightly wrong configs in the long
> > > > run.
> > > 
> > > As mentioned in the cover letter, please ignore this patch set entirely.
> > > The ARCH_MXC is actually used on arm32 too, so it won't work.
> > > 
> > > I'm working on a patchset that will add the Kconfig into 
> > > drivers/clk/imx/ and in it will add CLK_IMX8MQ. That will
> > > fix the clock dependency since the CLK_IMX8MQ will depend on
> > > ARCH_MXC and ARM64. I believe the CLK_IMX8QXP will follow
> > > the same pattern.
> > > 
> > > As for the SOC_IMX8MQ, all the other vendors have one single
> > > config for all the arm64 platforms. TBH, to control every SoC
> > > independently it's a little bit of an overkill.
> > 
> > Lucas,
> > 
> > We are still waiting for further comments from Olof [1].  But it sounds
> > like SoC specific option is not welcomed on ARM64.
> 
> While I personally would prefer to keep the SoC options, I see that we
> need to align with the judgment of the arm-soc maintainers.
> 
> But at the very least we should keep the select for vital system
> workarounds. They need to move to the arch Kconfig symbol in that case
> and might select stuff that isn't needed on each of the i.MX8 SoCs. But
> better enabling more workaround and drivers than necessary than having
> hard to debug system failures in the future.
> 

I get your point. But that seems to be an issue with the whole arm64 approach.
TBH, I believe now would be the perfect time to "get it right" on IMX since the 
8MQ
is the first one to get boot-up support upstream. It will be way much harder
to change this later when more arm64 IMX SoCs get upstreamed.

I would really love more opinions on this.

I have patches on stand-by that remove the SOC_IMX8MQ in all the subsystems and
a patch for the defconfig update which I'll keep on holding on to until there
is a agreement on this.

> Regards,
> Lucas

[PATCH v2] clk: imx: Make the i.MX8MQ CCM clock driver CLK_IMX8MQ dependant

2018-12-14 Thread Abel Vesa
Remove the dependency between the i.MX8MQ CCM clock driver
and the CONFIG_SOC_IMX8MQ and use CONFIG_CLK_IMX8MQ instead.
CONFIG_CLK_IMX8MQ depends on ARCH_MXC && ARM64.

Signed-off-by: Abel Vesa 
---

Changes since v1:
 * reordered the CONFIGs in clk/imx/Makefile as suggested
by Daniel and Shawn

 drivers/clk/Kconfig  | 1 +
 drivers/clk/imx/Kconfig  | 5 +
 drivers/clk/imx/Makefile | 4 +++-
 3 files changed, 9 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/imx/Kconfig

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 2dc12bf..833353c 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -293,6 +293,7 @@ config COMMON_CLK_BD718XX
 source "drivers/clk/actions/Kconfig"
 source "drivers/clk/bcm/Kconfig"
 source "drivers/clk/hisilicon/Kconfig"
+source "drivers/clk/imx/Kconfig"
 source "drivers/clk/imgtec/Kconfig"
 source "drivers/clk/ingenic/Kconfig"
 source "drivers/clk/keystone/Kconfig"
diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig
new file mode 100644
index 000..98ede6a
--- /dev/null
+++ b/drivers/clk/imx/Kconfig
@@ -0,0 +1,5 @@
+config CLK_IMX8MQ
+   bool "IMX8MQ CCM Clock Driver"
+   depends on ARCH_MXC && ARM64
+   help
+   Build the driver for i.MX8MQ CCM Clock Driver
diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 5c0b11e..7e55a4b 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -20,6 +20,8 @@ obj-y += \
clk-pllv4.o \
clk-sccg-pll.o
 
+obj-$(CONFIG_CLK_IMX8MQ) += clk-imx8mq.o
+
 obj-$(CONFIG_SOC_IMX1)   += clk-imx1.o
 obj-$(CONFIG_SOC_IMX21)  += clk-imx21.o
 obj-$(CONFIG_SOC_IMX25)  += clk-imx25.o
@@ -34,5 +36,5 @@ obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o
 obj-$(CONFIG_SOC_IMX6UL) += clk-imx6ul.o
 obj-$(CONFIG_SOC_IMX7D)  += clk-imx7d.o
 obj-$(CONFIG_SOC_IMX7ULP) += clk-imx7ulp.o
-obj-$(CONFIG_SOC_IMX8MQ) += clk-imx8mq.o
 obj-$(CONFIG_SOC_VF610)  += clk-vf610.o
+
-- 
2.7.4



[PATCH 0/3] clk: imx: Make all the parent_names arrays be const pointers

2018-12-14 Thread Abel Vesa
This is mainly to shut up the checkpatch.pl script warnings about the
"static const char *" needing to be "static const char * const".

Abel Vesa (3):
  clk: imx: Make parent_names const pointer in composite-8m
  clk: imx: Make parents const pointer in mux wrappers
  clk: imx8mq: Make parent names arrays const pointers

 drivers/clk/imx/clk-composite-8m.c |   2 +-
 drivers/clk/imx/clk-imx8mq.c   | 194 ++---
 drivers/clk/imx/clk.h  |   5 +-
 3 files changed, 101 insertions(+), 100 deletions(-)

-- 
2.7.4



[PATCH 1/3] clk: imx: Make parent_names const pointer in composite-8m

2018-12-14 Thread Abel Vesa
The parent_names needs to be pointer to const pointer to const char.

Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/clk-composite-8m.c | 2 +-
 drivers/clk/imx/clk.h  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/imx/clk-composite-8m.c 
b/drivers/clk/imx/clk-composite-8m.c
index 527ade1..574fac1 100644
--- a/drivers/clk/imx/clk-composite-8m.c
+++ b/drivers/clk/imx/clk-composite-8m.c
@@ -123,7 +123,7 @@ static const struct clk_ops imx8m_clk_composite_divider_ops 
= {
 };
 
 struct clk *imx8m_clk_composite_flags(const char *name,
-   const char **parent_names,
+   const char * const *parent_names,
int num_parents, void __iomem *reg,
unsigned long flags)
 {
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index 028312d..1363dbe 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -354,7 +354,7 @@ struct clk *imx_clk_cpu(const char *name, const char 
*parent_name,
struct clk *step);
 
 struct clk *imx8m_clk_composite_flags(const char *name,
-   const char **parent_names,
+   const char * const *parent_names,
int num_parents, void __iomem *reg,
unsigned long flags);
 
-- 
2.7.4



[PATCH 2/3] clk: imx: Make parents const pointer in mux wrappers

2018-12-14 Thread Abel Vesa
The parents needs to be pointer to const pointer to const char.

Signed-off-by: Abel Vesa 
---
 drivers/clk/imx/clk.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index 1363dbe..2e442d8 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -329,7 +329,8 @@ static inline struct clk *imx_clk_mux_flags(const char 
*name,
 }
 
 static inline struct clk *imx_clk_mux2_flags(const char *name,
-   void __iomem *reg, u8 shift, u8 width, const char **parents,
+   void __iomem *reg, u8 shift, u8 width,
+   const char * const *parents,
int num_parents, unsigned long flags)
 {
return clk_register_mux(NULL, name, parents, num_parents,
-- 
2.7.4



  1   2   3   4   5   6   >