brcm47xx: update bcma and ssb to master-2011-07-21
[librecmc/librecmc.git] / target / linux / brcm47xx / patches-3.0 / 0003-bcma-add-functions-to-scan-cores-needed-on-SoCs.patch
1 From beb36a1a49227ca6c5778a667aefc8cd3fd56a4f Mon Sep 17 00:00:00 2001
2 From: Hauke Mehrtens <hauke@hauke-m.de>
3 Date: Sat, 18 Jun 2011 14:30:55 +0200
4 Subject: [PATCH 03/22] bcma: add functions to scan cores needed on SoCs
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 The chip common and mips core have to be setup early in the boot
10 process to get the cpu clock.
11 bcma_bus_early_register() gets pointers to some space to store the core
12 data and searches for the chip common and mips core and initializes
13 chip common. After that was done and the kernel is out of early boot we
14 just have to run bcma_bus_register() and it will search for the other
15 cores, initialize and register them.
16 The cores are getting the same numbers as before.
17
18 Acked-by: Rafał Miłecki <zajec5@gmail.com>
19 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
20 ---
21  drivers/bcma/bcma_private.h                 |    7 ++
22  drivers/bcma/driver_chipcommon.c            |    5 ++
23  drivers/bcma/driver_pci.c                   |    5 ++
24  drivers/bcma/main.c                         |   46 +++++++++++++
25  drivers/bcma/scan.c                         |   95 +++++++++++++++++++++++++--
26  include/linux/bcma/bcma.h                   |    1 +
27  include/linux/bcma/bcma_driver_chipcommon.h |    1 +
28  7 files changed, 154 insertions(+), 6 deletions(-)
29
30 --- a/drivers/bcma/bcma_private.h
31 +++ b/drivers/bcma/bcma_private.h
32 @@ -15,9 +15,16 @@ struct bcma_bus;
33  /* main.c */
34  int bcma_bus_register(struct bcma_bus *bus);
35  void bcma_bus_unregister(struct bcma_bus *bus);
36 +int __init bcma_bus_early_register(struct bcma_bus *bus,
37 +                                  struct bcma_device *core_cc,
38 +                                  struct bcma_device *core_mips);
39  
40  /* scan.c */
41  int bcma_bus_scan(struct bcma_bus *bus);
42 +int __init bcma_bus_scan_early(struct bcma_bus *bus,
43 +                              struct bcma_device_id *match,
44 +                              struct bcma_device *core);
45 +void bcma_init_bus(struct bcma_bus *bus);
46  
47  /* sprom.c */
48  int bcma_sprom_get(struct bcma_bus *bus);
49 --- a/drivers/bcma/driver_chipcommon.c
50 +++ b/drivers/bcma/driver_chipcommon.c
51 @@ -26,6 +26,9 @@ void bcma_core_chipcommon_init(struct bc
52         u32 leddc_on = 10;
53         u32 leddc_off = 90;
54  
55 +       if (cc->setup_done)
56 +               return;
57 +
58         if (cc->core->id.rev >= 11)
59                 cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
60         cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
61 @@ -52,6 +55,8 @@ void bcma_core_chipcommon_init(struct bc
62                         ((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) |
63                          (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT)));
64         }
65 +
66 +       cc->setup_done = true;
67  }
68  
69  /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
70 --- a/drivers/bcma/driver_pci.c
71 +++ b/drivers/bcma/driver_pci.c
72 @@ -187,6 +187,9 @@ static bool bcma_core_pci_is_in_hostmode
73  
74  void bcma_core_pci_init(struct bcma_drv_pci *pc)
75  {
76 +       if (pc->setup_done)
77 +               return;
78 +
79         if (bcma_core_pci_is_in_hostmode(pc)) {
80  #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
81                 bcma_core_pci_hostmode_init(pc);
82 @@ -196,6 +199,8 @@ void bcma_core_pci_init(struct bcma_drv_
83         } else {
84                 bcma_core_pci_clientmode_init(pc);
85         }
86 +
87 +       pc->setup_done = true;
88  }
89  
90  int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
91 --- a/drivers/bcma/main.c
92 +++ b/drivers/bcma/main.c
93 @@ -169,6 +169,52 @@ void bcma_bus_unregister(struct bcma_bus
94         bcma_unregister_cores(bus);
95  }
96  
97 +int __init bcma_bus_early_register(struct bcma_bus *bus,
98 +                                  struct bcma_device *core_cc,
99 +                                  struct bcma_device *core_mips)
100 +{
101 +       int err;
102 +       struct bcma_device *core;
103 +       struct bcma_device_id match;
104 +
105 +       bcma_init_bus(bus);
106 +
107 +       match.manuf = BCMA_MANUF_BCM;
108 +       match.id = BCMA_CORE_CHIPCOMMON;
109 +       match.class = BCMA_CL_SIM;
110 +       match.rev = BCMA_ANY_REV;
111 +
112 +       /* Scan for chip common core */
113 +       err = bcma_bus_scan_early(bus, &match, core_cc);
114 +       if (err) {
115 +               pr_err("Failed to scan for common core: %d\n", err);
116 +               return -1;
117 +       }
118 +
119 +       match.manuf = BCMA_MANUF_MIPS;
120 +       match.id = BCMA_CORE_MIPS_74K;
121 +       match.class = BCMA_CL_SIM;
122 +       match.rev = BCMA_ANY_REV;
123 +
124 +       /* Scan for mips core */
125 +       err = bcma_bus_scan_early(bus, &match, core_mips);
126 +       if (err) {
127 +               pr_err("Failed to scan for mips core: %d\n", err);
128 +               return -1;
129 +       }
130 +
131 +       /* Init CC core */
132 +       core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
133 +       if (core) {
134 +               bus->drv_cc.core = core;
135 +               bcma_core_chipcommon_init(&bus->drv_cc);
136 +       }
137 +
138 +       pr_info("Early bus registered\n");
139 +
140 +       return 0;
141 +}
142 +
143  int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
144  {
145         drv->drv.name = drv->name;
146 --- a/drivers/bcma/scan.c
147 +++ b/drivers/bcma/scan.c
148 @@ -200,7 +200,20 @@ static s32 bcma_erom_get_addr_desc(struc
149         return addrl;
150  }
151  
152 +static struct bcma_device *bcma_find_core_by_index(struct bcma_bus *bus,
153 +                                                  u16 index)
154 +{
155 +       struct bcma_device *core;
156 +
157 +       list_for_each_entry(core, &bus->cores, list) {
158 +               if (core->core_index == index)
159 +                       return core;
160 +       }
161 +       return NULL;
162 +}
163 +
164  static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
165 +                             struct bcma_device_id *match, int core_num,
166                               struct bcma_device *core)
167  {
168         s32 tmp;
169 @@ -251,6 +264,21 @@ static int bcma_get_next_core(struct bcm
170                 return -ENXIO;
171         }
172  
173 +       if (bcma_find_core_by_index(bus, core_num)) {
174 +               bcma_erom_skip_component(bus, eromptr);
175 +               return -ENODEV;
176 +       }
177 +
178 +       if (match && ((match->manuf != BCMA_ANY_MANUF &&
179 +             match->manuf != core->id.manuf) ||
180 +            (match->id != BCMA_ANY_ID && match->id != core->id.id) ||
181 +            (match->rev != BCMA_ANY_REV && match->rev != core->id.rev) ||
182 +            (match->class != BCMA_ANY_CLASS && match->class != core->id.class)
183 +           )) {
184 +               bcma_erom_skip_component(bus, eromptr);
185 +               return -ENODEV;
186 +       }
187 +
188         /* get & parse master ports */
189         for (i = 0; i < ports[0]; i++) {
190                 u32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr);
191 @@ -312,10 +340,13 @@ static int bcma_get_next_core(struct bcm
192         return 0;
193  }
194  
195 -static void bcma_init_bus(struct bcma_bus *bus)
196 +void bcma_init_bus(struct bcma_bus *bus)
197  {
198         s32 tmp;
199  
200 +       if (bus->init_done)
201 +               return;
202 +
203         INIT_LIST_HEAD(&bus->cores);
204         bus->nr_cores = 0;
205  
206 @@ -325,6 +356,7 @@ static void bcma_init_bus(struct bcma_bu
207         bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
208         bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
209         bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
210 +       bus->init_done = true;
211  }
212  
213  int bcma_bus_scan(struct bcma_bus *bus)
214 @@ -332,7 +364,7 @@ int bcma_bus_scan(struct bcma_bus *bus)
215         u32 erombase;
216         u32 __iomem *eromptr, *eromend;
217  
218 -       int err;
219 +       int err, core_num = 0;
220  
221         bcma_init_bus(bus);
222  
223 @@ -349,23 +381,74 @@ int bcma_bus_scan(struct bcma_bus *bus)
224                 INIT_LIST_HEAD(&core->list);
225                 core->bus = bus;
226  
227 -               err = bcma_get_next_core(bus, &eromptr, core);
228 -               if (err == -ENXIO)
229 +               err = bcma_get_next_core(bus, &eromptr, NULL, core_num, core);
230 +               if (err == -ENODEV) {
231 +                       core_num++;
232 +                       continue;
233 +               } else if (err == -ENXIO)
234                         continue;
235                 else if (err == -ESPIPE)
236                         break;
237                 else if (err < 0)
238                         return err;
239  
240 +               core->core_index = core_num++;
241 +               bus->nr_cores++;
242 +
243                 pr_info("Core %d found: %s "
244                         "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
245 -                       bus->nr_cores, bcma_device_name(&core->id),
246 +                       core->core_index, bcma_device_name(&core->id),
247                         core->id.manuf, core->id.id, core->id.rev,
248                         core->id.class);
249  
250 -               core->core_index = bus->nr_cores++;
251                 list_add(&core->list, &bus->cores);
252         }
253  
254         return 0;
255  }
256 +
257 +int __init bcma_bus_scan_early(struct bcma_bus *bus,
258 +                              struct bcma_device_id *match,
259 +                              struct bcma_device *core)
260 +{
261 +       u32 erombase;
262 +       u32 __iomem *eromptr, *eromend;
263 +
264 +       int err, core_num = 0;
265 +
266 +       erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
267 +       eromptr = bus->mmio;
268 +       eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
269 +
270 +       bcma_scan_switch_core(bus, erombase);
271 +
272 +       while (eromptr < eromend) {
273 +               memset(core, 0, sizeof(*core));
274 +               INIT_LIST_HEAD(&core->list);
275 +               core->bus = bus;
276 +
277 +               err = bcma_get_next_core(bus, &eromptr, match, core_num, core);
278 +               if (err == -ENODEV) {
279 +                       core_num++;
280 +                       continue;
281 +               } else if (err == -ENXIO)
282 +                       continue;
283 +               else if (err == -ESPIPE)
284 +                       break;
285 +               else if (err < 0)
286 +                       return err;
287 +
288 +               core->core_index = core_num++;
289 +               bus->nr_cores++;
290 +               pr_info("Core %d found: %s "
291 +                       "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
292 +                       core->core_index, bcma_device_name(&core->id),
293 +                       core->id.manuf, core->id.id, core->id.rev,
294 +                       core->id.class);
295 +
296 +               list_add(&core->list, &bus->cores);
297 +               return 0;
298 +       }
299 +
300 +       return -ENODEV;
301 +}
302 --- a/include/linux/bcma/bcma.h
303 +++ b/include/linux/bcma/bcma.h
304 @@ -190,6 +190,7 @@ struct bcma_bus {
305         struct bcma_device *mapped_core;
306         struct list_head cores;
307         u8 nr_cores;
308 +       u8 init_done:1;
309  
310         struct bcma_drv_cc drv_cc;
311         struct bcma_drv_pci drv_pci;
312 --- a/include/linux/bcma/bcma_driver_chipcommon.h
313 +++ b/include/linux/bcma/bcma_driver_chipcommon.h
314 @@ -252,6 +252,7 @@ struct bcma_drv_cc {
315         u32 status;
316         u32 capabilities;
317         u32 capabilities_ext;
318 +       u8 setup_done:1;
319         /* Fast Powerup Delay constant */
320         u16 fast_pwrup_delay;
321         struct bcma_chipcommon_pmu pmu;