sdhci-tegra.c 13.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * Copyright (C) 2010 Google, Inc.
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#include <linux/err.h>
16
#include <linux/module.h>
17 18 19 20
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/io.h>
21
#include <linux/of.h>
22
#include <linux/of_device.h>
23 24
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
L
Lucas Stach 已提交
25
#include <linux/mmc/mmc.h>
26
#include <linux/mmc/slot-gpio.h>
27
#include <linux/gpio/consumer.h>
28 29 30

#include "sdhci-pltfm.h"

31
/* Tegra SDHOST controller vendor register definitions */
L
Lucas Stach 已提交
32
#define SDHCI_TEGRA_VENDOR_CLOCK_CTRL			0x100
L
Lucas Stach 已提交
33 34 35
#define SDHCI_CLOCK_CTRL_TAP_MASK			0x00ff0000
#define SDHCI_CLOCK_CTRL_TAP_SHIFT			16
#define SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE		BIT(5)
L
Lucas Stach 已提交
36 37 38
#define SDHCI_CLOCK_CTRL_PADPIPE_CLKEN_OVERRIDE		BIT(3)
#define SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE	BIT(2)

39
#define SDHCI_TEGRA_VENDOR_MISC_CTRL		0x120
40 41
#define SDHCI_MISC_CTRL_ENABLE_SDR104		0x8
#define SDHCI_MISC_CTRL_ENABLE_SDR50		0x10
42
#define SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300	0x20
43
#define SDHCI_MISC_CTRL_ENABLE_DDR50		0x200
44

45 46
#define NVQUIRK_FORCE_SDHCI_SPEC_200	BIT(0)
#define NVQUIRK_ENABLE_BLOCK_GAP_DET	BIT(1)
47
#define NVQUIRK_ENABLE_SDHCI_SPEC_300	BIT(2)
48 49 50
#define NVQUIRK_DISABLE_SDR50		BIT(3)
#define NVQUIRK_DISABLE_SDR104		BIT(4)
#define NVQUIRK_DISABLE_DDR50		BIT(5)
51 52

struct sdhci_tegra_soc_data {
53
	const struct sdhci_pltfm_data *pdata;
54 55 56 57 58
	u32 nvquirks;
};

struct sdhci_tegra {
	const struct sdhci_tegra_soc_data *soc_data;
59
	struct gpio_desc *power_gpio;
60
	bool ddr_signaling;
61 62
};

63 64
static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
{
65 66 67 68 69 70
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_tegra *tegra_host = pltfm_host->priv;
	const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;

	if (unlikely((soc_data->nvquirks & NVQUIRK_FORCE_SDHCI_SPEC_200) &&
			(reg == SDHCI_HOST_VERSION))) {
71 72 73 74 75 76 77
		/* Erratum: Version register is invalid in HW. */
		return SDHCI_SPEC_200;
	}

	return readw(host->ioaddr + reg);
}

78 79 80 81
static void tegra_sdhci_writew(struct sdhci_host *host, u16 val, int reg)
{
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);

82 83 84 85 86 87 88 89 90 91 92 93
	switch (reg) {
	case SDHCI_TRANSFER_MODE:
		/*
		 * Postpone this write, we must do it together with a
		 * command write that is down below.
		 */
		pltfm_host->xfer_mode_shadow = val;
		return;
	case SDHCI_COMMAND:
		writel((val << 16) | pltfm_host->xfer_mode_shadow,
			host->ioaddr + SDHCI_TRANSFER_MODE);
		return;
94 95 96 97 98
	}

	writew(val, host->ioaddr + reg);
}

99 100
static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg)
{
101 102 103 104
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_tegra *tegra_host = pltfm_host->priv;
	const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;

105 106 107 108 109 110 111 112 113
	/* Seems like we're getting spurious timeout and crc errors, so
	 * disable signalling of them. In case of real errors software
	 * timers should take care of eventually detecting them.
	 */
	if (unlikely(reg == SDHCI_SIGNAL_ENABLE))
		val &= ~(SDHCI_INT_TIMEOUT|SDHCI_INT_CRC);

	writel(val, host->ioaddr + reg);

114 115
	if (unlikely((soc_data->nvquirks & NVQUIRK_ENABLE_BLOCK_GAP_DET) &&
			(reg == SDHCI_INT_ENABLE))) {
116 117 118 119 120 121 122 123 124 125
		/* Erratum: Must enable block gap interrupt detection */
		u8 gap_ctrl = readb(host->ioaddr + SDHCI_BLOCK_GAP_CONTROL);
		if (val & SDHCI_INT_CARD_INT)
			gap_ctrl |= 0x8;
		else
			gap_ctrl &= ~0x8;
		writeb(gap_ctrl, host->ioaddr + SDHCI_BLOCK_GAP_CONTROL);
	}
}

