1/*
2 * SDHCI support for SiRF primaII and marco SoCs
3 *
4 * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
5 *
6 * Licensed under GPLv2 or later.
7 */
8
9#include <linux/delay.h>
10#include <linux/device.h>
11#include <linux/mmc/host.h>
12#include <linux/module.h>
13#include <linux/of.h>
14#include <linux/of_gpio.h>
15#include <linux/mmc/slot-gpio.h>
16#include "sdhci-pltfm.h"
17
18#define SDHCI_CLK_DELAY_SETTING 0x4C
19#define SDHCI_SIRF_8BITBUS BIT(3)
20#define SIRF_TUNING_COUNT 128
21
22struct sdhci_sirf_priv {
23	int gpio_cd;
24};
25
26static void sdhci_sirf_set_bus_width(struct sdhci_host *host, int width)
27{
28	u8 ctrl;
29
30	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
31	ctrl &= ~(SDHCI_CTRL_4BITBUS | SDHCI_SIRF_8BITBUS);
32
33	/*
34	 * CSR atlas7 and prima2 SD host version is not 3.0
35	 * 8bit-width enable bit of CSR SD hosts is 3,
36	 * while stardard hosts use bit 5
37	 */
38	if (width == MMC_BUS_WIDTH_8)
39		ctrl |= SDHCI_SIRF_8BITBUS;
40	else if (width == MMC_BUS_WIDTH_4)
41		ctrl |= SDHCI_CTRL_4BITBUS;
42
43	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
44}
45
46static int sdhci_sirf_execute_tuning(struct sdhci_host *host, u32 opcode)
47{
48	int tuning_seq_cnt = 3;
49	u8 phase, tuned_phases[SIRF_TUNING_COUNT];
50	u8 tuned_phase_cnt = 0;
51	int rc = 0, longest_range = 0;
52	int start = -1, end = 0, tuning_value = -1, range = 0;
53	u16 clock_setting;
54	struct mmc_host *mmc = host->mmc;
55
56	clock_setting = sdhci_readw(host, SDHCI_CLK_DELAY_SETTING);
57	clock_setting &= ~0x3fff;
58
59retry:
60	phase = 0;
61	do {
62		sdhci_writel(host,
63			clock_setting | phase,
64			SDHCI_CLK_DELAY_SETTING);
65
66		if (!mmc_send_tuning(mmc)) {
67			/* Tuning is successful at this tuning point */
68			tuned_phases[tuned_phase_cnt++] = phase;
69			dev_dbg(mmc_dev(mmc), "%s: Found good phase = %d\n",
70				 mmc_hostname(mmc), phase);
71			if (start == -1)
72				start = phase;
73			end = phase;
74			range++;
75			if (phase == (SIRF_TUNING_COUNT - 1)
76				&& range > longest_range)
77				tuning_value = (start + end) / 2;
78		} else {
79			dev_dbg(mmc_dev(mmc), "%s: Found bad phase = %d\n",
80				 mmc_hostname(mmc), phase);
81			if (range > longest_range) {
82				tuning_value = (start + end) / 2;
83				longest_range = range;
84			}
85			start = -1;
86			end = range = 0;
87		}
88	} while (++phase < ARRAY_SIZE(tuned_phases));
89
90	if (tuned_phase_cnt && tuning_value > 0) {
91		/*
92		 * Finally set the selected phase in delay
93		 * line hw block.
94		 */
95		phase = tuning_value;
96		sdhci_writel(host,
97			clock_setting | phase,
98			SDHCI_CLK_DELAY_SETTING);
99
100		dev_dbg(mmc_dev(mmc), "%s: Setting the tuning phase to %d\n",
101			 mmc_hostname(mmc), phase);
102	} else {
103		if (--tuning_seq_cnt)
104			goto retry;
105		/* Tuning failed */
106		dev_dbg(mmc_dev(mmc), "%s: No tuning point found\n",
107		       mmc_hostname(mmc));
108		rc = -EIO;
109	}
110
111	return rc;
112}
113
114static struct sdhci_ops sdhci_sirf_ops = {
115	.platform_execute_tuning = sdhci_sirf_execute_tuning,
116	.set_clock = sdhci_set_clock,
117	.get_max_clock	= sdhci_pltfm_clk_get_max_clock,
118	.set_bus_width = sdhci_sirf_set_bus_width,
119	.reset = sdhci_reset,
120	.set_uhs_signaling = sdhci_set_uhs_signaling,
121};
122
123static struct sdhci_pltfm_data sdhci_sirf_pdata = {
124	.ops = &sdhci_sirf_ops,
125	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
126		SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
127		SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
128		SDHCI_QUIRK_INVERTED_WRITE_PROTECT |
129		SDHCI_QUIRK_DELAY_AFTER_POWER,
130};
131
132static int sdhci_sirf_probe(struct platform_device *pdev)
133{
134	struct sdhci_host *host;
135	struct sdhci_pltfm_host *pltfm_host;
136	struct sdhci_sirf_priv *priv;
137	struct clk *clk;
138	int gpio_cd;
139	int ret;
140
141	clk = devm_clk_get(&pdev->dev, NULL);
142	if (IS_ERR(clk)) {
143		dev_err(&pdev->dev, "unable to get clock");
144		return PTR_ERR(clk);
145	}
146
147	if (pdev->dev.of_node)
148		gpio_cd = of_get_named_gpio(pdev->dev.of_node, "cd-gpios", 0);
149	else
150		gpio_cd = -EINVAL;
151
152	host = sdhci_pltfm_init(pdev, &sdhci_sirf_pdata, sizeof(struct sdhci_sirf_priv));
153	if (IS_ERR(host))
154		return PTR_ERR(host);
155
156	pltfm_host = sdhci_priv(host);
157	pltfm_host->clk = clk;
158	priv = sdhci_pltfm_priv(pltfm_host);
159	priv->gpio_cd = gpio_cd;
160
161	sdhci_get_of_property(pdev);
162
163	ret = clk_prepare_enable(pltfm_host->clk);
164	if (ret)
165		goto err_clk_prepare;
166
167	ret = sdhci_add_host(host);
168	if (ret)
169		goto err_sdhci_add;
170
171	/*
172	 * We must request the IRQ after sdhci_add_host(), as the tasklet only
173	 * gets setup in sdhci_add_host() and we oops.
174	 */
175	if (gpio_is_valid(priv->gpio_cd)) {
176		ret = mmc_gpio_request_cd(host->mmc, priv->gpio_cd, 0);
177		if (ret) {
178			dev_err(&pdev->dev, "card detect irq request failed: %d\n",
179				ret);
180			goto err_request_cd;
181		}
182		mmc_gpiod_request_cd_irq(host->mmc);
183	}
184
185	return 0;
186
187err_request_cd:
188	sdhci_remove_host(host, 0);
189err_sdhci_add:
190	clk_disable_unprepare(pltfm_host->clk);
191err_clk_prepare:
192	sdhci_pltfm_free(pdev);
193	return ret;
194}
195
196#ifdef CONFIG_PM_SLEEP
197static int sdhci_sirf_suspend(struct device *dev)
198{
199	struct sdhci_host *host = dev_get_drvdata(dev);
200	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
201	int ret;
202
203	ret = sdhci_suspend_host(host);
204	if (ret)
205		return ret;
206
207	clk_disable(pltfm_host->clk);
208
209	return 0;
210}
211
212static int sdhci_sirf_resume(struct device *dev)
213{
214	struct sdhci_host *host = dev_get_drvdata(dev);
215	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
216	int ret;
217
218	ret = clk_enable(pltfm_host->clk);
219	if (ret) {
220		dev_dbg(dev, "Resume: Error enabling clock\n");
221		return ret;
222	}
223
224	return sdhci_resume_host(host);
225}
226
227static SIMPLE_DEV_PM_OPS(sdhci_sirf_pm_ops, sdhci_sirf_suspend, sdhci_sirf_resume);
228#endif
229
230static const struct of_device_id sdhci_sirf_of_match[] = {
231	{ .compatible = "sirf,prima2-sdhc" },
232	{ }
233};
234MODULE_DEVICE_TABLE(of, sdhci_sirf_of_match);
235
236static struct platform_driver sdhci_sirf_driver = {
237	.driver		= {
238		.name	= "sdhci-sirf",
239		.of_match_table = sdhci_sirf_of_match,
240#ifdef CONFIG_PM_SLEEP
241		.pm	= &sdhci_sirf_pm_ops,
242#endif
243	},
244	.probe		= sdhci_sirf_probe,
245	.remove		= sdhci_pltfm_unregister,
246};
247
248module_platform_driver(sdhci_sirf_driver);
249
250MODULE_DESCRIPTION("SDHCI driver for SiRFprimaII/SiRFmarco");
251MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
252MODULE_LICENSE("GPL v2");
253