aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc/syslib/mpc52xx_pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc/syslib/mpc52xx_pci.c')
-rw-r--r--arch/ppc/syslib/mpc52xx_pci.c95
1 files changed, 76 insertions, 19 deletions
diff --git a/arch/ppc/syslib/mpc52xx_pci.c b/arch/ppc/syslib/mpc52xx_pci.c
index 4ac19080eb85..313c96ec7eb1 100644
--- a/arch/ppc/syslib/mpc52xx_pci.c
+++ b/arch/ppc/syslib/mpc52xx_pci.c
@@ -24,6 +24,12 @@
24#include <asm/machdep.h> 24#include <asm/machdep.h>
25 25
26 26
27/* This macro is defined to activate the workaround for the bug
28 435 of the MPC5200 (L25R). With it activated, we don't do any
29 32 bits configuration access during type-1 cycles */
30#define MPC5200_BUG_435_WORKAROUND
31
32
27static int 33static int
28mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, 34mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
29 int offset, int len, u32 *val) 35 int offset, int len, u32 *val)
@@ -40,17 +46,39 @@ mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
40 ((bus->number - hose->bus_offset) << 16) | 46 ((bus->number - hose->bus_offset) << 16) |
41 (devfn << 8) | 47 (devfn << 8) |
42 (offset & 0xfc)); 48 (offset & 0xfc));
49 mb();
50
51#ifdef MPC5200_BUG_435_WORKAROUND
52 if (bus->number != hose->bus_offset) {
53 switch (len) {
54 case 1:
55 value = in_8(((u8 __iomem *)hose->cfg_data) + (offset & 3));
56 break;
57 case 2:
58 value = in_le16(((u16 __iomem *)hose->cfg_data) + ((offset>>1) & 1));
59 break;
60
61 default:
62 value = in_le16((u16 __iomem *)hose->cfg_data) |
63 (in_le16(((u16 __iomem *)hose->cfg_data) + 1) << 16);
64 break;
65 }
66 }
67 else
68#endif
69 {
70 value = in_le32(hose->cfg_data);
43 71
44 value = in_le32(hose->cfg_data); 72 if (len != 4) {
45 73 value >>= ((offset & 0x3) << 3);
46 if (len != 4) { 74 value &= 0xffffffff >> (32 - (len << 3));
47 value >>= ((offset & 0x3) << 3); 75 }
48 value &= 0xffffffff >> (32 - (len << 3));
49 } 76 }
50 77
51 *val = value; 78 *val = value;
52 79
53 out_be32(hose->cfg_addr, 0); 80 out_be32(hose->cfg_addr, 0);
81 mb();
54 82
55 return PCIBIOS_SUCCESSFUL; 83 return PCIBIOS_SUCCESSFUL;
56} 84}
@@ -71,21 +99,48 @@ mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
71 ((bus->number - hose->bus_offset) << 16) | 99 ((bus->number - hose->bus_offset) << 16) |
72 (devfn << 8) | 100 (devfn << 8) |
73 (offset & 0xfc)); 101 (offset & 0xfc));
102 mb();
103
104#ifdef MPC5200_BUG_435_WORKAROUND
105 if (bus->number != hose->bus_offset) {
106 switch (len) {
107 case 1:
108 out_8(((u8 __iomem *)hose->cfg_data) +
109 (offset & 3), val);
110 break;
111 case 2:
112 out_le16(((u16 __iomem *)hose->cfg_data) +
113 ((offset>>1) & 1), val);
114 break;
115
116 default:
117 out_le16((u16 __iomem *)hose->cfg_data,
118 (u16)val);
119 out_le16(((u16 __iomem *)hose->cfg_data) + 1,
120 (u16)(val>>16));
121 break;
122 }
123 }
124 else
125#endif
126 {
127 if (len != 4) {
128 value = in_le32(hose->cfg_data);
74 129
75 if (len != 4) { 130 offset = (offset & 0x3) << 3;
76 value = in_le32(hose->cfg_data); 131 mask = (0xffffffff >> (32 - (len << 3)));
132 mask <<= offset;
77 133
78 offset = (offset & 0x3) << 3; 134 value &= ~mask;
79 mask = (0xffffffff >> (32 - (len << 3))); 135 val = value | ((val << offset) & mask);
80 mask <<= offset; 136 }
81 137
82 value &= ~mask; 138 out_le32(hose->cfg_data, val);
83 val = value | ((val << offset) & mask);
84 } 139 }
85 140 mb();
86 out_le32(hose->cfg_data, val);
87 141
88 out_be32(hose->cfg_addr, 0); 142 out_be32(hose->cfg_addr, 0);
143 mb();
89 144
90 return PCIBIOS_SUCCESSFUL; 145 return PCIBIOS_SUCCESSFUL;
91} 146}
@@ -99,9 +154,12 @@ static struct pci_ops mpc52xx_pci_ops = {
99static void __init 154static void __init
100mpc52xx_pci_setup(struct mpc52xx_pci __iomem *pci_regs) 155mpc52xx_pci_setup(struct mpc52xx_pci __iomem *pci_regs)
101{ 156{
157 u32 tmp;
102 158
103 /* Setup control regs */ 159 /* Setup control regs */
104 /* Nothing to do afaik */ 160 tmp = in_be32(&pci_regs->scr);
161 tmp |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
162 out_be32(&pci_regs->scr, tmp);
105 163
106 /* Setup windows */ 164 /* Setup windows */
107 out_be32(&pci_regs->iw0btar, MPC52xx_PCI_IWBTAR_TRANSLATION( 165 out_be32(&pci_regs->iw0btar, MPC52xx_PCI_IWBTAR_TRANSLATION(
@@ -142,16 +200,15 @@ mpc52xx_pci_setup(struct mpc52xx_pci __iomem *pci_regs)
142 /* Not necessary and can be a bad thing if for example the bootloader 200 /* Not necessary and can be a bad thing if for example the bootloader
143 is displaying a splash screen or ... Just left here for 201 is displaying a splash screen or ... Just left here for
144 documentation purpose if anyone need it */ 202 documentation purpose if anyone need it */
145#if 0
146 u32 tmp;
147 tmp = in_be32(&pci_regs->gscr); 203 tmp = in_be32(&pci_regs->gscr);
204#if 0
148 out_be32(&pci_regs->gscr, tmp | MPC52xx_PCI_GSCR_PR); 205 out_be32(&pci_regs->gscr, tmp | MPC52xx_PCI_GSCR_PR);
149 udelay(50); 206 udelay(50);
150 out_be32(&pci_regs->gscr, tmp);
151#endif 207#endif
208 out_be32(&pci_regs->gscr, tmp & ~MPC52xx_PCI_GSCR_PR);
152} 209}
153 210
154static void __init 211static void
155mpc52xx_pci_fixup_resources(struct pci_dev *dev) 212mpc52xx_pci_fixup_resources(struct pci_dev *dev)
156{ 213{
157 int i; 214 int i;