162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci#include <linux/platform_device.h> 462306a36Sopenharmony_ci#include <linux/interrupt.h> 562306a36Sopenharmony_ci#include <linux/memblock.h> 662306a36Sopenharmony_ci#include <asm/virt.h> 762306a36Sopenharmony_ci#include <asm/irq.h> 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#define VIRTIO_BUS_NB 128 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_cistatic struct platform_device * __init virt_virtio_init(unsigned int id) 1262306a36Sopenharmony_ci{ 1362306a36Sopenharmony_ci const struct resource res[] = { 1462306a36Sopenharmony_ci DEFINE_RES_MEM(virt_bi_data.virtio.mmio + id * 0x200, 0x200), 1562306a36Sopenharmony_ci DEFINE_RES_IRQ(virt_bi_data.virtio.irq + id), 1662306a36Sopenharmony_ci }; 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci return platform_device_register_simple("virtio-mmio", id, 1962306a36Sopenharmony_ci res, ARRAY_SIZE(res)); 2062306a36Sopenharmony_ci} 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cistatic int __init virt_platform_init(void) 2362306a36Sopenharmony_ci{ 2462306a36Sopenharmony_ci const struct resource goldfish_tty_res[] = { 2562306a36Sopenharmony_ci DEFINE_RES_MEM(virt_bi_data.tty.mmio, 1), 2662306a36Sopenharmony_ci DEFINE_RES_IRQ(virt_bi_data.tty.irq), 2762306a36Sopenharmony_ci }; 2862306a36Sopenharmony_ci /* this is the second gf-rtc, the first one is used by the scheduler */ 2962306a36Sopenharmony_ci const struct resource goldfish_rtc_res[] = { 3062306a36Sopenharmony_ci DEFINE_RES_MEM(virt_bi_data.rtc.mmio + 0x1000, 0x1000), 3162306a36Sopenharmony_ci DEFINE_RES_IRQ(virt_bi_data.rtc.irq + 1), 3262306a36Sopenharmony_ci }; 3362306a36Sopenharmony_ci struct platform_device *pdev1, *pdev2; 3462306a36Sopenharmony_ci struct platform_device *pdevs[VIRTIO_BUS_NB]; 3562306a36Sopenharmony_ci unsigned int i; 3662306a36Sopenharmony_ci int ret = 0; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci if (!MACH_IS_VIRT) 3962306a36Sopenharmony_ci return -ENODEV; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci /* We need this to have DMA'able memory provided to goldfish-tty */ 4262306a36Sopenharmony_ci min_low_pfn = 0; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci pdev1 = platform_device_register_simple("goldfish_tty", 4562306a36Sopenharmony_ci PLATFORM_DEVID_NONE, 4662306a36Sopenharmony_ci goldfish_tty_res, 4762306a36Sopenharmony_ci ARRAY_SIZE(goldfish_tty_res)); 4862306a36Sopenharmony_ci if (IS_ERR(pdev1)) 4962306a36Sopenharmony_ci return PTR_ERR(pdev1); 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci pdev2 = platform_device_register_simple("goldfish_rtc", 5262306a36Sopenharmony_ci PLATFORM_DEVID_NONE, 5362306a36Sopenharmony_ci goldfish_rtc_res, 5462306a36Sopenharmony_ci ARRAY_SIZE(goldfish_rtc_res)); 5562306a36Sopenharmony_ci if (IS_ERR(pdev2)) { 5662306a36Sopenharmony_ci ret = PTR_ERR(pdev2); 5762306a36Sopenharmony_ci goto err_unregister_tty; 5862306a36Sopenharmony_ci } 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci for (i = 0; i < VIRTIO_BUS_NB; i++) { 6162306a36Sopenharmony_ci pdevs[i] = virt_virtio_init(i); 6262306a36Sopenharmony_ci if (IS_ERR(pdevs[i])) { 6362306a36Sopenharmony_ci ret = PTR_ERR(pdevs[i]); 6462306a36Sopenharmony_ci goto err_unregister_rtc_virtio; 6562306a36Sopenharmony_ci } 6662306a36Sopenharmony_ci } 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci return 0; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cierr_unregister_rtc_virtio: 7162306a36Sopenharmony_ci while (i > 0) 7262306a36Sopenharmony_ci platform_device_unregister(pdevs[--i]); 7362306a36Sopenharmony_ci platform_device_unregister(pdev2); 7462306a36Sopenharmony_cierr_unregister_tty: 7562306a36Sopenharmony_ci platform_device_unregister(pdev1); 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci return ret; 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ciarch_initcall(virt_platform_init); 81