sdio_ops.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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. #include <linux/err.h>
  12. #include <linux/device.h>
  13. #include <linux/pagemap.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/scatterlist.h>
  16. #include <linux/cardreader/sdio.h>
  17. #include <linux/cardreader/card_block.h>
  18. #include "sdio_ops.h"
  19. static int sdio_io_rw_direct_host(struct card_host *host, int write, unsigned fn,
  20. unsigned addr, u8 in, u8 *out)
  21. {
  22. struct card_blk_request brq;
  23. BUG_ON(!host);
  24. BUG_ON(fn > 7);
  25. /* sanity check */
  26. if (addr & ~0x1FFFF)
  27. return -EINVAL;
  28. if (write)
  29. brq.crq.cmd = WRITE;
  30. else
  31. brq.crq.cmd = READ;
  32. if (out)
  33. brq.crq.cmd |= READ_AFTER_WRITE;
  34. brq.crq.cmd |= SDIO_OPS_REG;
  35. brq.crq.buf = &in;
  36. brq.crq.back_buf = out;
  37. brq.card_data.lba = addr;
  38. brq.card_data.flags = fn;
  39. brq.card_data.blk_size = 1;
  40. brq.card_data.blk_nums = 1; // for read reg just one byte
  41. card_wait_for_req(host, &brq);
  42. return brq.card_data.error;
  43. }
  44. int sdio_io_rw_direct(struct memory_card *card, int write, unsigned fn,
  45. unsigned addr, u8 in, u8 *out)
  46. {
  47. BUG_ON(!card);
  48. card->host->card_busy = card;
  49. return sdio_io_rw_direct_host(card->host, write, fn, addr, in, out);
  50. }
  51. EXPORT_SYMBOL(sdio_io_rw_direct);
  52. int sdio_io_rw_extended(struct memory_card *card, int write, unsigned fn,
  53. unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz)
  54. {
  55. struct card_blk_request brq;
  56. BUG_ON(!card);
  57. BUG_ON(fn > 7);
  58. BUG_ON(blocks == 1 && blksz > 512);
  59. WARN_ON(blocks == 0);
  60. WARN_ON(blksz == 0);
  61. /* sanity check */
  62. if (addr & ~0x1FFFF)
  63. return -EINVAL;
  64. card->host->card_busy = card;
  65. if (write)
  66. brq.crq.cmd = WRITE;
  67. else
  68. brq.crq.cmd = READ;
  69. if (incr_addr)
  70. brq.crq.cmd |= SDIO_FIFO_ADDR;
  71. brq.crq.buf = buf;
  72. brq.card_data.lba = addr;
  73. brq.card_data.blk_size = blksz;
  74. brq.card_data.blk_nums = blocks;
  75. brq.card_data.flags = fn;
  76. card_wait_for_req(card->host, &brq);
  77. return brq.card_data.error;
  78. }
  79. EXPORT_SYMBOL(sdio_io_rw_extended);
  80. int sdio_reset(struct card_host *host)
  81. {
  82. int ret;
  83. u8 abort;
  84. /* SDIO Simplified Specification V2.0, 4.4 Reset for SDIO */
  85. host->card_busy = host->card;
  86. ret = sdio_io_rw_direct_host(host, 0, 0, SDIO_CCCR_ABORT, 0, &abort);
  87. if (ret)
  88. abort = 0x08;
  89. else
  90. abort |= 0x08;
  91. ret = sdio_io_rw_direct_host(host, 1, 0, SDIO_CCCR_ABORT, abort, NULL);
  92. return ret;
  93. }