Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/amba/bus.c
15111 views
1
/*
2
* linux/arch/arm/common/amba.c
3
*
4
* Copyright (C) 2003 Deep Blue Solutions Ltd, All Rights Reserved.
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License version 2 as
8
* published by the Free Software Foundation.
9
*/
10
#include <linux/module.h>
11
#include <linux/init.h>
12
#include <linux/device.h>
13
#include <linux/string.h>
14
#include <linux/slab.h>
15
#include <linux/io.h>
16
#include <linux/pm.h>
17
#include <linux/pm_runtime.h>
18
#include <linux/amba/bus.h>
19
20
#include <asm/irq.h>
21
#include <asm/sizes.h>
22
23
#define to_amba_driver(d) container_of(d, struct amba_driver, drv)
24
25
static const struct amba_id *
26
amba_lookup(const struct amba_id *table, struct amba_device *dev)
27
{
28
int ret = 0;
29
30
while (table->mask) {
31
ret = (dev->periphid & table->mask) == table->id;
32
if (ret)
33
break;
34
table++;
35
}
36
37
return ret ? table : NULL;
38
}
39
40
static int amba_match(struct device *dev, struct device_driver *drv)
41
{
42
struct amba_device *pcdev = to_amba_device(dev);
43
struct amba_driver *pcdrv = to_amba_driver(drv);
44
45
return amba_lookup(pcdrv->id_table, pcdev) != NULL;
46
}
47
48
#ifdef CONFIG_HOTPLUG
49
static int amba_uevent(struct device *dev, struct kobj_uevent_env *env)
50
{
51
struct amba_device *pcdev = to_amba_device(dev);
52
int retval = 0;
53
54
retval = add_uevent_var(env, "AMBA_ID=%08x", pcdev->periphid);
55
return retval;
56
}
57
#else
58
#define amba_uevent NULL
59
#endif
60
61
#define amba_attr_func(name,fmt,arg...) \
62
static ssize_t name##_show(struct device *_dev, \
63
struct device_attribute *attr, char *buf) \
64
{ \
65
struct amba_device *dev = to_amba_device(_dev); \
66
return sprintf(buf, fmt, arg); \
67
}
68
69
#define amba_attr(name,fmt,arg...) \
70
amba_attr_func(name,fmt,arg) \
71
static DEVICE_ATTR(name, S_IRUGO, name##_show, NULL)
72
73
amba_attr_func(id, "%08x\n", dev->periphid);
74
amba_attr(irq0, "%u\n", dev->irq[0]);
75
amba_attr(irq1, "%u\n", dev->irq[1]);
76
amba_attr_func(resource, "\t%016llx\t%016llx\t%016lx\n",
77
(unsigned long long)dev->res.start, (unsigned long long)dev->res.end,
78
dev->res.flags);
79
80
static struct device_attribute amba_dev_attrs[] = {
81
__ATTR_RO(id),
82
__ATTR_RO(resource),
83
__ATTR_NULL,
84
};
85
86
#ifdef CONFIG_PM_SLEEP
87
88
static int amba_legacy_suspend(struct device *dev, pm_message_t mesg)
89
{
90
struct amba_driver *adrv = to_amba_driver(dev->driver);
91
struct amba_device *adev = to_amba_device(dev);
92
int ret = 0;
93
94
if (dev->driver && adrv->suspend)
95
ret = adrv->suspend(adev, mesg);
96
97
return ret;
98
}
99
100
static int amba_legacy_resume(struct device *dev)
101
{
102
struct amba_driver *adrv = to_amba_driver(dev->driver);
103
struct amba_device *adev = to_amba_device(dev);
104
int ret = 0;
105
106
if (dev->driver && adrv->resume)
107
ret = adrv->resume(adev);
108
109
return ret;
110
}
111
112
static int amba_pm_prepare(struct device *dev)
113
{
114
struct device_driver *drv = dev->driver;
115
int ret = 0;
116
117
if (drv && drv->pm && drv->pm->prepare)
118
ret = drv->pm->prepare(dev);
119
120
return ret;
121
}
122
123
static void amba_pm_complete(struct device *dev)
124
{
125
struct device_driver *drv = dev->driver;
126
127
if (drv && drv->pm && drv->pm->complete)
128
drv->pm->complete(dev);
129
}
130
131
#else /* !CONFIG_PM_SLEEP */
132
133
#define amba_pm_prepare NULL
134
#define amba_pm_complete NULL
135
136
#endif /* !CONFIG_PM_SLEEP */
137
138
#ifdef CONFIG_SUSPEND
139
140
static int amba_pm_suspend(struct device *dev)
141
{
142
struct device_driver *drv = dev->driver;
143
int ret = 0;
144
145
if (!drv)
146
return 0;
147
148
if (drv->pm) {
149
if (drv->pm->suspend)
150
ret = drv->pm->suspend(dev);
151
} else {
152
ret = amba_legacy_suspend(dev, PMSG_SUSPEND);
153
}
154
155
return ret;
156
}
157
158
static int amba_pm_suspend_noirq(struct device *dev)
159
{
160
struct device_driver *drv = dev->driver;
161
int ret = 0;
162
163
if (!drv)
164
return 0;
165
166
if (drv->pm) {
167
if (drv->pm->suspend_noirq)
168
ret = drv->pm->suspend_noirq(dev);
169
}
170
171
return ret;
172
}
173
174
static int amba_pm_resume(struct device *dev)
175
{
176
struct device_driver *drv = dev->driver;
177
int ret = 0;
178
179
if (!drv)
180
return 0;
181
182
if (drv->pm) {
183
if (drv->pm->resume)
184
ret = drv->pm->resume(dev);
185
} else {
186
ret = amba_legacy_resume(dev);
187
}
188
189
return ret;
190
}
191
192
static int amba_pm_resume_noirq(struct device *dev)
193
{
194
struct device_driver *drv = dev->driver;
195
int ret = 0;
196
197
if (!drv)
198
return 0;
199
200
if (drv->pm) {
201
if (drv->pm->resume_noirq)
202
ret = drv->pm->resume_noirq(dev);
203
}
204
205
return ret;
206
}
207
208
#else /* !CONFIG_SUSPEND */
209
210
#define amba_pm_suspend NULL
211
#define amba_pm_resume NULL
212
#define amba_pm_suspend_noirq NULL
213
#define amba_pm_resume_noirq NULL
214
215
#endif /* !CONFIG_SUSPEND */
216
217
#ifdef CONFIG_HIBERNATE_CALLBACKS
218
219
static int amba_pm_freeze(struct device *dev)
220
{
221
struct device_driver *drv = dev->driver;
222
int ret = 0;
223
224
if (!drv)
225
return 0;
226
227
if (drv->pm) {
228
if (drv->pm->freeze)
229
ret = drv->pm->freeze(dev);
230
} else {
231
ret = amba_legacy_suspend(dev, PMSG_FREEZE);
232
}
233
234
return ret;
235
}
236
237
static int amba_pm_freeze_noirq(struct device *dev)
238
{
239
struct device_driver *drv = dev->driver;
240
int ret = 0;
241
242
if (!drv)
243
return 0;
244
245
if (drv->pm) {
246
if (drv->pm->freeze_noirq)
247
ret = drv->pm->freeze_noirq(dev);
248
}
249
250
return ret;
251
}
252
253
static int amba_pm_thaw(struct device *dev)
254
{
255
struct device_driver *drv = dev->driver;
256
int ret = 0;
257
258
if (!drv)
259
return 0;
260
261
if (drv->pm) {
262
if (drv->pm->thaw)
263
ret = drv->pm->thaw(dev);
264
} else {
265
ret = amba_legacy_resume(dev);
266
}
267
268
return ret;
269
}
270
271
static int amba_pm_thaw_noirq(struct device *dev)
272
{
273
struct device_driver *drv = dev->driver;
274
int ret = 0;
275
276
if (!drv)
277
return 0;
278
279
if (drv->pm) {
280
if (drv->pm->thaw_noirq)
281
ret = drv->pm->thaw_noirq(dev);
282
}
283
284
return ret;
285
}
286
287
static int amba_pm_poweroff(struct device *dev)
288
{
289
struct device_driver *drv = dev->driver;
290
int ret = 0;
291
292
if (!drv)
293
return 0;
294
295
if (drv->pm) {
296
if (drv->pm->poweroff)
297
ret = drv->pm->poweroff(dev);
298
} else {
299
ret = amba_legacy_suspend(dev, PMSG_HIBERNATE);
300
}
301
302
return ret;
303
}
304
305
static int amba_pm_poweroff_noirq(struct device *dev)
306
{
307
struct device_driver *drv = dev->driver;
308
int ret = 0;
309
310
if (!drv)
311
return 0;
312
313
if (drv->pm) {
314
if (drv->pm->poweroff_noirq)
315
ret = drv->pm->poweroff_noirq(dev);
316
}
317
318
return ret;
319
}
320
321
static int amba_pm_restore(struct device *dev)
322
{
323
struct device_driver *drv = dev->driver;
324
int ret = 0;
325
326
if (!drv)
327
return 0;
328
329
if (drv->pm) {
330
if (drv->pm->restore)
331
ret = drv->pm->restore(dev);
332
} else {
333
ret = amba_legacy_resume(dev);
334
}
335
336
return ret;
337
}
338
339
static int amba_pm_restore_noirq(struct device *dev)
340
{
341
struct device_driver *drv = dev->driver;
342
int ret = 0;
343
344
if (!drv)
345
return 0;
346
347
if (drv->pm) {
348
if (drv->pm->restore_noirq)
349
ret = drv->pm->restore_noirq(dev);
350
}
351
352
return ret;
353
}
354
355
#else /* !CONFIG_HIBERNATE_CALLBACKS */
356
357
#define amba_pm_freeze NULL
358
#define amba_pm_thaw NULL
359
#define amba_pm_poweroff NULL
360
#define amba_pm_restore NULL
361
#define amba_pm_freeze_noirq NULL
362
#define amba_pm_thaw_noirq NULL
363
#define amba_pm_poweroff_noirq NULL
364
#define amba_pm_restore_noirq NULL
365
366
#endif /* !CONFIG_HIBERNATE_CALLBACKS */
367
368
#ifdef CONFIG_PM
369
370
static const struct dev_pm_ops amba_pm = {
371
.prepare = amba_pm_prepare,
372
.complete = amba_pm_complete,
373
.suspend = amba_pm_suspend,
374
.resume = amba_pm_resume,
375
.freeze = amba_pm_freeze,
376
.thaw = amba_pm_thaw,
377
.poweroff = amba_pm_poweroff,
378
.restore = amba_pm_restore,
379
.suspend_noirq = amba_pm_suspend_noirq,
380
.resume_noirq = amba_pm_resume_noirq,
381
.freeze_noirq = amba_pm_freeze_noirq,
382
.thaw_noirq = amba_pm_thaw_noirq,
383
.poweroff_noirq = amba_pm_poweroff_noirq,
384
.restore_noirq = amba_pm_restore_noirq,
385
SET_RUNTIME_PM_OPS(
386
pm_generic_runtime_suspend,
387
pm_generic_runtime_resume,
388
pm_generic_runtime_idle
389
)
390
};
391
392
#define AMBA_PM (&amba_pm)
393
394
#else /* !CONFIG_PM */
395
396
#define AMBA_PM NULL
397
398
#endif /* !CONFIG_PM */
399
400
/*
401
* Primecells are part of the Advanced Microcontroller Bus Architecture,
402
* so we call the bus "amba".
403
*/
404
struct bus_type amba_bustype = {
405
.name = "amba",
406
.dev_attrs = amba_dev_attrs,
407
.match = amba_match,
408
.uevent = amba_uevent,
409
.pm = AMBA_PM,
410
};
411
412
static int __init amba_init(void)
413
{
414
return bus_register(&amba_bustype);
415
}
416
417
postcore_initcall(amba_init);
418
419
static int amba_get_enable_pclk(struct amba_device *pcdev)
420
{
421
struct clk *pclk = clk_get(&pcdev->dev, "apb_pclk");
422
int ret;
423
424
pcdev->pclk = pclk;
425
426
if (IS_ERR(pclk))
427
return PTR_ERR(pclk);
428
429
ret = clk_enable(pclk);
430
if (ret)
431
clk_put(pclk);
432
433
return ret;
434
}
435
436
static void amba_put_disable_pclk(struct amba_device *pcdev)
437
{
438
struct clk *pclk = pcdev->pclk;
439
440
clk_disable(pclk);
441
clk_put(pclk);
442
}
443
444
static int amba_get_enable_vcore(struct amba_device *pcdev)
445
{
446
struct regulator *vcore = regulator_get(&pcdev->dev, "vcore");
447
int ret;
448
449
pcdev->vcore = vcore;
450
451
if (IS_ERR(vcore)) {
452
/* It is OK not to supply a vcore regulator */
453
if (PTR_ERR(vcore) == -ENODEV)
454
return 0;
455
return PTR_ERR(vcore);
456
}
457
458
ret = regulator_enable(vcore);
459
if (ret) {
460
regulator_put(vcore);
461
pcdev->vcore = ERR_PTR(-ENODEV);
462
}
463
464
return ret;
465
}
466
467
static void amba_put_disable_vcore(struct amba_device *pcdev)
468
{
469
struct regulator *vcore = pcdev->vcore;
470
471
if (!IS_ERR(vcore)) {
472
regulator_disable(vcore);
473
regulator_put(vcore);
474
}
475
}
476
477
/*
478
* These are the device model conversion veneers; they convert the
479
* device model structures to our more specific structures.
480
*/
481
static int amba_probe(struct device *dev)
482
{
483
struct amba_device *pcdev = to_amba_device(dev);
484
struct amba_driver *pcdrv = to_amba_driver(dev->driver);
485
const struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev);
486
int ret;
487
488
do {
489
ret = amba_get_enable_vcore(pcdev);
490
if (ret)
491
break;
492
493
ret = amba_get_enable_pclk(pcdev);
494
if (ret)
495
break;
496
497
ret = pcdrv->probe(pcdev, id);
498
if (ret == 0)
499
break;
500
501
amba_put_disable_pclk(pcdev);
502
amba_put_disable_vcore(pcdev);
503
} while (0);
504
505
return ret;
506
}
507
508
static int amba_remove(struct device *dev)
509
{
510
struct amba_device *pcdev = to_amba_device(dev);
511
struct amba_driver *drv = to_amba_driver(dev->driver);
512
int ret = drv->remove(pcdev);
513
514
amba_put_disable_pclk(pcdev);
515
amba_put_disable_vcore(pcdev);
516
517
return ret;
518
}
519
520
static void amba_shutdown(struct device *dev)
521
{
522
struct amba_driver *drv = to_amba_driver(dev->driver);
523
drv->shutdown(to_amba_device(dev));
524
}
525
526
/**
527
* amba_driver_register - register an AMBA device driver
528
* @drv: amba device driver structure
529
*
530
* Register an AMBA device driver with the Linux device model
531
* core. If devices pre-exist, the drivers probe function will
532
* be called.
533
*/
534
int amba_driver_register(struct amba_driver *drv)
535
{
536
drv->drv.bus = &amba_bustype;
537
538
#define SETFN(fn) if (drv->fn) drv->drv.fn = amba_##fn
539
SETFN(probe);
540
SETFN(remove);
541
SETFN(shutdown);
542
543
return driver_register(&drv->drv);
544
}
545
546
/**
547
* amba_driver_unregister - remove an AMBA device driver
548
* @drv: AMBA device driver structure to remove
549
*
550
* Unregister an AMBA device driver from the Linux device
551
* model. The device model will call the drivers remove function
552
* for each device the device driver is currently handling.
553
*/
554
void amba_driver_unregister(struct amba_driver *drv)
555
{
556
driver_unregister(&drv->drv);
557
}
558
559
560
static void amba_device_release(struct device *dev)
561
{
562
struct amba_device *d = to_amba_device(dev);
563
564
if (d->res.parent)
565
release_resource(&d->res);
566
kfree(d);
567
}
568
569
/**
570
* amba_device_register - register an AMBA device
571
* @dev: AMBA device to register
572
* @parent: parent memory resource
573
*
574
* Setup the AMBA device, reading the cell ID if present.
575
* Claim the resource, and register the AMBA device with
576
* the Linux device manager.
577
*/
578
int amba_device_register(struct amba_device *dev, struct resource *parent)
579
{
580
u32 size;
581
void __iomem *tmp;
582
int i, ret;
583
584
device_initialize(&dev->dev);
585
586
/*
587
* Copy from device_add
588
*/
589
if (dev->dev.init_name) {
590
dev_set_name(&dev->dev, "%s", dev->dev.init_name);
591
dev->dev.init_name = NULL;
592
}
593
594
dev->dev.release = amba_device_release;
595
dev->dev.bus = &amba_bustype;
596
dev->dev.dma_mask = &dev->dma_mask;
597
dev->res.name = dev_name(&dev->dev);
598
599
if (!dev->dev.coherent_dma_mask && dev->dma_mask)
600
dev_warn(&dev->dev, "coherent dma mask is unset\n");
601
602
ret = request_resource(parent, &dev->res);
603
if (ret)
604
goto err_out;
605
606
/* Hard-coded primecell ID instead of plug-n-play */
607
if (dev->periphid != 0)
608
goto skip_probe;
609
610
/*
611
* Dynamically calculate the size of the resource
612
* and use this for iomap
613
*/
614
size = resource_size(&dev->res);
615
tmp = ioremap(dev->res.start, size);
616
if (!tmp) {
617
ret = -ENOMEM;
618
goto err_release;
619
}
620
621
ret = amba_get_enable_pclk(dev);
622
if (ret == 0) {
623
u32 pid, cid;
624
625
/*
626
* Read pid and cid based on size of resource
627
* they are located at end of region
628
*/
629
for (pid = 0, i = 0; i < 4; i++)
630
pid |= (readl(tmp + size - 0x20 + 4 * i) & 255) <<
631
(i * 8);
632
for (cid = 0, i = 0; i < 4; i++)
633
cid |= (readl(tmp + size - 0x10 + 4 * i) & 255) <<
634
(i * 8);
635
636
amba_put_disable_pclk(dev);
637
638
if (cid == AMBA_CID)
639
dev->periphid = pid;
640
641
if (!dev->periphid)
642
ret = -ENODEV;
643
}
644
645
iounmap(tmp);
646
647
if (ret)
648
goto err_release;
649
650
skip_probe:
651
ret = device_add(&dev->dev);
652
if (ret)
653
goto err_release;
654
655
if (dev->irq[0] != NO_IRQ)
656
ret = device_create_file(&dev->dev, &dev_attr_irq0);
657
if (ret == 0 && dev->irq[1] != NO_IRQ)
658
ret = device_create_file(&dev->dev, &dev_attr_irq1);
659
if (ret == 0)
660
return ret;
661
662
device_unregister(&dev->dev);
663
664
err_release:
665
release_resource(&dev->res);
666
err_out:
667
return ret;
668
}
669
670
/**
671
* amba_device_unregister - unregister an AMBA device
672
* @dev: AMBA device to remove
673
*
674
* Remove the specified AMBA device from the Linux device
675
* manager. All files associated with this object will be
676
* destroyed, and device drivers notified that the device has
677
* been removed. The AMBA device's resources including
678
* the amba_device structure will be freed once all
679
* references to it have been dropped.
680
*/
681
void amba_device_unregister(struct amba_device *dev)
682
{
683
device_unregister(&dev->dev);
684
}
685
686
687
struct find_data {
688
struct amba_device *dev;
689
struct device *parent;
690
const char *busid;
691
unsigned int id;
692
unsigned int mask;
693
};
694
695
static int amba_find_match(struct device *dev, void *data)
696
{
697
struct find_data *d = data;
698
struct amba_device *pcdev = to_amba_device(dev);
699
int r;
700
701
r = (pcdev->periphid & d->mask) == d->id;
702
if (d->parent)
703
r &= d->parent == dev->parent;
704
if (d->busid)
705
r &= strcmp(dev_name(dev), d->busid) == 0;
706
707
if (r) {
708
get_device(dev);
709
d->dev = pcdev;
710
}
711
712
return r;
713
}
714
715
/**
716
* amba_find_device - locate an AMBA device given a bus id
717
* @busid: bus id for device (or NULL)
718
* @parent: parent device (or NULL)
719
* @id: peripheral ID (or 0)
720
* @mask: peripheral ID mask (or 0)
721
*
722
* Return the AMBA device corresponding to the supplied parameters.
723
* If no device matches, returns NULL.
724
*
725
* NOTE: When a valid device is found, its refcount is
726
* incremented, and must be decremented before the returned
727
* reference.
728
*/
729
struct amba_device *
730
amba_find_device(const char *busid, struct device *parent, unsigned int id,
731
unsigned int mask)
732
{
733
struct find_data data;
734
735
data.dev = NULL;
736
data.parent = parent;
737
data.busid = busid;
738
data.id = id;
739
data.mask = mask;
740
741
bus_for_each_dev(&amba_bustype, NULL, &data, amba_find_match);
742
743
return data.dev;
744
}
745
746
/**
747
* amba_request_regions - request all mem regions associated with device
748
* @dev: amba_device structure for device
749
* @name: name, or NULL to use driver name
750
*/
751
int amba_request_regions(struct amba_device *dev, const char *name)
752
{
753
int ret = 0;
754
u32 size;
755
756
if (!name)
757
name = dev->dev.driver->name;
758
759
size = resource_size(&dev->res);
760
761
if (!request_mem_region(dev->res.start, size, name))
762
ret = -EBUSY;
763
764
return ret;
765
}
766
767
/**
768
* amba_release_regions - release mem regions associated with device
769
* @dev: amba_device structure for device
770
*
771
* Release regions claimed by a successful call to amba_request_regions.
772
*/
773
void amba_release_regions(struct amba_device *dev)
774
{
775
u32 size;
776
777
size = resource_size(&dev->res);
778
release_mem_region(dev->res.start, size);
779
}
780
781
EXPORT_SYMBOL(amba_driver_register);
782
EXPORT_SYMBOL(amba_driver_unregister);
783
EXPORT_SYMBOL(amba_device_register);
784
EXPORT_SYMBOL(amba_device_unregister);
785
EXPORT_SYMBOL(amba_find_device);
786
EXPORT_SYMBOL(amba_request_regions);
787
EXPORT_SYMBOL(amba_release_regions);
788
789