diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2006-09-27 19:57:54 +0100 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2006-09-27 19:57:54 +0100 |
commit | 2dc94310bd94d0906febea7d0f7c188da620c952 (patch) | |
tree | 6de4096f1887e2c00966177354b1c378e59bd632 /arch/arm | |
parent | c06015148fa9a3cc452ec7121b8c3f59f4a7d6ac (diff) | |
parent | fb60cf4ab52f3520c2119aa42f7d4ed8e7594eb6 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/tmlind/linux-omap-upstream into devel
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-omap1/clock.c | 107 | ||||
-rw-r--r-- | arch/arm/mach-omap1/clock.h | 14 | ||||
-rw-r--r-- | arch/arm/mach-omap1/mux.c | 11 | ||||
-rw-r--r-- | arch/arm/mach-omap2/board-apollon.c | 7 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock.c | 146 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock.h | 20 | ||||
-rw-r--r-- | arch/arm/mach-omap2/gpmc.c | 180 | ||||
-rw-r--r-- | arch/arm/mach-omap2/irq.c | 12 | ||||
-rw-r--r-- | arch/arm/mach-omap2/mux.c | 14 | ||||
-rw-r--r-- | arch/arm/mach-omap2/prcm.c | 10 | ||||
-rw-r--r-- | arch/arm/plat-omap/clock.c | 26 | ||||
-rw-r--r-- | arch/arm/plat-omap/devices.c | 20 | ||||
-rw-r--r-- | arch/arm/plat-omap/dma.c | 95 | ||||
-rw-r--r-- | arch/arm/plat-omap/dmtimer.c | 76 | ||||
-rw-r--r-- | arch/arm/plat-omap/gpio.c | 45 | ||||
-rw-r--r-- | arch/arm/plat-omap/mcbsp.c | 9 | ||||
-rw-r--r-- | arch/arm/plat-omap/pm.c | 670 | ||||
-rw-r--r-- | arch/arm/plat-omap/sram.c | 5 | ||||
-rw-r--r-- | arch/arm/plat-omap/timer32k.c | 38 |
19 files changed, 652 insertions, 853 deletions
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index f1958e882e8..638490e62d5 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -20,6 +20,7 @@ #include <linux/clk.h> #include <asm/io.h> +#include <asm/mach-types.h> #include <asm/arch/cpu.h> #include <asm/arch/usb.h> @@ -586,77 +587,53 @@ static int omap1_clk_set_rate(struct clk *clk, unsigned long rate) *-------------------------------------------------------------------------*/ #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; - /* USB_REQ_EN will be disabled later if necessary (usb_dc_ck) */ - regval32 = omap_readw(SOFT_REQ_REG) & (1 << 4); - omap_writew(regval32, SOFT_REQ_REG); - omap_writew(0, SOFT_REQ_REG2); - - list_for_each_entry(p, &clocks, node) { - 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; - } + /* Clocks in the DSP domain need api_ck. Just assume bootloader + * has not enabled any DSP clocks */ + if ((u32)clk->enable_reg == DSP_IDLECT2) { + printk(KERN_INFO "Skipping reset check for DSP domain " + "clock \"%s\"\n", clk->name); + return; + } - /* Is the clock already disabled? */ - if (p->flags & ENABLE_REG_32BIT) { - if (p->flags & VIRTUAL_IO_ADDRESS) - regval32 = __raw_readl(p->enable_reg); - else - regval32 = omap_readl(p->enable_reg); - } else { - if (p->flags & VIRTUAL_IO_ADDRESS) - regval32 = __raw_readw(p->enable_reg); + /* Is the clock already disabled? */ + if (clk->flags & ENABLE_REG_32BIT) { + if (clk->flags & VIRTUAL_IO_ADDRESS) + regval32 = __raw_readl(clk->enable_reg); else - regval32 = omap_readw(p->enable_reg); - } - - if ((regval32 & (1 << p->enable_bit)) == 0) - continue; + regval32 = omap_readl(clk->enable_reg); + } else { + if (clk->flags & VIRTUAL_IO_ADDRESS) + regval32 = __raw_readw(clk->enable_reg); + else + regval32 = omap_readw(clk->enable_reg); + } - /* FIXME: This clock seems to be necessary but no-one - * has asked for its activation. */ - 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; - } + if ((regval32 & (1 << clk->enable_bit)) == 0) + return; - printk(KERN_INFO "Disabling unused clock \"%s\"... ", p->name); - p->disable(p); - printk(" done\n"); + /* FIXME: This clock seems to be necessary but no-one + * has asked for its activation. */ + 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; } - return 0; + printk(KERN_INFO "Disabling unused clock \"%s\"... ", clk->name); + clk->disable(clk); + printk(" done\n"); } -late_initcall(omap1_late_clk_reset); #else -#define omap1_early_clk_reset() {} +#define omap1_clk_disable_unused NULL #endif static struct clk_functions omap1_clk_functions = { @@ -664,6 +641,7 @@ static struct clk_functions omap1_clk_functions = { .clk_disable = omap1_clk_disable, .clk_round_rate = omap1_clk_round_rate, .clk_set_rate = omap1_clk_set_rate, + .clk_disable_unused = omap1_clk_disable_unused, }; int __init omap1_clk_init(void) @@ -671,8 +649,13 @@ int __init omap1_clk_init(void) struct clk ** clkp; const struct omap_clock_config *info; 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); /* By default all idlect1 clocks are allowed to idle */ @@ -772,6 +755,12 @@ int __init omap1_clk_init(void) omap_writew(omap_readw(OMAP730_PCC_UPLD_CTRL) & ~0x1, OMAP730_PCC_UPLD_CTRL); #endif + /* Amstrad Delta wants BCLK high when inactive */ + if (machine_is_ams_delta()) + omap_writel(omap_readl(ULPD_CLOCK_CTRL) | + (1 << SDW_MCLK_INV_BIT), + ULPD_CLOCK_CTRL); + /* Turn off DSP and ARM_TIMXO. Make sure ARM_INTHCK is not divided */ /* (on 730, bit 13 must not be cleared) */ if (cpu_is_omap730()) diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h index b7c68819c4e..f7df00205c4 100644 --- a/arch/arm/mach-omap1/clock.h +++ b/arch/arm/mach-omap1/clock.h @@ -89,6 +89,7 @@ struct arm_idlect1_clk { #define EN_DSPTIMCK 5 /* Various register defines for clock controls scattered around OMAP chip */ +#define SDW_MCLK_INV_BIT 2 /* In ULPD_CLKC_CTRL */ #define USB_MCLK_EN_BIT 4 /* In ULPD_CLKC_CTRL */ #define USB_HOST_HHC_UHOST_EN 9 /* In MOD_CONF_CTRL_0 */ #define SWD_ULPD_PLL_CLK_REQ 1 /* In SWD_CLK_DIV_CTRL_SEL */ @@ -741,6 +742,18 @@ static struct clk i2c_fck = { .disable = &omap1_clk_disable_generic, }; +static struct clk i2c_ick = { + .name = "i2c_ick", + .id = 1, + .flags = CLOCK_IN_OMAP16XX | + VIRTUAL_CLOCK | CLOCK_NO_IDLE_PARENT | + ALWAYS_ENABLED, + .parent = &armper_ck.clk, + .recalc = &followparent_recalc, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, +}; + static struct clk * onchip_clks[] = { /* non-ULPD clocks */ &ck_ref, @@ -790,6 +803,7 @@ static struct clk * onchip_clks[] = { /* Virtual clocks */ &virtual_ck_mpu, &i2c_fck, + &i2c_ick, }; #endif diff --git a/arch/arm/mach-omap1/mux.c b/arch/arm/mach-omap1/mux.c index fa74ef7af15..5432335bc49 100644 --- a/arch/arm/mach-omap1/mux.c +++ b/arch/arm/mach-omap1/mux.c @@ -199,6 +199,17 @@ MUX_CFG("N14_1610_UWIRE_CS0", 8, 9, 1, 1, 21, 0, 1, 1, 1) MUX_CFG("P15_1610_UWIRE_CS3", 8, 12, 1, 1, 22, 0, 1, 1, 1) MUX_CFG("N15_1610_UWIRE_CS1", 7, 18, 2, 1, 14, 0, NA, 0, 1) +/* OMAP-1610 SPI */ +MUX_CFG("U19_1610_SPIF_SCK", 7, 21, 6, 1, 15, 0, 1, 1, 1) +MUX_CFG("U18_1610_SPIF_DIN", 8, 0, 6, 1, 18, 1, 1, 0, 1) +MUX_CFG("P20_1610_SPIF_DIN", 6, 27, 4, 1, 7, 1, 1, 0, 1) +MUX_CFG("W21_1610_SPIF_DOUT", 8, 3, 6, 1, 19, 0, 1, 0, 1) +MUX_CFG("R18_1610_SPIF_DOUT", 7, 9, 3, 1, 11, 0, 1, 0, 1) +MUX_CFG("N14_1610_SPIF_CS0", 8, 9, 6, 1, 21, 0, 1, 1, 1) +MUX_CFG("N15_1610_SPIF_CS1", 7, 18, 6, 1, 14, 0, 1, 1, 1) +MUX_CFG("T19_1610_SPIF_CS2", 7, 15, 4, 1, 13, 0, 1, 1, 1) +MUX_CFG("P15_1610_SPIF_CS3", 8, 12, 3, 1, 22, 0, 1, 1, 1) + /* OMAP-1610 Flash */ MUX_CFG("L3_1610_FLASH_CS2B_OE",10, 6, 1, NA, 0, 0, NA, 0, 1) MUX_CFG("M8_1610_FLASH_CS2B_WE",10, 3, 1, NA, 0, 0, NA, 0, 1) diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c index 7993b7bae2b..2db6b732b08 100644 --- a/arch/arm/mach-omap2/board-apollon.c +++ b/arch/arm/mach-omap2/board-apollon.c @@ -166,8 +166,8 @@ static struct omap_uart_config apollon_uart_config __initdata = { static struct omap_mmc_config apollon_mmc_config __initdata = { .mmc [0] = { - .enabled = 0, - .wire4 = 0, + .enabled = 1, + .wire4 = 1, .wp_pin = -1, .power_pin = -1, .switch_pin = -1, @@ -257,6 +257,9 @@ static void __init omap_apollon_init(void) /* REVISIT: where's the correct place */ omap_cfg_reg(W19_24XX_SYS_NIRQ); + /* Use Interal loop-back in MMC/SDIO Module Input Clock selection */ + CONTROL_DEVCONF |= (1 << 24); + /* * Make sure the serial ports are muxed on at this point. * You have to mux them off in device drivers later on diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index d1b648a4efb..0de201c3d50 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -32,10 +32,14 @@ #include "memory.h" #include "clock.h" +#undef DEBUG + //#define DOWN_VARIABLE_DPLL 1 /* Experimental */ static struct prcm_config *curr_prcm_set; static u32 curr_perf_level = PRCM_FULL_SPEED; +static struct clk *vclk; +static struct clk *sclk; /*------------------------------------------------------------------------- * Omap2 specific clock functions @@ -79,6 +83,14 @@ static void omap2_propagate_rate(struct clk * clk) propagate_rate(clk); } +static void omap2_set_osc_ck(int enable) +{ + if (enable) + PRCM_CLKSRC_CTRL &= ~(0x3 << 3); + else + PRCM_CLKSRC_CTRL |= 0x3 << 3; +} + /* Enable an APLL if off */ static void omap2_clk_fixed_enable(struct clk *clk) { @@ -101,12 +113,54 @@ static void omap2_clk_fixed_enable(struct clk *clk) else if (clk == &apll54_ck) cval = (1 << 6); - while (!CM_IDLEST_CKGEN & cval) { /* Wait for lock */ + while (!(CM_IDLEST_CKGEN & cval)) { /* Wait for lock */ ++i; udelay(1); - if (i == 100000) + if (i == 100000) { + printk(KERN_ERR "Clock %s didn't lock\n", clk->name); + break; + } + } +} + +static void omap2_clk_wait_ready(struct clk *clk) +{ + unsigned long reg, other_reg, st_reg; + u32 bit; + int i; + + reg = (unsigned long) clk->enable_reg; + if (reg == (unsigned long) &CM_FCLKEN1_CORE || + reg == (unsigned long) &CM_FCLKEN2_CORE) + other_reg = (reg & ~0xf0) | 0x10; + else if (reg == (unsigned long) &CM_ICLKEN1_CORE || + reg == (unsigned long) &CM_ICLKEN2_CORE) + other_reg = (reg & ~0xf0) | 0x00; + else + return; + + /* No check for DSS or cam clocks */ + if ((reg & 0x0f) == 0) { + if (clk->enable_bit <= 1 || clk->enable_bit == 31) + return; + } + + /* Check if both functional and interface clocks + * are running. */ + bit = 1 << clk->enable_bit; + if (!(__raw_readl(other_reg) & bit)) + return; + st_reg = (other_reg & ~0xf0) | 0x20; + i = 0; + while (!(__raw_readl(st_reg) & bit)) { + i++; + if (i == 100000) { + printk(KERN_ERR "Timeout enabling clock %s\n", clk->name); break; + } } + if (i) + pr_debug("Clock %s stable after %d loops\n", clk->name, i); } /* Enables clock without considering parent dependencies or use count @@ -119,6 +173,11 @@ static int _omap2_clk_enable(struct clk * clk) if (clk->flags & ALWAYS_ENABLED) return 0; + if (unlikely(clk == &osc_ck)) { + omap2_set_osc_ck(1); + return 0; + } + if (unlikely(clk->enable_reg == 0)) { printk(KERN_ERR "clock.c: Enable for %s without enable code\n", clk->name); @@ -133,6 +192,9 @@ static int _omap2_clk_enable(struct clk * clk) regval32 = __raw_readl(clk->enable_reg); regval32 |= (1 << clk->enable_bit); __raw_writel(regval32, clk->enable_reg); + wmb(); + + omap2_clk_wait_ready(clk); return 0; } @@ -155,6 +217,11 @@ static void _omap2_clk_disable(struct clk *clk) { u32 regval32; + if (unlikely(clk == &osc_ck)) { + omap2_set_osc_ck(0); + return; + } + if (clk->enable_reg == 0) return; @@ -166,6 +233,7 @@ static void _omap2_clk_disable(struct clk *clk) regval32 = __raw_readl(clk->enable_reg); regval32 &= ~(1 << clk->enable_bit); __raw_writel(regval32, clk->enable_reg); + wmb(); } static int omap2_clk_enable(struct clk *clk) @@ -695,12 +763,14 @@ static int omap2_clk_set_rate(struct clk *clk, unsigned long rate) reg_val = __raw_readl(reg); reg_val &= ~(field_mask << div_off); reg_val |= (field_val << div_off); - __raw_writel(reg_val, reg); + wmb(); clk->rate = clk->parent->rate / field_val; - if (clk->flags & DELAYED_APP) + if (clk->flags & DELAYED_APP) { __raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL); + wmb(); + } ret = 0; } else if (clk->set_rate != 0) ret = clk->set_rate(clk, rate); @@ -836,10 +906,12 @@ static int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) reg_val = __raw_readl(reg) & ~(field_mask << src_off); reg_val |= (field_val << src_off); __raw_writel(reg_val, reg); + wmb(); - if (clk->flags & DELAYED_APP) + if (clk->flags & DELAYED_APP) { __raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL); - + wmb(); + } if (clk->usecount > 0) _omap2_clk_enable(clk); @@ -953,12 +1025,29 @@ static int omap2_select_table_rate(struct clk * clk, unsigned long rate) * 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 = { .clk_enable = omap2_clk_enable, .clk_disable = omap2_clk_disable, .clk_round_rate = omap2_clk_round_rate, .clk_set_rate = omap2_clk_set_rate, .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) @@ -984,27 +1073,19 @@ static void __init omap2_get_crystal_rate(struct clk *osc, struct clk *sys) 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 regval32; + u32 rate; - 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 ((regval32 & (1 << ck->enable_bit)) == 0) - continue; + if (vclk == NULL || sclk == NULL) + return; - printk(KERN_INFO "Disabling unused clock \"%s\"\n", ck->name); - _omap2_clk_disable(ck); - } + rate = clk_get_rate(sclk); + clk_set_rate(vclk, rate); } -late_initcall(omap2_disable_unused_clocks); -#endif /* * Switch the MPU rate if specified on cmdline. @@ -1077,8 +1158,27 @@ int __init omap2_clk_init(void) */ clk_enable(&sync_32k_ick); clk_enable(&omapctrl_ick); + + /* Force the APLLs active during bootup to avoid disabling and + * enabling them unnecessarily. */ + clk_enable(&apll96_ck); + clk_enable(&apll54_ck); + if (cpu_is_omap2430()) 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; +} + +static int __init omap2_disable_aplls(void) +{ + clk_disable(&apll96_ck); + clk_disable(&apll54_ck); + return 0; } +late_initcall(omap2_disable_aplls); diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 2781dfbc516..8816f5a33a2 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -560,7 +560,7 @@ static struct clk osc_ck = { /* (*12, *13, 19.2, *26, 38.4)MHz */ .name = "osc_ck", .rate = 26000000, /* fixed up in clock init */ .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | - RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES, + RATE_FIXED | RATE_PROPAGATES, }; /* With out modem likely 12MHz, with modem likely 13MHz */ @@ -1368,7 +1368,8 @@ static struct clk mcbsp5_fck = { }; static struct clk mcspi1_ick = { - .name = "mcspi1_ick", + .name = "mcspi_ick", + .id = 1, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, @@ -1377,7 +1378,8 @@ static struct clk mcspi1_ick = { }; static struct clk mcspi1_fck = { - .name = "mcspi1_fck", + .name = "mcspi_fck", + .id = 1, .parent = &func_48m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, @@ -1386,7 +1388,8 @@ static struct clk mcspi1_fck = { }; static struct clk mcspi2_ick = { - .name = "mcspi2_ick", + .name = "mcspi_ick", + .id = 2, .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, @@ -1395,7 +1398,8 @@ static struct clk mcspi2_ick = { }; static struct clk mcspi2_fck = { - .name = "mcspi2_fck", + .name = "mcspi_fck", + .id = 2, .parent = &func_48m_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, @@ -1404,7 +1408,8 @@ static struct clk mcspi2_fck = { }; static struct clk mcspi3_ick = { - .name = "mcspi3_ick", + .name = "mcspi_ick", + .id = 3, .parent = &l4_ck, .flags = CLOCK_IN_OMAP243X, .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE, @@ -1413,7 +1418,8 @@ static struct clk mcspi3_ick = { }; static struct clk mcspi3_fck = { - .name = "mcspi3_fck", + .name = "mcspi_fck", + .id = 3, .parent = &func_48m_ck, .flags = CLOCK_IN_OMAP243X, .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE, diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index c7a48f921fe..f4f04d87df3 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -13,6 +13,8 @@ #include <linux/init.h> #include <linux/err.h> #include <linux/clk.h> +#include <linux/ioport.h> +#include <linux/spinlock.h> #include <asm/io.h> #include <asm/arch/gpmc.h> @@ -41,6 +43,19 @@ #define GPMC_CS0 0x60 #define GPMC_CS_SIZE 0x30 +#define GPMC_CS_NUM 8 +#define GPMC_MEM_START 0x00000000 +#define GPMC_MEM_END 0x3FFFFFFF +#define BOOT_ROM_SPACE 0x100000 /* 1MB */ + +#define GPMC_CHUNK_SHIFT 24 /* 16 MB */ +#define GPMC_SECTION_SHIFT 28 /* 128 MB */ + +static struct resource gpmc_mem_root; +static struct resource gpmc_cs_mem[GPMC_CS_NUM]; +static spinlock_t gpmc_mem_lock = SPIN_LOCK_UNLOCKED; +static unsigned gpmc_cs_map; + static void __iomem *gpmc_base = (void __iomem *) IO_ADDRESS(GPMC_BASE); static void __iomem *gpmc_cs_base = @@ -187,9 +202,168 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t) return 0; } -unsigned long gpmc_cs_get_base_addr(int cs) +static void gpmc_cs_enable_mem(int cs, u32 base, u32 size) +{ + u32 l; + u32 mask; + + mask = (1 << GPMC_SECTION_SHIFT) - size; + l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7); + l &= ~0x3f; + l = (base >> GPMC_CHUNK_SHIFT) & 0x3f; + l &= ~(0x0f << 8); + l |= ((mask >> GPMC_CHUNK_SHIFT) & 0x0f) << 8; + l |= 1 << 6; /* CSVALID */ + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l); +} + +static void gpmc_cs_disable_mem(int cs) +{ + u32 l; + + l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7); + l &= ~(1 << 6); /* CSVALID */ + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l); +} + +static void gpmc_cs_get_memconf(int cs, u32 *base, u32 *size) +{ + u32 l; + u32 mask; + + l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7); + *base = (l & 0x3f) << GPMC_CHUNK_SHIFT; + mask = (l >> 8) & 0x0f; + *size = (1 << GPMC_SECTION_SHIFT) - (mask << GPMC_CHUNK_SHIFT); +} + +static int gpmc_cs_mem_enabled(int cs) +{ + u32 l; + + l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7); + return l & (1 << 6); +} + +static void gpmc_cs_set_reserved(int cs, int reserved) { - return (gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7) & 0x1f) << 24; + gpmc_cs_map &= ~(1 << cs); + gpmc_cs_map |= (reserved ? 1 : 0) << cs; +} + +static int gpmc_cs_reserved(int cs) +{ + return gpmc_cs_map & (1 << cs); +} + +static unsigned long gpmc_mem_align(unsigned long size) +{ + int order; + + size = (size - 1) >> (GPMC_CHUNK_SHIFT - 1); + order = GPMC_CHUNK_SHIFT - 1; + do { + size >>= 1; + order++; + } while (size); + size = 1 << order; + return size; +} + +static int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size) +{ + struct resource *res = &gpmc_cs_mem[cs]; + int r; + + size = gpmc_mem_align(size); + spin_lock(&gpmc_mem_lock); + res->start = base; + res->end = base + size - 1; + r = request_resource(&gpmc_mem_root, res); + spin_unlock(&gpmc_mem_lock); + + return r; +} + +int gpmc_cs_request(int cs, unsigned long size, unsigned long *base) +{ + struct resource *res = &gpmc_cs_mem[cs]; + int r = -1; + + if (cs > GPMC_CS_NUM) + return -ENODEV; + + size = gpmc_mem_align(size); + if (size > (1 << GPMC_SECTION_SHIFT)) + return -ENOMEM; + + spin_lock(&gpmc_mem_lock); + if (gpmc_cs_reserved(cs)) { + r = -EBUSY; + goto out; + } + if (gpmc_cs_mem_enabled(cs)) + r = adjust_resource(res, res->start & ~(size - 1), size); + if (r < 0) + r = allocate_resource(&gpmc_mem_root, res, size, 0, ~0, + size, NULL, NULL); + if (r < 0) + goto out; + + gpmc_cs_enable_mem(cs, res->start, res->end - res->start + 1); + *base = res->start; + gpmc_cs_set_reserved(cs, 1); +out: + spin_unlock(&gpmc_mem_lock); + return r; +} + +void gpmc_cs_free(int cs) +{ + spin_lock(&gpmc_mem_lock); + if (cs >= GPMC_CS_NUM || !gpmc_cs_reserved(cs)) { + printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs); + BUG(); + spin_unlock(&gpmc_mem_lock); + return; + } + gpmc_cs_disable_mem(cs); + release_resource(&gpmc_cs_mem[cs]); + gpmc_cs_set_reserved(cs, 0); + spin_unlock(&gpmc_mem_lock); +} + +void __init gpmc_mem_init(void) +{ + int cs; + unsigned long boot_rom_space = 0; + + if (cpu_is_omap242x()) { + u32 l; + l = omap_readl(OMAP242X_CONTROL_STATUS); + /* In case of internal boot the 1st MB is redirected to the + * boot ROM memory space. + */ + if (l & (1 << 3)) + boot_rom_space = BOOT_ROM_SPACE; + } else + /* We assume internal boot if the mode can't be + * determined. + */ + boot_rom_space = BOOT_ROM_SPACE; + gpmc_mem_root.start = GPMC_MEM_START + boot_rom_space; + gpmc_mem_root.end = GPMC_MEM_END; + + /* Reserve all regions that has been set up by bootloader */ + for (cs = 0; cs < GPMC_CS_NUM; cs++) { + u32 base, size; + + if (!gpmc_cs_mem_enabled(cs)) + continue; + gpmc_cs_get_memconf(cs, &base, &size); + if (gpmc_cs_insert_mem(cs, base, size) < 0) + BUG(); + } } void __init gpmc_init(void) @@ -206,4 +380,6 @@ void __init gpmc_init(void) l &= 0x03 << 3; l |= (0x02 << 3) | (1 << 0); gpmc_write_reg(GPMC_SYSCONFIG, l); + + gpmc_mem_init(); } diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c index dfc3b35cc1f..1ed2fff4691 100644 --- a/arch/arm/mach-omap2/irq.c +++ b/arch/arm/mach-omap2/irq.c @@ -41,18 +41,6 @@ static struct omap_irq_bank { .nr_irqs = 96, }, { /* XXX: DSP INTC */ - -#if 0 - /* - * Commented out for now until we fix the IVA clocking - */ -#ifdef CONFIG_ARCH_OMAP2420 - }, { - /* IVA INTC (2420 only) */ - .base_reg = OMAP24XX_IVA_INTC_BASE, - .nr_irqs = 16, /* Actually 32, but only 16 are used */ -#endif -#endif } }; diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c index 60ef084faff..f538d0fdb13 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c @@ -104,6 +104,20 @@ MUX_CFG_24XX("P20_24XX_TSC_IRQ", 0x108, 0, 0, 0, 1) MUX_CFG_24XX("K15_24XX_UART3_TX", 0x118, 0, 0, 0, 1) MUX_CFG_24XX("K14_24XX_UART3_RX", 0x119, 0, 0, 0, 1) +/* MMC/SDIO */ +MUX_CFG_24XX("G19_24XX_MMC_CLKO", 0x0f3, 0, 0, 0, 1) +MUX_CFG_24XX("H18_24XX_MMC_CMD", 0x0f4, 0, 0, 0, 1) +MUX_CFG_24XX("F20_24XX_MMC_DAT0", 0x0f5, 0, 0, 0, 1) +MUX_CFG_24XX("H14_24XX_MMC_DAT1", 0x0f6, 0, 0, 0, 1) +MUX_CFG_24XX("E19_24XX_MMC_DAT2", 0x0f7, 0, 0, 0, 1) +MUX_CFG_24XX("D19_24XX_MMC_DAT3", 0x0f8, 0, 0, 0, 1) +MUX_CFG_24XX("F19_24XX_MMC_DAT_DIR0", 0x0f9, 0, 0, 0, 1) +MUX_CFG_24XX("E20_24XX_MMC_DAT_DIR1", 0x0fa, 0, 0, 0, 1) +MUX_CFG_24XX("F18_24XX_MMC_DAT_DIR2", 0x0fb, 0, 0, 0, 1) +MUX_CFG_24XX("E18_24XX_MMC_DAT_DIR3", 0x0fc, 0, 0, 0, 1) +MUX_CFG_24XX("G18_24XX_MMC_CMD_DIR", 0x0fd, 0, 0, 0, 1) +MUX_CFG_24XX("H15_24XX_MMC_CLKI", 0x0fe, 0, 0, 0, 1) + /* Keypad GPIO*/ MUX_CFG_24XX("T19_24XX_KBR0", 0x106, 3, 1, 1, 1) MUX_CFG_24XX("R19_24XX_KBR1", 0x107, 3, 1, 1, 1) diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c index c2bf57ef682..90f530540c6 100644 --- a/arch/arm/mach-omap2/prcm.c +++ b/arch/arm/mach-omap2/prcm.c @@ -19,6 +19,8 @@ #include "prcm-regs.h" +extern void omap2_clk_prepare_for_reboot(void); + u32 omap_prcm_get_reset_sources(void) { return RM_RSTST_WKUP & 0x7f; @@ -28,12 +30,6 @@ EXPORT_SYMBOL(omap_prcm_get_reset_sources); /* Resets clock rates and reboots the system. Only called from system.h */ void omap_prcm_arch_reset(char mode) { - u32 rate; - 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 */ + omap2_clk_prepare_for_reboot(); RM_RSTCTRL_WKUP |= 2; } diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 7f45c7c3e67..f1179ad4be1 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -100,6 +100,7 @@ void clk_disable(struct clk *clk) return; spin_lock_irqsave(&clockfw_lock, flags); + BUG_ON(clk->usecount == 0); if (arch_clock->clk_disable) arch_clock->clk_disable(clk); spin_unlock_irqrestore(&clockfw_lock, flags); @@ -322,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) { if (!custom_clocks) { diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index 1812f237d12..dbc3f44e07a 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -148,7 +148,7 @@ static inline void omap_init_kp(void) {} #ifdef CONFIG_ARCH_OMAP24XX #define OMAP_MMC1_BASE 0x4809c000 -#define OMAP_MMC1_INT 83 +#define OMAP_MMC1_INT INT_24XX_MMC_IRQ #else #define OMAP_MMC1_BASE 0xfffb7800 #define OMAP_MMC1_INT INT_MMC @@ -225,7 +225,14 @@ static void __init omap_init_mmc(void) /* block 1 is always available and has just one pinout option */ mmc = &mmc_conf->mmc[0]; if (mmc->enabled) { - if (!cpu_is_omap24xx()) { + if (cpu_is_omap24xx()) { + omap_cfg_reg(H18_24XX_MMC_CMD); + omap_cfg_reg(H15_24XX_MMC_CLKI); + omap_cfg_reg(G19_24XX_MMC_CLKO); + omap_cfg_reg(F20_24XX_MMC_DAT0); + omap_cfg_reg(F19_24XX_MMC_DAT_DIR0); + omap_cfg_reg(G18_24XX_MMC_CMD_DIR); + } else { omap_cfg_reg(MMC_CMD); omap_cfg_reg(MMC_CLK); omap_cfg_reg(MMC_DAT0); @@ -236,7 +243,14 @@ static void __init omap_init_mmc(void) } } if (mmc->wire4) { - if (!cpu_is_omap24xx()) { + if (cpu_is_omap24xx()) { + omap_cfg_reg(H14_24XX_MMC_DAT1); + omap_cfg_reg(E19_24XX_MMC_DAT2); + omap_cfg_reg(D19_24XX_MMC_DAT3); + omap_cfg_reg(E20_24XX_MMC_DAT_DIR1); + omap_cfg_reg(F18_24XX_MMC_DAT_DIR2); + omap_cfg_reg(E18_24XX_MMC_DAT_DIR3); + } else { omap_cfg_reg(MMC_DAT1); /* NOTE: DAT2 can be on W10 (here) or M15 */ if (!mmc->nomux) diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 9eddc950714..1bbb431843c 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -119,32 +119,41 @@ static void clear_lch_regs(int lch) omap_writew(0, lch_base + i); } -void omap_set_dma_priority(int dst_port, int priority) +void omap_set_dma_priority(int lch, int dst_port, int priority) { unsigned long reg; u32 l; - switch (dst_port) { - case OMAP_DMA_PORT_OCP_T1: /* FFFECC00 */ - reg = OMAP_TC_OCPT1_PRIOR; - break; - case OMAP_DMA_PORT_OCP_T2: /* FFFECCD0 */ - reg = OMAP_TC_OCPT2_PRIOR; - break; - case OMAP_DMA_PORT_EMIFF: /* FFFECC08 */ - reg = OMAP_TC_EMIFF_PRIOR; - break; - case OMAP_DMA_PORT_EMIFS: /* FFFECC04 */ - reg = OMAP_TC_EMIFS_PRIOR; - break; - default: - BUG(); - return; + if (cpu_class_is_omap1()) { + switch (dst_port) { + case OMAP_DMA_PORT_OCP_T1: /* FFFECC00 */ + reg = OMAP_TC_OCPT1_PRIOR; + break; + case OMAP_DMA_PORT_OCP_T2: /* FFFECCD0 */ + reg = OMAP_TC_OCPT2_PRIOR; + break; + case OMAP_DMA_PORT_EMIFF: /* FFFECC08 */ + reg = OMAP_TC_EMIFF_PRIOR; + break; + case OMAP_DMA_PORT_EMIFS: /* FFFECC04 */ + reg = OMAP_TC_EMIFS_PRIOR; + break; + default: + BUG(); + return; + } + l = omap_readl(reg); + l &= ~(0xf << 8); + l |= (priority & 0xf) << 8; + omap_writel(l, reg); + } + + if (cpu_is_omap24xx()) { + if (priority) + OMAP_DMA_CCR_REG(lch) |= (1 << 6); + else + OMAP_DMA_CCR_REG(lch) &= ~(1 << 6); } - l = omap_readl(reg); - l &= ~(0xf << 8); - l |= (priority & 0xf) << 8; - omap_writel(l, reg); } void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, @@ -234,6 +243,14 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) OMAP1_DMA_LCH_CTRL_REG(lch) = w; } +void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode) +{ + if (cpu_is_omap24xx()) { + OMAP_DMA_CSDP_REG(lch) &= ~(0x3 << 16); + OMAP_DMA_CSDP_REG(lch) |= (mode << 16); + } +} + /* Note that src_port is only for omap1 */ void omap_set_dma_src_params(int lch, int src_port, int src_amode, unsigned long src_start, @@ -698,6 +715,32 @@ void omap_stop_dma(int lch) } /* + * Allows changing the DMA callback function or data. This may be needed if + * the driver shares a single DMA channel for multiple dma triggers. + */ +int omap_set_dma_callback(int lch, + void (* callback)(int lch, u16 ch_status, void *data), + void *data) +{ + unsigned long flags; + + if (lch < 0) + return -ENODEV; + + spin_lock_irqsave(&dma_chan_lock, flags); + if (dma_chan[lch].dev_id == -1) { + printk(KERN_ERR "DMA callback for not set for free channel\n"); + spin_unlock_irqrestore(&dma_chan_lock, flags); + return -EINVAL; + } + dma_chan[lch].callback = callback; + dma_chan[lch].data = data; + spin_unlock_irqrestore(&dma_chan_lock, flags); + + return 0; +} + +/* * Returns current physical source address for the given DMA channel. * If the channel is running the caller must disable interrupts prior calling * this function and process the returned value before re-enabling interrupt to @@ -1339,6 +1382,14 @@ static int __init omap_init_dma(void) dma_chan_count = 16; } else dma_chan_count = 9; + if (cpu_is_omap16xx()) { + u16 w; + + /* this would prevent OMAP sleep */ + w = omap_readw(OMAP1610_DMA_LCD_CTRL); + w &= ~(1 << 8); + omap_writew(w, OMAP1610_DMA_LCD_CTRL); + } } else if (cpu_is_omap24xx()) { u8 revision = omap_readb(OMAP_DMA4_REVISION); printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n", @@ -1414,11 +1465,13 @@ EXPORT_SYMBOL(omap_request_dma); EXPORT_SYMBOL(omap_free_dma); EXPORT_SYMBOL(omap_start_dma); EXPORT_SYMBOL(omap_stop_dma); +EXPORT_SYMBOL(omap_set_dma_callback); EXPORT_SYMBOL(omap_enable_dma_irq); EXPORT_SYMBOL(omap_disable_dma_irq); EXPORT_SYMBOL(omap_set_dma_transfer_params); EXPORT_SYMBOL(omap_set_dma_color_mode); +EXPORT_SYMBOL(omap_set_dma_write_mode); EXPORT_SYMBOL(omap_set_dma_src_params); EXPORT_SYMBOL(omap_set_dma_src_index); diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 50524436de6..bcbb8d7392b 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -75,10 +75,14 @@ struct omap_dm_timer { #endif void __iomem *io_base; unsigned reserved:1; + unsigned enabled:1; }; #ifdef CONFIG_ARCH_OMAP1 +#define omap_dm_clk_enable(x) +#define omap_dm_clk_disable(x) + static struct omap_dm_timer dm_timers[] = { { .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 }, { .phys_base = 0xfffb1c00, .irq = INT_1610_GPTIMER2 }, @@ -92,6 +96,9 @@ static struct omap_dm_timer dm_timers[] = { #elif defined(CONFIG_ARCH_OMAP2) +#define omap_dm_clk_enable(x) clk_enable(x) +#define omap_dm_clk_disable(x) clk_disable(x) + static struct omap_dm_timer dm_timers[] = { { .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 }, { .phys_base = 0x4802a000, .irq = INT_24XX_GPTIMER2 }, @@ -154,24 +161,28 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer) { u32 l; - if (timer != &dm_timers[0]) { + if (!cpu_class_is_omap2() || timer != &dm_timers[0]) { omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06); omap_dm_timer_wait_for_reset(timer); } - omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_SYS_CLK); + omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ); /* Set to smart-idle mode */ l = omap_dm_timer_read_reg(timer, OMAP_TIMER_OCP_CFG_REG); l |= 0x02 << 3; + + if (cpu_class_is_omap2() && timer == &dm_timers[0]) { + /* Enable wake-up only for GPT1 on OMAP2 CPUs*/ + l |= 1 << 2; + /* Non-posted mode */ + omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0); + } omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l); } static void omap_dm_timer_prepare(struct omap_dm_timer *timer) { -#ifdef CONFIG_ARCH_OMAP2 - clk_enable(timer->iclk); - clk_enable(timer->fclk); -#endif + omap_dm_timer_enable(timer); omap_dm_timer_reset(timer); } @@ -223,15 +234,36 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id) void omap_dm_timer_free(struct omap_dm_timer *timer) { + omap_dm_timer_enable(timer); omap_dm_timer_reset(timer); -#ifdef CONFIG_ARCH_OMAP2 - clk_disable(timer->iclk); - clk_disable(timer->fclk); -#endif + omap_dm_timer_disable(timer); + WARN_ON(!timer->reserved); timer->reserved = 0; } +void omap_dm_timer_enable(struct omap_dm_timer *timer) +{ + if (timer->enabled) + return; + + omap_dm_clk_enable(timer->fclk); + omap_dm_clk_enable(timer->iclk); + + timer->enabled = 1; +} + +void omap_dm_timer_disable(struct omap_dm_timer *timer) +{ + if (!timer->enabled) + return; + + omap_dm_clk_disable(timer->iclk); + omap_dm_clk_disable(timer->fclk); + + timer->enabled = 0; +} + int omap_dm_timer_get_irq(struct omap_dm_timer *timer) { return timer->irq; @@ -276,7 +308,7 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer) { - return timer->fclk; + return timer->fclk; } __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) @@ -406,11 +438,16 @@ void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value) { omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value); + omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, value); } unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) { - return omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG); + unsigned int l; + + l = omap_dm_timer_read_reg(timer, OMAP_TIMER_STAT_REG); + + return l; } void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) @@ -420,12 +457,16 @@ void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) { - return omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG); + unsigned int l; + + l = omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG); + + return l; } void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value) { - return omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value); + omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value); } int omap_dm_timers_active(void) @@ -436,9 +477,14 @@ int omap_dm_timers_active(void) struct omap_dm_timer *timer; timer = &dm_timers[i]; + + if (!timer->enabled) + continue; + if (omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG) & - OMAP_TIMER_CTRL_ST) + OMAP_TIMER_CTRL_ST) { return 1; + } } return 0; } diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index cd7f973fb28..f55f99ae58a 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -94,6 +94,8 @@ #define OMAP24XX_GPIO_SYSCONFIG 0x0010 #define OMAP24XX_GPIO_SYSSTATUS 0x0014 #define OMAP24XX_GPIO_IRQSTATUS1 0x0018 +#define OMAP24XX_GPIO_IRQSTATUS2 0x0028 +#define OMAP24XX_GPIO_IRQENABLE2 0x002c #define OMAP24XX_GPIO_IRQENABLE1 0x001c #define OMAP24XX_GPIO_CTRL 0x0030 #define OMAP24XX_GPIO_OE 0x0034 @@ -110,8 +112,6 @@ #define OMAP24XX_GPIO_CLEARDATAOUT 0x0090 #define OMAP24XX_GPIO_SETDATAOUT 0x0094 -#define OMAP_MPUIO_MASK (~OMAP_MAX_GPIO_LINES & 0xff) - struct gpio_bank { void __iomem *base; u16 irq; @@ -216,11 +216,13 @@ static inline int gpio_valid(int gpio) { if (gpio < 0) return -1; +#ifndef CONFIG_ARCH_OMAP24XX if (OMAP_GPIO_IS_MPUIO(gpio)) { - if ((gpio & OMAP_MPUIO_MASK) > 16) + if (gpio >= OMAP_MAX_GPIO_LINES + 16) return -1; return 0; } +#endif #ifdef CONFIG_ARCH_OMAP15XX if (cpu_is_omap15xx() && gpio < 16) return 0; @@ -529,6 +531,10 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) return; } __raw_writel(gpio_mask, reg); + + /* Workaround for clearing DSP GPIO interrupts to allow retention */ + if (cpu_is_omap2420()) + __raw_writel(gpio_mask, bank->base + OMAP24XX_GPIO_IRQSTATUS2); } static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio) @@ -662,6 +668,14 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable) } } +static void _reset_gpio(struct gpio_bank *bank, int gpio) +{ + _set_gpio_direction(bank, get_gpio_index(gpio), 1); + _set_gpio_irqenable(bank, gpio, 0); + _clear_gpio_irqstatus(bank, gpio); + _set_gpio_triggering(bank, get_gpio_index(gpio), IRQT_NOEDGE); +} + /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */ static int gpio_wake_enable(unsigned int irq, unsigned int enable) { @@ -672,9 +686,7 @@ static int gpio_wake_enable(unsigned int irq, unsigned int enable) if (check_gpio(gpio) < 0) return -ENODEV; bank = get_gpio_bank(gpio); - spin_lock(&bank->lock); retval = _set_gpio_wakeup(bank, get_gpio_index(gpio), enable); - spin_unlock(&bank->lock); return retval; } @@ -696,7 +708,9 @@ int omap_request_gpio(int gpio) } bank->reserved_map |= (1 << get_gpio_index(gpio)); - /* Set trigger to none. You need to enable the trigger after request_irq */ + /* Set trigger to none. You need to enable the desired trigger with + * request_irq() or set_irq_type(). + */ _set_gpio_triggering(bank, get_gpio_index(gpio), IRQT_NOEDGE); #ifdef CONFIG_ARCH_OMAP15XX @@ -756,9 +770,7 @@ void omap_free_gpio(int gpio) } #endif bank->reserved_map &= ~(1 << get_gpio_index(gpio)); - _set_gpio_direction(bank, get_gpio_index(gpio), 1); - _set_gpio_irqenable(bank, gpio, 0); - _clear_gpio_irqstatus(bank, gpio); + _reset_gpio(bank, gpio); spin_unlock(&bank->lock); } @@ -898,6 +910,14 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc, } +static void gpio_irq_shutdown(unsigned int irq) +{ + unsigned int gpio = irq - IH_GPIO_BASE; + struct gpio_bank *bank = get_gpio_bank(gpio); + + _reset_gpio(bank, gpio); +} + static void gpio_ack_irq(unsigned int irq) { unsigned int gpio = irq - IH_GPIO_BASE; @@ -946,6 +966,7 @@ static void mpuio_unmask_irq(unsigned int irq) static struct irq_chip gpio_irq_chip = { .name = "GPIO", + .shutdown = gpio_irq_shutdown, .ack = gpio_ack_irq, .mask = gpio_mask_irq, .unmask = gpio_unmask_irq, @@ -985,7 +1006,7 @@ static int __init _omap_gpio_init(void) else clk_enable(gpio_ick); gpio_fck = clk_get(NULL, "gpios_fck"); - if (IS_ERR(gpio_ick)) + if (IS_ERR(gpio_fck)) printk("Could not get gpios_fck\n"); else clk_enable(gpio_fck); @@ -1144,8 +1165,8 @@ static int omap_gpio_resume(struct sys_device *dev) wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA; break; case METHOD_GPIO_24XX: - wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA; - wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA; + wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA; + wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA; break; default: continue; diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index 196aac3ac32..ade9a0fa6ef 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -75,8 +75,6 @@ static struct clk *mcbsp1_ick = 0; static struct clk *mcbsp1_fck = 0; static struct clk *mcbsp2_ick = 0; static struct clk *mcbsp2_fck = 0; -static struct clk *sys_ck = 0; -static struct clk *sys_clkout = 0; #endif static void omap_mcbsp_dump_reg(u8 id) @@ -232,7 +230,6 @@ static void omap2_mcbsp2_mux_setup(void) omap_cfg_reg(W15_24XX_MCBSP2_DR); omap_cfg_reg(V15_24XX_MCBSP2_DX); omap_cfg_reg(V14_24XX_GPIO117); - omap_cfg_reg(W14_24XX_SYS_CLKOUT); } #endif @@ -984,13 +981,7 @@ static int __init omap_mcbsp_init(void) if (cpu_is_omap24xx()) { mcbsp_info = mcbsp_24xx; mcbsp_count = ARRAY_SIZE(mcbsp_24xx); - - /* REVISIT: where's the right place? */ omap2_mcbsp2_mux_setup(); - sys_ck = clk_get(0, "sys_ck"); - sys_clkout = clk_get(0, "sys_clkout"); - clk_set_parent(sys_clkout, sys_ck); - clk_enable(sys_clkout); } #endif for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) { diff --git a/arch/arm/plat-omap/pm.c b/arch/arm/plat-omap/pm.c deleted file mode 100644 index 04b4102727a..00000000000 --- a/arch/arm/plat-omap/pm.c +++ /dev/null @@ -1,670 +0,0 @@ -/* - * linux/arch/arm/plat-omap/pm.c - * - * OMAP Power Management Routines - * - * Original code for the SA11x0: - * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com> - * - * Modified for the PXA250 by Nicolas Pitre: - * Copyright (c) 2002 Monta Vista Software, Inc. - * - * Modified for the OMAP1510 by David Singleton: - * Copyright (c) 2002 Monta Vista Software, Inc. - * - * Cleanup 2004 for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/pm.h> -#include <linux/sched.h> -#include <linux/proc_fs.h> -#include <linux/pm.h> -#include <linux/interrupt.h> - -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/mach/time.h> -#include <asm/mach/irq.h> - -#include <asm/mach-types.h> -#include <asm/arch/irqs.h> -#include <asm/arch/tc.h> -#include <asm/arch/pm.h> -#include <asm/arch/mux.h> -#include <asm/arch/tps65010.h> -#include <asm/arch/dsp_common.h> - -#include <asm/arch/clock.h> -#include <asm/arch/sram.h> - -static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE]; -static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE]; -static unsigned int mpui730_sleep_save[MPUI730_SLEEP_SAVE_SIZE]; -static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE]; -static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE]; - -static void (*omap_sram_idle)(void) = NULL; -static void (*omap_sram_suspend)(unsigned long r0, unsigned long r1) = NULL; - -/* - * Let's power down on idle, but only if we are really - * idle, because once we start down the path of - * going idle we continue to do idle even if we get - * a clock tick interrupt . . - */ -void omap_pm_idle(void) -{ - unsigned int mask32 = 0; - - /* - * If the DSP is being used let's just idle the CPU, the overhead - * to wake up from Big Sleep is big, milliseconds versus micro - * seconds for wait for interrupt. - */ - - local_irq_disable(); - local_fiq_disable(); - if (need_resched()) { - local_fiq_enable(); - local_irq_enable(); - return; - } - mask32 = omap_readl(ARM_SYSST); - - /* - * Prevent the ULPD from entering low power state by setting - * POWER_CTRL_REG:4 = 0 - */ - omap_writew(omap_readw(ULPD_POWER_CTRL) & - ~ULPD_DEEP_SLEEP_TRANSITION_EN, ULPD_POWER_CTRL); - - /* - * Since an interrupt may set up a timer, we don't want to - * reprogram the hardware timer with interrupts enabled. - * Re-enable interrupts only after returning from idle. - */ - timer_dyn_reprogram(); - - if ((mask32 & DSP_IDLE) == 0) { - __asm__ volatile ("mcr p15, 0, r0, c7, c0, 4"); - } else - omap_sram_idle(); - - local_fiq_enable(); - local_irq_enable(); -} - -/* - * Configuration of the wakeup event is board specific. For the - * moment we put it into this helper function. Later it may move - * to board specific files. - */ -static void omap_pm_wakeup_setup(void) -{ - u32 level1_wake = 0; - u32 level2_wake = OMAP_IRQ_BIT(INT_UART2); - - /* - * Turn off all interrupts except GPIO bank 1, L1-2nd level cascade, - * and the L2 wakeup interrupts: keypad and UART2. Note that the - * drivers must still separately call omap_set_gpio_wakeup() to - * wake up to a GPIO interrupt. - */ - if (cpu_is_omap730()) - level1_wake = OMAP_IRQ_BIT(INT_730_GPIO_BANK1) | - OMAP_IRQ_BIT(INT_730_IH2_IRQ); - else if (cpu_is_omap1510()) - level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) | - OMAP_IRQ_BIT(INT_1510_IH2_IRQ); - else if (cpu_is_omap16xx()) - level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) | - OMAP_IRQ_BIT(INT_1610_IH2_IRQ); - - omap_writel(~level1_wake, OMAP_IH1_MIR); - - if (cpu_is_omap730()) { - omap_writel(~level2_wake, OMAP_IH2_0_MIR); - omap_writel(~(OMAP_IRQ_BIT(INT_730_WAKE_UP_REQ) | OMAP_IRQ_BIT(INT_730_MPUIO_KEYPAD)), OMAP_IH2_1_MIR); - } else if (cpu_is_omap1510()) { - level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD); - omap_writel(~level2_wake, OMAP_IH2_MIR); - } else if (cpu_is_omap16xx()) { - level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD); - omap_writel(~level2_wake, OMAP_IH2_0_MIR); - - /* INT_1610_WAKE_UP_REQ is needed for GPIO wakeup... */ - omap_writel(~OMAP_IRQ_BIT(INT_1610_WAKE_UP_REQ), OMAP_IH2_1_MIR); - omap_writel(~0x0, OMAP_IH2_2_MIR); - omap_writel(~0x0, OMAP_IH2_3_MIR); - } - - /* New IRQ agreement, recalculate in cascade order */ - omap_writel(1, OMAP_IH2_CONTROL); - omap_writel(1, OMAP_IH1_CONTROL); -} - -void omap_pm_suspend(void) -{ - unsigned long arg0 = 0, arg1 = 0; - - printk("PM: OMAP%x is trying to enter deep sleep...\n", system_rev); - - omap_serial_wake_trigger(1); - - if (machine_is_omap_osk()) { - /* Stop LED1 (D9) blink */ - tps65010_set_led(LED1, OFF); - } - - omap_writew(0xffff, ULPD_SOFT_DISABLE_REQ_REG); - - /* - * Step 1: turn off interrupts (FIXME: NOTE: already disabled) - */ - - local_irq_disable(); - local_fiq_disable(); - - /* - * Step 2: save registers - * - * The omap is a strange/beautiful device. The caches, memory - * and register state are preserved across power saves. - * We have to save and restore very little register state to - * idle the omap. - * - * Save interrupt, MPUI, ARM and UPLD control registers. - */ - - if (cpu_is_omap730()) { - MPUI730_SAVE(OMAP_IH1_MIR); - MPUI730_SAVE(OMAP_IH2_0_MIR); - MPUI730_SAVE(OMAP_IH2_1_MIR); - MPUI730_SAVE(MPUI_CTRL); - MPUI730_SAVE(MPUI_DSP_BOOT_CONFIG); - MPUI730_SAVE(MPUI_DSP_API_CONFIG); - MPUI730_SAVE(EMIFS_CONFIG); - MPUI730_SAVE(EMIFF_SDRAM_CONFIG); - - } else if (cpu_is_omap1510()) { - MPUI1510_SAVE(OMAP_IH1_MIR); - MPUI1510_SAVE(OMAP_IH2_MIR); - MPUI1510_SAVE(MPUI_CTRL); - MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG); - MPUI1510_SAVE(MPUI_DSP_API_CONFIG); - MPUI1510_SAVE(EMIFS_CONFIG); - MPUI1510_SAVE(EMIFF_SDRAM_CONFIG); - } else if (cpu_is_omap16xx()) { - MPUI1610_SAVE(OMAP_IH1_MIR); - MPUI1610_SAVE(OMAP_IH2_0_MIR); - MPUI1610_SAVE(OMAP_IH2_1_MIR); - MPUI1610_SAVE(OMAP_IH2_2_MIR); - MPUI1610_SAVE(OMAP_IH2_3_MIR); - MPUI1610_SAVE(MPUI_CTRL); - MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG); - MPUI1610_SAVE(MPUI_DSP_API_CONFIG); - MPUI1610_SAVE(EMIFS_CONFIG); - MPUI1610_SAVE(EMIFF_SDRAM_CONFIG); - } - - ARM_SAVE(ARM_CKCTL); - ARM_SAVE(ARM_IDLECT1); - ARM_SAVE(ARM_IDLECT2); - if (!(cpu_is_omap1510())) - ARM_SAVE(ARM_IDLECT3); - ARM_SAVE(ARM_EWUPCT); - ARM_SAVE(ARM_RSTCT1); - ARM_SAVE(ARM_RSTCT2); - ARM_SAVE(ARM_SYSST); - ULPD_SAVE(ULPD_CLOCK_CTRL); - ULPD_SAVE(ULPD_STATUS_REQ); - - /* (Step 3 removed - we now allow deep sleep by default) */ - - /* - * Step 4: OMAP DSP Shutdown - */ - - - /* - * Step 5: Wakeup Event Setup - */ - - omap_pm_wakeup_setup(); - - /* - * Step 6: ARM and Traffic controller shutdown - */ - - /* disable ARM watchdog */ - omap_writel(0x00F5, OMAP_WDT_TIMER_MODE); - omap_writel(0x00A0, OMAP_WDT_TIMER_MODE); - - /* - * Step 6b: ARM and Traffic controller shutdown - * - * Step 6 continues here. Prepare jump to power management - * assembly code in internal SRAM. - * - * Since the omap_cpu_suspend routine has been copied to - * SRAM, we'll do an indirect procedure call to it and pass the - * contents of arm_idlect1 and arm_idlect2 so it can restore - * them when it wakes up and it will return. - */ - - arg0 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT1]; - arg1 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT2]; - - /* - * Step 6c: ARM and Traffic controller shutdown - * - * Jump to assembly code. The processor will stay there - * until wake up. - */ - omap_sram_suspend(arg0, arg1); - - /* - * If we are here, processor is woken up! - */ - - /* - * Restore ARM state, except ARM_IDLECT1/2 which omap_cpu_suspend did - */ - - if (!(cpu_is_omap1510())) - ARM_RESTORE(ARM_IDLECT3); - ARM_RESTORE(ARM_CKCTL); - ARM_RESTORE(ARM_EWUPCT); - ARM_RESTORE(ARM_RSTCT1); - ARM_RESTORE(ARM_RSTCT2); - ARM_RESTORE(ARM_SYSST); - ULPD_RESTORE(ULPD_CLOCK_CTRL); - ULPD_RESTORE(ULPD_STATUS_REQ); - - if (cpu_is_omap730()) { - MPUI730_RESTORE(EMIFS_CONFIG); - MPUI730_RESTORE(EMIFF_SDRAM_CONFIG); - MPUI730_RESTORE(OMAP_IH1_MIR); - MPUI730_RESTORE(OMAP_IH2_0_MIR); - MPUI730_RESTORE(OMAP_IH2_1_MIR); - } else if (cpu_is_omap1510()) { - MPUI1510_RESTORE(MPUI_CTRL); - MPUI1510_RESTORE(MPUI_DSP_BOOT_CONFIG); - MPUI1510_RESTORE(MPUI_DSP_API_CONFIG); - MPUI1510_RESTORE(EMIFS_CONFIG); - MPUI1510_RESTORE(EMIFF_SDRAM_CONFIG); - MPUI1510_RESTORE(OMAP_IH1_MIR); - MPUI1510_RESTORE(OMAP_IH2_MIR); - } else if (cpu_is_omap16xx()) { - MPUI1610_RESTORE(MPUI_CTRL); - MPUI1610_RESTORE(MPUI_DSP_BOOT_CONFIG); - MPUI1610_RESTORE(MPUI_DSP_API_CONFIG); - MPUI1610_RESTORE(EMIFS_CONFIG); - MPUI1610_RESTORE(EMIFF_SDRAM_CONFIG); - - MPUI1610_RESTORE(OMAP_IH1_MIR); - MPUI1610_RESTORE(OMAP_IH2_0_MIR); - MPUI1610_RESTORE(OMAP_IH2_1_MIR); - MPUI1610_RESTORE(OMAP_IH2_2_MIR); - MPUI1610_RESTORE(OMAP_IH2_3_MIR); - } - - omap_writew(0, ULPD_SOFT_DISABLE_REQ_REG); - - /* - * Reenable interrupts - */ - - local_irq_enable(); - local_fiq_enable(); - - omap_serial_wake_trigger(0); - - printk("PM: OMAP%x is re-starting from deep sleep...\n", system_rev); - - if (machine_is_omap_osk()) { - /* Let LED1 (D9) blink again */ - tps65010_set_led(LED1, BLINK); - } -} - -#if defined(DEBUG) && defined(CONFIG_PROC_FS) -static int g_read_completed; - -/* - * Read system PM registers for debugging - */ -static int omap_pm_read_proc( - char *page_buffer, - char **my_first_byte, - off_t virtual_start, - int length, - int *eof, - void *data) -{ - int my_buffer_offset = 0; - char * const my_base = page_buffer; - - ARM_SAVE(ARM_CKCTL); - ARM_SAVE(ARM_IDLECT1); - ARM_SAVE(ARM_IDLECT2); - if (!(cpu_is_omap1510())) - ARM_SAVE(ARM_IDLECT3); - ARM_SAVE(ARM_EWUPCT); - ARM_SAVE(ARM_RSTCT1); - ARM_SAVE(ARM_RSTCT2); - ARM_SAVE(ARM_SYSST); - - ULPD_SAVE(ULPD_IT_STATUS); - ULPD_SAVE(ULPD_CLOCK_CTRL); - ULPD_SAVE(ULPD_SOFT_REQ); - ULPD_SAVE(ULPD_STATUS_REQ); - ULPD_SAVE(ULPD_DPLL_CTRL); - ULPD_SAVE(ULPD_POWER_CTRL); - - if (cpu_is_omap730()) { - MPUI730_SAVE(MPUI_CTRL); - MPUI730_SAVE(MPUI_DSP_STATUS); - MPUI730_SAVE(MPUI_DSP_BOOT_CONFIG); - MPUI730_SAVE(MPUI_DSP_API_CONFIG); - MPUI730_SAVE(EMIFF_SDRAM_CONFIG); - MPUI730_SAVE(EMIFS_CONFIG); - } else if (cpu_is_omap1510()) { - MPUI1510_SAVE(MPUI_CTRL); - MPUI1510_SAVE(MPUI_DSP_STATUS); - MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG); - MPUI1510_SAVE(MPUI_DSP_API_CONFIG); - MPUI1510_SAVE(EMIFF_SDRAM_CONFIG); - MPUI1510_SAVE(EMIFS_CONFIG); - } else if (cpu_is_omap16xx()) { - MPUI1610_SAVE(MPUI_CTRL); - MPUI1610_SAVE(MPUI_DSP_STATUS); - MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG); - MPUI1610_SAVE(MPUI_DSP_API_CONFIG); - MPUI1610_SAVE(EMIFF_SDRAM_CONFIG); - MPUI1610_SAVE(EMIFS_CONFIG); - } - - if (virtual_start == 0) { - g_read_completed = 0; - - my_buffer_offset += sprintf(my_base + my_buffer_offset, - "ARM_CKCTL_REG: 0x%-8x \n" - "ARM_IDLECT1_REG: 0x%-8x \n" - "ARM_IDLECT2_REG: 0x%-8x \n" - "ARM_IDLECT3_REG: 0x%-8x \n" - "ARM_EWUPCT_REG: 0x%-8x \n" - "ARM_RSTCT1_REG: 0x%-8x \n" - "ARM_RSTCT2_REG: 0x%-8x \n" - "ARM_SYSST_REG: 0x%-8x \n" - "ULPD_IT_STATUS_REG: 0x%-4x \n" - "ULPD_CLOCK_CTRL_REG: 0x%-4x \n" - "ULPD_SOFT_REQ_REG: 0x%-4x \n" - "ULPD_DPLL_CTRL_REG: 0x%-4x \n" - "ULPD_STATUS_REQ_REG: 0x%-4x \n" - "ULPD_POWER_CTRL_REG: 0x%-4x \n", - ARM_SHOW(ARM_CKCTL), - ARM_SHOW(ARM_IDLECT1), - ARM_SHOW(ARM_IDLECT2), - ARM_SHOW(ARM_IDLECT3), - ARM_SHOW(ARM_EWUPCT), - ARM_SHOW(ARM_RSTCT1), - ARM_SHOW(ARM_RSTCT2), - ARM_SHOW(ARM_SYSST), - ULPD_SHOW(ULPD_IT_STATUS), - ULPD_SHOW(ULPD_CLOCK_CTRL), - ULPD_SHOW(ULPD_SOFT_REQ), - ULPD_SHOW(ULPD_DPLL_CTRL), - ULPD_SHOW(ULPD_STATUS_REQ), - ULPD_SHOW(ULPD_POWER_CTRL)); - - if (cpu_is_omap730()) { - my_buffer_offset += sprintf(my_base + my_buffer_offset, - "MPUI730_CTRL_REG 0x%-8x \n" - "MPUI730_DSP_STATUS_REG: 0x%-8x \n" - "MPUI730_DSP_BOOT_CONFIG_REG: 0x%-8x \n" - "MPUI730_DSP_API_CONFIG_REG: 0x%-8x \n" - "MPUI730_SDRAM_CONFIG_REG: 0x%-8x \n" - "MPUI730_EMIFS_CONFIG_REG: 0x%-8x \n", - MPUI730_SHOW(MPUI_CTRL), - MPUI730_SHOW(MPUI_DSP_STATUS), - MPUI730_SHOW(MPUI_DSP_BOOT_CONFIG), - MPUI730_SHOW(MPUI_DSP_API_CONFIG), - MPUI730_SHOW(EMIFF_SDRAM_CONFIG), - MPUI730_SHOW(EMIFS_CONFIG)); - } else if (cpu_is_omap1510()) { - my_buffer_offset += sprintf(my_base + my_buffer_offset, - "MPUI1510_CTRL_REG 0x%-8x \n" - "MPUI1510_DSP_STATUS_REG: 0x%-8x \n" - "MPUI1510_DSP_BOOT_CONFIG_REG: 0x%-8x \n" - "MPUI1510_DSP_API_CONFIG_REG: 0x%-8x \n" - "MPUI1510_SDRAM_CONFIG_REG: 0x%-8x \n" - "MPUI1510_EMIFS_CONFIG_REG: 0x%-8x \n", - MPUI1510_SHOW(MPUI_CTRL), - MPUI1510_SHOW(MPUI_DSP_STATUS), - MPUI1510_SHOW(MPUI_DSP_BOOT_CONFIG), - MPUI1510_SHOW(MPUI_DSP_API_CONFIG), - MPUI1510_SHOW(EMIFF_SDRAM_CONFIG), - MPUI1510_SHOW(EMIFS_CONFIG)); - } else if (cpu_is_omap16xx()) { - my_buffer_offset += sprintf(my_base + my_buffer_offset, - "MPUI1610_CTRL_REG 0x%-8x \n" - "MPUI1610_DSP_STATUS_REG: 0x%-8x \n" - "MPUI1610_DSP_BOOT_CONFIG_REG: 0x%-8x \n" - "MPUI1610_DSP_API_CONFIG_REG: 0x%-8x \n" - "MPUI1610_SDRAM_CONFIG_REG: 0x%-8x \n" - "MPUI1610_EMIFS_CONFIG_REG: 0x%-8x \n", - MPUI1610_SHOW(MPUI_CTRL), - MPUI1610_SHOW(MPUI_DSP_STATUS), - MPUI1610_SHOW(MPUI_DSP_BOOT_CONFIG), - MPUI1610_SHOW(MPUI_DSP_API_CONFIG), - MPUI1610_SHOW(EMIFF_SDRAM_CONFIG), - MPUI1610_SHOW(EMIFS_CONFIG)); - } - - g_read_completed++; - } else if (g_read_completed >= 1) { - *eof = 1; - return 0; - } - g_read_completed++; - - *my_first_byte = page_buffer; - return my_buffer_offset; -} - -static void omap_pm_init_proc(void) -{ - struct proc_dir_entry *entry; - - entry = create_proc_read_entry("driver/omap_pm", - S_IWUSR | S_IRUGO, NULL, - omap_pm_read_proc, NULL); -} - -#endif /* DEBUG && CONFIG_PROC_FS */ - -/* - * omap_pm_prepare - Do preliminary suspend work. - * @state: suspend state we're entering. - * - */ -//#include <asm/hardware.h> - -static int omap_pm_prepare(suspend_state_t state) -{ - int error = 0; - - switch (state) - { - case PM_SUSPEND_STANDBY: - case PM_SUSPEND_MEM: - break; - - case PM_SUSPEND_DISK: - return -ENOTSUPP; - - default: - return -EINVAL; - } - - return error; -} - - -/* - * omap_pm_enter - Actually enter a sleep state. - * @state: State we're entering. - * - */ - -static int omap_pm_enter(suspend_state_t state) -{ - switch (state) - { - case PM_SUSPEND_STANDBY: - case PM_SUSPEND_MEM: - omap_pm_suspend(); - break; - - case PM_SUSPEND_DISK: - return -ENOTSUPP; - - default: - return -EINVAL; - } - - return 0; -} - - -/** - * omap_pm_finish - Finish up suspend sequence. - * @state: State we're coming out of. - * - * This is called after we wake back up (or if entering the sleep state - * failed). - */ - -static int omap_pm_finish(suspend_state_t state) -{ - return 0; -} - - -static irqreturn_t omap_wakeup_interrupt(int irq, void * dev, - struct pt_regs * regs) -{ - return IRQ_HANDLED; -} - -static struct irqaction omap_wakeup_irq = { - .name = "peripheral wakeup", - .flags = IRQF_DISABLED, - .handler = omap_wakeup_interrupt -}; - - - -static struct pm_ops omap_pm_ops ={ - .pm_disk_mode = 0, - .prepare = omap_pm_prepare, - .enter = omap_pm_enter, - .finish = omap_pm_finish, -}; - -static int __init omap_pm_init(void) -{ - printk("Power Management for TI OMAP.\n"); - /* - * We copy the assembler sleep/wakeup routines to SRAM. - * These routines need to be in SRAM as that's the only - * memory the MPU can see when it wakes up. - */ - if (cpu_is_omap730()) { - omap_sram_idle = omap_sram_push(omap730_idle_loop_suspend, - omap730_idle_loop_suspend_sz); - omap_sram_suspend = omap_sram_push(omap730_cpu_suspend, - omap730_cpu_suspend_sz); - } else if (cpu_is_omap1510()) { - omap_sram_idle = omap_sram_push(omap1510_idle_loop_suspend, - omap1510_idle_loop_suspend_sz); - omap_sram_suspend = omap_sram_push(omap1510_cpu_suspend, - omap1510_cpu_suspend_sz); - } else if (cpu_is_omap16xx()) { - omap_sram_idle = omap_sram_push(omap1610_idle_loop_suspend, - omap1610_idle_loop_suspend_sz); - omap_sram_suspend = omap_sram_push(omap1610_cpu_suspend, - omap1610_cpu_suspend_sz); - } - - if (omap_sram_idle == NULL || omap_sram_suspend == NULL) { - printk(KERN_ERR "PM not initialized: Missing SRAM support\n"); - return -ENODEV; - } - - pm_idle = omap_pm_idle; - - if (cpu_is_omap730()) - setup_irq(INT_730_WAKE_UP_REQ, &omap_wakeup_irq); - else if (cpu_is_omap16xx()) - setup_irq(INT_1610_WAKE_UP_REQ, &omap_wakeup_irq); - -#if 0 - /* --- BEGIN BOARD-DEPENDENT CODE --- */ - /* Sleepx mask direction */ - omap_writew((omap_readw(0xfffb5008) & ~2), 0xfffb5008); - /* Unmask sleepx signal */ - omap_writew((omap_readw(0xfffb5004) & ~2), 0xfffb5004); - /* --- END BOARD-DEPENDENT CODE --- */ -#endif - - /* Program new power ramp-up time - * (0 for most boards since we don't lower voltage when in deep sleep) - */ - omap_writew(ULPD_SETUP_ANALOG_CELL_3_VAL, ULPD_SETUP_ANALOG_CELL_3); - - /* Setup ULPD POWER_CTRL_REG - enter deep sleep whenever possible */ - omap_writew(ULPD_POWER_CTRL_REG_VAL, ULPD_POWER_CTRL); - - /* Configure IDLECT3 */ - if (cpu_is_omap730()) - omap_writel(OMAP730_IDLECT3_VAL, OMAP730_IDLECT3); - else if (cpu_is_omap16xx()) - omap_writel(OMAP1610_IDLECT3_VAL, OMAP1610_IDLECT3); - - pm_set_ops(&omap_pm_ops); - -#if defined(DEBUG) && defined(CONFIG_PROC_FS) - omap_pm_init_proc(); -#endif - - if (cpu_is_omap16xx()) { - /* configure LOW_PWR pin */ - omap_cfg_reg(T20_1610_LOW_PWR); - } - - return 0; -} -__initcall(omap_pm_init); - diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index e75718301b0..19014b2ff4c 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -174,10 +174,7 @@ void __init omap_map_sram(void) if (cpu_is_omap24xx()) { omap_sram_io_desc[0].virtual = OMAP2_SRAM_VA; - if (is_sram_locked()) - base = OMAP2_SRAM_PUB_PA; - else - base = OMAP2_SRAM_PA; + base = OMAP2_SRAM_PA; base = ROUND_DOWN(base, PAGE_SIZE); omap_sram_io_desc[0].pfn = __phys_to_pfn(base); } diff --git a/arch/arm/plat-omap/timer32k.c b/arch/arm/plat-omap/timer32k.c index 281ecc7fcdf..cf6df3378d3 100644 --- a/arch/arm/plat-omap/timer32k.c +++ b/arch/arm/plat-omap/timer32k.c @@ -105,6 +105,8 @@ static inline unsigned long omap_32k_timer_read(int reg) static inline void omap_32k_timer_start(unsigned long load_val) { + if (!load_val) + load_val = 1; omap_32k_timer_write(load_val, OMAP1_32K_TIMER_TVR); omap_32k_timer_write(0x0f, OMAP1_32K_TIMER_CR); } @@ -192,14 +194,11 @@ unsigned long long sched_clock(void) * issues with dynamic tick. In the dynamic tick case, we need to lock * with irqsave. */ -static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id, - struct pt_regs *regs) +static inline irqreturn_t _omap_32k_timer_interrupt(int irq, void *dev_id, + struct pt_regs *regs) { - unsigned long flags; unsigned long now; - write_seqlock_irqsave(&xtime_lock, flags); - omap_32k_timer_ack_irq(); now = omap_32k_sync_timer_read(); @@ -215,6 +214,23 @@ static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id, * continuous timer can be overridden from pm_idle to be longer. */ omap_32k_timer_start(omap_32k_last_tick + OMAP_32K_TICKS_PER_HZ - now); + + return IRQ_HANDLED; +} + +static irqreturn_t omap_32k_timer_handler(int irq, void *dev_id, + struct pt_regs *regs) +{ + return _omap_32k_timer_interrupt(irq, dev_id, regs); +} + +static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id, + struct pt_regs *regs) +{ + unsigned long flags; + + write_seqlock_irqsave(&xtime_lock, flags); + _omap_32k_timer_interrupt(irq, dev_id, regs); write_sequnlock_irqrestore(&xtime_lock, flags); return IRQ_HANDLED; @@ -230,7 +246,15 @@ static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id, */ void omap_32k_timer_reprogram(unsigned long next_tick) { - omap_32k_timer_start(JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1); + unsigned long ticks = JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1; + unsigned long now = omap_32k_sync_timer_read(); + unsigned long idled = now - omap_32k_last_tick; + + if (idled + 1 < ticks) + ticks -= idled; + else + ticks = 1; + omap_32k_timer_start(ticks); } static struct irqaction omap_32k_timer_irq; @@ -252,7 +276,7 @@ static struct dyn_tick_timer omap_dyn_tick_timer = { .enable = omap_32k_timer_enable_dyn_tick, .disable = omap_32k_timer_disable_dyn_tick, .reprogram = omap_32k_timer_reprogram, - .handler = omap_32k_timer_interrupt, + .handler = omap_32k_timer_handler, }; #endif /* CONFIG_NO_IDLE_HZ */ |