diff mbox series

[1/1] clk: imx: scu: add set parent support

Message ID 1548855205-12249-1-git-send-email-aisheng.dong@nxp.com (mailing list archive)
State Accepted, archived
Headers show
Series [1/1] clk: imx: scu: add set parent support | expand

Commit Message

Aisheng Dong Jan. 30, 2019, 1:39 p.m. UTC
Add clk scu set parents 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>
---
 drivers/clk/imx/clk-scu.c | 87 +++++++++++++++++++++++++++++++++++++++++++++--
 drivers/clk/imx/clk-scu.h | 16 ++++++++-
 2 files changed, 100 insertions(+), 3 deletions(-)

Comments

Aisheng Dong Feb. 20, 2019, 7:14 a.m. UTC | #1
Ping

> From: Aisheng Dong
> Sent: Wednesday, January 30, 2019 9:39 PM
>
> Add clk scu set parents 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>
> ---
>  drivers/clk/imx/clk-scu.c | 87
> +++++++++++++++++++++++++++++++++++++++++++++--
>  drivers/clk/imx/clk-scu.h | 16 ++++++++-
>  2 files changed, 100 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index
> 7ccf7ed..3c13c41 100644
> --- a/drivers/clk/imx/clk-scu.c
> +++ b/drivers/clk/imx/clk-scu.c
> @@ -66,6 +66,41 @@ struct imx_sc_msg_get_clock_rate {  };
> 
>  /*
> + * struct imx_sc_msg_get_clock_parent - clock get parent protocol
> + * @hdr: SCU protocol header
> + * @req: get parent request protocol
> + * @resp: get parent response protocol
> + *
> + * This structure describes the SCU protocol of clock get parent  */
> +struct imx_sc_msg_get_clock_parent {
> +	struct imx_sc_rpc_msg hdr;
> +	union {
> +		struct req_get_clock_parent {
> +			__le16 resource;
> +			u8 clk;
> +		} __packed req;
> +		struct resp_get_clock_parent {
> +			u8 parent;
> +		} resp;
> +	} data;
> +};
> +
> +/*
> + * struct imx_sc_msg_set_clock_parent - clock set parent protocol
> + * @hdr: SCU protocol header
> + * @req: set parent request protocol
> + *
> + * This structure describes the SCU protocol of clock set parent  */
> +struct imx_sc_msg_set_clock_parent {
> +	struct imx_sc_rpc_msg hdr;
> +	__le16 resource;
> +	u8 clk;
> +	u8 parent;
> +} __packed;
> +
> +/*
>   * struct imx_sc_msg_req_clock_enable - clock gate protocol
>   * @hdr: SCU protocol header
>   * @resource: clock resource to gate
> @@ -173,6 +208,49 @@ static int clk_scu_set_rate(struct clk_hw *hw,
> unsigned long rate,
>  	return imx_scu_call_rpc(ccm_ipc_handle, &msg, true);  }
> 
> +static u8 clk_scu_get_parent(struct clk_hw *hw) {
> +	struct clk_scu *clk = to_clk_scu(hw);
> +	struct imx_sc_msg_get_clock_parent 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_PARENT;
> +	hdr->size = 2;
> +
> +	msg.data.req.resource = cpu_to_le16(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 parent %d\n",
> +		       clk_hw_get_name(hw), ret);
> +		return 0;
> +	}
> +
> +	return le32_to_cpu(msg.data.resp.parent);
> +}
> +
> +static int clk_scu_set_parent(struct clk_hw *hw, u8 index) {
> +	struct clk_scu *clk = to_clk_scu(hw);
> +	struct imx_sc_msg_set_clock_parent 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_PARENT;
> +	hdr->size = 2;
> +
> +	msg.resource = cpu_to_le16(clk->rsrc_id);
> +	msg.clk = clk->clk_type;
> +	msg.parent = index;
> +
> +	return imx_scu_call_rpc(ccm_ipc_handle, &msg, true); }
> +
>  static int sc_pm_clock_enable(struct imx_sc_ipc *ipc, u16 resource,
>  			      u8 clk, bool enable, bool autog)  { @@ -228,11 +306,14
> @@ 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,
> +	.get_parent = clk_scu_get_parent,
> +	.set_parent = clk_scu_set_parent,
>  	.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_hw *__imx_clk_scu(const char *name, const char * const *parents,
> +			     int num_parents, u32 rsrc_id, u8 clk_type)
>  {
>  	struct clk_init_data init;
>  	struct clk_scu *clk;
> @@ -248,7 +329,9 @@ struct clk_hw *imx_clk_scu(const char *name, u32
> rsrc_id, u8 clk_type)
> 
>  	init.name = name;
>  	init.ops = &clk_scu_ops;
> -	init.num_parents = 0;
> +	init.parent_names = parents;
> +	init.num_parents = num_parents;
> +
>  	/*
>  	 * Note on MX8, the clocks are tightly coupled with power domain
>  	 * that once the power domain is off, the clock status may be diff --git
> a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h index 52c1746..2bcfaf0
> 100644
> --- a/drivers/clk/imx/clk-scu.h
> +++ b/drivers/clk/imx/clk-scu.h
> @@ -10,7 +10,21 @@
>  #include <linux/firmware/imx/sci.h>
> 
>  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_scu(const char *name, const char * const *parents,
> +			     int num_parents, u32 rsrc_id, u8 clk_type);
> +
> +static inline struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id,
> +					 u8 clk_type)
> +{
> +	return __imx_clk_scu(name, NULL, 0, rsrc_id, clk_type); }
> +
> +static inline struct clk_hw *imx_clk_scu2(const char *name, const char *
> const *parents,
> +					  int num_parents, u32 rsrc_id, u8 clk_type) {
> +	return __imx_clk_scu(name, parents, num_parents, rsrc_id, clk_type); }
> 
>  struct clk_hw *imx_clk_lpcg_scu(const char *name, const char
> *parent_name,
>  				unsigned long flags, void __iomem *reg,
> --
> 2.7.4
Stephen Boyd Feb. 20, 2019, 9:01 p.m. UTC | #2
Quoting Aisheng Dong (2019-01-30 05:39:15)
> Add clk scu set parents 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>

Applied to clk-next + below

> @@ -173,6 +208,49 @@ static int clk_scu_set_rate(struct clk_hw *hw, unsigned long rate,
>         return imx_scu_call_rpc(ccm_ipc_handle, &msg, true);
>  }
>  
> +static u8 clk_scu_get_parent(struct clk_hw *hw)
> +{
> +       struct clk_scu *clk = to_clk_scu(hw);
> +       struct imx_sc_msg_get_clock_parent 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_PARENT;
> +       hdr->size = 2;
> +
> +       msg.data.req.resource = cpu_to_le16(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 parent %d\n",
> +                      clk_hw_get_name(hw), ret);
> +               return 0;
> +       }
> +
> +       return le32_to_cpu(msg.data.resp.parent);

Sparse complains about this line because it's a u8 not an __le32 that's
being converted. I removed the le32_to_cpu() to fix this.
diff mbox series

Patch

diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c
index 7ccf7ed..3c13c41 100644
--- a/drivers/clk/imx/clk-scu.c
+++ b/drivers/clk/imx/clk-scu.c
@@ -66,6 +66,41 @@  struct imx_sc_msg_get_clock_rate {
 };
 
 /*
+ * struct imx_sc_msg_get_clock_parent - clock get parent protocol
+ * @hdr: SCU protocol header
+ * @req: get parent request protocol
+ * @resp: get parent response protocol
+ *
+ * This structure describes the SCU protocol of clock get parent
+ */
+struct imx_sc_msg_get_clock_parent {
+	struct imx_sc_rpc_msg hdr;
+	union {
+		struct req_get_clock_parent {
+			__le16 resource;
+			u8 clk;
+		} __packed req;
+		struct resp_get_clock_parent {
+			u8 parent;
+		} resp;
+	} data;
+};
+
+/*
+ * struct imx_sc_msg_set_clock_parent - clock set parent protocol
+ * @hdr: SCU protocol header
+ * @req: set parent request protocol
+ *
+ * This structure describes the SCU protocol of clock set parent
+ */
+struct imx_sc_msg_set_clock_parent {
+	struct imx_sc_rpc_msg hdr;
+	__le16 resource;
+	u8 clk;
+	u8 parent;
+} __packed;
+
+/*
  * struct imx_sc_msg_req_clock_enable - clock gate protocol
  * @hdr: SCU protocol header
  * @resource: clock resource to gate
@@ -173,6 +208,49 @@  static int clk_scu_set_rate(struct clk_hw *hw, unsigned long rate,
 	return imx_scu_call_rpc(ccm_ipc_handle, &msg, true);
 }
 
+static u8 clk_scu_get_parent(struct clk_hw *hw)
+{
+	struct clk_scu *clk = to_clk_scu(hw);
+	struct imx_sc_msg_get_clock_parent 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_PARENT;
+	hdr->size = 2;
+
+	msg.data.req.resource = cpu_to_le16(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 parent %d\n",
+		       clk_hw_get_name(hw), ret);
+		return 0;
+	}
+
+	return le32_to_cpu(msg.data.resp.parent);
+}
+
+static int clk_scu_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct clk_scu *clk = to_clk_scu(hw);
+	struct imx_sc_msg_set_clock_parent 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_PARENT;
+	hdr->size = 2;
+
+	msg.resource = cpu_to_le16(clk->rsrc_id);
+	msg.clk = clk->clk_type;
+	msg.parent = index;
+
+	return imx_scu_call_rpc(ccm_ipc_handle, &msg, true);
+}
+
 static int sc_pm_clock_enable(struct imx_sc_ipc *ipc, u16 resource,
 			      u8 clk, bool enable, bool autog)
 {
@@ -228,11 +306,14 @@  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,
+	.get_parent = clk_scu_get_parent,
+	.set_parent = clk_scu_set_parent,
 	.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_hw *__imx_clk_scu(const char *name, const char * const *parents,
+			     int num_parents, u32 rsrc_id, u8 clk_type)
 {
 	struct clk_init_data init;
 	struct clk_scu *clk;
@@ -248,7 +329,9 @@  struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id, u8 clk_type)
 
 	init.name = name;
 	init.ops = &clk_scu_ops;
-	init.num_parents = 0;
+	init.parent_names = parents;
+	init.num_parents = num_parents;
+
 	/*
 	 * Note on MX8, the clocks are tightly coupled with power domain
 	 * that once the power domain is off, the clock status may be
diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h
index 52c1746..2bcfaf0 100644
--- a/drivers/clk/imx/clk-scu.h
+++ b/drivers/clk/imx/clk-scu.h
@@ -10,7 +10,21 @@ 
 #include <linux/firmware/imx/sci.h>
 
 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_scu(const char *name, const char * const *parents,
+			     int num_parents, u32 rsrc_id, u8 clk_type);
+
+static inline struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id,
+					 u8 clk_type)
+{
+	return __imx_clk_scu(name, NULL, 0, rsrc_id, clk_type);
+}
+
+static inline struct clk_hw *imx_clk_scu2(const char *name, const char * const *parents,
+					  int num_parents, u32 rsrc_id, u8 clk_type)
+{
+	return __imx_clk_scu(name, parents, num_parents, rsrc_id, clk_type);
+}
 
 struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
 				unsigned long flags, void __iomem *reg,