blob: e46d45da99c252e90d2baa0462a0a8e0537684f4 [file] [log] [blame]
Stefan Reinauer00636b02012-04-04 00:08:51 +02001/*
2 * This file is part of the coreboot project.
3 *
Stefan Reinauer00636b02012-04-04 00:08:51 +02004 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
Stefan Reinauer00636b02012-04-04 00:08:51 +020013 */
14
Kyösti Mälkki54d6abd2013-06-19 23:05:00 +030015#ifndef _PCI_MMIO_CFG_H
16#define _PCI_MMIO_CFG_H
17
Kyösti Mälkki8fd78a62019-01-23 15:59:38 +020018#include <stdint.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +020019#include <device/mmio.h>
Kyösti Mälkki8fd78a62019-01-23 15:59:38 +020020#include <device/pci_type.h>
Kyösti Mälkki54d6abd2013-06-19 23:05:00 +030021
Kyösti Mälkkid2cdfff2019-03-05 07:56:38 +020022
23/* By not assigning this to CONFIG_MMCONF_BASE_ADDRESS here we
24 * prevent some sub-optimal constant folding. */
25extern u8 *const pci_mmconf;
26
27/* Using a unique datatype for MMIO writes makes the pointers to _not_
28 * qualify for pointer aliasing with any other objects in memory.
29 *
30 * MMIO offset is a value originally derived from 'struct device *'
31 * in ramstage. For the compiler to not discard this MMIO offset value
32 * from CPU registers after any MMIO writes, -fstrict-aliasing has to
33 * be also set for the build.
34 *
35 * Bottom 12 bits (4 KiB) are reserved to address the registers of a
36 * single PCI function. Declare the bank as a union to avoid some casting
37 * in the functions below.
38 */
39union pci_bank {
40 uint8_t reg8[4096];
41 uint16_t reg16[4096 / sizeof(uint16_t)];
42 uint32_t reg32[4096 / sizeof(uint32_t)];
43};
44
45static __always_inline
46volatile union pci_bank *pcicfg(pci_devfn_t dev)
47{
48 return (void *)&pci_mmconf[PCI_DEVFN_OFFSET(dev)];
49}
Stefan Reinauer00636b02012-04-04 00:08:51 +020050
Aaron Durbin75a62e72018-09-13 02:10:45 -060051static __always_inline
Kyösti Mälkkib603fdc2019-03-11 20:33:01 +020052uint8_t pci_mmio_read_config8(pci_devfn_t dev, uint16_t reg)
Stefan Reinauer00636b02012-04-04 00:08:51 +020053{
Kyösti Mälkkid2cdfff2019-03-05 07:56:38 +020054 return pcicfg(dev)->reg8[reg];
Stefan Reinauer00636b02012-04-04 00:08:51 +020055}
56
Aaron Durbin75a62e72018-09-13 02:10:45 -060057static __always_inline
Kyösti Mälkkib603fdc2019-03-11 20:33:01 +020058uint16_t pci_mmio_read_config16(pci_devfn_t dev, uint16_t reg)
Stefan Reinauer00636b02012-04-04 00:08:51 +020059{
Kyösti Mälkkid2cdfff2019-03-05 07:56:38 +020060 return pcicfg(dev)->reg16[reg / sizeof(uint16_t)];
Stefan Reinauer00636b02012-04-04 00:08:51 +020061}
62
Aaron Durbin75a62e72018-09-13 02:10:45 -060063static __always_inline
Kyösti Mälkkib603fdc2019-03-11 20:33:01 +020064uint32_t pci_mmio_read_config32(pci_devfn_t dev, uint16_t reg)
Stefan Reinauer00636b02012-04-04 00:08:51 +020065{
Kyösti Mälkkid2cdfff2019-03-05 07:56:38 +020066 return pcicfg(dev)->reg32[reg / sizeof(uint32_t)];
Stefan Reinauer00636b02012-04-04 00:08:51 +020067}
68
Aaron Durbin75a62e72018-09-13 02:10:45 -060069static __always_inline
Kyösti Mälkkib603fdc2019-03-11 20:33:01 +020070void pci_mmio_write_config8(pci_devfn_t dev, uint16_t reg, uint8_t value)
Stefan Reinauer00636b02012-04-04 00:08:51 +020071{
Kyösti Mälkkid2cdfff2019-03-05 07:56:38 +020072 pcicfg(dev)->reg8[reg] = value;
Stefan Reinauer00636b02012-04-04 00:08:51 +020073}
74
Aaron Durbin75a62e72018-09-13 02:10:45 -060075static __always_inline
Kyösti Mälkkib603fdc2019-03-11 20:33:01 +020076void pci_mmio_write_config16(pci_devfn_t dev, uint16_t reg, uint16_t value)
Stefan Reinauer00636b02012-04-04 00:08:51 +020077{
Kyösti Mälkkid2cdfff2019-03-05 07:56:38 +020078 pcicfg(dev)->reg16[reg / sizeof(uint16_t)] = value;
Stefan Reinauer00636b02012-04-04 00:08:51 +020079}
80
Aaron Durbin75a62e72018-09-13 02:10:45 -060081static __always_inline
Kyösti Mälkkib603fdc2019-03-11 20:33:01 +020082void pci_mmio_write_config32(pci_devfn_t dev, uint16_t reg, uint32_t value)
Stefan Reinauer00636b02012-04-04 00:08:51 +020083{
Kyösti Mälkkid2cdfff2019-03-05 07:56:38 +020084 pcicfg(dev)->reg32[reg / sizeof(uint32_t)] = value;
Stefan Reinauer00636b02012-04-04 00:08:51 +020085}
86
Michael Niewöhnerefe3cfb2019-11-15 22:47:33 +010087/*
88 * The functions pci_mmio_config*_addr provide a way to determine the MMIO address of a PCI
89 * config register. The address returned is dependent of both the MMCONF base address and the
90 * assigned PCI bus number of the requested device, which both can change during the boot
91 * process. Thus, the pointer returned here must not be cached!
92 */
Michael Niewöhner8f221362019-11-08 22:02:02 +010093static __always_inline
94uint8_t *pci_mmio_config8_addr(pci_devfn_t dev, uint16_t reg)
95{
96 return (uint8_t *)&pcicfg(dev)->reg8[reg];
97}
98
99static __always_inline
100uint16_t *pci_mmio_config16_addr(pci_devfn_t dev, uint16_t reg)
101{
102 return (uint16_t *)&pcicfg(dev)->reg16[reg / sizeof(uint16_t)];
103}
104
105static __always_inline
106uint32_t *pci_mmio_config32_addr(pci_devfn_t dev, uint16_t reg)
107{
108 return (uint32_t *)&pcicfg(dev)->reg32[reg / sizeof(uint32_t)];
109}
110
Julius Wernercd49cce2019-03-05 16:53:33 -0800111#if CONFIG(MMCONF_SUPPORT)
Kyösti Mälkki2d8aff32019-01-23 16:44:55 +0200112
Arthur Heymans15fcc862019-10-08 11:29:12 +0200113#if CONFIG_MMCONF_BASE_ADDRESS == 0
114#error "CONFIG_MMCONF_BASE_ADDRESS undefined!"
115#endif
116
Kyösti Mälkki92b52962019-03-01 08:08:28 +0200117/* Avoid name collisions as different stages have different signature
118 * for these functions. The _s_ stands for simple, fundamental IO or
119 * MMIO variant.
120 */
121
Kyösti Mälkki2d8aff32019-01-23 16:44:55 +0200122static __always_inline
Kyösti Mälkkib603fdc2019-03-11 20:33:01 +0200123uint8_t pci_s_read_config8(pci_devfn_t dev, uint16_t reg)
Kyösti Mälkki2d8aff32019-01-23 16:44:55 +0200124{
Kyösti Mälkkib603fdc2019-03-11 20:33:01 +0200125 return pci_mmio_read_config8(dev, reg);
Kyösti Mälkki2d8aff32019-01-23 16:44:55 +0200126}
127
128static __always_inline
Kyösti Mälkkib603fdc2019-03-11 20:33:01 +0200129uint16_t pci_s_read_config16(pci_devfn_t dev, uint16_t reg)
Kyösti Mälkki2d8aff32019-01-23 16:44:55 +0200130{
Kyösti Mälkkib603fdc2019-03-11 20:33:01 +0200131 return pci_mmio_read_config16(dev, reg);
Kyösti Mälkki2d8aff32019-01-23 16:44:55 +0200132}
133
134static __always_inline
Kyösti Mälkkib603fdc2019-03-11 20:33:01 +0200135uint32_t pci_s_read_config32(pci_devfn_t dev, uint16_t reg)
Kyösti Mälkki2d8aff32019-01-23 16:44:55 +0200136{
Kyösti Mälkkib603fdc2019-03-11 20:33:01 +0200137 return pci_mmio_read_config32(dev, reg);
Kyösti Mälkki2d8aff32019-01-23 16:44:55 +0200138}
139
140static __always_inline
Kyösti Mälkkib603fdc2019-03-11 20:33:01 +0200141void pci_s_write_config8(pci_devfn_t dev, uint16_t reg, uint8_t value)
Kyösti Mälkki2d8aff32019-01-23 16:44:55 +0200142{
Kyösti Mälkkib603fdc2019-03-11 20:33:01 +0200143 pci_mmio_write_config8(dev, reg, value);
Kyösti Mälkki2d8aff32019-01-23 16:44:55 +0200144}
145
146static __always_inline
Kyösti Mälkkib603fdc2019-03-11 20:33:01 +0200147void pci_s_write_config16(pci_devfn_t dev, uint16_t reg, uint16_t value)
Kyösti Mälkki2d8aff32019-01-23 16:44:55 +0200148{
Kyösti Mälkkib603fdc2019-03-11 20:33:01 +0200149 pci_mmio_write_config16(dev, reg, value);
Kyösti Mälkki2d8aff32019-01-23 16:44:55 +0200150}
151
152static __always_inline
Kyösti Mälkkib603fdc2019-03-11 20:33:01 +0200153void pci_s_write_config32(pci_devfn_t dev, uint16_t reg, uint32_t value)
Kyösti Mälkki2d8aff32019-01-23 16:44:55 +0200154{
Kyösti Mälkkib603fdc2019-03-11 20:33:01 +0200155 pci_mmio_write_config32(dev, reg, value);
Kyösti Mälkki2d8aff32019-01-23 16:44:55 +0200156}
Kyösti Mälkki2d8aff32019-01-23 16:44:55 +0200157
158#endif
159
Kyösti Mälkki54d6abd2013-06-19 23:05:00 +0300160#endif /* _PCI_MMIO_CFG_H */