@@ -492,7 +492,7 @@ int pmc_core_resume_common(struct pmc_dev *pmcdev);
int get_primary_reg_base(struct pmc *pmc);
extern void pmc_core_get_low_power_modes(struct pmc_dev *pmcdev);
-extern void pmc_core_ssram_init(struct pmc_dev *pmcdev);
+extern int pmc_core_ssram_init(struct pmc_dev *pmcdev);
int spt_core_init(struct pmc_dev *pmcdev);
int cnp_core_init(struct pmc_dev *pmcdev);
@@ -35,20 +35,20 @@ static inline u64 get_base(void __iomem *addr, u32 offset)
return lo_hi_readq(addr + offset) & GENMASK_ULL(63, 3);
}
-static void
+static int
pmc_core_pmc_add(struct pmc_dev *pmcdev, u64 pwrm_base,
const struct pmc_reg_map *reg_map, int pmc_index)
{
struct pmc *pmc = pmcdev->pmcs[pmc_index];
if (!pwrm_base)
- return;
+ return -ENODEV;
/* 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;
+ return -ENOMEM;
}
pmc->map = reg_map;
@@ -57,77 +57,128 @@ pmc_core_pmc_add(struct pmc_dev *pmcdev, u64 pwrm_base,
if (!pmc->regbase) {
devm_kfree(&pmcdev->pdev->dev, pmc);
- return;
+ return -ENOMEM;
}
pmcdev->pmcs[pmc_index] = pmc;
+
+ return 0;
}
-static void
-pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, void __iomem *ssram, u32 offset,
- int pmc_idx)
+static int
+pmc_core_get_secondary_pmc(struct pmc_dev *pmcdev, int pmc_idx, u32 offset)
{
- u64 pwrm_base;
+ struct pci_dev *ssram_pcidev = pmcdev->ssram_pcidev;
+ const struct pmc_reg_map *map;
+ void __iomem *main_ssram, *secondary_ssram;
+ u64 ssram_base, pwrm_base;
u16 devid;
+ int ret;
+
+ if (!pmcdev->regmap_list)
+ return -ENOENT;
- if (pmc_idx != PMC_IDX_SOC) {
- u64 ssram_base = get_base(ssram, offset);
+ /*
+ * The secondary PMC BARS (which are behind hidden PCI devices) are read
+ * from fixed offsets in MMIO of the primary PMC BAR.
+ */
+ ssram_base = ssram_pcidev->resource[0].start;
+ main_ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
+ if (!main_ssram)
+ return -ENOMEM;
+
+ ssram_base = get_base(main_ssram, offset);
+ secondary_ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
+ if (!secondary_ssram) {
+ ret = -ENOMEM;
+ goto secondary_remap_fail;
+ }
- if (!ssram_base)
- return;
+ pwrm_base = get_base(secondary_ssram, SSRAM_PWRM_OFFSET);
+ devid = readw(secondary_ssram + SSRAM_DEVID_OFFSET);
- ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
- if (!ssram)
- return;
+ map = pmc_core_find_regmap(pmcdev->regmap_list, devid);
+ if (!map) {
+ ret = -ENODEV;
+ goto find_regmap_fail;
}
+ ret = pmc_core_pmc_add(pmcdev, pwrm_base, map, pmc_idx);
+
+find_regmap_fail:
+ iounmap(secondary_ssram);
+secondary_remap_fail:
+ iounmap(main_ssram);
+
+ return ret;
+
+}
+
+static int
+pmc_core_get_primary_pmc(struct pmc_dev *pmcdev)
+{
+ struct pci_dev *ssram_pcidev = pmcdev->ssram_pcidev;
+ const struct pmc_reg_map *map;
+ void __iomem *ssram;
+ u64 ssram_base, pwrm_base;
+ u16 devid;
+ int ret;
+
+ if (!pmcdev->regmap_list)
+ return -ENOENT;
+
+ /* The primary PMC (SOC die) BAR is BAR 0 in config space. */
+ ssram_base = ssram_pcidev->resource[0].start;
+ ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
+ if (!ssram)
+ return -ENOMEM;
+
pwrm_base = get_base(ssram, SSRAM_PWRM_OFFSET);
devid = readw(ssram + SSRAM_DEVID_OFFSET);
- if (pmcdev->regmap_list) {
- const struct pmc_reg_map *map;
-
- map = pmc_core_find_regmap(pmcdev->regmap_list, devid);
- if (map)
- pmc_core_pmc_add(pmcdev, pwrm_base, map, pmc_idx);
+ map = pmc_core_find_regmap(pmcdev->regmap_list, devid);
+ if (!map) {
+ ret = -ENODEV;
+ goto find_regmap_fail;
}
- if (pmc_idx != PMC_IDX_SOC)
- iounmap(ssram);
+ ret = pmc_core_pmc_add(pmcdev, pwrm_base, map, PMC_IDX_MAIN);
+
+find_regmap_fail:
+ iounmap(ssram);
+
+ return ret;
}
-void pmc_core_ssram_init(struct pmc_dev *pmcdev)
+int pmc_core_ssram_init(struct pmc_dev *pmcdev)
{
- void __iomem *ssram;
struct pci_dev *pcidev;
- u64 ssram_base;
int ret;
pcidev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(20, 2));
if (!pcidev)
- goto out;
+ return -ENODEV;
ret = pcim_enable_device(pcidev);
if (ret)
goto release_dev;
- ssram_base = pcidev->resource[0].start;
- ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
- if (!ssram)
- goto disable_dev;
-
pmcdev->ssram_pcidev = pcidev;
- pmc_core_ssram_get_pmc(pmcdev, ssram, 0, PMC_IDX_SOC);
- pmc_core_ssram_get_pmc(pmcdev, ssram, SSRAM_IOE_OFFSET, PMC_IDX_IOE);
- pmc_core_ssram_get_pmc(pmcdev, ssram, SSRAM_PCH_OFFSET, PMC_IDX_PCH);
+ ret = pmc_core_get_primary_pmc(pmcdev);
+ if (ret)
+ goto disable_dev;
- iounmap(ssram);
-out:
- return;
+ pmc_core_get_secondary_pmc(pmcdev, PMC_IDX_IOE, SSRAM_IOE_OFFSET);
+ pmc_core_get_secondary_pmc(pmcdev, PMC_IDX_PCH, SSRAM_PCH_OFFSET);
+
+ return 0;
disable_dev:
+ pmcdev->ssram_pcidev = NULL;
pci_disable_device(pcidev);
release_dev:
pci_dev_put(pcidev);
+
+ return ret;
}
@@ -990,12 +990,14 @@ int mtl_core_init(struct pmc_dev *pmcdev)
mtl_d3_fixup();
pmcdev->resume = mtl_resume;
-
pmcdev->regmap_list = mtl_pmc_info_list;
- pmc_core_ssram_init(pmcdev);
- /* If regbase not assigned, set map and discover using legacy method */
- if (!pmc->regbase) {
+ /*
+ * If ssram init fails use legacy method to at least get the
+ * primary PMC
+ */
+ ret = pmc_core_ssram_init(pmcdev);
+ if (ret) {
pmc->map = &mtl_socm_reg_map;
ret = get_primary_reg_base(pmc);
if (ret)