aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorKarl Bongers <kbongers@jged.com>2008-12-01 05:47:40 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2009-01-07 13:00:04 -0500
commit6013bbbab0dcbc43bcf9dd70beeab2a0b1ec5ea7 (patch)
tree79175da5e8fcf85a8650e825d0b7cc3f2d2a2d94 /drivers/usb
parent6c0735687d37e25a65866823881bcbf39a6a023f (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')
-rw-r--r--drivers/usb/host/isp1760-if.c97
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
132static u32 nxp_pci_io_base;
133static u32 iolength;
134static u32 pci_mem_phy0;
135static u32 length;
136static u8 __iomem *chip_addr;
137static u8 __iomem *iobase;
138
139static int __devinit isp1761_pci_probe(struct pci_dev *dev, 132static 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 }
239clean: 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
256cleanup3:
257 release_mem_region(pci_mem_phy0, memlength);
258cleanup2:
259 iounmap(iobase);
260cleanup1:
261 release_mem_region(nxp_pci_io_base, iolength);
262 return ret_status;
245} 263}
264
246static void isp1761_pci_remove(struct pci_dev *dev) 265static 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
266static void isp1761_pci_shutdown(struct pci_dev *dev) 279static void isp1761_pci_shutdown(struct pci_dev *dev)