@@ -124,6 +124,20 @@ static DEFINE_PER_CPU(struct cpc_desc *, cpc_desc_ptr);
124124#define CPC_SUPPORTED (cpc ) ((cpc)->type == ACPI_TYPE_INTEGER ? \
125125 !!(cpc)->cpc_entry.int_value : \
126126 !IS_NULL_REG(&(cpc)->cpc_entry.reg))
127+
128+ /*
129+ * Each bit indicates the optionality of the register in per-cpu
130+ * cpc_regs[] with the corresponding index. 0 means mandatory and 1
131+ * means optional.
132+ */
133+ #define REG_OPTIONAL (0x1FC7D0)
134+
135+ /*
136+ * Use the index of the register in per-cpu cpc_regs[] to check if
137+ * it's an optional one.
138+ */
139+ #define IS_OPTIONAL_CPC_REG (reg_idx ) (REG_OPTIONAL & (1U << (reg_idx)))
140+
127141/*
128142 * Arbitrary Retries in case the remote processor is slow to respond
129143 * to PCC commands. Keeping it high enough to cover emulators where
@@ -1128,43 +1142,106 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
11281142 return ret_val ;
11291143}
11301144
1131- static int cppc_get_perf (int cpunum , enum cppc_regs reg_idx , u64 * perf )
1145+ static int cppc_get_reg_val_in_pcc (int cpu , struct cpc_register_resource * reg , u64 * val )
11321146{
1133- struct cpc_desc * cpc_desc = per_cpu (cpc_desc_ptr , cpunum );
1147+ int pcc_ss_id = per_cpu (cpu_pcc_subspace_idx , cpu );
1148+ struct cppc_pcc_data * pcc_ss_data = NULL ;
1149+ int ret ;
1150+
1151+ if (pcc_ss_id < 0 ) {
1152+ pr_debug ("Invalid pcc_ss_id\n" );
1153+ return - ENODEV ;
1154+ }
1155+
1156+ pcc_ss_data = pcc_data [pcc_ss_id ];
1157+
1158+ down_write (& pcc_ss_data -> pcc_lock );
1159+
1160+ if (send_pcc_cmd (pcc_ss_id , CMD_READ ) >= 0 )
1161+ ret = cpc_read (cpu , reg , val );
1162+ else
1163+ ret = - EIO ;
1164+
1165+ up_write (& pcc_ss_data -> pcc_lock );
1166+
1167+ return ret ;
1168+ }
1169+
1170+ static int cppc_get_reg_val (int cpu , enum cppc_regs reg_idx , u64 * val )
1171+ {
1172+ struct cpc_desc * cpc_desc = per_cpu (cpc_desc_ptr , cpu );
11341173 struct cpc_register_resource * reg ;
11351174
1175+ if (val == NULL )
1176+ return - EINVAL ;
1177+
11361178 if (!cpc_desc ) {
1137- pr_debug ("No CPC descriptor for CPU:%d\n" , cpunum );
1179+ pr_debug ("No CPC descriptor for CPU:%d\n" , cpu );
11381180 return - ENODEV ;
11391181 }
11401182
11411183 reg = & cpc_desc -> cpc_regs [reg_idx ];
11421184
1143- if (CPC_IN_PCC (reg )) {
1144- int pcc_ss_id = per_cpu (cpu_pcc_subspace_idx , cpunum );
1145- struct cppc_pcc_data * pcc_ss_data = NULL ;
1146- int ret = 0 ;
1147-
1148- if (pcc_ss_id < 0 )
1149- return - EIO ;
1185+ if ((reg -> type == ACPI_TYPE_INTEGER && IS_OPTIONAL_CPC_REG (reg_idx ) &&
1186+ !reg -> cpc_entry .int_value ) || (reg -> type != ACPI_TYPE_INTEGER &&
1187+ IS_NULL_REG (& reg -> cpc_entry .reg ))) {
1188+ pr_debug ("CPC register is not supported\n" );
1189+ return - EOPNOTSUPP ;
1190+ }
11501191
1151- pcc_ss_data = pcc_data [pcc_ss_id ];
1192+ if (CPC_IN_PCC (reg ))
1193+ return cppc_get_reg_val_in_pcc (cpu , reg , val );
11521194
1153- down_write (& pcc_ss_data -> pcc_lock );
1195+ return cpc_read (cpu , reg , val );
1196+ }
11541197
1155- if (send_pcc_cmd (pcc_ss_id , CMD_READ ) >= 0 )
1156- cpc_read (cpunum , reg , perf );
1157- else
1158- ret = - EIO ;
1198+ static int cppc_set_reg_val_in_pcc (int cpu , struct cpc_register_resource * reg , u64 val )
1199+ {
1200+ int pcc_ss_id = per_cpu (cpu_pcc_subspace_idx , cpu );
1201+ struct cppc_pcc_data * pcc_ss_data = NULL ;
1202+ int ret ;
11591203
1160- up_write (& pcc_ss_data -> pcc_lock );
1204+ if (pcc_ss_id < 0 ) {
1205+ pr_debug ("Invalid pcc_ss_id\n" );
1206+ return - ENODEV ;
1207+ }
11611208
1209+ ret = cpc_write (cpu , reg , val );
1210+ if (ret )
11621211 return ret ;
1212+
1213+ pcc_ss_data = pcc_data [pcc_ss_id ];
1214+
1215+ down_write (& pcc_ss_data -> pcc_lock );
1216+ /* after writing CPC, transfer the ownership of PCC to platform */
1217+ ret = send_pcc_cmd (pcc_ss_id , CMD_WRITE );
1218+ up_write (& pcc_ss_data -> pcc_lock );
1219+
1220+ return ret ;
1221+ }
1222+
1223+ static int cppc_set_reg_val (int cpu , enum cppc_regs reg_idx , u64 val )
1224+ {
1225+ struct cpc_desc * cpc_desc = per_cpu (cpc_desc_ptr , cpu );
1226+ struct cpc_register_resource * reg ;
1227+
1228+ if (!cpc_desc ) {
1229+ pr_debug ("No CPC descriptor for CPU:%d\n" , cpu );
1230+ return - ENODEV ;
11631231 }
11641232
1165- cpc_read ( cpunum , reg , perf ) ;
1233+ reg = & cpc_desc -> cpc_regs [ reg_idx ] ;
11661234
1167- return 0 ;
1235+ /* if a register is writeable, it must be a buffer and not null */
1236+ if ((reg -> type != ACPI_TYPE_BUFFER ) || IS_NULL_REG (& reg -> cpc_entry .reg )) {
1237+ pr_debug ("CPC register is not supported\n" );
1238+ return - EOPNOTSUPP ;
1239+ }
1240+
1241+ if (CPC_IN_PCC (reg ))
1242+ return cppc_set_reg_val_in_pcc (cpu , reg , val );
1243+
1244+ return cpc_write (cpu , reg , val );
11681245}
11691246
11701247/**
@@ -1176,7 +1253,7 @@ static int cppc_get_perf(int cpunum, enum cppc_regs reg_idx, u64 *perf)
11761253 */
11771254int cppc_get_desired_perf (int cpunum , u64 * desired_perf )
11781255{
1179- return cppc_get_perf (cpunum , DESIRED_PERF , desired_perf );
1256+ return cppc_get_reg_val (cpunum , DESIRED_PERF , desired_perf );
11801257}
11811258EXPORT_SYMBOL_GPL (cppc_get_desired_perf );
11821259
@@ -1189,7 +1266,7 @@ EXPORT_SYMBOL_GPL(cppc_get_desired_perf);
11891266 */
11901267int cppc_get_nominal_perf (int cpunum , u64 * nominal_perf )
11911268{
1192- return cppc_get_perf (cpunum , NOMINAL_PERF , nominal_perf );
1269+ return cppc_get_reg_val (cpunum , NOMINAL_PERF , nominal_perf );
11931270}
11941271
11951272/**
@@ -1201,7 +1278,7 @@ int cppc_get_nominal_perf(int cpunum, u64 *nominal_perf)
12011278 */
12021279int cppc_get_highest_perf (int cpunum , u64 * highest_perf )
12031280{
1204- return cppc_get_perf (cpunum , HIGHEST_PERF , highest_perf );
1281+ return cppc_get_reg_val (cpunum , HIGHEST_PERF , highest_perf );
12051282}
12061283EXPORT_SYMBOL_GPL (cppc_get_highest_perf );
12071284
@@ -1214,7 +1291,7 @@ EXPORT_SYMBOL_GPL(cppc_get_highest_perf);
12141291 */
12151292int cppc_get_epp_perf (int cpunum , u64 * epp_perf )
12161293{
1217- return cppc_get_perf (cpunum , ENERGY_PERF , epp_perf );
1294+ return cppc_get_reg_val (cpunum , ENERGY_PERF , epp_perf );
12181295}
12191296EXPORT_SYMBOL_GPL (cppc_get_epp_perf );
12201297
@@ -1485,53 +1562,27 @@ int cppc_set_epp_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls, bool enable)
14851562EXPORT_SYMBOL_GPL (cppc_set_epp_perf );
14861563
14871564/**
1488- * cppc_get_auto_sel_caps - Read autonomous selection register.
1489- * @cpunum : CPU from which to read register.
1490- * @perf_caps : struct where autonomous selection register value is updated .
1565+ * cppc_get_auto_sel() - Read autonomous selection register.
1566+ * @cpu : CPU from which to read register.
1567+ * @enable: Return address .
14911568 */
1492- int cppc_get_auto_sel_caps (int cpunum , struct cppc_perf_caps * perf_caps )
1569+ int cppc_get_auto_sel (int cpu , bool * enable )
14931570{
1494- struct cpc_desc * cpc_desc = per_cpu (cpc_desc_ptr , cpunum );
1495- struct cpc_register_resource * auto_sel_reg ;
1496- u64 auto_sel ;
1497-
1498- if (!cpc_desc ) {
1499- pr_debug ("No CPC descriptor for CPU:%d\n" , cpunum );
1500- return - ENODEV ;
1501- }
1502-
1503- auto_sel_reg = & cpc_desc -> cpc_regs [AUTO_SEL_ENABLE ];
1504-
1505- if (!CPC_SUPPORTED (auto_sel_reg ))
1506- pr_warn_once ("Autonomous mode is not unsupported!\n" );
1507-
1508- if (CPC_IN_PCC (auto_sel_reg )) {
1509- int pcc_ss_id = per_cpu (cpu_pcc_subspace_idx , cpunum );
1510- struct cppc_pcc_data * pcc_ss_data = NULL ;
1511- int ret = 0 ;
1512-
1513- if (pcc_ss_id < 0 )
1514- return - ENODEV ;
1515-
1516- pcc_ss_data = pcc_data [pcc_ss_id ];
1517-
1518- down_write (& pcc_ss_data -> pcc_lock );
1519-
1520- if (send_pcc_cmd (pcc_ss_id , CMD_READ ) >= 0 ) {
1521- cpc_read (cpunum , auto_sel_reg , & auto_sel );
1522- perf_caps -> auto_sel = (bool )auto_sel ;
1523- } else {
1524- ret = - EIO ;
1525- }
1571+ u64 auto_sel ;
1572+ int ret ;
15261573
1527- up_write (& pcc_ss_data -> pcc_lock );
1574+ if (enable == NULL )
1575+ return - EINVAL ;
15281576
1577+ ret = cppc_get_reg_val (cpu , AUTO_SEL_ENABLE , & auto_sel );
1578+ if (ret )
15291579 return ret ;
1530- }
1580+
1581+ * enable = (bool )auto_sel ;
15311582
15321583 return 0 ;
15331584}
1534- EXPORT_SYMBOL_GPL (cppc_get_auto_sel_caps );
1585+ EXPORT_SYMBOL_GPL (cppc_get_auto_sel );
15351586
15361587/**
15371588 * cppc_set_auto_sel - Write autonomous selection register.
@@ -1540,43 +1591,7 @@ EXPORT_SYMBOL_GPL(cppc_get_auto_sel_caps);
15401591 */
15411592int cppc_set_auto_sel (int cpu , bool enable )
15421593{
1543- int pcc_ss_id = per_cpu (cpu_pcc_subspace_idx , cpu );
1544- struct cpc_register_resource * auto_sel_reg ;
1545- struct cpc_desc * cpc_desc = per_cpu (cpc_desc_ptr , cpu );
1546- struct cppc_pcc_data * pcc_ss_data = NULL ;
1547- int ret = - EINVAL ;
1548-
1549- if (!cpc_desc ) {
1550- pr_debug ("No CPC descriptor for CPU:%d\n" , cpu );
1551- return - ENODEV ;
1552- }
1553-
1554- auto_sel_reg = & cpc_desc -> cpc_regs [AUTO_SEL_ENABLE ];
1555-
1556- if (CPC_IN_PCC (auto_sel_reg )) {
1557- if (pcc_ss_id < 0 ) {
1558- pr_debug ("Invalid pcc_ss_id\n" );
1559- return - ENODEV ;
1560- }
1561-
1562- if (CPC_SUPPORTED (auto_sel_reg )) {
1563- ret = cpc_write (cpu , auto_sel_reg , enable );
1564- if (ret )
1565- return ret ;
1566- }
1567-
1568- pcc_ss_data = pcc_data [pcc_ss_id ];
1569-
1570- down_write (& pcc_ss_data -> pcc_lock );
1571- /* after writing CPC, transfer the ownership of PCC to platform */
1572- ret = send_pcc_cmd (pcc_ss_id , CMD_WRITE );
1573- up_write (& pcc_ss_data -> pcc_lock );
1574- } else {
1575- ret = - ENOTSUPP ;
1576- pr_debug ("_CPC in PCC is not supported\n" );
1577- }
1578-
1579- return ret ;
1594+ return cppc_set_reg_val (cpu , AUTO_SEL_ENABLE , enable );
15801595}
15811596EXPORT_SYMBOL_GPL (cppc_set_auto_sel );
15821597
@@ -1590,38 +1605,7 @@ EXPORT_SYMBOL_GPL(cppc_set_auto_sel);
15901605 */
15911606int cppc_set_enable (int cpu , bool enable )
15921607{
1593- int pcc_ss_id = per_cpu (cpu_pcc_subspace_idx , cpu );
1594- struct cpc_register_resource * enable_reg ;
1595- struct cpc_desc * cpc_desc = per_cpu (cpc_desc_ptr , cpu );
1596- struct cppc_pcc_data * pcc_ss_data = NULL ;
1597- int ret = - EINVAL ;
1598-
1599- if (!cpc_desc ) {
1600- pr_debug ("No CPC descriptor for CPU:%d\n" , cpu );
1601- return - EINVAL ;
1602- }
1603-
1604- enable_reg = & cpc_desc -> cpc_regs [ENABLE ];
1605-
1606- if (CPC_IN_PCC (enable_reg )) {
1607-
1608- if (pcc_ss_id < 0 )
1609- return - EIO ;
1610-
1611- ret = cpc_write (cpu , enable_reg , enable );
1612- if (ret )
1613- return ret ;
1614-
1615- pcc_ss_data = pcc_data [pcc_ss_id ];
1616-
1617- down_write (& pcc_ss_data -> pcc_lock );
1618- /* after writing CPC, transfer the ownership of PCC to platfrom */
1619- ret = send_pcc_cmd (pcc_ss_id , CMD_WRITE );
1620- up_write (& pcc_ss_data -> pcc_lock );
1621- return ret ;
1622- }
1623-
1624- return cpc_write (cpu , enable_reg , enable );
1608+ return cppc_set_reg_val (cpu , ENABLE , enable );
16251609}
16261610EXPORT_SYMBOL_GPL (cppc_set_enable );
16271611
0 commit comments