123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2022-10-24 GuEe-GUI first version
- */
- #include <drivers/pci.h>
- #include <drivers/core/power_domain.h>
- #define DBG_TAG "pci.pme"
- #define DBG_LVL DBG_INFO
- #include <rtdbg.h>
- /*
- * Power Management Capability Register:
- *
- * 31 27 26 25 24 22 21 20 19 18 16 15 8 7 0
- * +---------+---+---+--------+---+---+---+------+-----------+----------------+
- * | | | | | | | | | | Capabilitiy ID |
- * +---------+---+---+--------+---+---+---+------+-----------+----------------+
- * ^ ^ ^ ^ ^ ^ ^ ^ ^
- * | | | | | | | | |
- * | | | | | | | | +---- Next Capabilitiy Pointer
- * | | | | | | | +------------- Version
- * | | | | | | +------------------- PME Clock
- * | | | | | +----------------------- Immediate Readiness on Return to D0
- * | | | | +--------------------------- Device Specifiic Initializtion
- * | | | +--------------------------------- Aux Current
- * | | +---------------------------------------- D1 Support
- * | +-------------------------------------------- D2 Support
- * +--------------------------------------------------- PME Support
- */
- void rt_pci_pme_init(struct rt_pci_device *pdev)
- {
- rt_uint16_t pmc;
- if (!pdev || !(pdev->pme_cap = rt_pci_find_capability(pdev, PCIY_PMG)))
- {
- return;
- }
- rt_pci_read_config_u16(pdev, pdev->pme_cap + PCIR_POWER_CAP, &pmc);
- if ((pmc & PCIM_PCAP_SPEC) > 3)
- {
- LOG_E("%s: Unsupported PME CAP regs spec %u",
- rt_dm_dev_get_name(&pdev->parent), pmc & PCIM_PCAP_SPEC);
- return;
- }
- pmc &= PCIM_PCAP_PMEMASK;
- if (pmc)
- {
- pdev->pme_support = RT_FIELD_GET(PCIM_PCAP_PMEMASK, pmc);
- rt_pci_pme_active(pdev, RT_FALSE);
- }
- }
- rt_err_t rt_pci_enable_wake(struct rt_pci_device *pdev,
- enum rt_pci_power state, rt_bool_t enable)
- {
- if (!pdev || state >= RT_PCI_PME_MAX)
- {
- return -RT_EINVAL;
- }
- if (enable)
- {
- if (rt_pci_pme_capable(pdev, state) ||
- rt_pci_pme_capable(pdev, RT_PCI_D3COLD))
- {
- rt_pci_pme_active(pdev, RT_EOK);
- }
- }
- else
- {
- rt_pci_pme_active(pdev, RT_FALSE);
- }
- return RT_EOK;
- }
- static void pci_pme_active(struct rt_pci_device *pdev, rt_bool_t enable)
- {
- rt_uint16_t pmcsr;
- if (!pdev->pme_support)
- {
- return;
- }
- rt_pci_read_config_u16(pdev, pdev->pme_cap + PCIR_POWER_STATUS, &pmcsr);
- /* Clear PME_Status by writing 1 to it and enable PME# */
- pmcsr |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE;
- if (!enable)
- {
- pmcsr &= ~PCIM_PSTAT_PMEENABLE;
- }
- rt_pci_write_config_u16(pdev, pdev->pme_cap + PCIR_POWER_STATUS, pmcsr);
- pdev->pm_enabled = enable;
- }
- void rt_pci_pme_active(struct rt_pci_device *pdev, rt_bool_t enable)
- {
- if (!pdev)
- {
- return;
- }
- pci_pme_active(pdev, enable);
- rt_dm_power_domain_attach(&pdev->parent, enable);
- }
|