2023-06-19 12:23:24

by Yann Gautier

[permalink] [raw]
Subject: [PATCH v2 0/6] Update MMCI driver for STM32MP25

STM32MP25 is a new SoC from STMicroelectronics. The machine was
pushed by Alexandre [1] in his tree.
On this new SoC, the SDMMC peripheral, using PL18x/MMCI driver
has been updated to v3.
The driver has been updated to manage this new version, and the new
features it supports:
* FIFO size increased from 64B to 1kB
* IDMA size alignment/mask updated
* New block gap hardware flow control
* Delay block updated and dependent on SoC

This series was pushed on top of next branch in Ulf's mmc tree, as it
requires feedback clock update patch [2].

[1] https://lore.kernel.org/lkml/[email protected]/T/
[2] https://lore.kernel.org/r/[email protected]

Changes in v2:
- update dt-bindings file (remove bootloader reference and use enum)

Yann Gautier (6):
dt-bindings: mmc: mmci: Add st,stm32mp25-sdmmc2 compatible
mmc: mmci: add stm32_idmabsize_align parameter
mmc: mmci: Add support for sdmmc variant revision v3.0
mmc: mmci: stm32: manage block gap hardware flow control
mmc: mmci: stm32: prepare other delay block support
mmc: mmci: stm32: add delay block support for STM32MP25

.../devicetree/bindings/mmc/arm,pl18x.yaml | 7 +-
drivers/mmc/host/mmci.c | 35 ++++
drivers/mmc/host/mmci.h | 8 +-
drivers/mmc/host/mmci_stm32_sdmmc.c | 149 ++++++++++++++++--
4 files changed, 179 insertions(+), 20 deletions(-)

--
2.25.1



2023-06-19 12:23:27

by Yann Gautier

[permalink] [raw]
Subject: [PATCH v2 3/6] mmc: mmci: Add support for sdmmc variant revision v3.0

This is an update of the SDMMC revision v2.2, with just an increased
FIFO size, from 64B to 1kB.

Signed-off-by: Yann Gautier <[email protected]>
---
drivers/mmc/host/mmci.c | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index eae3d1c8934cb..3c54ab2c59176 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -306,6 +306,34 @@ static struct variant_data variant_stm32_sdmmcv2 = {
.init = sdmmc_variant_init,
};

+static struct variant_data variant_stm32_sdmmcv3 = {
+ .fifosize = 256 * 4,
+ .fifohalfsize = 128 * 4,
+ .f_max = 267000000,
+ .stm32_clkdiv = true,
+ .cmdreg_cpsm_enable = MCI_CPSM_STM32_ENABLE,
+ .cmdreg_lrsp_crc = MCI_CPSM_STM32_LRSP_CRC,
+ .cmdreg_srsp_crc = MCI_CPSM_STM32_SRSP_CRC,
+ .cmdreg_srsp = MCI_CPSM_STM32_SRSP,
+ .cmdreg_stop = MCI_CPSM_STM32_CMDSTOP,
+ .data_cmd_enable = MCI_CPSM_STM32_CMDTRANS,
+ .irq_pio_mask = MCI_IRQ_PIO_STM32_MASK,
+ .datactrl_first = true,
+ .datacnt_useless = true,
+ .datalength_bits = 25,
+ .datactrl_blocksz = 14,
+ .datactrl_any_blocksz = true,
+ .datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
+ .stm32_idmabsize_mask = GENMASK(16, 6),
+ .stm32_idmabsize_align = BIT(6),
+ .dma_lli = true,
+ .busy_timeout = true,
+ .busy_detect = true,
+ .busy_detect_flag = MCI_STM32_BUSYD0,
+ .busy_detect_mask = MCI_STM32_BUSYD0ENDMASK,
+ .init = sdmmc_variant_init,
+};
+
static struct variant_data variant_qcom = {
.fifosize = 16 * 4,
.fifohalfsize = 8 * 4,
@@ -2500,6 +2528,11 @@ static const struct amba_id mmci_ids[] = {
.mask = 0xf0ffffff,
.data = &variant_stm32_sdmmcv2,
},
+ {
+ .id = 0x00353180,
+ .mask = 0xf0ffffff,
+ .data = &variant_stm32_sdmmcv3,
+ },
/* Qualcomm variants */
{
.id = 0x00051180,
--
2.25.1


2023-06-19 12:24:24

by Yann Gautier

[permalink] [raw]
Subject: [PATCH v2 2/6] mmc: mmci: add stm32_idmabsize_align parameter

The alignment for the IDMA size depends on the peripheral version, it
should then be configurable. Add stm32_idmabsize_align in the variant
structure.
And remove now unused (and wrong) MMCI_STM32_IDMABNDT_* macros.

Signed-off-by: Yann Gautier <[email protected]>
---
drivers/mmc/host/mmci.c | 2 ++
drivers/mmc/host/mmci.h | 3 +--
drivers/mmc/host/mmci_stm32_sdmmc.c | 4 ++--
3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 726bf772b2e2d..eae3d1c8934cb 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -270,6 +270,7 @@ static struct variant_data variant_stm32_sdmmc = {
.datactrl_any_blocksz = true,
.datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
.stm32_idmabsize_mask = GENMASK(12, 5),
+ .stm32_idmabsize_align = BIT(5),
.busy_timeout = true,
.busy_detect = true,
.busy_detect_flag = MCI_STM32_BUSYD0,
@@ -296,6 +297,7 @@ static struct variant_data variant_stm32_sdmmcv2 = {
.datactrl_any_blocksz = true,
.datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
.stm32_idmabsize_mask = GENMASK(16, 5),
+ .stm32_idmabsize_align = BIT(5),
.dma_lli = true,
.busy_timeout = true,
.busy_detect = true,
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 12a7bbd3ce263..b1968cafc58bb 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -227,8 +227,6 @@
#define MMCI_STM32_IDMALLIEN BIT(1)

#define MMCI_STM32_IDMABSIZER 0x054
-#define MMCI_STM32_IDMABNDT_SHIFT 5
-#define MMCI_STM32_IDMABNDT_MASK GENMASK(12, 5)

#define MMCI_STM32_IDMABASE0R 0x058

@@ -374,6 +372,7 @@ struct variant_data {
u32 opendrain;
u8 dma_lli:1;
u32 stm32_idmabsize_mask;
+ u32 stm32_idmabsize_align;
void (*init)(struct mmci_host *host);
};

diff --git a/drivers/mmc/host/mmci_stm32_sdmmc.c b/drivers/mmc/host/mmci_stm32_sdmmc.c
index 50292f9c69046..7f43506b9bb08 100644
--- a/drivers/mmc/host/mmci_stm32_sdmmc.c
+++ b/drivers/mmc/host/mmci_stm32_sdmmc.c
@@ -15,7 +15,6 @@
#include "mmci.h"

#define SDMMC_LLI_BUF_LEN PAGE_SIZE
-#define SDMMC_IDMA_BURST BIT(MMCI_STM32_IDMABNDT_SHIFT)

#define DLYB_CR 0x0
#define DLYB_CR_DEN BIT(0)
@@ -69,7 +68,8 @@ static int sdmmc_idma_validate_data(struct mmci_host *host,
idma->use_bounce_buffer = false;
for_each_sg(data->sg, sg, data->sg_len - 1, i) {
if (!IS_ALIGNED(sg->offset, sizeof(u32)) ||
- !IS_ALIGNED(sg->length, SDMMC_IDMA_BURST)) {
+ !IS_ALIGNED(sg->length,
+ host->variant->stm32_idmabsize_align)) {
dev_dbg(mmc_dev(host->mmc),
"unaligned scatterlist: ofst:%x length:%d\n",
data->sg->offset, data->sg->length);
--
2.25.1


2023-06-19 12:24:44

by Yann Gautier

[permalink] [raw]
Subject: [PATCH v2 6/6] mmc: mmci: stm32: add delay block support for STM32MP25

On STM32MP25, the delay block is inside the SoC, and configured through
the SYSCFG registers. The algorithm is also different from what was in
STM32MP1 chip.

Signed-off-by: Yann Gautier <[email protected]>
---
drivers/mmc/host/mmci_stm32_sdmmc.c | 66 ++++++++++++++++++++++++++++-
1 file changed, 65 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/mmci_stm32_sdmmc.c b/drivers/mmc/host/mmci_stm32_sdmmc.c
index c51c85ca24917..d6112a8dacf8b 100644
--- a/drivers/mmc/host/mmci_stm32_sdmmc.c
+++ b/drivers/mmc/host/mmci_stm32_sdmmc.c
@@ -33,6 +33,20 @@
#define DLYB_LNG_TIMEOUT_US 1000
#define SDMMC_VSWEND_TIMEOUT_US 10000

+#define SYSCFG_DLYBSD_CR 0x0
+#define DLYBSD_CR_EN BIT(0)
+#define DLYBSD_CR_RXTAPSEL_MASK GENMASK(6, 1)
+#define DLYBSD_TAPSEL_NB 32
+#define DLYBSD_BYP_EN BIT(16)
+#define DLYBSD_BYP_CMD GENMASK(21, 17)
+#define DLYBSD_ANTIGLITCH_EN BIT(22)
+
+#define SYSCFG_DLYBSD_SR 0x4
+#define DLYBSD_SR_LOCK BIT(0)
+#define DLYBSD_SR_RXTAPSEL_ACK BIT(1)
+
+#define DLYBSD_TIMEOUT_1S_IN_US 1000000
+
struct sdmmc_lli_desc {
u32 idmalar;
u32 idmabase;
@@ -499,6 +513,46 @@ static int sdmmc_dlyb_mp15_prepare(struct mmci_host *host)
return 0;
}

+static int sdmmc_dlyb_mp25_enable(struct sdmmc_dlyb *dlyb)
+{
+ u32 cr, sr;
+
+ cr = readl_relaxed(dlyb->base + SYSCFG_DLYBSD_CR);
+ cr |= DLYBSD_CR_EN;
+
+ writel_relaxed(cr, dlyb->base + SYSCFG_DLYBSD_CR);
+
+ return readl_relaxed_poll_timeout(dlyb->base + SYSCFG_DLYBSD_SR,
+ sr, sr & DLYBSD_SR_LOCK, 1,
+ DLYBSD_TIMEOUT_1S_IN_US);
+}
+
+static int sdmmc_dlyb_mp25_set_cfg(struct sdmmc_dlyb *dlyb,
+ int unit __maybe_unused, int phase,
+ bool sampler __maybe_unused)
+{
+ u32 cr, sr;
+
+ cr = readl_relaxed(dlyb->base + SYSCFG_DLYBSD_CR);
+ cr &= ~DLYBSD_CR_RXTAPSEL_MASK;
+ cr |= FIELD_PREP(DLYBSD_CR_RXTAPSEL_MASK, phase);
+
+ writel_relaxed(cr, dlyb->base + SYSCFG_DLYBSD_CR);
+
+ return readl_relaxed_poll_timeout(dlyb->base + SYSCFG_DLYBSD_SR,
+ sr, sr & DLYBSD_SR_RXTAPSEL_ACK, 1,
+ DLYBSD_TIMEOUT_1S_IN_US);
+}
+
+static int sdmmc_dlyb_mp25_prepare(struct mmci_host *host)
+{
+ struct sdmmc_dlyb *dlyb = host->variant_priv;
+
+ dlyb->max = DLYBSD_TAPSEL_NB;
+
+ return 0;
+}
+
static int sdmmc_dlyb_phase_tuning(struct mmci_host *host, u32 opcode)
{
struct sdmmc_dlyb *dlyb = host->variant_priv;
@@ -639,6 +693,12 @@ static struct sdmmc_tuning_ops dlyb_tuning_mp15_ops = {
.set_cfg = sdmmc_dlyb_mp15_set_cfg,
};

+static struct sdmmc_tuning_ops dlyb_tuning_mp25_ops = {
+ .dlyb_enable = sdmmc_dlyb_mp25_enable,
+ .tuning_prepare = sdmmc_dlyb_mp25_prepare,
+ .set_cfg = sdmmc_dlyb_mp25_set_cfg,
+};
+
void sdmmc_variant_init(struct mmci_host *host)
{
struct device_node *np = host->mmc->parent->of_node;
@@ -657,7 +717,11 @@ void sdmmc_variant_init(struct mmci_host *host)
return;

dlyb->base = base_dlyb;
- dlyb->ops = &dlyb_tuning_mp15_ops;
+ if (of_device_is_compatible(np, "st,stm32mp25-sdmmc2"))
+ dlyb->ops = &dlyb_tuning_mp25_ops;
+ else
+ dlyb->ops = &dlyb_tuning_mp15_ops;
+
host->variant_priv = dlyb;
host->mmc_ops->execute_tuning = sdmmc_execute_tuning;
}
--
2.25.1


2023-06-19 12:37:15

by Yann Gautier

[permalink] [raw]
Subject: [PATCH v2 4/6] mmc: mmci: stm32: manage block gap hardware flow control

In stm32 sdmmc variant revision v3.0, a block gap hardware flow control
should be used with bus speed modes SDR104 and HS200.
It is enabled by writing a non-null value to the new added register
MMCI_STM32_FIFOTHRR.
The threshold will be 2^(N-1) bytes, so we can use the ffs() function to
compute the value N to be written to the register. The threshold used
should be the data block size, but must not be bigger than the FIFO size.

Signed-off-by: Yann Gautier <[email protected]>
---
drivers/mmc/host/mmci.h | 5 +++++
drivers/mmc/host/mmci_stm32_sdmmc.c | 13 +++++++++++++
2 files changed, 18 insertions(+)

diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index b1968cafc58bb..361954249d04d 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -218,6 +218,11 @@
#define MCI_STM32_BUSYD0ENDMASK BIT(21)

#define MMCIMASK1 0x040
+
+/* STM32 sdmmc data FIFO threshold register */
+#define MMCI_STM32_FIFOTHRR 0x044
+#define MMCI_STM32_THR_MASK GENMASK(3, 0)
+
#define MMCIFIFOCNT 0x048
#define MMCIFIFO 0x080 /* to 0x0bc */

diff --git a/drivers/mmc/host/mmci_stm32_sdmmc.c b/drivers/mmc/host/mmci_stm32_sdmmc.c
index 7f43506b9bb08..0dc1ae674f44c 100644
--- a/drivers/mmc/host/mmci_stm32_sdmmc.c
+++ b/drivers/mmc/host/mmci_stm32_sdmmc.c
@@ -361,6 +361,19 @@ static u32 sdmmc_get_dctrl_cfg(struct mmci_host *host)

datactrl = mmci_dctrl_blksz(host);

+ if (host->hw_revision >= 3) {
+ u32 thr = 0;
+
+ if (host->mmc->ios.timing == MMC_TIMING_UHS_SDR104 ||
+ host->mmc->ios.timing == MMC_TIMING_MMC_HS200) {
+ thr = ffs(min_t(unsigned int, host->data->blksz,
+ host->variant->fifosize));
+ thr = min_t(u32, thr, MMCI_STM32_THR_MASK);
+ }
+
+ writel_relaxed(thr, host->base + MMCI_STM32_FIFOTHRR);
+ }
+
if (host->mmc->card && mmc_card_sdio(host->mmc->card) &&
host->data->blocks == 1)
datactrl |= MCI_DPSM_STM32_MODE_SDIO;
--
2.25.1


2023-06-20 10:32:32

by Ulf Hansson

[permalink] [raw]
Subject: Re: [PATCH v2 0/6] Update MMCI driver for STM32MP25

On Mon, 19 Jun 2023 at 13:51, Yann Gautier <[email protected]> wrote:
>
> STM32MP25 is a new SoC from STMicroelectronics. The machine was
> pushed by Alexandre [1] in his tree.
> On this new SoC, the SDMMC peripheral, using PL18x/MMCI driver
> has been updated to v3.
> The driver has been updated to manage this new version, and the new
> features it supports:
> * FIFO size increased from 64B to 1kB
> * IDMA size alignment/mask updated
> * New block gap hardware flow control
> * Delay block updated and dependent on SoC
>
> This series was pushed on top of next branch in Ulf's mmc tree, as it
> requires feedback clock update patch [2].
>
> [1] https://lore.kernel.org/lkml/[email protected]/T/
> [2] https://lore.kernel.org/r/[email protected]
>
> Changes in v2:
> - update dt-bindings file (remove bootloader reference and use enum)
>
> Yann Gautier (6):
> dt-bindings: mmc: mmci: Add st,stm32mp25-sdmmc2 compatible
> mmc: mmci: add stm32_idmabsize_align parameter
> mmc: mmci: Add support for sdmmc variant revision v3.0
> mmc: mmci: stm32: manage block gap hardware flow control
> mmc: mmci: stm32: prepare other delay block support
> mmc: mmci: stm32: add delay block support for STM32MP25
>
> .../devicetree/bindings/mmc/arm,pl18x.yaml | 7 +-
> drivers/mmc/host/mmci.c | 35 ++++
> drivers/mmc/host/mmci.h | 8 +-
> drivers/mmc/host/mmci_stm32_sdmmc.c | 149 ++++++++++++++++--
> 4 files changed, 179 insertions(+), 20 deletions(-)
>

Applied for next, thanks!

Kind regards
Uffe