aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ipq806x/patches-4.9/0012-spi-qup-refactor-spi_qup_io_config-in-two-functions.patch
blob: c88dd9b0ecb91e55128369b665a67b03852919b3 (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
From ef00ad56d728618203358d9eba7ca8e7eb48e701 Mon Sep 17 00:00:00 2001
From: Matthew McClintock <mmcclint@codeaurora.org>
Date: Tue, 26 Apr 2016 12:57:46 -0500
Subject: [PATCH 12/37] spi: qup: refactor spi_qup_io_config in two functions

This is preparation for handling transactions larger than 64K-1 bytes in
block mode which is currently unsupported quietly fails.

We need to break these into two functions 1) prep is called once per
spi_message and 2) io_config is calle once per spi-qup bus transaction

This is just refactoring, there should be no functional change

Signed-off-by: Matthew McClintock <mmcclint@codeaurora.org>
---
 drivers/spi/spi-qup.c |  141 ++++++++++++++++++++++++++++++-------------------
 1 file changed, 86 insertions(+), 55 deletions(-)

--- a/drivers/spi/spi-qup.c
+++ b/drivers/spi/spi-qup.c
@@ -585,12 +585,11 @@ static irqreturn_t spi_qup_qup_irq(int i
 	return IRQ_HANDLED;
 }
 
