return value;
  }
  
 -void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
 +static u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc)
  {
 -      u32 leddc_on = 10;
 -      u32 leddc_off = 90;
 +      if (cc->capabilities & BCMA_CC_CAP_PMU)
 +              return bcma_pmu_get_alp_clock(cc);
  
 -      if (cc->setup_done)
 +      return 20000000;
 +}
 +
 +static u32 bcma_chipco_watchdog_get_max_timer(struct bcma_drv_cc *cc)
 +{
 +      struct bcma_bus *bus = cc->core->bus;
 +      u32 nb;
 +
 +      if (cc->capabilities & BCMA_CC_CAP_PMU) {
 +              if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706)
 +                      nb = 32;
 +              else if (cc->core->id.rev < 26)
 +                      nb = 16;
 +              else
 +                      nb = (cc->core->id.rev >= 37) ? 32 : 24;
 +      } else {
 +              nb = 28;
 +      }
 +      if (nb == 32)
 +              return 0xffffffff;
 +      else
 +              return (1 << nb) - 1;
 +}
 +
 +static u32 bcma_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt,
 +                                            u32 ticks)
 +{
 +      struct bcma_drv_cc *cc = bcm47xx_wdt_get_drvdata(wdt);
 +
 +      return bcma_chipco_watchdog_timer_set(cc, ticks);
 +}
 +
 +static u32 bcma_chipco_watchdog_timer_set_ms_wdt(struct bcm47xx_wdt *wdt,
 +                                               u32 ms)
 +{
 +      struct bcma_drv_cc *cc = bcm47xx_wdt_get_drvdata(wdt);
 +      u32 ticks;
 +
 +      ticks = bcma_chipco_watchdog_timer_set(cc, cc->ticks_per_ms * ms);
 +      return ticks / cc->ticks_per_ms;
 +}
 +
 +static int bcma_chipco_watchdog_ticks_per_ms(struct bcma_drv_cc *cc)
 +{
 +      struct bcma_bus *bus = cc->core->bus;
 +
 +      if (cc->capabilities & BCMA_CC_CAP_PMU) {
 +              if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706)
 +                      /* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP clock */
 +                      return bcma_chipco_get_alp_clock(cc) / 4000;
 +              else
 +                      /* based on 32KHz ILP clock */
 +                      return 32;
 +      } else {
 +              return bcma_chipco_get_alp_clock(cc) / 1000;
 +      }
 +}
 +
 +int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc)
 +{
 +      struct bcm47xx_wdt wdt = {};
 +      struct platform_device *pdev;
 +
 +      wdt.driver_data = cc;
 +      wdt.timer_set = bcma_chipco_watchdog_timer_set_wdt;
 +      wdt.timer_set_ms = bcma_chipco_watchdog_timer_set_ms_wdt;
 +      wdt.max_timer_ms = bcma_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms;
 +
 +      pdev = platform_device_register_data(NULL, "bcm47xx-wdt",
 +                                           cc->core->bus->num, &wdt,
 +                                           sizeof(wdt));
 +      if (IS_ERR(pdev))
 +              return PTR_ERR(pdev);
 +
 +      cc->watchdog = pdev;
 +
 +      return 0;
 +}
 +
 +void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc)
 +{
 +      if (cc->early_setup_done)
                return;
  
+       spin_lock_init(&cc->gpio_lock);
+ 
        if (cc->core->id.rev >= 11)
                cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
        cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
 
                        bcma_err(bus, "Error registering NAND flash\n");
        }
  #endif
+       err = bcma_gpio_init(&bus->drv_cc);
+       if (err == -ENOTSUPP)
+               bcma_debug(bus, "GPIO driver not activated\n");
+       else if (err)
+               bcma_err(bus, "Error registering GPIO driver: %i\n", err);
  
 +      if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
 +              err = bcma_chipco_watchdog_register(&bus->drv_cc);
 +              if (err)
 +                      bcma_err(bus, "Error registering watchdog driver\n");
 +      }
 +
        return 0;
  }
  
 
        *m = extif_read32(extif, SSB_EXTIF_CLOCK_SB);
  }
  
 -void ssb_extif_watchdog_timer_set(struct ssb_extif *extif,
 -                                u32 ticks)
 +u32 ssb_extif_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks)
  {
 +      struct ssb_extif *extif = bcm47xx_wdt_get_drvdata(wdt);
 +
 +      return ssb_extif_watchdog_timer_set(extif, ticks);
 +}
 +
 +u32 ssb_extif_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms)
 +{
 +      struct ssb_extif *extif = bcm47xx_wdt_get_drvdata(wdt);
 +      u32 ticks = (SSB_EXTIF_WATCHDOG_CLK / 1000) * ms;
 +
 +      ticks = ssb_extif_watchdog_timer_set(extif, ticks);
 +
 +      return (ticks * 1000) / SSB_EXTIF_WATCHDOG_CLK;
 +}
 +
 +u32 ssb_extif_watchdog_timer_set(struct ssb_extif *extif, u32 ticks)
 +{
 +      if (ticks > SSB_EXTIF_WATCHDOG_MAX_TIMER)
 +              ticks = SSB_EXTIF_WATCHDOG_MAX_TIMER;
        extif_write32(extif, SSB_EXTIF_WATCHDOG, ticks);
 +
 +      return ticks;
  }
  
+ void ssb_extif_init(struct ssb_extif *extif)
+ {
+       if (!extif->dev)
+               return; /* We don't have a Extif core */
+       spin_lock_init(&extif->gpio_lock);
+ }
+ 
  u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask)
  {
        return extif_read32(extif, SSB_EXTIF_GPIO_IN) & mask;
 
  /* driver_chipcommon_pmu.c */
  extern u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc);
  extern u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc);
 +extern u32 ssb_pmu_get_alp_clock(struct ssb_chipcommon *cc);
 +
 +extern u32 ssb_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt,
 +                                           u32 ticks);
 +extern u32 ssb_chipco_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms);
 +
 +#ifdef CONFIG_SSB_DRIVER_EXTIF
 +extern u32 ssb_extif_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks);
 +extern u32 ssb_extif_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms);
 +#else
 +static inline u32 ssb_extif_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt,
 +                                                 u32 ticks)
 +{
 +      return 0;
 +}
 +static inline u32 ssb_extif_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt,
 +                                                u32 ms)
 +{
 +      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 */
  
+ #ifdef CONFIG_SSB_DRIVER_EXTIF
+ extern void ssb_extif_init(struct ssb_extif *extif);
+ #else
+ static inline void ssb_extif_init(struct ssb_extif *extif)
+ {
+ }
+ #endif
+ 
+ #ifdef CONFIG_SSB_DRIVER_GPIO
+ extern int ssb_gpio_init(struct ssb_bus *bus);
+ #else /* CONFIG_SSB_DRIVER_GPIO */
+ static inline int ssb_gpio_init(struct ssb_bus *bus)
+ {
+       return -ENOTSUPP;
+ }
+ #endif /* CONFIG_SSB_DRIVER_GPIO */
+ 
  #endif /* LINUX_SSB_PRIVATE_H_ */
 
  #ifndef LINUX_BCMA_DRIVER_CC_H_
  #define LINUX_BCMA_DRIVER_CC_H_
  
 +#include <linux/platform_device.h>
+ #include <linux/gpio.h>
  
  /** ChipCommon core registers. **/
  #define BCMA_CC_ID                    0x0000
        int nr_serial_ports;
        struct bcma_serial_port serial_ports[4];
  #endif /* CONFIG_BCMA_DRIVER_MIPS */
 +      u32 ticks_per_ms;
 +      struct platform_device *watchdog;
+ 
+       /* Lock for GPIO register access. */
+       spinlock_t gpio_lock;
+ #ifdef CONFIG_BCMA_DRIVER_GPIO
+       struct gpio_chip gpio;
+ #endif
  };
  
  /* Register access */
 
  #include <linux/types.h>
  #include <linux/spinlock.h>
  #include <linux/pci.h>
+ #include <linux/gpio.h>
  #include <linux/mod_devicetable.h>
  #include <linux/dma-mapping.h>
 +#include <linux/platform_device.h>
  
  #include <linux/ssb/ssb_regs.h>
  
  #ifdef CONFIG_SSB_EMBEDDED
        /* Lock for GPIO register access. */
        spinlock_t gpio_lock;
 +      struct platform_device *watchdog;
  #endif /* EMBEDDED */
+ #ifdef CONFIG_SSB_DRIVER_GPIO
+       struct gpio_chip gpio;
+ #endif /* DRIVER_GPIO */
  
        /* Internal-only stuff follows. Do not touch. */
        struct list_head list;
 
        u32 status;
        /* Fast Powerup Delay constant */
        u16 fast_pwrup_delay;
+       spinlock_t gpio_lock;
        struct ssb_chipcommon_pmu pmu;
 +      u32 ticks_per_ms;
 +      u32 max_timer_ms;
  };
  
  static inline bool ssb_chipco_available(struct ssb_chipcommon *cc)