diff options
Diffstat (limited to 'arch/arm/mach-omap2')
| -rw-r--r-- | arch/arm/mach-omap2/Makefile | 15 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/board-2430sdp.c | 48 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/board-apollon.c | 11 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/board-generic.c | 11 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/board-h4.c | 11 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/board-ldp.c | 40 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/board-omap3beagle.c | 90 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/board-omap3pandora.c | 32 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/board-overo.c | 43 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/clock24xx.h | 9 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/clock34xx.h | 10 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/devices.c | 169 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/mmc-twl4030.c | 408 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/mmc-twl4030.h | 29 |
14 files changed, 875 insertions, 51 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index f12c43e4932f..bbd12bc10fdc 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile | |||
| @@ -27,10 +27,15 @@ obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o | |||
| 27 | # Specific board support | 27 | # Specific board support |
| 28 | obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o | 28 | obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o |
| 29 | obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o | 29 | obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o |
| 30 | obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.o | 30 | obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.o \ |
| 31 | mmc-twl4030.o | ||
| 31 | obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o | 32 | obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o |
| 32 | obj-$(CONFIG_MACH_OMAP3_BEAGLE) += board-omap3beagle.o | 33 | obj-$(CONFIG_MACH_OMAP3_BEAGLE) += board-omap3beagle.o \ |
| 33 | obj-$(CONFIG_MACH_OMAP_LDP) += board-ldp.o | 34 | mmc-twl4030.o |
| 34 | obj-$(CONFIG_MACH_OVERO) += board-overo.o | 35 | obj-$(CONFIG_MACH_OMAP_LDP) += board-ldp.o \ |
| 35 | obj-$(CONFIG_MACH_OMAP3_PANDORA) += board-omap3pandora.o | 36 | mmc-twl4030.o |
| 37 | obj-$(CONFIG_MACH_OVERO) += board-overo.o \ | ||
| 38 | mmc-twl4030.o | ||
| 39 | obj-$(CONFIG_MACH_OMAP3_PANDORA) += board-omap3pandora.o \ | ||
| 40 | mmc-twl4030.o | ||
| 36 | 41 | ||
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index 6748de6e19a8..83fa37211d77 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/mtd/mtd.h> | 19 | #include <linux/mtd/mtd.h> |
| 20 | #include <linux/mtd/partitions.h> | 20 | #include <linux/mtd/partitions.h> |
| 21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
| 22 | #include <linux/i2c/twl4030.h> | ||
| 22 | #include <linux/err.h> | 23 | #include <linux/err.h> |
| 23 | #include <linux/clk.h> | 24 | #include <linux/clk.h> |
| 24 | #include <linux/io.h> | 25 | #include <linux/io.h> |
| @@ -35,6 +36,7 @@ | |||
| 35 | #include <mach/common.h> | 36 | #include <mach/common.h> |
| 36 | #include <mach/gpmc.h> | 37 | #include <mach/gpmc.h> |
| 37 | 38 | ||
| 39 | #include "mmc-twl4030.h" | ||
| 38 | 40 | ||
| 39 | #define SDP2430_FLASH_CS 0 | 41 | #define SDP2430_FLASH_CS 0 |
| 40 | #define SDP2430_SMC91X_CS 5 | 42 | #define SDP2430_SMC91X_CS 5 |
| @@ -197,12 +199,58 @@ static struct omap_board_config_kernel sdp2430_config[] = { | |||
| 197 | {OMAP_TAG_UART, &sdp2430_uart_config}, | 199 | {OMAP_TAG_UART, &sdp2430_uart_config}, |
| 198 | }; | 200 | }; |
| 199 | 201 | ||
| 202 | |||
| 203 | static struct twl4030_gpio_platform_data sdp2430_gpio_data = { | ||
| 204 | .gpio_base = OMAP_MAX_GPIO_LINES, | ||
| 205 | .irq_base = TWL4030_GPIO_IRQ_BASE, | ||
| 206 | .irq_end = TWL4030_GPIO_IRQ_END, | ||
| 207 | }; | ||
| 208 | |||
| 209 | static struct twl4030_platform_data sdp2430_twldata = { | ||
| 210 | .irq_base = TWL4030_IRQ_BASE, | ||
| 211 | .irq_end = TWL4030_IRQ_END, | ||
| 212 | |||
| 213 | /* platform_data for children goes here */ | ||
| 214 | .gpio = &sdp2430_gpio_data, | ||
| 215 | }; | ||
| 216 | |||
| 217 | static struct i2c_board_info __initdata sdp2430_i2c_boardinfo[] = { | ||
| 218 | { | ||
| 219 | I2C_BOARD_INFO("twl4030", 0x48), | ||
| 220 | .flags = I2C_CLIENT_WAKE, | ||
| 221 | .irq = INT_24XX_SYS_NIRQ, | ||
| 222 | .platform_data = &sdp2430_twldata, | ||
| 223 | }, | ||
| 224 | }; | ||
| 225 | |||
| 226 | static int __init omap2430_i2c_init(void) | ||
| 227 | { | ||
| 228 | omap_register_i2c_bus(1, 400, NULL, 0); | ||
| 229 | omap_register_i2c_bus(2, 2600, sdp2430_i2c_boardinfo, | ||
| 230 | ARRAY_SIZE(sdp2430_i2c_boardinfo)); | ||
| 231 | return 0; | ||
| 232 | } | ||
| 233 | |||
| 234 | static struct twl4030_hsmmc_info mmc[] __initdata = { | ||
| 235 | { | ||
| 236 | .mmc = 1, | ||
| 237 | .wires = 4, | ||
| 238 | .gpio_cd = -EINVAL, | ||
| 239 | .gpio_wp = -EINVAL, | ||
| 240 | .ext_clock = 1, | ||
| 241 | }, | ||
| 242 | {} /* Terminator */ | ||
| 243 | }; | ||
| 244 | |||
| 200 | static void __init omap_2430sdp_init(void) | 245 | static void __init omap_2430sdp_init(void) |
| 201 | { | 246 | { |
| 247 | omap2430_i2c_init(); | ||
| 248 | |||
| 202 | platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices)); | 249 | platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices)); |
| 203 | omap_board_config = sdp2430_config; | 250 | omap_board_config = sdp2430_config; |
| 204 | omap_board_config_size = ARRAY_SIZE(sdp2430_config); | 251 | omap_board_config_size = ARRAY_SIZE(sdp2430_config); |
| 205 | omap_serial_init(); | 252 | omap_serial_init(); |
| 253 | twl4030_mmc_init(mmc); | ||
| 206 | } | 254 | } |
| 207 | 255 | ||
| 208 | static void __init omap_2430sdp_map_io(void) | 256 | static void __init omap_2430sdp_map_io(void) |
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c index d83035b436d5..bf1e5d32c2a3 100644 --- a/arch/arm/mach-omap2/board-apollon.c +++ b/arch/arm/mach-omap2/board-apollon.c | |||
| @@ -261,16 +261,6 @@ static struct omap_uart_config apollon_uart_config __initdata = { | |||
| 261 | .enabled_uarts = (1 << 0) | (0 << 1) | (0 << 2), | 261 | .enabled_uarts = (1 << 0) | (0 << 1) | (0 << 2), |
| 262 | }; | 262 | }; |
| 263 | 263 | ||
| 264 | static struct omap_mmc_config apollon_mmc_config __initdata = { | ||
| 265 | .mmc [0] = { | ||
| 266 | .enabled = 1, | ||
| 267 | .wire4 = 1, | ||
| 268 | .wp_pin = -1, | ||
| 269 | .power_pin = -1, | ||
| 270 | .switch_pin = -1, | ||
| 271 | }, | ||
| 272 | }; | ||
| 273 | |||
| 274 | static struct omap_usb_config apollon_usb_config __initdata = { | 264 | static struct omap_usb_config apollon_usb_config __initdata = { |
| 275 | .register_dev = 1, | 265 | .register_dev = 1, |
| 276 | .hmc_mode = 0x14, /* 0:dev 1:host1 2:disable */ | 266 | .hmc_mode = 0x14, /* 0:dev 1:host1 2:disable */ |
| @@ -284,7 +274,6 @@ static struct omap_lcd_config apollon_lcd_config __initdata = { | |||
| 284 | 274 | ||
| 285 | static struct omap_board_config_kernel apollon_config[] = { | 275 | static struct omap_board_config_kernel apollon_config[] = { |
| 286 | { OMAP_TAG_UART, &apollon_uart_config }, | 276 | { OMAP_TAG_UART, &apollon_uart_config }, |
| 287 | { OMAP_TAG_MMC, &apollon_mmc_config }, | ||
| 288 | { OMAP_TAG_USB, &apollon_usb_config }, | 277 | { OMAP_TAG_USB, &apollon_usb_config }, |
| 289 | { OMAP_TAG_LCD, &apollon_lcd_config }, | 278 | { OMAP_TAG_LCD, &apollon_lcd_config }, |
| 290 | }; | 279 | }; |
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c index 9ba097868e72..3b34c20d1df4 100644 --- a/arch/arm/mach-omap2/board-generic.c +++ b/arch/arm/mach-omap2/board-generic.c | |||
| @@ -41,19 +41,8 @@ static struct omap_uart_config generic_uart_config __initdata = { | |||
| 41 | .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), | 41 | .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), |
| 42 | }; | 42 | }; |
| 43 | 43 | ||
| 44 | static struct omap_mmc_config generic_mmc_config __initdata = { | ||
| 45 | .mmc [0] = { | ||
| 46 | .enabled = 0, | ||
| 47 | .wire4 = 0, | ||
| 48 | .wp_pin = -1, | ||
| 49 | .power_pin = -1, | ||
| 50 | .switch_pin = -1, | ||
| 51 | }, | ||
| 52 | }; | ||
| 53 | |||
| 54 | static struct omap_board_config_kernel generic_config[] = { | 44 | static struct omap_board_config_kernel generic_config[] = { |
| 55 | { OMAP_TAG_UART, &generic_uart_config }, | 45 | { OMAP_TAG_UART, &generic_uart_config }, |
| 56 | { OMAP_TAG_MMC, &generic_mmc_config }, | ||
| 57 | }; | 46 | }; |
| 58 | 47 | ||
| 59 | static void __init omap_generic_init(void) | 48 | static void __init omap_generic_init(void) |
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c index 7de0506e1e29..5e9b14675b1e 100644 --- a/arch/arm/mach-omap2/board-h4.c +++ b/arch/arm/mach-omap2/board-h4.c | |||
| @@ -373,23 +373,12 @@ static struct omap_uart_config h4_uart_config __initdata = { | |||
| 373 | .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), | 373 | .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), |
| 374 | }; | 374 | }; |
| 375 | 375 | ||
| 376 | static struct omap_mmc_config h4_mmc_config __initdata = { | ||
| 377 | .mmc [0] = { | ||
| 378 | .enabled = 1, | ||
| 379 | .wire4 = 1, | ||
| 380 | .wp_pin = -1, | ||
| 381 | .power_pin = -1, | ||
| 382 | .switch_pin = -1, | ||
| 383 | }, | ||
| 384 | }; | ||
| 385 | |||
| 386 | static struct omap_lcd_config h4_lcd_config __initdata = { | 376 | static struct omap_lcd_config h4_lcd_config __initdata = { |
| 387 | .ctrl_name = "internal", | 377 | .ctrl_name = "internal", |
| 388 | }; | 378 | }; |
| 389 | 379 | ||
| 390 | static struct omap_board_config_kernel h4_config[] = { | 380 | static struct omap_board_config_kernel h4_config[] = { |
| 391 | { OMAP_TAG_UART, &h4_uart_config }, | 381 | { OMAP_TAG_UART, &h4_uart_config }, |
| 392 | { OMAP_TAG_MMC, &h4_mmc_config }, | ||
| 393 | { OMAP_TAG_LCD, &h4_lcd_config }, | 382 | { OMAP_TAG_LCD, &h4_lcd_config }, |
| 394 | }; | 383 | }; |
| 395 | 384 | ||
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c index 43c7ac4b7f8f..aa6972781e4a 100644 --- a/arch/arm/mach-omap2/board-ldp.c +++ b/arch/arm/mach-omap2/board-ldp.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/clk.h> | 21 | #include <linux/clk.h> |
| 22 | #include <linux/spi/spi.h> | 22 | #include <linux/spi/spi.h> |
| 23 | #include <linux/spi/ads7846.h> | 23 | #include <linux/spi/ads7846.h> |
| 24 | #include <linux/i2c/twl4030.h> | ||
| 24 | 25 | ||
| 25 | #include <mach/hardware.h> | 26 | #include <mach/hardware.h> |
| 26 | #include <asm/mach-types.h> | 27 | #include <asm/mach-types.h> |
| @@ -38,6 +39,8 @@ | |||
| 38 | #include <asm/delay.h> | 39 | #include <asm/delay.h> |
| 39 | #include <mach/control.h> | 40 | #include <mach/control.h> |
| 40 | 41 | ||
| 42 | #include "mmc-twl4030.h" | ||
| 43 | |||
| 41 | #define SDP3430_SMC91X_CS 3 | 44 | #define SDP3430_SMC91X_CS 3 |
| 42 | 45 | ||
| 43 | static struct resource ldp_smc911x_resources[] = { | 46 | static struct resource ldp_smc911x_resources[] = { |
| @@ -109,14 +112,48 @@ static struct omap_board_config_kernel ldp_config[] __initdata = { | |||
| 109 | { OMAP_TAG_UART, &ldp_uart_config }, | 112 | { OMAP_TAG_UART, &ldp_uart_config }, |
| 110 | }; | 113 | }; |
| 111 | 114 | ||
| 115 | static struct twl4030_gpio_platform_data ldp_gpio_data = { | ||
| 116 | .gpio_base = OMAP_MAX_GPIO_LINES, | ||
| 117 | .irq_base = TWL4030_GPIO_IRQ_BASE, | ||
| 118 | .irq_end = TWL4030_GPIO_IRQ_END, | ||
| 119 | }; | ||
| 120 | |||
| 121 | static struct twl4030_platform_data ldp_twldata = { | ||
| 122 | .irq_base = TWL4030_IRQ_BASE, | ||
| 123 | .irq_end = TWL4030_IRQ_END, | ||
| 124 | |||
| 125 | /* platform_data for children goes here */ | ||
| 126 | .gpio = &ldp_gpio_data, | ||
| 127 | }; | ||
| 128 | |||
| 129 | static struct i2c_board_info __initdata ldp_i2c_boardinfo[] = { | ||
| 130 | { | ||
| 131 | I2C_BOARD_INFO("twl4030", 0x48), | ||
| 132 | .flags = I2C_CLIENT_WAKE, | ||
| 133 | .irq = INT_34XX_SYS_NIRQ, | ||
| 134 | .platform_data = &ldp_twldata, | ||
| 135 | }, | ||
| 136 | }; | ||
| 137 | |||
| 112 | static int __init omap_i2c_init(void) | 138 | static int __init omap_i2c_init(void) |
| 113 | { | 139 | { |
| 114 | omap_register_i2c_bus(1, 2600, NULL, 0); | 140 | omap_register_i2c_bus(1, 2600, ldp_i2c_boardinfo, |
| 141 | ARRAY_SIZE(ldp_i2c_boardinfo)); | ||
| 115 | omap_register_i2c_bus(2, 400, NULL, 0); | 142 | omap_register_i2c_bus(2, 400, NULL, 0); |
| 116 | omap_register_i2c_bus(3, 400, NULL, 0); | 143 | omap_register_i2c_bus(3, 400, NULL, 0); |
| 117 | return 0; | 144 | return 0; |
| 118 | } | 145 | } |
| 119 | 146 | ||
| 147 | static struct twl4030_hsmmc_info mmc[] __initdata = { | ||
| 148 | { | ||
| 149 | .mmc = 1, | ||
| 150 | .wires = 4, | ||
| 151 | .gpio_cd = -EINVAL, | ||
| 152 | .gpio_wp = -EINVAL, | ||
| 153 | }, | ||
| 154 | {} /* Terminator */ | ||
| 155 | }; | ||
| 156 | |||
| 120 | static void __init omap_ldp_init(void) | 157 | static void __init omap_ldp_init(void) |
| 121 | { | 158 | { |
| 122 | omap_i2c_init(); | 159 | omap_i2c_init(); |
| @@ -124,6 +161,7 @@ static void __init omap_ldp_init(void) | |||
| 124 | omap_board_config = ldp_config; | 161 | omap_board_config = ldp_config; |
| 125 | omap_board_config_size = ARRAY_SIZE(ldp_config); | 162 | omap_board_config_size = ARRAY_SIZE(ldp_config); |
| 126 | omap_serial_init(); | 163 | omap_serial_init(); |
| 164 | twl4030_mmc_init(mmc); | ||
| 127 | } | 165 | } |
| 128 | 166 | ||
| 129 | static void __init omap_ldp_map_io(void) | 167 | static void __init omap_ldp_map_io(void) |
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index baa79674e9d5..9e5ada01b5fa 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c | |||
| @@ -38,7 +38,9 @@ | |||
| 38 | #include <mach/common.h> | 38 | #include <mach/common.h> |
| 39 | #include <mach/gpmc.h> | 39 | #include <mach/gpmc.h> |
| 40 | #include <mach/nand.h> | 40 | #include <mach/nand.h> |
| 41 | #include <mach/mux.h> | ||
| 41 | 42 | ||
| 43 | #include "mmc-twl4030.h" | ||
| 42 | 44 | ||
| 43 | #define GPMC_CS0_BASE 0x60 | 45 | #define GPMC_CS0_BASE 0x60 |
| 44 | #define GPMC_CS_SIZE 0x30 | 46 | #define GPMC_CS_SIZE 0x30 |
| @@ -103,6 +105,78 @@ static struct omap_uart_config omap3_beagle_uart_config __initdata = { | |||
| 103 | .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), | 105 | .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), |
| 104 | }; | 106 | }; |
| 105 | 107 | ||
| 108 | static struct twl4030_hsmmc_info mmc[] = { | ||
| 109 | { | ||
| 110 | .mmc = 1, | ||
| 111 | .wires = 8, | ||
| 112 | .gpio_wp = 29, | ||
| 113 | }, | ||
| 114 | {} /* Terminator */ | ||
| 115 | }; | ||
| 116 | |||
| 117 | static struct gpio_led gpio_leds[]; | ||
| 118 | |||
| 119 | static int beagle_twl_gpio_setup(struct device *dev, | ||
| 120 | unsigned gpio, unsigned ngpio) | ||
| 121 | { | ||
| 122 | /* gpio + 0 is "mmc0_cd" (input/IRQ) */ | ||
| 123 | |||
| 124 | /* REVISIT: need ehci-omap hooks for external VBUS | ||
| 125 | * power switch and overcurrent detect | ||
| 126 | */ | ||
| 127 | |||
| 128 | gpio_request(gpio + 1, "EHCI_nOC"); | ||
| 129 | gpio_direction_input(gpio + 1); | ||
| 130 | |||
| 131 | /* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */ | ||
| 132 | gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR"); | ||
| 133 | gpio_direction_output(gpio + TWL4030_GPIO_MAX, 1); | ||
| 134 | |||
| 135 | /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */ | ||
| 136 | gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1; | ||
| 137 | |||
| 138 | return 0; | ||
| 139 | } | ||
| 140 | |||
| 141 | static struct twl4030_gpio_platform_data beagle_gpio_data = { | ||
| 142 | .gpio_base = OMAP_MAX_GPIO_LINES, | ||
| 143 | .irq_base = TWL4030_GPIO_IRQ_BASE, | ||
| 144 | .irq_end = TWL4030_GPIO_IRQ_END, | ||
| 145 | .use_leds = true, | ||
| 146 | .pullups = BIT(1), | ||
| 147 | .pulldowns = BIT(2) | BIT(6) | BIT(7) | BIT(8) | BIT(13) | ||
| 148 | | BIT(15) | BIT(16) | BIT(17), | ||
| 149 | .setup = beagle_twl_gpio_setup, | ||
| 150 | }; | ||
| 151 | |||
| 152 | static struct twl4030_platform_data beagle_twldata = { | ||
| 153 | .irq_base = TWL4030_IRQ_BASE, | ||
| 154 | .irq_end = TWL4030_IRQ_END, | ||
| 155 | |||
| 156 | /* platform_data for children goes here */ | ||
| 157 | .gpio = &beagle_gpio_data, | ||
| 158 | }; | ||
| 159 | |||
| 160 | static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = { | ||
| 161 | { | ||
| 162 | I2C_BOARD_INFO("twl4030", 0x48), | ||
| 163 | .flags = I2C_CLIENT_WAKE, | ||
| 164 | .irq = INT_34XX_SYS_NIRQ, | ||
| 165 | .platform_data = &beagle_twldata, | ||
| 166 | }, | ||
| 167 | }; | ||
| 168 | |||
| 169 | static int __init omap3_beagle_i2c_init(void) | ||
| 170 | { | ||
| 171 | omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo, | ||
| 172 | ARRAY_SIZE(beagle_i2c_boardinfo)); | ||
| 173 | #ifdef CONFIG_I2C2_OMAP_BEAGLE | ||
| 174 | omap_register_i2c_bus(2, 400, NULL, 0); | ||
| 175 | #endif | ||
| 176 | omap_register_i2c_bus(3, 400, NULL, 0); | ||
| 177 | return 0; | ||
| 178 | } | ||
| 179 | |||
| 106 | static void __init omap3_beagle_init_irq(void) | 180 | static void __init omap3_beagle_init_irq(void) |
| 107 | { | 181 | { |
| 108 | omap2_init_common_hw(); | 182 | omap2_init_common_hw(); |
| @@ -130,6 +204,11 @@ static struct gpio_led gpio_leds[] = { | |||
| 130 | .default_trigger = "mmc0", | 204 | .default_trigger = "mmc0", |
| 131 | .gpio = 149, | 205 | .gpio = 149, |
| 132 | }, | 206 | }, |
| 207 | { | ||
| 208 | .name = "beagleboard::pmu_stat", | ||
| 209 | .gpio = -EINVAL, /* gets replaced */ | ||
| 210 | .active_low = true, | ||
| 211 | }, | ||
| 133 | }; | 212 | }; |
| 134 | 213 | ||
| 135 | static struct gpio_led_platform_data gpio_led_info = { | 214 | static struct gpio_led_platform_data gpio_led_info = { |
| @@ -218,11 +297,22 @@ static void __init omap3beagle_flash_init(void) | |||
| 218 | 297 | ||
| 219 | static void __init omap3_beagle_init(void) | 298 | static void __init omap3_beagle_init(void) |
| 220 | { | 299 | { |
| 300 | omap3_beagle_i2c_init(); | ||
| 221 | platform_add_devices(omap3_beagle_devices, | 301 | platform_add_devices(omap3_beagle_devices, |
| 222 | ARRAY_SIZE(omap3_beagle_devices)); | 302 | ARRAY_SIZE(omap3_beagle_devices)); |
| 223 | omap_board_config = omap3_beagle_config; | 303 | omap_board_config = omap3_beagle_config; |
| 224 | omap_board_config_size = ARRAY_SIZE(omap3_beagle_config); | 304 | omap_board_config_size = ARRAY_SIZE(omap3_beagle_config); |
| 225 | omap_serial_init(); | 305 | omap_serial_init(); |
| 306 | |||
| 307 | omap_cfg_reg(AH8_34XX_GPIO29); | ||
| 308 | mmc[0].gpio_cd = gpio + 0; | ||
| 309 | twl4030_mmc_init(mmc); | ||
| 310 | |||
| 311 | omap_cfg_reg(J25_34XX_GPIO170); | ||
| 312 | gpio_request(170, "DVI_nPD"); | ||
| 313 | /* REVISIT leave DVI powered down until it's needed ... */ | ||
| 314 | gpio_direction_output(170, true); | ||
| 315 | |||
| 226 | omap3beagle_flash_init(); | 316 | omap3beagle_flash_init(); |
| 227 | } | 317 | } |
| 228 | 318 | ||
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index 7236c7be05b3..b3196107afdb 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c | |||
| @@ -35,16 +35,48 @@ | |||
| 35 | #include <mach/hardware.h> | 35 | #include <mach/hardware.h> |
| 36 | #include <mach/mcspi.h> | 36 | #include <mach/mcspi.h> |
| 37 | 37 | ||
| 38 | #include "mmc-twl4030.h" | ||
| 39 | |||
| 38 | #define OMAP3_PANDORA_TS_GPIO 94 | 40 | #define OMAP3_PANDORA_TS_GPIO 94 |
| 39 | 41 | ||
| 42 | static struct twl4030_hsmmc_info omap3pandora_mmc[] = { | ||
| 43 | { | ||
| 44 | .mmc = 1, | ||
| 45 | .wires = 4, | ||
| 46 | .gpio_cd = -EINVAL, | ||
| 47 | .gpio_wp = 126, | ||
| 48 | .ext_clock = 0, | ||
| 49 | }, | ||
| 50 | { | ||
| 51 | .mmc = 2, | ||
| 52 | .wires = 4, | ||
| 53 | .gpio_cd = -EINVAL, | ||
| 54 | .gpio_wp = 127, | ||
| 55 | .ext_clock = 1, | ||
| 56 | }, | ||
| 57 | {} /* Terminator */ | ||
| 58 | }; | ||
| 59 | |||
| 40 | static struct omap_uart_config omap3pandora_uart_config __initdata = { | 60 | static struct omap_uart_config omap3pandora_uart_config __initdata = { |
| 41 | .enabled_uarts = (1 << 2), /* UART3 */ | 61 | .enabled_uarts = (1 << 2), /* UART3 */ |
| 42 | }; | 62 | }; |
| 43 | 63 | ||
| 64 | static int omap3pandora_twl_gpio_setup(struct device *dev, | ||
| 65 | unsigned gpio, unsigned ngpio) | ||
| 66 | { | ||
| 67 | /* gpio + {0,1} is "mmc{0,1}_cd" (input/IRQ) */ | ||
| 68 | omap3pandora_mmc[0].gpio_cd = gpio + 0; | ||
| 69 | omap3pandora_mmc[1].gpio_cd = gpio + 1; | ||
| 70 | twl4030_mmc_init(omap3pandora_mmc); | ||
| 71 | |||
| 72 | return 0; | ||
| 73 | } | ||
| 74 | |||
| 44 | static struct twl4030_gpio_platform_data omap3pandora_gpio_data = { | 75 | static struct twl4030_gpio_platform_data omap3pandora_gpio_data = { |
| 45 | .gpio_base = OMAP_MAX_GPIO_LINES, | 76 | .gpio_base = OMAP_MAX_GPIO_LINES, |
| 46 | .irq_base = TWL4030_GPIO_IRQ_BASE, | 77 | .irq_base = TWL4030_GPIO_IRQ_BASE, |
| 47 | .irq_end = TWL4030_GPIO_IRQ_END, | 78 | .irq_end = TWL4030_GPIO_IRQ_END, |
| 79 | .setup = omap3pandora_twl_gpio_setup, | ||
| 48 | }; | 80 | }; |
| 49 | 81 | ||
| 50 | static struct twl4030_usb_data omap3pandora_usb_data = { | 82 | static struct twl4030_usb_data omap3pandora_usb_data = { |
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index e09aa59a399c..82b3dc557c96 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
| 27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
| 28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
| 29 | #include <linux/i2c/twl4030.h> | ||
| 29 | 30 | ||
| 30 | #include <linux/mtd/mtd.h> | 31 | #include <linux/mtd/mtd.h> |
| 31 | #include <linux/mtd/nand.h> | 32 | #include <linux/mtd/nand.h> |
| @@ -44,6 +45,8 @@ | |||
| 44 | #include <mach/hardware.h> | 45 | #include <mach/hardware.h> |
| 45 | #include <mach/nand.h> | 46 | #include <mach/nand.h> |
| 46 | 47 | ||
| 48 | #include "mmc-twl4030.h" | ||
| 49 | |||
| 47 | #define NAND_BLOCK_SIZE SZ_128K | 50 | #define NAND_BLOCK_SIZE SZ_128K |
| 48 | #define GPMC_CS0_BASE 0x60 | 51 | #define GPMC_CS0_BASE 0x60 |
| 49 | #define GPMC_CS_SIZE 0x30 | 52 | #define GPMC_CS_SIZE 0x30 |
| @@ -139,8 +142,31 @@ static struct omap_uart_config overo_uart_config __initdata = { | |||
| 139 | .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), | 142 | .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), |
| 140 | }; | 143 | }; |
| 141 | 144 | ||
| 145 | static struct twl4030_gpio_platform_data overo_gpio_data = { | ||
| 146 | .gpio_base = OMAP_MAX_GPIO_LINES, | ||
| 147 | .irq_base = TWL4030_GPIO_IRQ_BASE, | ||
| 148 | .irq_end = TWL4030_GPIO_IRQ_END, | ||
| 149 | }; | ||
| 150 | |||
| 151 | static struct twl4030_platform_data overo_twldata = { | ||
| 152 | .irq_base = TWL4030_IRQ_BASE, | ||
| 153 | .irq_end = TWL4030_IRQ_END, | ||
| 154 | .gpio = &overo_gpio_data, | ||
| 155 | }; | ||
| 156 | |||
| 157 | static struct i2c_board_info __initdata overo_i2c_boardinfo[] = { | ||
| 158 | { | ||
| 159 | I2C_BOARD_INFO("twl4030", 0x48), | ||
| 160 | .flags = I2C_CLIENT_WAKE, | ||
| 161 | .irq = INT_34XX_SYS_NIRQ, | ||
| 162 | .platform_data = &overo_twldata, | ||
| 163 | }, | ||
| 164 | }; | ||
| 165 | |||
| 142 | static int __init overo_i2c_init(void) | 166 | static int __init overo_i2c_init(void) |
| 143 | { | 167 | { |
| 168 | omap_register_i2c_bus(1, 2600, overo_i2c_boardinfo, | ||
| 169 | ARRAY_SIZE(overo_i2c_boardinfo)); | ||
| 144 | /* i2c2 pins are used for gpio */ | 170 | /* i2c2 pins are used for gpio */ |
| 145 | omap_register_i2c_bus(3, 400, NULL, 0); | 171 | omap_register_i2c_bus(3, 400, NULL, 0); |
| 146 | return 0; | 172 | return 0; |
| @@ -171,6 +197,22 @@ static struct platform_device *overo_devices[] __initdata = { | |||
| 171 | &overo_lcd_device, | 197 | &overo_lcd_device, |
| 172 | }; | 198 | }; |
| 173 | 199 | ||
| 200 | static struct twl4030_hsmmc_info mmc[] __initdata = { | ||
| 201 | { | ||
| 202 | .mmc = 1, | ||
| 203 | .wires = 4, | ||
| 204 | .gpio_cd = -EINVAL, | ||
| 205 | .gpio_wp = -EINVAL, | ||
| 206 | }, | ||
| 207 | { | ||
| 208 | .mmc = 2, | ||
| 209 | .wires = 4, | ||
| 210 | .gpio_cd = -EINVAL, | ||
| 211 | .gpio_wp = -EINVAL, | ||
| 212 | }, | ||
| 213 | {} /* Terminator */ | ||
| 214 | }; | ||
| 215 | |||
| 174 | static void __init overo_init(void) | 216 | static void __init overo_init(void) |
| 175 | { | 217 | { |
| 176 | overo_i2c_init(); | 218 | overo_i2c_init(); |
| @@ -178,6 +220,7 @@ static void __init overo_init(void) | |||
| 178 | omap_board_config = overo_config; | 220 | omap_board_config = overo_config; |
| 179 | omap_board_config_size = ARRAY_SIZE(overo_config); | 221 | omap_board_config_size = ARRAY_SIZE(overo_config); |
| 180 | omap_serial_init(); | 222 | omap_serial_init(); |
| 223 | twl4030_mmc_init(mmc); | ||
| 181 | overo_flash_init(); | 224 | overo_flash_init(); |
| 182 | 225 | ||
| 183 | if ((gpio_request(OVERO_GPIO_W2W_NRESET, | 226 | if ((gpio_request(OVERO_GPIO_W2W_NRESET, |
diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h index 242a19d86ccd..ff6cd14d254d 100644 --- a/arch/arm/mach-omap2/clock24xx.h +++ b/arch/arm/mach-omap2/clock24xx.h | |||
| @@ -2522,7 +2522,6 @@ static struct clk usbhs_ick = { | |||
| 2522 | 2522 | ||
| 2523 | static struct clk mmchs1_ick = { | 2523 | static struct clk mmchs1_ick = { |
| 2524 | .name = "mmchs_ick", | 2524 | .name = "mmchs_ick", |
| 2525 | .id = 1, | ||
| 2526 | .parent = &l4_ck, | 2525 | .parent = &l4_ck, |
| 2527 | .flags = CLOCK_IN_OMAP243X, | 2526 | .flags = CLOCK_IN_OMAP243X, |
| 2528 | .clkdm_name = "core_l4_clkdm", | 2527 | .clkdm_name = "core_l4_clkdm", |
| @@ -2533,7 +2532,6 @@ static struct clk mmchs1_ick = { | |||
| 2533 | 2532 | ||
| 2534 | static struct clk mmchs1_fck = { | 2533 | static struct clk mmchs1_fck = { |
| 2535 | .name = "mmchs_fck", | 2534 | .name = "mmchs_fck", |
| 2536 | .id = 1, | ||
| 2537 | .parent = &func_96m_ck, | 2535 | .parent = &func_96m_ck, |
| 2538 | .flags = CLOCK_IN_OMAP243X, | 2536 | .flags = CLOCK_IN_OMAP243X, |
| 2539 | .clkdm_name = "core_l3_clkdm", | 2537 | .clkdm_name = "core_l3_clkdm", |
| @@ -2544,7 +2542,7 @@ static struct clk mmchs1_fck = { | |||
| 2544 | 2542 | ||
| 2545 | static struct clk mmchs2_ick = { | 2543 | static struct clk mmchs2_ick = { |
| 2546 | .name = "mmchs_ick", | 2544 | .name = "mmchs_ick", |
| 2547 | .id = 2, | 2545 | .id = 1, |
| 2548 | .parent = &l4_ck, | 2546 | .parent = &l4_ck, |
| 2549 | .flags = CLOCK_IN_OMAP243X, | 2547 | .flags = CLOCK_IN_OMAP243X, |
| 2550 | .clkdm_name = "core_l4_clkdm", | 2548 | .clkdm_name = "core_l4_clkdm", |
| @@ -2555,7 +2553,7 @@ static struct clk mmchs2_ick = { | |||
| 2555 | 2553 | ||
| 2556 | static struct clk mmchs2_fck = { | 2554 | static struct clk mmchs2_fck = { |
| 2557 | .name = "mmchs_fck", | 2555 | .name = "mmchs_fck", |
| 2558 | .id = 2, | 2556 | .id = 1, |
| 2559 | .parent = &func_96m_ck, | 2557 | .parent = &func_96m_ck, |
| 2560 | .flags = CLOCK_IN_OMAP243X, | 2558 | .flags = CLOCK_IN_OMAP243X, |
| 2561 | .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), | 2559 | .enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2), |
| @@ -2595,7 +2593,6 @@ static struct clk mdm_intc_ick = { | |||
| 2595 | 2593 | ||
| 2596 | static struct clk mmchsdb1_fck = { | 2594 | static struct clk mmchsdb1_fck = { |
| 2597 | .name = "mmchsdb_fck", | 2595 | .name = "mmchsdb_fck", |
| 2598 | .id = 1, | ||
| 2599 | .parent = &func_32k_ck, | 2596 | .parent = &func_32k_ck, |
| 2600 | .flags = CLOCK_IN_OMAP243X, | 2597 | .flags = CLOCK_IN_OMAP243X, |
| 2601 | .clkdm_name = "core_l4_clkdm", | 2598 | .clkdm_name = "core_l4_clkdm", |
| @@ -2606,7 +2603,7 @@ static struct clk mmchsdb1_fck = { | |||
| 2606 | 2603 | ||
| 2607 | static struct clk mmchsdb2_fck = { | 2604 | static struct clk mmchsdb2_fck = { |
| 2608 | .name = "mmchsdb_fck", | 2605 | .name = "mmchsdb_fck", |
| 2609 | .id = 2, | 2606 | .id = 1, |
| 2610 | .parent = &func_32k_ck, | 2607 | .parent = &func_32k_ck, |
| 2611 | .flags = CLOCK_IN_OMAP243X, | 2608 | .flags = CLOCK_IN_OMAP243X, |
| 2612 | .clkdm_name = "core_l4_clkdm", | 2609 | .clkdm_name = "core_l4_clkdm", |
diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index 7217a0824ec4..a826094d89b5 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h | |||
| @@ -1374,7 +1374,7 @@ static struct clk core_96m_fck = { | |||
| 1374 | 1374 | ||
| 1375 | static struct clk mmchs3_fck = { | 1375 | static struct clk mmchs3_fck = { |
| 1376 | .name = "mmchs_fck", | 1376 | .name = "mmchs_fck", |
| 1377 | .id = 3, | 1377 | .id = 2, |
| 1378 | .parent = &core_96m_fck, | 1378 | .parent = &core_96m_fck, |
| 1379 | .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), | 1379 | .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), |
| 1380 | .enable_bit = OMAP3430ES2_EN_MMC3_SHIFT, | 1380 | .enable_bit = OMAP3430ES2_EN_MMC3_SHIFT, |
| @@ -1385,7 +1385,7 @@ static struct clk mmchs3_fck = { | |||
| 1385 | 1385 | ||
| 1386 | static struct clk mmchs2_fck = { | 1386 | static struct clk mmchs2_fck = { |
| 1387 | .name = "mmchs_fck", | 1387 | .name = "mmchs_fck", |
| 1388 | .id = 2, | 1388 | .id = 1, |
| 1389 | .parent = &core_96m_fck, | 1389 | .parent = &core_96m_fck, |
| 1390 | .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), | 1390 | .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), |
| 1391 | .enable_bit = OMAP3430_EN_MMC2_SHIFT, | 1391 | .enable_bit = OMAP3430_EN_MMC2_SHIFT, |
| @@ -1406,7 +1406,6 @@ static struct clk mspro_fck = { | |||
| 1406 | 1406 | ||
| 1407 | static struct clk mmchs1_fck = { | 1407 | static struct clk mmchs1_fck = { |
| 1408 | .name = "mmchs_fck", | 1408 | .name = "mmchs_fck", |
| 1409 | .id = 1, | ||
| 1410 | .parent = &core_96m_fck, | 1409 | .parent = &core_96m_fck, |
| 1411 | .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), | 1410 | .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), |
| 1412 | .enable_bit = OMAP3430_EN_MMC1_SHIFT, | 1411 | .enable_bit = OMAP3430_EN_MMC1_SHIFT, |
| @@ -1722,7 +1721,7 @@ static struct clk usbtll_ick = { | |||
| 1722 | 1721 | ||
| 1723 | static struct clk mmchs3_ick = { | 1722 | static struct clk mmchs3_ick = { |
| 1724 | .name = "mmchs_ick", | 1723 | .name = "mmchs_ick", |
| 1725 | .id = 3, | 1724 | .id = 2, |
| 1726 | .parent = &core_l4_ick, | 1725 | .parent = &core_l4_ick, |
| 1727 | .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), | 1726 | .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), |
| 1728 | .enable_bit = OMAP3430ES2_EN_MMC3_SHIFT, | 1727 | .enable_bit = OMAP3430ES2_EN_MMC3_SHIFT, |
| @@ -1774,7 +1773,7 @@ static struct clk des2_ick = { | |||
| 1774 | 1773 | ||
| 1775 | static struct clk mmchs2_ick = { | 1774 | static struct clk mmchs2_ick = { |
| 1776 | .name = "mmchs_ick", | 1775 | .name = "mmchs_ick", |
| 1777 | .id = 2, | 1776 | .id = 1, |
| 1778 | .parent = &core_l4_ick, | 1777 | .parent = &core_l4_ick, |
| 1779 | .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), | 1778 | .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), |
| 1780 | .enable_bit = OMAP3430_EN_MMC2_SHIFT, | 1779 | .enable_bit = OMAP3430_EN_MMC2_SHIFT, |
| @@ -1785,7 +1784,6 @@ static struct clk mmchs2_ick = { | |||
| 1785 | 1784 | ||
| 1786 | static struct clk mmchs1_ick = { | 1785 | static struct clk mmchs1_ick = { |
| 1787 | .name = "mmchs_ick", | 1786 | .name = "mmchs_ick", |
| 1788 | .id = 1, | ||
| 1789 | .parent = &core_l4_ick, | 1787 | .parent = &core_l4_ick, |
| 1790 | .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), | 1788 | .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), |
| 1791 | .enable_bit = OMAP3430_EN_MMC1_SHIFT, | 1789 | .enable_bit = OMAP3430_EN_MMC1_SHIFT, |
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 90af2ac469aa..9d7216ff6c9f 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c | |||
| @@ -14,16 +14,19 @@ | |||
| 14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
| 15 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
| 16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
| 17 | #include <linux/clk.h> | ||
| 17 | 18 | ||
| 18 | #include <mach/hardware.h> | 19 | #include <mach/hardware.h> |
| 19 | #include <asm/mach-types.h> | 20 | #include <asm/mach-types.h> |
| 20 | #include <asm/mach/map.h> | 21 | #include <asm/mach/map.h> |
| 21 | 22 | ||
| 23 | #include <mach/control.h> | ||
| 22 | #include <mach/tc.h> | 24 | #include <mach/tc.h> |
| 23 | #include <mach/board.h> | 25 | #include <mach/board.h> |
| 24 | #include <mach/mux.h> | 26 | #include <mach/mux.h> |
| 25 | #include <mach/gpio.h> | 27 | #include <mach/gpio.h> |
| 26 | #include <mach/eac.h> | 28 | #include <mach/eac.h> |
| 29 | #include <mach/mmc.h> | ||
| 27 | 30 | ||
| 28 | #if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE) | 31 | #if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE) |
| 29 | #define OMAP2_MBOX_BASE IO_ADDRESS(OMAP24XX_MAILBOX_BASE) | 32 | #define OMAP2_MBOX_BASE IO_ADDRESS(OMAP24XX_MAILBOX_BASE) |
| @@ -295,6 +298,171 @@ static void omap_init_sha1_md5(void) | |||
| 295 | static inline void omap_init_sha1_md5(void) { } | 298 | static inline void omap_init_sha1_md5(void) { } |
| 296 | #endif | 299 | #endif |
| 297 | 300 | ||
| 301 | /*-------------------------------------------------------------------------*/ | ||
| 302 | |||
| 303 | #ifdef CONFIG_ARCH_OMAP3 | ||
| 304 | |||
| 305 | #define MMCHS_SYSCONFIG 0x0010 | ||
| 306 | #define MMCHS_SYSCONFIG_SWRESET (1 << 1) | ||
| 307 | #define MMCHS_SYSSTATUS 0x0014 | ||
| 308 | #define MMCHS_SYSSTATUS_RESETDONE (1 << 0) | ||
| 309 | |||
| 310 | static struct platform_device dummy_pdev = { | ||
| 311 | .dev = { | ||
| 312 | .bus = &platform_bus_type, | ||
| 313 | }, | ||
| 314 | }; | ||
| 315 | |||
| 316 | /** | ||
| 317 | * omap_hsmmc_reset() - Full reset of each HS-MMC controller | ||
| 318 | * | ||
| 319 | * Ensure that each MMC controller is fully reset. Controllers | ||
| 320 | * left in an unknown state (by bootloader) may prevent retention | ||
| 321 | * or OFF-mode. This is especially important in cases where the | ||
| 322 | * MMC driver is not enabled, _or_ built as a module. | ||
| 323 | * | ||
| 324 | * In order for reset to work, interface, functional and debounce | ||
| 325 | * clocks must be enabled. The debounce clock comes from func_32k_clk | ||
| 326 | * and is not under SW control, so we only enable i- and f-clocks. | ||
| 327 | **/ | ||
| 328 | static void __init omap_hsmmc_reset(void) | ||
| 329 | { | ||
| 330 | u32 i, nr_controllers = cpu_is_omap34xx() ? OMAP34XX_NR_MMC : | ||
| 331 | OMAP24XX_NR_MMC; | ||
| 332 | |||
| 333 | for (i = 0; i < nr_controllers; i++) { | ||
| 334 | u32 v, base = 0; | ||
| 335 | struct clk *iclk, *fclk; | ||
| 336 | struct device *dev = &dummy_pdev.dev; | ||
| 337 | |||
| 338 | switch (i) { | ||
| 339 | case 0: | ||
| 340 | base = OMAP2_MMC1_BASE; | ||
| 341 | break; | ||
| 342 | case 1: | ||
| 343 | base = OMAP2_MMC2_BASE; | ||
| 344 | break; | ||
| 345 | case 2: | ||
| 346 | base = OMAP3_MMC3_BASE; | ||
| 347 | break; | ||
| 348 | } | ||
| 349 | |||
| 350 | dummy_pdev.id = i; | ||
| 351 | iclk = clk_get(dev, "mmchs_ick"); | ||
| 352 | if (iclk && clk_enable(iclk)) | ||
| 353 | iclk = NULL; | ||
| 354 | |||
| 355 | fclk = clk_get(dev, "mmchs_fck"); | ||
| 356 | if (fclk && clk_enable(fclk)) | ||
| 357 | fclk = NULL; | ||
| 358 | |||
| 359 | if (!iclk || !fclk) { | ||
| 360 | printk(KERN_WARNING | ||
| 361 | "%s: Unable to enable clocks for MMC%d, " | ||
| 362 | "cannot reset.\n", __func__, i); | ||
| 363 | break; | ||
| 364 | } | ||
| 365 | |||
| 366 | omap_writel(MMCHS_SYSCONFIG_SWRESET, base + MMCHS_SYSCONFIG); | ||
| 367 | v = omap_readl(base + MMCHS_SYSSTATUS); | ||
| 368 | while (!(omap_readl(base + MMCHS_SYSSTATUS) & | ||
| 369 | MMCHS_SYSSTATUS_RESETDONE)) | ||
| 370 | cpu_relax(); | ||
| 371 | |||
| 372 | if (fclk) { | ||
| 373 | clk_disable(fclk); | ||
| 374 | clk_put(fclk); | ||
| 375 | } | ||
| 376 | if (iclk) { | ||
| 377 | clk_disable(iclk); | ||
| 378 | clk_put(iclk); | ||
| 379 | } | ||
| 380 | } | ||
| 381 | } | ||
| 382 | #else | ||
| 383 | static inline void omap_hsmmc_reset(void) {} | ||
| 384 | #endif | ||
| 385 | |||
| 386 | #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \ | ||
| 387 | defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE) | ||
| 388 | |||
| 389 | static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller, | ||
| 390 | int controller_nr) | ||
| 391 | { | ||
| 392 | if (cpu_is_omap2420() && controller_nr == 0) { | ||
| 393 | omap_cfg_reg(H18_24XX_MMC_CMD); | ||
| 394 | omap_cfg_reg(H15_24XX_MMC_CLKI); | ||
| 395 | omap_cfg_reg(G19_24XX_MMC_CLKO); | ||
| 396 | omap_cfg_reg(F20_24XX_MMC_DAT0); | ||
| 397 | omap_cfg_reg(F19_24XX_MMC_DAT_DIR0); | ||
| 398 | omap_cfg_reg(G18_24XX_MMC_CMD_DIR); | ||
| 399 | if (mmc_controller->slots[0].wires == 4) { | ||
| 400 | omap_cfg_reg(H14_24XX_MMC_DAT1); | ||
| 401 | omap_cfg_reg(E19_24XX_MMC_DAT2); | ||
| 402 | omap_cfg_reg(D19_24XX_MMC_DAT3); | ||
| 403 | omap_cfg_reg(E20_24XX_MMC_DAT_DIR1); | ||
| 404 | omap_cfg_reg(F18_24XX_MMC_DAT_DIR2); | ||
| 405 | omap_cfg_reg(E18_24XX_MMC_DAT_DIR3); | ||
| 406 | } | ||
| 407 | |||
| 408 | /* | ||
| 409 | * Use internal loop-back in MMC/SDIO Module Input Clock | ||
| 410 | * selection | ||
| 411 | */ | ||
| 412 | if (mmc_controller->slots[0].internal_clock) { | ||
| 413 | u32 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); | ||
| 414 | v |= (1 << 24); | ||
| 415 | omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0); | ||
| 416 | } | ||
| 417 | } | ||
| 418 | } | ||
| 419 | |||
| 420 | void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, | ||
| 421 | int nr_controllers) | ||
| 422 | { | ||
| 423 | int i; | ||
| 424 | |||
| 425 | for (i = 0; i < nr_controllers; i++) { | ||
| 426 | unsigned long base, size; | ||
| 427 | unsigned int irq = 0; | ||
| 428 | |||
| 429 | if (!mmc_data[i]) | ||
| 430 | continue; | ||
| 431 | |||
| 432 | omap2_mmc_mux(mmc_data[i], i); | ||
| 433 | |||
| 434 | switch (i) { | ||
| 435 | case 0: | ||
| 436 | base = OMAP2_MMC1_BASE; | ||
| 437 | irq = INT_24XX_MMC_IRQ; | ||
| 438 | break; | ||
| 439 | case 1: | ||
| 440 | base = OMAP2_MMC2_BASE; | ||
| 441 | irq = INT_24XX_MMC2_IRQ; | ||
| 442 | break; | ||
| 443 | case 2: | ||
| 444 | if (!cpu_is_omap34xx()) | ||
| 445 | return; | ||
| 446 | base = OMAP3_MMC3_BASE; | ||
| 447 | irq = INT_34XX_MMC3_IRQ; | ||
| 448 | break; | ||
| 449 | default: | ||
| 450 | continue; | ||
| 451 | } | ||
| 452 | |||
| 453 | if (cpu_is_omap2420()) | ||
| 454 | size = OMAP2420_MMC_SIZE; | ||
| 455 | else | ||
| 456 | size = HSMMC_SIZE; | ||
| 457 | |||
| 458 | omap_mmc_add(i, base, size, irq, mmc_data[i]); | ||
| 459 | }; | ||
| 460 | } | ||
| 461 | |||
| 462 | #endif | ||
| 463 | |||
| 464 | /*-------------------------------------------------------------------------*/ | ||
| 465 | |||
| 298 | #if defined(CONFIG_HDQ_MASTER_OMAP) || defined(CONFIG_HDQ_MASTER_OMAP_MODULE) | 466 | #if defined(CONFIG_HDQ_MASTER_OMAP) || defined(CONFIG_HDQ_MASTER_OMAP_MODULE) |
| 299 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430) | 467 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430) |
| 300 | #define OMAP_HDQ_BASE 0x480B2000 | 468 | #define OMAP_HDQ_BASE 0x480B2000 |
| @@ -334,6 +502,7 @@ static int __init omap2_init_devices(void) | |||
| 334 | /* please keep these calls, and their implementations above, | 502 | /* please keep these calls, and their implementations above, |
| 335 | * in alphabetical order so they're easier to sort through. | 503 | * in alphabetical order so they're easier to sort through. |
| 336 | */ | 504 | */ |
| 505 | omap_hsmmc_reset(); | ||
| 337 | omap_init_mbox(); | 506 | omap_init_mbox(); |
| 338 | omap_init_mcspi(); | 507 | omap_init_mcspi(); |
| 339 | omap_hdq_init(); | 508 | omap_hdq_init(); |
diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c new file mode 100644 index 000000000000..437f52073f6e --- /dev/null +++ b/arch/arm/mach-omap2/mmc-twl4030.c | |||
| @@ -0,0 +1,408 @@ | |||
| 1 | /* | ||
| 2 | * linux/arch/arm/mach-omap2/mmc-twl4030.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007-2008 Texas Instruments | ||
| 5 | * Copyright (C) 2008 Nokia Corporation | ||
| 6 | * Author: Texas Instruments | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | #include <linux/err.h> | ||
| 13 | #include <linux/io.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/platform_device.h> | ||
| 16 | #include <linux/interrupt.h> | ||
| 17 | #include <linux/delay.h> | ||
| 18 | #include <linux/gpio.h> | ||
| 19 | #include <linux/i2c/twl4030.h> | ||
| 20 | |||
| 21 | #include <mach/hardware.h> | ||
| 22 | #include <mach/control.h> | ||
| 23 | #include <mach/mmc.h> | ||
| 24 | #include <mach/board.h> | ||
| 25 | |||
| 26 | #include "mmc-twl4030.h" | ||
| 27 | |||
| 28 | #if defined(CONFIG_TWL4030_CORE) && \ | ||
| 29 | (defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)) | ||
| 30 | |||
| 31 | #define LDO_CLR 0x00 | ||
| 32 | #define VSEL_S2_CLR 0x40 | ||
| 33 | |||
| 34 | #define VMMC1_DEV_GRP 0x27 | ||
| 35 | #define VMMC1_CLR 0x00 | ||
| 36 | #define VMMC1_315V 0x03 | ||
| 37 | #define VMMC1_300V 0x02 | ||
| 38 | #define VMMC1_285V 0x01 | ||
| 39 | #define VMMC1_185V 0x00 | ||
| 40 | #define VMMC1_DEDICATED 0x2A | ||
| 41 | |||
| 42 | #define VMMC2_DEV_GRP 0x2B | ||
| 43 | #define VMMC2_CLR 0x40 | ||
| 44 | #define VMMC2_315V 0x0c | ||
| 45 | #define VMMC2_300V 0x0b | ||
| 46 | #define VMMC2_285V 0x0a | ||
| 47 | #define VMMC2_260V 0x08 | ||
| 48 | #define VMMC2_185V 0x06 | ||
| 49 | #define VMMC2_DEDICATED 0x2E | ||
| 50 | |||
| 51 | #define VMMC_DEV_GRP_P1 0x20 | ||
| 52 | |||
| 53 | static u16 control_pbias_offset; | ||
| 54 | static u16 control_devconf1_offset; | ||
| 55 | |||
| 56 | #define HSMMC_NAME_LEN 9 | ||
| 57 | |||
| 58 | static struct twl_mmc_controller { | ||
| 59 | struct omap_mmc_platform_data *mmc; | ||
| 60 | u8 twl_vmmc_dev_grp; | ||
| 61 | u8 twl_mmc_dedicated; | ||
| 62 | char name[HSMMC_NAME_LEN]; | ||
| 63 | } hsmmc[] = { | ||
| 64 | { | ||
| 65 | .twl_vmmc_dev_grp = VMMC1_DEV_GRP, | ||
| 66 | .twl_mmc_dedicated = VMMC1_DEDICATED, | ||
| 67 | }, | ||
| 68 | { | ||
| 69 | .twl_vmmc_dev_grp = VMMC2_DEV_GRP, | ||
| 70 | .twl_mmc_dedicated = VMMC2_DEDICATED, | ||
| 71 | }, | ||
| 72 | }; | ||
| 73 | |||
| 74 | static int twl_mmc_card_detect(int irq) | ||
| 75 | { | ||
| 76 | unsigned i; | ||
| 77 | |||
| 78 | for (i = 0; i < ARRAY_SIZE(hsmmc); i++) { | ||
| 79 | struct omap_mmc_platform_data *mmc; | ||
| 80 | |||
| 81 | mmc = hsmmc[i].mmc; | ||
| 82 | if (!mmc) | ||
| 83 | continue; | ||
| 84 | if (irq != mmc->slots[0].card_detect_irq) | ||
| 85 | continue; | ||
| 86 | |||
| 87 | /* NOTE: assumes card detect signal is active-low */ | ||
| 88 | return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); | ||
| 89 | } | ||
| 90 | return -ENOSYS; | ||
| 91 | } | ||
| 92 | |||
| 93 | static int twl_mmc_get_ro(struct device *dev, int slot) | ||
| 94 | { | ||
| 95 | struct omap_mmc_platform_data *mmc = dev->platform_data; | ||
| 96 | |||
| 97 | /* NOTE: assumes write protect signal is active-high */ | ||
| 98 | return gpio_get_value_cansleep(mmc->slots[0].gpio_wp); | ||
| 99 | } | ||
| 100 | |||
| 101 | /* | ||
| 102 | * MMC Slot Initialization. | ||
| 103 | */ | ||
| 104 | static int twl_mmc_late_init(struct device *dev) | ||
| 105 | { | ||
| 106 | struct omap_mmc_platform_data *mmc = dev->platform_data; | ||
| 107 | int ret = 0; | ||
| 108 | int i; | ||
| 109 | |||
| 110 | ret = gpio_request(mmc->slots[0].switch_pin, "mmc_cd"); | ||
| 111 | if (ret) | ||
| 112 | goto done; | ||
| 113 | ret = gpio_direction_input(mmc->slots[0].switch_pin); | ||
| 114 | if (ret) | ||
| 115 | goto err; | ||
| 116 | |||
| 117 | for (i = 0; i < ARRAY_SIZE(hsmmc); i++) { | ||
| 118 | if (hsmmc[i].name == mmc->slots[0].name) { | ||
| 119 | hsmmc[i].mmc = mmc; | ||
| 120 | break; | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | return 0; | ||
| 125 | |||
| 126 | err: | ||
| 127 | gpio_free(mmc->slots[0].switch_pin); | ||
| 128 | done: | ||
| 129 | mmc->slots[0].card_detect_irq = 0; | ||
| 130 | mmc->slots[0].card_detect = NULL; | ||
| 131 | |||
| 132 | dev_err(dev, "err %d configuring card detect\n", ret); | ||
| 133 | return ret; | ||
| 134 | } | ||
| 135 | |||
| 136 | static void twl_mmc_cleanup(struct device *dev) | ||
| 137 | { | ||
| 138 | struct omap_mmc_platform_data *mmc = dev->platform_data; | ||
| 139 | |||
| 140 | gpio_free(mmc->slots[0].switch_pin); | ||
| 141 | } | ||
| 142 | |||
| 143 | #ifdef CONFIG_PM | ||
| 144 | |||
| 145 | static int twl_mmc_suspend(struct device *dev, int slot) | ||
| 146 | { | ||
| 147 | struct omap_mmc_platform_data *mmc = dev->platform_data; | ||
| 148 | |||
| 149 | disable_irq(mmc->slots[0].card_detect_irq); | ||
| 150 | return 0; | ||
| 151 | } | ||
| 152 | |||
| 153 | static int twl_mmc_resume(struct device *dev, int slot) | ||
| 154 | { | ||
| 155 | struct omap_mmc_platform_data *mmc = dev->platform_data; | ||
| 156 | |||
| 157 | enable_irq(mmc->slots[0].card_detect_irq); | ||
| 158 | return 0; | ||
| 159 | } | ||
| 160 | |||
| 161 | #else | ||
| 162 | #define twl_mmc_suspend NULL | ||
| 163 | #define twl_mmc_resume NULL | ||
| 164 | #endif | ||
| 165 | |||
| 166 | /* | ||
| 167 | * Sets the MMC voltage in twl4030 | ||
| 168 | */ | ||
| 169 | static int twl_mmc_set_voltage(struct twl_mmc_controller *c, int vdd) | ||
| 170 | { | ||
| 171 | int ret; | ||
| 172 | u8 vmmc, dev_grp_val; | ||
| 173 | |||
| 174 | switch (1 << vdd) { | ||
| 175 | case MMC_VDD_35_36: | ||
| 176 | case MMC_VDD_34_35: | ||
| 177 | case MMC_VDD_33_34: | ||
| 178 | case MMC_VDD_32_33: | ||
| 179 | case MMC_VDD_31_32: | ||
| 180 | case MMC_VDD_30_31: | ||
| 181 | if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) | ||
| 182 | vmmc = VMMC1_315V; | ||
| 183 | else | ||
| 184 | vmmc = VMMC2_315V; | ||
| 185 | break; | ||
| 186 | case MMC_VDD_29_30: | ||
| 187 | if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) | ||
| 188 | vmmc = VMMC1_315V; | ||
| 189 | else | ||
| 190 | vmmc = VMMC2_300V; | ||
| 191 | break; | ||
| 192 | case MMC_VDD_27_28: | ||
| 193 | case MMC_VDD_26_27: | ||
| 194 | if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) | ||
| 195 | vmmc = VMMC1_285V; | ||
| 196 | else | ||
| 197 | vmmc = VMMC2_285V; | ||
| 198 | break; | ||
| 199 | case MMC_VDD_25_26: | ||
| 200 | case MMC_VDD_24_25: | ||
| 201 | case MMC_VDD_23_24: | ||
| 202 | case MMC_VDD_22_23: | ||
| 203 | case MMC_VDD_21_22: | ||
| 204 | case MMC_VDD_20_21: | ||
| 205 | if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) | ||
| 206 | vmmc = VMMC1_285V; | ||
| 207 | else | ||
| 208 | vmmc = VMMC2_260V; | ||
| 209 | break; | ||
| 210 | case MMC_VDD_165_195: | ||
| 211 | if (c->twl_vmmc_dev_grp == VMMC1_DEV_GRP) | ||
| 212 | vmmc = VMMC1_185V; | ||
| 213 | else | ||
| 214 | vmmc = VMMC2_185V; | ||
| 215 | break; | ||
| 216 | default: | ||
| 217 | vmmc = 0; | ||
| 218 | break; | ||
| 219 | } | ||
| 220 | |||
| 221 | if (vmmc) | ||
| 222 | dev_grp_val = VMMC_DEV_GRP_P1; /* Power up */ | ||
| 223 | else | ||
| 224 | dev_grp_val = LDO_CLR; /* Power down */ | ||
| 225 | |||
| 226 | ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, | ||
| 227 | dev_grp_val, c->twl_vmmc_dev_grp); | ||
| 228 | if (ret) | ||
| 229 | return ret; | ||
| 230 | |||
| 231 | ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, | ||
| 232 | vmmc, c->twl_mmc_dedicated); | ||
| 233 | |||
| 234 | return ret; | ||
| 235 | } | ||
| 236 | |||
| 237 | static int twl_mmc1_set_power(struct device *dev, int slot, int power_on, | ||
| 238 | int vdd) | ||
| 239 | { | ||
| 240 | u32 reg; | ||
| 241 | int ret = 0; | ||
| 242 | struct twl_mmc_controller *c = &hsmmc[0]; | ||
| 243 | struct omap_mmc_platform_data *mmc = dev->platform_data; | ||
| 244 | |||
| 245 | if (power_on) { | ||
| 246 | if (cpu_is_omap2430()) { | ||
| 247 | reg = omap_ctrl_readl(OMAP243X_CONTROL_DEVCONF1); | ||
| 248 | if ((1 << vdd) >= MMC_VDD_30_31) | ||
| 249 | reg |= OMAP243X_MMC1_ACTIVE_OVERWRITE; | ||
| 250 | else | ||
| 251 | reg &= ~OMAP243X_MMC1_ACTIVE_OVERWRITE; | ||
| 252 | omap_ctrl_writel(reg, OMAP243X_CONTROL_DEVCONF1); | ||
| 253 | } | ||
| 254 | |||
| 255 | if (mmc->slots[0].internal_clock) { | ||
| 256 | reg = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); | ||
| 257 | reg |= OMAP2_MMCSDIO1ADPCLKISEL; | ||
| 258 | omap_ctrl_writel(reg, OMAP2_CONTROL_DEVCONF0); | ||
| 259 | } | ||
| 260 | |||
| 261 | reg = omap_ctrl_readl(control_pbias_offset); | ||
| 262 | reg |= OMAP2_PBIASSPEEDCTRL0; | ||
| 263 | reg &= ~OMAP2_PBIASLITEPWRDNZ0; | ||
| 264 | omap_ctrl_writel(reg, control_pbias_offset); | ||
| 265 | |||
| 266 | ret = twl_mmc_set_voltage(c, vdd); | ||
| 267 | |||
| 268 | /* 100ms delay required for PBIAS configuration */ | ||
| 269 | msleep(100); | ||
| 270 | reg = omap_ctrl_readl(control_pbias_offset); | ||
| 271 | reg |= (OMAP2_PBIASLITEPWRDNZ0 | OMAP2_PBIASSPEEDCTRL0); | ||
| 272 | if ((1 << vdd) <= MMC_VDD_165_195) | ||
| 273 | reg &= ~OMAP2_PBIASLITEVMODE0; | ||
| 274 | else | ||
| 275 | reg |= OMAP2_PBIASLITEVMODE0; | ||
| 276 | omap_ctrl_writel(reg, control_pbias_offset); | ||
| 277 | } else { | ||
| 278 | reg = omap_ctrl_readl(control_pbias_offset); | ||
| 279 | reg &= ~OMAP2_PBIASLITEPWRDNZ0; | ||
| 280 | omap_ctrl_writel(reg, control_pbias_offset); | ||
| 281 | |||
| 282 | ret = twl_mmc_set_voltage(c, 0); | ||
| 283 | |||
| 284 | /* 100ms delay required for PBIAS configuration */ | ||
| 285 | msleep(100); | ||
| 286 | reg = omap_ctrl_readl(control_pbias_offset); | ||
| 287 | reg |= (OMAP2_PBIASSPEEDCTRL0 | OMAP2_PBIASLITEPWRDNZ0 | | ||
| 288 | OMAP2_PBIASLITEVMODE0); | ||
| 289 | omap_ctrl_writel(reg, control_pbias_offset); | ||
| 290 | } | ||
| 291 | |||
| 292 | return ret; | ||
| 293 | } | ||
| 294 | |||
| 295 | static int twl_mmc2_set_power(struct device *dev, int slot, int power_on, int vdd) | ||
| 296 | { | ||
| 297 | int ret; | ||
| 298 | struct twl_mmc_controller *c = &hsmmc[1]; | ||
| 299 | struct omap_mmc_platform_data *mmc = dev->platform_data; | ||
| 300 | |||
| 301 | if (power_on) { | ||
| 302 | if (mmc->slots[0].internal_clock) { | ||
| 303 | u32 reg; | ||
| 304 | |||
| 305 | reg = omap_ctrl_readl(control_devconf1_offset); | ||
| 306 | reg |= OMAP2_MMCSDIO2ADPCLKISEL; | ||
| 307 | omap_ctrl_writel(reg, control_devconf1_offset); | ||
| 308 | } | ||
| 309 | ret = twl_mmc_set_voltage(c, vdd); | ||
| 310 | } else { | ||
| 311 | ret = twl_mmc_set_voltage(c, 0); | ||
| 312 | } | ||
| 313 | |||
| 314 | return ret; | ||
| 315 | } | ||
| 316 | |||
| 317 | static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata; | ||
| 318 | |||
| 319 | void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) | ||
| 320 | { | ||
| 321 | struct twl4030_hsmmc_info *c; | ||
| 322 | int nr_hsmmc = ARRAY_SIZE(hsmmc_data); | ||
| 323 | |||
| 324 | if (cpu_is_omap2430()) { | ||
| 325 | control_pbias_offset = OMAP243X_CONTROL_PBIAS_LITE; | ||
| 326 | control_devconf1_offset = OMAP243X_CONTROL_DEVCONF1; | ||
| 327 | nr_hsmmc = 2; | ||
| 328 | } else { | ||
| 329 | control_pbias_offset = OMAP343X_CONTROL_PBIAS_LITE; | ||
| 330 | control_devconf1_offset = OMAP343X_CONTROL_DEVCONF1; | ||
| 331 | } | ||
| 332 | |||
| 333 | for (c = controllers; c->mmc; c++) { | ||
| 334 | struct twl_mmc_controller *twl = hsmmc + c->mmc - 1; | ||
| 335 | struct omap_mmc_platform_data *mmc = hsmmc_data[c->mmc - 1]; | ||
| 336 | |||
| 337 | if (!c->mmc || c->mmc > nr_hsmmc) { | ||
| 338 | pr_debug("MMC%d: no such controller\n", c->mmc); | ||
| 339 | continue; | ||
| 340 | } | ||
| 341 | if (mmc) { | ||
| 342 | pr_debug("MMC%d: already configured\n", c->mmc); | ||
| 343 | continue; | ||
| 344 | } | ||
| 345 | |||
| 346 | mmc = kzalloc(sizeof(struct omap_mmc_platform_data), GFP_KERNEL); | ||
| 347 | if (!mmc) { | ||
| 348 | pr_err("Cannot allocate memory for mmc device!\n"); | ||
| 349 | return; | ||
| 350 | } | ||
| 351 | |||
| 352 | sprintf(twl->name, "mmc%islot%i", c->mmc, 1); | ||
| 353 | mmc->slots[0].name = twl->name; | ||
| 354 | mmc->nr_slots = 1; | ||
| 355 | mmc->slots[0].ocr_mask = MMC_VDD_165_195 | | ||
| 356 | MMC_VDD_26_27 | MMC_VDD_27_28 | | ||
| 357 | MMC_VDD_29_30 | | ||
| 358 | MMC_VDD_30_31 | MMC_VDD_31_32; | ||
| 359 | mmc->slots[0].wires = c->wires; | ||
| 360 | mmc->slots[0].internal_clock = !c->ext_clock; | ||
| 361 | mmc->dma_mask = 0xffffffff; | ||
| 362 | |||
| 363 | /* note: twl4030 card detect GPIOs normally switch VMMCx ... */ | ||
| 364 | if (gpio_is_valid(c->gpio_cd)) { | ||
| 365 | mmc->init = twl_mmc_late_init; | ||
| 366 | mmc->cleanup = twl_mmc_cleanup; | ||
| 367 | mmc->suspend = twl_mmc_suspend; | ||
| 368 | mmc->resume = twl_mmc_resume; | ||
| 369 | |||
| 370 | mmc->slots[0].switch_pin = c->gpio_cd; | ||
| 371 | mmc->slots[0].card_detect_irq = gpio_to_irq(c->gpio_cd); | ||
| 372 | mmc->slots[0].card_detect = twl_mmc_card_detect; | ||
| 373 | } else | ||
| 374 | mmc->slots[0].switch_pin = -EINVAL; | ||
| 375 | |||
| 376 | /* write protect normally uses an OMAP gpio */ | ||
| 377 | if (gpio_is_valid(c->gpio_wp)) { | ||
| 378 | gpio_request(c->gpio_wp, "mmc_wp"); | ||
| 379 | gpio_direction_input(c->gpio_wp); | ||
| 380 | |||
| 381 | mmc->slots[0].gpio_wp = c->gpio_wp; | ||
| 382 | mmc->slots[0].get_ro = twl_mmc_get_ro; | ||
| 383 | } else | ||
| 384 | mmc->slots[0].gpio_wp = -EINVAL; | ||
| 385 | |||
| 386 | /* NOTE: we assume OMAP's MMC1 and MMC2 use | ||
| 387 | * the TWL4030's VMMC1 and VMMC2, respectively; | ||
| 388 | * and that OMAP's MMC3 isn't used. | ||
| 389 | */ | ||
| 390 | |||
| 391 | switch (c->mmc) { | ||
| 392 | case 1: | ||
| 393 | mmc->slots[0].set_power = twl_mmc1_set_power; | ||
| 394 | break; | ||
| 395 | case 2: | ||
| 396 | mmc->slots[0].set_power = twl_mmc2_set_power; | ||
| 397 | break; | ||
| 398 | default: | ||
| 399 | pr_err("MMC%d configuration not supported!\n", c->mmc); | ||
| 400 | continue; | ||
| 401 | } | ||
| 402 | hsmmc_data[c->mmc - 1] = mmc; | ||
| 403 | } | ||
| 404 | |||
| 405 | omap2_init_mmc(hsmmc_data, OMAP34XX_NR_MMC); | ||
| 406 | } | ||
| 407 | |||
| 408 | #endif | ||
diff --git a/arch/arm/mach-omap2/mmc-twl4030.h b/arch/arm/mach-omap2/mmc-twl4030.h new file mode 100644 index 000000000000..e1c8076400ca --- /dev/null +++ b/arch/arm/mach-omap2/mmc-twl4030.h | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | /* | ||
| 2 | * MMC definitions for OMAP2 | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License version 2 as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | */ | ||
| 8 | |||
| 9 | struct twl4030_hsmmc_info { | ||
| 10 | u8 mmc; /* controller 1/2/3 */ | ||
| 11 | u8 wires; /* 1/4/8 wires */ | ||
| 12 | int gpio_cd; /* or -EINVAL */ | ||
| 13 | int gpio_wp; /* or -EINVAL */ | ||
| 14 | int ext_clock:1; /* use external pin for input clock */ | ||
| 15 | }; | ||
| 16 | |||
| 17 | #if defined(CONFIG_TWL4030_CORE) && \ | ||
| 18 | (defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \ | ||
| 19 | defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)) | ||
| 20 | |||
| 21 | void twl4030_mmc_init(struct twl4030_hsmmc_info *); | ||
| 22 | |||
| 23 | #else | ||
| 24 | |||
| 25 | static inline void twl4030_mmc_init(struct twl4030_hsmmc_info *info) | ||
| 26 | { | ||
| 27 | } | ||
| 28 | |||
| 29 | #endif | ||
