summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMattias Nilsson <mattias.i.nilsson@stericsson.com>2011-05-31 19:33:29 +0200
committersaid m bagheri <ebgheri@steludxu2848.(none)>2011-06-17 13:42:10 +0200
commitf077b35a82bf33a74264603390e295795432cf21 (patch)
treeb062553878be9ff92e708e9be39f8a6084c96d3b
parentd9b926c98ccd263d79a01bc7ab4ee948ea90c561 (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>
-rw-r--r--arch/arm/mach-ux500/clock-db8500.c57
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",