spi-butterfly.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. /*
  2. * parport-to-butterfly adapter
  3. *
  4. * Copyright (C) 2005 David Brownell
  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
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. */
  16. #include <linux/kernel.h>
  17. #include <linux/init.h>
  18. #include <linux/delay.h>
  19. #include <linux/module.h>
  20. #include <linux/device.h>
  21. #include <linux/parport.h>
  22. #include <linux/sched.h>
  23. #include <linux/spi/spi.h>
  24. #include <linux/spi/spi_bitbang.h>
  25. #include <linux/spi/flash.h>
  26. #include <linux/mtd/partitions.h>
  27. /*
  28. * This uses SPI to talk with an "AVR Butterfly", which is a $US20 card
  29. * with a battery powered AVR microcontroller and lots of goodies. You
  30. * can use GCC to develop firmware for this.
  31. *
  32. * See Documentation/spi/butterfly for information about how to build
  33. * and use this custom parallel port cable.
  34. */
  35. /* DATA output bits (pins 2..9 == D0..D7) */
  36. #define butterfly_nreset (1 << 1) /* pin 3 */
  37. #define spi_sck_bit (1 << 0) /* pin 2 */
  38. #define spi_mosi_bit (1 << 7) /* pin 9 */
  39. #define vcc_bits ((1 << 6) | (1 << 5)) /* pins 7, 8 */
  40. /* STATUS input bits */
  41. #define spi_miso_bit PARPORT_STATUS_BUSY /* pin 11 */
  42. /* CONTROL output bits */
  43. #define spi_cs_bit PARPORT_CONTROL_SELECT /* pin 17 */
  44. static inline struct butterfly *spidev_to_pp(struct spi_device *spi)
  45. {
  46. return spi->controller_data;
  47. }
  48. struct butterfly {
  49. /* REVISIT ... for now, this must be first */
  50. struct spi_bitbang bitbang;
  51. struct parport *port;
  52. struct pardevice *pd;
  53. u8 lastbyte;
  54. struct spi_device *dataflash;
  55. struct spi_device *butterfly;
  56. struct spi_board_info info[2];
  57. };
  58. /*----------------------------------------------------------------------*/
  59. static inline void
  60. setsck(struct spi_device *spi, int is_on)
  61. {
  62. struct butterfly *pp = spidev_to_pp(spi);
  63. u8 bit, byte = pp->lastbyte;
  64. bit = spi_sck_bit;
  65. if (is_on)
  66. byte |= bit;
  67. else
  68. byte &= ~bit;
  69. parport_write_data(pp->port, byte);
  70. pp->lastbyte = byte;
  71. }
  72. static inline void
  73. setmosi(struct spi_device *spi, int is_on)
  74. {
  75. struct butterfly *pp = spidev_to_pp(spi);
  76. u8 bit, byte = pp->lastbyte;
  77. bit = spi_mosi_bit;
  78. if (is_on)
  79. byte |= bit;
  80. else
  81. byte &= ~bit;
  82. parport_write_data(pp->port, byte);
  83. pp->lastbyte = byte;
  84. }
  85. static inline int getmiso(struct spi_device *spi)
  86. {
  87. struct butterfly *pp = spidev_to_pp(spi);
  88. int value;
  89. u8 bit;
  90. bit = spi_miso_bit;
  91. /* only STATUS_BUSY is NOT negated */
  92. value = !(parport_read_status(pp->port) & bit);
  93. return (bit == PARPORT_STATUS_BUSY) ? value : !value;
  94. }
  95. static void butterfly_chipselect(struct spi_device *spi, int value)
  96. {
  97. struct butterfly *pp = spidev_to_pp(spi);
  98. /* set default clock polarity */
  99. if (value != BITBANG_CS_INACTIVE)
  100. setsck(spi, spi->mode & SPI_CPOL);
  101. /* here, value == "activate or not";
  102. * most PARPORT_CONTROL_* bits are negated, so we must
  103. * morph it to value == "bit value to write in control register"
  104. */
  105. if (spi_cs_bit == PARPORT_CONTROL_INIT)
  106. value = !value;
  107. parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0);
  108. }
  109. /* we only needed to implement one mode here, and choose SPI_MODE_0 */
  110. #define spidelay(X) do { } while (0)
  111. /* #define spidelay ndelay */
  112. #include "spi-bitbang-txrx.h"
  113. static u32
  114. butterfly_txrx_word_mode0(struct spi_device *spi,
  115. unsigned nsecs,
  116. u32 word, u8 bits)
  117. {
  118. return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
  119. }
  120. /*----------------------------------------------------------------------*/
  121. /* override default partitioning with cmdlinepart */
  122. static struct mtd_partition partitions[] = { {
  123. /* JFFS2 wants partitions of 4*N blocks for this device,
  124. * so sectors 0 and 1 can't be partitions by themselves.
  125. */
  126. /* sector 0 = 8 pages * 264 bytes/page (1 block)
  127. * sector 1 = 248 pages * 264 bytes/page
  128. */
  129. .name = "bookkeeping", /* 66 KB */
  130. .offset = 0,
  131. .size = (8 + 248) * 264,
  132. /* .mask_flags = MTD_WRITEABLE, */
  133. }, {
  134. /* sector 2 = 256 pages * 264 bytes/page
  135. * sectors 3-5 = 512 pages * 264 bytes/page
  136. */
  137. .name = "filesystem", /* 462 KB */
  138. .offset = MTDPART_OFS_APPEND,
  139. .size = MTDPART_SIZ_FULL,
  140. } };
  141. static struct flash_platform_data flash = {
  142. .name = "butterflash",
  143. .parts = partitions,
  144. .nr_parts = ARRAY_SIZE(partitions),
  145. };
  146. /* REVISIT remove this ugly global and its "only one" limitation */
  147. static struct butterfly *butterfly;
  148. static void butterfly_attach(struct parport *p)
  149. {
  150. struct pardevice *pd;
  151. int status;
  152. struct butterfly *pp;
  153. struct spi_master *master;
  154. struct device *dev = p->physport->dev;
  155. if (butterfly || !dev)
  156. return;
  157. /* REVISIT: this just _assumes_ a butterfly is there ... no probe,
  158. * and no way to be selective about what it binds to.
  159. */
  160. master = spi_alloc_master(dev, sizeof(*pp));
  161. if (!master) {
  162. status = -ENOMEM;
  163. goto done;
  164. }
  165. pp = spi_master_get_devdata(master);
  166. /*
  167. * SPI and bitbang hookup
  168. *
  169. * use default setup(), cleanup(), and transfer() methods; and
  170. * only bother implementing mode 0. Start it later.
  171. */
  172. master->bus_num = 42;
  173. master->num_chipselect = 2;
  174. pp->bitbang.master = master;
  175. pp->bitbang.chipselect = butterfly_chipselect;
  176. pp->bitbang.txrx_word[SPI_MODE_0] = butterfly_txrx_word_mode0;
  177. /*
  178. * parport hookup
  179. */
  180. pp->port = p;
  181. pd = parport_register_device(p, "spi_butterfly",
  182. NULL, NULL, NULL,
  183. 0 /* FLAGS */, pp);
  184. if (!pd) {
  185. status = -ENOMEM;
  186. goto clean0;
  187. }
  188. pp->pd = pd;
  189. status = parport_claim(pd);
  190. if (status < 0)
  191. goto clean1;
  192. /*
  193. * Butterfly reset, powerup, run firmware
  194. */
  195. pr_debug("%s: powerup/reset Butterfly\n", p->name);
  196. /* nCS for dataflash (this bit is inverted on output) */
  197. parport_frob_control(pp->port, spi_cs_bit, 0);
  198. /* stabilize power with chip in reset (nRESET), and
  199. * spi_sck_bit clear (CPOL=0)
  200. */
  201. pp->lastbyte |= vcc_bits;
  202. parport_write_data(pp->port, pp->lastbyte);
  203. msleep(5);
  204. /* take it out of reset; assume long reset delay */
  205. pp->lastbyte |= butterfly_nreset;
  206. parport_write_data(pp->port, pp->lastbyte);
  207. msleep(100);
  208. /*
  209. * Start SPI ... for now, hide that we're two physical busses.
  210. */
  211. status = spi_bitbang_start(&pp->bitbang);
  212. if (status < 0)
  213. goto clean2;
  214. /* Bus 1 lets us talk to at45db041b (firmware disables AVR SPI), AVR
  215. * (firmware resets at45, acts as spi slave) or neither (we ignore
  216. * both, AVR uses AT45). Here we expect firmware for the first option.
  217. */
  218. pp->info[0].max_speed_hz = 15 * 1000 * 1000;
  219. strcpy(pp->info[0].modalias, "mtd_dataflash");
  220. pp->info[0].platform_data = &flash;
  221. pp->info[0].chip_select = 1;
  222. pp->info[0].controller_data = pp;
  223. pp->dataflash = spi_new_device(pp->bitbang.master, &pp->info[0]);
  224. if (pp->dataflash)
  225. pr_debug("%s: dataflash at %s\n", p->name,
  226. dev_name(&pp->dataflash->dev));
  227. pr_info("%s: AVR Butterfly\n", p->name);
  228. butterfly = pp;
  229. return;
  230. clean2:
  231. /* turn off VCC */
  232. parport_write_data(pp->port, 0);
  233. parport_release(pp->pd);
  234. clean1:
  235. parport_unregister_device(pd);
  236. clean0:
  237. (void) spi_master_put(pp->bitbang.master);
  238. done:
  239. pr_debug("%s: butterfly probe, fail %d\n", p->name, status);
  240. }
  241. static void butterfly_detach(struct parport *p)
  242. {
  243. struct butterfly *pp;
  244. /* FIXME this global is ugly ... but, how to quickly get from
  245. * the parport to the "struct butterfly" associated with it?
  246. * "old school" driver-internal device lists?
  247. */
  248. if (!butterfly || butterfly->port != p)
  249. return;
  250. pp = butterfly;
  251. butterfly = NULL;
  252. /* stop() unregisters child devices too */
  253. spi_bitbang_stop(&pp->bitbang);
  254. /* turn off VCC */
  255. parport_write_data(pp->port, 0);
  256. msleep(10);
  257. parport_release(pp->pd);
  258. parport_unregister_device(pp->pd);
  259. (void) spi_master_put(pp->bitbang.master);
  260. }
  261. static struct parport_driver butterfly_driver = {
  262. .name = "spi_butterfly",
  263. .attach = butterfly_attach,
  264. .detach = butterfly_detach,
  265. };
  266. static int __init butterfly_init(void)
  267. {
  268. return parport_register_driver(&butterfly_driver);
  269. }
  270. device_initcall(butterfly_init);
  271. static void __exit butterfly_exit(void)
  272. {
  273. parport_unregister_driver(&butterfly_driver);
  274. }
  275. module_exit(butterfly_exit);
  276. MODULE_DESCRIPTION("Parport Adapter driver for AVR Butterfly");
  277. MODULE_LICENSE("GPL");