Skip to content

Commit

Permalink
Merge tag 'omap-fixes-a-for-v3.8-window' of git://git.kernel.org/pub/…
Browse files Browse the repository at this point in the history
…scm/linux/kernel/git/pjw/omap-pending into fixes

From Paul Walmsley per Tony Lindgrens request:

Fix some OMAP4 clock problems, and deal with some sparse warnings from
the OMAP CPUIdle code.

* tag 'omap-fixes-a-for-v3.8-window' of git://git.kernel.org/pub/scm/linux/kernel/git/pjw/omap-pending:
  ARM: OMAP3/4: cpuidle: fix sparse and checkpatch warnings
  ARM: OMAP4: clock data: DPLLs are missing bypass clocks in their parent lists
  ARM: OMAP4: clock data: div_iva_hs_clk is a power-of-two divider
  ARM: OMAP4: Fix EMU clock domain always on
  ARM: OMAP4460: Workaround ABE DPLL failing to turn-on
  ARM: OMAP4: Enhance support for DPLLs with 4X multiplier
  ARM: OMAP4: Add function table for non-M4X dplls
  ARM: OMAP4: Update timer clock aliases
  • Loading branch information
Olof Johansson committed Dec 18, 2012
2 parents 68136b1 + 9db316b commit 10be289
Show file tree
Hide file tree
Showing 7 changed files with 189 additions and 54 deletions.
78 changes: 65 additions & 13 deletions arch/arm/mach-omap2/cclock44xx_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@
#define OMAP4430_MODULEMODE_HWCTRL_SHIFT 0
#define OMAP4430_MODULEMODE_SWCTRL_SHIFT 1

/*
* OMAP4 ABE DPLL default frequency. In OMAP4460 TRM version V, section
* "3.6.3.2.3 CM1_ABE Clock Generator" states that the "DPLL_ABE_X2_CLK
* must be set to 196.608 MHz" and hence, the DPLL locked frequency is
* half of this value.
*/
#define OMAP4_DPLL_ABE_DEFFREQ 98304000

/* Root clocks */