126
static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host)
127
{
128
	return mmc_gpio_get_ro(host->mmc);
129 130
}

131
static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
132 133 134 135
{
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_tegra *tegra_host = pltfm_host->priv;
	const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
L
Lucas Stach 已提交
136
	u32 misc_ctrl, clk_ctrl;
137

138 139
	sdhci_reset(host, mask);

140 141 142
	if (!(mask & SDHCI_RESET_ALL))
		return;

143
	misc_ctrl = sdhci_readw(host, SDHCI_TEGRA_VENDOR_MISC_CTRL);
144
	/* Erratum: Enable SDHCI spec v3.00 support */
145
	if (soc_data->nvquirks & NVQUIRK_ENABLE_SDHCI_SPEC_300)
146
		misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300;
147 148 149 150 151 152 153 154
	/* Don't advertise UHS modes which aren't supported yet */
	if (soc_data->nvquirks & NVQUIRK_DISABLE_SDR50)
		misc_ctrl &= ~SDHCI_MISC_CTRL_ENABLE_SDR50;
	if (soc_data->nvquirks & NVQUIRK_DISABLE_DDR50)
		misc_ctrl &= ~SDHCI_MISC_CTRL_ENABLE_DDR50;
	if (soc_data->nvquirks & NVQUIRK_DISABLE_SDR104)
		misc_ctrl &= ~SDHCI_MISC_CTRL_ENABLE_SDR104;
	sdhci_writew(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL);
155

L
Lucas Stach 已提交
156 157
	clk_ctrl = sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
	clk_ctrl &= ~SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE;
L
Lucas Stach 已提交
158 159
	if (!(soc_data->nvquirks & NVQUIRK_DISABLE_SDR50))
		clk_ctrl |= SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE;
L
Lucas Stach 已提交
160 161
	sdhci_writel(host, clk_ctrl, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);

162
	tegra_host->ddr_signaling = false;
163 164
}

165
static void tegra_sdhci_set_bus_width(struct sdhci_host *host, int bus_width)
166 167 168 169
{
	u32 ctrl;

	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
170 171
	if ((host->mmc->caps & MMC_CAP_8_BIT_DATA) &&
	    (bus_width == MMC_BUS_WIDTH_8)) {
172 173 174 175 176 177 178 179 180 181 182 183
		ctrl &= ~SDHCI_CTRL_4BITBUS;
		ctrl |= SDHCI_CTRL_8BITBUS;
	} else {
		ctrl &= ~SDHCI_CTRL_8BITBUS;
		if (bus_width == MMC_BUS_WIDTH_4)
			ctrl |= SDHCI_CTRL_4BITBUS;
		else
			ctrl &= ~SDHCI_CTRL_4BITBUS;
	}
	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
}

184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
{
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_tegra *tegra_host = pltfm_host->priv;
	unsigned long host_clk;

	if (!clock)
		return;

	host_clk = tegra_host->ddr_signaling ? clock * 2 : clock;
	clk_set_rate(pltfm_host->clk, host_clk);
	host->max_clk = clk_get_rate(pltfm_host->clk);

	return sdhci_set_clock(host, clock);
}

static void tegra_sdhci_set_uhs_signaling(struct sdhci_host *host,
					  unsigned timing)
{
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_tegra *tegra_host = pltfm_host->priv;

	if (timing == MMC_TIMING_UHS_DDR50)
		tegra_host->ddr_signaling = true;

	return sdhci_set_uhs_signaling(host, timing);
}

static unsigned int tegra_sdhci_get_max_clock(struct sdhci_host *host)
{
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);

	/*
	 * DDR modes require the host to run at double the card frequency, so
	 * the maximum rate we can support is half of the module input clock.
	 */
	return clk_round_rate(pltfm_host->clk, UINT_MAX) / 2;
}

L
Lucas Stach 已提交
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
static void tegra_sdhci_set_tap(struct sdhci_host *host, unsigned int tap)
{
	u32 reg;

	reg = sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
	reg &= ~SDHCI_CLOCK_CTRL_TAP_MASK;
	reg |= tap << SDHCI_CLOCK_CTRL_TAP_SHIFT;
	sdhci_writel(host, reg, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
}

static int tegra_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
{
	unsigned int min, max;

	/*
	 * Start search for minimum tap value at 10, as smaller values are
	 * may wrongly be reported as working but fail at higher speeds,
	 * according to the TRM.
	 */
	min = 10;
	while (min < 255) {
		tegra_sdhci_set_tap(host, min);
		if (!mmc_send_tuning(host->mmc, opcode, NULL))
			break;
		min++;
	}

	/* Find the maximum tap value that still passes. */
	max = min + 1;
	while (max < 255) {
		tegra_sdhci_set_tap(host, max);
		if (mmc_send_tuning(host->mmc, opcode, NULL)) {
			max--;
			break;
		}
		max++;
	}

	/* The TRM states the ideal tap value is at 75% in the passing range. */
	tegra_sdhci_set_tap(host, min + ((max - min) * 3 / 4));

	return mmc_send_tuning(host->mmc, opcode, NULL);
}

267
static const struct sdhci_ops tegra_sdhci_ops = {
268 269 270
	.get_ro     = tegra_sdhci_get_ro,
	.read_w     = tegra_sdhci_readw,
	.write_l    = tegra_sdhci_writel,
271
	.set_clock  = tegra_sdhci_set_clock,
272
	.set_bus_width = tegra_sdhci_set_bus_width,
273
	.reset      = tegra_sdhci_reset,
L
Lucas Stach 已提交
274
	.platform_execute_tuning = tegra_sdhci_execute_tuning,
275 276
	.set_uhs_signaling = tegra_sdhci_set_uhs_signaling,
	.get_max_clock = tegra_sdhci_get_max_clock,
277 278
};

279
static const struct sdhci_pltfm_data sdhci_tegra20_pdata = {
280 281 282
	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
		  SDHCI_QUIRK_NO_HISPD_BIT |
283 284
		  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
		  SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
285 286 287
	.ops  = &tegra_sdhci_ops,
};

T
Thierry Reding 已提交
288
static const struct sdhci_tegra_soc_data soc_data_tegra20 = {
289 290 291 292 293
	.pdata = &sdhci_tegra20_pdata,
	.nvquirks = NVQUIRK_FORCE_SDHCI_SPEC_200 |
		    NVQUIRK_ENABLE_BLOCK_GAP_DET,
};

294
static const struct sdhci_pltfm_data sdhci_tegra30_pdata = {
295
	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
296
		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
297 298
		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
		  SDHCI_QUIRK_NO_HISPD_BIT |
299 300
		  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
		  SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
301
	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
302 303
	.ops  = &tegra_sdhci_ops,
};
304

T
Thierry Reding 已提交
305
static const struct sdhci_tegra_soc_data soc_data_tegra30 = {
306
	.pdata = &sdhci_tegra30_pdata,
307 308 309
	.nvquirks = NVQUIRK_ENABLE_SDHCI_SPEC_300 |
		    NVQUIRK_DISABLE_SDR50 |
		    NVQUIRK_DISABLE_SDR104,
310 311
};

312 313 314 315 316
static const struct sdhci_ops tegra114_sdhci_ops = {
	.get_ro     = tegra_sdhci_get_ro,
	.read_w     = tegra_sdhci_readw,
	.write_w    = tegra_sdhci_writew,
	.write_l    = tegra_sdhci_writel,
317
	.set_clock  = tegra_sdhci_set_clock,
318 319
	.set_bus_width = tegra_sdhci_set_bus_width,
	.reset      = tegra_sdhci_reset,
L
Lucas Stach 已提交
320
	.platform_execute_tuning = tegra_sdhci_execute_tuning,
321 322
	.set_uhs_signaling = tegra_sdhci_set_uhs_signaling,
	.get_max_clock = tegra_sdhci_get_max_clock,
323 324
};

325
static const struct sdhci_pltfm_data sdhci_tegra114_pdata = {
326 327 328 329
	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
		  SDHCI_QUIRK_NO_HISPD_BIT |
330 331
		  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
		  SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
332
	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
333
	.ops  = &tegra114_sdhci_ops,
334 335
};

T
Thierry Reding 已提交
336
static const struct sdhci_tegra_soc_data soc_data_tegra114 = {
337
	.pdata = &sdhci_tegra114_pdata,
338 339
	.nvquirks = NVQUIRK_DISABLE_SDR50 |
		    NVQUIRK_DISABLE_DDR50 |
340
		    NVQUIRK_DISABLE_SDR104,
341 342
};

T
Thierry Reding 已提交
343 344 345 346 347
static const struct sdhci_pltfm_data sdhci_tegra210_pdata = {
	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
		  SDHCI_QUIRK_NO_HISPD_BIT |
348 349 350
		  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
		  SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
T
Thierry Reding 已提交
351 352 353 354 355 356 357 358 359 360
	.ops  = &tegra114_sdhci_ops,
};

static const struct sdhci_tegra_soc_data soc_data_tegra210 = {
	.pdata = &sdhci_tegra210_pdata,
	.nvquirks = NVQUIRK_DISABLE_SDR50 |
		    NVQUIRK_DISABLE_DDR50 |
		    NVQUIRK_DISABLE_SDR104,
};

B
Bill Pemberton 已提交
361
static const struct of_device_id sdhci_tegra_dt_match[] = {
T
Thierry Reding 已提交
362
	{ .compatible = "nvidia,tegra210-sdhci", .data = &soc_data_tegra210 },
363
	{ .compatible = "nvidia,tegra124-sdhci", .data = &soc_data_tegra114 },
364
	{ .compatible = "nvidia,tegra114-sdhci", .data = &soc_data_tegra114 },
365 366
	{ .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 },
	{ .compatible = "nvidia,tegra20-sdhci", .data = &soc_data_tegra20 },
367 368
	{}
};
369
MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match);
370

