Message ID | 20230215234853.2624074-3-jonas@kwiboo.se |
---|---|
State | Superseded |
Delegated to: | Kever Yang |
Headers | show |
Series | rockchip: Add efuse and otp support to more SoCs | expand |
On 2023/2/16 07:48, Jonas Karlman wrote: > Add support for rk3568 compatible. > > Handle allocation of an aligned bounce buffer in 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-otp.c | 67 ++++++++++++++++++++++++++++++++++++- > 1 file changed, 66 insertions(+), 1 deletion(-) > > diff --git a/drivers/misc/rockchip-otp.c b/drivers/misc/rockchip-otp.c > index a6df0834ebbc..243c173cdb18 100644 > --- a/drivers/misc/rockchip-otp.c > +++ b/drivers/misc/rockchip-otp.c > @@ -9,6 +9,7 @@ > #include <linux/bitops.h> > #include <linux/delay.h> > #include <linux/iopoll.h> > +#include <malloc.h> > #include <misc.h> > > /* OTP Register Offsets */ > @@ -54,6 +55,7 @@ struct rockchip_otp_plat { > struct rockchip_otp_data { > int (*read)(struct udevice *dev, int offset, void *buf, int size); > int size; > + int block_size; > }; > > static int rockchip_otp_poll_timeout(struct rockchip_otp_plat *otp, u32 flag) > @@ -124,11 +126,47 @@ read_end: > return ret; > } > > +static int rockchip_rk3568_otp_read(struct udevice *dev, int offset, > + void *buf, int size) > +{ > + struct rockchip_otp_plat *otp = dev_get_plat(dev); > + u16 *buffer = buf; > + int ret; > + > + ret = rockchip_otp_ecc_enable(otp, false); > + if (ret) > + return ret; > + > + writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); > + udelay(5); > + > + while (size--) { > + writel(offset++ | OTPC_USER_ADDR_MASK, > + otp->base + OTPC_USER_ADDR); > + writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK, > + otp->base + OTPC_USER_ENABLE); > + > + ret = rockchip_otp_poll_timeout(otp, OTPC_USER_DONE); > + if (ret) > + goto read_end; > + > + *buffer++ = readw(otp->base + OTPC_USER_Q); > + } > + > +read_end: > + writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); > + > + return ret; > +} > + > static int rockchip_otp_read(struct udevice *dev, int offset, > void *buf, int size) > { > const struct rockchip_otp_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; > @@ -136,7 +174,24 @@ static int rockchip_otp_read(struct udevice *dev, int offset, > if (!data->read) > return -ENOSYS; > > - return data->read(dev, offset, buf, size); > + 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_otp_ops = { > @@ -157,6 +212,12 @@ static const struct rockchip_otp_data px30_data = { > .size = 0x40, > }; > > +static const struct rockchip_otp_data rk3568_data = { > + .read = rockchip_rk3568_otp_read, > + .size = 0x80, > + .block_size = 2, > +}; > + > static const struct udevice_id rockchip_otp_ids[] = { > { > .compatible = "rockchip,px30-otp", > @@ -166,6 +227,10 @@ static const struct udevice_id rockchip_otp_ids[] = { > .compatible = "rockchip,rk3308-otp", > .data = (ulong)&px30_data, > }, > + { > + .compatible = "rockchip,rk3568-otp", > + .data = (ulong)&rk3568_data, > + }, > {} > }; >
diff --git a/drivers/misc/rockchip-otp.c b/drivers/misc/rockchip-otp.c index a6df0834ebbc..243c173cdb18 100644 --- a/drivers/misc/rockchip-otp.c +++ b/drivers/misc/rockchip-otp.c @@ -9,6 +9,7 @@ #include <linux/bitops.h> #include <linux/delay.h> #include <linux/iopoll.h> +#include <malloc.h> #include <misc.h> /* OTP Register Offsets */ @@ -54,6 +55,7 @@ struct rockchip_otp_plat { struct rockchip_otp_data { int (*read)(struct udevice *dev, int offset, void *buf, int size); int size; + int block_size; }; static int rockchip_otp_poll_timeout(struct rockchip_otp_plat *otp, u32 flag) @@ -124,11 +126,47 @@ read_end: return ret; } +static int rockchip_rk3568_otp_read(struct udevice *dev, int offset, + void *buf, int size) +{ + struct rockchip_otp_plat *otp = dev_get_plat(dev); + u16 *buffer = buf; + int ret; + + ret = rockchip_otp_ecc_enable(otp, false); + if (ret) + return ret; + + writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); + udelay(5); + + while (size--) { + writel(offset++ | OTPC_USER_ADDR_MASK, + otp->base + OTPC_USER_ADDR); + writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK, + otp->base + OTPC_USER_ENABLE); + + ret = rockchip_otp_poll_timeout(otp, OTPC_USER_DONE); + if (ret) + goto read_end; + + *buffer++ = readw(otp->base + OTPC_USER_Q); + } + +read_end: + writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); + + return ret; +} + static int rockchip_otp_read(struct udevice *dev, int offset, void *buf, int size) { const struct rockchip_otp_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; @@ -136,7 +174,24 @@ static int rockchip_otp_read(struct udevice *dev, int offset, if (!data->read) return -ENOSYS; - return data->read(dev, offset, buf, size); + 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_otp_ops = { @@ -157,6 +212,12 @@ static const struct rockchip_otp_data px30_data = { .size = 0x40, }; +static const struct rockchip_otp_data rk3568_data = { + .read = rockchip_rk3568_otp_read, + .size = 0x80, + .block_size = 2, +}; + static const struct udevice_id rockchip_otp_ids[] = { { .compatible = "rockchip,px30-otp", @@ -166,6 +227,10 @@ static const struct udevice_id rockchip_otp_ids[] = { .compatible = "rockchip,rk3308-otp", .data = (ulong)&px30_data, }, + { + .compatible = "rockchip,rk3568-otp", + .data = (ulong)&rk3568_data, + }, {} };
Add support for rk3568 compatible. Handle allocation of an aligned bounce buffer in main read op in order to keep the SoC unique read op simple. Signed-off-by: Jonas Karlman <jonas@kwiboo.se> --- drivers/misc/rockchip-otp.c | 67 ++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-)