Linux Audio

Check our new training course

Loading...
v3.5.6
  1/*
  2 * Copyright (C) 2010 Marvell International Ltd.
  3 *		Zhangfei Gao <zhangfei.gao@marvell.com>
  4 *		Kevin Wang <dwang4@marvell.com>
  5 *		Mingwei Wang <mwwang@marvell.com>
  6 *		Philip Rakity <prakity@marvell.com>
  7 *		Mark Brown <markb@marvell.com>
  8 *
  9 * This software is licensed under the terms of the GNU General Public
 10 * License version 2, as published by the Free Software Foundation, and
 11 * may be copied, distributed, and modified under those terms.
 12 *
 13 * This program is distributed in the hope that it will be useful,
 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16 * GNU General Public License for more details.
 17 *
 18 */
 19#include <linux/err.h>
 20#include <linux/init.h>
 21#include <linux/platform_device.h>
 22#include <linux/clk.h>
 23#include <linux/io.h>
 24#include <linux/gpio.h>
 25#include <linux/mmc/card.h>
 26#include <linux/mmc/host.h>
 27#include <linux/platform_data/pxa_sdhci.h>
 28#include <linux/slab.h>
 29#include <linux/delay.h>
 30#include <linux/module.h>
 31#include "sdhci.h"
 32#include "sdhci-pltfm.h"
 33
 34#define SD_CLOCK_BURST_SIZE_SETUP		0x10A
 35#define SDCLK_SEL	0x100
 36#define SDCLK_DELAY_SHIFT	9
 37#define SDCLK_DELAY_MASK	0x1f
 38
 39#define SD_CFG_FIFO_PARAM       0x100
 40#define SDCFG_GEN_PAD_CLK_ON	(1<<6)
 41#define SDCFG_GEN_PAD_CLK_CNT_MASK	0xFF
 42#define SDCFG_GEN_PAD_CLK_CNT_SHIFT	24
 43
 44#define SD_SPI_MODE          0x108
 45#define SD_CE_ATA_1          0x10C
 46
 47#define SD_CE_ATA_2          0x10E
 48#define SDCE_MISC_INT		(1<<2)
 49#define SDCE_MISC_INT_EN	(1<<1)
 50
 51static void pxav3_set_private_registers(struct sdhci_host *host, u8 mask)
 52{
 53	struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
 54	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
 55
 56	if (mask == SDHCI_RESET_ALL) {
 57		/*
 58		 * tune timing of read data/command when crc error happen
 59		 * no performance impact
 60		 */
 61		if (pdata && 0 != pdata->clk_delay_cycles) {
 62			u16 tmp;
 63
 64			tmp = readw(host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP);
 65			tmp |= (pdata->clk_delay_cycles & SDCLK_DELAY_MASK)
 66				<< SDCLK_DELAY_SHIFT;
 67			tmp |= SDCLK_SEL;
 68			writew(tmp, host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP);
 69		}
 70	}
 71}
 72
 73#define MAX_WAIT_COUNT 5
 74static void pxav3_gen_init_74_clocks(struct sdhci_host *host, u8 power_mode)
 75{
 76	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 77	struct sdhci_pxa *pxa = pltfm_host->priv;
 78	u16 tmp;
 79	int count;
 80
 81	if (pxa->power_mode == MMC_POWER_UP
 82			&& power_mode == MMC_POWER_ON) {
 83
 84		dev_dbg(mmc_dev(host->mmc),
 85				"%s: slot->power_mode = %d,"
 86				"ios->power_mode = %d\n",
 87				__func__,
 88				pxa->power_mode,
 89				power_mode);
 90
 91		/* set we want notice of when 74 clocks are sent */
 92		tmp = readw(host->ioaddr + SD_CE_ATA_2);
 93		tmp |= SDCE_MISC_INT_EN;
 94		writew(tmp, host->ioaddr + SD_CE_ATA_2);
 95
 96		/* start sending the 74 clocks */
 97		tmp = readw(host->ioaddr + SD_CFG_FIFO_PARAM);
 98		tmp |= SDCFG_GEN_PAD_CLK_ON;
 99		writew(tmp, host->ioaddr + SD_CFG_FIFO_PARAM);
100
101		/* slowest speed is about 100KHz or 10usec per clock */
102		udelay(740);
103		count = 0;
104
105		while (count++ < MAX_WAIT_COUNT) {
106			if ((readw(host->ioaddr + SD_CE_ATA_2)
107						& SDCE_MISC_INT) == 0)
108				break;
109			udelay(10);
110		}
111
112		if (count == MAX_WAIT_COUNT)
113			dev_warn(mmc_dev(host->mmc), "74 clock interrupt not cleared\n");
114
115		/* clear the interrupt bit if posted */
116		tmp = readw(host->ioaddr + SD_CE_ATA_2);
117		tmp |= SDCE_MISC_INT;
118		writew(tmp, host->ioaddr + SD_CE_ATA_2);
119	}
120	pxa->power_mode = power_mode;
121}
122
123static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
124{
125	u16 ctrl_2;
126
127	/*
128	 * Set V18_EN -- UHS modes do not work without this.
129	 * does not change signaling voltage
130	 */
131	ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
132
133	/* Select Bus Speed Mode for host */
134	ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
135	switch (uhs) {
136	case MMC_TIMING_UHS_SDR12:
137		ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
138		break;
139	case MMC_TIMING_UHS_SDR25:
140		ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
141		break;
142	case MMC_TIMING_UHS_SDR50:
143		ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180;
144		break;
145	case MMC_TIMING_UHS_SDR104:
146		ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180;
147		break;
148	case MMC_TIMING_UHS_DDR50:
149		ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180;
150		break;
151	}
152
153	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
154	dev_dbg(mmc_dev(host->mmc),
155		"%s uhs = %d, ctrl_2 = %04X\n",
156		__func__, uhs, ctrl_2);
157
158	return 0;
159}
160
161static struct sdhci_ops pxav3_sdhci_ops = {
162	.platform_reset_exit = pxav3_set_private_registers,
163	.set_uhs_signaling = pxav3_set_uhs_signaling,
164	.platform_send_init_74_clocks = pxav3_gen_init_74_clocks,
165};
166
167static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
168{
169	struct sdhci_pltfm_host *pltfm_host;
170	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
171	struct device *dev = &pdev->dev;
172	struct sdhci_host *host = NULL;
173	struct sdhci_pxa *pxa = NULL;
174	int ret;
175	struct clk *clk;
176
177	pxa = kzalloc(sizeof(struct sdhci_pxa), GFP_KERNEL);
178	if (!pxa)
179		return -ENOMEM;
180
181	host = sdhci_pltfm_init(pdev, NULL);
182	if (IS_ERR(host)) {
183		kfree(pxa);
184		return PTR_ERR(host);
185	}
186	pltfm_host = sdhci_priv(host);
187	pltfm_host->priv = pxa;
188
189	clk = clk_get(dev, "PXA-SDHCLK");
190	if (IS_ERR(clk)) {
191		dev_err(dev, "failed to get io clock\n");
192		ret = PTR_ERR(clk);
193		goto err_clk_get;
194	}
195	pltfm_host->clk = clk;
196	clk_enable(clk);
197
198	host->quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
199		| SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
200		| SDHCI_QUIRK_32BIT_ADMA_SIZE;
201
202	/* enable 1/8V DDR capable */
203	host->mmc->caps |= MMC_CAP_1_8V_DDR;
204
205	if (pdata) {
206		if (pdata->flags & PXA_FLAG_CARD_PERMANENT) {
207			/* on-chip device */
208			host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
209			host->mmc->caps |= MMC_CAP_NONREMOVABLE;
210		}
211
212		/* If slot design supports 8 bit data, indicate this to MMC. */
213		if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT)
214			host->mmc->caps |= MMC_CAP_8_BIT_DATA;
215
216		if (pdata->quirks)
217			host->quirks |= pdata->quirks;
218		if (pdata->host_caps)
219			host->mmc->caps |= pdata->host_caps;
220		if (pdata->pm_caps)
221			host->mmc->pm_caps |= pdata->pm_caps;
222	}
223
224	host->ops = &pxav3_sdhci_ops;
225
226	ret = sdhci_add_host(host);
227	if (ret) {
228		dev_err(&pdev->dev, "failed to add host\n");
229		goto err_add_host;
230	}
231
232	platform_set_drvdata(pdev, host);
233
234	return 0;
235
236err_add_host:
237	clk_disable(clk);
238	clk_put(clk);
239err_clk_get:
240	sdhci_pltfm_free(pdev);
241	kfree(pxa);
242	return ret;
243}
244
245static int __devexit sdhci_pxav3_remove(struct platform_device *pdev)
246{
247	struct sdhci_host *host = platform_get_drvdata(pdev);
248	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
249	struct sdhci_pxa *pxa = pltfm_host->priv;
250
251	sdhci_remove_host(host, 1);
252
253	clk_disable(pltfm_host->clk);
254	clk_put(pltfm_host->clk);
255	sdhci_pltfm_free(pdev);
256	kfree(pxa);
257
258	platform_set_drvdata(pdev, NULL);
259
260	return 0;
261}
262
263static struct platform_driver sdhci_pxav3_driver = {
264	.driver		= {
265		.name	= "sdhci-pxav3",
266		.owner	= THIS_MODULE,
267		.pm	= SDHCI_PLTFM_PMOPS,
268	},
269	.probe		= sdhci_pxav3_probe,
270	.remove		= __devexit_p(sdhci_pxav3_remove),
 
 
 
 
271};
 
 
 
 
 
 
 
 
 
