Lines Matching +full:virtio +full:- +full:pci
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Virtio memory mapped device driver
5 * Copyright 2011-2014, ARM Ltd.
7 * This module allows virtio devices to be used over a virtual, memory mapped
15 * .name = "virtio-mmio",
16 * .id = -1,
34 * compatible = "virtio,mmio";
39 * 3. Kernel module (or command line) parameter. Can be used more than once -
52 * Based on Virtio PCI driver by Anthony Liguori, copyright IBM Corp. 2007
55 #define pr_fmt(fmt) "virtio-mmio: " fmt
58 #include <linux/dma-mapping.h>
67 #include <linux/virtio.h>
112 writel(1, vm_dev->base + VIRTIO_MMIO_DEVICE_FEATURES_SEL); in vm_get_features()
113 features = readl(vm_dev->base + VIRTIO_MMIO_DEVICE_FEATURES); in vm_get_features()
116 writel(0, vm_dev->base + VIRTIO_MMIO_DEVICE_FEATURES_SEL); in vm_get_features()
117 features |= readl(vm_dev->base + VIRTIO_MMIO_DEVICE_FEATURES); in vm_get_features()
130 if (vm_dev->version == 2 && in vm_finalize_features()
132 …dev_err(&vdev->dev, "New virtio-mmio devices (version 2) must provide VIRTIO_F_VERSION_1 feature!\… in vm_finalize_features()
133 return -EINVAL; in vm_finalize_features()
136 writel(1, vm_dev->base + VIRTIO_MMIO_DRIVER_FEATURES_SEL); in vm_finalize_features()
137 writel((u32)(vdev->features >> 32), in vm_finalize_features()
138 vm_dev->base + VIRTIO_MMIO_DRIVER_FEATURES); in vm_finalize_features()
140 writel(0, vm_dev->base + VIRTIO_MMIO_DRIVER_FEATURES_SEL); in vm_finalize_features()
141 writel((u32)vdev->features, in vm_finalize_features()
142 vm_dev->base + VIRTIO_MMIO_DRIVER_FEATURES); in vm_finalize_features()
151 void __iomem *base = vm_dev->base + VIRTIO_MMIO_CONFIG; in vm_get()
156 if (vm_dev->version == 1) { in vm_get()
193 void __iomem *base = vm_dev->base + VIRTIO_MMIO_CONFIG; in vm_set()
198 if (vm_dev->version == 1) { in vm_set()
236 if (vm_dev->version == 1) in vm_generation()
239 return readl(vm_dev->base + VIRTIO_MMIO_CONFIG_GENERATION); in vm_generation()
246 return readl(vm_dev->base + VIRTIO_MMIO_STATUS) & 0xff; in vm_get_status()
256 writel(status, vm_dev->base + VIRTIO_MMIO_STATUS); in vm_set_status()
264 writel(0, vm_dev->base + VIRTIO_MMIO_STATUS); in vm_reset()
274 struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev); in vm_notify()
278 writel(vq->index, vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY); in vm_notify()
292 status = readl(vm_dev->base + VIRTIO_MMIO_INTERRUPT_STATUS); in vm_interrupt()
293 writel(status, vm_dev->base + VIRTIO_MMIO_INTERRUPT_ACK); in vm_interrupt()
296 virtio_config_changed(&vm_dev->vdev); in vm_interrupt()
301 spin_lock_irqsave(&vm_dev->lock, flags); in vm_interrupt()
302 list_for_each_entry(info, &vm_dev->virtqueues, node) in vm_interrupt()
303 ret |= vring_interrupt(irq, info->vq); in vm_interrupt()
304 spin_unlock_irqrestore(&vm_dev->lock, flags); in vm_interrupt()
314 struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev); in vm_del_vq()
315 struct virtio_mmio_vq_info *info = vq->priv; in vm_del_vq()
317 unsigned int index = vq->index; in vm_del_vq()
319 spin_lock_irqsave(&vm_dev->lock, flags); in vm_del_vq()
320 list_del(&info->node); in vm_del_vq()
321 spin_unlock_irqrestore(&vm_dev->lock, flags); in vm_del_vq()
324 writel(index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL); in vm_del_vq()
325 if (vm_dev->version == 1) { in vm_del_vq()
326 writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); in vm_del_vq()
328 writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_READY); in vm_del_vq()
329 WARN_ON(readl(vm_dev->base + VIRTIO_MMIO_QUEUE_READY)); in vm_del_vq()
342 list_for_each_entry_safe(vq, n, &vdev->vqs, list) in vm_del_vqs()
345 free_irq(platform_get_irq(vm_dev->pdev, 0), vm_dev); in vm_del_vqs()
363 writel(index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL); in vm_setup_vq()
366 if (readl(vm_dev->base + (vm_dev->version == 1 ? in vm_setup_vq()
368 err = -ENOENT; in vm_setup_vq()
375 err = -ENOMEM; in vm_setup_vq()
379 num = readl(vm_dev->base + VIRTIO_MMIO_QUEUE_NUM_MAX); in vm_setup_vq()
381 err = -ENOENT; in vm_setup_vq()
389 err = -ENOMEM; in vm_setup_vq()
394 writel(virtqueue_get_vring_size(vq), vm_dev->base + VIRTIO_MMIO_QUEUE_NUM); in vm_setup_vq()
395 if (vm_dev->version == 1) { in vm_setup_vq()
399 * virtio-mmio v1 uses a 32bit QUEUE PFN. If we have something in vm_setup_vq()
404 dev_err(&vdev->dev, in vm_setup_vq()
405 "platform bug: legacy virtio-mmio must not be used with RAM above 0x%llxGB\n", in vm_setup_vq()
406 0x1ULL << (32 + PAGE_SHIFT - 30)); in vm_setup_vq()
407 err = -E2BIG; in vm_setup_vq()
411 writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_QUEUE_ALIGN); in vm_setup_vq()
412 writel(q_pfn, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); in vm_setup_vq()
417 writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_DESC_LOW); in vm_setup_vq()
419 vm_dev->base + VIRTIO_MMIO_QUEUE_DESC_HIGH); in vm_setup_vq()
422 writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_AVAIL_LOW); in vm_setup_vq()
424 vm_dev->base + VIRTIO_MMIO_QUEUE_AVAIL_HIGH); in vm_setup_vq()
427 writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_USED_LOW); in vm_setup_vq()
429 vm_dev->base + VIRTIO_MMIO_QUEUE_USED_HIGH); in vm_setup_vq()
431 writel(1, vm_dev->base + VIRTIO_MMIO_QUEUE_READY); in vm_setup_vq()
434 vq->priv = info; in vm_setup_vq()
435 info->vq = vq; in vm_setup_vq()
437 spin_lock_irqsave(&vm_dev->lock, flags); in vm_setup_vq()
438 list_add(&info->node, &vm_dev->virtqueues); in vm_setup_vq()
439 spin_unlock_irqrestore(&vm_dev->lock, flags); in vm_setup_vq()
446 if (vm_dev->version == 1) { in vm_setup_vq()
447 writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); in vm_setup_vq()
449 writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_READY); in vm_setup_vq()
450 WARN_ON(readl(vm_dev->base + VIRTIO_MMIO_QUEUE_READY)); in vm_setup_vq()
466 int irq = platform_get_irq(vm_dev->pdev, 0); in vm_find_vqs()
473 dev_name(&vdev->dev), vm_dev); in vm_find_vqs()
498 return vm_dev->pdev->name; in vm_bus_name()
508 writel(id, vm_dev->base + VIRTIO_MMIO_SHM_SEL); in vm_get_shm_region()
511 len = (u64) readl(vm_dev->base + VIRTIO_MMIO_SHM_LEN_LOW); in vm_get_shm_region()
512 len |= (u64) readl(vm_dev->base + VIRTIO_MMIO_SHM_LEN_HIGH) << 32; in vm_get_shm_region()
514 region->len = len; in vm_get_shm_region()
516 /* Check if region length is -1. If that's the case, the shared memory in vm_get_shm_region()
523 addr = (u64) readl(vm_dev->base + VIRTIO_MMIO_SHM_BASE_LOW); in vm_get_shm_region()
524 addr |= (u64) readl(vm_dev->base + VIRTIO_MMIO_SHM_BASE_HIGH) << 32; in vm_get_shm_region()
526 region->addr = addr; in vm_get_shm_region()
553 struct platform_device *pdev = vm_dev->pdev; in virtio_mmio_release_dev()
555 devm_kfree(&pdev->dev, vm_dev); in virtio_mmio_release_dev()
566 vm_dev = devm_kzalloc(&pdev->dev, sizeof(*vm_dev), GFP_KERNEL); in virtio_mmio_probe()
568 return -ENOMEM; in virtio_mmio_probe()
570 vm_dev->vdev.dev.parent = &pdev->dev; in virtio_mmio_probe()
571 vm_dev->vdev.dev.release = virtio_mmio_release_dev; in virtio_mmio_probe()
572 vm_dev->vdev.config = &virtio_mmio_config_ops; in virtio_mmio_probe()
573 vm_dev->pdev = pdev; in virtio_mmio_probe()
574 INIT_LIST_HEAD(&vm_dev->virtqueues); in virtio_mmio_probe()
575 spin_lock_init(&vm_dev->lock); in virtio_mmio_probe()
577 vm_dev->base = devm_platform_ioremap_resource(pdev, 0); in virtio_mmio_probe()
578 if (IS_ERR(vm_dev->base)) in virtio_mmio_probe()
579 return PTR_ERR(vm_dev->base); in virtio_mmio_probe()
582 magic = readl(vm_dev->base + VIRTIO_MMIO_MAGIC_VALUE); in virtio_mmio_probe()
584 dev_warn(&pdev->dev, "Wrong magic value 0x%08lx!\n", magic); in virtio_mmio_probe()
585 return -ENODEV; in virtio_mmio_probe()
589 vm_dev->version = readl(vm_dev->base + VIRTIO_MMIO_VERSION); in virtio_mmio_probe()
590 if (vm_dev->version < 1 || vm_dev->version > 2) { in virtio_mmio_probe()
591 dev_err(&pdev->dev, "Version %ld not supported!\n", in virtio_mmio_probe()
592 vm_dev->version); in virtio_mmio_probe()
593 return -ENXIO; in virtio_mmio_probe()
596 vm_dev->vdev.id.device = readl(vm_dev->base + VIRTIO_MMIO_DEVICE_ID); in virtio_mmio_probe()
597 if (vm_dev->vdev.id.device == 0) { in virtio_mmio_probe()
599 * virtio-mmio device with an ID 0 is a (dummy) placeholder in virtio_mmio_probe()
602 return -ENODEV; in virtio_mmio_probe()
604 vm_dev->vdev.id.vendor = readl(vm_dev->base + VIRTIO_MMIO_VENDOR_ID); in virtio_mmio_probe()
606 if (vm_dev->version == 1) { in virtio_mmio_probe()
607 writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE); in virtio_mmio_probe()
609 rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)); in virtio_mmio_probe()
611 * In the legacy case, ensure our coherently-allocated virtio in virtio_mmio_probe()
612 * ring will be at an address expressable as a 32-bit PFN. in virtio_mmio_probe()
615 dma_set_coherent_mask(&pdev->dev, in virtio_mmio_probe()
618 rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); in virtio_mmio_probe()
621 rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); in virtio_mmio_probe()
623 …dev_warn(&pdev->dev, "Failed to enable 64-bit or 32-bit DMA. Trying to continue, but this might n… in virtio_mmio_probe()
627 rc = register_virtio_device(&vm_dev->vdev); in virtio_mmio_probe()
629 put_device(&vm_dev->vdev.dev); in virtio_mmio_probe()
637 unregister_virtio_device(&vm_dev->vdev); in virtio_mmio_remove()
649 .init_name = "virtio-mmio-cmdline",
680 return -EINVAL; in vm_cmdline_set()
684 resources[0].end = base + size - 1; in vm_cmdline_set()
698 pr_info("Registering device virtio-mmio.%d at 0x%llx-0x%llx, IRQ %d.\n", in vm_cmdline_set()
705 "virtio-mmio", vm_cmdline_id++, in vm_cmdline_set()
717 snprintf(buffer + len, PAGE_SIZE - len, "0x%llx@0x%llx:%llu:%d\n", in vm_cmdline_get_device()
718 pdev->resource[0].end - pdev->resource[0].start + 1ULL, in vm_cmdline_get_device()
719 (unsigned long long)pdev->resource[0].start, in vm_cmdline_get_device()
720 (unsigned long long)pdev->resource[1].start, in vm_cmdline_get_device()
721 pdev->id); in vm_cmdline_get_device()
769 { .compatible = "virtio,mmio", },
786 .name = "virtio-mmio",
807 MODULE_DESCRIPTION("Platform bus driver for memory mapped virtio devices");