linux/arch/mips/pci/pci-virtio-guest.c
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Copyright (C) 2013 Cavium, Inc.
   7 */
   8
   9#include <linux/kernel.h>
  10#include <linux/init.h>
  11#include <linux/interrupt.h>
  12#include <linux/pci.h>
  13
  14#include <uapi/asm/bitfield.h>
  15#include <asm/byteorder.h>
  16#include <asm/io.h>
  17
  18#define PCI_CONFIG_ADDRESS      0xcf8
  19#define PCI_CONFIG_DATA         0xcfc
  20
  21union pci_config_address {
  22        struct {
  23                __BITFIELD_FIELD(unsigned enable_bit      : 1,  /* 31       */
  24                __BITFIELD_FIELD(unsigned reserved        : 7,  /* 30 .. 24 */
  25                __BITFIELD_FIELD(unsigned bus_number      : 8,  /* 23 .. 16 */
  26                __BITFIELD_FIELD(unsigned devfn_number    : 8,  /* 15 .. 8  */
  27                __BITFIELD_FIELD(unsigned register_number : 8,  /* 7  .. 0  */
  28                )))));
  29        };
  30        u32 w;
  31};
  32
  33int pcibios_plat_dev_init(struct pci_dev *dev)
  34{
  35        return 0;
  36}
  37
  38int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
  39{
  40        return ((pin + slot) % 4)+ MIPS_IRQ_PCIA;
  41}
  42
  43static void pci_virtio_guest_write_config_addr(struct pci_bus *bus,
  44                                        unsigned int devfn, int reg)
  45{
  46        union pci_config_address pca = { .w = 0 };
  47
  48        pca.register_number = reg;
  49        pca.devfn_number = devfn;
  50        pca.bus_number = bus->number;
  51        pca.enable_bit = 1;
  52
  53        outl(pca.w, PCI_CONFIG_ADDRESS);
  54}
  55
  56static int pci_virtio_guest_write_config(struct pci_bus *bus,
  57                unsigned int devfn, int reg, int size, u32 val)
  58{
  59        pci_virtio_guest_write_config_addr(bus, devfn, reg);
  60
  61        switch (size) {
  62        case 1:
  63                outb(val, PCI_CONFIG_DATA + (reg & 3));
  64                break;
  65        case 2:
  66                outw(val, PCI_CONFIG_DATA + (reg & 2));
  67                break;
  68        case 4:
  69                outl(val, PCI_CONFIG_DATA);
  70                break;
  71        }
  72
  73        return PCIBIOS_SUCCESSFUL;
  74}
  75
  76static int pci_virtio_guest_read_config(struct pci_bus *bus, unsigned int devfn,
  77                                        int reg, int size, u32 *val)
  78{
  79        pci_virtio_guest_write_config_addr(bus, devfn, reg);
  80
  81        switch (size) {
  82        case 1:
  83                *val = inb(PCI_CONFIG_DATA + (reg & 3));
  84                break;
  85        case 2:
  86                *val = inw(PCI_CONFIG_DATA + (reg & 2));
  87                break;
  88        case 4:
  89                *val = inl(PCI_CONFIG_DATA);
  90                break;
  91        }
  92        return PCIBIOS_SUCCESSFUL;
  93}
  94
  95static struct pci_ops pci_virtio_guest_ops = {
  96        .read  = pci_virtio_guest_read_config,
  97        .write = pci_virtio_guest_write_config,
  98};
  99
 100static struct resource pci_virtio_guest_mem_resource = {
 101        .name = "Virtio MEM",
 102        .flags = IORESOURCE_MEM,
 103        .start  = 0x10000000,
 104        .end    = 0x1dffffff
 105};
 106
 107static struct resource pci_virtio_guest_io_resource = {
 108        .name = "Virtio IO",
 109        .flags = IORESOURCE_IO,
 110        .start  = 0,
 111        .end    = 0xffff
 112};
 113
 114static struct pci_controller pci_virtio_guest_controller = {
 115        .pci_ops = &pci_virtio_guest_ops,
 116        .mem_resource = &pci_virtio_guest_mem_resource,
 117        .io_resource = &pci_virtio_guest_io_resource,
 118};
 119
 120static int __init pci_virtio_guest_setup(void)
 121{
 122        pr_err("pci_virtio_guest_setup\n");
 123
 124        /* Virtio comes pre-assigned */
 125        pci_set_flags(PCI_PROBE_ONLY);
 126
 127        pci_virtio_guest_controller.io_map_base = mips_io_port_base;
 128        register_pci_controller(&pci_virtio_guest_controller);
 129        return 0;
 130}
 131arch_initcall(pci_virtio_guest_setup);
 132