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 <misc.h> 13 14 /* OTP Register Offsets */ 15 #define OTPC_SBPI_CTRL 0x0020 16 #define OTPC_SBPI_CMD_VALID_PRE 0x0024 17 #define OTPC_SBPI_CS_VALID_PRE 0x0028 18 #define OTPC_SBPI_STATUS 0x002C 19 #define OTPC_USER_CTRL 0x0100 20 #define OTPC_USER_ADDR 0x0104 21 #define OTPC_USER_ENABLE 0x0108 22 #define OTPC_USER_Q 0x0124 23 #define OTPC_INT_STATUS 0x0304 24 #define OTPC_SBPI_CMD0_OFFSET 0x1000 25 #define OTPC_SBPI_CMD1_OFFSET 0x1004 26 27 /* OTP Register bits and masks */ 28 #define OTPC_USER_ADDR_MASK GENMASK(31, 16) 29 #define OTPC_USE_USER BIT(0) 30 #define OTPC_USE_USER_MASK GENMASK(16, 16) 31 #define OTPC_USER_FSM_ENABLE BIT(0) 32 #define OTPC_USER_FSM_ENABLE_MASK GENMASK(16, 16) 33 #define OTPC_SBPI_DONE BIT(1) 34 #define OTPC_USER_DONE BIT(2) 35 36 #define SBPI_DAP_ADDR 0x02 37 #define SBPI_DAP_ADDR_SHIFT 8 38 #define SBPI_DAP_ADDR_MASK GENMASK(31, 24) 39 #define SBPI_CMD_VALID_MASK GENMASK(31, 16) 40 #define SBPI_DAP_CMD_WRF 0xC0 41 #define SBPI_DAP_REG_ECC 0x3A 42 #define SBPI_ECC_ENABLE 0x00 43 #define SBPI_ECC_DISABLE 0x09 44 #define SBPI_ENABLE BIT(0) 45 #define SBPI_ENABLE_MASK GENMASK(16, 16) 46 47 #define OTPC_TIMEOUT 10000 48 49 typedef int (*OTP_READ)(struct udevice *dev, int offset, void *buf, int size); 50 51 struct rockchip_otp_platdata { 52 void __iomem *base; 53 }; 54 55 #if defined(DEBUG) 56 static int dump_otps(cmd_tbl_t *cmdtp, int flag, 57 int argc, char * const argv[]) 58 { 59 struct udevice *dev; 60 u8 otps[64] = {0}; 61 int ret; 62 63 /* retrieve the device */ 64 ret = uclass_get_device_by_driver(UCLASS_MISC, 65 DM_GET_DRIVER(rockchip_otp), &dev); 66 if (ret) { 67 printf("%s: no misc-device found\n", __func__); 68 return 0; 69 } 70 71 ret = misc_read(dev, 0, &otps, sizeof(otps)); 72 if (ret) { 73 printf("%s: misc_read failed\n", __func__); 74 return 0; 75 } 76 77 printf("otp-contents:\n"); 78 print_buffer(0, otps, 1, 64, 16); 79 80 return 0; 81 } 82 83 U_BOOT_CMD( 84 rockchip_dump_otps, 1, 1, dump_otps, 85 "Dump the content of the otps", 86 "" 87 ); 88 #endif 89 90 static int rockchip_otp_wait_status(struct rockchip_otp_platdata *otp, 91 u32 flag) 92 { 93 int delay = OTPC_TIMEOUT; 94 95 while (!(readl(otp->base + OTPC_INT_STATUS) & flag)) { 96 udelay(1); 97 delay--; 98 if (delay <= 0) { 99 printf("%s: wait init status timeout\n", __func__); 100 return -ETIMEDOUT; 101 } 102 } 103 104 /* clean int status */ 105 writel(flag, otp->base + OTPC_INT_STATUS); 106 107 return 0; 108 } 109 110 static int rockchip_otp_ecc_enable(struct rockchip_otp_platdata *otp, 111 bool enable) 112 { 113 int ret = 0; 114 115 writel(SBPI_DAP_ADDR_MASK | (SBPI_DAP_ADDR << SBPI_DAP_ADDR_SHIFT), 116 otp->base + OTPC_SBPI_CTRL); 117 118 writel(SBPI_CMD_VALID_MASK | 0x1, otp->base + OTPC_SBPI_CMD_VALID_PRE); 119 writel(SBPI_DAP_CMD_WRF | SBPI_DAP_REG_ECC, 120 otp->base + OTPC_SBPI_CMD0_OFFSET); 121 if (enable) 122 writel(SBPI_ECC_ENABLE, otp->base + OTPC_SBPI_CMD1_OFFSET); 123 else 124 writel(SBPI_ECC_DISABLE, otp->base + OTPC_SBPI_CMD1_OFFSET); 125 126 writel(SBPI_ENABLE_MASK | SBPI_ENABLE, otp->base + OTPC_SBPI_CTRL); 127 128 ret = rockchip_otp_wait_status(otp, OTPC_SBPI_DONE); 129 if (ret < 0) 130 printf("%s timeout during ecc_enable\n", __func__); 131 132 return ret; 133 } 134 135 static int rockchip_px30_otp_read(struct udevice *dev, int offset, 136 void *buf, int size) 137 { 138 struct rockchip_otp_platdata *otp = dev_get_platdata(dev); 139 u8 *buffer = buf; 140 int ret = 0; 141 142 ret = rockchip_otp_ecc_enable(otp, false); 143 if (ret < 0) { 144 printf("%s rockchip_otp_ecc_enable err\n", __func__); 145 return ret; 146 } 147 148 writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); 149 udelay(5); 150 while (size--) { 151 writel(offset++ | OTPC_USER_ADDR_MASK, 152 otp->base + OTPC_USER_ADDR); 153 writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK, 154 otp->base + OTPC_USER_ENABLE); 155 ret = rockchip_otp_wait_status(otp, OTPC_USER_DONE); 156 if (ret < 0) { 157 printf("%s timeout during read setup\n", __func__); 158 goto read_end; 159 } 160 *buffer++ = readb(otp->base + OTPC_USER_Q); 161 } 162 163 read_end: 164 writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL); 165 166 return ret; 167 } 168 169 static int rockchip_otp_read(struct udevice *dev, int offset, 170 void *buf, int size) 171 { 172 OTP_READ otp_read = NULL; 173 174 otp_read = (OTP_READ)dev_get_driver_data(dev); 175 if (!otp_read) 176 return -ENOSYS; 177 178 return (*otp_read)(dev, offset, buf, size); 179 } 180 181 static const struct misc_ops rockchip_otp_ops = { 182 .read = rockchip_otp_read, 183 }; 184 185 static int rockchip_otp_ofdata_to_platdata(struct udevice *dev) 186 { 187 struct rockchip_otp_platdata *otp = dev_get_platdata(dev); 188 189 otp->base = dev_read_addr_ptr(dev); 190 191 return 0; 192 } 193 194 static const struct udevice_id rockchip_otp_ids[] = { 195 { 196 .compatible = "rockchip,px30-otp", 197 .data = (ulong)&rockchip_px30_otp_read, 198 }, 199 { 200 .compatible = "rockchip,rk3308-otp", 201 .data = (ulong)&rockchip_px30_otp_read, 202 }, 203 {} 204 }; 205 206 U_BOOT_DRIVER(rockchip_otp) = { 207 .name = "rockchip_otp", 208 .id = UCLASS_MISC, 209 .of_match = rockchip_otp_ids, 210 .ops = &rockchip_otp_ops, 211 .ofdata_to_platdata = rockchip_otp_ofdata_to_platdata, 212 .platdata_auto_alloc_size = sizeof(struct rockchip_otp_platdata), 213 }; 214