1 /* 2 * Copyright (c) 2022-2023, Intel Corporation. All rights reserved. 3 * Copyright (c) 2024, Altera Corporation. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 8 #include <assert.h> 9 #include <errno.h> 10 #include <stdbool.h> 11 #include <string.h> 12 13 #include <arch_helpers.h> 14 #include <common/debug.h> 15 #include <drivers/cadence/cdns_combo_phy.h> 16 #include <drivers/cadence/cdns_sdmmc.h> 17 #include <drivers/delay_timer.h> 18 #include <lib/mmio.h> 19 #include <lib/utils.h> 20 21 #include "sdmmc.h" 22 #include "socfpga_mailbox.h" 23 #include "wdt/watchdog.h" 24 25 static const struct mmc_ops *ops; 26 static unsigned int mmc_ocr_value; 27 static unsigned int mmc_flags; 28 static unsigned int rca; 29 30 extern const struct mmc_ops cdns_sdmmc_ops; 31 extern struct cdns_sdmmc_params cdns_params; 32 extern struct cdns_sdmmc_combo_phy sdmmc_combo_phy_reg; 33 extern struct cdns_sdmmc_sdhc sdmmc_sdhc_reg; 34 35 bool is_cmd23_enabled(void) 36 { 37 return ((mmc_flags & MMC_FLAG_CMD23) != 0U); 38 } 39 40 int sdmmc_send_cmd(unsigned int idx, unsigned int arg, 41 unsigned int r_type, unsigned int *r_data) 42 { 43 struct mmc_cmd cmd; 44 int ret; 45 46 zeromem(&cmd, sizeof(struct mmc_cmd)); 47 48 cmd.cmd_idx = idx; 49 cmd.cmd_arg = arg; 50 cmd.resp_type = r_type; 51 52 ret = ops->send_cmd(&cmd); 53 54 if ((ret == 0) && (r_data != NULL)) { 55 int i; 56 57 for (i = 0; i < 4; i++) { 58 *r_data = cmd.resp_data[i]; 59 r_data++; 60 } 61 } 62 63 if (ret != 0) { 64 VERBOSE("Send command %u error: %d\n", idx, ret); 65 } 66 67 return ret; 68 } 69 70 int sdmmc_device_state(void) 71 { 72 int retries = DEFAULT_SDMMC_MAX_RETRIES; 73 unsigned int resp_data[4]; 74 75 do { 76 int ret; 77 78 if (retries == 0) { 79 ERROR("CMD13 failed after %d retries\n", 80 DEFAULT_SDMMC_MAX_RETRIES); 81 return -EIO; 82 } 83 84 ret = sdmmc_send_cmd(MMC_CMD(13), rca << RCA_SHIFT_OFFSET, 85 MMC_RESPONSE_R1, &resp_data[0]); 86 if (ret != 0) { 87 retries--; 88 continue; 89 } 90 91 if ((resp_data[0] & STATUS_SWITCH_ERROR) != 0U) { 92 return -EIO; 93 } 94 95 retries--; 96 } while ((resp_data[0] & STATUS_READY_FOR_DATA) == 0U); 97 98 return MMC_GET_STATE(resp_data[0]); 99 } 100 101 size_t sdmmc_read_blocks(int lba, uintptr_t buf, size_t size) 102 { 103 mmc_read_blocks(lba, buf, size); 104 105 /* Restart watchdog for reading each chunk byte */ 106 watchdog_sw_rst(); 107 108 return size; 109 } 110 111 size_t sdmmc_write_blocks(int lba, const uintptr_t buf, size_t size) 112 { 113 int ret; 114 unsigned int cmd_idx, cmd_arg; 115 116 assert((ops != NULL) && 117 (ops->write != NULL) && 118 (size != 0U) && 119 ((buf & MMC_BLOCK_MASK) == 0U) && 120 ((size & MMC_BLOCK_MASK) == 0U)); 121 122 ret = ops->prepare(lba, buf, size); 123 if (ret != 0) { 124 return 0; 125 } 126 127 if (is_cmd23_enabled()) { 128 /* Set block count */ 129 ret = sdmmc_send_cmd(MMC_CMD(23), size / MMC_BLOCK_SIZE, 130 MMC_RESPONSE_R1, NULL); 131 if (ret != 0) { 132 return 0; 133 } 134 135 cmd_idx = MMC_CMD(25); 136 } else { 137 if (size > MMC_BLOCK_SIZE) { 138 cmd_idx = MMC_CMD(25); 139 } else { 140 cmd_idx = MMC_CMD(24); 141 } 142 } 143 144 if ((mmc_ocr_value & OCR_ACCESS_MODE_MASK) == OCR_BYTE_MODE) { 145 cmd_arg = lba * MMC_BLOCK_SIZE; 146 } else { 147 cmd_arg = lba; 148 } 149 150 ret = sdmmc_send_cmd(cmd_idx, cmd_arg, MMC_RESPONSE_R1, NULL); 151 if (ret != 0) { 152 return 0; 153 } 154 155 ret = ops->write(lba, buf, size); 156 if (ret != 0) { 157 return 0; 158 } 159 160 /* Wait buffer empty */ 161 do { 162 ret = sdmmc_device_state(); 163 if (ret < 0) { 164 return 0; 165 } 166 } while ((ret != MMC_STATE_TRAN) && (ret != MMC_STATE_RCV)); 167 168 if (!is_cmd23_enabled() && (size > MMC_BLOCK_SIZE)) { 169 ret = sdmmc_send_cmd(MMC_CMD(12), 0, MMC_RESPONSE_R1B, NULL); 170 if (ret != 0) { 171 return 0; 172 } 173 } 174 175 return size; 176 } 177