x86: qemu: add a cpu uclass driver for qemu target
[oweals/u-boot.git] / arch / x86 / cpu / pci.c
1 /*
2  * Copyright (c) 2011 The Chromium OS Authors.
3  * (C) Copyright 2008,2009
4  * Graeme Russ, <graeme.russ@gmail.com>
5  *
6  * (C) Copyright 2002
7  * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
8  *
9  * SPDX-License-Identifier:     GPL-2.0+
10  */
11
12 #include <common.h>
13 #include <dm.h>
14 #include <errno.h>
15 #include <malloc.h>
16 #include <pci.h>
17 #include <asm/io.h>
18 #include <asm/pci.h>
19
20 DECLARE_GLOBAL_DATA_PTR;
21
22 static struct pci_controller *get_hose(void)
23 {
24         if (gd->hose)
25                 return gd->hose;
26
27         return pci_bus_to_hose(0);
28 }
29
30 unsigned int x86_pci_read_config8(pci_dev_t dev, unsigned where)
31 {
32         uint8_t value;
33
34         if (pci_hose_read_config_byte(get_hose(), dev, where, &value))
35                 return -1U;
36
37         return value;
38 }
39
40 unsigned int x86_pci_read_config16(pci_dev_t dev, unsigned where)
41 {
42         uint16_t value;
43
44         if (pci_hose_read_config_word(get_hose(), dev, where, &value))
45                 return -1U;
46
47         return value;
48 }
49
50 unsigned int x86_pci_read_config32(pci_dev_t dev, unsigned where)
51 {
52         uint32_t value;
53
54         if (pci_hose_read_config_dword(get_hose(), dev, where, &value))
55                 return -1U;
56
57         return value;
58 }
59
60 void x86_pci_write_config8(pci_dev_t dev, unsigned where, unsigned value)
61 {
62         pci_hose_write_config_byte(get_hose(), dev, where, value);
63 }
64
65 void x86_pci_write_config16(pci_dev_t dev, unsigned where, unsigned value)
66 {
67         pci_hose_write_config_word(get_hose(), dev, where, value);
68 }
69
70 void x86_pci_write_config32(pci_dev_t dev, unsigned where, unsigned value)
71 {
72         pci_hose_write_config_dword(get_hose(), dev, where, value);
73 }
74
75 int pci_x86_read_config(struct udevice *bus, pci_dev_t bdf, uint offset,
76                         ulong *valuep, enum pci_size_t size)
77 {
78         outl(bdf | (offset & 0xfc) | PCI_CFG_EN, PCI_REG_ADDR);
79         switch (size) {
80         case PCI_SIZE_8:
81                 *valuep = inb(PCI_REG_DATA + (offset & 3));
82                 break;
83         case PCI_SIZE_16:
84                 *valuep = inw(PCI_REG_DATA + (offset & 2));
85                 break;
86         case PCI_SIZE_32:
87                 *valuep = inl(PCI_REG_DATA);
88                 break;
89         }
90
91         return 0;
92 }
93
94 int pci_x86_write_config(struct udevice *bus, pci_dev_t bdf, uint offset,
95                          ulong value, enum pci_size_t size)
96 {
97         outl(bdf | (offset & 0xfc) | PCI_CFG_EN, PCI_REG_ADDR);
98         switch (size) {
99         case PCI_SIZE_8:
100                 outb(value, PCI_REG_DATA + (offset & 3));
101                 break;
102         case PCI_SIZE_16:
103                 outw(value, PCI_REG_DATA + (offset & 2));
104                 break;
105         case PCI_SIZE_32:
106                 outl(value, PCI_REG_DATA);
107                 break;
108         }
109
110         return 0;
111 }
112
113 void pci_assign_irqs(int bus, int device, u8 irq[4])
114 {
115         pci_dev_t bdf;
116         int func;
117         u16 vendor;
118         u8 pin, line;
119
120         for (func = 0; func < 8; func++) {
121                 bdf = PCI_BDF(bus, device, func);
122                 vendor = x86_pci_read_config16(bdf, PCI_VENDOR_ID);
123                 if (vendor == 0xffff || vendor == 0x0000)
124                         continue;
125
126                 pin = x86_pci_read_config8(bdf, PCI_INTERRUPT_PIN);
127
128                 /* PCI spec says all values except 1..4 are reserved */
129                 if ((pin < 1) || (pin > 4))
130                         continue;
131
132                 line = irq[pin - 1];
133                 if (!line)
134                         continue;
135
136                 debug("Assigning IRQ %d to PCI device %d.%x.%d (INT%c)\n",
137                       line, bus, device, func, 'A' + pin - 1);
138
139                 x86_pci_write_config8(bdf, PCI_INTERRUPT_LINE, line);
140         }
141 }