B
Bill Pemberton 已提交
371
static int sdhci_tegra_probe(struct platform_device *pdev)
372
{
373 374 375
	const struct of_device_id *match;
	const struct sdhci_tegra_soc_data *soc_data;
	struct sdhci_host *host;
376
	struct sdhci_pltfm_host *pltfm_host;
377
	struct sdhci_tegra *tegra_host;
378 379 380
	struct clk *clk;
	int rc;

381
	match = of_match_device(sdhci_tegra_dt_match, &pdev->dev);
382 383 384
	if (!match)
		return -EINVAL;
	soc_data = match->data;
385

386
	host = sdhci_pltfm_init(pdev, soc_data->pdata, 0);
387 388 389 390
	if (IS_ERR(host))
		return PTR_ERR(host);
	pltfm_host = sdhci_priv(host);

391 392 393 394
	tegra_host = devm_kzalloc(&pdev->dev, sizeof(*tegra_host), GFP_KERNEL);
	if (!tegra_host) {
		dev_err(mmc_dev(host->mmc), "failed to allocate tegra_host\n");
		rc = -ENOMEM;
395
		goto err_alloc_tegra_host;
396
	}
397
	tegra_host->ddr_signaling = false;
398 399
	tegra_host->soc_data = soc_data;
	pltfm_host->priv = tegra_host;
400

401
	rc = mmc_of_parse(host->mmc);
402 403
	if (rc)
		goto err_parse_dt;
404

L
Lucas Stach 已提交
405 406 407
	if (!(tegra_host->soc_data->nvquirks & NVQUIRK_DISABLE_DDR50))
		host->mmc->caps |= MMC_CAP_1_8V_DDR;

408 409 410 411 412
	tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power",
							 GPIOD_OUT_HIGH);
	if (IS_ERR(tegra_host->power_gpio)) {
		rc = PTR_ERR(tegra_host->power_gpio);
		goto err_power_req;
413 414
	}

415
	clk = devm_clk_get(mmc_dev(host->mmc), NULL);
416 417 418
	if (IS_ERR(clk)) {
		dev_err(mmc_dev(host->mmc), "clk err\n");
		rc = PTR_ERR(clk);
419
		goto err_clk_get;
420
	}
421
	clk_prepare_enable(clk);
422 423
	pltfm_host->clk = clk;

424 425 426 427
	rc = sdhci_add_host(host);
	if (rc)
		goto err_add_host;

428 429
	return 0;

430
err_add_host:
431
	clk_disable_unprepare(pltfm_host->clk);
432 433
err_clk_get:
err_power_req:
434
err_parse_dt:
435
err_alloc_tegra_host:
436
	sdhci_pltfm_free(pdev);
437 438 439
	return rc;
}

440 441 442
static struct platform_driver sdhci_tegra_driver = {
	.driver		= {
		.name	= "sdhci-tegra",
443
		.of_match_table = sdhci_tegra_dt_match,
444
		.pm	= SDHCI_PLTFM_PMOPS,
445 446
	},
	.probe		= sdhci_tegra_probe,
447
	.remove		= sdhci_pltfm_unregister,
448 449
};

450
module_platform_driver(sdhci_tegra_driver);
451 452

MODULE_DESCRIPTION("SDHCI driver for Tegra");
453
MODULE_AUTHOR("Google, Inc.");
454
MODULE_LICENSE("GPL v2");