aboutsummaryrefslogtreecommitdiff
path: root/src/soc/qualcomm/ipq40xx/qup.c
diff options
context:
space:
mode:
authorVaradarajan Narayanan <varada@codeaurora.org>2016-03-08 15:02:56 +0530
committerPatrick Georgi <pgeorgi@google.com>2016-05-10 23:23:40 +0200
commit2596764f34a03e4f53704ca5efef71de5c4f9f4c (patch)
tree6064e180ee9bbc9ca84896831cc4f2ed8313312f /src/soc/qualcomm/ipq40xx/qup.c
parent3939acaa77016b6d480c292e01087a7d76e91906 (diff)
soc/qualcomm/ipq40xx: Add support for BLSP QUP I2C
Able to talk to the TPM device and the commands seem to succeed. BUG=chrome-os-partner:49249 chrome-os-partner:49250 TEST=All commands to the TPM succeed BRANCH=none Original-Commit-Id: c13900108f524c8422c38dee88469c8bfe24d0bd Original-Change-Id: Ie8c3c1ab1290cd8d7e6ddd1ae22f765c7be81019 Original-Signed-off-by: Varadarajan Narayanan <varada@codeaurora.org> Original-Reviewed-on: https://chromium-review.googlesource.com/333314 Original-Commit-Ready: David Hendricks <dhendrix@chromium.org> Original-Tested-by: David Hendricks <dhendrix@chromium.org> Original-Reviewed-by: David Hendricks <dhendrix@chromium.org> squashed: soc/qualcomm/ipq40xx: Add support for BLSP QUP SPI - Enable BLSP SPI driver for ipq40xx - supports only FIFO mode BUG=chrome-os-partner:49249 TEST=None. Initial code not sure if it will even compile BRANCH=none Original-Commit-Id: 0714025975854dd048d35fe602824ead4c7d94e9 Original-Change-Id: If809b0fdf7d6c9405db6fd3747a3774c00ea9870 Original-Signed-off-by: Varadarajan Narayanan <varada@codeaurora.org> Original-Reviewed-on: https://chromium-review.googlesource.com/333303 Original-Commit-Ready: David Hendricks <dhendrix@chromium.org> Original-Tested-by: David Hendricks <dhendrix@chromium.org> Original-Reviewed-by: David Hendricks <dhendrix@chromium.org> Change-Id: Ia518af5bfc782b08a0883ac93224d476d07e2426 Signed-off-by: Patrick Georgi <pgeorgi@chromium.org> Reviewed-on: https://review.coreboot.org/14677 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'src/soc/qualcomm/ipq40xx/qup.c')
-rw-r--r--src/soc/qualcomm/ipq40xx/qup.c408
1 files changed, 253 insertions, 155 deletions
diff --git a/src/soc/qualcomm/ipq40xx/qup.c b/src/soc/qualcomm/ipq40xx/qup.c
index c876d30c67..63b37ef7b4 100644
--- a/src/soc/qualcomm/ipq40xx/qup.c
+++ b/src/soc/qualcomm/ipq40xx/qup.c
@@ -36,27 +36,35 @@
#include <stdlib.h>
#include <soc/qup.h>
-#define TIMEOUT_CNT 100000
-
-//TODO: refactor the following array to iomap driver.
-static unsigned gsbi_qup_base[] = {
- (unsigned)GSBI_QUP1_BASE,
- (unsigned)GSBI_QUP2_BASE,
- (unsigned)GSBI_QUP3_BASE,
- (unsigned)GSBI_QUP4_BASE,
- (unsigned)GSBI_QUP5_BASE,
- (unsigned)GSBI_QUP6_BASE,
- (unsigned)GSBI_QUP7_BASE,
-};
-
-#define QUP_ADDR(gsbi_num, reg) ((void *)((gsbi_qup_base[gsbi_num-1]) + (reg)))
-
-static qup_return_t qup_i2c_master_status(gsbi_id_t gsbi_id)
+#define TIMEOUT_CNT 100
+
+#define QUP_ADDR(id, reg) (blsp_qup_base(id) + (reg))
+
+#define QUP_DEBUG 0
+
+#define QUPDBG BIOS_ERR, "\t-> "
+
+#if QUP_DEBUG
+#define qup_write32(a, v) do { \
+ write32(a, v); \
+ printk(QUPDBG "%s(%d): write32(0x%p, 0x%x)\n", \
+ __func__, __LINE__, a, v); \
+} while (0)
+#else
+#define qup_write32 write32
+#endif
+
+static qup_return_t qup_i2c_master_status(blsp_qup_id_t id)
{
- uint32_t reg_val = read32(QUP_ADDR(gsbi_id, QUP_I2C_MASTER_STATUS));
+ uint32_t reg_val = read32(QUP_ADDR(id, QUP_I2C_MASTER_STATUS));
- if (read32(QUP_ADDR(gsbi_id, QUP_ERROR_FLAGS)))
+ if (read32(QUP_ADDR(id, QUP_ERROR_FLAGS)))
return QUP_ERR_XFER_FAIL;
+
+#if QUP_DEBUG
+ printk(QUPDBG "%s: 0x%x\n", __func__, reg_val);
+#endif
+
if (reg_val & QUP_I2C_INVALID_READ_ADDR)
return QUP_ERR_I2C_INVALID_SLAVE_ADDR;
if (reg_val & QUP_I2C_FAILED_MASK)
@@ -84,7 +92,6 @@ static int check_bit_state(uint32_t *reg, int wait_for)
if (count == 0)
return QUP_ERR_TIMEOUT;
count--;
- udelay(1);
}
return QUP_SUCCESS;
@@ -93,37 +100,36 @@ static int check_bit_state(uint32_t *reg, int wait_for)
/*
* Check whether GSBIn_QUP State is valid
*/
-static qup_return_t qup_wait_for_state(gsbi_id_t gsbi_id, unsigned wait_for)
+static qup_return_t qup_wait_for_state(blsp_qup_id_t id, unsigned wait_for)
{
- return check_bit_state(QUP_ADDR(gsbi_id, QUP_STATE), wait_for);
+ return check_bit_state(QUP_ADDR(id, QUP_STATE), wait_for);
}
-qup_return_t qup_reset_i2c_master_status(gsbi_id_t gsbi_id)
+qup_return_t qup_reset_i2c_master_status(blsp_qup_id_t id)
{
/*
- * Writing a one clears the status bits.
- * Bit31-25, Bit1 and Bit0 are reserved.
+ * The I2C_STATUS is a status register.
+ * Writing any value clears the status bits.
*/
- //TODO: Define each status bit. OR all status bits in a single macro.
- write32(QUP_ADDR(gsbi_id, QUP_I2C_MASTER_STATUS), 0x3FFFFFC);
+ qup_write32(QUP_ADDR(id, QUP_I2C_MASTER_STATUS), 0);
return QUP_SUCCESS;
}
-static qup_return_t qup_reset_master_status(gsbi_id_t gsbi_id)
+static qup_return_t qup_reset_master_status(blsp_qup_id_t id)
{
- write32(QUP_ADDR(gsbi_id, QUP_ERROR_FLAGS), 0x7C);
- write32(QUP_ADDR(gsbi_id, QUP_ERROR_FLAGS_EN), 0x7C);
- qup_reset_i2c_master_status(gsbi_id);
+ qup_write32(QUP_ADDR(id, QUP_ERROR_FLAGS), 0x3C);
+ qup_write32(QUP_ADDR(id, QUP_ERROR_FLAGS_EN), 0x3C);
+ qup_reset_i2c_master_status(id);
return QUP_SUCCESS;
}
-static qup_return_t qup_fifo_wait_for(gsbi_id_t gsbi_id, uint32_t status)
+static qup_return_t qup_fifo_wait_for(blsp_qup_id_t id, uint32_t status)
{
qup_return_t ret = QUP_ERR_UNDEFINED;
unsigned int count = TIMEOUT_CNT;
- while (!(read32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL)) & status)) {
- ret = qup_i2c_master_status(gsbi_id);
+ while (!(read32(QUP_ADDR(id, QUP_OPERATIONAL)) & status)) {
+ ret = qup_i2c_master_status(id);
if (ret)
return ret;
if (count == 0)
@@ -134,13 +140,13 @@ static qup_return_t qup_fifo_wait_for(gsbi_id_t gsbi_id, uint32_t status)
return QUP_SUCCESS;
}
-static qup_return_t qup_fifo_wait_while(gsbi_id_t gsbi_id, uint32_t status)
+static qup_return_t qup_fifo_wait_while(blsp_qup_id_t id, uint32_t status)
{
qup_return_t ret = QUP_ERR_UNDEFINED;
unsigned int count = TIMEOUT_CNT;
- while (read32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL)) & status) {
- ret = qup_i2c_master_status(gsbi_id);
+ while (read32(QUP_ADDR(id, QUP_OPERATIONAL)) & status) {
+ ret = qup_i2c_master_status(id);
if (ret)
return ret;
if (count == 0)
@@ -151,7 +157,39 @@ static qup_return_t qup_fifo_wait_while(gsbi_id_t gsbi_id, uint32_t status)
return QUP_SUCCESS;
}
-static qup_return_t qup_i2c_write_fifo(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj,
+static inline uint32_t qup_i2c_create_output_tag(int stop, u8 data)
+{
+ uint32_t tag;
+
+ if (stop)
+ tag = QUP_I2C_STOP_SEQ | QUP_I2C_DATA(data);
+ else
+ tag = QUP_I2C_DATA_SEQ | QUP_I2C_DATA(data);
+
+ return tag;
+}
+
+static inline qup_return_t qup_i2c_write_fifo_flush(blsp_qup_id_t id)
+{
+ qup_return_t ret = QUP_ERR_UNDEFINED;
+
+ qup_write32(QUP_ADDR(id, QUP_OPERATIONAL), OUTPUT_SERVICE_FLAG);
+
+ mdelay(10); /* TPM seems to need this */
+
+ ret = qup_fifo_wait_while(id, OUTPUT_FIFO_NOT_EMPTY);
+ if (ret)
+ return ret;
+
+ ret = qup_i2c_master_status(id);
+
+ if (ret)
+ printk(BIOS_DEBUG, "%s: error\n", __func__);
+
+ return ret;
+}
+
+static qup_return_t qup_i2c_write_fifo(blsp_qup_id_t id, qup_data_t *p_tx_obj,
uint8_t stop_seq)
{
qup_return_t ret = QUP_ERR_UNDEFINED;
@@ -159,180 +197,235 @@ static qup_return_t qup_i2c_write_fifo(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj,
uint8_t *data_ptr = p_tx_obj->p.iic.data;
unsigned data_len = p_tx_obj->p.iic.data_len;
unsigned idx = 0;
+ uint32_t tag, *fifo = QUP_ADDR(id, QUP_OUTPUT_FIFO);
+ const uint32_t *fifo_end = fifo + QUP_OUTPUT_FIFO_SIZE / sizeof(*fifo);
- qup_reset_master_status(gsbi_id);
- qup_set_state(gsbi_id, QUP_STATE_RUN);
+ qup_reset_master_status(id);
- write32(QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO),
- (QUP_I2C_START_SEQ | QUP_I2C_ADDR(addr)));
+ qup_set_state(id, QUP_STATE_RUN);
+
+ /*
+ * Since UNPACK enable is set in io mode register, populate 2 tags
+ * for each fifo register.
+ *
+ * Create the first tag as follows, with the start tag and first byte
+ * of the data to be written
+ * +--------+--------+--------+--------+
+ * | STOP / | data | START | ADDR |
+ * |DATA tag| byte | tag | << 1 |
+ * +--------+--------+--------+--------+
+ * rest will be created in the following while loop.
+ */
+ tag = qup_i2c_create_output_tag(data_len == 1 && stop_seq,
+ data_ptr[idx]);
+ tag = ((tag << 16) & 0xffff0000) |
+ (QUP_I2C_START_SEQ | QUP_I2C_ADDR(addr));
+ data_len--;
+ idx++;
+
+ qup_write32(fifo, tag);
+ fifo++;
while (data_len) {
- if (data_len == 1 && stop_seq) {
- write32(QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO),
- QUP_I2C_STOP_SEQ | QUP_I2C_DATA(data_ptr[idx]));
- } else {
- write32(QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO),
- QUP_I2C_DATA_SEQ | QUP_I2C_DATA(data_ptr[idx]));
- }
+
+ tag = qup_i2c_create_output_tag(data_len == 1 && stop_seq,
+ data_ptr[idx]);
data_len--;
idx++;
+
if (data_len) {
- ret = qup_fifo_wait_while(gsbi_id, OUTPUT_FIFO_FULL);
- if (ret)
- return ret;
+ tag |= qup_i2c_create_output_tag(
+ data_len == 1 && stop_seq,
+ data_ptr[idx]) << 16;
+ data_len--;
+ idx++;
}
- /* Hardware sets the OUTPUT_SERVICE_FLAG flag to 1 when
- OUTPUT_FIFO_NOT_EMPTY flag in the QUP_OPERATIONAL
- register changes from 1 to 0, indicating that software
- can write more data to the output FIFO. Software should
- set OUTPUT_SERVICE_FLAG to 1 to clear it to 0, which
- means that software knows to return to fill the output
- FIFO with data.
- */
- if (read32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL)) &
- OUTPUT_SERVICE_FLAG) {
- write32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL),
- OUTPUT_SERVICE_FLAG);
+
+ qup_write32(fifo, tag);
+ fifo++;
+
+ if ((fifo >= fifo_end) && data_len) {
+
+ fifo = QUP_ADDR(id, QUP_OUTPUT_FIFO);
+
+ ret = qup_i2c_write_fifo_flush(id);
+
+ if (ret) {
+ printk(BIOS_DEBUG, "%s: error\n", __func__);
+ return ret;
+ }
+
}
}
- ret = qup_fifo_wait_while(gsbi_id, OUTPUT_FIFO_NOT_EMPTY);
- if (ret)
- return ret;
+ ret = qup_i2c_write_fifo_flush(id);
- qup_set_state(gsbi_id, QUP_STATE_PAUSE);
- return qup_i2c_master_status(gsbi_id);
+ qup_set_state(id, QUP_STATE_RESET);
+
+ return ret;
}
-static qup_return_t qup_i2c_write(gsbi_id_t gsbi_id, uint8_t mode,
+static qup_return_t qup_i2c_write(blsp_qup_id_t id, uint8_t mode,
qup_data_t *p_tx_obj, uint8_t stop_seq)
{
qup_return_t ret = QUP_ERR_UNDEFINED;
switch (mode) {
case QUP_MODE_FIFO:
- ret = qup_i2c_write_fifo(gsbi_id, p_tx_obj, stop_seq);
+ ret = qup_i2c_write_fifo(id, p_tx_obj, stop_seq);
break;
default:
ret = QUP_ERR_UNSUPPORTED;
}
if (ret) {
- qup_set_state(gsbi_id, QUP_STATE_RESET);
- printk(BIOS_ERR, "%s() failed (%d)\n", __func__, ret);
+ qup_set_state(id, QUP_STATE_RESET);
+ printk(QUPDBG "%s() failed (%d)\n", __func__, ret);
}
return ret;
}
-static qup_return_t qup_i2c_read_fifo(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj)
+static int qup_i2c_parse_tag(uint32_t data, uint8_t *data_ptr, uint32_t len)
+{
+ int i, idx = 0;
+ int max = (len > 2) ? 2 : len;
+
+ for (i = 0; i < max; i++) {
+ switch (QUP_I2C_MI_TAG(data)) {
+ case QUP_I2C_MIDATA_SEQ:
+ data_ptr[idx] = QUP_I2C_DATA(data);
+ idx++;
+ break;
+ case QUP_I2C_MISTOP_SEQ:
+ data_ptr[idx] = QUP_I2C_DATA(data);
+ idx++;
+ return idx;
+ default:
+ printk(QUPDBG "%s: Unexpected tag (0x%x)\n", __func__,
+ QUP_I2C_MI_TAG(data));
+ return -1;
+ }
+
+ data = (data >> 16);
+ }
+
+ return idx;
+}
+
+static qup_return_t qup_i2c_read_fifo(blsp_qup_id_t id, qup_data_t *p_tx_obj)
{
qup_return_t ret = QUP_ERR_UNDEFINED;
uint8_t addr = p_tx_obj->p.iic.addr;
uint8_t *data_ptr = p_tx_obj->p.iic.data;
unsigned data_len = p_tx_obj->p.iic.data_len;
unsigned idx = 0;
+ uint32_t *fifo = QUP_ADDR(id, QUP_OUTPUT_FIFO);
+ const uint32_t *fifo_end = fifo + QUP_INPUT_FIFO_SIZE / sizeof(*fifo);
- qup_reset_master_status(gsbi_id);
- qup_set_state(gsbi_id, QUP_STATE_RUN);
+ qup_reset_master_status(id);
- write32(QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO),
- QUP_I2C_START_SEQ | (QUP_I2C_ADDR(addr) | QUP_I2C_SLAVE_READ));
+ qup_set_state(id, QUP_STATE_RUN);
- write32(QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO),
- QUP_I2C_RECV_SEQ | data_len);
+ qup_write32(fifo, (QUP_I2C_START_SEQ |
+ (QUP_I2C_ADDR(addr) | QUP_I2C_SLAVE_READ)) |
+ ((QUP_I2C_RECV_SEQ | data_len) << 16));
- ret = qup_fifo_wait_while(gsbi_id, OUTPUT_FIFO_NOT_EMPTY);
- if (ret)
+ ret = qup_i2c_write_fifo_flush(id);
+ if (ret) {
+ printk(QUPDBG "%s: OUTPUT_FIFO_NOT_EMPTY\n", __func__);
+ return ret;
+ }
+
+ qup_write32(QUP_ADDR(id, QUP_MX_READ_COUNT), data_len);
+
+ ret = qup_fifo_wait_for(id, INPUT_SERVICE_FLAG);
+ if (ret) {
+ printk(QUPDBG "%s: INPUT_SERVICE_FLAG\n", __func__);
return ret;
+ }
- write32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL), OUTPUT_SERVICE_FLAG);
+ fifo = QUP_ADDR(id, QUP_INPUT_FIFO);
while (data_len) {
uint32_t data;
+ int count;
- ret = qup_fifo_wait_for(gsbi_id, INPUT_SERVICE_FLAG);
- if (ret)
- return ret;
+ data = read32(fifo);
+ fifo++;
- data = read32(QUP_ADDR(gsbi_id, QUP_INPUT_FIFO));
+ count = qup_i2c_parse_tag(data, data_ptr + idx, data_len);
- /*
- * Process tag and corresponding data value. For I2C master
- * mini-core, data in FIFO is composed of 16 bits and is divided
- * into an 8-bit tag for the upper bits and 8-bit data for the
- * lower bits. The 8-bit tag indicates whether the byte is the
- * last byte, or if a bus error happened during the receipt of
- * the byte.
- */
- if ((QUP_I2C_MI_TAG(data)) == QUP_I2C_MIDATA_SEQ) {
- /* Tag: MIDATA = Master input data.*/
- data_ptr[idx] = QUP_I2C_DATA(data);
- idx++;
- data_len--;
- write32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL),
- INPUT_SERVICE_FLAG);
- } else {
- if (QUP_I2C_MI_TAG(data) == QUP_I2C_MISTOP_SEQ) {
- /* Tag: MISTOP: Last byte of master input. */
- data_ptr[idx] = QUP_I2C_DATA(data);
- idx++;
- data_len--;
- break;
- }
- /* Tag: MINACK: Invalid master input data.*/
- break;
+ if (count < 0) {
+ printk(QUPDBG "%s: Cannot parse tag 0x%x\n",
+ __func__, data);
+ qup_set_state(id, QUP_STATE_PAUSE);
+
+ return QUP_ERR_I2C_INVALID_TAG;
+ }
+
+ idx += count;
+ data_len -= count;
+
+ if ((fifo >= fifo_end) || (data_len == 0)) {
+ fifo = QUP_ADDR(id, QUP_INPUT_FIFO);
+ qup_write32(QUP_ADDR(id, QUP_OPERATIONAL),
+ INPUT_SERVICE_FLAG);
}
}
- write32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL), INPUT_SERVICE_FLAG);
p_tx_obj->p.iic.data_len = idx;
- qup_set_state(gsbi_id, QUP_STATE_PAUSE);
+
+ qup_write32(QUP_ADDR(id, QUP_MX_READ_COUNT), 0);
+
+ qup_set_state(id, QUP_STATE_RESET);
return QUP_SUCCESS;
}
-static qup_return_t qup_i2c_read(gsbi_id_t gsbi_id, uint8_t mode,
+static qup_return_t qup_i2c_read(blsp_qup_id_t id, uint8_t mode,
qup_data_t *p_tx_obj)
{
qup_return_t ret = QUP_ERR_UNDEFINED;
+ qup_set_state(id, QUP_STATE_RESET);
+
switch (mode) {
case QUP_MODE_FIFO:
- ret = qup_i2c_read_fifo(gsbi_id, p_tx_obj);
+ ret = qup_i2c_read_fifo(id, p_tx_obj);
break;
default:
ret = QUP_ERR_UNSUPPORTED;
}
if (ret) {
- qup_set_state(gsbi_id, QUP_STATE_RESET);
- printk(BIOS_ERR, "%s() failed (%d)\n", __func__, ret);
+ qup_set_state(id, QUP_STATE_RESET);
+ printk(QUPDBG "%s() failed (%d)\n", __func__, ret);
}
return ret;
}
-qup_return_t qup_init(gsbi_id_t gsbi_id, const qup_config_t *config_ptr)
+qup_return_t qup_init(blsp_qup_id_t id, const qup_config_t *config_ptr)
{
qup_return_t ret = QUP_ERR_UNDEFINED;
uint32_t reg_val;
/* Reset the QUP core.*/
- write32(QUP_ADDR(gsbi_id, QUP_SW_RESET), 0x1);
+ qup_write32(QUP_ADDR(id, QUP_SW_RESET), 0x1);
- /*Wait till the reset takes effect */
- ret = qup_wait_for_state(gsbi_id, QUP_STATE_RESET);
+ /* Wait till the reset takes effect */
+ ret = qup_wait_for_state(id, QUP_STATE_RESET);
if (ret)
goto bailout;
/* Reset the config */
- write32(QUP_ADDR(gsbi_id, QUP_CONFIG), 0);
+ qup_write32(QUP_ADDR(id, QUP_CONFIG), 0);
- /*Program the config register*/
- /*Set N value*/
+ /* Program the config register */
+ /* Set N value */
reg_val = 0x0F;
- /*Set protocol*/
+ /* Set protocol */
switch (config_ptr->protocol) {
case QUP_MINICORE_I2C_MASTER:
reg_val |= ((config_ptr->protocol &
@@ -343,15 +436,19 @@ qup_return_t qup_init(gsbi_id_t gsbi_id, const qup_config_t *config_ptr)
ret = QUP_ERR_UNSUPPORTED;
goto bailout;
}
- write32(QUP_ADDR(gsbi_id, QUP_CONFIG), reg_val);
+ reg_val |= QUP_APP_CLK_ON_EN | QUP_CORE_CLK_ON_EN;
+ qup_write32(QUP_ADDR(id, QUP_CONFIG), reg_val);
+
+ /* Choose version 1 tag */
+ qup_write32(QUP_ADDR(id, QUP_I2C_MASTER_CONFIG), 0);
- /*Reset i2c clk cntl register*/
- write32(QUP_ADDR(gsbi_id, QUP_I2C_MASTER_CLK_CTL), 0);
+ /* Reset i2c clk cntl register */
+ qup_write32(QUP_ADDR(id, QUP_I2C_MASTER_CLK_CTL), 0);
- /*Set QUP IO Mode*/
+ /* Set QUP IO Mode */
switch (config_ptr->mode) {
case QUP_MODE_FIFO:
- reg_val = QUP_OUTPUT_BIT_SHIFT_EN |
+ reg_val = QUP_UNPACK_EN | QUP_PACK_EN |
((config_ptr->mode & QUP_MODE_MASK) <<
QUP_OUTPUT_MODE_SHFT) |
((config_ptr->mode & QUP_MODE_MASK) <<
@@ -361,26 +458,27 @@ qup_return_t qup_init(gsbi_id_t gsbi_id, const qup_config_t *config_ptr)
ret = QUP_ERR_UNSUPPORTED;
goto bailout;
}
- write32(QUP_ADDR(gsbi_id, QUP_IO_MODES), reg_val);
+ qup_write32(QUP_ADDR(id, QUP_IO_MODES), reg_val);
/*Set i2c clk cntl*/
reg_val = (QUP_DIVIDER_MIN_VAL << QUP_HS_DIVIDER_SHFT);
reg_val |= ((((config_ptr->src_frequency / config_ptr->clk_frequency)
/ 2) - QUP_DIVIDER_MIN_VAL) &
QUP_FS_DIVIDER_MASK);
- write32(QUP_ADDR(gsbi_id, QUP_I2C_MASTER_CLK_CTL), reg_val);
+ qup_write32(QUP_ADDR(id, QUP_I2C_MASTER_CLK_CTL), reg_val);
+ qup_set_state(id, QUP_STATE_RESET);
bailout:
if (ret)
- printk(BIOS_ERR, "failed to init qup (%d)\n", ret);
+ printk(QUPDBG "failed to init qup (%d)\n", ret);
return ret;
}
-qup_return_t qup_set_state(gsbi_id_t gsbi_id, uint32_t state)
+qup_return_t qup_set_state(blsp_qup_id_t id, uint32_t state)
{
qup_return_t ret = QUP_ERR_UNDEFINED;
- unsigned curr_state = read32(QUP_ADDR(gsbi_id, QUP_STATE));
+ unsigned curr_state = read32(QUP_ADDR(id, QUP_STATE));
if ((state >= QUP_STATE_RESET && state <= QUP_STATE_PAUSE)
&& (curr_state & QUP_STATE_VALID_MASK)) {
@@ -390,30 +488,30 @@ qup_return_t qup_set_state(gsbi_id_t gsbi_id, uint32_t state)
* transition to complete.
*/
if (QUP_STATE_PAUSE == curr_state && QUP_STATE_RESET == state) {
- write32(QUP_ADDR(gsbi_id, QUP_STATE), 0x2);
- write32(QUP_ADDR(gsbi_id, QUP_STATE), 0x2);
+ qup_write32(QUP_ADDR(id, QUP_STATE), 0x2);
+ qup_write32(QUP_ADDR(id, QUP_STATE), 0x2);
} else {
- write32(QUP_ADDR(gsbi_id, QUP_STATE), state);
+ qup_write32(QUP_ADDR(id, QUP_STATE), state);
}
- ret = qup_wait_for_state(gsbi_id, state);
+ ret = qup_wait_for_state(id, state);
}
return ret;
}
-static qup_return_t qup_i2c_send_data(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj,
+static qup_return_t qup_i2c_send_data(blsp_qup_id_t id, qup_data_t *p_tx_obj,
uint8_t stop_seq)
{
qup_return_t ret = QUP_ERR_UNDEFINED;
- uint8_t mode = (read32(QUP_ADDR(gsbi_id, QUP_IO_MODES)) >>
+ uint8_t mode = (read32(QUP_ADDR(id, QUP_IO_MODES)) >>
QUP_OUTPUT_MODE_SHFT) & QUP_MODE_MASK;
- ret = qup_i2c_write(gsbi_id, mode, p_tx_obj, stop_seq);
- if (0) {
+ ret = qup_i2c_write(id, mode, p_tx_obj, stop_seq);
+ if (QUP_DEBUG) {
int i;
printk(BIOS_DEBUG, "i2c tx bus %d device %2.2x:",
- gsbi_id, p_tx_obj->p.iic.addr);
+ id, p_tx_obj->p.iic.addr);
for (i = 0; i < p_tx_obj->p.iic.data_len; i++)
printk(BIOS_DEBUG, " %2.2x", p_tx_obj->p.iic.data[i]);
printk(BIOS_DEBUG, "\n");
@@ -422,16 +520,16 @@ static qup_return_t qup_i2c_send_data(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj,
return ret;
}
-qup_return_t qup_send_data(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj,
+qup_return_t qup_send_data(blsp_qup_id_t id, qup_data_t *p_tx_obj,
uint8_t stop_seq)
{
qup_return_t ret = QUP_ERR_UNDEFINED;
- if (p_tx_obj->protocol == ((read32(QUP_ADDR(gsbi_id, QUP_CONFIG)) >>
+ if (p_tx_obj->protocol == ((read32(QUP_ADDR(id, QUP_CONFIG)) >>
QUP_MINI_CORE_PROTO_SHFT) & QUP_MINI_CORE_PROTO_MASK)) {
switch (p_tx_obj->protocol) {
case QUP_MINICORE_I2C_MASTER:
- ret = qup_i2c_send_data(gsbi_id, p_tx_obj, stop_seq);
+ ret = qup_i2c_send_data(id, p_tx_obj, stop_seq);
break;
default:
ret = QUP_ERR_UNSUPPORTED;
@@ -441,18 +539,18 @@ qup_return_t qup_send_data(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj,
return ret;
}
-static qup_return_t qup_i2c_recv_data(gsbi_id_t gsbi_id, qup_data_t *p_rx_obj)
+static qup_return_t qup_i2c_recv_data(blsp_qup_id_t id, qup_data_t *p_rx_obj)
{
qup_return_t ret = QUP_ERR_UNDEFINED;
- uint8_t mode = (read32(QUP_ADDR(gsbi_id, QUP_IO_MODES)) >>
+ uint8_t mode = (read32(QUP_ADDR(id, QUP_IO_MODES)) >>
QUP_INPUT_MODE_SHFT) & QUP_MODE_MASK;
- ret = qup_i2c_read(gsbi_id, mode, p_rx_obj);
- if (0) {
+ ret = qup_i2c_read(id, mode, p_rx_obj);
+ if (QUP_DEBUG) {
int i;
printk(BIOS_DEBUG, "i2c rxed on bus %d device %2.2x:",
- gsbi_id, p_rx_obj->p.iic.addr);
+ id, p_rx_obj->p.iic.addr);
for (i = 0; i < p_rx_obj->p.iic.data_len; i++)
printk(BIOS_DEBUG, " %2.2x", p_rx_obj->p.iic.data[i]);
printk(BIOS_DEBUG, "\n");
@@ -461,15 +559,15 @@ static qup_return_t qup_i2c_recv_data(gsbi_id_t gsbi_id, qup_data_t *p_rx_obj)
return ret;
}
-qup_return_t qup_recv_data(gsbi_id_t gsbi_id, qup_data_t *p_rx_obj)
+qup_return_t qup_recv_data(blsp_qup_id_t id, qup_data_t *p_rx_obj)
{
qup_return_t ret = QUP_ERR_UNDEFINED;
- if (p_rx_obj->protocol == ((read32(QUP_ADDR(gsbi_id, QUP_CONFIG)) >>
+ if (p_rx_obj->protocol == ((read32(QUP_ADDR(id, QUP_CONFIG)) >>
QUP_MINI_CORE_PROTO_SHFT) & QUP_MINI_CORE_PROTO_MASK)) {
switch (p_rx_obj->protocol) {
case QUP_MINICORE_I2C_MASTER:
- ret = qup_i2c_recv_data(gsbi_id, p_rx_obj);
+ ret = qup_i2c_recv_data(id, p_rx_obj);
break;
default:
ret = QUP_ERR_UNSUPPORTED;