2022-03-11 21:28:01

by Janusz Krzysztofik

[permalink] [raw]
Subject: [RFC RFT PATCH 0/4] ARM: OMAP1: clock: Convert to CCF

The main motivation behind this series is planned resurection of OMAP1
camera driver. Since OMAP1 clock internals have never been visible to
drivers, that driver used to use v4l2-clk to expose a pixel clock for a
sensor. The v4l2-clk code has been recently depreciated and removed from
the media subtree, hence the need for an alternative solution.

Janusz Krzysztofik (4):
ARM: OMAP1: clock: Remove unused code
ARM: OMAP1: clock: Remove noop code
ARM: OMAP1: Prepare for conversion of OMAP1 clocks to CCF
ARM: OMAP1: clock: Convert to CCF

arch/arm/Kconfig | 2 +-
arch/arm/mach-omap1/clock.c | 791 ++++++++++++-------------------
arch/arm/mach-omap1/clock.h | 191 ++------
arch/arm/mach-omap1/clock_data.c | 491 ++++++++-----------
arch/arm/mach-omap1/io.c | 5 -
arch/arm/mach-omap1/mcbsp.c | 8 +-
arch/arm/mach-omap1/ocpi.c | 4 +-
arch/arm/mach-omap1/serial.c | 6 +-
arch/arm/mach-omap1/time.c | 5 +
arch/arm/mach-omap1/timer32k.c | 2 +-
drivers/usb/host/ohci-omap.c | 8 +-
drivers/video/fbdev/omap/lcdc.c | 6 +-
12 files changed, 582 insertions(+), 937 deletions(-)

The series has been tested on OMAP1510 based Amstrad Delta board,
where it works best on top of two recently submitted fixes:
ARM: OMAP1: clock: Fix early UART rate issues
ARM: OMAP1: clock: Fix UART rate reporting algorithm

--
2.35.1


2022-03-11 22:59:15

by Janusz Krzysztofik

[permalink] [raw]
Subject: [RFC PATCH 2/4] ARM: OMAP1: clock: Remove noop code

There are some OMAP1 clock code bits that have no effect:
- crystal_type variable is set to 0 but never changed, then
crystal_type == 2 condition is never true and ck_ref.rate never set to
19200000,
- clk->ops->allow_idle() is called from omap_clk_enable_autoidle_all() but
that op is not configured for any clock, then the function does nothing
and the op field is not needed,
- ENABLE_ON_INIT flag is set for some clocks but is never checked by any
code, then not needed.
Drop that code.

Signed-off-by: Janusz Krzysztofik <[email protected]>
---
arch/arm/mach-omap1/clock.c | 17 -----------------
arch/arm/mach-omap1/clock.h | 3 ---
arch/arm/mach-omap1/clock_data.c | 8 +-------
3 files changed, 1 insertion(+), 27 deletions(-)

diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index 5622ad487c8b..da74c09a71de 100644
--- a/arch/arm/mach-omap1/clock.c
+++ b/arch/arm/mach-omap1/clock.c
@@ -798,22 +798,6 @@ void clk_unregister(struct clk *clk)
}
EXPORT_SYMBOL(clk_unregister);

-int omap_clk_enable_autoidle_all(void)
-{
- struct clk *c;
- unsigned long flags;
-
- spin_lock_irqsave(&clockfw_lock, flags);
-
- list_for_each_entry(c, &clocks, node)
- if (c->ops->allow_idle)
- c->ops->allow_idle(c);
-
- spin_unlock_irqrestore(&clockfw_lock, flags);
-
- return 0;
-}
-
/*
* Low level helpers
*/
@@ -871,7 +855,6 @@ static int __init clk_disable_unused(void)
return 0;
}
late_initcall(clk_disable_unused);
-late_initcall(omap_clk_enable_autoidle_all);
#endif

#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h
index 7bebd488f1be..8025e4a22469 100644
--- a/arch/arm/mach-omap1/clock.h
+++ b/arch/arm/mach-omap1/clock.h
@@ -53,7 +53,6 @@ struct omap_clk {
struct clkops {
int (*enable)(struct clk *);
void (*disable)(struct clk *);
- void (*allow_idle)(struct clk *);
};

/*
@@ -64,7 +63,6 @@ struct clkops {
#define ENABLE_REG_32BIT (1 << 0) /* Use 32-bit access */
#define CLOCK_IDLE_CONTROL (1 << 1)
#define CLOCK_NO_IDLE_PARENT (1 << 2)
-#define ENABLE_ON_INIT (1 << 3) /* Enable upon framework init */

/**
* struct clk - OMAP struct clk
@@ -135,7 +133,6 @@ extern void clk_unregister(struct clk *clk);
extern void propagate_rate(struct clk *clk);
extern unsigned long followparent_recalc(struct clk *clk);
unsigned long omap_fixed_divisor_recalc(struct clk *clk);
-extern int omap_clk_enable_autoidle_all(void);

extern const struct clkops clkops_null;

diff --git a/arch/arm/mach-omap1/clock_data.c b/arch/arm/mach-omap1/clock_data.c
index 3ebcd96efbff..d55e4af7932e 100644
--- a/arch/arm/mach-omap1/clock_data.c
+++ b/arch/arm/mach-omap1/clock_data.c
@@ -93,8 +93,7 @@ static struct arm_idlect1_clk ck_dpll1out = {
.name = "ck_dpll1out",
.ops = &clkops_generic,
.parent = &ck_dpll1,
- .flags = CLOCK_IDLE_CONTROL | ENABLE_REG_32BIT |
- ENABLE_ON_INIT,
+ .flags = CLOCK_IDLE_CONTROL | ENABLE_REG_32BIT,
.enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2),
.enable_bit = EN_CKOUT_ARM,
.recalc = &followparent_recalc,
@@ -147,7 +146,6 @@ static struct clk arm_gpio_ck = {
.name = "ick",
.ops = &clkops_generic,
.parent = &ck_dpll1,
- .flags = ENABLE_ON_INIT,
.enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2),
.enable_bit = EN_GPIOCK,
.recalc = &followparent_recalc,
@@ -317,7 +315,6 @@ static struct clk tc2_ck = {
.name = "tc2_ck",
.ops = &clkops_generic,
.parent = &tc_ck.clk,
- .flags = ENABLE_ON_INIT,
.enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT3),
.enable_bit = EN_TC2_CK,
.recalc = &followparent_recalc,
@@ -763,7 +760,6 @@ u32 cpu_mask;
int __init omap1_clk_init(void)
{
struct omap_clk *c;
- int crystal_type = 0; /* Default 12 MHz */
u32 reg;

#ifdef CONFIG_DEBUG_LL
@@ -811,8 +807,6 @@ int __init omap1_clk_init(void)

if (cpu_is_omap7xx())
ck_ref.rate = 13000000;
- if (cpu_is_omap16xx() && crystal_type == 2)
- ck_ref.rate = 19200000;

pr_info("Clocks: ARM_SYSST: 0x%04x DPLL_CTL: 0x%04x ARM_CKCTL: 0x%04x\n",
omap_readw(ARM_SYSST), omap_readw(DPLL_CTL),
--
2.35.1

2022-03-11 23:09:30

by Janusz Krzysztofik

[permalink] [raw]
Subject: [RFC RFT PATCH 4/4] ARM: OMAP1: clock: Convert to CCF

OMAP1 still uses its own implementation of standard clock API defined in
include/linux/clk.h. Internals of that implementation are not visible
outside OMAP1 directory. As a consequence, device drivers are not able to
register clocks potentially provided by peripheral devices.

Drop OMAP1 implementation of the clock API and enable common clock
framework. Modify the remaining low level code to be compatible with
clock provider API and register the clocks with CCF.

Move initialisation of clocks to omap1_timer_init() to avoid memory
allocation issues at early setup phase from where omap1_init_early() is
called. Register the clocks after initialization of clock I/O registers,
local clock pointers used by OMAP1 clock ops, and local .rate fields of
clocks with no local implementation of .recalc ops, so CCF structures are
populated with correct data during clock registration. Instead of
enabling some of the registered clocks, flag them for CCF as critical.
Introduce .is_enabled op using code that verifies hardware status of clock
enablement, split out from implementation of .disable_unused op, so the
latter is actually called by CCF for not requested but hardware enabled
clocks. Add .round_rate ops where missing so .set_rate ops are called by
CCF as expected. Since CCF allows parallel execution of .enable/.disable
and .set_rate ops, protect registers shared among those groups of ops from
concurrent access with spinlocks. Drop local debugfs support in favor of
that provided by CCF.

Signed-off-by: Janusz Krzysztofik <[email protected]>
---
arch/arm/Kconfig | 2 +-
arch/arm/mach-omap1/clock.c | 693 +++++++++++++------------------
arch/arm/mach-omap1/clock.h | 139 +++----
arch/arm/mach-omap1/clock_data.c | 483 ++++++++++-----------
arch/arm/mach-omap1/io.c | 5 -
arch/arm/mach-omap1/time.c | 5 +
6 files changed, 564 insertions(+), 763 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 4c97cb40eebb..b7ad83b64339 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -499,7 +499,7 @@ config ARCH_OMAP1
select GENERIC_IRQ_CHIP
select GENERIC_IRQ_MULTI_HANDLER
select GPIOLIB
- select HAVE_LEGACY_CLK
+ select COMMON_CLK
select IRQ_DOMAIN
select NEED_MACH_IO_H if PCCARD
select NEED_MACH_MEMORY_H
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index da74c09a71de..2e83a3a51897 100644
--- a/arch/arm/mach-omap1/clock.c
+++ b/arch/arm/mach-omap1/clock.c
@@ -16,6 +16,8 @@
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/spinlock.h>

#include <asm/mach-types.h>

@@ -28,33 +30,37 @@
#include "sram.h"

__u32 arm_idlect1_mask;
-struct clk *api_ck_p, *ck_dpll1_p, *ck_ref_p;
+/* provide direct internal access (not via clk API) to some clocks */
+struct omap1_clk *api_ck_p, *ck_dpll1_p, *ck_ref_p;

-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-static DEFINE_SPINLOCK(clockfw_lock);
+/* protect registeres shared among clk_enable/disable() and clk_set_rate() operations */
+static DEFINE_SPINLOCK(arm_ckctl_lock);
+static DEFINE_SPINLOCK(arm_idlect2_lock);
+static DEFINE_SPINLOCK(mod_conf_ctrl_0_lock);
+static DEFINE_SPINLOCK(mod_conf_ctrl_1_lock);
+static DEFINE_SPINLOCK(swd_clk_div_ctrl_sel_lock);

/*
* Omap1 specific clock functions
*/

-unsigned long omap1_uart_recalc(struct clk *clk)
+unsigned long omap1_uart_recalc(struct omap1_clk *clk, unsigned long p_rate)
{
unsigned int val = __raw_readl(clk->enable_reg);
return val & clk->enable_bit ? 48000000 : 12000000;
}

-unsigned long omap1_sossi_recalc(struct clk *clk)
+unsigned long omap1_sossi_recalc(struct omap1_clk *clk, unsigned long p_rate)
{
u32 div = omap_readl(MOD_CONF_CTRL_1);

div = (div >> 17) & 0x7;
div++;

- return clk->parent->rate / div;
+ return p_rate / div;
}

-static void omap1_clk_allow_idle(struct clk *clk)
+static void omap1_clk_allow_idle(struct omap1_clk *clk)
{
struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk;

@@ -65,7 +71,7 @@ static void omap1_clk_allow_idle(struct clk *clk)
arm_idlect1_mask |= 1 << iclk->idlect_shift;
}

-static void omap1_clk_deny_idle(struct clk *clk)
+static void omap1_clk_deny_idle(struct omap1_clk *clk)
{
struct arm_idlect1_clk * iclk = (struct arm_idlect1_clk *)clk;

@@ -129,7 +135,7 @@ static __u16 verify_ckctl_value(__u16 newval)
return newval;
}

-static int calc_dsor_exp(struct clk *clk, unsigned long rate)
+static int calc_dsor_exp(unsigned long rate, unsigned long realrate)
{
/* Note: If target frequency is too low, this function will return 4,
* which is invalid value. Caller must check for this value and act
@@ -142,15 +148,11 @@ static int calc_dsor_exp(struct clk *clk, unsigned long rate)
* DSP_CK >= TC_CK
* DSPMMU_CK >= TC_CK
*/
- unsigned long realrate;
- struct clk * parent;
unsigned dsor_exp;

- parent = clk->parent;
- if (unlikely(parent == NULL))
+ if (unlikely(realrate == 0))
return -EIO;

- realrate = parent->rate;
for (dsor_exp=0; dsor_exp<4; dsor_exp++) {
if (realrate <= rate)
break;
@@ -161,16 +163,50 @@ static int calc_dsor_exp(struct clk *clk, unsigned long rate)
return dsor_exp;
}

-unsigned long omap1_ckctl_recalc(struct clk *clk)
+unsigned long omap1_ckctl_recalc(struct omap1_clk *clk, unsigned long p_rate)
{
/* Calculate divisor encoded as 2-bit exponent */
int dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset));

- return clk->parent->rate / dsor;
+ /* update locally maintained rate, required by arm_ck for omap1_show_rates() */
+ clk->rate = p_rate / dsor;
+ return clk->rate;
}

-unsigned long omap1_ckctl_recalc_dsp_domain(struct clk *clk)
+static int omap1_clk_is_enabled(struct clk_hw *hw)
{
+ struct omap1_clk *clk = to_omap1_clk(hw);
+ bool api_ck_was_enabled = true;
+ __u32 regval32;
+ int ret;
+
+ if (!clk->ops) /* no gate -- always enabled */
+ return 1;
+
+ if (clk->ops == &clkops_dspck) {
+ api_ck_was_enabled = omap1_clk_is_enabled(&api_ck_p->hw);
+ if (!api_ck_was_enabled)
+ if (api_ck_p->ops->enable(api_ck_p) < 0)
+ return 0;
+ }
+
+ if (clk->flags & ENABLE_REG_32BIT)
+ regval32 = __raw_readl(clk->enable_reg);
+ else
+ regval32 = __raw_readw(clk->enable_reg);
+
+ ret = regval32 & (1 << clk->enable_bit);
+
+ if (!api_ck_was_enabled)
+ api_ck_p->ops->disable(api_ck_p);
+
+ return ret;
+}
+
+
+unsigned long omap1_ckctl_recalc_dsp_domain(struct omap1_clk *clk, unsigned long p_rate)
+{
+ bool api_ck_was_enabled;
int dsor;

/* Calculate divisor encoded as 2-bit exponent
@@ -180,15 +216,18 @@ unsigned long omap1_ckctl_recalc_dsp_domain(struct clk *clk)
* Note that DSP_CKCTL virt addr = phys addr, so
* we must use __raw_readw() instead of omap_readw().
*/
- omap1_clk_enable(api_ck_p);
+ api_ck_was_enabled = omap1_clk_is_enabled(&api_ck_p->hw);
+ if (!api_ck_was_enabled)
+ api_ck_p->ops->enable(api_ck_p);
dsor = 1 << (3 & (__raw_readw(DSP_CKCTL) >> clk->rate_offset));
- omap1_clk_disable(api_ck_p);
+ if (!api_ck_was_enabled)
+ api_ck_p->ops->disable(api_ck_p);

- return clk->parent->rate / dsor;
+ return p_rate / dsor;
}

/* MPU virtual clock functions */
-int omap1_select_table_rate(struct clk *clk, unsigned long rate)
+int omap1_select_table_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
{
/* Find the highest supported frequency <= rate and switch to it */
struct mpu_rate * ptr;
@@ -223,12 +262,12 @@ int omap1_select_table_rate(struct clk *clk, unsigned long rate)
return 0;
}

-int omap1_clk_set_rate_dsp_domain(struct clk *clk, unsigned long rate)
+int omap1_clk_set_rate_dsp_domain(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
{
int dsor_exp;
u16 regval;

- dsor_exp = calc_dsor_exp(clk, rate);
+ dsor_exp = calc_dsor_exp(rate, p_rate);
if (dsor_exp > 3)
dsor_exp = -EINVAL;
if (dsor_exp < 0)
@@ -238,42 +277,51 @@ int omap1_clk_set_rate_dsp_domain(struct clk *clk, unsigned long rate)
regval &= ~(3 << clk->rate_offset);
regval |= dsor_exp << clk->rate_offset;
__raw_writew(regval, DSP_CKCTL);
- clk->rate = clk->parent->rate / (1 << dsor_exp);
+ clk->rate = p_rate / (1 << dsor_exp);

return 0;
}

-long omap1_clk_round_rate_ckctl_arm(struct clk *clk, unsigned long rate)
+long omap1_clk_round_rate_ckctl_arm(struct omap1_clk *clk, unsigned long rate,
+ unsigned long *p_rate)
{
- int dsor_exp = calc_dsor_exp(clk, rate);
+ int dsor_exp = calc_dsor_exp(rate, *p_rate);
+
if (dsor_exp < 0)
return dsor_exp;
if (dsor_exp > 3)
dsor_exp = 3;
- return clk->parent->rate / (1 << dsor_exp);
+ return *p_rate / (1 << dsor_exp);
}

-int omap1_clk_set_rate_ckctl_arm(struct clk *clk, unsigned long rate)
+int omap1_clk_set_rate_ckctl_arm(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
{
+ unsigned long flags;
int dsor_exp;
u16 regval;

- dsor_exp = calc_dsor_exp(clk, rate);
+ dsor_exp = calc_dsor_exp(rate, p_rate);
if (dsor_exp > 3)
dsor_exp = -EINVAL;
if (dsor_exp < 0)
return dsor_exp;

+ /* protect ARM_CKCTL register from concurrent access via clk_enable/disable() */
+ spin_lock_irqsave(&arm_ckctl_lock, flags);
+
regval = omap_readw(ARM_CKCTL);
regval &= ~(3 << clk->rate_offset);
regval |= dsor_exp << clk->rate_offset;
regval = verify_ckctl_value(regval);
omap_writew(regval, ARM_CKCTL);
- clk->rate = clk->parent->rate / (1 << dsor_exp);
+ clk->rate = p_rate / (1 << dsor_exp);
+
+ spin_unlock_irqrestore(&arm_ckctl_lock, flags);
+
return 0;
}

-long omap1_round_to_table_rate(struct clk *clk, unsigned long rate)
+long omap1_round_to_table_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate)
{
/* Find the highest supported frequency <= rate */
struct mpu_rate * ptr;
@@ -324,26 +372,40 @@ static unsigned calc_ext_dsor(unsigned long rate)
}

/* XXX Only needed on 1510 */
-int omap1_set_uart_rate(struct clk *clk, unsigned long rate)
+long omap1_round_uart_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate)
{
+ return rate > 24000000 ? 48000000 : 12000000;
+}
+
+int omap1_set_uart_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
+{
+ unsigned long flags;
unsigned int val;

- val = __raw_readl(clk->enable_reg);
if (rate == 12000000)
- val &= ~(1 << clk->enable_bit);
+ val = 0;
else if (rate == 48000000)
- val |= (1 << clk->enable_bit);
+ val = 1 << clk->enable_bit;
else
return -EINVAL;
+
+ /* protect MOD_CONF_CTRL_0 register from concurrent access via clk_enable/disable() */
+ spin_lock_irqsave(&mod_conf_ctrl_0_lock, flags);
+
+ val |= __raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit);
__raw_writel(val, clk->enable_reg);
+
+ spin_unlock_irqrestore(&mod_conf_ctrl_0_lock, flags);
+
clk->rate = rate;

return 0;
}

/* External clock (MCLK & BCLK) functions */
-int omap1_set_ext_clk_rate(struct clk *clk, unsigned long rate)
+int omap1_set_ext_clk_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
{
+ unsigned long flags;
unsigned dsor;
__u16 ratio_bits;

@@ -354,25 +416,53 @@ int omap1_set_ext_clk_rate(struct clk *clk, unsigned long rate)
else
ratio_bits = (dsor - 2) << 2;

+ /* protect SWD_CLK_DIV_CTRL_SEL register from concurrent access via clk_enable/disable() */
+ spin_lock_irqsave(&swd_clk_div_ctrl_sel_lock, flags);
+
ratio_bits |= __raw_readw(clk->enable_reg) & ~0xfd;
__raw_writew(ratio_bits, clk->enable_reg);

+ spin_unlock_irqrestore(&swd_clk_div_ctrl_sel_lock, flags);
+
return 0;
}

-int omap1_set_sossi_rate(struct clk *clk, unsigned long rate)
+static int calc_div_sossi(unsigned long rate, unsigned long p_rate)
{
- u32 l;
int div;
- unsigned long p_rate;

- p_rate = clk->parent->rate;
/* Round towards slower frequency */
div = (p_rate + rate - 1) / rate;
- div--;
+
+ return --div;
+}
+
+long omap1_round_sossi_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate)
+{
+ int div;
+
+ div = calc_div_sossi(rate, *p_rate);
+ if (div < 0)
+ div = 0;
+ else if (div > 7)
+ div = 7;
+
+ return *p_rate / (div + 1);
+}
+
+int omap1_set_sossi_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate)
+{
+ unsigned long flags;
+ u32 l;
+ int div;
+
+ div = calc_div_sossi(rate, p_rate);
if (div < 0 || div > 7)
return -EINVAL;

+ /* protect MOD_CONF_CTRL_1 register from concurrent access via clk_enable/disable() */
+ spin_lock_irqsave(&mod_conf_ctrl_1_lock, flags);
+
l = omap_readl(MOD_CONF_CTRL_1);
l &= ~(7 << 17);
l |= div << 17;
@@ -380,15 +470,17 @@ int omap1_set_sossi_rate(struct clk *clk, unsigned long rate)

clk->rate = p_rate / (div + 1);

+ spin_unlock_irqrestore(&mod_conf_ctrl_1_lock, flags);
+
return 0;
}

-long omap1_round_ext_clk_rate(struct clk *clk, unsigned long rate)
+long omap1_round_ext_clk_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate)
{
return 96000000 / calc_ext_dsor(rate);
}

-void omap1_init_ext_clk(struct clk *clk)
+int omap1_init_ext_clk(struct omap1_clk *clk)
{
unsigned dsor;
__u16 ratio_bits;
@@ -404,59 +496,59 @@ void omap1_init_ext_clk(struct clk *clk)
dsor = ratio_bits + 2;

clk-> rate = 96000000 / dsor;
+
+ return 0;
}

-int omap1_clk_enable(struct clk *clk)
+static int omap1_clk_enable(struct clk_hw *hw)
{
+ struct omap1_clk *clk = to_omap1_clk(hw), *parent = to_omap1_clk(clk_hw_get_parent(hw));
int ret = 0;

- if (clk->usecount++ == 0) {
- if (clk->parent) {
- ret = omap1_clk_enable(clk->parent);
- if (ret)
- goto err;
-
- if (clk->flags & CLOCK_NO_IDLE_PARENT)
- omap1_clk_deny_idle(clk->parent);
- }
+ if (parent && clk->flags & CLOCK_NO_IDLE_PARENT)
+ omap1_clk_deny_idle(parent);

+ if (clk->ops && !(WARN_ON(!clk->ops->enable)))
ret = clk->ops->enable(clk);
- if (ret) {
- if (clk->parent)
- omap1_clk_disable(clk->parent);
- goto err;
- }
- }
- return ret;

-err:
- clk->usecount--;
return ret;
}

