[PATCH 05/11] rockchip: efuse: Refactor to use driver data and ops
Kever Yang
kever.yang at rock-chips.com
Wed Feb 22 09:55:45 CET 2023
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 at kwiboo.se>
Reviewed-by: Kever Yang <kever.yang at 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);
> + efuse->base + EFUSE_CTRL);
> udelay(1);
> - 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,
> + RK3399_STROBE | RK3399_ADDR(offset++));
> udelay(1);
> - out_value = readl(&efuse->dout);
> - clrbits_le32(&efuse->ctrl, RK3399_STROBE);
> + *buffer++ = readl(efuse->base + EFUSE_DOUT);
> + clrbits_le32(efuse->base + EFUSE_CTRL, RK3399_STROBE);
> udelay(1);
> -
> - 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,
> };
More information about the U-Boot
mailing list