Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/sdhci/sdhci_fdt.c
Context not available. | |||||
#include <dev/ofw/ofw_bus.h> | #include <dev/ofw/ofw_bus.h> | ||||
#include <dev/ofw/ofw_bus_subr.h> | #include <dev/ofw/ofw_bus_subr.h> | ||||
#include <dev/extres/clk/clk.h> | |||||
#include <dev/extres/syscon/syscon.h> | |||||
manu: This needs to be undef ifdef EXT_RESOURCES.
Same comment for most of the thing below. | |||||
#include <dev/mmc/bridge.h> | #include <dev/mmc/bridge.h> | ||||
#include <dev/sdhci/sdhci.h> | #include <dev/sdhci/sdhci.h> | ||||
Context not available. | |||||
#include "opt_mmccam.h" | #include "opt_mmccam.h" | ||||
#include "syscon_if.h" | |||||
#define MAX_SLOTS 6 | #define MAX_SLOTS 6 | ||||
#define SDHCI_FDT_ARMADA38X 1 | #define SDHCI_FDT_ARMADA38X 1 | ||||
#define SDHCI_FDT_GENERIC 2 | #define SDHCI_FDT_GENERIC 2 | ||||
#define SDHCI_FDT_XLNX_ZY7 3 | #define SDHCI_FDT_XLNX_ZY7 3 | ||||
#define SDHCI_FDT_QUALCOMM 4 | #define SDHCI_FDT_QUALCOMM 4 | ||||
#define SDHCI_FDT_RK3399 5 | |||||
#define RK3399_GRF_EMMCCORE_CON0 0xf000 | |||||
#define RK3399_CORECFG_BASECLKFREQ (1 << 15) | (1 << 8) | |||||
#define RK3399_CORECFG_TIMEOUTCLKUNIT (1 << 7) | |||||
#define RK3399_CORECFG_TUNINGCOUNT (1 << 5) | (1 << 0) | |||||
#define RK3399_GRF_EMMCCORE_CON11 0xf02c | |||||
#define RK3399_CORECFG_CLOCKMULTIPLIER (1 << 7) | (1 << 0) | |||||
#define LOWEST_SET_BIT(mask) ((((mask) - 1) & (mask)) ^ (mask)) | |||||
#define SHIFTIN(x, mask) ((x) * LOWEST_SET_BIT(mask)) | |||||
static struct ofw_compat_data compat_data[] = { | static struct ofw_compat_data compat_data[] = { | ||||
{ "marvell,armada-380-sdhci", SDHCI_FDT_ARMADA38X }, | { "marvell,armada-380-sdhci", SDHCI_FDT_ARMADA38X }, | ||||
{ "sdhci_generic", SDHCI_FDT_GENERIC }, | { "sdhci_generic", SDHCI_FDT_GENERIC }, | ||||
{ "qcom,sdhci-msm-v4", SDHCI_FDT_QUALCOMM }, | { "qcom,sdhci-msm-v4", SDHCI_FDT_QUALCOMM }, | ||||
{ "rockchip,rk3399-sdhci-5.1", SDHCI_FDT_RK3399 }, | |||||
{ "xlnx,zy7_sdhci", SDHCI_FDT_XLNX_ZY7 }, | { "xlnx,zy7_sdhci", SDHCI_FDT_XLNX_ZY7 }, | ||||
{ NULL, 0 } | { NULL, 0 } | ||||
}; | }; | ||||
Context not available. | |||||
bool wp_inverted; /* WP pin is inverted */ | bool wp_inverted; /* WP pin is inverted */ | ||||
bool no_18v; /* No 1.8V support */ | bool no_18v; /* No 1.8V support */ | ||||
clk_t clk_xin; | |||||
clk_t clk_ahb; | |||||
}; | }; | ||||
static void | |||||
sdhc_init_rk3399(struct syscon *grf, phandle_t node, uint64_t freq) | |||||
{ | |||||
uint32_t mask, val; | |||||
/* Disable clock multiplier */ | |||||
mask = RK3399_CORECFG_CLOCKMULTIPLIER; | |||||
val = 0; | |||||
SYSCON_WRITE_4(grf, RK3399_GRF_EMMCCORE_CON11, (mask << 16) | val); | |||||
/* Set base clock frequency */ | |||||
mask = RK3399_CORECFG_BASECLKFREQ; | |||||
val = SHIFTIN((freq + (1000000 / 2)) / 1000000, | |||||
RK3399_CORECFG_BASECLKFREQ); | |||||
SYSCON_WRITE_4(grf, RK3399_GRF_EMMCCORE_CON0, (mask << 16) | val); | |||||
} | |||||
static uint8_t | static uint8_t | ||||
sdhci_fdt_read_1(device_t dev, struct sdhci_slot *slot, bus_size_t off) | sdhci_fdt_read_1(device_t dev, struct sdhci_slot *slot, bus_size_t off) | ||||
{ | { | ||||
Not Done Inline ActionsYou should validate that this was the emmcclock that was requested based on the cells content and return ENXIO if it wasn't manu: You should validate that this was the emmcclock that was requested based on the cells content… | |||||
Not Done Inline ActionsYou still don't validate the clock id based on cells[0] content. manu: You still don't validate the clock id based on cells[0] content. | |||||
Context not available. | |||||
sdhci_fdt_probe(device_t dev) | sdhci_fdt_probe(device_t dev) | ||||
{ | { | ||||
struct sdhci_fdt_softc *sc = device_get_softc(dev); | struct sdhci_fdt_softc *sc = device_get_softc(dev); | ||||
struct syscon *grf = NULL; | |||||
phandle_t node; | phandle_t node; | ||||
pcell_t cid; | pcell_t cid; | ||||
uint64_t freq; | |||||
int error; | |||||
sc->quirks = 0; | sc->quirks = 0; | ||||
sc->num_slots = 1; | sc->num_slots = 1; | ||||
Context not available. | |||||
if (!ofw_bus_status_okay(dev)) | if (!ofw_bus_status_okay(dev)) | ||||
return (ENXIO); | return (ENXIO); | ||||
node = ofw_bus_get_node(dev); | |||||
switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data) { | switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data) { | ||||
case SDHCI_FDT_ARMADA38X: | case SDHCI_FDT_ARMADA38X: | ||||
sc->quirks = SDHCI_QUIRK_BROKEN_AUTO_STOP; | sc->quirks = SDHCI_QUIRK_BROKEN_AUTO_STOP; | ||||
Context not available. | |||||
sc->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_4K; | sc->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_4K; | ||||
device_set_desc(dev, "Qualcomm FDT SDHCI controller"); | device_set_desc(dev, "Qualcomm FDT SDHCI controller"); | ||||
break; | break; | ||||
case SDHCI_FDT_RK3399: | |||||
/* Get and activate clocks */ | |||||
error = clk_get_by_ofw_name(dev, 0, "clk_xin", &sc->clk_xin); | |||||
if (error != 0) { | |||||
device_printf(dev, "cannot get xin clock\n"); | |||||
return (ENXIO); | |||||
} | |||||
error = clk_enable(sc->clk_xin); | |||||
if (error != 0) { | |||||
device_printf(dev, "cannot enable xin clock\n"); | |||||
return (ENXIO); | |||||
} | |||||
error = clk_get_freq(sc->clk_xin, &freq); | |||||
if (error != 0) { | |||||
device_printf(dev, "cannot get xin clock frequency\n"); | |||||
return (ENXIO); | |||||
} | |||||
error = clk_get_by_ofw_name(dev, 0, "clk_ahb", &sc->clk_ahb); | |||||
if (error != 0) { | |||||
device_printf(dev, "cannot get ahb clock\n"); | |||||
return (ENXIO); | |||||
} | |||||
error = clk_enable(sc->clk_ahb); | |||||
if (error != 0) { | |||||
device_printf(dev, "cannot enable ahb clock\n"); | |||||
return (ENXIO); | |||||
} | |||||
if (OF_hasprop(node, "arasan,soc-ctl-syscon") && | |||||
syscon_get_by_ofw_property(dev, node, | |||||
"arasan,soc-ctl-syscon", &grf) != 0) { | |||||
device_printf(dev, "cannot get grf driver handle\n"); | |||||
return (ENXIO); | |||||
} | |||||
andrewUnsubmitted Not Done Inline ActionsThis should be moved from probe to attach. andrew: This should be moved from probe to attach. | |||||
sdhc_init_rk3399(grf, node, freq); | |||||
device_set_desc(dev, "Rockchip RK3399 fdt SDHCI controller"); | |||||
break; | |||||
case SDHCI_FDT_XLNX_ZY7: | case SDHCI_FDT_XLNX_ZY7: | ||||
sc->quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK; | sc->quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK; | ||||
device_set_desc(dev, "Zynq-7000 generic fdt SDHCI controller"); | device_set_desc(dev, "Zynq-7000 generic fdt SDHCI controller"); | ||||
Context not available. | |||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
node = ofw_bus_get_node(dev); | |||||
/* Allow dts to patch quirks, slots, and max-frequency. */ | /* Allow dts to patch quirks, slots, and max-frequency. */ | ||||
if ((OF_getencprop(node, "quirks", &cid, sizeof(cid))) > 0) | if ((OF_getencprop(node, "quirks", &cid, sizeof(cid))) > 0) | ||||
sc->quirks = cid; | sc->quirks = cid; | ||||
Context not available. | |||||
Not Done Inline Actionsphy_init(sc->phy); manu: phy_init(sc->phy); | |||||
Not Done Inline ActionsI would prefer this block to be in a deticated rockchip function. manu: I would prefer this block to be in a deticated rockchip function. |
This needs to be undef ifdef EXT_RESOURCES.
Same comment for most of the thing below.