sdhci_fsl_fdt.c: Add a missing call to mmc_fdt_parse.

Add a missing call to mmc_fdt_parse, without it some dts properties
are not parsed.

Submitted by: Lukasz Hajec <lha@semihalf.com>
Reviewed by: manu
Obtained from: Semihalf
Sponsored by: Alstom Group
Differential Revision: https://reviews.freebsd.org/D30122
This commit is contained in:
Marcin Wojtas 2021-04-22 12:54:41 +02:00
parent ffd61af32c
commit f0a9d7d799

View File

@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <dev/extres/clk/clk.h>
#include <dev/mmc/bridge.h>
#include <dev/mmc/mmcbrvar.h>
#include <dev/mmc/mmc_fdt_helpers.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/sdhci/sdhci.h>
@ -96,11 +97,13 @@ struct sdhci_fsl_fdt_softc {
struct resource *irq_res;
void *irq_cookie;
uint32_t baseclk_hz;
uint32_t maxclk_hz;
struct sdhci_fdt_gpio *gpio;
struct sdhci_slot slot;
bool slot_init_done;
uint32_t cmd_and_mode;
uint16_t sdclk_bits;
struct mmc_fdt_helper fdt_helper;
uint32_t (* read)(struct sdhci_fsl_fdt_softc *, bus_size_t);
void (* write)(struct sdhci_fsl_fdt_softc *, bus_size_t, uint32_t);
@ -194,9 +197,9 @@ fsl_sdhc_fdt_set_clock(struct sdhci_fsl_fdt_softc *sc, uint16_t val)
((val >> SDHCI_DIVIDER_HI_SHIFT) & SDHCI_DIVIDER_HI_MASK) <<
SDHCI_DIVIDER_MASK_LEN;
if (div == 0)
freq = sc->baseclk_hz;
freq = sc->maxclk_hz;
else
freq = sc->baseclk_hz / (2 * div);
freq = sc->maxclk_hz / (2 * div);
for (prescale = 2; freq < sc->baseclk_hz / (prescale * 16); )
prescale <<= 1;
@ -445,6 +448,86 @@ sdhci_fsl_fdt_irq(void *arg)
return;
}
static int
sdhci_fsl_fdt_update_ios(device_t brdev, device_t reqdev)
{
int err;
struct sdhci_fsl_fdt_softc *sc;
struct mmc_ios *ios;
struct sdhci_slot *slot;
err = sdhci_generic_update_ios(brdev, reqdev);
if (err != 0)
return (err);
sc = device_get_softc(brdev);
slot = device_get_ivars(reqdev);
ios = &slot->host.ios;
switch (ios->power_mode) {
case power_on:
break;
case power_off:
if (bootverbose)
device_printf(sc->dev, "Powering down sd/mmc\n");
if (sc->fdt_helper.vmmc_supply)
regulator_disable(sc->fdt_helper.vmmc_supply);
if (sc->fdt_helper.vqmmc_supply)
regulator_disable(sc->fdt_helper.vqmmc_supply);
break;
case power_up:
if (bootverbose)
device_printf(sc->dev, "Powering up sd/mmc\n");
if (sc->fdt_helper.vmmc_supply)
regulator_enable(sc->fdt_helper.vmmc_supply);
if (sc->fdt_helper.vqmmc_supply)
regulator_enable(sc->fdt_helper.vqmmc_supply);
break;
};
return (0);
}
static int
sdhci_fsl_fdt_switch_vccq(device_t brdev, device_t reqdev)
{
struct sdhci_fsl_fdt_softc *sc;
struct sdhci_slot *slot;
int uvolt, err;
err = sdhci_generic_switch_vccq(brdev, reqdev);
if (err != 0)
return (err);
sc = device_get_softc(brdev);
if (sc->fdt_helper.vqmmc_supply == NULL)
return EOPNOTSUPP;
slot = device_get_ivars(reqdev);
switch (slot->host.ios.vccq) {
case vccq_180:
uvolt = 1800000;
break;
case vccq_330:
uvolt = 3300000;
break;
default:
return EINVAL;
}
err = regulator_set_voltage(sc->fdt_helper.vqmmc_supply, uvolt, uvolt);
if (err != 0) {
device_printf(sc->dev,
"Cannot set vqmmc to %d<->%d\n", uvolt, uvolt);
return (err);
}
return (0);
}
static int
sdhci_fsl_fdt_get_ro(device_t bus, device_t child)
{
@ -463,10 +546,24 @@ sdhci_fsl_fdt_get_card_present(device_t dev, struct sdhci_slot *slot)
return (sdhci_fdt_gpio_get_present(sc->gpio));
}
static void
sdhci_fsl_fdt_of_parse(device_t dev)
{
struct sdhci_fsl_fdt_softc *sc;
phandle_t node;
sc = device_get_softc(dev);
node = ofw_bus_get_node(dev);
/* Call mmc_fdt_parse in order to get mmc related properties. */
mmc_fdt_parse(dev, node, &sc->fdt_helper, &sc->slot.host);
}
static int
sdhci_fsl_fdt_attach(device_t dev)
{
struct sdhci_fsl_fdt_softc *sc;
struct mmc_host *host;
uint32_t val, buf_order;
uintptr_t ocd_data;
uint64_t clk_hz;
@ -481,6 +578,7 @@ sdhci_fsl_fdt_attach(device_t dev)
sc->soc_data = (struct sdhci_fsl_fdt_soc_data *)ocd_data;
sc->dev = dev;
sc->slot.quirks = sc->soc_data->quirks;
host = &sc->slot.host;
rid = 0;
sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
@ -534,6 +632,9 @@ sdhci_fsl_fdt_attach(device_t dev)
buf_order = SDHCI_FSL_PROT_CTRL_BYTE_SWAP;
}
sdhci_fsl_fdt_of_parse(dev);
sc->maxclk_hz = host->f_max ? host->f_max : sc->baseclk_hz;
/*
* Setting this register affects byte order in SDHCI_BUFFER only.
* If the eSDHC block is connected over a big-endian bus, the data
@ -555,7 +656,7 @@ sdhci_fsl_fdt_attach(device_t dev)
WR4(sc, SDHCI_CLOCK_CONTROL, val & ~SDHCI_FSL_CLK_SDCLKEN);
val = RD4(sc, SDHCI_FSL_ESDHC_CTRL);
WR4(sc, SDHCI_FSL_ESDHC_CTRL, val | SDHCI_FSL_ESDHC_CTRL_CLK_DIV2);
sc->slot.max_clk = sc->baseclk_hz;
sc->slot.max_clk = sc->maxclk_hz;
sc->gpio = sdhci_fdt_gpio_setup(dev, &sc->slot);
/*
@ -656,11 +757,12 @@ static const device_method_t sdhci_fsl_fdt_methods[] = {
DEVMETHOD(bus_write_ivar, sdhci_generic_write_ivar),
/* MMC bridge interface. */
DEVMETHOD(mmcbr_update_ios, sdhci_generic_update_ios),
DEVMETHOD(mmcbr_request, sdhci_generic_request),
DEVMETHOD(mmcbr_get_ro, sdhci_fsl_fdt_get_ro),
DEVMETHOD(mmcbr_acquire_host, sdhci_generic_acquire_host),
DEVMETHOD(mmcbr_release_host, sdhci_generic_release_host),
DEVMETHOD(mmcbr_switch_vccq, sdhci_fsl_fdt_switch_vccq),
DEVMETHOD(mmcbr_update_ios, sdhci_fsl_fdt_update_ios),
/* SDHCI accessors. */
DEVMETHOD(sdhci_read_1, sdhci_fsl_fdt_read_1),