From 994c84ea526ea1c348f63dc3aa7cfeec931bb612 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 6 Dec 2006 17:14:03 -0800 Subject: ARM: OMAP: h4 must have blinky leds!! This adds generic support for the "debug board" LEDs used by most of TI's OMAP reference boards, and board-specific support for the H4. It's derived from the not-as-generic stuff used by OMAP1 H2/H3/P2. Those should be able to switch easily to this version, and clean up some of the omap1-specific code. In addition to H4 support, one key improvement is supporting not just the "old" ARM debug LED API (with timer and idle LEDs, plus four that can be handy for kernel debugging), but it also supports the "new" generic LED API (most useful for usermode stuff IMO). Either or both APIs can be enabled. Signed-off-by: David Brownell Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap2/Kconfig | 1 + arch/arm/mach-omap2/board-h4.c | 14 ++++++++++++++ 2 files changed, 15 insertions(+) (limited to 'arch/arm/mach-omap2') diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index aab97ccf1e63..2a1aca7a6371 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -20,6 +20,7 @@ config MACH_OMAP_GENERIC config MACH_OMAP_H4 bool "OMAP 2420 H4 board" depends on ARCH_OMAP2 && ARCH_OMAP24XX + select OMAP_DEBUG_LEDS if LEDS || LEDS_OMAP_DEBUG config MACH_OMAP_APOLLON bool "OMAP 2420 Apollon board" diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c index 1e7ed6d22ca9..452193f01531 100644 --- a/arch/arm/mach-omap2/board-h4.c +++ b/arch/arm/mach-omap2/board-h4.c @@ -266,12 +266,26 @@ static struct platform_device h4_lcd_device = { .id = -1, }; +static struct resource h4_led_resources[] = { + [0] = { + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device h4_led_device = { + .name = "omap_dbg_led", + .id = -1, + .num_resources = ARRAY_SIZE(h4_led_resources), + .resource = h4_led_resources, +}; + static struct platform_device *h4_devices[] __initdata = { &h4_smc91x_device, &h4_flash_device, &h4_irda_device, &h4_kp_device, &h4_lcd_device, + &h4_led_device, }; static inline void __init h4_init_smc91x(void) -- cgit v1.2.3 From c40fae9525e6c29c87a4f4361ff0a8d67a36e448 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 7 Dec 2006 13:58:10 -0800 Subject: ARM: OMAP: Sync core code with linux-omap This patch syncs omap specific core code with linux-omap. Most of the changes are needed to fix bitrot caused by driver updates in linux-omap tree. Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap1/Kconfig | 3 + arch/arm/mach-omap1/Makefile | 1 - arch/arm/mach-omap1/devices.c | 71 ++++++++------- arch/arm/mach-omap2/Kconfig | 1 + arch/arm/mach-omap2/devices.c | 60 +++++++++++-- arch/arm/mach-omap2/gpmc.c | 12 ++- arch/arm/mach-omap2/io.c | 18 +++- arch/arm/plat-omap/Kconfig | 8 ++ arch/arm/plat-omap/Makefile | 3 +- arch/arm/plat-omap/common.c | 8 +- arch/arm/plat-omap/devices.c | 70 ++++++++++++++- arch/arm/plat-omap/dmtimer.c | 2 +- arch/arm/plat-omap/fb.c | 72 +++++++++++---- arch/arm/plat-omap/sram.c | 77 +++++++++------- arch/arm/plat-omap/usb.c | 199 +++++++++++++++++++++++++++++++++--------- 15 files changed, 470 insertions(+), 135 deletions(-) (limited to 'arch/arm/mach-omap2') diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig index 8781aaeb576b..18ea7313a499 100644 --- a/arch/arm/mach-omap1/Kconfig +++ b/arch/arm/mach-omap1/Kconfig @@ -22,6 +22,7 @@ comment "OMAP Board Type" config MACH_OMAP_INNOVATOR bool "TI Innovator" depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX) + select OMAP_MCBSP help TI OMAP 1510 or 1610 Innovator board support. Say Y here if you have such a board. @@ -29,6 +30,7 @@ config MACH_OMAP_INNOVATOR config MACH_OMAP_H2 bool "TI H2 Support" depends on ARCH_OMAP1 && ARCH_OMAP16XX + select OMAP_MCBSP help TI OMAP 1610/1611B H2 board support. Say Y here if you have such a board. @@ -36,6 +38,7 @@ config MACH_OMAP_H2 config MACH_OMAP_H3 bool "TI H3 Support" depends on ARCH_OMAP1 && ARCH_OMAP16XX + select GPIOEXPANDER_OMAP help TI OMAP 1710 H3 board support. Say Y here if you have such a board. diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile index 7165f74f78da..a8b9a00cea22 100644 --- a/arch/arm/mach-omap1/Makefile +++ b/arch/arm/mach-omap1/Makefile @@ -37,4 +37,3 @@ led-$(CONFIG_MACH_OMAP_INNOVATOR) += leds-innovator.o led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-h2p2-debug.o led-$(CONFIG_MACH_OMAP_OSK) += leds-osk.o obj-$(CONFIG_LEDS) += $(led-y) - diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c index 6dcd10ab4496..da8a3ac47e13 100644 --- a/arch/arm/mach-omap1/devices.c +++ b/arch/arm/mach-omap1/devices.c @@ -24,35 +24,6 @@ #include #include -#if defined(CONFIG_OMAP1610_IR) || defined(CONFIG_OMAP161O_IR_MODULE) - -static u64 irda_dmamask = 0xffffffff; - -static struct platform_device omap1610ir_device = { - .name = "omap1610-ir", - .id = -1, - .dev = { - .dma_mask = &irda_dmamask, - }, -}; - -static void omap_init_irda(void) -{ - /* FIXME define and use a boot tag, members something like: - * u8 uart; // uart1, or uart3 - * ... but driver only handles uart3 for now - * s16 fir_sel; // gpio for SIR vs FIR - * ... may prefer a callback for SIR/MIR/FIR mode select; - * while h2 uses a GPIO, H3 uses a gpio expander - */ - if (machine_is_omap_h2() - || machine_is_omap_h3()) - (void) platform_device_register(&omap1610ir_device); -} -#else -static inline void omap_init_irda(void) {} -#endif - /*-------------------------------------------------------------------------*/ #if defined(CONFIG_RTC_DRV_OMAP) || defined(CONFIG_RTC_DRV_OMAP_MODULE) @@ -90,6 +61,45 @@ static void omap_init_rtc(void) static inline void omap_init_rtc(void) {} #endif +#if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE) + +#if defined(CONFIG_ARCH_OMAP15XX) +# define OMAP1_MBOX_SIZE 0x23 +# define INT_DSP_MAILBOX1 INT_1510_DSP_MAILBOX1 +#elif defined(CONFIG_ARCH_OMAP16XX) +# define OMAP1_MBOX_SIZE 0x2f +# define INT_DSP_MAILBOX1 INT_1610_DSP_MAILBOX1 +#endif + +#define OMAP1_MBOX_BASE IO_ADDRESS(OMAP16XX_MAILBOX_BASE) + +static struct resource mbox_resources[] = { + { + .start = OMAP1_MBOX_BASE, + .end = OMAP1_MBOX_BASE + OMAP1_MBOX_SIZE, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_DSP_MAILBOX1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device mbox_device = { + .name = "mailbox", + .id = -1, + .num_resources = ARRAY_SIZE(mbox_resources), + .resource = mbox_resources, +}; + +static inline void omap_init_mbox(void) +{ + platform_device_register(&mbox_device); +} +#else +static inline void omap_init_mbox(void) { } +#endif + #if defined(CONFIG_OMAP_STI) #define OMAP1_STI_BASE IO_ADDRESS(0xfffea000) @@ -154,7 +164,8 @@ static int __init omap1_init_devices(void) /* please keep these calls, and their implementations above, * in alphabetical order so they're easier to sort through. */ - omap_init_irda(); + + omap_init_mbox(); omap_init_rtc(); omap_init_sti(); diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 2a1aca7a6371..7393109f5c30 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -9,6 +9,7 @@ config ARCH_OMAP2420 bool "OMAP2420 support" depends on ARCH_OMAP24XX select OMAP_DM_TIMER + select ARCH_OMAP_OTG comment "OMAP Board Type" depends on ARCH_OMAP2 diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index aa4322451e8b..b3ac9622f4a7 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -66,6 +66,40 @@ static void omap_init_i2c(void) {} #endif +#if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE) +#define OMAP2_MBOX_BASE IO_ADDRESS(OMAP24XX_MAILBOX_BASE) + +static struct resource mbox_resources[] = { + { + .start = OMAP2_MBOX_BASE, + .end = OMAP2_MBOX_BASE + 0x11f, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_24XX_MAIL_U0_MPU, + .flags = IORESOURCE_IRQ, + }, + { + .start = INT_24XX_MAIL_U3_MPU, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device mbox_device = { + .name = "mailbox", + .id = -1, + .num_resources = ARRAY_SIZE(mbox_resources), + .resource = mbox_resources, +}; + +static inline void omap_init_mbox(void) +{ + platform_device_register(&mbox_device); +} +#else +static inline void omap_init_mbox(void) { } +#endif + #if defined(CONFIG_OMAP_STI) #define OMAP2_STI_BASE IO_ADDRESS(0x48068000) @@ -111,29 +145,45 @@ static inline void omap_init_sti(void) {} #define OMAP2_MCSPI1_BASE 0x48098000 #define OMAP2_MCSPI2_BASE 0x4809a000 -/* FIXME: use resources instead */ - static struct omap2_mcspi_platform_config omap2_mcspi1_config = { - .base = io_p2v(OMAP2_MCSPI1_BASE), .num_cs = 4, }; +static struct resource omap2_mcspi1_resources[] = { + { + .start = OMAP2_MCSPI1_BASE, + .end = OMAP2_MCSPI1_BASE + 0xff, + .flags = IORESOURCE_MEM, + }, +}; + struct platform_device omap2_mcspi1 = { .name = "omap2_mcspi", .id = 1, + .num_resources = ARRAY_SIZE(omap2_mcspi1_resources), + .resource = omap2_mcspi1_resources, .dev = { .platform_data = &omap2_mcspi1_config, }, }; static struct omap2_mcspi_platform_config omap2_mcspi2_config = { - .base = io_p2v(OMAP2_MCSPI2_BASE), .num_cs = 2, }; +static struct resource omap2_mcspi2_resources[] = { + { + .start = OMAP2_MCSPI2_BASE, + .end = OMAP2_MCSPI2_BASE + 0xff, + .flags = IORESOURCE_MEM, + }, +}; + struct platform_device omap2_mcspi2 = { .name = "omap2_mcspi", .id = 2, + .num_resources = ARRAY_SIZE(omap2_mcspi2_resources), + .resource = omap2_mcspi2_resources, .dev = { .platform_data = &omap2_mcspi2_config, }, @@ -157,10 +207,10 @@ static int __init omap2_init_devices(void) * in alphabetical order so they're easier to sort through. */ omap_init_i2c(); + omap_init_mbox(); omap_init_mcspi(); omap_init_sti(); return 0; } arch_initcall(omap2_init_devices); - diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index d8f57824423f..54c836a98456 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -246,14 +246,22 @@ static int gpmc_cs_mem_enabled(int cs) return l & (1 << 6); } -static void gpmc_cs_set_reserved(int cs, int reserved) +int gpmc_cs_set_reserved(int cs, int reserved) { + if (cs > GPMC_CS_NUM) + return -ENODEV; + gpmc_cs_map &= ~(1 << cs); gpmc_cs_map |= (reserved ? 1 : 0) << cs; + + return 0; } -static int gpmc_cs_reserved(int cs) +int gpmc_cs_reserved(int cs) { + if (cs > GPMC_CS_NUM) + return -ENODEV; + return gpmc_cs_map & (1 << cs); } diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index a0728c33e5d9..59458642e9eb 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -40,9 +40,21 @@ static struct map_desc omap2_io_desc[] __initdata = { .type = MT_DEVICE }, { - .virtual = L4_24XX_VIRT, - .pfn = __phys_to_pfn(L4_24XX_PHYS), - .length = L4_24XX_SIZE, + .virtual = DSP_MEM_24XX_VIRT, + .pfn = __phys_to_pfn(DSP_MEM_24XX_PHYS), + .length = DSP_MEM_24XX_SIZE, + .type = MT_DEVICE + }, + { + .virtual = DSP_IPI_24XX_VIRT, + .pfn = __phys_to_pfn(DSP_IPI_24XX_PHYS), + .length = DSP_IPI_24XX_SIZE, + .type = MT_DEVICE + }, + { + .virtual = DSP_MMU_24XX_VIRT, + .pfn = __phys_to_pfn(DSP_MMU_24XX_PHYS), + .length = DSP_MMU_24XX_SIZE, .type = MT_DEVICE } }; diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index ce8bc3304e19..a347fb5946c7 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -62,6 +62,14 @@ config OMAP_MUX_WARNINGS to change the pin multiplexing setup. When there are no warnings printed, it's safe to deselect OMAP_MUX for your product. +config OMAP_MCBSP + bool "McBSP support" + depends on ARCH_OMAP + default y + help + Say Y here if you want support for the OMAP Multichannel + Buffered Serial Port. + choice prompt "System timer" default OMAP_MPU_TIMER diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index 4ce277d3485a..41a3c1cf3bd4 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile @@ -3,7 +3,8 @@ # # Common support -obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o mcbsp.o usb.o fb.o +obj-y := common.o sram.o sram-fn.o clock.o devices.o dma.o mux.o gpio.o \ + usb.o fb.o obj-m := obj-n := obj- := diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c index 57b7b93674a4..ffb94aa164ad 100644 --- a/arch/arm/plat-omap/common.c +++ b/arch/arm/plat-omap/common.c @@ -93,8 +93,12 @@ static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out) * in the kernel. */ for (i = 0; i < omap_board_config_size; i++) { if (omap_board_config[i].tag == tag) { - kinfo = &omap_board_config[i]; - break; + if (skip == 0) { + kinfo = &omap_board_config[i]; + break; + } else { + skip--; + } } } if (kinfo == NULL) diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index eeb33fed6f7c..2fac7d3f2af3 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -25,7 +25,71 @@ #include #include -#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) +#if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE) + +#include "../plat-omap/dsp/dsp_common.h" + +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); + + mutex_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_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) #define OMAP1_I2C_BASE 0xfffb3800 #define OMAP2_I2C_BASE1 0x48070000 @@ -376,7 +440,7 @@ static inline void omap_init_wdt(void) {} /*-------------------------------------------------------------------------*/ -#if defined(CONFIG_OMAP_RNG) || defined(CONFIG_OMAP_RNG_MODULE) +#if defined(CONFIG_HW_RANDOM_OMAP) || defined(CONFIG_HW_RANDOM_OMAP_MODULE) #ifdef CONFIG_ARCH_OMAP24XX #define OMAP_RNG_BASE 0x480A0000 @@ -436,6 +500,7 @@ 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_i2c(); omap_init_kp(); omap_init_mmc(); @@ -446,4 +511,3 @@ static int __init omap_init_devices(void) return 0; } arch_initcall(omap_init_devices); - diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 659619f235ca..36073dfaa4db 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -372,7 +372,7 @@ void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) /* When the functional clock disappears, too quick writes seem to * cause an abort. */ - __delay(15000); + __delay(150000); } #endif diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c index 91ebdafcca39..a302d9194f57 100644 --- a/arch/arm/plat-omap/fb.c +++ b/arch/arm/plat-omap/fb.c @@ -1,3 +1,26 @@ +/* + * File: arch/arm/plat-omap/fb.c + * + * Framebuffer device registration for TI OMAP platforms + * + * Copyright (C) 2006 Nokia Corporation + * Author: Imre Deak + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This 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., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + #include #include #include @@ -34,25 +57,42 @@ static struct platform_device omap_fb_device = { void omapfb_reserve_mem(void) { const struct omap_fbmem_config *fbmem_conf; + unsigned long total_size; + int i; + + if (!omap_fb_sram_valid) { + /* FBMEM SRAM configuration was already found to be invalid. + * Ignore the whole configuration block. */ + omapfb_config.mem_desc.region_cnt = 0; + return; + } + + i = 0; + total_size = 0; + while ((fbmem_conf = omap_get_nr_config(OMAP_TAG_FBMEM, + struct omap_fbmem_config, i)) != NULL) { + unsigned long start; + unsigned long size; - omapfb_config.fbmem.fb_sram_start = omap_fb_sram_start; - omapfb_config.fbmem.fb_sram_size = omap_fb_sram_size; - - fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config); - - if (fbmem_conf != NULL) { - /* indicate that the bootloader already initialized the - * fb device, so we'll skip that part in the fb driver - */ - omapfb_config.fbmem.fb_sdram_start = fbmem_conf->fb_sdram_start; - omapfb_config.fbmem.fb_sdram_size = fbmem_conf->fb_sdram_size; - if (fbmem_conf->fb_sdram_size) { - pr_info("Reserving %u bytes SDRAM for frame buffer\n", - fbmem_conf->fb_sdram_size); - reserve_bootmem(fbmem_conf->fb_sdram_start, - fbmem_conf->fb_sdram_size); + if (i == OMAPFB_PLANE_NUM) { + printk(KERN_ERR "ignoring extra plane info\n"); + break; } + start = fbmem_conf->start; + size = fbmem_conf->size; + omapfb_config.mem_desc.region[i].paddr = start; + omapfb_config.mem_desc.region[i].size = size; + if (omap_fb_sram_plane != i && start) { + reserve_bootmem(start, size); + total_size += size; + } + i++; } + omapfb_config.mem_desc.region_cnt = i; + if (total_size) + pr_info("Reserving %lu bytes SDRAM for frame buffer\n", + total_size); + } void omapfb_set_ctrl_platform_data(void *data) diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index 19014b2ff4c6..7e5f8877e051 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -46,12 +46,13 @@ #define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1))) +static unsigned long omap_sram_start; static unsigned long omap_sram_base; static unsigned long omap_sram_size; static unsigned long omap_sram_ceil; -unsigned long omap_fb_sram_start; -unsigned long omap_fb_sram_size; +int omap_fb_sram_plane = -1; +int omap_fb_sram_valid; /* Depending on the target RAMFS firewall setup, the public usable amount of * SRAM varies. The default accessable size for all device types is 2k. A GP @@ -77,30 +78,43 @@ static int is_sram_locked(void) return 1; /* assume locked with no PPA or security driver */ } -void get_fb_sram_conf(unsigned long start_avail, unsigned size_avail, - unsigned long *start, unsigned long *size) +static int get_fb_sram_conf(unsigned long start_avail, unsigned size_avail, + unsigned long *start, int *plane_idx) { const struct omap_fbmem_config *fbmem_conf; - - fbmem_conf = omap_get_config(OMAP_TAG_FBMEM, struct omap_fbmem_config); - if (fbmem_conf != NULL) { - *start = fbmem_conf->fb_sram_start; - *size = fbmem_conf->fb_sram_size; - } else { - *size = 0; - *start = 0; + unsigned long size = 0; + int i; + + i = 0; + *start = 0; + *plane_idx = -1; + while ((fbmem_conf = omap_get_nr_config(OMAP_TAG_FBMEM, + struct omap_fbmem_config, i)) != NULL) { + u32 paddr, end; + + paddr = fbmem_conf->start; + end = fbmem_conf->start + fbmem_conf->size; + if (paddr > omap_sram_start && + paddr < omap_sram_start + omap_sram_size) { + if (*plane_idx != -1 || paddr < start_avail || + paddr == end || + end > start_avail + size_avail) { + printk(KERN_ERR "invalid FB SRAM configuration"); + *start = 0; + return -1; + } + *plane_idx = i; + *start = fbmem_conf->start; + size = fbmem_conf->size; + } + i++; } - if (*size && ( - *start < start_avail || - *start + *size > start_avail + size_avail)) { - printk(KERN_ERR "invalid FB SRAM configuration\n"); - *start = start_avail; - *size = size_avail; - } + if (*plane_idx >= 0) + pr_info("Reserving %lu bytes SRAM frame buffer " + "for plane %d\n", size, *plane_idx); - if (*size) - pr_info("Reserving %lu bytes SRAM for frame buffer\n", *size); + return 0; } /* @@ -111,16 +125,16 @@ void get_fb_sram_conf(unsigned long start_avail, unsigned size_avail, */ void __init omap_detect_sram(void) { - unsigned long sram_start; + unsigned long fb_sram_start; if (cpu_is_omap24xx()) { if (is_sram_locked()) { omap_sram_base = OMAP2_SRAM_PUB_VA; - sram_start = OMAP2_SRAM_PUB_PA; + omap_sram_start = OMAP2_SRAM_PUB_PA; omap_sram_size = 0x800; /* 2K */ } else { omap_sram_base = OMAP2_SRAM_VA; - sram_start = OMAP2_SRAM_PA; + omap_sram_start = OMAP2_SRAM_PA; if (cpu_is_omap242x()) omap_sram_size = 0xa0000; /* 640K */ else if (cpu_is_omap243x()) @@ -128,7 +142,7 @@ void __init omap_detect_sram(void) } } else { omap_sram_base = OMAP1_SRAM_VA; - sram_start = OMAP1_SRAM_PA; + omap_sram_start = OMAP1_SRAM_PA; if (cpu_is_omap730()) omap_sram_size = 0x32000; /* 200K */ @@ -144,12 +158,13 @@ void __init omap_detect_sram(void) omap_sram_size = 0x4000; } } - get_fb_sram_conf(sram_start + SRAM_BOOTLOADER_SZ, - omap_sram_size - SRAM_BOOTLOADER_SZ, - &omap_fb_sram_start, &omap_fb_sram_size); - if (omap_fb_sram_size) - omap_sram_size -= sram_start + omap_sram_size - - omap_fb_sram_start; + if (get_fb_sram_conf(omap_sram_start + SRAM_BOOTLOADER_SZ, + omap_sram_size - SRAM_BOOTLOADER_SZ, + &fb_sram_start, &omap_fb_sram_plane) == 0) + omap_fb_sram_valid = 1; + if (omap_fb_sram_valid && omap_fb_sram_plane >= 0) + omap_sram_size -= omap_sram_start + omap_sram_size - + fb_sram_start; omap_sram_ceil = omap_sram_base + omap_sram_size; } diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c index 7e8096809be2..25489aafb113 100644 --- a/arch/arm/plat-omap/usb.c +++ b/arch/arm/plat-omap/usb.c @@ -37,9 +37,27 @@ #include #include +#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. - * Call omap_usb_init() once, from INIT_MACHINE(). * * Some board-*.c files will need to set up additional mux options, * like for suspend handling, vbus sensing, GPIOs, and the D+ pullup. @@ -96,19 +114,26 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) { u32 syscon1 = 0; + if (cpu_is_omap24xx()) + CONTROL_DEVCONF_REG &= ~USBT0WRMODEI(USB_BIDIR_TLL); + if (nwires == 0) { - if (!cpu_is_omap15xx()) { + if (cpu_class_is_omap1() && !cpu_is_omap15xx()) { /* pulldown D+/D- */ USB_TRANSCEIVER_CTRL_REG &= ~(3 << 1); } return 0; } - if (is_device) - omap_cfg_reg(W4_USB_PUEN); + if (is_device) { + if (cpu_is_omap24xx()) + omap_cfg_reg(J20_24XX_USB0_PUEN); + else + omap_cfg_reg(W4_USB_PUEN); + } - /* internal transceiver */ - if (nwires == 2) { + /* internal transceiver (unavailable on 17xx, 24xx) */ + if (!cpu_class_is_omap2() && nwires == 2) { // omap_cfg_reg(P9_USB_DP); // omap_cfg_reg(R8_USB_DM); @@ -136,29 +161,50 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device) return 0; } - omap_cfg_reg(V6_USB0_TXD); - omap_cfg_reg(W9_USB0_TXEN); - omap_cfg_reg(W5_USB0_SE0); + 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 */ + /* 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 detction. + */ - if (nwires != 3) - omap_cfg_reg(Y5_USB0_RCV); - if (nwires != 6) + if (cpu_class_is_omap1() && nwires != 6) USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R; switch (nwires) { case 3: syscon1 = 2; + if (cpu_is_omap24xx()) + CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_BIDIR); break; case 4: syscon1 = 1; + if (cpu_is_omap24xx()) + CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_BIDIR); break; case 6: syscon1 = 3; - omap_cfg_reg(AA9_USB0_VP); - omap_cfg_reg(R9_USB0_VM); - USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R; + if (cpu_is_omap24xx()) { + omap_cfg_reg(J19_24XX_USB0_VP); + omap_cfg_reg(K20_24XX_USB0_VM); + CONTROL_DEVCONF_REG |= USBT0WRMODEI(USB_UNIDIR); + } else { + omap_cfg_reg(AA9_USB0_VP); + omap_cfg_reg(R9_USB0_VM); + USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R; + } break; default: printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", @@ -171,14 +217,22 @@ static u32 __init omap_usb1_init(unsigned nwires) { u32 syscon1 = 0; - if (nwires != 6 && !cpu_is_omap15xx()) + if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6) USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB1_UNI_R; + if (cpu_is_omap24xx()) + CONTROL_DEVCONF_REG &= ~USBT1WRMODEI(USB_BIDIR_TLL); + if (nwires == 0) return 0; /* external transceiver */ - omap_cfg_reg(USB1_TXD); - omap_cfg_reg(USB1_TXEN); + 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); @@ -190,20 +244,38 @@ static u32 __init omap_usb1_init(unsigned nwires) } 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 unrecognized\n"); + pr_debug("usb%d cpu unrecognized\n", 1); + return 0; } - if (nwires != 3) - omap_cfg_reg(USB1_RCV); 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; + CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR_TLL); + break; case 3: syscon1 = 2; + if (cpu_is_omap24xx()) + CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR); break; case 4: syscon1 = 1; + if (cpu_is_omap24xx()) + CONTROL_DEVCONF_REG |= USBT1WRMODEI(USB_BIDIR); break; case 6: + if (cpu_is_omap24xx()) + goto bad; syscon1 = 3; omap_cfg_reg(USB1_VP); omap_cfg_reg(USB1_VM); @@ -211,6 +283,7 @@ static u32 __init omap_usb1_init(unsigned nwires) USB_TRANSCEIVER_CTRL_REG |= CONF_USB1_UNI_R; break; default: +bad: printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", 1, nwires); } @@ -221,10 +294,17 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) { u32 syscon1 = 0; - /* NOTE erratum: must leave USB2_UNI_R set if usb0 in use */ + if (cpu_is_omap24xx()) { + CONTROL_DEVCONF_REG &= ~(USBT2WRMODEI(USB_BIDIR_TLL) + | USBT2TLL5PI); + alt_pingroup = 0; + } + + /* NOTE omap1 erratum: must leave USB2_UNI_R set if usb0 in use */ if (alt_pingroup || nwires == 0) return 0; - if (nwires != 6 && !cpu_is_omap15xx()) + + if (cpu_class_is_omap1() && !cpu_is_omap15xx() && nwires != 6) USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R; /* external transceiver */ @@ -242,19 +322,54 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) 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 unrecognized\n"); + pr_debug("usb%d cpu unrecognized\n", 1); + return 0; } - // omap_cfg_reg(USB2_SUSP); + // 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; + CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR_TLL); + break; case 3: syscon1 = 2; + if (cpu_is_omap24xx()) + CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_BIDIR); break; case 4: syscon1 = 1; + if (cpu_is_omap24xx()) + CONTROL_DEVCONF_REG |= USBT2WRMODEI(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; + CONTROL_DEVCONF_REG |= USBT2WRMODEI(USB_UNIDIR_TLL) + | USBT2TLL5PI; break; case 6: + if (cpu_is_omap24xx()) + goto bad; syscon1 = 3; if (cpu_is_omap15xx()) { omap_cfg_reg(USB2_VP); @@ -266,6 +381,7 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup) } break; default: +bad: printk(KERN_ERR "illegal usb%d %d-wire transceiver\n", 2, nwires); } @@ -294,13 +410,13 @@ static struct resource udc_resources[] = { .end = UDC_BASE + 0xff, .flags = IORESOURCE_MEM, }, { /* general IRQ */ - .start = IH2_BASE + 20, + .start = INT_USB_IRQ_GEN, .flags = IORESOURCE_IRQ, }, { /* PIO IRQ */ - .start = IH2_BASE + 30, + .start = INT_USB_IRQ_NISO, .flags = IORESOURCE_IRQ, }, { /* SOF IRQ */ - .start = IH2_BASE + 29, + .start = INT_USB_IRQ_ISO, .flags = IORESOURCE_IRQ, }, }; @@ -329,11 +445,11 @@ static u64 ohci_dmamask = ~(u32)0; static struct resource ohci_resources[] = { { .start = OMAP_OHCI_BASE, - .end = OMAP_OHCI_BASE + 4096 - 1, + .end = OMAP_OHCI_BASE + 0xff, .flags = IORESOURCE_MEM, }, { - .start = INT_USB_HHC_1, + .start = INT_USB_IRQ_HGEN, .flags = IORESOURCE_IRQ, }, }; @@ -361,7 +477,7 @@ static struct resource otg_resources[] = { .end = OTG_BASE + 0xff, .flags = IORESOURCE_MEM, }, { - .start = IH2_BASE + 8, + .start = INT_USB_IRQ_OTG, .flags = IORESOURCE_IRQ, }, }; @@ -385,7 +501,7 @@ static struct platform_device otg_device = { // FIXME correct answer depends on hmc_mode, -// as does any nonzero value for config->otg port number +// as does (on omap1) any nonzero value for config->otg port number #ifdef CONFIG_USB_GADGET_OMAP #define is_usb0_device(config) 1 #else @@ -426,12 +542,13 @@ omap_otg_init(struct omap_usb_config *config) if (config->otg) syscon |= OTG_EN; #endif - pr_debug("USB_TRANSCEIVER_CTRL_REG = %03x\n", USB_TRANSCEIVER_CTRL_REG); + if (cpu_class_is_omap1()) + pr_debug("USB_TRANSCEIVER_CTRL_REG = %03x\n", USB_TRANSCEIVER_CTRL_REG); pr_debug("OTG_SYSCON_2_REG = %08x\n", syscon); OTG_SYSCON_2_REG = syscon; printk("USB: hmc %d", config->hmc_mode); - if (alt_pingroup) + if (!alt_pingroup) printk(", usb2 alt %d wires", config->pins[2]); else if (config->pins[0]) printk(", usb0 %d wires%s", config->pins[0], @@ -444,10 +561,12 @@ omap_otg_init(struct omap_usb_config *config) printk(", Mini-AB on usb%d", config->otg - 1); printk("\n"); - /* leave USB clocks/controllers off until needed */ - ULPD_SOFT_REQ_REG &= ~SOFT_USB_CLK_REQ; - ULPD_CLOCK_CTRL_REG &= ~USB_MCLK_EN; - ULPD_CLOCK_CTRL_REG |= DIS_USB_PVCI_CLK; + if (cpu_class_is_omap1()) { + /* leave USB clocks/controllers off until needed */ + ULPD_SOFT_REQ_REG &= ~SOFT_USB_CLK_REQ; + ULPD_CLOCK_CTRL_REG &= ~USB_MCLK_EN; + ULPD_CLOCK_CTRL_REG |= DIS_USB_PVCI_CLK; + } syscon = OTG_SYSCON_1_REG; syscon |= HST_IDLE_EN|DEV_IDLE_EN|OTG_IDLE_EN; @@ -585,7 +704,7 @@ omap_usb_init(void) } platform_data = *config; - if (cpu_is_omap730() || cpu_is_omap16xx()) + if (cpu_is_omap730() || cpu_is_omap16xx() || cpu_is_omap24xx()) omap_otg_init(&platform_data); else if (cpu_is_omap15xx()) omap_1510_usb_init(&platform_data); -- cgit v1.2.3 From 340a614ac6766df18cba87ff7e66182193c2bd6d Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU Date: Thu, 7 Dec 2006 15:43:59 -0800 Subject: ARM: OMAP: Add mailbox support for IVA This patch adds a generic mailbox interface for for DSP and IVA (Image Video Accelerator). This patch itself doesn't contain any IVA driver. Signed-off-by: Hiroshi DOYU Signed-off-by: Juha Yrjola Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap1/mailbox.c | 206 +++++++++++++++ arch/arm/mach-omap2/mailbox.c | 318 ++++++++++++++++++++++ arch/arm/plat-omap/mailbox.c | 509 ++++++++++++++++++++++++++++++++++++ arch/arm/plat-omap/mailbox.h | 100 +++++++ include/asm-arm/arch-omap/mailbox.h | 73 ++++++ 5 files changed, 1206 insertions(+) create mode 100644 arch/arm/mach-omap1/mailbox.c create mode 100644 arch/arm/mach-omap2/mailbox.c create mode 100644 arch/arm/plat-omap/mailbox.c create mode 100644 arch/arm/plat-omap/mailbox.h create mode 100644 include/asm-arm/arch-omap/mailbox.h (limited to 'arch/arm/mach-omap2') diff --git a/arch/arm/mach-omap1/mailbox.c b/arch/arm/mach-omap1/mailbox.c new file mode 100644 index 000000000000..d3abf5609902 --- /dev/null +++ b/arch/arm/mach-omap1/mailbox.c @@ -0,0 +1,206 @@ +/* + * Mailbox reservation modules for DSP + * + * Copyright (C) 2006 Nokia Corporation + * Written by: Hiroshi DOYU + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MAILBOX_ARM2DSP1 0x00 +#define MAILBOX_ARM2DSP1b 0x04 +#define MAILBOX_DSP2ARM1 0x08 +#define MAILBOX_DSP2ARM1b 0x0c +#define MAILBOX_DSP2ARM2 0x10 +#define MAILBOX_DSP2ARM2b 0x14 +#define MAILBOX_ARM2DSP1_Flag 0x18 +#define MAILBOX_DSP2ARM1_Flag 0x1c +#define MAILBOX_DSP2ARM2_Flag 0x20 + +unsigned long mbox_base; + +struct omap_mbox1_fifo { + unsigned long cmd; + unsigned long data; + unsigned long flag; +}; + +struct omap_mbox1_priv { + struct omap_mbox1_fifo tx_fifo; + struct omap_mbox1_fifo rx_fifo; +}; + +static inline int mbox_read_reg(unsigned int reg) +{ + return __raw_readw(mbox_base + reg); +} + +static inline void mbox_write_reg(unsigned int val, unsigned int reg) +{ + __raw_writew(val, mbox_base + reg); +} + +/* msg */ +static inline mbox_msg_t omap1_mbox_fifo_read(struct omap_mbox *mbox) +{ + struct omap_mbox1_fifo *fifo = + &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo; + mbox_msg_t msg; + + msg = mbox_read_reg(fifo->data); + msg |= ((mbox_msg_t) mbox_read_reg(fifo->cmd)) << 16; + + return msg; +} + +static inline void +omap1_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) +{ + struct omap_mbox1_fifo *fifo = + &((struct omap_mbox1_priv *)mbox->priv)->tx_fifo; + + mbox_write_reg(msg & 0xffff, fifo->data); + mbox_write_reg(msg >> 16, fifo->cmd); +} + +static inline int omap1_mbox_fifo_empty(struct omap_mbox *mbox) +{ + return 0; +} + +static inline int omap1_mbox_fifo_full(struct omap_mbox *mbox) +{ + struct omap_mbox1_fifo *fifo = + &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo; + + return (mbox_read_reg(fifo->flag)); +} + +/* irq */ +static inline void +omap1_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq) +{ + if (irq == IRQ_RX) + enable_irq(mbox->irq); +} + +static inline void +omap1_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq) +{ + if (irq == IRQ_RX) + disable_irq(mbox->irq); +} + +static inline int +omap1_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_type_t irq) +{ + if (irq == IRQ_TX) + return 0; + return 1; +} + +static struct omap_mbox_ops omap1_mbox_ops = { + .type = OMAP_MBOX_TYPE1, + .fifo_read = omap1_mbox_fifo_read, + .fifo_write = omap1_mbox_fifo_write, + .fifo_empty = omap1_mbox_fifo_empty, + .fifo_full = omap1_mbox_fifo_full, + .enable_irq = omap1_mbox_enable_irq, + .disable_irq = omap1_mbox_disable_irq, + .is_irq = omap1_mbox_is_irq, +}; + +/* FIXME: the following struct should be created automatically by the user id */ + +/* DSP */ +static struct omap_mbox1_priv omap1_mbox_dsp_priv = { + .tx_fifo = { + .cmd = MAILBOX_ARM2DSP1b, + .data = MAILBOX_ARM2DSP1, + .flag = MAILBOX_ARM2DSP1_Flag, + }, + .rx_fifo = { + .cmd = MAILBOX_DSP2ARM1b, + .data = MAILBOX_DSP2ARM1, + .flag = MAILBOX_DSP2ARM1_Flag, + }, +}; + +struct omap_mbox mbox_dsp_info = { + .name = "dsp", + .ops = &omap1_mbox_ops, + .priv = &omap1_mbox_dsp_priv, +}; +EXPORT_SYMBOL(mbox_dsp_info); + +static int __init omap1_mbox_probe(struct platform_device *pdev) +{ + struct resource *res; + int ret = 0; + + if (pdev->num_resources != 2) { + dev_err(&pdev->dev, "invalid number of resources: %d\n", + pdev->num_resources); + return -ENODEV; + } + + /* MBOX base */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (unlikely(!res)) { + dev_err(&pdev->dev, "invalid mem resource\n"); + return -ENODEV; + } + mbox_base = res->start; + + /* DSP IRQ */ + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (unlikely(!res)) { + dev_err(&pdev->dev, "invalid irq resource\n"); + return -ENODEV; + } + mbox_dsp_info.irq = res->start; + + ret = omap_mbox_register(&mbox_dsp_info); + + return ret; +} + +static int omap1_mbox_remove(struct platform_device *pdev) +{ + omap_mbox_unregister(&mbox_dsp_info); + + return 0; +} + +static struct platform_driver omap1_mbox_driver = { + .probe = omap1_mbox_probe, + .remove = omap1_mbox_remove, + .driver = { + .name = "mailbox", + }, +}; + +static int __init omap1_mbox_init(void) +{ + return platform_driver_register(&omap1_mbox_driver); +} + +static void __exit omap1_mbox_exit(void) +{ + platform_driver_unregister(&omap1_mbox_driver); +} + +module_init(omap1_mbox_init); +module_exit(omap1_mbox_exit); + +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c new file mode 100644 index 000000000000..b03cd06e055b --- /dev/null +++ b/arch/arm/mach-omap2/mailbox.c @@ -0,0 +1,318 @@ +/* + * Mailbox reservation modules for OMAP2 + * + * Copyright (C) 2006 Nokia Corporation + * Written by: Hiroshi DOYU + * and Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MAILBOX_REVISION 0x00 +#define MAILBOX_SYSCONFIG 0x10 +#define MAILBOX_SYSSTATUS 0x14 +#define MAILBOX_MESSAGE_0 0x40 +#define MAILBOX_MESSAGE_1 0x44 +#define MAILBOX_MESSAGE_2 0x48 +#define MAILBOX_MESSAGE_3 0x4c +#define MAILBOX_MESSAGE_4 0x50 +#define MAILBOX_MESSAGE_5 0x54 +#define MAILBOX_FIFOSTATUS_0 0x80 +#define MAILBOX_FIFOSTATUS_1 0x84 +#define MAILBOX_FIFOSTATUS_2 0x88 +#define MAILBOX_FIFOSTATUS_3 0x8c +#define MAILBOX_FIFOSTATUS_4 0x90 +#define MAILBOX_FIFOSTATUS_5 0x94 +#define MAILBOX_MSGSTATUS_0 0xc0 +#define MAILBOX_MSGSTATUS_1 0xc4 +#define MAILBOX_MSGSTATUS_2 0xc8 +#define MAILBOX_MSGSTATUS_3 0xcc +#define MAILBOX_MSGSTATUS_4 0xd0 +#define MAILBOX_MSGSTATUS_5 0xd4 +#define MAILBOX_IRQSTATUS_0 0x100 +#define MAILBOX_IRQENABLE_0 0x104 +#define MAILBOX_IRQSTATUS_1 0x108 +#define MAILBOX_IRQENABLE_1 0x10c +#define MAILBOX_IRQSTATUS_2 0x110 +#define MAILBOX_IRQENABLE_2 0x114 +#define MAILBOX_IRQSTATUS_3 0x118 +#define MAILBOX_IRQENABLE_3 0x11c + +static unsigned long mbox_base; + +#define MAILBOX_IRQ_NOTFULL(n) (1 << (2 * (n) + 1)) +#define MAILBOX_IRQ_NEWMSG(n) (1 << (2 * (n))) + +struct omap_mbox2_fifo { + unsigned long msg; + unsigned long fifo_stat; + unsigned long msg_stat; +}; + +struct omap_mbox2_priv { + struct omap_mbox2_fifo tx_fifo; + struct omap_mbox2_fifo rx_fifo; + unsigned long irqenable; + unsigned long irqstatus; + u32 newmsg_bit; + u32 notfull_bit; +}; + +static struct clk *mbox_ick_handle; + +static inline unsigned int mbox_read_reg(unsigned int reg) +{ + return __raw_readl(mbox_base + reg); +} + +static inline void mbox_write_reg(unsigned int val, unsigned int reg) +{ + __raw_writel(val, mbox_base + reg); +} + +/* Mailbox H/W preparations */ +static inline int omap2_mbox_startup(struct omap_mbox *mbox) +{ + unsigned int l; + + mbox_ick_handle = clk_get(NULL, "mailboxes_ick"); + if (IS_ERR(mbox_ick_handle)) { + printk("Could not get mailboxes_ick\n"); + return -ENODEV; + } + clk_enable(mbox_ick_handle); + + /* set smart-idle & autoidle */ + l = mbox_read_reg(MAILBOX_SYSCONFIG); + l |= 0x00000011; + mbox_write_reg(l, MAILBOX_SYSCONFIG); + + return 0; +} + +static inline void omap2_mbox_shutdown(struct omap_mbox *mbox) +{ + clk_disable(mbox_ick_handle); + clk_put(mbox_ick_handle); +} + +/* Mailbox FIFO handle functions */ +static inline mbox_msg_t omap2_mbox_fifo_read(struct omap_mbox *mbox) +{ + struct omap_mbox2_fifo *fifo = + &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo; + return (mbox_msg_t) mbox_read_reg(fifo->msg); +} + +static inline void omap2_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) +{ + struct omap_mbox2_fifo *fifo = + &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo; + mbox_write_reg(msg, fifo->msg); +} + +static inline int omap2_mbox_fifo_empty(struct omap_mbox *mbox) +{ + struct omap_mbox2_fifo *fifo = + &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo; + return (mbox_read_reg(fifo->msg_stat) == 0); +} + +static inline int omap2_mbox_fifo_full(struct omap_mbox *mbox) +{ + struct omap_mbox2_fifo *fifo = + &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo; + return (mbox_read_reg(fifo->fifo_stat)); +} + +/* Mailbox IRQ handle functions */ +static inline void omap2_mbox_enable_irq(struct omap_mbox *mbox, + omap_mbox_type_t irq) +{ + struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv; + u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; + + l = mbox_read_reg(p->irqenable); + l |= bit; + mbox_write_reg(l, p->irqenable); +} + +static inline void omap2_mbox_disable_irq(struct omap_mbox *mbox, + omap_mbox_type_t irq) +{ + struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv; + u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; + + l = mbox_read_reg(p->irqenable); + l &= ~bit; + mbox_write_reg(l, p->irqenable); +} + +static inline void omap2_mbox_ack_irq(struct omap_mbox *mbox, + omap_mbox_type_t irq) +{ + struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv; + u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; + + mbox_write_reg(bit, p->irqstatus); +} + +static inline int omap2_mbox_is_irq(struct omap_mbox *mbox, + omap_mbox_type_t irq) +{ + struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv; + u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; + u32 enable = mbox_read_reg(p->irqenable); + u32 status = mbox_read_reg(p->irqstatus); + + return (enable & status & bit); +} + +static struct omap_mbox_ops omap2_mbox_ops = { + .type = OMAP_MBOX_TYPE2, + .startup = omap2_mbox_startup, + .shutdown = omap2_mbox_shutdown, + .fifo_read = omap2_mbox_fifo_read, + .fifo_write = omap2_mbox_fifo_write, + .fifo_empty = omap2_mbox_fifo_empty, + .fifo_full = omap2_mbox_fifo_full, + .enable_irq = omap2_mbox_enable_irq, + .disable_irq = omap2_mbox_disable_irq, + .ack_irq = omap2_mbox_ack_irq, + .is_irq = omap2_mbox_is_irq, +}; + +/* + * MAILBOX 0: ARM -> DSP, + * MAILBOX 1: ARM <- DSP. + * MAILBOX 2: ARM -> IVA, + * MAILBOX 3: ARM <- IVA. + */ + +/* FIXME: the following structs should be filled automatically by the user id */ + +/* DSP */ +static struct omap_mbox2_priv omap2_mbox_dsp_priv = { + .tx_fifo = { + .msg = MAILBOX_MESSAGE_0, + .fifo_stat = MAILBOX_FIFOSTATUS_0, + }, + .rx_fifo = { + .msg = MAILBOX_MESSAGE_1, + .msg_stat = MAILBOX_MSGSTATUS_1, + }, + .irqenable = MAILBOX_IRQENABLE_0, + .irqstatus = MAILBOX_IRQSTATUS_0, + .notfull_bit = MAILBOX_IRQ_NOTFULL(0), + .newmsg_bit = MAILBOX_IRQ_NEWMSG(1), +}; + +struct omap_mbox mbox_dsp_info = { + .name = "dsp", + .ops = &omap2_mbox_ops, + .priv = &omap2_mbox_dsp_priv, +}; +EXPORT_SYMBOL(mbox_dsp_info); + +/* IVA */ +static struct omap_mbox2_priv omap2_mbox_iva_priv = { + .tx_fifo = { + .msg = MAILBOX_MESSAGE_2, + .fifo_stat = MAILBOX_FIFOSTATUS_2, + }, + .rx_fifo = { + .msg = MAILBOX_MESSAGE_3, + .msg_stat = MAILBOX_MSGSTATUS_3, + }, + .irqenable = MAILBOX_IRQENABLE_3, + .irqstatus = MAILBOX_IRQSTATUS_3, + .notfull_bit = MAILBOX_IRQ_NOTFULL(2), + .newmsg_bit = MAILBOX_IRQ_NEWMSG(3), +}; + +static struct omap_mbox mbox_iva_info = { + .name = "iva", + .ops = &omap2_mbox_ops, + .priv = &omap2_mbox_iva_priv, +}; + +static int __init omap2_mbox_probe(struct platform_device *pdev) +{ + struct resource *res; + int ret = 0; + + if (pdev->num_resources != 3) { + dev_err(&pdev->dev, "invalid number of resources: %d\n", + pdev->num_resources); + return -ENODEV; + } + + /* MBOX base */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (unlikely(!res)) { + dev_err(&pdev->dev, "invalid mem resource\n"); + return -ENODEV; + } + mbox_base = res->start; + + /* DSP IRQ */ + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (unlikely(!res)) { + dev_err(&pdev->dev, "invalid irq resource\n"); + return -ENODEV; + } + mbox_dsp_info.irq = res->start; + + ret = omap_mbox_register(&mbox_dsp_info); + + /* IVA IRQ */ + res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); + if (unlikely(!res)) { + dev_err(&pdev->dev, "invalid irq resource\n"); + return -ENODEV; + } + mbox_iva_info.irq = res->start; + + ret = omap_mbox_register(&mbox_iva_info); + + return ret; +} + +static int omap2_mbox_remove(struct platform_device *pdev) +{ + omap_mbox_unregister(&mbox_dsp_info); + return 0; +} + +static struct platform_driver omap2_mbox_driver = { + .probe = omap2_mbox_probe, + .remove = omap2_mbox_remove, + .driver = { + .name = "mailbox", + }, +}; + +static int __init omap2_mbox_init(void) +{ + return platform_driver_register(&omap2_mbox_driver); +} + +static void __exit omap2_mbox_exit(void) +{ + platform_driver_unregister(&omap2_mbox_driver); +} + +module_init(omap2_mbox_init); +module_exit(omap2_mbox_exit); + +MODULE_LICENSE("GPL"); diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c new file mode 100644 index 000000000000..de7e6ef48bd0 --- /dev/null +++ b/arch/arm/plat-omap/mailbox.c @@ -0,0 +1,509 @@ +/* + * OMAP mailbox driver + * + * Copyright (C) 2006 Nokia Corporation. All rights reserved. + * + * Contact: Toshihiro Kobayashi + * Restructured by Hiroshi DOYU + * + * 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 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mailbox.h" + +static struct omap_mbox *mboxes; +static DEFINE_RWLOCK(mboxes_lock); + +/* Mailbox Sequence Bit function */ +void omap_mbox_init_seq(struct omap_mbox *mbox) +{ + mbox_seq_init(mbox); +} +EXPORT_SYMBOL(omap_mbox_init_seq); + +/* + * message sender + */ +static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void *arg) +{ + int ret = 0, i = 1000; + + while (mbox_fifo_full(mbox)) { + if (mbox->ops->type == OMAP_MBOX_TYPE2) + return -1; + if (--i == 0) + return -1; + udelay(1); + } + + if (arg && mbox->txq->callback) { + ret = mbox->txq->callback(arg); + if (ret) + goto out; + } + + mbox_seq_toggle(mbox, &msg); + mbox_fifo_write(mbox, msg); + out: + return ret; +} + +int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void* arg) +{ + struct request *rq; + struct request_queue *q = mbox->txq->queue; + int ret = 0; + + rq = blk_get_request(q, WRITE, GFP_ATOMIC); + if (unlikely(!rq)) { + ret = -ENOMEM; + goto fail; + } + + rq->data = (void *)msg; + blk_insert_request(q, rq, 0, arg); + + schedule_work(&mbox->txq->work); + fail: + return ret; +} +EXPORT_SYMBOL(omap_mbox_msg_send); + +static void mbox_tx_work(struct work_struct *work) +{ + int ret; + struct request *rq; + 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->txq->queue; + + while (1) { + spin_lock(q->queue_lock); + rq = elv_next_request(q); + spin_unlock(q->queue_lock); + + if (!rq) + break; + + ret = __mbox_msg_send(mbox, (mbox_msg_t) rq->data, rq->special); + if (ret) { + enable_mbox_irq(mbox, IRQ_TX); + return; + } + + spin_lock(q->queue_lock); + blkdev_dequeue_request(rq); + end_that_request_last(rq, 0); + spin_unlock(q->queue_lock); + } +} + +/* + * Message receiver(workqueue) + */ +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; + + if (mbox->rxq->callback == NULL) { + sysfs_notify(&mbox->dev.kobj, NULL, "mbox"); + return; + } + + while (1) { + spin_lock_irqsave(q->queue_lock, flags); + rq = elv_next_request(q); + spin_unlock_irqrestore(q->queue_lock, flags); + if (!rq) + break; + + msg = (mbox_msg_t) rq->data; + + spin_lock_irqsave(q->queue_lock, flags); + blkdev_dequeue_request(rq); + end_that_request_last(rq, 0); + spin_unlock_irqrestore(q->queue_lock, flags); + + mbox->rxq->callback((void *)msg); + } +} + +/* + * Mailbox interrupt handler + */ +static void mbox_txq_fn(request_queue_t * q) +{ +} + +static void mbox_rxq_fn(request_queue_t * q) +{ +} + +static void __mbox_tx_interrupt(struct omap_mbox *mbox) +{ + disable_mbox_irq(mbox, IRQ_TX); + ack_mbox_irq(mbox, IRQ_TX); + schedule_work(&mbox->txq->work); +} + +static void __mbox_rx_interrupt(struct omap_mbox *mbox) +{ + struct request *rq; + mbox_msg_t msg; + request_queue_t *q = mbox->rxq->queue; + + disable_mbox_irq(mbox, IRQ_RX); + + while (!mbox_fifo_empty(mbox)) { + rq = blk_get_request(q, WRITE, GFP_ATOMIC); + if (unlikely(!rq)) + goto nomem; + + msg = mbox_fifo_read(mbox); + rq->data = (void *)msg; + + if (unlikely(mbox_seq_test(mbox, msg))) { + pr_info("mbox: Illegal seq bit!(%08x)\n", msg); + if (mbox->err_notify) + mbox->err_notify(); + } + + blk_insert_request(q, rq, 0, NULL); + if (mbox->ops->type == OMAP_MBOX_TYPE1) + break; + } + + /* no more messages in the fifo. clear IRQ source. */ + ack_mbox_irq(mbox, IRQ_RX); + enable_mbox_irq(mbox, IRQ_RX); + nomem: + schedule_work(&mbox->rxq->work); +} + +static irqreturn_t mbox_interrupt(int irq, void *p) +{ + struct omap_mbox *mbox = (struct omap_mbox *)p; + + if (is_mbox_irq(mbox, IRQ_TX)) + __mbox_tx_interrupt(mbox); + + if (is_mbox_irq(mbox, IRQ_RX)) + __mbox_rx_interrupt(mbox); + + return IRQ_HANDLED; +} + +/* + * sysfs files + */ +static ssize_t +omap_mbox_write(struct device *dev, struct device_attribute *attr, + const char * buf, size_t count) +{ + int ret; + mbox_msg_t *p = (mbox_msg_t *)buf; + struct omap_mbox *mbox = dev_get_drvdata(dev); + + for (; count >= sizeof(mbox_msg_t); count -= sizeof(mbox_msg_t)) { + ret = omap_mbox_msg_send(mbox, be32_to_cpu(*p), NULL); + if (ret) + return -EAGAIN; + p++; + } + + return (size_t)((char *)p - buf); +} + +static ssize_t +omap_mbox_read(struct device *dev, struct device_attribute *attr, char *buf) +{ + unsigned long flags; + struct request *rq; + mbox_msg_t *p = (mbox_msg_t *) buf; + struct omap_mbox *mbox = dev_get_drvdata(dev); + struct request_queue *q = mbox->rxq->queue; + + while (1) { + spin_lock_irqsave(q->queue_lock, flags); + rq = elv_next_request(q); + spin_unlock_irqrestore(q->queue_lock, flags); + + if (!rq) + break; + + *p = (mbox_msg_t) rq->data; + + spin_lock_irqsave(q->queue_lock, flags); + blkdev_dequeue_request(rq); + end_that_request_last(rq, 0); + spin_unlock_irqrestore(q->queue_lock, flags); + + if (unlikely(mbox_seq_test(mbox, *p))) { + pr_info("mbox: Illegal seq bit!(%08x) ignored\n", *p); + continue; + } + p++; + } + + pr_debug("%02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3]); + + return (size_t) ((char *)p - buf); +} + +static DEVICE_ATTR(mbox, S_IRUGO | S_IWUSR, omap_mbox_read, omap_mbox_write); + +static ssize_t mbox_show(struct class *class, char *buf) +{ + return sprintf(buf, "mbox"); +} + +static CLASS_ATTR(mbox, S_IRUGO, mbox_show, NULL); + +static struct class omap_mbox_class = { + .name = "omap_mbox", +}; + +static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox, + request_fn_proc * proc, + void (*work) (struct work_struct *)) +{ + request_queue_t *q; + struct omap_mbox_queue *mq; + + mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL); + if (!mq) + return NULL; + + spin_lock_init(&mq->lock); + + q = blk_init_queue(proc, &mq->lock); + if (!q) + goto error; + q->queuedata = mbox; + mq->queue = q; + + INIT_WORK(&mq->work, work); + + return mq; +error: + kfree(mq); + return NULL; +} + +static void mbox_queue_free(struct omap_mbox_queue *q) +{ + blk_cleanup_queue(q->queue); + kfree(q); +} + +static int omap_mbox_init(struct omap_mbox *mbox) +{ + int ret; + struct omap_mbox_queue *mq; + + if (likely(mbox->ops->startup)) { + ret = mbox->ops->startup(mbox); + if (unlikely(ret)) + return ret; + } + + mbox->dev.class = &omap_mbox_class; + strlcpy(mbox->dev.bus_id, mbox->name, KOBJ_NAME_LEN); + dev_set_drvdata(&mbox->dev, mbox); + + ret = device_register(&mbox->dev); + if (unlikely(ret)) + goto fail_device_reg; + + ret = device_create_file(&mbox->dev, &dev_attr_mbox); + if (unlikely(ret)) { + printk(KERN_ERR + "device_create_file failed: %d\n", ret); + goto fail_create_mbox; + } + + ret = request_irq(mbox->irq, mbox_interrupt, IRQF_DISABLED, + mbox->name, mbox); + if (unlikely(ret)) { + printk(KERN_ERR + "failed to register mailbox interrupt:%d\n", ret); + goto fail_request_irq; + } + enable_mbox_irq(mbox, IRQ_RX); + + mq = mbox_queue_alloc(mbox, mbox_txq_fn, mbox_tx_work); + if (!mq) { + ret = -ENOMEM; + goto fail_alloc_txq; + } + mbox->txq = mq; + + mq = mbox_queue_alloc(mbox, mbox_rxq_fn, mbox_rx_work); + if (!mq) { + ret = -ENOMEM; + goto fail_alloc_rxq; + } + mbox->rxq = mq; + + return 0; + + fail_alloc_rxq: + mbox_queue_free(mbox->txq); + fail_alloc_txq: + free_irq(mbox->irq, mbox); + fail_request_irq: + device_remove_file(&mbox->dev, &dev_attr_mbox); + fail_create_mbox: + device_unregister(&mbox->dev); + fail_device_reg: + if (unlikely(mbox->ops->shutdown)) + mbox->ops->shutdown(mbox); + + return ret; +} + +static void omap_mbox_fini(struct omap_mbox *mbox) +{ + mbox_queue_free(mbox->txq); + mbox_queue_free(mbox->rxq); + + free_irq(mbox->irq, mbox); + device_remove_file(&mbox->dev, &dev_attr_mbox); + class_unregister(&omap_mbox_class); + + if (unlikely(mbox->ops->shutdown)) + mbox->ops->shutdown(mbox); +} + +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; + } + + return p; +} + +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); + } + + read_unlock(&mboxes_lock); + + ret = omap_mbox_init(mbox); + if (ret) + return ERR_PTR(-ENODEV); + + return mbox; +} +EXPORT_SYMBOL(omap_mbox_get); + +void omap_mbox_put(struct omap_mbox *mbox) +{ + omap_mbox_fini(mbox); +} +EXPORT_SYMBOL(omap_mbox_put); + +int omap_mbox_register(struct omap_mbox *mbox) +{ + int ret = 0; + struct omap_mbox **tmp; + + if (!mbox) + return -EINVAL; + if (mbox->next) + return -EBUSY; + + write_lock(&mboxes_lock); + tmp = find_mboxes(mbox->name); + if (*tmp) + ret = -EBUSY; + else + *tmp = mbox; + write_unlock(&mboxes_lock); + + return ret; +} +EXPORT_SYMBOL(omap_mbox_register); + +int omap_mbox_unregister(struct omap_mbox *mbox) +{ + 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); + + return -EINVAL; +} +EXPORT_SYMBOL(omap_mbox_unregister); + +static int __init omap_mbox_class_init(void) +{ + int ret = class_register(&omap_mbox_class); + if (!ret) + ret = class_create_file(&omap_mbox_class, &class_attr_mbox); + + return ret; +} + +static void __exit omap_mbox_class_exit(void) +{ + class_remove_file(&omap_mbox_class, &class_attr_mbox); + class_unregister(&omap_mbox_class); +} + +subsys_initcall(omap_mbox_class_init); +module_exit(omap_mbox_class_exit); + +MODULE_LICENSE("GPL"); diff --git a/arch/arm/plat-omap/mailbox.h b/arch/arm/plat-omap/mailbox.h new file mode 100644 index 000000000000..67c6740b8ad5 --- /dev/null +++ b/arch/arm/plat-omap/mailbox.h @@ -0,0 +1,100 @@ +/* + * Mailbox internal functions + * + * Copyright (C) 2006 Nokia Corporation + * Written by: Hiroshi DOYU + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#ifndef __ARCH_ARM_PLAT_MAILBOX_H +#define __ARCH_ARM_PLAT_MAILBOX_H + +/* + * Mailbox sequence bit API + */ +#if defined(CONFIG_ARCH_OMAP1) +# define MBOX_USE_SEQ_BIT +#elif defined(CONFIG_ARCH_OMAP2) +# define MBOX_USE_SEQ_BIT +#endif + +#ifdef MBOX_USE_SEQ_BIT +/* seq_rcv should be initialized with any value other than + * 0 and 1 << 31, to allow either value for the first + * message. */ +static inline void mbox_seq_init(struct omap_mbox *mbox) +{ + /* any value other than 0 and 1 << 31 */ + mbox->seq_rcv = 0xffffffff; +} + +static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg) +{ + /* add seq_snd to msg */ + *msg = (*msg & 0x7fffffff) | mbox->seq_snd; + /* flip seq_snd */ + mbox->seq_snd ^= 1 << 31; +} + +static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg) +{ + mbox_msg_t seq = msg & (1 << 31); + if (seq == mbox->seq_rcv) + return -1; + mbox->seq_rcv = seq; + return 0; +} +#else +static inline void mbox_seq_init(struct omap_mbox *mbox) +{ +} +static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg) +{ +} +static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg) +{ + return 0; +} +#endif + +/* Mailbox FIFO handle functions */ +static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox) +{ + return mbox->ops->fifo_read(mbox); +} +static inline void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) +{ + mbox->ops->fifo_write(mbox, msg); +} +static inline int mbox_fifo_empty(struct omap_mbox *mbox) +{ + return mbox->ops->fifo_empty(mbox); +} +static inline int mbox_fifo_full(struct omap_mbox *mbox) +{ + return mbox->ops->fifo_full(mbox); +} + +/* Mailbox IRQ handle functions */ +static inline void enable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) +{ + mbox->ops->enable_irq(mbox, irq); +} +static inline void disable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) +{ + mbox->ops->disable_irq(mbox, irq); +} +static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) +{ + if (mbox->ops->ack_irq) + mbox->ops->ack_irq(mbox, irq); +} +static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) +{ + return mbox->ops->is_irq(mbox, irq); +} + +#endif /* __ARCH_ARM_PLAT_MAILBOX_H */ diff --git a/include/asm-arm/arch-omap/mailbox.h b/include/asm-arm/arch-omap/mailbox.h new file mode 100644 index 000000000000..4bf0909461f2 --- /dev/null +++ b/include/asm-arm/arch-omap/mailbox.h @@ -0,0 +1,73 @@ +/* mailbox.h */ + +#ifndef MAILBOX_H +#define MAILBOX_H + +#include +#include +#include + +typedef u32 mbox_msg_t; +typedef void (mbox_receiver_t)(mbox_msg_t msg); +struct omap_mbox; + +typedef int __bitwise omap_mbox_irq_t; +#define IRQ_TX ((__force omap_mbox_irq_t) 1) +#define IRQ_RX ((__force omap_mbox_irq_t) 2) + +typedef int __bitwise omap_mbox_type_t; +#define OMAP_MBOX_TYPE1 ((__force omap_mbox_type_t) 1) +#define OMAP_MBOX_TYPE2 ((__force omap_mbox_type_t) 2) + +struct omap_mbox_ops { + omap_mbox_type_t type; + int (*startup)(struct omap_mbox *mbox); + void (*shutdown)(struct omap_mbox *mbox); + /* fifo */ + mbox_msg_t (*fifo_read)(struct omap_mbox *mbox); + void (*fifo_write)(struct omap_mbox *mbox, mbox_msg_t msg); + int (*fifo_empty)(struct omap_mbox *mbox); + int (*fifo_full)(struct omap_mbox *mbox); + /* irq */ + void (*enable_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq); + void (*disable_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq); + void (*ack_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq); + int (*is_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq); +}; + +struct omap_mbox_queue { + spinlock_t lock; + request_queue_t *queue; + struct work_struct work; + int (*callback)(void *); + struct omap_mbox *mbox; +}; + +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, void *); +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 omap_mbox *); +int omap_mbox_unregister(struct omap_mbox *); + +#endif /* MAILBOX_H */ -- cgit v1.2.3 From d82973d1cdc149d06ac9685ae008105d382c4236 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 26 Jan 2007 12:01:17 -0800 Subject: ARM: OMAP: Mostly cosmetic to sync up with linux-omap tree Mostly cosmetic to sync up with linux-omap tree Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap1/Kconfig | 2 +- arch/arm/mach-omap2/devices.c | 6 +++--- arch/arm/plat-omap/devices.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'arch/arm/mach-omap2') diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig index 18ea7313a499..ab1b17d35bd3 100644 --- a/arch/arm/mach-omap1/Kconfig +++ b/arch/arm/mach-omap1/Kconfig @@ -46,7 +46,7 @@ config MACH_OMAP_H3 config MACH_OMAP_OSK bool "TI OSK Support" depends on ARCH_OMAP1 && ARCH_OMAP16XX - select TPS65010 + select OMAP_MCBSP help TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here if you have such a board. diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index b3ac9622f4a7..52ec2f2d6360 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -24,7 +24,7 @@ #include #include -#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) +#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) #define OMAP2_I2C_BASE2 0x48072000 #define OMAP2_I2C_INT2 57 @@ -42,8 +42,8 @@ static struct resource i2c_resources2[] = { }; static struct platform_device omap_i2c_device2 = { - .name = "i2c_omap", - .id = 2, + .name = "i2c_omap", + .id = 2, .num_resources = ARRAY_SIZE(i2c_resources2), .resource = i2c_resources2, }; diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index 2fac7d3f2af3..c5dab1d6417e 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -112,8 +112,8 @@ static struct resource i2c_resources1[] = { /* DMA not used; works around erratum writing to non-empty i2c fifo */ static struct platform_device omap_i2c_device1 = { - .name = "i2c_omap", - .id = 1, + .name = "i2c_omap", + .id = 1, .num_resources = ARRAY_SIZE(i2c_resources1), .resource = i2c_resources1, }; -- cgit v1.2.3 From b7cc6d46b4f8157bfc58a6ed143ffa83575e236a Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 6 Mar 2007 03:16:36 -0800 Subject: ARM: OMAP: FB sync with N800 tree (support for dynamic SRAM allocations) - in addition to fixed FB regions - as passed by the bootloader - allow dynamic allocations - do some more checking against overlapping / reserved regions - move the FB specific parts out from sram.c to fb.c Signed-off-by: Imre Deak Signed-off-by: Tony Lindgren Signed-off-by: Russell King --- arch/arm/mach-omap1/io.c | 4 +- arch/arm/mach-omap2/io.c | 3 +- arch/arm/plat-omap/fb.c | 277 ++++++++++++++++++++++++++++++++++----- arch/arm/plat-omap/sram.c | 63 ++------- include/asm-arm/arch-omap/sram.h | 3 - 5 files changed, 264 insertions(+), 86 deletions(-) (limited to 'arch/arm/mach-omap2') diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c index fab8b0b27cfb..81c4e738506c 100644 --- a/arch/arm/mach-omap1/io.c +++ b/arch/arm/mach-omap1/io.c @@ -17,11 +17,11 @@ #include #include #include -#include extern int omap1_clk_init(void); extern void omap_check_revision(void); extern void omap_sram_init(void); +extern void omapfb_reserve_sdram(void); /* * The machine specific code may provide the extra mapping besides the @@ -121,7 +121,7 @@ void __init omap1_map_common_io(void) #endif omap_sram_init(); - omapfb_reserve_mem(); + omapfb_reserve_sdram(); } /* diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 59458642e9eb..82dc70f6b779 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -27,6 +27,7 @@ extern void omap_sram_init(void); extern int omap2_clk_init(void); extern void omap2_check_revision(void); extern void gpmc_init(void); +extern void omapfb_reserve_sdram(void); /* * The machine specific code may provide the extra mapping besides the @@ -72,7 +73,7 @@ void __init omap2_map_common_io(void) omap2_check_revision(); omap_sram_init(); - omapfb_reserve_mem(); + omapfb_reserve_sdram(); } void __init omap2_init_common_hw(void) diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c index a302d9194f57..469f580ca057 100644 --- a/arch/arm/plat-omap/fb.c +++ b/arch/arm/plat-omap/fb.c @@ -39,6 +39,8 @@ #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) static struct omapfb_platform_data omapfb_config; +static int config_invalid; +static int configured_regions; static u64 omap_fb_dma_mask = ~(u32)0; @@ -53,46 +55,246 @@ static struct platform_device omap_fb_device = { .num_resources = 0, }; -/* called from map_io */ -void omapfb_reserve_mem(void) +static inline int ranges_overlap(unsigned long start1, unsigned long size1, + unsigned long start2, unsigned long size2) { - const struct omap_fbmem_config *fbmem_conf; - unsigned long total_size; + return (start1 >= start2 && start1 < start2 + size2) || + (start2 >= start1 && start2 < start1 + size1); +} + +static inline int range_included(unsigned long start1, unsigned long size1, + unsigned long start2, unsigned long size2) +{ + return start1 >= start2 && start1 + size1 <= start2 + size2; +} + + +/* Check if there is an overlapping region. */ +static int fbmem_region_reserved(unsigned long start, size_t size) +{ + struct omapfb_mem_region *rg; int i; - if (!omap_fb_sram_valid) { - /* FBMEM SRAM configuration was already found to be invalid. - * Ignore the whole configuration block. */ - omapfb_config.mem_desc.region_cnt = 0; - return; + rg = &omapfb_config.mem_desc.region[0]; + for (i = 0; i < OMAPFB_PLANE_NUM; i++, rg++) { + if (!rg->paddr) + /* Empty slot. */ + continue; + if (ranges_overlap(start, size, rg->paddr, rg->size)) + return 1; } + return 0; +} - i = 0; - total_size = 0; - while ((fbmem_conf = omap_get_nr_config(OMAP_TAG_FBMEM, - struct omap_fbmem_config, i)) != NULL) { - unsigned long start; - unsigned long size; +/* + * Get the region_idx`th region from board config/ATAG and convert it to + * our internal format. + */ +static int get_fbmem_region(int region_idx, struct omapfb_mem_region *rg) +{ + const struct omap_fbmem_config *conf; + u32 paddr; - if (i == OMAPFB_PLANE_NUM) { - printk(KERN_ERR "ignoring extra plane info\n"); + conf = omap_get_nr_config(OMAP_TAG_FBMEM, + struct omap_fbmem_config, region_idx); + if (conf == NULL) + return -ENOENT; + + paddr = conf->start; + /* + * Low bits encode the page allocation mode, if high bits + * are zero. Otherwise we need a page aligned fixed + * address. + */ + memset(rg, 0, sizeof(*rg)); + rg->type = paddr & ~PAGE_MASK; + rg->paddr = paddr & PAGE_MASK; + rg->size = PAGE_ALIGN(conf->size); + return 0; +} + +static int set_fbmem_region_type(struct omapfb_mem_region *rg, int mem_type, + unsigned long mem_start, + unsigned long mem_size) +{ + /* + * Check if the configuration specifies the type explicitly. + * type = 0 && paddr = 0, a default don't care case maps to + * the SDRAM type. + */ + if (rg->type || (!rg->type && !rg->paddr)) + return 0; + if (ranges_overlap(rg->paddr, rg->size, mem_start, mem_size)) { + rg->type = mem_type; + return 0; + } + /* Can't determine it. */ + return -1; +} + +static int check_fbmem_region(int region_idx, struct omapfb_mem_region *rg, + unsigned long start_avail, unsigned size_avail) +{ + unsigned long paddr = rg->paddr; + size_t size = rg->size; + + if (rg->type > OMAPFB_MEMTYPE_MAX) { + printk(KERN_ERR + "Invalid start address for FB region %d\n", region_idx); + return -EINVAL; + } + + if (!rg->size) { + printk(KERN_ERR "Zero size for FB region %d\n", region_idx); + return -EINVAL; + } + + if (!paddr) + /* Allocate this dynamically, leave paddr 0 for now. */ + return 0; + + /* + * Fixed region for the given RAM range. Check if it's already + * reserved by the FB code or someone else. + */ + if (fbmem_region_reserved(paddr, size) || + !range_included(paddr, size, start_avail, size_avail)) { + printk(KERN_ERR "Trying to use reserved memory " + "for FB region %d\n", region_idx); + return -EINVAL; + } + + 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 omapfb_reserve_sdram(void) +{ + struct bootmem_data *bdata; + unsigned long sdram_start, sdram_size; + unsigned long reserved; + int i; + + if (config_invalid) + return; + + bdata = NODE_DATA(0)->bdata; + sdram_start = bdata->node_boot_start; + sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start; + reserved = 0; + for (i = 0; ; i++) { + 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"); + config_invalid = 1; + return; } - start = fbmem_conf->start; - size = fbmem_conf->size; - omapfb_config.mem_desc.region[i].paddr = start; - omapfb_config.mem_desc.region[i].size = size; - if (omap_fb_sram_plane != i && start) { - reserve_bootmem(start, size); - total_size += size; + /* 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)) + continue; + BUG_ON(omapfb_config.mem_desc.region[i].size); + if (check_fbmem_region(i, &rg, sdram_start, sdram_size) < 0) { + config_invalid = 1; + return; } - i++; + if (rg.paddr) + reserve_bootmem(rg.paddr, rg.size); + reserved += rg.size; + omapfb_config.mem_desc.region[i] = rg; + configured_regions++; } omapfb_config.mem_desc.region_cnt = i; - if (total_size) + if (reserved) pr_info("Reserving %lu bytes SDRAM for frame buffer\n", - total_size); + reserved); +} + +/* + * Called at sram init time, before anything is pushed to the SRAM stack. + * Because of the stack scheme, we will allocate everything from the + * start of the lowest address region to the end of SRAM. This will also + * include padding for page alignment and possible holes between regions. + * + * As opposed to the SDRAM case, we'll also do any dynamic allocations at + * this point, since the driver built as a module would have problem with + * freeing / reallocating the regions. + */ +unsigned long omapfb_reserve_sram(unsigned long sram_pstart, + unsigned long sram_vstart, + unsigned long sram_size, + unsigned long pstart_avail, + unsigned long size_avail) +{ + struct omapfb_mem_region rg; + unsigned long pend_avail; + unsigned long reserved; + int i; + + if (config_invalid) + return 0; + + reserved = 0; + pend_avail = pstart_avail + size_avail; + for (i = 0; ; i++) { + if (get_fbmem_region(i, &rg) < 0) + break; + if (i == OMAPFB_PLANE_NUM) { + printk(KERN_ERR + "Extraneous FB mem configuration entries\n"); + config_invalid = 1; + return 0; + } + /* Check if it's our memory type. */ + if (set_fbmem_region_type(&rg, OMAPFB_MEMTYPE_SRAM, + sram_pstart, sram_size) < 0 || + (rg.type != OMAPFB_MEMTYPE_SRAM)) + continue; + BUG_ON(omapfb_config.mem_desc.region[i].size); + + if (check_fbmem_region(i, &rg, pstart_avail, size_avail) < 0) { + config_invalid = 1; + return 0; + } + + if (!rg.paddr) { + /* Dynamic allocation */ + if ((size_avail & PAGE_MASK) < rg.size) { + printk("Not enough SRAM for FB region %d\n", + i); + config_invalid = 1; + return 0; + } + size_avail = (size_avail - rg.size) & PAGE_MASK; + rg.paddr = pstart_avail + size_avail; + } + /* Reserve everything above the start of the region. */ + if (pend_avail - rg.paddr > reserved) + reserved = pend_avail - rg.paddr; + size_avail = pend_avail - reserved - pstart_avail; + + /* + * We have a kernel mapping for this already, so the + * driver won't have to make one. + */ + rg.vaddr = (void *)(sram_vstart + rg.paddr - sram_pstart); + omapfb_config.mem_desc.region[i] = rg; + configured_regions++; + } + omapfb_config.mem_desc.region_cnt = i; + if (reserved) + pr_info("Reserving %lu bytes SRAM for frame buffer\n", + reserved); + return reserved; } void omapfb_set_ctrl_platform_data(void *data) @@ -104,10 +306,19 @@ static inline int omap_init_fb(void) { const struct omap_lcd_config *conf; + if (config_invalid) + return 0; + if (configured_regions != omapfb_config.mem_desc.region_cnt) { + printk(KERN_ERR "Invalid FB mem configuration entries\n"); + return 0; + } conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config); - if (conf == NULL) + if (conf == NULL) { + if (configured_regions) + /* FB mem config, but no LCD config? */ + printk(KERN_ERR "Missing LCD configuration\n"); return 0; - + } omapfb_config.lcd = *conf; return platform_device_register(&omap_fb_device); @@ -117,7 +328,13 @@ arch_initcall(omap_init_fb); #else -void omapfb_reserve_mem(void) {} +void omapfb_reserve_sdram(void) {} +unsigned long omapfb_reserve_sram(unsigned long sram_pstart, + unsigned long sram_vstart, + unsigned long sram_size, + unsigned long start_avail, + unsigned long size_avail) {} + #endif diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index 7e5f8877e051..bc46f33aede3 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -51,10 +51,14 @@ static unsigned long omap_sram_base; static unsigned long omap_sram_size; static unsigned long omap_sram_ceil; -int omap_fb_sram_plane = -1; -int omap_fb_sram_valid; +extern unsigned long omapfb_reserve_sram(unsigned long sram_pstart, + unsigned long sram_vstart, + unsigned long sram_size, + unsigned long pstart_avail, + unsigned long size_avail); -/* Depending on the target RAMFS firewall setup, the public usable amount of +/* + * Depending on the target RAMFS firewall setup, the public usable amount of * SRAM varies. The default accessable size for all device types is 2k. A GP * device allows ARM11 but not other initators for full size. This * functionality seems ok until some nice security API happens. @@ -78,45 +82,6 @@ static int is_sram_locked(void) return 1; /* assume locked with no PPA or security driver */ } -static int get_fb_sram_conf(unsigned long start_avail, unsigned size_avail, - unsigned long *start, int *plane_idx) -{ - const struct omap_fbmem_config *fbmem_conf; - unsigned long size = 0; - int i; - - i = 0; - *start = 0; - *plane_idx = -1; - while ((fbmem_conf = omap_get_nr_config(OMAP_TAG_FBMEM, - struct omap_fbmem_config, i)) != NULL) { - u32 paddr, end; - - paddr = fbmem_conf->start; - end = fbmem_conf->start + fbmem_conf->size; - if (paddr > omap_sram_start && - paddr < omap_sram_start + omap_sram_size) { - if (*plane_idx != -1 || paddr < start_avail || - paddr == end || - end > start_avail + size_avail) { - printk(KERN_ERR "invalid FB SRAM configuration"); - *start = 0; - return -1; - } - *plane_idx = i; - *start = fbmem_conf->start; - size = fbmem_conf->size; - } - i++; - } - - if (*plane_idx >= 0) - pr_info("Reserving %lu bytes SRAM frame buffer " - "for plane %d\n", size, *plane_idx); - - return 0; -} - /* * The amount of SRAM depends on the core type. * Note that we cannot try to test for SRAM here because writes @@ -125,7 +90,7 @@ static int get_fb_sram_conf(unsigned long start_avail, unsigned size_avail, */ void __init omap_detect_sram(void) { - unsigned long fb_sram_start; + unsigned long reserved; if (cpu_is_omap24xx()) { if (is_sram_locked()) { @@ -158,13 +123,11 @@ void __init omap_detect_sram(void) omap_sram_size = 0x4000; } } - if (get_fb_sram_conf(omap_sram_start + SRAM_BOOTLOADER_SZ, - omap_sram_size - SRAM_BOOTLOADER_SZ, - &fb_sram_start, &omap_fb_sram_plane) == 0) - omap_fb_sram_valid = 1; - if (omap_fb_sram_valid && omap_fb_sram_plane >= 0) - omap_sram_size -= omap_sram_start + omap_sram_size - - fb_sram_start; + reserved = omapfb_reserve_sram(omap_sram_start, omap_sram_base, + omap_sram_size, + omap_sram_start + SRAM_BOOTLOADER_SZ, + omap_sram_size - SRAM_BOOTLOADER_SZ); + omap_sram_size -= reserved; omap_sram_ceil = omap_sram_base + omap_sram_size; } diff --git a/include/asm-arm/arch-omap/sram.h b/include/asm-arm/arch-omap/sram.h index cc6161d63988..bb9bb3fd532f 100644 --- a/include/asm-arm/arch-omap/sram.h +++ b/include/asm-arm/arch-omap/sram.h @@ -20,9 +20,6 @@ extern void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val, u32 mem_type); extern u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass); -extern int omap_fb_sram_plane; -extern int omap_fb_sram_valid; - /* Do not use these */ extern void sram_reprogram_clock(u32 ckctl, u32 dpllctl); extern unsigned long sram_reprogram_clock_sz; -- cgit v1.2.3