From: Paul Walmsley <paul@pwsan.com>
To: linux-omap-open-source@linux.omap.com
Subject: [PATCH 17/22] omap2 clock: Cleanup in clksel-related code; add sys_clkout2 divisor handling
Date: Thu, 02 Aug 2007 12:10:19 -0600 [thread overview]
Message-ID: <20070802181143.242524981@pwsan.com> (raw)
In-Reply-To: 20070802181002.792550043@pwsan.com
[-- Attachment #1: get_clksel_cleanup.patch --]
[-- Type: text/plain, Size: 11242 bytes --]
Convert omap2_get_clksel to use void __iomem *. Add
omap2_divisor_to_clksel(), to convert clock divisors into appropriate
register bit field values. Use non-shifted register bit field masks
in clksel code, rather than masks that have been preshifted down to
bit 0 -- this simplifies existing code and facilitates the use of
symbolic constants from the recent PRCM cleanup. Also add code to
properly handle divisors for sys_clkout2 on OMAP2420. Previously
this clock's divisor settings were ignored.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
---
arch/arm/mach-omap2/clock.c | 192 +++++++++++++++++++++-----------------------
1 file changed, 93 insertions(+), 99 deletions(-)
Index: linux-omap/arch/arm/mach-omap2/clock.c
Index: linux-omap/arch/arm/mach-omap2/clock.c
===================================================================
--- linux-omap.orig/arch/arm/mach-omap2/clock.c
+++ linux-omap/arch/arm/mach-omap2/clock.c
@@ -52,6 +52,8 @@ static struct clk *vclk;
static struct clk *sclk;
static u8 cpu_mask;
+static u32 sysclkout_div[] = {1, 2, 4, 8, 16};
+
/*-------------------------------------------------------------------------
* Omap2 specific clock functions
*-------------------------------------------------------------------------*/
@@ -428,7 +430,6 @@ static u32 omap2_clksel_round_rate(struc
u32 *new_div)
{
u32 gfx_div[] = {2, 3, 4};
- u32 sysclkout_div[] = {1, 2, 4, 8, 16};
u32 dss1_div[] = {1, 2, 3, 4, 5, 6, 8, 9, 12, 16};
u32 vlynq_div[] = {1, 2, 3, 4, 6, 8, 9, 12, 16, 18};
u32 best_div = ~0, asize = 0;
@@ -601,38 +602,50 @@ static long omap2_round_to_table_rate(st
}
/*
- * omap2_convert_field_to_div() - turn field value into integer divider
+ * omap2_clksel_to_divisor() - turn field value into integer divider
*/
static u32 omap2_clksel_to_divisor(u32 div_sel, u32 field_val)
{
u32 i;
- u32 clkout_array[] = {1, 2, 4, 8, 16};
if ((div_sel & SRC_RATE_SEL_MASK) == CM_SYSCLKOUT_SEL1) {
- for (i = 0; i < 5; i++) {
+ for (i = 0; i < ARRAY_SIZE(sysclkout_div); i++) {
if (field_val == i)
- return clkout_array[i];
+ return sysclkout_div[i];
}
- return ~0;
+ return 0;
} else
return field_val;
}
/*
+ * omap2_divisor_to_clksel() - turn integer divider into field value
+ */
+static u32 omap2_divisor_to_clksel(u32 div_sel, u32 div)
+{
+ u32 i;
+
+ if ((div_sel & SRC_RATE_SEL_MASK) == CM_SYSCLKOUT_SEL1) {
+ for (i = 0; i < ARRAY_SIZE(sysclkout_div); i++) {
+ if (div == sysclkout_div[i])
+ return i;
+ }
+ return ~0;
+ } else
+ return div;
+}
+
+/*
* Returns the CLKSEL divider register value
- * REVISIT: This should be cleaned up to work nicely with void __iomem *
*/
-static u32 omap2_get_clksel(u32 *div_sel, u32 *field_mask,
- struct clk *clk)
+static void __iomem *omap2_get_clksel(u32 *field_mask, struct clk *clk)
{
- int ret = ~0;
- u32 reg_val, div_off;
+ u32 div_off, mask = ~0;
void __iomem *div_addr = 0;
- u32 mask = ~0;
div_off = clk->rate_offset;
- switch ((*div_sel & SRC_RATE_SEL_MASK)) {
+ switch (clk->flags & SRC_RATE_SEL_MASK) {
case CM_MPU_SEL1:
div_addr = OMAP_CM_REGADDR(MPU_MOD, CM_CLKSEL);
mask = OMAP24XX_CLKSEL_MPU_MASK;
@@ -696,44 +709,32 @@ static u32 omap2_get_clksel(u32 *div_sel
}
}
- *field_mask = (mask >> div_off);
-
- if (unlikely(mask == ~0))
- div_addr = 0;
-
- *div_sel = (u32)div_addr;
-
- if (unlikely(div_addr == 0))
- return ret;
-
- /* Isolate field */
- reg_val = cm_read_reg(div_addr) & mask;
+ if (unlikely((mask == ~0) || (div_addr == 0)))
+ return 0;
- /* Normalize back to divider value */
- reg_val >>= div_off;
+ *field_mask = mask;
- return reg_val;
+ return div_addr;
}
+
/*
* Return divider to be applied to parent clock.
* Return 0 on error.
*/
static u32 omap2_clksel_get_divisor(struct clk *clk)
{
- int ret = 0;
- u32 div, div_sel, div_off, field_mask, field_val;
+ u32 div, field_mask, field_val;
+ void __iomem *div_addr;
- /* isolate control register */
- div_sel = (SRC_RATE_SEL_MASK & clk->flags);
+ div_addr = omap2_get_clksel(&field_mask, clk);
+ if (div_addr == 0)
+ return 0;
- div_off = clk->rate_offset;
- field_val = omap2_get_clksel(&div_sel, &field_mask, clk);
- if (div_sel == 0)
- return ret;
+ field_val = cm_read_reg(div_addr) & field_mask;
+ field_val >>= clk->rate_offset;
- div_sel = (SRC_RATE_SEL_MASK & clk->flags);
- div = omap2_clksel_to_divisor(div_sel, field_val);
+ div = omap2_clksel_to_divisor(clk->flags, field_val);
return div;
}
@@ -742,53 +743,33 @@ static u32 omap2_clksel_get_divisor(stru
static int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
{
int ret = -EINVAL;
- void __iomem * reg;
- u32 div_sel, div_off, field_mask, field_val, reg_val, validrate;
+ u32 div_off, field_mask, field_val, reg_val, validrate;
u32 new_div = 0;
+ void __iomem *div_addr;
if (!(clk->flags & CONFIG_PARTICIPANT) && (clk->flags & RATE_CKCTL)) {
if (clk == &dpll_ck)
return omap2_reprogram_dpll(clk, rate);
/* Isolate control register */
- div_sel = (SRC_RATE_SEL_MASK & clk->flags);
div_off = clk->rate_offset;
validrate = omap2_clksel_round_rate(clk, rate, &new_div);
if (validrate != rate)
return ret;
- field_val = omap2_get_clksel(&div_sel, &field_mask, clk);
- if (div_sel == 0)
+ div_addr = omap2_get_clksel(&field_mask, clk);
+ if (div_addr == 0)
return ret;
- if (clk->flags & CM_SYSCLKOUT_SEL1) {
- switch (new_div) {
- case 16:
- field_val = 4;
- break;
- case 8:
- field_val = 3;
- break;
- case 4:
- field_val = 2;
- break;
- case 2:
- field_val = 1;
- break;
- case 1:
- field_val = 0;
- break;
- }
- } else
- field_val = new_div;
-
- reg = (void __iomem *)div_sel;
+ field_val = omap2_divisor_to_clksel(clk->flags, new_div);
+ if (field_val == ~0)
+ return ret;
- reg_val = cm_read_reg(reg);
- reg_val &= ~(field_mask << div_off);
+ reg_val = cm_read_reg(div_addr);
+ reg_val &= ~field_mask;
reg_val |= (field_val << div_off);
- cm_write_reg(reg_val, reg);
+ cm_write_reg(reg_val, div_addr);
wmb();
clk->rate = clk->parent->rate / new_div;
@@ -809,26 +790,28 @@ static int omap2_clk_set_rate(struct clk
}
/* Converts encoded control register address into a full address */
-static u32 omap2_get_src_field(u32 *type_to_addr, u32 reg_offset,
- struct clk *src_clk, u32 *field_mask)
+static u32 omap2_clksel_get_src_field(void __iomem **src_addr,
+ struct clk *src_clk, u32 *field_mask,
+ struct clk *clk)
{
u32 val = ~0, mask = 0;
void __iomem *src_reg_addr = 0;
+ u32 reg_offset;
+
+ reg_offset = clk->src_offset;
/* Find target control register.*/
- switch ((*type_to_addr & SRC_RATE_SEL_MASK)) {
+ switch (clk->flags & SRC_RATE_SEL_MASK) {
case CM_CORE_SEL1:
src_reg_addr = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL1);
if (reg_offset == OMAP24XX_CLKSEL_DSS2_SHIFT) {
mask = OMAP24XX_CLKSEL_DSS2_MASK;
- mask >>= OMAP24XX_CLKSEL_DSS2_SHIFT;
if (src_clk == &sys_ck)
val = 0;
if (src_clk == &func_48m_ck)
val = 1;
} else if (reg_offset == OMAP24XX_CLKSEL_DSS1_SHIFT) {
mask = OMAP24XX_CLKSEL_DSS1_MASK;
- mask >>= OMAP24XX_CLKSEL_DSS1_SHIFT;
if (src_clk == &sys_ck)
val = 0;
else if (src_clk == &core_ck) /* divided clock */
@@ -836,16 +819,20 @@ static u32 omap2_get_src_field(u32 *type
} else if ((reg_offset == OMAP2420_CLKSEL_VLYNQ_SHIFT) &&
cpu_is_omap2420()) {
mask = OMAP2420_CLKSEL_VLYNQ_MASK;
- mask >>= OMAP2420_CLKSEL_VLYNQ_SHIFT;
if (src_clk == &func_96m_ck)
val = 0;
else if (src_clk == &core_ck)
val = 0x10; /* rate needs fixing */
+ } else {
+ WARN_ON(1); /* unknown reg_offset */
}
break;
case CM_CORE_SEL2:
+ WARN_ON(reg_offset < OMAP24XX_CLKSEL_GPT2_SHIFT ||
+ reg_offset > OMAP24XX_CLKSEL_GPT12_SHIFT);
src_reg_addr = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL2);
- mask = 0x3;
+ mask = OMAP24XX_CLKSEL_GPT2_MASK;
+ mask <<= (reg_offset - OMAP24XX_CLKSEL_GPT2_SHIFT);
if (src_clk == &func_32k_ck)
val = 0x0;
if (src_clk == &sys_ck)
@@ -854,8 +841,9 @@ static u32 omap2_get_src_field(u32 *type
val = 0x2;
break;
case CM_WKUP_SEL1:
+ WARN_ON(reg_offset != 0); /* unknown reg_offset */
src_reg_addr = OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL);
- mask = 0x3;
+ mask = OMAP24XX_CLKSEL_GPT1_MASK;
if (src_clk == &func_32k_ck)
val = 0x0;
if (src_clk == &sys_ck)
@@ -865,23 +853,27 @@ static u32 omap2_get_src_field(u32 *type
break;
case CM_PLL_SEL1:
src_reg_addr = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1);
- mask = 0x1;
if (reg_offset == 0x3) {
+ mask = OMAP24XX_48M_SOURCE;
if (src_clk == &apll96_ck)
val = 0;
if (src_clk == &alt_ck)
val = 1;
}
else if (reg_offset == 0x5) {
+ mask = OMAP24XX_54M_SOURCE;
if (src_clk == &apll54_ck)
val = 0;
if (src_clk == &alt_ck)
val = 1;
+ } else {
+ WARN_ON(1); /* unknown reg_offset */
}
break;
case CM_PLL_SEL2:
+ WARN_ON(reg_offset != 0);
src_reg_addr = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2);
- mask = 0x3;
+ mask = OMAP24XX_CORE_CLK_SRC_MASK;
if (src_clk == &func_32k_ck)
val = 0x0;
if (src_clk == &dpll_ck)
@@ -889,7 +881,15 @@ static u32 omap2_get_src_field(u32 *type
break;
case CM_SYSCLKOUT_SEL1:
src_reg_addr = OMAP24XX_PRCM_CLKOUT_CTRL;
- mask = 0x3;
+
+ if (reg_offset == OMAP24XX_CLKOUT_SOURCE_SHIFT) {
+ mask = OMAP24XX_CLKOUT_SOURCE_MASK;
+ } else if (reg_offset == OMAP2420_CLKOUT2_SOURCE_SHIFT) {
+ mask = OMAP2420_CLKOUT2_SOURCE_MASK;
+ } else {
+ WARN_ON(1); /* unknown reg_offset */
+ }
+
if (src_clk == &dpll_ck)
val = 0;
if (src_clk == &sys_ck)
@@ -902,9 +902,10 @@ static u32 omap2_get_src_field(u32 *type
}
if (val == ~0) /* Catch errors in offset */
- *type_to_addr = 0;
+ *src_addr = 0;
else
- *type_to_addr = (u32)src_reg_addr;
+ *src_addr = src_reg_addr;
+
*field_mask = mask;
return val;
@@ -912,34 +913,27 @@ static u32 omap2_get_src_field(u32 *type
static int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
{
- void __iomem * reg;
- u32 src_sel, src_off, field_val, field_mask, reg_val;
- int ret = -EINVAL;
+ void __iomem *src_addr;
+ u32 field_val, field_mask, reg_val;
if (unlikely(clk->flags & CONFIG_PARTICIPANT))
- return ret;
+ return -EINVAL;
if (unlikely(!(clk->flags & SRC_SEL_MASK)))
- return ret;
-
- src_sel = (SRC_RATE_SEL_MASK & clk->flags);
- src_off = clk->src_offset;
-
- if (src_sel == 0)
- return ret;
-
- field_val = omap2_get_src_field(&src_sel, src_off, new_parent,
- &field_mask);
+ return -EINVAL;
- reg = (void __iomem *)src_sel;
+ field_val = omap2_clksel_get_src_field(&src_addr, new_parent,
+ &field_mask, clk);
+ if (src_addr == 0)
+ return -EINVAL;
if (clk->usecount > 0)
_omap2_clk_disable(clk);
/* Set new source value (previous dividers if any in effect) */
- reg_val = __raw_readl(reg) & ~(field_mask << src_off);
- reg_val |= (field_val << src_off);
- __raw_writel(reg_val, reg);
+ reg_val = __raw_readl(src_addr) & ~field_mask;
+ reg_val |= (field_val << clk->src_offset);
+ __raw_writel(reg_val, src_addr);
wmb();
if (clk->flags & DELAYED_APP) {
--
next prev parent reply other threads:[~2007-08-02 18:10 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-08-02 18:10 [PATCH 00/22] omap2 clock: Bugfixes and cleanups in OMAP2 clock framework Paul Walmsley
2007-08-02 18:10 ` [PATCH 01/22] omap2 clock: drop meaningless RATE_CKCTLs Paul Walmsley
2007-08-02 18:10 ` [PATCH 02/22] omap2 clock: fix incorrect rate calculation for osc_ck, sys_ck Paul Walmsley
2007-08-10 21:08 ` [PATCH 02/22 - Reverse] omap2 osc & sys clock calculation Woodruff, Richard
2007-08-13 7:03 ` Tony Lindgren
2007-08-02 18:10 ` [PATCH 03/22] omap2 clock: fix clksel divisor bug Paul Walmsley
2007-08-02 18:10 ` [PATCH 04/22] omap2 clock: vlynq_fck recalc should be clksel, not followparent Paul Walmsley
2007-08-02 18:10 ` [PATCH 05/22] omap2 clock: fix CodingStyle issues Paul Walmsley
2007-08-02 18:10 ` [PATCH 06/22] omap2 clock: drop unnecessary variable in omap2_clk_round_rate() Paul Walmsley
2007-08-02 18:10 ` [PATCH 07/22] omap2 clock: get rid of sleep_ck Paul Walmsley
2007-08-02 18:10 ` [PATCH 08/22] omap2 clock: clean up dss2_fck clock flags Paul Walmsley
2007-08-02 18:10 ` [PATCH 09/22] omap2 clock: move SDRC-related code from clock.c to memory.c Paul Walmsley
2007-08-02 18:10 ` [PATCH 10/22] omap2 clock: use symbolic constants in clock.h rate_offset/src_offset fields Paul Walmsley
2007-08-02 18:10 ` [PATCH 11/22] omap2 clock: fix some clocks incorrectly marked as present on OMAP2430 Paul Walmsley
2007-08-02 18:45 ` [PATCH 11/22] omap2 clock: fix some clocks incorrectly marked aspresent " Woodruff, Richard
2007-08-02 19:05 ` Woodruff, Richard
2007-08-03 18:09 ` Paul Walmsley
2007-08-03 18:47 ` Woodruff, Richard
2007-08-04 15:56 ` Paul Walmsley
2007-08-04 22:02 ` Woodruff, Richard
2007-08-10 9:43 ` Tony Lindgren
2007-08-02 18:10 ` [PATCH 12/22] omap2 clock: vlynq_fck is missing clksel divider code Paul Walmsley
2007-08-02 18:10 ` [PATCH 13/22] omap2 clock: convert PARENT_CONTROLS_CLOCK into a clock flag Paul Walmsley
2007-08-02 18:10 ` [PATCH 14/22] omap2 clock: omap2 clock.c: Consolidate wait-for-lock code Paul Walmsley
2007-08-02 18:10 ` [PATCH 15/22] omap2 clock: return -EINVAL if no clock enable code; fix dpll_ck enable Paul Walmsley
2007-08-02 18:10 ` [PATCH 16/22] omap2 clock: From: Paul Walmsley <paul@pwsan.com> Subject: Paul Walmsley
2007-08-02 18:10 ` Paul Walmsley [this message]
2007-08-02 18:10 ` [PATCH 18/22] omap2 clock: Use symbolic constants in clock.c Paul Walmsley
2007-08-02 18:10 ` [PATCH 19/22] omap2 clock: use dedicated omap2_dpll_recalc() for DPLL recalc func Paul Walmsley
2007-08-02 18:10 ` [PATCH 20/22] omap2 clock: add fixed divisor clock code Paul Walmsley
2007-08-02 18:10 ` [PATCH 21/22] omap2 clock: remove fixed rate from mdm_osc_ck Paul Walmsley
2007-08-02 18:10 ` [PATCH 22/22] omap2 clock: get rid of omap2_followparent_recalc() Paul Walmsley
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070802181143.242524981@pwsan.com \
--to=paul@pwsan.com \
--cc=linux-omap-open-source@linux.omap.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox