Linux Audio

Check our new training course

Linux BSP development engineering services

Need help to port Linux and bootloaders to your hardware?
Loading...
v3.15
  1/*
  2 * Copyright (C) 2010 Google, Inc.
  3 *
  4 * This software is licensed under the terms of the GNU General Public
  5 * License version 2, as published by the Free Software Foundation, and
  6 * may be copied, distributed, and modified under those terms.
  7 *
  8 * This program is distributed in the hope that it will be useful,
  9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 11 * GNU General Public License for more details.
 12 *
 13 */
 14
 
 15#include <linux/err.h>
 16#include <linux/module.h>
 17#include <linux/init.h>
 18#include <linux/platform_device.h>
 19#include <linux/clk.h>
 20#include <linux/io.h>
 21#include <linux/of.h>
 22#include <linux/of_device.h>
 23#include <linux/of_gpio.h>
 24#include <linux/gpio.h>
 25#include <linux/mmc/card.h>
 26#include <linux/mmc/host.h>
 
 27#include <linux/mmc/slot-gpio.h>
 28
 29#include <asm/gpio.h>
 30
 31#include "sdhci-pltfm.h"
 32
 33/* Tegra SDHOST controller vendor register definitions */
 
 
 
 
 
 
 
 34#define SDHCI_TEGRA_VENDOR_MISC_CTRL		0x120
 
 
 35#define SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300	0x20
 
 
 
 
 
 36
 37#define NVQUIRK_FORCE_SDHCI_SPEC_200	BIT(0)
 38#define NVQUIRK_ENABLE_BLOCK_GAP_DET	BIT(1)
 39#define NVQUIRK_ENABLE_SDHCI_SPEC_300	BIT(2)
 
 
 
 
 40
 41struct sdhci_tegra_soc_data {
 42	const struct sdhci_pltfm_data *pdata;
 43	u32 nvquirks;
 44};
 45
 46struct sdhci_tegra {
 47	const struct sdhci_tegra_soc_data *soc_data;
 48	int power_gpio;
 
 
 49};
 50
 51static u32 tegra_sdhci_readl(struct sdhci_host *host, int reg)
 52{
 53	u32 val;
 54
 55	if (unlikely(reg == SDHCI_PRESENT_STATE)) {
 56		/* Use wp_gpio here instead? */
 57		val = readl(host->ioaddr + reg);
 58		return val | SDHCI_WRITE_PROTECT;
 59	}
 60
 61	return readl(host->ioaddr + reg);
 62}
 63
 64static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
 65{
 66	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 67	struct sdhci_tegra *tegra_host = pltfm_host->priv;
 68	const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
 69
 70	if (unlikely((soc_data->nvquirks & NVQUIRK_FORCE_SDHCI_SPEC_200) &&
 71			(reg == SDHCI_HOST_VERSION))) {
 72		/* Erratum: Version register is invalid in HW. */
 73		return SDHCI_SPEC_200;
 74	}
 75
 76	return readw(host->ioaddr + reg);
 77}
 78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 79static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg)
 80{
 81	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 82	struct sdhci_tegra *tegra_host = pltfm_host->priv;
 83	const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
 84
 85	/* Seems like we're getting spurious timeout and crc errors, so
 86	 * disable signalling of them. In case of real errors software
 87	 * timers should take care of eventually detecting them.
 88	 */
 89	if (unlikely(reg == SDHCI_SIGNAL_ENABLE))
 90		val &= ~(SDHCI_INT_TIMEOUT|SDHCI_INT_CRC);
 91
 92	writel(val, host->ioaddr + reg);
 93
 94	if (unlikely((soc_data->nvquirks & NVQUIRK_ENABLE_BLOCK_GAP_DET) &&
 95			(reg == SDHCI_INT_ENABLE))) {
 96		/* Erratum: Must enable block gap interrupt detection */
 97		u8 gap_ctrl = readb(host->ioaddr + SDHCI_BLOCK_GAP_CONTROL);
 98		if (val & SDHCI_INT_CARD_INT)
 99			gap_ctrl |= 0x8;
100		else
101			gap_ctrl &= ~0x8;
102		writeb(gap_ctrl, host->ioaddr + SDHCI_BLOCK_GAP_CONTROL);
103	}
104}
105
106static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host)
107{
108	return mmc_gpio_get_ro(host->mmc);
109}
110
111static void tegra_sdhci_reset_exit(struct sdhci_host *host, u8 mask)
112{
113	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
114	struct sdhci_tegra *tegra_host = pltfm_host->priv;
115	const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
 
 
 
116
117	if (!(mask & SDHCI_RESET_ALL))
118		return;
119
120	/* Erratum: Enable SDHCI spec v3.00 support */
121	if (soc_data->nvquirks & NVQUIRK_ENABLE_SDHCI_SPEC_300) {
122		u32 misc_ctrl;
123
124		misc_ctrl = sdhci_readb(host, SDHCI_TEGRA_VENDOR_MISC_CTRL);
125		misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300;
126		sdhci_writeb(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127	}
 
 
 
 
 
 
 
 
128}
129
130static int tegra_sdhci_buswidth(struct sdhci_host *host, int bus_width)
131{
132	u32 ctrl;
133
134	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
135	if ((host->mmc->caps & MMC_CAP_8_BIT_DATA) &&
136	    (bus_width == MMC_BUS_WIDTH_8)) {
137		ctrl &= ~SDHCI_CTRL_4BITBUS;
138		ctrl |= SDHCI_CTRL_8BITBUS;
139	} else {
140		ctrl &= ~SDHCI_CTRL_8BITBUS;
141		if (bus_width == MMC_BUS_WIDTH_4)
142			ctrl |= SDHCI_CTRL_4BITBUS;
143		else
144			ctrl &= ~SDHCI_CTRL_4BITBUS;
145	}
146	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
147	return 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148}
149
150static const struct sdhci_ops tegra_sdhci_ops = {
151	.get_ro     = tegra_sdhci_get_ro,
152	.read_l     = tegra_sdhci_readl,
153	.read_w     = tegra_sdhci_readw,
154	.write_l    = tegra_sdhci_writel,
155	.platform_bus_width = tegra_sdhci_buswidth,
156	.platform_reset_exit = tegra_sdhci_reset_exit,
 
 
 
 
 
157};
158
159static const struct sdhci_pltfm_data sdhci_tegra20_pdata = {
160	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
161		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
162		  SDHCI_QUIRK_NO_HISPD_BIT |
163		  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC,
 
164	.ops  = &tegra_sdhci_ops,
165};
166
167static struct sdhci_tegra_soc_data soc_data_tegra20 = {
168	.pdata = &sdhci_tegra20_pdata,
169	.nvquirks = NVQUIRK_FORCE_SDHCI_SPEC_200 |
170		    NVQUIRK_ENABLE_BLOCK_GAP_DET,
171};
172
173static const struct sdhci_pltfm_data sdhci_tegra30_pdata = {
174	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
175		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
176		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
177		  SDHCI_QUIRK_NO_HISPD_BIT |
178		  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC,
 
 
179	.ops  = &tegra_sdhci_ops,
180};
181
182static struct sdhci_tegra_soc_data soc_data_tegra30 = {
183	.pdata = &sdhci_tegra30_pdata,
184	.nvquirks = NVQUIRK_ENABLE_SDHCI_SPEC_300,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185};
186
187static const struct sdhci_pltfm_data sdhci_tegra114_pdata = {
188	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
189		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
190		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
191		  SDHCI_QUIRK_NO_HISPD_BIT |
192		  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC,
193	.ops  = &tegra_sdhci_ops,
 
 
194};
195
196static struct sdhci_tegra_soc_data soc_data_tegra114 = {
197	.pdata = &sdhci_tegra114_pdata,
198};
199
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200static const struct of_device_id sdhci_tegra_dt_match[] = {
201	{ .compatible = "nvidia,tegra124-sdhci", .data = &soc_data_tegra114 },
 
202	{ .compatible = "nvidia,tegra114-sdhci", .data = &soc_data_tegra114 },
203	{ .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 },
204	{ .compatible = "nvidia,tegra20-sdhci", .data = &soc_data_tegra20 },
205	{}
206};
207MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match);
208
209static int sdhci_tegra_parse_dt(struct device *dev)
210{
211	struct device_node *np = dev->of_node;
212	struct sdhci_host *host = dev_get_drvdata(dev);
213	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
214	struct sdhci_tegra *tegra_host = pltfm_host->priv;
215
216	tegra_host->power_gpio = of_get_named_gpio(np, "power-gpios", 0);
217	return mmc_of_parse(host->mmc);
218}
219
220static int sdhci_tegra_probe(struct platform_device *pdev)
221{
222	const struct of_device_id *match;
223	const struct sdhci_tegra_soc_data *soc_data;
224	struct sdhci_host *host;
225	struct sdhci_pltfm_host *pltfm_host;
226	struct sdhci_tegra *tegra_host;
227	struct clk *clk;
228	int rc;
229
230	match = of_match_device(sdhci_tegra_dt_match, &pdev->dev);
231	if (!match)
232		return -EINVAL;
233	soc_data = match->data;
234
235	host = sdhci_pltfm_init(pdev, soc_data->pdata, 0);
236	if (IS_ERR(host))
237		return PTR_ERR(host);
238	pltfm_host = sdhci_priv(host);
239
240	tegra_host = devm_kzalloc(&pdev->dev, sizeof(*tegra_host), GFP_KERNEL);
241	if (!tegra_host) {
242		dev_err(mmc_dev(host->mmc), "failed to allocate tegra_host\n");
243		rc = -ENOMEM;
244		goto err_alloc_tegra_host;
245	}
246	tegra_host->soc_data = soc_data;
247	pltfm_host->priv = tegra_host;
248
249	rc = sdhci_tegra_parse_dt(&pdev->dev);
250	if (rc)
251		goto err_parse_dt;
252
253	if (gpio_is_valid(tegra_host->power_gpio)) {
254		rc = gpio_request(tegra_host->power_gpio, "sdhci_power");
255		if (rc) {
256			dev_err(mmc_dev(host->mmc),
257				"failed to allocate power gpio\n");
258			goto err_power_req;
259		}
260		gpio_direction_output(tegra_host->power_gpio, 1);
261	}
262
263	clk = clk_get(mmc_dev(host->mmc), NULL);
264	if (IS_ERR(clk)) {
265		dev_err(mmc_dev(host->mmc), "clk err\n");
266		rc = PTR_ERR(clk);
267		goto err_clk_get;
268	}
269	clk_prepare_enable(clk);
270	pltfm_host->clk = clk;
271
272	rc = sdhci_add_host(host);
273	if (rc)
274		goto err_add_host;
275
276	return 0;
277
278err_add_host:
279	clk_disable_unprepare(pltfm_host->clk);
280	clk_put(pltfm_host->clk);
281err_clk_get:
282	if (gpio_is_valid(tegra_host->power_gpio))
283		gpio_free(tegra_host->power_gpio);
284err_power_req:
285err_parse_dt:
286err_alloc_tegra_host:
287	sdhci_pltfm_free(pdev);
288	return rc;
289}
290
291static int sdhci_tegra_remove(struct platform_device *pdev)
292{
293	struct sdhci_host *host = platform_get_drvdata(pdev);
294	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
295	struct sdhci_tegra *tegra_host = pltfm_host->priv;
296	int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
297
298	sdhci_remove_host(host, dead);
299
300	if (gpio_is_valid(tegra_host->power_gpio))
301		gpio_free(tegra_host->power_gpio);
302
303	clk_disable_unprepare(pltfm_host->clk);
304	clk_put(pltfm_host->clk);
305
306	sdhci_pltfm_free(pdev);
307
308	return 0;
309}
310
311static struct platform_driver sdhci_tegra_driver = {
312	.driver		= {
313		.name	= "sdhci-tegra",
314		.owner	= THIS_MODULE,
315		.of_match_table = sdhci_tegra_dt_match,
316		.pm	= SDHCI_PLTFM_PMOPS,
317	},
318	.probe		= sdhci_tegra_probe,
319	.remove		= sdhci_tegra_remove,
320};
321
322module_platform_driver(sdhci_tegra_driver);
323
324MODULE_DESCRIPTION("SDHCI driver for Tegra");
325MODULE_AUTHOR("Google, Inc.");
326MODULE_LICENSE("GPL v2");
v4.10.11
  1/*
  2 * Copyright (C) 2010 Google, Inc.
  3 *
  4 * This software is licensed under the terms of the GNU General Public
  5 * License version 2, as published by the Free Software Foundation, and
  6 * may be copied, distributed, and modified under those terms.
  7 *
  8 * This program is distributed in the hope that it will be useful,
  9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 11 * GNU General Public License for more details.
 12 *
 13 */
 14
 15#include <linux/delay.h>
 16#include <linux/err.h>
 17#include <linux/module.h>
 18#include <linux/init.h>
 19#include <linux/platform_device.h>
 20#include <linux/clk.h>
 21#include <linux/io.h>
 22#include <linux/of.h>
 23#include <linux/of_device.h>
 
 
 24#include <linux/mmc/card.h>
 25#include <linux/mmc/host.h>
 26#include <linux/mmc/mmc.h>
 27#include <linux/mmc/slot-gpio.h>
 28#include <linux/gpio/consumer.h>
 
 29
 30#include "sdhci-pltfm.h"
 31
 32/* Tegra SDHOST controller vendor register definitions */
 33#define SDHCI_TEGRA_VENDOR_CLOCK_CTRL			0x100
 34#define SDHCI_CLOCK_CTRL_TAP_MASK			0x00ff0000
 35#define SDHCI_CLOCK_CTRL_TAP_SHIFT			16
 36#define SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE		BIT(5)
 37#define SDHCI_CLOCK_CTRL_PADPIPE_CLKEN_OVERRIDE		BIT(3)
 38#define SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE	BIT(2)
 39
 40#define SDHCI_TEGRA_VENDOR_MISC_CTRL		0x120
 41#define SDHCI_MISC_CTRL_ENABLE_SDR104		0x8
 42#define SDHCI_MISC_CTRL_ENABLE_SDR50		0x10
 43#define SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300	0x20
 44#define SDHCI_MISC_CTRL_ENABLE_DDR50		0x200
 45
 46#define SDHCI_TEGRA_AUTO_CAL_CONFIG		0x1e4
 47#define SDHCI_AUTO_CAL_START			BIT(31)
 48#define SDHCI_AUTO_CAL_ENABLE			BIT(29)
 49
 50#define NVQUIRK_FORCE_SDHCI_SPEC_200	BIT(0)
 51#define NVQUIRK_ENABLE_BLOCK_GAP_DET	BIT(1)
 52#define NVQUIRK_ENABLE_SDHCI_SPEC_300	BIT(2)
 53#define NVQUIRK_ENABLE_SDR50		BIT(3)
 54#define NVQUIRK_ENABLE_SDR104		BIT(4)
 55#define NVQUIRK_ENABLE_DDR50		BIT(5)
 56#define NVQUIRK_HAS_PADCALIB		BIT(6)
 57
 58struct sdhci_tegra_soc_data {
 59	const struct sdhci_pltfm_data *pdata;
 60	u32 nvquirks;
 61};
 62
 63struct sdhci_tegra {
 64	const struct sdhci_tegra_soc_data *soc_data;
 65	struct gpio_desc *power_gpio;
 66	bool ddr_signaling;
 67	bool pad_calib_required;
 68};
 69
 
 
 
 
 
 
 
 
 
 
 
 
 
 70static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
 71{
 72	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 73	struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
 74	const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
 75
 76	if (unlikely((soc_data->nvquirks & NVQUIRK_FORCE_SDHCI_SPEC_200) &&
 77			(reg == SDHCI_HOST_VERSION))) {
 78		/* Erratum: Version register is invalid in HW. */
 79		return SDHCI_SPEC_200;
 80	}
 81
 82	return readw(host->ioaddr + reg);
 83}
 84
 85static void tegra_sdhci_writew(struct sdhci_host *host, u16 val, int reg)
 86{
 87	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 88
 89	switch (reg) {
 90	case SDHCI_TRANSFER_MODE:
 91		/*
 92		 * Postpone this write, we must do it together with a
 93		 * command write that is down below.
 94		 */
 95		pltfm_host->xfer_mode_shadow = val;
 96		return;
 97	case SDHCI_COMMAND:
 98		writel((val << 16) | pltfm_host->xfer_mode_shadow,
 99			host->ioaddr + SDHCI_TRANSFER_MODE);
100		return;
101	}
102
103	writew(val, host->ioaddr + reg);
104}
105
106static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg)
107{
108	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
109	struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
110	const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
111
112	/* Seems like we're getting spurious timeout and crc errors, so
113	 * disable signalling of them. In case of real errors software
114	 * timers should take care of eventually detecting them.
115	 */
116	if (unlikely(reg == SDHCI_SIGNAL_ENABLE))
117		val &= ~(SDHCI_INT_TIMEOUT|SDHCI_INT_CRC);
118
119	writel(val, host->ioaddr + reg);
120
121	if (unlikely((soc_data->nvquirks & NVQUIRK_ENABLE_BLOCK_GAP_DET) &&
122			(reg == SDHCI_INT_ENABLE))) {
123		/* Erratum: Must enable block gap interrupt detection */
124		u8 gap_ctrl = readb(host->ioaddr + SDHCI_BLOCK_GAP_CONTROL);
125		if (val & SDHCI_INT_CARD_INT)
126			gap_ctrl |= 0x8;
127		else
128			gap_ctrl &= ~0x8;
129		writeb(gap_ctrl, host->ioaddr + SDHCI_BLOCK_GAP_CONTROL);
130	}
131}
132
133static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host)
134{
135	return mmc_gpio_get_ro(host->mmc);
136}
137
138static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
139{
140	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
141	struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
142	const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
143	u32 misc_ctrl, clk_ctrl;
144
145	sdhci_reset(host, mask);
146
147	if (!(mask & SDHCI_RESET_ALL))
148		return;
149
150	misc_ctrl = sdhci_readl(host, SDHCI_TEGRA_VENDOR_MISC_CTRL);
151	clk_ctrl = sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
152
153	misc_ctrl &= ~(SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300 |
154		       SDHCI_MISC_CTRL_ENABLE_SDR50 |
155		       SDHCI_MISC_CTRL_ENABLE_DDR50 |
156		       SDHCI_MISC_CTRL_ENABLE_SDR104);
157
158	clk_ctrl &= ~SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE;
159
160	/*
161	 * If the board does not define a regulator for the SDHCI
162	 * IO voltage, then don't advertise support for UHS modes
163	 * even if the device supports it because the IO voltage
164	 * cannot be configured.
165	 */
166	if (!IS_ERR(host->mmc->supply.vqmmc)) {
167		/* Erratum: Enable SDHCI spec v3.00 support */
168		if (soc_data->nvquirks & NVQUIRK_ENABLE_SDHCI_SPEC_300)
169			misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300;
170		/* Advertise UHS modes as supported by host */
171		if (soc_data->nvquirks & NVQUIRK_ENABLE_SDR50)
172			misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDR50;
173		if (soc_data->nvquirks & NVQUIRK_ENABLE_DDR50)
174			misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_DDR50;
175		if (soc_data->nvquirks & NVQUIRK_ENABLE_SDR104)
176			misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDR104;
177		if (soc_data->nvquirks & SDHCI_MISC_CTRL_ENABLE_SDR50)
178			clk_ctrl |= SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE;
179	}
180
181	sdhci_writel(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL);
182	sdhci_writel(host, clk_ctrl, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
183
184	if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB)
185		tegra_host->pad_calib_required = true;
186
187	tegra_host->ddr_signaling = false;
188}
189
190static void tegra_sdhci_set_bus_width(struct sdhci_host *host, int bus_width)
191{
192	u32 ctrl;
193
194	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
195	if ((host->mmc->caps & MMC_CAP_8_BIT_DATA) &&
196	    (bus_width == MMC_BUS_WIDTH_8)) {
197		ctrl &= ~SDHCI_CTRL_4BITBUS;
198		ctrl |= SDHCI_CTRL_8BITBUS;
199	} else {
200		ctrl &= ~SDHCI_CTRL_8BITBUS;
201		if (bus_width == MMC_BUS_WIDTH_4)
202			ctrl |= SDHCI_CTRL_4BITBUS;
203		else
204			ctrl &= ~SDHCI_CTRL_4BITBUS;
205	}
206	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
207}
208
209static void tegra_sdhci_pad_autocalib(struct sdhci_host *host)
210{
211	u32 val;
212
213	mdelay(1);
214
215	val = sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG);
216	val |= SDHCI_AUTO_CAL_ENABLE | SDHCI_AUTO_CAL_START;
217	sdhci_writel(host,val, SDHCI_TEGRA_AUTO_CAL_CONFIG);
218}
219
220static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
221{
222	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
223	struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
224	unsigned long host_clk;
225
226	if (!clock)
227		return sdhci_set_clock(host, clock);
228
229	host_clk = tegra_host->ddr_signaling ? clock * 2 : clock;
230	clk_set_rate(pltfm_host->clk, host_clk);
231	host->max_clk = clk_get_rate(pltfm_host->clk);
232
233	sdhci_set_clock(host, clock);
234
235	if (tegra_host->pad_calib_required) {
236		tegra_sdhci_pad_autocalib(host);
237		tegra_host->pad_calib_required = false;
238	}
239}
240
241static void tegra_sdhci_set_uhs_signaling(struct sdhci_host *host,
242					  unsigned timing)
243{
244	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
245	struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
246
247	if (timing == MMC_TIMING_UHS_DDR50)
248		tegra_host->ddr_signaling = true;
249
250	return sdhci_set_uhs_signaling(host, timing);
251}
252
253static unsigned int tegra_sdhci_get_max_clock(struct sdhci_host *host)
254{
255	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
256
257	/*
258	 * DDR modes require the host to run at double the card frequency, so
259	 * the maximum rate we can support is half of the module input clock.
260	 */
261	return clk_round_rate(pltfm_host->clk, UINT_MAX) / 2;
262}
263
264static void tegra_sdhci_set_tap(struct sdhci_host *host, unsigned int tap)
265{
266	u32 reg;
267
268	reg = sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
269	reg &= ~SDHCI_CLOCK_CTRL_TAP_MASK;
270	reg |= tap << SDHCI_CLOCK_CTRL_TAP_SHIFT;
271	sdhci_writel(host, reg, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
272}
273
274static int tegra_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
275{
276	unsigned int min, max;
277
278	/*
279	 * Start search for minimum tap value at 10, as smaller values are
280	 * may wrongly be reported as working but fail at higher speeds,
281	 * according to the TRM.
282	 */
283	min = 10;
284	while (min < 255) {
285		tegra_sdhci_set_tap(host, min);
286		if (!mmc_send_tuning(host->mmc, opcode, NULL))
287			break;
288		min++;
289	}
290
291	/* Find the maximum tap value that still passes. */
292	max = min + 1;
293	while (max < 255) {
294		tegra_sdhci_set_tap(host, max);
295		if (mmc_send_tuning(host->mmc, opcode, NULL)) {
296			max--;
297			break;
298		}
299		max++;
300	}
301
302	/* The TRM states the ideal tap value is at 75% in the passing range. */
303	tegra_sdhci_set_tap(host, min + ((max - min) * 3 / 4));
304
305	return mmc_send_tuning(host->mmc, opcode, NULL);
306}
307
308static void tegra_sdhci_voltage_switch(struct sdhci_host *host)
309{
310	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
311	struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
312	const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
313
314	if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB)
315		tegra_host->pad_calib_required = true;
316}
317
318static const struct sdhci_ops tegra_sdhci_ops = {
319	.get_ro     = tegra_sdhci_get_ro,
 
320	.read_w     = tegra_sdhci_readw,
321	.write_l    = tegra_sdhci_writel,
322	.set_clock  = tegra_sdhci_set_clock,
323	.set_bus_width = tegra_sdhci_set_bus_width,
324	.reset      = tegra_sdhci_reset,
325	.platform_execute_tuning = tegra_sdhci_execute_tuning,
326	.set_uhs_signaling = tegra_sdhci_set_uhs_signaling,
327	.voltage_switch = tegra_sdhci_voltage_switch,
328	.get_max_clock = tegra_sdhci_get_max_clock,
329};
330
331static const struct sdhci_pltfm_data sdhci_tegra20_pdata = {
332	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
333		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
334		  SDHCI_QUIRK_NO_HISPD_BIT |
335		  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
336		  SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
337	.ops  = &tegra_sdhci_ops,
338};
339
340static const struct sdhci_tegra_soc_data soc_data_tegra20 = {
341	.pdata = &sdhci_tegra20_pdata,
342	.nvquirks = NVQUIRK_FORCE_SDHCI_SPEC_200 |
343		    NVQUIRK_ENABLE_BLOCK_GAP_DET,
344};
345
346static const struct sdhci_pltfm_data sdhci_tegra30_pdata = {
347	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
348		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
349		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
350		  SDHCI_QUIRK_NO_HISPD_BIT |
351		  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
352		  SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
353	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
354	.ops  = &tegra_sdhci_ops,
355};
356
357static const struct sdhci_tegra_soc_data soc_data_tegra30 = {
358	.pdata = &sdhci_tegra30_pdata,
359	.nvquirks = NVQUIRK_ENABLE_SDHCI_SPEC_300 |
360		    NVQUIRK_ENABLE_SDR50 |
361		    NVQUIRK_ENABLE_SDR104 |
362		    NVQUIRK_HAS_PADCALIB,
363};
364
365static const struct sdhci_ops tegra114_sdhci_ops = {
366	.get_ro     = tegra_sdhci_get_ro,
367	.read_w     = tegra_sdhci_readw,
368	.write_w    = tegra_sdhci_writew,
369	.write_l    = tegra_sdhci_writel,
370	.set_clock  = tegra_sdhci_set_clock,
371	.set_bus_width = tegra_sdhci_set_bus_width,
372	.reset      = tegra_sdhci_reset,
373	.platform_execute_tuning = tegra_sdhci_execute_tuning,
374	.set_uhs_signaling = tegra_sdhci_set_uhs_signaling,
375	.voltage_switch = tegra_sdhci_voltage_switch,
376	.get_max_clock = tegra_sdhci_get_max_clock,
377};
378
379static const struct sdhci_pltfm_data sdhci_tegra114_pdata = {
380	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
381		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
382		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
383		  SDHCI_QUIRK_NO_HISPD_BIT |
384		  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
385		  SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
386	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
387	.ops  = &tegra114_sdhci_ops,
388};
389
390static const struct sdhci_tegra_soc_data soc_data_tegra114 = {
391	.pdata = &sdhci_tegra114_pdata,
392};
393
394static const struct sdhci_pltfm_data sdhci_tegra124_pdata = {
395	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
396		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
397		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
398		  SDHCI_QUIRK_NO_HISPD_BIT |
399		  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
400		  SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
401	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
402		   /*
403		    * The TRM states that the SD/MMC controller found on
404		    * Tegra124 can address 34 bits (the maximum supported by
405		    * the Tegra memory controller), but tests show that DMA
406		    * to or from above 4 GiB doesn't work. This is possibly
407		    * caused by missing programming, though it's not obvious
408		    * what sequence is required. Mark 64-bit DMA broken for
409		    * now to fix this for existing users (e.g. Nyan boards).
410		    */
411		   SDHCI_QUIRK2_BROKEN_64_BIT_DMA,
412	.ops  = &tegra114_sdhci_ops,
413};
414
415static const struct sdhci_tegra_soc_data soc_data_tegra124 = {
416	.pdata = &sdhci_tegra124_pdata,
417};
418
419static const struct sdhci_pltfm_data sdhci_tegra210_pdata = {
420	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
421		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
422		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
423		  SDHCI_QUIRK_NO_HISPD_BIT |
424		  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
425		  SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
426	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
427	.ops  = &tegra114_sdhci_ops,
428};
429
430static const struct sdhci_tegra_soc_data soc_data_tegra210 = {
431	.pdata = &sdhci_tegra210_pdata,
432};
433
434static const struct of_device_id sdhci_tegra_dt_match[] = {
435	{ .compatible = "nvidia,tegra210-sdhci", .data = &soc_data_tegra210 },
436	{ .compatible = "nvidia,tegra124-sdhci", .data = &soc_data_tegra124 },
437	{ .compatible = "nvidia,tegra114-sdhci", .data = &soc_data_tegra114 },
438	{ .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 },
439	{ .compatible = "nvidia,tegra20-sdhci", .data = &soc_data_tegra20 },
440	{}
441};
442MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match);
443
 
 
 
 
 
 
 
 
 
 
 
