xref: /openbmc/u-boot/arch/x86/cpu/pci.c (revision 83bf0057)
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 x86_hose;
23 
24 int pci_early_init_hose(struct pci_controller **hosep)
25 {
26 	struct pci_controller *hose;
27 
28 	hose = calloc(1, sizeof(struct pci_controller));
29 	if (!hose)
30 		return -ENOMEM;
31 
32 	board_pci_setup_hose(hose);
33 	pci_setup_type1(hose);
34 	hose->last_busno = pci_hose_scan(hose);
35 	gd->hose = hose;
36 	*hosep = hose;
37 
38 	return 0;
39 }
40 
41 __weak int board_pci_pre_scan(struct pci_controller *hose)
42 {
43 	return 0;
44 }
45 
46 __weak int board_pci_post_scan(struct pci_controller *hose)
47 {
48 	return 0;
49 }
50 
51 void pci_init_board(void)
52 {
53 	struct pci_controller *hose = &x86_hose;
54 
55 	/* Stop using the early hose */
56 	gd->hose = NULL;
57 
58 	board_pci_setup_hose(hose);
59 	pci_setup_type1(hose);
60 	pci_register_hose(hose);
61 
62 	board_pci_pre_scan(hose);
63 	hose->last_busno = pci_hose_scan(hose);
64 	board_pci_post_scan(hose);
65 }
66 
67 static struct pci_controller *get_hose(void)
68 {
69 	if (gd->hose)
70 		return gd->hose;
71 
72 	return pci_bus_to_hose(0);
73 }
74 
75 unsigned int x86_pci_read_config8(pci_dev_t dev, unsigned where)
76 {
77 	uint8_t value;
78 
79 	if (pci_hose_read_config_byte(get_hose(), dev, where, &value))
80 		return -1U;
81 
82 	return value;
83 }
84 
85 unsigned int x86_pci_read_config16(pci_dev_t dev, unsigned where)
86 {
87 	uint16_t value;
88 
89 	if (pci_hose_read_config_word(get_hose(), dev, where, &value))
90 		return -1U;
91 
92 	return value;
93 }
94 
95 unsigned int x86_pci_read_config32(pci_dev_t dev, unsigned where)
96 {
97 	uint32_t value;
98 
99 	if (pci_hose_read_config_dword(get_hose(), dev, where, &value))
100 		return -1U;
101 
102 	return value;
103 }
104 
105 void x86_pci_write_config8(pci_dev_t dev, unsigned where, unsigned value)
106 {
107 	pci_hose_write_config_byte(get_hose(), dev, where, value);
108 }
109 
110 void x86_pci_write_config16(pci_dev_t dev, unsigned where, unsigned value)
111 {
112 	pci_hose_write_config_word(get_hose(), dev, where, value);
113 }
114 
115 void x86_pci_write_config32(pci_dev_t dev, unsigned where, unsigned value)
116 {
117 	pci_hose_write_config_dword(get_hose(), dev, where, value);
118 }
119 
120 int pci_x86_read_config(struct udevice *bus, pci_dev_t bdf, uint offset,
121 			ulong *valuep, enum pci_size_t size)
122 {
123 	outl(bdf | (offset & 0xfc) | PCI_CFG_EN, PCI_REG_ADDR);
124 	switch (size) {
125 	case PCI_SIZE_8:
126 		*valuep = inb(PCI_REG_DATA + (offset & 3));
127 		break;
128 	case PCI_SIZE_16:
129 		*valuep = inw(PCI_REG_DATA + (offset & 2));
130 		break;
131 	case PCI_SIZE_32:
132 		*valuep = inl(PCI_REG_DATA);
133 		break;
134 	}
135 
136 	return 0;
137 }
138 
139 int pci_x86_write_config(struct udevice *bus, pci_dev_t bdf, uint offset,
140 			 ulong value, enum pci_size_t size)
141 {
142 	outl(bdf | (offset & 0xfc) | PCI_CFG_EN, PCI_REG_ADDR);
143 	switch (size) {
144 	case PCI_SIZE_8:
145 		outb(value, PCI_REG_DATA + (offset & 3));
146 		break;
147 	case PCI_SIZE_16:
148 		outw(value, PCI_REG_DATA + (offset & 2));
149 		break;
150 	case PCI_SIZE_32:
151 		outl(value, PCI_REG_DATA);
152 		break;
153 	}
154 
155 	return 0;
156 }
157 
158 void pci_assign_irqs(int bus, int device, u8 irq[4])
159 {
160 	pci_dev_t bdf;
161 	int func;
162 	u16 vendor;
163 	u8 pin, line;
164 
165 	for (func = 0; func < 8; func++) {
166 		bdf = PCI_BDF(bus, device, func);
167 		vendor = x86_pci_read_config16(bdf, PCI_VENDOR_ID);
168 		if (vendor == 0xffff || vendor == 0x0000)
169 			continue;
170 
171 		pin = x86_pci_read_config8(bdf, PCI_INTERRUPT_PIN);
172 
173 		/* PCI spec says all values except 1..4 are reserved */
174 		if ((pin < 1) || (pin > 4))
175 			continue;
176 
177 		line = irq[pin - 1];
178 		if (!line)
179 			continue;
180 
181 		debug("Assigning IRQ %d to PCI device %d.%x.%d (INT%c)\n",
182 		      line, bus, device, func, 'A' + pin - 1);
183 
184 		x86_pci_write_config8(bdf, PCI_INTERRUPT_LINE, line);
185 	}
186 }
187