1 // SPDX-License-Identifier: GPL-2.0
3 * This file contains functions to handle discovery of PMC metrics located
4 * in the PMC SSRAM PCI device.
6 * Copyright (c) 2023, Intel Corporation.
11 #include <linux/cleanup.h>
12 #include <linux/intel_vsec.h>
13 #include <linux/pci.h>
14 #include <linux/io-64-nonatomic-lo-hi.h>
17 #include "../pmt/telemetry.h"
19 #define SSRAM_HDR_SIZE 0x100
20 #define SSRAM_PWRM_OFFSET 0x14
21 #define SSRAM_DVSEC_OFFSET 0x1C
22 #define SSRAM_DVSEC_SIZE 0x10
23 #define SSRAM_PCH_OFFSET 0x60
24 #define SSRAM_IOE_OFFSET 0x68
25 #define SSRAM_DEVID_OFFSET 0x70
28 #define LPM_HEADER_OFFSET 1
29 #define LPM_REG_COUNT 28
30 #define LPM_MODE_OFFSET 1
32 DEFINE_FREE(pmc_core_iounmap
, void __iomem
*, if (_T
) iounmap(_T
))
34 static u32
pmc_core_find_guid(struct pmc_info
*list
, const struct pmc_reg_map
*map
)
36 for (; list
->map
; ++list
)
43 static int pmc_core_get_lpm_req(struct pmc_dev
*pmcdev
, struct pmc
*pmc
)
45 struct telem_endpoint
*ep
;
46 const u8
*lpm_indices
;
47 int num_maps
, mode_offset
= 0;
52 lpm_indices
= pmc
->map
->lpm_reg_index
;
53 num_maps
= pmc
->map
->lpm_num_maps
;
54 lpm_size
= LPM_MAX_NUM_MODES
* num_maps
;
56 guid
= pmc_core_find_guid(pmcdev
->regmap_list
, pmc
->map
);
60 ep
= pmt_telem_find_and_register_endpoint(pmcdev
->ssram_pcidev
, guid
, 0);
62 dev_dbg(&pmcdev
->pdev
->dev
, "couldn't get telem endpoint %ld",
67 pmc
->lpm_req_regs
= devm_kzalloc(&pmcdev
->pdev
->dev
,
68 lpm_size
* sizeof(u32
),
70 if (!pmc
->lpm_req_regs
) {
76 * PMC Low Power Mode (LPM) table
78 * In telemetry space, the LPM table contains a 4 byte header followed
79 * by 8 consecutive mode blocks (one for each LPM mode). Each block
80 * has a 4 byte header followed by a set of registers that describe the
81 * IP state requirements for the given mode. The IP mapping is platform
82 * specific but the same for each block, making for easy analysis.
83 * Platforms only use a subset of the space to track the requirements
84 * for their IPs. Callers provide the requirement registers they use as
85 * a list of indices. Each requirement register is associated with an
86 * IP map that's maintained by the caller.
89 * +----+----------------------------+----------------------------+
90 * | 0 | REVISION | ENABLED MODES |
91 * +----+--------------+-------------+-------------+--------------+
93 * Low Power Mode 0 Block
94 * +----+--------------+-------------+-------------+--------------+
95 * | 1 | SUB ID | SIZE | MAJOR | MINOR |
96 * +----+--------------+-------------+-------------+--------------+
97 * | 2 | LPM0 Requirements 0 |
98 * +----+---------------------------------------------------------+
100 * +----+---------------------------------------------------------+
101 * | 29 | LPM0 Requirements 27 |
102 * +----+---------------------------------------------------------+
106 * Low Power Mode 7 Block
107 * +----+--------------+-------------+-------------+--------------+
108 * | | SUB ID | SIZE | MAJOR | MINOR |
109 * +----+--------------+-------------+-------------+--------------+
110 * | 60 | LPM7 Requirements 0 |
111 * +----+---------------------------------------------------------+
113 * +----+---------------------------------------------------------+
114 * | 87 | LPM7 Requirements 27 |
115 * +----+---------------------------------------------------------+
118 mode_offset
= LPM_HEADER_OFFSET
+ LPM_MODE_OFFSET
;
119 pmc_for_each_mode(mode
, pmcdev
) {
120 u32
*req_offset
= pmc
->lpm_req_regs
+ (mode
* num_maps
);
123 for (m
= 0; m
< num_maps
; m
++) {
124 u8 sample_id
= lpm_indices
[m
] + mode_offset
;
126 ret
= pmt_telem_read32(ep
, sample_id
, req_offset
, 1);
128 dev_err(&pmcdev
->pdev
->dev
,
129 "couldn't read Low Power Mode requirements: %d\n", ret
);
130 devm_kfree(&pmcdev
->pdev
->dev
, pmc
->lpm_req_regs
);
135 mode_offset
+= LPM_REG_COUNT
+ LPM_MODE_OFFSET
;
139 pmt_telem_unregister_endpoint(ep
);
144 int pmc_core_ssram_get_lpm_reqs(struct pmc_dev
*pmcdev
)
148 if (!pmcdev
->ssram_pcidev
)
151 for (i
= 0; i
< ARRAY_SIZE(pmcdev
->pmcs
); ++i
) {
152 if (!pmcdev
->pmcs
[i
])
155 ret
= pmc_core_get_lpm_req(pmcdev
, pmcdev
->pmcs
[i
]);
164 pmc_add_pmt(struct pmc_dev
*pmcdev
, u64 ssram_base
, void __iomem
*ssram
)
166 struct pci_dev
*pcidev
= pmcdev
->ssram_pcidev
;
167 struct intel_vsec_platform_info info
= {};
168 struct intel_vsec_header
*headers
[2] = {};
169 struct intel_vsec_header header
;
174 ssram
= ioremap(ssram_base
, SSRAM_HDR_SIZE
);
178 dvsec_offset
= readl(ssram
+ SSRAM_DVSEC_OFFSET
);
181 dvsec
= ioremap(ssram_base
+ dvsec_offset
, SSRAM_DVSEC_SIZE
);
185 hdr
= readl(dvsec
+ PCI_DVSEC_HEADER1
);
186 header
.id
= readw(dvsec
+ PCI_DVSEC_HEADER2
);
187 header
.rev
= PCI_DVSEC_HEADER1_REV(hdr
);
188 header
.length
= PCI_DVSEC_HEADER1_LEN(hdr
);
189 header
.num_entries
= readb(dvsec
+ INTEL_DVSEC_ENTRIES
);
190 header
.entry_size
= readb(dvsec
+ INTEL_DVSEC_SIZE
);
192 table
= readl(dvsec
+ INTEL_DVSEC_TABLE
);
193 header
.tbir
= INTEL_DVSEC_TABLE_BAR(table
);
194 header
.offset
= INTEL_DVSEC_TABLE_OFFSET(table
);
197 headers
[0] = &header
;
198 info
.caps
= VSEC_CAP_TELEMETRY
;
199 info
.headers
= headers
;
200 info
.base_addr
= ssram_base
;
201 info
.parent
= &pmcdev
->pdev
->dev
;
203 intel_vsec_register(pcidev
, &info
);
206 static const struct pmc_reg_map
*pmc_core_find_regmap(struct pmc_info
*list
, u16 devid
)
208 for (; list
->map
; ++list
)
209 if (devid
== list
->devid
)
215 static inline u64
get_base(void __iomem
*addr
, u32 offset
)
217 return lo_hi_readq(addr
+ offset
) & GENMASK_ULL(63, 3);
221 pmc_core_pmc_add(struct pmc_dev
*pmcdev
, u64 pwrm_base
,
222 const struct pmc_reg_map
*reg_map
, int pmc_index
)
224 struct pmc
*pmc
= pmcdev
->pmcs
[pmc_index
];
229 /* Memory for primary PMC has been allocated in core.c */
231 pmc
= devm_kzalloc(&pmcdev
->pdev
->dev
, sizeof(*pmc
), GFP_KERNEL
);
237 pmc
->base_addr
= pwrm_base
;
238 pmc
->regbase
= ioremap(pmc
->base_addr
, pmc
->map
->regmap_length
);
241 devm_kfree(&pmcdev
->pdev
->dev
, pmc
);
245 pmcdev
->pmcs
[pmc_index
] = pmc
;
251 pmc_core_ssram_get_pmc(struct pmc_dev
*pmcdev
, int pmc_idx
, u32 offset
)
253 struct pci_dev
*ssram_pcidev
= pmcdev
->ssram_pcidev
;
254 void __iomem
__free(pmc_core_iounmap
) *tmp_ssram
= NULL
;
255 void __iomem
__free(pmc_core_iounmap
) *ssram
= NULL
;
256 const struct pmc_reg_map
*map
;
257 u64 ssram_base
, pwrm_base
;
260 if (!pmcdev
->regmap_list
)
263 ssram_base
= ssram_pcidev
->resource
[0].start
;
264 tmp_ssram
= ioremap(ssram_base
, SSRAM_HDR_SIZE
);
268 if (pmc_idx
!= PMC_IDX_MAIN
) {
270 * The secondary PMC BARS (which are behind hidden PCI devices)
271 * are read from fixed offsets in MMIO of the primary PMC BAR.
273 ssram_base
= get_base(tmp_ssram
, offset
);
274 ssram
= ioremap(ssram_base
, SSRAM_HDR_SIZE
);
279 ssram
= no_free_ptr(tmp_ssram
);
282 pwrm_base
= get_base(ssram
, SSRAM_PWRM_OFFSET
);
283 devid
= readw(ssram
+ SSRAM_DEVID_OFFSET
);
285 /* Find and register and PMC telemetry entries */
286 pmc_add_pmt(pmcdev
, ssram_base
, ssram
);
288 map
= pmc_core_find_regmap(pmcdev
->regmap_list
, devid
);
292 return pmc_core_pmc_add(pmcdev
, pwrm_base
, map
, pmc_idx
);
295 int pmc_core_ssram_init(struct pmc_dev
*pmcdev
, int func
)
297 struct pci_dev
*pcidev
;
300 pcidev
= pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(20, func
));
304 ret
= pcim_enable_device(pcidev
);
308 pmcdev
->ssram_pcidev
= pcidev
;
310 ret
= pmc_core_ssram_get_pmc(pmcdev
, PMC_IDX_MAIN
, 0);
314 pmc_core_ssram_get_pmc(pmcdev
, PMC_IDX_IOE
, SSRAM_IOE_OFFSET
);
315 pmc_core_ssram_get_pmc(pmcdev
, PMC_IDX_PCH
, SSRAM_PCH_OFFSET
);
320 pmcdev
->ssram_pcidev
= NULL
;
321 pci_disable_device(pcidev
);
327 MODULE_IMPORT_NS("INTEL_VSEC");
328 MODULE_IMPORT_NS("INTEL_PMT_TELEMETRY");