Commit 6013bbba authored by Karl Bongers's avatar Karl Bongers Committed by Greg Kroah-Hartman

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: default avatarKarl Bongers <kbongers@jged.com>
Signed-off-by: default avatarSebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: stable <stable@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 6c073568
......@@ -129,23 +129,23 @@ static struct of_platform_driver isp1760_of_driver = {
#endif
#ifdef CONFIG_PCI
static u32 nxp_pci_io_base;
static u32 iolength;
static u32 pci_mem_phy0;
static u32 length;
static u8 __iomem *chip_addr;
static u8 __iomem *iobase;
static int __devinit isp1761_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
u8 latency, limit;
__u32 reg_data;
int retry_count;
int length;
int status = 1;
struct usb_hcd *hcd;
unsigned int devflags = 0;
int ret_status = 0;
resource_size_t pci_mem_phy0;
resource_size_t memlength;
u8 __iomem *chip_addr;
u8 __iomem *iobase;
resource_size_t nxp_pci_io_base;
resource_size_t iolength;
if (usb_disabled())
return -ENODEV;
......@@ -168,26 +168,30 @@ static int __devinit isp1761_pci_probe(struct pci_dev *dev,
iobase = ioremap_nocache(nxp_pci_io_base, iolength);
if (!iobase) {
printk(KERN_ERR "ioremap #1\n");
release_mem_region(nxp_pci_io_base, iolength);
return -ENOMEM;
ret_status = -ENOMEM;
goto cleanup1;
}
/* Grab the PLX PCI shared memory of the ISP 1761 we need */
pci_mem_phy0 = pci_resource_start(dev, 3);
length = pci_resource_len(dev, 3);
if (length < 0xffff) {
printk(KERN_ERR "memory length for this resource is less than "
"required\n");
release_mem_region(nxp_pci_io_base, iolength);
iounmap(iobase);
return -ENOMEM;
memlength = pci_resource_len(dev, 3);
if (memlength < 0xffff) {
printk(KERN_ERR "memory length for this resource is wrong\n");
ret_status = -ENOMEM;
goto cleanup2;
}
if (!request_mem_region(pci_mem_phy0, length, "ISP-PCI")) {
if (!request_mem_region(pci_mem_phy0, memlength, "ISP-PCI")) {
printk(KERN_ERR "host controller already in use\n");
release_mem_region(nxp_pci_io_base, iolength);
iounmap(iobase);
return -EBUSY;
ret_status = -EBUSY;
goto cleanup2;
}
/* map available memory */
chip_addr = ioremap_nocache(pci_mem_phy0,memlength);
if (!chip_addr) {
printk(KERN_ERR "Error ioremap failed\n");
ret_status = -ENOMEM;
goto cleanup3;
}
/* bad pci latencies can contribute to overruns */
......@@ -210,39 +214,54 @@ static int __devinit isp1761_pci_probe(struct pci_dev *dev,
* */
writel(0xface, chip_addr + HC_SCRATCH_REG);
udelay(100);
reg_data = readl(chip_addr + HC_SCRATCH_REG);
reg_data = readl(chip_addr + HC_SCRATCH_REG) & 0x0000ffff;
retry_count--;
}
iounmap(chip_addr);
/* Host Controller presence is detected by writing to scratch register
* and reading back and checking the contents are same or not
*/
if (reg_data != 0xFACE) {
dev_err(&dev->dev, "scratch register mismatch %x\n", reg_data);
goto clean;
ret_status = -ENOMEM;
goto cleanup3;
}
pci_set_master(dev);
status = readl(iobase + 0x68);
status |= 0x900;
writel(status, iobase + 0x68);
/* configure PLX PCI chip to pass interrupts */
#define PLX_INT_CSR_REG 0x68
reg_data = readl(iobase + PLX_INT_CSR_REG);
reg_data |= 0x900;
writel(reg_data, iobase + PLX_INT_CSR_REG);
dev->dev.dma_mask = NULL;
hcd = isp1760_register(pci_mem_phy0, length, dev->irq,
hcd = isp1760_register(pci_mem_phy0, memlength, dev->irq,
IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev),
devflags);
if (!IS_ERR(hcd)) {
pci_set_drvdata(dev, hcd);
return 0;
if (IS_ERR(hcd)) {
ret_status = -ENODEV;
goto cleanup3;
}
clean:
status = -ENODEV;
/* done with PLX IO access */
iounmap(iobase);
release_mem_region(pci_mem_phy0, length);
release_mem_region(nxp_pci_io_base, iolength);
return status;
pci_set_drvdata(dev, hcd);
return 0;
cleanup3:
release_mem_region(pci_mem_phy0, memlength);
cleanup2:
iounmap(iobase);
cleanup1:
release_mem_region(nxp_pci_io_base, iolength);
return ret_status;
}
static void isp1761_pci_remove(struct pci_dev *dev)
{
struct usb_hcd *hcd;
......@@ -255,12 +274,6 @@ static void isp1761_pci_remove(struct pci_dev *dev)
usb_put_hcd(hcd);
pci_disable_device(dev);
iounmap(iobase);
iounmap(chip_addr);
release_mem_region(nxp_pci_io_base, iolength);
release_mem_region(pci_mem_phy0, length);
}
static void isp1761_pci_shutdown(struct pci_dev *dev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment