mirror of
https://github.com/libretro/Lakka-LibreELEC.git
synced 2024-11-24 21:56:19 +00:00
118 lines
3.4 KiB
Diff
118 lines
3.4 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Joseph Chen <chenjh@rock-chips.com>
|
|
Date: Thu, 2 Aug 2018 20:33:16 +0800
|
|
Subject: [PATCH 2/6] rockchip: efuse: add support for RK3328 non-secure efuse
|
|
block
|
|
|
|
Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
|
|
---
|
|
drivers/misc/rockchip-efuse.c | 67 +++++++++++++++++++++++++++++++++++
|
|
1 file changed, 67 insertions(+)
|
|
|
|
diff --git a/drivers/misc/rockchip-efuse.c b/drivers/misc/rockchip-efuse.c
|
|
index 4c9239f7ba..c75405bfcf 100644
|
|
--- a/drivers/misc/rockchip-efuse.c
|
|
+++ b/drivers/misc/rockchip-efuse.c
|
|
@@ -13,6 +13,7 @@
|
|
#include <dm.h>
|
|
#include <linux/bitops.h>
|
|
#include <linux/delay.h>
|
|
+#include <malloc.h>
|
|
#include <misc.h>
|
|
|
|
#define RK3399_A_SHIFT 16
|
|
@@ -36,6 +37,13 @@
|
|
#define RK3288_STROBE BIT(1)
|
|
#define RK3288_CSB BIT(0)
|
|
|
|
+#define RK3328_INT_STATUS 0x0018
|
|
+#define RK3328_DOUT 0x0020
|
|
+#define RK3328_AUTO_CTRL 0x0024
|
|
+#define RK3328_INT_FINISH BIT(0)
|
|
+#define RK3328_AUTO_ENB BIT(0)
|
|
+#define RK3328_AUTO_RD BIT(1)
|
|
+
|
|
typedef int (*EFUSE_READ)(struct udevice *dev, int offset, void *buf, int size);
|
|
|
|
struct rockchip_efuse_regs {
|
|
@@ -46,6 +54,10 @@ struct rockchip_efuse_regs {
|
|
u32 jtag_pass; /* 0x10 JTAG password */
|
|
u32 strobe_finish_ctrl;
|
|
/* 0x14 efuse strobe finish control register */
|
|
+ u32 int_status;/* 0x18 */
|
|
+ u32 reserved; /* 0x1c */
|
|
+ u32 dout2; /* 0x20 */
|
|
+ u32 auto_ctrl; /* 0x24 */
|
|
};
|
|
|
|
struct rockchip_efuse_plat {
|
|
@@ -181,6 +193,57 @@ static int rockchip_rk3288_efuse_read(struct udevice *dev, int offset,
|
|
return 0;
|
|
}
|
|
|
|
+static int rockchip_rk3328_efuse_read(struct udevice *dev, int offset,
|
|
+ void *buf, int size)
|
|
+{
|
|
+ struct rockchip_efuse_plat *plat = dev_get_plat(dev);
|
|
+ struct rockchip_efuse_regs *efuse =
|
|
+ (struct rockchip_efuse_regs *)plat->base;
|
|
+ unsigned int addr_start, addr_end, addr_offset, addr_len;
|
|
+ u32 out_value, status;
|
|
+ u8 *buffer;
|
|
+ int ret = 0, i = 0, j = 0;
|
|
+
|
|
+ /* Max non-secure Byte */
|
|
+ if (size > 32)
|
|
+ size = 32;
|
|
+
|
|
+ /* 128 Byte efuse, 96 Byte for secure, 32 Byte for non-secure */
|
|
+ offset += 96;
|
|
+ addr_start = rounddown(offset, RK3399_BYTES_PER_FUSE) /
|
|
+ RK3399_BYTES_PER_FUSE;
|
|
+ addr_end = roundup(offset + size, RK3399_BYTES_PER_FUSE) /
|
|
+ RK3399_BYTES_PER_FUSE;
|
|
+ addr_offset = offset % RK3399_BYTES_PER_FUSE;
|
|
+ addr_len = addr_end - addr_start;
|
|
+
|
|
+ buffer = calloc(1, sizeof(*buffer) * addr_len * RK3399_BYTES_PER_FUSE);
|
|
+ if (!buffer)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ for (j = 0; j < addr_len; j++) {
|
|
+ writel(RK3328_AUTO_RD | RK3328_AUTO_ENB |
|
|
+ ((addr_start++ & RK3399_A_MASK) << RK3399_A_SHIFT),
|
|
+ &efuse->auto_ctrl);
|
|
+ udelay(5);
|
|
+ status = readl(&efuse->int_status);
|
|
+ if (!(status & RK3328_INT_FINISH)) {
|
|
+ ret = -EIO;
|
|
+ goto err;
|
|
+ }
|
|
+ out_value = readl(&efuse->dout2);
|
|
+ writel(RK3328_INT_FINISH, &efuse->int_status);
|
|
+
|
|
+ memcpy(&buffer[i], &out_value, RK3399_BYTES_PER_FUSE);
|
|
+ i += RK3399_BYTES_PER_FUSE;
|
|
+ }
|
|
+ memcpy(buf, buffer + addr_offset, size);
|
|
+err:
|
|
+ free(buffer);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static int rockchip_efuse_read(struct udevice *dev, int offset,
|
|
void *buf, int size)
|
|
{
|
|
@@ -231,6 +294,10 @@ static const struct udevice_id rockchip_efuse_ids[] = {
|
|
.compatible = "rockchip,rk3368-efuse",
|
|
.data = (ulong)&rockchip_rk3288_efuse_read,
|
|
},
|
|
+ {
|
|
+ .compatible = "rockchip,rk3328-efuse",
|
|
+ .data = (ulong)&rockchip_rk3328_efuse_read,
|
|
+ },
|
|
{
|
|
.compatible = "rockchip,rk3399-efuse",
|
|
.data = (ulong)&rockchip_rk3399_efuse_read,
|