diff options
author | Karl Bongers <kbongers@jged.com> | 2008-12-01 05:47:40 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-01-07 13:00:04 -0500 |
commit | 6013bbbab0dcbc43bcf9dd70beeab2a0b1ec5ea7 (patch) | |
tree | 79175da5e8fcf85a8650e825d0b7cc3f2d2a2d94 /drivers/usb/host/isp1760-if.c | |
parent | 6c0735687d37e25a65866823881bcbf39a6a023f (diff) |
USB: isp1760: Fix probe in PCI glue code
Contains fixes so probe on x86 PCI runs, apparently I'm first to try
this. Several fixes to memory access to probe host scratch register.
Previously would bug check on chip_addr var used uninitialized.
Scratch reg write failed in one instance due to 16-bit initial access
mode, so added "& 0x0000ffff" to the readl as fix.
Includes some general cleanup - remove global vars, organize memory map
resource use.
Signed-off-by: Karl Bongers <kbongers@jged.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/isp1760-if.c')
-rw-r--r-- | drivers/usb/host/isp1760-if.c | 97 |
1 files changed, 55 insertions, 42 deletions
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index a53114c367cd..25453066fda5 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c | |||
@@ -129,23 +129,23 @@ static struct of_platform_driver isp1760_of_driver = { | |||
129 | #endif | 129 | #endif |
130 | 130 | ||
131 | #ifdef CONFIG_PCI | 131 | #ifdef CONFIG_PCI |
132 | static u32 nxp_pci_io_base; | ||
133 | static u32 iolength; | ||
134 | static u32 pci_mem_phy0; | ||
135 | static u32 length; | ||
136 | static u8 __iomem *chip_addr; | ||
137 | static u8 __iomem *iobase; | ||
138 | |||
139 | static int __devinit isp1761_pci_probe(struct pci_dev *dev, | 132 | static int __devinit isp1761_pci_probe(struct pci_dev *dev, |
140 | const struct pci_device_id *id) | 133 | const struct pci_device_id *id) |
141 | { | 134 | { |
142 | u8 latency, limit; | 135 | u8 latency, limit; |
143 | __u32 reg_data; | 136 | __u32 reg_data; |
144 | int retry_count; | 137 | int retry_count; |
145 | int length; | ||
146 | int status = 1; | ||
147 | struct usb_hcd *hcd; | 138 | struct usb_hcd *hcd; |
148 | unsigned int devflags = 0; | 139 | unsigned int devflags = 0; |
140 | int ret_status = 0; | ||
141 | |||
142 | resource_size_t pci_mem_phy0; | ||
143 | resource_size_t memlength; | ||
144 | |||
145 | u8 __iomem *chip_addr; | ||
146 | u8 __iomem *iobase; | ||
147 | resource_size_t nxp_pci_io_base; | ||
148 | resource_size_t iolength; | ||
149 | 149 | ||
150 | if (usb_disabled()) | 150 | if (usb_disabled()) |
151 | return -ENODEV; | 151 | return -ENODEV; |
@@ -168,26 +168,30 @@ static int __devinit isp1761_pci_probe(struct pci_dev *dev, | |||
168 | iobase = ioremap_nocache(nxp_pci_io_base, iolength); | 168 | iobase = ioremap_nocache(nxp_pci_io_base, iolength); |
169 | if (!iobase) { | 169 | if (!iobase) { |
170 | printk(KERN_ERR "ioremap #1\n"); | 170 | printk(KERN_ERR "ioremap #1\n"); |
171 | release_mem_region(nxp_pci_io_base, iolength); | 171 | ret_status = -ENOMEM; |
172 | return -ENOMEM; | 172 | goto cleanup1; |
173 | } | 173 | } |
174 | /* Grab the PLX PCI shared memory of the ISP 1761 we need */ | 174 | /* Grab the PLX PCI shared memory of the ISP 1761 we need */ |
175 | pci_mem_phy0 = pci_resource_start(dev, 3); | 175 | pci_mem_phy0 = pci_resource_start(dev, 3); |
176 | length = pci_resource_len(dev, 3); | 176 | memlength = pci_resource_len(dev, 3); |
177 | 177 | if (memlength < 0xffff) { | |
178 | if (length < 0xffff) { | 178 | printk(KERN_ERR "memory length for this resource is wrong\n"); |
179 | printk(KERN_ERR "memory length for this resource is less than " | 179 | ret_status = -ENOMEM; |
180 | "required\n"); | 180 | goto cleanup2; |
181 | release_mem_region(nxp_pci_io_base, iolength); | ||
182 | iounmap(iobase); | ||
183 | return -ENOMEM; | ||
184 | } | 181 | } |
185 | 182 | ||
186 | if (!request_mem_region(pci_mem_phy0, length, "ISP-PCI")) { | 183 | if (!request_mem_region(pci_mem_phy0, memlength, "ISP-PCI")) { |
187 | printk(KERN_ERR "host controller already in use\n"); | 184 | printk(KERN_ERR "host controller already in use\n"); |
188 | release_mem_region(nxp_pci_io_base, iolength); | 185 | ret_status = -EBUSY; |
189 | iounmap(iobase); | 186 | goto cleanup2; |
190 | return -EBUSY; | 187 | } |
188 | |||
189 | /* map available memory */ | ||
190 | chip_addr = ioremap_nocache(pci_mem_phy0,memlength); | ||
191 | if (!chip_addr) { | ||
192 | printk(KERN_ERR "Error ioremap failed\n"); | ||
193 | ret_status = -ENOMEM; | ||
194 | goto cleanup3; | ||
191 | } | 195 | } |
192 | 196 | ||
193 | /* bad pci latencies can contribute to overruns */ | 197 | /* bad pci latencies can contribute to overruns */ |
@@ -210,39 +214,54 @@ static int __devinit isp1761_pci_probe(struct pci_dev *dev, | |||
210 | * */ | 214 | * */ |
211 | writel(0xface, chip_addr + HC_SCRATCH_REG); | 215 | writel(0xface, chip_addr + HC_SCRATCH_REG); |
212 | udelay(100); | 216 | udelay(100); |
213 | reg_data = readl(chip_addr + HC_SCRATCH_REG); | 217 | reg_data = readl(chip_addr + HC_SCRATCH_REG) & 0x0000ffff; |
214 | retry_count--; | 218 | retry_count--; |
215 | } | 219 | } |
216 | 220 | ||
221 | iounmap(chip_addr); | ||
222 | |||
217 | /* Host Controller presence is detected by writing to scratch register | 223 | /* Host Controller presence is detected by writing to scratch register |
218 | * and reading back and checking the contents are same or not | 224 | * and reading back and checking the contents are same or not |
219 | */ | 225 | */ |
220 | if (reg_data != 0xFACE) { | 226 | if (reg_data != 0xFACE) { |
221 | dev_err(&dev->dev, "scratch register mismatch %x\n", reg_data); | 227 | dev_err(&dev->dev, "scratch register mismatch %x\n", reg_data); |
222 | goto clean; | 228 | ret_status = -ENOMEM; |
229 | goto cleanup3; | ||
223 | } | 230 | } |
224 | 231 | ||
225 | pci_set_master(dev); | 232 | pci_set_master(dev); |
226 | 233 | ||
227 | status = readl(iobase + 0x68); | 234 | /* configure PLX PCI chip to pass interrupts */ |
228 | status |= 0x900; | 235 | #define PLX_INT_CSR_REG 0x68 |
229 | writel(status, iobase + 0x68); | 236 | reg_data = readl(iobase + PLX_INT_CSR_REG); |
237 | reg_data |= 0x900; | ||
238 | writel(reg_data, iobase + PLX_INT_CSR_REG); | ||
230 | 239 | ||
231 | dev->dev.dma_mask = NULL; | 240 | dev->dev.dma_mask = NULL; |
232 | hcd = isp1760_register(pci_mem_phy0, length, dev->irq, | 241 | hcd = isp1760_register(pci_mem_phy0, memlength, dev->irq, |
233 | IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev), | 242 | IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev), |
234 | devflags); | 243 | devflags); |
235 | if (!IS_ERR(hcd)) { | 244 | if (IS_ERR(hcd)) { |
236 | pci_set_drvdata(dev, hcd); | 245 | ret_status = -ENODEV; |
237 | return 0; | 246 | goto cleanup3; |
238 | } | 247 | } |
239 | clean: | 248 | |
240 | status = -ENODEV; | 249 | /* done with PLX IO access */ |
241 | iounmap(iobase); | 250 | iounmap(iobase); |
242 | release_mem_region(pci_mem_phy0, length); | ||
243 | release_mem_region(nxp_pci_io_base, iolength); | 251 | release_mem_region(nxp_pci_io_base, iolength); |
244 | return status; | 252 | |
253 | pci_set_drvdata(dev, hcd); | ||
254 | return 0; | ||
255 | |||
256 | cleanup3: | ||
257 | release_mem_region(pci_mem_phy0, memlength); | ||
258 | cleanup2: | ||
259 | iounmap(iobase); | ||
260 | cleanup1: | ||
261 | release_mem_region(nxp_pci_io_base, iolength); | ||
262 | return ret_status; | ||
245 | } | 263 | } |
264 | |||
246 | static void isp1761_pci_remove(struct pci_dev *dev) | 265 | static void isp1761_pci_remove(struct pci_dev *dev) |
247 | { | 266 | { |
248 | struct usb_hcd *hcd; | 267 | struct usb_hcd *hcd; |
@@ -255,12 +274,6 @@ static void isp1761_pci_remove(struct pci_dev *dev) | |||
255 | usb_put_hcd(hcd); | 274 | usb_put_hcd(hcd); |
256 | 275 | ||
257 | pci_disable_device(dev); | 276 | pci_disable_device(dev); |
258 | |||
259 | iounmap(iobase); | ||
260 | iounmap(chip_addr); | ||
261 | |||
262 | release_mem_region(nxp_pci_io_base, iolength); | ||
263 | release_mem_region(pci_mem_phy0, length); | ||
264 | } | 277 | } |
265 | 278 | ||
266 | static void isp1761_pci_shutdown(struct pci_dev *dev) | 279 | static void isp1761_pci_shutdown(struct pci_dev *dev) |