ssb: register watchdog driver
authorHauke Mehrtens <hauke@hauke-m.de>
Wed, 5 Dec 2012 17:46:08 +0000 (18:46 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 6 Dec 2012 19:58:58 +0000 (14:58 -0500)
Register the watchdog driver to the system if it is a SoC. Using the
watchdog on a non SoC device, like a PCI card, will make the PCI
card die when the timeout expired, but starting it again is not
supported by ssb.

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/ssb/embedded.c
drivers/ssb/main.c
drivers/ssb/ssb_private.h
include/linux/ssb/ssb.h

index 9ef124f9ee2d4e73f20db392e45b29b7c558ec00..bb18d76f9f2c39668dc0fa80ed854aa16fbece7d 100644 (file)
@@ -4,11 +4,13 @@
  *
  * Copyright 2005-2008, Broadcom Corporation
  * Copyright 2006-2008, Michael Buesch <m@bues.ch>
+ * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
  *
  * Licensed under the GNU/GPL. See COPYING for details.
  */
 
 #include <linux/export.h>
+#include <linux/platform_device.h>
 #include <linux/ssb/ssb.h>
 #include <linux/ssb/ssb_embedded.h>
 #include <linux/ssb/ssb_driver_pci.h>
@@ -32,6 +34,39 @@ int ssb_watchdog_timer_set(struct ssb_bus *bus, u32 ticks)
 }
 EXPORT_SYMBOL(ssb_watchdog_timer_set);
 
+int ssb_watchdog_register(struct ssb_bus *bus)
+{
+       struct bcm47xx_wdt wdt = {};
+       struct platform_device *pdev;
+
+       if (ssb_chipco_available(&bus->chipco)) {
+               wdt.driver_data = &bus->chipco;
+               wdt.timer_set = ssb_chipco_watchdog_timer_set_wdt;
+               wdt.timer_set_ms = ssb_chipco_watchdog_timer_set_ms;
+               wdt.max_timer_ms = bus->chipco.max_timer_ms;
+       } else if (ssb_extif_available(&bus->extif)) {
+               wdt.driver_data = &bus->extif;
+               wdt.timer_set = ssb_extif_watchdog_timer_set_wdt;
+               wdt.timer_set_ms = ssb_extif_watchdog_timer_set_ms;
+               wdt.max_timer_ms = SSB_EXTIF_WATCHDOG_MAX_TIMER_MS;
+       } else {
+               return -ENODEV;
+       }
+
+       pdev = platform_device_register_data(NULL, "bcm47xx-wdt",
+                                            bus->busnumber, &wdt,
+                                            sizeof(wdt));
+       if (IS_ERR(pdev)) {
+               ssb_dprintk(KERN_INFO PFX
+                           "can not register watchdog device, err: %li\n",
+                           PTR_ERR(pdev));
+               return PTR_ERR(pdev);
+       }
+
+       bus->watchdog = pdev;
+       return 0;
+}
+
 u32 ssb_gpio_in(struct ssb_bus *bus, u32 mask)
 {
        unsigned long flags;
index df0f145c22fc80c175d277cca0f68647fbfd90fd..58c7da29a37ccda27f8e123d4a76af42cf2b3ab7 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/ssb/ssb.h>
 #include <linux/ssb/ssb_regs.h>
 #include <linux/ssb/ssb_driver_gige.h>
@@ -433,6 +434,11 @@ static void ssb_devices_unregister(struct ssb_bus *bus)
                if (sdev->dev)
                        device_unregister(sdev->dev);
        }
+
+#ifdef CONFIG_SSB_EMBEDDED
+       if (bus->bustype == SSB_BUSTYPE_SSB)
+               platform_device_unregister(bus->watchdog);
+#endif
 }
 
 void ssb_bus_unregister(struct ssb_bus *bus)
@@ -561,6 +567,8 @@ static int __devinit ssb_attach_queued_buses(void)
                if (err)
                        goto error;
                ssb_pcicore_init(&bus->pcicore);
+               if (bus->bustype == SSB_BUSTYPE_SSB)
+                       ssb_watchdog_register(bus);
                ssb_bus_may_powerdown(bus);
 
                err = ssb_devices_register(bus);
index 50ea0287777771c4119c98128563dc450b13a24d..8942db1d855af8ef69c6f3f4d639f4efe414fdd1 100644 (file)
@@ -232,4 +232,14 @@ static inline u32 ssb_extif_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt,
        return 0;
 }
 #endif
+
+#ifdef CONFIG_SSB_EMBEDDED
+extern int ssb_watchdog_register(struct ssb_bus *bus);
+#else /* CONFIG_SSB_EMBEDDED */
+static inline int ssb_watchdog_register(struct ssb_bus *bus)
+{
+       return 0;
+}
+#endif /* CONFIG_SSB_EMBEDDED */
+
 #endif /* LINUX_SSB_PRIVATE_H_ */
index bb674c02f3060c3917763dfe2bae1f8bd3559a4d..1f64e3f1f22b52f5d1db2f57bfb69c4a80bca0e8 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/pci.h>
 #include <linux/mod_devicetable.h>
 #include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
 
 #include <linux/ssb/ssb_regs.h>
 
@@ -432,6 +433,7 @@ struct ssb_bus {
 #ifdef CONFIG_SSB_EMBEDDED
        /* Lock for GPIO register access. */
        spinlock_t gpio_lock;
+       struct platform_device *watchdog;
 #endif /* EMBEDDED */
 
        /* Internal-only stuff follows. Do not touch. */