sdhci_xenon.c (8a8166e5bcfb50e2b7280581b600d098fa6c9fc7) sdhci_xenon.c (d78e464d23304084be17cb8db8981558f2829d6c)
1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2018 Rubicon Communications, LLC (Netgate)
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 34 unchanged lines hidden (view full) ---

43#include <sys/rman.h>
44#include <sys/sysctl.h>
45#include <sys/taskqueue.h>
46
47#include <machine/bus.h>
48#include <machine/resource.h>
49
50#include <dev/extres/regulator/regulator.h>
1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2018 Rubicon Communications, LLC (Netgate)
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 34 unchanged lines hidden (view full) ---

43#include <sys/rman.h>
44#include <sys/sysctl.h>
45#include <sys/taskqueue.h>
46
47#include <machine/bus.h>
48#include <machine/resource.h>
49
50#include <dev/extres/regulator/regulator.h>
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/mmc/bridge.h>
51
52#include <dev/mmc/bridge.h>
56#include <dev/mmc/mmc_fdt_helpers.h>
57#include <dev/mmc/mmcbrvar.h>
58#include <dev/mmc/mmcreg.h>
59
60#include <dev/sdhci/sdhci.h>
53#include <dev/mmc/mmcbrvar.h>
54#include <dev/mmc/mmcreg.h>
55
56#include <dev/sdhci/sdhci.h>
61#include <dev/sdhci/sdhci_fdt_gpio.h>
62#include <dev/sdhci/sdhci_xenon.h>
63
64#include "mmcbr_if.h"
65#include "sdhci_if.h"
66
67#include "opt_mmccam.h"
68#include "opt_soc.h"
69
70#define MAX_SLOTS 6
71
57#include <dev/sdhci/sdhci_xenon.h>
58
59#include "mmcbr_if.h"
60#include "sdhci_if.h"
61
62#include "opt_mmccam.h"
63#include "opt_soc.h"
64
65#define MAX_SLOTS 6
66
72static struct ofw_compat_data compat_data[] = {
73 { "marvell,armada-3700-sdhci", 1 },
74#ifdef SOC_MARVELL_8K
75 { "marvell,armada-cp110-sdhci", 1 },
76 { "marvell,armada-ap806-sdhci", 1 },
77 { "marvell,armada-ap807-sdhci", 1 },
78#endif
79 { NULL, 0 }
80};
81
82struct sdhci_xenon_softc {
83 device_t dev; /* Controller device */
84 int slot_id; /* Controller ID */
85 phandle_t node; /* FDT node */
86 struct resource *irq_res; /* IRQ resource */
87 void *intrhand; /* Interrupt handle */
88 struct sdhci_fdt_gpio *gpio; /* GPIO pins for CD detection. */
89
90 struct sdhci_slot *slot; /* SDHCI internal data */
91 struct resource *mem_res; /* Memory resource */
92
93 uint8_t znr; /* PHY ZNR */
94 uint8_t zpr; /* PHY ZPR */
95 bool slow_mode; /* PHY slow mode */
96
97 struct mmc_helper mmc_helper; /* MMC helper for parsing FDT */
98};
99
100static uint8_t
101sdhci_xenon_read_1(device_t dev, struct sdhci_slot *slot __unused,
102 bus_size_t off)
103{
104 struct sdhci_xenon_softc *sc = device_get_softc(dev);
105
106 return (bus_read_1(sc->mem_res, off));
107}

--- 69 unchanged lines hidden (view full) ---

