Blame view

drivers/spi/spi-bcm2835aux.c 17.1 KB
c942fddf8   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
2
3
4
5
6
7
8
9
10
  /*
   * Driver for Broadcom BCM2835 auxiliary SPI Controllers
   *
   * the driver does not rely on the native chipselects at all
   * but only uses the gpio type chipselects
   *
   * Based on: spi-bcm2835.c
   *
   * Copyright (C) 2015 Martin Sperl
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
11
12
13
14
   */
  
  #include <linux/clk.h>
  #include <linux/completion.h>
8048d151e   Martin Sperl   spi: bcm2835aux: ...
15
  #include <linux/debugfs.h>
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  #include <linux/delay.h>
  #include <linux/err.h>
  #include <linux/interrupt.h>
  #include <linux/io.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/of.h>
  #include <linux/of_address.h>
  #include <linux/of_device.h>
  #include <linux/of_gpio.h>
  #include <linux/of_irq.h>
  #include <linux/regmap.h>
  #include <linux/spi/spi.h>
  #include <linux/spinlock.h>
5fd917afc   Martin Sperl   spi: bcm2835aux: ...
30
  /* define polling limits */
1a8fa5166   kbuild test robot   spi: bcm2835aux: ...
31
  static unsigned int polling_limit_us = 30;
