summaryrefslogtreecommitdiffstats
path: root/include/spi.h
blob: ffd66478b194180e10db2649b96dee8280f77751 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
/*
 * Common SPI Interface: Controller-specific definitions
 *
 * (C) Copyright 2001
 * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com.
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#ifndef _SPI_H_
#define _SPI_H_

/* SPI mode flags */
#define	SPI_CPHA	0x01			/* clock phase */
#define	SPI_CPOL	0x02			/* clock polarity */
#define	SPI_MODE_0	(0|0)			/* (original MicroWire) */
#define	SPI_MODE_1	(0|SPI_CPHA)
#define	SPI_MODE_2	(SPI_CPOL|0)
#define	SPI_MODE_3	(SPI_CPOL|SPI_CPHA)
#define	SPI_CS_HIGH	0x04			/* CS active high */
#define	SPI_LSB_FIRST	0x08			/* per-word bits-on-wire */
#define	SPI_3WIRE	0x10			/* SI/SO signals shared */
#define	SPI_LOOP	0x20			/* loopback mode */
#define	SPI_SLAVE	0x40			/* slave mode */
#define	SPI_PREAMBLE	0x80			/* Skip preamble bytes */

/* SPI transfer flags */
#define SPI_XFER_BEGIN		0x01	/* Assert CS before transfer */
#define SPI_XFER_END		0x02	/* Deassert CS after transfer */
#define SPI_XFER_MMAP		0x08	/* Memory Mapped start */
#define SPI_XFER_MMAP_END	0x10	/* Memory Mapped End */
#define SPI_XFER_ONCE		(SPI_XFER_BEGIN | SPI_XFER_END)
#define SPI_XFER_U_PAGE		(1 << 5)

/* SPI TX operation modes */
#define SPI_OPM_TX_QPP		1 << 0

/* SPI RX operation modes */
#define SPI_OPM_RX_AS		1 << 0
#define SPI_OPM_RX_DOUT		1 << 1
#define SPI_OPM_RX_DIO		1 << 2
#define SPI_OPM_RX_QOF		1 << 3
#define SPI_OPM_RX_QIOF		1 << 4
#define SPI_OPM_RX_EXTN		SPI_OPM_RX_AS | SPI_OPM_RX_DOUT | \
				SPI_OPM_RX_DIO | SPI_OPM_RX_QOF | \
				SPI_OPM_RX_QIOF

/* SPI bus connection options */
#define SPI_CONN_DUAL_SHARED	1 << 0
#define SPI_CONN_DUAL_SEPARATED	1 << 1

/* Header byte that marks the start of the message */
#define SPI_PREAMBLE_END_BYTE	0xec

#define SPI_DEFAULT_WORDLEN 8

/**
 * struct spi_slave - Representation of a SPI slave
 *
 * Drivers are expected to extend this with controller-specific data.
 *
 * @bus:		ID of the bus that the slave is attached to.
 * @cs:			ID of the chip select connected to the slave.
 * @op_mode_rx:		SPI RX operation mode.
 * @op_mode_tx:		SPI TX operation mode.
 * @wordlen:		Size of SPI word in number of bits
 * @max_write_size:	If non-zero, the maximum number of bytes which can
 *			be written at once, excluding command bytes.
 * @memory_map:		Address of read-only SPI flash access.
 * @option:		Varies SPI bus options - separate, shared bus.
 * @flags:		Indication of SPI flags.
 */
struct spi_slave {
	unsigned int bus;
	unsigned int cs;
	u8 op_mode_rx;
	u8 op_mode_tx;
	unsigned int wordlen;
	unsigned int max_write_size;
	void *memory_map;
	u8 option;
	u8 flags;
};

/**
 * Initialization, must be called once on start up.
 *
 * TODO: I don't think we really need this.
 */
void spi_init(void);

/**
 * spi_do_alloc_slave - Allocate a new SPI slave (internal)
 *
 * Allocate and zero all fields in the spi slave, and set the bus/chip
 * select. Use the helper macro spi_alloc_slave() to call this.
 *
 * @offset:	Offset of struct spi_slave within slave structure.
 * @size:	Size of slave structure.
 * @bus:	Bus ID of the slave chip.
 * @cs:		Chip select ID of the slave chip on the specified bus.
 */
void *spi_do_alloc_slave(int offset, int size, unsigned int bus,
			 unsigned int cs);

/**
 * spi_alloc_slave - Allocate a new SPI slave
 *
 * Allocate and zero all fields in the spi slave, and set the bus/chip
 * select.
 *
 * @_struct:	Name of structure to allocate (e.g. struct tegra_spi).
 *		This structure must contain a member 'struct spi_slave *slave'.
 * @bus:	Bus ID of the slave chip.
 * @cs:		Chip select ID of the slave chip on the specified bus.
 */
#define spi_alloc_slave(_struct, bus, cs) \
	spi_do_alloc_slave(offsetof(_struct, slave), \
			    sizeof(_struct), bus, cs)

/**
 * spi_alloc_slave_base - Allocate a new SPI slave with no private data
 *
 * Allocate and zero all fields in the spi slave, and set the bus/chip
 * select.
 *
 * @bus:	Bus ID of the slave chip.
 * @cs:		Chip select ID of the slave chip on the specified bus.
 */
#define spi_alloc_slave_base(bus, cs) \
	spi_do_alloc_slave(0, sizeof(struct spi_slave), bus, cs)

