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        dev->dev.dma_mask = NULL;
 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                /* Some systems wire up only 16 of the 32 data lines */
 214                of_property_read_u32(dp, "bus-width", &bus_width);
 215                if (bus_width == 16)
 216                        devflags |= ISP1760_FLAG_BUS_WIDTH_16;
 217
 218                if (of_property_read_bool(dp, "port1-otg"))
 219                        devflags |= ISP1760_FLAG_OTG_EN;
 220
 221                if (of_property_read_bool(dp, "analog-oc"))
 222                        devflags |= ISP1760_FLAG_ANALOG_OC;
 223
 224                if (of_property_read_bool(dp, "dack-polarity"))
 225                        devflags |= ISP1760_FLAG_DACK_POL_HIGH;
 226
 227                if (of_property_read_bool(dp, "dreq-polarity"))
 228                        devflags |= ISP1760_FLAG_DREQ_POL_HIGH;
 229        } else if (dev_get_platdata(&pdev->dev)) {
 230                struct isp1760_platform_data *pdata =
 231                        dev_get_platdata(&pdev->dev);
 232
 233                if (pdata->is_isp1761)
 234                        devflags |= ISP1760_FLAG_ISP1761;
 235                if (pdata->bus_width_16)
 236                        devflags |= ISP1760_FLAG_BUS_WIDTH_16;
 237                if (pdata->port1_otg)
 238                        devflags |= ISP1760_FLAG_OTG_EN;
 239                if (pdata->analog_oc)
 240                        devflags |= ISP1760_FLAG_ANALOG_OC;
 241                if (pdata->dack_polarity_high)
 242                        devflags |= ISP1760_FLAG_DACK_POL_HIGH;
 243                if (pdata->dreq_polarity_high)
 244                        devflags |= ISP1760_FLAG_DREQ_POL_HIGH;
 245        }
 246
 247        ret = isp1760_register(mem_res, irq_res->start, irqflags, &pdev->dev,
 248                               devflags);
 249        if (ret < 0)
 250                return ret;
 251
 252        pr_info("ISP1760 USB device initialised\n");
 253        return 0;
 254}
 255
 256static int isp1760_plat_remove(struct platform_device *pdev)
 257{
 258        isp1760_unregister(&pdev->dev);
 259
 260        return 0;
 261}
 262
 263#ifdef CONFIG_OF
 264static const struct of_device_id isp1760_of_match[] = {
 265        { .compatible = "nxp,usb-isp1760", },
 266        { .compatible = "nxp,usb-isp1761", },
 267        { },
 268};
 269MODULE_DEVICE_TABLE(of, isp1760_of_match);
 270#endif
 271
 272static struct platform_driver isp1760_plat_driver = {
 273        .probe  = isp1760_plat_probe,
 274        .remove = isp1760_plat_remove,
 275        .driver = {
 276                .name   = "isp1760",
 277                .of_match_table = of_match_ptr(isp1760_of_match),
 278        },
 279};
 280
 281static int __init isp1760_init(void)
 282{
 283        int ret, any_ret = -ENODEV;
 284
 285        isp1760_init_kmem_once();
 286
 287        ret = platform_driver_register(&isp1760_plat_driver);
 288        if (!ret)
 289                any_ret = 0;
 290#ifdef CONFIG_USB_PCI
 291        ret = pci_register_driver(&isp1761_pci_driver);
 292        if (!ret)
 293                any_ret = 0;
 294#endif
 295
 296        if (any_ret)
 297                isp1760_deinit_kmem_cache();
 298        return any_ret;
 299}
 300module_init(isp1760_init);
 301
 302static void __exit isp1760_exit(void)
 303{
 304        platform_driver_unregister(&isp1760_plat_driver);
 305#ifdef CONFIG_USB_PCI
 306        pci_unregister_driver(&isp1761_pci_driver);
 307#endif
 308        isp1760_deinit_kmem_cache();
 309}
 310module_exit(isp1760_exit);
 311