Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/sdhci/sdhci_xenon.c
Show First 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | |||||
#include <sys/rman.h> | #include <sys/rman.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/taskqueue.h> | #include <sys/taskqueue.h> | ||||
#include <machine/bus.h> | #include <machine/bus.h> | ||||
#include <machine/resource.h> | #include <machine/resource.h> | ||||
#include <dev/extres/regulator/regulator.h> | #include <dev/extres/regulator/regulator.h> | ||||
#include <dev/fdt/fdt_common.h> | |||||
#include <dev/ofw/ofw_bus.h> | |||||
#include <dev/ofw/ofw_bus_subr.h> | |||||
#include <dev/mmc/bridge.h> | #include <dev/mmc/bridge.h> | ||||
#include <dev/mmc/mmc_fdt_helpers.h> | |||||
#include <dev/mmc/mmcbrvar.h> | #include <dev/mmc/mmcbrvar.h> | ||||
#include <dev/mmc/mmcreg.h> | #include <dev/mmc/mmcreg.h> | ||||
#include <dev/sdhci/sdhci.h> | #include <dev/sdhci/sdhci.h> | ||||
#include <dev/sdhci/sdhci_fdt_gpio.h> | |||||
#include <dev/sdhci/sdhci_xenon.h> | #include <dev/sdhci/sdhci_xenon.h> | ||||
#include "mmcbr_if.h" | #include "mmcbr_if.h" | ||||
#include "sdhci_if.h" | #include "sdhci_if.h" | ||||
#include "opt_mmccam.h" | #include "opt_mmccam.h" | ||||
#include "opt_soc.h" | #include "opt_soc.h" | ||||
#define MAX_SLOTS 6 | #define MAX_SLOTS 6 | ||||
static struct ofw_compat_data compat_data[] = { | |||||
{ "marvell,armada-3700-sdhci", 1 }, | |||||
#ifdef SOC_MARVELL_8K | |||||
{ "marvell,armada-cp110-sdhci", 1 }, | |||||
{ "marvell,armada-ap806-sdhci", 1 }, | |||||
{ "marvell,armada-ap807-sdhci", 1 }, | |||||
#endif | |||||
{ NULL, 0 } | |||||
}; | |||||
struct sdhci_xenon_softc { | |||||
device_t dev; /* Controller device */ | |||||
int slot_id; /* Controller ID */ | |||||
phandle_t node; /* FDT node */ | |||||
struct resource *irq_res; /* IRQ resource */ | |||||
void *intrhand; /* Interrupt handle */ | |||||
struct sdhci_fdt_gpio *gpio; /* GPIO pins for CD detection. */ | |||||
struct sdhci_slot *slot; /* SDHCI internal data */ | |||||
struct resource *mem_res; /* Memory resource */ | |||||
uint8_t znr; /* PHY ZNR */ | |||||
uint8_t zpr; /* PHY ZPR */ | |||||
bool slow_mode; /* PHY slow mode */ | |||||
struct mmc_helper mmc_helper; /* MMC helper for parsing FDT */ | |||||
}; | |||||
static uint8_t | static uint8_t | ||||
sdhci_xenon_read_1(device_t dev, struct sdhci_slot *slot __unused, | sdhci_xenon_read_1(device_t dev, struct sdhci_slot *slot __unused, | ||||
bus_size_t off) | bus_size_t off) | ||||
{ | { | ||||
struct sdhci_xenon_softc *sc = device_get_softc(dev); | struct sdhci_xenon_softc *sc = device_get_softc(dev); | ||||
return (bus_read_1(sc->mem_res, off)); | return (bus_read_1(sc->mem_res, off)); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | sdhci_xenon_intr(void *arg) | ||||
sdhci_generic_intr(sc->slot); | sdhci_generic_intr(sc->slot); | ||||
} | } | ||||
static int | static int | ||||
sdhci_xenon_get_ro(device_t bus, device_t dev) | sdhci_xenon_get_ro(device_t bus, device_t dev) | ||||
{ | { | ||||
struct sdhci_xenon_softc *sc = device_get_softc(bus); | struct sdhci_xenon_softc *sc = device_get_softc(bus); | ||||
return (sdhci_generic_get_ro(bus, dev) ^ | return (sdhci_generic_get_ro(bus, dev) ^ sc->wp_inverted); | ||||
(sc->mmc_helper.props & MMC_PROP_WP_INVERTED)); | |||||
} | } | ||||
static bool | |||||
sdhci_xenon_get_card_present(device_t dev, struct sdhci_slot *slot) | |||||
{ | |||||
struct sdhci_xenon_softc *sc = device_get_softc(dev); | |||||
return (sdhci_fdt_gpio_get_present(sc->gpio)); | |||||
} | |||||
static void | static void | ||||
sdhci_xenon_set_uhs_timing(device_t brdev, struct sdhci_slot *slot) | sdhci_xenon_set_uhs_timing(device_t brdev, struct sdhci_slot *slot) | ||||
{ | { | ||||
const struct mmc_ios *ios; | const struct mmc_ios *ios; | ||||
uint16_t hostctrl2; | uint16_t hostctrl2; | ||||
if (slot->version < SDHCI_SPEC_300) | if (slot->version < SDHCI_SPEC_300) | ||||
return; | return; | ||||
▲ Show 20 Lines • Show All 177 Lines • ▼ Show 20 Lines | sdhci_xenon_update_ios(device_t brdev, device_t reqdev) | ||||
switch (ios->power_mode) { | switch (ios->power_mode) { | ||||
case power_on: | case power_on: | ||||
break; | break; | ||||
case power_off: | case power_off: | ||||
if (bootverbose) | if (bootverbose) | ||||
device_printf(sc->dev, "Powering down sd/mmc\n"); | device_printf(sc->dev, "Powering down sd/mmc\n"); | ||||
if (sc->mmc_helper.vmmc_supply) | if (sc->vmmc_supply) | ||||
regulator_disable(sc->mmc_helper.vmmc_supply); | regulator_disable(sc->vmmc_supply); | ||||
if (sc->mmc_helper.vqmmc_supply) | if (sc->vqmmc_supply) | ||||
regulator_disable(sc->mmc_helper.vqmmc_supply); | regulator_disable(sc->vqmmc_supply); | ||||
break; | break; | ||||
case power_up: | case power_up: | ||||
if (bootverbose) | if (bootverbose) | ||||
device_printf(sc->dev, "Powering up sd/mmc\n"); | device_printf(sc->dev, "Powering up sd/mmc\n"); | ||||
if (sc->mmc_helper.vmmc_supply) | if (sc->vmmc_supply) | ||||
regulator_enable(sc->mmc_helper.vmmc_supply); | regulator_enable(sc->vmmc_supply); | ||||
if (sc->mmc_helper.vqmmc_supply) | if (sc->vqmmc_supply) | ||||
regulator_enable(sc->mmc_helper.vqmmc_supply); | regulator_enable(sc->vqmmc_supply); | ||||
break; | break; | ||||
}; | }; | ||||
/* Update the PHY settings. */ | /* Update the PHY settings. */ | ||||
if (ios->clock != 0) | if (ios->clock != 0) | ||||
sdhci_xenon_phy_set(brdev, ios); | sdhci_xenon_phy_set(brdev, ios); | ||||
if (ios->clock > SD_MMC_CARD_ID_FREQUENCY) { | if (ios->clock > SD_MMC_CARD_ID_FREQUENCY) { | ||||
/* Enable SDCLK_IDLEOFF. */ | /* Enable SDCLK_IDLEOFF. */ | ||||
reg = bus_read_4(sc->mem_res, XENON_SYS_OP_CTRL); | reg = bus_read_4(sc->mem_res, XENON_SYS_OP_CTRL); | ||||
reg |= 1 << (XENON_SDCLK_IDLEOFF_ENABLE_SHIFT + sc->slot_id); | reg |= 1 << (XENON_SDCLK_IDLEOFF_ENABLE_SHIFT + sc->slot_id); | ||||
bus_write_4(sc->mem_res, XENON_SYS_OP_CTRL, reg); | bus_write_4(sc->mem_res, XENON_SYS_OP_CTRL, reg); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
sdhci_xenon_switch_vccq(device_t brdev, device_t reqdev) | sdhci_xenon_switch_vccq(device_t brdev, device_t reqdev) | ||||
{ | { | ||||
struct sdhci_xenon_softc *sc; | struct sdhci_xenon_softc *sc; | ||||
mw: Don't mix declarations with assignements. | |||||
struct sdhci_slot *slot; | struct sdhci_slot *slot; | ||||
uint16_t hostctrl2; | uint16_t hostctrl2; | ||||
int uvolt, err; | int uvolt, err; | ||||
slot = device_get_ivars(reqdev); | slot = device_get_ivars(reqdev); | ||||
if (slot->version < SDHCI_SPEC_300) | if (slot->version < SDHCI_SPEC_300) | ||||
return (0); | return (0); | ||||
sc = device_get_softc(brdev); | sc = device_get_softc(brdev); | ||||
if (sc->mmc_helper.vqmmc_supply == NULL) | if (sc->vqmmc_supply == NULL && !sc->skip_regulators) | ||||
return EOPNOTSUPP; | return (EOPNOTSUPP); | ||||
err = 0; | err = 0; | ||||
Done Inline ActionsLeave above assignments intact (of course apart from extending the if). mw: Leave above assignments intact (of course apart from extending the `if`). | |||||
hostctrl2 = bus_read_2(sc->mem_res, SDHCI_HOST_CONTROL2); | hostctrl2 = bus_read_2(sc->mem_res, SDHCI_HOST_CONTROL2); | ||||
switch (slot->host.ios.vccq) { | switch (slot->host.ios.vccq) { | ||||
case vccq_330: | case vccq_330: | ||||
if (!(hostctrl2 & SDHCI_CTRL2_S18_ENABLE)) | if (!(hostctrl2 & SDHCI_CTRL2_S18_ENABLE)) | ||||
return (0); | return (0); | ||||
hostctrl2 &= ~SDHCI_CTRL2_S18_ENABLE; | hostctrl2 &= ~SDHCI_CTRL2_S18_ENABLE; | ||||
bus_write_2(sc->mem_res, SDHCI_HOST_CONTROL2, hostctrl2); | bus_write_2(sc->mem_res, SDHCI_HOST_CONTROL2, hostctrl2); | ||||
if (!sc->skip_regulators) { | |||||
uvolt = 3300000; | uvolt = 3300000; | ||||
err = regulator_set_voltage(sc->mmc_helper.vqmmc_supply, | err = regulator_set_voltage(sc->vqmmc_supply, | ||||
uvolt, uvolt); | uvolt, uvolt); | ||||
if (err != 0) { | if (err != 0) { | ||||
device_printf(sc->dev, | device_printf(sc->dev, | ||||
"Cannot set vqmmc to %d<->%d\n", | "Cannot set vqmmc to %d<->%d\n", | ||||
uvolt, | uvolt, | ||||
uvolt); | uvolt); | ||||
return (err); | return (err); | ||||
} | } | ||||
} | |||||
/* | /* | ||||
* According to the 'SD Host Controller Simplified | * According to the 'SD Host Controller Simplified | ||||
* Specification 4.20 the host driver should take more | * Specification 4.20 the host driver should take more | ||||
* than 5ms for stable time of host voltage regulator | * than 5ms for stable time of host voltage regulator | ||||
* from changing 1.8V Signaling Enable. | * from changing 1.8V Signaling Enable. | ||||
*/ | */ | ||||
DELAY(5000); | DELAY(5000); | ||||
hostctrl2 = bus_read_2(sc->mem_res, SDHCI_HOST_CONTROL2); | hostctrl2 = bus_read_2(sc->mem_res, SDHCI_HOST_CONTROL2); | ||||
if (!(hostctrl2 & SDHCI_CTRL2_S18_ENABLE)) | if (!(hostctrl2 & SDHCI_CTRL2_S18_ENABLE)) | ||||
return (0); | return (0); | ||||
return EAGAIN; | return (EAGAIN); | ||||
case vccq_180: | case vccq_180: | ||||
if (!(slot->host.caps & MMC_CAP_SIGNALING_180)) { | if (!(slot->host.caps & MMC_CAP_SIGNALING_180)) { | ||||
return EINVAL; | return (EINVAL); | ||||
} | } | ||||
if (hostctrl2 & SDHCI_CTRL2_S18_ENABLE) | if (hostctrl2 & SDHCI_CTRL2_S18_ENABLE) | ||||
return (0); | return (0); | ||||
hostctrl2 |= SDHCI_CTRL2_S18_ENABLE; | hostctrl2 |= SDHCI_CTRL2_S18_ENABLE; | ||||
bus_write_2(sc->mem_res, SDHCI_HOST_CONTROL2, hostctrl2); | bus_write_2(sc->mem_res, SDHCI_HOST_CONTROL2, hostctrl2); | ||||
if (!sc->skip_regulators) { | |||||
uvolt = 1800000; | uvolt = 1800000; | ||||
err = regulator_set_voltage(sc->mmc_helper.vqmmc_supply, | err = regulator_set_voltage(sc->vqmmc_supply, | ||||
uvolt, uvolt); | uvolt, uvolt); | ||||
if (err != 0) { | if (err != 0) { | ||||
device_printf(sc->dev, | device_printf(sc->dev, | ||||
"Cannot set vqmmc to %d<->%d\n", | "Cannot set vqmmc to %d<->%d\n", | ||||
uvolt, | uvolt, | ||||
uvolt); | uvolt); | ||||
return (err); | return (err); | ||||
} | } | ||||
} | |||||
/* | /* | ||||
* According to the 'SD Host Controller Simplified | * According to the 'SD Host Controller Simplified | ||||
* Specification 4.20 the host driver should take more | * Specification 4.20 the host driver should take more | ||||
* than 5ms for stable time of host voltage regulator | * than 5ms for stable time of host voltage regulator | ||||
* from changing 1.8V Signaling Enable. | * from changing 1.8V Signaling Enable. | ||||
*/ | */ | ||||
DELAY(5000); | DELAY(5000); | ||||
hostctrl2 = bus_read_2(sc->mem_res, SDHCI_HOST_CONTROL2); | hostctrl2 = bus_read_2(sc->mem_res, SDHCI_HOST_CONTROL2); | ||||
if (hostctrl2 & SDHCI_CTRL2_S18_ENABLE) | if (hostctrl2 & SDHCI_CTRL2_S18_ENABLE) | ||||
return (0); | return (0); | ||||
return EAGAIN; | return (EAGAIN); | ||||
default: | default: | ||||
device_printf(brdev, | device_printf(brdev, | ||||
"Attempt to set unsupported signaling voltage\n"); | "Attempt to set unsupported signaling voltage\n"); | ||||
return EINVAL; | return (EINVAL); | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
sdhci_xenon_fdt_parse(device_t dev, struct sdhci_slot *slot) | sdhci_xenon_parse_prop(device_t dev) | ||||
{ | { | ||||
struct sdhci_xenon_softc *sc = device_get_softc(dev); | struct sdhci_xenon_softc *sc; | ||||
pcell_t cid; | uint64_t val; | ||||
mmc_fdt_parse(dev, 0, &sc->mmc_helper, &slot->host); | sc = device_get_softc(dev); | ||||
val = 0; | |||||
/* Allow dts to patch quirks, slots, and max-frequency. */ | if (device_get_property(dev, "quirks", &val, sizeof(val)) > 0) | ||||
if ((OF_getencprop(sc->node, "quirks", &cid, sizeof(cid))) > 0) | sc->slot->quirks = val; | ||||
slot->quirks = cid; | |||||
if (OF_hasprop(sc->node, "marvell,xenon-phy-slow-mode")) | |||||
sc->slow_mode = true; | |||||
sc->znr = XENON_ZNR_DEF_VALUE; | sc->znr = XENON_ZNR_DEF_VALUE; | ||||
if ((OF_getencprop(sc->node, "marvell,xenon-phy-znr", &cid, | if (device_get_property(dev, "marvell,xenon-phy-znr", | ||||
sizeof(cid))) > 0) | &val, sizeof(val)) > 0) | ||||
sc->znr = cid & XENON_ZNR_MASK; | sc->znr = val & XENON_ZNR_MASK; | ||||
Done Inline ActionsA single assignment of val in this function will be sufficient. mw: A single assignment of `val` in this function will be sufficient. | |||||
Done Inline ActionsCheck device_get_property consistently and compare explicitly to 0, as in the first if. mw: Check device_get_property consistently and compare explicitly to 0, as in the first `if`. | |||||
sc->zpr = XENON_ZPR_DEF_VALUE; | sc->zpr = XENON_ZPR_DEF_VALUE; | ||||
if ((OF_getencprop(sc->node, "marvell,xenon-phy-zpr", &cid, | if (device_get_property(dev, "marvell,xenon-phy-zpr", | ||||
sizeof(cid))) > 0) | &val, sizeof(val)) > 0) | ||||
sc->zpr = cid & XENON_ZPR_MASK; | sc->zpr = val & XENON_ZPR_MASK; | ||||
if (device_has_property(dev, "marvell,xenon-phy-slow-mode")) | |||||
sc->slow_mode = true; | |||||
} | } | ||||
static int | int | ||||
sdhci_xenon_probe(device_t dev) | |||||
{ | |||||
if (!ofw_bus_status_okay(dev)) | |||||
return (ENXIO); | |||||
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) | |||||
return (ENXIO); | |||||
device_set_desc(dev, "Armada Xenon SDHCI controller"); | |||||
return (0); | |||||
} | |||||
static int | |||||
sdhci_xenon_attach(device_t dev) | sdhci_xenon_attach(device_t dev) | ||||
{ | { | ||||
struct sdhci_xenon_softc *sc = device_get_softc(dev); | struct sdhci_xenon_softc *sc = device_get_softc(dev); | ||||
struct sdhci_slot *slot; | |||||
int err, rid; | int err, rid; | ||||
uint32_t reg; | uint32_t reg; | ||||
sc->dev = dev; | sc->dev = dev; | ||||
sc->slot_id = 0; | sc->slot_id = 0; | ||||
sc->node = ofw_bus_get_node(dev); | |||||
Done Inline ActionsNo need to reorder the assignments. mw: No need to reorder the assignments. | |||||
/* Allocate IRQ. */ | /* Allocate IRQ. */ | ||||
Done Inline ActionsCall this function after resources allocation. mw: Call this function after resources allocation. | |||||
rid = 0; | rid = 0; | ||||
sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, | sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, | ||||
RF_ACTIVE); | RF_ACTIVE); | ||||
if (sc->irq_res == NULL) { | if (sc->irq_res == NULL) { | ||||
device_printf(dev, "Can't allocate IRQ\n"); | device_printf(dev, "Can't allocate IRQ\n"); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
/* Allocate memory. */ | /* Allocate memory. */ | ||||
rid = 0; | rid = 0; | ||||
sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, | sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, | ||||
&rid, RF_ACTIVE); | &rid, RF_ACTIVE); | ||||
if (sc->mem_res == NULL) { | if (sc->mem_res == NULL) { | ||||
bus_release_resource(dev, SYS_RES_IRQ, | bus_release_resource(dev, SYS_RES_IRQ, | ||||
rman_get_rid(sc->irq_res), sc->irq_res); | rman_get_rid(sc->irq_res), sc->irq_res); | ||||
device_printf(dev, "Can't allocate memory for slot\n"); | device_printf(dev, "Can't allocate memory for slot\n"); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
slot = malloc(sizeof(*slot), M_DEVBUF, M_ZERO | M_WAITOK); | sdhci_xenon_parse_prop(dev); | ||||
/* | sc->slot->max_clk = XENON_MMC_MAX_CLK; | ||||
* Set up any gpio pin handling described in the FDT data. This cannot | if (sc->slot->host.f_max > 0) | ||||
* fail; see comments in sdhci_fdt_gpio.h for details. | sc->slot->max_clk = sc->slot->host.f_max; | ||||
*/ | |||||
sc->gpio = sdhci_fdt_gpio_setup(dev, slot); | |||||
sdhci_xenon_fdt_parse(dev, slot); | |||||
slot->max_clk = XENON_MMC_MAX_CLK; | |||||
if (slot->host.f_max > 0) | |||||
slot->max_clk = slot->host.f_max; | |||||
Done Inline ActionsLeave above 3 lines in a common sdhci_xenon_attach(). There is no need to duplicate it for OF_ and ACPI_ cases. mw: Leave above 3 lines in a common sdhci_xenon_attach(). There is no need to duplicate it for OF_… | |||||
/* Check if the device is flagged as non-removable. */ | |||||
if (sc->mmc_helper.props & MMC_PROP_NON_REMOVABLE) { | |||||
slot->opt |= SDHCI_NON_REMOVABLE; | |||||
if (bootverbose) | |||||
device_printf(dev, "Non-removable media\n"); | |||||
} | |||||
sc->slot = slot; | |||||
if (sdhci_init_slot(dev, sc->slot, 0)) | if (sdhci_init_slot(dev, sc->slot, 0)) | ||||
goto fail; | goto fail; | ||||
/* 1.2V signaling is not supported. */ | /* 1.2V signaling is not supported. */ | ||||
sc->slot->host.caps &= ~MMC_CAP_SIGNALING_120; | sc->slot->host.caps &= ~MMC_CAP_SIGNALING_120; | ||||
/* Disable UHS in case of the PHY slow mode. */ | /* Disable UHS in case of the PHY slow mode. */ | ||||
if (sc->slow_mode) | if (sc->slow_mode) | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | fail: | ||||
bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem_res), | bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem_res), | ||||
sc->mem_res); | sc->mem_res); | ||||
free(sc->slot, M_DEVBUF); | free(sc->slot, M_DEVBUF); | ||||
sc->slot = NULL; | sc->slot = NULL; | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
static int | int | ||||
sdhci_xenon_detach(device_t dev) | sdhci_xenon_detach(device_t dev) | ||||
{ | { | ||||
struct sdhci_xenon_softc *sc = device_get_softc(dev); | struct sdhci_xenon_softc *sc = device_get_softc(dev); | ||||
if (sc->gpio != NULL) | |||||
sdhci_fdt_gpio_teardown(sc->gpio); | |||||
bus_generic_detach(dev); | bus_generic_detach(dev); | ||||
bus_teardown_intr(dev, sc->irq_res, sc->intrhand); | bus_teardown_intr(dev, sc->irq_res, sc->intrhand); | ||||
Done Inline ActionsPlease retain an original name - this is a cosmetic change, not related to this patch. mw: Please retain an original name - this is a cosmetic change, not related to this patch. | |||||
bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq_res), | bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq_res), | ||||
sc->irq_res); | sc->irq_res); | ||||
sdhci_cleanup_slot(sc->slot); | sdhci_cleanup_slot(sc->slot); | ||||
bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem_res), | bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem_res), | ||||
sc->mem_res); | sc->mem_res); | ||||
free(sc->slot, M_DEVBUF); | free(sc->slot, M_DEVBUF); | ||||
sc->slot = NULL; | sc->slot = NULL; | ||||
return (0); | return (0); | ||||
} | } | ||||
static device_method_t sdhci_xenon_methods[] = { | static device_method_t sdhci_xenon_methods[] = { | ||||
/* device_if */ | |||||
DEVMETHOD(device_probe, sdhci_xenon_probe), | |||||
DEVMETHOD(device_attach, sdhci_xenon_attach), | |||||
DEVMETHOD(device_detach, sdhci_xenon_detach), | |||||
/* Bus interface */ | /* Bus interface */ | ||||
DEVMETHOD(bus_read_ivar, sdhci_generic_read_ivar), | DEVMETHOD(bus_read_ivar, sdhci_generic_read_ivar), | ||||
DEVMETHOD(bus_write_ivar, sdhci_generic_write_ivar), | DEVMETHOD(bus_write_ivar, sdhci_generic_write_ivar), | ||||
/* mmcbr_if */ | /* mmcbr_if */ | ||||
DEVMETHOD(mmcbr_update_ios, sdhci_xenon_update_ios), | DEVMETHOD(mmcbr_update_ios, sdhci_xenon_update_ios), | ||||
DEVMETHOD(mmcbr_request, sdhci_generic_request), | DEVMETHOD(mmcbr_request, sdhci_generic_request), | ||||
DEVMETHOD(mmcbr_get_ro, sdhci_xenon_get_ro), | DEVMETHOD(mmcbr_get_ro, sdhci_xenon_get_ro), | ||||
DEVMETHOD(mmcbr_acquire_host, sdhci_generic_acquire_host), | DEVMETHOD(mmcbr_acquire_host, sdhci_generic_acquire_host), | ||||
DEVMETHOD(mmcbr_release_host, sdhci_generic_release_host), | DEVMETHOD(mmcbr_release_host, sdhci_generic_release_host), | ||||
DEVMETHOD(mmcbr_switch_vccq, sdhci_xenon_switch_vccq), | DEVMETHOD(mmcbr_switch_vccq, sdhci_xenon_switch_vccq), | ||||
DEVMETHOD(mmcbr_tune, sdhci_generic_tune), | DEVMETHOD(mmcbr_tune, sdhci_generic_tune), | ||||
DEVMETHOD(mmcbr_retune, sdhci_generic_retune), | DEVMETHOD(mmcbr_retune, sdhci_generic_retune), | ||||
Done Inline ActionsNo need to change order of this method. mw: No need to change order of this method. | |||||
/* SDHCI registers accessors */ | /* SDHCI registers accessors */ | ||||
DEVMETHOD(sdhci_read_1, sdhci_xenon_read_1), | DEVMETHOD(sdhci_read_1, sdhci_xenon_read_1), | ||||
DEVMETHOD(sdhci_read_2, sdhci_xenon_read_2), | DEVMETHOD(sdhci_read_2, sdhci_xenon_read_2), | ||||
DEVMETHOD(sdhci_read_4, sdhci_xenon_read_4), | DEVMETHOD(sdhci_read_4, sdhci_xenon_read_4), | ||||
DEVMETHOD(sdhci_read_multi_4, sdhci_xenon_read_multi_4), | DEVMETHOD(sdhci_read_multi_4, sdhci_xenon_read_multi_4), | ||||
DEVMETHOD(sdhci_write_1, sdhci_xenon_write_1), | DEVMETHOD(sdhci_write_1, sdhci_xenon_write_1), | ||||
DEVMETHOD(sdhci_write_2, sdhci_xenon_write_2), | DEVMETHOD(sdhci_write_2, sdhci_xenon_write_2), | ||||
DEVMETHOD(sdhci_write_4, sdhci_xenon_write_4), | DEVMETHOD(sdhci_write_4, sdhci_xenon_write_4), | ||||
DEVMETHOD(sdhci_write_multi_4, sdhci_xenon_write_multi_4), | DEVMETHOD(sdhci_write_multi_4, sdhci_xenon_write_multi_4), | ||||
DEVMETHOD(sdhci_get_card_present, sdhci_xenon_get_card_present), | |||||
DEVMETHOD(sdhci_set_uhs_timing, sdhci_xenon_set_uhs_timing), | DEVMETHOD(sdhci_set_uhs_timing, sdhci_xenon_set_uhs_timing), | ||||
DEVMETHOD_END | DEVMETHOD_END | ||||
}; | }; | ||||
static driver_t sdhci_xenon_driver = { | DEFINE_CLASS_0(sdhci_xenon, sdhci_xenon_driver, sdhci_xenon_methods, | ||||
"sdhci_xenon", | sizeof(struct sdhci_xenon_softc)); | ||||
sdhci_xenon_methods, | |||||
sizeof(struct sdhci_xenon_softc), | |||||
}; | |||||
static devclass_t sdhci_xenon_devclass; | |||||
DRIVER_MODULE(sdhci_xenon, simplebus, sdhci_xenon_driver, sdhci_xenon_devclass, | |||||
NULL, NULL); | |||||
SDHCI_DEPEND(sdhci_xenon); | SDHCI_DEPEND(sdhci_xenon); | ||||
#ifndef MMCCAM | #ifndef MMCCAM | ||||
MMC_DECLARE_BRIDGE(sdhci_xenon); | MMC_DECLARE_BRIDGE(sdhci_xenon); | ||||
#endif | #endif |
Don't mix declarations with assignements.