diff options
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) |