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