Skip to content

Commit e12dee1

Browse files
zhang-ruirafaeljw
authored andcommitted
powercap: intel_rapl: Introduce core support for TPMI interface
Compared with existing RAPL MSR/MMIO Interface, the RAPL TPMI Interface 1. has per Power Limit register, thus has per Power Limit Lock and Enable bit. 2. doesn't have Power Limit Clamp bit. 3. the Power Limit Lock and Enable bits have different bit offsets. These mean RAPL TPMI Interface needs its own primitive information. RAPL TPMI Interface also has per domain unit register but with a different register layout. This requires a TPMI specific rapl_defaults call to decode the unit register. Introduce the RAPL core support for TPMI Interface. Signed-off-by: Zhang Rui <[email protected]> Tested-by: Wang Wendy <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent b4288ce commit e12dee1

File tree

2 files changed

+122
-2
lines changed

2 files changed

+122
-2
lines changed

drivers/powercap/intel_rapl_common.c

Lines changed: 117 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,15 @@
7575
#define PSYS_TIME_WINDOW1_MASK (0x7FULL<<19)
7676
#define PSYS_TIME_WINDOW2_MASK (0x7FULL<<51)
7777

78+
/* bitmasks for RAPL TPMI, used by primitive access functions */
79+
#define TPMI_POWER_LIMIT_MASK 0x3FFFF
80+
#define TPMI_POWER_LIMIT_ENABLE BIT_ULL(62)
81+
#define TPMI_TIME_WINDOW_MASK (0x7FULL<<18)
82+
#define TPMI_INFO_SPEC_MASK 0x3FFFF
83+
#define TPMI_INFO_MIN_MASK (0x3FFFFULL << 18)
84+
#define TPMI_INFO_MAX_MASK (0x3FFFFULL << 36)
85+
#define TPMI_INFO_MAX_TIME_WIN_MASK (0x7FULL << 54)
86+
7887
/* Non HW constants */
7988
#define RAPL_PRIMITIVE_DERIVED BIT(1) /* not from raw data */
8089
#define RAPL_PRIMITIVE_DUMMY BIT(2)
@@ -119,6 +128,19 @@ static bool is_pl_valid(struct rapl_domain *rd, int pl)
119128

