[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