linux/drivers/usb/isp1760/isp1760-if.c
<<
>>
Prefs
   1/*
   2 * Glue code for the ISP1760 driver and bus
   3 * Currently there is support for
   4 * - OpenFirmware
   5 * - PCI
   6 * - PDEV (generic platform device centralized driver model)
   7 *
   8 * (c) 2007 Sebastian Siewior <bigeasy@linutronix.de>
   9 *
  10 */
  11
  12#include <linux/usb.h>
  13#include <linux/io.h>
  14#include <linux/module.h>
  15#include <linux/of.h>
  16#include <linux/platform_device.h>
  17#include <linux/slab.h>
  18#include <linux/usb/isp1760.h>
  19#include <linux/usb/hcd.h>
  20
  21#include "isp1760-core.h"
  22#include "isp1760-regs.h"
  23
  24#ifdef CONFIG_PCI
  25#include <linux/pci.h>
  26#endif
  27
  28#ifdef CONFIG_PCI
  29static int isp1761_pci_init(struct pci_dev *dev)
  30{
  31        resource_size_t mem_start;
  32        resource_size_t mem_length;
  33        u8 __iomem *iobase;
  34        u8 latency, limit;
  35        int retry_count;
  36        u32 reg_data;
  37
  38        /* Grab the PLX PCI shared memory of the ISP 1761 we need  */
  39        mem_start = pci_resource_start(dev, 3);
  40        mem_length = pci_resource_len(dev, 3);
  41        if (mem_length < 0xffff) {
  42                printk(KERN_ERR "memory length for this resource is wrong\n");
  43                return -ENOMEM;
  44        }
  45
  46        if (!request_mem_region(mem_start, mem_length, "ISP-PCI")) {
  47                printk(KERN_ERR "host controller already in use\n");
  48                return -EBUSY;
  49        }
  50
  51        /* map available memory */
  52        iobase = ioremap_nocache(mem_start, mem_length);
  53        if (!iobase) {
  54                printk(KERN_ERR "Error ioremap failed\n");
  55                release_mem_region(mem_start, mem_length);
  56                return -ENOMEM;
  57        }
  58
  59        /* bad pci latencies can contribute to overruns */
  60        pci_read_config_byte(dev, PCI_LATENCY_TIMER, &latency);
  61        if (latency) {
  62                pci_read_config_byte(dev, PCI_MAX_LAT, &limit);
  63                if (limit && limit < latency)
  64                        pci_write_config_byte(dev, PCI_LATENCY_TIMER, limit);
  65        }
  66
  67        /* Try to check whether we can access Scratch Register of
  68         * Host Controller or not. The initial PCI access is retried until
  69         * local init for the PCI bridge is completed
  70         */
  71        retry_count = 20;
  72        reg_data = 0;
  73        while ((reg_data != 0xFACE) && retry_count) {
  74                /*by default host is in 16bit mode, so
  75                 * io operations at this stage must be 16 bit
  76                 * */
  77                writel(0xface, iobase + HC_SCRATCH_REG);
  78                udelay(100);
  79                reg_data = readl(iobase + HC_SCRATCH_REG) & 0x0000ffff;
  80                retry_count--;
  81        }
  82
  83        iounmap(iobase);
  84        release_mem_region(mem_start, mem_length);
  85
  86        /* Host Controller presence is detected by writing to scratch register
  87         * and reading back and checking the contents are same or not
  88         */
  89        if (reg_data != 0xFACE) {
  90                dev_err(&dev->dev, "scratch register mismatch %x\n", reg_data);
  91                return -ENOMEM;
  92        }
  93
  94        /* Grab the PLX PCI mem maped port start address we need  */
  95        mem_start = pci_resource_start(dev, 0);
  96        mem_length = pci_resource_len(dev, 0);
  97
  98        if (!request_mem_region(mem_start, mem_length, "ISP1761 IO MEM")) {
  99                printk(KERN_ERR "request region #1\n");
 100                return -EBUSY;
 101        }
 102
 103        iobase = ioremap_nocache(mem_start, mem_length);
 104        if (!iobase) {
 105                printk(KERN_ERR "ioremap #1\n");
 106                release_mem_region(mem_start, mem_length);
 107                return -ENOMEM;
 108        }
 109
 110        /* configure PLX PCI chip to pass interrupts */
 111#define PLX_INT_CSR_REG 0x68
 112        reg_data = readl(iobase + PLX_INT_CSR_REG);
 113        reg_data |= 0x900;
 114        writel(reg_data, iobase + PLX_INT_CSR_REG);
 115
 116        /* done with PLX IO access */
 117        iounmap(iobase);
 118        release_mem_region(mem_start, mem_length);
 119
 120        return 0;
 121}
 122
 123static int isp1761_pci_probe(struct pci_dev *dev,
 124                const struct pci_device_id *id)
 125{
 126        unsigned int devflags = 0;
 127        int ret;
 128
 129        if (!dev->irq)
 130                return -ENODEV;
 131
 132        if (pci_enable_device(dev) < 0)
 133                return -ENODEV;
 134
 135        ret = isp1761_pci_init(dev);
 136        if (ret < 0)
 137                goto error;
 138
 139        pci_set_master(dev);
 140
 141        dev->dev.dma_mask = NULL;
 142        ret = isp1760_register(&dev->resource[3], dev->irq, 0, &dev->dev,
 143                               devflags);
 144        if (ret < 0)
 145                goto error;
 146
 147        return 0;
 148
 149error:
 150        pci_disable_device(dev);
 151        return ret;
 152}
 153
 154static void isp1761_pci_remove(struct pci_dev *dev)
 155{
 156        isp1760_unregister(&dev->dev);
 157
 158        pci_disable_device(dev);
 159}
 160
 161static void isp1761_pci_shutdown(struct pci_dev *dev)
 162{
 163        printk(KERN_ERR "ips1761_pci_shutdown\n");
 164}
 165
 166static const struct pci_device_id isp1760_plx [] = {
 167        {
 168                .class          = PCI_CLASS_BRIDGE_OTHER << 8,
 169                .class_mask     = ~0,
 170                .vendor         = PCI_VENDOR_ID_PLX,
 171                .device         = 0x5406,
 172                .subvendor      = PCI_VENDOR_ID_PLX,
 173                .subdevice      = 0x9054,
 174        },
 175        { }
 176};
 177MODULE_DEVICE_TABLE(pci, isp1760_plx);
 178
 179static struct pci_driver isp1761_pci_driver = {
 180        .name =         "isp1760",
 181        .id_table =     isp1760_plx,
 182        .probe =        isp1761_pci_probe,
 183        .remove =       isp1761_pci_remove,
 184        .shutdown =     isp1761_pci_shutdown,
 185};
 186#endif
 187
 188static int isp1760_plat_probe(struct platform_device *pdev)
 189{
 190        unsigned long irqflags;
 191        unsigned int devflags = 0;
 192        struct resource *mem_res;
 193        struct resource *irq_res;
 194        int ret;
 195
 196        mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 197
 198        irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 199        if (!irq_res) {
 200                pr_warning("isp1760: IRQ resource not available\n");
 201                return -ENODEV;
 202        }
 203        irqflags = irq_res->flags & IRQF_TRIGGER_MASK;
 204
 205        if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
 206                struct device_node *dp = pdev->dev.of_node;
 207                u32 bus_width = 0;
 208
 209                if (of_device_is_compatible(dp, "nxp,usb-isp1761"))
 210                        devflags |= ISP1760_FLAG_ISP1761;
 211
 212                /* Some systems wire up only 16 of the 32 data lines */
 213                of_property_read_u32(dp, "bus-width", &bus_width);
 214                if (bus_width == 16)
 215                        devflags |= ISP1760_FLAG_BUS_WIDTH_16;
 216
 217                if (of_property_read_bool(dp, "port1-otg"))
 218                        devflags |= ISP1760_FLAG_OTG_EN;
 219
 220                if (of_property_read_bool(dp, "analog-oc"))
 221                        devflags |= ISP1760_FLAG_ANALOG_OC;
 222
 223                if (of_property_read_bool(dp, "dack-polarity"))
 224                        devflags |= ISP1760_FLAG_DACK_POL_HIGH;
 225
 226                if (of_property_read_bool(dp, "dreq-polarity"))
 227                        devflags |= ISP1760_FLAG_DREQ_POL_HIGH;
 228        } else if (dev_get_platdata(&pdev->dev)) {
 229                struct isp1760_platform_data *pdata =
 230                        dev_get_platdata(&pdev->dev);
 231
 232                if (pdata->is_isp1761)
 233                        devflags |= ISP1760_FLAG_ISP1761;
 234                if (pdata->bus_width_16)
 235                        devflags |= ISP1760_FLAG_BUS_WIDTH_16;
 236                if (pdata->port1_otg)
 237                        devflags |= ISP1760_FLAG_OTG_EN;
 238                if (pdata->analog_oc)
 239                        devflags |= ISP1760_FLAG_ANALOG_OC;
 240                if (pdata->dack_polarity_high)
 241                        devflags |= ISP1760_FLAG_DACK_POL_HIGH;
 242                if (pdata->dreq_polarity_high)
 243                        devflags |= ISP1760_FLAG_DREQ_POL_HIGH;
 244        }
 245
 246        ret = isp1760_register(mem_res, irq_res->start, irqflags, &pdev->dev,
 247                               devflags);
 248        if (ret < 0)
 249                return ret;
 250
 251        pr_info("ISP1760 USB device initialised\n");
 252        return 0;
 253}
 254
 255static int isp1760_plat_remove(struct platform_device *pdev)
 256{
 257        isp1760_unregister(&pdev->dev);
 258
 259        return 0;
 260}
 261
 262#ifdef CONFIG_OF
 263static const struct of_device_id isp1760_of_match[] = {
 264        { .compatible = "nxp,usb-isp1760", },
 265        { .compatible = "nxp,usb-isp1761", },
 266        { },
 267};
 268MODULE_DEVICE_TABLE(of, isp1760_of_match);
 269#endif
 270
 271static struct platform_driver isp1760_plat_driver = {
 272        .probe  = isp1760_plat_probe,
 273        .remove = isp1760_plat_remove,
 274        .driver = {
 275                .name   = "isp1760",
 276                .of_match_table = of_match_ptr(isp1760_of_match),
 277        },
 278};
 279
 280static int __init isp1760_init(void)
 281{
 282        int ret, any_ret = -ENODEV;
 283
 284        isp1760_init_kmem_once();
 285
 286        ret = platform_driver_register(&isp1760_plat_driver);
 287        if (!ret)
 288                any_ret = 0;
 289#ifdef CONFIG_PCI
 290        ret = pci_register_driver(&isp1761_pci_driver);
 291        if (!ret)
 292                any_ret = 0;
 293#endif
 294
 295        if (any_ret)
 296                isp1760_deinit_kmem_cache();
 297        return any_ret;
 298}
 299module_init(isp1760_init);
 300
 301static void __exit isp1760_exit(void)
 302{
 303        platform_driver_unregister(&isp1760_plat_driver);
 304#ifdef CONFIG_PCI
 305        pci_unregister_driver(&isp1761_pci_driver);
 306#endif
 307        isp1760_deinit_kmem_cache();
 308}
 309module_exit(isp1760_exit);
 310