hsmmc.c 9.7 KB
Newer Older
1
/*
2
 * linux/arch/arm/mach-omap2/hsmmc.c
3 4 5 6 7 8 9 10 11
 *
 * Copyright (C) 2007-2008 Texas Instruments
 * Copyright (C) 2008 Nokia Corporation
 * Author: Texas Instruments
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
12 13 14
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/string.h>
15 16
#include <linux/delay.h>
#include <mach/hardware.h>
17 18
#include <plat/control.h>
#include <plat/mmc.h>
19
#include <plat/omap-pm.h>
20

21
#include "hsmmc.h"
22

23
#if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
24 25 26

static u16 control_pbias_offset;
static u16 control_devconf1_offset;
27
static u16 control_mmc1;
28 29 30

#define HSMMC_NAME_LEN	9

31
static struct hsmmc_controller {
32 33
	char				name[HSMMC_NAME_LEN + 1];
} hsmmc[OMAP34XX_NR_MMC];
34

35 36
#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)

37
static int hsmmc_get_context_loss(struct device *dev)
38
{
39
	return omap_pm_get_dev_context_loss_count(dev);
40 41 42
}

#else
43
#define hsmmc_get_context_loss NULL
44 45
#endif

46
static void omap_hsmmc1_before_set_reg(struct device *dev, int slot,
47
				  int power_on, int vdd)
48
{
49
	u32 reg, prog_io;
50 51
	struct omap_mmc_platform_data *mmc = dev->platform_data;

52 53 54
	if (mmc->slots[0].remux)
		mmc->slots[0].remux(dev, slot, power_on);

55 56
	/*
	 * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the
57
	 * card with Vcc regulator (from twl4030 or whatever).  OMAP has both
58 59 60 61
	 * 1.8V and 3.0V modes, controlled by the PBIAS register.
	 *
	 * In 8-bit modes, OMAP VMMC1A (for DAT4..7) needs a supply, which
	 * is most naturally TWL VSIM; those pins also use PBIAS.
62 63
	 *
	 * FIXME handle VMMC1A as needed ...
64
	 */
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
	if (power_on) {
		if (cpu_is_omap2430()) {
			reg = omap_ctrl_readl(OMAP243X_CONTROL_DEVCONF1);
			if ((1 << vdd) >= MMC_VDD_30_31)
				reg |= OMAP243X_MMC1_ACTIVE_OVERWRITE;
			else
				reg &= ~OMAP243X_MMC1_ACTIVE_OVERWRITE;
			omap_ctrl_writel(reg, OMAP243X_CONTROL_DEVCONF1);
		}

		if (mmc->slots[0].internal_clock) {
			reg = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
			reg |= OMAP2_MMCSDIO1ADPCLKISEL;
			omap_ctrl_writel(reg, OMAP2_CONTROL_DEVCONF0);
		}

		reg = omap_ctrl_readl(control_pbias_offset);
82 83 84 85 86 87 88 89
		if (cpu_is_omap3630()) {
			/* Set MMC I/O to 52Mhz */
			prog_io = omap_ctrl_readl(OMAP343X_CONTROL_PROG_IO1);
			prog_io |= OMAP3630_PRG_SDMMC1_SPEEDCTRL;
			omap_ctrl_writel(prog_io, OMAP343X_CONTROL_PROG_IO1);
		} else {
			reg |= OMAP2_PBIASSPEEDCTRL0;
		}
90 91
		reg &= ~OMAP2_PBIASLITEPWRDNZ0;
		omap_ctrl_writel(reg, control_pbias_offset);
92 93 94 95 96 97 98
	} else {
		reg = omap_ctrl_readl(control_pbias_offset);
		reg &= ~OMAP2_PBIASLITEPWRDNZ0;
		omap_ctrl_writel(reg, control_pbias_offset);
	}
}

99
static void omap_hsmmc1_after_set_reg(struct device *dev, int slot,
100 101 102
				 int power_on, int vdd)
{
	u32 reg;
103

104 105
	/* 100ms delay required for PBIAS configuration */
	msleep(100);
106

107
	if (power_on) {
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
		reg = omap_ctrl_readl(control_pbias_offset);
		reg |= (OMAP2_PBIASLITEPWRDNZ0 | OMAP2_PBIASSPEEDCTRL0);
		if ((1 << vdd) <= MMC_VDD_165_195)
			reg &= ~OMAP2_PBIASLITEVMODE0;
		else
			reg |= OMAP2_PBIASLITEVMODE0;
		omap_ctrl_writel(reg, control_pbias_offset);
	} else {
		reg = omap_ctrl_readl(control_pbias_offset);
		reg |= (OMAP2_PBIASSPEEDCTRL0 | OMAP2_PBIASLITEPWRDNZ0 |
			OMAP2_PBIASLITEVMODE0);
		omap_ctrl_writel(reg, control_pbias_offset);
	}
}

