blob: cf93dca97b9a688d24be908e58e32af951626496 [file] [log] [blame]
Hanumath Prasad008f8a22010-08-19 12:06:32 +01001/*
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
Linus Walleij4b4f7572011-02-15 15:01:35 +010015#include <asm/mach-types.h>
Linus Walleij5d7b8462010-10-14 13:57:59 +020016#include <plat/ste_dma40.h>
Hanumath Prasad008f8a22010-08-19 12:06:32 +010017#include <mach/devices.h>
18#include <mach/hardware.h>
19
Rabin Vincentfbf1ead2010-09-29 19:46:32 +053020#include "devices-db8500.h"
Hanumath Prasad008f8a22010-08-19 12:06:32 +010021#include "board-mop500.h"
Linus Walleij5d7b8462010-10-14 13:57:59 +020022#include "ste-dma40-db8500.h"
Hanumath Prasad008f8a22010-08-19 12:06:32 +010023
Hanumath Prasad008f8a22010-08-19 12:06:32 +010024/*
Rabin Vincentb8410a12010-08-09 19:18:17 +053025 * SDI 0 (MicroSD slot)
26 */
27
28/* MMCIPOWER bits */
29#define MCI_DATA2DIREN (1 << 2)
30#define MCI_CMDDIREN (1 << 3)
31#define MCI_DATA0DIREN (1 << 4)
32#define MCI_DATA31DIREN (1 << 5)
33#define MCI_FBCLKEN (1 << 7)
34
Linus Walleijf727a052011-04-27 12:55:37 +020035/* GPIO pins used by the sdi0 level shifter */
36static int sdi0_en = -1;
37static int sdi0_vsel = -1;
38
Rabin Vincentb8410a12010-08-09 19:18:17 +053039static u32 mop500_sdi0_vdd_handler(struct device *dev, unsigned int vdd,
40 unsigned char power_mode)
41{
Linus Walleijf727a052011-04-27 12:55:37 +020042 switch (power_mode) {
43 case MMC_POWER_UP:
44 case MMC_POWER_ON:
45 /*
46 * Level shifter voltage should depend on vdd to when deciding
47 * on either 1.8V or 2.9V. Once the decision has been made the
48 * level shifter must be disabled and re-enabled with a changed
49 * select signal in order to switch the voltage. Since there is
50 * no framework support yet for indicating 1.8V in vdd, use the
51 * default 2.9V.
52 */
53 gpio_direction_output(sdi0_vsel, 0);
54 gpio_direction_output(sdi0_en, 1);
55 break;
56 case MMC_POWER_OFF:
57 gpio_direction_output(sdi0_vsel, 0);
58 gpio_direction_output(sdi0_en, 0);
59 break;
60 }
Rabin Vincentb8410a12010-08-09 19:18:17 +053061
62 return MCI_FBCLKEN | MCI_CMDDIREN | MCI_DATA0DIREN |
63 MCI_DATA2DIREN | MCI_DATA31DIREN;
64}
65
Linus Walleij5d7b8462010-10-14 13:57:59 +020066#ifdef CONFIG_STE_DMA40
67struct stedma40_chan_cfg mop500_sdi0_dma_cfg_rx = {
68 .mode = STEDMA40_MODE_LOGICAL,
69 .dir = STEDMA40_PERIPH_TO_MEM,
70 .src_dev_type = DB8500_DMA_DEV29_SD_MM0_RX,
71 .dst_dev_type = STEDMA40_DEV_DST_MEMORY,
72 .src_info.data_width = STEDMA40_WORD_WIDTH,
73 .dst_info.data_width = STEDMA40_WORD_WIDTH,
74};
75
76static struct stedma40_chan_cfg mop500_sdi0_dma_cfg_tx = {
77 .mode = STEDMA40_MODE_LOGICAL,
78 .dir = STEDMA40_MEM_TO_PERIPH,
79 .src_dev_type = STEDMA40_DEV_SRC_MEMORY,
80 .dst_dev_type = DB8500_DMA_DEV29_SD_MM0_TX,
81 .src_info.data_width = STEDMA40_WORD_WIDTH,
82 .dst_info.data_width = STEDMA40_WORD_WIDTH,
83};
84#endif
85
Rabin Vincentb8410a12010-08-09 19:18:17 +053086static struct mmci_platform_data mop500_sdi0_data = {
87 .vdd_handler = mop500_sdi0_vdd_handler,
88 .ocr_mask = MMC_VDD_29_30,
Linus Walleij02a73432011-03-30 16:00:39 +020089 .f_max = 50000000,
90 .capabilities = MMC_CAP_4_BIT_DATA |
91 MMC_CAP_SD_HIGHSPEED |
92 MMC_CAP_MMC_HIGHSPEED,
Rabin Vincentb8410a12010-08-09 19:18:17 +053093 .gpio_wp = -1,
Linus Walleij5d7b8462010-10-14 13:57:59 +020094#ifdef CONFIG_STE_DMA40
95 .dma_filter = stedma40_filter,
96 .dma_rx_param = &mop500_sdi0_dma_cfg_rx,
97 .dma_tx_param = &mop500_sdi0_dma_cfg_tx,
98#endif
Rabin Vincentb8410a12010-08-09 19:18:17 +053099};
100
Linus Walleij4b4f7572011-02-15 15:01:35 +0100101static void sdi0_configure(void)
Rabin Vincentb8410a12010-08-09 19:18:17 +0530102{
103 int ret;
104
Linus Walleij4b4f7572011-02-15 15:01:35 +0100105 ret = gpio_request(sdi0_en, "level shifter enable");
Rabin Vincentb8410a12010-08-09 19:18:17 +0530106 if (!ret)
Linus Walleij4b4f7572011-02-15 15:01:35 +0100107 ret = gpio_request(sdi0_vsel,
108 "level shifter 1v8-3v select");
109
110 if (ret) {
111 pr_warning("unable to config sdi0 gpios for level shifter.\n");
Rabin Vincentb8410a12010-08-09 19:18:17 +0530112 return;
Linus Walleij4b4f7572011-02-15 15:01:35 +0100113 }
Rabin Vincentb8410a12010-08-09 19:18:17 +0530114
Linus Walleij4b4f7572011-02-15 15:01:35 +0100115 /* Select the default 2.9V and enable level shifter */
116 gpio_direction_output(sdi0_vsel, 0);
117 gpio_direction_output(sdi0_en, 1);
Rabin Vincentb8410a12010-08-09 19:18:17 +0530118
Linus Walleij72930312011-03-24 16:13:13 +0100119 /* Add the device, force v2 to subrevision 1 */
120 if (cpu_is_u8500v2())
121 db8500_add_sdi0(&mop500_sdi0_data, 0x10480180);
122 else
123 db8500_add_sdi0(&mop500_sdi0_data, 0);
Rabin Vincentb8410a12010-08-09 19:18:17 +0530124}
125
Linus Walleij4b4f7572011-02-15 15:01:35 +0100126void mop500_sdi_tc35892_init(void)
127{
128 mop500_sdi0_data.gpio_cd = GPIO_SDMMC_CD;
129 sdi0_en = GPIO_SDMMC_EN;
130 sdi0_vsel = GPIO_SDMMC_1V8_3V_SEL;
131 sdi0_configure();
132}
133
Rabin Vincentb8410a12010-08-09 19:18:17 +0530134/*
Stefan Nilsson XK76d67172011-10-26 10:50:42 +0200135 * SDI1 (SDIO WLAN)
136 */
137#ifdef CONFIG_STE_DMA40
138static struct stedma40_chan_cfg sdi1_dma_cfg_rx = {
139 .mode = STEDMA40_MODE_LOGICAL,
140 .dir = STEDMA40_PERIPH_TO_MEM,
141 .src_dev_type = DB8500_DMA_DEV32_SD_MM1_RX,
142 .dst_dev_type = STEDMA40_DEV_DST_MEMORY,
143 .src_info.data_width = STEDMA40_WORD_WIDTH,
144 .dst_info.data_width = STEDMA40_WORD_WIDTH,
145};
146
147static struct stedma40_chan_cfg sdi1_dma_cfg_tx = {
148 .mode = STEDMA40_MODE_LOGICAL,
149 .dir = STEDMA40_MEM_TO_PERIPH,
150 .src_dev_type = STEDMA40_DEV_SRC_MEMORY,
151 .dst_dev_type = DB8500_DMA_DEV32_SD_MM1_TX,
152 .src_info.data_width = STEDMA40_WORD_WIDTH,
153 .dst_info.data_width = STEDMA40_WORD_WIDTH,
154};
155#endif
156
157static struct mmci_platform_data mop500_sdi1_data = {
158 .ocr_mask = MMC_VDD_29_30,
159 .f_max = 50000000,
160 .capabilities = MMC_CAP_4_BIT_DATA,
161 .gpio_cd = -1,
162 .gpio_wp = -1,
163#ifdef CONFIG_STE_DMA40
164 .dma_filter = stedma40_filter,
165 .dma_rx_param = &sdi1_dma_cfg_rx,
166 .dma_tx_param = &sdi1_dma_cfg_tx,
167#endif
168};
169
170/*
Hanumath Prasad008f8a22010-08-19 12:06:32 +0100171 * SDI 2 (POP eMMC, not on DB8500ed)
172 */
173
Linus Walleij5d7b8462010-10-14 13:57:59 +0200174#ifdef CONFIG_STE_DMA40
175struct stedma40_chan_cfg mop500_sdi2_dma_cfg_rx = {
176 .mode = STEDMA40_MODE_LOGICAL,
177 .dir = STEDMA40_PERIPH_TO_MEM,
178 .src_dev_type = DB8500_DMA_DEV28_SD_MM2_RX,
179 .dst_dev_type = STEDMA40_DEV_DST_MEMORY,
180 .src_info.data_width = STEDMA40_WORD_WIDTH,
181 .dst_info.data_width = STEDMA40_WORD_WIDTH,
182};
183
184static struct stedma40_chan_cfg mop500_sdi2_dma_cfg_tx = {
185 .mode = STEDMA40_MODE_LOGICAL,
186 .dir = STEDMA40_MEM_TO_PERIPH,
187 .src_dev_type = STEDMA40_DEV_SRC_MEMORY,
188 .dst_dev_type = DB8500_DMA_DEV28_SD_MM2_TX,
189 .src_info.data_width = STEDMA40_WORD_WIDTH,
190 .dst_info.data_width = STEDMA40_WORD_WIDTH,
191};
192#endif
193
Hanumath Prasad008f8a22010-08-19 12:06:32 +0100194static struct mmci_platform_data mop500_sdi2_data = {
195 .ocr_mask = MMC_VDD_165_195,
Linus Walleij02a73432011-03-30 16:00:39 +0200196 .f_max = 50000000,
Hanumath Prasad008f8a22010-08-19 12:06:32 +0100197 .capabilities = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
198 .gpio_cd = -1,
199 .gpio_wp = -1,
Linus Walleij5d7b8462010-10-14 13:57:59 +0200200#ifdef CONFIG_STE_DMA40
201 .dma_filter = stedma40_filter,
202 .dma_rx_param = &mop500_sdi2_dma_cfg_rx,
203 .dma_tx_param = &mop500_sdi2_dma_cfg_tx,
204#endif
Hanumath Prasad008f8a22010-08-19 12:06:32 +0100205};
206
207/*
208 * SDI 4 (on-board eMMC)
209 */
210
Linus Walleij5d7b8462010-10-14 13:57:59 +0200211#ifdef CONFIG_STE_DMA40
212struct stedma40_chan_cfg mop500_sdi4_dma_cfg_rx = {
213 .mode = STEDMA40_MODE_LOGICAL,
214 .dir = STEDMA40_PERIPH_TO_MEM,
215 .src_dev_type = DB8500_DMA_DEV42_SD_MM4_RX,
216 .dst_dev_type = STEDMA40_DEV_DST_MEMORY,
217 .src_info.data_width = STEDMA40_WORD_WIDTH,
218 .dst_info.data_width = STEDMA40_WORD_WIDTH,
219};
220
221static struct stedma40_chan_cfg mop500_sdi4_dma_cfg_tx = {
222 .mode = STEDMA40_MODE_LOGICAL,
223 .dir = STEDMA40_MEM_TO_PERIPH,
224 .src_dev_type = STEDMA40_DEV_SRC_MEMORY,
225 .dst_dev_type = DB8500_DMA_DEV42_SD_MM4_TX,
226 .src_info.data_width = STEDMA40_WORD_WIDTH,
227 .dst_info.data_width = STEDMA40_WORD_WIDTH,
228};
229#endif
230
Hanumath Prasad008f8a22010-08-19 12:06:32 +0100231static struct mmci_platform_data mop500_sdi4_data = {
232 .ocr_mask = MMC_VDD_29_30,
Linus Walleij02a73432011-03-30 16:00:39 +0200233 .f_max = 50000000,
Hanumath Prasad008f8a22010-08-19 12:06:32 +0100234 .capabilities = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA |
235 MMC_CAP_MMC_HIGHSPEED,
236 .gpio_cd = -1,
237 .gpio_wp = -1,
Linus Walleij5d7b8462010-10-14 13:57:59 +0200238#ifdef CONFIG_STE_DMA40
239 .dma_filter = stedma40_filter,
240 .dma_rx_param = &mop500_sdi4_dma_cfg_rx,
241 .dma_tx_param = &mop500_sdi4_dma_cfg_tx,
242#endif
Hanumath Prasad008f8a22010-08-19 12:06:32 +0100243};
244
Linus Walleijedaa86a2010-12-02 12:05:18 +0100245void __init mop500_sdi_init(void)
Hanumath Prasad008f8a22010-08-19 12:06:32 +0100246{
Linus Walleij72930312011-03-24 16:13:13 +0100247 u32 periphid = 0;
248
249 /* v2 has a new version of this block that need to be forced */
250 if (cpu_is_u8500v2())
251 periphid = 0x10480180;
Bibek Basu4bc3a692011-02-15 10:46:59 +0100252 /* PoP:ed eMMC on top of DB8500 v1.0 has problems with high speed */
253 if (!cpu_is_u8500v10())
254 mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
Lee Jones110c2c22011-08-26 16:54:07 +0100255
256 db8500_add_sdi2(&mop500_sdi2_data, periphid);
Bibek Basu4bc3a692011-02-15 10:46:59 +0100257
258 /* On-board eMMC */
Linus Walleij72930312011-03-24 16:13:13 +0100259 db8500_add_sdi4(&mop500_sdi4_data, periphid);
Hanumath Prasad008f8a22010-08-19 12:06:32 +0100260
Linus Walleijedaa86a2010-12-02 12:05:18 +0100261 /*
Linus Walleij4b4f7572011-02-15 15:01:35 +0100262 * On boards with the TC35892 GPIO expander, sdi0 will finally
263 * be added when the TC35892 initializes and calls
Linus Walleijedaa86a2010-12-02 12:05:18 +0100264 * mop500_sdi_tc35892_init() above.
265 */
Hanumath Prasad008f8a22010-08-19 12:06:32 +0100266}
Lee Jones110c2c22011-08-26 16:54:07 +0100267
268void __init snowball_sdi_init(void)
269{
270 u32 periphid = 0x10480180;
271
272 mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
273
274 /* On-board eMMC */
275 db8500_add_sdi4(&mop500_sdi4_data, periphid);
276
277 mop500_sdi0_data.gpio_cd = SNOWBALL_SDMMC_CD_GPIO;
278 mop500_sdi0_data.cd_invert = true;
279 sdi0_en = SNOWBALL_SDMMC_EN_GPIO;
280 sdi0_vsel = SNOWBALL_SDMMC_1V8_3V_GPIO;
281 sdi0_configure();
282}
283
284void __init hrefv60_sdi_init(void)
285{
286 u32 periphid = 0x10480180;
287
288 mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
289
290 db8500_add_sdi2(&mop500_sdi2_data, periphid);
291
292 /* On-board eMMC */
293 db8500_add_sdi4(&mop500_sdi4_data, periphid);
294
295 mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO;
296 sdi0_en = HREFV60_SDMMC_EN_GPIO;
297 sdi0_vsel = HREFV60_SDMMC_1V8_3V_GPIO;
298 sdi0_configure();
Stefan Nilsson XK76d67172011-10-26 10:50:42 +0200299
300 db8500_add_sdi1(&mop500_sdi1_data, periphid);
Lee Jones110c2c22011-08-26 16:54:07 +0100301}