linux/drivers/usb/isp1760/isp1760-if.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Glue code for the ISP1760 driver and bus
   4 * Currently there is support for
   5 * - OpenFirmware
   6 * - PCI
   7 * - PDEV (generic platform device centralized driver model)
   8 *
   9 * (c) 2007 Sebastian Siewior <bigeasy@linutronix.de>
  10 *
  11 */
  12
  13#include <linux/usb.h>
  14#include <linux/io.h>
  15#include <linux/module.h>
  16#include <linux/of.h>
  17#include <linux/platform_device.h>
  18#include <linux/slab.h>
  19#include <linux/usb/isp1760.h>
  20#include <linux/usb/hcd.h>
  21
  22#include "isp1760-core.h"
  23#include "isp1760-regs.h"
  24
  25#ifdef CONFIG_USB_PCI
  26#include <linux/pci.h>
  27#endif
  28
  29#ifdef CONFIG_USB_PCI
  30static int isp1761_pci_init(struct pci_dev *dev)
  31{
  32        resource_size_t mem_start;
  33        resource_size_t mem_length;
  34        u8 __iomem *iobase;
  35        u8 latency, limit;
  36        int retry_count;
  37        u32 reg_data;
  38
  39        /* Grab the PLX PCI shared memory of the ISP 1761 we need  */
  40        mem_start = pci_resource_start(dev, 3);
  41        mem_length = pci_resource_len(dev, 3);
  42        if (mem_length < 0xffff) {
  43                printk(KERN_ERR "memory length for this resource is wrong\n");
  44                return -ENOMEM;
  45        }
  46
  47        if (!request_mem_region(mem_start, mem_length, "ISP-PCI")) {
  48                printk(KERN_ERR "host controller already in use\n");
  49                return -EBUSY;
  50        }
  51
  52        /* map available memory */
  53        iobase = ioremap_nocache(mem_start, mem_length);
  54        if (!iobase) {
  55                printk(KERN_ERR "Error ioremap failed\n");
  56                release_mem_region(mem_start, mem_length);
  57                return -ENOMEM;
  58        }
  59
  60        /* bad pci latencies can contribute to overruns */
  61        pci_read_config_byte(dev, PCI_LATENCY_TIMER, &latency);
  62        if (latency) {
  63                pci_read_config_byte(dev, PCI_MAX_LAT, &limit);
  64                if (limit && limit < latency)
  65                        pci_write_config_byte(dev, PCI_LATENCY_TIMER, limit);
  66        }
  67
  68        /* Try to check whether we can access Scratch Register of
  69         * Host Controller or not. The initial PCI access is retried until
  70         * local init for the PCI bridge is completed
  71         */
  72        retry_count = 20;
  73        reg_data = 0;
  74        while ((reg_data != 0xFACE) && retry_count) {
  75                /*by default host is in 16bit mode, so
  76                 * io operations at this stage must be 16 bit
  77                 * */
  78                writel(0xface, iobase + HC_SCRATCH_REG);
  79                udelay(100);
  80                reg_data = readl(iobase + HC_SCRATCH_REG) & 0x0000ffff;
  81                retry_count--;
  82        }
  83
  84        iounmap(iobase);
  85        release_mem_region(mem_start, mem_length);
  86
  87        /* Host Controller presence is detected by writing to scratch register
  88         * and reading back and checking the contents are same or not
  89         */
  90        if (reg_data != 0xFACE) {
  91                dev_err(&dev->dev, "scratch register mismatch %x\n", reg_data);
  92                return -ENOMEM;
  93        }
  94
  95        /* Grab the PLX PCI mem maped port start address we need  */
  96        mem_start = pci_resource_start(dev, 0);
  97        mem_length = pci_resource_len(dev, 0);
  98
  99        if (!request_mem_region(mem_start, mem_length, "ISP1761 IO MEM")) {
 100                printk(KERN_ERR "request region #1\n");
 101                return -EBUSY;
 102        }
 103
 104        iobase = ioremap_nocache(mem_start, mem_length);
 105        if (!iobase) {
 106                printk(KERN_ERR "ioremap #1\n");
 107                release_mem_region(mem_start, mem_length);
 108                return -ENOMEM;
 109        }
 110
 111        /* configure PLX PCI chip to pass interrupts */
 112#define PLX_INT_CSR_REG 0x68
 113        reg_data = readl(iobase + PLX_INT_CSR_REG);
 114        reg_data |= 0x900;
 115        writel(reg_data, iobase + PLX_INT_CSR_REG);
 116
 117        /* done with PLX IO access */
 118        iounmap(iobase);
 119        release_mem_region(mem_start, mem_length);
 120
 121        return 0;
 122}
 123
 124static int isp1761_pci_probe(struct pci_dev *dev,
 125                const struct pci_device_id *id)
 126{
 127        unsigned int devflags = 0;
 128        int ret;
 129
 130        if (!dev->irq)
 131                return -ENODEV;
 132
 133        if (pci_enable_device(dev) < 0)
 134                return -ENODEV;
 135
 136        ret = isp1761_pci_init(dev);
 137        if (ret < 0)
 138                goto error;
 139
 140        pci_set_master(dev);
 141
 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_warn("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_USB_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_USB_PCI
 305        pci_unregister_driver(&isp1761_pci_driver);
 306#endif
 307        isp1760_deinit_kmem_cache();
 308}
 309module_exit(isp1760_exit);
 310