
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,
- }, {} };