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_KEYLAD_INIT, NULL); 164 165 return 0; 166 } 167 168 static int rk_otp_keylad_read_deinit(void) 169 { 170 struct udevice *dev; 171 172 dev = misc_otp_get_device(OTP_S); 173 if (!dev) 174 return -ENODEV; 175 176 misc_otp_ioctl(dev, IOCTL_REQ_KEYLAD_DEINIT, NULL); 177 178 return 0; 179 } 180 181 static int rk_keylad_read_otp_key(u32 otp_offset, u32 keylad_area, u32 keylen) 182 { 183 int ret = 0; 184 u32 val = 0; 185 u32 nbytes = keylen; 186 187 /* keylad_area of 256bits can be 0-1 */ 188 if (keylad_area >= KEYLAD_AREA_NUM) 189 return -EINVAL; 190 191 ret = rk_otp_keylad_read_init(); 192 if (ret) { 193 printf("Keyladder read otp key init err: 0x%x.", ret); 194 return ret; 195 } 196 197 /* src use byte address, dst use keytable block address */ 198 val = KL_OTP_KEY_REQ_SRC_ADDR(otp_offset / 2) | 199 KL_OTP_KEY_REQ_DST_ADDR(keylad_area) | 200 KL_OTP_KEY_REQ_BYTE_SWAP | 201 KL_OTP_KEY_REQ_EN; 202 203 keylad_write(KEYLAD_KEY_SEL, VALUE_KEY_SEL_OUTER_KEY); 204 205 keylad_write(KEY_LADDER_KEY_LEN, KL_KEY_LEN(nbytes)); 206 207 keylad_write(KEY_LADDER_OTP_KEY_REQ, val); 208 209 KEYLAD_POLL_TIMEOUT(keylad_read(KEY_LADDER_OTP_KEY_REQ) & KL_OTP_KEY_REQ_EN, 210 RK_KEYLAD_TIME_OUT, ret); 211 212 val = keylad_read(KEY_LADDER_OTP_KEY_REQ); 213 if (val & KL_OTP_KEY_ECC_ST) { 214 printf("KEYLAD transfer OTP key ECC check error!"); 215 ret = -EIO; 216 } 217 218 rk_otp_keylad_read_deinit(); 219 220 return ret; 221 } 222 223 static int rockchip_keylad_transfer_fwkey(struct udevice *dev, ulong dst, 224 u32 fw_keyid, u32 keylen) 225 { 226 int res = 0; 227 u32 fw_key_offset; 228 u32 max_key_len = 0; 229 230 if (keylen % 4) { 231 printf("key_len(%u) must be multiple of 4 error.", keylen); 232 return -EINVAL; 233 } 234 235 res = rk_get_fwkey_param(fw_keyid, &fw_key_offset, &max_key_len); 236 if (res) 237 return res; 238 239 if (keylen > max_key_len) { 240 printf("key_len(%u) > %u error.", keylen, max_key_len); 241 return -EINVAL; 242 } 243 244 rk_keylad_enable_clk(dev); 245 246 res = rk_keylad_read_otp_key(fw_key_offset, 0, keylen); 247 if (res) { 248 printf("Keyladder read otp key err: 0x%x.", res); 249 return res; 250 } 251 252 res = rk_keylad_send_key(0, keylen / 4, dst); 253 254 rk_keylad_disable_clk(dev); 255 256 if (res) { 257 printf("Keyladder transfer key err: 0x%x.", res); 258 goto exit; 259 } 260 261 exit: 262 return res; 263 } 264 265 static const struct dm_keylad_ops rockchip_keylad_ops = { 266 .transfer_fwkey = rockchip_keylad_transfer_fwkey, 267 }; 268 269 static int rockchip_keylad_ofdata_to_platdata(struct udevice *dev) 270 { 271 struct rockchip_keylad_priv *priv = dev_get_priv(dev); 272 int len = 0; 273 int ret = 0; 274 275 memset(priv, 0x00, sizeof(*priv)); 276 277 priv->reg = (fdt_addr_t)dev_read_addr_ptr(dev); 278 if (priv->reg == FDT_ADDR_T_NONE) 279 return -EINVAL; 280 281 keylad_base = priv->reg; 282 283 /* if there is no clocks in dts, just skip it */ 284 if (!dev_read_prop(dev, "clocks", &len)) { 285 printf("Keylad \"clocks\" property not set.\n"); 286 return 0; 287 } 288 289 priv->clocks = malloc(len); 290 if (!priv->clocks) 291 return -ENOMEM; 292 293 priv->nclocks = len / (2 * sizeof(u32)); 294 if (dev_read_u32_array(dev, "clocks", (u32 *)priv->clocks, 295 priv->nclocks)) { 296 printf("Keylad can't read \"clocks\" property.\n"); 297 ret = -EINVAL; 298 goto exit; 299 } 300 301 return 0; 302 exit: 303 if (priv->clocks) 304 free(priv->clocks); 305 306 return ret; 307 } 308 309 static int rockchip_keylad_probe(struct udevice *dev) 310 { 311 rk_keylad_disable_clk(dev); 312 313 return 0; 314 } 315 316 static const struct udevice_id rockchip_keylad_ids[] = { 317 { 318 .compatible = "rockchip,keylad", 319 }, 320 }; 321 322 U_BOOT_DRIVER(rockchip_keylad) = { 323 .name = "rockchip_keylad", 324 .id = UCLASS_KEYLAD, 325 .of_match = rockchip_keylad_ids, 326 .ops = &rockchip_keylad_ops, 327 .probe = rockchip_keylad_probe, 328 .ofdata_to_platdata = rockchip_keylad_ofdata_to_platdata, 329 .priv_auto_alloc_size = sizeof(struct rockchip_keylad_priv), 330 }; 331