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