From c807dbedb5e5adbd4e1e2d07574d230df924a5a7 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 23 Feb 2015 21:06:08 +0200 Subject: [PATCH 01/10] clk: ti: fix ti_clk_get_reg_addr error handling There is a case where NULL can be a valid return value for ti_clk_get_reg_addr, specifically the case where both the provider index and register offsets are zero. In this case, the current error checking against a NULL pointer will fail. Thus, change the API to return a ERR_PTR value in an error case, and change all the users of this API to check against IS_ERR instead. Signed-off-by: Tero Kristo Acked-by: Michael Turquette --- drivers/clk/ti/apll.c | 5 +++-- drivers/clk/ti/autoidle.c | 2 +- drivers/clk/ti/clk.c | 7 ++++--- drivers/clk/ti/divider.c | 4 ++-- drivers/clk/ti/dpll.c | 6 +++--- drivers/clk/ti/gate.c | 4 ++-- drivers/clk/ti/interface.c | 2 +- drivers/clk/ti/mux.c | 4 ++-- 8 files changed, 18 insertions(+), 16 deletions(-) diff --git a/drivers/clk/ti/apll.c b/drivers/clk/ti/apll.c index 72d97279eae1..49baf3831546 100644 --- a/drivers/clk/ti/apll.c +++ b/drivers/clk/ti/apll.c @@ -203,7 +203,7 @@ static void __init of_dra7_apll_setup(struct device_node *node) ad->control_reg = ti_clk_get_reg_addr(node, 0); ad->idlest_reg = ti_clk_get_reg_addr(node, 1); - if (!ad->control_reg || !ad->idlest_reg) + if (IS_ERR(ad->control_reg) || IS_ERR(ad->idlest_reg)) goto cleanup; ad->idlest_mask = 0x1; @@ -384,7 +384,8 @@ static void __init of_omap2_apll_setup(struct device_node *node) ad->autoidle_reg = ti_clk_get_reg_addr(node, 1); ad->idlest_reg = ti_clk_get_reg_addr(node, 2); - if (!ad->control_reg || !ad->autoidle_reg || !ad->idlest_reg) + if (IS_ERR(ad->control_reg) || IS_ERR(ad->autoidle_reg) || + IS_ERR(ad->idlest_reg)) goto cleanup; clk = clk_register(NULL, &clk_hw->hw); diff --git a/drivers/clk/ti/autoidle.c b/drivers/clk/ti/autoidle.c index 8912ff80af34..e75c64c9e81c 100644 --- a/drivers/clk/ti/autoidle.c +++ b/drivers/clk/ti/autoidle.c @@ -119,7 +119,7 @@ int __init of_ti_clk_autoidle_setup(struct device_node *node) clk->name = node->name; clk->reg = ti_clk_get_reg_addr(node, 0); - if (!clk->reg) { + if (IS_ERR(clk->reg)) { kfree(clk); return -EINVAL; } diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c index e22b95646e09..0ebe5c51062b 100644 --- a/drivers/clk/ti/clk.c +++ b/drivers/clk/ti/clk.c @@ -103,7 +103,8 @@ int __init ti_clk_retry_init(struct device_node *node, struct clk_hw *hw, * @index: register index from the clock node * * Builds clock register address from device tree information. This - * is a struct of type clk_omap_reg. + * is a struct of type clk_omap_reg. Returns a pointer to the register + * address, or a pointer error value in failure. */ void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index) { @@ -121,14 +122,14 @@ void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index) if (i == CLK_MAX_MEMMAPS) { pr_err("clk-provider not found for %s!\n", node->name); - return NULL; + return ERR_PTR(-ENOENT); } reg->index = i; if (of_property_read_u32_index(node, "reg", index, &val)) { pr_err("%s must have reg[%d]!\n", node->name, index); - return NULL; + return ERR_PTR(-EINVAL); } reg->offset = val; diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c index 6211893c0980..ff5f117950a9 100644 --- a/drivers/clk/ti/divider.c +++ b/drivers/clk/ti/divider.c @@ -530,8 +530,8 @@ static int __init ti_clk_divider_populate(struct device_node *node, u32 val; *reg = ti_clk_get_reg_addr(node, 0); - if (!*reg) - return -EINVAL; + if (IS_ERR(*reg)) + return PTR_ERR(*reg); if (!of_property_read_u32(node, "ti,bit-shift", &val)) *shift = val; diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c index 81dc4698dc41..11478a501c30 100644 --- a/drivers/clk/ti/dpll.c +++ b/drivers/clk/ti/dpll.c @@ -390,18 +390,18 @@ static void __init of_ti_dpll_setup(struct device_node *node, #endif } else { dd->idlest_reg = ti_clk_get_reg_addr(node, 1); - if (!dd->idlest_reg) + if (IS_ERR(dd->idlest_reg)) goto cleanup; dd->mult_div1_reg = ti_clk_get_reg_addr(node, 2); } - if (!dd->control_reg || !dd->mult_div1_reg) + if (IS_ERR(dd->control_reg) || IS_ERR(dd->mult_div1_reg)) goto cleanup; if (dd->autoidle_mask) { dd->autoidle_reg = ti_clk_get_reg_addr(node, 3); - if (!dd->autoidle_reg) + if (IS_ERR(dd->autoidle_reg)) goto cleanup; } diff --git a/drivers/clk/ti/gate.c b/drivers/clk/ti/gate.c index d493307b73f4..0c6fdfcd5f93 100644 --- a/drivers/clk/ti/gate.c +++ b/drivers/clk/ti/gate.c @@ -225,7 +225,7 @@ static void __init _of_ti_gate_clk_setup(struct device_node *node, if (ops != &omap_gate_clkdm_clk_ops) { reg = ti_clk_get_reg_addr(node, 0); - if (!reg) + if (IS_ERR(reg)) return; if (!of_property_read_u32(node, "ti,bit-shift", &val)) @@ -264,7 +264,7 @@ _of_ti_composite_gate_clk_setup(struct device_node *node, return; gate->enable_reg = ti_clk_get_reg_addr(node, 0); - if (!gate->enable_reg) + if (IS_ERR(gate->enable_reg)) goto cleanup; of_property_read_u32(node, "ti,bit-shift", &val); diff --git a/drivers/clk/ti/interface.c b/drivers/clk/ti/interface.c index 265d91f071c5..c76230d8dd04 100644 --- a/drivers/clk/ti/interface.c +++ b/drivers/clk/ti/interface.c @@ -111,7 +111,7 @@ static void __init _of_ti_interface_clk_setup(struct device_node *node, u32 val; reg = ti_clk_get_reg_addr(node, 0); - if (!reg) + if (IS_ERR(reg)) return; if (!of_property_read_u32(node, "ti,bit-shift", &val)) diff --git a/drivers/clk/ti/mux.c b/drivers/clk/ti/mux.c index 728e253606bc..5cdeed538b08 100644 --- a/drivers/clk/ti/mux.c +++ b/drivers/clk/ti/mux.c @@ -210,7 +210,7 @@ static void of_mux_clk_setup(struct device_node *node) reg = ti_clk_get_reg_addr(node, 0); - if (!reg) + if (IS_ERR(reg)) goto cleanup; of_property_read_u32(node, "ti,bit-shift", &shift); @@ -283,7 +283,7 @@ static void __init of_ti_composite_mux_clk_setup(struct device_node *node) mux->reg = ti_clk_get_reg_addr(node, 0); - if (!mux->reg) + if (IS_ERR(mux->reg)) goto cleanup; if (!of_property_read_u32(node, "ti,bit-shift", &val)) From f757d1b047dfe704d459746c289f27934de6f91e Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 16 Mar 2015 12:40:57 +0200 Subject: [PATCH 02/10] clk: ti: clk-3xxx: Correct McBSP related DT clock definitions In DT boot we do not have devices named as omap-mcbsp.X. Correct the McBSP2/4 ick mapping (they were 2->4 and 4->2). Collect the McBSP clock definition in one location at the same time. Fixes the following warning on boot: [ 0.307739] omap_hwmod: mcbsp2: _wait_target_ready failed: -16 [ 0.307769] omap_hwmod: mcbsp2: cannot be enabled for reset (3) Signed-off-by: Peter Ujfalusi Signed-off-by: Tero Kristo --- drivers/clk/ti/clk-3xxx.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/clk/ti/clk-3xxx.c b/drivers/clk/ti/clk-3xxx.c index 383a06e49b09..757636d166cf 100644 --- a/drivers/clk/ti/clk-3xxx.c +++ b/drivers/clk/ti/clk-3xxx.c @@ -34,7 +34,6 @@ static struct ti_dt_clk omap3xxx_clks[] = { DT_CLK(NULL, "omap_96m_alwon_fck", "omap_96m_alwon_fck"), DT_CLK("etb", "emu_core_alwon_ck", "emu_core_alwon_ck"), DT_CLK(NULL, "sys_altclk", "sys_altclk"), - DT_CLK(NULL, "mcbsp_clks", "mcbsp_clks"), DT_CLK(NULL, "sys_clkout1", "sys_clkout1"), DT_CLK(NULL, "dpll1_ck", "dpll1_ck"), DT_CLK(NULL, "dpll1_x2_ck", "dpll1_x2_ck"), @@ -82,8 +81,6 @@ static struct ti_dt_clk omap3xxx_clks[] = { DT_CLK(NULL, "i2c3_fck", "i2c3_fck"), DT_CLK(NULL, "i2c2_fck", "i2c2_fck"), DT_CLK(NULL, "i2c1_fck", "i2c1_fck"), - DT_CLK(NULL, "mcbsp5_fck", "mcbsp5_fck"), - DT_CLK(NULL, "mcbsp1_fck", "mcbsp1_fck"), DT_CLK(NULL, "core_48m_fck", "core_48m_fck"), DT_CLK(NULL, "mcspi4_fck", "mcspi4_fck"), DT_CLK(NULL, "mcspi3_fck", "mcspi3_fck"), @@ -122,10 +119,6 @@ static struct ti_dt_clk omap3xxx_clks[] = { DT_CLK(NULL, "uart1_ick", "uart1_ick"), DT_CLK(NULL, "gpt11_ick", "gpt11_ick"), DT_CLK(NULL, "gpt10_ick", "gpt10_ick"), - DT_CLK("omap-mcbsp.5", "ick", "mcbsp5_ick"), - DT_CLK("omap-mcbsp.1", "ick", "mcbsp1_ick"), - DT_CLK(NULL, "mcbsp5_ick", "mcbsp5_ick"), - DT_CLK(NULL, "mcbsp1_ick", "mcbsp1_ick"), DT_CLK(NULL, "omapctrl_ick", "omapctrl_ick"), DT_CLK(NULL, "dss_tv_fck", "dss_tv_fck"), DT_CLK(NULL, "dss_96m_fck", "dss_96m_fck"), @@ -179,15 +172,17 @@ static struct ti_dt_clk omap3xxx_clks[] = { DT_CLK(NULL, "gpt4_ick", "gpt4_ick"), DT_CLK(NULL, "gpt3_ick", "gpt3_ick"), DT_CLK(NULL, "gpt2_ick", "gpt2_ick"), - DT_CLK("omap-mcbsp.2", "ick", "mcbsp2_ick"), - DT_CLK("omap-mcbsp.3", "ick", "mcbsp3_ick"), - DT_CLK("omap-mcbsp.4", "ick", "mcbsp4_ick"), - DT_CLK(NULL, "mcbsp4_ick", "mcbsp2_ick"), + DT_CLK(NULL, "mcbsp_clks", "mcbsp_clks"), + DT_CLK(NULL, "mcbsp1_ick", "mcbsp1_ick"), + DT_CLK(NULL, "mcbsp2_ick", "mcbsp2_ick"), DT_CLK(NULL, "mcbsp3_ick", "mcbsp3_ick"), - DT_CLK(NULL, "mcbsp2_ick", "mcbsp4_ick"), + DT_CLK(NULL, "mcbsp4_ick", "mcbsp4_ick"), + DT_CLK(NULL, "mcbsp5_ick", "mcbsp5_ick"), + DT_CLK(NULL, "mcbsp1_fck", "mcbsp1_fck"), DT_CLK(NULL, "mcbsp2_fck", "mcbsp2_fck"), DT_CLK(NULL, "mcbsp3_fck", "mcbsp3_fck"), DT_CLK(NULL, "mcbsp4_fck", "mcbsp4_fck"), + DT_CLK(NULL, "mcbsp5_fck", "mcbsp5_fck"), DT_CLK("etb", "emu_src_ck", "emu_src_ck"), DT_CLK(NULL, "emu_src_ck", "emu_src_ck"), DT_CLK(NULL, "pclk_fck", "pclk_fck"), From c8d382921299a32e4ed9b690d3865e01a73ea02c Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Mon, 16 Mar 2015 12:40:58 +0200 Subject: [PATCH 03/10] clk: ti: clk-3xxx-legacy: Correct McBSP related clock aliases Correct the McBSP2/4 ick mapping (they were 2->4 and 4->2). Add missing mcbsp clock aliases. Collect the McBSP clock definition in one location at the same time. Fixes the following warning on boot: [ 0.307739] omap_hwmod: mcbsp2: _wait_target_ready failed: -16 [ 0.307769] omap_hwmod: mcbsp2: cannot be enabled for reset (3) Signed-off-by: Peter Ujfalusi Signed-off-by: Tero Kristo --- drivers/clk/ti/clk-3xxx-legacy.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/clk/ti/clk-3xxx-legacy.c b/drivers/clk/ti/clk-3xxx-legacy.c index e0732a4c8f26..0b61548d569b 100644 --- a/drivers/clk/ti/clk-3xxx-legacy.c +++ b/drivers/clk/ti/clk-3xxx-legacy.c @@ -4320,7 +4320,6 @@ static struct ti_clk_alias omap3xxx_clks[] = { CLK(NULL, "dpll3_m3x2_ck", &dpll3_m3x2_ck), CLK("etb", "emu_core_alwon_ck", &emu_core_alwon_ck), CLK(NULL, "sys_altclk", &sys_altclk), - CLK(NULL, "mcbsp_clks", &mcbsp_clks), CLK(NULL, "sys_clkout1", &sys_clkout1), CLK(NULL, "dpll3_m2_ck", &dpll3_m2_ck), CLK(NULL, "core_ck", &core_ck), @@ -4369,8 +4368,6 @@ static struct ti_clk_alias omap3xxx_clks[] = { CLK(NULL, "i2c3_fck", &i2c3_fck), CLK(NULL, "i2c2_fck", &i2c2_fck), CLK(NULL, "i2c1_fck", &i2c1_fck), - CLK(NULL, "mcbsp5_fck", &mcbsp5_fck), - CLK(NULL, "mcbsp1_fck", &mcbsp1_fck), CLK(NULL, "core_48m_fck", &core_48m_fck), CLK(NULL, "mcspi4_fck", &mcspi4_fck), CLK(NULL, "mcspi3_fck", &mcspi3_fck), @@ -4409,8 +4406,6 @@ static struct ti_clk_alias omap3xxx_clks[] = { CLK(NULL, "uart1_ick", &uart1_ick), CLK(NULL, "gpt11_ick", &gpt11_ick), CLK(NULL, "gpt10_ick", &gpt10_ick), - CLK("omap-mcbsp.5", "ick", &mcbsp5_ick), - CLK("omap-mcbsp.1", "ick", &mcbsp1_ick), CLK(NULL, "mcbsp5_ick", &mcbsp5_ick), CLK(NULL, "mcbsp1_ick", &mcbsp1_ick), CLK(NULL, "omapctrl_ick", &omapctrl_ick), @@ -4467,15 +4462,22 @@ static struct ti_clk_alias omap3xxx_clks[] = { CLK(NULL, "gpt4_ick", &gpt4_ick), CLK(NULL, "gpt3_ick", &gpt3_ick), CLK(NULL, "gpt2_ick", &gpt2_ick), + CLK(NULL, "mcbsp_clks", &mcbsp_clks), + CLK("omap-mcbsp.1", "ick", &mcbsp1_ick), CLK("omap-mcbsp.2", "ick", &mcbsp2_ick), CLK("omap-mcbsp.3", "ick", &mcbsp3_ick), CLK("omap-mcbsp.4", "ick", &mcbsp4_ick), - CLK(NULL, "mcbsp4_ick", &mcbsp2_ick), + CLK("omap-mcbsp.5", "ick", &mcbsp5_ick), + CLK(NULL, "mcbsp1_ick", &mcbsp1_ick), + CLK(NULL, "mcbsp2_ick", &mcbsp2_ick), CLK(NULL, "mcbsp3_ick", &mcbsp3_ick), - CLK(NULL, "mcbsp2_ick", &mcbsp4_ick), + CLK(NULL, "mcbsp4_ick", &mcbsp4_ick), + CLK(NULL, "mcbsp5_ick", &mcbsp5_ick), + CLK(NULL, "mcbsp1_fck", &mcbsp1_fck), CLK(NULL, "mcbsp2_fck", &mcbsp2_fck), CLK(NULL, "mcbsp3_fck", &mcbsp3_fck), CLK(NULL, "mcbsp4_fck", &mcbsp4_fck), + CLK(NULL, "mcbsp5_fck", &mcbsp5_fck), CLK(NULL, "emu_src_mux_ck", &emu_src_mux_ck), CLK("etb", "emu_src_ck", &emu_src_ck), CLK(NULL, "emu_src_mux_ck", &emu_src_mux_ck), From 2ff8d75c234193147a118c1431d7d75775fabe58 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Fri, 13 Mar 2015 17:58:35 -0500 Subject: [PATCH 04/10] clk: ti: OMAP4: Remove the legacy timer DT clock aliases The DT clock aliases for timers using the legacy OMAP timer device names have been cleaned up. These device names reflect the names used in legacy boot, and are no longer applicable as OMAP4 is DT boot only now. Signed-off-by: Suman Anna Signed-off-by: Tero Kristo --- drivers/clk/ti/clk-44xx.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/clk/ti/clk-44xx.c b/drivers/clk/ti/clk-44xx.c index 4f4c87751db5..581db7711f51 100644 --- a/drivers/clk/ti/clk-44xx.c +++ b/drivers/clk/ti/clk-44xx.c @@ -249,17 +249,6 @@ static struct ti_dt_clk omap44xx_clks[] = { DT_CLK("usbhs_tll", "usbtll_fck", "dummy_ck"), DT_CLK("omap_wdt", "ick", "dummy_ck"), DT_CLK(NULL, "timer_32k_ck", "sys_32k_ck"), - DT_CLK("omap_timer.1", "timer_sys_ck", "sys_clkin_ck"), - DT_CLK("omap_timer.2", "timer_sys_ck", "sys_clkin_ck"), - DT_CLK("omap_timer.3", "timer_sys_ck", "sys_clkin_ck"), - DT_CLK("omap_timer.4", "timer_sys_ck", "sys_clkin_ck"), - DT_CLK("omap_timer.9", "timer_sys_ck", "sys_clkin_ck"), - DT_CLK("omap_timer.10", "timer_sys_ck", "sys_clkin_ck"), - DT_CLK("omap_timer.11", "timer_sys_ck", "sys_clkin_ck"), - DT_CLK("omap_timer.5", "timer_sys_ck", "syc_clk_div_ck"), - DT_CLK("omap_timer.6", "timer_sys_ck", "syc_clk_div_ck"), - DT_CLK("omap_timer.7", "timer_sys_ck", "syc_clk_div_ck"), - DT_CLK("omap_timer.8", "timer_sys_ck", "syc_clk_div_ck"), DT_CLK("4a318000.timer", "timer_sys_ck", "sys_clkin_ck"), DT_CLK("48032000.timer", "timer_sys_ck", "sys_clkin_ck"), DT_CLK("48034000.timer", "timer_sys_ck", "sys_clkin_ck"), From 03ff41a938d0c31c3e712590600b474454ac39fe Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Fri, 13 Mar 2015 17:58:36 -0500 Subject: [PATCH 05/10] clk: ti: OMAP5: Correct the DT clock aliases for timers The DT clock aliases for Timers use the legacy (non-DT) device names and a source clock named sys_ck. OMAP5 is DT-boot only, so correct the DT clock aliases to use the DT device names instead. Also, the source clock name is corrected from 'sys_ck' to 'timer_sys_ck', the name used by the OMAP dmtimer driver. Signed-off-by: Suman Anna Signed-off-by: Tero Kristo --- drivers/clk/ti/clk-54xx.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/clk/ti/clk-54xx.c b/drivers/clk/ti/clk-54xx.c index 14160b223548..96c69a335975 100644 --- a/drivers/clk/ti/clk-54xx.c +++ b/drivers/clk/ti/clk-54xx.c @@ -208,17 +208,17 @@ static struct ti_dt_clk omap54xx_clks[] = { DT_CLK("usbhs_omap", "usbtll_fck", "dummy_ck"), DT_CLK("omap_wdt", "ick", "dummy_ck"), DT_CLK(NULL, "timer_32k_ck", "sys_32k_ck"), - DT_CLK("omap_timer.1", "sys_ck", "sys_clkin"), - DT_CLK("omap_timer.2", "sys_ck", "sys_clkin"), - DT_CLK("omap_timer.3", "sys_ck", "sys_clkin"), - DT_CLK("omap_timer.4", "sys_ck", "sys_clkin"), - DT_CLK("omap_timer.9", "sys_ck", "sys_clkin"), - DT_CLK("omap_timer.10", "sys_ck", "sys_clkin"), - DT_CLK("omap_timer.11", "sys_ck", "sys_clkin"), - DT_CLK("omap_timer.5", "sys_ck", "dss_syc_gfclk_div"), - DT_CLK("omap_timer.6", "sys_ck", "dss_syc_gfclk_div"), - DT_CLK("omap_timer.7", "sys_ck", "dss_syc_gfclk_div"), - DT_CLK("omap_timer.8", "sys_ck", "dss_syc_gfclk_div"), + DT_CLK("4ae18000.timer", "timer_sys_ck", "sys_clkin"), + DT_CLK("48032000.timer", "timer_sys_ck", "sys_clkin"), + DT_CLK("48034000.timer", "timer_sys_ck", "sys_clkin"), + DT_CLK("48036000.timer", "timer_sys_ck", "sys_clkin"), + DT_CLK("4803e000.timer", "timer_sys_ck", "sys_clkin"), + DT_CLK("48086000.timer", "timer_sys_ck", "sys_clkin"), + DT_CLK("48088000.timer", "timer_sys_ck", "sys_clkin"), + DT_CLK("40138000.timer", "timer_sys_ck", "dss_syc_gfclk_div"), + DT_CLK("4013a000.timer", "timer_sys_ck", "dss_syc_gfclk_div"), + DT_CLK("4013c000.timer", "timer_sys_ck", "dss_syc_gfclk_div"), + DT_CLK("4013e000.timer", "timer_sys_ck", "dss_syc_gfclk_div"), { .node_name = NULL }, }; From d4295be3874c1d464ae83a71f87ed93f84aa5d21 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Fri, 13 Mar 2015 17:58:37 -0500 Subject: [PATCH 06/10] clk: ti: DRA7: Correct timer_sys_ck clock aliases for Timers The OMAP DMTimer API, omap_dm_timer_set_source(), can set the parent of a timer node using 3 different values that use fixed parent names for the clocks. The parent name, timer_sys_ck, is used for setting the parent when used with the source index OMAP_TIMER_SRC_SYS_CLK. This should point to the TIMER_SYS_CLK and not the SYSCLKIN2, so correct the clock aliases appropriately. SYSCLKIN2 is not a mandatory clock input. Signed-off-by: Suman Anna Signed-off-by: Tero Kristo --- drivers/clk/ti/clk-7xx.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/clk/ti/clk-7xx.c b/drivers/clk/ti/clk-7xx.c index ee32f4deebf4..256295eb5157 100644 --- a/drivers/clk/ti/clk-7xx.c +++ b/drivers/clk/ti/clk-7xx.c @@ -289,13 +289,13 @@ static struct ti_dt_clk dra7xx_clks[] = { DT_CLK("usbhs_omap", "usbtll_fck", "dummy_ck"), DT_CLK("omap_wdt", "ick", "dummy_ck"), DT_CLK(NULL, "timer_32k_ck", "sys_32k_ck"), - DT_CLK("4ae18000.timer", "timer_sys_ck", "sys_clkin2"), - DT_CLK("48032000.timer", "timer_sys_ck", "sys_clkin2"), - DT_CLK("48034000.timer", "timer_sys_ck", "sys_clkin2"), - DT_CLK("48036000.timer", "timer_sys_ck", "sys_clkin2"), - DT_CLK("4803e000.timer", "timer_sys_ck", "sys_clkin2"), - DT_CLK("48086000.timer", "timer_sys_ck", "sys_clkin2"), - DT_CLK("48088000.timer", "timer_sys_ck", "sys_clkin2"), + DT_CLK("4ae18000.timer", "timer_sys_ck", "timer_sys_clk_div"), + DT_CLK("48032000.timer", "timer_sys_ck", "timer_sys_clk_div"), + DT_CLK("48034000.timer", "timer_sys_ck", "timer_sys_clk_div"), + DT_CLK("48036000.timer", "timer_sys_ck", "timer_sys_clk_div"), + DT_CLK("4803e000.timer", "timer_sys_ck", "timer_sys_clk_div"), + DT_CLK("48086000.timer", "timer_sys_ck", "timer_sys_clk_div"), + DT_CLK("48088000.timer", "timer_sys_ck", "timer_sys_clk_div"), DT_CLK("48820000.timer", "timer_sys_ck", "timer_sys_clk_div"), DT_CLK("48822000.timer", "timer_sys_ck", "timer_sys_clk_div"), DT_CLK("48824000.timer", "timer_sys_ck", "timer_sys_clk_div"), From 712f7d64f079872d2895743f4b718bc0fdff725c Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Fri, 13 Mar 2015 17:58:38 -0500 Subject: [PATCH 07/10] clk: ti: DRA7: Add timer_sys_ck aliases for Timers 13 through 16 The OMAP DMTimer API, omap_dm_timer_set_source(), uses the clock name timer_sys_ck for setting a timer's clock source for the source index OMAP_TIMER_SRC_SYS_CLK. There is currently no clock alias data for the Timers 13 through 16 for this clock name, so add the same. Signed-off-by: Suman Anna Signed-off-by: Tero Kristo --- drivers/clk/ti/clk-7xx.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/clk/ti/clk-7xx.c b/drivers/clk/ti/clk-7xx.c index 256295eb5157..5d2217ae4478 100644 --- a/drivers/clk/ti/clk-7xx.c +++ b/drivers/clk/ti/clk-7xx.c @@ -300,6 +300,10 @@ static struct ti_dt_clk dra7xx_clks[] = { DT_CLK("48822000.timer", "timer_sys_ck", "timer_sys_clk_div"), DT_CLK("48824000.timer", "timer_sys_ck", "timer_sys_clk_div"), DT_CLK("48826000.timer", "timer_sys_ck", "timer_sys_clk_div"), + DT_CLK("48828000.timer", "timer_sys_ck", "timer_sys_clk_div"), + DT_CLK("4882a000.timer", "timer_sys_ck", "timer_sys_clk_div"), + DT_CLK("4882c000.timer", "timer_sys_ck", "timer_sys_clk_div"), + DT_CLK("4882e000.timer", "timer_sys_ck", "timer_sys_clk_div"), DT_CLK(NULL, "sys_clkin", "sys_clkin1"), { .node_name = NULL }, }; From 33ca29c99e8680b4c921c6eafb9fc1603c5b9779 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Sun, 22 Mar 2015 15:35:24 -0700 Subject: [PATCH 08/10] clk: ti: Fix FAPLL recalc_rate for rounding errors We need to round the calculated value to have it match the requested rate. While at it, let's fix a typo and use a define for SYNTH_MAX_DIV_M as we will need it in later patches for set_rate. And let's remove two unused includes. Cc: Brian Hutchinson Cc: Matthijs van Duin Cc: Tero Kristo Signed-off-by: Tony Lindgren Signed-off-by: Tero Kristo --- drivers/clk/ti/fapll.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/clk/ti/fapll.c b/drivers/clk/ti/fapll.c index 6ef89639a9f6..97138c106a67 100644 --- a/drivers/clk/ti/fapll.c +++ b/drivers/clk/ti/fapll.c @@ -11,12 +11,10 @@ #include #include -#include #include #include #include #include -#include /* FAPLL Control Register PLL_CTRL */ #define FAPLL_MAIN_LOCK BIT(7) @@ -49,6 +47,8 @@ /* Synthesizer frequency register */ #define SYNTH_LDFREQ BIT(31) +#define SYNTH_MAX_DIV_M 0xff + struct fapll_data { struct clk_hw hw; void __iomem *base; @@ -218,11 +218,10 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw, rate *= 8; } - /* Synth ost-divider M */ - synth_div_m = readl_relaxed(synth->div) & 0xff; - do_div(rate, synth_div_m); + /* Synth post-divider M */ + synth_div_m = readl_relaxed(synth->div) & SYNTH_MAX_DIV_M; - return rate; + return DIV_ROUND_UP_ULL(rate, synth_div_m); } static struct clk_ops ti_fapll_synt_ops = { From cafeb002cf2cd8b0f8796b59130f9c1b91da4fcf Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 16 Mar 2015 18:04:20 -0700 Subject: [PATCH 09/10] clk: ti: Implement FAPLL set_rate for the synthesizer We can pretty much get any rate out of the FAPLL because of the fractional divider. Let's first try just adjusting the post divider, and if that is not enough, then reprogram both the fractional divider and the post divider. Let's also add a define for the fixed SYNTH_PHASE_K instead of using 8. Cc: Brian Hutchinson Cc: Matthijs van Duin Cc: Tero Kristo Signed-off-by: Tony Lindgren Signed-off-by: Tero Kristo --- drivers/clk/ti/fapll.c | 134 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 132 insertions(+), 2 deletions(-) diff --git a/drivers/clk/ti/fapll.c b/drivers/clk/ti/fapll.c index 97138c106a67..fc06abe5eaaf 100644 --- a/drivers/clk/ti/fapll.c +++ b/drivers/clk/ti/fapll.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,8 @@ /* Synthesizer frequency register */ #define SYNTH_LDFREQ BIT(31) +#define SYNTH_PHASE_K 8 +#define SYNTH_MAX_INT_DIV 0xf #define SYNTH_MAX_DIV_M 0xff struct fapll_data { @@ -204,7 +207,7 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw, /* * Synth frequency integer and fractional divider. * Note that the phase output K is 8, so the result needs - * to be multiplied by 8. + * to be multiplied by SYNTH_PHASE_K. */ if (synth->freq) { u32 v, synth_int_div, synth_frac_div, synth_div_freq; @@ -215,7 +218,7 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw, synth_div_freq = (synth_int_div * 10000000) + synth_frac_div; rate *= 10000000; do_div(rate, synth_div_freq); - rate *= 8; + rate *= SYNTH_PHASE_K; } /* Synth post-divider M */ @@ -224,11 +227,138 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw, return DIV_ROUND_UP_ULL(rate, synth_div_m); } +static unsigned long ti_fapll_synth_get_frac_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct fapll_synth *synth = to_synth(hw); + unsigned long current_rate, frac_rate; + u32 post_div_m; + + current_rate = ti_fapll_synth_recalc_rate(hw, parent_rate); + post_div_m = readl_relaxed(synth->div) & SYNTH_MAX_DIV_M; + frac_rate = current_rate * post_div_m; + + return frac_rate; +} + +static u32 ti_fapll_synth_set_frac_rate(struct fapll_synth *synth, + unsigned long rate, + unsigned long parent_rate) +{ + u32 post_div_m, synth_int_div = 0, synth_frac_div = 0, v; + + post_div_m = DIV_ROUND_UP_ULL((u64)parent_rate * SYNTH_PHASE_K, rate); + post_div_m = post_div_m / SYNTH_MAX_INT_DIV; + if (post_div_m > SYNTH_MAX_DIV_M) + return -EINVAL; + if (!post_div_m) + post_div_m = 1; + + for (; post_div_m < SYNTH_MAX_DIV_M; post_div_m++) { + synth_int_div = DIV_ROUND_UP_ULL((u64)parent_rate * + SYNTH_PHASE_K * + 10000000, + rate * post_div_m); + synth_frac_div = synth_int_div % 10000000; + synth_int_div /= 10000000; + + if (synth_int_div <= SYNTH_MAX_INT_DIV) + break; + } + + if (synth_int_div > SYNTH_MAX_INT_DIV) + return -EINVAL; + + v = readl_relaxed(synth->freq); + v &= ~0x1fffffff; + v |= (synth_int_div & SYNTH_MAX_INT_DIV) << 24; + v |= (synth_frac_div & 0xffffff); + v |= SYNTH_LDFREQ; + writel_relaxed(v, synth->freq); + + return post_div_m; +} + +static long ti_fapll_synth_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct fapll_synth *synth = to_synth(hw); + struct fapll_data *fd = synth->fd; + unsigned long r; + + if (ti_fapll_clock_is_bypass(fd) || !synth->div || !rate) + return -EINVAL; + + /* Only post divider m available with no fractional divider? */ + if (!synth->freq) { + unsigned long frac_rate; + u32 synth_post_div_m; + + frac_rate = ti_fapll_synth_get_frac_rate(hw, *parent_rate); + synth_post_div_m = DIV_ROUND_UP(frac_rate, rate); + r = DIV_ROUND_UP(frac_rate, synth_post_div_m); + goto out; + } + + r = *parent_rate * SYNTH_PHASE_K; + if (rate > r) + goto out; + + r = DIV_ROUND_UP_ULL(r, SYNTH_MAX_INT_DIV * SYNTH_MAX_DIV_M); + if (rate < r) + goto out; + + r = rate; +out: + return r; +} + +static int ti_fapll_synth_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct fapll_synth *synth = to_synth(hw); + struct fapll_data *fd = synth->fd; + unsigned long frac_rate, post_rate = 0; + u32 post_div_m = 0, v; + + if (ti_fapll_clock_is_bypass(fd) || !synth->div || !rate) + return -EINVAL; + + /* Produce the rate with just post divider M? */ + frac_rate = ti_fapll_synth_get_frac_rate(hw, parent_rate); + if (frac_rate < rate) { + if (!synth->freq) + return -EINVAL; + } else { + post_div_m = DIV_ROUND_UP(frac_rate, rate); + if (post_div_m && (post_div_m <= SYNTH_MAX_DIV_M)) + post_rate = DIV_ROUND_UP(frac_rate, post_div_m); + if (!synth->freq && !post_rate) + return -EINVAL; + } + + /* Need to recalculate the fractional divider? */ + if ((post_rate != rate) && synth->freq) + post_div_m = ti_fapll_synth_set_frac_rate(synth, + rate, + parent_rate); + + v = readl_relaxed(synth->div); + v &= ~SYNTH_MAX_DIV_M; + v |= post_div_m; + v |= SYNTH_LDMDIV1; + writel_relaxed(v, synth->div); + + return 0; +} + static struct clk_ops ti_fapll_synt_ops = { .enable = ti_fapll_synth_enable, .disable = ti_fapll_synth_disable, .is_enabled = ti_fapll_synth_is_enabled, .recalc_rate = ti_fapll_synth_recalc_rate, + .round_rate = ti_fapll_synth_round_rate, + .set_rate = ti_fapll_synth_set_rate, }; static struct clk * __init ti_fapll_synth_setup(struct fapll_data *fd, From 9089848d9afa34a796988b5b666c2c4e611ccb61 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Sun, 22 Mar 2015 15:35:26 -0700 Subject: [PATCH 10/10] clk: ti: Implement FAPLL set_rate for the PLL Since we have a fractional divider for the synthesizer, just implement a simple multiply logic for the PLL. It seems the PLL divider needs to have also the multiplier set for the PLL to lock. At least I have not yet figured out if divided rates are doable. So let's just ignore the PLL divider for now as the synthesizer has both integer and fractional dividers so we don't even need to use the PLL divider for the rates we know work with PLL locking. Cc: Brian Hutchinson Cc: Matthijs van Duin Cc: Tero Kristo Signed-off-by: Tony Lindgren Signed-off-by: Tero Kristo --- drivers/clk/ti/fapll.c | 125 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/drivers/clk/ti/fapll.c b/drivers/clk/ti/fapll.c index fc06abe5eaaf..e8291c3a0e76 100644 --- a/drivers/clk/ti/fapll.c +++ b/drivers/clk/ti/fapll.c @@ -18,11 +18,20 @@ #include /* FAPLL Control Register PLL_CTRL */ +#define FAPLL_MAIN_MULT_N_SHIFT 16 +#define FAPLL_MAIN_DIV_P_SHIFT 8 #define FAPLL_MAIN_LOCK BIT(7) #define FAPLL_MAIN_PLLEN BIT(3) #define FAPLL_MAIN_BP BIT(2) #define FAPLL_MAIN_LOC_CTL BIT(0) +#define FAPLL_MAIN_MAX_MULT_N 0xffff +#define FAPLL_MAIN_MAX_DIV_P 0xff +#define FAPLL_MAIN_CLEAR_MASK \ + ((FAPLL_MAIN_MAX_MULT_N << FAPLL_MAIN_MULT_N_SHIFT) | \ + (FAPLL_MAIN_DIV_P_SHIFT << FAPLL_MAIN_DIV_P_SHIFT) | \ + FAPLL_MAIN_LOC_CTL) + /* FAPLL powerdown register PWD */ #define FAPLL_PWD_OFFSET 4 @@ -82,6 +91,48 @@ static bool ti_fapll_clock_is_bypass(struct fapll_data *fd) return !!(v & FAPLL_MAIN_BP); } +static void ti_fapll_set_bypass(struct fapll_data *fd) +{ + u32 v = readl_relaxed(fd->base); + + if (fd->bypass_bit_inverted) + v &= ~FAPLL_MAIN_BP; + else + v |= FAPLL_MAIN_BP; + writel_relaxed(v, fd->base); +} + +static void ti_fapll_clear_bypass(struct fapll_data *fd) +{ + u32 v = readl_relaxed(fd->base); + + if (fd->bypass_bit_inverted) + v |= FAPLL_MAIN_BP; + else + v &= ~FAPLL_MAIN_BP; + writel_relaxed(v, fd->base); +} + +static int ti_fapll_wait_lock(struct fapll_data *fd) +{ + int retries = FAPLL_MAX_RETRIES; + u32 v; + + while ((v = readl_relaxed(fd->base))) { + if (v & FAPLL_MAIN_LOCK) + return 0; + + if (retries-- <= 0) + break; + + udelay(1); + } + + pr_err("%s failed to lock\n", fd->name); + + return -ETIMEDOUT; +} + static int ti_fapll_enable(struct clk_hw *hw) { struct fapll_data *fd = to_fapll(hw); @@ -89,6 +140,7 @@ static int ti_fapll_enable(struct clk_hw *hw) v |= (1 << FAPLL_MAIN_PLLEN); writel_relaxed(v, fd->base); + ti_fapll_wait_lock(fd); return 0; } @@ -144,12 +196,85 @@ static u8 ti_fapll_get_parent(struct clk_hw *hw) return 0; } +static int ti_fapll_set_div_mult(unsigned long rate, + unsigned long parent_rate, + u32 *pre_div_p, u32 *mult_n) +{ + /* + * So far no luck getting decent clock with PLL divider, + * PLL does not seem to lock and the signal does not look + * right. It seems the divider can only be used together + * with the multiplier? + */ + if (rate < parent_rate) { + pr_warn("FAPLL main divider rates unsupported\n"); + return -EINVAL; + } + + *mult_n = rate / parent_rate; + if (*mult_n > FAPLL_MAIN_MAX_MULT_N) + return -EINVAL; + *pre_div_p = 1; + + return 0; +} + +static long ti_fapll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + u32 pre_div_p, mult_n; + int error; + + if (!rate) + return -EINVAL; + + error = ti_fapll_set_div_mult(rate, *parent_rate, + &pre_div_p, &mult_n); + if (error) + return error; + + rate = *parent_rate / pre_div_p; + rate *= mult_n; + + return rate; +} + +static int ti_fapll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct fapll_data *fd = to_fapll(hw); + u32 pre_div_p, mult_n, v; + int error; + + if (!rate) + return -EINVAL; + + error = ti_fapll_set_div_mult(rate, parent_rate, + &pre_div_p, &mult_n); + if (error) + return error; + + ti_fapll_set_bypass(fd); + v = readl_relaxed(fd->base); + v &= ~FAPLL_MAIN_CLEAR_MASK; + v |= pre_div_p << FAPLL_MAIN_DIV_P_SHIFT; + v |= mult_n << FAPLL_MAIN_MULT_N_SHIFT; + writel_relaxed(v, fd->base); + if (ti_fapll_is_enabled(hw)) + ti_fapll_wait_lock(fd); + ti_fapll_clear_bypass(fd); + + return 0; +} + static struct clk_ops ti_fapll_ops = { .enable = ti_fapll_enable, .disable = ti_fapll_disable, .is_enabled = ti_fapll_is_enabled, .recalc_rate = ti_fapll_recalc_rate, .get_parent = ti_fapll_get_parent, + .round_rate = ti_fapll_round_rate, + .set_rate = ti_fapll_set_rate, }; static int ti_fapll_synth_enable(struct clk_hw *hw)