-void omap1_clk_disable(struct clk *clk)
+static void omap1_clk_disable(struct clk_hw *hw)
{
- if (clk->usecount > 0 && !(--clk->usecount)) {
+ struct omap1_clk *clk = to_omap1_clk(hw), *parent = to_omap1_clk(clk_hw_get_parent(hw));
+
+ if (clk->ops && !(WARN_ON(!clk->ops->disable)))
clk->ops->disable(clk);
- if (likely(clk->parent)) {
- omap1_clk_disable(clk->parent);
- if (clk->flags & CLOCK_NO_IDLE_PARENT)
- omap1_clk_allow_idle(clk->parent);
- }
- }
+
+ if (likely(parent) && clk->flags & CLOCK_NO_IDLE_PARENT)
+ omap1_clk_allow_idle(parent);
}

-static int omap1_clk_enable_generic(struct clk *clk)
+static int omap1_clk_enable_generic(struct omap1_clk *clk)
{
+ unsigned long flags;
__u16 regval16;
__u32 regval32;

if (unlikely(clk->enable_reg == NULL)) {
printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
- clk->name);
+ clk_hw_get_name(&clk->hw));
return -EINVAL;
}

+ /* protect clk->enable_reg from concurrent access via clk_set_rate() */
+ if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_CKCTL))
+ spin_lock_irqsave(&arm_ckctl_lock, flags);
+ else if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_IDLECT2))
+ spin_lock_irqsave(&arm_idlect2_lock, flags);
+ else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0))
+ spin_lock_irqsave(&mod_conf_ctrl_0_lock, flags);
+ else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1))
+ spin_lock_irqsave(&mod_conf_ctrl_1_lock, flags);
+ else if (clk->enable_reg == OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL))
+ spin_lock_irqsave(&swd_clk_div_ctrl_sel_lock, flags);
+
if (clk->flags & ENABLE_REG_32BIT) {
regval32 = __raw_readl(clk->enable_reg);
regval32 |= (1 << clk->enable_bit);
@@ -467,17 +559,41 @@ static int omap1_clk_enable_generic(struct clk *clk)
__raw_writew(regval16, clk->enable_reg);
}

+ if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_CKCTL))
+ spin_unlock_irqrestore(&arm_ckctl_lock, flags);
+ else if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_IDLECT2))
+ spin_unlock_irqrestore(&arm_idlect2_lock, flags);
+ else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0))
+ spin_unlock_irqrestore(&mod_conf_ctrl_0_lock, flags);
+ else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1))
+ spin_unlock_irqrestore(&mod_conf_ctrl_1_lock, flags);
+ else if (clk->enable_reg == OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL))
+ spin_unlock_irqrestore(&swd_clk_div_ctrl_sel_lock, flags);
+
return 0;
}

-static void omap1_clk_disable_generic(struct clk *clk)
+static void omap1_clk_disable_generic(struct omap1_clk *clk)
{
+ unsigned long flags;
__u16 regval16;
__u32 regval32;

if (clk->enable_reg == NULL)
return;

+ /* protect clk->enable_reg from concurrent access via clk_set_rate() */
+ if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_CKCTL))
+ spin_lock_irqsave(&arm_ckctl_lock, flags);
+ else if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_IDLECT2))
+ spin_lock_irqsave(&arm_idlect2_lock, flags);
+ else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0))
+ spin_lock_irqsave(&mod_conf_ctrl_0_lock, flags);
+ else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1))
+ spin_lock_irqsave(&mod_conf_ctrl_1_lock, flags);
+ else if (clk->enable_reg == OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL))
+ spin_lock_irqsave(&swd_clk_div_ctrl_sel_lock, flags);
+
if (clk->flags & ENABLE_REG_32BIT) {
regval32 = __raw_readl(clk->enable_reg);
regval32 &= ~(1 << clk->enable_bit);
@@ -487,6 +603,17 @@ static void omap1_clk_disable_generic(struct clk *clk)
regval16 &= ~(1 << clk->enable_bit);
__raw_writew(regval16, clk->enable_reg);
}
+
+ if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_CKCTL))
+ spin_unlock_irqrestore(&arm_ckctl_lock, flags);
+ else if (clk->enable_reg == OMAP1_IO_ADDRESS(ARM_IDLECT2))
+ spin_unlock_irqrestore(&arm_idlect2_lock, flags);
+ else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0))
+ spin_unlock_irqrestore(&mod_conf_ctrl_0_lock, flags);
+ else if (clk->enable_reg == OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1))
+ spin_unlock_irqrestore(&mod_conf_ctrl_1_lock, flags);
+ else if (clk->enable_reg == OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL))
+ spin_unlock_irqrestore(&swd_clk_div_ctrl_sel_lock, flags);
}

const struct clkops clkops_generic = {
@@ -494,25 +621,38 @@ const struct clkops clkops_generic = {
.disable = omap1_clk_disable_generic,
};

-static int omap1_clk_enable_dsp_domain(struct clk *clk)
+static int omap1_clk_enable_dsp_domain(struct omap1_clk *clk)
{
- int retval;
+ bool api_ck_was_enabled;
+ int retval = 0;
+
+ api_ck_was_enabled = omap1_clk_is_enabled(&api_ck_p->hw);
+ if (!api_ck_was_enabled)
+ retval = api_ck_p->ops->enable(api_ck_p);

- retval = omap1_clk_enable(api_ck_p);
if (!retval) {
retval = omap1_clk_enable_generic(clk);
- omap1_clk_disable(api_ck_p);
+
+ if (!api_ck_was_enabled)
+ api_ck_p->ops->disable(api_ck_p);
}

return retval;
}

-static void omap1_clk_disable_dsp_domain(struct clk *clk)
+static void omap1_clk_disable_dsp_domain(struct omap1_clk *clk)
{
- if (omap1_clk_enable(api_ck_p) == 0) {
- omap1_clk_disable_generic(clk);
- omap1_clk_disable(api_ck_p);
- }
+ bool api_ck_was_enabled;
+
+ api_ck_was_enabled = omap1_clk_is_enabled(&api_ck_p->hw);
+ if (!api_ck_was_enabled)
+ if (api_ck_p->ops->enable(api_ck_p) < 0)
+ return;
+
+ omap1_clk_disable_generic(clk);
+
+ if (!api_ck_was_enabled)
+ api_ck_p->ops->disable(api_ck_p);
}

const struct clkops clkops_dspck = {
@@ -521,7 +661,7 @@ const struct clkops clkops_dspck = {
};

/* XXX SYSC register handling does not belong in the clock framework */
-static int omap1_clk_enable_uart_functional_16xx(struct clk *clk)
+static int omap1_clk_enable_uart_functional_16xx(struct omap1_clk *clk)
{
int ret;
struct uart_clk *uclk;
@@ -538,7 +678,7 @@ static int omap1_clk_enable_uart_functional_16xx(struct clk *clk)
}

/* XXX SYSC register handling does not belong in the clock framework */
-static void omap1_clk_disable_uart_functional_16xx(struct clk *clk)
+static void omap1_clk_disable_uart_functional_16xx(struct omap1_clk *clk)
{
struct uart_clk *uclk;

@@ -555,20 +695,33 @@ const struct clkops clkops_uart_16xx = {
.disable = omap1_clk_disable_uart_functional_16xx,
};

-long omap1_clk_round_rate(struct clk *clk, unsigned long rate)
+static unsigned long omap1_clk_recalc_rate(struct clk_hw *hw, unsigned long p_rate)
{
- if (clk->round_rate != NULL)
- return clk->round_rate(clk, rate);
+ struct omap1_clk *clk = to_omap1_clk(hw);
+
+ if (clk->recalc)
+ return clk->recalc(clk, p_rate);

return clk->rate;
}

-int omap1_clk_set_rate(struct clk *clk, unsigned long rate)
+static long omap1_clk_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *p_rate)
+{
+ struct omap1_clk *clk = to_omap1_clk(hw);
+
+ if (clk->round_rate != NULL)
+ return clk->round_rate(clk, rate, p_rate);
+
+ return omap1_clk_recalc_rate(hw, *p_rate);
+}
+
+static int omap1_clk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long p_rate)
{
+ struct omap1_clk *clk = to_omap1_clk(hw);
int ret = -EINVAL;

if (clk->set_rate)
- ret = clk->set_rate(clk, rate);
+ ret = clk->set_rate(clk, rate, p_rate);
return ret;
}

@@ -576,243 +729,105 @@ int omap1_clk_set_rate(struct clk *clk, unsigned long rate)
* Omap1 clock reset and init functions
*/

+static int omap1_clk_init_op(struct clk_hw *hw)
+{
+ struct omap1_clk *clk = to_omap1_clk(hw);
+
+ if (clk->init)
+ return clk->init(clk);
+
+ return 0;
+}
+
#ifdef CONFIG_OMAP_RESET_CLOCKS

-void omap1_clk_disable_unused(struct clk *clk)
+static void omap1_clk_disable_unused(struct clk_hw *hw)
{
- __u32 regval32;
+ struct omap1_clk *clk = to_omap1_clk(hw);
+ const char *name = clk_hw_get_name(hw);

/* Clocks in the DSP domain need api_ck. Just assume bootloader
* has not enabled any DSP clocks */
if (clk->enable_reg == DSP_IDLECT2) {
- pr_info("Skipping reset check for DSP domain clock \"%s\"\n",
- clk->name);
+ pr_info("Skipping reset check for DSP domain clock \"%s\"\n", name);
return;
}

- /* Is the clock already disabled? */
- if (clk->flags & ENABLE_REG_32BIT)
- regval32 = __raw_readl(clk->enable_reg);
- else
- regval32 = __raw_readw(clk->enable_reg);
-
- if ((regval32 & (1 << clk->enable_bit)) == 0)
- return;
-
- printk(KERN_INFO "Disabling unused clock \"%s\"... ", clk->name);
- clk->ops->disable(clk);
+ pr_info("Disabling unused clock \"%s\"... ", name);
+ omap1_clk_disable(hw);
printk(" done\n");
}

#endif

+const struct clk_ops omap1_clk_gate_ops = {
+ .enable = omap1_clk_enable,
+ .disable = omap1_clk_disable,
+ .is_enabled = omap1_clk_is_enabled,
+#ifdef CONFIG_OMAP_RESET_CLOCKS
+ .disable_unused = omap1_clk_disable_unused,
+#endif
+};

-int clk_enable(struct clk *clk)
-{
- unsigned long flags;
- int ret;
-
- if (IS_ERR_OR_NULL(clk))
- return -EINVAL;
-
- spin_lock_irqsave(&clockfw_lock, flags);
- ret = omap1_clk_enable(clk);
- spin_unlock_irqrestore(&clockfw_lock, flags);
-
- return ret;
-}
-EXPORT_SYMBOL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
- unsigned long flags;
-
- if (IS_ERR_OR_NULL(clk))
- return;
-
- spin_lock_irqsave(&clockfw_lock, flags);
- if (clk->usecount == 0) {
- pr_err("Trying disable clock %s with 0 usecount\n",
- clk->name);
- WARN_ON(1);
- goto out;
- }
-
- omap1_clk_disable(clk);
-
-out:
- spin_unlock_irqrestore(&clockfw_lock, flags);
-}
-EXPORT_SYMBOL(clk_disable);
-
-unsigned long clk_get_rate(struct clk *clk)
-{
- unsigned long flags;
- unsigned long ret;
-
- if (IS_ERR_OR_NULL(clk))
- return 0;
-
- spin_lock_irqsave(&clockfw_lock, flags);
- ret = clk->rate;
- spin_unlock_irqrestore(&clockfw_lock, flags);
-
- return ret;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-/*
- * Optional clock functions defined in include/linux/clk.h
- */
-
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
- unsigned long flags;
- long ret;
-
- if (IS_ERR_OR_NULL(clk))
- return 0;
-
- spin_lock_irqsave(&clockfw_lock, flags);
- ret = omap1_clk_round_rate(clk, rate);
- spin_unlock_irqrestore(&clockfw_lock, flags);
-
- return ret;
-}
-EXPORT_SYMBOL(clk_round_rate);
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
- unsigned long flags;
- int ret = -EINVAL;
-
- if (IS_ERR_OR_NULL(clk))
- return ret;
-
- spin_lock_irqsave(&clockfw_lock, flags);
- ret = omap1_clk_set_rate(clk, rate);
- if (ret == 0)
- propagate_rate(clk);
- spin_unlock_irqrestore(&clockfw_lock, flags);
-
- return ret;
-}
-EXPORT_SYMBOL(clk_set_rate);
-
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
- WARN_ONCE(1, "clk_set_parent() not implemented for OMAP1\n");
-
- return -EINVAL;
-}
-EXPORT_SYMBOL(clk_set_parent);
+const struct clk_ops omap1_clk_rate_ops = {
+ .recalc_rate = omap1_clk_recalc_rate,
+ .round_rate = omap1_clk_round_rate,
+ .set_rate = omap1_clk_set_rate,
+ .init = omap1_clk_init_op,
+};

-struct clk *clk_get_parent(struct clk *clk)
-{
- return clk->parent;
-}
-EXPORT_SYMBOL(clk_get_parent);
+const struct clk_ops omap1_clk_full_ops = {
+ .enable = omap1_clk_enable,
+ .disable = omap1_clk_disable,
+ .is_enabled = omap1_clk_is_enabled,
+#ifdef CONFIG_OMAP_RESET_CLOCKS
+ .disable_unused = omap1_clk_disable_unused,
+#endif
+ .recalc_rate = omap1_clk_recalc_rate,
+ .round_rate = omap1_clk_round_rate,
+ .set_rate = omap1_clk_set_rate,
+ .init = omap1_clk_init_op,
+};

/*
* OMAP specific clock functions shared between omap1 and omap2
*/

/* Used for clocks that always have same value as the parent clock */
-unsigned long followparent_recalc(struct clk *clk)
+unsigned long followparent_recalc(struct omap1_clk *clk, unsigned long p_rate)
{
- return clk->parent->rate;
+ return p_rate;
}

/*
* Used for clocks that have the same value as the parent clock,
* divided by some factor
*/
-unsigned long omap_fixed_divisor_recalc(struct clk *clk)
+unsigned long omap_fixed_divisor_recalc(struct omap1_clk *clk, unsigned long p_rate)
{
WARN_ON(!clk->fixed_div);

- return clk->parent->rate / clk->fixed_div;
+ return p_rate / clk->fixed_div;
}

/* Propagate rate to children */
-void propagate_rate(struct clk *tclk)
+void propagate_rate(struct omap1_clk *tclk)
{
struct clk *clkp;

- list_for_each_entry(clkp, &tclk->children, sibling) {
- if (clkp->recalc)
- clkp->rate = clkp->recalc(clkp);
- propagate_rate(clkp);
- }
-}
-
-static LIST_HEAD(root_clks);
-
-/**
- * clk_preinit - initialize any fields in the struct clk before clk init
- * @clk: struct clk * to initialize
- *
- * Initialize any struct clk fields needed before normal clk initialization
- * can run. No return value.
- */
-void clk_preinit(struct clk *clk)
-{
- INIT_LIST_HEAD(&clk->children);
-}
-
-int clk_register(struct clk *clk)
-{
- if (IS_ERR_OR_NULL(clk))
- return -EINVAL;
-
- /*
- * trap out already registered clocks
- */
- if (clk->node.next || clk->node.prev)
- return 0;
-
- mutex_lock(&clocks_mutex);
- if (clk->parent)
- list_add(&clk->sibling, &clk->parent->children);
- else
- list_add(&clk->sibling, &root_clks);
-
- list_add(&clk->node, &clocks);
- if (clk->init)
- clk->init(clk);
- mutex_unlock(&clocks_mutex);
-
- return 0;
-}
-EXPORT_SYMBOL(clk_register);
-
-void clk_unregister(struct clk *clk)
-{
- if (IS_ERR_OR_NULL(clk))
+ /* depend on CCF ability to recalculate new rates across whole clock subtree */
+ if (WARN_ON(!(clk_hw_get_flags(&tclk->hw) & CLK_GET_RATE_NOCACHE)))
return;

- mutex_lock(&clocks_mutex);
- list_del(&clk->sibling);
- list_del(&clk->node);
- mutex_unlock(&clocks_mutex);
-}
-EXPORT_SYMBOL(clk_unregister);
-
-/*
- * Low level helpers
- */
-static int clkll_enable_null(struct clk *clk)
-{
- return 0;
-}
+ clkp = clk_get_sys(NULL, clk_hw_get_name(&tclk->hw));
+ if (WARN_ON(!clkp))
+ return;

-static void clkll_disable_null(struct clk *clk)
-{
+ clk_get_rate(clkp);
+ clk_put(clkp);
}

-const struct clkops clkops_null = {
- .enable = clkll_enable_null,
- .disable = clkll_disable_null,
+const struct clk_ops omap1_clk_null_ops = {
};

/*
@@ -820,114 +835,6 @@ const struct clkops clkops_null = {
*
* Used for clock aliases that are needed on some OMAPs, but not others
*/
-struct clk dummy_ck = {
- .name = "dummy",
- .ops = &clkops_null,
+struct omap1_clk dummy_ck __refdata = {
+ .hw.init = CLK_HW_INIT_NO_PARENT("dummy", &omap1_clk_null_ops, 0),
};
-
-/*
- *
- */
-
-#ifdef CONFIG_OMAP_RESET_CLOCKS
-/*
- * Disable any unused clocks left on by the bootloader
- */
-static int __init clk_disable_unused(void)
-{
- struct clk *ck;
- unsigned long flags;
-
- pr_info("clock: disabling unused clocks to save power\n");
-
- spin_lock_irqsave(&clockfw_lock, flags);
- list_for_each_entry(ck, &clocks, node) {
- if (ck->ops == &clkops_null)
- continue;
-
- if (ck->usecount > 0 || !ck->enable_reg)
- continue;
-
- omap1_clk_disable_unused(ck);
- }
- spin_unlock_irqrestore(&clockfw_lock, flags);
-
- return 0;
-}
-late_initcall(clk_disable_unused);
-#endif
-
-#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
-/*
- * debugfs support to trace clock tree hierarchy and attributes
- */
-
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-
-static struct dentry *clk_debugfs_root;
-
-static int debug_clock_show(struct seq_file *s, void *unused)
-{
- struct clk *c;
- struct clk *pa;
-
- mutex_lock(&clocks_mutex);
- seq_printf(s, "%-30s %-30s %-10s %s\n",
- "clock-name", "parent-name", "rate", "use-count");
-
- list_for_each_entry(c, &clocks, node) {
- pa = c->parent;
- seq_printf(s, "%-30s %-30s %-10lu %d\n",
- c->name, pa ? pa->name : "none", c->rate,
- c->usecount);
- }
- mutex_unlock(&clocks_mutex);
-
- return 0;
-}
-
-DEFINE_SHOW_ATTRIBUTE(debug_clock);
-
-static void clk_debugfs_register_one(struct clk *c)
-{
- struct dentry *d;
- struct clk *pa = c->parent;
-
- d = debugfs_create_dir(c->name, pa ? pa->dent : clk_debugfs_root);
- c->dent = d;
-
- debugfs_create_u8("usecount", S_IRUGO, c->dent, &c->usecount);
- debugfs_create_ulong("rate", S_IRUGO, c->dent, &c->rate);
- debugfs_create_x8("flags", S_IRUGO, c->dent, &c->flags);
-}
-
-static void clk_debugfs_register(struct clk *c)
-{
- struct clk *pa = c->parent;
-
- if (pa && !pa->dent)
- clk_debugfs_register(pa);
-
- if (!c->dent)
- clk_debugfs_register_one(c);
-}
-
-static int __init clk_debugfs_init(void)
-{
- struct clk *c;
- struct dentry *d;
-
- d = debugfs_create_dir("clock", NULL);
- clk_debugfs_root = d;
-
- list_for_each_entry(c, &clocks, node)
- clk_debugfs_register(c);
-
- debugfs_create_file("summary", S_IRUGO, d, NULL, &debug_clock_fops);
-
- return 0;
-}
-late_initcall(clk_debugfs_init);
-
-#endif /* defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) */
diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h
index 8025e4a22469..16cfb2e86ee4 100644
--- a/arch/arm/mach-omap1/clock.h
+++ b/arch/arm/mach-omap1/clock.h
@@ -11,12 +11,11 @@
#define __ARCH_ARM_MACH_OMAP1_CLOCK_H

#include <linux/clk.h>
-#include <linux/list.h>
-
#include <linux/clkdev.h>
+#include <linux/clk-provider.h>

struct module;
-struct clk;
+struct omap1_clk;

struct omap_clk {
u16 cpu;
@@ -29,7 +28,7 @@ struct omap_clk {
.lk = { \
.dev_id = dev, \
.con_id = con, \
- .clk = ck, \
+ .clk_hw = ck, \
}, \
}

@@ -40,10 +39,6 @@ struct omap_clk {
#define CK_16XX (1 << 3) /* 16xx, 17xx, 5912 */
#define CK_1710 (1 << 4) /* 1710 extra for rate selection */

-
-/* Temporary, needed during the common clock framework conversion */
-#define __clk_get_name(clk) (clk->name)
-
/**
* struct clkops - some clock function pointers
* @enable: fn ptr that enables the current clock in hardware
@@ -51,8 +46,8 @@ struct omap_clk {
* @allow_idle: fn ptr that enables autoidle for the current clock in hardware
*/
struct clkops {
- int (*enable)(struct clk *);
- void (*disable)(struct clk *);
+ int (*enable)(struct omap1_clk *clk);
+ void (*disable)(struct omap1_clk *clk);
};

/*
@@ -65,13 +60,9 @@ struct clkops {
#define CLOCK_NO_IDLE_PARENT (1 << 2)

/**
- * struct clk - OMAP struct clk
- * @node: list_head connecting this clock into the full clock list
+ * struct omap1_clk - OMAP1 struct clk
+ * @hw: struct clk_hw for common clock framework integration
* @ops: struct clkops * for this clock
- * @name: the name of the clock in the hardware (used in hwmod data and debug)
- * @parent: pointer to this clock's parent struct clk
- * @children: list_head connecting to the child clks' @sibling list_heads
- * @sibling: list_head connecting this clk to its parent clk's @children
* @rate: current clock rate
* @enable_reg: register to write to enable the clock (see @enable_bit)
* @recalc: fn ptr that returns the clock's current rate
@@ -79,102 +70,65 @@ struct clkops {
* @round_rate: fn ptr that can round the clock's current rate
* @init: fn ptr to do clock-specific initialization
* @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg)
- * @usecount: number of users that have requested this clock to be enabled
* @fixed_div: when > 0, this clock's rate is its parent's rate / @fixed_div
* @flags: see "struct clk.flags possibilities" above
* @rate_offset: bitshift for rate selection bitfield (OMAP1 only)
- *
- * XXX @rate_offset should probably be removed and OMAP1
- * clock code converted to use clksel.
- *
- * XXX @usecount is poorly named. It should be "enable_count" or
- * something similar. "users" in the description refers to kernel
- * code (core code or drivers) that have called clk_enable() and not
- * yet called clk_disable(); the usecount of parent clocks is also
- * incremented by the clock code when clk_enable() is called on child
- * clocks and decremented by the clock code when clk_disable() is
- * called on child clocks.
- *
- * XXX @usecount, @children, @sibling should be marked for
- * internal use only.
- *
- * @children and @sibling are used to optimize parent-to-child clock
- * tree traversals. (child-to-parent traversals use @parent.)
- *
- * XXX The notion of the clock's current rate probably needs to be
- * separated from the clock's target rate.
*/
-struct clk {
- struct list_head node;
+struct omap1_clk {
+ struct clk_hw hw;
const struct clkops *ops;
- const char *name;
- struct clk *parent;
- struct list_head children;
- struct list_head sibling; /* node for children */
unsigned long rate;
void __iomem *enable_reg;
- unsigned long (*recalc)(struct clk *);
- int (*set_rate)(struct clk *, unsigned long);
- long (*round_rate)(struct clk *, unsigned long);
- void (*init)(struct clk *);
+ unsigned long (*recalc)(struct omap1_clk *clk, unsigned long rate);
+ int (*set_rate)(struct omap1_clk *clk, unsigned long rate,
+ unsigned long p_rate);
+ long (*round_rate)(struct omap1_clk *clk, unsigned long rate,
+ unsigned long *p_rate);
+ int (*init)(struct omap1_clk *clk);
u8 enable_bit;
- s8 usecount;
u8 fixed_div;
u8 flags;
u8 rate_offset;
-#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
- struct dentry *dent; /* For visible tree hierarchy */
-#endif
};
+#define to_omap1_clk(_hw) container_of(_hw, struct omap1_clk, hw)

-extern void clk_preinit(struct clk *clk);
-extern int clk_register(struct clk *clk);
-extern void clk_unregister(struct clk *clk);
-extern void propagate_rate(struct clk *clk);
-extern unsigned long followparent_recalc(struct clk *clk);
-unsigned long omap_fixed_divisor_recalc(struct clk *clk);
+void propagate_rate(struct omap1_clk *clk);
+unsigned long followparent_recalc(struct omap1_clk *clk, unsigned long p_rate);
+unsigned long omap_fixed_divisor_recalc(struct omap1_clk *clk, unsigned long p_rate);

-extern const struct clkops clkops_null;
-
-extern struct clk dummy_ck;
+extern struct omap1_clk dummy_ck;

int omap1_clk_init(void);
void omap1_clk_late_init(void);
-extern int omap1_clk_enable(struct clk *clk);
-extern void omap1_clk_disable(struct clk *clk);
-extern long omap1_clk_round_rate(struct clk *clk, unsigned long rate);
-extern int omap1_clk_set_rate(struct clk *clk, unsigned long rate);
-extern unsigned long omap1_ckctl_recalc(struct clk *clk);
-extern int omap1_set_sossi_rate(struct clk *clk, unsigned long rate);
-extern unsigned long omap1_sossi_recalc(struct clk *clk);
-extern unsigned long omap1_ckctl_recalc_dsp_domain(struct clk *clk);
-extern int omap1_clk_set_rate_dsp_domain(struct clk *clk, unsigned long rate);
-extern int omap1_set_uart_rate(struct clk *clk, unsigned long rate);
-extern unsigned long omap1_uart_recalc(struct clk *clk);
-extern int omap1_set_ext_clk_rate(struct clk *clk, unsigned long rate);
-extern long omap1_round_ext_clk_rate(struct clk *clk, unsigned long rate);
-extern void omap1_init_ext_clk(struct clk *clk);
-extern int omap1_select_table_rate(struct clk *clk, unsigned long rate);
-extern long omap1_round_to_table_rate(struct clk *clk, unsigned long rate);
-extern int omap1_clk_set_rate_ckctl_arm(struct clk *clk, unsigned long rate);
-extern long omap1_clk_round_rate_ckctl_arm(struct clk *clk, unsigned long rate);
-
-#ifdef CONFIG_OMAP_RESET_CLOCKS
-extern void omap1_clk_disable_unused(struct clk *clk);
-#else
-#define omap1_clk_disable_unused NULL
-#endif
+unsigned long omap1_ckctl_recalc(struct omap1_clk *clk, unsigned long p_rate);
+long omap1_round_sossi_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate);
+int omap1_set_sossi_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate);
+unsigned long omap1_sossi_recalc(struct omap1_clk *clk, unsigned long p_rate);
+unsigned long omap1_ckctl_recalc_dsp_domain(struct omap1_clk *clk, unsigned long p_rate);
+int omap1_clk_set_rate_dsp_domain(struct omap1_clk *clk, unsigned long rate,
+ unsigned long p_rate);
+long omap1_round_uart_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate);
+int omap1_set_uart_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate);
+unsigned long omap1_uart_recalc(struct omap1_clk *clk, unsigned long p_rate);
+int omap1_set_ext_clk_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate);
+long omap1_round_ext_clk_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate);
+int omap1_init_ext_clk(struct omap1_clk *clk);
+int omap1_select_table_rate(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate);
+long omap1_round_to_table_rate(struct omap1_clk *clk, unsigned long rate, unsigned long *p_rate);
+int omap1_clk_set_rate_ckctl_arm(struct omap1_clk *clk, unsigned long rate, unsigned long p_rate);
+long omap1_clk_round_rate_ckctl_arm(struct omap1_clk *clk, unsigned long rate,
+ unsigned long *p_rate);

