board-mop500-sdi.c 7.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 * Copyright (C) ST-Ericsson SA 2010
 *
 * Author: Hanumath Prasad <hanumath.prasad@stericsson.com>
 * License terms: GNU General Public License (GPL) version 2
 */

#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/amba/bus.h>
#include <linux/amba/mmci.h>
#include <linux/mmc/host.h>
#include <linux/platform_device.h>

15
#include <asm/mach-types.h>
16
#include <plat/ste_dma40.h>
17 18 19
#include <mach/devices.h>
#include <mach/hardware.h>

R
Rabin Vincent 已提交
20
#include "devices-db8500.h"
21
#include "board-mop500.h"
22
#include "ste-dma40-db8500.h"
23

24 25 26 27 28 29
/*
 * v2 has a new version of this block that need to be forced, the number found
 * in hardware is incorrect
 */
#define U8500_SDI_V2_PERIPHID 0x10480180

30 31 32 33
/*
 * SDI 0 (MicroSD slot)
 */

34 35 36 37
/* GPIO pins used by the sdi0 level shifter */
static int sdi0_en = -1;
static int sdi0_vsel = -1;

38
static int mop500_sdi0_ios_handler(struct device *dev, struct mmc_ios *ios)
39
{
40
	switch (ios->power_mode) {
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
	case MMC_POWER_UP:
	case MMC_POWER_ON:
		/*
		 * Level shifter voltage should depend on vdd to when deciding
		 * on either 1.8V or 2.9V. Once the decision has been made the
		 * level shifter must be disabled and re-enabled with a changed
		 * select signal in order to switch the voltage. Since there is
		 * no framework support yet for indicating 1.8V in vdd, use the
		 * default 2.9V.
		 */
		gpio_direction_output(sdi0_vsel, 0);
		gpio_direction_output(sdi0_en, 1);
		break;
	case MMC_POWER_OFF:
		gpio_direction_output(sdi0_vsel, 0);
		gpio_direction_output(sdi0_en, 0);
		break;
	}
59

60
	return 0;
61 62
}

63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
#ifdef CONFIG_STE_DMA40
struct stedma40_chan_cfg mop500_sdi0_dma_cfg_rx = {
	.mode = STEDMA40_MODE_LOGICAL,
	.dir = STEDMA40_PERIPH_TO_MEM,
	.src_dev_type = DB8500_DMA_DEV29_SD_MM0_RX,
	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
	.src_info.data_width = STEDMA40_WORD_WIDTH,
	.dst_info.data_width = STEDMA40_WORD_WIDTH,
};

static struct stedma40_chan_cfg mop500_sdi0_dma_cfg_tx = {
	.mode = STEDMA40_MODE_LOGICAL,
	.dir = STEDMA40_MEM_TO_PERIPH,
	.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
	.dst_dev_type = DB8500_DMA_DEV29_SD_MM0_TX,
	.src_info.data_width = STEDMA40_WORD_WIDTH,
	.dst_info.data_width = STEDMA40_WORD_WIDTH,
};
#endif

83
struct mmci_platform_data mop500_sdi0_data = {
84
	.ios_handler	= mop500_sdi0_ios_handler,
85
	.ocr_mask	= MMC_VDD_29_30,
86 87 88 89
	.f_max		= 50000000,
	.capabilities	= MMC_CAP_4_BIT_DATA |
				MMC_CAP_SD_HIGHSPEED |
				MMC_CAP_MMC_HIGHSPEED,
90
	.gpio_wp	= -1,
91 92 93 94
	.sigdir		= MCI_ST_FBCLKEN |
				MCI_ST_CMDDIREN |
				MCI_ST_DATA0DIREN |
				MCI_ST_DATA2DIREN,
95 96 97 98 99
#ifdef CONFIG_STE_DMA40
	.dma_filter	= stedma40_filter,
	.dma_rx_param	= &mop500_sdi0_dma_cfg_rx,
	.dma_tx_param	= &mop500_sdi0_dma_cfg_tx,
#endif
100 101
};

102
static void sdi0_configure(struct device *parent)
103 104 105
{
	int ret;

106
	ret = gpio_request(sdi0_en, "level shifter enable");
107
	if (!ret)
108 109 110 111 112
		ret = gpio_request(sdi0_vsel,
				   "level shifter 1v8-3v select");

	if (ret) {
		pr_warning("unable to config sdi0 gpios for level shifter.\n");
113
		return;
114
	}
115

116 117 118
	/* Select the default 2.9V and enable level shifter */
	gpio_direction_output(sdi0_vsel, 0);
	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 127 128
{
	mop500_sdi0_data.gpio_cd = GPIO_SDMMC_CD;
	sdi0_en = GPIO_SDMMC_EN;
	sdi0_vsel = GPIO_SDMMC_1V8_3V_SEL;
129
	sdi0_configure(parent);
130 131
}

132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
/*
 * SDI1 (SDIO WLAN)
 */
#ifdef CONFIG_STE_DMA40
static struct stedma40_chan_cfg sdi1_dma_cfg_rx = {
	.mode = STEDMA40_MODE_LOGICAL,
	.dir = STEDMA40_PERIPH_TO_MEM,
	.src_dev_type = DB8500_DMA_DEV32_SD_MM1_RX,
	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
	.src_info.data_width = STEDMA40_WORD_WIDTH,
	.dst_info.data_width = STEDMA40_WORD_WIDTH,
};

static struct stedma40_chan_cfg sdi1_dma_cfg_tx = {
	.mode = STEDMA40_MODE_LOGICAL,
	.dir = STEDMA40_MEM_TO_PERIPH,
	.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
	.dst_dev_type = DB8500_DMA_DEV32_SD_MM1_TX,
	.src_info.data_width = STEDMA40_WORD_WIDTH,
	.dst_info.data_width = STEDMA40_WORD_WIDTH,
};
#endif

static struct mmci_platform_data mop500_sdi1_data = {
	.ocr_mask	= MMC_VDD_29_30,
	.f_max		= 50000000,
	.capabilities	= MMC_CAP_4_BIT_DATA,
	.gpio_cd	= -1,
	.gpio_wp	= -1,
#ifdef CONFIG_STE_DMA40
	.dma_filter	= stedma40_filter,
	.dma_rx_param	= &sdi1_dma_cfg_rx,
	.dma_tx_param	= &sdi1_dma_cfg_tx,
#endif
};

168 169 170 171
/*
 * SDI 2 (POP eMMC, not on DB8500ed)
 */

172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
#ifdef CONFIG_STE_DMA40
struct stedma40_chan_cfg mop500_sdi2_dma_cfg_rx = {
	.mode = STEDMA40_MODE_LOGICAL,
	.dir = STEDMA40_PERIPH_TO_MEM,
	.src_dev_type =  DB8500_DMA_DEV28_SD_MM2_RX,
	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
	.src_info.data_width = STEDMA40_WORD_WIDTH,
	.dst_info.data_width = STEDMA40_WORD_WIDTH,
};

static struct stedma40_chan_cfg mop500_sdi2_dma_cfg_tx = {
	.mode = STEDMA40_MODE_LOGICAL,
	.dir = STEDMA40_MEM_TO_PERIPH,
	.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
	.dst_dev_type = DB8500_DMA_DEV28_SD_MM2_TX,
	.src_info.data_width = STEDMA40_WORD_WIDTH,
	.dst_info.data_width = STEDMA40_WORD_WIDTH,
};
#endif

192 193
static struct mmci_platform_data mop500_sdi2_data = {
	.ocr_mask	= MMC_VDD_165_195,
194
	.f_max		= 50000000,
195 196
	.capabilities	= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA |
			  MMC_CAP_MMC_HIGHSPEED,
197 198
	.gpio_cd	= -1,
	.gpio_wp	= -1,
199 200 201 202 203
#ifdef CONFIG_STE_DMA40
	.dma_filter	= stedma40_filter,
	.dma_rx_param	= &mop500_sdi2_dma_cfg_rx,
	.dma_tx_param	= &mop500_sdi2_dma_cfg_tx,
#endif
204 205 206 207 208 209
};

/*
 * SDI 4 (on-board eMMC)
 */

210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
#ifdef CONFIG_STE_DMA40
struct stedma40_chan_cfg mop500_sdi4_dma_cfg_rx = {
	.mode = STEDMA40_MODE_LOGICAL,
	.dir = STEDMA40_PERIPH_TO_MEM,
	.src_dev_type =  DB8500_DMA_DEV42_SD_MM4_RX,
	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
	.src_info.data_width = STEDMA40_WORD_WIDTH,
	.dst_info.data_width = STEDMA40_WORD_WIDTH,
};

static struct stedma40_chan_cfg mop500_sdi4_dma_cfg_tx = {
	.mode = STEDMA40_MODE_LOGICAL,
	.dir = STEDMA40_MEM_TO_PERIPH,
	.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
	.dst_dev_type = DB8500_DMA_DEV42_SD_MM4_TX,
	.src_info.data_width = STEDMA40_WORD_WIDTH,
	.dst_info.data_width = STEDMA40_WORD_WIDTH,
};
#endif

230
struct mmci_platform_data mop500_sdi4_data = {
231
	.ocr_mask	= MMC_VDD_29_30,
232
	.f_max		= 50000000,
233 234 235 236
	.capabilities	= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA |
			  MMC_CAP_MMC_HIGHSPEED,
	.gpio_cd	= -1,
	.gpio_wp	= -1,
237 238 239 240 241
#ifdef CONFIG_STE_DMA40
	.dma_filter	= stedma40_filter,
	.dma_rx_param	= &mop500_sdi4_dma_cfg_rx,
	.dma_tx_param	= &mop500_sdi4_dma_cfg_tx,
#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);
B
Bibek Basu 已提交
248
	/* On-board eMMC */
249 250
	db8500_add_sdi4(parent, &mop500_sdi4_data, U8500_SDI_V2_PERIPHID);

251
	/*
252 253
	 * On boards with the TC35892 GPIO expander, sdi0 will finally
	 * be added when the TC35892 initializes and calls
254 255
	 * mop500_sdi_tc35892_init() above.
	 */
256
}
257

258
void __init snowball_sdi_init(struct device *parent)
259
{
260 261
	/* On Snowball MMC_CAP_SD_HIGHSPEED isn't supported (Hardware issue?) */
	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 266 267 268
	mop500_sdi0_data.gpio_cd = SNOWBALL_SDMMC_CD_GPIO;
	mop500_sdi0_data.cd_invert = true;
	sdi0_en = SNOWBALL_SDMMC_EN_GPIO;
	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 280 281
	mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO;
	sdi0_en = HREFV60_SDMMC_EN_GPIO;
	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
}