18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Mix this utility code with some glue code to get one of several types of 48c2ecf20Sopenharmony_ci * simple SPI master driver. Two do polled word-at-a-time I/O: 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * - GPIO/parport bitbangers. Provide chipselect() and txrx_word[](), 78c2ecf20Sopenharmony_ci * expanding the per-word routines from the inline templates below. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * - Drivers for controllers resembling bare shift registers. Provide 108c2ecf20Sopenharmony_ci * chipselect() and txrx_word[](), with custom setup()/cleanup() methods 118c2ecf20Sopenharmony_ci * that use your controller's clock and chipselect registers. 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * Some hardware works well with requests at spi_transfer scope: 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * - Drivers leveraging smarter hardware, with fifos or DMA; or for half 168c2ecf20Sopenharmony_ci * duplex (MicroWire) controllers. Provide chipselect() and txrx_bufs(), 178c2ecf20Sopenharmony_ci * and custom setup()/cleanup() methods. 188c2ecf20Sopenharmony_ci */ 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci/* 218c2ecf20Sopenharmony_ci * The code that knows what GPIO pins do what should have declared four 228c2ecf20Sopenharmony_ci * functions, ideally as inlines, before including this header: 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * void setsck(struct spi_device *, int is_on); 258c2ecf20Sopenharmony_ci * void setmosi(struct spi_device *, int is_on); 268c2ecf20Sopenharmony_ci * int getmiso(struct spi_device *); 278c2ecf20Sopenharmony_ci * void spidelay(unsigned); 288c2ecf20Sopenharmony_ci * 298c2ecf20Sopenharmony_ci * setsck()'s is_on parameter is a zero/nonzero boolean. 308c2ecf20Sopenharmony_ci * 318c2ecf20Sopenharmony_ci * setmosi()'s is_on parameter is a zero/nonzero boolean. 328c2ecf20Sopenharmony_ci * 338c2ecf20Sopenharmony_ci * getmiso() is required to return 0 or 1 only. Any other value is invalid 348c2ecf20Sopenharmony_ci * and will result in improper operation. 358c2ecf20Sopenharmony_ci * 368c2ecf20Sopenharmony_ci * A non-inlined routine would call bitbang_txrx_*() routines. The 378c2ecf20Sopenharmony_ci * main loop could easily compile down to a handful of instructions, 388c2ecf20Sopenharmony_ci * especially if the delay is a NOP (to run at peak speed). 398c2ecf20Sopenharmony_ci * 408c2ecf20Sopenharmony_ci * Since this is software, the timings may not be exactly what your board's 418c2ecf20Sopenharmony_ci * chips need ... there may be several reasons you'd need to tweak timings 428c2ecf20Sopenharmony_ci * in these routines, not just to make it faster or slower to match a 438c2ecf20Sopenharmony_ci * particular CPU clock rate. 448c2ecf20Sopenharmony_ci */ 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_cistatic inline u32 478c2ecf20Sopenharmony_cibitbang_txrx_be_cpha0(struct spi_device *spi, 488c2ecf20Sopenharmony_ci unsigned nsecs, unsigned cpol, unsigned flags, 498c2ecf20Sopenharmony_ci u32 word, u8 bits) 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */ 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci u32 oldbit = (!(word & (1<<(bits-1)))) << 31; 548c2ecf20Sopenharmony_ci /* clock starts at inactive polarity */ 558c2ecf20Sopenharmony_ci for (word <<= (32 - bits); likely(bits); bits--) { 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci /* setup MSB (to slave) on trailing edge */ 588c2ecf20Sopenharmony_ci if ((flags & SPI_MASTER_NO_TX) == 0) { 598c2ecf20Sopenharmony_ci if ((word & (1 << 31)) != oldbit) { 608c2ecf20Sopenharmony_ci setmosi(spi, word & (1 << 31)); 618c2ecf20Sopenharmony_ci oldbit = word & (1 << 31); 628c2ecf20Sopenharmony_ci } 638c2ecf20Sopenharmony_ci } 648c2ecf20Sopenharmony_ci spidelay(nsecs); /* T(setup) */ 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci setsck(spi, !cpol); 678c2ecf20Sopenharmony_ci spidelay(nsecs); 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci /* sample MSB (from slave) on leading edge */ 708c2ecf20Sopenharmony_ci word <<= 1; 718c2ecf20Sopenharmony_ci if ((flags & SPI_MASTER_NO_RX) == 0) 728c2ecf20Sopenharmony_ci word |= getmiso(spi); 738c2ecf20Sopenharmony_ci setsck(spi, cpol); 748c2ecf20Sopenharmony_ci } 758c2ecf20Sopenharmony_ci return word; 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistatic inline u32 798c2ecf20Sopenharmony_cibitbang_txrx_be_cpha1(struct spi_device *spi, 808c2ecf20Sopenharmony_ci unsigned nsecs, unsigned cpol, unsigned flags, 818c2ecf20Sopenharmony_ci u32 word, u8 bits) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */ 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci u32 oldbit = (!(word & (1<<(bits-1)))) << 31; 868c2ecf20Sopenharmony_ci /* clock starts at inactive polarity */ 878c2ecf20Sopenharmony_ci for (word <<= (32 - bits); likely(bits); bits--) { 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci /* setup MSB (to slave) on leading edge */ 908c2ecf20Sopenharmony_ci setsck(spi, !cpol); 918c2ecf20Sopenharmony_ci if ((flags & SPI_MASTER_NO_TX) == 0) { 928c2ecf20Sopenharmony_ci if ((word & (1 << 31)) != oldbit) { 938c2ecf20Sopenharmony_ci setmosi(spi, word & (1 << 31)); 948c2ecf20Sopenharmony_ci oldbit = word & (1 << 31); 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci } 978c2ecf20Sopenharmony_ci spidelay(nsecs); /* T(setup) */ 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci setsck(spi, cpol); 1008c2ecf20Sopenharmony_ci spidelay(nsecs); 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci /* sample MSB (from slave) on trailing edge */ 1038c2ecf20Sopenharmony_ci word <<= 1; 1048c2ecf20Sopenharmony_ci if ((flags & SPI_MASTER_NO_RX) == 0) 1058c2ecf20Sopenharmony_ci word |= getmiso(spi); 1068c2ecf20Sopenharmony_ci } 1078c2ecf20Sopenharmony_ci return word; 1088c2ecf20Sopenharmony_ci} 109