xref: /openbmc/u-boot/arch/x86/cpu/pci.c (revision 60570df1)
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 	pci_hose_read_config_byte(get_hose(), dev, where, &value);
80 
81 	return value;
82 }
83 
84 unsigned int x86_pci_read_config16(pci_dev_t dev, unsigned where)
85 {
86 	uint16_t value;
87 
88 	pci_hose_read_config_word(get_hose(), dev, where, &value);
89 
90 	return value;
91 }
92 
93 unsigned int x86_pci_read_config32(pci_dev_t dev, unsigned where)
94 {
95 	uint32_t value;
96 
97 	pci_hose_read_config_dword(get_hose(), dev, where, &value);
98 
99 	return value;
100 }
101 
102 void x86_pci_write_config8(pci_dev_t dev, unsigned where, unsigned value)
103 {
104 	pci_hose_write_config_byte(get_hose(), dev, where, value);
105 }
106 
107 void x86_pci_write_config16(pci_dev_t dev, unsigned where, unsigned value)
108 {
109 	pci_hose_write_config_word(get_hose(), dev, where, value);
110 }
111 
112 void x86_pci_write_config32(pci_dev_t dev, unsigned where, unsigned value)
113 {
114 	pci_hose_write_config_dword(get_hose(), dev, where, value);
115 }
116 
117 int pci_x86_read_config(struct udevice *bus, pci_dev_t bdf, uint offset,
118 			ulong *valuep, enum pci_size_t size)
119 {
120 	outl(bdf | (offset & 0xfc) | PCI_CFG_EN, PCI_REG_ADDR);
121 	switch (size) {
122 	case PCI_SIZE_8:
123 		*valuep = inb(PCI_REG_DATA + (offset & 3));
124 		break;
125 	case PCI_SIZE_16:
126 		*valuep = inw(PCI_REG_DATA + (offset & 2));
127 		break;
128 	case PCI_SIZE_32:
129 		*valuep = inl(PCI_REG_DATA);
130 		break;
131 	}
132 
133 	return 0;
134 }
135 
136 int pci_x86_write_config(struct udevice *bus, pci_dev_t bdf, uint offset,
137 			 ulong value, enum pci_size_t size)
138 {
139 	outl(bdf | (offset & 0xfc) | PCI_CFG_EN, PCI_REG_ADDR);
140 	switch (size) {
141 	case PCI_SIZE_8:
142 		outb(value, PCI_REG_DATA + (offset & 3));
143 		break;
144 	case PCI_SIZE_16:
145 		outw(value, PCI_REG_DATA + (offset & 2));
146 		break;
147 	case PCI_SIZE_32:
148 		outl(value, PCI_REG_DATA);
149 		break;
150 	}
151 
152 	return 0;
153 }
154 
155 void pci_assign_irqs(int bus, int device, int func, u8 irq[4])
156 {
157 	pci_dev_t bdf;
158 	u8 pin, line;
159 
160 	bdf = PCI_BDF(bus, device, func);
161 
162 	pin = x86_pci_read_config8(bdf, PCI_INTERRUPT_PIN);
163 
164 	/* PCI spec says all values except 1..4 are reserved */
165 	if ((pin < 1) || (pin > 4))
166 		return;
167 
168 	line = irq[pin - 1];
169 
170 	debug("Assigning IRQ %d to PCI device %d.%x.%d (INT%c)\n",
171 	      line, bus, device, func, 'A' + pin - 1);
172 
173 	x86_pci_write_config8(bdf, PCI_INTERRUPT_LINE, line);
174 }
175