diff options
Diffstat (limited to 'drivers/usb/host/isp1760-if.c')
-rw-r--r-- | drivers/usb/host/isp1760-if.c | 116 |
1 files changed, 65 insertions, 51 deletions
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index b87ca7cf4b37..4cf7ca428b33 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c | |||
@@ -60,9 +60,6 @@ static int of_isp1760_probe(struct of_device *dev, | |||
60 | if (of_device_is_compatible(dp, "nxp,usb-isp1761")) | 60 | if (of_device_is_compatible(dp, "nxp,usb-isp1761")) |
61 | devflags |= ISP1760_FLAG_ISP1761; | 61 | devflags |= ISP1760_FLAG_ISP1761; |
62 | 62 | ||
63 | if (of_get_property(dp, "port1-disable", NULL) != NULL) | ||
64 | devflags |= ISP1760_FLAG_PORT1_DIS; | ||
65 | |||
66 | /* Some systems wire up only 16 of the 32 data lines */ | 63 | /* Some systems wire up only 16 of the 32 data lines */ |
67 | prop = of_get_property(dp, "bus-width", NULL); | 64 | prop = of_get_property(dp, "bus-width", NULL); |
68 | if (prop && *prop == 16) | 65 | if (prop && *prop == 16) |
@@ -129,23 +126,23 @@ static struct of_platform_driver isp1760_of_driver = { | |||
129 | #endif | 126 | #endif |
130 | 127 | ||
131 | #ifdef CONFIG_PCI | 128 | #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, | 129 | static int __devinit isp1761_pci_probe(struct pci_dev *dev, |
140 | const struct pci_device_id *id) | 130 | const struct pci_device_id *id) |
141 | { | 131 | { |
142 | u8 latency, limit; | 132 | u8 latency, limit; |
143 | __u32 reg_data; | 133 | __u32 reg_data; |
144 | int retry_count; | 134 | int retry_count; |
145 | int length; | ||
146 | int status = 1; | ||
147 | struct usb_hcd *hcd; | 135 | struct usb_hcd *hcd; |
148 | unsigned int devflags = 0; | 136 | unsigned int devflags = 0; |
137 | int ret_status = 0; | ||
138 | |||
139 | resource_size_t pci_mem_phy0; | ||
140 | resource_size_t memlength; | ||
141 | |||
142 | u8 __iomem *chip_addr; | ||
143 | u8 __iomem *iobase; | ||
144 | resource_size_t nxp_pci_io_base; | ||
145 | resource_size_t iolength; | ||
149 | 146 | ||
150 | if (usb_disabled()) | 147 | if (usb_disabled()) |
151 | return -ENODEV; | 148 | return -ENODEV; |
@@ -168,26 +165,30 @@ static int __devinit isp1761_pci_probe(struct pci_dev *dev, | |||
168 | iobase = ioremap_nocache(nxp_pci_io_base, iolength); | 165 | iobase = ioremap_nocache(nxp_pci_io_base, iolength); |
169 | if (!iobase) { | 166 | if (!iobase) { |
170 | printk(KERN_ERR "ioremap #1\n"); | 167 | printk(KERN_ERR "ioremap #1\n"); |
171 | release_mem_region(nxp_pci_io_base, iolength); | 168 | ret_status = -ENOMEM; |
172 | return -ENOMEM; | 169 | goto cleanup1; |
173 | } | 170 | } |
174 | /* Grab the PLX PCI shared memory of the ISP 1761 we need */ | 171 | /* Grab the PLX PCI shared memory of the ISP 1761 we need */ |
175 | pci_mem_phy0 = pci_resource_start(dev, 3); | 172 | pci_mem_phy0 = pci_resource_start(dev, 3); |
176 | length = pci_resource_len(dev, 3); | 173 | memlength = pci_resource_len(dev, 3); |
177 | 174 | if (memlength < 0xffff) { | |
178 | if (length < 0xffff) { | 175 | printk(KERN_ERR "memory length for this resource is wrong\n"); |
179 | printk(KERN_ERR "memory length for this resource is less than " | 176 | ret_status = -ENOMEM; |
180 | "required\n"); | 177 | goto cleanup2; |
181 | release_mem_region(nxp_pci_io_base, iolength); | ||
182 | iounmap(iobase); | ||
183 | return -ENOMEM; | ||
184 | } | 178 | } |
185 | 179 | ||
186 | if (!request_mem_region(pci_mem_phy0, length, "ISP-PCI")) { | 180 | if (!request_mem_region(pci_mem_phy0, memlength, "ISP-PCI")) { |
187 | printk(KERN_ERR "host controller already in use\n"); | 181 | printk(KERN_ERR "host controller already in use\n"); |
188 | release_mem_region(nxp_pci_io_base, iolength); | 182 | ret_status = -EBUSY; |
189 | iounmap(iobase); | 183 | goto cleanup2; |
190 | return -EBUSY; | 184 | } |
185 | |||
186 | /* map available memory */ | ||
187 | chip_addr = ioremap_nocache(pci_mem_phy0,memlength); | ||
188 | if (!chip_addr) { | ||
189 | printk(KERN_ERR "Error ioremap failed\n"); | ||
190 | ret_status = -ENOMEM; | ||
191 | goto cleanup3; | ||
191 | } | 192 | } |
192 | 193 | ||
193 | /* bad pci latencies can contribute to overruns */ | 194 | /* bad pci latencies can contribute to overruns */ |
@@ -210,39 +211,54 @@ static int __devinit isp1761_pci_probe(struct pci_dev *dev, | |||
210 | * */ | 211 | * */ |
211 | writel(0xface, chip_addr + HC_SCRATCH_REG); | 212 | writel(0xface, chip_addr + HC_SCRATCH_REG); |
212 | udelay(100); | 213 | udelay(100); |
213 | reg_data = readl(chip_addr + HC_SCRATCH_REG); | 214 | reg_data = readl(chip_addr + HC_SCRATCH_REG) & 0x0000ffff; |
214 | retry_count--; | 215 | retry_count--; |
215 | } | 216 | } |
216 | 217 | ||
218 | iounmap(chip_addr); | ||
219 | |||
217 | /* Host Controller presence is detected by writing to scratch register | 220 | /* Host Controller presence is detected by writing to scratch register |
218 | * and reading back and checking the contents are same or not | 221 | * and reading back and checking the contents are same or not |
219 | */ | 222 | */ |
220 | if (reg_data != 0xFACE) { | 223 | if (reg_data != 0xFACE) { |
221 | dev_err(&dev->dev, "scratch register mismatch %x\n", reg_data); | 224 | dev_err(&dev->dev, "scratch register mismatch %x\n", reg_data); |
222 | goto clean; | 225 | ret_status = -ENOMEM; |
226 | goto cleanup3; | ||
223 | } | 227 | } |
224 | 228 | ||
225 | pci_set_master(dev); | 229 | pci_set_master(dev); |
226 | 230 | ||
227 | status = readl(iobase + 0x68); | 231 | /* configure PLX PCI chip to pass interrupts */ |
228 | status |= 0x900; | 232 | #define PLX_INT_CSR_REG 0x68 |
229 | writel(status, iobase + 0x68); | 233 | reg_data = readl(iobase + PLX_INT_CSR_REG); |
234 | reg_data |= 0x900; | ||
235 | writel(reg_data, iobase + PLX_INT_CSR_REG); | ||
230 | 236 | ||
231 | dev->dev.dma_mask = NULL; | 237 | dev->dev.dma_mask = NULL; |
232 | hcd = isp1760_register(pci_mem_phy0, length, dev->irq, | 238 | hcd = isp1760_register(pci_mem_phy0, memlength, dev->irq, |
233 | IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev), | 239 | IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev), |
234 | devflags); | 240 | devflags); |
235 | if (!IS_ERR(hcd)) { | 241 | if (IS_ERR(hcd)) { |
236 | pci_set_drvdata(dev, hcd); | 242 | ret_status = -ENODEV; |
237 | return 0; | 243 | goto cleanup3; |
238 | } | 244 | } |
239 | clean: | 245 | |
240 | status = -ENODEV; | 246 | /* done with PLX IO access */ |
247 | iounmap(iobase); | ||
248 | release_mem_region(nxp_pci_io_base, iolength); | ||
249 | |||
250 | pci_set_drvdata(dev, hcd); | ||
251 | return 0; | ||
252 | |||
253 | cleanup3: | ||
254 | release_mem_region(pci_mem_phy0, memlength); | ||
255 | cleanup2: | ||
241 | iounmap(iobase); | 256 | iounmap(iobase); |
242 | release_mem_region(pci_mem_phy0, length); | 257 | cleanup1: |
243 | release_mem_region(nxp_pci_io_base, iolength); | 258 | release_mem_region(nxp_pci_io_base, iolength); |
244 | return status; | 259 | return ret_status; |
245 | } | 260 | } |
261 | |||
246 | static void isp1761_pci_remove(struct pci_dev *dev) | 262 | static void isp1761_pci_remove(struct pci_dev *dev) |
247 | { | 263 | { |
248 | struct usb_hcd *hcd; | 264 | struct usb_hcd *hcd; |
@@ -255,12 +271,6 @@ static void isp1761_pci_remove(struct pci_dev *dev) | |||
255 | usb_put_hcd(hcd); | 271 | usb_put_hcd(hcd); |
256 | 272 | ||
257 | pci_disable_device(dev); | 273 | 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 | } | 274 | } |
265 | 275 | ||
266 | static void isp1761_pci_shutdown(struct pci_dev *dev) | 276 | static void isp1761_pci_shutdown(struct pci_dev *dev) |
@@ -268,12 +278,16 @@ static void isp1761_pci_shutdown(struct pci_dev *dev) | |||
268 | printk(KERN_ERR "ips1761_pci_shutdown\n"); | 278 | printk(KERN_ERR "ips1761_pci_shutdown\n"); |
269 | } | 279 | } |
270 | 280 | ||
271 | static const struct pci_device_id isp1760_plx [] = { { | 281 | static const struct pci_device_id isp1760_plx [] = { |
272 | /* handle any USB 2.0 EHCI controller */ | 282 | { |
273 | PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_OTHER << 8) | (0x06 << 16)), ~0), | 283 | .class = PCI_CLASS_BRIDGE_OTHER << 8, |
274 | .driver_data = 0, | 284 | .class_mask = ~0, |
275 | }, | 285 | .vendor = PCI_VENDOR_ID_PLX, |
276 | { /* end: all zeroes */ } | 286 | .device = 0x5406, |
287 | .subvendor = PCI_VENDOR_ID_PLX, | ||
288 | .subdevice = 0x9054, | ||
289 | }, | ||
290 | { } | ||
277 | }; | 291 | }; |
278 | MODULE_DEVICE_TABLE(pci, isp1760_plx); | 292 | MODULE_DEVICE_TABLE(pci, isp1760_plx); |
279 | 293 | ||