drivers/intel/dptf: Add support for PCH methods

Add various methods support for pch device under dptf driver.
This provides support of different control knobs for FIVR.

BUG=b:198582766
BRANCH=None
TEST=Build FW and test on brya0 board

Change-Id: I2d40fff98cb4eb9144d55fd5383d9946e4cb0558
Signed-off-by: Sumeet Pawnikar <sumeet.r.pawnikar@intel.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/57925
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
This commit is contained in:
Sumeet Pawnikar 2021-09-23 21:49:29 +05:30 committed by Felix Held
parent 14886aec99
commit e0bff814da
3 changed files with 162 additions and 20 deletions

View File

@ -5,16 +5,21 @@
#include <console/console.h>
#include <device/device.h>
#include <intelblocks/pmc_ipc.h>
#include <soc/pci_devs.h>
#include "chip.h"
#include "dptf.h"
/* Generic DPTF participants have a PTYP field to distinguish them */
enum dptf_generic_participant_type {
DPTF_GENERIC_PARTICIPANT_TYPE_TSR = 0x3,
DPTF_GENERIC_PARTICIPANT_TYPE_TPCH = 0x5,
DPTF_GENERIC_PARTICIPANT_TYPE_CHARGER = 0xB,
};
#define DEFAULT_CHARGER_STR "Battery Charger"
#define DEFAULT_TPCH_STR "Intel PCH FIVR Participant"
#define PMC_IPC_COMMAND_FIVR_SIZE 0x8
/*
* Helper method to determine if a device is "used" (called out anywhere as a source or a target
@ -195,19 +200,31 @@ static void write_generic_devices(const struct drivers_intel_dptf_config *config
}
}
/* \_SB.DPTF.TPCH.RFC methods */
static void write_tpch_rfc_methods(const char *tpch_rfc_method_name,
static const char *get_pmc_ipcs_method(void)
{
const char *method = acpi_device_path_join(
pcidev_path_on_root(PCH_DEVFN_PMC), "IPCS");
if (!method) {
printk(BIOS_ERR, "%s: Unable to find PMC device IPCS method\n", __func__);
return NULL;
}
return method;
}
static void write_tpch_write_method(const char *tpch_write_method_name,
unsigned int ipc_subcmd_ctrl_value)
{
acpigen_write_method_serialized(tpch_rfc_method_name, 1);
acpigen_emit_namestring("IPCS");
/* Get IPCS method from the PMC device */
const char *ipcs = get_pmc_ipcs_method();
acpigen_write_method_serialized(tpch_write_method_name, 1);
acpigen_emit_namestring(ipcs);
acpigen_write_integer(PMC_IPC_CMD_COMMAND_FIVR);
acpigen_write_integer(PMC_IPC_CMD_CMD_ID_FIVR_WRITE);
acpigen_write_integer(0x8);
acpigen_write_integer(PMC_IPC_COMMAND_FIVR_SIZE);
acpigen_write_integer(ipc_subcmd_ctrl_value);
acpigen_emit_byte(ARG0_OP);
acpigen_write_dword(0);
acpigen_write_dword(0);
acpigen_write_zero();
acpigen_write_zero();
/* The reason for returning a value here is a W/A for the ESIF shell */
acpigen_emit_byte(RETURN_OP);
acpigen_write_package(0);
@ -215,12 +232,78 @@ static void write_tpch_rfc_methods(const char *tpch_rfc_method_name,
acpigen_write_method_end();
}
static void write_ppkg_package(const uint8_t i)
{
acpigen_write_store();
acpigen_emit_byte(DEREF_OP);
acpigen_emit_byte(INDEX_OP);
acpigen_emit_byte(ARG0_OP);
acpigen_write_integer(i);
acpigen_emit_byte(ZERO_OP);
acpigen_emit_byte(INDEX_OP);
acpigen_emit_namestring("PPKG");
acpigen_write_integer(i);
acpigen_emit_byte(ZERO_OP);
}
/*
* Truncate Package received from IPC
* Arguments:
* Arg0: Package returned from the IPCS read call from the Pmc
* Return Value:
* Return Package with just the Status and ReadBuf0
* Status returns 0 for success and 2 for device error
*/
static void write_pkgc_method(void)
{
acpigen_write_method_serialized("PKGC", 1);
acpigen_write_name("PPKG");
acpigen_write_package(2);
acpigen_write_zero();
acpigen_write_zero();
acpigen_write_package_end();
write_ppkg_package(0);
write_ppkg_package(1);
acpigen_write_return_namestr("PPKG");
acpigen_write_method_end();
}
static void write_tpch_read_method(const char *tpch_read_method_name,
unsigned int ipc_subcmd_ctrl_value)
{
/* Get IPCS method from the PMC device */
const char *ipcs = get_pmc_ipcs_method();
acpigen_write_method_serialized(tpch_read_method_name, 0);
acpigen_write_store();
acpigen_emit_namestring(ipcs);
acpigen_write_integer(PMC_IPC_CMD_COMMAND_FIVR);
acpigen_write_integer(PMC_IPC_CMD_CMD_ID_FIVR_READ);
acpigen_write_integer(PMC_IPC_COMMAND_FIVR_SIZE);
acpigen_write_integer(ipc_subcmd_ctrl_value);
acpigen_write_zero();
acpigen_write_zero();
acpigen_write_zero();
acpigen_emit_byte(LOCAL0_OP);
acpigen_write_store();
acpigen_emit_namestring("PKGC");
acpigen_emit_byte(LOCAL0_OP);
acpigen_emit_byte(LOCAL1_OP);
acpigen_emit_byte(RETURN_OP);
acpigen_emit_byte(LOCAL1_OP);
acpigen_write_method_end();
}
static void write_create_tpch(const struct dptf_platform_info *platform_info)
{
acpigen_write_device("TPCH");
acpigen_write_name("_HID");
dptf_write_hid(platform_info->use_eisa_hids, platform_info->tpch_device_hid);
acpigen_write_name_integer("_UID", 0);
acpigen_write_name_string("_STR", DEFAULT_TPCH_STR);
acpigen_write_name_integer("PTYP", DPTF_GENERIC_PARTICIPANT_TYPE_TPCH);
acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON);
}
@ -228,12 +311,58 @@ static void write_tpch_methods(const struct dptf_platform_info *platform_info)
{
write_create_tpch(platform_info);
/* Create RFC0 method */
write_tpch_rfc_methods(platform_info->tpch_rfc0_method,
PMC_IPC_SUBCMD_RFI_CTRL0_LOGIC);
/* Create RFC1 method */
write_tpch_rfc_methods(platform_info->tpch_rfc1_method,
PMC_IPC_SUBCMD_RFI_CTRL4_LOGIC);
const struct {
enum { READ, WRITE } type;
const char *method_name;
unsigned int subcommand;
} tpch_methods[] = {
{ .type = WRITE,
.method_name =
platform_info->tpch_method_names.set_fivr_low_clock_method,
.subcommand = PMC_IPC_SUBCMD_RFI_CTRL0_LOGIC
},
{ .type = WRITE,
.method_name =
platform_info->tpch_method_names.set_fivr_high_clock_method,
.subcommand = PMC_IPC_SUBCMD_RFI_CTRL4_LOGIC
},
{ .type = READ,
.method_name =
platform_info->tpch_method_names.get_fivr_low_clock_method,
.subcommand = PMC_IPC_SUBCMD_RFI_CTRL0_LOGIC
},
{ .type = READ,
.method_name =
platform_info->tpch_method_names.get_fivr_high_clock_method,
.subcommand = PMC_IPC_SUBCMD_RFI_CTRL4_LOGIC
},
{ .type = READ,
.method_name =
platform_info->tpch_method_names.get_fivr_ssc_method,
.subcommand = PMC_IPC_SUBCMD_EMI_CTRL0_LOGIC
},
{ .type = READ,
.method_name =
platform_info->tpch_method_names.get_fivr_switching_fault_status,
.subcommand = PMC_IPC_SUBCMD_FFFC_FAULT_STATUS
},
{ .type = READ,
.method_name =
platform_info->tpch_method_names.get_fivr_switching_freq_mhz,
.subcommand = PMC_IPC_SUBCMD_FFFC_RFI_STATUS
},
};
write_pkgc_method();
for (size_t i = 0; i < ARRAY_SIZE(tpch_methods); i++) {
if (tpch_methods[i].type == READ) {
write_tpch_read_method(tpch_methods[i].method_name,
tpch_methods[i].subcommand);
} else if (tpch_methods[i].type == WRITE) {
write_tpch_write_method(tpch_methods[i].method_name,
tpch_methods[i].subcommand);
}
}
acpigen_write_device_end(); /* TPCH Device */
}

View File

@ -15,8 +15,15 @@ struct dptf_platform_info {
const char *generic_hid;
const char *fan_hid;
const char *tpch_device_hid;
const char *tpch_rfc0_method;
const char *tpch_rfc1_method;
struct {
const char *set_fivr_low_clock_method;
const char *set_fivr_high_clock_method;
const char *get_fivr_low_clock_method;
const char *get_fivr_high_clock_method;
const char *get_fivr_ssc_method;
const char *get_fivr_switching_fault_status;
const char *get_fivr_switching_freq_mhz;
} tpch_method_names;
};
const struct dptf_platform_info *get_dptf_platform_info(void);

View File

@ -12,10 +12,16 @@ static const struct dptf_platform_info adl_dptf_platform_info = {
.fan_hid = "INTC1048",
/* _HID for the toplevel TPCH device, typically \_SB.TPCH */
.tpch_device_hid = "INTC1049",
/* RFC0 method name */
.tpch_rfc0_method = "RFC0",
/* RFC1 method name */
.tpch_rfc1_method = "RFC1",
.tpch_method_names = {
.set_fivr_low_clock_method = "RFC0",
.set_fivr_high_clock_method = "RFC1",
.get_fivr_low_clock_method = "GFC0",
.get_fivr_high_clock_method = "GFC1",
.get_fivr_ssc_method = "GEMI",
.get_fivr_switching_fault_status = "GFFS",
.get_fivr_switching_freq_mhz = "GFCS",
},
};
const struct dptf_platform_info *get_dptf_platform_info(void)