From: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
To: linaro-dev-cunTk1MwBs8s++Sfvej+rw@public.gmane.org,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
Cc: patches-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org
Subject: [PATCH 3/5] arm/dt: mx51: dynamically add gpt and uart related clocks per dt nodes
Date: Tue, 8 Mar 2011 00:22:10 +0800 [thread overview]
Message-ID: <1299514932-13558-4-git-send-email-shawn.guo@linaro.org> (raw)
In-Reply-To: <1299514932-13558-1-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
This patch is to change the static clock creating and registering to
the dynamic way, which scans dt clock nodes, associate clk with
device_node, and then add them to clkdev accordingly.
Signed-off-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
arch/arm/mach-mx5/clock-mx51-mx53.c | 436 +++++++++++++++++++++++++++++++++--
1 files changed, 422 insertions(+), 14 deletions(-)
diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c
index dedb7f9..1940171 100644
--- a/arch/arm/mach-mx5/clock-mx51-mx53.c
+++ b/arch/arm/mach-mx5/clock-mx51-mx53.c
@@ -135,6 +135,9 @@ static inline u32 _get_mux(struct clk *parent, struct clk *m0,
static inline void __iomem *_mx51_get_pll_base(struct clk *pll)
{
+#ifdef CONFIG_OF
+ return pll->pll_base;
+#else
if (pll == &pll1_main_clk)
return MX51_DPLL1_BASE;
else if (pll == &pll2_sw_clk)
@@ -145,6 +148,7 @@ static inline void __iomem *_mx51_get_pll_base(struct clk *pll)
BUG();
return NULL;
+#endif
}
static inline void __iomem *_mx53_get_pll_base(struct clk *pll)
@@ -1439,33 +1443,437 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
return 0;
}
+/*
+ * Dynamically create and register clks per dt nodes
+ */
#ifdef CONFIG_OF
-static struct clk *mx5_dt_clk_get(struct device_node *np,
- const char *output_id, void *data)
+
+#define ALLOC_CLK_LOOKUP() \
+ struct clk_lookup *cl; \
+ struct clk *clk; \
+ int ret; \
+ \
+ do { \
+ cl = kzalloc(sizeof(*cl) + sizeof(*clk), GFP_KERNEL); \
+ if (!cl) \
+ return -ENOMEM; \
+ clk = (struct clk *) (cl + 1); \
+ \
+ clk->parent = mx5_get_source_clk(node); \
+ clk->secondary = mx5_get_source_clk(node); \
+ } while (0)
+
+#define ADD_CLK_LOOKUP() \
+ do { \
+ node->data = clk; \
+ cl->dev_id = of_get_property(node, \
+ "clock-outputs", NULL); \
+ cl->con_id = of_get_property(node, \
+ "clock-alias", NULL); \
+ if (!cl->dev_id && !cl->con_id) { \
+ ret = -EINVAL; \
+ goto out_kfree; \
+ } \
+ cl->clk = clk; \
+ clkdev_add(cl); \
+ \
+ return 0; \
+ \
+ out_kfree: \
+ kfree(cl); \
+ return ret; \
+ } while (0)
+
+static unsigned long get_fixed_clk_rate(struct clk *clk)
{
- return data;
+ return clk->rate;
}
-static __init void mx5_dt_scan_clks(void)
+static __init int mx5_scan_fixed_clks(void)
{
struct device_node *node;
+ struct clk_lookup *cl;
struct clk *clk;
- const char *id;
- int rc;
+ const __be32 *rate;
+ int ret = 0;
- for_each_compatible_node(node, NULL, "clock") {
- id = of_get_property(node, "clock-outputs", NULL);
- if (!id)
+ for_each_compatible_node(node, NULL, "fixed-clock") {
+ cl = kzalloc(sizeof(*cl) + sizeof(*clk), GFP_KERNEL);
+ if (!cl) {
+ ret = -ENOMEM;
+ break;
+ }
+ clk = (struct clk *) (cl + 1);
+
+ rate = of_get_property(node, "clock-frequency", NULL);
+ if (!rate) {
+ kfree(cl);
continue;
+ }
+ clk->rate = be32_to_cpu(*rate);
+ clk->get_rate = get_fixed_clk_rate;
+
+ node->data = clk;
- clk = clk_get_sys(id, NULL);
- if (IS_ERR(clk))
+ cl->dev_id = of_get_property(node, "clock-outputs", NULL);
+ cl->con_id = of_get_property(node, "clock-alias", NULL);
+ if (!cl->dev_id && !cl->con_id) {
+ kfree(cl);
continue;
+ }
+ cl->clk = clk;
+ clkdev_add(cl);
+ }
+
+ return ret;
+}
+
+static struct clk *mx5_prop_name_to_clk(struct device_node *node,
+ const char *prop_name)
+{
+ struct device_node *provnode;
+ struct clk *clk;
+ const void *prop;
+ u32 provhandle;
+
+ prop = of_get_property(node, prop_name, NULL);
+ if (!prop)
+ return NULL;
+ provhandle = be32_to_cpup(prop);
+
+ provnode = of_find_node_by_phandle(provhandle);
+ if (!provnode)
+ return NULL;
+
+ clk = provnode->data;
+
+ of_node_put(provnode);
+
+ return clk;
+}
+
+static inline struct clk *mx5_get_source_clk(struct device_node *node)
+{
+ return mx5_prop_name_to_clk(node, "clock-source");
+}
+
+static inline struct clk *mx5_get_depend_clk(struct device_node *node)
+{
+ return mx5_prop_name_to_clk(node, "clock-depend");
+}
- rc = of_clk_add_provider(node, mx5_dt_clk_get, clk);
- if (rc)
- pr_err("error adding fixed clk %s\n", node->name);
+static __init int mx5_add_uart_clk(struct device_node *node)
+{
+ const __be32 *reg;
+ int id;
+
+ ALLOC_CLK_LOOKUP();
+
+ reg = of_get_property(node, "reg", NULL);
+ if (!reg) {
+ ret = -ENOENT;
+ goto out_kfree;
+ }
+
+ id = be32_to_cpu(*reg);
+ if (id < 0 || id > 2) {
+ ret = -EINVAL;
+ goto out_kfree;
+ }
+
+ clk->id = id;
+ clk->parent = mx5_get_source_clk(node);
+ clk->secondary = mx5_get_depend_clk(node);
+ clk->enable = _clk_ccgr_enable;
+ clk->disable = _clk_ccgr_disable;
+ clk->enable_reg = MXC_CCM_CCGR1;
+
+ switch (id) {
+ case 0:
+ clk->enable_shift = MXC_CCM_CCGRx_CG4_OFFSET;
+ break;
+ case 1:
+ clk->enable_shift = MXC_CCM_CCGRx_CG6_OFFSET;
+ break;
+ case 2:
+ clk->enable_shift = MXC_CCM_CCGRx_CG8_OFFSET;
+ }
+
+ ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_uart_root_clk(struct device_node *node)
+{
+ ALLOC_CLK_LOOKUP();
+
+ clk->get_rate = clk_uart_get_rate;
+ clk->set_parent = clk_uart_set_parent;
+
+ ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_uart_ipg_clk(struct device_node *node)
+{
+ const __be32 *reg;
+ int id;
+
+ ALLOC_CLK_LOOKUP();
+
+ reg = of_get_property(node, "reg", NULL);
+ if (!reg) {
+ ret = -ENOENT;
+ goto out_kfree;
}
+
+ id = be32_to_cpu(*reg);
+ if (id < 0 || id > 2) {
+ ret = -EINVAL;
+ goto out_kfree;
+ }
+
+ clk->id = id;
+ clk->enable_reg = MXC_CCM_CCGR1;
+ clk->enable = _clk_ccgr_enable;
+ clk->disable = _clk_ccgr_disable;
+
+ switch (id) {
+ case 0:
+ clk->enable_shift = MXC_CCM_CCGRx_CG3_OFFSET;
+ break;
+ case 1:
+ clk->enable_shift = MXC_CCM_CCGRx_CG5_OFFSET;
+ break;
+ case 2:
+ clk->enable_shift = MXC_CCM_CCGRx_CG7_OFFSET;
+ }
+
+ ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_gpt_clk(struct device_node *node)
+{
+ ALLOC_CLK_LOOKUP();
+
+ clk->enable_reg = MXC_CCM_CCGR2;
+ clk->enable_shift = MXC_CCM_CCGRx_CG9_OFFSET;
+ clk->enable = _clk_ccgr_enable;
+ clk->disable = _clk_ccgr_disable;
+
+ ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_gpt_ipg_clk(struct device_node *node)
+{
+ ALLOC_CLK_LOOKUP();
+
+ clk->enable_reg = MXC_CCM_CCGR2;
+ clk->enable_shift = MXC_CCM_CCGRx_CG10_OFFSET;
+ clk->enable = _clk_ccgr_enable;
+ clk->disable = _clk_ccgr_disable;
+
+ ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_aips_tz_clk(struct device_node *node)
+{
+ const __be32 *reg;
+ int id;
+
+ ALLOC_CLK_LOOKUP();
+
+ reg = of_get_property(node, "reg", NULL);
+ if (!reg) {
+ ret = -ENOENT;
+ goto out_kfree;
+ }
+
+ id = be32_to_cpu(*reg);
+ if (id < 0 || id > 1) {
+ ret = -EINVAL;
+ goto out_kfree;
+ }
+
+ clk->id = id;
+ clk->enable_reg = MXC_CCM_CCGR0;
+ clk->enable_shift = id ? MXC_CCM_CCGRx_CG12_OFFSET :
+ MXC_CCM_CCGRx_CG13_OFFSET;
+ clk->enable = _clk_ccgr_enable;
+ clk->disable = _clk_ccgr_disable_inwait;
+
+ ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_ahb_max_clk(struct device_node *node)
+{
+ ALLOC_CLK_LOOKUP();
+
+ clk->enable_reg = MXC_CCM_CCGR0;
+ clk->enable_shift = MXC_CCM_CCGRx_CG14_OFFSET;
+ clk->enable = _clk_max_enable;
+ clk->disable = _clk_max_disable;
+
+ ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_spba_clk(struct device_node *node)
+{
+ ALLOC_CLK_LOOKUP();
+
+ clk->enable_reg = MXC_CCM_CCGR5;
+ clk->enable_shift = MXC_CCM_CCGRx_CG0_OFFSET;
+ clk->enable = _clk_ccgr_enable;
+ clk->disable = _clk_ccgr_disable;
+
+ ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_ipg_clk(struct device_node *node)
+{
+ ALLOC_CLK_LOOKUP();
+
+ clk->get_rate = clk_ipg_get_rate;
+
+ ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_ahb_clk(struct device_node *node)
+{
+ ALLOC_CLK_LOOKUP();
+
+ clk->get_rate = clk_ahb_get_rate;
+ clk->set_rate = _clk_ahb_set_rate;
+ clk->round_rate = _clk_ahb_round_rate;
+
+ ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_main_bus_clk(struct device_node *node)
+{
+ ALLOC_CLK_LOOKUP();
+
+ clk->set_parent = _clk_main_bus_set_parent;
+
+ ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_lp_apm_clk(struct device_node *node)
+{
+ ALLOC_CLK_LOOKUP();
+
+ clk->set_parent = _clk_lp_apm_set_parent;
+
+ ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_pll_switch_clk(struct device_node *node)
+{
+ const __be32 *reg;
+ int id;
+
+ ALLOC_CLK_LOOKUP();
+
+ reg = of_get_property(node, "reg", NULL);
+ if (!reg) {
+ ret = -ENOENT;
+ goto out_kfree;
+ }
+
+ id = be32_to_cpu(*reg);
+ if (id < 0 || id > 2) {
+ ret = -EINVAL;
+ goto out_kfree;
+ }
+
+ clk->id = id;
+
+ switch (id) {
+ case 0:
+ clk->get_rate = clk_pll1_sw_get_rate;
+ clk->set_parent = _clk_pll1_sw_set_parent;
+ break;
+ case 1:
+ clk->get_rate = clk_pll_get_rate;
+ clk->set_rate = _clk_pll_set_rate;
+ clk->enable = _clk_pll_enable;
+ clk->disable = _clk_pll_disable;
+ clk->set_parent = _clk_pll2_sw_set_parent;
+ clk->pll_base = MX51_DPLL2_BASE;
+ break;
+ case 2:
+ clk->get_rate = clk_pll_get_rate;
+ clk->set_rate = _clk_pll_set_rate;
+ clk->enable = _clk_pll_enable;
+ clk->disable = _clk_pll_disable;
+ clk->pll_base = MX51_DPLL3_BASE;
+ }
+
+ ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_add_pll1_main_clk(struct device_node *node)
+{
+ ALLOC_CLK_LOOKUP();
+
+ clk->get_rate = clk_pll_get_rate;
+ clk->enable = _clk_pll_enable;
+ clk->disable = _clk_pll_disable;
+ clk->pll_base = MX51_DPLL1_BASE;
+
+ ADD_CLK_LOOKUP();
+}
+
+static __init int mx5_dt_scan_clks(void)
+{
+ struct device_node *node;
+ int ret;
+
+ ret = mx5_scan_fixed_clks();
+ if (ret) {
+ pr_err("%s: fixed-clock failed %d\n", __func__, ret);
+ return ret;
+ }
+
+ for_each_compatible_node(node, NULL, "clock") {
+ if (!strcmp(node->name, "pll1_main"))
+ ret = mx5_add_pll1_main_clk(node);
+ else if (!strcmp(node->name, "pll_switch"))
+ ret = mx5_add_pll_switch_clk(node);
+ else if (!strcmp(node->name, "lp_apm"))
+ ret = mx5_add_lp_apm_clk(node);
+ else if (!strcmp(node->name, "main_bus"))
+ ret = mx5_add_main_bus_clk(node);
+ else if (!strcmp(node->name, "ahb"))
+ ret = mx5_add_ahb_clk(node);
+ else if (!strcmp(node->name, "ipg"))
+ ret = mx5_add_ipg_clk(node);
+ else if (!strcmp(node->name, "spba"))
+ ret = mx5_add_spba_clk(node);
+ else if (!strcmp(node->name, "ahb_max"))
+ ret = mx5_add_ahb_max_clk(node);
+ else if (!strcmp(node->name, "aips_tz"))
+ ret = mx5_add_aips_tz_clk(node);
+ else if (!strcmp(node->name, "gpt_ipg"))
+ ret = mx5_add_gpt_ipg_clk(node);
+ else if (!strcmp(node->name, "gpt"))
+ ret = mx5_add_gpt_clk(node);
+ else if (!strcmp(node->name, "uart_ipg"))
+ ret = mx5_add_uart_ipg_clk(node);
+ else if (!strcmp(node->name, "uart_root"))
+ ret = mx5_add_uart_root_clk(node);
+ else if (!strcmp(node->name, "uart"))
+ ret = mx5_add_uart_clk(node);
+ else
+ pr_warn("%s: unknown clock node %s\n",
+ __func__, node->name);
+
+ if (ret) {
+ pr_err("%s: clock %s failed %d\n",
+ __func__, node->name, ret);
+ break;
+ }
+ }
+
+ return ret;
}
void __init mx5_clk_dt_init(void)
--
1.7.1
next prev parent reply other threads:[~2011-03-07 16:22 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-03-07 16:22 [PATCH RFC 0/5] Dynamically add clk to clkdev per dt clock nodes Shawn Guo
[not found] ` <1299514932-13558-1-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2011-03-07 16:22 ` [PATCH 1/5] arm/dts: babbage: add gpt and uart related " Shawn Guo
[not found] ` <1299514932-13558-2-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2011-03-07 17:48 ` Grant Likely
[not found] ` <AANLkTimn4fNvM0bSHnpuQmCAweTZ00JQCZCZ=vOdV4NZ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2011-03-08 3:44 ` Shawn Guo
[not found] ` <20110308034447.GB14370-rvtDTF3kK1ictlrPMvKcciBecyulp+rMXqFh9Ls21Oc@public.gmane.org>
2011-03-12 5:55 ` Shawn Guo
2011-03-13 8:08 ` Shawn Guo
2011-03-08 6:56 ` Jason Hui
[not found] ` <AANLkTima=zGr96dZUaYvCN6oE=KCY=ySOgOLweEJYk97-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2011-03-08 7:07 ` Shawn Guo
[not found] ` <20110308070716.GA16642-rvtDTF3kK1ictlrPMvKcciBecyulp+rMXqFh9Ls21Oc@public.gmane.org>
2011-03-08 7:27 ` Jason Hui
2011-03-07 16:22 ` [PATCH 2/5] arm/mxc: add clk members to ease dt clock support Shawn Guo
[not found] ` <1299514932-13558-3-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2011-03-07 17:53 ` Grant Likely
[not found] ` <AANLkTikZsMxs1dXgBxVEar+MLF0j4ROZO+uTmo+OSF4s-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2011-03-08 3:56 ` Shawn Guo
[not found] ` <20110308035633.GD14370-rvtDTF3kK1ictlrPMvKcciBecyulp+rMXqFh9Ls21Oc@public.gmane.org>
2011-03-13 15:19 ` Shawn Guo
2011-03-15 7:41 ` Grant Likely
[not found] ` <20110315074101.GH23050-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
2011-03-15 7:50 ` Shawn Guo
[not found] ` <20110315075028.GG11098-+NayF8gZjK2ctlrPMvKcciBecyulp+rMXqFh9Ls21Oc@public.gmane.org>
2011-03-15 8:02 ` Grant Likely
[not found] ` <20110315080256.GM23050-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
2011-03-15 8:05 ` Shawn Guo
2011-03-07 16:22 ` Shawn Guo [this message]
[not found] ` <1299514932-13558-4-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2011-03-15 7:37 ` [PATCH 3/5] arm/dt: mx51: dynamically add gpt and uart related clocks per dt nodes Grant Likely
[not found] ` <20110315073731.GG23050-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
2011-03-16 12:04 ` Shawn Guo
[not found] ` <20110316120455.GA11658-+NayF8gZjK2ctlrPMvKcciBecyulp+rMXqFh9Ls21Oc@public.gmane.org>
2011-03-17 20:47 ` Grant Likely
[not found] ` <20110317204748.GJ12824-MrY2KI0G/OVr83L8+7iqerDks+cytr/Z@public.gmane.org>
2011-03-18 16:35 ` Shawn Guo
2011-03-07 16:22 ` [PATCH 4/5] arm/dt: mx5: change timer init function to dt clock way Shawn Guo
2011-03-07 16:22 ` [PATCH 5/5] of/clock: eliminate function __of_clk_get_from_provider Shawn Guo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1299514932-13558-4-git-send-email-shawn.guo@linaro.org \
--to=shawn.guo-qsej5fyqhm4dnm+yrofe0a@public.gmane.org \
--cc=devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org \
--cc=linaro-dev-cunTk1MwBs8s++Sfvej+rw@public.gmane.org \
--cc=patches-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).