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