Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }