1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Copyright (C) 2019 ASPEED Technology Inc. */
3 /* Copyright (C) 2019 IBM Corp. */
4 
5 #include <linux/clk.h>
6 #include <linux/delay.h>
7 #include <linux/device.h>
8 #include <linux/io.h>
9 #include <linux/math64.h>
10 #include <linux/mmc/host.h>
11 #include <linux/module.h>
12 #include <linux/of_address.h>
13 #include <linux/of.h>
14 #include <linux/of_platform.h>
15 #include <linux/platform_device.h>
16 #include <linux/spinlock.h>
17 
18 #include "sdhci-pltfm.h"
19 
20 #define ASPEED_SDC_INFO			0x00
21 #define   ASPEED_SDC_S1_MMC8		BIT(25)
22 #define   ASPEED_SDC_S0_MMC8		BIT(24)
23 #define ASPEED_SDC_PHASE		0xf4
24 #define   ASPEED_SDC_S1_PHASE_IN	GENMASK(25, 21)
25 #define   ASPEED_SDC_S0_PHASE_IN	GENMASK(20, 16)
26 #define   ASPEED_SDC_S1_PHASE_OUT	GENMASK(15, 11)
27 #define   ASPEED_SDC_S1_PHASE_IN_EN	BIT(10)
28 #define   ASPEED_SDC_S1_PHASE_OUT_EN	GENMASK(9, 8)
29 #define   ASPEED_SDC_S0_PHASE_OUT	GENMASK(7, 3)
30 #define   ASPEED_SDC_S0_PHASE_IN_EN	BIT(2)
31 #define   ASPEED_SDC_S0_PHASE_OUT_EN	GENMASK(1, 0)
32 #define   ASPEED_SDC_PHASE_MAX		31
33 
34 struct aspeed_sdc {
35 	struct clk *clk;
36 	struct resource *res;
37 
38 	spinlock_t lock;
39 	void __iomem *regs;
40 };
41 
42 struct aspeed_sdhci_tap_param {
43 	bool valid;
44 
45 #define ASPEED_SDHCI_TAP_PARAM_INVERT_CLK	BIT(4)
46 	u8 in;
47 	u8 out;
48 };
49 
50 struct aspeed_sdhci_tap_desc {
51 	u32 tap_mask;
52 	u32 enable_mask;
53 	u8 enable_value;
54 };
55 
56 struct aspeed_sdhci_phase_desc {
57 	struct aspeed_sdhci_tap_desc in;
58 	struct aspeed_sdhci_tap_desc out;
59 };
60 
61 struct aspeed_sdhci_pdata {
62 	const struct aspeed_sdhci_phase_desc *phase_desc;
63 	size_t nr_phase_descs;
64 };
65 
66 struct aspeed_sdhci {
67 	const struct aspeed_sdhci_pdata *pdata;
68 	struct aspeed_sdc *parent;
69 	u32 width_mask;
70 	struct mmc_clk_phase_map phase_map;
71 	const struct aspeed_sdhci_phase_desc *phase_desc;
72 };
73 
74 static void aspeed_sdc_configure_8bit_mode(struct aspeed_sdc *sdc,
75 					   struct aspeed_sdhci *sdhci,
76 					   bool bus8)
77 {
78 	u32 info;
79 
80 	/* Set/clear 8 bit mode */
81 	spin_lock(&sdc->lock);
82 	info = readl(sdc->regs + ASPEED_SDC_INFO);
83 	if (bus8)
84 		info |= sdhci->width_mask;
85 	else
86 		info &= ~sdhci->width_mask;
87 	writel(info, sdc->regs + ASPEED_SDC_INFO);
88 	spin_unlock(&sdc->lock);
89 }
90 
91 static u32
92 aspeed_sdc_set_phase_tap(const struct aspeed_sdhci_tap_desc *desc,
93 			 u8 tap, bool enable, u32 reg)
94 {
95 	reg &= ~(desc->enable_mask | desc->tap_mask);
96 	if (enable) {
97 		reg |= tap << __ffs(desc->tap_mask);
98 		reg |= desc->enable_value << __ffs(desc->enable_mask);
99 	}
100 
101 	return reg;
102 }
103 
104 static void
105 aspeed_sdc_set_phase_taps(struct aspeed_sdc *sdc,
106 			  const struct aspeed_sdhci_phase_desc *desc,
107 			  const struct aspeed_sdhci_tap_param *taps)
108 {
109 	u32 reg;
110 
111 	spin_lock(&sdc->lock);
112 	reg = readl(sdc->regs + ASPEED_SDC_PHASE);
113 
114 	reg = aspeed_sdc_set_phase_tap(&desc->in, taps->in, taps->valid, reg);
115 	reg = aspeed_sdc_set_phase_tap(&desc->out, taps->out, taps->valid, reg);
116 
117 	writel(reg, sdc->regs + ASPEED_SDC_PHASE);
118 	spin_unlock(&sdc->lock);
119 }
120 
121 #define PICOSECONDS_PER_SECOND		1000000000000ULL
122 #define ASPEED_SDHCI_NR_TAPS		15
123 /* Measured value with *handwave* environmentals and static loading */
124 #define ASPEED_SDHCI_MAX_TAP_DELAY_PS	1253
125 static int aspeed_sdhci_phase_to_tap(struct device *dev, unsigned long rate_hz,
126 				     int phase_deg)
127 {
128 	u64 phase_period_ps;
129 	u64 prop_delay_ps;
130 	u64 clk_period_ps;
131 	unsigned int tap;
132 	u8 inverted;
133 
134 	phase_deg %= 360;
135 
136 	if (phase_deg >= 180) {
137 		inverted = ASPEED_SDHCI_TAP_PARAM_INVERT_CLK;
138 		phase_deg -= 180;
139 		dev_dbg(dev,
140 			"Inverting clock to reduce phase correction from %d to %d degrees\n",
141 			phase_deg + 180, phase_deg);
142 	} else {
143 		inverted = 0;
144 	}
145 
146 	prop_delay_ps = ASPEED_SDHCI_MAX_TAP_DELAY_PS / ASPEED_SDHCI_NR_TAPS;
147 	clk_period_ps = div_u64(PICOSECONDS_PER_SECOND, (u64)rate_hz);
148 	phase_period_ps = div_u64((u64)phase_deg * clk_period_ps, 360ULL);
149 
150 	tap = div_u64(phase_period_ps, prop_delay_ps);
151 	if (tap > ASPEED_SDHCI_NR_TAPS) {
152 		dev_warn(dev,
153 			 "Requested out of range phase tap %d for %d degrees of phase compensation at %luHz, clamping to tap %d\n",
154 			 tap, phase_deg, rate_hz, ASPEED_SDHCI_NR_TAPS);
155 		tap = ASPEED_SDHCI_NR_TAPS;
156 	}
157 
158 	return inverted | tap;
159 }
160 
161 static void
162 aspeed_sdhci_phases_to_taps(struct device *dev, unsigned long rate,
163 			    const struct mmc_clk_phase *phases,
164 			    struct aspeed_sdhci_tap_param *taps)
165 {
166 	taps->valid = phases->valid;
167 
168 	if (!phases->valid)
169 		return;
170 
171 	taps->in = aspeed_sdhci_phase_to_tap(dev, rate, phases->in_deg);
172 	taps->out = aspeed_sdhci_phase_to_tap(dev, rate, phases->out_deg);
173 }
174 
175 static void
176 aspeed_sdhci_configure_phase(struct sdhci_host *host, unsigned long rate)
177 {
178 	struct aspeed_sdhci_tap_param _taps = {0}, *taps = &_taps;
179 	struct mmc_clk_phase *params;
180 	struct aspeed_sdhci *sdhci;
181 	struct device *dev;
182 
183 	dev = host->mmc->parent;
184 	sdhci = sdhci_pltfm_priv(sdhci_priv(host));
185 
186 	if (!sdhci->phase_desc)
187 		return;
188 
189 	params = &sdhci->phase_map.phase[host->timing];
190 	aspeed_sdhci_phases_to_taps(dev, rate, params, taps);
191 	aspeed_sdc_set_phase_taps(sdhci->parent, sdhci->phase_desc, taps);
192 	dev_dbg(dev,
193 		"Using taps [%d, %d] for [%d, %d] degrees of phase correction at %luHz (%d)\n",
194 		taps->in & ASPEED_SDHCI_NR_TAPS,
195 		taps->out & ASPEED_SDHCI_NR_TAPS,
196 		params->in_deg, params->out_deg, rate, host->timing);
197 }
198 
199 static void aspeed_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
200 {
201 	struct sdhci_pltfm_host *pltfm_host;
202 	unsigned long parent, bus;
203 	int div;
204 	u16 clk;
205 
206 	pltfm_host = sdhci_priv(host);
207 	parent = clk_get_rate(pltfm_host->clk);
208 
209 	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
210 
211 	if (clock == 0)
212 		return;
213 
214 	if (WARN_ON(clock > host->max_clk))
215 		clock = host->max_clk;
216 
217 	for (div = 2; div < 256; div *= 2) {
218 		bus = parent / div;
219 		if (bus <= clock)
220 			break;
221 	}
222 
223 	div >>= 1;
224 
225 	clk = div << SDHCI_DIVIDER_SHIFT;
226 
227 	aspeed_sdhci_configure_phase(host, bus);
228 
229 	sdhci_enable_clk(host, clk);
230 }
231 
232 static unsigned int aspeed_sdhci_get_max_clock(struct sdhci_host *host)
233 {
234 	if (host->mmc->f_max)
235 		return host->mmc->f_max;
236 
237 	return sdhci_pltfm_clk_get_max_clock(host);
238 }
239 
240 static void aspeed_sdhci_set_bus_width(struct sdhci_host *host, int width)
241 {
242 	struct sdhci_pltfm_host *pltfm_priv;
243 	struct aspeed_sdhci *aspeed_sdhci;
244 	struct aspeed_sdc *aspeed_sdc;
245 	u8 ctrl;
246 
247 	pltfm_priv = sdhci_priv(host);
248 	aspeed_sdhci = sdhci_pltfm_priv(pltfm_priv);
249 	aspeed_sdc = aspeed_sdhci->parent;
250 
251 	/* Set/clear 8-bit mode */
252 	aspeed_sdc_configure_8bit_mode(aspeed_sdc, aspeed_sdhci,
253 				       width == MMC_BUS_WIDTH_8);
254 
255 	/* Set/clear 1 or 4 bit mode */
256 	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
257 	if (width == MMC_BUS_WIDTH_4)
258 		ctrl |= SDHCI_CTRL_4BITBUS;
259 	else
260 		ctrl &= ~SDHCI_CTRL_4BITBUS;
261 	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
262 }
263 
264 static u32 aspeed_sdhci_readl(struct sdhci_host *host, int reg)
265 {
266 	u32 val = readl(host->ioaddr + reg);
267 
268 	if (unlikely(reg == SDHCI_PRESENT_STATE) &&
269 	    (host->mmc->caps2 & MMC_CAP2_CD_ACTIVE_HIGH))
270 		val ^= SDHCI_CARD_PRESENT;
271 
272 	return val;
273 }
274 
275 static const struct sdhci_ops aspeed_sdhci_ops = {
276 	.read_l = aspeed_sdhci_readl,
277 	.set_clock = aspeed_sdhci_set_clock,
278 	.get_max_clock = aspeed_sdhci_get_max_clock,
279 	.set_bus_width = aspeed_sdhci_set_bus_width,
280 	.get_timeout_clock = sdhci_pltfm_clk_get_max_clock,
281 	.reset = sdhci_reset,
282 	.set_uhs_signaling = sdhci_set_uhs_signaling,
283 };
284 
285 static const struct sdhci_pltfm_data aspeed_sdhci_pdata = {
286 	.ops = &aspeed_sdhci_ops,
287 	.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
288 };
289 
290 static inline int aspeed_sdhci_calculate_slot(struct aspeed_sdhci *dev,
291 					      struct resource *res)
292 {
293 	resource_size_t delta;
294 
295 	if (!res || resource_type(res) != IORESOURCE_MEM)
296 		return -EINVAL;
297 
298 	if (res->start < dev->parent->res->start)
299 		return -EINVAL;
300 
301 	delta = res->start - dev->parent->res->start;
302 	if (delta & (0x100 - 1))
303 		return -EINVAL;
304 
305 	return (delta / 0x100) - 1;
306 }
307 
308 static int aspeed_sdhci_probe(struct platform_device *pdev)
309 {
310 	const struct aspeed_sdhci_pdata *aspeed_pdata;
311 	struct sdhci_pltfm_host *pltfm_host;
312 	struct aspeed_sdhci *dev;
313 	struct sdhci_host *host;
314 	struct resource *res;
315 	int slot;
316 	int ret;
317 
318 	aspeed_pdata = of_device_get_match_data(&pdev->dev);
319 
320 	host = sdhci_pltfm_init(pdev, &aspeed_sdhci_pdata, sizeof(*dev));
321 	if (IS_ERR(host))
322 		return PTR_ERR(host);
323 
324 	pltfm_host = sdhci_priv(host);
325 	dev = sdhci_pltfm_priv(pltfm_host);
326 	dev->pdata = aspeed_pdata;
327 	dev->parent = dev_get_drvdata(pdev->dev.parent);
328 
329 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
330 	slot = aspeed_sdhci_calculate_slot(dev, res);
331 
332 	if (slot < 0)
333 		return slot;
334 	else if (slot >= 2)
335 		return -EINVAL;
336 
337 	if (dev->pdata && slot < dev->pdata->nr_phase_descs) {
338 		dev->phase_desc = &dev->pdata->phase_desc[slot];
339 	} else {
340 		dev_info(&pdev->dev,
341 			 "Phase control not supported for slot %d\n", slot);
342 		dev->phase_desc = NULL;
343 	}
344 
345 	dev->width_mask = !slot ? ASPEED_SDC_S0_MMC8 : ASPEED_SDC_S1_MMC8;
346 
347 	dev_info(&pdev->dev, "Configured for slot %d\n", slot);
348 
349 	sdhci_get_of_property(pdev);
350 
351 	pltfm_host->clk = devm_clk_get(&pdev->dev, NULL);
352 	if (IS_ERR(pltfm_host->clk))
353 		return PTR_ERR(pltfm_host->clk);
354 
355 	ret = clk_prepare_enable(pltfm_host->clk);
356 	if (ret) {
357 		dev_err(&pdev->dev, "Unable to enable SDIO clock\n");
358 		goto err_pltfm_free;
359 	}
360 
361 	ret = mmc_of_parse(host->mmc);
362 	if (ret)
363 		goto err_sdhci_add;
364 
365 	if (dev->phase_desc)
366 		mmc_of_parse_clk_phase(host->mmc, &dev->phase_map);
367 
368 	ret = sdhci_add_host(host);
369 	if (ret)
370 		goto err_sdhci_add;
371 
372 	return 0;
373 
374 err_sdhci_add:
375 	clk_disable_unprepare(pltfm_host->clk);
376 err_pltfm_free:
377 	sdhci_pltfm_free(pdev);
378 	return ret;
379 }
380 
381 static int aspeed_sdhci_remove(struct platform_device *pdev)
382 {
383 	struct sdhci_pltfm_host *pltfm_host;
384 	struct sdhci_host *host;
385 	int dead = 0;
386 
387 	host = platform_get_drvdata(pdev);
388 	pltfm_host = sdhci_priv(host);
389 
390 	sdhci_remove_host(host, dead);
391 
392 	clk_disable_unprepare(pltfm_host->clk);
393 
394 	sdhci_pltfm_free(pdev);
395 
396 	return 0;
397 }
398 
399 static const struct aspeed_sdhci_phase_desc ast2600_sdhci_phase[] = {
400 	/* SDHCI/Slot 0 */
401 	[0] = {
402 		.in = {
403 			.tap_mask = ASPEED_SDC_S0_PHASE_IN,
404 			.enable_mask = ASPEED_SDC_S0_PHASE_IN_EN,
405 			.enable_value = 1,
406 		},
407 		.out = {
408 			.tap_mask = ASPEED_SDC_S0_PHASE_OUT,
409 			.enable_mask = ASPEED_SDC_S0_PHASE_OUT_EN,
410 			.enable_value = 3,
411 		},
412 	},
413 	/* SDHCI/Slot 1 */
414 	[1] = {
415 		.in = {
416 			.tap_mask = ASPEED_SDC_S1_PHASE_IN,
417 			.enable_mask = ASPEED_SDC_S1_PHASE_IN_EN,
418 			.enable_value = 1,
419 		},
420 		.out = {
421 			.tap_mask = ASPEED_SDC_S1_PHASE_OUT,
422 			.enable_mask = ASPEED_SDC_S1_PHASE_OUT_EN,
423 			.enable_value = 3,
424 		},
425 	},
426 };
427 
428 static const struct aspeed_sdhci_pdata ast2600_sdhci_pdata = {
429 	.phase_desc = ast2600_sdhci_phase,
430 	.nr_phase_descs = ARRAY_SIZE(ast2600_sdhci_phase),
431 };
432 
433 static const struct of_device_id aspeed_sdhci_of_match[] = {
434 	{ .compatible = "aspeed,ast2400-sdhci", },
435 	{ .compatible = "aspeed,ast2500-sdhci", },
436 	{ .compatible = "aspeed,ast2600-sdhci", .data = &ast2600_sdhci_pdata, },
437 	{ }
438 };
439 
440 static struct platform_driver aspeed_sdhci_driver = {
441 	.driver		= {
442 		.name	= "sdhci-aspeed",
443 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
444 		.of_match_table = aspeed_sdhci_of_match,
445 	},
446 	.probe		= aspeed_sdhci_probe,
447 	.remove		= aspeed_sdhci_remove,
448 };
449 
450 static int aspeed_sdc_probe(struct platform_device *pdev)
451 
452 {
453 	struct device_node *parent, *child;
454 	struct aspeed_sdc *sdc;
455 	int ret;
456 
457 	sdc = devm_kzalloc(&pdev->dev, sizeof(*sdc), GFP_KERNEL);
458 	if (!sdc)
459 		return -ENOMEM;
460 
461 	spin_lock_init(&sdc->lock);
462 
463 	sdc->clk = devm_clk_get(&pdev->dev, NULL);
464 	if (IS_ERR(sdc->clk))
465 		return PTR_ERR(sdc->clk);
466 
467 	ret = clk_prepare_enable(sdc->clk);
468 	if (ret) {
469 		dev_err(&pdev->dev, "Unable to enable SDCLK\n");
470 		return ret;
471 	}
472 
473 	sdc->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
474 	sdc->regs = devm_ioremap_resource(&pdev->dev, sdc->res);
475 	if (IS_ERR(sdc->regs)) {
476 		ret = PTR_ERR(sdc->regs);
477 		goto err_clk;
478 	}
479 
480 	dev_set_drvdata(&pdev->dev, sdc);
481 
482 	parent = pdev->dev.of_node;
483 	for_each_available_child_of_node(parent, child) {
484 		struct platform_device *cpdev;
485 
486 		cpdev = of_platform_device_create(child, NULL, &pdev->dev);
487 		if (!cpdev) {
488 			of_node_put(child);
489 			ret = -ENODEV;
490 			goto err_clk;
491 		}
492 	}
493 
494 	return 0;
495 
496 err_clk:
497 	clk_disable_unprepare(sdc->clk);
498 	return ret;
499 }
500 
501 static int aspeed_sdc_remove(struct platform_device *pdev)
502 {
503 	struct aspeed_sdc *sdc = dev_get_drvdata(&pdev->dev);
504 
505 	clk_disable_unprepare(sdc->clk);
506 
507 	return 0;
508 }
509 
510 static const struct of_device_id aspeed_sdc_of_match[] = {
511 	{ .compatible = "aspeed,ast2400-sd-controller", },
512 	{ .compatible = "aspeed,ast2500-sd-controller", },
513 	{ .compatible = "aspeed,ast2600-sd-controller", },
514 	{ }
515 };
516 
517 MODULE_DEVICE_TABLE(of, aspeed_sdc_of_match);
518 
519 static struct platform_driver aspeed_sdc_driver = {
520 	.driver		= {
521 		.name	= "sd-controller-aspeed",
522 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
523 		.pm	= &sdhci_pltfm_pmops,
524 		.of_match_table = aspeed_sdc_of_match,
525 	},
526 	.probe		= aspeed_sdc_probe,
527 	.remove		= aspeed_sdc_remove,
528 };
529 
530 static int __init aspeed_sdc_init(void)
531 {
532 	int rc;
533 
534 	rc = platform_driver_register(&aspeed_sdhci_driver);
535 	if (rc < 0)
536 		return rc;
537 
538 	rc = platform_driver_register(&aspeed_sdc_driver);
539 	if (rc < 0)
540 		platform_driver_unregister(&aspeed_sdhci_driver);
541 
542 	return rc;
543 }
544 module_init(aspeed_sdc_init);
545 
546 static void __exit aspeed_sdc_exit(void)
547 {
548 	platform_driver_unregister(&aspeed_sdc_driver);
549 	platform_driver_unregister(&aspeed_sdhci_driver);
550 }
551 module_exit(aspeed_sdc_exit);
552 
553 MODULE_DESCRIPTION("Driver for the ASPEED SD/SDIO/SDHCI Controllers");
554 MODULE_AUTHOR("Ryan Chen <ryan_chen@aspeedtech.com>");
555 MODULE_AUTHOR("Andrew Jeffery <andrew@aj.id.au>");
556 MODULE_LICENSE("GPL");
557