272
273module_platform_driver(sdhci_pxav3_driver);
 
274
275MODULE_DESCRIPTION("SDHCI driver for pxav3");
276MODULE_AUTHOR("Marvell International Ltd.");
277MODULE_LICENSE("GPL v2");
278
v3.1
  1/*
  2 * Copyright (C) 2010 Marvell International Ltd.
  3 *		Zhangfei Gao <zhangfei.gao@marvell.com>
  4 *		Kevin Wang <dwang4@marvell.com>
  5 *		Mingwei Wang <mwwang@marvell.com>
  6 *		Philip Rakity <prakity@marvell.com>
  7 *		Mark Brown <markb@marvell.com>
  8 *
  9 * This software is licensed under the terms of the GNU General Public
 10 * License version 2, as published by the Free Software Foundation, and
 11 * may be copied, distributed, and modified under those terms.
 12 *
 13 * This program is distributed in the hope that it will be useful,
 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16 * GNU General Public License for more details.
 17 *
 18 */
 19#include <linux/err.h>
 20#include <linux/init.h>
 21#include <linux/platform_device.h>
 22#include <linux/clk.h>
 23#include <linux/io.h>
 24#include <linux/gpio.h>
 25#include <linux/mmc/card.h>
 26#include <linux/mmc/host.h>
 27#include <linux/platform_data/pxa_sdhci.h>
 28#include <linux/slab.h>
 29#include <linux/delay.h>
 
 30#include "sdhci.h"
 31#include "sdhci-pltfm.h"
 32
 33#define SD_CLOCK_BURST_SIZE_SETUP		0x10A
 34#define SDCLK_SEL	0x100
 35#define SDCLK_DELAY_SHIFT	9
 36#define SDCLK_DELAY_MASK	0x1f
 37
 38#define SD_CFG_FIFO_PARAM       0x100
 39#define SDCFG_GEN_PAD_CLK_ON	(1<<6)
 40#define SDCFG_GEN_PAD_CLK_CNT_MASK	0xFF
 41#define SDCFG_GEN_PAD_CLK_CNT_SHIFT	24
 42
 43#define SD_SPI_MODE          0x108
 44#define SD_CE_ATA_1          0x10C
 45
 46#define SD_CE_ATA_2          0x10E
 47#define SDCE_MISC_INT		(1<<2)
 48#define SDCE_MISC_INT_EN	(1<<1)
 49
 50static void pxav3_set_private_registers(struct sdhci_host *host, u8 mask)
 51{
 52	struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
 53	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
 54
 55	if (mask == SDHCI_RESET_ALL) {
 56		/*
 57		 * tune timing of read data/command when crc error happen
 58		 * no performance impact
 59		 */
 60		if (pdata && 0 != pdata->clk_delay_cycles) {
 61			u16 tmp;
 62
 63			tmp = readw(host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP);
 64			tmp |= (pdata->clk_delay_cycles & SDCLK_DELAY_MASK)
 65				<< SDCLK_DELAY_SHIFT;
 66			tmp |= SDCLK_SEL;
 67			writew(tmp, host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP);
 68		}
 69	}
 70}
 71
 72#define MAX_WAIT_COUNT 5
 73static void pxav3_gen_init_74_clocks(struct sdhci_host *host, u8 power_mode)
 74{
 75	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 76	struct sdhci_pxa *pxa = pltfm_host->priv;
 77	u16 tmp;
 78	int count;
 79
 80	if (pxa->power_mode == MMC_POWER_UP
 81			&& power_mode == MMC_POWER_ON) {
 82
 83		dev_dbg(mmc_dev(host->mmc),
 84				"%s: slot->power_mode = %d,"
 85				"ios->power_mode = %d\n",
 86				__func__,
 87				pxa->power_mode,
 88				power_mode);
 89
 90		/* set we want notice of when 74 clocks are sent */
 91		tmp = readw(host->ioaddr + SD_CE_ATA_2);
 92		tmp |= SDCE_MISC_INT_EN;
 93		writew(tmp, host->ioaddr + SD_CE_ATA_2);
 94
 95		/* start sending the 74 clocks */
 96		tmp = readw(host->ioaddr + SD_CFG_FIFO_PARAM);
 97		tmp |= SDCFG_GEN_PAD_CLK_ON;
 98		writew(tmp, host->ioaddr + SD_CFG_FIFO_PARAM);
 99
100		/* slowest speed is about 100KHz or 10usec per clock */
101		udelay(740);
102		count = 0;
103
104		while (count++ < MAX_WAIT_COUNT) {
105			if ((readw(host->ioaddr + SD_CE_ATA_2)
106						& SDCE_MISC_INT) == 0)
107				break;
108			udelay(10);
109		}
110
111		if (count == MAX_WAIT_COUNT)
112			dev_warn(mmc_dev(host->mmc), "74 clock interrupt not cleared\n");
113
114		/* clear the interrupt bit if posted */
115		tmp = readw(host->ioaddr + SD_CE_ATA_2);
116		tmp |= SDCE_MISC_INT;
117		writew(tmp, host->ioaddr + SD_CE_ATA_2);
118	}
119	pxa->power_mode = power_mode;
120}
121
122static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
123{
124	u16 ctrl_2;
125
126	/*
127	 * Set V18_EN -- UHS modes do not work without this.
128	 * does not change signaling voltage
129	 */
130	ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
131
132	/* Select Bus Speed Mode for host */
133	ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
134	switch (uhs) {
135	case MMC_TIMING_UHS_SDR12:
136		ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
137		break;
138	case MMC_TIMING_UHS_SDR25:
139		ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
140		break;
141	case MMC_TIMING_UHS_SDR50:
142		ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180;
143		break;
144	case MMC_TIMING_UHS_SDR104:
145		ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180;
146		break;
147	case MMC_TIMING_UHS_DDR50:
148		ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180;
149		break;
150	}
151
152	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
153	dev_dbg(mmc_dev(host->mmc),
154		"%s uhs = %d, ctrl_2 = %04X\n",
155		__func__, uhs, ctrl_2);
156
157	return 0;
158}
159
160static struct sdhci_ops pxav3_sdhci_ops = {
161	.platform_reset_exit = pxav3_set_private_registers,
162	.set_uhs_signaling = pxav3_set_uhs_signaling,
163	.platform_send_init_74_clocks = pxav3_gen_init_74_clocks,
164};
165
166static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
167{
168	struct sdhci_pltfm_host *pltfm_host;
169	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
170	struct device *dev = &pdev->dev;
171	struct sdhci_host *host = NULL;
172	struct sdhci_pxa *pxa = NULL;
173	int ret;
174	struct clk *clk;
175
176	pxa = kzalloc(sizeof(struct sdhci_pxa), GFP_KERNEL);
177	if (!pxa)
178		return -ENOMEM;
179
180	host = sdhci_pltfm_init(pdev, NULL);
181	if (IS_ERR(host)) {
182		kfree(pxa);
183		return PTR_ERR(host);
184	}
185	pltfm_host = sdhci_priv(host);
186	pltfm_host->priv = pxa;
187
188	clk = clk_get(dev, "PXA-SDHCLK");
189	if (IS_ERR(clk)) {
190		dev_err(dev, "failed to get io clock\n");
191		ret = PTR_ERR(clk);
192		goto err_clk_get;
193	}
194	pltfm_host->clk = clk;
195	clk_enable(clk);
196
197	host->quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
198		| SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
199		| SDHCI_QUIRK_32BIT_ADMA_SIZE;
200
201	/* enable 1/8V DDR capable */
202	host->mmc->caps |= MMC_CAP_1_8V_DDR;
203
204	if (pdata) {
205		if (pdata->flags & PXA_FLAG_CARD_PERMANENT) {
206			/* on-chip device */
207			host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
208			host->mmc->caps |= MMC_CAP_NONREMOVABLE;
209		}
210
211		/* If slot design supports 8 bit data, indicate this to MMC. */
212		if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT)
213			host->mmc->caps |= MMC_CAP_8_BIT_DATA;
214
215		if (pdata->quirks)
216			host->quirks |= pdata->quirks;
217		if (pdata->host_caps)
218			host->mmc->caps |= pdata->host_caps;
219		if (pdata->pm_caps)
220			host->mmc->pm_caps |= pdata->pm_caps;
221	}
222
223	host->ops = &pxav3_sdhci_ops;
224
225	ret = sdhci_add_host(host);
226	if (ret) {
227		dev_err(&pdev->dev, "failed to add host\n");
228		goto err_add_host;
229	}
230
231	platform_set_drvdata(pdev, host);
232
233	return 0;
234
235err_add_host:
236	clk_disable(clk);
237	clk_put(clk);
238err_clk_get:
239	sdhci_pltfm_free(pdev);
240	kfree(pxa);
241	return ret;
242}
243
244static int __devexit sdhci_pxav3_remove(struct platform_device *pdev)
245{
246	struct sdhci_host *host = platform_get_drvdata(pdev);
247	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
248	struct sdhci_pxa *pxa = pltfm_host->priv;
249
250	sdhci_remove_host(host, 1);
251
252	clk_disable(pltfm_host->clk);
253	clk_put(pltfm_host->clk);
254	sdhci_pltfm_free(pdev);
255	kfree(pxa);
256
257	platform_set_drvdata(pdev, NULL);
258
259	return 0;
260}
261
262static struct platform_driver sdhci_pxav3_driver = {
263	.driver		= {
264		.name	= "sdhci-pxav3",
265		.owner	= THIS_MODULE,
 
266	},
267	.probe		= sdhci_pxav3_probe,
268	.remove		= __devexit_p(sdhci_pxav3_remove),
269#ifdef CONFIG_PM
270	.suspend	= sdhci_pltfm_suspend,
271	.resume		= sdhci_pltfm_resume,
272#endif
273};
274static int __init sdhci_pxav3_init(void)
275{
276	return platform_driver_register(&sdhci_pxav3_driver);
277}
278
279static void __exit sdhci_pxav3_exit(void)
280{
281	platform_driver_unregister(&sdhci_pxav3_driver);
282}
283
284module_init(sdhci_pxav3_init);
285module_exit(sdhci_pxav3_exit);
286
287MODULE_DESCRIPTION("SDHCI driver for pxav3");
288MODULE_AUTHOR("Marvell International Ltd.");
289MODULE_LICENSE("GPL v2");
290