1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2012 Thomas Skibo
5 * Copyright (c) 2008 Alexander Motin <mav@FreeBSD.org>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /* Generic driver to attach sdhci controllers on simplebus.
30 * Derived mainly from sdhci_pci.c
31 */
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/bus.h>
36 #include <sys/kernel.h>
37 #include <sys/lock.h>
38 #include <sys/module.h>
39 #include <sys/mutex.h>
40 #include <sys/resource.h>
41 #include <sys/rman.h>
42 #include <sys/sysctl.h>
43 #include <sys/taskqueue.h>
44
45 #include <machine/bus.h>
46 #include <machine/resource.h>
47
48 #include <dev/fdt/fdt_common.h>
49 #include <dev/ofw/ofw_bus.h>
50 #include <dev/ofw/ofw_bus_subr.h>
51
52 #include <dev/ofw/ofw_subr.h>
53 #include <dev/clk/clk.h>
54 #include <dev/clk/clk_fixed.h>
55 #include <dev/syscon/syscon.h>
56 #include <dev/phy/phy.h>
57
58 #include <dev/mmc/bridge.h>
59
60 #include <dev/sdhci/sdhci.h>
61
62 #include "mmcbr_if.h"
63 #include "sdhci_if.h"
64
65 #include "opt_mmccam.h"
66
67 #include "clkdev_if.h"
68 #include "syscon_if.h"
69
70 #define MAX_SLOTS 6
71 #define SDHCI_FDT_ARMADA38X 1
72 #define SDHCI_FDT_XLNX_ZY7 2
73 #define SDHCI_FDT_QUALCOMM 3
74 #define SDHCI_FDT_RK3399 4
75 #define SDHCI_FDT_RK3568 5
76 #define SDHCI_FDT_XLNX_ZMP 6
77
78 #define RK3399_GRF_EMMCCORE_CON0 0xf000
79 #define RK3399_CORECFG_BASECLKFREQ 0xff00
80 #define RK3399_CORECFG_TIMEOUTCLKUNIT (1 << 7)
81 #define RK3399_CORECFG_TUNINGCOUNT 0x3f
82 #define RK3399_GRF_EMMCCORE_CON11 0xf02c
83 #define RK3399_CORECFG_CLOCKMULTIPLIER 0xff
84
85 #define RK3568_EMMC_HOST_CTRL 0x0508
86 #define RK3568_EMMC_EMMC_CTRL 0x052c
87 #define RK3568_EMMC_ATCTRL 0x0540
88 #define RK3568_EMMC_DLL_CTRL 0x0800
89 #define DLL_CTRL_SRST 0x00000001
90 #define DLL_CTRL_START 0x00000002
91 #define DLL_CTRL_START_POINT_DEFAULT 0x00050000
92 #define DLL_CTRL_INCREMENT_DEFAULT 0x00000200
93
94 #define RK3568_EMMC_DLL_RXCLK 0x0804
95 #define DLL_RXCLK_DELAY_ENABLE 0x08000000
96 #define DLL_RXCLK_NO_INV 0x20000000
97
98 #define RK3568_EMMC_DLL_TXCLK 0x0808
99 #define DLL_TXCLK_DELAY_ENABLE 0x08000000
100 #define DLL_TXCLK_TAPNUM_DEFAULT 0x00000008
101 #define DLL_TXCLK_TAPNUM_FROM_SW 0x01000000
102
103 #define RK3568_EMMC_DLL_STRBIN 0x080c
104 #define DLL_STRBIN_DELAY_ENABLE 0x08000000
105 #define DLL_STRBIN_TAPNUM_DEFAULT 0x00000008
106 #define DLL_STRBIN_TAPNUM_FROM_SW 0x01000000
107
108 #define RK3568_EMMC_DLL_STATUS0 0x0840
109 #define DLL_STATUS0_DLL_LOCK 0x00000100
110 #define DLL_STATUS0_DLL_TIMEOUT 0x00000200
111
112 #define LOWEST_SET_BIT(mask) ((((mask) - 1) & (mask)) ^ (mask))
113 #define SHIFTIN(x, mask) ((x) * LOWEST_SET_BIT(mask))
114
115 static struct ofw_compat_data compat_data[] = {
116 { "marvell,armada-380-sdhci", SDHCI_FDT_ARMADA38X },
117 { "qcom,sdhci-msm-v4", SDHCI_FDT_QUALCOMM },
118 { "rockchip,rk3399-sdhci-5.1", SDHCI_FDT_RK3399 },
119 { "xlnx,zy7_sdhci", SDHCI_FDT_XLNX_ZY7 },
120 { "rockchip,rk3568-dwcmshc", SDHCI_FDT_RK3568 },
121 { "xlnx,zynqmp-8.9a", SDHCI_FDT_XLNX_ZMP },
122 { NULL, 0 }
123 };
124
125 struct sdhci_fdt_softc {
126 device_t dev; /* Controller device */
127 u_int quirks; /* Chip specific quirks */
128 u_int caps; /* If we override SDHCI_CAPABILITIES */
129 uint32_t max_clk; /* Max possible freq */
130 uint8_t sdma_boundary; /* If we override the SDMA boundary */
131 struct resource *irq_res; /* IRQ resource */
132 void *intrhand; /* Interrupt handle */
133
134 int num_slots; /* Number of slots on this controller*/
135 struct sdhci_slot slots[MAX_SLOTS];
136 struct resource *mem_res[MAX_SLOTS]; /* Memory resource */
137
138 bool wp_inverted; /* WP pin is inverted */
139 bool wp_disabled; /* WP pin is not supported */
140 bool no_18v; /* No 1.8V support */
141
142 clk_t clk_xin; /* xin24m fixed clock */
143 clk_t clk_ahb; /* ahb clock */
144 clk_t clk_core; /* core clock */
145 phy_t phy; /* phy to be used */
146
147 struct syscon *syscon; /* Handle to the syscon */
148 };
149
150 struct sdhci_exported_clocks_sc {
151 device_t clkdev;
152 };
153
154 static int
sdhci_exported_clocks_init(struct clknode * clk,device_t dev)155 sdhci_exported_clocks_init(struct clknode *clk, device_t dev)
156 {
157
158 clknode_init_parent_idx(clk, 0);
159 return (0);
160 }
161
162 static clknode_method_t sdhci_exported_clocks_clknode_methods[] = {
163 /* Device interface */
164 CLKNODEMETHOD(clknode_init, sdhci_exported_clocks_init),
165 CLKNODEMETHOD_END
166 };
167 DEFINE_CLASS_1(sdhci_exported_clocks_clknode, sdhci_exported_clocks_clknode_class,
168 sdhci_exported_clocks_clknode_methods, sizeof(struct sdhci_exported_clocks_sc),
169 clknode_class);
170
171 static int
sdhci_clock_ofw_map(struct clkdom * clkdom,uint32_t ncells,phandle_t * cells,struct clknode ** clk)172 sdhci_clock_ofw_map(struct clkdom *clkdom, uint32_t ncells,
173 phandle_t *cells, struct clknode **clk)
174 {
175 int id = 1; /* Our clock id starts at 1 */
176
177 if (ncells != 0)
178 id = cells[1];
179 *clk = clknode_find_by_id(clkdom, id);
180
181 if (*clk == NULL)
182 return (ENXIO);
183 return (0);
184 }
185
186 static void
sdhci_export_clocks(struct sdhci_fdt_softc * sc)187 sdhci_export_clocks(struct sdhci_fdt_softc *sc)
188 {
189 struct clknode_init_def def;
190 struct sdhci_exported_clocks_sc *clksc;
191 struct clkdom *clkdom;
192 struct clknode *clk;
193 bus_addr_t paddr;
194 bus_size_t psize;
195 const char **clknames;
196 phandle_t node;
197 int i, nclocks, ncells, error;
198
199 node = ofw_bus_get_node(sc->dev);
200
201 if (ofw_reg_to_paddr(node, 0, &paddr, &psize, NULL) != 0) {
202 device_printf(sc->dev, "cannot parse 'reg' property\n");
203 return;
204 }
205
206 error = ofw_bus_parse_xref_list_get_length(node, "clocks",
207 "#clock-cells", &ncells);
208 if (error != 0 || ncells != 2) {
209 device_printf(sc->dev, "couldn't find parent clocks\n");
210 return;
211 }
212
213 nclocks = ofw_bus_string_list_to_array(node, "clock-output-names",
214 &clknames);
215 /* No clocks to export */
216 if (nclocks <= 0)
217 return;
218
219 clkdom = clkdom_create(sc->dev);
220 clkdom_set_ofw_mapper(clkdom, sdhci_clock_ofw_map);
221
222 for (i = 0; i < nclocks; i++) {
223 memset(&def, 0, sizeof(def));
224 def.id = i + 1; /* Exported clock IDs starts at 1 */
225 def.name = clknames[i];
226 def.parent_names = malloc(sizeof(char *) * 1, M_OFWPROP, M_WAITOK);
227 def.parent_names[0] = clk_get_name(sc->clk_xin);
228 def.parent_cnt = 1;
229
230 clk = clknode_create(clkdom, &sdhci_exported_clocks_clknode_class, &def);
231 if (clk == NULL) {
232 device_printf(sc->dev, "cannot create clknode\n");
233 return;
234 }
235
236 clksc = clknode_get_softc(clk);
237 clksc->clkdev = device_get_parent(sc->dev);
238
239 clknode_register(clkdom, clk);
240 }
241
242 if (clkdom_finit(clkdom) != 0) {
243 device_printf(sc->dev, "cannot finalize clkdom initialization\n");
244 return;
245 }
246
247 if (bootverbose)
248 clkdom_dump(clkdom);
249 }
250
251 static int
sdhci_init_clocks(device_t dev)252 sdhci_init_clocks(device_t dev)
253 {
254 struct sdhci_fdt_softc *sc = device_get_softc(dev);
255 int error;
256
257 /* Get and activate clocks */
258 error = clk_get_by_ofw_name(dev, 0, "clk_xin", &sc->clk_xin);
259 if (error != 0) {
260 device_printf(dev, "cannot get xin clock\n");
261 return (ENXIO);
262 }
263 error = clk_enable(sc->clk_xin);
264 if (error != 0) {
265 device_printf(dev, "cannot enable xin clock\n");
266 return (ENXIO);
267 }
268 error = clk_get_by_ofw_name(dev, 0, "clk_ahb", &sc->clk_ahb);
269 if (error != 0) {
270 device_printf(dev, "cannot get ahb clock\n");
271 return (ENXIO);
272 }
273 error = clk_enable(sc->clk_ahb);
274 if (error != 0) {
275 device_printf(dev, "cannot enable ahb clock\n");
276 return (ENXIO);
277 }
278
279 return (0);
280 }
281
282 static int
sdhci_init_phy(struct sdhci_fdt_softc * sc)283 sdhci_init_phy(struct sdhci_fdt_softc *sc)
284 {
285 int error;
286
287 /* Enable PHY */
288 error = phy_get_by_ofw_name(sc->dev, 0, "phy_arasan", &sc->phy);
289 if (error == ENOENT)
290 return (0);
291 if (error != 0) {
292 device_printf(sc->dev, "Could not get phy\n");
293 return (ENXIO);
294 }
295 error = phy_enable(sc->phy);
296 if (error != 0) {
297 device_printf(sc->dev, "Could not enable phy\n");
298 return (ENXIO);
299 }
300
301 return (0);
302 }
303
304 static int
sdhci_get_syscon(struct sdhci_fdt_softc * sc)305 sdhci_get_syscon(struct sdhci_fdt_softc *sc)
306 {
307 phandle_t node;
308
309 /* Get syscon */
310 node = ofw_bus_get_node(sc->dev);
311 if (OF_hasprop(node, "arasan,soc-ctl-syscon") &&
312 syscon_get_by_ofw_property(sc->dev, node,
313 "arasan,soc-ctl-syscon", &sc->syscon) != 0) {
314 device_printf(sc->dev, "cannot get syscon handle\n");
315 return (ENXIO);
316 }
317
318 return (0);
319 }
320
321 static int
sdhci_init_rk3399(device_t dev)322 sdhci_init_rk3399(device_t dev)
323 {
324 struct sdhci_fdt_softc *sc = device_get_softc(dev);
325 uint64_t freq;
326 uint32_t mask, val;
327 int error;
328
329 error = clk_get_freq(sc->clk_xin, &freq);
330 if (error != 0) {
331 device_printf(dev, "cannot get xin clock frequency\n");
332 return (ENXIO);
333 }
334
335 /* Disable clock multiplier */
336 mask = RK3399_CORECFG_CLOCKMULTIPLIER;
337 val = 0;
338 SYSCON_WRITE_4(sc->syscon, RK3399_GRF_EMMCCORE_CON11, (mask << 16) | val);
339
340 /* Set base clock frequency */
341 mask = RK3399_CORECFG_BASECLKFREQ;
342 val = SHIFTIN((freq + (1000000 / 2)) / 1000000,
343 RK3399_CORECFG_BASECLKFREQ);
344 SYSCON_WRITE_4(sc->syscon, RK3399_GRF_EMMCCORE_CON0, (mask << 16) | val);
345
346 return (0);
347 }
348
349 static uint8_t
sdhci_fdt_read_1(device_t dev,struct sdhci_slot * slot,bus_size_t off)350 sdhci_fdt_read_1(device_t dev, struct sdhci_slot *slot, bus_size_t off)
351 {
352 struct sdhci_fdt_softc *sc = device_get_softc(dev);
353
354 return (bus_read_1(sc->mem_res[slot->num], off));
355 }
356
357 static void
sdhci_fdt_write_1(device_t dev,struct sdhci_slot * slot,bus_size_t off,uint8_t val)358 sdhci_fdt_write_1(device_t dev, struct sdhci_slot *slot, bus_size_t off,
359 uint8_t val)
360 {
361 struct sdhci_fdt_softc *sc = device_get_softc(dev);
362
363 bus_write_1(sc->mem_res[slot->num], off, val);
364 }
365
366 static uint16_t
sdhci_fdt_read_2(device_t dev,struct sdhci_slot * slot,bus_size_t off)367 sdhci_fdt_read_2(device_t dev, struct sdhci_slot *slot, bus_size_t off)
368 {
369 struct sdhci_fdt_softc *sc = device_get_softc(dev);
370
371 return (bus_read_2(sc->mem_res[slot->num], off));
372 }
373
374 static void
sdhci_fdt_write_2(device_t dev,struct sdhci_slot * slot,bus_size_t off,uint16_t val)375 sdhci_fdt_write_2(device_t dev, struct sdhci_slot *slot, bus_size_t off,
376 uint16_t val)
377 {
378 struct sdhci_fdt_softc *sc = device_get_softc(dev);
379
380 bus_write_2(sc->mem_res[slot->num], off, val);
381 }
382
383 static uint32_t
sdhci_fdt_read_4(device_t dev,struct sdhci_slot * slot,bus_size_t off)384 sdhci_fdt_read_4(device_t dev, struct sdhci_slot *slot, bus_size_t off)
385 {
386 struct sdhci_fdt_softc *sc = device_get_softc(dev);
387 uint32_t val32;
388
389 val32 = bus_read_4(sc->mem_res[slot->num], off);
390 if (off == SDHCI_CAPABILITIES && sc->no_18v)
391 val32 &= ~SDHCI_CAN_VDD_180;
392
393 return (val32);
394 }
395
396 static void
sdhci_fdt_write_4(device_t dev,struct sdhci_slot * slot,bus_size_t off,uint32_t val)397 sdhci_fdt_write_4(device_t dev, struct sdhci_slot *slot, bus_size_t off,
398 uint32_t val)
399 {
400 struct sdhci_fdt_softc *sc = device_get_softc(dev);
401
402 bus_write_4(sc->mem_res[slot->num], off, val);
403 }
404
405 static void
sdhci_fdt_read_multi_4(device_t dev,struct sdhci_slot * slot,bus_size_t off,uint32_t * data,bus_size_t count)406 sdhci_fdt_read_multi_4(device_t dev, struct sdhci_slot *slot,
407 bus_size_t off, uint32_t *data, bus_size_t count)
408 {
409 struct sdhci_fdt_softc *sc = device_get_softc(dev);
410
411 bus_read_multi_4(sc->mem_res[slot->num], off, data, count);
412 }
413
414 static void
sdhci_fdt_write_multi_4(device_t dev,struct sdhci_slot * slot,bus_size_t off,uint32_t * data,bus_size_t count)415 sdhci_fdt_write_multi_4(device_t dev, struct sdhci_slot *slot,
416 bus_size_t off, uint32_t *data, bus_size_t count)
417 {
418 struct sdhci_fdt_softc *sc = device_get_softc(dev);
419
420 bus_write_multi_4(sc->mem_res[slot->num], off, data, count);
421 }
422
423 static void
sdhci_fdt_intr(void * arg)424 sdhci_fdt_intr(void *arg)
425 {
426 struct sdhci_fdt_softc *sc = (struct sdhci_fdt_softc *)arg;
427 int i;
428
429 for (i = 0; i < sc->num_slots; i++)
430 sdhci_generic_intr(&sc->slots[i]);
431 }
432
433 static int
sdhci_fdt_get_ro(device_t bus,device_t dev)434 sdhci_fdt_get_ro(device_t bus, device_t dev)
435 {
436 struct sdhci_fdt_softc *sc = device_get_softc(bus);
437
438 if (sc->wp_disabled)
439 return (false);
440 return (sdhci_generic_get_ro(bus, dev) ^ sc->wp_inverted);
441 }
442
443 static int
sdhci_fdt_set_clock(device_t dev,struct sdhci_slot * slot,int clock)444 sdhci_fdt_set_clock(device_t dev, struct sdhci_slot *slot, int clock)
445 {
446 struct sdhci_fdt_softc *sc = device_get_softc(dev);
447 int32_t val;
448 int i;
449
450 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data ==
451 SDHCI_FDT_RK3568) {
452 if (clock == 400000)
453 clock = 375000;
454
455 if (clock) {
456 clk_set_freq(sc->clk_core, clock, 0);
457
458 if (clock <= 52000000) {
459 bus_write_4(sc->mem_res[slot->num],
460 RK3568_EMMC_DLL_CTRL, 0x0);
461 bus_write_4(sc->mem_res[slot->num],
462 RK3568_EMMC_DLL_RXCLK, DLL_RXCLK_NO_INV);
463 bus_write_4(sc->mem_res[slot->num],
464 RK3568_EMMC_DLL_TXCLK, 0x0);
465 bus_write_4(sc->mem_res[slot->num],
466 RK3568_EMMC_DLL_STRBIN, 0x0);
467 return (clock);
468 }
469
470 bus_write_4(sc->mem_res[slot->num],
471 RK3568_EMMC_DLL_CTRL, DLL_CTRL_START);
472 DELAY(1000);
473 bus_write_4(sc->mem_res[slot->num],
474 RK3568_EMMC_DLL_CTRL, 0);
475 bus_write_4(sc->mem_res[slot->num],
476 RK3568_EMMC_DLL_CTRL, DLL_CTRL_START_POINT_DEFAULT |
477 DLL_CTRL_INCREMENT_DEFAULT | DLL_CTRL_START);
478 for (i = 0; i < 500; i++) {
479 val = bus_read_4(sc->mem_res[slot->num],
480 RK3568_EMMC_DLL_STATUS0);
481 if (val & DLL_STATUS0_DLL_LOCK &&
482 !(val & DLL_STATUS0_DLL_TIMEOUT))
483 break;
484 DELAY(1000);
485 }
486 bus_write_4(sc->mem_res[slot->num], RK3568_EMMC_ATCTRL,
487 (0x1 << 16 | 0x2 << 17 | 0x3 << 19));
488 bus_write_4(sc->mem_res[slot->num],
489 RK3568_EMMC_DLL_RXCLK,
490 DLL_RXCLK_DELAY_ENABLE | DLL_RXCLK_NO_INV);
491 bus_write_4(sc->mem_res[slot->num],
492 RK3568_EMMC_DLL_TXCLK, DLL_TXCLK_DELAY_ENABLE |
493 DLL_TXCLK_TAPNUM_DEFAULT|DLL_TXCLK_TAPNUM_FROM_SW);
494 bus_write_4(sc->mem_res[slot->num],
495 RK3568_EMMC_DLL_STRBIN, DLL_STRBIN_DELAY_ENABLE |
496 DLL_STRBIN_TAPNUM_DEFAULT |
497 DLL_STRBIN_TAPNUM_FROM_SW);
498 }
499 }
500 return (clock);
501 }
502
503 static int
sdhci_fdt_probe(device_t dev)504 sdhci_fdt_probe(device_t dev)
505 {
506 struct sdhci_fdt_softc *sc = device_get_softc(dev);
507 phandle_t node;
508 pcell_t cid;
509
510 sc->quirks = 0;
511 sc->num_slots = 1;
512 sc->max_clk = 0;
513
514 if (!ofw_bus_status_okay(dev))
515 return (ENXIO);
516
517 switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data) {
518 case SDHCI_FDT_ARMADA38X:
519 sc->quirks = SDHCI_QUIRK_BROKEN_AUTO_STOP;
520 device_set_desc(dev, "ARMADA38X SDHCI controller");
521 break;
522 case SDHCI_FDT_QUALCOMM:
523 sc->quirks = SDHCI_QUIRK_ALL_SLOTS_NON_REMOVABLE |
524 SDHCI_QUIRK_BROKEN_SDMA_BOUNDARY;
525 sc->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_4K;
526 device_set_desc(dev, "Qualcomm FDT SDHCI controller");
527 break;
528 case SDHCI_FDT_RK3399:
529 device_set_desc(dev, "Rockchip RK3399 fdt SDHCI controller");
530 break;
531 case SDHCI_FDT_XLNX_ZY7:
532 sc->quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK;
533 device_set_desc(dev, "Zynq-7000 generic fdt SDHCI controller");
534 break;
535 case SDHCI_FDT_RK3568:
536 device_set_desc(dev, "Rockchip RK3568 fdt SDHCI controller");
537 break;
538 case SDHCI_FDT_XLNX_ZMP:
539 device_set_desc(dev, "ZynqMP generic fdt SDHCI controller");
540 break;
541 default:
542 return (ENXIO);
543 }
544
545 node = ofw_bus_get_node(dev);
546
547 /* Allow dts to patch quirks, slots, and max-frequency. */
548 if ((OF_getencprop(node, "quirks", &cid, sizeof(cid))) > 0)
549 sc->quirks = cid;
550 if ((OF_getencprop(node, "num-slots", &cid, sizeof(cid))) > 0)
551 sc->num_slots = cid;
552 if ((OF_getencprop(node, "max-frequency", &cid, sizeof(cid))) > 0)
553 sc->max_clk = cid;
554 if (OF_hasprop(node, "no-1-8-v"))
555 sc->no_18v = true;
556 if (OF_hasprop(node, "wp-inverted"))
557 sc->wp_inverted = true;
558 if (OF_hasprop(node, "disable-wp"))
559 sc->wp_disabled = true;
560
561 return (0);
562 }
563
564 static int
sdhci_fdt_attach(device_t dev)565 sdhci_fdt_attach(device_t dev)
566 {
567 struct sdhci_fdt_softc *sc = device_get_softc(dev);
568 struct sdhci_slot *slot;
569 int err, slots, rid, i, compat;
570
571 sc->dev = dev;
572
573 /* Allocate IRQ. */
574 rid = 0;
575 sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
576 RF_ACTIVE);
577 if (sc->irq_res == NULL) {
578 device_printf(dev, "Can't allocate IRQ\n");
579 return (ENOMEM);
580 }
581
582 compat = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
583 switch (compat) {
584 case SDHCI_FDT_RK3399:
585 case SDHCI_FDT_XLNX_ZMP:
586 err = sdhci_init_clocks(dev);
587 if (err != 0) {
588 device_printf(dev, "Cannot init clocks\n");
589 return (err);
590 }
591 sdhci_export_clocks(sc);
592 if ((err = sdhci_init_phy(sc)) != 0) {
593 device_printf(dev, "Cannot init phy\n");
594 return (err);
595 }
596 if ((err = sdhci_get_syscon(sc)) != 0) {
597 device_printf(dev, "Cannot get syscon handle\n");
598 return (err);
599 }
600 if (compat == SDHCI_FDT_RK3399) {
601 err = sdhci_init_rk3399(dev);
602 if (err != 0) {
603 device_printf(dev, "Cannot init RK3399 SDHCI\n");
604 return (err);
605 }
606 }
607 break;
608 case SDHCI_FDT_RK3568:
609 /* setup & enable clocks */
610 if (clk_get_by_ofw_name(dev, 0, "core", &sc->clk_core)) {
611 device_printf(dev, "cannot get core clock\n");
612 return (ENXIO);
613 }
614 clk_enable(sc->clk_core);
615 break;
616 default:
617 break;
618 }
619
620 /* Scan all slots. */
621 slots = sc->num_slots; /* number of slots determined in probe(). */
622 sc->num_slots = 0;
623 for (i = 0; i < slots; i++) {
624 slot = &sc->slots[sc->num_slots];
625
626 /* Allocate memory. */
627 rid = 0;
628 sc->mem_res[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
629 &rid, RF_ACTIVE);
630 if (sc->mem_res[i] == NULL) {
631 device_printf(dev,
632 "Can't allocate memory for slot %d\n", i);
633 continue;
634 }
635
636 slot->quirks = sc->quirks;
637 slot->caps = sc->caps;
638 slot->max_clk = sc->max_clk;
639 slot->sdma_boundary = sc->sdma_boundary;
640
641 if (sdhci_init_slot(dev, slot, i) != 0)
642 continue;
643
644 sc->num_slots++;
645 }
646 device_printf(dev, "%d slot(s) allocated\n", sc->num_slots);
647
648 /* Activate the interrupt */
649 err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
650 NULL, sdhci_fdt_intr, sc, &sc->intrhand);
651 if (err) {
652 device_printf(dev, "Cannot setup IRQ\n");
653 return (err);
654 }
655
656 /* Process cards detection. */
657 for (i = 0; i < sc->num_slots; i++)
658 sdhci_start_slot(&sc->slots[i]);
659
660 return (0);
661 }
662
663 static int
sdhci_fdt_detach(device_t dev)664 sdhci_fdt_detach(device_t dev)
665 {
666 struct sdhci_fdt_softc *sc = device_get_softc(dev);
667 int i;
668
669 bus_generic_detach(dev);
670 bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
671 bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq_res),
672 sc->irq_res);
673
674 for (i = 0; i < sc->num_slots; i++) {
675 sdhci_cleanup_slot(&sc->slots[i]);
676 bus_release_resource(dev, SYS_RES_MEMORY,
677 rman_get_rid(sc->mem_res[i]), sc->mem_res[i]);
678 }
679
680 return (0);
681 }
682
683 static device_method_t sdhci_fdt_methods[] = {
684 /* device_if */
685 DEVMETHOD(device_probe, sdhci_fdt_probe),
686 DEVMETHOD(device_attach, sdhci_fdt_attach),
687 DEVMETHOD(device_detach, sdhci_fdt_detach),
688
689 /* Bus interface */
690 DEVMETHOD(bus_read_ivar, sdhci_generic_read_ivar),
691 DEVMETHOD(bus_write_ivar, sdhci_generic_write_ivar),
692
693 /* mmcbr_if */
694 DEVMETHOD(mmcbr_update_ios, sdhci_generic_update_ios),
695 DEVMETHOD(mmcbr_request, sdhci_generic_request),
696 DEVMETHOD(mmcbr_get_ro, sdhci_fdt_get_ro),
697 DEVMETHOD(mmcbr_acquire_host, sdhci_generic_acquire_host),
698 DEVMETHOD(mmcbr_release_host, sdhci_generic_release_host),
699
700 /* SDHCI registers accessors */
701 DEVMETHOD(sdhci_read_1, sdhci_fdt_read_1),
702 DEVMETHOD(sdhci_read_2, sdhci_fdt_read_2),
703 DEVMETHOD(sdhci_read_4, sdhci_fdt_read_4),
704 DEVMETHOD(sdhci_read_multi_4, sdhci_fdt_read_multi_4),
705 DEVMETHOD(sdhci_write_1, sdhci_fdt_write_1),
706 DEVMETHOD(sdhci_write_2, sdhci_fdt_write_2),
707 DEVMETHOD(sdhci_write_4, sdhci_fdt_write_4),
708 DEVMETHOD(sdhci_write_multi_4, sdhci_fdt_write_multi_4),
709 DEVMETHOD(sdhci_set_clock, sdhci_fdt_set_clock),
710
711 DEVMETHOD_END
712 };
713
714 static driver_t sdhci_fdt_driver = {
715 "sdhci_fdt",
716 sdhci_fdt_methods,
717 sizeof(struct sdhci_fdt_softc),
718 };
719
720 DRIVER_MODULE(sdhci_fdt, simplebus, sdhci_fdt_driver, NULL, NULL);
721 SDHCI_DEPEND(sdhci_fdt);
722 #ifndef MMCCAM
723 MMC_DECLARE_BRIDGE(sdhci_fdt);
724 #endif
725