177 sdhci_generic_intr(sc->slot);
178}
179
180static int
181sdhci_xenon_get_ro(device_t bus, device_t dev)
182{
183 struct sdhci_xenon_softc *sc = device_get_softc(bus);
184
67static uint8_t
68sdhci_xenon_read_1(device_t dev, struct sdhci_slot *slot __unused,
69 bus_size_t off)
70{
71 struct sdhci_xenon_softc *sc = device_get_softc(dev);
72
73 return (bus_read_1(sc->mem_res, off));
74}

--- 69 unchanged lines hidden (view full) ---

144 sdhci_generic_intr(sc->slot);
145}
146
147static int
148sdhci_xenon_get_ro(device_t bus, device_t dev)
149{
150 struct sdhci_xenon_softc *sc = device_get_softc(bus);
151
185 return (sdhci_generic_get_ro(bus, dev) ^
186 (sc->mmc_helper.props & MMC_PROP_WP_INVERTED));
152 return (sdhci_generic_get_ro(bus, dev) ^ sc->wp_inverted);
187}
188
153}
154
189static bool
190sdhci_xenon_get_card_present(device_t dev, struct sdhci_slot *slot)
191{
192 struct sdhci_xenon_softc *sc = device_get_softc(dev);
193
194 return (sdhci_fdt_gpio_get_present(sc->gpio));
195}
196
197static void
198sdhci_xenon_set_uhs_timing(device_t brdev, struct sdhci_slot *slot)
199{
200 const struct mmc_ios *ios;
201 uint16_t hostctrl2;
202
203 if (slot->version < SDHCI_SPEC_300)
204 return;

--- 177 unchanged lines hidden (view full) ---

382
383 switch (ios->power_mode) {
384 case power_on:
385 break;
386 case power_off:
387 if (bootverbose)
388 device_printf(sc->dev, "Powering down sd/mmc\n");
389
155static void
156sdhci_xenon_set_uhs_timing(device_t brdev, struct sdhci_slot *slot)
157{
158 const struct mmc_ios *ios;
159 uint16_t hostctrl2;
160
161 if (slot->version < SDHCI_SPEC_300)
162 return;

--- 177 unchanged lines hidden (view full) ---

340
341 switch (ios->power_mode) {
342 case power_on:
343 break;
344 case power_off:
345 if (bootverbose)
346 device_printf(sc->dev, "Powering down sd/mmc\n");
347
390 if (sc->mmc_helper.vmmc_supply)
391 regulator_disable(sc->mmc_helper.vmmc_supply);
392 if (sc->mmc_helper.vqmmc_supply)
393 regulator_disable(sc->mmc_helper.vqmmc_supply);
348 if (sc->vmmc_supply)
349 regulator_disable(sc->vmmc_supply);
350 if (sc->vqmmc_supply)
351 regulator_disable(sc->vqmmc_supply);
394 break;
395 case power_up:
396 if (bootverbose)
397 device_printf(sc->dev, "Powering up sd/mmc\n");
398
352 break;
353 case power_up:
354 if (bootverbose)
355 device_printf(sc->dev, "Powering up sd/mmc\n");
356
399 if (sc->mmc_helper.vmmc_supply)
400 regulator_enable(sc->mmc_helper.vmmc_supply);
401 if (sc->mmc_helper.vqmmc_supply)
402 regulator_enable(sc->mmc_helper.vqmmc_supply);
357 if (sc->vmmc_supply)
358 regulator_enable(sc->vmmc_supply);
359 if (sc->vqmmc_supply)
360 regulator_enable(sc->vqmmc_supply);
403 break;
404 };
405
406 /* Update the PHY settings. */
407 if (ios->clock != 0)
408 sdhci_xenon_phy_set(brdev, ios);
409
410 if (ios->clock > SD_MMC_CARD_ID_FREQUENCY) {

--- 16 unchanged lines hidden (view full) ---

427
428 slot = device_get_ivars(reqdev);
429
430 if (slot->version < SDHCI_SPEC_300)
431 return (0);
432
433 sc = device_get_softc(brdev);
434
361 break;
362 };
363
364 /* Update the PHY settings. */
365 if (ios->clock != 0)
366 sdhci_xenon_phy_set(brdev, ios);
367
368 if (ios->clock > SD_MMC_CARD_ID_FREQUENCY) {

--- 16 unchanged lines hidden (view full) ---

385
386 slot = device_get_ivars(reqdev);
387
388 if (slot->version < SDHCI_SPEC_300)
389 return (0);
390
391 sc = device_get_softc(brdev);
392
435 if (sc->mmc_helper.vqmmc_supply == NULL)
436 return EOPNOTSUPP;
393 if (sc->vqmmc_supply == NULL && !sc->skip_regulators)
394 return (EOPNOTSUPP);
437
438 err = 0;
439
440 hostctrl2 = bus_read_2(sc->mem_res, SDHCI_HOST_CONTROL2);
441 switch (slot->host.ios.vccq) {
442 case vccq_330:
443 if (!(hostctrl2 & SDHCI_CTRL2_S18_ENABLE))
444 return (0);
445 hostctrl2 &= ~SDHCI_CTRL2_S18_ENABLE;
446 bus_write_2(sc->mem_res, SDHCI_HOST_CONTROL2, hostctrl2);
447
395
396 err = 0;
397
398 hostctrl2 = bus_read_2(sc->mem_res, SDHCI_HOST_CONTROL2);
399 switch (slot->host.ios.vccq) {
400 case vccq_330:
401 if (!(hostctrl2 & SDHCI_CTRL2_S18_ENABLE))
402 return (0);
403 hostctrl2 &= ~SDHCI_CTRL2_S18_ENABLE;
404 bus_write_2(sc->mem_res, SDHCI_HOST_CONTROL2, hostctrl2);
405
448 uvolt = 3300000;
449 err = regulator_set_voltage(sc->mmc_helper.vqmmc_supply,
450 uvolt, uvolt);
451 if (err != 0) {
452 device_printf(sc->dev,
453 "Cannot set vqmmc to %d<->%d\n",
454 uvolt,
455 uvolt);
456 return (err);
406 if (!sc->skip_regulators) {
407 uvolt = 3300000;
408 err = regulator_set_voltage(sc->vqmmc_supply,
409 uvolt, uvolt);
410 if (err != 0) {
411 device_printf(sc->dev,
412 "Cannot set vqmmc to %d<->%d\n",
413 uvolt,
414 uvolt);
415 return (err);
416 }
457 }
458
459 /*
460 * According to the 'SD Host Controller Simplified
461 * Specification 4.20 the host driver should take more
462 * than 5ms for stable time of host voltage regulator
463 * from changing 1.8V Signaling Enable.
464 */
465 DELAY(5000);
466 hostctrl2 = bus_read_2(sc->mem_res, SDHCI_HOST_CONTROL2);
467 if (!(hostctrl2 & SDHCI_CTRL2_S18_ENABLE))
468 return (0);
417 }
418
419 /*
420 * According to the 'SD Host Controller Simplified
421 * Specification 4.20 the host driver should take more
422 * than 5ms for stable time of host voltage regulator
423 * from changing 1.8V Signaling Enable.
424 */
425 DELAY(5000);
426 hostctrl2 = bus_read_2(sc->mem_res, SDHCI_HOST_CONTROL2);
427 if (!(hostctrl2 & SDHCI_CTRL2_S18_ENABLE))
428 return (0);
469 return EAGAIN;
429 return (EAGAIN);
470 case vccq_180:
471 if (!(slot->host.caps & MMC_CAP_SIGNALING_180)) {
430 case vccq_180:
431 if (!(slot->host.caps & MMC_CAP_SIGNALING_180)) {
472 return EINVAL;
432 return (EINVAL);
473 }
474 if (hostctrl2 & SDHCI_CTRL2_S18_ENABLE)
475 return (0);
476 hostctrl2 |= SDHCI_CTRL2_S18_ENABLE;
477 bus_write_2(sc->mem_res, SDHCI_HOST_CONTROL2, hostctrl2);
478
433 }
434 if (hostctrl2 & SDHCI_CTRL2_S18_ENABLE)
435 return (0);
436 hostctrl2 |= SDHCI_CTRL2_S18_ENABLE;
437 bus_write_2(sc->mem_res, SDHCI_HOST_CONTROL2, hostctrl2);
438
479 uvolt = 1800000;
480 err = regulator_set_voltage(sc->mmc_helper.vqmmc_supply,
481 uvolt, uvolt);
482 if (err != 0) {
483 device_printf(sc->dev,
484 "Cannot set vqmmc to %d<->%d\n",
485 uvolt,
486 uvolt);
487 return (err);
439 if (!sc->skip_regulators) {
440 uvolt = 1800000;
441 err = regulator_set_voltage(sc->vqmmc_supply,
442 uvolt, uvolt);
443 if (err != 0) {
444 device_printf(sc->dev,
445 "Cannot set vqmmc to %d<->%d\n",
446 uvolt,
447 uvolt);
448 return (err);
449 }
488 }
489
490 /*
491 * According to the 'SD Host Controller Simplified
492 * Specification 4.20 the host driver should take more
493 * than 5ms for stable time of host voltage regulator
494 * from changing 1.8V Signaling Enable.
495 */
496 DELAY(5000);
497 hostctrl2 = bus_read_2(sc->mem_res, SDHCI_HOST_CONTROL2);
498 if (hostctrl2 & SDHCI_CTRL2_S18_ENABLE)
499 return (0);
450 }
451
452 /*
453 * According to the 'SD Host Controller Simplified
454 * Specification 4.20 the host driver should take more
455 * than 5ms for stable time of host voltage regulator
456 * from changing 1.8V Signaling Enable.
457 */
458 DELAY(5000);
459 hostctrl2 = bus_read_2(sc->mem_res, SDHCI_HOST_CONTROL2);
460 if (hostctrl2 & SDHCI_CTRL2_S18_ENABLE)
461 return (0);
500 return EAGAIN;
462 return (EAGAIN);
501 default:
502 device_printf(brdev,
503 "Attempt to set unsupported signaling voltage\n");
463 default:
464 device_printf(brdev,
465 "Attempt to set unsupported signaling voltage\n");
504 return EINVAL;
466 return (EINVAL);
505 }
506}
507
508static void
467 }
468}
469
470static void
509sdhci_xenon_fdt_parse(device_t dev, struct sdhci_slot *slot)
471sdhci_xenon_parse_prop(device_t dev)
510{
472{
511 struct sdhci_xenon_softc *sc = device_get_softc(dev);
512 pcell_t cid;
473 struct sdhci_xenon_softc *sc;
474 uint64_t val;
513
475
514 mmc_fdt_parse(dev, 0, &sc->mmc_helper, &slot->host);
476 sc = device_get_softc(dev);
477 val = 0;
515
478
516 /* Allow dts to patch quirks, slots, and max-frequency. */
517 if ((OF_getencprop(sc->node, "quirks", &cid, sizeof(cid))) > 0)
518 slot->quirks = cid;
519 if (OF_hasprop(sc->node, "marvell,xenon-phy-slow-mode"))
520 sc->slow_mode = true;
479 if (device_get_property(dev, "quirks", &val, sizeof(val)) > 0)
480 sc->slot->quirks = val;
521 sc->znr = XENON_ZNR_DEF_VALUE;
481 sc->znr = XENON_ZNR_DEF_VALUE;
522 if ((OF_getencprop(sc->node, "marvell,xenon-phy-znr", &cid,
523 sizeof(cid))) > 0)
524 sc->znr = cid & XENON_ZNR_MASK;
482 if (device_get_property(dev, "marvell,xenon-phy-znr",
483 &val, sizeof(val)) > 0)
484 sc->znr = val & XENON_ZNR_MASK;
525 sc->zpr = XENON_ZPR_DEF_VALUE;
485 sc->zpr = XENON_ZPR_DEF_VALUE;
526 if ((OF_getencprop(sc->node, "marvell,xenon-phy-zpr", &cid,
527 sizeof(cid))) > 0)
528 sc->zpr = cid & XENON_ZPR_MASK;
486 if (device_get_property(dev, "marvell,xenon-phy-zpr",
487 &val, sizeof(val)) > 0)
488 sc->zpr = val & XENON_ZPR_MASK;
489 if (device_has_property(dev, "marvell,xenon-phy-slow-mode"))
490 sc->slow_mode = true;
529}
530
491}
492
531static int
532sdhci_xenon_probe(device_t dev)
533{
534 if (!ofw_bus_status_okay(dev))
535 return (ENXIO);
536
537 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
538 return (ENXIO);
539
540 device_set_desc(dev, "Armada Xenon SDHCI controller");
541
542 return (0);
543}
544
545static int
493int
546sdhci_xenon_attach(device_t dev)
547{
548 struct sdhci_xenon_softc *sc = device_get_softc(dev);
494sdhci_xenon_attach(device_t dev)
495{
496 struct sdhci_xenon_softc *sc = device_get_softc(dev);
549 struct sdhci_slot *slot;
550 int err, rid;
551 uint32_t reg;
552
553 sc->dev = dev;
554 sc->slot_id = 0;
497 int err, rid;
498 uint32_t reg;
499
500 sc->dev = dev;
501 sc->slot_id = 0;
555 sc->node = ofw_bus_get_node(dev);
556
557 /* Allocate IRQ. */
558 rid = 0;
559 sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
560 RF_ACTIVE);
561 if (sc->irq_res == NULL) {
562 device_printf(dev, "Can't allocate IRQ\n");
563 return (ENOMEM);

--- 5 unchanged lines hidden (view full) ---

569 &rid, RF_ACTIVE);
570 if (sc->mem_res == NULL) {
571 bus_release_resource(dev, SYS_RES_IRQ,
572 rman_get_rid(sc->irq_res), sc->irq_res);
573 device_printf(dev, "Can't allocate memory for slot\n");
574 return (ENOMEM);
575 }
576
502
503 /* Allocate IRQ. */
504 rid = 0;
505 sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
506 RF_ACTIVE);
507 if (sc->irq_res == NULL) {
508 device_printf(dev, "Can't allocate IRQ\n");
509 return (ENOMEM);

--- 5 unchanged lines hidden (view full) ---

515 &rid, RF_ACTIVE);
516 if (sc->mem_res == NULL) {
517 bus_release_resource(dev, SYS_RES_IRQ,
518 rman_get_rid(sc->irq_res), sc->irq_res);
519 device_printf(dev, "Can't allocate memory for slot\n");
520 return (ENOMEM);
521 }
522
577 slot = malloc(sizeof(*slot), M_DEVBUF, M_ZERO | M_WAITOK);
523 sdhci_xenon_parse_prop(dev);
578
524
579 /*
580 * Set up any gpio pin handling described in the FDT data. This cannot
581 * fail; see comments in sdhci_fdt_gpio.h for details.
582 */
583 sc->gpio = sdhci_fdt_gpio_setup(dev, slot);
525 sc->slot->max_clk = XENON_MMC_MAX_CLK;
526 if (sc->slot->host.f_max > 0)
527 sc->slot->max_clk = sc->slot->host.f_max;
584
528
585 sdhci_xenon_fdt_parse(dev, slot);
586
587 slot->max_clk = XENON_MMC_MAX_CLK;
588 if (slot->host.f_max > 0)
589 slot->max_clk = slot->host.f_max;
590 /* Check if the device is flagged as non-removable. */
591 if (sc->mmc_helper.props & MMC_PROP_NON_REMOVABLE) {
592 slot->opt |= SDHCI_NON_REMOVABLE;
593 if (bootverbose)
594 device_printf(dev, "Non-removable media\n");
595 }
596
597 sc->slot = slot;
598
599 if (sdhci_init_slot(dev, sc->slot, 0))
600 goto fail;
601
602 /* 1.2V signaling is not supported. */
603 sc->slot->host.caps &= ~MMC_CAP_SIGNALING_120;
604
605 /* Disable UHS in case of the PHY slow mode. */
606 if (sc->slow_mode)

--- 46 unchanged lines hidden (view full) ---

653 bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem_res),
654 sc->mem_res);
655 free(sc->slot, M_DEVBUF);
656 sc->slot = NULL;
657
658 return (ENXIO);
659}
660
529 if (sdhci_init_slot(dev, sc->slot, 0))
530 goto fail;
531
532 /* 1.2V signaling is not supported. */
533 sc->slot->host.caps &= ~MMC_CAP_SIGNALING_120;
534
535 /* Disable UHS in case of the PHY slow mode. */
536 if (sc->slow_mode)

