brcm47xx: fix cpu clock detection on ASUS WL-520gU
[openwrt.git] / target / linux / brcm47xx / patches-3.6 / 551-ssb-add-methods-for-watchdog-driver.patch
1 --- a/drivers/ssb/driver_chipcommon.c
2 +++ b/drivers/ssb/driver_chipcommon.c
3 @@ -4,6 +4,7 @@
4   *
5   * Copyright 2005, Broadcom Corporation
6   * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
7 + * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
8   *
9   * Licensed under the GNU/GPL. See COPYING for details.
10   */
11 @@ -12,6 +13,7 @@
12  #include <linux/ssb/ssb_regs.h>
13  #include <linux/export.h>
14  #include <linux/pci.h>
15 +#include <linux/bcm47xx_wdt.h>
16  
17  #include "ssb_private.h"
18  
19 @@ -306,6 +308,43 @@ static u32 ssb_chipco_watchdog_get_max_t
20                 return (1 << nb) - 1;
21  }
22  
23 +u32 ssb_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks)
24 +{
25 +       struct ssb_chipcommon *cc = bcm47xx_wdt_get_drvdata(wdt);
26 +
27 +       if (cc->dev->bus->bustype != SSB_BUSTYPE_SSB)
28 +               return 0;
29 +
30 +       return ssb_chipco_watchdog_timer_set(cc, ticks);
31 +}
32 +
33 +u32 ssb_chipco_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms)
34 +{
35 +       struct ssb_chipcommon *cc = bcm47xx_wdt_get_drvdata(wdt);
36 +       u32 ticks;
37 +
38 +       if (cc->dev->bus->bustype != SSB_BUSTYPE_SSB)
39 +               return 0;
40 +
41 +       ticks = ssb_chipco_watchdog_timer_set(cc, cc->ticks_per_ms * ms);
42 +       return ticks / cc->ticks_per_ms;
43 +}
44 +
45 +static int ssb_chipco_watchdog_ticks_per_ms(struct ssb_chipcommon *cc)
46 +{
47 +       struct ssb_bus *bus = cc->dev->bus;
48 +
49 +       if (cc->capabilities & SSB_CHIPCO_CAP_PMU) {
50 +                       /* based on 32KHz ILP clock */
51 +                       return 32;
52 +       } else {
53 +               if (cc->dev->id.revision < 18)
54 +                       return ssb_clockspeed(bus) / 1000;
55 +               else
56 +                       return ssb_chipco_alp_clock(cc) / 1000;
57 +       }
58 +}
59 +
60  void ssb_chipcommon_init(struct ssb_chipcommon *cc)
61  {
62         if (!cc->dev)
63 @@ -323,6 +362,11 @@ void ssb_chipcommon_init(struct ssb_chip
64         chipco_powercontrol_init(cc);
65         ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST);
66         calc_fast_powerup_delay(cc);
67 +
68 +       if (cc->dev->bus->bustype == SSB_BUSTYPE_SSB) {
69 +               cc->ticks_per_ms = ssb_chipco_watchdog_ticks_per_ms(cc);
70 +               cc->max_timer_ms = ssb_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms;
71 +       }
72  }
73  
74  void ssb_chipco_suspend(struct ssb_chipcommon *cc)
75 @@ -421,7 +465,7 @@ void ssb_chipco_timing_init(struct ssb_c
76  }
77  
78  /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
79 -void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks)
80 +u32 ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks)
81  {
82         u32 maxt;
83         enum ssb_clkmode clkmode;
84 @@ -441,6 +485,7 @@ void ssb_chipco_watchdog_timer_set(struc
85                 /* instant NMI */
86                 chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks);
87         }
88 +       return ticks;
89  }
90  
91  void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value)
92 --- a/drivers/ssb/ssb_private.h
93 +++ b/drivers/ssb/ssb_private.h
94 @@ -3,6 +3,7 @@
95  
96  #include <linux/ssb/ssb.h>
97  #include <linux/types.h>
98 +#include <linux/bcm47xx_wdt.h>
99  
100  
101  #define PFX    "ssb: "
102 @@ -226,4 +227,8 @@ static inline int ssb_sflash_init(struct
103  
104  extern struct platform_device ssb_pflash_dev;
105  
106 +extern u32 ssb_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt,
107 +                                            u32 ticks);
108 +extern u32 ssb_chipco_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms);
109 +
110  #endif /* LINUX_SSB_PRIVATE_H_ */
111 --- a/include/linux/ssb/ssb_driver_chipcommon.h
112 +++ b/include/linux/ssb/ssb_driver_chipcommon.h
113 @@ -607,6 +607,8 @@ struct ssb_chipcommon {
114  #ifdef CONFIG_SSB_SFLASH
115         struct bcm47xx_sflash sflash;
116  #endif
117 +       u32 ticks_per_ms;
118 +       u32 max_timer_ms;
119  };
120  
121  static inline bool ssb_chipco_available(struct ssb_chipcommon *cc)
122 @@ -646,8 +648,7 @@ enum ssb_clkmode {
123  extern void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc,
124                                      enum ssb_clkmode mode);
125  
126 -extern void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc,
127 -                                         u32 ticks);
128 +extern u32 ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks);
129  
130  void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value);
131