/**
 * Set up communications parameters for a SPI slave.
 *
 * This must be called once for each slave. Note that this function
 * usually doesn't touch any actual hardware, it only initializes the
 * contents of spi_slave so that the hardware can be easily
 * initialized later.
 *
 * @bus:	Bus ID of the slave chip.
 * @cs:		Chip select ID of the slave chip on the specified bus.
 * @max_hz:	Maximum SCK rate in Hz.
 * @mode:	Clock polarity, clock phase and other parameters.
 *
 * Returns: A spi_slave reference that can be used in subsequent SPI
 * calls, or NULL if one or more of the parameters are not supported.
 */
struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
		unsigned int max_hz, unsigned int mode);

/**
 * Free any memory associated with a SPI slave.
 *
 * @slave:	The SPI slave
 */
void spi_free_slave(struct spi_slave *slave);

/**
 * Claim the bus and prepare it for communication with a given slave.
 *
 * This must be called before doing any transfers with a SPI slave. It
 * will enable and initialize any SPI hardware as necessary, and make
 * sure that the SCK line is in the correct idle state. It is not
 * allowed to claim the same bus for several slaves without releasing
 * the bus in between.
 *
 * @slave:	The SPI slave
 *
 * Returns: 0 if the bus was claimed successfully, or a negative value
 * if it wasn't.
 */
int spi_claim_bus(struct spi_slave *slave);

/**
 * Release the SPI bus
 *
 * This must be called once for every call to spi_claim_bus() after
 * all transfers have finished. It may disable any SPI hardware as
 * appropriate.
 *
 * @slave:	The SPI slave
 */
void spi_release_bus(struct spi_slave *slave);

/**
 * Set the word length for SPI transactions
 *
 * Set the word length (number of bits per word) for SPI transactions.
 *
 * @slave:	The SPI slave
 * @wordlen:	The number of bits in a word
 *
 * Returns: 0 on success, -1 on failure.
 */
int spi_set_wordlen(struct spi_slave *slave, unsigned int wordlen);

/**
 * SPI transfer
 *
 * This writes "bitlen" bits out the SPI MOSI port and simultaneously clocks
 * "bitlen" bits in the SPI MISO port.  That's just the way SPI works.
 *
 * The source of the outgoing bits is the "dout" parameter and the
 * destination of the input bits is the "din" parameter.  Note that "dout"
 * and "din" can point to the same memory location, in which case the
 * input data overwrites the output data (since both are buffered by
 * temporary variables, this is OK).
 *
 * spi_xfer() interface:
 * @slave:	The SPI slave which will be sending/receiving the data.
 * @bitlen:	How many bits to write and read.
 * @dout:	Pointer to a string of bits to send out.  The bits are
 *		held in a byte array and are sent MSB first.
 * @din:	Pointer to a string of bits that will be filled in.
 * @flags:	A bitwise combination of SPI_XFER_* flags.
 *
 * Returns: 0 on success, not 0 on failure
 */
int  spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
		void *din, unsigned long flags);

/**
 * Determine if a SPI chipselect is valid.
 * This function is provided by the board if the low-level SPI driver
 * needs it to determine if a given chipselect is actually valid.
 *
 * Returns: 1 if bus:cs identifies a valid chip on this board, 0
 * otherwise.
 */
int  spi_cs_is_valid(unsigned int bus, unsigned int cs);

/**
 * Activate a SPI chipselect.
 * This function is provided by the board code when using a driver
 * that can't control its chipselects automatically (e.g.
 * common/soft_spi.c). When called, it should activate the chip select
 * to the device identified by "slave".
 */
void spi_cs_activate(struct spi_slave *slave);

/**
 * Deactivate a SPI chipselect.
 * This function is provided by the board code when using a driver
 * that can't control its chipselects automatically (e.g.
 * common/soft_spi.c). When called, it should deactivate the chip
 * select to the device identified by "slave".
 */
void spi_cs_deactivate(struct spi_slave *slave);

/**
 * Set transfer speed.
 * This sets a new speed to be applied for next spi_xfer().
 * @slave:	The SPI slave
 * @hz:		The transfer speed
 */
void spi_set_speed(struct spi_slave *slave, uint hz);

/**
 * Write 8 bits, then read 8 bits.
 * @slave:	The SPI slave we're communicating with
 * @byte:	Byte to be written
 *
 * Returns: The value that was read, or a negative value on error.
 *
 * TODO: This function probably shouldn't be inlined.
 */
static inline int spi_w8r8(struct spi_slave *slave, unsigned char byte)
{
	unsigned char dout[2];
	unsigned char din[2];
	int ret;

	dout[0] = byte;
	dout[1] = 0;

	ret = spi_xfer(slave, 16, dout, din, SPI_XFER_BEGIN | SPI_XFER_END);
	return ret < 0 ? ret : din[1];
}

/**
 * Set up a SPI slave for a particular device tree node
 *
 * This calls spi_setup_slave() with the correct bus number. Call
 * spi_free_slave() to free it later.
 *
 * @param blob:		Device tree blob
 * @param slave_node:	Slave node to use
 * @param spi_node:	SPI peripheral node to use
 * @return pointer to new spi_slave structure
 */
struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node,
				      int spi_node);

/**
 * spi_base_setup_slave_fdt() - helper function to set up a SPI slace
 *
 * This decodes SPI properties from the slave node to determine the
 * chip select and SPI parameters.
 *
 * @blob:	Device tree blob
 * @busnum:	Bus number to use
 * @node:	Device tree node for the SPI bus
 */
struct spi_slave *spi_base_setup_slave_fdt(const void *blob, int busnum,
					   int node);

#endif	/* _SPI_H_ */
OpenPOWER on IntegriCloud