Commit bc605cd7 authored by Alexey Kardashevskiy's avatar Alexey Kardashevskiy Committed by Michael Ellerman
Browse files

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: default avatarAlexey Kardashevskiy <aik@ozlabs.ru>
[mpe: Unsplit some 80/81 char lines, space the code with some newlines]
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20190829084417.71873-1-aik@ozlabs.ru
parent f2902a2f
Loading
Loading
Loading
Loading
+55 −11
Original line number Original line Diff line number Diff line
@@ -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
 * 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.
 * @addr0: value of 1st cell of a device tree PCI address.
 * @bridge: Set this flag if the address is from a bridge 'ranges' property
 * @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 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 = IORESOURCE_MEM | PCI_BASE_ADDRESS_SPACE_MEMORY;
		flags |= (addr0 >> 22) & PCI_BASE_ADDRESS_MEM_TYPE_64;

		if (flags & PCI_BASE_ADDRESS_MEM_TYPE_64)
		if (as == OF_PCI_ADDR0_SPACE_MMIO64)
			flags |= IORESOURCE_MEM_64;
			flags |= PCI_BASE_ADDRESS_MEM_TYPE_64 | IORESOURCE_MEM_64;
		flags |= (addr0 >> 28) & PCI_BASE_ADDRESS_MEM_TYPE_1M;

		if (addr0 & 0x40000000)
		if (addr0 & OF_PCI_ADDR0_ALIAS)
			flags |= IORESOURCE_PREFETCH
			flags |= PCI_BASE_ADDRESS_MEM_TYPE_1M;
				 | PCI_BASE_ADDRESS_MEM_PREFETCH;

		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
		/* 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
		 * by the firmware or not. We mark it as disabled (ie, we do
		 * not set the IORESOURCE_ROM_ENABLE flag) for now rather than
		 * not set the IORESOURCE_ROM_ENABLE flag) for now rather than
		 * do a config space read, it will be force-enabled if needed
		 * 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;
			flags |= IORESOURCE_READONLY;
	} else if (addr0 & 0x01000000)

	} else if (as == OF_PCI_ADDR0_SPACE_IO)
		flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO;
		flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO;

	if (flags)
	if (flags)
		flags |= IORESOURCE_SIZEALIGN;
		flags |= IORESOURCE_SIZEALIGN;

	return flags;
	return flags;
}
}