Commit b19974dc authored by Juha Yrjola's avatar Juha Yrjola

Merge 65.200.49.170:linux-omap

parents 246e7893 3bfb289c
...@@ -586,77 +586,55 @@ static int omap1_clk_set_rate(struct clk *clk, unsigned long rate) ...@@ -586,77 +586,55 @@ static int omap1_clk_set_rate(struct clk *clk, unsigned long rate)
*-------------------------------------------------------------------------*/ *-------------------------------------------------------------------------*/
#ifdef CONFIG_OMAP_RESET_CLOCKS #ifdef CONFIG_OMAP_RESET_CLOCKS
/*
* Resets some clocks that may be left on from bootloader,
* but leaves serial clocks on. See also omap_late_clk_reset().
*/
static inline void omap1_early_clk_reset(void)
{
//omap_writel(0x3 << 29, MOD_CONF_CTRL_0);
}
static int __init omap1_late_clk_reset(void) static void __init omap1_clk_disable_unused(struct clk *clk)
{ {
/* Turn off all unused clocks */
struct clk *p;
__u32 regval32; __u32 regval32;
/* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */ /* Clocks in the DSP domain need api_ck. Just assume bootloader
regval32 = omap_readw(SOFT_REQ_REG) & (1 << 4); * has not enabled any DSP clocks */
omap_writew(regval32, SOFT_REQ_REG); if ((u32)clk->enable_reg == DSP_IDLECT2) {
omap_writew(0, SOFT_REQ_REG2); printk(KERN_INFO "Skipping reset check for DSP domain "
"clock \"%s\"\n", clk->name);
list_for_each_entry(p, &clocks, node) { return;
if (p->usecount > 0 || (p->flags & ALWAYS_ENABLED) || }
p->enable_reg == 0)
continue;
/* Clocks in the DSP domain need api_ck. Just assume bootloader
* has not enabled any DSP clocks */
if ((u32)p->enable_reg == DSP_IDLECT2) {
printk(KERN_INFO "Skipping reset check for DSP domain "
"clock \"%s\"\n", p->name);
continue;
}
/* Is the clock already disabled? */ /* Is the clock already disabled? */
if (p->flags & ENABLE_REG_32BIT) { if (clk->flags & ENABLE_REG_32BIT) {
if (p->flags & VIRTUAL_IO_ADDRESS) if (clk->flags & VIRTUAL_IO_ADDRESS)
regval32 = __raw_readl(p->enable_reg); regval32 = __raw_readl(clk->enable_reg);
else
regval32 = omap_readl(p->enable_reg);
} else {
if (p->flags & VIRTUAL_IO_ADDRESS)
regval32 = __raw_readw(p->enable_reg);
else else
regval32 = omap_readw(p->enable_reg); regval32 = omap_readl(clk->enable_reg);
} } else {
if (clk->flags & VIRTUAL_IO_ADDRESS)
if ((regval32 & (1 << p->enable_bit)) == 0) regval32 = __raw_readw(clk->enable_reg);
continue; else
regval32 = omap_readw(clk->enable_reg);
}
/* FIXME: This clock seems to be necessary but no-one if ((regval32 & (1 << clk->enable_bit)) == 0)
* has asked for its activation. */ return;
if (p == &tc2_ck // FIX: pm.c (SRAM), CCP, Camera
|| p == &ck_dpll1out.clk // FIX: SoSSI, SSR
|| p == &arm_gpio_ck // FIX: GPIO code for 1510
) {
printk(KERN_INFO "FIXME: Clock \"%s\" seems unused\n",
p->name);
continue;
}
printk(KERN_INFO "Disabling unused clock \"%s\"... ", p->name); /* FIXME: This clock seems to be necessary but no-one
p->disable(p); * has asked for its activation. */
printk(" done\n"); if (clk == &tc2_ck // FIX: pm.c (SRAM), CCP, Camera
|| clk == &ck_dpll1out.clk // FIX: SoSSI, SSR
|| clk == &arm_gpio_ck // FIX: GPIO code for 1510
) {
printk(KERN_INFO "FIXME: Clock \"%s\" seems unused\n",
clk->name);
return;
} }
printk(KERN_INFO "Disabling unused clock \"%s\"... ", clk->name);
clk->disable(clk);
printk(" done\n");
return 0; return 0;
} }
late_initcall(omap1_late_clk_reset);
#else #else
#define omap1_early_clk_reset() {} #define omap1_clk_disable_unused NULL
#endif #endif
static struct clk_functions omap1_clk_functions = { static struct clk_functions omap1_clk_functions = {
...@@ -664,6 +642,7 @@ static struct clk_functions omap1_clk_functions = { ...@@ -664,6 +642,7 @@ static struct clk_functions omap1_clk_functions = {
.clk_disable = omap1_clk_disable, .clk_disable = omap1_clk_disable,
.clk_round_rate = omap1_clk_round_rate, .clk_round_rate = omap1_clk_round_rate,
.clk_set_rate = omap1_clk_set_rate, .clk_set_rate = omap1_clk_set_rate,
.clk_disable_unused = omap1_clk_disable_unused,
}; };
int __init omap1_clk_init(void) int __init omap1_clk_init(void)
...@@ -671,8 +650,13 @@ int __init omap1_clk_init(void) ...@@ -671,8 +650,13 @@ int __init omap1_clk_init(void)
struct clk ** clkp; struct clk ** clkp;
const struct omap_clock_config *info; const struct omap_clock_config *info;
int crystal_type = 0; /* Default 12 MHz */ int crystal_type = 0; /* Default 12 MHz */
u32 reg;
/* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */
reg = omap_readw(SOFT_REQ_REG) & (1 << 4);
omap_writew(reg, SOFT_REQ_REG);
omap_writew(0, SOFT_REQ_REG2);
omap1_early_clk_reset();
clk_init(&omap1_clk_functions); clk_init(&omap1_clk_functions);
/* By default all idlect1 clocks are allowed to idle */ /* By default all idlect1 clocks are allowed to idle */
......
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
static struct prcm_config *curr_prcm_set; static struct prcm_config *curr_prcm_set;
static u32 curr_perf_level = PRCM_FULL_SPEED; static u32 curr_perf_level = PRCM_FULL_SPEED;
static struct clk *vclk;
static struct clk *sclk;
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* Omap2 specific clock functions * Omap2 specific clock functions
...@@ -954,12 +956,29 @@ static int omap2_select_table_rate(struct clk * clk, unsigned long rate) ...@@ -954,12 +956,29 @@ static int omap2_select_table_rate(struct clk * clk, unsigned long rate)
* Omap2 clock reset and init functions * Omap2 clock reset and init functions
*-------------------------------------------------------------------------*/ *-------------------------------------------------------------------------*/
#ifdef CONFIG_OMAP_RESET_CLOCKS
static void __init omap2_clk_disable_unused(struct clk *clk)
{
u32 regval32;
regval32 = __raw_readl(clk->enable_reg);
if ((regval32 & (1 << clk->enable_bit)) == 0)
return;
printk(KERN_INFO "Disabling unused clock \"%s\"\n", clk->name);
_omap2_clk_disable(clk);
}
#else
#define omap2_clk_disable_unused NULL
#endif
static struct clk_functions omap2_clk_functions = { static struct clk_functions omap2_clk_functions = {
.clk_enable = omap2_clk_enable, .clk_enable = omap2_clk_enable,
.clk_disable = omap2_clk_disable, .clk_disable = omap2_clk_disable,
.clk_round_rate = omap2_clk_round_rate, .clk_round_rate = omap2_clk_round_rate,
.clk_set_rate = omap2_clk_set_rate, .clk_set_rate = omap2_clk_set_rate,
.clk_set_parent = omap2_clk_set_parent, .clk_set_parent = omap2_clk_set_parent,
.clk_disable_unused = omap2_clk_disable_unused,
}; };
static void __init omap2_get_crystal_rate(struct clk *osc, struct clk *sys) static void __init omap2_get_crystal_rate(struct clk *osc, struct clk *sys)
...@@ -985,27 +1004,19 @@ static void __init omap2_get_crystal_rate(struct clk *osc, struct clk *sys) ...@@ -985,27 +1004,19 @@ static void __init omap2_get_crystal_rate(struct clk *osc, struct clk *sys)
sys->rate = sclk; sys->rate = sclk;
} }
#ifdef CONFIG_OMAP_RESET_CLOCKS /*
static void __init omap2_disable_unused_clocks(void) * Set clocks for bypass mode for reboot to work.
*/
void omap2_clk_prepare_for_reboot(void)
{ {
struct clk *ck; u32 rate;
u32 regval32;
list_for_each_entry(ck, &clocks, node) {
if (ck->usecount > 0 || (ck->flags & ALWAYS_ENABLED) ||
ck->enable_reg == 0)
continue;
regval32 = __raw_readl(ck->enable_reg); if (vclk == NULL || sclk == NULL)
if ((regval32 & (1 << ck->enable_bit)) == 0) return;
continue;
printk(KERN_INFO "Disabling unused clock \"%s\"\n", ck->name); rate = clk_get_rate(sclk);
_omap2_clk_disable(ck); clk_set_rate(vclk, rate);
}
} }
late_initcall(omap2_disable_unused_clocks);
#endif
/* /*
* Switch the MPU rate if specified on cmdline. * Switch the MPU rate if specified on cmdline.
...@@ -1081,5 +1092,9 @@ int __init omap2_clk_init(void) ...@@ -1081,5 +1092,9 @@ int __init omap2_clk_init(void)
if (cpu_is_omap2430()) if (cpu_is_omap2430())
clk_enable(&sdrc_ick); clk_enable(&sdrc_ick);
/* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */
vclk = clk_get(NULL, "virt_prcm_set");
sclk = clk_get(NULL, "sys_ck");
return 0; return 0;
} }
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#include "prcm-regs.h" #include "prcm-regs.h"
extern void omap2_clk_prepare_for_reboot(void);
u32 omap_prcm_get_reset_sources(void) u32 omap_prcm_get_reset_sources(void)
{ {
return RM_RSTST_WKUP & 0x7f; return RM_RSTST_WKUP & 0x7f;
...@@ -29,12 +31,6 @@ EXPORT_SYMBOL(omap_prcm_get_reset_sources); ...@@ -29,12 +31,6 @@ EXPORT_SYMBOL(omap_prcm_get_reset_sources);
/* Resets clock rates and reboots the system. Only called from system.h */ /* Resets clock rates and reboots the system. Only called from system.h */
void omap_prcm_arch_reset(char mode) void omap_prcm_arch_reset(char mode)
{ {
u32 rate; omap2_clk_prepare_for_reboot();
struct clk *vclk, *sclk;
vclk = clk_get(NULL, "virt_prcm_set");
sclk = clk_get(NULL, "sys_ck");
rate = clk_get_rate(sclk);
clk_set_rate(vclk, rate); /* go to bypass for OMAP limitation */
RM_RSTCTRL_WKUP |= 2; RM_RSTCTRL_WKUP |= 2;
} }
...@@ -323,6 +323,31 @@ EXPORT_SYMBOL(clk_allow_idle); ...@@ -323,6 +323,31 @@ EXPORT_SYMBOL(clk_allow_idle);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
#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;
list_for_each_entry(ck, &clocks, node) {
if (ck->usecount > 0 || (ck->flags & ALWAYS_ENABLED) ||
ck->enable_reg == 0)
continue;
spin_lock_irqsave(&clockfw_lock, flags);
if (arch_clock->clk_disable_unused)
arch_clock->clk_disable_unused(ck);
spin_unlock_irqrestore(&clockfw_lock, flags);
}
return 0;
}
late_initcall(clk_disable_unused);
#endif
int __init clk_init(struct clk_functions * custom_clocks) int __init clk_init(struct clk_functions * custom_clocks)
{ {
if (!custom_clocks) { if (!custom_clocks) {
......
...@@ -2271,10 +2271,14 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) ...@@ -2271,10 +2271,14 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
touch_nmi_watchdog(); touch_nmi_watchdog();
if (oops_in_progress) { local_irq_save(flags);
locked = spin_trylock_irqsave(&up->port.lock, flags); if (up->port.sysrq) {
/* serial8250_handle_port() already took the lock */
locked = 0;
} else if (oops_in_progress) {
locked = spin_trylock(&up->port.lock);
} else } else
spin_lock_irqsave(&up->port.lock, flags); spin_lock(&up->port.lock);
/* /*
* First save the IER then disable the interrupts * First save the IER then disable the interrupts
...@@ -2296,7 +2300,8 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count) ...@@ -2296,7 +2300,8 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
serial_out(up, UART_IER, ier); serial_out(up, UART_IER, ier);
if (locked) if (locked)
spin_unlock_irqrestore(&up->port.lock, flags); spin_unlock(&up->port.lock);
local_irq_restore(flags);
} }
static int serial8250_console_setup(struct console *co, char *options) static int serial8250_console_setup(struct console *co, char *options)
......
...@@ -45,11 +45,10 @@ struct clk_functions { ...@@ -45,11 +45,10 @@ struct clk_functions {
struct clk * (*clk_get_parent)(struct clk *clk); struct clk * (*clk_get_parent)(struct clk *clk);
void (*clk_allow_idle)(struct clk *clk); void (*clk_allow_idle)(struct clk *clk);
void (*clk_deny_idle)(struct clk *clk); void (*clk_deny_idle)(struct clk *clk);
void (*clk_disable_unused)(struct clk *clk);
}; };
extern unsigned int mpurate; extern unsigned int mpurate;
extern struct list_head clocks;
extern spinlock_t clockfw_lock;
extern int clk_init(struct clk_functions * custom_clocks); extern int clk_init(struct clk_functions * custom_clocks);
extern int clk_register(struct clk *clk); extern int clk_register(struct clk *clk);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment