Stefan Reinauer (stefan.reinauer(a)coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9582
-gerrit
commit 64cff8ea3517127dba8d3f7107ea13a4f121a553
Author: Daisuke Nojiri <dnojiri(a)chromium.org>
Date: Fri Nov 21 15:33:26 2014 -0800
ipq806x: copy i2c, qup, and gsbi drivers from depthcharge
this is a preparation for porting these drivers to coreboot. the code will be modified by the following patches.
BUG=chrome-os-partner:33647
BRANCH=ToT
TEST=None
Change-Id: I2baeed5b6130ace2515d6e28115f8d1008004976
Signed-off-by: Stefan Reinauer <reinauer(a)chromium.org>
Original-Commit-Id: 7c03a186a599be9d274c6fcdea1906529cc117d7
Original-Signed-off-by: Daisuke Nojiri <dnojiri(a)chromium.org>
Original-Change-Id: I9f3428ef02d2ba15ae63c99b10fe0605dd595313
Original-Reviewed-on: https://chromium-review.googlesource.com/231461
Original-Reviewed-by: Vadim Bendebury <vbendeb(a)chromium.org>
Original-Commit-Queue: Vadim Bendebury <vbendeb(a)chromium.org>
Original-Tested-by: Vadim Bendebury <vbendeb(a)chromium.org>
---
src/soc/qualcomm/ipq806x/gsbi.c | 115 ++++++++++
src/soc/qualcomm/ipq806x/gsbi.h | 60 +++++
src/soc/qualcomm/ipq806x/i2c.c | 143 ++++++++++++
src/soc/qualcomm/ipq806x/qup.c | 483 ++++++++++++++++++++++++++++++++++++++++
src/soc/qualcomm/ipq806x/qup.h | 207 +++++++++++++++++
5 files changed, 1008 insertions(+)
diff --git a/src/soc/qualcomm/ipq806x/gsbi.c b/src/soc/qualcomm/ipq806x/gsbi.c
new file mode 100644
index 0000000..be75d9a
--- /dev/null
+++ b/src/soc/qualcomm/ipq806x/gsbi.c
@@ -0,0 +1,115 @@
+/*
+ * This file is part of the depthcharge project.
+ *
+ * Copyright (C) 2014 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <arch/io.h>
+#include "drivers/gpio/ipq806x.h"
+#include "ipq806x_gsbi.h"
+
+//TODO: To be implemented as part of the iomap.
+static int gsbi_base[] = {
+ 0x12440000, /*GSBI1*/
+ 0x12480000, /*GSBI2*/
+ 0x16200000, /*GSBI3*/
+ 0x16300000, /*GSBI4*/
+ 0x1A200000, /*GSBI5*/
+ 0x16500000, /*GSBI6*/
+ 0x16600000 /*GSBI7*/
+};
+
+#define QUP_APPS_ADDR(N, os) ((void *)((0x009029C8+os)+(32*(N-1))))
+#define GSBI_HCLK_CTL(N) ((void *)(0x009029C0 + (32*(N-1))))
+#define GSBI_RESET(N) ((void *)(0x009029DC + (32*(N-1))))
+#define GSBI_CTL(N) ((void *)(gsbi_base[N-1]))
+
+#define GSBI_APPS_MD_OFFSET 0x0
+#define GSBI_APPS_NS_OFFSET 0x4
+#define GSBI_APPS_MAX_OFFSET 0xff
+
+#define GPIO_FUNC_I2C 0x1
+
+gsbi_return_t gsbi_init(gsbi_id_t gsbi_id, gsbi_protocol_t protocol)
+{
+ unsigned i = 0;
+ unsigned qup_apps_ini[] = {
+ GSBI_APPS_NS_OFFSET, 0xf80b43,
+ GSBI_APPS_NS_OFFSET, 0xfc095b,
+ GSBI_APPS_NS_OFFSET, 0xfc015b,
+ GSBI_APPS_NS_OFFSET, 0xfc005b,
+ GSBI_APPS_NS_OFFSET, 0xA05,
+ GSBI_APPS_NS_OFFSET, 0x185,
+ GSBI_APPS_MD_OFFSET, 0x100fb,
+ GSBI_APPS_NS_OFFSET, 0xA05,
+ GSBI_APPS_NS_OFFSET, 0xfc015b,
+ GSBI_APPS_NS_OFFSET, 0xfc015b,
+ GSBI_APPS_NS_OFFSET, 0xfc095b,
+ GSBI_APPS_NS_OFFSET, 0xfc0b5b,
+ GSBI_APPS_MAX_OFFSET, 0x0
+ };
+
+ gsbi_return_t ret = GSBI_SUCCESS;
+
+ writel(0, GSBI_RESET(gsbi_id));
+
+ switch (gsbi_id) {
+ case GSBI_ID_4: {
+ /* Configure GPIOs 13 - SCL, 12 - SDA, 2mA gpio_en */
+ gpio_tlmm_config_set(12, GPIO_FUNC_I2C,
+ GPIO_NO_PULL, GPIO_2MA, 1);
+ gpio_tlmm_config_set(13, GPIO_FUNC_I2C,
+ GPIO_NO_PULL, GPIO_2MA, 1);
+ }
+ break;
+ case GSBI_ID_1: {
+ /* Configure GPIOs 54 - SCL, 53 - SDA, 2mA gpio_en */
+ gpio_tlmm_config_set(54, GPIO_FUNC_I2C,
+ GPIO_NO_PULL, GPIO_2MA, 1);
+ gpio_tlmm_config_set(53, GPIO_FUNC_I2C,
+ GPIO_NO_PULL, GPIO_2MA, 1);
+ }
+ break;
+ default: {
+ ret = GSBI_UNSUPPORTED;
+ goto bail_out;
+ }
+ }
+
+ /*Select i2c protocol*/
+ writel((2 << 4), GSBI_CTL(gsbi_id));
+
+ //TODO: Make use of clock API when available instead of the hardcoding.
+ /* Clock set to 24Mhz */
+ for (i = 0; GSBI_APPS_MAX_OFFSET != qup_apps_ini[i]; i += 2)
+ writel(qup_apps_ini[i+1],
+ QUP_APPS_ADDR(gsbi_id, qup_apps_ini[i]));
+
+ writel(((1 << 6)|(1 << 4)), GSBI_HCLK_CTL(gsbi_id));
+
+bail_out:
+ return ret;
+}
diff --git a/src/soc/qualcomm/ipq806x/gsbi.h b/src/soc/qualcomm/ipq806x/gsbi.h
new file mode 100644
index 0000000..0da7a47
--- /dev/null
+++ b/src/soc/qualcomm/ipq806x/gsbi.h
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the depthcharge project.
+ *
+ * Copyright (C) 2014 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __GSBI_TYPES_H__
+#define __GSBI_TYPES_H__
+
+typedef enum {
+ GSBI_ID_1 = 1,
+ GSBI_ID_2,
+ GSBI_ID_3,
+ GSBI_ID_4,
+ GSBI_ID_5,
+ GSBI_ID_6,
+ GSBI_ID_7,
+} gsbi_id_t;
+
+typedef enum {
+ GSBI_SUCCESS = 0,
+ GSBI_ID_ERROR,
+ GSBI_ERROR,
+ GSBI_UNSUPPORTED
+} gsbi_return_t;
+
+typedef enum {
+ GSBI_PROTO_I2C_UIM = 1,
+ GSBI_PROTO_I2C_ONLY,
+ GSBI_PROTO_SPI_ONLY,
+ GSBI_PROTO_UART_FLOW_CTL,
+ GSBI_PROTO_UIM,
+ GSBI_PROTO_I2C_UART,
+} gsbi_protocol_t;
+
+gsbi_return_t gsbi_init(gsbi_id_t gsbi_id, gsbi_protocol_t protocol);
+#endif
diff --git a/src/soc/qualcomm/ipq806x/i2c.c b/src/soc/qualcomm/ipq806x/i2c.c
new file mode 100644
index 0000000..9bae822
--- /dev/null
+++ b/src/soc/qualcomm/ipq806x/i2c.c
@@ -0,0 +1,143 @@
+/*
+ * This file is part of the depthcharge project.
+ *
+ * Copyright (C) 2014 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <libpayload.h>
+
+#include "base/container_of.h"
+#include "drivers/bus/i2c/i2c.h"
+#include "drivers/bus/i2c/ipq806x_qup.h"
+#include "drivers/bus/i2c/ipq806x_gsbi.h"
+#include "drivers/bus/i2c/ipq806x.h"
+
+static int i2c_init(unsigned gsbi_id)
+{
+ gsbi_return_t gsbi_ret = 0;
+ qup_return_t qup_ret = 0;
+ qup_config_t gsbi4_qup_config = {
+ QUP_MINICORE_I2C_MASTER,
+ 100000,
+ 24000000,
+ QUP_MODE_FIFO
+ };
+
+ gsbi_ret = gsbi_init(gsbi_id, GSBI_PROTO_I2C_ONLY);
+ if (GSBI_SUCCESS != gsbi_ret)
+ return 1;
+
+ qup_ret = qup_init(gsbi_id, &gsbi4_qup_config);
+ if (QUP_SUCCESS != qup_ret)
+ return 1;
+
+ qup_ret = qup_reset_i2c_master_status(gsbi_id);
+ if (QUP_SUCCESS != qup_ret)
+ return 1;
+
+ return 0;
+}
+
+static int i2c_read(uint32_t gsbi_id, uint8_t slave,
+ uint8_t *data, int data_len)
+{
+ qup_data_t obj;
+ qup_return_t qup_ret = 0;
+
+ memset(&obj, 0, sizeof(obj));
+ obj.protocol = QUP_MINICORE_I2C_MASTER;
+ obj.p.iic.addr = slave;
+ obj.p.iic.data_len = data_len;
+ obj.p.iic.data = data;
+ qup_ret = qup_recv_data(gsbi_id, &obj);
+
+ if (QUP_SUCCESS != qup_ret)
+ return 1;
+ else
+ return 0;
+}
+
+static int i2c_write(uint32_t gsbi_id, uint8_t slave,
+ uint8_t *data, int data_len, uint8_t stop_seq)
+{
+ qup_data_t obj;
+ qup_return_t qup_ret = 0;
+
+ memset(&obj, 0, sizeof(obj));
+ obj.protocol = QUP_MINICORE_I2C_MASTER;
+ obj.p.iic.addr = slave;
+ obj.p.iic.data_len = data_len;
+ obj.p.iic.data = data;
+ qup_ret = qup_send_data(gsbi_id, &obj, stop_seq);
+
+ if (QUP_SUCCESS != qup_ret)
+ return 1;
+ else
+ return 0;
+}
+
+static int i2c_transfer(struct I2cOps *me, I2cSeg *segments, int seg_count)
+{
+ Ipq806xI2c *bus = container_of(me, Ipq806xI2c, ops);
+ I2cSeg *seg = segments;
+ int ret = 0;
+
+ if (!bus->initialized)
+ if (0 != i2c_init(bus->gsbi_id))
+ return 1;
+
+ while (seg_count--) {
+ if (seg->read)
+ ret = i2c_read(bus->gsbi_id, seg->chip,
+ seg->buf, seg->len);
+ else
+ ret = i2c_write(bus->gsbi_id, seg->chip,
+ seg->buf, seg->len,
+ (seg_count ? 0 : 1));
+ seg++;
+ }
+
+ if (QUP_SUCCESS != ret) {
+ qup_set_state(bus->gsbi_id, QUP_STATE_RESET);
+ return 1;
+ }
+
+ return 0;
+}
+
+Ipq806xI2c *new_ipq806x_i2c(unsigned gsbi_id)
+{
+ Ipq806xI2c *bus = 0;
+
+ if (!i2c_init(gsbi_id)) {
+ bus = xzalloc(sizeof(*bus));
+ bus->gsbi_id = gsbi_id;
+ bus->initialized = 1;
+ bus->ops.transfer = &i2c_transfer;
+ }
+ return bus;
+}
diff --git a/src/soc/qualcomm/ipq806x/qup.c b/src/soc/qualcomm/ipq806x/qup.c
new file mode 100644
index 0000000..5ac7f07
--- /dev/null
+++ b/src/soc/qualcomm/ipq806x/qup.c
@@ -0,0 +1,483 @@
+/*
+ * This file is part of the depthcharge project.
+ *
+ * Copyright (C) 2014 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <arch/io.h>
+#include <libpayload.h>
+#include "ipq806x_qup.h"
+
+//TODO: refactor the following array to iomap driver.
+static unsigned gsbi_qup_base[] = {
+ 0x12460000, /*gsbi 1*/
+ 0x124A0000, /*gsbi 2*/
+ 0x16280000, /*gsbi 3*/
+ 0x16380000, /*gsbi 4*/
+ 0x1A280000, /*gsbi 5*/
+ 0x16580000, /*gsbi 6*/
+ 0x16680000, /*gsbi 7*/
+};
+
+#define QUP_ADDR(gsbi_num, reg) ((void *)((gsbi_qup_base[gsbi_num-1]) + (reg)))
+#define MAX_DELAY_MS 100
+
+static char *get_error_string(qup_return_t error)
+{
+ char *msg;
+ switch (error) {
+ case QUP_ERR_BAD_PARAM:
+ msg = "bad parameter";
+ break;
+ case QUP_ERR_STATE_SET:
+ msg = "setting state failed";
+ break;
+ case QUP_ERR_TIMEOUT:
+ msg = "timeout";
+ break;
+ case QUP_ERR_UNSUPPORTED:
+ msg = "unsupported";
+ break;
+ case QUP_ERR_I2C_INVALID_SLAVE_ADDR:
+ msg = "invalid slave address";
+ break;
+ case QUP_ERR_XFER_FAIL:
+ msg = "transfer failed";
+ break;
+ case QUP_ERR_UNDEFINED:
+ default:
+ msg = "undefined";
+ break;
+ }
+ return msg;
+}
+
+static qup_return_t qup_i2c_master_status(gsbi_id_t gsbi_id)
+{
+ qup_return_t ret = QUP_SUCCESS;
+ uint32_t reg_val = readl(QUP_ADDR(gsbi_id, QUP_I2C_MASTER_STATUS));
+
+ if (readl(QUP_ADDR(gsbi_id, QUP_ERROR_FLAGS)))
+ ret = QUP_ERR_XFER_FAIL;
+ else if (reg_val & QUP_I2C_INVALID_READ_ADDR)
+ ret = QUP_ERR_I2C_INVALID_SLAVE_ADDR;
+ else if (reg_val & (QUP_I2C_FAILED_MASK |
+ QUP_I2C_ARB_LOST |
+ QUP_I2C_BUS_ERROR))
+ ret = QUP_ERR_XFER_FAIL;
+
+ return ret;
+}
+
+static qup_return_t qup_wait_for_state(gsbi_id_t gsbi_id, unsigned wait_for)
+{
+ qup_return_t ret = QUP_ERR_STATE_SET;
+ uint32_t val = 0;
+ uint32_t start_ts;
+ uint32_t d = MAX_DELAY_MS * timer_hz() / 1000;
+ uint8_t final_state = 0;
+
+ start_ts = timer_raw_value();
+ do {
+ val = readl(QUP_ADDR(gsbi_id, QUP_STATE));
+ final_state = ((val & (QUP_STATE_VALID_MASK|QUP_STATE_MASK))
+ == (QUP_STATE_VALID|wait_for));
+ } while ((!final_state) && (start_ts > (timer_raw_value() - d)));
+
+ if (final_state)
+ ret = QUP_SUCCESS;
+
+ return ret;
+}
+
+static qup_return_t qup_i2c_write(gsbi_id_t gsbi_id, uint8_t mode,
+ qup_data_t *p_tx_obj, uint8_t stop_seq)
+{
+ qup_return_t ret = QUP_ERR_UNDEFINED;
+ uint32_t start_ts;
+ uint32_t d = MAX_DELAY_MS * timer_hz() / 1000;
+
+ switch (mode) {
+ case QUP_MODE_FIFO: {
+ 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;
+
+ writel(0x7C, QUP_ADDR(gsbi_id, QUP_ERROR_FLAGS));
+ writel(0x7C, QUP_ADDR(gsbi_id, QUP_ERROR_FLAGS_EN));
+ qup_reset_i2c_master_status(gsbi_id);
+ qup_set_state(gsbi_id, QUP_STATE_RUN);
+
+ writel((QUP_I2C_START_SEQ | QUP_I2C_ADDR(addr)),
+ QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO));
+
+ while (data_len) {
+ if (data_len == 1 && stop_seq) {
+ writel((QUP_I2C_STOP_SEQ |
+ QUP_I2C_DATA(data_ptr[idx])),
+ QUP_ADDR(gsbi_id,
+ QUP_OUTPUT_FIFO));
+ } else {
+ writel((QUP_I2C_DATA_SEQ |
+ QUP_I2C_DATA(data_ptr[idx])),
+ QUP_ADDR(gsbi_id,
+ QUP_OUTPUT_FIFO));
+ }
+ data_len--;
+ idx++;
+ start_ts = timer_raw_value();
+ while (data_len && readl(QUP_ADDR(gsbi_id,
+ QUP_OPERATIONAL)) &
+ OUTPUT_FIFO_FULL) {
+ ret = qup_i2c_master_status(gsbi_id);
+ if (QUP_SUCCESS != ret)
+ goto bailout;
+ if (start_ts < (timer_raw_value() - d)) {
+ ret = QUP_ERR_TIMEOUT;
+ goto bailout;
+ }
+ }
+ /* 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 (readl(QUP_ADDR(gsbi_id, QUP_OPERATIONAL)) &
+ OUTPUT_SERVICE_FLAG) {
+ writel(OUTPUT_SERVICE_FLAG,
+ QUP_ADDR(gsbi_id,
+ QUP_OPERATIONAL));
+ }
+ }
+
+ start_ts = timer_raw_value();
+ while (((readl(QUP_ADDR(gsbi_id, QUP_OPERATIONAL))) &
+ OUTPUT_FIFO_NOT_EMPTY)) {
+ ret = qup_i2c_master_status(gsbi_id);
+ if (QUP_SUCCESS != ret)
+ goto bailout;
+ if (start_ts < (timer_raw_value() - d)) {
+ ret = QUP_ERR_TIMEOUT;
+ goto bailout;
+ }
+ }
+
+ qup_set_state(gsbi_id, QUP_STATE_PAUSE);
+ ret = QUP_SUCCESS;
+ }
+ break;
+
+ default:
+ ret = QUP_ERR_UNSUPPORTED;
+ }
+
+bailout:
+ if (QUP_SUCCESS != ret) {
+ qup_set_state(gsbi_id, QUP_STATE_RESET);
+ printf("%s() returns %s\n", __func__, get_error_string(ret));
+ }
+
+ return ret;
+}
+
+static qup_return_t qup_i2c_read(gsbi_id_t gsbi_id, uint8_t mode,
+ qup_data_t *p_tx_obj)
+{
+ qup_return_t ret = QUP_ERR_UNDEFINED;
+ uint32_t start_ts;
+ uint32_t d = MAX_DELAY_MS * timer_hz() / 1000;
+
+ switch (mode) {
+ case QUP_MODE_FIFO: {
+ 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;
+
+ writel(0x7C, QUP_ADDR(gsbi_id, QUP_ERROR_FLAGS));
+ writel(0x7C, QUP_ADDR(gsbi_id, QUP_ERROR_FLAGS_EN));
+ qup_reset_i2c_master_status(gsbi_id);
+ qup_set_state(gsbi_id, QUP_STATE_RUN);
+
+ writel((QUP_I2C_START_SEQ |
+ (QUP_I2C_ADDR(addr)|
+ QUP_I2C_SLAVE_READ)),
+ QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO));
+
+ writel((QUP_I2C_RECV_SEQ | data_len),
+ QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO));
+
+ start_ts = timer_raw_value();
+ while ((readl(QUP_ADDR(gsbi_id, QUP_OPERATIONAL)) &
+ OUTPUT_FIFO_NOT_EMPTY)) {
+ ret = qup_i2c_master_status(gsbi_id);
+ if (QUP_SUCCESS != ret)
+ goto bailout;
+ if (start_ts < (timer_raw_value() - d)) {
+ ret = QUP_ERR_TIMEOUT;
+ goto bailout;
+ }
+ }
+
+ writel(OUTPUT_SERVICE_FLAG,
+ QUP_ADDR(gsbi_id, QUP_OPERATIONAL));
+
+ while (data_len) {
+ unsigned data;
+ start_ts = timer_raw_value();
+ while ((!((readl(QUP_ADDR(gsbi_id, QUP_OPERATIONAL))) &
+ INPUT_SERVICE_FLAG))) {
+ ret = qup_i2c_master_status(gsbi_id);
+ if (QUP_SUCCESS != ret)
+ goto bailout;
+ if (start_ts < (timer_raw_value() - d)) {
+ ret = QUP_ERR_TIMEOUT;
+ goto bailout;
+ }
+ }
+
+ data = readl(QUP_ADDR(gsbi_id, QUP_INPUT_FIFO));
+
+ /*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--;
+ writel(INPUT_SERVICE_FLAG, QUP_ADDR(gsbi_id,
+ QUP_OPERATIONAL));
+ } 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--;
+ goto recv_done;
+ } else {
+ /* Tag: MINACK: Invalid master input data.*/
+ goto recv_done;
+ }
+ }
+recv_done:
+ writel(INPUT_SERVICE_FLAG,
+ QUP_ADDR(gsbi_id, QUP_OPERATIONAL));
+ p_tx_obj->p.iic.data_len = idx;
+ qup_set_state(gsbi_id, QUP_STATE_PAUSE);
+ ret = QUP_SUCCESS;
+ }
+ break;
+
+ default:
+ ret = QUP_ERR_UNSUPPORTED;
+ }
+
+bailout:
+ if (QUP_SUCCESS != ret) {
+ qup_set_state(gsbi_id, QUP_STATE_RESET);
+ printf("%s() returns %s\n", __func__, get_error_string(ret));
+ }
+
+ return ret;
+}
+
+qup_return_t qup_init(gsbi_id_t gsbi_id, qup_config_t *config_ptr)
+{
+ qup_return_t ret = QUP_ERR_UNDEFINED;
+ uint32_t reg_val;
+
+ /* Reset the QUP core.*/
+ writel(0x1, QUP_ADDR(gsbi_id, QUP_SW_RESET));
+
+ /*Wait till the reset takes effect */
+ ret = qup_wait_for_state(gsbi_id, QUP_STATE_RESET);
+
+ if (QUP_SUCCESS != ret)
+ return ret;
+
+ /*Reset the config*/
+ writel(0, QUP_ADDR(gsbi_id, QUP_CONFIG));
+
+ /*Program the config register*/
+ /*Set N value*/
+ reg_val = 0x0F;
+ /*Set protocol*/
+ switch (config_ptr->protocol) {
+ case QUP_MINICORE_I2C_MASTER: {
+ reg_val |= ((config_ptr->protocol &
+ QUP_MINI_CORE_PROTO_MASK) <<
+ QUP_MINI_CORE_PROTO_SHFT);
+ }
+ break;
+ default: {
+ ret = QUP_ERR_UNSUPPORTED;
+ goto bailout;
+ }
+ }
+ writel(reg_val, QUP_ADDR(gsbi_id, QUP_CONFIG));
+
+ /*Reset i2c clk cntl register*/
+ writel(0, QUP_ADDR(gsbi_id, QUP_I2C_MASTER_CLK_CTL));
+
+ /*Set QUP IO Mode*/
+ switch (config_ptr->mode) {
+ case QUP_MODE_FIFO: {
+ reg_val = QUP_OUTPUT_BIT_SHIFT_EN |
+ ((config_ptr->mode & QUP_MODE_MASK) <<
+ QUP_OUTPUT_MODE_SHFT) |
+ ((config_ptr->mode & QUP_MODE_MASK) <<
+ QUP_INPUT_MODE_SHFT);
+ }
+ break;
+ default: {
+ ret = QUP_ERR_UNSUPPORTED;
+ goto bailout;
+ }
+ }
+ writel(reg_val, QUP_ADDR(gsbi_id, QUP_IO_MODES));
+
+ /*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);
+ writel(reg_val, QUP_ADDR(gsbi_id, QUP_I2C_MASTER_CLK_CTL));
+
+bailout:
+ if (QUP_SUCCESS != ret)
+ printf("%s() returns %s\n", __func__, get_error_string(ret));
+
+ return ret;
+}
+
+qup_return_t qup_set_state(gsbi_id_t gsbi_id, uint32_t state)
+{
+ qup_return_t ret = QUP_ERR_UNDEFINED;
+ unsigned curr_state = readl(QUP_ADDR(gsbi_id, QUP_STATE));
+
+ if ((state >= QUP_STATE_RESET && state <= QUP_STATE_PAUSE)
+ && (curr_state & QUP_STATE_VALID_MASK)) {
+ /*
+ * For PAUSE_STATE to RESET_STATE transition,
+ * two writes of 10[binary]) are required for the
+ * transition to complete.
+ */
+ if (QUP_STATE_PAUSE == curr_state &&
+ QUP_STATE_RESET == state) {
+ writel(0x2, QUP_ADDR(gsbi_id, QUP_STATE));
+ writel(0x2, QUP_ADDR(gsbi_id, QUP_STATE));
+ } else {
+ writel(state, QUP_ADDR(gsbi_id, QUP_STATE));
+ }
+ ret = qup_wait_for_state(gsbi_id, state);
+ }
+ return ret;
+}
+
+qup_return_t qup_reset_i2c_master_status(gsbi_id_t gsbi_id)
+{
+ /*
+ * Writing a one clears the status bits.
+ * Bit31-25, Bit1 and Bit0 are reserved.
+ */
+ //TODO: Define each status bit. OR all status bits in a single macro.
+ writel(0x3FFFFFC, QUP_ADDR(gsbi_id, QUP_I2C_MASTER_STATUS));
+ return QUP_SUCCESS;
+}
+
+qup_return_t qup_send_data(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj,
+ uint8_t stop_seq)
+{
+ qup_return_t ret = QUP_ERR_UNDEFINED;
+
+ if (p_tx_obj->protocol == ((readl(QUP_ADDR(gsbi_id, QUP_CONFIG)) >>
+ QUP_MINI_CORE_PROTO_SHFT) &
+ QUP_MINI_CORE_PROTO_MASK)) {
+ switch (p_tx_obj->protocol) {
+ case QUP_MINICORE_I2C_MASTER: {
+ uint8_t mode = (readl(QUP_ADDR(gsbi_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) {
+ int i;
+ printf("i2c tx bus %d device %2.2x:",
+ gsbi_id, p_tx_obj->p.iic.addr);
+ for (i = 0; i < p_tx_obj->p.iic.data_len; i++)
+ printf(" %2.2x",
+ p_tx_obj->p.iic.data[i]);
+ printf("\n");
+ }
+ break;
+ }
+
+ default:
+ ret = QUP_ERR_UNSUPPORTED;
+ }
+ }
+ return ret;
+}
+
+qup_return_t qup_recv_data(gsbi_id_t gsbi_id, qup_data_t *p_rx_obj)
+{
+ qup_return_t ret = QUP_ERR_UNDEFINED;
+ if (p_rx_obj->protocol == ((readl(QUP_ADDR(gsbi_id, QUP_CONFIG)) >>
+ QUP_MINI_CORE_PROTO_SHFT) &
+ QUP_MINI_CORE_PROTO_MASK)) {
+ switch (p_rx_obj->protocol) {
+ case QUP_MINICORE_I2C_MASTER: {
+ uint8_t mode = (readl(QUP_ADDR(gsbi_id,
+ QUP_IO_MODES)) >>
+ QUP_INPUT_MODE_SHFT) &
+ QUP_MODE_MASK;
+ ret = qup_i2c_read(gsbi_id, mode, p_rx_obj);
+ if (0) {
+ int i;
+ printf("i2c rxed on bus %d device %2.2x:",
+ gsbi_id, p_rx_obj->p.iic.addr);
+ for (i = 0; i < p_rx_obj->p.iic.data_len; i++)
+ printf(" %2.2x",
+ p_rx_obj->p.iic.data[i]);
+ printf("\n");
+ }
+ break;
+ }
+ default:
+ ret = QUP_ERR_UNSUPPORTED;
+ }
+ }
+ return ret;
+}
diff --git a/src/soc/qualcomm/ipq806x/qup.h b/src/soc/qualcomm/ipq806x/qup.h
new file mode 100644
index 0000000..f848cf6
--- /dev/null
+++ b/src/soc/qualcomm/ipq806x/qup.h
@@ -0,0 +1,207 @@
+/*
+ * This file is part of the depthcharge project.
+ *
+ * Copyright (C) 2014 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __QUP_H__
+#define __QUP_H__
+#include "ipq806x_gsbi.h"
+
+/* QUP block registers */
+#define QUP_CONFIG 0x0
+#define QUP_STATE 0x4
+#define QUP_IO_MODES 0x8
+#define QUP_SW_RESET 0xc
+#define QUP_TIME_OUT 0x10
+#define QUP_TIME_OUT_CURRENT 0x14
+#define QUP_OPERATIONAL 0x18
+#define QUP_ERROR_FLAGS 0x1c
+#define QUP_ERROR_FLAGS_EN 0x20
+#define QUP_TEST_CTRL 0x24
+#define QUP_MX_OUTPUT_COUNT 0x100
+#define QUP_MX_OUTPUT_CNT_CURRENT 0x104
+#define QUP_OUTPUT_DEBUG 0x108
+#define QUP_OUTPUT_FIFO_WORD_CNT 0x10c
+#define QUP_OUTPUT_FIFO 0x110
+#define QUP_MX_WRITE_COUNT 0x150
+#define QUP_WRITE_CNT_CURRENT 0x154
+#define QUP_MX_INPUT_COUNT 0x200
+#define QUP_READ_COUNT 0x208
+#define QUP_MX_READ_CNT_CURRENT 0x20c
+#define QUP_INPUT_DEBUG 0x210
+#define QUP_INPUT_FIFO_WORD_CNT 0x214
+#define QUP_INPUT_FIFO 0x218
+#define QUP_I2C_MASTER_CLK_CTL 0x400
+#define QUP_I2C_MASTER_STATUS 0x404
+
+#define OUTPUT_FIFO_FULL (1<<6)
+#define INPUT_FIFO_NOT_EMPTY (1<<5)
+#define OUTPUT_FIFO_NOT_EMPTY (1<<4)
+#define INPUT_SERVICE_FLAG (1<<9)
+#define OUTPUT_SERVICE_FLAG (1<<8)
+#define QUP_OUTPUT_BIT_SHIFT_EN (1<<16)
+
+#define QUP_MODE_MASK (0x03)
+#define QUP_OUTPUT_MODE_SHFT (10)
+#define QUP_INPUT_MODE_SHFT (12)
+
+#define QUP_FS_DIVIDER_MASK (0xFF)
+
+#define QUP_MINI_CORE_PROTO_SHFT (8)
+#define QUP_MINI_CORE_PROTO_MASK (0x0F)
+
+/* Mini-core states */
+#define QUP_STATE_RESET 0x0
+#define QUP_STATE_RUN 0x1
+#define QUP_STATE_PAUSE 0x3
+#define QUP_STATE_VALID (1<<2)
+#define QUP_STATE_MASK 0x3
+#define QUP_STATE_VALID_MASK (1<<2)
+
+/* Tags for output FIFO */
+#define QUP_I2C_1CLK_NOOP_SEQ 0x1 /*MSB 8-bit NOP, LSB 8-bits 1 clk.*/
+#define QUP_I2C_START_SEQ (0x1 << 8)
+#define QUP_I2C_DATA_SEQ (0x2 << 8)
+#define QUP_I2C_STOP_SEQ (0x3 << 8)
+#define QUP_I2C_RECV_SEQ (0x4 << 8)
+
+/* Tags for input FIFO */
+#define QUP_I2C_MIDATA_SEQ (0x5 << 8)
+#define QUP_I2C_MISTOP_SEQ (0x6 << 8)
+#define QUP_I2C_MINACK_SEQ (0x7 << 8)
+
+#define QUP_I2C_ADDR(x) ((x & 0xFF) << 1)
+#define QUP_I2C_DATA(x) (x & 0xFF)
+#define QUP_I2C_MI_TAG(x) (x & 0xFF00)
+#define QUP_I2C_SLAVE_READ (0x1)
+
+/*Bit vals for I2C_MASTER_CLK_CTL register */
+#define QUP_HS_DIVIDER_SHFT (8)
+#define QUP_DIVIDER_MIN_VAL (0x3)
+
+/* Bit masks for I2C_MASTER_STATUS register */
+#define QUP_I2C_INVALID_READ_SEQ (1 << 25)
+#define QUP_I2C_INVALID_READ_ADDR (1 << 24)
+#define QUP_I2C_INVALID_TAG (1 << 23)
+#define QUP_I2C_FAILED_MASK (0x3 << 6)
+#define QUP_I2C_ARB_LOST (1 << 4)
+#define QUP_I2C_BUS_ERROR (1 << 2)
+
+typedef enum {
+ QUP_SUCCESS = 0,
+ QUP_ERR_BAD_PARAM,
+ QUP_ERR_STATE_SET,
+ QUP_ERR_TIMEOUT,
+ QUP_ERR_UNSUPPORTED,
+ QUP_ERR_I2C_INVALID_SLAVE_ADDR,
+ QUP_ERR_XFER_FAIL,
+ QUP_ERR_UNDEFINED,
+} qup_return_t;
+
+typedef enum {
+ QUP_MINICORE_SPI = 1,
+ QUP_MINICORE_I2C_MASTER,
+ QUP_MINICORE_I2C_SLAVE
+} qup_protocol_t;
+
+typedef enum {
+ QUP_MODE_FIFO = 0,
+ QUP_MODE_BLOCK,
+ QUP_MODE_DATAMOVER,
+} qup_mode_t;
+
+typedef struct {
+ qup_protocol_t protocol;
+ unsigned clk_frequency;
+ unsigned src_frequency;
+ qup_mode_t mode;
+} qup_config_t;
+
+typedef struct {
+ qup_protocol_t protocol;
+ union {
+ struct {
+ uint8_t addr;
+ uint8_t *data;
+ unsigned data_len;
+ } iic;
+ struct {
+ void *in;
+ void *out;
+ unsigned size;
+ } spi;
+ } p;
+} qup_data_t;
+
+/*
+ * Initialize GSBI QUP block for FIFO I2C transfers.
+ * gsbi_id[IN]: GSBI for which QUP is to be initialized.
+ * config_ptr[IN]: configurations parameters for the QUP.
+ *
+ * return: QUP_SUCCESS, if initialization succeeds.
+ */
+qup_return_t qup_init(gsbi_id_t gsbi_id, qup_config_t *config_ptr);
+
+/*
+ * Set QUP state to run, pause, reset.
+ * gsbi_id[IN]: GSBI block for which QUP state is to be set.
+ * state[IN]: New state to transition to.
+ *
+ * return: QUP_SUCCESS, if state transition succeeds.
+ */
+qup_return_t qup_set_state(gsbi_id_t gsbi_id, uint32_t state);
+
+/*
+ * Reset the status bits set during an i2c transfer.
+ * gsbi_id[IN]: GSBI block for which i2c status bits are to be cleared.
+ *
+ * return: QUP_SUCCESS, if status bits are cleared successfully.
+ */
+qup_return_t qup_reset_i2c_master_status(gsbi_id_t gsbi_id);
+
+/*
+ * Send data to the peripheral on the bus.
+ * gsbi_id[IN]: GSBI block for which data is to be sent.
+ * p_tx_obj[IN]: Data to be sent to the slave on the bus.
+ * stop_seq[IN]: When set to non-zero QUP engine sends i2c stop sequnce.
+ *
+ * return: QUP_SUCCESS, when data is sent successfully to the peripheral.
+ */
+qup_return_t qup_send_data(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj,
+ uint8_t stop_seq);
+
+/*
+ * Receive data from peripheral on the bus.
+ * gsbi_id[IN]: GSBI block from which data is to be received.
+ * p_tx_obj[IN]: length of data to be received, slave address.
+ * [OUT]: buffer filled with data from slave.
+ *
+ * return: QUP_SUCCESS, when data is received successfully.
+ */
+qup_return_t qup_recv_data(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj);
+
+#endif //__QUP_H__
Stefan Reinauer (stefan.reinauer(a)coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9581
-gerrit
commit bb4c64906a08372010c0140987839393580291ad
Author: Daisuke Nojiri <dnojiri(a)chromium.org>
Date: Wed Nov 12 14:37:25 2014 -0800
storm: add hard_reset template
this is required to do early firmware selection using vboot2. actual
implementation can be done later.
BUG=chrome-os-partner:33755
BRANCH=ToT
TEST=Booted storm.
Change-Id: I8e9e168ea6fa3af149d5ad4ca51c5c9bba4d986d
Signed-off-by: Stefan Reinauer <reinauer(a)chromium.org>
Original-Commit-Id: 611c24773478c8c212d567bb4f2cb9a09898ddc8
Original-Change-Id: Idd1a1de4991a19902ffe45f01be89d47f4413779
Original-Signed-off-by: Daisuke Nojiri <dnojiri(a)chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/229425
Original-Commit-Queue: Vadim Bendebury <vbendeb(a)chromium.org>
Original-Tested-by: Vadim Bendebury <vbendeb(a)chromium.org>
---
src/mainboard/google/storm/Kconfig | 1 +
src/mainboard/google/storm/Makefile.inc | 5 +++++
src/mainboard/google/storm/reset.c | 26 ++++++++++++++++++++++++++
3 files changed, 32 insertions(+)
diff --git a/src/mainboard/google/storm/Kconfig b/src/mainboard/google/storm/Kconfig
index 5e010fc..00405e1 100644
--- a/src/mainboard/google/storm/Kconfig
+++ b/src/mainboard/google/storm/Kconfig
@@ -25,6 +25,7 @@ config BOARD_SPECIFIC_OPTIONS
select BOARD_ID_SUPPORT
select BOARD_ROMSIZE_KB_4096
select COMMON_CBFS_SPI_WRAPPER
+ select HAVE_HARD_RESET
select MAINBOARD_HAS_BOOTBLOCK_INIT
select SPI_FLASH
select SPI_FLASH_SPANSION
diff --git a/src/mainboard/google/storm/Makefile.inc b/src/mainboard/google/storm/Makefile.inc
index 80727b6..453caae 100644
--- a/src/mainboard/google/storm/Makefile.inc
+++ b/src/mainboard/google/storm/Makefile.inc
@@ -19,13 +19,18 @@
bootblock-y += bootblock.c
bootblock-y += cdp.c
+bootblock-y += reset.c
+
+verstage-y += reset.c
romstage-y += romstage.c
romstage-y += cdp.c
+romstage-y += reset.c
ramstage-y += boardid.c
ramstage-y += cdp.c
ramstage-y += mainboard.c
+ramstage-y += reset.c
bootblock-y += memlayout.ld
romstage-y += memlayout.ld
diff --git a/src/mainboard/google/storm/reset.c b/src/mainboard/google/storm/reset.c
new file mode 100644
index 0000000..8020fbf
--- /dev/null
+++ b/src/mainboard/google/storm/reset.c
@@ -0,0 +1,26 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <reset.h>
+
+void hard_reset(void)
+{
+ while (1)
+ ;
+}
Stefan Reinauer (stefan.reinauer(a)coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9580
-gerrit
commit fb17d7aeab175399afe84224d160d56653724148
Author: Tom Warren <twarren(a)nvidia.com>
Date: Mon Dec 8 14:18:13 2014 -0700
ryu: audio: Setup I2S1/DAP2 and EXTPERIPH1/MCLK muxes correctly
This configures I2S1 and the codec MCLK muxes to pass the PCM
audio data to the RT5677 codec. Once depthcharge RT5677 codec
driver changes are in, audio 'beeps' should be heard on boot
(Ctrl-U / devmode/recmode).
BUG=chrome-os-partner:32582
BRANCH=none
TEST=Built and booted Ryu/A44.
Change-Id: I2143d544c75ee7e03ffc809561171920650e8d7d
Signed-off-by: Stefan Reinauer <reinauer(a)chromium.org>
Original-Commit-Id: 600c12ddf3543d2dcb47fd3e2f0704803dac5957
Original-Change-Id: Ib071bcb41fba8f6d628a386ed233ec84a54b0323
Original-Signed-off-by: Tom Warren <twarren(a)nvidia.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/233945
Original-Reviewed-by: Aaron Durbin <adurbin(a)chromium.org>
---
src/mainboard/google/rush_ryu/mainboard.c | 39 +++++++++++++++++++++----------
1 file changed, 27 insertions(+), 12 deletions(-)
diff --git a/src/mainboard/google/rush_ryu/mainboard.c b/src/mainboard/google/rush_ryu/mainboard.c
index 2955958..8efd0a0 100644
--- a/src/mainboard/google/rush_ryu/mainboard.c
+++ b/src/mainboard/google/rush_ryu/mainboard.c
@@ -173,6 +173,21 @@ static int enable_lcd_vdd(void)
return 0;
}
+static const struct pad_config i2s1_pad[] = {
+ /* I2S1 */
+ PAD_CFG_SFIO(DAP2_SCLK, PINMUX_INPUT_ENABLE, I2S1),
+ PAD_CFG_SFIO(DAP2_FS, PINMUX_INPUT_ENABLE, I2S1),
+ PAD_CFG_SFIO(DAP2_DOUT, PINMUX_INPUT_ENABLE, I2S1),
+ PAD_CFG_SFIO(DAP2_DIN, PINMUX_INPUT_ENABLE | PINMUX_TRISTATE, I2S1),
+ /* codec MCLK via EXTPERIPH1 */
+ PAD_CFG_SFIO(DAP_MCLK1, PINMUX_PULL_NONE, EXTPERIPH1),
+};
+
+static const struct funit_cfg audio_funit[] = {
+ /* We need 1.5MHz for I2S1. So we use CLK_M */
+ FUNIT_CFG(I2S1, CLK_M, 1500, i2s1_pad, ARRAY_SIZE(i2s1_pad)),
+};
+
static int configure_display_blocks(void)
{
/* set and enable panel related vdd */
@@ -188,24 +203,24 @@ static int configure_display_blocks(void)
/* Audio init: clocks and enables/resets */
static void setup_audio(void)
{
- /* External peripheral 1: audio codec (RT5677) using 12MHz CLK1 */
+ /*
+ * External peripheral 1: audio codec (RT5677) uses 12MHz CLK1
+ * NOTE: We can't use a funits struct/call here because EXTPERIPH1/2/3
+ * don't have BASE regs or CAR RST/ENA bits. Also, the mux setting for
+ * EXTPERIPH1/DAP_MCLK1 is rolled into the I2S1 padcfg.
+ */
clock_configure_source(extperiph1, CLK_M, 12000);
- /*
- * We need 1.5MHz for I2S1. So, we use CLK_M. CLK_DIVIDER macro
- * returns a divisor (0xe) a little bit off from the ideal value (0xd),
- * but it's good enough for beeps.
- */
- clock_configure_source(i2s1, CLK_M, 1500);
+ soc_configure_funits(audio_funit, ARRAY_SIZE(audio_funit));
clock_external_output(1); /* For external RT5677 audio codec. */
/*
- * Confirmed by NVIDIA hardware team, we need to take ALL audio devices
- * connected to AHUB (AUDIO, APBIF, I2S, DAM, AMX, ADX, SPDIF, AFC) out
- * of reset and clock-enabled, otherwise reading AHUB devices (in our
- * case, I2S/APBIF/AUDIO<XBAR>) will hang.
- */
+ * Confirmed by NVIDIA hardware team, we need to take ALL audio devices
+ * connected to AHUB (AUDIO, APBIF, I2S, DAM, AMX, ADX, SPDIF, AFC) out
+ * of reset and clock-enabled, otherwise reading AHUB devices (in our
+ * case, I2S/APBIF/AUDIO<XBAR>) will hang.
+ */
clock_enable_audio();
}
Stefan Reinauer (stefan.reinauer(a)coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9579
-gerrit
commit a6a32cf3fa28e308a722ad1cf43ad3de07248ad1
Author: Tom Warren <twarren(a)nvidia.com>
Date: Fri Dec 5 13:34:53 2014 -0700
rush: audio: Setup I2S1/DAP2 and EXTPERIPH1/MCLK muxes correctly
With this change, audio 'beeps' are heard on boot if Ctrl-U is
pressed, or devmode/recmode is entered. I also tested via an
explicit call to VbExBeep in the kernel boot path. Note that
a couple of Rush CLs for depthcharge are needed for audio, too.
BUG=chrome-os-partner:32582
BRANCH=none
TEST=as above. Built and booted Rush/Norrin64.
Change-Id: I43c65a4d11c5ab7b16289e19f3b42cfc0300ea7c
Signed-off-by: Stefan Reinauer <reinauer(a)chromium.org>
Original-Commit-Id: 4a682fb2403f7c6d53e74bfa945481242577f6c3
Original-Change-Id: Ia37f077569afd806ce6574c4c58813fd7aca1644
Original-Signed-off-by: Tom Warren <twarren(a)nvidia.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/233671
Original-Reviewed-by: Aaron Durbin <adurbin(a)chromium.org>
---
src/mainboard/google/rush/mainboard.c | 29 ++++++++++++++++++++++-------
1 file changed, 22 insertions(+), 7 deletions(-)
diff --git a/src/mainboard/google/rush/mainboard.c b/src/mainboard/google/rush/mainboard.c
index bb4da19..341d373 100644
--- a/src/mainboard/google/rush/mainboard.c
+++ b/src/mainboard/google/rush/mainboard.c
@@ -95,18 +95,33 @@ static void setup_usb(void)
usb_setup_utmip((void *)TEGRA_USB3_BASE);
}
+static const struct pad_config i2s1_pad[] = {
+ /* I2S1 */
+ PAD_CFG_SFIO(DAP2_SCLK, PINMUX_INPUT_ENABLE, I2S1),
+ PAD_CFG_SFIO(DAP2_FS, PINMUX_INPUT_ENABLE, I2S1),
+ PAD_CFG_SFIO(DAP2_DOUT, PINMUX_INPUT_ENABLE, I2S1),
+ PAD_CFG_SFIO(DAP2_DIN, PINMUX_INPUT_ENABLE | PINMUX_TRISTATE, I2S1),
+ /* codec MCLK via EXTPERIPH1 */
+ PAD_CFG_SFIO(DAP_MCLK1, PINMUX_PULL_NONE, EXTPERIPH1),
+};
+
+static const struct funit_cfg audio_funit[] = {
+ /* We need 1.5MHz for I2S1. So we use CLK_M */
+ FUNIT_CFG(I2S1, CLK_M, 1500, i2s1_pad, ARRAY_SIZE(i2s1_pad)),
+};
+
/* Audio init: clocks and enables/resets */
static void setup_audio(void)
{
- /* External peripheral 1: audio codec (max98090) using 12MHz CLK1 */
- clock_configure_source(extperiph1, CLK_M, 12000);
-
/*
- * We need 1.5MHz for I2S1. So, we use CLK_M. CLK_DIVIDER macro
- * returns a divisor (0xe) a little bit off from the ideal value (0xd),
- * but it's good enough for beeps.
+ * External peripheral 1: audio codec (max98090) uses 12MHz CLK1
+ * NOTE: We can't use a funits struct/call here because EXTPERIPH1/2/3
+ * don't have BASE regs or CAR RST/ENA bits. Also, the mux setting for
+ * EXTPERIPH1/DAP_MCLK1 is rolled into the I2S1 padcfg.
*/
- clock_configure_source(i2s1, CLK_M, 1500);
+ clock_configure_source(extperiph1, CLK_M, 12000);
+
+ soc_configure_funits(audio_funit, ARRAY_SIZE(audio_funit));
clock_external_output(1); /* For external MAX98090 audio codec. */
Stefan Reinauer (stefan.reinauer(a)coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9578
-gerrit
commit b8ed3d85181f2fc0c8b92b705fadb7c7fc6705ac
Author: Dailunxue <lunxue.dai(a)rock-chips.com>
Date: Wed Dec 3 16:03:23 2014 +0800
rk3288: Increase the delay to 10us when DDR revoked reset.
After DDR PHY reset de-asserted, DLL automatically starts to
lock, and the lock time is maximum 5.12us. The output clock of
DLL supplies the clocks of DDR controller and PHY digital logic.
So before DLL lock, the clocks of DDR controller and PHY digital
logic are indeterminate. When programming DDR in the period of
DLL unlock, the programming maybe unstable because of the
indeterminate clocks. So we need wait for at least 5.12us after
de-asserting reset, then start to program DDR registers.
Add some redundancy, the waiting time hopes to achieve 10us.
BUG=chrome-os-partner:33148
TEST=I'm using the following command line test ok(15000 cycles).
"while sleep 4 && dut-control cold_reset:on sleep:.1 cold_reset:off;
do : ; done"
BRANCH=None
Change-Id: Ie7d615f5a2264c615c4b4413d6b828cd3d78cd2b
Signed-off-by: Stefan Reinauer <reinauer(a)chromium.org>
Original-Commit-Id: 54e1a439c0e29aaf4fc542ae756f7bb036ceaf3e
Original-Change-Id: I55f8cb11ed3d7962567c5f40a31e6c8aed8fdcb0
Original-Signed-off-by: DaiLunXue <dlx(a)rock-chips.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/232894
Original-Reviewed-by: Julius Werner <jwerner(a)chromium.org>
Original-Commit-Queue: Lunxue Dai <lunxue.dai(a)rock-chips.com>
Original-Tested-by: Lunxue Dai <lunxue.dai(a)rock-chips.com>
---
src/soc/rockchip/rk3288/sdram.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/soc/rockchip/rk3288/sdram.c b/src/soc/rockchip/rk3288/sdram.c
index d49b860..5a158ad 100644
--- a/src/soc/rockchip/rk3288/sdram.c
+++ b/src/soc/rockchip/rk3288/sdram.c
@@ -531,7 +531,7 @@ static void phy_pctrl_reset(struct rk3288_ddr_publ_regs *ddr_publ_regs,
rkclk_ddr_reset(channel, 1, 0);
udelay(10);
rkclk_ddr_reset(channel, 0, 0);
- udelay(1);
+ udelay(10);
}
static void phy_dll_bypass_set(struct rk3288_ddr_publ_regs *ddr_publ_regs,
Stefan Reinauer (stefan.reinauer(a)coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9577
-gerrit
commit 61ae26cde1060d7cb8b1dafaaee95c3cbb67bd86
Author: Vadim Bendebury <vbendeb(a)chromium.org>
Date: Sat Dec 6 18:24:56 2014 -0800
storm: add ipq8064 blobs to the CBFS
Files necessary for the SOC bringup are added to the CBFS as raw
blobs.
Ipq8064 specific MBN header will allow to determine were the blobs
should be loaded and what start address should be used.
BRANCH=storm
BUG=chrome-os-partner:34161
TEST=build storm firmware and verify that the right components are added:
$ emerge-storm coreboot chromeos-bootimage
$ cbfstool /build/storm/firmware/image.bin print
image.bin: 8192 kB, bootblocksize 32488, romsize 2883584, offset 0x7f40
alignment: 64 bytes, architecture: arm
Name Offset Type Size
cdt.mbn 0x7f40 raw 376
ddr.mbn 0x8100 raw 25820
rpm.mbn 0xe640 raw 78512
tz.mbn 0x21940 raw 85360
fallback/verstage 0x36700 stage 39500
fallback/romstage 0x401c0 stage 15652
fallback/ramstage 0x43f40 stage 24328
config 0x49e80 raw 2701
fallback/payload 0x4a940 payload 65592
u-boot.dtb 0x5a9c0 (unknown) 2922
(empty) 0x5b580 null 2509336
$
Change-Id: I967cd20364c90a1ef7add959621992c2356f158d
Signed-off-by: Stefan Reinauer <reinauer(a)chromium.org>
Original-Commit-Id: 6b5238d47da417b8b1993ad3348f4c32381cd0e4
Original-Change-Id: Id642ae68ef07750624f85b31ad891752d8af99bf
Original-Signed-off-by: Vadim Bendebury <vbendeb(a)chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/233672
Original-Reviewed-by: Aaron Durbin <adurbin(a)chromium.org>
---
src/soc/qualcomm/ipq806x/Makefile.inc | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/src/soc/qualcomm/ipq806x/Makefile.inc b/src/soc/qualcomm/ipq806x/Makefile.inc
index 604cdc1..16381a4 100644
--- a/src/soc/qualcomm/ipq806x/Makefile.inc
+++ b/src/soc/qualcomm/ipq806x/Makefile.inc
@@ -63,3 +63,15 @@ $(objcbfs)/bootblock.bin: $(call strip_quotes,$(CONFIG_SBL_BLOB)) \
endif
CPPFLAGS_common += -Isrc/soc/qualcomm/ipq806x/include
+
+# List of binary blobs coreboot needs in CBFS to be able to boot up this SOC
+mbn-files := cdt.mbn ddr.mbn rpm.mbn tz.mbn
+
+# Location of the binary blobs
+mbn-root := 3rdparty/cpu/qualcomm/ipq806x
+
+# Create make variables to aid cbfs-files-handler in processing the blobs (add
+# them all as raw binaries at the root level).
+$(foreach f,$(mbn-files),$(eval cbfs-files-y += $(f))\
+ $(eval $(f)-file := $(mbn-root)/$(f))\
+ $(eval $(f)-type := raw))