diff options
author | Mattias Nilsson <mattias.i.nilsson@stericsson.com> | 2011-05-31 19:33:29 +0200 |
---|---|---|
committer | said m bagheri <ebgheri@steludxu2848.(none)> | 2011-06-17 13:42:10 +0200 |
commit | f077b35a82bf33a74264603390e295795432cf21 (patch) | |
tree | b062553878be9ff92e708e9be39f8a6084c96d3b /arch | |
parent | d9b926c98ccd263d79a01bc7ab4ee948ea90c561 (diff) |
arm: ux500: ab_intclk setting workaround
This patch changes the AB8500 IntClk setting, to solve what
appears to be a problem with the SysClk routing in the AB8500.
It is not understood why this workaround seems to make the
problem go away.
ST Ericsson ID: 342288
ST Ericsson FOSS-OUT ID: trivial
ST Ericsson Linux-next: -
Change-Id: If5537f57664ba2be910f46b1468727c9cbe21e1b
Signed-off-by: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/24363
Reviewed-by: QATEST
Reviewed-by: Mian Yousaf KAUKAB <mian.yousaf.kaukab@stericsson.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-ux500/clock-db8500.c | 57 |
1 files changed, 48 insertions, 9 deletions
diff --git a/arch/arm/mach-ux500/clock-db8500.c b/arch/arm/mach-ux500/clock-db8500.c index afdd12f6406..73da27f0d57 100644 --- a/arch/arm/mach-ux500/clock-db8500.c +++ b/arch/arm/mach-ux500/clock-db8500.c @@ -181,16 +181,48 @@ static struct clkops ab_ulpclk_ops = { /* AB8500 intclk operations */ +enum ab_intclk_parent { + AB_INTCLK_PARENT_SYSCLK, + AB_INTCLK_PARENT_ULPCLK, + AB_INTCLK_PARENTS_END, + NUM_AB_INTCLK_PARENTS +}; + +static int ab_intclk_enable(struct clk *clk) +{ + if (clk->parent == clk->parents[AB_INTCLK_PARENT_ULPCLK]) { + return ab8500_sysctrl_write(AB8500_SYSULPCLKCTRL1, + AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_MASK, + (1 << AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_SHIFT)); + } + return 0; +} + +static void ab_intclk_disable(struct clk *clk) +{ + if (clk->parent == clk->parents[AB_INTCLK_PARENT_SYSCLK]) + return; + + if (ab8500_sysctrl_clear(AB8500_SYSULPCLKCTRL1, + AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_MASK)) { + pr_err("clock: %s failed to disable %s.\n", __func__, + clk->name); + } +} + static int ab_intclk_set_parent(struct clk *clk, struct clk *parent) { int err; - if (clk->enabled) { - err = __clk_enable(parent, clk->mutex); - if (unlikely(err)) - goto parent_enable_error; - } - if (parent->ops == &ab_ulpclk_ops) { + if (!clk->enabled) + return 0; + + err = __clk_enable(parent, clk->mutex); + + if (unlikely(err)) + goto parent_enable_error; + + if (parent == clk->parents[AB_INTCLK_PARENT_ULPCLK]) { err = ab8500_sysctrl_write(AB8500_SYSULPCLKCTRL1, AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_MASK, (1 << AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_SHIFT)); @@ -200,8 +232,9 @@ static int ab_intclk_set_parent(struct clk *clk, struct clk *parent) } if (unlikely(err)) goto config_error; - if (clk->enabled) - __clk_disable(clk->parent, clk->mutex); + + __clk_disable(clk->parent, clk->mutex); + return 0; config_error: @@ -211,6 +244,8 @@ parent_enable_error: } static struct clkops ab_intclk_ops = { + .enable = ab_intclk_enable, + .disable = ab_intclk_disable, .set_parent = ab_intclk_set_parent, }; @@ -453,7 +488,11 @@ static struct clk ab_ulpclk = { .mutex = &ab_ulpclk_mutex, }; -static struct clk *ab_intclk_parents[] = { &sysclk, &ab_ulpclk, NULL }; +static struct clk *ab_intclk_parents[NUM_AB_INTCLK_PARENTS] = { + [AB_INTCLK_PARENT_SYSCLK] = &sysclk, + [AB_INTCLK_PARENT_ULPCLK] = &ab_ulpclk, + [AB_INTCLK_PARENTS_END] = NULL, +}; static struct clk ab_intclk = { .name = "ab_intclk", |