5fd917afc   Martin Sperl   spi: bcm2835aux: ...
32
33
34
35
  module_param(polling_limit_us, uint, 0664);
  MODULE_PARM_DESC(polling_limit_us,
  		 "time in us to run a transfer in polling mode - if zero no polling is used
  ");
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
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
  /*
   * spi register defines
   *
   * note there is garbage in the "official" documentation,
   * so some data is taken from the file:
   *   brcm_usrlib/dag/vmcsx/vcinclude/bcm2708_chip/aux_io.h
   * inside of:
   *   http://www.broadcom.com/docs/support/videocore/Brcm_Android_ICS_Graphics_Stack.tar.gz
   */
  
  /* SPI register offsets */
  #define BCM2835_AUX_SPI_CNTL0	0x00
  #define BCM2835_AUX_SPI_CNTL1	0x04
  #define BCM2835_AUX_SPI_STAT	0x08
  #define BCM2835_AUX_SPI_PEEK	0x0C
  #define BCM2835_AUX_SPI_IO	0x20
  #define BCM2835_AUX_SPI_TXHOLD	0x30
  
  /* Bitfields in CNTL0 */
  #define BCM2835_AUX_SPI_CNTL0_SPEED	0xFFF00000
  #define BCM2835_AUX_SPI_CNTL0_SPEED_MAX	0xFFF
  #define BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT	20
  #define BCM2835_AUX_SPI_CNTL0_CS	0x000E0000
  #define BCM2835_AUX_SPI_CNTL0_POSTINPUT	0x00010000
  #define BCM2835_AUX_SPI_CNTL0_VAR_CS	0x00008000
  #define BCM2835_AUX_SPI_CNTL0_VAR_WIDTH	0x00004000
  #define BCM2835_AUX_SPI_CNTL0_DOUTHOLD	0x00003000
  #define BCM2835_AUX_SPI_CNTL0_ENABLE	0x00000800
e9dd4edcc   Stephan Olbrich   spi: bcm2835aux: ...
64
  #define BCM2835_AUX_SPI_CNTL0_IN_RISING	0x00000400
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
65
  #define BCM2835_AUX_SPI_CNTL0_CLEARFIFO	0x00000200
e9dd4edcc   Stephan Olbrich   spi: bcm2835aux: ...
66
  #define BCM2835_AUX_SPI_CNTL0_OUT_RISING	0x00000100
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
67
68
69
70
71
72
  #define BCM2835_AUX_SPI_CNTL0_CPOL	0x00000080
  #define BCM2835_AUX_SPI_CNTL0_MSBF_OUT	0x00000040
  #define BCM2835_AUX_SPI_CNTL0_SHIFTLEN	0x0000003F
  
  /* Bitfields in CNTL1 */
  #define BCM2835_AUX_SPI_CNTL1_CSHIGH	0x00000700
fe0e2304f   Stephan Olbrich   spi: bcm2835aux: ...
73
74
  #define BCM2835_AUX_SPI_CNTL1_TXEMPTY	0x00000080
  #define BCM2835_AUX_SPI_CNTL1_IDLE	0x00000040
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
75
76
77
78
79
80
81
82
83
84
85
86
  #define BCM2835_AUX_SPI_CNTL1_MSBF_IN	0x00000002
  #define BCM2835_AUX_SPI_CNTL1_KEEP_IN	0x00000001
  
  /* Bitfields in STAT */
  #define BCM2835_AUX_SPI_STAT_TX_LVL	0xFF000000
  #define BCM2835_AUX_SPI_STAT_RX_LVL	0x00FF0000
  #define BCM2835_AUX_SPI_STAT_TX_FULL	0x00000400
  #define BCM2835_AUX_SPI_STAT_TX_EMPTY	0x00000200
  #define BCM2835_AUX_SPI_STAT_RX_FULL	0x00000100
  #define BCM2835_AUX_SPI_STAT_RX_EMPTY	0x00000080
  #define BCM2835_AUX_SPI_STAT_BUSY	0x00000040
  #define BCM2835_AUX_SPI_STAT_BITCOUNT	0x0000003F
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
87
88
89
90
91
92
93
94
95
  struct bcm2835aux_spi {
  	void __iomem *regs;
  	struct clk *clk;
  	int irq;
  	u32 cntl[2];
  	const u8 *tx_buf;
  	u8 *rx_buf;
  	int tx_len;
  	int rx_len;
72aac02b3   Martin Sperl   spi: bcm2835aux: ...
96
  	int pending;
8048d151e   Martin Sperl   spi: bcm2835aux: ...
97
98
99
100
101
102
  
  	u64 count_transfer_polling;
  	u64 count_transfer_irq;
  	u64 count_transfer_irq_after_poll;
  
  	struct dentry *debugfs_dir;
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
103
  };
8048d151e   Martin Sperl   spi: bcm2835aux: ...
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
  #if defined(CONFIG_DEBUG_FS)
  static void bcm2835aux_debugfs_create(struct bcm2835aux_spi *bs,
  				      const char *dname)
  {
  	char name[64];
  	struct dentry *dir;
  
  	/* get full name */
  	snprintf(name, sizeof(name), "spi-bcm2835aux-%s", dname);
  
  	/* the base directory */
  	dir = debugfs_create_dir(name, NULL);
  	bs->debugfs_dir = dir;
  
  	/* the counters */
  	debugfs_create_u64("count_transfer_polling", 0444, dir,
  			   &bs->count_transfer_polling);
  	debugfs_create_u64("count_transfer_irq", 0444, dir,
  			   &bs->count_transfer_irq);
  	debugfs_create_u64("count_transfer_irq_after_poll", 0444, dir,
  			   &bs->count_transfer_irq_after_poll);
  }
  
  static void bcm2835aux_debugfs_remove(struct bcm2835aux_spi *bs)
  {
  	debugfs_remove_recursive(bs->debugfs_dir);
  	bs->debugfs_dir = NULL;
  }
  #else
9b186e9a6   YueHaibing   spi: bcm2835aux: ...
133
134
  static void bcm2835aux_debugfs_create(struct bcm2835aux_spi *bs,
  				      const char *dname)
8048d151e   Martin Sperl   spi: bcm2835aux: ...
135
136
137
138
139
140
141
  {
  }
  
  static void bcm2835aux_debugfs_remove(struct bcm2835aux_spi *bs)
  {
  }
  #endif /* CONFIG_DEBUG_FS */
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
142
143
144
145
146
147
148
149
150
151
152
153
154
155
  static inline u32 bcm2835aux_rd(struct bcm2835aux_spi *bs, unsigned reg)
  {
  	return readl(bs->regs + reg);
  }
  
  static inline void bcm2835aux_wr(struct bcm2835aux_spi *bs, unsigned reg,
  				 u32 val)
  {
  	writel(val, bs->regs + reg);
  }
  
  static inline void bcm2835aux_rd_fifo(struct bcm2835aux_spi *bs)
  {
  	u32 data;
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
156
157
158
159
  	int count = min(bs->rx_len, 3);
  
  	data = bcm2835aux_rd(bs, BCM2835_AUX_SPI_IO);
  	if (bs->rx_buf) {
72aac02b3   Martin Sperl   spi: bcm2835aux: ...
160
  		switch (count) {
72aac02b3   Martin Sperl   spi: bcm2835aux: ...
161
162
163
164
165
166
167
168
169
170
  		case 3:
  			*bs->rx_buf++ = (data >> 16) & 0xff;
  			/* fallthrough */
  		case 2:
  			*bs->rx_buf++ = (data >> 8) & 0xff;
  			/* fallthrough */
  		case 1:
  			*bs->rx_buf++ = (data >> 0) & 0xff;
  			/* fallthrough - no default */
  		}
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
171
172
  	}
  	bs->rx_len -= count;
72aac02b3   Martin Sperl   spi: bcm2835aux: ...
173
  	bs->pending -= count;
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
  }
  
  static inline void bcm2835aux_wr_fifo(struct bcm2835aux_spi *bs)
  {
  	u32 data;
  	u8 byte;
  	int count;
  	int i;
  
  	/* gather up to 3 bytes to write to the FIFO */
  	count = min(bs->tx_len, 3);
  	data = 0;
  	for (i = 0; i < count; i++) {
  		byte = bs->tx_buf ? *bs->tx_buf++ : 0;
  		data |= byte << (8 * (2 - i));
  	}
  
  	/* and set the variable bit-length */
  	data |= (count * 8) << 24;
  
  	/* and decrement length */
  	bs->tx_len -= count;
72aac02b3   Martin Sperl   spi: bcm2835aux: ...
196
  	bs->pending += count;
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
  
  	/* write to the correct TX-register */
  	if (bs->tx_len)
  		bcm2835aux_wr(bs, BCM2835_AUX_SPI_TXHOLD, data);
  	else
  		bcm2835aux_wr(bs, BCM2835_AUX_SPI_IO, data);
  }
  
  static void bcm2835aux_spi_reset_hw(struct bcm2835aux_spi *bs)
  {
  	/* disable spi clearing fifo and interrupts */
  	bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, 0);
  	bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0,
  		      BCM2835_AUX_SPI_CNTL0_CLEARFIFO);
  }
