Browse Source

Added generic SPI protocol handler with read and write support.

tags/v0.9.3
Michael Brown 18 years ago
parent
commit
1961ba44e1
2 changed files with 127 additions and 0 deletions
  1. 122
    0
      src/drivers/nvs/spi.c
  2. 5
    0
      src/include/gpxe/spi.h

+ 122
- 0
src/drivers/nvs/spi.c View File

@@ -0,0 +1,122 @@
1
+/*
2
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
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
+#include <stddef.h>
20
+#include <errno.h>
21
+#include <timer.h>
22
+#include <gpxe/spi.h>
23
+
24
+/** @file
25
+ *
26
+ * SPI devices
27
+ *
28
+ */
29
+
30
+/**
31
+ * Munge SPI device address into command
32
+ *
33
+ * @v command		SPI command
34
+ * @v address		Address
35
+ * @v munge_address	Device requires address munging
36
+ * @ret command		Actual SPI command to use
37
+ *
38
+ * Some devices with 9-bit addresses (e.g. AT25040A EEPROM) use bit 3
39
+ * of the command byte as address bit A8, rather than having a
40
+ * two-byte address.  This function takes care of generating the
41
+ * appropriate command.
42
+ */
43
+static inline unsigned int spi_command ( unsigned int command,
44
+					 unsigned int address,
45
+					 int munge_address ) {
46
+	return ( command | ( ( ( address >> 8 ) & munge_address ) << 3 ) );
47
+}
48
+
49
+/**
50
+ * Wait for SPI device to complete operation
51
+ *
52
+ * @v device		SPI device
53
+ * @ret rc		Return status code
54
+ */
55
+static int spi_wait ( struct spi_device *device ) {
56
+	struct spi_bus *bus = device->bus;
57
+	uint8_t status;
58
+	int i;
59
+	int rc;
60
+
61
+	for ( i = 0 ; i < 50 ; i++ ) {
62
+		udelay ( 20 );
63
+		if ( ( rc = bus->rw ( bus, device, SPI_RDSR, -1, NULL,
64
+				      &status, sizeof ( status ) ) ) != 0 )
65
+			return rc;
66
+		if ( ! ( status & SPI_STATUS_NRDY ) )
67
+			return 0;
68
+	}
69
+	DBG ( "SPI %p timed out\n", device );
70
+	return -ETIMEDOUT;
71
+}
72
+
73
+/**
74
+ * Read data from SPI device
75
+ *
76
+ * @v nvs		NVS device
77
+ * @v address		Address from which to read
78
+ * @v data		Data buffer
79
+ * @v len		Length of data buffer
80
+ * @ret rc		Return status code
81
+ */
82
+int spi_read ( struct nvs_device *nvs, unsigned int address,
83
+	       void *data, unsigned int len ) {
84
+	struct spi_device *device = nvs_to_spi ( nvs );
85
+	struct spi_bus *bus = device->bus;
86
+	unsigned int command = spi_command ( SPI_READ, address,
87
+					     device->munge_address );
88
+
89
+	return bus->rw ( bus, device, command, address, NULL, data, len );
90
+}
91
+
92
+/**
93
+ * Write data to SPI device
94
+ *
95
+ * @v nvs		NVS device
96
+ * @v address		Address from which to read
97
+ * @v data		Data buffer
98
+ * @v len		Length of data buffer
99
+ * @ret rc		Return status code
100
+ */
101
+int spi_write ( struct nvs_device *nvs, unsigned int address,
102
+		const void *data, unsigned int len ) {
103
+	struct spi_device *device = nvs_to_spi ( nvs );
104
+	struct spi_bus *bus = device->bus;
105
+	unsigned int command = spi_command ( SPI_WRITE, address,
106
+					     device->munge_address );
107
+	int rc;
108
+
109
+	if ( ( rc = bus->rw ( bus, device, SPI_WREN, -1,
110
+			      NULL, NULL, 0 ) ) != 0 )
111
+		return rc;
112
+
113
+	if ( ( rc = bus->rw ( bus, device, command, address,
114
+			      data, NULL, len ) ) != 0 )
115
+		return rc;
116
+	
117
+	if ( ( rc = spi_wait ( device ) ) != 0 )
118
+		return rc;
119
+
120
+	return 0;
121
+}
122
+

+ 5
- 0
src/include/gpxe/spi.h View File

@@ -188,4 +188,9 @@ struct spi_bus {
188 188
  */
189 189
 #define SPI_MODE_THREEWIRE ( SPI_MODE_MICROWIRE_PLUS | SPI_MODE_SSPOL )
190 190
 
191
+extern int spi_read ( struct nvs_device *nvs, unsigned int address,
192
+		      void *data, size_t len );
193
+extern int spi_write ( struct nvs_device *nvs, unsigned int address,
194
+		       const void *data, size_t len );
195
+
191 196
 #endif /* _GPXE_SPI_H */

Loading…
Cancel
Save