diff options
Diffstat (limited to 'arch/arm/plat-omap')
23 files changed, 406 insertions, 296 deletions
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 6da796ef82bd..78b49a626d06 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -110,8 +110,13 @@ config OMAP_IOMMU tristate config OMAP_IOMMU_DEBUG - depends on OMAP_IOMMU - tristate + tristate "Export OMAP IOMMU internals in DebugFS" + depends on OMAP_IOMMU && DEBUG_FS + help + Select this to see extensive information about + the internal state of OMAP IOMMU in debugfs. + + Say N unless you know you need this. choice prompt "System timer" diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 5261a0923691..7190cbd92620 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -12,14 +12,12 @@ */ #include <linux/kernel.h> #include <linux/init.h> -#include <linux/module.h> #include <linux/list.h> #include <linux/errno.h> #include <linux/err.h> #include <linux/string.h> #include <linux/clk.h> #include <linux/mutex.h> -#include <linux/platform_device.h> #include <linux/cpufreq.h> #include <linux/debugfs.h> #include <linux/io.h> @@ -32,9 +30,9 @@ static DEFINE_SPINLOCK(clockfw_lock); static struct clk_functions *arch_clock; -/*------------------------------------------------------------------------- +/* * Standard clock functions defined in include/linux/clk.h - *-------------------------------------------------------------------------*/ + */ int clk_enable(struct clk *clk) { @@ -92,9 +90,9 @@ unsigned long clk_get_rate(struct clk *clk) } EXPORT_SYMBOL(clk_get_rate); -/*------------------------------------------------------------------------- +/* * Optional clock functions defined in include/linux/clk.h - *-------------------------------------------------------------------------*/ + */ long clk_round_rate(struct clk *clk, unsigned long rate) { @@ -140,9 +138,6 @@ int clk_set_parent(struct clk *clk, struct clk *parent) unsigned long flags; int ret = -EINVAL; - if (cpu_is_omap44xx()) - /* OMAP4 clk framework not supported yet */ - return 0; if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent)) return ret; @@ -169,9 +164,9 @@ struct clk *clk_get_parent(struct clk *clk) } EXPORT_SYMBOL(clk_get_parent); -/*------------------------------------------------------------------------- +/* * OMAP specific clock functions shared between omap1 and omap2 - *-------------------------------------------------------------------------*/ + */ int __initdata mpurate; @@ -222,7 +217,7 @@ void clk_reparent(struct clk *child, struct clk *parent) } /* Propagate rate to children */ -void propagate_rate(struct clk * tclk) +void propagate_rate(struct clk *tclk) { struct clk *clkp; @@ -389,7 +384,9 @@ void clk_exit_cpufreq_table(struct cpufreq_frequency_table **table) } #endif -/*-------------------------------------------------------------------------*/ +/* + * + */ #ifdef CONFIG_OMAP_RESET_CLOCKS /* @@ -404,7 +401,7 @@ static int __init clk_disable_unused(void) if (ck->ops == &clkops_null) continue; - if (ck->usecount > 0 || ck->enable_reg == 0) + if (ck->usecount > 0 || !ck->enable_reg) continue; spin_lock_irqsave(&clockfw_lock, flags); diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c index f12f0e39ddf2..219c01e82bc5 100644 --- a/arch/arm/plat-omap/common.c +++ b/arch/arm/plat-omap/common.c @@ -47,9 +47,6 @@ struct omap_board_config_kernel *omap_board_config; int omap_board_config_size; -/* used by omap-smp.c and board-4430sdp.c */ -void __iomem *gic_cpu_base_addr; - static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out) { struct omap_board_config_kernel *kinfo = NULL; diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 1d959965ff52..f7f571e7987e 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -501,7 +501,8 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) burst = 0x2; break; } - /* not supported by current hardware on OMAP1 + /* + * not supported by current hardware on OMAP1 * w |= (0x03 << 7); * fall through */ @@ -510,7 +511,8 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) burst = 0x3; break; } - /* OMAP1 don't support burst 16 + /* + * OMAP1 don't support burst 16 * fall through */ default: @@ -604,7 +606,8 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) burst = 0x3; break; } - /* OMAP1 don't support burst 16 + /* + * OMAP1 don't support burst 16 * fall through */ default: @@ -709,6 +712,21 @@ static inline void omap2_enable_irq_lch(int lch) spin_unlock_irqrestore(&dma_chan_lock, flags); } +static inline void omap2_disable_irq_lch(int lch) +{ + u32 val; + unsigned long flags; + + if (!cpu_class_is_omap2()) + return; + + spin_lock_irqsave(&dma_chan_lock, flags); + val = dma_read(IRQENABLE_L0); + val &= ~(1 << lch); + dma_write(val, IRQENABLE_L0); + spin_unlock_irqrestore(&dma_chan_lock, flags); +} + int omap_request_dma(int dev_id, const char *dev_name, void (*callback)(int lch, u16 ch_status, void *data), void *data, int *dma_ch_out) @@ -807,14 +825,7 @@ void omap_free_dma(int lch) } if (cpu_class_is_omap2()) { - u32 val; - - spin_lock_irqsave(&dma_chan_lock, flags); - /* Disable interrupts */ - val = dma_read(IRQENABLE_L0); - val &= ~(1 << lch); - dma_write(val, IRQENABLE_L0); - spin_unlock_irqrestore(&dma_chan_lock, flags); + omap2_disable_irq_lch(lch); /* Clear the CSR register and IRQ status register */ dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(lch)); @@ -1277,8 +1288,10 @@ int omap_request_dma_chain(int dev_id, const char *dev_name, return -EINVAL; } - /* Allocate a queue to maintain the status of the channels - * in the chain */ + /* + * Allocate a queue to maintain the status of the channels + * in the chain + */ channels = kmalloc(sizeof(*channels) * no_of_chans, GFP_KERNEL); if (channels == NULL) { printk(KERN_ERR "omap_dma: No memory for channel queue\n"); @@ -1907,7 +1920,8 @@ static int omap2_dma_handle_ch(int ch) printk(KERN_INFO "DMA transaction error with device %d\n", dma_chan[ch].dev_id); if (cpu_class_is_omap2()) { - /* Errata: sDMA Channel is not disabled + /* + * Errata: sDMA Channel is not disabled * after a transaction error. So we explicitely * disable the channel */ @@ -2107,6 +2121,9 @@ static int __init omap_init_dma(void) for (ch = 0; ch < dma_chan_count; ch++) { omap_clear_dma(ch); + if (cpu_class_is_omap2()) + omap2_disable_irq_lch(ch); + dma_chan[ch].dev_id = -1; dma_chan[ch].next_lch = -1; diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 4d99dfbc8bef..c64875f11fac 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -264,8 +264,8 @@ static struct omap_dm_timer omap4_dm_timers[] = { { .phys_base = 0x4a320000, .irq = OMAP44XX_IRQ_GPT12 }, }; static const char *omap4_dm_source_names[] __initdata = { - "sys_ck", - "omap_32k_fck", + "sys_clkin_ck", + "sys_32k_ck", NULL }; static struct clk *omap4_dm_source_clocks[2]; diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 45a225d09125..dc2ac42d6319 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -27,6 +27,7 @@ #include <mach/irqs.h> #include <mach/gpio.h> #include <asm/mach/irq.h> +#include <plat/powerdomain.h> /* * OMAP1510 GPIO registers @@ -137,7 +138,11 @@ #define OMAP4_GPIO_IRQSTATUSCLR1 0x0040 #define OMAP4_GPIO_IRQWAKEN0 0x0044 #define OMAP4_GPIO_IRQWAKEN1 0x0048 -#define OMAP4_GPIO_SYSSTATUS 0x0104 +#define OMAP4_GPIO_SYSSTATUS 0x0114 +#define OMAP4_GPIO_IRQENABLE1 0x011c +#define OMAP4_GPIO_WAKE_EN 0x0120 +#define OMAP4_GPIO_IRQSTATUS2 0x0128 +#define OMAP4_GPIO_IRQENABLE2 0x012c #define OMAP4_GPIO_CTRL 0x0130 #define OMAP4_GPIO_OE 0x0134 #define OMAP4_GPIO_DATAIN 0x0138 @@ -148,6 +153,10 @@ #define OMAP4_GPIO_FALLINGDETECT 0x014c #define OMAP4_GPIO_DEBOUNCENABLE 0x0150 #define OMAP4_GPIO_DEBOUNCINGTIME 0x0154 +#define OMAP4_GPIO_CLEARIRQENABLE1 0x0160 +#define OMAP4_GPIO_SETIRQENABLE1 0x0164 +#define OMAP4_GPIO_CLEARWKUENA 0x0180 +#define OMAP4_GPIO_SETWKUENA 0x0184 #define OMAP4_GPIO_CLEARDATAOUT 0x0190 #define OMAP4_GPIO_SETDATAOUT 0x0194 /* @@ -195,6 +204,7 @@ struct gpio_bank { struct gpio_chip chip; struct clk *dbck; u32 mod_usage; + u32 dbck_enable_mask; }; #define METHOD_MPUIO 0 @@ -303,8 +313,6 @@ struct omap3_gpio_regs { u32 risingdetect; u32 fallingdetect; u32 dataout; - u32 setwkuena; - u32 setdataout; }; static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS]; @@ -591,12 +599,16 @@ static int _get_gpio_dataout(struct gpio_bank *bank, int gpio) reg += OMAP7XX_GPIO_DATA_OUTPUT; break; #endif -#ifdef CONFIG_ARCH_OMAP2PLUS +#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) case METHOD_GPIO_24XX: - case METHOD_GPIO_44XX: reg += OMAP24XX_GPIO_DATAOUT; break; #endif +#ifdef CONFIG_ARCH_OMAP4 + case METHOD_GPIO_44XX: + reg += OMAP4_GPIO_DATAOUT; + break; +#endif default: return -EINVAL; } @@ -646,6 +658,7 @@ void omap_set_gpio_debounce(int gpio, int enable) goto done; if (cpu_is_omap34xx() || cpu_is_omap44xx()) { + bank->dbck_enable_mask = val; if (enable) clk_enable(bank->dbck); else @@ -724,15 +737,27 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio, OMAP4_GPIO_IRQWAKEN0); } } else { - if (trigger != 0) + /* + * GPIO wakeup request can only be generated on edge + * transitions + */ + if (trigger & IRQ_TYPE_EDGE_BOTH) __raw_writel(1 << gpio, bank->base + OMAP24XX_GPIO_SETWKUENA); else __raw_writel(1 << gpio, bank->base + OMAP24XX_GPIO_CLEARWKUENA); } - } else { - if (trigger != 0) + } + /* This part needs to be executed always for OMAP34xx */ + if (cpu_is_omap34xx() || (bank->non_wakeup_gpios & gpio_bit)) { + /* + * Log the edge gpio and manually trigger the IRQ + * after resume if the input level changes + * to avoid irq lost during PER RET/OFF mode + * Applies for omap2 non-wakeup gpio and all omap3 gpios + */ + if (trigger & IRQ_TYPE_EDGE_BOTH) bank->enabled_non_wakeup_gpios |= gpio_bit; else bank->enabled_non_wakeup_gpios &= ~gpio_bit; @@ -1200,11 +1225,17 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset) #endif if (!cpu_class_is_omap1()) { if (!bank->mod_usage) { + void __iomem *reg = bank->base; u32 ctrl; - ctrl = __raw_readl(bank->base + OMAP24XX_GPIO_CTRL); - ctrl &= 0xFFFFFFFE; + + if (cpu_is_omap24xx() || cpu_is_omap34xx()) + reg += OMAP24XX_GPIO_CTRL; + else if (cpu_is_omap44xx()) + reg += OMAP4_GPIO_CTRL; + ctrl = __raw_readl(reg); /* Module is enabled, clocks are not gated */ - __raw_writel(ctrl, bank->base + OMAP24XX_GPIO_CTRL); + ctrl &= 0xFFFFFFFE; + __raw_writel(ctrl, reg); } bank->mod_usage |= 1 << offset; } @@ -1226,22 +1257,34 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset) __raw_writel(1 << offset, reg); } #endif -#ifdef CONFIG_ARCH_OMAP2PLUS - if ((bank->method == METHOD_GPIO_24XX) || - (bank->method == METHOD_GPIO_44XX)) { +#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) + if (bank->method == METHOD_GPIO_24XX) { /* Disable wake-up during idle for dynamic tick */ void __iomem *reg = bank->base + OMAP24XX_GPIO_CLEARWKUENA; __raw_writel(1 << offset, reg); } #endif +#ifdef CONFIG_ARCH_OMAP4 + if (bank->method == METHOD_GPIO_44XX) { + /* Disable wake-up during idle for dynamic tick */ + void __iomem *reg = bank->base + OMAP4_GPIO_IRQWAKEN0; + __raw_writel(1 << offset, reg); + } +#endif if (!cpu_class_is_omap1()) { bank->mod_usage &= ~(1 << offset); if (!bank->mod_usage) { + void __iomem *reg = bank->base; u32 ctrl; - ctrl = __raw_readl(bank->base + OMAP24XX_GPIO_CTRL); + + if (cpu_is_omap24xx() || cpu_is_omap34xx()) + reg += OMAP24XX_GPIO_CTRL; + else if (cpu_is_omap44xx()) + reg += OMAP4_GPIO_CTRL; + ctrl = __raw_readl(reg); /* Module is disabled, clocks are gated */ ctrl |= 1; - __raw_writel(ctrl, bank->base + OMAP24XX_GPIO_CTRL); + __raw_writel(ctrl, reg); } } _reset_gpio(bank, bank->chip.base + offset); @@ -1570,9 +1613,14 @@ static int gpio_is_input(struct gpio_bank *bank, int mask) reg += OMAP7XX_GPIO_DIR_CONTROL; break; case METHOD_GPIO_24XX: - case METHOD_GPIO_44XX: reg += OMAP24XX_GPIO_OE; break; + case METHOD_GPIO_44XX: + reg += OMAP4_GPIO_OE; + break; + default: + WARN_ONCE(1, "gpio_is_input: incorrect OMAP GPIO method"); + return -EINVAL; } return __raw_readl(reg) & mask; } @@ -1845,7 +1893,8 @@ static int __init _omap_gpio_init(void) __raw_writel(0, bank->base + OMAP24XX_GPIO_CTRL); } - if (i < ARRAY_SIZE(non_wakeup_gpios)) + if (cpu_is_omap24xx() && + i < ARRAY_SIZE(non_wakeup_gpios)) bank->non_wakeup_gpios = non_wakeup_gpios[i]; gpio_count = 32; } @@ -2028,16 +2077,27 @@ static struct sys_device omap_gpio_device = { static int workaround_enabled; -void omap2_gpio_prepare_for_retention(void) +void omap2_gpio_prepare_for_idle(int power_state) { int i, c = 0; + int min = 0; - /* Remove triggering for all non-wakeup GPIOs. Otherwise spurious - * IRQs will be generated. See OMAP2420 Errata item 1.101. */ - for (i = 0; i < gpio_bank_count; i++) { + if (cpu_is_omap34xx()) + min = 1; + + for (i = min; i < gpio_bank_count; i++) { struct gpio_bank *bank = &gpio_bank[i]; u32 l1, l2; + if (bank->dbck_enable_mask) + clk_disable(bank->dbck); + + if (power_state > PWRDM_POWER_OFF) + continue; + + /* If going to OFF, remove triggering for all + * non-wakeup GPIOs. Otherwise spurious IRQs will be + * generated. See OMAP2420 Errata item 1.101. */ if (!(bank->enabled_non_wakeup_gpios)) continue; @@ -2085,16 +2145,23 @@ void omap2_gpio_prepare_for_retention(void) workaround_enabled = 1; } -void omap2_gpio_resume_after_retention(void) +void omap2_gpio_resume_after_idle(void) { int i; + int min = 0; - if (!workaround_enabled) - return; - for (i = 0; i < gpio_bank_count; i++) { + if (cpu_is_omap34xx()) + min = 1; + for (i = min; i < gpio_bank_count; i++) { struct gpio_bank *bank = &gpio_bank[i]; u32 l, gen, gen0, gen1; + if (bank->dbck_enable_mask) + clk_enable(bank->dbck); + + if (!workaround_enabled) + continue; + if (!(bank->enabled_non_wakeup_gpios)) continue; @@ -2119,7 +2186,7 @@ void omap2_gpio_resume_after_retention(void) * horribly racy, but it's the best we can do to work around * this silicon bug. */ l ^= bank->saved_datain; - l &= bank->non_wakeup_gpios; + l &= bank->enabled_non_wakeup_gpios; /* * No need to generate IRQs for the rising edge for gpio IRQs @@ -2207,10 +2274,6 @@ void omap_gpio_save_context(void) __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT); gpio_context[i].dataout = __raw_readl(bank->base + OMAP24XX_GPIO_DATAOUT); - gpio_context[i].setwkuena = - __raw_readl(bank->base + OMAP24XX_GPIO_SETWKUENA); - gpio_context[i].setdataout = - __raw_readl(bank->base + OMAP24XX_GPIO_SETDATAOUT); } } @@ -2243,10 +2306,6 @@ void omap_gpio_restore_context(void) bank->base + OMAP24XX_GPIO_FALLINGDETECT); __raw_writel(gpio_context[i].dataout, bank->base + OMAP24XX_GPIO_DATAOUT); - __raw_writel(gpio_context[i].setwkuena, - bank->base + OMAP24XX_GPIO_SETWKUENA); - __raw_writel(gpio_context[i].setdataout, - bank->base + OMAP24XX_GPIO_SETDATAOUT); } } #endif @@ -2286,110 +2345,3 @@ static int __init omap_gpio_sysinit(void) } arch_initcall(omap_gpio_sysinit); - - -#ifdef CONFIG_DEBUG_FS - -#include <linux/debugfs.h> -#include <linux/seq_file.h> - -static int dbg_gpio_show(struct seq_file *s, void *unused) -{ - unsigned i, j, gpio; - - for (i = 0, gpio = 0; i < gpio_bank_count; i++) { - struct gpio_bank *bank = gpio_bank + i; - unsigned bankwidth = 16; - u32 mask = 1; - - if (bank_is_mpuio(bank)) - gpio = OMAP_MPUIO(0); - else if (cpu_class_is_omap2() || cpu_is_omap7xx()) - bankwidth = 32; - - for (j = 0; j < bankwidth; j++, gpio++, mask <<= 1) { - unsigned irq, value, is_in, irqstat; - const char *label; - - label = gpiochip_is_requested(&bank->chip, j); - if (!label) - continue; - - irq = bank->virtual_irq_start + j; - value = gpio_get_value(gpio); - is_in = gpio_is_input(bank, mask); - - if (bank_is_mpuio(bank)) - seq_printf(s, "MPUIO %2d ", j); - else - seq_printf(s, "GPIO %3d ", gpio); - seq_printf(s, "(%-20.20s): %s %s", - label, - is_in ? "in " : "out", - value ? "hi" : "lo"); - -/* FIXME for at least omap2, show pullup/pulldown state */ - - irqstat = irq_desc[irq].status; -#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS) - if (is_in && ((bank->suspend_wakeup & mask) - || irqstat & IRQ_TYPE_SENSE_MASK)) { - char *trigger = NULL; - - switch (irqstat & IRQ_TYPE_SENSE_MASK) { - case IRQ_TYPE_EDGE_FALLING: - trigger = "falling"; - break; - case IRQ_TYPE_EDGE_RISING: - trigger = "rising"; - break; - case IRQ_TYPE_EDGE_BOTH: - trigger = "bothedge"; - break; - case IRQ_TYPE_LEVEL_LOW: - trigger = "low"; - break; - case IRQ_TYPE_LEVEL_HIGH: - trigger = "high"; - break; - case IRQ_TYPE_NONE: - trigger = "(?)"; - break; - } - seq_printf(s, ", irq-%d %-8s%s", - irq, trigger, - (bank->suspend_wakeup & mask) - ? " wakeup" : ""); - } -#endif - seq_printf(s, "\n"); - } - - if (bank_is_mpuio(bank)) { - seq_printf(s, "\n"); - gpio = 0; - } - } - return 0; -} - -static int dbg_gpio_open(struct inode *inode, struct file *file) -{ - return single_open(file, dbg_gpio_show, &inode->i_private); -} - -static const struct file_operations debug_fops = { - .open = dbg_gpio_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init omap_gpio_debuginit(void) -{ - (void) debugfs_create_file("omap_gpio", S_IRUGO, - NULL, NULL, &debug_fops); - return 0; -} -late_initcall(omap_gpio_debuginit); -#endif diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index f044b5927508..eec2b4993c69 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -38,6 +38,7 @@ #define OMAP2_I2C_BASE1 0x48070000 #define OMAP2_I2C_BASE2 0x48072000 #define OMAP2_I2C_BASE3 0x48060000 +#define OMAP4_I2C_BASE4 0x48350000 static const char name[] = "i2c_omap"; @@ -54,11 +55,14 @@ static const char name[] = "i2c_omap"; static struct resource i2c_resources[][2] = { { I2C_RESOURCE_BUILDER(0, 0) }, -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) - { I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE2, INT_24XX_I2C2_IRQ) }, +#if defined(CONFIG_ARCH_OMAP2PLUS) + { I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE2, 0) }, #endif -#if defined(CONFIG_ARCH_OMAP3) - { I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE3, INT_34XX_I2C3_IRQ) }, +#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) + { I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE3, 0) }, +#endif +#if defined(CONFIG_ARCH_OMAP4) + { I2C_RESOURCE_BUILDER(OMAP4_I2C_BASE4, 0) }, #endif }; @@ -76,12 +80,15 @@ static struct resource i2c_resources[][2] = { static struct omap_i2c_bus_platform_data i2c_pdata[ARRAY_SIZE(i2c_resources)]; static struct platform_device omap_i2c_devices[] = { I2C_DEV_BUILDER(1, i2c_resources[0], &i2c_pdata[0]), -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) +#if defined(CONFIG_ARCH_OMAP2PLUS) I2C_DEV_BUILDER(2, i2c_resources[1], &i2c_pdata[1]), #endif -#if defined(CONFIG_ARCH_OMAP3) +#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) I2C_DEV_BUILDER(3, i2c_resources[2], &i2c_pdata[2]), #endif +#if defined(CONFIG_ARCH_OMAP4) + I2C_DEV_BUILDER(4, i2c_resources[3], &i2c_pdata[3]), +#endif }; #define OMAP_I2C_CMDLINE_SETUP (BIT(31)) @@ -96,37 +103,60 @@ static int __init omap_i2c_nr_ports(void) ports = 2; else if (cpu_is_omap34xx()) ports = 3; + else if (cpu_is_omap44xx()) + ports = 4; return ports; } -static int __init omap_i2c_add_bus(int bus_id) +/* Shared between omap2 and 3 */ +static resource_size_t omap2_i2c_irq[3] __initdata = { + INT_24XX_I2C1_IRQ, + INT_24XX_I2C2_IRQ, + INT_34XX_I2C3_IRQ, +}; + +static resource_size_t omap4_i2c_irq[4] __initdata = { + OMAP44XX_IRQ_I2C1, + OMAP44XX_IRQ_I2C2, + OMAP44XX_IRQ_I2C3, + OMAP44XX_IRQ_I2C4, +}; + +static inline int omap1_i2c_add_bus(struct platform_device *pdev, int bus_id) { - struct platform_device *pdev; struct omap_i2c_bus_platform_data *pd; struct resource *res; - resource_size_t base, irq; - pdev = &omap_i2c_devices[bus_id - 1]; pd = pdev->dev.platform_data; + res = pdev->resource; + res[0].start = OMAP1_I2C_BASE; + res[0].end = res[0].start + OMAP_I2C_SIZE; + res[1].start = INT_I2C; + omap1_i2c_mux_pins(bus_id); + + return platform_device_register(pdev); +} + +static inline int omap2_i2c_add_bus(struct platform_device *pdev, int bus_id) +{ + struct resource *res; + resource_size_t *irq; + + res = pdev->resource; + + if (!cpu_is_omap44xx()) + irq = omap2_i2c_irq; + else + irq = omap4_i2c_irq; + if (bus_id == 1) { - res = pdev->resource; - if (cpu_class_is_omap1()) { - base = OMAP1_I2C_BASE; - irq = INT_I2C; - } else { - base = OMAP2_I2C_BASE1; - irq = INT_24XX_I2C1_IRQ; - } - res[0].start = base; - res[0].end = base + OMAP_I2C_SIZE; - res[1].start = irq; + res[0].start = OMAP2_I2C_BASE1; + res[0].end = res[0].start + OMAP_I2C_SIZE; } - if (cpu_class_is_omap1()) - omap1_i2c_mux_pins(bus_id); - if (cpu_class_is_omap2()) - omap2_i2c_mux_pins(bus_id); + res[1].start = irq[bus_id - 1]; + omap2_i2c_mux_pins(bus_id); /* * When waiting for completion of a i2c transfer, we need to @@ -134,12 +164,28 @@ static int __init omap_i2c_add_bus(int bus_id) * ensure quick enough wakeup from idle, when transfer * completes. */ - if (cpu_is_omap34xx()) + if (cpu_is_omap34xx()) { + struct omap_i2c_bus_platform_data *pd; + + pd = pdev->dev.platform_data; pd->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat; + } return platform_device_register(pdev); } +static int __init omap_i2c_add_bus(int bus_id) +{ + struct platform_device *pdev; + + pdev = &omap_i2c_devices[bus_id - 1]; + + if (cpu_class_is_omap1()) + return omap1_i2c_add_bus(pdev, bus_id); + else + return omap2_i2c_add_bus(pdev, bus_id); +} + /** * omap_i2c_bus_setup - Process command line options for the I2C bus speed * @str: String of options diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h index 34f7fa9ad4c0..dfc472ca0cc4 100644 --- a/arch/arm/plat-omap/include/plat/clock.h +++ b/arch/arm/plat-omap/include/plat/clock.h @@ -196,15 +196,15 @@ extern struct clk dummy_ck; #define INVERT_ENABLE (1 << 4) /* 0 enables, 1 disables */ /* Clksel_rate flags */ -#define DEFAULT_RATE (1 << 0) -#define RATE_IN_242X (1 << 1) -#define RATE_IN_243X (1 << 2) -#define RATE_IN_343X (1 << 3) /* rates common to all 343X */ -#define RATE_IN_3430ES2 (1 << 4) /* 3430ES2 rates only */ -#define RATE_IN_36XX (1 << 5) -#define RATE_IN_4430 (1 << 6) +#define RATE_IN_242X (1 << 0) +#define RATE_IN_243X (1 << 1) +#define RATE_IN_3XXX (1 << 2) /* rates common to all OMAP3 */ +#define RATE_IN_3430ES2 (1 << 3) /* 3430ES2 rates only */ +#define RATE_IN_36XX (1 << 4) +#define RATE_IN_4430 (1 << 5) #define RATE_IN_24XX (RATE_IN_242X | RATE_IN_243X) +#define RATE_IN_3430ES2PLUS (RATE_IN_3430ES2 | RATE_IN_36XX) #endif diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h index 7556e271942e..d265018f5e6b 100644 --- a/arch/arm/plat-omap/include/plat/common.h +++ b/arch/arm/plat-omap/include/plat/common.h @@ -31,9 +31,6 @@ struct sys_timer; -/* used by omap-smp.c and board-4430sdp.c */ -extern void __iomem *gic_cpu_base_addr; - extern void omap_map_common_io(void); extern struct sys_timer omap_timer; diff --git a/arch/arm/plat-omap/include/plat/control.h b/arch/arm/plat-omap/include/plat/control.h index a56deee97676..131bf405c2f6 100644 --- a/arch/arm/plat-omap/include/plat/control.h +++ b/arch/arm/plat-omap/include/plat/control.h @@ -207,6 +207,9 @@ /* 44xx control status register offset */ #define OMAP44XX_CONTROL_STATUS 0x2c4 +/* 44xx-only CONTROL_GENERAL register offsets */ +#define OMAP44XX_CONTROL_MMC1 0x628 +#define OMAP44XX_CONTROL_PBIAS_LITE 0x600 /* * REVISIT: This list of registers is not comprehensive - there are more * that should be added. @@ -252,6 +255,23 @@ #define OMAP2_PBIASLITEPWRDNZ0 (1 << 1) #define OMAP2_PBIASLITEVMODE0 (1 << 0) +/* CONTROL_PBIAS_LITE bits for OMAP4 */ +#define OMAP4_MMC1_PWRDNZ (1 << 26) +#define OMAP4_MMC1_PBIASLITE_HIZ_MODE (1 << 25) +#define OMAP4_MMC1_PBIASLITE_SUPPLY_HI_OUT (1 << 24) +#define OMAP4_MMC1_PBIASLITE_VMODE_ERROR (1 << 23) +#define OMAP4_MMC1_PBIASLITE_PWRDNZ (1 << 22) +#define OMAP4_MMC1_PBIASLITE_VMODE (1 << 21) +#define OMAP4_USBC1_ICUSB_PWRDNZ (1 << 20) + +#define OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP0 (1 << 31) +#define OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP1 (1 << 30) +#define OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP2 (1 << 29) +#define OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP3 (1 << 28) +#define OMAP4_CONTROL_SDMMC1_DR0_SPEEDCTRL (1 << 27) +#define OMAP4_CONTROL_SDMMC1_DR1_SPEEDCTRL (1 << 26) +#define OMAP4_CONTROL_SDMMC1_DR2_SPEEDCTRL (1 << 25) + /* CONTROL_PROG_IO1 bits */ #define OMAP3630_PRG_SDMMC1_SPEEDCTRL (1 << 20) diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index de7c54731cbe..de1c604962eb 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h @@ -72,8 +72,8 @@ IH_GPIO_BASE + (nr)) extern int omap_gpio_init(void); /* Call from board init only */ -extern void omap2_gpio_prepare_for_retention(void); -extern void omap2_gpio_resume_after_retention(void); +extern void omap2_gpio_prepare_for_idle(int power_state); +extern void omap2_gpio_resume_after_idle(void); extern void omap_set_gpio_debounce(int gpio, int enable); extern void omap_set_gpio_debounce_time(int gpio, int enable); extern void omap_gpio_save_context(void); diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h index 401701977dbb..c01d9f08a198 100644 --- a/arch/arm/plat-omap/include/plat/irqs.h +++ b/arch/arm/plat-omap/include/plat/irqs.h @@ -428,4 +428,8 @@ void omap3_intc_resume_idle(void); #include <mach/hardware.h> +#ifdef CONFIG_FIQ +#define FIQ_START 1024 +#endif + #endif diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h index a1bac07c89eb..c835f1e994c6 100644 --- a/arch/arm/plat-omap/include/plat/mmc.h +++ b/arch/arm/plat-omap/include/plat/mmc.h @@ -102,6 +102,10 @@ struct omap_mmc_platform_data { /* Regulator off remapped to sleep */ unsigned vcc_aux_disable_is_sleep:1; + /* we can put the features above into this variable */ +#define HSMMC_HAS_PBIAS (1 << 0) + unsigned features; + int switch_pin; /* gpio (card detect) */ int gpio_wp; /* gpio (write protect) */ diff --git a/arch/arm/plat-omap/include/plat/multi.h b/arch/arm/plat-omap/include/plat/multi.h index f235d32cd942..ffd909fa5287 100644 --- a/arch/arm/plat-omap/include/plat/multi.h +++ b/arch/arm/plat-omap/include/plat/multi.h @@ -61,9 +61,9 @@ # define OMAP_NAME omap16xx # endif #endif -#if (defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)) +#ifdef CONFIG_ARCH_OMAP2PLUS # if (defined(OMAP_NAME) || defined(MULTI_OMAP1)) -# error "OMAP1 and OMAP2 can't be selected at the same time" +# error "OMAP1 and OMAP2PLUS can't be selected at the same time" # endif #endif #ifdef CONFIG_ARCH_OMAP2420 @@ -82,12 +82,20 @@ # define OMAP_NAME omap2430 # endif #endif -#ifdef CONFIG_ARCH_OMAP3430 +#ifdef CONFIG_ARCH_OMAP3 # ifdef OMAP_NAME # undef MULTI_OMAP2 # define MULTI_OMAP2 # else -# define OMAP_NAME omap3430 +# define OMAP_NAME omap3 +# endif +#endif +#ifdef CONFIG_ARCH_OMAP4 +# ifdef OMAP_NAME +# undef MULTI_OMAP2 +# define MULTI_OMAP2 +# else +# define OMAP_NAME omap4 # endif #endif diff --git a/arch/arm/plat-omap/include/plat/omap44xx.h b/arch/arm/plat-omap/include/plat/omap44xx.h index b3ef1a7f53cc..8b3f12ff5cbc 100644 --- a/arch/arm/plat-omap/include/plat/omap44xx.h +++ b/arch/arm/plat-omap/include/plat/omap44xx.h @@ -30,6 +30,7 @@ #define OMAP4430_CM_BASE OMAP4430_CM1_BASE #define OMAP4430_CM2_BASE 0x4a008000 #define OMAP4430_PRM_BASE 0x4a306000 +#define OMAP4430_PRCM_MPU_BASE 0x48243000 #define OMAP44XX_GPMC_BASE 0x50000000 #define OMAP443X_SCM_BASE 0x4a002000 #define OMAP443X_CTRL_BASE 0x4a100000 @@ -48,5 +49,8 @@ #define OMAP44XX_MAILBOX_BASE (L4_44XX_BASE + 0xF4000) #define OMAP44XX_HSUSB_OTG_BASE (L4_44XX_BASE + 0xAB000) +#define OMAP4_MMU1_BASE 0x55082000 +#define OMAP4_MMU2_BASE 0x4A066000 + #endif /* __ASM_ARCH_OMAP44XX_H */ diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index 36d6ea56ab51..0eccc09ac4a9 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -176,9 +176,8 @@ struct omap_hwmod_addr_space { #define OCP_USER_SDMA (1 << 1) /* omap_hwmod_ocp_if.flags bits */ -#define OCPIF_HAS_IDLEST (1 << 0) -#define OCPIF_SWSUP_IDLE (1 << 1) -#define OCPIF_CAN_BURST (1 << 2) +#define OCPIF_SWSUP_IDLE (1 << 0) +#define OCPIF_CAN_BURST (1 << 1) /** * struct omap_hwmod_ocp_if - OCP interface data @@ -327,14 +326,12 @@ struct omap_hwmod_omap2_prcm { /** * struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data - * @module_offs: PRCM submodule offset from the start of the PRM/CM1/CM2 - * @device_offs: device register offset from @module_offs + * @clkctrl_reg: PRCM address of the clock control register * @submodule_wkdep_bit: bit shift of the WKDEP range */ struct omap_hwmod_omap4_prcm { - u32 module_offs; - u16 device_offs; - u8 submodule_wkdep_bit; + void __iomem *clkctrl_reg; + u8 submodule_wkdep_bit; }; @@ -353,6 +350,8 @@ struct omap_hwmod_omap4_prcm { * when module is enabled, rather than the default, which is to * enable autoidle * HWMOD_SET_DEFAULT_CLOCKACT: program CLOCKACTIVITY bits at startup + * HWMOD_NO_IDLEST : this module does not have idle status - this is the case + * only for few initiator modules on OMAP2 & 3. */ #define HWMOD_SWSUP_SIDLE (1 << 0) #define HWMOD_SWSUP_MSTANDBY (1 << 1) @@ -360,6 +359,7 @@ struct omap_hwmod_omap4_prcm { #define HWMOD_INIT_NO_IDLE (1 << 3) #define HWMOD_NO_OCP_AUTOIDLE (1 << 4) #define HWMOD_SET_DEFAULT_CLOCKACT (1 << 5) +#define HWMOD_NO_IDLEST (1 << 6) /* * omap_hwmod._int_flags definitions diff --git a/arch/arm/plat-omap/include/plat/powerdomain.h b/arch/arm/plat-omap/include/plat/powerdomain.h index d82b2c00d4f1..fb6ec74fe39e 100644 --- a/arch/arm/plat-omap/include/plat/powerdomain.h +++ b/arch/arm/plat-omap/include/plat/powerdomain.h @@ -31,6 +31,7 @@ #define PWRDM_MAX_PWRSTS 4 /* Powerdomain allowable state bitfields */ +#define PWRSTS_ON (1 << PWRDM_POWER_ON) #define PWRSTS_OFF_ON ((1 << PWRDM_POWER_OFF) | \ (1 << PWRDM_POWER_ON)) @@ -49,6 +50,12 @@ * in MEM bank 1 position. This is * true for OMAP3430 */ +#define PWRDM_HAS_LOWPOWERSTATECHANGE (1 << 2) /* + * support to transition from a + * sleep state to a lower sleep + * state without waking up the + * powerdomain + */ /* * Number of memory banks that are power-controllable. On OMAP4430, the diff --git a/arch/arm/plat-omap/include/plat/serial.h b/arch/arm/plat-omap/include/plat/serial.h index 83dce4c4f7e6..19145f5c32ba 100644 --- a/arch/arm/plat-omap/include/plat/serial.h +++ b/arch/arm/plat-omap/include/plat/serial.h @@ -15,6 +15,20 @@ #include <linux/init.h> +/* + * Memory entry used for the DEBUG_LL UART configuration. See also + * uncompress.h and debug-macro.S. + * + * Note that using a memory location for storing the UART configuration + * has at least two limitations: + * + * 1. Kernel uncompress code cannot overlap OMAP_UART_INFO as the + * uncompress code could then partially overwrite itself + * 2. We assume printascii is called at least once before paging_init, + * and addruart has a chance to read OMAP_UART_INFO + */ +#define OMAP_UART_INFO (PHYS_OFFSET + 0x3ffc) + /* OMAP1 serial ports */ #define OMAP1_UART1_BASE 0xfffb0000 #define OMAP1_UART2_BASE 0xfffb0800 @@ -39,7 +53,7 @@ /* External port on Zoom2/3 */ #define ZOOM_UART_BASE 0x10000000 -#define ZOOM_UART_VIRT 0xfb000000 +#define ZOOM_UART_VIRT 0xfa400000 #define OMAP_PORT_SHIFT 2 #define OMAP7XX_PORT_SHIFT 0 diff --git a/arch/arm/plat-omap/include/plat/uncompress.h b/arch/arm/plat-omap/include/plat/uncompress.h index 81d9ec540fcf..bbedd71943f6 100644 --- a/arch/arm/plat-omap/include/plat/uncompress.h +++ b/arch/arm/plat-omap/include/plat/uncompress.h @@ -20,27 +20,21 @@ #include <linux/types.h> #include <linux/serial_reg.h> +#include <asm/memory.h> #include <asm/mach-types.h> #include <plat/serial.h> -static volatile u8 *uart1_base; -static int uart1_shift; - static volatile u8 *uart_base; static int uart_shift; /* - * Store the DEBUG_LL uart number into UART1 scratchpad register. + * Store the DEBUG_LL uart number into memory. * See also debug-macro.S, and serial.c for related code. - * - * Please note that we currently assume that: - * - UART1 clocks are enabled for register access - * - UART1 scratchpad register can be used */ -static void set_uart1_scratchpad(unsigned char port) +static void set_omap_uart_info(unsigned char port) { - uart1_base[UART_SCR << uart1_shift] = port; + *(volatile u32 *)OMAP_UART_INFO = port; } static void putc(int c) @@ -60,42 +54,38 @@ static inline void flush(void) /* * Macros to configure UART1 and debug UART */ -#define _DEBUG_LL_ENTRY(mach, uart1_phys, uart1_shft, \ - dbg_uart, dbg_shft, dbg_id) \ +#define _DEBUG_LL_ENTRY(mach, dbg_uart, dbg_shft, dbg_id) \ if (machine_is_##mach()) { \ - uart1_base = (volatile u8 *)(uart1_phys); \ - uart1_shift = (uart1_shft); \ uart_base = (volatile u8 *)(dbg_uart); \ uart_shift = (dbg_shft); \ port = (dbg_id); \ - set_uart1_scratchpad(port); \ + set_omap_uart_info(port); \ break; \ } #define DEBUG_LL_OMAP7XX(p, mach) \ - _DEBUG_LL_ENTRY(mach, OMAP1_UART1_BASE, OMAP7XX_PORT_SHIFT, \ - OMAP1_UART##p##_BASE, OMAP7XX_PORT_SHIFT, OMAP1UART##p) + _DEBUG_LL_ENTRY(mach, OMAP1_UART##p##_BASE, OMAP7XX_PORT_SHIFT, \ + OMAP1UART##p) #define DEBUG_LL_OMAP1(p, mach) \ - _DEBUG_LL_ENTRY(mach, OMAP1_UART1_BASE, OMAP_PORT_SHIFT, \ - OMAP1_UART##p##_BASE, OMAP_PORT_SHIFT, OMAP1UART##p) + _DEBUG_LL_ENTRY(mach, OMAP1_UART##p##_BASE, OMAP_PORT_SHIFT, \ + OMAP1UART##p) #define DEBUG_LL_OMAP2(p, mach) \ - _DEBUG_LL_ENTRY(mach, OMAP2_UART1_BASE, OMAP_PORT_SHIFT, \ - OMAP2_UART##p##_BASE, OMAP_PORT_SHIFT, OMAP2UART##p) + _DEBUG_LL_ENTRY(mach, OMAP2_UART##p##_BASE, OMAP_PORT_SHIFT, \ + OMAP2UART##p) #define DEBUG_LL_OMAP3(p, mach) \ - _DEBUG_LL_ENTRY(mach, OMAP3_UART1_BASE, OMAP_PORT_SHIFT, \ - OMAP3_UART##p##_BASE, OMAP_PORT_SHIFT, OMAP3UART##p) + _DEBUG_LL_ENTRY(mach, OMAP3_UART##p##_BASE, OMAP_PORT_SHIFT, \ + OMAP3UART##p) #define DEBUG_LL_OMAP4(p, mach) \ - _DEBUG_LL_ENTRY(mach, OMAP4_UART1_BASE, OMAP_PORT_SHIFT, \ - OMAP4_UART##p##_BASE, OMAP_PORT_SHIFT, OMAP4UART##p) + _DEBUG_LL_ENTRY(mach, OMAP4_UART##p##_BASE, OMAP_PORT_SHIFT, \ + OMAP4UART##p) /* Zoom2/3 shift is different for UART1 and external port */ #define DEBUG_LL_ZOOM(mach) \ - _DEBUG_LL_ENTRY(mach, OMAP2_UART1_BASE, OMAP_PORT_SHIFT, \ - ZOOM_UART_BASE, ZOOM_PORT_SHIFT, ZOOM_UART) + _DEBUG_LL_ENTRY(mach, ZOOM_UART_BASE, ZOOM_PORT_SHIFT, ZOOM_UART) static inline void __arch_decomp_setup(unsigned long arch_id) { diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c index 0e137663349c..bc094dbacee6 100644 --- a/arch/arm/plat-omap/iommu.c +++ b/arch/arm/plat-omap/iommu.c @@ -25,6 +25,11 @@ #include "iopgtable.h" +#define for_each_iotlb_cr(obj, n, __i, cr) \ + for (__i = 0; \ + (__i < (n)) && (cr = __iotlb_read_cr((obj), __i), true); \ + __i++) + /* accommodate the difference between omap1 and omap2/3 */ static const struct iommu_functions *arch_iommu; @@ -172,15 +177,12 @@ static void iotlb_lock_get(struct iommu *obj, struct iotlb_lock *l) l->base = MMU_LOCK_BASE(val); l->vict = MMU_LOCK_VICT(val); - BUG_ON(l->base != 0); /* Currently no preservation is used */ } static void iotlb_lock_set(struct iommu *obj, struct iotlb_lock *l) { u32 val; - BUG_ON(l->base != 0); /* Currently no preservation is used */ - val = (l->base << MMU_LOCK_BASE_SHIFT); val |= (l->vict << MMU_LOCK_VICT_SHIFT); @@ -214,6 +216,20 @@ static inline ssize_t iotlb_dump_cr(struct iommu *obj, struct cr_regs *cr, return arch_iommu->dump_cr(obj, cr, buf); } +/* only used in iotlb iteration for-loop */ +static struct cr_regs __iotlb_read_cr(struct iommu *obj, int n) +{ + struct cr_regs cr; + struct iotlb_lock l; + + iotlb_lock_get(obj, &l); + l.vict = n; + iotlb_lock_set(obj, &l); + iotlb_read_cr(obj, &cr); + + return cr; +} + /** * load_iotlb_entry - Set an iommu tlb entry * @obj: target iommu @@ -221,7 +237,6 @@ static inline ssize_t iotlb_dump_cr(struct iommu *obj, struct cr_regs *cr, **/ int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e) { - int i; int err = 0; struct iotlb_lock l; struct cr_regs *cr; @@ -231,21 +246,30 @@ int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e) clk_enable(obj->clk); - for (i = 0; i < obj->nr_tlb_entries; i++) { + iotlb_lock_get(obj, &l); + if (l.base == obj->nr_tlb_entries) { + dev_warn(obj->dev, "%s: preserve entries full\n", __func__); + err = -EBUSY; + goto out; + } + if (!e->prsvd) { + int i; struct cr_regs tmp; + for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, tmp) + if (!iotlb_cr_valid(&tmp)) + break; + + if (i == obj->nr_tlb_entries) { + dev_dbg(obj->dev, "%s: full: no entry\n", __func__); + err = -EBUSY; + goto out; + } + iotlb_lock_get(obj, &l); - l.vict = i; + } else { + l.vict = l.base; iotlb_lock_set(obj, &l); - iotlb_read_cr(obj, &tmp); - if (!iotlb_cr_valid(&tmp)) - break; - } - - if (i == obj->nr_tlb_entries) { - dev_dbg(obj->dev, "%s: full: no entry\n", __func__); - err = -EBUSY; - goto out; } cr = iotlb_alloc_cr(obj, e); @@ -257,9 +281,11 @@ int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e) iotlb_load_cr(obj, cr); kfree(cr); + if (e->prsvd) + l.base++; /* increment victim for next tlb load */ if (++l.vict == obj->nr_tlb_entries) - l.vict = 0; + l.vict = l.base; iotlb_lock_set(obj, &l); out: clk_disable(obj->clk); @@ -276,20 +302,15 @@ EXPORT_SYMBOL_GPL(load_iotlb_entry); **/ void flush_iotlb_page(struct iommu *obj, u32 da) { - struct iotlb_lock l; int i; + struct cr_regs cr; clk_enable(obj->clk); - for (i = 0; i < obj->nr_tlb_entries; i++) { - struct cr_regs cr; + for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, cr) { u32 start; size_t bytes; - iotlb_lock_get(obj, &l); - l.vict = i; - iotlb_lock_set(obj, &l); - iotlb_read_cr(obj, &cr); if (!iotlb_cr_valid(&cr)) continue; @@ -299,7 +320,6 @@ void flush_iotlb_page(struct iommu *obj, u32 da) if ((start <= da) && (da < start + bytes)) { dev_dbg(obj->dev, "%s: %08x<=%08x(%x)\n", __func__, start, da, bytes); - iotlb_load_cr(obj, &cr); iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY); } } @@ -370,26 +390,19 @@ EXPORT_SYMBOL_GPL(iommu_dump_ctx); static int __dump_tlb_entries(struct iommu *obj, struct cr_regs *crs, int num) { int i; - struct iotlb_lock saved, l; + struct iotlb_lock saved; + struct cr_regs tmp; struct cr_regs *p = crs; clk_enable(obj->clk); - iotlb_lock_get(obj, &saved); - memcpy(&l, &saved, sizeof(saved)); - for (i = 0; i < num; i++) { - struct cr_regs tmp; - - iotlb_lock_get(obj, &l); - l.vict = i; - iotlb_lock_set(obj, &l); - iotlb_read_cr(obj, &tmp); + for_each_iotlb_cr(obj, num, i, tmp) { if (!iotlb_cr_valid(&tmp)) continue; - *p++ = tmp; } + iotlb_lock_set(obj, &saved); clk_disable(obj->clk); @@ -503,6 +516,12 @@ static int iopgd_alloc_section(struct iommu *obj, u32 da, u32 pa, u32 prot) { u32 *iopgd = iopgd_offset(obj, da); + if ((da | pa) & ~IOSECTION_MASK) { + dev_err(obj->dev, "%s: %08x:%08x should aligned on %08lx\n", + __func__, da, pa, IOSECTION_SIZE); + return -EINVAL; + } + *iopgd = (pa & IOSECTION_MASK) | prot | IOPGD_SECTION; flush_iopgd_range(iopgd, iopgd); return 0; @@ -513,6 +532,12 @@ static int iopgd_alloc_super(struct iommu *obj, u32 da, u32 pa, u32 prot) u32 *iopgd = iopgd_offset(obj, da); int i; + if ((da | pa) & ~IOSUPER_MASK) { + dev_err(obj->dev, "%s: %08x:%08x should aligned on %08lx\n", + __func__, da, pa, IOSUPER_SIZE); + return -EINVAL; + } + for (i = 0; i < 16; i++) *(iopgd + i) = (pa & IOSUPER_MASK) | prot | IOPGD_SUPER; flush_iopgd_range(iopgd, iopgd + 15); @@ -542,6 +567,12 @@ static int iopte_alloc_large(struct iommu *obj, u32 da, u32 pa, u32 prot) u32 *iopte = iopte_alloc(obj, iopgd, da); int i; + if ((da | pa) & ~IOLARGE_MASK) { + dev_err(obj->dev, "%s: %08x:%08x should aligned on %08lx\n", + __func__, da, pa, IOLARGE_SIZE); + return -EINVAL; + } + if (IS_ERR(iopte)) return PTR_ERR(iopte); diff --git a/arch/arm/plat-omap/iovmm.c b/arch/arm/plat-omap/iovmm.c index 65c6d1ff7237..e43983ba59c5 100644 --- a/arch/arm/plat-omap/iovmm.c +++ b/arch/arm/plat-omap/iovmm.c @@ -287,16 +287,19 @@ static struct iovm_struct *alloc_iovm_area(struct iommu *obj, u32 da, prev_end = 0; list_for_each_entry(tmp, &obj->mmap, list) { - if ((prev_end <= start) && (start + bytes < tmp->da_start)) + if (prev_end >= start) + break; + + if (start + bytes < tmp->da_start) goto found; if (flags & IOVMF_DA_ANON) - start = roundup(tmp->da_end, alignement); + start = roundup(tmp->da_end + 1, alignement); prev_end = tmp->da_end; } - if ((start >= prev_end) && (ULONG_MAX - start >= bytes)) + if ((start > prev_end) && (ULONG_MAX - start >= bytes)) goto found; dev_dbg(obj->dev, "%s: no space to fit %08x(%x) flags: %08x\n", diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c index 0f5197479513..f899603051ac 100644 --- a/arch/arm/plat-omap/omap_device.c +++ b/arch/arm/plat-omap/omap_device.c @@ -2,10 +2,10 @@ * omap_device implementation * * Copyright (C) 2009 Nokia Corporation - * Paul Walmsley + * Paul Walmsley, Kevin Hilman * * Developed in collaboration with (alphabetical order): Benoit - * Cousson, Kevin Hilman, Tony Lindgren, Rajendra Nayak, Vikram + * Cousson, Thara Gopinath, Tony Lindgren, Rajendra Nayak, Vikram * Pandita, Sakari Poussa, Anand Sawant, Santosh Shilimkar, Richard * Woodruff * diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index 51f4dfb82e2b..226b2e858d6c 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -437,6 +437,20 @@ static inline int omap34xx_sram_init(void) } #endif +#ifdef CONFIG_ARCH_OMAP4 +int __init omap44xx_sram_init(void) +{ + printk(KERN_ERR "FIXME: %s not implemented\n", __func__); + + return -ENODEV; +} +#else +static inline int omap44xx_sram_init(void) +{ + return 0; +} +#endif + int __init omap_sram_init(void) { omap_detect_sram(); @@ -451,7 +465,7 @@ int __init omap_sram_init(void) else if (cpu_is_omap34xx()) omap34xx_sram_init(); else if (cpu_is_omap44xx()) - omap34xx_sram_init(); /* FIXME: */ + omap44xx_sram_init(); return 0; } |