clk: vt8500: Fix SDMMC clock special cases
PATCH RESEND 1/2 clk: vt8500: Fix SDMMC clock special cases
This patch adds some additional handling for the SDMMC special case in round_rate and set_rate which results in invalid divisor messages at boot time.
Signed-off-by Tony Prisk <[email protected]>
--- drivers/clk/clk-vt8500.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
drivers/clk/clk-vt8500.c +18 -0
@@ -120,8 +120,17 @@ static unsigned long vt8500_dclk_recalc_rate(struct clk_hw *hw,static long vt8500_dclk_round_rate (struct clk_hw *hw,unsigned long rate,unsigned long *prate) { +struct clk_device *cdev =to_clk_device (hw);u32 divisor = *prate / rate; +/* +* If this is a request for SDMMC we have to adjust the divisor +* when >31 to use the fixed predivisor +*/ +if ((cdev->div_mask ==0x3F ) && (divisor >31 )) { + divisor =64 * ((divisor /64 ) +1 ); + } +return *prate / divisor; }
@@ -135,6 +144,15 @@ static int vt8500_dclk_set_rate(struct clk_hw *hw, unsigned long rate,if (divisor == cdev->div_mask +1 ) divisor =0 ; +/* SDMMC mask may need to be corrected before testing if its valid */ +if ((cdev->div_mask ==0x3F ) && (divisor >31 )) { +/* +* Bit 5 is a fixed /64 predivisor. If the requested divisor +* is >31 then correct for the fixed divisor being required. +*/ + divisor =0x20 + (divisor /64 ); + } +if (divisor > cdev->div_mask) {pr_err ("%s: invalid divisor for clock\n" , __func__);return -EINVAL ;
Signature · 1 line
1.7.9.5
PATCH 2/2 clk: vt8500: Remove dependancy on pmc_base
This patch removes the requirement to pass a Power Management Controller base address to vtwm_clk_init(), in preparation of separating the power management code from arch-vt8500/vt8500.c.
Signed-off-by Tony Prisk <[email protected]>
---
Mike,
Do you mind if this patch goes through arm-soc, given it is self-contained, so I can base the other PM changes off it?
Regards
Tony P
arch/arm/mach-vt8500/common.h | 2 +- arch/arm/mach-vt8500/vt8500.c | 2 +- drivers/clk/clk-vt8500.c | 20 ++++++++++++++++---- 3 files changed, 18 insertions(+), 6 deletions(-)
arch/arm/mach-vt8500/common.h +1 -1
@@ -23,6 +23,6 @@ int __init vt8500_irq_init(struct device_node *node, struct device_node *parent);/* defined in drivers/clk/clk-vt8500.c */ -void __init vtwm_clk_init (void __iomem *pmc_base); +void __init vtwm_clk_init (void );#endif
arch/arm/mach-vt8500/vt8500.c +1 -1
@@ -162,7 +162,7 @@ void __init vt8500_init(void)else pr_err ("%s: PMC Hibernation register could not be remapped, not enabling power off!\n" , __func__); -vtwm_clk_init (pmc_base); +vtwm_clk_init ();of_platform_populate (NULL , of_default_bus_match_table,NULL ,NULL ); }
drivers/clk/clk-vt8500.c +16 -4
@@ -15,6 +15,7 @@#include <linux/io.h> #include <linux/of.h> +#include <linux/of_address.h> #include <linux/slab.h> #include <linux/bitops.h> #include <linux/clkdev.h>
@@ -517,12 +518,23 @@ static const __initconst struct of_device_id clk_match[] = { {/* sentinel */ } }; -void __init vtwm_clk_init (void __iomem *base) +void __init vtwm_clk_init (void ) { -if (!base) -return ; +struct device_node *np = +of_find_compatible_node (NULL ,NULL ,"via,vt8500-pmc" ); + +if (!np) { +pr_err ("%s: power management device node missing\n" , __func__); +return -ENODEV ; + } - pmc_base = base; + pmc_base =of_iomap (np,0 ); +of_node_put (np); + +if (!pmc_base) { +pr_err ("%s: of_iomap(pmc) failed\n" , __func__); +return -ENOMEM ; + }of_clk_init (clk_match); }
Signature · 1 line
1.7.9.5