Skip to content

Commit 1b8c7b8

Browse files
debox1jwrdegoede
authored andcommitted
platform/x86:intel/pmc: Discover PMC devices
On platforms with multiple PMCs, additional PMC devices are discovered in the SSRAM device associated with the primary PMC. Add support for discovering PMC devices from SSRAM. Use PMC devid to assign the corresponding register map. Signed-off-by: Xi Pardee <xi.pardee@intel.com> Signed-off-by: David E. Box <david.e.box@linux.intel.com> Signed-off-by: Rajvi Jingar <rajvi.jingar@linux.intel.com> Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Link: https://lore.kernel.org/r/20230613225347.2720665-6-rajvi.jingar@linux.intel.com Signed-off-by: Hans de Goede <hdegoede@redhat.com>
1 parent 2bcef45 commit 1b8c7b8

File tree

5 files changed

+180
-14
lines changed

5 files changed

+180
-14
lines changed

drivers/platform/x86/intel/pmc/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
# Intel x86 Platform-Specific Drivers
44
#
55

6-
intel_pmc_core-y := core.o spt.o cnp.o icl.o tgl.o \
7-
adl.o mtl.o
6+
intel_pmc_core-y := core.o core_ssram.o spt.o cnp.o \
7+
icl.o tgl.o adl.o mtl.o
88
obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core.o
99
intel_pmc_core_pltdrv-y := pltdrv.o
1010
obj-$(CONFIG_INTEL_PMC_CORE) += intel_pmc_core_pltdrv.o

drivers/platform/x86/intel/pmc/core.c

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,6 +1183,26 @@ static void pmc_core_do_dmi_quirks(struct pmc *pmc)
11831183
pmc_core_xtal_ignore(pmc);
11841184
}
11851185

