Annotation of qemu/roms/ipxe/src/drivers/nvs/spi.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.