Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
0002 /*
0003  * pci.c - DesignWare HS OTG Controller PCI driver
0004  *
0005  * Copyright (C) 2004-2013 Synopsys, Inc.
0006  *
0007  * Redistribution and use in source and binary forms, with or without
0008  * modification, are permitted provided that the following conditions
0009  * are met:
0010  * 1. Redistributions of source code must retain the above copyright
0011  *    notice, this list of conditions, and the following disclaimer,
0012  *    without modification.
0013  * 2. Redistributions in binary form must reproduce the above copyright
0014  *    notice, this list of conditions and the following disclaimer in the
0015  *    documentation and/or other materials provided with the distribution.
0016  * 3. The names of the above-listed copyright holders may not be used
0017  *    to endorse or promote products derived from this software without
0018  *    specific prior written permission.
0019  *
0020  * ALTERNATIVELY, this software may be distributed under the terms of the
0021  * GNU General Public License ("GPL") as published by the Free Software
0022  * Foundation; either version 2 of the License, or (at your option) any
0023  * later version.
0024  *
0025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
0026  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
0027  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
0028  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
0029  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0030  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0031  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
0032  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
0033  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
0034  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0035  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0036  */
0037 
0038 /*
0039  * Provides the initialization and cleanup entry points for the DWC_otg PCI
0040  * driver
0041  */
0042 #include <linux/kernel.h>
0043 #include <linux/module.h>
0044 #include <linux/moduleparam.h>
0045 #include <linux/spinlock.h>
0046 #include <linux/interrupt.h>
0047 #include <linux/io.h>
0048 #include <linux/slab.h>
0049 #include <linux/pci.h>
0050 #include <linux/usb.h>
0051 
0052 #include <linux/usb/hcd.h>
0053 #include <linux/usb/ch11.h>
0054 #include <linux/platform_device.h>
0055 #include <linux/usb/usb_phy_generic.h>
0056 
0057 #define PCI_PRODUCT_ID_HAPS_HSOTG   0xabc0
0058 
0059 static const char dwc2_driver_name[] = "dwc2-pci";
0060 
0061 struct dwc2_pci_glue {
0062     struct platform_device *dwc2;
0063     struct platform_device *phy;
0064 };
0065 
0066 /**
0067  * dwc2_pci_remove() - Provides the cleanup entry points for the DWC_otg PCI
0068  * driver
0069  *
0070  * @pci: The programming view of DWC_otg PCI
0071  */
0072 static void dwc2_pci_remove(struct pci_dev *pci)
0073 {
0074     struct dwc2_pci_glue *glue = pci_get_drvdata(pci);
0075 
0076     platform_device_unregister(glue->dwc2);
0077     usb_phy_generic_unregister(glue->phy);
0078     pci_set_drvdata(pci, NULL);
0079 }
0080 
0081 static int dwc2_pci_probe(struct pci_dev *pci,
0082               const struct pci_device_id *id)
0083 {
0084     struct resource     res[2];
0085     struct platform_device  *dwc2;
0086     struct platform_device  *phy;
0087     int         ret;
0088     struct device       *dev = &pci->dev;
0089     struct dwc2_pci_glue    *glue;
0090 
0091     ret = pcim_enable_device(pci);
0092     if (ret) {
0093         dev_err(dev, "failed to enable pci device\n");
0094         return -ENODEV;
0095     }
0096 
0097     pci_set_master(pci);
0098 
0099     phy = usb_phy_generic_register();
0100     if (IS_ERR(phy)) {
0101         dev_err(dev, "error registering generic PHY (%ld)\n",
0102             PTR_ERR(phy));
0103         return PTR_ERR(phy);
0104     }
0105 
0106     dwc2 = platform_device_alloc("dwc2", PLATFORM_DEVID_AUTO);
0107     if (!dwc2) {
0108         dev_err(dev, "couldn't allocate dwc2 device\n");
0109         ret = -ENOMEM;
0110         goto err;
0111     }
0112 
0113     memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res));
0114 
0115     res[0].start    = pci_resource_start(pci, 0);
0116     res[0].end  = pci_resource_end(pci, 0);
0117     res[0].name = "dwc2";
0118     res[0].flags    = IORESOURCE_MEM;
0119 
0120     res[1].start    = pci->irq;
0121     res[1].name = "dwc2";
0122     res[1].flags    = IORESOURCE_IRQ;
0123 
0124     ret = platform_device_add_resources(dwc2, res, ARRAY_SIZE(res));
0125     if (ret) {
0126         dev_err(dev, "couldn't add resources to dwc2 device\n");
0127         goto err;
0128     }
0129 
0130     dwc2->dev.parent = dev;
0131 
0132     glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL);
0133     if (!glue) {
0134         ret = -ENOMEM;
0135         goto err;
0136     }
0137 
0138     ret = platform_device_add(dwc2);
0139     if (ret) {
0140         dev_err(dev, "failed to register dwc2 device\n");
0141         goto err;
0142     }
0143 
0144     glue->phy = phy;
0145     glue->dwc2 = dwc2;
0146     pci_set_drvdata(pci, glue);
0147 
0148     return 0;
0149 err:
0150     usb_phy_generic_unregister(phy);
0151     platform_device_put(dwc2);
0152     return ret;
0153 }
0154 
0155 static const struct pci_device_id dwc2_pci_ids[] = {
0156     {
0157         PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, PCI_PRODUCT_ID_HAPS_HSOTG),
0158     },
0159     {
0160         PCI_DEVICE(PCI_VENDOR_ID_STMICRO,
0161                PCI_DEVICE_ID_STMICRO_USB_OTG),
0162     },
0163     { /* end: all zeroes */ }
0164 };
0165 MODULE_DEVICE_TABLE(pci, dwc2_pci_ids);
0166 
0167 static struct pci_driver dwc2_pci_driver = {
0168     .name = dwc2_driver_name,
0169     .id_table = dwc2_pci_ids,
0170     .probe = dwc2_pci_probe,
0171     .remove = dwc2_pci_remove,
0172 };
0173 
0174 module_pci_driver(dwc2_pci_driver);
0175 
0176 MODULE_DESCRIPTION("DESIGNWARE HS OTG PCI Bus Glue");
0177 MODULE_AUTHOR("Synopsys, Inc.");
0178 MODULE_LICENSE("Dual BSD/GPL");