2 * This file is part of the depthcharge project.
4 * Copyright (C) 2014 - 2015 The Linux Foundation. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials provided
14 * with the distribution.
15 * * Neither the name of The Linux Foundation nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
29 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <libpayload.h>
34 #include <base/container_of.h>
35 #include "drivers/bus/spi/ipq40xx.h"
36 #include "ipq40xx_qup.h"
37 #include "ipq40xx_blsp.h"
39 #define TIMEOUT_CNT 100
41 #define QUP_ADDR(id, reg) (blsp_qup_base(id) + (reg))
45 #define QUPDBG "\t-> "
48 #define qup_write32(a, v) do { \
50 printf(QUPDBG "%s(%d): write32(0x%p, 0x%x)\n", \
51 __func__, __LINE__, a, v); \
54 #define qup_write32 write32
57 static qup_return_t qup_i2c_master_status(blsp_qup_id_t id)
59 uint32_t reg_val = read32(QUP_ADDR(id, QUP_I2C_MASTER_STATUS));
61 if (read32(QUP_ADDR(id, QUP_ERROR_FLAGS)))
62 return QUP_ERR_XFER_FAIL;
65 printf(QUPDBG "%s: 0x%x\n", __func__, reg_val);
68 if (reg_val & QUP_I2C_INVALID_READ_ADDR)
69 return QUP_ERR_I2C_INVALID_SLAVE_ADDR;
70 if (reg_val & QUP_I2C_FAILED_MASK)
71 return QUP_ERR_I2C_FAILED;
72 if (reg_val & QUP_I2C_ARB_LOST)
73 return QUP_ERR_I2C_ARB_LOST;
74 if (reg_val & QUP_I2C_BUS_ERROR)
75 return QUP_ERR_I2C_BUS_ERROR;
76 if (reg_val & QUP_I2C_INVALID_WRITE)
77 return QUP_ERR_I2C_INVALID_WRITE;
78 if (reg_val & QUP_I2C_PACKET_NACK)
79 return QUP_ERR_I2C_NACK;
80 if (reg_val & QUP_I2C_INVALID_TAG)
81 return QUP_ERR_I2C_INVALID_TAG;
86 static int check_bit_state(uint32_t *reg, int wait_for)
88 unsigned int count = TIMEOUT_CNT;
91 (BLSP_QUP_STATE_VALID_MASK | BLSP_QUP_STATE_MASK)) !=
92 (BLSP_QUP_STATE_VALID | wait_for)) {
94 return QUP_ERR_TIMEOUT;
102 * Check whether GSBIn_QUP State is valid
104 static qup_return_t qup_wait_for_state(blsp_qup_id_t id, unsigned wait_for)
106 return check_bit_state(QUP_ADDR(id, QUP_STATE), wait_for);
109 qup_return_t qup_reset_i2c_master_status(blsp_qup_id_t id)
112 * The I2C_STATUS is a status register.
113 * Writing any value clears the status bits.
115 qup_write32(QUP_ADDR(id, QUP_I2C_MASTER_STATUS), 0);
119 static qup_return_t qup_reset_master_status(blsp_qup_id_t id)
121 qup_write32(QUP_ADDR(id, QUP_ERROR_FLAGS), 0x3C);
122 qup_write32(QUP_ADDR(id, QUP_ERROR_FLAGS_EN), 0x3C);
123 qup_reset_i2c_master_status(id);
127 static qup_return_t qup_fifo_wait_for(blsp_qup_id_t id, uint32_t status)
129 qup_return_t ret = QUP_ERR_UNDEFINED;
130 unsigned int count = TIMEOUT_CNT;
132 while (!(read32(QUP_ADDR(id, QUP_OPERATIONAL)) & status)) {
133 ret = qup_i2c_master_status(id);
137 return QUP_ERR_TIMEOUT;
144 static qup_return_t qup_fifo_wait_while(blsp_qup_id_t id, uint32_t status)
146 qup_return_t ret = QUP_ERR_UNDEFINED;
147 unsigned int count = TIMEOUT_CNT;
149 while (read32(QUP_ADDR(id, QUP_OPERATIONAL)) & status) {
150 ret = qup_i2c_master_status(id);
154 return QUP_ERR_TIMEOUT;
161 static inline uint32_t qup_i2c_create_tag(int stop, u8 data)
166 tag = QUP_I2C_STOP_SEQ | QUP_I2C_DATA(data);
168 tag = QUP_I2C_DATA_SEQ | QUP_I2C_DATA(data);
173 static inline qup_return_t qup_i2c_write_fifo_flush(blsp_qup_id_t id)
175 qup_return_t ret = QUP_ERR_UNDEFINED;
177 qup_write32(QUP_ADDR(id, QUP_OPERATIONAL), OUTPUT_SERVICE_FLAG);
179 mdelay(3); /* TPM seems to need this */
181 ret = qup_fifo_wait_while(id, OUTPUT_FIFO_NOT_EMPTY);
185 ret = qup_i2c_master_status(id);
188 printf(QUPDBG "%s: error 0x%x\n", __func__, ret);
193 static qup_return_t qup_i2c_write_fifo(blsp_qup_id_t id, qup_data_t *p_tx_obj,
196 qup_return_t ret = QUP_ERR_UNDEFINED;
197 uint8_t addr = p_tx_obj->p.iic.addr;
198 uint8_t *data_ptr = p_tx_obj->p.iic.data;
199 unsigned data_len = p_tx_obj->p.iic.data_len;
201 uint32_t tag, *fifo = QUP_ADDR(id, QUP_OUTPUT_FIFO);
203 qup_reset_master_status(id);
205 qup_write32(QUP_ADDR(id, QUP_MX_OUTPUT_COUNT), data_len + 1);
207 qup_set_state(id, BLSP_QUP_STATE_RUN);
210 * Since UNPACK enable is set in io mode register, populate 2 tags
211 * for each fifo register.
213 * Create the first tag as follows, with the start tag and first byte
214 * of the data to be written
215 * +--------+--------+--------+--------+
216 * | STOP / | data | START | ADDR |
217 * |DATA tag| byte | tag | << 1 |
218 * +--------+--------+--------+--------+
219 * rest will be created in the following while loop.
221 tag = qup_i2c_create_tag(data_len == 1 && stop_seq, data_ptr[idx]);
222 tag = ((tag << 16) & 0xffff0000) |
223 (QUP_I2C_START_SEQ | QUP_I2C_ADDR(addr));
227 qup_write32(fifo, tag);
231 tag = qup_i2c_create_tag(data_len == 1 && stop_seq,
237 tag |= qup_i2c_create_tag(data_len == 1 && stop_seq,
238 data_ptr[idx]) << 16;
243 qup_write32(fifo, tag);
245 ret = qup_i2c_write_fifo_flush(id);
248 printf(QUPDBG "%s: error\n", __func__);
253 ret = qup_i2c_write_fifo_flush(id);
255 qup_set_state(id, BLSP_QUP_STATE_RESET);
260 static qup_return_t qup_i2c_write(blsp_qup_id_t id, uint8_t mode,
261 qup_data_t *p_tx_obj, uint8_t stop_seq)
263 qup_return_t ret = QUP_ERR_UNDEFINED;
268 ret = qup_i2c_write_fifo(id, p_tx_obj, stop_seq);
271 ret = QUP_ERR_UNSUPPORTED;
275 qup_set_state(id, BLSP_QUP_STATE_RESET);
276 printf(QUPDBG "%s() failed (%d)\n", __func__, ret);
282 static int qup_i2c_parse_tag(uint32_t data, uint8_t *data_ptr, uint32_t len)
285 int max = (len > 2) ? 2 : len;
287 for (i = 0; i < max; i++) {
288 switch (QUP_I2C_MI_TAG(data)) {
289 case QUP_I2C_MIDATA_SEQ:
290 data_ptr[idx] = QUP_I2C_DATA(data);
293 case QUP_I2C_MISTOP_SEQ:
294 data_ptr[idx] = QUP_I2C_DATA(data);
307 static qup_return_t qup_i2c_read_fifo(blsp_qup_id_t id, qup_data_t *p_tx_obj)
309 qup_return_t ret = QUP_ERR_UNDEFINED;
310 uint8_t addr = p_tx_obj->p.iic.addr;
311 uint8_t *data_ptr = p_tx_obj->p.iic.data;
312 unsigned data_len = p_tx_obj->p.iic.data_len;
314 uint32_t *fifo = QUP_ADDR(id, QUP_OUTPUT_FIFO);
316 qup_reset_master_status(id);
318 qup_write32(QUP_ADDR(id, QUP_IO_MODES),
319 QUP_UNPACK_EN | QUP_PACK_EN |
320 ((QUP_MODE_BLOCK & QUP_MODE_MASK) <<
321 QUP_OUTPUT_MODE_SHFT) |
322 ((QUP_MODE_BLOCK & QUP_MODE_MASK) <<
323 QUP_INPUT_MODE_SHFT));
325 qup_write32(QUP_ADDR(id, QUP_MX_INPUT_COUNT), data_len);
327 qup_set_state(id, BLSP_QUP_STATE_RUN);
329 qup_write32(fifo, (QUP_I2C_START_SEQ |
330 (QUP_I2C_ADDR(addr) | QUP_I2C_SLAVE_READ)) |
331 ((QUP_I2C_RECV_SEQ | data_len) << 16));
333 ret = qup_i2c_write_fifo_flush(id);
335 printf(QUPDBG "%s: OUTPUT_FIFO_NOT_EMPTY\n", __func__);
339 ret = qup_fifo_wait_for(id, INPUT_SERVICE_FLAG);
341 printf(QUPDBG "%s: INPUT_SERVICE_FLAG\n", __func__);
345 fifo = QUP_ADDR(id, QUP_INPUT_FIFO);
354 count = qup_i2c_parse_tag(data, data_ptr + idx, data_len);
357 printf(QUPDBG "%s: Cannot parse tag 0x%x\n",
359 qup_set_state(id, BLSP_QUP_STATE_PAUSE);
361 return QUP_ERR_I2C_INVALID_TAG;
367 qup_write32(QUP_ADDR(id, QUP_OPERATIONAL), INPUT_SERVICE_FLAG);
370 p_tx_obj->p.iic.data_len = idx;
372 qup_write32(QUP_ADDR(id, QUP_MX_READ_COUNT), 0);
374 qup_set_state(id, BLSP_QUP_STATE_RESET);
379 static qup_return_t qup_i2c_read(blsp_qup_id_t id, uint8_t mode,
380 qup_data_t *p_tx_obj)
382 qup_return_t ret = QUP_ERR_UNDEFINED;
384 qup_set_state(id, BLSP_QUP_STATE_RESET);
389 ret = qup_i2c_read_fifo(id, p_tx_obj);
392 ret = QUP_ERR_UNSUPPORTED;
396 qup_set_state(id, BLSP_QUP_STATE_RESET);
397 printf(QUPDBG "%s() failed (%d)\n", __func__, ret);
403 qup_return_t qup_init(blsp_qup_id_t id, const qup_config_t *config_ptr)
405 qup_return_t ret = QUP_ERR_UNDEFINED;
408 /* Reset the QUP core.*/
409 qup_write32(QUP_ADDR(id, QUP_SW_RESET), 0x1);
411 /*Wait till the reset takes effect */
412 ret = qup_wait_for_state(id, BLSP_QUP_STATE_RESET);
416 /* Reset the config */
417 qup_write32(QUP_ADDR(id, QUP_CONFIG), 0);
419 /*Program the config register*/
423 switch (config_ptr->protocol) {
424 case QUP_MINICORE_I2C_MASTER:
425 reg_val |= ((config_ptr->protocol &
426 QUP_MINI_CORE_PROTO_MASK) <<
427 QUP_MINI_CORE_PROTO_SHFT);
430 ret = QUP_ERR_UNSUPPORTED;
433 reg_val |= QUP_APP_CLK_ON_EN | QUP_CORE_CLK_ON_EN;
434 qup_write32(QUP_ADDR(id, QUP_CONFIG), reg_val);
436 /* Choose version 1 tag */
437 qup_write32(QUP_ADDR(id, QUP_I2C_MASTER_CONFIG), 0);
439 /* Reset i2c clk cntl register */
440 qup_write32(QUP_ADDR(id, QUP_I2C_MASTER_CLK_CTL), 0);
442 /* Set QUP IO Mode */
443 switch (config_ptr->mode) {
446 reg_val = QUP_UNPACK_EN | QUP_PACK_EN |
447 ((config_ptr->mode & QUP_MODE_MASK) <<
448 QUP_OUTPUT_MODE_SHFT) |
449 ((config_ptr->mode & QUP_MODE_MASK) <<
450 QUP_INPUT_MODE_SHFT);
453 ret = QUP_ERR_UNSUPPORTED;
456 qup_write32(QUP_ADDR(id, QUP_IO_MODES), reg_val);
459 reg_val = (QUP_DIVIDER_MIN_VAL << QUP_HS_DIVIDER_SHFT);
460 reg_val |= ((((config_ptr->src_frequency / config_ptr->clk_frequency)
461 / 2) - QUP_DIVIDER_MIN_VAL) &
462 QUP_FS_DIVIDER_MASK);
463 qup_write32(QUP_ADDR(id, QUP_I2C_MASTER_CLK_CTL), reg_val);
465 qup_set_state(id, BLSP_QUP_STATE_RESET);
468 printf(QUPDBG "failed to init qup (%d)\n", ret);
473 qup_return_t qup_set_state(blsp_qup_id_t id, uint32_t state)
475 qup_return_t ret = QUP_ERR_UNDEFINED;
476 unsigned curr_state = read32(QUP_ADDR(id, QUP_STATE));
478 if ((state >= BLSP_QUP_STATE_RESET && state <= BLSP_QUP_STATE_PAUSE)
479 && (curr_state & BLSP_QUP_STATE_VALID_MASK)) {
481 * For PAUSE_STATE to RESET_STATE transition,
482 * two writes of 10[binary]) are required for the
483 * transition to complete.
485 if (BLSP_QUP_STATE_PAUSE == curr_state &&
486 BLSP_QUP_STATE_RESET == state) {
487 qup_write32(QUP_ADDR(id, QUP_STATE), 0x2);
488 qup_write32(QUP_ADDR(id, QUP_STATE), 0x2);
490 qup_write32(QUP_ADDR(id, QUP_STATE), state);
492 ret = qup_wait_for_state(id, state);
498 static qup_return_t qup_i2c_send_data(blsp_qup_id_t id, qup_data_t *p_tx_obj,
501 qup_return_t ret = QUP_ERR_UNDEFINED;
502 uint8_t mode = (read32(QUP_ADDR(id, QUP_IO_MODES)) >>
503 QUP_OUTPUT_MODE_SHFT) & QUP_MODE_MASK;
505 ret = qup_i2c_write(id, mode, p_tx_obj, stop_seq);
509 printf("i2c tx bus %d device %2.2x:", id, p_tx_obj->p.iic.addr);
510 for (i = 0; i < p_tx_obj->p.iic.data_len; i++)
511 printf(" %2.2x", p_tx_obj->p.iic.data[i]);
518 qup_return_t qup_send_data(blsp_qup_id_t id, qup_data_t *p_tx_obj,
521 qup_return_t ret = QUP_ERR_UNDEFINED;
523 if (p_tx_obj->protocol == ((read32(QUP_ADDR(id, QUP_CONFIG)) >>
524 QUP_MINI_CORE_PROTO_SHFT) & QUP_MINI_CORE_PROTO_MASK)) {
525 switch (p_tx_obj->protocol) {
526 case QUP_MINICORE_I2C_MASTER:
527 ret = qup_i2c_send_data(id, p_tx_obj, stop_seq);
530 ret = QUP_ERR_UNSUPPORTED;
537 static qup_return_t qup_i2c_recv_data(blsp_qup_id_t id, qup_data_t *p_rx_obj)
539 qup_return_t ret = QUP_ERR_UNDEFINED;
540 uint8_t mode = (read32(QUP_ADDR(id, QUP_IO_MODES)) >>
541 QUP_INPUT_MODE_SHFT) & QUP_MODE_MASK;
543 ret = qup_i2c_read(id, mode, p_rx_obj);
547 printf("i2c rxed on bus %d device %2.2x:",
548 id, p_rx_obj->p.iic.addr);
549 for (i = 0; i < p_rx_obj->p.iic.data_len; i++)
550 printf(" %2.2x", p_rx_obj->p.iic.data[i]);
557 qup_return_t qup_recv_data(blsp_qup_id_t id, qup_data_t *p_rx_obj)
559 qup_return_t ret = QUP_ERR_UNDEFINED;
561 if (p_rx_obj->protocol == ((read32(QUP_ADDR(id, QUP_CONFIG)) >>
562 QUP_MINI_CORE_PROTO_SHFT) & QUP_MINI_CORE_PROTO_MASK)) {
563 switch (p_rx_obj->protocol) {
564 case QUP_MINICORE_I2C_MASTER:
565 ret = qup_i2c_recv_data(id, p_rx_obj);
568 ret = QUP_ERR_UNSUPPORTED;