nvmem: rockchip-otp: Add support for RK3588

Add support for the OTP memory device found on the Rockchip RK3588 SoC.

While here, remove the unnecessary 'void *' casts in the OF device ID
table.

Co-developed-by: Finley Xiao <finley.xiao@rock-chips.com>
Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Tested-by: Vincent Legoll <vincent.legoll@gmail.com>
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Message-ID: <20230611140330.154222-14-srinivas.kandagatla@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Cristian Ciocaltea 2023-06-11 15:03:17 +01:00 committed by Greg Kroah-Hartman
parent 912517345b
commit 8ab099fafb
1 changed files with 76 additions and 2 deletions

View File

@ -54,6 +54,19 @@
#define OTPC_TIMEOUT 10000
/* RK3588 Register */
#define RK3588_OTPC_AUTO_CTRL 0x04
#define RK3588_OTPC_AUTO_EN 0x08
#define RK3588_OTPC_INT_ST 0x84
#define RK3588_OTPC_DOUT0 0x20
#define RK3588_NO_SECURE_OFFSET 0x300
#define RK3588_NBYTES 4
#define RK3588_BURST_NUM 1
#define RK3588_BURST_SHIFT 8
#define RK3588_ADDR_SHIFT 16
#define RK3588_AUTO_EN BIT(0)
#define RK3588_RD_DONE BIT(1)
struct rockchip_data {
int size;
const char * const *clks;
@ -171,6 +184,52 @@ read_end:
return ret;
}
static int rk3588_otp_read(void *context, unsigned int offset,
void *val, size_t bytes)
{
struct rockchip_otp *otp = context;
unsigned int addr_start, addr_end, addr_len;
int ret, i = 0;
u32 data;
u8 *buf;
addr_start = round_down(offset, RK3588_NBYTES) / RK3588_NBYTES;
addr_end = round_up(offset + bytes, RK3588_NBYTES) / RK3588_NBYTES;
addr_len = addr_end - addr_start;
addr_start += RK3588_NO_SECURE_OFFSET;
buf = kzalloc(array_size(addr_len, RK3588_NBYTES), GFP_KERNEL);
if (!buf)
return -ENOMEM;
while (addr_len--) {
writel((addr_start << RK3588_ADDR_SHIFT) |
(RK3588_BURST_NUM << RK3588_BURST_SHIFT),
otp->base + RK3588_OTPC_AUTO_CTRL);
writel(RK3588_AUTO_EN, otp->base + RK3588_OTPC_AUTO_EN);
ret = rockchip_otp_wait_status(otp, RK3588_OTPC_INT_ST,
RK3588_RD_DONE);
if (ret < 0) {
dev_err(otp->dev, "timeout during read setup\n");
goto read_end;
}
data = readl(otp->base + RK3588_OTPC_DOUT0);
memcpy(&buf[i], &data, RK3588_NBYTES);
i += RK3588_NBYTES;
addr_start++;
}
memcpy(val, buf + offset % RK3588_NBYTES, bytes);
read_end:
kfree(buf);
return ret;
}
static int rockchip_otp_read(void *context, unsigned int offset,
void *val, size_t bytes)
{
@ -213,14 +272,29 @@ static const struct rockchip_data px30_data = {
.reg_read = px30_otp_read,
};
static const char * const rk3588_otp_clocks[] = {
"otp", "apb_pclk", "phy", "arb",
};
static const struct rockchip_data rk3588_data = {
.size = 0x400,
.clks = rk3588_otp_clocks,
.num_clks = ARRAY_SIZE(rk3588_otp_clocks),
.reg_read = rk3588_otp_read,
};
static const struct of_device_id rockchip_otp_match[] = {
{
.compatible = "rockchip,px30-otp",
.data = (void *)&px30_data,
.data = &px30_data,
},
{
.compatible = "rockchip,rk3308-otp",
.data = (void *)&px30_data,
.data = &px30_data,
},
{
.compatible = "rockchip,rk3588-otp",
.data = &rk3588_data,
},
{ /* sentinel */ },
};