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