From patchwork Wed Jan 6 18:31:54 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Hilman X-Patchwork-Id: 71365 Received: from bear.ext.ti.com (bear.ext.ti.com [192.94.94.41]) by demeter.kernel.org (8.14.3/8.14.2) with ESMTP id o06IZOo5013787 for ; Wed, 6 Jan 2010 18:35:24 GMT Received: from dlep35.itg.ti.com ([157.170.170.118]) by bear.ext.ti.com (8.13.7/8.13.7) with ESMTP id o06IZN6g024998 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Wed, 6 Jan 2010 12:35:24 -0600 Received: from linux.omap.com (localhost [127.0.0.1]) by dlep35.itg.ti.com (8.13.7/8.13.7) with ESMTP id o06IZNIm016682 for ; Wed, 6 Jan 2010 12:35:23 -0600 (CST) Received: from linux.omap.com (localhost [127.0.0.1]) by linux.omap.com (Postfix) with ESMTP id C8C3180635 for ; Wed, 6 Jan 2010 12:35:22 -0600 (CST) X-Original-To: davinci-linux-open-source@linux.davincidsp.com Delivered-To: davinci-linux-open-source@linux.davincidsp.com Received: from dflp53.itg.ti.com (dflp53.itg.ti.com [128.247.5.6]) by linux.omap.com (Postfix) with ESMTP id CC9FA8062F for ; Wed, 6 Jan 2010 12:32:45 -0600 (CST) Received: from red.ext.ti.com (localhost [127.0.0.1]) by dflp53.itg.ti.com (8.13.8/8.13.8) with ESMTP id o06IWjkt009039 for ; Wed, 6 Jan 2010 12:32:45 -0600 (CST) Received: from psmtp.com (na3sys009amx236.postini.com [74.125.149.120]) by red.ext.ti.com (8.13.7/8.13.7) with SMTP id o06IWiPd004328 for ; Wed, 6 Jan 2010 12:32:44 -0600 Received: from source ([209.85.216.189]) by na3sys009amx236.postini.com ([74.125.148.10]) with SMTP; Wed, 06 Jan 2010 12:32:44 CST Received: by mail-px0-f189.google.com with SMTP id 27so11129937pxi.4 for ; Wed, 06 Jan 2010 10:32:43 -0800 (PST) Received: by 10.114.7.24 with SMTP id 24mr2619989wag.33.1262802763481; Wed, 06 Jan 2010 10:32:43 -0800 (PST) Received: from localhost (deeprootsystems.com [216.254.16.51]) by mx.google.com with ESMTPS id 23sm17238161pzk.12.2010.01.06.10.32.40 (version=TLSv1/SSLv3 cipher=RC4-MD5); Wed, 06 Jan 2010 10:32:41 -0800 (PST) From: Kevin Hilman To: linux-arm-kernel@lists.infradead.org Subject: [PATCH 12/35] davinci: clock framework: remove spinlock usage Date: Wed, 6 Jan 2010 10:31:54 -0800 Message-Id: <1262802737-6601-13-git-send-email-khilman@deeprootsystems.com> X-Mailer: git-send-email 1.6.6.rc2.1.g42108 In-Reply-To: <1262802737-6601-12-git-send-email-khilman@deeprootsystems.com> References: <1262802737-6601-1-git-send-email-khilman@deeprootsystems.com> <1262802737-6601-2-git-send-email-khilman@deeprootsystems.com> <1262802737-6601-3-git-send-email-khilman@deeprootsystems.com> <1262802737-6601-4-git-send-email-khilman@deeprootsystems.com> <1262802737-6601-5-git-send-email-khilman@deeprootsystems.com> <1262802737-6601-6-git-send-email-khilman@deeprootsystems.com> <1262802737-6601-7-git-send-email-khilman@deeprootsystems.com> <1262802737-6601-8-git-send-email-khilman@deeprootsystems.com> <1262802737-6601-9-git-send-email-khilman@deeprootsystems.com> <1262802737-6601-10-git-send-email-khilman@deeprootsystems.com> <1262802737-6601-11-git-send-email-khilman@deeprootsystems.com> <1262802737-6601-12-git-send-email-khilman@deeprootsystems.com> X-pstn-neptune: 0/0/0.00/0 X-pstn-levels: (S:93.26234/99.90000 CV:99.9000 FC:95.5390 LC:95.5390 R:95.9108 P:95.9108 M:97.0282 C:98.6951 ) X-pstn-settings: 2 (0.5000:0.5000) s cv gt3 gt2 gt1 X-pstn-addresses: from [db-null] Cc: davinci-linux-open-source@linux.davincidsp.com X-BeenThere: davinci-linux-open-source@linux.davincidsp.com X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: davinci-linux-open-source-bounces+patchwork-davinci=patchwork.kernel.org@linux.davincidsp.com Errors-To: davinci-linux-open-source-bounces+patchwork-davinci=patchwork.kernel.org@linux.davincidsp.com diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index 542bfdb..6ff3411 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c @@ -722,9 +722,9 @@ static __init void davinci_dm646x_evm_irq_init(void) void __init dm646x_board_setup_refclk(struct clk *clk) { if (machine_is_davinci_dm6467tevm()) - clk->rate = DM6467T_EVM_REF_FREQ; + atomic_set(&clk->rate, DM6467T_EVM_REF_FREQ); else - clk->rate = DM646X_EVM_REF_FREQ; + atomic_set(&clk->rate, DM646X_EVM_REF_FREQ); } MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM") diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c index 0fa68c5..46c95e0 100644 --- a/arch/arm/mach-davinci/clock.c +++ b/arch/arm/mach-davinci/clock.c @@ -28,7 +28,6 @@ static LIST_HEAD(clocks); static DEFINE_MUTEX(clocks_mutex); -static DEFINE_SPINLOCK(clockfw_lock); static unsigned psc_domain(struct clk *clk) { @@ -41,15 +40,16 @@ static void __clk_enable(struct clk *clk) { if (clk->parent) __clk_enable(clk->parent); - if (clk->usecount++ == 0 && (clk->flags & CLK_PSC)) + if (atomic_read(&clk->usecount) == 0 && (clk->flags & CLK_PSC)) davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc, 1); + atomic_inc(&clk->usecount); } static void __clk_disable(struct clk *clk) { - if (WARN_ON(clk->usecount == 0)) + if (WARN_ON(atomic_read(&clk->usecount) == 0)) return; - if (--clk->usecount == 0 && !(clk->flags & CLK_PLL)) + if (atomic_dec_and_test(&clk->usecount) && !(clk->flags & CLK_PLL)) davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc, 0); if (clk->parent) __clk_disable(clk->parent); @@ -57,14 +57,10 @@ static void __clk_disable(struct clk *clk) int clk_enable(struct clk *clk) { - unsigned long flags; - if (clk == NULL || IS_ERR(clk)) return -EINVAL; - spin_lock_irqsave(&clockfw_lock, flags); __clk_enable(clk); - spin_unlock_irqrestore(&clockfw_lock, flags); return 0; } @@ -72,14 +68,10 @@ EXPORT_SYMBOL(clk_enable); void clk_disable(struct clk *clk) { - unsigned long flags; - if (clk == NULL || IS_ERR(clk)) return; - spin_lock_irqsave(&clockfw_lock, flags); __clk_disable(clk); - spin_unlock_irqrestore(&clockfw_lock, flags); } EXPORT_SYMBOL(clk_disable); @@ -88,7 +80,7 @@ unsigned long clk_get_rate(struct clk *clk) if (clk == NULL || IS_ERR(clk)) return -EINVAL; - return clk->rate; + return atomic_read(&clk->rate); } EXPORT_SYMBOL(clk_get_rate); @@ -100,7 +92,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate) if (clk->round_rate) return clk->round_rate(clk, rate); - return clk->rate; + return atomic_read(&clk->rate); } EXPORT_SYMBOL(clk_round_rate); @@ -111,28 +103,27 @@ static void propagate_rate(struct clk *root) list_for_each_entry(clk, &root->children, childnode) { if (clk->recalc) - clk->rate = clk->recalc(clk); + atomic_set(&clk->rate, clk->recalc(clk)); propagate_rate(clk); } } int clk_set_rate(struct clk *clk, unsigned long rate) { - unsigned long flags; int ret = -EINVAL; if (clk == NULL || IS_ERR(clk)) return ret; - spin_lock_irqsave(&clockfw_lock, flags); if (clk->set_rate) ret = clk->set_rate(clk, rate); if (ret == 0) { if (clk->recalc) - clk->rate = clk->recalc(clk); + atomic_set(&clk->rate, clk->recalc(clk)); + mutex_lock(&clocks_mutex); propagate_rate(clk); + mutex_unlock(&clocks_mutex); } - spin_unlock_irqrestore(&clockfw_lock, flags); return ret; } @@ -140,26 +131,22 @@ EXPORT_SYMBOL(clk_set_rate); int clk_set_parent(struct clk *clk, struct clk *parent) { - unsigned long flags; - if (clk == NULL || IS_ERR(clk)) return -EINVAL; /* Cannot change parent on enabled clock */ - if (WARN_ON(clk->usecount)) + if (WARN_ON(atomic_read(&clk->usecount))) return -EINVAL; mutex_lock(&clocks_mutex); clk->parent = parent; list_del_init(&clk->childnode); list_add(&clk->childnode, &clk->parent->children); - mutex_unlock(&clocks_mutex); - spin_lock_irqsave(&clockfw_lock, flags); if (clk->recalc) - clk->rate = clk->recalc(clk); + atomic_set(&clk->rate, clk->recalc(clk)); propagate_rate(clk); - spin_unlock_irqrestore(&clockfw_lock, flags); + mutex_unlock(&clocks_mutex); return 0; } @@ -170,7 +157,7 @@ int clk_register(struct clk *clk) if (clk == NULL || IS_ERR(clk)) return -EINVAL; - if (WARN(clk->parent && !clk->parent->rate, + if (WARN(clk->parent && !atomic_read(&clk->parent->rate), "CLK: %s parent %s has no rate!\n", clk->name, clk->parent->name)) return -EINVAL; @@ -184,16 +171,16 @@ int clk_register(struct clk *clk) mutex_unlock(&clocks_mutex); /* If rate is already set, use it */ - if (clk->rate) + if (atomic_read(&clk->rate)) return 0; /* Else, see if there is a way to calculate it */ if (clk->recalc) - clk->rate = clk->recalc(clk); + atomic_set(&clk->rate, clk->recalc(clk)); /* Otherwise, default to parent rate */ else if (clk->parent) - clk->rate = clk->parent->rate; + atomic_set(&clk->rate, atomic_read(&clk->parent->rate)); return 0; } @@ -219,9 +206,9 @@ static int __init clk_disable_unused(void) { struct clk *ck; - spin_lock_irq(&clockfw_lock); + mutex_lock(&clocks_mutex); list_for_each_entry(ck, &clocks, node) { - if (ck->usecount > 0) + if (atomic_read(&ck->usecount) > 0) continue; if (!(ck->flags & CLK_PSC)) continue; @@ -233,7 +220,7 @@ static int __init clk_disable_unused(void) pr_info("Clocks: disable unused %s\n", ck->name); davinci_psc_config(psc_domain(ck), ck->gpsc, ck->lpsc, 0); } - spin_unlock_irq(&clockfw_lock); + mutex_unlock(&clocks_mutex); return 0; } @@ -244,7 +231,7 @@ static unsigned long clk_sysclk_recalc(struct clk *clk) { u32 v, plldiv; struct pll_data *pll; - unsigned long rate = clk->rate; + unsigned long rate = atomic_read(&clk->rate); /* If this is the PLL base clock, no more calculations needed */ if (clk->pll_data) @@ -253,7 +240,7 @@ static unsigned long clk_sysclk_recalc(struct clk *clk) if (WARN_ON(!clk->parent)) return rate; - rate = clk->parent->rate; + rate = atomic_read(&clk->parent->rate); /* Otherwise, the parent must be a PLL */ if (WARN_ON(!clk->parent->pll_data)) @@ -281,9 +268,9 @@ static unsigned long clk_sysclk_recalc(struct clk *clk) static unsigned long clk_leafclk_recalc(struct clk *clk) { if (WARN_ON(!clk->parent)) - return clk->rate; + return atomic_read(&clk->rate); - return clk->parent->rate; + return atomic_read(&clk->parent->rate); } static unsigned long clk_pllclk_recalc(struct clk *clk) @@ -291,11 +278,11 @@ static unsigned long clk_pllclk_recalc(struct clk *clk) u32 ctrl, mult = 1, prediv = 1, postdiv = 1; u8 bypass; struct pll_data *pll = clk->pll_data; - unsigned long rate = clk->rate; + unsigned long rate = atomic_read(&clk->rate); pll->base = IO_ADDRESS(pll->phys_base); ctrl = __raw_readl(pll->base + PLLCTL); - rate = pll->input_rate = clk->parent->rate; + rate = pll->input_rate = atomic_read(&clk->parent->rate); if (ctrl & PLLCTL_PLLEN) { bypass = 0; @@ -333,8 +320,8 @@ static unsigned long clk_pllclk_recalc(struct clk *clk) rate /= postdiv; } - pr_debug("PLL%d: input = %lu MHz [ ", - pll->num, clk->parent->rate / 1000000); + pr_debug("PLL%d: input = %u MHz [ ", + pll->num, atomic_read(&clk->parent->rate) / 1000000); if (bypass) pr_debug("bypass "); if (prediv > 1) @@ -443,7 +430,7 @@ int __init davinci_clk_init(struct davinci_clk *clocks) } if (clk->recalc) - clk->rate = clk->recalc(clk); + atomic_set(&clk->rate, clk->recalc(clk)); if (clk->lpsc) clk->flags |= CLK_PSC; @@ -505,7 +492,8 @@ dump_clock(struct seq_file *s, unsigned nest, struct clk *parent) min(i, (unsigned)(sizeof(buf) - 1 - nest))); seq_printf(s, "%s users=%2d %-3s %9ld Hz\n", - buf, parent->usecount, state, clk_get_rate(parent)); + buf, atomic_read(&parent->usecount), state, + clk_get_rate(parent)); /* REVISIT show device associations too */ /* cost is now small, but not linear... */ diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h index 31fb6ea..fa3e373 100644 --- a/arch/arm/mach-davinci/clock.h +++ b/arch/arm/mach-davinci/clock.h @@ -84,8 +84,8 @@ struct clk { struct list_head node; struct module *owner; const char *name; - unsigned long rate; - u8 usecount; + atomic_t rate; + atomic_t usecount; u8 lpsc; u8 gpsc; u32 flags; diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c index 5479605..7a7895d 100644 --- a/arch/arm/mach-davinci/da830.c +++ b/arch/arm/mach-davinci/da830.c @@ -43,7 +43,7 @@ static struct pll_data pll0_data = { static struct clk ref_clk = { .name = "ref_clk", - .rate = DA830_REF_FREQ, + .rate = ATOMIC_INIT(DA830_REF_FREQ), }; static struct clk pll0_clk = { diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 1ac8f63..5c6dd97 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -55,7 +55,7 @@ static struct pll_data pll0_data = { static struct clk ref_clk = { .name = "ref_clk", - .rate = DA850_REF_FREQ, + .rate = ATOMIC_INIT(DA850_REF_FREQ), }; static struct clk pll0_clk = { @@ -1025,7 +1025,7 @@ static int da850_set_pll0rate(struct clk *clk, unsigned long armrate) static int da850_round_armrate(struct clk *clk, unsigned long rate) { - return clk->rate; + return atomic_read(&clk->rate); } #endif diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index dedf4d4..2244e8c 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -55,7 +55,7 @@ static struct pll_data pll2_data = { static struct clk ref_clk = { .name = "ref_clk", /* FIXME -- crystal rate is board-specific */ - .rate = DM355_REF_FREQ, + .rate = ATOMIC_INIT(DM355_REF_FREQ), }; static struct clk pll1_clk = { @@ -314,7 +314,7 @@ static struct clk timer2_clk = { .name = "timer2", .parent = &pll1_aux_clk, .lpsc = DAVINCI_LPSC_TIMER2, - .usecount = 1, /* REVISIT: why cant' this be disabled? */ + .usecount = ATOMIC_INIT(1), /* REVISIT: why cant' this be disabled? */ }; static struct clk timer3_clk = { diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 2ec619e..cc3bae4 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -52,7 +52,7 @@ static struct pll_data pll2_data = { static struct clk ref_clk = { .name = "ref_clk", - .rate = DM365_REF_FREQ, + .rate = ATOMIC_INIT(DM365_REF_FREQ), }; static struct clk pll1_clk = { @@ -358,7 +358,7 @@ static struct clk timer2_clk = { .name = "timer2", .parent = &pll1_aux_clk, .lpsc = DAVINCI_LPSC_TIMER2, - .usecount = 1, + .usecount = ATOMIC_INIT(1), }; static struct clk timer3_clk = { diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index 2cd0081..e65e29e 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -47,7 +47,7 @@ static struct pll_data pll2_data = { static struct clk ref_clk = { .name = "ref_clk", - .rate = DM644X_REF_FREQ, + .rate = ATOMIC_INIT(DM644X_REF_FREQ), }; static struct clk pll1_clk = { @@ -131,7 +131,7 @@ static struct clk dsp_clk = { .parent = &pll1_sysclk1, .lpsc = DAVINCI_LPSC_GEM, .flags = PSC_DSP, - .usecount = 1, /* REVISIT how to disable? */ + .usecount = ATOMIC_INIT(1), /* REVISIT how to disable? */ }; static struct clk arm_clk = { @@ -146,7 +146,7 @@ static struct clk vicp_clk = { .parent = &pll1_sysclk2, .lpsc = DAVINCI_LPSC_IMCOP, .flags = PSC_DSP, - .usecount = 1, /* REVISIT how to disable? */ + .usecount = ATOMIC_INIT(1), /* REVISIT how to disable? */ }; static struct clk vpss_master_clk = { @@ -274,7 +274,7 @@ static struct clk timer2_clk = { .name = "timer2", .parent = &pll1_aux_clk, .lpsc = DAVINCI_LPSC_TIMER2, - .usecount = 1, /* REVISIT: why cant' this be disabled? */ + .usecount = ATOMIC_INIT(1), /* REVISIT: why cant' this be disabled? */ }; struct davinci_clk dm644x_clks[] = { diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 515d3ed..6f80616 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -60,7 +60,7 @@ static struct clk ref_clk = { static struct clk aux_clkin = { .name = "aux_clkin", - .rate = DM646X_AUX_FREQ, + .rate = ATOMIC_INIT(DM646X_AUX_FREQ), }; static struct clk pll1_clk = { @@ -158,7 +158,7 @@ static struct clk dsp_clk = { .parent = &pll1_sysclk1, .lpsc = DM646X_LPSC_C64X_CPU, .flags = PSC_DSP, - .usecount = 1, /* REVISIT how to disable? */ + .usecount = ATOMIC_INIT(1), /* REVISIT how to disable? */ }; static struct clk arm_clk = { @@ -262,14 +262,14 @@ static struct clk pwm0_clk = { .name = "pwm0", .parent = &pll1_sysclk3, .lpsc = DM646X_LPSC_PWM0, - .usecount = 1, /* REVIST: disabling hangs system */ + .usecount = ATOMIC_INIT(1), /* REVIST: disabling hangs system */ }; static struct clk pwm1_clk = { .name = "pwm1", .parent = &pll1_sysclk3, .lpsc = DM646X_LPSC_PWM1, - .usecount = 1, /* REVIST: disabling hangs system */ + .usecount = ATOMIC_INIT(1), /* REVIST: disabling hangs system */ }; static struct clk timer0_clk = { diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c index adf6b5c..06130df 100644 --- a/arch/arm/mach-davinci/psc.c +++ b/arch/arm/mach-davinci/psc.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -53,6 +54,9 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr, void __iomem *psc_base; struct davinci_soc_info *soc_info = &davinci_soc_info; u32 next_state = enable ? 0x3 : 0x2; /* 0x3 enables, 0x2 disables */ + /* Protect against simultaneous enable/disable of PSCs */ + DEFINE_SPINLOCK(lock); + unsigned long flags; if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) { pr_warning("PSC: Bad psc data: 0x%x[%d]\n", @@ -62,6 +66,7 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr, psc_base = soc_info->psc_bases[ctlr]; + spin_lock_irqsave(&lock, flags); mdctl = __raw_readl(psc_base + MDCTL + 4 * id); mdctl &= ~MDSTAT_STATE_MASK; mdctl |= next_state; @@ -100,4 +105,5 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr, do { mdstat = __raw_readl(psc_base + MDSTAT + 4 * id); } while (!((mdstat & MDSTAT_STATE_MASK) == next_state)); + spin_unlock_irqrestore(&lock, flags); }