Changeset View
Standalone View
sys/dev/sdhci/sdhci_fsl_fdt.c
Show First 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | |||||
#define SDHCI_FSL_PROT_CTRL_WIDTH_8BIT (2 << 1) | #define SDHCI_FSL_PROT_CTRL_WIDTH_8BIT (2 << 1) | ||||
#define SDHCI_FSL_PROT_CTRL_WIDTH_MASK (3 << 1) | #define SDHCI_FSL_PROT_CTRL_WIDTH_MASK (3 << 1) | ||||
#define SDHCI_FSL_PROT_CTRL_BYTE_SWAP (0 << 4) | #define SDHCI_FSL_PROT_CTRL_BYTE_SWAP (0 << 4) | ||||
#define SDHCI_FSL_PROT_CTRL_BYTE_NATIVE (2 << 4) | #define SDHCI_FSL_PROT_CTRL_BYTE_NATIVE (2 << 4) | ||||
#define SDHCI_FSL_PROT_CTRL_BYTE_MASK (3 << 4) | #define SDHCI_FSL_PROT_CTRL_BYTE_MASK (3 << 4) | ||||
#define SDHCI_FSL_PROT_CTRL_DMA_MASK (3 << 8) | #define SDHCI_FSL_PROT_CTRL_DMA_MASK (3 << 8) | ||||
#define SDHCI_FSL_PROT_CTRL_VOLT_SEL (1 << 10) | #define SDHCI_FSL_PROT_CTRL_VOLT_SEL (1 << 10) | ||||
#define SDHCI_FSL_IRQSTAT 0x30 | |||||
#define SDHCI_FSL_IRQSTAT_BRR (1 << 5) | |||||
#define SDHCI_FSL_IRQSTAT_CINTSEN (1 << 8) | |||||
#define SDHCI_FSL_IRQSTAT_RTE (1 << 12) | |||||
#define SDHCI_FSL_IRQSTAT_TNE (1 << 26) | |||||
#define SDHCI_FSL_SYS_CTRL 0x2c | #define SDHCI_FSL_SYS_CTRL 0x2c | ||||
#define SDHCI_FSL_CLK_IPGEN (1 << 0) | #define SDHCI_FSL_CLK_IPGEN (1 << 0) | ||||
#define SDHCI_FSL_CLK_SDCLKEN (1 << 3) | #define SDHCI_FSL_CLK_SDCLKEN (1 << 3) | ||||
#define SDHCI_FSL_CLK_DIVIDER_MASK 0x000000f0 | #define SDHCI_FSL_CLK_DIVIDER_MASK 0x000000f0 | ||||
#define SDHCI_FSL_CLK_DIVIDER_SHIFT 4 | #define SDHCI_FSL_CLK_DIVIDER_SHIFT 4 | ||||
#define SDHCI_FSL_CLK_PRESCALE_MASK 0x0000ff00 | #define SDHCI_FSL_CLK_PRESCALE_MASK 0x0000ff00 | ||||
#define SDHCI_FSL_CLK_PRESCALE_SHIFT 8 | #define SDHCI_FSL_CLK_PRESCALE_SHIFT 8 | ||||
#define SDHCI_FSL_WTMK_LVL 0x44 | #define SDHCI_FSL_WTMK_LVL 0x44 | ||||
#define SDHCI_FSL_WTMK_RD_512B (0 << 0) | #define SDHCI_FSL_WTMK_RD_512B (0 << 0) | ||||
#define SDHCI_FSL_WTMK_WR_512B (0 << 15) | #define SDHCI_FSL_WTMK_WR_512B (0 << 15) | ||||
#define SDHCI_FSL_AUTOCERR 0x3C | |||||
#define SDHCI_FSL_AUTOCERR_UHMS_HS200 (3 << 17) | |||||
#define SDHCI_FSL_AUTOCERR_UHMS (7 << 18) | |||||
#define SDHCI_FSL_AUTOCERR_EXTN (1 << 22) | |||||
#define SDHCI_FSL_AUTOCERR_SMPCLKSEL (1 << 23) | |||||
#define SDHCI_FSL_HOST_VERSION 0xfc | #define SDHCI_FSL_HOST_VERSION 0xfc | ||||
#define SDHCI_FSL_VENDOR_V23 0x13 | #define SDHCI_FSL_VENDOR_V23 0x13 | ||||
#define SDHCI_FSL_CAPABILITIES2 0x114 | #define SDHCI_FSL_CAPABILITIES2 0x114 | ||||
#define SDHCI_FSL_TBCTL 0x120 | #define SDHCI_FSL_TBCTL 0x120 | ||||
#define SDHCI_FSL_TBSTAT 0x124 | |||||
#define SDHCI_FSL_TBCTL_TBEN (1 << 2) | #define SDHCI_FSL_TBCTL_TBEN (1 << 2) | ||||
#define SDHCI_FSL_TBCTL_HS400_EN (1 << 4) | |||||
#define SDHCI_FSL_TBCTL_SAMP_CMD_DQS (1 << 5) | |||||
#define SDHCI_FSL_TBCTL_HS400_WND_ADJ (1 << 6) | |||||
#define SDHCI_FSL_TBCTL_TB_MODE_MASK 0x3 | |||||
#define SDHCI_FSL_TBCTL_MODE_1 0 | |||||
#define SDHCI_FSL_TBCTL_MODE_2 1 | |||||
#define SDHCI_FSL_TBCTL_MODE_3 2 | |||||
#define SDHCI_FSL_TBCTL_MODE_SW 3 | |||||
#define SDHCI_FSL_TBPTR 0x128 | |||||
#define SDHCI_FSL_TBPTR_WND_START 0x7F00 | |||||
#define SDHCI_FSL_TBPTR_WND_END 0x7F | |||||
#define SDHCI_FSL_SDCLKCTL 0x144 | |||||
#define SDHCI_FSL_SDCLKCTL_CMD_CLK_CTL (1 << 15) | |||||
#define SDHCI_FSL_SDCLKCTL_LPBK_CLK_SEL (1 << 31) | |||||
#define SDHCI_FSL_SDTIMINGCTL 0x148 | |||||
#define SDHCI_FSL_SDTIMINGCTL_FLW_CTL (1 << 15) | |||||
#define SDHCI_FSL_DLLCFG0 0x160 | |||||
#define SDHCI_FSL_DLLCFG0_FREQ_SEL (1 << 27) | |||||
#define SDHCI_FSL_DLLCFG0_EN (1 << 31) | |||||
#define SDHCI_FSL_DLLCFG1 0x164 | #define SDHCI_FSL_DLLCFG1 0x164 | ||||
#define SDHCI_FSL_DLLCFG1_PULSE_STRETCH (1 << 31) | #define SDHCI_FSL_DLLCFG1_PULSE_STRETCH (1 << 31) | ||||
#define SDHCI_FSL_DLLCFG1 0x164 | |||||
#define SDHCI_FSL_DLLCFG1_PULSE_STRETCH (1 << 31) | |||||
#define SDHCI_FSL_ESDHC_CTRL 0x40c | #define SDHCI_FSL_ESDHC_CTRL 0x40c | ||||
#define SDHCI_FSL_ESDHC_CTRL_SNOOP (1 << 6) | #define SDHCI_FSL_ESDHC_CTRL_SNOOP (1 << 6) | ||||
#define SDHCI_FSL_ESDHC_CTRL_FAF (1 << 18) | |||||
#define SDHCI_FSL_ESDHC_CTRL_CLK_DIV2 (1 << 19) | #define SDHCI_FSL_ESDHC_CTRL_CLK_DIV2 (1 << 19) | ||||
#define SDHCI_FSL_CAN_VDD_MASK \ | #define SDHCI_FSL_CAN_VDD_MASK \ | ||||
(SDHCI_CAN_VDD_180 | SDHCI_CAN_VDD_300 | SDHCI_CAN_VDD_330) | (SDHCI_CAN_VDD_180 | SDHCI_CAN_VDD_300 | SDHCI_CAN_VDD_330) | ||||
/* Some platforms do not detect pulse width correctly. */ | /* Some platforms do not detect pulse width correctly. */ | ||||
#define SDHCI_FSL_UNRELIABLE_PULSE_DET (1 << 0) | #define SDHCI_FSL_UNRELIABLE_PULSE_DET (1 << 0) | ||||
/* On some platforms switching voltage to 1.8V is not supported */ | /* On some platforms switching voltage to 1.8V is not supported */ | ||||
#define SDHCI_FSL_UNSUPP_1_8V (1 << 1) | #define SDHCI_FSL_UNSUPP_1_8V (1 << 1) | ||||
/* Hardware tuning can fail, fallback to SW tuning in that case. */ | |||||
#define SDHCI_FSL_TUNING_ERRATUM_TYPE1 (1 << 2) | |||||
/* | |||||
* Pointer window might not be set properly on some platforms. | |||||
contact_artur-rojek.eu: s/bo/be | |||||
* Check window and perform SW tuning. | |||||
*/ | |||||
#define SDHCI_FSL_TUNING_ERRATUM_TYPE2 (1 << 3) | |||||
/* | |||||
* In HS400 mode only 4, 8, 12 clock dividers can be used. | |||||
* Use the smallest value, bigger than requested in that case. | |||||
*/ | |||||
#define SDHCI_FSL_HS400_LIMITED_CLK_DIV (1 << 4) | |||||
#define SDHCI_FSL_HS400_FLAG (1 << 0) | |||||
#define SDHCI_FSL_SWITCH_TO_HS400_FLAG (1 << 1) | |||||
#define SDHCI_FSL_HS400_DONE (1 << 2) | |||||
#define SDHCI_FSL_MAX_RETRIES 10 | |||||
struct sdhci_fsl_fdt_softc { | struct sdhci_fsl_fdt_softc { | ||||
device_t dev; | device_t dev; | ||||
const struct sdhci_fsl_fdt_soc_data *soc_data; | const struct sdhci_fsl_fdt_soc_data *soc_data; | ||||
struct resource *mem_res; | struct resource *mem_res; | ||||
struct resource *irq_res; | struct resource *irq_res; | ||||
void *irq_cookie; | void *irq_cookie; | ||||
uint32_t baseclk_hz; | uint32_t baseclk_hz; | ||||
uint32_t maxclk_hz; | uint32_t maxclk_hz; | ||||
struct sdhci_fdt_gpio *gpio; | struct sdhci_fdt_gpio *gpio; | ||||
struct sdhci_slot slot; | struct sdhci_slot slot; | ||||
bool slot_init_done; | bool slot_init_done; | ||||
uint32_t cmd_and_mode; | uint32_t cmd_and_mode; | ||||
uint16_t sdclk_bits; | uint16_t sdclk_bits; | ||||
struct mmc_helper fdt_helper; | struct mmc_helper fdt_helper; | ||||
uint8_t vendor_ver; | uint8_t vendor_ver; | ||||
uint32_t flags; | |||||
enum mmc_bus_timing last_mode; | |||||
uint32_t (* read)(struct sdhci_fsl_fdt_softc *, bus_size_t); | uint32_t (* read)(struct sdhci_fsl_fdt_softc *, bus_size_t); | ||||
void (* write)(struct sdhci_fsl_fdt_softc *, bus_size_t, uint32_t); | void (* write)(struct sdhci_fsl_fdt_softc *, bus_size_t, uint32_t); | ||||
}; | }; | ||||
struct sdhci_fsl_fdt_soc_data { | struct sdhci_fsl_fdt_soc_data { | ||||
int quirks; | int quirks; | ||||
int baseclk_div; | int baseclk_div; | ||||
uint8_t errata; | uint8_t errata; | ||||
}; | }; | ||||
static const struct sdhci_fsl_fdt_soc_data sdhci_fsl_fdt_ls1012a_soc_data = { | static const struct sdhci_fsl_fdt_soc_data sdhci_fsl_fdt_ls1012a_soc_data = { | ||||
.quirks = 0, | .quirks = 0, | ||||
.baseclk_div = 1, | .baseclk_div = 1, | ||||
.errata = SDHCI_FSL_UNSUPP_1_8V, | .errata = SDHCI_FSL_UNSUPP_1_8V, | ||||
}; | }; | ||||
static const struct sdhci_fsl_fdt_soc_data sdhci_fsl_fdt_ls1028a_soc_data = { | static const struct sdhci_fsl_fdt_soc_data sdhci_fsl_fdt_ls1028a_soc_data = { | ||||
.quirks = SDHCI_QUIRK_DONT_SET_HISPD_BIT | | .quirks = SDHCI_QUIRK_DONT_SET_HISPD_BIT | | ||||
SDHCI_QUIRK_BROKEN_AUTO_STOP | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK, | SDHCI_QUIRK_BROKEN_AUTO_STOP | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK, | ||||
.baseclk_div = 2, | .baseclk_div = 2, | ||||
.errata = SDHCI_FSL_UNRELIABLE_PULSE_DET, | .errata = SDHCI_FSL_UNRELIABLE_PULSE_DET | | ||||
SDHCI_FSL_HS400_LIMITED_CLK_DIV, | |||||
}; | }; | ||||
static const struct sdhci_fsl_fdt_soc_data sdhci_fsl_fdt_ls1046a_soc_data = { | static const struct sdhci_fsl_fdt_soc_data sdhci_fsl_fdt_ls1046a_soc_data = { | ||||
.quirks = SDHCI_QUIRK_DONT_SET_HISPD_BIT | SDHCI_QUIRK_BROKEN_AUTO_STOP, | .quirks = SDHCI_QUIRK_DONT_SET_HISPD_BIT | SDHCI_QUIRK_BROKEN_AUTO_STOP, | ||||
.baseclk_div = 2, | .baseclk_div = 2, | ||||
.errata = SDHCI_FSL_UNSUPP_1_8V, | .errata = SDHCI_FSL_UNSUPP_1_8V, | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | do { \ | ||||
while ((freq) < (base) / ((pre) * (div)) && (div) < 16) \ | while ((freq) < (base) / ((pre) * (div)) && (div) < 16) \ | ||||
++(div); \ | ++(div); \ | ||||
} while (0) | } while (0) | ||||
static void | static void | ||||
fsl_sdhc_fdt_set_clock(struct sdhci_fsl_fdt_softc *sc, struct sdhci_slot *slot, | fsl_sdhc_fdt_set_clock(struct sdhci_fsl_fdt_softc *sc, struct sdhci_slot *slot, | ||||
uint16_t val) | uint16_t val) | ||||
{ | { | ||||
uint32_t prescale, div, val32; | uint32_t prescale, div, val32, div_ratio; | ||||
sc->sdclk_bits = val & SDHCI_DIVIDERS_MASK; | sc->sdclk_bits = val & SDHCI_DIVIDERS_MASK; | ||||
val32 = RD4(sc, SDHCI_CLOCK_CONTROL); | val32 = RD4(sc, SDHCI_CLOCK_CONTROL); | ||||
if ((val & SDHCI_CLOCK_CARD_EN) == 0) { | if ((val & SDHCI_CLOCK_CARD_EN) == 0) { | ||||
WR4(sc, SDHCI_CLOCK_CONTROL, val32 & ~SDHCI_FSL_CLK_SDCLKEN); | WR4(sc, SDHCI_CLOCK_CONTROL, val32 & ~SDHCI_FSL_CLK_SDCLKEN); | ||||
return; | return; | ||||
} | } | ||||
/* | /* | ||||
* Ignore dividers provided by core in `sdhci_set_clock` and calculate | * Ignore dividers provided by core in `sdhci_set_clock` and calculate | ||||
* them anew with higher accuracy. | * them anew with higher accuracy. | ||||
*/ | */ | ||||
SDHCI_FSL_FDT_CLK_DIV(sc, sc->baseclk_hz, slot->clock, prescale, div); | SDHCI_FSL_FDT_CLK_DIV(sc, sc->baseclk_hz, slot->clock, prescale, div); | ||||
#ifdef DEBUG | #ifdef DEBUG | ||||
device_printf(sc->dev, | device_printf(sc->dev, | ||||
"Desired SD/MMC freq: %d, actual: %d; base %d prescale %d divisor %d\n", | "Desired SD/MMC freq: %d, actual: %d; base %d prescale %d divisor %d\n", | ||||
slot->clock, sc->baseclk_hz / (prescale * div), | slot->clock, sc->baseclk_hz / (prescale * div), | ||||
sc->baseclk_hz, prescale, div); | sc->baseclk_hz, prescale, div); | ||||
#endif | #endif | ||||
div_ratio = prescale * div; | |||||
/* | |||||
* According to limited clock division erratum, clock dividers in hs400 | |||||
* can be only 4, 8 or 12 | |||||
*/ | |||||
if ((sc->soc_data->errata & SDHCI_FSL_HS400_LIMITED_CLK_DIV) && | |||||
(sc->slot.host.ios.timing == bus_timing_mmc_hs400 || | |||||
(sc->flags & SDHCI_FSL_HS400_FLAG))) { | |||||
if (div_ratio <= 4) { | |||||
prescale = 4; | |||||
div = 1; | |||||
} else if (div_ratio <= 8) { | |||||
prescale = 4; | |||||
div = 2; | |||||
} else if (div_ratio <= 12) { | |||||
prescale = 4; | |||||
div = 3; | |||||
} else { | |||||
device_printf(sc->dev, "Unsupported clock divider.\n"); | |||||
} | |||||
} | |||||
prescale >>= 1; | prescale >>= 1; | ||||
div -= 1; | div -= 1; | ||||
val32 &= ~(SDHCI_FSL_CLK_DIVIDER_MASK | SDHCI_FSL_CLK_PRESCALE_MASK); | val32 &= ~(SDHCI_FSL_CLK_DIVIDER_MASK | SDHCI_FSL_CLK_PRESCALE_MASK); | ||||
val32 |= div << SDHCI_FSL_CLK_DIVIDER_SHIFT; | val32 |= div << SDHCI_FSL_CLK_DIVIDER_SHIFT; | ||||
val32 |= prescale << SDHCI_FSL_CLK_PRESCALE_SHIFT; | val32 |= prescale << SDHCI_FSL_CLK_PRESCALE_SHIFT; | ||||
val32 |= SDHCI_FSL_CLK_IPGEN | SDHCI_FSL_CLK_SDCLKEN; | val32 |= SDHCI_FSL_CLK_IPGEN | SDHCI_FSL_CLK_SDCLKEN; | ||||
WR4(sc, SDHCI_CLOCK_CONTROL, val32); | WR4(sc, SDHCI_CLOCK_CONTROL, val32); | ||||
▲ Show 20 Lines • Show All 151 Lines • ▼ Show 20 Lines | case SDHCI_TRANSFER_MODE: | ||||
sc->cmd_and_mode = val; | sc->cmd_and_mode = val; | ||||
return; | return; | ||||
case SDHCI_COMMAND_FLAGS: | case SDHCI_COMMAND_FLAGS: | ||||
sc->cmd_and_mode = | sc->cmd_and_mode = | ||||
(sc->cmd_and_mode & UINT16_MAX) | (val << 16); | (sc->cmd_and_mode & UINT16_MAX) | (val << 16); | ||||
WR4(sc, SDHCI_TRANSFER_MODE, sc->cmd_and_mode); | WR4(sc, SDHCI_TRANSFER_MODE, sc->cmd_and_mode); | ||||
sc->cmd_and_mode = 0; | sc->cmd_and_mode = 0; | ||||
return; | return; | ||||
/* | |||||
* When switching to HS400 mode, setting these registers | |||||
* is required for successful tuning. | |||||
Not Done Inline Actionsnit: s/successfull/successful contact_artur-rojek.eu: nit: s/successfull/successful | |||||
*/ | |||||
case SDHCI_HOST_CONTROL2: | |||||
if ((val & SDHCI_CTRL2_MMC_HS400) && | |||||
(sc->flags & SDHCI_FSL_SWITCH_TO_HS400_FLAG)) { | |||||
val32 = RD4(sc, SDHCI_FSL_TBCTL); | |||||
val32 |= SDHCI_FSL_TBCTL_HS400_EN; | |||||
WR4(sc, SDHCI_FSL_TBCTL, val32); | |||||
val32 = RD4(sc, SDHCI_FSL_SDCLKCTL); | |||||
val32 |= SDHCI_FSL_SDCLKCTL_CMD_CLK_CTL; | |||||
WR4(sc, SDHCI_FSL_SDCLKCTL, val32); | |||||
} | |||||
val &= ~SDHCI_CTRL2_MMC_HS400; | |||||
default: | default: | ||||
val32 = RD4(sc, off & ~3); | val32 = RD4(sc, off & ~3); | ||||
val32 &= ~(UINT16_MAX << (off & 3) * 8); | val32 &= ~(UINT16_MAX << (off & 3) * 8); | ||||
val32 |= ((val & UINT16_MAX) << (off & 3) * 8); | val32 |= ((val & UINT16_MAX) << (off & 3) * 8); | ||||
WR4(sc, off & ~3, val32); | WR4(sc, off & ~3, val32); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 227 Lines • ▼ Show 20 Lines | if (vdd_mask != 0 && | ||||
(vdd_mask != (sc->slot.caps & SDHCI_FSL_CAN_VDD_MASK))) { | (vdd_mask != (sc->slot.caps & SDHCI_FSL_CAN_VDD_MASK))) { | ||||
sc->slot.caps &= ~(SDHCI_FSL_CAN_VDD_MASK); | sc->slot.caps &= ~(SDHCI_FSL_CAN_VDD_MASK); | ||||
sc->slot.caps |= vdd_mask; | sc->slot.caps |= vdd_mask; | ||||
sc->slot.quirks |= SDHCI_QUIRK_MISSING_CAPS; | sc->slot.quirks |= SDHCI_QUIRK_MISSING_CAPS; | ||||
} | } | ||||
} | } | ||||
static int | static int | ||||
sdhci_fsl_poll_register(struct sdhci_fsl_fdt_softc *sc, | |||||
uint32_t reg, uint32_t mask, int value) | |||||
{ | |||||
int retries; | |||||
retries = SDHCI_FSL_MAX_RETRIES; | |||||
while ((RD4(sc, reg) & mask) != value) { | |||||
if (!retries--) | |||||
return (ENXIO); | |||||
DELAY(10); | |||||
} | |||||
return (0); | |||||
} | |||||
static int | |||||
sdhci_fsl_fdt_attach(device_t dev) | sdhci_fsl_fdt_attach(device_t dev) | ||||
{ | { | ||||
struct sdhci_fsl_fdt_softc *sc; | struct sdhci_fsl_fdt_softc *sc; | ||||
struct mmc_host *host; | struct mmc_host *host; | ||||
uint32_t val, buf_order; | uint32_t val, buf_order; | ||||
uintptr_t ocd_data; | uintptr_t ocd_data; | ||||
uint64_t clk_hz; | uint64_t clk_hz; | ||||
phandle_t node; | phandle_t node; | ||||
int rid, ret; | int rid, ret; | ||||
clk_t clk; | clk_t clk; | ||||
node = ofw_bus_get_node(dev); | node = ofw_bus_get_node(dev); | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
ocd_data = ofw_bus_search_compatible(dev, | ocd_data = ofw_bus_search_compatible(dev, | ||||
sdhci_fsl_fdt_compat_data)->ocd_data; | sdhci_fsl_fdt_compat_data)->ocd_data; | ||||
sc->soc_data = (struct sdhci_fsl_fdt_soc_data *)ocd_data; | sc->soc_data = (struct sdhci_fsl_fdt_soc_data *)ocd_data; | ||||
sc->dev = dev; | sc->dev = dev; | ||||
sc->slot.quirks = sc->soc_data->quirks; | sc->slot.quirks = sc->soc_data->quirks; | ||||
sc->flags = 0; | |||||
sc->last_mode = bus_timing_normal; | |||||
host = &sc->slot.host; | host = &sc->slot.host; | ||||
rid = 0; | rid = 0; | ||||
sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, | sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, | ||||
RF_ACTIVE); | RF_ACTIVE); | ||||
if (sc->mem_res == NULL) { | if (sc->mem_res == NULL) { | ||||
device_printf(dev, | device_printf(dev, | ||||
"Could not allocate resources for controller\n"); | "Could not allocate resources for controller\n"); | ||||
▲ Show 20 Lines • Show All 210 Lines • ▼ Show 20 Lines | sdhci_fsl_fdt_reset(device_t dev, struct sdhci_slot *slot, uint8_t mask) | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
/* Some registers have to be cleared by hand. */ | /* Some registers have to be cleared by hand. */ | ||||
if (slot->version >= SDHCI_SPEC_300) { | if (slot->version >= SDHCI_SPEC_300) { | ||||
val = RD4(sc, SDHCI_FSL_TBCTL); | val = RD4(sc, SDHCI_FSL_TBCTL); | ||||
val &= ~SDHCI_FSL_TBCTL_TBEN; | val &= ~SDHCI_FSL_TBCTL_TBEN; | ||||
WR4(sc, SDHCI_FSL_TBCTL, val); | WR4(sc, SDHCI_FSL_TBCTL, val); | ||||
} | } | ||||
sc->flags &= ~SDHCI_FSL_HS400_DONE; | |||||
} | } | ||||
static void | |||||
sdhci_fsl_switch_tuning_block(device_t dev, bool enable) | |||||
{ | |||||
struct sdhci_fsl_fdt_softc *sc; | |||||
uint32_t reg; | |||||
sc = device_get_softc(dev); | |||||
reg = RD4(sc, SDHCI_FSL_TBCTL); | |||||
if (enable) | |||||
reg |= SDHCI_FSL_TBCTL_TBEN; | |||||
else | |||||
reg &= ~SDHCI_FSL_TBCTL_TBEN; | |||||
WR4(sc, SDHCI_FSL_TBCTL, reg); | |||||
} | |||||
static int | |||||
sdhci_hw_tuning(struct sdhci_fsl_fdt_softc *sc, device_t bus, device_t child, | |||||
bool hs400) | |||||
{ | |||||
int error, retries; | |||||
uint32_t reg; | |||||
retries = SDHCI_FSL_MAX_RETRIES; | |||||
/* Set SYSCTL2[EXTN] to start the tuning procedure. */ | |||||
reg = RD4(sc, SDHCI_FSL_AUTOCERR); | |||||
reg |= SDHCI_FSL_AUTOCERR_EXTN; | |||||
WR4(sc, SDHCI_FSL_AUTOCERR, reg); | |||||
while (true) { | |||||
/* Execute generic tuning to issue CMD19 and CMD21. */ | |||||
error = sdhci_generic_tune(bus, child, hs400); | |||||
if (error != 0) { | |||||
device_printf(bus, "Generic tuning failed.\n"); | |||||
return (error); | |||||
} | |||||
/* | |||||
* Tuning is done after a corresponding interrupt | |||||
* is set. | |||||
*/ | |||||
error = sdhci_fsl_poll_register(sc, SDHCI_FSL_IRQSTAT, | |||||
SDHCI_FSL_IRQSTAT_BRR, SDHCI_FSL_IRQSTAT_BRR); | |||||
if (error) | |||||
device_printf(sc->dev, | |||||
"Timeout while waiting for hardware to finish tuning.\n"); | |||||
/* Clear IRQSTAT[BRR] register. */ | |||||
reg = RD4(sc, SDHCI_FSL_IRQSTAT); | |||||
reg &= ~SDHCI_FSL_IRQSTAT_BRR; | |||||
WR4(sc, SDHCI_FSL_IRQSTAT, reg); | |||||
/* Check SYSCTL2[EXTN] register. */ | |||||
if ((RD4(sc, SDHCI_FSL_AUTOCERR) & | |||||
SDHCI_FSL_AUTOCERR_EXTN) == 0) | |||||
Not Done Inline ActionsThere's a lot of those repeating do-while loops in the code where you are polling on a particular register bit change. Why don't you create a helper function instead? And shouldn't it be while-do instead? E.g. you shouldn't incur delay penalty in case the bit in question is already off to begin with. contact_artur-rojek.eu: There's a lot of those repeating do-while loops in the code where you are polling on a… | |||||
break; | |||||
if (!retries--) { | |||||
error = ENXIO; | |||||
device_printf(bus, | |||||
"Failed to execute HW tuning.\n"); | |||||
break; | |||||
} | |||||
DELAY(10); | |||||
} | |||||
/* Check SYSCTL2[SMPCLKSEL]. */ | |||||
reg = RD4(sc, SDHCI_FSL_AUTOCERR); | |||||
if (!(reg & SDHCI_FSL_AUTOCERR_SMPCLKSEL)) { | |||||
error = ENXIO; | |||||
device_printf(bus, | |||||
"Hardware tuning failed. Turning off tuning block\n"); | |||||
sdhci_fsl_switch_tuning_block(bus, false); | |||||
} else | |||||
error = 0; | |||||
return (error); | |||||
} | |||||
static int | |||||
sdhci_fsl_sw_tuning(struct sdhci_fsl_fdt_softc *sc, device_t bus, | |||||
device_t child, bool hs400, uint32_t wnd_start, uint32_t wnd_end) | |||||
{ | |||||
uint32_t start_p, end_p, reg; | |||||
int error; | |||||
wnd_start = 5 * sc->soc_data->baseclk_div; | |||||
wnd_end = 3 * sc->soc_data->baseclk_div; | |||||
Not Done Inline ActionsSince this is the same type as above, why not list it at the same line as the remaining declarations? contact_artur-rojek.eu: Since this is the same type as above, why not list it at the same line as the remaining… | |||||
reg = RD4(sc, SDHCI_FSL_TBCTL); | |||||
reg &= ~SDHCI_FSL_TBCTL_TB_MODE_MASK; | |||||
reg |= SDHCI_FSL_TBCTL_MODE_SW; | |||||
WR4(sc, SDHCI_FSL_TBCTL, reg); | |||||
Not Done Inline ActionsDoesn't seem like it's ever used. contact_artur-rojek.eu: Doesn't seem like it's ever used. | |||||
reg = RD4(sc, SDHCI_FSL_TBPTR); | |||||
start_p = reg | SDHCI_FSL_TBPTR_WND_START; | |||||
end_p = reg | SDHCI_FSL_TBPTR_WND_END; | |||||
if (abs(start_p - end_p) > (4 * sc->soc_data->baseclk_div + 2)) { | |||||
wnd_start = 8 * sc->soc_data->baseclk_div; | |||||
wnd_end = 4 * sc->soc_data->baseclk_div; | |||||
} else { | |||||
wnd_start = 5 * sc->soc_data->baseclk_div; | |||||
wnd_end = 3 * sc->soc_data->baseclk_div; | |||||
} | |||||
reg |= (wnd_start << 14); | |||||
reg |= (wnd_end << 6); | |||||
WR4(sc, SDHCI_FSL_TBPTR, reg); | |||||
reg = RD4(sc, SDHCI_FSL_AUTOCERR); | |||||
reg |= SDHCI_FSL_AUTOCERR_EXTN | SDHCI_FSL_AUTOCERR_SMPCLKSEL; | |||||
WR4(sc, SDHCI_FSL_AUTOCERR, reg); | |||||
error = sdhci_generic_tune(bus, child, hs400); | |||||
if (error != 0) { | |||||
device_printf(bus, | |||||
"Failed to execute generic tune while performing software tuning.\n"); | |||||
return (error); | |||||
} | |||||
Not Done Inline ActionsThese two lines above can be concatenated into a single expression, as there is no need to be so explicit about these flags: contact_artur-rojek.eu: These two lines above can be concatenated into a single expression, as there is no need to be… | |||||
reg = RD4(sc, SDHCI_FSL_IRQSTAT); | |||||
reg &= ~SDHCI_FSL_IRQSTAT_BRR; | |||||
WR4(sc, SDHCI_FSL_IRQSTAT, reg); | |||||
reg = RD4(sc, SDHCI_FSL_AUTOCERR); | |||||
if (!(reg & SDHCI_FSL_AUTOCERR_SMPCLKSEL)) { | |||||
/* Error occured, need to disable tuning block. */ | |||||
reg = RD4(sc, SDHCI_FSL_TBCTL); | |||||
reg &= ~SDHCI_FSL_TBCTL_TBEN; | |||||
WR4(sc, SDHCI_FSL_TBCTL, reg); | |||||
error = ENXIO; | |||||
} | |||||
return (error); | |||||
} | |||||
static int | |||||
sdhci_fsl_fdt_tune(device_t bus, device_t child, bool hs400) | |||||
{ | |||||
uint32_t wnd_start, wnd_end, clk_divider, reg; | |||||
struct sdhci_fsl_fdt_softc *sc; | |||||
struct sdhci_slot *slot; | |||||
int error; | |||||
sc = device_get_softc(bus); | |||||
slot = device_get_ivars(child); | |||||
error = 0; | |||||
clk_divider = slot->max_clk / slot->clock; | |||||
/* For tuning mode SD clock divider must be within 3 to 16. */ | |||||
if (clk_divider < 3 || clk_divider > 16) | |||||
return (ENXIO); | |||||
if (hs400) | |||||
sc->flags |= SDHCI_FSL_HS400_FLAG; | |||||
/* Disable clock. */ | |||||
fsl_sdhc_fdt_set_clock(sc, slot, sc->sdclk_bits); | |||||
/* Wait for PRSSTAT[SDSTB] to be set by hardware. */ | |||||
error = sdhci_fsl_poll_register(sc, SDHCI_FSL_PRES_STATE, | |||||
SDHCI_FSL_PRES_SDSTB, SDHCI_FSL_PRES_SDSTB); | |||||
if (error != 0) | |||||
device_printf(bus, | |||||
"Timeout while waiting for hardware.\n"); | |||||
/* Set ESDHCCTL[FAF] register. */ | |||||
reg = RD4(sc, SDHCI_FSL_ESDHC_CTRL); | |||||
reg |= SDHCI_FSL_ESDHC_CTRL_FAF; | |||||
WR4(sc, SDHCI_FSL_ESDHC_CTRL, reg); | |||||
/* Wait for ESDHC[FAF] to be cleared by hardware. */ | |||||
error = sdhci_fsl_poll_register(sc, SDHCI_FSL_ESDHC_CTRL, | |||||
SDHCI_FSL_ESDHC_CTRL_FAF, 0); | |||||
if (error) | |||||
device_printf(bus, | |||||
"Timeout while waiting for hardware.\n"); | |||||
/* Set AUTOCERR[UHSM] register. */ | |||||
reg = RD4(sc, SDHCI_FSL_AUTOCERR); | |||||
reg &= ~SDHCI_FSL_AUTOCERR_UHMS; | |||||
reg |= SDHCI_FSL_AUTOCERR_UHMS_HS200; | |||||
WR4(sc, SDHCI_FSL_AUTOCERR, reg); | |||||
/* Set TBCTL[TB_EN] register and program valid tuning mode. */ | |||||
reg = RD4(sc, SDHCI_FSL_TBCTL); | |||||
reg &= ~SDHCI_FSL_TBCTL_TB_MODE_MASK; | |||||
reg |= SDHCI_FSL_TBCTL_TBEN | SDHCI_FSL_TBCTL_MODE_3; | |||||
WR4(sc, SDHCI_FSL_TBCTL, reg); | |||||
/* Enable clock. */ | |||||
fsl_sdhc_fdt_set_clock(sc, slot, SDHCI_CLOCK_CARD_EN | sc->sdclk_bits); | |||||
/* Wait for clock to stabilize. */ | |||||
error = sdhci_fsl_poll_register(sc, SDHCI_FSL_PRES_STATE, | |||||
SDHCI_FSL_PRES_SDSTB, SDHCI_FSL_PRES_SDSTB); | |||||
if (error) | |||||
device_printf(bus, | |||||
"Timeout while waiting for clock to stabilize.\n"); | |||||
/* Perform hardware tuning. */ | |||||
error = sdhci_hw_tuning(sc, bus, child, hs400); | |||||
reg = RD4(sc, SDHCI_FSL_TBPTR); | |||||
wnd_start = reg & SDHCI_FSL_TBPTR_WND_START; | |||||
wnd_end = reg & SDHCI_FSL_TBPTR_WND_END; | |||||
/* For erratum type2 affected platforms, check tuning pointer window. */ | |||||
if (sc->soc_data->errata & SDHCI_FSL_TUNING_ERRATUM_TYPE2) { | |||||
if (abs(wnd_start - wnd_end) > | |||||
(4 * sc->soc_data->baseclk_div + 2)) | |||||
error = ENXIO; | |||||
} | |||||
Not Done Inline ActionsAgain, no need to be explicit about these flags, we can just do: reg &= ~SDHCI_FSL_TBCTL_TB_MODE_MASK; reg |= SDHCI_FSL_TBCTL_TBEN | SDHCI_FSL_TBCTL_MODE_3; contact_artur-rojek.eu: Again, no need to be explicit about these flags, we can just do:
```
reg &=… | |||||
if (error != 0 && | |||||
(sc->soc_data->errata & | |||||
(SDHCI_FSL_TUNING_ERRATUM_TYPE1 | | |||||
SDHCI_FSL_TUNING_ERRATUM_TYPE2))) { | |||||
/* If hardware tuning failed, try software tuning. */ | |||||
error = sdhci_fsl_sw_tuning(sc, bus, child, hs400, wnd_start, | |||||
wnd_end); | |||||
if (error != 0) | |||||
device_printf(bus, "Software tuning failed.\n"); | |||||
} | |||||
if (error != 0) { | |||||
sdhci_fsl_switch_tuning_block(bus, false); | |||||
return (error); | |||||
} | |||||
if (hs400) { | |||||
reg = RD4(sc, SDHCI_FSL_SDTIMINGCTL); | |||||
reg |= SDHCI_FSL_SDTIMINGCTL_FLW_CTL; | |||||
WR4(sc, SDHCI_FSL_SDTIMINGCTL, reg); | |||||
/* | |||||
* Tuning block needs to be disabled now. | |||||
* It will be enabled by set_uhs_signalling | |||||
*/ | |||||
reg = RD4(sc, SDHCI_FSL_TBCTL); | |||||
reg &= ~SDHCI_FSL_TBCTL_TBEN; | |||||
WR4(sc, SDHCI_FSL_TBCTL, reg); | |||||
} | |||||
return (0); | |||||
} | |||||
static void | |||||
sdhci_fsl_disable_hs400_mode(device_t dev, struct sdhci_fsl_fdt_softc *sc) | |||||
{ | |||||
uint32_t reg; | |||||
int error; | |||||
reg = RD4(sc, SDHCI_FSL_SDTIMINGCTL); | |||||
reg &= ~SDHCI_FSL_SDTIMINGCTL_FLW_CTL; | |||||
WR4(sc, SDHCI_FSL_SDTIMINGCTL, reg); | |||||
reg = RD4(sc, SDHCI_FSL_SDCLKCTL); | |||||
reg &= ~SDHCI_FSL_SDCLKCTL_CMD_CLK_CTL; | |||||
WR4(sc, SDHCI_FSL_SDCLKCTL, reg); | |||||
fsl_sdhc_fdt_set_clock(sc, &sc->slot, sc->sdclk_bits); | |||||
error = sdhci_fsl_poll_register(sc, SDHCI_FSL_PRES_STATE, | |||||
SDHCI_FSL_PRES_SDSTB, SDHCI_FSL_PRES_SDSTB); | |||||
if (error != 0) | |||||
device_printf(dev, | |||||
"Internal clock never stabilized.\n"); | |||||
reg = RD4(sc, SDHCI_FSL_TBCTL); | |||||
reg &= ~SDHCI_FSL_TBCTL_HS400_EN; | |||||
WR4(sc, SDHCI_FSL_TBCTL, reg); | |||||
fsl_sdhc_fdt_set_clock(sc, &sc->slot, SDHCI_CLOCK_CARD_EN | | |||||
sc->sdclk_bits); | |||||
Not Done Inline ActionsFor else if (hs400) path, error will always evaluate to 0, so let's rewrite that section a bit: if (error != 0) { sdhci_fsl_switch_tuning_block(bus, false); return (error); } if (hs400) { ... } return (0); contact_artur-rojek.eu: For `else if (hs400)` path, `error` will always evaluate to `0`, so let's rewrite that section… | |||||
error = sdhci_fsl_poll_register(sc, SDHCI_FSL_PRES_STATE, | |||||
SDHCI_FSL_PRES_SDSTB, SDHCI_FSL_PRES_SDSTB); | |||||
if (error != 0) | |||||
device_printf(dev, | |||||
"Internal clock never stabilized.\n"); | |||||
reg = RD4(sc, SDHCI_FSL_DLLCFG0); | |||||
reg &= ~(SDHCI_FSL_DLLCFG0_EN | | |||||
SDHCI_FSL_DLLCFG0_FREQ_SEL); | |||||
WR4(sc, SDHCI_FSL_DLLCFG0, reg); | |||||
reg = RD4(sc, SDHCI_FSL_TBCTL); | |||||
reg &= ~SDHCI_FSL_TBCTL_HS400_WND_ADJ; | |||||
WR4(sc, SDHCI_FSL_TBCTL, reg); | |||||
sdhci_fsl_switch_tuning_block(dev, false); | |||||
} | |||||
static void | |||||
sdhci_fsl_enable_hs400_mode(device_t dev, struct sdhci_slot *slot, | |||||
struct sdhci_fsl_fdt_softc *sc) | |||||
{ | |||||
uint32_t reg; | |||||
int error; | |||||
sdhci_fsl_switch_tuning_block(dev, true); | |||||
fsl_sdhc_fdt_set_clock(sc, slot, sc->sdclk_bits); | |||||
error = sdhci_fsl_poll_register(sc, SDHCI_FSL_PRES_STATE, | |||||
SDHCI_FSL_PRES_SDSTB, SDHCI_FSL_PRES_SDSTB); | |||||
if (error != 0) | |||||
device_printf(dev, "Internal clock never stabilized.\n"); | |||||
fsl_sdhc_fdt_set_clock(sc, slot, SDHCI_CLOCK_CARD_EN | | |||||
sc->sdclk_bits); | |||||
error = sdhci_fsl_poll_register(sc, SDHCI_FSL_PRES_STATE, | |||||
SDHCI_FSL_PRES_SDSTB, SDHCI_FSL_PRES_SDSTB); | |||||
if (error != 0) | |||||
device_printf(dev, "Internal clock never stabilized.\n"); | |||||
reg = sc->read(sc, SDHCI_FSL_DLLCFG0); | |||||
reg |= SDHCI_FSL_DLLCFG0_EN | SDHCI_FSL_DLLCFG0_FREQ_SEL; | |||||
sc->write(sc, SDHCI_FSL_DLLCFG0, reg); | |||||
DELAY(20); | |||||
reg = sc->read(sc, SDHCI_FSL_TBCTL); | |||||
reg |= SDHCI_FSL_TBCTL_HS400_WND_ADJ; | |||||
Not Done Inline ActionsNo DELAY(10) here? contact_artur-rojek.eu: No `DELAY(10)` here? | |||||
sc->write(sc, SDHCI_FSL_TBCTL, reg); | |||||
fsl_sdhc_fdt_set_clock(sc, slot, sc->sdclk_bits); | |||||
error = sdhci_fsl_poll_register(sc, SDHCI_FSL_PRES_STATE, | |||||
SDHCI_FSL_PRES_SDSTB, SDHCI_FSL_PRES_SDSTB); | |||||
if (error != 0) | |||||
device_printf(dev, | |||||
"Timeout while waiting for clock to stabilize.\n"); | |||||
reg = sc->read(sc, SDHCI_FSL_ESDHC_CTRL); | |||||
reg |= SDHCI_FSL_ESDHC_CTRL_FAF; | |||||
sc->write(sc, SDHCI_FSL_ESDHC_CTRL, reg); | |||||
error = sdhci_fsl_poll_register(sc, SDHCI_FSL_ESDHC_CTRL, | |||||
SDHCI_FSL_ESDHC_CTRL_FAF, 0); | |||||
if (error != 0) | |||||
device_printf(dev, | |||||
"Timeout while waiting for hardware.\n"); | |||||
fsl_sdhc_fdt_set_clock(sc, slot, SDHCI_CLOCK_CARD_EN | | |||||
sc->sdclk_bits); | |||||
error = sdhci_fsl_poll_register(sc, SDHCI_FSL_PRES_STATE, | |||||
SDHCI_FSL_PRES_SDSTB, SDHCI_FSL_PRES_SDSTB); | |||||
if (error != 0) | |||||
device_printf(dev, | |||||
"Timeout while waiting for clock to stabilize.\n"); | |||||
sdhci_generic_set_uhs_timing(dev, slot); | |||||
sc->flags = SDHCI_FSL_HS400_DONE; | |||||
} | |||||
static void | |||||
sdhci_fsl_fdt_set_uhs_timing(device_t dev, struct sdhci_slot *slot) | |||||
{ | |||||
struct sdhci_fsl_fdt_softc *sc; | |||||
uint32_t reg; | |||||
sc = device_get_softc(dev); | |||||
if (sc->flags & SDHCI_FSL_HS400_DONE) | |||||
return; | |||||
reg = RD4(sc, SDHCI_FSL_TBCTL); | |||||
if (slot->host.ios.timing == bus_timing_hs && | |||||
(!(sc->flags & SDHCI_FSL_SWITCH_TO_HS400_FLAG)) && | |||||
sc->last_mode >= bus_timing_mmc_hs200) { | |||||
sdhci_fsl_switch_tuning_block(dev, false); | |||||
if (reg & SDHCI_FSL_TBCTL_HS400_EN) | |||||
sdhci_fsl_disable_hs400_mode(dev, sc); | |||||
sc->flags |= SDHCI_FSL_SWITCH_TO_HS400_FLAG; | |||||
return; | |||||
} | |||||
if ((slot->host.ios.timing == bus_timing_mmc_hs400) && | |||||
sc->flags & SDHCI_FSL_SWITCH_TO_HS400_FLAG) { | |||||
if (sc->last_mode < bus_timing_uhs_sdr50) { | |||||
sc->last_mode = sc->slot.host.ios.timing; | |||||
return; | |||||
} | |||||
sdhci_fsl_enable_hs400_mode(dev, slot, sc); | |||||
} else | |||||
sdhci_generic_set_uhs_timing(dev, slot); | |||||
sc->last_mode = sc->slot.host.ios.timing; | |||||
} | |||||
static const device_method_t sdhci_fsl_fdt_methods[] = { | static const device_method_t sdhci_fsl_fdt_methods[] = { | ||||
/* Device interface. */ | /* Device interface. */ | ||||
DEVMETHOD(device_probe, sdhci_fsl_fdt_probe), | DEVMETHOD(device_probe, sdhci_fsl_fdt_probe), | ||||
DEVMETHOD(device_attach, sdhci_fsl_fdt_attach), | DEVMETHOD(device_attach, sdhci_fsl_fdt_attach), | ||||
DEVMETHOD(device_detach, sdhci_fsl_fdt_detach), | DEVMETHOD(device_detach, sdhci_fsl_fdt_detach), | ||||
/* Bus interface. */ | /* Bus interface. */ | ||||
DEVMETHOD(bus_read_ivar, sdhci_fsl_fdt_read_ivar), | DEVMETHOD(bus_read_ivar, sdhci_fsl_fdt_read_ivar), | ||||
DEVMETHOD(bus_write_ivar, sdhci_fsl_fdt_write_ivar), | DEVMETHOD(bus_write_ivar, sdhci_fsl_fdt_write_ivar), | ||||
/* MMC bridge interface. */ | /* MMC bridge interface. */ | ||||
DEVMETHOD(mmcbr_request, sdhci_generic_request), | DEVMETHOD(mmcbr_request, sdhci_generic_request), | ||||
DEVMETHOD(mmcbr_get_ro, sdhci_fsl_fdt_get_ro), | DEVMETHOD(mmcbr_get_ro, sdhci_fsl_fdt_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_fsl_fdt_switch_vccq), | DEVMETHOD(mmcbr_switch_vccq, sdhci_fsl_fdt_switch_vccq), | ||||
DEVMETHOD(mmcbr_update_ios, sdhci_fsl_fdt_update_ios), | DEVMETHOD(mmcbr_update_ios, sdhci_fsl_fdt_update_ios), | ||||
DEVMETHOD(mmcbr_tune, sdhci_fsl_fdt_tune), | |||||
DEVMETHOD(mmcbr_retune, sdhci_generic_retune), | |||||
/* SDHCI accessors. */ | /* SDHCI accessors. */ | ||||
DEVMETHOD(sdhci_read_1, sdhci_fsl_fdt_read_1), | DEVMETHOD(sdhci_read_1, sdhci_fsl_fdt_read_1), | ||||
DEVMETHOD(sdhci_read_2, sdhci_fsl_fdt_read_2), | DEVMETHOD(sdhci_read_2, sdhci_fsl_fdt_read_2), | ||||
DEVMETHOD(sdhci_read_4, sdhci_fsl_fdt_read_4), | DEVMETHOD(sdhci_read_4, sdhci_fsl_fdt_read_4), | ||||
DEVMETHOD(sdhci_read_multi_4, sdhci_fsl_fdt_read_multi_4), | DEVMETHOD(sdhci_read_multi_4, sdhci_fsl_fdt_read_multi_4), | ||||
DEVMETHOD(sdhci_write_1, sdhci_fsl_fdt_write_1), | DEVMETHOD(sdhci_write_1, sdhci_fsl_fdt_write_1), | ||||
DEVMETHOD(sdhci_write_2, sdhci_fsl_fdt_write_2), | DEVMETHOD(sdhci_write_2, sdhci_fsl_fdt_write_2), | ||||
DEVMETHOD(sdhci_write_4, sdhci_fsl_fdt_write_4), | DEVMETHOD(sdhci_write_4, sdhci_fsl_fdt_write_4), | ||||
DEVMETHOD(sdhci_write_multi_4, sdhci_fsl_fdt_write_multi_4), | DEVMETHOD(sdhci_write_multi_4, sdhci_fsl_fdt_write_multi_4), | ||||
DEVMETHOD(sdhci_get_card_present, sdhci_fsl_fdt_get_card_present), | DEVMETHOD(sdhci_get_card_present, sdhci_fsl_fdt_get_card_present), | ||||
DEVMETHOD(sdhci_reset, sdhci_fsl_fdt_reset), | DEVMETHOD(sdhci_reset, sdhci_fsl_fdt_reset), | ||||
DEVMETHOD(sdhci_set_uhs_timing, sdhci_fsl_fdt_set_uhs_timing), | |||||
DEVMETHOD_END | DEVMETHOD_END | ||||
}; | }; | ||||
static devclass_t sdhci_fsl_fdt_devclass; | static devclass_t sdhci_fsl_fdt_devclass; | ||||
static driver_t sdhci_fsl_fdt_driver = { | static driver_t sdhci_fsl_fdt_driver = { | ||||
"sdhci_fsl_fdt", | "sdhci_fsl_fdt", | ||||
sdhci_fsl_fdt_methods, | sdhci_fsl_fdt_methods, | ||||
sizeof(struct sdhci_fsl_fdt_softc), | sizeof(struct sdhci_fsl_fdt_softc), | ||||
}; | }; | ||||
DRIVER_MODULE(sdhci_fsl_fdt, simplebus, sdhci_fsl_fdt_driver, | DRIVER_MODULE(sdhci_fsl_fdt, simplebus, sdhci_fsl_fdt_driver, | ||||
sdhci_fsl_fdt_devclass, NULL, NULL); | sdhci_fsl_fdt_devclass, NULL, NULL); | ||||
SDHCI_DEPEND(sdhci_fsl_fdt); | SDHCI_DEPEND(sdhci_fsl_fdt); | ||||
Not Done Inline ActionsAgain, unused. contact_artur-rojek.eu: Again, unused. | |||||
#ifndef MMCCAM | #ifndef MMCCAM | ||||
MMC_DECLARE_BRIDGE(sdhci_fsl_fdt); | MMC_DECLARE_BRIDGE(sdhci_fsl_fdt); | ||||
#endif | #endif |
s/bo/be