refactor(nxp-mmc): populate command transfer type
The CMD_XFR_TYP register description in the reference manual includes a
table where the response type, index check, and CRC check are populated
based on the CMD's response type. Therefore, replace the CMD_XFR_TYP set
based on the command ID with the mechanism mentioned in the reference
manual.
Change-Id: Ibe6e04d1682e258ae2377dd7a1d0abb6c7b3f164
Co-developed-by: Ciprian Costea <ciprianmarian.costea@nxp.com>
Signed-off-by: Ciprian Costea <ciprianmarian.costea@nxp.com>
Signed-off-by: Ghennadi Procopciuc <ghennadi.procopciuc@nxp.com>
diff --git a/drivers/imx/usdhc/imx_usdhc.c b/drivers/imx/usdhc/imx_usdhc.c
index 1e87ee3..2238943 100644
--- a/drivers/imx/usdhc/imx_usdhc.c
+++ b/drivers/imx/usdhc/imx_usdhc.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright 2025 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -17,6 +18,11 @@
#include <imx_usdhc.h>
+/* These masks represent the commands which involve a data transfer. */
+#define ADTC_MASK_SD (BIT_32(6U) | BIT_32(17U) | BIT_32(18U) |\
+ BIT_32(24U) | BIT_32(25U))
+#define ADTC_MASK_ACMD (BIT_64(51U))
+
static void imx_usdhc_initialize(void);
static int imx_usdhc_send_cmd(struct mmc_cmd *cmd);
static int imx_usdhc_set_ios(unsigned int clk, unsigned int width);
@@ -107,15 +113,78 @@
#define FSL_CMD_RETRIES 1000
+static bool is_data_transfer_cmd(const struct mmc_cmd *cmd)
+{
+ uintptr_t reg_base = imx_usdhc_params.reg_base;
+ unsigned int cmd_idx = cmd->cmd_idx;
+ uint32_t xfer_type;
+
+ xfer_type = mmio_read_32(reg_base + XFERTYPE);
+
+ if (XFERTYPE_GET_CMD(xfer_type) == MMC_CMD(55)) {
+ return (ADTC_MASK_ACMD & BIT_64(cmd_idx)) != 0ULL;
+ }
+
+ if ((ADTC_MASK_SD & BIT_32(cmd->cmd_idx)) != 0U) {
+ return true;
+ }
+
+ return false;
+}
+
+static int get_xfr_type(const struct mmc_cmd *cmd, bool data, uint32_t *xfertype)
+{
+ *xfertype = XFERTYPE_CMD(cmd->cmd_idx);
+
+ switch (cmd->resp_type) {
+ case MMC_RESPONSE_R2:
+ *xfertype |= XFERTYPE_RSPTYP_136;
+ *xfertype |= XFERTYPE_CCCEN;
+ break;
+ case MMC_RESPONSE_R4:
+ *xfertype |= XFERTYPE_RSPTYP_48;
+ break;
+ case MMC_RESPONSE_R6:
+ *xfertype |= XFERTYPE_RSPTYP_48;
+ *xfertype |= XFERTYPE_CICEN;
+ *xfertype |= XFERTYPE_CCCEN;
+ break;
+ case MMC_RESPONSE_R1B:
+ *xfertype |= XFERTYPE_RSPTYP_48_BUSY;
+ *xfertype |= XFERTYPE_CICEN;
+ *xfertype |= XFERTYPE_CCCEN;
+ break;
+ default:
+ ERROR("Invalid CMD response: %u\n", cmd->resp_type);
+ return -EINVAL;
+ }
+
+ if (data) {
+ *xfertype |= XFERTYPE_DPSEL;
+ }
+
+ return 0;
+}
+
static int imx_usdhc_send_cmd(struct mmc_cmd *cmd)
{
uintptr_t reg_base = imx_usdhc_params.reg_base;
- unsigned int xfertype = 0, mixctl = 0, multiple = 0, data = 0, err = 0;
unsigned int state, flags = INTSTATEN_CC | INTSTATEN_CTOE;
+ unsigned int mixctl = 0, multiple = 0;
unsigned int cmd_retries = 0;
+ uint32_t xfertype;
+ bool data;
+ int err = 0;
assert(cmd);
+ data = is_data_transfer_cmd(cmd);
+
+ err = get_xfr_type(cmd, data, &xfertype);
+ if (err != 0) {
+ return err;
+ }
+
/* clear all irq status */
mmio_write_32(reg_base + INTSTAT, 0xffffffff);
@@ -131,9 +200,6 @@
udelay(1000);
switch (cmd->cmd_idx) {
- case MMC_CMD(12):
- xfertype |= XFERTYPE_CMDTYP_ABORT;
- break;
case MMC_CMD(18):
multiple = 1;
/* for read op */
@@ -141,14 +207,11 @@
case MMC_CMD(17):
case MMC_CMD(8):
mixctl |= MIXCTRL_DTDSEL;
- data = 1;
break;
case MMC_CMD(25):
multiple = 1;
/* for data op flag */
/* fallthrough */
- case MMC_CMD(24):
- data = 1;
break;
default:
break;
@@ -160,25 +223,9 @@
}
if (data) {
- xfertype |= XFERTYPE_DPSEL;
mixctl |= MIXCTRL_DMAEN;
}
- if (cmd->resp_type & MMC_RSP_48 && cmd->resp_type != MMC_RESPONSE_R2)
- xfertype |= XFERTYPE_RSPTYP_48;
- else if (cmd->resp_type & MMC_RSP_136)
- xfertype |= XFERTYPE_RSPTYP_136;
- else if (cmd->resp_type & MMC_RSP_BUSY)
- xfertype |= XFERTYPE_RSPTYP_48_BUSY;
-
- if (cmd->resp_type & MMC_RSP_CMD_IDX)
- xfertype |= XFERTYPE_CICEN;
-
- if (cmd->resp_type & MMC_RSP_CRC)
- xfertype |= XFERTYPE_CCCEN;
-
- xfertype |= XFERTYPE_CMD(cmd->cmd_idx);
-
/* Send the command */
mmio_write_32(reg_base + CMDARG, cmd->cmd_arg);
mmio_clrsetbits32(reg_base + MIXCTRL, MIXCTRL_DATMASK, mixctl);