diff options
Diffstat (limited to 'drivers/bcma/driver_pci_host.c')
-rw-r--r-- | drivers/bcma/driver_pci_host.c | 62 |
1 files changed, 38 insertions, 24 deletions
diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c index af0c9fabee54..d3bde6cec927 100644 --- a/drivers/bcma/driver_pci_host.c +++ b/drivers/bcma/driver_pci_host.c | |||
@@ -94,19 +94,19 @@ static int bcma_extpci_read_config(struct bcma_drv_pci *pc, unsigned int dev, | |||
94 | if (dev == 0) { | 94 | if (dev == 0) { |
95 | /* we support only two functions on device 0 */ | 95 | /* we support only two functions on device 0 */ |
96 | if (func > 1) | 96 | if (func > 1) |
97 | return -EINVAL; | 97 | goto out; |
98 | 98 | ||
99 | /* accesses to config registers with offsets >= 256 | 99 | /* accesses to config registers with offsets >= 256 |
100 | * requires indirect access. | 100 | * requires indirect access. |
101 | */ | 101 | */ |
102 | if (off >= PCI_CONFIG_SPACE_SIZE) { | 102 | if (off >= PCI_CONFIG_SPACE_SIZE) { |
103 | addr = (func << 12); | 103 | addr = (func << 12); |
104 | addr |= (off & 0x0FFF); | 104 | addr |= (off & 0x0FFC); |
105 | val = bcma_pcie_read_config(pc, addr); | 105 | val = bcma_pcie_read_config(pc, addr); |
106 | } else { | 106 | } else { |
107 | addr = BCMA_CORE_PCI_PCICFG0; | 107 | addr = BCMA_CORE_PCI_PCICFG0; |
108 | addr |= (func << 8); | 108 | addr |= (func << 8); |
109 | addr |= (off & 0xfc); | 109 | addr |= (off & 0xFC); |
110 | val = pcicore_read32(pc, addr); | 110 | val = pcicore_read32(pc, addr); |
111 | } | 111 | } |
112 | } else { | 112 | } else { |
@@ -119,11 +119,9 @@ static int bcma_extpci_read_config(struct bcma_drv_pci *pc, unsigned int dev, | |||
119 | goto out; | 119 | goto out; |
120 | 120 | ||
121 | if (mips_busprobe32(val, mmio)) { | 121 | if (mips_busprobe32(val, mmio)) { |
122 | val = 0xffffffff; | 122 | val = 0xFFFFFFFF; |
123 | goto unmap; | 123 | goto unmap; |
124 | } | 124 | } |
125 | |||
126 | val = readl(mmio); | ||
127 | } | 125 | } |
128 | val >>= (8 * (off & 3)); | 126 | val >>= (8 * (off & 3)); |
129 | 127 | ||
@@ -151,7 +149,7 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev, | |||
151 | const void *buf, int len) | 149 | const void *buf, int len) |
152 | { | 150 | { |
153 | int err = -EINVAL; | 151 | int err = -EINVAL; |
154 | u32 addr = 0, val = 0; | 152 | u32 addr, val; |
155 | void __iomem *mmio = 0; | 153 | void __iomem *mmio = 0; |
156 | u16 chipid = pc->core->bus->chipinfo.id; | 154 | u16 chipid = pc->core->bus->chipinfo.id; |
157 | 155 | ||
@@ -159,16 +157,22 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev, | |||
159 | if (unlikely(len != 1 && len != 2 && len != 4)) | 157 | if (unlikely(len != 1 && len != 2 && len != 4)) |
160 | goto out; | 158 | goto out; |
161 | if (dev == 0) { | 159 | if (dev == 0) { |
160 | /* we support only two functions on device 0 */ | ||
161 | if (func > 1) | ||
162 | goto out; | ||
163 | |||
162 | /* accesses to config registers with offsets >= 256 | 164 | /* accesses to config registers with offsets >= 256 |
163 | * requires indirect access. | 165 | * requires indirect access. |
164 | */ | 166 | */ |
165 | if (off < PCI_CONFIG_SPACE_SIZE) { | 167 | if (off >= PCI_CONFIG_SPACE_SIZE) { |
166 | addr = pc->core->addr + BCMA_CORE_PCI_PCICFG0; | 168 | addr = (func << 12); |
169 | addr |= (off & 0x0FFC); | ||
170 | val = bcma_pcie_read_config(pc, addr); | ||
171 | } else { | ||
172 | addr = BCMA_CORE_PCI_PCICFG0; | ||
167 | addr |= (func << 8); | 173 | addr |= (func << 8); |
168 | addr |= (off & 0xfc); | 174 | addr |= (off & 0xFC); |
169 | mmio = ioremap_nocache(addr, sizeof(val)); | 175 | val = pcicore_read32(pc, addr); |
170 | if (!mmio) | ||
171 | goto out; | ||
172 | } | 176 | } |
173 | } else { | 177 | } else { |
174 | addr = bcma_get_cfgspace_addr(pc, dev, func, off); | 178 | addr = bcma_get_cfgspace_addr(pc, dev, func, off); |
@@ -180,19 +184,17 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev, | |||
180 | goto out; | 184 | goto out; |
181 | 185 | ||
182 | if (mips_busprobe32(val, mmio)) { | 186 | if (mips_busprobe32(val, mmio)) { |
183 | val = 0xffffffff; | 187 | val = 0xFFFFFFFF; |
184 | goto unmap; | 188 | goto unmap; |
185 | } | 189 | } |
186 | } | 190 | } |
187 | 191 | ||
188 | switch (len) { | 192 | switch (len) { |
189 | case 1: | 193 | case 1: |
190 | val = readl(mmio); | ||
191 | val &= ~(0xFF << (8 * (off & 3))); | 194 | val &= ~(0xFF << (8 * (off & 3))); |
192 | val |= *((const u8 *)buf) << (8 * (off & 3)); | 195 | val |= *((const u8 *)buf) << (8 * (off & 3)); |
193 | break; | 196 | break; |
194 | case 2: | 197 | case 2: |
195 | val = readl(mmio); | ||
196 | val &= ~(0xFFFF << (8 * (off & 3))); | 198 | val &= ~(0xFFFF << (8 * (off & 3))); |
197 | val |= *((const u16 *)buf) << (8 * (off & 3)); | 199 | val |= *((const u16 *)buf) << (8 * (off & 3)); |
198 | break; | 200 | break; |
@@ -200,13 +202,14 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev, | |||
200 | val = *((const u32 *)buf); | 202 | val = *((const u32 *)buf); |
201 | break; | 203 | break; |
202 | } | 204 | } |
203 | if (dev == 0 && !addr) { | 205 | if (dev == 0) { |
204 | /* accesses to config registers with offsets >= 256 | 206 | /* accesses to config registers with offsets >= 256 |
205 | * requires indirect access. | 207 | * requires indirect access. |
206 | */ | 208 | */ |
207 | addr = (func << 12); | 209 | if (off >= PCI_CONFIG_SPACE_SIZE) |
208 | addr |= (off & 0x0FFF); | 210 | bcma_pcie_write_config(pc, addr, val); |
209 | bcma_pcie_write_config(pc, addr, val); | 211 | else |
212 | pcicore_write32(pc, addr, val); | ||
210 | } else { | 213 | } else { |
211 | writel(val, mmio); | 214 | writel(val, mmio); |
212 | 215 | ||
@@ -276,7 +279,7 @@ static u8 bcma_find_pci_capability(struct bcma_drv_pci *pc, unsigned int dev, | |||
276 | /* check for Header type 0 */ | 279 | /* check for Header type 0 */ |
277 | bcma_extpci_read_config(pc, dev, func, PCI_HEADER_TYPE, &byte_val, | 280 | bcma_extpci_read_config(pc, dev, func, PCI_HEADER_TYPE, &byte_val, |
278 | sizeof(u8)); | 281 | sizeof(u8)); |
279 | if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL) | 282 | if ((byte_val & 0x7F) != PCI_HEADER_TYPE_NORMAL) |
280 | return cap_ptr; | 283 | return cap_ptr; |
281 | 284 | ||
282 | /* check if the capability pointer field exists */ | 285 | /* check if the capability pointer field exists */ |
@@ -426,7 +429,7 @@ void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) | |||
426 | /* Reset RC */ | 429 | /* Reset RC */ |
427 | usleep_range(3000, 5000); | 430 | usleep_range(3000, 5000); |
428 | pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE); | 431 | pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE); |
429 | usleep_range(1000, 2000); | 432 | msleep(50); |
430 | pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST | | 433 | pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST | |
431 | BCMA_CORE_PCI_CTL_RST_OE); | 434 | BCMA_CORE_PCI_CTL_RST_OE); |
432 | 435 | ||
@@ -488,6 +491,17 @@ void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) | |||
488 | 491 | ||
489 | bcma_core_pci_enable_crs(pc); | 492 | bcma_core_pci_enable_crs(pc); |
490 | 493 | ||
494 | if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706 || | ||
495 | bus->chipinfo.id == BCMA_CHIP_ID_BCM4716) { | ||
496 | u16 val16; | ||
497 | bcma_extpci_read_config(pc, 0, 0, BCMA_CORE_PCI_CFG_DEVCTRL, | ||
498 | &val16, sizeof(val16)); | ||
499 | val16 |= (2 << 5); /* Max payload size of 512 */ | ||
500 | val16 |= (2 << 12); /* MRRS 512 */ | ||
501 | bcma_extpci_write_config(pc, 0, 0, BCMA_CORE_PCI_CFG_DEVCTRL, | ||
502 | &val16, sizeof(val16)); | ||
503 | } | ||
504 | |||
491 | /* Enable PCI bridge BAR0 memory & master access */ | 505 | /* Enable PCI bridge BAR0 memory & master access */ |
492 | tmp = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; | 506 | tmp = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; |
493 | bcma_extpci_write_config(pc, 0, 0, PCI_COMMAND, &tmp, sizeof(tmp)); | 507 | bcma_extpci_write_config(pc, 0, 0, PCI_COMMAND, &tmp, sizeof(tmp)); |
@@ -576,7 +590,7 @@ int bcma_core_pci_plat_dev_init(struct pci_dev *dev) | |||
576 | pr_info("PCI: Fixing up device %s\n", pci_name(dev)); | 590 | pr_info("PCI: Fixing up device %s\n", pci_name(dev)); |
577 | 591 | ||
578 | /* Fix up interrupt lines */ | 592 | /* Fix up interrupt lines */ |
579 | dev->irq = bcma_core_mips_irq(pc_host->pdev->core) + 2; | 593 | dev->irq = bcma_core_irq(pc_host->pdev->core); |
580 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); | 594 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); |
581 | 595 | ||
582 | return 0; | 596 | return 0; |
@@ -595,6 +609,6 @@ int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev) | |||
595 | 609 | ||
596 | pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host, | 610 | pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host, |
597 | pci_ops); | 611 | pci_ops); |
598 | return bcma_core_mips_irq(pc_host->pdev->core) + 2; | 612 | return bcma_core_irq(pc_host->pdev->core); |
599 | } | 613 | } |
600 | EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq); | 614 | EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq); |