diff options
-rw-r--r-- | arch/arm/mach-omap1/board-innovator.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap1/devices.c | 4 | ||||
-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-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/devices.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-omap2/mmc-twl4030.c | 408 | ||||
-rw-r--r-- | arch/arm/mach-omap2/mmc-twl4030.h | 29 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/mach/control.h | 17 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/mach/mmc.h | 16 | ||||
-rw-r--r-- | drivers/mmc/host/omap.c | 2 |
14 files changed, 730 insertions, 19 deletions
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c index 8ffb06fc0f08..af2fb9070083 100644 --- a/arch/arm/mach-omap1/board-innovator.c +++ b/arch/arm/mach-omap1/board-innovator.c | |||
@@ -385,7 +385,7 @@ static struct omap_mmc_platform_data mmc1_data = { | |||
385 | .nr_slots = 1, | 385 | .nr_slots = 1, |
386 | .slots[0] = { | 386 | .slots[0] = { |
387 | .set_power = mmc_set_power, | 387 | .set_power = mmc_set_power, |
388 | .wire4 = 1, | 388 | .wires = 4, |
389 | .name = "mmcblk", | 389 | .name = "mmcblk", |
390 | }, | 390 | }, |
391 | }; | 391 | }; |
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c index 024dab13d4b4..77382d8b6b2f 100644 --- a/arch/arm/mach-omap1/devices.c +++ b/arch/arm/mach-omap1/devices.c | |||
@@ -116,7 +116,7 @@ static inline void omap1_mmc_mux(struct omap_mmc_platform_data *mmc_controller, | |||
116 | omap_cfg_reg(P19_1710_MMC_CMDDIR); | 116 | omap_cfg_reg(P19_1710_MMC_CMDDIR); |
117 | omap_cfg_reg(P20_1710_MMC_DATDIR0); | 117 | omap_cfg_reg(P20_1710_MMC_DATDIR0); |
118 | } | 118 | } |
119 | if (mmc_controller->slots[0].wire4) { | 119 | if (mmc_controller->slots[0].wires == 4) { |
120 | omap_cfg_reg(MMC_DAT1); | 120 | omap_cfg_reg(MMC_DAT1); |
121 | /* NOTE: DAT2 can be on W10 (here) or M15 */ | 121 | /* NOTE: DAT2 can be on W10 (here) or M15 */ |
122 | if (!mmc_controller->slots[0].nomux) | 122 | if (!mmc_controller->slots[0].nomux) |
@@ -132,7 +132,7 @@ static inline void omap1_mmc_mux(struct omap_mmc_platform_data *mmc_controller, | |||
132 | omap_cfg_reg(Y10_1610_MMC2_CLK); | 132 | omap_cfg_reg(Y10_1610_MMC2_CLK); |
133 | omap_cfg_reg(R18_1610_MMC2_CLKIN); | 133 | omap_cfg_reg(R18_1610_MMC2_CLKIN); |
134 | omap_cfg_reg(W8_1610_MMC2_DAT0); | 134 | omap_cfg_reg(W8_1610_MMC2_DAT0); |
135 | if (mmc_controller->slots[1].wire4) { | 135 | if (mmc_controller->slots[1].wires == 4) { |
136 | omap_cfg_reg(V8_1610_MMC2_DAT1); | 136 | omap_cfg_reg(V8_1610_MMC2_DAT1); |
137 | omap_cfg_reg(W15_1610_MMC2_DAT2); | 137 | omap_cfg_reg(W15_1610_MMC2_DAT2); |
138 | omap_cfg_reg(R10_1610_MMC2_DAT3); | 138 | omap_cfg_reg(R10_1610_MMC2_DAT3); |
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-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/devices.c b/arch/arm/mach-omap2/devices.c index 8ccdfcf2942c..6e03272b0521 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <asm/mach-types.h> | 19 | #include <asm/mach-types.h> |
20 | #include <asm/mach/map.h> | 20 | #include <asm/mach/map.h> |
21 | 21 | ||
22 | #include <mach/control.h> | ||
22 | #include <mach/tc.h> | 23 | #include <mach/tc.h> |
23 | #include <mach/board.h> | 24 | #include <mach/board.h> |
24 | #include <mach/mux.h> | 25 | #include <mach/mux.h> |
@@ -311,7 +312,7 @@ static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller, | |||
311 | omap_cfg_reg(F20_24XX_MMC_DAT0); | 312 | omap_cfg_reg(F20_24XX_MMC_DAT0); |
312 | omap_cfg_reg(F19_24XX_MMC_DAT_DIR0); | 313 | omap_cfg_reg(F19_24XX_MMC_DAT_DIR0); |
313 | omap_cfg_reg(G18_24XX_MMC_CMD_DIR); | 314 | omap_cfg_reg(G18_24XX_MMC_CMD_DIR); |
314 | if (mmc_controller->slots[0].wire4) { | 315 | if (mmc_controller->slots[0].wires == 4) { |
315 | omap_cfg_reg(H14_24XX_MMC_DAT1); | 316 | omap_cfg_reg(H14_24XX_MMC_DAT1); |
316 | omap_cfg_reg(E19_24XX_MMC_DAT2); | 317 | omap_cfg_reg(E19_24XX_MMC_DAT2); |
317 | omap_cfg_reg(D19_24XX_MMC_DAT3); | 318 | omap_cfg_reg(D19_24XX_MMC_DAT3); |
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 | ||
diff --git a/arch/arm/plat-omap/include/mach/control.h b/arch/arm/plat-omap/include/mach/control.h index dc9886760577..269147f3836f 100644 --- a/arch/arm/plat-omap/include/mach/control.h +++ b/arch/arm/plat-omap/include/mach/control.h | |||
@@ -74,6 +74,7 @@ | |||
74 | #define OMAP243X_CONTROL_IVA2_BOOTADDR (OMAP2_CONTROL_GENERAL + 0x0190) | 74 | #define OMAP243X_CONTROL_IVA2_BOOTADDR (OMAP2_CONTROL_GENERAL + 0x0190) |
75 | #define OMAP243X_CONTROL_IVA2_BOOTMOD (OMAP2_CONTROL_GENERAL + 0x0194) | 75 | #define OMAP243X_CONTROL_IVA2_BOOTMOD (OMAP2_CONTROL_GENERAL + 0x0194) |
76 | #define OMAP243X_CONTROL_IVA2_GEMCFG (OMAP2_CONTROL_GENERAL + 0x0198) | 76 | #define OMAP243X_CONTROL_IVA2_GEMCFG (OMAP2_CONTROL_GENERAL + 0x0198) |
77 | #define OMAP243X_CONTROL_PBIAS_LITE (OMAP2_CONTROL_GENERAL + 0x0230) | ||
77 | 78 | ||
78 | /* 24xx-only CONTROL_GENERAL register offsets */ | 79 | /* 24xx-only CONTROL_GENERAL register offsets */ |
79 | #define OMAP24XX_CONTROL_DEBOBS (OMAP2_CONTROL_GENERAL + 0x0000) | 80 | #define OMAP24XX_CONTROL_DEBOBS (OMAP2_CONTROL_GENERAL + 0x0000) |
@@ -140,6 +141,7 @@ | |||
140 | #define OMAP343X_CONTROL_TEST_KEY_13 (OMAP2_CONTROL_GENERAL + 0x00fc) | 141 | #define OMAP343X_CONTROL_TEST_KEY_13 (OMAP2_CONTROL_GENERAL + 0x00fc) |
141 | #define OMAP343X_CONTROL_IVA2_BOOTADDR (OMAP2_CONTROL_GENERAL + 0x0190) | 142 | #define OMAP343X_CONTROL_IVA2_BOOTADDR (OMAP2_CONTROL_GENERAL + 0x0190) |
142 | #define OMAP343X_CONTROL_IVA2_BOOTMOD (OMAP2_CONTROL_GENERAL + 0x0194) | 143 | #define OMAP343X_CONTROL_IVA2_BOOTMOD (OMAP2_CONTROL_GENERAL + 0x0194) |
144 | #define OMAP343X_CONTROL_PBIAS_LITE (OMAP2_CONTROL_GENERAL + 0x02b0) | ||
143 | #define OMAP343X_CONTROL_TEMP_SENSOR (OMAP2_CONTROL_GENERAL + 0x02b4) | 145 | #define OMAP343X_CONTROL_TEMP_SENSOR (OMAP2_CONTROL_GENERAL + 0x02b4) |
144 | 146 | ||
145 | /* | 147 | /* |
@@ -154,11 +156,14 @@ | |||
154 | * and the security mode (secure, non-secure, don't care) | 156 | * and the security mode (secure, non-secure, don't care) |
155 | */ | 157 | */ |
156 | /* CONTROL_DEVCONF0 bits */ | 158 | /* CONTROL_DEVCONF0 bits */ |
159 | #define OMAP2_MMCSDIO1ADPCLKISEL (1 << 24) /* MMC1 loop back clock */ | ||
157 | #define OMAP24XX_USBSTANDBYCTRL (1 << 15) | 160 | #define OMAP24XX_USBSTANDBYCTRL (1 << 15) |
158 | #define OMAP2_MCBSP2_CLKS_MASK (1 << 6) | 161 | #define OMAP2_MCBSP2_CLKS_MASK (1 << 6) |
159 | #define OMAP2_MCBSP1_CLKS_MASK (1 << 2) | 162 | #define OMAP2_MCBSP1_CLKS_MASK (1 << 2) |
160 | 163 | ||
161 | /* CONTROL_DEVCONF1 bits */ | 164 | /* CONTROL_DEVCONF1 bits */ |
165 | #define OMAP243X_MMC1_ACTIVE_OVERWRITE (1 << 31) | ||
166 | #define OMAP2_MMCSDIO2ADPCLKISEL (1 << 6) /* MMC2 loop back clock */ | ||
162 | #define OMAP2_MCBSP5_CLKS_MASK (1 << 4) /* > 242x */ | 167 | #define OMAP2_MCBSP5_CLKS_MASK (1 << 4) /* > 242x */ |
163 | #define OMAP2_MCBSP4_CLKS_MASK (1 << 2) /* > 242x */ | 168 | #define OMAP2_MCBSP4_CLKS_MASK (1 << 2) /* > 242x */ |
164 | #define OMAP2_MCBSP3_CLKS_MASK (1 << 0) /* > 242x */ | 169 | #define OMAP2_MCBSP3_CLKS_MASK (1 << 0) /* > 242x */ |
@@ -172,6 +177,18 @@ | |||
172 | #define OMAP2_SYSBOOT_1_MASK (1 << 1) | 177 | #define OMAP2_SYSBOOT_1_MASK (1 << 1) |
173 | #define OMAP2_SYSBOOT_0_MASK (1 << 0) | 178 | #define OMAP2_SYSBOOT_0_MASK (1 << 0) |
174 | 179 | ||
180 | /* CONTROL_PBIAS_LITE bits */ | ||
181 | #define OMAP343X_PBIASLITESUPPLY_HIGH1 (1 << 15) | ||
182 | #define OMAP343X_PBIASLITEVMODEERROR1 (1 << 11) | ||
183 | #define OMAP343X_PBIASSPEEDCTRL1 (1 << 10) | ||
184 | #define OMAP343X_PBIASLITEPWRDNZ1 (1 << 9) | ||
185 | #define OMAP343X_PBIASLITEVMODE1 (1 << 8) | ||
186 | #define OMAP343X_PBIASLITESUPPLY_HIGH0 (1 << 7) | ||
187 | #define OMAP343X_PBIASLITEVMODEERROR0 (1 << 3) | ||
188 | #define OMAP2_PBIASSPEEDCTRL0 (1 << 2) | ||
189 | #define OMAP2_PBIASLITEPWRDNZ0 (1 << 1) | ||
190 | #define OMAP2_PBIASLITEVMODE0 (1 << 0) | ||
191 | |||
175 | #ifndef __ASSEMBLY__ | 192 | #ifndef __ASSEMBLY__ |
176 | #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) | 193 | #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) |
177 | extern void __iomem *omap_ctrl_base_get(void); | 194 | extern void __iomem *omap_ctrl_base_get(void); |
diff --git a/arch/arm/plat-omap/include/mach/mmc.h b/arch/arm/plat-omap/include/mach/mmc.h index 0c2ef3b8956a..031250f02805 100644 --- a/arch/arm/plat-omap/include/mach/mmc.h +++ b/arch/arm/plat-omap/include/mach/mmc.h | |||
@@ -61,6 +61,11 @@ struct omap_mmc_platform_data { | |||
61 | 61 | ||
62 | struct omap_mmc_slot_data { | 62 | struct omap_mmc_slot_data { |
63 | 63 | ||
64 | /* 4 wire signaling is optional, and is used for SD/SDIO/HSMMC; | ||
65 | * 8 wire signaling is also optional, and is used with HSMMC | ||
66 | */ | ||
67 | u8 wires; | ||
68 | |||
64 | /* | 69 | /* |
65 | * nomux means "standard" muxing is wrong on this board, and | 70 | * nomux means "standard" muxing is wrong on this board, and |
66 | * that board-specific code handled it before common init logic. | 71 | * that board-specific code handled it before common init logic. |
@@ -70,13 +75,12 @@ struct omap_mmc_platform_data { | |||
70 | /* switch pin can be for card detect (default) or card cover */ | 75 | /* switch pin can be for card detect (default) or card cover */ |
71 | unsigned cover:1; | 76 | unsigned cover:1; |
72 | 77 | ||
73 | /* 4 wire signaling is optional, and is only used for SD/SDIO */ | ||
74 | unsigned wire4:1; | ||
75 | |||
76 | /* use the internal clock */ | 78 | /* use the internal clock */ |
77 | unsigned internal_clock:1; | 79 | unsigned internal_clock:1; |
78 | s16 power_pin; | 80 | s16 power_pin; |
79 | s16 switch_pin; | 81 | |
82 | int switch_pin; /* gpio (card detect) */ | ||
83 | int gpio_wp; /* gpio (write protect) */ | ||
80 | 84 | ||
81 | int (* set_bus_mode)(struct device *dev, int slot, int bus_mode); | 85 | int (* set_bus_mode)(struct device *dev, int slot, int bus_mode); |
82 | int (* set_power)(struct device *dev, int slot, int power_on, int vdd); | 86 | int (* set_power)(struct device *dev, int slot, int power_on, int vdd); |
@@ -111,7 +115,6 @@ void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data, | |||
111 | int nr_controllers); | 115 | int nr_controllers); |
112 | void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, | 116 | void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, |
113 | int nr_controllers); | 117 | int nr_controllers); |
114 | void hsmmc_init(int controller_mask); | ||
115 | int omap_mmc_add(int id, unsigned long base, unsigned long size, | 118 | int omap_mmc_add(int id, unsigned long base, unsigned long size, |
116 | unsigned int irq, struct omap_mmc_platform_data *data); | 119 | unsigned int irq, struct omap_mmc_platform_data *data); |
117 | #else | 120 | #else |
@@ -123,9 +126,6 @@ static inline void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, | |||
123 | int nr_controllers) | 126 | int nr_controllers) |
124 | { | 127 | { |
125 | } | 128 | } |
126 | static inline void hsmmc_init(int controller_mask) | ||
127 | { | ||
128 | } | ||
129 | static inline int omap_mmc_add(int id, unsigned long base, unsigned long size, | 129 | static inline int omap_mmc_add(int id, unsigned long base, unsigned long size, |
130 | unsigned int irq, struct omap_mmc_platform_data *data) | 130 | unsigned int irq, struct omap_mmc_platform_data *data) |
131 | { | 131 | { |
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index c6544d2d072a..67d7b7fef084 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c | |||
@@ -1317,7 +1317,7 @@ static int __init mmc_omap_new_slot(struct mmc_omap_host *host, int id) | |||
1317 | host->slots[id] = slot; | 1317 | host->slots[id] = slot; |
1318 | 1318 | ||
1319 | mmc->caps = 0; | 1319 | mmc->caps = 0; |
1320 | if (host->pdata->slots[id].wire4) | 1320 | if (host->pdata->slots[id].wires >= 4) |
1321 | mmc->caps |= MMC_CAP_4_BIT_DATA; | 1321 | mmc->caps |= MMC_CAP_4_BIT_DATA; |
1322 | 1322 | ||
1323 | mmc->ops = &mmc_omap_ops; | 1323 | mmc->ops = &mmc_omap_ops; |