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.17 143 lines 4.4 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 /* setup_transfer() changes clock and/or wordsize to match settings 34 * for this transfer; zeroes restore defaults from spi_device. 35 */ 36 int (*setup_transfer)(struct spi_device *spi, 37 struct spi_transfer *t); 38 39 void (*chipselect)(struct spi_device *spi, int is_on); 40#define BITBANG_CS_ACTIVE 1 /* normally nCS, active low */ 41#define BITBANG_CS_INACTIVE 0 42 43 /* txrx_bufs() may handle dma mapping for transfers that don't 44 * already have one (transfer.{tx,rx}_dma is zero), or use PIO 45 */ 46 int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t); 47 48 /* txrx_word[SPI_MODE_*]() just looks like a shift register */ 49 u32 (*txrx_word[4])(struct spi_device *spi, 50 unsigned nsecs, 51 u32 word, u8 bits); 52}; 53 54/* you can call these default bitbang->master methods from your custom 55 * methods, if you like. 56 */ 57extern int spi_bitbang_setup(struct spi_device *spi); 58extern void spi_bitbang_cleanup(const struct spi_device *spi); 59extern int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m); 60extern int spi_bitbang_setup_transfer(struct spi_device *spi, 61 struct spi_transfer *t); 62 63/* start or stop queue processing */ 64extern int spi_bitbang_start(struct spi_bitbang *spi); 65extern int spi_bitbang_stop(struct spi_bitbang *spi); 66 67#endif /* __SPI_BITBANG_H */ 68 69/*-------------------------------------------------------------------------*/ 70 71#ifdef EXPAND_BITBANG_TXRX 72 73/* 74 * The code that knows what GPIO pins do what should have declared four 75 * functions, ideally as inlines, before #defining EXPAND_BITBANG_TXRX 76 * and including this header: 77 * 78 * void setsck(struct spi_device *, int is_on); 79 * void setmosi(struct spi_device *, int is_on); 80 * int getmiso(struct spi_device *); 81 * void spidelay(unsigned); 82 * 83 * A non-inlined routine would call bitbang_txrx_*() routines. The 84 * main loop could easily compile down to a handful of instructions, 85 * especially if the delay is a NOP (to run at peak speed). 86 * 87 * Since this is software, the timings may not be exactly what your board's 88 * chips need ... there may be several reasons you'd need to tweak timings 89 * in these routines, not just make to make it faster or slower to match a 90 * particular CPU clock rate. 91 */ 92 93static inline u32 94bitbang_txrx_be_cpha0(struct spi_device *spi, 95 unsigned nsecs, unsigned cpol, 96 u32 word, u8 bits) 97{ 98 /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */ 99 100 /* clock starts at inactive polarity */ 101 for (word <<= (32 - bits); likely(bits); bits--) { 102 103 /* setup MSB (to slave) on trailing edge */ 104 setmosi(spi, word & (1 << 31)); 105 spidelay(nsecs); /* T(setup) */ 106 107 setsck(spi, !cpol); 108 spidelay(nsecs); 109 110 /* sample MSB (from slave) on leading edge */ 111 word <<= 1; 112 word |= getmiso(spi); 113 setsck(spi, cpol); 114 } 115 return word; 116} 117 118static inline u32 119bitbang_txrx_be_cpha1(struct spi_device *spi, 120 unsigned nsecs, unsigned cpol, 121 u32 word, u8 bits) 122{ 123 /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */ 124 125 /* clock starts at inactive polarity */ 126 for (word <<= (32 - bits); likely(bits); bits--) { 127 128 /* setup MSB (to slave) on leading edge */ 129 setsck(spi, !cpol); 130 setmosi(spi, word & (1 << 31)); 131 spidelay(nsecs); /* T(setup) */ 132 133 setsck(spi, cpol); 134 spidelay(nsecs); 135 136 /* sample MSB (from slave) on trailing edge */ 137 word <<= 1; 138 word |= getmiso(spi); 139 } 140 return word; 141} 142 143#endif /* EXPAND_BITBANG_TXRX */