7188a6f0e   Martin Sperl   spi: bcm2835aux: ...
212
  static void bcm2835aux_spi_transfer_helper(struct bcm2835aux_spi *bs)
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
213
  {
73b114ee7   Martin Sperl   spi: bcm2835aux: ...
214
  	u32 stat = bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT);
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
215
  	/* check if we have data to read */
73b114ee7   Martin Sperl   spi: bcm2835aux: ...
216
217
  	for (; bs->rx_len && (stat & BCM2835_AUX_SPI_STAT_RX_LVL);
  	     stat = bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT))
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
218
  		bcm2835aux_rd_fifo(bs);
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
219
220
221
  
  	/* check if we have data to write */
  	while (bs->tx_len &&
72aac02b3   Martin Sperl   spi: bcm2835aux: ...
222
  	       (bs->pending < 12) &&
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
223
224
225
  	       (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
  		  BCM2835_AUX_SPI_STAT_TX_FULL))) {
  		bcm2835aux_wr_fifo(bs);
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
226
  	}
7188a6f0e   Martin Sperl   spi: bcm2835aux: ...
227
228
229
230
231
232
233
234
235
236
237
238
239
240
  }
  
  static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id)
  {
  	struct spi_master *master = dev_id;
  	struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
  
  	/* IRQ may be shared, so return if our interrupts are disabled */
  	if (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_CNTL1) &
  	      (BCM2835_AUX_SPI_CNTL1_TXEMPTY | BCM2835_AUX_SPI_CNTL1_IDLE)))
  		return IRQ_NONE;
  
  	/* do common fifo handling */
  	bcm2835aux_spi_transfer_helper(bs);
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
241

f29ab1845   Stephan Olbrich   spi: bcm2835aux: ...
242
243
244
245
246
  	if (!bs->tx_len) {
  		/* disable tx fifo empty interrupt */
  		bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1] |
  			BCM2835_AUX_SPI_CNTL1_IDLE);
  	}
b4e2adef6   Stephan Olbrich   spi: bcm2835aux: ...
247
  	/* and if rx_len is 0 then disable interrupts and wake up completion */
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
248
  	if (!bs->rx_len) {
b4e2adef6   Stephan Olbrich   spi: bcm2835aux: ...
249
  		bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
250
251
  		complete(&master->xfer_completion);
  	}
