summaryrefslogtreecommitdiff
path: root/target/linux/brcm2708/patches-3.10/0056-spi-bcm2708-add-9-bit-support-using-LoSSI-mode.patch
blob: d7ad5a293c693f27909b92b7562077889ec90c6f (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
From 75c9b03f90ca974cb072d96f423884b773ca5425 Mon Sep 17 00:00:00 2001
From: notro <notro@tronnes.org>
Date: Sat, 26 Jan 2013 20:38:03 +0100
Subject: [PATCH 056/174] spi-bcm2708: add 9-bit support using LoSSI mode

---
 drivers/spi/spi-bcm2708.c | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

--- a/drivers/spi/spi-bcm2708.c
+++ b/drivers/spi/spi-bcm2708.c
@@ -146,10 +146,31 @@ static inline void bcm2708_rd_fifo(struc
 static inline void bcm2708_wr_fifo(struct bcm2708_spi *bs, int len)
 {
 	u8 byte;
+	u16 val;
 
 	if (len > bs->len)
 		len = bs->len;
 
+	if (unlikely(bcm2708_rd(bs, SPI_CS) & SPI_CS_LEN)) {
+		/* LoSSI mode */
+		if (unlikely(len % 2)) {
+			printk(KERN_ERR"bcm2708_wr_fifo: length must be even, skipping.\n");
+			bs->len = 0;
+			return;
+		}
+		while (len) {
+			if (bs->tx_buf) {
+				val = *(const u16 *)bs->tx_buf;
+				bs->tx_buf += 2;
+			} else
+				val = 0;
+			bcm2708_wr(bs, SPI_FIFO, val);
+			bs->len -= 2;
+			len -= 2;
+		}
+		return;
+	}
+
 	while (len--) {
 		byte = bs->tx_buf ? *bs->tx_buf++ : 0;
 		bcm2708_wr(bs, SPI_FIFO, byte);
@@ -234,8 +255,12 @@ static int bcm2708_setup_state(struct sp
 	switch (bpw) {
 	case 8:
 		break;
+	case 9:
+		/* Reading in LoSSI mode is a special case. See 'BCM2835 ARM Peripherals' datasheet */
+		cs |= SPI_CS_LEN;
+		break;
 	default:
-		dev_dbg(dev, "setup: invalid bits_per_word %u (must be 8)\n",
+		dev_dbg(dev, "setup: invalid bits_per_word %u (must be 8 or 9)\n",
 			bpw);
 		return -EINVAL;
 	}
@@ -283,7 +308,8 @@ static int bcm2708_process_transfer(stru
 		ret = bcm2708_setup_state(spi->master, &spi->dev, &state,
 			xfer->speed_hz ? xfer->speed_hz : spi->max_speed_hz,
 			spi->chip_select, spi->mode,
-			spi->bits_per_word);
+			xfer->bits_per_word ? xfer->bits_per_word :
+				spi->bits_per_word);
 		if (ret)
 			return ret;