[PATCH] wip: convert imx27 to common struct clk
Uwe Kleine-König
u.kleine-koenig at pengutronix.de
Tue Feb 22 18:33:19 EST 2011
Signed-off-by: Uwe Kleine-König <u.kleine-koenig at pengutronix.de>
---
Hello,
on top of .38-rc6 + making the clk_{un,}prepare stubs static inline,
this patch makes use of Jeremy's common struct clk (v13) on a i.MX27 based
machine.
This is compile tested using mx21_defconfig and runtime tested using
mx27_defconfig.
I had to degrade one WARN_ON to WARN_ON_ONCE in drivers/clk/clk.c to
actually make it work. Otherwise console output results in a warning
that results in console output ...
Best regards
Uwe
arch/arm/mach-imx/Kconfig | 1 +
arch/arm/mach-imx/clock-imx27.c | 186 ++++++++++++++++--------------
arch/arm/plat-mxc/clock.c | 127 +++++++++++++++++++++
arch/arm/plat-mxc/include/mach/clkdev.h | 4 +
arch/arm/plat-mxc/include/mach/clock.h | 32 ++++--
drivers/clk/clk.c | 2 +-
6 files changed, 255 insertions(+), 97 deletions(-)
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 56684b5..f2d3708 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -30,6 +30,7 @@ config SOC_IMX27
select IMX_HAVE_DMA_V1
select IMX_HAVE_IOMUX_V1
select MXC_AVIC
+ select USE_COMMON_STRUCT_CLK
if ARCH_MX1
diff --git a/arch/arm/mach-imx/clock-imx27.c b/arch/arm/mach-imx/clock-imx27.c
index 583f251..f413f7b 100644
--- a/arch/arm/mach-imx/clock-imx27.c
+++ b/arch/arm/mach-imx/clock-imx27.c
@@ -68,35 +68,35 @@
#define CCM_SPCTL1_LF (1 << 15)
#define CCM_SPCTL1_BRMO (1 << 6)
-static struct clk mpll_main1_clk, mpll_main2_clk;
+static struct clk_mxc mpll_main1_clk, mpll_main2_clk;
-static int clk_pccr_enable(struct clk *clk)
+static int clk_pccr_enable(struct clk_mxc *clk_mxc)
{
unsigned long reg;
- if (!clk->enable_reg)
+ if (!clk_mxc->enable_reg)
return 0;
- reg = __raw_readl(clk->enable_reg);
- reg |= 1 << clk->enable_shift;
- __raw_writel(reg, clk->enable_reg);
+ reg = __raw_readl(clk_mxc->enable_reg);
+ reg |= 1 << clk_mxc->enable_shift;
+ __raw_writel(reg, clk_mxc->enable_reg);
return 0;
}
-static void clk_pccr_disable(struct clk *clk)
+static void clk_pccr_disable(struct clk_mxc *clk_mxc)
{
unsigned long reg;
- if (!clk->enable_reg)
+ if (!clk_mxc->enable_reg)
return;
- reg = __raw_readl(clk->enable_reg);
- reg &= ~(1 << clk->enable_shift);
- __raw_writel(reg, clk->enable_reg);
+ reg = __raw_readl(clk_mxc->enable_reg);
+ reg &= ~(1 << clk_mxc->enable_shift);
+ __raw_writel(reg, clk_mxc->enable_reg);
}
-static int clk_spll_enable(struct clk *clk)
+static int clk_spll_enable(struct clk_mxc *clk_mxc)
{
unsigned long reg;
@@ -109,7 +109,7 @@ static int clk_spll_enable(struct clk *clk)
return 0;
}
-static void clk_spll_disable(struct clk *clk)
+static void clk_spll_disable(struct clk_mxc *clk_mxc)
{
unsigned long reg;
@@ -118,11 +118,11 @@ static void clk_spll_disable(struct clk *clk)
__raw_writel(reg, CCM_CSCR);
}
-static int clk_cpu_set_parent(struct clk *clk, struct clk *parent)
+static int clk_cpu_set_parent(struct clk_mxc *clk_mxc, struct clk_mxc *parent)
{
int cscr = __raw_readl(CCM_CSCR);
- if (clk->parent == parent)
+ if (clk_mxc->parent == parent)
return 0;
if (mx27_revision() >= IMX_CHIP_REVISION_2_0) {
@@ -135,18 +135,18 @@ static int clk_cpu_set_parent(struct clk *clk, struct clk *parent)
return -EINVAL;
}
__raw_writel(cscr, CCM_CSCR);
- clk->parent = parent;
+ clk_mxc->parent = parent;
return 0;
}
return -ENODEV;
}
-static unsigned long round_rate_cpu(struct clk *clk, unsigned long rate)
+static unsigned long round_rate_cpu(struct clk_mxc *clk_mxc, unsigned long rate)
{
int div;
unsigned long parent_rate;
- parent_rate = clk_get_rate(clk->parent);
+ parent_rate = clk_get_rate(&clk_mxc->parent->clk);
div = parent_rate / rate;
if (parent_rate % rate)
@@ -158,13 +158,13 @@ static unsigned long round_rate_cpu(struct clk *clk, unsigned long rate)
return parent_rate / div;
}
-static int set_rate_cpu(struct clk *clk, unsigned long rate)
+static int set_rate_cpu(struct clk_mxc *clk_mxc, unsigned long rate)
{
unsigned int div;
uint32_t reg;
unsigned long parent_rate;
- parent_rate = clk_get_rate(clk->parent);
+ parent_rate = clk_get_rate(&clk_mxc->parent->clk);
div = parent_rate / rate;
@@ -186,12 +186,12 @@ static int set_rate_cpu(struct clk *clk, unsigned long rate)
return 0;
}
-static unsigned long round_rate_per(struct clk *clk, unsigned long rate)
+static unsigned long round_rate_per(struct clk_mxc *clk_mxc, unsigned long rate)
{
u32 div;
unsigned long parent_rate;
- parent_rate = clk_get_rate(clk->parent);
+ parent_rate = clk_get_rate(&clk_mxc->parent->clk);
div = parent_rate / rate;
if (parent_rate % rate)
@@ -203,15 +203,15 @@ static unsigned long round_rate_per(struct clk *clk, unsigned long rate)
return parent_rate / div;
}
-static int set_rate_per(struct clk *clk, unsigned long rate)
+static int set_rate_per(struct clk_mxc *clk_mxc, unsigned long rate)
{
u32 reg;
u32 div;
unsigned long parent_rate;
- parent_rate = clk_get_rate(clk->parent);
+ parent_rate = clk_get_rate(&clk_mxc->parent->clk);
- if (clk->id < 0 || clk->id > 3)
+ if (clk_mxc->id < 0 || clk_mxc->id > 3)
return -EINVAL;
div = parent_rate / rate;
@@ -219,30 +219,30 @@ static int set_rate_per(struct clk *clk, unsigned long rate)
return -EINVAL;
div--;
- reg = __raw_readl(CCM_PCDR1) & ~(0x3f << (clk->id << 3));
- reg |= div << (clk->id << 3);
+ reg = __raw_readl(CCM_PCDR1) & ~(0x3f << (clk_mxc->id << 3));
+ reg |= div << (clk_mxc->id << 3);
__raw_writel(reg, CCM_PCDR1);
return 0;
}
-static unsigned long get_rate_usb(struct clk *clk)
+static unsigned long get_rate_usb(struct clk_mxc *clk_mxc)
{
unsigned long usb_pdf;
unsigned long parent_rate;
- parent_rate = clk_get_rate(clk->parent);
+ parent_rate = clk_get_rate(&clk_mxc->parent->clk);
usb_pdf = (__raw_readl(CCM_CSCR) >> 28) & 0x7;
return parent_rate / (usb_pdf + 1U);
}
-static unsigned long get_rate_ssix(struct clk *clk, unsigned long pdf)
+static unsigned long get_rate_ssix(struct clk_mxc *clk_mxc, unsigned long pdf)
{
unsigned long parent_rate;
- parent_rate = clk_get_rate(clk->parent);
+ parent_rate = clk_get_rate(&clk_mxc->parent->clk);
if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
pdf += 4; /* MX27 TO2+ */
@@ -252,22 +252,22 @@ static unsigned long get_rate_ssix(struct clk *clk, unsigned long pdf)
return 2UL * parent_rate / pdf;
}
-static unsigned long get_rate_ssi1(struct clk *clk)
+static unsigned long get_rate_ssi1(struct clk_mxc *clk_mxc)
{
- return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 16) & 0x3f);
+ return get_rate_ssix(clk_mxc, (__raw_readl(CCM_PCDR0) >> 16) & 0x3f);
}
-static unsigned long get_rate_ssi2(struct clk *clk)
+static unsigned long get_rate_ssi2(struct clk_mxc *clk_mxc)
{
- return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 26) & 0x3f);
+ return get_rate_ssix(clk_mxc, (__raw_readl(CCM_PCDR0) >> 26) & 0x3f);
}
-static unsigned long get_rate_nfc(struct clk *clk)
+static unsigned long get_rate_nfc(struct clk_mxc *clk_mxc)
{
unsigned long nfc_pdf;
unsigned long parent_rate;
- parent_rate = clk_get_rate(clk->parent);
+ parent_rate = clk_get_rate(&clk_mxc->parent->clk);
if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
nfc_pdf = (__raw_readl(CCM_PCDR0) >> 6) & 0xf;
@@ -277,12 +277,12 @@ static unsigned long get_rate_nfc(struct clk *clk)
return parent_rate / (nfc_pdf + 1);
}
-static unsigned long get_rate_vpu(struct clk *clk)
+static unsigned long get_rate_vpu(struct clk_mxc *clk_mxc)
{
unsigned long vpu_pdf;
unsigned long parent_rate;
- parent_rate = clk_get_rate(clk->parent);
+ parent_rate = clk_get_rate(&clk_mxc->parent->clk);
if (mx27_revision() >= IMX_CHIP_REVISION_2_0) {
vpu_pdf = (__raw_readl(CCM_PCDR0) >> 10) & 0x3f;
@@ -295,25 +295,25 @@ static unsigned long get_rate_vpu(struct clk *clk)
return 2UL * parent_rate / vpu_pdf;
}
-static unsigned long round_rate_parent(struct clk *clk, unsigned long rate)
+static unsigned long round_rate_parent(struct clk_mxc *clk_mxc, unsigned long rate)
{
- return clk->parent->round_rate(clk->parent, rate);
+ return clk_round_rate(&clk_mxc->parent->clk, rate);
}
-static unsigned long get_rate_parent(struct clk *clk)
+static unsigned long get_rate_parent(struct clk_mxc *clk_mxc)
{
- return clk_get_rate(clk->parent);
+ return clk_get_rate(&clk_mxc->parent->clk);
}
-static int set_rate_parent(struct clk *clk, unsigned long rate)
+static int set_rate_parent(struct clk_mxc *clk_mxc, unsigned long rate)
{
- return clk->parent->set_rate(clk->parent, rate);
+ return clk_set_rate(&clk_mxc->parent->clk, rate);
}
/* in Hz */
static unsigned long external_high_reference = 26000000;
-static unsigned long get_rate_high_reference(struct clk *clk)
+static unsigned long get_rate_high_reference(struct clk_mxc *clk)
{
return external_high_reference;
}
@@ -321,44 +321,44 @@ static unsigned long get_rate_high_reference(struct clk *clk)
/* in Hz */
static unsigned long external_low_reference = 32768;
-static unsigned long get_rate_low_reference(struct clk *clk)
+static unsigned long get_rate_low_reference(struct clk_mxc *clk_mxc)
{
return external_low_reference;
}
-static unsigned long get_rate_fpm(struct clk *clk)
+static unsigned long get_rate_fpm(struct clk_mxc *clk_mxc)
{
- return clk_get_rate(clk->parent) * 1024;
+ return clk_get_rate(&clk_mxc->parent->clk) * 1024;
}
-static unsigned long get_rate_mpll(struct clk *clk)
+static unsigned long get_rate_mpll(struct clk_mxc *clk_mxc)
{
return mxc_decode_pll(__raw_readl(CCM_MPCTL0),
- clk_get_rate(clk->parent));
+ clk_get_rate(&clk_mxc->parent->clk));
}
-static unsigned long get_rate_mpll_main(struct clk *clk)
+static unsigned long get_rate_mpll_main(struct clk_mxc *clk_mxc)
{
unsigned long parent_rate;
- parent_rate = clk_get_rate(clk->parent);
+ parent_rate = clk_get_rate(&clk_mxc->parent->clk);
/* i.MX27 TO2:
* clk->id == 0: arm clock source path 1 which is from 2 * MPLL / 2
* clk->id == 1: arm clock source path 2 which is from 2 * MPLL / 3
*/
- if (mx27_revision() >= IMX_CHIP_REVISION_2_0 && clk->id == 1)
+ if (mx27_revision() >= IMX_CHIP_REVISION_2_0 && clk_mxc->id == 1)
return 2UL * parent_rate / 3UL;
return parent_rate;
}
-static unsigned long get_rate_spll(struct clk *clk)
+static unsigned long get_rate_spll(struct clk_mxc *clk_mxc)
{
uint32_t reg;
unsigned long rate;
- rate = clk_get_rate(clk->parent);
+ rate = clk_get_rate(&clk_mxc->parent->clk);
reg = __raw_readl(CCM_SPCTL0);
@@ -371,7 +371,7 @@ static unsigned long get_rate_spll(struct clk *clk)
return mxc_decode_pll(reg, rate);
}
-static unsigned long get_rate_cpu(struct clk *clk)
+static unsigned long get_rate_cpu(struct clk_mxc *clk_mxc)
{
u32 div;
unsigned long rate;
@@ -381,11 +381,11 @@ static unsigned long get_rate_cpu(struct clk *clk)
else
div = (__raw_readl(CCM_CSCR) >> 13) & 0x7;
- rate = clk_get_rate(clk->parent);
+ rate = clk_get_rate(&clk_mxc->parent->clk);
return rate / (div + 1);
}
-static unsigned long get_rate_ahb(struct clk *clk)
+static unsigned long get_rate_ahb(struct clk_mxc *clk_mxc)
{
unsigned long rate, bclk_pdf;
@@ -394,33 +394,33 @@ static unsigned long get_rate_ahb(struct clk *clk)
else
bclk_pdf = (__raw_readl(CCM_CSCR) >> 9) & 0xf;
- rate = clk_get_rate(clk->parent);
+ rate = clk_get_rate(&clk_mxc->parent->clk);
return rate / (bclk_pdf + 1);
}
-static unsigned long get_rate_ipg(struct clk *clk)
+static unsigned long get_rate_ipg(struct clk_mxc *clk_mxc)
{
unsigned long rate, ipg_pdf;
if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
- return clk_get_rate(clk->parent);
+ return clk_get_rate(&clk_mxc->parent->clk);
else
ipg_pdf = (__raw_readl(CCM_CSCR) >> 8) & 1;
- rate = clk_get_rate(clk->parent);
+ rate = clk_get_rate(&clk_mxc->parent->clk);
return rate / (ipg_pdf + 1);
}
-static unsigned long get_rate_per(struct clk *clk)
+static unsigned long get_rate_per(struct clk_mxc *clk_mxc)
{
unsigned long perclk_pdf, parent_rate;
- parent_rate = clk_get_rate(clk->parent);
+ parent_rate = clk_get_rate(&clk_mxc->parent->clk);
- if (clk->id < 0 || clk->id > 3)
+ if (clk_mxc->id < 0 || clk_mxc->id > 3)
return 0;
- perclk_pdf = (__raw_readl(CCM_PCDR1) >> (clk->id << 3)) & 0x3f;
+ perclk_pdf = (__raw_readl(CCM_PCDR1) >> (clk_mxc->id << 3)) & 0x3f;
return parent_rate / (perclk_pdf + 1);
}
@@ -430,11 +430,13 @@ static unsigned long get_rate_per(struct clk *clk)
* Default case is 26MHz. Could be changed at runtime
* with a call to change_external_high_reference()
*/
-static struct clk ckih_clk = {
+static struct clk_mxc ckih_clk = {
+ .clk = INIT_CLK_MXC(ckih_clk),
.get_rate = get_rate_high_reference,
};
-static struct clk mpll_clk = {
+static struct clk_mxc mpll_clk = {
+ .clk = INIT_CLK_MXC(mpll_clk),
.parent = &ckih_clk,
.get_rate = get_rate_mpll,
};
@@ -442,7 +444,8 @@ static struct clk mpll_clk = {
/* For i.MX27 TO2, it is the MPLL path 1 of ARM core
* It provides the clock source whose rate is same as MPLL
*/
-static struct clk mpll_main1_clk = {
+static struct clk_mxc mpll_main1_clk = {
+ .clk = INIT_CLK_MXC(mpll_main1_clk),
.id = 0,
.parent = &mpll_clk,
.get_rate = get_rate_mpll_main,
@@ -451,23 +454,27 @@ static struct clk mpll_main1_clk = {
/* For i.MX27 TO2, it is the MPLL path 2 of ARM core
* It provides the clock source whose rate is same MPLL * 2 / 3
*/
-static struct clk mpll_main2_clk = {
+static struct clk_mxc mpll_main2_clk = {
+ .clk = INIT_CLK_MXC(mpll_main2_clk),
.id = 1,
.parent = &mpll_clk,
.get_rate = get_rate_mpll_main,
};
-static struct clk ahb_clk = {
+static struct clk_mxc ahb_clk = {
+ .clk = INIT_CLK_MXC(ahb_clk),
.parent = &mpll_main2_clk,
.get_rate = get_rate_ahb,
};
-static struct clk ipg_clk = {
+static struct clk_mxc ipg_clk = {
+ .clk = INIT_CLK_MXC(ipg_clk),
.parent = &ahb_clk,
.get_rate = get_rate_ipg,
};
-static struct clk cpu_clk = {
+static struct clk_mxc cpu_clk = {
+ .clk = INIT_CLK_MXC(cpu_clk),
.parent = &mpll_main2_clk,
.set_parent = clk_cpu_set_parent,
.round_rate = round_rate_cpu,
@@ -475,7 +482,8 @@ static struct clk cpu_clk = {
.set_rate = set_rate_cpu,
};
-static struct clk spll_clk = {
+static struct clk_mxc spll_clk = {
+ .clk = INIT_CLK_MXC(spll_clk),
.parent = &ckih_clk,
.get_rate = get_rate_spll,
.enable = clk_spll_enable,
@@ -486,12 +494,14 @@ static struct clk spll_clk = {
* the low frequency external clock reference
* Default case is 32.768kHz.
*/
-static struct clk ckil_clk = {
+static struct clk_mxc ckil_clk = {
+ .clk = INIT_CLK_MXC(ckil_clk),
.get_rate = get_rate_low_reference,
};
/* Output of frequency pre multiplier */
-static struct clk fpm_clk = {
+static struct clk_mxc fpm_clk = {
+ .clk = INIT_CLK_MXC(fpm_clk),
.parent = &ckil_clk,
.get_rate = get_rate_fpm,
};
@@ -500,7 +510,8 @@ static struct clk fpm_clk = {
#define PCCR1 CCM_PCCR1
#define DEFINE_CLOCK(name, i, er, es, gr, s, p) \
- static struct clk name = { \
+ static struct clk_mxc name = { \
+ .clk = INIT_CLK_MXC(name), \
.id = i, \
.enable_reg = er, \
.enable_shift = es, \
@@ -512,7 +523,8 @@ static struct clk fpm_clk = {
}
#define DEFINE_CLOCK1(name, i, er, es, getsetround, s, p) \
- static struct clk name = { \
+ static struct clk_mxc name = { \
+ .clk = INIT_CLK_MXC(name), \
.id = i, \
.enable_reg = er, \
.enable_shift = es, \
@@ -526,7 +538,7 @@ static struct clk fpm_clk = {
}
/* Forward declaration to keep the following list in order */
-static struct clk slcdc_clk1, sahara2_clk1, rtic_clk1, fec_clk1, emma_clk1,
+static struct clk_mxc slcdc_clk1, sahara2_clk1, rtic_clk1, fec_clk1, emma_clk1,
dma_clk1, lcdc_clk2, vpu_clk1;
/* All clocks we can gate through PCCRx in the order of PCCRx bits */
@@ -620,7 +632,7 @@ DEFINE_CLOCK1(csi_clk, 0, NULL, 0, parent, &csi_clk1, &per4_clk);
{ \
.dev_id = d, \
.con_id = n, \
- .clk = &c, \
+ .clk = &c.clk, \
},
static struct clk_lookup lookups[] = {
@@ -746,16 +758,16 @@ int __init mx27_clocks_init(unsigned long fref)
spll_clk.disable(&spll_clk);
/* enable basic clocks */
- clk_enable(&per1_clk);
- clk_enable(&gpio_clk);
- clk_enable(&emi_clk);
- clk_enable(&iim_clk);
+ clk_enable(&per1_clk.clk);
+ clk_enable(&gpio_clk.clk);
+ clk_enable(&emi_clk.clk);
+ clk_enable(&iim_clk.clk);
#if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC)
- clk_enable(&uart1_clk);
+ clk_enable(&uart1_clk.clk);
#endif
- mxc_timer_init(&gpt1_clk, MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR),
+ mxc_timer_init(&gpt1_clk.clk, MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR),
MX27_INT_GPT1);
return 0;
diff --git a/arch/arm/plat-mxc/clock.c b/arch/arm/plat-mxc/clock.c
index 2ed3ab1..3fc75dd 100644
--- a/arch/arm/plat-mxc/clock.c
+++ b/arch/arm/plat-mxc/clock.c
@@ -44,6 +44,131 @@
static LIST_HEAD(clocks);
static DEFINE_MUTEX(clocks_mutex);
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+static int clk_mxc_enable(struct clk *clk)
+{
+ struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+ int ret = 0;
+
+ if (clk_mxc->parent)
+ ret = clk_enable(&clk_mxc->parent->clk);
+
+ if (!ret && clk_mxc->secondary)
+ ret = clk_enable(&clk_mxc->secondary->clk);
+
+ if (!ret && clk_mxc->enable)
+ ret = clk_mxc->enable(clk_mxc);
+
+ return ret;
+}
+
+static void clk_mxc_disable(struct clk *clk)
+{
+ struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+
+ if (clk_mxc->disable)
+ clk_mxc->disable(clk_mxc);
+
+ if (clk_mxc->secondary)
+ clk_disable(&clk_mxc->secondary->clk);
+
+ if (clk_mxc->parent)
+ clk_disable(&clk_mxc->parent->clk);
+}
+
+static unsigned long clk_mxc_get_rate(struct clk *clk)
+{
+ struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+
+ if (clk_mxc->get_rate)
+ return clk_mxc->get_rate(clk_mxc);
+ else if (clk_mxc->parent)
+ return clk_get_rate(&clk_mxc->parent->clk);
+ else
+ return 0UL;
+}
+
+static long clk_mxc_round_rate(struct clk *clk, unsigned long rate)
+{
+ struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+
+ if (clk_mxc->round_rate)
+ return clk_mxc->round_rate(clk_mxc, rate);
+
+ return 0L;
+}
+
+static int clk_mxc_set_rate(struct clk *clk, unsigned long rate)
+{
+ struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+ int ret = -EINVAL;
+
+ if (clk_mxc->set_rate && rate != 0)
+ ret = clk_mxc->set_rate(clk_mxc, rate);
+
+ return ret;
+}
+
+static int clk_mxc_set_parent(struct clk *clk, struct clk *parent)
+{
+ struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+ struct clk *old_parent = parent;
+ struct clk_mxc *parent_mxc = to_clk_mxc(parent);
+ int ret;
+
+ if (!clk_mxc->set_parent)
+ return -EINVAL;
+
+ if (clk->prepare_count) {
+ ret = clk_prepare(parent);
+ if (ret)
+ goto err_prepare_parent;
+ }
+
+ if (clk->enable_count) {
+ ret = clk_enable(parent);
+ if (ret)
+ goto err_enable_parent;
+ }
+
+ ret = clk_mxc->set_parent(clk_mxc, parent_mxc);
+ if (ret == 0) {
+ old_parent = &clk_mxc->parent->clk;
+ clk_mxc->parent = to_clk_mxc(parent);
+ }
+
+ if (clk->enable_count)
+ clk_disable(old_parent);
+err_enable_parent:
+
+ if (clk->prepare_count)
+ clk_unprepare(old_parent);
+err_prepare_parent:
+
+ return ret;
+}
+
+static struct clk *clk_mxc_get_parent(struct clk *clk)
+{
+ struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+
+ if (clk_mxc->parent)
+ return &clk_mxc->parent->clk;
+
+ return NULL;
+}
+
+const struct clk_ops clk_mxc_ops = {
+ .enable = clk_mxc_enable,
+ .disable = clk_mxc_disable,
+ .get_rate = clk_mxc_get_rate,
+ .round_rate = clk_mxc_round_rate,
+ .set_rate = clk_mxc_set_rate,
+ .set_parent = clk_mxc_set_parent,
+ .get_parent = clk_mxc_get_parent,
+};
+#else
+
/*-------------------------------------------------------------------------
* Standard clock functions defined in include/linux/clk.h
*-------------------------------------------------------------------------*/
@@ -200,6 +325,8 @@ struct clk *clk_get_parent(struct clk *clk)
}
EXPORT_SYMBOL(clk_get_parent);
+#endif
+
/*
* Get the resulting clock rate from a PLL register value and the input
* frequency. PLLs with this register layout can at least be found on
diff --git a/arch/arm/plat-mxc/include/mach/clkdev.h b/arch/arm/plat-mxc/include/mach/clkdev.h
index 04b37a8..f663af3 100644
--- a/arch/arm/plat-mxc/include/mach/clkdev.h
+++ b/arch/arm/plat-mxc/include/mach/clkdev.h
@@ -1,7 +1,11 @@
#ifndef __ASM_MACH_CLKDEV_H
#define __ASM_MACH_CLKDEV_H
+#ifndef CONFIG_USE_COMMON_STRUCT_CLK
+
#define __clk_get(clk) ({ 1; })
#define __clk_put(clk) do { } while (0)
#endif
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/clock.h b/arch/arm/plat-mxc/include/mach/clock.h
index 753a598..d8efa77 100644
--- a/arch/arm/plat-mxc/include/mach/clock.h
+++ b/arch/arm/plat-mxc/include/mach/clock.h
@@ -23,14 +23,24 @@
#ifndef __ASSEMBLY__
#include <linux/list.h>
+#include <linux/clk.h>
+
struct module;
-struct clk {
+#ifndef CONFIG_USE_COMMON_STRUCT_CLK
+#define clk_mxc clk
+#endif
+
+struct clk_mxc {
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+ struct clk clk;
+#endif
+
int id;
/* Source clock this clk depends on */
- struct clk *parent;
+ struct clk_mxc *parent;
/* Secondary clock to enable/disable with this clock */
- struct clk *secondary;
+ struct clk_mxc *secondary;
/* Reference count of clock enable/disable */
__s8 usecount;
/* Register bit position for clock's enable/disable control. */
@@ -39,23 +49,27 @@ struct clk {
void __iomem *enable_reg;
u32 flags;
/* get the current clock rate (always a fresh value) */
- unsigned long (*get_rate) (struct clk *);
+ unsigned long (*get_rate) (struct clk_mxc *);
/* Function ptr to set the clock to a new rate. The rate must match a
supported rate returned from round_rate. Leave blank if clock is not
programmable */
- int (*set_rate) (struct clk *, unsigned long);
+ int (*set_rate) (struct clk_mxc *, unsigned long);
/* Function ptr to round the requested clock rate to the nearest
supported rate that is less than or equal to the requested rate. */
- unsigned long (*round_rate) (struct clk *, unsigned long);
+ unsigned long (*round_rate) (struct clk_mxc *, unsigned long);
/* Function ptr to enable the clock. Leave blank if clock can not
be gated. */
- int (*enable) (struct clk *);
+ int (*enable) (struct clk_mxc *);
/* Function ptr to disable the clock. Leave blank if clock can not
be gated. */
- void (*disable) (struct clk *);
+ void (*disable) (struct clk_mxc *);
/* Function ptr to set the parent clock of the clock. */
- int (*set_parent) (struct clk *, struct clk *);
+ int (*set_parent) (struct clk_mxc *, struct clk_mxc *);
};
+#define to_clk_mxc(_clk_mxc) container_of(_clk_mxc, struct clk_mxc, clk)
+
+extern const struct clk_ops clk_mxc_ops;
+#define INIT_CLK_MXC(name) INIT_CLK(name.clk, clk_mxc_ops)
int clk_register(struct clk *clk);
void clk_unregister(struct clk *clk);
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0da0bb9..fbafcb6 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -47,7 +47,7 @@ int clk_enable(struct clk *clk)
unsigned long flags;
int ret = 0;
- WARN_ON(clk->prepare_count == 0);
+ WARN_ON_ONCE(clk->prepare_count == 0);
spin_lock_irqsave(&clk->enable_lock, flags);
if (clk->enable_count == 0 && clk->ops->enable)
--
1.7.2.3
More information about the linux-arm-kernel
mailing list