Commit | Line | Data |
---|---|---|
008f8a2f HP |
1 | /* |
2 | * Copyright (C) ST-Ericsson SA 2010 | |
3 | * | |
4 | * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> | |
5 | * License terms: GNU General Public License (GPL) version 2 | |
6 | */ | |
7 | ||
8 | #include <linux/kernel.h> | |
9 | #include <linux/gpio.h> | |
10 | #include <linux/amba/bus.h> | |
11 | #include <linux/amba/mmci.h> | |
12 | #include <linux/mmc/host.h> | |
13 | #include <linux/platform_device.h> | |
14 | ||
4b4f757c | 15 | #include <asm/mach-types.h> |
5d7b8467 | 16 | #include <plat/ste_dma40.h> |
008f8a2f HP |
17 | #include <mach/devices.h> |
18 | #include <mach/hardware.h> | |
19 | ||
fbf1eadf | 20 | #include "devices-db8500.h" |
008f8a2f | 21 | #include "board-mop500.h" |
5d7b8467 | 22 | #include "ste-dma40-db8500.h" |
008f8a2f | 23 | |
c15def1c LW |
24 | /* |
25 | * v2 has a new version of this block that need to be forced, the number found | |
26 | * in hardware is incorrect | |
27 | */ | |
28 | #define U8500_SDI_V2_PERIPHID 0x10480180 | |
29 | ||
b8410a15 RV |
30 | /* |
31 | * SDI 0 (MicroSD slot) | |
32 | */ | |
33 | ||
f727a05a LW |
34 | /* GPIO pins used by the sdi0 level shifter */ |
35 | static int sdi0_en = -1; | |
36 | static int sdi0_vsel = -1; | |
37 | ||
bc521818 | 38 | static int mop500_sdi0_ios_handler(struct device *dev, struct mmc_ios *ios) |
b8410a15 | 39 | { |
bc521818 | 40 | switch (ios->power_mode) { |
f727a05a LW |
41 | case MMC_POWER_UP: |
42 | case MMC_POWER_ON: | |
43 | /* | |
44 | * Level shifter voltage should depend on vdd to when deciding | |
45 | * on either 1.8V or 2.9V. Once the decision has been made the | |
46 | * level shifter must be disabled and re-enabled with a changed | |
47 | * select signal in order to switch the voltage. Since there is | |
48 | * no framework support yet for indicating 1.8V in vdd, use the | |
49 | * default 2.9V. | |
50 | */ | |
51 | gpio_direction_output(sdi0_vsel, 0); | |
52 | gpio_direction_output(sdi0_en, 1); | |
53 | break; | |
54 | case MMC_POWER_OFF: | |
55 | gpio_direction_output(sdi0_vsel, 0); | |
56 | gpio_direction_output(sdi0_en, 0); | |
57 | break; | |
58 | } | |
b8410a15 | 59 | |
bc521818 | 60 | return 0; |
b8410a15 RV |
61 | } |
62 | ||
5d7b8467 LW |
63 | #ifdef CONFIG_STE_DMA40 |
64 | struct stedma40_chan_cfg mop500_sdi0_dma_cfg_rx = { | |
65 | .mode = STEDMA40_MODE_LOGICAL, | |
66 | .dir = STEDMA40_PERIPH_TO_MEM, | |
67 | .src_dev_type = DB8500_DMA_DEV29_SD_MM0_RX, | |
68 | .dst_dev_type = STEDMA40_DEV_DST_MEMORY, | |
69 | .src_info.data_width = STEDMA40_WORD_WIDTH, | |
70 | .dst_info.data_width = STEDMA40_WORD_WIDTH, | |
71 | }; | |
72 | ||
73 | static struct stedma40_chan_cfg mop500_sdi0_dma_cfg_tx = { | |
74 | .mode = STEDMA40_MODE_LOGICAL, | |
75 | .dir = STEDMA40_MEM_TO_PERIPH, | |
76 | .src_dev_type = STEDMA40_DEV_SRC_MEMORY, | |
77 | .dst_dev_type = DB8500_DMA_DEV29_SD_MM0_TX, | |
78 | .src_info.data_width = STEDMA40_WORD_WIDTH, | |
79 | .dst_info.data_width = STEDMA40_WORD_WIDTH, | |
80 | }; | |
81 | #endif | |
82 | ||
5e1ac7db | 83 | struct mmci_platform_data mop500_sdi0_data = { |
bc521818 | 84 | .ios_handler = mop500_sdi0_ios_handler, |
b8410a15 | 85 | .ocr_mask = MMC_VDD_29_30, |
02a73437 LW |
86 | .f_max = 50000000, |
87 | .capabilities = MMC_CAP_4_BIT_DATA | | |
88 | MMC_CAP_SD_HIGHSPEED | | |
89 | MMC_CAP_MMC_HIGHSPEED, | |
b8410a15 | 90 | .gpio_wp = -1, |
bc521818 UH |
91 | .sigdir = MCI_ST_FBCLKEN | |
92 | MCI_ST_CMDDIREN | | |
93 | MCI_ST_DATA0DIREN | | |
94 | MCI_ST_DATA2DIREN, | |
5d7b8467 LW |
95 | #ifdef CONFIG_STE_DMA40 |
96 | .dma_filter = stedma40_filter, | |
97 | .dma_rx_param = &mop500_sdi0_dma_cfg_rx, | |
98 | .dma_tx_param = &mop500_sdi0_dma_cfg_tx, | |
99 | #endif | |
b8410a15 RV |
100 | }; |
101 | ||
18403424 | 102 | static void sdi0_configure(struct device *parent) |
b8410a15 RV |
103 | { |
104 | int ret; | |
105 | ||
4b4f757c | 106 | ret = gpio_request(sdi0_en, "level shifter enable"); |
b8410a15 | 107 | if (!ret) |
4b4f757c LW |
108 | ret = gpio_request(sdi0_vsel, |
109 | "level shifter 1v8-3v select"); | |
110 | ||
111 | if (ret) { | |
112 | pr_warning("unable to config sdi0 gpios for level shifter.\n"); | |
b8410a15 | 113 | return; |
4b4f757c | 114 | } |
b8410a15 | 115 | |
4b4f757c LW |
116 | /* Select the default 2.9V and enable level shifter */ |
117 | gpio_direction_output(sdi0_vsel, 0); | |
118 | gpio_direction_output(sdi0_en, 1); | |
b8410a15 | 119 | |
72930319 | 120 | /* Add the device, force v2 to subrevision 1 */ |
18403424 | 121 | db8500_add_sdi0(parent, &mop500_sdi0_data, U8500_SDI_V2_PERIPHID); |
b8410a15 RV |
122 | } |
123 | ||
18403424 | 124 | void mop500_sdi_tc35892_init(struct device *parent) |
4b4f757c LW |
125 | { |
126 | mop500_sdi0_data.gpio_cd = GPIO_SDMMC_CD; | |
127 | sdi0_en = GPIO_SDMMC_EN; | |
128 | sdi0_vsel = GPIO_SDMMC_1V8_3V_SEL; | |
18403424 | 129 | sdi0_configure(parent); |
4b4f757c LW |
130 | } |
131 | ||
76d6717b SNX |
132 | /* |
133 | * SDI1 (SDIO WLAN) | |
134 | */ | |
135 | #ifdef CONFIG_STE_DMA40 | |
136 | static struct stedma40_chan_cfg sdi1_dma_cfg_rx = { | |
137 | .mode = STEDMA40_MODE_LOGICAL, | |
138 | .dir = STEDMA40_PERIPH_TO_MEM, | |
139 | .src_dev_type = DB8500_DMA_DEV32_SD_MM1_RX, | |
140 | .dst_dev_type = STEDMA40_DEV_DST_MEMORY, | |
141 | .src_info.data_width = STEDMA40_WORD_WIDTH, | |
142 | .dst_info.data_width = STEDMA40_WORD_WIDTH, | |
143 | }; | |
144 | ||
145 | static struct stedma40_chan_cfg sdi1_dma_cfg_tx = { | |
146 | .mode = STEDMA40_MODE_LOGICAL, | |
147 | .dir = STEDMA40_MEM_TO_PERIPH, | |
148 | .src_dev_type = STEDMA40_DEV_SRC_MEMORY, | |
149 | .dst_dev_type = DB8500_DMA_DEV32_SD_MM1_TX, | |
150 | .src_info.data_width = STEDMA40_WORD_WIDTH, | |
151 | .dst_info.data_width = STEDMA40_WORD_WIDTH, | |
152 | }; | |
153 | #endif | |
154 | ||
9cf24b15 | 155 | struct mmci_platform_data mop500_sdi1_data = { |
76d6717b SNX |
156 | .ocr_mask = MMC_VDD_29_30, |
157 | .f_max = 50000000, | |
158 | .capabilities = MMC_CAP_4_BIT_DATA, | |
159 | .gpio_cd = -1, | |
160 | .gpio_wp = -1, | |
161 | #ifdef CONFIG_STE_DMA40 | |
162 | .dma_filter = stedma40_filter, | |
163 | .dma_rx_param = &sdi1_dma_cfg_rx, | |
164 | .dma_tx_param = &sdi1_dma_cfg_tx, | |
165 | #endif | |
166 | }; | |
167 | ||
008f8a2f HP |
168 | /* |
169 | * SDI 2 (POP eMMC, not on DB8500ed) | |
170 | */ | |
171 | ||
5d7b8467 LW |
172 | #ifdef CONFIG_STE_DMA40 |
173 | struct stedma40_chan_cfg mop500_sdi2_dma_cfg_rx = { | |
174 | .mode = STEDMA40_MODE_LOGICAL, | |
175 | .dir = STEDMA40_PERIPH_TO_MEM, | |
176 | .src_dev_type = DB8500_DMA_DEV28_SD_MM2_RX, | |
177 | .dst_dev_type = STEDMA40_DEV_DST_MEMORY, | |
178 | .src_info.data_width = STEDMA40_WORD_WIDTH, | |
179 | .dst_info.data_width = STEDMA40_WORD_WIDTH, | |
180 | }; | |
181 | ||
182 | static struct stedma40_chan_cfg mop500_sdi2_dma_cfg_tx = { | |
183 | .mode = STEDMA40_MODE_LOGICAL, | |
184 | .dir = STEDMA40_MEM_TO_PERIPH, | |
185 | .src_dev_type = STEDMA40_DEV_SRC_MEMORY, | |
186 | .dst_dev_type = DB8500_DMA_DEV28_SD_MM2_TX, | |
187 | .src_info.data_width = STEDMA40_WORD_WIDTH, | |
188 | .dst_info.data_width = STEDMA40_WORD_WIDTH, | |
189 | }; | |
190 | #endif | |
191 | ||
9cf24b15 | 192 | struct mmci_platform_data mop500_sdi2_data = { |
008f8a2f | 193 | .ocr_mask = MMC_VDD_165_195, |
02a73437 | 194 | .f_max = 50000000, |
c15def1c LW |
195 | .capabilities = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA | |
196 | MMC_CAP_MMC_HIGHSPEED, | |
008f8a2f HP |
197 | .gpio_cd = -1, |
198 | .gpio_wp = -1, | |
5d7b8467 LW |
199 | #ifdef CONFIG_STE_DMA40 |
200 | .dma_filter = stedma40_filter, | |
201 | .dma_rx_param = &mop500_sdi2_dma_cfg_rx, | |
202 | .dma_tx_param = &mop500_sdi2_dma_cfg_tx, | |
203 | #endif | |
008f8a2f HP |
204 | }; |
205 | ||
206 | /* | |
207 | * SDI 4 (on-board eMMC) | |
208 | */ | |
209 | ||
5d7b8467 LW |
210 | #ifdef CONFIG_STE_DMA40 |
211 | struct stedma40_chan_cfg mop500_sdi4_dma_cfg_rx = { | |
212 | .mode = STEDMA40_MODE_LOGICAL, | |
213 | .dir = STEDMA40_PERIPH_TO_MEM, | |
214 | .src_dev_type = DB8500_DMA_DEV42_SD_MM4_RX, | |
215 | .dst_dev_type = STEDMA40_DEV_DST_MEMORY, | |
216 | .src_info.data_width = STEDMA40_WORD_WIDTH, | |
217 | .dst_info.data_width = STEDMA40_WORD_WIDTH, | |
218 | }; | |
219 | ||
220 | static struct stedma40_chan_cfg mop500_sdi4_dma_cfg_tx = { | |
221 | .mode = STEDMA40_MODE_LOGICAL, | |
222 | .dir = STEDMA40_MEM_TO_PERIPH, | |
223 | .src_dev_type = STEDMA40_DEV_SRC_MEMORY, | |
224 | .dst_dev_type = DB8500_DMA_DEV42_SD_MM4_TX, | |
225 | .src_info.data_width = STEDMA40_WORD_WIDTH, | |
226 | .dst_info.data_width = STEDMA40_WORD_WIDTH, | |
227 | }; | |
228 | #endif | |
229 | ||
5e1ac7db | 230 | struct mmci_platform_data mop500_sdi4_data = { |
008f8a2f | 231 | .ocr_mask = MMC_VDD_29_30, |
02a73437 | 232 | .f_max = 50000000, |
008f8a2f HP |
233 | .capabilities = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA | |
234 | MMC_CAP_MMC_HIGHSPEED, | |
235 | .gpio_cd = -1, | |
236 | .gpio_wp = -1, | |
5d7b8467 LW |
237 | #ifdef CONFIG_STE_DMA40 |
238 | .dma_filter = stedma40_filter, | |
239 | .dma_rx_param = &mop500_sdi4_dma_cfg_rx, | |
240 | .dma_tx_param = &mop500_sdi4_dma_cfg_tx, | |
241 | #endif | |
008f8a2f HP |
242 | }; |
243 | ||
18403424 | 244 | void __init mop500_sdi_init(struct device *parent) |
008f8a2f | 245 | { |
c15def1c | 246 | /* PoP:ed eMMC */ |
18403424 | 247 | db8500_add_sdi2(parent, &mop500_sdi2_data, U8500_SDI_V2_PERIPHID); |
4bc3a698 | 248 | /* On-board eMMC */ |
18403424 LJ |
249 | db8500_add_sdi4(parent, &mop500_sdi4_data, U8500_SDI_V2_PERIPHID); |
250 | ||
edaa86a4 | 251 | /* |
4b4f757c LW |
252 | * On boards with the TC35892 GPIO expander, sdi0 will finally |
253 | * be added when the TC35892 initializes and calls | |
edaa86a4 LW |
254 | * mop500_sdi_tc35892_init() above. |
255 | */ | |
008f8a2f | 256 | } |
110c2c2f | 257 | |
18403424 | 258 | void __init snowball_sdi_init(struct device *parent) |
110c2c2f | 259 | { |
2ab1159e PL |
260 | /* On Snowball MMC_CAP_SD_HIGHSPEED isn't supported (Hardware issue?) */ |
261 | mop500_sdi0_data.capabilities &= ~MMC_CAP_SD_HIGHSPEED; | |
110c2c2f | 262 | /* On-board eMMC */ |
18403424 | 263 | db8500_add_sdi4(parent, &mop500_sdi4_data, U8500_SDI_V2_PERIPHID); |
c15def1c | 264 | /* External Micro SD slot */ |
110c2c2f LJ |
265 | mop500_sdi0_data.gpio_cd = SNOWBALL_SDMMC_CD_GPIO; |
266 | mop500_sdi0_data.cd_invert = true; | |
267 | sdi0_en = SNOWBALL_SDMMC_EN_GPIO; | |
268 | sdi0_vsel = SNOWBALL_SDMMC_1V8_3V_GPIO; | |
18403424 | 269 | sdi0_configure(parent); |
110c2c2f LJ |
270 | } |
271 | ||
18403424 | 272 | void __init hrefv60_sdi_init(struct device *parent) |
110c2c2f | 273 | { |
c15def1c | 274 | /* PoP:ed eMMC */ |
18403424 | 275 | db8500_add_sdi2(parent, &mop500_sdi2_data, U8500_SDI_V2_PERIPHID); |
110c2c2f | 276 | /* On-board eMMC */ |
18403424 | 277 | db8500_add_sdi4(parent, &mop500_sdi4_data, U8500_SDI_V2_PERIPHID); |
c15def1c | 278 | /* External Micro SD slot */ |
110c2c2f LJ |
279 | mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO; |
280 | sdi0_en = HREFV60_SDMMC_EN_GPIO; | |
281 | sdi0_vsel = HREFV60_SDMMC_1V8_3V_GPIO; | |
18403424 | 282 | sdi0_configure(parent); |
c15def1c | 283 | /* WLAN SDIO channel */ |
18403424 | 284 | db8500_add_sdi1(parent, &mop500_sdi1_data, U8500_SDI_V2_PERIPHID); |
110c2c2f | 285 | } |