Skip to content

Commit

Permalink
[PATCH] ppc32: Fix MPC52xx configuration space access
Browse files Browse the repository at this point in the history
This patch takes care of an errata of the MPC5200 by avoiding 32 bits access
in type 1 configuration accesses.  All others accesses are still 32 bits wide.
 It also adds some mb() since the simple out_be(...) are not sufficient in
this case.

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Sylvain Munaut authored and Linus Torvalds committed Jan 6, 2006
1 parent dbeb198 commit db674ed
Showing 1 changed file with 69 additions and 14 deletions.
83 changes: 69 additions & 14 deletions arch/ppc/syslib/mpc52xx_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
#include <asm/machdep.h>


/* This macro is defined to activate the workaround for the bug
435 of the MPC5200 (L25R). With it activated, we don't do any
32 bits configuration access during type-1 cycles */
#define MPC5200_BUG_435_WORKAROUND


static int
mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
int offset, int len, u32 *val)
Expand All @@ -40,17 +46,39 @@ mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
((bus->number - hose->bus_offset) << 16) |
(devfn << 8) |
(offset & 0xfc));
mb();

#ifdef MPC5200_BUG_435_WORKAROUND
if (bus->number != hose->bus_offset) {
switch (len) {
case 1:
value = in_8(((u8 __iomem *)hose->cfg_data) + (offset & 3));
break;
case 2:
value = in_le16(((u16 __iomem *)hose->cfg_data) + ((offset>>1) & 1));
break;

default:
value = in_le16((u16 __iomem *)hose->cfg_data) |
(in_le16(((u16 __iomem *)hose->cfg_data) + 1) << 16);
break;
}
}
else
#endif
{
value = in_le32(hose->cfg_data);

value = in_le32(hose->cfg_data);

if (len != 4) {
value >>= ((offset & 0x3) << 3);
value &= 0xffffffff >> (32 - (len << 3));
if (len != 4) {
value >>= ((offset & 0x3) << 3);
value &= 0xffffffff >> (32 - (len << 3));
}
}

*val = value;

out_be32(hose->cfg_addr, 0);
mb();

return PCIBIOS_SUCCESSFUL;
}
Expand All @@ -71,21 +99,48 @@ mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
((bus->number - hose->bus_offset) << 16) |
(devfn << 8) |
(offset & 0xfc));
mb();

#ifdef MPC5200_BUG_435_WORKAROUND
if (bus->number != hose->bus_offset) {
switch (len) {
case 1:
out_8(((u8 __iomem *)hose->cfg_data) +
(offset & 3), val);
break;
case 2:
out_le16(((u16 __iomem *)hose->cfg_data) +
((offset>>1) & 1), val);
break;

default:
out_le16((u16 __iomem *)hose->cfg_data,
(u16)val);
out_le16(((u16 __iomem *)hose->cfg_data) + 1,
(u16)(val>>16));
break;
}
}
else
#endif
{
if (len != 4) {
value = in_le32(hose->cfg_data);

if (len != 4) {
value = in_le32(hose->cfg_data);
offset = (offset & 0x3) << 3;
mask = (0xffffffff >> (32 - (len << 3)));
mask <<= offset;

offset = (offset & 0x3) << 3;
mask = (0xffffffff >> (32 - (len << 3)));
mask <<= offset;
value &= ~mask;
val = value | ((val << offset) & mask);
}

value &= ~mask;
val = value | ((val << offset) & mask);
out_le32(hose->cfg_data, val);
}

out_le32(hose->cfg_data, val);
mb();

out_be32(hose->cfg_addr, 0);
mb();

return PCIBIOS_SUCCESSFUL;
}
Expand Down

0 comments on commit db674ed

Please sign in to comment.