Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
board-mop500-sdi.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) ST-Ericsson SA 2010
3  *
4  * Author: Hanumath Prasad <[email protected]>
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 
15 #include <asm/mach-types.h>
16 #include <plat/ste_dma40.h>
17 #include <mach/devices.h>
18 #include <mach/hardware.h>
19 
20 #include "devices-db8500.h"
21 #include "board-mop500.h"
22 #include "ste-dma40-db8500.h"
23 
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 
30 /*
31  * SDI 0 (MicroSD slot)
32  */
33 
34 /* GPIO pins used by the sdi0 level shifter */
35 static int sdi0_en = -1;
36 static int sdi0_vsel = -1;
37 
38 static int mop500_sdi0_ios_handler(struct device *dev, struct mmc_ios *ios)
39 {
40  switch (ios->power_mode) {
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  }
59 
60  return 0;
61 }
62 
63 #ifdef CONFIG_STE_DMA40
64 struct stedma40_chan_cfg mop500_sdi0_dma_cfg_rx = {
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 = {
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 
84  .ios_handler = mop500_sdi0_ios_handler,
85  .ocr_mask = MMC_VDD_29_30,
86  .f_max = 50000000,
87  .capabilities = MMC_CAP_4_BIT_DATA |
90  .gpio_wp = -1,
91  .sigdir = MCI_ST_FBCLKEN |
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
100 };
101 
102 static void sdi0_configure(struct device *parent)
103 {
104  int ret;
105 
106  ret = gpio_request(sdi0_en, "level shifter enable");
107  if (!ret)
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");
113  return;
114  }
115 
116  /* Select the default 2.9V and enable level shifter */
117  gpio_direction_output(sdi0_vsel, 0);
118  gpio_direction_output(sdi0_en, 1);
119 
120  /* Add the device, force v2 to subrevision 1 */
121  db8500_add_sdi0(parent, &mop500_sdi0_data, U8500_SDI_V2_PERIPHID);
122 }
123 
124 void mop500_sdi_tc35892_init(struct device *parent)
125 {
126  mop500_sdi0_data.gpio_cd = GPIO_SDMMC_CD;
127  sdi0_en = GPIO_SDMMC_EN;
128  sdi0_vsel = GPIO_SDMMC_1V8_3V_SEL;
129  sdi0_configure(parent);
130 }
131 
132 /*
133  * SDI1 (SDIO WLAN)
134  */
135 #ifdef CONFIG_STE_DMA40
136 static struct stedma40_chan_cfg sdi1_dma_cfg_rx = {
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 = {
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 
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 
168 /*
169  * SDI 2 (POP eMMC, not on DB8500ed)
170  */
171 
172 #ifdef CONFIG_STE_DMA40
173 struct stedma40_chan_cfg mop500_sdi2_dma_cfg_rx = {
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 = {
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 
193  .ocr_mask = MMC_VDD_165_195,
194  .f_max = 50000000,
195  .capabilities = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA |
197  .gpio_cd = -1,
198  .gpio_wp = -1,
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
204 };
205 
206 /*
207  * SDI 4 (on-board eMMC)
208  */
209 
210 #ifdef CONFIG_STE_DMA40
211 struct stedma40_chan_cfg mop500_sdi4_dma_cfg_rx = {
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 = {
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 
231  .ocr_mask = MMC_VDD_29_30,
232  .f_max = 50000000,
233  .capabilities = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA |
235  .gpio_cd = -1,
236  .gpio_wp = -1,
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
242 };
243 
244 void __init mop500_sdi_init(struct device *parent)
245 {
246  /* PoP:ed eMMC */
247  db8500_add_sdi2(parent, &mop500_sdi2_data, U8500_SDI_V2_PERIPHID);
248  /* On-board eMMC */
249  db8500_add_sdi4(parent, &mop500_sdi4_data, U8500_SDI_V2_PERIPHID);
250 
251  /*
252  * On boards with the TC35892 GPIO expander, sdi0 will finally
253  * be added when the TC35892 initializes and calls
254  * mop500_sdi_tc35892_init() above.
255  */
256 }
257 
258 void __init snowball_sdi_init(struct device *parent)
259 {
260  /* On Snowball MMC_CAP_SD_HIGHSPEED isn't supported (Hardware issue?) */
261  mop500_sdi0_data.capabilities &= ~MMC_CAP_SD_HIGHSPEED;
262  /* On-board eMMC */
263  db8500_add_sdi4(parent, &mop500_sdi4_data, U8500_SDI_V2_PERIPHID);
264  /* External Micro SD slot */
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;
269  sdi0_configure(parent);
270 }
271 
272 void __init hrefv60_sdi_init(struct device *parent)
273 {
274  /* PoP:ed eMMC */
275  db8500_add_sdi2(parent, &mop500_sdi2_data, U8500_SDI_V2_PERIPHID);
276  /* On-board eMMC */
277  db8500_add_sdi4(parent, &mop500_sdi4_data, U8500_SDI_V2_PERIPHID);
278  /* External Micro SD slot */
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;
282  sdi0_configure(parent);
283  /* WLAN SDIO channel */
284  db8500_add_sdi1(parent, &mop500_sdi1_data, U8500_SDI_V2_PERIPHID);
285 }