Merge branch '2020-05-18-reduce-size-of-common.h'
[oweals/u-boot.git] / arch / x86 / cpu / pci.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2011 The Chromium OS Authors.
4  * (C) Copyright 2008,2009
5  * Graeme Russ, <graeme.russ@gmail.com>
6  *
7  * (C) Copyright 2002
8  * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
9  */
10
11 #include <common.h>
12 #include <dm.h>
13 #include <errno.h>
14 #include <log.h>
15 #include <malloc.h>
16 #include <pci.h>
17 #include <asm/io.h>
18 #include <asm/pci.h>
19
20 int pci_x86_read_config(pci_dev_t bdf, uint offset, ulong *valuep,
21                         enum pci_size_t size)
22 {
23         outl(bdf | (offset & 0xfc) | PCI_CFG_EN, PCI_REG_ADDR);
24         switch (size) {
25         case PCI_SIZE_8:
26                 *valuep = inb(PCI_REG_DATA + (offset & 3));
27                 break;
28         case PCI_SIZE_16:
29                 *valuep = inw(PCI_REG_DATA + (offset & 2));
30                 break;
31         case PCI_SIZE_32:
32                 *valuep = inl(PCI_REG_DATA);
33                 break;
34         }
35
36         return 0;
37 }
38
39 int pci_x86_write_config(pci_dev_t bdf, uint offset, ulong value,
40                          enum pci_size_t size)
41 {
42         outl(bdf | (offset & 0xfc) | PCI_CFG_EN, PCI_REG_ADDR);
43         switch (size) {
44         case PCI_SIZE_8:
45                 outb(value, PCI_REG_DATA + (offset & 3));
46                 break;
47         case PCI_SIZE_16:
48                 outw(value, PCI_REG_DATA + (offset & 2));
49                 break;
50         case PCI_SIZE_32:
51                 outl(value, PCI_REG_DATA);
52                 break;
53         }
54
55         return 0;
56 }
57
58 int pci_x86_clrset_config(pci_dev_t bdf, uint offset, ulong clr, ulong set,
59                           enum pci_size_t size)
60 {
61         ulong value;
62         int ret;
63
64         ret = pci_x86_read_config(bdf, offset, &value, size);
65         if (ret)
66                 return ret;
67         value &= ~clr;
68         value |= set;
69
70         return pci_x86_write_config(bdf, offset, value, size);
71 }
72
73 void pci_assign_irqs(int bus, int device, u8 irq[4])
74 {
75         pci_dev_t bdf;
76         int func;
77         u16 vendor;
78         u8 pin, line;
79
80         for (func = 0; func < 8; func++) {
81                 bdf = PCI_BDF(bus, device, func);
82                 pci_read_config16(bdf, PCI_VENDOR_ID, &vendor);
83                 if (vendor == 0xffff || vendor == 0x0000)
84                         continue;
85
86                 pci_read_config8(bdf, PCI_INTERRUPT_PIN, &pin);
87
88                 /* PCI spec says all values except 1..4 are reserved */
89                 if ((pin < 1) || (pin > 4))
90                         continue;
91
92                 line = irq[pin - 1];
93                 if (!line)
94                         continue;
95
96                 debug("Assigning IRQ %d to PCI device %d.%x.%d (INT%c)\n",
97                       line, bus, device, func, 'A' + pin - 1);
98
99                 pci_write_config8(bdf, PCI_INTERRUPT_LINE, line);
100         }
101 }