|
|
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 <string.h> ! 23: #include <assert.h> ! 24: #include <unistd.h> ! 25: #include <ipxe/threewire.h> ! 26: ! 27: /** @file ! 28: * ! 29: * Three-wire serial devices ! 30: * ! 31: */ ! 32: ! 33: /** ! 34: * Read data from three-wire device ! 35: * ! 36: * @v nvs NVS device ! 37: * @v address Address from which to read ! 38: * @v data Data buffer ! 39: * @v len Length of data buffer ! 40: * @ret rc Return status code ! 41: */ ! 42: int threewire_read ( struct nvs_device *nvs, unsigned int address, ! 43: void *data, size_t len ) { ! 44: struct spi_device *device = nvs_to_spi ( nvs ); ! 45: struct spi_bus *bus = device->bus; ! 46: int rc; ! 47: ! 48: assert ( bus->mode == SPI_MODE_THREEWIRE ); ! 49: ! 50: DBGC ( device, "3wire %p reading %zd bytes at %04x\n", ! 51: device, len, address ); ! 52: ! 53: if ( ( rc = bus->rw ( bus, device, THREEWIRE_READ, address, ! 54: NULL, data, len ) ) != 0 ) { ! 55: DBGC ( device, "3wire %p could not read: %s\n", ! 56: device, strerror ( rc ) ); ! 57: return rc; ! 58: } ! 59: ! 60: return 0; ! 61: } ! 62: ! 63: /** ! 64: * Write data to three-wire device ! 65: * ! 66: * @v nvs NVS device ! 67: * @v address Address from which to read ! 68: * @v data Data buffer ! 69: * @v len Length of data buffer ! 70: * @ret rc Return status code ! 71: */ ! 72: int threewire_write ( struct nvs_device *nvs, unsigned int address, ! 73: const void *data, size_t len ) { ! 74: struct spi_device *device = nvs_to_spi ( nvs ); ! 75: struct spi_bus *bus = device->bus; ! 76: int rc; ! 77: ! 78: assert ( bus->mode == SPI_MODE_THREEWIRE ); ! 79: ! 80: DBGC ( device, "3wire %p writing %zd bytes at %04x\n", ! 81: device, len, address ); ! 82: ! 83: /* Enable device for writing */ ! 84: if ( ( rc = bus->rw ( bus, device, THREEWIRE_EWEN, ! 85: THREEWIRE_EWEN_ADDRESS, NULL, NULL, 0 ) ) != 0 ){ ! 86: DBGC ( device, "3wire %p could not enable writing: %s\n", ! 87: device, strerror ( rc ) ); ! 88: return rc; ! 89: } ! 90: ! 91: /* Write data */ ! 92: if ( ( rc = bus->rw ( bus, device, THREEWIRE_WRITE, address, ! 93: data, NULL, len ) ) != 0 ) { ! 94: DBGC ( device, "3wire %p could not write: %s\n", ! 95: device, strerror ( rc ) ); ! 96: return rc; ! 97: } ! 98: ! 99: /* Our model of an SPI bus doesn't provide a mechanism for ! 100: * "assert CS, wait for MISO to become high, so just wait for ! 101: * long enough to ensure that the write has completed. ! 102: */ ! 103: mdelay ( THREEWIRE_WRITE_MDELAY ); ! 104: ! 105: return 0; ! 106: } ! 107: ! 108: /** ! 109: * Autodetect device address length ! 110: * ! 111: * @v device SPI device ! 112: * @ret rc Return status code ! 113: */ ! 114: int threewire_detect_address_len ( struct spi_device *device ) { ! 115: struct nvs_device *nvs = &device->nvs; ! 116: int rc; ! 117: ! 118: DBGC ( device, "3wire %p autodetecting address length\n", device ); ! 119: ! 120: device->address_len = SPI_AUTODETECT_ADDRESS_LEN; ! 121: if ( ( rc = threewire_read ( nvs, 0, NULL, ! 122: ( 1 << nvs->word_len_log2 ) ) ) != 0 ) { ! 123: DBGC ( device, "3wire %p could not autodetect address " ! 124: "length: %s\n", device, strerror ( rc ) ); ! 125: return rc; ! 126: } ! 127: ! 128: DBGC ( device, "3wire %p autodetected address length %d\n", ! 129: device, device->address_len ); ! 130: return 0; ! 131: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.