1 | // SPDX-License-Identifier: GPL-2.0 |
2 | |
3 | #include <linux/platform_device.h> |
4 | #include <linux/interrupt.h> |
5 | #include <linux/memblock.h> |
6 | #include <asm/virt.h> |
7 | #include <asm/irq.h> |
8 | |
9 | #define VIRTIO_BUS_NB 128 |
10 | |
11 | static struct platform_device * __init virt_virtio_init(unsigned int id) |
12 | { |
13 | const struct resource res[] = { |
14 | DEFINE_RES_MEM(virt_bi_data.virtio.mmio + id * 0x200, 0x200), |
15 | DEFINE_RES_IRQ(virt_bi_data.virtio.irq + id), |
16 | }; |
17 | |
18 | return platform_device_register_simple("virtio-mmio" , id, |
19 | res, ARRAY_SIZE(res)); |
20 | } |
21 | |
22 | static int __init virt_platform_init(void) |
23 | { |
24 | const struct resource goldfish_tty_res[] = { |
25 | DEFINE_RES_MEM(virt_bi_data.tty.mmio, 1), |
26 | DEFINE_RES_IRQ(virt_bi_data.tty.irq), |
27 | }; |
28 | /* this is the second gf-rtc, the first one is used by the scheduler */ |
29 | const struct resource goldfish_rtc_res[] = { |
30 | DEFINE_RES_MEM(virt_bi_data.rtc.mmio + 0x1000, 0x1000), |
31 | DEFINE_RES_IRQ(virt_bi_data.rtc.irq + 1), |
32 | }; |
33 | struct platform_device *pdev1, *pdev2; |
34 | struct platform_device *pdevs[VIRTIO_BUS_NB]; |
35 | unsigned int i; |
36 | int ret = 0; |
37 | |
38 | if (!MACH_IS_VIRT) |
39 | return -ENODEV; |
40 | |
41 | /* We need this to have DMA'able memory provided to goldfish-tty */ |
42 | min_low_pfn = 0; |
43 | |
44 | pdev1 = platform_device_register_simple("goldfish_tty" , |
45 | PLATFORM_DEVID_NONE, |
46 | goldfish_tty_res, |
47 | ARRAY_SIZE(goldfish_tty_res)); |
48 | if (IS_ERR(ptr: pdev1)) |
49 | return PTR_ERR(ptr: pdev1); |
50 | |
51 | pdev2 = platform_device_register_simple("goldfish_rtc" , |
52 | PLATFORM_DEVID_NONE, |
53 | goldfish_rtc_res, |
54 | ARRAY_SIZE(goldfish_rtc_res)); |
55 | if (IS_ERR(ptr: pdev2)) { |
56 | ret = PTR_ERR(ptr: pdev2); |
57 | goto err_unregister_tty; |
58 | } |
59 | |
60 | for (i = 0; i < VIRTIO_BUS_NB; i++) { |
61 | pdevs[i] = virt_virtio_init(id: i); |
62 | if (IS_ERR(ptr: pdevs[i])) { |
63 | ret = PTR_ERR(ptr: pdevs[i]); |
64 | goto err_unregister_rtc_virtio; |
65 | } |
66 | } |
67 | |
68 | return 0; |
69 | |
70 | err_unregister_rtc_virtio: |
71 | while (i > 0) |
72 | platform_device_unregister(pdevs[--i]); |
73 | platform_device_unregister(pdev2); |
74 | err_unregister_tty: |
75 | platform_device_unregister(pdev1); |
76 | |
77 | return ret; |
78 | } |
79 | |
80 | arch_initcall(virt_platform_init); |
81 | |