--- 46 unchanged lines hidden (view full) ---

583 bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem_res),
584 sc->mem_res);
585 free(sc->slot, M_DEVBUF);
586 sc->slot = NULL;
587
588 return (ENXIO);
589}
590
661static int
591int
662sdhci_xenon_detach(device_t dev)
663{
664 struct sdhci_xenon_softc *sc = device_get_softc(dev);
665
592sdhci_xenon_detach(device_t dev)
593{
594 struct sdhci_xenon_softc *sc = device_get_softc(dev);
595
666 if (sc->gpio != NULL)
667 sdhci_fdt_gpio_teardown(sc->gpio);
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 sdhci_cleanup_slot(sc->slot);
674 bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem_res),
675 sc->mem_res);
676 free(sc->slot, M_DEVBUF);
677 sc->slot = NULL;
678
679 return (0);
680}
681
682static device_method_t sdhci_xenon_methods[] = {
596 bus_generic_detach(dev);
597 bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
598 bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq_res),
599 sc->irq_res);
600 sdhci_cleanup_slot(sc->slot);
601 bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem_res),
602 sc->mem_res);
603 free(sc->slot, M_DEVBUF);
604 sc->slot = NULL;
605
606 return (0);
607}
608
609static device_method_t sdhci_xenon_methods[] = {
683 /* device_if */
684 DEVMETHOD(device_probe, sdhci_xenon_probe),
685 DEVMETHOD(device_attach, sdhci_xenon_attach),
686 DEVMETHOD(device_detach, sdhci_xenon_detach),
687
688 /* Bus interface */
689 DEVMETHOD(bus_read_ivar, sdhci_generic_read_ivar),
690 DEVMETHOD(bus_write_ivar, sdhci_generic_write_ivar),
691
692 /* mmcbr_if */
693 DEVMETHOD(mmcbr_update_ios, sdhci_xenon_update_ios),
694 DEVMETHOD(mmcbr_request, sdhci_generic_request),
695 DEVMETHOD(mmcbr_get_ro, sdhci_xenon_get_ro),

--- 7 unchanged lines hidden (view full) ---

703 DEVMETHOD(sdhci_read_1, sdhci_xenon_read_1),
704 DEVMETHOD(sdhci_read_2, sdhci_xenon_read_2),
705 DEVMETHOD(sdhci_read_4, sdhci_xenon_read_4),
706 DEVMETHOD(sdhci_read_multi_4, sdhci_xenon_read_multi_4),
707 DEVMETHOD(sdhci_write_1, sdhci_xenon_write_1),
708 DEVMETHOD(sdhci_write_2, sdhci_xenon_write_2),
709 DEVMETHOD(sdhci_write_4, sdhci_xenon_write_4),
710 DEVMETHOD(sdhci_write_multi_4, sdhci_xenon_write_multi_4),
610 /* Bus interface */
611 DEVMETHOD(bus_read_ivar, sdhci_generic_read_ivar),
612 DEVMETHOD(bus_write_ivar, sdhci_generic_write_ivar),
613
614 /* mmcbr_if */
615 DEVMETHOD(mmcbr_update_ios, sdhci_xenon_update_ios),
616 DEVMETHOD(mmcbr_request, sdhci_generic_request),
617 DEVMETHOD(mmcbr_get_ro, sdhci_xenon_get_ro),

--- 7 unchanged lines hidden (view full) ---

625 DEVMETHOD(sdhci_read_1, sdhci_xenon_read_1),
626 DEVMETHOD(sdhci_read_2, sdhci_xenon_read_2),
627 DEVMETHOD(sdhci_read_4, sdhci_xenon_read_4),
628 DEVMETHOD(sdhci_read_multi_4, sdhci_xenon_read_multi_4),
629 DEVMETHOD(sdhci_write_1, sdhci_xenon_write_1),
630 DEVMETHOD(sdhci_write_2, sdhci_xenon_write_2),
631 DEVMETHOD(sdhci_write_4, sdhci_xenon_write_4),
632 DEVMETHOD(sdhci_write_multi_4, sdhci_xenon_write_multi_4),
711 DEVMETHOD(sdhci_get_card_present, sdhci_xenon_get_card_present),
712 DEVMETHOD(sdhci_set_uhs_timing, sdhci_xenon_set_uhs_timing),
713
714 DEVMETHOD_END
715};
716
633 DEVMETHOD(sdhci_set_uhs_timing, sdhci_xenon_set_uhs_timing),
634
635 DEVMETHOD_END
636};
637
717static driver_t sdhci_xenon_driver = {
718 "sdhci_xenon",
719 sdhci_xenon_methods,
720 sizeof(struct sdhci_xenon_softc),
721};
722static devclass_t sdhci_xenon_devclass;
638DEFINE_CLASS_0(sdhci_xenon, sdhci_xenon_driver, sdhci_xenon_methods,
639 sizeof(struct sdhci_xenon_softc));
723
640
724DRIVER_MODULE(sdhci_xenon, simplebus, sdhci_xenon_driver, sdhci_xenon_devclass,
725 NULL, NULL);
726
727SDHCI_DEPEND(sdhci_xenon);
728#ifndef MMCCAM
729MMC_DECLARE_BRIDGE(sdhci_xenon);
730#endif
641SDHCI_DEPEND(sdhci_xenon);
642#ifndef MMCCAM
643MMC_DECLARE_BRIDGE(sdhci_xenon);
644#endif