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