
On 2023/2/16 07:48, Jonas Karlman wrote:
Refactor the driver to use driver data and ops to simplify handling of SoCs that require a unique read op.
Move handling of the aligned bounce buffer to main read op in order to keep the SoC unique read op simple.
Signed-off-by: Jonas Karlman jonas@kwiboo.se
Reviewed-by: Kever Yang kever.yang@rock-chips.com
Thanks, - Kever
drivers/misc/rockchip-efuse.c | 160 ++++++++++++++++++---------------- 1 file changed, 85 insertions(+), 75 deletions(-)
diff --git a/drivers/misc/rockchip-efuse.c b/drivers/misc/rockchip-efuse.c index 083ee65e0ad7..864c9c15bbe5 100644 --- a/drivers/misc/rockchip-efuse.c +++ b/drivers/misc/rockchip-efuse.c @@ -13,50 +13,40 @@ #include <dm.h> #include <linux/bitops.h> #include <linux/delay.h> +#include <malloc.h> #include <misc.h>
-#define RK3399_A_SHIFT 16 -#define RK3399_A_MASK 0x3ff -#define RK3399_NFUSES 32 -#define RK3399_BYTES_PER_FUSE 4 -#define RK3399_STROBSFTSEL BIT(9) -#define RK3399_RSB BIT(7) -#define RK3399_PD BIT(5) -#define RK3399_PGENB BIT(3) -#define RK3399_LOAD BIT(2) -#define RK3399_STROBE BIT(1) -#define RK3399_CSB BIT(0)
-struct rockchip_efuse_regs {
- u32 ctrl; /* 0x00 efuse control register */
- u32 dout; /* 0x04 efuse data out register */
- u32 rf; /* 0x08 efuse redundancy bit used register */
- u32 _rsvd0;
- u32 jtag_pass; /* 0x10 JTAG password */
- u32 strobe_finish_ctrl;
/* 0x14 efuse strobe finish control register */
-}; +#define EFUSE_CTRL 0x0000 +#define RK3399_A_SHIFT 16 +#define RK3399_A_MASK GENMASK(25, 16) +#define RK3399_ADDR(n) ((n) << RK3399_A_SHIFT) +#define RK3399_STROBSFTSEL BIT(9) +#define RK3399_RSB BIT(7) +#define RK3399_PD BIT(5) +#define RK3399_PGENB BIT(3) +#define RK3399_LOAD BIT(2) +#define RK3399_STROBE BIT(1) +#define RK3399_CSB BIT(0) +#define EFUSE_DOUT 0x0004
struct rockchip_efuse_plat { void __iomem *base;
- struct clk *clk;
+};
+struct rockchip_efuse_data {
int (*read)(struct udevice *dev, int offset, void *buf, int size);
int size;
int block_size; };
#if defined(DEBUG)
-static int dump_efuses(struct cmd_tbl *cmdtp, int flag,
int argc, char *const argv[])
+static int dump_efuse(struct cmd_tbl *cmdtp, int flag,
{int argc, char *const argv[])
- /*
* N.B.: This function is tailored towards the RK3399 and assumes that
* there's always 32 fuses x 32 bits (i.e. 128 bytes of data) to
* be read.
*/
- struct udevice *dev;
- u8 fuses[128];
- int ret;
- u8 data[4];
- int ret, i;
- /* retrieve the device */ ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(rockchip_efuse), &dev); if (ret) {
@@ -64,21 +54,20 @@ static int dump_efuses(struct cmd_tbl *cmdtp, int flag, return 0; }
- ret = misc_read(dev, 0, &fuses, sizeof(fuses));
- if (ret < 0) {
printf("%s: misc_read failed\n", __func__);
return 0;
- }
- for (i = 0; true; i += sizeof(data)) {
ret = misc_read(dev, i, &data, sizeof(data));
if (ret < 0)
return 0;
- printf("efuse-contents:\n");
- print_buffer(0, fuses, 1, 128, 16);
print_buffer(i, data, sizeof(data), 1, 1);
}
return 0; }
U_BOOT_CMD(
- rk3399_dump_efuses, 1, 1, dump_efuses,
- "Dump the content of the efuses",
- dump_efuse, 1, 1, dump_efuse,
- "Dump the content of the efuse", "" ); #endif
@@ -86,43 +75,25 @@ U_BOOT_CMD( static int rockchip_rk3399_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;
- u32 out_value;
- u8 bytes[RK3399_NFUSES * RK3399_BYTES_PER_FUSE];
- int i = 0;
- u32 addr;
- addr_start = offset / RK3399_BYTES_PER_FUSE;
- addr_offset = offset % RK3399_BYTES_PER_FUSE;
- addr_end = DIV_ROUND_UP(offset + size, RK3399_BYTES_PER_FUSE);
- /* cap to the size of the efuse block */
- if (addr_end > RK3399_NFUSES)
addr_end = RK3399_NFUSES;
struct rockchip_efuse_plat *efuse = dev_get_plat(dev);
u32 *buffer = buf;
/* Switch to array read mode */ writel(RK3399_LOAD | RK3399_PGENB | RK3399_STROBSFTSEL | RK3399_RSB,
&efuse->ctrl);
udelay(1);efuse->base + EFUSE_CTRL);
- for (addr = addr_start; addr < addr_end; addr++) {
setbits_le32(&efuse->ctrl,
RK3399_STROBE | (addr << RK3399_A_SHIFT));
- while (size--) {
setbits_le32(efuse->base + EFUSE_CTRL,
udelay(1);RK3399_STROBE | RK3399_ADDR(offset++));
out_value = readl(&efuse->dout);
clrbits_le32(&efuse->ctrl, RK3399_STROBE);
*buffer++ = readl(efuse->base + EFUSE_DOUT);
udelay(1);clrbits_le32(efuse->base + EFUSE_CTRL, RK3399_STROBE);
memcpy(&bytes[i], &out_value, RK3399_BYTES_PER_FUSE);
i += RK3399_BYTES_PER_FUSE;
}
/* Switch to standby mode */
writel(RK3399_PD | RK3399_CSB, &efuse->ctrl);
memcpy(buf, bytes + addr_offset, size);
/* Switch to power-down mode */
writel(RK3399_PD | RK3399_CSB, efuse->base + EFUSE_CTRL);
return 0; }
@@ -130,7 +101,36 @@ static int rockchip_rk3399_efuse_read(struct udevice *dev, int offset, static int rockchip_efuse_read(struct udevice *dev, int offset, void *buf, int size) {
- return rockchip_rk3399_efuse_read(dev, offset, buf, size);
const struct rockchip_efuse_data *data =
(void *)dev_get_driver_data(dev);
u32 block_start, block_end, block_offset, blocks;
u8 *buffer;
int ret;
if (offset < 0 || !buf || size <= 0 || offset + size > data->size)
return -EINVAL;
if (!data->read)
return -ENOSYS;
if (data->block_size <= 1)
return data->read(dev, offset, buf, size);
block_start = offset / data->block_size;
block_offset = offset % data->block_size;
block_end = DIV_ROUND_UP(offset + size, data->block_size);
blocks = block_end - block_start;
buffer = calloc(blocks, data->block_size);
if (!buffer)
return -ENOMEM;
ret = data->read(dev, block_start, buffer, blocks);
if (!ret)
memcpy(buf, buffer + block_offset, size);
free(buffer);
return ret; }
static const struct misc_ops rockchip_efuse_ops = {
@@ -142,11 +142,21 @@ static int rockchip_efuse_of_to_plat(struct udevice *dev) struct rockchip_efuse_plat *plat = dev_get_plat(dev);
plat->base = dev_read_addr_ptr(dev);
- return 0; }
+static const struct rockchip_efuse_data rk3399_data = {
- .read = rockchip_rk3399_efuse_read,
- .size = 0x80,
- .block_size = 4,
+};
- static const struct udevice_id rockchip_efuse_ids[] = {
- { .compatible = "rockchip,rk3399-efuse" },
- {
.compatible = "rockchip,rk3399-efuse",
.data = (ulong)&rk3399_data,
- }, {} };
@@ -155,6 +165,6 @@ U_BOOT_DRIVER(rockchip_efuse) = { .id = UCLASS_MISC, .of_match = rockchip_efuse_ids, .of_to_plat = rockchip_efuse_of_to_plat,
- .plat_auto = sizeof(struct rockchip_efuse_plat),
- .plat_auto = sizeof(struct rockchip_efuse_plat), .ops = &rockchip_efuse_ops, };