This series has some updates for the common SDHCI support and finally support for the eMMC controller found on Rockchip RK3568 SoCs. Sascha Hauer (12): mci: sdhci: straighten capabilities register mci: sdhci: Add and use SDHCI_CAPABILITIES_1 defines mci: sdhci: Use SDHCI_MAX_DIV_SPEC_200 define mci: sdhci: port over some common functions from Linux mci: sdhci: imx: Use sdhci_setup_host() mci: sdhci: Use Linux defines for SDHCI_HOST_CONTROL register mci: sdhci: arasan: Use sdhci_setup_host() mci: sdhci: arasan: Use sdhci_set_bus_width() mci: sdhci: Use Linux defines for SDHCI_CLOCK_CONTROL register mci: sdhci: arasan: Use sdhci_set_clock() mci: sdhci: Get rid of many register ops mci: Add support for Rockchip variant of the dwcmshc drivers/mci/Kconfig | 7 + drivers/mci/Makefile | 1 + drivers/mci/arasan-sdhci.c | 143 +--------- drivers/mci/atmel-sdhci-common.c | 72 ++--- drivers/mci/dove-sdhci.c | 84 ++---- drivers/mci/imx-esdhc-common.c | 21 +- drivers/mci/imx-esdhc-pbl.c | 20 +- drivers/mci/imx-esdhc.c | 20 +- drivers/mci/imx-esdhc.h | 8 - drivers/mci/rockchip-dwcmshc-sdhci.c | 382 +++++++++++++++++++++++++++ drivers/mci/sdhci.c | 281 ++++++++++++++++++++ drivers/mci/sdhci.h | 159 +++++++++-- include/mci.h | 2 + 13 files changed, 879 insertions(+), 321 deletions(-) create mode 100644 drivers/mci/rockchip-dwcmshc-sdhci.c -- 2.29.2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
So far we read the host capabilites register as two 16bit registers SDHCI_CAPABILITIES (0x40) and SDHCI_CAPABILITIES_1 (0x42). Read them as one 32bit register like Linux does. While at it switch to the register defines Linux uses. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/mci/arasan-sdhci.c | 12 ++++++------ drivers/mci/atmel-sdhci-common.c | 8 ++++---- drivers/mci/dove-sdhci.c | 15 +++++++-------- drivers/mci/imx-esdhc.c | 8 ++++---- drivers/mci/imx-esdhc.h | 7 ------- drivers/mci/sdhci.h | 23 +++++++++++++++++------ 6 files changed, 38 insertions(+), 35 deletions(-) diff --git a/drivers/mci/arasan-sdhci.c b/drivers/mci/arasan-sdhci.c index 520bf30ff9..53492e10d4 100644 --- a/drivers/mci/arasan-sdhci.c +++ b/drivers/mci/arasan-sdhci.c @@ -316,17 +316,17 @@ error: static void arasan_sdhci_set_mci_caps(struct arasan_sdhci_host *host) { - u16 caps = sdhci_read16(&host->sdhci, SDHCI_CAPABILITIES_1); + u32 caps = sdhci_read32(&host->sdhci, SDHCI_CAPABILITIES); - if ((caps & SDHCI_HOSTCAP_VOLTAGE_180) && + if ((caps & SDHCI_CAN_VDD_180) && !(host->quirks & SDHCI_ARASAN_QUIRK_NO_1_8_V)) host->mci.voltages |= MMC_VDD_165_195; - if (caps & SDHCI_HOSTCAP_VOLTAGE_300) + if (caps & SDHCI_CAN_VDD_300) host->mci.voltages |= MMC_VDD_29_30 | MMC_VDD_30_31; - if (caps & SDHCI_HOSTCAP_VOLTAGE_330) + if (caps & SDHCI_CAN_VDD_330) host->mci.voltages |= MMC_VDD_32_33 | MMC_VDD_33_34; - if (caps & SDHCI_HOSTCAP_HIGHSPEED) + if (caps & SDHCI_CAN_DO_HISPD) host->mci.host_caps |= (MMC_CAP_MMC_HIGHSPEED_52MHZ | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED); @@ -335,7 +335,7 @@ static void arasan_sdhci_set_mci_caps(struct arasan_sdhci_host *host) mci_of_parse(&host->mci); /* limit bus widths to controller capabilities */ - if (!(caps & SDHCI_HOSTCAP_8BIT)) + if (!(caps & SDHCI_CAN_DO_8BIT)) host->mci.host_caps &= ~MMC_CAP_8_BIT_DATA; } diff --git a/drivers/mci/atmel-sdhci-common.c b/drivers/mci/atmel-sdhci-common.c index a83610c3d0..92013feb95 100644 --- a/drivers/mci/atmel-sdhci-common.c +++ b/drivers/mci/atmel-sdhci-common.c @@ -42,13 +42,13 @@ void at91_sdhci_host_capability(struct at91_sdhci *host, { u16 caps; - caps = sdhci_read16(&host->sdhci, SDHCI_CAPABILITIES_1); + caps = sdhci_read32(&host->sdhci, SDHCI_CAPABILITIES); - if (caps & SDHCI_HOSTCAP_VOLTAGE_330) + if (caps & SDHCI_CAN_VDD_330) *voltages |= MMC_VDD_32_33 | MMC_VDD_33_34; - if (caps & SDHCI_HOSTCAP_VOLTAGE_300) + if (caps & SDHCI_CAN_VDD_300) *voltages |= MMC_VDD_29_30 | MMC_VDD_30_31; - if (caps & SDHCI_HOSTCAP_VOLTAGE_180) + if (caps & SDHCI_CAN_VDD_180) *voltages |= MMC_VDD_165_195; } diff --git a/drivers/mci/dove-sdhci.c b/drivers/mci/dove-sdhci.c index c734a6e0dd..945c4bb4b1 100644 --- a/drivers/mci/dove-sdhci.c +++ b/drivers/mci/dove-sdhci.c @@ -290,19 +290,18 @@ static int dove_sdhci_mci_init(struct mci_host *mci, struct device_d *dev) static void dove_sdhci_set_mci_caps(struct dove_sdhci *host) { - u16 caps[2]; + u32 caps; - caps[0] = sdhci_read16(&host->sdhci, SDHCI_CAPABILITIES); - caps[1] = sdhci_read16(&host->sdhci, SDHCI_CAPABILITIES_1); + caps = sdhci_read32(&host->sdhci, SDHCI_CAPABILITIES); - if (caps[1] & SDHCI_HOSTCAP_VOLTAGE_180) + if (caps & SDHCI_CAN_VDD_180) host->mci.voltages |= MMC_VDD_165_195; - if (caps[1] & SDHCI_HOSTCAP_VOLTAGE_300) + if (caps & SDHCI_CAN_VDD_300) host->mci.voltages |= MMC_VDD_29_30 | MMC_VDD_30_31; - if (caps[1] & SDHCI_HOSTCAP_VOLTAGE_330) + if (caps & SDHCI_CAN_VDD_330) host->mci.voltages |= MMC_VDD_32_33 | MMC_VDD_33_34; - if (caps[1] & SDHCI_HOSTCAP_HIGHSPEED) + if (caps & SDHCI_CAN_DO_HISPD) host->mci.host_caps |= (MMC_CAP_MMC_HIGHSPEED_52MHZ | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED); @@ -311,7 +310,7 @@ static void dove_sdhci_set_mci_caps(struct dove_sdhci *host) mci_of_parse(&host->mci); /* limit bus widths to controller capabilities */ - if ((caps[1] & SDHCI_HOSTCAP_8BIT) == 0) + if ((caps & SDHCI_CAN_DO_8BIT) == 0) host->mci.host_caps &= ~MMC_CAP_8_BIT_DATA; } diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c index 93f3c57d4e..fa858a9853 100644 --- a/drivers/mci/imx-esdhc.c +++ b/drivers/mci/imx-esdhc.c @@ -271,11 +271,11 @@ static int fsl_esdhc_probe(struct device_d *dev) caps = sdhci_read32(&host->sdhci, SDHCI_CAPABILITIES); - if (caps & ESDHC_HOSTCAPBLT_VS18) + if (caps & SDHCI_CAN_VDD_180) mci->voltages |= MMC_VDD_165_195; - if (caps & ESDHC_HOSTCAPBLT_VS30) + if (caps & SDHCI_CAN_VDD_300) mci->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31; - if (caps & ESDHC_HOSTCAPBLT_VS33) + if (caps & SDHCI_CAN_VDD_330) mci->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34; if (pdata) { @@ -284,7 +284,7 @@ static int fsl_esdhc_probe(struct device_d *dev) mci->devname = pdata->devname; } - if (caps & ESDHC_HOSTCAPBLT_HSS) + if (caps & SDHCI_CAN_DO_HISPD) mci->host_caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; host->mci.send_cmd = esdhc_send_cmd; diff --git a/drivers/mci/imx-esdhc.h b/drivers/mci/imx-esdhc.h index 8abe1207d7..0de1e72e7b 100644 --- a/drivers/mci/imx-esdhc.h +++ b/drivers/mci/imx-esdhc.h @@ -37,13 +37,6 @@ #define BLKATTR_SIZE(x) (x & 0x1fff) #define MAX_BLK_CNT 0x7fff /* so malloc will have enough room with 32M */ -#define ESDHC_HOSTCAPBLT_VS18 0x04000000 -#define ESDHC_HOSTCAPBLT_VS30 0x02000000 -#define ESDHC_HOSTCAPBLT_VS33 0x01000000 -#define ESDHC_HOSTCAPBLT_SRS 0x00800000 -#define ESDHC_HOSTCAPBLT_DMAS 0x00400000 -#define ESDHC_HOSTCAPBLT_HSS 0x00200000 - #define PIO_TIMEOUT 100000 #define IMX_SDHCI_WML 0x44 diff --git a/drivers/mci/sdhci.h b/drivers/mci/sdhci.h index 7b3f64486f..9bd9749dd6 100644 --- a/drivers/mci/sdhci.h +++ b/drivers/mci/sdhci.h @@ -105,12 +105,23 @@ #define SDHCI_SIGNAL_ENABLE 0x38 #define SDHCI_ACMD12_ERR__HOST_CONTROL2 0x3C #define SDHCI_CAPABILITIES 0x40 -#define SDHCI_CAPABILITIES_1 0x42 -#define SDHCI_HOSTCAP_VOLTAGE_180 BIT(10) -#define SDHCI_HOSTCAP_VOLTAGE_300 BIT(9) -#define SDHCI_HOSTCAP_VOLTAGE_330 BIT(8) -#define SDHCI_HOSTCAP_HIGHSPEED BIT(5) -#define SDHCI_HOSTCAP_8BIT BIT(2) +#define SDHCI_TIMEOUT_CLK_MASK GENMASK(5, 0) +#define SDHCI_TIMEOUT_CLK_UNIT 0x00000080 +#define SDHCI_CLOCK_BASE_MASK GENMASK(13, 8) +#define SDHCI_CLOCK_V3_BASE_MASK GENMASK(15, 8) +#define SDHCI_MAX_BLOCK_MASK 0x00030000 +#define SDHCI_MAX_BLOCK_SHIFT 16 +#define SDHCI_CAN_DO_8BIT 0x00040000 +#define SDHCI_CAN_DO_ADMA2 0x00080000 +#define SDHCI_CAN_DO_ADMA1 0x00100000 +#define SDHCI_CAN_DO_HISPD 0x00200000 +#define SDHCI_CAN_DO_SDMA 0x00400000 +#define SDHCI_CAN_DO_SUSPEND 0x00800000 +#define SDHCI_CAN_VDD_330 0x01000000 +#define SDHCI_CAN_VDD_300 0x02000000 +#define SDHCI_CAN_VDD_180 0x04000000 +#define SDHCI_CAN_64BIT_V4 0x08000000 +#define SDHCI_CAN_64BIT 0x10000000 #define SDHCI_CLOCK_MUL_MASK 0x00FF0000 #define SDHCI_CLOCK_MUL_SHIFT 16 -- 2.29.2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
Linux has defines for the SDHCI_CAPABILITIES_1 register at offset 0x44. Add these and convert the only user so far to use the defines. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/mci/atmel-sdhci-common.c | 6 ++---- drivers/mci/sdhci.h | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/mci/atmel-sdhci-common.c b/drivers/mci/atmel-sdhci-common.c index 92013feb95..b391775b00 100644 --- a/drivers/mci/atmel-sdhci-common.c +++ b/drivers/mci/atmel-sdhci-common.c @@ -24,8 +24,6 @@ #include "atmel-sdhci.h" -#define AT91_SDHCI_CA1R 0x44 /* Capabilities 1 Register */ - #define AT91_SDHCI_MC1R 0x204 #define AT91_SDHCI_MC1_FCD BIT(7) #define AT91_SDHCI_CALCR 0x240 @@ -237,9 +235,9 @@ static int at91_sdhci_set_clock(struct at91_sdhci *host, unsigned clock) if (clock == 0) return 0; - caps = sdhci_read32(sdhci, AT91_SDHCI_CA1R); + caps = sdhci_read32(sdhci, SDHCI_CAPABILITIES_1); - caps_clk_mult = (caps & SDHCI_CLOCK_MUL_MASK) >> SDHCI_CLOCK_MUL_SHIFT; + caps_clk_mult = FIELD_GET(SDHCI_CLOCK_MUL_MASK, caps); if (caps_clk_mult) { for (clk_div = 1; clk_div <= 1024; clk_div++) { diff --git a/drivers/mci/sdhci.h b/drivers/mci/sdhci.h index 9bd9749dd6..fd63cd84de 100644 --- a/drivers/mci/sdhci.h +++ b/drivers/mci/sdhci.h @@ -123,7 +123,20 @@ #define SDHCI_CAN_64BIT_V4 0x08000000 #define SDHCI_CAN_64BIT 0x10000000 -#define SDHCI_CLOCK_MUL_MASK 0x00FF0000 +#define SDHCI_CAPABILITIES_1 0x44 +#define SDHCI_SUPPORT_SDR50 0x00000001 +#define SDHCI_SUPPORT_SDR104 0x00000002 +#define SDHCI_SUPPORT_DDR50 0x00000004 +#define SDHCI_DRIVER_TYPE_A 0x00000010 +#define SDHCI_DRIVER_TYPE_C 0x00000020 +#define SDHCI_DRIVER_TYPE_D 0x00000040 +#define SDHCI_RETUNING_TIMER_COUNT_MASK GENMASK(11, 8) +#define SDHCI_USE_SDR50_TUNING 0x00002000 +#define SDHCI_RETUNING_MODE_MASK GENMASK(15, 14) +#define SDHCI_CLOCK_MUL_MASK GENMASK(23, 16) +#define SDHCI_CAN_DO_ADMA3 0x08000000 +#define SDHCI_SUPPORT_HS400 0x80000000 /* Non-standard */ + #define SDHCI_CLOCK_MUL_SHIFT 16 #define SDHCI_SPEC_200_MAX_CLK_DIVIDER 256 -- 2.29.2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
Linux uses SDHCI_MAX_DIV_SPEC_200 for what we have SDHCI_SPEC_200_MAX_CLK_DIVIDER. Also we have SDHCI_MAX_DIV_SPEC_300 defined in the arasan driver. Use the Linux defines and add them both to the header file. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/mci/arasan-sdhci.c | 2 -- drivers/mci/dove-sdhci.c | 2 +- drivers/mci/sdhci.h | 4 +++- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mci/arasan-sdhci.c b/drivers/mci/arasan-sdhci.c index 53492e10d4..e22db4cfa3 100644 --- a/drivers/mci/arasan-sdhci.c +++ b/drivers/mci/arasan-sdhci.c @@ -152,8 +152,6 @@ static int arasan_sdhci_init(struct mci_host *mci, struct device_d *dev) return 0; } -#define SDHCI_MAX_DIV_SPEC_300 2046 - static u16 arasan_sdhci_get_clock_divider(struct arasan_sdhci_host *host, unsigned int reqclk) { diff --git a/drivers/mci/dove-sdhci.c b/drivers/mci/dove-sdhci.c index 945c4bb4b1..9c10e67eb8 100644 --- a/drivers/mci/dove-sdhci.c +++ b/drivers/mci/dove-sdhci.c @@ -197,7 +197,7 @@ static u16 dove_sdhci_get_clock_divider(struct dove_sdhci *host, u32 reqclk) { u16 div; - for (div = 1; div < SDHCI_SPEC_200_MAX_CLK_DIVIDER; div *= 2) + for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) if ((host->mci.f_max / div) <= reqclk) break; div /= 2; diff --git a/drivers/mci/sdhci.h b/drivers/mci/sdhci.h index fd63cd84de..aa6dd9824e 100644 --- a/drivers/mci/sdhci.h +++ b/drivers/mci/sdhci.h @@ -139,9 +139,11 @@ #define SDHCI_CLOCK_MUL_SHIFT 16 -#define SDHCI_SPEC_200_MAX_CLK_DIVIDER 256 #define SDHCI_MMC_BOOT 0xC4 +#define SDHCI_MAX_DIV_SPEC_200 256 +#define SDHCI_MAX_DIV_SPEC_300 2046 + struct sdhci { u32 (*read32)(struct sdhci *host, int reg); u16 (*read16)(struct sdhci *host, int reg); -- 2.29.2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
This adds some functions useful for SDHCI drivers from Linux: sdhci_calc_clk() sdhci_set_clock() sdhci_enable_clk() sdhci_read_caps() sdhci_set_bus_width() These functions can be used to further unify our different SDHCI drivers. All the new functions assume the also newly introduced sdhci_setup_host() has been called before using them. The functions are moslty the same as their Linux pendants, only sdhci_calc_clk() takes an addional clock rate argument where Linux uses host->max_clk. This is not suitable for the upcoming Rockchip driver which needs to adjust the input clock using clk_set_rate(), so fixed host->max_clk is not accurate for this driver. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/mci/sdhci.c | 281 ++++++++++++++++++++++++++++++++++++++++++++ drivers/mci/sdhci.h | 53 +++++++++ include/mci.h | 2 + 3 files changed, 336 insertions(+) diff --git a/drivers/mci/sdhci.c b/drivers/mci/sdhci.c index dba26b2665..0783f6d420 100644 --- a/drivers/mci/sdhci.c +++ b/drivers/mci/sdhci.c @@ -4,6 +4,7 @@ #include <driver.h> #include <mci.h> #include <io.h> +#include <linux/bitfield.h> #include "sdhci.h" @@ -88,6 +89,27 @@ static void sdhci_tx_pio(struct sdhci *sdhci, struct mci_data *data, sdhci_write32(sdhci, SDHCI_BUFFER, buf[i]); } +void sdhci_set_bus_width(struct sdhci *host, int width) +{ + u8 ctrl; + + BUG_ON(!host->mci); /* Call sdhci_setup_host() before using this */ + + ctrl = sdhci_read8(host, SDHCI_HOST_CONTROL); + if (width == MMC_BUS_WIDTH_8) { + ctrl &= ~SDHCI_CTRL_4BITBUS; + ctrl |= SDHCI_CTRL_8BITBUS; + } else { + if (host->mci->host_caps & MMC_CAP_8_BIT_DATA) + ctrl &= ~SDHCI_CTRL_8BITBUS; + if (width == MMC_BUS_WIDTH_4) + ctrl |= SDHCI_CTRL_4BITBUS; + else + ctrl &= ~SDHCI_CTRL_4BITBUS; + } + sdhci_write8(host, SDHCI_HOST_CONTROL, ctrl); +} + #ifdef __PBL__ /* * Stubs to make timeout logic below work in PBL @@ -149,3 +171,262 @@ int sdhci_reset(struct sdhci *sdhci, u8 mask) val, !(val & mask), 100 * USEC_PER_MSEC); } + +static u16 sdhci_get_preset_value(struct sdhci *host) +{ + u16 preset = 0; + + BUG_ON(!host->mci); /* Call sdhci_setup_host() before using this */ + + switch (host->timing) { + case MMC_TIMING_UHS_SDR12: + preset = sdhci_read16(host, SDHCI_PRESET_FOR_SDR12); + break; + case MMC_TIMING_UHS_SDR25: + preset = sdhci_read16(host, SDHCI_PRESET_FOR_SDR25); + break; + case MMC_TIMING_UHS_SDR50: + preset = sdhci_read16(host, SDHCI_PRESET_FOR_SDR50); + break; + case MMC_TIMING_UHS_SDR104: + case MMC_TIMING_MMC_HS200: + preset = sdhci_read16(host, SDHCI_PRESET_FOR_SDR104); + break; + case MMC_TIMING_UHS_DDR50: + case MMC_TIMING_MMC_DDR52: + preset = sdhci_read16(host, SDHCI_PRESET_FOR_DDR50); + break; + case MMC_TIMING_MMC_HS400: + preset = sdhci_read16(host, SDHCI_PRESET_FOR_HS400); + break; + default: + dev_warn(host->mci->hw_dev, "Invalid UHS-I mode selected\n"); + preset = sdhci_read16(host, SDHCI_PRESET_FOR_SDR12); + break; + } + return preset; +} + +u16 sdhci_calc_clk(struct sdhci *host, unsigned int clock, + unsigned int *actual_clock, unsigned int input_clock) +{ + int div = 0; /* Initialized for compiler warning */ + int real_div = div, clk_mul = 1; + u16 clk = 0; + bool switch_base_clk = false; + + BUG_ON(!host->mci); /* Call sdhci_setup_host() before using this */ + + if (host->version >= SDHCI_SPEC_300) { + if (host->preset_enabled) { + u16 pre_val; + + clk = sdhci_read16(host, SDHCI_CLOCK_CONTROL); + pre_val = sdhci_get_preset_value(host); + div = FIELD_GET(SDHCI_PRESET_SDCLK_FREQ_MASK, pre_val); + if (host->clk_mul && + (pre_val & SDHCI_PRESET_CLKGEN_SEL)) { + clk = SDHCI_PROG_CLOCK_MODE; + real_div = div + 1; + clk_mul = host->clk_mul; + } else { + real_div = max_t(int, 1, div << 1); + } + goto clock_set; + } + + /* + * Check if the Host Controller supports Programmable Clock + * Mode. + */ + if (host->clk_mul) { + for (div = 1; div <= 1024; div++) { + if ((input_clock * host->clk_mul / div) + <= clock) + break; + } + if ((input_clock * host->clk_mul / div) <= clock) { + /* + * Set Programmable Clock Mode in the Clock + * Control register. + */ + clk = SDHCI_PROG_CLOCK_MODE; + real_div = div; + clk_mul = host->clk_mul; + div--; + } else { + /* + * Divisor can be too small to reach clock + * speed requirement. Then use the base clock. + */ + switch_base_clk = true; + } + } + + if (!host->clk_mul || switch_base_clk) { + /* Version 3.00 divisors must be a multiple of 2. */ + if (input_clock <= clock) + div = 1; + else { + for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; + div += 2) { + if ((input_clock / div) <= clock) + break; + } + } + real_div = div; + div >>= 1; + if ((host->quirks2 & SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN) + && !div && input_clock <= 25000000) + div = 1; + } + } else { + /* Version 2.00 divisors must be a power of 2. */ + for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) { + if ((input_clock / div) <= clock) + break; + } + real_div = div; + div >>= 1; + } + +clock_set: + if (real_div) + *actual_clock = (input_clock * clk_mul) / real_div; + clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; + clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) + << SDHCI_DIVIDER_HI_SHIFT; + + return clk; +} + +void sdhci_enable_clk(struct sdhci *host, u16 clk) +{ + u64 start; + + BUG_ON(!host->mci); /* Call sdhci_setup_host() before using this */ + + clk |= SDHCI_CLOCK_INT_EN; + sdhci_write16(host, SDHCI_CLOCK_CONTROL, clk); + + start = get_time_ns(); + while (!(sdhci_read16(host, SDHCI_CLOCK_CONTROL) & + SDHCI_CLOCK_INT_STABLE)) { + if (is_timeout(start, 150 * MSECOND)) { + dev_err(host->mci->hw_dev, + "SDHCI clock stable timeout\n"); + return; + } + } + + clk |= SDHCI_CLOCK_CARD_EN; + sdhci_write16(host, SDHCI_CLOCK_CONTROL, clk); +} + +void sdhci_set_clock(struct sdhci *host, unsigned int clock, unsigned int input_clock) +{ + u16 clk; + + BUG_ON(!host->mci); /* Call sdhci_setup_host() before using this */ + + host->mci->clock = 0; + + sdhci_write16(host, SDHCI_CLOCK_CONTROL, 0); + + if (clock == 0) + return; + + clk = sdhci_calc_clk(host, clock, &host->mci->clock, input_clock); + sdhci_enable_clk(host, clk); +} + +void __sdhci_read_caps(struct sdhci *host, const u16 *ver, + const u32 *caps, const u32 *caps1) +{ + u16 v; + u64 dt_caps_mask = 0; + u64 dt_caps = 0; + struct device_node *np = host->mci->hw_dev->device_node; + + BUG_ON(!host->mci); /* Call sdhci_setup_host() before using this */ + + if (host->read_caps) + return; + + host->read_caps = true; + + sdhci_reset(host, SDHCI_RESET_ALL); + + of_property_read_u64(np, "sdhci-caps-mask", &dt_caps_mask); + of_property_read_u64(np, "sdhci-caps", &dt_caps); + + v = ver ? *ver : sdhci_read16(host, SDHCI_HOST_VERSION); + host->version = (v & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT; + + if (host->quirks & SDHCI_QUIRK_MISSING_CAPS) + return; + + if (caps) { + host->caps = *caps; + } else { + host->caps = sdhci_read32(host, SDHCI_CAPABILITIES); + host->caps &= ~lower_32_bits(dt_caps_mask); + host->caps |= lower_32_bits(dt_caps); + } + + if (host->version < SDHCI_SPEC_300) + return; + + if (caps1) { + host->caps1 = *caps1; + } else { + host->caps1 = sdhci_read32(host, SDHCI_CAPABILITIES_1); + host->caps1 &= ~upper_32_bits(dt_caps_mask); + host->caps1 |= upper_32_bits(dt_caps); + } +} + +int sdhci_setup_host(struct sdhci *host) +{ + struct mci_host *mci = host->mci; + + BUG_ON(!mci); + + sdhci_read_caps(host); + + if (!host->max_clk) { + if (host->version >= SDHCI_SPEC_300) + host->max_clk = FIELD_GET(SDHCI_CLOCK_V3_BASE_MASK, host->caps); + else + host->max_clk = FIELD_GET(SDHCI_CLOCK_BASE_MASK, host->caps); + + host->max_clk *= 1000000; + } + + /* + * In case of Host Controller v3.00, find out whether clock + * multiplier is supported. + */ + host->clk_mul = FIELD_GET(SDHCI_CLOCK_MUL_MASK, host->caps1); + + /* + * In case the value in Clock Multiplier is 0, then programmable + * clock mode is not supported, otherwise the actual clock + * multiplier is one more than the value of Clock Multiplier + * in the Capabilities Register. + */ + if (host->clk_mul) + host->clk_mul += 1; + + if (host->caps & SDHCI_CAN_VDD_180) + mci->voltages |= MMC_VDD_165_195; + if (host->caps & SDHCI_CAN_VDD_300) + mci->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31; + if (host->caps & SDHCI_CAN_VDD_330) + mci->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34; + + if (host->caps & SDHCI_CAN_DO_HISPD) + mci->host_caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; + + return 0; +} diff --git a/drivers/mci/sdhci.h b/drivers/mci/sdhci.h index aa6dd9824e..872caabde5 100644 --- a/drivers/mci/sdhci.h +++ b/drivers/mci/sdhci.h @@ -69,7 +69,9 @@ #define SDHCI_BUS_POWER_EN BIT(0) #define SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET 0x2c #define SDHCI_CLOCK_CONTROL 0x2c +#define SDHCI_DIVIDER_SHIFT 8 #define SDHCI_DIVIDER_HI_SHIFT 6 +#define SDHCI_DIV_MASK 0xFF #define SDHCI_DIV_HI_MASK 0x300 #define SDHCI_DIV_MASK_LEN 8 #define SDHCI_FREQ_SEL(x) (((x) & 0xff) << 8) @@ -137,6 +139,27 @@ #define SDHCI_CAN_DO_ADMA3 0x08000000 #define SDHCI_SUPPORT_HS400 0x80000000 /* Non-standard */ +#define SDHCI_PRESET_FOR_SDR12 0x66 +#define SDHCI_PRESET_FOR_SDR25 0x68 +#define SDHCI_PRESET_FOR_SDR50 0x6A +#define SDHCI_PRESET_FOR_SDR104 0x6C +#define SDHCI_PRESET_FOR_DDR50 0x6E +#define SDHCI_PRESET_FOR_HS400 0x74 /* Non-standard */ +#define SDHCI_PRESET_CLKGEN_SEL BIT(10) +#define SDHCI_PRESET_SDCLK_FREQ_MASK GENMASK(9, 0) + +#define SDHCI_HOST_VERSION 0xFE +#define SDHCI_VENDOR_VER_MASK 0xFF00 +#define SDHCI_VENDOR_VER_SHIFT 8 +#define SDHCI_SPEC_VER_MASK 0x00FF +#define SDHCI_SPEC_VER_SHIFT 0 +#define SDHCI_SPEC_100 0 +#define SDHCI_SPEC_200 1 +#define SDHCI_SPEC_300 2 +#define SDHCI_SPEC_400 3 +#define SDHCI_SPEC_410 4 +#define SDHCI_SPEC_420 5 + #define SDHCI_CLOCK_MUL_SHIFT 16 #define SDHCI_MMC_BOOT 0xC4 @@ -151,6 +174,24 @@ struct sdhci { void (*write32)(struct sdhci *host, int reg, u32 val); void (*write16)(struct sdhci *host, int reg, u16 val); void (*write8)(struct sdhci *host, int reg, u8 val); + + int max_clk; /* Max possible freq (Hz) */ + int clk_mul; /* Clock Muliplier value */ + + unsigned int version; /* SDHCI spec. version */ + + enum mci_timing timing; + bool preset_enabled; /* Preset is enabled */ + + unsigned int quirks; +#define SDHCI_QUIRK_MISSING_CAPS BIT(27) + unsigned int quirks2; +#define SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN BIT(15) + u32 caps; /* CAPABILITY_0 */ + u32 caps1; /* CAPABILITY_1 */ + bool read_caps; /* Capability flags have been read */ + + struct mci_host *mci; }; static inline u32 sdhci_read32(struct sdhci *host, int reg) @@ -189,6 +230,18 @@ void sdhci_set_cmd_xfer_mode(struct sdhci *host, struct mci_cmd *cmd, u32 *xfer); int sdhci_transfer_data(struct sdhci *sdhci, struct mci_data *data); int sdhci_reset(struct sdhci *sdhci, u8 mask); +u16 sdhci_calc_clk(struct sdhci *host, unsigned int clock, + unsigned int *actual_clock, unsigned int input_clock); +void sdhci_set_clock(struct sdhci *host, unsigned int clock, unsigned int input_clock); +void sdhci_enable_clk(struct sdhci *host, u16 clk); +int sdhci_setup_host(struct sdhci *host); +void __sdhci_read_caps(struct sdhci *host, const u16 *ver, + const u32 *caps, const u32 *caps1); +static inline void sdhci_read_caps(struct sdhci *host) +{ + __sdhci_read_caps(host, NULL, NULL, NULL); +} +void sdhci_set_bus_width(struct sdhci *host, int width); #define sdhci_read8_poll_timeout(sdhci, reg, val, cond, timeout_us) \ read_poll_timeout(sdhci_read8, val, cond, timeout_us, sdhci, reg) diff --git a/include/mci.h b/include/mci.h index 5e6805e8dc..df2437f618 100644 --- a/include/mci.h +++ b/include/mci.h @@ -365,6 +365,8 @@ enum mci_timing { MMC_TIMING_UHS_SDR104 = 4, MMC_TIMING_UHS_DDR50 = 5, MMC_TIMING_MMC_HS200 = 6, + MMC_TIMING_MMC_DDR52 = 7, + MMC_TIMING_MMC_HS400 = 8, }; struct mci_ios { -- 2.29.2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
sdhci_setup_host() handles reading the caps. Call it instead of doing it in the driver. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/mci/imx-esdhc.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c index fa858a9853..12e98ce26a 100644 --- a/drivers/mci/imx-esdhc.c +++ b/drivers/mci/imx-esdhc.c @@ -230,7 +230,6 @@ static int fsl_esdhc_probe(struct device_d *dev) struct resource *iores; struct fsl_esdhc_host *host; struct mci_host *mci; - u32 caps; int ret; unsigned long rate; struct esdhc_platform_data *pdata = dev->platform_data; @@ -269,29 +268,22 @@ static int fsl_esdhc_probe(struct device_d *dev) esdhc_populate_sdhci(host); - caps = sdhci_read32(&host->sdhci, SDHCI_CAPABILITIES); - - if (caps & SDHCI_CAN_VDD_180) - mci->voltages |= MMC_VDD_165_195; - if (caps & SDHCI_CAN_VDD_300) - mci->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31; - if (caps & SDHCI_CAN_VDD_330) - mci->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34; - if (pdata) { mci->host_caps = pdata->caps; if (pdata->devname) mci->devname = pdata->devname; } - if (caps & SDHCI_CAN_DO_HISPD) - mci->host_caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; - host->mci.send_cmd = esdhc_send_cmd; host->mci.set_ios = esdhc_set_ios; host->mci.init = esdhc_init; host->mci.card_present = esdhc_card_present; host->mci.hw_dev = dev; + host->sdhci.mci = &host->mci; + + ret = sdhci_setup_host(&host->sdhci); + if (ret) + goto err_clk_disable; rate = clk_get_rate(host->clk); host->mci.f_min = rate >> 12; -- 2.29.2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
To ease porting and comparing of Linux code. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/mci/arasan-sdhci.c | 12 ++++++------ drivers/mci/atmel-sdhci-common.c | 14 +++++++------- drivers/mci/dove-sdhci.c | 10 +++++----- drivers/mci/sdhci.h | 17 ++++++++++++----- 4 files changed, 30 insertions(+), 23 deletions(-) diff --git a/drivers/mci/arasan-sdhci.c b/drivers/mci/arasan-sdhci.c index e22db4cfa3..e02f222345 100644 --- a/drivers/mci/arasan-sdhci.c +++ b/drivers/mci/arasan-sdhci.c @@ -124,7 +124,7 @@ static int arasan_sdhci_reset(struct arasan_sdhci_host *host, u8 mask) u8 ctrl; ctrl = sdhci_read8(&host->sdhci, SDHCI_HOST_CONTROL); - ctrl |= SDHCI_CARD_DETECT_TEST_LEVEL | SDHCI_CARD_DETECT_SIGNAL_SELECTION; + ctrl |= SDHCI_CTRL_CDTEST_INS | SDHCI_CTRL_CDTEST_INS; sdhci_write8(&host->sdhci, ctrl, SDHCI_HOST_CONTROL); } @@ -200,21 +200,21 @@ static void arasan_sdhci_set_ios(struct mci_host *mci, struct mci_ios *ios) } val = sdhci_read8(&host->sdhci, SDHCI_HOST_CONTROL) & - ~(SDHCI_DATA_WIDTH_4BIT | SDHCI_DATA_WIDTH_8BIT); + ~(SDHCI_CTRL_8BITBUS | SDHCI_CTRL_8BITBUS); switch (ios->bus_width) { case MMC_BUS_WIDTH_8: - val |= SDHCI_DATA_WIDTH_8BIT; + val |= SDHCI_CTRL_8BITBUS; break; case MMC_BUS_WIDTH_4: - val |= SDHCI_DATA_WIDTH_4BIT; + val |= SDHCI_CTRL_8BITBUS; break; } if (ios->clock > 26000000) - val |= SDHCI_HIGHSPEED_EN; + val |= SDHCI_CTRL_HISPD; else - val &= ~SDHCI_HIGHSPEED_EN; + val &= ~SDHCI_CTRL_HISPD; sdhci_write8(&host->sdhci, SDHCI_HOST_CONTROL, val); } diff --git a/drivers/mci/atmel-sdhci-common.c b/drivers/mci/atmel-sdhci-common.c index b391775b00..d2b777a93c 100644 --- a/drivers/mci/atmel-sdhci-common.c +++ b/drivers/mci/atmel-sdhci-common.c @@ -279,9 +279,9 @@ static int at91_sdhci_set_clock(struct at91_sdhci *host, unsigned clock) reg = sdhci_read8(sdhci, SDHCI_HOST_CONTROL); if (clock > 26000000) - reg |= SDHCI_HIGHSPEED_EN; + reg |= SDHCI_CTRL_HISPD; else - reg &= ~SDHCI_HIGHSPEED_EN; + reg &= ~SDHCI_CTRL_HISPD; sdhci_write8(sdhci, SDHCI_HOST_CONTROL, reg); @@ -297,15 +297,15 @@ static int at91_sdhci_set_bus_width(struct at91_sdhci *host, unsigned bus_width) switch(bus_width) { case MMC_BUS_WIDTH_8: - reg |= SDHCI_DATA_WIDTH_8BIT; + reg |= SDHCI_CTRL_8BITBUS; break; case MMC_BUS_WIDTH_4: - reg &= ~SDHCI_DATA_WIDTH_8BIT; - reg |= SDHCI_DATA_WIDTH_4BIT; + reg &= ~SDHCI_CTRL_8BITBUS; + reg |= SDHCI_CTRL_8BITBUS; break; default: - reg &= ~SDHCI_DATA_WIDTH_8BIT; - reg &= ~SDHCI_DATA_WIDTH_4BIT; + reg &= ~SDHCI_CTRL_8BITBUS; + reg &= ~SDHCI_CTRL_8BITBUS; } sdhci_write8(sdhci, SDHCI_HOST_CONTROL, reg); diff --git a/drivers/mci/dove-sdhci.c b/drivers/mci/dove-sdhci.c index 9c10e67eb8..cafc9dc579 100644 --- a/drivers/mci/dove-sdhci.c +++ b/drivers/mci/dove-sdhci.c @@ -224,20 +224,20 @@ static void dove_sdhci_mci_set_ios(struct mci_host *mci, struct mci_ios *ios) /* set bus width */ val = sdhci_read8(&host->sdhci, SDHCI_HOST_CONTROL) & - ~(SDHCI_DATA_WIDTH_4BIT | SDHCI_DATA_WIDTH_8BIT); + ~(SDHCI_CTRL_8BITBUS | SDHCI_CTRL_8BITBUS); switch (ios->bus_width) { case MMC_BUS_WIDTH_8: - val |= SDHCI_DATA_WIDTH_8BIT; + val |= SDHCI_CTRL_8BITBUS; break; case MMC_BUS_WIDTH_4: - val |= SDHCI_DATA_WIDTH_4BIT; + val |= SDHCI_CTRL_8BITBUS; break; } if (ios->clock > 26000000) - val |= SDHCI_HIGHSPEED_EN; + val |= SDHCI_CTRL_HISPD; else - val &= ~SDHCI_HIGHSPEED_EN; + val &= ~SDHCI_CTRL_HISPD; sdhci_write8(&host->sdhci, SDHCI_HOST_CONTROL, val); diff --git a/drivers/mci/sdhci.h b/drivers/mci/sdhci.h index 872caabde5..0b436d3aa2 100644 --- a/drivers/mci/sdhci.h +++ b/drivers/mci/sdhci.h @@ -54,11 +54,18 @@ #define SDHCI_PRESENT_STATE1 0x26 #define SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL 0x28 #define SDHCI_HOST_CONTROL 0x28 -#define SDHCI_CARD_DETECT_SIGNAL_SELECTION BIT(7) -#define SDHCI_CARD_DETECT_TEST_LEVEL BIT(6) -#define SDHCI_DATA_WIDTH_8BIT BIT(5) -#define SDHCI_HIGHSPEED_EN BIT(2) -#define SDHCI_DATA_WIDTH_4BIT BIT(1) +#define SDHCI_CTRL_LED BIT(0) +#define SDHCI_CTRL_4BITBUS BIT(1) +#define SDHCI_CTRL_HISPD BIT(2) +#define SDHCI_CTRL_DMA_MASK 0x18 +#define SDHCI_CTRL_SDMA 0x00 +#define SDHCI_CTRL_ADMA1 0x08 +#define SDHCI_CTRL_ADMA32 0x10 +#define SDHCI_CTRL_ADMA64 0x18 +#define SDHCI_CTRL_ADMA3 0x18 +#define SDHCI_CTRL_8BITBUS BIT(5) +#define SDHCI_CTRL_CDTEST_INS BIT(6) +#define SDHCI_CTRL_CDTEST_EN BIT(7) #define SDHCI_POWER_CONTROL 0x29 #define SDHCI_POWER_ON 0x01 #define SDHCI_POWER_180 0x0A -- 2.29.2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
Use common code instead of duplicating it in the driver. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/mci/arasan-sdhci.c | 32 +++++--------------------------- 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/drivers/mci/arasan-sdhci.c b/drivers/mci/arasan-sdhci.c index e02f222345..acc2827f1d 100644 --- a/drivers/mci/arasan-sdhci.c +++ b/drivers/mci/arasan-sdhci.c @@ -311,32 +311,6 @@ error: return ret; } - -static void arasan_sdhci_set_mci_caps(struct arasan_sdhci_host *host) -{ - u32 caps = sdhci_read32(&host->sdhci, SDHCI_CAPABILITIES); - - if ((caps & SDHCI_CAN_VDD_180) && - !(host->quirks & SDHCI_ARASAN_QUIRK_NO_1_8_V)) - host->mci.voltages |= MMC_VDD_165_195; - if (caps & SDHCI_CAN_VDD_300) - host->mci.voltages |= MMC_VDD_29_30 | MMC_VDD_30_31; - if (caps & SDHCI_CAN_VDD_330) - host->mci.voltages |= MMC_VDD_32_33 | MMC_VDD_33_34; - - if (caps & SDHCI_CAN_DO_HISPD) - host->mci.host_caps |= (MMC_CAP_MMC_HIGHSPEED_52MHZ | - MMC_CAP_MMC_HIGHSPEED | - MMC_CAP_SD_HIGHSPEED); - - /* parse board supported bus width capabilities */ - mci_of_parse(&host->mci); - - /* limit bus widths to controller capabilities */ - if (!(caps & SDHCI_CAN_DO_8BIT)) - host->mci.host_caps &= ~MMC_CAP_8_BIT_DATA; -} - static int arasan_sdhci_probe(struct device_d *dev) { struct device_node *np = dev->device_node; @@ -391,6 +365,7 @@ static int arasan_sdhci_probe(struct device_d *dev) arasan_sdhci->sdhci.write32 = arasan_sdhci_writel; arasan_sdhci->sdhci.write16 = arasan_sdhci_writew; arasan_sdhci->sdhci.write8 = arasan_sdhci_writeb; + arasan_sdhci->sdhci.mci = mci; mci->send_cmd = arasan_sdhci_send_cmd; mci->set_ios = arasan_sdhci_set_ios; mci->init = arasan_sdhci_init; @@ -401,7 +376,10 @@ static int arasan_sdhci_probe(struct device_d *dev) mci->f_max = clk_get_rate(clk_xin); mci->f_min = 50000000 / 256; - arasan_sdhci_set_mci_caps(arasan_sdhci); + /* parse board supported bus width capabilities */ + mci_of_parse(&arasan_sdhci->mci); + + sdhci_setup_host(&arasan_sdhci->sdhci); dev->priv = arasan_sdhci; -- 2.29.2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
Use common code rather than duplicating it in the driver. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/mci/arasan-sdhci.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/mci/arasan-sdhci.c b/drivers/mci/arasan-sdhci.c index acc2827f1d..7bd98c0a96 100644 --- a/drivers/mci/arasan-sdhci.c +++ b/drivers/mci/arasan-sdhci.c @@ -199,17 +199,9 @@ static void arasan_sdhci_set_ios(struct mci_host *mci, struct mci_ios *ios) val | SDHCI_SDCLOCK_EN); } - val = sdhci_read8(&host->sdhci, SDHCI_HOST_CONTROL) & - ~(SDHCI_CTRL_8BITBUS | SDHCI_CTRL_8BITBUS); - - switch (ios->bus_width) { - case MMC_BUS_WIDTH_8: - val |= SDHCI_CTRL_8BITBUS; - break; - case MMC_BUS_WIDTH_4: - val |= SDHCI_CTRL_8BITBUS; - break; - } + sdhci_set_bus_width(&host->sdhci, ios->bus_width); + + val = sdhci_read8(&host->sdhci, SDHCI_HOST_CONTROL); if (ios->clock > 26000000) val |= SDHCI_CTRL_HISPD; -- 2.29.2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
Convert another register to use the Linux defines. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/mci/arasan-sdhci.c | 6 +++--- drivers/mci/atmel-sdhci-common.c | 6 +++--- drivers/mci/dove-sdhci.c | 6 +++--- drivers/mci/sdhci.h | 13 +++++++------ 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/mci/arasan-sdhci.c b/drivers/mci/arasan-sdhci.c index 7bd98c0a96..180f0042bf 100644 --- a/drivers/mci/arasan-sdhci.c +++ b/drivers/mci/arasan-sdhci.c @@ -182,12 +182,12 @@ static void arasan_sdhci_set_ios(struct mci_host *mci, struct mci_ios *ios) val = arasan_sdhci_get_clock_divider(host, ios->clock); /* Bit 6 & 7 are upperbits of 10bit divider */ val = SDHCI_FREQ_SEL(val) | SDHCI_FREQ_SEL_10_BIT(val); - val |= SDHCI_INTCLOCK_EN; + val |= SDHCI_CLOCK_INT_EN; sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, val); start = get_time_ns(); while (!(sdhci_read16(&host->sdhci, SDHCI_CLOCK_CONTROL) & - SDHCI_INTCLOCK_STABLE)) { + SDHCI_CLOCK_INT_STABLE)) { if (is_timeout(start, 20 * MSECOND)) { dev_err(host->mci.hw_dev, "SDHCI clock stable timeout\n"); @@ -196,7 +196,7 @@ static void arasan_sdhci_set_ios(struct mci_host *mci, struct mci_ios *ios) } /* enable bus clock */ sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, - val | SDHCI_SDCLOCK_EN); + val | SDHCI_CLOCK_CARD_EN); } sdhci_set_bus_width(&host->sdhci, ios->bus_width); diff --git a/drivers/mci/atmel-sdhci-common.c b/drivers/mci/atmel-sdhci-common.c index d2b777a93c..5a734d0d47 100644 --- a/drivers/mci/atmel-sdhci-common.c +++ b/drivers/mci/atmel-sdhci-common.c @@ -262,19 +262,19 @@ static int at91_sdhci_set_clock(struct at91_sdhci *host, unsigned clock) clk |= SDHCI_FREQ_SEL(clk_div); clk |= ((clk_div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) << SDHCI_DIVIDER_HI_SHIFT; - clk |= SDHCI_INTCLOCK_EN; + clk |= SDHCI_CLOCK_INT_EN; sdhci_write16(sdhci, SDHCI_CLOCK_CONTROL, clk); ret = sdhci_read32_poll_timeout(sdhci, SDHCI_CLOCK_CONTROL, clk, - clk & SDHCI_INTCLOCK_STABLE, + clk & SDHCI_CLOCK_INT_STABLE, 20 * USEC_PER_MSEC); if (ret) { dev_warn(host->dev, "Timeout waiting for clock stable\n"); return ret; } - clk |= SDHCI_SDCLOCK_EN; + clk |= SDHCI_CLOCK_CARD_EN; sdhci_write16(sdhci, SDHCI_CLOCK_CONTROL, clk); reg = sdhci_read8(sdhci, SDHCI_HOST_CONTROL); diff --git a/drivers/mci/dove-sdhci.c b/drivers/mci/dove-sdhci.c index cafc9dc579..f4f8dabba1 100644 --- a/drivers/mci/dove-sdhci.c +++ b/drivers/mci/dove-sdhci.c @@ -244,13 +244,13 @@ static void dove_sdhci_mci_set_ios(struct mci_host *mci, struct mci_ios *ios) /* set bus clock */ sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, 0); val = dove_sdhci_get_clock_divider(host, ios->clock); - val = SDHCI_INTCLOCK_EN | SDHCI_FREQ_SEL(val); + val = SDHCI_CLOCK_INT_EN | SDHCI_FREQ_SEL(val); sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, val); /* wait for internal clock stable */ start = get_time_ns(); while (!(sdhci_read16(&host->sdhci, SDHCI_CLOCK_CONTROL) & - SDHCI_INTCLOCK_STABLE)) { + SDHCI_CLOCK_INT_STABLE)) { if (is_timeout(start, 20 * MSECOND)) { dev_err(host->mci.hw_dev, "SDHCI clock stable timeout\n"); return; @@ -258,7 +258,7 @@ static void dove_sdhci_mci_set_ios(struct mci_host *mci, struct mci_ios *ios) } /* enable bus clock */ - sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, val | SDHCI_SDCLOCK_EN); + sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, val | SDHCI_CLOCK_CARD_EN); } static int dove_sdhci_mci_init(struct mci_host *mci, struct device_d *dev) diff --git a/drivers/mci/sdhci.h b/drivers/mci/sdhci.h index 0b436d3aa2..2605ecb535 100644 --- a/drivers/mci/sdhci.h +++ b/drivers/mci/sdhci.h @@ -75,17 +75,18 @@ #define SDHCI_BUS_VOLTAGE(v) ((v) << 1) #define SDHCI_BUS_POWER_EN BIT(0) #define SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET 0x2c -#define SDHCI_CLOCK_CONTROL 0x2c +#define SDHCI_CLOCK_CONTROL 0x2C #define SDHCI_DIVIDER_SHIFT 8 #define SDHCI_DIVIDER_HI_SHIFT 6 #define SDHCI_DIV_MASK 0xFF -#define SDHCI_DIV_HI_MASK 0x300 #define SDHCI_DIV_MASK_LEN 8 -#define SDHCI_FREQ_SEL(x) (((x) & 0xff) << 8) +#define SDHCI_FREQ_SEL(x) (((x) & 0xff) << 8) +#define SDHCI_DIV_HI_MASK 0x300 #define SDHCI_PROG_CLOCK_MODE BIT(5) -#define SDHCI_SDCLOCK_EN BIT(2) -#define SDHCI_INTCLOCK_STABLE BIT(1) -#define SDHCI_INTCLOCK_EN BIT(0) +#define SDHCI_CLOCK_CARD_EN BIT(2) +#define SDHCI_CLOCK_PLL_EN BIT(3) +#define SDHCI_CLOCK_INT_STABLE BIT(1) +#define SDHCI_CLOCK_INT_EN BIT(0) #define SDHCI_TIMEOUT_CONTROL 0x2e #define SDHCI_SOFTWARE_RESET 0x2f #define SDHCI_RESET_ALL BIT(0) -- 2.29.2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
We now have a function to calculate the clock divider. Use it. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/mci/arasan-sdhci.c | 40 ++------------------------------------ 1 file changed, 2 insertions(+), 38 deletions(-) diff --git a/drivers/mci/arasan-sdhci.c b/drivers/mci/arasan-sdhci.c index 180f0042bf..8a5e85109c 100644 --- a/drivers/mci/arasan-sdhci.c +++ b/drivers/mci/arasan-sdhci.c @@ -152,21 +152,6 @@ static int arasan_sdhci_init(struct mci_host *mci, struct device_d *dev) return 0; } -static u16 arasan_sdhci_get_clock_divider(struct arasan_sdhci_host *host, - unsigned int reqclk) -{ - u16 div; - - for (div = 1; div < SDHCI_MAX_DIV_SPEC_300; div += 2) - if ((host->mci.f_max / div) <= reqclk) - break; - div /= 2; - - return div; -} - -#define SDHCI_FREQ_SEL_10_BIT(x) (((x) & 0x300) >> 2) - static void arasan_sdhci_set_ios(struct mci_host *mci, struct mci_ios *ios) { struct arasan_sdhci_host *host = to_arasan_sdhci_host(mci); @@ -175,29 +160,8 @@ static void arasan_sdhci_set_ios(struct mci_host *mci, struct mci_ios *ios) /* stop clock */ sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, 0); - if (ios->clock) { - u64 start; - - /* set & start clock */ - val = arasan_sdhci_get_clock_divider(host, ios->clock); - /* Bit 6 & 7 are upperbits of 10bit divider */ - val = SDHCI_FREQ_SEL(val) | SDHCI_FREQ_SEL_10_BIT(val); - val |= SDHCI_CLOCK_INT_EN; - sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, val); - - start = get_time_ns(); - while (!(sdhci_read16(&host->sdhci, SDHCI_CLOCK_CONTROL) & - SDHCI_CLOCK_INT_STABLE)) { - if (is_timeout(start, 20 * MSECOND)) { - dev_err(host->mci.hw_dev, - "SDHCI clock stable timeout\n"); - return; - } - } - /* enable bus clock */ - sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, - val | SDHCI_CLOCK_CARD_EN); - } + if (ios->clock) + sdhci_set_clock(&host->sdhci, ios->clock, host->sdhci.max_clk); sdhci_set_bus_width(&host->sdhci, ios->bus_width); -- 2.29.2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
Most SDHCI drivers use standard readl/writel to access registers. Implement these in the common register accessor functions so that drivers only to overwrite them when they want to do something different. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/mci/arasan-sdhci.c | 51 +------------------------------- drivers/mci/atmel-sdhci-common.c | 38 +----------------------- drivers/mci/dove-sdhci.c | 51 +------------------------------- drivers/mci/imx-esdhc-common.c | 21 +++++++------ drivers/mci/imx-esdhc-pbl.c | 20 ++++++------- drivers/mci/imx-esdhc.c | 2 +- drivers/mci/imx-esdhc.h | 1 - drivers/mci/sdhci.h | 32 ++++++++++++++++---- 8 files changed, 50 insertions(+), 166 deletions(-) diff --git a/drivers/mci/arasan-sdhci.c b/drivers/mci/arasan-sdhci.c index 8a5e85109c..c19e1022c5 100644 --- a/drivers/mci/arasan-sdhci.c +++ b/drivers/mci/arasan-sdhci.c @@ -33,7 +33,6 @@ struct arasan_sdhci_host { struct mci_host mci; struct sdhci sdhci; - void __iomem *ioaddr; unsigned int quirks; /* Arasan deviations from spec */ /* Controller does not have CD wired and will not function normally without */ #define SDHCI_ARASAN_QUIRK_FORCE_CDTEST BIT(0) @@ -53,48 +52,6 @@ struct arasan_sdhci_host *sdhci_to_arasan(struct sdhci *sdhci) return container_of(sdhci, struct arasan_sdhci_host, sdhci); } -static void arasan_sdhci_writel(struct sdhci *sdhci, int reg, u32 val) -{ - struct arasan_sdhci_host *p = sdhci_to_arasan(sdhci); - - writel(val, p->ioaddr + reg); -} - -static void arasan_sdhci_writew(struct sdhci *sdhci, int reg, u16 val) -{ - struct arasan_sdhci_host *p = sdhci_to_arasan(sdhci); - - writew(val, p->ioaddr + reg); -} - -static void arasan_sdhci_writeb(struct sdhci *sdhci, int reg, u8 val) -{ - struct arasan_sdhci_host *p = sdhci_to_arasan(sdhci); - - writeb(val, p->ioaddr + reg); -} - -static u32 arasan_sdhci_readl(struct sdhci *sdhci, int reg) -{ - struct arasan_sdhci_host *p = sdhci_to_arasan(sdhci); - - return readl(p->ioaddr + reg); -} - -static u16 arasan_sdhci_readw(struct sdhci *sdhci, int reg) -{ - struct arasan_sdhci_host *p = sdhci_to_arasan(sdhci); - - return readw(p->ioaddr + reg); -} - -static u8 arasan_sdhci_readb(struct sdhci *sdhci, int reg) -{ - struct arasan_sdhci_host *p = sdhci_to_arasan(sdhci); - - return readb(p->ioaddr + reg); -} - static int arasan_sdhci_card_present(struct mci_host *mci) { struct arasan_sdhci_host *host = to_arasan_sdhci_host(mci); @@ -283,7 +240,6 @@ static int arasan_sdhci_probe(struct device_d *dev) iores = dev_request_mem_resource(dev, 0); if (IS_ERR(iores)) return PTR_ERR(iores); - arasan_sdhci->ioaddr = IOMEM(iores->start); clk_ahb = clk_get(dev, "clk_ahb"); if (IS_ERR(clk_ahb)) { @@ -315,12 +271,7 @@ static int arasan_sdhci_probe(struct device_d *dev) if (of_property_read_bool(np, "no-1-8-v")) arasan_sdhci->quirks |= SDHCI_ARASAN_QUIRK_NO_1_8_V; - arasan_sdhci->sdhci.read32 = arasan_sdhci_readl; - arasan_sdhci->sdhci.read16 = arasan_sdhci_readw; - arasan_sdhci->sdhci.read8 = arasan_sdhci_readb; - arasan_sdhci->sdhci.write32 = arasan_sdhci_writel; - arasan_sdhci->sdhci.write16 = arasan_sdhci_writew; - arasan_sdhci->sdhci.write8 = arasan_sdhci_writeb; + arasan_sdhci->sdhci.base = IOMEM(iores->start); arasan_sdhci->sdhci.mci = mci; mci->send_cmd = arasan_sdhci_send_cmd; mci->set_ios = arasan_sdhci_set_ios; diff --git a/drivers/mci/atmel-sdhci-common.c b/drivers/mci/atmel-sdhci-common.c index 5a734d0d47..be8b6b38c3 100644 --- a/drivers/mci/atmel-sdhci-common.c +++ b/drivers/mci/atmel-sdhci-common.c @@ -377,43 +377,7 @@ int at91_sdhci_init(struct at91_sdhci *host, u32 maxclk, return 0; } -static u32 at91_sdhci_read32(struct sdhci *sdhci, int reg) -{ - return readl(to_priv(sdhci)->base + reg); -} - -static void at91_sdhci_write32(struct sdhci *sdhci, int reg, u32 value) -{ - writel(value, to_priv(sdhci)->base + reg); -} - -static u16 at91_sdhci_read16(struct sdhci *sdhci, int reg) -{ - return readw(to_priv(sdhci)->base + reg); -} - -static void at91_sdhci_write16(struct sdhci *sdhci, int reg, u16 value) -{ - writew(value, to_priv(sdhci)->base + reg); -} - -static u8 at91_sdhci_read8(struct sdhci *sdhci, int reg) -{ - return readb(to_priv(sdhci)->base + reg); -} - -static void at91_sdhci_write8(struct sdhci *sdhci, int reg, u8 value) -{ - writeb(value, to_priv(sdhci)->base + reg); -} - void at91_sdhci_mmio_init(struct at91_sdhci *host, void __iomem *base) { - host->base = base; - host->sdhci.read8 = at91_sdhci_read8; - host->sdhci.read16 = at91_sdhci_read16; - host->sdhci.read32 = at91_sdhci_read32; - host->sdhci.write8 = at91_sdhci_write8; - host->sdhci.write16 = at91_sdhci_write16; - host->sdhci.write32 = at91_sdhci_write32; + host->sdhci.base = base; } diff --git a/drivers/mci/dove-sdhci.c b/drivers/mci/dove-sdhci.c index f4f8dabba1..e6ac769bde 100644 --- a/drivers/mci/dove-sdhci.c +++ b/drivers/mci/dove-sdhci.c @@ -20,55 +20,12 @@ struct dove_sdhci { struct mci_host mci; - void __iomem *base; struct sdhci sdhci; }; #define priv_from_mci_host(h) \ container_of(h, struct dove_sdhci, mci); -static void dove_sdhci_writel(struct sdhci *sdhci, int reg, u32 val) -{ - struct dove_sdhci *p = container_of(sdhci, struct dove_sdhci, sdhci); - - writel(val, p->base + reg); -} - -static void dove_sdhci_writew(struct sdhci *sdhci, int reg, u16 val) -{ - struct dove_sdhci *p = container_of(sdhci, struct dove_sdhci, sdhci); - - writew(val, p->base + reg); -} - -static void dove_sdhci_writeb(struct sdhci *sdhci, int reg, u8 val) -{ - struct dove_sdhci *p = container_of(sdhci, struct dove_sdhci, sdhci); - - writeb(val, p->base + reg); -} - -static u32 dove_sdhci_readl(struct sdhci *sdhci, int reg) -{ - struct dove_sdhci *p = container_of(sdhci, struct dove_sdhci, sdhci); - - return readl(p->base + reg); -} - -static u16 dove_sdhci_readw(struct sdhci *sdhci, int reg) -{ - struct dove_sdhci *p = container_of(sdhci, struct dove_sdhci, sdhci); - - return readw(p->base + reg); -} - -static u8 dove_sdhci_readb(struct sdhci *sdhci, int reg) -{ - struct dove_sdhci *p = container_of(sdhci, struct dove_sdhci, sdhci); - - return readb(p->base + reg); -} - static int dove_sdhci_wait_for_done(struct dove_sdhci *host, u16 mask) { u16 status; @@ -320,7 +277,7 @@ static int dove_sdhci_probe(struct device_d *dev) int ret; host = xzalloc(sizeof(*host)); - host->base = dev_request_mem_region(dev, 0); + host->sdhci.base = dev_request_mem_region(dev, 0); host->mci.max_req_size = 0x8000; host->mci.hw_dev = dev; host->mci.send_cmd = dove_sdhci_mci_send_cmd; @@ -328,12 +285,6 @@ static int dove_sdhci_probe(struct device_d *dev) host->mci.init = dove_sdhci_mci_init; host->mci.f_max = 50000000; host->mci.f_min = host->mci.f_max / 256; - host->sdhci.read32 = dove_sdhci_readl; - host->sdhci.read16 = dove_sdhci_readw; - host->sdhci.read8 = dove_sdhci_readb; - host->sdhci.write32 = dove_sdhci_writel; - host->sdhci.write16 = dove_sdhci_writew; - host->sdhci.write8 = dove_sdhci_writeb; dove_sdhci_set_mci_caps(host); diff --git a/drivers/mci/imx-esdhc-common.c b/drivers/mci/imx-esdhc-common.c index c9d589468f..7980278801 100644 --- a/drivers/mci/imx-esdhc-common.c +++ b/drivers/mci/imx-esdhc-common.c @@ -16,42 +16,41 @@ struct fsl_esdhc_dma_transfer { enum dma_data_direction dir; }; -static u32 esdhc_op_read32_le(struct sdhci *sdhci, int reg) +static u32 esdhc_op_read32_be(struct sdhci *sdhci, int reg) { struct fsl_esdhc_host *host = sdhci_to_esdhc(sdhci); - return readl(host->regs + reg); + return in_be32(host->sdhci.base + reg); } -static u32 esdhc_op_read32_be(struct sdhci *sdhci, int reg) +static void esdhc_op_write32_be(struct sdhci *sdhci, int reg, u32 val) { struct fsl_esdhc_host *host = sdhci_to_esdhc(sdhci); - return in_be32(host->regs + reg); + out_be32(host->sdhci.base + reg, val); } -static void esdhc_op_write32_le(struct sdhci *sdhci, int reg, u32 val) +static u16 esdhc_op_read16_be(struct sdhci *sdhci, int reg) { struct fsl_esdhc_host *host = sdhci_to_esdhc(sdhci); - writel(val, host->regs + reg); + return in_be16(host->sdhci.base + reg); } -static void esdhc_op_write32_be(struct sdhci *sdhci, int reg, u32 val) +static void esdhc_op_write16_be(struct sdhci *sdhci, int reg, u16 val) { struct fsl_esdhc_host *host = sdhci_to_esdhc(sdhci); - out_be32(host->regs + reg, val); + out_be16(host->sdhci.base + reg, val); } void esdhc_populate_sdhci(struct fsl_esdhc_host *host) { if (host->socdata->flags & ESDHC_FLAG_BIGENDIAN) { + host->sdhci.read16 = esdhc_op_read16_be; + host->sdhci.write16 = esdhc_op_write16_be; host->sdhci.read32 = esdhc_op_read32_be; host->sdhci.write32 = esdhc_op_write32_be; - } else { - host->sdhci.read32 = esdhc_op_read32_le; - host->sdhci.write32 = esdhc_op_write32_le; } } diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c index c3a8b377e2..cf469eff44 100644 --- a/drivers/mci/imx-esdhc-pbl.c +++ b/drivers/mci/imx-esdhc-pbl.c @@ -200,14 +200,14 @@ static int imx8m_esdhc_init(struct fsl_esdhc_host *host, { switch (instance) { case 0: - host->regs = IOMEM(MX8M_USDHC1_BASE_ADDR); + host->sdhci.base = IOMEM(MX8M_USDHC1_BASE_ADDR); break; case 1: - host->regs = IOMEM(MX8M_USDHC2_BASE_ADDR); + host->sdhci.base = IOMEM(MX8M_USDHC2_BASE_ADDR); break; case 2: /* Only exists on i.MX8MM, not on i.MX8MQ */ - host->regs = IOMEM(MX8MM_USDHC3_BASE_ADDR); + host->sdhci.base = IOMEM(MX8MM_USDHC3_BASE_ADDR); break; default: return -EINVAL; @@ -237,16 +237,16 @@ int imx6_esdhc_start_image(int instance) switch (instance) { case 0: - host.regs = IOMEM(MX6_USDHC1_BASE_ADDR); + host.sdhci.base = IOMEM(MX6_USDHC1_BASE_ADDR); break; case 1: - host.regs = IOMEM(MX6_USDHC2_BASE_ADDR); + host.sdhci.base = IOMEM(MX6_USDHC2_BASE_ADDR); break; case 2: - host.regs = IOMEM(MX6_USDHC3_BASE_ADDR); + host.sdhci.base = IOMEM(MX6_USDHC3_BASE_ADDR); break; case 3: - host.regs = IOMEM(MX6_USDHC4_BASE_ADDR); + host.sdhci.base = IOMEM(MX6_USDHC4_BASE_ADDR); break; default: return -EINVAL; @@ -276,13 +276,13 @@ int imx7_esdhc_start_image(int instance) switch (instance) { case 0: - host.regs = IOMEM(MX7_USDHC1_BASE_ADDR); + host.sdhci.base = IOMEM(MX7_USDHC1_BASE_ADDR); break; case 1: - host.regs = IOMEM(MX7_USDHC2_BASE_ADDR); + host.sdhci.base = IOMEM(MX7_USDHC2_BASE_ADDR); break; case 2: - host.regs = IOMEM(MX7_USDHC3_BASE_ADDR); + host.sdhci.base = IOMEM(MX7_USDHC3_BASE_ADDR); break; default: return -EINVAL; diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c index 12e98ce26a..5a664ce4c3 100644 --- a/drivers/mci/imx-esdhc.c +++ b/drivers/mci/imx-esdhc.c @@ -264,7 +264,7 @@ static int fsl_esdhc_probe(struct device_d *dev) ret = PTR_ERR(iores); goto err_clk_disable; } - host->regs = IOMEM(iores->start); + host->sdhci.base = IOMEM(iores->start); esdhc_populate_sdhci(host); diff --git a/drivers/mci/imx-esdhc.h b/drivers/mci/imx-esdhc.h index 0de1e72e7b..f1685eac06 100644 --- a/drivers/mci/imx-esdhc.h +++ b/drivers/mci/imx-esdhc.h @@ -101,7 +101,6 @@ struct fsl_esdhc_host { struct mci_host mci; struct clk *clk; struct device_d *dev; - void __iomem *regs; const struct esdhc_soc_data *socdata; struct sdhci sdhci; }; diff --git a/drivers/mci/sdhci.h b/drivers/mci/sdhci.h index 2605ecb535..e07f4a3fb2 100644 --- a/drivers/mci/sdhci.h +++ b/drivers/mci/sdhci.h @@ -183,6 +183,8 @@ struct sdhci { void (*write16)(struct sdhci *host, int reg, u16 val); void (*write8)(struct sdhci *host, int reg, u8 val); + void __iomem *base; + int max_clk; /* Max possible freq (Hz) */ int clk_mul; /* Clock Muliplier value */ @@ -204,32 +206,50 @@ struct sdhci { static inline u32 sdhci_read32(struct sdhci *host, int reg) { - return host->read32(host, reg); + if (host->read32) + return host->read32(host, reg); + else + return readl(host->base + reg); } static inline u32 sdhci_read16(struct sdhci *host, int reg) { - return host->read16(host, reg); + if (host->read16) + return host->read16(host, reg); + else + return readw(host->base + reg); } static inline u32 sdhci_read8(struct sdhci *host, int reg) { - return host->read8(host, reg); + if (host->read8) + return host->read8(host, reg); + else + return readb(host->base + reg); } static inline void sdhci_write32(struct sdhci *host, int reg, u32 val) { - host->write32(host, reg, val); + if (host->write32) + host->write32(host, reg, val); + else + writel(val, host->base + reg); } static inline void sdhci_write16(struct sdhci *host, int reg, u32 val) { - host->write16(host, reg, val); + if (host->write16) + host->write16(host, reg, val); + else + writew(val, host->base + reg); } static inline void sdhci_write8(struct sdhci *host, int reg, u32 val) { - host->write8(host, reg, val); + if (host->write8) + host->write8(host, reg, val); + else + writeb(val, host->base + reg); } void sdhci_read_response(struct sdhci *host, struct mci_cmd *cmd); -- 2.29.2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
This adds support for a Rockchip derivation of the DWCMSHC controller which itself is a SDHCI controller found on some Rockchip SoCs like the RK3568. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/mci/Kconfig | 7 + drivers/mci/Makefile | 1 + drivers/mci/rockchip-dwcmshc-sdhci.c | 382 +++++++++++++++++++++++++++ 3 files changed, 390 insertions(+) create mode 100644 drivers/mci/rockchip-dwcmshc-sdhci.c diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig index 7d4e72138d..e1fcd41271 100644 --- a/drivers/mci/Kconfig +++ b/drivers/mci/Kconfig @@ -79,6 +79,13 @@ config MCI_MXS Enable this entry to add support to read and write SD cards on a i.MX23/i.MX28 based system. +config MCI_ROCKCHIP_DWCMSHC + bool "MCI sdhc support for Rockchip SoCs" + select MCI_SDHCI + help + Enable this entry to add support for a Rockchip derivation of the + DWCMSHC controller found on some Rockchip SoCs like the RK3568. + config MCI_S3C bool "S3C" depends on ARCH_S3C24xx diff --git a/drivers/mci/Makefile b/drivers/mci/Makefile index 60dc100c37..b113b1c732 100644 --- a/drivers/mci/Makefile +++ b/drivers/mci/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_MCI_MXS) += mxs.o obj-$(CONFIG_MCI_OMAP_HSMMC) += omap_hsmmc.o obj-$(CONFIG_MCI_PXA) += pxamci.o obj-$(CONFIG_MCI_S3C) += s3c.o +obj-$(CONFIG_MCI_ROCKCHIP_DWCMSHC) += rockchip-dwcmshc-sdhci.o obj-$(CONFIG_MCI_TEGRA) += tegra-sdmmc.o obj-$(CONFIG_MCI_SPI) += mci_spi.o obj-$(CONFIG_MCI_DW) += dw_mmc.o diff --git a/drivers/mci/rockchip-dwcmshc-sdhci.c b/drivers/mci/rockchip-dwcmshc-sdhci.c new file mode 100644 index 0000000000..e44fc16c39 --- /dev/null +++ b/drivers/mci/rockchip-dwcmshc-sdhci.c @@ -0,0 +1,382 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <clock.h> +#include <common.h> +#include <driver.h> +#include <init.h> +#include <linux/clk.h> +#include <mci.h> +#include <linux/iopoll.h> + +#include "sdhci.h" + +/* DWCMSHC specific Mode Select value */ +#define DWCMSHC_CTRL_HS400 0x7 + +#define DWCMSHC_VER_ID 0x500 +#define DWCMSHC_VER_TYPE 0x504 +#define DWCMSHC_HOST_CTRL3 0x508 +#define DWCMSHC_EMMC_CONTROL 0x52c +#define DWCMSHC_EMMC_ATCTRL 0x540 + +/* Rockchip specific Registers */ +#define DWCMSHC_EMMC_DLL_CTRL 0x800 +#define DWCMSHC_EMMC_DLL_RXCLK 0x804 +#define DWCMSHC_EMMC_DLL_TXCLK 0x808 +#define DWCMSHC_EMMC_DLL_STRBIN 0x80c +#define DWCMSHC_EMMC_DLL_STATUS0 0x840 +#define DWCMSHC_EMMC_DLL_START BIT(0) +#define DWCMSHC_EMMC_DLL_RXCLK_SRCSEL 29 +#define DWCMSHC_EMMC_DLL_START_POINT 16 +#define DWCMSHC_EMMC_DLL_INC 8 +#define DWCMSHC_EMMC_DLL_DLYENA BIT(27) +#define DLL_TXCLK_TAPNUM_DEFAULT 0x8 +#define DLL_STRBIN_TAPNUM_DEFAULT 0x8 +#define DLL_TXCLK_TAPNUM_FROM_SW BIT(24) +#define DLL_STRBIN_TAPNUM_FROM_SW BIT(24) +#define DWCMSHC_EMMC_DLL_LOCKED BIT(8) +#define DWCMSHC_EMMC_DLL_TIMEOUT BIT(9) +#define DLL_RXCLK_NO_INVERTER 1 +#define DLL_RXCLK_INVERTER 0 +#define DWCMSHC_ENHANCED_STROBE BIT(8) +#define DLL_LOCK_WO_TMOUT(x) \ + ((((x) & DWCMSHC_EMMC_DLL_LOCKED) == DWCMSHC_EMMC_DLL_LOCKED) && \ + (((x) & DWCMSHC_EMMC_DLL_TIMEOUT) == 0)) + +#define SDHCI_DWCMSHC_INT_DATA_MASK SDHCI_INT_XFER_COMPLETE | \ + SDHCI_INT_DMA | \ + SDHCI_INT_SPACE_AVAIL | \ + SDHCI_INT_DATA_AVAIL | \ + SDHCI_INT_DATA_TIMEOUT | \ + SDHCI_INT_DATA_CRC | \ + SDHCI_INT_DATA_END_BIT + +#define SDHCI_DWCMSHC_INT_CMD_MASK SDHCI_INT_CMD_COMPLETE | \ + SDHCI_INT_TIMEOUT | \ + SDHCI_INT_CRC | \ + SDHCI_INT_END_BIT | \ + SDHCI_INT_INDEX + +enum { + CLK_CORE, + CLK_BUS, + CLK_AXI, + CLK_BLOCK, + CLK_TIMER, + CLK_MAX, +}; + +struct rk_sdhci_host { + struct mci_host mci; + struct sdhci sdhci; + struct clk_bulk_data clks[CLK_MAX]; +}; + + +static inline +struct rk_sdhci_host *to_rk_sdhci_host(struct mci_host *mci) +{ + return container_of(mci, struct rk_sdhci_host, mci); +} + +static int rk_sdhci_card_present(struct mci_host *mci) +{ + struct rk_sdhci_host *host = to_rk_sdhci_host(mci); + + return !!(sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & SDHCI_CARD_DETECT); +} + +static int rk_sdhci_reset(struct rk_sdhci_host *host, u8 mask) +{ + sdhci_write8(&host->sdhci, SDHCI_SOFTWARE_RESET, mask); + + /* wait for reset completion */ + if (wait_on_timeout(100 * MSECOND, + !(sdhci_read8(&host->sdhci, SDHCI_SOFTWARE_RESET) & mask))){ + dev_err(host->mci.hw_dev, "SDHCI reset timeout\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static int rk_sdhci_init(struct mci_host *mci, struct device_d *dev) +{ + struct rk_sdhci_host *host = to_rk_sdhci_host(mci); + int ret; + + ret = rk_sdhci_reset(host, SDHCI_RESET_ALL); + if (ret) + return ret; + + sdhci_write8(&host->sdhci, SDHCI_POWER_CONTROL, + SDHCI_BUS_VOLTAGE_330 | SDHCI_BUS_POWER_EN); + udelay(400); + + sdhci_write32(&host->sdhci, SDHCI_INT_ENABLE, + SDHCI_DWCMSHC_INT_DATA_MASK | + SDHCI_DWCMSHC_INT_CMD_MASK); + sdhci_write32(&host->sdhci, SDHCI_SIGNAL_ENABLE, 0x00); + + /* Disable cmd conflict check */ + sdhci_write32(&host->sdhci, DWCMSHC_HOST_CTRL3, 0x0); + /* Reset previous settings */ + sdhci_write32(&host->sdhci, DWCMSHC_EMMC_DLL_TXCLK, 0); + sdhci_write32(&host->sdhci, DWCMSHC_EMMC_DLL_STRBIN, 0); + + return 0; +} + +static void rk_sdhci_set_clock(struct rk_sdhci_host *host, unsigned int clock) +{ + u32 txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT, extra; + int err; + + host->mci.clock = 0; + + /* DO NOT TOUCH THIS SETTING */ + extra = DWCMSHC_EMMC_DLL_DLYENA | + DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL; + sdhci_write32(&host->sdhci, DWCMSHC_EMMC_DLL_RXCLK, extra); + + if (clock == 0) + return; + + /* Rockchip platform only support 375KHz for identify mode */ + if (clock <= 400000) + clock = 375000; + + clk_set_rate(host->clks[CLK_CORE].clk, clock); + + sdhci_set_clock(&host->sdhci, clock, clk_get_rate(host->clks[CLK_CORE].clk)); + + if (clock <= 400000) + return; + + /* Reset DLL */ + sdhci_write32(&host->sdhci, DWCMSHC_EMMC_DLL_CTRL, BIT(1)); + udelay(1); + sdhci_write32(&host->sdhci, DWCMSHC_EMMC_DLL_CTRL, 0x0); + + /* Init DLL settings */ + extra = 0x5 << DWCMSHC_EMMC_DLL_START_POINT | + 0x2 << DWCMSHC_EMMC_DLL_INC | + DWCMSHC_EMMC_DLL_START; + sdhci_write32(&host->sdhci, DWCMSHC_EMMC_DLL_CTRL, extra); + err = readl_poll_timeout(host->sdhci.base + DWCMSHC_EMMC_DLL_STATUS0, + extra, DLL_LOCK_WO_TMOUT(extra), + 500 * USEC_PER_MSEC); + if (err) { + dev_err(host->mci.hw_dev, "DLL lock timeout!\n"); + return; + } + + /* Disable cmd conflict check */ + extra = sdhci_read32(&host->sdhci, DWCMSHC_HOST_CTRL3); + extra &= ~BIT(0); + sdhci_write32(&host->sdhci, DWCMSHC_HOST_CTRL3, extra); + + extra = 0x1 << 16 | /* tune clock stop en */ + 0x2 << 17 | /* pre-change delay */ + 0x3 << 19; /* post-change delay */ + sdhci_write32(&host->sdhci, DWCMSHC_EMMC_ATCTRL, extra); + + extra = DWCMSHC_EMMC_DLL_DLYENA | + DLL_TXCLK_TAPNUM_FROM_SW | + txclk_tapnum; + sdhci_write32(&host->sdhci, DWCMSHC_EMMC_DLL_TXCLK, extra); + + extra = DWCMSHC_EMMC_DLL_DLYENA | + DLL_STRBIN_TAPNUM_DEFAULT | + DLL_STRBIN_TAPNUM_FROM_SW; + sdhci_write32(&host->sdhci, DWCMSHC_EMMC_DLL_STRBIN, extra); +} + +static void rk_sdhci_set_ios(struct mci_host *mci, struct mci_ios *ios) +{ + struct rk_sdhci_host *host = to_rk_sdhci_host(mci); + u16 val; + + /* stop clock */ + sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, 0); + + if (ios->clock) + rk_sdhci_set_clock(host, ios->clock); + + sdhci_set_bus_width(&host->sdhci, ios->bus_width); + + val = sdhci_read8(&host->sdhci, SDHCI_HOST_CONTROL); + + if (ios->clock > 26000000) + val |= SDHCI_CTRL_HISPD; + else + val &= ~SDHCI_CTRL_HISPD; + + sdhci_write8(&host->sdhci, SDHCI_HOST_CONTROL, val); +} + +static int rk_sdhci_wait_for_done(struct rk_sdhci_host *host, u32 mask) +{ + u64 start = get_time_ns(); + u16 stat; + + do { + stat = sdhci_read16(&host->sdhci, SDHCI_INT_NORMAL_STATUS); + if (stat & SDHCI_INT_ERROR) { + dev_err(host->mci.hw_dev, "SDHCI_INT_ERROR: 0x%08x\n", + sdhci_read16(&host->sdhci, SDHCI_INT_ERROR_STATUS)); + return -EPERM; + } + + if (is_timeout(start, 1000 * MSECOND)) { + dev_err(host->mci.hw_dev, + "SDHCI timeout while waiting for done\n"); + return -ETIMEDOUT; + } + } while ((stat & mask) != mask); + + return 0; +} + +static void print_error(struct rk_sdhci_host *host, int cmdidx) +{ + dev_err(host->mci.hw_dev, + "error while transfering data for command %d\n", cmdidx); + dev_err(host->mci.hw_dev, "state = 0x%08x , interrupt = 0x%08x\n", + sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE), + sdhci_read32(&host->sdhci, SDHCI_INT_NORMAL_STATUS)); +} + +static int rk_sdhci_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, + struct mci_data *data) +{ + struct rk_sdhci_host *host = to_rk_sdhci_host(mci); + u32 mask, command, xfer; + int ret; + + /* Wait for idle before next command */ + mask = SDHCI_CMD_INHIBIT_CMD; + if (cmd->cmdidx != MMC_CMD_STOP_TRANSMISSION) + mask |= SDHCI_CMD_INHIBIT_DATA; + + ret = wait_on_timeout(10 * MSECOND, + !(sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & mask)); + + if (ret) { + dev_err(host->mci.hw_dev, + "SDHCI timeout while waiting for idle\n"); + return ret; + } + + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, ~0); + + mask = SDHCI_INT_CMD_COMPLETE; + if (data) + mask |= SDHCI_INT_DATA_AVAIL; + + sdhci_set_cmd_xfer_mode(&host->sdhci, cmd, data, false, &command, &xfer); + + sdhci_write8(&host->sdhci, SDHCI_TIMEOUT_CONTROL, 0xe); + + sdhci_write16(&host->sdhci, SDHCI_TRANSFER_MODE, xfer); + + if (data) { + sdhci_write16(&host->sdhci, SDHCI_BLOCK_SIZE, SDHCI_DMA_BOUNDARY_512K | + SDHCI_TRANSFER_BLOCK_SIZE(data->blocksize)); + sdhci_write16(&host->sdhci, SDHCI_BLOCK_COUNT, data->blocks); + } + + sdhci_write32(&host->sdhci, SDHCI_ARGUMENT, cmd->cmdarg); + sdhci_write16(&host->sdhci, SDHCI_COMMAND, command); + + ret = rk_sdhci_wait_for_done(host, mask); + if (ret == -EPERM) + goto error; + else if (ret) + return ret; + + sdhci_read_response(&host->sdhci, cmd); + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, mask); + + if (data) + ret = sdhci_transfer_data(&host->sdhci, data); + +error: + if (ret) { + print_error(host, cmd->cmdidx); + rk_sdhci_reset(host, BIT(1)); /* SDHCI_RESET_CMD */ + rk_sdhci_reset(host, BIT(2)); /* SDHCI_RESET_DATA */ + } + + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, ~0); + return ret; +} + +static int rk_sdhci_probe(struct device_d *dev) +{ + struct rk_sdhci_host *host; + struct resource *iores; + struct mci_host *mci; + int ret; + + host = xzalloc(sizeof(*host)); + + mci = &host->mci; + + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) + return PTR_ERR(iores); + + host->sdhci.base = IOMEM(iores->start); + host->sdhci.mci = mci; + mci->send_cmd = rk_sdhci_send_cmd; + mci->set_ios = rk_sdhci_set_ios; + mci->init = rk_sdhci_init; + mci->card_present = rk_sdhci_card_present; + mci->hw_dev = dev; + + host->clks[CLK_CORE].id = "core"; + host->clks[CLK_BUS].id = "bus"; + host->clks[CLK_AXI].id = "axi"; + host->clks[CLK_BLOCK].id = "block"; + host->clks[CLK_TIMER].id = "timer"; + + ret = clk_bulk_get(host->mci.hw_dev, CLK_MAX, host->clks); + if (ret) { + dev_err(host->mci.hw_dev, "failed to get clocks: %s\n", + strerror(-ret)); + return ret; + } + + ret = clk_bulk_enable(CLK_MAX, host->clks); + if (ret) { + dev_err(host->mci.hw_dev, "failed to enable clocks: %s\n", + strerror(-ret)); + return ret; + } + + host->sdhci.max_clk = clk_get_rate(host->clks[CLK_CORE].clk); + + mci_of_parse(&host->mci); + + sdhci_setup_host(&host->sdhci); + + dev->priv = host; + + return mci_register(&host->mci); +} + +static __maybe_unused struct of_device_id rk_sdhci_compatible[] = { + { + .compatible = "rockchip,rk3568-dwcmshc" + }, { + /* sentinel */ + } +}; + +static struct driver_d rk_sdhci_driver = { + .name = "rk3568-dwcmshc-sdhci", + .probe = rk_sdhci_probe, + .of_compatible = DRV_OF_COMPAT(rk_sdhci_compatible), +}; +device_platform_driver(rk_sdhci_driver); -- 2.29.2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
On Mon, 7 Jun 2021 12:44:05 +0200 Sascha Hauer <s.hauer@pengutronix.de> wrote: Hi Sascha! > To ease porting and comparing of Linux code. > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> > --- > drivers/mci/arasan-sdhci.c | 12 ++++++------ > drivers/mci/atmel-sdhci-common.c | 14 +++++++------- > drivers/mci/dove-sdhci.c | 10 +++++----- > drivers/mci/sdhci.h | 17 ++++++++++++----- > 4 files changed, 30 insertions(+), 23 deletions(-) > > diff --git a/drivers/mci/arasan-sdhci.c b/drivers/mci/arasan-sdhci.c > index e22db4cfa3..e02f222345 100644 > --- a/drivers/mci/arasan-sdhci.c > +++ b/drivers/mci/arasan-sdhci.c ... > @@ -200,21 +200,21 @@ static void arasan_sdhci_set_ios(struct mci_host *mci, struct mci_ios *ios) > } > > val = sdhci_read8(&host->sdhci, SDHCI_HOST_CONTROL) & > - ~(SDHCI_DATA_WIDTH_4BIT | SDHCI_DATA_WIDTH_8BIT); > + ~(SDHCI_CTRL_8BITBUS | SDHCI_CTRL_8BITBUS); > > switch (ios->bus_width) { > case MMC_BUS_WIDTH_8: > - val |= SDHCI_DATA_WIDTH_8BIT; > + val |= SDHCI_CTRL_8BITBUS; > break; > case MMC_BUS_WIDTH_4: ^^^^^^^^ > - val |= SDHCI_DATA_WIDTH_4BIT; ^^^^^^^^^^^ > + val |= SDHCI_CTRL_8BITBUS; ^^^^^^^ Is this correct? > break; > } > > if (ios->clock > 26000000) > - val |= SDHCI_HIGHSPEED_EN; > + val |= SDHCI_CTRL_HISPD; > else > - val &= ~SDHCI_HIGHSPEED_EN; > + val &= ~SDHCI_CTRL_HISPD; > > sdhci_write8(&host->sdhci, SDHCI_HOST_CONTROL, val); > } > diff --git a/drivers/mci/atmel-sdhci-common.c b/drivers/mci/atmel-sdhci-common.c > index b391775b00..d2b777a93c 100644 > --- a/drivers/mci/atmel-sdhci-common.c > +++ b/drivers/mci/atmel-sdhci-common.c ... > @@ -297,15 +297,15 @@ static int at91_sdhci_set_bus_width(struct at91_sdhci *host, unsigned bus_width) > > switch(bus_width) { > case MMC_BUS_WIDTH_8: > - reg |= SDHCI_DATA_WIDTH_8BIT; > + reg |= SDHCI_CTRL_8BITBUS; > break; > case MMC_BUS_WIDTH_4: ^^^^^^^ > - reg &= ~SDHCI_DATA_WIDTH_8BIT; > - reg |= SDHCI_DATA_WIDTH_4BIT; ^^^^^^^^^^^ > + reg &= ~SDHCI_CTRL_8BITBUS; > + reg |= SDHCI_CTRL_8BITBUS; ^^^^^^^^ just the same question here > break; > default: > - reg &= ~SDHCI_DATA_WIDTH_8BIT; > - reg &= ~SDHCI_DATA_WIDTH_4BIT; > + reg &= ~SDHCI_CTRL_8BITBUS; > + reg &= ~SDHCI_CTRL_8BITBUS; and here > } > > sdhci_write8(sdhci, SDHCI_HOST_CONTROL, reg); > diff --git a/drivers/mci/dove-sdhci.c b/drivers/mci/dove-sdhci.c > index 9c10e67eb8..cafc9dc579 100644 > --- a/drivers/mci/dove-sdhci.c > +++ b/drivers/mci/dove-sdhci.c > @@ -224,20 +224,20 @@ static void dove_sdhci_mci_set_ios(struct mci_host *mci, struct mci_ios *ios) > > /* set bus width */ > val = sdhci_read8(&host->sdhci, SDHCI_HOST_CONTROL) & > - ~(SDHCI_DATA_WIDTH_4BIT | SDHCI_DATA_WIDTH_8BIT); > + ~(SDHCI_CTRL_8BITBUS | SDHCI_CTRL_8BITBUS); > switch (ios->bus_width) { > case MMC_BUS_WIDTH_8: > - val |= SDHCI_DATA_WIDTH_8BIT; > + val |= SDHCI_CTRL_8BITBUS; > break; > case MMC_BUS_WIDTH_4: > - val |= SDHCI_DATA_WIDTH_4BIT; > + val |= SDHCI_CTRL_8BITBUS; and here > break; > } > > if (ios->clock > 26000000) > - val |= SDHCI_HIGHSPEED_EN; > + val |= SDHCI_CTRL_HISPD; > else > - val &= ~SDHCI_HIGHSPEED_EN; > + val &= ~SDHCI_CTRL_HISPD; > > sdhci_write8(&host->sdhci, SDHCI_HOST_CONTROL, val); > -- Best regards, Antony Pavlov _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
On Wed, Jan 26, 2022 at 09:32:33AM +0300, Antony Pavlov wrote: > On Mon, 7 Jun 2021 12:44:05 +0200 > Sascha Hauer <s.hauer@pengutronix.de> wrote: > > Hi Sascha! > > > To ease porting and comparing of Linux code. > > > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> > > --- > > drivers/mci/arasan-sdhci.c | 12 ++++++------ > > drivers/mci/atmel-sdhci-common.c | 14 +++++++------- > > drivers/mci/dove-sdhci.c | 10 +++++----- > > drivers/mci/sdhci.h | 17 ++++++++++++----- > > 4 files changed, 30 insertions(+), 23 deletions(-) > > > > diff --git a/drivers/mci/arasan-sdhci.c b/drivers/mci/arasan-sdhci.c > > index e22db4cfa3..e02f222345 100644 > > --- a/drivers/mci/arasan-sdhci.c > > +++ b/drivers/mci/arasan-sdhci.c > > ... > > > @@ -200,21 +200,21 @@ static void arasan_sdhci_set_ios(struct mci_host *mci, struct mci_ios *ios) > > } > > > > val = sdhci_read8(&host->sdhci, SDHCI_HOST_CONTROL) & > > - ~(SDHCI_DATA_WIDTH_4BIT | SDHCI_DATA_WIDTH_8BIT); > > + ~(SDHCI_CTRL_8BITBUS | SDHCI_CTRL_8BITBUS); > > > > switch (ios->bus_width) { > > case MMC_BUS_WIDTH_8: > > - val |= SDHCI_DATA_WIDTH_8BIT; > > + val |= SDHCI_CTRL_8BITBUS; > > break; > > case MMC_BUS_WIDTH_4: > ^^^^^^^^ > > - val |= SDHCI_DATA_WIDTH_4BIT; > ^^^^^^^^^^^ > > + val |= SDHCI_CTRL_8BITBUS; > ^^^^^^^ > Is this correct? Nope, indeed not. Fortunately it's fixed in the same series in "[PATCH 08/12] mci: sdhci: arasan: Use sdhci_set_bus_width()". The other places need fixing though, patch is out. Thanks for noting Sascha -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox
On Wed, 26 Jan 2022 10:23:17 +0100 Sascha Hauer <s.hauer@pengutronix.de> wrote: > On Wed, Jan 26, 2022 at 09:32:33AM +0300, Antony Pavlov wrote: > > On Mon, 7 Jun 2021 12:44:05 +0200 > > Sascha Hauer <s.hauer@pengutronix.de> wrote: > > > > Hi Sascha! > > > > > To ease porting and comparing of Linux code. > > > > > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> > > > --- > > > drivers/mci/arasan-sdhci.c | 12 ++++++------ > > > drivers/mci/atmel-sdhci-common.c | 14 +++++++------- > > > drivers/mci/dove-sdhci.c | 10 +++++----- > > > drivers/mci/sdhci.h | 17 ++++++++++++----- > > > 4 files changed, 30 insertions(+), 23 deletions(-) > > > > > > diff --git a/drivers/mci/arasan-sdhci.c b/drivers/mci/arasan-sdhci.c > > > index e22db4cfa3..e02f222345 100644 > > > --- a/drivers/mci/arasan-sdhci.c > > > +++ b/drivers/mci/arasan-sdhci.c > > > > ... > > > > > @@ -200,21 +200,21 @@ static void arasan_sdhci_set_ios(struct mci_host *mci, struct mci_ios *ios) > > > } > > > > > > val = sdhci_read8(&host->sdhci, SDHCI_HOST_CONTROL) & > > > - ~(SDHCI_DATA_WIDTH_4BIT | SDHCI_DATA_WIDTH_8BIT); > > > + ~(SDHCI_CTRL_8BITBUS | SDHCI_CTRL_8BITBUS); > > > > > > switch (ios->bus_width) { > > > case MMC_BUS_WIDTH_8: > > > - val |= SDHCI_DATA_WIDTH_8BIT; > > > + val |= SDHCI_CTRL_8BITBUS; > > > break; > > > case MMC_BUS_WIDTH_4: > > ^^^^^^^^ > > > - val |= SDHCI_DATA_WIDTH_4BIT; > > ^^^^^^^^^^^ > > > + val |= SDHCI_CTRL_8BITBUS; > > ^^^^^^^ > > Is this correct? > > Nope, indeed not. Fortunately it's fixed in the same series in "[PATCH > 08/12] mci: sdhci: arasan: Use sdhci_set_bus_width()". The other places > need fixing though, patch is out. > > Thanks for noting > It looks like that there is one more line to fix. Please see > diff --git a/drivers/mci/dove-sdhci.c b/drivers/mci/dove-sdhci.c > index 9c10e67eb8..cafc9dc579 100644 > --- a/drivers/mci/dove-sdhci.c > +++ b/drivers/mci/dove-sdhci.c > @@ -224,20 +224,20 @@ static void dove_sdhci_mci_set_ios(struct mci_host *mci, struct mci_ios *ios) > > /* set bus width */ > val = sdhci_read8(&host->sdhci, SDHCI_HOST_CONTROL) & > - ~(SDHCI_DATA_WIDTH_4BIT | SDHCI_DATA_WIDTH_8BIT); > + ~(SDHCI_CTRL_8BITBUS | SDHCI_CTRL_8BITBUS); "SDHCI_CTRL_4BITBUS | SDHCI_CTRL_8BITBUS" instead of "SDHCI_CTRL_8BITBUS | SDHCI_CTRL_8BITBUS", I suppose. -- Best regards, Antony Pavlov _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox