mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
watchdog: qcom: add support to get the bootstatus from IMEM
When the system boots up after a watchdog reset, the EXPIRED_STATUS bit in the WDT_STS register is cleared. To identify if the system was restarted due to WDT expiry, XBL update the information in the IMEM region. Update the driver to read the restart reason from IMEM and populate the bootstatus accordingly. With the CONFIG_WATCHDOG_SYSFS enabled, user can extract the information as below: cat /sys/devices/platform/soc@0/f410000.watchdog/watchdog/watchdog0/bootstatus 32 For backward compatibility, keep the EXPIRED_STATUS bit check. Add a new function qcom_wdt_get_bootstatus() to read the restart reason from IMEM. Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com> Signed-off-by: Kathiravan Thirumoorthy <kathiravan.thirumoorthy@oss.qualcomm.com> Link: https://lore.kernel.org/r/20260408-wdt_reset_reason-v10-2-caf66786329f@oss.qualcomm.com Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
parent
ea333d1991
commit
158dd300b0
|
|
@ -9,6 +9,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/watchdog.h>
|
||||
|
||||
|
|
@ -42,6 +43,7 @@ struct qcom_wdt_match_data {
|
|||
const u32 *offset;
|
||||
bool pretimeout;
|
||||
u32 max_tick_count;
|
||||
u32 wdt_reason_val;
|
||||
};
|
||||
|
||||
struct qcom_wdt {
|
||||
|
|
@ -185,6 +187,7 @@ static const struct qcom_wdt_match_data match_data_ipq5424 = {
|
|||
.offset = reg_offset_data_kpss,
|
||||
.pretimeout = true,
|
||||
.max_tick_count = 0xFFFFFU,
|
||||
.wdt_reason_val = 5,
|
||||
};
|
||||
|
||||
static const struct qcom_wdt_match_data match_data_kpss = {
|
||||
|
|
@ -193,6 +196,40 @@ static const struct qcom_wdt_match_data match_data_kpss = {
|
|||
.max_tick_count = 0xFFFFFU,
|
||||
};
|
||||
|
||||
static int qcom_wdt_get_bootstatus(struct device *dev, struct qcom_wdt *wdt,
|
||||
u32 val)
|
||||
{
|
||||
struct device_node *imem;
|
||||
struct resource res;
|
||||
void __iomem *addr;
|
||||
int ret;
|
||||
|
||||
imem = of_parse_phandle(dev->of_node, "sram", 0);
|
||||
if (!imem) {
|
||||
/* Read the EXPIRED_STATUS bit as a fallback */
|
||||
if (readl(wdt_addr(wdt, WDT_STS)) & 1)
|
||||
wdt->wdd.bootstatus = WDIOF_CARDRESET;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = of_address_to_resource(imem, 0, &res);
|
||||
of_node_put(imem);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
addr = ioremap(res.start, resource_size(&res));
|
||||
if (!addr)
|
||||
return -ENOMEM;
|
||||
|
||||
if (readl(addr) == val)
|
||||
wdt->wdd.bootstatus = WDIOF_CARDRESET;
|
||||
|
||||
iounmap(addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_wdt_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
|
|
@ -273,8 +310,9 @@ static int qcom_wdt_probe(struct platform_device *pdev)
|
|||
wdt->wdd.parent = dev;
|
||||
wdt->layout = data->offset;
|
||||
|
||||
if (readl(wdt_addr(wdt, WDT_STS)) & 1)
|
||||
wdt->wdd.bootstatus = WDIOF_CARDRESET;
|
||||
ret = qcom_wdt_get_bootstatus(dev, wdt, data->wdt_reason_val);
|
||||
if (ret)
|
||||
dev_err(dev, "failed to get the bootstatus, %d\n", ret);
|
||||
|
||||
/*
|
||||
* If 'timeout-sec' unspecified in devicetree, assume a 30 second
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user