|
|
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 <errno.h> ! 23: #include <unistd.h> ! 24: #include <ipxe/spi.h> ! 25: ! 26: /** @file ! 27: * ! 28: * SPI devices ! 29: * ! 30: */ ! 31: ! 32: /** ! 33: * Munge SPI device address into command ! 34: * ! 35: * @v command SPI command ! 36: * @v address Address ! 37: * @v munge_address Device requires address munging ! 38: * @ret command Actual SPI command to use ! 39: * ! 40: * Some devices with 9-bit addresses (e.g. AT25040A EEPROM) use bit 3 ! 41: * of the command byte as address bit A8, rather than having a ! 42: * two-byte address. This function takes care of generating the ! 43: * appropriate command. ! 44: */ ! 45: static inline unsigned int spi_command ( unsigned int command, ! 46: unsigned int address, ! 47: int munge_address ) { ! 48: return ( command | ( ( ( address >> 8 ) & munge_address ) << 3 ) ); ! 49: } ! 50: ! 51: /** ! 52: * Wait for SPI device to complete operation ! 53: * ! 54: * @v device SPI device ! 55: * @ret rc Return status code ! 56: */ ! 57: static int spi_wait ( struct spi_device *device ) { ! 58: struct spi_bus *bus = device->bus; ! 59: uint8_t status; ! 60: int i; ! 61: int rc; ! 62: ! 63: for ( i = 0 ; i < 50 ; i++ ) { ! 64: udelay ( 20 ); ! 65: if ( ( rc = bus->rw ( bus, device, SPI_RDSR, -1, NULL, ! 66: &status, sizeof ( status ) ) ) != 0 ) ! 67: return rc; ! 68: if ( ! ( status & SPI_STATUS_NRDY ) ) ! 69: return 0; ! 70: } ! 71: DBG ( "SPI %p timed out\n", device ); ! 72: return -ETIMEDOUT; ! 73: } ! 74: ! 75: /** ! 76: * Read data from SPI device ! 77: * ! 78: * @v nvs NVS device ! 79: * @v address Address from which to read ! 80: * @v data Data buffer ! 81: * @v len Length of data buffer ! 82: * @ret rc Return status code ! 83: */ ! 84: int spi_read ( struct nvs_device *nvs, unsigned int address, ! 85: void *data, size_t len ) { ! 86: struct spi_device *device = nvs_to_spi ( nvs ); ! 87: struct spi_bus *bus = device->bus; ! 88: unsigned int command = spi_command ( SPI_READ, address, ! 89: device->munge_address ); ! 90: int rc; ! 91: ! 92: DBG ( "SPI %p reading %zd bytes from %#04x\n", device, len, address ); ! 93: if ( ( rc = bus->rw ( bus, device, command, address, ! 94: NULL, data, len ) ) != 0 ) { ! 95: DBG ( "SPI %p failed to read data from device\n", device ); ! 96: return rc; ! 97: } ! 98: ! 99: return 0; ! 100: } ! 101: ! 102: /** ! 103: * Write data to SPI device ! 104: * ! 105: * @v nvs NVS device ! 106: * @v address Address from which to read ! 107: * @v data Data buffer ! 108: * @v len Length of data buffer ! 109: * @ret rc Return status code ! 110: */ ! 111: int spi_write ( struct nvs_device *nvs, unsigned int address, ! 112: const void *data, size_t len ) { ! 113: struct spi_device *device = nvs_to_spi ( nvs ); ! 114: struct spi_bus *bus = device->bus; ! 115: unsigned int command = spi_command ( SPI_WRITE, address, ! 116: device->munge_address ); ! 117: int rc; ! 118: ! 119: DBG ( "SPI %p writing %zd bytes to %#04x\n", device, len, address ); ! 120: ! 121: if ( ( rc = bus->rw ( bus, device, SPI_WREN, -1, ! 122: NULL, NULL, 0 ) ) != 0 ) { ! 123: DBG ( "SPI %p failed to write-enable device\n", device ); ! 124: return rc; ! 125: } ! 126: ! 127: if ( ( rc = bus->rw ( bus, device, command, address, ! 128: data, NULL, len ) ) != 0 ) { ! 129: DBG ( "SPI %p failed to write data to device\n", device ); ! 130: return rc; ! 131: } ! 132: ! 133: if ( ( rc = spi_wait ( device ) ) != 0 ) { ! 134: DBG ( "SPI %p failed to complete write operation\n", device ); ! 135: return rc; ! 136: } ! 137: ! 138: return 0; ! 139: } ! 140:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.