Commit c7d8669f46ba97f6a8e14d6e9b8d6c39e2c07727
1 parent
54ecb8f702
bus: ti-sysc: Fix watchdog quirk handling
I noticed that when probed with ti-sysc, watchdog can trigger on am3, am4 and dra7 causing a device reset. Turns out I made several mistakes implementing the watchdog quirk handling: 1. We must do both writes to spr register 2. We must also call the reset quirk on disable 3. On am3 and am4 we need to also set swsup quirk flag I probably only tested this earlier with watchdog service running when the watchdog never gets disabled. Fixes: 4e23be473e30 ("bus: ti-sysc: Add support for module specific reset quirks") Signed-off-by: Tony Lindgren <tony@atomide.com>
Showing 1 changed file with 14 additions and 4 deletions Side-by-side Diff
drivers/bus/ti-sysc.c
... | ... | @@ -74,6 +74,7 @@ |
74 | 74 | * @clk_disable_quirk: module specific clock disable quirk |
75 | 75 | * @reset_done_quirk: module specific reset done quirk |
76 | 76 | * @module_enable_quirk: module specific enable quirk |
77 | + * @module_disable_quirk: module specific disable quirk | |
77 | 78 | */ |
78 | 79 | struct sysc { |
79 | 80 | struct device *dev; |
... | ... | @@ -100,6 +101,7 @@ |
100 | 101 | void (*clk_disable_quirk)(struct sysc *sysc); |
101 | 102 | void (*reset_done_quirk)(struct sysc *sysc); |
102 | 103 | void (*module_enable_quirk)(struct sysc *sysc); |
104 | + void (*module_disable_quirk)(struct sysc *sysc); | |
103 | 105 | }; |
104 | 106 | |
105 | 107 | static void sysc_parse_dts_quirks(struct sysc *ddata, struct device_node *np, |
... | ... | @@ -959,6 +961,9 @@ |
959 | 961 | if (ddata->offsets[SYSC_SYSCONFIG] == -ENODEV) |
960 | 962 | return 0; |
961 | 963 | |
964 | + if (ddata->module_disable_quirk) | |
965 | + ddata->module_disable_quirk(ddata); | |
966 | + | |
962 | 967 | regbits = ddata->cap->regbits; |
963 | 968 | reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]); |
964 | 969 | |
... | ... | @@ -1248,6 +1253,9 @@ |
1248 | 1253 | SYSC_MODULE_QUIRK_SGX), |
1249 | 1254 | SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0, |
1250 | 1255 | SYSC_MODULE_QUIRK_WDT), |
1256 | + /* Watchdog on am3 and am4 */ | |
1257 | + SYSC_QUIRK("wdt", 0x44e35000, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0, | |
1258 | + SYSC_MODULE_QUIRK_WDT | SYSC_QUIRK_SWSUP_SIDLE), | |
1251 | 1259 | |
1252 | 1260 | #ifdef DEBUG |
1253 | 1261 | SYSC_QUIRK("adc", 0, 0, 0x10, -1, 0x47300001, 0xffffffff, 0), |
1254 | 1262 | |
1255 | 1263 | |
... | ... | @@ -1440,14 +1448,14 @@ |
1440 | 1448 | !(val & 0x10), 100, |
1441 | 1449 | MAX_MODULE_SOFTRESET_WAIT); |
1442 | 1450 | if (error) |
1443 | - dev_warn(ddata->dev, "wdt disable spr failed\n"); | |
1451 | + dev_warn(ddata->dev, "wdt disable step1 failed\n"); | |
1444 | 1452 | |
1445 | - sysc_write(ddata, wps, 0x5555); | |
1453 | + sysc_write(ddata, spr, 0x5555); | |
1446 | 1454 | error = readl_poll_timeout(ddata->module_va + wps, val, |
1447 | 1455 | !(val & 0x10), 100, |
1448 | 1456 | MAX_MODULE_SOFTRESET_WAIT); |
1449 | 1457 | if (error) |
1450 | - dev_warn(ddata->dev, "wdt disable wps failed\n"); | |
1458 | + dev_warn(ddata->dev, "wdt disable step2 failed\n"); | |
1451 | 1459 | } |
1452 | 1460 | |
1453 | 1461 | static void sysc_init_module_quirks(struct sysc *ddata) |
1454 | 1462 | |
... | ... | @@ -1471,8 +1479,10 @@ |
1471 | 1479 | if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_SGX) |
1472 | 1480 | ddata->module_enable_quirk = sysc_module_enable_quirk_sgx; |
1473 | 1481 | |
1474 | - if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_WDT) | |
1482 | + if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_WDT) { | |
1475 | 1483 | ddata->reset_done_quirk = sysc_reset_done_quirk_wdt; |
1484 | + ddata->module_disable_quirk = sysc_reset_done_quirk_wdt; | |
1485 | + } | |
1476 | 1486 | } |
1477 | 1487 | |
1478 | 1488 | static int sysc_clockdomain_init(struct sysc *ddata) |