Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit db674ed4 authored by Sylvain Munaut's avatar Sylvain Munaut Committed by Linus Torvalds
Browse files

[PATCH] ppc32: Fix MPC52xx configuration space access



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: default avatarSylvain Munaut <tnt@246tNt.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent dbeb198d
Loading
Loading
Loading
Loading
+69 −14
Original line number Diff line number Diff line
@@ -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)
@@ -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);

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

	*val = value;

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

	return PCIBIOS_SUCCESSFUL;
}
@@ -71,7 +99,31 @@ 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);

@@ -84,8 +136,11 @@ mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
		}

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

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

	return PCIBIOS_SUCCESSFUL;
}