7188a6f0e   Martin Sperl   spi: bcm2835aux: ...
252
  	return IRQ_HANDLED;
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
  }
  
  static int __bcm2835aux_spi_transfer_one_irq(struct spi_master *master,
  					     struct spi_device *spi,
  					     struct spi_transfer *tfr)
  {
  	struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
  
  	/* enable interrupts */
  	bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1] |
  		BCM2835_AUX_SPI_CNTL1_TXEMPTY |
  		BCM2835_AUX_SPI_CNTL1_IDLE);
  
  	/* and wait for finish... */
  	return 1;
  }
  
  static int bcm2835aux_spi_transfer_one_irq(struct spi_master *master,
  					   struct spi_device *spi,
  					   struct spi_transfer *tfr)
  {
  	struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
8048d151e   Martin Sperl   spi: bcm2835aux: ...
275
276
  	/* update statistics */
  	bs->count_transfer_irq++;
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
277
278
279
280
281
282
  	/* fill in registers and fifos before enabling interrupts */
  	bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
  	bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]);
  
  	/* fill in tx fifo with data before enabling interrupts */
  	while ((bs->tx_len) &&
72aac02b3   Martin Sperl   spi: bcm2835aux: ...
283
  	       (bs->pending < 12) &&
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
284
285
286
287
288
289
290
291
292
293
294
  	       (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
  		  BCM2835_AUX_SPI_STAT_TX_FULL))) {
  		bcm2835aux_wr_fifo(bs);
  	}
  
  	/* now run the interrupt mode */
  	return __bcm2835aux_spi_transfer_one_irq(master, spi, tfr);
  }
  
  static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master,
  					    struct spi_device *spi,
72aac02b3   Martin Sperl   spi: bcm2835aux: ...
295
  					struct spi_transfer *tfr)
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
296
297
298
  {
  	struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
  	unsigned long timeout;
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
299

8048d151e   Martin Sperl   spi: bcm2835aux: ...
300
301
  	/* update statistics */
  	bs->count_transfer_polling++;
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
302
303
304
  	/* configure spi */
  	bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
  	bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]);
