linux/drivers/usb/host/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/platform_device.h>
  15#include <linux/usb/isp1760.h>
  16
  17#include "../core/hcd.h"
  18#include "isp1760-hcd.h"
  19
  20#ifdef CONFIG_PPC_OF
  21#include <linux/of.h>
  22#include <linux/of_platform.h>
  23#endif
  24
  25#ifdef CONFIG_PCI
  26#include <linux/pci.h>
  27#endif
  28
  29#ifdef CONFIG_PPC_OF
  30static int of_isp1760_probe(struct of_device *dev,
  31                const struct of_device_id *match)
  32{
  33        struct usb_hcd *hcd;
  34        struct device_node *dp = dev->node;
  35        struct resource *res;
  36        struct resource memory;
  37        struct of_irq oirq;
  38        int virq;
  39        u64 res_len;
  40        int ret;
  41        const unsigned int *prop;
  42        unsigned int devflags = 0;
  43
  44        ret = of_address_to_resource(dp, 0, &memory);
  45        if (ret)
  46                return -ENXIO;
  47
  48        res = request_mem_region(memory.start, memory.end - memory.start + 1,
  49                        dev_name(&dev->dev));
  50        if (!res)
  51                return -EBUSY;
  52
  53        res_len = memory.end - memory.start + 1;
  54
  55        if (of_irq_map_one(dp, 0, &oirq)) {
  56                ret = -ENODEV;
  57                goto release_reg;
  58        }
  59
  60        virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
  61                        oirq.size);
  62
  63        if (of_device_is_compatible(dp, "nxp,usb-isp1761"))
  64                devflags |= ISP1760_FLAG_ISP1761;
  65
  66        /* Some systems wire up only 16 of the 32 data lines */
  67        prop = of_get_property(dp, "bus-width", NULL);
  68        if (prop && *prop == 16)
  69                devflags |= ISP1760_FLAG_BUS_WIDTH_16;
  70
  71        if (of_get_property(dp, "port1-otg", NULL) != NULL)
  72                devflags |= ISP1760_FLAG_OTG_EN;
  73
  74        if (of_get_property(dp, "analog-oc", NULL) != NULL)
  75                devflags |= ISP1760_FLAG_ANALOG_OC;
  76
  77        if (of_get_property(dp, "dack-polarity", NULL) != NULL)
  78                devflags |= ISP1760_FLAG_DACK_POL_HIGH;
  79
  80        if (of_get_property(dp, "dreq-polarity", NULL) != NULL)
  81                devflags |= ISP1760_FLAG_DREQ_POL_HIGH;
  82
  83        hcd = isp1760_register(memory.start, res_len, virq,
  84                IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev),
  85                devflags);
  86        if (IS_ERR(hcd)) {
  87                ret = PTR_ERR(hcd);
  88                goto release_reg;
  89        }
  90
  91        dev_set_drvdata(&dev->dev, hcd);
  92        return ret;
  93
  94release_reg:
  95        release_mem_region(memory.start, memory.end - memory.start + 1);
  96        return ret;
  97}
  98
  99static int of_isp1760_remove(struct of_device *dev)
 100{
 101        struct usb_hcd *hcd = dev_get_drvdata(&dev->dev);
 102
 103        dev_set_drvdata(&dev->dev, NULL);
 104
 105        usb_remove_hcd(hcd);
 106        iounmap(hcd->regs);
 107        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 108        usb_put_hcd(hcd);
 109        return 0;
 110}
 111
 112static struct of_device_id of_isp1760_match[] = {
 113        {
 114                .compatible = "nxp,usb-isp1760",
 115        },
 116        {
 117                .compatible = "nxp,usb-isp1761",
 118        },
 119        { },
 120};
 121MODULE_DEVICE_TABLE(of, of_isp1760_match);
 122
 123static struct of_platform_driver isp1760_of_driver = {
 124        .name           = "nxp-isp1760",
 125        .match_table    = of_isp1760_match,
 126        .probe          = of_isp1760_probe,
 127        .remove         = of_isp1760_remove,
 128};
 129#endif
 130
 131#ifdef CONFIG_PCI
 132static int __devinit isp1761_pci_probe(struct pci_dev *dev,
 133                const struct pci_device_id *id)
 134{
 135        u8 latency, limit;
 136        __u32 reg_data;
 137        int retry_count;
 138        struct usb_hcd *hcd;
 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
 150        if (usb_disabled())
 151                return -ENODEV;
 152
 153        if (pci_enable_device(dev) < 0)
 154                return -ENODEV;
 155
 156        if (!dev->irq)
 157                return -ENODEV;
 158
 159        /* Grab the PLX PCI mem maped port start address we need  */
 160        nxp_pci_io_base = pci_resource_start(dev, 0);
 161        iolength = pci_resource_len(dev, 0);
 162
 163        if (!request_mem_region(nxp_pci_io_base, iolength, "ISP1761 IO MEM")) {
 164                printk(KERN_ERR "request region #1\n");
 165                return -EBUSY;
 166        }
 167
 168        iobase = ioremap_nocache(nxp_pci_io_base, iolength);
 169        if (!iobase) {
 170                printk(KERN_ERR "ioremap #1\n");
 171                ret_status = -ENOMEM;
 172                goto cleanup1;
 173        }
 174        /* Grab the PLX PCI shared memory of the ISP 1761 we need  */
 175        pci_mem_phy0 = pci_resource_start(dev, 3);
 176        memlength = pci_resource_len(dev, 3);
 177        if (memlength < 0xffff) {
 178                printk(KERN_ERR "memory length for this resource is wrong\n");
 179                ret_status = -ENOMEM;
 180                goto cleanup2;
 181        }
 182
 183        if (!request_mem_region(pci_mem_phy0, memlength, "ISP-PCI")) {
 184                printk(KERN_ERR "host controller already in use\n");
 185                ret_status = -EBUSY;
 186                goto cleanup2;
 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;
 195        }
 196
 197        /* bad pci latencies can contribute to overruns */
 198        pci_read_config_byte(dev, PCI_LATENCY_TIMER, &latency);
 199        if (latency) {
 200                pci_read_config_byte(dev, PCI_MAX_LAT, &limit);
 201                if (limit && limit < latency)
 202                        pci_write_config_byte(dev, PCI_LATENCY_TIMER, limit);
 203        }
 204
 205        /* Try to check whether we can access Scratch Register of
 206         * Host Controller or not. The initial PCI access is retried until
 207         * local init for the PCI bridge is completed
 208         */
 209        retry_count = 20;
 210        reg_data = 0;
 211        while ((reg_data != 0xFACE) && retry_count) {
 212                /*by default host is in 16bit mode, so
 213                 * io operations at this stage must be 16 bit
 214                 * */
 215                writel(0xface, chip_addr + HC_SCRATCH_REG);
 216                udelay(100);
 217                reg_data = readl(chip_addr + HC_SCRATCH_REG) & 0x0000ffff;
 218                retry_count--;
 219        }
 220
 221        iounmap(chip_addr);
 222
 223        /* Host Controller presence is detected by writing to scratch register
 224         * and reading back and checking the contents are same or not
 225         */
 226        if (reg_data != 0xFACE) {
 227                dev_err(&dev->dev, "scratch register mismatch %x\n", reg_data);
 228                ret_status = -ENOMEM;
 229                goto cleanup3;
 230        }
 231
 232        pci_set_master(dev);
 233
 234        /* configure PLX PCI chip to pass interrupts */
 235#define PLX_INT_CSR_REG 0x68
 236        reg_data = readl(iobase + PLX_INT_CSR_REG);
 237        reg_data |= 0x900;
 238        writel(reg_data, iobase + PLX_INT_CSR_REG);
 239
 240        dev->dev.dma_mask = NULL;
 241        hcd = isp1760_register(pci_mem_phy0, memlength, dev->irq,
 242                IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev),
 243                devflags);
 244        if (IS_ERR(hcd)) {
 245                ret_status = -ENODEV;
 246                goto cleanup3;
 247        }
 248
 249        /* done with PLX IO access */
 250        iounmap(iobase);
 251        release_mem_region(nxp_pci_io_base, iolength);
 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;
 263}
 264
 265static void isp1761_pci_remove(struct pci_dev *dev)
 266{
 267        struct usb_hcd *hcd;
 268
 269        hcd = pci_get_drvdata(dev);
 270
 271        usb_remove_hcd(hcd);
 272        iounmap(hcd->regs);
 273        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 274        usb_put_hcd(hcd);
 275
 276        pci_disable_device(dev);
 277}
 278
 279static void isp1761_pci_shutdown(struct pci_dev *dev)
 280{
 281        printk(KERN_ERR "ips1761_pci_shutdown\n");
 282}
 283
 284static const struct pci_device_id isp1760_plx [] = {
 285        {
 286                .class          = PCI_CLASS_BRIDGE_OTHER << 8,
 287                .class_mask     = ~0,
 288                .vendor         = PCI_VENDOR_ID_PLX,
 289                .device         = 0x5406,
 290                .subvendor      = PCI_VENDOR_ID_PLX,
 291                .subdevice      = 0x9054,
 292        },
 293        { }
 294};
 295MODULE_DEVICE_TABLE(pci, isp1760_plx);
 296
 297static struct pci_driver isp1761_pci_driver = {
 298        .name =         "isp1760",
 299        .id_table =     isp1760_plx,
 300        .probe =        isp1761_pci_probe,
 301        .remove =       isp1761_pci_remove,
 302        .shutdown =     isp1761_pci_shutdown,
 303};
 304#endif
 305
 306static int __devinit isp1760_plat_probe(struct platform_device *pdev)
 307{
 308        int ret = 0;
 309        struct usb_hcd *hcd;
 310        struct resource *mem_res;
 311        struct resource *irq_res;
 312        resource_size_t mem_size;
 313        struct isp1760_platform_data *priv = pdev->dev.platform_data;
 314        unsigned int devflags = 0;
 315        unsigned long irqflags = IRQF_SHARED | IRQF_DISABLED;
 316
 317        mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 318        if (!mem_res) {
 319                pr_warning("isp1760: Memory resource not available\n");
 320                ret = -ENODEV;
 321                goto out;
 322        }
 323        mem_size = resource_size(mem_res);
 324        if (!request_mem_region(mem_res->start, mem_size, "isp1760")) {
 325                pr_warning("isp1760: Cannot reserve the memory resource\n");
 326                ret = -EBUSY;
 327                goto out;
 328        }
 329
 330        irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 331        if (!irq_res) {
 332                pr_warning("isp1760: IRQ resource not available\n");
 333                return -ENODEV;
 334        }
 335        irqflags |= irq_res->flags & IRQF_TRIGGER_MASK;
 336
 337        if (priv) {
 338                if (priv->is_isp1761)
 339                        devflags |= ISP1760_FLAG_ISP1761;
 340                if (priv->bus_width_16)
 341                        devflags |= ISP1760_FLAG_BUS_WIDTH_16;
 342                if (priv->port1_otg)
 343                        devflags |= ISP1760_FLAG_OTG_EN;
 344                if (priv->analog_oc)
 345                        devflags |= ISP1760_FLAG_ANALOG_OC;
 346                if (priv->dack_polarity_high)
 347                        devflags |= ISP1760_FLAG_DACK_POL_HIGH;
 348                if (priv->dreq_polarity_high)
 349                        devflags |= ISP1760_FLAG_DREQ_POL_HIGH;
 350        }
 351
 352        hcd = isp1760_register(mem_res->start, mem_size, irq_res->start,
 353                               irqflags, &pdev->dev, dev_name(&pdev->dev), devflags);
 354        if (IS_ERR(hcd)) {
 355                pr_warning("isp1760: Failed to register the HCD device\n");
 356                ret = -ENODEV;
 357                goto cleanup;
 358        }
 359
 360        pr_info("ISP1760 USB device initialised\n");
 361        return ret;
 362
 363cleanup:
 364        release_mem_region(mem_res->start, mem_size);
 365out:
 366        return ret;
 367}
 368
 369static int __devexit isp1760_plat_remove(struct platform_device *pdev)
 370{
 371        struct resource *mem_res;
 372        resource_size_t mem_size;
 373
 374        mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 375        mem_size = resource_size(mem_res);
 376        release_mem_region(mem_res->start, mem_size);
 377
 378        return 0;
 379}
 380
 381static struct platform_driver isp1760_plat_driver = {
 382        .probe  = isp1760_plat_probe,
 383        .remove = __devexit_p(isp1760_plat_remove),
 384        .driver = {
 385                .name   = "isp1760",
 386        },
 387};
 388
 389static int __init isp1760_init(void)
 390{
 391        int ret, any_ret = -ENODEV;
 392
 393        init_kmem_once();
 394
 395        ret = platform_driver_register(&isp1760_plat_driver);
 396        if (!ret)
 397                any_ret = 0;
 398#ifdef CONFIG_PPC_OF
 399        ret = of_register_platform_driver(&isp1760_of_driver);
 400        if (!ret)
 401                any_ret = 0;
 402#endif
 403#ifdef CONFIG_PCI
 404        ret = pci_register_driver(&isp1761_pci_driver);
 405        if (!ret)
 406                any_ret = 0;
 407#endif
 408
 409        if (any_ret)
 410                deinit_kmem_cache();
 411        return any_ret;
 412}
 413module_init(isp1760_init);
 414
 415static void __exit isp1760_exit(void)
 416{
 417        platform_driver_unregister(&isp1760_plat_driver);
 418#ifdef CONFIG_PPC_OF
 419        of_unregister_platform_driver(&isp1760_of_driver);
 420#endif
 421#ifdef CONFIG_PCI
 422        pci_unregister_driver(&isp1761_pci_driver);
 423#endif
 424        deinit_kmem_cache();
 425}
 426module_exit(isp1760_exit);
 427