120129
static int get_pl_lock_prim(struct rapl_domain *rd, int pl)
121130
{
131+
if (rd->rp->priv->type == RAPL_IF_TPMI) {
132+
if (pl == POWER_LIMIT1)
133+
return PL1_LOCK;
134+
if (pl == POWER_LIMIT2)
135+
return PL2_LOCK;
136+
if (pl == POWER_LIMIT4)
137+
return PL4_LOCK;
138+
}
139+
140+
/* MSR/MMIO Interface doesn't have Lock bit for PL4 */
141+
if (pl == POWER_LIMIT4)
142+
return -EINVAL;
143+
122144
/*
123145
* Power Limit register that supports two power limits has a different
124146
* bit position for the Lock bit.
@@ -134,7 +156,7 @@ static int get_pl_prim(struct rapl_domain *rd, int pl, enum pl_prims prim)
134156
case POWER_LIMIT1:
135157
if (prim == PL_ENABLE)
136158
return PL1_ENABLE;
137-
if (prim == PL_CLAMP)
159+
if (prim == PL_CLAMP && rd->rp->priv->type != RAPL_IF_TPMI)
138160
return PL1_CLAMP;
139161
if (prim == PL_LIMIT)
140162
return POWER_LIMIT1;
@@ -148,7 +170,7 @@ static int get_pl_prim(struct rapl_domain *rd, int pl, enum pl_prims prim)
148170
case POWER_LIMIT2:
149171
if (prim == PL_ENABLE)
150172
return PL2_ENABLE;
151-
if (prim == PL_CLAMP)
173+
if (prim == PL_CLAMP && rd->rp->priv->type != RAPL_IF_TPMI)
152174
return PL2_CLAMP;
153175
if (prim == PL_LIMIT)
154176
return POWER_LIMIT2;
@@ -167,6 +189,8 @@ static int get_pl_prim(struct rapl_domain *rd, int pl, enum pl_prims prim)
167189
/* PL4 would be around two times PL2, use same prim as PL2. */
168190
if (prim == PL_MAX_POWER)
169191
return MAX_POWER;
192+
if (prim == PL_LOCK)
193+
return get_pl_lock_prim(rd, pl);
170194
return -EINVAL;
171195
default:
172196
return -EINVAL;
@@ -187,6 +211,7 @@ struct rapl_defaults {
187211
bool spr_psys_bits;
188212
};
189213
static struct rapl_defaults *defaults_msr;
214+
static const struct rapl_defaults defaults_tpmi;
190215

191216
static struct rapl_defaults *get_defaults(struct rapl_package *rp)
192217
{
@@ -610,6 +635,7 @@ static u64 rapl_unit_xlate(struct rapl_domain *rd, enum unit_type type,
610635
return div64_u64(value, scale);
611636
}
612637

638+
/* RAPL primitives for MSR and MMIO I/F */
613639
static struct rapl_primitive_info rpi_msr[NR_RAPL_PRIMITIVES] = {
614640
/* name, mask, shift, msr index, unit divisor */
615641
[POWER_LIMIT1] = PRIMITIVE_INFO_INIT(POWER_LIMIT1, POWER_LIMIT1_MASK, 0,
@@ -667,6 +693,48 @@ static struct rapl_primitive_info rpi_msr[NR_RAPL_PRIMITIVES] = {
667693
RAPL_PRIMITIVE_DERIVED),
668694
};
669695

696+
/* RAPL primitives for TPMI I/F */
697+
static struct rapl_primitive_info rpi_tpmi[NR_RAPL_PRIMITIVES] = {
698+
/* name, mask, shift, msr index, unit divisor */
699+
[POWER_LIMIT1] = PRIMITIVE_INFO_INIT(POWER_LIMIT1, TPMI_POWER_LIMIT_MASK, 0,
700+
RAPL_DOMAIN_REG_LIMIT, POWER_UNIT, 0),
701+
[POWER_LIMIT2] = PRIMITIVE_INFO_INIT(POWER_LIMIT2, TPMI_POWER_LIMIT_MASK, 0,
702+
RAPL_DOMAIN_REG_PL2, POWER_UNIT, 0),
703+
[POWER_LIMIT4] = PRIMITIVE_INFO_INIT(POWER_LIMIT4, TPMI_POWER_LIMIT_MASK, 0,
704+
RAPL_DOMAIN_REG_PL4, POWER_UNIT, 0),
705+
[ENERGY_COUNTER] = PRIMITIVE_INFO_INIT(ENERGY_COUNTER, ENERGY_STATUS_MASK, 0,
706+
RAPL_DOMAIN_REG_STATUS, ENERGY_UNIT, 0),
707+
[PL1_LOCK] = PRIMITIVE_INFO_INIT(PL1_LOCK, POWER_HIGH_LOCK, 63,
708+
RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0),
709+
[PL2_LOCK] = PRIMITIVE_INFO_INIT(PL2_LOCK, POWER_HIGH_LOCK, 63,
710+
RAPL_DOMAIN_REG_PL2, ARBITRARY_UNIT, 0),
711+
[PL4_LOCK] = PRIMITIVE_INFO_INIT(PL4_LOCK, POWER_HIGH_LOCK, 63,
712+
RAPL_DOMAIN_REG_PL4, ARBITRARY_UNIT, 0),
713+
[PL1_ENABLE] = PRIMITIVE_INFO_INIT(PL1_ENABLE, TPMI_POWER_LIMIT_ENABLE, 62,
714+
RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0),
715+
[PL2_ENABLE] = PRIMITIVE_INFO_INIT(PL2_ENABLE, TPMI_POWER_LIMIT_ENABLE, 62,
716+
RAPL_DOMAIN_REG_PL2, ARBITRARY_UNIT, 0),
717+
[PL4_ENABLE] = PRIMITIVE_INFO_INIT(PL4_ENABLE, TPMI_POWER_LIMIT_ENABLE, 62,
718+
RAPL_DOMAIN_REG_PL4, ARBITRARY_UNIT, 0),
719+
[TIME_WINDOW1] = PRIMITIVE_INFO_INIT(TIME_WINDOW1, TPMI_TIME_WINDOW_MASK, 18,
720+
RAPL_DOMAIN_REG_LIMIT, TIME_UNIT, 0),
721+
[TIME_WINDOW2] = PRIMITIVE_INFO_INIT(TIME_WINDOW2, TPMI_TIME_WINDOW_MASK, 18,
722+
RAPL_DOMAIN_REG_PL2, TIME_UNIT, 0),
723+
[THERMAL_SPEC_POWER] = PRIMITIVE_INFO_INIT(THERMAL_SPEC_POWER, TPMI_INFO_SPEC_MASK, 0,
724+
RAPL_DOMAIN_REG_INFO, POWER_UNIT, 0),
725+
[MAX_POWER] = PRIMITIVE_INFO_INIT(MAX_POWER, TPMI_INFO_MAX_MASK, 36,
726+
RAPL_DOMAIN_REG_INFO, POWER_UNIT, 0),
727+
[MIN_POWER] = PRIMITIVE_INFO_INIT(MIN_POWER, TPMI_INFO_MIN_MASK, 18,
728+
RAPL_DOMAIN_REG_INFO, POWER_UNIT, 0),
729+
[MAX_TIME_WINDOW] = PRIMITIVE_INFO_INIT(MAX_TIME_WINDOW, TPMI_INFO_MAX_TIME_WIN_MASK, 54,
730+
RAPL_DOMAIN_REG_INFO, TIME_UNIT, 0),
731+
[THROTTLED_TIME] = PRIMITIVE_INFO_INIT(THROTTLED_TIME, PERF_STATUS_THROTTLE_TIME_MASK, 0,
732+
RAPL_DOMAIN_REG_PERF, TIME_UNIT, 0),
733+
/* non-hardware */
734+
[AVERAGE_POWER] = PRIMITIVE_INFO_INIT(AVERAGE_POWER, 0, 0, 0,
735+
POWER_UNIT, RAPL_PRIMITIVE_DERIVED),
736+
};
737+
670738
static struct rapl_primitive_info *get_rpi(struct rapl_package *rp, int prim)
671739
{
672740
struct rapl_primitive_info *rpi = rp->priv->rpi;
@@ -686,6 +754,10 @@ static int rapl_config(struct rapl_package *rp)
686754
rp->priv->defaults = (void *)defaults_msr;
687755
rp->priv->rpi = (void *)rpi_msr;
688756
break;
757+
case RAPL_IF_TPMI:
758+
rp->priv->defaults = (void *)&defaults_tpmi;
759+
rp->priv->rpi = (void *)rpi_tpmi;
760+
break;
689761
default:
690762
return -EINVAL;
691763
}
@@ -1046,6 +1118,49 @@ static u64 rapl_compute_time_window_atom(struct rapl_domain *rd, u64 value,
10461118
return value;
10471119
}
10481120

1121+
/* TPMI Unit register has different layout */
1122+
#define TPMI_POWER_UNIT_OFFSET POWER_UNIT_OFFSET
1123+
#define TPMI_POWER_UNIT_MASK POWER_UNIT_MASK
1124+
#define TPMI_ENERGY_UNIT_OFFSET 0x06
1125+
#define TPMI_ENERGY_UNIT_MASK 0x7C0
1126+
#define TPMI_TIME_UNIT_OFFSET 0x0C
1127+
#define TPMI_TIME_UNIT_MASK 0xF000
1128+
1129+
static int rapl_check_unit_tpmi(struct rapl_domain *rd)
1130+
{
1131+
struct reg_action ra;
1132+
u32 value;
1133+
1134+
ra.reg = rd->regs[RAPL_DOMAIN_REG_UNIT];
1135+
ra.mask = ~0;
1136+
if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) {
1137+
pr_err("Failed to read power unit REG 0x%llx on %s:%s, exit.\n",
1138+
ra.reg, rd->rp->name, rd->name);
1139+
return -ENODEV;
1140+
}
1141+
1142+
value = (ra.value & TPMI_ENERGY_UNIT_MASK) >> TPMI_ENERGY_UNIT_OFFSET;
1143+
rd->energy_unit = ENERGY_UNIT_SCALE * 1000000 / (1 << value);
1144+
1145+
value = (ra.value & TPMI_POWER_UNIT_MASK) >> TPMI_POWER_UNIT_OFFSET;
1146+
rd->power_unit = 1000000 / (1 << value);
1147+
1148+
value = (ra.value & TPMI_TIME_UNIT_MASK) >> TPMI_TIME_UNIT_OFFSET;
1149+
rd->time_unit = 1000000 / (1 << value);
1150+
1151+
pr_debug("Core CPU %s:%s energy=%dpJ, time=%dus, power=%duW\n",
1152+
rd->rp->name, rd->name, rd->energy_unit, rd->time_unit, rd->power_unit);
1153+
1154+
return 0;
1155+
}
1156+
1157+
static const struct rapl_defaults defaults_tpmi = {
1158+
.check_unit = rapl_check_unit_tpmi,
1159+
/* Reuse existing logic, ignore the PL_CLAMP failures and enable all Power Limits */
1160+
.set_floor_freq = set_floor_freq_default,
1161+
.compute_time_window = rapl_compute_time_window_core,
1162+
};
1163+
10491164
static const struct rapl_defaults rapl_defaults_core = {
10501165
.floor_freq_reg_addr = 0,
10511166
.check_unit = rapl_check_unit_core,

include/linux/intel_rapl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
enum rapl_if_type {
1818
RAPL_IF_MSR, /* RAPL I/F using MSR registers */
1919
RAPL_IF_MMIO, /* RAPL I/F using MMIO registers */
20+
RAPL_IF_TPMI, /* RAPL I/F using TPMI registers */
2021
};
2122

2223
enum rapl_domain_type {
@@ -36,6 +37,7 @@ enum rapl_domain_reg_id {
3637
RAPL_DOMAIN_REG_INFO,
3738
RAPL_DOMAIN_REG_PL4,
3839
RAPL_DOMAIN_REG_UNIT,
40+
RAPL_DOMAIN_REG_PL2,
3941
RAPL_DOMAIN_REG_MAX,
4042
};
4143

@@ -48,6 +50,9 @@ enum rapl_primitives {
4850
ENERGY_COUNTER,
4951
FW_LOCK,
5052
FW_HIGH_LOCK,
53+
PL1_LOCK,
54+
PL2_LOCK,
55+
PL4_LOCK,
5156

5257
PL1_ENABLE, /* power limit 1, aka long term */
5358
PL1_CLAMP, /* allow frequency to go below OS request */

0 commit comments

Comments
 (0)