5fd917afc   Martin Sperl   spi: bcm2835aux: ...
305
306
  	/* set the timeout to at least 2 jiffies */
  	timeout = jiffies + 2 + HZ * polling_limit_us / 1000000;
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
307
308
309
  
  	/* loop until finished the transfer */
  	while (bs->rx_len) {
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
310

7188a6f0e   Martin Sperl   spi: bcm2835aux: ...
311
312
  		/* do common fifo handling */
  		bcm2835aux_spi_transfer_helper(bs);
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
313
314
315
316
317
318
319
320
321
  
  		/* there is still data pending to read check the timeout */
  		if (bs->rx_len && time_after(jiffies, timeout)) {
  			dev_dbg_ratelimited(&spi->dev,
  					    "timeout period reached: jiffies: %lu remaining tx/rx: %d/%d - falling back to interrupt mode
  ",
  					    jiffies - timeout,
  					    bs->tx_len, bs->rx_len);
  			/* forward to interrupt handler */
8048d151e   Martin Sperl   spi: bcm2835aux: ...
322
  			bs->count_transfer_irq_after_poll++;
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
323
324
325
326
  			return __bcm2835aux_spi_transfer_one_irq(master,
  							       spi, tfr);
  		}
  	}
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
327
328
329
330
331
332
333
334
335
  	/* and return without waiting for completion */
  	return 0;
  }
  
  static int bcm2835aux_spi_transfer_one(struct spi_master *master,
  				       struct spi_device *spi,
  				       struct spi_transfer *tfr)
  {
  	struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
5fd917afc   Martin Sperl   spi: bcm2835aux: ...
336
337
  	unsigned long spi_hz, clk_hz, speed, spi_used_hz;
  	unsigned long hz_per_byte, byte_limit;
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
338
339
340
341
342
343
344
345
  
  	/* calculate the registers to handle
  	 *
  	 * note that we use the variable data mode, which
  	 * is not optimal for longer transfers as we waste registers
  	 * resulting (potentially) in more interrupts when transferring
  	 * more than 12 bytes
  	 */
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
346
347
348
349
350
351
352
353
354
355
356
357
358
359
  
  	/* set clock */
  	spi_hz = tfr->speed_hz;
  	clk_hz = clk_get_rate(bs->clk);
  
  	if (spi_hz >= clk_hz / 2) {
  		speed = 0;
  	} else if (spi_hz) {
  		speed = DIV_ROUND_UP(clk_hz, 2 * spi_hz) - 1;
  		if (speed >  BCM2835_AUX_SPI_CNTL0_SPEED_MAX)
  			speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX;
  	} else { /* the slowest we can go */
  		speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX;
  	}
b4e2adef6   Stephan Olbrich   spi: bcm2835aux: ...
360
361
362
  	/* mask out old speed from previous spi_transfer */
  	bs->cntl[0] &= ~(BCM2835_AUX_SPI_CNTL0_SPEED);
  	/* set the new speed */
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
363
364
365
  	bs->cntl[0] |= speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT;
  
  	spi_used_hz = clk_hz / (2 * (speed + 1));
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
366
367
368
369
370
  	/* set transmit buffers and length */
  	bs->tx_buf = tfr->tx_buf;
  	bs->rx_buf = tfr->rx_buf;
  	bs->tx_len = tfr->len;
  	bs->rx_len = tfr->len;
72aac02b3   Martin Sperl   spi: bcm2835aux: ...
371
  	bs->pending = 0;
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
372

d704afffe   Trent Piepho   spi: bcm2835aux: ...
373
374
375
376
377
378
  	/* Calculate the estimated time in us the transfer runs.  Note that
  	 * there are are 2 idle clocks cycles after each chunk getting
  	 * transferred - in our case the chunk size is 3 bytes, so we
  	 * approximate this by 9 cycles/byte.  This is used to find the number
  	 * of Hz per byte per polling limit.  E.g., we can transfer 1 byte in
  	 * 30 µs per 300,000 Hz of bus clock.
72aac02b3   Martin Sperl   spi: bcm2835aux: ...
379
  	 */
5fd917afc   Martin Sperl   spi: bcm2835aux: ...
380
381
  	hz_per_byte = polling_limit_us ? (9 * 1000000) / polling_limit_us : 0;
  	byte_limit = hz_per_byte ? spi_used_hz / hz_per_byte : 1;
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
382
  	/* run in polling mode for short transfers */
5fd917afc   Martin Sperl   spi: bcm2835aux: ...
383
  	if (tfr->len < byte_limit)
72aac02b3   Martin Sperl   spi: bcm2835aux: ...
384
  		return bcm2835aux_spi_transfer_one_poll(master, spi, tfr);
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
385
386
387
388
  
  	/* run in interrupt mode for all others */
  	return bcm2835aux_spi_transfer_one_irq(master, spi, tfr);
  }
b4e2adef6   Stephan Olbrich   spi: bcm2835aux: ...
389
390
391
392
393
394
395
396
397
398
399
400
  static int bcm2835aux_spi_prepare_message(struct spi_master *master,
  					  struct spi_message *msg)
  {
  	struct spi_device *spi = msg->spi;
  	struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
  
  	bs->cntl[0] = BCM2835_AUX_SPI_CNTL0_ENABLE |
  		      BCM2835_AUX_SPI_CNTL0_VAR_WIDTH |
  		      BCM2835_AUX_SPI_CNTL0_MSBF_OUT;
  	bs->cntl[1] = BCM2835_AUX_SPI_CNTL1_MSBF_IN;
  
  	/* handle all the modes */
e9dd4edcc   Stephan Olbrich   spi: bcm2835aux: ...
401
  	if (spi->mode & SPI_CPOL) {
b4e2adef6   Stephan Olbrich   spi: bcm2835aux: ...
402
  		bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPOL;
e9dd4edcc   Stephan Olbrich   spi: bcm2835aux: ...
403
404
405
406
  		bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_OUT_RISING;
  	} else {
  		bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_IN_RISING;
  	}
b4e2adef6   Stephan Olbrich   spi: bcm2835aux: ...
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
  	bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
  	bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]);
  
  	return 0;
  }
  
  static int bcm2835aux_spi_unprepare_message(struct spi_master *master,
  					    struct spi_message *msg)
  {
  	struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
  
  	bcm2835aux_spi_reset_hw(bs);
  
  	return 0;
  }
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
422
423
424
425
426
427
428
  static void bcm2835aux_spi_handle_err(struct spi_master *master,
  				      struct spi_message *msg)
  {
  	struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
  
  	bcm2835aux_spi_reset_hw(bs);
  }
