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