struct uart_clk {
- struct clk clk;
- unsigned long sysc_addr;
+ struct omap1_clk clk;
+ unsigned long sysc_addr;
};

/* Provide a method for preventing idling some ARM IDLECT clocks */
struct arm_idlect1_clk {
- struct clk clk;
- unsigned long no_idle_count;
- __u8 idlect_shift;
+ struct omap1_clk clk;
+ unsigned long no_idle_count;
+ __u8 idlect_shift;
};

/* ARM_CKCTL bit shifts */
@@ -224,7 +178,7 @@ struct arm_idlect1_clk {
#define SOFT_REQ_REG2 0xfffe0880

extern __u32 arm_idlect1_mask;
-extern struct clk *api_ck_p, *ck_dpll1_p, *ck_ref_p;
+extern struct omap1_clk *api_ck_p, *ck_dpll1_p, *ck_ref_p;

extern const struct clkops clkops_dspck;
extern const struct clkops clkops_uart_16xx;
@@ -233,4 +187,9 @@ extern const struct clkops clkops_generic;
/* used for passing SoC type to omap1_{select,round_to}_table_rate() */
extern u32 cpu_mask;

+extern const struct clk_ops omap1_clk_null_ops;
+extern const struct clk_ops omap1_clk_gate_ops;
+extern const struct clk_ops omap1_clk_rate_ops;
+extern const struct clk_ops omap1_clk_full_ops;
+
#endif
diff --git a/arch/arm/mach-omap1/clock_data.c b/arch/arm/mach-omap1/clock_data.c
index d55e4af7932e..e33e11f826af 100644
--- a/arch/arm/mach-omap1/clock_data.c
+++ b/arch/arm/mach-omap1/clock_data.c
@@ -14,6 +14,8 @@
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
#include <linux/cpufreq.h>
#include <linux/delay.h>

@@ -72,16 +74,18 @@
* Omap1 clocks
*/

-static struct clk ck_ref = {
- .name = "ck_ref",
- .ops = &clkops_null,
+static struct omap1_clk ck_ref = {
+ .hw.init = CLK_HW_INIT_NO_PARENT("ck_ref", &omap1_clk_rate_ops, 0),
.rate = 12000000,
};

-static struct clk ck_dpll1 = {
- .name = "ck_dpll1",
- .ops = &clkops_null,
- .parent = &ck_ref,
+static struct omap1_clk ck_dpll1 = {
+ .hw.init = CLK_HW_INIT("ck_dpll1", "ck_ref", &omap1_clk_rate_ops,
+ /*
+ * force recursive refresh of rates of the clock
+ * and its children when clk_get_rate() is called
+ */
+ CLK_GET_RATE_NOCACHE),
};

/*
@@ -90,32 +94,28 @@ static struct clk ck_dpll1 = {
*/
static struct arm_idlect1_clk ck_dpll1out = {
.clk = {
- .name = "ck_dpll1out",
+ .hw.init = CLK_HW_INIT("ck_dpll1out", "ck_dpll1", &omap1_clk_gate_ops, 0),
.ops = &clkops_generic,
- .parent = &ck_dpll1,
.flags = CLOCK_IDLE_CONTROL | ENABLE_REG_32BIT,
.enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2),
.enable_bit = EN_CKOUT_ARM,
- .recalc = &followparent_recalc,
},
.idlect_shift = IDL_CLKOUT_ARM_SHIFT,
};

-static struct clk sossi_ck = {
- .name = "ck_sossi",
+static struct omap1_clk sossi_ck = {
+ .hw.init = CLK_HW_INIT("ck_sossi", "ck_dpll1out", &omap1_clk_full_ops, 0),
.ops = &clkops_generic,
- .parent = &ck_dpll1out.clk,
.flags = CLOCK_NO_IDLE_PARENT | ENABLE_REG_32BIT,
.enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_1),
.enable_bit = CONF_MOD_SOSSI_CLK_EN_R,
.recalc = &omap1_sossi_recalc,
+ .round_rate = &omap1_round_sossi_rate,
.set_rate = &omap1_set_sossi_rate,
};

-static struct clk arm_ck = {
- .name = "arm_ck",
- .ops = &clkops_null,
- .parent = &ck_dpll1,
+static struct omap1_clk arm_ck = {
+ .hw.init = CLK_HW_INIT("arm_ck", "ck_dpll1", &omap1_clk_rate_ops, 0),
.rate_offset = CKCTL_ARMDIV_OFFSET,
.recalc = &omap1_ckctl_recalc,
.round_rate = omap1_clk_round_rate_ckctl_arm,
@@ -124,9 +124,9 @@ static struct clk arm_ck = {

static struct arm_idlect1_clk armper_ck = {
.clk = {
- .name = "armper_ck",
+ .hw.init = CLK_HW_INIT("armper_ck", "ck_dpll1", &omap1_clk_full_ops,
+ CLK_IS_CRITICAL),
.ops = &clkops_generic,
- .parent = &ck_dpll1,
.flags = CLOCK_IDLE_CONTROL,
.enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2),
.enable_bit = EN_PERCK,
@@ -142,46 +142,41 @@ static struct arm_idlect1_clk armper_ck = {
* FIXME: This clock seems to be necessary but no-one has asked for its
* activation. [ GPIO code for 1510 ]
*/
-static struct clk arm_gpio_ck = {
- .name = "ick",
+static struct omap1_clk arm_gpio_ck = {
+ .hw.init = CLK_HW_INIT("ick", "ck_dpll1", &omap1_clk_gate_ops, CLK_IS_CRITICAL),
.ops = &clkops_generic,
- .parent = &ck_dpll1,
.enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2),
.enable_bit = EN_GPIOCK,
- .recalc = &followparent_recalc,
};

static struct arm_idlect1_clk armxor_ck = {
.clk = {
- .name = "armxor_ck",
+ .hw.init = CLK_HW_INIT("armxor_ck", "ck_ref", &omap1_clk_gate_ops,
+ CLK_IS_CRITICAL),
.ops = &clkops_generic,
- .parent = &ck_ref,
.flags = CLOCK_IDLE_CONTROL,
.enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2),
.enable_bit = EN_XORPCK,
- .recalc = &followparent_recalc,
},
.idlect_shift = IDLXORP_ARM_SHIFT,
};

static struct arm_idlect1_clk armtim_ck = {
.clk = {
- .name = "armtim_ck",
+ .hw.init = CLK_HW_INIT("armtim_ck", "ck_ref", &omap1_clk_gate_ops,
+ CLK_IS_CRITICAL),
.ops = &clkops_generic,
- .parent = &ck_ref,
.flags = CLOCK_IDLE_CONTROL,
.enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2),
.enable_bit = EN_TIMCK,
- .recalc = &followparent_recalc,
},
.idlect_shift = IDLTIM_ARM_SHIFT,
};

static struct arm_idlect1_clk armwdt_ck = {
.clk = {
- .name = "armwdt_ck",
+ .hw.init = CLK_HW_INIT("armwdt_ck", "ck_ref", &omap1_clk_full_ops, 0),
.ops = &clkops_generic,
- .parent = &ck_ref,
.flags = CLOCK_IDLE_CONTROL,
.enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2),
.enable_bit = EN_WDTCK,
@@ -191,11 +186,8 @@ static struct arm_idlect1_clk armwdt_ck = {
.idlect_shift = IDLWDT_ARM_SHIFT,
};

-static struct clk arminth_ck16xx = {
- .name = "arminth_ck",
- .ops = &clkops_null,
- .parent = &arm_ck,
- .recalc = &followparent_recalc,
+static struct omap1_clk arminth_ck16xx = {
+ .hw.init = CLK_HW_INIT("arminth_ck", "arm_ck", &omap1_clk_null_ops, 0),
/* Note: On 16xx the frequency can be divided by 2 by programming
* ARM_CKCTL:ARM_INTHCK_SEL(14) to 1
*
@@ -203,10 +195,9 @@ static struct clk arminth_ck16xx = {
*/
};

-static struct clk dsp_ck = {
- .name = "dsp_ck",
+static struct omap1_clk dsp_ck = {
+ .hw.init = CLK_HW_INIT("dsp_ck", "ck_dpll1", &omap1_clk_full_ops, 0),
.ops = &clkops_generic,
- .parent = &ck_dpll1,
.enable_reg = OMAP1_IO_ADDRESS(ARM_CKCTL),
.enable_bit = EN_DSPCK,
.rate_offset = CKCTL_DSPDIV_OFFSET,
@@ -215,20 +206,17 @@ static struct clk dsp_ck = {
.set_rate = omap1_clk_set_rate_ckctl_arm,
};

-static struct clk dspmmu_ck = {
- .name = "dspmmu_ck",
- .ops = &clkops_null,
- .parent = &ck_dpll1,
+static struct omap1_clk dspmmu_ck = {
+ .hw.init = CLK_HW_INIT("dspmmu_ck", "ck_dpll1", &omap1_clk_rate_ops, 0),
.rate_offset = CKCTL_DSPMMUDIV_OFFSET,
.recalc = &omap1_ckctl_recalc,
.round_rate = omap1_clk_round_rate_ckctl_arm,
.set_rate = omap1_clk_set_rate_ckctl_arm,
};

-static struct clk dspper_ck = {
- .name = "dspper_ck",
+static struct omap1_clk dspper_ck = {
+ .hw.init = CLK_HW_INIT("dspper_ck", "ck_dpll1", &omap1_clk_full_ops, 0),
.ops = &clkops_dspck,
- .parent = &ck_dpll1,
.enable_reg = DSP_IDLECT2,
.enable_bit = EN_PERCK,
.rate_offset = CKCTL_PERDIV_OFFSET,
@@ -237,29 +225,23 @@ static struct clk dspper_ck = {
.set_rate = &omap1_clk_set_rate_dsp_domain,
};

-static struct clk dspxor_ck = {
- .name = "dspxor_ck",
+static struct omap1_clk dspxor_ck = {
+ .hw.init = CLK_HW_INIT("dspxor_ck", "ck_ref", &omap1_clk_gate_ops, 0),
.ops = &clkops_dspck,
- .parent = &ck_ref,
.enable_reg = DSP_IDLECT2,
.enable_bit = EN_XORPCK,
- .recalc = &followparent_recalc,
};

-static struct clk dsptim_ck = {
- .name = "dsptim_ck",
+static struct omap1_clk dsptim_ck = {
+ .hw.init = CLK_HW_INIT("dsptim_ck", "ck_ref", &omap1_clk_gate_ops, 0),
.ops = &clkops_dspck,
- .parent = &ck_ref,
.enable_reg = DSP_IDLECT2,
.enable_bit = EN_DSPTIMCK,
- .recalc = &followparent_recalc,
};

static struct arm_idlect1_clk tc_ck = {
.clk = {
- .name = "tc_ck",
- .ops = &clkops_null,
- .parent = &ck_dpll1,
+ .hw.init = CLK_HW_INIT("tc_ck", "ck_dpll1", &omap1_clk_rate_ops, 0),
.flags = CLOCK_IDLE_CONTROL,
.rate_offset = CKCTL_TCDIV_OFFSET,
.recalc = &omap1_ckctl_recalc,
@@ -269,116 +251,88 @@ static struct arm_idlect1_clk tc_ck = {
.idlect_shift = IDLIF_ARM_SHIFT,
};

-static struct clk arminth_ck1510 = {
- .name = "arminth_ck",
- .ops = &clkops_null,
- .parent = &tc_ck.clk,
- .recalc = &followparent_recalc,
+static struct omap1_clk arminth_ck1510 = {
+ .hw.init = CLK_HW_INIT("arminth_ck", "tc_ck", &omap1_clk_null_ops, 0),
/* Note: On 1510 the frequency follows TC_CK
*
* 16xx version is in MPU clocks.
*/
};

-static struct clk tipb_ck = {
+static struct omap1_clk tipb_ck = {
/* No-idle controlled by "tc_ck" */
- .name = "tipb_ck",
- .ops = &clkops_null,
- .parent = &tc_ck.clk,
- .recalc = &followparent_recalc,
+ .hw.init = CLK_HW_INIT("tipb_ck", "tc_ck", &omap1_clk_null_ops, 0),
};

-static struct clk l3_ocpi_ck = {
+static struct omap1_clk l3_ocpi_ck = {
/* No-idle controlled by "tc_ck" */
- .name = "l3_ocpi_ck",
+ .hw.init = CLK_HW_INIT("l3_ocpi_ck", "tc_ck", &omap1_clk_gate_ops, 0),
.ops = &clkops_generic,
- .parent = &tc_ck.clk,
.enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT3),
.enable_bit = EN_OCPI_CK,
- .recalc = &followparent_recalc,
};

-static struct clk tc1_ck = {
- .name = "tc1_ck",
+static struct omap1_clk tc1_ck = {
+ .hw.init = CLK_HW_INIT("tc1_ck", "tc_ck", &omap1_clk_gate_ops, 0),
.ops = &clkops_generic,
- .parent = &tc_ck.clk,
.enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT3),
.enable_bit = EN_TC1_CK,
- .recalc = &followparent_recalc,
};

/*
* FIXME: This clock seems to be necessary but no-one has asked for its
* activation. [ pm.c (SRAM), CCP, Camera ]
*/
-static struct clk tc2_ck = {
- .name = "tc2_ck",
+
+static struct omap1_clk tc2_ck = {
+ .hw.init = CLK_HW_INIT("tc2_ck", "tc_ck", &omap1_clk_gate_ops, 0),
.ops = &clkops_generic,
- .parent = &tc_ck.clk,
.enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT3),
.enable_bit = EN_TC2_CK,
- .recalc = &followparent_recalc,
};

-static struct clk dma_ck = {
+static struct omap1_clk dma_ck = {
/* No-idle controlled by "tc_ck" */
- .name = "dma_ck",
- .ops = &clkops_null,
- .parent = &tc_ck.clk,
- .recalc = &followparent_recalc,
+ .hw.init = CLK_HW_INIT("dma_ck", "tc_ck", &omap1_clk_null_ops, 0),
};

-static struct clk dma_lcdfree_ck = {
- .name = "dma_lcdfree_ck",
- .ops = &clkops_null,
- .parent = &tc_ck.clk,
- .recalc = &followparent_recalc,
+static struct omap1_clk dma_lcdfree_ck = {
+ .hw.init = CLK_HW_INIT("dma_lcdfree_ck", "tc_ck", &omap1_clk_null_ops, 0),
};

static struct arm_idlect1_clk api_ck = {
.clk = {
- .name = "api_ck",
+ .hw.init = CLK_HW_INIT("api_ck", "tc_ck", &omap1_clk_gate_ops, 0),
.ops = &clkops_generic,
- .parent = &tc_ck.clk,
.flags = CLOCK_IDLE_CONTROL,
.enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2),
.enable_bit = EN_APICK,
- .recalc = &followparent_recalc,
},
.idlect_shift = IDLAPI_ARM_SHIFT,
};

static struct arm_idlect1_clk lb_ck = {
.clk = {
- .name = "lb_ck",
+ .hw.init = CLK_HW_INIT("lb_ck", "tc_ck", &omap1_clk_gate_ops, 0),
.ops = &clkops_generic,
- .parent = &tc_ck.clk,
.flags = CLOCK_IDLE_CONTROL,
.enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2),
.enable_bit = EN_LBCK,
- .recalc = &followparent_recalc,
},
.idlect_shift = IDLLB_ARM_SHIFT,
};

-static struct clk rhea1_ck = {
- .name = "rhea1_ck",
- .ops = &clkops_null,
- .parent = &tc_ck.clk,
- .recalc = &followparent_recalc,
+static struct omap1_clk rhea1_ck = {
+ .hw.init = CLK_HW_INIT("rhea1_ck", "tc_ck", &omap1_clk_null_ops, 0),
};

-static struct clk rhea2_ck = {
- .name = "rhea2_ck",
- .ops = &clkops_null,
- .parent = &tc_ck.clk,
- .recalc = &followparent_recalc,
+static struct omap1_clk rhea2_ck = {
+ .hw.init = CLK_HW_INIT("rhea2_ck", "tc_ck", &omap1_clk_null_ops, 0),
};

-static struct clk lcd_ck_16xx = {
- .name = "lcd_ck",
+static struct omap1_clk lcd_ck_16xx = {
+ .hw.init = CLK_HW_INIT("lcd_ck", "ck_dpll1", &omap1_clk_full_ops, 0),
.ops = &clkops_generic,
- .parent = &ck_dpll1,
.enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2),
.enable_bit = EN_LCDCK,
.rate_offset = CKCTL_LCDDIV_OFFSET,
@@ -389,9 +343,8 @@ static struct clk lcd_ck_16xx = {

static struct arm_idlect1_clk lcd_ck_1510 = {
.clk = {
- .name = "lcd_ck",
+ .hw.init = CLK_HW_INIT("lcd_ck", "ck_dpll1", &omap1_clk_full_ops, 0),
.ops = &clkops_generic,
- .parent = &ck_dpll1,
.flags = CLOCK_IDLE_CONTROL,
.enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2),
.enable_bit = EN_LCDCK,
@@ -403,37 +356,35 @@ static struct arm_idlect1_clk lcd_ck_1510 = {
.idlect_shift = OMAP1510_IDLLCD_ARM_SHIFT,
};

+
/*
* XXX The enable_bit here is misused - it simply switches between 12MHz
- * and 48MHz. Reimplement with clksel.
+ * and 48MHz. Reimplement with clk_mux.
*
* XXX does this need SYSC register handling?
*/
-static struct clk uart1_1510 = {
- .name = "uart1_ck",
- .ops = &clkops_null,
+static struct omap1_clk uart1_1510 = {
/* Direct from ULPD, no real parent */
- .parent = &armper_ck.clk,
- .rate = 12000000,
+ .hw.init = CLK_HW_INIT("uart1_ck", "armper_ck", &omap1_clk_full_ops, 0),
.flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
.enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
.enable_bit = CONF_MOD_UART1_CLK_MODE_R,
+ .round_rate = &omap1_round_uart_rate,
.set_rate = &omap1_set_uart_rate,
.recalc = &omap1_uart_recalc,
};

/*
* XXX The enable_bit here is misused - it simply switches between 12MHz
- * and 48MHz. Reimplement with clksel.
+ * and 48MHz. Reimplement with clk_mux.
*
* XXX SYSC register handling does not belong in the clock framework
*/
static struct uart_clk uart1_16xx = {
.clk = {
- .name = "uart1_ck",
.ops = &clkops_uart_16xx,
/* Direct from ULPD, no real parent */
- .parent = &armper_ck.clk,
+ .hw.init = CLK_HW_INIT("uart1_ck", "armper_ck", &omap1_clk_full_ops, 0),
.rate = 48000000,
.flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
.enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
@@ -444,54 +395,49 @@ static struct uart_clk uart1_16xx = {

/*
* XXX The enable_bit here is misused - it simply switches between 12MHz
- * and 48MHz. Reimplement with clksel.
+ * and 48MHz. Reimplement with clk_mux.
*
* XXX does this need SYSC register handling?
*/
-static struct clk uart2_ck = {
- .name = "uart2_ck",
- .ops = &clkops_null,
+static struct omap1_clk uart2_ck = {
/* Direct from ULPD, no real parent */
- .parent = &armper_ck.clk,
- .rate = 12000000,
+ .hw.init = CLK_HW_INIT("uart2_ck", "armper_ck", &omap1_clk_full_ops, 0),
.flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
.enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
.enable_bit = CONF_MOD_UART2_CLK_MODE_R,
+ .round_rate = &omap1_round_uart_rate,
.set_rate = &omap1_set_uart_rate,
.recalc = &omap1_uart_recalc,
};

/*
* XXX The enable_bit here is misused - it simply switches between 12MHz
- * and 48MHz. Reimplement with clksel.
+ * and 48MHz. Reimplement with clk_mux.
*
* XXX does this need SYSC register handling?
*/
-static struct clk uart3_1510 = {
- .name = "uart3_ck",
- .ops = &clkops_null,
+static struct omap1_clk uart3_1510 = {
/* Direct from ULPD, no real parent */
- .parent = &armper_ck.clk,
- .rate = 12000000,
+ .hw.init = CLK_HW_INIT("uart3_ck", "armper_ck", &omap1_clk_full_ops, 0),
.flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
.enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
.enable_bit = CONF_MOD_UART3_CLK_MODE_R,
+ .round_rate = &omap1_round_uart_rate,
.set_rate = &omap1_set_uart_rate,
.recalc = &omap1_uart_recalc,
};

/*
* XXX The enable_bit here is misused - it simply switches between 12MHz
- * and 48MHz. Reimplement with clksel.
+ * and 48MHz. Reimplement with clk_mux.
*
* XXX SYSC register handling does not belong in the clock framework
*/
static struct uart_clk uart3_16xx = {
.clk = {
- .name = "uart3_ck",
.ops = &clkops_uart_16xx,
/* Direct from ULPD, no real parent */
- .parent = &armper_ck.clk,
+ .hw.init = CLK_HW_INIT("uart3_ck", "armper_ck", &omap1_clk_full_ops, 0),
.rate = 48000000,
.flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
.enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
@@ -500,30 +446,30 @@ static struct uart_clk uart3_16xx = {
.sysc_addr = 0xfffb9854,
};

-static struct clk usb_clko = { /* 6 MHz output on W4_USB_CLKO */
- .name = "usb_clko",
+static struct omap1_clk usb_clko = { /* 6 MHz output on W4_USB_CLKO */
.ops = &clkops_generic,
/* Direct from ULPD, no parent */
+ .hw.init = CLK_HW_INIT_NO_PARENT("usb_clko", &omap1_clk_full_ops, 0),
.rate = 6000000,
.flags = ENABLE_REG_32BIT,
.enable_reg = OMAP1_IO_ADDRESS(ULPD_CLOCK_CTRL),
.enable_bit = USB_MCLK_EN_BIT,
};

-static struct clk usb_hhc_ck1510 = {
- .name = "usb_hhc_ck",
+static struct omap1_clk usb_hhc_ck1510 = {
.ops = &clkops_generic,
/* Direct from ULPD, no parent */
+ .hw.init = CLK_HW_INIT_NO_PARENT("usb_hhc_ck", &omap1_clk_full_ops, 0),
.rate = 48000000, /* Actually 2 clocks, 12MHz and 48MHz */
.flags = ENABLE_REG_32BIT,
.enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
.enable_bit = USB_HOST_HHC_UHOST_EN,
};

-static struct clk usb_hhc_ck16xx = {
- .name = "usb_hhc_ck",
+static struct omap1_clk usb_hhc_ck16xx = {
.ops = &clkops_generic,
/* Direct from ULPD, no parent */
+ .hw.init = CLK_HW_INIT_NO_PARENT("usb_hhc_ck", &omap1_clk_full_ops, 0),
.rate = 48000000,
/* OTG_SYSCON_2.OTG_PADEN == 0 (not 1510-compatible) */
.flags = ENABLE_REG_32BIT,
@@ -531,46 +477,46 @@ static struct clk usb_hhc_ck16xx = {
.enable_bit = OTG_SYSCON_2_UHOST_EN_SHIFT
};

-static struct clk usb_dc_ck = {
- .name = "usb_dc_ck",
+static struct omap1_clk usb_dc_ck = {
.ops = &clkops_generic,
/* Direct from ULPD, no parent */
+ .hw.init = CLK_HW_INIT_NO_PARENT("usb_dc_ck", &omap1_clk_full_ops, 0),
.rate = 48000000,
.enable_reg = OMAP1_IO_ADDRESS(SOFT_REQ_REG),
.enable_bit = SOFT_USB_OTG_DPLL_REQ_SHIFT,
};

-static struct clk uart1_7xx = {
- .name = "uart1_ck",
+static struct omap1_clk uart1_7xx = {
.ops = &clkops_generic,
/* Direct from ULPD, no parent */
+ .hw.init = CLK_HW_INIT_NO_PARENT("uart1_ck", &omap1_clk_full_ops, 0),
.rate = 12000000,
.enable_reg = OMAP1_IO_ADDRESS(SOFT_REQ_REG),
.enable_bit = 9,
};

-static struct clk uart2_7xx = {
- .name = "uart2_ck",
+static struct omap1_clk uart2_7xx = {
.ops = &clkops_generic,
/* Direct from ULPD, no parent */
+ .hw.init = CLK_HW_INIT_NO_PARENT("uart2_ck", &omap1_clk_full_ops, 0),
.rate = 12000000,
.enable_reg = OMAP1_IO_ADDRESS(SOFT_REQ_REG),
.enable_bit = 11,
};

-static struct clk mclk_1510 = {
- .name = "mclk",
+static struct omap1_clk mclk_1510 = {
.ops = &clkops_generic,
/* Direct from ULPD, no parent. May be enabled by ext hardware. */
+ .hw.init = CLK_HW_INIT_NO_PARENT("mclk", &omap1_clk_full_ops, 0),
.rate = 12000000,
.enable_reg = OMAP1_IO_ADDRESS(SOFT_REQ_REG),
.enable_bit = SOFT_COM_MCKO_REQ_SHIFT,
};

-static struct clk mclk_16xx = {
- .name = "mclk",
+static struct omap1_clk mclk_16xx = {
.ops = &clkops_generic,
/* Direct from ULPD, no parent. May be enabled by ext hardware. */
+ .hw.init = CLK_HW_INIT_NO_PARENT("mclk", &omap1_clk_full_ops, 0),
.enable_reg = OMAP1_IO_ADDRESS(COM_CLK_DIV_CTRL_SEL),
.enable_bit = COM_ULPD_PLL_CLK_REQ,
.set_rate = &omap1_set_ext_clk_rate,
@@ -578,17 +524,16 @@ static struct clk mclk_16xx = {
.init = &omap1_init_ext_clk,
};

-static struct clk bclk_1510 = {
- .name = "bclk",
- .ops = &clkops_generic,
+static struct omap1_clk bclk_1510 = {
/* Direct from ULPD, no parent. May be enabled by ext hardware. */
+ .hw.init = CLK_HW_INIT_NO_PARENT("bclk", &omap1_clk_rate_ops, 0),
.rate = 12000000,
};

-static struct clk bclk_16xx = {
- .name = "bclk",
+static struct omap1_clk bclk_16xx = {
.ops = &clkops_generic,
/* Direct from ULPD, no parent. May be enabled by ext hardware. */
+ .hw.init = CLK_HW_INIT_NO_PARENT("bclk", &omap1_clk_full_ops, 0),
.enable_reg = OMAP1_IO_ADDRESS(SWD_CLK_DIV_CTRL_SEL),
.enable_bit = SWD_ULPD_PLL_CLK_REQ,
.set_rate = &omap1_set_ext_clk_rate,
@@ -596,11 +541,10 @@ static struct clk bclk_16xx = {
.init = &omap1_init_ext_clk,
};

-static struct clk mmc1_ck = {
- .name = "mmc1_ck",
+static struct omap1_clk mmc1_ck = {
.ops = &clkops_generic,
/* Functional clock is direct from ULPD, interface clock is ARMPER */
- .parent = &armper_ck.clk,
+ .hw.init = CLK_HW_INIT("mmc1_ck", "armper_ck", &omap1_clk_full_ops, 0),
.rate = 48000000,
.flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
.enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
@@ -611,32 +555,29 @@ static struct clk mmc1_ck = {
* XXX MOD_CONF_CTRL_0 bit 20 is defined in the 1510 TRM as
* CONF_MOD_MCBSP3_AUXON ??
*/
-static struct clk mmc2_ck = {
- .name = "mmc2_ck",
+static struct omap1_clk mmc2_ck = {
.ops = &clkops_generic,
/* Functional clock is direct from ULPD, interface clock is ARMPER */
- .parent = &armper_ck.clk,
+ .hw.init = CLK_HW_INIT("mmc2_ck", "armper_ck", &omap1_clk_full_ops, 0),
.rate = 48000000,
.flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
.enable_reg = OMAP1_IO_ADDRESS(MOD_CONF_CTRL_0),
.enable_bit = 20,
};

-static struct clk mmc3_ck = {
- .name = "mmc3_ck",
+static struct omap1_clk mmc3_ck = {
.ops = &clkops_generic,
/* Functional clock is direct from ULPD, interface clock is ARMPER */
- .parent = &armper_ck.clk,
+ .hw.init = CLK_HW_INIT("mmc3_ck", "armper_ck", &omap1_clk_full_ops, 0),
.rate = 48000000,
.flags = ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
.enable_reg = OMAP1_IO_ADDRESS(SOFT_REQ_REG),
.enable_bit = SOFT_MMC_DPLL_REQ_SHIFT,
};

-static struct clk virtual_ck_mpu = {
- .name = "mpu",
- .ops = &clkops_null,
- .parent = &arm_ck, /* Is smarter alias for */
+static struct omap1_clk virtual_ck_mpu = {
+ /* Is smarter alias for arm_ck */
+ .hw.init = CLK_HW_INIT("mpu", "arm_ck", &omap1_clk_rate_ops, 0),
.recalc = &followparent_recalc,
.set_rate = &omap1_select_table_rate,
.round_rate = &omap1_round_to_table_rate,
@@ -644,20 +585,14 @@ static struct clk virtual_ck_mpu = {

/* virtual functional clock domain for I2C. Just for making sure that ARMXOR_CK
remains active during MPU idle whenever this is enabled */
-static struct clk i2c_fck = {
- .name = "i2c_fck",
- .ops = &clkops_null,
+static struct omap1_clk i2c_fck = {
+ .hw.init = CLK_HW_INIT("i2c_fck", "armxor_ck", &omap1_clk_gate_ops, 0),
.flags = CLOCK_NO_IDLE_PARENT,
- .parent = &armxor_ck.clk,
- .recalc = &followparent_recalc,
};

-static struct clk i2c_ick = {
- .name = "i2c_ick",
- .ops = &clkops_null,
+static struct omap1_clk i2c_ick = {
+ .hw.init = CLK_HW_INIT("i2c_ick", "armper_ck", &omap1_clk_gate_ops, 0),
.flags = CLOCK_NO_IDLE_PARENT,
- .parent = &armper_ck.clk,
- .recalc = &followparent_recalc,
};

/*
@@ -666,81 +601,81 @@ static struct clk i2c_ick = {

static struct omap_clk omap_clks[] = {
/* non-ULPD clocks */
- CLK(NULL, "ck_ref", &ck_ref, CK_16XX | CK_1510 | CK_310 | CK_7XX),
- CLK(NULL, "ck_dpll1", &ck_dpll1, CK_16XX | CK_1510 | CK_310 | CK_7XX),
+ CLK(NULL, "ck_ref", &ck_ref.hw, CK_16XX | CK_1510 | CK_310 | CK_7XX),
+ CLK(NULL, "ck_dpll1", &ck_dpll1.hw, CK_16XX | CK_1510 | CK_310 | CK_7XX),
/* CK_GEN1 clocks */
- CLK(NULL, "ck_dpll1out", &ck_dpll1out.clk, CK_16XX),
- CLK(NULL, "ck_sossi", &sossi_ck, CK_16XX),
- CLK(NULL, "arm_ck", &arm_ck, CK_16XX | CK_1510 | CK_310),
- CLK(NULL, "armper_ck", &armper_ck.clk, CK_16XX | CK_1510 | CK_310),
- CLK("omap_gpio.0", "ick", &arm_gpio_ck, CK_1510 | CK_310),
- CLK(NULL, "armxor_ck", &armxor_ck.clk, CK_16XX | CK_1510 | CK_310 | CK_7XX),
- CLK(NULL, "armtim_ck", &armtim_ck.clk, CK_16XX | CK_1510 | CK_310),
- CLK("omap_wdt", "fck", &armwdt_ck.clk, CK_16XX | CK_1510 | CK_310),
- CLK("omap_wdt", "ick", &armper_ck.clk, CK_16XX),
- CLK("omap_wdt", "ick", &dummy_ck, CK_1510 | CK_310),
- CLK(NULL, "arminth_ck", &arminth_ck1510, CK_1510 | CK_310),
- CLK(NULL, "arminth_ck", &arminth_ck16xx, CK_16XX),
+ CLK(NULL, "ck_dpll1out", &ck_dpll1out.clk.hw, CK_16XX),
+ CLK(NULL, "ck_sossi", &sossi_ck.hw, CK_16XX),
+ CLK(NULL, "arm_ck", &arm_ck.hw, CK_16XX | CK_1510 | CK_310),
+ CLK(NULL, "armper_ck", &armper_ck.clk.hw, CK_16XX | CK_1510 | CK_310),
+ CLK("omap_gpio.0", "ick", &arm_gpio_ck.hw, CK_1510 | CK_310),
+ CLK(NULL, "armxor_ck", &armxor_ck.clk.hw, CK_16XX | CK_1510 | CK_310 | CK_7XX),
+ CLK(NULL, "armtim_ck", &armtim_ck.clk.hw, CK_16XX | CK_1510 | CK_310),
+ CLK("omap_wdt", "fck", &armwdt_ck.clk.hw, CK_16XX | CK_1510 | CK_310),
+ CLK("omap_wdt", "ick", &armper_ck.clk.hw, CK_16XX),
+ CLK("omap_wdt", "ick", &dummy_ck.hw, CK_1510 | CK_310),
+ CLK(NULL, "arminth_ck", &arminth_ck1510.hw, CK_1510 | CK_310),
+ CLK(NULL, "arminth_ck", &arminth_ck16xx.hw, CK_16XX),
/* CK_GEN2 clocks */
- CLK(NULL, "dsp_ck", &dsp_ck, CK_16XX | CK_1510 | CK_310),
- CLK(NULL, "dspmmu_ck", &dspmmu_ck, CK_16XX | CK_1510 | CK_310),
- CLK(NULL, "dspper_ck", &dspper_ck, CK_16XX | CK_1510 | CK_310),
- CLK(NULL, "dspxor_ck", &dspxor_ck, CK_16XX | CK_1510 | CK_310),
- CLK(NULL, "dsptim_ck", &dsptim_ck, CK_16XX | CK_1510 | CK_310),
+ CLK(NULL, "dsp_ck", &dsp_ck.hw, CK_16XX | CK_1510 | CK_310),
+ CLK(NULL, "dspmmu_ck", &dspmmu_ck.hw, CK_16XX | CK_1510 | CK_310),
+ CLK(NULL, "dspper_ck", &dspper_ck.hw, CK_16XX | CK_1510 | CK_310),
+ CLK(NULL, "dspxor_ck", &dspxor_ck.hw, CK_16XX | CK_1510 | CK_310),
+ CLK(NULL, "dsptim_ck", &dsptim_ck.hw, CK_16XX | CK_1510 | CK_310),
/* CK_GEN3 clocks */
- CLK(NULL, "tc_ck", &tc_ck.clk, CK_16XX | CK_1510 | CK_310 | CK_7XX),
- CLK(NULL, "tipb_ck", &tipb_ck, CK_1510 | CK_310),
- CLK(NULL, "l3_ocpi_ck", &l3_ocpi_ck, CK_16XX | CK_7XX),
- CLK(NULL, "tc1_ck", &tc1_ck, CK_16XX),
- CLK(NULL, "tc2_ck", &tc2_ck, CK_16XX),
- CLK(NULL, "dma_ck", &dma_ck, CK_16XX | CK_1510 | CK_310),
- CLK(NULL, "dma_lcdfree_ck", &dma_lcdfree_ck, CK_16XX),
- CLK(NULL, "api_ck", &api_ck.clk, CK_16XX | CK_1510 | CK_310 | CK_7XX),
- CLK(NULL, "lb_ck", &lb_ck.clk, CK_1510 | CK_310),
- CLK(NULL, "rhea1_ck", &rhea1_ck, CK_16XX),
- CLK(NULL, "rhea2_ck", &rhea2_ck, CK_16XX),
- CLK(NULL, "lcd_ck", &lcd_ck_16xx, CK_16XX | CK_7XX),
- CLK(NULL, "lcd_ck", &lcd_ck_1510.clk, CK_1510 | CK_310),
+ CLK(NULL, "tc_ck", &tc_ck.clk.hw, CK_16XX | CK_1510 | CK_310 | CK_7XX),
+ CLK(NULL, "tipb_ck", &tipb_ck.hw, CK_1510 | CK_310),
+ CLK(NULL, "l3_ocpi_ck", &l3_ocpi_ck.hw, CK_16XX | CK_7XX),
+ CLK(NULL, "tc1_ck", &tc1_ck.hw, CK_16XX),
+ CLK(NULL, "tc2_ck", &tc2_ck.hw, CK_16XX),
+ CLK(NULL, "dma_ck", &dma_ck.hw, CK_16XX | CK_1510 | CK_310),
+ CLK(NULL, "dma_lcdfree_ck", &dma_lcdfree_ck.hw, CK_16XX),
+ CLK(NULL, "api_ck", &api_ck.clk.hw, CK_16XX | CK_1510 | CK_310 | CK_7XX),
+ CLK(NULL, "lb_ck", &lb_ck.clk.hw, CK_1510 | CK_310),
+ CLK(NULL, "rhea1_ck", &rhea1_ck.hw, CK_16XX),
+ CLK(NULL, "rhea2_ck", &rhea2_ck.hw, CK_16XX),
+ CLK(NULL, "lcd_ck", &lcd_ck_16xx.hw, CK_16XX | CK_7XX),
+ CLK(NULL, "lcd_ck", &lcd_ck_1510.clk.hw, CK_1510 | CK_310),
/* ULPD clocks */
- CLK(NULL, "uart1_ck", &uart1_1510, CK_1510 | CK_310),
- CLK(NULL, "uart1_ck", &uart1_16xx.clk, CK_16XX),
- CLK(NULL, "uart1_ck", &uart1_7xx, CK_7XX),
- CLK(NULL, "uart2_ck", &uart2_ck, CK_16XX | CK_1510 | CK_310),
- CLK(NULL, "uart2_ck", &uart2_7xx, CK_7XX),
- CLK(NULL, "uart3_ck", &uart3_1510, CK_1510 | CK_310),
- CLK(NULL, "uart3_ck", &uart3_16xx.clk, CK_16XX),
- CLK(NULL, "usb_clko", &usb_clko, CK_16XX | CK_1510 | CK_310),
- CLK(NULL, "usb_hhc_ck", &usb_hhc_ck1510, CK_1510 | CK_310),
- CLK(NULL, "usb_hhc_ck", &usb_hhc_ck16xx, CK_16XX),
- CLK(NULL, "usb_dc_ck", &usb_dc_ck, CK_16XX | CK_7XX),
- CLK(NULL, "mclk", &mclk_1510, CK_1510 | CK_310),
- CLK(NULL, "mclk", &mclk_16xx, CK_16XX),
- CLK(NULL, "bclk", &bclk_1510, CK_1510 | CK_310),
- CLK(NULL, "bclk", &bclk_16xx, CK_16XX),
- CLK("mmci-omap.0", "fck", &mmc1_ck, CK_16XX | CK_1510 | CK_310),
- CLK("mmci-omap.0", "fck", &mmc3_ck, CK_7XX),
- CLK("mmci-omap.0", "ick", &armper_ck.clk, CK_16XX | CK_1510 | CK_310 | CK_7XX),
- CLK("mmci-omap.1", "fck", &mmc2_ck, CK_16XX),
- CLK("mmci-omap.1", "ick", &armper_ck.clk, CK_16XX),
+ CLK(NULL, "uart1_ck", &uart1_1510.hw, CK_1510 | CK_310),
+ CLK(NULL, "uart1_ck", &uart1_16xx.clk.hw, CK_16XX),
+ CLK(NULL, "uart1_ck", &uart1_7xx.hw, CK_7XX),
+ CLK(NULL, "uart2_ck", &uart2_ck.hw, CK_16XX | CK_1510 | CK_310),
+ CLK(NULL, "uart2_ck", &uart2_7xx.hw, CK_7XX),
+ CLK(NULL, "uart3_ck", &uart3_1510.hw, CK_1510 | CK_310),
+ CLK(NULL, "uart3_ck", &uart3_16xx.clk.hw, CK_16XX),
+ CLK(NULL, "usb_clko", &usb_clko.hw, CK_16XX | CK_1510 | CK_310),
+ CLK(NULL, "usb_hhc_ck", &usb_hhc_ck1510.hw, CK_1510 | CK_310),
+ CLK(NULL, "usb_hhc_ck", &usb_hhc_ck16xx.hw, CK_16XX),
+ CLK(NULL, "usb_dc_ck", &usb_dc_ck.hw, CK_16XX | CK_7XX),
+ CLK(NULL, "mclk", &mclk_1510.hw, CK_1510 | CK_310),
+ CLK(NULL, "mclk", &mclk_16xx.hw, CK_16XX),
+ CLK(NULL, "bclk", &bclk_1510.hw, CK_1510 | CK_310),
+ CLK(NULL, "bclk", &bclk_16xx.hw, CK_16XX),
+ CLK("mmci-omap.0", "fck", &mmc1_ck.hw, CK_16XX | CK_1510 | CK_310),
+ CLK("mmci-omap.0", "fck", &mmc3_ck.hw, CK_7XX),
+ CLK("mmci-omap.0", "ick", &armper_ck.clk.hw, CK_16XX | CK_1510 | CK_310 | CK_7XX),
+ CLK("mmci-omap.1", "fck", &mmc2_ck.hw, CK_16XX),
+ CLK("mmci-omap.1", "ick", &armper_ck.clk.hw, CK_16XX),
/* Virtual clocks */
- CLK(NULL, "mpu", &virtual_ck_mpu, CK_16XX | CK_1510 | CK_310),
- CLK("omap_i2c.1", "fck", &i2c_fck, CK_16XX | CK_1510 | CK_310 | CK_7XX),
- CLK("omap_i2c.1", "ick", &i2c_ick, CK_16XX),
- CLK("omap_i2c.1", "ick", &dummy_ck, CK_1510 | CK_310 | CK_7XX),
- CLK("omap1_spi100k.1", "fck", &dummy_ck, CK_7XX),
- CLK("omap1_spi100k.1", "ick", &dummy_ck, CK_7XX),
- CLK("omap1_spi100k.2", "fck", &dummy_ck, CK_7XX),
- CLK("omap1_spi100k.2", "ick", &dummy_ck, CK_7XX),
- CLK("omap_uwire", "fck", &armxor_ck.clk, CK_16XX | CK_1510 | CK_310),
- CLK("omap-mcbsp.1", "ick", &dspper_ck, CK_16XX),
- CLK("omap-mcbsp.1", "ick", &dummy_ck, CK_1510 | CK_310),
- CLK("omap-mcbsp.2", "ick", &armper_ck.clk, CK_16XX),
- CLK("omap-mcbsp.2", "ick", &dummy_ck, CK_1510 | CK_310),
- CLK("omap-mcbsp.3", "ick", &dspper_ck, CK_16XX),
- CLK("omap-mcbsp.3", "ick", &dummy_ck, CK_1510 | CK_310),
- CLK("omap-mcbsp.1", "fck", &dspxor_ck, CK_16XX | CK_1510 | CK_310),
- CLK("omap-mcbsp.2", "fck", &armper_ck.clk, CK_16XX | CK_1510 | CK_310),
- CLK("omap-mcbsp.3", "fck", &dspxor_ck, CK_16XX | CK_1510 | CK_310),
+ CLK(NULL, "mpu", &virtual_ck_mpu.hw, CK_16XX | CK_1510 | CK_310),
+ CLK("omap_i2c.1", "fck", &i2c_fck.hw, CK_16XX | CK_1510 | CK_310 | CK_7XX),
+ CLK("omap_i2c.1", "ick", &i2c_ick.hw, CK_16XX),
+ CLK("omap_i2c.1", "ick", &dummy_ck.hw, CK_1510 | CK_310 | CK_7XX),
+ CLK("omap1_spi100k.1", "fck", &dummy_ck.hw, CK_7XX),
+ CLK("omap1_spi100k.1", "ick", &dummy_ck.hw, CK_7XX),
+ CLK("omap1_spi100k.2", "fck", &dummy_ck.hw, CK_7XX),
+ CLK("omap1_spi100k.2", "ick", &dummy_ck.hw, CK_7XX),
+ CLK("omap_uwire", "fck", &armxor_ck.clk.hw, CK_16XX | CK_1510 | CK_310),
+ CLK("omap-mcbsp.1", "ick", &dspper_ck.hw, CK_16XX),
+ CLK("omap-mcbsp.1", "ick", &dummy_ck.hw, CK_1510 | CK_310),
+ CLK("omap-mcbsp.2", "ick", &armper_ck.clk.hw, CK_16XX),
+ CLK("omap-mcbsp.2", "ick", &dummy_ck.hw, CK_1510 | CK_310),
+ CLK("omap-mcbsp.3", "ick", &dspper_ck.hw, CK_16XX),
+ CLK("omap-mcbsp.3", "ick", &dummy_ck.hw, CK_1510 | CK_310),
+ CLK("omap-mcbsp.1", "fck", &dspxor_ck.hw, CK_16XX | CK_1510 | CK_310),
+ CLK("omap-mcbsp.2", "fck", &armper_ck.clk.hw, CK_16XX | CK_1510 | CK_310),
+ CLK("omap-mcbsp.3", "fck", &dspxor_ck.hw, CK_16XX | CK_1510 | CK_310),
};

/*
@@ -779,9 +714,6 @@ int __init omap1_clk_init(void)
/* By default all idlect1 clocks are allowed to idle */
arm_idlect1_mask = ~0;

- for (c = omap_clks; c < omap_clks + ARRAY_SIZE(omap_clks); c++)
- clk_preinit(c->lk.clk);
-
cpu_mask = 0;
if (cpu_is_omap1710())
cpu_mask |= CK_1710;
@@ -794,16 +726,10 @@ int __init omap1_clk_init(void)
if (cpu_is_omap310())
cpu_mask |= CK_310;

- for (c = omap_clks; c < omap_clks + ARRAY_SIZE(omap_clks); c++)
- if (c->cpu & cpu_mask) {
- clkdev_add(&c->lk);
- clk_register(c->lk.clk);
- }
-
/* Pointers to these clocks are needed by code in clock.c */
- api_ck_p = clk_get(NULL, "api_ck");
- ck_dpll1_p = clk_get(NULL, "ck_dpll1");
- ck_ref_p = clk_get(NULL, "ck_ref");
+ api_ck_p = &api_ck.clk;
+ ck_dpll1_p = &ck_dpll1;
+ ck_ref_p = &ck_ref;

if (cpu_is_omap7xx())
ck_ref.rate = 13000000;
@@ -845,10 +771,7 @@ int __init omap1_clk_init(void)
}
}
}
- propagate_rate(&ck_dpll1);
- /* Cache rates for clocks connected to ck_ref (not dpll1) */
- propagate_rate(&ck_ref);
- omap1_show_rates();
+
if (machine_is_omap_perseus2() || machine_is_omap_fsample()) {
/* Select slicer output as OMAP input clock */
omap_writew(omap_readw(OMAP7XX_PCC_UPLD_CTRL) & ~0x1,
@@ -880,16 +803,28 @@ int __init omap1_clk_init(void)
*/
omap_writew(0x0000, ARM_IDLECT2); /* Turn LCD clock off also */

- /*
- * Only enable those clocks we will need, let the drivers
- * enable other clocks as necessary
- */
- clk_enable(&armper_ck.clk);
- clk_enable(&armxor_ck.clk);
- clk_enable(&armtim_ck.clk); /* This should be done by timer code */
+ for (c = omap_clks; c < omap_clks + ARRAY_SIZE(omap_clks); c++) {
+ if (!(c->cpu & cpu_mask))
+ continue;
+
+ if (c->lk.clk_hw->init) { /* NULL if provider already registered */
+ const struct clk_init_data *init = c->lk.clk_hw->init;
+ const char *name = c->lk.clk_hw->init->name;
+ int err;
+
+ err = clk_hw_register(NULL, c->lk.clk_hw);
+ if (err < 0) {
+ pr_err("failed to register clock \"%s\"! (%d)\n", name, err);
+ /* may be tried again, restore init data */
+ c->lk.clk_hw->init = init;
+ continue;
+ }
+ }
+
+ clk_hw_register_clkdev(c->lk.clk_hw, c->lk.con_id, c->lk.dev_id);
+ }

- if (cpu_is_omap15xx())
- clk_enable(&arm_gpio_ck);
+ omap1_show_rates();

return 0;
}
@@ -901,7 +836,7 @@ void __init omap1_clk_late_init(void)
unsigned long rate = ck_dpll1.rate;

/* Find the highest supported frequency and enable it */
- if (omap1_select_table_rate(&virtual_ck_mpu, ~0)) {
+ if (omap1_select_table_rate(&virtual_ck_mpu, ~0, arm_ck.rate)) {
pr_err("System frequencies not set, using default. Check your config.\n");
/*
* Reprogramming the DPLL is tricky, it must be done from SRAM.
diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c
index 5a173fc2a1ca..57f72cc0893f 100644
--- a/arch/arm/mach-omap1/io.c
+++ b/arch/arm/mach-omap1/io.c
@@ -126,11 +126,6 @@ void __init omap1_init_early(void)
*/
omap_writew(0x0, MPU_PUBLIC_TIPB_CNTL);
omap_writew(0x0, MPU_PRIVATE_TIPB_CNTL);
-
- /* Must init clocks early to assure that timer interrupt works
- */
- omap1_clk_init();
- omap1_mux_init();
}

void __init omap1_init_late(void)
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c
index de590a85a42b..c68b0d5a2e0f 100644
--- a/arch/arm/mach-omap1/time.c
+++ b/arch/arm/mach-omap1/time.c
@@ -48,9 +48,11 @@
#include <asm/irq.h>

#include <mach/hardware.h>
+#include <mach/mux.h>
#include <asm/mach/irq.h>
#include <asm/mach/time.h>

+#include "clock.h"
#include "iomap.h"
#include "common.h"

@@ -224,6 +226,9 @@ static inline void omap_mpu_timer_init(void)
*/
void __init omap1_timer_init(void)
{
+ omap1_clk_init();
+ omap1_mux_init();
+
if (omap_32k_timer_init() != 0)
omap_mpu_timer_init();
}
--
2.35.1

2022-03-12 14:23:37

by Tony Lindgren

[permalink] [raw]
Subject: Re: [RFC RFT PATCH 0/4] ARM: OMAP1: clock: Convert to CCF

* Janusz Krzysztofik <[email protected]> [220310 23:32]:
> The main motivation behind this series is planned resurection of OMAP1
> camera driver. Since OMAP1 clock internals have never been visible to
> drivers, that driver used to use v4l2-clk to expose a pixel clock for a
> sensor. The v4l2-clk code has been recently depreciated and removed from
> the media subtree, hence the need for an alternative solution.

Nice :) This will also help Arnd with building multi-v5 kernels.

Regards,

Tony

2022-03-21 06:05:49

by Aaro Koskinen

[permalink] [raw]
Subject: Re: [RFC RFT PATCH 0/4] ARM: OMAP1: clock: Convert to CCF

Hi,

On Sat, Mar 19, 2022 at 08:49:55PM +0200, Aaro Koskinen wrote:
> On Sat, Mar 12, 2022 at 10:14:31AM +0200, Tony Lindgren wrote:
> > * Janusz Krzysztofik <[email protected]> [220310 23:32]:
> > > The main motivation behind this series is planned resurection of OMAP1
> > > camera driver. Since OMAP1 clock internals have never been visible to
> > > drivers, that driver used to use v4l2-clk to expose a pixel clock for a
> > > sensor. The v4l2-clk code has been recently depreciated and removed from
> > > the media subtree, hence the need for an alternative solution.
> >
> > Nice :) This will also help Arnd with building multi-v5 kernels.
>
> This will need more testing still... The patch 4 is breaking at least 770
> (the display/fb doesn't work anymore).

Patches 1-3 are OK on Nokia 770, OSK and Palm TE.

Patch 4 breaks 770, but OSK and Palm TE are OK.

Below is the problem with 770. As a quick hack, I tried replacing
all clk_enable/disable()s with prepare_enable/disable_unprepare()s in
drivers/video/fbdev/omap/hwa742.c and drivers/video/fbdev/omap/sossi.c
and that seems to help...

[ 0.374389] omapfb: lph8923 rev 92 LCD detected, 16 data lines
[ 0.374816] omapfb: configured for panel lph8923
[ 0.383789] omapfb: LCDC initialized
[ 0.384216] ------------[ cut here ]------------
[ 0.384368] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:1012 clk_core_enable+0x94/0xb0
[ 0.384613] Enabling unprepared ck_sossi
[ 0.384704] Modules linked in:
[ 0.384796] CPU: 0 PID: 1 Comm: swapper Not tainted 5.17.0-rc8-770-los_381206+-00072-gb2406fc1ddd4 #2
[ 0.385009] Hardware name: Nokia 770
[ 0.385101] unwind_backtrace from show_stack+0x10/0x14
[ 0.385314] show_stack from __warn+0xac/0xe4
[ 0.385528] __warn from warn_slowpath_fmt+0x90/0xc8
[ 0.385711] warn_slowpath_fmt from clk_core_enable+0x94/0xb0
[ 0.385894] clk_core_enable from clk_core_enable_lock+0x18/0x2c
[ 0.386077] clk_core_enable_lock from sossi_init+0xa0/0x258
[ 0.386260] sossi_init from hwa742_init+0x90/0x538
[ 0.386474] hwa742_init from omapfb_do_probe+0x200/0x68c
[ 0.386657] omapfb_do_probe from mipid_spi_probe+0x1b4/0x230
[ 0.386840] mipid_spi_probe from spi_probe+0x48/0x6c
[ 0.387054] spi_probe from really_probe+0xac/0x2f0
[ 0.387237] really_probe from __driver_probe_device+0x80/0xe4
[ 0.387390] __driver_probe_device from driver_probe_device+0x30/0xd8
[ 0.387573] driver_probe_device from __driver_attach+0x70/0xf0
[ 0.387756] __driver_attach from bus_for_each_dev+0x74/0xc0
[ 0.387908] bus_for_each_dev from bus_add_driver+0x14c/0x1d8
[ 0.388061] bus_add_driver from driver_register+0x74/0x108
[ 0.388244] driver_register from do_one_initcall+0x4c/0x1cc
[ 0.388427] do_one_initcall from kernel_init_freeable+0x170/0x1f4
[ 0.388641] kernel_init_freeable from kernel_init+0x10/0x108
[ 0.388824] kernel_init from ret_from_fork+0x14/0x2c
[ 0.388977] Exception stack(0xc0c41fb0 to 0xc0c41ff8)
[ 0.389099] 1fa0: 00000000 00000000 00000000 00000000
[ 0.389282] 1fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 0.389434] 1fe0: 00000000 00000000 00000000 00000000 00000013 00000000
[ 0.389556] ---[ end trace 0000000000000000 ]---
[ 0.389709] omapfb omapfb: invalid SoSSI sync pattern: 00000000, 00000000
[ 0.389831] ------------[ cut here ]------------
[ 0.389923] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:953 clk_core_disable+0xb4/0xcc
[ 0.390136] ck_sossi already disabled
[ 0.390228] Modules linked in:
[ 0.390319] CPU: 0 PID: 1 Comm: swapper Tainted: G W 5.17.0-rc8-770-los_381206+-00072-gb2406fc1ddd4 #2
[ 0.390502] Hardware name: Nokia 770
[ 0.390594] unwind_backtrace from show_stack+0x10/0x14
[ 0.390808] show_stack from __warn+0xac/0xe4
[ 0.391021] __warn from warn_slowpath_fmt+0x90/0xc8
[ 0.391204] warn_slowpath_fmt from clk_core_disable+0xb4/0xcc
[ 0.391387] clk_core_disable from clk_core_disable_lock+0x18/0x24
[ 0.391540] clk_core_disable_lock from sossi_init+0x1bc/0x258
[ 0.391754] sossi_init from hwa742_init+0x90/0x538
[ 0.391937] hwa742_init from omapfb_do_probe+0x200/0x68c
[ 0.392120] omapfb_do_probe from mipid_spi_probe+0x1b4/0x230
[ 0.392333] mipid_spi_probe from spi_probe+0x48/0x6c
[ 0.392547] spi_probe from really_probe+0xac/0x2f0
[ 0.392730] really_probe from __driver_probe_device+0x80/0xe4
[ 0.392883] __driver_probe_device from driver_probe_device+0x30/0xd8
[ 0.393066] driver_probe_device from __driver_attach+0x70/0xf0
[ 0.393249] __driver_attach from bus_for_each_dev+0x74/0xc0
[ 0.393402] bus_for_each_dev from bus_add_driver+0x14c/0x1d8
[ 0.393585] bus_add_driver from driver_register+0x74/0x108
[ 0.393737] driver_register from do_one_initcall+0x4c/0x1cc
[ 0.393920] do_one_initcall from kernel_init_freeable+0x170/0x1f4
[ 0.394134] kernel_init_freeable from kernel_init+0x10/0x108
[ 0.394317] kernel_init from ret_from_fork+0x14/0x2c
[ 0.394470] Exception stack(0xc0c41fb0 to 0xc0c41ff8)
[ 0.394592] 1fa0: 00000000 00000000 00000000 00000000
[ 0.394775] 1fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 0.394958] 1fe0: 00000000 00000000 00000000 00000000 00000013 00000000
[ 0.395080] ---[ end trace 0000000000000000 ]---
[ 0.417907] omapfb omapfb: controller initialization failed (-19)

A.

2022-03-21 09:15:00

by Janusz Krzysztofik

[permalink] [raw]
Subject: Re: [RFC RFT PATCH 0/4] ARM: OMAP1: clock: Convert to CCF

Hi Aaro,

On Saturday, 19 March 2022 22:21:19 CET Aaro Koskinen wrote:
> Hi,
>
> On Sat, Mar 19, 2022 at 08:49:55PM +0200, Aaro Koskinen wrote:
> > On Sat, Mar 12, 2022 at 10:14:31AM +0200, Tony Lindgren wrote:
> > > * Janusz Krzysztofik <[email protected]> [220310 23:32]:
> > > > The main motivation behind this series is planned resurection of OMAP1
> > > > camera driver. Since OMAP1 clock internals have never been visible to
> > > > drivers, that driver used to use v4l2-clk to expose a pixel clock for a
> > > > sensor. The v4l2-clk code has been recently depreciated and removed from
> > > > the media subtree, hence the need for an alternative solution.
> > >
> > > Nice :) This will also help Arnd with building multi-v5 kernels.
> >
> > This will need more testing still... The patch 4 is breaking at least 770
> > (the display/fb doesn't work anymore).
>
> Patches 1-3 are OK on Nokia 770, OSK and Palm TE.
>
> Patch 4 breaks 770, but OSK and Palm TE are OK.
>
> Below is the problem with 770. As a quick hack, I tried replacing
> all clk_enable/disable()s with prepare_enable/disable_unprepare()s in
> drivers/video/fbdev/omap/hwa742.c and drivers/video/fbdev/omap/sossi.c
> and that seems to help...
>
> [ 0.374389] omapfb: lph8923 rev 92 LCD detected, 16 data lines
> [ 0.374816] omapfb: configured for panel lph8923
> [ 0.383789] omapfb: LCDC initialized
> [ 0.384216] ------------[ cut here ]------------
> [ 0.384368] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:1012 clk_core_enable+0x94/0xb0
> [ 0.384613] Enabling unprepared ck_sossi

Yes, I've identified still a few drivers that need to be updated, I'll
prepare v2 of PATCH 3/4 and resubmit.

Thanks,
Janusz

> [ 0.384704] Modules linked in:
> [ 0.384796] CPU: 0 PID: 1 Comm: swapper Not tainted 5.17.0-rc8-770-los_381206+-00072-gb2406fc1ddd4 #2
> [ 0.385009] Hardware name: Nokia 770
> [ 0.385101] unwind_backtrace from show_stack+0x10/0x14
> [ 0.385314] show_stack from __warn+0xac/0xe4
> [ 0.385528] __warn from warn_slowpath_fmt+0x90/0xc8
> [ 0.385711] warn_slowpath_fmt from clk_core_enable+0x94/0xb0
> [ 0.385894] clk_core_enable from clk_core_enable_lock+0x18/0x2c
> [ 0.386077] clk_core_enable_lock from sossi_init+0xa0/0x258
> [ 0.386260] sossi_init from hwa742_init+0x90/0x538
> [ 0.386474] hwa742_init from omapfb_do_probe+0x200/0x68c
> [ 0.386657] omapfb_do_probe from mipid_spi_probe+0x1b4/0x230
> [ 0.386840] mipid_spi_probe from spi_probe+0x48/0x6c
> [ 0.387054] spi_probe from really_probe+0xac/0x2f0
> [ 0.387237] really_probe from __driver_probe_device+0x80/0xe4
> [ 0.387390] __driver_probe_device from driver_probe_device+0x30/0xd8
> [ 0.387573] driver_probe_device from __driver_attach+0x70/0xf0
> [ 0.387756] __driver_attach from bus_for_each_dev+0x74/0xc0
> [ 0.387908] bus_for_each_dev from bus_add_driver+0x14c/0x1d8
> [ 0.388061] bus_add_driver from driver_register+0x74/0x108
> [ 0.388244] driver_register from do_one_initcall+0x4c/0x1cc
> [ 0.388427] do_one_initcall from kernel_init_freeable+0x170/0x1f4
> [ 0.388641] kernel_init_freeable from kernel_init+0x10/0x108
> [ 0.388824] kernel_init from ret_from_fork+0x14/0x2c
> [ 0.388977] Exception stack(0xc0c41fb0 to 0xc0c41ff8)
> [ 0.389099] 1fa0: 00000000 00000000 00000000 00000000
> [ 0.389282] 1fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> [ 0.389434] 1fe0: 00000000 00000000 00000000 00000000 00000013 00000000
> [ 0.389556] ---[ end trace 0000000000000000 ]---
> [ 0.389709] omapfb omapfb: invalid SoSSI sync pattern: 00000000, 00000000
> [ 0.389831] ------------[ cut here ]------------
> [ 0.389923] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:953 clk_core_disable+0xb4/0xcc
> [ 0.390136] ck_sossi already disabled
> [ 0.390228] Modules linked in:
> [ 0.390319] CPU: 0 PID: 1 Comm: swapper Tainted: G W 5.17.0-rc8-770-los_381206+-00072-gb2406fc1ddd4 #2
> [ 0.390502] Hardware name: Nokia 770
> [ 0.390594] unwind_backtrace from show_stack+0x10/0x14
> [ 0.390808] show_stack from __warn+0xac/0xe4
> [ 0.391021] __warn from warn_slowpath_fmt+0x90/0xc8
> [ 0.391204] warn_slowpath_fmt from clk_core_disable+0xb4/0xcc
> [ 0.391387] clk_core_disable from clk_core_disable_lock+0x18/0x24
> [ 0.391540] clk_core_disable_lock from sossi_init+0x1bc/0x258
> [ 0.391754] sossi_init from hwa742_init+0x90/0x538
> [ 0.391937] hwa742_init from omapfb_do_probe+0x200/0x68c
> [ 0.392120] omapfb_do_probe from mipid_spi_probe+0x1b4/0x230
> [ 0.392333] mipid_spi_probe from spi_probe+0x48/0x6c
> [ 0.392547] spi_probe from really_probe+0xac/0x2f0
> [ 0.392730] really_probe from __driver_probe_device+0x80/0xe4
> [ 0.392883] __driver_probe_device from driver_probe_device+0x30/0xd8
> [ 0.393066] driver_probe_device from __driver_attach+0x70/0xf0
> [ 0.393249] __driver_attach from bus_for_each_dev+0x74/0xc0
> [ 0.393402] bus_for_each_dev from bus_add_driver+0x14c/0x1d8
> [ 0.393585] bus_add_driver from driver_register+0x74/0x108
> [ 0.393737] driver_register from do_one_initcall+0x4c/0x1cc
> [ 0.393920] do_one_initcall from kernel_init_freeable+0x170/0x1f4
> [ 0.394134] kernel_init_freeable from kernel_init+0x10/0x108
> [ 0.394317] kernel_init from ret_from_fork+0x14/0x2c
> [ 0.394470] Exception stack(0xc0c41fb0 to 0xc0c41ff8)
> [ 0.394592] 1fa0: 00000000 00000000 00000000 00000000
> [ 0.394775] 1fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> [ 0.394958] 1fe0: 00000000 00000000 00000000 00000000 00000013 00000000
> [ 0.395080] ---[ end trace 0000000000000000 ]---
> [ 0.417907] omapfb omapfb: controller initialization failed (-19)
>
> A.
>




2022-03-21 12:32:21

by Aaro Koskinen

[permalink] [raw]
Subject: Re: [RFC RFT PATCH 0/4] ARM: OMAP1: clock: Convert to CCF

Hi,

On Sat, Mar 12, 2022 at 10:14:31AM +0200, Tony Lindgren wrote:
> * Janusz Krzysztofik <[email protected]> [220310 23:32]:
> > The main motivation behind this series is planned resurection of OMAP1
> > camera driver. Since OMAP1 clock internals have never been visible to
> > drivers, that driver used to use v4l2-clk to expose a pixel clock for a
> > sensor. The v4l2-clk code has been recently depreciated and removed from
> > the media subtree, hence the need for an alternative solution.
>
> Nice :) This will also help Arnd with building multi-v5 kernels.

This will need more testing still... The patch 4 is breaking at least 770
(the display/fb doesn't work anymore).

A.

2022-03-21 21:17:05

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [RFC RFT PATCH 0/4] ARM: OMAP1: clock: Convert to CCF

On Sat, Mar 12, 2022 at 9:14 AM Tony Lindgren <[email protected]> wrote:
>
> * Janusz Krzysztofik <[email protected]> [220310 23:32]:
> > The main motivation behind this series is planned resurection of OMAP1
> > camera driver. Since OMAP1 clock internals have never been visible to
> > drivers, that driver used to use v4l2-clk to expose a pixel clock for a
> > sensor. The v4l2-clk code has been recently depreciated and removed from
> > the media subtree, hence the need for an alternative solution.
>
> Nice :) This will also help Arnd with building multi-v5 kernels.

Thanks for looping me in, I missed the thread originally but now
got the replies.

As OMAP1 is the last user of HAVE_LEGACY_CLK on Arm, converting
it would be particularly nice, and it allows me to dig out my omap1
multiplatform patches, which does get us closer to endgame.

The only other ARM9 platforms that are not multiplatform yet are
ep93xx (which can probably be done now as well after its
clk conversion) and s3c24xx (which is scheduled for removal next
year).

When those are out of the way, we only have StrongARM (rpc,
sa1100, footbridge) and XScale (pxa, ixp, iop) remaining.

Arnd

2022-03-21 23:34:12

by Janusz Krzysztofik

[permalink] [raw]
Subject: [PATCH v2] ARM: OMAP1: Prepare for conversion of OMAP1 clocks to CCF

In preparation for conversion of OMAP1 clocks to common clock framework,
identify users of those clocks which don't call clk_prepare/unprepare()
and update them to call clk_prepare_enable/clk_disable_unprepare() instead
of just clk_enable/disable(), as required by CCF implementation of clock
API.

v2: update still a few more OMAP specific drivers missed in v1,
- call clk_prepare/unprepare() just after/before clk_get/put() where it
can make more sense than merging prepare/unprepare with enable/disable.

Signed-off-by: Janusz Krzysztofik <[email protected]>
---
arch/arm/mach-omap1/mcbsp.c | 8 ++++----
arch/arm/mach-omap1/ocpi.c | 4 ++--
arch/arm/mach-omap1/serial.c | 6 +++---
arch/arm/mach-omap1/timer32k.c | 2 +-
drivers/mmc/host/omap.c | 23 ++++++++++++++---------
drivers/usb/gadget/udc/omap_udc.c | 14 ++++++++------
drivers/usb/host/ohci-omap.c | 18 ++++++++++++++++--
drivers/video/fbdev/omap/hwa742.c | 6 +++---
drivers/video/fbdev/omap/lcdc.c | 6 +++---
drivers/video/fbdev/omap/sossi.c | 5 +++--
sound/soc/ti/osk5912.c | 9 ++++++++-
11 files changed, 65 insertions(+), 36 deletions(-)

diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c
index f36c34f47f11..3ec2badff6af 100644
--- a/arch/arm/mach-omap1/mcbsp.c
+++ b/arch/arm/mach-omap1/mcbsp.c
@@ -44,8 +44,8 @@ static void omap1_mcbsp_request(unsigned int id)
api_clk = clk_get(NULL, "api_ck");
dsp_clk = clk_get(NULL, "dsp_ck");
if (!IS_ERR(api_clk) && !IS_ERR(dsp_clk)) {
- clk_enable(api_clk);
- clk_enable(dsp_clk);
+ clk_prepare_enable(api_clk);
+ clk_prepare_enable(dsp_clk);

/*
* DSP external peripheral reset
@@ -63,11 +63,11 @@ static void omap1_mcbsp_free(unsigned int id)
if (id == 0 || id == 2) {
if (--dsp_use == 0) {
if (!IS_ERR(api_clk)) {
- clk_disable(api_clk);
+ clk_disable_unprepare(api_clk);
clk_put(api_clk);
}
if (!IS_ERR(dsp_clk)) {
- clk_disable(dsp_clk);
+ clk_disable_unprepare(dsp_clk);
clk_put(dsp_clk);
}
}
diff --git a/arch/arm/mach-omap1/ocpi.c b/arch/arm/mach-omap1/ocpi.c
index 380ea2de58c1..03cc48024fd6 100644
--- a/arch/arm/mach-omap1/ocpi.c
+++ b/arch/arm/mach-omap1/ocpi.c
@@ -73,7 +73,7 @@ static int __init omap_ocpi_init(void)
if (IS_ERR(ocpi_ck))
return PTR_ERR(ocpi_ck);

- clk_enable(ocpi_ck);
+ clk_prepare_enable(ocpi_ck);
ocpi_enable();
pr_info("OMAP OCPI interconnect driver loaded\n");

@@ -87,7 +87,7 @@ static void __exit omap_ocpi_exit(void)
if (!cpu_is_omap16xx())
return;

- clk_disable(ocpi_ck);
+ clk_disable_unprepare(ocpi_ck);
clk_put(ocpi_ck);
}

diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c
index 9eb591fbfd89..5f591a836ab5 100644
--- a/arch/arm/mach-omap1/serial.c
+++ b/arch/arm/mach-omap1/serial.c
@@ -141,7 +141,7 @@ void __init omap_serial_init(void)
if (IS_ERR(uart1_ck))
printk("Could not get uart1_ck\n");
else {
- clk_enable(uart1_ck);
+ clk_prepare_enable(uart1_ck);
if (cpu_is_omap15xx())
clk_set_rate(uart1_ck, 12000000);
}
@@ -151,7 +151,7 @@ void __init omap_serial_init(void)
if (IS_ERR(uart2_ck))
printk("Could not get uart2_ck\n");
else {
- clk_enable(uart2_ck);
+ clk_prepare_enable(uart2_ck);
if (cpu_is_omap15xx())
clk_set_rate(uart2_ck, 12000000);
else
@@ -163,7 +163,7 @@ void __init omap_serial_init(void)
if (IS_ERR(uart3_ck))
printk("Could not get uart3_ck\n");
else {
- clk_enable(uart3_ck);
+ clk_prepare_enable(uart3_ck);
if (cpu_is_omap15xx())
clk_set_rate(uart3_ck, 12000000);
}
diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c
index 780fdf03c3ce..049c7b7f28c4 100644
--- a/arch/arm/mach-omap1/timer32k.c
+++ b/arch/arm/mach-omap1/timer32k.c
@@ -180,7 +180,7 @@ int __init omap_32k_timer_init(void)

sync32k_ick = clk_get(NULL, "omap_32ksync_ick");
if (!IS_ERR(sync32k_ick))
- clk_enable(sync32k_ick);
+ clk_prepare_enable(sync32k_ick);

ret = omap_init_clocksource_32k(base);
}
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 5e5af34090f1..57d39283924d 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -1374,7 +1374,7 @@ static int mmc_omap_probe(struct platform_device *pdev)
host->iclk = clk_get(&pdev->dev, "ick");
if (IS_ERR(host->iclk))
return PTR_ERR(host->iclk);
- clk_enable(host->iclk);
+ clk_prepare_enable(host->iclk);

host->fclk = clk_get(&pdev->dev, "fck");
if (IS_ERR(host->fclk)) {
@@ -1382,16 +1382,18 @@ static int mmc_omap_probe(struct platform_device *pdev)
goto err_free_iclk;
}

+ ret = clk_prepare(host->fclk);
+ if (ret)
+ goto err_put_fclk;
+
host->dma_tx_burst = -1;
host->dma_rx_burst = -1;

host->dma_tx = dma_request_chan(&pdev->dev, "tx");
if (IS_ERR(host->dma_tx)) {
ret = PTR_ERR(host->dma_tx);
- if (ret == -EPROBE_DEFER) {
- clk_put(host->fclk);
- goto err_free_iclk;
- }
+ if (ret == -EPROBE_DEFER)
+ goto err_free_fclk;

host->dma_tx = NULL;
dev_warn(host->dev, "TX DMA channel request failed\n");
@@ -1403,8 +1405,7 @@ static int mmc_omap_probe(struct platform_device *pdev)
if (ret == -EPROBE_DEFER) {
if (host->dma_tx)
dma_release_channel(host->dma_tx);
- clk_put(host->fclk);
- goto err_free_iclk;
+ goto err_free_fclk;
}

host->dma_rx = NULL;
@@ -1454,9 +1455,12 @@ static int mmc_omap_probe(struct platform_device *pdev)
dma_release_channel(host->dma_tx);
if (host->dma_rx)
dma_release_channel(host->dma_rx);
+err_free_fclk:
+ clk_unprepare(host->fclk);
+err_put_fclk:
clk_put(host->fclk);
err_free_iclk:
- clk_disable(host->iclk);
+ clk_disable_unprepare(host->iclk);
clk_put(host->iclk);
return ret;
}
@@ -1476,8 +1480,9 @@ static int mmc_omap_remove(struct platform_device *pdev)

mmc_omap_fclk_enable(host, 0);
free_irq(host->irq, host);
+ clk_unprepare(host->fclk);
clk_put(host->fclk);
- clk_disable(host->iclk);
+ clk_disable_unprepare(host->iclk);
clk_put(host->iclk);

if (host->dma_tx)
diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c
index 494da00398d7..8768a3280e19 100644
--- a/drivers/usb/gadget/udc/omap_udc.c
+++ b/drivers/usb/gadget/udc/omap_udc.c
@@ -2604,6 +2604,8 @@ static void omap_udc_release(struct device *dev)
if (udc->dc_clk) {
if (udc->clk_requested)
omap_udc_enable_clock(0);
+ clk_unprepare(udc->hhc_clk);
+ clk_unprepare(udc->dc_clk);
clk_put(udc->hhc_clk);
clk_put(udc->dc_clk);
}
@@ -2768,8 +2770,8 @@ static int omap_udc_probe(struct platform_device *pdev)
hhc_clk = clk_get(&pdev->dev, "usb_hhc_ck");
BUG_ON(IS_ERR(dc_clk) || IS_ERR(hhc_clk));
/* can't use omap_udc_enable_clock yet */
- clk_enable(dc_clk);
- clk_enable(hhc_clk);
+ clk_prepare_enable(dc_clk);
+ clk_prepare_enable(hhc_clk);
udelay(100);
}

@@ -2778,8 +2780,8 @@ static int omap_udc_probe(struct platform_device *pdev)
hhc_clk = clk_get(&pdev->dev, "l3_ocpi_ck");
BUG_ON(IS_ERR(dc_clk) || IS_ERR(hhc_clk));
/* can't use omap_udc_enable_clock yet */
- clk_enable(dc_clk);
- clk_enable(hhc_clk);
+ clk_prepare_enable(dc_clk);
+ clk_prepare_enable(hhc_clk);
udelay(100);
}

@@ -2927,8 +2929,8 @@ static int omap_udc_probe(struct platform_device *pdev)
usb_put_phy(xceiv);

if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
- clk_disable(hhc_clk);
- clk_disable(dc_clk);
+ clk_disable_unprepare(hhc_clk);
+ clk_disable_unprepare(dc_clk);
clk_put(hhc_clk);
clk_put(dc_clk);
}
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 45dcf8292072..2ab2e089a2b7 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -281,6 +281,10 @@ static int ohci_hcd_omap_probe(struct platform_device *pdev)
goto err_put_hcd;
}

+ retval = clk_prepare(priv->usb_host_ck);
+ if (retval)
+ goto err_put_host_ck;
+
if (!cpu_is_omap15xx())
priv->usb_dc_ck = clk_get(&pdev->dev, "usb_dc_ck");
else
@@ -288,13 +292,17 @@ static int ohci_hcd_omap_probe(struct platform_device *pdev)

if (IS_ERR(priv->usb_dc_ck)) {
retval = PTR_ERR(priv->usb_dc_ck);
- goto err_put_host_ck;
+ goto err_unprepare_host_ck;
}

+ retval = clk_prepare(priv->usb_dc_ck);
+ if (retval)
+ goto err_put_dc_ck;
+
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
dev_dbg(&pdev->dev, "request_mem_region failed\n");
retval = -EBUSY;
- goto err_put_dc_ck;
+ goto err_unprepare_dc_ck;
}

hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
@@ -319,8 +327,12 @@ static int ohci_hcd_omap_probe(struct platform_device *pdev)
iounmap(hcd->regs);
err2:
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err_unprepare_dc_ck:
+ clk_unprepare(priv->usb_dc_ck);
err_put_dc_ck:
clk_put(priv->usb_dc_ck);
+err_unprepare_host_ck:
+ clk_unprepare(priv->usb_host_ck);
err_put_host_ck:
clk_put(priv->usb_host_ck);
err_put_hcd:
@@ -355,7 +367,9 @@ static int ohci_hcd_omap_remove(struct platform_device *pdev)
}
iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ clk_unprepare(priv->usb_dc_ck);
clk_put(priv->usb_dc_ck);
+ clk_unprepare(priv->usb_host_ck);
clk_put(priv->usb_host_ck);
usb_put_hcd(hcd);
return 0;
diff --git a/drivers/video/fbdev/omap/hwa742.c b/drivers/video/fbdev/omap/hwa742.c
index b191bef22d98..9d9fe5c3a7a1 100644
--- a/drivers/video/fbdev/omap/hwa742.c
+++ b/drivers/video/fbdev/omap/hwa742.c
@@ -964,7 +964,7 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode,
if ((r = calc_extif_timings(ext_clk, &extif_mem_div)) < 0)
goto err3;
hwa742.extif->set_timings(&hwa742.reg_timings);
- clk_enable(hwa742.sys_ck);
+ clk_prepare_enable(hwa742.sys_ck);

calc_hwa742_clk_rates(ext_clk, &sys_clk, &pix_clk);
if ((r = calc_extif_timings(sys_clk, &extif_mem_div)) < 0)
@@ -1023,7 +1023,7 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode,

return 0;
err4:
- clk_disable(hwa742.sys_ck);
+ clk_disable_unprepare(hwa742.sys_ck);
err3:
hwa742.extif->cleanup();
err2:
@@ -1037,7 +1037,7 @@ static void hwa742_cleanup(void)
hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED);
hwa742.extif->cleanup();
hwa742.int_ctrl->cleanup();
- clk_disable(hwa742.sys_ck);
+ clk_disable_unprepare(hwa742.sys_ck);
}

struct lcd_ctrl hwa742_ctrl = {
diff --git a/drivers/video/fbdev/omap/lcdc.c b/drivers/video/fbdev/omap/lcdc.c
index 7317c9aad677..97d20dc0d1d0 100644
--- a/drivers/video/fbdev/omap/lcdc.c
+++ b/drivers/video/fbdev/omap/lcdc.c
@@ -711,7 +711,7 @@ static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode,
dev_err(fbdev->dev, "failed to adjust LCD rate\n");
goto fail1;
}
- clk_enable(lcdc.lcd_ck);
+ clk_prepare_enable(lcdc.lcd_ck);

r = request_irq(OMAP_LCDC_IRQ, lcdc_irq_handler, 0, MODULE_NAME, fbdev);
if (r) {
@@ -746,7 +746,7 @@ static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode,
fail3:
free_irq(OMAP_LCDC_IRQ, lcdc.fbdev);
fail2:
- clk_disable(lcdc.lcd_ck);
+ clk_disable_unprepare(lcdc.lcd_ck);
fail1:
clk_put(lcdc.lcd_ck);
fail0:
@@ -760,7 +760,7 @@ static void omap_lcdc_cleanup(void)
free_fbmem();
omap_free_lcd_dma();
free_irq(OMAP_LCDC_IRQ, lcdc.fbdev);
- clk_disable(lcdc.lcd_ck);
+ clk_disable_unprepare(lcdc.lcd_ck);
clk_put(lcdc.lcd_ck);
}

diff --git a/drivers/video/fbdev/omap/sossi.c b/drivers/video/fbdev/omap/sossi.c
index 80ac67f27f0d..b9cb8b386627 100644
--- a/drivers/video/fbdev/omap/sossi.c
+++ b/drivers/video/fbdev/omap/sossi.c
@@ -598,7 +598,7 @@ static int sossi_init(struct omapfb_device *fbdev)
l &= ~CONF_SOSSI_RESET_R;
omap_writel(l, MOD_CONF_CTRL_1);

- clk_enable(sossi.fck);
+ clk_prepare_enable(sossi.fck);
l = omap_readl(ARM_IDLECT2);
l &= ~(1 << 8); /* DMACK_REQ */
omap_writel(l, ARM_IDLECT2);
@@ -649,7 +649,7 @@ static int sossi_init(struct omapfb_device *fbdev)
return 0;

err:
- clk_disable(sossi.fck);
+ clk_disable_unprepare(sossi.fck);
clk_put(sossi.fck);
return r;
}
@@ -657,6 +657,7 @@ static int sossi_init(struct omapfb_device *fbdev)
static void sossi_cleanup(void)
{
omap_lcdc_free_dma_callback();
+ clk_unprepare(sossi.fck);
clk_put(sossi.fck);
iounmap(sossi.base);
}
diff --git a/sound/soc/ti/osk5912.c b/sound/soc/ti/osk5912.c
index 40e29dda7e7a..22da3b335e81 100644
--- a/sound/soc/ti/osk5912.c
+++ b/sound/soc/ti/osk5912.c
@@ -134,6 +134,10 @@ static int __init osk_soc_init(void)
goto err2;
}

+ err = clk_prepare(tlv320aic23_mclk);
+ if (err)
+ goto err3;
+
/*
* Configure 12 MHz output on MCLK.
*/
@@ -142,7 +146,7 @@ static int __init osk_soc_init(void)
if (clk_set_rate(tlv320aic23_mclk, CODEC_CLOCK)) {
printk(KERN_ERR "Cannot set MCLK for AIC23 CODEC\n");
err = -ECANCELED;
- goto err3;
+ goto err4;
}
}

@@ -151,6 +155,8 @@ static int __init osk_soc_init(void)

return 0;

+err4:
+ clk_unprepare(tlv320aic23_mclk);
err3:
clk_put(tlv320aic23_mclk);
err2:
@@ -164,6 +170,7 @@ static int __init osk_soc_init(void)

static void __exit osk_soc_exit(void)
{
+ clk_unprepare(tlv320aic23_mclk);
clk_put(tlv320aic23_mclk);
platform_device_unregister(osk_snd_device);
}
--
2.35.1

2022-03-22 20:27:31

by Aaro Koskinen

[permalink] [raw]
Subject: Re: [PATCH v2] ARM: OMAP1: Prepare for conversion of OMAP1 clocks to CCF

Hi,

On Mon, Mar 21, 2022 at 10:54:16PM +0100, Janusz Krzysztofik wrote:
> In preparation for conversion of OMAP1 clocks to common clock framework,
> identify users of those clocks which don't call clk_prepare/unprepare()
> and update them to call clk_prepare_enable/clk_disable_unprepare() instead
> of just clk_enable/disable(), as required by CCF implementation of clock
> API.
>
> v2: update still a few more OMAP specific drivers missed in v1,
> - call clk_prepare/unprepare() just after/before clk_get/put() where it
> can make more sense than merging prepare/unprepare with enable/disable.

Something is still broken. When doing kexec (using CCF kernel), the
kexec'ed kernel now hangs early (on 770):

[ 0.853912] MUX: initialized W4_USB_PUEN
[ 0.858001] MUX: initialized V6_USB0_TXD
[ 0.862060] MUX: initialized W5_USB0_SE0
[ 0.866210] MUX: initialized Y5_USB0_RCV
[ 0.870269] MUX: initialized AA9_USB0_VP
[ 0.874389] MUX: initialized R9_USB0_VM
[ 0.878356] USB: hmc 16, usb0 6 wires (dev), Mini-AB on usb0
[ 0.886230] initcall customize_machine+0x0/0x30 returned 0 after 29296 usecs
[ 0.893707] calling init_atags_procfs+0x0/0xe8 @ 1
[ 0.898864] initcall init_atags_procfs+0x0/0xe8 returned 0 after 0 usecs
[ 0.905883] calling exceptions_init+0x0/0x8c @ 1
[ 0.910797] initcall exceptions_init+0x0/0x8c returned 0 after 0 usecs
[ 0.917602] calling omap_init+0x0/0xc @ 1
[ 0.922393] initcall omap_init+0x0/0xc returned 0 after 9765 usecs
[ 0.928863] calling omap1_init_devices+0x0/0x2c @ 1
[ 2.568664] random: fast init done

Probably something is now disabled that has been previously always
enabled by default/bootloader. I'll try adding some printk()s to see
the exact place where it hangs...

A.

2022-03-22 22:18:49

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH v2] ARM: OMAP1: Prepare for conversion of OMAP1 clocks to CCF

On Mon, Mar 21, 2022 at 10:54:16PM +0100, Janusz Krzysztofik wrote:
> In preparation for conversion of OMAP1 clocks to common clock framework,
> identify users of those clocks which don't call clk_prepare/unprepare()
> and update them to call clk_prepare_enable/clk_disable_unprepare() instead
> of just clk_enable/disable(), as required by CCF implementation of clock
> API.

Acked-by: Mark Brown <[email protected]>


Attachments:
(No filename) (427.00 B)
signature.asc (499.00 B)
Download all attachments

2022-03-23 14:11:16

by Aaro Koskinen

[permalink] [raw]
Subject: Re: [PATCH v2] ARM: OMAP1: Prepare for conversion of OMAP1 clocks to CCF

Hi,

On Tue, Mar 22, 2022 at 06:36:48PM +0200, Aaro Koskinen wrote:
> On Mon, Mar 21, 2022 at 10:54:16PM +0100, Janusz Krzysztofik wrote:
> > In preparation for conversion of OMAP1 clocks to common clock framework,
> > identify users of those clocks which don't call clk_prepare/unprepare()
> > and update them to call clk_prepare_enable/clk_disable_unprepare() instead
> > of just clk_enable/disable(), as required by CCF implementation of clock
> > API.
> >
> > v2: update still a few more OMAP specific drivers missed in v1,
> > - call clk_prepare/unprepare() just after/before clk_get/put() where it
> > can make more sense than merging prepare/unprepare with enable/disable.
>
> Something is still broken. When doing kexec (using CCF kernel), the
> kexec'ed kernel now hangs early (on 770):
[...]
> [ 0.928863] calling omap1_init_devices+0x0/0x2c @ 1

It hangs in omap_sram_reprogram_clock() (<- omap1_select_table_rate()
<- omap1_clk_late_init()).

A.

2022-03-27 15:25:26

by Janusz Krzysztofik

[permalink] [raw]
Subject: Re: [PATCH v2] ARM: OMAP1: Prepare for conversion of OMAP1 clocks to CCF

Hi Aaro,

Dnia wtorek, 22 marca 2022 20:07:53 CET Aaro Koskinen pisze:
> Hi,
>
> On Tue, Mar 22, 2022 at 06:36:48PM +0200, Aaro Koskinen wrote:
> > On Mon, Mar 21, 2022 at 10:54:16PM +0100, Janusz Krzysztofik wrote:
> > > In preparation for conversion of OMAP1 clocks to common clock framework,
> > > identify users of those clocks which don't call clk_prepare/unprepare()
> > > and update them to call clk_prepare_enable/clk_disable_unprepare() instead
> > > of just clk_enable/disable(), as required by CCF implementation of clock
> > > API.
> > >
> > > v2: update still a few more OMAP specific drivers missed in v1,
> > > - call clk_prepare/unprepare() just after/before clk_get/put() where it
> > > can make more sense than merging prepare/unprepare with enable/disable.
> >
> > Something is still broken. When doing kexec (using CCF kernel), the
> > kexec'ed kernel now hangs early (on 770):
> [...]
> > [ 0.928863] calling omap1_init_devices+0x0/0x2c @ 1
>
> It hangs in omap_sram_reprogram_clock() (<- omap1_select_table_rate()
> <- omap1_clk_late_init()).

I've reviewed my changes but haven't found anything suspicious. Could you
please provide:
- dmesg from both cold start and kexec, both non-CCF and CCF version,
- contents of /sys/kernel/debug/clock/summary (non-CCF) after boot/kexec,
- contents of /sys/kernel/debug/clk/clk_summary (CCF) after boot?

Thanks,
Janusz

>
> A.
>




2022-03-31 11:59:25

by Ulf Hansson

[permalink] [raw]
Subject: Re: [PATCH v2] ARM: OMAP1: Prepare for conversion of OMAP1 clocks to CCF

On Mon, 21 Mar 2022 at 22:54, Janusz Krzysztofik <[email protected]> wrote:
>
> In preparation for conversion of OMAP1 clocks to common clock framework,
> identify users of those clocks which don't call clk_prepare/unprepare()
> and update them to call clk_prepare_enable/clk_disable_unprepare() instead
> of just clk_enable/disable(), as required by CCF implementation of clock
> API.
>
> v2: update still a few more OMAP specific drivers missed in v1,
> - call clk_prepare/unprepare() just after/before clk_get/put() where it
> can make more sense than merging prepare/unprepare with enable/disable.
>
> Signed-off-by: Janusz Krzysztofik <[email protected]>

Is there a specific reason why you can't split this into a per subsystem patch?

Don't get me wrong, if you need my ack you have it, but I just wanted
to know why this is?

Kind regards
Uffe

> ---
> arch/arm/mach-omap1/mcbsp.c | 8 ++++----
> arch/arm/mach-omap1/ocpi.c | 4 ++--
> arch/arm/mach-omap1/serial.c | 6 +++---
> arch/arm/mach-omap1/timer32k.c | 2 +-
> drivers/mmc/host/omap.c | 23 ++++++++++++++---------
> drivers/usb/gadget/udc/omap_udc.c | 14 ++++++++------
> drivers/usb/host/ohci-omap.c | 18 ++++++++++++++++--
> drivers/video/fbdev/omap/hwa742.c | 6 +++---
> drivers/video/fbdev/omap/lcdc.c | 6 +++---
> drivers/video/fbdev/omap/sossi.c | 5 +++--
> sound/soc/ti/osk5912.c | 9 ++++++++-
> 11 files changed, 65 insertions(+), 36 deletions(-)
>
> diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c
> index f36c34f47f11..3ec2badff6af 100644
> --- a/arch/arm/mach-omap1/mcbsp.c
> +++ b/arch/arm/mach-omap1/mcbsp.c
> @@ -44,8 +44,8 @@ static void omap1_mcbsp_request(unsigned int id)
> api_clk = clk_get(NULL, "api_ck");
> dsp_clk = clk_get(NULL, "dsp_ck");
> if (!IS_ERR(api_clk) && !IS_ERR(dsp_clk)) {
> - clk_enable(api_clk);
> - clk_enable(dsp_clk);
> + clk_prepare_enable(api_clk);
> + clk_prepare_enable(dsp_clk);
>
> /*
> * DSP external peripheral reset
> @@ -63,11 +63,11 @@ static void omap1_mcbsp_free(unsigned int id)
> if (id == 0 || id == 2) {
> if (--dsp_use == 0) {
> if (!IS_ERR(api_clk)) {
> - clk_disable(api_clk);
> + clk_disable_unprepare(api_clk);
> clk_put(api_clk);
> }
> if (!IS_ERR(dsp_clk)) {
> - clk_disable(dsp_clk);
> + clk_disable_unprepare(dsp_clk);
> clk_put(dsp_clk);
> }
> }
> diff --git a/arch/arm/mach-omap1/ocpi.c b/arch/arm/mach-omap1/ocpi.c
> index 380ea2de58c1..03cc48024fd6 100644
> --- a/arch/arm/mach-omap1/ocpi.c
> +++ b/arch/arm/mach-omap1/ocpi.c
> @@ -73,7 +73,7 @@ static int __init omap_ocpi_init(void)
> if (IS_ERR(ocpi_ck))
> return PTR_ERR(ocpi_ck);
>
> - clk_enable(ocpi_ck);
> + clk_prepare_enable(ocpi_ck);
> ocpi_enable();
> pr_info("OMAP OCPI interconnect driver loaded\n");
>
> @@ -87,7 +87,7 @@ static void __exit omap_ocpi_exit(void)
> if (!cpu_is_omap16xx())
> return;
>
> - clk_disable(ocpi_ck);
> + clk_disable_unprepare(ocpi_ck);
> clk_put(ocpi_ck);
> }
>
> diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c
> index 9eb591fbfd89..5f591a836ab5 100644
> --- a/arch/arm/mach-omap1/serial.c
> +++ b/arch/arm/mach-omap1/serial.c
> @@ -141,7 +141,7 @@ void __init omap_serial_init(void)
> if (IS_ERR(uart1_ck))
> printk("Could not get uart1_ck\n");
> else {
> - clk_enable(uart1_ck);
> + clk_prepare_enable(uart1_ck);
> if (cpu_is_omap15xx())
> clk_set_rate(uart1_ck, 12000000);
> }
> @@ -151,7 +151,7 @@ void __init omap_serial_init(void)
> if (IS_ERR(uart2_ck))
> printk("Could not get uart2_ck\n");
> else {
> - clk_enable(uart2_ck);
> + clk_prepare_enable(uart2_ck);
> if (cpu_is_omap15xx())
> clk_set_rate(uart2_ck, 12000000);
> else
> @@ -163,7 +163,7 @@ void __init omap_serial_init(void)
> if (IS_ERR(uart3_ck))
> printk("Could not get uart3_ck\n");
> else {
> - clk_enable(uart3_ck);
> + clk_prepare_enable(uart3_ck);
> if (cpu_is_omap15xx())
> clk_set_rate(uart3_ck, 12000000);
> }
> diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c
> index 780fdf03c3ce..049c7b7f28c4 100644
> --- a/arch/arm/mach-omap1/timer32k.c
> +++ b/arch/arm/mach-omap1/timer32k.c
> @@ -180,7 +180,7 @@ int __init omap_32k_timer_init(void)
>
> sync32k_ick = clk_get(NULL, "omap_32ksync_ick");
> if (!IS_ERR(sync32k_ick))
> - clk_enable(sync32k_ick);
> + clk_prepare_enable(sync32k_ick);
>
> ret = omap_init_clocksource_32k(base);
> }
> diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
> index 5e5af34090f1..57d39283924d 100644
> --- a/drivers/mmc/host/omap.c
> +++ b/drivers/mmc/host/omap.c
> @@ -1374,7 +1374,7 @@ static int mmc_omap_probe(struct platform_device *pdev)
> host->iclk = clk_get(&pdev->dev, "ick");
> if (IS_ERR(host->iclk))
> return PTR_ERR(host->iclk);
> - clk_enable(host->iclk);
> + clk_prepare_enable(host->iclk);
>
> host->fclk = clk_get(&pdev->dev, "fck");
> if (IS_ERR(host->fclk)) {
> @@ -1382,16 +1382,18 @@ static int mmc_omap_probe(struct platform_device *pdev)
> goto err_free_iclk;
> }
>
> + ret = clk_prepare(host->fclk);
> + if (ret)
> + goto err_put_fclk;
> +
> host->dma_tx_burst = -1;
> host->dma_rx_burst = -1;
>
> host->dma_tx = dma_request_chan(&pdev->dev, "tx");
> if (IS_ERR(host->dma_tx)) {
> ret = PTR_ERR(host->dma_tx);
> - if (ret == -EPROBE_DEFER) {
> - clk_put(host->fclk);
> - goto err_free_iclk;
> - }
> + if (ret == -EPROBE_DEFER)
> + goto err_free_fclk;
>
> host->dma_tx = NULL;
> dev_warn(host->dev, "TX DMA channel request failed\n");
> @@ -1403,8 +1405,7 @@ static int mmc_omap_probe(struct platform_device *pdev)
> if (ret == -EPROBE_DEFER) {
> if (host->dma_tx)
> dma_release_channel(host->dma_tx);
> - clk_put(host->fclk);
> - goto err_free_iclk;
> + goto err_free_fclk;
> }
>
> host->dma_rx = NULL;
> @@ -1454,9 +1455,12 @@ static int mmc_omap_probe(struct platform_device *pdev)
> dma_release_channel(host->dma_tx);
> if (host->dma_rx)
> dma_release_channel(host->dma_rx);
> +err_free_fclk:
> + clk_unprepare(host->fclk);
> +err_put_fclk:
> clk_put(host->fclk);
> err_free_iclk:
> - clk_disable(host->iclk);
> + clk_disable_unprepare(host->iclk);
> clk_put(host->iclk);
> return ret;
> }
> @@ -1476,8 +1480,9 @@ static int mmc_omap_remove(struct platform_device *pdev)
>
> mmc_omap_fclk_enable(host, 0);
> free_irq(host->irq, host);
> + clk_unprepare(host->fclk);
> clk_put(host->fclk);
> - clk_disable(host->iclk);
> + clk_disable_unprepare(host->iclk);
> clk_put(host->iclk);
>
> if (host->dma_tx)
> diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c
> index 494da00398d7..8768a3280e19 100644
> --- a/drivers/usb/gadget/udc/omap_udc.c
> +++ b/drivers/usb/gadget/udc/omap_udc.c
> @@ -2604,6 +2604,8 @@ static void omap_udc_release(struct device *dev)
> if (udc->dc_clk) {
> if (udc->clk_requested)
> omap_udc_enable_clock(0);
> + clk_unprepare(udc->hhc_clk);
> + clk_unprepare(udc->dc_clk);
> clk_put(udc->hhc_clk);
> clk_put(udc->dc_clk);
> }
> @@ -2768,8 +2770,8 @@ static int omap_udc_probe(struct platform_device *pdev)
> hhc_clk = clk_get(&pdev->dev, "usb_hhc_ck");
> BUG_ON(IS_ERR(dc_clk) || IS_ERR(hhc_clk));
> /* can't use omap_udc_enable_clock yet */
> - clk_enable(dc_clk);
> - clk_enable(hhc_clk);
> + clk_prepare_enable(dc_clk);
> + clk_prepare_enable(hhc_clk);
> udelay(100);
> }
>
> @@ -2778,8 +2780,8 @@ static int omap_udc_probe(struct platform_device *pdev)
> hhc_clk = clk_get(&pdev->dev, "l3_ocpi_ck");
> BUG_ON(IS_ERR(dc_clk) || IS_ERR(hhc_clk));
> /* can't use omap_udc_enable_clock yet */
> - clk_enable(dc_clk);
> - clk_enable(hhc_clk);
> + clk_prepare_enable(dc_clk);
> + clk_prepare_enable(hhc_clk);
> udelay(100);
> }
>
> @@ -2927,8 +2929,8 @@ static int omap_udc_probe(struct platform_device *pdev)
> usb_put_phy(xceiv);
>
> if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
> - clk_disable(hhc_clk);
> - clk_disable(dc_clk);
> + clk_disable_unprepare(hhc_clk);
> + clk_disable_unprepare(dc_clk);
> clk_put(hhc_clk);
> clk_put(dc_clk);
> }
> diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
> index 45dcf8292072..2ab2e089a2b7 100644
> --- a/drivers/usb/host/ohci-omap.c
> +++ b/drivers/usb/host/ohci-omap.c
> @@ -281,6 +281,10 @@ static int ohci_hcd_omap_probe(struct platform_device *pdev)
> goto err_put_hcd;
> }
>
> + retval = clk_prepare(priv->usb_host_ck);
> + if (retval)
> + goto err_put_host_ck;
> +
> if (!cpu_is_omap15xx())
> priv->usb_dc_ck = clk_get(&pdev->dev, "usb_dc_ck");
> else
> @@ -288,13 +292,17 @@ static int ohci_hcd_omap_probe(struct platform_device *pdev)
>
> if (IS_ERR(priv->usb_dc_ck)) {
> retval = PTR_ERR(priv->usb_dc_ck);
> - goto err_put_host_ck;
> + goto err_unprepare_host_ck;
> }
>
> + retval = clk_prepare(priv->usb_dc_ck);
> + if (retval)
> + goto err_put_dc_ck;
> +
> if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
> dev_dbg(&pdev->dev, "request_mem_region failed\n");
> retval = -EBUSY;
> - goto err_put_dc_ck;
> + goto err_unprepare_dc_ck;
> }
>
> hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
> @@ -319,8 +327,12 @@ static int ohci_hcd_omap_probe(struct platform_device *pdev)
> iounmap(hcd->regs);
> err2:
> release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
> +err_unprepare_dc_ck:
> + clk_unprepare(priv->usb_dc_ck);
> err_put_dc_ck:
> clk_put(priv->usb_dc_ck);
> +err_unprepare_host_ck:
> + clk_unprepare(priv->usb_host_ck);
> err_put_host_ck:
> clk_put(priv->usb_host_ck);
> err_put_hcd:
> @@ -355,7 +367,9 @@ static int ohci_hcd_omap_remove(struct platform_device *pdev)
> }
> iounmap(hcd->regs);
> release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
> + clk_unprepare(priv->usb_dc_ck);
> clk_put(priv->usb_dc_ck);
> + clk_unprepare(priv->usb_host_ck);
> clk_put(priv->usb_host_ck);
> usb_put_hcd(hcd);
> return 0;
> diff --git a/drivers/video/fbdev/omap/hwa742.c b/drivers/video/fbdev/omap/hwa742.c
> index b191bef22d98..9d9fe5c3a7a1 100644
> --- a/drivers/video/fbdev/omap/hwa742.c
> +++ b/drivers/video/fbdev/omap/hwa742.c
> @@ -964,7 +964,7 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode,
> if ((r = calc_extif_timings(ext_clk, &extif_mem_div)) < 0)
> goto err3;
> hwa742.extif->set_timings(&hwa742.reg_timings);
> - clk_enable(hwa742.sys_ck);
> + clk_prepare_enable(hwa742.sys_ck);
>
> calc_hwa742_clk_rates(ext_clk, &sys_clk, &pix_clk);
> if ((r = calc_extif_timings(sys_clk, &extif_mem_div)) < 0)
> @@ -1023,7 +1023,7 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode,
>
> return 0;
> err4:
> - clk_disable(hwa742.sys_ck);
> + clk_disable_unprepare(hwa742.sys_ck);
> err3:
> hwa742.extif->cleanup();
> err2:
> @@ -1037,7 +1037,7 @@ static void hwa742_cleanup(void)
> hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED);
> hwa742.extif->cleanup();
> hwa742.int_ctrl->cleanup();
> - clk_disable(hwa742.sys_ck);
> + clk_disable_unprepare(hwa742.sys_ck);
> }
>
> struct lcd_ctrl hwa742_ctrl = {
> diff --git a/drivers/video/fbdev/omap/lcdc.c b/drivers/video/fbdev/omap/lcdc.c
> index 7317c9aad677..97d20dc0d1d0 100644
> --- a/drivers/video/fbdev/omap/lcdc.c
> +++ b/drivers/video/fbdev/omap/lcdc.c
> @@ -711,7 +711,7 @@ static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode,
> dev_err(fbdev->dev, "failed to adjust LCD rate\n");
> goto fail1;
> }
> - clk_enable(lcdc.lcd_ck);
> + clk_prepare_enable(lcdc.lcd_ck);
>
> r = request_irq(OMAP_LCDC_IRQ, lcdc_irq_handler, 0, MODULE_NAME, fbdev);
> if (r) {
> @@ -746,7 +746,7 @@ static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode,
> fail3:
> free_irq(OMAP_LCDC_IRQ, lcdc.fbdev);
> fail2:
> - clk_disable(lcdc.lcd_ck);
> + clk_disable_unprepare(lcdc.lcd_ck);
> fail1:
> clk_put(lcdc.lcd_ck);
> fail0:
> @@ -760,7 +760,7 @@ static void omap_lcdc_cleanup(void)
> free_fbmem();
> omap_free_lcd_dma();
> free_irq(OMAP_LCDC_IRQ, lcdc.fbdev);
> - clk_disable(lcdc.lcd_ck);
> + clk_disable_unprepare(lcdc.lcd_ck);
> clk_put(lcdc.lcd_ck);
> }
>
> diff --git a/drivers/video/fbdev/omap/sossi.c b/drivers/video/fbdev/omap/sossi.c
> index 80ac67f27f0d..b9cb8b386627 100644
> --- a/drivers/video/fbdev/omap/sossi.c
> +++ b/drivers/video/fbdev/omap/sossi.c
> @@ -598,7 +598,7 @@ static int sossi_init(struct omapfb_device *fbdev)
> l &= ~CONF_SOSSI_RESET_R;
> omap_writel(l, MOD_CONF_CTRL_1);
>
> - clk_enable(sossi.fck);
> + clk_prepare_enable(sossi.fck);
> l = omap_readl(ARM_IDLECT2);
> l &= ~(1 << 8); /* DMACK_REQ */
> omap_writel(l, ARM_IDLECT2);
> @@ -649,7 +649,7 @@ static int sossi_init(struct omapfb_device *fbdev)
> return 0;
>
> err:
> - clk_disable(sossi.fck);
> + clk_disable_unprepare(sossi.fck);
> clk_put(sossi.fck);
> return r;
> }
> @@ -657,6 +657,7 @@ static int sossi_init(struct omapfb_device *fbdev)
> static void sossi_cleanup(void)
> {
> omap_lcdc_free_dma_callback();
> + clk_unprepare(sossi.fck);
> clk_put(sossi.fck);
> iounmap(sossi.base);
> }
> diff --git a/sound/soc/ti/osk5912.c b/sound/soc/ti/osk5912.c
> index 40e29dda7e7a..22da3b335e81 100644
> --- a/sound/soc/ti/osk5912.c
> +++ b/sound/soc/ti/osk5912.c
> @@ -134,6 +134,10 @@ static int __init osk_soc_init(void)
> goto err2;
> }
>
> + err = clk_prepare(tlv320aic23_mclk);
> + if (err)
> + goto err3;
> +
> /*
> * Configure 12 MHz output on MCLK.
> */
> @@ -142,7 +146,7 @@ static int __init osk_soc_init(void)
> if (clk_set_rate(tlv320aic23_mclk, CODEC_CLOCK)) {
> printk(KERN_ERR "Cannot set MCLK for AIC23 CODEC\n");
> err = -ECANCELED;
> - goto err3;
> + goto err4;
> }
> }
>
> @@ -151,6 +155,8 @@ static int __init osk_soc_init(void)
>
> return 0;
>
> +err4:
> + clk_unprepare(tlv320aic23_mclk);
> err3:
> clk_put(tlv320aic23_mclk);
> err2:
> @@ -164,6 +170,7 @@ static int __init osk_soc_init(void)
>
> static void __exit osk_soc_exit(void)
> {
> + clk_unprepare(tlv320aic23_mclk);
> clk_put(tlv320aic23_mclk);
> platform_device_unregister(osk_snd_device);
> }
> --
> 2.35.1
>

2022-03-31 19:09:58

by Janusz Krzysztofik

[permalink] [raw]
Subject: Re: [PATCH v2] ARM: OMAP1: Prepare for conversion of OMAP1 clocks to CCF

Hi Uffe,

On Thursday, 31 March 2022 11:19:43 CEST Ulf Hansson wrote:
> On Mon, 21 Mar 2022 at 22:54, Janusz Krzysztofik <[email protected]> wrote:
> >
> > In preparation for conversion of OMAP1 clocks to common clock framework,
> > identify users of those clocks which don't call clk_prepare/unprepare()
> > and update them to call clk_prepare_enable/clk_disable_unprepare() instead
> > of just clk_enable/disable(), as required by CCF implementation of clock
> > API.
> >
> > v2: update still a few more OMAP specific drivers missed in v1,
> > - call clk_prepare/unprepare() just after/before clk_get/put() where it
> > can make more sense than merging prepare/unprepare with enable/disable.
> >
> > Signed-off-by: Janusz Krzysztofik <[email protected]>
>
> Is there a specific reason why you can't split this into a per subsystem patch?
>
> Don't get me wrong, if you need my ack you have it, but I just wanted
> to know why this is?

There is no specific reason, I just didn't think of that, and indeed, that
is perfectly possible and will be more easy to handle. Please expect a
separate patch for each subsystem soon.

Thanks,
Janusz

>
> Kind regards
> Uffe
>
> > ---
> > arch/arm/mach-omap1/mcbsp.c | 8 ++++----
> > arch/arm/mach-omap1/ocpi.c | 4 ++--
> > arch/arm/mach-omap1/serial.c | 6 +++---
> > arch/arm/mach-omap1/timer32k.c | 2 +-
> > drivers/mmc/host/omap.c | 23 ++++++++++++++---------
> > drivers/usb/gadget/udc/omap_udc.c | 14 ++++++++------
> > drivers/usb/host/ohci-omap.c | 18 ++++++++++++++++--
> > drivers/video/fbdev/omap/hwa742.c | 6 +++---
> > drivers/video/fbdev/omap/lcdc.c | 6 +++---
> > drivers/video/fbdev/omap/sossi.c | 5 +++--
> > sound/soc/ti/osk5912.c | 9 ++++++++-
> > 11 files changed, 65 insertions(+), 36 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c
> > index f36c34f47f11..3ec2badff6af 100644
> > --- a/arch/arm/mach-omap1/mcbsp.c
> > +++ b/arch/arm/mach-omap1/mcbsp.c
> > @@ -44,8 +44,8 @@ static void omap1_mcbsp_request(unsigned int id)
> > api_clk = clk_get(NULL, "api_ck");
> > dsp_clk = clk_get(NULL, "dsp_ck");
> > if (!IS_ERR(api_clk) && !IS_ERR(dsp_clk)) {
> > - clk_enable(api_clk);
> > - clk_enable(dsp_clk);
> > + clk_prepare_enable(api_clk);
> > + clk_prepare_enable(dsp_clk);
> >
> > /*
> > * DSP external peripheral reset
> > @@ -63,11 +63,11 @@ static void omap1_mcbsp_free(unsigned int id)
> > if (id == 0 || id == 2) {
> > if (--dsp_use == 0) {
> > if (!IS_ERR(api_clk)) {
> > - clk_disable(api_clk);
> > + clk_disable_unprepare(api_clk);
> > clk_put(api_clk);
> > }
> > if (!IS_ERR(dsp_clk)) {
> > - clk_disable(dsp_clk);
> > + clk_disable_unprepare(dsp_clk);
> > clk_put(dsp_clk);
> > }
> > }
> > diff --git a/arch/arm/mach-omap1/ocpi.c b/arch/arm/mach-omap1/ocpi.c
> > index 380ea2de58c1..03cc48024fd6 100644
> > --- a/arch/arm/mach-omap1/ocpi.c
> > +++ b/arch/arm/mach-omap1/ocpi.c
> > @@ -73,7 +73,7 @@ static int __init omap_ocpi_init(void)
> > if (IS_ERR(ocpi_ck))
> > return PTR_ERR(ocpi_ck);
> >
> > - clk_enable(ocpi_ck);
> > + clk_prepare_enable(ocpi_ck);
> > ocpi_enable();
> > pr_info("OMAP OCPI interconnect driver loaded\n");
> >
> > @@ -87,7 +87,7 @@ static void __exit omap_ocpi_exit(void)
> > if (!cpu_is_omap16xx())
> > return;
> >
> > - clk_disable(ocpi_ck);
> > + clk_disable_unprepare(ocpi_ck);
> > clk_put(ocpi_ck);
> > }
> >
> > diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c
> > index 9eb591fbfd89..5f591a836ab5 100644
> > --- a/arch/arm/mach-omap1/serial.c
> > +++ b/arch/arm/mach-omap1/serial.c
> > @@ -141,7 +141,7 @@ void __init omap_serial_init(void)
> > if (IS_ERR(uart1_ck))
> > printk("Could not get uart1_ck\n");
> > else {
> > - clk_enable(uart1_ck);
> > + clk_prepare_enable(uart1_ck);
> > if (cpu_is_omap15xx())
> > clk_set_rate(uart1_ck, 12000000);
> > }
> > @@ -151,7 +151,7 @@ void __init omap_serial_init(void)
> > if (IS_ERR(uart2_ck))
> > printk("Could not get uart2_ck\n");
> > else {
> > - clk_enable(uart2_ck);
> > + clk_prepare_enable(uart2_ck);
> > if (cpu_is_omap15xx())
> > clk_set_rate(uart2_ck, 12000000);
> > else
> > @@ -163,7 +163,7 @@ void __init omap_serial_init(void)
> > if (IS_ERR(uart3_ck))
> > printk("Could not get uart3_ck\n");
> > else {
> > - clk_enable(uart3_ck);
> > + clk_prepare_enable(uart3_ck);
> > if (cpu_is_omap15xx())
> > clk_set_rate(uart3_ck, 12000000);
> > }
> > diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c
> > index 780fdf03c3ce..049c7b7f28c4 100644
> > --- a/arch/arm/mach-omap1/timer32k.c
> > +++ b/arch/arm/mach-omap1/timer32k.c
> > @@ -180,7 +180,7 @@ int __init omap_32k_timer_init(void)
> >
> > sync32k_ick = clk_get(NULL, "omap_32ksync_ick");
> > if (!IS_ERR(sync32k_ick))
> > - clk_enable(sync32k_ick);
> > + clk_prepare_enable(sync32k_ick);
> >
> > ret = omap_init_clocksource_32k(base);
> > }
> > diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
> > index 5e5af34090f1..57d39283924d 100644
> > --- a/drivers/mmc/host/omap.c
> > +++ b/drivers/mmc/host/omap.c
> > @@ -1374,7 +1374,7 @@ static int mmc_omap_probe(struct platform_device *pdev)
> > host->iclk = clk_get(&pdev->dev, "ick");
> > if (IS_ERR(host->iclk))
> > return PTR_ERR(host->iclk);
> > - clk_enable(host->iclk);
> > + clk_prepare_enable(host->iclk);
> >
> > host->fclk = clk_get(&pdev->dev, "fck");
> > if (IS_ERR(host->fclk)) {
> > @@ -1382,16 +1382,18 @@ static int mmc_omap_probe(struct platform_device *pdev)
> > goto err_free_iclk;
> > }
> >
> > + ret = clk_prepare(host->fclk);
> > + if (ret)
> > + goto err_put_fclk;
> > +
> > host->dma_tx_burst = -1;
> > host->dma_rx_burst = -1;
> >
> > host->dma_tx = dma_request_chan(&pdev->dev, "tx");
> > if (IS_ERR(host->dma_tx)) {
> > ret = PTR_ERR(host->dma_tx);
> > - if (ret == -EPROBE_DEFER) {
> > - clk_put(host->fclk);
> > - goto err_free_iclk;
> > - }
> > + if (ret == -EPROBE_DEFER)
> > + goto err_free_fclk;
> >
> > host->dma_tx = NULL;
> > dev_warn(host->dev, "TX DMA channel request failed\n");
> > @@ -1403,8 +1405,7 @@ static int mmc_omap_probe(struct platform_device *pdev)
> > if (ret == -EPROBE_DEFER) {
> > if (host->dma_tx)
> > dma_release_channel(host->dma_tx);
> > - clk_put(host->fclk);
> > - goto err_free_iclk;
> > + goto err_free_fclk;
> > }
> >
> > host->dma_rx = NULL;
> > @@ -1454,9 +1455,12 @@ static int mmc_omap_probe(struct platform_device *pdev)
> > dma_release_channel(host->dma_tx);
> > if (host->dma_rx)
> > dma_release_channel(host->dma_rx);
> > +err_free_fclk:
> > + clk_unprepare(host->fclk);
> > +err_put_fclk:
> > clk_put(host->fclk);
> > err_free_iclk:
> > - clk_disable(host->iclk);
> > + clk_disable_unprepare(host->iclk);
> > clk_put(host->iclk);
> > return ret;
> > }
> > @@ -1476,8 +1480,9 @@ static int mmc_omap_remove(struct platform_device *pdev)
> >
> > mmc_omap_fclk_enable(host, 0);
> > free_irq(host->irq, host);
> > + clk_unprepare(host->fclk);
> > clk_put(host->fclk);
> > - clk_disable(host->iclk);
> > + clk_disable_unprepare(host->iclk);
> > clk_put(host->iclk);
> >
> > if (host->dma_tx)
> > diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c
> > index 494da00398d7..8768a3280e19 100644
> > --- a/drivers/usb/gadget/udc/omap_udc.c
> > +++ b/drivers/usb/gadget/udc/omap_udc.c
> > @@ -2604,6 +2604,8 @@ static void omap_udc_release(struct device *dev)
> > if (udc->dc_clk) {
> > if (udc->clk_requested)
> > omap_udc_enable_clock(0);
> > + clk_unprepare(udc->hhc_clk);
> > + clk_unprepare(udc->dc_clk);
> > clk_put(udc->hhc_clk);
> > clk_put(udc->dc_clk);
> > }
> > @@ -2768,8 +2770,8 @@ static int omap_udc_probe(struct platform_device *pdev)
> > hhc_clk = clk_get(&pdev->dev, "usb_hhc_ck");
> > BUG_ON(IS_ERR(dc_clk) || IS_ERR(hhc_clk));
> > /* can't use omap_udc_enable_clock yet */
> > - clk_enable(dc_clk);
> > - clk_enable(hhc_clk);
> > + clk_prepare_enable(dc_clk);
> > + clk_prepare_enable(hhc_clk);
> > udelay(100);
> > }
> >
> > @@ -2778,8 +2780,8 @@ static int omap_udc_probe(struct platform_device *pdev)
> > hhc_clk = clk_get(&pdev->dev, "l3_ocpi_ck");
> > BUG_ON(IS_ERR(dc_clk) || IS_ERR(hhc_clk));
> > /* can't use omap_udc_enable_clock yet */
> > - clk_enable(dc_clk);
> > - clk_enable(hhc_clk);
> > + clk_prepare_enable(dc_clk);
> > + clk_prepare_enable(hhc_clk);
> > udelay(100);
> > }
> >
> > @@ -2927,8 +2929,8 @@ static int omap_udc_probe(struct platform_device *pdev)
> > usb_put_phy(xceiv);
> >
> > if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
> > - clk_disable(hhc_clk);
> > - clk_disable(dc_clk);
> > + clk_disable_unprepare(hhc_clk);
> > + clk_disable_unprepare(dc_clk);
> > clk_put(hhc_clk);
> > clk_put(dc_clk);
> > }
> > diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
> > index 45dcf8292072..2ab2e089a2b7 100644
> > --- a/drivers/usb/host/ohci-omap.c
> > +++ b/drivers/usb/host/ohci-omap.c
> > @@ -281,6 +281,10 @@ static int ohci_hcd_omap_probe(struct platform_device *pdev)
> > goto err_put_hcd;
> > }
> >
> > + retval = clk_prepare(priv->usb_host_ck);
> > + if (retval)
> > + goto err_put_host_ck;
> > +
> > if (!cpu_is_omap15xx())
> > priv->usb_dc_ck = clk_get(&pdev->dev, "usb_dc_ck");
> > else
> > @@ -288,13 +292,17 @@ static int ohci_hcd_omap_probe(struct platform_device *pdev)
> >
> > if (IS_ERR(priv->usb_dc_ck)) {
> > retval = PTR_ERR(priv->usb_dc_ck);
> > - goto err_put_host_ck;
> > + goto err_unprepare_host_ck;
> > }
> >
> > + retval = clk_prepare(priv->usb_dc_ck);
> > + if (retval)
> > + goto err_put_dc_ck;
> > +
> > if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
> > dev_dbg(&pdev->dev, "request_mem_region failed\n");
> > retval = -EBUSY;
> > - goto err_put_dc_ck;
> > + goto err_unprepare_dc_ck;
> > }
> >
> > hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
> > @@ -319,8 +327,12 @@ static int ohci_hcd_omap_probe(struct platform_device *pdev)
> > iounmap(hcd->regs);
> > err2:
> > release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
> > +err_unprepare_dc_ck:
> > + clk_unprepare(priv->usb_dc_ck);
> > err_put_dc_ck:
> > clk_put(priv->usb_dc_ck);
> > +err_unprepare_host_ck:
> > + clk_unprepare(priv->usb_host_ck);
> > err_put_host_ck:
> > clk_put(priv->usb_host_ck);
> > err_put_hcd:
> > @@ -355,7 +367,9 @@ static int ohci_hcd_omap_remove(struct platform_device *pdev)
> > }
> > iounmap(hcd->regs);
> > release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
> > + clk_unprepare(priv->usb_dc_ck);
> > clk_put(priv->usb_dc_ck);
> > + clk_unprepare(priv->usb_host_ck);
> > clk_put(priv->usb_host_ck);
> > usb_put_hcd(hcd);
> > return 0;
> > diff --git a/drivers/video/fbdev/omap/hwa742.c b/drivers/video/fbdev/omap/hwa742.c
> > index b191bef22d98..9d9fe5c3a7a1 100644
> > --- a/drivers/video/fbdev/omap/hwa742.c
> > +++ b/drivers/video/fbdev/omap/hwa742.c
> > @@ -964,7 +964,7 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode,
> > if ((r = calc_extif_timings(ext_clk, &extif_mem_div)) < 0)
> > goto err3;
> > hwa742.extif->set_timings(&hwa742.reg_timings);
> > - clk_enable(hwa742.sys_ck);
> > + clk_prepare_enable(hwa742.sys_ck);
> >
> > calc_hwa742_clk_rates(ext_clk, &sys_clk, &pix_clk);
> > if ((r = calc_extif_timings(sys_clk, &extif_mem_div)) < 0)
> > @@ -1023,7 +1023,7 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode,
> >
> > return 0;
> > err4:
> > - clk_disable(hwa742.sys_ck);
> > + clk_disable_unprepare(hwa742.sys_ck);
> > err3:
> > hwa742.extif->cleanup();
> > err2:
> > @@ -1037,7 +1037,7 @@ static void hwa742_cleanup(void)
> > hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED);
> > hwa742.extif->cleanup();
> > hwa742.int_ctrl->cleanup();
> > - clk_disable(hwa742.sys_ck);
> > + clk_disable_unprepare(hwa742.sys_ck);
> > }
> >
> > struct lcd_ctrl hwa742_ctrl = {
> > diff --git a/drivers/video/fbdev/omap/lcdc.c b/drivers/video/fbdev/omap/lcdc.c
> > index 7317c9aad677..97d20dc0d1d0 100644
> > --- a/drivers/video/fbdev/omap/lcdc.c
> > +++ b/drivers/video/fbdev/omap/lcdc.c
> > @@ -711,7 +711,7 @@ static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode,
> > dev_err(fbdev->dev, "failed to adjust LCD rate\n");
> > goto fail1;
> > }
> > - clk_enable(lcdc.lcd_ck);
> > + clk_prepare_enable(lcdc.lcd_ck);
> >
> > r = request_irq(OMAP_LCDC_IRQ, lcdc_irq_handler, 0, MODULE_NAME, fbdev);
> > if (r) {
> > @@ -746,7 +746,7 @@ static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode,
> > fail3:
> > free_irq(OMAP_LCDC_IRQ, lcdc.fbdev);
> > fail2:
> > - clk_disable(lcdc.lcd_ck);
> > + clk_disable_unprepare(lcdc.lcd_ck);
> > fail1:
> > clk_put(lcdc.lcd_ck);
> > fail0:
> > @@ -760,7 +760,7 @@ static void omap_lcdc_cleanup(void)
> > free_fbmem();
> > omap_free_lcd_dma();
> > free_irq(OMAP_LCDC_IRQ, lcdc.fbdev);
> > - clk_disable(lcdc.lcd_ck);
> > + clk_disable_unprepare(lcdc.lcd_ck);
> > clk_put(lcdc.lcd_ck);
> > }
> >
> > diff --git a/drivers/video/fbdev/omap/sossi.c b/drivers/video/fbdev/omap/sossi.c
> > index 80ac67f27f0d..b9cb8b386627 100644
> > --- a/drivers/video/fbdev/omap/sossi.c
> > +++ b/drivers/video/fbdev/omap/sossi.c
> > @@ -598,7 +598,7 @@ static int sossi_init(struct omapfb_device *fbdev)
> > l &= ~CONF_SOSSI_RESET_R;
> > omap_writel(l, MOD_CONF_CTRL_1);
> >
> > - clk_enable(sossi.fck);
> > + clk_prepare_enable(sossi.fck);
> > l = omap_readl(ARM_IDLECT2);
> > l &= ~(1 << 8); /* DMACK_REQ */
> > omap_writel(l, ARM_IDLECT2);
> > @@ -649,7 +649,7 @@ static int sossi_init(struct omapfb_device *fbdev)
> > return 0;
> >
> > err:
> > - clk_disable(sossi.fck);
> > + clk_disable_unprepare(sossi.fck);
> > clk_put(sossi.fck);
> > return r;
> > }
> > @@ -657,6 +657,7 @@ static int sossi_init(struct omapfb_device *fbdev)
> > static void sossi_cleanup(void)
> > {
> > omap_lcdc_free_dma_callback();
> > + clk_unprepare(sossi.fck);
> > clk_put(sossi.fck);
> > iounmap(sossi.base);
> > }
> > diff --git a/sound/soc/ti/osk5912.c b/sound/soc/ti/osk5912.c
> > index 40e29dda7e7a..22da3b335e81 100644
> > --- a/sound/soc/ti/osk5912.c
> > +++ b/sound/soc/ti/osk5912.c
> > @@ -134,6 +134,10 @@ static int __init osk_soc_init(void)
> > goto err2;
> > }
> >
> > + err = clk_prepare(tlv320aic23_mclk);
> > + if (err)
> > + goto err3;
> > +
> > /*
> > * Configure 12 MHz output on MCLK.
> > */
> > @@ -142,7 +146,7 @@ static int __init osk_soc_init(void)
> > if (clk_set_rate(tlv320aic23_mclk, CODEC_CLOCK)) {
> > printk(KERN_ERR "Cannot set MCLK for AIC23 CODEC\n");
> > err = -ECANCELED;
> > - goto err3;
> > + goto err4;
> > }
> > }
> >
> > @@ -151,6 +155,8 @@ static int __init osk_soc_init(void)
> >
> > return 0;
> >
> > +err4:
> > + clk_unprepare(tlv320aic23_mclk);
> > err3:
> > clk_put(tlv320aic23_mclk);
> > err2:
> > @@ -164,6 +170,7 @@ static int __init osk_soc_init(void)
> >
> > static void __exit osk_soc_exit(void)
> > {
> > + clk_unprepare(tlv320aic23_mclk);
> > clk_put(tlv320aic23_mclk);
> > platform_device_unregister(osk_snd_device);
> > }
> > --
> > 2.35.1
> >
>




2022-04-06 16:45:27

by Aaro Koskinen

[permalink] [raw]
Subject: Re: [PATCH v2] ARM: OMAP1: Prepare for conversion of OMAP1 clocks to CCF

Hi,

On Sat, Mar 26, 2022 at 10:17:49PM +0100, Janusz Krzysztofik wrote:
> Dnia wtorek, 22 marca 2022 20:07:53 CET Aaro Koskinen pisze:
> > On Tue, Mar 22, 2022 at 06:36:48PM +0200, Aaro Koskinen wrote:
> > > Something is still broken. When doing kexec (using CCF kernel), the
> > > kexec'ed kernel now hangs early (on 770):
> > [...]
> > > [ 0.928863] calling omap1_init_devices+0x0/0x2c @ 1
> >
> > It hangs in omap_sram_reprogram_clock() (<- omap1_select_table_rate()
> > <- omap1_clk_late_init()).
>
> I've reviewed my changes but haven't found anything suspicious.

The below change is fixing the kexec boot. Based on the comment in the
code, it seems this clock is needed for the SRAM to work.

diff --git a/arch/arm/mach-omap1/clock_data.c b/arch/arm/mach-omap1/clock_data.c
index e33e11f826af..b8b4876ff935 100644
--- a/arch/arm/mach-omap1/clock_data.c
+++ b/arch/arm/mach-omap1/clock_data.c
@@ -285,7 +285,7 @@ static struct omap1_clk tc1_ck = {
*/

static struct omap1_clk tc2_ck = {
- .hw.init = CLK_HW_INIT("tc2_ck", "tc_ck", &omap1_clk_gate_ops, 0),
+ .hw.init = CLK_HW_INIT("tc2_ck", "tc_ck", &omap1_clk_gate_ops, CLK_IS_CRITICAL),
.ops = &clkops_generic,
.enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT3),
.enable_bit = EN_TC2_CK,

A.

2022-04-06 21:03:16

by Janusz Krzysztofik

[permalink] [raw]
Subject: Re: [PATCH v2] ARM: OMAP1: Prepare for conversion of OMAP1 clocks to CCF

Dnia środa, 6 kwietnia 2022 15:21:49 CEST Aaro Koskinen pisze:
> Hi,
>
> On Sat, Mar 26, 2022 at 10:17:49PM +0100, Janusz Krzysztofik wrote:
> > Dnia wtorek, 22 marca 2022 20:07:53 CET Aaro Koskinen pisze:
> > > On Tue, Mar 22, 2022 at 06:36:48PM +0200, Aaro Koskinen wrote:
> > > > Something is still broken. When doing kexec (using CCF kernel), the
> > > > kexec'ed kernel now hangs early (on 770):
> > > [...]
> > > > [ 0.928863] calling omap1_init_devices+0x0/0x2c @ 1
> > >
> > > It hangs in omap_sram_reprogram_clock() (<- omap1_select_table_rate()
> > > <- omap1_clk_late_init()).
> >
> > I've reviewed my changes but haven't found anything suspicious.
>
> The below change is fixing the kexec boot. Based on the comment in the
> code, it seems this clock is needed for the SRAM to work.
>
> diff --git a/arch/arm/mach-omap1/clock_data.c b/arch/arm/mach-omap1/clock_data.c
> index e33e11f826af..b8b4876ff935 100644
> --- a/arch/arm/mach-omap1/clock_data.c
> +++ b/arch/arm/mach-omap1/clock_data.c
> @@ -285,7 +285,7 @@ static struct omap1_clk tc1_ck = {
> */
>
> static struct omap1_clk tc2_ck = {
> - .hw.init = CLK_HW_INIT("tc2_ck", "tc_ck", &omap1_clk_gate_ops, 0),
> + .hw.init = CLK_HW_INIT("tc2_ck", "tc_ck", &omap1_clk_gate_ops, CLK_IS_CRITICAL),
> .ops = &clkops_generic,
> .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT3),
> .enable_bit = EN_TC2_CK,
>
> A.
>

Thank you Aaro. Will you submit this as a separate fix, or should I submit
v2 of my patch 4/4 with your fix included?

Thanks,
Janusz



2022-04-07 01:23:19

by Aaro Koskinen

[permalink] [raw]
Subject: Re: [PATCH v2] ARM: OMAP1: Prepare for conversion of OMAP1 clocks to CCF

Hi,

On Wed, Apr 06, 2022 at 08:48:14PM +0200, Janusz Krzysztofik wrote:
> Dnia środa, 6 kwietnia 2022 15:21:49 CEST Aaro Koskinen pisze:
> > On Sat, Mar 26, 2022 at 10:17:49PM +0100, Janusz Krzysztofik wrote:
> > > Dnia wtorek, 22 marca 2022 20:07:53 CET Aaro Koskinen pisze:
> > > > On Tue, Mar 22, 2022 at 06:36:48PM +0200, Aaro Koskinen wrote:
> > > > > Something is still broken. When doing kexec (using CCF kernel), the
> > > > > kexec'ed kernel now hangs early (on 770):
> > > > [...]
> > > > > [ 0.928863] calling omap1_init_devices+0x0/0x2c @ 1
> > > >
> > > > It hangs in omap_sram_reprogram_clock() (<- omap1_select_table_rate()
> > > > <- omap1_clk_late_init()).
> > >
> > > I've reviewed my changes but haven't found anything suspicious.
> >
> > The below change is fixing the kexec boot. Based on the comment in the
> > code, it seems this clock is needed for the SRAM to work.
> >
> > diff --git a/arch/arm/mach-omap1/clock_data.c b/arch/arm/mach-omap1/clock_data.c
> > index e33e11f826af..b8b4876ff935 100644
> > --- a/arch/arm/mach-omap1/clock_data.c
> > +++ b/arch/arm/mach-omap1/clock_data.c
> > @@ -285,7 +285,7 @@ static struct omap1_clk tc1_ck = {
> > */
> >
> > static struct omap1_clk tc2_ck = {
> > - .hw.init = CLK_HW_INIT("tc2_ck", "tc_ck", &omap1_clk_gate_ops, 0),
> > + .hw.init = CLK_HW_INIT("tc2_ck", "tc_ck", &omap1_clk_gate_ops, CLK_IS_CRITICAL),
> > .ops = &clkops_generic,
> > .enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT3),
> > .enable_bit = EN_TC2_CK,
> >
> > A.
> >
>
> Thank you Aaro. Will you submit this as a separate fix, or should I submit
> v2 of my patch 4/4 with your fix included?

Please send a new version with the fix included.

A.