diff options
Diffstat (limited to 'arch/arm/plat-omap')
39 files changed, 747 insertions, 1322 deletions
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 78b49a626d06..e39a417a368d 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -1,6 +1,6 @@ if ARCH_OMAP -menu "TI OMAP Implementations" +menu "TI OMAP Common Features" config ARCH_OMAP_OTG bool @@ -21,24 +21,6 @@ config ARCH_OMAP2PLUS help "Systems based on omap24xx, omap34xx or omap44xx" -config ARCH_OMAP2 - bool "TI OMAP2" - depends on ARCH_OMAP2PLUS - select CPU_V6 - -config ARCH_OMAP3 - bool "TI OMAP3" - depends on ARCH_OMAP2PLUS - select CPU_V7 - select USB_ARCH_HAS_EHCI - select ARM_L1_CACHE_SHIFT_6 - -config ARCH_OMAP4 - bool "TI OMAP4" - depends on ARCH_OMAP2PLUS - select CPU_V7 - select ARM_GIC - endchoice comment "OMAP Feature Selections" @@ -51,7 +33,7 @@ config OMAP_DEBUG_DEVICES config OMAP_DEBUG_LEDS bool depends on OMAP_DEBUG_DEVICES - default y if LEDS || LEDS_OMAP_DEBUG + default y if LEDS config OMAP_RESET_CLOCKS bool "Reset unused clocks during boot" @@ -106,6 +88,15 @@ config OMAP_MBOX_FWK Say Y here if you want to use OMAP Mailbox framework support for DSP, IVA1.0 and IVA2 in OMAP1/2/3. +config OMAP_MBOX_KFIFO_SIZE + int "Mailbox kfifo default buffer size (bytes)" + depends on OMAP_MBOX_FWK + default 256 + help + Specify the default size of mailbox's kfifo buffers (bytes). + This can also be changed at runtime (via the mbox_kfifo_size + module parameter). + config OMAP_IOMMU tristate @@ -120,7 +111,7 @@ config OMAP_IOMMU_DEBUG choice prompt "System timer" - default OMAP_MPU_TIMER + default OMAP_32K_TIMER if !ARCH_OMAP15XX config OMAP_MPU_TIMER bool "Use mpu timer" diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index 98f01910c2cf..9405831b746a 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o # omap_device support (OMAP2+ only at the moment) obj-$(CONFIG_ARCH_OMAP2) += omap_device.o obj-$(CONFIG_ARCH_OMAP3) += omap_device.o +obj-$(CONFIG_ARCH_OMAP4) += omap_device.o obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c index 219c01e82bc5..3008e7104487 100644 --- a/arch/arm/plat-omap/common.c +++ b/arch/arm/plat-omap/common.c @@ -22,6 +22,7 @@ #include <linux/serial_reg.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/omapfb.h> #include <mach/hardware.h> #include <asm/system.h> @@ -35,6 +36,7 @@ #include <plat/mux.h> #include <plat/fpga.h> #include <plat/serial.h> +#include <plat/vram.h> #include <plat/clock.h> @@ -81,6 +83,12 @@ const void *omap_get_var_config(u16 tag, size_t *len) } EXPORT_SYMBOL(omap_get_var_config); +void __init omap_reserve(void) +{ + omapfb_reserve_sdram_memblock(); + omap_vram_reserve_sdram_memblock(); +} + /* * 32KHz clocksource ... always available, on pretty most chips except * OMAP 730 and 1510. Other timers could be used as clocksources, with @@ -309,18 +317,18 @@ static struct omap_globals omap3_globals = { .uart1_phys = OMAP3_UART1_BASE, .uart2_phys = OMAP3_UART2_BASE, .uart3_phys = OMAP3_UART3_BASE, + .uart4_phys = OMAP3_UART4_BASE, /* Only on 3630 */ }; -void __init omap2_set_globals_343x(void) +void __init omap2_set_globals_3xxx(void) { __omap2_set_globals(&omap3_globals); } -void __init omap2_set_globals_36xx(void) +void __init omap3_map_io(void) { - omap3_globals.uart4_phys = OMAP3_UART4_BASE; - - __omap2_set_globals(&omap3_globals); + omap2_set_globals_3xxx(); + omap34xx_map_common_io(); } #endif diff --git a/arch/arm/plat-omap/debug-leds.c b/arch/arm/plat-omap/debug-leds.c index 53fcef7c5201..fc05b1022602 100644 --- a/arch/arm/plat-omap/debug-leds.c +++ b/arch/arm/plat-omap/debug-leds.c @@ -39,7 +39,7 @@ static struct h2p2_dbg_fpga __iomem *fpga; static u16 led_state, hw_led_state; -#ifdef CONFIG_LEDS_OMAP_DEBUG +#ifdef CONFIG_OMAP_DEBUG_LEDS #define new_led_api() 1 #else #define new_led_api() 0 diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index 95677d17cd1c..d1920be7833b 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -24,135 +24,13 @@ #include <plat/control.h> #include <plat/board.h> #include <plat/mmc.h> -#include <plat/mux.h> #include <mach/gpio.h> #include <plat/menelaus.h> #include <plat/mcbsp.h> -#include <plat/dsp_common.h> #include <plat/omap44xx.h> -#if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE) - -static struct dsp_platform_data dsp_pdata = { - .kdev_list = LIST_HEAD_INIT(dsp_pdata.kdev_list), -}; - -static struct resource omap_dsp_resources[] = { - { - .name = "dsp_mmu", - .start = -1, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device omap_dsp_device = { - .name = "dsp", - .id = -1, - .num_resources = ARRAY_SIZE(omap_dsp_resources), - .resource = omap_dsp_resources, - .dev = { - .platform_data = &dsp_pdata, - }, -}; - -static inline void omap_init_dsp(void) -{ - struct resource *res; - int irq; - - if (cpu_is_omap15xx()) - irq = INT_1510_DSP_MMU; - else if (cpu_is_omap16xx()) - irq = INT_1610_DSP_MMU; - else if (cpu_is_omap24xx()) - irq = INT_24XX_DSP_MMU; - - res = platform_get_resource_byname(&omap_dsp_device, - IORESOURCE_IRQ, "dsp_mmu"); - res->start = irq; - - platform_device_register(&omap_dsp_device); -} - -int dsp_kfunc_device_register(struct dsp_kfunc_device *kdev) -{ - static DEFINE_MUTEX(dsp_pdata_lock); - - spin_lock_init(&kdev->lock); - - mutex_lock(&dsp_pdata_lock); - list_add_tail(&kdev->entry, &dsp_pdata.kdev_list); - mutex_unlock(&dsp_pdata_lock); - - return 0; -} -EXPORT_SYMBOL(dsp_kfunc_device_register); - -#else -static inline void omap_init_dsp(void) { } -#endif /* CONFIG_OMAP_DSP */ - /*-------------------------------------------------------------------------*/ -#if defined(CONFIG_KEYBOARD_OMAP) || defined(CONFIG_KEYBOARD_OMAP_MODULE) - -static void omap_init_kp(void) -{ - /* 2430 and 34xx keypad is on TWL4030 */ - if (cpu_is_omap2430() || cpu_is_omap34xx()) - return; - if (machine_is_omap_h2() || machine_is_omap_h3()) { - omap_cfg_reg(F18_1610_KBC0); - omap_cfg_reg(D20_1610_KBC1); - omap_cfg_reg(D19_1610_KBC2); - omap_cfg_reg(E18_1610_KBC3); - omap_cfg_reg(C21_1610_KBC4); - - omap_cfg_reg(G18_1610_KBR0); - omap_cfg_reg(F19_1610_KBR1); - omap_cfg_reg(H14_1610_KBR2); - omap_cfg_reg(E20_1610_KBR3); - omap_cfg_reg(E19_1610_KBR4); - omap_cfg_reg(N19_1610_KBR5); - } else if (machine_is_omap_perseus2() || machine_is_omap_fsample()) { - omap_cfg_reg(E2_7XX_KBR0); - omap_cfg_reg(J7_7XX_KBR1); - omap_cfg_reg(E1_7XX_KBR2); - omap_cfg_reg(F3_7XX_KBR3); - omap_cfg_reg(D2_7XX_KBR4); - - omap_cfg_reg(C2_7XX_KBC0); - omap_cfg_reg(D3_7XX_KBC1); - omap_cfg_reg(E4_7XX_KBC2); - omap_cfg_reg(F4_7XX_KBC3); - omap_cfg_reg(E3_7XX_KBC4); - } else if (machine_is_omap_h4()) { - omap_cfg_reg(T19_24XX_KBR0); - omap_cfg_reg(R19_24XX_KBR1); - omap_cfg_reg(V18_24XX_KBR2); - omap_cfg_reg(M21_24XX_KBR3); - omap_cfg_reg(E5__24XX_KBR4); - if (omap_has_menelaus()) { - omap_cfg_reg(B3__24XX_KBR5); - omap_cfg_reg(AA4_24XX_KBC2); - omap_cfg_reg(B13_24XX_KBC6); - } else { - omap_cfg_reg(M18_24XX_KBR5); - omap_cfg_reg(H19_24XX_KBC2); - omap_cfg_reg(N19_24XX_KBC6); - } - omap_cfg_reg(R20_24XX_KBC0); - omap_cfg_reg(M14_24XX_KBC1); - omap_cfg_reg(V17_24XX_KBC3); - omap_cfg_reg(P21_24XX_KBC4); - omap_cfg_reg(L14_24XX_KBC5); - } -} -#else -static inline void omap_init_kp(void) {} -#endif - -/*-------------------------------------------------------------------------*/ #if defined(CONFIG_OMAP_MCBSP) || defined(CONFIG_OMAP_MCBSP_MODULE) static struct platform_device **omap_mcbsp_devices; @@ -419,8 +297,6 @@ static int __init omap_init_devices(void) /* please keep these calls, and their implementations above, * in alphabetical order so they're easier to sort through. */ - omap_init_dsp(); - omap_init_kp(); omap_init_rng(); omap_init_mcpdm(); omap_init_uwire(); diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index f7f571e7987e..ec7eddf9e525 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -290,7 +290,7 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, val = dma_read(CCR(lch)); /* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */ - val &= ~((3 << 19) | 0x1f); + val &= ~((1 << 23) | (3 << 19) | 0x1f); val |= (dma_trigger & ~0x1f) << 14; val |= dma_trigger & 0x1f; @@ -304,11 +304,14 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, else val &= ~(1 << 18); - if (src_or_dst_synch) + if (src_or_dst_synch == OMAP_DMA_DST_SYNC_PREFETCH) { + val &= ~(1 << 24); /* dest synch */ + val |= (1 << 23); /* Prefetch */ + } else if (src_or_dst_synch) { val |= 1 << 24; /* source synch */ - else + } else { val &= ~(1 << 24); /* dest synch */ - + } dma_write(val, CCR(lch)); } diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index c64875f11fac..44bafdab2dce 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -541,11 +541,11 @@ void omap_dm_timer_stop(struct omap_dm_timer *timer) * timer is stopped */ udelay(3500000 / clk_get_rate(timer->fclk) + 1); - /* Ack possibly pending interrupt */ - omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, - OMAP_TIMER_INT_OVERFLOW); #endif } + /* Ack possibly pending interrupt */ + omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, + OMAP_TIMER_INT_OVERFLOW); } EXPORT_SYMBOL_GPL(omap_dm_timer_stop); diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c index d3eea4f47533..0054b9501a53 100644 --- a/arch/arm/plat-omap/fb.c +++ b/arch/arm/plat-omap/fb.c @@ -26,7 +26,7 @@ #include <linux/mm.h> #include <linux/init.h> #include <linux/platform_device.h> -#include <linux/bootmem.h> +#include <linux/memblock.h> #include <linux/io.h> #include <linux/omapfb.h> @@ -171,49 +171,78 @@ static int check_fbmem_region(int region_idx, struct omapfb_mem_region *rg, return 0; } +static int valid_sdram(unsigned long addr, unsigned long size) +{ + struct memblock_property res; + + res.base = addr; + res.size = size; + return !memblock_find(&res) && res.base == addr && res.size == size; +} + +static int reserve_sdram(unsigned long addr, unsigned long size) +{ + if (memblock_is_region_reserved(addr, size)) + return -EBUSY; + if (memblock_reserve(addr, size)) + return -ENOMEM; + return 0; +} + /* * Called from map_io. We need to call to this early enough so that we * can reserve the fixed SDRAM regions before VM could get hold of them. */ -void __init omapfb_reserve_sdram(void) +void __init omapfb_reserve_sdram_memblock(void) { - struct bootmem_data *bdata; - unsigned long sdram_start, sdram_size; - unsigned long reserved; - int i; + unsigned long reserved = 0; + int i; if (config_invalid) return; - bdata = NODE_DATA(0)->bdata; - sdram_start = bdata->node_min_pfn << PAGE_SHIFT; - sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start; - reserved = 0; for (i = 0; ; i++) { - struct omapfb_mem_region rg; + struct omapfb_mem_region rg; if (get_fbmem_region(i, &rg) < 0) break; + if (i == OMAPFB_PLANE_NUM) { - printk(KERN_ERR - "Extraneous FB mem configuration entries\n"); + pr_err("Extraneous FB mem configuration entries\n"); config_invalid = 1; return; } + /* Check if it's our memory type. */ - if (set_fbmem_region_type(&rg, OMAPFB_MEMTYPE_SDRAM, - sdram_start, sdram_size) < 0 || - (rg.type != OMAPFB_MEMTYPE_SDRAM)) + if (rg.type != OMAPFB_MEMTYPE_SDRAM) continue; - BUG_ON(omapfb_config.mem_desc.region[i].size); - if (check_fbmem_region(i, &rg, sdram_start, sdram_size) < 0) { + + /* Check if the region falls within SDRAM */ + if (rg.paddr && !valid_sdram(rg.paddr, rg.size)) + continue; + + if (rg.size == 0) { + pr_err("Zero size for FB region %d\n", i); config_invalid = 1; return; } + if (rg.paddr) { - reserve_bootmem(rg.paddr, rg.size, BOOTMEM_DEFAULT); + if (reserve_sdram(rg.paddr, rg.size)) { + pr_err("Trying to use reserved memory for FB region %d\n", + i); + config_invalid = 1; + return; + } reserved += rg.size; } + + if (omapfb_config.mem_desc.region[i].size) { + pr_err("FB region %d already set\n", i); + config_invalid = 1; + return; + } + omapfb_config.mem_desc.region[i] = rg; configured_regions++; } @@ -359,7 +388,10 @@ static inline int omap_init_fb(void) arch_initcall(omap_init_fb); -void omapfb_reserve_sdram(void) {} +void omapfb_reserve_sdram_memblock(void) +{ +} + unsigned long omapfb_reserve_sram(unsigned long sram_pstart, unsigned long sram_vstart, unsigned long sram_size, @@ -375,7 +407,10 @@ void omapfb_set_platform_data(struct omapfb_platform_data *data) { } -void omapfb_reserve_sdram(void) {} +void omapfb_reserve_sdram_memblock(void) +{ +} + unsigned long omapfb_reserve_sram(unsigned long sram_pstart, unsigned long sram_vstart, unsigned long sram_size, diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 393e9219a5b6..7951eefe1a0e 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -390,7 +390,9 @@ static inline int gpio_valid(int gpio) return 0; if (cpu_is_omap7xx() && gpio < 192) return 0; - if (cpu_is_omap24xx() && gpio < 128) + if (cpu_is_omap2420() && gpio < 128) + return 0; + if (cpu_is_omap2430() && gpio < 160) return 0; if ((cpu_is_omap34xx() || cpu_is_omap44xx()) && gpio < 192) return 0; @@ -673,6 +675,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio, if (cpu_is_omap34xx() || cpu_is_omap44xx()) clk_disable(bank->dbck); } + bank->dbck_enable_mask = val; __raw_writel(val, reg); } diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index eec2b4993c69..a5ce4f0aad35 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -138,6 +138,16 @@ static inline int omap1_i2c_add_bus(struct platform_device *pdev, int bus_id) return platform_device_register(pdev); } +/* + * XXX This function is a temporary compatibility wrapper - only + * needed until the I2C driver can be converted to call + * omap_pm_set_max_dev_wakeup_lat() and handle a return code. + */ +static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t) +{ + omap_pm_set_max_mpu_wakeup_lat(dev, t); +} + static inline int omap2_i2c_add_bus(struct platform_device *pdev, int bus_id) { struct resource *res; @@ -168,7 +178,7 @@ static inline int omap2_i2c_add_bus(struct platform_device *pdev, int bus_id) struct omap_i2c_bus_platform_data *pd; pd = pdev->dev.platform_data; - pd->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat; + pd->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat; } return platform_device_register(pdev); diff --git a/arch/arm/plat-omap/include/plat/board.h b/arch/arm/plat-omap/include/plat/board.h index 5cd622039da0..3cf4fa25ab3d 100644 --- a/arch/arm/plat-omap/include/plat/board.h +++ b/arch/arm/plat-omap/include/plat/board.h @@ -85,6 +85,14 @@ struct omap_usb_config { * 6 == 6 wire unidirectional (or TLL) */ u8 pins[3]; + + struct platform_device *udc_device; + struct platform_device *ohci_device; + struct platform_device *otg_device; + + u32 (*usb0_init)(unsigned nwires, unsigned is_device); + u32 (*usb1_init)(unsigned nwires); + u32 (*usb2_init)(unsigned nwires, unsigned alt_pingroup); }; struct omap_lcd_config { diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h index dfc472ca0cc4..fef4696dcf67 100644 --- a/arch/arm/plat-omap/include/plat/clock.h +++ b/arch/arm/plat-omap/include/plat/clock.h @@ -19,6 +19,22 @@ struct module; struct clk; struct clockdomain; +/** + * struct clkops - some clock function pointers + * @enable: fn ptr that enables the current clock in hardware + * @disable: fn ptr that enables the current clock in hardware + * @find_idlest: function returning the IDLEST register for the clock's IP blk + * @find_companion: function returning the "companion" clk reg for the clock + * + * A "companion" clk is an accompanying clock to the one being queried + * that must be enabled for the IP module connected to the clock to + * become accessible by the hardware. Neither @find_idlest nor + * @find_companion should be needed; that information is IP + * block-specific; the hwmod code has been created to handle this, but + * until hwmod data is ready and drivers have been converted to use PM + * runtime calls in place of clk_enable()/clk_disable(), @find_idlest and + * @find_companion must, unfortunately, remain. + */ struct clkops { int (*enable)(struct clk *); void (*disable)(struct clk *); @@ -30,12 +46,45 @@ struct clkops { #ifdef CONFIG_ARCH_OMAP2PLUS +/* struct clksel_rate.flags possibilities */ +#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) + +/** + * struct clksel_rate - register bitfield values corresponding to clk divisors + * @val: register bitfield value (shifted to bit 0) + * @div: clock divisor corresponding to @val + * @flags: (see "struct clksel_rate.flags possibilities" above) + * + * @val should match the value of a read from struct clk.clksel_reg + * AND'ed with struct clk.clksel_mask, shifted right to bit 0. + * + * @div is the divisor that should be applied to the parent clock's rate + * to produce the current clock's rate. + * + * XXX @flags probably should be replaced with an struct omap_chip. + */ struct clksel_rate { u32 val; u8 div; u8 flags; }; +/** + * struct clksel - available parent clocks, and a pointer to their divisors + * @parent: struct clk * to a possible parent clock + * @rates: available divisors for this parent clock + * + * A struct clksel is always associated with one or more struct clks + * and one or more struct clksel_rates. + */ struct clksel { struct clk *parent; const struct clksel_rate *rates; @@ -116,6 +165,60 @@ struct dpll_data { #endif +/* struct clk.flags possibilities */ +#define ENABLE_REG_32BIT (1 << 0) /* Use 32-bit access */ +#define CLOCK_IDLE_CONTROL (1 << 1) +#define CLOCK_NO_IDLE_PARENT (1 << 2) +#define ENABLE_ON_INIT (1 << 3) /* Enable upon framework init */ +#define INVERT_ENABLE (1 << 4) /* 0 enables, 1 disables */ + +/** + * struct clk - OMAP struct clk + * @node: list_head connecting this clock into the full clock list + * @ops: struct clkops * for this clock + * @name: the name of the clock in the hardware (used in hwmod data and debug) + * @parent: pointer to this clock's parent struct clk + * @children: list_head connecting to the child clks' @sibling list_heads + * @sibling: list_head connecting this clk to its parent clk's @children + * @rate: current clock rate + * @enable_reg: register to write to enable the clock (see @enable_bit) + * @recalc: fn ptr that returns the clock's current rate + * @set_rate: fn ptr that can change the clock's current rate + * @round_rate: fn ptr that can round the clock's current rate + * @init: fn ptr to do clock-specific initialization + * @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg) + * @usecount: number of users that have requested this clock to be enabled + * @fixed_div: when > 0, this clock's rate is its parent's rate / @fixed_div + * @flags: see "struct clk.flags possibilities" above + * @clksel_reg: for clksel clks, register va containing src/divisor select + * @clksel_mask: bitmask in @clksel_reg for the src/divisor selector + * @clksel: for clksel clks, pointer to struct clksel for this clock + * @dpll_data: for DPLLs, pointer to struct dpll_data for this clock + * @clkdm_name: clockdomain name that this clock is contained in + * @clkdm: pointer to struct clockdomain, resolved from @clkdm_name at runtime + * @rate_offset: bitshift for rate selection bitfield (OMAP1 only) + * @src_offset: bitshift for source selection bitfield (OMAP1 only) + * + * XXX @rate_offset, @src_offset should probably be removed and OMAP1 + * clock code converted to use clksel. + * + * XXX @usecount is poorly named. It should be "enable_count" or + * something similar. "users" in the description refers to kernel + * code (core code or drivers) that have called clk_enable() and not + * yet called clk_disable(); the usecount of parent clocks is also + * incremented by the clock code when clk_enable() is called on child + * clocks and decremented by the clock code when clk_disable() is + * called on child clocks. + * + * XXX @clkdm, @usecount, @children, @sibling should be marked for + * internal use only. + * + * @children and @sibling are used to optimize parent-to-child clock + * tree traversals. (child-to-parent traversals use @parent.) + * + * XXX The notion of the clock's current rate probably needs to be + * separated from the clock's target rate. + */ struct clk { struct list_head node; const struct clkops *ops; @@ -129,8 +232,8 @@ struct clk { int (*set_rate)(struct clk *, unsigned long); long (*round_rate)(struct clk *, unsigned long); void (*init)(struct clk *); - __u8 enable_bit; - __s8 usecount; + u8 enable_bit; + s8 usecount; u8 fixed_div; u8 flags; #ifdef CONFIG_ARCH_OMAP2PLUS @@ -141,8 +244,8 @@ struct clk { const char *clkdm_name; struct clockdomain *clkdm; #else - __u8 rate_offset; - __u8 src_offset; + u8 rate_offset; + u8 src_offset; #endif #if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) struct dentry *dent; /* For visible tree hierarchy */ @@ -188,23 +291,4 @@ extern const struct clkops clkops_null; extern struct clk dummy_ck; -/* Clock flags */ -#define ENABLE_REG_32BIT (1 << 0) /* Use 32-bit access */ -#define CLOCK_IDLE_CONTROL (1 << 1) -#define CLOCK_NO_IDLE_PARENT (1 << 2) -#define ENABLE_ON_INIT (1 << 3) /* Enable upon framework init */ -#define INVERT_ENABLE (1 << 4) /* 0 enables, 1 disables */ - -/* Clksel_rate flags */ -#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 d265018f5e6b..9776b41ad76f 100644 --- a/arch/arm/plat-omap/include/plat/common.h +++ b/arch/arm/plat-omap/include/plat/common.h @@ -34,6 +34,8 @@ struct sys_timer; extern void omap_map_common_io(void); extern struct sys_timer omap_timer; +extern void omap_reserve(void); + /* * IO bases for various OMAP processors * Except the tap base, rest all the io bases @@ -56,8 +58,7 @@ struct omap_globals { void omap2_set_globals_242x(void); void omap2_set_globals_243x(void); -void omap2_set_globals_343x(void); -void omap2_set_globals_36xx(void); +void omap2_set_globals_3xxx(void); void omap2_set_globals_443x(void); /* These get called from omap2_set_globals_xxxx(), do not call these */ @@ -67,6 +68,8 @@ void omap2_set_globals_control(struct omap_globals *); void omap2_set_globals_prcm(struct omap_globals *); void omap2_set_globals_uart(struct omap_globals *); +void omap3_map_io(void); + /** * omap_test_timeout - busy-loop, testing a condition * @cond: condition to test until it evaluates to true @@ -87,4 +90,8 @@ void omap2_set_globals_uart(struct omap_globals *); } \ }) +extern struct device *omap2_get_mpuss_device(void); +extern struct device *omap2_get_dsp_device(void); +extern struct device *omap2_get_l3_device(void); + #endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */ diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h index 75141742300c..2e2ae530fced 100644 --- a/arch/arm/plat-omap/include/plat/cpu.h +++ b/arch/arm/plat-omap/include/plat/cpu.h @@ -66,6 +66,8 @@ unsigned int omap_rev(void); * family. This difference can be handled separately. */ #define OMAP_REVBITS_00 0x00 +#define OMAP_REVBITS_01 0x01 +#define OMAP_REVBITS_02 0x02 #define OMAP_REVBITS_10 0x10 #define OMAP_REVBITS_20 0x20 #define OMAP_REVBITS_30 0x30 @@ -376,6 +378,8 @@ IS_OMAP_TYPE(3517, 0x3517) #define OMAP3430_REV_ES3_1_2 0x34305034 #define OMAP3630_REV_ES1_0 0x36300034 +#define OMAP3630_REV_ES1_1 0x36300134 +#define OMAP3630_REV_ES1_2 0x36300234 #define OMAP35XX_CLASS 0x35000034 #define OMAP3503_REV(v) (OMAP35XX_CLASS | (0x3503 << 16) | (v << 8)) @@ -411,6 +415,8 @@ IS_OMAP_TYPE(3517, 0x3517) #define CHIP_IS_OMAP3430ES3_1 (1 << 6) #define CHIP_IS_OMAP3630ES1 (1 << 7) #define CHIP_IS_OMAP4430ES1 (1 << 8) +#define CHIP_IS_OMAP3630ES1_1 (1 << 9) +#define CHIP_IS_OMAP3630ES1_2 (1 << 10) #define CHIP_IS_OMAP24XX (CHIP_IS_OMAP2420 | CHIP_IS_OMAP2430) @@ -424,11 +430,12 @@ IS_OMAP_TYPE(3517, 0x3517) */ #define CHIP_GE_OMAP3430ES2 (CHIP_IS_OMAP3430ES2 | \ CHIP_IS_OMAP3430ES3_0 | \ - CHIP_IS_OMAP3430ES3_1 | \ - CHIP_IS_OMAP3630ES1) + CHIP_GE_OMAP3430ES3_1) #define CHIP_GE_OMAP3430ES3_1 (CHIP_IS_OMAP3430ES3_1 | \ - CHIP_IS_OMAP3630ES1) - + CHIP_IS_OMAP3630ES1 | \ + CHIP_GE_OMAP3630ES1_1) +#define CHIP_GE_OMAP3630ES1_1 (CHIP_IS_OMAP3630ES1_1 | \ + CHIP_IS_OMAP3630ES1_2) int omap_chip_is(struct omap_chip_id oci); void omap2_check_revision(void); @@ -444,6 +451,7 @@ extern u32 omap3_features; #define OMAP3_HAS_NEON BIT(3) #define OMAP3_HAS_ISP BIT(4) #define OMAP3_HAS_192MHZ_CLK BIT(5) +#define OMAP3_HAS_IO_WAKEUP BIT(6) #define OMAP3_HAS_FEATURE(feat,flag) \ static inline unsigned int omap3_has_ ##feat(void) \ @@ -457,5 +465,6 @@ OMAP3_HAS_FEATURE(iva, IVA) OMAP3_HAS_FEATURE(neon, NEON) OMAP3_HAS_FEATURE(isp, ISP) OMAP3_HAS_FEATURE(192mhz_clk, 192MHZ_CLK) +OMAP3_HAS_FEATURE(io_wakeup, IO_WAKEUP) #endif diff --git a/arch/arm/plat-omap/include/plat/display.h b/arch/arm/plat-omap/include/plat/display.h index 1c529ce9dc11..8bd15bdb4132 100644 --- a/arch/arm/plat-omap/include/plat/display.h +++ b/arch/arm/plat-omap/include/plat/display.h @@ -238,7 +238,7 @@ int dsi_vc_dcs_write_1(int channel, u8 dcs_cmd, u8 param); int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len); int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen); int dsi_vc_dcs_read_1(int channel, u8 dcs_cmd, u8 *data); -int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u16 *data); +int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u8 *data1, u8 *data2); int dsi_vc_set_max_rx_packet_size(int channel, u16 len); int dsi_vc_send_null(int channel); int dsi_vc_send_bta_sync(int channel); @@ -277,8 +277,8 @@ struct omap_video_timings { * identify the mode, and does not actually use the configs * itself. However, the configs should be something that * a normal monitor can also show */ -const extern struct omap_video_timings omap_dss_pal_timings; -const extern struct omap_video_timings omap_dss_ntsc_timings; +extern const struct omap_video_timings omap_dss_pal_timings; +extern const struct omap_video_timings omap_dss_ntsc_timings; #endif struct omap_overlay_info { @@ -560,7 +560,8 @@ void omapdss_dsi_vc_enable_hs(int channel, bool enable); int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable); int omap_dsi_prepare_update(struct omap_dss_device *dssdev, - u16 *x, u16 *y, u16 *w, u16 *h); + u16 *x, u16 *y, u16 *w, u16 *h, + bool enlarge_update_area); int omap_dsi_update(struct omap_dss_device *dssdev, int channel, u16 x, u16 y, u16 w, u16 h, diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h index 02232ca2c37f..af3a03941add 100644 --- a/arch/arm/plat-omap/include/plat/dma.h +++ b/arch/arm/plat-omap/include/plat/dma.h @@ -345,6 +345,7 @@ #define OMAP_DMA_SYNC_BLOCK 0x02 #define OMAP_DMA_SYNC_PACKET 0x03 +#define OMAP_DMA_DST_SYNC_PREFETCH 0x02 #define OMAP_DMA_SRC_SYNC 0x01 #define OMAP_DMA_DST_SYNC 0x00 diff --git a/arch/arm/plat-omap/include/plat/dsp_common.h b/arch/arm/plat-omap/include/plat/dsp_common.h deleted file mode 100644 index da97736f3efa..000000000000 --- a/arch/arm/plat-omap/include/plat/dsp_common.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1) - * - * Copyright (C) 2004-2006 Nokia Corporation. All rights reserved. - * - * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef ASM_ARCH_DSP_COMMON_H -#define ASM_ARCH_DSP_COMMON_H - -#if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_OMAP_MMU_FWK) -extern void omap_dsp_request_mpui(void); -extern void omap_dsp_release_mpui(void); -extern int omap_dsp_request_mem(void); -extern int omap_dsp_release_mem(void); -#else -static inline int omap_dsp_request_mem(void) -{ - return 0; -} -#define omap_dsp_release_mem() do {} while (0) -#endif - -#endif /* ASM_ARCH_DSP_COMMON_H */ diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index 145838a81ef6..9fd99b9e40ab 100644 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h @@ -25,10 +25,26 @@ #define GPMC_CS_NAND_ADDRESS 0x20 #define GPMC_CS_NAND_DATA 0x24 -#define GPMC_CONFIG 0x50 -#define GPMC_STATUS 0x54 -#define GPMC_CS0_BASE 0x60 -#define GPMC_CS_SIZE 0x30 +/* Control Commands */ +#define GPMC_CONFIG_RDY_BSY 0x00000001 +#define GPMC_CONFIG_DEV_SIZE 0x00000002 +#define GPMC_CONFIG_DEV_TYPE 0x00000003 +#define GPMC_SET_IRQ_STATUS 0x00000004 +#define GPMC_CONFIG_WP 0x00000005 + +#define GPMC_GET_IRQ_STATUS 0x00000006 +#define GPMC_PREFETCH_FIFO_CNT 0x00000007 /* bytes available in FIFO for r/w */ +#define GPMC_PREFETCH_COUNT 0x00000008 /* remaining bytes to be read/write*/ +#define GPMC_STATUS_BUFFER 0x00000009 /* 1: buffer is available to write */ + +#define GPMC_NAND_COMMAND 0x0000000a +#define GPMC_NAND_ADDRESS 0x0000000b +#define GPMC_NAND_DATA 0x0000000c + +/* ECC commands */ +#define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */ +#define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */ +#define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back */ #define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31) #define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30) @@ -47,7 +63,6 @@ #define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1) #define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10) #define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0) -#define GPMC_CONFIG1_DEVICETYPE_NAND GPMC_CONFIG1_DEVICETYPE(2) #define GPMC_CONFIG1_MUXADDDATA (1 << 9) #define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4) #define GPMC_CONFIG1_FCLK_DIV(val) (val & 3) @@ -56,6 +71,14 @@ #define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3)) #define GPMC_CONFIG7_CSVALID (1 << 6) +#define GPMC_DEVICETYPE_NOR 0 +#define GPMC_DEVICETYPE_NAND 2 +#define GPMC_CONFIG_WRITEPROTECT 0x00000010 +#define GPMC_STATUS_BUFF_EMPTY 0x00000001 +#define WR_RD_PIN_MONITORING 0x00600000 +#define GPMC_PREFETCH_STATUS_FIFO_CNT(val) ((val >> 24) & 0x7F) +#define GPMC_PREFETCH_STATUS_COUNT(val) (val & 0x00003fff) + /* * Note that all values in this struct are in nanoseconds, while * the register values are in gpmc_fck cycles. @@ -108,10 +131,15 @@ extern int gpmc_cs_set_reserved(int cs, int reserved); extern int gpmc_cs_reserved(int cs); extern int gpmc_prefetch_enable(int cs, int dma_mode, unsigned int u32_count, int is_write); -extern void gpmc_prefetch_reset(void); -extern int gpmc_prefetch_status(void); +extern int gpmc_prefetch_reset(int cs); extern void omap3_gpmc_save_context(void); extern void omap3_gpmc_restore_context(void); extern void gpmc_init(void); +extern int gpmc_read_status(int cmd); +extern int gpmc_cs_configure(int cs, int cmd, int wval); +extern int gpmc_nand_read(int cs, int cmd); +extern int gpmc_nand_write(int cs, int cmd, int wval); +int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size); +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code); #endif diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h index 0752af9d099e..33c7d41cb6a5 100644 --- a/arch/arm/plat-omap/include/plat/iommu.h +++ b/arch/arm/plat-omap/include/plat/iommu.h @@ -80,6 +80,7 @@ struct iommu_functions { int (*enable)(struct iommu *obj); void (*disable)(struct iommu *obj); + void (*set_twl)(struct iommu *obj, bool on); u32 (*fault_isr)(struct iommu *obj, u32 *ra); void (*tlb_read_cr)(struct iommu *obj, struct cr_regs *cr); @@ -143,6 +144,7 @@ extern void iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e); extern u32 iotlb_cr_to_virt(struct cr_regs *cr); extern int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e); +extern void iommu_set_twl(struct iommu *obj, bool on); extern void flush_iotlb_page(struct iommu *obj, u32 da); extern void flush_iotlb_range(struct iommu *obj, u32 start, u32 end); extern void flush_iotlb_all(struct iommu *obj); diff --git a/arch/arm/plat-omap/include/plat/mailbox.h b/arch/arm/plat-omap/include/plat/mailbox.h index 729166b76a7c..997656552109 100644 --- a/arch/arm/plat-omap/include/plat/mailbox.h +++ b/arch/arm/plat-omap/include/plat/mailbox.h @@ -3,10 +3,11 @@ #ifndef MAILBOX_H #define MAILBOX_H -#include <linux/wait.h> +#include <linux/spinlock.h> #include <linux/workqueue.h> -#include <linux/blkdev.h> #include <linux/interrupt.h> +#include <linux/device.h> +#include <linux/kfifo.h> typedef u32 mbox_msg_t; struct omap_mbox; @@ -42,7 +43,7 @@ struct omap_mbox_ops { struct omap_mbox_queue { spinlock_t lock; - struct request_queue *queue; + struct kfifo fifo; struct work_struct work; struct tasklet_struct tasklet; int (*callback)(void *); @@ -52,19 +53,10 @@ struct omap_mbox_queue { struct omap_mbox { char *name; unsigned int irq; - struct omap_mbox_queue *txq, *rxq; - struct omap_mbox_ops *ops; - - mbox_msg_t seq_snd, seq_rcv; - struct device *dev; - - struct omap_mbox *next; void *priv; - - void (*err_notify)(void); }; int omap_mbox_msg_send(struct omap_mbox *, mbox_msg_t msg); @@ -73,8 +65,8 @@ void omap_mbox_init_seq(struct omap_mbox *); struct omap_mbox *omap_mbox_get(const char *); void omap_mbox_put(struct omap_mbox *); -int omap_mbox_register(struct device *parent, struct omap_mbox *); -int omap_mbox_unregister(struct omap_mbox *); +int omap_mbox_register(struct device *parent, struct omap_mbox **); +int omap_mbox_unregister(void); static inline void omap_mbox_save_ctx(struct omap_mbox *mbox) { diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h index c835f1e994c6..9b89ec601ee2 100644 --- a/arch/arm/plat-omap/include/plat/mmc.h +++ b/arch/arm/plat-omap/include/plat/mmc.h @@ -122,6 +122,8 @@ struct omap_mmc_platform_data { /* Call back after enabling / disabling regulators */ void (*after_set_reg)(struct device *dev, int slot, int power_on, int vdd); + /* if we have special card, init it using this callback */ + void (*init_card)(struct mmc_card *card); /* return MMC cover switch state, can be NULL if not supported. * diff --git a/arch/arm/plat-omap/include/plat/mux.h b/arch/arm/plat-omap/include/plat/mux.h index c7472a28ce24..aeba71796ad9 100644 --- a/arch/arm/plat-omap/include/plat/mux.h +++ b/arch/arm/plat-omap/include/plat/mux.h @@ -114,28 +114,11 @@ PU_PD_REG(NA, 0) \ }, -#define MUX_CFG_24XX(desc, reg_offset, mode, \ - pull_en, pull_mode, dbg) \ -{ \ - .name = desc, \ - .debug = dbg, \ - .mux_reg = reg_offset, \ - .mask = mode, \ - .pull_val = pull_en, \ - .pu_pd_val = pull_mode, \ -}, - -/* 24xx/34xx mux bit defines */ -#define OMAP2_PULL_ENA (1 << 3) -#define OMAP2_PULL_UP (1 << 4) -#define OMAP2_ALTELECTRICALSEL (1 << 5) - struct pin_config { char *name; const unsigned int mux_reg; unsigned char debug; -#if defined(CONFIG_ARCH_OMAP1) || defined(CONFIG_ARCH_OMAP2) const unsigned char mask_offset; const unsigned char mask; @@ -147,7 +130,6 @@ struct pin_config { const char *pu_pd_name; const unsigned int pu_pd_reg; const unsigned char pu_pd_val; -#endif #if defined(CONFIG_OMAP_MUX_DEBUG) || defined(CONFIG_OMAP_MUX_WARNINGS) const char *mux_reg_name; @@ -191,6 +173,10 @@ enum omap7xx_index { SPI_7XX_4, SPI_7XX_5, SPI_7XX_6, + + /* UART */ + UART_7XX_1, + UART_7XX_2, }; enum omap1xxx_index { @@ -446,208 +432,6 @@ enum omap1xxx_index { }; -enum omap24xx_index { - /* 24xx I2C */ - M19_24XX_I2C1_SCL, - L15_24XX_I2C1_SDA, - J15_24XX_I2C2_SCL, - H19_24XX_I2C2_SDA, - - /* 24xx Menelaus interrupt */ - W19_24XX_SYS_NIRQ, - - /* 24xx clock */ - W14_24XX_SYS_CLKOUT, - - /* 24xx GPMC chipselects, wait pin monitoring */ - E2_GPMC_NCS2, - L2_GPMC_NCS7, - L3_GPMC_WAIT0, - N7_GPMC_WAIT1, - M1_GPMC_WAIT2, - P1_GPMC_WAIT3, - - /* 242X McBSP */ - Y15_24XX_MCBSP2_CLKX, - R14_24XX_MCBSP2_FSX, - W15_24XX_MCBSP2_DR, - V15_24XX_MCBSP2_DX, - - /* 24xx GPIO */ - M21_242X_GPIO11, - P21_242X_GPIO12, - AA10_242X_GPIO13, - AA6_242X_GPIO14, - AA4_242X_GPIO15, - Y11_242X_GPIO16, - AA12_242X_GPIO17, - AA8_242X_GPIO58, - Y20_24XX_GPIO60, - W4__24XX_GPIO74, - N15_24XX_GPIO85, - M15_24XX_GPIO92, - P20_24XX_GPIO93, - P18_24XX_GPIO95, - M18_24XX_GPIO96, - L14_24XX_GPIO97, - J15_24XX_GPIO99, - V14_24XX_GPIO117, - P14_24XX_GPIO125, - - /* 242x DBG GPIO */ - V4_242X_GPIO49, - W2_242X_GPIO50, - U4_242X_GPIO51, - V3_242X_GPIO52, - V2_242X_GPIO53, - V6_242X_GPIO53, - T4_242X_GPIO54, - Y4_242X_GPIO54, - T3_242X_GPIO55, - U2_242X_GPIO56, - - /* 24xx external DMA requests */ - AA10_242X_DMAREQ0, - AA6_242X_DMAREQ1, - E4_242X_DMAREQ2, - G4_242X_DMAREQ3, - D3_242X_DMAREQ4, - E3_242X_DMAREQ5, - - /* UART3 */ - K15_24XX_UART3_TX, - K14_24XX_UART3_RX, - - /* MMC/SDIO */ - G19_24XX_MMC_CLKO, - H18_24XX_MMC_CMD, - F20_24XX_MMC_DAT0, - H14_24XX_MMC_DAT1, - E19_24XX_MMC_DAT2, - D19_24XX_MMC_DAT3, - F19_24XX_MMC_DAT_DIR0, - E20_24XX_MMC_DAT_DIR1, - F18_24XX_MMC_DAT_DIR2, - E18_24XX_MMC_DAT_DIR3, - G18_24XX_MMC_CMD_DIR, - H15_24XX_MMC_CLKI, - - /* Full speed USB */ - J20_24XX_USB0_PUEN, - J19_24XX_USB0_VP, - K20_24XX_USB0_VM, - J18_24XX_USB0_RCV, - K19_24XX_USB0_TXEN, - J14_24XX_USB0_SE0, - K18_24XX_USB0_DAT, - - N14_24XX_USB1_SE0, - W12_24XX_USB1_SE0, - P15_24XX_USB1_DAT, - R13_24XX_USB1_DAT, - W20_24XX_USB1_TXEN, - P13_24XX_USB1_TXEN, - V19_24XX_USB1_RCV, - V12_24XX_USB1_RCV, - - AA10_24XX_USB2_SE0, - Y11_24XX_USB2_DAT, - AA12_24XX_USB2_TXEN, - AA6_24XX_USB2_RCV, - AA4_24XX_USB2_TLLSE0, - - /* Keypad GPIO*/ - T19_24XX_KBR0, - R19_24XX_KBR1, - V18_24XX_KBR2, - M21_24XX_KBR3, - E5__24XX_KBR4, - M18_24XX_KBR5, - R20_24XX_KBC0, - M14_24XX_KBC1, - H19_24XX_KBC2, - V17_24XX_KBC3, - P21_24XX_KBC4, - L14_24XX_KBC5, - N19_24XX_KBC6, - - /* 24xx Menelaus Keypad GPIO */ - B3__24XX_KBR5, - AA4_24XX_KBC2, - B13_24XX_KBC6, - - /* 2430 USB */ - AD9_2430_USB0_PUEN, - Y11_2430_USB0_VP, - AD7_2430_USB0_VM, - AE7_2430_USB0_RCV, - AD4_2430_USB0_TXEN, - AF9_2430_USB0_SE0, - AE6_2430_USB0_DAT, - AD24_2430_USB1_SE0, - AB24_2430_USB1_RCV, - Y25_2430_USB1_TXEN, - AA26_2430_USB1_DAT, - - /* 2430 HS-USB */ - AD9_2430_USB0HS_DATA3, - Y11_2430_USB0HS_DATA4, - AD7_2430_USB0HS_DATA5, - AE7_2430_USB0HS_DATA6, - AD4_2430_USB0HS_DATA2, - AF9_2430_USB0HS_DATA0, - AE6_2430_USB0HS_DATA1, - AE8_2430_USB0HS_CLK, - AD8_2430_USB0HS_DIR, - AE5_2430_USB0HS_STP, - AE9_2430_USB0HS_NXT, - AC7_2430_USB0HS_DATA7, - - /* 2430 McBSP */ - AD6_2430_MCBSP_CLKS, - - AB2_2430_MCBSP1_CLKR, - AD5_2430_MCBSP1_FSR, - AA1_2430_MCBSP1_DX, - AF3_2430_MCBSP1_DR, - AB3_2430_MCBSP1_FSX, - Y9_2430_MCBSP1_CLKX, - - AC10_2430_MCBSP2_FSX, - AD16_2430_MCBSP2_CLX, - AE13_2430_MCBSP2_DX, - AD13_2430_MCBSP2_DR, - AC10_2430_MCBSP2_FSX_OFF, - AD16_2430_MCBSP2_CLX_OFF, - AE13_2430_MCBSP2_DX_OFF, - AD13_2430_MCBSP2_DR_OFF, - - AC9_2430_MCBSP3_CLKX, - AE4_2430_MCBSP3_FSX, - AE2_2430_MCBSP3_DR, - AF4_2430_MCBSP3_DX, - - N3_2430_MCBSP4_CLKX, - AD23_2430_MCBSP4_DR, - AB25_2430_MCBSP4_DX, - AC25_2430_MCBSP4_FSX, - - AE16_2430_MCBSP5_CLKX, - AF12_2430_MCBSP5_FSX, - K7_2430_MCBSP5_DX, - M1_2430_MCBSP5_DR, - - /* 2430 McSPI*/ - Y18_2430_MCSPI1_CLK, - AD15_2430_MCSPI1_SIMO, - AE17_2430_MCSPI1_SOMI, - U1_2430_MCSPI1_CS0, - - /* Touchscreen GPIO */ - AF19_2430_GPIO_85, - -}; - struct omap_mux_cfg { struct pin_config *pins; unsigned long size; diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h index f8efd5466b1d..6562cd082bb1 100644 --- a/arch/arm/plat-omap/include/plat/nand.h +++ b/arch/arm/plat-omap/include/plat/nand.h @@ -21,13 +21,11 @@ struct omap_nand_platform_data { int (*dev_ready)(struct omap_nand_platform_data *); int dma_channel; unsigned long phys_base; - void __iomem *gpmc_cs_baseaddr; - void __iomem *gpmc_baseaddr; int devsize; }; -/* size (4 KiB) for IO mapping */ -#define NAND_IO_SIZE SZ_4K +/* minimum size for IO mapping */ +#define NAND_IO_SIZE 4 #if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE) extern int gpmc_nand_init(struct omap_nand_platform_data *d); diff --git a/arch/arm/plat-omap/include/plat/nokia-dsi-panel.h b/arch/arm/plat-omap/include/plat/nokia-dsi-panel.h new file mode 100644 index 000000000000..01ab6572ccbb --- /dev/null +++ b/arch/arm/plat-omap/include/plat/nokia-dsi-panel.h @@ -0,0 +1,31 @@ +#ifndef __ARCH_ARM_PLAT_OMAP_NOKIA_DSI_PANEL_H +#define __ARCH_ARM_PLAT_OMAP_NOKIA_DSI_PANEL_H + +#include "display.h" + +/** + * struct nokia_dsi_panel_data - Nokia DSI panel driver configuration + * @name: panel name + * @use_ext_te: use external TE + * @ext_te_gpio: external TE GPIO + * @use_esd_check: perform ESD checks + * @max_backlight_level: maximum backlight level + * @set_backlight: pointer to backlight set function + * @get_backlight: pointer to backlight get function + */ +struct nokia_dsi_panel_data { + const char *name; + + int reset_gpio; + + bool use_ext_te; + int ext_te_gpio; + + bool use_esd_check; + + int max_backlight_level; + int (*set_backlight)(struct omap_dss_device *dssdev, int level); + int (*get_backlight)(struct omap_dss_device *dssdev); +}; + +#endif /* __ARCH_ARM_PLAT_OMAP_NOKIA_DSI_PANEL_H */ diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h index 3ee41d711492..728fbb9dd549 100644 --- a/arch/arm/plat-omap/include/plat/omap-pm.h +++ b/arch/arm/plat-omap/include/plat/omap-pm.h @@ -1,8 +1,8 @@ /* * omap-pm.h - OMAP power management interface * - * Copyright (C) 2008-2009 Texas Instruments, Inc. - * Copyright (C) 2008-2009 Nokia Corporation + * Copyright (C) 2008-2010 Texas Instruments, Inc. + * Copyright (C) 2008-2010 Nokia Corporation * Paul Walmsley * * Interface developed by (in alphabetical order): Karthik Dasu, Jouni @@ -16,6 +16,7 @@ #include <linux/device.h> #include <linux/cpufreq.h> +#include <linux/clk.h> #include "powerdomain.h" @@ -89,7 +90,7 @@ void omap_pm_if_exit(void); * @t: maximum MPU wakeup latency in microseconds * * Request that the maximum interrupt latency for the MPU to be no - * greater than 't' microseconds. "Interrupt latency" in this case is + * greater than @t microseconds. "Interrupt latency" in this case is * defined as the elapsed time from the occurrence of a hardware or * timer interrupt to the time when the device driver's interrupt * service routine has been entered by the MPU. @@ -105,15 +106,19 @@ void omap_pm_if_exit(void); * elapsed from when a device driver enables a hardware device with * clk_enable(), to when the device is ready for register access or * other use. To control this device wakeup latency, use - * set_max_dev_wakeup_lat() + * omap_pm_set_max_dev_wakeup_lat() * - * Multiple calls to set_max_mpu_wakeup_lat() will replace the + * Multiple calls to omap_pm_set_max_mpu_wakeup_lat() will replace the * previous t value. To remove the latency target for the MPU, call * with t = -1. * - * No return value. + * XXX This constraint will be deprecated soon in favor of the more + * general omap_pm_set_max_dev_wakeup_lat() + * + * Returns -EINVAL for an invalid argument, -ERANGE if the constraint + * is not satisfiable, or 0 upon success. */ -void omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t); +int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t); /** @@ -123,8 +128,8 @@ void omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t); * @r: minimum throughput (in KiB/s) * * Request that the minimum data throughput on the OCP interconnect - * attached to device 'dev' interconnect agent 'tbus_id' be no less - * than 'r' KiB/s. + * attached to device @dev interconnect agent @tbus_id be no less + * than @r KiB/s. * * It is expected that the OMAP PM or bus code will use this * information to set the interconnect clock to run at the lowest @@ -138,40 +143,44 @@ void omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t); * code will also need to add an minimum L3 interconnect speed * constraint, * - * Multiple calls to set_min_bus_tput() will replace the previous rate - * value for this device. To remove the interconnect throughput - * restriction for this device, call with r = 0. + * Multiple calls to omap_pm_set_min_bus_tput() will replace the + * previous rate value for this device. To remove the interconnect + * throughput restriction for this device, call with r = 0. * - * No return value. + * Returns -EINVAL for an invalid argument, -ERANGE if the constraint + * is not satisfiable, or 0 upon success. */ -void omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r); +int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r); /** * omap_pm_set_max_dev_wakeup_lat - set the maximum device enable latency - * @dev: struct device * + * @req_dev: struct device * requesting the constraint, or NULL if none + * @dev: struct device * to set the constraint one * @t: maximum device wakeup latency in microseconds * - * Request that the maximum amount of time necessary for a device to - * become accessible after its clocks are enabled should be no greater - * than 't' microseconds. Specifically, this represents the time from - * when a device driver enables device clocks with clk_enable(), to - * when the register reads and writes on the device will succeed. - * This function should be called before clk_disable() is called, - * since the power state transition decision may be made during - * clk_disable(). + * Request that the maximum amount of time necessary for a device @dev + * to become accessible after its clocks are enabled should be no + * greater than @t microseconds. Specifically, this represents the + * time from when a device driver enables device clocks with + * clk_enable(), to when the register reads and writes on the device + * will succeed. This function should be called before clk_disable() + * is called, since the power state transition decision may be made + * during clk_disable(). * * It is intended that underlying PM code will use this information to * determine what power state to put the powerdomain enclosing this * device into. * - * Multiple calls to set_max_dev_wakeup_lat() will replace the - * previous wakeup latency values for this device. To remove the wakeup - * latency restriction for this device, call with t = -1. + * Multiple calls to omap_pm_set_max_dev_wakeup_lat() will replace the + * previous wakeup latency values for this device. To remove the + * wakeup latency restriction for this device, call with t = -1. * - * No return value. + * Returns -EINVAL for an invalid argument, -ERANGE if the constraint + * is not satisfiable, or 0 upon success. */ -void omap_pm_set_max_dev_wakeup_lat(struct device *dev, long t); +int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev, + long t); /** @@ -198,10 +207,71 @@ void omap_pm_set_max_dev_wakeup_lat(struct device *dev, long t); * value for this device. To remove the maximum DMA latency for this * device, call with t = -1. * - * No return value. + * Returns -EINVAL for an invalid argument, -ERANGE if the constraint + * is not satisfiable, or 0 upon success. */ -void omap_pm_set_max_sdma_lat(struct device *dev, long t); +int omap_pm_set_max_sdma_lat(struct device *dev, long t); + +/** + * omap_pm_set_min_clk_rate - set minimum clock rate requested by @dev + * @dev: struct device * requesting the constraint + * @clk: struct clk * to set the minimum rate constraint on + * @r: minimum rate in Hz + * + * Request that the minimum clock rate on the device @dev's clk @clk + * be no less than @r Hz. + * + * It is expected that the OMAP PM code will use this information to + * find an OPP or clock setting that will satisfy this clock rate + * constraint, along with any other applicable system constraints on + * the clock rate or corresponding voltage, etc. + * + * omap_pm_set_min_clk_rate() differs from the clock code's + * clk_set_rate() in that it considers other constraints before taking + * any hardware action, and may change a system OPP rather than just a + * clock rate. clk_set_rate() is intended to be a low-level + * interface. + * + * omap_pm_set_min_clk_rate() is easily open to abuse. A better API + * would be something like "omap_pm_set_min_dev_performance()"; + * however, there is no easily-generalizable concept of performance + * that applies to all devices. Only a device (and possibly the + * device subsystem) has both the subsystem-specific knowledge, and + * the hardware IP block-specific knowledge, to translate a constraint + * on "touchscreen sampling accuracy" or "number of pixels or polygons + * rendered per second" to a clock rate. This translation can be + * dependent on the hardware IP block's revision, or firmware version, + * and the driver is the only code on the system that has this + * information and can know how to translate that into a clock rate. + * + * The intended use-case for this function is for userspace or other + * kernel code to communicate a particular performance requirement to + * a subsystem; then for the subsystem to communicate that requirement + * to something that is meaningful to the device driver; then for the + * device driver to convert that requirement to a clock rate, and to + * then call omap_pm_set_min_clk_rate(). + * + * Users of this function (such as device drivers) should not simply + * call this function with some high clock rate to ensure "high + * performance." Rather, the device driver should take a performance + * constraint from its subsystem, such as "render at least X polygons + * per second," and use some formula or table to convert that into a + * clock rate constraint given the hardware type and hardware + * revision. Device drivers or subsystems should not assume that they + * know how to make a power/performance tradeoff - some device use + * cases may tolerate a lower-fidelity device function for lower power + * consumption; others may demand a higher-fidelity device function, + * no matter what the power consumption. + * + * Multiple calls to omap_pm_set_min_clk_rate() will replace the + * previous rate value for the device @dev. To remove the minimum clock + * rate constraint for the device, call with r = 0. + * + * Returns -EINVAL for an invalid argument, -ERANGE if the constraint + * is not satisfiable, or 0 upon success. + */ +int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r); /* * DSP Bridge-specific constraints diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h index 3694b622c4ac..25cd9ac3b095 100644 --- a/arch/arm/plat-omap/include/plat/omap_device.h +++ b/arch/arm/plat-omap/include/plat/omap_device.h @@ -101,6 +101,8 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id, int omap_device_register(struct omap_device *od); int omap_early_device_register(struct omap_device *od); +void __iomem *omap_device_get_rt_va(struct omap_device *od); + /* OMAP PM interface */ int omap_device_align_pm_lat(struct platform_device *pdev, u32 new_wakeup_lat_limit); diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index 0eccc09ac4a9..a4e508dfaba2 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -1,7 +1,7 @@ /* * omap_hwmod macros, structures * - * Copyright (C) 2009 Nokia Corporation + * Copyright (C) 2009-2010 Nokia Corporation * Paul Walmsley * * Created in collaboration with (alphabetical order): Benoît Cousson, @@ -419,7 +419,7 @@ struct omap_hwmod_class { * @slaves: ptr to array of OCP ifs that this hwmod can respond on * @dev_attr: arbitrary device attributes that can be passed to the driver * @_sysc_cache: internal-use hwmod flags - * @_rt_va: cached register target start address (internal use) + * @_mpu_rt_va: cached register target start address (internal use) * @_mpu_port_index: cached MPU register target slave ID (internal use) * @msuspendmux_reg_id: CONTROL_MSUSPENDMUX register ID (1-6) * @msuspendmux_shift: CONTROL_MSUSPENDMUX register bit shift @@ -460,7 +460,7 @@ struct omap_hwmod { struct omap_hwmod_ocp_if **slaves; /* connect to *_TA */ void *dev_attr; u32 _sysc_cache; - void __iomem *_rt_va; + void __iomem *_mpu_rt_va; struct list_head node; u16 flags; u8 _mpu_port_index; @@ -482,11 +482,14 @@ int omap_hwmod_init(struct omap_hwmod **ohs); int omap_hwmod_register(struct omap_hwmod *oh); int omap_hwmod_unregister(struct omap_hwmod *oh); struct omap_hwmod *omap_hwmod_lookup(const char *name); -int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh)); -int omap_hwmod_late_init(void); +int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data), + void *data); +int omap_hwmod_late_init(u8 skip_setup_idle); int omap_hwmod_enable(struct omap_hwmod *oh); +int _omap_hwmod_enable(struct omap_hwmod *oh); int omap_hwmod_idle(struct omap_hwmod *oh); +int _omap_hwmod_idle(struct omap_hwmod *oh); int omap_hwmod_shutdown(struct omap_hwmod *oh); int omap_hwmod_enable_clocks(struct omap_hwmod *oh); @@ -504,6 +507,7 @@ int omap_hwmod_count_resources(struct omap_hwmod *oh); int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res); struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh); +void __iomem *omap_hwmod_get_mpu_rt_va(struct omap_hwmod *oh); int omap_hwmod_add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh); diff --git a/arch/arm/plat-omap/include/plat/smp.h b/arch/arm/plat-omap/include/plat/smp.h index 8983d54c4fd2..6a3ff65c0303 100644 --- a/arch/arm/plat-omap/include/plat/smp.h +++ b/arch/arm/plat-omap/include/plat/smp.h @@ -30,6 +30,7 @@ extern void omap_secondary_startup(void); extern u32 omap_modify_auxcoreboot0(u32 set_mask, u32 clear_mask); extern void omap_auxcoreboot_addr(u32 cpu_addr); +extern u32 omap_read_auxcoreboot0(void); /* * We use Soft IRQ1 as the IPI diff --git a/arch/arm/plat-omap/include/plat/uncompress.h b/arch/arm/plat-omap/include/plat/uncompress.h index bbedd71943f6..ddf723be48dc 100644 --- a/arch/arm/plat-omap/include/plat/uncompress.h +++ b/arch/arm/plat-omap/include/plat/uncompress.h @@ -25,6 +25,8 @@ #include <plat/serial.h> +#define MDR1_MODE_MASK 0x07 + static volatile u8 *uart_base; static int uart_shift; @@ -42,6 +44,10 @@ static void putc(int c) if (!uart_base) return; + /* Check for UART 16x mode */ + if ((uart_base[UART_OMAP_MDR1 << uart_shift] & MDR1_MODE_MASK) != 0) + return; + while (!(uart_base[UART_LSR << uart_shift] & UART_LSR_THRE)) barrier(); uart_base[UART_TX << uart_shift] = c; diff --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h index 98eef5360e6d..2a9427c8cc48 100644 --- a/arch/arm/plat-omap/include/plat/usb.h +++ b/arch/arm/plat-omap/include/plat/usb.h @@ -81,7 +81,34 @@ extern void usb_ohci_init(const struct ohci_hcd_omap_platform_data *pdata); #endif -void omap_usb_init(struct omap_usb_config *pdata); + +/* + * FIXME correct answer depends on hmc_mode, + * as does (on omap1) any nonzero value for config->otg port number + */ +#ifdef CONFIG_USB_GADGET_OMAP +#define is_usb0_device(config) 1 +#else +#define is_usb0_device(config) 0 +#endif + +void omap_otg_init(struct omap_usb_config *config); + +#if defined(CONFIG_USB) || defined(CONFIG_USB_MODULE) +void omap1_usb_init(struct omap_usb_config *pdata); +#else +static inline void omap1_usb_init(struct omap_usb_config *pdata) +{ +} +#endif + +#if defined(CONFIG_ARCH_OMAP_OTG) || defined(CONFIG_ARCH_OMAP_OTG_MODULE) +void omap2_usbfs_init(struct omap_usb_config *pdata); +#else +static inline omap2_usbfs_init(struct omap_usb_config *pdata) +{ +} +#endif /*-------------------------------------------------------------------------*/ @@ -192,4 +219,24 @@ void omap_usb_init(struct omap_usb_config *pdata); # define USB0PUENACTLOI (1 << 16) # define USBSTANDBYCTRL (1 << 15) +#if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_USB) +u32 omap1_usb0_init(unsigned nwires, unsigned is_device); +u32 omap1_usb1_init(unsigned nwires); +u32 omap1_usb2_init(unsigned nwires, unsigned alt_pingroup); +#else +static inline u32 omap1_usb0_init(unsigned nwires, unsigned is_device) +{ + return 0; +} +static inline u32 omap1_usb1_init(unsigned nwires) +{ + return 0; + +} +static inline u32 omap1_usb2_init(unsigned nwires, unsigned alt_pingroup) +{ + return 0; +} +#endif + #endif /* __ASM_ARCH_OMAP_USB_H */ diff --git a/arch/arm/plat-omap/include/plat/vram.h b/arch/arm/plat-omap/include/plat/vram.h index edd4987758a6..0aa4ecd12c7d 100644 --- a/arch/arm/plat-omap/include/plat/vram.h +++ b/arch/arm/plat-omap/include/plat/vram.h @@ -38,7 +38,7 @@ extern void omap_vram_get_info(unsigned long *vram, unsigned long *free_vram, extern void omap_vram_set_sdram_vram(u32 size, u32 start); extern void omap_vram_set_sram_vram(u32 size, u32 start); -extern void omap_vram_reserve_sdram(void); +extern void omap_vram_reserve_sdram_memblock(void); extern unsigned long omap_vram_reserve_sram(unsigned long sram_pstart, unsigned long sram_vstart, unsigned long sram_size, @@ -48,7 +48,7 @@ extern unsigned long omap_vram_reserve_sram(unsigned long sram_pstart, static inline void omap_vram_set_sdram_vram(u32 size, u32 start) { } static inline void omap_vram_set_sram_vram(u32 size, u32 start) { } -static inline void omap_vram_reserve_sdram(void) { } +static inline void omap_vram_reserve_sdram_memblock(void) { } static inline unsigned long omap_vram_reserve_sram(unsigned long sram_pstart, unsigned long sram_vstart, unsigned long sram_size, diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c index bc094dbacee6..a202a2ce6e3d 100644 --- a/arch/arm/plat-omap/iommu.c +++ b/arch/arm/plat-omap/iommu.c @@ -370,6 +370,23 @@ void flush_iotlb_all(struct iommu *obj) } EXPORT_SYMBOL_GPL(flush_iotlb_all); +/** + * iommu_set_twl - enable/disable table walking logic + * @obj: target iommu + * @on: enable/disable + * + * Function used to enable/disable TWL. If one wants to work + * exclusively with locked TLB entries and receive notifications + * for TLB miss then call this function to disable TWL. + */ +void iommu_set_twl(struct iommu *obj, bool on) +{ + clk_enable(obj->clk); + arch_iommu->set_twl(obj, on); + clk_disable(obj->clk); +} +EXPORT_SYMBOL_GPL(iommu_set_twl); + #if defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE) ssize_t iommu_dump_ctx(struct iommu *obj, char *buf, ssize_t bytes) @@ -653,7 +670,7 @@ void iopgtable_lookup_entry(struct iommu *obj, u32 da, u32 **ppgd, u32 **ppte) if (!*iopgd) goto out; - if (*iopgd & IOPGD_TABLE) + if (iopgd_is_table(*iopgd)) iopte = iopte_offset(iopgd, da); out: *ppgd = iopgd; @@ -670,7 +687,7 @@ static size_t iopgtable_clear_entry_core(struct iommu *obj, u32 da) if (!*iopgd) return 0; - if (*iopgd & IOPGD_TABLE) { + if (iopgd_is_table(*iopgd)) { int i; u32 *iopte = iopte_offset(iopgd, da); @@ -745,7 +762,7 @@ static void iopgtable_clear_entry_all(struct iommu *obj) if (!*iopgd) continue; - if (*iopgd & IOPGD_TABLE) + if (iopgd_is_table(*iopgd)) iopte_free(iopte_offset(iopgd, 0)); *iopgd = 0; @@ -783,9 +800,11 @@ static irqreturn_t iommu_fault_handler(int irq, void *data) if (!stat) return IRQ_HANDLED; + iommu_disable(obj); + iopgd = iopgd_offset(obj, da); - if (!(*iopgd & IOPGD_TABLE)) { + if (!iopgd_is_table(*iopgd)) { dev_err(obj->dev, "%s: da:%08x pgd:%p *pgd:%08x\n", __func__, da, iopgd, *iopgd); return IRQ_NONE; diff --git a/arch/arm/plat-omap/iopgtable.h b/arch/arm/plat-omap/iopgtable.h index ab23b6a140fd..c3e93bb0911f 100644 --- a/arch/arm/plat-omap/iopgtable.h +++ b/arch/arm/plat-omap/iopgtable.h @@ -63,6 +63,8 @@ #define IOPGD_SECTION (2 << 0) #define IOPGD_SUPER (1 << 18 | 2 << 0) +#define iopgd_is_table(x) (((x) & 3) == IOPGD_TABLE) + #define IOPTE_SMALL (2 << 0) #define IOPTE_LARGE (1 << 0) @@ -70,12 +72,12 @@ #define iopgd_index(da) (((da) >> IOPGD_SHIFT) & (PTRS_PER_IOPGD - 1)) #define iopgd_offset(obj, da) ((obj)->iopgd + iopgd_index(da)) -#define iopte_paddr(iopgd) (*iopgd & ~((1 << 10) - 1)) -#define iopte_vaddr(iopgd) ((u32 *)phys_to_virt(iopte_paddr(iopgd))) +#define iopgd_page_paddr(iopgd) (*iopgd & ~((1 << 10) - 1)) +#define iopgd_page_vaddr(iopgd) ((u32 *)phys_to_virt(iopgd_page_paddr(iopgd))) /* to find an entry in the second-level page table. */ #define iopte_index(da) (((da) >> IOPTE_SHIFT) & (PTRS_PER_IOPTE - 1)) -#define iopte_offset(iopgd, da) (iopte_vaddr(iopgd) + iopte_index(da)) +#define iopte_offset(iopgd, da) (iopgd_page_vaddr(iopgd) + iopte_index(da)) static inline u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa, u32 flags) diff --git a/arch/arm/plat-omap/iovmm.c b/arch/arm/plat-omap/iovmm.c index e43983ba59c5..8ce0de247c71 100644 --- a/arch/arm/plat-omap/iovmm.c +++ b/arch/arm/plat-omap/iovmm.c @@ -140,8 +140,10 @@ static struct sg_table *sgtable_alloc(const size_t bytes, u32 flags) return ERR_PTR(-ENOMEM); err = sg_alloc_table(sgt, nr_entries, GFP_KERNEL); - if (err) + if (err) { + kfree(sgt); return ERR_PTR(err); + } pr_debug("%s: sgt:%p(%d entries)\n", __func__, sgt, nr_entries); diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c index 08a2df766289..d2fafb892f7f 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/arch/arm/plat-omap/mailbox.c @@ -21,19 +21,26 @@ * */ -#include <linux/module.h> #include <linux/interrupt.h> -#include <linux/device.h> +#include <linux/spinlock.h> +#include <linux/mutex.h> #include <linux/delay.h> #include <linux/slab.h> +#include <linux/kfifo.h> +#include <linux/err.h> #include <plat/mailbox.h> static struct workqueue_struct *mboxd; -static struct omap_mbox *mboxes; -static DEFINE_RWLOCK(mboxes_lock); +static struct omap_mbox **mboxes; +static bool rq_full; static int mbox_configured; +static DEFINE_MUTEX(mbox_configured_lock); + +static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE; +module_param(mbox_kfifo_size, uint, S_IRUGO); +MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)"); /* Mailbox FIFO handle functions */ static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox) @@ -67,7 +74,7 @@ static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) /* * message sender */ -static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg) +static int __mbox_poll_for_space(struct omap_mbox *mbox) { int ret = 0, i = 1000; @@ -78,49 +85,50 @@ static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg) return -1; udelay(1); } - mbox_fifo_write(mbox, msg); return ret; } - int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg) { + struct omap_mbox_queue *mq = mbox->txq; + int ret = 0, len; - struct request *rq; - struct request_queue *q = mbox->txq->queue; + spin_lock(&mq->lock); - rq = blk_get_request(q, WRITE, GFP_ATOMIC); - if (unlikely(!rq)) - return -ENOMEM; + if (kfifo_avail(&mq->fifo) < sizeof(msg)) { + ret = -ENOMEM; + goto out; + } + + len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg)); + WARN_ON(len != sizeof(msg)); - blk_insert_request(q, rq, 0, (void *) msg); tasklet_schedule(&mbox->txq->tasklet); - return 0; +out: + spin_unlock(&mq->lock); + return ret; } EXPORT_SYMBOL(omap_mbox_msg_send); static void mbox_tx_tasklet(unsigned long tx_data) { - int ret; - struct request *rq; struct omap_mbox *mbox = (struct omap_mbox *)tx_data; - struct request_queue *q = mbox->txq->queue; - - while (1) { - - rq = blk_fetch_request(q); - - if (!rq) - break; + struct omap_mbox_queue *mq = mbox->txq; + mbox_msg_t msg; + int ret; - ret = __mbox_msg_send(mbox, (mbox_msg_t)rq->special); - if (ret) { + while (kfifo_len(&mq->fifo)) { + if (__mbox_poll_for_space(mbox)) { omap_mbox_enable_irq(mbox, IRQ_TX); - blk_requeue_request(q, rq); - return; + break; } - blk_end_request_all(rq, 0); + + ret = kfifo_out(&mq->fifo, (unsigned char *)&msg, + sizeof(msg)); + WARN_ON(ret != sizeof(msg)); + + mbox_fifo_write(mbox, msg); } } @@ -131,36 +139,21 @@ static void mbox_rx_work(struct work_struct *work) { struct omap_mbox_queue *mq = container_of(work, struct omap_mbox_queue, work); - struct omap_mbox *mbox = mq->queue->queuedata; - struct request_queue *q = mbox->rxq->queue; - struct request *rq; mbox_msg_t msg; - unsigned long flags; + int len; - while (1) { - spin_lock_irqsave(q->queue_lock, flags); - rq = blk_fetch_request(q); - spin_unlock_irqrestore(q->queue_lock, flags); - if (!rq) - break; + while (kfifo_len(&mq->fifo) >= sizeof(msg)) { + len = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg)); + WARN_ON(len != sizeof(msg)); - msg = (mbox_msg_t)rq->special; - blk_end_request_all(rq, 0); - mbox->rxq->callback((void *)msg); + if (mq->callback) + mq->callback((void *)msg); } } /* * Mailbox interrupt handler */ -static void mbox_txq_fn(struct request_queue *q) -{ -} - -static void mbox_rxq_fn(struct request_queue *q) -{ -} - static void __mbox_tx_interrupt(struct omap_mbox *mbox) { omap_mbox_disable_irq(mbox, IRQ_TX); @@ -170,19 +163,22 @@ static void __mbox_tx_interrupt(struct omap_mbox *mbox) static void __mbox_rx_interrupt(struct omap_mbox *mbox) { - struct request *rq; + struct omap_mbox_queue *mq = mbox->rxq; mbox_msg_t msg; - struct request_queue *q = mbox->rxq->queue; + int len; while (!mbox_fifo_empty(mbox)) { - rq = blk_get_request(q, WRITE, GFP_ATOMIC); - if (unlikely(!rq)) + if (unlikely(kfifo_avail(&mq->fifo) < sizeof(msg))) { + omap_mbox_disable_irq(mbox, IRQ_RX); + rq_full = true; goto nomem; + } msg = mbox_fifo_read(mbox); + len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg)); + WARN_ON(len != sizeof(msg)); - blk_insert_request(q, rq, 0, (void *)msg); if (mbox->ops->type == OMAP_MBOX_TYPE1) break; } @@ -207,11 +203,9 @@ static irqreturn_t mbox_interrupt(int irq, void *p) } static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox, - request_fn_proc *proc, void (*work) (struct work_struct *), void (*tasklet)(unsigned long)) { - struct request_queue *q; struct omap_mbox_queue *mq; mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL); @@ -220,11 +214,8 @@ static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox, spin_lock_init(&mq->lock); - q = blk_init_queue(proc, &mq->lock); - if (!q) + if (kfifo_alloc(&mq->fifo, mbox_kfifo_size, GFP_KERNEL)) goto error; - q->queuedata = mbox; - mq->queue = q; if (work) INIT_WORK(&mq->work, work); @@ -239,7 +230,7 @@ error: static void mbox_queue_free(struct omap_mbox_queue *q) { - blk_cleanup_queue(q->queue); + kfifo_free(&q->fifo); kfree(q); } @@ -248,35 +239,35 @@ static int omap_mbox_startup(struct omap_mbox *mbox) int ret = 0; struct omap_mbox_queue *mq; - if (likely(mbox->ops->startup)) { - write_lock(&mboxes_lock); + if (mbox->ops->startup) { + mutex_lock(&mbox_configured_lock); if (!mbox_configured) ret = mbox->ops->startup(mbox); - if (unlikely(ret)) { - write_unlock(&mboxes_lock); + if (ret) { + mutex_unlock(&mbox_configured_lock); return ret; } mbox_configured++; - write_unlock(&mboxes_lock); + mutex_unlock(&mbox_configured_lock); } ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED, mbox->name, mbox); - if (unlikely(ret)) { + if (ret) { printk(KERN_ERR "failed to register mailbox interrupt:%d\n", ret); goto fail_request_irq; } - mq = mbox_queue_alloc(mbox, mbox_txq_fn, NULL, mbox_tx_tasklet); + mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet); if (!mq) { ret = -ENOMEM; goto fail_alloc_txq; } mbox->txq = mq; - mq = mbox_queue_alloc(mbox, mbox_rxq_fn, mbox_rx_work, NULL); + mq = mbox_queue_alloc(mbox, mbox_rx_work, NULL); if (!mq) { ret = -ENOMEM; goto fail_alloc_rxq; @@ -290,7 +281,7 @@ static int omap_mbox_startup(struct omap_mbox *mbox) fail_alloc_txq: free_irq(mbox->irq, mbox); fail_request_irq: - if (unlikely(mbox->ops->shutdown)) + if (mbox->ops->shutdown) mbox->ops->shutdown(mbox); return ret; @@ -298,31 +289,20 @@ static int omap_mbox_startup(struct omap_mbox *mbox) static void omap_mbox_fini(struct omap_mbox *mbox) { + free_irq(mbox->irq, mbox); + tasklet_kill(&mbox->txq->tasklet); + flush_work(&mbox->rxq->work); mbox_queue_free(mbox->txq); mbox_queue_free(mbox->rxq); - free_irq(mbox->irq, mbox); - - if (unlikely(mbox->ops->shutdown)) { - write_lock(&mboxes_lock); + if (mbox->ops->shutdown) { + mutex_lock(&mbox_configured_lock); if (mbox_configured > 0) mbox_configured--; if (!mbox_configured) mbox->ops->shutdown(mbox); - write_unlock(&mboxes_lock); - } -} - -static struct omap_mbox **find_mboxes(const char *name) -{ - struct omap_mbox **p; - - for (p = &mboxes; *p; p = &(*p)->next) { - if (strcmp((*p)->name, name) == 0) - break; + mutex_unlock(&mbox_configured_lock); } - - return p; } struct omap_mbox *omap_mbox_get(const char *name) @@ -330,14 +310,15 @@ struct omap_mbox *omap_mbox_get(const char *name) struct omap_mbox *mbox; int ret; - read_lock(&mboxes_lock); - mbox = *(find_mboxes(name)); - if (mbox == NULL) { - read_unlock(&mboxes_lock); - return ERR_PTR(-ENOENT); - } + if (!mboxes) + return ERR_PTR(-EINVAL); - read_unlock(&mboxes_lock); + for (mbox = *mboxes; mbox; mbox++) + if (!strcmp(mbox->name, name)) + break; + + if (!mbox) + return ERR_PTR(-ENOENT); ret = omap_mbox_startup(mbox); if (ret) @@ -353,70 +334,77 @@ void omap_mbox_put(struct omap_mbox *mbox) } EXPORT_SYMBOL(omap_mbox_put); -int omap_mbox_register(struct device *parent, struct omap_mbox *mbox) +static struct class omap_mbox_class = { .name = "mbox", }; + +int omap_mbox_register(struct device *parent, struct omap_mbox **list) { - int ret = 0; - struct omap_mbox **tmp; + int ret; + int i; - if (!mbox) + mboxes = list; + if (!mboxes) return -EINVAL; - if (mbox->next) - return -EBUSY; - - write_lock(&mboxes_lock); - tmp = find_mboxes(mbox->name); - if (*tmp) { - ret = -EBUSY; - write_unlock(&mboxes_lock); - goto err_find; - } - *tmp = mbox; - write_unlock(&mboxes_lock); + for (i = 0; mboxes[i]; i++) { + struct omap_mbox *mbox = mboxes[i]; + mbox->dev = device_create(&omap_mbox_class, + parent, 0, mbox, "%s", mbox->name); + if (IS_ERR(mbox->dev)) { + ret = PTR_ERR(mbox->dev); + goto err_out; + } + } return 0; -err_find: +err_out: + while (i--) + device_unregister(mboxes[i]->dev); return ret; } EXPORT_SYMBOL(omap_mbox_register); -int omap_mbox_unregister(struct omap_mbox *mbox) +int omap_mbox_unregister(void) { - struct omap_mbox **tmp; - - write_lock(&mboxes_lock); - tmp = &mboxes; - while (*tmp) { - if (mbox == *tmp) { - *tmp = mbox->next; - mbox->next = NULL; - write_unlock(&mboxes_lock); - return 0; - } - tmp = &(*tmp)->next; - } - write_unlock(&mboxes_lock); + int i; + + if (!mboxes) + return -EINVAL; - return -EINVAL; + for (i = 0; mboxes[i]; i++) + device_unregister(mboxes[i]->dev); + mboxes = NULL; + return 0; } EXPORT_SYMBOL(omap_mbox_unregister); static int __init omap_mbox_init(void) { + int err; + + err = class_register(&omap_mbox_class); + if (err) + return err; + mboxd = create_workqueue("mboxd"); if (!mboxd) return -ENOMEM; + /* kfifo size sanity check: alignment and minimal size */ + mbox_kfifo_size = ALIGN(mbox_kfifo_size, sizeof(mbox_msg_t)); + mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size, sizeof(mbox_msg_t)); + return 0; } -module_init(omap_mbox_init); +subsys_initcall(omap_mbox_init); static void __exit omap_mbox_exit(void) { destroy_workqueue(mboxd); + class_unregister(&omap_mbox_class); } module_exit(omap_mbox_exit); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("omap mailbox: interrupt driven messaging"); -MODULE_AUTHOR("Toshihiro Kobayashi and Hiroshi DOYU"); +MODULE_AUTHOR("Toshihiro Kobayashi"); +MODULE_AUTHOR("Hiroshi DOYU"); diff --git a/arch/arm/plat-omap/mux.c b/arch/arm/plat-omap/mux.c index 06703635ace1..0d4aa0d5876c 100644 --- a/arch/arm/plat-omap/mux.c +++ b/arch/arm/plat-omap/mux.c @@ -54,7 +54,7 @@ int __init_or_module omap_cfg_reg(const unsigned long index) { struct pin_config *reg; - if (cpu_is_omap34xx() || cpu_is_omap44xx()) { + if (!cpu_class_is_omap1()) { printk(KERN_ERR "mux: Broken omap_cfg_reg(%lu) entry\n", index); WARN_ON(1); diff --git a/arch/arm/plat-omap/omap-pm-noop.c b/arch/arm/plat-omap/omap-pm-noop.c index 186bca82cfab..e129ce80c53b 100644 --- a/arch/arm/plat-omap/omap-pm-noop.c +++ b/arch/arm/plat-omap/omap-pm-noop.c @@ -34,11 +34,11 @@ struct omap_opp *l3_opps; * Device-driver-originated constraints (via board-*.c files) */ -void omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t) +int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t) { if (!dev || t < -1) { - WARN_ON(1); - return; + WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); + return -EINVAL; }; if (t == -1) @@ -58,14 +58,16 @@ void omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t) * * TI CDP code can call constraint_set here. */ + + return 0; } -void omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r) +int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r) { if (!dev || (agent_id != OCP_INITIATOR_AGENT && agent_id != OCP_TARGET_AGENT)) { - WARN_ON(1); - return; + WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); + return -EINVAL; }; if (r == 0) @@ -83,13 +85,16 @@ void omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r) * * TI CDP code can call constraint_set here on the VDD2 OPP. */ + + return 0; } -void omap_pm_set_max_dev_wakeup_lat(struct device *dev, long t) +int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev, + long t) { - if (!dev || t < -1) { - WARN_ON(1); - return; + if (!req_dev || !dev || t < -1) { + WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); + return -EINVAL; }; if (t == -1) @@ -111,13 +116,15 @@ void omap_pm_set_max_dev_wakeup_lat(struct device *dev, long t) * * TI CDP code can call constraint_set here. */ + + return 0; } -void omap_pm_set_max_sdma_lat(struct device *dev, long t) +int omap_pm_set_max_sdma_lat(struct device *dev, long t) { if (!dev || t < -1) { - WARN_ON(1); - return; + WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); + return -EINVAL; }; if (t == -1) @@ -139,8 +146,36 @@ void omap_pm_set_max_sdma_lat(struct device *dev, long t) * TI CDP code can call constraint_set here. */ + return 0; } +int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r) +{ + if (!dev || !c || r < 0) { + WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); + return -EINVAL; + } + + if (r == 0) + pr_debug("OMAP PM: remove min clk rate constraint: " + "dev %s\n", dev_name(dev)); + else + pr_debug("OMAP PM: add min clk rate constraint: " + "dev %s, rate = %ld Hz\n", dev_name(dev), r); + + /* + * Code in a real implementation should keep track of these + * constraints on the clock, and determine the highest minimum + * clock rate. It should iterate over each OPP and determine + * whether the OPP will result in a clock rate that would + * satisfy this constraint (and any other PM constraint in effect + * at that time). Once it finds the lowest-voltage OPP that + * meets those conditions, it should switch to it, or return + * an error if the code is not capable of doing so. + */ + + return 0; +} /* * DSP Bridge-specific constraints diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c index f899603051ac..d2b160942ccc 100644 --- a/arch/arm/plat-omap/omap_device.c +++ b/arch/arm/plat-omap/omap_device.c @@ -1,7 +1,7 @@ /* * omap_device implementation * - * Copyright (C) 2009 Nokia Corporation + * Copyright (C) 2009-2010 Nokia Corporation * Paul Walmsley, Kevin Hilman * * Developed in collaboration with (alphabetical order): Benoit @@ -90,8 +90,11 @@ #define USE_WAKEUP_LAT 0 #define IGNORE_WAKEUP_LAT 1 - -#define OMAP_DEVICE_MAGIC 0xf00dcafe +/* + * OMAP_DEVICE_MAGIC: used to determine whether a struct omap_device + * obtained via container_of() is in fact a struct omap_device + */ +#define OMAP_DEVICE_MAGIC 0xf00dcafe /* Private functions */ @@ -359,7 +362,7 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id, struct omap_device *od; char *pdev_name2; struct resource *res = NULL; - int res_count; + int i, res_count; struct omap_hwmod **hwmods; if (!ohs || oh_cnt == 0 || !pdev_name) @@ -404,7 +407,9 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id, od->pdev.num_resources = res_count; od->pdev.resource = res; - platform_device_add_data(&od->pdev, pdata, pdata_len); + ret = platform_device_add_data(&od->pdev, pdata, pdata_len); + if (ret) + goto odbs_exit4; od->pm_lats = pm_lats; od->pm_lats_cnt = pm_lats_cnt; @@ -416,6 +421,9 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id, else ret = omap_device_register(od); + for (i = 0; i < oh_cnt; i++) + hwmods[i]->od = od; + if (ret) goto odbs_exit4; @@ -652,6 +660,25 @@ struct powerdomain *omap_device_get_pwrdm(struct omap_device *od) return omap_hwmod_get_pwrdm(od->hwmods[0]); } +/** + * omap_device_get_mpu_rt_va - return the MPU's virtual addr for the hwmod base + * @od: struct omap_device * + * + * Return the MPU's virtual address for the base of the hwmod, from + * the ioremap() that the hwmod code does. Only valid if there is one + * hwmod associated with this device. Returns NULL if there are zero + * or more than one hwmods associated with this omap_device; + * otherwise, passes along the return value from + * omap_hwmod_get_mpu_rt_va(). + */ +void __iomem *omap_device_get_rt_va(struct omap_device *od) +{ + if (od->hwmods_cnt != 1) + return NULL; + + return omap_hwmod_get_mpu_rt_va(od->hwmods[0]); +} + /* * Public functions intended for use in omap_device_pm_latency * .activate_func and .deactivate_func function pointers diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c index d3bf17cd36f3..f3570884883e 100644 --- a/arch/arm/plat-omap/usb.c +++ b/arch/arm/plat-omap/usb.c @@ -22,524 +22,13 @@ #include <linux/module.h> #include <linux/kernel.h> -#include <linux/types.h> -#include <linux/errno.h> #include <linux/init.h> #include <linux/platform_device.h> -#include <linux/usb/otg.h> #include <linux/io.h> -#include <asm/irq.h> -#include <asm/system.h> -#include <mach/hardware.h> - -#include <plat/control.h> -#include <plat/mux.h> #include <plat/usb.h> #include <plat/board.h> -#ifdef CONFIG_ARCH_OMAP1 - -#define INT_USB_IRQ_GEN IH2_BASE + 20 -#define INT_USB_IRQ_NISO IH2_BASE + 30 -#define INT_USB_IRQ_ISO IH2_BASE + 29 -#define INT_USB_IRQ_HGEN INT_USB_HHC_1 -#define INT_USB_IRQ_OTG IH2_BASE + 8 - -#else - -#define INT_USB_IRQ_GEN INT_24XX_USB_IRQ_GEN -#define INT_USB_IRQ_NISO INT_24XX_USB_IRQ_NISO -#define INT_USB_IRQ_ISO INT_24XX_USB_IRQ_ISO -#define INT_USB_IRQ_HGEN INT_24XX_USB_IRQ_HGEN -#define INT_USB_IRQ_OTG INT_24XX_USB_IRQ_OTG - -#endif - - -/* These routines should handle the standard chip-specific modes - * for usb0/1/2 ports, covering basic mux and transceiver setup. - * - * Some board-*.c files will need to set up additional mux options, - * like for suspend handling, vbus sensing, GPIOs, and the D+ pullup. - */ - -/* TESTED ON: - * - 1611B H2 (with usb1 mini-AB) using standard Mini-B or OTG cables - * - 5912 OSK OHCI (with usb0 standard-A), standard A-to-B cables - * - 5912 OSK UDC, with *nonstandard* A-to-A cable - * - 1510 Innovator UDC with bundled usb0 cable - * - 1510 Innovator OHCI with bundled usb1/usb2 cable - * - 1510 Innovator OHCI with custom usb0 cable, feeding 5V VBUS - * - 1710 custom development board using alternate pin group - * - 1710 H3 (with usb1 mini-AB) using standard Mini-B or OTG cables - */ - -/*-------------------------------------------------------------------------*/ - -#if defined(CONFIG_ARCH_OMAP_OTG) || defined(CONFIG_ARCH_OMAP15XX) - -static void omap2_usb_devconf_clear(u8 port, u32 mask) -{ - u32 r; - - r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); - r &= ~USBTXWRMODEI(port, mask); - omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0); -} - -static void omap2_usb_devconf_set(u8 port, u32 mask) -{ - u32 r; - - r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); - r |= USBTXWRMODEI(port, mask); - omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0); -} - -static void omap2_usb2_disable_5pinbitll(void) -{ - u32 r; - - r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); - r &= ~(USBTXWRMODEI(2, USB_BIDIR_TLL) | USBT2TLL5PI); - omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0); -} - -static void omap2_usb2_enable_5pinunitll(void) -{ - u32 r; - - r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); - r |= USBTXWRMODEI(2, USB_UNIDIR_TLL) | USBT2TLL5PI; - omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0); -} - -static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) -{ - u32 syscon1 = 0; - - if (cpu_is_omap24xx()) - omap2_usb_devconf_clear(0, USB_BIDIR_TLL); - - if (nwires == 0) { - if (cpu_class_is_omap1() && !cpu_is_omap15xx()) { - u32 l; - - /* pulldown D+/D- */ - l = omap_readl(USB_TRANSCEIVER_CTRL); - l &= ~(3 << 1); - omap_writel(l, USB_TRANSCEIVER_CTRL); - } - return 0; - } - - if (is_device) { - if (cpu_is_omap24xx()) - omap_cfg_reg(J20_24XX_USB0_PUEN); - else if (cpu_is_omap7xx()) { - omap_cfg_reg(AA17_7XX_USB_DM); - omap_cfg_reg(W16_7XX_USB_PU_EN); - omap_cfg_reg(W17_7XX_USB_VBUSI); - omap_cfg_reg(W18_7XX_USB_DMCK_OUT); - omap_cfg_reg(W19_7XX_USB_DCRST); - } else - omap_cfg_reg(W4_USB_PUEN); - } - - /* internal transceiver (unavailable on 17xx, 24xx) */ - if (!cpu_class_is_omap2() && nwires == 2) { - u32 l; - - // omap_cfg_reg(P9_USB_DP); - // omap_cfg_reg(R8_USB_DM); - - if (cpu_is_omap15xx()) { - /* This works on 1510-Innovator */ - return 0; - } - - /* NOTES: - * - peripheral should configure VBUS detection! - * - only peripherals may use the internal D+/D- pulldowns - * - OTG support on this port not yet written - */ - - /* Don't do this for omap7xx -- it causes USB to not work correctly */ - if (!cpu_is_omap7xx()) { - l = omap_readl(USB_TRANSCEIVER_CTRL); - l &= ~(7 << 4); - if (!is_device) - l |= (3 << 1); - omap_writel(l, USB_TRANSCEIVER_CTRL); - } - - return 3 << 16; - } - - /* alternate pin config, external transceiver */ - if (cpu_is_omap15xx()) { - printk(KERN_ERR "no usb0 alt pin config on 15xx\n"); - return 0; - } - - if (cpu_is_omap24xx()) { - omap_cfg_reg(K18_24XX_USB0_DAT); - omap_cfg_reg(K19_24XX_USB0_TXEN); - omap_cfg_reg(J14_24XX_USB0_SE0); - if (nwires != 3) - omap_cfg_reg(J18_24XX_USB0_RCV); - } else { - omap_cfg_reg(V6_USB0_TXD); - omap_cfg_reg(W9_USB0_TXEN); - omap_cfg_reg(W5_USB0_SE0); - if (nwires != 3) - omap_cfg_reg(Y5_USB0_RCV); - } - - /* NOTE: SPEED and SUSP aren't configured here. OTG hosts - * may be able to use I2C requests to set those bits along - * with VBUS switching and overcurrent detection. - */ - - if (cpu_class_is_omap1() && nwires != 6) { - u32 l; - - l = omap_readl(USB_TRANSCEIVER_CTRL); - l &= ~CONF_USB2_UNI_R; - omap_writel(l, USB_TRANSCEIVER_CTRL); - } - - switch (nwires) { - case 3: - syscon1 = 2; - if (cpu_is_omap24xx()) - omap2_usb_devconf_set(0, USB_BIDIR); - break; - case 4: - syscon1 = 1; - if (cpu_is_omap24xx()) - omap2_usb_devconf_set(0, USB_BIDIR); - break; - case 6: - syscon1 = 3; - if (cpu_is_omap24xx()) { - omap_cfg_reg(J19_24XX_USB0_VP); - omap_cfg_reg(K20_24XX_USB0_VM); - omap2_usb_devconf_set(0, USB_UNIDIR); - } else { - u32 l; - - omap_cfg_reg(AA9_USB0_VP); - omap_cfg_reg(R9_USB0_VM); - l = omap_readl(USB_TRANSCEIVER_CTRL); - l |= CONF_USB2_UNI_R; - omap_writel(l, USB_TRANSCEIVER_CTRL); - } - break; - default: - printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", - 0, nwires); - } - return syscon1 << 16; -} - -static u32 __init omap_usb1_init(unsigned nwires) -{ - u32 syscon1 = 0; - - if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6) { - u32 l; - - l = omap_readl(USB_TRANSCEIVER_CTRL); - l &= ~CONF_USB1_UNI_R; - omap_writel(l, USB_TRANSCEIVER_CTRL); - } - if (cpu_is_omap24xx()) - omap2_usb_devconf_clear(1, USB_BIDIR_TLL); - - if (nwires == 0) - return 0; - - /* external transceiver */ - if (cpu_class_is_omap1()) { - omap_cfg_reg(USB1_TXD); - omap_cfg_reg(USB1_TXEN); - if (nwires != 3) - omap_cfg_reg(USB1_RCV); - } - - if (cpu_is_omap15xx()) { - omap_cfg_reg(USB1_SEO); - omap_cfg_reg(USB1_SPEED); - // SUSP - } else if (cpu_is_omap1610() || cpu_is_omap5912()) { - omap_cfg_reg(W13_1610_USB1_SE0); - omap_cfg_reg(R13_1610_USB1_SPEED); - // SUSP - } else if (cpu_is_omap1710()) { - omap_cfg_reg(R13_1710_USB1_SE0); - // SUSP - } else if (cpu_is_omap24xx()) { - /* NOTE: board-specific code must set up pin muxing for usb1, - * since each signal could come out on either of two balls. - */ - } else { - pr_debug("usb%d cpu unrecognized\n", 1); - return 0; - } - - switch (nwires) { - case 2: - if (!cpu_is_omap24xx()) - goto bad; - /* NOTE: board-specific code must override this setting if - * this TLL link is not using DP/DM - */ - syscon1 = 1; - omap2_usb_devconf_set(1, USB_BIDIR_TLL); - break; - case 3: - syscon1 = 2; - if (cpu_is_omap24xx()) - omap2_usb_devconf_set(1, USB_BIDIR); - break; - case 4: - syscon1 = 1; - if (cpu_is_omap24xx()) - omap2_usb_devconf_set(1, USB_BIDIR); - break; - case 6: - if (cpu_is_omap24xx()) - goto bad; - syscon1 = 3; - omap_cfg_reg(USB1_VP); - omap_cfg_reg(USB1_VM); - if (!cpu_is_omap15xx()) { - u32 l; - - l = omap_readl(USB_TRANSCEIVER_CTRL); - l |= CONF_USB1_UNI_R; - omap_writel(l, USB_TRANSCEIVER_CTRL); - } - break; - default: -bad: - printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", - 1, nwires); - } - return syscon1 << 20; -} - -static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) -{ - u32 syscon1 = 0; - - if (cpu_is_omap24xx()) { - omap2_usb2_disable_5pinbitll(); - alt_pingroup = 0; - } - - /* NOTE omap1 erratum: must leave USB2_UNI_R set if usb0 in use */ - if (alt_pingroup || nwires == 0) - return 0; - - if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6) { - u32 l; - - l = omap_readl(USB_TRANSCEIVER_CTRL); - l &= ~CONF_USB2_UNI_R; - omap_writel(l, USB_TRANSCEIVER_CTRL); - } - - /* external transceiver */ - if (cpu_is_omap15xx()) { - omap_cfg_reg(USB2_TXD); - omap_cfg_reg(USB2_TXEN); - omap_cfg_reg(USB2_SEO); - if (nwires != 3) - omap_cfg_reg(USB2_RCV); - /* there is no USB2_SPEED */ - } else if (cpu_is_omap16xx()) { - omap_cfg_reg(V6_USB2_TXD); - omap_cfg_reg(W9_USB2_TXEN); - omap_cfg_reg(W5_USB2_SE0); - if (nwires != 3) - omap_cfg_reg(Y5_USB2_RCV); - // FIXME omap_cfg_reg(USB2_SPEED); - } else if (cpu_is_omap24xx()) { - omap_cfg_reg(Y11_24XX_USB2_DAT); - omap_cfg_reg(AA10_24XX_USB2_SE0); - if (nwires > 2) - omap_cfg_reg(AA12_24XX_USB2_TXEN); - if (nwires > 3) - omap_cfg_reg(AA6_24XX_USB2_RCV); - } else { - pr_debug("usb%d cpu unrecognized\n", 1); - return 0; - } - // if (cpu_class_is_omap1()) omap_cfg_reg(USB2_SUSP); - - switch (nwires) { - case 2: - if (!cpu_is_omap24xx()) - goto bad; - /* NOTE: board-specific code must override this setting if - * this TLL link is not using DP/DM - */ - syscon1 = 1; - omap2_usb_devconf_set(2, USB_BIDIR_TLL); - break; - case 3: - syscon1 = 2; - if (cpu_is_omap24xx()) - omap2_usb_devconf_set(2, USB_BIDIR); - break; - case 4: - syscon1 = 1; - if (cpu_is_omap24xx()) - omap2_usb_devconf_set(2, USB_BIDIR); - break; - case 5: - if (!cpu_is_omap24xx()) - goto bad; - omap_cfg_reg(AA4_24XX_USB2_TLLSE0); - /* NOTE: board-specific code must override this setting if - * this TLL link is not using DP/DM. Something must also - * set up OTG_SYSCON2.HMC_TLL{ATTACH,SPEED} - */ - syscon1 = 3; - omap2_usb2_enable_5pinunitll(); - break; - case 6: - if (cpu_is_omap24xx()) - goto bad; - syscon1 = 3; - if (cpu_is_omap15xx()) { - omap_cfg_reg(USB2_VP); - omap_cfg_reg(USB2_VM); - } else { - u32 l; - - omap_cfg_reg(AA9_USB2_VP); - omap_cfg_reg(R9_USB2_VM); - l = omap_readl(USB_TRANSCEIVER_CTRL); - l |= CONF_USB2_UNI_R; - omap_writel(l, USB_TRANSCEIVER_CTRL); - } - break; - default: -bad: - printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", - 2, nwires); - } - return syscon1 << 24; -} - -#endif - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_USB_GADGET_OMAP - -static struct resource udc_resources[] = { - /* order is significant! */ - { /* registers */ - .start = UDC_BASE, - .end = UDC_BASE + 0xff, - .flags = IORESOURCE_MEM, - }, { /* general IRQ */ - .start = INT_USB_IRQ_GEN, - .flags = IORESOURCE_IRQ, - }, { /* PIO IRQ */ - .start = INT_USB_IRQ_NISO, - .flags = IORESOURCE_IRQ, - }, { /* SOF IRQ */ - .start = INT_USB_IRQ_ISO, - .flags = IORESOURCE_IRQ, - }, -}; - -static u64 udc_dmamask = ~(u32)0; - -static struct platform_device udc_device = { - .name = "omap_udc", - .id = -1, - .dev = { - .dma_mask = &udc_dmamask, - .coherent_dma_mask = 0xffffffff, - }, - .num_resources = ARRAY_SIZE(udc_resources), - .resource = udc_resources, -}; - -#endif - -#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) - -/* The dmamask must be set for OHCI to work */ -static u64 ohci_dmamask = ~(u32)0; - -static struct resource ohci_resources[] = { - { - .start = OMAP_OHCI_BASE, - .end = OMAP_OHCI_BASE + 0xff, - .flags = IORESOURCE_MEM, - }, - { - .start = INT_USB_IRQ_HGEN, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device ohci_device = { - .name = "ohci", - .id = -1, - .dev = { - .dma_mask = &ohci_dmamask, - .coherent_dma_mask = 0xffffffff, - }, - .num_resources = ARRAY_SIZE(ohci_resources), - .resource = ohci_resources, -}; - -#endif - -#if defined(CONFIG_USB_OTG) && defined(CONFIG_ARCH_OMAP_OTG) - -static struct resource otg_resources[] = { - /* order is significant! */ - { - .start = OTG_BASE, - .end = OTG_BASE + 0xff, - .flags = IORESOURCE_MEM, - }, { - .start = INT_USB_IRQ_OTG, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device otg_device = { - .name = "omap_otg", - .id = -1, - .num_resources = ARRAY_SIZE(otg_resources), - .resource = otg_resources, -}; - -#endif - -/*-------------------------------------------------------------------------*/ - -// FIXME correct answer depends on hmc_mode, -// as does (on omap1) any nonzero value for config->otg port number -#ifdef CONFIG_USB_GADGET_OMAP -#define is_usb0_device(config) 1 -#else -#define is_usb0_device(config) 0 -#endif - -/*-------------------------------------------------------------------------*/ - #ifdef CONFIG_ARCH_OMAP_OTG void __init @@ -560,9 +49,9 @@ omap_otg_init(struct omap_usb_config *config) /* pin muxing and transceiver pinouts */ if (config->pins[0] > 2) /* alt pingroup 2 */ alt_pingroup = 1; - syscon |= omap_usb0_init(config->pins[0], is_usb0_device(config)); - syscon |= omap_usb1_init(config->pins[1]); - syscon |= omap_usb2_init(config->pins[2], alt_pingroup); + syscon |= config->usb0_init(config->pins[0], is_usb0_device(config)); + syscon |= config->usb1_init(config->pins[1]); + syscon |= config->usb2_init(config->pins[2], alt_pingroup); pr_debug("OTG_SYSCON_1 = %08x\n", omap_readl(OTG_SYSCON_1)); omap_writel(syscon, OTG_SYSCON_1); @@ -610,15 +99,11 @@ omap_otg_init(struct omap_usb_config *config) #ifdef CONFIG_USB_GADGET_OMAP if (config->otg || config->register_dev) { + struct platform_device *udc_device = config->udc_device; + syscon &= ~DEV_IDLE_EN; - udc_device.dev.platform_data = config; - /* IRQ numbers for omap7xx */ - if(cpu_is_omap7xx()) { - udc_resources[1].start = INT_7XX_USB_GENI; - udc_resources[2].start = INT_7XX_USB_NON_ISO; - udc_resources[3].start = INT_7XX_USB_ISO; - } - status = platform_device_register(&udc_device); + udc_device->dev.platform_data = config; + status = platform_device_register(udc_device); if (status) pr_debug("can't register UDC device, %d\n", status); } @@ -626,11 +111,11 @@ omap_otg_init(struct omap_usb_config *config) #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) if (config->otg || config->register_host) { + struct platform_device *ohci_device = config->ohci_device; + syscon &= ~HST_IDLE_EN; - ohci_device.dev.platform_data = config; - if (cpu_is_omap7xx()) - ohci_resources[1].start = INT_7XX_USB_HHC_1; - status = platform_device_register(&ohci_device); + ohci_device->dev.platform_data = config; + status = platform_device_register(ohci_device); if (status) pr_debug("can't register OHCI device, %d\n", status); } @@ -638,11 +123,11 @@ omap_otg_init(struct omap_usb_config *config) #ifdef CONFIG_USB_OTG if (config->otg) { + struct platform_device *otg_device = config->otg_device; + syscon &= ~OTG_IDLE_EN; - otg_device.dev.platform_data = config; - if (cpu_is_omap7xx()) - otg_resources[1].start = INT_7XX_USB_OTG; - status = platform_device_register(&otg_device); + otg_device->dev.platform_data = config; + status = platform_device_register(otg_device); if (status) pr_debug("can't register OTG device, %d\n", status); } @@ -654,102 +139,5 @@ omap_otg_init(struct omap_usb_config *config) } #else -static inline void omap_otg_init(struct omap_usb_config *config) {} -#endif - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_ARCH_OMAP15XX - -/* ULPD_DPLL_CTRL */ -#define DPLL_IOB (1 << 13) -#define DPLL_PLL_ENABLE (1 << 4) -#define DPLL_LOCK (1 << 0) - -/* ULPD_APLL_CTRL */ -#define APLL_NDPLL_SWITCH (1 << 0) - - -static void __init omap_1510_usb_init(struct omap_usb_config *config) -{ - unsigned int val; - u16 w; - - omap_usb0_init(config->pins[0], is_usb0_device(config)); - omap_usb1_init(config->pins[1]); - omap_usb2_init(config->pins[2], 0); - - val = omap_readl(MOD_CONF_CTRL_0) & ~(0x3f << 1); - val |= (config->hmc_mode << 1); - omap_writel(val, MOD_CONF_CTRL_0); - - printk("USB: hmc %d", config->hmc_mode); - if (config->pins[0]) - printk(", usb0 %d wires%s", config->pins[0], - is_usb0_device(config) ? " (dev)" : ""); - if (config->pins[1]) - printk(", usb1 %d wires", config->pins[1]); - if (config->pins[2]) - printk(", usb2 %d wires", config->pins[2]); - printk("\n"); - - /* use DPLL for 48 MHz function clock */ - pr_debug("APLL %04x DPLL %04x REQ %04x\n", omap_readw(ULPD_APLL_CTRL), - omap_readw(ULPD_DPLL_CTRL), omap_readw(ULPD_SOFT_REQ)); - - w = omap_readw(ULPD_APLL_CTRL); - w &= ~APLL_NDPLL_SWITCH; - omap_writew(w, ULPD_APLL_CTRL); - - w = omap_readw(ULPD_DPLL_CTRL); - w |= DPLL_IOB | DPLL_PLL_ENABLE; - omap_writew(w, ULPD_DPLL_CTRL); - - w = omap_readw(ULPD_SOFT_REQ); - w |= SOFT_UDC_REQ | SOFT_DPLL_REQ; - omap_writew(w, ULPD_SOFT_REQ); - - while (!(omap_readw(ULPD_DPLL_CTRL) & DPLL_LOCK)) - cpu_relax(); - -#ifdef CONFIG_USB_GADGET_OMAP - if (config->register_dev) { - int status; - - udc_device.dev.platform_data = config; - status = platform_device_register(&udc_device); - if (status) - pr_debug("can't register UDC device, %d\n", status); - /* udc driver gates 48MHz by D+ pullup */ - } -#endif - -#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) - if (config->register_host) { - int status; - - ohci_device.dev.platform_data = config; - status = platform_device_register(&ohci_device); - if (status) - pr_debug("can't register OHCI device, %d\n", status); - /* hcd explicitly gates 48MHz */ - } -#endif -} - -#else -static inline void omap_1510_usb_init(struct omap_usb_config *config) {} +void omap_otg_init(struct omap_usb_config *config) {} #endif - -/*-------------------------------------------------------------------------*/ - -void __init omap_usb_init(struct omap_usb_config *pdata) -{ - if (cpu_is_omap7xx() || cpu_is_omap16xx() || cpu_is_omap24xx()) - omap_otg_init(pdata); - else if (cpu_is_omap15xx()) - omap_1510_usb_init(pdata); - else - printk(KERN_ERR "USB: No init for your chip yet\n"); -} - |