1ff956826SZhang Rui /* SPDX-License-Identifier: GPL-2.0 */
2ff956826SZhang Rui /*
3ff956826SZhang Rui * Data types and headers for RAPL support
4ff956826SZhang Rui *
5ff956826SZhang Rui * Copyright (C) 2019 Intel Corporation.
6ff956826SZhang Rui *
7ff956826SZhang Rui * Author: Zhang Rui <[email protected]>
8ff956826SZhang Rui */
9ff956826SZhang Rui
10ff956826SZhang Rui #ifndef __INTEL_RAPL_H__
11ff956826SZhang Rui #define __INTEL_RAPL_H__
12ff956826SZhang Rui
13ff956826SZhang Rui #include <linux/types.h>
14ff956826SZhang Rui #include <linux/powercap.h>
158da04e05SStephen Rothwell #include <linux/cpuhotplug.h>
16ff956826SZhang Rui
17b4288ce7SZhang Rui enum rapl_if_type {
18b4288ce7SZhang Rui RAPL_IF_MSR, /* RAPL I/F using MSR registers */
19b4288ce7SZhang Rui RAPL_IF_MMIO, /* RAPL I/F using MMIO registers */
20e12dee18SZhang Rui RAPL_IF_TPMI, /* RAPL I/F using TPMI registers */
21b4288ce7SZhang Rui };
22b4288ce7SZhang Rui
23ff956826SZhang Rui enum rapl_domain_type {
24ff956826SZhang Rui RAPL_DOMAIN_PACKAGE, /* entire package/socket */
25ff956826SZhang Rui RAPL_DOMAIN_PP0, /* core power plane */
26ff956826SZhang Rui RAPL_DOMAIN_PP1, /* graphics uncore */
27ff956826SZhang Rui RAPL_DOMAIN_DRAM, /* DRAM control_type */
28ff956826SZhang Rui RAPL_DOMAIN_PLATFORM, /* PSys control_type */
29ff956826SZhang Rui RAPL_DOMAIN_MAX,
30ff956826SZhang Rui };
31ff956826SZhang Rui
32ff956826SZhang Rui enum rapl_domain_reg_id {
33ff956826SZhang Rui RAPL_DOMAIN_REG_LIMIT,
34ff956826SZhang Rui RAPL_DOMAIN_REG_STATUS,
35ff956826SZhang Rui RAPL_DOMAIN_REG_PERF,
36ff956826SZhang Rui RAPL_DOMAIN_REG_POLICY,
37ff956826SZhang Rui RAPL_DOMAIN_REG_INFO,
388365a898SSumeet Pawnikar RAPL_DOMAIN_REG_PL4,
39cb532e72SZhang Rui RAPL_DOMAIN_REG_UNIT,
40e12dee18SZhang Rui RAPL_DOMAIN_REG_PL2,
41ff956826SZhang Rui RAPL_DOMAIN_REG_MAX,
42ff956826SZhang Rui };
43ff956826SZhang Rui
4435eb1f50SWan Jiabing struct rapl_domain;
45ff956826SZhang Rui
46ff956826SZhang Rui enum rapl_primitives {
47ff956826SZhang Rui POWER_LIMIT1,
48ff956826SZhang Rui POWER_LIMIT2,
498365a898SSumeet Pawnikar POWER_LIMIT4,
50045610c3SZhang Rui ENERGY_COUNTER,
51ff956826SZhang Rui FW_LOCK,
52f442bd27SZhang Rui FW_HIGH_LOCK,
53e12dee18SZhang Rui PL1_LOCK,
54e12dee18SZhang Rui PL2_LOCK,
55e12dee18SZhang Rui PL4_LOCK,
56ff956826SZhang Rui
57ff956826SZhang Rui PL1_ENABLE, /* power limit 1, aka long term */
58ff956826SZhang Rui PL1_CLAMP, /* allow frequency to go below OS request */
59ff956826SZhang Rui PL2_ENABLE, /* power limit 2, aka short term, instantaneous */
60ff956826SZhang Rui PL2_CLAMP,
618365a898SSumeet Pawnikar PL4_ENABLE, /* power limit 4, aka max peak power */
62ff956826SZhang Rui
63ff956826SZhang Rui TIME_WINDOW1, /* long term */
64ff956826SZhang Rui TIME_WINDOW2, /* short term */
65ff956826SZhang Rui THERMAL_SPEC_POWER,
66ff956826SZhang Rui MAX_POWER,
67ff956826SZhang Rui
68ff956826SZhang Rui MIN_POWER,
69ff956826SZhang Rui MAX_TIME_WINDOW,
70ff956826SZhang Rui THROTTLED_TIME,
71ff956826SZhang Rui PRIORITY_LEVEL,
72ff956826SZhang Rui
73931da6a0SZhang Rui PSYS_POWER_LIMIT1,
74931da6a0SZhang Rui PSYS_POWER_LIMIT2,
75931da6a0SZhang Rui PSYS_PL1_ENABLE,
76931da6a0SZhang Rui PSYS_PL2_ENABLE,
77931da6a0SZhang Rui PSYS_TIME_WINDOW1,
78931da6a0SZhang Rui PSYS_TIME_WINDOW2,
79ff956826SZhang Rui /* below are not raw primitive data */
80ff956826SZhang Rui AVERAGE_POWER,
81ff956826SZhang Rui NR_RAPL_PRIMITIVES,
82ff956826SZhang Rui };
83ff956826SZhang Rui
84ff956826SZhang Rui struct rapl_domain_data {
85ff956826SZhang Rui u64 primitives[NR_RAPL_PRIMITIVES];
86ff956826SZhang Rui unsigned long timestamp;
87ff956826SZhang Rui };
88ff956826SZhang Rui
89045610c3SZhang Rui #define NR_POWER_LIMITS (POWER_LIMIT4 + 1)
90045610c3SZhang Rui
91ff956826SZhang Rui struct rapl_power_limit {
92ff956826SZhang Rui struct powercap_zone_constraint *constraint;
93ff956826SZhang Rui struct rapl_domain *domain;
94ff956826SZhang Rui const char *name;
95f442bd27SZhang Rui bool locked;
96ff956826SZhang Rui u64 last_power_limit;
97ff956826SZhang Rui };
98ff956826SZhang Rui
99ff956826SZhang Rui struct rapl_package;
100ff956826SZhang Rui
101f1e8d756SZhang Rui #define RAPL_DOMAIN_NAME_LENGTH 16
102f1e8d756SZhang Rui
10316e95a62SZhang Rui union rapl_reg {
10416e95a62SZhang Rui void __iomem *mmio;
10516e95a62SZhang Rui u32 msr;
10616e95a62SZhang Rui u64 val;
10716e95a62SZhang Rui };
10816e95a62SZhang Rui
109ff956826SZhang Rui struct rapl_domain {
110f1e8d756SZhang Rui char name[RAPL_DOMAIN_NAME_LENGTH];
111ff956826SZhang Rui enum rapl_domain_type id;
11216e95a62SZhang Rui union rapl_reg regs[RAPL_DOMAIN_REG_MAX];
113ff956826SZhang Rui struct powercap_zone power_zone;
114ff956826SZhang Rui struct rapl_domain_data rdd;
115ff956826SZhang Rui struct rapl_power_limit rpl[NR_POWER_LIMITS];
116ff956826SZhang Rui u64 attr_map; /* track capabilities */
117ff956826SZhang Rui unsigned int state;
118cb532e72SZhang Rui unsigned int power_unit;
119cb532e72SZhang Rui unsigned int energy_unit;
120cb532e72SZhang Rui unsigned int time_unit;
121ff956826SZhang Rui struct rapl_package *rp;
122ff956826SZhang Rui };
123ff956826SZhang Rui
124beea8df8SZhang Rui struct reg_action {
12516e95a62SZhang Rui union rapl_reg reg;
126beea8df8SZhang Rui u64 mask;
127beea8df8SZhang Rui u64 value;
128beea8df8SZhang Rui int err;
129beea8df8SZhang Rui };
130beea8df8SZhang Rui
1317ebf8effSZhang Rui /**
1327ebf8effSZhang Rui * struct rapl_if_priv: private data for different RAPL interfaces
1337ebf8effSZhang Rui * @control_type: Each RAPL interface must have its own powercap
1347ebf8effSZhang Rui * control type.
1357ebf8effSZhang Rui * @platform_rapl_domain: Optional. Some RAPL interface may have platform
1367ebf8effSZhang Rui * level RAPL control.
1377ebf8effSZhang Rui * @pcap_rapl_online: CPU hotplug state for each RAPL interface.
1387fde2712SZhang Rui * @reg_unit: Register for getting energy/power/time unit.
1397fde2712SZhang Rui * @regs: Register sets for different RAPL Domains.
1400c2ddeddSZhang Rui * @limits: Number of power limits supported by each domain.
141beea8df8SZhang Rui * @read_raw: Callback for reading RAPL interface specific
142beea8df8SZhang Rui * registers.
143beea8df8SZhang Rui * @write_raw: Callback for writing RAPL interface specific
144beea8df8SZhang Rui * registers.
145e8e28c2aSZhang Rui * @defaults: internal pointer to interface default settings
14698ff639aSZhang Rui * @rpi: internal pointer to interface primitive info
1477ebf8effSZhang Rui */
1487ebf8effSZhang Rui struct rapl_if_priv {
149b4288ce7SZhang Rui enum rapl_if_type type;
1507ebf8effSZhang Rui struct powercap_control_type *control_type;
1517ebf8effSZhang Rui enum cpuhp_state pcap_rapl_online;
15216e95a62SZhang Rui union rapl_reg reg_unit;
15316e95a62SZhang Rui union rapl_reg regs[RAPL_DOMAIN_MAX][RAPL_DOMAIN_REG_MAX];
1540c2ddeddSZhang Rui int limits[RAPL_DOMAIN_MAX];
155bf44b901SZhang Rui int (*read_raw)(int id, struct reg_action *ra);
156bf44b901SZhang Rui int (*write_raw)(int id, struct reg_action *ra);
157e8e28c2aSZhang Rui void *defaults;
15898ff639aSZhang Rui void *rpi;
1597ebf8effSZhang Rui };
1607ebf8effSZhang Rui
161*575024a8SZhang Rui #ifdef CONFIG_PERF_EVENTS
162*575024a8SZhang Rui /**
163*575024a8SZhang Rui * struct rapl_package_pmu_data: Per package data for PMU support
164*575024a8SZhang Rui * @scale: Scale of 2^-32 Joules for each energy counter increase.
165*575024a8SZhang Rui * @lock: Lock to protect n_active and active_list.
166*575024a8SZhang Rui * @n_active: Number of active events.
167*575024a8SZhang Rui * @active_list: List of active events.
168*575024a8SZhang Rui * @timer_interval: Maximum timer expiration time before counter overflow.
169*575024a8SZhang Rui * @hrtimer: Periodically update the counter to prevent overflow.
170*575024a8SZhang Rui */
171*575024a8SZhang Rui struct rapl_package_pmu_data {
172*575024a8SZhang Rui u64 scale[RAPL_DOMAIN_MAX];
173*575024a8SZhang Rui raw_spinlock_t lock;
174*575024a8SZhang Rui int n_active;
175*575024a8SZhang Rui struct list_head active_list;
176*575024a8SZhang Rui ktime_t timer_interval;
177*575024a8SZhang Rui struct hrtimer hrtimer;
178*575024a8SZhang Rui };
179*575024a8SZhang Rui #endif
180*575024a8SZhang Rui
181ff956826SZhang Rui /* maximum rapl package domain name: package-%d-die-%d */
182ff956826SZhang Rui #define PACKAGE_DOMAIN_NAME_LENGTH 30
183ff956826SZhang Rui
184ff956826SZhang Rui struct rapl_package {
185ff956826SZhang Rui unsigned int id; /* logical die id, equals physical 1-die systems */
186ff956826SZhang Rui unsigned int nr_domains;
187ff956826SZhang Rui unsigned long domain_map; /* bit map of active domains */
188ff956826SZhang Rui struct rapl_domain *domains; /* array of domains, sized at runtime */
189ff956826SZhang Rui struct powercap_zone *power_zone; /* keep track of parent zone */
190ff956826SZhang Rui unsigned long power_limit_irq; /* keep track of package power limit
191ff956826SZhang Rui * notify interrupt enable status.
192ff956826SZhang Rui */
193ff956826SZhang Rui struct list_head plist;
194ff956826SZhang Rui int lead_cpu; /* one active cpu per package for access */
195ff956826SZhang Rui /* Track active cpus */
196ff956826SZhang Rui struct cpumask cpumask;
197ff956826SZhang Rui char name[PACKAGE_DOMAIN_NAME_LENGTH];
1987ebf8effSZhang Rui struct rapl_if_priv *priv;
199*575024a8SZhang Rui #ifdef CONFIG_PERF_EVENTS
200*575024a8SZhang Rui bool has_pmu;
201*575024a8SZhang Rui struct rapl_package_pmu_data pmu_data;
202*575024a8SZhang Rui #endif
203ff956826SZhang Rui };
204ff956826SZhang Rui
2051aa09b93SZhang Rui struct rapl_package *rapl_find_package_domain_cpuslocked(int id, struct rapl_if_priv *priv,
2061aa09b93SZhang Rui bool id_is_cpu);
2071aa09b93SZhang Rui struct rapl_package *rapl_add_package_cpuslocked(int id, struct rapl_if_priv *priv,
2081aa09b93SZhang Rui bool id_is_cpu);
2091aa09b93SZhang Rui void rapl_remove_package_cpuslocked(struct rapl_package *rp);
2101aa09b93SZhang Rui
211bf44b901SZhang Rui struct rapl_package *rapl_find_package_domain(int id, struct rapl_if_priv *priv, bool id_is_cpu);
212bf44b901SZhang Rui struct rapl_package *rapl_add_package(int id, struct rapl_if_priv *priv, bool id_is_cpu);
2133382388dSZhang Rui void rapl_remove_package(struct rapl_package *rp);
2143382388dSZhang Rui
215*575024a8SZhang Rui #ifdef CONFIG_PERF_EVENTS
216*575024a8SZhang Rui int rapl_package_add_pmu(struct rapl_package *rp);
217*575024a8SZhang Rui void rapl_package_remove_pmu(struct rapl_package *rp);
218*575024a8SZhang Rui #else
rapl_package_add_pmu(struct rapl_package * rp)219*575024a8SZhang Rui static inline int rapl_package_add_pmu(struct rapl_package *rp) { return 0; }
rapl_package_remove_pmu(struct rapl_package * rp)220*575024a8SZhang Rui static inline void rapl_package_remove_pmu(struct rapl_package *rp) { }
221*575024a8SZhang Rui #endif
222*575024a8SZhang Rui
223ff956826SZhang Rui #endif /* __INTEL_RAPL_H__ */
224