* [PATCH 00/12] Share i.MX ESDHC PBL and PIO code
@ 2019-12-02 15:19 Andrey Smirnov
2019-12-02 15:19 ` [PATCH 01/12] mci: imx-esdhc: Drop unnecessary type conversion Andrey Smirnov
` (12 more replies)
0 siblings, 13 replies; 14+ messages in thread
From: Andrey Smirnov @ 2019-12-02 15:19 UTC (permalink / raw)
To: barebox; +Cc: Andrey Smirnov
Everyone:
This series is an attempt to share as much functionality between PBL
ESDHC code and PIO case of regular ESDHC driver as possible, since
both implementations are identical in a lot of ways.
Tested on RDU2 (i.MX6) and RDU3 (i.MX8MQ)
Feedback is welcome!
Thanks,
Andrey Smirnov
Andrey Smirnov (12):
mci: imx-esdhc: Drop unnecessary type conversion
mci: imx-esdhc: Drop unused type definition
mci: imx-esdhc: Drop extra helper varaible
mci: imx-esdhc-pbl: Don't setup DMA registers
mci: imx-esdhc-pbl: Share initialization code
mci: imx-esdhc-pbl: Drop 'wrap_wml' flag
mci: imx-esdhc-pbl: Share IO accessors with regular driver
mci: imx-esdhc-pbl: Use sdhci_transfer_data()
mci: imx-esdhc-pbl: Use sdhci_set_cmd_xfer_mode()
mci: imx-esdhc: Share code for esdhc_(setup|do)_data operations
mci: imx-esdhc: Introduce esdhc_poll()
mci: imx-esdhc: Share code for esdhc_send_cmd()
drivers/mci/Kconfig | 1 +
drivers/mci/Makefile | 6 +-
drivers/mci/imx-esdhc-common.c | 275 +++++++++++++++++++++++++++
drivers/mci/imx-esdhc-pbl.c | 330 ++++++++-------------------------
drivers/mci/imx-esdhc.c | 326 ++------------------------------
drivers/mci/imx-esdhc.h | 104 ++++++++++-
drivers/mci/sdhci.c | 13 ++
7 files changed, 487 insertions(+), 568 deletions(-)
create mode 100644 drivers/mci/imx-esdhc-common.c
--
2.21.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 01/12] mci: imx-esdhc: Drop unnecessary type conversion
2019-12-02 15:19 [PATCH 00/12] Share i.MX ESDHC PBL and PIO code Andrey Smirnov
@ 2019-12-02 15:19 ` Andrey Smirnov
2019-12-02 15:19 ` [PATCH 02/12] mci: imx-esdhc: Drop unused type definition Andrey Smirnov
` (11 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Andrey Smirnov @ 2019-12-02 15:19 UTC (permalink / raw)
To: barebox; +Cc: Andrey Smirnov
Nether esdhc_setup_data() nor esdhc_do_data() really need struct
mci_host, so we can drop a bit of extra type conversion code by
changing their signature to accept struct fsl_esdhc_host instead
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
drivers/mci/imx-esdhc.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c
index bebc36d0b..7d12df2b8 100644
--- a/drivers/mci/imx-esdhc.c
+++ b/drivers/mci/imx-esdhc.c
@@ -164,10 +164,9 @@ static inline void esdhc_setbits32(struct fsl_esdhc_host *host, unsigned int reg
esdhc_clrsetbits32(host, reg, 0, set);
}
-static int esdhc_setup_data(struct mci_host *mci, struct mci_data *data,
+static int esdhc_setup_data(struct fsl_esdhc_host *host, struct mci_data *data,
dma_addr_t dma)
{
- struct fsl_esdhc_host *host = to_fsl_esdhc(mci);
u32 wml_value;
if (!IS_ENABLED(CONFIG_MCI_IMX_ESDHC_PIO)) {
@@ -193,9 +192,8 @@ static int esdhc_setup_data(struct mci_host *mci, struct mci_data *data,
return 0;
}
-static int esdhc_do_data(struct mci_host *mci, struct mci_data *data)
+static int esdhc_do_data(struct fsl_esdhc_host *host, struct mci_data *data)
{
- struct fsl_esdhc_host *host = to_fsl_esdhc(mci);
u32 irqstat;
if (IS_ENABLED(CONFIG_MCI_IMX_ESDHC_PIO))
@@ -256,7 +254,7 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
return -EFAULT;
}
- err = esdhc_setup_data(mci, data, dma);
+ err = esdhc_setup_data(host, data, dma);
if(err)
return err;
}
@@ -319,7 +317,7 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
/* Wait until all of the blocks are transferred */
if (data) {
- ret = esdhc_do_data(mci, data);
+ ret = esdhc_do_data(host, data);
if (ret)
return ret;
--
2.21.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 02/12] mci: imx-esdhc: Drop unused type definition
2019-12-02 15:19 [PATCH 00/12] Share i.MX ESDHC PBL and PIO code Andrey Smirnov
2019-12-02 15:19 ` [PATCH 01/12] mci: imx-esdhc: Drop unnecessary type conversion Andrey Smirnov
@ 2019-12-02 15:19 ` Andrey Smirnov
2019-12-02 15:19 ` [PATCH 03/12] mci: imx-esdhc: Drop extra helper varaible Andrey Smirnov
` (10 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Andrey Smirnov @ 2019-12-02 15:19 UTC (permalink / raw)
To: barebox; +Cc: Andrey Smirnov
There doesn't seem to be any users of struct fsl_esdhc_cfg in the
tree. Drop it.
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
drivers/mci/imx-esdhc.h | 5 -----
1 file changed, 5 deletions(-)
diff --git a/drivers/mci/imx-esdhc.h b/drivers/mci/imx-esdhc.h
index 46f592e49..ad05c4c0b 100644
--- a/drivers/mci/imx-esdhc.h
+++ b/drivers/mci/imx-esdhc.h
@@ -69,9 +69,4 @@
#define ESDHC_DMA_SYSCTL 0x40c /* Layerscape specific */
#define ESDHC_SYSCTL_DMA_SNOOP BIT(6)
-struct fsl_esdhc_cfg {
- u32 esdhc_base;
- u32 no_snoop;
-};
-
#endif /* __FSL_ESDHC_H__ */
--
2.21.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 03/12] mci: imx-esdhc: Drop extra helper varaible
2019-12-02 15:19 [PATCH 00/12] Share i.MX ESDHC PBL and PIO code Andrey Smirnov
2019-12-02 15:19 ` [PATCH 01/12] mci: imx-esdhc: Drop unnecessary type conversion Andrey Smirnov
2019-12-02 15:19 ` [PATCH 02/12] mci: imx-esdhc: Drop unused type definition Andrey Smirnov
@ 2019-12-02 15:19 ` Andrey Smirnov
2019-12-02 15:19 ` [PATCH 04/12] mci: imx-esdhc-pbl: Don't setup DMA registers Andrey Smirnov
` (9 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Andrey Smirnov @ 2019-12-02 15:19 UTC (permalink / raw)
To: barebox; +Cc: Andrey Smirnov
There's already 'ret' availible, no need to declare another return
value variable.
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
drivers/mci/imx-esdhc.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c
index 7d12df2b8..b6dd75d2c 100644
--- a/drivers/mci/imx-esdhc.c
+++ b/drivers/mci/imx-esdhc.c
@@ -236,8 +236,6 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
/* Set up for a data transfer if we have one */
if (data) {
- int err;
-
if (!IS_ENABLED(CONFIG_MCI_IMX_ESDHC_PIO)) {
num_bytes = data->blocks * data->blocksize;
@@ -254,9 +252,9 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
return -EFAULT;
}
- err = esdhc_setup_data(host, data, dma);
- if(err)
- return err;
+ ret = esdhc_setup_data(host, data, dma);
+ if (ret)
+ return ret;
}
sdhci_set_cmd_xfer_mode(&host->sdhci, cmd, data,
--
2.21.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 04/12] mci: imx-esdhc-pbl: Don't setup DMA registers
2019-12-02 15:19 [PATCH 00/12] Share i.MX ESDHC PBL and PIO code Andrey Smirnov
` (2 preceding siblings ...)
2019-12-02 15:19 ` [PATCH 03/12] mci: imx-esdhc: Drop extra helper varaible Andrey Smirnov
@ 2019-12-02 15:19 ` Andrey Smirnov
2019-12-02 15:19 ` [PATCH 05/12] mci: imx-esdhc-pbl: Share initialization code Andrey Smirnov
` (8 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Andrey Smirnov @ 2019-12-02 15:19 UTC (permalink / raw)
To: barebox; +Cc: Andrey Smirnov
PBL code is PIO only, so setting up DMA related registers shouldn't be
necessary.
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
drivers/mci/imx-esdhc-pbl.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c
index 5e3157e6c..2afb55af9 100644
--- a/drivers/mci/imx-esdhc-pbl.c
+++ b/drivers/mci/imx-esdhc-pbl.c
@@ -139,13 +139,7 @@ esdhc_send_cmd(struct esdhc *esdhc, struct mci_cmd *cmd, struct mci_data *data)
__udelay(1);
if (data) {
- unsigned long dest = (unsigned long)data->dest;
-
- if (dest > 0xffffffff)
- return -EINVAL;
-
/* Set up for a data transfer if we have one */
- esdhc_write32(esdhc, SDHCI_DMA_ADDRESS, (u32)dest);
esdhc_write32(esdhc, SDHCI_BLOCK_SIZE__BLOCK_COUNT, data->blocks << 16 | SECTOR_SIZE);
}
--
2.21.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 05/12] mci: imx-esdhc-pbl: Share initialization code
2019-12-02 15:19 [PATCH 00/12] Share i.MX ESDHC PBL and PIO code Andrey Smirnov
` (3 preceding siblings ...)
2019-12-02 15:19 ` [PATCH 04/12] mci: imx-esdhc-pbl: Don't setup DMA registers Andrey Smirnov
@ 2019-12-02 15:19 ` Andrey Smirnov
2019-12-02 15:19 ` [PATCH 06/12] mci: imx-esdhc-pbl: Drop 'wrap_wml' flag Andrey Smirnov
` (7 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Andrey Smirnov @ 2019-12-02 15:19 UTC (permalink / raw)
To: barebox; +Cc: Andrey Smirnov
Move common ESDHC initialization code into subroutines and convert the
rest of the code to use it.
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
drivers/mci/imx-esdhc-pbl.c | 64 +++++++++++++++++++------------------
1 file changed, 33 insertions(+), 31 deletions(-)
diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c
index 2afb55af9..d5d83d18e 100644
--- a/drivers/mci/imx-esdhc-pbl.c
+++ b/drivers/mci/imx-esdhc-pbl.c
@@ -365,6 +365,31 @@ esdhc_start_image(struct esdhc *esdhc, ptrdiff_t address, ptrdiff_t entry,
bb();
}
+static void imx_esdhc_init(struct esdhc *esdhc)
+{
+ esdhc->is_be = 0;
+ esdhc->is_mx6 = 1;
+ esdhc->wrap_wml = false;
+}
+
+static int imx8_esdhc_init(struct esdhc *esdhc, int instance)
+{
+ switch (instance) {
+ case 0:
+ esdhc->regs = IOMEM(MX8MQ_USDHC1_BASE_ADDR);
+ break;
+ case 1:
+ esdhc->regs = IOMEM(MX8MQ_USDHC2_BASE_ADDR);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ imx_esdhc_init(esdhc);
+
+ return 0;
+}
+
/**
* imx6_esdhc_start_image - Load and start an image from USDHC controller
* @instance: The USDHC controller instance (0..4)
@@ -398,9 +423,7 @@ int imx6_esdhc_start_image(int instance)
return -EINVAL;
}
- esdhc.is_be = 0;
- esdhc.is_mx6 = 1;
- esdhc.wrap_wml = false;
+ imx_esdhc_init(&esdhc);
return esdhc_start_image(&esdhc, 0x10000000, 0x10000000, 0);
}
@@ -420,21 +443,11 @@ int imx6_esdhc_start_image(int instance)
int imx8_esdhc_start_image(int instance)
{
struct esdhc esdhc;
+ int ret;
- switch (instance) {
- case 0:
- esdhc.regs = IOMEM(MX8MQ_USDHC1_BASE_ADDR);
- break;
- case 1:
- esdhc.regs = IOMEM(MX8MQ_USDHC2_BASE_ADDR);
- break;
- default:
- return -EINVAL;
- }
-
- esdhc.is_be = 0;
- esdhc.is_mx6 = 1;
- esdhc.wrap_wml = false;
+ ret = imx8_esdhc_init(&esdhc, instance);
+ if (ret)
+ return ret;
return esdhc_start_image(&esdhc, MX8MQ_DDR_CSD1_BASE_ADDR,
MX8MQ_ATF_BL33_BASE_ADDR, SZ_32K);
@@ -448,20 +461,9 @@ int imx8_esdhc_load_piggy(int instance)
int ret, len;
int offset = SZ_32K;
- switch (instance) {
- case 0:
- esdhc.regs = IOMEM(MX8MQ_USDHC1_BASE_ADDR);
- break;
- case 1:
- esdhc.regs = IOMEM(MX8MQ_USDHC2_BASE_ADDR);
- break;
- default:
- return -EINVAL;
- }
-
- esdhc.is_be = 0;
- esdhc.is_mx6 = 1;
- esdhc.wrap_wml = false;
+ ret = imx8_esdhc_init(&esdhc, instance);
+ if (ret)
+ return ret;
/*
* We expect to be running at MX8MQ_ATF_BL33_BASE_ADDR where the atf
--
2.21.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 06/12] mci: imx-esdhc-pbl: Drop 'wrap_wml' flag
2019-12-02 15:19 [PATCH 00/12] Share i.MX ESDHC PBL and PIO code Andrey Smirnov
` (4 preceding siblings ...)
2019-12-02 15:19 ` [PATCH 05/12] mci: imx-esdhc-pbl: Share initialization code Andrey Smirnov
@ 2019-12-02 15:19 ` Andrey Smirnov
2019-12-02 15:19 ` [PATCH 07/12] mci: imx-esdhc-pbl: Share IO accessors with regular driver Andrey Smirnov
` (6 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Andrey Smirnov @ 2019-12-02 15:19 UTC (permalink / raw)
To: barebox; +Cc: Andrey Smirnov
IMX_SDHCI_WML doesn't change its value during PBL opearation, so it
should be possible to configure it once. Doing it once also allows us
to move the call into SoC specific code making 'wrap_wml' flag
unnecessary.
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
drivers/mci/imx-esdhc-pbl.c | 26 +++++++++-----------------
1 file changed, 9 insertions(+), 17 deletions(-)
diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c
index d5d83d18e..e81f0f107 100644
--- a/drivers/mci/imx-esdhc-pbl.c
+++ b/drivers/mci/imx-esdhc-pbl.c
@@ -34,7 +34,6 @@ struct esdhc {
void __iomem *regs;
bool is_mx6;
bool is_be;
- bool wrap_wml;
};
static uint32_t esdhc_read32(struct esdhc *esdhc, int reg)
@@ -204,7 +203,7 @@ static int esdhc_read_blocks(struct esdhc *esdhc, void *dst, size_t len)
{
struct mci_cmd cmd;
struct mci_data data;
- u32 val, wml;
+ u32 val;
int ret;
esdhc_write32(esdhc, SDHCI_INT_ENABLE,
@@ -213,19 +212,6 @@ static int esdhc_read_blocks(struct esdhc *esdhc, void *dst, size_t len)
SDHCI_INT_END_BIT | SDHCI_INT_INDEX | SDHCI_INT_DATA_TIMEOUT |
SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT | SDHCI_INT_DMA);
- wml = FIELD_PREP(WML_WR_BRST_LEN, 16) |
- FIELD_PREP(WML_WR_WML_MASK, SECTOR_WML) |
- FIELD_PREP(WML_RD_BRST_LEN, 16) |
- FIELD_PREP(WML_RD_WML_MASK, SECTOR_WML);
- /*
- * Some SoCs intrpret 0 as MAX value so for those cases the
- * above value translates to zero
- */
- if (esdhc->wrap_wml)
- wml = 0;
-
- esdhc_write32(esdhc, IMX_SDHCI_WML, wml);
-
val = esdhc_read32(esdhc, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET);
val |= SYSCTL_HCKEN | SYSCTL_IPGEN;
esdhc_write32(esdhc, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, val);
@@ -369,7 +355,12 @@ static void imx_esdhc_init(struct esdhc *esdhc)
{
esdhc->is_be = 0;
esdhc->is_mx6 = 1;
- esdhc->wrap_wml = false;
+
+ esdhc_write32(esdhc, IMX_SDHCI_WML,
+ FIELD_PREP(WML_WR_BRST_LEN, 16) |
+ FIELD_PREP(WML_WR_WML_MASK, SECTOR_WML) |
+ FIELD_PREP(WML_RD_BRST_LEN, 16) |
+ FIELD_PREP(WML_RD_WML_MASK, SECTOR_WML));
}
static int imx8_esdhc_init(struct esdhc *esdhc, int instance)
@@ -520,12 +511,13 @@ int ls1046a_esdhc_start_image(unsigned long r0, unsigned long r1, unsigned long
struct esdhc esdhc = {
.regs = IOMEM(0x01560000),
.is_be = true,
- .wrap_wml = true,
};
unsigned long sdram = 0x80000000;
void (*barebox)(unsigned long, unsigned long, unsigned long) =
(void *)(sdram + LS1046A_SD_IMAGE_OFFSET);
+ esdhc_write32(&esdhc, IMX_SDHCI_WML, 0);
+
/*
* The ROM leaves us here with a clock frequency of around 400kHz. Speed
* this up a bit. FIXME: The resulting frequency has not yet been verified
--
2.21.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 07/12] mci: imx-esdhc-pbl: Share IO accessors with regular driver
2019-12-02 15:19 [PATCH 00/12] Share i.MX ESDHC PBL and PIO code Andrey Smirnov
` (5 preceding siblings ...)
2019-12-02 15:19 ` [PATCH 06/12] mci: imx-esdhc-pbl: Drop 'wrap_wml' flag Andrey Smirnov
@ 2019-12-02 15:19 ` Andrey Smirnov
2019-12-02 15:19 ` [PATCH 08/12] mci: imx-esdhc-pbl: Use sdhci_transfer_data() Andrey Smirnov
` (5 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Andrey Smirnov @ 2019-12-02 15:19 UTC (permalink / raw)
To: barebox; +Cc: Andrey Smirnov
With a bit of a change to PBL ESDHC initialization code it is possible
to share all of the low-level I/O accessor code with the regular
driver, including sharing definitions of flags describing HW's quirks.
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
drivers/mci/Makefile | 4 +-
drivers/mci/imx-esdhc-common.c | 47 ++++++++++
drivers/mci/imx-esdhc-pbl.c | 151 +++++++++++++++------------------
drivers/mci/imx-esdhc.c | 126 +--------------------------
drivers/mci/imx-esdhc.h | 98 +++++++++++++++++++++
5 files changed, 218 insertions(+), 208 deletions(-)
create mode 100644 drivers/mci/imx-esdhc-common.c
diff --git a/drivers/mci/Makefile b/drivers/mci/Makefile
index e2e3ba7ef..cfb84a899 100644
--- a/drivers/mci/Makefile
+++ b/drivers/mci/Makefile
@@ -5,8 +5,8 @@ obj-$(CONFIG_MCI_BCM283X) += mci-bcm2835.o
obj-$(CONFIG_MCI_BCM283X_SDHOST) += bcm2835-sdhost.o
obj-$(CONFIG_MCI_DOVE) += dove-sdhci.o
obj-$(CONFIG_MCI_IMX) += imx.o
-obj-$(CONFIG_MCI_IMX_ESDHC) += imx-esdhc.o
-pbl-$(CONFIG_MCI_IMX_ESDHC_PBL) += imx-esdhc-pbl.o
+obj-$(CONFIG_MCI_IMX_ESDHC) += imx-esdhc.o imx-esdhc-common.o
+pbl-$(CONFIG_MCI_IMX_ESDHC_PBL) += imx-esdhc-pbl.o imx-esdhc-common.o
obj-$(CONFIG_MCI_MXS) += mxs.o
obj-$(CONFIG_MCI_OMAP_HSMMC) += omap_hsmmc.o
obj-$(CONFIG_MCI_PXA) += pxamci.o
diff --git a/drivers/mci/imx-esdhc-common.c b/drivers/mci/imx-esdhc-common.c
new file mode 100644
index 000000000..bcdf661ed
--- /dev/null
+++ b/drivers/mci/imx-esdhc-common.c
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <common.h>
+#include <io.h>
+#include <mci.h>
+
+#include "sdhci.h"
+#include "imx-esdhc.h"
+
+static u32 esdhc_op_read32_le(struct sdhci *sdhci, int reg)
+{
+ struct fsl_esdhc_host *host = sdhci_to_esdhc(sdhci);
+
+ return readl(host->regs + reg);
+}
+
+static u32 esdhc_op_read32_be(struct sdhci *sdhci, int reg)
+{
+ struct fsl_esdhc_host *host = sdhci_to_esdhc(sdhci);
+
+ return in_be32(host->regs + reg);
+}
+
+static void esdhc_op_write32_le(struct sdhci *sdhci, int reg, u32 val)
+{
+ struct fsl_esdhc_host *host = sdhci_to_esdhc(sdhci);
+
+ writel(val, host->regs + reg);
+}
+
+static void esdhc_op_write32_be(struct sdhci *sdhci, int reg, u32 val)
+{
+ struct fsl_esdhc_host *host = sdhci_to_esdhc(sdhci);
+
+ out_be32(host->regs + reg, val);
+}
+
+void esdhc_populate_sdhci(struct fsl_esdhc_host *host)
+{
+ if (host->socdata->flags & ESDHC_FLAG_BIGENDIAN) {
+ 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 e81f0f107..08f28471c 100644
--- a/drivers/mci/imx-esdhc-pbl.c
+++ b/drivers/mci/imx-esdhc-pbl.c
@@ -30,28 +30,6 @@
#define SECTOR_SIZE 512
#define SECTOR_WML (SECTOR_SIZE / sizeof(u32))
-struct esdhc {
- void __iomem *regs;
- bool is_mx6;
- bool is_be;
-};
-
-static uint32_t esdhc_read32(struct esdhc *esdhc, int reg)
-{
- if (esdhc->is_be)
- return in_be32(esdhc->regs + reg);
- else
- return readl(esdhc->regs + reg);
-}
-
-static void esdhc_write32(struct esdhc *esdhc, int reg, uint32_t val)
-{
- if (esdhc->is_be)
- out_be32(esdhc->regs + reg, val);
- else
- writel(val, esdhc->regs + reg);
-}
-
static void __udelay(int us)
{
volatile int i;
@@ -86,7 +64,7 @@ static u32 esdhc_xfertyp(struct mci_cmd *cmd, struct mci_data *data)
return command << 16 | xfertyp;
}
-static int esdhc_do_data(struct esdhc *esdhc, struct mci_data *data)
+static int esdhc_do_data(struct fsl_esdhc_host *host, struct mci_data *data)
{
char *buffer;
u32 databuf;
@@ -97,14 +75,14 @@ static int esdhc_do_data(struct esdhc *esdhc, struct mci_data *data)
buffer = data->dest;
size = data->blocksize * data->blocks;
- irqstat = esdhc_read32(esdhc, SDHCI_INT_STATUS);
+ irqstat = sdhci_read32(&host->sdhci, SDHCI_INT_STATUS);
while (size) {
int i;
int timeout = 1000000;
while (1) {
- present = esdhc_read32(esdhc, SDHCI_PRESENT_STATE) & SDHCI_BUFFER_READ_ENABLE;
+ present = sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & SDHCI_BUFFER_READ_ENABLE;
if (present)
break;
if (!--timeout) {
@@ -114,7 +92,7 @@ static int esdhc_do_data(struct esdhc *esdhc, struct mci_data *data)
}
for (i = 0; i < SECTOR_WML; i++) {
- databuf = esdhc_read32(esdhc, SDHCI_BUFFER);
+ databuf = sdhci_read32(&host->sdhci, SDHCI_BUFFER);
*((u32 *)buffer) = databuf;
buffer += 4;
size -= 4;
@@ -125,49 +103,49 @@ static int esdhc_do_data(struct esdhc *esdhc, struct mci_data *data)
}
static int
-esdhc_send_cmd(struct esdhc *esdhc, struct mci_cmd *cmd, struct mci_data *data)
+esdhc_send_cmd(struct fsl_esdhc_host *host, struct mci_cmd *cmd, struct mci_data *data)
{
u32 xfertyp, mixctrl;
u32 irqstat;
int ret;
int timeout;
- esdhc_write32(esdhc, SDHCI_INT_STATUS, -1);
+ sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, -1);
/* Wait at least 8 SD clock cycles before the next command */
__udelay(1);
if (data) {
/* Set up for a data transfer if we have one */
- esdhc_write32(esdhc, SDHCI_BLOCK_SIZE__BLOCK_COUNT, data->blocks << 16 | SECTOR_SIZE);
+ sdhci_write32(&host->sdhci, SDHCI_BLOCK_SIZE__BLOCK_COUNT, data->blocks << 16 | SECTOR_SIZE);
}
/* Figure out the transfer arguments */
xfertyp = esdhc_xfertyp(cmd, data);
/* Send the command */
- esdhc_write32(esdhc, SDHCI_ARGUMENT, cmd->cmdarg);
+ sdhci_write32(&host->sdhci, SDHCI_ARGUMENT, cmd->cmdarg);
- if (esdhc->is_mx6) {
+ if (esdhc_is_usdhc(host)) {
/* write lower-half of xfertyp to mixctrl */
mixctrl = xfertyp & 0xFFFF;
/* Keep the bits 22-25 of the register as is */
- mixctrl |= (esdhc_read32(esdhc, IMX_SDHCI_MIXCTRL) & (0xF << 22));
- esdhc_write32(esdhc, IMX_SDHCI_MIXCTRL, mixctrl);
+ mixctrl |= (sdhci_read32(&host->sdhci, IMX_SDHCI_MIXCTRL) & (0xF << 22));
+ sdhci_write32(&host->sdhci, IMX_SDHCI_MIXCTRL, mixctrl);
}
- esdhc_write32(esdhc, SDHCI_TRANSFER_MODE__COMMAND, xfertyp);
+ sdhci_write32(&host->sdhci, SDHCI_TRANSFER_MODE__COMMAND, xfertyp);
/* Wait for the command to complete */
timeout = 10000;
- while (!(esdhc_read32(esdhc, SDHCI_INT_STATUS) & SDHCI_INT_CMD_COMPLETE)) {
+ while (!(sdhci_read32(&host->sdhci, SDHCI_INT_STATUS) & SDHCI_INT_CMD_COMPLETE)) {
__udelay(1);
if (!timeout--)
return -ETIMEDOUT;
}
- irqstat = esdhc_read32(esdhc, SDHCI_INT_STATUS);
- esdhc_write32(esdhc, SDHCI_INT_STATUS, irqstat);
+ irqstat = sdhci_read32(&host->sdhci, SDHCI_INT_STATUS);
+ sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, irqstat);
if (irqstat & CMD_ERR)
return -EIO;
@@ -176,20 +154,20 @@ esdhc_send_cmd(struct esdhc *esdhc, struct mci_cmd *cmd, struct mci_data *data)
return -ETIMEDOUT;
/* Copy the response to the response buffer */
- cmd->response[0] = esdhc_read32(esdhc, SDHCI_RESPONSE_0);
+ cmd->response[0] = sdhci_read32(&host->sdhci, SDHCI_RESPONSE_0);
/* Wait until all of the blocks are transferred */
if (data) {
- ret = esdhc_do_data(esdhc, data);
+ ret = esdhc_do_data(host, data);
if (ret)
return ret;
}
- esdhc_write32(esdhc, SDHCI_INT_STATUS, -1);
+ sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, -1);
/* Wait for the bus to be idle */
timeout = 10000;
- while (esdhc_read32(esdhc, SDHCI_PRESENT_STATE) & (SDHCI_CMD_INHIBIT_CMD |
+ while (sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & (SDHCI_CMD_INHIBIT_CMD |
SDHCI_CMD_INHIBIT_DATA | SDHCI_DATA_LINE_ACTIVE)) {
__udelay(1);
if (!timeout--)
@@ -199,22 +177,22 @@ esdhc_send_cmd(struct esdhc *esdhc, struct mci_cmd *cmd, struct mci_data *data)
return 0;
}
-static int esdhc_read_blocks(struct esdhc *esdhc, void *dst, size_t len)
+static int esdhc_read_blocks(struct fsl_esdhc_host *host, void *dst, size_t len)
{
struct mci_cmd cmd;
struct mci_data data;
u32 val;
int ret;
- esdhc_write32(esdhc, SDHCI_INT_ENABLE,
+ sdhci_write32(&host->sdhci, SDHCI_INT_ENABLE,
SDHCI_INT_CMD_COMPLETE | SDHCI_INT_XFER_COMPLETE |
SDHCI_INT_CARD_INT | SDHCI_INT_TIMEOUT | SDHCI_INT_CRC |
SDHCI_INT_END_BIT | SDHCI_INT_INDEX | SDHCI_INT_DATA_TIMEOUT |
SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT | SDHCI_INT_DMA);
- val = esdhc_read32(esdhc, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET);
+ val = sdhci_read32(&host->sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET);
val |= SYSCTL_HCKEN | SYSCTL_IPGEN;
- esdhc_write32(esdhc, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, val);
+ sdhci_write32(&host->sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, val);
cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
cmd.cmdarg = 0;
@@ -225,7 +203,7 @@ static int esdhc_read_blocks(struct esdhc *esdhc, void *dst, size_t len)
data.blocksize = SECTOR_SIZE;
data.flags = MMC_DATA_READ;
- ret = esdhc_send_cmd(esdhc, &cmd, &data);
+ ret = esdhc_send_cmd(host, &cmd, &data);
if (ret) {
pr_debug("send command failed with %d\n", ret);
return ret;
@@ -235,13 +213,13 @@ static int esdhc_read_blocks(struct esdhc *esdhc, void *dst, size_t len)
cmd.cmdarg = 0;
cmd.resp_type = MMC_RSP_R1b;
- esdhc_send_cmd(esdhc, &cmd, NULL);
+ esdhc_send_cmd(host, &cmd, NULL);
return 0;
}
#ifdef CONFIG_ARCH_IMX
-static int esdhc_search_header(struct esdhc *esdhc,
+static int esdhc_search_header(struct fsl_esdhc_host *host,
struct imx_flash_header_v2 **header_pointer,
void *buffer, u32 *offset)
{
@@ -251,7 +229,7 @@ static int esdhc_search_header(struct esdhc *esdhc,
struct imx_flash_header_v2 *hdr;
for (i = 0; i < header_count; i++) {
- ret = esdhc_read_blocks(esdhc, buf,
+ ret = esdhc_read_blocks(host, buf,
*offset + SZ_1K + SECTOR_SIZE);
if (ret)
return ret;
@@ -288,7 +266,7 @@ static int esdhc_search_header(struct esdhc *esdhc,
}
static int
-esdhc_start_image(struct esdhc *esdhc, ptrdiff_t address, ptrdiff_t entry,
+esdhc_start_image(struct fsl_esdhc_host *host, ptrdiff_t address, ptrdiff_t entry,
u32 offset)
{
@@ -301,7 +279,7 @@ esdhc_start_image(struct esdhc *esdhc, ptrdiff_t address, ptrdiff_t entry,
len = imx_image_size();
len = ALIGN(len, SECTOR_SIZE);
- ret = esdhc_search_header(esdhc, &hdr, buf, &offset);
+ ret = esdhc_search_header(host, &hdr, buf, &offset);
if (ret)
return ret;
@@ -336,7 +314,7 @@ esdhc_start_image(struct esdhc *esdhc, ptrdiff_t address, ptrdiff_t entry,
buf = (void *)(entry - ofs);
}
- ret = esdhc_read_blocks(esdhc, buf, offset + len);
+ ret = esdhc_read_blocks(host, buf, offset + len);
if (ret) {
pr_err("Loading image failed with %d\n", ret);
return ret;
@@ -351,32 +329,36 @@ esdhc_start_image(struct esdhc *esdhc, ptrdiff_t address, ptrdiff_t entry,
bb();
}
-static void imx_esdhc_init(struct esdhc *esdhc)
+static void imx_esdhc_init(struct fsl_esdhc_host *host,
+ struct esdhc_soc_data *data)
{
- esdhc->is_be = 0;
- esdhc->is_mx6 = 1;
+ data->flags = ESDHC_FLAG_USDHC;
+ host->socdata = data;
+ esdhc_populate_sdhci(host);
- esdhc_write32(esdhc, IMX_SDHCI_WML,
+ sdhci_write32(&host->sdhci, IMX_SDHCI_WML,
FIELD_PREP(WML_WR_BRST_LEN, 16) |
FIELD_PREP(WML_WR_WML_MASK, SECTOR_WML) |
FIELD_PREP(WML_RD_BRST_LEN, 16) |
FIELD_PREP(WML_RD_WML_MASK, SECTOR_WML));
}
-static int imx8_esdhc_init(struct esdhc *esdhc, int instance)
+static int imx8_esdhc_init(struct fsl_esdhc_host *host,
+ struct esdhc_soc_data *data,
+ int instance)
{
switch (instance) {
case 0:
- esdhc->regs = IOMEM(MX8MQ_USDHC1_BASE_ADDR);
+ host->regs = IOMEM(MX8MQ_USDHC1_BASE_ADDR);
break;
case 1:
- esdhc->regs = IOMEM(MX8MQ_USDHC2_BASE_ADDR);
+ host->regs = IOMEM(MX8MQ_USDHC2_BASE_ADDR);
break;
default:
return -EINVAL;
}
- imx_esdhc_init(esdhc);
+ imx_esdhc_init(host, data);
return 0;
}
@@ -395,28 +377,29 @@ static int imx8_esdhc_init(struct esdhc *esdhc, int instance)
*/
int imx6_esdhc_start_image(int instance)
{
- struct esdhc esdhc;
+ struct esdhc_soc_data data;
+ struct fsl_esdhc_host host;
switch (instance) {
case 0:
- esdhc.regs = IOMEM(MX6_USDHC1_BASE_ADDR);
+ host.regs = IOMEM(MX6_USDHC1_BASE_ADDR);
break;
case 1:
- esdhc.regs = IOMEM(MX6_USDHC2_BASE_ADDR);
+ host.regs = IOMEM(MX6_USDHC2_BASE_ADDR);
break;
case 2:
- esdhc.regs = IOMEM(MX6_USDHC3_BASE_ADDR);
+ host.regs = IOMEM(MX6_USDHC3_BASE_ADDR);
break;
case 3:
- esdhc.regs = IOMEM(MX6_USDHC4_BASE_ADDR);
+ host.regs = IOMEM(MX6_USDHC4_BASE_ADDR);
break;
default:
return -EINVAL;
}
- imx_esdhc_init(&esdhc);
+ imx_esdhc_init(&host, &data);
- return esdhc_start_image(&esdhc, 0x10000000, 0x10000000, 0);
+ return esdhc_start_image(&host, 0x10000000, 0x10000000, 0);
}
/**
@@ -433,14 +416,15 @@ int imx6_esdhc_start_image(int instance)
*/
int imx8_esdhc_start_image(int instance)
{
- struct esdhc esdhc;
+ struct esdhc_soc_data data;
+ struct fsl_esdhc_host host;
int ret;
- ret = imx8_esdhc_init(&esdhc, instance);
+ ret = imx8_esdhc_init(&host, &data, instance);
if (ret)
return ret;
- return esdhc_start_image(&esdhc, MX8MQ_DDR_CSD1_BASE_ADDR,
+ return esdhc_start_image(&host, MX8MQ_DDR_CSD1_BASE_ADDR,
MX8MQ_ATF_BL33_BASE_ADDR, SZ_32K);
}
@@ -448,11 +432,12 @@ int imx8_esdhc_load_piggy(int instance)
{
void *buf, *piggy;
struct imx_flash_header_v2 *hdr = NULL;
- struct esdhc esdhc;
+ struct esdhc_soc_data data;
+ struct fsl_esdhc_host host;
int ret, len;
int offset = SZ_32K;
- ret = imx8_esdhc_init(&esdhc, instance);
+ ret = imx8_esdhc_init(&host, &data, instance);
if (ret)
return ret;
@@ -463,14 +448,14 @@ int imx8_esdhc_load_piggy(int instance)
*/
buf = (void *)MX8MQ_ATF_BL33_BASE_ADDR + SZ_32M;
- ret = esdhc_search_header(&esdhc, &hdr, buf, &offset);
+ ret = esdhc_search_header(&host, &hdr, buf, &offset);
if (ret)
return ret;
len = offset + hdr->boot_data.size + piggydata_size();
len = ALIGN(len, SECTOR_SIZE);
- ret = esdhc_read_blocks(&esdhc, buf, len);
+ ret = esdhc_read_blocks(&host, buf, len);
/*
* Calculate location of the piggydata at the offset loaded into RAM
@@ -508,29 +493,33 @@ int ls1046a_esdhc_start_image(unsigned long r0, unsigned long r1, unsigned long
{
int ret;
uint32_t val;
- struct esdhc esdhc = {
+ struct esdhc_soc_data data = {
+ .flags = ESDHC_FLAG_BIGENDIAN,
+ };
+ struct fsl_esdhc_host host = {
.regs = IOMEM(0x01560000),
- .is_be = true,
+ .socdata = &data,
};
unsigned long sdram = 0x80000000;
void (*barebox)(unsigned long, unsigned long, unsigned long) =
(void *)(sdram + LS1046A_SD_IMAGE_OFFSET);
- esdhc_write32(&esdhc, IMX_SDHCI_WML, 0);
+ esdhc_populate_sdhci(&host);
+ sdhci_write32(&host.sdhci, IMX_SDHCI_WML, 0);
/*
* The ROM leaves us here with a clock frequency of around 400kHz. Speed
* this up a bit. FIXME: The resulting frequency has not yet been verified
* to work on all cards.
*/
- val = esdhc_read32(&esdhc, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET);
+ val = sdhci_read32(&host.sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET);
val &= ~0x0000fff0;
val |= (8 << 8) | (3 << 4);
- esdhc_write32(&esdhc, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, val);
+ sdhci_write32(&host.sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, val);
- esdhc_write32(&esdhc, ESDHC_DMA_SYSCTL, ESDHC_SYSCTL_DMA_SNOOP);
+ sdhci_write32(&host.sdhci, ESDHC_DMA_SYSCTL, ESDHC_SYSCTL_DMA_SNOOP);
- ret = esdhc_read_blocks(&esdhc, (void *)sdram,
+ ret = esdhc_read_blocks(&host, (void *)sdram,
ALIGN(barebox_image_size + LS1046A_SD_IMAGE_OFFSET, 512));
if (ret) {
pr_err("%s: reading blocks failed with: %d\n", __func__, ret);
diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c
index b6dd75d2c..9dbf5bccc 100644
--- a/drivers/mci/imx-esdhc.c
+++ b/drivers/mci/imx-esdhc.c
@@ -39,131 +39,13 @@
#include "sdhci.h"
#include "imx-esdhc.h"
-/*
- * The CMDTYPE of the CMD register (offset 0xE) should be set to
- * "11" when the STOP CMD12 is issued on imx53 to abort one
- * open ended multi-blk IO. Otherwise the TC INT wouldn't
- * be generated.
- * In exact block transfer, the controller doesn't complete the
- * operations automatically as required at the end of the
- * transfer and remains on hold if the abort command is not sent.
- * As a result, the TC flag is not asserted and SW received timeout
- * exeception. Bit1 of Vendor Spec registor is used to fix it.
- */
-#define ESDHC_FLAG_MULTIBLK_NO_INT BIT(1)
-/*
- * The flag enables the workaround for ESDHC errata ENGcm07207 which
- * affects i.MX25 and i.MX35.
- */
-#define ESDHC_FLAG_ENGCM07207 BIT(2)
-/*
- * The flag tells that the ESDHC controller is an USDHC block that is
- * integrated on the i.MX6 series.
- */
-#define ESDHC_FLAG_USDHC BIT(3)
-/* The IP supports manual tuning process */
-#define ESDHC_FLAG_MAN_TUNING BIT(4)
-/* The IP supports standard tuning process */
-#define ESDHC_FLAG_STD_TUNING BIT(5)
-/* The IP has SDHCI_CAPABILITIES_1 register */
-#define ESDHC_FLAG_HAVE_CAP1 BIT(6)
-
-/*
- * The IP has errata ERR004536
- * uSDHC: ADMA Length Mismatch Error occurs if the AHB read access is slow,
- * when reading data from the card
- */
-#define ESDHC_FLAG_ERR004536 BIT(7)
-/* The IP supports HS200 mode */
-#define ESDHC_FLAG_HS200 BIT(8)
-/* The IP supports HS400 mode */
-#define ESDHC_FLAG_HS400 BIT(9)
-
-/* Need to access registers in bigendian mode */
-#define ESDHC_FLAG_BIGENDIAN BIT(10)
-/* Enable cache snooping */
-#define ESDHC_FLAG_CACHE_SNOOPING BIT(11)
#define PRSSTAT_DAT0 0x01000000
#define PRSSTAT_SDSTB 0x00000008
-struct esdhc_soc_data {
- u32 flags;
- const char *clkidx;
-};
-
-struct fsl_esdhc_host {
- struct mci_host mci;
- void __iomem *regs;
- struct device_d *dev;
- struct clk *clk;
- const struct esdhc_soc_data *socdata;
- struct sdhci sdhci;
-};
#define to_fsl_esdhc(mci) container_of(mci, struct fsl_esdhc_host, mci)
-static inline int esdhc_is_usdhc(struct fsl_esdhc_host *data)
-{
- return !!(data->socdata->flags & ESDHC_FLAG_USDHC);
-}
-
-static inline struct fsl_esdhc_host *sdhci_to_esdhc(struct sdhci *sdhci)
-{
- return container_of(sdhci, struct fsl_esdhc_host, sdhci);
-}
-
-static u32 esdhc_op_read32_le(struct sdhci *sdhci, int reg)
-{
- struct fsl_esdhc_host *host = sdhci_to_esdhc(sdhci);
-
- return readl(host->regs + reg);
-}
-
-static u32 esdhc_op_read32_be(struct sdhci *sdhci, int reg)
-{
- struct fsl_esdhc_host *host = sdhci_to_esdhc(sdhci);
-
- return in_be32(host->regs + reg);
-}
-
-static void esdhc_op_write32_le(struct sdhci *sdhci, int reg, u32 val)
-{
- struct fsl_esdhc_host *host = sdhci_to_esdhc(sdhci);
-
- writel(val, host->regs + reg);
-}
-
-static void esdhc_op_write32_be(struct sdhci *sdhci, int reg, u32 val)
-{
- struct fsl_esdhc_host *host = sdhci_to_esdhc(sdhci);
-
- out_be32(host->regs + reg, val);
-}
-
-static inline void esdhc_clrsetbits32(struct fsl_esdhc_host *host, unsigned int reg,
- u32 clear, u32 set)
-{
- u32 val;
-
- val = sdhci_read32(&host->sdhci, reg);
- val &= ~clear;
- val |= set;
- sdhci_write32(&host->sdhci, reg, val);
-}
-
-static inline void esdhc_clrbits32(struct fsl_esdhc_host *host, unsigned int reg,
- u32 clear)
-{
- esdhc_clrsetbits32(host, reg, clear, 0);
-}
-
-static inline void esdhc_setbits32(struct fsl_esdhc_host *host, unsigned int reg,
- u32 set)
-{
- esdhc_clrsetbits32(host, reg, 0, set);
-}
-
static int esdhc_setup_data(struct fsl_esdhc_host *host, struct mci_data *data,
dma_addr_t dma)
{
@@ -578,13 +460,7 @@ static int fsl_esdhc_probe(struct device_d *dev)
}
host->regs = IOMEM(iores->start);
- if (host->socdata->flags & ESDHC_FLAG_BIGENDIAN) {
- 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;
- }
+ esdhc_populate_sdhci(host);
caps = sdhci_read32(&host->sdhci, SDHCI_CAPABILITIES);
diff --git a/drivers/mci/imx-esdhc.h b/drivers/mci/imx-esdhc.h
index ad05c4c0b..e5647187b 100644
--- a/drivers/mci/imx-esdhc.h
+++ b/drivers/mci/imx-esdhc.h
@@ -69,4 +69,102 @@
#define ESDHC_DMA_SYSCTL 0x40c /* Layerscape specific */
#define ESDHC_SYSCTL_DMA_SNOOP BIT(6)
+
+/*
+ * The CMDTYPE of the CMD register (offset 0xE) should be set to
+ * "11" when the STOP CMD12 is issued on imx53 to abort one
+ * open ended multi-blk IO. Otherwise the TC INT wouldn't
+ * be generated.
+ * In exact block transfer, the controller doesn't complete the
+ * operations automatically as required at the end of the
+ * transfer and remains on hold if the abort command is not sent.
+ * As a result, the TC flag is not asserted and SW received timeout
+ * exeception. Bit1 of Vendor Spec registor is used to fix it.
+ */
+#define ESDHC_FLAG_MULTIBLK_NO_INT BIT(1)
+/*
+ * The flag enables the workaround for ESDHC errata ENGcm07207 which
+ * affects i.MX25 and i.MX35.
+ */
+#define ESDHC_FLAG_ENGCM07207 BIT(2)
+/*
+ * The flag tells that the ESDHC controller is an USDHC block that is
+ * integrated on the i.MX6 series.
+ */
+#define ESDHC_FLAG_USDHC BIT(3)
+/* The IP supports manual tuning process */
+#define ESDHC_FLAG_MAN_TUNING BIT(4)
+/* The IP supports standard tuning process */
+#define ESDHC_FLAG_STD_TUNING BIT(5)
+/* The IP has SDHCI_CAPABILITIES_1 register */
+#define ESDHC_FLAG_HAVE_CAP1 BIT(6)
+
+/*
+ * The IP has errata ERR004536
+ * uSDHC: ADMA Length Mismatch Error occurs if the AHB read access is slow,
+ * when reading data from the card
+ */
+#define ESDHC_FLAG_ERR004536 BIT(7)
+/* The IP supports HS200 mode */
+#define ESDHC_FLAG_HS200 BIT(8)
+/* The IP supports HS400 mode */
+#define ESDHC_FLAG_HS400 BIT(9)
+/* Need to access registers in bigendian mode */
+#define ESDHC_FLAG_BIGENDIAN BIT(10)
+/* Enable cache snooping */
+#define ESDHC_FLAG_CACHE_SNOOPING BIT(11)
+
+struct esdhc_soc_data {
+ u32 flags;
+ const char *clkidx;
+};
+
+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;
+};
+
+
+static inline int esdhc_is_usdhc(struct fsl_esdhc_host *data)
+{
+ return !!(data->socdata->flags & ESDHC_FLAG_USDHC);
+}
+
+static inline struct fsl_esdhc_host *sdhci_to_esdhc(struct sdhci *sdhci)
+{
+ return container_of(sdhci, struct fsl_esdhc_host, sdhci);
+}
+
+static inline void
+esdhc_clrsetbits32(struct fsl_esdhc_host *host, unsigned int reg,
+ u32 clear, u32 set)
+{
+ u32 val;
+
+ val = sdhci_read32(&host->sdhci, reg);
+ val &= ~clear;
+ val |= set;
+ sdhci_write32(&host->sdhci, reg, val);
+}
+
+static inline void
+esdhc_clrbits32(struct fsl_esdhc_host *host, unsigned int reg,
+ u32 clear)
+{
+ esdhc_clrsetbits32(host, reg, clear, 0);
+}
+
+static inline void
+esdhc_setbits32(struct fsl_esdhc_host *host, unsigned int reg,
+ u32 set)
+{
+ esdhc_clrsetbits32(host, reg, 0, set);
+}
+
+void esdhc_populate_sdhci(struct fsl_esdhc_host *host);
+
#endif /* __FSL_ESDHC_H__ */
--
2.21.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 08/12] mci: imx-esdhc-pbl: Use sdhci_transfer_data()
2019-12-02 15:19 [PATCH 00/12] Share i.MX ESDHC PBL and PIO code Andrey Smirnov
` (6 preceding siblings ...)
2019-12-02 15:19 ` [PATCH 07/12] mci: imx-esdhc-pbl: Share IO accessors with regular driver Andrey Smirnov
@ 2019-12-02 15:19 ` Andrey Smirnov
2019-12-02 15:19 ` [PATCH 09/12] mci: imx-esdhc-pbl: Use sdhci_set_cmd_xfer_mode() Andrey Smirnov
` (4 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Andrey Smirnov @ 2019-12-02 15:19 UTC (permalink / raw)
To: barebox; +Cc: Andrey Smirnov
Drop some extra code by converting esdhc_do_data() to use
sdhci_transfer_data().
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
drivers/mci/Kconfig | 1 +
drivers/mci/Makefile | 2 +-
drivers/mci/imx-esdhc-pbl.c | 35 +----------------------------------
drivers/mci/sdhci.c | 13 +++++++++++++
4 files changed, 16 insertions(+), 35 deletions(-)
diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig
index c269b71e8..13fa58504 100644
--- a/drivers/mci/Kconfig
+++ b/drivers/mci/Kconfig
@@ -105,6 +105,7 @@ config MCI_IMX_ESDHC_PIO
config MCI_IMX_ESDHC_PBL
bool
+ select MCI_SDHCI
config MCI_OMAP_HSMMC
bool "OMAP HSMMC"
diff --git a/drivers/mci/Makefile b/drivers/mci/Makefile
index cfb84a899..54eb65978 100644
--- a/drivers/mci/Makefile
+++ b/drivers/mci/Makefile
@@ -16,4 +16,4 @@ obj-$(CONFIG_MCI_SPI) += mci_spi.o
obj-$(CONFIG_MCI_DW) += dw_mmc.o
obj-$(CONFIG_MCI_MMCI) += mmci.o
obj-$(CONFIG_MCI_STM32_SDMMC2) += stm32_sdmmc2.o
-obj-$(CONFIG_MCI_SDHCI) += sdhci.o
+obj-pbl-$(CONFIG_MCI_SDHCI) += sdhci.o
diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c
index 08f28471c..b61cba2ba 100644
--- a/drivers/mci/imx-esdhc-pbl.c
+++ b/drivers/mci/imx-esdhc-pbl.c
@@ -66,40 +66,7 @@ static u32 esdhc_xfertyp(struct mci_cmd *cmd, struct mci_data *data)
static int esdhc_do_data(struct fsl_esdhc_host *host, struct mci_data *data)
{
- char *buffer;
- u32 databuf;
- u32 size;
- u32 irqstat;
- u32 present;
-
- buffer = data->dest;
-
- size = data->blocksize * data->blocks;
- irqstat = sdhci_read32(&host->sdhci, SDHCI_INT_STATUS);
-
- while (size) {
- int i;
- int timeout = 1000000;
-
- while (1) {
- present = sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & SDHCI_BUFFER_READ_ENABLE;
- if (present)
- break;
- if (!--timeout) {
- pr_err("read time out\n");
- return -ETIMEDOUT;
- }
- }
-
- for (i = 0; i < SECTOR_WML; i++) {
- databuf = sdhci_read32(&host->sdhci, SDHCI_BUFFER);
- *((u32 *)buffer) = databuf;
- buffer += 4;
- size -= 4;
- }
- }
-
- return 0;
+ return sdhci_transfer_data(&host->sdhci, data);
}
static int
diff --git a/drivers/mci/sdhci.c b/drivers/mci/sdhci.c
index 1ab1c0f23..172c8343a 100644
--- a/drivers/mci/sdhci.c
+++ b/drivers/mci/sdhci.c
@@ -88,6 +88,19 @@ static void sdhci_tx_pio(struct sdhci *sdhci, struct mci_data *data,
sdhci_write32(sdhci, SDHCI_BUFFER, buf[i]);
}
+#ifdef __PBL__
+/*
+ * Stubs to make timeout logic below work in PBL
+ */
+
+#define get_time_ns() 0
+/*
+ * Use time in us as a busy counter timeout value
+ */
+#define is_timeout(s, t) ((s)++ > ((t) / 1000))
+
+#endif
+
int sdhci_transfer_data(struct sdhci *sdhci, struct mci_data *data)
{
unsigned int block = 0;
--
2.21.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 09/12] mci: imx-esdhc-pbl: Use sdhci_set_cmd_xfer_mode()
2019-12-02 15:19 [PATCH 00/12] Share i.MX ESDHC PBL and PIO code Andrey Smirnov
` (7 preceding siblings ...)
2019-12-02 15:19 ` [PATCH 08/12] mci: imx-esdhc-pbl: Use sdhci_transfer_data() Andrey Smirnov
@ 2019-12-02 15:19 ` Andrey Smirnov
2019-12-02 15:19 ` [PATCH 10/12] mci: imx-esdhc: Share code for esdhc_(setup|do)_data operations Andrey Smirnov
` (3 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Andrey Smirnov @ 2019-12-02 15:19 UTC (permalink / raw)
To: barebox; +Cc: Andrey Smirnov
Drop extra code by converting imx-esdhc-pbl.c to use
sdhci_set_cmd_xfer_mode().
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
drivers/mci/imx-esdhc-pbl.c | 41 +++++++++----------------------------
1 file changed, 10 insertions(+), 31 deletions(-)
diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c
index b61cba2ba..43e0093cd 100644
--- a/drivers/mci/imx-esdhc-pbl.c
+++ b/drivers/mci/imx-esdhc-pbl.c
@@ -37,33 +37,6 @@ static void __udelay(int us)
for (i = 0; i < us * 4; i++);
}
-static u32 esdhc_xfertyp(struct mci_cmd *cmd, struct mci_data *data)
-{
- u32 xfertyp = 0;
- u32 command = 0;
-
- if (data) {
- command |= SDHCI_DATA_PRESENT;
- xfertyp |= SDHCI_MULTIPLE_BLOCKS | SDHCI_BLOCK_COUNT_EN |
- SDHCI_DATA_TO_HOST;
- }
-
- if (cmd->resp_type & MMC_RSP_CRC)
- command |= SDHCI_CMD_CRC_CHECK_EN;
- if (cmd->resp_type & MMC_RSP_OPCODE)
- xfertyp |= SDHCI_CMD_INDEX_CHECK_EN;
- if (cmd->resp_type & MMC_RSP_136)
- command |= SDHCI_RESP_TYPE_136;
- else if (cmd->resp_type & MMC_RSP_BUSY)
- command |= SDHCI_RESP_TYPE_48_BUSY;
- else if (cmd->resp_type & MMC_RSP_PRESENT)
- command |= SDHCI_RESP_TYPE_48;
-
- command |= SDHCI_CMD_INDEX(cmd->cmdidx);
-
- return command << 16 | xfertyp;
-}
-
static int esdhc_do_data(struct fsl_esdhc_host *host, struct mci_data *data)
{
return sdhci_transfer_data(&host->sdhci, data);
@@ -72,7 +45,7 @@ static int esdhc_do_data(struct fsl_esdhc_host *host, struct mci_data *data)
static int
esdhc_send_cmd(struct fsl_esdhc_host *host, struct mci_cmd *cmd, struct mci_data *data)
{
- u32 xfertyp, mixctrl;
+ u32 xfertyp, mixctrl, command;
u32 irqstat;
int ret;
int timeout;
@@ -87,8 +60,12 @@ esdhc_send_cmd(struct fsl_esdhc_host *host, struct mci_cmd *cmd, struct mci_data
sdhci_write32(&host->sdhci, SDHCI_BLOCK_SIZE__BLOCK_COUNT, data->blocks << 16 | SECTOR_SIZE);
}
- /* Figure out the transfer arguments */
- xfertyp = esdhc_xfertyp(cmd, data);
+ sdhci_set_cmd_xfer_mode(&host->sdhci, cmd, data,
+ false, &command, &xfertyp);
+
+ if ((host->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT) &&
+ (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION))
+ command |= SDHCI_COMMAND_CMDTYP_ABORT;
/* Send the command */
sdhci_write32(&host->sdhci, SDHCI_ARGUMENT, cmd->cmdarg);
@@ -101,7 +78,9 @@ esdhc_send_cmd(struct fsl_esdhc_host *host, struct mci_cmd *cmd, struct mci_data
sdhci_write32(&host->sdhci, IMX_SDHCI_MIXCTRL, mixctrl);
}
- sdhci_write32(&host->sdhci, SDHCI_TRANSFER_MODE__COMMAND, xfertyp);
+
+ sdhci_write32(&host->sdhci, SDHCI_TRANSFER_MODE__COMMAND,
+ command << 16 | xfertyp);
/* Wait for the command to complete */
timeout = 10000;
--
2.21.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 10/12] mci: imx-esdhc: Share code for esdhc_(setup|do)_data operations
2019-12-02 15:19 [PATCH 00/12] Share i.MX ESDHC PBL and PIO code Andrey Smirnov
` (8 preceding siblings ...)
2019-12-02 15:19 ` [PATCH 09/12] mci: imx-esdhc-pbl: Use sdhci_set_cmd_xfer_mode() Andrey Smirnov
@ 2019-12-02 15:19 ` Andrey Smirnov
2019-12-02 15:19 ` [PATCH 11/12] mci: imx-esdhc: Introduce esdhc_poll() Andrey Smirnov
` (2 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Andrey Smirnov @ 2019-12-02 15:19 UTC (permalink / raw)
To: barebox; +Cc: Andrey Smirnov
PBL and PIO case of the regular driver do exaclty the same thing
during esdhc_(setup|do)_data stages of esdhc_send_cmd(). Move the code
to a common file and adjust all of the users accordingly.
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
drivers/mci/imx-esdhc-common.c | 75 +++++++++++++++++++++++++++++++++
drivers/mci/imx-esdhc-pbl.c | 12 +++---
drivers/mci/imx-esdhc.c | 77 ++--------------------------------
drivers/mci/imx-esdhc.h | 12 ++++++
4 files changed, 95 insertions(+), 81 deletions(-)
diff --git a/drivers/mci/imx-esdhc-common.c b/drivers/mci/imx-esdhc-common.c
index bcdf661ed..55a337557 100644
--- a/drivers/mci/imx-esdhc-common.c
+++ b/drivers/mci/imx-esdhc-common.c
@@ -3,6 +3,7 @@
#include <common.h>
#include <io.h>
#include <mci.h>
+#include <pbl.h>
#include "sdhci.h"
#include "imx-esdhc.h"
@@ -45,3 +46,77 @@ void esdhc_populate_sdhci(struct fsl_esdhc_host *host)
host->sdhci.write32 = esdhc_op_write32_le;
}
}
+
+static bool esdhc_use_pio_mode(void)
+{
+ return IN_PBL || IS_ENABLED(CONFIG_MCI_IMX_ESDHC_PIO);
+}
+
+int esdhc_setup_data(struct fsl_esdhc_host *host, struct mci_data *data,
+ struct fsl_esdhc_dma_transfer *tr)
+{
+ u32 wml_value;
+ void *ptr;
+
+ if (!esdhc_use_pio_mode()) {
+ wml_value = data->blocksize/4;
+
+ if (data->flags & MMC_DATA_READ) {
+ if (wml_value > 0x10)
+ wml_value = 0x10;
+
+ esdhc_clrsetbits32(host, IMX_SDHCI_WML, WML_RD_WML_MASK, wml_value);
+ } else {
+ if (wml_value > 0x80)
+ wml_value = 0x80;
+
+ esdhc_clrsetbits32(host, IMX_SDHCI_WML, WML_WR_WML_MASK,
+ wml_value << 16);
+ }
+
+ tr->size = data->blocks * data->blocksize;
+
+ if (data->flags & MMC_DATA_WRITE) {
+ ptr = (void *)data->src;
+ tr->dir = DMA_TO_DEVICE;
+ } else {
+ ptr = data->dest;
+ tr->dir = DMA_FROM_DEVICE;
+ }
+
+ tr->dma = dma_map_single(host->dev, ptr, tr->size, tr->dir);
+ if (dma_mapping_error(host->dev, tr->dma))
+ return -EFAULT;
+
+
+ sdhci_write32(&host->sdhci, SDHCI_DMA_ADDRESS, tr->dma);
+ }
+
+ sdhci_write32(&host->sdhci, SDHCI_BLOCK_SIZE__BLOCK_COUNT, data->blocks << 16 | data->blocksize);
+
+ return 0;
+}
+
+int esdhc_do_data(struct fsl_esdhc_host *host, struct mci_data *data,
+ struct fsl_esdhc_dma_transfer *tr)
+{
+ u32 irqstat;
+
+ if (esdhc_use_pio_mode())
+ return sdhci_transfer_data(&host->sdhci, data);
+
+ do {
+ irqstat = sdhci_read32(&host->sdhci, SDHCI_INT_STATUS);
+
+ if (irqstat & DATA_ERR)
+ return -EIO;
+
+ if (irqstat & SDHCI_INT_DATA_TIMEOUT)
+ return -ETIMEDOUT;
+ } while (!(irqstat & SDHCI_INT_XFER_COMPLETE) &&
+ (sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & SDHCI_DATA_LINE_ACTIVE));
+
+ dma_unmap_single(host->dev, tr->dma, tr->size, tr->dir);
+
+ return 0;
+}
diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c
index 43e0093cd..21aa758f9 100644
--- a/drivers/mci/imx-esdhc-pbl.c
+++ b/drivers/mci/imx-esdhc-pbl.c
@@ -37,14 +37,10 @@ static void __udelay(int us)
for (i = 0; i < us * 4; i++);
}
-static int esdhc_do_data(struct fsl_esdhc_host *host, struct mci_data *data)
-{
- return sdhci_transfer_data(&host->sdhci, data);
-}
-
static int
esdhc_send_cmd(struct fsl_esdhc_host *host, struct mci_cmd *cmd, struct mci_data *data)
{
+ struct fsl_esdhc_dma_transfer tr = { 0 };
u32 xfertyp, mixctrl, command;
u32 irqstat;
int ret;
@@ -57,7 +53,9 @@ esdhc_send_cmd(struct fsl_esdhc_host *host, struct mci_cmd *cmd, struct mci_data
if (data) {
/* Set up for a data transfer if we have one */
- sdhci_write32(&host->sdhci, SDHCI_BLOCK_SIZE__BLOCK_COUNT, data->blocks << 16 | SECTOR_SIZE);
+ ret = esdhc_setup_data(host, data, &tr);
+ if (ret)
+ return ret;
}
sdhci_set_cmd_xfer_mode(&host->sdhci, cmd, data,
@@ -104,7 +102,7 @@ esdhc_send_cmd(struct fsl_esdhc_host *host, struct mci_cmd *cmd, struct mci_data
/* Wait until all of the blocks are transferred */
if (data) {
- ret = esdhc_do_data(host, data);
+ ret = esdhc_do_data(host, data, &tr);
if (ret)
return ret;
}
diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c
index 9dbf5bccc..8e6f66ce4 100644
--- a/drivers/mci/imx-esdhc.c
+++ b/drivers/mci/imx-esdhc.c
@@ -46,55 +46,6 @@
#define to_fsl_esdhc(mci) container_of(mci, struct fsl_esdhc_host, mci)
-static int esdhc_setup_data(struct fsl_esdhc_host *host, struct mci_data *data,
- dma_addr_t dma)
-{
- u32 wml_value;
-
- if (!IS_ENABLED(CONFIG_MCI_IMX_ESDHC_PIO)) {
- wml_value = data->blocksize/4;
-
- if (data->flags & MMC_DATA_READ) {
- if (wml_value > 0x10)
- wml_value = 0x10;
-
- esdhc_clrsetbits32(host, IMX_SDHCI_WML, WML_RD_WML_MASK, wml_value);
- } else {
- if (wml_value > 0x80)
- wml_value = 0x80;
-
- esdhc_clrsetbits32(host, IMX_SDHCI_WML, WML_WR_WML_MASK,
- wml_value << 16);
- }
- sdhci_write32(&host->sdhci, SDHCI_DMA_ADDRESS, dma);
- }
-
- sdhci_write32(&host->sdhci, SDHCI_BLOCK_SIZE__BLOCK_COUNT, data->blocks << 16 | data->blocksize);
-
- return 0;
-}
-
-static int esdhc_do_data(struct fsl_esdhc_host *host, struct mci_data *data)
-{
- u32 irqstat;
-
- if (IS_ENABLED(CONFIG_MCI_IMX_ESDHC_PIO))
- return sdhci_transfer_data(&host->sdhci, data);
-
- do {
- irqstat = sdhci_read32(&host->sdhci, SDHCI_INT_STATUS);
-
- if (irqstat & DATA_ERR)
- return -EIO;
-
- if (irqstat & SDHCI_INT_DATA_TIMEOUT)
- return -ETIMEDOUT;
- } while (!(irqstat & SDHCI_INT_XFER_COMPLETE) &&
- (sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & SDHCI_DATA_LINE_ACTIVE));
-
- return 0;
-}
-
/*
* Sends a command out on the bus. Takes the mci pointer,
* a command pointer, and an optional data pointer.
@@ -105,11 +56,8 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
u32 xfertyp, mixctrl, command;
u32 irqstat;
struct fsl_esdhc_host *host = to_fsl_esdhc(mci);
- unsigned int num_bytes = 0;
+ struct fsl_esdhc_dma_transfer tr = { 0 };
int ret;
- void *ptr;
- enum dma_data_direction dir = 0;
- dma_addr_t dma = 0;
sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, -1);
@@ -118,23 +66,7 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
/* Set up for a data transfer if we have one */
if (data) {
- if (!IS_ENABLED(CONFIG_MCI_IMX_ESDHC_PIO)) {
- num_bytes = data->blocks * data->blocksize;
-
- if (data->flags & MMC_DATA_WRITE) {
- ptr = (void *)data->src;
- dir = DMA_TO_DEVICE;
- } else {
- ptr = data->dest;
- dir = DMA_FROM_DEVICE;
- }
-
- dma = dma_map_single(host->dev, ptr, num_bytes, dir);
- if (dma_mapping_error(host->dev, dma))
- return -EFAULT;
- }
-
- ret = esdhc_setup_data(host, data, dma);
+ ret = esdhc_setup_data(host, data, &tr);
if (ret)
return ret;
}
@@ -197,12 +129,9 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
/* Wait until all of the blocks are transferred */
if (data) {
- ret = esdhc_do_data(host, data);
+ ret = esdhc_do_data(host, data, &tr);
if (ret)
return ret;
-
- if (!IS_ENABLED(CONFIG_MCI_IMX_ESDHC_PIO))
- dma_unmap_single(host->dev, dma, num_bytes, dir);
}
sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, -1);
diff --git a/drivers/mci/imx-esdhc.h b/drivers/mci/imx-esdhc.h
index e5647187b..8ab6b0bb8 100644
--- a/drivers/mci/imx-esdhc.h
+++ b/drivers/mci/imx-esdhc.h
@@ -22,6 +22,7 @@
#ifndef __FSL_ESDHC_H__
#define __FSL_ESDHC_H__
+#include <dma.h>
#include <errno.h>
#include <asm/byteorder.h>
#include <linux/bitfield.h>
@@ -128,6 +129,12 @@ struct fsl_esdhc_host {
struct sdhci sdhci;
};
+struct fsl_esdhc_dma_transfer {
+ dma_addr_t dma;
+ unsigned int size;
+ enum dma_data_direction dir;
+};
+
static inline int esdhc_is_usdhc(struct fsl_esdhc_host *data)
{
@@ -166,5 +173,10 @@ esdhc_setbits32(struct fsl_esdhc_host *host, unsigned int reg,
}
void esdhc_populate_sdhci(struct fsl_esdhc_host *host);
+int esdhc_setup_data(struct fsl_esdhc_host *host, struct mci_data *data,
+ struct fsl_esdhc_dma_transfer *tr);
+int esdhc_do_data(struct fsl_esdhc_host *host, struct mci_data *data,
+ struct fsl_esdhc_dma_transfer *tr);
+
#endif /* __FSL_ESDHC_H__ */
--
2.21.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 11/12] mci: imx-esdhc: Introduce esdhc_poll()
2019-12-02 15:19 [PATCH 00/12] Share i.MX ESDHC PBL and PIO code Andrey Smirnov
` (9 preceding siblings ...)
2019-12-02 15:19 ` [PATCH 10/12] mci: imx-esdhc: Share code for esdhc_(setup|do)_data operations Andrey Smirnov
@ 2019-12-02 15:19 ` Andrey Smirnov
2019-12-02 15:19 ` [PATCH 12/12] mci: imx-esdhc: Share code for esdhc_send_cmd() Andrey Smirnov
2019-12-04 8:42 ` [PATCH 00/12] Share i.MX ESDHC PBL and PIO code Sascha Hauer
12 siblings, 0 replies; 14+ messages in thread
From: Andrey Smirnov @ 2019-12-02 15:19 UTC (permalink / raw)
To: barebox; +Cc: Andrey Smirnov
Replace all of the explcitly coded timeout loops with a shared
subroutine that is used by both regular driver and PBL code.
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
drivers/mci/imx-esdhc-common.c | 30 ++++++++++++++++++++++
drivers/mci/imx-esdhc-pbl.c | 24 ++++++++---------
drivers/mci/imx-esdhc.c | 47 +++++++++++++++++-----------------
drivers/mci/imx-esdhc.h | 4 ++-
4 files changed, 66 insertions(+), 39 deletions(-)
diff --git a/drivers/mci/imx-esdhc-common.c b/drivers/mci/imx-esdhc-common.c
index 55a337557..5e1f28401 100644
--- a/drivers/mci/imx-esdhc-common.c
+++ b/drivers/mci/imx-esdhc-common.c
@@ -120,3 +120,33 @@ int esdhc_do_data(struct fsl_esdhc_host *host, struct mci_data *data,
return 0;
}
+
+static bool esdhc_match32(struct fsl_esdhc_host *host, unsigned int off,
+ unsigned int mask, unsigned int val)
+{
+ const unsigned int reg = sdhci_read32(&host->sdhci, off) & mask;
+
+ return reg == val;
+}
+
+#ifdef __PBL__
+/*
+ * Stubs to make timeout logic below work in PBL
+ */
+
+#define get_time_ns() 0
+/*
+ * Use time in us (approx) as a busy counter timeout value
+ */
+#define is_timeout(s, t) ((s)++ > ((t) / 1024))
+
+#endif
+
+int esdhc_poll(struct fsl_esdhc_host *host, unsigned int off,
+ unsigned int mask, unsigned int val,
+ uint64_t timeout)
+{
+ return wait_on_timeout(timeout,
+ esdhc_match32(host, off, mask, val));
+}
+
diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c
index 21aa758f9..d6c178651 100644
--- a/drivers/mci/imx-esdhc-pbl.c
+++ b/drivers/mci/imx-esdhc-pbl.c
@@ -44,7 +44,6 @@ esdhc_send_cmd(struct fsl_esdhc_host *host, struct mci_cmd *cmd, struct mci_data
u32 xfertyp, mixctrl, command;
u32 irqstat;
int ret;
- int timeout;
sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, -1);
@@ -81,12 +80,11 @@ esdhc_send_cmd(struct fsl_esdhc_host *host, struct mci_cmd *cmd, struct mci_data
command << 16 | xfertyp);
/* Wait for the command to complete */
- timeout = 10000;
- while (!(sdhci_read32(&host->sdhci, SDHCI_INT_STATUS) & SDHCI_INT_CMD_COMPLETE)) {
- __udelay(1);
- if (!timeout--)
- return -ETIMEDOUT;
- }
+ ret = esdhc_poll(host, SDHCI_INT_STATUS,
+ SDHCI_INT_CMD_COMPLETE, SDHCI_INT_CMD_COMPLETE,
+ 100 * MSECOND);
+ if (ret)
+ return ret;
irqstat = sdhci_read32(&host->sdhci, SDHCI_INT_STATUS);
sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, irqstat);
@@ -110,13 +108,11 @@ esdhc_send_cmd(struct fsl_esdhc_host *host, struct mci_cmd *cmd, struct mci_data
sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, -1);
/* Wait for the bus to be idle */
- timeout = 10000;
- while (sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & (SDHCI_CMD_INHIBIT_CMD |
- SDHCI_CMD_INHIBIT_DATA | SDHCI_DATA_LINE_ACTIVE)) {
- __udelay(1);
- if (!timeout--)
- return -ETIMEDOUT;
- }
+ ret = esdhc_poll(host, SDHCI_PRESENT_STATE,
+ SDHCI_CMD_INHIBIT_CMD |
+ SDHCI_CMD_INHIBIT_DATA |
+ SDHCI_DATA_LINE_ACTIVE, 0,
+ 100 * MSECOND);
return 0;
}
diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c
index 8e6f66ce4..7e24b2b02 100644
--- a/drivers/mci/imx-esdhc.c
+++ b/drivers/mci/imx-esdhc.c
@@ -94,8 +94,9 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
command << 16 | xfertyp);
/* Wait for the command to complete */
- ret = wait_on_timeout(100 * MSECOND,
- sdhci_read32(&host->sdhci, SDHCI_INT_STATUS) & SDHCI_INT_CMD_COMPLETE);
+ ret = esdhc_poll(host, SDHCI_INT_STATUS,
+ SDHCI_INT_CMD_COMPLETE, SDHCI_INT_CMD_COMPLETE,
+ 100 * MSECOND);
if (ret) {
dev_dbg(host->dev, "timeout 1\n");
return -ETIMEDOUT;
@@ -116,9 +117,9 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
* Poll on DATA0 line for cmd with busy signal for
* timout / 10 usec since DLA polling can be insecure.
*/
- ret = wait_on_timeout(2500 * MSECOND,
- (sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & PRSSTAT_DAT0));
-
+ ret = esdhc_poll(host, SDHCI_PRESENT_STATE,
+ PRSSTAT_DAT0, PRSSTAT_DAT0,
+ 2500 * MSECOND);
if (ret) {
dev_err(host->dev, "timeout PRSSTAT_DAT0\n");
return -ETIMEDOUT;
@@ -137,16 +138,17 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, -1);
/* Wait for the bus to be idle */
- ret = wait_on_timeout(SECOND,
- !(sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) &
- (SDHCI_CMD_INHIBIT_CMD | SDHCI_CMD_INHIBIT_DATA)));
+ ret = esdhc_poll(host, SDHCI_PRESENT_STATE,
+ SDHCI_CMD_INHIBIT_CMD | SDHCI_CMD_INHIBIT_DATA, 0,
+ SECOND);
if (ret) {
dev_err(host->dev, "timeout 2\n");
return -ETIMEDOUT;
}
- ret = wait_on_timeout(100 * MSECOND,
- !(sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & SDHCI_DATA_LINE_ACTIVE));
+ ret = esdhc_poll(host, SDHCI_PRESENT_STATE,
+ SDHCI_DATA_LINE_ACTIVE, 0,
+ 100 * MSECOND);
if (ret) {
dev_err(host->dev, "timeout 3\n");
return -ETIMEDOUT;
@@ -201,16 +203,18 @@ static void set_sysctl(struct mci_host *mci, u32 clock)
esdhc_clrsetbits32(host, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET,
SYSCTL_CLOCK_MASK, clk);
- wait_on_timeout(10 * MSECOND,
- sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & PRSSTAT_SDSTB);
+ esdhc_poll(host, SDHCI_PRESENT_STATE,
+ PRSSTAT_SDSTB, PRSSTAT_SDSTB,
+ 10 * MSECOND);
clk = SYSCTL_PEREN | SYSCTL_CKEN | SYSCTL_INITA;
esdhc_setbits32(host, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET,
clk);
- wait_on_timeout(1 * MSECOND,
- !(sdhci_read32(&host->sdhci, SDHCI_CLOCK_CONTROL) & SYSCTL_INITA));
+ esdhc_poll(host, SDHCI_CLOCK_CONTROL,
+ SYSCTL_INITA, SYSCTL_INITA,
+ 10 * MSECOND);
}
static void esdhc_set_ios(struct mci_host *mci, struct mci_ios *ios)
@@ -268,7 +272,6 @@ static int esdhc_card_present(struct mci_host *mci)
static int esdhc_reset(struct fsl_esdhc_host *host)
{
- uint64_t start;
int val;
/* reset the controller */
@@ -286,16 +289,12 @@ static int esdhc_reset(struct fsl_esdhc_host *host)
sdhci_write32(&host->sdhci, IMX_SDHCI_DLL_CTRL, 0x0);
}
- start = get_time_ns();
/* hardware clears the bit when it is done */
- while (1) {
- if (!(sdhci_read32(&host->sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET)
- & SYSCTL_RSTA))
- break;
- if (is_timeout(start, 100 * MSECOND)) {
- dev_err(host->dev, "Reset never completed.\n");
- return -EIO;
- }
+ if (esdhc_poll(host,
+ SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET,
+ SYSCTL_RSTA, 0, 100 * MSECOND)) {
+ dev_err(host->dev, "Reset never completed.\n");
+ return -EIO;
}
return 0;
diff --git a/drivers/mci/imx-esdhc.h b/drivers/mci/imx-esdhc.h
index 8ab6b0bb8..ac1208789 100644
--- a/drivers/mci/imx-esdhc.h
+++ b/drivers/mci/imx-esdhc.h
@@ -177,6 +177,8 @@ int esdhc_setup_data(struct fsl_esdhc_host *host, struct mci_data *data,
struct fsl_esdhc_dma_transfer *tr);
int esdhc_do_data(struct fsl_esdhc_host *host, struct mci_data *data,
struct fsl_esdhc_dma_transfer *tr);
-
+int esdhc_poll(struct fsl_esdhc_host *host, unsigned int off,
+ unsigned int mask, unsigned int val,
+ uint64_t timeout);
#endif /* __FSL_ESDHC_H__ */
--
2.21.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 12/12] mci: imx-esdhc: Share code for esdhc_send_cmd()
2019-12-02 15:19 [PATCH 00/12] Share i.MX ESDHC PBL and PIO code Andrey Smirnov
` (10 preceding siblings ...)
2019-12-02 15:19 ` [PATCH 11/12] mci: imx-esdhc: Introduce esdhc_poll() Andrey Smirnov
@ 2019-12-02 15:19 ` Andrey Smirnov
2019-12-04 8:42 ` [PATCH 00/12] Share i.MX ESDHC PBL and PIO code Sascha Hauer
12 siblings, 0 replies; 14+ messages in thread
From: Andrey Smirnov @ 2019-12-02 15:19 UTC (permalink / raw)
To: barebox; +Cc: Andrey Smirnov
Versions of esdhc_send_cmd() in imx-esdhc.c and imx-esdhc-pbl.c
implement almost the same algorithm. To avoid code repetition, move
that code to imx-esdhc-common.c and adjust all of the users
accordingly.
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
drivers/mci/imx-esdhc-common.c | 131 ++++++++++++++++++++++++++++++++-
drivers/mci/imx-esdhc-pbl.c | 87 +---------------------
drivers/mci/imx-esdhc.c | 102 +------------------------
drivers/mci/imx-esdhc.h | 13 +---
4 files changed, 131 insertions(+), 202 deletions(-)
diff --git a/drivers/mci/imx-esdhc-common.c b/drivers/mci/imx-esdhc-common.c
index 5e1f28401..d0bef9470 100644
--- a/drivers/mci/imx-esdhc-common.c
+++ b/drivers/mci/imx-esdhc-common.c
@@ -8,6 +8,14 @@
#include "sdhci.h"
#include "imx-esdhc.h"
+#define PRSSTAT_DAT0 0x01000000
+
+struct fsl_esdhc_dma_transfer {
+ dma_addr_t dma;
+ unsigned int size;
+ enum dma_data_direction dir;
+};
+
static u32 esdhc_op_read32_le(struct sdhci *sdhci, int reg)
{
struct fsl_esdhc_host *host = sdhci_to_esdhc(sdhci);
@@ -51,9 +59,8 @@ static bool esdhc_use_pio_mode(void)
{
return IN_PBL || IS_ENABLED(CONFIG_MCI_IMX_ESDHC_PIO);
}
-
-int esdhc_setup_data(struct fsl_esdhc_host *host, struct mci_data *data,
- struct fsl_esdhc_dma_transfer *tr)
+static int esdhc_setup_data(struct fsl_esdhc_host *host, struct mci_data *data,
+ struct fsl_esdhc_dma_transfer *tr)
{
u32 wml_value;
void *ptr;
@@ -97,7 +104,7 @@ int esdhc_setup_data(struct fsl_esdhc_host *host, struct mci_data *data,
return 0;
}
-int esdhc_do_data(struct fsl_esdhc_host *host, struct mci_data *data,
+static int esdhc_do_data(struct fsl_esdhc_host *host, struct mci_data *data,
struct fsl_esdhc_dma_transfer *tr)
{
u32 irqstat;
@@ -140,6 +147,17 @@ static bool esdhc_match32(struct fsl_esdhc_host *host, unsigned int off,
*/
#define is_timeout(s, t) ((s)++ > ((t) / 1024))
+static void __udelay(int us)
+{
+ volatile int i;
+
+ for (i = 0; i < us * 4; i++);
+}
+
+#define udelay(n) __udelay(n)
+#undef dev_err
+#define dev_err(d, ...) pr_err(__VA_ARGS__)
+
#endif
int esdhc_poll(struct fsl_esdhc_host *host, unsigned int off,
@@ -150,3 +168,108 @@ int esdhc_poll(struct fsl_esdhc_host *host, unsigned int off,
esdhc_match32(host, off, mask, val));
}
+int __esdhc_send_cmd(struct fsl_esdhc_host *host, struct mci_cmd *cmd,
+ struct mci_data *data)
+{
+ u32 xfertyp, mixctrl, command;
+ u32 irqstat;
+ struct fsl_esdhc_dma_transfer tr = { 0 };
+ int ret;
+
+ sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, -1);
+
+ /* Wait at least 8 SD clock cycles before the next command */
+ udelay(1);
+
+ /* Set up for a data transfer if we have one */
+ if (data) {
+ ret = esdhc_setup_data(host, data, &tr);
+ if (ret)
+ return ret;
+ }
+
+ sdhci_set_cmd_xfer_mode(&host->sdhci, cmd, data,
+ !esdhc_use_pio_mode(), &command, &xfertyp);
+
+ if ((host->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT) &&
+ (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION))
+ command |= SDHCI_COMMAND_CMDTYP_ABORT;
+
+ /* Send the command */
+ sdhci_write32(&host->sdhci, SDHCI_ARGUMENT, cmd->cmdarg);
+
+ if (esdhc_is_usdhc(host)) {
+ /* write lower-half of xfertyp to mixctrl */
+ mixctrl = xfertyp;
+ /* Keep the bits 22-25 of the register as is */
+ mixctrl |= (sdhci_read32(&host->sdhci, IMX_SDHCI_MIXCTRL) & (0xF << 22));
+ sdhci_write32(&host->sdhci, IMX_SDHCI_MIXCTRL, mixctrl);
+ }
+
+ sdhci_write32(&host->sdhci, SDHCI_TRANSFER_MODE__COMMAND,
+ command << 16 | xfertyp);
+
+ /* Wait for the command to complete */
+ ret = esdhc_poll(host, SDHCI_INT_STATUS,
+ SDHCI_INT_CMD_COMPLETE, SDHCI_INT_CMD_COMPLETE,
+ 100 * MSECOND);
+ if (ret) {
+ dev_err(host->dev, "timeout 1\n");
+ return -ETIMEDOUT;
+ }
+
+ irqstat = sdhci_read32(&host->sdhci, SDHCI_INT_STATUS);
+ sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, irqstat);
+
+ if (irqstat & CMD_ERR)
+ return -EIO;
+
+ if (irqstat & SDHCI_INT_TIMEOUT)
+ return -ETIMEDOUT;
+
+ /* Workaround for ESDHC errata ENGcm03648 / ENGcm12360 */
+ if (!data && (cmd->resp_type & MMC_RSP_BUSY)) {
+ /*
+ * Poll on DATA0 line for cmd with busy signal for
+ * timout / 10 usec since DLA polling can be insecure.
+ */
+ ret = esdhc_poll(host, SDHCI_PRESENT_STATE,
+ PRSSTAT_DAT0, PRSSTAT_DAT0,
+ 2500 * MSECOND);
+ if (ret) {
+ dev_err(host->dev, "timeout PRSSTAT_DAT0\n");
+ return -ETIMEDOUT;
+ }
+ }
+
+ sdhci_read_response(&host->sdhci, cmd);
+
+ /* Wait until all of the blocks are transferred */
+ if (data) {
+ ret = esdhc_do_data(host, data, &tr);
+ if (ret)
+ return ret;
+ }
+
+ sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, -1);
+
+ /* Wait for the bus to be idle */
+ ret = esdhc_poll(host, SDHCI_PRESENT_STATE,
+ SDHCI_CMD_INHIBIT_CMD | SDHCI_CMD_INHIBIT_DATA, 0,
+ SECOND);
+ if (ret) {
+ dev_err(host->dev, "timeout 2\n");
+ return -ETIMEDOUT;
+ }
+
+ ret = esdhc_poll(host, SDHCI_PRESENT_STATE,
+ SDHCI_DATA_LINE_ACTIVE, 0,
+ 100 * MSECOND);
+ if (ret) {
+ dev_err(host->dev, "timeout 3\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c
index d6c178651..c0d27fb7e 100644
--- a/drivers/mci/imx-esdhc-pbl.c
+++ b/drivers/mci/imx-esdhc-pbl.c
@@ -30,92 +30,7 @@
#define SECTOR_SIZE 512
#define SECTOR_WML (SECTOR_SIZE / sizeof(u32))
-static void __udelay(int us)
-{
- volatile int i;
-
- for (i = 0; i < us * 4; i++);
-}
-
-static int
-esdhc_send_cmd(struct fsl_esdhc_host *host, struct mci_cmd *cmd, struct mci_data *data)
-{
- struct fsl_esdhc_dma_transfer tr = { 0 };
- u32 xfertyp, mixctrl, command;
- u32 irqstat;
- int ret;
-
- sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, -1);
-
- /* Wait at least 8 SD clock cycles before the next command */
- __udelay(1);
-
- if (data) {
- /* Set up for a data transfer if we have one */
- ret = esdhc_setup_data(host, data, &tr);
- if (ret)
- return ret;
- }
-
- sdhci_set_cmd_xfer_mode(&host->sdhci, cmd, data,
- false, &command, &xfertyp);
-
- if ((host->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT) &&
- (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION))
- command |= SDHCI_COMMAND_CMDTYP_ABORT;
-
- /* Send the command */
- sdhci_write32(&host->sdhci, SDHCI_ARGUMENT, cmd->cmdarg);
-
- if (esdhc_is_usdhc(host)) {
- /* write lower-half of xfertyp to mixctrl */
- mixctrl = xfertyp & 0xFFFF;
- /* Keep the bits 22-25 of the register as is */
- mixctrl |= (sdhci_read32(&host->sdhci, IMX_SDHCI_MIXCTRL) & (0xF << 22));
- sdhci_write32(&host->sdhci, IMX_SDHCI_MIXCTRL, mixctrl);
- }
-
-
- sdhci_write32(&host->sdhci, SDHCI_TRANSFER_MODE__COMMAND,
- command << 16 | xfertyp);
-
- /* Wait for the command to complete */
- ret = esdhc_poll(host, SDHCI_INT_STATUS,
- SDHCI_INT_CMD_COMPLETE, SDHCI_INT_CMD_COMPLETE,
- 100 * MSECOND);
- if (ret)
- return ret;
-
- irqstat = sdhci_read32(&host->sdhci, SDHCI_INT_STATUS);
- sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, irqstat);
-
- if (irqstat & CMD_ERR)
- return -EIO;
-
- if (irqstat & SDHCI_INT_TIMEOUT)
- return -ETIMEDOUT;
-
- /* Copy the response to the response buffer */
- cmd->response[0] = sdhci_read32(&host->sdhci, SDHCI_RESPONSE_0);
-
- /* Wait until all of the blocks are transferred */
- if (data) {
- ret = esdhc_do_data(host, data, &tr);
- if (ret)
- return ret;
- }
-
- sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, -1);
-
- /* Wait for the bus to be idle */
- ret = esdhc_poll(host, SDHCI_PRESENT_STATE,
- SDHCI_CMD_INHIBIT_CMD |
- SDHCI_CMD_INHIBIT_DATA |
- SDHCI_DATA_LINE_ACTIVE, 0,
- 100 * MSECOND);
-
- return 0;
-}
+#define esdhc_send_cmd __esdhc_send_cmd
static int esdhc_read_blocks(struct fsl_esdhc_host *host, void *dst, size_t len)
{
diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c
index 7e24b2b02..4816608a2 100644
--- a/drivers/mci/imx-esdhc.c
+++ b/drivers/mci/imx-esdhc.c
@@ -40,7 +40,6 @@
#include "imx-esdhc.h"
-#define PRSSTAT_DAT0 0x01000000
#define PRSSTAT_SDSTB 0x00000008
@@ -53,108 +52,9 @@
static int
esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
{
- u32 xfertyp, mixctrl, command;
- u32 irqstat;
struct fsl_esdhc_host *host = to_fsl_esdhc(mci);
- struct fsl_esdhc_dma_transfer tr = { 0 };
- int ret;
-
- sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, -1);
-
- /* Wait at least 8 SD clock cycles before the next command */
- udelay(1);
-
- /* Set up for a data transfer if we have one */
- if (data) {
- ret = esdhc_setup_data(host, data, &tr);
- if (ret)
- return ret;
- }
-
- sdhci_set_cmd_xfer_mode(&host->sdhci, cmd, data,
- !IS_ENABLED(CONFIG_MCI_IMX_ESDHC_PIO), &command,
- &xfertyp);
-
- if ((host->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT) &&
- (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION))
- command |= SDHCI_COMMAND_CMDTYP_ABORT;
-
- /* Send the command */
- sdhci_write32(&host->sdhci, SDHCI_ARGUMENT, cmd->cmdarg);
-
- if (esdhc_is_usdhc(host)) {
- /* write lower-half of xfertyp to mixctrl */
- mixctrl = xfertyp;
- /* Keep the bits 22-25 of the register as is */
- mixctrl |= (sdhci_read32(&host->sdhci, IMX_SDHCI_MIXCTRL) & (0xF << 22));
- sdhci_write32(&host->sdhci, IMX_SDHCI_MIXCTRL, mixctrl);
- }
-
- sdhci_write32(&host->sdhci, SDHCI_TRANSFER_MODE__COMMAND,
- command << 16 | xfertyp);
-
- /* Wait for the command to complete */
- ret = esdhc_poll(host, SDHCI_INT_STATUS,
- SDHCI_INT_CMD_COMPLETE, SDHCI_INT_CMD_COMPLETE,
- 100 * MSECOND);
- if (ret) {
- dev_dbg(host->dev, "timeout 1\n");
- return -ETIMEDOUT;
- }
-
- irqstat = sdhci_read32(&host->sdhci, SDHCI_INT_STATUS);
- sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, irqstat);
- if (irqstat & CMD_ERR)
- return -EIO;
-
- if (irqstat & SDHCI_INT_TIMEOUT)
- return -ETIMEDOUT;
-
- /* Workaround for ESDHC errata ENGcm03648 / ENGcm12360 */
- if (!data && (cmd->resp_type & MMC_RSP_BUSY)) {
- /*
- * Poll on DATA0 line for cmd with busy signal for
- * timout / 10 usec since DLA polling can be insecure.
- */
- ret = esdhc_poll(host, SDHCI_PRESENT_STATE,
- PRSSTAT_DAT0, PRSSTAT_DAT0,
- 2500 * MSECOND);
- if (ret) {
- dev_err(host->dev, "timeout PRSSTAT_DAT0\n");
- return -ETIMEDOUT;
- }
- }
-
- sdhci_read_response(&host->sdhci, cmd);
-
- /* Wait until all of the blocks are transferred */
- if (data) {
- ret = esdhc_do_data(host, data, &tr);
- if (ret)
- return ret;
- }
-
- sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, -1);
-
- /* Wait for the bus to be idle */
- ret = esdhc_poll(host, SDHCI_PRESENT_STATE,
- SDHCI_CMD_INHIBIT_CMD | SDHCI_CMD_INHIBIT_DATA, 0,
- SECOND);
- if (ret) {
- dev_err(host->dev, "timeout 2\n");
- return -ETIMEDOUT;
- }
-
- ret = esdhc_poll(host, SDHCI_PRESENT_STATE,
- SDHCI_DATA_LINE_ACTIVE, 0,
- 100 * MSECOND);
- if (ret) {
- dev_err(host->dev, "timeout 3\n");
- return -ETIMEDOUT;
- }
-
- return 0;
+ return __esdhc_send_cmd(host, cmd, data);
}
static void set_sysctl(struct mci_host *mci, u32 clock)
diff --git a/drivers/mci/imx-esdhc.h b/drivers/mci/imx-esdhc.h
index ac1208789..4bf890edf 100644
--- a/drivers/mci/imx-esdhc.h
+++ b/drivers/mci/imx-esdhc.h
@@ -129,13 +129,6 @@ struct fsl_esdhc_host {
struct sdhci sdhci;
};
-struct fsl_esdhc_dma_transfer {
- dma_addr_t dma;
- unsigned int size;
- enum dma_data_direction dir;
-};
-
-
static inline int esdhc_is_usdhc(struct fsl_esdhc_host *data)
{
return !!(data->socdata->flags & ESDHC_FLAG_USDHC);
@@ -173,12 +166,10 @@ esdhc_setbits32(struct fsl_esdhc_host *host, unsigned int reg,
}
void esdhc_populate_sdhci(struct fsl_esdhc_host *host);
-int esdhc_setup_data(struct fsl_esdhc_host *host, struct mci_data *data,
- struct fsl_esdhc_dma_transfer *tr);
-int esdhc_do_data(struct fsl_esdhc_host *host, struct mci_data *data,
- struct fsl_esdhc_dma_transfer *tr);
int esdhc_poll(struct fsl_esdhc_host *host, unsigned int off,
unsigned int mask, unsigned int val,
uint64_t timeout);
+int __esdhc_send_cmd(struct fsl_esdhc_host *host, struct mci_cmd *cmd,
+ struct mci_data *data);
#endif /* __FSL_ESDHC_H__ */
--
2.21.0
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 00/12] Share i.MX ESDHC PBL and PIO code
2019-12-02 15:19 [PATCH 00/12] Share i.MX ESDHC PBL and PIO code Andrey Smirnov
` (11 preceding siblings ...)
2019-12-02 15:19 ` [PATCH 12/12] mci: imx-esdhc: Share code for esdhc_send_cmd() Andrey Smirnov
@ 2019-12-04 8:42 ` Sascha Hauer
12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2019-12-04 8:42 UTC (permalink / raw)
To: Andrey Smirnov; +Cc: barebox
On Mon, Dec 02, 2019 at 07:19:42AM -0800, Andrey Smirnov wrote:
> Everyone:
>
> This series is an attempt to share as much functionality between PBL
> ESDHC code and PIO case of regular ESDHC driver as possible, since
> both implementations are identical in a lot of ways.
>
> Tested on RDU2 (i.MX6) and RDU3 (i.MX8MQ)
>
> Feedback is welcome!
Looks good. I gave it some testing on a Phytec board, both with PBL and
non PBL. Works as expected. I have merged it to next, let's see if it
survives my compile tests.
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] 14+ messages in thread
end of thread, other threads:[~2019-12-04 8:42 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-02 15:19 [PATCH 00/12] Share i.MX ESDHC PBL and PIO code Andrey Smirnov
2019-12-02 15:19 ` [PATCH 01/12] mci: imx-esdhc: Drop unnecessary type conversion Andrey Smirnov
2019-12-02 15:19 ` [PATCH 02/12] mci: imx-esdhc: Drop unused type definition Andrey Smirnov
2019-12-02 15:19 ` [PATCH 03/12] mci: imx-esdhc: Drop extra helper varaible Andrey Smirnov
2019-12-02 15:19 ` [PATCH 04/12] mci: imx-esdhc-pbl: Don't setup DMA registers Andrey Smirnov
2019-12-02 15:19 ` [PATCH 05/12] mci: imx-esdhc-pbl: Share initialization code Andrey Smirnov
2019-12-02 15:19 ` [PATCH 06/12] mci: imx-esdhc-pbl: Drop 'wrap_wml' flag Andrey Smirnov
2019-12-02 15:19 ` [PATCH 07/12] mci: imx-esdhc-pbl: Share IO accessors with regular driver Andrey Smirnov
2019-12-02 15:19 ` [PATCH 08/12] mci: imx-esdhc-pbl: Use sdhci_transfer_data() Andrey Smirnov
2019-12-02 15:19 ` [PATCH 09/12] mci: imx-esdhc-pbl: Use sdhci_set_cmd_xfer_mode() Andrey Smirnov
2019-12-02 15:19 ` [PATCH 10/12] mci: imx-esdhc: Share code for esdhc_(setup|do)_data operations Andrey Smirnov
2019-12-02 15:19 ` [PATCH 11/12] mci: imx-esdhc: Introduce esdhc_poll() Andrey Smirnov
2019-12-02 15:19 ` [PATCH 12/12] mci: imx-esdhc: Share code for esdhc_send_cmd() Andrey Smirnov
2019-12-04 8:42 ` [PATCH 00/12] Share i.MX ESDHC PBL and PIO code Sascha Hauer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox