^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Mix this utility code with some glue code to get one of several types of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * simple SPI master driver. Two do polled word-at-a-time I/O:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * - GPIO/parport bitbangers. Provide chipselect() and txrx_word[](),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * expanding the per-word routines from the inline templates below.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * - Drivers for controllers resembling bare shift registers. Provide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * chipselect() and txrx_word[](), with custom setup()/cleanup() methods
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * that use your controller's clock and chipselect registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Some hardware works well with requests at spi_transfer scope:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * - Drivers leveraging smarter hardware, with fifos or DMA; or for half
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * duplex (MicroWire) controllers. Provide chipselect() and txrx_bufs(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * and custom setup()/cleanup() methods.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * The code that knows what GPIO pins do what should have declared four
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * functions, ideally as inlines, before including this header:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * void setsck(struct spi_device *, int is_on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * void setmosi(struct spi_device *, int is_on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * int getmiso(struct spi_device *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * void spidelay(unsigned);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * setsck()'s is_on parameter is a zero/nonzero boolean.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * setmosi()'s is_on parameter is a zero/nonzero boolean.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * getmiso() is required to return 0 or 1 only. Any other value is invalid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * and will result in improper operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * A non-inlined routine would call bitbang_txrx_*() routines. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * main loop could easily compile down to a handful of instructions,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * especially if the delay is a NOP (to run at peak speed).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * Since this is software, the timings may not be exactly what your board's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * chips need ... there may be several reasons you'd need to tweak timings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * in these routines, not just to make it faster or slower to match a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * particular CPU clock rate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static inline u32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) bitbang_txrx_be_cpha0(struct spi_device *spi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) unsigned nsecs, unsigned cpol, unsigned flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) u32 word, u8 bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) u32 oldbit = (!(word & (1<<(bits-1)))) << 31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /* clock starts at inactive polarity */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) for (word <<= (32 - bits); likely(bits); bits--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* setup MSB (to slave) on trailing edge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if ((flags & SPI_MASTER_NO_TX) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if ((word & (1 << 31)) != oldbit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) setmosi(spi, word & (1 << 31));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) oldbit = word & (1 << 31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) spidelay(nsecs); /* T(setup) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) setsck(spi, !cpol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) spidelay(nsecs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* sample MSB (from slave) on leading edge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) word <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if ((flags & SPI_MASTER_NO_RX) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) word |= getmiso(spi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) setsck(spi, cpol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static inline u32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) bitbang_txrx_be_cpha1(struct spi_device *spi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) unsigned nsecs, unsigned cpol, unsigned flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) u32 word, u8 bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) u32 oldbit = (!(word & (1<<(bits-1)))) << 31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* clock starts at inactive polarity */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) for (word <<= (32 - bits); likely(bits); bits--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /* setup MSB (to slave) on leading edge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) setsck(spi, !cpol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if ((flags & SPI_MASTER_NO_TX) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if ((word & (1 << 31)) != oldbit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) setmosi(spi, word & (1 << 31));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) oldbit = word & (1 << 31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) spidelay(nsecs); /* T(setup) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) setsck(spi, cpol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) spidelay(nsecs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* sample MSB (from slave) on trailing edge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) word <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if ((flags & SPI_MASTER_NO_RX) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) word |= getmiso(spi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }