Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.16 135 lines 4.1 kB view raw
1#ifndef __SPI_BITBANG_H 2#define __SPI_BITBANG_H 3 4/* 5 * Mix this utility code with some glue code to get one of several types of 6 * simple SPI master driver. Two do polled word-at-a-time I/O: 7 * 8 * - GPIO/parport bitbangers. Provide chipselect() and txrx_word[](), 9 * expanding the per-word routines from the inline templates below. 10 * 11 * - Drivers for controllers resembling bare shift registers. Provide 12 * chipselect() and txrx_word[](), with custom setup()/cleanup() methods 13 * that use your controller's clock and chipselect registers. 14 * 15 * Some hardware works well with requests at spi_transfer scope: 16 * 17 * - Drivers leveraging smarter hardware, with fifos or DMA; or for half 18 * duplex (MicroWire) controllers. Provide chipslect() and txrx_bufs(), 19 * and custom setup()/cleanup() methods. 20 */ 21struct spi_bitbang { 22 struct workqueue_struct *workqueue; 23 struct work_struct work; 24 25 spinlock_t lock; 26 struct list_head queue; 27 u8 busy; 28 u8 shutdown; 29 u8 use_dma; 30 31 struct spi_master *master; 32 33 void (*chipselect)(struct spi_device *spi, int is_on); 34#define BITBANG_CS_ACTIVE 1 /* normally nCS, active low */ 35#define BITBANG_CS_INACTIVE 0 36 37 /* txrx_bufs() may handle dma mapping for transfers that don't 38 * already have one (transfer.{tx,rx}_dma is zero), or use PIO 39 */ 40 int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t); 41 42 /* txrx_word[SPI_MODE_*]() just looks like a shift register */ 43 u32 (*txrx_word[4])(struct spi_device *spi, 44 unsigned nsecs, 45 u32 word, u8 bits); 46}; 47 48/* you can call these default bitbang->master methods from your custom 49 * methods, if you like. 50 */ 51extern int spi_bitbang_setup(struct spi_device *spi); 52extern void spi_bitbang_cleanup(const struct spi_device *spi); 53extern int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m); 54 55/* start or stop queue processing */ 56extern int spi_bitbang_start(struct spi_bitbang *spi); 57extern int spi_bitbang_stop(struct spi_bitbang *spi); 58 59#endif /* __SPI_BITBANG_H */ 60 61/*-------------------------------------------------------------------------*/ 62 63#ifdef EXPAND_BITBANG_TXRX 64 65/* 66 * The code that knows what GPIO pins do what should have declared four 67 * functions, ideally as inlines, before #defining EXPAND_BITBANG_TXRX 68 * and including this header: 69 * 70 * void setsck(struct spi_device *, int is_on); 71 * void setmosi(struct spi_device *, int is_on); 72 * int getmiso(struct spi_device *); 73 * void spidelay(unsigned); 74 * 75 * A non-inlined routine would call bitbang_txrx_*() routines. The 76 * main loop could easily compile down to a handful of instructions, 77 * especially if the delay is a NOP (to run at peak speed). 78 * 79 * Since this is software, the timings may not be exactly what your board's 80 * chips need ... there may be several reasons you'd need to tweak timings 81 * in these routines, not just make to make it faster or slower to match a 82 * particular CPU clock rate. 83 */ 84 85static inline u32 86bitbang_txrx_be_cpha0(struct spi_device *spi, 87 unsigned nsecs, unsigned cpol, 88 u32 word, u8 bits) 89{ 90 /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */ 91 92 /* clock starts at inactive polarity */ 93 for (word <<= (32 - bits); likely(bits); bits--) { 94 95 /* setup MSB (to slave) on trailing edge */ 96 setmosi(spi, word & (1 << 31)); 97 spidelay(nsecs); /* T(setup) */ 98 99 setsck(spi, !cpol); 100 spidelay(nsecs); 101 102 /* sample MSB (from slave) on leading edge */ 103 word <<= 1; 104 word |= getmiso(spi); 105 setsck(spi, cpol); 106 } 107 return word; 108} 109 110static inline u32 111bitbang_txrx_be_cpha1(struct spi_device *spi, 112 unsigned nsecs, unsigned cpol, 113 u32 word, u8 bits) 114{ 115 /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */ 116 117 /* clock starts at inactive polarity */ 118 for (word <<= (32 - bits); likely(bits); bits--) { 119 120 /* setup MSB (to slave) on leading edge */ 121 setsck(spi, !cpol); 122 setmosi(spi, word & (1 << 31)); 123 spidelay(nsecs); /* T(setup) */ 124 125 setsck(spi, cpol); 126 spidelay(nsecs); 127 128 /* sample MSB (from slave) on trailing edge */ 129 word <<= 1; 130 word |= getmiso(spi); 131 } 132 return word; 133} 134 135#endif /* EXPAND_BITBANG_TXRX */