diff options
author | Gabor Juhos <juhosg@openwrt.org> | 2012-03-14 05:36:04 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2012-05-15 11:49:03 -0400 |
commit | 64adb6bb62bee11ad04c2f9c3c797799e329c351 (patch) | |
tree | bc366ea60a40310184cbdb1bfb20e648ee639abe /arch/mips/pci/pci-ar724x.c | |
parent | ffdce4668234a113e767edd27aa1331903959106 (diff) |
MIPS: ath79: fix broken ar724x_pci_{read,write} functions
The current ar724x_pci_{read,write} functions are
broken. Due to that, pci_read_config_byte returns
with bogus values, and pci_write_config_{byte,word}
unconditionally clears the accessed PCI configuration
registers instead of changing the value of them.
The patch fixes the broken functions, thus the PCI
configuration space can be accessed correctly.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/3493/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/pci/pci-ar724x.c')
-rw-r--r-- | arch/mips/pci/pci-ar724x.c | 52 |
1 files changed, 26 insertions, 26 deletions
diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c index 342bf4ab8960..bb4f2162d4e4 100644 --- a/arch/mips/pci/pci-ar724x.c +++ b/arch/mips/pci/pci-ar724x.c | |||
@@ -22,8 +22,9 @@ static void __iomem *ar724x_pci_devcfg_base; | |||
22 | static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, | 22 | static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, |
23 | int size, uint32_t *value) | 23 | int size, uint32_t *value) |
24 | { | 24 | { |
25 | unsigned long flags, addr, tval, mask; | 25 | unsigned long flags; |
26 | void __iomem *base; | 26 | void __iomem *base; |
27 | u32 data; | ||
27 | 28 | ||
28 | if (devfn) | 29 | if (devfn) |
29 | return PCIBIOS_DEVICE_NOT_FOUND; | 30 | return PCIBIOS_DEVICE_NOT_FOUND; |
@@ -31,24 +32,22 @@ static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, | |||
31 | base = ar724x_pci_devcfg_base; | 32 | base = ar724x_pci_devcfg_base; |
32 | 33 | ||
33 | spin_lock_irqsave(&ar724x_pci_lock, flags); | 34 | spin_lock_irqsave(&ar724x_pci_lock, flags); |
35 | data = __raw_readl(base + (where & ~3)); | ||
34 | 36 | ||
35 | switch (size) { | 37 | switch (size) { |
36 | case 1: | 38 | case 1: |
37 | addr = where & ~3; | 39 | if (where & 1) |
38 | mask = 0xff000000 >> ((where % 4) * 8); | 40 | data >>= 8; |
39 | tval = __raw_readl(base + addr); | 41 | if (where & 2) |
40 | tval = tval & ~mask; | 42 | data >>= 16; |
41 | *value = (tval >> ((4 - (where % 4))*8)); | 43 | data &= 0xff; |
42 | break; | 44 | break; |
43 | case 2: | 45 | case 2: |
44 | addr = where & ~3; | 46 | if (where & 2) |
45 | mask = 0xffff0000 >> ((where % 4)*8); | 47 | data >>= 16; |
46 | tval = __raw_readl(base + addr); | 48 | data &= 0xffff; |
47 | tval = tval & ~mask; | ||
48 | *value = (tval >> ((4 - (where % 4))*8)); | ||
49 | break; | 49 | break; |
50 | case 4: | 50 | case 4: |
51 | *value = __raw_readl(base + where); | ||
52 | break; | 51 | break; |
53 | default: | 52 | default: |
54 | spin_unlock_irqrestore(&ar724x_pci_lock, flags); | 53 | spin_unlock_irqrestore(&ar724x_pci_lock, flags); |
@@ -57,6 +56,7 @@ static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, | |||
57 | } | 56 | } |
58 | 57 | ||
59 | spin_unlock_irqrestore(&ar724x_pci_lock, flags); | 58 | spin_unlock_irqrestore(&ar724x_pci_lock, flags); |
59 | *value = data; | ||
60 | 60 | ||
61 | return PCIBIOS_SUCCESSFUL; | 61 | return PCIBIOS_SUCCESSFUL; |
62 | } | 62 | } |
@@ -64,8 +64,10 @@ static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, | |||
64 | static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, | 64 | static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, |
65 | int size, uint32_t value) | 65 | int size, uint32_t value) |
66 | { | 66 | { |
67 | unsigned long flags, tval, addr, mask; | 67 | unsigned long flags; |
68 | void __iomem *base; | 68 | void __iomem *base; |
69 | u32 data; | ||
70 | int s; | ||
69 | 71 | ||
70 | if (devfn) | 72 | if (devfn) |
71 | return PCIBIOS_DEVICE_NOT_FOUND; | 73 | return PCIBIOS_DEVICE_NOT_FOUND; |
@@ -73,26 +75,21 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, | |||
73 | base = ar724x_pci_devcfg_base; | 75 | base = ar724x_pci_devcfg_base; |
74 | 76 | ||
75 | spin_lock_irqsave(&ar724x_pci_lock, flags); | 77 | spin_lock_irqsave(&ar724x_pci_lock, flags); |
78 | data = __raw_readl(base + (where & ~3)); | ||
76 | 79 | ||
77 | switch (size) { | 80 | switch (size) { |
78 | case 1: | 81 | case 1: |
79 | addr = where & ~3; | 82 | s = ((where & 3) * 8); |
80 | mask = 0xff000000 >> ((where % 4)*8); | 83 | data &= ~(0xff << s); |
81 | tval = __raw_readl(base + addr); | 84 | data |= ((value & 0xff) << s); |
82 | tval = tval & ~mask; | ||
83 | tval |= (value << ((4 - (where % 4))*8)) & mask; | ||
84 | __raw_writel(tval, base + addr); | ||
85 | break; | 85 | break; |
86 | case 2: | 86 | case 2: |
87 | addr = where & ~3; | 87 | s = ((where & 2) * 8); |
88 | mask = 0xffff0000 >> ((where % 4)*8); | 88 | data &= ~(0xffff << s); |
89 | tval = __raw_readl(base + addr); | 89 | data |= ((value & 0xffff) << s); |
90 | tval = tval & ~mask; | ||
91 | tval |= (value << ((4 - (where % 4))*8)) & mask; | ||
92 | __raw_writel(tval, base + addr); | ||
93 | break; | 90 | break; |
94 | case 4: | 91 | case 4: |
95 | __raw_writel(value, (base + where)); | 92 | data = value; |
96 | break; | 93 | break; |
97 | default: | 94 | default: |
98 | spin_unlock_irqrestore(&ar724x_pci_lock, flags); | 95 | spin_unlock_irqrestore(&ar724x_pci_lock, flags); |
@@ -100,6 +97,9 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, | |||
100 | return PCIBIOS_BAD_REGISTER_NUMBER; | 97 | return PCIBIOS_BAD_REGISTER_NUMBER; |
101 | } | 98 | } |
102 | 99 | ||
100 | __raw_writel(data, base + (where & ~3)); | ||
101 | /* flush write */ | ||
102 | __raw_readl(base + (where & ~3)); | ||
103 | spin_unlock_irqrestore(&ar724x_pci_lock, flags); | 103 | spin_unlock_irqrestore(&ar724x_pci_lock, flags); |
104 | 104 | ||
105 | return PCIBIOS_SUCCESSFUL; | 105 | return PCIBIOS_SUCCESSFUL; |