1186+
static void pmc_core_clean_structure(struct platform_device *pdev)
1187+
{
1188+
struct pmc_dev *pmcdev = platform_get_drvdata(pdev);
1189+
int i;
1190+
1191+
for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) {
1192+
struct pmc *pmc = pmcdev->pmcs[i];
1193+
1194+
if (pmc)
1195+
iounmap(pmc->regbase);
1196+
}
1197+
1198+
if (pmcdev->ssram_pcidev) {
1199+
pci_dev_put(pmcdev->ssram_pcidev);
1200+
pci_disable_device(pmcdev->ssram_pcidev);
1201+
}
1202+
platform_set_drvdata(pdev, NULL);
1203+
mutex_destroy(&pmcdev->lock);
1204+
}
1205+
11861206
static int pmc_core_probe(struct platform_device *pdev)
11871207
{
11881208
static bool device_initialized;
@@ -1225,7 +1245,7 @@ static int pmc_core_probe(struct platform_device *pdev)
12251245
mutex_init(&pmcdev->lock);
12261246
ret = core_init(pmcdev);
12271247
if (ret) {
1228-
mutex_destroy(&pmcdev->lock);
1248+
pmc_core_clean_structure(pdev);
12291249
return ret;
12301250
}
12311251

@@ -1246,18 +1266,8 @@ static int pmc_core_probe(struct platform_device *pdev)
12461266
static void pmc_core_remove(struct platform_device *pdev)
12471267
{
12481268
struct pmc_dev *pmcdev = platform_get_drvdata(pdev);
1249-
int i;
1250-
1251-
for (i = 0; i < ARRAY_SIZE(pmcdev->pmcs); ++i) {
1252-
struct pmc *pmc = pmcdev->pmcs[i];
1253-
1254-
if (pmc)
1255-
iounmap(pmc->regbase);
1256-
}
1257-
12581269
pmc_core_dbgfs_unregister(pmcdev);
1259-
platform_set_drvdata(pdev, NULL);
1260-
mutex_destroy(&pmcdev->lock);
1270+
pmc_core_clean_structure(pdev);
12611271
}
12621272

12631273
static bool warn_on_s0ix_failures;

drivers/platform/x86/intel/pmc/core.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,17 @@ struct pmc_reg_map {
319319
const u32 etr3_offset;
320320
};
321321

322+
/**
323+
* struct pmc_info - Structure to keep pmc info
324+
* @devid: device id of the pmc device
325+
* @map: pointer to a pmc_reg_map struct that contains platform
326+
* specific attributes
327+
*/
328+
struct pmc_info {
329+
u16 devid;
330+
const struct pmc_reg_map *map;
331+
};
332+
322333
/**
323334
* struct pmc - pmc private info structure
324335
* @base_addr: contains pmc base address
@@ -340,6 +351,7 @@ struct pmc {
340351
* struct pmc_dev - pmc device structure
341352
* @devs: pointer to an array of pmc pointers
342353
* @pdev: pointer to platform_device struct
354+
* @ssram_pcidev: pointer to pci device struct for the PMC SSRAM
343355
* @dbgfs_dir: path to debugfs interface
344356
* @pmc_xram_read_bit: flag to indicate whether PMC XRAM shadow registers
345357
* used to read MPHY PG and PLL status are available
@@ -356,6 +368,7 @@ struct pmc_dev {
356368
struct pmc *pmcs[MAX_NUM_PMC];
357369
struct dentry *dbgfs_dir;
358370
struct platform_device *pdev;
371+
struct pci_dev *ssram_pcidev;
359372
int pmc_xram_read_bit;
360373
struct mutex lock; /* generic mutex lock for PMC Core */
361374

@@ -368,6 +381,7 @@ struct pmc_dev {
368381
bool has_die_c6;
369382
u32 die_c6_offset;
370383
struct telem_endpoint *punit_ep;
384+
struct pmc_info *regmap_list;
371385
};
372386

373387
enum pmc_index {
@@ -450,6 +464,8 @@ extern int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value);
450464
int pmc_core_resume_common(struct pmc_dev *pmcdev);
451465
int get_primary_reg_base(struct pmc *pmc);
452466

467+
extern void pmc_core_ssram_init(struct pmc_dev *pmcdev);
468+
453469
int spt_core_init(struct pmc_dev *pmcdev);
454470
int cnp_core_init(struct pmc_dev *pmcdev);
455471
int icl_core_init(struct pmc_dev *pmcdev);
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* This file contains functions to handle discovery of PMC metrics located
4+
* in the PMC SSRAM PCI device.
5+
*
6+
* Copyright (c) 2023, Intel Corporation.
7+
* All Rights Reserved.
8+
*
9+
*/
10+
11+
#include <linux/pci.h>
12+
#include <linux/io-64-nonatomic-lo-hi.h>
13+
14+
#include "core.h"
15+
16+
#define SSRAM_HDR_SIZE 0x100
17+
#define SSRAM_PWRM_OFFSET 0x14
18+
#define SSRAM_DVSEC_OFFSET 0x1C
19+
#define SSRAM_DVSEC_SIZE 0x10
20+
#define SSRAM_PCH_OFFSET 0x60
21+
#define SSRAM_IOE_OFFSET 0x68
22+
#define SSRAM_DEVID_OFFSET 0x70
23+
24+
static const struct pmc_reg_map *pmc_core_find_regmap(struct pmc_info *list, u16 devid)
25+
{
26+
for (; list->map; ++list)
27+
if (devid == list->devid)
28+
return list->map;
29+
30+
return NULL;
31+
}
32+
33+
static inline u64 get_base(void __iomem *addr, u32 offset)
34+
{
35+
return lo_hi_readq(addr + offset) & GENMASK_ULL(63, 3);
36+
}
37+
38+
static void
39+
pmc_core_pmc_add(struct pmc_dev *pmcdev, u64 pwrm_base,
40+
const struct pmc_reg_map *reg_map, int pmc_index)
41+
{
42+
struct pmc *pmc = pmcdev->pmcs[pmc_index];
43+
44+
if (!pwrm_base)
45+
return;
46+
47+
/* Memory for primary PMC has been allocated in core.c */
48+
if (!pmc) {
49+
pmc = devm_kzalloc(&pmcdev->pdev->dev, sizeof(*pmc), GFP_KERNEL);
50+
if (!pmc)
51+
return;
52+
}
53+
54+
pmc->map = reg_map;
55+
pmc->base_addr = pwrm_base;
56+
pmc->regbase = ioremap(pmc->base_addr, pmc->map->regmap_length);
57+
58+
if (!pmc->regbase) {
59+
devm_kfree(&pmcdev->pdev->dev, pmc);
60+
return;
61+
}
62+
63+
pmcdev->pmcs[pmc_index] = pmc;
64+
}
65+
66+
static void
67+
pmc_core_ssram_get_pmc(struct pmc_dev *pmcdev, void __iomem *ssram, u32 offset,
68+
int pmc_idx)
69+
{
70+
u64 pwrm_base;
71+
u16 devid;
72+
73+
if (pmc_idx != PMC_IDX_SOC) {
74+
u64 ssram_base = get_base(ssram, offset);
75+
76+
if (!ssram_base)
77+
return;
78+
79+
ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
80+
if (!ssram)
81+
return;
82+
}
83+
84+
pwrm_base = get_base(ssram, SSRAM_PWRM_OFFSET);
85+
devid = readw(ssram + SSRAM_DEVID_OFFSET);
86+
87+
if (pmcdev->regmap_list) {
88+
const struct pmc_reg_map *map;
89+
90+
map = pmc_core_find_regmap(pmcdev->regmap_list, devid);
91+
if (map)
92+
pmc_core_pmc_add(pmcdev, pwrm_base, map, pmc_idx);
93+
}
94+
95+
if (pmc_idx != PMC_IDX_SOC)
96+
iounmap(ssram);
97+
}
98+
99+
void pmc_core_ssram_init(struct pmc_dev *pmcdev)
100+
{
101+
void __iomem *ssram;
102+
struct pci_dev *pcidev;
103+
u64 ssram_base;
104+
int ret;
105+
106+
pcidev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(20, 2));
107+
if (!pcidev)
108+
goto out;
109+
110+
ret = pcim_enable_device(pcidev);
111+
if (ret)
112+
goto release_dev;
113+
114+
ssram_base = pcidev->resource[0].start;
115+
ssram = ioremap(ssram_base, SSRAM_HDR_SIZE);
116+
if (!ssram)
117+
goto disable_dev;
118+
119+
pmcdev->ssram_pcidev = pcidev;
120+
121+
pmc_core_ssram_get_pmc(pmcdev, ssram, 0, PMC_IDX_SOC);
122+
pmc_core_ssram_get_pmc(pmcdev, ssram, SSRAM_IOE_OFFSET, PMC_IDX_IOE);
123+
pmc_core_ssram_get_pmc(pmcdev, ssram, SSRAM_PCH_OFFSET, PMC_IDX_PCH);
124+
125+
iounmap(ssram);
126+
out:
127+
return;
128+
129+
disable_dev:
130+
pci_disable_device(pcidev);
131+
release_dev:
132+
pci_dev_put(pcidev);
133+
}

drivers/platform/x86/intel/pmc/mtl.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,10 @@ const struct pmc_reg_map mtl_socm_reg_map = {
467467
.lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET,
468468
};
469469

470+
static struct pmc_info mtl_pmc_info_list[] = {
471+
{}
472+
};
473+
470474
#define MTL_GNA_PCI_DEV 0x7e4c
471475
#define MTL_IPU_PCI_DEV 0x7d19
472476
#define MTL_VPU_PCI_DEV 0x7d1d
@@ -517,6 +521,9 @@ int mtl_core_init(struct pmc_dev *pmcdev)
517521

518522
pmcdev->resume = mtl_resume;
519523

524+
pmcdev->regmap_list = mtl_pmc_info_list;
525+
pmc_core_ssram_init(pmcdev);
526+
520527
ret = get_primary_reg_base(pmc);
521528
if (ret)
522529
return ret;

0 commit comments

Comments
 (0)