aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorSandeep Tripathy <sandeep.tripathy@broadcom.com>2019-04-12 21:34:12 +0530
committerJérôme Forissier <jerome.forissier@linaro.org>2019-04-13 12:13:53 +0200
commit525c44ee7f3b0f10ca4f3b7f0bb5b899e2bccbc6 (patch)
treedd8060c90fd1c8d4aa5c069d1df4c0c7c8ea54f3 /core
parent16b6c0f6066f4b4036581bc7bd04508251a5bfb0 (diff)
drivers: bcm_sotp: add SOTP driver
low level driver for Broadcom SOTP controller. Acked-by: Jens Wiklander <jens.wiklander@linaro.org> Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org> Signed-off-by: Rahul Gupta <rahul.gupta@broadcom.com> Signed-off-by: Sandeep Tripathy <sandeep.tripathy@broadcom.com>
Diffstat (limited to 'core')
-rw-r--r--core/drivers/bcm_sotp.c131
-rw-r--r--core/drivers/sub.mk1
-rw-r--r--core/include/drivers/bcm_sotp.h15
3 files changed, 147 insertions, 0 deletions
diff --git a/core/drivers/bcm_sotp.c b/core/drivers/bcm_sotp.c
new file mode 100644
index 00000000..03d18a42
--- /dev/null
+++ b/core/drivers/bcm_sotp.c
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright 2019 Broadcom.
+ */
+
+#include <assert.h>
+#include <drivers/bcm_sotp.h>
+#include <initcall.h>
+#include <io.h>
+#include <kernel/delay.h>
+#include <mm/core_memprot.h>
+#include <platform_config.h>
+#include <util.h>
+
+#define SOTP_PROG_CONTROL 0x0
+#define SOTP_PROG_CONTROL__OTP_CPU_MODE_EN BIT(15)
+#define SOTP_PROG_CONTROL__OTP_DISABLE_ECC BIT(9)
+#define SOTP_ADDR__OTP_ROW_ADDR_R 6
+
+#define SOTP_ADDR 0xc
+
+#define SOTP_CTRL_0 0x10
+#define SOTP_CTRL_0__START 1
+#define SOTP_READ 0
+
+#define SOTP_STAT_0 0x18
+#define SOTP_STATUS_0__FDONE BIT(3)
+
+#define SOTP_STATUS_1 0x1c
+#define SOTP_STATUS_1__CMD_DONE BIT(1)
+#define SOTP_STATUS_1__ECC_DET BIT(17)
+
+#define SOTP_RDDATA_0 0x20
+#define SOTP_RDDATA_1 0x24
+#define SOTP_ADDR_MASK 0x3ff
+
+#define SOTP_ECC_ERR_DETECT BIT64(63)
+
+#define SOTP_TIMEOUT_US 300
+
+static vaddr_t bcm_sotp_base;
+
+static TEE_Result otp_status_done_wait(vaddr_t addr, uint32_t bit)
+{
+ uint64_t timeout = timeout_init_us(SOTP_TIMEOUT_US);
+
+ while (!(io_read32(addr) & bit))
+ if (timeout_elapsed(timeout))
+ return TEE_ERROR_BUSY;
+ return TEE_SUCCESS;
+}
+
+TEE_Result bcm_iproc_sotp_mem_read(uint32_t row_addr, uint32_t sotp_add_ecc,
+ uint64_t *rdata)
+{
+ uint64_t read_data = 0;
+ uint32_t reg_val = 0;
+ TEE_Result ret = TEE_SUCCESS;
+
+ assert(bcm_sotp_base);
+ /* Check for FDONE status */
+ ret = otp_status_done_wait((bcm_sotp_base + SOTP_STAT_0),
+ SOTP_STATUS_0__FDONE);
+ if (ret) {
+ EMSG("FDONE status done wait failed");
+ return ret;
+ }
+
+ /* Enable OTP access by CPU */
+ io_setbits32((bcm_sotp_base + SOTP_PROG_CONTROL),
+ SOTP_PROG_CONTROL__OTP_CPU_MODE_EN);
+
+ if (sotp_add_ecc == 1) {
+ io_clrbits32((bcm_sotp_base + SOTP_PROG_CONTROL),
+ SOTP_PROG_CONTROL__OTP_DISABLE_ECC);
+ } else {
+ io_setbits32((bcm_sotp_base + SOTP_PROG_CONTROL),
+ SOTP_PROG_CONTROL__OTP_DISABLE_ECC);
+ }
+
+ /* 10 bit row address */
+ reg_val = (row_addr & SOTP_ADDR_MASK) << SOTP_ADDR__OTP_ROW_ADDR_R;
+ io_write32((bcm_sotp_base + SOTP_ADDR), reg_val);
+ reg_val = SOTP_READ;
+ io_write32((bcm_sotp_base + SOTP_CTRL_0), reg_val);
+
+ /* Start bit to tell SOTP to send command to the OTP controller */
+ io_setbits32((bcm_sotp_base + SOTP_CTRL_0), SOTP_CTRL_0__START);
+
+ /* Wait for SOTP command done to be set */
+ ret = otp_status_done_wait((bcm_sotp_base + SOTP_STAT_0),
+ SOTP_STATUS_1__CMD_DONE);
+ if (ret) {
+ EMSG("FDONE cmd done wait failed\n");
+ return ret;
+ }
+
+ DMSG("CMD Done\n");
+
+ /* Clr Start bit after command done */
+ io_clrbits32((bcm_sotp_base + SOTP_CTRL_0), SOTP_CTRL_0__START);
+ read_data = io_read32(bcm_sotp_base + SOTP_RDDATA_1);
+ read_data = ((read_data & 0x1ff) << 32);
+ read_data |= io_read32(bcm_sotp_base + SOTP_RDDATA_0);
+
+ reg_val = io_read32(bcm_sotp_base + SOTP_STATUS_1);
+ /* no ECC check till row 15 */
+ if ((row_addr > 15) && (reg_val & SOTP_STATUS_1__ECC_DET)) {
+ EMSG("SOTP ECC ERROR Detected ROW %d\n", row_addr);
+ read_data = SOTP_ECC_ERR_DETECT;
+ }
+
+ /* Command done is cleared */
+ io_setbits32((bcm_sotp_base + SOTP_STATUS_1), SOTP_STATUS_1__CMD_DONE);
+ io_clrbits32((bcm_sotp_base + SOTP_PROG_CONTROL),
+ SOTP_PROG_CONTROL__OTP_CPU_MODE_EN);
+ DMSG("read done\n");
+
+ *rdata = read_data;
+ return ret;
+}
+
+static TEE_Result bcm_sotp_init(void)
+{
+ bcm_sotp_base = (vaddr_t)phys_to_virt(SOTP_BASE, MEM_AREA_IO_SEC);
+
+ DMSG("bcm_sotp init done\n");
+ return TEE_SUCCESS;
+}
+
+driver_init(bcm_sotp_init);
diff --git a/core/drivers/sub.mk b/core/drivers/sub.mk
index e0cf05ae..bbe5cef0 100644
--- a/core/drivers/sub.mk
+++ b/core/drivers/sub.mk
@@ -26,3 +26,4 @@ srcs-$(CFG_STM32_RNG) += stm32_rng.c
srcs-$(CFG_STM32_UART) += stm32_uart.c
srcs-$(CFG_STM32_I2C) += stm32_i2c.c
srcs-$(CFG_BCM_HWRNG) += bcm_hwrng.c
+srcs-$(CFG_BCM_SOTP) += bcm_sotp.c
diff --git a/core/include/drivers/bcm_sotp.h b/core/include/drivers/bcm_sotp.h
new file mode 100644
index 00000000..1b66115d
--- /dev/null
+++ b/core/include/drivers/bcm_sotp.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright 2019 Broadcom.
+ */
+
+#ifndef BCM_SOTP_H
+#define BCM_SOTP_H
+
+#include <stdint.h>
+#include <tee_api.h>
+
+TEE_Result bcm_iproc_sotp_mem_read(uint32_t row_addr, uint32_t sotp_add_ecc,
+ uint64_t *rdata);
+
+#endif