spi-sh-sci.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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. unsigned flags)
  69. {
  70. return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits);
  71. }
  72. static u32 sh_sci_spi_txrx_mode1(struct spi_device *spi,
  73. unsigned nsecs, u32 word, u8 bits,
  74. unsigned flags)
  75. {
  76. return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits);
  77. }
  78. static u32 sh_sci_spi_txrx_mode2(struct spi_device *spi,
  79. unsigned nsecs, u32 word, u8 bits,
  80. unsigned flags)
  81. {
  82. return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits);
  83. }
  84. static u32 sh_sci_spi_txrx_mode3(struct spi_device *spi,
  85. unsigned nsecs, u32 word, u8 bits,
  86. unsigned flags)
  87. {
  88. return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits);
  89. }
  90. static void sh_sci_spi_chipselect(struct spi_device *dev, int value)
  91. {
  92. struct sh_sci_spi *sp = spi_master_get_devdata(dev->master);
  93. if (sp->info->chip_select)
  94. (sp->info->chip_select)(sp->info, dev->chip_select, value);
  95. }
  96. static int sh_sci_spi_probe(struct platform_device *dev)
  97. {
  98. struct resource *r;
  99. struct spi_master *master;
  100. struct sh_sci_spi *sp;
  101. int ret;
  102. master = spi_alloc_master(&dev->dev, sizeof(struct sh_sci_spi));
  103. if (master == NULL) {
  104. dev_err(&dev->dev, "failed to allocate spi master\n");
  105. ret = -ENOMEM;
  106. goto err0;
  107. }
  108. sp = spi_master_get_devdata(master);
  109. platform_set_drvdata(dev, sp);
  110. sp->info = dev_get_platdata(&dev->dev);
  111. if (!sp->info) {
  112. dev_err(&dev->dev, "platform data is missing\n");
  113. ret = -ENOENT;
  114. goto err1;
  115. }
  116. /* setup spi bitbang adaptor */
  117. sp->bitbang.master = master;
  118. sp->bitbang.master->bus_num = sp->info->bus_num;
  119. sp->bitbang.master->num_chipselect = sp->info->num_chipselect;
  120. sp->bitbang.chipselect = sh_sci_spi_chipselect;
  121. sp->bitbang.txrx_word[SPI_MODE_0] = sh_sci_spi_txrx_mode0;
  122. sp->bitbang.txrx_word[SPI_MODE_1] = sh_sci_spi_txrx_mode1;
  123. sp->bitbang.txrx_word[SPI_MODE_2] = sh_sci_spi_txrx_mode2;
  124. sp->bitbang.txrx_word[SPI_MODE_3] = sh_sci_spi_txrx_mode3;
  125. r = platform_get_resource(dev, IORESOURCE_MEM, 0);
  126. if (r == NULL) {
  127. ret = -ENOENT;
  128. goto err1;
  129. }
  130. sp->membase = ioremap(r->start, resource_size(r));
  131. if (!sp->membase) {
  132. ret = -ENXIO;
  133. goto err1;
  134. }
  135. sp->val = ioread8(SCSPTR(sp));
  136. setbits(sp, PIN_INIT, 1);
  137. ret = spi_bitbang_start(&sp->bitbang);
  138. if (!ret)
  139. return 0;
  140. setbits(sp, PIN_INIT, 0);
  141. iounmap(sp->membase);
  142. err1:
  143. spi_master_put(sp->bitbang.master);
  144. err0:
  145. return ret;
  146. }
  147. static int sh_sci_spi_remove(struct platform_device *dev)
  148. {
  149. struct sh_sci_spi *sp = platform_get_drvdata(dev);
  150. spi_bitbang_stop(&sp->bitbang);
  151. setbits(sp, PIN_INIT, 0);
  152. iounmap(sp->membase);
  153. spi_master_put(sp->bitbang.master);
  154. return 0;
  155. }
  156. static struct platform_driver sh_sci_spi_drv = {
  157. .probe = sh_sci_spi_probe,
  158. .remove = sh_sci_spi_remove,
  159. .driver = {
  160. .name = "spi_sh_sci",
  161. },
  162. };
  163. module_platform_driver(sh_sci_spi_drv);
  164. MODULE_DESCRIPTION("SH SCI SPI Driver");
  165. MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
  166. MODULE_LICENSE("GPL");
  167. MODULE_ALIAS("platform:spi_sh_sci");