Message ID | 20220225182505.7234-1-markpearson@lenovo.com (mailing list archive) |
---|---|
State | Accepted, archived |
Headers | show |
Series | platform/x86: thinkpad_acpi: Add PSC mode support | expand |
Hi, On 2/25/22 19:25, Mark Pearson wrote: > The Lenovo AMD platforms use PSC mode for providing platform > profile support. > > Detect if PSC mode is available and add support for setting the > different profile modes appropriately. > > Note - if both MMC mode and PSC mode are available then MMC mode > will be used in preference. > > Tested on T14 G1 AMD and T14s G2 AMD. > > Signed-off-by: Mark Pearson <markpearson@lenovo.com> Thank you for your patch, I've applied this patch to my review-hans branch: https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/log/?h=review-hans Note it will show up in my review-hans branch once I've pushed my local branch there, which might take a while. Once I've run some tests on this branch the patches there will be added to the platform-drivers-x86/for-next branch and eventually will be included in the pdx86 pull-request to Linus for the next merge-window. Regards, Hans p.s. One small thing which I noticed which could be improved is to move the 2 convert_profile_to_dytc() calls in dytc_profile_set() to a single call at the top of the function (before taking the lock even) to avoid code duplication between the DYTC_FUNCMODE_MMC vs DYTC_FUNCMODE_PSC paths. I didn't want to block merging the patch on this, if you can do a follow up patch with that as cleanup that would be great. > --- > drivers/platform/x86/thinkpad_acpi.c | 172 ++++++++++++++++++--------- > 1 file changed, 119 insertions(+), 53 deletions(-) > > diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c > index d0599e8a7b4d..d9117f824ce9 100644 > --- a/drivers/platform/x86/thinkpad_acpi.c > +++ b/drivers/platform/x86/thinkpad_acpi.c > @@ -10130,6 +10130,7 @@ static struct ibm_struct proxsensor_driver_data = { > > #define DYTC_CMD_FUNC_CAP 3 /* To get DYTC capabilities */ > #define DYTC_FC_MMC 27 /* MMC Mode supported */ > +#define DYTC_FC_PSC 29 /* PSC Mode supported */ > > #define DYTC_GET_FUNCTION_BIT 8 /* Bits 8-11 - function setting */ > #define DYTC_GET_MODE_BIT 12 /* Bits 12-15 - mode setting */ > @@ -10140,12 +10141,17 @@ static struct ibm_struct proxsensor_driver_data = { > > #define DYTC_FUNCTION_STD 0 /* Function = 0, standard mode */ > #define DYTC_FUNCTION_CQL 1 /* Function = 1, lap mode */ > -#define DYTC_FUNCTION_MMC 11 /* Function = 11, desk mode */ > +#define DYTC_FUNCTION_MMC 11 /* Function = 11, MMC mode */ > +#define DYTC_FUNCTION_PSC 13 /* Function = 13, PSC mode */ > > -#define DYTC_MODE_PERFORM 2 /* High power mode aka performance */ > -#define DYTC_MODE_LOWPOWER 3 /* Low power mode */ > -#define DYTC_MODE_BALANCE 0xF /* Default mode aka balanced */ > -#define DYTC_MODE_MMC_BALANCE 0 /* Default mode from MMC_GET, aka balanced */ > +#define DYTC_MODE_MMC_PERFORM 2 /* High power mode aka performance */ > +#define DYTC_MODE_MMC_LOWPOWER 3 /* Low power mode */ > +#define DYTC_MODE_MMC_BALANCE 0xF /* Default mode aka balanced */ > +#define DYTC_MODE_MMC_DEFAULT 0 /* Default mode from MMC_GET, aka balanced */ > + > +#define DYTC_MODE_PSC_LOWPOWER 3 /* Low power mode */ > +#define DYTC_MODE_PSC_BALANCE 5 /* Default mode aka balanced */ > +#define DYTC_MODE_PSC_PERFORM 7 /* High power mode aka performance */ > > #define DYTC_ERR_MASK 0xF /* Bits 0-3 in cmd result are the error result */ > #define DYTC_ERR_SUCCESS 1 /* CMD completed successful */ > @@ -10155,10 +10161,16 @@ static struct ibm_struct proxsensor_driver_data = { > (mode) << DYTC_SET_MODE_BIT | \ > (on) << DYTC_SET_VALID_BIT) > > -#define DYTC_DISABLE_CQL DYTC_SET_COMMAND(DYTC_FUNCTION_CQL, DYTC_MODE_BALANCE, 0) > +#define DYTC_DISABLE_CQL DYTC_SET_COMMAND(DYTC_FUNCTION_CQL, DYTC_MODE_MMC_BALANCE, 0) > +#define DYTC_ENABLE_CQL DYTC_SET_COMMAND(DYTC_FUNCTION_CQL, DYTC_MODE_MMC_BALANCE, 1) > > -#define DYTC_ENABLE_CQL DYTC_SET_COMMAND(DYTC_FUNCTION_CQL, DYTC_MODE_BALANCE, 1) > +enum dytc_profile_funcmode { > + DYTC_FUNCMODE_NONE = 0, > + DYTC_FUNCMODE_MMC, > + DYTC_FUNCMODE_PSC, > +}; > > +static enum dytc_profile_funcmode dytc_profile_available; > static enum platform_profile_option dytc_current_profile; > static atomic_t dytc_ignore_event = ATOMIC_INIT(0); > static DEFINE_MUTEX(dytc_mutex); > @@ -10166,19 +10178,37 @@ static bool dytc_mmc_get_available; > > static int convert_dytc_to_profile(int dytcmode, enum platform_profile_option *profile) > { > - switch (dytcmode) { > - case DYTC_MODE_LOWPOWER: > - *profile = PLATFORM_PROFILE_LOW_POWER; > - break; > - case DYTC_MODE_BALANCE: > - case DYTC_MODE_MMC_BALANCE: > - *profile = PLATFORM_PROFILE_BALANCED; > - break; > - case DYTC_MODE_PERFORM: > - *profile = PLATFORM_PROFILE_PERFORMANCE; > - break; > - default: /* Unknown mode */ > - return -EINVAL; > + if (dytc_profile_available == DYTC_FUNCMODE_MMC) { > + switch (dytcmode) { > + case DYTC_MODE_MMC_LOWPOWER: > + *profile = PLATFORM_PROFILE_LOW_POWER; > + break; > + case DYTC_MODE_MMC_DEFAULT: > + case DYTC_MODE_MMC_BALANCE: > + *profile = PLATFORM_PROFILE_BALANCED; > + break; > + case DYTC_MODE_MMC_PERFORM: > + *profile = PLATFORM_PROFILE_PERFORMANCE; > + break; > + default: /* Unknown mode */ > + return -EINVAL; > + } > + return 0; > + } > + if (dytc_profile_available == DYTC_FUNCMODE_PSC) { > + switch (dytcmode) { > + case DYTC_MODE_PSC_LOWPOWER: > + *profile = PLATFORM_PROFILE_LOW_POWER; > + break; > + case DYTC_MODE_PSC_BALANCE: > + *profile = PLATFORM_PROFILE_BALANCED; > + break; > + case DYTC_MODE_PSC_PERFORM: > + *profile = PLATFORM_PROFILE_PERFORMANCE; > + break; > + default: /* Unknown mode */ > + return -EINVAL; > + } > } > return 0; > } > @@ -10187,13 +10217,22 @@ static int convert_profile_to_dytc(enum platform_profile_option profile, int *pe > { > switch (profile) { > case PLATFORM_PROFILE_LOW_POWER: > - *perfmode = DYTC_MODE_LOWPOWER; > + if (dytc_profile_available == DYTC_FUNCMODE_MMC) > + *perfmode = DYTC_MODE_MMC_LOWPOWER; > + else if (dytc_profile_available == DYTC_FUNCMODE_PSC) > + *perfmode = DYTC_MODE_PSC_LOWPOWER; > break; > case PLATFORM_PROFILE_BALANCED: > - *perfmode = DYTC_MODE_BALANCE; > + if (dytc_profile_available == DYTC_FUNCMODE_MMC) > + *perfmode = DYTC_MODE_MMC_BALANCE; > + else if (dytc_profile_available == DYTC_FUNCMODE_PSC) > + *perfmode = DYTC_MODE_PSC_BALANCE; > break; > case PLATFORM_PROFILE_PERFORMANCE: > - *perfmode = DYTC_MODE_PERFORM; > + if (dytc_profile_available == DYTC_FUNCMODE_MMC) > + *perfmode = DYTC_MODE_MMC_PERFORM; > + else if (dytc_profile_available == DYTC_FUNCMODE_PSC) > + *perfmode = DYTC_MODE_PSC_PERFORM; > break; > default: /* Unknown profile */ > return -EOPNOTSUPP; > @@ -10266,25 +10305,39 @@ static int dytc_profile_set(struct platform_profile_handler *pprof, > if (err) > return err; > > - if (profile == PLATFORM_PROFILE_BALANCED) { > - /* > - * To get back to balanced mode we need to issue a reset command. > - * Note we still need to disable CQL mode before hand and re-enable > - * it afterwards, otherwise dytc_lapmode gets reset to 0 and stays > - * stuck at 0 for aprox. 30 minutes. > - */ > - err = dytc_cql_command(DYTC_CMD_RESET, &output); > - if (err) > - goto unlock; > - } else { > + if (dytc_profile_available == DYTC_FUNCMODE_MMC) { > + if (profile == PLATFORM_PROFILE_BALANCED) { > + /* > + * To get back to balanced mode we need to issue a reset command. > + * Note we still need to disable CQL mode before hand and re-enable > + * it afterwards, otherwise dytc_lapmode gets reset to 0 and stays > + * stuck at 0 for aprox. 30 minutes. > + */ > + err = dytc_cql_command(DYTC_CMD_RESET, &output); > + if (err) > + goto unlock; > + } else { > + int perfmode; > + > + err = convert_profile_to_dytc(profile, &perfmode); > + if (err) > + goto unlock; > + > + /* Determine if we are in CQL mode. This alters the commands we do */ > + err = dytc_cql_command(DYTC_SET_COMMAND(DYTC_FUNCTION_MMC, perfmode, 1), > + &output); > + if (err) > + goto unlock; > + } > + } > + if (dytc_profile_available == DYTC_FUNCMODE_PSC) { > int perfmode; > > err = convert_profile_to_dytc(profile, &perfmode); > if (err) > goto unlock; > > - /* Determine if we are in CQL mode. This alters the commands we do */ > - err = dytc_cql_command(DYTC_SET_COMMAND(DYTC_FUNCTION_MMC, perfmode, 1), &output); > + err = dytc_command(DYTC_SET_COMMAND(DYTC_FUNCTION_PSC, perfmode, 1), &output); > if (err) > goto unlock; > } > @@ -10302,10 +10355,14 @@ static void dytc_profile_refresh(void) > int perfmode; > > mutex_lock(&dytc_mutex); > - if (dytc_mmc_get_available) > - err = dytc_command(DYTC_CMD_MMC_GET, &output); > - else > - err = dytc_cql_command(DYTC_CMD_GET, &output); > + if (dytc_profile_available == DYTC_FUNCMODE_MMC) { > + if (dytc_mmc_get_available) > + err = dytc_command(DYTC_CMD_MMC_GET, &output); > + else > + err = dytc_cql_command(DYTC_CMD_GET, &output); > + } else if (dytc_profile_available == DYTC_FUNCMODE_PSC) > + err = dytc_command(DYTC_CMD_GET, &output); > + > mutex_unlock(&dytc_mutex); > if (err) > return; > @@ -10332,6 +10389,7 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm) > set_bit(PLATFORM_PROFILE_BALANCED, dytc_profile.choices); > set_bit(PLATFORM_PROFILE_PERFORMANCE, dytc_profile.choices); > > + dytc_profile_available = DYTC_FUNCMODE_NONE; > err = dytc_command(DYTC_CMD_QUERY, &output); > if (err) > return err; > @@ -10343,27 +10401,34 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm) > if (dytc_version < 5) > return -ENODEV; > > - /* Check what capabilities are supported. Currently MMC is needed */ > + /* Check what capabilities are supported */ > err = dytc_command(DYTC_CMD_FUNC_CAP, &output); > if (err) > return err; > - if (!(output & BIT(DYTC_FC_MMC))) { > - dbg_printk(TPACPI_DBG_INIT, " DYTC MMC mode not supported\n"); > + > + if (test_bit(DYTC_FC_MMC, (void *)&output)) { /* MMC MODE */ > + dytc_profile_available = DYTC_FUNCMODE_MMC; > + > + /* > + * Check if MMC_GET functionality available > + * Version > 6 and return success from MMC_GET command > + */ > + dytc_mmc_get_available = false; > + if (dytc_version >= 6) { > + err = dytc_command(DYTC_CMD_MMC_GET, &output); > + if (!err && ((output & DYTC_ERR_MASK) == DYTC_ERR_SUCCESS)) > + dytc_mmc_get_available = true; > + } > + } else if (test_bit(DYTC_FC_PSC, (void *)&output)) { /*PSC MODE */ > + dytc_profile_available = DYTC_FUNCMODE_PSC; > + } else { > + dbg_printk(TPACPI_DBG_INIT, "No DYTC support available\n"); > return -ENODEV; > } > > dbg_printk(TPACPI_DBG_INIT, > "DYTC version %d: thermal mode available\n", dytc_version); > - /* > - * Check if MMC_GET functionality available > - * Version > 6 and return success from MMC_GET command > - */ > - dytc_mmc_get_available = false; > - if (dytc_version >= 6) { > - err = dytc_command(DYTC_CMD_MMC_GET, &output); > - if (!err && ((output & DYTC_ERR_MASK) == DYTC_ERR_SUCCESS)) > - dytc_mmc_get_available = true; > - } > + > /* Create platform_profile structure and register */ > err = platform_profile_register(&dytc_profile); > /* > @@ -10381,6 +10446,7 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm) > > static void dytc_profile_exit(void) > { > + dytc_profile_available = DYTC_FUNCMODE_NONE; > platform_profile_remove(); > } >
Thanks Hans On 2022-03-02 09:47, Hans de Goede wrote: > Hi, > > On 2/25/22 19:25, Mark Pearson wrote: >> The Lenovo AMD platforms use PSC mode for providing platform >> profile support. >> >> Detect if PSC mode is available and add support for setting the >> different profile modes appropriately. >> >> Note - if both MMC mode and PSC mode are available then MMC mode >> will be used in preference. >> >> Tested on T14 G1 AMD and T14s G2 AMD. >> >> Signed-off-by: Mark Pearson <markpearson@lenovo.com> > > Thank you for your patch, I've applied this patch to my review-hans > branch: > https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/log/?h=review-hans>> > Note it will show up in my review-hans branch once I've pushed my > local branch there, which might take a while. > > Once I've run some tests on this branch the patches there will be > added to the platform-drivers-x86/for-next branch and eventually > will be included in the pdx86 pull-request to Linus for the next > merge-window. > > Regards, > > Hans > Awesome - thank you! > > > p.s. > > One small thing which I noticed which could be improved is to > move the 2 convert_profile_to_dytc() calls in dytc_profile_set() > to a single call at the top of the function (before taking the > lock even) to avoid code duplication between the DYTC_FUNCMODE_MMC > vs DYTC_FUNCMODE_PSC paths. > > I didn't want to block merging the patch on this, if you can > do a follow up patch with that as cleanup that would be great. > ack - that makes sense. Will do. Mark
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index d0599e8a7b4d..d9117f824ce9 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -10130,6 +10130,7 @@ static struct ibm_struct proxsensor_driver_data = { #define DYTC_CMD_FUNC_CAP 3 /* To get DYTC capabilities */ #define DYTC_FC_MMC 27 /* MMC Mode supported */ +#define DYTC_FC_PSC 29 /* PSC Mode supported */ #define DYTC_GET_FUNCTION_BIT 8 /* Bits 8-11 - function setting */ #define DYTC_GET_MODE_BIT 12 /* Bits 12-15 - mode setting */ @@ -10140,12 +10141,17 @@ static struct ibm_struct proxsensor_driver_data = { #define DYTC_FUNCTION_STD 0 /* Function = 0, standard mode */ #define DYTC_FUNCTION_CQL 1 /* Function = 1, lap mode */ -#define DYTC_FUNCTION_MMC 11 /* Function = 11, desk mode */ +#define DYTC_FUNCTION_MMC 11 /* Function = 11, MMC mode */ +#define DYTC_FUNCTION_PSC 13 /* Function = 13, PSC mode */ -#define DYTC_MODE_PERFORM 2 /* High power mode aka performance */ -#define DYTC_MODE_LOWPOWER 3 /* Low power mode */ -#define DYTC_MODE_BALANCE 0xF /* Default mode aka balanced */ -#define DYTC_MODE_MMC_BALANCE 0 /* Default mode from MMC_GET, aka balanced */ +#define DYTC_MODE_MMC_PERFORM 2 /* High power mode aka performance */ +#define DYTC_MODE_MMC_LOWPOWER 3 /* Low power mode */ +#define DYTC_MODE_MMC_BALANCE 0xF /* Default mode aka balanced */ +#define DYTC_MODE_MMC_DEFAULT 0 /* Default mode from MMC_GET, aka balanced */ + +#define DYTC_MODE_PSC_LOWPOWER 3 /* Low power mode */ +#define DYTC_MODE_PSC_BALANCE 5 /* Default mode aka balanced */ +#define DYTC_MODE_PSC_PERFORM 7 /* High power mode aka performance */ #define DYTC_ERR_MASK 0xF /* Bits 0-3 in cmd result are the error result */ #define DYTC_ERR_SUCCESS 1 /* CMD completed successful */ @@ -10155,10 +10161,16 @@ static struct ibm_struct proxsensor_driver_data = { (mode) << DYTC_SET_MODE_BIT | \ (on) << DYTC_SET_VALID_BIT) -#define DYTC_DISABLE_CQL DYTC_SET_COMMAND(DYTC_FUNCTION_CQL, DYTC_MODE_BALANCE, 0) +#define DYTC_DISABLE_CQL DYTC_SET_COMMAND(DYTC_FUNCTION_CQL, DYTC_MODE_MMC_BALANCE, 0) +#define DYTC_ENABLE_CQL DYTC_SET_COMMAND(DYTC_FUNCTION_CQL, DYTC_MODE_MMC_BALANCE, 1) -#define DYTC_ENABLE_CQL DYTC_SET_COMMAND(DYTC_FUNCTION_CQL, DYTC_MODE_BALANCE, 1) +enum dytc_profile_funcmode { + DYTC_FUNCMODE_NONE = 0, + DYTC_FUNCMODE_MMC, + DYTC_FUNCMODE_PSC, +}; +static enum dytc_profile_funcmode dytc_profile_available; static enum platform_profile_option dytc_current_profile; static atomic_t dytc_ignore_event = ATOMIC_INIT(0); static DEFINE_MUTEX(dytc_mutex); @@ -10166,19 +10178,37 @@ static bool dytc_mmc_get_available; static int convert_dytc_to_profile(int dytcmode, enum platform_profile_option *profile) { - switch (dytcmode) { - case DYTC_MODE_LOWPOWER: - *profile = PLATFORM_PROFILE_LOW_POWER; - break; - case DYTC_MODE_BALANCE: - case DYTC_MODE_MMC_BALANCE: - *profile = PLATFORM_PROFILE_BALANCED; - break; - case DYTC_MODE_PERFORM: - *profile = PLATFORM_PROFILE_PERFORMANCE; - break; - default: /* Unknown mode */ - return -EINVAL; + if (dytc_profile_available == DYTC_FUNCMODE_MMC) { + switch (dytcmode) { + case DYTC_MODE_MMC_LOWPOWER: + *profile = PLATFORM_PROFILE_LOW_POWER; + break; + case DYTC_MODE_MMC_DEFAULT: + case DYTC_MODE_MMC_BALANCE: + *profile = PLATFORM_PROFILE_BALANCED; + break; + case DYTC_MODE_MMC_PERFORM: + *profile = PLATFORM_PROFILE_PERFORMANCE; + break; + default: /* Unknown mode */ + return -EINVAL; + } + return 0; + } + if (dytc_profile_available == DYTC_FUNCMODE_PSC) { + switch (dytcmode) { + case DYTC_MODE_PSC_LOWPOWER: + *profile = PLATFORM_PROFILE_LOW_POWER; + break; + case DYTC_MODE_PSC_BALANCE: + *profile = PLATFORM_PROFILE_BALANCED; + break; + case DYTC_MODE_PSC_PERFORM: + *profile = PLATFORM_PROFILE_PERFORMANCE; + break; + default: /* Unknown mode */ + return -EINVAL; + } } return 0; } @@ -10187,13 +10217,22 @@ static int convert_profile_to_dytc(enum platform_profile_option profile, int *pe { switch (profile) { case PLATFORM_PROFILE_LOW_POWER: - *perfmode = DYTC_MODE_LOWPOWER; + if (dytc_profile_available == DYTC_FUNCMODE_MMC) + *perfmode = DYTC_MODE_MMC_LOWPOWER; + else if (dytc_profile_available == DYTC_FUNCMODE_PSC) + *perfmode = DYTC_MODE_PSC_LOWPOWER; break; case PLATFORM_PROFILE_BALANCED: - *perfmode = DYTC_MODE_BALANCE; + if (dytc_profile_available == DYTC_FUNCMODE_MMC) + *perfmode = DYTC_MODE_MMC_BALANCE; + else if (dytc_profile_available == DYTC_FUNCMODE_PSC) + *perfmode = DYTC_MODE_PSC_BALANCE; break; case PLATFORM_PROFILE_PERFORMANCE: - *perfmode = DYTC_MODE_PERFORM; + if (dytc_profile_available == DYTC_FUNCMODE_MMC) + *perfmode = DYTC_MODE_MMC_PERFORM; + else if (dytc_profile_available == DYTC_FUNCMODE_PSC) + *perfmode = DYTC_MODE_PSC_PERFORM; break; default: /* Unknown profile */ return -EOPNOTSUPP; @@ -10266,25 +10305,39 @@ static int dytc_profile_set(struct platform_profile_handler *pprof, if (err) return err; - if (profile == PLATFORM_PROFILE_BALANCED) { - /* - * To get back to balanced mode we need to issue a reset command. - * Note we still need to disable CQL mode before hand and re-enable - * it afterwards, otherwise dytc_lapmode gets reset to 0 and stays - * stuck at 0 for aprox. 30 minutes. - */ - err = dytc_cql_command(DYTC_CMD_RESET, &output); - if (err) - goto unlock; - } else { + if (dytc_profile_available == DYTC_FUNCMODE_MMC) { + if (profile == PLATFORM_PROFILE_BALANCED) { + /* + * To get back to balanced mode we need to issue a reset command. + * Note we still need to disable CQL mode before hand and re-enable + * it afterwards, otherwise dytc_lapmode gets reset to 0 and stays + * stuck at 0 for aprox. 30 minutes. + */ + err = dytc_cql_command(DYTC_CMD_RESET, &output); + if (err) + goto unlock; + } else { + int perfmode; + + err = convert_profile_to_dytc(profile, &perfmode); + if (err) + goto unlock; + + /* Determine if we are in CQL mode. This alters the commands we do */ + err = dytc_cql_command(DYTC_SET_COMMAND(DYTC_FUNCTION_MMC, perfmode, 1), + &output); + if (err) + goto unlock; + } + } + if (dytc_profile_available == DYTC_FUNCMODE_PSC) { int perfmode; err = convert_profile_to_dytc(profile, &perfmode); if (err) goto unlock; - /* Determine if we are in CQL mode. This alters the commands we do */ - err = dytc_cql_command(DYTC_SET_COMMAND(DYTC_FUNCTION_MMC, perfmode, 1), &output); + err = dytc_command(DYTC_SET_COMMAND(DYTC_FUNCTION_PSC, perfmode, 1), &output); if (err) goto unlock; } @@ -10302,10 +10355,14 @@ static void dytc_profile_refresh(void) int perfmode; mutex_lock(&dytc_mutex); - if (dytc_mmc_get_available) - err = dytc_command(DYTC_CMD_MMC_GET, &output); - else - err = dytc_cql_command(DYTC_CMD_GET, &output); + if (dytc_profile_available == DYTC_FUNCMODE_MMC) { + if (dytc_mmc_get_available) + err = dytc_command(DYTC_CMD_MMC_GET, &output); + else + err = dytc_cql_command(DYTC_CMD_GET, &output); + } else if (dytc_profile_available == DYTC_FUNCMODE_PSC) + err = dytc_command(DYTC_CMD_GET, &output); + mutex_unlock(&dytc_mutex); if (err) return; @@ -10332,6 +10389,7 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm) set_bit(PLATFORM_PROFILE_BALANCED, dytc_profile.choices); set_bit(PLATFORM_PROFILE_PERFORMANCE, dytc_profile.choices); + dytc_profile_available = DYTC_FUNCMODE_NONE; err = dytc_command(DYTC_CMD_QUERY, &output); if (err) return err; @@ -10343,27 +10401,34 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm) if (dytc_version < 5) return -ENODEV; - /* Check what capabilities are supported. Currently MMC is needed */ + /* Check what capabilities are supported */ err = dytc_command(DYTC_CMD_FUNC_CAP, &output); if (err) return err; - if (!(output & BIT(DYTC_FC_MMC))) { - dbg_printk(TPACPI_DBG_INIT, " DYTC MMC mode not supported\n"); + + if (test_bit(DYTC_FC_MMC, (void *)&output)) { /* MMC MODE */ + dytc_profile_available = DYTC_FUNCMODE_MMC; + + /* + * Check if MMC_GET functionality available + * Version > 6 and return success from MMC_GET command + */ + dytc_mmc_get_available = false; + if (dytc_version >= 6) { + err = dytc_command(DYTC_CMD_MMC_GET, &output); + if (!err && ((output & DYTC_ERR_MASK) == DYTC_ERR_SUCCESS)) + dytc_mmc_get_available = true; + } + } else if (test_bit(DYTC_FC_PSC, (void *)&output)) { /*PSC MODE */ + dytc_profile_available = DYTC_FUNCMODE_PSC; + } else { + dbg_printk(TPACPI_DBG_INIT, "No DYTC support available\n"); return -ENODEV; } dbg_printk(TPACPI_DBG_INIT, "DYTC version %d: thermal mode available\n", dytc_version); - /* - * Check if MMC_GET functionality available - * Version > 6 and return success from MMC_GET command - */ - dytc_mmc_get_available = false; - if (dytc_version >= 6) { - err = dytc_command(DYTC_CMD_MMC_GET, &output); - if (!err && ((output & DYTC_ERR_MASK) == DYTC_ERR_SUCCESS)) - dytc_mmc_get_available = true; - } + /* Create platform_profile structure and register */ err = platform_profile_register(&dytc_profile); /* @@ -10381,6 +10446,7 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm) static void dytc_profile_exit(void) { + dytc_profile_available = DYTC_FUNCMODE_NONE; platform_profile_remove(); }
The Lenovo AMD platforms use PSC mode for providing platform profile support. Detect if PSC mode is available and add support for setting the different profile modes appropriately. Note - if both MMC mode and PSC mode are available then MMC mode will be used in preference. Tested on T14 G1 AMD and T14s G2 AMD. Signed-off-by: Mark Pearson <markpearson@lenovo.com> --- drivers/platform/x86/thinkpad_acpi.c | 172 ++++++++++++++++++--------- 1 file changed, 119 insertions(+), 53 deletions(-)