Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * dwc3-pci.c - PCI Specific glue layer
0004  *
0005  * Copyright (C) 2010-2011 Texas Instruments Incorporated - https://www.ti.com
0006  *
0007  * Authors: Felipe Balbi <balbi@ti.com>,
0008  *      Sebastian Andrzej Siewior <bigeasy@linutronix.de>
0009  */
0010 
0011 #include <linux/kernel.h>
0012 #include <linux/module.h>
0013 #include <linux/slab.h>
0014 #include <linux/pci.h>
0015 #include <linux/workqueue.h>
0016 #include <linux/pm_runtime.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/gpio/consumer.h>
0019 #include <linux/gpio/machine.h>
0020 #include <linux/acpi.h>
0021 #include <linux/delay.h>
0022 
0023 #define PCI_DEVICE_ID_INTEL_BYT         0x0f37
0024 #define PCI_DEVICE_ID_INTEL_MRFLD       0x119e
0025 #define PCI_DEVICE_ID_INTEL_BSW         0x22b7
0026 #define PCI_DEVICE_ID_INTEL_SPTLP       0x9d30
0027 #define PCI_DEVICE_ID_INTEL_SPTH        0xa130
0028 #define PCI_DEVICE_ID_INTEL_BXT         0x0aaa
0029 #define PCI_DEVICE_ID_INTEL_BXT_M       0x1aaa
0030 #define PCI_DEVICE_ID_INTEL_APL         0x5aaa
0031 #define PCI_DEVICE_ID_INTEL_KBP         0xa2b0
0032 #define PCI_DEVICE_ID_INTEL_CMLLP       0x02ee
0033 #define PCI_DEVICE_ID_INTEL_CMLH        0x06ee
0034 #define PCI_DEVICE_ID_INTEL_GLK         0x31aa
0035 #define PCI_DEVICE_ID_INTEL_CNPLP       0x9dee
0036 #define PCI_DEVICE_ID_INTEL_CNPH        0xa36e
0037 #define PCI_DEVICE_ID_INTEL_CNPV        0xa3b0
0038 #define PCI_DEVICE_ID_INTEL_ICLLP       0x34ee
0039 #define PCI_DEVICE_ID_INTEL_EHL         0x4b7e
0040 #define PCI_DEVICE_ID_INTEL_TGPLP       0xa0ee
0041 #define PCI_DEVICE_ID_INTEL_TGPH        0x43ee
0042 #define PCI_DEVICE_ID_INTEL_JSP         0x4dee
0043 #define PCI_DEVICE_ID_INTEL_ADL         0x465e
0044 #define PCI_DEVICE_ID_INTEL_ADLP        0x51ee
0045 #define PCI_DEVICE_ID_INTEL_ADLM        0x54ee
0046 #define PCI_DEVICE_ID_INTEL_ADLS        0x7ae1
0047 #define PCI_DEVICE_ID_INTEL_RPL         0x460e
0048 #define PCI_DEVICE_ID_INTEL_RPLS        0x7a61
0049 #define PCI_DEVICE_ID_INTEL_MTLP        0x7ec1
0050 #define PCI_DEVICE_ID_INTEL_MTL         0x7e7e
0051 #define PCI_DEVICE_ID_INTEL_TGL         0x9a15
0052 #define PCI_DEVICE_ID_AMD_MR            0x163a
0053 
0054 #define PCI_INTEL_BXT_DSM_GUID      "732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511"
0055 #define PCI_INTEL_BXT_FUNC_PMU_PWR  4
0056 #define PCI_INTEL_BXT_STATE_D0      0
0057 #define PCI_INTEL_BXT_STATE_D3      3
0058 
0059 #define GP_RWBAR            1
0060 #define GP_RWREG1           0xa0
0061 #define GP_RWREG1_ULPI_REFCLK_DISABLE   (1 << 17)
0062 
0063 /**
0064  * struct dwc3_pci - Driver private structure
0065  * @dwc3: child dwc3 platform_device
0066  * @pci: our link to PCI bus
0067  * @guid: _DSM GUID
0068  * @has_dsm_for_pm: true for devices which need to run _DSM on runtime PM
0069  * @wakeup_work: work for asynchronous resume
0070  */
0071 struct dwc3_pci {
0072     struct platform_device *dwc3;
0073     struct pci_dev *pci;
0074 
0075     guid_t guid;
0076 
0077     unsigned int has_dsm_for_pm:1;
0078     struct work_struct wakeup_work;
0079 };
0080 
0081 static const struct acpi_gpio_params reset_gpios = { 0, 0, false };
0082 static const struct acpi_gpio_params cs_gpios = { 1, 0, false };
0083 
0084 static const struct acpi_gpio_mapping acpi_dwc3_byt_gpios[] = {
0085     { "reset-gpios", &reset_gpios, 1 },
0086     { "cs-gpios", &cs_gpios, 1 },
0087     { },
0088 };
0089 
0090 static struct gpiod_lookup_table platform_bytcr_gpios = {
0091     .dev_id     = "0000:00:16.0",
0092     .table      = {
0093         GPIO_LOOKUP("INT33FC:00", 54, "cs", GPIO_ACTIVE_HIGH),
0094         GPIO_LOOKUP("INT33FC:02", 14, "reset", GPIO_ACTIVE_HIGH),
0095         {}
0096     },
0097 };
0098 
0099 static int dwc3_byt_enable_ulpi_refclock(struct pci_dev *pci)
0100 {
0101     void __iomem    *reg;
0102     u32     value;
0103 
0104     reg = pcim_iomap(pci, GP_RWBAR, 0);
0105     if (!reg)
0106         return -ENOMEM;
0107 
0108     value = readl(reg + GP_RWREG1);
0109     if (!(value & GP_RWREG1_ULPI_REFCLK_DISABLE))
0110         goto unmap; /* ULPI refclk already enabled */
0111 
0112     value &= ~GP_RWREG1_ULPI_REFCLK_DISABLE;
0113     writel(value, reg + GP_RWREG1);
0114     /* This comes from the Intel Android x86 tree w/o any explanation */
0115     msleep(100);
0116 unmap:
0117     pcim_iounmap(pci, reg);
0118     return 0;
0119 }
0120 
0121 static const struct property_entry dwc3_pci_intel_properties[] = {
0122     PROPERTY_ENTRY_STRING("dr_mode", "peripheral"),
0123     PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
0124     {}
0125 };
0126 
0127 static const struct property_entry dwc3_pci_intel_phy_charger_detect_properties[] = {
0128     PROPERTY_ENTRY_STRING("dr_mode", "peripheral"),
0129     PROPERTY_ENTRY_BOOL("snps,dis_u2_susphy_quirk"),
0130     PROPERTY_ENTRY_BOOL("linux,phy_charger_detect"),
0131     PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
0132     {}
0133 };
0134 
0135 static const struct property_entry dwc3_pci_intel_byt_properties[] = {
0136     PROPERTY_ENTRY_STRING("dr_mode", "peripheral"),
0137     PROPERTY_ENTRY_BOOL("snps,dis_u2_susphy_quirk"),
0138     PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
0139     {}
0140 };
0141 
0142 static const struct property_entry dwc3_pci_mrfld_properties[] = {
0143     PROPERTY_ENTRY_STRING("dr_mode", "otg"),
0144     PROPERTY_ENTRY_STRING("linux,extcon-name", "mrfld_bcove_pwrsrc"),
0145     PROPERTY_ENTRY_BOOL("snps,dis_u3_susphy_quirk"),
0146     PROPERTY_ENTRY_BOOL("snps,dis_u2_susphy_quirk"),
0147     PROPERTY_ENTRY_BOOL("snps,usb2-gadget-lpm-disable"),
0148     PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
0149     {}
0150 };
0151 
0152 static const struct property_entry dwc3_pci_amd_properties[] = {
0153     PROPERTY_ENTRY_BOOL("snps,has-lpm-erratum"),
0154     PROPERTY_ENTRY_U8("snps,lpm-nyet-threshold", 0xf),
0155     PROPERTY_ENTRY_BOOL("snps,u2exit_lfps_quirk"),
0156     PROPERTY_ENTRY_BOOL("snps,u2ss_inp3_quirk"),
0157     PROPERTY_ENTRY_BOOL("snps,req_p1p2p3_quirk"),
0158     PROPERTY_ENTRY_BOOL("snps,del_p1p2p3_quirk"),
0159     PROPERTY_ENTRY_BOOL("snps,del_phy_power_chg_quirk"),
0160     PROPERTY_ENTRY_BOOL("snps,lfps_filter_quirk"),
0161     PROPERTY_ENTRY_BOOL("snps,rx_detect_poll_quirk"),
0162     PROPERTY_ENTRY_BOOL("snps,tx_de_emphasis_quirk"),
0163     PROPERTY_ENTRY_U8("snps,tx_de_emphasis", 1),
0164     /* FIXME these quirks should be removed when AMD NL tapes out */
0165     PROPERTY_ENTRY_BOOL("snps,disable_scramble_quirk"),
0166     PROPERTY_ENTRY_BOOL("snps,dis_u3_susphy_quirk"),
0167     PROPERTY_ENTRY_BOOL("snps,dis_u2_susphy_quirk"),
0168     PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
0169     {}
0170 };
0171 
0172 static const struct property_entry dwc3_pci_mr_properties[] = {
0173     PROPERTY_ENTRY_STRING("dr_mode", "otg"),
0174     PROPERTY_ENTRY_BOOL("usb-role-switch"),
0175     PROPERTY_ENTRY_STRING("role-switch-default-mode", "host"),
0176     PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
0177     {}
0178 };
0179 
0180 static const struct software_node dwc3_pci_intel_swnode = {
0181     .properties = dwc3_pci_intel_properties,
0182 };
0183 
0184 static const struct software_node dwc3_pci_intel_phy_charger_detect_swnode = {
0185     .properties = dwc3_pci_intel_phy_charger_detect_properties,
0186 };
0187 
0188 static const struct software_node dwc3_pci_intel_byt_swnode = {
0189     .properties = dwc3_pci_intel_byt_properties,
0190 };
0191 
0192 static const struct software_node dwc3_pci_intel_mrfld_swnode = {
0193     .properties = dwc3_pci_mrfld_properties,
0194 };
0195 
0196 static const struct software_node dwc3_pci_amd_swnode = {
0197     .properties = dwc3_pci_amd_properties,
0198 };
0199 
0200 static const struct software_node dwc3_pci_amd_mr_swnode = {
0201     .properties = dwc3_pci_mr_properties,
0202 };
0203 
0204 static int dwc3_pci_quirks(struct dwc3_pci *dwc,
0205                const struct software_node *swnode)
0206 {
0207     struct pci_dev          *pdev = dwc->pci;
0208 
0209     if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
0210         if (pdev->device == PCI_DEVICE_ID_INTEL_BXT ||
0211             pdev->device == PCI_DEVICE_ID_INTEL_BXT_M ||
0212             pdev->device == PCI_DEVICE_ID_INTEL_EHL) {
0213             guid_parse(PCI_INTEL_BXT_DSM_GUID, &dwc->guid);
0214             dwc->has_dsm_for_pm = true;
0215         }
0216 
0217         if (pdev->device == PCI_DEVICE_ID_INTEL_BYT) {
0218             struct gpio_desc *gpio;
0219             int ret;
0220 
0221             /* On BYT the FW does not always enable the refclock */
0222             ret = dwc3_byt_enable_ulpi_refclock(pdev);
0223             if (ret)
0224                 return ret;
0225 
0226             ret = devm_acpi_dev_add_driver_gpios(&pdev->dev,
0227                     acpi_dwc3_byt_gpios);
0228             if (ret)
0229                 dev_dbg(&pdev->dev, "failed to add mapping table\n");
0230 
0231             /*
0232              * A lot of BYT devices lack ACPI resource entries for
0233              * the GPIOs, add a fallback mapping to the reference
0234              * design GPIOs which all boards seem to use.
0235              */
0236             gpiod_add_lookup_table(&platform_bytcr_gpios);
0237 
0238             /*
0239              * These GPIOs will turn on the USB2 PHY. Note that we have to
0240              * put the gpio descriptors again here because the phy driver
0241              * might want to grab them, too.
0242              */
0243             gpio = gpiod_get_optional(&pdev->dev, "cs", GPIOD_OUT_LOW);
0244             if (IS_ERR(gpio))
0245                 return PTR_ERR(gpio);
0246 
0247             gpiod_set_value_cansleep(gpio, 1);
0248             gpiod_put(gpio);
0249 
0250             gpio = gpiod_get_optional(&pdev->dev, "reset", GPIOD_OUT_LOW);
0251             if (IS_ERR(gpio))
0252                 return PTR_ERR(gpio);
0253 
0254             if (gpio) {
0255                 gpiod_set_value_cansleep(gpio, 1);
0256                 gpiod_put(gpio);
0257                 usleep_range(10000, 11000);
0258             }
0259 
0260             /*
0261              * Make the pdev name predictable (only 1 DWC3 on BYT)
0262              * and patch the phy dev-name into the lookup table so
0263              * that the phy-driver can get the GPIOs.
0264              */
0265             dwc->dwc3->id = PLATFORM_DEVID_NONE;
0266             platform_bytcr_gpios.dev_id = "dwc3.ulpi";
0267 
0268             /*
0269              * Some Android tablets with a Crystal Cove PMIC
0270              * (INT33FD), rely on the TUSB1211 phy for charger
0271              * detection. These can be identified by them _not_
0272              * using the standard ACPI battery and ac drivers.
0273              */
0274             if (acpi_dev_present("INT33FD", "1", 2) &&
0275                 acpi_quirk_skip_acpi_ac_and_battery()) {
0276                 dev_info(&pdev->dev, "Using TUSB1211 phy for charger detection\n");
0277                 swnode = &dwc3_pci_intel_phy_charger_detect_swnode;
0278             }
0279         }
0280     }
0281 
0282     return device_add_software_node(&dwc->dwc3->dev, swnode);
0283 }
0284 
0285 #ifdef CONFIG_PM
0286 static void dwc3_pci_resume_work(struct work_struct *work)
0287 {
0288     struct dwc3_pci *dwc = container_of(work, struct dwc3_pci, wakeup_work);
0289     struct platform_device *dwc3 = dwc->dwc3;
0290     int ret;
0291 
0292     ret = pm_runtime_get_sync(&dwc3->dev);
0293     if (ret < 0) {
0294         pm_runtime_put_sync_autosuspend(&dwc3->dev);
0295         return;
0296     }
0297 
0298     pm_runtime_mark_last_busy(&dwc3->dev);
0299     pm_runtime_put_sync_autosuspend(&dwc3->dev);
0300 }
0301 #endif
0302 
0303 static int dwc3_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
0304 {
0305     struct dwc3_pci     *dwc;
0306     struct resource     res[2];
0307     int         ret;
0308     struct device       *dev = &pci->dev;
0309 
0310     ret = pcim_enable_device(pci);
0311     if (ret) {
0312         dev_err(dev, "failed to enable pci device\n");
0313         return -ENODEV;
0314     }
0315 
0316     pci_set_master(pci);
0317 
0318     dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL);
0319     if (!dwc)
0320         return -ENOMEM;
0321 
0322     dwc->dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
0323     if (!dwc->dwc3)
0324         return -ENOMEM;
0325 
0326     memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res));
0327 
0328     res[0].start    = pci_resource_start(pci, 0);
0329     res[0].end  = pci_resource_end(pci, 0);
0330     res[0].name = "dwc_usb3";
0331     res[0].flags    = IORESOURCE_MEM;
0332 
0333     res[1].start    = pci->irq;
0334     res[1].name = "dwc_usb3";
0335     res[1].flags    = IORESOURCE_IRQ;
0336 
0337     ret = platform_device_add_resources(dwc->dwc3, res, ARRAY_SIZE(res));
0338     if (ret) {
0339         dev_err(dev, "couldn't add resources to dwc3 device\n");
0340         goto err;
0341     }
0342 
0343     dwc->pci = pci;
0344     dwc->dwc3->dev.parent = dev;
0345     ACPI_COMPANION_SET(&dwc->dwc3->dev, ACPI_COMPANION(dev));
0346 
0347     ret = dwc3_pci_quirks(dwc, (void *)id->driver_data);
0348     if (ret)
0349         goto err;
0350 
0351     ret = platform_device_add(dwc->dwc3);
0352     if (ret) {
0353         dev_err(dev, "failed to register dwc3 device\n");
0354         goto err;
0355     }
0356 
0357     device_init_wakeup(dev, true);
0358     pci_set_drvdata(pci, dwc);
0359     pm_runtime_put(dev);
0360 #ifdef CONFIG_PM
0361     INIT_WORK(&dwc->wakeup_work, dwc3_pci_resume_work);
0362 #endif
0363 
0364     return 0;
0365 err:
0366     device_remove_software_node(&dwc->dwc3->dev);
0367     platform_device_put(dwc->dwc3);
0368     return ret;
0369 }
0370 
0371 static void dwc3_pci_remove(struct pci_dev *pci)
0372 {
0373     struct dwc3_pci     *dwc = pci_get_drvdata(pci);
0374     struct pci_dev      *pdev = dwc->pci;
0375 
0376     if (pdev->device == PCI_DEVICE_ID_INTEL_BYT)
0377         gpiod_remove_lookup_table(&platform_bytcr_gpios);
0378 #ifdef CONFIG_PM
0379     cancel_work_sync(&dwc->wakeup_work);
0380 #endif
0381     device_init_wakeup(&pci->dev, false);
0382     pm_runtime_get(&pci->dev);
0383     device_remove_software_node(&dwc->dwc3->dev);
0384     platform_device_unregister(dwc->dwc3);
0385 }
0386 
0387 static const struct pci_device_id dwc3_pci_id_table[] = {
0388     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BSW),
0389       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0390 
0391     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BYT),
0392       (kernel_ulong_t) &dwc3_pci_intel_byt_swnode, },
0393 
0394     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MRFLD),
0395       (kernel_ulong_t) &dwc3_pci_intel_mrfld_swnode, },
0396 
0397     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CMLLP),
0398       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0399 
0400     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CMLH),
0401       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0402 
0403     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SPTLP),
0404       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0405 
0406     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SPTH),
0407       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0408 
0409     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BXT),
0410       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0411 
0412     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BXT_M),
0413       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0414 
0415     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_APL),
0416       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0417 
0418     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_KBP),
0419       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0420 
0421     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_GLK),
0422       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0423 
0424     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CNPLP),
0425       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0426 
0427     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CNPH),
0428       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0429 
0430     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CNPV),
0431       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0432 
0433     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICLLP),
0434       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0435 
0436     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_EHL),
0437       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0438 
0439     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGPLP),
0440       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0441 
0442     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGPH),
0443       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0444 
0445     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_JSP),
0446       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0447 
0448     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ADL),
0449       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0450 
0451     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ADLP),
0452       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0453 
0454     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ADLM),
0455       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0456 
0457     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ADLS),
0458       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0459 
0460     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_RPL),
0461       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0462 
0463     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_RPLS),
0464       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0465 
0466     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTLP),
0467       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0468 
0469     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTL),
0470       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0471 
0472     { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGL),
0473       (kernel_ulong_t) &dwc3_pci_intel_swnode, },
0474 
0475     { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_NL_USB),
0476       (kernel_ulong_t) &dwc3_pci_amd_swnode, },
0477 
0478     { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_MR),
0479       (kernel_ulong_t)&dwc3_pci_amd_mr_swnode, },
0480 
0481     {  }    /* Terminating Entry */
0482 };
0483 MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
0484 
0485 #if defined(CONFIG_PM) || defined(CONFIG_PM_SLEEP)
0486 static int dwc3_pci_dsm(struct dwc3_pci *dwc, int param)
0487 {
0488     union acpi_object *obj;
0489     union acpi_object tmp;
0490     union acpi_object argv4 = ACPI_INIT_DSM_ARGV4(1, &tmp);
0491 
0492     if (!dwc->has_dsm_for_pm)
0493         return 0;
0494 
0495     tmp.type = ACPI_TYPE_INTEGER;
0496     tmp.integer.value = param;
0497 
0498     obj = acpi_evaluate_dsm(ACPI_HANDLE(&dwc->pci->dev), &dwc->guid,
0499             1, PCI_INTEL_BXT_FUNC_PMU_PWR, &argv4);
0500     if (!obj) {
0501         dev_err(&dwc->pci->dev, "failed to evaluate _DSM\n");
0502         return -EIO;
0503     }
0504 
0505     ACPI_FREE(obj);
0506 
0507     return 0;
0508 }
0509 #endif /* CONFIG_PM || CONFIG_PM_SLEEP */
0510 
0511 #ifdef CONFIG_PM
0512 static int dwc3_pci_runtime_suspend(struct device *dev)
0513 {
0514     struct dwc3_pci     *dwc = dev_get_drvdata(dev);
0515 
0516     if (device_can_wakeup(dev))
0517         return dwc3_pci_dsm(dwc, PCI_INTEL_BXT_STATE_D3);
0518 
0519     return -EBUSY;
0520 }
0521 
0522 static int dwc3_pci_runtime_resume(struct device *dev)
0523 {
0524     struct dwc3_pci     *dwc = dev_get_drvdata(dev);
0525     int         ret;
0526 
0527     ret = dwc3_pci_dsm(dwc, PCI_INTEL_BXT_STATE_D0);
0528     if (ret)
0529         return ret;
0530 
0531     queue_work(pm_wq, &dwc->wakeup_work);
0532 
0533     return 0;
0534 }
0535 #endif /* CONFIG_PM */
0536 
0537 #ifdef CONFIG_PM_SLEEP
0538 static int dwc3_pci_suspend(struct device *dev)
0539 {
0540     struct dwc3_pci     *dwc = dev_get_drvdata(dev);
0541 
0542     return dwc3_pci_dsm(dwc, PCI_INTEL_BXT_STATE_D3);
0543 }
0544 
0545 static int dwc3_pci_resume(struct device *dev)
0546 {
0547     struct dwc3_pci     *dwc = dev_get_drvdata(dev);
0548 
0549     return dwc3_pci_dsm(dwc, PCI_INTEL_BXT_STATE_D0);
0550 }
0551 #endif /* CONFIG_PM_SLEEP */
0552 
0553 static const struct dev_pm_ops dwc3_pci_dev_pm_ops = {
0554     SET_SYSTEM_SLEEP_PM_OPS(dwc3_pci_suspend, dwc3_pci_resume)
0555     SET_RUNTIME_PM_OPS(dwc3_pci_runtime_suspend, dwc3_pci_runtime_resume,
0556         NULL)
0557 };
0558 
0559 static struct pci_driver dwc3_pci_driver = {
0560     .name       = "dwc3-pci",
0561     .id_table   = dwc3_pci_id_table,
0562     .probe      = dwc3_pci_probe,
0563     .remove     = dwc3_pci_remove,
0564     .driver     = {
0565         .pm = &dwc3_pci_dev_pm_ops,
0566     }
0567 };
0568 
0569 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
0570 MODULE_LICENSE("GPL v2");
0571 MODULE_DESCRIPTION("DesignWare USB3 PCI Glue Layer");
0572 
0573 module_pci_driver(dwc3_pci_driver);