1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2025 Rockchip Electronics Co., Ltd 4 */ 5 6 #include <common.h> 7 #include <clk.h> 8 #include <keylad.h> 9 #include <dm.h> 10 #include <misc.h> 11 #include <asm/io.h> 12 #include <clk-uclass.h> 13 #include <asm/arch/hardware.h> 14 #include <asm/arch/clock.h> 15 16 #define KEYLAD_APB_CMD 0x0450 17 #define REG_APB_CMD_EN BIT(0) 18 #define VALUE_APB_CMD_DISABLE 0 19 #define VALUE_APB_CMD_ENABLE BIT(0) 20 21 #define KEYLAD_APB_PADDR 0x0454 22 #define KEYLAD_APB_PWDATA 0x0458 23 #define KEYLAD_APB_PWRITE 0x045C 24 #define KEYLAD_DATA_CTL 0x0460 25 #define VALUE_DATA_CTL_EN BIT(15) 26 27 #define KEYLAD_KEY_SEL 0x0610 28 #define VALUE_KEY_SEL_OUTER_KEY 0x00000000 29 30 #define KEYLAD_LOCKSTEP_FLAG 0x0618 31 #define KEYLAD_LOCKSTEP_EN 0x061C 32 33 #define KEY_LADDER_OTP_KEY_REQ 0x0640 34 #define KL_OTP_KEY_REQ_DST_ADDR(addr) ((addr) & 0x3) // 256bit algin address 35 #define KL_OTP_KEY_REQ_BYTE_SWAP BIT(4) 36 #define KL_OTP_KEY_REQ_WORD_SWAP BIT(5) 37 #define KL_OTP_KEY_REQ_EN BIT(8) 38 #define KL_OTP_KEY_ECC_ST BIT(12) 39 #define KL_OTP_KEY_REQ_SRC_ADDR(addr) (((addr) & 0xffff) << 16)// byte address, dword align 40 41 #define KEY_LADDER_KEY_LEN 0x0648 42 #define KL_KEY_LEN(len) ((len) & 0x3f) 43 44 #define KEYLAD_KEY_REG_SIZE_BYTES 4 45 #define KEYLAD_KEY_REG_NUM 32 46 #define KEYLAD_AREA_NUM 2 47 48 #define RK_KEYLAD_TIME_OUT 10000 /* max 10ms */ 49 50 #define KEYLAD_POLL_TIMEOUT(condition, timeout, ret) do { \ 51 u32 time_out = timeout; \ 52 while (condition) { \ 53 if (time_out-- == 0) { \ 54 printf("[%s] %d: time out!\n", __func__, __LINE__); \ 55 ret = -ETIMEDOUT; \ 56 break; \ 57 } \ 58 udelay(1); \ 59 } \ 60 } while (0) 61 62 struct rockchip_keylad_priv { 63 fdt_addr_t reg; 64 char *clocks; 65 u32 nclocks; 66 }; 67 68 fdt_addr_t keylad_base; 69 70 static int rk_keylad_do_enable_clk(struct udevice *dev, int enable) 71 { 72 struct rockchip_keylad_priv *priv = dev_get_priv(dev); 73 struct clk clk; 74 int i, ret; 75 76 for (i = 0; i < priv->nclocks; i++) { 77 ret = clk_get_by_index(dev, i, &clk); 78 if (ret < 0) { 79 printf("Keylad failed to get clk index %d, ret=%d\n", i, ret); 80 return ret; 81 } 82 83 if (enable) 84 ret = clk_enable(&clk); 85 else 86 ret = clk_disable(&clk); 87 88 if (ret < 0 && ret != -ENOSYS) { 89 printf("Keylad failed to enable(%d) clk(%ld): ret=%d\n", 90 enable, clk.id, ret); 91 return ret; 92 } 93 } 94 95 return 0; 96 } 97 98 static int rk_keylad_enable_clk(struct udevice *dev) 99 { 100 return rk_keylad_do_enable_clk(dev, 1); 101 } 102 103 static int rk_keylad_disable_clk(struct udevice *dev) 104 { 105 return rk_keylad_do_enable_clk(dev, 0); 106 } 107 108 static inline u32 keylad_read(u32 offset) 109 { 110 return readl(keylad_base + offset); 111 } 112 113 static inline void keylad_write(u32 offset, u32 val) 114 { 115 writel(val, keylad_base + offset); 116 } 117 118 static int rk_get_fwkey_param(u32 keyid, u32 *offset, u32 *max_len) 119 { 120 switch (keyid) { 121 case RK_FW_KEY0: 122 *offset = OTP_FW_ENC_KEY_ADDR; 123 *max_len = OTP_FW_ENC_KEY_SIZE; 124 break; 125 default: 126 return -EINVAL; 127 } 128 129 return 0; 130 } 131 132 static int rk_keylad_send_key(u32 key_reg, u32 n_words, ulong dst_addr) 133 { 134 int ret = 0; 135 136 /* key_reg of 32bits can be 0-31 */ 137 if ((key_reg + n_words) > KEYLAD_KEY_REG_NUM) 138 return -EINVAL; 139 140 for (u32 i = 0; i < n_words; i++) { 141 /* set destination addr */ 142 keylad_write(KEYLAD_APB_PADDR, 143 (dst_addr & 0xffffffff) + (i * KEYLAD_KEY_REG_SIZE_BYTES)); 144 /* select which word of key table to be sent */ 145 keylad_write(KEYLAD_APB_PWDATA, key_reg + i); 146 147 keylad_write(KEYLAD_APB_CMD, VALUE_APB_CMD_ENABLE); 148 KEYLAD_POLL_TIMEOUT((keylad_read(KEYLAD_APB_CMD) & REG_APB_CMD_EN) == 149 VALUE_APB_CMD_ENABLE, RK_KEYLAD_TIME_OUT, ret); 150 } 151 152 return ret; 153 } 154 155 static int rk_otp_keylad_read_init(void) 156 { 157 struct udevice *dev; 158 159 dev = misc_otp_get_device(OTP_S); 160 if (!dev) 161 return -ENODEV; 162 163 misc_otp_ioctl(dev, IOCTL_REQ_START, NULL); 164 misc_otp_ioctl(dev, IOCTL_REQ_KEYLAD_INIT, NULL); 165 166 return 0; 167 } 168 169 static int rk_otp_keylad_read_deinit(void) 170 { 171 struct udevice *dev; 172 173 dev = misc_otp_get_device(OTP_S); 174 if (!dev) 175 return -ENODEV; 176 177 misc_otp_ioctl(dev, IOCTL_REQ_KEYLAD_DEINIT, NULL); 178 misc_otp_ioctl(dev, IOCTL_REQ_STOP, NULL); 179 180 return 0; 181 } 182 183 static int rk_keylad_read_otp_key(u32 otp_offset, u32 keylad_area, u32 keylen) 184 { 185 int ret = 0; 186 u32 val = 0; 187 u32 nbytes = keylen; 188 189 /* keylad_area of 256bits can be 0-1 */ 190 if (keylad_area >= KEYLAD_AREA_NUM) 191 return -EINVAL; 192 193 ret = rk_otp_keylad_read_init(); 194 if (ret) { 195 printf("Keyladder read otp key init err: 0x%x.", ret); 196 return ret; 197 } 198 199 /* src use byte address, dst use keytable block address */ 200 val = KL_OTP_KEY_REQ_SRC_ADDR(otp_offset / 2) | 201 KL_OTP_KEY_REQ_DST_ADDR(keylad_area) | 202 KL_OTP_KEY_REQ_BYTE_SWAP | 203 KL_OTP_KEY_REQ_EN; 204 205 keylad_write(KEYLAD_KEY_SEL, VALUE_KEY_SEL_OUTER_KEY); 206 207 keylad_write(KEY_LADDER_KEY_LEN, KL_KEY_LEN(nbytes)); 208 209 keylad_write(KEY_LADDER_OTP_KEY_REQ, val); 210 211 KEYLAD_POLL_TIMEOUT(keylad_read(KEY_LADDER_OTP_KEY_REQ) & KL_OTP_KEY_REQ_EN, 212 RK_KEYLAD_TIME_OUT, ret); 213 214 val = keylad_read(KEY_LADDER_OTP_KEY_REQ); 215 if (val & KL_OTP_KEY_ECC_ST) { 216 printf("KEYLAD transfer OTP key ECC check error!"); 217 ret = -EIO; 218 } 219 220 rk_otp_keylad_read_deinit(); 221 222 return ret; 223 } 224 225 static int rockchip_keylad_transfer_fwkey(struct udevice *dev, ulong dst, 226 u32 fw_keyid, u32 keylen) 227 { 228 int res = 0; 229 u32 fw_key_offset; 230 u32 max_key_len = 0; 231 232 if (keylen % 4) { 233 printf("key_len(%u) must be multiple of 4 error.", keylen); 234 return -EINVAL; 235 } 236 237 res = rk_get_fwkey_param(fw_keyid, &fw_key_offset, &max_key_len); 238 if (res) 239 return res; 240 241 if (keylen > max_key_len) { 242 printf("key_len(%u) > %u error.", keylen, max_key_len); 243 return -EINVAL; 244 } 245 246 rk_keylad_enable_clk(dev); 247 248 res = rk_keylad_read_otp_key(fw_key_offset, 0, keylen); 249 if (res) { 250 printf("Keyladder read otp key err: 0x%x.", res); 251 return res; 252 } 253 254 res = rk_keylad_send_key(0, keylen / 4, dst); 255 256 rk_keylad_disable_clk(dev); 257 258 if (res) { 259 printf("Keyladder transfer key err: 0x%x.", res); 260 goto exit; 261 } 262 263 exit: 264 return res; 265 } 266 267 static const struct dm_keylad_ops rockchip_keylad_ops = { 268 .transfer_fwkey = rockchip_keylad_transfer_fwkey, 269 }; 270 271 static int rockchip_keylad_ofdata_to_platdata(struct udevice *dev) 272 { 273 struct rockchip_keylad_priv *priv = dev_get_priv(dev); 274 int len = 0; 275 int ret = 0; 276 277 memset(priv, 0x00, sizeof(*priv)); 278 279 priv->reg = (fdt_addr_t)dev_read_addr_ptr(dev); 280 if (priv->reg == FDT_ADDR_T_NONE) 281 return -EINVAL; 282 283 keylad_base = priv->reg; 284 285 /* if there is no clocks in dts, just skip it */ 286 if (!dev_read_prop(dev, "clocks", &len)) { 287 printf("Keylad \"clocks\" property not set.\n"); 288 return 0; 289 } 290 291 priv->clocks = malloc(len); 292 if (!priv->clocks) 293 return -ENOMEM; 294 295 priv->nclocks = len / (2 * sizeof(u32)); 296 if (dev_read_u32_array(dev, "clocks", (u32 *)priv->clocks, 297 priv->nclocks)) { 298 printf("Keylad can't read \"clocks\" property.\n"); 299 ret = -EINVAL; 300 goto exit; 301 } 302 303 return 0; 304 exit: 305 if (priv->clocks) 306 free(priv->clocks); 307 308 return ret; 309 } 310 311 static int rockchip_keylad_probe(struct udevice *dev) 312 { 313 rk_keylad_disable_clk(dev); 314 315 return 0; 316 } 317 318 static const struct udevice_id rockchip_keylad_ids[] = { 319 { 320 .compatible = "rockchip,keylad", 321 }, 322 }; 323 324 U_BOOT_DRIVER(rockchip_keylad) = { 325 .name = "rockchip_keylad", 326 .id = UCLASS_KEYLAD, 327 .of_match = rockchip_keylad_ids, 328 .ops = &rockchip_keylad_ops, 329 .probe = rockchip_keylad_probe, 330 .ofdata_to_platdata = rockchip_keylad_ofdata_to_platdata, 331 .priv_auto_alloc_size = sizeof(struct rockchip_keylad_priv), 332 }; 333