• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
21 union 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 
pcibios_plat_dev_init(struct pci_dev * dev)33 int pcibios_plat_dev_init(struct pci_dev *dev)
34 {
35 	return 0;
36 }
37 
pcibios_map_irq(const struct pci_dev * dev,u8 slot,u8 pin)38 int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
39 {
40 	return ((pin + slot) % 4)+ MIPS_IRQ_PCIA;
41 }
42 
pci_virtio_guest_write_config_addr(struct pci_bus * bus,unsigned int devfn,int reg)43 static 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 
pci_virtio_guest_write_config(struct pci_bus * bus,unsigned int devfn,int reg,int size,u32 val)56 static 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 
pci_virtio_guest_read_config(struct pci_bus * bus,unsigned int devfn,int reg,int size,u32 * val)76 static 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 
95 static struct pci_ops pci_virtio_guest_ops = {
96 	.read  = pci_virtio_guest_read_config,
97 	.write = pci_virtio_guest_write_config,
98 };
99 
100 static struct resource pci_virtio_guest_mem_resource = {
101 	.name = "Virtio MEM",
102 	.flags = IORESOURCE_MEM,
103 	.start	= 0x10000000,
104 	.end	= 0x1dffffff
105 };
106 
107 static struct resource pci_virtio_guest_io_resource = {
108 	.name = "Virtio IO",
109 	.flags = IORESOURCE_IO,
110 	.start	= 0,
111 	.end	= 0xffff
112 };
113 
114 static 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 
pci_virtio_guest_setup(void)120 static 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 }
131 arch_initcall(pci_virtio_guest_setup);
132