diff options
Diffstat (limited to 'arch/arm/mach-omap1/devices.c')
| -rw-r--r-- | arch/arm/mach-omap1/devices.c | 547 |
1 files changed, 337 insertions, 210 deletions
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c index 3c5d901efea..325e6030095 100644 --- a/arch/arm/mach-omap1/devices.c +++ b/arch/arm/mach-omap1/devices.c @@ -9,213 +9,125 @@ * (at your option) any later version. */ -#include <linux/config.h> +#include <linux/dma-mapping.h> +#include <linux/gpio.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> +#include <linux/spi/spi.h> -#include <asm/hardware.h> -#include <asm/io.h> -#include <asm/mach-types.h> -#include <asm/mach/map.h> - -#include <asm/arch/tc.h> -#include <asm/arch/board.h> -#include <asm/arch/mux.h> -#include <asm/arch/gpio.h> - - -static void omap_nop_release(struct device *dev) -{ - /* Nothing */ -} +#include <linux/platform_data/omap-wd-timer.h> -/*-------------------------------------------------------------------------*/ +#include <asm/mach/map.h> -#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) +#include <mach/tc.h> +#include <mach/mux.h> -#define OMAP_I2C_BASE 0xfffb3800 +#include <mach/omap7xx.h> +#include <mach/camera.h> +#include <mach/hardware.h> -static struct resource i2c_resources[] = { - { - .start = OMAP_I2C_BASE, - .end = OMAP_I2C_BASE + 0x3f, - .flags = IORESOURCE_MEM, - }, - { - .start = INT_I2C, - .flags = IORESOURCE_IRQ, - }, -}; +#include "common.h" +#include "clock.h" +#include "mmc.h" +#include "sram.h" -/* DMA not used; works around erratum writing to non-empty i2c fifo */ +#if defined(CONFIG_SND_SOC) || defined(CONFIG_SND_SOC_MODULE) -static struct platform_device omap_i2c_device = { - .name = "i2c_omap", - .id = -1, - .dev = { - .release = omap_nop_release, - }, - .num_resources = ARRAY_SIZE(i2c_resources), - .resource = i2c_resources, +static struct platform_device omap_pcm = { + .name = "omap-pcm-audio", + .id = -1, }; -static void omap_init_i2c(void) +static void omap_init_audio(void) { - /* FIXME define and use a boot tag, in case of boards that - * either don't wire up I2C, or chips that mux it differently... - * it can include clocking and address info, maybe more. - */ - omap_cfg_reg(I2C_SCL); - omap_cfg_reg(I2C_SDA); - - (void) platform_device_register(&omap_i2c_device); + platform_device_register(&omap_pcm); } -#else -static inline void omap_init_i2c(void) {} -#endif - -/*-------------------------------------------------------------------------*/ - -#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 = { - .release = omap_nop_release, - .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) {} +static inline void omap_init_audio(void) {} #endif /*-------------------------------------------------------------------------*/ -#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) - -#define OMAP_MMC1_BASE 0xfffb7800 -#define OMAP_MMC2_BASE 0xfffb7c00 /* omap16xx only */ - -static struct omap_mmc_conf mmc1_conf; +#if defined(CONFIG_RTC_DRV_OMAP) || defined(CONFIG_RTC_DRV_OMAP_MODULE) -static u64 mmc1_dmamask = 0xffffffff; +#define OMAP_RTC_BASE 0xfffb4800 -static struct resource mmc1_resources[] = { +static struct resource rtc_resources[] = { { - .start = IO_ADDRESS(OMAP_MMC1_BASE), - .end = IO_ADDRESS(OMAP_MMC1_BASE) + 0x7f, + .start = OMAP_RTC_BASE, + .end = OMAP_RTC_BASE + 0x5f, .flags = IORESOURCE_MEM, }, { - .start = INT_MMC, + .start = INT_RTC_TIMER, .flags = IORESOURCE_IRQ, }, -}; - -static struct platform_device mmc_omap_device1 = { - .name = "mmci-omap", - .id = 1, - .dev = { - .release = omap_nop_release, - .dma_mask = &mmc1_dmamask, - .platform_data = &mmc1_conf, - }, - .num_resources = ARRAY_SIZE(mmc1_resources), - .resource = mmc1_resources, -}; - -#ifdef CONFIG_ARCH_OMAP16XX - -static struct omap_mmc_conf mmc2_conf; - -static u64 mmc2_dmamask = 0xffffffff; - -static struct resource mmc2_resources[] = { - { - .start = IO_ADDRESS(OMAP_MMC2_BASE), - .end = IO_ADDRESS(OMAP_MMC2_BASE) + 0x7f, - .flags = IORESOURCE_MEM, - }, { - .start = INT_1610_MMC2, + .start = INT_RTC_ALARM, .flags = IORESOURCE_IRQ, }, }; -static struct platform_device mmc_omap_device2 = { - .name = "mmci-omap", - .id = 2, - .dev = { - .release = omap_nop_release, - .dma_mask = &mmc2_dmamask, - .platform_data = &mmc2_conf, - }, - .num_resources = ARRAY_SIZE(mmc2_resources), - .resource = mmc2_resources, +static struct platform_device omap_rtc_device = { + .name = "omap_rtc", + .id = -1, + .num_resources = ARRAY_SIZE(rtc_resources), + .resource = rtc_resources, }; -#endif -static void __init omap_init_mmc(void) +static void omap_init_rtc(void) { - const struct omap_mmc_config *mmc_conf; - const struct omap_mmc_conf *mmc; + (void) platform_device_register(&omap_rtc_device); +} +#else +static inline void omap_init_rtc(void) {} +#endif - /* NOTE: assumes MMC was never (wrongly) enabled */ - mmc_conf = omap_get_config(OMAP_TAG_MMC, struct omap_mmc_config); - if (!mmc_conf) - return; +static inline void omap_init_mbox(void) { } + +/*-------------------------------------------------------------------------*/ + +#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) + +static inline void omap1_mmc_mux(struct omap_mmc_platform_data *mmc_controller, + int controller_nr) +{ + if (controller_nr == 0) { + if (cpu_is_omap7xx()) { + omap_cfg_reg(MMC_7XX_CMD); + omap_cfg_reg(MMC_7XX_CLK); + omap_cfg_reg(MMC_7XX_DAT0); + } else { + omap_cfg_reg(MMC_CMD); + omap_cfg_reg(MMC_CLK); + omap_cfg_reg(MMC_DAT0); + } - /* block 1 is always available and has just one pinout option */ - mmc = &mmc_conf->mmc[0]; - if (mmc->enabled) { - omap_cfg_reg(MMC_CMD); - omap_cfg_reg(MMC_CLK); - omap_cfg_reg(MMC_DAT0); if (cpu_is_omap1710()) { - omap_cfg_reg(M15_1710_MMC_CLKI); - omap_cfg_reg(P19_1710_MMC_CMDDIR); - omap_cfg_reg(P20_1710_MMC_DATDIR0); - } - if (mmc->wire4) { + omap_cfg_reg(M15_1710_MMC_CLKI); + omap_cfg_reg(P19_1710_MMC_CMDDIR); + omap_cfg_reg(P20_1710_MMC_DATDIR0); + } + if (mmc_controller->slots[0].wires == 4 && !cpu_is_omap7xx()) { omap_cfg_reg(MMC_DAT1); - /* NOTE: DAT2 can be on W10 (here) or M15 */ - if (!mmc->nomux) + /* NOTE: DAT2 can be on W10 (here) or M15 */ + if (!mmc_controller->slots[0].nomux) omap_cfg_reg(MMC_DAT2); omap_cfg_reg(MMC_DAT3); } - mmc1_conf = *mmc; - (void) platform_device_register(&mmc_omap_device1); } -#ifdef CONFIG_ARCH_OMAP16XX - /* block 2 is on newer chips, and has many pinout options */ - mmc = &mmc_conf->mmc[1]; - if (mmc->enabled) { - if (!mmc->nomux) { + /* Block 2 is on newer chips, and has many pinout options */ + if (cpu_is_omap16xx() && controller_nr == 1) { + if (!mmc_controller->slots[1].nomux) { omap_cfg_reg(Y8_1610_MMC2_CMD); omap_cfg_reg(Y10_1610_MMC2_CLK); omap_cfg_reg(R18_1610_MMC2_CLKIN); omap_cfg_reg(W8_1610_MMC2_DAT0); - if (mmc->wire4) { + if (mmc_controller->slots[1].wires == 4) { omap_cfg_reg(V8_1610_MMC2_DAT1); omap_cfg_reg(W15_1610_MMC2_DAT2); omap_cfg_reg(R10_1610_MMC2_DAT3); @@ -230,88 +142,255 @@ static void __init omap_init_mmc(void) /* Feedback clock must be set on OMAP-1710 MMC2 */ if (cpu_is_omap1710()) omap_writel(omap_readl(MOD_CONF_CTRL_1) | (1 << 24), - MOD_CONF_CTRL_1); - mmc2_conf = *mmc; - (void) platform_device_register(&mmc_omap_device2); + MOD_CONF_CTRL_1); } +} + +#define OMAP_MMC_NR_RES 4 + +/* + * Register MMC devices. + */ +static int __init omap_mmc_add(const char *name, int id, unsigned long base, + unsigned long size, unsigned int irq, + unsigned rx_req, unsigned tx_req, + struct omap_mmc_platform_data *data) +{ + struct platform_device *pdev; + struct resource res[OMAP_MMC_NR_RES]; + int ret; + + pdev = platform_device_alloc(name, id); + if (!pdev) + return -ENOMEM; + + memset(res, 0, OMAP_MMC_NR_RES * sizeof(struct resource)); + res[0].start = base; + res[0].end = base + size - 1; + res[0].flags = IORESOURCE_MEM; + res[1].start = res[1].end = irq; + res[1].flags = IORESOURCE_IRQ; + res[2].start = rx_req; + res[2].name = "rx"; + res[2].flags = IORESOURCE_DMA; + res[3].start = tx_req; + res[3].name = "tx"; + res[3].flags = IORESOURCE_DMA; + + if (cpu_is_omap7xx()) + data->slots[0].features = MMC_OMAP7XX; + if (cpu_is_omap15xx()) + data->slots[0].features = MMC_OMAP15XX; + if (cpu_is_omap16xx()) + data->slots[0].features = MMC_OMAP16XX; + + ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res)); + if (ret == 0) + ret = platform_device_add_data(pdev, data, sizeof(*data)); + if (ret) + goto fail; + + ret = platform_device_add(pdev); + if (ret) + goto fail; + + /* return device handle to board setup code */ + data->dev = &pdev->dev; + return 0; + +fail: + platform_device_put(pdev); + return ret; +} + +void __init omap1_init_mmc(struct omap_mmc_platform_data **mmc_data, + int nr_controllers) +{ + int i; + + for (i = 0; i < nr_controllers; i++) { + unsigned long base, size; + unsigned rx_req, tx_req; + unsigned int irq = 0; + + if (!mmc_data[i]) + continue; + + omap1_mmc_mux(mmc_data[i], i); + + switch (i) { + case 0: + base = OMAP1_MMC1_BASE; + irq = INT_MMC; + rx_req = 22; + tx_req = 21; + break; + case 1: + if (!cpu_is_omap16xx()) + return; + base = OMAP1_MMC2_BASE; + irq = INT_1610_MMC2; + rx_req = 55; + tx_req = 54; + break; + default: + continue; + } + size = OMAP1_MMC_SIZE; + + omap_mmc_add("mmci-omap", i, base, size, irq, + rx_req, tx_req, mmc_data[i]); + } +} + #endif - return; + +/*-------------------------------------------------------------------------*/ + +/* OMAP7xx SPI support */ +#if defined(CONFIG_SPI_OMAP_100K) || defined(CONFIG_SPI_OMAP_100K_MODULE) + +struct platform_device omap_spi1 = { + .name = "omap1_spi100k", + .id = 1, +}; + +struct platform_device omap_spi2 = { + .name = "omap1_spi100k", + .id = 2, +}; + +static void omap_init_spi100k(void) +{ + omap_spi1.dev.platform_data = ioremap(OMAP7XX_SPI1_BASE, 0x7ff); + if (omap_spi1.dev.platform_data) + platform_device_register(&omap_spi1); + + omap_spi2.dev.platform_data = ioremap(OMAP7XX_SPI2_BASE, 0x7ff); + if (omap_spi2.dev.platform_data) + platform_device_register(&omap_spi2); } + #else -static inline void omap_init_mmc(void) {} +static inline void omap_init_spi100k(void) +{ +} #endif -#if defined(CONFIG_OMAP_RTC) || defined(CONFIG_OMAP_RTC) -#define OMAP_RTC_BASE 0xfffb4800 +#define OMAP1_CAMERA_BASE 0xfffb6800 +#define OMAP1_CAMERA_IOSIZE 0x1c -static struct resource rtc_resources[] = { - { - .start = OMAP_RTC_BASE, - .end = OMAP_RTC_BASE + 0x5f, - .flags = IORESOURCE_MEM, +static struct resource omap1_camera_resources[] = { + [0] = { + .start = OMAP1_CAMERA_BASE, + .end = OMAP1_CAMERA_BASE + OMAP1_CAMERA_IOSIZE - 1, + .flags = IORESOURCE_MEM, }, - { - .start = INT_RTC_TIMER, - .flags = IORESOURCE_IRQ, - }, - { - .start = INT_RTC_ALARM, - .flags = IORESOURCE_IRQ, + [1] = { + .start = INT_CAMERA, + .flags = IORESOURCE_IRQ, }, }; -static struct platform_device omap_rtc_device = { - .name = "omap_rtc", - .id = -1, - .dev = { - .release = omap_nop_release, +static u64 omap1_camera_dma_mask = DMA_BIT_MASK(32); + +static struct platform_device omap1_camera_device = { + .name = "omap1-camera", + .id = 0, /* This is used to put cameras on this interface */ + .dev = { + .dma_mask = &omap1_camera_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), }, - .num_resources = ARRAY_SIZE(rtc_resources), - .resource = rtc_resources, + .num_resources = ARRAY_SIZE(omap1_camera_resources), + .resource = omap1_camera_resources, }; -static void omap_init_rtc(void) +void __init omap1_camera_init(void *info) { - (void) platform_device_register(&omap_rtc_device); + struct platform_device *dev = &omap1_camera_device; + int ret; + + dev->dev.platform_data = info; + + ret = platform_device_register(dev); + if (ret) + dev_err(&dev->dev, "unable to register device: %d\n", ret); } -#else -static inline void omap_init_rtc(void) {} -#endif + /*-------------------------------------------------------------------------*/ -#if defined(CONFIG_OMAP16XX_WATCHDOG) || defined(CONFIG_OMAP16XX_WATCHDOG_MODULE) +static inline void omap_init_sti(void) {} -#define OMAP_WDT_BASE 0xfffeb000 +/* Numbering for the SPI-capable controllers when used for SPI: + * spi = 1 + * uwire = 2 + * mmc1..2 = 3..4 + * mcbsp1..3 = 5..7 + */ -static struct resource wdt_resources[] = { +#if defined(CONFIG_SPI_OMAP_UWIRE) || defined(CONFIG_SPI_OMAP_UWIRE_MODULE) + +#define OMAP_UWIRE_BASE 0xfffb3000 + +static struct resource uwire_resources[] = { { - .start = OMAP_WDT_BASE, - .end = OMAP_WDT_BASE + 0x4f, + .start = OMAP_UWIRE_BASE, + .end = OMAP_UWIRE_BASE + 0x20, .flags = IORESOURCE_MEM, }, }; -static struct platform_device omap_wdt_device = { - .name = "omap1610_wdt", +static struct platform_device omap_uwire_device = { + .name = "omap_uwire", .id = -1, - .dev = { - .release = omap_nop_release, - }, - .num_resources = ARRAY_SIZE(wdt_resources), - .resource = wdt_resources, + .num_resources = ARRAY_SIZE(uwire_resources), + .resource = uwire_resources, }; -static void omap_init_wdt(void) +static void omap_init_uwire(void) { - (void) platform_device_register(&omap_wdt_device); + /* FIXME define and use a boot tag; not all boards will be hooking + * up devices to the microwire controller, and multi-board configs + * mean that CONFIG_SPI_OMAP_UWIRE may be configured anyway... + */ + + /* board-specific code must configure chipselects (only a few + * are normally used) and SCLK/SDI/SDO (each has two choices). + */ + (void) platform_device_register(&omap_uwire_device); } #else -static inline void omap_init_wdt(void) {} +static inline void omap_init_uwire(void) {} #endif +#define OMAP1_RNG_BASE 0xfffe5000 + +static struct resource omap1_rng_resources[] = { + { + .start = OMAP1_RNG_BASE, + .end = OMAP1_RNG_BASE + 0x4f, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device omap1_rng_device = { + .name = "omap_rng", + .id = -1, + .num_resources = ARRAY_SIZE(omap1_rng_resources), + .resource = omap1_rng_resources, +}; + +static void omap1_init_rng(void) +{ + if (!cpu_is_omap16xx()) + return; + + (void) platform_device_register(&omap1_rng_device); +} + /*-------------------------------------------------------------------------*/ /* @@ -329,23 +408,71 @@ static inline void omap_init_wdt(void) {} * Claiming GPIOs, and setting their direction and initial values, is the * responsibility of the device drivers. So is responding to probe(). * - * Board-specific knowlege like creating devices or pin setup is to be + * Board-specific knowledge like creating devices or pin setup is to be * kept out of drivers as much as possible. In particular, pin setup * may be handled by the boot loader, and drivers should expect it will * normally have been done by the time they're probed. */ -static int __init omap_init_devices(void) +static int __init omap1_init_devices(void) { + if (!cpu_class_is_omap1()) + return -ENODEV; + + omap_sram_init(); + omap1_clk_late_init(); + /* please keep these calls, and their implementations above, * in alphabetical order so they're easier to sort through. */ - omap_init_i2c(); - omap_init_irda(); - omap_init_mmc(); + + omap_init_audio(); + omap_init_mbox(); omap_init_rtc(); - omap_init_wdt(); + omap_init_spi100k(); + omap_init_sti(); + omap_init_uwire(); + omap1_init_rng(); return 0; } -arch_initcall(omap_init_devices); +arch_initcall(omap1_init_devices); + +#if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE) +static struct resource wdt_resources[] = { + { + .start = 0xfffeb000, + .end = 0xfffeb07F, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device omap_wdt_device = { + .name = "omap_wdt", + .id = -1, + .num_resources = ARRAY_SIZE(wdt_resources), + .resource = wdt_resources, +}; + +static int __init omap_init_wdt(void) +{ + struct omap_wd_timer_platform_data pdata; + int ret; + + if (!cpu_is_omap16xx()) + return -ENODEV; + + pdata.read_reset_sources = omap1_get_reset_sources; + + ret = platform_device_register(&omap_wdt_device); + if (!ret) { + ret = platform_device_add_data(&omap_wdt_device, &pdata, + sizeof(pdata)); + if (ret) + platform_device_del(&omap_wdt_device); + } + + return ret; +} +subsys_initcall(omap_init_wdt); +#endif |
