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