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