m68k: fix ColdFire PCI config reads and writes
authorGreg Ungerer <gerg@linux-m68k.org>
Wed, 11 Apr 2018 03:39:44 +0000 (13:39 +1000)
committerGreg Ungerer <gerg@linux-m68k.org>
Sun, 27 May 2018 23:45:27 +0000 (09:45 +1000)
The ColdFire PCI configuration space access functions swap addressing
regions to do their work. Just letting the read/write cycles exit
the CPU core (via the ColdFire "nop" instruction) is not enough to
guarantee that the address region remapping has actually completed.
Insert a read back of the mapping register to be absolutely sure
that the remapping has completed.

This fixes an occasional boot hang during the ColdFire PCI initialization
phase.

Signed-off-by: Greg Ungerer <gerg@linux-m68k.org>
Reviewed-by: Angelo Dureghello <angelo@sysam.it>
Tested-by: Angelo Dureghello <angelo@sysam.it>
arch/m68k/coldfire/pci.c

index db709ad30f88df3f80d4c3a27b00e197b70f46f2..62b0eb6cf69a357bc3f921a22f20a638d5eb55e3 100644 (file)
@@ -46,13 +46,6 @@ static unsigned char mcf_host_irq[] = {
        0, 69, 69, 71, 71,
 };
 
-
-static inline void syncio(void)
-{
-       /* The ColdFire "nop" instruction waits for all bus IO to complete */
-       __asm__ __volatile__ ("nop");
-}
-
 /*
  * Configuration space access functions. Configuration space access is
  * through the IO mapping window, enabling it via the PCICAR register.
@@ -74,9 +67,9 @@ static int mcf_pci_readconfig(struct pci_bus *bus, unsigned int devfn,
                        return PCIBIOS_SUCCESSFUL;
        }
 
-       syncio();
        addr = mcf_mk_pcicar(bus->number, devfn, where);
        __raw_writel(PCICAR_E | addr, PCICAR);
+       __raw_readl(PCICAR);
        addr = iospace + (where & 0x3);
 
        switch (size) {
@@ -91,8 +84,8 @@ static int mcf_pci_readconfig(struct pci_bus *bus, unsigned int devfn,
                break;
        }
 
-       syncio();
        __raw_writel(0, PCICAR);
+       __raw_readl(PCICAR);
        return PCIBIOS_SUCCESSFUL;
 }
 
@@ -106,9 +99,9 @@ static int mcf_pci_writeconfig(struct pci_bus *bus, unsigned int devfn,
                        return PCIBIOS_SUCCESSFUL;
        }
 
-       syncio();
        addr = mcf_mk_pcicar(bus->number, devfn, where);
        __raw_writel(PCICAR_E | addr, PCICAR);
+       __raw_readl(PCICAR);
        addr = iospace + (where & 0x3);
 
        switch (size) {
@@ -123,8 +116,8 @@ static int mcf_pci_writeconfig(struct pci_bus *bus, unsigned int devfn,
                break;
        }
 
-       syncio();
        __raw_writel(0, PCICAR);
+       __raw_readl(PCICAR);
        return PCIBIOS_SUCCESSFUL;
 }