[PATCH 3/7] platform/x86:intel/pmc: Add support to get PMC information from SSRAM

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



PWRMBASE address and devid for PMCs are available through API of
Intel PMC SSRAM Telemetry driver. Add support to discover and achieve
the information for each available PMC. Use PMC devid to find and
assign the corresponding register map.

Signed-off-by: Xi Pardee <xi.pardee@xxxxxxxxxxxxxxx>
---
 drivers/platform/x86/intel/pmc/Kconfig |  1 +
 drivers/platform/x86/intel/pmc/core.c  | 64 ++++++++++++++++++++++++++
 drivers/platform/x86/intel/pmc/core.h  |  1 +
 3 files changed, 66 insertions(+)

diff --git a/drivers/platform/x86/intel/pmc/Kconfig b/drivers/platform/x86/intel/pmc/Kconfig
index fe33348cd7e2..56c6d3650bf7 100644
--- a/drivers/platform/x86/intel/pmc/Kconfig
+++ b/drivers/platform/x86/intel/pmc/Kconfig
@@ -7,6 +7,7 @@ config INTEL_PMC_CORE
 	tristate "Intel PMC Core driver"
 	depends on PCI
 	depends on ACPI
+	depends on INTEL_PMC_SSRAM_TELEMETRY || !INTEL_PMC_SSRAM_TELEMETRY
 	depends on INTEL_PMT_TELEMETRY
 	help
 	  The Intel Platform Controller Hub for Intel Core SoCs provides access
diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c
index 5ecf55176734..634b4d939ed2 100644
--- a/drivers/platform/x86/intel/pmc/core.c
+++ b/drivers/platform/x86/intel/pmc/core.c
@@ -28,6 +28,7 @@
 #include <asm/tsc.h>
 
 #include "core.h"
+#include "ssram_telemetry.h"
 #include "../pmt/telemetry.h"
 
 /* Maximum number of modes supported by platfoms that has low power mode capability */
@@ -1146,6 +1147,69 @@ int get_primary_reg_base(struct pmc *pmc)
 	return 0;
 }
 
+static const struct pmc_reg_map *pmc_core_find_regmap(struct pmc_info *list, u16 devid)
+{
+	for (; list->map; ++list)
+		if (devid == list->devid)
+			return list->map;
+
+	return NULL;
+}
+
+static int pmc_core_ssram_pmc_add(struct pmc_dev *pmcdev, int pmc_idx)
+{
+	const struct pmc_reg_map *map;
+	struct pmc_ssram_telemetry pmc_ssram_telemetry;
+	struct pmc *pmc;
+	int ret;
+
+	ret = pmc_ssram_telemetry_get_pmc_info(pmc_idx, &pmc_ssram_telemetry);
+	if (ret)
+		return ret;
+
+	map = pmc_core_find_regmap(pmcdev->regmap_list, pmc_ssram_telemetry.devid);
+	if (!map)
+		return -ENODEV;
+
+	pmc = pmcdev->pmcs[pmc_idx];
+	/* Memory for primary PMC has been allocated in core.c */
+	if (!pmc) {
+		pmc = devm_kzalloc(&pmcdev->pdev->dev, sizeof(*pmc), GFP_KERNEL);
+		if (!pmc)
+			return -ENOMEM;
+	}
+
+	pmc->map = map;
+	pmc->base_addr = pmc_ssram_telemetry.base_addr;
+	pmc->regbase = ioremap(pmc->base_addr, pmc->map->regmap_length);
+
+	if (!pmc->regbase) {
+		devm_kfree(&pmcdev->pdev->dev, pmc);
+		return -ENOMEM;
+	}
+
+	pmcdev->pmcs[pmc_idx] = pmc;
+
+	return 0;
+}
+
+int pmc_core_ssram_get_reg_base(struct pmc_dev *pmcdev)
+{
+	int ret;
+
+	if (!pmcdev->regmap_list)
+		return -ENOENT;
+
+	ret = pmc_core_ssram_pmc_add(pmcdev, PMC_IDX_MAIN);
+	if (ret)
+		return ret;
+
+	pmc_core_ssram_pmc_add(pmcdev, PMC_IDX_IOE);
+	pmc_core_ssram_pmc_add(pmcdev, PMC_IDX_PCH);
+
+	return 0;
+}
+
 void pmc_core_punit_pmt_init(struct pmc_dev *pmcdev, u32 guid)
 {
 	struct telem_endpoint *ep;
diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h
index 1e5726745394..890caf558307 100644
--- a/drivers/platform/x86/intel/pmc/core.h
+++ b/drivers/platform/x86/intel/pmc/core.h
@@ -591,6 +591,7 @@ int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value, int ignore);
 
 int pmc_core_resume_common(struct pmc_dev *pmcdev);
 int get_primary_reg_base(struct pmc *pmc);
+extern int pmc_core_ssram_get_reg_base(struct pmc_dev *pmcdev);
 extern void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev);
 extern void pmc_core_punit_pmt_init(struct pmc_dev *pmcdev, u32 guid);
 extern void pmc_core_set_device_d3(unsigned int device);
-- 
2.43.0





[Index of Archives]     [Linux Kernel Development]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux