spi-sh-sci.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*
  2. * SH SCI SPI interface
  3. *
  4. * Copyright (c) 2008 Magnus Damm
  5. *
  6. * Based on S3C24XX GPIO based SPI driver, which is:
  7. * Copyright (c) 2006 Ben Dooks
  8. * Copyright (c) 2006 Simtec Electronics
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2 as
  12. * published by the Free Software Foundation.
  13. *
  14. */
  15. #include <linux/kernel.h>
  16. #include <linux/delay.h>
  17. #include <linux/spinlock.h>
  18. #include <linux/platform_device.h>
  19. #include <linux/spi/spi.h>
  20. #include <linux/spi/spi_bitbang.h>
  21. #include <linux/module.h>
  22. #include <asm/spi.h>
  23. #include <asm/io.h>
  24. struct sh_sci_spi {
  25. struct spi_bitbang bitbang;
  26. void __iomem *membase;
  27. unsigned char val;
  28. struct sh_spi_info *info;
  29. struct platform_device *dev;
  30. };
  31. #define SCSPTR(sp) (sp->membase + 0x1c)
  32. #define PIN_SCK (1 << 2)
  33. #define PIN_TXD (1 << 0)
  34. #define PIN_RXD PIN_TXD
  35. #define PIN_INIT ((1 << 1) | (1 << 3) | PIN_SCK | PIN_TXD)
  36. static inline void setbits(struct sh_sci_spi *sp, int bits, int on)
  37. {
  38. /*
  39. * We are the only user of SCSPTR so no locking is required.
  40. * Reading bit 2 and 0 in SCSPTR gives pin state as input.
  41. * Writing the same bits sets the output value.
  42. * This makes regular read-modify-write difficult so we
  43. * use sp->val to keep track of the latest register value.
  44. */
  45. if (on)
  46. sp->val |= bits;
  47. else
  48. sp->val &= ~bits;
  49. iowrite8(sp->val, SCSPTR(sp));
  50. }
  51. static inline void setsck(struct spi_device *dev, int on)
  52. {
  53. setbits(spi_master_get_devdata(dev->master), PIN_SCK, on);
  54. }
  55. static inline void setmosi(struct spi_device *dev, int on)
  56. {
  57. setbits(spi_master_get_devdata(dev->master), PIN_TXD, on);
  58. }
  59. static inline u32 getmiso(struct spi_device *dev)
  60. {
  61. struct sh_sci_spi *sp = spi_master_get_devdata(dev->master);
  62. return (ioread8(SCSPTR(sp)) & PIN_RXD) ? 1 : 0;
  63. }
  64. #define spidelay(x) ndelay(x)
  65. #include "spi-bitbang-txrx.h"
  66. static u32 sh_sci_spi_txrx_mode0(struct spi_device *spi,
  67. unsigned nsecs, u32 word, u8 bits)
  68. {
  69. return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
  70. }
  71. static u32 sh_sci_spi_txrx_mode1(struct spi_device *spi,
  72. unsigned nsecs, u32 word, u8 bits)
  73. {
  74. return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits);
  75. }
  76. static u32 sh_sci_spi_txrx_mode2(struct spi_device *spi,
  77. unsigned nsecs, u32 word, u8 bits)
  78. {
  79. return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits);
  80. }
  81. static u32 sh_sci_spi_txrx_mode3(struct spi_device *spi,
  82. unsigned nsecs, u32 word, u8 bits)
  83. {
  84. return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits);
  85. }
  86. static void sh_sci_spi_chipselect(struct spi_device *dev, int value)
  87. {
  88. struct sh_sci_spi *sp = spi_master_get_devdata(dev->master);
  89. if (sp->info->chip_select)
  90. (sp->info->chip_select)(sp->info, dev->chip_select, value);
  91. }
  92. static int sh_sci_spi_probe(struct platform_device *dev)
  93. {
  94. struct resource *r;
  95. struct spi_master *master;
  96. struct sh_sci_spi *sp;
  97. int ret;
  98. master = spi_alloc_master(&dev->dev, sizeof(struct sh_sci_spi));
  99. if (master == NULL) {
  100. dev_err(&dev->dev, "failed to allocate spi master\n");
  101. ret = -ENOMEM;
  102. goto err0;
  103. }
  104. sp = spi_master_get_devdata(master);
  105. platform_set_drvdata(dev, sp);
  106. sp->info = dev_get_platdata(&dev->dev);
  107. if (!sp->info) {
  108. dev_err(&dev->dev, "platform data is missing\n");
  109. ret = -ENOENT;
  110. goto err1;
  111. }
  112. /* setup spi bitbang adaptor */
  113. sp->bitbang.master = master;
  114. sp->bitbang.master->bus_num = sp->info->bus_num;
  115. sp->bitbang.master->num_chipselect = sp->info->num_chipselect;
  116. sp->bitbang.chipselect = sh_sci_spi_chipselect;
  117. sp->bitbang.txrx_word[SPI_MODE_0] = sh_sci_spi_txrx_mode0;
  118. sp->bitbang.txrx_word[SPI_MODE_1] = sh_sci_spi_txrx_mode1;
  119. sp->bitbang.txrx_word[SPI_MODE_2] = sh_sci_spi_txrx_mode2;
  120. sp->bitbang.txrx_word[SPI_MODE_3] = sh_sci_spi_txrx_mode3;
  121. r = platform_get_resource(dev, IORESOURCE_MEM, 0);
  122. if (r == NULL) {
  123. ret = -ENOENT;
  124. goto err1;
  125. }
  126. sp->membase = ioremap(r->start, resource_size(r));
  127. if (!sp->membase) {
  128. ret = -ENXIO;
  129. goto err1;
  130. }
  131. sp->val = ioread8(SCSPTR(sp));
  132. setbits(sp, PIN_INIT, 1);
  133. ret = spi_bitbang_start(&sp->bitbang);
  134. if (!ret)
  135. return 0;
  136. setbits(sp, PIN_INIT, 0);
  137. iounmap(sp->membase);
  138. err1:
  139. spi_master_put(sp->bitbang.master);
  140. err0:
  141. return ret;
  142. }
  143. static int sh_sci_spi_remove(struct platform_device *dev)
  144. {
  145. struct sh_sci_spi *sp = platform_get_drvdata(dev);
  146. spi_bitbang_stop(&sp->bitbang);
  147. setbits(sp, PIN_INIT, 0);
  148. iounmap(sp->membase);
  149. spi_master_put(sp->bitbang.master);
  150. return 0;
  151. }
  152. static struct platform_driver sh_sci_spi_drv = {
  153. .probe = sh_sci_spi_probe,
  154. .remove = sh_sci_spi_remove,
  155. .driver = {
  156. .name = "spi_sh_sci",
  157. },
  158. };
  159. module_platform_driver(sh_sci_spi_drv);
  160. MODULE_DESCRIPTION("SH SCI SPI Driver");
  161. MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
  162. MODULE_LICENSE("GPL");
  163. MODULE_ALIAS("platform:spi_sh_sci");