aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>2017-04-09 18:00:19 -0400
committerAndy Shevchenko <andriy.shevchenko@linux.intel.com>2017-04-28 14:51:28 -0400
commit140c91b26ebc48d80c6ac3ef06953b17d7fb3785 (patch)
tree9e76be258e33798e3582fc34878a7ef31f7db4eb
parentf583a884afecb16fcb8200ebb9956ea369aff57f (diff)
watchdog: iTCO_wdt: Add PMC specific noreboot update api
In some SoCs, setting noreboot bit needs modification to PMC GC registers. But not all PMC drivers allow other drivers to memory map their GC region. This could create mem request conflict in watchdog driver. So this patch adds facility to allow PMC drivers to pass noreboot update function to watchdog drivers via platform data. Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Acked-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-rw-r--r--drivers/watchdog/iTCO_wdt.c25
-rw-r--r--include/linux/platform_data/itco_wdt.h4
2 files changed, 22 insertions, 7 deletions
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index a62993381c52..347f0389b089 100644
--- a/drivers/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -106,6 +106,8 @@ struct iTCO_wdt_private {
106 struct pci_dev *pci_dev; 106 struct pci_dev *pci_dev;
107 /* whether or not the watchdog has been suspended */ 107 /* whether or not the watchdog has been suspended */
108 bool suspended; 108 bool suspended;
109 /* no reboot API private data */
110 void *no_reboot_priv;
109 /* no reboot update function pointer */ 111 /* no reboot update function pointer */
110 int (*update_no_reboot_bit)(void *p, bool set); 112 int (*update_no_reboot_bit)(void *p, bool set);
111}; 113};
@@ -217,14 +219,23 @@ static int update_no_reboot_bit_mem(void *priv, bool set)
217 return 0; 219 return 0;
218} 220}
219 221
220static void iTCO_wdt_no_reboot_bit_setup(struct iTCO_wdt_private *p) 222static void iTCO_wdt_no_reboot_bit_setup(struct iTCO_wdt_private *p,
223 struct itco_wdt_platform_data *pdata)
221{ 224{
225 if (pdata->update_no_reboot_bit) {
226 p->update_no_reboot_bit = pdata->update_no_reboot_bit;
227 p->no_reboot_priv = pdata->no_reboot_priv;
228 return;
229 }
230
222 if (p->iTCO_version >= 2) 231 if (p->iTCO_version >= 2)
223 p->update_no_reboot_bit = update_no_reboot_bit_mem; 232 p->update_no_reboot_bit = update_no_reboot_bit_mem;
224 else if (p->iTCO_version == 1) 233 else if (p->iTCO_version == 1)
225 p->update_no_reboot_bit = update_no_reboot_bit_pci; 234 p->update_no_reboot_bit = update_no_reboot_bit_pci;
226 else 235 else
227 p->update_no_reboot_bit = update_no_reboot_bit_def; 236 p->update_no_reboot_bit = update_no_reboot_bit_def;
237
238 p->no_reboot_priv = p;
228} 239}
229 240
230static int iTCO_wdt_start(struct watchdog_device *wd_dev) 241static int iTCO_wdt_start(struct watchdog_device *wd_dev)
@@ -237,7 +248,7 @@ static int iTCO_wdt_start(struct watchdog_device *wd_dev)
237 iTCO_vendor_pre_start(p->smi_res, wd_dev->timeout); 248 iTCO_vendor_pre_start(p->smi_res, wd_dev->timeout);
238 249
239 /* disable chipset's NO_REBOOT bit */ 250 /* disable chipset's NO_REBOOT bit */
240 if (p->update_no_reboot_bit(p, false)) { 251 if (p->update_no_reboot_bit(p->no_reboot_priv, false)) {
241 spin_unlock(&p->io_lock); 252 spin_unlock(&p->io_lock);
242 pr_err("failed to reset NO_REBOOT flag, reboot disabled by hardware/BIOS\n"); 253 pr_err("failed to reset NO_REBOOT flag, reboot disabled by hardware/BIOS\n");
243 return -EIO; 254 return -EIO;
@@ -278,7 +289,7 @@ static int iTCO_wdt_stop(struct watchdog_device *wd_dev)
278 val = inw(TCO1_CNT(p)); 289 val = inw(TCO1_CNT(p));
279 290
280 /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ 291 /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
281 p->update_no_reboot_bit(p, true); 292 p->update_no_reboot_bit(p->no_reboot_priv, true);
282 293
283 spin_unlock(&p->io_lock); 294 spin_unlock(&p->io_lock);
284 295
@@ -443,13 +454,13 @@ static int iTCO_wdt_probe(struct platform_device *pdev)
443 p->iTCO_version = pdata->version; 454 p->iTCO_version = pdata->version;
444 p->pci_dev = to_pci_dev(dev->parent); 455 p->pci_dev = to_pci_dev(dev->parent);
445 456
446 iTCO_wdt_no_reboot_bit_setup(p); 457 iTCO_wdt_no_reboot_bit_setup(p, pdata);
447 458
448 /* 459 /*
449 * Get the Memory-Mapped GCS or PMC register, we need it for the 460 * Get the Memory-Mapped GCS or PMC register, we need it for the
450 * NO_REBOOT flag (TCO v2 and v3). 461 * NO_REBOOT flag (TCO v2 and v3).
451 */ 462 */
452 if (p->iTCO_version >= 2) { 463 if (p->iTCO_version >= 2 && !pdata->update_no_reboot_bit) {
453 p->gcs_pmc_res = platform_get_resource(pdev, 464 p->gcs_pmc_res = platform_get_resource(pdev,
454 IORESOURCE_MEM, 465 IORESOURCE_MEM,
455 ICH_RES_MEM_GCS_PMC); 466 ICH_RES_MEM_GCS_PMC);
@@ -459,14 +470,14 @@ static int iTCO_wdt_probe(struct platform_device *pdev)
459 } 470 }
460 471
461 /* Check chipset's NO_REBOOT bit */ 472 /* Check chipset's NO_REBOOT bit */
462 if (p->update_no_reboot_bit(p, false) && 473 if (p->update_no_reboot_bit(p->no_reboot_priv, false) &&
463 iTCO_vendor_check_noreboot_on()) { 474 iTCO_vendor_check_noreboot_on()) {
464 pr_info("unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n"); 475 pr_info("unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n");
465 return -ENODEV; /* Cannot reset NO_REBOOT bit */ 476 return -ENODEV; /* Cannot reset NO_REBOOT bit */
466 } 477 }
467 478
468 /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ 479 /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
469 p->update_no_reboot_bit(p, true); 480 p->update_no_reboot_bit(p->no_reboot_priv, true);
470 481
471 /* The TCO logic uses the TCO_EN bit in the SMI_EN register */ 482 /* The TCO logic uses the TCO_EN bit in the SMI_EN register */
472 if (!devm_request_region(dev, p->smi_res->start, 483 if (!devm_request_region(dev, p->smi_res->start,
diff --git a/include/linux/platform_data/itco_wdt.h b/include/linux/platform_data/itco_wdt.h
index f16542c77ff7..0e95527edf25 100644
--- a/include/linux/platform_data/itco_wdt.h
+++ b/include/linux/platform_data/itco_wdt.h
@@ -14,6 +14,10 @@
14struct itco_wdt_platform_data { 14struct itco_wdt_platform_data {
15 char name[32]; 15 char name[32];
16 unsigned int version; 16 unsigned int version;
17 /* private data to be passed to update_no_reboot_bit API */
18 void *no_reboot_priv;
19 /* pointer for platform specific no reboot update function */
20 int (*update_no_reboot_bit)(void *priv, bool set);
17}; 21};
18 22
19#endif /* _ITCO_WDT_H_ */ 23#endif /* _ITCO_WDT_H_ */