1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * linux/drivers/mmc/sdio_ops.c 4 * 5 * Copyright 2006-2007 Pierre Ossman 6 */ 7 8 #include <linux/scatterlist.h> 9 10 #include <linux/mmc/host.h> 11 #include <linux/mmc/card.h> 12 #include <linux/mmc/mmc.h> 13 #include <linux/mmc/sdio.h> 14 15 #include "core.h" 16 #include "sdio_ops.h" 17 18 int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) 19 { 20 struct mmc_command cmd = {}; 21 int i, err = 0; 22 23 cmd.opcode = SD_IO_SEND_OP_COND; 24 cmd.arg = ocr; 25 cmd.flags = MMC_RSP_SPI_R4 | MMC_RSP_R4 | MMC_CMD_BCR; 26 27 for (i = 100; i; i--) { 28 err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); 29 if (err) 30 break; 31 32 /* if we're just probing, do a single pass */ 33 if (ocr == 0) 34 break; 35 36 /* otherwise wait until reset completes */ 37 if (mmc_host_is_spi(host)) { 38 /* 39 * Both R1_SPI_IDLE and MMC_CARD_BUSY indicate 40 * an initialized card under SPI, but some cards 41 * (Marvell's) only behave when looking at this 42 * one. 43 */ 44 if (cmd.resp[1] & MMC_CARD_BUSY) 45 break; 46 } else { 47 if (cmd.resp[0] & MMC_CARD_BUSY) 48 break; 49 } 50 51 err = -ETIMEDOUT; 52 53 mmc_delay(10); 54 } 55 56 if (rocr) 57 *rocr = cmd.resp[mmc_host_is_spi(host) ? 1 : 0]; 58 59 return err; 60 } 61 62 static int mmc_io_rw_direct_host(struct mmc_host *host, int write, unsigned fn, 63 unsigned addr, u8 in, u8 *out) 64 { 65 struct mmc_command cmd = {}; 66 int err; 67 68 if (fn > 7) 69 return -EINVAL; 70 71 /* sanity check */ 72 if (addr & ~0x1FFFF) 73 return -EINVAL; 74 75 cmd.opcode = SD_IO_RW_DIRECT; 76 cmd.arg = write ? 0x80000000 : 0x00000000; 77 cmd.arg |= fn << 28; 78 cmd.arg |= (write && out) ? 0x08000000 : 0x00000000; 79 cmd.arg |= addr << 9; 80 cmd.arg |= in; 81 cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC; 82 83 err = mmc_wait_for_cmd(host, &cmd, 0); 84 if (err) 85 return err; 86 87 if (mmc_host_is_spi(host)) { 88 /* host driver already reported errors */ 89 } else { 90 if (cmd.resp[0] & R5_ERROR) 91 return -EIO; 92 if (cmd.resp[0] & R5_FUNCTION_NUMBER) 93 return -EINVAL; 94 if (cmd.resp[0] & R5_OUT_OF_RANGE) 95 return -ERANGE; 96 } 97 98 if (out) { 99 if (mmc_host_is_spi(host)) 100 *out = (cmd.resp[0] >> 8) & 0xFF; 101 else 102 *out = cmd.resp[0] & 0xFF; 103 } 104 105 return 0; 106 } 107 108 int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, 109 unsigned addr, u8 in, u8 *out) 110 { 111 return mmc_io_rw_direct_host(card->host, write, fn, addr, in, out); 112 } 113 114 int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, 115 unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz) 116 { 117 struct mmc_request mrq = {}; 118 struct mmc_command cmd = {}; 119 struct mmc_data data = {}; 120 struct scatterlist sg, *sg_ptr; 121 struct sg_table sgtable; 122 unsigned int nents, left_size, i; 123 unsigned int seg_size = card->host->max_seg_size; 124 int err; 125 126 WARN_ON(blksz == 0); 127 128 /* sanity check */ 129 if (addr & ~0x1FFFF) 130 return -EINVAL; 131 132 mrq.cmd = &cmd; 133 mrq.data = &data; 134 135 cmd.opcode = SD_IO_RW_EXTENDED; 136 cmd.arg = write ? 0x80000000 : 0x00000000; 137 cmd.arg |= fn << 28; 138 cmd.arg |= incr_addr ? 0x04000000 : 0x00000000; 139 cmd.arg |= addr << 9; 140 if (blocks == 0) 141 cmd.arg |= (blksz == 512) ? 0 : blksz; /* byte mode */ 142 else 143 cmd.arg |= 0x08000000 | blocks; /* block mode */ 144 cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC; 145 146 data.blksz = blksz; 147 /* Code in host drivers/fwk assumes that "blocks" always is >=1 */ 148 data.blocks = blocks ? blocks : 1; 149 data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; 150 151 left_size = data.blksz * data.blocks; 152 nents = DIV_ROUND_UP(left_size, seg_size); 153 if (nents > 1) { 154 if (sg_alloc_table(&sgtable, nents, GFP_KERNEL)) 155 return -ENOMEM; 156 157 data.sg = sgtable.sgl; 158 data.sg_len = nents; 159 160 for_each_sg(data.sg, sg_ptr, data.sg_len, i) { 161 sg_set_buf(sg_ptr, buf + i * seg_size, 162 min(seg_size, left_size)); 163 left_size -= seg_size; 164 } 165 } else { 166 data.sg = &sg; 167 data.sg_len = 1; 168 169 sg_init_one(&sg, buf, left_size); 170 } 171 172 mmc_set_data_timeout(&data, card); 173 174 mmc_pre_req(card->host, &mrq); 175 176 mmc_wait_for_req(card->host, &mrq); 177 178 if (cmd.error) 179 err = cmd.error; 180 else if (data.error) 181 err = data.error; 182 else if (mmc_host_is_spi(card->host)) 183 /* host driver already reported errors */ 184 err = 0; 185 else if (cmd.resp[0] & R5_ERROR) 186 err = -EIO; 187 else if (cmd.resp[0] & R5_FUNCTION_NUMBER) 188 err = -EINVAL; 189 else if (cmd.resp[0] & R5_OUT_OF_RANGE) 190 err = -ERANGE; 191 else 192 err = 0; 193 194 mmc_post_req(card->host, &mrq, err); 195 196 if (nents > 1) 197 sg_free_table(&sgtable); 198 199 return err; 200 } 201 202 int sdio_reset(struct mmc_host *host) 203 { 204 int ret; 205 u8 abort; 206 207 /* SDIO Simplified Specification V2.0, 4.4 Reset for SDIO */ 208 209 ret = mmc_io_rw_direct_host(host, 0, 0, SDIO_CCCR_ABORT, 0, &abort); 210 if (ret) 211 abort = 0x08; 212 else 213 abort |= 0x08; 214 215 return mmc_io_rw_direct_host(host, 1, 0, SDIO_CCCR_ABORT, abort, NULL); 216 } 217 218