DEFINE_CLK_FIXED_RATE(extalt_clkin_ck, CLK_IS_ROOT, 59000000, 0x0);
Expand Down Expand Up @@ -124,6 +132,8 @@ static struct dpll_data dpll_abe_dd = {
.enable_mask = OMAP4430_DPLL_EN_MASK,
.autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
.idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
.m4xen_mask = OMAP4430_DPLL_REGM4XEN_MASK,
.lpmode_mask = OMAP4430_DPLL_LPMODE_EN_MASK,
.max_multiplier = 2047,
.max_divider = 128,
.min_divider = 1,
Expand Down Expand Up @@ -233,7 +243,7 @@ static struct dpll_data dpll_core_dd = {


static const char *dpll_core_ck_parents[] = {
"sys_clkin_ck",
"sys_clkin_ck", "core_hsd_byp_clk_mux_ck"
};

static struct clk dpll_core_ck;
Expand Down Expand Up @@ -286,9 +296,9 @@ DEFINE_CLK_DIVIDER(div_core_ck, "dpll_core_m5x2_ck", &dpll_core_m5x2_ck, 0x0,
OMAP4430_CM_CLKSEL_CORE, OMAP4430_CLKSEL_CORE_SHIFT,
OMAP4430_CLKSEL_CORE_WIDTH, 0x0, NULL);

DEFINE_CLK_OMAP_HSDIVIDER(div_iva_hs_clk, "dpll_core_m5x2_ck",
&dpll_core_m5x2_ck, 0x0, OMAP4430_CM_BYPCLK_DPLL_IVA,
OMAP4430_CLKSEL_0_1_MASK);
DEFINE_CLK_DIVIDER(div_iva_hs_clk, "dpll_core_m5x2_ck", &dpll_core_m5x2_ck,
0x0, OMAP4430_CM_BYPCLK_DPLL_IVA, OMAP4430_CLKSEL_0_1_SHIFT,
OMAP4430_CLKSEL_0_1_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);

DEFINE_CLK_DIVIDER(div_mpu_hs_clk, "dpll_core_m5x2_ck", &dpll_core_m5x2_ck,
0x0, OMAP4430_CM_BYPCLK_DPLL_MPU, OMAP4430_CLKSEL_0_1_SHIFT,
Expand Down Expand Up @@ -363,8 +373,21 @@ static struct dpll_data dpll_iva_dd = {
.min_divider = 1,
};

static const char *dpll_iva_ck_parents[] = {
"sys_clkin_ck", "iva_hsd_byp_clk_mux_ck"
};

static struct clk dpll_iva_ck;

static const struct clk_ops dpll_ck_ops = {
.enable = &omap3_noncore_dpll_enable,
.disable = &omap3_noncore_dpll_disable,
.recalc_rate = &omap3_dpll_recalc,
.round_rate = &omap2_dpll_round_rate,
.set_rate = &omap3_noncore_dpll_set_rate,
.get_parent = &omap2_init_dpll_parent,
};

static struct clk_hw_omap dpll_iva_ck_hw = {
.hw = {
.clk = &dpll_iva_ck,
Expand All @@ -373,7 +396,7 @@ static struct clk_hw_omap dpll_iva_ck_hw = {
.ops = &clkhwops_omap3_dpll,
};

DEFINE_STRUCT_CLK(dpll_iva_ck, dpll_core_ck_parents, dpll_abe_ck_ops);
DEFINE_STRUCT_CLK(dpll_iva_ck, dpll_iva_ck_parents, dpll_ck_ops);

static const char *dpll_iva_x2_ck_parents[] = {
"dpll_iva_ck",
Expand Down Expand Up @@ -416,6 +439,10 @@ static struct dpll_data dpll_mpu_dd = {
.min_divider = 1,
};

static const char *dpll_mpu_ck_parents[] = {
"sys_clkin_ck", "div_mpu_hs_clk"
};

static struct clk dpll_mpu_ck;

static struct clk_hw_omap dpll_mpu_ck_hw = {
Expand All @@ -426,7 +453,7 @@ static struct clk_hw_omap dpll_mpu_ck_hw = {
.ops = &clkhwops_omap3_dpll,
};

DEFINE_STRUCT_CLK(dpll_mpu_ck, dpll_core_ck_parents, dpll_abe_ck_ops);
DEFINE_STRUCT_CLK(dpll_mpu_ck, dpll_mpu_ck_parents, dpll_ck_ops);

DEFINE_CLK_FIXED_FACTOR(mpu_periphclk, "dpll_mpu_ck", &dpll_mpu_ck, 0x0, 1, 2);

Expand Down Expand Up @@ -464,6 +491,9 @@ static struct dpll_data dpll_per_dd = {
.min_divider = 1,
};

static const char *dpll_per_ck_parents[] = {
"sys_clkin_ck", "per_hsd_byp_clk_mux_ck"
};

static struct clk dpll_per_ck;

Expand All @@ -475,7 +505,7 @@ static struct clk_hw_omap dpll_per_ck_hw = {
.ops = &clkhwops_omap3_dpll,
};

DEFINE_STRUCT_CLK(dpll_per_ck, dpll_core_ck_parents, dpll_abe_ck_ops);
DEFINE_STRUCT_CLK(dpll_per_ck, dpll_per_ck_parents, dpll_ck_ops);

DEFINE_CLK_DIVIDER(dpll_per_m2_ck, "dpll_per_ck", &dpll_per_ck, 0x0,
OMAP4430_CM_DIV_M2_DPLL_PER, OMAP4430_DPLL_CLKOUT_DIV_SHIFT,
Expand Down Expand Up @@ -559,6 +589,10 @@ static struct dpll_data dpll_usb_dd = {
.min_divider = 1,
};

static const char *dpll_usb_ck_parents[] = {
"sys_clkin_ck", "usb_hs_clk_div_ck"
};

static struct clk dpll_usb_ck;

static struct clk_hw_omap dpll_usb_ck_hw = {
Expand All @@ -569,7 +603,7 @@ static struct clk_hw_omap dpll_usb_ck_hw = {
.ops = &clkhwops_omap3_dpll,
};

DEFINE_STRUCT_CLK(dpll_usb_ck, dpll_core_ck_parents, dpll_abe_ck_ops);
DEFINE_STRUCT_CLK(dpll_usb_ck, dpll_usb_ck_parents, dpll_ck_ops);

static const char *dpll_usb_clkdcoldo_ck_parents[] = {
"dpll_usb_ck",
Expand Down Expand Up @@ -696,9 +730,13 @@ DEFINE_CLK_DIVIDER(syc_clk_div_ck, "sys_clkin_ck", &sys_clkin_ck, 0x0,
OMAP4430_CM_ABE_DSS_SYS_CLKSEL, OMAP4430_CLKSEL_0_0_SHIFT,
OMAP4430_CLKSEL_0_0_WIDTH, 0x0, NULL);

static const char *dbgclk_mux_ck_parents[] = {
"sys_clkin_ck"
};

static struct clk dbgclk_mux_ck;
DEFINE_STRUCT_CLK_HW_OMAP(dbgclk_mux_ck, NULL);
DEFINE_STRUCT_CLK(dbgclk_mux_ck, dpll_core_ck_parents,
DEFINE_STRUCT_CLK(dbgclk_mux_ck, dbgclk_mux_ck_parents,
dpll_usb_clkdcoldo_ck_ops);

/* Leaf clocks controlled by modules */
Expand Down Expand Up @@ -1935,10 +1973,10 @@ static struct omap_clk omap44xx_clks[] = {
CLK("4803e000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X),
CLK("48086000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X),
CLK("48088000.timer", "timer_sys_ck", &sys_clkin_ck, CK_443X),
CLK("49038000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
CLK("4903a000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
CLK("4903c000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
CLK("4903e000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
CLK("40138000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
CLK("4013a000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
CLK("4013c000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
CLK("4013e000.timer", "timer_sys_ck", &syc_clk_div_ck, CK_443X),
CLK(NULL, "cpufreq_ck", &dpll_mpu_ck, CK_443X),
};

Expand All @@ -1955,6 +1993,7 @@ int __init omap4xxx_clk_init(void)
{
u32 cpu_clkflg;
struct omap_clk *c;
int rc;

if (cpu_is_omap443x()) {
cpu_mask = RATE_IN_4430;
Expand Down Expand Up @@ -1983,5 +2022,18 @@ int __init omap4xxx_clk_init(void)
omap2_clk_enable_init_clocks(enable_init_clks,
ARRAY_SIZE(enable_init_clks));

/*
* On OMAP4460 the ABE DPLL fails to turn on if in idle low-power
* state when turning the ABE clock domain. Workaround this by
* locking the ABE DPLL on boot.
*/
if (cpu_is_omap446x()) {
rc = clk_set_parent(&abe_dpll_refclk_mux_ck, &sys_32k_ck);
if (!rc)
rc = clk_set_rate(&dpll_abe_ck, OMAP4_DPLL_ABE_DEFFREQ);
if (rc)
pr_err("%s: failed to configure ABE DPLL!\n", __func__);
}

return 0;
}
10 changes: 10 additions & 0 deletions arch/arm/mach-omap2/clock.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ struct clksel {
* @enable_mask: mask of the DPLL mode bitfield in @control_reg
* @last_rounded_rate: cache of the last rate result of omap2_dpll_round_rate()
* @last_rounded_m: cache of the last M result of omap2_dpll_round_rate()
* @last_rounded_m4xen: cache of the last M4X result of
* omap4_dpll_regm4xen_round_rate()
* @last_rounded_lpmode: cache of the last lpmode result of
* omap4_dpll_lpmode_recalc()
* @max_multiplier: maximum valid non-bypass multiplier value (actual)
* @last_rounded_n: cache of the last N result of omap2_dpll_round_rate()
* @min_divider: minimum valid non-bypass divider value (actual)
Expand All @@ -205,6 +209,8 @@ struct clksel {
* @autoidle_mask: mask of the DPLL autoidle mode bitfield in @autoidle_reg
* @freqsel_mask: mask of the DPLL jitter correction bitfield in @control_reg
* @idlest_mask: mask of the DPLL idle status bitfield in @idlest_reg
* @lpmode_mask: mask of the DPLL low-power mode bitfield in @control_reg
* @m4xen_mask: mask of the DPLL M4X multiplier bitfield in @control_reg
* @auto_recal_bit: bitshift of the driftguard enable bit in @control_reg
* @recal_en_bit: bitshift of the PRM_IRQENABLE_* bit for recalibration IRQs
* @recal_st_bit: bitshift of the PRM_IRQSTATUS_* bit for recalibration IRQs
Expand Down Expand Up @@ -233,6 +239,8 @@ struct dpll_data {
u32 enable_mask;
unsigned long last_rounded_rate;
u16 last_rounded_m;
u8 last_rounded_m4xen;
u8 last_rounded_lpmode;
u16 max_multiplier;
u8 last_rounded_n;
u8 min_divider;
Expand All @@ -245,6 +253,8 @@ struct dpll_data {
u32 idlest_mask;
u32 dco_mask;
u32 sddiv_mask;
u32 lpmode_mask;
u32 m4xen_mask;
u8 auto_recal_bit;
u8 recal_en_bit;
u8 recal_st_bit;
Expand Down
3 changes: 2 additions & 1 deletion arch/arm/mach-omap2/clockdomain.c
Original file line number Diff line number Diff line change
Expand Up @@ -998,7 +998,8 @@ int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
spin_lock_irqsave(&clkdm->lock, flags);

/* corner case: disabling unused clocks */
if (__clk_get_enable_count(clk) == 0)
if ((__clk_get_enable_count(clk) == 0) &&
(atomic_read(&clkdm->usecount) == 0))
goto ccd_exit;

if (atomic_read(&clkdm->usecount) == 0) {
Expand Down
14 changes: 9 additions & 5 deletions arch/arm/mach-omap2/cpuidle34xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ struct omap3_idle_statedata {
u32 core_state;
};

static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd;

static struct omap3_idle_statedata omap3_idle_data[] = {
{
.mpu_state = PWRDM_POWER_ON,
Expand Down Expand Up @@ -71,7 +73,7 @@ static struct omap3_idle_statedata omap3_idle_data[] = {
},
};

static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd;
/* Private functions */

static int __omap3_enter_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
Expand Down Expand Up @@ -260,11 +262,11 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
return ret;
}

DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev);
static DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev);

struct cpuidle_driver omap3_idle_driver = {
.name = "omap3_idle",
.owner = THIS_MODULE,
static struct cpuidle_driver omap3_idle_driver = {
.name = "omap3_idle",
.owner = THIS_MODULE,
.states = {
{
.enter = omap3_enter_idle_bm,
Expand Down Expand Up @@ -327,6 +329,8 @@ struct cpuidle_driver omap3_idle_driver = {
.safe_state_index = 0,
};

/* Public functions */

/**
* omap3_idle_init - Init routine for OMAP3 idle
*
Expand Down
28 changes: 16 additions & 12 deletions arch/arm/mach-omap2/cpuidle44xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ static struct clockdomain *cpu_clkdm[NR_CPUS];
static atomic_t abort_barrier;
static bool cpu_done[NR_CPUS];

/* Private functions */

/**
* omap4_enter_idle_coupled_[simple/coupled] - OMAP4 cpuidle entry functions
* @dev: cpuidle device
Expand Down Expand Up @@ -161,9 +163,19 @@ static int omap4_enter_idle_coupled(struct cpuidle_device *dev,
return index;
}

DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev);
/*
* For each cpu, setup the broadcast timer because local timers
* stops for the states above C1.
*/
static void omap_setup_broadcast_timer(void *arg)
{
int cpu = smp_processor_id();
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
}

static DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev);

struct cpuidle_driver omap4_idle_driver = {
static struct cpuidle_driver omap4_idle_driver = {
.name = "omap4_idle",
.owner = THIS_MODULE,
.en_core_tk_irqen = 1,
Expand All @@ -178,7 +190,7 @@ struct cpuidle_driver omap4_idle_driver = {
.desc = "MPUSS ON"
},
{
/* C2 - CPU0 OFF + CPU1 OFF + MPU CSWR */
/* C2 - CPU0 OFF + CPU1 OFF + MPU CSWR */
.exit_latency = 328 + 440,
.target_residency = 960,
.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_COUPLED,
Expand All @@ -200,15 +212,7 @@ struct cpuidle_driver omap4_idle_driver = {
.safe_state_index = 0,
};

/*
* For each cpu, setup the broadcast timer because local timers
* stops for the states above C1.
*/
static void omap_setup_broadcast_timer(void *arg)
{
int cpu = smp_processor_id();
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
}
/* Public functions */

/**
* omap4_idle_init - Init routine for OMAP4 idle
Expand Down
Loading

0 comments on commit 10be289

Please sign in to comment.