From: Tony Lindgren Date: Fri, 3 Apr 2009 22:23:40 +0000 (-0700) Subject: Initial import of extra code in arch/arm/*omap* into omap-pool branch X-Git-Url: http://www.pilppa.org/gitweb/gitweb.cgi?p=linux-2.6-omap-h63xx.git;a=commitdiff_plain;h=e6cb73629ec43b7bd5c79d285f7e293cd7e7395f Initial import of extra code in arch/arm/*omap* into omap-pool branch This patch moves all arch/arm/*omap* changes not in mainline kernel into omap-pool branch where it can be worked into patches for mainline, or removed. Signed-off-by: Tony Lindgren --- diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig index 3f325d3718a..a51c730da64 100644 --- a/arch/arm/mach-omap1/Kconfig +++ b/arch/arm/mach-omap1/Kconfig @@ -46,7 +46,6 @@ 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 1bda8f5d754..6867cd3ad0b 100644 --- a/arch/arm/mach-omap1/Makefile +++ b/arch/arm/mach-omap1/Makefile @@ -13,6 +13,10 @@ obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o # Power Management obj-$(CONFIG_PM) += pm.o sleep.o +# DSP +obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o +mailbox_mach-objs := mailbox.o + led-y := leds.o # Specific board support diff --git a/arch/arm/mach-omap1/board-h2-mmc.c b/arch/arm/mach-omap1/board-h2-mmc.c index 44d4a966bed..46098f54682 100644 --- a/arch/arm/mach-omap1/board-h2-mmc.c +++ b/arch/arm/mach-omap1/board-h2-mmc.c @@ -26,19 +26,13 @@ static int mmc_set_power(struct device *dev, int slot, int power_on, int vdd) { - if (power_on) - gpio_direction_output(H2_TPS_GPIO_MMC_PWR_EN, 1); - else - gpio_direction_output(H2_TPS_GPIO_MMC_PWR_EN, 0); - + gpio_set_value(H2_TPS_GPIO_MMC_PWR_EN, power_on); return 0; } static int mmc_late_init(struct device *dev) { - int ret; - - ret = gpio_request(H2_TPS_GPIO_MMC_PWR_EN, "MMC power"); + int ret = gpio_request(H2_TPS_GPIO_MMC_PWR_EN, "MMC power"); if (ret < 0) return ret; @@ -47,7 +41,7 @@ static int mmc_late_init(struct device *dev) return ret; } -static void mmc_shutdown(struct device *dev) +static void mmc_cleanup(struct device *dev) { gpio_free(H2_TPS_GPIO_MMC_PWR_EN); } @@ -60,7 +54,7 @@ static void mmc_shutdown(struct device *dev) static struct omap_mmc_platform_data mmc1_data = { .nr_slots = 1, .init = mmc_late_init, - .shutdown = mmc_shutdown, + .cleanup = mmc_cleanup, .dma_mask = 0xffffffff, .slots[0] = { .set_power = mmc_set_power, diff --git a/arch/arm/mach-omap1/board-h3-mmc.c b/arch/arm/mach-omap1/board-h3-mmc.c index 0d8a3c195e2..5e8877ce35e 100644 --- a/arch/arm/mach-omap1/board-h3-mmc.c +++ b/arch/arm/mach-omap1/board-h3-mmc.c @@ -26,11 +26,7 @@ static int mmc_set_power(struct device *dev, int slot, int power_on, int vdd) { - if (power_on) - gpio_direction_output(H3_TPS_GPIO_MMC_PWR_EN, 1); - else - gpio_direction_output(H3_TPS_GPIO_MMC_PWR_EN, 0); - + gpio_set_value(H3_TPS_GPIO_MMC_PWR_EN, power_on); return 0; } diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index 4695965114c..f597968733b 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c @@ -39,12 +39,10 @@ #include #include -#include #include #include #include #include -#include #include #include #include @@ -276,104 +274,6 @@ static struct platform_device h3_kp_device = { .resource = h3_kp_resources, }; - -/* Select between the IrDA and aGPS module - */ -static int h3_select_irda(struct device *dev, int state) -{ - unsigned char expa; - int err = 0; - - if ((err = read_gpio_expa(&expa, 0x26))) { - printk(KERN_ERR "Error reading from I/O EXPANDER \n"); - return err; - } - - /* 'P6' enable/disable IRDA_TX and IRDA_RX */ - if (state & IR_SEL) { /* IrDA */ - if ((err = write_gpio_expa(expa | 0x40, 0x26))) { - printk(KERN_ERR "Error writing to I/O EXPANDER \n"); - return err; - } - } else { - if ((err = write_gpio_expa(expa & ~0x40, 0x26))) { - printk(KERN_ERR "Error writing to I/O EXPANDER \n"); - return err; - } - } - return err; -} - -static void set_trans_mode(struct work_struct *work) -{ - struct omap_irda_config *irda_config = - container_of(work, struct omap_irda_config, gpio_expa.work); - int mode = irda_config->mode; - unsigned char expa; - int err = 0; - - if ((err = read_gpio_expa(&expa, 0x27)) != 0) { - printk(KERN_ERR "Error reading from I/O expander\n"); - } - - expa &= ~0x03; - - if (mode & IR_SIRMODE) { - expa |= 0x01; - } else { /* MIR/FIR */ - expa |= 0x03; - } - - if ((err = write_gpio_expa(expa, 0x27)) != 0) { - printk(KERN_ERR "Error writing to I/O expander\n"); - } -} - -static int h3_transceiver_mode(struct device *dev, int mode) -{ - struct omap_irda_config *irda_config = dev->platform_data; - - irda_config->mode = mode; - cancel_delayed_work(&irda_config->gpio_expa); - PREPARE_DELAYED_WORK(&irda_config->gpio_expa, set_trans_mode); - schedule_delayed_work(&irda_config->gpio_expa, 0); - - return 0; -} - -static struct omap_irda_config h3_irda_data = { - .transceiver_cap = IR_SIRMODE | IR_MIRMODE | IR_FIRMODE, - .transceiver_mode = h3_transceiver_mode, - .select_irda = h3_select_irda, - .rx_channel = OMAP_DMA_UART3_RX, - .tx_channel = OMAP_DMA_UART3_TX, - .dest_start = UART3_THR, - .src_start = UART3_RHR, - .tx_trigger = 0, - .rx_trigger = 0, -}; - -static struct resource h3_irda_resources[] = { - [0] = { - .start = INT_UART3, - .end = INT_UART3, - .flags = IORESOURCE_IRQ, - }, -}; - -static u64 irda_dmamask = 0xffffffff; - -static struct platform_device h3_irda_device = { - .name = "omapirda", - .id = 0, - .dev = { - .platform_data = &h3_irda_data, - .dma_mask = &irda_dmamask, - }, - .num_resources = ARRAY_SIZE(h3_irda_resources), - .resource = h3_irda_resources, -}; - static struct platform_device h3_lcd_device = { .name = "lcd_h3", .id = -1, @@ -395,7 +295,6 @@ static struct platform_device *devices[] __initdata = { &nand_device, &smc91x_device, &intlat_device, - &h3_irda_device, &h3_kp_device, &h3_lcd_device, }; diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c index 7bc7a3cb9c5..8780ca66639 100644 --- a/arch/arm/mach-omap1/board-nokia770.c +++ b/arch/arm/mach-omap1/board-nokia770.c @@ -35,6 +35,7 @@ #include #include #include +#include #define ADS7846_PENDOWN_GPIO 15 @@ -181,11 +182,7 @@ static struct omap_usb_config nokia770_usb_config __initdata = { static int nokia770_mmc_set_power(struct device *dev, int slot, int power_on, int vdd) { - if (power_on) - gpio_set_value(NOKIA770_GPIO_MMC_POWER, 1); - else - gpio_set_value(NOKIA770_GPIO_MMC_POWER, 0); - + gpio_set_value(NOKIA770_GPIO_MMC_POWER, power_on); return 0; } diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 64ab386a65c..3a2214cb37a 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -10,10 +10,13 @@ config ARCH_OMAP2420 depends on ARCH_OMAP24XX select OMAP_DM_TIMER select ARCH_OMAP_OTG + select CPU_V6 config ARCH_OMAP2430 bool "OMAP2430 support" depends on ARCH_OMAP24XX + select ARCH_OMAP_OTG + select CPU_V6 config ARCH_OMAP34XX bool "OMAP34xx Based System" @@ -23,6 +26,7 @@ config ARCH_OMAP3430 bool "OMAP3430 support" depends on ARCH_OMAP3 && ARCH_OMAP34XX select ARCH_OMAP_OTG + select CPU_V7 comment "OMAP Board Type" depends on ARCH_OMAP2 || ARCH_OMAP3 @@ -31,25 +35,98 @@ config MACH_OMAP_GENERIC bool "Generic OMAP board" depends on ARCH_OMAP2 && ARCH_OMAP24XX +config MACH_NOKIA_N800 + bool "Nokia N800" + depends on ARCH_OMAP2420 + select VIDEO_TCM825X if VIDEO_OMAP2 && VIDEO_HELPER_CHIPS_AUTO + select CBUS if VIDEO_TCM825X + select CBUS_RETU if VIDEO_TCM825X + select MENELAUS if VIDEO_TCM825X + select OMAP_GPIO_SWITCH + +config MACH_NOKIA_N810 + bool "Nokia N810" + depends on MACH_NOKIA_N800 + +config MACH_NOKIA_N810_WIMAX + bool "Nokia N810 WiMAX" + depends on MACH_NOKIA_N800 + select MACH_NOKIA_N810 + +config MACH_NOKIA_RX51 + bool "Nokia RX-51 board" + depends on ARCH_OMAP3 && ARCH_OMAP34XX + +config MACH_OMAP2_TUSB6010 + bool + depends on ARCH_OMAP2 && ARCH_OMAP2420 + default y if MACH_NOKIA_N800 + config MACH_OMAP_H4 bool "OMAP 2420 H4 board" - depends on ARCH_OMAP2 && ARCH_OMAP24XX + depends on ARCH_OMAP2 && ARCH_OMAP2420 select OMAP_DEBUG_DEVICES +config MACH_OMAP_H4_TUSB + bool "TUSB 6010 EVM board" + depends on MACH_OMAP_H4 + select MACH_OMAP2_TUSB6010 + help + Set this if you've got a TUSB6010 high speed USB board. + You may need to consult the schematics for your revisions + of the Menelaus and TUSB boards, and make changes to be + sure this is set up properly for your board stack. + + Be sure to select OTG mode operation, not host-only or + peripheral-only. + +config MACH_OMAP_H4_OTG + bool "Use USB OTG connector, not device connector (S1.10)" + depends on MACH_OMAP_H4 + help + Set this if you've set S1.10 (on the mainboard) to use the + Mini-AB (OTG) connector and OTG transceiver with the USB0 + port, instead of the Mini-B ("download") connector with its + non-OTG transceiver. + + Note that the "download" connector can be used to bootstrap + the system from the OMAP mask ROM. Also, since this is a + development platform, you can also force the OTG port into + a non-OTG operational mode. + +config MACH_OMAP2_H4_USB1 + bool "Use USB1 port, not UART2 (S3.3)" + depends on MACH_OMAP_H4 + help + Set this if you've set SW3.3 (on the CPU card) so that the + expansion connectors receive USB1 signals instead of UART2. + config MACH_OMAP_APOLLON bool "OMAP 2420 Apollon board" - depends on ARCH_OMAP2 && ARCH_OMAP24XX + depends on ARCH_OMAP2 && ARCH_OMAP2420 config MACH_OMAP_2430SDP bool "OMAP 2430 SDP board" + depends on ARCH_OMAP2 && ARCH_OMAP2430 + +config MACH_OMAP_LDP + bool "OMAP3 LDP board" + depends on ARCH_OMAP3 && ARCH_OMAP34XX + +config MACH_OMAP2EVM + bool "OMAP 2530 EVM board" depends on ARCH_OMAP2 && ARCH_OMAP24XX -config MACH_OMAP3_BEAGLE - bool "OMAP3 BEAGLE board" +config MACH_OMAP_3430SDP + bool "OMAP 3430 SDP board" depends on ARCH_OMAP3 && ARCH_OMAP34XX -config MACH_OMAP_LDP - bool "OMAP3 LDP board" +config MACH_OMAP3EVM + bool "OMAP 3530 EVM board" + depends on ARCH_OMAP3 && ARCH_OMAP34XX + +config MACH_OMAP3_BEAGLE + bool "OMAP3 BEAGLE board" depends on ARCH_OMAP3 && ARCH_OMAP34XX config MACH_OVERO diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index a2c3fcc27a2..76acefa0c76 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -28,26 +28,59 @@ endif obj-$(CONFIG_ARCH_OMAP2) += clock24xx.o obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o +# DSP +obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o +mailbox_mach-objs := mailbox.o + # Specific board support obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.o \ + board-2430sdp-flash.o \ mmc-twl4030.o -obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o -obj-$(CONFIG_MACH_OMAP3_BEAGLE) += board-omap3beagle.o \ +obj-$(CONFIG_MACH_OMAP2EVM) += board-omap2evm.o \ mmc-twl4030.o +obj-$(CONFIG_MACH_OMAP_3430SDP) += board-3430sdp.o \ + mmc-twl4030.o \ + board-3430sdp-flash.o +obj-$(CONFIG_MACH_OMAP3EVM) += board-omap3evm.o \ + mmc-twl4030.o \ + board-omap3evm-flash.o \ + twl4030-generic-scripts.o +obj-$(CONFIG_MACH_OMAP3_BEAGLE) += board-omap3beagle.o \ + mmc-twl4030.o \ + twl4030-generic-scripts.o obj-$(CONFIG_MACH_OMAP_LDP) += board-ldp.o \ mmc-twl4030.o -obj-$(CONFIG_MACH_OVERO) += board-overo.o \ +obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o \ + board-apollon-mmc.o \ + board-apollon-keys.o +obj-$(CONFIG_MACH_NOKIA_N800) += board-n800.o board-n800-flash.o \ + board-n800-mmc.o board-n800-bt.o \ + board-n800-usb.o \ + board-n800-dsp.o \ + board-n800-camera.o +obj-$(CONFIG_MACH_NOKIA_N810) += board-n810.o +obj-$(CONFIG_MACH_NOKIA_RX51) += board-rx51.o \ + board-n800-flash.o \ + board-rx51-flash.o \ + board-rx51-sdram.o \ + board-rx51-video.o \ + board-rx51-peripherals.o \ mmc-twl4030.o + +obj-$(CONFIG_MACH_OVERO) += board-overo.o \ + mmc-twl4030.o \ + twl4030-generic-scripts.o obj-$(CONFIG_MACH_OMAP3_PANDORA) += board-omap3pandora.o \ mmc-twl4030.o -obj-$(CONFIG_MACH_OMAP_3430SDP) += board-3430sdp.o \ - mmc-twl4030.o -obj-$(CONFIG_MACH_NOKIA_RX51) += board-rx51.o \ - board-rx51-peripherals.o \ # Platform specific device init code -ifeq ($(CONFIG_USB_MUSB_SOC),y) -obj-y += usb-musb.o +obj-$(CONFIG_USB_MUSB_SOC) += usb-musb.o +obj-$(CONFIG_MACH_OMAP2_TUSB6010) += usb-tusb6010.o + +ifneq ($(CONFIG_USB_EHCI_HCD),) + obj-y += usb-ehci.o endif + + diff --git a/arch/arm/mach-omap2/board-2430sdp-flash.c b/arch/arm/mach-omap2/board-2430sdp-flash.c new file mode 100644 index 00000000000..57d3b553715 --- /dev/null +++ b/arch/arm/mach-omap2/board-2430sdp-flash.c @@ -0,0 +1,185 @@ +/* + * linux/arch/arm/mach-omap2/board-2430sdp-flash.c + * + * Copyright (C) 2007 MontaVista Software, Inc. + * Author: Kevin Hilman + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define ONENAND_MAP 0x20000000 +#define GPMC_OFF_CONFIG1_0 0x60 + +enum fstype { + NAND = 0, + NOR, + ONENAND, + UNKNOWN = -1 +}; + +static enum fstype flash_type = NAND; + +static struct mtd_partition nand_partitions[] = { + { + .name = "X-Loader", + .offset = 0, + .size = 4*(64*2048), /* 0-3 blks reserved. + Mandated by ROM code */ + .mask_flags = MTD_WRITEABLE /* force read-only */ + }, + { + .name = "U-Boot", + .offset = MTDPART_OFS_APPEND, + .size = 4*(64*2048), + .mask_flags = MTD_WRITEABLE /* force read-only */ + }, + { + .name = "U-Boot Environment", + .offset = MTDPART_OFS_APPEND, + .size = 2*(64*2048), + }, + { + .name = "Kernel", + .offset = MTDPART_OFS_APPEND, + .size = 32*(64*2048), /* 4*1M */ + }, + { + .name = "File System", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + }, +}; +static struct omap_nand_platform_data sdp_nand_data = { + .parts = nand_partitions, + .nr_parts = ARRAY_SIZE(nand_partitions), + .dma_channel = -1, /* disable DMA in OMAP OneNAND driver */ +}; + +static struct platform_device sdp_nand_device = { + .name = "omap2-nand", + .id = -1, + .dev = { + .platform_data = &sdp_nand_data, + }, +}; + +static struct mtd_partition onenand_partitions[] = { + { + .name = "(OneNAND)X-Loader", + .offset = 0, + .size = 4*(64*2048), /* 0-3 blks reserved. + Mandated by ROM code */ + .mask_flags = MTD_WRITEABLE /* force read-only */ + }, + { + .name = "(OneNAND)U-Boot", + .offset = MTDPART_OFS_APPEND, + .size = 2*(64*2048), + .mask_flags = MTD_WRITEABLE /* force read-only */ + }, + { + .name = "(OneNAND)U-Boot Environment", + .offset = MTDPART_OFS_APPEND, + .size = 1*(64*2048), + }, + { + .name = "(OneNAND)Kernel", + .offset = MTDPART_OFS_APPEND, + .size = 4*(64*2048), + }, + { + .name = "(OneNAND)File System", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct omap_onenand_platform_data sdp_onenand_data = { + .parts = onenand_partitions, + .nr_parts = ARRAY_SIZE(onenand_partitions), + .dma_channel = -1, /* disable DMA in OMAP OneNAND driver */ +}; + +static struct platform_device sdp_onenand_device = { + .name = "omap2-onenand", + .id = -1, + .dev = { + .platform_data = &sdp_onenand_data, + }, +}; + +void __init sdp2430_flash_init(void) +{ + void __iomem *gpmc_base_add, *gpmc_cs_base_add; + unsigned char cs = 0; + + gpmc_base_add = (__force void __iomem *)OMAP243X_GPMC_VIRT; + while (cs < GPMC_CS_NUM) { + int ret = 0; + + /* Each GPMC set for a single CS is at offset 0x30 */ + gpmc_cs_base_add = (gpmc_base_add + GPMC_OFF_CONFIG1_0 + + (cs*0x30)); + + /* xloader/Uboot would have programmed the NAND/oneNAND + * base address for us This is a ugly hack. The proper + * way of doing this is to pass the setup of u-boot up + * to kernel using kernel params - something on the + * lines of machineID. Check if Nand/oneNAND is + * configured */ + ret = __raw_readl(gpmc_cs_base_add + GPMC_CS_CONFIG1); + if ((ret & 0xC00) == (0x800)) { + /* Found it!! */ + printk(KERN_INFO "NAND: Found NAND on CS %d \n", cs); + flash_type = NAND; + break; + } + ret = __raw_readl(gpmc_cs_base_add + GPMC_CS_CONFIG7); + if ((ret & 0x3F) == (ONENAND_MAP >> 24)) { + /* Found it!! */ + flash_type = ONENAND; + break; + } + cs++; + } + if (cs >= GPMC_CS_NUM) { + printk(KERN_INFO "MTD: Unable to find MTD configuration in " + "GPMC - not registering.\n"); + return; + } + + if (flash_type == NAND) { + sdp_nand_data.cs = cs; + sdp_nand_data.gpmc_cs_baseaddr = gpmc_cs_base_add; + sdp_nand_data.gpmc_baseaddr = gpmc_base_add; + + if (platform_device_register(&sdp_nand_device) < 0) { + printk(KERN_ERR "Unable to register NAND device\n"); + return; + } + } + + if (flash_type == ONENAND) { + sdp_onenand_data.cs = cs; + + if (platform_device_register(&sdp_onenand_device) < 0) { + printk(KERN_ERR "Unable to register OneNAND device\n"); + return; + } + } +} diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index 22143651037..899e6e3402d 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c @@ -19,10 +19,13 @@ #include #include #include +#include #include #include #include #include +#include +#include #include #include @@ -33,18 +36,30 @@ #include #include #include +#include #include #include -#include +#include + #include "mmc-twl4030.h" #define SDP2430_CS0_BASE 0x04000000 #define SDP2430_FLASH_CS 0 #define SDP2430_SMC91X_CS 5 - #define SDP2430_ETHR_GPIO_IRQ 149 +/* GPIO used for TSC2046 (touchscreen) + * + * Also note that the tsc2046 is the same silicon as the ads7846, so + * that driver is used for the touchscreen. */ +#define TS_GPIO 24 + +#define TWL4030_MSECURE_GPIO 118 +#define SECONDARY_LCD_GPIO 147 + +extern void sdp2430_flash_init(void); + static struct mtd_partition sdp2430_partitions[] = { /* bootloader (U-Boot, etc) in first sector */ { @@ -112,6 +127,11 @@ static struct resource sdp2430_smc91x_resources[] = { }, }; +static struct platform_device sdp2430_lcd_device = { + .name = "sdp2430_lcd", + .id = -1, +}; + static struct platform_device sdp2430_smc91x_device = { .name = "smc91x", .id = -1, @@ -119,9 +139,125 @@ static struct platform_device sdp2430_smc91x_device = { .resource = sdp2430_smc91x_resources, }; +/* + * Key mapping for 2430 SDP board + */ + +static int sdp2430_keymap[] = { + KEY(0, 0, KEY_LEFT), + KEY(0, 1, KEY_RIGHT), + KEY(0, 2, KEY_A), + KEY(0, 3, KEY_B), + KEY(0, 4, KEY_C), + KEY(1, 0, KEY_DOWN), + KEY(1, 1, KEY_UP), + KEY(1, 2, KEY_E), + KEY(1, 3, KEY_F), + KEY(1, 4, KEY_G), + KEY(2, 0, KEY_ENTER), + KEY(2, 1, KEY_I), + KEY(2, 2, KEY_J), + KEY(2, 3, KEY_K), + KEY(2, 4, KEY_3), + KEY(3, 0, KEY_M), + KEY(3, 1, KEY_N), + KEY(3, 2, KEY_O), + KEY(3, 3, KEY_P), + KEY(3, 4, KEY_Q), + KEY(4, 0, KEY_R), + KEY(4, 1, KEY_4), + KEY(4, 2, KEY_T), + KEY(4, 3, KEY_U), + KEY(4, 4, KEY_D), + KEY(5, 0, KEY_V), + KEY(5, 1, KEY_W), + KEY(5, 2, KEY_L), + KEY(5, 3, KEY_S), + KEY(5, 4, KEY_H), + 0 +}; + +static struct twl4030_keypad_data sdp2430_kp_data = { + .rows = 5, + .cols = 6, + .keymap = sdp2430_keymap, + .keymapsize = ARRAY_SIZE(sdp2430_keymap), + .rep = 1, +}; + +static int __init msecure_init(void) +{ + int ret = 0; + +#ifdef CONFIG_RTC_DRV_TWL4030 + ret = gpio_request(TWL4030_MSECURE_GPIO, "msecure"); + if (ret < 0) { + printk(KERN_ERR "msecure_init: can't reserve GPIO:%d !\n", + TWL4030_MSECURE_GPIO); + goto out; + } + /* + * TWL4030 will be in secure mode if msecure line from OMAP is low. + * Make msecure line high in order to change the TWL4030 RTC time + * and calender registers. + */ + gpio_direction_output(TWL4030_MSECURE_GPIO, 1); +out: +#endif + + return ret; +} + static struct platform_device *sdp2430_devices[] __initdata = { &sdp2430_smc91x_device, &sdp2430_flash_device, + &sdp2430_lcd_device, +}; + +static void ads7846_dev_init(void) +{ + if (gpio_request(TS_GPIO, "ads7846 irq") < 0) + printk(KERN_ERR "can't get ads746 pen down GPIO\n"); + + gpio_direction_input(TS_GPIO); + + omap_set_gpio_debounce(TS_GPIO, 1); + omap_set_gpio_debounce_time(TS_GPIO, 0xa); +} + +static int ads7846_get_pendown_state(void) +{ + return !gpio_get_value(TS_GPIO); +} + +static struct ads7846_platform_data tsc2046_config __initdata = { + .get_pendown_state = ads7846_get_pendown_state, + .keep_vref_on = 1, +}; + +static struct omap2_mcspi_device_config tsc2046_mcspi_config = { + .turbo_mode = 0, + .single_channel = 0, /* 0: slave, 1: master */ +}; + +static struct omap_lcd_config sdp2430_lcd_config __initdata = { + .ctrl_name = "internal", +}; + +static struct spi_board_info sdp2430_spi_board_info[] __initdata = { + [0] = { + /* + * TSC2046 operates at a max freqency of 2MHz, so + * operate slightly below at 1.5MHz + */ + .modalias = "ads7846", + .bus_num = 1, + .chip_select = 0, + .max_speed_hz = 1500000, + .controller_data = &tsc2046_mcspi_config, + .irq = OMAP_GPIO_IRQ(TS_GPIO), + .platform_data = &tsc2046_config, + }, }; static inline void __init sdp2430_init_smc91x(void) @@ -199,8 +335,16 @@ static struct omap_uart_config sdp2430_uart_config __initdata = { .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), }; -static struct omap_board_config_kernel sdp2430_config[] = { +static +struct omap_serial_console_config sdp2430_serial_console_config __initdata = { + .console_uart = 1, + .console_speed = 115200, +}; + +static struct omap_board_config_kernel sdp2430_config[] __initdata = { {OMAP_TAG_UART, &sdp2430_uart_config}, + {OMAP_TAG_LCD, &sdp2430_lcd_config}, + {OMAP_TAG_SERIAL_CONSOLE, &sdp2430_serial_console_config}, }; @@ -210,12 +354,23 @@ static struct twl4030_gpio_platform_data sdp2430_gpio_data = { .irq_end = TWL4030_GPIO_IRQ_END, }; +static struct twl4030_usb_data sdp2430_usb_data = { + .usb_mode = T2_USB_MODE_ULPI, +}; + +static struct twl4030_madc_platform_data sdp2430_madc_data = { + .irq_line = 1, +}; + static struct twl4030_platform_data sdp2430_twldata = { .irq_base = TWL4030_IRQ_BASE, .irq_end = TWL4030_IRQ_END, /* platform_data for children goes here */ .gpio = &sdp2430_gpio_data, + .madc = &sdp2430_madc_data, + .keypad = &sdp2430_kp_data, + .usb = &sdp2430_usb_data, }; static struct i2c_board_info __initdata sdp2430_i2c_boardinfo[] = { @@ -254,8 +409,19 @@ static void __init omap_2430sdp_init(void) omap_board_config = sdp2430_config; omap_board_config_size = ARRAY_SIZE(sdp2430_config); omap_serial_init(); - twl4030_mmc_init(mmc); + + msecure_init(); + + sdp2430_flash_init(); usb_musb_init(); + + spi_register_board_info(sdp2430_spi_board_info, + ARRAY_SIZE(sdp2430_spi_board_info)); + ads7846_dev_init(); + twl4030_mmc_init(mmc); + + /* turn off secondary LCD backlight */ + gpio_direction_output(SECONDARY_LCD_GPIO, 0); } static void __init omap_2430sdp_map_io(void) diff --git a/arch/arm/mach-omap2/board-3430sdp-flash.c b/arch/arm/mach-omap2/board-3430sdp-flash.c new file mode 100644 index 00000000000..f0e25a46417 --- /dev/null +++ b/arch/arm/mach-omap2/board-3430sdp-flash.c @@ -0,0 +1,290 @@ +/* + * linux/arch/arm/mach-omap2/board-3430sdp-flash.c + * + * Copyright (c) 2007 Texas Instruments + * + * Modified from mach-omap2/board-2430sdp-flash.c + * Author: Rohit Choraria + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define NAND_BLOCK_SIZE SZ_128K + +/* NAND */ +/* IMPORTANT NOTE ON MAPPING + * 3430SDP - 34XX + * ---------- + * NOR always on 0x04000000 for SDPV1 + * NOR always on 0x10000000 for SDPV2 + * MPDB always on 0x08000000 + * NAND always on 0x0C000000 + * OneNand Mapped to 0x20000000 + * Boot Mode(NAND/NOR). The other on CS1 + */ +#define FLASH_BASE_SDPV1 0x04000000 /* NOR flash (64 Meg aligned) */ +#define FLASH_BASE_SDPV2 0x10000000 /* NOR flash (256 Meg aligned) */ +#define DEBUG_BASE 0x08000000 /* debug board */ +#define NAND_BASE 0x0C000000 /* NAND flash */ +#define ONENAND_MAP 0x20000000 /* OneNand flash */ + +/* various memory sizes */ +#define FLASH_SIZE_SDPV1 SZ_64M +#define FLASH_SIZE_SDPV2 SZ_128M + +static struct mtd_partition sdp_nor_partitions[] = { + /* bootloader (U-Boot, etc) in first sector */ + { + .name = "Bootloader-NOR", + .offset = 0, + .size = SZ_256K, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, + /* bootloader params in the next sector */ + { + .name = "Params-NOR", + .offset = MTDPART_OFS_APPEND, + .size = SZ_256K, + .mask_flags = 0, + }, + /* kernel */ + { + .name = "Kernel-NOR", + .offset = MTDPART_OFS_APPEND, + .size = SZ_2M, + .mask_flags = 0 + }, + /* file system */ + { + .name = "Filesystem-NOR", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + .mask_flags = 0 + } +}; + +static struct flash_platform_data sdp_nor_data = { + .map_name = "cfi_probe", + .width = 2, + .parts = sdp_nor_partitions, + .nr_parts = ARRAY_SIZE(sdp_nor_partitions), +}; + +static struct resource sdp_nor_resource = { + .start = 0, + .end = 0, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device sdp_nor_device = { + .name = "omapflash", + .id = 0, + .dev = { + .platform_data = &sdp_nor_data, + }, + .num_resources = 1, + .resource = &sdp_nor_resource, +}; + +static int sdp_onenand_setup(void __iomem *, int freq); + +static struct mtd_partition sdp_onenand_partitions[] = { + { + .name = "X-Loader-OneNAND", + .offset = 0, + .size = 4 * (64 * 2048), + .mask_flags = MTD_WRITEABLE /* force read-only */ + }, + { + .name = "U-Boot-OneNAND", + .offset = MTDPART_OFS_APPEND, + .size = 2 * (64 * 2048), + .mask_flags = MTD_WRITEABLE /* force read-only */ + }, + { + .name = "U-Boot Environment-OneNAND", + .offset = MTDPART_OFS_APPEND, + .size = 1 * (64 * 2048), + }, + { + .name = "Kernel-OneNAND", + .offset = MTDPART_OFS_APPEND, + .size = 16 * (64 * 2048), + }, + { + .name = "File System-OneNAND", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct omap_onenand_platform_data sdp_onenand_data = { + .parts = sdp_onenand_partitions, + .nr_parts = ARRAY_SIZE(sdp_onenand_partitions), + .onenand_setup = sdp_onenand_setup, + .dma_channel = -1, /* disable DMA in OMAP OneNAND driver */ +}; + +static struct platform_device sdp_onenand_device = { + .name = "omap2-onenand", + .id = -1, + .dev = { + .platform_data = &sdp_onenand_data, + }, +}; + +/* + * sdp_onenand_setup - The function configures the onenand flash. + * @onenand_base: Onenand base address + * + * @return int: Currently always returning zero. + */ +static int sdp_onenand_setup(void __iomem *onenand_base, int freq) +{ + /* Onenand setup does nothing at present */ + return 0; +} + +static struct mtd_partition sdp_nand_partitions[] = { + /* All the partition sizes are listed in terms of NAND block size */ + { + .name = "X-Loader-NAND", + .offset = 0, + .size = 4 * NAND_BLOCK_SIZE, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, + { + .name = "U-Boot-NAND", + .offset = MTDPART_OFS_APPEND, /* Offset = 0x80000 */ + .size = 4 * NAND_BLOCK_SIZE, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, + { + .name = "Boot Env-NAND", + .offset = MTDPART_OFS_APPEND, /* Offset = 0x100000 */ + .size = 2 * NAND_BLOCK_SIZE, + }, + { + .name = "Kernel-NAND", + .offset = MTDPART_OFS_APPEND, /* Offset = 0x140000 */ + .size = 32 * NAND_BLOCK_SIZE, + }, + { + .name = "File System - NAND", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, /* Offset = 0x540000 */ + }, +}; + +static struct omap_nand_platform_data sdp_nand_data = { + .parts = sdp_nand_partitions, + .nr_parts = ARRAY_SIZE(sdp_nand_partitions), + .nand_setup = NULL, + .dma_channel = -1, /* disable DMA in OMAP NAND driver */ + .dev_ready = NULL, +}; + +static struct resource sdp_nand_resource = { + .flags = IORESOURCE_MEM, +}; + +static struct platform_device sdp_nand_device = { + .name = "omap2-nand", + .id = 0, + .dev = { + .platform_data = &sdp_nand_data, + }, + .num_resources = 1, + .resource = &sdp_nand_resource, +}; + + +/** + * sdp3430_flash_init - Identify devices connected to GPMC and register. + * + * @return - void. + */ +void __init sdp3430_flash_init(void) +{ + u8 cs = 0; + u8 nandcs = GPMC_CS_NUM + 1; + u8 onenandcs = GPMC_CS_NUM + 1; + unsigned long gpmc_base_add; + + gpmc_base_add = OMAP34XX_GPMC_VIRT; + + /* Configure start address and size of NOR device */ + if (omap_rev() > OMAP3430_REV_ES1_0) { + sdp_nor_resource.start = FLASH_BASE_SDPV2; + sdp_nor_resource.end = FLASH_BASE_SDPV2 + + FLASH_SIZE_SDPV2 - 1; + } else { + sdp_nor_resource.start = FLASH_BASE_SDPV1; + sdp_nor_resource.end = FLASH_BASE_SDPV1 + + FLASH_SIZE_SDPV1 - 1; + } + + if (platform_device_register(&sdp_nor_device) < 0) + printk(KERN_ERR "Unable to register NOR device\n"); + + while (cs < GPMC_CS_NUM) { + u32 ret = 0; + ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + + /* + * xloader/Uboot would have programmed the NAND/oneNAND + * base address for us This is a ugly hack. The proper + * way of doing this is to pass the setup of u-boot up + * to kernel using kernel params - something on the + * lines of machineID. Check if oneNAND is configured + */ + if ((ret & 0xC00) == 0x800) { + /* Found it!! */ + if (nandcs > GPMC_CS_NUM) + nandcs = cs; + } else { + ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7); + if ((ret & 0x3F) == (ONENAND_MAP >> 24)) + onenandcs = cs; + } + cs++; + } + if ((nandcs > GPMC_CS_NUM) && (onenandcs > GPMC_CS_NUM)) { + printk(KERN_INFO "NAND/OneNAND: Unable to find configuration " + " in GPMC\n "); + return; + } + + if (nandcs < GPMC_CS_NUM) { + sdp_nand_data.cs = nandcs; + sdp_nand_data.gpmc_cs_baseaddr = (void *)(gpmc_base_add + + GPMC_CS0_BASE + nandcs*GPMC_CS_SIZE); + sdp_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add); + + if (platform_device_register(&sdp_nand_device) < 0) + printk(KERN_ERR "Unable to register NAND device\n"); + } + + if (onenandcs < GPMC_CS_NUM) { + sdp_onenand_data.cs = onenandcs; + if (platform_device_register(&sdp_onenand_device) < 0) + printk(KERN_ERR "Unable to register OneNAND device\n"); + } +} diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index ed927497212..03acac79adf 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -17,12 +17,12 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -38,12 +39,13 @@ #include #include -#include +#include "sdram-qimonda-hyb18m512160af-6.h" #include "mmc-twl4030.h" #define CONFIG_DISABLE_HFCLK 1 +#define SDP3430_ETHR_START DEBUG_BASE #define SDP3430_ETHR_GPIO_IRQ_SDPV1 29 #define SDP3430_ETHR_GPIO_IRQ_SDPV2 6 #define SDP3430_SMC91X_CS 3 @@ -54,8 +56,13 @@ #define ENABLE_VAUX3_DEDICATED 0x03 #define ENABLE_VAUX3_DEV_GRP 0x20 +#define ENABLE_VAUX3_DEDICATED 0x03 +#define ENABLE_VAUX3_DEV_GRP 0x20 + #define TWL4030_MSECURE_GPIO 22 +extern void sdp3430_flash_init(void); + static struct resource sdp3430_smc91x_resources[] = { [0] = { .flags = IORESOURCE_MEM, @@ -118,6 +125,42 @@ static struct twl4030_keypad_data sdp3430_kp_data = { static int ts_gpio; /* Needed for ads7846_get_pendown_state */ +static int __init msecure_init(void) +{ + int ret = 0; + +#ifdef CONFIG_RTC_DRV_TWL4030 + /* 3430ES2.0 doesn't have msecure/gpio-22 line connected to T2 */ + if (omap_type() == OMAP2_DEVICE_TYPE_GP && + omap_rev() < OMAP3430_REV_ES2_0) { + void __iomem *msecure_pad_config_reg = omap_ctrl_base_get() + + 0xA3C; + int mux_mask = 0x04; + u16 tmp; + + ret = gpio_request(TWL4030_MSECURE_GPIO, "msecure"); + if (ret < 0) { + printk(KERN_ERR "msecure_init: can't" + "reserve GPIO:%d !\n", TWL4030_MSECURE_GPIO); + goto out; + } + /* + * TWL4030 will be in secure mode if msecure line from OMAP + * is low. Make msecure line high in order to change the + * TWL4030 RTC time and calender registers. + */ + tmp = __raw_readw(msecure_pad_config_reg); + tmp &= 0xF8; /* To enable mux mode 03/04 = GPIO_RTC */ + tmp |= mux_mask;/* To enable mux mode 03/04 = GPIO_RTC */ + __raw_writew(tmp, msecure_pad_config_reg); + + gpio_direction_output(TWL4030_MSECURE_GPIO, 1); + } +out: +#endif + return ret; +} + /** * @brief ads7846_dev_init : Requests & sets GPIO line for pen-irq * @@ -141,9 +184,42 @@ static int ads7846_get_pendown_state(void) return !gpio_get_value(ts_gpio); } +/* + * This enable(1)/disable(0) the voltage for TS: uses twl4030 calls + */ +static int ads7846_vaux_control(int vaux_cntrl) +{ + int ret = 0; + + /* FIXME use regulator calls */ + +#ifdef CONFIG_TWL4030_CORE + /* check for return value of ldo_use: if success it returns 0 */ + if (vaux_cntrl == VAUX_ENABLE) { + if (ret != twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, + ENABLE_VAUX3_DEDICATED, TWL4030_VAUX3_DEDICATED)) + return -EIO; + if (ret != twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, + ENABLE_VAUX3_DEV_GRP, TWL4030_VAUX3_DEV_GRP)) + return -EIO; + } else if (vaux_cntrl == VAUX_DISABLE) { + if (ret != twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, + 0x00, TWL4030_VAUX3_DEDICATED)) + return -EIO; + if (ret != twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, + 0x00, TWL4030_VAUX3_DEV_GRP)) + return -EIO; + } +#else + ret = -EIO; +#endif + return ret; +} + static struct ads7846_platform_data tsc2046_config __initdata = { .get_pendown_state = ads7846_get_pendown_state, .keep_vref_on = 1, + .vaux_control = ads7846_vaux_control, }; @@ -222,7 +298,7 @@ static inline void __init sdp3430_init_smc91x(void) static void __init omap_3430sdp_init_irq(void) { - omap2_init_common_hw(NULL); + omap2_init_common_hw(hyb18m512160af6_sdrc_params); omap_init_irq(); omap_gpio_init(); sdp3430_init_smc91x(); @@ -331,6 +407,87 @@ static struct twl4030_madc_platform_data sdp3430_madc_data = { .irq_line = 1, }; + +static struct twl4030_ins __initdata sleep_on_seq[] = { +/* + * Turn off VDD1 and VDD2. + */ + {MSG_SINGULAR(DEV_GRP_P1, 0xf, RES_STATE_OFF), 4}, + {MSG_SINGULAR(DEV_GRP_P1, 0x10, RES_STATE_OFF), 2}, +#ifdef CONFIG_DISABLE_HFCLK +/* + * And also turn off the OMAP3 PLLs and the sysclk output. + */ + {MSG_SINGULAR(DEV_GRP_P1, 0x7, RES_STATE_OFF), 3}, + {MSG_SINGULAR(DEV_GRP_P1, 0x19, RES_STATE_OFF), 3}, +#endif +}; + +static struct twl4030_script sleep_on_script __initdata = { + .script = sleep_on_seq, + .size = ARRAY_SIZE(sleep_on_seq), + .flags = TRITON_SLEEP_SCRIPT, +}; + +static struct twl4030_ins wakeup_seq[] __initdata = { +#ifndef CONFIG_DISABLE_HFCLK +/* + * Wakeup VDD1 and VDD2. + */ + {MSG_SINGULAR(DEV_GRP_P1, 0xf, RES_STATE_ACTIVE), 4}, + {MSG_SINGULAR(DEV_GRP_P1, 0x10, RES_STATE_ACTIVE), 2}, +#else +/* + * Reenable the OMAP3 PLLs. + * Wakeup VDD1 and VDD2. + * Reenable sysclk output. + */ + {MSG_SINGULAR(DEV_GRP_P1, 0x7, RES_STATE_ACTIVE), 0x30}, + {MSG_SINGULAR(DEV_GRP_P1, 0xf, RES_STATE_ACTIVE), 0x30}, + {MSG_SINGULAR(DEV_GRP_P1, 0x10, RES_STATE_ACTIVE), 0x37}, + {MSG_SINGULAR(DEV_GRP_P1, 0x19, RES_STATE_ACTIVE), 3}, +#endif /* #ifndef CONFIG_DISABLE_HFCLK */ +}; + +static struct twl4030_script wakeup_script __initdata = { + .script = wakeup_seq, + .size = ARRAY_SIZE(wakeup_seq), + .flags = TRITON_WAKEUP12_SCRIPT | TRITON_WAKEUP3_SCRIPT, +}; + +static struct twl4030_ins wrst_seq[] __initdata = { +/* + * Reset twl4030. + * Reset VDD1 regulator. + * Reset VDD2 regulator. + * Reset VPLL1 regulator. + * Enable sysclk output. + * Reenable twl4030. + */ + {MSG_SINGULAR(DEV_GRP_NULL, 0x1b, RES_STATE_OFF), 2}, + {MSG_SINGULAR(DEV_GRP_P1, 0xf, RES_STATE_WRST), 15}, + {MSG_SINGULAR(DEV_GRP_P1, 0x10, RES_STATE_WRST), 15}, + {MSG_SINGULAR(DEV_GRP_P1, 0x7, RES_STATE_WRST), 0x60}, + {MSG_SINGULAR(DEV_GRP_P1, 0x19, RES_STATE_ACTIVE), 2}, + {MSG_SINGULAR(DEV_GRP_NULL, 0x1b, RES_STATE_ACTIVE), 2}, +}; +static struct twl4030_script wrst_script __initdata = { + .script = wrst_seq, + .size = ARRAY_SIZE(wakeup_seq), + .flags = TRITON_WRST_SCRIPT, +}; + +static struct twl4030_script *twl4030_scripts[] __initdata = { + &sleep_on_script, + &wakeup_script, + &wrst_script, +}; + +static struct twl4030_power_data sdp3430_t2scripts_data __initdata = { + .scripts = twl4030_scripts, + .size = ARRAY_SIZE(twl4030_scripts), +}; + /* * Apply all the fixed voltages since most versions of U-Boot * don't bother with that initialization. @@ -472,6 +629,7 @@ static struct twl4030_platform_data sdp3430_twldata = { .gpio = &sdp3430_gpio_data, .madc = &sdp3430_madc_data, .keypad = &sdp3430_kp_data, + .power = &sdp3430_t2scripts_data, .usb = &sdp3430_usb_data, .vaux1 = &sdp3430_vaux1, @@ -520,8 +678,11 @@ static void __init omap_3430sdp_init(void) spi_register_board_info(sdp3430_spi_board_info, ARRAY_SIZE(sdp3430_spi_board_info)); ads7846_dev_init(); + sdp3430_flash_init(); + msecure_init(); omap_serial_init(); usb_musb_init(); + usb_ehci_init(); } static void __init omap_3430sdp_map_io(void) diff --git a/arch/arm/mach-omap2/board-apollon-keys.c b/arch/arm/mach-omap2/board-apollon-keys.c new file mode 100644 index 00000000000..10329c0ae6a --- /dev/null +++ b/arch/arm/mach-omap2/board-apollon-keys.c @@ -0,0 +1,103 @@ +/* + * linux/arch/arm/mach-omap2/board-apollon-keys.c + * + * Copyright (C) 2007 Samsung Electronics + * Author: Kyungmin Park + * + * 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. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#define SW_ENTER_GPIO16 16 +#define SW_UP_GPIO17 17 +#define SW_DOWN_GPIO58 58 +#define SW_LEFT_GPIO95 95 +#define SW_RIGHT_GPIO96 96 +#define SW_ESC_GPIO97 97 + +extern int apollon_plus(void); + +static struct gpio_keys_button apollon_gpio_keys_buttons[] = { + [0] = { + .code = KEY_ENTER, + .gpio = SW_ENTER_GPIO16, + .desc = "enter sw", + }, + [1] = { + .code = KEY_UP, + .gpio = SW_UP_GPIO17, + .desc = "up sw", + }, + [2] = { + .code = KEY_DOWN, + .gpio = SW_DOWN_GPIO58, + .desc = "down sw", + }, + [3] = { + .code = KEY_LEFT, + .gpio = SW_LEFT_GPIO95, + .desc = "left sw", + }, + [4] = { + .code = KEY_RIGHT, + .gpio = SW_RIGHT_GPIO96, + .desc = "right sw", + }, + [5] = { + .code = KEY_ESC, + .gpio = SW_ESC_GPIO97, + .desc = "esc sw", + }, +}; + +static struct gpio_keys_platform_data apollon_gpio_keys = { + .buttons = apollon_gpio_keys_buttons, + .nbuttons = ARRAY_SIZE(apollon_gpio_keys_buttons), +}; + +static struct platform_device apollon_gpio_keys_device = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &apollon_gpio_keys, + }, +}; + +static void __init apollon_sw_init(void) +{ + /* Enter SW - Y11 */ + omap_cfg_reg(Y11_242X_GPIO16); + /* Up SW - AA12 */ + omap_cfg_reg(AA12_242X_GPIO17); + /* Down SW - AA8 */ + omap_cfg_reg(AA8_242X_GPIO58); + + if (apollon_plus()) { + /* Left SW - P18 */ + omap_cfg_reg(P18_24XX_GPIO95); + /* Right SW - M18 */ + omap_cfg_reg(M18_24XX_GPIO96); + /* Esc SW - L14 */ + omap_cfg_reg(L14_24XX_GPIO97); + } else + apollon_gpio_keys.nbuttons = 3; +} + +static int __init omap_apollon_keys_init(void) +{ + apollon_sw_init(); + + return platform_device_register(&apollon_gpio_keys_device); +} + +arch_initcall(omap_apollon_keys_init); diff --git a/arch/arm/mach-omap2/board-apollon-mmc.c b/arch/arm/mach-omap2/board-apollon-mmc.c new file mode 100644 index 00000000000..3197741ec47 --- /dev/null +++ b/arch/arm/mach-omap2/board-apollon-mmc.c @@ -0,0 +1,101 @@ +/* + * linux/arch/arm/mach-omap2/board-apollon-mmc.c + * + * Copyright (C) 2005-2007 Samsung Electronics + * Author: Kyungmin Park + * + * 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. + */ + +#include +#include + +#include +#include + +#ifdef CONFIG_MMC_OMAP + +static struct device *mmc_device; + +static int apollon_mmc_set_power(struct device *dev, int slot, int power_on, + int vdd) +{ +#ifdef CONFIG_MMC_DEBUG + dev_dbg(dev, "Set slot %d power: %s (vdd %d)\n", slot + 1, + power_on ? "on" : "off", vdd); +#endif + if (slot != 0) { + dev_err(dev, "No such slot %d\n", slot + 1); + return -ENODEV; + } + + return 0; +} + +static int apollon_mmc_set_bus_mode(struct device *dev, int slot, int bus_mode) +{ +#ifdef CONFIG_MMC_DEBUG + dev_dbg(dev, "Set slot %d bus_mode %s\n", slot + 1, + bus_mode == MMC_BUSMODE_OPENDRAIN ? "open-drain" : "push-pull"); +#endif + if (slot != 0) { + dev_err(dev, "No such slot %d\n", slot + 1); + return -ENODEV; + } + + return 0; +} + +static int apollon_mmc_late_init(struct device *dev) +{ + mmc_device = dev; + + return 0; +} + +static void apollon_mmc_cleanup(struct device *dev) +{ +} + +/* + * Note: If you want to detect card feature, please assign GPIO 37 + */ +static struct omap_mmc_platform_data mmc1_data = { + .nr_slots = 1, + .init = apollon_mmc_late_init, + .cleanup = apollon_mmc_cleanup, + .dma_mask = 0xffffffff, + .slots[0] = { + .wires = 4, + + /* + * Use internal loop-back in MMC/SDIO Module Input Clock + * selection + */ + .internal_clock = 1, + + .set_power = apollon_mmc_set_power, + .set_bus_mode = apollon_mmc_set_bus_mode, + .ocr_mask = MMC_VDD_30_31 | MMC_VDD_31_32 | + MMC_VDD_32_33 | MMC_VDD_33_34, + .name = "mmcblk", + }, +}; + +static struct omap_mmc_platform_data *mmc_data[OMAP24XX_NR_MMC]; + +void __init apollon_mmc_init(void) +{ + mmc_data[0] = &mmc1_data; + omap2_init_mmc(mmc_data, OMAP24XX_NR_MMC); +} + +#else /* !CONFIG_MMC_OMAP */ + +void __init apollon_mmc_init(void) +{ +} + +#endif /* CONFIG_MMC_OMAP */ diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c index 06dfba888b0..936cb49bdd0 100644 --- a/arch/arm/mach-omap2/board-apollon.c +++ b/arch/arm/mach-omap2/board-apollon.c @@ -1,10 +1,10 @@ /* * linux/arch/arm/mach-omap2/board-apollon.c * - * Copyright (C) 2005,2006 Samsung Electronics + * Copyright (C) 2005-2008 Samsung Electronics * Author: Kyungmin Park * - * Modified from mach-omap/omap2/board-h4.c + * Modified from mach-omap2/board-h4.c * * Code for apollon OMAP2 board. Should work on many OMAP2 systems where * the bootloader passes the board-specific data to the kernel. @@ -22,11 +22,16 @@ #include #include #include +#include +#include #include #include #include #include +#include +#include +#include #include #include #include @@ -39,20 +44,30 @@ #include #include #include -#include /* LED & Switch macros */ #define LED0_GPIO13 13 #define LED1_GPIO14 14 #define LED2_GPIO15 15 -#define SW_ENTER_GPIO16 16 -#define SW_UP_GPIO17 17 -#define SW_DOWN_GPIO58 58 +#define LED3_GPIO92 92 +#define LED4_GPIO93 93 #define APOLLON_FLASH_CS 0 #define APOLLON_ETH_CS 1 +#define APOLLON_NOR_CS 3 #define APOLLON_ETHR_GPIO_IRQ 74 +#define APOLLON_ONENAND_CS2_ADDRESS (0x00000e40 | (0x10000000 >> 24)) +#define APOLLON_EXT_CS3_ADDRESS (0x00000c40 | (0x18000000 >> 24)) + +extern apollon_mmc_init(void); + +int apollon_plus(void) +{ + /* The apollon plus has IDCODE revision 5 */ + return omap_rev() & 0xc0; +} + static struct mtd_partition apollon_partitions[] = { { .name = "X-Loader + U-Boot", @@ -108,6 +123,63 @@ static struct platform_device apollon_onenand_device = { .resource = apollon_flash_resource, }; +static struct mtd_partition apollon_nor_partitions[] = { + { + .name = "U-Boot", + .offset = 0, + .size = SZ_128K, + .mask_flags = MTD_WRITEABLE, + }, + { + .name = "params", + .offset = MTDPART_OFS_APPEND, + .size = SZ_128K, + }, + { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = SZ_2M, + }, + { + .name = "rootfs", + .offset = MTDPART_OFS_APPEND, + .size = SZ_4M - SZ_256K, + }, + { + .name = "application", + .offset = MTDPART_OFS_APPEND, + .size = SZ_8M + SZ_2M, + }, + { + .name = "reserved", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct flash_platform_data apollon_nor_data = { + .map_name = "cfi_probe", + .width = 2, + .parts = apollon_nor_partitions, + .nr_parts = ARRAY_SIZE(apollon_nor_partitions), +}; + +static struct resource apollon_nor_resource[] = { + [0] = { + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device apollon_nor_device = { + .name = "omapflash", + .id = -1, + .dev = { + .platform_data = &apollon_nor_data, + }, + .num_resources = ARRAY_SIZE(apollon_nor_resource), + .resource = apollon_nor_resource, +}; + static void __init apollon_flash_init(void) { unsigned long base; @@ -118,6 +190,13 @@ static void __init apollon_flash_init(void) } apollon_flash_resource[0].start = base; apollon_flash_resource[0].end = base + SZ_128K - 1; + + if (gpmc_cs_request(APOLLON_NOR_CS, SZ_32M, &base) < 0) { + printk(KERN_ERR "Cannot request NOR GPMC CS\n"); + return; + } + apollon_nor_resource[0].start = base; + apollon_nor_resource[0].end = base + SZ_32M - 1; } static struct resource apollon_smc91x_resources[] = { @@ -143,34 +222,37 @@ static struct platform_device apollon_lcd_device = { .id = -1, }; -static struct omap_led_config apollon_led_config[] = { +static struct gpio_led apollon_led_config[] = { { - .cdev = { - .name = "apollon:led0", - }, - .gpio = LED0_GPIO13, + .name = "d2", + .gpio = LED0_GPIO13, + .default_trigger = "heartbeat", }, { - .cdev = { - .name = "apollon:led1", - }, - .gpio = LED1_GPIO14, + .name = "d3", + .gpio = LED1_GPIO14, }, { - .cdev = { - .name = "apollon:led2", - }, - .gpio = LED2_GPIO15, + .name = "d4", + .gpio = LED2_GPIO15, + }, + { + .name = "d5", + .gpio = LED3_GPIO92, + }, + { + .name = "d6", + .gpio = LED4_GPIO93, }, }; -static struct omap_led_platform_data apollon_led_data = { - .nr_leds = ARRAY_SIZE(apollon_led_config), +static struct gpio_led_platform_data apollon_led_data = { + .num_leds = ARRAY_SIZE(apollon_led_config), .leds = apollon_led_config, }; static struct platform_device apollon_led_device = { - .name = "omap-led", + .name = "leds-gpio", .id = -1, .dev = { .platform_data = &apollon_led_data, @@ -179,6 +261,7 @@ static struct platform_device apollon_led_device = { static struct platform_device *apollon_devices[] __initdata = { &apollon_onenand_device, + &apollon_nor_device, &apollon_smc91x_device, &apollon_lcd_device, &apollon_led_device, @@ -187,7 +270,6 @@ static struct platform_device *apollon_devices[] __initdata = { static inline void __init apollon_init_smc91x(void) { unsigned long base; - unsigned int rate; struct clk *gpmc_fck; int eth_cs; @@ -226,7 +308,7 @@ static inline void __init apollon_init_smc91x(void) gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000003C2); } - if (gpmc_cs_request(APOLLON_ETH_CS, SZ_16M, &base) < 0) { + if (gpmc_cs_request(eth_cs, SZ_16M, &base) < 0) { printk(KERN_ERR "Failed to request GPMC CS for smc91x\n"); goto out; } @@ -238,7 +320,7 @@ static inline void __init apollon_init_smc91x(void) if (gpio_request(APOLLON_ETHR_GPIO_IRQ, "SMC91x irq") < 0) { printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n", APOLLON_ETHR_GPIO_IRQ); - gpmc_cs_free(APOLLON_ETH_CS); + gpmc_cs_free(eth_cs); goto out; } gpio_direction_input(APOLLON_ETHR_GPIO_IRQ); @@ -256,6 +338,24 @@ static void __init omap_apollon_init_irq(void) apollon_init_smc91x(); } +static struct tsc210x_config tsc_platform_data = { + .use_internal = 1, + .monitor = TSC_TEMP, + .mclk = "sys_clkout", +}; + +static struct spi_board_info apollon_spi_board_info[] = { + [0] = { + .modalias = "tsc2101", + .irq = OMAP_GPIO_IRQ(85), + .bus_num = 1, + .chip_select = 0, + .mode = SPI_MODE_1, + .max_speed_hz = 6000000, + .platform_data = &tsc_platform_data, + }, +}; + static struct omap_uart_config apollon_uart_config __initdata = { .enabled_uarts = (1 << 0) | (0 << 1) | (0 << 2), }; @@ -271,7 +371,7 @@ static struct omap_lcd_config apollon_lcd_config __initdata = { .ctrl_name = "internal", }; -static struct omap_board_config_kernel apollon_config[] = { +static struct omap_board_config_kernel apollon_config[] __initdata = { { OMAP_TAG_UART, &apollon_uart_config }, { OMAP_TAG_LCD, &apollon_lcd_config }, }; @@ -280,16 +380,18 @@ static void __init apollon_led_init(void) { /* LED0 - AA10 */ omap_cfg_reg(AA10_242X_GPIO13); - gpio_request(LED0_GPIO13, "LED0"); - gpio_direction_output(LED0_GPIO13, 0); /* LED1 - AA6 */ omap_cfg_reg(AA6_242X_GPIO14); - gpio_request(LED1_GPIO14, "LED1"); - gpio_direction_output(LED1_GPIO14, 0); /* LED2 - AA4 */ omap_cfg_reg(AA4_242X_GPIO15); - gpio_request(LED2_GPIO15, "LED2"); - gpio_direction_output(LED2_GPIO15, 0); + + if (apollon_plus()) { + /* LED3 - M15 */ + omap_cfg_reg(M15_24XX_GPIO92); + /* LED4 - P20 */ + omap_cfg_reg(P20_24XX_GPIO93); + } else + apollon_led_data.num_leds = 3; } static void __init apollon_usb_init(void) @@ -302,21 +404,101 @@ static void __init apollon_usb_init(void) omap_usb_init(&apollon_usb_config); } -static void __init omap_apollon_init(void) +static void __init apollon_tsc_init(void) +{ + /* TSC2101 */ + omap_cfg_reg(N15_24XX_GPIO85); + gpio_request(85, "tsc2101 irq"); + gpio_direction_input(85); + + omap_cfg_reg(W14_24XX_SYS_CLKOUT); /* mclk */ +} + +static void __init apollon_cs_init(void) { - u32 v; + unsigned long base; + unsigned int rate; + struct clk *l3ck; + u32 value; + int cs, sync = 0; + + l3ck = clk_get(NULL, "core_l3_ck"); + if (IS_ERR(l3ck)) + rate = 100000000; + else + rate = clk_get_rate(l3ck); + + /* CS2: OneNAND */ + cs = 2; + value = gpmc_cs_read_reg(0, GPMC_CS_CONFIG1); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, value); + value = gpmc_cs_read_reg(0, GPMC_CS_CONFIG2); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, value); + value = gpmc_cs_read_reg(0, GPMC_CS_CONFIG3); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, value); + value = gpmc_cs_read_reg(0, GPMC_CS_CONFIG4); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, value); + value = gpmc_cs_read_reg(0, GPMC_CS_CONFIG5); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG5, value); + value = gpmc_cs_read_reg(0, GPMC_CS_CONFIG6); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG6, value); + + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, APOLLON_ONENAND_CS2_ADDRESS); + + /* CS3: External NOR */ + cs = APOLLON_NOR_CS; + if (rate >= 160000000) { + sync = 1; + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, 0xe5011211); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, 0x00090b01); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, 0x00020201); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, 0x09030b03); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG5, 0x010a0a0c); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG6, 0x00000000); + } else if (rate >= 130000000) { + /* Not yet know ... Use the async values */ + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, 0x00021201); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, 0x00121601); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, 0x00040401); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, 0x12061605); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG5, 0x01151317); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG6, 0x00000000); + } else {/* rate = 100000000 */ + sync = 1; + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, 0xe1001202); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, 0x00151501); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, 0x00050501); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, 0x0e070e07); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG5, 0x01131F1F); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG6, 0x00000000); + } + + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, APOLLON_EXT_CS3_ADDRESS); + + if (gpmc_cs_request(cs, SZ_32M, &base) < 0) { + printk(KERN_ERR "Failed to request GPMC CS for external\n"); + return; + } + /* Synchronous mode */ + if (sync) { + void __iomem *addr = ioremap(base, SZ_32M); + writew(0xaa, addr + 0xaaa); + writew(0x55, addr + 0x554); + writew(0xc0, addr + 0x24aaa); + iounmap(addr); + } + + gpmc_cs_free(cs); +} + +static void __init omap_apollon_init(void) +{ + apollon_cs_init(); apollon_led_init(); apollon_flash_init(); apollon_usb_init(); - - /* REVISIT: where's the correct place */ - omap_cfg_reg(W19_24XX_SYS_NIRQ); - - /* Use Interal loop-back in MMC/SDIO Module Input Clock selection */ - v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); - v |= (1 << 24); - omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0); + apollon_tsc_init(); /* * Make sure the serial ports are muxed on at this point. @@ -327,6 +509,13 @@ static void __init omap_apollon_init(void) omap_board_config = apollon_config; omap_board_config_size = ARRAY_SIZE(apollon_config); omap_serial_init(); + omap_register_i2c_bus(1, 100, NULL, 0); + omap_register_i2c_bus(2, 100, NULL, 0); + + spi_register_board_info(apollon_spi_board_info, + ARRAY_SIZE(apollon_spi_board_info)); + + apollon_mmc_init(); } static void __init omap_apollon_map_io(void) diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c index 3492162a65c..0e353b3611f 100644 --- a/arch/arm/mach-omap2/board-generic.c +++ b/arch/arm/mach-omap2/board-generic.c @@ -41,7 +41,7 @@ static struct omap_uart_config generic_uart_config __initdata = { .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), }; -static struct omap_board_config_kernel generic_config[] = { +static struct omap_board_config_kernel generic_config[] __initdata = { { OMAP_TAG_UART, &generic_uart_config }, }; @@ -50,6 +50,8 @@ static void __init omap_generic_init(void) omap_board_config = generic_config; omap_board_config_size = ARRAY_SIZE(generic_config); omap_serial_init(); + omap_register_i2c_bus(1, 100, NULL, 0); + omap_register_i2c_bus(2, 100, NULL, 0); } static void __init omap_generic_map_io(void) diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c index a0267a9ab46..cbca22a0199 100644 --- a/arch/arm/mach-omap2/board-h4.c +++ b/arch/arm/mach-omap2/board-h4.c @@ -18,12 +18,22 @@ #include #include #include -#include -#include #include #include #include #include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include #include #include @@ -32,15 +42,12 @@ #include #include -#include -#include #include #include #include #include #include #include -#include #include #include @@ -49,6 +56,47 @@ #define H4_ETHR_GPIO_IRQ 92 +/* FPGA on debug board has 32 GPIOs: 16 dedicated to leds, + * 8 outputs on a header, and 6 inputs from a DIP switch. + */ +#define H4_DEBUG_GPIO_BASE OMAP_MAX_GPIO_LINES +# define H4_DEBUG_GPIO_SW3_1 (H4_DEBUG_GPIO_BASE + 24) +# define H4_DEBUG_GPIO_SW3_2 (H4_DEBUG_GPIO_BASE + 25) +# define H4_DEBUG_GPIO_SW3_3 (H4_DEBUG_GPIO_BASE + 26) +# define H4_DEBUG_GPIO_SW3_4 (H4_DEBUG_GPIO_BASE + 27) +# define H4_DEBUG_GPIO_SW3_5 (H4_DEBUG_GPIO_BASE + 28) +# define H4_DEBUG_GPIO_SW3_8 (H4_DEBUG_GPIO_BASE + 29) + +/* H4 baseboard has 3 PCF8574 (8 bit) I2C GPIO expanders */ +#define H4_U191_GPIO_BASE (H4_DEBUG_GPIO_BASE + 32) +# define H4_GPIO_IRDA_FIRSEL (H4_U191_GPIO_BASE + 0) +# define H4_GPIO_MODEM_MOD_EN (H4_U191_GPIO_BASE + 1) +# define H4_GPIO_WLAN_MOD_EN (H4_U191_GPIO_BASE + 2) +# define H4_GPIO_CAM_MODULE_EN (H4_U191_GPIO_BASE + 3) +# define H4_GPIO_HANDSET_EN (H4_U191_GPIO_BASE + 4) +# define H4_GPIO_LCD_ENBKL (H4_U191_GPIO_BASE + 5) +# define H4_GPIO_AUDIO_ENVDD (H4_U191_GPIO_BASE + 6) +# define H4_GPIO_LCD_ENVDD (H4_U191_GPIO_BASE + 7) + +#define H4_U192_GPIO_BASE (H4_U191_GPIO_BASE + 8) +# define H4_GPIO_IRDA_AGPSn (H4_U192_GPIO_BASE + 0) +# define H4_GPIO_AGPS_PWREN (H4_U192_GPIO_BASE + 1) +# define H4_GPIO_AGPS_RSTn (H4_U192_GPIO_BASE + 2) +# define H4_GPIO_AGPS_SLEEP (H4_U192_GPIO_BASE + 3) +# define H4_GPIO_AGPS_PA_XMT (H4_U192_GPIO_BASE + 4) +# define H4_GPIO_MODEM_SPR2 (H4_U192_GPIO_BASE + 5) +# define H4_GPIO_MODEM_SPR1 (H4_U192_GPIO_BASE + 6) +# define H4_GPIO_BT_ACLK_ENn (H4_U192_GPIO_BASE + 7) + +#define H4_U193_GPIO_BASE (H4_U192_GPIO_BASE + 8) +# define H4_GPIO_SPR0 (H4_U193_GPIO_BASE + 0) +# define H4_GPIO_SPR1 (H4_U193_GPIO_BASE + 1) +# define H4_GPIO_WLAN_SHUTDOWN (H4_U193_GPIO_BASE + 2) +# define H4_GPIO_WLAN_RESET (H4_U193_GPIO_BASE + 3) +# define H4_GPIO_WLAN_CLK_ENn (H4_U193_GPIO_BASE + 4) + /* 5, 6 not connected */ +# define H4_GPIO_CAM_RST (H4_U193_GPIO_BASE + 7) + static unsigned int row_gpios[6] = { 88, 89, 124, 11, 6, 96 }; static unsigned int col_gpios[7] = { 90, 91, 100, 36, 12, 97, 98 }; @@ -138,31 +186,16 @@ static struct platform_device h4_flash_device = { .resource = &h4_flash_resource, }; -/* Select between the IrDA and aGPS module - */ +#if defined(CONFIG_OMAP_IR) || defined(CONFIG_OMAP_IR_MODULE) + +/* Select between the IrDA and aGPS module */ static int h4_select_irda(struct device *dev, int state) { - unsigned char expa; - int err = 0; - - if ((err = read_gpio_expa(&expa, 0x21))) { - printk(KERN_ERR "Error reading from I/O expander\n"); - return err; - } + /* U192.P0 = high for IRDA; else AGPS */ + gpio_set_value_cansleep(H4_GPIO_IRDA_AGPSn, state & IR_SEL); - /* 'P6' enable/disable IRDA_TX and IRDA_RX */ - if (state & IR_SEL) { /* IrDa */ - if ((err = write_gpio_expa(expa | 0x01, 0x21))) { - printk(KERN_ERR "Error writing to I/O expander\n"); - return err; - } - } else { - if ((err = write_gpio_expa(expa & ~0x01, 0x21))) { - printk(KERN_ERR "Error writing to I/O expander\n"); - return err; - } - } - return err; + /* NOTE: UART3 can also hook up to a DB9 or to GSM ... */ + return 0; } static void set_trans_mode(struct work_struct *work) @@ -170,22 +203,9 @@ static void set_trans_mode(struct work_struct *work) struct omap_irda_config *irda_config = container_of(work, struct omap_irda_config, gpio_expa.work); int mode = irda_config->mode; - unsigned char expa; - int err = 0; - - if ((err = read_gpio_expa(&expa, 0x20)) != 0) { - printk(KERN_ERR "Error reading from I/O expander\n"); - } - expa &= ~0x01; - - if (!(mode & IR_SIRMODE)) { /* MIR/FIR */ - expa |= 0x01; - } - - if ((err = write_gpio_expa(expa, 0x20)) != 0) { - printk(KERN_ERR "Error writing to I/O expander\n"); - } + /* U191.P0 = low for SIR; else MIR/FIR */ + gpio_set_value_cansleep(H4_GPIO_IRDA_FIRSEL, !(mode & IR_SIRMODE)); } static int h4_transceiver_mode(struct device *dev, int mode) @@ -199,6 +219,10 @@ static int h4_transceiver_mode(struct device *dev, int mode) return 0; } +#else +static int h4_select_irda(struct device *dev, int state) { return 0; } +static int h4_transceiver_mode(struct device *dev, int mode) { return 0; } +#endif static struct omap_irda_config h4_irda_data = { .transceiver_cap = IR_SIRMODE | IR_MIRMODE | IR_FIRMODE, @@ -269,6 +293,8 @@ static u32 get_sysboot_value(void) OMAP2_SYSBOOT_1_MASK | OMAP2_SYSBOOT_0_MASK)); } +/* FIXME: This function should be moved to some other file, gpmc.c? */ + /* H4-2420's always used muxed mode, H4-2422's always use non-muxed * * Note: OMAP-GIT doesn't correctly do is_cpu_omap2422 and is_cpu_omap2423 @@ -372,7 +398,11 @@ static void __init omap_h4_init_irq(void) } static struct omap_uart_config h4_uart_config __initdata = { +#ifdef CONFIG_MACH_OMAP2_H4_USB1 + .enabled_uarts = ((1 << 0) | (1 << 1)), +#else .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), +#endif }; static struct omap_lcd_config h4_lcd_config __initdata = { @@ -412,21 +442,309 @@ static struct omap_usb_config h4_usb_config __initdata = { #endif }; -static struct omap_board_config_kernel h4_config[] = { +/* ----------------------------------------------------------------------- */ + +static struct tsc210x_config tsc_platform_data = { + .use_internal = 1, + .monitor = TSC_VBAT | TSC_TEMP, + /* REVISIT temp calibration data -- board-specific; from EEPROM? */ + .mclk = "sys_clkout", +}; + +static struct spi_board_info h4_spi_board_info[] __initdata = { + { + .modalias = "tsc2101", + .bus_num = 1, + .chip_select = 0, + .mode = SPI_MODE_1, + .irq = OMAP_GPIO_IRQ(93), + .max_speed_hz = 16000000, + .platform_data = &tsc_platform_data, + }, + + /* nCS1 -- to lcd board, but unused + * nCS2 -- to WLAN/miniPCI + */ +}; + +/* ----------------------------------------------------------------------- */ + +static struct omap_board_config_kernel h4_config[] __initdata = { { OMAP_TAG_UART, &h4_uart_config }, { OMAP_TAG_LCD, &h4_lcd_config }, }; +#ifdef CONFIG_MACH_OMAP_H4_TUSB + +#include + +static struct musb_hdrc_platform_data tusb_data = { + .mode = MUSB_OTG, + .min_power = 25, /* x2 = 50 mA drawn from VBUS as peripheral */ + + /* 1.8V supplied by Menelaus, other voltages supplied by VBAT; + * so no switching. + */ +}; + +static void __init tusb_evm_setup(void) +{ + static char announce[] __initdata = + KERN_INFO "TUSB 6010 EVM\n"; + int irq; + unsigned dmachan = 0; + + /* There are at least 32 different combinations of boards that + * are loosely called "H4", with a 2420 ... different OMAP chip + * revisions (with pin mux changes for DMAREQ, GPMC errata, etc), + * modifications of the CPU board, mainboard, EVM, TUSB etc. + * Plus omap2422, omap2423, etc. + * + * So you might need to tweak this setup to make the TUSB EVM + * behave on your particular setup ... + */ + + /* Already set up: GPMC AD[0..15], CLK, nOE, nWE, nADV_ALE */ + omap_cfg_reg(E2_GPMC_NCS2); + omap_cfg_reg(L2_GPMC_NCS7); + omap_cfg_reg(M1_GPMC_WAIT2); + + switch ((omap_rev() >> 8) & 0x0f) { + case 0: /* ES 1.0 */ + case 1: /* ES 2.0 */ + /* Assume early board revision without optional ES2.0 + * rework to swap J15 & AA10 so DMAREQ0 works + */ + omap_cfg_reg(AA10_242X_GPIO13); + irq = 13; + /* omap_cfg_reg(J15_24XX_DMAREQ0); */ + break; + default: + /* Later Menelaus boards can support all 6 DMA request + * lines, at the price of boot flash A23-A26. + */ + omap_cfg_reg(J15_24XX_GPIO99); + irq = 99; + dmachan = (1 << 1) | (1 << 0); +#if !(defined(CONFIG_MTD_OMAP_NOR) || defined(CONFIG_MTD_OMAP_NOR_MODULE)) + dmachan |= (1 << 5) | (1 << 4) (1 << 3) | (1 << 2); +#endif + break; + } + + if (tusb6010_setup_interface(&tusb_data, + TUSB6010_REFCLK_24, /* waitpin */ 2, + /* async cs */ 2, /* sync cs */ 7, + irq, dmachan) == 0) + printk(announce); +} + +#endif + +#if defined(CONFIG_VIDEO_OV9640) || defined(CONFIG_VIDEO_OV9640_MODULE) +/* + * Common OV9640 register initialization for all image sizes, pixel formats, + * and frame rates + */ +const static struct ov9640_reg ov9640_common[] = { + { 0x12, 0x80 }, { 0x11, 0x80 }, { 0x13, 0x8F }, /* COM7, CLKRC, COM8 */ + { 0x01, 0x80 }, { 0x02, 0x80 }, { 0x04, 0x00 }, /* BLUE, RED, COM1 */ + { 0x0E, 0x81 }, { 0x0F, 0x4F }, { 0x14, 0x4A }, /* COM5, COM6, COM9 */ + { 0x16, 0x02 }, { 0x1B, 0x01 }, { 0x24, 0x70 }, /* ?, PSHFT, AEW */ + { 0x25, 0x68 }, { 0x26, 0xD3 }, { 0x27, 0x90 }, /* AEB, VPT, BBIAS */ + { 0x2A, 0x00 }, { 0x2B, 0x00 }, { 0x32, 0x24 }, /* EXHCH, EXHCL, HREF */ + { 0x33, 0x02 }, { 0x37, 0x02 }, { 0x38, 0x13 }, /* CHLF, ADC, ACOM */ + { 0x39, 0xF0 }, { 0x3A, 0x00 }, { 0x3B, 0x01 }, /* OFON, TSLB, COM11 */ + { 0x3D, 0x90 }, { 0x3E, 0x02 }, { 0x3F, 0xF2 }, /* COM13, COM14, EDGE */ + { 0x41, 0x02 }, { 0x42, 0xC8 }, /* COM16, COM17 */ + { 0x43, 0xF0 }, { 0x44, 0x10 }, { 0x45, 0x6C }, /* ?, ?, ? */ + { 0x46, 0x6C }, { 0x47, 0x44 }, { 0x48, 0x44 }, /* ?, ?, ? */ + { 0x49, 0x03 }, { 0x59, 0x49 }, { 0x5A, 0x94 }, /* ?, ?, ? */ + { 0x5B, 0x46 }, { 0x5C, 0x84 }, { 0x5D, 0x5C }, /* ?, ?, ? */ + { 0x5E, 0x08 }, { 0x5F, 0x00 }, { 0x60, 0x14 }, /* ?, ?, ? */ + { 0x61, 0xCE }, /* ? */ + { 0x62, 0x70 }, { 0x63, 0x00 }, { 0x64, 0x04 }, /* LCC1, LCC2, LCC3 */ + { 0x65, 0x00 }, { 0x66, 0x00 }, /* LCC4, LCC5 */ + { 0x69, 0x00 }, { 0x6A, 0x3E }, { 0x6B, 0x3F }, /* HV, MBD, DBLV */ + { 0x6C, 0x40 }, { 0x6D, 0x30 }, { 0x6E, 0x4B }, /* GSP1, GSP2, GSP3 */ + { 0x6F, 0x60 }, { 0x70, 0x70 }, { 0x71, 0x70 }, /* GSP4, GSP5, GSP6 */ + { 0x72, 0x70 }, { 0x73, 0x70 }, { 0x74, 0x60 }, /* GSP7, GSP8, GSP9 */ + { 0x75, 0x60 }, { 0x76, 0x50 }, { 0x77, 0x48 }, /* GSP10,GSP11,GSP12 */ + { 0x78, 0x3A }, { 0x79, 0x2E }, { 0x7A, 0x28 }, /* GSP13,GSP14,GSP15 */ + { 0x7B, 0x22 }, { 0x7C, 0x04 }, { 0x7D, 0x07 }, /* GSP16,GST1, GST2 */ + { 0x7E, 0x10 }, { 0x7F, 0x28 }, { 0x80, 0x36 }, /* GST3, GST4, GST5 */ + { 0x81, 0x44 }, { 0x82, 0x52 }, { 0x83, 0x60 }, /* GST6, GST7, GST8 */ + { 0x84, 0x6C }, { 0x85, 0x78 }, { 0x86, 0x8C }, /* GST9, GST10,GST11 */ + { 0x87, 0x9E }, { 0x88, 0xBB }, { 0x89, 0xD2 }, /* GST12,GST13,GST14 */ + { 0x8A, 0xE6 }, { 0x13, 0x8F }, { 0x00, 0x7F }, /* GST15, COM8 */ + { OV9640_REG_TERM, OV9640_VAL_TERM } +}; + +static int ov9640_sensor_power_set(int power) +{ + /* power up the sensor? */ + gpio_set_value_cansleep(H4_GPIO_CAM_MODULE_EN, power); + + /* take it out of reset if it's not powered */ + gpio_direction_output(H4_GPIO_CAM_RST, !power); + + return 0; +} + +static struct v4l2_ifparm ifparm = { + .if_type = V4L2_IF_TYPE_BT656, + .u = { + .bt656 = { + .frame_start_on_rising_vs = 1, + .nobt_vs_inv = 1, + .mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT, + .clock_min = OV9640_XCLK_MIN, + .clock_max = OV9640_XCLK_MAX, + }, + }, +}; + +static int ov9640_ifparm(struct v4l2_ifparm *p) +{ + *p = ifparm; + + return 0; +} + +static struct ov9640_platform_data h4_ov9640_platform_data = { + .power_set = ov9640_sensor_power_set, + .default_regs = ov9640_common, + .ifparm = ov9640_ifparm, +}; + +#endif + +/* leave LCD powered off unless it will be used */ +#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) +#define LCD_ENABLED true +#else +#define LCD_ENABLED false +#endif + +static struct gpio_led backlight_leds[] = { + { + .name = "lcd_h4", + .default_trigger = "backlight", + .gpio = H4_GPIO_LCD_ENBKL, + }, + { }, +}; + +static struct gpio_led_platform_data backlight_led_data = { + .num_leds = 1, + .leds = backlight_leds, +}; + +static struct platform_device h4_backlight_device = { + .name = "leds-gpio", + .id = 0, + .dev.platform_data = &backlight_led_data, +}; + +static int +u191_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *context) +{ + /* P0 = IRDA control, FIR/MIR vs SIR */ + gpio_request(H4_GPIO_IRDA_FIRSEL, "irda_firsel"); + gpio_direction_output(H4_GPIO_IRDA_FIRSEL, false); + + /* P3 = camera sensor module PWDN */ + gpio_request(H4_GPIO_CAM_MODULE_EN, "camera_en"); + gpio_direction_output(H4_GPIO_CAM_MODULE_EN, false); + + /* P7 = LCD_ENVDD ... controls power to LCD (including backlight) + * P5 = LCD_ENBKL ... switches backlight + */ + gpio_request(H4_GPIO_LCD_ENVDD, "lcd_power"); + gpio_direction_output(H4_GPIO_LCD_ENVDD, LCD_ENABLED); + if (LCD_ENABLED) { + h4_backlight_device.dev.parent = &client->dev; + platform_device_register(&h4_backlight_device); + } + + /* P6 = AUDIO_ENVDD ... switch power to microphone */ + gpio_request(H4_GPIO_AUDIO_ENVDD, "audio_power"); + gpio_direction_output(H4_GPIO_AUDIO_ENVDD, true); + + return 0; +} + + +static struct pcf857x_platform_data u191_platform_data = { + .gpio_base = H4_U191_GPIO_BASE, + .setup = u191_setup, +}; + +static int +u192_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *context) +{ + gpio_request(H4_GPIO_IRDA_AGPSn, "irda/agps"); + gpio_direction_output(H4_GPIO_IRDA_AGPSn, false); + + return 0; +} + +static struct pcf857x_platform_data u192_platform_data = { + .gpio_base = H4_U192_GPIO_BASE, + .setup = u192_setup, +}; + +static int +u193_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *context) +{ + /* reset sensor */ + gpio_request(H4_GPIO_CAM_RST, "camera_rst"); + gpio_direction_output(H4_GPIO_CAM_RST, true); + + return 0; +} + +static struct pcf857x_platform_data u193_platform_data = { + .gpio_base = H4_U193_GPIO_BASE, + .setup = u193_setup, +}; + static struct at24_platform_data m24c01 = { .byte_len = SZ_1K / 8, .page_size = 16, }; static struct i2c_board_info __initdata h4_i2c_board_info[] = { + { /* U191 gpios */ + I2C_BOARD_INFO("pcf8574", 0x20), + .platform_data = &u191_platform_data, + }, + { /* U192 gpios */ + I2C_BOARD_INFO("pcf8574", 0x21), + .platform_data = &u192_platform_data, + }, + { /* U193 gpios */ + I2C_BOARD_INFO("pcf8574", 0x22), + .platform_data = &u193_platform_data, + }, + { + I2C_BOARD_INFO("rv5c387a", 0x32), + /* no IRQ wired to OMAP; nINTB goes to AGPS */ + }, + { + I2C_BOARD_INFO("menelaus", 0x72), + .irq = INT_24XX_SYS_NIRQ, + }, { I2C_BOARD_INFO("isp1301_omap", 0x2d), .irq = OMAP_GPIO_IRQ(125), }, +#if defined(CONFIG_VIDEO_OV9640) || defined(CONFIG_VIDEO_OV9640_MODULE) + { + I2C_BOARD_INFO("ov9640", 0x30), + .platform_data = &h4_ov9640_platform_data, + }, +#endif { /* EEPROM on mainboard */ I2C_BOARD_INFO("24c01", 0x52), .platform_data = &m24c01, @@ -457,14 +775,54 @@ static void __init omap_h4_init(void) } #endif - i2c_register_board_info(1, h4_i2c_board_info, - ARRAY_SIZE(h4_i2c_board_info)); +#ifdef CONFIG_MACH_OMAP2_H4_USB1 + /* S3.3 controls whether these pins are for UART2 or USB1 */ + omap_cfg_reg(N14_24XX_USB1_SE0); + omap_cfg_reg(P15_24XX_USB1_DAT); + omap_cfg_reg(W20_24XX_USB1_TXEN); + omap_cfg_reg(V19_24XX_USB1_RCV); +#endif + + /* Menelaus interrupt */ + omap_cfg_reg(W19_24XX_SYS_NIRQ); platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices)); omap_board_config = h4_config; omap_board_config_size = ARRAY_SIZE(h4_config); - omap_usb_init(&h4_usb_config); omap_serial_init(); + omap_usb_init(&h4_usb_config); + omap_register_i2c_bus(1, 100, h4_i2c_board_info, + ARRAY_SIZE(h4_i2c_board_info)); + + /* smc91x, debug leds, ps/2, extra uarts */ + h4_init_debug(); + +#ifdef CONFIG_MACH_OMAP_H4_TUSB + tusb_evm_setup(); +#endif + + /* defaults seem ok for: + * omap_cfg_reg(U18_24XX_SPI1_SCK); + * omap_cfg_reg(V20_24XX_SPI1_MOSI); + * omap_cfg_reg(T18_24XX_SPI1_MISO); + * omap_cfg_reg(U19_24XX_SPI1_NCS0); + */ + + /* TSC2101 */ + omap_cfg_reg(P20_24XX_GPIO93); + gpio_request(93, "tsc_irq"); + gpio_direction_input(93); + + omap_cfg_reg(W14_24XX_SYS_CLKOUT); /* mclk */ + /* defaults seem ok for: + * omap_cfg_reg(Y15_EAC_AC_SCLK); // bclk + * omap_cfg_reg(R14_EAC_AC_FS); + * omap_cfg_reg(V15_EAC_AC_DOUT); + * omap_cfg_reg(W15_EAC_AC_DIN); + */ + + spi_register_board_info(h4_spi_board_info, + ARRAY_SIZE(h4_spi_board_info)); } static void __init omap_h4_map_io(void) diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c index e096f776f99..91fd0889a35 100644 --- a/arch/arm/mach-omap2/board-ldp.c +++ b/arch/arm/mach-omap2/board-ldp.c @@ -16,13 +16,13 @@ #include #include #include +#include #include #include #include #include #include #include -#include #include #include @@ -34,10 +34,11 @@ #include #include #include +#include +#include #include #include -#include #include "mmc-twl4030.h" @@ -45,6 +46,10 @@ #define LDP_SMC911X_GPIO 152 #define DEBUG_BASE 0x08000000 #define LDP_ETHR_START DEBUG_BASE +#define ENABLE_VAUX1_DEDICATED 0x03 +#define ENABLE_VAUX1_DEV_GRP 0x20 + +#define TWL4030_MSECURE_GPIO 22 static struct resource ldp_smc911x_resources[] = { [0] = { @@ -66,8 +71,244 @@ static struct platform_device ldp_smc911x_device = { .resource = ldp_smc911x_resources, }; +static int ldp_twl4030_keymap[] = { + KEY(0, 0, KEY_1), + KEY(1, 0, KEY_2), + KEY(2, 0, KEY_3), + KEY(0, 1, KEY_4), + KEY(1, 1, KEY_5), + KEY(2, 1, KEY_6), + KEY(3, 1, KEY_F5), + KEY(0, 2, KEY_7), + KEY(1, 2, KEY_8), + KEY(2, 2, KEY_9), + KEY(3, 2, KEY_F6), + KEY(0, 3, KEY_F7), + KEY(1, 3, KEY_0), + KEY(2, 3, KEY_F8), + PERSISTENT_KEY(4, 5), + KEY(4, 4, KEY_VOLUMEUP), + KEY(5, 5, KEY_VOLUMEDOWN), + 0 +}; + +static struct twl4030_keypad_data ldp_kp_twl4030_data = { + .rows = 6, + .cols = 6, + .keymap = ldp_twl4030_keymap, + .keymapsize = ARRAY_SIZE(ldp_twl4030_keymap), + .rep = 1, +}; + +static struct gpio_keys_button ldp_gpio_keys_buttons[] = { + [0] = { + .code = KEY_ENTER, + .gpio = 101, + .desc = "enter sw", + .active_low = 1, + .debounce_interval = 30, + }, + [1] = { + .code = KEY_F1, + .gpio = 102, + .desc = "func 1", + .active_low = 1, + .debounce_interval = 30, + }, + [2] = { + .code = KEY_F2, + .gpio = 103, + .desc = "func 2", + .active_low = 1, + .debounce_interval = 30, + }, + [3] = { + .code = KEY_F3, + .gpio = 104, + .desc = "func 3", + .active_low = 1, + .debounce_interval = 30, + }, + [4] = { + .code = KEY_F4, + .gpio = 105, + .desc = "func 4", + .active_low = 1, + .debounce_interval = 30, + }, + [5] = { + .code = KEY_LEFT, + .gpio = 106, + .desc = "left sw", + .active_low = 1, + .debounce_interval = 30, + }, + [6] = { + .code = KEY_RIGHT, + .gpio = 107, + .desc = "right sw", + .active_low = 1, + .debounce_interval = 30, + }, + [7] = { + .code = KEY_UP, + .gpio = 108, + .desc = "up sw", + .active_low = 1, + .debounce_interval = 30, + }, + [8] = { + .code = KEY_DOWN, + .gpio = 109, + .desc = "down sw", + .active_low = 1, + .debounce_interval = 30, + }, +}; + +static struct gpio_keys_platform_data ldp_gpio_keys = { + .buttons = ldp_gpio_keys_buttons, + .nbuttons = ARRAY_SIZE(ldp_gpio_keys_buttons), + .rep = 1, +}; + +static struct platform_device ldp_gpio_keys_device = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &ldp_gpio_keys, + }, +}; + +static int ts_gpio; + +static int __init msecure_init(void) +{ + int ret = 0; + +#ifdef CONFIG_RTC_DRV_TWL4030 + /* 3430ES2.0 doesn't have msecure/gpio-22 line connected to T2 */ + if (omap_type() == OMAP2_DEVICE_TYPE_GP && + omap_rev() < OMAP3430_REV_ES2_0) { + void __iomem *msecure_pad_config_reg = + omap_ctrl_base_get() + 0xA3C; + int mux_mask = 0x04; + u16 tmp; + + ret = gpio_request(TWL4030_MSECURE_GPIO, "msecure"); + if (ret < 0) { + printk(KERN_ERR "msecure_init: can't" + "reserve GPIO:%d !\n", TWL4030_MSECURE_GPIO); + goto out; + } + /* + * TWL4030 will be in secure mode if msecure line from OMAP + * is low. Make msecure line high in order to change the + * TWL4030 RTC time and calender registers. + */ + + tmp = __raw_readw(msecure_pad_config_reg); + tmp &= 0xF8; /* To enable mux mode 03/04 = GPIO_RTC */ + tmp |= mux_mask;/* To enable mux mode 03/04 = GPIO_RTC */ + __raw_writew(tmp, msecure_pad_config_reg); + + gpio_direction_output(TWL4030_MSECURE_GPIO, 1); + } +out: +#endif + return ret; +} + +/** + * @brief ads7846_dev_init : Requests & sets GPIO line for pen-irq + * + * @return - void. If request gpio fails then Flag KERN_ERR. + */ +static void ads7846_dev_init(void) +{ + if (gpio_request(ts_gpio, "ads7846 irq") < 0) { + printk(KERN_ERR "can't get ads746 pen down GPIO\n"); + return; + } + + gpio_direction_input(ts_gpio); + + omap_set_gpio_debounce(ts_gpio, 1); + omap_set_gpio_debounce_time(ts_gpio, 0xa); +} + +static int ads7846_get_pendown_state(void) +{ + return !gpio_get_value(ts_gpio); +} + +/* + * This enable(1)/disable(0) the voltage for TS: uses twl4030 calls + */ +static int ads7846_vaux_control(int vaux_cntrl) +{ + int ret = 0; + +#ifdef CONFIG_TWL4030_CORE + /* check for return value of ldo_use: if success it returns 0 */ + if (vaux_cntrl == VAUX_ENABLE) { + if (ret != twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, + ENABLE_VAUX1_DEDICATED, TWL4030_VAUX1_DEDICATED)) + return -EIO; + if (ret != twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, + ENABLE_VAUX1_DEV_GRP, TWL4030_VAUX1_DEV_GRP)) + return -EIO; + } else if (vaux_cntrl == VAUX_DISABLE) { + if (ret != twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, + 0x00, TWL4030_VAUX1_DEDICATED)) + return -EIO; + if (ret != twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, + 0x00, TWL4030_VAUX1_DEV_GRP)) + return -EIO; + } +#else + ret = -EIO; +#endif + return ret; +} + +static struct ads7846_platform_data tsc2046_config __initdata = { + .get_pendown_state = ads7846_get_pendown_state, + .keep_vref_on = 1, + .vaux_control = ads7846_vaux_control, +}; + + +static struct omap2_mcspi_device_config tsc2046_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, /* 0: slave, 1: master */ +}; + +static struct spi_board_info ldp_spi_board_info[] __initdata = { + [0] = { + /* + * TSC2046 operates at a max freqency of 2MHz, so + * operate slightly below at 1.5MHz + */ + .modalias = "ads7846", + .bus_num = 1, + .chip_select = 0, + .max_speed_hz = 1500000, + .controller_data = &tsc2046_mcspi_config, + .irq = 0, + .platform_data = &tsc2046_config, + }, +}; + +static struct platform_device ldp_lcd_device = { + .name = "ldp_lcd", + .id = -1, +}; + static struct platform_device *ldp_devices[] __initdata = { &ldp_smc911x_device, + &ldp_lcd_device, + &ldp_gpio_keys_device, }; static inline void __init ldp_init_smc911x(void) @@ -99,6 +340,7 @@ static inline void __init ldp_init_smc911x(void) gpio_direction_input(eth_gpio); } + static void __init omap_ldp_init_irq(void) { omap2_init_common_hw(NULL); @@ -111,8 +353,114 @@ static struct omap_uart_config ldp_uart_config __initdata = { .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), }; +static struct omap_lcd_config ldp_lcd_config __initdata = { + .ctrl_name = "internal", +}; + static struct omap_board_config_kernel ldp_config[] __initdata = { { OMAP_TAG_UART, &ldp_uart_config }, + { OMAP_TAG_LCD, &ldp_lcd_config }, +}; + +static int ldp_batt_table[] = { +/* 0 C*/ +30800, 29500, 28300, 27100, +26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700, 17900, +17200, 16500, 15900, 15300, 14700, 14100, 13600, 13100, 12600, 12100, +11600, 11200, 10800, 10400, 10000, 9630, 9280, 8950, 8620, 8310, +8020, 7730, 7460, 7200, 6950, 6710, 6470, 6250, 6040, 5830, +5640, 5450, 5260, 5090, 4920, 4760, 4600, 4450, 4310, 4170, +4040, 3910, 3790, 3670, 3550 +}; + +static struct twl4030_ins __initdata sleep_on_seq[] = { +/* + * Turn off VDD1 and VDD2. + */ + {MSG_SINGULAR(DEV_GRP_P1, 0xf, RES_STATE_OFF), 4}, + {MSG_SINGULAR(DEV_GRP_P1, 0x10, RES_STATE_OFF), 2}, +#ifdef CONFIG_DISABLE_HFCLK +/* + * And also turn off the OMAP3 PLLs and the sysclk output. + */ + {MSG_SINGULAR(DEV_GRP_P1, 0x7, RES_STATE_OFF), 3}, + {MSG_SINGULAR(DEV_GRP_P1, 0x19, RES_STATE_OFF), 3}, +#endif +}; + +static struct twl4030_script sleep_on_script __initdata = { + .script = sleep_on_seq, + .size = ARRAY_SIZE(sleep_on_seq), + .flags = TRITON_SLEEP_SCRIPT, +}; + +static struct twl4030_ins wakeup_seq[] __initdata = { +#ifndef CONFIG_DISABLE_HFCLK +/* + * Wakeup VDD1 and VDD2. + */ + {MSG_SINGULAR(DEV_GRP_P1, 0xf, RES_STATE_ACTIVE), 4}, + {MSG_SINGULAR(DEV_GRP_P1, 0x10, RES_STATE_ACTIVE), 2}, +#else +/* + * Reenable the OMAP3 PLLs. + * Wakeup VDD1 and VDD2. + * Reenable sysclk output. + */ + {MSG_SINGULAR(DEV_GRP_P1, 0x7, RES_STATE_ACTIVE), 0x30}, + {MSG_SINGULAR(DEV_GRP_P1, 0xf, RES_STATE_ACTIVE), 0x30}, + {MSG_SINGULAR(DEV_GRP_P1, 0x10, RES_STATE_ACTIVE), 0x37}, + {MSG_SINGULAR(DEV_GRP_P1, 0x19, RES_STATE_ACTIVE), 3}, +#endif /* #ifndef CONFIG_DISABLE_HFCLK */ +}; + +static struct twl4030_script wakeup_script __initdata = { + .script = wakeup_seq, + .size = ARRAY_SIZE(wakeup_seq), + .flags = TRITON_WAKEUP12_SCRIPT | TRITON_WAKEUP3_SCRIPT, +}; + +static struct twl4030_ins wrst_seq[] __initdata = { +/* + * Reset twl4030. + * Reset VDD1 regulator. + * Reset VDD2 regulator. + * Reset VPLL1 regulator. + * Enable sysclk output. + * Reenable twl4030. + */ + {MSG_SINGULAR(DEV_GRP_NULL, 0x1b, RES_STATE_OFF), 2}, + {MSG_SINGULAR(DEV_GRP_P1, 0xf, RES_STATE_WRST), 15}, + {MSG_SINGULAR(DEV_GRP_P1, 0x10, RES_STATE_WRST), 15}, + {MSG_SINGULAR(DEV_GRP_P1, 0x7, RES_STATE_WRST), 0x60}, + {MSG_SINGULAR(DEV_GRP_P1, 0x19, RES_STATE_ACTIVE), 2}, + {MSG_SINGULAR(DEV_GRP_NULL, 0x1b, RES_STATE_ACTIVE), 2}, +}; + +static struct twl4030_script wrst_script __initdata = { + .script = wrst_seq, + .size = ARRAY_SIZE(wakeup_seq), + .flags = TRITON_WRST_SCRIPT, +}; + +static struct twl4030_script *twl4030_scripts[] __initdata = { + &sleep_on_script, + &wakeup_script, + &wrst_script, +}; + +static struct twl4030_power_data sdp3430_t2scripts_data __initdata = { + .scripts = twl4030_scripts, + .size = ARRAY_SIZE(twl4030_scripts), +}; + +static struct twl4030_bci_platform_data ldp_bci_data = { + .battery_tmp_tbl = ldp_batt_table, + .tblsize = ARRAY_SIZE(ldp_batt_table), +}; + +static struct twl4030_usb_data ldp_usb_data = { + .usb_mode = T2_USB_MODE_ULPI, }; static struct twl4030_gpio_platform_data ldp_gpio_data = { @@ -121,12 +469,21 @@ static struct twl4030_gpio_platform_data ldp_gpio_data = { .irq_end = TWL4030_GPIO_IRQ_END, }; +static struct twl4030_madc_platform_data ldp_madc_data = { + .irq_line = 1, +}; + static struct twl4030_platform_data ldp_twldata = { .irq_base = TWL4030_IRQ_BASE, .irq_end = TWL4030_IRQ_END, /* platform_data for children goes here */ + .bci = &ldp_bci_data, + .madc = &ldp_madc_data, + .usb = &ldp_usb_data, + .power = &sdp3430_t2scripts_data, .gpio = &ldp_gpio_data, + .keypad = &ldp_kp_twl4030_data, }; static struct i2c_board_info __initdata ldp_i2c_boardinfo[] = { @@ -163,9 +520,15 @@ static void __init omap_ldp_init(void) platform_add_devices(ldp_devices, ARRAY_SIZE(ldp_devices)); omap_board_config = ldp_config; omap_board_config_size = ARRAY_SIZE(ldp_config); + ts_gpio = 54; + ldp_spi_board_info[0].irq = gpio_to_irq(ts_gpio); + spi_register_board_info(ldp_spi_board_info, + ARRAY_SIZE(ldp_spi_board_info)); + msecure_init(); + ads7846_dev_init(); omap_serial_init(); - twl4030_mmc_init(mmc); usb_musb_init(); + twl4030_mmc_init(mmc); } static void __init omap_ldp_map_io(void) diff --git a/arch/arm/mach-omap2/board-n800-bt.c b/arch/arm/mach-omap2/board-n800-bt.c new file mode 100644 index 00000000000..da3a7bb6d89 --- /dev/null +++ b/arch/arm/mach-omap2/board-n800-bt.c @@ -0,0 +1,43 @@ +/* + * Nokia N800 platform-specific data for Bluetooth + * + * Copyright (C) 2005, 2006 Nokia Corporation + * Contact: Ville Tervo + * + * 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 + +static struct platform_device n800_bt_device = { + .name = "hci_h4p", + .id = -1, + .num_resources = 0, +}; + +void __init n800_bt_init(void) +{ + const struct omap_bluetooth_config *bt_config; + + bt_config = (void *) omap_get_config(OMAP_TAG_NOKIA_BT, + struct omap_bluetooth_config); + n800_bt_device.dev.platform_data = (void *) bt_config; + if (platform_device_register(&n800_bt_device) < 0) + BUG(); +} + diff --git a/arch/arm/mach-omap2/board-n800-camera.c b/arch/arm/mach-omap2/board-n800-camera.c new file mode 100644 index 00000000000..395912818ae --- /dev/null +++ b/arch/arm/mach-omap2/board-n800-camera.c @@ -0,0 +1,376 @@ +/* + * arch/arm/mach-omap2/board-n800-camera.c + * + * Copyright (C) 2007 Nokia Corporation + * + * Contact: Sakari Ailus + * + * 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 <../drivers/cbus/retu.h> +#include <../drivers/media/video/tcm825x.h> + +#include "board-n800.h" + +#if defined (CONFIG_VIDEO_TCM825X) || defined (CONFIG_VIDEO_TCM825X_MODULE) + +#define OMAP24XX_CAMERA_JAM_HACK + +#ifdef OMAP24XX_CAMERA_JAM_HACK +/* + * We don't need to check every pixel to assume that the frame is + * corrupt and the sensor is jammed. CHECK_X and CHECK_Y are the + * number of u32s to check per line / row, plus there are two lines in + * the bottom of the frame. + */ +#define CHECK_X 8 +#define CHECK_Y 6 +/* + * Start checking after this many frames since resetting the sensor. + * Sometimes the first frame(s) is(/are) black which could trigger + * unwanted reset(s). + */ +#define JAM_CHECK_AFTER 3 +/* + * If the sensor is quickly brought into bright conditions from dark, + * it may temporarily be saturated, leaving out the normal background + * noise. This many saturated frames may go through before the sensor + * is considered jammed. + */ +#define SATURATED_MAX 30 +#endif + +#define N800_CAM_SENSOR_RESET_GPIO 53 + +static int sensor_okay; +#ifdef OMAP24XX_CAMERA_JAM_HACK +static int frames_after_reset; +static int saturated_count; +#endif + +const static struct tcm825x_reg tcm825x_regs_n800[] = { + /* initial settings for 2.5 V */ + {0x00, 0x03}, {0x03, 0x29}, {0xaa, 0x2a}, {0xc0, 0x2b}, + {0x10, 0x2c}, {0x4c, 0x2d}, {0x9c, 0x3f}, + + /* main settings */ + {0x00, 0x00}, {0x30, 0x01}, {0x0e, 0x02}, /* initial */ + {0x0f, 0x04}, {0x02, 0x05}, {0x0d, 0x06}, {0xc0, 0x07}, + {0x38, 0x08}, {0x50, 0x09}, {0x80, 0x0a}, {0x40, 0x0b}, + {0x40, 0x0c}, {0x00, 0x0d}, {0x04, 0x0e}, {0x04, 0x0f}, + {0x22, 0x10}, {0x96, 0x11}, {0xf0, 0x12}, {0x08, 0x13}, + {0x08, 0x14}, {0x30, 0x15}, {0x30, 0x16}, {0x01, 0x17}, + {0x40, 0x18}, {0x87, 0x19}, {0x2b, 0x1a}, {0x84, 0x1b}, + {0x52, 0x1c}, {0x44, 0x1d}, {0x68, 0x1e}, {0x00, 0x1f}, + {0x00, 0x20}, {0x01, 0x21}, {0x27, 0x22}, {0x40, 0x23}, + {0x27, 0x24}, {0x5f, 0x25}, {0x00, 0x26}, {0x16, 0x27}, + {0x23, 0x28}, /* initial */ /* initial */ /* initial */ + /* initial */ /* initial */ {0x00, 0x2e}, {0x00, 0x2f}, + {0x00, 0x30}, {0x00, 0x31}, {0x00, 0x32}, {0x00, 0x33}, + {0x00, 0x34}, {0x00, 0x35}, {0x00, 0x36}, {0x00, 0x37}, + {0x00, 0x38}, {0x8c, 0x39}, {0xc8, 0x3A}, {0x80, 0x3b}, + {0x00, 0x3c}, {0x17, 0x3d}, {0x85, 0x3e}, /* initial */ + {0xa0, 0x40}, {0x00, 0x41}, {0x00, 0x42}, {0x00, 0x43}, + {0x08, 0x44}, {0x12, 0x45}, {0x00, 0x46}, {0x20, 0x47}, + {0x30, 0x48}, {0x18, 0x49}, {0x20, 0x4a}, {0x4d, 0x4b}, + {0x0c, 0x4c}, {0xe0, 0x4d}, {0x20, 0x4e}, {0x89, 0x4f}, + {0x21, 0x50}, {0x80, 0x51}, {0x02, 0x52}, {0x00, 0x53}, + {0x30, 0x54}, {0x90, 0x55}, {0x40, 0x56}, {0x06, 0x57}, + {0x0f, 0x58}, {0x23, 0x59}, {0x08, 0x5A}, {0x04, 0x5b}, + {0x08, 0x5c}, {0x08, 0x5d}, {0x08, 0x5e}, {0x08, 0x5f}, + {TCM825X_VAL_TERM, TCM825X_REG_TERM} +}; + +const static struct tcm825x_reg tcm825x_regs_n810[] = { + /* initial settings for 2.5 V */ + {0x00, 0x03}, {0x03, 0x29}, {0xaa, 0x2a}, {0xc0, 0x2b}, + {0x10, 0x2c}, {0x4c, 0x2d}, {0x9c, 0x3f}, + + /* main settings */ + {0x00, 0x00}, {0x30, 0x01}, {0x0e, 0x02}, /* initial */ + {0xcf, 0x04}, {0x02, 0x05}, {0x0d, 0x06}, {0xc0, 0x07}, + {0x38, 0x08}, {0x50, 0x09}, {0x80, 0x0a}, {0x40, 0x0b}, + {0x40, 0x0c}, {0x00, 0x0d}, {0x04, 0x0e}, {0x04, 0x0f}, + {0x22, 0x10}, {0x96, 0x11}, {0xf0, 0x12}, {0x08, 0x13}, + {0x08, 0x14}, {0x30, 0x15}, {0x30, 0x16}, {0x01, 0x17}, + {0x40, 0x18}, {0x87, 0x19}, {0x2b, 0x1a}, {0x84, 0x1b}, + {0x52, 0x1c}, {0x44, 0x1d}, {0x68, 0x1e}, {0x00, 0x1f}, + {0x00, 0x20}, {0x01, 0x21}, {0x27, 0x22}, {0x40, 0x23}, + {0x27, 0x24}, {0x5f, 0x25}, {0x00, 0x26}, {0x16, 0x27}, + {0x23, 0x28}, /* initial */ /* initial */ /* initial */ + /* initial */ /* initial */ {0x00, 0x2e}, {0x00, 0x2f}, + {0x00, 0x30}, {0x00, 0x31}, {0x00, 0x32}, {0x00, 0x33}, + {0x00, 0x34}, {0x00, 0x35}, {0x00, 0x36}, {0x00, 0x37}, + {0x00, 0x38}, {0x8c, 0x39}, {0xc8, 0x3A}, {0x80, 0x3b}, + {0x00, 0x3c}, {0x17, 0x3d}, {0x85, 0x3e}, /* initial */ + {0xa0, 0x40}, {0x00, 0x41}, {0x00, 0x42}, {0x00, 0x43}, + {0x08, 0x44}, {0x12, 0x45}, {0x00, 0x46}, {0x20, 0x47}, + {0x30, 0x48}, {0x18, 0x49}, {0x20, 0x4a}, {0x4d, 0x4b}, + {0x0c, 0x4c}, {0xe0, 0x4d}, {0x20, 0x4e}, {0x89, 0x4f}, + {0x21, 0x50}, {0x80, 0x51}, {0x02, 0x52}, {0x00, 0x53}, + {0x30, 0x54}, {0x90, 0x55}, {0x40, 0x56}, {0x06, 0x57}, + {0x0f, 0x58}, {0x23, 0x59}, {0x08, 0x5A}, {0x04, 0x5b}, + {0x08, 0x5c}, {0x08, 0x5d}, {0x08, 0x5e}, {0x08, 0x5f}, + {TCM825X_VAL_TERM, TCM825X_REG_TERM} +}; + +static int tcm825x_is_okay(void) +{ + return sensor_okay; +} + +/* + * VSIM1 --> CAM_IOVDD --> IOVDD (1.8 V) + */ +static int tcm825x_power_on(void) +{ + int ret; + + /* Set VMEM to 1.5V and VIO to 2.5V */ + ret = menelaus_set_vmem(1500); + if (ret < 0) { + /* Try once more, it seems the sensor power up causes + * some problems on the I2C bus. */ + ret = menelaus_set_vmem(1500); + if (ret < 0) + return ret; + } + msleep(1); + + ret = menelaus_set_vio(2500); + if (ret < 0) + return ret; + + /* Set VSim1 on */ + retu_write_reg(RETU_REG_CTRL_SET, 0x0080); + msleep(1); + + gpio_set_value(N800_CAM_SENSOR_RESET_GPIO, 1); + msleep(1); + + saturated_count = 0; + frames_after_reset = 0; + + return 0; +} + +static int tcm825x_power_off(void) +{ + int ret; + + gpio_set_value(N800_CAM_SENSOR_RESET_GPIO, 0); + msleep(1); + + /* Set VSim1 off */ + retu_write_reg(RETU_REG_CTRL_CLR, 0x0080); + msleep(1); + + /* Set VIO_MODE to off */ + ret = menelaus_set_vio(0); + if (ret < 0) + return ret; + msleep(1); + + /* Set VMEM_MODE to off */ + ret = menelaus_set_vmem(0); + if (ret < 0) + return ret; + msleep(1); + + return 0; +} + +static int tcm825x_power_set(int power) +{ + BUG_ON(!sensor_okay); + + if (power) + return tcm825x_power_on(); + else + return tcm825x_power_off(); +} + +static const struct tcm825x_reg *tcm825x_default_regs(void) +{ + if (machine_is_nokia_n810()) + return tcm825x_regs_n810; + + return tcm825x_regs_n800; +} + +#ifdef OMAP24XX_CAMERA_JAM_HACK +/* + * Check for jammed sensor, in which case all horizontal lines are + * equal. Handle also case where sensor could be saturated awhile in + * case of rapid increase of brightness. + */ +static int tcm825x_needs_reset(struct v4l2_int_device *s, void *buf, + struct v4l2_pix_format *pix) +{ + int i, j; + uint32_t xor, xor2; + uint32_t offset; + uint32_t dx_offset; + uint32_t saturated_pattern; + int is_saturated = 1; + + switch (pix->pixelformat) { + default: + case V4L2_PIX_FMT_RGB565: + saturated_pattern = 0xffffffff; /* guess */ + break; + case V4L2_PIX_FMT_UYVY: + saturated_pattern = 0xe080e080; + break; + } + + /* This won't work for height under 2 at all. */ + if (pix->height < 2) + return 0; + /* Check that there is enough image data. */ + if (pix->width * TCM825X_BYTES_PER_PIXEL < sizeof(uint32_t)) + return 0; + /* + * Don't check for jamming immediately. Sometimes frames + * immediately after reset are black. + */ + if (frames_after_reset < JAM_CHECK_AFTER) { + frames_after_reset++; + return 0; + } + + dx_offset = ((pix->width - sizeof(uint32_t) / TCM825X_BYTES_PER_PIXEL) + * TCM825X_BYTES_PER_PIXEL) / (CHECK_X - 1); + dx_offset = dx_offset - dx_offset % TCM825X_BYTES_PER_PIXEL; + /* + * Check two lines in the bottom first. They're unlikely to be + * saturated and quick to check. + */ + offset = (pix->height - 2) * pix->bytesperline; + xor = xor2 = 0; + for (j = 0; j < CHECK_X; j++) { + uint32_t *val = buf + offset; + uint32_t *val2 = buf + offset + pix->bytesperline; + xor ^= *val; + if (*val != saturated_pattern) + is_saturated = 0; + xor2 ^= *val2; + if (xor2 != xor) { + saturated_count = 0; + return 0; + } + offset += dx_offset; + } + /* Check the rest of the picture. */ + offset = 0; + for (i = 0; i < CHECK_Y; i++) { + uint32_t offset2 = offset; + xor2 = 0; + for (j = 0; j < CHECK_X; j++) { + uint32_t *val = buf + offset2; + xor2 ^= *val; + offset2 += dx_offset; + } + if (xor2 != xor) { + saturated_count = 0; + return 0; + } + offset += pix->bytesperline * ((pix->height - 2) / CHECK_Y); + } + + if (is_saturated && saturated_count++ < SATURATED_MAX) + return 0; + + return -EIO; +} +#else +static int tcm825x_needs_reset(struct v4l2_int_device *s, void *buf, + struct v4l2_pix_format *pix) +{ + return 0; +} +#endif + +static const struct v4l2_ifparm ifparm = { + .if_type = V4L2_IF_TYPE_BT656, + .u = { + .bt656 = { + .frame_start_on_rising_vs = 1, + .latch_clk_inv = 1, + .mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT, + .clock_min = TCM825X_XCLK_MIN, + .clock_max = TCM825X_XCLK_MAX, + }, + }, +}; + +static int tcm825x_ifparm(struct v4l2_ifparm *p) +{ + *p = ifparm; + + return 0; +} + +static int tcm825x_is_upside_down(void) +{ + return machine_is_nokia_n810(); +} + +const struct tcm825x_platform_data n800_tcm825x_platform_data = { + .is_okay = tcm825x_is_okay, + .power_set = tcm825x_power_set, + .default_regs = tcm825x_default_regs, + .needs_reset = tcm825x_needs_reset, + .ifparm = tcm825x_ifparm, + .is_upside_down = tcm825x_is_upside_down, +}; + +void __init n800_cam_init(void) +{ + int r; + + r = gpio_request(N800_CAM_SENSOR_RESET_GPIO, "TCM825x reset"); + if (r < 0) { + printk(KERN_WARNING "%s: failed to request gpio\n", + __func__); + return; + } + + gpio_direction_output(N800_CAM_SENSOR_RESET_GPIO, 0); + + sensor_okay = 1; +} + +#else +void __init n800_cam_init(void) +{ +} + +#endif diff --git a/arch/arm/mach-omap2/board-n800-dsp.c b/arch/arm/mach-omap2/board-n800-dsp.c new file mode 100644 index 00000000000..5f3f0d6e954 --- /dev/null +++ b/arch/arm/mach-omap2/board-n800-dsp.c @@ -0,0 +1,155 @@ +/* + * linux/arch/arm/mach-omap2/board-n800-dsp.c + * + * Copyright (C) 2006 Nokia Corporation. + * + * Contact: 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 + +#if defined(CONFIG_OMAP_DSP) + +/* + * dsp peripheral device: AUDIO + */ +static struct dsp_kfunc_device n800_audio_device = { + .name = "audio", + .type = DSP_KFUNC_DEV_TYPE_AUDIO, + .enable = n800_audio_enable, + .disable = n800_audio_disable, +}; + +/* + * dsp peripheral device: TIMER + */ +static int dsp_timer_probe(struct dsp_kfunc_device *kdev, int stage) +{ + char clockname[20]; + + strcpy(clockname, kdev->name); + strcat(clockname, "_fck"); + + kdev->fck = clk_get(NULL, clockname); + if (IS_ERR(kdev->fck)) { + printk(KERN_ERR "couldn't acquire %s\n", clockname); + return PTR_ERR(kdev->fck); + } + pr_debug("%s probed successfully\n", clockname); + + strcpy(clockname, kdev->name); + strcat(clockname, "_ick"); + kdev->ick = clk_get(NULL, clockname); + if (IS_ERR(kdev->ick)) { + printk(KERN_ERR "couldn't acquire %s\n", clockname); + goto fail; + } + pr_debug("%s probed successfully\n", clockname); + + return 0; + fail: + clk_put(kdev->fck); + + return PTR_ERR(kdev->ick); +} + +static int dsp_timer_remove(struct dsp_kfunc_device *kdev, int stage) +{ + clk_put(kdev->ick); + clk_put(kdev->fck); + pr_debug("%s removed successfully\n", kdev->name); + return 0; +} + +static int dsp_timer_enable(struct dsp_kfunc_device *kdev, int stage) +{ + pr_debug("%s enabled(%d)\n", kdev->name, stage); + + spin_lock(&kdev->lock); + + if (kdev->enabled) + goto out; + kdev->enabled = 1; + + clk_enable(kdev->fck); + clk_enable(kdev->ick); + out: + spin_unlock(&kdev->lock); + + return 0; +} + +static int dsp_timer_disable(struct dsp_kfunc_device *kdev, int stage) +{ + pr_debug("%s disabled(%d)\n", kdev->name, stage); + + spin_lock(&kdev->lock); + + if (kdev->enabled == 0) + goto out; + kdev->enabled = 0; + + clk_disable(kdev->ick); + clk_disable(kdev->fck); + out: + spin_unlock(&kdev->lock); + + return 0; +} + +static struct dsp_kfunc_device n800_timer_device = { + .name = "gpt5", + .type = DSP_KFUNC_DEV_TYPE_COMMON, + .probe = dsp_timer_probe, + .remove = dsp_timer_remove, + .enable = dsp_timer_enable, + .disable = dsp_timer_disable, +}; + +static struct dsp_kfunc_device *n800_kfunc_dev[] = { + &n800_audio_device, + &n800_timer_device, +}; + +void __init n800_dsp_init(void) +{ + int i, ret; + struct dsp_kfunc_device **p = n800_kfunc_dev; + + for (i = 0; i < ARRAY_SIZE(n800_kfunc_dev); i++) { + ret = dsp_kfunc_device_register(p[i]); + if (ret) { + printk(KERN_ERR + "KFUNC device registration failed: %s\n", + p[i]->name); + } + } +} + +#else +void __init n800_dsp_init(void) { } +#endif /* CONFIG_OMAP_DSP */ diff --git a/arch/arm/mach-omap2/board-n800-flash.c b/arch/arm/mach-omap2/board-n800-flash.c new file mode 100644 index 00000000000..52aaf76417e --- /dev/null +++ b/arch/arm/mach-omap2/board-n800-flash.c @@ -0,0 +1,349 @@ +/* + * linux/arch/arm/mach-omap2/board-n800-flash.c + * + * Copyright (C) 2006 Nokia Corporation + * Author: Juha Yrjola + * + * 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. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +struct mtd_partition n800_partitions[ONENAND_MAX_PARTITIONS]; + +int n800_onenand_setup(void __iomem *, int freq); + +static struct omap_onenand_platform_data n800_onenand_data = { + .cs = 0, + .parts = n800_partitions, + .nr_parts = 0, /* filled later */ + .onenand_setup = n800_onenand_setup, +}; + +static struct platform_device n800_onenand_device = { + .name = "omap2-onenand", + .id = -1, + .dev = { + .platform_data = &n800_onenand_data, + }, +}; + +static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) +{ + struct gpmc_timings t; + + const int t_cer = 15; + const int t_avdp = 12; + const int t_aavdh = 7; + const int t_ce = 76; + const int t_aa = 76; + const int t_oe = 20; + const int t_cez = 20; /* max of t_cez, t_oez */ + const int t_ds = 30; + const int t_wpl = 40; + const int t_wph = 30; + + memset(&t, 0, sizeof(t)); + t.sync_clk = 0; + t.cs_on = 0; + t.adv_on = 0; + + /* Read */ + t.adv_rd_off = gpmc_round_ns_to_ticks(max_t(int, t_avdp, t_cer)); + t.oe_on = t.adv_rd_off + gpmc_round_ns_to_ticks(t_aavdh); + t.access = t.adv_on + gpmc_round_ns_to_ticks(t_aa); + t.access = max_t(int, t.access, t.cs_on + gpmc_round_ns_to_ticks(t_ce)); + t.access = max_t(int, t.access, t.oe_on + gpmc_round_ns_to_ticks(t_oe)); + t.oe_off = t.access + gpmc_round_ns_to_ticks(1); + t.cs_rd_off = t.oe_off; + t.rd_cycle = t.cs_rd_off + gpmc_round_ns_to_ticks(t_cez); + + /* Write */ + t.adv_wr_off = t.adv_rd_off; + t.we_on = t.oe_on; + if (cpu_is_omap34xx()) { + t.wr_data_mux_bus = t.we_on; + t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds); + } + t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl); + t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph); + t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez); + + /* Configure GPMC for asynchronous read */ + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, + GPMC_CONFIG1_DEVICESIZE_16 | + GPMC_CONFIG1_MUXADDDATA); + + return gpmc_cs_set_timings(cs, &t); +} + +static unsigned short omap2_onenand_readw(void __iomem *addr) +{ + return readw(addr); +} + +static void omap2_onenand_writew(unsigned short value, void __iomem *addr) +{ + writew(value, addr); +} + +static void set_onenand_cfg(void __iomem *onenand_base, int latency, + int sync_write, int hf) +{ + u32 reg; + + reg = omap2_onenand_readw(onenand_base + ONENAND_REG_SYS_CFG1); + reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9)); + reg |= (latency << ONENAND_SYS_CFG1_BRL_SHIFT) | + ONENAND_SYS_CFG1_SYNC_READ | + ONENAND_SYS_CFG1_BL_16; + if (sync_write) + reg |= ONENAND_SYS_CFG1_SYNC_WRITE; + else + reg &= ~ONENAND_SYS_CFG1_SYNC_WRITE; + if (hf) + reg |= ONENAND_SYS_CFG1_HF; + else + reg &= ~ONENAND_SYS_CFG1_HF; + omap2_onenand_writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); +} + +static int omap2_onenand_set_sync_mode(int cs, void __iomem *onenand_base, + int freq) +{ + struct gpmc_timings t; + const int t_cer = 15; + const int t_avdp = 12; + const int t_cez = 20; /* max of t_cez, t_oez */ + const int t_ds = 30; + const int t_wpl = 40; + const int t_wph = 30; + int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo; + int tick_ns, div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency; + int err, ticks_cez, sync_write = 0, first_time = 0, hf = 0; + u32 reg; + + if (!freq) { + /* Very first call freq is not known */ + err = omap2_onenand_set_async_mode(cs, onenand_base); + if (err) + return err; + reg = omap2_onenand_readw(onenand_base + + ONENAND_REG_VERSION_ID); + switch ((reg >> 4) & 0xf) { + case 0: + freq = 40; + break; + case 1: + freq = 54; + break; + case 2: + freq = 66; + break; + case 3: + freq = 83; + break; + case 4: + freq = 104; + break; + default: + freq = 54; + break; + } + first_time = 1; + } + + switch (freq) { + case 83: + min_gpmc_clk_period = 12; /* 83 MHz */ + t_ces = 5; + t_avds = 4; + t_avdh = 2; + t_ach = 6; + t_aavdh = 6; + t_rdyo = 9; + if (cpu_is_omap34xx()) + sync_write = 1; + break; + case 66: + min_gpmc_clk_period = 15; /* 66 MHz */ + t_ces = 6; + t_avds = 5; + t_avdh = 2; + t_ach = 6; + t_aavdh = 6; + t_rdyo = 11; + if (cpu_is_omap34xx()) + sync_write = 1; + break; + default: + min_gpmc_clk_period = 18; /* 54 MHz */ + t_ces = 7; + t_avds = 7; + t_avdh = 7; + t_ach = 9; + t_aavdh = 7; + t_rdyo = 15; + break; + } + + tick_ns = gpmc_ticks_to_ns(1); + div = gpmc_cs_calc_divider(cs, min_gpmc_clk_period); + gpmc_clk_ns = gpmc_ticks_to_ns(div); + if (gpmc_clk_ns < 15) /* >66Mhz */ + hf = 1; + if (hf) + latency = 6; + else if (gpmc_clk_ns >= 25) /* 40 MHz*/ + latency = 3; + else + latency = 4; + + if (first_time) + set_onenand_cfg(onenand_base, latency, sync_write, hf); + + if (div == 1) { + reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2); + reg |= (1 << 7); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg); + reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3); + reg |= (1 << 7); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg); + reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4); + reg |= (1 << 7); + reg |= (1 << 23); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg); + } else { + reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2); + reg &= ~(1 << 7); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg); + reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3); + reg &= ~(1 << 7); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg); + reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4); + reg &= ~(1 << 7); + reg &= ~(1 << 23); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg); + } + + /* Set synchronous read timings */ + memset(&t, 0, sizeof(t)); + t.sync_clk = min_gpmc_clk_period; + t.cs_on = 0; + t.adv_on = 0; + fclk_offset_ns = gpmc_round_ns_to_ticks(max_t(int, t_ces, t_avds)); + fclk_offset = gpmc_ns_to_ticks(fclk_offset_ns); + t.page_burst_access = gpmc_clk_ns; + + /* Read */ + t.adv_rd_off = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_avdh)); + t.oe_on = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_ach)); + t.access = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div); + t.oe_off = t.access + gpmc_round_ns_to_ticks(1); + t.cs_rd_off = t.oe_off; + ticks_cez = ((gpmc_ns_to_ticks(t_cez) + div - 1) / div) * div; + t.rd_cycle = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div + + ticks_cez); + + /* Write */ + if (sync_write) { + t.adv_wr_off = t.adv_rd_off; + t.we_on = 0; + t.we_off = t.cs_rd_off; + t.cs_wr_off = t.cs_rd_off; + t.wr_cycle = t.rd_cycle; + if (cpu_is_omap34xx()) { + t.wr_data_mux_bus = gpmc_ticks_to_ns(fclk_offset + + gpmc_ns_to_ticks(min_gpmc_clk_period + + t_rdyo)); + t.wr_access = t.access; + } + } else { + t.adv_wr_off = gpmc_round_ns_to_ticks(max_t(int, t_avdp, t_cer)); + t.we_on = t.adv_wr_off + gpmc_round_ns_to_ticks(t_aavdh); + t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl); + t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph); + t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez); + if (cpu_is_omap34xx()) { + t.wr_data_mux_bus = t.we_on; + t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds); + } + } + + /* Configure GPMC for synchronous read */ + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, + GPMC_CONFIG1_WRAPBURST_SUPP | + GPMC_CONFIG1_READMULTIPLE_SUPP | + GPMC_CONFIG1_READTYPE_SYNC | + (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) | + (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) | + GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) | + GPMC_CONFIG1_PAGE_LEN(2) | + (cpu_is_omap34xx() ? 0 : + (GPMC_CONFIG1_WAIT_READ_MON | + GPMC_CONFIG1_WAIT_PIN_SEL(0))) | + GPMC_CONFIG1_DEVICESIZE_16 | + GPMC_CONFIG1_DEVICETYPE_NOR | + GPMC_CONFIG1_MUXADDDATA); + + err = gpmc_cs_set_timings(cs, &t); + if (err) + return err; + + set_onenand_cfg(onenand_base, latency, sync_write, hf); + + return 0; +} + +int n800_onenand_setup(void __iomem *onenand_base, int freq) +{ + struct omap_onenand_platform_data *datap = &n800_onenand_data; + struct device *dev = &n800_onenand_device.dev; + + /* Set sync timings in GPMC */ + if (omap2_onenand_set_sync_mode(datap->cs, onenand_base, freq) < 0) { + dev_err(dev, "Unable to set synchronous mode\n"); + return -EINVAL; + } + + return 0; +} + +void __init n800_flash_init(void) +{ + const struct omap_partition_config *part; + int i = 0; + + n800_onenand_data.gpio_irq = cpu_is_omap34xx() ? 65 : 26; + + while ((part = omap_get_nr_config(OMAP_TAG_PARTITION, + struct omap_partition_config, i)) != NULL) { + struct mtd_partition *mpart; + + mpart = n800_partitions + i; + mpart->name = (char *) part->name; + mpart->size = part->size; + mpart->offset = part->offset; + mpart->mask_flags = part->mask_flags; + i++; + if (i == ARRAY_SIZE(n800_partitions)) { + printk(KERN_ERR "Too many partitions supplied\n"); + return; + } + } + n800_onenand_data.nr_parts = i; + if (platform_device_register(&n800_onenand_device) < 0) { + printk(KERN_ERR "Unable to register OneNAND device\n"); + return; + } +} diff --git a/arch/arm/mach-omap2/board-n800-mmc.c b/arch/arm/mach-omap2/board-n800-mmc.c new file mode 100644 index 00000000000..b2376a96fbf --- /dev/null +++ b/arch/arm/mach-omap2/board-n800-mmc.c @@ -0,0 +1,374 @@ +/* + * linux/arch/arm/mach-omap2/board-n800-mmc.c + * + * Copyright (C) 2006 Nokia Corporation + * Author: Juha Yrjola + * + * 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. + */ + +#include +#include +#include +#include + +#include + +#include + +#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) + +static const int slot_switch_gpio = 96; + +static const int n810_slot2_pw_vddf = 23; +static const int n810_slot2_pw_vdd = 9; + +static int slot1_cover_open; +static int slot2_cover_open; +static struct device *mmc_device; + +/* + * VMMC --> slot 1 (N800 & N810) + * VDCDC3_APE, VMCS2_APE --> slot 2 on N800 + * GPIO96 --> Menelaus GPIO2 + * GPIO23 --> controls slot2 VSD (N810 only) + * GPIO9 --> controls slot2 VIO_SD (N810 only) + */ + +static int n800_mmc_switch_slot(struct device *dev, int slot) +{ +#ifdef CONFIG_MMC_DEBUG + dev_dbg(dev, "Choose slot %d\n", slot + 1); +#endif + gpio_set_value(slot_switch_gpio, slot); + return 0; +} + +static int n800_mmc_set_power_menelaus(struct device *dev, int slot, + int power_on, int vdd) +{ + int mV; + +#ifdef CONFIG_MMC_DEBUG + dev_dbg(dev, "Set slot %d power: %s (vdd %d)\n", slot + 1, + power_on ? "on" : "off", vdd); +#endif + if (slot == 0) { + if (!power_on) + return menelaus_set_vmmc(0); + switch (1 << vdd) { + case MMC_VDD_33_34: + case MMC_VDD_32_33: + case MMC_VDD_31_32: + mV = 3100; + break; + case MMC_VDD_30_31: + mV = 3000; + break; + case MMC_VDD_28_29: + mV = 2800; + break; + case MMC_VDD_165_195: + mV = 1850; + break; + default: + BUG(); + } + return menelaus_set_vmmc(mV); + } else { + if (!power_on) + return menelaus_set_vdcdc(3, 0); + switch (1 << vdd) { + case MMC_VDD_33_34: + case MMC_VDD_32_33: + mV = 3300; + break; + case MMC_VDD_30_31: + case MMC_VDD_29_30: + mV = 3000; + break; + case MMC_VDD_28_29: + case MMC_VDD_27_28: + mV = 2800; + break; + case MMC_VDD_24_25: + case MMC_VDD_23_24: + mV = 2400; + break; + case MMC_VDD_22_23: + case MMC_VDD_21_22: + mV = 2200; + break; + case MMC_VDD_20_21: + mV = 2000; + break; + case MMC_VDD_165_195: + mV = 1800; + break; + default: + BUG(); + } + return menelaus_set_vdcdc(3, mV); + } + return 0; +} + +static void nokia_mmc_set_power_internal(struct device *dev, + int power_on) +{ + dev_dbg(dev, "Set internal slot power %s\n", + power_on ? "on" : "off"); + + if (power_on) { + gpio_set_value(n810_slot2_pw_vddf, 1); + udelay(30); + gpio_set_value(n810_slot2_pw_vdd, 1); + udelay(100); + } else { + gpio_set_value(n810_slot2_pw_vdd, 0); + msleep(50); + gpio_set_value(n810_slot2_pw_vddf, 0); + msleep(50); + } +} + +static int n800_mmc_set_power(struct device *dev, int slot, int power_on, + int vdd) +{ + if (machine_is_nokia_n800() || slot == 0) + return n800_mmc_set_power_menelaus(dev, slot, power_on, vdd); + + nokia_mmc_set_power_internal(dev, power_on); + + return 0; +} + +static int n800_mmc_set_bus_mode(struct device *dev, int slot, int bus_mode) +{ + int r; + + dev_dbg(dev, "Set slot %d bus mode %s\n", slot + 1, + bus_mode == MMC_BUSMODE_OPENDRAIN ? "open-drain" : "push-pull"); + BUG_ON(slot != 0 && slot != 1); + slot++; + switch (bus_mode) { + case MMC_BUSMODE_OPENDRAIN: + r = menelaus_set_mmc_opendrain(slot, 1); + break; + case MMC_BUSMODE_PUSHPULL: + r = menelaus_set_mmc_opendrain(slot, 0); + break; + default: + BUG(); + } + if (r != 0 && printk_ratelimit()) + dev_err(dev, "MMC: unable to set bus mode for slot %d\n", + slot); + return r; +} + +static int n800_mmc_get_cover_state(struct device *dev, int slot) +{ + slot++; + BUG_ON(slot != 1 && slot != 2); + if (slot == 1) + return slot1_cover_open; + else + return slot2_cover_open; +} + +static void n800_mmc_callback(void *data, u8 card_mask) +{ + int bit, *openp, index; + + if (machine_is_nokia_n800()) { + bit = 1 << 1; + openp = &slot2_cover_open; + index = 1; + } else { + bit = 1; + openp = &slot1_cover_open; + index = 0; + } + + if (card_mask & bit) + *openp = 1; + else + *openp = 0; + + omap_mmc_notify_cover_event(mmc_device, index, *openp); +} + +void n800_mmc_slot1_cover_handler(void *arg, int closed_state) +{ + if (mmc_device == NULL) + return; + + slot1_cover_open = !closed_state; + omap_mmc_notify_cover_event(mmc_device, 0, closed_state); +} + +static int n800_mmc_late_init(struct device *dev) +{ + int r, bit, *openp; + int vs2sel; + + mmc_device = dev; + + r = menelaus_set_slot_sel(1); + if (r < 0) + return r; + + if (machine_is_nokia_n800()) + vs2sel = 0; + else + vs2sel = 2; + + r = menelaus_set_mmc_slot(2, 0, vs2sel, 1); + if (r < 0) + return r; + + n800_mmc_set_power(dev, 0, MMC_POWER_ON, 16); /* MMC_VDD_28_29 */ + n800_mmc_set_power(dev, 1, MMC_POWER_ON, 16); + + r = menelaus_set_mmc_slot(1, 1, 0, 1); + if (r < 0) + return r; + r = menelaus_set_mmc_slot(2, 1, vs2sel, 1); + if (r < 0) + return r; + + r = menelaus_get_slot_pin_states(); + if (r < 0) + return r; + + if (machine_is_nokia_n800()) { + bit = 1 << 1; + openp = &slot2_cover_open; + } else { + bit = 1; + openp = &slot1_cover_open; + slot2_cover_open = 0; + } + + /* All slot pin bits seem to be inversed until first swith change */ + if (r == 0xf || r == (0xf & ~bit)) + r = ~r; + + if (r & bit) + *openp = 1; + else + *openp = 0; + + r = menelaus_register_mmc_callback(n800_mmc_callback, NULL); + + return r; +} + +static void n800_mmc_shutdown(struct device *dev) +{ + int vs2sel; + + if (machine_is_nokia_n800()) + vs2sel = 0; + else + vs2sel = 2; + + menelaus_set_mmc_slot(1, 0, 0, 0); + menelaus_set_mmc_slot(2, 0, vs2sel, 0); +} + +static void n800_mmc_cleanup(struct device *dev) +{ + menelaus_unregister_mmc_callback(); + + gpio_free(slot_switch_gpio); + + if (machine_is_nokia_n810()) { + gpio_free(n810_slot2_pw_vddf); + gpio_free(n810_slot2_pw_vdd); + } +} + +/* + * MMC controller1 has two slots that are multiplexed via I2C. + * MMC controller2 is not in use. + */ +static struct omap_mmc_platform_data mmc1_data = { + .nr_slots = 2, + .switch_slot = n800_mmc_switch_slot, + .init = n800_mmc_late_init, + .cleanup = n800_mmc_cleanup, + .shutdown = n800_mmc_shutdown, + .max_freq = 24000000, + .dma_mask = 0xffffffff, + .slots[0] = { + .wires = 4, + .set_power = n800_mmc_set_power, + .set_bus_mode = n800_mmc_set_bus_mode, + .get_cover_state= n800_mmc_get_cover_state, + .ocr_mask = MMC_VDD_165_195 | MMC_VDD_30_31 | + MMC_VDD_32_33 | MMC_VDD_33_34, + .name = "internal", + }, + .slots[1] = { + .set_power = n800_mmc_set_power, + .set_bus_mode = n800_mmc_set_bus_mode, + .get_cover_state= n800_mmc_get_cover_state, + .ocr_mask = MMC_VDD_165_195 | MMC_VDD_20_21 | + MMC_VDD_21_22 | MMC_VDD_22_23 | MMC_VDD_23_24 | + MMC_VDD_24_25 | MMC_VDD_27_28 | MMC_VDD_28_29 | + MMC_VDD_29_30 | MMC_VDD_30_31 | MMC_VDD_32_33 | + MMC_VDD_33_34, + .name = "external", + }, +}; + +static struct omap_mmc_platform_data *mmc_data[OMAP24XX_NR_MMC]; + +void __init n800_mmc_init(void) + +{ + if (machine_is_nokia_n810()) { + mmc1_data.slots[0].name = "external"; + + /* + * Some Samsung Movinand chips do not like open-ended + * multi-block reads and fall to braind-dead state + * while doing so. Reducing the number of blocks in + * the transfer or delays in clock disable do not help + */ + mmc1_data.slots[1].name = "internal"; + mmc1_data.slots[1].ban_openended = 1; + } + + if (gpio_request(slot_switch_gpio, "MMC slot switch") < 0) + BUG(); + gpio_direction_output(slot_switch_gpio, 0); + + if (machine_is_nokia_n810()) { + if (gpio_request(n810_slot2_pw_vddf, "MMC slot 2 Vddf") < 0) + BUG(); + gpio_direction_output(n810_slot2_pw_vddf, 0); + + if (gpio_request(n810_slot2_pw_vdd, "MMC slot 2 Vdd") < 0) + BUG(); + gpio_direction_output(n810_slot2_pw_vdd, 0); + } + + mmc_data[0] = &mmc1_data; + omap2_init_mmc(mmc_data, OMAP24XX_NR_MMC); +} +#else + +void __init n800_mmc_init(void) +{ +} + +void n800_mmc_slot1_cover_handler(void *arg, int state) +{ +} + +#endif diff --git a/arch/arm/mach-omap2/board-n800-usb.c b/arch/arm/mach-omap2/board-n800-usb.c new file mode 100644 index 00000000000..8250014bee6 --- /dev/null +++ b/arch/arm/mach-omap2/board-n800-usb.c @@ -0,0 +1,175 @@ +/* + * linux/arch/arm/mach-omap2/board-n800-usb.c + * + * Copyright (C) 2006 Nokia Corporation + * Author: Juha Yrjola + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TUSB_ASYNC_CS 1 +#define TUSB_SYNC_CS 4 +#define GPIO_TUSB_INT 58 +#define GPIO_TUSB_ENABLE 0 + +static int tusb_set_power(int state); +static int tusb_set_clock(struct clk *osc_ck, int state); + +#if defined(CONFIG_USB_MUSB_OTG) +# define BOARD_MODE MUSB_OTG +#elif defined(CONFIG_USB_MUSB_PERIPHERAL) +# define BOARD_MODE MUSB_PERIPHERAL +#else /* defined(CONFIG_USB_MUSB_HOST) */ +# define BOARD_MODE MUSB_HOST +#endif + +static struct musb_hdrc_eps_bits musb_eps[] = { + { "ep1_tx", 5, }, + { "ep1_rx", 5, }, + { "ep2_tx", 5, }, + { "ep2_rx", 5, }, + { "ep3_tx", 3, }, + { "ep3_rx", 3, }, + { "ep4_tx", 3, }, + { "ep4_rx", 3, }, + { "ep5_tx", 2, }, + { "ep5_rx", 2, }, + { "ep6_tx", 2, }, + { "ep6_rx", 2, }, + { "ep7_tx", 2, }, + { "ep7_rx", 2, }, + { "ep8_tx", 2, }, + { "ep8_rx", 2, }, + { "ep9_tx", 2, }, + { "ep9_rx", 2, }, + { "ep10_tx", 2, }, + { "ep10_rx", 2, }, + { "ep11_tx", 2, }, + { "ep11_rx", 2, }, + { "ep12_tx", 2, }, + { "ep12_rx", 2, }, + { "ep13_tx", 2, }, + { "ep13_rx", 2, }, + { "ep14_tx", 2, }, + { "ep14_rx", 2, }, + { "ep15_tx", 2, }, + { "ep15_rx", 2, }, +}; + +static struct musb_hdrc_config musb_config = { + .multipoint = 1, + .dyn_fifo = 1, + .soft_con = 1, + .dma = 1, + .num_eps = 16, + .dma_channels = 7, + .ram_bits = 12, + .eps_bits = musb_eps, +}; + +static struct musb_hdrc_platform_data tusb_data = { + .mode = BOARD_MODE, + .set_power = tusb_set_power, + .set_clock = tusb_set_clock, + .min_power = 25, /* x2 = 50 mA drawn from VBUS as peripheral */ + .power = 100, /* Max 100 mA VBUS for host mode */ + .clock = "osc_ck", + .config = &musb_config, +}; + +/* + * Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and + * 1.5 V voltage regulators of PM companion chip. Companion chip will then + * provide then PGOOD signal to TUSB6010 which will release it from reset. + */ +static int tusb_set_power(int state) +{ + int i, retval = 0; + + if (state) { + gpio_set_value(GPIO_TUSB_ENABLE, 1); + msleep(1); + + /* Wait until TUSB6010 pulls INT pin down */ + i = 100; + while (i && gpio_get_value(GPIO_TUSB_INT)) { + msleep(1); + i--; + } + + if (!i) { + printk(KERN_ERR "tusb: powerup failed\n"); + retval = -ENODEV; + } + } else { + gpio_set_value(GPIO_TUSB_ENABLE, 0); + msleep(10); + } + + return retval; +} + +static int osc_ck_on; + +static int tusb_set_clock(struct clk *osc_ck, int state) +{ + if (state) { + if (osc_ck_on > 0) + return -ENODEV; + + //omap2_block_sleep(); + clk_enable(osc_ck); + osc_ck_on = 1; + } else { + if (osc_ck_on == 0) + return -ENODEV; + + clk_disable(osc_ck); + osc_ck_on = 0; + //omap2_allow_sleep(); + } + + return 0; +} + +void __init n800_usb_init(void) +{ + int ret = 0; + static char announce[] __initdata = KERN_INFO "TUSB 6010\n"; + + /* PM companion chip power control pin */ + ret = gpio_request(GPIO_TUSB_ENABLE, "TUSB6010 enable"); + if (ret != 0) { + printk(KERN_ERR "Could not get TUSB power GPIO%i\n", + GPIO_TUSB_ENABLE); + return; + } + gpio_direction_output(GPIO_TUSB_ENABLE, 0); + + tusb_set_power(0); + + ret = tusb6010_setup_interface(&tusb_data, TUSB6010_REFCLK_19, 2, + TUSB_ASYNC_CS, TUSB_SYNC_CS, + GPIO_TUSB_INT, 0x3f); + if (ret != 0) + goto err; + + printk(announce); + + return; + +err: + gpio_free(GPIO_TUSB_ENABLE); +} diff --git a/arch/arm/mach-omap2/board-n800.c b/arch/arm/mach-omap2/board-n800.c new file mode 100644 index 00000000000..f1552f0d7b6 --- /dev/null +++ b/arch/arm/mach-omap2/board-n800.c @@ -0,0 +1,750 @@ +/* + * linux/arch/arm/mach-omap2/board-n800.c + * + * Copyright (C) 2005-2007 Nokia Corporation + * Author: Juha Yrjola + * + * Modified from mach-omap2/board-generic.c + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include <../drivers/cbus/tahvo.h> +#include <../drivers/media/video/tcm825x.h> + +#define N800_BLIZZARD_POWERDOWN_GPIO 15 +#define N800_STI_GPIO 62 +#define N800_KEYB_IRQ_GPIO 109 +#define N800_DAV_IRQ_GPIO 103 +#define N800_TSC2301_RESET_GPIO 118 + +#ifdef CONFIG_MACH_NOKIA_N810 +static s16 rx44_keymap[LM8323_KEYMAP_SIZE] = { + [0x01] = KEY_Q, + [0x02] = KEY_K, + [0x03] = KEY_O, + [0x04] = KEY_P, + [0x05] = KEY_BACKSPACE, + [0x06] = KEY_A, + [0x07] = KEY_S, + [0x08] = KEY_D, + [0x09] = KEY_F, + [0x0a] = KEY_G, + [0x0b] = KEY_H, + [0x0c] = KEY_J, + + [0x11] = KEY_W, + [0x12] = KEY_F4, + [0x13] = KEY_L, + [0x14] = KEY_APOSTROPHE, + [0x16] = KEY_Z, + [0x17] = KEY_X, + [0x18] = KEY_C, + [0x19] = KEY_V, + [0x1a] = KEY_B, + [0x1b] = KEY_N, + [0x1c] = KEY_LEFTSHIFT, /* Actually, this is both shift keys */ + [0x1f] = KEY_F7, + + [0x21] = KEY_E, + [0x22] = KEY_SEMICOLON, + [0x23] = KEY_MINUS, + [0x24] = KEY_EQUAL, + [0x2b] = KEY_FN, + [0x2c] = KEY_M, + [0x2f] = KEY_F8, + + [0x31] = KEY_R, + [0x32] = KEY_RIGHTCTRL, + [0x34] = KEY_SPACE, + [0x35] = KEY_COMMA, + [0x37] = KEY_UP, + [0x3c] = KEY_COMPOSE, + [0x3f] = KEY_F6, + + [0x41] = KEY_T, + [0x44] = KEY_DOT, + [0x46] = KEY_RIGHT, + [0x4f] = KEY_F5, + [0x51] = KEY_Y, + [0x53] = KEY_DOWN, + [0x55] = KEY_ENTER, + [0x5f] = KEY_ESC, + + [0x61] = KEY_U, + [0x64] = KEY_LEFT, + + [0x71] = KEY_I, + [0x75] = KEY_KPENTER, +}; + +static struct lm8323_platform_data lm8323_pdata = { + .repeat = 0, /* Repeat is handled in userspace for now. */ + .keymap = rx44_keymap, + .size_x = 8, + .size_y = 8, + .debounce_time = 12, + .active_time = 500, + + .name = "Internal keyboard", + .pwm1_name = "n810::keyboard", + .pwm2_name = "n810::cover", +}; +#endif + +void __init nokia_n800_init_irq(void) +{ + omap2_init_common_hw(NULL); + omap_init_irq(); + omap_gpio_init(); + +#ifdef CONFIG_OMAP_STI + if (gpio_request(N800_STI_GPIO, "STI") < 0) { + printk(KERN_ERR "Failed to request GPIO %d for STI\n", + N800_STI_GPIO); + return; + } + + gpio_direction_output(N800_STI_GPIO, 0); +#endif +} + +#if defined(CONFIG_MENELAUS) && defined(CONFIG_SENSORS_TMP105) + +static int n800_tmp105_set_power(int enable) +{ + return menelaus_set_vaux(enable ? 2800 : 0); +} + +#else + +#define n800_tmp105_set_power NULL + +#endif + +static struct omap_uart_config n800_uart_config __initdata = { + .enabled_uarts = (1 << 0) | (1 << 2), +}; + +#include "../../../drivers/cbus/retu.h" + +static struct omap_fbmem_config n800_fbmem0_config __initdata = { + .size = 752 * 1024, +}; + +static struct omap_fbmem_config n800_fbmem1_config __initdata = { + .size = 752 * 1024, +}; + +static struct omap_fbmem_config n800_fbmem2_config __initdata = { + .size = 752 * 1024, +}; + +static struct omap_tmp105_config n800_tmp105_config __initdata = { + .tmp105_irq_pin = 125, + .set_power = n800_tmp105_set_power, +}; + +static void mipid_shutdown(struct mipid_platform_data *pdata) +{ + if (pdata->nreset_gpio != -1) { + pr_info("shutdown LCD\n"); + gpio_set_value(pdata->nreset_gpio, 0); + msleep(120); + } +} + +static struct mipid_platform_data n800_mipid_platform_data = { + .shutdown = mipid_shutdown, +}; + +static void __init mipid_dev_init(void) +{ + const struct omap_lcd_config *conf; + + conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config); + if (conf != NULL) { + n800_mipid_platform_data.nreset_gpio = conf->nreset_gpio; + n800_mipid_platform_data.data_lines = conf->data_lines; + } +} + +static struct { + struct clk *sys_ck; +} blizzard; + +static int blizzard_get_clocks(void) +{ + blizzard.sys_ck = clk_get(0, "osc_ck"); + if (IS_ERR(blizzard.sys_ck)) { + printk(KERN_ERR "can't get Blizzard clock\n"); + return PTR_ERR(blizzard.sys_ck); + } + return 0; +} + +static unsigned long blizzard_get_clock_rate(struct device *dev) +{ + return clk_get_rate(blizzard.sys_ck); +} + +static void blizzard_enable_clocks(int enable) +{ + if (enable) + clk_enable(blizzard.sys_ck); + else + clk_disable(blizzard.sys_ck); +} + +static void blizzard_power_up(struct device *dev) +{ + /* Vcore to 1.475V */ + tahvo_set_clear_reg_bits(0x07, 0, 0xf); + msleep(10); + + blizzard_enable_clocks(1); + gpio_set_value(N800_BLIZZARD_POWERDOWN_GPIO, 1); +} + +static void blizzard_power_down(struct device *dev) +{ + gpio_set_value(N800_BLIZZARD_POWERDOWN_GPIO, 0); + blizzard_enable_clocks(0); + + /* Vcore to 1.005V */ + tahvo_set_clear_reg_bits(0x07, 0xf, 0); +} + +static struct blizzard_platform_data n800_blizzard_data = { + .power_up = blizzard_power_up, + .power_down = blizzard_power_down, + .get_clock_rate = blizzard_get_clock_rate, + .te_connected = 1, +}; + +static void __init blizzard_dev_init(void) +{ + int r; + + r = gpio_request(N800_BLIZZARD_POWERDOWN_GPIO, "Blizzard pd"); + if (r < 0) + return; + gpio_direction_output(N800_BLIZZARD_POWERDOWN_GPIO, 1); + + blizzard_get_clocks(); + omapfb_set_ctrl_platform_data(&n800_blizzard_data); +} + +static struct omap_board_config_kernel n800_config[] __initdata = { + { OMAP_TAG_UART, &n800_uart_config }, + { OMAP_TAG_FBMEM, &n800_fbmem0_config }, + { OMAP_TAG_FBMEM, &n800_fbmem1_config }, + { OMAP_TAG_FBMEM, &n800_fbmem2_config }, + { OMAP_TAG_TMP105, &n800_tmp105_config }, +}; + +static struct tsc2301_platform_data tsc2301_config = { + .reset_gpio = N800_TSC2301_RESET_GPIO, + .keymap = { + -1, /* Event for bit 0 */ + KEY_UP, /* Event for bit 1 (up) */ + KEY_F5, /* Event for bit 2 (home) */ + -1, /* Event for bit 3 */ + KEY_LEFT, /* Event for bit 4 (left) */ + KEY_ENTER, /* Event for bit 5 (enter) */ + KEY_RIGHT, /* Event for bit 6 (right) */ + -1, /* Event for bit 7 */ + KEY_ESC, /* Event for bit 8 (cycle) */ + KEY_DOWN, /* Event for bit 9 (down) */ + KEY_F4, /* Event for bit 10 (menu) */ + -1, /* Event for bit 11 */ + KEY_F8, /* Event for bit 12 (Zoom-) */ + KEY_F6, /* Event for bit 13 (FS) */ + KEY_F7, /* Event for bit 14 (Zoom+) */ + -1, /* Event for bit 15 */ + }, + .kp_rep = 0, + .keyb_name = "Internal keypad", +}; + +static void tsc2301_dev_init(void) +{ + int r; + int gpio = N800_KEYB_IRQ_GPIO; + + r = gpio_request(gpio, "tsc2301 KBD IRQ"); + if (r >= 0) { + gpio_direction_input(gpio); + tsc2301_config.keyb_int = gpio_to_irq(gpio); + } else { + printk(KERN_ERR "unable to get KBD GPIO"); + } + + gpio = N800_DAV_IRQ_GPIO; + r = gpio_request(gpio, "tsc2301 DAV IRQ"); + if (r >= 0) { + gpio_direction_input(gpio); + tsc2301_config.dav_int = gpio_to_irq(gpio); + } else { + printk(KERN_ERR "unable to get DAV GPIO"); + } +} + +static int __init tea5761_dev_init(void) +{ + const struct omap_tea5761_config *info; + int enable_gpio = 0; + + info = omap_get_config(OMAP_TAG_TEA5761, struct omap_tea5761_config); + if (info) + enable_gpio = info->enable_gpio; + + if (enable_gpio) { + pr_debug("Enabling tea5761 at GPIO %d\n", + enable_gpio); + + if (gpio_request(enable_gpio, "TEA5761 enable") < 0) { + printk(KERN_ERR "Can't request GPIO %d\n", + enable_gpio); + return -ENODEV; + } + + gpio_direction_output(enable_gpio, 0); + udelay(50); + gpio_set_value(enable_gpio, 1); + } + + return 0; +} + +static struct omap2_mcspi_device_config tsc2301_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, +}; + +static struct omap2_mcspi_device_config mipid_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, +}; + +static struct omap2_mcspi_device_config cx3110x_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, +}; + +#ifdef CONFIG_TOUCHSCREEN_TSC2005 +static struct tsc2005_platform_data tsc2005_config = { + .reset_gpio = 94, + .dav_gpio = 106 +}; + +static struct omap2_mcspi_device_config tsc2005_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, +}; +#endif + +static struct spi_board_info n800_spi_board_info[] __initdata = { + { + .modalias = "lcd_mipid", + .bus_num = 1, + .chip_select = 1, + .max_speed_hz = 4000000, + .controller_data= &mipid_mcspi_config, + .platform_data = &n800_mipid_platform_data, + }, { + .modalias = "cx3110x", + .bus_num = 2, + .chip_select = 0, + .max_speed_hz = 48000000, + .controller_data= &cx3110x_mcspi_config, + }, + { + .modalias = "tsc2301", + .bus_num = 1, + .chip_select = 0, + .max_speed_hz = 6000000, + .controller_data= &tsc2301_mcspi_config, + .platform_data = &tsc2301_config, + }, +}; + +static struct spi_board_info n810_spi_board_info[] __initdata = { + { + .modalias = "lcd_mipid", + .bus_num = 1, + .chip_select = 1, + .max_speed_hz = 4000000, + .controller_data = &mipid_mcspi_config, + .platform_data = &n800_mipid_platform_data, + }, + { + .modalias = "cx3110x", + .bus_num = 2, + .chip_select = 0, + .max_speed_hz = 48000000, + .controller_data = &cx3110x_mcspi_config, + }, + { + .modalias = "tsc2005", + .bus_num = 1, + .chip_select = 0, + .max_speed_hz = 6000000, + .controller_data = &tsc2005_mcspi_config, + .platform_data = &tsc2005_config, + }, +}; + +static void __init tsc2005_set_config(void) +{ + const struct omap_lcd_config *conf; + + conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config); + if (conf != NULL) { +#ifdef CONFIG_TOUCHSCREEN_TSC2005 + if (strcmp(conf->panel_name, "lph8923") == 0) { + tsc2005_config.ts_x_plate_ohm = 180; + tsc2005_config.ts_hw_avg = 0; + tsc2005_config.ts_ignore_last = 0; + tsc2005_config.ts_touch_pressure = 1500; + tsc2005_config.ts_stab_time = 100; + tsc2005_config.ts_pressure_max = 2048; + tsc2005_config.ts_pressure_fudge = 2; + tsc2005_config.ts_x_max = 4096; + tsc2005_config.ts_x_fudge = 4; + tsc2005_config.ts_y_max = 4096; + tsc2005_config.ts_y_fudge = 7; + } else if (strcmp(conf->panel_name, "ls041y3") == 0) { + tsc2005_config.ts_x_plate_ohm = 280; + tsc2005_config.ts_hw_avg = 0; + tsc2005_config.ts_ignore_last = 0; + tsc2005_config.ts_touch_pressure = 1500; + tsc2005_config.ts_stab_time = 1000; + tsc2005_config.ts_pressure_max = 2048; + tsc2005_config.ts_pressure_fudge = 2; + tsc2005_config.ts_x_max = 4096; + tsc2005_config.ts_x_fudge = 4; + tsc2005_config.ts_y_max = 4096; + tsc2005_config.ts_y_fudge = 7; + } else { + printk(KERN_ERR "Unknown panel type, set default " + "touchscreen configuration\n"); + tsc2005_config.ts_x_plate_ohm = 200; + tsc2005_config.ts_stab_time = 100; + } +#endif + } +} + +#if defined(CONFIG_CBUS_RETU) && defined(CONFIG_LEDS_OMAP_PWM) + +void retu_keypad_led_set_power(struct omap_pwm_led_platform_data *self, + int on_off) +{ + if (on_off) { + retu_write_reg(RETU_REG_CTRL_SET, 1 << 6); + msleep(2); + retu_write_reg(RETU_REG_CTRL_SET, 1 << 3); + } else { + retu_write_reg(RETU_REG_CTRL_CLR, (1 << 6) | (1 << 3)); + } +} + +static struct omap_pwm_led_platform_data n800_keypad_led_data = { + .name = "keypad", + .intensity_timer = 10, + .blink_timer = 9, + .set_power = retu_keypad_led_set_power, +}; + +static struct platform_device n800_keypad_led_device = { + .name = "omap_pwm_led", + .id = -1, + .dev = { + .platform_data = &n800_keypad_led_data, + }, +}; +#endif + +#if defined(CONFIG_TOUCHSCREEN_TSC2301) +static void __init n800_ts_set_config(void) +{ + const struct omap_lcd_config *conf; + + conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config); + if (conf != NULL) { + if (strcmp(conf->panel_name, "lph8923") == 0) { + tsc2301_config.ts_x_plate_ohm = 180; + tsc2301_config.ts_hw_avg = 8; + tsc2301_config.ts_max_pressure = 2048; + tsc2301_config.ts_touch_pressure = 400; + tsc2301_config.ts_stab_time = 100; + tsc2301_config.ts_pressure_fudge = 2; + tsc2301_config.ts_x_max = 4096; + tsc2301_config.ts_x_fudge = 4; + tsc2301_config.ts_y_max = 4096; + tsc2301_config.ts_y_fudge = 7; + } else if (strcmp(conf->panel_name, "ls041y3") == 0) { + tsc2301_config.ts_x_plate_ohm = 280; + tsc2301_config.ts_hw_avg = 8; + tsc2301_config.ts_touch_pressure = 400; + tsc2301_config.ts_max_pressure = 2048; + tsc2301_config.ts_stab_time = 1000; + tsc2301_config.ts_pressure_fudge = 2; + tsc2301_config.ts_x_max = 4096; + tsc2301_config.ts_x_fudge = 4; + tsc2301_config.ts_y_max = 4096; + tsc2301_config.ts_y_fudge = 7; + } else { + printk(KERN_ERR "Unknown panel type, set default " + "touchscreen configuration\n"); + tsc2301_config.ts_x_plate_ohm = 200; + tsc2301_config.ts_stab_time = 100; + } + } +} +#else +static inline void n800_ts_set_config(void) +{ +} +#endif + +static struct omap_gpio_switch n800_gpio_switches[] __initdata = { + { + .name = "bat_cover", + .gpio = -1, + .debounce_rising = 100, + .debounce_falling = 0, + .notify = n800_mmc_slot1_cover_handler, + .notify_data = NULL, + }, { + .name = "headphone", + .gpio = -1, + .debounce_rising = 200, + .debounce_falling = 200, + }, { + .name = "cam_act", + .gpio = -1, + .debounce_rising = 200, + .debounce_falling = 200, + }, { + .name = "cam_turn", + .gpio = -1, + .debounce_rising = 100, + .debounce_falling = 100, + }, +}; + +#if defined(CONFIG_CBUS_RETU_HEADSET) +static struct platform_device retu_headset_device = { + .name = "retu-headset", + .id = -1, +}; +#endif + +static struct platform_device *n800_devices[] __initdata = { +#if defined(CONFIG_CBUS_RETU) && defined(CONFIG_LEDS_OMAP_PWM) + &n800_keypad_led_device, +#endif +#if defined(CONFIG_CBUS_RETU_HEADSET) + &retu_headset_device, +#endif +}; + +#ifdef CONFIG_MENELAUS +static int n800_auto_sleep_regulators(void) +{ + u32 val; + int ret; + + val = EN_VPLL_SLEEP | EN_VMMC_SLEEP \ + | EN_VAUX_SLEEP | EN_VIO_SLEEP \ + | EN_VMEM_SLEEP | EN_DC3_SLEEP \ + | EN_VC_SLEEP | EN_DC2_SLEEP; + + ret = menelaus_set_regulator_sleep(1, val); + if (ret < 0) { + printk(KERN_ERR "Could not set regulators to sleep on " + "menelaus: %u\n", ret); + return ret; + } + return 0; +} + +static int n800_auto_voltage_scale(void) +{ + int ret; + + ret = menelaus_set_vcore_hw(1400, 1050); + if (ret < 0) { + printk(KERN_ERR "Could not set VCORE voltage on " + "menelaus: %u\n", ret); + return ret; + } + return 0; +} + +static int n800_menelaus_init(struct device *dev) +{ + int ret; + + ret = n800_auto_voltage_scale(); + if (ret < 0) + return ret; + ret = n800_auto_sleep_regulators(); + if (ret < 0) + return ret; + return 0; +} + +static struct menelaus_platform_data n800_menelaus_platform_data = { + .late_init = n800_menelaus_init, +}; +#endif + +static struct i2c_board_info __initdata n800_i2c_board_info_1[] = { + { + I2C_BOARD_INFO("menelaus", 0x72), + .irq = INT_24XX_SYS_NIRQ, + .platform_data = &n800_menelaus_platform_data, + }, +}; + +static struct lp5521_platform_data n810_lp5521_platform_data = { + .mode = LP5521_MODE_DIRECT_CONTROL, + .label = "n810", + .red_present = true, + .green_present = true, + .blue_present = true, +}; + +extern struct tcm825x_platform_data n800_tcm825x_platform_data; + +static struct i2c_board_info __initdata_or_module n8x0_i2c_board_info_2[] = { + { + I2C_BOARD_INFO(TCM825X_NAME, TCM825X_I2C_ADDR), +#if defined (CONFIG_VIDEO_TCM825X) || defined (CONFIG_VIDEO_TCM825X_MODULE) + .platform_data = &n800_tcm825x_platform_data, +#endif + }, +}; + + +static struct i2c_board_info __initdata_or_module n800_i2c_board_info_2[] = { + { + I2C_BOARD_INFO("tea5761", 0x10), + }, +}; + +static struct i2c_board_info __initdata_or_module n810_i2c_board_info_2[] = { + { + I2C_BOARD_INFO("lm8323", 0x45), + .irq = OMAP_GPIO_IRQ(109), + .platform_data = &lm8323_pdata, + }, + { + I2C_BOARD_INFO("tsl2563", 0x29), + }, + { + I2C_BOARD_INFO("lp5521", 0x32), + .platform_data = &n810_lp5521_platform_data, + }, +}; + +void __init nokia_n800_common_init(void) +{ + platform_add_devices(n800_devices, ARRAY_SIZE(n800_devices)); + + n800_flash_init(); + n800_mmc_init(); + n800_bt_init(); + n800_dsp_init(); + n800_usb_init(); + n800_cam_init(); + if (machine_is_nokia_n800()) + spi_register_board_info(n800_spi_board_info, + ARRAY_SIZE(n800_spi_board_info)); + if (machine_is_nokia_n810()) { + tsc2005_set_config(); + spi_register_board_info(n810_spi_board_info, + ARRAY_SIZE(n810_spi_board_info)); + } + omap_serial_init(); + omap_register_i2c_bus(1, 400, n800_i2c_board_info_1, + ARRAY_SIZE(n800_i2c_board_info_1)); + omap_register_i2c_bus(2, 400, n8x0_i2c_board_info_2, + ARRAY_SIZE(n8x0_i2c_board_info_2)); + if (machine_is_nokia_n800()) + i2c_register_board_info(2, n800_i2c_board_info_2, + ARRAY_SIZE(n800_i2c_board_info_2)); + if (machine_is_nokia_n810()) + i2c_register_board_info(2, n810_i2c_board_info_2, + ARRAY_SIZE(n810_i2c_board_info_2)); + + mipid_dev_init(); + blizzard_dev_init(); +} + +static void __init nokia_n800_init(void) +{ + nokia_n800_common_init(); + + n800_ts_set_config(); + tsc2301_dev_init(); + tea5761_dev_init(); + omap_register_gpio_switches(n800_gpio_switches, + ARRAY_SIZE(n800_gpio_switches)); +} + +void __init nokia_n800_map_io(void) +{ + omap_board_config = n800_config; + omap_board_config_size = ARRAY_SIZE(n800_config); + + omap2_set_globals_242x(); + omap2_map_common_io(); +} + +MACHINE_START(NOKIA_N800, "Nokia N800") + .phys_io = 0x48000000, + .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = nokia_n800_map_io, + .init_irq = nokia_n800_init_irq, + .init_machine = nokia_n800_init, + .timer = &omap_timer, +MACHINE_END diff --git a/arch/arm/mach-omap2/board-n800.h b/arch/arm/mach-omap2/board-n800.h new file mode 100644 index 00000000000..e71dae4722a --- /dev/null +++ b/arch/arm/mach-omap2/board-n800.h @@ -0,0 +1,23 @@ +/* + * linux/arch/arm/mach-omap2/board-n800.h + * + * Copyright (C) 2005-2007 Nokia Corporation + * Author: Lauri Leukkunen + * + * Modified from mach-omap2/board-n800.c + * + * 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. + */ + +#ifndef __ARCH_ARM_MACH_OMAP2_BOARD_N800_H +#define __ARCH_ARM_MACH_OMAP2_BOARD_N800_H + +void __init nokia_n800_common_init(void); +void __init nokia_n800_map_io(void); +void __init nokia_n800_init_irq(void); + +extern const struct tcm825x_platform_data n800_tcm825x_platform_data; + +#endif diff --git a/arch/arm/mach-omap2/board-n810.c b/arch/arm/mach-omap2/board-n810.c new file mode 100644 index 00000000000..7984d43aeec --- /dev/null +++ b/arch/arm/mach-omap2/board-n810.c @@ -0,0 +1,47 @@ +/* + * linux/arch/arm/mach-omap2/board-n810.c + * + * Copyright (C) 2007 Nokia + * Author: Lauri Leukkunen + * + * 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. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "board-n800.h" + +static void __init nokia_n810_init(void) +{ + nokia_n800_common_init(); +} + +MACHINE_START(NOKIA_N810, "Nokia N810") + .phys_io = 0x48000000, + .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = nokia_n800_map_io, + .init_irq = nokia_n800_init_irq, + .init_machine = nokia_n810_init, + .timer = &omap_timer, +MACHINE_END + +MACHINE_START(NOKIA_N810_WIMAX, "Nokia N810 WiMAX") + .phys_io = 0x48000000, + .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = nokia_n800_map_io, + .init_irq = nokia_n800_init_irq, + .init_machine = nokia_n810_init, + .timer = &omap_timer, +MACHINE_END diff --git a/arch/arm/mach-omap2/board-omap2evm.c b/arch/arm/mach-omap2/board-omap2evm.c new file mode 100644 index 00000000000..86477ccc996 --- /dev/null +++ b/arch/arm/mach-omap2/board-omap2evm.c @@ -0,0 +1,385 @@ +/* + * linux/arch/arm/mach-omap2/board-omap2evm.c + * + * Copyright (C) 2008 Mistral Solutions Pvt Ltd + * + * Modified from mach-omap2/board-generic.c + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mmc-twl4030.h" + +#define OMAP2EVM_ETHR_START 0x2c000000 +#define OMAP2EVM_ETHR_SIZE 1024 +#define OMAP2EVM_ETHR_GPIO_IRQ 149 +#define OMAP2_EVM_TS_GPIO 85 + +#define GPMC_OFF_CONFIG1_0 0x60 + +static struct mtd_partition omap2evm_nand_partitions[] = { + { + .name = "X-Loader", + .offset = 0, + .size = 1 * (64 * 2048), + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, + { + .name = "U-Boot", + .offset = MTDPART_OFS_APPEND, + .size = 3 * (64 * 2048), + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, + { + .name = "U-Boot Environment", + .offset = MTDPART_OFS_APPEND, + .size = 1 * (64 * 2048), + }, + { + .name = "Kernel", + .offset = MTDPART_OFS_APPEND, + .size = 16 * (64 * 2048), /* 2MB */ + }, + { + .name = "Ramdisk", + .offset = MTDPART_OFS_APPEND, + .size = 32 * (64 * 2048), /* 4MB */ + }, + { + .name = "Filesystem", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + } +}; + +static struct omap_nand_platform_data omap2evm_nand_data = { + .parts = omap2evm_nand_partitions, + .nr_parts = ARRAY_SIZE(omap2evm_nand_partitions), + .dma_channel = -1, /* disable DMA in OMAP NAND driver */ +}; + +static struct resource omap2evm_nand_resource = { + .flags = IORESOURCE_MEM, +}; + +static struct platform_device omap2evm_nand_device = { + .name = "omap2-nand", + .id = -1, + .dev = { + .platform_data = &omap2evm_nand_data, + }, + .num_resources = 1, + .resource = &omap2evm_nand_resource, +}; + +void __init omap2evm_flash_init(void) +{ + void __iomem *gpmc_base_add, *gpmc_cs_base_add; + unsigned char cs = 0; + + gpmc_base_add = (__force void __iomem *)OMAP243X_GPMC_VIRT; + while (cs < GPMC_CS_NUM) { + int ret = 0; + + /* Each GPMC set for a single CS is at offset 0x30 */ + gpmc_cs_base_add = (gpmc_base_add + GPMC_OFF_CONFIG1_0 + + (cs * 0x30)); + + /* xloader/Uboot would have programmed the NAND + * base address for us This is a ugly hack. The proper + * way of doing this is to pass the setup of u-boot up + * to kernel using kernel params - something on the + * lines of machineID. Check if Nand is + * configured */ + ret = __raw_readl(gpmc_cs_base_add + GPMC_CS_CONFIG1); + if ((ret & 0xC00) == (0x800)) { + /* Found it!! */ + printk(KERN_INFO "NAND: Found NAND on CS %d \n", cs); + break; + } + cs++; + } + if (cs >= GPMC_CS_NUM) { + printk(KERN_INFO "MTD: Unable to find MTD configuration in " + "GPMC - not registering.\n"); + return; + } + + omap2evm_nand_data.cs = cs; + omap2evm_nand_data.gpmc_cs_baseaddr = gpmc_cs_base_add; + omap2evm_nand_data.gpmc_baseaddr = gpmc_base_add; + + if (platform_device_register(&omap2evm_nand_device) < 0) { + printk(KERN_ERR "Unable to register NAND device\n"); + return; + } +} + +static struct resource omap2evm_smc911x_resources[] = { + [0] = { + .start = OMAP2EVM_ETHR_START, + .end = (OMAP2EVM_ETHR_START + OMAP2EVM_ETHR_SIZE - 1), + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = OMAP_GPIO_IRQ(OMAP2EVM_ETHR_GPIO_IRQ), + .end = OMAP_GPIO_IRQ(OMAP2EVM_ETHR_GPIO_IRQ), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device omap2evm_smc911x_device = { + .name = "smc911x", + .id = -1, + .num_resources = ARRAY_SIZE(omap2evm_smc911x_resources), + .resource = &omap2evm_smc911x_resources [0], +}; + +static inline void __init omap2evm_init_smc911x(void) +{ + int gpio = OMAP2EVM_ETHR_GPIO_IRQ; + int ret; + + ret = gpio_request(gpio, "smc911x IRQ"); + if (ret < 0) { + printk(KERN_ERR "Failed to request GPIO %d for smc911x IRQ\n", + gpio); + return; + } + gpio_direction_input(gpio); + +} + +static struct platform_device omap2_evm_lcd_device = { + .name = "omap2evm_lcd", + .id = -1, +}; + +static struct omap_lcd_config omap2_evm_lcd_config __initdata = { + .ctrl_name = "internal", +}; + +static void ads7846_dev_init(void) +{ + int gpio = OMAP2_EVM_TS_GPIO; + int ret; + + ret = gpio_request(gpio, "ads7846_pen_down"); + if (ret < 0) { + printk(KERN_ERR "Failed to request GPIO %d for ads7846 pen down IRQ\n", + gpio); + return; + } + + gpio_direction_input(gpio); + + /*Setting the MUX */ + omap_cfg_reg(Y18_2430_MCSPI1_CLK); + omap_cfg_reg(AD15_2430_MCSPI1_SIMO); + omap_cfg_reg(AE17_2430_MCSPI1_SOMI); + omap_cfg_reg(U1_2430_MCSPI1_CS0); + + omap_cfg_reg(AF19_2430_GPIO_85); + +} + +static int ads7846_get_pendown_state(void) +{ + return !gpio_get_value(OMAP2_EVM_TS_GPIO); +} + +struct ads7846_platform_data ads7846_config = { + .x_max = 0x0fff, + .y_max = 0x0fff, + .x_plate_ohms = 180, + .pressure_max = 255, + .debounce_max = 10, + .debounce_tol = 3, + .debounce_rep = 1, + .get_pendown_state = ads7846_get_pendown_state, + .keep_vref_on = 1, + .settle_delay_usecs = 150, +}; + +static struct omap2_mcspi_device_config ads7846_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, /* 0: slave, 1: master */ +}; + +struct spi_board_info omap2evm_spi_board_info[] = { + [0] = { + .modalias = "ads7846", + .bus_num = 1, + .chip_select = 0, + .max_speed_hz = 1500000, + .controller_data = &ads7846_mcspi_config, + .irq = OMAP_GPIO_IRQ(OMAP2_EVM_TS_GPIO), + .platform_data = &ads7846_config, + }, +}; + + +static int omap2evm_keymap[] = { + KEY(0, 0, KEY_LEFT), + KEY(0, 1, KEY_RIGHT), + KEY(0, 2, KEY_A), + KEY(0, 3, KEY_B), + KEY(1, 0, KEY_DOWN), + KEY(1, 1, KEY_UP), + KEY(1, 2, KEY_E), + KEY(1, 3, KEY_F), + KEY(2, 0, KEY_ENTER), + KEY(2, 1, KEY_I), + KEY(2, 2, KEY_J), + KEY(2, 3, KEY_K), + KEY(3, 0, KEY_M), + KEY(3, 1, KEY_N), + KEY(3, 2, KEY_O), + KEY(3, 3, KEY_P) +}; + +static struct twl4030_keypad_data omap2evm_kp_data = { + .rows = 4, + .cols = 4, + .keymap = omap2evm_keymap, + .keymapsize = ARRAY_SIZE(omap2evm_keymap), + .rep = 1, +}; + +static void __init omap2_evm_init_irq(void) +{ + omap2_init_common_hw(NULL); + omap_init_irq(); + omap_gpio_init(); + omap2evm_init_smc911x(); +} + +static struct omap_uart_config omap2_evm_uart_config __initdata = { + .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), +}; + +static struct omap_board_config_kernel omap2_evm_config[] __initdata = { + { OMAP_TAG_UART, &omap2_evm_uart_config }, + { OMAP_TAG_LCD, &omap2_evm_lcd_config }, +}; + +static struct twl4030_gpio_platform_data omap2evm_gpio_data = { + .gpio_base = OMAP_MAX_GPIO_LINES, + .irq_base = TWL4030_GPIO_IRQ_BASE, + .irq_end = TWL4030_GPIO_IRQ_END, +}; + +static struct twl4030_usb_data omap2evm_usb_data = { + .usb_mode = T2_USB_MODE_ULPI, +}; + +static struct twl4030_madc_platform_data omap2evm_madc_data = { + .irq_line = 1, +}; + +static struct twl4030_platform_data omap2evm_twldata = { + .irq_base = TWL4030_IRQ_BASE, + .irq_end = TWL4030_IRQ_END, + + /* platform_data for children goes here */ + .keypad = &omap2evm_kp_data, + .madc = &omap2evm_madc_data, + .usb = &omap2evm_usb_data, + .gpio = &omap2evm_gpio_data, +}; + +static struct i2c_board_info __initdata omap2evm_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("twl4030", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_24XX_SYS_NIRQ, + .platform_data = &omap2evm_twldata, + }, +}; + +static int __init omap2_evm_i2c_init(void) +{ + omap_register_i2c_bus(1, 400, NULL, 0); + omap_register_i2c_bus(2, 2600, omap2evm_i2c_boardinfo, + ARRAY_SIZE(omap2evm_i2c_boardinfo)); + return 0; +} + +static struct platform_device *omap2_evm_devices[] __initdata = { + &omap2_evm_lcd_device, + &omap2evm_smc911x_device, +}; + +static struct twl4030_hsmmc_info mmc[] __initdata = { + { + .mmc = 1, + .wires = 4, + .gpio_cd = -EINVAL, + .gpio_wp = -EINVAL, + }, + {} /* Terminator */ +}; + +static void __init omap2_evm_init(void) +{ + omap2_evm_i2c_init(); + + platform_add_devices(omap2_evm_devices, ARRAY_SIZE(omap2_evm_devices)); + omap_board_config = omap2_evm_config; + omap_board_config_size = ARRAY_SIZE(omap2_evm_config); + spi_register_board_info(omap2evm_spi_board_info, + ARRAY_SIZE(omap2evm_spi_board_info)); + omap_serial_init(); + twl4030_mmc_init(mmc); + omap2evm_flash_init(); + ads7846_dev_init(); +} + +static void __init omap2_evm_map_io(void) +{ + omap2_set_globals_243x(); + omap2_map_common_io(); +} + +MACHINE_START(OMAP2EVM, "OMAP2EVM Board") + /* Maintainer: Arun KS */ + .phys_io = 0x48000000, + .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = omap2_evm_map_io, + .init_irq = omap2_evm_init_irq, + .init_machine = omap2_evm_init, + .timer = &omap_timer, +MACHINE_END diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 744740ae1b9..346351e0fe8 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -37,14 +38,16 @@ #include #include +#include #include #include #include #include -#include +#include "twl4030-generic-scripts.h" #include "mmc-twl4030.h" + #define GPMC_CS0_BASE 0x60 #define GPMC_CS_SIZE 0x30 @@ -104,10 +107,16 @@ static struct platform_device omap3beagle_nand_device = { .resource = &omap3beagle_nand_resource, }; +#include "sdram-micron-mt46h32m32lf-6.h" + static struct omap_uart_config omap3_beagle_uart_config __initdata = { .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), }; +static struct twl4030_usb_data beagle_usb_data = { + .usb_mode = T2_USB_MODE_ULPI, +}; + static struct twl4030_hsmmc_info mmc[] = { { .mmc = 1, @@ -117,6 +126,14 @@ static struct twl4030_hsmmc_info mmc[] = { {} /* Terminator */ }; +static struct regulator_consumer_supply beagle_vmmc1_supply = { + .supply = "vmmc", +}; + +static struct regulator_consumer_supply beagle_vsim_supply = { + .supply = "vmmc_aux", +}; + static struct gpio_led gpio_leds[]; static int beagle_twl_gpio_setup(struct device *dev, @@ -127,6 +144,10 @@ static int beagle_twl_gpio_setup(struct device *dev, mmc[0].gpio_cd = gpio + 0; twl4030_mmc_init(mmc); + /* link regulators to MMC adapters */ + beagle_vmmc1_supply.dev = mmc[0].dev; + beagle_vsim_supply.dev = mmc[0].dev; + /* REVISIT: need ehci-omap hooks for external VBUS * power switch and overcurrent detect */ @@ -155,12 +176,114 @@ static struct twl4030_gpio_platform_data beagle_gpio_data = { .setup = beagle_twl_gpio_setup, }; +static struct platform_device omap3_beagle_lcd_device = { + .name = "omap3beagle_lcd", + .id = -1, +}; + +static struct regulator_consumer_supply beagle_vdac_supply = { + .supply = "vdac", + .dev = &omap3_beagle_lcd_device.dev, +}; + +static struct regulator_consumer_supply beagle_vdvi_supply = { + .supply = "vdvi", + .dev = &omap3_beagle_lcd_device.dev, +}; + +/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */ +static struct regulator_init_data beagle_vmmc1 = { + .constraints = { + .min_uV = 1850000, + .max_uV = 3150000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE + | REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &beagle_vmmc1_supply, +}; + +/* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */ +static struct regulator_init_data beagle_vsim = { + .constraints = { + .min_uV = 1800000, + .max_uV = 3000000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE + | REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &beagle_vsim_supply, +}; + +/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */ +static struct regulator_init_data beagle_vdac = { + .constraints = { + .min_uV = 1800000, + .max_uV = 1800000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &beagle_vdac_supply, +}; + +/* VPLL2 for digital video outputs */ +static struct regulator_init_data beagle_vpll2 = { + .constraints = { + .name = "VDVI", + .min_uV = 1800000, + .max_uV = 1800000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &beagle_vdvi_supply, +}; + +static const struct twl4030_resconfig beagle_resconfig[] = { + /* disable regulators that u-boot left enabled; the + * devices' drivers should be managing these. + */ + { .resource = RES_VAUX3, }, /* not even connected! */ + { .resource = RES_VMMC1, }, + { .resource = RES_VSIM, }, + { .resource = RES_VPLL2, }, + { .resource = RES_VDAC, }, + { .resource = RES_VUSB_1V5, }, + { .resource = RES_VUSB_1V8, }, + { .resource = RES_VUSB_3V1, }, + { 0, }, +}; + +static struct twl4030_power_data beagle_power_data = { + .resource_config = beagle_resconfig, + /* REVISIT can't use GENERIC3430_T2SCRIPTS_DATA; + * among other things, it makes reboot fail. + */ +}; + static struct twl4030_platform_data beagle_twldata = { .irq_base = TWL4030_IRQ_BASE, .irq_end = TWL4030_IRQ_END, /* platform_data for children goes here */ + .usb = &beagle_usb_data, .gpio = &beagle_gpio_data, + .power = &beagle_power_data, + .vmmc1 = &beagle_vmmc1, + .vsim = &beagle_vsim, + .vdac = &beagle_vdac, + .vpll2 = &beagle_vpll2, }; static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = { @@ -184,16 +307,11 @@ static int __init omap3_beagle_i2c_init(void) static void __init omap3_beagle_init_irq(void) { - omap2_init_common_hw(NULL); + omap2_init_common_hw(mt46h32m32lf6_sdrc_params); omap_init_irq(); omap_gpio_init(); } -static struct platform_device omap3_beagle_lcd_device = { - .name = "omap3beagle_lcd", - .id = -1, -}; - static struct omap_lcd_config omap3_beagle_lcd_config __initdata = { .ctrl_name = "internal", }; @@ -315,6 +433,7 @@ static void __init omap3_beagle_init(void) gpio_direction_output(170, true); usb_musb_init(); + usb_ehci_init(); omap3beagle_flash_init(); } diff --git a/arch/arm/mach-omap2/board-omap3evm-flash.c b/arch/arm/mach-omap2/board-omap3evm-flash.c new file mode 100644 index 00000000000..b58b7c6b1af --- /dev/null +++ b/arch/arm/mach-omap2/board-omap3evm-flash.c @@ -0,0 +1,192 @@ +/* + * board-omap3evm-flash.c + * + * Copyright (c) 2008 Texas Instruments, + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define ONENAND_MAP 0x20000000 + +static int omap3evm_onenand_setup(void __iomem *, int freq); + +static struct mtd_partition omap3evm_onenand_partitions[] = { + { + .name = "xloader-onenand", + .offset = 0, + .size = 4*(64*2048), + .mask_flags = MTD_WRITEABLE + }, + { + .name = "uboot-onenand", + .offset = MTDPART_OFS_APPEND, + .size = 15*(64*2048), + .mask_flags = MTD_WRITEABLE + }, + { + .name = "params-onenand", + .offset = MTDPART_OFS_APPEND, + .size = 1*(64*2048), + }, + { + .name = "linux-onenand", + .offset = MTDPART_OFS_APPEND, + .size = 40*(64*2048), + }, + { + .name = "jffs2-onenand", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct omap_onenand_platform_data omap3evm_onenand_data = { + .parts = omap3evm_onenand_partitions, + .nr_parts = ARRAY_SIZE(omap3evm_onenand_partitions), + .onenand_setup = omap3evm_onenand_setup, + .dma_channel = -1, /* disable DMA in OMAP OneNAND driver */ +}; + +static struct platform_device omap3evm_onenand_device = { + .name = "omap2-onenand", + .id = -1, + .dev = { + .platform_data = &omap3evm_onenand_data, + }, +}; + +static struct mtd_partition omap3evm_nand_partitions[] = { + /* All the partition sizes are listed in terms of NAND block size */ + { + .name = "xloader-nand", + .offset = 0, + .size = 4*(128 * 1024), + .mask_flags = MTD_WRITEABLE + }, + { + .name = "uboot-nand", + .offset = MTDPART_OFS_APPEND, + .size = 14*(128 * 1024), + .mask_flags = MTD_WRITEABLE + }, + { + .name = "params-nand", + + .offset = MTDPART_OFS_APPEND, + .size = 2*(128 * 1024) + }, + { + .name = "linux-nand", + .offset = MTDPART_OFS_APPEND, + .size = 40*(128 * 1024) + }, + { + .name = "jffs2-nand", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, + }, +}; + +static struct omap_nand_platform_data omap3evm_nand_data = { + .parts = omap3evm_nand_partitions, + .nr_parts = ARRAY_SIZE(omap3evm_nand_partitions), + .nand_setup = NULL, + .dma_channel = -1, /* disable DMA in OMAP NAND driver */ + .dev_ready = NULL, +}; + +static struct resource omap3evm_nand_resource = { + .flags = IORESOURCE_MEM, +}; + +static struct platform_device omap3evm_nand_device = { + .name = "omap2-nand", + .id = 0, + .dev = { + .platform_data = &omap3evm_nand_data, + }, + .num_resources = 1, + .resource = &omap3evm_nand_resource, +}; + +/* + * omap3evm_onenand_setup - Set the onenand sync mode + * @onenand_base: The onenand base address in GPMC memory map + * + */ + +static int omap3evm_onenand_setup(void __iomem *onenand_base, int freq) +{ + /* nothing is required to be setup for onenand as of now */ + return 0; +} + +void __init omap3evm_flash_init(void) +{ + u8 cs = 0; + u8 onenandcs = GPMC_CS_NUM + 1, nandcs = GPMC_CS_NUM + 1; + u32 gpmc_base_add = OMAP34XX_GPMC_VIRT; + + while (cs < GPMC_CS_NUM) { + u32 ret = 0; + ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + + /* + * xloader/Uboot would have programmed the NAND/oneNAND + * base address for us This is a ugly hack. The proper + * way of doing this is to pass the setup of u-boot up + * to kernel using kernel params - something on the + * lines of machineID. Check if NAND/oneNAND is configured + */ + if ((ret & 0xC00) == 0x800) { + /* Found it!! */ + if (nandcs > GPMC_CS_NUM) + nandcs = cs; + } else { + ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7); + if ((ret & 0x3F) == (ONENAND_MAP >> 24)) + onenandcs = cs; + } + cs++; + } + if ((nandcs > GPMC_CS_NUM) && (onenandcs > GPMC_CS_NUM)) { + printk(KERN_INFO "NAND/OneNAND: Unable to find configuration " + " in GPMC\n "); + return; + } + + if (nandcs < GPMC_CS_NUM) { + omap3evm_nand_data.cs = nandcs; + omap3evm_nand_data.gpmc_cs_baseaddr = (void *)(gpmc_base_add + + GPMC_CS0_BASE + nandcs*GPMC_CS_SIZE); + omap3evm_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add); + + if (platform_device_register(&omap3evm_nand_device) < 0) { + printk(KERN_ERR "Unable to register NAND device\n"); + } + } + + if (onenandcs < GPMC_CS_NUM) { + omap3evm_onenand_data.cs = onenandcs; + if (platform_device_register(&omap3evm_onenand_device) < 0) + printk(KERN_ERR "Unable to register OneNAND device\n"); + } +} + diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c new file mode 100644 index 00000000000..6eb3c523091 --- /dev/null +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -0,0 +1,333 @@ +/* + * linux/arch/arm/mach-omap2/board-omap3evm.c + * + * Copyright (C) 2008 Texas Instruments + * + * Modified from mach-omap2/board-3430sdp.c + * + * Initial code: Syed Mohammed Khasim + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "sdram-micron-mt46h32m32lf-6.h" +#include "twl4030-generic-scripts.h" +#include "mmc-twl4030.h" + +#define OMAP3_EVM_TS_GPIO 175 + +#define OMAP3EVM_ETHR_START 0x2c000000 +#define OMAP3EVM_ETHR_SIZE 1024 +#define OMAP3EVM_ETHR_GPIO_IRQ 176 +#define OMAP3EVM_SMC911X_CS 5 + +extern void omap3evm_flash_init(void); + +static struct resource omap3evm_smc911x_resources[] = { + [0] = { + .start = OMAP3EVM_ETHR_START, + .end = (OMAP3EVM_ETHR_START + OMAP3EVM_ETHR_SIZE - 1), + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = OMAP_GPIO_IRQ(OMAP3EVM_ETHR_GPIO_IRQ), + .end = OMAP_GPIO_IRQ(OMAP3EVM_ETHR_GPIO_IRQ), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device omap3evm_smc911x_device = { + .name = "smc911x", + .id = -1, + .num_resources = ARRAY_SIZE(omap3evm_smc911x_resources), + .resource = &omap3evm_smc911x_resources [0], +}; + +static inline void __init omap3evm_init_smc911x(void) +{ + int eth_cs; + struct clk *l3ck; + unsigned int rate; + + eth_cs = OMAP3EVM_SMC911X_CS; + + l3ck = clk_get(NULL, "l3_ck"); + if (IS_ERR(l3ck)) + rate = 100000000; + else + rate = clk_get_rate(l3ck); + + if (gpio_request(OMAP3EVM_ETHR_GPIO_IRQ, "SMC911x irq") < 0) { + printk(KERN_ERR "Failed to request GPIO%d for smc911x IRQ\n", + OMAP3EVM_ETHR_GPIO_IRQ); + return; + } + + gpio_direction_input(OMAP3EVM_ETHR_GPIO_IRQ); +} + +static struct omap_uart_config omap3_evm_uart_config __initdata = { + .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), +}; + +static struct twl4030_hsmmc_info mmc[] = { + { + .mmc = 1, + .wires = 4, + .gpio_cd = -EINVAL, + .gpio_wp = 63, + }, + {} /* Terminator */ +}; + +static struct gpio_led gpio_leds[] = { + { + .name = "omap3evm::ledb", + /* normally not visible (board underside) */ + .default_trigger = "default-on", + .gpio = -EINVAL, /* gets replaced */ + .active_low = true, + }, +}; + +static struct gpio_led_platform_data gpio_led_info = { + .leds = gpio_leds, + .num_leds = ARRAY_SIZE(gpio_leds), +}; + +static struct platform_device leds_gpio = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &gpio_led_info, + }, +}; + + +static int omap3evm_twl_gpio_setup(struct device *dev, + unsigned gpio, unsigned ngpio) +{ + /* gpio + 0 is "mmc0_cd" (input/IRQ) */ + omap_cfg_reg(L8_34XX_GPIO63); + mmc[0].gpio_cd = gpio + 0; + twl4030_mmc_init(mmc); + + /* Most GPIOs are for USB OTG. Some are mostly sent to + * the P2 connector; notably LEDA for the LCD backlight. + */ + + /* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */ + gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1; + + platform_device_register(&leds_gpio); + + return 0; +} + +static struct twl4030_gpio_platform_data omap3evm_gpio_data = { + .gpio_base = OMAP_MAX_GPIO_LINES, + .irq_base = TWL4030_GPIO_IRQ_BASE, + .irq_end = TWL4030_GPIO_IRQ_END, + .use_leds = true, + .setup = omap3evm_twl_gpio_setup, +}; + +static struct twl4030_usb_data omap3evm_usb_data = { + .usb_mode = T2_USB_MODE_ULPI, +}; + +static int omap3evm_keymap[] = { + KEY(0, 0, KEY_LEFT), + KEY(0, 1, KEY_RIGHT), + KEY(0, 2, KEY_A), + KEY(0, 3, KEY_B), + KEY(1, 0, KEY_DOWN), + KEY(1, 1, KEY_UP), + KEY(1, 2, KEY_E), + KEY(1, 3, KEY_F), + KEY(2, 0, KEY_ENTER), + KEY(2, 1, KEY_I), + KEY(2, 2, KEY_J), + KEY(2, 3, KEY_K), + KEY(3, 0, KEY_M), + KEY(3, 1, KEY_N), + KEY(3, 2, KEY_O), + KEY(3, 3, KEY_P) +}; + +static struct twl4030_keypad_data omap3evm_kp_data = { + .rows = 4, + .cols = 4, + .keymap = omap3evm_keymap, + .keymapsize = ARRAY_SIZE(omap3evm_keymap), + .rep = 1, +}; + +static struct twl4030_madc_platform_data omap3evm_madc_data = { + .irq_line = 1, +}; + +static struct twl4030_platform_data omap3evm_twldata = { + .irq_base = TWL4030_IRQ_BASE, + .irq_end = TWL4030_IRQ_END, + + /* platform_data for children goes here */ + .keypad = &omap3evm_kp_data, + .madc = &omap3evm_madc_data, + .usb = &omap3evm_usb_data, + .power = GENERIC3430_T2SCRIPTS_DATA, + .gpio = &omap3evm_gpio_data, +}; + +static struct i2c_board_info __initdata omap3evm_i2c_boardinfo[] = { + { + I2C_BOARD_INFO("twl4030", 0x48), + .flags = I2C_CLIENT_WAKE, + .irq = INT_34XX_SYS_NIRQ, + .platform_data = &omap3evm_twldata, + }, +}; + +static int __init omap3_evm_i2c_init(void) +{ + omap_register_i2c_bus(1, 2600, omap3evm_i2c_boardinfo, + ARRAY_SIZE(omap3evm_i2c_boardinfo)); + omap_register_i2c_bus(2, 400, NULL, 0); + omap_register_i2c_bus(3, 400, NULL, 0); + return 0; +} + +static struct platform_device omap3_evm_lcd_device = { + .name = "omap3evm_lcd", + .id = -1, +}; + +static struct omap_lcd_config omap3_evm_lcd_config __initdata = { + .ctrl_name = "internal", +}; + +static void ads7846_dev_init(void) +{ + if (gpio_request(OMAP3_EVM_TS_GPIO, "ADS7846 pendown") < 0) + printk(KERN_ERR "can't get ads7846 pen down GPIO\n"); + + gpio_direction_input(OMAP3_EVM_TS_GPIO); + + omap_set_gpio_debounce(OMAP3_EVM_TS_GPIO, 1); + omap_set_gpio_debounce_time(OMAP3_EVM_TS_GPIO, 0xa); +} + +static int ads7846_get_pendown_state(void) +{ + return !gpio_get_value(OMAP3_EVM_TS_GPIO); +} + +struct ads7846_platform_data ads7846_config = { + .x_max = 0x0fff, + .y_max = 0x0fff, + .x_plate_ohms = 180, + .pressure_max = 255, + .debounce_max = 10, + .debounce_tol = 3, + .debounce_rep = 1, + .get_pendown_state = ads7846_get_pendown_state, + .keep_vref_on = 1, + .settle_delay_usecs = 150, +}; + +static struct omap2_mcspi_device_config ads7846_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, /* 0: slave, 1: master */ +}; + +struct spi_board_info omap3evm_spi_board_info[] = { + [0] = { + .modalias = "ads7846", + .bus_num = 1, + .chip_select = 0, + .max_speed_hz = 1500000, + .controller_data = &ads7846_mcspi_config, + .irq = OMAP_GPIO_IRQ(OMAP3_EVM_TS_GPIO), + .platform_data = &ads7846_config, + }, +}; + +static void __init omap3_evm_init_irq(void) +{ + omap2_init_common_hw(mt46h32m32lf6_sdrc_params); + omap_init_irq(); + omap_gpio_init(); + omap3evm_init_smc911x(); +} + +static struct omap_board_config_kernel omap3_evm_config[] __initdata = { + { OMAP_TAG_UART, &omap3_evm_uart_config }, + { OMAP_TAG_LCD, &omap3_evm_lcd_config }, +}; + +static struct platform_device *omap3_evm_devices[] __initdata = { + &omap3_evm_lcd_device, + &omap3evm_smc911x_device, +}; + +static void __init omap3_evm_init(void) +{ + omap3_evm_i2c_init(); + + platform_add_devices(omap3_evm_devices, ARRAY_SIZE(omap3_evm_devices)); + omap_board_config = omap3_evm_config; + omap_board_config_size = ARRAY_SIZE(omap3_evm_config); + + spi_register_board_info(omap3evm_spi_board_info, + ARRAY_SIZE(omap3evm_spi_board_info)); + + omap_serial_init(); + usb_musb_init(); + usb_ehci_init(); + omap3evm_flash_init(); + ads7846_dev_init(); +} + +static void __init omap3_evm_map_io(void) +{ + omap2_set_globals_343x(); + omap2_map_common_io(); +} + +MACHINE_START(OMAP3EVM, "OMAP3 EVM") + /* Maintainer: Syed Mohammed Khasim - Texas Instruments */ + .phys_io = 0x48000000, + .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = omap3_evm_map_io, + .init_irq = omap3_evm_init_irq, + .init_machine = omap3_evm_init, + .timer = &omap_timer, +MACHINE_END diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index 402f09c6cf1..c67f62ff885 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -17,7 +17,11 @@ * */ +#include +#include +#include #include +#include #include #include @@ -25,21 +29,119 @@ #include #include +#include +#include +#include + #include #include +#include #include #include #include #include +#include #include -#include +#include #include +#include +#include "sdram-micron-mt46h32m32lf-6.h" #include "mmc-twl4030.h" + +#define NAND_BLOCK_SIZE SZ_128K +#define GPMC_CS0_BASE 0x60 +#define GPMC_CS_SIZE 0x30 + #define OMAP3_PANDORA_TS_GPIO 94 +static struct mtd_partition omap3pandora_nand_partitions[] = { + { + .name = "xloader", + .offset = 0, /* Offset = 0x00000 */ + .size = 4 * NAND_BLOCK_SIZE, + .mask_flags = MTD_WRITEABLE + }, { + .name = "uboot", + .offset = MTDPART_OFS_APPEND, /* Offset = 0x80000 */ + .size = 14 * NAND_BLOCK_SIZE, + }, { + .name = "uboot environment", + .offset = MTDPART_OFS_APPEND, /* Offset = 0x240000 */ + .size = 2 * NAND_BLOCK_SIZE, + }, { + .name = "linux", + .offset = MTDPART_OFS_APPEND, /* Offset = 0x280000 */ + .size = 32 * NAND_BLOCK_SIZE, + }, { + .name = "rootfs", + .offset = MTDPART_OFS_APPEND, /* Offset = 0x680000 */ + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct omap_nand_platform_data omap3pandora_nand_data = { + .parts = omap3pandora_nand_partitions, + .nr_parts = ARRAY_SIZE(omap3pandora_nand_partitions), + .dma_channel = -1, /* disable DMA in OMAP NAND driver */ +}; + +static struct resource omap3pandora_nand_resource[] = { + { + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device omap3pandora_nand_device = { + .name = "omap2-nand", + .id = -1, + .dev = { + .platform_data = &omap3pandora_nand_data, + }, + .num_resources = ARRAY_SIZE(omap3pandora_nand_resource), + .resource = omap3pandora_nand_resource, +}; + +static void __init omap3pandora_flash_init(void) +{ + u8 cs = 0; + u8 nandcs = GPMC_CS_NUM + 1; + + u32 gpmc_base_add = OMAP34XX_GPMC_VIRT; + + /* find out the chip-select on which NAND exists */ + while (cs < GPMC_CS_NUM) { + u32 ret = 0; + ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + + if ((ret & 0xC00) == 0x800) { + printk(KERN_INFO "Found NAND on CS%d\n", cs); + if (nandcs > GPMC_CS_NUM) + nandcs = cs; + } + cs++; + } + + if (nandcs > GPMC_CS_NUM) { + printk(KERN_INFO "NAND: Unable to find configuration " + "in GPMC\n "); + return; + } + + if (nandcs < GPMC_CS_NUM) { + omap3pandora_nand_data.cs = nandcs; + omap3pandora_nand_data.gpmc_cs_baseaddr = (void *) + (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE); + omap3pandora_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add); + + printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); + if (platform_device_register(&omap3pandora_nand_device) < 0) + printk(KERN_ERR "Unable to register NAND device\n"); + } +} + static struct twl4030_hsmmc_info omap3pandora_mmc[] = { { .mmc = 1, @@ -118,7 +220,7 @@ static int __init omap3pandora_i2c_init(void) static void __init omap3pandora_init_irq(void) { - omap2_init_common_hw(NULL); + omap2_init_common_hw(mt46h32m32lf6_sdrc_params); omap_init_irq(); omap_gpio_init(); } @@ -200,8 +302,10 @@ static void __init omap3pandora_init(void) omap_serial_init(); spi_register_board_info(omap3pandora_spi_board_info, ARRAY_SIZE(omap3pandora_spi_board_info)); - omap3pandora_ads7846_init(); usb_musb_init(); + usb_ehci_init(); + omap3pandora_flash_init(); + omap3pandora_ads7846_init(); } static void __init omap3pandora_map_io(void) diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index b3f6e9d8180..f9cc015d36d 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,8 @@ #include #include +#include "sdram-micron-mt46h32m32lf-6.h" +#include "twl4030-generic-scripts.h" #include "mmc-twl4030.h" #define OVERO_GPIO_BT_XGATE 15 @@ -57,6 +60,70 @@ #define GPMC_CS0_BASE 0x60 #define GPMC_CS_SIZE 0x30 +#define OVERO_SMSC911X_CS 5 +#define OVERO_SMSC911X_GPIO 176 + +#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) + +#include + +static struct resource overo_smsc911x_resources[] = { + { + .name = "smsc911x-memory", + .flags = IORESOURCE_MEM, + }, + { + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, + }, +}; + +static struct smsc911x_platform_config overo_smsc911x_config = { + .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, + .irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN, + .flags = SMSC911X_USE_32BIT , + .phy_interface = PHY_INTERFACE_MODE_MII, +}; + +static struct platform_device overo_smsc911x_device = { + .name = "smsc911x", + .id = -1, + .num_resources = ARRAY_SIZE(overo_smsc911x_resources), + .resource = &overo_smsc911x_resources, + .dev = { + .platform_data = &overo_smsc911x_config, + }, +}; + +static inline void __init overo_init_smsc911x(void) +{ + unsigned long cs_mem_base; + + if (gpmc_cs_request(OVERO_SMSC911X_CS, SZ_16M, &cs_mem_base) < 0) { + printk(KERN_ERR "Failed request for GPMC mem for smsc911x\n"); + return; + } + + overo_smsc911x_resources[0].start = cs_mem_base + 0x0; + overo_smsc911x_resources[0].end = cs_mem_base + 0xff; + + if ((gpio_request(OVERO_SMSC911X_GPIO, "SMSC911X IRQ") == 0) && + (gpio_direction_input(OVERO_SMSC911X_GPIO) == 0)) { + gpio_export(OVERO_SMSC911X_GPIO, 0); + } else { + printk(KERN_ERR "could not obtain gpio for SMSC911X IRQ\n"); + return; + } + + overo_smsc911x_resources[1].start = OMAP_GPIO_IRQ(OVERO_SMSC911X_GPIO); + overo_smsc911x_resources[1].end = 0; + + platform_device_register(&overo_smsc911x_device); +} + +#else +static inline void __init overo_init_smsc911x(void) { return; } +#endif + #if defined(CONFIG_TOUCHSCREEN_ADS7846) || \ defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE) @@ -69,6 +136,7 @@ static struct omap2_mcspi_device_config ads7846_mcspi_config = { .single_channel = 1, /* 0: slave, 1: master */ }; + static int ads7846_get_pendown_state(void) { return !gpio_get_value(OVERO_GPIO_PENDOWN); @@ -207,21 +275,77 @@ static struct omap_uart_config overo_uart_config __initdata = { .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), }; +static struct twl4030_hsmmc_info mmc[] = { + { + .mmc = 1, + .wires = 4, + .gpio_cd = -EINVAL, + .gpio_wp = -EINVAL, + }, + { + .mmc = 2, + .wires = 4, + .gpio_cd = -EINVAL, + .gpio_wp = -EINVAL, + .transceiver = true, + .ocr_mask = 0x00100000, /* 3.3V */ + }, + {} /* Terminator */ +}; + +static struct regulator_consumer_supply overo_vmmc1_supply = { + .supply = "vmmc", +}; + +static int overo_twl_gpio_setup(struct device *dev, + unsigned gpio, unsigned ngpio) +{ + twl4030_mmc_init(mmc); + + overo_vmmc1_supply.dev = mmc[0].dev; + + return 0; +} + static struct twl4030_gpio_platform_data overo_gpio_data = { .gpio_base = OMAP_MAX_GPIO_LINES, .irq_base = TWL4030_GPIO_IRQ_BASE, .irq_end = TWL4030_GPIO_IRQ_END, + .setup = overo_twl_gpio_setup, +}; + +static struct twl4030_usb_data overo_usb_data = { + .usb_mode = T2_USB_MODE_ULPI, +}; + +static struct regulator_init_data overo_vmmc1 = { + .constraints = { + .min_uV = 1850000, + .max_uV = 3150000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE + | REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &overo_vmmc1_supply, }; +/* mmc2 (WLAN) and Bluetooth don't use twl4030 regulators */ + static struct twl4030_platform_data overo_twldata = { .irq_base = TWL4030_IRQ_BASE, .irq_end = TWL4030_IRQ_END, .gpio = &overo_gpio_data, + .usb = &overo_usb_data, + .power = GENERIC3430_T2SCRIPTS_DATA, + .vmmc1 = &overo_vmmc1, }; static struct i2c_board_info __initdata overo_i2c_boardinfo[] = { { - I2C_BOARD_INFO("twl4030", 0x48), + I2C_BOARD_INFO("tps65950", 0x48), .flags = I2C_CLIENT_WAKE, .irq = INT_34XX_SYS_NIRQ, .platform_data = &overo_twldata, @@ -239,7 +363,7 @@ static int __init overo_i2c_init(void) static void __init overo_init_irq(void) { - omap2_init_common_hw(NULL); + omap2_init_common_hw(mt46h32m32lf6_sdrc_params); omap_init_irq(); omap_gpio_init(); } @@ -262,23 +386,6 @@ static struct platform_device *overo_devices[] __initdata = { &overo_lcd_device, }; -static struct twl4030_hsmmc_info mmc[] __initdata = { - { - .mmc = 1, - .wires = 4, - .gpio_cd = -EINVAL, - .gpio_wp = -EINVAL, - }, - { - .mmc = 2, - .wires = 4, - .gpio_cd = -EINVAL, - .gpio_wp = -EINVAL, - .transceiver = true, - }, - {} /* Terminator */ -}; - static void __init overo_init(void) { overo_i2c_init(); @@ -286,9 +393,10 @@ static void __init overo_init(void) omap_board_config = overo_config; omap_board_config_size = ARRAY_SIZE(overo_config); omap_serial_init(); - twl4030_mmc_init(mmc); - overo_flash_init(); usb_musb_init(); + usb_ehci_init(); + overo_flash_init(); + overo_init_smsc911x(); overo_ads7846_init(); if ((gpio_request(OVERO_GPIO_W2W_NRESET, diff --git a/arch/arm/mach-omap2/board-rx51-flash.c b/arch/arm/mach-omap2/board-rx51-flash.c new file mode 100644 index 00000000000..f3b7eaf5d8d --- /dev/null +++ b/arch/arm/mach-omap2/board-rx51-flash.c @@ -0,0 +1,21 @@ +/* + * linux/arch/arm/mach-omap2/board-rx51-flash.c + * + * Copyright (C) 2008 Nokia + * + * 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. + */ + +#include +#include +#include + +extern void __init n800_flash_init(void); + +void __init rx51_flash_init(void) +{ + n800_flash_init(); +} + diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index a7381729645..22183aff166 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -13,29 +13,34 @@ #include #include #include +#include #include #include #include #include #include -#include #include +#include #include #include #include #include #include -#include #include "mmc-twl4030.h" +#define SYSTEM_REV_B_USES_VAUX3 0x1699 +#define SYSTEM_REV_S_USES_VAUX3 0x8 #define SMC91X_CS 1 #define SMC91X_GPIO_IRQ 54 #define SMC91X_GPIO_RESET 164 #define SMC91X_GPIO_PWRDWN 86 +#define RX51_TSC2005_RESET_GPIO 104 +#define RX51_TSC2005_IRQ_GPIO 100 + static struct resource rx51_smc91x_resources[] = { [0] = { .flags = IORESOURCE_MEM, @@ -52,6 +57,38 @@ static struct platform_device rx51_smc91x_device = { .resource = rx51_smc91x_resources, }; +static struct tsc2005_platform_data tsc2005_config = { + .reset_gpio = RX51_TSC2005_RESET_GPIO, /* not used */ + + .ts_x_plate_ohm = 280, + .ts_hw_avg = 0, + .ts_touch_pressure = 1500, + .ts_stab_time = 1000, + .ts_pressure_max = 2048, + .ts_pressure_fudge = 2, + .ts_x_max = 4096, + .ts_x_fudge = 4, + .ts_y_max = 4096, + .ts_y_fudge = 7, +}; + +static struct omap2_mcspi_device_config tsc2005_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, +}; + +static struct spi_board_info rx51_peripherals_spi_board_info[] = { + [0] = { + .modalias = "tsc2005", + .bus_num = 1, + .chip_select = 0, + .irq = OMAP_GPIO_IRQ(RX51_TSC2005_IRQ_GPIO), + .max_speed_hz = 6000000, + .controller_data = &tsc2005_mcspi_config, + .platform_data = &tsc2005_config, + }, +}; + static int rx51_keymap[] = { KEY(0, 0, KEY_Q), KEY(0, 1, KEY_W), @@ -199,6 +236,18 @@ free1: printk(KERN_ERR "Could not initialize smc91x\n"); } +static void __init rx51_init_tsc2005(void) +{ + int r; + + r = gpio_request(RX51_TSC2005_IRQ_GPIO, "tsc2005 DAV IRQ"); + if (r >= 0) { + gpio_direction_input(RX51_TSC2005_IRQ_GPIO); + } else { + printk(KERN_ERR "unable to get DAV GPIO"); + } +} + static struct twl4030_madc_platform_data rx51_madc_data = { .irq_line = 1, }; @@ -259,7 +308,7 @@ static struct regulator_init_data rx51_vaux2 = { }; /* VAUX3 - adds more power to VIO_18 rail */ -static struct regulator_init_data rx51_vaux3 = { +static struct regulator_init_data rx51_vaux3_cam = { .constraints = { .name = "VCAM_DIG_18", .min_uV = 1800000, @@ -272,6 +321,22 @@ static struct regulator_init_data rx51_vaux3 = { }, }; +static struct regulator_init_data rx51_vaux3_mmc = { + .constraints = { + .name = "VMMC2_30", + .min_uV = 2800000, + .max_uV = 3000000, + .apply_uV = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE + | REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &rx51_vmmc2_supply, +}; + static struct regulator_init_data rx51_vaux4 = { .constraints = { .name = "VCAM_ANA_28", @@ -382,10 +447,8 @@ static struct twl4030_platform_data rx51_twldata = { .vaux1 = &rx51_vaux1, .vaux2 = &rx51_vaux2, - .vaux3 = &rx51_vaux3, .vaux4 = &rx51_vaux4, .vmmc1 = &rx51_vmmc1, - .vmmc2 = &rx51_vmmc2, .vsim = &rx51_vsim, .vdac = &rx51_vdac, }; @@ -401,6 +464,13 @@ static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_1[] = { static int __init rx51_i2c_init(void) { + if ((system_rev >= SYSTEM_REV_S_USES_VAUX3 && system_rev < 0x100) || + system_rev >= SYSTEM_REV_B_USES_VAUX3) + rx51_twldata.vaux3 = &rx51_vaux3_mmc; + else { + rx51_twldata.vaux3 = &rx51_vaux3_cam; + rx51_twldata.vmmc2 = &rx51_vmmc2; + } omap_register_i2c_bus(1, 2600, rx51_peripherals_i2c_board_info_1, ARRAY_SIZE(rx51_peripherals_i2c_board_info_1)); omap_register_i2c_bus(2, 100, NULL, 0); @@ -413,7 +483,10 @@ void __init rx51_peripherals_init(void) { platform_add_devices(rx51_peripherals_devices, ARRAY_SIZE(rx51_peripherals_devices)); + spi_register_board_info(rx51_peripherals_spi_board_info, + ARRAY_SIZE(rx51_peripherals_spi_board_info)); rx51_i2c_init(); rx51_init_smc91x(); + rx51_init_tsc2005(); } diff --git a/arch/arm/mach-omap2/board-rx51-sdram.c b/arch/arm/mach-omap2/board-rx51-sdram.c new file mode 100644 index 00000000000..32b5da412af --- /dev/null +++ b/arch/arm/mach-omap2/board-rx51-sdram.c @@ -0,0 +1,219 @@ +/* + * SDRC register values for the Samsung K4X1G323PC + * + * Copyright (C) 2008 Nokia Corporation + * + * Lauri Leukkunen + * + * Original code by Juha Yrjölä + * + * 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. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + + +/* In picoseconds, except for tREF */ +struct sdram_timings { + u32 casl; + u32 tDAL; + u32 tDPL; + u32 tRRD; + u32 tRCD; + u32 tRP; + u32 tRAS; + u32 tRC; + u32 tRFC; + u32 tXSR; + + u32 tREF; /* in ms */ +}; + +struct sdram_info { + u8 row_lines; +}; + + +struct omap_sdrc_params rx51_sdrc_params[2]; + +static const struct sdram_timings rx51_timings[] = { + { + .casl = 3, + .tDAL = 15000 + 18000, + .tDPL = 15000, + .tRRD = 12000, + .tRCD = 18000, + .tRP = 18000, + .tRAS = 42000, + .tRC = 66000, + .tRFC = 97500, + .tXSR = 120000, + + .tREF = 64, + }, +}; + +static const struct sdram_info rx51_info = { + .row_lines = 13, +}; + +#define CM_BASE 0x48004000 + +#define CM_CLKSEL_CORE 0x0a40 +#define CM_CLKSEL1_PLL 0x0d40 + +#define PRM_CLKSEL 0x48306d40 +#define PRM_CLKSRC_CTRL 0x48307270 + +static u32 cm_base = CM_BASE; + +static inline u32 cm_read_reg(int idx) +{ + return *(u32 *)OMAP2_IO_ADDRESS(cm_base + idx); +} + +static const unsigned long sys_clk_rate_table[] = { + 12000, 13000, 19200, 26000, 38400, 16800 +}; + +static unsigned long get_sys_clk_rate(void) +{ + unsigned long rate; + + rate = sys_clk_rate_table[*(u32 *)OMAP2_IO_ADDRESS(PRM_CLKSEL) & 0x07]; + if (((*(u32 *)OMAP2_IO_ADDRESS(PRM_CLKSRC_CTRL) >> 6) & 0x03) == 0x02) + rate /= 2; + return rate; +} + +static unsigned long get_core_rate(void) +{ + unsigned long rate; + u32 l; + + l = cm_read_reg(CM_CLKSEL1_PLL); + rate = get_sys_clk_rate(); + rate *= ((l >> 16) & 0x7ff); + rate /= ((l >> 8) & 0x7f) + 1; + rate /= (l >> 27) & 0x1f; + + return rate; +} + +static unsigned long get_l3_rate(void) +{ + u32 l; + + l = cm_read_reg(CM_CLKSEL_CORE); + return get_core_rate() / (l & 0x03); +} + + + +static unsigned long sdrc_get_fclk_period(void) +{ + /* In picoseconds */ + return 1000000000 / get_l3_rate(); +} + +static unsigned int sdrc_ps_to_ticks(unsigned int time_ps) +{ + unsigned long tick_ps; + + /* Calculate in picosecs to yield more exact results */ + tick_ps = sdrc_get_fclk_period(); + + return (time_ps + tick_ps - 1) / tick_ps; +} +#undef DEBUG +#ifdef DEBUG +static int set_sdrc_timing_regval(u32 *regval, int st_bit, int end_bit, + int time, const char *name) +#else +static int set_sdrc_timing_regval(u32 *regval, int st_bit, int end_bit, + int time) +#endif +{ + int ticks, mask, nr_bits; + + if (time == 0) + ticks = 0; + else + ticks = sdrc_ps_to_ticks(time); + nr_bits = end_bit - st_bit + 1; + if (ticks >= 1 << nr_bits) + return -1; + mask = (1 << nr_bits) - 1; + *regval &= ~(mask << st_bit); + *regval |= ticks << st_bit; +#ifdef DEBUG + printk("SDRC %s: %i ticks %i ns\n", name, ticks, + (unsigned int)sdrc_get_fclk_period() * ticks / 1000); +#endif + + return 0; +} + +#ifdef DEBUG +#define SDRC_SET_ONE(reg, st, end, field) \ + if (set_sdrc_timing_regval((reg), (st), (end), rx51_timings->field, #field) < 0) \ + err = -1 +#else +#define SDRC_SET_ONE(reg, st, end, field) \ + if (set_sdrc_timing_regval((reg), (st), (end), rx51_timings->field) < 0) \ + err = -1 +#endif + +struct omap_sdrc_params *rx51_get_sdram_timings(void) +{ + u32 ticks_per_ms; + u32 rfr, l; + u32 actim_ctrla, actim_ctrlb; + u32 rfr_ctrl; + int err = 0; + + SDRC_SET_ONE(&actim_ctrla, 0, 4, tDAL); + SDRC_SET_ONE(&actim_ctrla, 6, 8, tDPL); + SDRC_SET_ONE(&actim_ctrla, 9, 11, tRRD); + SDRC_SET_ONE(&actim_ctrla, 12, 14, tRCD); + SDRC_SET_ONE(&actim_ctrla, 15, 17, tRP); + SDRC_SET_ONE(&actim_ctrla, 18, 21, tRAS); + SDRC_SET_ONE(&actim_ctrla, 22, 26, tRC); + SDRC_SET_ONE(&actim_ctrla, 27, 31, tRFC); + + SDRC_SET_ONE(&actim_ctrlb, 0, 7, tXSR); + + ticks_per_ms = sdrc_ps_to_ticks(1000000000); + rfr = rx51_timings[0].tREF * ticks_per_ms / (1 << rx51_info.row_lines); + if (rfr > 65535 + 50) + rfr = 65535; + else + rfr -= 50; + + l = rfr << 8; + rfr_ctrl = l | 0x3; /* autorefresh, reload counter with 8xARCV */ + + rx51_sdrc_params[0].rate = 133333333; + rx51_sdrc_params[0].actim_ctrla = actim_ctrla; + rx51_sdrc_params[0].actim_ctrlb = actim_ctrlb; + rx51_sdrc_params[0].rfr_ctrl = rfr_ctrl; + rx51_sdrc_params[0].mr = 0x32; + + rx51_sdrc_params[1].rate = 0; + + if (err < 0) + return NULL; + + return &rx51_sdrc_params[0]; +} + diff --git a/arch/arm/mach-omap2/board-rx51-video.c b/arch/arm/mach-omap2/board-rx51-video.c new file mode 100644 index 00000000000..6ebdc8279e0 --- /dev/null +++ b/arch/arm/mach-omap2/board-rx51-video.c @@ -0,0 +1,79 @@ +/* + * linux/arch/arm/mach-omap2/board-rx51-video.c + * + * Copyright (C) 2008 Nokia + * + * 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. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +static struct omap2_mcspi_device_config mipid_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, +}; + +static struct platform_device rx51_lcd_device = { + .name = "lcd_mipid", + .id = -1, +}; + +static void mipid_shutdown(struct mipid_platform_data *pdata) +{ + if (pdata->nreset_gpio != -1) { + pr_info("shutdown LCD\n"); + gpio_direction_output(pdata->nreset_gpio, 0); + msleep(120); + } +} + +static struct mipid_platform_data rx51_mipid_platform_data = { + .shutdown = mipid_shutdown, +}; + +static void __init mipid_dev_init(void) +{ + const struct omap_lcd_config *conf; + + conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config); + if (conf != NULL) { + rx51_mipid_platform_data.nreset_gpio = conf->nreset_gpio; + rx51_mipid_platform_data.data_lines = conf->data_lines; + } +} + +static struct spi_board_info rx51_video_spi_board_info[] = { + [0] = { + .modalias = "lcd_mipid", + .bus_num = 1, + .chip_select = 2, + .max_speed_hz = 6000000, + .controller_data = &mipid_mcspi_config, + .platform_data = &rx51_mipid_platform_data, + }, +}; + +static struct platform_device *rx51_video_devices[] = { + &rx51_lcd_device, +}; + +void __init rx51_video_init(void) +{ + platform_add_devices(rx51_video_devices, ARRAY_SIZE(rx51_video_devices)); + spi_register_board_info(rx51_video_spi_board_info, + ARRAY_SIZE(rx51_video_spi_board_info)); + mipid_dev_init(); +} + diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c index 3a0daac6c83..768f507a569 100644 --- a/arch/arm/mach-omap2/board-rx51.c +++ b/arch/arm/mach-omap2/board-rx51.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -24,6 +23,7 @@ #include #include +#include #include #include #include @@ -31,6 +31,7 @@ #include #include #include +#include static struct omap_uart_config rx51_uart_config = { .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), @@ -62,12 +63,14 @@ static struct omap_board_config_kernel rx51_config[] = { static void __init rx51_init_irq(void) { - omap2_init_common_hw(NULL); + omap2_init_common_hw(rx51_get_sdram_timings()); omap_init_irq(); omap_gpio_init(); } +extern void __init rx51_flash_init(void); extern void __init rx51_peripherals_init(void); +extern void __init rx51_video_init(void); static void __init rx51_init(void) { @@ -75,7 +78,9 @@ static void __init rx51_init(void) omap_board_config_size = ARRAY_SIZE(rx51_config); omap_serial_init(); usb_musb_init(); + rx51_flash_init(); rx51_peripherals_init(); + rx51_video_init(); } static void __init rx51_map_io(void) diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index d6b4b2f8722..cb697e11577 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -355,10 +355,12 @@ static void omap_init_mcspi(void) platform_device_register(&omap2_mcspi1); platform_device_register(&omap2_mcspi2); #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) - platform_device_register(&omap2_mcspi3); + if (cpu_is_omap2430() || cpu_is_omap343x()) + platform_device_register(&omap2_mcspi3); #endif #ifdef CONFIG_ARCH_OMAP3 - platform_device_register(&omap2_mcspi4); + if (cpu_is_omap343x()) + platform_device_register(&omap2_mcspi4); #endif } diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c index 34b5914e0f8..32ceaa65824 100644 --- a/arch/arm/mach-omap2/id.c +++ b/arch/arm/mach-omap2/id.c @@ -45,6 +45,28 @@ int omap_chip_is(struct omap_chip_id oci) } EXPORT_SYMBOL(omap_chip_is); +int omap_type(void) +{ + u32 val = 0; + + if (cpu_is_omap24xx()) { + val = omap_ctrl_readl(OMAP24XX_CONTROL_STATUS); + } else if (cpu_is_omap34xx()) { + val = omap_ctrl_readl(OMAP343X_CONTROL_STATUS); + } else { + pr_err("Cannot detect omap type!\n"); + goto out; + } + + val &= OMAP2_DEVICETYPE_MASK; + val >>= 8; + +out: + return val; +} +EXPORT_SYMBOL(omap_type); + + /*----------------------------------------------------------------------------*/ #define OMAP_TAP_IDCODE 0x0204 diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c index dc40b3e7220..cb56fe270ab 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.c +++ b/arch/arm/mach-omap2/mmc-twl4030.c @@ -16,8 +16,8 @@ #include #include #include -#include -#include +#include +#include #include #include @@ -26,31 +26,9 @@ #include "mmc-twl4030.h" -#if defined(CONFIG_TWL4030_CORE) && \ - (defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)) -#define LDO_CLR 0x00 -#define VSEL_S2_CLR 0x40 - -#define VMMC1_DEV_GRP 0x27 -#define VMMC1_CLR 0x00 -#define VMMC1_315V 0x03 -#define VMMC1_300V 0x02 -#define VMMC1_285V 0x01 -#define VMMC1_185V 0x00 -#define VMMC1_DEDICATED 0x2A - -#define VMMC2_DEV_GRP 0x2B -#define VMMC2_CLR 0x40 -#define VMMC2_315V 0x0c -#define VMMC2_300V 0x0b -#define VMMC2_285V 0x0a -#define VMMC2_280V 0x09 -#define VMMC2_260V 0x08 -#define VMMC2_185V 0x06 -#define VMMC2_DEDICATED 0x2E - -#define VMMC_DEV_GRP_P1 0x20 +#if defined(CONFIG_REGULATOR) && \ + (defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)) static u16 control_pbias_offset; static u16 control_devconf1_offset; @@ -59,19 +37,16 @@ static u16 control_devconf1_offset; static struct twl_mmc_controller { struct omap_mmc_platform_data *mmc; - u8 twl_vmmc_dev_grp; - u8 twl_mmc_dedicated; - char name[HSMMC_NAME_LEN + 1]; -} hsmmc[OMAP34XX_NR_MMC] = { - { - .twl_vmmc_dev_grp = VMMC1_DEV_GRP, - .twl_mmc_dedicated = VMMC1_DEDICATED, - }, - { - .twl_vmmc_dev_grp = VMMC2_DEV_GRP, - .twl_mmc_dedicated = VMMC2_DEDICATED, - }, -}; + /* Vcc == configured supply + * Vcc_alt == optional + * - MMC1, supply for DAT4..DAT7 + * - MMC2/MMC2, external level shifter voltage supply, for + * chip (SDIO, eMMC, etc) or transceiver (MMC2 only) + */ + struct regulator *vcc; + struct regulator *vcc_aux; + char name[HSMMC_NAME_LEN + 1]; +} hsmmc[OMAP34XX_NR_MMC]; static int twl_mmc_card_detect(int irq) { @@ -117,16 +92,63 @@ static int twl_mmc_late_init(struct device *dev) int ret = 0; int i; - ret = gpio_request(mmc->slots[0].switch_pin, "mmc_cd"); - if (ret) - goto done; - ret = gpio_direction_input(mmc->slots[0].switch_pin); - if (ret) - goto err; + /* MMC/SD/SDIO doesn't require a card detect switch */ + if (gpio_is_valid(mmc->slots[0].switch_pin)) { + ret = gpio_request(mmc->slots[0].switch_pin, "mmc_cd"); + if (ret) + goto done; + ret = gpio_direction_input(mmc->slots[0].switch_pin); + if (ret) + goto err; + } + /* require at least main regulator */ for (i = 0; i < ARRAY_SIZE(hsmmc); i++) { if (hsmmc[i].name == mmc->slots[0].name) { + struct regulator *reg; + hsmmc[i].mmc = mmc; + + reg = regulator_get(dev, "vmmc"); + if (IS_ERR(reg)) { + dev_dbg(dev, "vmmc regulator missing\n"); + /* HACK: until fixed.c regulator is usable, + * we don't require a main regulator + * for MMC2 or MMC3 + */ + if (i != 0) + break; + ret = PTR_ERR(reg); + goto err; + } + hsmmc[i].vcc = reg; + mmc->slots[0].ocr_mask = mmc_regulator_get_ocrmask(reg); + + /* allow an aux regulator */ + reg = regulator_get(dev, "vmmc_aux"); + hsmmc[i].vcc_aux = IS_ERR(reg) ? NULL : reg; + + /* UGLY HACK: workaround regulator framework bugs. + * When the bootloader leaves a supply active, it's + * initialized with zero usecount ... and we can't + * disable it without first disabling it. Until the + * framework is fixed, we need a workaround like this + * (which is safe for MMC, but not in general). + */ + if (regulator_is_enabled(hsmmc[i].vcc) > 0) { + dev_warn(dev, "APPLY REGULATOR HACK for vmmc\n"); + regulator_enable(hsmmc[i].vcc); + regulator_disable(hsmmc[i].vcc); + } + if (hsmmc[i].vcc_aux) { + if (regulator_is_enabled(reg) > 0) { + dev_warn(dev, "APPLY REGULATOR HACK " + "for vmmc_aux\n"); + regulator_enable(reg); + regulator_disable(reg); + } + } + break; } } @@ -173,96 +195,6 @@ static int twl_mmc_resume(struct device *dev, int slot) #define twl_mmc_resume NULL #endif -/* - * Sets the MMC voltage in twl4030 - */ - -#define MMC1_OCR (MMC_VDD_165_195 \ - |MMC_VDD_28_29|MMC_VDD_29_30|MMC_VDD_30_31|MMC_VDD_31_32) -#define MMC2_OCR (MMC_VDD_165_195 \ - |MMC_VDD_25_26|MMC_VDD_26_27|MMC_VDD_27_28 \ - |MMC_VDD_28_29|MMC_VDD_29_30|MMC_VDD_30_31|MMC_VDD_31_32) - -static int twl_mmc_set_voltage(struct twl_mmc_controller *c, int vdd) -{ - int ret; - u8 vmmc = 0, dev_grp_val; - - if (!vdd) - goto doit; - - if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) { - /* VMMC1: max 220 mA. And for 8-bit mode, - * VSIM: max 50 mA - */ - switch (1 << vdd) { - case MMC_VDD_165_195: - vmmc = VMMC1_185V; - /* and VSIM_180V */ - break; - case MMC_VDD_28_29: - vmmc = VMMC1_285V; - /* and VSIM_280V */ - break; - case MMC_VDD_29_30: - case MMC_VDD_30_31: - vmmc = VMMC1_300V; - /* and VSIM_300V */ - break; - case MMC_VDD_31_32: - vmmc = VMMC1_315V; - /* error if VSIM needed */ - break; - default: - return -EINVAL; - } - } else if (c->twl_vmmc_dev_grp == VMMC2_DEV_GRP) { - /* VMMC2: max 100 mA */ - switch (1 << vdd) { - case MMC_VDD_165_195: - vmmc = VMMC2_185V; - break; - case MMC_VDD_25_26: - case MMC_VDD_26_27: - vmmc = VMMC2_260V; - break; - case MMC_VDD_27_28: - vmmc = VMMC2_280V; - break; - case MMC_VDD_28_29: - vmmc = VMMC2_285V; - break; - case MMC_VDD_29_30: - case MMC_VDD_30_31: - vmmc = VMMC2_300V; - break; - case MMC_VDD_31_32: - vmmc = VMMC2_315V; - break; - default: - return -EINVAL; - } - } else { - return -EINVAL; - } - -doit: - if (vdd) - dev_grp_val = VMMC_DEV_GRP_P1; /* Power up */ - else - dev_grp_val = LDO_CLR; /* Power down */ - - ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, - dev_grp_val, c->twl_vmmc_dev_grp); - if (ret || !vdd) - return ret; - - ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, - vmmc, c->twl_mmc_dedicated); - - return ret; -} - static int twl_mmc1_set_power(struct device *dev, int slot, int power_on, int vdd) { @@ -273,11 +205,13 @@ static int twl_mmc1_set_power(struct device *dev, int slot, int power_on, /* * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the - * card using the same TWL VMMC1 supply (hsmmc[0]); OMAP has both + * card with Vcc regulator (from twl4030 or whatever). OMAP has both * 1.8V and 3.0V modes, controlled by the PBIAS register. * * In 8-bit modes, OMAP VMMC1A (for DAT4..7) needs a supply, which * is most naturally TWL VSIM; those pins also use PBIAS. + * + * FIXME handle VMMC1A as needed ... */ if (power_on) { if (cpu_is_omap2430()) { @@ -300,7 +234,7 @@ static int twl_mmc1_set_power(struct device *dev, int slot, int power_on, reg &= ~OMAP2_PBIASLITEPWRDNZ0; omap_ctrl_writel(reg, control_pbias_offset); - ret = twl_mmc_set_voltage(c, vdd); + ret = mmc_regulator_set_ocr(c->vcc, vdd); /* 100ms delay required for PBIAS configuration */ msleep(100); @@ -316,7 +250,7 @@ static int twl_mmc1_set_power(struct device *dev, int slot, int power_on, reg &= ~OMAP2_PBIASLITEPWRDNZ0; omap_ctrl_writel(reg, control_pbias_offset); - ret = twl_mmc_set_voltage(c, 0); + ret = mmc_regulator_set_ocr(c->vcc, 0); /* 100ms delay required for PBIAS configuration */ msleep(100); @@ -329,19 +263,33 @@ static int twl_mmc1_set_power(struct device *dev, int slot, int power_on, return ret; } -static int twl_mmc2_set_power(struct device *dev, int slot, int power_on, int vdd) +static int twl_mmc23_set_power(struct device *dev, int slot, int power_on, int vdd) { - int ret; + int ret = 0; struct twl_mmc_controller *c = &hsmmc[1]; struct omap_mmc_platform_data *mmc = dev->platform_data; + /* If we don't see a Vcc regulator, assume it's a fixed + * voltage always-on regulator. + */ + if (!c->vcc) + return 0; + /* - * Assume TWL VMMC2 (hsmmc[1]) is used only to power the card ... OMAP + * Assume Vcc regulator is used only to power the card ... OMAP * VDDS is used to power the pins, optionally with a transceiver to * support cards using voltages other than VDDS (1.8V nominal). When a * transceiver is used, DAT3..7 are muxed as transceiver control pins. + * + * In some cases this regulator won't support enable/disable; + * e.g. it's a fixed rail for a WLAN chip. + * + * In other cases vcc_aux switches interface power. Example, for + * eMMC cards it represents VccQ. Sometimes transceivers or SDIO + * chips/cards need an interface voltage rail too. */ if (power_on) { + /* only MMC2 supports a CLKIN */ if (mmc->slots[0].internal_clock) { u32 reg; @@ -349,24 +297,23 @@ static int twl_mmc2_set_power(struct device *dev, int slot, int power_on, int vd reg |= OMAP2_MMCSDIO2ADPCLKISEL; omap_ctrl_writel(reg, control_devconf1_offset); } - ret = twl_mmc_set_voltage(c, vdd); + ret = mmc_regulator_set_ocr(c->vcc, vdd); + /* enable interface voltage rail, if needed */ + if (ret == 0 && c->vcc_aux) { + ret = regulator_enable(c->vcc_aux); + if (ret < 0) + ret = mmc_regulator_set_ocr(c->vcc, 0); + } } else { - ret = twl_mmc_set_voltage(c, 0); + if (c->vcc_aux && (ret = regulator_is_enabled(c->vcc_aux)) > 0) + ret = regulator_disable(c->vcc_aux); + if (ret == 0) + ret = mmc_regulator_set_ocr(c->vcc, 0); } return ret; } -static int twl_mmc3_set_power(struct device *dev, int slot, int power_on, - int vdd) -{ - /* - * Assume MMC3 has self-powered device connected, for example on-board - * chip with external power source. - */ - return 0; -} - static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata; void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) @@ -405,17 +352,16 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) if (c->name) strncpy(twl->name, c->name, HSMMC_NAME_LEN); else - snprintf(twl->name, ARRAY_SIZE(twl->name), - "mmc%islot%i", c->mmc, 1); + sprintf(twl->name, "mmc%islot%i", c->mmc, 1); mmc->slots[0].name = twl->name; mmc->nr_slots = 1; mmc->slots[0].wires = c->wires; mmc->slots[0].internal_clock = !c->ext_clock; mmc->dma_mask = 0xffffffff; + mmc->init = twl_mmc_late_init; - /* note: twl4030 card detect GPIOs normally switch VMMCx ... */ + /* note: twl4030 card detect GPIOs can disable VMMCx ... */ if (gpio_is_valid(c->gpio_cd)) { - mmc->init = twl_mmc_late_init; mmc->cleanup = twl_mmc_cleanup; mmc->suspend = twl_mmc_suspend; mmc->resume = twl_mmc_resume; @@ -439,26 +385,28 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) } else mmc->slots[0].gpio_wp = -EINVAL; - /* NOTE: we assume OMAP's MMC1 and MMC2 use - * the TWL4030's VMMC1 and VMMC2, respectively; - * and that MMC3 device has it's own power source. + /* NOTE: MMC slots should have a Vcc regulator set up. + * This may be from a TWL4030-family chip, another + * controllable regulator, or a fixed supply. + * + * temporary HACK: ocr_mask instead of fixed supply */ + mmc->slots[0].ocr_mask = c->ocr_mask; switch (c->mmc) { case 1: + /* on-chip level shifting via PBIAS0/PBIAS1 */ mmc->slots[0].set_power = twl_mmc1_set_power; - mmc->slots[0].ocr_mask = MMC1_OCR; break; case 2: - mmc->slots[0].set_power = twl_mmc2_set_power; - if (c->transceiver) - mmc->slots[0].ocr_mask = MMC2_OCR; - else - mmc->slots[0].ocr_mask = MMC_VDD_165_195; - break; + if (c->ext_clock) + c->transceiver = 1; + if (c->transceiver && c->wires > 4) + c->wires = 4; + /* FALLTHROUGH */ case 3: - mmc->slots[0].set_power = twl_mmc3_set_power; - mmc->slots[0].ocr_mask = MMC_VDD_165_195; + /* off-chip level shifting, or none */ + mmc->slots[0].set_power = twl_mmc23_set_power; break; default: pr_err("MMC%d configuration not supported!\n", c->mmc); diff --git a/arch/arm/mach-omap2/mmc-twl4030.h b/arch/arm/mach-omap2/mmc-twl4030.h index ea59e862429..3807c45c9a6 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.h +++ b/arch/arm/mach-omap2/mmc-twl4030.h @@ -16,9 +16,10 @@ struct twl4030_hsmmc_info { int gpio_wp; /* or -EINVAL */ char *name; /* or NULL for default */ struct device *dev; /* returned: pointer to mmc adapter */ + int ocr_mask; /* temporary HACK */ }; -#if defined(CONFIG_TWL4030_CORE) && \ +#if defined(CONFIG_REGULATOR) && \ (defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \ defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)) diff --git a/arch/arm/mach-omap2/sdram-micron-mt46h32m32lf-6.h b/arch/arm/mach-omap2/sdram-micron-mt46h32m32lf-6.h new file mode 100644 index 00000000000..ef35415ca89 --- /dev/null +++ b/arch/arm/mach-omap2/sdram-micron-mt46h32m32lf-6.h @@ -0,0 +1,55 @@ +/* + * SDRC register values for the Micron MT46H32M32LF-6 + * + * Copyright (C) 2008 Texas Instruments, Inc. + * Copyright (C) 2008 Nokia Corporation + * + * Paul Walmsley + * + * 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. + */ + +#ifndef ARCH_ARM_MACH_OMAP2_SDRAM_MICRON_MT46H32M32LF +#define ARCH_ARM_MACH_OMAP2_SDRAM_MICRON_MT46H32M32LF + +#include + +/* Micron MT46H32M32LF-6 */ +/* XXX Using ARE = 0x1 (no autorefresh burst) -- can this be changed? */ +static struct omap_sdrc_params mt46h32m32lf6_sdrc_params[] = { + [0] = { + .rate = 165941176, + .actim_ctrla = 0x9a9db4c6, + .actim_ctrlb = 0x00011217, + .rfr_ctrl = 0x0004dc01, + .mr = 0x00000032, + }, + [1] = { + .rate = 133333333, + .actim_ctrla = 0x7a19b485, + .actim_ctrlb = 0x00011213, + .rfr_ctrl = 0x0003de01, + .mr = 0x00000032, + }, + [2] = { + .rate = 82970588, + .actim_ctrla = 0x51512283, + .actim_ctrlb = 0x0001120c, + .rfr_ctrl = 0x00025501, + .mr = 0x00000032, + }, + [3] = { + .rate = 66666666, + .actim_ctrla = 0x410d2243, + .actim_ctrlb = 0x0001120a, + .rfr_ctrl = 0x0001d601, + .mr = 0x00000032, + }, + [4] = { + .rate = 0 + }, +}; + +#endif diff --git a/arch/arm/mach-omap2/sdram-qimonda-hyb18m512160af-6.h b/arch/arm/mach-omap2/sdram-qimonda-hyb18m512160af-6.h new file mode 100644 index 00000000000..74a92c862e6 --- /dev/null +++ b/arch/arm/mach-omap2/sdram-qimonda-hyb18m512160af-6.h @@ -0,0 +1,55 @@ +/* + * SDRC register values for the Qimonda HYB18M512160AF-6 + * + * Copyright (C) 2008 Texas Instruments, Inc. + * Copyright (C) 2008 Nokia Corporation + * + * Paul Walmsley + * + * 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. + */ + +#ifndef ARCH_ARM_MACH_OMAP2_SDRAM_QIMONDA_HYB18M512160AF6 +#define ARCH_ARM_MACH_OMAP2_SDRAM_QIMONDA_HYB18M512160AF6 + +#include + +/* Qimonda HYB18M512160AF-6 */ +/* XXX Using ARE = 0x1 (no autorefresh burst) -- can this be changed? */ +static struct omap_sdrc_params hyb18m512160af6_sdrc_params[] = { + [0] = { + .rate = 165941176, + .actim_ctrla = 0x629db4c6, + .actim_ctrlb = 0x00012214, + .rfr_ctrl = 0x0004dc01, + .mr = 0x00000032, + }, + [1] = { + .rate = 133333333, + .actim_ctrla = 0x5219b485, + .actim_ctrlb = 0x00012210, + .rfr_ctrl = 0x0003de01, + .mr = 0x00000032, + }, + [2] = { + .rate = 82970588, + .actim_ctrla = 0x31512283, + .actim_ctrlb = 0x0001220a, + .rfr_ctrl = 0x00025501, + .mr = 0x00000022, + }, + [3] = { + .rate = 66666666, + .actim_ctrla = 0x290d2243, + .actim_ctrlb = 0x00012208, + .rfr_ctrl = 0x0001d601, + .mr = 0x00000022, + }, + [4] = { + .rate = 0 + }, +}; + +#endif diff --git a/arch/arm/mach-omap2/twl4030-generic-scripts.c b/arch/arm/mach-omap2/twl4030-generic-scripts.c new file mode 100644 index 00000000000..4293752732d --- /dev/null +++ b/arch/arm/mach-omap2/twl4030-generic-scripts.c @@ -0,0 +1,81 @@ +/* + * arch/arm/mach-omap2/twl4030-generic-scripts.c + * + * Generic power control scripts for TWL4030 + * + * Copyright (C) 2008 Nokia Corporation + * Copyright (C) 2006 Texas Instruments, Inc + * + * Written by Kalle Jokiniemi + * Peter De Schrijver + * + * 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. + * + * 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 + */ + +#ifdef CONFIG_TWL4030_POWER + +#include +#include +#include +#include + +/* + * This script instructs twl4030 to first put the Reset and Control (RC) + * resources to sleep and then all the other resources. + */ + +static struct twl4030_ins sleep_on_seq[] __initdata = { + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_RC, RES_TYPE_ALL, RES_TYPE2_R0, + RES_STATE_SLEEP), 4}, + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_ALL, RES_TYPE2_R0, + RES_STATE_SLEEP), 4}, +}; + +static struct twl4030_script sleep_on_script __initdata = { + .script = sleep_on_seq, + .size = ARRAY_SIZE(sleep_on_seq), + .flags = TRITON_SLEEP_SCRIPT, +}; + +/* + * This script instructs twl4030 to first enable CLKEN, then wakeup the + * regulators and then all other resources. + */ + +static struct twl4030_ins wakeup_seq[] __initdata = { + {MSG_SINGULAR(DEV_GRP_NULL, 0x17, RES_STATE_ACTIVE), 0x30}, + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_PP_PR, RES_TYPE_ALL, RES_TYPE2_R0, + RES_STATE_ACTIVE), 0x37}, + {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_ALL, RES_TYPE2_R0, + RES_STATE_ACTIVE), 0x2}, +}; + +static struct twl4030_script wakeup_script __initdata = { + .script = wakeup_seq, + .size = ARRAY_SIZE(wakeup_seq), + .flags = TRITON_WAKEUP12_SCRIPT | TRITON_WAKEUP3_SCRIPT, +}; + +static struct twl4030_script *twl4030_scripts[] __initdata = { + &sleep_on_script, + &wakeup_script, +}; + +struct twl4030_power_data generic3430_t2scripts_data __initdata = { + .scripts = twl4030_scripts, + .size = ARRAY_SIZE(twl4030_scripts), +}; + + +#endif /* CONFIG_TWL4030_POWER */ diff --git a/arch/arm/mach-omap2/twl4030-generic-scripts.h b/arch/arm/mach-omap2/twl4030-generic-scripts.h new file mode 100644 index 00000000000..fb69c2e45bf --- /dev/null +++ b/arch/arm/mach-omap2/twl4030-generic-scripts.h @@ -0,0 +1,13 @@ +#ifndef __TWL4030_GENERIC_SCRIPTS_H +#define __TWL4030_GENERIC_SCRIPTS_H + +#include + +#ifdef CONFIG_TWL4030_POWER +extern struct twl4030_power_data generic3430_t2scripts_data; +#define GENERIC3430_T2SCRIPTS_DATA &generic3430_t2scripts_data +#else +#define GENERIC3430_T2SCRIPTS_DATA NULL +#endif /* CONFIG_TWL4030_POWER */ + +#endif diff --git a/arch/arm/mach-omap2/usb-ehci.c b/arch/arm/mach-omap2/usb-ehci.c new file mode 100644 index 00000000000..23fe8578d2a --- /dev/null +++ b/arch/arm/mach-omap2/usb-ehci.c @@ -0,0 +1,160 @@ +/* + * linux/arch/arm/mach-omap2/usb-ehci.c + * + * This file will contain the board specific details for the + * Synopsys EHCI host controller on OMAP3430 + * + * Copyright (C) 2007 Texas Instruments + * Author: Vikram Pandita + * + * Generalization by: + * Felipe Balbi + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static struct resource ehci_resources[] = { + [0] = { + .start = OMAP34XX_HSUSB_HOST_BASE + 0x800, + .end = OMAP34XX_HSUSB_HOST_BASE + 0x800 + SZ_1K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { /* general IRQ */ + .start = INT_34XX_EHCI_IRQ, + .flags = IORESOURCE_IRQ, + } +}; + +static u64 ehci_dmamask = ~(u32)0; +static struct platform_device ehci_device = { + .name = "ehci-omap", + .id = 0, + .dev = { + .dma_mask = &ehci_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = NULL, + }, + .num_resources = ARRAY_SIZE(ehci_resources), + .resource = ehci_resources, +}; + +/* MUX settings for EHCI pins */ +/* + * setup_ehci_io_mux - initialize IO pad mux for USBHOST + */ +static void setup_ehci_io_mux(void) +{ +#ifdef CONFIG_OMAP_EHCI_PHY_MODE + /* PHY mode of operation for board: 750-2083-001 + * ISP1504 connected to Port1 and Port2 + * Do Func Mux setting for 12-pin ULPI PHY mode + */ + + /* Port1 */ + omap_cfg_reg(Y9_3430_USB1HS_PHY_STP); + omap_cfg_reg(Y8_3430_USB1HS_PHY_CLK); + omap_cfg_reg(AA14_3430_USB1HS_PHY_DIR); + omap_cfg_reg(AA11_3430_USB1HS_PHY_NXT); + omap_cfg_reg(W13_3430_USB1HS_PHY_DATA0); + omap_cfg_reg(W12_3430_USB1HS_PHY_DATA1); + omap_cfg_reg(W11_3430_USB1HS_PHY_DATA2); + omap_cfg_reg(Y11_3430_USB1HS_PHY_DATA3); + omap_cfg_reg(W9_3430_USB1HS_PHY_DATA4); + omap_cfg_reg(Y12_3430_USB1HS_PHY_DATA5); + omap_cfg_reg(W8_3430_USB1HS_PHY_DATA6); + omap_cfg_reg(Y13_3430_USB1HS_PHY_DATA7); + + /* Port2 */ + omap_cfg_reg(AA10_3430_USB2HS_PHY_STP); + omap_cfg_reg(AA8_3430_USB2HS_PHY_CLK); + omap_cfg_reg(AA9_3430_USB2HS_PHY_DIR); + omap_cfg_reg(AB11_3430_USB2HS_PHY_NXT); + omap_cfg_reg(AB10_3430_USB2HS_PHY_DATA0); + omap_cfg_reg(AB9_3430_USB2HS_PHY_DATA1); + omap_cfg_reg(W3_3430_USB2HS_PHY_DATA2); + omap_cfg_reg(T4_3430_USB2HS_PHY_DATA3); + omap_cfg_reg(T3_3430_USB2HS_PHY_DATA4); + omap_cfg_reg(R3_3430_USB2HS_PHY_DATA5); + omap_cfg_reg(R4_3430_USB2HS_PHY_DATA6); + omap_cfg_reg(T2_3430_USB2HS_PHY_DATA7); + +#else + /* Set Func mux for : + * TLL mode of operation + * 12-pin ULPI SDR TLL mode for Port1/2/3 + */ + + /* Port1 */ + omap_cfg_reg(Y9_3430_USB1HS_TLL_STP); + omap_cfg_reg(Y8_3430_USB1HS_TLL_CLK); + omap_cfg_reg(AA14_3430_USB1HS_TLL_DIR); + omap_cfg_reg(AA11_3430_USB1HS_TLL_NXT); + omap_cfg_reg(W13_3430_USB1HS_TLL_DATA0); + omap_cfg_reg(W12_3430_USB1HS_TLL_DATA1); + omap_cfg_reg(W11_3430_USB1HS_TLL_DATA2); + omap_cfg_reg(Y11_3430_USB1HS_TLL_DATA3); + omap_cfg_reg(W9_3430_USB1HS_TLL_DATA4); + omap_cfg_reg(Y12_3430_USB1HS_TLL_DATA5); + omap_cfg_reg(W8_3430_USB1HS_TLL_DATA6); + omap_cfg_reg(Y13_3430_USB1HS_TLL_DATA7); + + /* Port2 */ + omap_cfg_reg(AA10_3430_USB2HS_TLL_STP); + omap_cfg_reg(AA8_3430_USB2HS_TLL_CLK); + omap_cfg_reg(AA9_3430_USB2HS_TLL_DIR); + omap_cfg_reg(AB11_3430_USB2HS_TLL_NXT); + omap_cfg_reg(AB10_3430_USB2HS_TLL_DATA0); + omap_cfg_reg(AB9_3430_USB2HS_TLL_DATA1); + omap_cfg_reg(W3_3430_USB2HS_TLL_DATA2); + omap_cfg_reg(T4_3430_USB2HS_TLL_DATA3); + omap_cfg_reg(T3_3430_USB2HS_TLL_DATA4); + omap_cfg_reg(R3_3430_USB2HS_TLL_DATA5); + omap_cfg_reg(R4_3430_USB2HS_TLL_DATA6); + omap_cfg_reg(T2_3430_USB2HS_TLL_DATA7); + + /* Port3 */ + omap_cfg_reg(AB3_3430_USB3HS_TLL_STP); + omap_cfg_reg(AA6_3430_USB3HS_TLL_CLK); + omap_cfg_reg(AA3_3430_USB3HS_TLL_DIR); + omap_cfg_reg(Y3_3430_USB3HS_TLL_NXT); + omap_cfg_reg(AA5_3430_USB3HS_TLL_DATA0); + omap_cfg_reg(Y4_3430_USB3HS_TLL_DATA1); + omap_cfg_reg(Y5_3430_USB3HS_TLL_DATA2); + omap_cfg_reg(W5_3430_USB3HS_TLL_DATA3); + omap_cfg_reg(AB12_3430_USB3HS_TLL_DATA4); + omap_cfg_reg(AB13_3430_USB3HS_TLL_DATA5); + omap_cfg_reg(AA13_3430_USB3HS_TLL_DATA6); + omap_cfg_reg(AA12_3430_USB3HS_TLL_DATA7); +#endif /* CONFIG_OMAP_EHCI_PHY_MODE */ + + return; +} + +void __init usb_ehci_init(void) +{ + /* Setup Pin IO MUX for EHCI */ + if (cpu_is_omap34xx()) + setup_ehci_io_mux(); + + if (platform_device_register(&ehci_device) < 0) { + printk(KERN_ERR "Unable to register HS-USB (EHCI) device\n"); + return; + } +} + + diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c index fc74e913c41..927c2d91a03 100644 --- a/arch/arm/mach-omap2/usb-musb.c +++ b/arch/arm/mach-omap2/usb-musb.c @@ -161,17 +161,15 @@ static struct platform_device nop_xceiv_device = { void __init usb_musb_init(void) { - if (cpu_is_omap243x()) + if (cpu_is_omap243x()) { musb_resources[0].start = OMAP243X_HS_BASE; - else + musb_plat.clock = "usbhs_ick"; + } else { musb_resources[0].start = OMAP34XX_HSUSB_OTG_BASE; - musb_resources[0].end = musb_resources[0].start + SZ_8K - 1; + musb_plat.clock = "hsotgusb_ick"; + } - /* - * REVISIT: This line can be removed once all the platforms using - * musb_core.c have been converted to use use clkdev. - */ - musb_plat.clock = "ick"; + musb_resources[0].end = musb_resources[0].start + SZ_8K - 1; #ifdef CONFIG_NOP_USB_XCEIV if (platform_device_register(&nop_xceiv_device) < 0) { diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c index 15e509013de..59c1d57e507 100644 --- a/arch/arm/mach-omap2/usb-tusb6010.c +++ b/arch/arm/mach-omap2/usb-tusb6010.c @@ -175,8 +175,6 @@ static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps) return gpmc_cs_set_timings(sync_cs, &t); } -extern unsigned long gpmc_get_fclk_period(void); - /* tusb driver calls this when it changes the chip's clocking */ int tusb6010_platform_retime(unsigned is_refclk) { @@ -187,7 +185,7 @@ int tusb6010_platform_retime(unsigned is_refclk) unsigned sysclk_ps; int status; - if (!refclk_psec) + if (!refclk_psec || sysclk_ps == 0) return -ENODEV; sysclk_ps = is_refclk ? refclk_psec : TUSB6010_OSCCLK_60; diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 9dd68fafb37..b37fc101e9f 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -73,6 +73,39 @@ config OMAP_RESET_CLOCKS probably do not want this option enabled until your device drivers work properly. +config OMAP_BOOT_TAG + bool "OMAP bootloader information passing" + depends on ARCH_OMAP + default n + help + Say Y, if you have a bootloader which passes information + about your board and its peripheral configuration. + +config OMAP_BOOT_REASON + bool "Support for boot reason" + depends on OMAP_BOOT_TAG + default n + help + Say Y, if you want to have a procfs entry for reading the boot + reason in user-space. + +config OMAP_COMPONENT_VERSION + bool "Support for component version display" + depends on OMAP_BOOT_TAG && PROC_FS + default n + help + Say Y, if you want to have a procfs entry for reading component + versions (supplied by the bootloader) in user-space. + +config OMAP_GPIO_SWITCH + bool "GPIO switch support" + default n + help + Say Y, if you want to have support for reporting of GPIO + switches (e.g. cover switches) via sysfs. Your bootloader has + to provide information about the switches to the kernel via the + ATAG_BOARD mechanism if they're not defined by the board config. + config OMAP_MUX bool "OMAP multiplexing support" depends on ARCH_OMAP diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index 04a100cfb8e..3ebc09ed0f6 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile @@ -16,6 +16,9 @@ obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o obj-$(CONFIG_CPU_FREQ) += cpu-omap.o obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o +obj-$(CONFIG_OMAP_BOOT_REASON) += bootreason.o +obj-$(CONFIG_OMAP_COMPONENT_VERSION) += component-version.o +obj-$(CONFIG_OMAP_GPIO_SWITCH) += gpio-switch.o obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o diff --git a/arch/arm/plat-omap/bootreason.c b/arch/arm/plat-omap/bootreason.c new file mode 100644 index 00000000000..d527b1bb06f --- /dev/null +++ b/arch/arm/plat-omap/bootreason.c @@ -0,0 +1,79 @@ +/* + * linux/arch/arm/plat-omap/bootreason.c + * + * OMAP Bootreason passing + * + * Copyright (c) 2004 Nokia + * + * Written by David Weinehall + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include + +static char boot_reason[16]; + +static int omap_bootreason_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len = 0; + + len += sprintf(page + len, "%s\n", boot_reason); + + *start = page + off; + + if (len > off) + len -= off; + else + len = 0; + + return len < count ? len : count; +} + +static int __init bootreason_init(void) +{ + const struct omap_boot_reason_config *cfg; + int reason_valid = 0; + + cfg = omap_get_config(OMAP_TAG_BOOT_REASON, struct omap_boot_reason_config); + if (cfg != NULL) { + strncpy(boot_reason, cfg->reason_str, sizeof(cfg->reason_str)); + boot_reason[sizeof(cfg->reason_str)] = 0; + reason_valid = 1; + } else { + /* Read the boot reason from the OMAP registers */ + } + + if (!reason_valid) + return -ENOENT; + + printk(KERN_INFO "Bootup reason: %s\n", boot_reason); + + if (!create_proc_read_entry("bootreason", S_IRUGO, NULL, + omap_bootreason_read_proc, NULL)) + return -ENOMEM; + + return 0; +} + +late_initcall(bootreason_init); diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c index d1797147732..28666126fd3 100644 --- a/arch/arm/plat-omap/common.c +++ b/arch/arm/plat-omap/common.c @@ -40,12 +40,32 @@ #define NO_LENGTH_CHECK 0xffffffff -unsigned char omap_bootloader_tag[512]; +unsigned char omap_bootloader_tag[1024]; int omap_bootloader_tag_len; struct omap_board_config_kernel *omap_board_config; int omap_board_config_size; +#ifdef CONFIG_OMAP_BOOT_TAG + +static int __init parse_tag_omap(const struct tag *tag) +{ + u32 size = tag->hdr.size - (sizeof(tag->hdr) >> 2); + + size <<= 2; + if (size > sizeof(omap_bootloader_tag)) + return -1; + + memcpy(omap_bootloader_tag, tag->u.omap.data, size); + omap_bootloader_tag_len = size; + + return 0; +} + +__tagtable(ATAG_BOARD, parse_tag_omap); + +#endif + static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out) { struct omap_board_config_kernel *kinfo = NULL; diff --git a/arch/arm/plat-omap/component-version.c b/arch/arm/plat-omap/component-version.c new file mode 100644 index 00000000000..3c9d5230cd8 --- /dev/null +++ b/arch/arm/plat-omap/component-version.c @@ -0,0 +1,65 @@ +/* + * linux/arch/arm/plat-omap/component-version.c + * + * Copyright (C) 2005 Nokia Corporation + * Written by Juha Yrjölä + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +static int component_version_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len, i; + const struct omap_version_config *ver; + char *p; + + i = 0; + p = page; + while ((ver = omap_get_nr_config(OMAP_TAG_VERSION_STR, + struct omap_version_config, i)) != NULL) { + p += sprintf(p, "%-12s%s\n", ver->component, ver->version); + i++; + } + + len = (p - page) - off; + if (len < 0) + len = 0; + + *eof = (len <= count) ? 1 : 0; + *start = page + off; + + return len; +} + +static int __init component_version_init(void) +{ + if (omap_get_config(OMAP_TAG_VERSION_STR, struct omap_version_config) == NULL) + return -ENODEV; + if (!create_proc_read_entry("component_version", S_IRUGO, NULL, + component_version_read_proc, NULL)) + return -ENOMEM; + + return 0; +} + +static void __exit component_version_exit(void) +{ + remove_proc_entry("component_version", NULL); +} + +late_initcall(component_version_init); +module_exit(component_version_exit); + +MODULE_AUTHOR("Juha Yrjölä "); +MODULE_DESCRIPTION("Component version driver"); +MODULE_LICENSE("GPL"); diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c old mode 100644 new mode 100755 index 21cc0142b97..3fd0e77bb9f --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -738,7 +738,7 @@ int omap_request_dma(int dev_id, const char *dev_name, * id. */ dma_write(dev_id | (1 << 10), CCR(free_ch)); - } else if (cpu_is_omap7xx() || cpu_is_omap15xx()) { + } else if (cpu_is_omap730() || cpu_is_omap15xx()) { dma_write(dev_id, CCR(free_ch)); } @@ -2346,7 +2346,7 @@ static int __init omap_init_dma(void) printk(KERN_INFO "DMA support for OMAP15xx initialized\n"); dma_chan_count = 9; enable_1510_mode = 1; - } else if (cpu_is_omap16xx() || cpu_is_omap7xx()) { + } else if (cpu_is_omap16xx() || cpu_is_omap730()) { printk(KERN_INFO "OMAP DMA hardware version %d\n", dma_read(HW_ID)); printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n", @@ -2424,6 +2424,19 @@ static int __init omap_init_dma(void) if (cpu_class_is_omap2()) setup_irq(INT_24XX_SDMA_IRQ0, &omap24xx_dma_irq); + /* Enable smartidle idlemodes and autoidle */ + if (cpu_is_omap34xx()) { + u32 v = dma_read(OCP_SYSCONFIG); + v &= ~(DMA_SYSCONFIG_MIDLEMODE_MASK | + DMA_SYSCONFIG_SIDLEMODE_MASK | + DMA_SYSCONFIG_AUTOIDLE); + v |= (DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_SMARTIDLE) | + DMA_SYSCONFIG_SIDLEMODE(DMA_IDLEMODE_SMARTIDLE) | + DMA_SYSCONFIG_AUTOIDLE); + dma_write(v , OCP_SYSCONFIG); + } + + /* FIXME: Update LCD DMA to work on 24xx */ if (cpu_class_is_omap1()) { r = request_irq(INT_DMA_LCD, lcd_dma_irq_handler, 0, diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index bfd47570cc9..a05205c12f7 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -238,7 +238,7 @@ static struct omap_dm_timer omap3_dm_timers[] = { { .phys_base = 0x49040000, .irq = INT_24XX_GPTIMER9 }, { .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 }, { .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 }, - { .phys_base = 0x48304000, .irq = INT_24XX_GPTIMER12 }, + { .phys_base = 0x48304000, .irq = INT_34XX_GPT12_IRQ }, }; static const char *omap3_dm_source_names[] __initdata = { @@ -321,11 +321,9 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer) l |= 0x2 << 8; /* Set clock activity to perserve f-clock on idle */ /* - * Enable wake-up only for GPT1 on OMAP2 CPUs. - * FIXME: All timers should have wake-up enabled and clear - * PRCM status. + * Enable wake-up on OMAP2 CPUs. */ - if (cpu_class_is_omap2() && (timer == &dm_timers[0])) + if (cpu_class_is_omap2()) l |= 1 << 2; omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l); diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c index ce6b4baeede..3746222bed1 100644 --- a/arch/arm/plat-omap/fb.c +++ b/arch/arm/plat-omap/fb.c @@ -206,9 +206,10 @@ void __init omapfb_reserve_sdram(void) config_invalid = 1; return; } - if (rg.paddr) + if (rg.paddr) { reserve_bootmem(rg.paddr, rg.size, BOOTMEM_DEFAULT); - reserved += rg.size; + reserved += rg.size; + } omapfb_config.mem_desc.region[i] = rg; configured_regions++; } diff --git a/arch/arm/plat-omap/gpio-switch.c b/arch/arm/plat-omap/gpio-switch.c new file mode 100644 index 00000000000..9053ea08696 --- /dev/null +++ b/arch/arm/plat-omap/gpio-switch.c @@ -0,0 +1,558 @@ +/* + * linux/arch/arm/plat-omap/gpio-switch.c + * + * Copyright (C) 2004-2006 Nokia Corporation + * Written by Juha Yrjölä + * and Paul Mundt + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct gpio_switch { + char name[14]; + u16 gpio; + unsigned flags:4; + unsigned type:4; + unsigned state:1; + unsigned both_edges:1; + + u16 debounce_rising; + u16 debounce_falling; + + void (* notify)(void *data, int state); + void *notify_data; + + struct work_struct work; + struct timer_list timer; + struct platform_device pdev; + + struct list_head node; +}; + +static LIST_HEAD(gpio_switches); +static struct platform_device *gpio_sw_platform_dev; +static struct platform_driver gpio_sw_driver; + +static const struct omap_gpio_switch *board_gpio_sw_table; +static int board_gpio_sw_count; + +static const char *cover_str[2] = { "open", "closed" }; +static const char *connection_str[2] = { "disconnected", "connected" }; +static const char *activity_str[2] = { "inactive", "active" }; + +/* + * GPIO switch state default debounce delay in ms + */ +#define OMAP_GPIO_SW_DEFAULT_DEBOUNCE 10 + +static const char **get_sw_str(struct gpio_switch *sw) +{ + switch (sw->type) { + case OMAP_GPIO_SWITCH_TYPE_COVER: + return cover_str; + case OMAP_GPIO_SWITCH_TYPE_CONNECTION: + return connection_str; + case OMAP_GPIO_SWITCH_TYPE_ACTIVITY: + return activity_str; + default: + BUG(); + return NULL; + } +} + +static const char *get_sw_type(struct gpio_switch *sw) +{ + switch (sw->type) { + case OMAP_GPIO_SWITCH_TYPE_COVER: + return "cover"; + case OMAP_GPIO_SWITCH_TYPE_CONNECTION: + return "connection"; + case OMAP_GPIO_SWITCH_TYPE_ACTIVITY: + return "activity"; + default: + BUG(); + return NULL; + } +} + +static void print_sw_state(struct gpio_switch *sw, int state) +{ + const char **str; + + str = get_sw_str(sw); + if (str != NULL) + printk(KERN_INFO "%s (GPIO %d) is now %s\n", sw->name, sw->gpio, str[state]); +} + +static int gpio_sw_get_state(struct gpio_switch *sw) +{ + int state; + + state = gpio_get_value(sw->gpio); + if (sw->flags & OMAP_GPIO_SWITCH_FLAG_INVERTED) + state = !state; + + return state; +} + +static ssize_t gpio_sw_state_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct gpio_switch *sw = dev_get_drvdata(dev); + const char **str; + char state[16]; + int enable; + + if (!(sw->flags & OMAP_GPIO_SWITCH_FLAG_OUTPUT)) + return -EPERM; + + if (sscanf(buf, "%15s", state) != 1) + return -EINVAL; + + str = get_sw_str(sw); + if (strcmp(state, str[0]) == 0) + sw->state = enable = 0; + else if (strcmp(state, str[1]) == 0) + sw->state = enable = 1; + else + return -EINVAL; + + if (sw->flags & OMAP_GPIO_SWITCH_FLAG_INVERTED) + enable = !enable; + gpio_set_value(sw->gpio, enable); + + return count; +} + +static ssize_t gpio_sw_state_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct gpio_switch *sw = dev_get_drvdata(dev); + const char **str; + + str = get_sw_str(sw); + return sprintf(buf, "%s\n", str[sw->state]); +} + +static DEVICE_ATTR(state, S_IRUGO | S_IWUSR, gpio_sw_state_show, + gpio_sw_state_store); + +static ssize_t gpio_sw_type_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct gpio_switch *sw = dev_get_drvdata(dev); + + return sprintf(buf, "%s\n", get_sw_type(sw)); +} + +static DEVICE_ATTR(type, S_IRUGO, gpio_sw_type_show, NULL); + +static ssize_t gpio_sw_direction_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct gpio_switch *sw = dev_get_drvdata(dev); + int is_output; + + is_output = sw->flags & OMAP_GPIO_SWITCH_FLAG_OUTPUT; + return sprintf(buf, "%s\n", is_output ? "output" : "input"); +} + +static DEVICE_ATTR(direction, S_IRUGO, gpio_sw_direction_show, NULL); + + +static irqreturn_t gpio_sw_irq_handler(int irq, void *arg) +{ + struct gpio_switch *sw = arg; + unsigned long timeout; + int state; + + if (!sw->both_edges) { + if (gpio_get_value(sw->gpio)) + set_irq_type(gpio_to_irq(sw->gpio), IRQ_TYPE_EDGE_FALLING); + else + set_irq_type(gpio_to_irq(sw->gpio), IRQ_TYPE_EDGE_RISING); + } + + state = gpio_sw_get_state(sw); + if (sw->state == state) + return IRQ_HANDLED; + + if (state) + timeout = sw->debounce_rising; + else + timeout = sw->debounce_falling; + if (!timeout) + schedule_work(&sw->work); + else + mod_timer(&sw->timer, jiffies + msecs_to_jiffies(timeout)); + + return IRQ_HANDLED; +} + +static void gpio_sw_timer(unsigned long arg) +{ + struct gpio_switch *sw = (struct gpio_switch *) arg; + + schedule_work(&sw->work); +} + +static void gpio_sw_handler(struct work_struct *work) +{ + struct gpio_switch *sw = container_of(work, struct gpio_switch, work); + int state; + + state = gpio_sw_get_state(sw); + if (sw->state == state) + return; + + sw->state = state; + if (sw->notify != NULL) + sw->notify(sw->notify_data, state); + sysfs_notify(&sw->pdev.dev.kobj, NULL, "state"); + print_sw_state(sw, state); +} + +static int __init can_do_both_edges(struct gpio_switch *sw) +{ + if (!cpu_class_is_omap1()) + return 1; + if (OMAP_GPIO_IS_MPUIO(sw->gpio)) + return 0; + else + return 1; +} + +static void gpio_sw_release(struct device *dev) +{ +} + +static int __init new_switch(struct gpio_switch *sw) +{ + int r, direction, trigger; + + switch (sw->type) { + case OMAP_GPIO_SWITCH_TYPE_COVER: + case OMAP_GPIO_SWITCH_TYPE_CONNECTION: + case OMAP_GPIO_SWITCH_TYPE_ACTIVITY: + break; + default: + printk(KERN_ERR "invalid GPIO switch type: %d\n", sw->type); + return -EINVAL; + } + + sw->pdev.name = sw->name; + sw->pdev.id = -1; + + sw->pdev.dev.parent = &gpio_sw_platform_dev->dev; + sw->pdev.dev.driver = &gpio_sw_driver.driver; + sw->pdev.dev.release = gpio_sw_release; + + r = platform_device_register(&sw->pdev); + if (r) { + printk(KERN_ERR "gpio-switch: platform device registration " + "failed for %s", sw->name); + return r; + } + dev_set_drvdata(&sw->pdev.dev, sw); + + r = gpio_request(sw->gpio, sw->name); + if (r < 0) { + platform_device_unregister(&sw->pdev); + return r; + } + + /* input: 1, output: 0 */ + direction = !(sw->flags & OMAP_GPIO_SWITCH_FLAG_OUTPUT); + if (direction) { + gpio_direction_input(sw->gpio); + sw->state = gpio_sw_get_state(sw); + } else { + int state = sw->state = !!(sw->flags & + OMAP_GPIO_SWITCH_FLAG_OUTPUT_INIT_ACTIVE); + + if (sw->flags & OMAP_GPIO_SWITCH_FLAG_INVERTED) + state = !state; + gpio_direction_output(sw->gpio, state); + } + + r = 0; + r |= device_create_file(&sw->pdev.dev, &dev_attr_state); + r |= device_create_file(&sw->pdev.dev, &dev_attr_type); + r |= device_create_file(&sw->pdev.dev, &dev_attr_direction); + if (r) + printk(KERN_ERR "gpio-switch: attribute file creation " + "failed for %s\n", sw->name); + + if (!direction) + return 0; + + if (can_do_both_edges(sw)) { + trigger = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING; + sw->both_edges = 1; + } else { + if (gpio_get_value(sw->gpio)) + trigger = IRQF_TRIGGER_FALLING; + else + trigger = IRQF_TRIGGER_RISING; + } + r = request_irq(gpio_to_irq(sw->gpio), gpio_sw_irq_handler, + IRQF_SHARED | trigger, sw->name, sw); + if (r < 0) { + printk(KERN_ERR "gpio-switch: request_irq() failed " + "for GPIO %d\n", sw->gpio); + platform_device_unregister(&sw->pdev); + gpio_free(sw->gpio); + return r; + } + + INIT_WORK(&sw->work, gpio_sw_handler); + init_timer(&sw->timer); + + sw->timer.function = gpio_sw_timer; + sw->timer.data = (unsigned long)sw; + + list_add(&sw->node, &gpio_switches); + + return 0; +} + +static int __init add_atag_switches(void) +{ + const struct omap_gpio_switch_config *cfg; + struct gpio_switch *sw; + int i, r; + + for (i = 0; ; i++) { + cfg = omap_get_nr_config(OMAP_TAG_GPIO_SWITCH, + struct omap_gpio_switch_config, i); + if (cfg == NULL) + break; + sw = kzalloc(sizeof(*sw), GFP_KERNEL); + if (sw == NULL) { + printk(KERN_ERR "gpio-switch: kmalloc failed\n"); + return -ENOMEM; + } + strncpy(sw->name, cfg->name, sizeof(cfg->name)); + sw->gpio = cfg->gpio; + sw->flags = cfg->flags; + sw->type = cfg->type; + sw->debounce_rising = OMAP_GPIO_SW_DEFAULT_DEBOUNCE; + sw->debounce_falling = OMAP_GPIO_SW_DEFAULT_DEBOUNCE; + if ((r = new_switch(sw)) < 0) { + kfree(sw); + return r; + } + } + return 0; +} + +static struct gpio_switch * __init find_switch(int gpio, const char *name) +{ + struct gpio_switch *sw; + + list_for_each_entry(sw, &gpio_switches, node) { + if ((gpio < 0 || sw->gpio != gpio) && + (name == NULL || strcmp(sw->name, name) != 0)) + continue; + + if (gpio < 0 || name == NULL) + goto no_check; + + if (strcmp(sw->name, name) != 0) + printk("gpio-switch: name mismatch for %d (%s, %s)\n", + gpio, name, sw->name); + else if (sw->gpio != gpio) + printk("gpio-switch: GPIO mismatch for %s (%d, %d)\n", + name, gpio, sw->gpio); +no_check: + return sw; + } + return NULL; +} + +static int __init add_board_switches(void) +{ + int i; + + for (i = 0; i < board_gpio_sw_count; i++) { + const struct omap_gpio_switch *cfg; + struct gpio_switch *sw; + int r; + + cfg = board_gpio_sw_table + i; + if (strlen(cfg->name) > sizeof(sw->name) - 1) + return -EINVAL; + /* Check whether we only update an existing switch + * or add a new switch. */ + sw = find_switch(cfg->gpio, cfg->name); + if (sw != NULL) { + sw->debounce_rising = cfg->debounce_rising; + sw->debounce_falling = cfg->debounce_falling; + sw->notify = cfg->notify; + sw->notify_data = cfg->notify_data; + continue; + } else { + if (cfg->gpio < 0 || cfg->name == NULL) { + printk("gpio-switch: required switch not " + "found (%d, %s)\n", cfg->gpio, + cfg->name); + continue; + } + } + sw = kzalloc(sizeof(*sw), GFP_KERNEL); + if (sw == NULL) { + printk(KERN_ERR "gpio-switch: kmalloc failed\n"); + return -ENOMEM; + } + strlcpy(sw->name, cfg->name, sizeof(sw->name)); + sw->gpio = cfg->gpio; + sw->flags = cfg->flags; + sw->type = cfg->type; + sw->debounce_rising = cfg->debounce_rising; + sw->debounce_falling = cfg->debounce_falling; + sw->notify = cfg->notify; + sw->notify_data = cfg->notify_data; + if ((r = new_switch(sw)) < 0) { + kfree(sw); + return r; + } + } + return 0; +} + +static void gpio_sw_cleanup(void) +{ + struct gpio_switch *sw = NULL, *old = NULL; + + list_for_each_entry(sw, &gpio_switches, node) { + if (old != NULL) + kfree(old); + flush_scheduled_work(); + del_timer_sync(&sw->timer); + + free_irq(gpio_to_irq(sw->gpio), sw); + + device_remove_file(&sw->pdev.dev, &dev_attr_state); + device_remove_file(&sw->pdev.dev, &dev_attr_type); + device_remove_file(&sw->pdev.dev, &dev_attr_direction); + + platform_device_unregister(&sw->pdev); + gpio_free(sw->gpio); + old = sw; + } + kfree(old); +} + +static void __init report_initial_state(void) +{ + struct gpio_switch *sw; + + list_for_each_entry(sw, &gpio_switches, node) { + int state; + + state = gpio_get_value(sw->gpio); + if (sw->flags & OMAP_GPIO_SWITCH_FLAG_INVERTED) + state = !state; + if (sw->notify != NULL) + sw->notify(sw->notify_data, state); + print_sw_state(sw, state); + } +} + +static int gpio_sw_remove(struct platform_device *dev) +{ + return 0; +} + +static struct platform_driver gpio_sw_driver = { + .remove = gpio_sw_remove, + .driver = { + .name = "gpio-switch", + }, +}; + +void __init omap_register_gpio_switches(const struct omap_gpio_switch *tbl, + int count) +{ + BUG_ON(board_gpio_sw_table != NULL); + + board_gpio_sw_table = tbl; + board_gpio_sw_count = count; +} + +static int __init gpio_sw_init(void) +{ + int r; + + printk(KERN_INFO "OMAP GPIO switch handler initializing\n"); + + r = platform_driver_register(&gpio_sw_driver); + if (r) + return r; + + gpio_sw_platform_dev = platform_device_register_simple("gpio-switch", + -1, NULL, 0); + if (IS_ERR(gpio_sw_platform_dev)) { + r = PTR_ERR(gpio_sw_platform_dev); + goto err1; + } + + r = add_atag_switches(); + if (r < 0) + goto err2; + + r = add_board_switches(); + if (r < 0) + goto err2; + + report_initial_state(); + + return 0; +err2: + gpio_sw_cleanup(); + platform_device_unregister(gpio_sw_platform_dev); +err1: + platform_driver_unregister(&gpio_sw_driver); + return r; +} + +static void __exit gpio_sw_exit(void) +{ + gpio_sw_cleanup(); + platform_device_unregister(gpio_sw_platform_dev); + platform_driver_unregister(&gpio_sw_driver); +} + +#ifndef MODULE +late_initcall(gpio_sw_init); +#else +module_init(gpio_sw_init); +#endif +module_exit(gpio_sw_exit); + +MODULE_AUTHOR("Juha Yrjölä , Paul Mundt lock, flags); - if (enable) { + if (enable) bank->suspend_wakeup |= (1 << gpio); - enable_irq_wake(bank->irq); - } else { - disable_irq_wake(bank->irq); + else bank->suspend_wakeup &= ~(1 << gpio); - } spin_unlock_irqrestore(&bank->lock, flags); return 0; #endif @@ -940,13 +937,10 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable) return -EINVAL; } spin_lock_irqsave(&bank->lock, flags); - if (enable) { + if (enable) bank->suspend_wakeup |= (1 << gpio); - enable_irq_wake(bank->irq); - } else { - disable_irq_wake(bank->irq); + else bank->suspend_wakeup &= ~(1 << gpio); - } spin_unlock_irqrestore(&bank->lock, flags); return 0; #endif diff --git a/arch/arm/plat-omap/include/mach/board-nokia.h b/arch/arm/plat-omap/include/mach/board-nokia.h new file mode 100644 index 00000000000..198d761136b --- /dev/null +++ b/arch/arm/plat-omap/include/mach/board-nokia.h @@ -0,0 +1,67 @@ +/* + * arch/arm/plat-omap/include/mach/board-nokia.h + * + * Information structures for Nokia-specific board config data + * + * Copyright (C) 2005 Nokia Corporation + */ + +#ifndef __ASM_ARCH_OMAP_NOKIA_H +#define __ASM_ARCH_OMAP_NOKIA_H + +#include + +struct tsc2301_platform_data; +struct dsp_kfunc_device; +extern void n800_bt_init(void); +extern void n800_dsp_init(void); +extern void n800_flash_init(void); +extern void n800_mmc_init(void); +extern void n800_pm_init(void); +extern void n800_usb_init(void); +extern void n800_cam_init(void); +extern void n800_audio_init(struct tsc2301_platform_data *); +extern int n800_audio_enable(struct dsp_kfunc_device *kdev, int stage); +extern int n800_audio_disable(struct dsp_kfunc_device *kdev, int stage); +extern void n800_mmc_slot1_cover_handler(void *arg, int state); + +#define OMAP_TAG_NOKIA_BT 0x4e01 +#define OMAP_TAG_WLAN_CX3110X 0x4e02 +#define OMAP_TAG_CBUS 0x4e03 +#define OMAP_TAG_EM_ASIC_BB5 0x4e04 + +#define BT_CHIP_CSR 1 +#define BT_CHIP_TI 2 + +#define BT_SYSCLK_12 1 +#define BT_SYSCLK_38_4 2 + +struct omap_bluetooth_config { + u8 chip_type; + u8 bt_wakeup_gpio; + u8 host_wakeup_gpio; + u8 reset_gpio; + u8 bt_uart; + u8 bd_addr[6]; + u8 bt_sysclk; +}; + +struct omap_wlan_cx3110x_config { + u8 chip_type; + s16 power_gpio; + s16 irq_gpio; + s16 spi_cs_gpio; +}; + +struct omap_cbus_config { + s16 clk_gpio; + s16 dat_gpio; + s16 sel_gpio; +}; + +struct omap_em_asic_bb5_config { + s16 retu_irq_gpio; + s16 tahvo_irq_gpio; +}; + +#endif diff --git a/arch/arm/plat-omap/include/mach/board-rx51.h b/arch/arm/plat-omap/include/mach/board-rx51.h new file mode 100644 index 00000000000..7b3287202f1 --- /dev/null +++ b/arch/arm/plat-omap/include/mach/board-rx51.h @@ -0,0 +1,47 @@ +/* + * linux/include/asm-arm/arch-omap/board-rx51.h + * + * Copyright (C) 2007 Nokia + * + * Hardware definitions for Nokia RX-51 + * based on board-3430sdp.h + * + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __ASM_ARCH_OMAP_BOARD_RX51_H +#define __ASM_ARCH_OMAP_BOARD_RX51_H + +#include + +#ifdef CONFIG_USB_MUSB_SOC +extern void rx51_usb_init(void); +#else +static inline void rx51_usb_init(void) { } +#endif + +extern void n800_bt_init(void); + +struct omap_sdrc_params *rx51_get_sdram_timings(void); + +#endif /* __ASM_ARCH_OMAP_BOARD_RX51_H */ + diff --git a/arch/arm/plat-omap/include/mach/board.h b/arch/arm/plat-omap/include/mach/board.h index 50ea79a0efa..ae8c2db22eb 100644 --- a/arch/arm/plat-omap/include/mach/board.h +++ b/arch/arm/plat-omap/include/mach/board.h @@ -23,9 +23,12 @@ #define OMAP_TAG_FBMEM 0x4f08 #define OMAP_TAG_STI_CONSOLE 0x4f09 #define OMAP_TAG_CAMERA_SENSOR 0x4f0a +#define OMAP_TAG_PARTITION 0x4f0b +#define OMAP_TAG_TEA5761 0x4f10 +#define OMAP_TAG_TMP105 0x4f11 #define OMAP_TAG_BOOT_REASON 0x4f80 -#define OMAP_TAG_FLASH_PART 0x4f81 +#define OMAP_TAG_FLASH_PART_STR 0x4f81 #define OMAP_TAG_VERSION_STR 0x4f82 struct omap_clock_config { @@ -43,12 +46,6 @@ struct omap_sti_console_config { u8 channel; }; -struct omap_camera_sensor_config { - u16 reset_gpio; - int (*power_on)(void * data); - int (*power_off)(void * data); -}; - struct omap_usb_config { /* Configure drivers according to the connectors on your board: * - "A" connector (rectagular) @@ -108,9 +105,9 @@ struct omap_pwm_led_platform_data { struct omap_gpio_switch_config { char name[12]; u16 gpio; - int flags:4; - int type:4; - int key_code:24; /* Linux key code */ + u8 flags:4; + u8 type:4; + unsigned int key_code:24; /* Linux key code */ }; struct omap_uart_config { @@ -118,8 +115,25 @@ struct omap_uart_config { unsigned int enabled_uarts; }; +struct omap_tea5761_config { + u16 enable_gpio; +}; + +/* This cannot be passed from the bootloader */ +struct omap_tmp105_config { + u16 tmp105_irq_pin; + int (* set_power)(int enable); +}; + +struct omap_partition_config { + char name[16]; + unsigned int size; + unsigned int offset; + /* same as in include/linux/mtd/partitions.h */ + unsigned int mask_flags; +}; -struct omap_flash_part_config { +struct omap_flash_part_str_config { char part_table[0]; }; diff --git a/arch/arm/plat-omap/include/mach/dma.h b/arch/arm/plat-omap/include/mach/dma.h index 54fe9665b18..224b0770ec2 100644 --- a/arch/arm/plat-omap/include/mach/dma.h +++ b/arch/arm/plat-omap/include/mach/dma.h @@ -387,6 +387,21 @@ #define DMA_THREAD_FIFO_25 (0x02 << 14) #define DMA_THREAD_FIFO_50 (0x03 << 14) +/* DMA4_OCP_SYSCONFIG bits */ +#define DMA_SYSCONFIG_MIDLEMODE_MASK (3 << 12) +#define DMA_SYSCONFIG_CLOCKACTIVITY_MASK (3 << 8) +#define DMA_SYSCONFIG_EMUFREE (1 << 5) +#define DMA_SYSCONFIG_SIDLEMODE_MASK (3 << 3) +#define DMA_SYSCONFIG_SOFTRESET (1 << 2) +#define DMA_SYSCONFIG_AUTOIDLE (1 << 0) + +#define DMA_SYSCONFIG_MIDLEMODE(n) ((n) << 12) +#define DMA_SYSCONFIG_SIDLEMODE(n) ((n) << 3) + +#define DMA_IDLEMODE_SMARTIDLE 0x2 +#define DMA_IDLEMODE_NO_IDLE 0x1 +#define DMA_IDLEMODE_FORCE_IDLE 0x0 + /* Chaining modes*/ #ifndef CONFIG_ARCH_OMAP1 #define OMAP_DMA_STATIC_CHAIN 0x1 diff --git a/arch/arm/plat-omap/include/mach/gpio-switch.h b/arch/arm/plat-omap/include/mach/gpio-switch.h index 10da0e07c0c..20967806609 100644 --- a/arch/arm/plat-omap/include/mach/gpio-switch.h +++ b/arch/arm/plat-omap/include/mach/gpio-switch.h @@ -24,11 +24,12 @@ * low -> inactive * */ -#define OMAP_GPIO_SWITCH_TYPE_COVER 0x0000 -#define OMAP_GPIO_SWITCH_TYPE_CONNECTION 0x0001 -#define OMAP_GPIO_SWITCH_TYPE_ACTIVITY 0x0002 -#define OMAP_GPIO_SWITCH_FLAG_INVERTED 0x0001 -#define OMAP_GPIO_SWITCH_FLAG_OUTPUT 0x0002 +#define OMAP_GPIO_SWITCH_TYPE_COVER 0x0000 +#define OMAP_GPIO_SWITCH_TYPE_CONNECTION 0x0001 +#define OMAP_GPIO_SWITCH_TYPE_ACTIVITY 0x0002 +#define OMAP_GPIO_SWITCH_FLAG_INVERTED 0x0001 +#define OMAP_GPIO_SWITCH_FLAG_OUTPUT 0x0002 +#define OMAP_GPIO_SWITCH_FLAG_OUTPUT_INIT_ACTIVE 0x0004 struct omap_gpio_switch { const char *name; @@ -48,7 +49,11 @@ struct omap_gpio_switch { }; /* Call at init time only */ +#ifdef CONFIG_OMAP_GPIO_SWITCH extern void omap_register_gpio_switches(const struct omap_gpio_switch *tbl, int count); +#else +#define omap_register_gpio_switches(tbl, count) do { } while (0) +#endif #endif diff --git a/arch/arm/plat-omap/include/mach/gpioexpander.h b/arch/arm/plat-omap/include/mach/gpioexpander.h deleted file mode 100644 index 90444a0d6b1..00000000000 --- a/arch/arm/plat-omap/include/mach/gpioexpander.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * arch/arm/plat-omap/include/mach/gpioexpander.h - * - * - * Copyright (C) 2004 Texas Instruments, Inc. - * - * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#ifndef __ASM_ARCH_OMAP_GPIOEXPANDER_H -#define __ASM_ARCH_OMAP_GPIOEXPANDER_H - -/* Function Prototypes for GPIO Expander functions */ - -#ifdef CONFIG_GPIOEXPANDER_OMAP -int read_gpio_expa(u8 *, int); -int write_gpio_expa(u8 , int); -#else -static inline int read_gpio_expa(u8 *val, int addr) -{ - return 0; -} -static inline int write_gpio_expa(u8 val, int addr) -{ - return 0; -} -#endif - -#endif /* __ASM_ARCH_OMAP_GPIOEXPANDER_H */ diff --git a/arch/arm/plat-omap/include/mach/gpmc.h b/arch/arm/plat-omap/include/mach/gpmc.h index 921b16532ff..b0b2edf8c55 100644 --- a/arch/arm/plat-omap/include/mach/gpmc.h +++ b/arch/arm/plat-omap/include/mach/gpmc.h @@ -25,8 +25,18 @@ #define GPMC_CS_NAND_ADDRESS 0x20 #define GPMC_CS_NAND_DATA 0x24 +/* + * The following gpmc registers are being used by + * nand driver and hence is defined here. + * TBD: Move them to gpmc.c by providing appropriate + * methods to read and write into these registers + */ +#define GPMC_IRQSTATUS 0x18 #define GPMC_CONFIG 0x50 #define GPMC_STATUS 0x54 +#define GPMC_CS0_BASE 0x60 +#define GPMC_CS_SIZE 0x30 + #define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31) #define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30) diff --git a/arch/arm/plat-omap/include/mach/irqs.h b/arch/arm/plat-omap/include/mach/irqs.h index 7f57ee66f36..9499a0520e0 100644 --- a/arch/arm/plat-omap/include/mach/irqs.h +++ b/arch/arm/plat-omap/include/mach/irqs.h @@ -420,8 +420,6 @@ #define INT_34XX_MMC3_IRQ 94 #define INT_34XX_GPT12_IRQ 95 -#define INT_34XX_BENCH_MPU_EMUL 3 - /* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730/850) and * 16 MPUIO lines */ #define OMAP_MAX_GPIO_LINES 192 @@ -467,6 +465,7 @@ #ifndef __ASSEMBLY__ extern void omap_init_irq(void); +extern int omap_irq_pending(void); #endif #include diff --git a/arch/arm/plat-omap/include/mach/keypad.h b/arch/arm/plat-omap/include/mach/keypad.h index 232923aaf61..b7f270a6782 100644 --- a/arch/arm/plat-omap/include/mach/keypad.h +++ b/arch/arm/plat-omap/include/mach/keypad.h @@ -14,6 +14,7 @@ struct omap_kp_platform_data { int rows; int cols; int *keymap; + int irq; unsigned int keymapsize; unsigned int rep:1; unsigned long delay; @@ -33,7 +34,12 @@ struct omap_kp_platform_data { #define GROUP_3 (3 << 16) #define GROUP_MASK GROUP_3 +#define ROWCOL_MASK 0xFF000000 +#define KEY_PERSISTENT 0x00800000 +#define KEYNUM_MASK 0x00EFFFFF #define KEY(col, row, val) (((col) << 28) | ((row) << 24) | (val)) +#define PERSISTENT_KEY(col, row) (((col) << 28) | ((row) << 24) | \ + KEY_PERSISTENT) #endif diff --git a/arch/arm/plat-omap/include/mach/mmc.h b/arch/arm/plat-omap/include/mach/mmc.h index 4435bd434e1..81d5b36534b 100644 --- a/arch/arm/plat-omap/include/mach/mmc.h +++ b/arch/arm/plat-omap/include/mach/mmc.h @@ -79,7 +79,6 @@ struct omap_mmc_platform_data { /* use the internal clock */ unsigned internal_clock:1; - s16 power_pin; int switch_pin; /* gpio (card detect) */ int gpio_wp; /* gpio (write protect) */ diff --git a/arch/arm/plat-omap/include/mach/sti.h b/arch/arm/plat-omap/include/mach/sti.h new file mode 100644 index 00000000000..af439170eba --- /dev/null +++ b/arch/arm/plat-omap/include/mach/sti.h @@ -0,0 +1,172 @@ +#ifndef __ASM_ARCH_OMAP_STI_H +#define __ASM_ARCH_OMAP_STI_H + +#include + +/* + * STI/SDTI + */ +#define STI_REVISION 0x00 +#define STI_SYSCONFIG 0x10 +#define STI_SYSSTATUS 0x14 +#define STI_IRQSTATUS 0x18 +#define STI_IRQSETEN 0x1c + +#if defined(CONFIG_ARCH_OMAP1) +#define STI_IRQCLREN 0x20 +#define STI_ER 0x24 +#define STI_DR 0x28 +#define STI_RX_DR 0x2c +#define STI_RX_STATUS 0x30 +#define STI_CLK_CTRL 0x34 +#define STI_IOBOTT0 0x4c +#define STI_IOTOP0 0x50 +#define STI_IOBOTT1 0x54 +#define STI_IOTOP1 0x58 +#define STI_SERIAL_CFG 0x60 + +#define STI_OCPT2_MATCH_INT 0 +#define STI_OCPT1_MATCH_INT 1 +#define STI_EMIFS_MATCH_INT 2 +#define STI_EMIFF_MATCH_INT 3 +#define STI_IO_MATCH_INT 4 +#define STI_RX_INT 5 +#define STI_DUMP_REQUEST_INT 6 +#define STI_DUMP_UNDERRUN_INT 7 +#define STI_WAKEUP_INT 9 + +#define STI_NR_IRQS 10 + +#define STI_IRQSTATUS_MASK 0x2ff + +#define STI_RXFIFO_EMPTY (1 << 0) + +/* + * We use the following enums to retain consistency with the STI "functional" + * specification. + */ + +/* STI_ER */ +enum { + UnlockStatMatch = (1 << 2), /* Unlock status match event regs */ + IOMPUStr1En1 = (1 << 3), /* MPU IO match, strobe 1, window 1 */ + IOMPUStr0En1 = (1 << 4), /* MPU IO match, strobe 0, window 1 */ + IOMPUStr1En0 = (1 << 5), /* MPU IO match, strobe 1, window 0 */ + IOMPUStr0En0 = (1 << 6), /* MPU IO match, strobe 0, window 0 */ + IODSPStr1En1 = (1 << 7), /* DSP IO match, strobe 1, window 1 */ + IODSPStr0En1 = (1 << 8), /* DSP IO match, strobe 0, window 1 */ + IODSPStr1En0 = (1 << 9), /* DSP IO match, strobe 1, window 0 */ + IODSPStr0En0 = (1 << 10), /* DSP IO match, strobe 0, window 0 */ + MemMatchEn = (1 << 11), /* Memory matched event */ + DSPCmdEn = (1 << 12), /* DSP command write */ + MPUCmdEn = (1 << 13), /* MPU command write */ + MemDumpEn = (1 << 14), /* System memory dump */ + STIEn = (1 << 15), /* Global trace enable */ +}; + +#define STI_PERCHANNEL_SIZE 4 + +#define to_channel_address(channel) \ + (sti_channel_base + STI_PERCHANNEL_SIZE * (channel)) + +#elif defined(CONFIG_ARCH_OMAP2) + +/* XTI interrupt bits */ +enum { + STI_WAKEUP_INT = 0, + STI_ETB_THRESHOLD_INT, + STI_RX_INT, + STI_DUMP_REQUEST_INT, + STI_NR_IRQS, +}; + +/* XTI_TRACESELECT */ +enum { + CmdTimeStampEn = (1 << 0), /* Command write timestamps */ + WinTimeStampEn = (1 << 1), /* Window match timestamps */ + WinMatchEn = (1 << 2), /* Window match trace */ + DSPCmdEn = (1 << 3), /* DSP command write */ + MPUCmdEn = (1 << 4), /* MPU command write */ + MemDumpEn0 = (1 << 5), /* System memory dump */ + MemDumpEn1 = (1 << 6), + MemDumpEn2 = (1 << 7), + ExtTriggerEn = (1 << 8), /* External trace trigger */ + STIEn = (1 << 9), /* System trace enable */ +}; + +#define STI_IRQSTATUS_MASK 0x0f +#define STI_PERCHANNEL_SIZE 64 + +/* XTI registers */ +#define XTI_SYSSTATUS 0x14 +#define XTI_TRACESELECT 0x24 +#define XTI_RXDATA 0x28 +#define XTI_SCLKCRTL 0x2c +#define XTI_SCONFIG 0x30 + +/* STI Compatability */ +#define STI_RX_STATUS XTI_SYSSTATUS +#define STI_IRQCLREN STI_IRQSETEN +#define STI_ER XTI_TRACESELECT +#define STI_DR XTI_TRACESELECT +#define STI_RX_DR XTI_RXDATA +#define STI_CLK_CTRL XTI_SCLKCRTL +#define STI_SERIAL_CFG XTI_SCONFIG + +#define STI_RXFIFO_EMPTY (1 << 8) + +#define to_channel_address(channel) \ + (sti_channel_base + STI_PERCHANNEL_SIZE * (channel)) + +#elif defined(CONFIG_ARCH_OMAP3) + +#define STI_PERCHANNEL_SIZE 0x1000 +#define to_channel_address(channel) \ + (sti_channel_base + STI_PERCHANNEL_SIZE * (channel) + 0x800) + +#endif + +/* arch/arm/plat-omap/sti/sti.c */ +extern void __iomem *sti_base, *sti_channel_base; + +int sti_request_irq(unsigned int irq, void *handler, unsigned long arg); +void sti_free_irq(unsigned int irq); +void sti_enable_irq(unsigned int irq); +void sti_disable_irq(unsigned int irq); +void sti_ack_irq(unsigned int irq); + +int sti_trace_enable(int event); +void sti_trace_disable(int event); + +void sti_channel_write_trace(int len, int id, void *data, unsigned int channel); + +/* arch/arm/plat-omap/sti/sti-fifo.c */ +int sti_read_packet(unsigned char *buf, int maxsize); + +static inline unsigned long sti_readl(unsigned long reg) +{ + return __raw_readl(sti_base + reg); +} + +static inline void sti_writel(unsigned long data, unsigned long reg) +{ + __raw_writel(data, sti_base + reg); +} + +static inline void sti_channel_writeb(unsigned char data, unsigned int channel) +{ + __raw_writeb(data, to_channel_address(channel)); +} + +static inline void sti_channel_writel(unsigned long data, unsigned int channel) +{ + __raw_writel(data, to_channel_address(channel)); +} + +#define STI_TRACE_CONTROL_CHANNEL 253 + +static inline void sti_channel_flush(unsigned int channel) +{ + sti_channel_writeb(channel, STI_TRACE_CONTROL_CHANNEL); +} +#endif /* __ASM_ARCH_OMAP_STI_H */ diff --git a/arch/arm/plat-omap/include/mach/usb.h b/arch/arm/plat-omap/include/mach/usb.h index 69f0ceed500..f6d334ffaae 100644 --- a/arch/arm/plat-omap/include/mach/usb.h +++ b/arch/arm/plat-omap/include/mach/usb.h @@ -33,9 +33,17 @@ extern void usb_musb_init(void); static inline void usb_musb_init(void) { } -#endif +#endif /* !OMAP1 && !MUSB */ -#endif +#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_EHCI_HCD_MODULE) +extern void usb_ehci_init(void); +#else +static inline void usb_ehci_init(void) +{ +} +#endif /* !OMAP1 && !EHCI */ + +#endif /* !OMAP1 */ void omap_usb_init(struct omap_usb_config *pdata); diff --git a/arch/arm/plat-omap/include/mach/vmalloc.h b/arch/arm/plat-omap/include/mach/vmalloc.h index dc104cd9619..b97dfafeebd 100644 --- a/arch/arm/plat-omap/include/mach/vmalloc.h +++ b/arch/arm/plat-omap/include/mach/vmalloc.h @@ -17,5 +17,5 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define VMALLOC_END (PAGE_OFFSET + 0x10000000) +#define VMALLOC_END (PAGE_OFFSET + 0x18000000) diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index fa5297d643d..e1e637f222c 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -38,8 +38,8 @@ #define OMAP1_SRAM_VA VMALLOC_END #define OMAP2_SRAM_PA 0x40200000 #define OMAP2_SRAM_PUB_PA 0x4020f800 -#define OMAP2_SRAM_VA VMALLOC_END -#define OMAP2_SRAM_PUB_VA (VMALLOC_END + 0x800) +#define OMAP2_SRAM_VA 0xe3000000 +#define OMAP2_SRAM_PUB_VA (OMAP2_SRAM_VA + 0x800) #define OMAP3_SRAM_PA 0x40200000 #define OMAP3_SRAM_VA 0xd7000000 #define OMAP3_SRAM_PUB_PA 0x40208000 @@ -359,14 +359,14 @@ static u32 (*_omap3_sram_configure_core_dpll)(u32 sdrc_rfr_ctrl, u32 m2); u32 omap3_configure_core_dpll(u32 sdrc_rfr_ctrl, u32 sdrc_actim_ctrla, u32 sdrc_actim_ctrlb, u32 m2) -{ + { if (!_omap3_sram_configure_core_dpll) omap_sram_error(); return _omap3_sram_configure_core_dpll(sdrc_rfr_ctrl, sdrc_actim_ctrla, sdrc_actim_ctrlb, m2); -} + } /* REVISIT: Should this be same as omap34xx_sram_init() after off-idle? */ void restore_sram_functions(void) @@ -378,7 +378,7 @@ void restore_sram_functions(void) omap3_sram_configure_core_dpll_sz); } -int __init omap34xx_sram_init(void) +int __init omap3_sram_init(void) { _omap3_sram_configure_core_dpll = omap_sram_push(omap3_sram_configure_core_dpll, @@ -387,7 +387,7 @@ int __init omap34xx_sram_init(void) return 0; } #else -static inline int omap34xx_sram_init(void) +static inline int omap3_sram_init(void) { return 0; } @@ -405,7 +405,7 @@ int __init omap_sram_init(void) else if (cpu_is_omap2430()) omap243x_sram_init(); else if (cpu_is_omap34xx()) - omap34xx_sram_init(); + omap3_sram_init(); return 0; }