powerpc/of/pci: Rewrite pci_parse_of_flags

The existing code uses bunch of hardcoded values from the PCI Bus
Binding to IEEE Std 1275 spec; and it does so in quite non-obvious
way.

This defines fields from the cell#0 of the "reg" property of a PCI
device and uses them for parsing.

This should cause no behavioral change.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
[mpe: Unsplit some 80/81 char lines, space the code with some newlines]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20190829084417.71873-1-aik@ozlabs.ru
This commit is contained in:
Alexey Kardashevskiy 2019-08-29 18:44:17 +10:00 committed by Michael Ellerman
parent f2902a2fb4
commit bc605cd79e
1 changed files with 55 additions and 11 deletions

View File

@ -34,31 +34,75 @@ static u32 get_int_prop(struct device_node *np, const char *name, u32 def)
* pci_parse_of_flags - Parse the flags cell of a device tree PCI address
* @addr0: value of 1st cell of a device tree PCI address.
* @bridge: Set this flag if the address is from a bridge 'ranges' property
*
* PCI Bus Binding to IEEE Std 1275-1994
*
* Bit# 33222222 22221111 11111100 00000000
* 10987654 32109876 54321098 76543210
* phys.hi cell: npt000ss bbbbbbbb dddddfff rrrrrrrr
* phys.mid cell: hhhhhhhh hhhhhhhh hhhhhhhh hhhhhhhh
* phys.lo cell: llllllll llllllll llllllll llllllll
*
* where:
* n is 0 if the address is relocatable, 1 otherwise
* p is 1 if the addressable region is "prefetchable", 0 otherwise
* t is 1 if the address is aliased (for non-relocatable I/O),
* below 1 MB (for Memory),or below 64 KB (for relocatable I/O).
* ss is the space code, denoting the address space:
* 00 denotes Configuration Space
* 01 denotes I/O Space
* 10 denotes 32-bit-address Memory Space
* 11 denotes 64-bit-address Memory Space
* bbbbbbbb is the 8-bit Bus Number
* ddddd is the 5-bit Device Number
* fff is the 3-bit Function Number
* rrrrrrrr is the 8-bit Register Number
*/
#define OF_PCI_ADDR0_SPACE(ss) (((ss)&3)<<24)
#define OF_PCI_ADDR0_SPACE_CFG OF_PCI_ADDR0_SPACE(0)
#define OF_PCI_ADDR0_SPACE_IO OF_PCI_ADDR0_SPACE(1)
#define OF_PCI_ADDR0_SPACE_MMIO32 OF_PCI_ADDR0_SPACE(2)
#define OF_PCI_ADDR0_SPACE_MMIO64 OF_PCI_ADDR0_SPACE(3)
#define OF_PCI_ADDR0_SPACE_MASK OF_PCI_ADDR0_SPACE(3)
#define OF_PCI_ADDR0_RELOC (1UL<<31)
#define OF_PCI_ADDR0_PREFETCH (1UL<<30)
#define OF_PCI_ADDR0_ALIAS (1UL<<29)
#define OF_PCI_ADDR0_BUS 0x00FF0000UL
#define OF_PCI_ADDR0_DEV 0x0000F800UL
#define OF_PCI_ADDR0_FN 0x00000700UL
#define OF_PCI_ADDR0_BARREG 0x000000FFUL
unsigned int pci_parse_of_flags(u32 addr0, int bridge)
{
unsigned int flags = 0;
unsigned int flags = 0, as = addr0 & OF_PCI_ADDR0_SPACE_MASK;
if (addr0 & 0x02000000) {
if (as == OF_PCI_ADDR0_SPACE_MMIO32 || as == OF_PCI_ADDR0_SPACE_MMIO64) {
flags = IORESOURCE_MEM | PCI_BASE_ADDRESS_SPACE_MEMORY;
flags |= (addr0 >> 22) & PCI_BASE_ADDRESS_MEM_TYPE_64;
if (flags & PCI_BASE_ADDRESS_MEM_TYPE_64)
flags |= IORESOURCE_MEM_64;
flags |= (addr0 >> 28) & PCI_BASE_ADDRESS_MEM_TYPE_1M;
if (addr0 & 0x40000000)
flags |= IORESOURCE_PREFETCH
| PCI_BASE_ADDRESS_MEM_PREFETCH;
if (as == OF_PCI_ADDR0_SPACE_MMIO64)
flags |= PCI_BASE_ADDRESS_MEM_TYPE_64 | IORESOURCE_MEM_64;
if (addr0 & OF_PCI_ADDR0_ALIAS)
flags |= PCI_BASE_ADDRESS_MEM_TYPE_1M;
if (addr0 & OF_PCI_ADDR0_PREFETCH)
flags |= IORESOURCE_PREFETCH |
PCI_BASE_ADDRESS_MEM_PREFETCH;
/* Note: We don't know whether the ROM has been left enabled
* by the firmware or not. We mark it as disabled (ie, we do
* not set the IORESOURCE_ROM_ENABLE flag) for now rather than
* do a config space read, it will be force-enabled if needed
*/
if (!bridge && (addr0 & 0xff) == 0x30)
if (!bridge && (addr0 & OF_PCI_ADDR0_BARREG) == PCI_ROM_ADDRESS)
flags |= IORESOURCE_READONLY;
} else if (addr0 & 0x01000000)
} else if (as == OF_PCI_ADDR0_SPACE_IO)
flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO;
if (flags)
flags |= IORESOURCE_SIZEALIGN;
return flags;
}