spi_sh_sci.c 4.9 KB

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