123 124 125 126 127 128 129 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 168 169 170 171 172 173 174 175 176
static void omap4_hsmmc1_before_set_reg(struct device *dev, int slot,
				  int power_on, int vdd)
{
	u32 reg;

	/*
	 * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the
	 * card with Vcc regulator (from twl4030 or whatever).  OMAP has both
	 * 1.8V and 3.0V modes, controlled by the PBIAS register.
	 *
	 * In 8-bit modes, OMAP VMMC1A (for DAT4..7) needs a supply, which
	 * is most naturally TWL VSIM; those pins also use PBIAS.
	 *
	 * FIXME handle VMMC1A as needed ...
	 */
	reg = omap_ctrl_readl(control_pbias_offset);
	reg &= ~(OMAP4_MMC1_PBIASLITE_PWRDNZ | OMAP4_MMC1_PWRDNZ |
					OMAP4_USBC1_ICUSB_PWRDNZ);
	omap_ctrl_writel(reg, control_pbias_offset);
}

static void omap4_hsmmc1_after_set_reg(struct device *dev, int slot,
				 int power_on, int vdd)
{
	u32 reg;

	if (power_on) {
		reg = omap_ctrl_readl(control_pbias_offset);
		reg |= OMAP4_MMC1_PBIASLITE_PWRDNZ;
		if ((1 << vdd) <= MMC_VDD_165_195)
			reg &= ~OMAP4_MMC1_PBIASLITE_VMODE;
		else
			reg |= OMAP4_MMC1_PBIASLITE_VMODE;
		reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ | OMAP4_MMC1_PWRDNZ |
						OMAP4_USBC1_ICUSB_PWRDNZ);
		omap_ctrl_writel(reg, control_pbias_offset);
		/* 4 microsec delay for comparator to generate an error*/
		udelay(4);
		reg = omap_ctrl_readl(control_pbias_offset);
		if (reg & OMAP4_MMC1_PBIASLITE_VMODE_ERROR) {
			pr_err("Pbias Voltage is not same as LDO\n");
			/* Caution : On VMODE_ERROR Power Down MMC IO */
			reg &= ~(OMAP4_MMC1_PWRDNZ | OMAP4_USBC1_ICUSB_PWRDNZ);
			omap_ctrl_writel(reg, control_pbias_offset);
		}
	} else {
		reg = omap_ctrl_readl(control_pbias_offset);
		 reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ |
			OMAP4_MMC1_PBIASLITE_VMODE | OMAP4_MMC1_PWRDNZ |
			OMAP4_USBC1_ICUSB_PWRDNZ);
		omap_ctrl_writel(reg, control_pbias_offset);
	}
}

177 178
static void hsmmc23_before_set_reg(struct device *dev, int slot,
				   int power_on, int vdd)
179 180
{
	struct omap_mmc_platform_data *mmc = dev->platform_data;
181

182 183 184
	if (mmc->slots[0].remux)
		mmc->slots[0].remux(dev, slot, power_on);

185
	if (power_on) {
186
		/* Only MMC2 supports a CLKIN */
187 188 189 190 191 192 193
		if (mmc->slots[0].internal_clock) {
			u32 reg;

			reg = omap_ctrl_readl(control_devconf1_offset);
			reg |= OMAP2_MMCSDIO2ADPCLKISEL;
			omap_ctrl_writel(reg, control_devconf1_offset);
		}
194 195 196
	}
}

197 198 199 200 201 202
static int nop_mmc_set_power(struct device *dev, int slot, int power_on,
							int vdd)
{
	return 0;
}

203 204
static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata;

