105d51e42SLaurent Vivier // SPDX-License-Identifier: GPL-2.0
205d51e42SLaurent Vivier
305d51e42SLaurent Vivier #include <linux/platform_device.h>
405d51e42SLaurent Vivier #include <linux/interrupt.h>
505d51e42SLaurent Vivier #include <linux/memblock.h>
605d51e42SLaurent Vivier #include <asm/virt.h>
705d51e42SLaurent Vivier #include <asm/irq.h>
805d51e42SLaurent Vivier
905d51e42SLaurent Vivier #define VIRTIO_BUS_NB 128
1005d51e42SLaurent Vivier
virt_virtio_init(unsigned int id)11*566a2d6dSYang Yingliang static struct platform_device * __init virt_virtio_init(unsigned int id)
1205d51e42SLaurent Vivier {
1305d51e42SLaurent Vivier const struct resource res[] = {
1405d51e42SLaurent Vivier DEFINE_RES_MEM(virt_bi_data.virtio.mmio + id * 0x200, 0x200),
1505d51e42SLaurent Vivier DEFINE_RES_IRQ(virt_bi_data.virtio.irq + id),
1605d51e42SLaurent Vivier };
1705d51e42SLaurent Vivier
18*566a2d6dSYang Yingliang return platform_device_register_simple("virtio-mmio", id,
1905d51e42SLaurent Vivier res, ARRAY_SIZE(res));
2005d51e42SLaurent Vivier }
2105d51e42SLaurent Vivier
virt_platform_init(void)2205d51e42SLaurent Vivier static int __init virt_platform_init(void)
2305d51e42SLaurent Vivier {
2405d51e42SLaurent Vivier const struct resource goldfish_tty_res[] = {
2505d51e42SLaurent Vivier DEFINE_RES_MEM(virt_bi_data.tty.mmio, 1),
2605d51e42SLaurent Vivier DEFINE_RES_IRQ(virt_bi_data.tty.irq),
2705d51e42SLaurent Vivier };
2805d51e42SLaurent Vivier /* this is the second gf-rtc, the first one is used by the scheduler */
2905d51e42SLaurent Vivier const struct resource goldfish_rtc_res[] = {
3005d51e42SLaurent Vivier DEFINE_RES_MEM(virt_bi_data.rtc.mmio + 0x1000, 0x1000),
3105d51e42SLaurent Vivier DEFINE_RES_IRQ(virt_bi_data.rtc.irq + 1),
3205d51e42SLaurent Vivier };
33*566a2d6dSYang Yingliang struct platform_device *pdev1, *pdev2;
34*566a2d6dSYang Yingliang struct platform_device *pdevs[VIRTIO_BUS_NB];
3505d51e42SLaurent Vivier unsigned int i;
36*566a2d6dSYang Yingliang int ret = 0;
3705d51e42SLaurent Vivier
3805d51e42SLaurent Vivier if (!MACH_IS_VIRT)
3905d51e42SLaurent Vivier return -ENODEV;
4005d51e42SLaurent Vivier
4105d51e42SLaurent Vivier /* We need this to have DMA'able memory provided to goldfish-tty */
4205d51e42SLaurent Vivier min_low_pfn = 0;
4305d51e42SLaurent Vivier
44*566a2d6dSYang Yingliang pdev1 = platform_device_register_simple("goldfish_tty",
4505d51e42SLaurent Vivier PLATFORM_DEVID_NONE,
4605d51e42SLaurent Vivier goldfish_tty_res,
4705d51e42SLaurent Vivier ARRAY_SIZE(goldfish_tty_res));
48*566a2d6dSYang Yingliang if (IS_ERR(pdev1))
49*566a2d6dSYang Yingliang return PTR_ERR(pdev1);
5005d51e42SLaurent Vivier
51*566a2d6dSYang Yingliang pdev2 = platform_device_register_simple("goldfish_rtc",
5205d51e42SLaurent Vivier PLATFORM_DEVID_NONE,
5305d51e42SLaurent Vivier goldfish_rtc_res,
5405d51e42SLaurent Vivier ARRAY_SIZE(goldfish_rtc_res));
55*566a2d6dSYang Yingliang if (IS_ERR(pdev2)) {
56*566a2d6dSYang Yingliang ret = PTR_ERR(pdev2);
57*566a2d6dSYang Yingliang goto err_unregister_tty;
58*566a2d6dSYang Yingliang }
5905d51e42SLaurent Vivier
6005d51e42SLaurent Vivier for (i = 0; i < VIRTIO_BUS_NB; i++) {
61*566a2d6dSYang Yingliang pdevs[i] = virt_virtio_init(i);
62*566a2d6dSYang Yingliang if (IS_ERR(pdevs[i])) {
63*566a2d6dSYang Yingliang ret = PTR_ERR(pdevs[i]);
64*566a2d6dSYang Yingliang goto err_unregister_rtc_virtio;
65*566a2d6dSYang Yingliang }
6605d51e42SLaurent Vivier }
6705d51e42SLaurent Vivier
6805d51e42SLaurent Vivier return 0;
69*566a2d6dSYang Yingliang
70*566a2d6dSYang Yingliang err_unregister_rtc_virtio:
71*566a2d6dSYang Yingliang while (i > 0)
72*566a2d6dSYang Yingliang platform_device_unregister(pdevs[--i]);
73*566a2d6dSYang Yingliang platform_device_unregister(pdev2);
74*566a2d6dSYang Yingliang err_unregister_tty:
75*566a2d6dSYang Yingliang platform_device_unregister(pdev1);
76*566a2d6dSYang Yingliang
77*566a2d6dSYang Yingliang return ret;
7805d51e42SLaurent Vivier }
7905d51e42SLaurent Vivier
8005d51e42SLaurent Vivier arch_initcall(virt_platform_init);
81