1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd 4 */ 5 6 #include <common.h> 7 #include <asm/io.h> 8 #include <command.h> 9 #include <dm.h> 10 #include <linux/bitops.h> 11 #include <linux/delay.h> 12 #include <linux/iopoll.h> 13 #include <misc.h> 14 #include <rockchip-otp.h> 15 16 struct otp_data { 17 int (*init)(struct udevice *dev); 18 int (*read)(struct udevice *dev, int offset, void *buf, int size); 19 }; 20 21 static int rockchip_otp_wait_status(struct rockchip_otp_platdata *otp, 22 u32 flag) 23 { 24 int delay = OTPC_TIMEOUT; 25 26 while (!(readl(otp->base + OTPC_INT_STATUS) & flag)) { 27 udelay(1); 28 delay--; 29 if (delay <= 0) { 30 printf("%s: wait init status timeout\n", __func__); 31 return -ETIMEDOUT; 32 } 33 } 34 35 /* clean int status */ 36 writel(flag, otp->base + OTPC_INT_STATUS); 37 38 return 0; 39 } 40 41 static int rockchip_otp_ecc_enable(struct rockchip_otp_platdata *otp, 42 bool enable) 43 { 44 int ret = 0; 45 46 writel(SBPI_DAP_ADDR_MASK | (SBPI_DAP_ADDR << SBPI_DAP_ADDR_SHIFT), 47 otp->base + OTPC_SBPI_CTRL); 48 49 writel(SBPI_CMD_VALID_MASK | 0x1, otp->base + OTPC_SBPI_CMD_VALID_PRE); 50 writel(SBPI_DAP_CMD_WRF | SBPI_DAP_REG_ECC, 51 otp->base + OTPC_SBPI_CMD0_OFFSET); 52 if (enable) 53 writel(SBPI_ECC_ENABLE, otp->base + OTPC_SBPI_CMD1_OFFSET); 54 else 55 writel(SBPI_ECC_DISABLE, otp->base + OTPC_SBPI_CMD1_OFFSET); 56 57 writel(SBPI_ENABLE_MASK | SBPI_ENABLE, otp->base + OTPC_SBPI_CTRL); 58 59 ret = rockchip_otp_wait_status(otp, OTPC_SBPI_DONE); 60 if (ret < 0) 61 printf("%s timeout during ecc_enable\n", __func__); 62 63 return ret; 64 } 65 66 static int rockchip_px30_otp_read(struct udevice *dev, int offset, 67 void *buf, int size) 68 { 69 struct rockchip_otp_platdata *otp = dev_get_platdata(dev); 70 u8 *buffer = buf; 71 int ret = 0; 72 73 ret = rockchip_otp_ecc_enable(otp, false); 74 if (ret < 0) { 75 printf("%s rockchip_otp_ecc_enable err\n", __func__); 76 return ret; 77 } 78 79 writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); 80 udelay(5); 81 while (size--) { 82 writel(offset++ | OTPC_USER_ADDR_MASK, 83 otp->base + OTPC_USER_ADDR); 84 writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK, 85 otp->base + OTPC_USER_ENABLE); 86 ret = rockchip_otp_wait_status(otp, OTPC_USER_DONE); 87 if (ret < 0) { 88 printf("%s timeout during read setup\n", __func__); 89 goto read_end; 90 } 91 *buffer++ = readb(otp->base + OTPC_USER_Q); 92 } 93 94 read_end: 95 writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); 96 97 return ret; 98 } 99 100 static int rockchip_rk3568_otp_read(struct udevice *dev, int offset, void *buf, 101 int size) 102 { 103 struct rockchip_otp_platdata *otp = dev_get_platdata(dev); 104 unsigned int addr_start, addr_end, addr_offset, addr_len; 105 u32 out_value; 106 u8 *buffer; 107 int ret = 0, i = 0; 108 109 addr_start = rounddown(offset, RK3568_NBYTES) / RK3568_NBYTES; 110 addr_end = roundup(offset + size, RK3568_NBYTES) / RK3568_NBYTES; 111 addr_offset = offset % RK3568_NBYTES; 112 addr_len = addr_end - addr_start; 113 114 buffer = calloc(1, sizeof(*buffer) * addr_len * RK3568_NBYTES); 115 if (!buffer) 116 return -ENOMEM; 117 118 ret = rockchip_otp_ecc_enable(otp, false); 119 if (ret < 0) { 120 printf("%s rockchip_otp_ecc_enable err\n", __func__); 121 return ret; 122 } 123 124 writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); 125 udelay(5); 126 while (addr_len--) { 127 writel(addr_start++ | OTPC_USER_ADDR_MASK, 128 otp->base + OTPC_USER_ADDR); 129 writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK, 130 otp->base + OTPC_USER_ENABLE); 131 ret = rockchip_otp_wait_status(otp, OTPC_USER_DONE); 132 if (ret < 0) { 133 printf("%s timeout during read setup\n", __func__); 134 goto read_end; 135 } 136 out_value = readl(otp->base + OTPC_USER_Q); 137 memcpy(&buffer[i], &out_value, RK3568_NBYTES); 138 i += RK3568_NBYTES; 139 } 140 141 memcpy(buf, buffer + addr_offset, size); 142 143 read_end: 144 writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); 145 146 kfree(buffer); 147 148 return ret; 149 } 150 151 static int rockchip_rv1126_otp_init(struct udevice *dev) 152 { 153 struct rockchip_otp_platdata *otp = dev_get_platdata(dev); 154 u32 status = 0; 155 int ret; 156 157 writel(0x0, otp->base + RV1126_OTP_NVM_CEB); 158 ret = readl_poll_timeout(otp->base + RV1126_OTP_NVM_ST, status, 159 status & 0x1, OTPC_TIMEOUT); 160 if (ret < 0) { 161 printf("%s timeout during set ceb\n", __func__); 162 return ret; 163 } 164 165 writel(0x1, otp->base + RV1126_OTP_NVM_RSTB); 166 ret = readl_poll_timeout(otp->base + RV1126_OTP_NVM_ST, status, 167 status & 0x4, OTPC_TIMEOUT); 168 if (ret < 0) { 169 printf("%s timeout during set rstb\n", __func__); 170 return ret; 171 } 172 173 return 0; 174 } 175 176 static int rockchip_rv1126_otp_read(struct udevice *dev, int offset, void *buf, 177 int size) 178 { 179 struct rockchip_otp_platdata *otp = dev_get_platdata(dev); 180 u32 status = 0; 181 u8 *buffer = buf; 182 int ret = 0; 183 184 while (size--) { 185 writel(offset++, otp->base + RV1126_OTP_NVM_RADDR); 186 writel(0x1, otp->base + RV1126_OTP_NVM_RSTART); 187 ret = readl_poll_timeout(otp->base + RV1126_OTP_READ_ST, 188 status, status == 0, OTPC_TIMEOUT); 189 if (ret < 0) { 190 printf("%s timeout during read setup\n", __func__); 191 return ret; 192 } 193 194 *buffer++ = readb(otp->base + RV1126_OTP_NVM_RDATA); 195 } 196 197 return 0; 198 } 199 200 static int rockchip_otp_read(struct udevice *dev, int offset, 201 void *buf, int size) 202 { 203 struct otp_data *data; 204 205 data = (struct otp_data *)dev_get_driver_data(dev); 206 if (!data) 207 return -ENOSYS; 208 209 return data->read(dev, offset, buf, size); 210 } 211 212 static const struct misc_ops rockchip_otp_ops = { 213 .read = rockchip_otp_read, 214 }; 215 216 static int rockchip_otp_ofdata_to_platdata(struct udevice *dev) 217 { 218 struct rockchip_otp_platdata *otp = dev_get_platdata(dev); 219 220 otp->base = dev_read_addr_ptr(dev); 221 222 return 0; 223 } 224 225 static int rockchip_otp_probe(struct udevice *dev) 226 { 227 struct otp_data *data; 228 229 data = (struct otp_data *)dev_get_driver_data(dev); 230 if (!data) 231 return -EINVAL; 232 233 if (data->init) 234 return data->init(dev); 235 236 return 0; 237 } 238 239 static const struct otp_data px30_data = { 240 .read = rockchip_px30_otp_read, 241 }; 242 243 static const struct otp_data rk3568_data = { 244 .read = rockchip_rk3568_otp_read, 245 }; 246 247 static const struct otp_data rv1126_data = { 248 .init = rockchip_rv1126_otp_init, 249 .read = rockchip_rv1126_otp_read, 250 }; 251 252 static const struct udevice_id rockchip_otp_ids[] = { 253 { 254 .compatible = "rockchip,px30-otp", 255 .data = (ulong)&px30_data, 256 }, 257 { 258 .compatible = "rockchip,rk3308-otp", 259 .data = (ulong)&px30_data, 260 }, 261 { 262 .compatible = "rockchip,rk3568-otp", 263 .data = (ulong)&rk3568_data, 264 }, 265 { 266 .compatible = "rockchip,rv1126-otp", 267 .data = (ulong)&rv1126_data, 268 }, 269 {} 270 }; 271 272 U_BOOT_DRIVER(rockchip_otp) = { 273 .name = "rockchip_otp", 274 .id = UCLASS_MISC, 275 .of_match = rockchip_otp_ids, 276 .ops = &rockchip_otp_ops, 277 .ofdata_to_platdata = rockchip_otp_ofdata_to_platdata, 278 .platdata_auto_alloc_size = sizeof(struct rockchip_otp_platdata), 279 .probe = rockchip_otp_probe, 280 }; 281