1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright (C) 2013 Broadcom Corporation
3
4 #include <linux/kernel.h>
5 #include <linux/module.h>
6 #include <linux/delay.h>
7 #include <linux/highmem.h>
8 #include <linux/platform_device.h>
9 #include <linux/mmc/host.h>
10 #include <linux/io.h>
11 #include <linux/clk.h>
12 #include <linux/regulator/consumer.h>
13 #include <linux/of.h>
14 #include <linux/mmc/slot-gpio.h>
15
16 #include "sdhci-pltfm.h"
17 #include "sdhci.h"
18
19 #define SDHCI_SOFT_RESET 0x01000000
20 #define KONA_SDHOST_CORECTRL 0x8000
21 #define KONA_SDHOST_CD_PINCTRL 0x00000008
22 #define KONA_SDHOST_STOP_HCLK 0x00000004
23 #define KONA_SDHOST_RESET 0x00000002
24 #define KONA_SDHOST_EN 0x00000001
25
26 #define KONA_SDHOST_CORESTAT 0x8004
27 #define KONA_SDHOST_WP 0x00000002
28 #define KONA_SDHOST_CD_SW 0x00000001
29
30 #define KONA_SDHOST_COREIMR 0x8008
31 #define KONA_SDHOST_IP 0x00000001
32
33 #define KONA_SDHOST_COREISR 0x800C
34 #define KONA_SDHOST_COREIMSR 0x8010
35 #define KONA_SDHOST_COREDBG1 0x8014
36 #define KONA_SDHOST_COREGPO_MASK 0x8018
37
38 #define SD_DETECT_GPIO_DEBOUNCE_128MS 128
39
40 #define KONA_MMC_AUTOSUSPEND_DELAY (50)
41
42 struct sdhci_bcm_kona_dev {
43 struct mutex write_lock; /* protect back to back writes */
44 };
45
46
sdhci_bcm_kona_sd_reset(struct sdhci_host * host)47 static int sdhci_bcm_kona_sd_reset(struct sdhci_host *host)
48 {
49 unsigned int val;
50 unsigned long timeout;
51
52 /* This timeout should be sufficent for core to reset */
53 timeout = jiffies + msecs_to_jiffies(100);
54
55 /* reset the host using the top level reset */
56 val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
57 val |= KONA_SDHOST_RESET;
58 sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
59
60 while (!(sdhci_readl(host, KONA_SDHOST_CORECTRL) & KONA_SDHOST_RESET)) {
61 if (time_is_before_jiffies(timeout)) {
62 pr_err("Error: sd host is stuck in reset!!!\n");
63 return -EFAULT;
64 }
65 }
66
67 /* bring the host out of reset */
68 val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
69 val &= ~KONA_SDHOST_RESET;
70
71 /*
72 * Back-to-Back register write needs a delay of 1ms at bootup (min 10uS)
73 * Back-to-Back writes to same register needs delay when SD bus clock
74 * is very low w.r.t AHB clock, mainly during boot-time and during card
75 * insert-removal.
76 */
77 usleep_range(1000, 5000);
78 sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
79
80 return 0;
81 }
82
sdhci_bcm_kona_sd_init(struct sdhci_host * host)83 static void sdhci_bcm_kona_sd_init(struct sdhci_host *host)
84 {
85 unsigned int val;
86
87 /* enable the interrupt from the IP core */
88 val = sdhci_readl(host, KONA_SDHOST_COREIMR);
89 val |= KONA_SDHOST_IP;
90 sdhci_writel(host, val, KONA_SDHOST_COREIMR);
91
92 /* Enable the AHB clock gating module to the host */
93 val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
94 val |= KONA_SDHOST_EN;
95
96 /*
97 * Back-to-Back register write needs a delay of 1ms at bootup (min 10uS)
98 * Back-to-Back writes to same register needs delay when SD bus clock
99 * is very low w.r.t AHB clock, mainly during boot-time and during card
100 * insert-removal.
101 */
102 usleep_range(1000, 5000);
103 sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
104 }
105
106 /*
107 * Software emulation of the SD card insertion/removal. Set insert=1 for insert
108 * and insert=0 for removal. The card detection is done by GPIO. For Broadcom
109 * IP to function properly the bit 0 of CORESTAT register needs to be set/reset
110 * to generate the CD IRQ handled in sdhci.c
111 */
sdhci_bcm_kona_sd_card_emulate(struct sdhci_host * host,int insert)112 static int sdhci_bcm_kona_sd_card_emulate(struct sdhci_host *host, int insert)
113 {
114 struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host);
115 struct sdhci_bcm_kona_dev *kona_dev = sdhci_pltfm_priv(pltfm_priv);
116 u32 val;
117
118 /*
119 * Back-to-Back register write needs a delay of min 10uS.
120 * Back-to-Back writes to same register needs delay when SD bus clock
121 * is very low w.r.t AHB clock, mainly during boot-time and during card
122 * insert-removal.
123 * We keep 20uS
124 */
125 mutex_lock(&kona_dev->write_lock);
126 udelay(20);
127 val = sdhci_readl(host, KONA_SDHOST_CORESTAT);
128
129 if (insert) {
130 int ret;
131
132 ret = mmc_gpio_get_ro(host->mmc);
133 if (ret >= 0)
134 val = (val & ~KONA_SDHOST_WP) |
135 ((ret) ? KONA_SDHOST_WP : 0);
136
137 val |= KONA_SDHOST_CD_SW;
138 sdhci_writel(host, val, KONA_SDHOST_CORESTAT);
139 } else {
140 val &= ~KONA_SDHOST_CD_SW;
141 sdhci_writel(host, val, KONA_SDHOST_CORESTAT);
142 }
143 mutex_unlock(&kona_dev->write_lock);
144
145 return 0;
146 }
147
148 /*
149 * SD card interrupt event callback
150 */
sdhci_bcm_kona_card_event(struct sdhci_host * host)151 static void sdhci_bcm_kona_card_event(struct sdhci_host *host)
152 {
153 if (mmc_gpio_get_cd(host->mmc) > 0) {
154 dev_dbg(mmc_dev(host->mmc),
155 "card inserted\n");
156 sdhci_bcm_kona_sd_card_emulate(host, 1);
157 } else {
158 dev_dbg(mmc_dev(host->mmc),
159 "card removed\n");
160 sdhci_bcm_kona_sd_card_emulate(host, 0);
161 }
162 }
163
sdhci_bcm_kona_init_74_clocks(struct sdhci_host * host,u8 power_mode)164 static void sdhci_bcm_kona_init_74_clocks(struct sdhci_host *host,
165 u8 power_mode)
166 {
167 /*
168 * JEDEC and SD spec specify supplying 74 continuous clocks to
169 * device after power up. With minimum bus (100KHz) that
170 * translates to 740us
171 */
172 if (power_mode != MMC_POWER_OFF)
173 udelay(740);
174 }
175
176 static const struct sdhci_ops sdhci_bcm_kona_ops = {
177 .set_clock = sdhci_set_clock,
178 .get_max_clock = sdhci_pltfm_clk_get_max_clock,
179 .get_timeout_clock = sdhci_pltfm_clk_get_max_clock,
180 .platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks,
181 .set_bus_width = sdhci_set_bus_width,
182 .reset = sdhci_reset,
183 .set_uhs_signaling = sdhci_set_uhs_signaling,
184 .card_event = sdhci_bcm_kona_card_event,
185 };
186
187 static const struct sdhci_pltfm_data sdhci_pltfm_data_kona = {
188 .ops = &sdhci_bcm_kona_ops,
189 .quirks = SDHCI_QUIRK_NO_CARD_NO_RESET |
190 SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | SDHCI_QUIRK_32BIT_DMA_ADDR |
191 SDHCI_QUIRK_32BIT_DMA_SIZE | SDHCI_QUIRK_32BIT_ADMA_SIZE |
192 SDHCI_QUIRK_FORCE_BLK_SZ_2048 |
193 SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
194 };
195
196 static const struct of_device_id sdhci_bcm_kona_of_match[] = {
197 { .compatible = "brcm,kona-sdhci"},
198 { .compatible = "bcm,kona-sdhci"}, /* deprecated name */
199 {}
200 };
201 MODULE_DEVICE_TABLE(of, sdhci_bcm_kona_of_match);
202
sdhci_bcm_kona_probe(struct platform_device * pdev)203 static int sdhci_bcm_kona_probe(struct platform_device *pdev)
204 {
205 struct sdhci_bcm_kona_dev *kona_dev = NULL;
206 struct sdhci_pltfm_host *pltfm_priv;
207 struct device *dev = &pdev->dev;
208 struct sdhci_host *host;
209 int ret;
210
211 ret = 0;
212
213 host = sdhci_pltfm_init(pdev, &sdhci_pltfm_data_kona,
214 sizeof(*kona_dev));
215 if (IS_ERR(host))
216 return PTR_ERR(host);
217
218 dev_dbg(dev, "%s: inited. IOADDR=%p\n", __func__, host->ioaddr);
219
220 pltfm_priv = sdhci_priv(host);
221
222 kona_dev = sdhci_pltfm_priv(pltfm_priv);
223 mutex_init(&kona_dev->write_lock);
224
225 ret = mmc_of_parse(host->mmc);
226 if (ret)
227 goto err_pltfm_free;
228
229 if (!host->mmc->f_max) {
230 dev_err(&pdev->dev, "Missing max-freq for SDHCI cfg\n");
231 ret = -ENXIO;
232 goto err_pltfm_free;
233 }
234
235 /* Get and enable the core clock */
236 pltfm_priv->clk = devm_clk_get(dev, NULL);
237 if (IS_ERR(pltfm_priv->clk)) {
238 dev_err(dev, "Failed to get core clock\n");
239 ret = PTR_ERR(pltfm_priv->clk);
240 goto err_pltfm_free;
241 }
242
243 ret = clk_set_rate(pltfm_priv->clk, host->mmc->f_max);
244 if (ret) {
245 dev_err(dev, "Failed to set rate core clock\n");
246 goto err_pltfm_free;
247 }
248
249 ret = clk_prepare_enable(pltfm_priv->clk);
250 if (ret) {
251 dev_err(dev, "Failed to enable core clock\n");
252 goto err_pltfm_free;
253 }
254
255 dev_dbg(dev, "non-removable=%c\n",
256 mmc_card_is_removable(host->mmc) ? 'N' : 'Y');
257 dev_dbg(dev, "cd_gpio %c, wp_gpio %c\n",
258 (mmc_gpio_get_cd(host->mmc) != -ENOSYS) ? 'Y' : 'N',
259 (mmc_gpio_get_ro(host->mmc) != -ENOSYS) ? 'Y' : 'N');
260
261 if (!mmc_card_is_removable(host->mmc))
262 host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
263
264 dev_dbg(dev, "is_8bit=%c\n",
265 (host->mmc->caps & MMC_CAP_8_BIT_DATA) ? 'Y' : 'N');
266
267 ret = sdhci_bcm_kona_sd_reset(host);
268 if (ret)
269 goto err_clk_disable;
270
271 sdhci_bcm_kona_sd_init(host);
272
273 ret = sdhci_add_host(host);
274 if (ret)
275 goto err_reset;
276
277 /* if device is eMMC, emulate card insert right here */
278 if (!mmc_card_is_removable(host->mmc)) {
279 ret = sdhci_bcm_kona_sd_card_emulate(host, 1);
280 if (ret) {
281 dev_err(dev,
282 "unable to emulate card insertion\n");
283 goto err_remove_host;
284 }
285 }
286 /*
287 * Since the card detection GPIO interrupt is configured to be
288 * edge sensitive, check the initial GPIO value here, emulate
289 * only if the card is present
290 */
291 if (mmc_gpio_get_cd(host->mmc) > 0)
292 sdhci_bcm_kona_sd_card_emulate(host, 1);
293
294 dev_dbg(dev, "initialized properly\n");
295 return 0;
296
297 err_remove_host:
298 sdhci_remove_host(host, 0);
299
300 err_reset:
301 sdhci_bcm_kona_sd_reset(host);
302
303 err_clk_disable:
304 clk_disable_unprepare(pltfm_priv->clk);
305
306 err_pltfm_free:
307 sdhci_pltfm_free(pdev);
308
309 dev_err(dev, "Probing of sdhci-pltfm failed: %d\n", ret);
310 return ret;
311 }
312
sdhci_bcm_kona_remove(struct platform_device * pdev)313 static void sdhci_bcm_kona_remove(struct platform_device *pdev)
314 {
315 struct sdhci_host *host = platform_get_drvdata(pdev);
316 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
317 struct clk *clk = pltfm_host->clk;
318
319 sdhci_pltfm_remove(pdev);
320 clk_disable_unprepare(clk);
321 }
322
323 static struct platform_driver sdhci_bcm_kona_driver = {
324 .driver = {
325 .name = "sdhci-kona",
326 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
327 .pm = &sdhci_pltfm_pmops,
328 .of_match_table = sdhci_bcm_kona_of_match,
329 },
330 .probe = sdhci_bcm_kona_probe,
331 .remove_new = sdhci_bcm_kona_remove,
332 };
333 module_platform_driver(sdhci_bcm_kona_driver);
334
335 MODULE_DESCRIPTION("SDHCI driver for Broadcom Kona platform");
336 MODULE_AUTHOR("Broadcom");
337 MODULE_LICENSE("GPL v2");
338