615 lines
18 KiB
Diff
615 lines
18 KiB
Diff
From 03343c2a0b2ed8b85a6dce567bbe515d69f75697 Mon Sep 17 00:00:00 2001
|
|
From: Paolo Sabatino <paolo.sabatino@gmail.com>
|
|
Date: Thu, 18 Nov 2021 17:33:59 +0000
|
|
Subject: [PATCH] rk3328: add efuse initialization in ATF
|
|
|
|
---
|
|
plat/rockchip/rk3328/drivers/efuse/efuse.c | 397 +++++++++++++++++++++
|
|
plat/rockchip/rk3328/drivers/efuse/efuse.h | 142 ++++++++
|
|
plat/rockchip/rk3328/drivers/soc/soc.c | 6 +
|
|
plat/rockchip/rk3328/platform.mk | 4 +-
|
|
4 files changed, 548 insertions(+), 1 deletion(-)
|
|
create mode 100644 plat/rockchip/rk3328/drivers/efuse/efuse.c
|
|
create mode 100644 plat/rockchip/rk3328/drivers/efuse/efuse.h
|
|
|
|
diff --git a/plat/rockchip/rk3328/drivers/efuse/efuse.c b/plat/rockchip/rk3328/drivers/efuse/efuse.c
|
|
new file mode 100644
|
|
index 0000000..05bbcf4
|
|
--- /dev/null
|
|
+++ b/plat/rockchip/rk3328/drivers/efuse/efuse.c
|
|
@@ -0,0 +1,397 @@
|
|
+/*
|
|
+ * Copyright (C) 2016, Fuzhou Rockchip Electronics Co., Ltd.
|
|
+ * All rights reserved.
|
|
+ *
|
|
+ * Redistribution and use in source and binary forms, with or without
|
|
+ * modification, are permitted provided that the following conditions are met:
|
|
+ *
|
|
+ * Redistributions of source code must retain the above copyright notice, this
|
|
+ * list of conditions and the following disclaimer.
|
|
+ *
|
|
+ * 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.
|
|
+ *
|
|
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 <common/debug.h>
|
|
+#include <drivers/delay_timer.h>
|
|
+#include <lib/mmio.h>
|
|
+#include <platform_def.h>
|
|
+#include <efuse.h>
|
|
+#include <string.h>
|
|
+
|
|
+#define EFUSE_AUTO_MODE 1 // RK3328 wants auto mode on
|
|
+
|
|
+#define read32(reg) mmio_read_32(reg)
|
|
+#define write32(v, reg) mmio_write_32(reg, v)
|
|
+#define efuse8_read(offset) mmio_read_32(EFUSE8_BASE + offset)
|
|
+#define efuse8_write(v, offset) mmio_write_32(EFUSE8_BASE + offset, v)
|
|
+#define efuse32_read(offset) mmio_read_32(EFUSE32_BASE + offset)
|
|
+#define efuse32_write(v, offset) mmio_write_32(EFUSE32_BASE + offset, v)
|
|
+
|
|
+/* global buf to store efuse data */
|
|
+static uint32_t efuse32_buf[32] = {0};
|
|
+
|
|
+enum clk_type {
|
|
+ CLK = 0,
|
|
+ PCLK,
|
|
+};
|
|
+
|
|
+int enable_efuse_clk()
|
|
+{
|
|
+
|
|
+ uint32_t reg = 0;
|
|
+
|
|
+ reg = read32(CRU_BASE + CRU_CLKGATE_CON2);
|
|
+ /* enable efuse work clk */
|
|
+ if (reg & EFUSE_SRC_CLK_EN)
|
|
+ write32(EFUSE_SRC_CLK_EN << CRU_WRITE_MASK,
|
|
+ CRU_BASE + CRU_CLKGATE_CON2);
|
|
+
|
|
+ reg = read32(CRU_BASE + CRU_CLKGATE_CON15);
|
|
+ /* enable efuse APB clk */
|
|
+ if (reg & EFUSE_1024_PCLK_EN)
|
|
+ write32(EFUSE_1024_PCLK_EN << CRU_WRITE_MASK,
|
|
+ CRU_BASE + CRU_CLKGATE_CON15);
|
|
+
|
|
+ return reg;
|
|
+
|
|
+}
|
|
+
|
|
+/*
|
|
+static uint32_t enable_efuse_clk(int clk)
|
|
+{
|
|
+ uint32_t reg = 0;
|
|
+
|
|
+ switch (clk) {
|
|
+ case CLK:
|
|
+ reg = read32(CRU_BASE + CRU_CLKGATE_CON2);
|
|
+ // enable efuse work clk
|
|
+ if (reg & EFUSE_SRC_CLK_EN)
|
|
+ write32(EFUSE_SRC_CLK_EN << CRU_WRITE_MASK,
|
|
+ CRU_BASE + CRU_CLKGATE_CON2);
|
|
+ break;
|
|
+ case PCLK:
|
|
+ reg = read32(CRU_BASE + CRU_CLKGATE_CON15);
|
|
+ // enable efuse APB clk
|
|
+ if (reg & EFUSE_1024_PCLK_EN)
|
|
+ write32(EFUSE_1024_PCLK_EN << CRU_WRITE_MASK,
|
|
+ CRU_BASE + CRU_CLKGATE_CON15);
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return reg;
|
|
+}
|
|
+*/
|
|
+
|
|
+static void restore_efuse_clk(int clk, uint32_t reg)
|
|
+{
|
|
+ switch (clk) {
|
|
+ case CLK:
|
|
+ /* disable efuse work clk */
|
|
+ if (reg & EFUSE_SRC_CLK_EN)
|
|
+ write32(reg | (EFUSE_SRC_CLK_EN << CRU_WRITE_MASK),
|
|
+ CRU_BASE + CRU_CLKGATE_CON2);
|
|
+ break;
|
|
+ case PCLK:
|
|
+ /* disable efuse APB clk */
|
|
+ if (reg & EFUSE_1024_PCLK_EN)
|
|
+ write32(reg | (EFUSE_1024_PCLK_EN << CRU_WRITE_MASK),
|
|
+ CRU_BASE + CRU_CLKGATE_CON15);
|
|
+ break;
|
|
+ default:
|
|
+ return;
|
|
+ }
|
|
+}
|
|
+
|
|
+/* user mode and auto mode */
|
|
+int rk_efuse32_readregs(uint32_t addr, uint32_t length, uint32_t *buf)
|
|
+{
|
|
+ uint32_t reg0 = 0;
|
|
+ uint32_t reg1 = 0;
|
|
+
|
|
+ uint32_t efuse_base = 0;
|
|
+
|
|
+ if (addr > 31)
|
|
+ return -1;
|
|
+ if (length < 1 || length > 32)
|
|
+ return -1;
|
|
+ if (!buf)
|
|
+ return -1;
|
|
+
|
|
+ if (addr < 24) {
|
|
+ if (addr + length < 25)
|
|
+ efuse_base = EFUSE32_BASE;
|
|
+ else
|
|
+ return -1;
|
|
+ }
|
|
+ if (addr > 23) {
|
|
+ if (addr + length < 33)
|
|
+ efuse_base = EFUSE8_BASE;
|
|
+ else
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ //reg0 = enable_efuse_clk(CLK);
|
|
+ //reg1 = enable_efuse_clk(PCLK);
|
|
+
|
|
+#if EFUSE_AUTO_MODE
|
|
+ do {
|
|
+ write32(EFUSE_AUTO_RD | EFUSE_AUTO_ENABLE |
|
|
+ ((addr & EFUSE_A_MASK) << EFUSE_A_SHIFT),
|
|
+ efuse_base + REG_EFUSE_AUTO_CTRL);
|
|
+ udelay(2);
|
|
+ while (1) {
|
|
+ if (read32(efuse_base + REG_EFUSE_INT_STATUS) & 0x01)
|
|
+ break;
|
|
+ }
|
|
+ *buf = read32(efuse_base + REG_EFUSE_DOUT);
|
|
+ write32(read32(efuse_base + REG_EFUSE_AUTO_CTRL) &
|
|
+ (~EFUSE_AUTO_ENABLE), efuse_base + REG_EFUSE_AUTO_CTRL);
|
|
+ write32(0x07, efuse_base + REG_EFUSE_INT_STATUS);
|
|
+ buf++;
|
|
+ addr++;
|
|
+
|
|
+ } while (--length);
|
|
+#else
|
|
+ /* enable read in user mode */
|
|
+ write32((read32(efuse_base + REG_EFUSE_MOD) | EFUSE_RD_ENB_USER) &
|
|
+ (~EFUSE_PG_ENB_USER), efuse_base + REG_EFUSE_MOD);
|
|
+ write32(EFUSE_CSB, efuse_base + REG_EFUSE_CTRL);
|
|
+ write32(EFUSE_LOAD | EFUSE_PGENB, efuse_base + REG_EFUSE_CTRL);
|
|
+ udelay(2);
|
|
+ do {
|
|
+ write32(read32(efuse_base + REG_EFUSE_CTRL) &
|
|
+ (~(EFUSE_A_MASK << EFUSE_A_SHIFT)),
|
|
+ efuse_base + REG_EFUSE_CTRL);
|
|
+ write32(read32(efuse_base + REG_EFUSE_CTRL) |
|
|
+ ((addr & EFUSE_A_MASK) << EFUSE_A_SHIFT),
|
|
+ efuse_base + REG_EFUSE_CTRL);
|
|
+
|
|
+ udelay(2);
|
|
+ write32(read32(efuse_base + REG_EFUSE_CTRL) |
|
|
+ EFUSE_STROBE, efuse_base + REG_EFUSE_CTRL);
|
|
+ udelay(2);
|
|
+ *buf = read32(efuse_base + REG_EFUSE_DOUT);
|
|
+ write32(read32(efuse_base + REG_EFUSE_CTRL) &
|
|
+ (~EFUSE_STROBE), efuse_base + REG_EFUSE_CTRL);
|
|
+ udelay(2);
|
|
+ buf++;
|
|
+ addr++;
|
|
+ } while (--length);
|
|
+ udelay(2);
|
|
+ write32(read32(efuse_base + REG_EFUSE_CTRL) | EFUSE_CSB,
|
|
+ efuse_base + REG_EFUSE_CTRL);
|
|
+ udelay(1);
|
|
+#endif /* EFUSE_AUTO_MODE */
|
|
+
|
|
+ restore_efuse_clk(CLK, reg0);
|
|
+ restore_efuse_clk(PCLK, reg1);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*user mode and auto mode*/
|
|
+int rk_efuse32_write(uint32_t addr, uint32_t val)
|
|
+{
|
|
+ uint32_t reg0 = 0, reg1 = 0, efuse_base = 0;
|
|
+
|
|
+ if (addr > 31)
|
|
+ return -1;
|
|
+
|
|
+ if (addr < 24)
|
|
+ efuse_base = EFUSE32_BASE;
|
|
+ if (addr > 23 && addr < 32)
|
|
+ efuse_base = EFUSE8_BASE;
|
|
+
|
|
+ //reg0 = enable_efuse_clk(CLK);
|
|
+ //reg1 = enable_efuse_clk(PCLK);
|
|
+
|
|
+#if EFUSE_AUTO_MODE
|
|
+ while (val) {
|
|
+ if (val & 0x01) {
|
|
+ write32((EFUSE_AUTO_ENABLE |
|
|
+ ((addr & EFUSE_A_MASK) << EFUSE_A_SHIFT))
|
|
+ & (~EFUSE_AUTO_RD),
|
|
+ efuse_base + REG_EFUSE_AUTO_CTRL);
|
|
+ udelay(2);
|
|
+ while (1) {
|
|
+ if (read32(efuse_base + REG_EFUSE_INT_STATUS) &
|
|
+ 0x01)
|
|
+ break;
|
|
+ }
|
|
+ write32(read32(efuse_base + REG_EFUSE_AUTO_CTRL) &
|
|
+ (~EFUSE_AUTO_ENABLE),
|
|
+ efuse_base + REG_EFUSE_AUTO_CTRL);
|
|
+ write32(0x07, efuse_base + REG_EFUSE_INT_STATUS);
|
|
+ udelay(2);
|
|
+ }
|
|
+ addr += 32;
|
|
+ val = val >> 1;
|
|
+ udelay(2);
|
|
+ }
|
|
+#else
|
|
+ /* enable program in user mode */
|
|
+ write32((read32(efuse_base + REG_EFUSE_MOD) | EFUSE_PG_ENB_USER) &
|
|
+ (~EFUSE_RD_ENB_USER), efuse_base + REG_EFUSE_MOD);
|
|
+ write32(EFUSE_CSB | EFUSE_LOAD | EFUSE_PGENB,
|
|
+ efuse_base + REG_EFUSE_CTRL);
|
|
+ write32(read32(efuse_base + REG_EFUSE_CTRL) & (~EFUSE_CSB),
|
|
+ efuse_base + REG_EFUSE_CTRL);
|
|
+ write32(read32(efuse_base + REG_EFUSE_CTRL) & (~EFUSE_PGENB) &
|
|
+ (~EFUSE_LOAD), efuse_base + REG_EFUSE_CTRL);
|
|
+ udelay(2);
|
|
+
|
|
+ while (val) {
|
|
+ if (val & 0x01) {
|
|
+ write32(read32(efuse_base + REG_EFUSE_CTRL) &
|
|
+ (~(EFUSE_A_MASK << EFUSE_A_SHIFT)),
|
|
+ efuse_base + REG_EFUSE_CTRL);
|
|
+ write32(read32(efuse_base + REG_EFUSE_CTRL) |
|
|
+ ((addr & EFUSE_A_MASK) << EFUSE_A_SHIFT),
|
|
+ efuse_base + REG_EFUSE_CTRL);
|
|
+ udelay(2);
|
|
+ write32(read32(efuse_base + REG_EFUSE_CTRL) |
|
|
+ EFUSE_STROBE, efuse_base + REG_EFUSE_CTRL);
|
|
+ udelay(10);
|
|
+ write32(read32(efuse_base + REG_EFUSE_CTRL) &
|
|
+ (~EFUSE_STROBE),
|
|
+ efuse_base + REG_EFUSE_CTRL);
|
|
+ udelay(2);
|
|
+ }
|
|
+ addr += 32;
|
|
+ val = val >> 1;
|
|
+ }
|
|
+
|
|
+ udelay(2);
|
|
+ write32(read32(efuse_base + REG_EFUSE_CTRL) | EFUSE_LOAD |
|
|
+ EFUSE_PGENB, efuse_base + REG_EFUSE_CTRL);
|
|
+ write32(read32(efuse_base + REG_EFUSE_CTRL) | EFUSE_CSB,
|
|
+ efuse_base + REG_EFUSE_CTRL);
|
|
+ udelay(1);
|
|
+#endif /* EFUSE_AUTO_MODE */
|
|
+
|
|
+ restore_efuse_clk(CLK, reg0);
|
|
+ restore_efuse_clk(PCLK, reg1);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int rk_efuse32_read(uint32_t addr, uint32_t length, uint32_t *buf)
|
|
+{
|
|
+ if (!buf)
|
|
+ return -1;
|
|
+
|
|
+ if (addr > 23) {
|
|
+ if (length < 1 || length + addr > 32)
|
|
+ return -1;
|
|
+
|
|
+ memcpy(buf, efuse32_buf + addr, length * sizeof(uint32_t));
|
|
+ } else if (addr < 24) {
|
|
+ if (length < 1 || length + addr > 24)
|
|
+ return -1;
|
|
+
|
|
+ memcpy(buf, efuse32_buf + addr, length * sizeof(uint32_t));
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void mode_init(int sec)
|
|
+{
|
|
+ int reg;
|
|
+ uint32_t efuse_base = 0;
|
|
+
|
|
+ if (sec == 1)
|
|
+ efuse_base = EFUSE32_BASE;/*secure efuse addr*/
|
|
+ if (sec == 0)
|
|
+ efuse_base = EFUSE8_BASE;/*un_secure efsue addr*/
|
|
+
|
|
+#if EFUSE_AUTO_MODE
|
|
+ /* enable auto mode */
|
|
+ reg = read32(efuse_base + REG_EFUSE_MOD);
|
|
+ write32(reg & (~EFUSE_USER_MODE), efuse_base + REG_EFUSE_MOD);
|
|
+
|
|
+ /* enable finish & auto_s_access_ns_err & auto_ns_access_s_err int */
|
|
+ write32(0x07, efuse_base + REG_EFUSE_INT_CON);
|
|
+ write32((T_CSB_P_S << 16) | T_CSB_P_L,
|
|
+ efuse_base + REG_EFUSE_T_CSB_P);
|
|
+ write32((T_PGENB_P_S << 16) | T_PGENB_P_L,
|
|
+ efuse_base + REG_EFUSE_T_PGENB_P);
|
|
+ write32((T_LOAD_P_S << 16) | T_LOAD_P_L,
|
|
+ efuse_base + REG_EFUSE_T_LOAD_P);
|
|
+ write32((T_ADDR_P_S << 16) | T_ADDR_P_L,
|
|
+ efuse_base + REG_EFUSE_T_ADDR_P);
|
|
+ write32((T_STROBE_P_S << 16) | T_STROBE_P_L,
|
|
+ efuse_base + REG_EFUSE_T_STROBE_P);
|
|
+ write32((T_CSB_R_S << 16) | T_CSB_R_L,
|
|
+ efuse_base + REG_EFUSE_T_CSB_R);
|
|
+ write32((T_PGENB_R_S << 16) | T_PGENB_R_L,
|
|
+ efuse_base + REG_EFUSE_T_PGENB_R);
|
|
+ write32((T_LOAD_R_S << 16) | T_LOAD_R_L,
|
|
+ efuse_base + REG_EFUSE_T_LOAD_R);
|
|
+ write32((T_ADDR_R_S << 16) | T_ADDR_R_L,
|
|
+ efuse_base + REG_EFUSE_T_ADDR_R);
|
|
+ write32((T_STROBE_R_S << 16) | T_STROBE_R_L,
|
|
+ efuse_base + REG_EFUSE_T_STROBE_R);
|
|
+#else
|
|
+ reg = read32(efuse_base + REG_EFUSE_MOD);
|
|
+ write32(reg | EFUSE_USER_MODE, efuse_base + REG_EFUSE_MOD);
|
|
+#endif /* EFUSE_AUTO_MODE */
|
|
+}
|
|
+
|
|
+void rk_efuse_prog_en(int n)
|
|
+{
|
|
+ if (n == 1) {
|
|
+ write32(read32(GPIO2_BASE) & (~(0X1 << 3)), GPIO2_BASE);
|
|
+ write32((efuse_pwren | efuse_pwren << 16) |
|
|
+ ((0) << 7 | efuse_pwren << 16 << 1),
|
|
+ GRF_BASE + GRF_GPIO2A_IOMUX);
|
|
+ /*efuse program enable*/
|
|
+ write32((1 << 7) | (1 << 7 << 16), SGRF_BASE +
|
|
+ EFUSE_SGRF_SOC_CON5);
|
|
+ } else {
|
|
+ write32((0 << 7) | (1 << 7 << 16),
|
|
+ SGRF_BASE + EFUSE_SGRF_SOC_CON5);
|
|
+ write32(0 << 6 | efuse_pwren << 16 |
|
|
+ ((0) << 7 | efuse_pwren << 16 << 1),
|
|
+ GRF_BASE + GRF_GPIO2A_IOMUX);
|
|
+ write32(read32(GPIO2_BASE) | (0X1 << 3), GPIO2_BASE);
|
|
+ }
|
|
+}
|
|
+
|
|
+int rk_efuse_init(void)
|
|
+{
|
|
+ mode_init(1);
|
|
+ mode_init(0);
|
|
+
|
|
+ if (rk_efuse32_readregs(RK322XH_S_EFUSE_START,
|
|
+ RK322XH_S_EFUSE_WORDS,
|
|
+ efuse32_buf)) {
|
|
+ ERROR("read S-efuse failed!!!!\n");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (rk_efuse32_readregs(RK322XH_NS_EFUSE_START,
|
|
+ RK322XH_NS_EFUSE_WORDS,
|
|
+ efuse32_buf + RK322XH_NS_EFUSE_START)) {
|
|
+ ERROR("read NS-efuse failed!!!!\n");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
diff --git a/plat/rockchip/rk3328/drivers/efuse/efuse.h b/plat/rockchip/rk3328/drivers/efuse/efuse.h
|
|
new file mode 100644
|
|
index 0000000..22275c2
|
|
--- /dev/null
|
|
+++ b/plat/rockchip/rk3328/drivers/efuse/efuse.h
|
|
@@ -0,0 +1,142 @@
|
|
+/*
|
|
+ * Copyright (C) 2016, Fuzhou Rockchip Electronics Co., Ltd.
|
|
+ * All rights reserved.
|
|
+ *
|
|
+ * Redistribution and use in source and binary forms, with or without
|
|
+ * modification, are permitted provided that the following conditions are met:
|
|
+ *
|
|
+ * Redistributions of source code must retain the above copyright notice, this
|
|
+ * list of conditions and the following disclaimer.
|
|
+ *
|
|
+ * 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.
|
|
+ *
|
|
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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 EFUSE_H
|
|
+#define EFUSE_H
|
|
+
|
|
+#include <platform_def.h>
|
|
+
|
|
+/* CRU controller register */
|
|
+#define CRU_WRITE_MASK (16)
|
|
+
|
|
+#define GRF_GPIO2A_IOMUX (0x0020)
|
|
+#define EFUSE_SGRF_SOC_CON5 (0X0014)
|
|
+
|
|
+#define CRU_CLKGATE_CON2 (0x0208)
|
|
+#define CRU_CLKGATE_CON15 (0x023C)
|
|
+#define EFUSE_SRC_CLK_EN (1 << 13)
|
|
+#define EFUSE_1024_PCLK_EN (1 << 9)
|
|
+
|
|
+#define RK322XH_S_EFUSE_START 0
|
|
+#define RK322XH_S_EFUSE_WORDS 24
|
|
+#define RK322XH_NS_EFUSE_START (RK322XH_S_EFUSE_START + RK322XH_S_EFUSE_WORDS)
|
|
+#define RK322XH_NS_EFUSE_WORDS 8
|
|
+
|
|
+/* SGRF controller register */
|
|
+#define SGRF_WRITE_MASK (16)
|
|
+
|
|
+/* eFuse controller register */
|
|
+#define CRU_CLKSEL_CON5 (0x0114)
|
|
+#define REG_EFUSE_MOD (0x0000)
|
|
+#define efuse_pwren (1 << 6)
|
|
+#define EFUSE_RD_ENB_USER (1 << 6)
|
|
+#define EFUSE_PG_ENB_USER (1 << 5)
|
|
+#define EFUSE_STROBE_POL (1 << 4)
|
|
+#define EFUSE_LOAD_POL (1 << 3)
|
|
+#define EFUSE_PGENB_POL (1 << 2)
|
|
+#define EFUSE_CSB_POL (1 << 1)
|
|
+/* 0:auto mode; 1:user mode */
|
|
+#define EFUSE_USER_MODE (1 << 0)
|
|
+
|
|
+#define REG_EFUSE_RD_MASK_S (0x0004)
|
|
+#define REG_EFUSE_PG_MASK_S (0x0008)
|
|
+
|
|
+#define REG_EFUSE_RD_MASK_NS (0x000C)
|
|
+#define REG_EFUSE_PG_MASK_NS (0x0010)
|
|
+
|
|
+#define REG_EFUSE_INT_CON (0x0014)
|
|
+#define REG_EFUSE_INT_STATUS (0x0018)
|
|
+#define REG_EFUSE_USER_CTRL (0x001C)
|
|
+#define EFUSE_A_SHIFT (16)
|
|
+#define EFUSE_A_MASK (0x3FF)
|
|
+#define EFUSE_PGENB (1 << 3) /* active low */
|
|
+#define EFUSE_LOAD (1 << 2)
|
|
+#define EFUSE_STROBE (1 << 1)
|
|
+#define EFUSE_CSB (1 << 0) /* active low */
|
|
+#define REG_EFUSE_DOUT (0x0020)
|
|
+#define REG_EFUSE_AUTO_CTRL (0x0024)
|
|
+/* 0:programming mode; 1:read mode */
|
|
+#define EFUSE_AUTO_RD (1 << 1)
|
|
+#define EFUSE_AUTO_ENABLE (1 << 0)
|
|
+
|
|
+#define EFUSE_PG_ENB_MODE (0 << 1)
|
|
+
|
|
+#define REG_EFUSE_T_CSB_P (0x0028)
|
|
+#define REG_EFUSE_T_PGENB_P (0x002C)
|
|
+#define REG_EFUSE_T_LOAD_P (0x0030)
|
|
+#define REG_EFUSE_T_ADDR_P (0x0034)
|
|
+#define REG_EFUSE_T_STROBE_P (0x0038)
|
|
+#define REG_EFUSE_T_CSB_R (0x003C)
|
|
+#define REG_EFUSE_T_PGENB_R (0x0040)
|
|
+#define REG_EFUSE_T_LOAD_R (0x0044)
|
|
+#define REG_EFUSE_T_ADDR_R (0x0048)
|
|
+#define REG_EFUSE_T_STROBE_R (0x004C)
|
|
+#define REG_EFUSE_REVISION (0x0050)
|
|
+#define REG_EFUSE_CTRL REG_EFUSE_USER_CTRL
|
|
+
|
|
+#define T_CSB_P_S 1
|
|
+#define T_PGENB_P_S 1
|
|
+#define T_LOAD_P_S 1
|
|
+#define T_ADDR_P_S 1
|
|
+#define T_STROBE_P_S 2
|
|
+#define T_CSB_P_L 241
|
|
+#define T_PGENB_P_L 241
|
|
+#define T_LOAD_P_L 241
|
|
+#define T_ADDR_P_L 241
|
|
+#define T_STROBE_P_L 240
|
|
+#define T_CSB_R_S 1
|
|
+#define T_PGENB_R_S 1
|
|
+#define T_LOAD_R_S 1
|
|
+#define T_ADDR_R_S 1
|
|
+#define T_STROBE_R_S 2
|
|
+#define T_CSB_R_L 4
|
|
+#define T_PGENB_R_L 4
|
|
+#define T_LOAD_R_L 4
|
|
+#define T_ADDR_R_L 4
|
|
+#define T_STROBE_R_L 3
|
|
+
|
|
+/*
|
|
+ * readregs function is real-time read, from the efuse hardware.
|
|
+ * read function is not real-time read, read the value stored in
|
|
+ * memory when machine starting up.
|
|
+ */
|
|
+int rk_efuse8_readregs(uint32_t addr, uint32_t length, uint8_t *buf);
|
|
+int rk_efuse8_write(uint32_t addr, uint8_t val);
|
|
+
|
|
+int rk_efuse32_readregs(uint32_t addr, uint32_t length, uint32_t *buf);
|
|
+int rk_efuse32_write(uint32_t addr, uint32_t val);
|
|
+int rk_efuse32_read(uint32_t addr, uint32_t length, uint32_t *buf);
|
|
+
|
|
+int enable_efuse_clk();
|
|
+
|
|
+void mode_init(int sec);
|
|
+void rk_efuse_prog_en(int n);
|
|
+
|
|
+int rk_efuse_init(void);
|
|
+
|
|
+#endif /* RK_EFUSE_H */
|
|
+
|
|
diff --git a/plat/rockchip/rk3328/drivers/soc/soc.c b/plat/rockchip/rk3328/drivers/soc/soc.c
|
|
index 306308f..48a001c 100644
|
|
--- a/plat/rockchip/rk3328/drivers/soc/soc.c
|
|
+++ b/plat/rockchip/rk3328/drivers/soc/soc.c
|
|
@@ -16,6 +16,7 @@
|
|
#include <plat_private.h>
|
|
#include <rk3328_def.h>
|
|
#include <soc.h>
|
|
+#include <efuse.h>
|
|
|
|
/* Table of regions to map using the MMU. */
|
|
const mmap_region_t plat_rk_mmap[] = {
|
|
@@ -153,6 +154,11 @@ void plat_rockchip_soc_init(void)
|
|
secure_timer_init();
|
|
sgrf_init();
|
|
|
|
+ mode_init(1);
|
|
+ mode_init(0);
|
|
+
|
|
+ enable_efuse_clk();
|
|
+
|
|
NOTICE("BL31:Rockchip release version: v%d.%d\n",
|
|
MAJOR_VERSION, MINOR_VERSION);
|
|
}
|
|
diff --git a/plat/rockchip/rk3328/platform.mk b/plat/rockchip/rk3328/platform.mk
|
|
index 5b4766d..4ff5a7a 100644
|
|
--- a/plat/rockchip/rk3328/platform.mk
|
|
+++ b/plat/rockchip/rk3328/platform.mk
|
|
@@ -22,6 +22,7 @@ PLAT_INCLUDES := -Idrivers/arm/gic/common/ \
|
|
-I${RK_PLAT_SOC}/ \
|
|
-I${RK_PLAT_SOC}/drivers/pmu/ \
|
|
-I${RK_PLAT_SOC}/drivers/soc/ \
|
|
+ -I${RK_PLAT_SOC}/drivers/efuse/ \
|
|
-I${RK_PLAT_SOC}/include/
|
|
|
|
RK_GIC_SOURCES := ${GICV2_SOURCES} \
|
|
@@ -54,7 +55,8 @@ BL31_SOURCES += ${RK_GIC_SOURCES} \
|
|
${RK_PLAT_COMMON}/plat_topology.c \
|
|
${RK_PLAT_COMMON}/aarch64/platform_common.c \
|
|
${RK_PLAT_SOC}/drivers/pmu/pmu.c \
|
|
- ${RK_PLAT_SOC}/drivers/soc/soc.c
|
|
+ ${RK_PLAT_SOC}/drivers/soc/soc.c \
|
|
+ ${RK_PLAT_SOC}/drivers/efuse/efuse.c
|
|
|
|
ifdef PLAT_RK_SECURE_DDR_MINILOADER
|
|
BL31_SOURCES += ${RK_PLAT_COMMON}/drivers/parameter/ddr_parameter.c
|
|
--
|
|
2.30.2
|
|
|