aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorPierre Ossman <drzeus@drzeus.cx>2007-07-06 07:35:01 -0400
committerPierre Ossman <drzeus@drzeus.cx>2007-09-23 15:09:34 -0400
commit112c9db91ee6bf19eca7cbb6854be3127381c229 (patch)
treee2d45c7d18a4a218cc0716d7aef79aa04b73a498 /drivers/mmc
parent5ed334a1f8caaae98806d572f78c5802975ea20f (diff)
sdio: support IO_RW_EXTENDED
Support the multi-byte transfer operation, including handlers for common operations like writel()/readl(). Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/core/sdio_io.c184
-rw-r--r--drivers/mmc/core/sdio_ops.c57
-rw-r--r--drivers/mmc/core/sdio_ops.h2
3 files changed, 243 insertions, 0 deletions
diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c
index eb6c20935cef..ecdb77242e98 100644
--- a/drivers/mmc/core/sdio_io.c
+++ b/drivers/mmc/core/sdio_io.c
@@ -196,3 +196,187 @@ void sdio_writeb(struct sdio_func *func, unsigned char b, unsigned int addr,
196} 196}
197EXPORT_SYMBOL_GPL(sdio_writeb); 197EXPORT_SYMBOL_GPL(sdio_writeb);
198 198
199/**
200 * sdio_memcpy_fromio - read a chunk of memory from a SDIO function
201 * @func: SDIO function to access
202 * @dst: buffer to store the data
203 * @addr: address to begin reading from
204 * @count: number of bytes to read
205 *
206 * Reads up to 512 bytes from the address space of a given SDIO
207 * function. Return value indicates if the transfer succeeded or
208 * not.
209 */
210int sdio_memcpy_fromio(struct sdio_func *func, void *dst,
211 unsigned int addr, int count)
212{
213 return mmc_io_rw_extended(func->card, 0, func->num, addr, 0, dst,
214 count);
215}
216EXPORT_SYMBOL_GPL(sdio_memcpy_fromio);
217
218/**
219 * sdio_memcpy_toio - write a chunk of memory to a SDIO function
220 * @func: SDIO function to access
221 * @addr: address to start writing to
222 * @src: buffer that contains the data to write
223 * @count: number of bytes to write
224 *
225 * Writes up to 512 bytes to the address space of a given SDIO
226 * function. Return value indicates if the transfer succeeded or
227 * not.
228 */
229int sdio_memcpy_toio(struct sdio_func *func, unsigned int addr,
230 void *src, int count)
231{
232 return mmc_io_rw_extended(func->card, 1, func->num, addr, 0, src,
233 count);
234}
235EXPORT_SYMBOL_GPL(sdio_memcpy_toio);
236
237/**
238 * sdio_readsb - read from a FIFO on a SDIO function
239 * @func: SDIO function to access
240 * @dst: buffer to store the data
241 * @addr: address of (single byte) FIFO
242 * @count: number of bytes to read
243 *
244 * Reads up to 512 bytes from the specified FIFO of a given SDIO
245 * function. Return value indicates if the transfer succeeded or
246 * not.
247 */
248int sdio_readsb(struct sdio_func *func, void *dst, unsigned int addr,
249 int count)
250{
251 return mmc_io_rw_extended(func->card, 0, func->num, addr, 1, dst,
252 count);
253}
254
255EXPORT_SYMBOL_GPL(sdio_readsb);
256
257/**
258 * sdio_writesb - write to a FIFO of a SDIO function
259 * @func: SDIO function to access
260 * @addr: address of (single byte) FIFO
261 * @src: buffer that contains the data to write
262 * @count: number of bytes to write
263 *
264 * Writes up to 512 bytes to the specified FIFO of a given SDIO
265 * function. Return value indicates if the transfer succeeded or
266 * not.
267 */
268int sdio_writesb(struct sdio_func *func, unsigned int addr, void *src,
269 int count)
270{
271 return mmc_io_rw_extended(func->card, 1, func->num, addr, 1, src,
272 count);
273}
274EXPORT_SYMBOL_GPL(sdio_writesb);
275
276/**
277 * sdio_readw - read a 16 bit integer from a SDIO function
278 * @func: SDIO function to access
279 * @addr: address to read
280 * @err_ret: optional status value from transfer
281 *
282 * Reads a 16 bit integer from the address space of a given SDIO
283 * function. If there is a problem reading the address, 0xffff
284 * is returned and @err_ret will contain the error code.
285 */
286unsigned short sdio_readw(struct sdio_func *func, unsigned int addr,
287 int *err_ret)
288{
289 int ret;
290
291 if (err_ret)
292 *err_ret = 0;
293
294 ret = sdio_memcpy_fromio(func, func->tmpbuf, addr, 2);
295 if (ret) {
296 if (err_ret)
297 *err_ret = ret;
298 return 0xFFFF;
299 }
300
301 return le16_to_cpu(*(u16*)func->tmpbuf);
302}
303EXPORT_SYMBOL_GPL(sdio_readw);
304
305/**
306 * sdio_writew - write a 16 bit integer to a SDIO function
307 * @func: SDIO function to access
308 * @b: integer to write
309 * @addr: address to write to
310 * @err_ret: optional status value from transfer
311 *
312 * Writes a 16 bit integer to the address space of a given SDIO
313 * function. @err_ret will contain the status of the actual
314 * transfer.
315 */
316void sdio_writew(struct sdio_func *func, unsigned short b, unsigned int addr,
317 int *err_ret)
318{
319 int ret;
320
321 *(u16*)func->tmpbuf = cpu_to_le16(b);
322
323 ret = sdio_memcpy_toio(func, addr, func->tmpbuf, 2);
324 if (err_ret)
325 *err_ret = ret;
326}
327EXPORT_SYMBOL_GPL(sdio_writew);
328
329/**
330 * sdio_readl - read a 32 bit integer from a SDIO function
331 * @func: SDIO function to access
332 * @addr: address to read
333 * @err_ret: optional status value from transfer
334 *
335 * Reads a 32 bit integer from the address space of a given SDIO
336 * function. If there is a problem reading the address,
337 * 0xffffffff is returned and @err_ret will contain the error
338 * code.
339 */
340unsigned long sdio_readl(struct sdio_func *func, unsigned int addr,
341 int *err_ret)
342{
343 int ret;
344
345 if (err_ret)
346 *err_ret = 0;
347
348 ret = sdio_memcpy_fromio(func, func->tmpbuf, addr, 4);
349 if (ret) {
350 if (err_ret)
351 *err_ret = ret;
352 return 0xFFFFFFFF;
353 }
354
355 return le32_to_cpu(*(u32*)func->tmpbuf);
356}
357EXPORT_SYMBOL_GPL(sdio_readl);
358
359/**
360 * sdio_writel - write a 32 bit integer to a SDIO function
361 * @func: SDIO function to access
362 * @b: integer to write
363 * @addr: address to write to
364 * @err_ret: optional status value from transfer
365 *
366 * Writes a 32 bit integer to the address space of a given SDIO
367 * function. @err_ret will contain the status of the actual
368 * transfer.
369 */
370void sdio_writel(struct sdio_func *func, unsigned long b, unsigned int addr,
371 int *err_ret)
372{
373 int ret;
374
375 *(u32*)func->tmpbuf = cpu_to_le32(b);
376
377 ret = sdio_memcpy_toio(func, addr, func->tmpbuf, 4);
378 if (err_ret)
379 *err_ret = ret;
380}
381EXPORT_SYMBOL_GPL(sdio_writel);
382
diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c
index 31233f7b55cd..4f2c77139477 100644
--- a/drivers/mmc/core/sdio_ops.c
+++ b/drivers/mmc/core/sdio_ops.c
@@ -9,6 +9,9 @@
9 * your option) any later version. 9 * your option) any later version.
10 */ 10 */
11 11
12#include <asm/scatterlist.h>
13#include <linux/scatterlist.h>
14
12#include <linux/mmc/host.h> 15#include <linux/mmc/host.h>
13#include <linux/mmc/card.h> 16#include <linux/mmc/card.h>
14#include <linux/mmc/mmc.h> 17#include <linux/mmc/mmc.h>
@@ -84,3 +87,57 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
84 return 0; 87 return 0;
85} 88}
86 89
90int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
91 unsigned addr, int bang, u8 *buf, unsigned size)
92{
93 struct mmc_request mrq;
94 struct mmc_command cmd;
95 struct mmc_data data;
96 struct scatterlist sg;
97
98 BUG_ON(!card);
99 BUG_ON(fn > 7);
100 BUG_ON(size > 512);
101
102 memset(&mrq, 0, sizeof(struct mmc_request));
103 memset(&cmd, 0, sizeof(struct mmc_command));
104 memset(&data, 0, sizeof(struct mmc_data));
105
106 mrq.cmd = &cmd;
107 mrq.data = &data;
108
109 cmd.opcode = SD_IO_RW_EXTENDED;
110 cmd.arg = write ? 0x80000000 : 0x00000000;
111 cmd.arg |= fn << 28;
112 cmd.arg |= bang ? 0x00000000 : 0x04000000;
113 cmd.arg |= addr << 9;
114 cmd.arg |= (size == 512) ? 0 : size;
115 cmd.flags = MMC_RSP_R5 | MMC_CMD_ADTC;
116
117 data.blksz = size;
118 data.blocks = 1;
119 data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
120 data.sg = &sg;
121 data.sg_len = 1;
122
123 sg_init_one(&sg, buf, size);
124
125 mmc_set_data_timeout(&data, card);
126
127 mmc_wait_for_req(card->host, &mrq);
128
129 if (cmd.error)
130 return cmd.error;
131 if (data.error)
132 return data.error;
133
134 if (cmd.resp[0] & R5_ERROR)
135 return -EIO;
136 if (cmd.resp[0] & R5_FUNCTION_NUMBER)
137 return -EINVAL;
138 if (cmd.resp[0] & R5_OUT_OF_RANGE)
139 return -ERANGE;
140
141 return 0;
142}
143
diff --git a/drivers/mmc/core/sdio_ops.h b/drivers/mmc/core/sdio_ops.h
index f0e9d69e5ce8..1d42e4f366aa 100644
--- a/drivers/mmc/core/sdio_ops.h
+++ b/drivers/mmc/core/sdio_ops.h
@@ -15,6 +15,8 @@
15int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr); 15int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
16int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, 16int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
17 unsigned addr, u8 in, u8* out); 17 unsigned addr, u8 in, u8* out);
18int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
19 unsigned addr, int bang, u8 *data, unsigned size);
18 20
19#endif 21#endif
20 22