1 /* 2 * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. 3 * Copyright 2025 NXP 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 8 #include <assert.h> 9 #include <errno.h> 10 #include <string.h> 11 12 #include <arch.h> 13 #include <arch_helpers.h> 14 #include <common/debug.h> 15 #include <drivers/delay_timer.h> 16 #include <drivers/mmc.h> 17 #include <lib/mmio.h> 18 #include <lib/xlat_tables/xlat_tables_v2.h> 19 20 #include <imx_usdhc.h> 21 22 /* These masks represent the commands which involve a data transfer. */ 23 #define ADTC_MASK_SD (BIT_32(6U) | BIT_32(17U) | BIT_32(18U) |\ 24 BIT_32(24U) | BIT_32(25U)) 25 #define ADTC_MASK_ACMD (BIT_64(51U)) 26 27 struct imx_usdhc_device_data { 28 uint32_t addr; 29 uint32_t blk_size; 30 uint32_t blks; 31 bool valid; 32 }; 33 34 static void imx_usdhc_initialize(void); 35 static int imx_usdhc_send_cmd(struct mmc_cmd *cmd); 36 static int imx_usdhc_set_ios(unsigned int clk, unsigned int width); 37 static int imx_usdhc_prepare(int lba, uintptr_t buf, size_t size); 38 static int imx_usdhc_read(int lba, uintptr_t buf, size_t size); 39 static int imx_usdhc_write(int lba, uintptr_t buf, size_t size); 40 41 static const struct mmc_ops imx_usdhc_ops = { 42 .init = imx_usdhc_initialize, 43 .send_cmd = imx_usdhc_send_cmd, 44 .set_ios = imx_usdhc_set_ios, 45 .prepare = imx_usdhc_prepare, 46 .read = imx_usdhc_read, 47 .write = imx_usdhc_write, 48 }; 49 50 static imx_usdhc_params_t imx_usdhc_params; 51 static struct imx_usdhc_device_data imx_usdhc_data; 52 53 static bool imx_usdhc_is_buf_valid(void) 54 { 55 return imx_usdhc_data.valid; 56 } 57 58 static bool imx_usdhc_is_buf_multiblk(void) 59 { 60 return imx_usdhc_data.blks > 1U; 61 } 62 63 static void imx_usdhc_inval_buf_data(void) 64 { 65 imx_usdhc_data.valid = false; 66 } 67 68 static int imx_usdhc_save_buf_data(uintptr_t buf, size_t size) 69 { 70 uint32_t block_size; 71 uint64_t blks; 72 73 if (size <= MMC_BLOCK_SIZE) { 74 block_size = (uint32_t)size; 75 } else { 76 block_size = MMC_BLOCK_SIZE; 77 } 78 79 if (buf > UINT32_MAX) { 80 return -EOVERFLOW; 81 } 82 83 imx_usdhc_data.addr = (uint32_t)buf; 84 imx_usdhc_data.blk_size = block_size; 85 blks = size / block_size; 86 imx_usdhc_data.blks = (uint32_t)blks; 87 88 imx_usdhc_data.valid = true; 89 90 return 0; 91 } 92 93 static void imx_usdhc_write_buf_data(void) 94 { 95 uintptr_t reg_base = imx_usdhc_params.reg_base; 96 uint32_t addr, blks, blk_size; 97 98 addr = imx_usdhc_data.addr; 99 blks = imx_usdhc_data.blks; 100 blk_size = imx_usdhc_data.blk_size; 101 102 mmio_write_32(reg_base + DSADDR, addr); 103 mmio_write_32(reg_base + BLKATT, BLKATT_BLKCNT(blks) | 104 BLKATT_BLKSIZE(blk_size)); 105 } 106 107 #define IMX7_MMC_SRC_CLK_RATE (200 * 1000 * 1000) 108 static void imx_usdhc_set_clk(unsigned int clk) 109 { 110 unsigned int sdhc_clk = IMX7_MMC_SRC_CLK_RATE; 111 uintptr_t reg_base = imx_usdhc_params.reg_base; 112 unsigned int pre_div = 1U, div = 1U; 113 114 assert(clk > 0); 115 116 while (sdhc_clk / (16 * pre_div) > clk && pre_div < 256) 117 pre_div *= 2; 118 119 while (((sdhc_clk / (div * pre_div)) > clk) && (div < 16U)) { 120 div++; 121 } 122 123 pre_div >>= 1; 124 div -= 1; 125 clk = (pre_div << 8) | (div << 4); 126 127 while ((mmio_read_32(reg_base + PSTATE) & PSTATE_SDSTB) == 0U) { 128 } 129 130 mmio_clrbits32(reg_base + VENDSPEC, VENDSPEC_CARD_CLKEN); 131 mmio_clrsetbits32(reg_base + SYSCTRL, SYSCTRL_CLOCK_MASK, clk); 132 udelay(10000); 133 134 mmio_setbits32(reg_base + VENDSPEC, VENDSPEC_PER_CLKEN | VENDSPEC_CARD_CLKEN); 135 } 136 137 static void imx_usdhc_initialize(void) 138 { 139 unsigned int timeout = 10000; 140 uintptr_t reg_base = imx_usdhc_params.reg_base; 141 142 assert((imx_usdhc_params.reg_base & MMC_BLOCK_MASK) == 0); 143 144 /* reset the controller */ 145 mmio_setbits32(reg_base + SYSCTRL, SYSCTRL_RSTA); 146 147 /* wait for reset done */ 148 while ((mmio_read_32(reg_base + SYSCTRL) & SYSCTRL_RSTA)) { 149 if (!timeout) 150 ERROR("IMX MMC reset timeout.\n"); 151 timeout--; 152 } 153 154 mmio_write_32(reg_base + MMCBOOT, 0); 155 mmio_write_32(reg_base + MIXCTRL, 0); 156 mmio_write_32(reg_base + CLKTUNECTRLSTS, 0); 157 158 mmio_write_32(reg_base + VENDSPEC, VENDSPEC_INIT); 159 mmio_write_32(reg_base + DLLCTRL, 0); 160 mmio_setbits32(reg_base + VENDSPEC, VENDSPEC_IPG_CLKEN | VENDSPEC_PER_CLKEN); 161 162 /* Set the initial boot clock rate */ 163 imx_usdhc_set_clk(MMC_BOOT_CLK_RATE); 164 udelay(100); 165 166 /* Clear read/write ready status */ 167 mmio_clrbits32(reg_base + INTSTATEN, INTSTATEN_BRR | INTSTATEN_BWR); 168 169 /* configure as little endian */ 170 mmio_write_32(reg_base + PROTCTRL, PROTCTRL_LE); 171 172 /* Set timeout to the maximum value */ 173 mmio_clrsetbits32(reg_base + SYSCTRL, SYSCTRL_TIMEOUT_MASK, 174 SYSCTRL_TIMEOUT(15)); 175 176 /* set wartermark level as 16 for safe for MMC */ 177 mmio_clrsetbits32(reg_base + WATERMARKLEV, WMKLV_MASK, 16 | (16 << 16)); 178 } 179 180 #define FSL_CMD_RETRIES 1000 181 182 static bool is_data_transfer_to_card(const struct mmc_cmd *cmd) 183 { 184 unsigned int cmd_idx = cmd->cmd_idx; 185 186 return (cmd_idx == MMC_CMD(24)) || (cmd_idx == MMC_CMD(25)); 187 } 188 189 static bool is_data_transfer_cmd(const struct mmc_cmd *cmd) 190 { 191 uintptr_t reg_base = imx_usdhc_params.reg_base; 192 unsigned int cmd_idx = cmd->cmd_idx; 193 uint32_t xfer_type; 194 195 xfer_type = mmio_read_32(reg_base + XFERTYPE); 196 197 if (XFERTYPE_GET_CMD(xfer_type) == MMC_CMD(55)) { 198 return (ADTC_MASK_ACMD & BIT_64(cmd_idx)) != 0ULL; 199 } 200 201 if ((ADTC_MASK_SD & BIT_32(cmd->cmd_idx)) != 0U) { 202 return true; 203 } 204 205 return false; 206 } 207 208 static int get_xfr_type(const struct mmc_cmd *cmd, bool data, uint32_t *xfertype) 209 { 210 *xfertype = XFERTYPE_CMD(cmd->cmd_idx); 211 212 switch (cmd->resp_type) { 213 case MMC_RESPONSE_R2: 214 *xfertype |= XFERTYPE_RSPTYP_136; 215 *xfertype |= XFERTYPE_CCCEN; 216 break; 217 case MMC_RESPONSE_R4: 218 *xfertype |= XFERTYPE_RSPTYP_48; 219 break; 220 case MMC_RESPONSE_R6: 221 *xfertype |= XFERTYPE_RSPTYP_48; 222 *xfertype |= XFERTYPE_CICEN; 223 *xfertype |= XFERTYPE_CCCEN; 224 break; 225 case MMC_RESPONSE_R1B: 226 *xfertype |= XFERTYPE_RSPTYP_48_BUSY; 227 *xfertype |= XFERTYPE_CICEN; 228 *xfertype |= XFERTYPE_CCCEN; 229 break; 230 default: 231 ERROR("Invalid CMD response: %u\n", cmd->resp_type); 232 return -EINVAL; 233 } 234 235 if (data) { 236 *xfertype |= XFERTYPE_DPSEL; 237 } 238 239 return 0; 240 } 241 242 static int imx_usdhc_send_cmd(struct mmc_cmd *cmd) 243 { 244 uintptr_t reg_base = imx_usdhc_params.reg_base; 245 unsigned int state, flags = INTSTATEN_CC | INTSTATEN_CTOE; 246 unsigned int mixctl = 0; 247 unsigned int cmd_retries = 0; 248 uint32_t xfertype; 249 bool data; 250 int err = 0; 251 252 assert(cmd); 253 254 data = is_data_transfer_cmd(cmd); 255 256 err = get_xfr_type(cmd, data, &xfertype); 257 if (err != 0) { 258 return err; 259 } 260 261 /* clear all irq status */ 262 mmio_write_32(reg_base + INTSTAT, 0xffffffff); 263 264 /* Wait for the bus to be idle */ 265 do { 266 state = mmio_read_32(reg_base + PSTATE); 267 } while (state & (PSTATE_CDIHB | PSTATE_CIHB)); 268 269 while (mmio_read_32(reg_base + PSTATE) & PSTATE_DLA) 270 ; 271 272 mmio_write_32(reg_base + INTSIGEN, 0); 273 274 if (data) { 275 mixctl |= MIXCTRL_DMAEN; 276 } 277 278 if (!is_data_transfer_to_card(cmd)) { 279 mixctl |= MIXCTRL_DTDSEL; 280 } 281 282 if ((cmd->cmd_idx != MMC_CMD(55)) && imx_usdhc_is_buf_valid()) { 283 if (imx_usdhc_is_buf_multiblk()) { 284 mixctl |= MIXCTRL_MSBSEL | MIXCTRL_BCEN; 285 } 286 287 imx_usdhc_write_buf_data(); 288 imx_usdhc_inval_buf_data(); 289 } 290 291 /* Send the command */ 292 mmio_write_32(reg_base + CMDARG, cmd->cmd_arg); 293 mmio_clrsetbits32(reg_base + MIXCTRL, MIXCTRL_DATMASK, mixctl); 294 mmio_write_32(reg_base + XFERTYPE, xfertype); 295 296 /* Wait for the command done */ 297 do { 298 state = mmio_read_32(reg_base + INTSTAT); 299 if (cmd_retries) 300 udelay(1); 301 } while ((!(state & flags)) && ++cmd_retries < FSL_CMD_RETRIES); 302 303 if ((state & (INTSTATEN_CTOE | CMD_ERR)) || cmd_retries == FSL_CMD_RETRIES) { 304 if (cmd_retries == FSL_CMD_RETRIES) 305 err = -ETIMEDOUT; 306 else 307 err = -EIO; 308 ERROR("imx_usdhc mmc cmd %d state 0x%x errno=%d\n", 309 cmd->cmd_idx, state, err); 310 goto out; 311 } 312 313 /* Copy the response to the response buffer */ 314 if (cmd->resp_type & MMC_RSP_136) { 315 unsigned int cmdrsp3, cmdrsp2, cmdrsp1, cmdrsp0; 316 317 cmdrsp3 = mmio_read_32(reg_base + CMDRSP3); 318 cmdrsp2 = mmio_read_32(reg_base + CMDRSP2); 319 cmdrsp1 = mmio_read_32(reg_base + CMDRSP1); 320 cmdrsp0 = mmio_read_32(reg_base + CMDRSP0); 321 cmd->resp_data[3] = (cmdrsp3 << 8) | (cmdrsp2 >> 24); 322 cmd->resp_data[2] = (cmdrsp2 << 8) | (cmdrsp1 >> 24); 323 cmd->resp_data[1] = (cmdrsp1 << 8) | (cmdrsp0 >> 24); 324 cmd->resp_data[0] = (cmdrsp0 << 8); 325 } else { 326 cmd->resp_data[0] = mmio_read_32(reg_base + CMDRSP0); 327 } 328 329 /* Wait until all of the blocks are transferred */ 330 if (data) { 331 flags = DATA_COMPLETE; 332 do { 333 state = mmio_read_32(reg_base + INTSTAT); 334 335 if (state & (INTSTATEN_DTOE | DATA_ERR)) { 336 err = -EIO; 337 ERROR("imx_usdhc mmc data state 0x%x\n", state); 338 goto out; 339 } 340 } while ((state & flags) != flags); 341 } 342 343 out: 344 /* Reset CMD and DATA on error */ 345 if (err) { 346 mmio_setbits32(reg_base + SYSCTRL, SYSCTRL_RSTC); 347 while (mmio_read_32(reg_base + SYSCTRL) & SYSCTRL_RSTC) 348 ; 349 350 if (data) { 351 mmio_setbits32(reg_base + SYSCTRL, SYSCTRL_RSTD); 352 while (mmio_read_32(reg_base + SYSCTRL) & SYSCTRL_RSTD) 353 ; 354 } 355 } 356 357 /* clear all irq status */ 358 mmio_write_32(reg_base + INTSTAT, 0xffffffff); 359 360 return err; 361 } 362 363 static int imx_usdhc_set_ios(unsigned int clk, unsigned int width) 364 { 365 uintptr_t reg_base = imx_usdhc_params.reg_base; 366 367 imx_usdhc_set_clk(clk); 368 369 if (width == MMC_BUS_WIDTH_4) 370 mmio_clrsetbits32(reg_base + PROTCTRL, PROTCTRL_WIDTH_MASK, 371 PROTCTRL_WIDTH_4); 372 else if (width == MMC_BUS_WIDTH_8) 373 mmio_clrsetbits32(reg_base + PROTCTRL, PROTCTRL_WIDTH_MASK, 374 PROTCTRL_WIDTH_8); 375 376 return 0; 377 } 378 379 static int imx_usdhc_prepare(int lba, uintptr_t buf, size_t size) 380 { 381 flush_dcache_range(buf, size); 382 return imx_usdhc_save_buf_data(buf, size); 383 } 384 385 static int imx_usdhc_read(int lba, uintptr_t buf, size_t size) 386 { 387 inv_dcache_range(buf, size); 388 return 0; 389 } 390 391 static int imx_usdhc_write(int lba, uintptr_t buf, size_t size) 392 { 393 return 0; 394 } 395 396 void imx_usdhc_init(imx_usdhc_params_t *params, 397 struct mmc_device_info *mmc_dev_info) 398 { 399 int ret __maybe_unused; 400 401 assert((params != 0) && 402 ((params->reg_base & MMC_BLOCK_MASK) == 0) && 403 ((params->bus_width == MMC_BUS_WIDTH_1) || 404 (params->bus_width == MMC_BUS_WIDTH_4) || 405 (params->bus_width == MMC_BUS_WIDTH_8))); 406 407 #if PLAT_XLAT_TABLES_DYNAMIC 408 ret = mmap_add_dynamic_region(params->reg_base, params->reg_base, 409 PAGE_SIZE, 410 MT_DEVICE | MT_RW | MT_SECURE); 411 if (ret != 0) { 412 ERROR("Failed to map the uSDHC registers\n"); 413 panic(); 414 } 415 #endif 416 417 memcpy(&imx_usdhc_params, params, sizeof(imx_usdhc_params_t)); 418 mmc_init(&imx_usdhc_ops, params->clk_rate, params->bus_width, 419 params->flags, mmc_dev_info); 420 } 421