diff options
author | Andy Shevchenko <andriy.shevchenko@linux.intel.com> | 2020-04-24 13:56:46 +0300 |
---|---|---|
committer | Andy Shevchenko <andriy.shevchenko@linux.intel.com> | 2020-04-24 13:56:46 +0300 |
commit | 4a65ed6562bcfa58fe0c2ca5855c45268f40d365 (patch) | |
tree | 072de56917dc218b75a4796f4605428959ec0dc9 /drivers/watchdog | |
parent | b5f7311d3a2ed153f26b21c56d54a46d07a4da3f (diff) | |
parent | 2f72d35ea75ee8bf8c9e63fb43d43d5bfb4ac8fd (diff) | |
download | linux-4a65ed6562bcfa58fe0c2ca5855c45268f40d365.tar.xz |
Merge branch 'ib-mfd-x86-usb-watchdog-v5.7'
Merge branch 'ib-mfd-x86-usb-watchdog-v5.7' of
git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git
to avoid conflicts in PDx86.
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/iTCO_wdt.c | 25 | ||||
-rw-r--r-- | drivers/watchdog/intel-mid_wdt.c | 53 |
2 files changed, 56 insertions, 22 deletions
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index e707c4797f76..a370a185a41c 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -64,6 +64,7 @@ #include <linux/uaccess.h> /* For copy_to_user/put_user/... */ #include <linux/io.h> /* For inb/outb/... */ #include <linux/platform_data/itco_wdt.h> +#include <linux/mfd/intel_pmc_bxt.h> #include "iTCO_vendor.h" @@ -233,12 +234,24 @@ static int update_no_reboot_bit_cnt(void *priv, bool set) return val != newval ? -EIO : 0; } +static int update_no_reboot_bit_pmc(void *priv, bool set) +{ + struct intel_pmc_dev *pmc = priv; + u32 bits = PMC_CFG_NO_REBOOT_EN; + u32 value = set ? bits : 0; + + return intel_pmc_gcr_update(pmc, PMC_GCR_PMC_CFG_REG, bits, value); +} + static void iTCO_wdt_no_reboot_bit_setup(struct iTCO_wdt_private *p, - struct itco_wdt_platform_data *pdata) + struct platform_device *pdev, + struct itco_wdt_platform_data *pdata) { - if (pdata->update_no_reboot_bit) { - p->update_no_reboot_bit = pdata->update_no_reboot_bit; - p->no_reboot_priv = pdata->no_reboot_priv; + if (pdata->no_reboot_use_pmc) { + struct intel_pmc_dev *pmc = dev_get_drvdata(pdev->dev.parent); + + p->update_no_reboot_bit = update_no_reboot_bit_pmc; + p->no_reboot_priv = pmc; return; } @@ -478,14 +491,14 @@ static int iTCO_wdt_probe(struct platform_device *pdev) return -ENODEV; } - iTCO_wdt_no_reboot_bit_setup(p, pdata); + iTCO_wdt_no_reboot_bit_setup(p, pdev, pdata); /* * Get the Memory-Mapped GCS or PMC register, we need it for the * NO_REBOOT flag (TCO v2 and v3). */ if (p->iTCO_version >= 2 && p->iTCO_version < 6 && - !pdata->update_no_reboot_bit) { + !pdata->no_reboot_use_pmc) { p->gcs_pmc_res = platform_get_resource(pdev, IORESOURCE_MEM, ICH_RES_MEM_GCS_PMC); diff --git a/drivers/watchdog/intel-mid_wdt.c b/drivers/watchdog/intel-mid_wdt.c index 470213abfd3d..1ae03b64ef8b 100644 --- a/drivers/watchdog/intel-mid_wdt.c +++ b/drivers/watchdog/intel-mid_wdt.c @@ -33,14 +33,24 @@ enum { SCU_WATCHDOG_KEEPALIVE, }; -static inline int wdt_command(int sub, u32 *in, int inlen) +struct mid_wdt { + struct watchdog_device wd; + struct device *dev; + struct intel_scu_ipc_dev *scu; +}; + +static inline int +wdt_command(struct mid_wdt *mid, int sub, const void *in, size_t inlen, size_t size) { - return intel_scu_ipc_command(IPC_WATCHDOG, sub, in, inlen, NULL, 0); + struct intel_scu_ipc_dev *scu = mid->scu; + + return intel_scu_ipc_dev_command_with_size(scu, IPC_WATCHDOG, sub, in, + inlen, size, NULL, 0); } static int wdt_start(struct watchdog_device *wd) { - struct device *dev = watchdog_get_drvdata(wd); + struct mid_wdt *mid = watchdog_get_drvdata(wd); int ret, in_size; int timeout = wd->timeout; struct ipc_wd_start { @@ -49,38 +59,41 @@ static int wdt_start(struct watchdog_device *wd) } ipc_wd_start = { timeout - MID_WDT_PRETIMEOUT, timeout }; /* - * SCU expects the input size for watchdog IPC to - * be based on 4 bytes + * SCU expects the input size for watchdog IPC to be 2 which is the + * size of the structure in dwords. SCU IPC normally takes bytes + * but this is a special case where we specify size to be different + * than inlen. */ in_size = DIV_ROUND_UP(sizeof(ipc_wd_start), 4); - ret = wdt_command(SCU_WATCHDOG_START, (u32 *)&ipc_wd_start, in_size); + ret = wdt_command(mid, SCU_WATCHDOG_START, &ipc_wd_start, + sizeof(ipc_wd_start), in_size); if (ret) - dev_crit(dev, "error starting watchdog: %d\n", ret); + dev_crit(mid->dev, "error starting watchdog: %d\n", ret); return ret; } static int wdt_ping(struct watchdog_device *wd) { - struct device *dev = watchdog_get_drvdata(wd); + struct mid_wdt *mid = watchdog_get_drvdata(wd); int ret; - ret = wdt_command(SCU_WATCHDOG_KEEPALIVE, NULL, 0); + ret = wdt_command(mid, SCU_WATCHDOG_KEEPALIVE, NULL, 0, 0); if (ret) - dev_crit(dev, "Error executing keepalive: %d\n", ret); + dev_crit(mid->dev, "Error executing keepalive: %d\n", ret); return ret; } static int wdt_stop(struct watchdog_device *wd) { - struct device *dev = watchdog_get_drvdata(wd); + struct mid_wdt *mid = watchdog_get_drvdata(wd); int ret; - ret = wdt_command(SCU_WATCHDOG_STOP, NULL, 0); + ret = wdt_command(mid, SCU_WATCHDOG_STOP, NULL, 0, 0); if (ret) - dev_crit(dev, "Error stopping watchdog: %d\n", ret); + dev_crit(mid->dev, "Error stopping watchdog: %d\n", ret); return ret; } @@ -110,6 +123,7 @@ static int mid_wdt_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct watchdog_device *wdt_dev; struct intel_mid_wdt_pdata *pdata = dev->platform_data; + struct mid_wdt *mid; int ret; if (!pdata) { @@ -123,10 +137,13 @@ static int mid_wdt_probe(struct platform_device *pdev) return ret; } - wdt_dev = devm_kzalloc(dev, sizeof(*wdt_dev), GFP_KERNEL); - if (!wdt_dev) + mid = devm_kzalloc(dev, sizeof(*mid), GFP_KERNEL); + if (!mid) return -ENOMEM; + mid->dev = dev; + wdt_dev = &mid->wd; + wdt_dev->info = &mid_wdt_info; wdt_dev->ops = &mid_wdt_ops; wdt_dev->min_timeout = MID_WDT_TIMEOUT_MIN; @@ -135,7 +152,7 @@ static int mid_wdt_probe(struct platform_device *pdev) wdt_dev->parent = dev; watchdog_set_nowayout(wdt_dev, WATCHDOG_NOWAYOUT); - watchdog_set_drvdata(wdt_dev, dev); + watchdog_set_drvdata(wdt_dev, mid); ret = devm_request_irq(dev, pdata->irq, mid_wdt_irq, IRQF_SHARED | IRQF_NO_SUSPEND, "watchdog", @@ -145,6 +162,10 @@ static int mid_wdt_probe(struct platform_device *pdev) return ret; } + mid->scu = devm_intel_scu_ipc_dev_get(dev); + if (!mid->scu) + return -EPROBE_DEFER; + /* * The firmware followed by U-Boot leaves the watchdog running * with the default threshold which may vary. When we get here |