spi.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00019 FILE_LICENCE ( GPL2_OR_LATER );
00020 
00021 #include <stddef.h>
00022 #include <errno.h>
00023 #include <unistd.h>
00024 #include <gpxe/spi.h>
00025 
00026 /** @file
00027  *
00028  * SPI devices
00029  *
00030  */
00031 
00032 /**
00033  * Munge SPI device address into command
00034  *
00035  * @v command           SPI command
00036  * @v address           Address
00037  * @v munge_address     Device requires address munging
00038  * @ret command         Actual SPI command to use
00039  *
00040  * Some devices with 9-bit addresses (e.g. AT25040A EEPROM) use bit 3
00041  * of the command byte as address bit A8, rather than having a
00042  * two-byte address.  This function takes care of generating the
00043  * appropriate command.
00044  */
00045 static inline unsigned int spi_command ( unsigned int command,
00046                                          unsigned int address,
00047                                          int munge_address ) {
00048         return ( command | ( ( ( address >> 8 ) & munge_address ) << 3 ) );
00049 }
00050 
00051 /**
00052  * Wait for SPI device to complete operation
00053  *
00054  * @v device            SPI device
00055  * @ret rc              Return status code
00056  */
00057 static int spi_wait ( struct spi_device *device ) {
00058         struct spi_bus *bus = device->bus;
00059         uint8_t status;
00060         int i;
00061         int rc;
00062 
00063         for ( i = 0 ; i < 50 ; i++ ) {
00064                 udelay ( 20 );
00065                 if ( ( rc = bus->rw ( bus, device, SPI_RDSR, -1, NULL,
00066                                       &status, sizeof ( status ) ) ) != 0 )
00067                         return rc;
00068                 if ( ! ( status & SPI_STATUS_NRDY ) )
00069                         return 0;
00070         }
00071         DBG ( "SPI %p timed out\n", device );
00072         return -ETIMEDOUT;
00073 }
00074 
00075 /**
00076  * Read data from SPI device
00077  *
00078  * @v nvs               NVS device
00079  * @v address           Address from which to read
00080  * @v data              Data buffer
00081  * @v len               Length of data buffer
00082  * @ret rc              Return status code
00083  */
00084 int spi_read ( struct nvs_device *nvs, unsigned int address,
00085                void *data, size_t len ) {
00086         struct spi_device *device = nvs_to_spi ( nvs );
00087         struct spi_bus *bus = device->bus;
00088         unsigned int command = spi_command ( SPI_READ, address,
00089                                              device->munge_address );
00090         int rc;
00091 
00092         DBG ( "SPI %p reading %zd bytes from %#04x\n", device, len, address );
00093         if ( ( rc = bus->rw ( bus, device, command, address,
00094                               NULL, data, len ) ) != 0 ) {
00095                 DBG ( "SPI %p failed to read data from device\n", device );
00096                 return rc;
00097         }
00098 
00099         return 0;
00100 }
00101 
00102 /**
00103  * Write data to SPI device
00104  *
00105  * @v nvs               NVS device
00106  * @v address           Address from which to read
00107  * @v data              Data buffer
00108  * @v len               Length of data buffer
00109  * @ret rc              Return status code
00110  */
00111 int spi_write ( struct nvs_device *nvs, unsigned int address,
00112                 const void *data, size_t len ) {
00113         struct spi_device *device = nvs_to_spi ( nvs );
00114         struct spi_bus *bus = device->bus;
00115         unsigned int command = spi_command ( SPI_WRITE, address,
00116                                              device->munge_address );
00117         int rc;
00118 
00119         DBG ( "SPI %p writing %zd bytes to %#04x\n", device, len, address );
00120 
00121         if ( ( rc = bus->rw ( bus, device, SPI_WREN, -1,
00122                               NULL, NULL, 0 ) ) != 0 ) {
00123                 DBG ( "SPI %p failed to write-enable device\n", device );
00124                 return rc;
00125         }
00126 
00127         if ( ( rc = bus->rw ( bus, device, command, address,
00128                               data, NULL, len ) ) != 0 ) {
00129                 DBG ( "SPI %p failed to write data to device\n", device );
00130                 return rc;
00131         }
00132         
00133         if ( ( rc = spi_wait ( device ) ) != 0 ) {
00134                 DBG ( "SPI %p failed to complete write operation\n", device );
00135                 return rc;
00136         }
00137 
00138         return 0;
00139 }
00140 

Generated on Tue Apr 6 20:01:06 2010 for gPXE by  doxygen 1.5.7.1