1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32#include <linux/module.h>
33#include <linux/config.h>
34#include <linux/list.h>
35#include <linux/miscdevice.h>
36#include <linux/slab.h>
37#include <linux/types.h>
38#include <linux/init.h>
39#include <linux/pm.h>
40#include <linux/bootmem.h>
41#include <asm/io.h>
42#include <asm/ocp.h>
43#include <asm/errno.h>
44#include <asm/rwsem.h>
45#include <asm/semaphore.h>
46
47
48#define DBG(x)
49
50extern int mem_init_done;
51
52extern struct ocp_def core_ocp[];
53
54
55LIST_HEAD(ocp_devices);
56LIST_HEAD(ocp_drivers);
57DECLARE_RWSEM(ocp_devices_sem);
58DECLARE_MUTEX(ocp_drivers_sem);
59
60static int ocp_inited;
61
62
63
64
65
66
67
68
69static int
70ocp_driver_match(struct ocp_driver *drv, struct ocp_device *dev)
71{
72 const struct ocp_device_id *ids = drv->id_table;
73
74 if (!ids)
75 return 0;
76
77 while (ids->vendor || ids->function) {
78 if ((ids->vendor == OCP_ANY_ID
79 || ids->vendor == dev->def->vendor)
80 && (ids->function == OCP_ANY_ID
81 || ids->function == dev->def->function))
82 return 1;
83 ids++;
84 }
85 return 0;
86}
87
88
89
90
91
92
93
94
95
96
97
98
99
100static int
101ocp_bind_drivers(struct ocp_driver *candidate)
102{
103 struct list_head *deventry, *drventry;
104 struct ocp_device *dev;
105 struct ocp_driver *drv;
106 int one_again, one_match;
107 int count = 0;
108
109 DBG(("ocp: binding drivers...\n"));
110 do {
111
112
113 one_match = one_again = 0;
114 down_read(&ocp_devices_sem);
115 list_for_each(deventry, &ocp_devices) {
116 dev = list_entry(deventry, struct ocp_device, link);
117 if (dev->driver != NULL)
118 continue;
119 DBG(("ocp: device %s unmatched, trying to match...\n", dev->name));
120 list_for_each(drventry, &ocp_drivers) {
121 drv = list_entry(drventry, struct ocp_driver, link);
122 if (ocp_driver_match(drv, dev)) {
123 int rc;
124
125
126 DBG(("ocp: match with driver %s, calling probe...\n", drv->name));
127 rc = drv->probe(dev);
128 DBG(("ocp: probe result: %d\n", rc));
129 if (rc == 0) {
130
131 dev->driver = drv;
132 one_match = 1;
133 if (drv == candidate)
134 count++;
135 break;
136 } else if (rc == -EAGAIN) {
137
138 one_again = 1;
139 if (drv == candidate)
140 count++;
141 break;
142 }
143 }
144 }
145 }
146 up_read(&ocp_devices_sem);
147 } while(one_match && one_again);
148 DBG(("ocp: binding drivers... done.\n"));
149
150 return count;
151}
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180int
181ocp_register_driver(struct ocp_driver *drv)
182{
183 int rc = 0;
184
185 DBG(("ocp: ocp_register_driver(%s)...\n", drv->name));
186
187
188 down(&ocp_drivers_sem);
189 list_add_tail(&drv->link, &ocp_drivers);
190
191
192 rc = ocp_bind_drivers(drv);
193
194 up(&ocp_drivers_sem);
195
196 DBG(("ocp: ocp_register_driver(%s)... done, count: %d.\n", drv->name, rc));
197
198 return rc;
199}
200
201
202
203
204
205
206
207
208
209void
210ocp_unregister_driver(struct ocp_driver *drv)
211{
212 struct ocp_device *dev;
213 struct list_head *entry;
214
215 DBG(("ocp: ocp_unregister_driver(%s)...\n", drv->name));
216
217
218 down(&ocp_drivers_sem);
219 down_read(&ocp_devices_sem);
220 list_for_each(entry, &ocp_devices) {
221 dev = list_entry(entry, struct ocp_device, link);
222 if (dev->driver == drv) {
223 drv->remove(dev);
224 dev->driver = NULL;
225 dev->drvdata = NULL;
226 }
227 }
228 up_read(&ocp_devices_sem);
229
230
231 list_del_init(&drv->link);
232 up(&ocp_drivers_sem);
233
234 DBG(("ocp: ocp_unregister_driver(%s)... done.\n", drv->name));
235}
236
237
238static struct ocp_device *
239__ocp_find_device(unsigned int vendor, unsigned int function, int index)
240{
241 struct list_head *entry;
242 struct ocp_device *dev, *found = NULL;
243
244 DBG(("ocp: __ocp_find_device(vendor: %x, function: %x, index: %d)...\n", vendor, function, index));
245
246 list_for_each(entry, &ocp_devices) {
247 dev = list_entry(entry, struct ocp_device, link);
248 if (vendor != OCP_ANY_ID && vendor != dev->def->vendor)
249 continue;
250 if (function != OCP_ANY_ID && function != dev->def->function)
251 continue;
252 if (index != OCP_ANY_INDEX && index != dev->def->index)
253 continue;
254 found = dev;
255 break;
256 }
257
258 DBG(("ocp: __ocp_find_device(vendor: %x, function: %x, index: %d)... done\n", vendor, function, index));
259
260 return found;
261}
262
263
264
265
266
267
268
269
270
271
272
273
274struct ocp_device *
275ocp_find_device(unsigned int vendor, unsigned int function, int index)
276{
277 struct ocp_device *dev;
278
279 down_read(&ocp_devices_sem);
280 dev = __ocp_find_device(vendor, function, index);
281 up_read(&ocp_devices_sem);
282
283 return dev;
284}
285
286
287
288
289
290
291
292
293
294
295
296struct ocp_def *
297ocp_get_one_device(unsigned int vendor, unsigned int function, int index)
298{
299 struct ocp_device *dev;
300 struct ocp_def *found = NULL;
301
302 DBG(("ocp: ocp_get_one_device(vendor: %x, function: %x, index: %d)...\n",
303 vendor, function, index));
304
305 dev = ocp_find_device(vendor, function, index);
306
307 if (dev)
308 found = dev->def;
309
310 DBG(("ocp: ocp_get_one_device(vendor: %x, function: %x, index: %d)... done.\n",
311 vendor, function, index));
312
313 return found;
314}
315
316
317
318
319
320
321
322
323
324
325int
326ocp_add_one_device(struct ocp_def *def)
327{
328 struct ocp_device *dev;
329
330 DBG(("ocp: ocp_add_one_device(vendor: %x, function: %x, index: %d)...\n", vendor, function, index));
331
332
333 if (ocp_inited)
334 return 1;
335
336 if (mem_init_done)
337 dev = kmalloc(sizeof(*dev), GFP_KERNEL);
338 else
339 dev = alloc_bootmem(sizeof(*dev));
340
341 if (dev == NULL)
342 return 1;
343 memset(dev, 0, sizeof(*dev));
344 dev->def = def;
345 dev->current_state = 4;
346 sprintf(dev->name, "OCP device %04x:%04x:%04x",
347 dev->def->vendor, dev->def->function, dev->def->index);
348 down_write(&ocp_devices_sem);
349 list_add_tail(&dev->link, &ocp_devices);
350 up_write(&ocp_devices_sem);
351
352 DBG(("ocp: ocp_add_one_device(vendor: %x, function: %x, index: %d)...done.\n", vendor, function, index));
353
354 return 0;
355}
356
357
358
359
360
361
362
363
364
365
366
367int
368ocp_remove_one_device(unsigned int vendor, unsigned int function, int index)
369{
370 struct ocp_device *dev;
371 int rc = 0;
372
373 DBG(("ocp: ocp_remove_one_device(vendor: %x, function: %x, index: %d)...\n", vendor, function, index));
374
375
376 if (ocp_inited)
377 return 1;
378
379 down_write(&ocp_devices_sem);
380 dev = __ocp_find_device(vendor, function, index);
381 if (dev != NULL)
382 list_del((struct list_head *)dev);
383 else
384 rc = 1;
385 up_write(&ocp_devices_sem);
386
387 DBG(("ocp: ocp_remove_one_device(vendor: %x, function: %x, index: %d)... done.\n", vendor, function, index));
388
389 return rc;
390}
391
392#ifdef CONFIG_PM
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413static int ocp_pm_save_state_device(struct ocp_device *dev, u32 state)
414{
415 int error = 0;
416 if (dev) {
417 struct ocp_driver *driver = dev->driver;
418 if (driver && driver->save_state)
419 error = driver->save_state(dev,state);
420 }
421 return error;
422}
423
424static int ocp_pm_suspend_device(struct ocp_device *dev, u32 state)
425{
426 int error = 0;
427 if (dev) {
428 struct ocp_driver *driver = dev->driver;
429 if (driver && driver->suspend)
430 error = driver->suspend(dev,state);
431 }
432 return error;
433}
434
435static int ocp_pm_resume_device(struct ocp_device *dev)
436{
437 int error = 0;
438 if (dev) {
439 struct ocp_driver *driver = dev->driver;
440 if (driver && driver->resume)
441 error = driver->resume(dev);
442 }
443 return error;
444}
445
446static int
447ocp_pm_callback(struct pm_dev *pm_device, pm_request_t rqst, void *data)
448{
449 int error = 0;
450 struct list_head *entry;
451 struct ocp_device *dev;
452
453 down(&ocp_drivers_sem);
454 down_read(&ocp_devices_sem);
455
456 list_for_each(entry, &ocp_devices) {
457 dev = list_entry(entry, struct ocp_device, link);
458 switch (rqst) {
459 case PM_SAVE_STATE:
460 error = ocp_pm_save_state_device(dev, 3);
461 break;
462 case PM_SUSPEND:
463 error = ocp_pm_suspend_device(dev, 3);
464 break;
465 case PM_RESUME:
466 error = ocp_pm_resume_device(dev);
467 break;
468 default: break;
469 }
470 if (error)
471 break;
472 }
473 return error;
474}
475
476
477
478
479void
480ppc4xx_cpm_fr(u32 bits, int val)
481{
482 unsigned long flags;
483
484 save_flags(flags);
485 cli();
486
487 if (val)
488 mtdcr(DCRN_CPMFR, mfdcr(DCRN_CPMFR) | bits);
489 else
490 mtdcr(DCRN_CPMFR, mfdcr(DCRN_CPMFR) & ~bits);
491
492 restore_flags(flags);
493}
494#endif
495
496
497
498
499
500
501
502
503
504int __init
505ocp_early_init(void)
506{
507 struct ocp_def *def;
508
509 DBG(("ocp: ocp_early_init()...\n"));
510
511
512 for (def = core_ocp; def->vendor != OCP_VENDOR_INVALID; def++)
513 ocp_add_one_device(def);
514
515 DBG(("ocp: ocp_early_init()... done.\n"));
516
517 return 0;
518}
519
520
521
522
523
524
525
526
527
528int
529ocp_driver_init(void)
530{
531
532
533
534
535 if (ocp_inited)
536 return 0;
537 ocp_inited = 1;
538
539 DBG(("ocp: ocp_driver_init()...\n"));
540
541
542 down(&ocp_drivers_sem);
543 ocp_bind_drivers(NULL);
544 up(&ocp_drivers_sem);
545
546#ifdef CONFIG_PM
547 pm_register(PM_SYS_DEV, 0, ocp_pm_callback);
548#endif
549
550 DBG(("ocp: ocp_driver_init()... done.\n"));
551
552 return 0;
553}
554
555__initcall(ocp_driver_init);
556
557EXPORT_SYMBOL(ocp_find_device);
558EXPORT_SYMBOL(ocp_register_driver);
559EXPORT_SYMBOL(ocp_unregister_driver);
560