| // SPDX-License-Identifier: GPL-2.0 |
| |
| #include <linux/platform_device.h> |
| #include <linux/interrupt.h> |
| #include <linux/memblock.h> |
| #include <asm/virt.h> |
| #include <asm/irq.h> |
| |
| #define VIRTIO_BUS_NB 128 |
| |
| static struct platform_device * __init virt_virtio_init(unsigned int id) |
| { |
| const struct resource res[] = { |
| DEFINE_RES_MEM(virt_bi_data.virtio.mmio + id * 0x200, 0x200), |
| DEFINE_RES_IRQ(virt_bi_data.virtio.irq + id), |
| }; |
| |
| return platform_device_register_simple("virtio-mmio", id, |
| res, ARRAY_SIZE(res)); |
| } |
| |
| static int __init virt_platform_init(void) |
| { |
| const struct resource goldfish_tty_res[] = { |
| DEFINE_RES_MEM(virt_bi_data.tty.mmio, 1), |
| DEFINE_RES_IRQ(virt_bi_data.tty.irq), |
| }; |
| /* this is the second gf-rtc, the first one is used by the scheduler */ |
| const struct resource goldfish_rtc_res[] = { |
| DEFINE_RES_MEM(virt_bi_data.rtc.mmio + 0x1000, 0x1000), |
| DEFINE_RES_IRQ(virt_bi_data.rtc.irq + 1), |
| }; |
| struct platform_device *pdev1, *pdev2; |
| struct platform_device *pdevs[VIRTIO_BUS_NB]; |
| unsigned int i; |
| int ret = 0; |
| |
| if (!MACH_IS_VIRT) |
| return -ENODEV; |
| |
| /* We need this to have DMA'able memory provided to goldfish-tty */ |
| min_low_pfn = 0; |
| |
| pdev1 = platform_device_register_simple("goldfish_tty", |
| PLATFORM_DEVID_NONE, |
| goldfish_tty_res, |
| ARRAY_SIZE(goldfish_tty_res)); |
| if (IS_ERR(pdev1)) |
| return PTR_ERR(pdev1); |
| |
| pdev2 = platform_device_register_simple("goldfish_rtc", |
| PLATFORM_DEVID_NONE, |
| goldfish_rtc_res, |
| ARRAY_SIZE(goldfish_rtc_res)); |
| if (IS_ERR(pdev2)) { |
| ret = PTR_ERR(pdev2); |
| goto err_unregister_tty; |
| } |
| |
| for (i = 0; i < VIRTIO_BUS_NB; i++) { |
| pdevs[i] = virt_virtio_init(i); |
| if (IS_ERR(pdevs[i])) { |
| ret = PTR_ERR(pdevs[i]); |
| goto err_unregister_rtc_virtio; |
| } |
| } |
| |
| return 0; |
| |
| err_unregister_rtc_virtio: |
| while (i > 0) |
| platform_device_unregister(pdevs[--i]); |
| platform_device_unregister(pdev2); |
| err_unregister_tty: |
| platform_device_unregister(pdev1); |
| |
| return ret; |
| } |
| |
| arch_initcall(virt_platform_init); |