1 /* 2 * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <arch.h> 8 #include <arch_helpers.h> 9 #include <assert.h> 10 #include <debug.h> 11 #include <delay_timer.h> 12 #include <imx_usdhc.h> 13 #include <mmc.h> 14 #include <errno.h> 15 #include <mmio.h> 16 #include <string.h> 17 18 static void imx_usdhc_initialize(void); 19 static int imx_usdhc_send_cmd(struct mmc_cmd *cmd); 20 static int imx_usdhc_set_ios(unsigned int clk, unsigned int width); 21 static int imx_usdhc_prepare(int lba, uintptr_t buf, size_t size); 22 static int imx_usdhc_read(int lba, uintptr_t buf, size_t size); 23 static int imx_usdhc_write(int lba, uintptr_t buf, size_t size); 24 25 static const struct mmc_ops imx_usdhc_ops = { 26 .init = imx_usdhc_initialize, 27 .send_cmd = imx_usdhc_send_cmd, 28 .set_ios = imx_usdhc_set_ios, 29 .prepare = imx_usdhc_prepare, 30 .read = imx_usdhc_read, 31 .write = imx_usdhc_write, 32 }; 33 34 static imx_usdhc_params_t imx_usdhc_params; 35 36 #define IMX7_MMC_SRC_CLK_RATE (200 * 1000 * 1000) 37 static void imx_usdhc_set_clk(int clk) 38 { 39 int div = 1; 40 int pre_div = 1; 41 unsigned int sdhc_clk = IMX7_MMC_SRC_CLK_RATE; 42 uintptr_t reg_base = imx_usdhc_params.reg_base; 43 44 assert(clk > 0); 45 46 while (sdhc_clk / (16 * pre_div) > clk && pre_div < 256) 47 pre_div *= 2; 48 49 while (sdhc_clk / div > clk && div < 16) 50 div++; 51 52 pre_div >>= 1; 53 div -= 1; 54 clk = (pre_div << 8) | (div << 4); 55 56 mmio_clrbits32(reg_base + VENDSPEC, VENDSPEC_CARD_CLKEN); 57 mmio_clrsetbits32(reg_base + SYSCTRL, SYSCTRL_CLOCK_MASK, clk); 58 udelay(10000); 59 60 mmio_setbits32(reg_base + VENDSPEC, VENDSPEC_PER_CLKEN | VENDSPEC_CARD_CLKEN); 61 } 62 63 static void imx_usdhc_initialize(void) 64 { 65 unsigned int timeout = 10000; 66 uintptr_t reg_base = imx_usdhc_params.reg_base; 67 68 assert((imx_usdhc_params.reg_base & MMC_BLOCK_MASK) == 0); 69 70 /* reset the controller */ 71 mmio_setbits32(reg_base + SYSCTRL, SYSCTRL_RSTA); 72 73 /* wait for reset done */ 74 while ((mmio_read_32(reg_base + SYSCTRL) & SYSCTRL_RSTA)) { 75 if (!timeout) 76 ERROR("IMX MMC reset timeout.\n"); 77 timeout--; 78 } 79 80 mmio_write_32(reg_base + MMCBOOT, 0); 81 mmio_write_32(reg_base + MIXCTRL, 0); 82 mmio_write_32(reg_base + CLKTUNECTRLSTS, 0); 83 84 mmio_write_32(reg_base + VENDSPEC, VENDSPEC_INIT); 85 mmio_write_32(reg_base + DLLCTRL, 0); 86 mmio_setbits32(reg_base + VENDSPEC, VENDSPEC_IPG_CLKEN | VENDSPEC_PER_CLKEN); 87 88 /* Set the initial boot clock rate */ 89 imx_usdhc_set_clk(MMC_BOOT_CLK_RATE); 90 udelay(100); 91 92 /* Clear read/write ready status */ 93 mmio_clrbits32(reg_base + INTSTATEN, INTSTATEN_BRR | INTSTATEN_BWR); 94 95 /* configure as little endian */ 96 mmio_write_32(reg_base + PROTCTRL, PROTCTRL_LE); 97 98 /* Set timeout to the maximum value */ 99 mmio_clrsetbits32(reg_base + SYSCTRL, SYSCTRL_TIMEOUT_MASK, 100 SYSCTRL_TIMEOUT(15)); 101 102 /* set wartermark level as 16 for safe for MMC */ 103 mmio_clrsetbits32(reg_base + WATERMARKLEV, WMKLV_MASK, 16 | (16 << 16)); 104 } 105 106 #define FSL_CMD_RETRIES 1000 107 108 static int imx_usdhc_send_cmd(struct mmc_cmd *cmd) 109 { 110 uintptr_t reg_base = imx_usdhc_params.reg_base; 111 unsigned int xfertype = 0, mixctl = 0, multiple = 0, data = 0, err = 0; 112 unsigned int state, flags = INTSTATEN_CC | INTSTATEN_CTOE; 113 unsigned int cmd_retries = 0; 114 115 assert(cmd); 116 117 /* clear all irq status */ 118 mmio_write_32(reg_base + INTSTAT, 0xffffffff); 119 120 /* Wait for the bus to be idle */ 121 do { 122 state = mmio_read_32(reg_base + PSTATE); 123 } while (state & (PSTATE_CDIHB | PSTATE_CIHB)); 124 125 while (mmio_read_32(reg_base + PSTATE) & PSTATE_DLA) 126 ; 127 128 mmio_write_32(reg_base + INTSIGEN, 0); 129 udelay(1000); 130 131 switch (cmd->cmd_idx) { 132 case MMC_CMD(12): 133 xfertype |= XFERTYPE_CMDTYP_ABORT; 134 break; 135 case MMC_CMD(18): 136 multiple = 1; 137 /* fall thru for read op */ 138 case MMC_CMD(17): 139 case MMC_CMD(8): 140 mixctl |= MIXCTRL_DTDSEL; 141 data = 1; 142 break; 143 case MMC_CMD(25): 144 multiple = 1; 145 /* fall thru for data op flag */ 146 case MMC_CMD(24): 147 data = 1; 148 break; 149 default: 150 break; 151 } 152 153 if (multiple) { 154 mixctl |= MIXCTRL_MSBSEL; 155 mixctl |= MIXCTRL_BCEN; 156 } 157 158 if (data) { 159 xfertype |= XFERTYPE_DPSEL; 160 mixctl |= MIXCTRL_DMAEN; 161 } 162 163 if (cmd->resp_type & MMC_RSP_48) 164 xfertype |= XFERTYPE_RSPTYP_48; 165 else if (cmd->resp_type & MMC_RSP_136) 166 xfertype |= XFERTYPE_RSPTYP_136; 167 else if (cmd->resp_type & MMC_RSP_BUSY) 168 xfertype |= XFERTYPE_RSPTYP_48_BUSY; 169 170 if (cmd->resp_type & MMC_RSP_CMD_IDX) 171 xfertype |= XFERTYPE_CICEN; 172 173 if (cmd->resp_type & MMC_RSP_CRC) 174 xfertype |= XFERTYPE_CCCEN; 175 176 xfertype |= XFERTYPE_CMD(cmd->cmd_idx); 177 178 /* Send the command */ 179 mmio_write_32(reg_base + CMDARG, cmd->cmd_arg); 180 mmio_clrsetbits32(reg_base + MIXCTRL, MIXCTRL_DATMASK, mixctl); 181 mmio_write_32(reg_base + XFERTYPE, xfertype); 182 183 /* Wait for the command done */ 184 do { 185 state = mmio_read_32(reg_base + INTSTAT); 186 if (cmd_retries) 187 udelay(1); 188 } while ((!(state & flags)) && ++cmd_retries < FSL_CMD_RETRIES); 189 190 if ((state & (INTSTATEN_CTOE | CMD_ERR)) || cmd_retries == FSL_CMD_RETRIES) { 191 if (cmd_retries == FSL_CMD_RETRIES) 192 err = -ETIMEDOUT; 193 else 194 err = -EIO; 195 ERROR("imx_usdhc mmc cmd %d state 0x%x errno=%d\n", 196 cmd->cmd_idx, state, err); 197 goto out; 198 } 199 200 /* Copy the response to the response buffer */ 201 if (cmd->resp_type & MMC_RSP_136) { 202 unsigned int cmdrsp3, cmdrsp2, cmdrsp1, cmdrsp0; 203 204 cmdrsp3 = mmio_read_32(reg_base + CMDRSP3); 205 cmdrsp2 = mmio_read_32(reg_base + CMDRSP2); 206 cmdrsp1 = mmio_read_32(reg_base + CMDRSP1); 207 cmdrsp0 = mmio_read_32(reg_base + CMDRSP0); 208 cmd->resp_data[3] = (cmdrsp3 << 8) | (cmdrsp2 >> 24); 209 cmd->resp_data[2] = (cmdrsp2 << 8) | (cmdrsp1 >> 24); 210 cmd->resp_data[1] = (cmdrsp1 << 8) | (cmdrsp0 >> 24); 211 cmd->resp_data[0] = (cmdrsp0 << 8); 212 } else { 213 cmd->resp_data[0] = mmio_read_32(reg_base + CMDRSP0); 214 } 215 216 /* Wait until all of the blocks are transferred */ 217 if (data) { 218 flags = DATA_COMPLETE; 219 do { 220 state = mmio_read_32(reg_base + INTSTAT); 221 222 if (state & (INTSTATEN_DTOE | DATA_ERR)) { 223 err = -EIO; 224 ERROR("imx_usdhc mmc data state 0x%x\n", state); 225 goto out; 226 } 227 } while ((state & flags) != flags); 228 } 229 230 out: 231 /* Reset CMD and DATA on error */ 232 if (err) { 233 mmio_setbits32(reg_base + SYSCTRL, SYSCTRL_RSTC); 234 while (mmio_read_32(reg_base + SYSCTRL) & SYSCTRL_RSTC) 235 ; 236 237 if (data) { 238 mmio_setbits32(reg_base + SYSCTRL, SYSCTRL_RSTD); 239 while (mmio_read_32(reg_base + SYSCTRL) & SYSCTRL_RSTD) 240 ; 241 } 242 } 243 244 /* clear all irq status */ 245 mmio_write_32(reg_base + INTSTAT, 0xffffffff); 246 247 return err; 248 } 249 250 static int imx_usdhc_set_ios(unsigned int clk, unsigned int width) 251 { 252 uintptr_t reg_base = imx_usdhc_params.reg_base; 253 254 imx_usdhc_set_clk(clk); 255 256 if (width == MMC_BUS_WIDTH_4) 257 mmio_clrsetbits32(reg_base + PROTCTRL, PROTCTRL_WIDTH_MASK, 258 PROTCTRL_WIDTH_4); 259 else if (width == MMC_BUS_WIDTH_8) 260 mmio_clrsetbits32(reg_base + PROTCTRL, PROTCTRL_WIDTH_MASK, 261 PROTCTRL_WIDTH_8); 262 263 return 0; 264 } 265 266 static int imx_usdhc_prepare(int lba, uintptr_t buf, size_t size) 267 { 268 uintptr_t reg_base = imx_usdhc_params.reg_base; 269 270 mmio_write_32(reg_base + DSADDR, buf); 271 mmio_write_32(reg_base + BLKATT, 272 (size / MMC_BLOCK_SIZE) << 16 | MMC_BLOCK_SIZE); 273 274 return 0; 275 } 276 277 static int imx_usdhc_read(int lba, uintptr_t buf, size_t size) 278 { 279 return 0; 280 } 281 282 static int imx_usdhc_write(int lba, uintptr_t buf, size_t size) 283 { 284 return 0; 285 } 286 287 void imx_usdhc_init(imx_usdhc_params_t *params, 288 struct mmc_device_info *mmc_dev_info) 289 { 290 assert((params != 0) && 291 ((params->reg_base & MMC_BLOCK_MASK) == 0) && 292 (params->clk_rate > 0) && 293 ((params->bus_width == MMC_BUS_WIDTH_1) || 294 (params->bus_width == MMC_BUS_WIDTH_4) || 295 (params->bus_width == MMC_BUS_WIDTH_8))); 296 297 memcpy(&imx_usdhc_params, params, sizeof(imx_usdhc_params_t)); 298 mmc_init(&imx_usdhc_ops, params->clk_rate, params->bus_width, 299 params->flags, mmc_dev_info); 300 } 301