* [PATCH V6 0/6] clk: imx: add imx8qxp clock support
@ 2018-11-10 15:19 ` A.s. Dong
0 siblings, 0 replies; 36+ messages in thread
From: A.s. Dong @ 2018-11-10 15:19 UTC (permalink / raw)
To: linux-clk
Cc: linux-arm-kernel, sboyd, mturquette, shawnguo, Fabio Estevam,
dl-linux-imx, kernel, A.s. Dong
This patch series adds i.MX8QXP clock support which is based
on the clock service provided by SCU firmware.
Note: It depends on SCU driver which has already been merged by Shawn.
So this patch series could go through Shawn's tree as well.
ChangeLog:
v5->v6:
* simply the driver a lot by re-orgnizing the driver into a few clock types:
scu clock (merge scu divider/gate/mux) and scu gpr lock which accessing is
through SCU protocol and LPCG clock which is directly accessible by CPU.
* LPCG clock is separate from SCU clock, gpr clock is still not used
and will be added later.
* remove old year license as the code is totally rewritten
* scu mux support will be added later as it's also still not used.
v4->v5:
Address all Stephen and Sascha's review comments, see details in each patch
v3->v4:
* scu headfile path update
* no functionality change
v2->v3:
* structures/enums name update with imx_sc prefix
* no functionality change
v1->v2:
* structure and enums name update
* api usage update due to api change
* no functionality change
Dong Aisheng (6):
clk: imx: add scu clock common part
dt-bindings: clock: imx8qxp: add SCU clock IDs
clk: imx: add imx8qxp clk driver
dt-bindings: clock: add imx8qxp lpcg clock binding
clk: imx: add lpcg clock support
clk: imx: add imx8qxp lpcg driver
.../devicetree/bindings/clock/imx8qxp-lpcg.txt | 51 ++++
drivers/clk/imx/Kconfig | 4 +
drivers/clk/imx/Makefile | 6 +
drivers/clk/imx/clk-imx8qxp-lpcg.c | 198 ++++++++++++++
drivers/clk/imx/clk-imx8qxp-lpcg.h | 102 ++++++++
drivers/clk/imx/clk-imx8qxp.c | 156 +++++++++++
drivers/clk/imx/clk-lpcg-scu.c | 108 ++++++++
drivers/clk/imx/clk-scu.c | 237 +++++++++++++++++
drivers/clk/imx/clk-scu.h | 24 ++
include/dt-bindings/clock/imx8qxp-clock.h | 289 +++++++++++++++++++++
10 files changed, 1175 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt
create mode 100644 drivers/clk/imx/clk-imx8qxp-lpcg.c
create mode 100644 drivers/clk/imx/clk-imx8qxp-lpcg.h
create mode 100644 drivers/clk/imx/clk-imx8qxp.c
create mode 100644 drivers/clk/imx/clk-lpcg-scu.c
create mode 100644 drivers/clk/imx/clk-scu.c
create mode 100644 drivers/clk/imx/clk-scu.h
create mode 100644 include/dt-bindings/clock/imx8qxp-clock.h
--
2.7.4
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH V6 0/6] clk: imx: add imx8qxp clock support
@ 2018-11-10 15:19 ` A.s. Dong
0 siblings, 0 replies; 36+ messages in thread
From: A.s. Dong @ 2018-11-10 15:19 UTC (permalink / raw)
To: linux-arm-kernel
This patch series adds i.MX8QXP clock support which is based
on the clock service provided by SCU firmware.
Note: It depends on SCU driver which has already been merged by Shawn.
So this patch series could go through Shawn's tree as well.
ChangeLog:
v5->v6:
* simply the driver a lot by re-orgnizing the driver into a few clock types:
scu clock (merge scu divider/gate/mux) and scu gpr lock which accessing is
through SCU protocol and LPCG clock which is directly accessible by CPU.
* LPCG clock is separate from SCU clock, gpr clock is still not used
and will be added later.
* remove old year license as the code is totally rewritten
* scu mux support will be added later as it's also still not used.
v4->v5:
Address all Stephen and Sascha's review comments, see details in each patch
v3->v4:
* scu headfile path update
* no functionality change
v2->v3:
* structures/enums name update with imx_sc prefix
* no functionality change
v1->v2:
* structure and enums name update
* api usage update due to api change
* no functionality change
Dong Aisheng (6):
clk: imx: add scu clock common part
dt-bindings: clock: imx8qxp: add SCU clock IDs
clk: imx: add imx8qxp clk driver
dt-bindings: clock: add imx8qxp lpcg clock binding
clk: imx: add lpcg clock support
clk: imx: add imx8qxp lpcg driver
.../devicetree/bindings/clock/imx8qxp-lpcg.txt | 51 ++++
drivers/clk/imx/Kconfig | 4 +
drivers/clk/imx/Makefile | 6 +
drivers/clk/imx/clk-imx8qxp-lpcg.c | 198 ++++++++++++++
drivers/clk/imx/clk-imx8qxp-lpcg.h | 102 ++++++++
drivers/clk/imx/clk-imx8qxp.c | 156 +++++++++++
drivers/clk/imx/clk-lpcg-scu.c | 108 ++++++++
drivers/clk/imx/clk-scu.c | 237 +++++++++++++++++
drivers/clk/imx/clk-scu.h | 24 ++
include/dt-bindings/clock/imx8qxp-clock.h | 289 +++++++++++++++++++++
10 files changed, 1175 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt
create mode 100644 drivers/clk/imx/clk-imx8qxp-lpcg.c
create mode 100644 drivers/clk/imx/clk-imx8qxp-lpcg.h
create mode 100644 drivers/clk/imx/clk-imx8qxp.c
create mode 100644 drivers/clk/imx/clk-lpcg-scu.c
create mode 100644 drivers/clk/imx/clk-scu.c
create mode 100644 drivers/clk/imx/clk-scu.h
create mode 100644 include/dt-bindings/clock/imx8qxp-clock.h
--
2.7.4
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH V6 1/6] clk: imx: add scu clock common part
2018-11-10 15:19 ` A.s. Dong
@ 2018-11-10 15:19 ` A.s. Dong
-1 siblings, 0 replies; 36+ messages in thread
From: A.s. Dong @ 2018-11-10 15:19 UTC (permalink / raw)
To: linux-clk
Cc: linux-arm-kernel, sboyd, mturquette, shawnguo, Fabio Estevam,
dl-linux-imx, kernel, A.s. Dong
Add scu clock common part which will be used by client clock drivers.
SCU clocks are totally different from the legacy clocks (No much
legacy things can be reused). So a new configuration option
CONFIG_MXC_CLK_SCU is added.
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: Fabio Estevam <fabio.estevam@nxp.com>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Michael Turquette <mturquette@baylibre.com>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
ChangeLog:
v5->v6:
* simply the whole clock driver a lot by re-orgnizing the driver into a
few clock types:: scu clock (merge scu divider/gate/mux) and scu gpr lock
which accessing is through SCU protocol and LPCG clock which is directly
accessible by CPU.
* LPCG clock support will be added in next patch, gpr clock is still not used
and will be added later.
* remove old year license as the code is totally rewritten
* scu mux support will be added later as it's also still not used.
v4->v5:
* add more explanation in commit message on why put scu clocks
in a deeper folder.
* move scu clk files into the top directory of imx folder
v3->v4:
* scu headfile path change
v2->v3:
* no changes
v1->v2:
* update function call name
---
drivers/clk/imx/Kconfig | 4 +
drivers/clk/imx/Makefile | 3 +
drivers/clk/imx/clk-scu.c | 237 ++++++++++++++++++++++++++++++++++++++++++++++
drivers/clk/imx/clk-scu.h | 21 ++++
4 files changed, 265 insertions(+)
create mode 100644 drivers/clk/imx/clk-scu.c
create mode 100644 drivers/clk/imx/clk-scu.h
diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig
index 43a3ecc..63e7b01 100644
--- a/drivers/clk/imx/Kconfig
+++ b/drivers/clk/imx/Kconfig
@@ -3,3 +3,7 @@
config MXC_CLK
bool
depends on ARCH_MXC
+
+config MXC_CLK_SCU
+ bool
+ depends on ARCH_MXC && ARM64
diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index d447f8c..eec6d72 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -13,6 +13,9 @@ obj-$(CONFIG_MXC_CLK) += \
clk-pllv3.o \
clk-pfd.o
+obj-$(CONFIG_MXC_CLK_SCU) += \
+ clk-scu.o
+
obj-$(CONFIG_SOC_IMX1) += clk-imx1.o
obj-$(CONFIG_SOC_IMX21) += clk-imx21.o
obj-$(CONFIG_SOC_IMX25) += clk-imx25.o
diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c
new file mode 100644
index 0000000..9fec574
--- /dev/null
+++ b/drivers/clk/imx/clk-scu.c
@@ -0,0 +1,237 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ * Dong Aisheng <aisheng.dong@nxp.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include "clk-scu.h"
+
+struct imx_sc_ipc *ccm_ipc_handle;
+
+struct clk_scu {
+ struct clk_hw hw;
+ u32 rsrc_id;
+ u8 clk_type;
+};
+
+/* SCU Clock Protocol definitions */
+
+/* rate */
+struct imx_sc_msg_req_set_clock_rate {
+ struct imx_sc_rpc_msg hdr;
+ u32 rate;
+ u16 resource;
+ u8 clk;
+} __packed;
+
+struct req_get_clock_rate {
+ u16 resource;
+ u8 clk;
+} __packed;
+
+struct resp_get_clock_rate {
+ u32 rate;
+};
+
+struct imx_sc_msg_get_clock_rate {
+ struct imx_sc_rpc_msg hdr;
+ union {
+ struct req_get_clock_rate req;
+ struct resp_get_clock_rate resp;
+ } data;
+} __packed;
+
+/* gate */
+struct imx_sc_msg_req_clock_enable {
+ struct imx_sc_rpc_msg hdr;
+ u16 resource;
+ u8 clk;
+ u8 enable;
+ u8 autog;
+} __packed;
+
+static inline struct clk_scu *to_clk_scu(struct clk_hw *hw)
+{
+ return container_of(hw, struct clk_scu, hw);
+}
+
+/*
+ * clk_scu_recalc_rate - Get clock rate for a SCU clock
+ * @hw: clock to get rate for
+ * @parent_rate: parent rate provided by common clock framework, not used
+ *
+ * Gets the current clock rate of a SCU clock. Returns the current
+ * clock rate, or zero in failure.
+ */
+static unsigned long clk_scu_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_scu *clk = to_clk_scu(hw);
+ struct imx_sc_msg_get_clock_rate msg;
+ struct imx_sc_rpc_msg *hdr = &msg.hdr;
+ int ret;
+
+ hdr->ver = IMX_SC_RPC_VERSION;
+ hdr->svc = IMX_SC_RPC_SVC_PM;
+ hdr->func = IMX_SC_PM_FUNC_GET_CLOCK_RATE;
+ hdr->size = 2;
+
+ msg.data.req.resource = clk->rsrc_id;
+ msg.data.req.clk = clk->clk_type;
+
+ ret = imx_scu_call_rpc(ccm_ipc_handle, &msg, true);
+ if (ret) {
+ pr_err("%s: failed to get clock rate %d\n",
+ clk_hw_get_name(hw), ret);
+ return 0;
+ }
+
+ return msg.data.resp.rate;
+}
+
+/*
+ * clk_scu_round_rate - Round clock rate for a SCU clock
+ * @hw: clock to round rate for
+ * @rate: rate to round
+ * @parent_rate: parent rate provided by common clock framework, not used
+ *
+ * Gets the current clock rate of a SCU clock. Returns the current
+ * clock rate, or zero in failure.
+ */
+static long clk_scu_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ /*
+ * Assume we support all the requested rate and let the SCU firmware
+ * to handle the left work
+ */
+ return rate;
+}
+
+/*
+ * clk_scu_set_rate - Set rate for a SCU clock
+ * @hw: clock to change rate for
+ * @rate: target rate for the clock
+ * @parent_rate: rate of the clock parent, not used for SCU clocks
+ *
+ * Sets a clock frequency for a SCU clock. Returns the SCU
+ * protocol status.
+ */
+static int clk_scu_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_scu *clk = to_clk_scu(hw);
+ struct imx_sc_msg_req_set_clock_rate msg;
+ struct imx_sc_rpc_msg *hdr = &msg.hdr;
+
+ hdr->ver = IMX_SC_RPC_VERSION;
+ hdr->svc = IMX_SC_RPC_SVC_PM;
+ hdr->func = IMX_SC_PM_FUNC_SET_CLOCK_RATE;
+ hdr->size = 3;
+
+ msg.rate = rate;
+ msg.resource = clk->rsrc_id;
+ msg.clk = clk->clk_type;
+
+ return imx_scu_call_rpc(ccm_ipc_handle, &msg, true);
+}
+
+static int sc_pm_clock_enable(struct imx_sc_ipc *ipc, u32 resource,
+ u8 clk, bool enable, bool autog)
+{
+ struct imx_sc_msg_req_clock_enable msg;
+ struct imx_sc_rpc_msg *hdr = &msg.hdr;
+
+ hdr->ver = IMX_SC_RPC_VERSION;
+ hdr->svc = IMX_SC_RPC_SVC_PM;
+ hdr->func = IMX_SC_PM_FUNC_CLOCK_ENABLE;
+ hdr->size = 3;
+
+ msg.resource = resource;
+ msg.clk = clk;
+ msg.enable = enable;
+ msg.autog = autog;
+
+ return imx_scu_call_rpc(ccm_ipc_handle, &msg, true);
+}
+
+/*
+ * clk_scu_prepare - Enable a SCU clock
+ * @hw: clock to enable
+ *
+ * Enable the clock at the DSC slice level
+ */
+static int clk_scu_prepare(struct clk_hw *hw)
+{
+ struct clk_scu *clk = to_clk_scu(hw);
+
+ return sc_pm_clock_enable(ccm_ipc_handle, clk->rsrc_id,
+ clk->clk_type, true, false);
+}
+
+/*
+ * clk_scu_unprepare - Disable a SCU clock
+ * @hw: clock to enable
+ *
+ * Disable the clock at the DSC slice level
+ */
+static void clk_scu_unprepare(struct clk_hw *hw)
+{
+ struct clk_scu *clk = to_clk_scu(hw);
+ int ret;
+
+ ret = sc_pm_clock_enable(ccm_ipc_handle, clk->rsrc_id,
+ clk->clk_type, false, false);
+ if (ret)
+ pr_warn("%s: clk unprepare failed %d\n", clk_hw_get_name(hw),
+ ret);
+}
+
+static const struct clk_ops clk_scu_ops = {
+ .recalc_rate = clk_scu_recalc_rate,
+ .round_rate = clk_scu_round_rate,
+ .set_rate = clk_scu_set_rate,
+ .prepare = clk_scu_prepare,
+ .unprepare = clk_scu_unprepare,
+};
+
+struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id, u8 clk_type)
+{
+ struct clk_init_data init;
+ struct clk_scu *clk;
+ struct clk_hw *hw;
+ int ret;
+
+ clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+ if (!clk)
+ return ERR_PTR(-ENOMEM);
+
+ clk->rsrc_id = rsrc_id;
+ clk->clk_type = clk_type;
+
+ init.name = name;
+ init.ops = &clk_scu_ops;
+ init.num_parents = 0;
+ /*
+ * Note on MX8, the clocks are tightly coupled with power domain
+ * that once the power domain is off, the clock status may be
+ * lost. So we make it NOCACHE to let user to retrieve the real
+ * clock status from HW instead of using the possible invalid
+ * cached rate.
+ */
+ init.flags = CLK_GET_RATE_NOCACHE;
+ clk->hw.init = &init;
+
+ hw = &clk->hw;
+ ret = clk_hw_register(NULL, hw);
+ if (ret) {
+ kfree(clk);
+ hw = ERR_PTR(ret);
+ }
+
+ return hw;
+}
diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h
new file mode 100644
index 0000000..09f381b
--- /dev/null
+++ b/drivers/clk/imx/clk-scu.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2018 NXP
+ * Dong Aisheng <aisheng.dong@nxp.com>
+ */
+
+#ifndef __IMX_CLK_SCU_H
+#define __IMX_CLK_SCU_H
+
+#include <linux/firmware/imx/sci.h>
+
+extern struct imx_sc_ipc *ccm_ipc_handle;
+
+static inline int imx_clk_scu_init(void)
+{
+ return imx_scu_get_handle(&ccm_ipc_handle);
+}
+
+struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id, u8 clk_type);
+
+#endif
--
2.7.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH V6 1/6] clk: imx: add scu clock common part
@ 2018-11-10 15:19 ` A.s. Dong
0 siblings, 0 replies; 36+ messages in thread
From: A.s. Dong @ 2018-11-10 15:19 UTC (permalink / raw)
To: linux-arm-kernel
Add scu clock common part which will be used by client clock drivers.
SCU clocks are totally different from the legacy clocks (No much
legacy things can be reused). So a new configuration option
CONFIG_MXC_CLK_SCU is added.
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: Fabio Estevam <fabio.estevam@nxp.com>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Michael Turquette <mturquette@baylibre.com>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
ChangeLog:
v5->v6:
* simply the whole clock driver a lot by re-orgnizing the driver into a
few clock types:: scu clock (merge scu divider/gate/mux) and scu gpr lock
which accessing is through SCU protocol and LPCG clock which is directly
accessible by CPU.
* LPCG clock support will be added in next patch, gpr clock is still not used
and will be added later.
* remove old year license as the code is totally rewritten
* scu mux support will be added later as it's also still not used.
v4->v5:
* add more explanation in commit message on why put scu clocks
in a deeper folder.
* move scu clk files into the top directory of imx folder
v3->v4:
* scu headfile path change
v2->v3:
* no changes
v1->v2:
* update function call name
---
drivers/clk/imx/Kconfig | 4 +
drivers/clk/imx/Makefile | 3 +
drivers/clk/imx/clk-scu.c | 237 ++++++++++++++++++++++++++++++++++++++++++++++
drivers/clk/imx/clk-scu.h | 21 ++++
4 files changed, 265 insertions(+)
create mode 100644 drivers/clk/imx/clk-scu.c
create mode 100644 drivers/clk/imx/clk-scu.h
diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig
index 43a3ecc..63e7b01 100644
--- a/drivers/clk/imx/Kconfig
+++ b/drivers/clk/imx/Kconfig
@@ -3,3 +3,7 @@
config MXC_CLK
bool
depends on ARCH_MXC
+
+config MXC_CLK_SCU
+ bool
+ depends on ARCH_MXC && ARM64
diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index d447f8c..eec6d72 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -13,6 +13,9 @@ obj-$(CONFIG_MXC_CLK) += \
clk-pllv3.o \
clk-pfd.o
+obj-$(CONFIG_MXC_CLK_SCU) += \
+ clk-scu.o
+
obj-$(CONFIG_SOC_IMX1) += clk-imx1.o
obj-$(CONFIG_SOC_IMX21) += clk-imx21.o
obj-$(CONFIG_SOC_IMX25) += clk-imx25.o
diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c
new file mode 100644
index 0000000..9fec574
--- /dev/null
+++ b/drivers/clk/imx/clk-scu.c
@@ -0,0 +1,237 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ * Dong Aisheng <aisheng.dong@nxp.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include "clk-scu.h"
+
+struct imx_sc_ipc *ccm_ipc_handle;
+
+struct clk_scu {
+ struct clk_hw hw;
+ u32 rsrc_id;
+ u8 clk_type;
+};
+
+/* SCU Clock Protocol definitions */
+
+/* rate */
+struct imx_sc_msg_req_set_clock_rate {
+ struct imx_sc_rpc_msg hdr;
+ u32 rate;
+ u16 resource;
+ u8 clk;
+} __packed;
+
+struct req_get_clock_rate {
+ u16 resource;
+ u8 clk;
+} __packed;
+
+struct resp_get_clock_rate {
+ u32 rate;
+};
+
+struct imx_sc_msg_get_clock_rate {
+ struct imx_sc_rpc_msg hdr;
+ union {
+ struct req_get_clock_rate req;
+ struct resp_get_clock_rate resp;
+ } data;
+} __packed;
+
+/* gate */
+struct imx_sc_msg_req_clock_enable {
+ struct imx_sc_rpc_msg hdr;
+ u16 resource;
+ u8 clk;
+ u8 enable;
+ u8 autog;
+} __packed;
+
+static inline struct clk_scu *to_clk_scu(struct clk_hw *hw)
+{
+ return container_of(hw, struct clk_scu, hw);
+}
+
+/*
+ * clk_scu_recalc_rate - Get clock rate for a SCU clock
+ * @hw: clock to get rate for
+ * @parent_rate: parent rate provided by common clock framework, not used
+ *
+ * Gets the current clock rate of a SCU clock. Returns the current
+ * clock rate, or zero in failure.
+ */
+static unsigned long clk_scu_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_scu *clk = to_clk_scu(hw);
+ struct imx_sc_msg_get_clock_rate msg;
+ struct imx_sc_rpc_msg *hdr = &msg.hdr;
+ int ret;
+
+ hdr->ver = IMX_SC_RPC_VERSION;
+ hdr->svc = IMX_SC_RPC_SVC_PM;
+ hdr->func = IMX_SC_PM_FUNC_GET_CLOCK_RATE;
+ hdr->size = 2;
+
+ msg.data.req.resource = clk->rsrc_id;
+ msg.data.req.clk = clk->clk_type;
+
+ ret = imx_scu_call_rpc(ccm_ipc_handle, &msg, true);
+ if (ret) {
+ pr_err("%s: failed to get clock rate %d\n",
+ clk_hw_get_name(hw), ret);
+ return 0;
+ }
+
+ return msg.data.resp.rate;
+}
+
+/*
+ * clk_scu_round_rate - Round clock rate for a SCU clock
+ * @hw: clock to round rate for
+ * @rate: rate to round
+ * @parent_rate: parent rate provided by common clock framework, not used
+ *
+ * Gets the current clock rate of a SCU clock. Returns the current
+ * clock rate, or zero in failure.
+ */
+static long clk_scu_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ /*
+ * Assume we support all the requested rate and let the SCU firmware
+ * to handle the left work
+ */
+ return rate;
+}
+
+/*
+ * clk_scu_set_rate - Set rate for a SCU clock
+ * @hw: clock to change rate for
+ * @rate: target rate for the clock
+ * @parent_rate: rate of the clock parent, not used for SCU clocks
+ *
+ * Sets a clock frequency for a SCU clock. Returns the SCU
+ * protocol status.
+ */
+static int clk_scu_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_scu *clk = to_clk_scu(hw);
+ struct imx_sc_msg_req_set_clock_rate msg;
+ struct imx_sc_rpc_msg *hdr = &msg.hdr;
+
+ hdr->ver = IMX_SC_RPC_VERSION;
+ hdr->svc = IMX_SC_RPC_SVC_PM;
+ hdr->func = IMX_SC_PM_FUNC_SET_CLOCK_RATE;
+ hdr->size = 3;
+
+ msg.rate = rate;
+ msg.resource = clk->rsrc_id;
+ msg.clk = clk->clk_type;
+
+ return imx_scu_call_rpc(ccm_ipc_handle, &msg, true);
+}
+
+static int sc_pm_clock_enable(struct imx_sc_ipc *ipc, u32 resource,
+ u8 clk, bool enable, bool autog)
+{
+ struct imx_sc_msg_req_clock_enable msg;
+ struct imx_sc_rpc_msg *hdr = &msg.hdr;
+
+ hdr->ver = IMX_SC_RPC_VERSION;
+ hdr->svc = IMX_SC_RPC_SVC_PM;
+ hdr->func = IMX_SC_PM_FUNC_CLOCK_ENABLE;
+ hdr->size = 3;
+
+ msg.resource = resource;
+ msg.clk = clk;
+ msg.enable = enable;
+ msg.autog = autog;
+
+ return imx_scu_call_rpc(ccm_ipc_handle, &msg, true);
+}
+
+/*
+ * clk_scu_prepare - Enable a SCU clock
+ * @hw: clock to enable
+ *
+ * Enable the clock at the DSC slice level
+ */
+static int clk_scu_prepare(struct clk_hw *hw)
+{
+ struct clk_scu *clk = to_clk_scu(hw);
+
+ return sc_pm_clock_enable(ccm_ipc_handle, clk->rsrc_id,
+ clk->clk_type, true, false);
+}
+
+/*
+ * clk_scu_unprepare - Disable a SCU clock
+ * @hw: clock to enable
+ *
+ * Disable the clock at the DSC slice level
+ */
+static void clk_scu_unprepare(struct clk_hw *hw)
+{
+ struct clk_scu *clk = to_clk_scu(hw);
+ int ret;
+
+ ret = sc_pm_clock_enable(ccm_ipc_handle, clk->rsrc_id,
+ clk->clk_type, false, false);
+ if (ret)
+ pr_warn("%s: clk unprepare failed %d\n", clk_hw_get_name(hw),
+ ret);
+}
+
+static const struct clk_ops clk_scu_ops = {
+ .recalc_rate = clk_scu_recalc_rate,
+ .round_rate = clk_scu_round_rate,
+ .set_rate = clk_scu_set_rate,
+ .prepare = clk_scu_prepare,
+ .unprepare = clk_scu_unprepare,
+};
+
+struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id, u8 clk_type)
+{
+ struct clk_init_data init;
+ struct clk_scu *clk;
+ struct clk_hw *hw;
+ int ret;
+
+ clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+ if (!clk)
+ return ERR_PTR(-ENOMEM);
+
+ clk->rsrc_id = rsrc_id;
+ clk->clk_type = clk_type;
+
+ init.name = name;
+ init.ops = &clk_scu_ops;
+ init.num_parents = 0;
+ /*
+ * Note on MX8, the clocks are tightly coupled with power domain
+ * that once the power domain is off, the clock status may be
+ * lost. So we make it NOCACHE to let user to retrieve the real
+ * clock status from HW instead of using the possible invalid
+ * cached rate.
+ */
+ init.flags = CLK_GET_RATE_NOCACHE;
+ clk->hw.init = &init;
+
+ hw = &clk->hw;
+ ret = clk_hw_register(NULL, hw);
+ if (ret) {
+ kfree(clk);
+ hw = ERR_PTR(ret);
+ }
+
+ return hw;
+}
diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h
new file mode 100644
index 0000000..09f381b
--- /dev/null
+++ b/drivers/clk/imx/clk-scu.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2018 NXP
+ * Dong Aisheng <aisheng.dong@nxp.com>
+ */
+
+#ifndef __IMX_CLK_SCU_H
+#define __IMX_CLK_SCU_H
+
+#include <linux/firmware/imx/sci.h>
+
+extern struct imx_sc_ipc *ccm_ipc_handle;
+
+static inline int imx_clk_scu_init(void)
+{
+ return imx_scu_get_handle(&ccm_ipc_handle);
+}
+
+struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id, u8 clk_type);
+
+#endif
--
2.7.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH V6 2/6] dt-bindings: clock: imx8qxp: add SCU clock IDs
2018-11-10 15:19 ` A.s. Dong
(?)
@ 2018-11-10 15:19 ` A.s. Dong
-1 siblings, 0 replies; 36+ messages in thread
From: A.s. Dong @ 2018-11-10 15:19 UTC (permalink / raw)
To: linux-clk
Cc: A.s. Dong, devicetree, sboyd, mturquette, Rob Herring,
dl-linux-imx, kernel, Fabio Estevam, shawnguo, linux-arm-kernel
Add IMX8QXP SCU clock IDs.
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: devicetree@vger.kernel.org
Cc: linux-clk@vger.kernel.org
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
v6: new patch, separate from driver changes to avoid a checkpatch warning
IDs are changed a lot due to SCU divider/gate/mux are merged into
one general SCU clock and LPCG clocks are moved out.
---
include/dt-bindings/clock/imx8qxp-clock.h | 136 ++++++++++++++++++++++++++++++
1 file changed, 136 insertions(+)
create mode 100644 include/dt-bindings/clock/imx8qxp-clock.h
diff --git a/include/dt-bindings/clock/imx8qxp-clock.h b/include/dt-bindings/clock/imx8qxp-clock.h
new file mode 100644
index 0000000..d72a39c
--- /dev/null
+++ b/include/dt-bindings/clock/imx8qxp-clock.h
@@ -0,0 +1,136 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2018 NXP
+ * Dong Aisheng <aisheng.dong@nxp.com>
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_IMX8QXP_H
+#define __DT_BINDINGS_CLOCK_IMX8QXP_H
+
+/* SCU Clocks */
+
+#define IMX8QXP_CLK_DUMMY 0
+
+/* CPU */
+#define IMX8QXP_A35_CLK 1
+
+/* LSIO SS */
+#define IMX8QXP_LSIO_MEM_CLK 2
+#define IMX8QXP_LSIO_BUS_CLK 3
+#define IMX8QXP_LSIO_PWM0_CLK 10
+#define IMX8QXP_LSIO_PWM1_CLK 11
+#define IMX8QXP_LSIO_PWM2_CLK 12
+#define IMX8QXP_LSIO_PWM3_CLK 13
+#define IMX8QXP_LSIO_PWM4_CLK 14
+#define IMX8QXP_LSIO_PWM5_CLK 15
+#define IMX8QXP_LSIO_PWM6_CLK 16
+#define IMX8QXP_LSIO_PWM7_CLK 17
+#define IMX8QXP_LSIO_GPT0_CLK 18
+#define IMX8QXP_LSIO_GPT1_CLK 19
+#define IMX8QXP_LSIO_GPT2_CLK 20
+#define IMX8QXP_LSIO_GPT3_CLK 21
+#define IMX8QXP_LSIO_GPT4_CLK 22
+#define IMX8QXP_LSIO_FSPI0_CLK 23
+#define IMX8QXP_LSIO_FSPI1_CLK 24
+
+/* Connectivity SS */
+#define IMX8QXP_CONN_AXI_CLK_ROOT 30
+#define IMX8QXP_CONN_AHB_CLK_ROOT 31
+#define IMX8QXP_CONN_IPG_CLK_ROOT 32
+#define IMX8QXP_CONN_SDHC0_CLK 40
+#define IMX8QXP_CONN_SDHC1_CLK 41
+#define IMX8QXP_CONN_SDHC2_CLK 42
+#define IMX8QXP_CONN_ENET0_ROOT_CLK 43
+#define IMX8QXP_CONN_ENET0_BYPASS_CLK 44
+#define IMX8QXP_CONN_ENET0_RGMII_CLK 45
+#define IMX8QXP_CONN_ENET1_ROOT_CLK 46
+#define IMX8QXP_CONN_ENET1_BYPASS_CLK 47
+#define IMX8QXP_CONN_ENET1_RGMII_CLK 48
+#define IMX8QXP_CONN_GPMI_BCH_IO_CLK 49
+#define IMX8QXP_CONN_GPMI_BCH_CLK 50
+#define IMX8QXP_CONN_USB2_ACLK 51
+#define IMX8QXP_CONN_USB2_BUS_CLK 52
+#define IMX8QXP_CONN_USB2_LPM_CLK 53
+
+/* HSIO SS */
+#define IMX8QXP_HSIO_AXI_CLK 60
+#define IMX8QXP_HSIO_PER_CLK 61
+
+/* Display controller SS */
+#define IMX8QXP_DC_AXI_EXT_CLK 70
+#define IMX8QXP_DC_AXI_INT_CLK 71
+#define IMX8QXP_DC_CFG_CLK 72
+#define IMX8QXP_DC0_PLL0_CLK 80
+#define IMX8QXP_DC0_PLL1_CLK 81
+#define IMX8QXP_DC0_DISP0_CLK 82
+#define IMX8QXP_DC0_DISP1_CLK 83
+
+/* MIPI-LVDS SS */
+#define IMX8QXP_MIPI_IPG_CLK 90
+#define IMX8QXP_MIPI0_PIXEL_CLK 100
+#define IMX8QXP_MIPI0_BYPASS_CLK 101
+#define IMX8QXP_MIPI0_LVDS_PIXEL_CLK 102
+#define IMX8QXP_MIPI0_LVDS_BYPASS_CLK 103
+#define IMX8QXP_MIPI0_LVDS_PHY_CLK 104
+#define IMX8QXP_MIPI0_I2C0_CLK 105
+#define IMX8QXP_MIPI0_I2C1_CLK 106
+#define IMX8QXP_MIPI0_PWM0_CLK 107
+#define IMX8QXP_MIPI1_PIXEL_CLK 108
+#define IMX8QXP_MIPI1_BYPASS_CLK 109
+#define IMX8QXP_MIPI1_LVDS_PIXEL_CLK 110
+#define IMX8QXP_MIPI1_LVDS_BYPASS_CLK 111
+#define IMX8QXP_MIPI1_LVDS_PHY_CLK 112
+#define IMX8QXP_MIPI1_I2C0_CLK 113
+#define IMX8QXP_MIPI1_I2C1_CLK 114
+#define IMX8QXP_MIPI1_PWM0_CLK 115
+
+/* IMG SS */
+#define IMX8QXP_IMG_AXI_CLK 120
+#define IMX8QXP_IMG_IPG_CLK 121
+#define IMX8QXP_IMG_PXL_CLK 122
+
+/* MIPI-CSI SS */
+#define IMX8QXP_CSI0_CORE_CLK 130
+#define IMX8QXP_CSI0_ESC_CLK 131
+#define IMX8QXP_CSI0_PWM0_CLK 132
+#define IMX8QXP_CSI0_I2C0_CLK 133
+
+/* PARALLER CSI SS */
+#define IMX8QXP_PARALLEL_CSI_DPLL_CLK 140
+#define IMX8QXP_PARALLEL_CSI_PIXEL_CLK 141
+#define IMX8QXP_PARALLEL_CSI_MCLK_CLK 142
+
+/* VPU SS */
+#define IMX8QXP_VPU_ENC_CLK 150
+#define IMX8QXP_VPU_DEC_CLK 151
+
+/* GPU SS */
+#define IMX8QXP_GPU0_CORE_CLK 160
+#define IMX8QXP_GPU0_SHADER_CLK 161
+
+/* ADMA SS */
+#define IMX8QXP_ADMA_IPG_CLK_ROOT 165
+#define IMX8QXP_ADMA_UART0_CLK 170
+#define IMX8QXP_ADMA_UART1_CLK 171
+#define IMX8QXP_ADMA_UART2_CLK 172
+#define IMX8QXP_ADMA_UART3_CLK 173
+#define IMX8QXP_ADMA_SPI0_CLK 174
+#define IMX8QXP_ADMA_SPI1_CLK 175
+#define IMX8QXP_ADMA_SPI2_CLK 176
+#define IMX8QXP_ADMA_SPI3_CLK 177
+#define IMX8QXP_ADMA_CAN0_CLK 178
+#define IMX8QXP_ADMA_CAN1_CLK 179
+#define IMX8QXP_ADMA_CAN2_CLK 180
+#define IMX8QXP_ADMA_I2C0_CLK 181
+#define IMX8QXP_ADMA_I2C1_CLK 182
+#define IMX8QXP_ADMA_I2C2_CLK 183
+#define IMX8QXP_ADMA_I2C3_CLK 184
+#define IMX8QXP_ADMA_FTM0_CLK 185
+#define IMX8QXP_ADMA_FTM1_CLK 186
+#define IMX8QXP_ADMA_ADC0_CLK 187
+#define IMX8QXP_ADMA_PWM_CLK 188
+#define IMX8QXP_ADMA_LCD_CLK 189
+
+#define IMX8QXP_SCU_CLK_END 190
+
+#endif /* __DT_BINDINGS_CLOCK_IMX8QXP_H */
--
2.7.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH V6 2/6] dt-bindings: clock: imx8qxp: add SCU clock IDs
@ 2018-11-10 15:19 ` A.s. Dong
0 siblings, 0 replies; 36+ messages in thread
From: A.s. Dong @ 2018-11-10 15:19 UTC (permalink / raw)
To: linux-clk
Cc: linux-arm-kernel, sboyd, mturquette, shawnguo, Fabio Estevam,
dl-linux-imx, kernel, A.s. Dong, Rob Herring, devicetree
Add IMX8QXP SCU clock IDs.
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: devicetree@vger.kernel.org
Cc: linux-clk@vger.kernel.org
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
v6: new patch, separate from driver changes to avoid a checkpatch warning
IDs are changed a lot due to SCU divider/gate/mux are merged into
one general SCU clock and LPCG clocks are moved out.
---
include/dt-bindings/clock/imx8qxp-clock.h | 136 ++++++++++++++++++++++++++++++
1 file changed, 136 insertions(+)
create mode 100644 include/dt-bindings/clock/imx8qxp-clock.h
diff --git a/include/dt-bindings/clock/imx8qxp-clock.h b/include/dt-bindings/clock/imx8qxp-clock.h
new file mode 100644
index 0000000..d72a39c
--- /dev/null
+++ b/include/dt-bindings/clock/imx8qxp-clock.h
@@ -0,0 +1,136 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2018 NXP
+ * Dong Aisheng <aisheng.dong@nxp.com>
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_IMX8QXP_H
+#define __DT_BINDINGS_CLOCK_IMX8QXP_H
+
+/* SCU Clocks */
+
+#define IMX8QXP_CLK_DUMMY 0
+
+/* CPU */
+#define IMX8QXP_A35_CLK 1
+
+/* LSIO SS */
+#define IMX8QXP_LSIO_MEM_CLK 2
+#define IMX8QXP_LSIO_BUS_CLK 3
+#define IMX8QXP_LSIO_PWM0_CLK 10
+#define IMX8QXP_LSIO_PWM1_CLK 11
+#define IMX8QXP_LSIO_PWM2_CLK 12
+#define IMX8QXP_LSIO_PWM3_CLK 13
+#define IMX8QXP_LSIO_PWM4_CLK 14
+#define IMX8QXP_LSIO_PWM5_CLK 15
+#define IMX8QXP_LSIO_PWM6_CLK 16
+#define IMX8QXP_LSIO_PWM7_CLK 17
+#define IMX8QXP_LSIO_GPT0_CLK 18
+#define IMX8QXP_LSIO_GPT1_CLK 19
+#define IMX8QXP_LSIO_GPT2_CLK 20
+#define IMX8QXP_LSIO_GPT3_CLK 21
+#define IMX8QXP_LSIO_GPT4_CLK 22
+#define IMX8QXP_LSIO_FSPI0_CLK 23
+#define IMX8QXP_LSIO_FSPI1_CLK 24
+
+/* Connectivity SS */
+#define IMX8QXP_CONN_AXI_CLK_ROOT 30
+#define IMX8QXP_CONN_AHB_CLK_ROOT 31
+#define IMX8QXP_CONN_IPG_CLK_ROOT 32
+#define IMX8QXP_CONN_SDHC0_CLK 40
+#define IMX8QXP_CONN_SDHC1_CLK 41
+#define IMX8QXP_CONN_SDHC2_CLK 42
+#define IMX8QXP_CONN_ENET0_ROOT_CLK 43
+#define IMX8QXP_CONN_ENET0_BYPASS_CLK 44
+#define IMX8QXP_CONN_ENET0_RGMII_CLK 45
+#define IMX8QXP_CONN_ENET1_ROOT_CLK 46
+#define IMX8QXP_CONN_ENET1_BYPASS_CLK 47
+#define IMX8QXP_CONN_ENET1_RGMII_CLK 48
+#define IMX8QXP_CONN_GPMI_BCH_IO_CLK 49
+#define IMX8QXP_CONN_GPMI_BCH_CLK 50
+#define IMX8QXP_CONN_USB2_ACLK 51
+#define IMX8QXP_CONN_USB2_BUS_CLK 52
+#define IMX8QXP_CONN_USB2_LPM_CLK 53
+
+/* HSIO SS */
+#define IMX8QXP_HSIO_AXI_CLK 60
+#define IMX8QXP_HSIO_PER_CLK 61
+
+/* Display controller SS */
+#define IMX8QXP_DC_AXI_EXT_CLK 70
+#define IMX8QXP_DC_AXI_INT_CLK 71
+#define IMX8QXP_DC_CFG_CLK 72
+#define IMX8QXP_DC0_PLL0_CLK 80
+#define IMX8QXP_DC0_PLL1_CLK 81
+#define IMX8QXP_DC0_DISP0_CLK 82
+#define IMX8QXP_DC0_DISP1_CLK 83
+
+/* MIPI-LVDS SS */
+#define IMX8QXP_MIPI_IPG_CLK 90
+#define IMX8QXP_MIPI0_PIXEL_CLK 100
+#define IMX8QXP_MIPI0_BYPASS_CLK 101
+#define IMX8QXP_MIPI0_LVDS_PIXEL_CLK 102
+#define IMX8QXP_MIPI0_LVDS_BYPASS_CLK 103
+#define IMX8QXP_MIPI0_LVDS_PHY_CLK 104
+#define IMX8QXP_MIPI0_I2C0_CLK 105
+#define IMX8QXP_MIPI0_I2C1_CLK 106
+#define IMX8QXP_MIPI0_PWM0_CLK 107
+#define IMX8QXP_MIPI1_PIXEL_CLK 108
+#define IMX8QXP_MIPI1_BYPASS_CLK 109
+#define IMX8QXP_MIPI1_LVDS_PIXEL_CLK 110
+#define IMX8QXP_MIPI1_LVDS_BYPASS_CLK 111
+#define IMX8QXP_MIPI1_LVDS_PHY_CLK 112
+#define IMX8QXP_MIPI1_I2C0_CLK 113
+#define IMX8QXP_MIPI1_I2C1_CLK 114
+#define IMX8QXP_MIPI1_PWM0_CLK 115
+
+/* IMG SS */
+#define IMX8QXP_IMG_AXI_CLK 120
+#define IMX8QXP_IMG_IPG_CLK 121
+#define IMX8QXP_IMG_PXL_CLK 122
+
+/* MIPI-CSI SS */
+#define IMX8QXP_CSI0_CORE_CLK 130
+#define IMX8QXP_CSI0_ESC_CLK 131
+#define IMX8QXP_CSI0_PWM0_CLK 132
+#define IMX8QXP_CSI0_I2C0_CLK 133
+
+/* PARALLER CSI SS */
+#define IMX8QXP_PARALLEL_CSI_DPLL_CLK 140
+#define IMX8QXP_PARALLEL_CSI_PIXEL_CLK 141
+#define IMX8QXP_PARALLEL_CSI_MCLK_CLK 142
+
+/* VPU SS */
+#define IMX8QXP_VPU_ENC_CLK 150
+#define IMX8QXP_VPU_DEC_CLK 151
+
+/* GPU SS */
+#define IMX8QXP_GPU0_CORE_CLK 160
+#define IMX8QXP_GPU0_SHADER_CLK 161
+
+/* ADMA SS */
+#define IMX8QXP_ADMA_IPG_CLK_ROOT 165
+#define IMX8QXP_ADMA_UART0_CLK 170
+#define IMX8QXP_ADMA_UART1_CLK 171
+#define IMX8QXP_ADMA_UART2_CLK 172
+#define IMX8QXP_ADMA_UART3_CLK 173
+#define IMX8QXP_ADMA_SPI0_CLK 174
+#define IMX8QXP_ADMA_SPI1_CLK 175
+#define IMX8QXP_ADMA_SPI2_CLK 176
+#define IMX8QXP_ADMA_SPI3_CLK 177
+#define IMX8QXP_ADMA_CAN0_CLK 178
+#define IMX8QXP_ADMA_CAN1_CLK 179
+#define IMX8QXP_ADMA_CAN2_CLK 180
+#define IMX8QXP_ADMA_I2C0_CLK 181
+#define IMX8QXP_ADMA_I2C1_CLK 182
+#define IMX8QXP_ADMA_I2C2_CLK 183
+#define IMX8QXP_ADMA_I2C3_CLK 184
+#define IMX8QXP_ADMA_FTM0_CLK 185
+#define IMX8QXP_ADMA_FTM1_CLK 186
+#define IMX8QXP_ADMA_ADC0_CLK 187
+#define IMX8QXP_ADMA_PWM_CLK 188
+#define IMX8QXP_ADMA_LCD_CLK 189
+
+#define IMX8QXP_SCU_CLK_END 190
+
+#endif /* __DT_BINDINGS_CLOCK_IMX8QXP_H */
--
2.7.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH V6 2/6] dt-bindings: clock: imx8qxp: add SCU clock IDs
@ 2018-11-10 15:19 ` A.s. Dong
0 siblings, 0 replies; 36+ messages in thread
From: A.s. Dong @ 2018-11-10 15:19 UTC (permalink / raw)
To: linux-arm-kernel
Add IMX8QXP SCU clock IDs.
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: devicetree at vger.kernel.org
Cc: linux-clk at vger.kernel.org
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
v6: new patch, separate from driver changes to avoid a checkpatch warning
IDs are changed a lot due to SCU divider/gate/mux are merged into
one general SCU clock and LPCG clocks are moved out.
---
include/dt-bindings/clock/imx8qxp-clock.h | 136 ++++++++++++++++++++++++++++++
1 file changed, 136 insertions(+)
create mode 100644 include/dt-bindings/clock/imx8qxp-clock.h
diff --git a/include/dt-bindings/clock/imx8qxp-clock.h b/include/dt-bindings/clock/imx8qxp-clock.h
new file mode 100644
index 0000000..d72a39c
--- /dev/null
+++ b/include/dt-bindings/clock/imx8qxp-clock.h
@@ -0,0 +1,136 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2018 NXP
+ * Dong Aisheng <aisheng.dong@nxp.com>
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_IMX8QXP_H
+#define __DT_BINDINGS_CLOCK_IMX8QXP_H
+
+/* SCU Clocks */
+
+#define IMX8QXP_CLK_DUMMY 0
+
+/* CPU */
+#define IMX8QXP_A35_CLK 1
+
+/* LSIO SS */
+#define IMX8QXP_LSIO_MEM_CLK 2
+#define IMX8QXP_LSIO_BUS_CLK 3
+#define IMX8QXP_LSIO_PWM0_CLK 10
+#define IMX8QXP_LSIO_PWM1_CLK 11
+#define IMX8QXP_LSIO_PWM2_CLK 12
+#define IMX8QXP_LSIO_PWM3_CLK 13
+#define IMX8QXP_LSIO_PWM4_CLK 14
+#define IMX8QXP_LSIO_PWM5_CLK 15
+#define IMX8QXP_LSIO_PWM6_CLK 16
+#define IMX8QXP_LSIO_PWM7_CLK 17
+#define IMX8QXP_LSIO_GPT0_CLK 18
+#define IMX8QXP_LSIO_GPT1_CLK 19
+#define IMX8QXP_LSIO_GPT2_CLK 20
+#define IMX8QXP_LSIO_GPT3_CLK 21
+#define IMX8QXP_LSIO_GPT4_CLK 22
+#define IMX8QXP_LSIO_FSPI0_CLK 23
+#define IMX8QXP_LSIO_FSPI1_CLK 24
+
+/* Connectivity SS */
+#define IMX8QXP_CONN_AXI_CLK_ROOT 30
+#define IMX8QXP_CONN_AHB_CLK_ROOT 31
+#define IMX8QXP_CONN_IPG_CLK_ROOT 32
+#define IMX8QXP_CONN_SDHC0_CLK 40
+#define IMX8QXP_CONN_SDHC1_CLK 41
+#define IMX8QXP_CONN_SDHC2_CLK 42
+#define IMX8QXP_CONN_ENET0_ROOT_CLK 43
+#define IMX8QXP_CONN_ENET0_BYPASS_CLK 44
+#define IMX8QXP_CONN_ENET0_RGMII_CLK 45
+#define IMX8QXP_CONN_ENET1_ROOT_CLK 46
+#define IMX8QXP_CONN_ENET1_BYPASS_CLK 47
+#define IMX8QXP_CONN_ENET1_RGMII_CLK 48
+#define IMX8QXP_CONN_GPMI_BCH_IO_CLK 49
+#define IMX8QXP_CONN_GPMI_BCH_CLK 50
+#define IMX8QXP_CONN_USB2_ACLK 51
+#define IMX8QXP_CONN_USB2_BUS_CLK 52
+#define IMX8QXP_CONN_USB2_LPM_CLK 53
+
+/* HSIO SS */
+#define IMX8QXP_HSIO_AXI_CLK 60
+#define IMX8QXP_HSIO_PER_CLK 61
+
+/* Display controller SS */
+#define IMX8QXP_DC_AXI_EXT_CLK 70
+#define IMX8QXP_DC_AXI_INT_CLK 71
+#define IMX8QXP_DC_CFG_CLK 72
+#define IMX8QXP_DC0_PLL0_CLK 80
+#define IMX8QXP_DC0_PLL1_CLK 81
+#define IMX8QXP_DC0_DISP0_CLK 82
+#define IMX8QXP_DC0_DISP1_CLK 83
+
+/* MIPI-LVDS SS */
+#define IMX8QXP_MIPI_IPG_CLK 90
+#define IMX8QXP_MIPI0_PIXEL_CLK 100
+#define IMX8QXP_MIPI0_BYPASS_CLK 101
+#define IMX8QXP_MIPI0_LVDS_PIXEL_CLK 102
+#define IMX8QXP_MIPI0_LVDS_BYPASS_CLK 103
+#define IMX8QXP_MIPI0_LVDS_PHY_CLK 104
+#define IMX8QXP_MIPI0_I2C0_CLK 105
+#define IMX8QXP_MIPI0_I2C1_CLK 106
+#define IMX8QXP_MIPI0_PWM0_CLK 107
+#define IMX8QXP_MIPI1_PIXEL_CLK 108
+#define IMX8QXP_MIPI1_BYPASS_CLK 109
+#define IMX8QXP_MIPI1_LVDS_PIXEL_CLK 110
+#define IMX8QXP_MIPI1_LVDS_BYPASS_CLK 111
+#define IMX8QXP_MIPI1_LVDS_PHY_CLK 112
+#define IMX8QXP_MIPI1_I2C0_CLK 113
+#define IMX8QXP_MIPI1_I2C1_CLK 114
+#define IMX8QXP_MIPI1_PWM0_CLK 115
+
+/* IMG SS */
+#define IMX8QXP_IMG_AXI_CLK 120
+#define IMX8QXP_IMG_IPG_CLK 121
+#define IMX8QXP_IMG_PXL_CLK 122
+
+/* MIPI-CSI SS */
+#define IMX8QXP_CSI0_CORE_CLK 130
+#define IMX8QXP_CSI0_ESC_CLK 131
+#define IMX8QXP_CSI0_PWM0_CLK 132
+#define IMX8QXP_CSI0_I2C0_CLK 133
+
+/* PARALLER CSI SS */
+#define IMX8QXP_PARALLEL_CSI_DPLL_CLK 140
+#define IMX8QXP_PARALLEL_CSI_PIXEL_CLK 141
+#define IMX8QXP_PARALLEL_CSI_MCLK_CLK 142
+
+/* VPU SS */
+#define IMX8QXP_VPU_ENC_CLK 150
+#define IMX8QXP_VPU_DEC_CLK 151
+
+/* GPU SS */
+#define IMX8QXP_GPU0_CORE_CLK 160
+#define IMX8QXP_GPU0_SHADER_CLK 161
+
+/* ADMA SS */
+#define IMX8QXP_ADMA_IPG_CLK_ROOT 165
+#define IMX8QXP_ADMA_UART0_CLK 170
+#define IMX8QXP_ADMA_UART1_CLK 171
+#define IMX8QXP_ADMA_UART2_CLK 172
+#define IMX8QXP_ADMA_UART3_CLK 173
+#define IMX8QXP_ADMA_SPI0_CLK 174
+#define IMX8QXP_ADMA_SPI1_CLK 175
+#define IMX8QXP_ADMA_SPI2_CLK 176
+#define IMX8QXP_ADMA_SPI3_CLK 177
+#define IMX8QXP_ADMA_CAN0_CLK 178
+#define IMX8QXP_ADMA_CAN1_CLK 179
+#define IMX8QXP_ADMA_CAN2_CLK 180
+#define IMX8QXP_ADMA_I2C0_CLK 181
+#define IMX8QXP_ADMA_I2C1_CLK 182
+#define IMX8QXP_ADMA_I2C2_CLK 183
+#define IMX8QXP_ADMA_I2C3_CLK 184
+#define IMX8QXP_ADMA_FTM0_CLK 185
+#define IMX8QXP_ADMA_FTM1_CLK 186
+#define IMX8QXP_ADMA_ADC0_CLK 187
+#define IMX8QXP_ADMA_PWM_CLK 188
+#define IMX8QXP_ADMA_LCD_CLK 189
+
+#define IMX8QXP_SCU_CLK_END 190
+
+#endif /* __DT_BINDINGS_CLOCK_IMX8QXP_H */
--
2.7.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH V6 3/6] clk: imx: add imx8qxp clk driver
2018-11-10 15:19 ` A.s. Dong
@ 2018-11-10 15:19 ` A.s. Dong
-1 siblings, 0 replies; 36+ messages in thread
From: A.s. Dong @ 2018-11-10 15:19 UTC (permalink / raw)
To: linux-clk
Cc: linux-arm-kernel, sboyd, mturquette, shawnguo, Fabio Estevam,
dl-linux-imx, kernel, A.s. Dong
Add imx8qxp clk driver which is based on SCU firmware clock service.
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: Fabio Estevam <fabio.estevam@nxp.com>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Michael Turquette <mturquette@baylibre.com>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
ChangeLog:
v5->v6:
* changed to new scu clock type imx_clk_scu
clk number is reduced signifcantly
* moved lpcgs clock out into separate driver
v4->v5:
Address all comments from Stephen
* more unique name for clk_data
* remove void __iomem * cast for LPCG physical address
* move out external fixed clk definition
* drop using of imx_clk_hw_fixed and imx_check_clk_hws wrappers
* remove i'm alive message
* move scu clk files into imx top directory
v3->v4:
* scu headfile path update
v2->v3:
* enum name update
v1->v2:
* no changes except headfile name updated
---
drivers/clk/imx/Makefile | 2 +
drivers/clk/imx/clk-imx8qxp.c | 156 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 158 insertions(+)
create mode 100644 drivers/clk/imx/clk-imx8qxp.c
diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index eec6d72..8369a34 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -30,3 +30,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_VF610) += clk-vf610.o
+
+obj-$(CONFIG_SOC_IMX8QXP) += clk-imx8qxp.o
diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c
new file mode 100644
index 0000000..d1b288c
--- /dev/null
+++ b/drivers/clk/imx/clk-imx8qxp.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ * Dong Aisheng <aisheng.dong@nxp.com>
+ */
+
+#include <dt-bindings/clock/imx8qxp-clock.h>
+#include <dt-bindings/firmware/imx/rsrc.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "clk-scu.h"
+
+static int imx8qxp_clk_probe(struct platform_device *pdev)
+{
+ struct device_node *ccm_node = pdev->dev.of_node;
+ struct clk_hw_onecell_data *clk_data;
+ struct clk_hw **clks;
+ int ret, i;
+
+ ret = imx_clk_scu_init();
+ if (ret)
+ return ret;
+
+ clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data) +
+ sizeof(*clk_data->hws) * IMX8QXP_SCU_CLK_END,
+ GFP_KERNEL);
+ if (!clk_data)
+ return -ENOMEM;
+
+ clk_data->num = IMX8QXP_SCU_CLK_END;
+ clks = clk_data->hws;
+
+ /* Fixed clocks */
+ clks[IMX8QXP_CLK_DUMMY] = clk_hw_register_fixed_rate(NULL, "dummy", NULL, 0, 0);
+ clks[IMX8QXP_ADMA_IPG_CLK_ROOT] = clk_hw_register_fixed_rate(NULL, "dma_ipg_clk_root", NULL, 0, 120000000);
+ clks[IMX8QXP_CONN_AXI_CLK_ROOT] = clk_hw_register_fixed_rate(NULL, "conn_axi_clk_root", NULL, 0, 333333333);
+ clks[IMX8QXP_CONN_AHB_CLK_ROOT] = clk_hw_register_fixed_rate(NULL, "conn_ahb_clk_root", NULL, 0, 166666666);
+ clks[IMX8QXP_CONN_IPG_CLK_ROOT] = clk_hw_register_fixed_rate(NULL, "conn_ipg_clk_root", NULL, 0, 83333333);
+ clks[IMX8QXP_DC_AXI_EXT_CLK] = clk_hw_register_fixed_rate(NULL, "dc_axi_ext_clk_root", NULL, 0, 800000000);
+ clks[IMX8QXP_DC_AXI_INT_CLK] = clk_hw_register_fixed_rate(NULL, "dc_axi_int_clk_root", NULL, 0, 400000000);
+ clks[IMX8QXP_DC_CFG_CLK] = clk_hw_register_fixed_rate(NULL, "dc_cfg_clk_root", NULL, 0, 100000000);
+ clks[IMX8QXP_MIPI_IPG_CLK] = clk_hw_register_fixed_rate(NULL, "mipi_ipg_clk_root", NULL, 0, 120000000);
+ clks[IMX8QXP_IMG_AXI_CLK] = clk_hw_register_fixed_rate(NULL, "img_axi_clk_root", NULL, 0, 400000000);
+ clks[IMX8QXP_IMG_IPG_CLK] = clk_hw_register_fixed_rate(NULL, "img_ipg_clk_root", NULL, 0, 200000000);
+ clks[IMX8QXP_IMG_PXL_CLK] = clk_hw_register_fixed_rate(NULL, "img_pxl_clk_root", NULL, 0, 600000000);
+ clks[IMX8QXP_HSIO_AXI_CLK] = clk_hw_register_fixed_rate(NULL, "hsio_axi_clk_root", NULL, 0, 400000000);
+ clks[IMX8QXP_HSIO_PER_CLK] = clk_hw_register_fixed_rate(NULL, "hsio_per_clk_root", NULL, 0, 133333333);
+ clks[IMX8QXP_LSIO_MEM_CLK] = clk_hw_register_fixed_rate(NULL, "lsio_mem_clk_root", NULL, 0, 100000000);
+ clks[IMX8QXP_LSIO_BUS_CLK] = clk_hw_register_fixed_rate(NULL, "lsio_bus_clk_root", NULL, 0, 200000000);
+
+ /* ARM core */
+ clks[IMX8QXP_A35_CLK] = imx_clk_scu("a35_clk", IMX_SC_R_A35, IMX_SC_PM_CLK_CPU);
+
+ /* LSIO SS */
+ clks[IMX8QXP_LSIO_PWM0_CLK] = imx_clk_scu("pwm0_clk", IMX_SC_R_PWM_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_PWM1_CLK] = imx_clk_scu("pwm1_clk", IMX_SC_R_PWM_1, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_PWM2_CLK] = imx_clk_scu("pwm2_clk", IMX_SC_R_PWM_2, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_PWM3_CLK] = imx_clk_scu("pwm3_clk", IMX_SC_R_PWM_3, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_PWM4_CLK] = imx_clk_scu("pwm4_clk", IMX_SC_R_PWM_4, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_PWM5_CLK] = imx_clk_scu("pwm5_clk", IMX_SC_R_PWM_5, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_PWM6_CLK] = imx_clk_scu("pwm6_clk", IMX_SC_R_PWM_6, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_PWM7_CLK] = imx_clk_scu("pwm7_clk", IMX_SC_R_PWM_7, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_GPT0_CLK] = imx_clk_scu("gpt0_clk", IMX_SC_R_GPT_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_GPT1_CLK] = imx_clk_scu("gpt1_clk", IMX_SC_R_GPT_1, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_GPT2_CLK] = imx_clk_scu("gpt2_clk", IMX_SC_R_GPT_2, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_GPT3_CLK] = imx_clk_scu("gpt3_clk", IMX_SC_R_GPT_3, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_GPT4_CLK] = imx_clk_scu("gpt4_clk", IMX_SC_R_GPT_4, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_FSPI0_CLK] = imx_clk_scu("fspi0_clk", IMX_SC_R_FSPI_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_FSPI1_CLK] = imx_clk_scu("fspi1_clk", IMX_SC_R_FSPI_1, IMX_SC_PM_CLK_PER);
+
+ /* ADMA SS */
+ clks[IMX8QXP_ADMA_UART0_CLK] = imx_clk_scu("uart0_clk", IMX_SC_R_UART_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_UART1_CLK] = imx_clk_scu("uart1_clk", IMX_SC_R_UART_1, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_UART2_CLK] = imx_clk_scu("uart2_clk", IMX_SC_R_UART_2, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_UART3_CLK] = imx_clk_scu("uart3_clk", IMX_SC_R_UART_3, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_SPI0_CLK] = imx_clk_scu("spi0_clk", IMX_SC_R_SPI_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_SPI1_CLK] = imx_clk_scu("spi1_clk", IMX_SC_R_SPI_2, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_SPI2_CLK] = imx_clk_scu("spi2_clk", IMX_SC_R_SPI_2, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_SPI3_CLK] = imx_clk_scu("spi3_clk", IMX_SC_R_SPI_3, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_CAN0_CLK] = imx_clk_scu("can0_clk", IMX_SC_R_CAN_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_I2C0_CLK] = imx_clk_scu("i2c0_clk", IMX_SC_R_I2C_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_I2C1_CLK] = imx_clk_scu("i2c1_clk", IMX_SC_R_I2C_1, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_I2C2_CLK] = imx_clk_scu("i2c2_clk", IMX_SC_R_I2C_2, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_I2C3_CLK] = imx_clk_scu("i2c3_clk", IMX_SC_R_I2C_3, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_FTM0_CLK] = imx_clk_scu("ftm0_clk", IMX_SC_R_FTM_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_FTM1_CLK] = imx_clk_scu("ftm1_clk", IMX_SC_R_FTM_1, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_ADC0_CLK] = imx_clk_scu("adc0_clk", IMX_SC_R_ADC_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_PWM_CLK] = imx_clk_scu("pwm_clk", IMX_SC_R_LCD_0_PWM_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_LCD_CLK] = imx_clk_scu("lcd_clk", IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER);
+
+ /* Connectivity */
+ clks[IMX8QXP_CONN_SDHC0_CLK] = imx_clk_scu("sdhc0_clk", IMX_SC_R_SDHC_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_CONN_SDHC1_CLK] = imx_clk_scu("sdhc1_clk", IMX_SC_R_SDHC_1, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_CONN_SDHC2_CLK] = imx_clk_scu("sdhc2_clk", IMX_SC_R_SDHC_2, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_CONN_ENET0_ROOT_CLK] = imx_clk_scu("enet0_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_CONN_ENET0_BYPASS_CLK] = imx_clk_scu("enet0_bypass_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_BYPASS);
+ clks[IMX8QXP_CONN_ENET0_RGMII_CLK] = imx_clk_scu("enet0_rgmii_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0);
+ clks[IMX8QXP_CONN_ENET1_ROOT_CLK] = imx_clk_scu("enet1_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_CONN_ENET1_BYPASS_CLK] = imx_clk_scu("enet1_bypass_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_BYPASS);
+ clks[IMX8QXP_CONN_ENET1_RGMII_CLK] = imx_clk_scu("enet1_rgmii_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0);
+ clks[IMX8QXP_CONN_GPMI_BCH_IO_CLK] = imx_clk_scu("gpmi_io_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_MST_BUS);
+ clks[IMX8QXP_CONN_GPMI_BCH_CLK] = imx_clk_scu("gpmi_bch_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_CONN_USB2_ACLK] = imx_clk_scu("usb3_aclk_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_CONN_USB2_BUS_CLK] = imx_clk_scu("usb3_bus_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MST_BUS);
+ clks[IMX8QXP_CONN_USB2_LPM_CLK] = imx_clk_scu("usb3_lpm_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MISC);
+
+ /* Display controller SS */
+ clks[IMX8QXP_DC0_DISP0_CLK] = imx_clk_scu("dc0_disp0_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC0);
+ clks[IMX8QXP_DC0_DISP1_CLK] = imx_clk_scu("dc0_disp1_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC1);
+
+ /* MIPI-LVDS SS */
+ clks[IMX8QXP_MIPI0_I2C0_CLK] = imx_clk_scu("mipi0_i2c0_clk", IMX_SC_R_MIPI_0_I2C_0, IMX_SC_PM_CLK_MISC2);
+ clks[IMX8QXP_MIPI0_I2C1_CLK] = imx_clk_scu("mipi0_i2c1_clk", IMX_SC_R_MIPI_0_I2C_1, IMX_SC_PM_CLK_MISC2);
+
+ /* MIPI CSI SS */
+ clks[IMX8QXP_CSI0_CORE_CLK] = imx_clk_scu("mipi_csi0_core_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_CSI0_ESC_CLK] = imx_clk_scu("mipi_csi0_esc_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_MISC);
+ clks[IMX8QXP_CSI0_I2C0_CLK] = imx_clk_scu("mipi_csi0_i2c0_clk", IMX_SC_R_CSI_0_I2C_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_CSI0_PWM0_CLK] = imx_clk_scu("mipi_csi0_pwm0_clk", IMX_SC_R_CSI_0_PWM_0, IMX_SC_PM_CLK_PER);
+
+ /* GPU SS */
+ clks[IMX8QXP_GPU0_CORE_CLK] = imx_clk_scu("gpu_core0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_GPU0_SHADER_CLK] = imx_clk_scu("gpu_shader0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_MISC);
+
+ for (i = 0; i < clk_data->num; i++) {
+ if (IS_ERR(clks[i]))
+ pr_err("i.MX clk %u: register failed with %ld\n",
+ i, PTR_ERR(clks[i]));
+ }
+
+ return of_clk_add_hw_provider(ccm_node, of_clk_hw_onecell_get, clk_data);
+}
+
+static const struct of_device_id imx8qxp_match[] = {
+ { .compatible = "fsl,imx8qxp-clk", },
+ { /* sentinel */ }
+};
+
+static struct platform_driver imx8qxp_clk_driver = {
+ .driver = {
+ .name = "imx8qxp-clk",
+ .of_match_table = imx8qxp_match,
+ },
+ .probe = imx8qxp_clk_probe,
+};
+builtin_platform_driver(imx8qxp_clk_driver);
+
+MODULE_AUTHOR("Dong Aisheng <aisheng.dong@nxp.com>");
+MODULE_DESCRIPTION("IMX8QXP Clock driver");
+MODULE_LICENSE("GPL v2");
--
2.7.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH V6 3/6] clk: imx: add imx8qxp clk driver
@ 2018-11-10 15:19 ` A.s. Dong
0 siblings, 0 replies; 36+ messages in thread
From: A.s. Dong @ 2018-11-10 15:19 UTC (permalink / raw)
To: linux-arm-kernel
Add imx8qxp clk driver which is based on SCU firmware clock service.
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: Fabio Estevam <fabio.estevam@nxp.com>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Michael Turquette <mturquette@baylibre.com>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
ChangeLog:
v5->v6:
* changed to new scu clock type imx_clk_scu
clk number is reduced signifcantly
* moved lpcgs clock out into separate driver
v4->v5:
Address all comments from Stephen
* more unique name for clk_data
* remove void __iomem * cast for LPCG physical address
* move out external fixed clk definition
* drop using of imx_clk_hw_fixed and imx_check_clk_hws wrappers
* remove i'm alive message
* move scu clk files into imx top directory
v3->v4:
* scu headfile path update
v2->v3:
* enum name update
v1->v2:
* no changes except headfile name updated
---
drivers/clk/imx/Makefile | 2 +
drivers/clk/imx/clk-imx8qxp.c | 156 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 158 insertions(+)
create mode 100644 drivers/clk/imx/clk-imx8qxp.c
diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index eec6d72..8369a34 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -30,3 +30,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_VF610) += clk-vf610.o
+
+obj-$(CONFIG_SOC_IMX8QXP) += clk-imx8qxp.o
diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c
new file mode 100644
index 0000000..d1b288c
--- /dev/null
+++ b/drivers/clk/imx/clk-imx8qxp.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ * Dong Aisheng <aisheng.dong@nxp.com>
+ */
+
+#include <dt-bindings/clock/imx8qxp-clock.h>
+#include <dt-bindings/firmware/imx/rsrc.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "clk-scu.h"
+
+static int imx8qxp_clk_probe(struct platform_device *pdev)
+{
+ struct device_node *ccm_node = pdev->dev.of_node;
+ struct clk_hw_onecell_data *clk_data;
+ struct clk_hw **clks;
+ int ret, i;
+
+ ret = imx_clk_scu_init();
+ if (ret)
+ return ret;
+
+ clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data) +
+ sizeof(*clk_data->hws) * IMX8QXP_SCU_CLK_END,
+ GFP_KERNEL);
+ if (!clk_data)
+ return -ENOMEM;
+
+ clk_data->num = IMX8QXP_SCU_CLK_END;
+ clks = clk_data->hws;
+
+ /* Fixed clocks */
+ clks[IMX8QXP_CLK_DUMMY] = clk_hw_register_fixed_rate(NULL, "dummy", NULL, 0, 0);
+ clks[IMX8QXP_ADMA_IPG_CLK_ROOT] = clk_hw_register_fixed_rate(NULL, "dma_ipg_clk_root", NULL, 0, 120000000);
+ clks[IMX8QXP_CONN_AXI_CLK_ROOT] = clk_hw_register_fixed_rate(NULL, "conn_axi_clk_root", NULL, 0, 333333333);
+ clks[IMX8QXP_CONN_AHB_CLK_ROOT] = clk_hw_register_fixed_rate(NULL, "conn_ahb_clk_root", NULL, 0, 166666666);
+ clks[IMX8QXP_CONN_IPG_CLK_ROOT] = clk_hw_register_fixed_rate(NULL, "conn_ipg_clk_root", NULL, 0, 83333333);
+ clks[IMX8QXP_DC_AXI_EXT_CLK] = clk_hw_register_fixed_rate(NULL, "dc_axi_ext_clk_root", NULL, 0, 800000000);
+ clks[IMX8QXP_DC_AXI_INT_CLK] = clk_hw_register_fixed_rate(NULL, "dc_axi_int_clk_root", NULL, 0, 400000000);
+ clks[IMX8QXP_DC_CFG_CLK] = clk_hw_register_fixed_rate(NULL, "dc_cfg_clk_root", NULL, 0, 100000000);
+ clks[IMX8QXP_MIPI_IPG_CLK] = clk_hw_register_fixed_rate(NULL, "mipi_ipg_clk_root", NULL, 0, 120000000);
+ clks[IMX8QXP_IMG_AXI_CLK] = clk_hw_register_fixed_rate(NULL, "img_axi_clk_root", NULL, 0, 400000000);
+ clks[IMX8QXP_IMG_IPG_CLK] = clk_hw_register_fixed_rate(NULL, "img_ipg_clk_root", NULL, 0, 200000000);
+ clks[IMX8QXP_IMG_PXL_CLK] = clk_hw_register_fixed_rate(NULL, "img_pxl_clk_root", NULL, 0, 600000000);
+ clks[IMX8QXP_HSIO_AXI_CLK] = clk_hw_register_fixed_rate(NULL, "hsio_axi_clk_root", NULL, 0, 400000000);
+ clks[IMX8QXP_HSIO_PER_CLK] = clk_hw_register_fixed_rate(NULL, "hsio_per_clk_root", NULL, 0, 133333333);
+ clks[IMX8QXP_LSIO_MEM_CLK] = clk_hw_register_fixed_rate(NULL, "lsio_mem_clk_root", NULL, 0, 100000000);
+ clks[IMX8QXP_LSIO_BUS_CLK] = clk_hw_register_fixed_rate(NULL, "lsio_bus_clk_root", NULL, 0, 200000000);
+
+ /* ARM core */
+ clks[IMX8QXP_A35_CLK] = imx_clk_scu("a35_clk", IMX_SC_R_A35, IMX_SC_PM_CLK_CPU);
+
+ /* LSIO SS */
+ clks[IMX8QXP_LSIO_PWM0_CLK] = imx_clk_scu("pwm0_clk", IMX_SC_R_PWM_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_PWM1_CLK] = imx_clk_scu("pwm1_clk", IMX_SC_R_PWM_1, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_PWM2_CLK] = imx_clk_scu("pwm2_clk", IMX_SC_R_PWM_2, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_PWM3_CLK] = imx_clk_scu("pwm3_clk", IMX_SC_R_PWM_3, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_PWM4_CLK] = imx_clk_scu("pwm4_clk", IMX_SC_R_PWM_4, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_PWM5_CLK] = imx_clk_scu("pwm5_clk", IMX_SC_R_PWM_5, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_PWM6_CLK] = imx_clk_scu("pwm6_clk", IMX_SC_R_PWM_6, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_PWM7_CLK] = imx_clk_scu("pwm7_clk", IMX_SC_R_PWM_7, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_GPT0_CLK] = imx_clk_scu("gpt0_clk", IMX_SC_R_GPT_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_GPT1_CLK] = imx_clk_scu("gpt1_clk", IMX_SC_R_GPT_1, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_GPT2_CLK] = imx_clk_scu("gpt2_clk", IMX_SC_R_GPT_2, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_GPT3_CLK] = imx_clk_scu("gpt3_clk", IMX_SC_R_GPT_3, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_GPT4_CLK] = imx_clk_scu("gpt4_clk", IMX_SC_R_GPT_4, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_FSPI0_CLK] = imx_clk_scu("fspi0_clk", IMX_SC_R_FSPI_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_LSIO_FSPI1_CLK] = imx_clk_scu("fspi1_clk", IMX_SC_R_FSPI_1, IMX_SC_PM_CLK_PER);
+
+ /* ADMA SS */
+ clks[IMX8QXP_ADMA_UART0_CLK] = imx_clk_scu("uart0_clk", IMX_SC_R_UART_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_UART1_CLK] = imx_clk_scu("uart1_clk", IMX_SC_R_UART_1, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_UART2_CLK] = imx_clk_scu("uart2_clk", IMX_SC_R_UART_2, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_UART3_CLK] = imx_clk_scu("uart3_clk", IMX_SC_R_UART_3, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_SPI0_CLK] = imx_clk_scu("spi0_clk", IMX_SC_R_SPI_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_SPI1_CLK] = imx_clk_scu("spi1_clk", IMX_SC_R_SPI_2, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_SPI2_CLK] = imx_clk_scu("spi2_clk", IMX_SC_R_SPI_2, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_SPI3_CLK] = imx_clk_scu("spi3_clk", IMX_SC_R_SPI_3, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_CAN0_CLK] = imx_clk_scu("can0_clk", IMX_SC_R_CAN_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_I2C0_CLK] = imx_clk_scu("i2c0_clk", IMX_SC_R_I2C_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_I2C1_CLK] = imx_clk_scu("i2c1_clk", IMX_SC_R_I2C_1, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_I2C2_CLK] = imx_clk_scu("i2c2_clk", IMX_SC_R_I2C_2, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_I2C3_CLK] = imx_clk_scu("i2c3_clk", IMX_SC_R_I2C_3, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_FTM0_CLK] = imx_clk_scu("ftm0_clk", IMX_SC_R_FTM_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_FTM1_CLK] = imx_clk_scu("ftm1_clk", IMX_SC_R_FTM_1, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_ADC0_CLK] = imx_clk_scu("adc0_clk", IMX_SC_R_ADC_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_PWM_CLK] = imx_clk_scu("pwm_clk", IMX_SC_R_LCD_0_PWM_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_ADMA_LCD_CLK] = imx_clk_scu("lcd_clk", IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER);
+
+ /* Connectivity */
+ clks[IMX8QXP_CONN_SDHC0_CLK] = imx_clk_scu("sdhc0_clk", IMX_SC_R_SDHC_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_CONN_SDHC1_CLK] = imx_clk_scu("sdhc1_clk", IMX_SC_R_SDHC_1, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_CONN_SDHC2_CLK] = imx_clk_scu("sdhc2_clk", IMX_SC_R_SDHC_2, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_CONN_ENET0_ROOT_CLK] = imx_clk_scu("enet0_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_CONN_ENET0_BYPASS_CLK] = imx_clk_scu("enet0_bypass_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_BYPASS);
+ clks[IMX8QXP_CONN_ENET0_RGMII_CLK] = imx_clk_scu("enet0_rgmii_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0);
+ clks[IMX8QXP_CONN_ENET1_ROOT_CLK] = imx_clk_scu("enet1_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_CONN_ENET1_BYPASS_CLK] = imx_clk_scu("enet1_bypass_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_BYPASS);
+ clks[IMX8QXP_CONN_ENET1_RGMII_CLK] = imx_clk_scu("enet1_rgmii_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0);
+ clks[IMX8QXP_CONN_GPMI_BCH_IO_CLK] = imx_clk_scu("gpmi_io_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_MST_BUS);
+ clks[IMX8QXP_CONN_GPMI_BCH_CLK] = imx_clk_scu("gpmi_bch_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_CONN_USB2_ACLK] = imx_clk_scu("usb3_aclk_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_CONN_USB2_BUS_CLK] = imx_clk_scu("usb3_bus_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MST_BUS);
+ clks[IMX8QXP_CONN_USB2_LPM_CLK] = imx_clk_scu("usb3_lpm_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MISC);
+
+ /* Display controller SS */
+ clks[IMX8QXP_DC0_DISP0_CLK] = imx_clk_scu("dc0_disp0_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC0);
+ clks[IMX8QXP_DC0_DISP1_CLK] = imx_clk_scu("dc0_disp1_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC1);
+
+ /* MIPI-LVDS SS */
+ clks[IMX8QXP_MIPI0_I2C0_CLK] = imx_clk_scu("mipi0_i2c0_clk", IMX_SC_R_MIPI_0_I2C_0, IMX_SC_PM_CLK_MISC2);
+ clks[IMX8QXP_MIPI0_I2C1_CLK] = imx_clk_scu("mipi0_i2c1_clk", IMX_SC_R_MIPI_0_I2C_1, IMX_SC_PM_CLK_MISC2);
+
+ /* MIPI CSI SS */
+ clks[IMX8QXP_CSI0_CORE_CLK] = imx_clk_scu("mipi_csi0_core_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_CSI0_ESC_CLK] = imx_clk_scu("mipi_csi0_esc_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_MISC);
+ clks[IMX8QXP_CSI0_I2C0_CLK] = imx_clk_scu("mipi_csi0_i2c0_clk", IMX_SC_R_CSI_0_I2C_0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_CSI0_PWM0_CLK] = imx_clk_scu("mipi_csi0_pwm0_clk", IMX_SC_R_CSI_0_PWM_0, IMX_SC_PM_CLK_PER);
+
+ /* GPU SS */
+ clks[IMX8QXP_GPU0_CORE_CLK] = imx_clk_scu("gpu_core0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_PER);
+ clks[IMX8QXP_GPU0_SHADER_CLK] = imx_clk_scu("gpu_shader0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_MISC);
+
+ for (i = 0; i < clk_data->num; i++) {
+ if (IS_ERR(clks[i]))
+ pr_err("i.MX clk %u: register failed with %ld\n",
+ i, PTR_ERR(clks[i]));
+ }
+
+ return of_clk_add_hw_provider(ccm_node, of_clk_hw_onecell_get, clk_data);
+}
+
+static const struct of_device_id imx8qxp_match[] = {
+ { .compatible = "fsl,imx8qxp-clk", },
+ { /* sentinel */ }
+};
+
+static struct platform_driver imx8qxp_clk_driver = {
+ .driver = {
+ .name = "imx8qxp-clk",
+ .of_match_table = imx8qxp_match,
+ },
+ .probe = imx8qxp_clk_probe,
+};
+builtin_platform_driver(imx8qxp_clk_driver);
+
+MODULE_AUTHOR("Dong Aisheng <aisheng.dong@nxp.com>");
+MODULE_DESCRIPTION("IMX8QXP Clock driver");
+MODULE_LICENSE("GPL v2");
--
2.7.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH V6 4/6] dt-bindings: clock: add imx8qxp lpcg clock binding
2018-11-10 15:19 ` A.s. Dong
(?)
@ 2018-11-10 15:20 ` A.s. Dong
-1 siblings, 0 replies; 36+ messages in thread
From: A.s. Dong @ 2018-11-10 15:20 UTC (permalink / raw)
To: linux-clk
Cc: A.s. Dong, devicetree, sboyd, mturquette, Rob Herring,
dl-linux-imx, kernel, Fabio Estevam, shawnguo, linux-arm-kernel
The Low-Power Clock Gate (LPCG) modules contain a local programming
model to control the clock gates for the peripherals. An LPCG module
is used to locally gate the clocks for the associated peripheral.
Note:
This level of clock gating is provided after the clocks are generated
by the SCU resources and clock controls. Thus even if the clock is
enabled by these control bits, it might still not be running based
on the base resource.
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: devicetree@vger.kernel.org
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
.../devicetree/bindings/clock/imx8qxp-lpcg.txt | 51 +++++++
include/dt-bindings/clock/imx8qxp-clock.h | 153 +++++++++++++++++++++
2 files changed, 204 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt
diff --git a/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt b/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt
new file mode 100644
index 0000000..965cfa4
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt
@@ -0,0 +1,51 @@
+* NXP i.MX8QXP LPCG (Low-Power Clock Gating) Clock bindings
+
+The Low-Power Clock Gate (LPCG) modules contain a local programming
+model to control the clock gates for the peripherals. An LPCG module
+is used to locally gate the clocks for the associated peripheral.
+
+Note:
+This level of clock gating is provided after the clocks are generated
+by the SCU resources and clock controls. Thus even if the clock is
+enabled by these control bits, it might still not be running based
+on the base resource.
+
+Required properties:
+- compatible: Should be one of:
+ "fsl,imx8qxp-lpcg-adma",
+ "fsl,imx8qxp-lpcg-conn",
+ "fsl,imx8qxp-lpcg-dc",
+ "fsl,imx8qxp-lpcg-dsp",
+ "fsl,imx8qxp-lpcg-gpu",
+ "fsl,imx8qxp-lpcg-hsio",
+ "fsl,imx8qxp-lpcg-img",
+ "fsl,imx8qxp-lpcg-lsio",
+ "fsl,imx8qxp-lpcg-vpu"
+- reg: Address and length of the register set
+- #clock-cells: Should be <1>
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell.
+See the full list of clock IDs from:
+include/dt-bindings/clock/imx8qxp-clock.h
+
+Examples:
+
+#include <dt-bindings/clock/imx8qxp-clock.h>
+
+conn_lpcg: clock-controller@5b200000 {
+ compatible = "fsl,imx8qxp-lpcg-conn";
+ reg = <0x5b200000 0xb0000>;
+ #clock-cells = <1>;
+};
+
+usdhc1: mmc@5b010000 {
+ compatible = "fsl,imx8qxp-usdhc", "fsl,imx7d-usdhc";
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 232 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x5b010000 0x10000>;
+ clocks = <&conn_lpcg IMX8QXP_CONN_LPCG_SDHC0_IPG_CLK>,
+ <&conn_lpcg IMX8QXP_CONN_LPCG_SDHC0_PER_CLK>,
+ <&conn_lpcg IMX8QXP_CONN_LPCG_SDHC0_HCLK>;
+ clock-names = "ipg", "per", "ahb";
+};
diff --git a/include/dt-bindings/clock/imx8qxp-clock.h b/include/dt-bindings/clock/imx8qxp-clock.h
index d72a39c..6fec368 100644
--- a/include/dt-bindings/clock/imx8qxp-clock.h
+++ b/include/dt-bindings/clock/imx8qxp-clock.h
@@ -133,4 +133,157 @@
#define IMX8QXP_SCU_CLK_END 190
+/* LPCG clocks */
+
+/* LSIO SS LPCG */
+#define IMX8QXP_LSIO_LPCG_PWM0_IPG_CLK 0
+#define IMX8QXP_LSIO_LPCG_PWM0_IPG_S_CLK 1
+#define IMX8QXP_LSIO_LPCG_PWM0_IPG_HF_CLK 2
+#define IMX8QXP_LSIO_LPCG_PWM0_IPG_SLV_CLK 3
+#define IMX8QXP_LSIO_LPCG_PWM0_IPG_MSTR_CLK 4
+#define IMX8QXP_LSIO_LPCG_PWM1_IPG_CLK 5
+#define IMX8QXP_LSIO_LPCG_PWM1_IPG_S_CLK 6
+#define IMX8QXP_LSIO_LPCG_PWM1_IPG_HF_CLK 7
+#define IMX8QXP_LSIO_LPCG_PWM1_IPG_SLV_CLK 8
+#define IMX8QXP_LSIO_LPCG_PWM1_IPG_MSTR_CLK 9
+#define IMX8QXP_LSIO_LPCG_PWM2_IPG_CLK 10
+#define IMX8QXP_LSIO_LPCG_PWM2_IPG_S_CLK 11
+#define IMX8QXP_LSIO_LPCG_PWM2_IPG_HF_CLK 12
+#define IMX8QXP_LSIO_LPCG_PWM2_IPG_SLV_CLK 13
+#define IMX8QXP_LSIO_LPCG_PWM2_IPG_MSTR_CLK 14
+#define IMX8QXP_LSIO_LPCG_PWM3_IPG_CLK 15
+#define IMX8QXP_LSIO_LPCG_PWM3_IPG_S_CLK 16
+#define IMX8QXP_LSIO_LPCG_PWM3_IPG_HF_CLK 17
+#define IMX8QXP_LSIO_LPCG_PWM3_IPG_SLV_CLK 18
+#define IMX8QXP_LSIO_LPCG_PWM3_IPG_MSTR_CLK 19
+#define IMX8QXP_LSIO_LPCG_PWM4_IPG_CLK 20
+#define IMX8QXP_LSIO_LPCG_PWM4_IPG_S_CLK 21
+#define IMX8QXP_LSIO_LPCG_PWM4_IPG_HF_CLK 22
+#define IMX8QXP_LSIO_LPCG_PWM4_IPG_SLV_CLK 23
+#define IMX8QXP_LSIO_LPCG_PWM4_IPG_MSTR_CLK 24
+#define IMX8QXP_LSIO_LPCG_PWM5_IPG_CLK 25
+#define IMX8QXP_LSIO_LPCG_PWM5_IPG_S_CLK 26
+#define IMX8QXP_LSIO_LPCG_PWM5_IPG_HF_CLK 27
+#define IMX8QXP_LSIO_LPCG_PWM5_IPG_SLV_CLK 28
+#define IMX8QXP_LSIO_LPCG_PWM5_IPG_MSTR_CLK 29
+#define IMX8QXP_LSIO_LPCG_PWM6_IPG_CLK 30
+#define IMX8QXP_LSIO_LPCG_PWM6_IPG_S_CLK 31
+#define IMX8QXP_LSIO_LPCG_PWM6_IPG_HF_CLK 32
+#define IMX8QXP_LSIO_LPCG_PWM6_IPG_SLV_CLK 33
+#define IMX8QXP_LSIO_LPCG_PWM6_IPG_MSTR_CLK 34
+#define IMX8QXP_LSIO_LPCG_PWM7_IPG_CLK 35
+#define IMX8QXP_LSIO_LPCG_PWM7_IPG_S_CLK 36
+#define IMX8QXP_LSIO_LPCG_PWM7_IPG_HF_CLK 37
+#define IMX8QXP_LSIO_LPCG_PWM7_IPG_SLV_CLK 38
+#define IMX8QXP_LSIO_LPCG_PWM7_IPG_MSTR_CLK 39
+#define IMX8QXP_LSIO_LPCG_GPT0_IPG_CLK 40
+#define IMX8QXP_LSIO_LPCG_GPT0_IPG_S_CLK 41
+#define IMX8QXP_LSIO_LPCG_GPT0_IPG_HF_CLK 42
+#define IMX8QXP_LSIO_LPCG_GPT0_IPG_SLV_CLK 43
+#define IMX8QXP_LSIO_LPCG_GPT0_IPG_MSTR_CLK 44
+#define IMX8QXP_LSIO_LPCG_GPT1_IPG_CLK 45
+#define IMX8QXP_LSIO_LPCG_GPT1_IPG_S_CLK 46
+#define IMX8QXP_LSIO_LPCG_GPT1_IPG_HF_CLK 47
+#define IMX8QXP_LSIO_LPCG_GPT1_IPG_SLV_CLK 48
+#define IMX8QXP_LSIO_LPCG_GPT1_IPG_MSTR_CLK 49
+#define IMX8QXP_LSIO_LPCG_GPT2_IPG_CLK 50
+#define IMX8QXP_LSIO_LPCG_GPT2_IPG_S_CLK 51
+#define IMX8QXP_LSIO_LPCG_GPT2_IPG_HF_CLK 52
+#define IMX8QXP_LSIO_LPCG_GPT2_IPG_SLV_CLK 53
+#define IMX8QXP_LSIO_LPCG_GPT2_IPG_MSTR_CLK 54
+#define IMX8QXP_LSIO_LPCG_GPT3_IPG_CLK 55
+#define IMX8QXP_LSIO_LPCG_GPT3_IPG_S_CLK 56
+#define IMX8QXP_LSIO_LPCG_GPT3_IPG_HF_CLK 57
+#define IMX8QXP_LSIO_LPCG_GPT3_IPG_SLV_CLK 58
+#define IMX8QXP_LSIO_LPCG_GPT3_IPG_MSTR_CLK 59
+#define IMX8QXP_LSIO_LPCG_GPT4_IPG_CLK 60
+#define IMX8QXP_LSIO_LPCG_GPT4_IPG_S_CLK 61
+#define IMX8QXP_LSIO_LPCG_GPT4_IPG_HF_CLK 62
+#define IMX8QXP_LSIO_LPCG_GPT4_IPG_SLV_CLK 63
+#define IMX8QXP_LSIO_LPCG_GPT4_IPG_MSTR_CLK 64
+#define IMX8QXP_LSIO_LPCG_FSPI0_HCLK 65
+#define IMX8QXP_LSIO_LPCG_FSPI0_IPG_CLK 66
+#define IMX8QXP_LSIO_LPCG_FSPI0_IPG_S_CLK 67
+#define IMX8QXP_LSIO_LPCG_FSPI0_IPG_SFCK 68
+#define IMX8QXP_LSIO_LPCG_FSPI1_HCLK 69
+#define IMX8QXP_LSIO_LPCG_FSPI1_IPG_CLK 70
+#define IMX8QXP_LSIO_LPCG_FSPI1_IPG_S_CLK 71
+#define IMX8QXP_LSIO_LPCG_FSPI1_IPG_SFCK 72
+
+#define IMX8QXP_LSIO_LPCG_CLK_END 73
+
+/* Connectivity SS LPCG */
+#define IMX8QXP_CONN_LPCG_SDHC0_IPG_CLK 0
+#define IMX8QXP_CONN_LPCG_SDHC0_PER_CLK 1
+#define IMX8QXP_CONN_LPCG_SDHC0_HCLK 2
+#define IMX8QXP_CONN_LPCG_SDHC1_IPG_CLK 3
+#define IMX8QXP_CONN_LPCG_SDHC1_PER_CLK 4
+#define IMX8QXP_CONN_LPCG_SDHC1_HCLK 5
+#define IMX8QXP_CONN_LPCG_SDHC2_IPG_CLK 6
+#define IMX8QXP_CONN_LPCG_SDHC2_PER_CLK 7
+#define IMX8QXP_CONN_LPCG_SDHC2_HCLK 8
+#define IMX8QXP_CONN_LPCG_GPMI_APB_CLK 9
+#define IMX8QXP_CONN_LPCG_GPMI_BCH_APB_CLK 10
+#define IMX8QXP_CONN_LPCG_GPMI_BCH_IO_CLK 11
+#define IMX8QXP_CONN_LPCG_GPMI_BCH_CLK 12
+#define IMX8QXP_CONN_LPCG_APBHDMA_CLK 13
+#define IMX8QXP_CONN_LPCG_ENET0_ROOT_CLK 14
+#define IMX8QXP_CONN_LPCG_ENET0_TX_CLK 15
+#define IMX8QXP_CONN_LPCG_ENET0_AHB_CLK 16
+#define IMX8QXP_CONN_LPCG_ENET0_IPG_S_CLK 17
+#define IMX8QXP_CONN_LPCG_ENET0_IPG_CLK 18
+
+#define IMX8QXP_CONN_LPCG_ENET1_ROOT_CLK 19
+#define IMX8QXP_CONN_LPCG_ENET1_TX_CLK 20
+#define IMX8QXP_CONN_LPCG_ENET1_AHB_CLK 21
+#define IMX8QXP_CONN_LPCG_ENET1_IPG_S_CLK 22
+#define IMX8QXP_CONN_LPCG_ENET1_IPG_CLK 23
+
+#define IMX8QXP_CONN_LPCG_CLK_END 24
+
+/* ADMA SS LPCG */
+#define IMX8QXP_ADMA_LPCG_UART0_IPG_CLK 0
+#define IMX8QXP_ADMA_LPCG_UART0_BAUD_CLK 1
+#define IMX8QXP_ADMA_LPCG_UART1_IPG_CLK 2
+#define IMX8QXP_ADMA_LPCG_UART1_BAUD_CLK 3
+#define IMX8QXP_ADMA_LPCG_UART2_IPG_CLK 4
+#define IMX8QXP_ADMA_LPCG_UART2_BAUD_CLK 5
+#define IMX8QXP_ADMA_LPCG_UART3_IPG_CLK 6
+#define IMX8QXP_ADMA_LPCG_UART3_BAUD_CLK 7
+#define IMX8QXP_ADMA_LPCG_SPI0_IPG_CLK 8
+#define IMX8QXP_ADMA_LPCG_SPI1_IPG_CLK 9
+#define IMX8QXP_ADMA_LPCG_SPI2_IPG_CLK 10
+#define IMX8QXP_ADMA_LPCG_SPI3_IPG_CLK 11
+#define IMX8QXP_ADMA_LPCG_SPI0_CLK 12
+#define IMX8QXP_ADMA_LPCG_SPI1_CLK 13
+#define IMX8QXP_ADMA_LPCG_SPI2_CLK 14
+#define IMX8QXP_ADMA_LPCG_SPI3_CLK 15
+#define IMX8QXP_ADMA_LPCG_CAN0_IPG_CLK 16
+#define IMX8QXP_ADMA_LPCG_CAN0_IPG_PE_CLK 17
+#define IMX8QXP_ADMA_LPCG_CAN0_IPG_CHI_CLK 18
+#define IMX8QXP_ADMA_LPCG_CAN1_IPG_CLK 19
+#define IMX8QXP_ADMA_LPCG_CAN1_IPG_PE_CLK 20
+#define IMX8QXP_ADMA_LPCG_CAN1_IPG_CHI_CLK 21
+#define IMX8QXP_ADMA_LPCG_CAN2_IPG_CLK 22
+#define IMX8QXP_ADMA_LPCG_CAN2_IPG_PE_CLK 23
+#define IMX8QXP_ADMA_LPCG_CAN2_IPG_CHI_CLK 24
+#define IMX8QXP_ADMA_LPCG_I2C0_CLK 25
+#define IMX8QXP_ADMA_LPCG_I2C1_CLK 26
+#define IMX8QXP_ADMA_LPCG_I2C2_CLK 27
+#define IMX8QXP_ADMA_LPCG_I2C3_CLK 28
+#define IMX8QXP_ADMA_LPCG_I2C0_IPG_CLK 29
+#define IMX8QXP_ADMA_LPCG_I2C1_IPG_CLK 30
+#define IMX8QXP_ADMA_LPCG_I2C2_IPG_CLK 31
+#define IMX8QXP_ADMA_LPCG_I2C3_IPG_CLK 32
+#define IMX8QXP_ADMA_LPCG_FTM0_CLK 33
+#define IMX8QXP_ADMA_LPCG_FTM1_CLK 34
+#define IMX8QXP_ADMA_LPCG_FTM0_IPG_CLK 35
+#define IMX8QXP_ADMA_LPCG_FTM1_IPG_CLK 36
+#define IMX8QXP_ADMA_LPCG_PWM_HI_CLK 37
+#define IMX8QXP_ADMA_LPCG_PWM_IPG_CLK 38
+#define IMX8QXP_ADMA_LPCG_LCD_PIX_CLK 39
+#define IMX8QXP_ADMA_LPCG_LCD_APB_CLK 40
+
+#define IMX8QXP_ADMA_LPCG_CLK_END 41
+
#endif /* __DT_BINDINGS_CLOCK_IMX8QXP_H */
--
2.7.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH V6 4/6] dt-bindings: clock: add imx8qxp lpcg clock binding
@ 2018-11-10 15:20 ` A.s. Dong
0 siblings, 0 replies; 36+ messages in thread
From: A.s. Dong @ 2018-11-10 15:20 UTC (permalink / raw)
To: linux-clk
Cc: linux-arm-kernel, sboyd, mturquette, shawnguo, Fabio Estevam,
dl-linux-imx, kernel, A.s. Dong, Rob Herring, devicetree
The Low-Power Clock Gate (LPCG) modules contain a local programming
model to control the clock gates for the peripherals. An LPCG module
is used to locally gate the clocks for the associated peripheral.
Note:
This level of clock gating is provided after the clocks are generated
by the SCU resources and clock controls. Thus even if the clock is
enabled by these control bits, it might still not be running based
on the base resource.
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: devicetree@vger.kernel.org
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
.../devicetree/bindings/clock/imx8qxp-lpcg.txt | 51 +++++++
include/dt-bindings/clock/imx8qxp-clock.h | 153 +++++++++++++++++++++
2 files changed, 204 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt
diff --git a/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt b/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt
new file mode 100644
index 0000000..965cfa4
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt
@@ -0,0 +1,51 @@
+* NXP i.MX8QXP LPCG (Low-Power Clock Gating) Clock bindings
+
+The Low-Power Clock Gate (LPCG) modules contain a local programming
+model to control the clock gates for the peripherals. An LPCG module
+is used to locally gate the clocks for the associated peripheral.
+
+Note:
+This level of clock gating is provided after the clocks are generated
+by the SCU resources and clock controls. Thus even if the clock is
+enabled by these control bits, it might still not be running based
+on the base resource.
+
+Required properties:
+- compatible: Should be one of:
+ "fsl,imx8qxp-lpcg-adma",
+ "fsl,imx8qxp-lpcg-conn",
+ "fsl,imx8qxp-lpcg-dc",
+ "fsl,imx8qxp-lpcg-dsp",
+ "fsl,imx8qxp-lpcg-gpu",
+ "fsl,imx8qxp-lpcg-hsio",
+ "fsl,imx8qxp-lpcg-img",
+ "fsl,imx8qxp-lpcg-lsio",
+ "fsl,imx8qxp-lpcg-vpu"
+- reg: Address and length of the register set
+- #clock-cells: Should be <1>
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell.
+See the full list of clock IDs from:
+include/dt-bindings/clock/imx8qxp-clock.h
+
+Examples:
+
+#include <dt-bindings/clock/imx8qxp-clock.h>
+
+conn_lpcg: clock-controller@5b200000 {
+ compatible = "fsl,imx8qxp-lpcg-conn";
+ reg = <0x5b200000 0xb0000>;
+ #clock-cells = <1>;
+};
+
+usdhc1: mmc@5b010000 {
+ compatible = "fsl,imx8qxp-usdhc", "fsl,imx7d-usdhc";
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 232 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x5b010000 0x10000>;
+ clocks = <&conn_lpcg IMX8QXP_CONN_LPCG_SDHC0_IPG_CLK>,
+ <&conn_lpcg IMX8QXP_CONN_LPCG_SDHC0_PER_CLK>,
+ <&conn_lpcg IMX8QXP_CONN_LPCG_SDHC0_HCLK>;
+ clock-names = "ipg", "per", "ahb";
+};
diff --git a/include/dt-bindings/clock/imx8qxp-clock.h b/include/dt-bindings/clock/imx8qxp-clock.h
index d72a39c..6fec368 100644
--- a/include/dt-bindings/clock/imx8qxp-clock.h
+++ b/include/dt-bindings/clock/imx8qxp-clock.h
@@ -133,4 +133,157 @@
#define IMX8QXP_SCU_CLK_END 190
+/* LPCG clocks */
+
+/* LSIO SS LPCG */
+#define IMX8QXP_LSIO_LPCG_PWM0_IPG_CLK 0
+#define IMX8QXP_LSIO_LPCG_PWM0_IPG_S_CLK 1
+#define IMX8QXP_LSIO_LPCG_PWM0_IPG_HF_CLK 2
+#define IMX8QXP_LSIO_LPCG_PWM0_IPG_SLV_CLK 3
+#define IMX8QXP_LSIO_LPCG_PWM0_IPG_MSTR_CLK 4
+#define IMX8QXP_LSIO_LPCG_PWM1_IPG_CLK 5
+#define IMX8QXP_LSIO_LPCG_PWM1_IPG_S_CLK 6
+#define IMX8QXP_LSIO_LPCG_PWM1_IPG_HF_CLK 7
+#define IMX8QXP_LSIO_LPCG_PWM1_IPG_SLV_CLK 8
+#define IMX8QXP_LSIO_LPCG_PWM1_IPG_MSTR_CLK 9
+#define IMX8QXP_LSIO_LPCG_PWM2_IPG_CLK 10
+#define IMX8QXP_LSIO_LPCG_PWM2_IPG_S_CLK 11
+#define IMX8QXP_LSIO_LPCG_PWM2_IPG_HF_CLK 12
+#define IMX8QXP_LSIO_LPCG_PWM2_IPG_SLV_CLK 13
+#define IMX8QXP_LSIO_LPCG_PWM2_IPG_MSTR_CLK 14
+#define IMX8QXP_LSIO_LPCG_PWM3_IPG_CLK 15
+#define IMX8QXP_LSIO_LPCG_PWM3_IPG_S_CLK 16
+#define IMX8QXP_LSIO_LPCG_PWM3_IPG_HF_CLK 17
+#define IMX8QXP_LSIO_LPCG_PWM3_IPG_SLV_CLK 18
+#define IMX8QXP_LSIO_LPCG_PWM3_IPG_MSTR_CLK 19
+#define IMX8QXP_LSIO_LPCG_PWM4_IPG_CLK 20
+#define IMX8QXP_LSIO_LPCG_PWM4_IPG_S_CLK 21
+#define IMX8QXP_LSIO_LPCG_PWM4_IPG_HF_CLK 22
+#define IMX8QXP_LSIO_LPCG_PWM4_IPG_SLV_CLK 23
+#define IMX8QXP_LSIO_LPCG_PWM4_IPG_MSTR_CLK 24
+#define IMX8QXP_LSIO_LPCG_PWM5_IPG_CLK 25
+#define IMX8QXP_LSIO_LPCG_PWM5_IPG_S_CLK 26
+#define IMX8QXP_LSIO_LPCG_PWM5_IPG_HF_CLK 27
+#define IMX8QXP_LSIO_LPCG_PWM5_IPG_SLV_CLK 28
+#define IMX8QXP_LSIO_LPCG_PWM5_IPG_MSTR_CLK 29
+#define IMX8QXP_LSIO_LPCG_PWM6_IPG_CLK 30
+#define IMX8QXP_LSIO_LPCG_PWM6_IPG_S_CLK 31
+#define IMX8QXP_LSIO_LPCG_PWM6_IPG_HF_CLK 32
+#define IMX8QXP_LSIO_LPCG_PWM6_IPG_SLV_CLK 33
+#define IMX8QXP_LSIO_LPCG_PWM6_IPG_MSTR_CLK 34
+#define IMX8QXP_LSIO_LPCG_PWM7_IPG_CLK 35
+#define IMX8QXP_LSIO_LPCG_PWM7_IPG_S_CLK 36
+#define IMX8QXP_LSIO_LPCG_PWM7_IPG_HF_CLK 37
+#define IMX8QXP_LSIO_LPCG_PWM7_IPG_SLV_CLK 38
+#define IMX8QXP_LSIO_LPCG_PWM7_IPG_MSTR_CLK 39
+#define IMX8QXP_LSIO_LPCG_GPT0_IPG_CLK 40
+#define IMX8QXP_LSIO_LPCG_GPT0_IPG_S_CLK 41
+#define IMX8QXP_LSIO_LPCG_GPT0_IPG_HF_CLK 42
+#define IMX8QXP_LSIO_LPCG_GPT0_IPG_SLV_CLK 43
+#define IMX8QXP_LSIO_LPCG_GPT0_IPG_MSTR_CLK 44
+#define IMX8QXP_LSIO_LPCG_GPT1_IPG_CLK 45
+#define IMX8QXP_LSIO_LPCG_GPT1_IPG_S_CLK 46
+#define IMX8QXP_LSIO_LPCG_GPT1_IPG_HF_CLK 47
+#define IMX8QXP_LSIO_LPCG_GPT1_IPG_SLV_CLK 48
+#define IMX8QXP_LSIO_LPCG_GPT1_IPG_MSTR_CLK 49
+#define IMX8QXP_LSIO_LPCG_GPT2_IPG_CLK 50
+#define IMX8QXP_LSIO_LPCG_GPT2_IPG_S_CLK 51
+#define IMX8QXP_LSIO_LPCG_GPT2_IPG_HF_CLK 52
+#define IMX8QXP_LSIO_LPCG_GPT2_IPG_SLV_CLK 53
+#define IMX8QXP_LSIO_LPCG_GPT2_IPG_MSTR_CLK 54
+#define IMX8QXP_LSIO_LPCG_GPT3_IPG_CLK 55
+#define IMX8QXP_LSIO_LPCG_GPT3_IPG_S_CLK 56
+#define IMX8QXP_LSIO_LPCG_GPT3_IPG_HF_CLK 57
+#define IMX8QXP_LSIO_LPCG_GPT3_IPG_SLV_CLK 58
+#define IMX8QXP_LSIO_LPCG_GPT3_IPG_MSTR_CLK 59
+#define IMX8QXP_LSIO_LPCG_GPT4_IPG_CLK 60
+#define IMX8QXP_LSIO_LPCG_GPT4_IPG_S_CLK 61
+#define IMX8QXP_LSIO_LPCG_GPT4_IPG_HF_CLK 62
+#define IMX8QXP_LSIO_LPCG_GPT4_IPG_SLV_CLK 63
+#define IMX8QXP_LSIO_LPCG_GPT4_IPG_MSTR_CLK 64
+#define IMX8QXP_LSIO_LPCG_FSPI0_HCLK 65
+#define IMX8QXP_LSIO_LPCG_FSPI0_IPG_CLK 66
+#define IMX8QXP_LSIO_LPCG_FSPI0_IPG_S_CLK 67
+#define IMX8QXP_LSIO_LPCG_FSPI0_IPG_SFCK 68
+#define IMX8QXP_LSIO_LPCG_FSPI1_HCLK 69
+#define IMX8QXP_LSIO_LPCG_FSPI1_IPG_CLK 70
+#define IMX8QXP_LSIO_LPCG_FSPI1_IPG_S_CLK 71
+#define IMX8QXP_LSIO_LPCG_FSPI1_IPG_SFCK 72
+
+#define IMX8QXP_LSIO_LPCG_CLK_END 73
+
+/* Connectivity SS LPCG */
+#define IMX8QXP_CONN_LPCG_SDHC0_IPG_CLK 0
+#define IMX8QXP_CONN_LPCG_SDHC0_PER_CLK 1
+#define IMX8QXP_CONN_LPCG_SDHC0_HCLK 2
+#define IMX8QXP_CONN_LPCG_SDHC1_IPG_CLK 3
+#define IMX8QXP_CONN_LPCG_SDHC1_PER_CLK 4
+#define IMX8QXP_CONN_LPCG_SDHC1_HCLK 5
+#define IMX8QXP_CONN_LPCG_SDHC2_IPG_CLK 6
+#define IMX8QXP_CONN_LPCG_SDHC2_PER_CLK 7
+#define IMX8QXP_CONN_LPCG_SDHC2_HCLK 8
+#define IMX8QXP_CONN_LPCG_GPMI_APB_CLK 9
+#define IMX8QXP_CONN_LPCG_GPMI_BCH_APB_CLK 10
+#define IMX8QXP_CONN_LPCG_GPMI_BCH_IO_CLK 11
+#define IMX8QXP_CONN_LPCG_GPMI_BCH_CLK 12
+#define IMX8QXP_CONN_LPCG_APBHDMA_CLK 13
+#define IMX8QXP_CONN_LPCG_ENET0_ROOT_CLK 14
+#define IMX8QXP_CONN_LPCG_ENET0_TX_CLK 15
+#define IMX8QXP_CONN_LPCG_ENET0_AHB_CLK 16
+#define IMX8QXP_CONN_LPCG_ENET0_IPG_S_CLK 17
+#define IMX8QXP_CONN_LPCG_ENET0_IPG_CLK 18
+
+#define IMX8QXP_CONN_LPCG_ENET1_ROOT_CLK 19
+#define IMX8QXP_CONN_LPCG_ENET1_TX_CLK 20
+#define IMX8QXP_CONN_LPCG_ENET1_AHB_CLK 21
+#define IMX8QXP_CONN_LPCG_ENET1_IPG_S_CLK 22
+#define IMX8QXP_CONN_LPCG_ENET1_IPG_CLK 23
+
+#define IMX8QXP_CONN_LPCG_CLK_END 24
+
+/* ADMA SS LPCG */
+#define IMX8QXP_ADMA_LPCG_UART0_IPG_CLK 0
+#define IMX8QXP_ADMA_LPCG_UART0_BAUD_CLK 1
+#define IMX8QXP_ADMA_LPCG_UART1_IPG_CLK 2
+#define IMX8QXP_ADMA_LPCG_UART1_BAUD_CLK 3
+#define IMX8QXP_ADMA_LPCG_UART2_IPG_CLK 4
+#define IMX8QXP_ADMA_LPCG_UART2_BAUD_CLK 5
+#define IMX8QXP_ADMA_LPCG_UART3_IPG_CLK 6
+#define IMX8QXP_ADMA_LPCG_UART3_BAUD_CLK 7
+#define IMX8QXP_ADMA_LPCG_SPI0_IPG_CLK 8
+#define IMX8QXP_ADMA_LPCG_SPI1_IPG_CLK 9
+#define IMX8QXP_ADMA_LPCG_SPI2_IPG_CLK 10
+#define IMX8QXP_ADMA_LPCG_SPI3_IPG_CLK 11
+#define IMX8QXP_ADMA_LPCG_SPI0_CLK 12
+#define IMX8QXP_ADMA_LPCG_SPI1_CLK 13
+#define IMX8QXP_ADMA_LPCG_SPI2_CLK 14
+#define IMX8QXP_ADMA_LPCG_SPI3_CLK 15
+#define IMX8QXP_ADMA_LPCG_CAN0_IPG_CLK 16
+#define IMX8QXP_ADMA_LPCG_CAN0_IPG_PE_CLK 17
+#define IMX8QXP_ADMA_LPCG_CAN0_IPG_CHI_CLK 18
+#define IMX8QXP_ADMA_LPCG_CAN1_IPG_CLK 19
+#define IMX8QXP_ADMA_LPCG_CAN1_IPG_PE_CLK 20
+#define IMX8QXP_ADMA_LPCG_CAN1_IPG_CHI_CLK 21
+#define IMX8QXP_ADMA_LPCG_CAN2_IPG_CLK 22
+#define IMX8QXP_ADMA_LPCG_CAN2_IPG_PE_CLK 23
+#define IMX8QXP_ADMA_LPCG_CAN2_IPG_CHI_CLK 24
+#define IMX8QXP_ADMA_LPCG_I2C0_CLK 25
+#define IMX8QXP_ADMA_LPCG_I2C1_CLK 26
+#define IMX8QXP_ADMA_LPCG_I2C2_CLK 27
+#define IMX8QXP_ADMA_LPCG_I2C3_CLK 28
+#define IMX8QXP_ADMA_LPCG_I2C0_IPG_CLK 29
+#define IMX8QXP_ADMA_LPCG_I2C1_IPG_CLK 30
+#define IMX8QXP_ADMA_LPCG_I2C2_IPG_CLK 31
+#define IMX8QXP_ADMA_LPCG_I2C3_IPG_CLK 32
+#define IMX8QXP_ADMA_LPCG_FTM0_CLK 33
+#define IMX8QXP_ADMA_LPCG_FTM1_CLK 34
+#define IMX8QXP_ADMA_LPCG_FTM0_IPG_CLK 35
+#define IMX8QXP_ADMA_LPCG_FTM1_IPG_CLK 36
+#define IMX8QXP_ADMA_LPCG_PWM_HI_CLK 37
+#define IMX8QXP_ADMA_LPCG_PWM_IPG_CLK 38
+#define IMX8QXP_ADMA_LPCG_LCD_PIX_CLK 39
+#define IMX8QXP_ADMA_LPCG_LCD_APB_CLK 40
+
+#define IMX8QXP_ADMA_LPCG_CLK_END 41
+
#endif /* __DT_BINDINGS_CLOCK_IMX8QXP_H */
--
2.7.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH V6 4/6] dt-bindings: clock: add imx8qxp lpcg clock binding
@ 2018-11-10 15:20 ` A.s. Dong
0 siblings, 0 replies; 36+ messages in thread
From: A.s. Dong @ 2018-11-10 15:20 UTC (permalink / raw)
To: linux-arm-kernel
The Low-Power Clock Gate (LPCG) modules contain a local programming
model to control the clock gates for the peripherals. An LPCG module
is used to locally gate the clocks for the associated peripheral.
Note:
This level of clock gating is provided after the clocks are generated
by the SCU resources and clock controls. Thus even if the clock is
enabled by these control bits, it might still not be running based
on the base resource.
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: devicetree at vger.kernel.org
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
.../devicetree/bindings/clock/imx8qxp-lpcg.txt | 51 +++++++
include/dt-bindings/clock/imx8qxp-clock.h | 153 +++++++++++++++++++++
2 files changed, 204 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt
diff --git a/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt b/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt
new file mode 100644
index 0000000..965cfa4
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt
@@ -0,0 +1,51 @@
+* NXP i.MX8QXP LPCG (Low-Power Clock Gating) Clock bindings
+
+The Low-Power Clock Gate (LPCG) modules contain a local programming
+model to control the clock gates for the peripherals. An LPCG module
+is used to locally gate the clocks for the associated peripheral.
+
+Note:
+This level of clock gating is provided after the clocks are generated
+by the SCU resources and clock controls. Thus even if the clock is
+enabled by these control bits, it might still not be running based
+on the base resource.
+
+Required properties:
+- compatible: Should be one of:
+ "fsl,imx8qxp-lpcg-adma",
+ "fsl,imx8qxp-lpcg-conn",
+ "fsl,imx8qxp-lpcg-dc",
+ "fsl,imx8qxp-lpcg-dsp",
+ "fsl,imx8qxp-lpcg-gpu",
+ "fsl,imx8qxp-lpcg-hsio",
+ "fsl,imx8qxp-lpcg-img",
+ "fsl,imx8qxp-lpcg-lsio",
+ "fsl,imx8qxp-lpcg-vpu"
+- reg: Address and length of the register set
+- #clock-cells: Should be <1>
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell.
+See the full list of clock IDs from:
+include/dt-bindings/clock/imx8qxp-clock.h
+
+Examples:
+
+#include <dt-bindings/clock/imx8qxp-clock.h>
+
+conn_lpcg: clock-controller at 5b200000 {
+ compatible = "fsl,imx8qxp-lpcg-conn";
+ reg = <0x5b200000 0xb0000>;
+ #clock-cells = <1>;
+};
+
+usdhc1: mmc at 5b010000 {
+ compatible = "fsl,imx8qxp-usdhc", "fsl,imx7d-usdhc";
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 232 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x5b010000 0x10000>;
+ clocks = <&conn_lpcg IMX8QXP_CONN_LPCG_SDHC0_IPG_CLK>,
+ <&conn_lpcg IMX8QXP_CONN_LPCG_SDHC0_PER_CLK>,
+ <&conn_lpcg IMX8QXP_CONN_LPCG_SDHC0_HCLK>;
+ clock-names = "ipg", "per", "ahb";
+};
diff --git a/include/dt-bindings/clock/imx8qxp-clock.h b/include/dt-bindings/clock/imx8qxp-clock.h
index d72a39c..6fec368 100644
--- a/include/dt-bindings/clock/imx8qxp-clock.h
+++ b/include/dt-bindings/clock/imx8qxp-clock.h
@@ -133,4 +133,157 @@
#define IMX8QXP_SCU_CLK_END 190
+/* LPCG clocks */
+
+/* LSIO SS LPCG */
+#define IMX8QXP_LSIO_LPCG_PWM0_IPG_CLK 0
+#define IMX8QXP_LSIO_LPCG_PWM0_IPG_S_CLK 1
+#define IMX8QXP_LSIO_LPCG_PWM0_IPG_HF_CLK 2
+#define IMX8QXP_LSIO_LPCG_PWM0_IPG_SLV_CLK 3
+#define IMX8QXP_LSIO_LPCG_PWM0_IPG_MSTR_CLK 4
+#define IMX8QXP_LSIO_LPCG_PWM1_IPG_CLK 5
+#define IMX8QXP_LSIO_LPCG_PWM1_IPG_S_CLK 6
+#define IMX8QXP_LSIO_LPCG_PWM1_IPG_HF_CLK 7
+#define IMX8QXP_LSIO_LPCG_PWM1_IPG_SLV_CLK 8
+#define IMX8QXP_LSIO_LPCG_PWM1_IPG_MSTR_CLK 9
+#define IMX8QXP_LSIO_LPCG_PWM2_IPG_CLK 10
+#define IMX8QXP_LSIO_LPCG_PWM2_IPG_S_CLK 11
+#define IMX8QXP_LSIO_LPCG_PWM2_IPG_HF_CLK 12
+#define IMX8QXP_LSIO_LPCG_PWM2_IPG_SLV_CLK 13
+#define IMX8QXP_LSIO_LPCG_PWM2_IPG_MSTR_CLK 14
+#define IMX8QXP_LSIO_LPCG_PWM3_IPG_CLK 15
+#define IMX8QXP_LSIO_LPCG_PWM3_IPG_S_CLK 16
+#define IMX8QXP_LSIO_LPCG_PWM3_IPG_HF_CLK 17
+#define IMX8QXP_LSIO_LPCG_PWM3_IPG_SLV_CLK 18
+#define IMX8QXP_LSIO_LPCG_PWM3_IPG_MSTR_CLK 19
+#define IMX8QXP_LSIO_LPCG_PWM4_IPG_CLK 20
+#define IMX8QXP_LSIO_LPCG_PWM4_IPG_S_CLK 21
+#define IMX8QXP_LSIO_LPCG_PWM4_IPG_HF_CLK 22
+#define IMX8QXP_LSIO_LPCG_PWM4_IPG_SLV_CLK 23
+#define IMX8QXP_LSIO_LPCG_PWM4_IPG_MSTR_CLK 24
+#define IMX8QXP_LSIO_LPCG_PWM5_IPG_CLK 25
+#define IMX8QXP_LSIO_LPCG_PWM5_IPG_S_CLK 26
+#define IMX8QXP_LSIO_LPCG_PWM5_IPG_HF_CLK 27
+#define IMX8QXP_LSIO_LPCG_PWM5_IPG_SLV_CLK 28
+#define IMX8QXP_LSIO_LPCG_PWM5_IPG_MSTR_CLK 29
+#define IMX8QXP_LSIO_LPCG_PWM6_IPG_CLK 30
+#define IMX8QXP_LSIO_LPCG_PWM6_IPG_S_CLK 31
+#define IMX8QXP_LSIO_LPCG_PWM6_IPG_HF_CLK 32
+#define IMX8QXP_LSIO_LPCG_PWM6_IPG_SLV_CLK 33
+#define IMX8QXP_LSIO_LPCG_PWM6_IPG_MSTR_CLK 34
+#define IMX8QXP_LSIO_LPCG_PWM7_IPG_CLK 35
+#define IMX8QXP_LSIO_LPCG_PWM7_IPG_S_CLK 36
+#define IMX8QXP_LSIO_LPCG_PWM7_IPG_HF_CLK 37
+#define IMX8QXP_LSIO_LPCG_PWM7_IPG_SLV_CLK 38
+#define IMX8QXP_LSIO_LPCG_PWM7_IPG_MSTR_CLK 39
+#define IMX8QXP_LSIO_LPCG_GPT0_IPG_CLK 40
+#define IMX8QXP_LSIO_LPCG_GPT0_IPG_S_CLK 41
+#define IMX8QXP_LSIO_LPCG_GPT0_IPG_HF_CLK 42
+#define IMX8QXP_LSIO_LPCG_GPT0_IPG_SLV_CLK 43
+#define IMX8QXP_LSIO_LPCG_GPT0_IPG_MSTR_CLK 44
+#define IMX8QXP_LSIO_LPCG_GPT1_IPG_CLK 45
+#define IMX8QXP_LSIO_LPCG_GPT1_IPG_S_CLK 46
+#define IMX8QXP_LSIO_LPCG_GPT1_IPG_HF_CLK 47
+#define IMX8QXP_LSIO_LPCG_GPT1_IPG_SLV_CLK 48
+#define IMX8QXP_LSIO_LPCG_GPT1_IPG_MSTR_CLK 49
+#define IMX8QXP_LSIO_LPCG_GPT2_IPG_CLK 50
+#define IMX8QXP_LSIO_LPCG_GPT2_IPG_S_CLK 51
+#define IMX8QXP_LSIO_LPCG_GPT2_IPG_HF_CLK 52
+#define IMX8QXP_LSIO_LPCG_GPT2_IPG_SLV_CLK 53
+#define IMX8QXP_LSIO_LPCG_GPT2_IPG_MSTR_CLK 54
+#define IMX8QXP_LSIO_LPCG_GPT3_IPG_CLK 55
+#define IMX8QXP_LSIO_LPCG_GPT3_IPG_S_CLK 56
+#define IMX8QXP_LSIO_LPCG_GPT3_IPG_HF_CLK 57
+#define IMX8QXP_LSIO_LPCG_GPT3_IPG_SLV_CLK 58
+#define IMX8QXP_LSIO_LPCG_GPT3_IPG_MSTR_CLK 59
+#define IMX8QXP_LSIO_LPCG_GPT4_IPG_CLK 60
+#define IMX8QXP_LSIO_LPCG_GPT4_IPG_S_CLK 61
+#define IMX8QXP_LSIO_LPCG_GPT4_IPG_HF_CLK 62
+#define IMX8QXP_LSIO_LPCG_GPT4_IPG_SLV_CLK 63
+#define IMX8QXP_LSIO_LPCG_GPT4_IPG_MSTR_CLK 64
+#define IMX8QXP_LSIO_LPCG_FSPI0_HCLK 65
+#define IMX8QXP_LSIO_LPCG_FSPI0_IPG_CLK 66
+#define IMX8QXP_LSIO_LPCG_FSPI0_IPG_S_CLK 67
+#define IMX8QXP_LSIO_LPCG_FSPI0_IPG_SFCK 68
+#define IMX8QXP_LSIO_LPCG_FSPI1_HCLK 69
+#define IMX8QXP_LSIO_LPCG_FSPI1_IPG_CLK 70
+#define IMX8QXP_LSIO_LPCG_FSPI1_IPG_S_CLK 71
+#define IMX8QXP_LSIO_LPCG_FSPI1_IPG_SFCK 72
+
+#define IMX8QXP_LSIO_LPCG_CLK_END 73
+
+/* Connectivity SS LPCG */
+#define IMX8QXP_CONN_LPCG_SDHC0_IPG_CLK 0
+#define IMX8QXP_CONN_LPCG_SDHC0_PER_CLK 1
+#define IMX8QXP_CONN_LPCG_SDHC0_HCLK 2
+#define IMX8QXP_CONN_LPCG_SDHC1_IPG_CLK 3
+#define IMX8QXP_CONN_LPCG_SDHC1_PER_CLK 4
+#define IMX8QXP_CONN_LPCG_SDHC1_HCLK 5
+#define IMX8QXP_CONN_LPCG_SDHC2_IPG_CLK 6
+#define IMX8QXP_CONN_LPCG_SDHC2_PER_CLK 7
+#define IMX8QXP_CONN_LPCG_SDHC2_HCLK 8
+#define IMX8QXP_CONN_LPCG_GPMI_APB_CLK 9
+#define IMX8QXP_CONN_LPCG_GPMI_BCH_APB_CLK 10
+#define IMX8QXP_CONN_LPCG_GPMI_BCH_IO_CLK 11
+#define IMX8QXP_CONN_LPCG_GPMI_BCH_CLK 12
+#define IMX8QXP_CONN_LPCG_APBHDMA_CLK 13
+#define IMX8QXP_CONN_LPCG_ENET0_ROOT_CLK 14
+#define IMX8QXP_CONN_LPCG_ENET0_TX_CLK 15
+#define IMX8QXP_CONN_LPCG_ENET0_AHB_CLK 16
+#define IMX8QXP_CONN_LPCG_ENET0_IPG_S_CLK 17
+#define IMX8QXP_CONN_LPCG_ENET0_IPG_CLK 18
+
+#define IMX8QXP_CONN_LPCG_ENET1_ROOT_CLK 19
+#define IMX8QXP_CONN_LPCG_ENET1_TX_CLK 20
+#define IMX8QXP_CONN_LPCG_ENET1_AHB_CLK 21
+#define IMX8QXP_CONN_LPCG_ENET1_IPG_S_CLK 22
+#define IMX8QXP_CONN_LPCG_ENET1_IPG_CLK 23
+
+#define IMX8QXP_CONN_LPCG_CLK_END 24
+
+/* ADMA SS LPCG */
+#define IMX8QXP_ADMA_LPCG_UART0_IPG_CLK 0
+#define IMX8QXP_ADMA_LPCG_UART0_BAUD_CLK 1
+#define IMX8QXP_ADMA_LPCG_UART1_IPG_CLK 2
+#define IMX8QXP_ADMA_LPCG_UART1_BAUD_CLK 3
+#define IMX8QXP_ADMA_LPCG_UART2_IPG_CLK 4
+#define IMX8QXP_ADMA_LPCG_UART2_BAUD_CLK 5
+#define IMX8QXP_ADMA_LPCG_UART3_IPG_CLK 6
+#define IMX8QXP_ADMA_LPCG_UART3_BAUD_CLK 7
+#define IMX8QXP_ADMA_LPCG_SPI0_IPG_CLK 8
+#define IMX8QXP_ADMA_LPCG_SPI1_IPG_CLK 9
+#define IMX8QXP_ADMA_LPCG_SPI2_IPG_CLK 10
+#define IMX8QXP_ADMA_LPCG_SPI3_IPG_CLK 11
+#define IMX8QXP_ADMA_LPCG_SPI0_CLK 12
+#define IMX8QXP_ADMA_LPCG_SPI1_CLK 13
+#define IMX8QXP_ADMA_LPCG_SPI2_CLK 14
+#define IMX8QXP_ADMA_LPCG_SPI3_CLK 15
+#define IMX8QXP_ADMA_LPCG_CAN0_IPG_CLK 16
+#define IMX8QXP_ADMA_LPCG_CAN0_IPG_PE_CLK 17
+#define IMX8QXP_ADMA_LPCG_CAN0_IPG_CHI_CLK 18
+#define IMX8QXP_ADMA_LPCG_CAN1_IPG_CLK 19
+#define IMX8QXP_ADMA_LPCG_CAN1_IPG_PE_CLK 20
+#define IMX8QXP_ADMA_LPCG_CAN1_IPG_CHI_CLK 21
+#define IMX8QXP_ADMA_LPCG_CAN2_IPG_CLK 22
+#define IMX8QXP_ADMA_LPCG_CAN2_IPG_PE_CLK 23
+#define IMX8QXP_ADMA_LPCG_CAN2_IPG_CHI_CLK 24
+#define IMX8QXP_ADMA_LPCG_I2C0_CLK 25
+#define IMX8QXP_ADMA_LPCG_I2C1_CLK 26
+#define IMX8QXP_ADMA_LPCG_I2C2_CLK 27
+#define IMX8QXP_ADMA_LPCG_I2C3_CLK 28
+#define IMX8QXP_ADMA_LPCG_I2C0_IPG_CLK 29
+#define IMX8QXP_ADMA_LPCG_I2C1_IPG_CLK 30
+#define IMX8QXP_ADMA_LPCG_I2C2_IPG_CLK 31
+#define IMX8QXP_ADMA_LPCG_I2C3_IPG_CLK 32
+#define IMX8QXP_ADMA_LPCG_FTM0_CLK 33
+#define IMX8QXP_ADMA_LPCG_FTM1_CLK 34
+#define IMX8QXP_ADMA_LPCG_FTM0_IPG_CLK 35
+#define IMX8QXP_ADMA_LPCG_FTM1_IPG_CLK 36
+#define IMX8QXP_ADMA_LPCG_PWM_HI_CLK 37
+#define IMX8QXP_ADMA_LPCG_PWM_IPG_CLK 38
+#define IMX8QXP_ADMA_LPCG_LCD_PIX_CLK 39
+#define IMX8QXP_ADMA_LPCG_LCD_APB_CLK 40
+
+#define IMX8QXP_ADMA_LPCG_CLK_END 41
+
#endif /* __DT_BINDINGS_CLOCK_IMX8QXP_H */
--
2.7.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH V6 5/6] clk: imx: add lpcg clock support
2018-11-10 15:19 ` A.s. Dong
@ 2018-11-10 15:20 ` A.s. Dong
-1 siblings, 0 replies; 36+ messages in thread
From: A.s. Dong @ 2018-11-10 15:20 UTC (permalink / raw)
To: linux-clk
Cc: linux-arm-kernel, sboyd, mturquette, shawnguo, Fabio Estevam,
dl-linux-imx, kernel, A.s. Dong
The Low-Power Clock Gate (LPCG) modules contain a local programming
model to control the clock gates for the peripherals. An LPCG module
is used to locally gate the clocks for the associated peripheral.
And they're bedind the SCU clock.
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: Fabio Estevam <fabio.estevam@nxp.com>
Cc: Michael Turquette <mturquette@baylibre.com>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
ChangeLog:
v6: separate from [PATCH V5 5/9] clk: imx: scu: add scu clock gate
---
drivers/clk/imx/Makefile | 3 +-
drivers/clk/imx/clk-lpcg-scu.c | 108 +++++++++++++++++++++++++++++++++++++++++
drivers/clk/imx/clk-scu.h | 3 ++
3 files changed, 113 insertions(+), 1 deletion(-)
create mode 100644 drivers/clk/imx/clk-lpcg-scu.c
diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 8369a34..cd2b6f0 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -14,7 +14,8 @@ obj-$(CONFIG_MXC_CLK) += \
clk-pfd.o
obj-$(CONFIG_MXC_CLK_SCU) += \
- clk-scu.o
+ clk-scu.o \
+ clk-lpcg-scu.o
obj-$(CONFIG_SOC_IMX1) += clk-imx1.o
obj-$(CONFIG_SOC_IMX21) += clk-imx21.o
diff --git a/drivers/clk/imx/clk-lpcg-scu.c b/drivers/clk/imx/clk-lpcg-scu.c
new file mode 100644
index 0000000..54a1cb3
--- /dev/null
+++ b/drivers/clk/imx/clk-lpcg-scu.c
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ * Dong Aisheng <aisheng.dong@nxp.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+static DEFINE_SPINLOCK(imx_lpcg_scu_lock);
+
+#define CLK_GATE_SCU_LPCG_MASK 0x3
+#define CLK_GATE_SCU_LPCG_HW_SEL BIT(0)
+#define CLK_GATE_SCU_LPCG_SW_SEL BIT(1)
+
+struct clk_lpcg_scu {
+ struct clk_hw hw;
+ void __iomem *reg;
+ u8 bit_idx;
+ bool hw_gate;
+};
+
+#define to_clk_lpcg_scu(_hw) container_of(_hw, struct clk_lpcg_scu, hw)
+
+/* Write to the LPCG bits. */
+static int clk_lpcg_scu_enable(struct clk_hw *hw)
+{
+ struct clk_lpcg_scu *clk = to_clk_lpcg_scu(hw);
+ unsigned long flags = 0;
+ u32 reg;
+
+ spin_lock_irqsave(&imx_lpcg_scu_lock, flags);
+
+ if (clk->reg) {
+ reg = readl(clk->reg);
+ reg &= ~(CLK_GATE_SCU_LPCG_MASK << clk->bit_idx);
+ if (clk->hw_gate)
+ reg |= (CLK_GATE_SCU_LPCG_HW_SEL |
+ CLK_GATE_SCU_LPCG_SW_SEL) << clk->bit_idx;
+ else
+ reg |= (CLK_GATE_SCU_LPCG_SW_SEL << clk->bit_idx);
+ writel(reg, clk->reg);
+ }
+
+ spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags);
+
+ return 0;
+}
+
+static void clk_lpcg_scu_disable(struct clk_hw *hw)
+{
+ struct clk_lpcg_scu *clk = to_clk_lpcg_scu(hw);
+ unsigned long flags = 0;
+ u32 reg;
+
+ spin_lock_irqsave(&imx_lpcg_scu_lock, flags);
+
+ if (clk->reg) {
+ reg = readl(clk->reg);
+ reg &= ~(CLK_GATE_SCU_LPCG_MASK << clk->bit_idx);
+ writel(reg, clk->reg);
+ }
+
+ spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags);
+}
+
+static const struct clk_ops clk_lpcg_scu_ops = {
+ .enable = clk_lpcg_scu_enable,
+ .disable = clk_lpcg_scu_disable,
+};
+
+struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
+ unsigned long flags, void __iomem *reg,
+ u8 bit_idx, bool hw_gate)
+{
+ struct clk_lpcg_scu *clk;
+ struct clk_init_data init;
+ struct clk_hw *hw;
+ int ret;
+
+ clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+ if (!clk)
+ return ERR_PTR(-ENOMEM);
+
+ clk->reg = reg;
+ clk->bit_idx = bit_idx;
+ clk->hw_gate = hw_gate;
+
+ init.name = name;
+ init.ops = &clk_lpcg_scu_ops;
+ init.flags = CLK_SET_RATE_PARENT | flags;
+ init.parent_names = parent_name ? &parent_name : NULL;
+ init.num_parents = parent_name ? 1 : 0;
+
+ clk->hw.init = &init;
+
+ hw = &clk->hw;
+ ret = clk_hw_register(NULL, hw);
+ if (ret) {
+ kfree(clk);
+ hw = ERR_PTR(ret);
+ }
+
+ return hw;
+}
diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h
index 09f381b..b8e91b1 100644
--- a/drivers/clk/imx/clk-scu.h
+++ b/drivers/clk/imx/clk-scu.h
@@ -18,4 +18,7 @@ static inline int imx_clk_scu_init(void)
struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id, u8 clk_type);
+struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
+ unsigned long flags, void __iomem *reg,
+ u8 bit_idx, bool hw_gate);
#endif
--
2.7.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH V6 5/6] clk: imx: add lpcg clock support
@ 2018-11-10 15:20 ` A.s. Dong
0 siblings, 0 replies; 36+ messages in thread
From: A.s. Dong @ 2018-11-10 15:20 UTC (permalink / raw)
To: linux-arm-kernel
The Low-Power Clock Gate (LPCG) modules contain a local programming
model to control the clock gates for the peripherals. An LPCG module
is used to locally gate the clocks for the associated peripheral.
And they're bedind the SCU clock.
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: Fabio Estevam <fabio.estevam@nxp.com>
Cc: Michael Turquette <mturquette@baylibre.com>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
ChangeLog:
v6: separate from [PATCH V5 5/9] clk: imx: scu: add scu clock gate
---
drivers/clk/imx/Makefile | 3 +-
drivers/clk/imx/clk-lpcg-scu.c | 108 +++++++++++++++++++++++++++++++++++++++++
drivers/clk/imx/clk-scu.h | 3 ++
3 files changed, 113 insertions(+), 1 deletion(-)
create mode 100644 drivers/clk/imx/clk-lpcg-scu.c
diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 8369a34..cd2b6f0 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -14,7 +14,8 @@ obj-$(CONFIG_MXC_CLK) += \
clk-pfd.o
obj-$(CONFIG_MXC_CLK_SCU) += \
- clk-scu.o
+ clk-scu.o \
+ clk-lpcg-scu.o
obj-$(CONFIG_SOC_IMX1) += clk-imx1.o
obj-$(CONFIG_SOC_IMX21) += clk-imx21.o
diff --git a/drivers/clk/imx/clk-lpcg-scu.c b/drivers/clk/imx/clk-lpcg-scu.c
new file mode 100644
index 0000000..54a1cb3
--- /dev/null
+++ b/drivers/clk/imx/clk-lpcg-scu.c
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ * Dong Aisheng <aisheng.dong@nxp.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+static DEFINE_SPINLOCK(imx_lpcg_scu_lock);
+
+#define CLK_GATE_SCU_LPCG_MASK 0x3
+#define CLK_GATE_SCU_LPCG_HW_SEL BIT(0)
+#define CLK_GATE_SCU_LPCG_SW_SEL BIT(1)
+
+struct clk_lpcg_scu {
+ struct clk_hw hw;
+ void __iomem *reg;
+ u8 bit_idx;
+ bool hw_gate;
+};
+
+#define to_clk_lpcg_scu(_hw) container_of(_hw, struct clk_lpcg_scu, hw)
+
+/* Write to the LPCG bits. */
+static int clk_lpcg_scu_enable(struct clk_hw *hw)
+{
+ struct clk_lpcg_scu *clk = to_clk_lpcg_scu(hw);
+ unsigned long flags = 0;
+ u32 reg;
+
+ spin_lock_irqsave(&imx_lpcg_scu_lock, flags);
+
+ if (clk->reg) {
+ reg = readl(clk->reg);
+ reg &= ~(CLK_GATE_SCU_LPCG_MASK << clk->bit_idx);
+ if (clk->hw_gate)
+ reg |= (CLK_GATE_SCU_LPCG_HW_SEL |
+ CLK_GATE_SCU_LPCG_SW_SEL) << clk->bit_idx;
+ else
+ reg |= (CLK_GATE_SCU_LPCG_SW_SEL << clk->bit_idx);
+ writel(reg, clk->reg);
+ }
+
+ spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags);
+
+ return 0;
+}
+
+static void clk_lpcg_scu_disable(struct clk_hw *hw)
+{
+ struct clk_lpcg_scu *clk = to_clk_lpcg_scu(hw);
+ unsigned long flags = 0;
+ u32 reg;
+
+ spin_lock_irqsave(&imx_lpcg_scu_lock, flags);
+
+ if (clk->reg) {
+ reg = readl(clk->reg);
+ reg &= ~(CLK_GATE_SCU_LPCG_MASK << clk->bit_idx);
+ writel(reg, clk->reg);
+ }
+
+ spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags);
+}
+
+static const struct clk_ops clk_lpcg_scu_ops = {
+ .enable = clk_lpcg_scu_enable,
+ .disable = clk_lpcg_scu_disable,
+};
+
+struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
+ unsigned long flags, void __iomem *reg,
+ u8 bit_idx, bool hw_gate)
+{
+ struct clk_lpcg_scu *clk;
+ struct clk_init_data init;
+ struct clk_hw *hw;
+ int ret;
+
+ clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+ if (!clk)
+ return ERR_PTR(-ENOMEM);
+
+ clk->reg = reg;
+ clk->bit_idx = bit_idx;
+ clk->hw_gate = hw_gate;
+
+ init.name = name;
+ init.ops = &clk_lpcg_scu_ops;
+ init.flags = CLK_SET_RATE_PARENT | flags;
+ init.parent_names = parent_name ? &parent_name : NULL;
+ init.num_parents = parent_name ? 1 : 0;
+
+ clk->hw.init = &init;
+
+ hw = &clk->hw;
+ ret = clk_hw_register(NULL, hw);
+ if (ret) {
+ kfree(clk);
+ hw = ERR_PTR(ret);
+ }
+
+ return hw;
+}
diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h
index 09f381b..b8e91b1 100644
--- a/drivers/clk/imx/clk-scu.h
+++ b/drivers/clk/imx/clk-scu.h
@@ -18,4 +18,7 @@ static inline int imx_clk_scu_init(void)
struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id, u8 clk_type);
+struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
+ unsigned long flags, void __iomem *reg,
+ u8 bit_idx, bool hw_gate);
#endif
--
2.7.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH V6 6/6] clk: imx: add imx8qxp lpcg driver
2018-11-10 15:19 ` A.s. Dong
@ 2018-11-10 15:20 ` A.s. Dong
-1 siblings, 0 replies; 36+ messages in thread
From: A.s. Dong @ 2018-11-10 15:20 UTC (permalink / raw)
To: linux-clk
Cc: linux-arm-kernel, sboyd, mturquette, shawnguo, Fabio Estevam,
dl-linux-imx, kernel, A.s. Dong
Add imx8qxp lpcg driver support
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: Fabio Estevam <fabio.estevam@nxp.com>
Cc: Michael Turquette <mturquette@baylibre.com>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
ChangeLog:
v6: new patch, separate from scu gate driver
---
drivers/clk/imx/Makefile | 2 +-
drivers/clk/imx/clk-imx8qxp-lpcg.c | 198 +++++++++++++++++++++++++++++++++++++
drivers/clk/imx/clk-imx8qxp-lpcg.h | 102 +++++++++++++++++++
3 files changed, 301 insertions(+), 1 deletion(-)
create mode 100644 drivers/clk/imx/clk-imx8qxp-lpcg.c
create mode 100644 drivers/clk/imx/clk-imx8qxp-lpcg.h
diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index cd2b6f0..96ab82b 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -32,4 +32,4 @@ obj-$(CONFIG_SOC_IMX6UL) += clk-imx6ul.o
obj-$(CONFIG_SOC_IMX7D) += clk-imx7d.o
obj-$(CONFIG_SOC_VF610) += clk-vf610.o
-obj-$(CONFIG_SOC_IMX8QXP) += clk-imx8qxp.o
+obj-$(CONFIG_SOC_IMX8QXP) += clk-imx8qxp.o clk-imx8qxp-lpcg.o
diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c
new file mode 100644
index 0000000..7b318d7
--- /dev/null
+++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ * Dong Aisheng <aisheng.dong@nxp.com>
+ */
+
+#include <dt-bindings/clock/imx8qxp-clock.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "clk-scu.h"
+#include "clk-imx8qxp-lpcg.h"
+
+struct imx8qxp_lpcg_data {
+ int id;
+ char *name;
+ char *parent;
+ unsigned long flags;
+ u32 offset;
+ u8 bit_idx;
+ bool hw_gate;
+};
+
+struct imx8qxp_ss_lpcg {
+ const struct imx8qxp_lpcg_data *lpcg;
+ u8 num_lpcg;
+ u8 num_max;
+};
+
+static const struct imx8qxp_lpcg_data imx8qxp_lpcg_adma[] = {
+ { IMX8QXP_ADMA_LPCG_UART0_IPG_CLK, "uart0_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPUART_0_LPCG, 16, 0, },
+ { IMX8QXP_ADMA_LPCG_UART0_BAUD_CLK, "uart0_lpcg_baud_clk", "uart0_clk", 0, ADMA_LPUART_0_LPCG, 0, 0, },
+ { IMX8QXP_ADMA_LPCG_UART1_IPG_CLK, "uart1_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPUART_1_LPCG, 16, 0, },
+ { IMX8QXP_ADMA_LPCG_UART1_BAUD_CLK, "uart1_lpcg_baud_clk", "uart1_clk", 0, ADMA_LPUART_1_LPCG, 0, 0, },
+ { IMX8QXP_ADMA_LPCG_UART2_IPG_CLK, "uart2_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPUART_2_LPCG, 16, 0, },
+ { IMX8QXP_ADMA_LPCG_UART2_BAUD_CLK, "uart2_lpcg_baud_clk", "uart2_clk", 0, ADMA_LPUART_2_LPCG, 0, 0, },
+ { IMX8QXP_ADMA_LPCG_UART3_IPG_CLK, "uart3_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPUART_3_LPCG, 16, 0, },
+ { IMX8QXP_ADMA_LPCG_UART3_BAUD_CLK, "uart3_lpcg_baud_clk", "uart3_clk", 0, ADMA_LPUART_3_LPCG, 0, 0, },
+ { IMX8QXP_ADMA_LPCG_I2C0_IPG_CLK, "i2c0_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPI2C_0_LPCG, 16, 0, },
+ { IMX8QXP_ADMA_LPCG_I2C0_CLK, "i2c0_lpcg_clk", "i2c0_clk", 0, ADMA_LPI2C_0_LPCG, 0, 0, },
+ { IMX8QXP_ADMA_LPCG_I2C1_IPG_CLK, "i2c1_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPI2C_1_LPCG, 16, 0, },
+ { IMX8QXP_ADMA_LPCG_I2C1_CLK, "i2c1_lpcg_clk", "i2c1_clk", 0, ADMA_LPI2C_1_LPCG, 0, 0, },
+ { IMX8QXP_ADMA_LPCG_I2C2_IPG_CLK, "i2c2_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPI2C_2_LPCG, 16, 0, },
+ { IMX8QXP_ADMA_LPCG_I2C2_CLK, "i2c2_lpcg_clk", "i2c2_clk", 0, ADMA_LPI2C_2_LPCG, 0, 0, },
+ { IMX8QXP_ADMA_LPCG_I2C3_IPG_CLK, "i2c3_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPI2C_3_LPCG, 16, 0, },
+ { IMX8QXP_ADMA_LPCG_I2C3_CLK, "i2c3_lpcg_clk", "i2c3_clk", 0, ADMA_LPI2C_3_LPCG, 0, 0, },
+};
+
+static const struct imx8qxp_ss_lpcg imx8qxp_ss_adma = {
+ .lpcg = imx8qxp_lpcg_adma,
+ .num_lpcg = ARRAY_SIZE(imx8qxp_lpcg_adma),
+ .num_max = IMX8QXP_ADMA_LPCG_CLK_END,
+};
+
+static const struct imx8qxp_lpcg_data imx8qxp_lpcg_conn[] = {
+ { IMX8QXP_CONN_LPCG_SDHC0_PER_CLK, "sdhc0_lpcg_per_clk", "sdhc0_clk", 0, CONN_USDHC_0_LPCG, 0, 0, },
+ { IMX8QXP_CONN_LPCG_SDHC0_IPG_CLK, "sdhc0_lpcg_ipg_clk", "conn_ipg_clk_root", 0, CONN_USDHC_0_LPCG, 16, 0, },
+ { IMX8QXP_CONN_LPCG_SDHC0_HCLK, "sdhc0_lpcg_ahb_clk", "conn_axi_clk_root", 0, CONN_USDHC_0_LPCG, 20, 0, },
+ { IMX8QXP_CONN_LPCG_SDHC1_PER_CLK, "sdhc1_lpcg_per_clk", "sdhc1_clk", 0, CONN_USDHC_1_LPCG, 0, 0, },
+ { IMX8QXP_CONN_LPCG_SDHC1_IPG_CLK, "sdhc1_lpcg_ipg_clk", "conn_ipg_clk_root", 0, CONN_USDHC_1_LPCG, 16, 0, },
+ { IMX8QXP_CONN_LPCG_SDHC1_HCLK, "sdhc1_lpcg_ahb_clk", "conn_axi_clk_root", 0, CONN_USDHC_1_LPCG, 20, 0, },
+ { IMX8QXP_CONN_LPCG_SDHC2_PER_CLK, "sdhc2_lpcg_per_clk", "sdhc2_clk", 0, CONN_USDHC_2_LPCG, 0, 0, },
+ { IMX8QXP_CONN_LPCG_SDHC2_IPG_CLK, "sdhc2_lpcg_ipg_clk", "conn_ipg_clk_root", 0, CONN_USDHC_2_LPCG, 16, 0, },
+ { IMX8QXP_CONN_LPCG_SDHC2_HCLK, "sdhc2_lpcg_ahb_clk", "conn_axi_clk_root", 0, CONN_USDHC_2_LPCG, 20, 0, },
+ { IMX8QXP_CONN_LPCG_ENET0_ROOT_CLK, "enet0_ipg_root_clk", "enet0_clk", 0, CONN_ENET_0_LPCG, 0, 0, },
+ { IMX8QXP_CONN_LPCG_ENET0_TX_CLK, "enet0_tx_clk", "enet0_clk", 0, CONN_ENET_0_LPCG, 4, 0, },
+ { IMX8QXP_CONN_LPCG_ENET0_AHB_CLK, "enet0_ahb_clk", "conn_axi_clk_root", 0, CONN_ENET_0_LPCG, 8, 0, },
+ { IMX8QXP_CONN_LPCG_ENET0_IPG_S_CLK, "enet0_ipg_s_clk", "conn_ipg_clk_root", 0, CONN_ENET_0_LPCG, 20, 0, },
+ { IMX8QXP_CONN_LPCG_ENET0_IPG_CLK, "enet0_ipg_clk", "enet0_ipg_s_clk", 0, CONN_ENET_0_LPCG, 16, 0, },
+ { IMX8QXP_CONN_LPCG_ENET1_ROOT_CLK, "enet1_ipg_root_clk", "enet1_clk", 0, CONN_ENET_1_LPCG, 0, 0, },
+ { IMX8QXP_CONN_LPCG_ENET1_TX_CLK, "enet1_tx_clk", "enet1_clk", 0, CONN_ENET_1_LPCG, 4, 0, },
+ { IMX8QXP_CONN_LPCG_ENET1_AHB_CLK, "enet1_ahb_clk", "conn_axi_clk_root", 0, CONN_ENET_1_LPCG, 8, 0, },
+ { IMX8QXP_CONN_LPCG_ENET1_IPG_S_CLK, "enet1_ipg_s_clk", "conn_ipg_clk_root", 0, CONN_ENET_1_LPCG, 20, 0, },
+ { IMX8QXP_CONN_LPCG_ENET1_IPG_CLK, "enet1_ipg_clk", "enet0_ipg_s_clk", 0, CONN_ENET_1_LPCG, 16, 0, },
+};
+
+static const struct imx8qxp_ss_lpcg imx8qxp_ss_conn = {
+ .lpcg = imx8qxp_lpcg_conn,
+ .num_lpcg = ARRAY_SIZE(imx8qxp_lpcg_conn),
+ .num_max = IMX8QXP_CONN_LPCG_CLK_END,
+};
+
+static const struct imx8qxp_lpcg_data imx8qxp_lpcg_lsio[] = {
+ { IMX8QXP_LSIO_LPCG_PWM0_IPG_CLK, "pwm0_lpcg_ipg_clk", "pwm0_clk", 0, LSIO_PWM_0_LPCG, 0, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM0_IPG_HF_CLK, "pwm0_lpcg_ipg_hf_clk", "pwm0_clk", 0, LSIO_PWM_0_LPCG, 4, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM0_IPG_S_CLK, "pwm0_lpcg_ipg_s_clk", "pwm0_clk", 0, LSIO_PWM_0_LPCG, 16, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM0_IPG_SLV_CLK, "pwm0_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_0_LPCG, 20, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM0_IPG_MSTR_CLK, "pwm0_lpcg_ipg_mstr_clk", "pwm0_clk", 0, LSIO_PWM_0_LPCG, 24, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM1_IPG_CLK, "pwm1_lpcg_ipg_clk", "pwm1_clk", 0, LSIO_PWM_1_LPCG, 0, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM1_IPG_HF_CLK, "pwm1_lpcg_ipg_hf_clk", "pwm1_clk", 0, LSIO_PWM_1_LPCG, 4, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM1_IPG_S_CLK, "pwm1_lpcg_ipg_s_clk", "pwm1_clk", 0, LSIO_PWM_1_LPCG, 16, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM1_IPG_SLV_CLK, "pwm1_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_1_LPCG, 20, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM1_IPG_MSTR_CLK, "pwm1_lpcg_ipg_mstr_clk", "pwm1_clk", 0, LSIO_PWM_1_LPCG, 24, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM2_IPG_CLK, "pwm2_lpcg_ipg_clk", "pwm2_clk", 0, LSIO_PWM_2_LPCG, 0, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM2_IPG_HF_CLK, "pwm2_lpcg_ipg_hf_clk", "pwm2_clk", 0, LSIO_PWM_2_LPCG, 4, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM2_IPG_S_CLK, "pwm2_lpcg_ipg_s_clk", "pwm2_clk", 0, LSIO_PWM_2_LPCG, 16, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM2_IPG_SLV_CLK, "pwm2_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_2_LPCG, 20, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM2_IPG_MSTR_CLK, "pwm2_lpcg_ipg_mstr_clk", "pwm2_clk", 0, LSIO_PWM_2_LPCG, 24, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM3_IPG_CLK, "pwm3_lpcg_ipg_clk", "pwm3_clk", 0, LSIO_PWM_3_LPCG, 0, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM3_IPG_HF_CLK, "pwm3_lpcg_ipg_hf_clk", "pwm3_clk", 0, LSIO_PWM_3_LPCG, 4, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM3_IPG_S_CLK, "pwm3_lpcg_ipg_s_clk", "pwm3_clk", 0, LSIO_PWM_3_LPCG, 16, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM3_IPG_SLV_CLK, "pwm3_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_3_LPCG, 20, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM3_IPG_MSTR_CLK, "pwm3_lpcg_ipg_mstr_clk", "pwm3_clk", 0, LSIO_PWM_3_LPCG, 24, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM4_IPG_CLK, "pwm4_lpcg_ipg_clk", "pwm4_clk", 0, LSIO_PWM_4_LPCG, 0, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM4_IPG_HF_CLK, "pwm4_lpcg_ipg_hf_clk", "pwm4_clk", 0, LSIO_PWM_4_LPCG, 4, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM4_IPG_S_CLK, "pwm4_lpcg_ipg_s_clk", "pwm4_clk", 0, LSIO_PWM_4_LPCG, 16, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM4_IPG_SLV_CLK, "pwm4_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_4_LPCG, 20, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM4_IPG_MSTR_CLK, "pwm4_lpcg_ipg_mstr_clk", "pwm4_clk", 0, LSIO_PWM_4_LPCG, 24, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM5_IPG_CLK, "pwm5_lpcg_ipg_clk", "pwm5_clk", 0, LSIO_PWM_5_LPCG, 0, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM5_IPG_HF_CLK, "pwm5_lpcg_ipg_hf_clk", "pwm5_clk", 0, LSIO_PWM_5_LPCG, 4, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM5_IPG_S_CLK, "pwm5_lpcg_ipg_s_clk", "pwm5_clk", 0, LSIO_PWM_5_LPCG, 16, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM5_IPG_SLV_CLK, "pwm5_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_5_LPCG, 20, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM5_IPG_MSTR_CLK, "pwm5_lpcg_ipg_mstr_clk", "pwm5_clk", 0, LSIO_PWM_5_LPCG, 24, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM6_IPG_CLK, "pwm6_lpcg_ipg_clk", "pwm6_clk", 0, LSIO_PWM_6_LPCG, 0, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM6_IPG_HF_CLK, "pwm6_lpcg_ipg_hf_clk", "pwm6_clk", 0, LSIO_PWM_6_LPCG, 4, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM6_IPG_S_CLK, "pwm6_lpcg_ipg_s_clk", "pwm6_clk", 0, LSIO_PWM_6_LPCG, 16, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM6_IPG_SLV_CLK, "pwm6_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_6_LPCG, 20, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM6_IPG_MSTR_CLK, "pwm6_lpcg_ipg_mstr_clk", "pwm6_clk", 0, LSIO_PWM_6_LPCG, 24, 0, },
+};
+
+static const struct imx8qxp_ss_lpcg imx8qxp_ss_lsio = {
+ .lpcg = imx8qxp_lpcg_lsio,
+ .num_lpcg = ARRAY_SIZE(imx8qxp_lpcg_lsio),
+ .num_max = IMX8QXP_LSIO_LPCG_CLK_END,
+};
+
+static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct clk_hw_onecell_data *clk_data;
+ const struct imx8qxp_ss_lpcg *ss_lpcg;
+ const struct imx8qxp_lpcg_data *lpcg;
+ struct resource *res;
+ struct clk_hw **clks;
+ void __iomem *base;
+ int i;
+
+ ss_lpcg = of_device_get_match_data(dev);
+ if (!ss_lpcg)
+ return -ENODEV;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap(dev, res->start, resource_size(res));
+ if (!base)
+ return -ENOMEM;
+
+ clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data) +
+ sizeof(*clk_data->hws) * ss_lpcg->num_max,
+ GFP_KERNEL);
+ if (!clk_data)
+ return -ENOMEM;
+
+ clk_data->num = ss_lpcg->num_max;
+ clks = clk_data->hws;
+
+ for (i = 0; i < ss_lpcg->num_lpcg; i++) {
+ lpcg = ss_lpcg->lpcg + i;
+ clks[lpcg->id] = imx_clk_lpcg_scu(lpcg->name, lpcg->parent,
+ lpcg->flags, base + lpcg->offset,
+ lpcg->bit_idx, lpcg->hw_gate);
+ }
+
+ for (i = 0; i < clk_data->num; i++) {
+ if (IS_ERR(clks[i]))
+ pr_err("i.MX clk %u: register failed with %ld\n",
+ i, PTR_ERR(clks[i]));
+ }
+
+ return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
+}
+
+static const struct of_device_id imx8qxp_lpcg_match[] = {
+ { .compatible = "fsl,imx8qxp-lpcg-adma", &imx8qxp_ss_adma, },
+ { .compatible = "fsl,imx8qxp-lpcg-conn", &imx8qxp_ss_conn, },
+ { .compatible = "fsl,imx8qxp-lpcg-lsio", &imx8qxp_ss_lsio, },
+ { /* sentinel */ }
+};
+
+static struct platform_driver imx8qxp_lpcg_clk_driver = {
+ .driver = {
+ .name = "imx8qxp-lpcg-clk",
+ .of_match_table = imx8qxp_lpcg_match,
+ },
+ .probe = imx8qxp_lpcg_clk_probe,
+};
+
+builtin_platform_driver(imx8qxp_lpcg_clk_driver);
+
+MODULE_AUTHOR("Dong Aisheng <aisheng.dong@nxp.com>");
+MODULE_DESCRIPTION("IMX8QXP LPCG Clock driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.h b/drivers/clk/imx/clk-imx8qxp-lpcg.h
new file mode 100644
index 0000000..2a37ce5
--- /dev/null
+++ b/drivers/clk/imx/clk-imx8qxp-lpcg.h
@@ -0,0 +1,102 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2018 NXP
+ * Dong Aisheng <aisheng.dong@nxp.com>
+ */
+
+#ifndef _IMX8QXP_LPCG_H
+#define _IMX8QXP_LPCG_H
+
+/*LSIO SS */
+#define LSIO_PWM_0_LPCG 0x00000
+#define LSIO_PWM_1_LPCG 0x10000
+#define LSIO_PWM_2_LPCG 0x20000
+#define LSIO_PWM_3_LPCG 0x30000
+#define LSIO_PWM_4_LPCG 0x40000
+#define LSIO_PWM_5_LPCG 0x50000
+#define LSIO_PWM_6_LPCG 0x60000
+#define LSIO_PWM_7_LPCG 0x70000
+#define LSIO_GPIO_0_LPCG 0x80000
+#define LSIO_GPIO_1_LPCG 0x90000
+#define LSIO_GPIO_2_LPCG 0xa0000
+#define LSIO_GPIO_3_LPCG 0xb0000
+#define LSIO_GPIO_4_LPCG 0xc0000
+#define LSIO_GPIO_5_LPCG 0xd0000
+#define LSIO_GPIO_6_LPCG 0xe0000
+#define LSIO_GPIO_7_LPCG 0xf0000
+#define LSIO_FSPI_0_LPCG 0x120000
+#define LSIO_FSPI_1_LPCG 0x130000
+#define LSIO_GPT_0_LPCG 0x140000
+#define LSIO_GPT_1_LPCG 0x150000
+#define LSIO_GPT_2_LPCG 0x160000
+#define LSIO_GPT_3_LPCG 0x170000
+#define LSIO_GPT_4_LPCG 0x180000
+#define LSIO_OCRAM_LPCG 0x190000
+#define LSIO_KPP_LPCG 0x1a0000
+#define LSIO_ROMCP_LPCG 0x100000
+
+/* Connectivity SS */
+#define CONN_USDHC_0_LPCG 0x00000
+#define CONN_USDHC_1_LPCG 0x10000
+#define CONN_USDHC_2_LPCG 0x20000
+#define CONN_ENET_0_LPCG 0x30000
+#define CONN_ENET_1_LPCG 0x40000
+#define CONN_DTCP_LPCG 0x50000
+#define CONN_MLB_LPCG 0x60000
+#define CONN_USB_2_LPCG 0x70000
+#define CONN_USB_3_LPCG 0x80000
+#define CONN_NAND_LPCG 0x90000
+#define CONN_EDMA_LPCG 0xa0000
+
+/* ADMA SS */
+#define ADMA_ASRC_0_LPCG 0x400000
+#define ADMA_ESAI_0_LPCG 0x410000
+#define ADMA_SPDIF_0_LPCG 0x420000
+#define ADMA_SAI_0_LPCG 0x440000
+#define ADMA_SAI_1_LPCG 0x450000
+#define ADMA_SAI_2_LPCG 0x460000
+#define ADMA_SAI_3_LPCG 0x470000
+#define ADMA_GPT_5_LPCG 0x4b0000
+#define ADMA_GPT_6_LPCG 0x4c0000
+#define ADMA_GPT_7_LPCG 0x4d0000
+#define ADMA_GPT_8_LPCG 0x4e0000
+#define ADMA_GPT_9_LPCG 0x4f0000
+#define ADMA_GPT_10_LPCG 0x500000
+#define ADMA_HIFI_LPCG 0x580000
+#define ADMA_OCRAM_LPCG 0x590000
+#define ADMA_EDMA_0_LPCG 0x5f0000
+#define ADMA_ASRC_1_LPCG 0xc00000
+#define ADMA_SAI_4_LPCG 0xc20000
+#define ADMA_SAI_5_LPCG 0xc30000
+#define ADMA_AMIX_LPCG 0xc40000
+#define ADMA_MQS_LPCG 0xc50000
+#define ADMA_ACM_LPCG 0xc60000
+#define ADMA_REC_CLK0_LPCG 0xd00000
+#define ADMA_REC_CLK1_LPCG 0xd10000
+#define ADMA_PLL_CLK0_LPCG 0xd20000
+#define ADMA_PLL_CLK1_LPCG 0xd30000
+#define ADMA_MCLKOUT0_LPCG 0xd50000
+#define ADMA_MCLKOUT1_LPCG 0xd60000
+#define ADMA_EDMA_1_LPCG 0xdf0000
+#define ADMA_LPSPI_0_LPCG 0x1400000
+#define ADMA_LPSPI_1_LPCG 0x1410000
+#define ADMA_LPSPI_2_LPCG 0x1420000
+#define ADMA_LPSPI_3_LPCG 0x1430000
+#define ADMA_LPUART_0_LPCG 0x1460000
+#define ADMA_LPUART_1_LPCG 0x1470000
+#define ADMA_LPUART_2_LPCG 0x1480000
+#define ADMA_LPUART_3_LPCG 0x1490000
+#define ADMA_LCD_LPCG 0x1580000
+#define ADMA_PWM_LPCG 0x1590000
+#define ADMA_LPI2C_0_LPCG 0x1c00000
+#define ADMA_LPI2C_1_LPCG 0x1c10000
+#define ADMA_LPI2C_2_LPCG 0x1c20000
+#define ADMA_LPI2C_3_LPCG 0x1c30000
+#define ADMA_ADC_0_LPCG 0x1c80000
+#define ADMA_FTM_0_LPCG 0x1ca0000
+#define ADMA_FTM_1_LPCG 0x1cb0000
+#define ADMA_FLEXCAN_0_LPCG 0x1cd0000
+#define ADMA_FLEXCAN_1_LPCG 0x1ce0000
+#define ADMA_FLEXCAN_2_LPCG 0x1cf0000
+
+#endif /* _IMX8QXP_LPCG_H */
--
2.7.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH V6 6/6] clk: imx: add imx8qxp lpcg driver
@ 2018-11-10 15:20 ` A.s. Dong
0 siblings, 0 replies; 36+ messages in thread
From: A.s. Dong @ 2018-11-10 15:20 UTC (permalink / raw)
To: linux-arm-kernel
Add imx8qxp lpcg driver support
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: Fabio Estevam <fabio.estevam@nxp.com>
Cc: Michael Turquette <mturquette@baylibre.com>
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
---
ChangeLog:
v6: new patch, separate from scu gate driver
---
drivers/clk/imx/Makefile | 2 +-
drivers/clk/imx/clk-imx8qxp-lpcg.c | 198 +++++++++++++++++++++++++++++++++++++
drivers/clk/imx/clk-imx8qxp-lpcg.h | 102 +++++++++++++++++++
3 files changed, 301 insertions(+), 1 deletion(-)
create mode 100644 drivers/clk/imx/clk-imx8qxp-lpcg.c
create mode 100644 drivers/clk/imx/clk-imx8qxp-lpcg.h
diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index cd2b6f0..96ab82b 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -32,4 +32,4 @@ obj-$(CONFIG_SOC_IMX6UL) += clk-imx6ul.o
obj-$(CONFIG_SOC_IMX7D) += clk-imx7d.o
obj-$(CONFIG_SOC_VF610) += clk-vf610.o
-obj-$(CONFIG_SOC_IMX8QXP) += clk-imx8qxp.o
+obj-$(CONFIG_SOC_IMX8QXP) += clk-imx8qxp.o clk-imx8qxp-lpcg.o
diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c
new file mode 100644
index 0000000..7b318d7
--- /dev/null
+++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ * Dong Aisheng <aisheng.dong@nxp.com>
+ */
+
+#include <dt-bindings/clock/imx8qxp-clock.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "clk-scu.h"
+#include "clk-imx8qxp-lpcg.h"
+
+struct imx8qxp_lpcg_data {
+ int id;
+ char *name;
+ char *parent;
+ unsigned long flags;
+ u32 offset;
+ u8 bit_idx;
+ bool hw_gate;
+};
+
+struct imx8qxp_ss_lpcg {
+ const struct imx8qxp_lpcg_data *lpcg;
+ u8 num_lpcg;
+ u8 num_max;
+};
+
+static const struct imx8qxp_lpcg_data imx8qxp_lpcg_adma[] = {
+ { IMX8QXP_ADMA_LPCG_UART0_IPG_CLK, "uart0_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPUART_0_LPCG, 16, 0, },
+ { IMX8QXP_ADMA_LPCG_UART0_BAUD_CLK, "uart0_lpcg_baud_clk", "uart0_clk", 0, ADMA_LPUART_0_LPCG, 0, 0, },
+ { IMX8QXP_ADMA_LPCG_UART1_IPG_CLK, "uart1_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPUART_1_LPCG, 16, 0, },
+ { IMX8QXP_ADMA_LPCG_UART1_BAUD_CLK, "uart1_lpcg_baud_clk", "uart1_clk", 0, ADMA_LPUART_1_LPCG, 0, 0, },
+ { IMX8QXP_ADMA_LPCG_UART2_IPG_CLK, "uart2_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPUART_2_LPCG, 16, 0, },
+ { IMX8QXP_ADMA_LPCG_UART2_BAUD_CLK, "uart2_lpcg_baud_clk", "uart2_clk", 0, ADMA_LPUART_2_LPCG, 0, 0, },
+ { IMX8QXP_ADMA_LPCG_UART3_IPG_CLK, "uart3_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPUART_3_LPCG, 16, 0, },
+ { IMX8QXP_ADMA_LPCG_UART3_BAUD_CLK, "uart3_lpcg_baud_clk", "uart3_clk", 0, ADMA_LPUART_3_LPCG, 0, 0, },
+ { IMX8QXP_ADMA_LPCG_I2C0_IPG_CLK, "i2c0_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPI2C_0_LPCG, 16, 0, },
+ { IMX8QXP_ADMA_LPCG_I2C0_CLK, "i2c0_lpcg_clk", "i2c0_clk", 0, ADMA_LPI2C_0_LPCG, 0, 0, },
+ { IMX8QXP_ADMA_LPCG_I2C1_IPG_CLK, "i2c1_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPI2C_1_LPCG, 16, 0, },
+ { IMX8QXP_ADMA_LPCG_I2C1_CLK, "i2c1_lpcg_clk", "i2c1_clk", 0, ADMA_LPI2C_1_LPCG, 0, 0, },
+ { IMX8QXP_ADMA_LPCG_I2C2_IPG_CLK, "i2c2_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPI2C_2_LPCG, 16, 0, },
+ { IMX8QXP_ADMA_LPCG_I2C2_CLK, "i2c2_lpcg_clk", "i2c2_clk", 0, ADMA_LPI2C_2_LPCG, 0, 0, },
+ { IMX8QXP_ADMA_LPCG_I2C3_IPG_CLK, "i2c3_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPI2C_3_LPCG, 16, 0, },
+ { IMX8QXP_ADMA_LPCG_I2C3_CLK, "i2c3_lpcg_clk", "i2c3_clk", 0, ADMA_LPI2C_3_LPCG, 0, 0, },
+};
+
+static const struct imx8qxp_ss_lpcg imx8qxp_ss_adma = {
+ .lpcg = imx8qxp_lpcg_adma,
+ .num_lpcg = ARRAY_SIZE(imx8qxp_lpcg_adma),
+ .num_max = IMX8QXP_ADMA_LPCG_CLK_END,
+};
+
+static const struct imx8qxp_lpcg_data imx8qxp_lpcg_conn[] = {
+ { IMX8QXP_CONN_LPCG_SDHC0_PER_CLK, "sdhc0_lpcg_per_clk", "sdhc0_clk", 0, CONN_USDHC_0_LPCG, 0, 0, },
+ { IMX8QXP_CONN_LPCG_SDHC0_IPG_CLK, "sdhc0_lpcg_ipg_clk", "conn_ipg_clk_root", 0, CONN_USDHC_0_LPCG, 16, 0, },
+ { IMX8QXP_CONN_LPCG_SDHC0_HCLK, "sdhc0_lpcg_ahb_clk", "conn_axi_clk_root", 0, CONN_USDHC_0_LPCG, 20, 0, },
+ { IMX8QXP_CONN_LPCG_SDHC1_PER_CLK, "sdhc1_lpcg_per_clk", "sdhc1_clk", 0, CONN_USDHC_1_LPCG, 0, 0, },
+ { IMX8QXP_CONN_LPCG_SDHC1_IPG_CLK, "sdhc1_lpcg_ipg_clk", "conn_ipg_clk_root", 0, CONN_USDHC_1_LPCG, 16, 0, },
+ { IMX8QXP_CONN_LPCG_SDHC1_HCLK, "sdhc1_lpcg_ahb_clk", "conn_axi_clk_root", 0, CONN_USDHC_1_LPCG, 20, 0, },
+ { IMX8QXP_CONN_LPCG_SDHC2_PER_CLK, "sdhc2_lpcg_per_clk", "sdhc2_clk", 0, CONN_USDHC_2_LPCG, 0, 0, },
+ { IMX8QXP_CONN_LPCG_SDHC2_IPG_CLK, "sdhc2_lpcg_ipg_clk", "conn_ipg_clk_root", 0, CONN_USDHC_2_LPCG, 16, 0, },
+ { IMX8QXP_CONN_LPCG_SDHC2_HCLK, "sdhc2_lpcg_ahb_clk", "conn_axi_clk_root", 0, CONN_USDHC_2_LPCG, 20, 0, },
+ { IMX8QXP_CONN_LPCG_ENET0_ROOT_CLK, "enet0_ipg_root_clk", "enet0_clk", 0, CONN_ENET_0_LPCG, 0, 0, },
+ { IMX8QXP_CONN_LPCG_ENET0_TX_CLK, "enet0_tx_clk", "enet0_clk", 0, CONN_ENET_0_LPCG, 4, 0, },
+ { IMX8QXP_CONN_LPCG_ENET0_AHB_CLK, "enet0_ahb_clk", "conn_axi_clk_root", 0, CONN_ENET_0_LPCG, 8, 0, },
+ { IMX8QXP_CONN_LPCG_ENET0_IPG_S_CLK, "enet0_ipg_s_clk", "conn_ipg_clk_root", 0, CONN_ENET_0_LPCG, 20, 0, },
+ { IMX8QXP_CONN_LPCG_ENET0_IPG_CLK, "enet0_ipg_clk", "enet0_ipg_s_clk", 0, CONN_ENET_0_LPCG, 16, 0, },
+ { IMX8QXP_CONN_LPCG_ENET1_ROOT_CLK, "enet1_ipg_root_clk", "enet1_clk", 0, CONN_ENET_1_LPCG, 0, 0, },
+ { IMX8QXP_CONN_LPCG_ENET1_TX_CLK, "enet1_tx_clk", "enet1_clk", 0, CONN_ENET_1_LPCG, 4, 0, },
+ { IMX8QXP_CONN_LPCG_ENET1_AHB_CLK, "enet1_ahb_clk", "conn_axi_clk_root", 0, CONN_ENET_1_LPCG, 8, 0, },
+ { IMX8QXP_CONN_LPCG_ENET1_IPG_S_CLK, "enet1_ipg_s_clk", "conn_ipg_clk_root", 0, CONN_ENET_1_LPCG, 20, 0, },
+ { IMX8QXP_CONN_LPCG_ENET1_IPG_CLK, "enet1_ipg_clk", "enet0_ipg_s_clk", 0, CONN_ENET_1_LPCG, 16, 0, },
+};
+
+static const struct imx8qxp_ss_lpcg imx8qxp_ss_conn = {
+ .lpcg = imx8qxp_lpcg_conn,
+ .num_lpcg = ARRAY_SIZE(imx8qxp_lpcg_conn),
+ .num_max = IMX8QXP_CONN_LPCG_CLK_END,
+};
+
+static const struct imx8qxp_lpcg_data imx8qxp_lpcg_lsio[] = {
+ { IMX8QXP_LSIO_LPCG_PWM0_IPG_CLK, "pwm0_lpcg_ipg_clk", "pwm0_clk", 0, LSIO_PWM_0_LPCG, 0, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM0_IPG_HF_CLK, "pwm0_lpcg_ipg_hf_clk", "pwm0_clk", 0, LSIO_PWM_0_LPCG, 4, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM0_IPG_S_CLK, "pwm0_lpcg_ipg_s_clk", "pwm0_clk", 0, LSIO_PWM_0_LPCG, 16, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM0_IPG_SLV_CLK, "pwm0_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_0_LPCG, 20, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM0_IPG_MSTR_CLK, "pwm0_lpcg_ipg_mstr_clk", "pwm0_clk", 0, LSIO_PWM_0_LPCG, 24, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM1_IPG_CLK, "pwm1_lpcg_ipg_clk", "pwm1_clk", 0, LSIO_PWM_1_LPCG, 0, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM1_IPG_HF_CLK, "pwm1_lpcg_ipg_hf_clk", "pwm1_clk", 0, LSIO_PWM_1_LPCG, 4, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM1_IPG_S_CLK, "pwm1_lpcg_ipg_s_clk", "pwm1_clk", 0, LSIO_PWM_1_LPCG, 16, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM1_IPG_SLV_CLK, "pwm1_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_1_LPCG, 20, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM1_IPG_MSTR_CLK, "pwm1_lpcg_ipg_mstr_clk", "pwm1_clk", 0, LSIO_PWM_1_LPCG, 24, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM2_IPG_CLK, "pwm2_lpcg_ipg_clk", "pwm2_clk", 0, LSIO_PWM_2_LPCG, 0, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM2_IPG_HF_CLK, "pwm2_lpcg_ipg_hf_clk", "pwm2_clk", 0, LSIO_PWM_2_LPCG, 4, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM2_IPG_S_CLK, "pwm2_lpcg_ipg_s_clk", "pwm2_clk", 0, LSIO_PWM_2_LPCG, 16, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM2_IPG_SLV_CLK, "pwm2_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_2_LPCG, 20, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM2_IPG_MSTR_CLK, "pwm2_lpcg_ipg_mstr_clk", "pwm2_clk", 0, LSIO_PWM_2_LPCG, 24, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM3_IPG_CLK, "pwm3_lpcg_ipg_clk", "pwm3_clk", 0, LSIO_PWM_3_LPCG, 0, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM3_IPG_HF_CLK, "pwm3_lpcg_ipg_hf_clk", "pwm3_clk", 0, LSIO_PWM_3_LPCG, 4, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM3_IPG_S_CLK, "pwm3_lpcg_ipg_s_clk", "pwm3_clk", 0, LSIO_PWM_3_LPCG, 16, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM3_IPG_SLV_CLK, "pwm3_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_3_LPCG, 20, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM3_IPG_MSTR_CLK, "pwm3_lpcg_ipg_mstr_clk", "pwm3_clk", 0, LSIO_PWM_3_LPCG, 24, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM4_IPG_CLK, "pwm4_lpcg_ipg_clk", "pwm4_clk", 0, LSIO_PWM_4_LPCG, 0, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM4_IPG_HF_CLK, "pwm4_lpcg_ipg_hf_clk", "pwm4_clk", 0, LSIO_PWM_4_LPCG, 4, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM4_IPG_S_CLK, "pwm4_lpcg_ipg_s_clk", "pwm4_clk", 0, LSIO_PWM_4_LPCG, 16, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM4_IPG_SLV_CLK, "pwm4_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_4_LPCG, 20, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM4_IPG_MSTR_CLK, "pwm4_lpcg_ipg_mstr_clk", "pwm4_clk", 0, LSIO_PWM_4_LPCG, 24, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM5_IPG_CLK, "pwm5_lpcg_ipg_clk", "pwm5_clk", 0, LSIO_PWM_5_LPCG, 0, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM5_IPG_HF_CLK, "pwm5_lpcg_ipg_hf_clk", "pwm5_clk", 0, LSIO_PWM_5_LPCG, 4, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM5_IPG_S_CLK, "pwm5_lpcg_ipg_s_clk", "pwm5_clk", 0, LSIO_PWM_5_LPCG, 16, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM5_IPG_SLV_CLK, "pwm5_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_5_LPCG, 20, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM5_IPG_MSTR_CLK, "pwm5_lpcg_ipg_mstr_clk", "pwm5_clk", 0, LSIO_PWM_5_LPCG, 24, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM6_IPG_CLK, "pwm6_lpcg_ipg_clk", "pwm6_clk", 0, LSIO_PWM_6_LPCG, 0, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM6_IPG_HF_CLK, "pwm6_lpcg_ipg_hf_clk", "pwm6_clk", 0, LSIO_PWM_6_LPCG, 4, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM6_IPG_S_CLK, "pwm6_lpcg_ipg_s_clk", "pwm6_clk", 0, LSIO_PWM_6_LPCG, 16, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM6_IPG_SLV_CLK, "pwm6_lpcg_ipg_slv_clk", "lsio_bus_clk_root", 0, LSIO_PWM_6_LPCG, 20, 0, },
+ { IMX8QXP_LSIO_LPCG_PWM6_IPG_MSTR_CLK, "pwm6_lpcg_ipg_mstr_clk", "pwm6_clk", 0, LSIO_PWM_6_LPCG, 24, 0, },
+};
+
+static const struct imx8qxp_ss_lpcg imx8qxp_ss_lsio = {
+ .lpcg = imx8qxp_lpcg_lsio,
+ .num_lpcg = ARRAY_SIZE(imx8qxp_lpcg_lsio),
+ .num_max = IMX8QXP_LSIO_LPCG_CLK_END,
+};
+
+static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct clk_hw_onecell_data *clk_data;
+ const struct imx8qxp_ss_lpcg *ss_lpcg;
+ const struct imx8qxp_lpcg_data *lpcg;
+ struct resource *res;
+ struct clk_hw **clks;
+ void __iomem *base;
+ int i;
+
+ ss_lpcg = of_device_get_match_data(dev);
+ if (!ss_lpcg)
+ return -ENODEV;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap(dev, res->start, resource_size(res));
+ if (!base)
+ return -ENOMEM;
+
+ clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data) +
+ sizeof(*clk_data->hws) * ss_lpcg->num_max,
+ GFP_KERNEL);
+ if (!clk_data)
+ return -ENOMEM;
+
+ clk_data->num = ss_lpcg->num_max;
+ clks = clk_data->hws;
+
+ for (i = 0; i < ss_lpcg->num_lpcg; i++) {
+ lpcg = ss_lpcg->lpcg + i;
+ clks[lpcg->id] = imx_clk_lpcg_scu(lpcg->name, lpcg->parent,
+ lpcg->flags, base + lpcg->offset,
+ lpcg->bit_idx, lpcg->hw_gate);
+ }
+
+ for (i = 0; i < clk_data->num; i++) {
+ if (IS_ERR(clks[i]))
+ pr_err("i.MX clk %u: register failed with %ld\n",
+ i, PTR_ERR(clks[i]));
+ }
+
+ return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
+}
+
+static const struct of_device_id imx8qxp_lpcg_match[] = {
+ { .compatible = "fsl,imx8qxp-lpcg-adma", &imx8qxp_ss_adma, },
+ { .compatible = "fsl,imx8qxp-lpcg-conn", &imx8qxp_ss_conn, },
+ { .compatible = "fsl,imx8qxp-lpcg-lsio", &imx8qxp_ss_lsio, },
+ { /* sentinel */ }
+};
+
+static struct platform_driver imx8qxp_lpcg_clk_driver = {
+ .driver = {
+ .name = "imx8qxp-lpcg-clk",
+ .of_match_table = imx8qxp_lpcg_match,
+ },
+ .probe = imx8qxp_lpcg_clk_probe,
+};
+
+builtin_platform_driver(imx8qxp_lpcg_clk_driver);
+
+MODULE_AUTHOR("Dong Aisheng <aisheng.dong@nxp.com>");
+MODULE_DESCRIPTION("IMX8QXP LPCG Clock driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.h b/drivers/clk/imx/clk-imx8qxp-lpcg.h
new file mode 100644
index 0000000..2a37ce5
--- /dev/null
+++ b/drivers/clk/imx/clk-imx8qxp-lpcg.h
@@ -0,0 +1,102 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2018 NXP
+ * Dong Aisheng <aisheng.dong@nxp.com>
+ */
+
+#ifndef _IMX8QXP_LPCG_H
+#define _IMX8QXP_LPCG_H
+
+/*LSIO SS */
+#define LSIO_PWM_0_LPCG 0x00000
+#define LSIO_PWM_1_LPCG 0x10000
+#define LSIO_PWM_2_LPCG 0x20000
+#define LSIO_PWM_3_LPCG 0x30000
+#define LSIO_PWM_4_LPCG 0x40000
+#define LSIO_PWM_5_LPCG 0x50000
+#define LSIO_PWM_6_LPCG 0x60000
+#define LSIO_PWM_7_LPCG 0x70000
+#define LSIO_GPIO_0_LPCG 0x80000
+#define LSIO_GPIO_1_LPCG 0x90000
+#define LSIO_GPIO_2_LPCG 0xa0000
+#define LSIO_GPIO_3_LPCG 0xb0000
+#define LSIO_GPIO_4_LPCG 0xc0000
+#define LSIO_GPIO_5_LPCG 0xd0000
+#define LSIO_GPIO_6_LPCG 0xe0000
+#define LSIO_GPIO_7_LPCG 0xf0000
+#define LSIO_FSPI_0_LPCG 0x120000
+#define LSIO_FSPI_1_LPCG 0x130000
+#define LSIO_GPT_0_LPCG 0x140000
+#define LSIO_GPT_1_LPCG 0x150000
+#define LSIO_GPT_2_LPCG 0x160000
+#define LSIO_GPT_3_LPCG 0x170000
+#define LSIO_GPT_4_LPCG 0x180000
+#define LSIO_OCRAM_LPCG 0x190000
+#define LSIO_KPP_LPCG 0x1a0000
+#define LSIO_ROMCP_LPCG 0x100000
+
+/* Connectivity SS */
+#define CONN_USDHC_0_LPCG 0x00000
+#define CONN_USDHC_1_LPCG 0x10000
+#define CONN_USDHC_2_LPCG 0x20000
+#define CONN_ENET_0_LPCG 0x30000
+#define CONN_ENET_1_LPCG 0x40000
+#define CONN_DTCP_LPCG 0x50000
+#define CONN_MLB_LPCG 0x60000
+#define CONN_USB_2_LPCG 0x70000
+#define CONN_USB_3_LPCG 0x80000
+#define CONN_NAND_LPCG 0x90000
+#define CONN_EDMA_LPCG 0xa0000
+
+/* ADMA SS */
+#define ADMA_ASRC_0_LPCG 0x400000
+#define ADMA_ESAI_0_LPCG 0x410000
+#define ADMA_SPDIF_0_LPCG 0x420000
+#define ADMA_SAI_0_LPCG 0x440000
+#define ADMA_SAI_1_LPCG 0x450000
+#define ADMA_SAI_2_LPCG 0x460000
+#define ADMA_SAI_3_LPCG 0x470000
+#define ADMA_GPT_5_LPCG 0x4b0000
+#define ADMA_GPT_6_LPCG 0x4c0000
+#define ADMA_GPT_7_LPCG 0x4d0000
+#define ADMA_GPT_8_LPCG 0x4e0000
+#define ADMA_GPT_9_LPCG 0x4f0000
+#define ADMA_GPT_10_LPCG 0x500000
+#define ADMA_HIFI_LPCG 0x580000
+#define ADMA_OCRAM_LPCG 0x590000
+#define ADMA_EDMA_0_LPCG 0x5f0000
+#define ADMA_ASRC_1_LPCG 0xc00000
+#define ADMA_SAI_4_LPCG 0xc20000
+#define ADMA_SAI_5_LPCG 0xc30000
+#define ADMA_AMIX_LPCG 0xc40000
+#define ADMA_MQS_LPCG 0xc50000
+#define ADMA_ACM_LPCG 0xc60000
+#define ADMA_REC_CLK0_LPCG 0xd00000
+#define ADMA_REC_CLK1_LPCG 0xd10000
+#define ADMA_PLL_CLK0_LPCG 0xd20000
+#define ADMA_PLL_CLK1_LPCG 0xd30000
+#define ADMA_MCLKOUT0_LPCG 0xd50000
+#define ADMA_MCLKOUT1_LPCG 0xd60000
+#define ADMA_EDMA_1_LPCG 0xdf0000
+#define ADMA_LPSPI_0_LPCG 0x1400000
+#define ADMA_LPSPI_1_LPCG 0x1410000
+#define ADMA_LPSPI_2_LPCG 0x1420000
+#define ADMA_LPSPI_3_LPCG 0x1430000
+#define ADMA_LPUART_0_LPCG 0x1460000
+#define ADMA_LPUART_1_LPCG 0x1470000
+#define ADMA_LPUART_2_LPCG 0x1480000
+#define ADMA_LPUART_3_LPCG 0x1490000
+#define ADMA_LCD_LPCG 0x1580000
+#define ADMA_PWM_LPCG 0x1590000
+#define ADMA_LPI2C_0_LPCG 0x1c00000
+#define ADMA_LPI2C_1_LPCG 0x1c10000
+#define ADMA_LPI2C_2_LPCG 0x1c20000
+#define ADMA_LPI2C_3_LPCG 0x1c30000
+#define ADMA_ADC_0_LPCG 0x1c80000
+#define ADMA_FTM_0_LPCG 0x1ca0000
+#define ADMA_FTM_1_LPCG 0x1cb0000
+#define ADMA_FLEXCAN_0_LPCG 0x1cd0000
+#define ADMA_FLEXCAN_1_LPCG 0x1ce0000
+#define ADMA_FLEXCAN_2_LPCG 0x1cf0000
+
+#endif /* _IMX8QXP_LPCG_H */
--
2.7.4
^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH V6 2/6] dt-bindings: clock: imx8qxp: add SCU clock IDs
2018-11-10 15:19 ` A.s. Dong
(?)
@ 2018-11-11 22:38 ` Rob Herring
-1 siblings, 0 replies; 36+ messages in thread
From: Rob Herring @ 2018-11-11 22:38 UTC (permalink / raw)
Cc: A.s. Dong, devicetree, sboyd, mturquette, dl-linux-imx, kernel,
Fabio Estevam, shawnguo, linux-clk, linux-arm-kernel
On Sat, 10 Nov 2018 15:19:53 +0000, "A.s. Dong" wrote:
> Add IMX8QXP SCU clock IDs.
>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Stephen Boyd <sboyd@kernel.org>
> Cc: Shawn Guo <shawnguo@kernel.org>
> Cc: Sascha Hauer <kernel@pengutronix.de>
> Cc: devicetree@vger.kernel.org
> Cc: linux-clk@vger.kernel.org
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
> v6: new patch, separate from driver changes to avoid a checkpatch warning
> IDs are changed a lot due to SCU divider/gate/mux are merged into
> one general SCU clock and LPCG clocks are moved out.
> ---
> include/dt-bindings/clock/imx8qxp-clock.h | 136 ++++++++++++++++++++++++++++++
> 1 file changed, 136 insertions(+)
> create mode 100644 include/dt-bindings/clock/imx8qxp-clock.h
>
Reviewed-by: Rob Herring <robh@kernel.org>
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH V6 2/6] dt-bindings: clock: imx8qxp: add SCU clock IDs
@ 2018-11-11 22:38 ` Rob Herring
0 siblings, 0 replies; 36+ messages in thread
From: Rob Herring @ 2018-11-11 22:38 UTC (permalink / raw)
To: A.s. Dong
Cc: linux-clk, linux-arm-kernel, sboyd, mturquette, shawnguo,
Fabio Estevam, dl-linux-imx, kernel, A.s. Dong, devicetree
On Sat, 10 Nov 2018 15:19:53 +0000, "A.s. Dong" wrote:
> Add IMX8QXP SCU clock IDs.
>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Stephen Boyd <sboyd@kernel.org>
> Cc: Shawn Guo <shawnguo@kernel.org>
> Cc: Sascha Hauer <kernel@pengutronix.de>
> Cc: devicetree@vger.kernel.org
> Cc: linux-clk@vger.kernel.org
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
> v6: new patch, separate from driver changes to avoid a checkpatch warning
> IDs are changed a lot due to SCU divider/gate/mux are merged into
> one general SCU clock and LPCG clocks are moved out.
> ---
> include/dt-bindings/clock/imx8qxp-clock.h | 136 ++++++++++++++++++++++++++++++
> 1 file changed, 136 insertions(+)
> create mode 100644 include/dt-bindings/clock/imx8qxp-clock.h
>
Reviewed-by: Rob Herring <robh@kernel.org>
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH V6 2/6] dt-bindings: clock: imx8qxp: add SCU clock IDs
@ 2018-11-11 22:38 ` Rob Herring
0 siblings, 0 replies; 36+ messages in thread
From: Rob Herring @ 2018-11-11 22:38 UTC (permalink / raw)
To: linux-arm-kernel
On Sat, 10 Nov 2018 15:19:53 +0000, "A.s. Dong" wrote:
> Add IMX8QXP SCU clock IDs.
>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Stephen Boyd <sboyd@kernel.org>
> Cc: Shawn Guo <shawnguo@kernel.org>
> Cc: Sascha Hauer <kernel@pengutronix.de>
> Cc: devicetree at vger.kernel.org
> Cc: linux-clk at vger.kernel.org
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
> v6: new patch, separate from driver changes to avoid a checkpatch warning
> IDs are changed a lot due to SCU divider/gate/mux are merged into
> one general SCU clock and LPCG clocks are moved out.
> ---
> include/dt-bindings/clock/imx8qxp-clock.h | 136 ++++++++++++++++++++++++++++++
> 1 file changed, 136 insertions(+)
> create mode 100644 include/dt-bindings/clock/imx8qxp-clock.h
>
Reviewed-by: Rob Herring <robh@kernel.org>
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH V6 4/6] dt-bindings: clock: add imx8qxp lpcg clock binding
2018-11-10 15:20 ` A.s. Dong
(?)
@ 2018-11-11 22:40 ` Rob Herring
-1 siblings, 0 replies; 36+ messages in thread
From: Rob Herring @ 2018-11-11 22:40 UTC (permalink / raw)
Cc: A.s. Dong, devicetree, sboyd, mturquette, dl-linux-imx, kernel,
Fabio Estevam, shawnguo, linux-clk, linux-arm-kernel
On Sat, 10 Nov 2018 15:20:01 +0000, "A.s. Dong" wrote:
> The Low-Power Clock Gate (LPCG) modules contain a local programming
> model to control the clock gates for the peripherals. An LPCG module
> is used to locally gate the clocks for the associated peripheral.
>
> Note:
> This level of clock gating is provided after the clocks are generated
> by the SCU resources and clock controls. Thus even if the clock is
> enabled by these control bits, it might still not be running based
> on the base resource.
>
> Cc: Stephen Boyd <sboyd@kernel.org>
> Cc: Shawn Guo <shawnguo@kernel.org>
> Cc: Sascha Hauer <kernel@pengutronix.de>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
> .../devicetree/bindings/clock/imx8qxp-lpcg.txt | 51 +++++++
> include/dt-bindings/clock/imx8qxp-clock.h | 153 +++++++++++++++++++++
> 2 files changed, 204 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt
>
Reviewed-by: Rob Herring <robh@kernel.org>
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH V6 4/6] dt-bindings: clock: add imx8qxp lpcg clock binding
@ 2018-11-11 22:40 ` Rob Herring
0 siblings, 0 replies; 36+ messages in thread
From: Rob Herring @ 2018-11-11 22:40 UTC (permalink / raw)
To: A.s. Dong
Cc: linux-clk, linux-arm-kernel, sboyd, mturquette, shawnguo,
Fabio Estevam, dl-linux-imx, kernel, A.s. Dong, devicetree
On Sat, 10 Nov 2018 15:20:01 +0000, "A.s. Dong" wrote:
> The Low-Power Clock Gate (LPCG) modules contain a local programming
> model to control the clock gates for the peripherals. An LPCG module
> is used to locally gate the clocks for the associated peripheral.
>
> Note:
> This level of clock gating is provided after the clocks are generated
> by the SCU resources and clock controls. Thus even if the clock is
> enabled by these control bits, it might still not be running based
> on the base resource.
>
> Cc: Stephen Boyd <sboyd@kernel.org>
> Cc: Shawn Guo <shawnguo@kernel.org>
> Cc: Sascha Hauer <kernel@pengutronix.de>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
> .../devicetree/bindings/clock/imx8qxp-lpcg.txt | 51 +++++++
> include/dt-bindings/clock/imx8qxp-clock.h | 153 +++++++++++++++++++++
> 2 files changed, 204 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt
>
Reviewed-by: Rob Herring <robh@kernel.org>
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH V6 4/6] dt-bindings: clock: add imx8qxp lpcg clock binding
@ 2018-11-11 22:40 ` Rob Herring
0 siblings, 0 replies; 36+ messages in thread
From: Rob Herring @ 2018-11-11 22:40 UTC (permalink / raw)
To: linux-arm-kernel
On Sat, 10 Nov 2018 15:20:01 +0000, "A.s. Dong" wrote:
> The Low-Power Clock Gate (LPCG) modules contain a local programming
> model to control the clock gates for the peripherals. An LPCG module
> is used to locally gate the clocks for the associated peripheral.
>
> Note:
> This level of clock gating is provided after the clocks are generated
> by the SCU resources and clock controls. Thus even if the clock is
> enabled by these control bits, it might still not be running based
> on the base resource.
>
> Cc: Stephen Boyd <sboyd@kernel.org>
> Cc: Shawn Guo <shawnguo@kernel.org>
> Cc: Sascha Hauer <kernel@pengutronix.de>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: devicetree at vger.kernel.org
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
> ---
> .../devicetree/bindings/clock/imx8qxp-lpcg.txt | 51 +++++++
> include/dt-bindings/clock/imx8qxp-clock.h | 153 +++++++++++++++++++++
> 2 files changed, 204 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/clock/imx8qxp-lpcg.txt
>
Reviewed-by: Rob Herring <robh@kernel.org>
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH V6 6/6] clk: imx: add imx8qxp lpcg driver
2018-11-10 15:20 ` A.s. Dong
@ 2018-11-14 23:28 ` Stephen Boyd
-1 siblings, 0 replies; 36+ messages in thread
From: Stephen Boyd @ 2018-11-14 23:28 UTC (permalink / raw)
To: A.s. Dong, linux-clk
Cc: linux-arm-kernel, mturquette, shawnguo, Fabio Estevam,
dl-linux-imx, kernel, A.s. Dong
Quoting A.s. Dong (2018-11-10 07:20:08)
> Add imx8qxp lpcg driver support
>
> Cc: Stephen Boyd <sboyd@kernel.org>
> Cc: Shawn Guo <shawnguo@kernel.org>
> Cc: Sascha Hauer <kernel@pengutronix.de>
> Cc: Fabio Estevam <fabio.estevam@nxp.com>
> Cc: Michael Turquette <mturquette@baylibre.com>
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
I like it!
> diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c
> new file mode 100644
> index 0000000..7b318d7
> --- /dev/null
> +++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c
> @@ -0,0 +1,198 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright 2018 NXP
> + * Dong Aisheng <aisheng.dong@nxp.com>
> + */
> +
> +#include <dt-bindings/clock/imx8qxp-clock.h>
Include this after <linux/*> and before locals please.
> +#include <linux/clk-provider.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +
> +#include "clk-scu.h"
> +#include "clk-imx8qxp-lpcg.h"
> +
> +struct imx8qxp_lpcg_data {
> + int id;
> + char *name;
> + char *parent;
> + unsigned long flags;
> + u32 offset;
> + u8 bit_idx;
> + bool hw_gate;
> +};
> +
> +struct imx8qxp_ss_lpcg {
> + const struct imx8qxp_lpcg_data *lpcg;
> + u8 num_lpcg;
> + u8 num_max;
> +};
Any chance we can get kernel-doc on these structs and members of the
structs?
> +
> +static const struct imx8qxp_lpcg_data imx8qxp_lpcg_adma[] = {
> + { IMX8QXP_ADMA_LPCG_UART0_IPG_CLK, "uart0_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPUART_0_LPCG, 16, 0, },
> + { IMX8QXP_ADMA_LPCG_UART0_BAUD_CLK, "uart0_lpcg_baud_clk", "uart0_clk", 0, ADMA_LPUART_0_LPCG, 0, 0, },
> + { IMX8QXP_ADMA_LPCG_UART1_IPG_CLK, "uart1_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPUART_1_LPCG, 16, 0, },
> + { IMX8QXP_ADMA_LPCG_UART1_BAUD_CLK, "uart1_lpcg_baud_clk", "uart1_clk", 0, ADMA_LPUART_1_LPCG, 0, 0, },
[...]
> +
> +static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device_node *np = dev->of_node;
> + struct clk_hw_onecell_data *clk_data;
> + const struct imx8qxp_ss_lpcg *ss_lpcg;
> + const struct imx8qxp_lpcg_data *lpcg;
> + struct resource *res;
> + struct clk_hw **clks;
> + void __iomem *base;
> + int i;
That's a good amount of local variables!
> +
> + ss_lpcg = of_device_get_match_data(dev);
> + if (!ss_lpcg)
> + return -ENODEV;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + base = devm_ioremap(dev, res->start, resource_size(res));
Why not devm_ioremap_resource()?
> + if (!base)
> + return -ENOMEM;
And then return the error code out of it?
> +
> + clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data) +
> + sizeof(*clk_data->hws) * ss_lpcg->num_max,
Can you use struct_size() here?
> + GFP_KERNEL);
> + if (!clk_data)
> + return -ENOMEM;
> +
> + clk_data->num = ss_lpcg->num_max;
> + clks = clk_data->hws;
> +
> + for (i = 0; i < ss_lpcg->num_lpcg; i++) {
> + lpcg = ss_lpcg->lpcg + i;
> + clks[lpcg->id] = imx_clk_lpcg_scu(lpcg->name, lpcg->parent,
> + lpcg->flags, base + lpcg->offset,
> + lpcg->bit_idx, lpcg->hw_gate);
> + }
> +
> + for (i = 0; i < clk_data->num; i++) {
> + if (IS_ERR(clks[i]))
> + pr_err("i.MX clk %u: register failed with %ld\n",
> + i, PTR_ERR(clks[i]));
But we're OK to continue? Alright...
> + }
> +
> + return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
Why not use devm_? Or can the driver never be unbound from sysfs?
> +}
> +
> +static const struct of_device_id imx8qxp_lpcg_match[] = {
> + { .compatible = "fsl,imx8qxp-lpcg-adma", &imx8qxp_ss_adma, },
> + { .compatible = "fsl,imx8qxp-lpcg-conn", &imx8qxp_ss_conn, },
> + { .compatible = "fsl,imx8qxp-lpcg-lsio", &imx8qxp_ss_lsio, },
> + { /* sentinel */ }
> +};
> +
> +static struct platform_driver imx8qxp_lpcg_clk_driver = {
> + .driver = {
> + .name = "imx8qxp-lpcg-clk",
> + .of_match_table = imx8qxp_lpcg_match,
> + },
> + .probe = imx8qxp_lpcg_clk_probe,
> +};
> +
> +builtin_platform_driver(imx8qxp_lpcg_clk_driver);
> +
> +MODULE_AUTHOR("Dong Aisheng <aisheng.dong@nxp.com>");
> +MODULE_DESCRIPTION("IMX8QXP LPCG Clock driver");
> +MODULE_LICENSE("GPL v2");
If the module is builtin all the time because of
builtin_platform_driver() I think we don't need these MODULE_ macros.
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH V6 6/6] clk: imx: add imx8qxp lpcg driver
@ 2018-11-14 23:28 ` Stephen Boyd
0 siblings, 0 replies; 36+ messages in thread
From: Stephen Boyd @ 2018-11-14 23:28 UTC (permalink / raw)
To: linux-arm-kernel
Quoting A.s. Dong (2018-11-10 07:20:08)
> Add imx8qxp lpcg driver support
>
> Cc: Stephen Boyd <sboyd@kernel.org>
> Cc: Shawn Guo <shawnguo@kernel.org>
> Cc: Sascha Hauer <kernel@pengutronix.de>
> Cc: Fabio Estevam <fabio.estevam@nxp.com>
> Cc: Michael Turquette <mturquette@baylibre.com>
> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
I like it!
> diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c
> new file mode 100644
> index 0000000..7b318d7
> --- /dev/null
> +++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c
> @@ -0,0 +1,198 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright 2018 NXP
> + * Dong Aisheng <aisheng.dong@nxp.com>
> + */
> +
> +#include <dt-bindings/clock/imx8qxp-clock.h>
Include this after <linux/*> and before locals please.
> +#include <linux/clk-provider.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +
> +#include "clk-scu.h"
> +#include "clk-imx8qxp-lpcg.h"
> +
> +struct imx8qxp_lpcg_data {
> + int id;
> + char *name;
> + char *parent;
> + unsigned long flags;
> + u32 offset;
> + u8 bit_idx;
> + bool hw_gate;
> +};
> +
> +struct imx8qxp_ss_lpcg {
> + const struct imx8qxp_lpcg_data *lpcg;
> + u8 num_lpcg;
> + u8 num_max;
> +};
Any chance we can get kernel-doc on these structs and members of the
structs?
> +
> +static const struct imx8qxp_lpcg_data imx8qxp_lpcg_adma[] = {
> + { IMX8QXP_ADMA_LPCG_UART0_IPG_CLK, "uart0_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPUART_0_LPCG, 16, 0, },
> + { IMX8QXP_ADMA_LPCG_UART0_BAUD_CLK, "uart0_lpcg_baud_clk", "uart0_clk", 0, ADMA_LPUART_0_LPCG, 0, 0, },
> + { IMX8QXP_ADMA_LPCG_UART1_IPG_CLK, "uart1_lpcg_ipg_clk", "dma_ipg_clk_root", 0, ADMA_LPUART_1_LPCG, 16, 0, },
> + { IMX8QXP_ADMA_LPCG_UART1_BAUD_CLK, "uart1_lpcg_baud_clk", "uart1_clk", 0, ADMA_LPUART_1_LPCG, 0, 0, },
[...]
> +
> +static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device_node *np = dev->of_node;
> + struct clk_hw_onecell_data *clk_data;
> + const struct imx8qxp_ss_lpcg *ss_lpcg;
> + const struct imx8qxp_lpcg_data *lpcg;
> + struct resource *res;
> + struct clk_hw **clks;
> + void __iomem *base;
> + int i;
That's a good amount of local variables!
> +
> + ss_lpcg = of_device_get_match_data(dev);
> + if (!ss_lpcg)
> + return -ENODEV;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + base = devm_ioremap(dev, res->start, resource_size(res));
Why not devm_ioremap_resource()?
> + if (!base)
> + return -ENOMEM;
And then return the error code out of it?
> +
> + clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data) +
> + sizeof(*clk_data->hws) * ss_lpcg->num_max,
Can you use struct_size() here?
> + GFP_KERNEL);
> + if (!clk_data)
> + return -ENOMEM;
> +
> + clk_data->num = ss_lpcg->num_max;
> + clks = clk_data->hws;
> +
> + for (i = 0; i < ss_lpcg->num_lpcg; i++) {
> + lpcg = ss_lpcg->lpcg + i;
> + clks[lpcg->id] = imx_clk_lpcg_scu(lpcg->name, lpcg->parent,
> + lpcg->flags, base + lpcg->offset,
> + lpcg->bit_idx, lpcg->hw_gate);
> + }
> +
> + for (i = 0; i < clk_data->num; i++) {
> + if (IS_ERR(clks[i]))
> + pr_err("i.MX clk %u: register failed with %ld\n",
> + i, PTR_ERR(clks[i]));
But we're OK to continue? Alright...
> + }
> +
> + return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
Why not use devm_? Or can the driver never be unbound from sysfs?
> +}
> +
> +static const struct of_device_id imx8qxp_lpcg_match[] = {
> + { .compatible = "fsl,imx8qxp-lpcg-adma", &imx8qxp_ss_adma, },
> + { .compatible = "fsl,imx8qxp-lpcg-conn", &imx8qxp_ss_conn, },
> + { .compatible = "fsl,imx8qxp-lpcg-lsio", &imx8qxp_ss_lsio, },
> + { /* sentinel */ }
> +};
> +
> +static struct platform_driver imx8qxp_lpcg_clk_driver = {
> + .driver = {
> + .name = "imx8qxp-lpcg-clk",
> + .of_match_table = imx8qxp_lpcg_match,
> + },
> + .probe = imx8qxp_lpcg_clk_probe,
> +};
> +
> +builtin_platform_driver(imx8qxp_lpcg_clk_driver);
> +
> +MODULE_AUTHOR("Dong Aisheng <aisheng.dong@nxp.com>");
> +MODULE_DESCRIPTION("IMX8QXP LPCG Clock driver");
> +MODULE_LICENSE("GPL v2");
If the module is builtin all the time because of
builtin_platform_driver() I think we don't need these MODULE_ macros.
^ permalink raw reply [flat|nested] 36+ messages in thread
* RE: [PATCH V6 6/6] clk: imx: add imx8qxp lpcg driver
2018-11-14 23:28 ` Stephen Boyd
@ 2018-11-15 1:28 ` A.s. Dong
-1 siblings, 0 replies; 36+ messages in thread
From: A.s. Dong @ 2018-11-15 1:28 UTC (permalink / raw)
To: Stephen Boyd, linux-clk
Cc: linux-arm-kernel, mturquette, shawnguo, Fabio Estevam,
dl-linux-imx, kernel
Hi Stephen,
Thanks for the quick review! :)
> -----Original Message-----
> From: Stephen Boyd [mailto:sboyd@kernel.org]
> Sent: Thursday, November 15, 2018 7:29 AM
[...]
>
> Quoting A.s. Dong (2018-11-10 07:20:08)
> > Add imx8qxp lpcg driver support
> >
> > Cc: Stephen Boyd <sboyd@kernel.org>
> > Cc: Shawn Guo <shawnguo@kernel.org>
> > Cc: Sascha Hauer <kernel@pengutronix.de>
> > Cc: Fabio Estevam <fabio.estevam@nxp.com>
> > Cc: Michael Turquette <mturquette@baylibre.com>
> > Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>
> I like it!
>
Great to know that.
> > diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c
> > b/drivers/clk/imx/clk-imx8qxp-lpcg.c
> > new file mode 100644
> > index 0000000..7b318d7
> > --- /dev/null
> > +++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c
> > @@ -0,0 +1,198 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright 2018 NXP
> > + * Dong Aisheng <aisheng.dong@nxp.com>
> > + */
> > +
> > +#include <dt-bindings/clock/imx8qxp-clock.h>
>
> Include this after <linux/*> and before locals please.
>
Got it.
> > +#include <linux/clk-provider.h>
> > +#include <linux/err.h>
> > +#include <linux/io.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/of_device.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/slab.h>
> > +
> > +#include "clk-scu.h"
> > +#include "clk-imx8qxp-lpcg.h"
> > +
> > +struct imx8qxp_lpcg_data {
> > + int id;
> > + char *name;
> > + char *parent;
> > + unsigned long flags;
> > + u32 offset;
> > + u8 bit_idx;
> > + bool hw_gate;
> > +};
> > +
> > +struct imx8qxp_ss_lpcg {
> > + const struct imx8qxp_lpcg_data *lpcg;
> > + u8 num_lpcg;
> > + u8 num_max;
> > +};
>
> Any chance we can get kernel-doc on these structs and members of the
> structs?
>
I can add it.
> > +
> > +static const struct imx8qxp_lpcg_data imx8qxp_lpcg_adma[] = {
> > + { IMX8QXP_ADMA_LPCG_UART0_IPG_CLK, "uart0_lpcg_ipg_clk",
> "dma_ipg_clk_root", 0, ADMA_LPUART_0_LPCG, 16, 0, },
> > + { IMX8QXP_ADMA_LPCG_UART0_BAUD_CLK,
> "uart0_lpcg_baud_clk", "uart0_clk", 0, ADMA_LPUART_0_LPCG, 0, 0, },
> > + { IMX8QXP_ADMA_LPCG_UART1_IPG_CLK, "uart1_lpcg_ipg_clk",
> "dma_ipg_clk_root", 0, ADMA_LPUART_1_LPCG, 16, 0, },
> > + { IMX8QXP_ADMA_LPCG_UART1_BAUD_CLK,
> "uart1_lpcg_baud_clk",
> > +"uart1_clk", 0, ADMA_LPUART_1_LPCG, 0, 0, },
> [...]
> > +
> > +static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev) {
> > + struct device *dev = &pdev->dev;
> > + struct device_node *np = dev->of_node;
> > + struct clk_hw_onecell_data *clk_data;
> > + const struct imx8qxp_ss_lpcg *ss_lpcg;
> > + const struct imx8qxp_lpcg_data *lpcg;
> > + struct resource *res;
> > + struct clk_hw **clks;
> > + void __iomem *base;
> > + int i;
>
> That's a good amount of local variables!
Yes, seems we need them.
Please let me know if you have a better idea.
>
> > +
> > + ss_lpcg = of_device_get_match_data(dev);
> > + if (!ss_lpcg)
> > + return -ENODEV;
> > +
> > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > + base = devm_ioremap(dev, res->start, resource_size(res));
>
> Why not devm_ioremap_resource()?
Because LPCGs are distributed in various subsystem memory space which
may be overlapped with some IP modules. So we can't use devm_ioremap_resource
which has a request_mem_region() in it.
It's something like what we've done for drivers/mfd/syscon.c.
>
> > + if (!base)
> > + return -ENOMEM;
>
> And then return the error code out of it?
>
See above.
> > +
> > + clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data) +
> > + sizeof(*clk_data->hws) *
> > + ss_lpcg->num_max,
>
> Can you use struct_size() here?
>
Got it, thanks for pointing to this new api.
> > + GFP_KERNEL);
> > + if (!clk_data)
> > + return -ENOMEM;
> > +
> > + clk_data->num = ss_lpcg->num_max;
> > + clks = clk_data->hws;
> > +
> > + for (i = 0; i < ss_lpcg->num_lpcg; i++) {
> > + lpcg = ss_lpcg->lpcg + i;
> > + clks[lpcg->id] = imx_clk_lpcg_scu(lpcg->name,
> lpcg->parent,
> > + lpcg->flags, base +
> lpcg->offset,
> > + lpcg->bit_idx,
> lpcg->hw_gate);
> > + }
> > +
> > + for (i = 0; i < clk_data->num; i++) {
> > + if (IS_ERR(clks[i]))
> > + pr_err("i.MX clk %u: register failed with %ld\n",
> > + i, PTR_ERR(clks[i]));
>
> But we're OK to continue? Alright...
>
Yes, probably better to use pr_warn()?
> > + }
> > +
> > + return of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
> > + clk_data);
>
> Why not use devm_? Or can the driver never be unbound from sysfs?
>
We expect the driver to be never unbound from sysfs.
Probably we'd better add .suppress_bind_attrs.
> > +}
> > +
> > +static const struct of_device_id imx8qxp_lpcg_match[] = {
> > + { .compatible = "fsl,imx8qxp-lpcg-adma", &imx8qxp_ss_adma, },
> > + { .compatible = "fsl,imx8qxp-lpcg-conn", &imx8qxp_ss_conn, },
> > + { .compatible = "fsl,imx8qxp-lpcg-lsio", &imx8qxp_ss_lsio, },
> > + { /* sentinel */ }
> > +};
> > +
> > +static struct platform_driver imx8qxp_lpcg_clk_driver = {
> > + .driver = {
> > + .name = "imx8qxp-lpcg-clk",
> > + .of_match_table = imx8qxp_lpcg_match,
> > + },
> > + .probe = imx8qxp_lpcg_clk_probe, };
> > +
> > +builtin_platform_driver(imx8qxp_lpcg_clk_driver);
> > +
> > +MODULE_AUTHOR("Dong Aisheng <aisheng.dong@nxp.com>");
> > +MODULE_DESCRIPTION("IMX8QXP LPCG Clock driver");
> MODULE_LICENSE("GPL
> > +v2");
>
> If the module is builtin all the time because of
> builtin_platform_driver() I think we don't need these MODULE_ macros.
Okay, I can remove them.
Regards
Dong Aisheng
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH V6 6/6] clk: imx: add imx8qxp lpcg driver
@ 2018-11-15 1:28 ` A.s. Dong
0 siblings, 0 replies; 36+ messages in thread
From: A.s. Dong @ 2018-11-15 1:28 UTC (permalink / raw)
To: linux-arm-kernel
Hi Stephen,
Thanks for the quick review! :)
> -----Original Message-----
> From: Stephen Boyd [mailto:sboyd at kernel.org]
> Sent: Thursday, November 15, 2018 7:29 AM
[...]
>
> Quoting A.s. Dong (2018-11-10 07:20:08)
> > Add imx8qxp lpcg driver support
> >
> > Cc: Stephen Boyd <sboyd@kernel.org>
> > Cc: Shawn Guo <shawnguo@kernel.org>
> > Cc: Sascha Hauer <kernel@pengutronix.de>
> > Cc: Fabio Estevam <fabio.estevam@nxp.com>
> > Cc: Michael Turquette <mturquette@baylibre.com>
> > Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
>
> I like it!
>
Great to know that.
> > diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c
> > b/drivers/clk/imx/clk-imx8qxp-lpcg.c
> > new file mode 100644
> > index 0000000..7b318d7
> > --- /dev/null
> > +++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c
> > @@ -0,0 +1,198 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright 2018 NXP
> > + * Dong Aisheng <aisheng.dong@nxp.com>
> > + */
> > +
> > +#include <dt-bindings/clock/imx8qxp-clock.h>
>
> Include this after <linux/*> and before locals please.
>
Got it.
> > +#include <linux/clk-provider.h>
> > +#include <linux/err.h>
> > +#include <linux/io.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/of_device.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/slab.h>
> > +
> > +#include "clk-scu.h"
> > +#include "clk-imx8qxp-lpcg.h"
> > +
> > +struct imx8qxp_lpcg_data {
> > + int id;
> > + char *name;
> > + char *parent;
> > + unsigned long flags;
> > + u32 offset;
> > + u8 bit_idx;
> > + bool hw_gate;
> > +};
> > +
> > +struct imx8qxp_ss_lpcg {
> > + const struct imx8qxp_lpcg_data *lpcg;
> > + u8 num_lpcg;
> > + u8 num_max;
> > +};
>
> Any chance we can get kernel-doc on these structs and members of the
> structs?
>
I can add it.
> > +
> > +static const struct imx8qxp_lpcg_data imx8qxp_lpcg_adma[] = {
> > + { IMX8QXP_ADMA_LPCG_UART0_IPG_CLK, "uart0_lpcg_ipg_clk",
> "dma_ipg_clk_root", 0, ADMA_LPUART_0_LPCG, 16, 0, },
> > + { IMX8QXP_ADMA_LPCG_UART0_BAUD_CLK,
> "uart0_lpcg_baud_clk", "uart0_clk", 0, ADMA_LPUART_0_LPCG, 0, 0, },
> > + { IMX8QXP_ADMA_LPCG_UART1_IPG_CLK, "uart1_lpcg_ipg_clk",
> "dma_ipg_clk_root", 0, ADMA_LPUART_1_LPCG, 16, 0, },
> > + { IMX8QXP_ADMA_LPCG_UART1_BAUD_CLK,
> "uart1_lpcg_baud_clk",
> > +"uart1_clk", 0, ADMA_LPUART_1_LPCG, 0, 0, },
> [...]
> > +
> > +static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev) {
> > + struct device *dev = &pdev->dev;
> > + struct device_node *np = dev->of_node;
> > + struct clk_hw_onecell_data *clk_data;
> > + const struct imx8qxp_ss_lpcg *ss_lpcg;
> > + const struct imx8qxp_lpcg_data *lpcg;
> > + struct resource *res;
> > + struct clk_hw **clks;
> > + void __iomem *base;
> > + int i;
>
> That's a good amount of local variables!
Yes, seems we need them.
Please let me know if you have a better idea.
>
> > +
> > + ss_lpcg = of_device_get_match_data(dev);
> > + if (!ss_lpcg)
> > + return -ENODEV;
> > +
> > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > + base = devm_ioremap(dev, res->start, resource_size(res));
>
> Why not devm_ioremap_resource()?
Because LPCGs are distributed in various subsystem memory space which
may be overlapped with some IP modules. So we can't use devm_ioremap_resource
which has a request_mem_region() in it.
It's something like what we've done for drivers/mfd/syscon.c.
>
> > + if (!base)
> > + return -ENOMEM;
>
> And then return the error code out of it?
>
See above.
> > +
> > + clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data) +
> > + sizeof(*clk_data->hws) *
> > + ss_lpcg->num_max,
>
> Can you use struct_size() here?
>
Got it, thanks for pointing to this new api.
> > + GFP_KERNEL);
> > + if (!clk_data)
> > + return -ENOMEM;
> > +
> > + clk_data->num = ss_lpcg->num_max;
> > + clks = clk_data->hws;
> > +
> > + for (i = 0; i < ss_lpcg->num_lpcg; i++) {
> > + lpcg = ss_lpcg->lpcg + i;
> > + clks[lpcg->id] = imx_clk_lpcg_scu(lpcg->name,
> lpcg->parent,
> > + lpcg->flags, base +
> lpcg->offset,
> > + lpcg->bit_idx,
> lpcg->hw_gate);
> > + }
> > +
> > + for (i = 0; i < clk_data->num; i++) {
> > + if (IS_ERR(clks[i]))
> > + pr_err("i.MX clk %u: register failed with %ld\n",
> > + i, PTR_ERR(clks[i]));
>
> But we're OK to continue? Alright...
>
Yes, probably better to use pr_warn()?
> > + }
> > +
> > + return of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
> > + clk_data);
>
> Why not use devm_? Or can the driver never be unbound from sysfs?
>
We expect the driver to be never unbound from sysfs.
Probably we'd better add .suppress_bind_attrs.
> > +}
> > +
> > +static const struct of_device_id imx8qxp_lpcg_match[] = {
> > + { .compatible = "fsl,imx8qxp-lpcg-adma", &imx8qxp_ss_adma, },
> > + { .compatible = "fsl,imx8qxp-lpcg-conn", &imx8qxp_ss_conn, },
> > + { .compatible = "fsl,imx8qxp-lpcg-lsio", &imx8qxp_ss_lsio, },
> > + { /* sentinel */ }
> > +};
> > +
> > +static struct platform_driver imx8qxp_lpcg_clk_driver = {
> > + .driver = {
> > + .name = "imx8qxp-lpcg-clk",
> > + .of_match_table = imx8qxp_lpcg_match,
> > + },
> > + .probe = imx8qxp_lpcg_clk_probe, };
> > +
> > +builtin_platform_driver(imx8qxp_lpcg_clk_driver);
> > +
> > +MODULE_AUTHOR("Dong Aisheng <aisheng.dong@nxp.com>");
> > +MODULE_DESCRIPTION("IMX8QXP LPCG Clock driver");
> MODULE_LICENSE("GPL
> > +v2");
>
> If the module is builtin all the time because of
> builtin_platform_driver() I think we don't need these MODULE_ macros.
Okay, I can remove them.
Regards
Dong Aisheng
^ permalink raw reply [flat|nested] 36+ messages in thread
* RE: [PATCH V6 6/6] clk: imx: add imx8qxp lpcg driver
2018-11-15 1:28 ` A.s. Dong
@ 2018-11-20 18:55 ` Stephen Boyd
-1 siblings, 0 replies; 36+ messages in thread
From: Stephen Boyd @ 2018-11-20 18:55 UTC (permalink / raw)
To: A.s. Dong, linux-clk
Cc: linux-arm-kernel, mturquette, shawnguo, Fabio Estevam,
dl-linux-imx, kernel
Quoting A.s. Dong (2018-11-14 17:28:05)
> > -----Original Message-----
> > From: Stephen Boyd [mailto:sboyd@kernel.org]
>
> >
> > > +
> > > + ss_lpcg = of_device_get_match_data(dev);
> > > + if (!ss_lpcg)
> > > + return -ENODEV;
> > > +
> > > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > + base = devm_ioremap(dev, res->start, resource_size(res));
> >
> > Why not devm_ioremap_resource()?
>
> Because LPCGs are distributed in various subsystem memory space which
> may be overlapped with some IP modules. So we can't use devm_ioremap_resource
> which has a request_mem_region() in it.
> It's something like what we've done for drivers/mfd/syscon.c.
Ok. Any chance that the various subsystems that are combined with the
clk controller can be split up so that we can use
devm_ioremap_resource() here? It may be better to carve up the I/O space
of this SoC into device nodes that map to the hardware IP blocks, and
then have those device drivers generate sub-devices for the various
logical subsystems that the hardware IP spans. Or it could be a big
driver that registers with multiple subsytems/frameworks from one device
driver. This way, the logical structure of the linux kernel device
driver design doesn't leak into the DT description of the SoC.
>
> > > + GFP_KERNEL);
> > > + if (!clk_data)
> > > + return -ENOMEM;
> > > +
> > > + clk_data->num = ss_lpcg->num_max;
> > > + clks = clk_data->hws;
> > > +
> > > + for (i = 0; i < ss_lpcg->num_lpcg; i++) {
> > > + lpcg = ss_lpcg->lpcg + i;
> > > + clks[lpcg->id] = imx_clk_lpcg_scu(lpcg->name,
> > lpcg->parent,
> > > + lpcg->flags, base +
> > lpcg->offset,
> > > + lpcg->bit_idx,
> > lpcg->hw_gate);
> > > + }
> > > +
> > > + for (i = 0; i < clk_data->num; i++) {
> > > + if (IS_ERR(clks[i]))
> > > + pr_err("i.MX clk %u: register failed with %ld\n",
> > > + i, PTR_ERR(clks[i]));
> >
> > But we're OK to continue? Alright...
> >
>
> Yes, probably better to use pr_warn()?
Yes.
>
> > > + }
> > > +
> > > + return of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
> > > + clk_data);
> >
> > Why not use devm_? Or can the driver never be unbound from sysfs?
> >
>
> We expect the driver to be never unbound from sysfs.
> Probably we'd better add .suppress_bind_attrs.
Ok. Please add it.
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH V6 6/6] clk: imx: add imx8qxp lpcg driver
@ 2018-11-20 18:55 ` Stephen Boyd
0 siblings, 0 replies; 36+ messages in thread
From: Stephen Boyd @ 2018-11-20 18:55 UTC (permalink / raw)
To: linux-arm-kernel
Quoting A.s. Dong (2018-11-14 17:28:05)
> > -----Original Message-----
> > From: Stephen Boyd [mailto:sboyd at kernel.org]
>
> >
> > > +
> > > + ss_lpcg = of_device_get_match_data(dev);
> > > + if (!ss_lpcg)
> > > + return -ENODEV;
> > > +
> > > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > + base = devm_ioremap(dev, res->start, resource_size(res));
> >
> > Why not devm_ioremap_resource()?
>
> Because LPCGs are distributed in various subsystem memory space which
> may be overlapped with some IP modules. So we can't use devm_ioremap_resource
> which has a request_mem_region() in it.
> It's something like what we've done for drivers/mfd/syscon.c.
Ok. Any chance that the various subsystems that are combined with the
clk controller can be split up so that we can use
devm_ioremap_resource() here? It may be better to carve up the I/O space
of this SoC into device nodes that map to the hardware IP blocks, and
then have those device drivers generate sub-devices for the various
logical subsystems that the hardware IP spans. Or it could be a big
driver that registers with multiple subsytems/frameworks from one device
driver. This way, the logical structure of the linux kernel device
driver design doesn't leak into the DT description of the SoC.
>
> > > + GFP_KERNEL);
> > > + if (!clk_data)
> > > + return -ENOMEM;
> > > +
> > > + clk_data->num = ss_lpcg->num_max;
> > > + clks = clk_data->hws;
> > > +
> > > + for (i = 0; i < ss_lpcg->num_lpcg; i++) {
> > > + lpcg = ss_lpcg->lpcg + i;
> > > + clks[lpcg->id] = imx_clk_lpcg_scu(lpcg->name,
> > lpcg->parent,
> > > + lpcg->flags, base +
> > lpcg->offset,
> > > + lpcg->bit_idx,
> > lpcg->hw_gate);
> > > + }
> > > +
> > > + for (i = 0; i < clk_data->num; i++) {
> > > + if (IS_ERR(clks[i]))
> > > + pr_err("i.MX clk %u: register failed with %ld\n",
> > > + i, PTR_ERR(clks[i]));
> >
> > But we're OK to continue? Alright...
> >
>
> Yes, probably better to use pr_warn()?
Yes.
>
> > > + }
> > > +
> > > + return of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
> > > + clk_data);
> >
> > Why not use devm_? Or can the driver never be unbound from sysfs?
> >
>
> We expect the driver to be never unbound from sysfs.
> Probably we'd better add .suppress_bind_attrs.
Ok. Please add it.
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH V6 5/6] clk: imx: add lpcg clock support
2018-11-10 15:20 ` A.s. Dong
@ 2018-11-20 20:14 ` Stephen Boyd
-1 siblings, 0 replies; 36+ messages in thread
From: Stephen Boyd @ 2018-11-20 20:14 UTC (permalink / raw)
To: A.s. Dong, linux-clk
Cc: linux-arm-kernel, mturquette, shawnguo, Fabio Estevam,
dl-linux-imx, kernel, A.s. Dong
Quoting A.s. Dong (2018-11-10 07:20:04)
> diff --git a/drivers/clk/imx/clk-lpcg-scu.c b/drivers/clk/imx/clk-lpcg-scu.c
> new file mode 100644
> index 0000000..54a1cb3
> --- /dev/null
> +++ b/drivers/clk/imx/clk-lpcg-scu.c
> @@ -0,0 +1,108 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright 2018 NXP
> + * Dong Aisheng <aisheng.dong@nxp.com>
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +
> +static DEFINE_SPINLOCK(imx_lpcg_scu_lock);
> +
> +#define CLK_GATE_SCU_LPCG_MASK 0x3
> +#define CLK_GATE_SCU_LPCG_HW_SEL BIT(0)
> +#define CLK_GATE_SCU_LPCG_SW_SEL BIT(1)
> +
> +struct clk_lpcg_scu {
> + struct clk_hw hw;
> + void __iomem *reg;
> + u8 bit_idx;
> + bool hw_gate;
What does hw_gate mean? Can you add kernel-doc to this structure?
> +};
> +
> +#define to_clk_lpcg_scu(_hw) container_of(_hw, struct clk_lpcg_scu, hw)
> +
> +/* Write to the LPCG bits. */
Please remove this useless comment.
> +static int clk_lpcg_scu_enable(struct clk_hw *hw)
> +{
> + struct clk_lpcg_scu *clk = to_clk_lpcg_scu(hw);
> + unsigned long flags = 0;
Don't initialize flags here.
> + u32 reg;
> +
> + spin_lock_irqsave(&imx_lpcg_scu_lock, flags);
> +
> + if (clk->reg) {
> + reg = readl(clk->reg);
> + reg &= ~(CLK_GATE_SCU_LPCG_MASK << clk->bit_idx);
> + if (clk->hw_gate)
> + reg |= (CLK_GATE_SCU_LPCG_HW_SEL |
> + CLK_GATE_SCU_LPCG_SW_SEL) << clk->bit_idx;
> + else
> + reg |= (CLK_GATE_SCU_LPCG_SW_SEL << clk->bit_idx);
> + writel(reg, clk->reg);
> + }
> +
> + spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags);
> +
> + return 0;
> +}
> +
> +static void clk_lpcg_scu_disable(struct clk_hw *hw)
> +{
> + struct clk_lpcg_scu *clk = to_clk_lpcg_scu(hw);
> + unsigned long flags = 0;
Same comment.
> + u32 reg;
> +
> + spin_lock_irqsave(&imx_lpcg_scu_lock, flags);
> +
> + if (clk->reg) {
Why do we even call this function if there isn't a clk->reg value?
Can't we just not assign the clk_ops in that case?
> + reg = readl(clk->reg);
> + reg &= ~(CLK_GATE_SCU_LPCG_MASK << clk->bit_idx);
> + writel(reg, clk->reg);
> + }
> +
> + spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags);
> +}
> +
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH V6 5/6] clk: imx: add lpcg clock support
@ 2018-11-20 20:14 ` Stephen Boyd
0 siblings, 0 replies; 36+ messages in thread
From: Stephen Boyd @ 2018-11-20 20:14 UTC (permalink / raw)
To: linux-arm-kernel
Quoting A.s. Dong (2018-11-10 07:20:04)
> diff --git a/drivers/clk/imx/clk-lpcg-scu.c b/drivers/clk/imx/clk-lpcg-scu.c
> new file mode 100644
> index 0000000..54a1cb3
> --- /dev/null
> +++ b/drivers/clk/imx/clk-lpcg-scu.c
> @@ -0,0 +1,108 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright 2018 NXP
> + * Dong Aisheng <aisheng.dong@nxp.com>
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +
> +static DEFINE_SPINLOCK(imx_lpcg_scu_lock);
> +
> +#define CLK_GATE_SCU_LPCG_MASK 0x3
> +#define CLK_GATE_SCU_LPCG_HW_SEL BIT(0)
> +#define CLK_GATE_SCU_LPCG_SW_SEL BIT(1)
> +
> +struct clk_lpcg_scu {
> + struct clk_hw hw;
> + void __iomem *reg;
> + u8 bit_idx;
> + bool hw_gate;
What does hw_gate mean? Can you add kernel-doc to this structure?
> +};
> +
> +#define to_clk_lpcg_scu(_hw) container_of(_hw, struct clk_lpcg_scu, hw)
> +
> +/* Write to the LPCG bits. */
Please remove this useless comment.
> +static int clk_lpcg_scu_enable(struct clk_hw *hw)
> +{
> + struct clk_lpcg_scu *clk = to_clk_lpcg_scu(hw);
> + unsigned long flags = 0;
Don't initialize flags here.
> + u32 reg;
> +
> + spin_lock_irqsave(&imx_lpcg_scu_lock, flags);
> +
> + if (clk->reg) {
> + reg = readl(clk->reg);
> + reg &= ~(CLK_GATE_SCU_LPCG_MASK << clk->bit_idx);
> + if (clk->hw_gate)
> + reg |= (CLK_GATE_SCU_LPCG_HW_SEL |
> + CLK_GATE_SCU_LPCG_SW_SEL) << clk->bit_idx;
> + else
> + reg |= (CLK_GATE_SCU_LPCG_SW_SEL << clk->bit_idx);
> + writel(reg, clk->reg);
> + }
> +
> + spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags);
> +
> + return 0;
> +}
> +
> +static void clk_lpcg_scu_disable(struct clk_hw *hw)
> +{
> + struct clk_lpcg_scu *clk = to_clk_lpcg_scu(hw);
> + unsigned long flags = 0;
Same comment.
> + u32 reg;
> +
> + spin_lock_irqsave(&imx_lpcg_scu_lock, flags);
> +
> + if (clk->reg) {
Why do we even call this function if there isn't a clk->reg value?
Can't we just not assign the clk_ops in that case?
> + reg = readl(clk->reg);
> + reg &= ~(CLK_GATE_SCU_LPCG_MASK << clk->bit_idx);
> + writel(reg, clk->reg);
> + }
> +
> + spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags);
> +}
> +
^ permalink raw reply [flat|nested] 36+ messages in thread
* RE: [PATCH V6 6/6] clk: imx: add imx8qxp lpcg driver
2018-11-20 18:55 ` Stephen Boyd
@ 2018-11-21 1:50 ` Aisheng DONG
-1 siblings, 0 replies; 36+ messages in thread
From: Aisheng DONG @ 2018-11-21 1:50 UTC (permalink / raw)
To: Stephen Boyd, linux-clk
Cc: linux-arm-kernel, mturquette, shawnguo, Fabio Estevam,
dl-linux-imx, kernel
> -----Original Message-----
> From: Stephen Boyd [mailto:sboyd@kernel.org]
[...]
> > > > +
> > > > + ss_lpcg = of_device_get_match_data(dev);
> > > > + if (!ss_lpcg)
> > > > + return -ENODEV;
> > > > +
> > > > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > > + base = devm_ioremap(dev, res->start, resource_size(res));
> > >
> > > Why not devm_ioremap_resource()?
> >
> > Because LPCGs are distributed in various subsystem memory space which
> > may be overlapped with some IP modules. So we can't use
> > devm_ioremap_resource which has a request_mem_region() in it.
> > It's something like what we've done for drivers/mfd/syscon.c.
>
> Ok. Any chance that the various subsystems that are combined with the clk
> controller can be split up so that we can use
> devm_ioremap_resource() here?
We can achieve that by describing each LPCGS node in devicetree, but that would
bloat the Devicetree seriously as we have hundreds of LPCGS.
This is similar as what we did for legacy SoCs, e.g MX7D.
The difference is that on MX7D LPCGS are continuous.
e.g.
Table 5-19. CCGR Mapping Table
Gating Register LPCG Enable Offset
CCM_CCGR4 sim_main 0x4040
CCM_CCGR5 sim_display 0x4050
...
CCM_CCGR168 iomux 0x4A80
CCM_CCGR169 iomux_lpsr 0x4A90
CCM_CCGR170 kpp 0x4AA0
But on MX8QXP/QM, they're not continuous anymore and distributed in each SS.
And we probably want to push our IC designer to re-orgnize them into a continuous
memory map again for new chips in the future.
So do you think we can start with this way for MX8 as well?
Then we won't block MX8QXP booting up too long or probably could improve it
Later.
> It may be better to carve up the I/O space of
> this SoC into device nodes that map to the hardware IP blocks, and then have
> those device drivers generate sub-devices for the various logical subsystems
> that the hardware IP spans. Or it could be a big driver that registers with
> multiple subsytems/frameworks from one device driver. This way, the logical
> structure of the linux kernel device driver design doesn't leak into the DT
> description of the SoC.
>
Yes, we currently already describe them with each subsystems in Devicetree.
https://patchwork.kernel.org/patch/10677311/
Regards
Dong Aisheng
> >
> > > > + GFP_KERNEL);
> > > > + if (!clk_data)
> > > > + return -ENOMEM;
> > > > +
> > > > + clk_data->num = ss_lpcg->num_max;
> > > > + clks = clk_data->hws;
> > > > +
> > > > + for (i = 0; i < ss_lpcg->num_lpcg; i++) {
> > > > + lpcg = ss_lpcg->lpcg + i;
> > > > + clks[lpcg->id] = imx_clk_lpcg_scu(lpcg->name,
> > > lpcg->parent,
> > > > + lpcg->flags,
> > > > + base +
> > > lpcg->offset,
> > > > + lpcg->bit_idx,
> > > lpcg->hw_gate);
> > > > + }
> > > > +
> > > > + for (i = 0; i < clk_data->num; i++) {
> > > > + if (IS_ERR(clks[i]))
> > > > + pr_err("i.MX clk %u: register failed
> with %ld\n",
> > > > + i, PTR_ERR(clks[i]));
> > >
> > > But we're OK to continue? Alright...
> > >
> >
> > Yes, probably better to use pr_warn()?
>
> Yes.
>
> >
> > > > + }
> > > > +
> > > > + return of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
> > > > + clk_data);
> > >
> > > Why not use devm_? Or can the driver never be unbound from sysfs?
> > >
> >
> > We expect the driver to be never unbound from sysfs.
> > Probably we'd better add .suppress_bind_attrs.
>
> Ok. Please add it.
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH V6 6/6] clk: imx: add imx8qxp lpcg driver
@ 2018-11-21 1:50 ` Aisheng DONG
0 siblings, 0 replies; 36+ messages in thread
From: Aisheng DONG @ 2018-11-21 1:50 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Stephen Boyd [mailto:sboyd at kernel.org]
[...]
> > > > +
> > > > + ss_lpcg = of_device_get_match_data(dev);
> > > > + if (!ss_lpcg)
> > > > + return -ENODEV;
> > > > +
> > > > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > > + base = devm_ioremap(dev, res->start, resource_size(res));
> > >
> > > Why not devm_ioremap_resource()?
> >
> > Because LPCGs are distributed in various subsystem memory space which
> > may be overlapped with some IP modules. So we can't use
> > devm_ioremap_resource which has a request_mem_region() in it.
> > It's something like what we've done for drivers/mfd/syscon.c.
>
> Ok. Any chance that the various subsystems that are combined with the clk
> controller can be split up so that we can use
> devm_ioremap_resource() here?
We can achieve that by describing each LPCGS node in devicetree, but that would
bloat the Devicetree seriously as we have hundreds of LPCGS.
This is similar as what we did for legacy SoCs, e.g MX7D.
The difference is that on MX7D LPCGS are continuous.
e.g.
Table 5-19. CCGR Mapping Table
Gating Register LPCG Enable Offset
CCM_CCGR4 sim_main 0x4040
CCM_CCGR5 sim_display 0x4050
...
CCM_CCGR168 iomux 0x4A80
CCM_CCGR169 iomux_lpsr 0x4A90
CCM_CCGR170 kpp 0x4AA0
But on MX8QXP/QM, they're not continuous anymore and distributed in each SS.
And we probably want to push our IC designer to re-orgnize them into a continuous
memory map again for new chips in the future.
So do you think we can start with this way for MX8 as well?
Then we won't block MX8QXP booting up too long or probably could improve it
Later.
> It may be better to carve up the I/O space of
> this SoC into device nodes that map to the hardware IP blocks, and then have
> those device drivers generate sub-devices for the various logical subsystems
> that the hardware IP spans. Or it could be a big driver that registers with
> multiple subsytems/frameworks from one device driver. This way, the logical
> structure of the linux kernel device driver design doesn't leak into the DT
> description of the SoC.
>
Yes, we currently already describe them with each subsystems in Devicetree.
https://patchwork.kernel.org/patch/10677311/
Regards
Dong Aisheng
> >
> > > > + GFP_KERNEL);
> > > > + if (!clk_data)
> > > > + return -ENOMEM;
> > > > +
> > > > + clk_data->num = ss_lpcg->num_max;
> > > > + clks = clk_data->hws;
> > > > +
> > > > + for (i = 0; i < ss_lpcg->num_lpcg; i++) {
> > > > + lpcg = ss_lpcg->lpcg + i;
> > > > + clks[lpcg->id] = imx_clk_lpcg_scu(lpcg->name,
> > > lpcg->parent,
> > > > + lpcg->flags,
> > > > + base +
> > > lpcg->offset,
> > > > + lpcg->bit_idx,
> > > lpcg->hw_gate);
> > > > + }
> > > > +
> > > > + for (i = 0; i < clk_data->num; i++) {
> > > > + if (IS_ERR(clks[i]))
> > > > + pr_err("i.MX clk %u: register failed
> with %ld\n",
> > > > + i, PTR_ERR(clks[i]));
> > >
> > > But we're OK to continue? Alright...
> > >
> >
> > Yes, probably better to use pr_warn()?
>
> Yes.
>
> >
> > > > + }
> > > > +
> > > > + return of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
> > > > + clk_data);
> > >
> > > Why not use devm_? Or can the driver never be unbound from sysfs?
> > >
> >
> > We expect the driver to be never unbound from sysfs.
> > Probably we'd better add .suppress_bind_attrs.
>
> Ok. Please add it.
^ permalink raw reply [flat|nested] 36+ messages in thread
* RE: [PATCH V6 5/6] clk: imx: add lpcg clock support
2018-11-20 20:14 ` Stephen Boyd
@ 2018-11-21 1:54 ` Aisheng DONG
-1 siblings, 0 replies; 36+ messages in thread
From: Aisheng DONG @ 2018-11-21 1:54 UTC (permalink / raw)
To: Stephen Boyd, linux-clk
Cc: linux-arm-kernel, mturquette, shawnguo, Fabio Estevam,
dl-linux-imx, kernel
> -----Original Message-----
> From: Stephen Boyd [mailto:sboyd@kernel.org]
[...]
> Quoting A.s. Dong (2018-11-10 07:20:04)
> > diff --git a/drivers/clk/imx/clk-lpcg-scu.c
> > b/drivers/clk/imx/clk-lpcg-scu.c new file mode 100644 index
> > 0000000..54a1cb3
> > --- /dev/null
> > +++ b/drivers/clk/imx/clk-lpcg-scu.c
> > @@ -0,0 +1,108 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright 2018 NXP
> > + * Dong Aisheng <aisheng.dong@nxp.com>
> > + */
> > +
> > +#include <linux/clk-provider.h>
> > +#include <linux/err.h>
> > +#include <linux/io.h>
> > +#include <linux/slab.h>
> > +#include <linux/spinlock.h>
> > +
> > +static DEFINE_SPINLOCK(imx_lpcg_scu_lock);
> > +
> > +#define CLK_GATE_SCU_LPCG_MASK 0x3
> > +#define CLK_GATE_SCU_LPCG_HW_SEL BIT(0)
> > +#define CLK_GATE_SCU_LPCG_SW_SEL BIT(1)
> > +
> > +struct clk_lpcg_scu {
> > + struct clk_hw hw;
> > + void __iomem *reg;
> > + u8 bit_idx;
> > + bool hw_gate;
>
> What does hw_gate mean? Can you add kernel-doc to this structure?
>
It's for enabling HW auto gate feature.
Up till now, mostly IP drivers does not use it, but we still keep it in case someone
wants it in the future.
I will add kernel doc for it later.
> > +};
> > +
> > +#define to_clk_lpcg_scu(_hw) container_of(_hw, struct clk_lpcg_scu,
> > +hw)
> > +
> > +/* Write to the LPCG bits. */
>
> Please remove this useless comment.
>
Got it.
> > +static int clk_lpcg_scu_enable(struct clk_hw *hw) {
> > + struct clk_lpcg_scu *clk = to_clk_lpcg_scu(hw);
> > + unsigned long flags = 0;
>
> Don't initialize flags here.
>
Can't remember whether initialize it to avoid a kernel warning.
Will check and remove it if not needed.
> > + u32 reg;
> > +
> > + spin_lock_irqsave(&imx_lpcg_scu_lock, flags);
> > +
> > + if (clk->reg) {
> > + reg = readl(clk->reg);
> > + reg &= ~(CLK_GATE_SCU_LPCG_MASK << clk->bit_idx);
> > + if (clk->hw_gate)
> > + reg |= (CLK_GATE_SCU_LPCG_HW_SEL |
> > + CLK_GATE_SCU_LPCG_SW_SEL) <<
> clk->bit_idx;
> > + else
> > + reg |= (CLK_GATE_SCU_LPCG_SW_SEL <<
> clk->bit_idx);
> > + writel(reg, clk->reg);
> > + }
> > +
> > + spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags);
> > +
> > + return 0;
> > +}
> > +
> > +static void clk_lpcg_scu_disable(struct clk_hw *hw) {
> > + struct clk_lpcg_scu *clk = to_clk_lpcg_scu(hw);
> > + unsigned long flags = 0;
>
> Same comment.
>
> > + u32 reg;
> > +
> > + spin_lock_irqsave(&imx_lpcg_scu_lock, flags);
> > +
> > + if (clk->reg) {
>
> Why do we even call this function if there isn't a clk->reg value?
> Can't we just not assign the clk_ops in that case?
>
Good catch, this is legacy code and could be removed.
Regards
Dong Aisheng
> > + reg = readl(clk->reg);
> > + reg &= ~(CLK_GATE_SCU_LPCG_MASK << clk->bit_idx);
> > + writel(reg, clk->reg);
> > + }
> > +
> > + spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags); }
> > +
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH V6 5/6] clk: imx: add lpcg clock support
@ 2018-11-21 1:54 ` Aisheng DONG
0 siblings, 0 replies; 36+ messages in thread
From: Aisheng DONG @ 2018-11-21 1:54 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Stephen Boyd [mailto:sboyd at kernel.org]
[...]
> Quoting A.s. Dong (2018-11-10 07:20:04)
> > diff --git a/drivers/clk/imx/clk-lpcg-scu.c
> > b/drivers/clk/imx/clk-lpcg-scu.c new file mode 100644 index
> > 0000000..54a1cb3
> > --- /dev/null
> > +++ b/drivers/clk/imx/clk-lpcg-scu.c
> > @@ -0,0 +1,108 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright 2018 NXP
> > + * Dong Aisheng <aisheng.dong@nxp.com>
> > + */
> > +
> > +#include <linux/clk-provider.h>
> > +#include <linux/err.h>
> > +#include <linux/io.h>
> > +#include <linux/slab.h>
> > +#include <linux/spinlock.h>
> > +
> > +static DEFINE_SPINLOCK(imx_lpcg_scu_lock);
> > +
> > +#define CLK_GATE_SCU_LPCG_MASK 0x3
> > +#define CLK_GATE_SCU_LPCG_HW_SEL BIT(0)
> > +#define CLK_GATE_SCU_LPCG_SW_SEL BIT(1)
> > +
> > +struct clk_lpcg_scu {
> > + struct clk_hw hw;
> > + void __iomem *reg;
> > + u8 bit_idx;
> > + bool hw_gate;
>
> What does hw_gate mean? Can you add kernel-doc to this structure?
>
It's for enabling HW auto gate feature.
Up till now, mostly IP drivers does not use it, but we still keep it in case someone
wants it in the future.
I will add kernel doc for it later.
> > +};
> > +
> > +#define to_clk_lpcg_scu(_hw) container_of(_hw, struct clk_lpcg_scu,
> > +hw)
> > +
> > +/* Write to the LPCG bits. */
>
> Please remove this useless comment.
>
Got it.
> > +static int clk_lpcg_scu_enable(struct clk_hw *hw) {
> > + struct clk_lpcg_scu *clk = to_clk_lpcg_scu(hw);
> > + unsigned long flags = 0;
>
> Don't initialize flags here.
>
Can't remember whether initialize it to avoid a kernel warning.
Will check and remove it if not needed.
> > + u32 reg;
> > +
> > + spin_lock_irqsave(&imx_lpcg_scu_lock, flags);
> > +
> > + if (clk->reg) {
> > + reg = readl(clk->reg);
> > + reg &= ~(CLK_GATE_SCU_LPCG_MASK << clk->bit_idx);
> > + if (clk->hw_gate)
> > + reg |= (CLK_GATE_SCU_LPCG_HW_SEL |
> > + CLK_GATE_SCU_LPCG_SW_SEL) <<
> clk->bit_idx;
> > + else
> > + reg |= (CLK_GATE_SCU_LPCG_SW_SEL <<
> clk->bit_idx);
> > + writel(reg, clk->reg);
> > + }
> > +
> > + spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags);
> > +
> > + return 0;
> > +}
> > +
> > +static void clk_lpcg_scu_disable(struct clk_hw *hw) {
> > + struct clk_lpcg_scu *clk = to_clk_lpcg_scu(hw);
> > + unsigned long flags = 0;
>
> Same comment.
>
> > + u32 reg;
> > +
> > + spin_lock_irqsave(&imx_lpcg_scu_lock, flags);
> > +
> > + if (clk->reg) {
>
> Why do we even call this function if there isn't a clk->reg value?
> Can't we just not assign the clk_ops in that case?
>
Good catch, this is legacy code and could be removed.
Regards
Dong Aisheng
> > + reg = readl(clk->reg);
> > + reg &= ~(CLK_GATE_SCU_LPCG_MASK << clk->bit_idx);
> > + writel(reg, clk->reg);
> > + }
> > +
> > + spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags); }
> > +
^ permalink raw reply [flat|nested] 36+ messages in thread
* RE: [PATCH V6 6/6] clk: imx: add imx8qxp lpcg driver
2018-11-21 1:50 ` Aisheng DONG
@ 2018-12-03 18:55 ` Stephen Boyd
-1 siblings, 0 replies; 36+ messages in thread
From: Stephen Boyd @ 2018-12-03 18:55 UTC (permalink / raw)
To: linux-clk, Aisheng DONG
Cc: linux-arm-kernel, mturquette, shawnguo, Fabio Estevam,
dl-linux-imx, kernel
Quoting Aisheng DONG (2018-11-20 17:50:47)
> > -----Original Message-----
> > From: Stephen Boyd [mailto:sboyd@kernel.org]
> [...]
> > > > > +
> > > > > + ss_lpcg = of_device_get_match_data(dev);
> > > > > + if (!ss_lpcg)
> > > > > + return -ENODEV;
> > > > > +
> > > > > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > > > + base = devm_ioremap(dev, res->start, resource_size(res));
> > > >
> > > > Why not devm_ioremap_resource()?
> > >
> > > Because LPCGs are distributed in various subsystem memory space which
> > > may be overlapped with some IP modules. So we can't use
> > > devm_ioremap_resource which has a request_mem_region() in it.
> > > It's something like what we've done for drivers/mfd/syscon.c.
> >
> > Ok. Any chance that the various subsystems that are combined with the clk
> > controller can be split up so that we can use
> > devm_ioremap_resource() here?
>
> We can achieve that by describing each LPCGS node in devicetree, but that would
> bloat the Devicetree seriously as we have hundreds of LPCGS.
>
> This is similar as what we did for legacy SoCs, e.g MX7D.
> The difference is that on MX7D LPCGS are continuous.
> e.g.
> Table 5-19. CCGR Mapping Table
> Gating Register LPCG Enable Offset
> CCM_CCGR4 sim_main 0x4040
> CCM_CCGR5 sim_display 0x4050
> ...
> CCM_CCGR168 iomux 0x4A80
> CCM_CCGR169 iomux_lpsr 0x4A90
> CCM_CCGR170 kpp 0x4AA0
>
> But on MX8QXP/QM, they're not continuous anymore and distributed in each SS.
> And we probably want to push our IC designer to re-orgnize them into a continuous
> memory map again for new chips in the future.
>
> So do you think we can start with this way for MX8 as well?
> Then we won't block MX8QXP booting up too long or probably could improve it
> Later.
Ok, I don't really understand the memory map of this SoC. I wouldn't
push the IC designer to reorganize everything. I'd push the designer to
make clock controller hw blocks, maybe even one per subsystem is OK, and
then have that build on basic clk types that the clock controller
drivers could use to implement the clk support.
Either way, this hardware must already exist so I think we're done here.
I'm OK with whatever works at this point.
>
> > It may be better to carve up the I/O space of
> > this SoC into device nodes that map to the hardware IP blocks, and then have
> > those device drivers generate sub-devices for the various logical subsystems
> > that the hardware IP spans. Or it could be a big driver that registers with
> > multiple subsytems/frameworks from one device driver. This way, the logical
> > structure of the linux kernel device driver design doesn't leak into the DT
> > description of the SoC.
> >
>
> Yes, we currently already describe them with each subsystems in Devicetree.
> https://patchwork.kernel.org/patch/10677311/
>
Ok.
^ permalink raw reply [flat|nested] 36+ messages in thread
* RE: [PATCH V6 6/6] clk: imx: add imx8qxp lpcg driver
@ 2018-12-03 18:55 ` Stephen Boyd
0 siblings, 0 replies; 36+ messages in thread
From: Stephen Boyd @ 2018-12-03 18:55 UTC (permalink / raw)
To: linux-clk, Aisheng DONG
Cc: mturquette, dl-linux-imx, kernel, Fabio Estevam, shawnguo,
linux-arm-kernel
Quoting Aisheng DONG (2018-11-20 17:50:47)
> > -----Original Message-----
> > From: Stephen Boyd [mailto:sboyd@kernel.org]
> [...]
> > > > > +
> > > > > + ss_lpcg = of_device_get_match_data(dev);
> > > > > + if (!ss_lpcg)
> > > > > + return -ENODEV;
> > > > > +
> > > > > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > > > + base = devm_ioremap(dev, res->start, resource_size(res));
> > > >
> > > > Why not devm_ioremap_resource()?
> > >
> > > Because LPCGs are distributed in various subsystem memory space which
> > > may be overlapped with some IP modules. So we can't use
> > > devm_ioremap_resource which has a request_mem_region() in it.
> > > It's something like what we've done for drivers/mfd/syscon.c.
> >
> > Ok. Any chance that the various subsystems that are combined with the clk
> > controller can be split up so that we can use
> > devm_ioremap_resource() here?
>
> We can achieve that by describing each LPCGS node in devicetree, but that would
> bloat the Devicetree seriously as we have hundreds of LPCGS.
>
> This is similar as what we did for legacy SoCs, e.g MX7D.
> The difference is that on MX7D LPCGS are continuous.
> e.g.
> Table 5-19. CCGR Mapping Table
> Gating Register LPCG Enable Offset
> CCM_CCGR4 sim_main 0x4040
> CCM_CCGR5 sim_display 0x4050
> ...
> CCM_CCGR168 iomux 0x4A80
> CCM_CCGR169 iomux_lpsr 0x4A90
> CCM_CCGR170 kpp 0x4AA0
>
> But on MX8QXP/QM, they're not continuous anymore and distributed in each SS.
> And we probably want to push our IC designer to re-orgnize them into a continuous
> memory map again for new chips in the future.
>
> So do you think we can start with this way for MX8 as well?
> Then we won't block MX8QXP booting up too long or probably could improve it
> Later.
Ok, I don't really understand the memory map of this SoC. I wouldn't
push the IC designer to reorganize everything. I'd push the designer to
make clock controller hw blocks, maybe even one per subsystem is OK, and
then have that build on basic clk types that the clock controller
drivers could use to implement the clk support.
Either way, this hardware must already exist so I think we're done here.
I'm OK with whatever works at this point.
>
> > It may be better to carve up the I/O space of
> > this SoC into device nodes that map to the hardware IP blocks, and then have
> > those device drivers generate sub-devices for the various logical subsystems
> > that the hardware IP spans. Or it could be a big driver that registers with
> > multiple subsytems/frameworks from one device driver. This way, the logical
> > structure of the linux kernel device driver design doesn't leak into the DT
> > description of the SoC.
> >
>
> Yes, we currently already describe them with each subsystems in Devicetree.
> https://patchwork.kernel.org/patch/10677311/
>
Ok.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 36+ messages in thread
end of thread, other threads:[~2018-12-03 18:56 UTC | newest]
Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-10 15:19 [PATCH V6 0/6] clk: imx: add imx8qxp clock support A.s. Dong
2018-11-10 15:19 ` A.s. Dong
2018-11-10 15:19 ` [PATCH V6 1/6] clk: imx: add scu clock common part A.s. Dong
2018-11-10 15:19 ` A.s. Dong
2018-11-10 15:19 ` [PATCH V6 2/6] dt-bindings: clock: imx8qxp: add SCU clock IDs A.s. Dong
2018-11-10 15:19 ` A.s. Dong
2018-11-10 15:19 ` A.s. Dong
2018-11-11 22:38 ` Rob Herring
2018-11-11 22:38 ` Rob Herring
2018-11-11 22:38 ` Rob Herring
2018-11-10 15:19 ` [PATCH V6 3/6] clk: imx: add imx8qxp clk driver A.s. Dong
2018-11-10 15:19 ` A.s. Dong
2018-11-10 15:20 ` [PATCH V6 4/6] dt-bindings: clock: add imx8qxp lpcg clock binding A.s. Dong
2018-11-10 15:20 ` A.s. Dong
2018-11-10 15:20 ` A.s. Dong
2018-11-11 22:40 ` Rob Herring
2018-11-11 22:40 ` Rob Herring
2018-11-11 22:40 ` Rob Herring
2018-11-10 15:20 ` [PATCH V6 5/6] clk: imx: add lpcg clock support A.s. Dong
2018-11-10 15:20 ` A.s. Dong
2018-11-20 20:14 ` Stephen Boyd
2018-11-20 20:14 ` Stephen Boyd
2018-11-21 1:54 ` Aisheng DONG
2018-11-21 1:54 ` Aisheng DONG
2018-11-10 15:20 ` [PATCH V6 6/6] clk: imx: add imx8qxp lpcg driver A.s. Dong
2018-11-10 15:20 ` A.s. Dong
2018-11-14 23:28 ` Stephen Boyd
2018-11-14 23:28 ` Stephen Boyd
2018-11-15 1:28 ` A.s. Dong
2018-11-15 1:28 ` A.s. Dong
2018-11-20 18:55 ` Stephen Boyd
2018-11-20 18:55 ` Stephen Boyd
2018-11-21 1:50 ` Aisheng DONG
2018-11-21 1:50 ` Aisheng DONG
2018-12-03 18:55 ` Stephen Boyd
2018-12-03 18:55 ` Stephen Boyd
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.