iPXE
threewire.c
Go to the documentation of this file.
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., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27#include <stddef.h>
28#include <string.h>
29#include <assert.h>
30#include <unistd.h>
31#include <ipxe/threewire.h>
32
33/** @file
34 *
35 * Three-wire serial devices
36 *
37 */
38
39/**
40 * Read data from three-wire device
41 *
42 * @v nvs NVS device
43 * @v address Address from which to read
44 * @v data Data buffer
45 * @v len Length of data buffer
46 * @ret rc Return status code
47 */
48int threewire_read ( struct nvs_device *nvs, unsigned int address,
49 void *data, size_t len ) {
50 struct spi_device *device = nvs_to_spi ( nvs );
51 struct spi_bus *bus = device->bus;
52 int rc;
53
54 assert ( bus->mode == SPI_MODE_THREEWIRE );
55
56 DBGC ( device, "3wire %p reading %zd bytes at %04x\n",
57 device, len, address );
58
59 if ( ( rc = bus->rw ( bus, device, THREEWIRE_READ, address,
60 NULL, data, len ) ) != 0 ) {
61 DBGC ( device, "3wire %p could not read: %s\n",
62 device, strerror ( rc ) );
63 return rc;
64 }
65
66 return 0;
67}
68
69/**
70 * Write data to three-wire device
71 *
72 * @v nvs NVS device
73 * @v address Address from which to read
74 * @v data Data buffer
75 * @v len Length of data buffer
76 * @ret rc Return status code
77 */
78int threewire_write ( struct nvs_device *nvs, unsigned int address,
79 const void *data, size_t len ) {
80 struct spi_device *device = nvs_to_spi ( nvs );
81 struct spi_bus *bus = device->bus;
82 int rc;
83
84 assert ( bus->mode == SPI_MODE_THREEWIRE );
85
86 DBGC ( device, "3wire %p writing %zd bytes at %04x\n",
87 device, len, address );
88
89 /* Enable device for writing */
90 if ( ( rc = bus->rw ( bus, device, THREEWIRE_EWEN,
91 THREEWIRE_EWEN_ADDRESS, NULL, NULL, 0 ) ) != 0 ){
92 DBGC ( device, "3wire %p could not enable writing: %s\n",
93 device, strerror ( rc ) );
94 return rc;
95 }
96
97 /* Write data */
98 if ( ( rc = bus->rw ( bus, device, THREEWIRE_WRITE, address,
99 data, NULL, len ) ) != 0 ) {
100 DBGC ( device, "3wire %p could not write: %s\n",
101 device, strerror ( rc ) );
102 return rc;
103 }
104
105 /* Our model of an SPI bus doesn't provide a mechanism for
106 * "assert CS, wait for MISO to become high, so just wait for
107 * long enough to ensure that the write has completed.
108 */
110
111 return 0;
112}
113
114/**
115 * Autodetect device address length
116 *
117 * @v device SPI device
118 * @ret rc Return status code
119 */
121 struct nvs_device *nvs = &device->nvs;
122 int rc;
123
124 DBGC ( device, "3wire %p autodetecting address length\n", device );
125
126 device->address_len = SPI_AUTODETECT_ADDRESS_LEN;
127 if ( ( rc = threewire_read ( nvs, 0, NULL,
128 ( 1 << nvs->word_len_log2 ) ) ) != 0 ) {
129 DBGC ( device, "3wire %p could not autodetect address "
130 "length: %s\n", device, strerror ( rc ) );
131 return rc;
132 }
133
134 DBGC ( device, "3wire %p autodetected address length %d\n",
135 device, device->address_len );
136 return 0;
137}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
Assertions.
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
ring len
Length.
Definition dwmac.h:226
uint8_t bus
Bus.
Definition edd.h:1
uint8_t data[48]
Additional event data.
Definition ena.h:11
uint64_t address
Base address.
Definition ena.h:13
#define DBGC(...)
Definition compiler.h:505
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
#define THREEWIRE_WRITE_MDELAY
Time to wait for write cycles to complete.
Definition threewire.h:41
#define THREEWIRE_WRITE
Write data to memory array.
Definition threewire.h:28
#define THREEWIRE_EWEN
Write enable.
Definition threewire.h:31
#define THREEWIRE_EWEN_ADDRESS
Address to be used for write enable command.
Definition threewire.h:34
#define THREEWIRE_READ
Read data from memory array.
Definition threewire.h:25
String functions.
#define SPI_MODE_THREEWIRE
Threewire-compatible mode.
Definition spi.h:200
#define SPI_AUTODETECT_ADDRESS_LEN
SPI magic autodetection address length.
Definition spi.h:114
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
A hardware device.
Definition device.h:77
A non-volatile storage device.
Definition nvs.h:16
unsigned int word_len_log2
Word length.
Definition nvs.h:23
An SPI bus.
Definition spi.h:127
An SPI device.
Definition spi.h:87
struct nvs_device nvs
NVS device.
Definition spi.h:89
int threewire_detect_address_len(struct spi_device *device)
Autodetect device address length.
Definition threewire.c:120
int threewire_read(struct nvs_device *nvs, unsigned int address, void *data, size_t len)
Read data from three-wire device.
Definition threewire.c:48
int threewire_write(struct nvs_device *nvs, unsigned int address, const void *data, size_t len)
Write data to three-wire device.
Definition threewire.c:78
Three-wire serial interface.
void mdelay(unsigned long msecs)
Delay for a fixed number of milliseconds.
Definition timer.c:79