staticvoid amd_pmc_get_ip_info(struct amd_pmc_dev *dev)
{ switch (dev->cpu_id) { case AMD_CPU_ID_PCO: case AMD_CPU_ID_RN: case AMD_CPU_ID_YC: case AMD_CPU_ID_CB:
dev->num_ips = 12;
dev->ips_ptr = soc15_ip_blk;
dev->smu_msg = 0x538; break; case AMD_CPU_ID_PS:
dev->num_ips = 21;
dev->ips_ptr = soc15_ip_blk;
dev->smu_msg = 0x538; break; case PCI_DEVICE_ID_AMD_1AH_M20H_ROOT: case PCI_DEVICE_ID_AMD_1AH_M60H_ROOT: if (boot_cpu_data.x86_model == 0x70) {
dev->num_ips = ARRAY_SIZE(soc15_ip_blk_v2);
dev->ips_ptr = soc15_ip_blk_v2;
} else {
dev->num_ips = ARRAY_SIZE(soc15_ip_blk);
dev->ips_ptr = soc15_ip_blk;
}
dev->smu_msg = 0x938; break;
}
}
staticint amd_pmc_setup_smu_logging(struct amd_pmc_dev *dev)
{ if (dev->cpu_id == AMD_CPU_ID_PCO) {
dev_warn_once(dev->dev, "SMU debugging info not supported on this platform\n"); return -EINVAL;
}
/* Get Active devices list from SMU */ if (!dev->active_ips)
amd_pmc_send_cmd(dev, 0, &dev->active_ips, SMU_MSG_GET_SUP_CONSTRAINTS, true);
/* Get dram address */ if (!dev->smu_virt_addr) {
u32 phys_addr_low, phys_addr_hi;
u64 smu_phys_addr;
switch (pdev->cpu_id) { case AMD_CPU_ID_CZN: /* we haven't yet read SMU version */ if (!pdev->major) {
rc = amd_pmc_get_smu_version(pdev); if (rc) return rc;
} if (pdev->major > 56 || (pdev->major >= 55 && pdev->minor >= 37))
val = amd_pmc_reg_read(pdev, AMD_PMC_SCRATCH_REG_CZN); else return -EINVAL; break; case AMD_CPU_ID_YC: case AMD_CPU_ID_CB: case AMD_CPU_ID_PS:
val = amd_pmc_reg_read(pdev, AMD_PMC_SCRATCH_REG_YC); break; case PCI_DEVICE_ID_AMD_1AH_M20H_ROOT: case PCI_DEVICE_ID_AMD_1AH_M60H_ROOT:
val = amd_pmc_reg_read(pdev, AMD_PMC_SCRATCH_REG_1AH); break; default: return -EINVAL;
}
if (dev)
pm_pr_dbg("SMU idlemask s0i3: 0x%x\n", val);
if (s)
seq_printf(s, "SMU idlemask : 0x%x\n", val);
/* Wait until we get a valid response */
rc = readx_poll_timeout(ioread32, dev->regbase + response,
val, val != 0, PMC_MSG_DELAY_MIN_US,
PMC_MSG_DELAY_MIN_US * RESPONSE_REGISTER_LOOP_MAX); if (rc) {
dev_err(dev->dev, "failed to talk to SMU\n"); return rc;
}
/* Write zero to response register */
amd_pmc_reg_write(dev, response, 0);
/* Write argument into response register */
amd_pmc_reg_write(dev, argument, arg);
/* Write message ID to message ID register */
amd_pmc_reg_write(dev, message, msg);
/* Wait until we get a valid response */
rc = readx_poll_timeout(ioread32, dev->regbase + response,
val, val != 0, PMC_MSG_DELAY_MIN_US,
PMC_MSG_DELAY_MIN_US * RESPONSE_REGISTER_LOOP_MAX); if (rc) {
dev_err(dev->dev, "SMU response timed out\n"); return rc;
}
switch (val) { case AMD_PMC_RESULT_OK: if (ret) { /* PMFW may take longer time to return back the data */
usleep_range(DELAY_MIN_US, 10 * DELAY_MAX_US);
*data = amd_pmc_reg_read(dev, argument);
} break; case AMD_PMC_RESULT_CMD_REJECT_BUSY:
dev_err(dev->dev, "SMU not ready. err: 0x%x\n", val);
rc = -EBUSY; break; case AMD_PMC_RESULT_CMD_UNKNOWN:
dev_err(dev->dev, "SMU cmd unknown. err: 0x%x\n", val);
rc = -EINVAL; break; case AMD_PMC_RESULT_CMD_REJECT_PREREQ: case AMD_PMC_RESULT_FAILED: default:
dev_err(dev->dev, "SMU cmd failed. err: 0x%x\n", val);
rc = -EIO; break;
}
amd_pmc_dump_registers(dev); return rc;
}
staticint amd_pmc_get_os_hint(struct amd_pmc_dev *dev)
{ switch (dev->cpu_id) { case AMD_CPU_ID_PCO: return MSG_OS_HINT_PCO; case AMD_CPU_ID_RN: case AMD_CPU_ID_YC: case AMD_CPU_ID_CB: case AMD_CPU_ID_PS: case PCI_DEVICE_ID_AMD_1AH_M20H_ROOT: case PCI_DEVICE_ID_AMD_1AH_M60H_ROOT: return MSG_OS_HINT_RN;
} return -EINVAL;
}
rtc_device = rtc_class_open("rtc0"); if (!rtc_device) return 0;
rc = rtc_read_alarm(rtc_device, &alarm); if (rc) return rc; if (!alarm.enabled) {
dev_dbg(pdev->dev, "alarm not enabled\n"); return 0;
}
rc = rtc_read_time(rtc_device, &tm); if (rc) return rc;
then = rtc_tm_to_time64(&alarm.time);
now = rtc_tm_to_time64(&tm);
duration = then-now;
/* in the past */ if (then < now) return 0;
/* will be stored in upper 16 bits of s0i3 hint argument, * so timer wakeup from s0i3 is limited to ~18 hours or less
*/ if (duration <= 4 || duration > U16_MAX) return -EINVAL;
/* * Must be called only from the same set of dev_pm_ops handlers * as i8042_pm_suspend() is called: currently just from .suspend.
*/ if (pdev->disable_8042_wakeup && !disable_workarounds) {
rc = amd_pmc_wa_irq1(pdev); if (rc) {
dev_err(pdev->dev, "failed to adjust keyboard wakeup: %d\n", rc); return rc;
}
}
err = devm_mutex_init(dev->dev, &dev->lock); if (err) goto err_pci_dev_put;
/* Get num of IP blocks within the SoC */
amd_pmc_get_ip_info(dev);
platform_set_drvdata(pdev, dev); if (IS_ENABLED(CONFIG_SUSPEND)) {
err = acpi_register_lps0_dev(&amd_pmc_s2idle_dev_ops); if (err)
dev_warn(dev->dev, "failed to register LPS0 sleep handler, expect increased power consumption\n"); if (!disable_workarounds)
amd_pmc_quirks_init(dev);
}
amd_pmc_dbgfs_register(dev);
err = amd_stb_s2d_init(dev); if (err) goto err_pci_dev_put;
if (IS_ENABLED(CONFIG_AMD_MP2_STB))
amd_mp2_stb_init(dev);
pm_report_max_hw_sleep(U64_MAX); return 0;
if (IS_ENABLED(CONFIG_SUSPEND))
acpi_unregister_lps0_dev(&amd_pmc_s2idle_dev_ops);
amd_pmc_dbgfs_unregister(dev);
pci_dev_put(dev->rdev); if (IS_ENABLED(CONFIG_AMD_MP2_STB))
amd_mp2_stb_deinit(dev);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.