* [PATCH 01/12] mci: sdhci: straighten capabilities register
2021-06-07 10:43 [PATCH 00/12] SDHCI updates Sascha Hauer
@ 2021-06-07 10:44 ` Sascha Hauer
2021-06-07 10:44 ` [PATCH 02/12] mci: sdhci: Add and use SDHCI_CAPABILITIES_1 defines Sascha Hauer
` (10 subsequent siblings)
11 siblings, 0 replies; 16+ messages in thread
From: Sascha Hauer @ 2021-06-07 10:44 UTC (permalink / raw)
To: Barebox List
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
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 02/12] mci: sdhci: Add and use SDHCI_CAPABILITIES_1 defines
2021-06-07 10:43 [PATCH 00/12] SDHCI updates Sascha Hauer
2021-06-07 10:44 ` [PATCH 01/12] mci: sdhci: straighten capabilities register Sascha Hauer
@ 2021-06-07 10:44 ` Sascha Hauer
2021-06-07 10:44 ` [PATCH 03/12] mci: sdhci: Use SDHCI_MAX_DIV_SPEC_200 define Sascha Hauer
` (9 subsequent siblings)
11 siblings, 0 replies; 16+ messages in thread
From: Sascha Hauer @ 2021-06-07 10:44 UTC (permalink / raw)
To: Barebox List
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
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 03/12] mci: sdhci: Use SDHCI_MAX_DIV_SPEC_200 define
2021-06-07 10:43 [PATCH 00/12] SDHCI updates Sascha Hauer
2021-06-07 10:44 ` [PATCH 01/12] mci: sdhci: straighten capabilities register Sascha Hauer
2021-06-07 10:44 ` [PATCH 02/12] mci: sdhci: Add and use SDHCI_CAPABILITIES_1 defines Sascha Hauer
@ 2021-06-07 10:44 ` Sascha Hauer
2021-06-07 10:44 ` [PATCH 04/12] mci: sdhci: port over some common functions from Linux Sascha Hauer
` (8 subsequent siblings)
11 siblings, 0 replies; 16+ messages in thread
From: Sascha Hauer @ 2021-06-07 10:44 UTC (permalink / raw)
To: Barebox List
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
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 04/12] mci: sdhci: port over some common functions from Linux
2021-06-07 10:43 [PATCH 00/12] SDHCI updates Sascha Hauer
` (2 preceding siblings ...)
2021-06-07 10:44 ` [PATCH 03/12] mci: sdhci: Use SDHCI_MAX_DIV_SPEC_200 define Sascha Hauer
@ 2021-06-07 10:44 ` Sascha Hauer
2021-06-07 10:44 ` [PATCH 05/12] mci: sdhci: imx: Use sdhci_setup_host() Sascha Hauer
` (7 subsequent siblings)
11 siblings, 0 replies; 16+ messages in thread
From: Sascha Hauer @ 2021-06-07 10:44 UTC (permalink / raw)
To: Barebox List
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
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 05/12] mci: sdhci: imx: Use sdhci_setup_host()
2021-06-07 10:43 [PATCH 00/12] SDHCI updates Sascha Hauer
` (3 preceding siblings ...)
2021-06-07 10:44 ` [PATCH 04/12] mci: sdhci: port over some common functions from Linux Sascha Hauer
@ 2021-06-07 10:44 ` Sascha Hauer
2021-06-07 10:44 ` [PATCH 06/12] mci: sdhci: Use Linux defines for SDHCI_HOST_CONTROL register Sascha Hauer
` (6 subsequent siblings)
11 siblings, 0 replies; 16+ messages in thread
From: Sascha Hauer @ 2021-06-07 10:44 UTC (permalink / raw)
To: Barebox List
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
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 06/12] mci: sdhci: Use Linux defines for SDHCI_HOST_CONTROL register
2021-06-07 10:43 [PATCH 00/12] SDHCI updates Sascha Hauer
` (4 preceding siblings ...)
2021-06-07 10:44 ` [PATCH 05/12] mci: sdhci: imx: Use sdhci_setup_host() Sascha Hauer
@ 2021-06-07 10:44 ` Sascha Hauer
2022-01-26 6:32 ` Antony Pavlov
2021-06-07 10:44 ` [PATCH 07/12] mci: sdhci: arasan: Use sdhci_setup_host() Sascha Hauer
` (5 subsequent siblings)
11 siblings, 1 reply; 16+ messages in thread
From: Sascha Hauer @ 2021-06-07 10:44 UTC (permalink / raw)
To: Barebox List
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
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 06/12] mci: sdhci: Use Linux defines for SDHCI_HOST_CONTROL register
2021-06-07 10:44 ` [PATCH 06/12] mci: sdhci: Use Linux defines for SDHCI_HOST_CONTROL register Sascha Hauer
@ 2022-01-26 6:32 ` Antony Pavlov
2022-01-26 9:23 ` Sascha Hauer
0 siblings, 1 reply; 16+ messages in thread
From: Antony Pavlov @ 2022-01-26 6:32 UTC (permalink / raw)
To: Sascha Hauer; +Cc: Barebox List
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
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 06/12] mci: sdhci: Use Linux defines for SDHCI_HOST_CONTROL register
2022-01-26 6:32 ` Antony Pavlov
@ 2022-01-26 9:23 ` Sascha Hauer
2022-01-26 10:13 ` Antony Pavlov
0 siblings, 1 reply; 16+ messages in thread
From: Sascha Hauer @ 2022-01-26 9:23 UTC (permalink / raw)
To: Antony Pavlov; +Cc: Barebox List
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
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 06/12] mci: sdhci: Use Linux defines for SDHCI_HOST_CONTROL register
2022-01-26 9:23 ` Sascha Hauer
@ 2022-01-26 10:13 ` Antony Pavlov
0 siblings, 0 replies; 16+ messages in thread
From: Antony Pavlov @ 2022-01-26 10:13 UTC (permalink / raw)
To: Sascha Hauer; +Cc: Barebox List
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
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 07/12] mci: sdhci: arasan: Use sdhci_setup_host()
2021-06-07 10:43 [PATCH 00/12] SDHCI updates Sascha Hauer
` (5 preceding siblings ...)
2021-06-07 10:44 ` [PATCH 06/12] mci: sdhci: Use Linux defines for SDHCI_HOST_CONTROL register Sascha Hauer
@ 2021-06-07 10:44 ` Sascha Hauer
2021-06-07 10:44 ` [PATCH 08/12] mci: sdhci: arasan: Use sdhci_set_bus_width() Sascha Hauer
` (4 subsequent siblings)
11 siblings, 0 replies; 16+ messages in thread
From: Sascha Hauer @ 2021-06-07 10:44 UTC (permalink / raw)
To: Barebox List
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
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 08/12] mci: sdhci: arasan: Use sdhci_set_bus_width()
2021-06-07 10:43 [PATCH 00/12] SDHCI updates Sascha Hauer
` (6 preceding siblings ...)
2021-06-07 10:44 ` [PATCH 07/12] mci: sdhci: arasan: Use sdhci_setup_host() Sascha Hauer
@ 2021-06-07 10:44 ` Sascha Hauer
2021-06-07 10:44 ` [PATCH 09/12] mci: sdhci: Use Linux defines for SDHCI_CLOCK_CONTROL register Sascha Hauer
` (3 subsequent siblings)
11 siblings, 0 replies; 16+ messages in thread
From: Sascha Hauer @ 2021-06-07 10:44 UTC (permalink / raw)
To: Barebox List
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
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 09/12] mci: sdhci: Use Linux defines for SDHCI_CLOCK_CONTROL register
2021-06-07 10:43 [PATCH 00/12] SDHCI updates Sascha Hauer
` (7 preceding siblings ...)
2021-06-07 10:44 ` [PATCH 08/12] mci: sdhci: arasan: Use sdhci_set_bus_width() Sascha Hauer
@ 2021-06-07 10:44 ` Sascha Hauer
2021-06-07 10:44 ` [PATCH 10/12] mci: sdhci: arasan: Use sdhci_set_clock() Sascha Hauer
` (2 subsequent siblings)
11 siblings, 0 replies; 16+ messages in thread
From: Sascha Hauer @ 2021-06-07 10:44 UTC (permalink / raw)
To: Barebox List
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
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 10/12] mci: sdhci: arasan: Use sdhci_set_clock()
2021-06-07 10:43 [PATCH 00/12] SDHCI updates Sascha Hauer
` (8 preceding siblings ...)
2021-06-07 10:44 ` [PATCH 09/12] mci: sdhci: Use Linux defines for SDHCI_CLOCK_CONTROL register Sascha Hauer
@ 2021-06-07 10:44 ` Sascha Hauer
2021-06-07 10:44 ` [PATCH 11/12] mci: sdhci: Get rid of many register ops Sascha Hauer
2021-06-07 10:44 ` [PATCH 12/12] mci: Add support for Rockchip variant of the dwcmshc Sascha Hauer
11 siblings, 0 replies; 16+ messages in thread
From: Sascha Hauer @ 2021-06-07 10:44 UTC (permalink / raw)
To: Barebox List
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
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 11/12] mci: sdhci: Get rid of many register ops
2021-06-07 10:43 [PATCH 00/12] SDHCI updates Sascha Hauer
` (9 preceding siblings ...)
2021-06-07 10:44 ` [PATCH 10/12] mci: sdhci: arasan: Use sdhci_set_clock() Sascha Hauer
@ 2021-06-07 10:44 ` Sascha Hauer
2021-06-07 10:44 ` [PATCH 12/12] mci: Add support for Rockchip variant of the dwcmshc Sascha Hauer
11 siblings, 0 replies; 16+ messages in thread
From: Sascha Hauer @ 2021-06-07 10:44 UTC (permalink / raw)
To: Barebox List
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
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 12/12] mci: Add support for Rockchip variant of the dwcmshc
2021-06-07 10:43 [PATCH 00/12] SDHCI updates Sascha Hauer
` (10 preceding siblings ...)
2021-06-07 10:44 ` [PATCH 11/12] mci: sdhci: Get rid of many register ops Sascha Hauer
@ 2021-06-07 10:44 ` Sascha Hauer
11 siblings, 0 replies; 16+ messages in thread
From: Sascha Hauer @ 2021-06-07 10:44 UTC (permalink / raw)
To: Barebox List
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
^ permalink raw reply [flat|nested] 16+ messages in thread