-/* set clock freq ... bits per word */
-static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer)
+/* set clock freq ... bits per word, determine mode */
+static int spi_qup_io_prep(struct spi_device *spi, struct spi_transfer *xfer)
 {
 	struct spi_qup *controller = spi_master_get_devdata(spi->master);
-	u32 config, iomode, control;
-	int ret, n_words;
+	int ret;
 
 	if (spi->mode & SPI_LOOP && xfer->len > controller->in_fifo_sz) {
 		dev_err(controller->dev, "too big size for loopback %d > %d\n",
@@ -605,56 +604,94 @@ static int spi_qup_io_config(struct spi_
 		return -EIO;
 	}
 
-	if (spi_qup_set_state(controller, QUP_STATE_RESET)) {
-		dev_err(controller->dev, "cannot set RESET state\n");
-		return -EIO;
-	}
-
 	controller->w_size = DIV_ROUND_UP(xfer->bits_per_word, 8);
 	controller->n_words = xfer->len / controller->w_size;
-	n_words = controller->n_words;
 
-	if (n_words <= (controller->in_fifo_sz / sizeof(u32))) {
+	if (controller->n_words <= (controller->in_fifo_sz / sizeof(u32)))
 		controller->mode = QUP_IO_M_MODE_FIFO;
-		writel_relaxed(n_words, controller->base + QUP_MX_READ_CNT);
-		writel_relaxed(n_words, controller->base + QUP_MX_WRITE_CNT);
-		/* must be zero for FIFO */
-		writel_relaxed(0, controller->base + QUP_MX_INPUT_CNT);
-		writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT);
-	} else if (spi->master->can_dma &&
-	    spi->master->can_dma(spi->master, spi, xfer) &&
-	    spi->master->cur_msg_mapped) {
+	else if (spi->master->can_dma &&
+		 spi->master->can_dma(spi->master, spi, xfer) &&
+		 spi->master->cur_msg_mapped)
 		controller->mode = QUP_IO_M_MODE_BAM;
-		writel_relaxed(n_words, controller->base + QUP_MX_INPUT_CNT);
-		writel_relaxed(n_words, controller->base + QUP_MX_OUTPUT_CNT);
-		/* must be zero for BLOCK and BAM */
-		writel_relaxed(0, controller->base + QUP_MX_READ_CNT);
-		writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT);
+	else
+		controller->mode = QUP_IO_M_MODE_BLOCK;
 
-		if (!controller->qup_v1) {
-			void __iomem *input_cnt;
+	return 0;
+}
 
-			input_cnt = controller->base + QUP_MX_INPUT_CNT;
-			/*
-			 * for DMA transfers, both QUP_MX_INPUT_CNT and
-			 * QUP_MX_OUTPUT_CNT must be zero to all cases but one.
-			 * That case is a non-balanced transfer when there is
-			 * only a rx_buf.
-			 */
-			if (xfer->tx_buf)
-				writel_relaxed(0, input_cnt);
-			else
-				writel_relaxed(n_words, input_cnt);
+/* prep qup for another spi transaction of specific type */
+static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer)
+{
+	struct spi_qup *controller = spi_master_get_devdata(spi->master);
+	u32 config, iomode, control;
+	unsigned long flags;
 
+	reinit_completion(&controller->done);
+	reinit_completion(&controller->dma_tx_done);
+
+	spin_lock_irqsave(&controller->lock, flags);
+	controller->xfer     = xfer;
+	controller->error    = 0;
+	controller->rx_bytes = 0;
+	controller->tx_bytes = 0;
+	spin_unlock_irqrestore(&controller->lock, flags);
+
+
+	if (spi_qup_set_state(controller, QUP_STATE_RESET)) {
+		dev_err(controller->dev, "cannot set RESET state\n");
+		return -EIO;
+	}
+
+	switch (controller->mode) {
+		case QUP_IO_M_MODE_FIFO:
+			writel_relaxed(controller->n_words,
+				       controller->base + QUP_MX_READ_CNT);
+			writel_relaxed(controller->n_words,
+				       controller->base + QUP_MX_WRITE_CNT);
+			/* must be zero for FIFO */
+			writel_relaxed(0, controller->base + QUP_MX_INPUT_CNT);
 			writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT);
-		}
-	} else {
-		controller->mode = QUP_IO_M_MODE_BLOCK;
-		writel_relaxed(n_words, controller->base + QUP_MX_INPUT_CNT);
-		writel_relaxed(n_words, controller->base + QUP_MX_OUTPUT_CNT);
-		/* must be zero for BLOCK and BAM */
-		writel_relaxed(0, controller->base + QUP_MX_READ_CNT);
-		writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT);
+			break;
+		case QUP_IO_M_MODE_BAM:
+			writel_relaxed(controller->n_words,
+				       controller->base + QUP_MX_INPUT_CNT);
+			writel_relaxed(controller->n_words,
+				       controller->base + QUP_MX_OUTPUT_CNT);
+			/* must be zero for BLOCK and BAM */
+			writel_relaxed(0, controller->base + QUP_MX_READ_CNT);
+			writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT);
+			if (!controller->qup_v1) {
+				void __iomem *input_cnt;
+
+				input_cnt = controller->base + QUP_MX_INPUT_CNT;
+				/*
+				 * for DMA transfers, both QUP_MX_INPUT_CNT and
+				 * QUP_MX_OUTPUT_CNT must be zero to all cases
+				 * but one. That case is a non-balanced
+				 * transfer when there is only a rx_buf.
+				 */
+				if (xfer->tx_buf)
+					writel_relaxed(0, input_cnt);
+				else
+					writel_relaxed(controller->n_words,
+						       input_cnt);
+
+				writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT);
+			}
+			break;
+		case QUP_IO_M_MODE_BLOCK:
+			writel_relaxed(controller->n_words,
+				       controller->base + QUP_MX_INPUT_CNT);
+			writel_relaxed(controller->n_words,
+				       controller->base + QUP_MX_OUTPUT_CNT);
+			/* must be zero for BLOCK and BAM */
+			writel_relaxed(0, controller->base + QUP_MX_READ_CNT);
+			writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT);
+			break;
+		default:
+			dev_err(controller->dev, "unknown mode = %d\n",
+					controller->mode);
+			return -EIO;
 	}
 
 	iomode = readl_relaxed(controller->base + QUP_IO_M_MODES);
@@ -743,6 +780,10 @@ static int spi_qup_transfer_one(struct s
 	unsigned long timeout, flags;
 	int ret = -EIO;
 
+	ret = spi_qup_io_prep(spi, xfer);
+	if (ret)
+		return ret;
+
 	ret = spi_qup_io_config(spi, xfer);
 	if (ret)
 		return ret;
@@ -751,16 +792,6 @@ static int spi_qup_transfer_one(struct s
 	timeout = DIV_ROUND_UP(xfer->len * 8, timeout);
 	timeout = 100 * msecs_to_jiffies(timeout);
 
-	reinit_completion(&controller->done);
-	reinit_completion(&controller->dma_tx_done);
-
-	spin_lock_irqsave(&controller->lock, flags);
-	controller->xfer     = xfer;
-	controller->error    = 0;
-	controller->rx_bytes = 0;
-	controller->tx_bytes = 0;
-	spin_unlock_irqrestore(&controller->lock, flags);
-
 	if (spi_qup_is_dma_xfer(controller->mode))
 		ret = spi_qup_do_dma(master, xfer, timeout);
 	else