git: e00774a91750 - main - Add support for Rockchip RK3568 SDHCI controller.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 24 Dec 2022 12:40:55 UTC
The branch main has been updated by ganbold: URL: https://cgit.FreeBSD.org/src/commit/?id=e00774a917503e7e23c469954471c2b519e852c1 commit e00774a917503e7e23c469954471c2b519e852c1 Author: Søren Schmidt <sos@FreeBSD.org> AuthorDate: 2022-12-24 12:38:33 +0000 Commit: Ganbold Tsagaankhuu <ganbold@FreeBSD.org> CommitDate: 2022-12-24 12:38:33 +0000 Add support for Rockchip RK3568 SDHCI controller. --- sys/dev/sdhci/sdhci.c | 1 + sys/dev/sdhci/sdhci_fdt.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++ sys/dev/sdhci/sdhci_if.m | 14 +++++++ 3 files changed, 119 insertions(+) diff --git a/sys/dev/sdhci/sdhci.c b/sys/dev/sdhci/sdhci.c index d8532b132ac5..a7283e66df31 100644 --- a/sys/dev/sdhci/sdhci.c +++ b/sys/dev/sdhci/sdhci.c @@ -419,6 +419,7 @@ sdhci_set_clock(struct sdhci_slot *slot, uint32_t clock) if (clock == slot->clock) return; + clock = SDHCI_SET_CLOCK(slot->bus, slot, clock); slot->clock = clock; /* Turn off the clock. */ diff --git a/sys/dev/sdhci/sdhci_fdt.c b/sys/dev/sdhci/sdhci_fdt.c index f7e6eb27d180..dcc16a87a9f8 100644 --- a/sys/dev/sdhci/sdhci_fdt.c +++ b/sys/dev/sdhci/sdhci_fdt.c @@ -76,6 +76,7 @@ __FBSDID("$FreeBSD$"); #define SDHCI_FDT_XLNX_ZY7 3 #define SDHCI_FDT_QUALCOMM 4 #define SDHCI_FDT_RK3399 5 +#define SDHCI_FDT_RK3568 6 #define RK3399_GRF_EMMCCORE_CON0 0xf000 #define RK3399_CORECFG_BASECLKFREQ 0xff00 @@ -84,6 +85,33 @@ __FBSDID("$FreeBSD$"); #define RK3399_GRF_EMMCCORE_CON11 0xf02c #define RK3399_CORECFG_CLOCKMULTIPLIER 0xff +#define RK3568_EMMC_HOST_CTRL 0x0508 +#define RK3568_EMMC_EMMC_CTRL 0x052c +#define RK3568_EMMC_ATCTRL 0x0540 +#define RK3568_EMMC_DLL_CTRL 0x0800 +#define DLL_CTRL_SRST 0x00000001 +#define DLL_CTRL_START 0x00000002 +#define DLL_CTRL_START_POINT_DEFAULT 0x00050000 +#define DLL_CTRL_INCREMENT_DEFAULT 0x00000200 + +#define RK3568_EMMC_DLL_RXCLK 0x0804 +#define DLL_RXCLK_DELAY_ENABLE 0x08000000 +#define DLL_RXCLK_NO_INV 0x20000000 + +#define RK3568_EMMC_DLL_TXCLK 0x0808 +#define DLL_TXCLK_DELAY_ENABLE 0x08000000 +#define DLL_TXCLK_TAPNUM_DEFAULT 0x00000008 +#define DLL_TXCLK_TAPNUM_FROM_SW 0x01000000 + +#define RK3568_EMMC_DLL_STRBIN 0x080c +#define DLL_STRBIN_DELAY_ENABLE 0x08000000 +#define DLL_STRBIN_TAPNUM_DEFAULT 0x00000008 +#define DLL_STRBIN_TAPNUM_FROM_SW 0x01000000 + +#define RK3568_EMMC_DLL_STATUS0 0x0840 +#define DLL_STATUS0_DLL_LOCK 0x00000100 +#define DLL_STATUS0_DLL_TIMEOUT 0x00000200 + #define LOWEST_SET_BIT(mask) ((((mask) - 1) & (mask)) ^ (mask)) #define SHIFTIN(x, mask) ((x) * LOWEST_SET_BIT(mask)) @@ -95,6 +123,7 @@ static struct ofw_compat_data compat_data[] = { { "qcom,sdhci-msm-v4", SDHCI_FDT_QUALCOMM }, { "rockchip,rk3399-sdhci-5.1", SDHCI_FDT_RK3399 }, { "xlnx,zy7_sdhci", SDHCI_FDT_XLNX_ZY7 }, + { "rockchip,rk3568-dwcmshc", SDHCI_FDT_RK3568 }, { NULL, 0 } }; @@ -116,6 +145,7 @@ struct sdhci_fdt_softc { clk_t clk_xin; /* xin24m fixed clock */ clk_t clk_ahb; /* ahb clock */ + clk_t clk_core; /* core clock */ phy_t phy; /* phy to be used */ }; @@ -404,6 +434,66 @@ sdhci_fdt_get_ro(device_t bus, device_t dev) return (sdhci_generic_get_ro(bus, dev) ^ sc->wp_inverted); } +static int +sdhci_fdt_set_clock(device_t dev, struct sdhci_slot *slot, int clock) +{ + struct sdhci_fdt_softc *sc = device_get_softc(dev); + int32_t val; + int i; + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == + SDHCI_FDT_RK3568) { + if (clock == 400000) + clock = 375000; + + if (clock) { + clk_set_freq(sc->clk_core, clock, 0); + + if (clock <= 52000000) { + bus_write_4(sc->mem_res[slot->num], + RK3568_EMMC_DLL_CTRL, 0x0); + bus_write_4(sc->mem_res[slot->num], + RK3568_EMMC_DLL_RXCLK, DLL_RXCLK_NO_INV); + bus_write_4(sc->mem_res[slot->num], + RK3568_EMMC_DLL_TXCLK, 0x0); + bus_write_4(sc->mem_res[slot->num], + RK3568_EMMC_DLL_STRBIN, 0x0); + return (clock); + } + + bus_write_4(sc->mem_res[slot->num], + RK3568_EMMC_DLL_CTRL, DLL_CTRL_START); + DELAY(1000); + bus_write_4(sc->mem_res[slot->num], + RK3568_EMMC_DLL_CTRL, 0); + bus_write_4(sc->mem_res[slot->num], + RK3568_EMMC_DLL_CTRL, DLL_CTRL_START_POINT_DEFAULT | + DLL_CTRL_INCREMENT_DEFAULT | DLL_CTRL_START); + for (i = 0; i < 500; i++) { + val = bus_read_4(sc->mem_res[slot->num], + RK3568_EMMC_DLL_STATUS0); + if (val & DLL_STATUS0_DLL_LOCK && + !(val & DLL_STATUS0_DLL_TIMEOUT)) + break; + DELAY(1000); + } + bus_write_4(sc->mem_res[slot->num], RK3568_EMMC_ATCTRL, + (0x1 << 16 | 0x2 << 17 | 0x3 << 19)); + bus_write_4(sc->mem_res[slot->num], + RK3568_EMMC_DLL_RXCLK, + DLL_RXCLK_DELAY_ENABLE | DLL_RXCLK_NO_INV); + bus_write_4(sc->mem_res[slot->num], + RK3568_EMMC_DLL_TXCLK, DLL_TXCLK_DELAY_ENABLE | + DLL_TXCLK_TAPNUM_DEFAULT|DLL_TXCLK_TAPNUM_FROM_SW); + bus_write_4(sc->mem_res[slot->num], + RK3568_EMMC_DLL_STRBIN, DLL_STRBIN_DELAY_ENABLE | + DLL_STRBIN_TAPNUM_DEFAULT | + DLL_STRBIN_TAPNUM_FROM_SW); + } + } + return (clock); +} + static int sdhci_fdt_probe(device_t dev) { @@ -439,6 +529,9 @@ sdhci_fdt_probe(device_t dev) sc->quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK; device_set_desc(dev, "Zynq-7000 generic fdt SDHCI controller"); break; + case SDHCI_FDT_RK3568: + device_set_desc(dev, "Rockchip RK3568 fdt SDHCI controller"); + break; default: return (ENXIO); } @@ -488,6 +581,16 @@ sdhci_fdt_attach(device_t dev) } } + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == + SDHCI_FDT_RK3568) { + /* setup & enable clocks */ + if (clk_get_by_ofw_name(dev, 0, "core", &sc->clk_core)) { + device_printf(dev, "cannot get core clock\n"); + return (ENXIO); + } + clk_enable(sc->clk_core); + } + /* Scan all slots. */ slots = sc->num_slots; /* number of slots determined in probe(). */ sc->num_slots = 0; @@ -577,6 +680,7 @@ static device_method_t sdhci_fdt_methods[] = { DEVMETHOD(sdhci_write_2, sdhci_fdt_write_2), DEVMETHOD(sdhci_write_4, sdhci_fdt_write_4), DEVMETHOD(sdhci_write_multi_4, sdhci_fdt_write_multi_4), + DEVMETHOD(sdhci_set_clock, sdhci_fdt_set_clock), DEVMETHOD_END }; diff --git a/sys/dev/sdhci/sdhci_if.m b/sys/dev/sdhci/sdhci_if.m index c888f35bdaf0..531ef0e3adec 100644 --- a/sys/dev/sdhci/sdhci_if.m +++ b/sys/dev/sdhci/sdhci_if.m @@ -69,6 +69,14 @@ #include <dev/sdhci/sdhci.h> CODE { + static int + null_set_clock(device_t brdev __unused, + struct sdhci_slot *slot __unused, + int clock) + { + return (clock); + } + static void null_set_uhs_timing(device_t brdev __unused, struct sdhci_slot *slot __unused) @@ -165,6 +173,12 @@ METHOD void set_uhs_timing { struct sdhci_slot *slot; } DEFAULT null_set_uhs_timing; +METHOD int set_clock { + device_t brdev; + struct sdhci_slot *slot; + int clock; +} DEFAULT null_set_clock; + METHOD void reset { device_t brdev; struct sdhci_slot *slot;