519f2c22a   Martin Sperl   spi: bcm2835aux: ...
429
430
431
432
433
434
435
  static int bcm2835aux_spi_setup(struct spi_device *spi)
  {
  	int ret;
  
  	/* sanity check for native cs */
  	if (spi->mode & SPI_NO_CS)
  		return 0;
ccd978b70   Martin Sperl   spi: bcm2835aux: ...
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
  	if (gpio_is_valid(spi->cs_gpio)) {
  		/* with gpio-cs set the GPIO to the correct level
  		 * and as output (in case the dt has the gpio not configured
  		 * as output but native cs)
  		 */
  		ret = gpio_direction_output(spi->cs_gpio,
  					    (spi->mode & SPI_CS_HIGH) ? 0 : 1);
  		if (ret)
  			dev_err(&spi->dev,
  				"could not set gpio %i as output: %i
  ",
  				spi->cs_gpio, ret);
  
  		return ret;
  	}
519f2c22a   Martin Sperl   spi: bcm2835aux: ...
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
  
  	/* for dt-backwards compatibility: only support native on CS0
  	 * known things not supported with broken native CS:
  	 * * multiple chip-selects: cs0-cs2 are all
  	 *     simultaniously asserted whenever there is a transfer
  	 *     this even includes SPI_NO_CS
  	 * * SPI_CS_HIGH: cs are always asserted low
  	 * * cs_change: cs is deasserted after each spi_transfer
  	 * * cs_delay_usec: cs is always deasserted one SCK cycle
  	 *     after the last transfer
  	 * probably more...
  	 */
  	dev_warn(&spi->dev,
  		 "Native CS is not supported - please configure cs-gpio in device-tree
  ");
  
  	if (spi->chip_select == 0)
  		return 0;
  
  	dev_warn(&spi->dev, "Native CS is not working for cs > 0
  ");
  
  	return -EINVAL;
  }
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
475
476
477
478
  static int bcm2835aux_spi_probe(struct platform_device *pdev)
  {
  	struct spi_master *master;
  	struct bcm2835aux_spi *bs;
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
479
480
481
482
  	unsigned long clk_hz;
  	int err;
  
  	master = spi_alloc_master(&pdev->dev, sizeof(*bs));
bf93b9512   Hoan Nguyen An   spi: bcm2835aux: ...
483
  	if (!master)
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
484
  		return -ENOMEM;
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
485
486
  
  	platform_set_drvdata(pdev, master);
e9dd4edcc   Stephan Olbrich   spi: bcm2835aux: ...
487
  	master->mode_bits = (SPI_CPOL | SPI_CS_HIGH | SPI_NO_CS);
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
488
  	master->bits_per_word_mask = SPI_BPW_MASK(8);
509c58362   Martin Sperl   spi: bcm2835aux: ...
489
490
491
492
493
494
495
496
497
498
499
500
  	/* even though the driver never officially supported native CS
  	 * allow a single native CS for legacy DT support purposes when
  	 * no cs-gpio is configured.
  	 * Known limitations for native cs are:
  	 * * multiple chip-selects: cs0-cs2 are all simultaniously asserted
  	 *     whenever there is a transfer -  this even includes SPI_NO_CS
  	 * * SPI_CS_HIGH: is ignores - cs are always asserted low
  	 * * cs_change: cs is deasserted after each spi_transfer
  	 * * cs_delay_usec: cs is always deasserted one SCK cycle after
  	 *     a spi_transfer
  	 */
  	master->num_chipselect = 1;
519f2c22a   Martin Sperl   spi: bcm2835aux: ...
501
  	master->setup = bcm2835aux_spi_setup;
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
502
503
  	master->transfer_one = bcm2835aux_spi_transfer_one;
  	master->handle_err = bcm2835aux_spi_handle_err;
b4e2adef6   Stephan Olbrich   spi: bcm2835aux: ...
504
505
  	master->prepare_message = bcm2835aux_spi_prepare_message;
  	master->unprepare_message = bcm2835aux_spi_unprepare_message;
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
506
507
508
509
510
  	master->dev.of_node = pdev->dev.of_node;
  
  	bs = spi_master_get_devdata(master);
  
  	/* the main area */
d1975d059   YueHaibing   spi: bcm2835aux: ...
511
  	bs->regs = devm_platform_ioremap_resource(pdev, 0);
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
512
513
514
515
516
517
  	if (IS_ERR(bs->regs)) {
  		err = PTR_ERR(bs->regs);
  		goto out_master_put;
  	}
  
  	bs->clk = devm_clk_get(&pdev->dev, NULL);
bfc7af6d6   YueHaibing   spi: bcm2835aux: ...
518
  	if (IS_ERR(bs->clk)) {
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
519
520
521
522
523
  		err = PTR_ERR(bs->clk);
  		dev_err(&pdev->dev, "could not get clk: %d
  ", err);
  		goto out_master_put;
  	}
07bce09e1   Martin Sperl   spi: bcm2835aux: ...
524
  	bs->irq = platform_get_irq(pdev, 0);
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
525
  	if (bs->irq <= 0) {
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
  		err = bs->irq ? bs->irq : -ENODEV;
  		goto out_master_put;
  	}
  
  	/* this also enables the HW block */
  	err = clk_prepare_enable(bs->clk);
  	if (err) {
  		dev_err(&pdev->dev, "could not prepare clock: %d
  ", err);
  		goto out_master_put;
  	}
  
  	/* just checking if the clock returns a sane value */
  	clk_hz = clk_get_rate(bs->clk);
  	if (!clk_hz) {
  		dev_err(&pdev->dev, "clock returns 0 Hz
  ");
  		err = -ENODEV;
  		goto out_clk_disable;
  	}
07bce09e1   Martin Sperl   spi: bcm2835aux: ...
546
547
  	/* reset SPI-HW block */
  	bcm2835aux_spi_reset_hw(bs);
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
548
549
550
551
552
553
554
555
556
  	err = devm_request_irq(&pdev->dev, bs->irq,
  			       bcm2835aux_spi_interrupt,
  			       IRQF_SHARED,
  			       dev_name(&pdev->dev), master);
  	if (err) {
  		dev_err(&pdev->dev, "could not request IRQ: %d
  ", err);
  		goto out_clk_disable;
  	}
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
557
558
559
560
561
562
  	err = devm_spi_register_master(&pdev->dev, master);
  	if (err) {
  		dev_err(&pdev->dev, "could not register SPI master: %d
  ", err);
  		goto out_clk_disable;
  	}
8048d151e   Martin Sperl   spi: bcm2835aux: ...
563
  	bcm2835aux_debugfs_create(bs, dev_name(&pdev->dev));
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
564
565
566
567
568
569
570
571
572
573
574
575
576
  	return 0;
  
  out_clk_disable:
  	clk_disable_unprepare(bs->clk);
  out_master_put:
  	spi_master_put(master);
  	return err;
  }
  
  static int bcm2835aux_spi_remove(struct platform_device *pdev)
  {
  	struct spi_master *master = platform_get_drvdata(pdev);
  	struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
8048d151e   Martin Sperl   spi: bcm2835aux: ...
577
  	bcm2835aux_debugfs_remove(bs);
1ea29b39f   Martin Sperl   spi: bcm2835aux: ...
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
  	bcm2835aux_spi_reset_hw(bs);
  
  	/* disable the HW block by releasing the clock */
  	clk_disable_unprepare(bs->clk);
  
  	return 0;
  }
  
  static const struct of_device_id bcm2835aux_spi_match[] = {
  	{ .compatible = "brcm,bcm2835-aux-spi", },
  	{}
  };
  MODULE_DEVICE_TABLE(of, bcm2835aux_spi_match);
  
  static struct platform_driver bcm2835aux_spi_driver = {
  	.driver		= {
  		.name		= "spi-bcm2835aux",
  		.of_match_table	= bcm2835aux_spi_match,
  	},
  	.probe		= bcm2835aux_spi_probe,
  	.remove		= bcm2835aux_spi_remove,
  };
  module_platform_driver(bcm2835aux_spi_driver);
  
  MODULE_DESCRIPTION("SPI controller driver for Broadcom BCM2835 aux");
  MODULE_AUTHOR("Martin Sperl <kernel@martin.sperl.org>");
22bf6cd2c   Stefan Wahren   spi: bcm2835: mak...
604
  MODULE_LICENSE("GPL");