1*8e2e5e8bSYann Gautier /* 2*8e2e5e8bSYann Gautier * Copyright (c) 2018, STMicroelectronics - All Rights Reserved 3*8e2e5e8bSYann Gautier * 4*8e2e5e8bSYann Gautier * SPDX-License-Identifier: BSD-3-Clause 5*8e2e5e8bSYann Gautier */ 6*8e2e5e8bSYann Gautier 7*8e2e5e8bSYann Gautier #include <arch.h> 8*8e2e5e8bSYann Gautier #include <arch_helpers.h> 9*8e2e5e8bSYann Gautier #include <assert.h> 10*8e2e5e8bSYann Gautier #include <debug.h> 11*8e2e5e8bSYann Gautier #include <delay_timer.h> 12*8e2e5e8bSYann Gautier #include <dt-bindings/clock/stm32mp1-clks.h> 13*8e2e5e8bSYann Gautier #include <dt-bindings/reset/stm32mp1-resets.h> 14*8e2e5e8bSYann Gautier #include <errno.h> 15*8e2e5e8bSYann Gautier #include <libfdt.h> 16*8e2e5e8bSYann Gautier #include <mmc.h> 17*8e2e5e8bSYann Gautier #include <mmio.h> 18*8e2e5e8bSYann Gautier #include <platform.h> 19*8e2e5e8bSYann Gautier #include <stm32_sdmmc2.h> 20*8e2e5e8bSYann Gautier #include <stm32mp1_clk.h> 21*8e2e5e8bSYann Gautier #include <stm32mp1_dt.h> 22*8e2e5e8bSYann Gautier #include <stm32mp1_rcc.h> 23*8e2e5e8bSYann Gautier #include <stm32mp1_reset.h> 24*8e2e5e8bSYann Gautier #include <string.h> 25*8e2e5e8bSYann Gautier #include <utils.h> 26*8e2e5e8bSYann Gautier 27*8e2e5e8bSYann Gautier /* Registers offsets */ 28*8e2e5e8bSYann Gautier #define SDMMC_POWER 0x00U 29*8e2e5e8bSYann Gautier #define SDMMC_CLKCR 0x04U 30*8e2e5e8bSYann Gautier #define SDMMC_ARGR 0x08U 31*8e2e5e8bSYann Gautier #define SDMMC_CMDR 0x0CU 32*8e2e5e8bSYann Gautier #define SDMMC_RESPCMDR 0x10U 33*8e2e5e8bSYann Gautier #define SDMMC_RESP1R 0x14U 34*8e2e5e8bSYann Gautier #define SDMMC_RESP2R 0x18U 35*8e2e5e8bSYann Gautier #define SDMMC_RESP3R 0x1CU 36*8e2e5e8bSYann Gautier #define SDMMC_RESP4R 0x20U 37*8e2e5e8bSYann Gautier #define SDMMC_DTIMER 0x24U 38*8e2e5e8bSYann Gautier #define SDMMC_DLENR 0x28U 39*8e2e5e8bSYann Gautier #define SDMMC_DCTRLR 0x2CU 40*8e2e5e8bSYann Gautier #define SDMMC_DCNTR 0x30U 41*8e2e5e8bSYann Gautier #define SDMMC_STAR 0x34U 42*8e2e5e8bSYann Gautier #define SDMMC_ICR 0x38U 43*8e2e5e8bSYann Gautier #define SDMMC_MASKR 0x3CU 44*8e2e5e8bSYann Gautier #define SDMMC_ACKTIMER 0x40U 45*8e2e5e8bSYann Gautier #define SDMMC_IDMACTRLR 0x50U 46*8e2e5e8bSYann Gautier #define SDMMC_IDMABSIZER 0x54U 47*8e2e5e8bSYann Gautier #define SDMMC_IDMABASE0R 0x58U 48*8e2e5e8bSYann Gautier #define SDMMC_IDMABASE1R 0x5CU 49*8e2e5e8bSYann Gautier #define SDMMC_FIFOR 0x80U 50*8e2e5e8bSYann Gautier 51*8e2e5e8bSYann Gautier /* SDMMC power control register */ 52*8e2e5e8bSYann Gautier #define SDMMC_POWER_PWRCTRL GENMASK(1, 0) 53*8e2e5e8bSYann Gautier #define SDMMC_POWER_DIRPOL BIT(4) 54*8e2e5e8bSYann Gautier 55*8e2e5e8bSYann Gautier /* SDMMC clock control register */ 56*8e2e5e8bSYann Gautier #define SDMMC_CLKCR_WIDBUS_4 BIT(14) 57*8e2e5e8bSYann Gautier #define SDMMC_CLKCR_WIDBUS_8 BIT(15) 58*8e2e5e8bSYann Gautier #define SDMMC_CLKCR_NEGEDGE BIT(16) 59*8e2e5e8bSYann Gautier #define SDMMC_CLKCR_HWFC_EN BIT(17) 60*8e2e5e8bSYann Gautier #define SDMMC_CLKCR_SELCLKRX_0 BIT(20) 61*8e2e5e8bSYann Gautier 62*8e2e5e8bSYann Gautier /* SDMMC command register */ 63*8e2e5e8bSYann Gautier #define SDMMC_CMDR_CMDTRANS BIT(6) 64*8e2e5e8bSYann Gautier #define SDMMC_CMDR_CMDSTOP BIT(7) 65*8e2e5e8bSYann Gautier #define SDMMC_CMDR_WAITRESP GENMASK(9, 8) 66*8e2e5e8bSYann Gautier #define SDMMC_CMDR_WAITRESP_SHORT BIT(8) 67*8e2e5e8bSYann Gautier #define SDMMC_CMDR_WAITRESP_SHORT_NOCRC BIT(9) 68*8e2e5e8bSYann Gautier #define SDMMC_CMDR_CPSMEN BIT(12) 69*8e2e5e8bSYann Gautier 70*8e2e5e8bSYann Gautier /* SDMMC data control register */ 71*8e2e5e8bSYann Gautier #define SDMMC_DCTRLR_DTEN BIT(0) 72*8e2e5e8bSYann Gautier #define SDMMC_DCTRLR_DTDIR BIT(1) 73*8e2e5e8bSYann Gautier #define SDMMC_DCTRLR_DTMODE GENMASK(3, 2) 74*8e2e5e8bSYann Gautier #define SDMMC_DCTRLR_DBLOCKSIZE_0 BIT(4) 75*8e2e5e8bSYann Gautier #define SDMMC_DCTRLR_DBLOCKSIZE_1 BIT(5) 76*8e2e5e8bSYann Gautier #define SDMMC_DCTRLR_DBLOCKSIZE_3 BIT(7) 77*8e2e5e8bSYann Gautier #define SDMMC_DCTRLR_DBLOCKSIZE GENMASK(7, 4) 78*8e2e5e8bSYann Gautier #define SDMMC_DCTRLR_FIFORST BIT(13) 79*8e2e5e8bSYann Gautier 80*8e2e5e8bSYann Gautier #define SDMMC_DCTRLR_CLEAR_MASK (SDMMC_DCTRLR_DTEN | \ 81*8e2e5e8bSYann Gautier SDMMC_DCTRLR_DTDIR | \ 82*8e2e5e8bSYann Gautier SDMMC_DCTRLR_DTMODE | \ 83*8e2e5e8bSYann Gautier SDMMC_DCTRLR_DBLOCKSIZE) 84*8e2e5e8bSYann Gautier #define SDMMC_DBLOCKSIZE_8 (SDMMC_DCTRLR_DBLOCKSIZE_0 | \ 85*8e2e5e8bSYann Gautier SDMMC_DCTRLR_DBLOCKSIZE_1) 86*8e2e5e8bSYann Gautier #define SDMMC_DBLOCKSIZE_512 (SDMMC_DCTRLR_DBLOCKSIZE_0 | \ 87*8e2e5e8bSYann Gautier SDMMC_DCTRLR_DBLOCKSIZE_3) 88*8e2e5e8bSYann Gautier 89*8e2e5e8bSYann Gautier /* SDMMC status register */ 90*8e2e5e8bSYann Gautier #define SDMMC_STAR_CCRCFAIL BIT(0) 91*8e2e5e8bSYann Gautier #define SDMMC_STAR_DCRCFAIL BIT(1) 92*8e2e5e8bSYann Gautier #define SDMMC_STAR_CTIMEOUT BIT(2) 93*8e2e5e8bSYann Gautier #define SDMMC_STAR_DTIMEOUT BIT(3) 94*8e2e5e8bSYann Gautier #define SDMMC_STAR_TXUNDERR BIT(4) 95*8e2e5e8bSYann Gautier #define SDMMC_STAR_RXOVERR BIT(5) 96*8e2e5e8bSYann Gautier #define SDMMC_STAR_CMDREND BIT(6) 97*8e2e5e8bSYann Gautier #define SDMMC_STAR_CMDSENT BIT(7) 98*8e2e5e8bSYann Gautier #define SDMMC_STAR_DATAEND BIT(8) 99*8e2e5e8bSYann Gautier #define SDMMC_STAR_DBCKEND BIT(10) 100*8e2e5e8bSYann Gautier #define SDMMC_STAR_DPSMACT BIT(11) 101*8e2e5e8bSYann Gautier #define SDMMC_STAR_RXFIFOHF BIT(15) 102*8e2e5e8bSYann Gautier #define SDMMC_STAR_RXFIFOE BIT(19) 103*8e2e5e8bSYann Gautier #define SDMMC_STAR_IDMATE BIT(27) 104*8e2e5e8bSYann Gautier #define SDMMC_STAR_IDMABTC BIT(28) 105*8e2e5e8bSYann Gautier 106*8e2e5e8bSYann Gautier /* SDMMC DMA control register */ 107*8e2e5e8bSYann Gautier #define SDMMC_IDMACTRLR_IDMAEN BIT(0) 108*8e2e5e8bSYann Gautier 109*8e2e5e8bSYann Gautier #define SDMMC_STATIC_FLAGS (SDMMC_STAR_CCRCFAIL | \ 110*8e2e5e8bSYann Gautier SDMMC_STAR_DCRCFAIL | \ 111*8e2e5e8bSYann Gautier SDMMC_STAR_CTIMEOUT | \ 112*8e2e5e8bSYann Gautier SDMMC_STAR_DTIMEOUT | \ 113*8e2e5e8bSYann Gautier SDMMC_STAR_TXUNDERR | \ 114*8e2e5e8bSYann Gautier SDMMC_STAR_RXOVERR | \ 115*8e2e5e8bSYann Gautier SDMMC_STAR_CMDREND | \ 116*8e2e5e8bSYann Gautier SDMMC_STAR_CMDSENT | \ 117*8e2e5e8bSYann Gautier SDMMC_STAR_DATAEND | \ 118*8e2e5e8bSYann Gautier SDMMC_STAR_DBCKEND | \ 119*8e2e5e8bSYann Gautier SDMMC_STAR_IDMATE | \ 120*8e2e5e8bSYann Gautier SDMMC_STAR_IDMABTC) 121*8e2e5e8bSYann Gautier 122*8e2e5e8bSYann Gautier #define TIMEOUT_10_MS (plat_get_syscnt_freq2() / 100U) 123*8e2e5e8bSYann Gautier #define TIMEOUT_1_S plat_get_syscnt_freq2() 124*8e2e5e8bSYann Gautier 125*8e2e5e8bSYann Gautier #define DT_SDMMC2_COMPAT "st,stm32-sdmmc2" 126*8e2e5e8bSYann Gautier 127*8e2e5e8bSYann Gautier static void stm32_sdmmc2_init(void); 128*8e2e5e8bSYann Gautier static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd); 129*8e2e5e8bSYann Gautier static int stm32_sdmmc2_send_cmd(struct mmc_cmd *cmd); 130*8e2e5e8bSYann Gautier static int stm32_sdmmc2_set_ios(unsigned int clk, unsigned int width); 131*8e2e5e8bSYann Gautier static int stm32_sdmmc2_prepare(int lba, uintptr_t buf, size_t size); 132*8e2e5e8bSYann Gautier static int stm32_sdmmc2_read(int lba, uintptr_t buf, size_t size); 133*8e2e5e8bSYann Gautier static int stm32_sdmmc2_write(int lba, uintptr_t buf, size_t size); 134*8e2e5e8bSYann Gautier 135*8e2e5e8bSYann Gautier static const struct mmc_ops stm32_sdmmc2_ops = { 136*8e2e5e8bSYann Gautier .init = stm32_sdmmc2_init, 137*8e2e5e8bSYann Gautier .send_cmd = stm32_sdmmc2_send_cmd, 138*8e2e5e8bSYann Gautier .set_ios = stm32_sdmmc2_set_ios, 139*8e2e5e8bSYann Gautier .prepare = stm32_sdmmc2_prepare, 140*8e2e5e8bSYann Gautier .read = stm32_sdmmc2_read, 141*8e2e5e8bSYann Gautier .write = stm32_sdmmc2_write, 142*8e2e5e8bSYann Gautier }; 143*8e2e5e8bSYann Gautier 144*8e2e5e8bSYann Gautier static struct stm32_sdmmc2_params sdmmc2_params; 145*8e2e5e8bSYann Gautier 146*8e2e5e8bSYann Gautier #pragma weak plat_sdmmc2_use_dma 147*8e2e5e8bSYann Gautier bool plat_sdmmc2_use_dma(unsigned int instance, unsigned int memory) 148*8e2e5e8bSYann Gautier { 149*8e2e5e8bSYann Gautier return false; 150*8e2e5e8bSYann Gautier } 151*8e2e5e8bSYann Gautier 152*8e2e5e8bSYann Gautier static void stm32_sdmmc2_init(void) 153*8e2e5e8bSYann Gautier { 154*8e2e5e8bSYann Gautier uint32_t clock_div; 155*8e2e5e8bSYann Gautier uintptr_t base = sdmmc2_params.reg_base; 156*8e2e5e8bSYann Gautier 157*8e2e5e8bSYann Gautier clock_div = div_round_up(sdmmc2_params.clk_rate, 158*8e2e5e8bSYann Gautier STM32MP1_MMC_INIT_FREQ * 2); 159*8e2e5e8bSYann Gautier 160*8e2e5e8bSYann Gautier mmio_write_32(base + SDMMC_CLKCR, SDMMC_CLKCR_HWFC_EN | clock_div | 161*8e2e5e8bSYann Gautier sdmmc2_params.negedge | 162*8e2e5e8bSYann Gautier sdmmc2_params.pin_ckin); 163*8e2e5e8bSYann Gautier 164*8e2e5e8bSYann Gautier mmio_write_32(base + SDMMC_POWER, 165*8e2e5e8bSYann Gautier SDMMC_POWER_PWRCTRL | sdmmc2_params.dirpol); 166*8e2e5e8bSYann Gautier 167*8e2e5e8bSYann Gautier mdelay(1); 168*8e2e5e8bSYann Gautier } 169*8e2e5e8bSYann Gautier 170*8e2e5e8bSYann Gautier static int stm32_sdmmc2_stop_transfer(void) 171*8e2e5e8bSYann Gautier { 172*8e2e5e8bSYann Gautier struct mmc_cmd cmd_stop; 173*8e2e5e8bSYann Gautier 174*8e2e5e8bSYann Gautier zeromem(&cmd_stop, sizeof(struct mmc_cmd)); 175*8e2e5e8bSYann Gautier 176*8e2e5e8bSYann Gautier cmd_stop.cmd_idx = MMC_CMD(12); 177*8e2e5e8bSYann Gautier cmd_stop.resp_type = MMC_RESPONSE_R1B; 178*8e2e5e8bSYann Gautier 179*8e2e5e8bSYann Gautier return stm32_sdmmc2_send_cmd(&cmd_stop); 180*8e2e5e8bSYann Gautier } 181*8e2e5e8bSYann Gautier 182*8e2e5e8bSYann Gautier static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd) 183*8e2e5e8bSYann Gautier { 184*8e2e5e8bSYann Gautier uint32_t flags_cmd, status; 185*8e2e5e8bSYann Gautier uint32_t flags_data = 0; 186*8e2e5e8bSYann Gautier int err = 0; 187*8e2e5e8bSYann Gautier uintptr_t base = sdmmc2_params.reg_base; 188*8e2e5e8bSYann Gautier unsigned int cmd_reg, arg_reg, start; 189*8e2e5e8bSYann Gautier 190*8e2e5e8bSYann Gautier if (cmd == NULL) { 191*8e2e5e8bSYann Gautier return -EINVAL; 192*8e2e5e8bSYann Gautier } 193*8e2e5e8bSYann Gautier 194*8e2e5e8bSYann Gautier flags_cmd = SDMMC_STAR_CTIMEOUT; 195*8e2e5e8bSYann Gautier arg_reg = cmd->cmd_arg; 196*8e2e5e8bSYann Gautier 197*8e2e5e8bSYann Gautier if ((mmio_read_32(base + SDMMC_CMDR) & SDMMC_CMDR_CPSMEN) != 0U) { 198*8e2e5e8bSYann Gautier mmio_write_32(base + SDMMC_CMDR, 0); 199*8e2e5e8bSYann Gautier } 200*8e2e5e8bSYann Gautier 201*8e2e5e8bSYann Gautier cmd_reg = cmd->cmd_idx | SDMMC_CMDR_CPSMEN; 202*8e2e5e8bSYann Gautier 203*8e2e5e8bSYann Gautier if (cmd->resp_type == 0U) { 204*8e2e5e8bSYann Gautier flags_cmd |= SDMMC_STAR_CMDSENT; 205*8e2e5e8bSYann Gautier } 206*8e2e5e8bSYann Gautier 207*8e2e5e8bSYann Gautier if ((cmd->resp_type & MMC_RSP_48) != 0U) { 208*8e2e5e8bSYann Gautier if ((cmd->resp_type & MMC_RSP_136) != 0U) { 209*8e2e5e8bSYann Gautier flags_cmd |= SDMMC_STAR_CMDREND; 210*8e2e5e8bSYann Gautier cmd_reg |= SDMMC_CMDR_WAITRESP; 211*8e2e5e8bSYann Gautier } else if ((cmd->resp_type & MMC_RSP_CRC) != 0U) { 212*8e2e5e8bSYann Gautier flags_cmd |= SDMMC_STAR_CMDREND | SDMMC_STAR_CCRCFAIL; 213*8e2e5e8bSYann Gautier cmd_reg |= SDMMC_CMDR_WAITRESP_SHORT; 214*8e2e5e8bSYann Gautier } else { 215*8e2e5e8bSYann Gautier flags_cmd |= SDMMC_STAR_CMDREND; 216*8e2e5e8bSYann Gautier cmd_reg |= SDMMC_CMDR_WAITRESP_SHORT_NOCRC; 217*8e2e5e8bSYann Gautier } 218*8e2e5e8bSYann Gautier } 219*8e2e5e8bSYann Gautier 220*8e2e5e8bSYann Gautier switch (cmd->cmd_idx) { 221*8e2e5e8bSYann Gautier case MMC_CMD(1): 222*8e2e5e8bSYann Gautier arg_reg |= OCR_POWERUP; 223*8e2e5e8bSYann Gautier break; 224*8e2e5e8bSYann Gautier case MMC_CMD(8): 225*8e2e5e8bSYann Gautier if (sdmmc2_params.device_info->mmc_dev_type == MMC_IS_EMMC) { 226*8e2e5e8bSYann Gautier cmd_reg |= SDMMC_CMDR_CMDTRANS; 227*8e2e5e8bSYann Gautier } 228*8e2e5e8bSYann Gautier break; 229*8e2e5e8bSYann Gautier case MMC_CMD(12): 230*8e2e5e8bSYann Gautier cmd_reg |= SDMMC_CMDR_CMDSTOP; 231*8e2e5e8bSYann Gautier break; 232*8e2e5e8bSYann Gautier case MMC_CMD(17): 233*8e2e5e8bSYann Gautier case MMC_CMD(18): 234*8e2e5e8bSYann Gautier cmd_reg |= SDMMC_CMDR_CMDTRANS; 235*8e2e5e8bSYann Gautier if (sdmmc2_params.use_dma) { 236*8e2e5e8bSYann Gautier flags_data |= SDMMC_STAR_DCRCFAIL | 237*8e2e5e8bSYann Gautier SDMMC_STAR_DTIMEOUT | 238*8e2e5e8bSYann Gautier SDMMC_STAR_DATAEND | 239*8e2e5e8bSYann Gautier SDMMC_STAR_RXOVERR | 240*8e2e5e8bSYann Gautier SDMMC_STAR_IDMATE; 241*8e2e5e8bSYann Gautier } 242*8e2e5e8bSYann Gautier break; 243*8e2e5e8bSYann Gautier case MMC_ACMD(41): 244*8e2e5e8bSYann Gautier arg_reg |= OCR_3_2_3_3 | OCR_3_3_3_4; 245*8e2e5e8bSYann Gautier break; 246*8e2e5e8bSYann Gautier case MMC_ACMD(51): 247*8e2e5e8bSYann Gautier cmd_reg |= SDMMC_CMDR_CMDTRANS; 248*8e2e5e8bSYann Gautier if (sdmmc2_params.use_dma) { 249*8e2e5e8bSYann Gautier flags_data |= SDMMC_STAR_DCRCFAIL | 250*8e2e5e8bSYann Gautier SDMMC_STAR_DTIMEOUT | 251*8e2e5e8bSYann Gautier SDMMC_STAR_DATAEND | 252*8e2e5e8bSYann Gautier SDMMC_STAR_RXOVERR | 253*8e2e5e8bSYann Gautier SDMMC_STAR_IDMATE | 254*8e2e5e8bSYann Gautier SDMMC_STAR_DBCKEND; 255*8e2e5e8bSYann Gautier } 256*8e2e5e8bSYann Gautier break; 257*8e2e5e8bSYann Gautier default: 258*8e2e5e8bSYann Gautier break; 259*8e2e5e8bSYann Gautier } 260*8e2e5e8bSYann Gautier 261*8e2e5e8bSYann Gautier if ((cmd->resp_type & MMC_RSP_BUSY) != 0U) { 262*8e2e5e8bSYann Gautier mmio_write_32(base + SDMMC_DTIMER, UINT32_MAX); 263*8e2e5e8bSYann Gautier } 264*8e2e5e8bSYann Gautier 265*8e2e5e8bSYann Gautier mmio_write_32(base + SDMMC_ARGR, arg_reg); 266*8e2e5e8bSYann Gautier 267*8e2e5e8bSYann Gautier mmio_write_32(base + SDMMC_CMDR, cmd_reg); 268*8e2e5e8bSYann Gautier 269*8e2e5e8bSYann Gautier start = get_timer(0); 270*8e2e5e8bSYann Gautier 271*8e2e5e8bSYann Gautier do { 272*8e2e5e8bSYann Gautier status = mmio_read_32(base + SDMMC_STAR); 273*8e2e5e8bSYann Gautier 274*8e2e5e8bSYann Gautier if (get_timer(start) > TIMEOUT_10_MS) { 275*8e2e5e8bSYann Gautier err = -ETIMEDOUT; 276*8e2e5e8bSYann Gautier ERROR("%s: timeout 10ms (cmd = %d,status = %x)\n", 277*8e2e5e8bSYann Gautier __func__, cmd->cmd_idx, status); 278*8e2e5e8bSYann Gautier break; 279*8e2e5e8bSYann Gautier } 280*8e2e5e8bSYann Gautier } while ((status & flags_cmd) == 0U); 281*8e2e5e8bSYann Gautier 282*8e2e5e8bSYann Gautier if (((status & (SDMMC_STAR_CTIMEOUT | SDMMC_STAR_CCRCFAIL)) != 0U) && 283*8e2e5e8bSYann Gautier (err == 0)) { 284*8e2e5e8bSYann Gautier if ((status & SDMMC_STAR_CTIMEOUT) != 0U) { 285*8e2e5e8bSYann Gautier err = -ETIMEDOUT; 286*8e2e5e8bSYann Gautier /* 287*8e2e5e8bSYann Gautier * Those timeouts can occur, and framework will handle 288*8e2e5e8bSYann Gautier * the retries. CMD8 is expected to return this timeout 289*8e2e5e8bSYann Gautier * for eMMC 290*8e2e5e8bSYann Gautier */ 291*8e2e5e8bSYann Gautier if (!((cmd->cmd_idx == MMC_CMD(1)) || 292*8e2e5e8bSYann Gautier (cmd->cmd_idx == MMC_CMD(13)) || 293*8e2e5e8bSYann Gautier ((cmd->cmd_idx == MMC_CMD(8)) && 294*8e2e5e8bSYann Gautier (cmd->resp_type == MMC_RESPONSE_R7)))) { 295*8e2e5e8bSYann Gautier ERROR("%s: CTIMEOUT (cmd = %d,status = %x)\n", 296*8e2e5e8bSYann Gautier __func__, cmd->cmd_idx, status); 297*8e2e5e8bSYann Gautier } 298*8e2e5e8bSYann Gautier } else { 299*8e2e5e8bSYann Gautier err = -EIO; 300*8e2e5e8bSYann Gautier ERROR("%s: CRCFAIL (cmd = %d,status = %x)\n", 301*8e2e5e8bSYann Gautier __func__, cmd->cmd_idx, status); 302*8e2e5e8bSYann Gautier } 303*8e2e5e8bSYann Gautier } 304*8e2e5e8bSYann Gautier 305*8e2e5e8bSYann Gautier if (((cmd_reg & SDMMC_CMDR_WAITRESP) != 0U) && (err == 0)) { 306*8e2e5e8bSYann Gautier if ((cmd->cmd_idx == MMC_CMD(9)) && 307*8e2e5e8bSYann Gautier ((cmd_reg & SDMMC_CMDR_WAITRESP) == SDMMC_CMDR_WAITRESP)) { 308*8e2e5e8bSYann Gautier /* Need to invert response to match CSD structure */ 309*8e2e5e8bSYann Gautier cmd->resp_data[0] = mmio_read_32(base + SDMMC_RESP4R); 310*8e2e5e8bSYann Gautier cmd->resp_data[1] = mmio_read_32(base + SDMMC_RESP3R); 311*8e2e5e8bSYann Gautier cmd->resp_data[2] = mmio_read_32(base + SDMMC_RESP2R); 312*8e2e5e8bSYann Gautier cmd->resp_data[3] = mmio_read_32(base + SDMMC_RESP1R); 313*8e2e5e8bSYann Gautier } else { 314*8e2e5e8bSYann Gautier cmd->resp_data[0] = mmio_read_32(base + SDMMC_RESP1R); 315*8e2e5e8bSYann Gautier if ((cmd_reg & SDMMC_CMDR_WAITRESP) == 316*8e2e5e8bSYann Gautier SDMMC_CMDR_WAITRESP) { 317*8e2e5e8bSYann Gautier cmd->resp_data[1] = mmio_read_32(base + 318*8e2e5e8bSYann Gautier SDMMC_RESP2R); 319*8e2e5e8bSYann Gautier cmd->resp_data[2] = mmio_read_32(base + 320*8e2e5e8bSYann Gautier SDMMC_RESP3R); 321*8e2e5e8bSYann Gautier cmd->resp_data[3] = mmio_read_32(base + 322*8e2e5e8bSYann Gautier SDMMC_RESP4R); 323*8e2e5e8bSYann Gautier } 324*8e2e5e8bSYann Gautier } 325*8e2e5e8bSYann Gautier } 326*8e2e5e8bSYann Gautier 327*8e2e5e8bSYann Gautier if ((flags_data == 0U) || (err != 0)) { 328*8e2e5e8bSYann Gautier if (flags_data != 0U) { 329*8e2e5e8bSYann Gautier mmio_clrbits_32(base + SDMMC_CMDR, SDMMC_CMDR_CMDTRANS); 330*8e2e5e8bSYann Gautier } 331*8e2e5e8bSYann Gautier 332*8e2e5e8bSYann Gautier mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS); 333*8e2e5e8bSYann Gautier 334*8e2e5e8bSYann Gautier if ((err != 0) && (flags_data != 0U)) { 335*8e2e5e8bSYann Gautier return stm32_sdmmc2_stop_transfer(); 336*8e2e5e8bSYann Gautier } 337*8e2e5e8bSYann Gautier 338*8e2e5e8bSYann Gautier return err; 339*8e2e5e8bSYann Gautier } 340*8e2e5e8bSYann Gautier 341*8e2e5e8bSYann Gautier start = get_timer(0); 342*8e2e5e8bSYann Gautier 343*8e2e5e8bSYann Gautier do { 344*8e2e5e8bSYann Gautier status = mmio_read_32(base + SDMMC_STAR); 345*8e2e5e8bSYann Gautier 346*8e2e5e8bSYann Gautier if (get_timer(start) > TIMEOUT_10_MS) { 347*8e2e5e8bSYann Gautier ERROR("%s: timeout 10ms (cmd = %d,status = %x)\n", 348*8e2e5e8bSYann Gautier __func__, cmd->cmd_idx, status); 349*8e2e5e8bSYann Gautier err = -ETIMEDOUT; 350*8e2e5e8bSYann Gautier break; 351*8e2e5e8bSYann Gautier } 352*8e2e5e8bSYann Gautier } while ((status & flags_data) == 0U); 353*8e2e5e8bSYann Gautier 354*8e2e5e8bSYann Gautier if ((status & (SDMMC_STAR_DTIMEOUT | SDMMC_STAR_DCRCFAIL | 355*8e2e5e8bSYann Gautier SDMMC_STAR_TXUNDERR | SDMMC_STAR_RXOVERR | 356*8e2e5e8bSYann Gautier SDMMC_STAR_IDMATE)) != 0U) { 357*8e2e5e8bSYann Gautier ERROR("%s: Error flag (cmd = %d,status = %x)\n", __func__, 358*8e2e5e8bSYann Gautier cmd->cmd_idx, status); 359*8e2e5e8bSYann Gautier err = -EIO; 360*8e2e5e8bSYann Gautier } 361*8e2e5e8bSYann Gautier 362*8e2e5e8bSYann Gautier mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS); 363*8e2e5e8bSYann Gautier mmio_clrbits_32(base + SDMMC_CMDR, SDMMC_CMDR_CMDTRANS); 364*8e2e5e8bSYann Gautier 365*8e2e5e8bSYann Gautier if (err != 0) { 366*8e2e5e8bSYann Gautier return stm32_sdmmc2_stop_transfer(); 367*8e2e5e8bSYann Gautier } 368*8e2e5e8bSYann Gautier 369*8e2e5e8bSYann Gautier return err; 370*8e2e5e8bSYann Gautier } 371*8e2e5e8bSYann Gautier 372*8e2e5e8bSYann Gautier static int stm32_sdmmc2_send_cmd(struct mmc_cmd *cmd) 373*8e2e5e8bSYann Gautier { 374*8e2e5e8bSYann Gautier int8_t retry; 375*8e2e5e8bSYann Gautier int err = 0; 376*8e2e5e8bSYann Gautier 377*8e2e5e8bSYann Gautier assert(cmd != NULL); 378*8e2e5e8bSYann Gautier 379*8e2e5e8bSYann Gautier for (retry = 0; retry <= 3; retry++) { 380*8e2e5e8bSYann Gautier err = stm32_sdmmc2_send_cmd_req(cmd); 381*8e2e5e8bSYann Gautier if (err == 0) { 382*8e2e5e8bSYann Gautier return err; 383*8e2e5e8bSYann Gautier } 384*8e2e5e8bSYann Gautier 385*8e2e5e8bSYann Gautier if ((cmd->cmd_idx == MMC_CMD(1)) || 386*8e2e5e8bSYann Gautier (cmd->cmd_idx == MMC_CMD(13))) { 387*8e2e5e8bSYann Gautier return 0; /* Retry managed by framework */ 388*8e2e5e8bSYann Gautier } 389*8e2e5e8bSYann Gautier 390*8e2e5e8bSYann Gautier /* Command 8 is expected to fail for eMMC */ 391*8e2e5e8bSYann Gautier if (!(cmd->cmd_idx == MMC_CMD(8))) { 392*8e2e5e8bSYann Gautier WARN(" CMD%d, Retry: %d, Error: %d\n", 393*8e2e5e8bSYann Gautier cmd->cmd_idx, retry, err); 394*8e2e5e8bSYann Gautier } 395*8e2e5e8bSYann Gautier 396*8e2e5e8bSYann Gautier udelay(10); 397*8e2e5e8bSYann Gautier } 398*8e2e5e8bSYann Gautier 399*8e2e5e8bSYann Gautier return err; 400*8e2e5e8bSYann Gautier } 401*8e2e5e8bSYann Gautier 402*8e2e5e8bSYann Gautier static int stm32_sdmmc2_set_ios(unsigned int clk, unsigned int width) 403*8e2e5e8bSYann Gautier { 404*8e2e5e8bSYann Gautier uintptr_t base = sdmmc2_params.reg_base; 405*8e2e5e8bSYann Gautier uint32_t bus_cfg = 0; 406*8e2e5e8bSYann Gautier uint32_t clock_div, max_freq; 407*8e2e5e8bSYann Gautier uint32_t clk_rate = sdmmc2_params.clk_rate; 408*8e2e5e8bSYann Gautier uint32_t max_bus_freq = sdmmc2_params.device_info->max_bus_freq; 409*8e2e5e8bSYann Gautier 410*8e2e5e8bSYann Gautier switch (width) { 411*8e2e5e8bSYann Gautier case MMC_BUS_WIDTH_1: 412*8e2e5e8bSYann Gautier break; 413*8e2e5e8bSYann Gautier case MMC_BUS_WIDTH_4: 414*8e2e5e8bSYann Gautier bus_cfg |= SDMMC_CLKCR_WIDBUS_4; 415*8e2e5e8bSYann Gautier break; 416*8e2e5e8bSYann Gautier case MMC_BUS_WIDTH_8: 417*8e2e5e8bSYann Gautier bus_cfg |= SDMMC_CLKCR_WIDBUS_8; 418*8e2e5e8bSYann Gautier break; 419*8e2e5e8bSYann Gautier default: 420*8e2e5e8bSYann Gautier panic(); 421*8e2e5e8bSYann Gautier break; 422*8e2e5e8bSYann Gautier } 423*8e2e5e8bSYann Gautier 424*8e2e5e8bSYann Gautier if (sdmmc2_params.device_info->mmc_dev_type == MMC_IS_EMMC) { 425*8e2e5e8bSYann Gautier if (max_bus_freq >= 52000000U) { 426*8e2e5e8bSYann Gautier max_freq = STM32MP1_EMMC_HIGH_SPEED_MAX_FREQ; 427*8e2e5e8bSYann Gautier } else { 428*8e2e5e8bSYann Gautier max_freq = STM32MP1_EMMC_NORMAL_SPEED_MAX_FREQ; 429*8e2e5e8bSYann Gautier } 430*8e2e5e8bSYann Gautier } else { 431*8e2e5e8bSYann Gautier if (max_bus_freq >= 50000000U) { 432*8e2e5e8bSYann Gautier max_freq = STM32MP1_SD_HIGH_SPEED_MAX_FREQ; 433*8e2e5e8bSYann Gautier } else { 434*8e2e5e8bSYann Gautier max_freq = STM32MP1_SD_NORMAL_SPEED_MAX_FREQ; 435*8e2e5e8bSYann Gautier } 436*8e2e5e8bSYann Gautier } 437*8e2e5e8bSYann Gautier 438*8e2e5e8bSYann Gautier clock_div = div_round_up(clk_rate, max_freq * 2); 439*8e2e5e8bSYann Gautier 440*8e2e5e8bSYann Gautier mmio_write_32(base + SDMMC_CLKCR, 441*8e2e5e8bSYann Gautier SDMMC_CLKCR_HWFC_EN | clock_div | bus_cfg | 442*8e2e5e8bSYann Gautier sdmmc2_params.negedge | 443*8e2e5e8bSYann Gautier sdmmc2_params.pin_ckin); 444*8e2e5e8bSYann Gautier 445*8e2e5e8bSYann Gautier return 0; 446*8e2e5e8bSYann Gautier } 447*8e2e5e8bSYann Gautier 448*8e2e5e8bSYann Gautier static int stm32_sdmmc2_prepare(int lba, uintptr_t buf, size_t size) 449*8e2e5e8bSYann Gautier { 450*8e2e5e8bSYann Gautier struct mmc_cmd cmd; 451*8e2e5e8bSYann Gautier int ret; 452*8e2e5e8bSYann Gautier uintptr_t base = sdmmc2_params.reg_base; 453*8e2e5e8bSYann Gautier uint32_t data_ctrl = SDMMC_DCTRLR_DTDIR; 454*8e2e5e8bSYann Gautier 455*8e2e5e8bSYann Gautier if (size == 8U) { 456*8e2e5e8bSYann Gautier data_ctrl |= SDMMC_DBLOCKSIZE_8; 457*8e2e5e8bSYann Gautier } else { 458*8e2e5e8bSYann Gautier data_ctrl |= SDMMC_DBLOCKSIZE_512; 459*8e2e5e8bSYann Gautier } 460*8e2e5e8bSYann Gautier 461*8e2e5e8bSYann Gautier sdmmc2_params.use_dma = plat_sdmmc2_use_dma(base, buf); 462*8e2e5e8bSYann Gautier 463*8e2e5e8bSYann Gautier if (sdmmc2_params.use_dma) { 464*8e2e5e8bSYann Gautier inv_dcache_range(buf, size); 465*8e2e5e8bSYann Gautier } 466*8e2e5e8bSYann Gautier 467*8e2e5e8bSYann Gautier /* Prepare CMD 16*/ 468*8e2e5e8bSYann Gautier mmio_write_32(base + SDMMC_DTIMER, UINT32_MAX); 469*8e2e5e8bSYann Gautier 470*8e2e5e8bSYann Gautier mmio_write_32(base + SDMMC_DLENR, 0); 471*8e2e5e8bSYann Gautier 472*8e2e5e8bSYann Gautier mmio_clrsetbits_32(base + SDMMC_DCTRLR, 473*8e2e5e8bSYann Gautier SDMMC_DCTRLR_CLEAR_MASK, SDMMC_DCTRLR_DTDIR); 474*8e2e5e8bSYann Gautier 475*8e2e5e8bSYann Gautier zeromem(&cmd, sizeof(struct mmc_cmd)); 476*8e2e5e8bSYann Gautier 477*8e2e5e8bSYann Gautier cmd.cmd_idx = MMC_CMD(16); 478*8e2e5e8bSYann Gautier if (size > MMC_BLOCK_SIZE) { 479*8e2e5e8bSYann Gautier cmd.cmd_arg = MMC_BLOCK_SIZE; 480*8e2e5e8bSYann Gautier } else { 481*8e2e5e8bSYann Gautier cmd.cmd_arg = size; 482*8e2e5e8bSYann Gautier } 483*8e2e5e8bSYann Gautier 484*8e2e5e8bSYann Gautier cmd.resp_type = MMC_RESPONSE_R1; 485*8e2e5e8bSYann Gautier 486*8e2e5e8bSYann Gautier ret = stm32_sdmmc2_send_cmd(&cmd); 487*8e2e5e8bSYann Gautier if (ret != 0) { 488*8e2e5e8bSYann Gautier ERROR("CMD16 failed\n"); 489*8e2e5e8bSYann Gautier return ret; 490*8e2e5e8bSYann Gautier } 491*8e2e5e8bSYann Gautier 492*8e2e5e8bSYann Gautier /* Prepare data command */ 493*8e2e5e8bSYann Gautier mmio_write_32(base + SDMMC_DTIMER, UINT32_MAX); 494*8e2e5e8bSYann Gautier 495*8e2e5e8bSYann Gautier mmio_write_32(base + SDMMC_DLENR, size); 496*8e2e5e8bSYann Gautier 497*8e2e5e8bSYann Gautier if (sdmmc2_params.use_dma) { 498*8e2e5e8bSYann Gautier mmio_write_32(base + SDMMC_IDMACTRLR, 499*8e2e5e8bSYann Gautier SDMMC_IDMACTRLR_IDMAEN); 500*8e2e5e8bSYann Gautier mmio_write_32(base + SDMMC_IDMABASE0R, buf); 501*8e2e5e8bSYann Gautier 502*8e2e5e8bSYann Gautier flush_dcache_range(buf, size); 503*8e2e5e8bSYann Gautier } 504*8e2e5e8bSYann Gautier 505*8e2e5e8bSYann Gautier mmio_clrsetbits_32(base + SDMMC_DCTRLR, 506*8e2e5e8bSYann Gautier SDMMC_DCTRLR_CLEAR_MASK, 507*8e2e5e8bSYann Gautier data_ctrl); 508*8e2e5e8bSYann Gautier 509*8e2e5e8bSYann Gautier return 0; 510*8e2e5e8bSYann Gautier } 511*8e2e5e8bSYann Gautier 512*8e2e5e8bSYann Gautier static int stm32_sdmmc2_read(int lba, uintptr_t buf, size_t size) 513*8e2e5e8bSYann Gautier { 514*8e2e5e8bSYann Gautier uint32_t error_flags = SDMMC_STAR_RXOVERR | SDMMC_STAR_DCRCFAIL | 515*8e2e5e8bSYann Gautier SDMMC_STAR_DTIMEOUT; 516*8e2e5e8bSYann Gautier uint32_t flags = error_flags | SDMMC_STAR_DATAEND; 517*8e2e5e8bSYann Gautier uint32_t status; 518*8e2e5e8bSYann Gautier uint32_t *buffer; 519*8e2e5e8bSYann Gautier uintptr_t base = sdmmc2_params.reg_base; 520*8e2e5e8bSYann Gautier uintptr_t fifo_reg = base + SDMMC_FIFOR; 521*8e2e5e8bSYann Gautier unsigned int start; 522*8e2e5e8bSYann Gautier int ret; 523*8e2e5e8bSYann Gautier 524*8e2e5e8bSYann Gautier /* Assert buf is 4 bytes aligned */ 525*8e2e5e8bSYann Gautier assert((buf & GENMASK(1, 0)) == 0U); 526*8e2e5e8bSYann Gautier 527*8e2e5e8bSYann Gautier buffer = (uint32_t *)buf; 528*8e2e5e8bSYann Gautier 529*8e2e5e8bSYann Gautier if (sdmmc2_params.use_dma) { 530*8e2e5e8bSYann Gautier inv_dcache_range(buf, size); 531*8e2e5e8bSYann Gautier 532*8e2e5e8bSYann Gautier return 0; 533*8e2e5e8bSYann Gautier } 534*8e2e5e8bSYann Gautier 535*8e2e5e8bSYann Gautier if (size <= MMC_BLOCK_SIZE) { 536*8e2e5e8bSYann Gautier flags |= SDMMC_STAR_DBCKEND; 537*8e2e5e8bSYann Gautier } 538*8e2e5e8bSYann Gautier 539*8e2e5e8bSYann Gautier start = get_timer(0); 540*8e2e5e8bSYann Gautier 541*8e2e5e8bSYann Gautier do { 542*8e2e5e8bSYann Gautier status = mmio_read_32(base + SDMMC_STAR); 543*8e2e5e8bSYann Gautier 544*8e2e5e8bSYann Gautier if ((status & error_flags) != 0U) { 545*8e2e5e8bSYann Gautier ERROR("%s: Read error (status = %x)\n", __func__, 546*8e2e5e8bSYann Gautier status); 547*8e2e5e8bSYann Gautier mmio_write_32(base + SDMMC_DCTRLR, 548*8e2e5e8bSYann Gautier SDMMC_DCTRLR_FIFORST); 549*8e2e5e8bSYann Gautier 550*8e2e5e8bSYann Gautier mmio_write_32(base + SDMMC_ICR, 551*8e2e5e8bSYann Gautier SDMMC_STATIC_FLAGS); 552*8e2e5e8bSYann Gautier 553*8e2e5e8bSYann Gautier ret = stm32_sdmmc2_stop_transfer(); 554*8e2e5e8bSYann Gautier if (ret != 0) { 555*8e2e5e8bSYann Gautier return ret; 556*8e2e5e8bSYann Gautier } 557*8e2e5e8bSYann Gautier 558*8e2e5e8bSYann Gautier return -EIO; 559*8e2e5e8bSYann Gautier } 560*8e2e5e8bSYann Gautier 561*8e2e5e8bSYann Gautier if (get_timer(start) > TIMEOUT_1_S) { 562*8e2e5e8bSYann Gautier ERROR("%s: timeout 1s (status = %x)\n", 563*8e2e5e8bSYann Gautier __func__, status); 564*8e2e5e8bSYann Gautier mmio_write_32(base + SDMMC_ICR, 565*8e2e5e8bSYann Gautier SDMMC_STATIC_FLAGS); 566*8e2e5e8bSYann Gautier 567*8e2e5e8bSYann Gautier ret = stm32_sdmmc2_stop_transfer(); 568*8e2e5e8bSYann Gautier if (ret != 0) { 569*8e2e5e8bSYann Gautier return ret; 570*8e2e5e8bSYann Gautier } 571*8e2e5e8bSYann Gautier 572*8e2e5e8bSYann Gautier return -ETIMEDOUT; 573*8e2e5e8bSYann Gautier } 574*8e2e5e8bSYann Gautier 575*8e2e5e8bSYann Gautier if (size < (8U * sizeof(uint32_t))) { 576*8e2e5e8bSYann Gautier if ((mmio_read_32(base + SDMMC_DCNTR) > 0U) && 577*8e2e5e8bSYann Gautier ((status & SDMMC_STAR_RXFIFOE) == 0U)) { 578*8e2e5e8bSYann Gautier *buffer = mmio_read_32(fifo_reg); 579*8e2e5e8bSYann Gautier buffer++; 580*8e2e5e8bSYann Gautier } 581*8e2e5e8bSYann Gautier } else if ((status & SDMMC_STAR_RXFIFOHF) != 0U) { 582*8e2e5e8bSYann Gautier uint32_t count; 583*8e2e5e8bSYann Gautier 584*8e2e5e8bSYann Gautier /* Read data from SDMMC Rx FIFO */ 585*8e2e5e8bSYann Gautier for (count = 0; count < 8U; count++) { 586*8e2e5e8bSYann Gautier *buffer = mmio_read_32(fifo_reg); 587*8e2e5e8bSYann Gautier buffer++; 588*8e2e5e8bSYann Gautier } 589*8e2e5e8bSYann Gautier } 590*8e2e5e8bSYann Gautier } while ((status & flags) == 0U); 591*8e2e5e8bSYann Gautier 592*8e2e5e8bSYann Gautier mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS); 593*8e2e5e8bSYann Gautier 594*8e2e5e8bSYann Gautier if ((status & SDMMC_STAR_DPSMACT) != 0U) { 595*8e2e5e8bSYann Gautier WARN("%s: DPSMACT=1, send stop\n", __func__); 596*8e2e5e8bSYann Gautier return stm32_sdmmc2_stop_transfer(); 597*8e2e5e8bSYann Gautier } 598*8e2e5e8bSYann Gautier 599*8e2e5e8bSYann Gautier return 0; 600*8e2e5e8bSYann Gautier } 601*8e2e5e8bSYann Gautier 602*8e2e5e8bSYann Gautier static int stm32_sdmmc2_write(int lba, uintptr_t buf, size_t size) 603*8e2e5e8bSYann Gautier { 604*8e2e5e8bSYann Gautier return 0; 605*8e2e5e8bSYann Gautier } 606*8e2e5e8bSYann Gautier 607*8e2e5e8bSYann Gautier static int stm32_sdmmc2_dt_get_config(void) 608*8e2e5e8bSYann Gautier { 609*8e2e5e8bSYann Gautier int sdmmc_node; 610*8e2e5e8bSYann Gautier void *fdt = NULL; 611*8e2e5e8bSYann Gautier const fdt32_t *cuint; 612*8e2e5e8bSYann Gautier 613*8e2e5e8bSYann Gautier if (fdt_get_address(&fdt) == 0) { 614*8e2e5e8bSYann Gautier return -FDT_ERR_NOTFOUND; 615*8e2e5e8bSYann Gautier } 616*8e2e5e8bSYann Gautier 617*8e2e5e8bSYann Gautier if (fdt == NULL) { 618*8e2e5e8bSYann Gautier return -FDT_ERR_NOTFOUND; 619*8e2e5e8bSYann Gautier } 620*8e2e5e8bSYann Gautier 621*8e2e5e8bSYann Gautier sdmmc_node = fdt_node_offset_by_compatible(fdt, -1, DT_SDMMC2_COMPAT); 622*8e2e5e8bSYann Gautier 623*8e2e5e8bSYann Gautier while (sdmmc_node != -FDT_ERR_NOTFOUND) { 624*8e2e5e8bSYann Gautier cuint = fdt_getprop(fdt, sdmmc_node, "reg", NULL); 625*8e2e5e8bSYann Gautier if (cuint == NULL) { 626*8e2e5e8bSYann Gautier continue; 627*8e2e5e8bSYann Gautier } 628*8e2e5e8bSYann Gautier 629*8e2e5e8bSYann Gautier if (fdt32_to_cpu(*cuint) == sdmmc2_params.reg_base) { 630*8e2e5e8bSYann Gautier break; 631*8e2e5e8bSYann Gautier } 632*8e2e5e8bSYann Gautier 633*8e2e5e8bSYann Gautier sdmmc_node = fdt_node_offset_by_compatible(fdt, sdmmc_node, 634*8e2e5e8bSYann Gautier DT_SDMMC2_COMPAT); 635*8e2e5e8bSYann Gautier } 636*8e2e5e8bSYann Gautier 637*8e2e5e8bSYann Gautier if (sdmmc_node == -FDT_ERR_NOTFOUND) { 638*8e2e5e8bSYann Gautier return -FDT_ERR_NOTFOUND; 639*8e2e5e8bSYann Gautier } 640*8e2e5e8bSYann Gautier 641*8e2e5e8bSYann Gautier if (fdt_check_status(sdmmc_node) == 0) { 642*8e2e5e8bSYann Gautier return -FDT_ERR_NOTFOUND; 643*8e2e5e8bSYann Gautier } 644*8e2e5e8bSYann Gautier 645*8e2e5e8bSYann Gautier if (dt_set_pinctrl_config(sdmmc_node) != 0) { 646*8e2e5e8bSYann Gautier return -FDT_ERR_BADVALUE; 647*8e2e5e8bSYann Gautier } 648*8e2e5e8bSYann Gautier 649*8e2e5e8bSYann Gautier cuint = fdt_getprop(fdt, sdmmc_node, "clocks", NULL); 650*8e2e5e8bSYann Gautier if (cuint == NULL) { 651*8e2e5e8bSYann Gautier return -FDT_ERR_NOTFOUND; 652*8e2e5e8bSYann Gautier } 653*8e2e5e8bSYann Gautier 654*8e2e5e8bSYann Gautier cuint++; 655*8e2e5e8bSYann Gautier sdmmc2_params.clock_id = fdt32_to_cpu(*cuint); 656*8e2e5e8bSYann Gautier 657*8e2e5e8bSYann Gautier cuint = fdt_getprop(fdt, sdmmc_node, "resets", NULL); 658*8e2e5e8bSYann Gautier if (cuint == NULL) { 659*8e2e5e8bSYann Gautier return -FDT_ERR_NOTFOUND; 660*8e2e5e8bSYann Gautier } 661*8e2e5e8bSYann Gautier 662*8e2e5e8bSYann Gautier cuint++; 663*8e2e5e8bSYann Gautier sdmmc2_params.reset_id = fdt32_to_cpu(*cuint); 664*8e2e5e8bSYann Gautier 665*8e2e5e8bSYann Gautier if ((fdt_getprop(fdt, sdmmc_node, "st,pin-ckin", NULL)) != NULL) { 666*8e2e5e8bSYann Gautier sdmmc2_params.pin_ckin = SDMMC_CLKCR_SELCLKRX_0; 667*8e2e5e8bSYann Gautier } 668*8e2e5e8bSYann Gautier 669*8e2e5e8bSYann Gautier if ((fdt_getprop(fdt, sdmmc_node, "st,dirpol", NULL)) != NULL) { 670*8e2e5e8bSYann Gautier sdmmc2_params.dirpol = SDMMC_POWER_DIRPOL; 671*8e2e5e8bSYann Gautier } 672*8e2e5e8bSYann Gautier 673*8e2e5e8bSYann Gautier if ((fdt_getprop(fdt, sdmmc_node, "st,negedge", NULL)) != NULL) { 674*8e2e5e8bSYann Gautier sdmmc2_params.negedge = SDMMC_CLKCR_NEGEDGE; 675*8e2e5e8bSYann Gautier } 676*8e2e5e8bSYann Gautier 677*8e2e5e8bSYann Gautier cuint = fdt_getprop(fdt, sdmmc_node, "bus-width", NULL); 678*8e2e5e8bSYann Gautier if (cuint != NULL) { 679*8e2e5e8bSYann Gautier switch (fdt32_to_cpu(*cuint)) { 680*8e2e5e8bSYann Gautier case 4: 681*8e2e5e8bSYann Gautier sdmmc2_params.bus_width = MMC_BUS_WIDTH_4; 682*8e2e5e8bSYann Gautier break; 683*8e2e5e8bSYann Gautier 684*8e2e5e8bSYann Gautier case 8: 685*8e2e5e8bSYann Gautier sdmmc2_params.bus_width = MMC_BUS_WIDTH_8; 686*8e2e5e8bSYann Gautier break; 687*8e2e5e8bSYann Gautier 688*8e2e5e8bSYann Gautier default: 689*8e2e5e8bSYann Gautier break; 690*8e2e5e8bSYann Gautier } 691*8e2e5e8bSYann Gautier } 692*8e2e5e8bSYann Gautier 693*8e2e5e8bSYann Gautier return 0; 694*8e2e5e8bSYann Gautier } 695*8e2e5e8bSYann Gautier 696*8e2e5e8bSYann Gautier unsigned long long stm32_sdmmc2_mmc_get_device_size(void) 697*8e2e5e8bSYann Gautier { 698*8e2e5e8bSYann Gautier return sdmmc2_params.device_info->device_size; 699*8e2e5e8bSYann Gautier } 700*8e2e5e8bSYann Gautier 701*8e2e5e8bSYann Gautier int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params) 702*8e2e5e8bSYann Gautier { 703*8e2e5e8bSYann Gautier int ret; 704*8e2e5e8bSYann Gautier 705*8e2e5e8bSYann Gautier assert((params != NULL) && 706*8e2e5e8bSYann Gautier ((params->reg_base & MMC_BLOCK_MASK) == 0U) && 707*8e2e5e8bSYann Gautier ((params->bus_width == MMC_BUS_WIDTH_1) || 708*8e2e5e8bSYann Gautier (params->bus_width == MMC_BUS_WIDTH_4) || 709*8e2e5e8bSYann Gautier (params->bus_width == MMC_BUS_WIDTH_8))); 710*8e2e5e8bSYann Gautier 711*8e2e5e8bSYann Gautier memcpy(&sdmmc2_params, params, sizeof(struct stm32_sdmmc2_params)); 712*8e2e5e8bSYann Gautier 713*8e2e5e8bSYann Gautier if (stm32_sdmmc2_dt_get_config() != 0) { 714*8e2e5e8bSYann Gautier ERROR("%s: DT error\n", __func__); 715*8e2e5e8bSYann Gautier return -ENOMEM; 716*8e2e5e8bSYann Gautier } 717*8e2e5e8bSYann Gautier 718*8e2e5e8bSYann Gautier ret = stm32mp1_clk_enable(sdmmc2_params.clock_id); 719*8e2e5e8bSYann Gautier if (ret != 0) { 720*8e2e5e8bSYann Gautier ERROR("%s: clock %d failed\n", __func__, 721*8e2e5e8bSYann Gautier sdmmc2_params.clock_id); 722*8e2e5e8bSYann Gautier return ret; 723*8e2e5e8bSYann Gautier } 724*8e2e5e8bSYann Gautier 725*8e2e5e8bSYann Gautier stm32mp1_reset_assert(sdmmc2_params.reset_id); 726*8e2e5e8bSYann Gautier udelay(2); 727*8e2e5e8bSYann Gautier stm32mp1_reset_deassert(sdmmc2_params.reset_id); 728*8e2e5e8bSYann Gautier mdelay(1); 729*8e2e5e8bSYann Gautier 730*8e2e5e8bSYann Gautier sdmmc2_params.clk_rate = stm32mp1_clk_get_rate(sdmmc2_params.clock_id); 731*8e2e5e8bSYann Gautier 732*8e2e5e8bSYann Gautier return mmc_init(&stm32_sdmmc2_ops, sdmmc2_params.clk_rate, 733*8e2e5e8bSYann Gautier sdmmc2_params.bus_width, sdmmc2_params.flags, 734*8e2e5e8bSYann Gautier sdmmc2_params.device_info); 735*8e2e5e8bSYann Gautier } 736