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