aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/mach-omap2
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2009-05-28 15:45:07 -0700
committerTony Lindgren <tony@atomide.com>2009-05-28 15:45:07 -0700
commit4c50d22a0cf240918d53afbf9a8416a9d93aacee (patch)
tree5b76b4c167cdc80a6911fc70b168c2a2025814db /arch/arm/mach-omap2
parent970a724d9173526512ebd8be991a4cbe18b7aace (diff)
parent7419045016e5002b3ccee72b28e41bf53dca68f2 (diff)
Merge branch 'omap3-boards' into for-next
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r--arch/arm/mach-omap2/Kconfig8
-rw-r--r--arch/arm/mach-omap2/Makefile6
-rw-r--r--arch/arm/mach-omap2/board-omap3beagle.c104
-rw-r--r--arch/arm/mach-omap2/board-omap3evm.c329
-rw-r--r--arch/arm/mach-omap2/board-omap3pandora.c194
-rw-r--r--arch/arm/mach-omap2/board-overo.c76
-rw-r--r--arch/arm/mach-omap2/board-rx51-peripherals.c30
-rw-r--r--arch/arm/mach-omap2/board-zoom-debugboard.c160
-rw-r--r--arch/arm/mach-omap2/board-zoom2.c110
-rw-r--r--arch/arm/mach-omap2/mmc-twl4030.c280
-rw-r--r--arch/arm/mach-omap2/mmc-twl4030.h3
11 files changed, 1100 insertions, 200 deletions
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 64ab386a65c..b5c9088a6a4 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -56,6 +56,10 @@ config MACH_OVERO
bool "Gumstix Overo board"
depends on ARCH_OMAP3 && ARCH_OMAP34XX
+config MACH_OMAP3EVM
+ bool "OMAP 3530 EVM board"
+ depends on ARCH_OMAP3 && ARCH_OMAP34XX
+
config MACH_OMAP3_PANDORA
bool "OMAP3 Pandora"
depends on ARCH_OMAP3 && ARCH_OMAP34XX
@@ -67,3 +71,7 @@ config MACH_OMAP_3430SDP
config MACH_NOKIA_RX51
bool "Nokia RX-51 board"
depends on ARCH_OMAP3 && ARCH_OMAP34XX
+
+config MACH_OMAP_ZOOM2
+ bool "OMAP3 Zoom2 board"
+ depends on ARCH_OMAP3 && ARCH_OMAP34XX
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 516477ee569..c48b12c0fe2 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -47,6 +47,8 @@ obj-$(CONFIG_MACH_OMAP_LDP) += board-ldp.o \
mmc-twl4030.o
obj-$(CONFIG_MACH_OVERO) += board-overo.o \
mmc-twl4030.o
+obj-$(CONFIG_MACH_OMAP3EVM) += board-omap3evm.o \
+ mmc-twl4030.o
obj-$(CONFIG_MACH_OMAP3_PANDORA) += board-omap3pandora.o \
mmc-twl4030.o
obj-$(CONFIG_MACH_OMAP_3430SDP) += board-3430sdp.o \
@@ -55,7 +57,9 @@ obj-$(CONFIG_MACH_OMAP_3430SDP) += board-3430sdp.o \
obj-$(CONFIG_MACH_NOKIA_RX51) += board-rx51.o \
board-rx51-peripherals.o \
mmc-twl4030.o
-
+obj-$(CONFIG_MACH_OMAP_ZOOM2) += board-zoom2.o \
+ mmc-twl4030.o \
+ board-zoom-debugboard.o
# Platform specific device init code
obj-y += usb-musb.o
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index f25082c53c6..991ac9c3803 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -28,6 +28,7 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/nand.h>
+#include <linux/regulator/machine.h>
#include <linux/i2c/twl4030.h>
#include <mach/hardware.h>
@@ -120,6 +121,23 @@ static struct twl4030_hsmmc_info mmc[] = {
{} /* Terminator */
};
+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",
+};
+
+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,
@@ -130,6 +148,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
*/
@@ -158,12 +180,85 @@ static struct twl4030_gpio_platform_data beagle_gpio_data = {
.setup = beagle_twl_gpio_setup,
};
+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 struct twl4030_platform_data beagle_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
/* platform_data for children goes here */
.gpio = &beagle_gpio_data,
+ .vmmc1 = &beagle_vmmc1,
+ .vsim = &beagle_vsim,
+ .vdac = &beagle_vdac,
+ .vpll2 = &beagle_vpll2,
};
static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = {
@@ -195,15 +290,6 @@ static void __init omap3_beagle_init_irq(void)
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",
-};
-
static struct gpio_led gpio_leds[] = {
{
.name = "beagleboard::usr0",
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
new file mode 100644
index 00000000000..d3cc145814d
--- /dev/null
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -0,0 +1,329 @@
+/*
+ * 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 <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/leds.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+#include <linux/i2c/twl4030.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/board.h>
+#include <mach/mux.h>
+#include <mach/usb.h>
+#include <mach/common.h>
+#include <mach/mcspi.h>
+#include <mach/keypad.h>
+
+#include "sdram-micron-mt46h32m32lf-6.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
+
+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,
+ .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();
+ 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 3571bb47ab8..e32aa23ce96 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -23,7 +23,11 @@
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
+#include <linux/regulator/machine.h>
#include <linux/i2c/twl4030.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -35,12 +39,154 @@
#include <mach/hardware.h>
#include <mach/mcspi.h>
#include <mach/usb.h>
+#include <mach/keypad.h>
#include "sdram-micron-mt46h32m32lf-6.h"
#include "mmc-twl4030.h"
#define OMAP3_PANDORA_TS_GPIO 94
+/* hardware debounce: (value + 1) * 31us */
+#define GPIO_DEBOUNCE_TIME 127
+
+static struct gpio_led pandora_gpio_leds[] = {
+ {
+ .name = "pandora::sd1",
+ .default_trigger = "mmc0",
+ .gpio = 128,
+ }, {
+ .name = "pandora::sd2",
+ .default_trigger = "mmc1",
+ .gpio = 129,
+ }, {
+ .name = "pandora::bluetooth",
+ .gpio = 158,
+ }, {
+ .name = "pandora::wifi",
+ .gpio = 159,
+ },
+};
+
+static struct gpio_led_platform_data pandora_gpio_led_data = {
+ .leds = pandora_gpio_leds,
+ .num_leds = ARRAY_SIZE(pandora_gpio_leds),
+};
+
+static struct platform_device pandora_leds_gpio = {
+ .name = "leds-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &pandora_gpio_led_data,
+ },
+};
+
+#define GPIO_BUTTON(gpio_num, ev_type, ev_code, act_low, descr) \
+{ \
+ .gpio = gpio_num, \
+ .type = ev_type, \
+ .code = ev_code, \
+ .active_low = act_low, \
+ .desc = "btn " descr, \
+}
+
+#define GPIO_BUTTON_LOW(gpio_num, event_code, description) \
+ GPIO_BUTTON(gpio_num, EV_KEY, event_code, 1, description)
+
+static struct gpio_keys_button pandora_gpio_keys[] = {
+ GPIO_BUTTON_LOW(110, KEY_UP, "up"),
+ GPIO_BUTTON_LOW(103, KEY_DOWN, "down"),
+ GPIO_BUTTON_LOW(96, KEY_LEFT, "left"),
+ GPIO_BUTTON_LOW(98, KEY_RIGHT, "right"),
+ GPIO_BUTTON_LOW(111, BTN_A, "a"),
+ GPIO_BUTTON_LOW(106, BTN_B, "b"),
+ GPIO_BUTTON_LOW(109, BTN_X, "x"),
+ GPIO_BUTTON_LOW(101, BTN_Y, "y"),
+ GPIO_BUTTON_LOW(102, BTN_TL, "l"),
+ GPIO_BUTTON_LOW(97, BTN_TL2, "l2"),
+ GPIO_BUTTON_LOW(105, BTN_TR, "r"),
+ GPIO_BUTTON_LOW(107, BTN_TR2, "r2"),
+ GPIO_BUTTON_LOW(104, KEY_LEFTCTRL, "ctrl"),
+ GPIO_BUTTON_LOW(99, KEY_MENU, "menu"),
+ GPIO_BUTTON_LOW(176, KEY_COFFEE, "hold"),
+ GPIO_BUTTON(100, EV_KEY, KEY_LEFTALT, 0, "alt"),
+ GPIO_BUTTON(108, EV_SW, SW_LID, 1, "lid"),
+};
+
+static struct gpio_keys_platform_data pandora_gpio_key_info = {
+ .buttons = pandora_gpio_keys,
+ .nbuttons = ARRAY_SIZE(pandora_gpio_keys),
+};
+
+static struct platform_device pandora_keys_gpio = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &pandora_gpio_key_info,
+ },
+};
+
+static void __init pandora_keys_gpio_init(void)
+{
+ /* set debounce time for GPIO banks 4 and 6 */
+ omap_set_gpio_debounce_time(32 * 3, GPIO_DEBOUNCE_TIME);
+ omap_set_gpio_debounce_time(32 * 5, GPIO_DEBOUNCE_TIME);
+}
+
+static int pandora_keypad_map[] = {
+ /* col, row, code */
+ KEY(0, 0, KEY_9),
+ KEY(0, 1, KEY_0),
+ KEY(0, 2, KEY_BACKSPACE),
+ KEY(0, 3, KEY_O),
+ KEY(0, 4, KEY_P),
+ KEY(0, 5, KEY_K),
+ KEY(0, 6, KEY_L),
+ KEY(0, 7, KEY_ENTER),
+ KEY(1, 0, KEY_8),
+ KEY(1, 1, KEY_7),
+ KEY(1, 2, KEY_6),
+ KEY(1, 3, KEY_5),
+ KEY(1, 4, KEY_4),
+ KEY(1, 5, KEY_3),
+ KEY(1, 6, KEY_2),
+ KEY(1, 7, KEY_1),
+ KEY(2, 0, KEY_I),
+ KEY(2, 1, KEY_U),
+ KEY(2, 2, KEY_Y),
+ KEY(2, 3, KEY_T),
+ KEY(2, 4, KEY_R),
+ KEY(2, 5, KEY_E),
+ KEY(2, 6, KEY_W),
+ KEY(2, 7, KEY_Q),
+ KEY(3, 0, KEY_J),
+ KEY(3, 1, KEY_H),
+ KEY(3, 2, KEY_G),
+ KEY(3, 3, KEY_F),
+ KEY(3, 4, KEY_D),
+ KEY(3, 5, KEY_S),
+ KEY(3, 6, KEY_A),
+ KEY(3, 7, KEY_LEFTSHIFT),
+ KEY(4, 0, KEY_N),
+ KEY(4, 1, KEY_B),
+ KEY(4, 2, KEY_V),
+ KEY(4, 3, KEY_C),
+ KEY(4, 4, KEY_X),
+ KEY(4, 5, KEY_Z),
+ KEY(4, 6, KEY_DOT),
+ KEY(4, 7, KEY_COMMA),
+ KEY(5, 0, KEY_M),
+ KEY(5, 1, KEY_SPACE),
+ KEY(5, 2, KEY_FN),
+};
+
+static struct twl4030_keypad_data pandora_kp_data = {
+ .rows = 8,
+ .cols = 6,
+ .keymap = pandora_keypad_map,
+ .keymapsize = ARRAY_SIZE(pandora_keypad_map),
+ .rep = 1,
+};
+
static struct twl4030_hsmmc_info omap3pandora_mmc[] = {
{
.mmc = 1,
@@ -70,6 +216,14 @@ static struct omap_uart_config omap3pandora_uart_config __initdata = {
.enabled_uarts = (1 << 2), /* UART3 */
};
+static struct regulator_consumer_supply pandora_vmmc1_supply = {
+ .supply = "vmmc",
+};
+
+static struct regulator_consumer_supply pandora_vmmc2_supply = {
+ .supply = "vmmc",
+};
+
static int omap3pandora_twl_gpio_setup(struct device *dev,
unsigned gpio, unsigned ngpio)
{
@@ -78,6 +232,10 @@ static int omap3pandora_twl_gpio_setup(struct device *dev,
omap3pandora_mmc[1].gpio_cd = gpio + 1;
twl4030_mmc_init(omap3pandora_mmc);
+ /* link regulators to MMC adapters */
+ pandora_vmmc1_supply.dev = omap3pandora_mmc[0].dev;
+ pandora_vmmc2_supply.dev = omap3pandora_mmc[1].dev;
+
return 0;
}
@@ -88,6 +246,36 @@ static struct twl4030_gpio_platform_data omap3pandora_gpio_data = {
.setup = omap3pandora_twl_gpio_setup,
};
+/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
+static struct regulator_init_data pandora_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 = &pandora_vmmc1_supply,
+};
+
+/* VMMC2 for MMC2 pins CMD, CLK, DAT0..DAT3 (max 100 mA) */
+static struct regulator_init_data pandora_vmmc2 = {
+ .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 = &pandora_vmmc2_supply,
+};
+
static struct twl4030_usb_data omap3pandora_usb_data = {
.usb_mode = T2_USB_MODE_ULPI,
};
@@ -97,6 +285,9 @@ static struct twl4030_platform_data omap3pandora_twldata = {
.irq_end = TWL4030_IRQ_END,
.gpio = &omap3pandora_gpio_data,
.usb = &omap3pandora_usb_data,
+ .vmmc1 = &pandora_vmmc1,
+ .vmmc2 = &pandora_vmmc2,
+ .keypad = &pandora_kp_data,
};
static struct i2c_board_info __initdata omap3pandora_i2c_boardinfo[] = {
@@ -189,6 +380,8 @@ static struct omap_board_config_kernel omap3pandora_config[] __initdata = {
static struct platform_device *omap3pandora_devices[] __initdata = {
&omap3pandora_lcd_device,
+ &pandora_leds_gpio,
+ &pandora_keys_gpio,
};
static void __init omap3pandora_init(void)
@@ -202,6 +395,7 @@ static void __init omap3pandora_init(void)
spi_register_board_info(omap3pandora_spi_board_info,
ARRAY_SIZE(omap3pandora_spi_board_info));
omap3pandora_ads7846_init();
+ pandora_keys_gpio_init();
usb_musb_init();
}
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index c7443ff98ee..dff5528fbfb 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -27,6 +27,7 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/i2c/twl4030.h>
+#include <linux/regulator/machine.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
@@ -272,21 +273,76 @@ 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,
+ .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,
@@ -327,23 +383,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();
@@ -351,7 +390,6 @@ 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();
overo_ads7846_init();
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index 233c7454d84..da93b86234e 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -32,6 +32,9 @@
#include "mmc-twl4030.h"
+#define SYSTEM_REV_B_USES_VAUX3 0x1699
+#define SYSTEM_REV_S_USES_VAUX3 0x8
+
static int rx51_keymap[] = {
KEY(0, 0, KEY_Q),
KEY(0, 1, KEY_W),
@@ -147,7 +150,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,
@@ -160,6 +163,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",
@@ -270,10 +289,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,
};
@@ -289,6 +306,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);
diff --git a/arch/arm/mach-omap2/board-zoom-debugboard.c b/arch/arm/mach-omap2/board-zoom-debugboard.c
new file mode 100644
index 00000000000..bac5c4321ff
--- /dev/null
+++ b/arch/arm/mach-omap2/board-zoom-debugboard.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2009 Texas Instruments Inc.
+ * Mikkel Christensen <mlc@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/serial_8250.h>
+#include <linux/smsc911x.h>
+
+#include <mach/gpmc.h>
+
+#define ZOOM2_SMSC911X_CS 7
+#define ZOOM2_SMSC911X_GPIO 158
+#define ZOOM2_QUADUART_CS 3
+#define ZOOM2_QUADUART_GPIO 102
+#define QUART_CLK 1843200
+#define DEBUG_BASE 0x08000000
+#define ZOOM2_ETHR_START DEBUG_BASE
+
+static struct resource zoom2_smsc911x_resources[] = {
+ [0] = {
+ .start = ZOOM2_ETHR_START,
+ .end = ZOOM2_ETHR_START + SZ_4K,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
+ },
+};
+
+static struct smsc911x_platform_config zoom2_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 zoom2_smsc911x_device = {
+ .name = "smsc911x",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(zoom2_smsc911x_resources),
+ .resource = zoom2_smsc911x_resources,
+ .dev = {
+ .platform_data = &zoom2_smsc911x_config,
+ },
+};
+
+static inline void __init zoom2_init_smsc911x(void)
+{
+ int eth_cs;
+ unsigned long cs_mem_base;
+ int eth_gpio = 0;
+
+ eth_cs = ZOOM2_SMSC911X_CS;
+
+ if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) {
+ printk(KERN_ERR "Failed to request GPMC mem for smsc911x\n");
+ return;
+ }
+
+ zoom2_smsc911x_resources[0].start = cs_mem_base + 0x0;
+ zoom2_smsc911x_resources[0].end = cs_mem_base + 0xff;
+
+ eth_gpio = ZOOM2_SMSC911X_GPIO;
+
+ zoom2_smsc911x_resources[1].start = OMAP_GPIO_IRQ(eth_gpio);
+
+ if (gpio_request(eth_gpio, "smsc911x irq") < 0) {
+ printk(KERN_ERR "Failed to request GPIO%d for smsc911x IRQ\n",
+ eth_gpio);
+ return;
+ }
+ gpio_direction_input(eth_gpio);
+}
+
+static struct plat_serial8250_port serial_platform_data[] = {
+ {
+ .mapbase = 0x10000000,
+ .irq = OMAP_GPIO_IRQ(102),
+ .flags = UPF_BOOT_AUTOCONF|UPF_IOREMAP|UPF_SHARE_IRQ,
+ .iotype = UPIO_MEM,
+ .regshift = 1,
+ .uartclk = QUART_CLK,
+ }, {
+ .flags = 0
+ }
+};
+
+static struct platform_device zoom2_debugboard_serial_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM1,
+ .dev = {
+ .platform_data = serial_platform_data,
+ },
+};
+
+static inline void __init zoom2_init_quaduart(void)
+{
+ int quart_cs;
+ unsigned long cs_mem_base;
+ int quart_gpio = 0;
+
+ quart_cs = ZOOM2_QUADUART_CS;
+
+ if (gpmc_cs_request(quart_cs, SZ_1M, &cs_mem_base) < 0) {
+ printk(KERN_ERR "Failed to request GPMC mem"
+ "for Quad UART(TL16CP754C)\n");
+ return;
+ }
+
+ quart_gpio = ZOOM2_QUADUART_GPIO;
+
+ if (gpio_request(quart_gpio, "TL16CP754C GPIO") < 0) {
+ printk(KERN_ERR "Failed to request GPIO%d for TL16CP754C\n",
+ quart_gpio);
+ return;
+ }
+ gpio_direction_input(quart_gpio);
+}
+
+static inline int omap_zoom2_debugboard_detect(void)
+{
+ int debug_board_detect = 0;
+
+ debug_board_detect = ZOOM2_SMSC911X_GPIO;
+
+ if (gpio_request(debug_board_detect, "Zoom2 debug board detect") < 0) {
+ printk(KERN_ERR "Failed to request GPIO%d for Zoom2 debug"
+ "board detect\n", debug_board_detect);
+ return 0;
+ }
+ gpio_direction_input(debug_board_detect);
+
+ if (!gpio_get_value(debug_board_detect)) {
+ gpio_free(debug_board_detect);
+ return 0;
+ }
+ return 1;
+}
+
+static struct platform_device *zoom2_devices[] __initdata = {
+ &zoom2_smsc911x_device,
+ &zoom2_debugboard_serial_device,
+};
+
+int __init omap_zoom2_debugboard_init(void)
+{
+ if (!omap_zoom2_debugboard_detect())
+ return 0;
+
+ zoom2_init_smsc911x();
+ zoom2_init_quaduart();
+ return platform_add_devices(zoom2_devices, ARRAY_SIZE(zoom2_devices));
+}
diff --git a/arch/arm/mach-omap2/board-zoom2.c b/arch/arm/mach-omap2/board-zoom2.c
new file mode 100644
index 00000000000..bcc0f7632de
--- /dev/null
+++ b/arch/arm/mach-omap2/board-zoom2.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2009 Texas Instruments Inc.
+ * Mikkel Christensen <mlc@ti.com>
+ *
+ * Modified from mach-omap2/board-ldp.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 <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/i2c/twl4030.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/common.h>
+#include <mach/usb.h>
+
+#include "mmc-twl4030.h"
+
+static void __init omap_zoom2_init_irq(void)
+{
+ omap2_init_common_hw(NULL);
+ omap_init_irq();
+ omap_gpio_init();
+}
+
+static struct omap_uart_config zoom2_uart_config __initdata = {
+ .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)),
+};
+
+static struct omap_board_config_kernel zoom2_config[] __initdata = {
+ { OMAP_TAG_UART, &zoom2_uart_config },
+};
+
+static struct twl4030_gpio_platform_data zoom2_gpio_data = {
+ .gpio_base = OMAP_MAX_GPIO_LINES,
+ .irq_base = TWL4030_GPIO_IRQ_BASE,
+ .irq_end = TWL4030_GPIO_IRQ_END,
+};
+
+static struct twl4030_platform_data zoom2_twldata = {
+ .irq_base = TWL4030_IRQ_BASE,
+ .irq_end = TWL4030_IRQ_END,
+
+ /* platform_data for children goes here */
+ .gpio = &zoom2_gpio_data,
+};
+
+static struct i2c_board_info __initdata zoom2_i2c_boardinfo[] = {
+ {
+ I2C_BOARD_INFO("twl4030", 0x48),
+ .flags = I2C_CLIENT_WAKE,
+ .irq = INT_34XX_SYS_NIRQ,
+ .platform_data = &zoom2_twldata,
+ },
+};
+
+static int __init omap_i2c_init(void)
+{
+ omap_register_i2c_bus(1, 2600, zoom2_i2c_boardinfo,
+ ARRAY_SIZE(zoom2_i2c_boardinfo));
+ omap_register_i2c_bus(2, 400, NULL, 0);
+ omap_register_i2c_bus(3, 400, NULL, 0);
+ return 0;
+}
+
+static struct twl4030_hsmmc_info mmc[] __initdata = {
+ {
+ .mmc = 1,
+ .wires = 4,
+ .gpio_cd = -EINVAL,
+ .gpio_wp = -EINVAL,
+ },
+ {} /* Terminator */
+};
+
+extern int __init omap_zoom2_debugboard_init(void);
+
+static void __init omap_zoom2_init(void)
+{
+ omap_i2c_init();
+ omap_board_config = zoom2_config;
+ omap_board_config_size = ARRAY_SIZE(zoom2_config);
+ omap_serial_init();
+ omap_zoom2_debugboard_init();
+ twl4030_mmc_init(mmc);
+ usb_musb_init();
+}
+
+static void __init omap_zoom2_map_io(void)
+{
+ omap2_set_globals_343x();
+ omap2_map_common_io();
+}
+
+MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board")
+ .phys_io = 0x48000000,
+ .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc,
+ .boot_params = 0x80000100,
+ .map_io = omap_zoom2_map_io,
+ .init_irq = omap_zoom2_init_irq,
+ .init_machine = omap_zoom2_init,
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c
index dc40b3e7220..9756a878fd9 100644
--- a/arch/arm/mach-omap2/mmc-twl4030.c
+++ b/arch/arm/mach-omap2/mmc-twl4030.c
@@ -16,8 +16,8 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/gpio.h>
-#include <linux/i2c/twl4030.h>
-#include <linux/regulator/machine.h>
+#include <linux/mmc/host.h>
+#include <linux/regulator/consumer.h>
#include <mach/hardware.h>
#include <mach/control.h>
@@ -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,60 @@ 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 enabling 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) {
+ regulator_enable(hsmmc[i].vcc);
+ regulator_disable(hsmmc[i].vcc);
+ }
+ if (hsmmc[i].vcc_aux) {
+ if (regulator_is_enabled(reg) > 0) {
+ regulator_enable(reg);
+ regulator_disable(reg);
+ }
+ }
+
break;
}
}
@@ -173,96 +192,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 +202,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 +231,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 +247,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 +260,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 +294,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)
@@ -412,10 +356,10 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers)
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 +383,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))