|
|
1.1 ! root 1: /* ! 2: * Copyright (C) 2006 Michael Brown <[email protected]>. ! 3: * ! 4: * This program is free software; you can redistribute it and/or ! 5: * modify it under the terms of the GNU General Public License as ! 6: * published by the Free Software Foundation; either version 2 of the ! 7: * License, or any later version. ! 8: * ! 9: * This program is distributed in the hope that it will be useful, but ! 10: * WITHOUT ANY WARRANTY; without even the implied warranty of ! 11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 12: * General Public License for more details. ! 13: * ! 14: * You should have received a copy of the GNU General Public License ! 15: * along with this program; if not, write to the Free Software ! 16: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! 17: */ ! 18: ! 19: FILE_LICENCE ( GPL2_OR_LATER ); ! 20: ! 21: #include <stddef.h> ! 22: #include <stdint.h> ! 23: #include <string.h> ! 24: #include <byteswap.h> ! 25: #include <errno.h> ! 26: #include <assert.h> ! 27: #include <unistd.h> ! 28: #include <ipxe/bitbash.h> ! 29: #include <ipxe/spi_bit.h> ! 30: ! 31: /** @file ! 32: * ! 33: * SPI bit-bashing interface ! 34: * ! 35: */ ! 36: ! 37: /** Delay between SCLK changes and around SS changes */ ! 38: static void spi_bit_delay ( void ) { ! 39: udelay ( SPI_BIT_UDELAY ); ! 40: } ! 41: ! 42: /** Chip select line will be asserted */ ! 43: #define SELECT_SLAVE 0 ! 44: ! 45: /** Chip select line will be deasserted */ ! 46: #define DESELECT_SLAVE SPI_MODE_SSPOL ! 47: ! 48: /** ! 49: * Select/deselect slave ! 50: * ! 51: * @v spibit SPI bit-bashing interface ! 52: * @v slave Slave number ! 53: * @v state Slave select state ! 54: * ! 55: * @c state must be @c SELECT_SLAVE or @c DESELECT_SLAVE. ! 56: */ ! 57: static void spi_bit_set_slave_select ( struct spi_bit_basher *spibit, ! 58: unsigned int slave, ! 59: unsigned int state ) { ! 60: struct bit_basher *basher = &spibit->basher; ! 61: ! 62: state ^= ( spibit->bus.mode & SPI_MODE_SSPOL ); ! 63: DBGC2 ( spibit, "SPIBIT %p setting slave %d select %s\n", ! 64: spibit, slave, ( state ? "high" : "low" ) ); ! 65: ! 66: spi_bit_delay(); ! 67: write_bit ( basher, SPI_BIT_SS ( slave ), state ); ! 68: spi_bit_delay(); ! 69: } ! 70: ! 71: /** ! 72: * Transfer bits over SPI bit-bashing bus ! 73: * ! 74: * @v bus SPI bus ! 75: * @v data_out TX data buffer (or NULL) ! 76: * @v data_in RX data buffer (or NULL) ! 77: * @v len Length of transfer (in @b bits) ! 78: * @v endianness Endianness of this data transfer ! 79: * ! 80: * This issues @c len clock cycles on the SPI bus, shifting out data ! 81: * from the @c data_out buffer to the MOSI line and shifting in data ! 82: * from the MISO line to the @c data_in buffer. If @c data_out is ! 83: * NULL, then the data sent will be all zeroes. If @c data_in is ! 84: * NULL, then the incoming data will be discarded. ! 85: */ ! 86: static void spi_bit_transfer ( struct spi_bit_basher *spibit, ! 87: const void *data_out, void *data_in, ! 88: unsigned int len, int endianness ) { ! 89: struct spi_bus *bus = &spibit->bus; ! 90: struct bit_basher *basher = &spibit->basher; ! 91: unsigned int sclk = ( ( bus->mode & SPI_MODE_CPOL ) ? 1 : 0 ); ! 92: unsigned int cpha = ( ( bus->mode & SPI_MODE_CPHA ) ? 1 : 0 ); ! 93: unsigned int bit_offset; ! 94: unsigned int byte_offset; ! 95: unsigned int byte_mask; ! 96: unsigned int bit; ! 97: unsigned int step; ! 98: ! 99: DBGC2 ( spibit, "SPIBIT %p transferring %d bits in mode %#x\n", ! 100: spibit, len, bus->mode ); ! 101: ! 102: for ( step = 0 ; step < ( len * 2 ) ; step++ ) { ! 103: /* Calculate byte offset and byte mask */ ! 104: bit_offset = ( ( endianness == SPI_BIT_BIG_ENDIAN ) ? ! 105: ( len - ( step / 2 ) - 1 ) : ( step / 2 ) ); ! 106: byte_offset = ( bit_offset / 8 ); ! 107: byte_mask = ( 1 << ( bit_offset % 8 ) ); ! 108: ! 109: /* Shift data in or out */ ! 110: if ( sclk == cpha ) { ! 111: const uint8_t *byte; ! 112: ! 113: /* Shift data out */ ! 114: if ( data_out ) { ! 115: byte = ( data_out + byte_offset ); ! 116: bit = ( *byte & byte_mask ); ! 117: DBGCP ( spibit, "SPIBIT %p wrote bit %d\n", ! 118: spibit, ( bit ? 1 : 0 ) ); ! 119: } else { ! 120: bit = 0; ! 121: } ! 122: write_bit ( basher, SPI_BIT_MOSI, bit ); ! 123: } else { ! 124: uint8_t *byte; ! 125: ! 126: /* Shift data in */ ! 127: bit = read_bit ( basher, SPI_BIT_MISO ); ! 128: if ( data_in ) { ! 129: DBGCP ( spibit, "SPIBIT %p read bit %d\n", ! 130: spibit, ( bit ? 1 : 0 ) ); ! 131: byte = ( data_in + byte_offset ); ! 132: *byte &= ~byte_mask; ! 133: *byte |= ( bit & byte_mask ); ! 134: } ! 135: } ! 136: ! 137: /* Toggle clock line */ ! 138: spi_bit_delay(); ! 139: sclk ^= 1; ! 140: write_bit ( basher, SPI_BIT_SCLK, sclk ); ! 141: } ! 142: } ! 143: ! 144: /** ! 145: * Read/write data via SPI bit-bashing bus ! 146: * ! 147: * @v bus SPI bus ! 148: * @v device SPI device ! 149: * @v command Command ! 150: * @v address Address to read/write (<0 for no address) ! 151: * @v data_out TX data buffer (or NULL) ! 152: * @v data_in RX data buffer (or NULL) ! 153: * @v len Length of transfer ! 154: * @ret rc Return status code ! 155: */ ! 156: static int spi_bit_rw ( struct spi_bus *bus, struct spi_device *device, ! 157: unsigned int command, int address, ! 158: const void *data_out, void *data_in, size_t len ) { ! 159: struct spi_bit_basher *spibit ! 160: = container_of ( bus, struct spi_bit_basher, bus ); ! 161: uint32_t tmp_command; ! 162: uint32_t tmp_address; ! 163: uint32_t tmp_address_detect; ! 164: ! 165: /* Deassert chip select to reset specified slave */ ! 166: spi_bit_set_slave_select ( spibit, device->slave, DESELECT_SLAVE ); ! 167: ! 168: /* Set clock line to idle state */ ! 169: write_bit ( &spibit->basher, SPI_BIT_SCLK, ! 170: ( bus->mode & SPI_MODE_CPOL ) ); ! 171: ! 172: /* Assert chip select on specified slave */ ! 173: spi_bit_set_slave_select ( spibit, device->slave, SELECT_SLAVE ); ! 174: ! 175: /* Transmit command */ ! 176: assert ( device->command_len <= ( 8 * sizeof ( tmp_command ) ) ); ! 177: tmp_command = cpu_to_le32 ( command ); ! 178: spi_bit_transfer ( spibit, &tmp_command, NULL, device->command_len, ! 179: SPI_BIT_BIG_ENDIAN ); ! 180: ! 181: /* Transmit address, if present */ ! 182: if ( address >= 0 ) { ! 183: assert ( device->address_len <= ( 8 * sizeof ( tmp_address ))); ! 184: tmp_address = cpu_to_le32 ( address ); ! 185: if ( device->address_len == SPI_AUTODETECT_ADDRESS_LEN ) { ! 186: /* Autodetect address length. This relies on ! 187: * the device responding with a dummy zero ! 188: * data bit before the first real data bit. ! 189: */ ! 190: DBGC ( spibit, "SPIBIT %p autodetecting device " ! 191: "address length\n", spibit ); ! 192: assert ( address == 0 ); ! 193: device->address_len = 0; ! 194: do { ! 195: spi_bit_transfer ( spibit, &tmp_address, ! 196: &tmp_address_detect, 1, ! 197: SPI_BIT_BIG_ENDIAN ); ! 198: device->address_len++; ! 199: } while ( le32_to_cpu ( tmp_address_detect ) & 1 ); ! 200: DBGC ( spibit, "SPIBIT %p autodetected device address " ! 201: "length %d\n", spibit, device->address_len ); ! 202: } else { ! 203: spi_bit_transfer ( spibit, &tmp_address, NULL, ! 204: device->address_len, ! 205: SPI_BIT_BIG_ENDIAN ); ! 206: } ! 207: } ! 208: ! 209: /* Transmit/receive data */ ! 210: spi_bit_transfer ( spibit, data_out, data_in, ( len * 8 ), ! 211: spibit->endianness ); ! 212: ! 213: /* Deassert chip select on specified slave */ ! 214: spi_bit_set_slave_select ( spibit, device->slave, DESELECT_SLAVE ); ! 215: ! 216: return 0; ! 217: } ! 218: ! 219: /** ! 220: * Initialise SPI bit-bashing interface ! 221: * ! 222: * @v spibit SPI bit-bashing interface ! 223: */ ! 224: void init_spi_bit_basher ( struct spi_bit_basher *spibit ) { ! 225: assert ( &spibit->basher.op->read != NULL ); ! 226: assert ( &spibit->basher.op->write != NULL ); ! 227: spibit->bus.rw = spi_bit_rw; ! 228: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.