205
void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
206
{
207
	struct omap2_hsmmc_info *c;
208
	int nr_hsmmc = ARRAY_SIZE(hsmmc_data);
A
Aaro Koskinen 已提交
209
	int i;
210
	u32 reg;
211

212 213 214 215 216 217 218 219
	if (!cpu_is_omap44xx()) {
		if (cpu_is_omap2430()) {
			control_pbias_offset = OMAP243X_CONTROL_PBIAS_LITE;
			control_devconf1_offset = OMAP243X_CONTROL_DEVCONF1;
		} else {
			control_pbias_offset = OMAP343X_CONTROL_PBIAS_LITE;
			control_devconf1_offset = OMAP343X_CONTROL_DEVCONF1;
		}
220
	} else {
221 222 223 224 225 226 227 228 229 230 231
		control_pbias_offset = OMAP44XX_CONTROL_PBIAS_LITE;
		control_mmc1 = OMAP44XX_CONTROL_MMC1;
		reg = omap_ctrl_readl(control_mmc1);
		reg |= (OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP0 |
			OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP1);
		reg &= ~(OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP2 |
			OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP3);
		reg |= (OMAP4_CONTROL_SDMMC1_DR0_SPEEDCTRL |
			OMAP4_CONTROL_SDMMC1_DR1_SPEEDCTRL |
			OMAP4_CONTROL_SDMMC1_DR2_SPEEDCTRL);
		omap_ctrl_writel(reg, control_mmc1);
232 233 234
	}

	for (c = controllers; c->mmc; c++) {
235
		struct hsmmc_controller *hc = hsmmc + c->mmc - 1;
236 237 238 239 240 241 242 243 244 245 246
		struct omap_mmc_platform_data *mmc = hsmmc_data[c->mmc - 1];

		if (!c->mmc || c->mmc > nr_hsmmc) {
			pr_debug("MMC%d: no such controller\n", c->mmc);
			continue;
		}
		if (mmc) {
			pr_debug("MMC%d: already configured\n", c->mmc);
			continue;
		}

247 248
		mmc = kzalloc(sizeof(struct omap_mmc_platform_data),
			      GFP_KERNEL);
249 250
		if (!mmc) {
			pr_err("Cannot allocate memory for mmc device!\n");
A
Aaro Koskinen 已提交
251
			goto done;
252 253
		}

254
		if (c->name)
255
			strncpy(hc->name, c->name, HSMMC_NAME_LEN);
256
		else
257
			snprintf(hc->name, ARRAY_SIZE(hc->name),
258
				"mmc%islot%i", c->mmc, 1);
259
		mmc->slots[0].name = hc->name;
260 261 262 263 264
		mmc->nr_slots = 1;
		mmc->slots[0].wires = c->wires;
		mmc->slots[0].internal_clock = !c->ext_clock;
		mmc->dma_mask = 0xffffffff;

265
		mmc->get_context_loss_count = hsmmc_get_context_loss;
266

267 268
		mmc->slots[0].switch_pin = c->gpio_cd;
		mmc->slots[0].gpio_wp = c->gpio_wp;
269

270
		mmc->slots[0].remux = c->remux;
271
		mmc->slots[0].init_card = c->init_card;
272

273 274
		if (c->cover_only)
			mmc->slots[0].cover = 1;
275

276 277 278
		if (c->nonremovable)
			mmc->slots[0].nonremovable = 1;

279 280 281
		if (c->power_saving)
			mmc->slots[0].power_saving = 1;

282 283 284
		if (c->no_off)
			mmc->slots[0].no_off = 1;

285 286 287
		if (c->vcc_aux_disable_is_sleep)
			mmc->slots[0].vcc_aux_disable_is_sleep = 1;

288 289 290 291 292
		/* NOTE:  MMC slots should have a Vcc regulator set up.
		 * This may be from a TWL4030-family chip, another
		 * controllable regulator, or a fixed supply.
		 *
		 * temporary HACK: ocr_mask instead of fixed supply
293
		 */
294
		mmc->slots[0].ocr_mask = c->ocr_mask;
295

296 297 298 299 300
		if (cpu_is_omap3517() || cpu_is_omap3505())
			mmc->slots[0].set_power = nop_mmc_set_power;
		else
			mmc->slots[0].features |= HSMMC_HAS_PBIAS;

301 302
		switch (c->mmc) {
		case 1:
303 304
			if (mmc->slots[0].features & HSMMC_HAS_PBIAS) {
				/* on-chip level shifting via PBIAS0/PBIAS1 */
305 306 307 308 309 310 311 312 313 314 315
				if (cpu_is_omap44xx()) {
					mmc->slots[0].before_set_reg =
						omap4_hsmmc1_before_set_reg;
					mmc->slots[0].after_set_reg =
						omap4_hsmmc1_after_set_reg;
				} else {
					mmc->slots[0].before_set_reg =
						omap_hsmmc1_before_set_reg;
					mmc->slots[0].after_set_reg =
						omap_hsmmc1_after_set_reg;
				}
316
			}
M
Madhu 已提交
317 318 319 320 321 322

			/* Omap3630 HSMMC1 supports only 4-bit */
			if (cpu_is_omap3630() && c->wires > 4) {
				c->wires = 4;
				mmc->slots[0].wires = c->wires;
			}
323 324
			break;
		case 2:
325 326 327 328 329
			if (c->ext_clock)
				c->transceiver = 1;
			if (c->transceiver && c->wires > 4)
				c->wires = 4;
			/* FALLTHROUGH */
330
		case 3:
331 332 333 334 335
			if (mmc->slots[0].features & HSMMC_HAS_PBIAS) {
				/* off-chip level shifting, or none */
				mmc->slots[0].before_set_reg = hsmmc23_before_set_reg;
				mmc->slots[0].after_set_reg = NULL;
			}
336
			break;
337 338
		default:
			pr_err("MMC%d configuration not supported!\n", c->mmc);
339
			kfree(mmc);
340 341 342 343 344 345
			continue;
		}
		hsmmc_data[c->mmc - 1] = mmc;
	}

	omap2_init_mmc(hsmmc_data, OMAP34XX_NR_MMC);
346 347 348 349 350 351 352 353 354

	/* pass the device nodes back to board setup code */
	for (c = controllers; c->mmc; c++) {
		struct omap_mmc_platform_data *mmc = hsmmc_data[c->mmc - 1];

		if (!c->mmc || c->mmc > nr_hsmmc)
			continue;
		c->dev = mmc->dev;
	}
A
Aaro Koskinen 已提交
355 356 357 358

done:
	for (i = 0; i < nr_hsmmc; i++)
		kfree(hsmmc_data[i]);
359 360 361
}

#endif