1 // SPDX-License-Identifier: BSD-3-Clause 2 /* 3 * Copyright (c) 2017-2025, STMicroelectronics - All Rights Reserved 4 */ 5 6 #include <assert.h> 7 #include <drivers/clk.h> 8 #include <drivers/clk_dt.h> 9 #include <drivers/stm32_iwdg.h> 10 #include <drivers/wdt.h> 11 #include <io.h> 12 #include <keep.h> 13 #include <kernel/boot.h> 14 #include <kernel/delay.h> 15 #include <kernel/dt.h> 16 #include <kernel/dt_driver.h> 17 #include <kernel/interrupt.h> 18 #include <kernel/misc.h> 19 #include <kernel/panic.h> 20 #include <kernel/pm.h> 21 #include <kernel/spinlock.h> 22 #include <libfdt.h> 23 #include <mm/core_memprot.h> 24 #include <sm/sm.h> 25 #include <stm32_util.h> 26 #include <string.h> 27 #include <trace.h> 28 29 /* IWDG Compatibility */ 30 #define IWDG_TIMEOUT_US U(10000) 31 #define IWDG_CNT_MASK GENMASK_32(11, 0) 32 #define IWDG_ONF_MIN_VER U(0x31) 33 34 /* IWDG registers offsets */ 35 #define IWDG_KR_OFFSET U(0x00) 36 #define IWDG_PR_OFFSET U(0x04) 37 #define IWDG_RLR_OFFSET U(0x08) 38 #define IWDG_SR_OFFSET U(0x0C) 39 #define IWDG_EWCR_OFFSET U(0x14) 40 #define IWDG_VERR_OFFSET U(0x3F4) 41 42 #define IWDG_KR_WPROT_KEY U(0x0000) 43 #define IWDG_KR_ACCESS_KEY U(0x5555) 44 #define IWDG_KR_RELOAD_KEY U(0xAAAA) 45 #define IWDG_KR_START_KEY U(0xCCCC) 46 47 /* Use a fixed prescaler divider of 256 */ 48 #define IWDG_PRESCALER_256 U(256) 49 #define IWDG_PR_DIV_256 U(0x06) 50 #define IWDG_PR_DIV_MASK GENMASK_32(3, 0) 51 52 #define IWDG_SR_PVU BIT(0) 53 #define IWDG_SR_RVU BIT(1) 54 #define IWDG_SR_WVU BIT(2) 55 #define IWDG_SR_EWU BIT(3) 56 #define IWDG_SR_UPDATE_MASK (IWDG_SR_PVU | IWDG_SR_RVU | IWDG_SR_WVU | \ 57 IWDG_SR_EWU) 58 #define IWDG_SR_ONF BIT(8) 59 60 #define IWDG_EWCR_EWIE BIT(15) 61 #define IWDG_EWCR_EWIC BIT(14) 62 63 #define IWDG_VERR_REV_MASK GENMASK_32(7, 0) 64 65 /* 66 * Values for struct stm32_iwdg_device::flags 67 * IWDG_FLAGS_HW_ENABLED Watchdog is enabled by BootROM 68 * IWDG_FLAGS_DISABLE_ON_STOP Watchdog is freezed in SoC STOP mode 69 * IWDG_FLAGS_DISABLE_ON_STANDBY Watchdog is freezed in SoC STANDBY mode 70 * IWDG_FLAGS_ENABLED Watchdog has been enabled 71 */ 72 #define IWDG_FLAGS_HW_ENABLED BIT(0) 73 #define IWDG_FLAGS_DISABLE_ON_STOP BIT(1) 74 #define IWDG_FLAGS_DISABLE_ON_STANDBY BIT(2) 75 #define IWDG_FLAGS_ENABLED BIT(3) 76 77 /* 78 * IWDG watch instance data 79 * @base - IWDG interface IOMEM base address 80 * @clk_pclk - Bus clock 81 * @clk_lsi - IWDG source clock 82 * @flags - Property flags for the IWDG instance 83 * @timeout - Watchdog elaspure timeout 84 * @hw_version - Watchdog HW version 85 * @wdt_chip - Wathcdog chip instance 86 */ 87 struct stm32_iwdg_device { 88 struct io_pa_va base; 89 struct clk *clk_pclk; 90 struct clk *clk_lsi; 91 uint32_t flags; 92 unsigned long timeout; 93 unsigned int hw_version; 94 struct wdt_chip wdt_chip; 95 }; 96 97 static vaddr_t get_base(struct stm32_iwdg_device *iwdg) 98 { 99 return io_pa_or_va(&iwdg->base, 1); 100 } 101 102 static void iwdg_wdt_set_enabled(struct stm32_iwdg_device *iwdg) 103 { 104 iwdg->flags |= IWDG_FLAGS_ENABLED; 105 } 106 107 static bool iwdg_wdt_is_enabled(struct stm32_iwdg_device *iwdg) 108 { 109 return iwdg->flags & IWDG_FLAGS_ENABLED; 110 } 111 112 /* Return counter value to related to input timeout in seconds, or 0 on error */ 113 static uint32_t iwdg_timeout_cnt(struct stm32_iwdg_device *iwdg, 114 unsigned long to_sec) 115 { 116 uint64_t reload = (uint64_t)to_sec * clk_get_rate(iwdg->clk_lsi); 117 uint64_t cnt = (reload / IWDG_PRESCALER_256) - 1; 118 119 /* Be safe and expect any counter to be above 2 */ 120 if (cnt > IWDG_CNT_MASK || cnt < 3) 121 return 0; 122 123 return cnt; 124 } 125 126 /* Wait IWDG programming completes */ 127 static TEE_Result iwdg_wait_sync(struct stm32_iwdg_device *iwdg) 128 { 129 uint64_t timeout_ref = timeout_init_us(IWDG_TIMEOUT_US); 130 vaddr_t iwdg_base = get_base(iwdg); 131 132 while (io_read32(iwdg_base + IWDG_SR_OFFSET) & IWDG_SR_UPDATE_MASK) 133 if (timeout_elapsed(timeout_ref)) 134 break; 135 136 if (io_read32(iwdg_base + IWDG_SR_OFFSET) & IWDG_SR_UPDATE_MASK) 137 return TEE_ERROR_GENERIC; 138 139 return TEE_SUCCESS; 140 } 141 142 static TEE_Result configure_timeout(struct stm32_iwdg_device *iwdg) 143 { 144 TEE_Result res = TEE_ERROR_GENERIC; 145 vaddr_t iwdg_base = get_base(iwdg); 146 uint32_t rlr_value = 0; 147 148 assert(iwdg_wdt_is_enabled(iwdg)); 149 150 rlr_value = iwdg_timeout_cnt(iwdg, iwdg->timeout); 151 if (!rlr_value) 152 return TEE_ERROR_GENERIC; 153 154 io_write32(iwdg_base + IWDG_KR_OFFSET, IWDG_KR_ACCESS_KEY); 155 io_write32(iwdg_base + IWDG_PR_OFFSET, IWDG_PR_DIV_256); 156 io_write32(iwdg_base + IWDG_RLR_OFFSET, rlr_value); 157 io_write32(iwdg_base + IWDG_KR_OFFSET, IWDG_KR_RELOAD_KEY); 158 159 res = iwdg_wait_sync(iwdg); 160 161 return res; 162 } 163 164 static void iwdg_start(struct stm32_iwdg_device *iwdg) 165 { 166 io_write32(get_base(iwdg) + IWDG_KR_OFFSET, IWDG_KR_START_KEY); 167 168 iwdg_wdt_set_enabled(iwdg); 169 } 170 171 static void iwdg_refresh(struct stm32_iwdg_device *iwdg) 172 { 173 io_write32(get_base(iwdg) + IWDG_KR_OFFSET, IWDG_KR_RELOAD_KEY); 174 } 175 176 /* Operators for watchdog OP-TEE interface */ 177 static struct stm32_iwdg_device *wdt_chip_to_iwdg(struct wdt_chip *chip) 178 { 179 return container_of(chip, struct stm32_iwdg_device, wdt_chip); 180 } 181 182 static TEE_Result iwdg_wdt_init(struct wdt_chip *chip, 183 unsigned long *min_timeout, 184 unsigned long *max_timeout) 185 { 186 struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip); 187 unsigned long rate = clk_get_rate(iwdg->clk_lsi); 188 189 if (!rate) 190 return TEE_ERROR_GENERIC; 191 192 /* Be safe and expect any counter to be above 2 */ 193 *min_timeout = 3 * IWDG_PRESCALER_256 / rate; 194 *max_timeout = (IWDG_CNT_MASK + 1) * IWDG_PRESCALER_256 / rate; 195 196 return TEE_SUCCESS; 197 } 198 199 static void iwdg_wdt_start(struct wdt_chip *chip) 200 { 201 struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip); 202 203 iwdg_start(iwdg); 204 205 if (configure_timeout(iwdg)) 206 panic(); 207 } 208 209 static void iwdg_wdt_refresh(struct wdt_chip *chip) 210 { 211 struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip); 212 213 iwdg_refresh(iwdg); 214 } 215 216 static TEE_Result iwdg_wdt_set_timeout(struct wdt_chip *chip, 217 unsigned long timeout) 218 { 219 struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip); 220 221 if (!iwdg_timeout_cnt(iwdg, timeout)) 222 return TEE_ERROR_BAD_PARAMETERS; 223 224 iwdg->timeout = timeout; 225 226 if (iwdg_wdt_is_enabled(iwdg)) { 227 TEE_Result res = TEE_ERROR_GENERIC; 228 229 res = configure_timeout(iwdg); 230 if (res) 231 return res; 232 } 233 234 return TEE_SUCCESS; 235 } 236 237 static const struct wdt_ops stm32_iwdg_ops = { 238 .init = iwdg_wdt_init, 239 .start = iwdg_wdt_start, 240 .ping = iwdg_wdt_refresh, 241 .set_timeout = iwdg_wdt_set_timeout, 242 }; 243 DECLARE_KEEP_PAGER(stm32_iwdg_ops); 244 245 /* Driver initialization */ 246 static TEE_Result stm32_iwdg_parse_fdt(struct stm32_iwdg_device *iwdg, 247 const void *fdt, int node) 248 { 249 TEE_Result res = TEE_ERROR_GENERIC; 250 struct dt_node_info dt_info = { }; 251 const fdt32_t *cuint = NULL; 252 253 fdt_fill_device_info(fdt, &dt_info, node); 254 255 if (dt_info.reg == DT_INFO_INVALID_REG || 256 dt_info.reg_size == DT_INFO_INVALID_REG_SIZE) 257 panic(); 258 259 res = clk_dt_get_by_name(fdt, node, "pclk", &iwdg->clk_pclk); 260 if (res) 261 return res; 262 263 res = clk_dt_get_by_name(fdt, node, "lsi", &iwdg->clk_lsi); 264 if (res) 265 return res; 266 267 /* Get IOMEM address */ 268 iwdg->base.pa = dt_info.reg; 269 io_pa_or_va_secure(&iwdg->base, dt_info.reg_size); 270 assert(iwdg->base.va); 271 272 /* Get and check timeout value */ 273 cuint = fdt_getprop(fdt, node, "timeout-sec", NULL); 274 if (!cuint) 275 return TEE_ERROR_BAD_PARAMETERS; 276 277 iwdg->timeout = (int)fdt32_to_cpu(*cuint); 278 if (!iwdg->timeout) 279 return TEE_ERROR_BAD_PARAMETERS; 280 281 if (!iwdg_timeout_cnt(iwdg, iwdg->timeout)) { 282 EMSG("Timeout %lu not applicable", iwdg->timeout); 283 return TEE_ERROR_BAD_PARAMETERS; 284 } 285 286 /* DT can specify low power cases */ 287 if (!fdt_getprop(fdt, node, "stm32,enable-on-stop", NULL)) 288 iwdg->flags |= IWDG_FLAGS_DISABLE_ON_STOP; 289 290 if (!fdt_getprop(fdt, node, "stm32,enable-on-standby", NULL)) 291 iwdg->flags |= IWDG_FLAGS_DISABLE_ON_STANDBY; 292 293 return TEE_SUCCESS; 294 } 295 296 /* Platform should override this function to provide IWDG fuses configuration */ 297 TEE_Result __weak stm32_get_iwdg_otp_config(paddr_t pbase __unused, 298 struct stm32_iwdg_otp_data *otp_d) 299 { 300 otp_d->hw_enabled = false; 301 otp_d->disable_on_stop = false; 302 otp_d->disable_on_standby = false; 303 304 return TEE_SUCCESS; 305 } 306 307 static void iwdg_wdt_get_version_and_status(struct stm32_iwdg_device *iwdg) 308 { 309 vaddr_t iwdg_base = get_base(iwdg); 310 uint32_t rlr_value = 0; 311 312 iwdg->hw_version = io_read32(iwdg_base + IWDG_VERR_OFFSET) & 313 IWDG_VERR_REV_MASK; 314 315 /* Test if watchdog is already running */ 316 if (iwdg->hw_version >= IWDG_ONF_MIN_VER) { 317 if (io_read32(iwdg_base + IWDG_SR_OFFSET) & IWDG_SR_ONF) 318 iwdg_wdt_set_enabled(iwdg); 319 } else { 320 /* 321 * Workaround for old versions without IWDG_SR_ONF bit: 322 * - write in IWDG_RLR_OFFSET 323 * - wait for sync 324 * - if sync succeeds, then iwdg is running 325 */ 326 io_write32(iwdg_base + IWDG_KR_OFFSET, IWDG_KR_ACCESS_KEY); 327 328 rlr_value = io_read32(iwdg_base + IWDG_RLR_OFFSET); 329 io_write32(iwdg_base + IWDG_RLR_OFFSET, rlr_value); 330 331 if (!iwdg_wait_sync(iwdg)) 332 iwdg_wdt_set_enabled(iwdg); 333 334 io_write32(iwdg_base + IWDG_KR_OFFSET, IWDG_KR_WPROT_KEY); 335 } 336 337 DMSG("Watchdog is %sabled", iwdg_wdt_is_enabled(iwdg) ? "en" : "dis"); 338 } 339 340 static TEE_Result stm32_iwdg_setup(struct stm32_iwdg_device *iwdg, 341 const void *fdt, int node) 342 { 343 struct stm32_iwdg_otp_data otp_data = { }; 344 TEE_Result res = TEE_SUCCESS; 345 346 res = stm32_iwdg_parse_fdt(iwdg, fdt, node); 347 if (res) 348 return res; 349 350 res = stm32_get_iwdg_otp_config(iwdg->base.pa, &otp_data); 351 if (res) 352 return res; 353 354 if (otp_data.hw_enabled) 355 iwdg->flags |= IWDG_FLAGS_HW_ENABLED; 356 if (otp_data.disable_on_stop) 357 iwdg->flags |= IWDG_FLAGS_DISABLE_ON_STOP; 358 if (otp_data.disable_on_standby) 359 iwdg->flags |= IWDG_FLAGS_DISABLE_ON_STANDBY; 360 361 /* Enable watchdog source and bus clocks once for all */ 362 clk_enable(iwdg->clk_lsi); 363 clk_enable(iwdg->clk_pclk); 364 365 iwdg_wdt_get_version_and_status(iwdg); 366 367 if (otp_data.hw_enabled) 368 iwdg_wdt_set_enabled(iwdg); 369 370 if (iwdg_wdt_is_enabled(iwdg)) { 371 /* Configure timeout if watchdog is already enabled */ 372 res = configure_timeout(iwdg); 373 if (res) 374 return res; 375 376 iwdg_refresh(iwdg); 377 } 378 379 return TEE_SUCCESS; 380 } 381 382 static TEE_Result stm32_iwdg_probe(const void *fdt, int node, 383 const void *compat_data __unused) 384 { 385 struct stm32_iwdg_device *iwdg = NULL; 386 TEE_Result res = TEE_SUCCESS; 387 388 iwdg = calloc(1, sizeof(*iwdg)); 389 if (!iwdg) 390 return TEE_ERROR_OUT_OF_MEMORY; 391 392 res = stm32_iwdg_setup(iwdg, fdt, node); 393 if (res) 394 goto out; 395 396 iwdg->wdt_chip.ops = &stm32_iwdg_ops; 397 398 res = watchdog_register(&iwdg->wdt_chip); 399 400 out: 401 if (res) 402 free(iwdg); 403 404 return res; 405 } 406 407 static const struct dt_device_match stm32_iwdg_match_table[] = { 408 { .compatible = "st,stm32mp1-iwdg" }, 409 { } 410 }; 411 412 DEFINE_DT_DRIVER(stm32_iwdg_dt_driver) = { 413 .name = "stm32-iwdg", 414 .match_table = stm32_iwdg_match_table, 415 .probe = stm32_iwdg_probe, 416 }; 417