0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/pci.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/dma-mapping.h>
0015 #include <linux/slab.h>
0016
0017 struct cdns3_wrap {
0018 struct platform_device *plat_dev;
0019 struct resource dev_res[6];
0020 int devfn;
0021 };
0022
0023 #define RES_IRQ_HOST_ID 0
0024 #define RES_IRQ_PERIPHERAL_ID 1
0025 #define RES_IRQ_OTG_ID 2
0026 #define RES_HOST_ID 3
0027 #define RES_DEV_ID 4
0028 #define RES_DRD_ID 5
0029
0030 #define PCI_BAR_HOST 0
0031 #define PCI_BAR_DEV 2
0032 #define PCI_BAR_OTG 0
0033
0034 #define PCI_DEV_FN_HOST_DEVICE 0
0035 #define PCI_DEV_FN_OTG 1
0036
0037 #define PCI_DRIVER_NAME "cdns3-pci-usbss"
0038 #define PLAT_DRIVER_NAME "cdns-usb3"
0039
0040 #define CDNS_VENDOR_ID 0x17cd
0041 #define CDNS_DEVICE_ID 0x0100
0042
0043 static struct pci_dev *cdns3_get_second_fun(struct pci_dev *pdev)
0044 {
0045 struct pci_dev *func;
0046
0047
0048
0049
0050
0051
0052
0053 func = pci_get_device(pdev->vendor, pdev->device, NULL);
0054 if (unlikely(!func))
0055 return NULL;
0056
0057 if (func->devfn == pdev->devfn) {
0058 func = pci_get_device(pdev->vendor, pdev->device, func);
0059 if (unlikely(!func))
0060 return NULL;
0061 }
0062
0063 return func;
0064 }
0065
0066 static int cdns3_pci_probe(struct pci_dev *pdev,
0067 const struct pci_device_id *id)
0068 {
0069 struct platform_device_info plat_info;
0070 struct cdns3_wrap *wrap;
0071 struct resource *res;
0072 struct pci_dev *func;
0073 int err;
0074
0075
0076
0077
0078
0079 if (!id || (pdev->devfn != PCI_DEV_FN_HOST_DEVICE &&
0080 pdev->devfn != PCI_DEV_FN_OTG))
0081 return -EINVAL;
0082
0083 func = cdns3_get_second_fun(pdev);
0084 if (unlikely(!func))
0085 return -EINVAL;
0086
0087 err = pcim_enable_device(pdev);
0088 if (err) {
0089 dev_err(&pdev->dev, "Enabling PCI device has failed %d\n", err);
0090 return err;
0091 }
0092
0093 pci_set_master(pdev);
0094
0095 if (pci_is_enabled(func)) {
0096 wrap = pci_get_drvdata(func);
0097 } else {
0098 wrap = kzalloc(sizeof(*wrap), GFP_KERNEL);
0099 if (!wrap) {
0100 pci_disable_device(pdev);
0101 return -ENOMEM;
0102 }
0103 }
0104
0105 res = wrap->dev_res;
0106
0107 if (pdev->devfn == PCI_DEV_FN_HOST_DEVICE) {
0108
0109 dev_dbg(&pdev->dev, "Initialize Device resources\n");
0110 res[RES_DEV_ID].start = pci_resource_start(pdev, PCI_BAR_DEV);
0111 res[RES_DEV_ID].end = pci_resource_end(pdev, PCI_BAR_DEV);
0112 res[RES_DEV_ID].name = "dev";
0113 res[RES_DEV_ID].flags = IORESOURCE_MEM;
0114 dev_dbg(&pdev->dev, "USBSS-DEV physical base addr: %pa\n",
0115 &res[RES_DEV_ID].start);
0116
0117 res[RES_HOST_ID].start = pci_resource_start(pdev, PCI_BAR_HOST);
0118 res[RES_HOST_ID].end = pci_resource_end(pdev, PCI_BAR_HOST);
0119 res[RES_HOST_ID].name = "xhci";
0120 res[RES_HOST_ID].flags = IORESOURCE_MEM;
0121 dev_dbg(&pdev->dev, "USBSS-XHCI physical base addr: %pa\n",
0122 &res[RES_HOST_ID].start);
0123
0124
0125 wrap->dev_res[RES_IRQ_HOST_ID].start = pdev->irq;
0126 wrap->dev_res[RES_IRQ_HOST_ID].name = "host";
0127 wrap->dev_res[RES_IRQ_HOST_ID].flags = IORESOURCE_IRQ;
0128
0129
0130 wrap->dev_res[RES_IRQ_PERIPHERAL_ID].start = pdev->irq;
0131 wrap->dev_res[RES_IRQ_PERIPHERAL_ID].name = "peripheral";
0132 wrap->dev_res[RES_IRQ_PERIPHERAL_ID].flags = IORESOURCE_IRQ;
0133 } else {
0134 res[RES_DRD_ID].start = pci_resource_start(pdev, PCI_BAR_OTG);
0135 res[RES_DRD_ID].end = pci_resource_end(pdev, PCI_BAR_OTG);
0136 res[RES_DRD_ID].name = "otg";
0137 res[RES_DRD_ID].flags = IORESOURCE_MEM;
0138 dev_dbg(&pdev->dev, "USBSS-DRD physical base addr: %pa\n",
0139 &res[RES_DRD_ID].start);
0140
0141
0142 wrap->dev_res[RES_IRQ_OTG_ID].start = pdev->irq;
0143 wrap->dev_res[RES_IRQ_OTG_ID].name = "otg";
0144 wrap->dev_res[RES_IRQ_OTG_ID].flags = IORESOURCE_IRQ;
0145 }
0146
0147 if (pci_is_enabled(func)) {
0148
0149 memset(&plat_info, 0, sizeof(plat_info));
0150 plat_info.parent = &pdev->dev;
0151 plat_info.fwnode = pdev->dev.fwnode;
0152 plat_info.name = PLAT_DRIVER_NAME;
0153 plat_info.id = pdev->devfn;
0154 wrap->devfn = pdev->devfn;
0155 plat_info.res = wrap->dev_res;
0156 plat_info.num_res = ARRAY_SIZE(wrap->dev_res);
0157 plat_info.dma_mask = pdev->dma_mask;
0158
0159 wrap->plat_dev = platform_device_register_full(&plat_info);
0160 if (IS_ERR(wrap->plat_dev)) {
0161 pci_disable_device(pdev);
0162 err = PTR_ERR(wrap->plat_dev);
0163 kfree(wrap);
0164 return err;
0165 }
0166 }
0167
0168 pci_set_drvdata(pdev, wrap);
0169 return err;
0170 }
0171
0172 static void cdns3_pci_remove(struct pci_dev *pdev)
0173 {
0174 struct cdns3_wrap *wrap;
0175 struct pci_dev *func;
0176
0177 func = cdns3_get_second_fun(pdev);
0178
0179 wrap = (struct cdns3_wrap *)pci_get_drvdata(pdev);
0180 if (wrap->devfn == pdev->devfn)
0181 platform_device_unregister(wrap->plat_dev);
0182
0183 if (!pci_is_enabled(func))
0184 kfree(wrap);
0185 }
0186
0187 static const struct pci_device_id cdns3_pci_ids[] = {
0188 { PCI_DEVICE(CDNS_VENDOR_ID, CDNS_DEVICE_ID), },
0189 { 0, }
0190 };
0191
0192 static struct pci_driver cdns3_pci_driver = {
0193 .name = PCI_DRIVER_NAME,
0194 .id_table = cdns3_pci_ids,
0195 .probe = cdns3_pci_probe,
0196 .remove = cdns3_pci_remove,
0197 };
0198
0199 module_pci_driver(cdns3_pci_driver);
0200 MODULE_DEVICE_TABLE(pci, cdns3_pci_ids);
0201
0202 MODULE_AUTHOR("Pawel Laszczak <pawell@cadence.com>");
0203 MODULE_LICENSE("GPL v2");
0204 MODULE_DESCRIPTION("Cadence USBSS PCI wrapper");