blob: c43aabce2316675b674f56121a9a3377cd727a51 [file] [log] [blame]
Maria Yubeabb332017-03-02 17:04:24 +08001/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation, Inc. nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/*
30 * QUP spi driver for Qualcomm MSM platforms
31 *
32 */
33
34#include <debug.h>
35#include <arch/arm.h>
36#include <reg.h>
37#include <kernel/thread.h>
38#include <stdlib.h>
39#include <string.h>
40#include <gsbi.h>
41#include <spi_qup.h>
42#include <platform/irqs.h>
43#include <platform/iomap.h>
44#include <platform/gpio.h>
45#include <platform/clock.h>
46#include <platform/timer.h>
47#include <platform/interrupts.h>
48
49//#define DEBUGLEVEL 3
50
51static unsigned int spi_get_qup_hw_ver(struct qup_spi_dev *dev)
52{
53 unsigned int data = readl_relaxed(dev->qup_base + QUP_HW_VERSION);
54
55 dprintf(SPEW, "Qup hardware version is 0x%x\n", data);
56 return data;
57}
58
59static void qup_print_status(struct qup_spi_dev *dev)
60{
61 unsigned val;
62 val = readl(dev->qup_base + QUP_CONFIG);
63 dprintf(SPEW, "Qup config is :0x%x\n", val);
64 val = readl(dev->qup_base + QUP_STATE);
65 dprintf(SPEW, "Qup state is :0x%x\n", val);
66 val = readl(dev->qup_base + QUP_IO_MODES);
67 dprintf(SPEW, "Qup mode is :0x%x\n", val);
68 val = readl(dev->qup_base + SPI_IO_CONTROL);
69 dprintf(SPEW, "SPI_IO_CONTROL is :0x%x\n", val);
70 val = readl(dev->qup_base + SPI_CONFIG);
71 dprintf(SPEW, "SPI_CONFIG is :0x%x\n", val);
72 val = readl(dev->qup_base + QUP_MX_WRITE_CNT_CURRENT);
73 dprintf(SPEW, "QUP_MX_WRITE_CNT_CURRENT is :0x%x\n", val);
74 val = readl(dev->qup_base + QUP_MX_WRITE_CNT);
75 dprintf(SPEW, "QUP_MX_WRITE_CNT is :0x%x\n", val);
76 val = readl(dev->qup_base + QUP_MX_OUTPUT_CNT_CURRENT);
77 dprintf(SPEW, "QUP_MX_OUTPUT_CNT_CURRENT is :0x%x\n", val);
78 val = readl(dev->qup_base + QUP_MX_OUTPUT_CNT);
79 dprintf(SPEW, "QUP_MX_OUTPUT_CNT is :0x%x\n", val);
80 val = readl(dev->qup_base + QUP_OPERATIONAL);
81 dprintf(SPEW, "QUP_OPERATIONAL is :0x%x\n", val);
82 val = readl(dev->qup_base + QUP_OUTPUT_FIFO_WORD_CNT);
83 dprintf(SPEW, "QUP_OUTPUT_FIFO_WORD_CNT is :0x%x\n", val);
84}
85
86static inline bool qup_state_is_valid(struct qup_spi_dev *dev)
87{
88 unsigned int st = readl_relaxed(dev->qup_base + QUP_STATE);
89
90 return st & QUP_STATE_VALID;
91}
92
93static inline int qup_wait_state_valid(struct qup_spi_dev *dev)
94{
95 unsigned retries = 0xFFFF;
96
97 while (!qup_state_is_valid(dev) && (--retries != 0));
98
99 if(!retries)
100 return -ETIMEDOUT;
101
102 return 0;
103}
104
105static int qup_poll_state(struct qup_spi_dev *dev, unsigned state)
106{
107 int ret = 0;
108 unsigned int status;
109
110 ret = qup_wait_state_valid(dev);
111
112 if(ret)
113 goto exit;
114
115 status = readl(dev->qup_base + QUP_STATE);
116 if ((status & (QUP_STATE_VALID | state)) ==
117 (QUP_STATE_VALID | state))
118 return 0;
119
120exit:
121 dprintf(SPEW, "Polling fail for state:0x%x\n", state);
122 qup_print_status(dev);
123 return ret;
124}
125
126static inline int qup_set_state(struct qup_spi_dev *dev,
127 enum qup_state state)
128{
129 enum qup_state cur_state;
130
131 if (qup_wait_state_valid(dev)) {
132 qup_print_status(dev);
133 return -EIO;
134 }
135
136 cur_state = readl_relaxed(dev->qup_base + QUP_STATE);
137
138 /* For PAUSE_STATE to RESET_STATE,
139 * two writes of (0b10) are required.
140 */
141 if (((cur_state & QUP_STATE_MASK) == QUP_PAUSE_STATE) &&
142 (state == QUP_RESET_STATE)) {
143 writel(QUP_STATE_CLEAR_BITS, dev->qup_base + QUP_STATE);
144 writel(QUP_STATE_CLEAR_BITS, dev->qup_base + QUP_STATE);
145 } else {
146 writel((cur_state & ~QUP_STATE_MASK) | state,
147 dev->qup_base + QUP_STATE);
148 }
149
150 if (qup_poll_state(dev, state)) {
151 return -EIO;
152 }
153
154 return 0;
155}
156
157static inline void qup_register_init(struct qup_spi_dev *dev)
158{
159 /* Initialize QUP registers */
160 qup_set_state(dev, QUP_RESET_STATE);
161 writel(0x00000001, dev->qup_base + QUP_SW_RESET);
162 qup_wait_state_valid(dev);
163 qup_set_state(dev, QUP_RESET_STATE);
164
165 writel(0x00000000, dev->qup_base + QUP_CONFIG);
166 writel(0x00000000, dev->qup_base + QUP_IO_MODES);
167 writel(0xfff0, dev->qup_base + QUP_OPERATIONAL);
168 writel(0x7e, dev->qup_base + QUP_ERROR_FLAGS);
169 writel(0x00000000, dev->qup_base + QUP_TEST_CTRL);
170 writel(0x00000000, dev->qup_base + QUP_OPERATIONAL_MASK);
171 writel(0x0, dev->qup_base + QUP_MX_INPUT_CNT);
172 writel(0x1, dev->qup_base + QUP_MX_OUTPUT_CNT);
173 writel(0x0, dev->qup_base + QUP_MX_READ_CNT);
174}
175
176static inline void spi_register_init(struct qup_spi_dev *dev)
177{
178 /* Set SPI mini core to QUP config */
179 writel(QUP_CONFIG_SPI_MODE | QUP_CONFIG_NO_INPUT, dev->qup_base + QUP_CONFIG);
180
181 /* Initialize SPI mini core registers */
182 writel(0, dev->qup_base + SPI_CONFIG);
183 writel(SPI_IO_C_NO_TRI_STATE | SPI_IO_C_CS_SELECT_CS0 | SPI_IO_C_CLK_IDLE_HIGH,
184 dev->qup_base + SPI_IO_CONTROL);
185 writel(SPI_ERROR_CLK_OVER_RUN | SPI_ERROR_CLK_UNDER_RUN, dev->qup_base + SPI_ERROR_FLAGS_EN);
186 writel(0, dev->qup_base + SPI_DEASSERT_WAIT);
187
188 qup_print_status(dev);
189}
190
191static void spi_qup_io_config_block(struct qup_spi_dev *dev, int len)
192{
193 unsigned int config, iomode, mode;
194 unsigned int bits_per_word;
195
196 qup_register_init(dev);
197 spi_register_init(dev);
198
199 /* bytes_per_word valid range is [1-4].
200 * Other value may not working as expected.
201 */
202 dev->bytes_per_word = dev->bytes_per_word % 5;
203
204 /* If bytes_per_word not given, use DEFAULT_BYTES_PER_WORD.
205 */
206 if(!dev->bytes_per_word)
207 dev->bytes_per_word = DEFAULT_BYTES_PER_WORD;
208
209 bits_per_word = dev->bytes_per_word * 8 - 1;
210
211 writel(len / dev->bytes_per_word, dev->qup_base + QUP_MX_OUTPUT_CNT);
212 writel(0, dev->qup_base + QUP_MX_INPUT_CNT);
213 writel(0, dev->qup_base + QUP_MX_READ_CNT);
214 writel(0, dev->qup_base + QUP_MX_WRITE_CNT);
215
216 mode = QUP_IO_MODES_BLOCK;
217 iomode = readl_relaxed(dev->qup_base + QUP_IO_MODES);
218 iomode &= ~(INPUT_MODE_MASK | OUTPUT_MODE_MASK);
219 if(dev->unpack_en)
220 iomode |= QUP_IO_MODES_UNPACK_EN;
221 else
222 iomode &= ~QUP_IO_MODES_UNPACK_EN;
223 iomode |= (mode << OUTPUT_MODE_SHIFT);
224 iomode |= (mode << INPUT_MODE_SHIFT);
225 if(dev->bit_shift_en)
226 iomode |= QUP_IO_MODES_OUTPUT_BIT_SHIFT_EN;
227 else
228 iomode &= ~QUP_IO_MODES_OUTPUT_BIT_SHIFT_EN;
229 writel(iomode, dev->qup_base + QUP_IO_MODES);
230
231 config = readl_relaxed(dev->qup_base + QUP_CONFIG);
232 config |= QUP_CONFIG_NO_INPUT;
233 config |= QUP_CONFIG_SPI_MODE;
234 config |= bits_per_word;
235 writel(config, dev->qup_base + QUP_CONFIG);
236
237 writel(0, dev->qup_base + QUP_OPERATIONAL_MASK);
238
239 unmask_interrupt(dev->qup_irq);
240}
241
242static void spi_qup_fifo_write(struct qup_spi_dev *dev, struct spi_transfer *xfer)
243{
244 const unsigned char *tx_buf = xfer->tx_buf;
245 unsigned int word, state, data;
246 unsigned int idx;
247
248 while (dev->tx_bytes < xfer->len) {
249
250 state = readl_relaxed(dev->qup_base + QUP_OPERATIONAL);
251 if (state & QUP_OP_OUT_FIFO_FULL)
252 {
253 dprintf(SPEW, "%s: oper QUP_OP_OUT_FIFO_FULL: 0x%x"
254 "dev->tx_bytes:0x%x, xfer->len:0x%x\n",
255 __func__, state, dev->tx_bytes, xfer->len);
256 break;
257 }
258
259 word = 0;
260 for (idx = 0; idx < dev->bytes_per_word; idx++, dev->tx_bytes++) {
261
262 if (!tx_buf) {
263 dprintf(CRITICAL, "%s: tx_buf null error.\n", __func__);
264 dev->tx_bytes += dev->bytes_per_word;
265 break;
266 }
267 data = dev->tx_bytes < xfer->len ? tx_buf[dev->tx_bytes] : 0;
268 word |= data << (BITS_PER_BYTE * idx);
269 }
270
271 writel(word, dev->qup_base + QUP_OUTPUT_FIFO_BASE);
272 }
273}
274
275int _spi_qup_transfer(struct qup_spi_dev *dev, struct spi_transfer *xfer)
276{
277 int ret = -EIO;
278 int retries = 0xFF;
279 unsigned val;
280
281 dev->xfer = xfer;
282 dev->tx_bytes = 0;
283
284 spi_qup_io_config_block(dev, xfer->len);
285
286 ret = qup_set_state(dev, QUP_RUN_STATE);
287 if (ret) {
288 dprintf(CRITICAL, "%s: cannot set first RUN state\n", __func__);
289 goto exit;
290 }
291
292 while((readl(dev->qup_base + QUP_MX_OUTPUT_CNT)
293 != readl(dev->qup_base + QUP_MX_OUTPUT_CNT_CURRENT))
294 && retries--);
295
296 while(readl(dev->qup_base + QUP_MX_OUTPUT_CNT_CURRENT) ) {
297 val = readl(dev->qup_base + QUP_OPERATIONAL);
298 val &= ~QUP_OP_OUT_SERVICE_FLAG;
299 writel(val, dev->qup_base + QUP_OPERATIONAL);
300
301 ret = qup_set_state(dev, QUP_PAUSE_STATE);
302 if (ret) {
303 dprintf(CRITICAL, "%s: cannot set PAUSE state\n", __func__);
304 goto exit;
305 }
306
307 spi_qup_fifo_write(dev, xfer);
308
309 ret = qup_set_state(dev, QUP_RUN_STATE);
310 if (ret) {
311 dprintf(CRITICAL, "%s: cannot set RUN state\n", __func__);
312 goto exit;
313 }
314 }
315 dprintf(SPEW, "dev->tx_bytes:0x%x, xfer->len:0x%x\n",
316 dev->tx_bytes, xfer->len);
317
318exit:
319 qup_set_state(dev, QUP_RESET_STATE);
320 dev->xfer = NULL;
321 return ret;
322}
323
324/**
325 * @brief Transfer data_size bytes data from tx_buf via spi
326 * @param dev SPI config structure initialized from qup_blsp_spi_init
327 * @param tx_buf output buffer pointer
328 * @param data_size Should be multiple of max bytes per word
329 */
330int spi_qup_transfer(struct qup_spi_dev *dev, const unsigned char * tx_buf, unsigned int data_size)
331{
332 unsigned int cur = 0;
333 struct spi_transfer s_xfer;
334 int ret = -EIO;
335
336 if(!tx_buf)
337 return ret;
338
339 while(data_size > MAX_QUP_MX_OUTPUT_COUNT + cur) {
340 s_xfer.len = MAX_QUP_MX_OUTPUT_COUNT;
341 s_xfer.tx_buf = tx_buf + cur;
342
343 ret = _spi_qup_transfer(dev, &s_xfer);
344 if (ret)
345 goto exit;
346
347 cur += MAX_QUP_MX_OUTPUT_COUNT;
348 }
349
350 s_xfer.len = data_size - cur;
351 s_xfer.tx_buf = tx_buf + cur;
352 ret = _spi_qup_transfer(dev, &s_xfer);
353 if (ret)
354 goto exit;
355 return ret;
356
357exit:
358 dprintf(CRITICAL, "%s: transfer error!\n", __func__);
359 return ret;
360}
361
362static enum handler_return qup_spi_interrupt(void *arg)
363{
364 struct qup_spi_dev *dev = (struct qup_spi_dev *)arg;
365 unsigned int opflags, qup_err, spi_err;
366
367 if (!dev) {
368 dprintf(CRITICAL,
369 "dev_addr is NULL, that means spi_qup_init failed...\n");
370 return INT_NO_RESCHEDULE;
371 }
372
373 qup_err = readl_relaxed(dev->qup_base + QUP_ERROR_FLAGS);
374 spi_err = readl_relaxed(dev->qup_base + SPI_ERROR_FLAGS);
375 opflags = readl_relaxed(dev->qup_base + QUP_OPERATIONAL);
376
377 /* Writing a 'one' to the error bit to clear it. */
378 writel(qup_err, dev->qup_base + QUP_ERROR_FLAGS);
379 writel(spi_err, dev->qup_base + SPI_ERROR_FLAGS);
380 writel(opflags, dev->qup_base + QUP_OPERATIONAL);
381
382 if (qup_err) {
383 if (qup_err & QUP_ERROR_OUTPUT_OVER_RUN)
384 dprintf(SPEW, "OUTPUT_OVER_RUN\n");
385 if (qup_err & QUP_ERROR_INPUT_UNDER_RUN)
386 dprintf(SPEW, "INPUT_UNDER_RUN\n");
387 if (qup_err & QUP_ERROR_OUTPUT_UNDER_RUN)
388 dprintf(SPEW, "OUTPUT_UNDER_RUN\n");
389 if (qup_err & QUP_ERROR_INPUT_OVER_RUN)
390 dprintf(SPEW, "INPUT_OVER_RUN\n");
391 }
392
393 if (spi_err) {
394 if (spi_err & SPI_ERROR_CLK_OVER_RUN)
395 dprintf(SPEW, "CLK_OVER_RUN\n");
396 if (spi_err & SPI_ERROR_CLK_UNDER_RUN)
397 dprintf(SPEW, "CLK_UNDER_RUN\n");
398 }
399
400 return INT_NO_RESCHEDULE;
401}
402
403static void qup_spi_sec_init(struct qup_spi_dev *dev)
404{
405 /* Get qup hw version */
406 spi_get_qup_hw_ver(dev);
407
408 qup_register_init(dev);
409 spi_register_init(dev);
410
411 /* Register the GSBIn QUP IRQ */
412 register_int_handler(dev->qup_irq, qup_spi_interrupt, dev);
413
414 /* Then disable it */
415 mask_interrupt(dev->qup_irq);
416}
417
418struct qup_spi_dev *qup_blsp_spi_init(uint8_t blsp_id, uint8_t qup_id)
419{
420 struct qup_spi_dev *dev;
421
422 dev = malloc(sizeof(struct qup_spi_dev));
423 if (!dev) {
424 return NULL;
425 }
426 dev = memset(dev, 0, sizeof(struct qup_spi_dev));
427
428 /* Platform uses BLSP */
429 dev->qup_irq = BLSP_QUP_IRQ(blsp_id, qup_id);
430 dev->qup_base = BLSP_QUP_BASE(blsp_id, qup_id);
431
432 /* Initialize the GPIO for BLSP spi */
433 gpio_config_blsp_spi(blsp_id, qup_id);
434
435 clock_config_blsp_spi(blsp_id, qup_id);
436
437 qup_spi_sec_init(dev);
438
439 return dev;
440}
441
442int qup_spi_deinit(struct qup_spi_dev *dev)
443{
444 /* Disable the qup_irq */
445 mask_interrupt(dev->qup_irq);
446 /* Free the memory used for dev */
447 free(dev);
448 return 0;
449}