threewire.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 <string.h>
00023 #include <assert.h>
00024 #include <unistd.h>
00025 #include <gpxe/threewire.h>
00026 
00027 /** @file
00028  *
00029  * Three-wire serial devices
00030  *
00031  */
00032 
00033 /**
00034  * Read data from three-wire device
00035  *
00036  * @v nvs               NVS device
00037  * @v address           Address from which to read
00038  * @v data              Data buffer
00039  * @v len               Length of data buffer
00040  * @ret rc              Return status code
00041  */
00042 int threewire_read ( struct nvs_device *nvs, unsigned int address,
00043                      void *data, size_t len ) {
00044         struct spi_device *device = nvs_to_spi ( nvs );
00045         struct spi_bus *bus = device->bus;
00046         int rc;
00047 
00048         assert ( bus->mode == SPI_MODE_THREEWIRE );
00049 
00050         DBGC ( device, "3wire %p reading %zd bytes at %04x\n",
00051                device, len, address );
00052 
00053         if ( ( rc = bus->rw ( bus, device, THREEWIRE_READ, address,
00054                               NULL, data, len ) ) != 0 ) {
00055                 DBGC ( device, "3wire %p could not read: %s\n",
00056                        device, strerror ( rc ) );
00057                 return rc;
00058         }
00059 
00060         return 0;
00061 }
00062 
00063 /**
00064  * Write data to three-wire device
00065  *
00066  * @v nvs               NVS device
00067  * @v address           Address from which to read
00068  * @v data              Data buffer
00069  * @v len               Length of data buffer
00070  * @ret rc              Return status code
00071  */
00072 int threewire_write ( struct nvs_device *nvs, unsigned int address,
00073                       const void *data, size_t len ) {
00074         struct spi_device *device = nvs_to_spi ( nvs );
00075         struct spi_bus *bus = device->bus;
00076         int rc;
00077 
00078         assert ( bus->mode == SPI_MODE_THREEWIRE );
00079 
00080         DBGC ( device, "3wire %p writing %zd bytes at %04x\n",
00081                device, len, address );
00082 
00083         /* Enable device for writing */
00084         if ( ( rc = bus->rw ( bus, device, THREEWIRE_EWEN,
00085                               THREEWIRE_EWEN_ADDRESS, NULL, NULL, 0 ) ) != 0 ){
00086                 DBGC ( device, "3wire %p could not enable writing: %s\n",
00087                        device, strerror ( rc ) );
00088                 return rc;
00089         }
00090 
00091         /* Write data */
00092         if ( ( rc = bus->rw ( bus, device, THREEWIRE_WRITE, address,
00093                               data, NULL, len ) ) != 0 ) {
00094                 DBGC ( device, "3wire %p could not write: %s\n",
00095                        device, strerror ( rc ) );
00096                 return rc;
00097         }
00098 
00099         /* Our model of an SPI bus doesn't provide a mechanism for
00100          * "assert CS, wait for MISO to become high, so just wait for
00101          * long enough to ensure that the write has completed.
00102          */
00103         mdelay ( THREEWIRE_WRITE_MDELAY );
00104 
00105         return 0;
00106 }
00107 
00108 /**
00109  * Autodetect device address length
00110  *
00111  * @v device            SPI device
00112  * @ret rc              Return status code
00113  */
00114 int threewire_detect_address_len ( struct spi_device *device ) {
00115         struct nvs_device *nvs = &device->nvs;
00116         int rc;
00117 
00118         DBGC ( device, "3wire %p autodetecting address length\n", device );
00119 
00120         device->address_len = SPI_AUTODETECT_ADDRESS_LEN;
00121         if ( ( rc = threewire_read ( nvs, 0, NULL,
00122                                      ( 1 << nvs->word_len_log2 ) ) ) != 0 ) {
00123                 DBGC ( device, "3wire %p could not autodetect address "
00124                        "length: %s\n", device, strerror ( rc ) );
00125                 return rc;
00126         }
00127 
00128         DBGC ( device, "3wire %p autodetected address length %d\n",
00129                device, device->address_len );
00130         return 0;
00131 }

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