Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

watchdog: qcom: fine tune the max timeout value calculation

To determine the max_timeout value, the below calculation is used.

max_timeout = 0x10000000 / clk_rate

cat /sys/devices/platform/soc@0/b017000.watchdog/watchdog/watchdog0/max_timeout
8388

However, this is not valid for all the platforms. IPQ SoCs starting from
IPQ40xx and recent Snapdragron SoCs also has the bark and bite time field
length of 20bits, which can hold max up to 32 seconds if the clk_rate is
32KHz.

If the user tries to configure the timeout more than 32s, then the value
will be truncated and the actual value will not be reflected in the HW.

To avoid this, lets add a variable called max_tick_count in the device data,
which defines max counter value of the WDT controller. Using this, max-timeout
will be calculated in runtime for various WDT contorllers.

With this change, we get the proper max_timeout as below and restricts
the user from configuring the timeout higher than this.

cat /sys/devices/platform/soc@0/b017000.watchdog/watchdog/watchdog0/max_timeout
32

Signed-off-by: Kathiravan Thirumoorthy <quic_kathirav@quicinc.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Link: https://lore.kernel.org/r/20240116-wdt-v2-1-501c7694c3f0@quicinc.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>

authored by

Kathiravan Thirumoorthy and committed by
Wim Van Sebroeck
975e4b27 d2f656dc

+5 -2
+5 -2
drivers/watchdog/qcom-wdt.c
··· 41 41 struct qcom_wdt_match_data { 42 42 const u32 *offset; 43 43 bool pretimeout; 44 + u32 max_tick_count; 44 45 }; 45 46 46 47 struct qcom_wdt { ··· 178 177 static const struct qcom_wdt_match_data match_data_apcs_tmr = { 179 178 .offset = reg_offset_data_apcs_tmr, 180 179 .pretimeout = false, 180 + .max_tick_count = 0x10000000U, 181 181 }; 182 182 183 183 static const struct qcom_wdt_match_data match_data_kpss = { 184 184 .offset = reg_offset_data_kpss, 185 185 .pretimeout = true, 186 + .max_tick_count = 0xFFFFFU, 186 187 }; 187 188 188 189 static int qcom_wdt_probe(struct platform_device *pdev) ··· 239 236 */ 240 237 wdt->rate = clk_get_rate(clk); 241 238 if (wdt->rate == 0 || 242 - wdt->rate > 0x10000000U) { 239 + wdt->rate > data->max_tick_count) { 243 240 dev_err(dev, "invalid clock rate\n"); 244 241 return -EINVAL; 245 242 } ··· 263 260 264 261 wdt->wdd.ops = &qcom_wdt_ops; 265 262 wdt->wdd.min_timeout = 1; 266 - wdt->wdd.max_timeout = 0x10000000U / wdt->rate; 263 + wdt->wdd.max_timeout = data->max_tick_count / wdt->rate; 267 264 wdt->wdd.parent = dev; 268 265 wdt->layout = data->offset; 269 266