444static int sdhci_tegra_probe(struct platform_device *pdev)
445{
446	const struct of_device_id *match;
447	const struct sdhci_tegra_soc_data *soc_data;
448	struct sdhci_host *host;
449	struct sdhci_pltfm_host *pltfm_host;
450	struct sdhci_tegra *tegra_host;
451	struct clk *clk;
452	int rc;
453
454	match = of_match_device(sdhci_tegra_dt_match, &pdev->dev);
455	if (!match)
456		return -EINVAL;
457	soc_data = match->data;
458
459	host = sdhci_pltfm_init(pdev, soc_data->pdata, sizeof(*tegra_host));
460	if (IS_ERR(host))
461		return PTR_ERR(host);
462	pltfm_host = sdhci_priv(host);
463
464	tegra_host = sdhci_pltfm_priv(pltfm_host);
465	tegra_host->ddr_signaling = false;
466	tegra_host->pad_calib_required = false;
 
 
 
467	tegra_host->soc_data = soc_data;
 
468
469	rc = mmc_of_parse(host->mmc);
470	if (rc)
471		goto err_parse_dt;
472
473	if (tegra_host->soc_data->nvquirks & NVQUIRK_ENABLE_DDR50)
474		host->mmc->caps |= MMC_CAP_1_8V_DDR;
475
476	tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power",
477							 GPIOD_OUT_HIGH);
478	if (IS_ERR(tegra_host->power_gpio)) {
479		rc = PTR_ERR(tegra_host->power_gpio);
480		goto err_power_req;
481	}
482
483	clk = devm_clk_get(mmc_dev(host->mmc), NULL);
484	if (IS_ERR(clk)) {
485		dev_err(mmc_dev(host->mmc), "clk err\n");
486		rc = PTR_ERR(clk);
487		goto err_clk_get;
488	}
489	clk_prepare_enable(clk);
490	pltfm_host->clk = clk;
491
492	rc = sdhci_add_host(host);
493	if (rc)
494		goto err_add_host;
495
496	return 0;
497
498err_add_host:
499	clk_disable_unprepare(pltfm_host->clk);
 
500err_clk_get:
 
 
501err_power_req:
502err_parse_dt:
 
503	sdhci_pltfm_free(pdev);
504	return rc;
505}
506
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
507static struct platform_driver sdhci_tegra_driver = {
508	.driver		= {
509		.name	= "sdhci-tegra",
 
510		.of_match_table = sdhci_tegra_dt_match,
511		.pm	= &sdhci_pltfm_pmops,
512	},
513	.probe		= sdhci_tegra_probe,
514	.remove		= sdhci_pltfm_unregister,
515};
516
517module_platform_driver(sdhci_tegra_driver);
518
519MODULE_DESCRIPTION("SDHCI driver for Tegra");
520MODULE_AUTHOR("Google, Inc.");
521MODULE_LICENSE("GPL v2");