summaryrefslogtreecommitdiff
path: root/drivers/soc/mediatek/mtk-svs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/soc/mediatek/mtk-svs.c')
-rw-r--r--drivers/soc/mediatek/mtk-svs.c1678
1 files changed, 1002 insertions, 676 deletions
diff --git a/drivers/soc/mediatek/mtk-svs.c b/drivers/soc/mediatek/mtk-svs.c
index f31e3bedff50..c832f5c670bc 100644
--- a/drivers/soc/mediatek/mtk-svs.c
+++ b/drivers/soc/mediatek/mtk-svs.c
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2022 MediaTek Inc.
+ * Copyright (C) 2022 Collabora Ltd.
+ * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
*/
#include <linux/bitfield.h>
@@ -32,16 +34,6 @@
#include <linux/spinlock.h>
#include <linux/thermal.h>
-/* svs bank 1-line software id */
-#define SVSB_CPU_LITTLE BIT(0)
-#define SVSB_CPU_BIG BIT(1)
-#define SVSB_CCI BIT(2)
-#define SVSB_GPU BIT(3)
-
-/* svs bank 2-line type */
-#define SVSB_LOW BIT(8)
-#define SVSB_HIGH BIT(9)
-
/* svs bank mode support */
#define SVSB_MODE_ALL_DISABLE 0
#define SVSB_MODE_INIT01 BIT(1)
@@ -128,6 +120,13 @@
#define SVSB_VOPS_FLD_VOP2_6 GENMASK(23, 16)
#define SVSB_VOPS_FLD_VOP3_7 GENMASK(31, 24)
+/* SVS Thermal Coefficients */
+#define SVSB_TS_COEFF_MT8195 250460
+#define SVSB_TS_COEFF_MT8186 204650
+
+/* Algo helpers */
+#define FUSE_DATA_NOT_VALID U32_MAX
+
/* svs bank related setting */
#define BITS8 8
#define MAX_OPP_ENTRIES 16
@@ -175,6 +174,36 @@ static DEFINE_SPINLOCK(svs_lock);
#endif
/**
+ * enum svsb_sw_id - SVS Bank Software ID
+ * @SVSB_SWID_CPU_LITTLE: CPU little cluster Bank
+ * @SVSB_SWID_CPU_BIG: CPU big cluster Bank
+ * @SVSB_SWID_CCI: Cache Coherent Interconnect Bank
+ * @SVSB_SWID_GPU: GPU Bank
+ * @SVSB_SWID_MAX: Total number of Banks
+ */
+enum svsb_sw_id {
+ SVSB_SWID_CPU_LITTLE,
+ SVSB_SWID_CPU_BIG,
+ SVSB_SWID_CCI,
+ SVSB_SWID_GPU,
+ SVSB_SWID_MAX
+};
+
+/**
+ * enum svsb_type - SVS Bank 2-line: Type and Role
+ * @SVSB_TYPE_NONE: One-line type Bank - Global role
+ * @SVSB_TYPE_LOW: Two-line type Bank - Low bank role
+ * @SVSB_TYPE_HIGH: Two-line type Bank - High bank role
+ * @SVSB_TYPE_MAX: Total number of bank types
+ */
+enum svsb_type {
+ SVSB_TYPE_NONE,
+ SVSB_TYPE_LOW,
+ SVSB_TYPE_HIGH,
+ SVSB_TYPE_MAX
+};
+
+/**
* enum svsb_phase - svs bank phase enumeration
* @SVSB_PHASE_ERROR: svs bank encounters unexpected condition
* @SVSB_PHASE_INIT01: svs bank basic init for data calibration
@@ -256,60 +285,88 @@ enum svs_reg_index {
};
static const u32 svs_regs_v2[] = {
- [DESCHAR] = 0xc00,
- [TEMPCHAR] = 0xc04,
- [DETCHAR] = 0xc08,
- [AGECHAR] = 0xc0c,
- [DCCONFIG] = 0xc10,
- [AGECONFIG] = 0xc14,
- [FREQPCT30] = 0xc18,
- [FREQPCT74] = 0xc1c,
- [LIMITVALS] = 0xc20,
- [VBOOT] = 0xc24,
- [DETWINDOW] = 0xc28,
- [CONFIG] = 0xc2c,
- [TSCALCS] = 0xc30,
- [RUNCONFIG] = 0xc34,
- [SVSEN] = 0xc38,
- [INIT2VALS] = 0xc3c,
- [DCVALUES] = 0xc40,
- [AGEVALUES] = 0xc44,
- [VOP30] = 0xc48,
- [VOP74] = 0xc4c,
- [TEMP] = 0xc50,
- [INTSTS] = 0xc54,
- [INTSTSRAW] = 0xc58,
- [INTEN] = 0xc5c,
- [CHKINT] = 0xc60,
- [CHKSHIFT] = 0xc64,
- [STATUS] = 0xc68,
- [VDESIGN30] = 0xc6c,
- [VDESIGN74] = 0xc70,
- [DVT30] = 0xc74,
- [DVT74] = 0xc78,
- [AGECOUNT] = 0xc7c,
- [SMSTATE0] = 0xc80,
- [SMSTATE1] = 0xc84,
- [CTL0] = 0xc88,
- [DESDETSEC] = 0xce0,
- [TEMPAGESEC] = 0xce4,
- [CTRLSPARE0] = 0xcf0,
- [CTRLSPARE1] = 0xcf4,
- [CTRLSPARE2] = 0xcf8,
- [CTRLSPARE3] = 0xcfc,
- [CORESEL] = 0xf00,
- [THERMINTST] = 0xf04,
- [INTST] = 0xf08,
- [THSTAGE0ST] = 0xf0c,
- [THSTAGE1ST] = 0xf10,
- [THSTAGE2ST] = 0xf14,
- [THAHBST0] = 0xf18,
- [THAHBST1] = 0xf1c,
- [SPARE0] = 0xf20,
- [SPARE1] = 0xf24,
- [SPARE2] = 0xf28,
- [SPARE3] = 0xf2c,
- [THSLPEVEB] = 0xf30,
+ [DESCHAR] = 0x00,
+ [TEMPCHAR] = 0x04,
+ [DETCHAR] = 0x08,
+ [AGECHAR] = 0x0c,
+ [DCCONFIG] = 0x10,
+ [AGECONFIG] = 0x14,
+ [FREQPCT30] = 0x18,
+ [FREQPCT74] = 0x1c,
+ [LIMITVALS] = 0x20,
+ [VBOOT] = 0x24,
+ [DETWINDOW] = 0x28,
+ [CONFIG] = 0x2c,
+ [TSCALCS] = 0x30,
+ [RUNCONFIG] = 0x34,
+ [SVSEN] = 0x38,
+ [INIT2VALS] = 0x3c,
+ [DCVALUES] = 0x40,
+ [AGEVALUES] = 0x44,
+ [VOP30] = 0x48,
+ [VOP74] = 0x4c,
+ [TEMP] = 0x50,
+ [INTSTS] = 0x54,
+ [INTSTSRAW] = 0x58,
+ [INTEN] = 0x5c,
+ [CHKINT] = 0x60,
+ [CHKSHIFT] = 0x64,
+ [STATUS] = 0x68,
+ [VDESIGN30] = 0x6c,
+ [VDESIGN74] = 0x70,
+ [DVT30] = 0x74,
+ [DVT74] = 0x78,
+ [AGECOUNT] = 0x7c,
+ [SMSTATE0] = 0x80,
+ [SMSTATE1] = 0x84,
+ [CTL0] = 0x88,
+ [DESDETSEC] = 0xe0,
+ [TEMPAGESEC] = 0xe4,
+ [CTRLSPARE0] = 0xf0,
+ [CTRLSPARE1] = 0xf4,
+ [CTRLSPARE2] = 0xf8,
+ [CTRLSPARE3] = 0xfc,
+ [CORESEL] = 0x300,
+ [THERMINTST] = 0x304,
+ [INTST] = 0x308,
+ [THSTAGE0ST] = 0x30c,
+ [THSTAGE1ST] = 0x310,
+ [THSTAGE2ST] = 0x314,
+ [THAHBST0] = 0x318,
+ [THAHBST1] = 0x31c,
+ [SPARE0] = 0x320,
+ [SPARE1] = 0x324,
+ [SPARE2] = 0x328,
+ [SPARE3] = 0x32c,
+ [THSLPEVEB] = 0x330,
+};
+
+static const char * const svs_swid_names[SVSB_SWID_MAX] = {
+ "SVSB_CPU_LITTLE", "SVSB_CPU_BIG", "SVSB_CCI", "SVSB_GPU"
+};
+
+static const char * const svs_type_names[SVSB_TYPE_MAX] = {
+ "", "_LOW", "_HIGH"
+};
+
+enum svs_fusemap_dev {
+ BDEV_BDES,
+ BDEV_MDES,
+ BDEV_MTDES,
+ BDEV_DCBDET,
+ BDEV_DCMDET,
+ BDEV_MAX
+};
+
+enum svs_fusemap_glb {
+ GLB_FT_PGM,
+ GLB_VMIN,
+ GLB_MAX
+};
+
+struct svs_fusemap {
+ s8 index;
+ u8 ofst;
};
/**
@@ -317,88 +374,124 @@ static const u32 svs_regs_v2[] = {
* @base: svs platform register base
* @dev: svs platform device
* @main_clk: main clock for svs bank
- * @pbank: svs bank pointer needing to be protected by spin_lock section
* @banks: svs banks that svs platform supports
* @rst: svs platform reset control
* @efuse_max: total number of svs efuse
* @tefuse_max: total number of thermal efuse
* @regs: svs platform registers map
- * @bank_max: total number of svs banks
* @efuse: svs efuse data received from NVMEM framework
* @tefuse: thermal efuse data received from NVMEM framework
+ * @ts_coeff: thermal sensors coefficient
+ * @bank_max: total number of svs banks
*/
struct svs_platform {
void __iomem *base;
struct device *dev;
struct clk *main_clk;
- struct svs_bank *pbank;
struct svs_bank *banks;
struct reset_control *rst;
size_t efuse_max;
size_t tefuse_max;
const u32 *regs;
- u32 bank_max;
u32 *efuse;
u32 *tefuse;
+ u32 ts_coeff;
+ u16 bank_max;
};
struct svs_platform_data {
char *name;
struct svs_bank *banks;
- bool (*efuse_parsing)(struct svs_platform *svsp);
+ bool (*efuse_parsing)(struct svs_platform *svsp, const struct svs_platform_data *pdata);
int (*probe)(struct svs_platform *svsp);
+ const struct svs_fusemap *glb_fuse_map;
const u32 *regs;
- u32 bank_max;
+ u32 ts_coeff;
+ u16 bank_max;
+};
+
+/**
+ * struct svs_bank_pdata - SVS Bank immutable config parameters
+ * @dev_fuse_map: Bank fuse map data
+ * @buck_name: Regulator name
+ * @tzone_name: Thermal zone name
+ * @age_config: Bank age configuration
+ * @ctl0: TS-x selection
+ * @dc_config: Bank dc configuration
+ * @int_st: Bank interrupt identification
+ * @turn_freq_base: Reference frequency for 2-line turn point
+ * @tzone_htemp: Thermal zone high temperature threshold
+ * @tzone_ltemp: Thermal zone low temperature threshold
+ * @volt_step: Bank voltage step
+ * @volt_base: Bank voltage base
+ * @tzone_htemp_voffset: Thermal zone high temperature voltage offset
+ * @tzone_ltemp_voffset: Thermal zone low temperature voltage offset
+ * @chk_shift: Bank chicken shift
+ * @cpu_id: CPU core ID for SVS CPU bank use only
+ * @opp_count: Bank opp count
+ * @vboot: Voltage request for bank init01 only
+ * @vco: Bank VCO value
+ * @sw_id: Bank software identification
+ * @type: SVS Bank Type (1 or 2-line) and Role (high/low)
+ * @set_freq_pct: function pointer to set bank frequency percent table
+ * @get_volts: function pointer to get bank voltages
+ */
+struct svs_bank_pdata {
+ const struct svs_fusemap *dev_fuse_map;
+ char *buck_name;
+ char *tzone_name;
+ u32 age_config;
+ u32 ctl0;
+ u32 dc_config;
+ u32 int_st;
+ u32 turn_freq_base;
+ u32 tzone_htemp;
+ u32 tzone_ltemp;
+ u32 volt_step;
+ u32 volt_base;
+ u16 tzone_htemp_voffset;
+ u16 tzone_ltemp_voffset;
+ u8 chk_shift;
+ u8 cpu_id;
+ u8 opp_count;
+ u8 vboot;
+ u8 vco;
+ u8 sw_id;
+ u8 type;
+
+ /* Callbacks */
+ void (*set_freq_pct)(struct svs_platform *svsp, struct svs_bank *svsb);
+ void (*get_volts)(struct svs_platform *svsp, struct svs_bank *svsb);
};
/**
* struct svs_bank - svs bank representation
+ * @pdata: SVS Bank immutable config parameters
* @dev: bank device
* @opp_dev: device for opp table/buck control
* @init_completion: the timeout completion for bank init
* @buck: regulator used by opp_dev
* @tzd: thermal zone device for getting temperature
* @lock: mutex lock to protect voltage update process
- * @set_freq_pct: function pointer to set bank frequency percent table
- * @get_volts: function pointer to get bank voltages
* @name: bank name
- * @buck_name: regulator name
- * @tzone_name: thermal zone name
* @phase: bank current phase
* @volt_od: bank voltage overdrive
* @reg_data: bank register data in different phase for debug purpose
* @pm_runtime_enabled_count: bank pm runtime enabled count
- * @mode_support: bank mode support.
+ * @mode_support: bank mode support
* @freq_base: reference frequency for bank init
- * @turn_freq_base: refenrece frequency for 2-line turn point
- * @vboot: voltage request for bank init01 only
* @opp_dfreq: default opp frequency table
* @opp_dvolt: default opp voltage table
* @freq_pct: frequency percent table for bank init
* @volt: bank voltage table
- * @volt_step: bank voltage step
- * @volt_base: bank voltage base
* @volt_flags: bank voltage flags
* @vmax: bank voltage maximum
* @vmin: bank voltage minimum
- * @age_config: bank age configuration
* @age_voffset_in: bank age voltage offset
- * @dc_config: bank dc configuration
* @dc_voffset_in: bank dc voltage offset
* @dvt_fixed: bank dvt fixed value
- * @vco: bank VCO value
- * @chk_shift: bank chicken shift
* @core_sel: bank selection
- * @opp_count: bank opp count
- * @int_st: bank interrupt identification
- * @sw_id: bank software identification
- * @cpu_id: cpu core id for SVS CPU bank use only
- * @ctl0: TS-x selection
* @temp: bank temperature
- * @tzone_htemp: thermal zone high temperature threshold
- * @tzone_htemp_voffset: thermal zone high temperature voltage offset
- * @tzone_ltemp: thermal zone low temperature threshold
- * @tzone_ltemp_voffset: thermal zone low temperature voltage offset
* @bts: svs efuse data
* @mts: svs efuse data
* @bdes: svs efuse data
@@ -408,70 +501,48 @@ struct svs_platform_data {
* @dcmdet: svs efuse data
* @turn_pt: 2-line turn point tells which opp_volt calculated by high/low bank
* @vbin_turn_pt: voltage bin turn point helps know which svsb_volt should be overridden
- * @type: bank type to represent it is 2-line (high/low) bank or 1-line bank
*
- * Svs bank will generate suitalbe voltages by below general math equation
+ * Svs bank will generate suitable voltages by below general math equation
* and provide these voltages to opp voltage table.
*
* opp_volt[i] = (volt[i] * volt_step) + volt_base;
*/
struct svs_bank {
+ const struct svs_bank_pdata pdata;
struct device *dev;
struct device *opp_dev;
struct completion init_completion;
struct regulator *buck;
struct thermal_zone_device *tzd;
- struct mutex lock; /* lock to protect voltage update process */
- void (*set_freq_pct)(struct svs_platform *svsp);
- void (*get_volts)(struct svs_platform *svsp);
+ struct mutex lock;
+ int pm_runtime_enabled_count;
+ short int volt_od;
char *name;
- char *buck_name;
- char *tzone_name;
enum svsb_phase phase;
- s32 volt_od;
u32 reg_data[SVSB_PHASE_MAX][SVS_REG_MAX];
- u32 pm_runtime_enabled_count;
- u32 mode_support;
- u32 freq_base;
- u32 turn_freq_base;
- u32 vboot;
+ u8 mode_support;
u32 opp_dfreq[MAX_OPP_ENTRIES];
u32 opp_dvolt[MAX_OPP_ENTRIES];
u32 freq_pct[MAX_OPP_ENTRIES];
u32 volt[MAX_OPP_ENTRIES];
- u32 volt_step;
- u32 volt_base;
u32 volt_flags;
- u32 vmax;
- u32 vmin;
- u32 age_config;
- u32 age_voffset_in;
- u32 dc_config;
- u32 dc_voffset_in;
- u32 dvt_fixed;
- u32 vco;
- u32 chk_shift;
- u32 core_sel;
- u32 opp_count;
- u32 int_st;
- u32 sw_id;
- u32 cpu_id;
- u32 ctl0;
- u32 temp;
- u32 tzone_htemp;
- u32 tzone_htemp_voffset;
- u32 tzone_ltemp;
- u32 tzone_ltemp_voffset;
- u32 bts;
- u32 mts;
- u32 bdes;
- u32 mdes;
- u32 mtdes;
- u32 dcbdet;
- u32 dcmdet;
+ u32 freq_base;
u32 turn_pt;
u32 vbin_turn_pt;
- u32 type;
+ u32 core_sel;
+ u32 temp;
+ u16 age_voffset_in;
+ u16 dc_voffset_in;
+ u8 dvt_fixed;
+ u8 vmax;
+ u8 vmin;
+ u16 bts;
+ u16 mts;
+ u16 bdes;
+ u16 mdes;
+ u8 mtdes;
+ u8 dcbdet;
+ u8 dcmdet;
};
static u32 percent(u32 numerator, u32 denominator)
@@ -494,10 +565,8 @@ static void svs_writel_relaxed(struct svs_platform *svsp, u32 val,
writel_relaxed(val, svsp->base + svsp->regs[rg_i]);
}
-static void svs_switch_bank(struct svs_platform *svsp)
+static void svs_switch_bank(struct svs_platform *svsp, struct svs_bank *svsb)
{
- struct svs_bank *svsb = svsp->pbank;
-
svs_writel_relaxed(svsp, svsb->core_sel, CORESEL);
}
@@ -515,10 +584,11 @@ static u32 svs_opp_volt_to_bank_volt(u32 opp_u_volt, u32 svsb_volt_step,
static int svs_sync_bank_volts_from_opp(struct svs_bank *svsb)
{
+ const struct svs_bank_pdata *bdata = &svsb->pdata;
struct dev_pm_opp *opp;
u32 i, opp_u_volt;
- for (i = 0; i < svsb->opp_count; i++) {
+ for (i = 0; i < bdata->opp_count; i++) {
opp = dev_pm_opp_find_freq_exact(svsb->opp_dev,
svsb->opp_dfreq[i],
true);
@@ -530,8 +600,8 @@ static int svs_sync_bank_volts_from_opp(struct svs_bank *svsb)
opp_u_volt = dev_pm_opp_get_voltage(opp);
svsb->volt[i] = svs_opp_volt_to_bank_volt(opp_u_volt,
- svsb->volt_step,
- svsb->volt_base);
+ bdata->volt_step,
+ bdata->volt_base);
dev_pm_opp_put(opp);
}
@@ -541,6 +611,7 @@ static int svs_sync_bank_volts_from_opp(struct svs_bank *svsb)
static int svs_adjust_pm_opp_volts(struct svs_bank *svsb)
{
int ret = -EPERM, tzone_temp = 0;
+ const struct svs_bank_pdata *bdata = &svsb->pdata;
u32 i, svsb_volt, opp_volt, temp_voffset = 0, opp_start, opp_stop;
mutex_lock(&svsb->lock);
@@ -549,15 +620,15 @@ static int svs_adjust_pm_opp_volts(struct svs_bank *svsb)
* 2-line bank updates its corresponding opp volts.
* 1-line bank updates all opp volts.
*/
- if (svsb->type == SVSB_HIGH) {
+ if (bdata->type == SVSB_TYPE_HIGH) {
opp_start = 0;
opp_stop = svsb->turn_pt;
- } else if (svsb->type == SVSB_LOW) {
+ } else if (bdata->type == SVSB_TYPE_LOW) {
opp_start = svsb->turn_pt;
- opp_stop = svsb->opp_count;
+ opp_stop = bdata->opp_count;
} else {
opp_start = 0;
- opp_stop = svsb->opp_count;
+ opp_stop = bdata->opp_count;
}
/* Get thermal effect */
@@ -566,20 +637,20 @@ static int svs_adjust_pm_opp_volts(struct svs_bank *svsb)
if (ret || (svsb->temp > SVSB_TEMP_UPPER_BOUND &&
svsb->temp < SVSB_TEMP_LOWER_BOUND)) {
dev_err(svsb->dev, "%s: %d (0x%x), run default volts\n",
- svsb->tzone_name, ret, svsb->temp);
+ bdata->tzone_name, ret, svsb->temp);
svsb->phase = SVSB_PHASE_ERROR;
}
- if (tzone_temp >= svsb->tzone_htemp)
- temp_voffset += svsb->tzone_htemp_voffset;
- else if (tzone_temp <= svsb->tzone_ltemp)
- temp_voffset += svsb->tzone_ltemp_voffset;
+ if (tzone_temp >= bdata->tzone_htemp)
+ temp_voffset += bdata->tzone_htemp_voffset;
+ else if (tzone_temp <= bdata->tzone_ltemp)
+ temp_voffset += bdata->tzone_ltemp_voffset;
/* 2-line bank update all opp volts when running mon mode */
- if (svsb->phase == SVSB_PHASE_MON && (svsb->type == SVSB_HIGH ||
- svsb->type == SVSB_LOW)) {
+ if (svsb->phase == SVSB_PHASE_MON && (bdata->type == SVSB_TYPE_HIGH ||
+ bdata->type == SVSB_TYPE_LOW)) {
opp_start = 0;
- opp_stop = svsb->opp_count;
+ opp_stop = bdata->opp_count;
}
}
@@ -596,8 +667,8 @@ static int svs_adjust_pm_opp_volts(struct svs_bank *svsb)
case SVSB_PHASE_MON:
svsb_volt = max(svsb->volt[i] + temp_voffset, svsb->vmin);
opp_volt = svs_bank_volt_to_opp_volt(svsb_volt,
- svsb->volt_step,
- svsb->volt_base);
+ bdata->volt_step,
+ bdata->volt_base);
break;
default:
dev_err(svsb->dev, "unknown phase: %u\n", svsb->phase);
@@ -632,8 +703,7 @@ static void svs_bank_disable_and_restore_default_volts(struct svs_platform *svsp
return;
spin_lock_irqsave(&svs_lock, flags);
- svsp->pbank = svsb;
- svs_switch_bank(svsp);
+ svs_switch_bank(svsp, svsb);
svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN);
svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS);
spin_unlock_irqrestore(&svs_lock, flags);
@@ -760,7 +830,7 @@ static int svs_status_debug_show(struct seq_file *m, void *v)
svsb->name, tzone_temp, svsb->vbin_turn_pt,
svsb->turn_pt);
- for (i = 0; i < svsb->opp_count; i++) {
+ for (i = 0; i < svsb->pdata.opp_count; i++) {
opp = dev_pm_opp_find_freq_exact(svsb->opp_dev,
svsb->opp_dfreq[i], true);
if (IS_ERR(opp)) {
@@ -865,12 +935,12 @@ static u32 interpolate(u32 f0, u32 f1, u32 v0, u32 v1, u32 fx)
return DIV_ROUND_UP(vx, 100);
}
-static void svs_get_bank_volts_v3(struct svs_platform *svsp)
+static void svs_get_bank_volts_v3(struct svs_platform *svsp, struct svs_bank *svsb)
{
- struct svs_bank *svsb = svsp->pbank;
+ const struct svs_bank_pdata *bdata = &svsb->pdata;
u32 i, j, *vop, vop74, vop30, turn_pt = svsb->turn_pt;
u32 b_sft, shift_byte = 0, opp_start = 0, opp_stop = 0;
- u32 middle_index = (svsb->opp_count / 2);
+ u32 middle_index = (bdata->opp_count / 2);
if (svsb->phase == SVSB_PHASE_MON &&
svsb->volt_flags & SVSB_MON_VOLT_IGNORE)
@@ -881,7 +951,7 @@ static void svs_get_bank_volts_v3(struct svs_platform *svsp)
/* Target is to set svsb->volt[] by algorithm */
if (turn_pt < middle_index) {
- if (svsb->type == SVSB_HIGH) {
+ if (bdata->type == SVSB_TYPE_HIGH) {
/* volt[0] ~ volt[turn_pt - 1] */
for (i = 0; i < turn_pt; i++) {
b_sft = BITS8 * (shift_byte % REG_BYTES);
@@ -890,12 +960,12 @@ static void svs_get_bank_volts_v3(struct svs_platform *svsp)
svsb->volt[i] = (*vop >> b_sft) & GENMASK(7, 0);
shift_byte++;
}
- } else if (svsb->type == SVSB_LOW) {
+ } else if (bdata->type == SVSB_TYPE_LOW) {
/* volt[turn_pt] + volt[j] ~ volt[opp_count - 1] */
- j = svsb->opp_count - 7;
+ j = bdata->opp_count - 7;
svsb->volt[turn_pt] = FIELD_GET(SVSB_VOPS_FLD_VOP0_4, vop30);
shift_byte++;
- for (i = j; i < svsb->opp_count; i++) {
+ for (i = j; i < bdata->opp_count; i++) {
b_sft = BITS8 * (shift_byte % REG_BYTES);
vop = (shift_byte < REG_BYTES) ? &vop30 :
&vop74;
@@ -912,7 +982,7 @@ static void svs_get_bank_volts_v3(struct svs_platform *svsp)
svsb->freq_pct[i]);
}
} else {
- if (svsb->type == SVSB_HIGH) {
+ if (bdata->type == SVSB_TYPE_HIGH) {
/* volt[0] + volt[j] ~ volt[turn_pt - 1] */
j = turn_pt - 7;
svsb->volt[0] = FIELD_GET(SVSB_VOPS_FLD_VOP0_4, vop30);
@@ -932,9 +1002,9 @@ static void svs_get_bank_volts_v3(struct svs_platform *svsp)
svsb->volt[0],
svsb->volt[j],
svsb->freq_pct[i]);
- } else if (svsb->type == SVSB_LOW) {
+ } else if (bdata->type == SVSB_TYPE_LOW) {
/* volt[turn_pt] ~ volt[opp_count - 1] */
- for (i = turn_pt; i < svsb->opp_count; i++) {
+ for (i = turn_pt; i < bdata->opp_count; i++) {
b_sft = BITS8 * (shift_byte % REG_BYTES);
vop = (shift_byte < REG_BYTES) ? &vop30 :
&vop74;
@@ -944,12 +1014,12 @@ static void svs_get_bank_volts_v3(struct svs_platform *svsp)
}
}
- if (svsb->type == SVSB_HIGH) {
+ if (bdata->type == SVSB_TYPE_HIGH) {
opp_start = 0;
opp_stop = svsb->turn_pt;
- } else if (svsb->type == SVSB_LOW) {
+ } else if (bdata->type == SVSB_TYPE_LOW) {
opp_start = svsb->turn_pt;
- opp_stop = svsb->opp_count;
+ opp_stop = bdata->opp_count;
}
for (i = opp_start; i < opp_stop; i++)
@@ -959,11 +1029,11 @@ static void svs_get_bank_volts_v3(struct svs_platform *svsp)
/* For voltage bin support */
if (svsb->opp_dfreq[0] > svsb->freq_base) {
svsb->volt[0] = svs_opp_volt_to_bank_volt(svsb->opp_dvolt[0],
- svsb->volt_step,
- svsb->volt_base);
+ bdata->volt_step,
+ bdata->volt_base);
/* Find voltage bin turn point */
- for (i = 0; i < svsb->opp_count; i++) {
+ for (i = 0; i < bdata->opp_count; i++) {
if (svsb->opp_dfreq[i] <= svsb->freq_base) {
svsb->vbin_turn_pt = i;
break;
@@ -980,15 +1050,15 @@ static void svs_get_bank_volts_v3(struct svs_platform *svsp)
}
}
-static void svs_set_bank_freq_pct_v3(struct svs_platform *svsp)
+static void svs_set_bank_freq_pct_v3(struct svs_platform *svsp, struct svs_bank *svsb)
{
- struct svs_bank *svsb = svsp->pbank;
+ const struct svs_bank_pdata *bdata = &svsb->pdata;
u32 i, j, *freq_pct, freq_pct74 = 0, freq_pct30 = 0;
u32 b_sft, shift_byte = 0, turn_pt;
- u32 middle_index = (svsb->opp_count / 2);
+ u32 middle_index = (bdata->opp_count / 2);
- for (i = 0; i < svsb->opp_count; i++) {
- if (svsb->opp_dfreq[i] <= svsb->turn_freq_base) {
+ for (i = 0; i < bdata->opp_count; i++) {
+ if (svsb->opp_dfreq[i] <= bdata->turn_freq_base) {
svsb->turn_pt = i;
break;
}
@@ -998,11 +1068,11 @@ static void svs_set_bank_freq_pct_v3(struct svs_platform *svsp)
/* Target is to fill out freq_pct74 / freq_pct30 by algorithm */
if (turn_pt < middle_index) {
- if (svsb->type == SVSB_HIGH) {
+ if (bdata->type == SVSB_TYPE_HIGH) {
/*
* If we don't handle this situation,
- * SVSB_HIGH's FREQPCT74 / FREQPCT30 would keep "0"
- * and this leads SVSB_LOW to work abnormally.
+ * SVSB_TYPE_HIGH's FREQPCT74 / FREQPCT30 would keep "0"
+ * and this leads SVSB_TYPE_LOW to work abnormally.
*/
if (turn_pt == 0)
freq_pct30 = svsb->freq_pct[0];
@@ -1015,15 +1085,15 @@ static void svs_set_bank_freq_pct_v3(struct svs_platform *svsp)
*freq_pct |= (svsb->freq_pct[i] << b_sft);
shift_byte++;
}
- } else if (svsb->type == SVSB_LOW) {
+ } else if (bdata->type == SVSB_TYPE_LOW) {
/*
* freq_pct[turn_pt] +
* freq_pct[opp_count - 7] ~ freq_pct[opp_count -1]
*/
freq_pct30 = svsb->freq_pct[turn_pt];
shift_byte++;
- j = svsb->opp_count - 7;
- for (i = j; i < svsb->opp_count; i++) {
+ j = bdata->opp_count - 7;
+ for (i = j; i < bdata->opp_count; i++) {
b_sft = BITS8 * (shift_byte % REG_BYTES);
freq_pct = (shift_byte < REG_BYTES) ?
&freq_pct30 : &freq_pct74;
@@ -1032,7 +1102,7 @@ static void svs_set_bank_freq_pct_v3(struct svs_platform *svsp)
}
}
} else {
- if (svsb->type == SVSB_HIGH) {
+ if (bdata->type == SVSB_TYPE_HIGH) {
/*
* freq_pct[0] +
* freq_pct[turn_pt - 7] ~ freq_pct[turn_pt - 1]
@@ -1047,9 +1117,9 @@ static void svs_set_bank_freq_pct_v3(struct svs_platform *svsp)
*freq_pct |= (svsb->freq_pct[i] << b_sft);
shift_byte++;
}
- } else if (svsb->type == SVSB_LOW) {
+ } else if (bdata->type == SVSB_TYPE_LOW) {
/* freq_pct[turn_pt] ~ freq_pct[opp_count - 1] */
- for (i = turn_pt; i < svsb->opp_count; i++) {
+ for (i = turn_pt; i < bdata->opp_count; i++) {
b_sft = BITS8 * (shift_byte % REG_BYTES);
freq_pct = (shift_byte < REG_BYTES) ?
&freq_pct30 : &freq_pct74;
@@ -1063,9 +1133,9 @@ static void svs_set_bank_freq_pct_v3(struct svs_platform *svsp)
svs_writel_relaxed(svsp, freq_pct30, FREQPCT30);
}
-static void svs_get_bank_volts_v2(struct svs_platform *svsp)
+static void svs_get_bank_volts_v2(struct svs_platform *svsp, struct svs_bank *svsb)
{
- struct svs_bank *svsb = svsp->pbank;
+ const struct svs_bank_pdata *bdata = &svsb->pdata;
u32 temp, i;
temp = svs_readl_relaxed(svsp, VOP74);
@@ -1093,17 +1163,17 @@ static void svs_get_bank_volts_v2(struct svs_platform *svsp)
svsb->volt[14],
svsb->freq_pct[15]);
- for (i = 0; i < svsb->opp_count; i++)
+ for (i = 0; i < bdata->opp_count; i++)
svsb->volt[i] += svsb->volt_od;
/* For voltage bin support */
if (svsb->opp_dfreq[0] > svsb->freq_base) {
svsb->volt[0] = svs_opp_volt_to_bank_volt(svsb->opp_dvolt[0],
- svsb->volt_step,
- svsb->volt_base);
+ bdata->volt_step,
+ bdata->volt_base);
/* Find voltage bin turn point */
- for (i = 0; i < svsb->opp_count; i++) {
+ for (i = 0; i < bdata->opp_count; i++) {
if (svsb->opp_dfreq[i] <= svsb->freq_base) {
svsb->vbin_turn_pt = i;
break;
@@ -1120,9 +1190,8 @@ static void svs_get_bank_volts_v2(struct svs_platform *svsp)
}
}
-static void svs_set_bank_freq_pct_v2(struct svs_platform *svsp)
+static void svs_set_bank_freq_pct_v2(struct svs_platform *svsp, struct svs_bank *svsb)
{
- struct svs_bank *svsb = svsp->pbank;
u32 freqpct74_val, freqpct30_val;
freqpct74_val = FIELD_PREP(SVSB_FREQPCTS_FLD_PCT0_4, svsb->freq_pct[8]) |
@@ -1140,18 +1209,20 @@ static void svs_set_bank_freq_pct_v2(struct svs_platform *svsp)
}
static void svs_set_bank_phase(struct svs_platform *svsp,
+ unsigned int bank_idx,
enum svsb_phase target_phase)
{
- struct svs_bank *svsb = svsp->pbank;
+ struct svs_bank *svsb = &svsp->banks[bank_idx];
+ const struct svs_bank_pdata *bdata = &svsb->pdata;
u32 des_char, temp_char, det_char, limit_vals, init2vals, ts_calcs;
- svs_switch_bank(svsp);
+ svs_switch_bank(svsp, svsb);
des_char = FIELD_PREP(SVSB_DESCHAR_FLD_BDES, svsb->bdes) |
FIELD_PREP(SVSB_DESCHAR_FLD_MDES, svsb->mdes);
svs_writel_relaxed(svsp, des_char, DESCHAR);
- temp_char = FIELD_PREP(SVSB_TEMPCHAR_FLD_VCO, svsb->vco) |
+ temp_char = FIELD_PREP(SVSB_TEMPCHAR_FLD_VCO, bdata->vco) |
FIELD_PREP(SVSB_TEMPCHAR_FLD_MTDES, svsb->mtdes) |
FIELD_PREP(SVSB_TEMPCHAR_FLD_DVT_FIXED, svsb->dvt_fixed);
svs_writel_relaxed(svsp, temp_char, TEMPCHAR);
@@ -1160,11 +1231,11 @@ static void svs_set_bank_phase(struct svs_platform *svsp,
FIELD_PREP(SVSB_DETCHAR_FLD_DCMDET, svsb->dcmdet);
svs_writel_relaxed(svsp, det_char, DETCHAR);
- svs_writel_relaxed(svsp, svsb->dc_config, DCCONFIG);
- svs_writel_relaxed(svsp, svsb->age_config, AGECONFIG);
+ svs_writel_relaxed(svsp, bdata->dc_config, DCCONFIG);
+ svs_writel_relaxed(svsp, bdata->age_config, AGECONFIG);
svs_writel_relaxed(svsp, SVSB_RUNCONFIG_DEFAULT, RUNCONFIG);
- svsb->set_freq_pct(svsp);
+ bdata->set_freq_pct(svsp, svsb);
limit_vals = FIELD_PREP(SVSB_LIMITVALS_FLD_DTLO, SVSB_VAL_DTLO) |
FIELD_PREP(SVSB_LIMITVALS_FLD_DTHI, SVSB_VAL_DTHI) |
@@ -1174,13 +1245,13 @@ static void svs_set_bank_phase(struct svs_platform *svsp,
svs_writel_relaxed(svsp, SVSB_DET_WINDOW, DETWINDOW);
svs_writel_relaxed(svsp, SVSB_DET_MAX, CONFIG);
- svs_writel_relaxed(svsp, svsb->chk_shift, CHKSHIFT);
- svs_writel_relaxed(svsp, svsb->ctl0, CTL0);
+ svs_writel_relaxed(svsp, bdata->chk_shift, CHKSHIFT);
+ svs_writel_relaxed(svsp, bdata->ctl0, CTL0);
svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS);
switch (target_phase) {
case SVSB_PHASE_INIT01:
- svs_writel_relaxed(svsp, svsb->vboot, VBOOT);
+ svs_writel_relaxed(svsp, bdata->vboot, VBOOT);
svs_writel_relaxed(svsp, SVSB_INTEN_INIT0x, INTEN);
svs_writel_relaxed(svsp, SVSB_PTPEN_INIT01, SVSEN);
break;
@@ -1206,18 +1277,20 @@ static void svs_set_bank_phase(struct svs_platform *svsp,
}
static inline void svs_save_bank_register_data(struct svs_platform *svsp,
+ unsigned short bank_idx,
enum svsb_phase phase)
{
- struct svs_bank *svsb = svsp->pbank;
+ struct svs_bank *svsb = &svsp->banks[bank_idx];
enum svs_reg_index rg_i;
for (rg_i = DESCHAR; rg_i < SVS_REG_MAX; rg_i++)
svsb->reg_data[phase][rg_i] = svs_readl_relaxed(svsp, rg_i);
}
-static inline void svs_error_isr_handler(struct svs_platform *svsp)
+static inline void svs_error_isr_handler(struct svs_platform *svsp,
+ unsigned short bank_idx)
{
- struct svs_bank *svsb = svsp->pbank;
+ struct svs_bank *svsb = &svsp->banks[bank_idx];
dev_err(svsb->dev, "%s: CORESEL = 0x%08x\n",
__func__, svs_readl_relaxed(svsp, CORESEL));
@@ -1229,27 +1302,29 @@ static inline void svs_error_isr_handler(struct svs_platform *svsp)
svs_readl_relaxed(svsp, SMSTATE1));
dev_err(svsb->dev, "TEMP = 0x%08x\n", svs_readl_relaxed(svsp, TEMP));
- svs_save_bank_register_data(svsp, SVSB_PHASE_ERROR);
+ svs_save_bank_register_data(svsp, bank_idx, SVSB_PHASE_ERROR);
svsb->phase = SVSB_PHASE_ERROR;
svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN);
svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS);
}
-static inline void svs_init01_isr_handler(struct svs_platform *svsp)
+static inline void svs_init01_isr_handler(struct svs_platform *svsp,
+ unsigned short bank_idx)
{
- struct svs_bank *svsb = svsp->pbank;
+ struct svs_bank *svsb = &svsp->banks[bank_idx];
+ u32 val;
dev_info(svsb->dev, "%s: VDN74~30:0x%08x~0x%08x, DC:0x%08x\n",
__func__, svs_readl_relaxed(svsp, VDESIGN74),
svs_readl_relaxed(svsp, VDESIGN30),
svs_readl_relaxed(svsp, DCVALUES));
- svs_save_bank_register_data(svsp, SVSB_PHASE_INIT01);
+ svs_save_bank_register_data(svsp, bank_idx, SVSB_PHASE_INIT01);
svsb->phase = SVSB_PHASE_INIT01;
- svsb->dc_voffset_in = ~(svs_readl_relaxed(svsp, DCVALUES) &
- GENMASK(15, 0)) + 1;
+ val = ~(svs_readl_relaxed(svsp, DCVALUES) & GENMASK(15, 0)) + 1;
+ svsb->dc_voffset_in = val & GENMASK(15, 0);
if (svsb->volt_flags & SVSB_INIT01_VOLT_IGNORE ||
(svsb->dc_voffset_in & SVSB_DC_SIGNED_BIT &&
svsb->volt_flags & SVSB_INIT01_VOLT_INC_ONLY))
@@ -1263,32 +1338,36 @@ static inline void svs_init01_isr_handler(struct svs_platform *svsp)
svsb->core_sel &= ~SVSB_DET_CLK_EN;
}
-static inline void svs_init02_isr_handler(struct svs_platform *svsp)
+static inline void svs_init02_isr_handler(struct svs_platform *svsp,
+ unsigned short bank_idx)
{
- struct svs_bank *svsb = svsp->pbank;
+ struct svs_bank *svsb = &svsp->banks[bank_idx];
+ const struct svs_bank_pdata *bdata = &svsb->pdata;
dev_info(svsb->dev, "%s: VOP74~30:0x%08x~0x%08x, DC:0x%08x\n",
__func__, svs_readl_relaxed(svsp, VOP74),
svs_readl_relaxed(svsp, VOP30),
svs_readl_relaxed(svsp, DCVALUES));
- svs_save_bank_register_data(svsp, SVSB_PHASE_INIT02);
+ svs_save_bank_register_data(svsp, bank_idx, SVSB_PHASE_INIT02);
svsb->phase = SVSB_PHASE_INIT02;
- svsb->get_volts(svsp);
+ bdata->get_volts(svsp, svsb);
svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN);
svs_writel_relaxed(svsp, SVSB_INTSTS_F0_COMPLETE, INTSTS);
}
-static inline void svs_mon_mode_isr_handler(struct svs_platform *svsp)
+static inline void svs_mon_mode_isr_handler(struct svs_platform *svsp,
+ unsigned short bank_idx)
{
- struct svs_bank *svsb = svsp->pbank;
+ struct svs_bank *svsb = &svsp->banks[bank_idx];
+ const struct svs_bank_pdata *bdata = &svsb->pdata;
- svs_save_bank_register_data(svsp, SVSB_PHASE_MON);
+ svs_save_bank_register_data(svsp, bank_idx, SVSB_PHASE_MON);
svsb->phase = SVSB_PHASE_MON;
- svsb->get_volts(svsp);
+ bdata->get_volts(svsp, svsb);
svsb->temp = svs_readl_relaxed(svsp, TEMP) & GENMASK(7, 0);
svs_writel_relaxed(svsp, SVSB_INTSTS_FLD_MONVOP, INTSTS);
@@ -1297,37 +1376,38 @@ static inline void svs_mon_mode_isr_handler(struct svs_platform *svsp)
static irqreturn_t svs_isr(int irq, void *data)
{
struct svs_platform *svsp = data;
+ const struct svs_bank_pdata *bdata;
struct svs_bank *svsb = NULL;
unsigned long flags;
u32 idx, int_sts, svs_en;
for (idx = 0; idx < svsp->bank_max; idx++) {
svsb = &svsp->banks[idx];
+ bdata = &svsb->pdata;
WARN(!svsb, "%s: svsb(%s) is null", __func__, svsb->name);
spin_lock_irqsave(&svs_lock, flags);
- svsp->pbank = svsb;
/* Find out which svs bank fires interrupt */
- if (svsb->int_st & svs_readl_relaxed(svsp, INTST)) {
+ if (bdata->int_st & svs_readl_relaxed(svsp, INTST)) {
spin_unlock_irqrestore(&svs_lock, flags);
continue;
}
- svs_switch_bank(svsp);
+ svs_switch_bank(svsp, svsb);
int_sts = svs_readl_relaxed(svsp, INTSTS);
svs_en = svs_readl_relaxed(svsp, SVSEN);
if (int_sts == SVSB_INTSTS_F0_COMPLETE &&
svs_en == SVSB_PTPEN_INIT01)
- svs_init01_isr_handler(svsp);
+ svs_init01_isr_handler(svsp, idx);
else if (int_sts == SVSB_INTSTS_F0_COMPLETE &&
svs_en == SVSB_PTPEN_INIT02)
- svs_init02_isr_handler(svsp);
+ svs_init02_isr_handler(svsp, idx);
else if (int_sts & SVSB_INTSTS_FLD_MONVOP)
- svs_mon_mode_isr_handler(svsp);
+ svs_mon_mode_isr_handler(svsp, idx);
else
- svs_error_isr_handler(svsp);
+ svs_error_isr_handler(svsp, idx);
spin_unlock_irqrestore(&svs_lock, flags);
break;
@@ -1342,20 +1422,35 @@ static irqreturn_t svs_isr(int irq, void *data)
return IRQ_HANDLED;
}
+static bool svs_mode_available(struct svs_platform *svsp, u8 mode)
+{
+ int i;
+
+ for (i = 0; i < svsp->bank_max; i++)
+ if (svsp->banks[i].mode_support & mode)
+ return true;
+ return false;
+}
+
static int svs_init01(struct svs_platform *svsp)
{
+ const struct svs_bank_pdata *bdata;
struct svs_bank *svsb;
unsigned long flags, time_left;
bool search_done;
int ret = 0, r;
u32 opp_freq, opp_vboot, buck_volt, idx, i;
+ if (!svs_mode_available(svsp, SVSB_MODE_INIT01))
+ return 0;
+
/* Keep CPUs' core power on for svs_init01 initialization */
cpuidle_pause_and_lock();
/* Svs bank init01 preparation - power enable */
for (idx = 0; idx < svsp->bank_max; idx++) {
svsb = &svsp->banks[idx];
+ bdata = &svsb->pdata;
if (!(svsb->mode_support & SVSB_MODE_INIT01))
continue;
@@ -1363,7 +1458,7 @@ static int svs_init01(struct svs_platform *svsp)
ret = regulator_enable(svsb->buck);
if (ret) {
dev_err(svsb->dev, "%s enable fail: %d\n",
- svsb->buck_name, ret);
+ bdata->buck_name, ret);
goto svs_init01_resume_cpuidle;
}
@@ -1393,6 +1488,7 @@ static int svs_init01(struct svs_platform *svsp)
*/
for (idx = 0; idx < svsp->bank_max; idx++) {
svsb = &svsp->banks[idx];
+ bdata = &svsb->pdata;
if (!(svsb->mode_support & SVSB_MODE_INIT01))
continue;
@@ -1402,11 +1498,11 @@ static int svs_init01(struct svs_platform *svsp)
* fix to that freq until svs_init01 is done.
*/
search_done = false;
- opp_vboot = svs_bank_volt_to_opp_volt(svsb->vboot,
- svsb->volt_step,
- svsb->volt_base);
+ opp_vboot = svs_bank_volt_to_opp_volt(bdata->vboot,
+ bdata->volt_step,
+ bdata->volt_base);
- for (i = 0; i < svsb->opp_count; i++) {
+ for (i = 0; i < bdata->opp_count; i++) {
opp_freq = svsb->opp_dfreq[i];
if (!search_done && svsb->opp_dvolt[i] <= opp_vboot) {
ret = dev_pm_opp_adjust_voltage(svsb->opp_dev,
@@ -1438,13 +1534,14 @@ static int svs_init01(struct svs_platform *svsp)
/* Svs bank init01 begins */
for (idx = 0; idx < svsp->bank_max; idx++) {
svsb = &svsp->banks[idx];
+ bdata = &svsb->pdata;
if (!(svsb->mode_support & SVSB_MODE_INIT01))
continue;
- opp_vboot = svs_bank_volt_to_opp_volt(svsb->vboot,
- svsb->volt_step,
- svsb->volt_base);
+ opp_vboot = svs_bank_volt_to_opp_volt(bdata->vboot,
+ bdata->volt_step,
+ bdata->volt_base);
buck_volt = regulator_get_voltage(svsb->buck);
if (buck_volt != opp_vboot) {
@@ -1456,8 +1553,7 @@ static int svs_init01(struct svs_platform *svsp)
}
spin_lock_irqsave(&svs_lock, flags);
- svsp->pbank = svsb;
- svs_set_bank_phase(svsp, SVSB_PHASE_INIT01);
+ svs_set_bank_phase(svsp, idx, SVSB_PHASE_INIT01);
spin_unlock_irqrestore(&svs_lock, flags);
time_left = wait_for_completion_timeout(&svsb->init_completion,
@@ -1472,11 +1568,12 @@ static int svs_init01(struct svs_platform *svsp)
svs_init01_finish:
for (idx = 0; idx < svsp->bank_max; idx++) {
svsb = &svsp->banks[idx];
+ bdata = &svsb->pdata;
if (!(svsb->mode_support & SVSB_MODE_INIT01))
continue;
- for (i = 0; i < svsb->opp_count; i++) {
+ for (i = 0; i < bdata->opp_count; i++) {
r = dev_pm_opp_enable(svsb->opp_dev,
svsb->opp_dfreq[i]);
if (r)
@@ -1502,7 +1599,7 @@ svs_init01_finish:
r = regulator_disable(svsb->buck);
if (r)
dev_err(svsb->dev, "%s disable fail: %d\n",
- svsb->buck_name, r);
+ bdata->buck_name, r);
}
svs_init01_resume_cpuidle:
@@ -1513,11 +1610,15 @@ svs_init01_resume_cpuidle:
static int svs_init02(struct svs_platform *svsp)
{
+ const struct svs_bank_pdata *bdata;
struct svs_bank *svsb;
unsigned long flags, time_left;
int ret;
u32 idx;
+ if (!svs_mode_available(svsp, SVSB_MODE_INIT02))
+ return 0;
+
for (idx = 0; idx < svsp->bank_max; idx++) {
svsb = &svsp->banks[idx];
@@ -1526,8 +1627,7 @@ static int svs_init02(struct svs_platform *svsp)
reinit_completion(&svsb->init_completion);
spin_lock_irqsave(&svs_lock, flags);
- svsp->pbank = svsb;
- svs_set_bank_phase(svsp, SVSB_PHASE_INIT02);
+ svs_set_bank_phase(svsp, idx, SVSB_PHASE_INIT02);
spin_unlock_irqrestore(&svs_lock, flags);
time_left = wait_for_completion_timeout(&svsb->init_completion,
@@ -1546,11 +1646,12 @@ static int svs_init02(struct svs_platform *svsp)
*/
for (idx = 0; idx < svsp->bank_max; idx++) {
svsb = &svsp->banks[idx];
+ bdata = &svsb->pdata;
if (!(svsb->mode_support & SVSB_MODE_INIT02))
continue;
- if (svsb->type == SVSB_HIGH || svsb->type == SVSB_LOW) {
+ if (bdata->type == SVSB_TYPE_HIGH || bdata->type == SVSB_TYPE_LOW) {
if (svs_sync_bank_volts_from_opp(svsb)) {
dev_err(svsb->dev, "sync volt fail\n");
ret = -EPERM;
@@ -1583,8 +1684,7 @@ static void svs_mon_mode(struct svs_platform *svsp)
continue;
spin_lock_irqsave(&svs_lock, flags);
- svsp->pbank = svsb;
- svs_set_bank_phase(svsp, SVSB_PHASE_MON);
+ svs_set_bank_phase(svsp, idx, SVSB_PHASE_MON);
spin_unlock_irqrestore(&svs_lock, flags);
}
}
@@ -1609,12 +1709,12 @@ static int svs_start(struct svs_platform *svsp)
static int svs_suspend(struct device *dev)
{
struct svs_platform *svsp = dev_get_drvdata(dev);
- struct svs_bank *svsb;
int ret;
u32 idx;
for (idx = 0; idx < svsp->bank_max; idx++) {
- svsb = &svsp->banks[idx];
+ struct svs_bank *svsb = &svsp->banks[idx];
+
svs_bank_disable_and_restore_default_volts(svsp, svsb);
}
@@ -1665,6 +1765,7 @@ out_of_resume:
static int svs_bank_resource_setup(struct svs_platform *svsp)
{
+ const struct svs_bank_pdata *bdata;
struct svs_bank *svsb;
struct dev_pm_opp *opp;
unsigned long freq;
@@ -1675,35 +1776,23 @@ static int svs_bank_resource_setup(struct svs_platform *svsp)
for (idx = 0; idx < svsp->bank_max; idx++) {
svsb = &svsp->banks[idx];
+ bdata = &svsb->pdata;
- switch (svsb->sw_id) {
- case SVSB_CPU_LITTLE:
- svsb->name = "SVSB_CPU_LITTLE";
- break;
- case SVSB_CPU_BIG:
- svsb->name = "SVSB_CPU_BIG";
- break;
- case SVSB_CCI:
- svsb->name = "SVSB_CCI";
- break;
- case SVSB_GPU:
- if (svsb->type == SVSB_HIGH)
- svsb->name = "SVSB_GPU_HIGH";
- else if (svsb->type == SVSB_LOW)
- svsb->name = "SVSB_GPU_LOW";
- else
- svsb->name = "SVSB_GPU";
- break;
- default:
- dev_err(svsb->dev, "unknown sw_id: %u\n", svsb->sw_id);
+ if (bdata->sw_id >= SVSB_SWID_MAX || bdata->type >= SVSB_TYPE_MAX) {
+ dev_err(svsb->dev, "unknown bank sw_id or type\n");
return -EINVAL;
}
- svsb->dev = devm_kzalloc(svsp->dev, sizeof(*svsb->dev),
- GFP_KERNEL);
+ svsb->dev = devm_kzalloc(svsp->dev, sizeof(*svsb->dev), GFP_KERNEL);
if (!svsb->dev)
return -ENOMEM;
+ svsb->name = devm_kasprintf(svsp->dev, GFP_KERNEL, "%s%s",
+ svs_swid_names[bdata->sw_id],
+ svs_type_names[bdata->type]);
+ if (!svsb->name)
+ return -ENOMEM;
+
ret = dev_set_name(svsb->dev, "%s", svsb->name);
if (ret)
return ret;
@@ -1721,32 +1810,32 @@ static int svs_bank_resource_setup(struct svs_platform *svsp)
if (svsb->mode_support & SVSB_MODE_INIT01) {
svsb->buck = devm_regulator_get_optional(svsb->opp_dev,
- svsb->buck_name);
+ bdata->buck_name);
if (IS_ERR(svsb->buck)) {
dev_err(svsb->dev, "cannot get \"%s-supply\"\n",
- svsb->buck_name);
+ bdata->buck_name);
return PTR_ERR(svsb->buck);
}
}
- if (!IS_ERR_OR_NULL(svsb->tzone_name)) {
- svsb->tzd = thermal_zone_get_zone_by_name(svsb->tzone_name);
+ if (!IS_ERR_OR_NULL(bdata->tzone_name)) {
+ svsb->tzd = thermal_zone_get_zone_by_name(bdata->tzone_name);
if (IS_ERR(svsb->tzd)) {
dev_err(svsb->dev, "cannot get \"%s\" thermal zone\n",
- svsb->tzone_name);
+ bdata->tzone_name);
return PTR_ERR(svsb->tzd);
}
}
count = dev_pm_opp_get_opp_count(svsb->opp_dev);
- if (svsb->opp_count != count) {
+ if (bdata->opp_count != count) {
dev_err(svsb->dev,
"opp_count not \"%u\" but get \"%d\"?\n",
- svsb->opp_count, count);
+ bdata->opp_count, count);
return count;
}
- for (i = 0, freq = U32_MAX; i < svsb->opp_count; i++, freq--) {
+ for (i = 0, freq = ULONG_MAX; i < bdata->opp_count; i++, freq--) {
opp = dev_pm_opp_find_freq_floor(svsb->opp_dev, &freq);
if (IS_ERR(opp)) {
dev_err(svsb->dev, "cannot find freq = %ld\n",
@@ -1780,8 +1869,6 @@ static int svs_get_efuse_data(struct svs_platform *svsp,
*svsp_efuse = nvmem_cell_read(cell, svsp_efuse_max);
if (IS_ERR(*svsp_efuse)) {
- dev_err(svsp->dev, "cannot read \"%s\" efuse: %ld\n",
- nvmem_cell_name, PTR_ERR(*svsp_efuse));
nvmem_cell_put(cell);
return PTR_ERR(*svsp_efuse);
}
@@ -1792,139 +1879,91 @@ static int svs_get_efuse_data(struct svs_platform *svsp,
return 0;
}
-static bool svs_mt8192_efuse_parsing(struct svs_platform *svsp)
+static u32 svs_get_fuse_val(u32 *fuse_array, const struct svs_fusemap *fmap, u8 nbits)
{
- struct svs_bank *svsb;
- u32 idx, i, vmin, golden_temp;
- int ret;
-
- for (i = 0; i < svsp->efuse_max; i++)
- if (svsp->efuse[i])
- dev_info(svsp->dev, "M_HW_RES%d: 0x%08x\n",
- i, svsp->efuse[i]);
-
- if (!svsp->efuse[9]) {
- dev_notice(svsp->dev, "svs_efuse[9] = 0x0?\n");
- return false;
- }
-
- /* Svs efuse parsing */
- vmin = (svsp->efuse[19] >> 4) & GENMASK(1, 0);
-
- for (idx = 0; idx < svsp->bank_max; idx++) {
- svsb = &svsp->banks[idx];
+ u32 val;
- if (vmin == 0x1)
- svsb->vmin = 0x1e;
-
- if (svsb->type == SVSB_LOW) {
- svsb->mtdes = svsp->efuse[10] & GENMASK(7, 0);
- svsb->bdes = (svsp->efuse[10] >> 16) & GENMASK(7, 0);
- svsb->mdes = (svsp->efuse[10] >> 24) & GENMASK(7, 0);
- svsb->dcbdet = (svsp->efuse[17]) & GENMASK(7, 0);
- svsb->dcmdet = (svsp->efuse[17] >> 8) & GENMASK(7, 0);
- } else if (svsb->type == SVSB_HIGH) {
- svsb->mtdes = svsp->efuse[9] & GENMASK(7, 0);
- svsb->bdes = (svsp->efuse[9] >> 16) & GENMASK(7, 0);
- svsb->mdes = (svsp->efuse[9] >> 24) & GENMASK(7, 0);
- svsb->dcbdet = (svsp->efuse[17] >> 16) & GENMASK(7, 0);
- svsb->dcmdet = (svsp->efuse[17] >> 24) & GENMASK(7, 0);
- }
+ if (fmap->index < 0)
+ return FUSE_DATA_NOT_VALID;
- svsb->vmax += svsb->dvt_fixed;
- }
+ val = fuse_array[fmap->index] >> fmap->ofst;
+ val &= GENMASK(nbits - 1, 0);
- ret = svs_get_efuse_data(svsp, "t-calibration-data",
- &svsp->tefuse, &svsp->tefuse_max);
- if (ret)
- return false;
+ return val;
+}
- for (i = 0; i < svsp->tefuse_max; i++)
- if (svsp->tefuse[i] != 0)
- break;
+static bool svs_is_available(struct svs_platform *svsp)
+{
+ int i, num_populated = 0;
- if (i == svsp->tefuse_max)
- golden_temp = 50; /* All thermal efuse data are 0 */
- else
- golden_temp = (svsp->tefuse[0] >> 24) & GENMASK(7, 0);
+ /* If at least two fuse arrays are populated, SVS is calibrated */
+ for (i = 0; i < svsp->efuse_max; i++) {
+ if (svsp->efuse[i])
+ num_populated++;
- for (idx = 0; idx < svsp->bank_max; idx++) {
- svsb = &svsp->banks[idx];
- svsb->mts = 500;
- svsb->bts = (((500 * golden_temp + 250460) / 1000) - 25) * 4;
+ if (num_populated > 1)
+ return true;
}
- return true;
+ return false;
}
-static bool svs_mt8188_efuse_parsing(struct svs_platform *svsp)
+static bool svs_common_parse_efuse(struct svs_platform *svsp,
+ const struct svs_platform_data *pdata)
{
- struct svs_bank *svsb;
- u32 idx, i, golden_temp;
- int ret;
-
- for (i = 0; i < svsp->efuse_max; i++)
- if (svsp->efuse[i])
- dev_info(svsp->dev, "M_HW_RES%d: 0x%08x\n",
- i, svsp->efuse[i]);
+ const struct svs_fusemap *gfmap = pdata->glb_fuse_map;
+ struct svs_fusemap tfm = { 0, 24 };
+ u32 golden_temp, val;
+ u8 ft_pgm, vmin;
+ int i;
- if (!svsp->efuse[5]) {
- dev_notice(svsp->dev, "svs_efuse[5] = 0x0?\n");
+ if (!svs_is_available(svsp))
return false;
- }
- /* Svs efuse parsing */
- for (idx = 0; idx < svsp->bank_max; idx++) {
- svsb = &svsp->banks[idx];
+ /* Get golden temperature from SVS-Thermal calibration */
+ val = svs_get_fuse_val(svsp->tefuse, &tfm, 8);
- if (svsb->type == SVSB_LOW) {
- svsb->mtdes = svsp->efuse[5] & GENMASK(7, 0);
- svsb->bdes = (svsp->efuse[5] >> 16) & GENMASK(7, 0);
- svsb->mdes = (svsp->efuse[5] >> 24) & GENMASK(7, 0);
- svsb->dcbdet = (svsp->efuse[15] >> 16) & GENMASK(7, 0);
- svsb->dcmdet = (svsp->efuse[15] >> 24) & GENMASK(7, 0);
- } else if (svsb->type == SVSB_HIGH) {
- svsb->mtdes = svsp->efuse[4] & GENMASK(7, 0);
- svsb->bdes = (svsp->efuse[4] >> 16) & GENMASK(7, 0);
- svsb->mdes = (svsp->efuse[4] >> 24) & GENMASK(7, 0);
- svsb->dcbdet = svsp->efuse[14] & GENMASK(7, 0);
- svsb->dcmdet = (svsp->efuse[14] >> 8) & GENMASK(7, 0);
- }
+ /* If golden temp is not programmed, use the default of 50 */
+ golden_temp = val ? val : 50;
- svsb->vmax += svsb->dvt_fixed;
- }
+ /* Parse fused SVS calibration */
+ ft_pgm = svs_get_fuse_val(svsp->efuse, &gfmap[GLB_FT_PGM], 8);
+ vmin = svs_get_fuse_val(svsp->efuse, &gfmap[GLB_VMIN], 2);
- ret = svs_get_efuse_data(svsp, "t-calibration-data",
- &svsp->tefuse, &svsp->tefuse_max);
- if (ret)
- return false;
+ for (i = 0; i < svsp->bank_max; i++) {
+ struct svs_bank *svsb = &svsp->banks[i];
+ const struct svs_bank_pdata *bdata = &svsb->pdata;
+ const struct svs_fusemap *dfmap = bdata->dev_fuse_map;
- for (i = 0; i < svsp->tefuse_max; i++)
- if (svsp->tefuse[i] != 0)
- break;
+ if (vmin == 1)
+ svsb->vmin = 0x1e;
- if (i == svsp->tefuse_max)
- golden_temp = 50; /* All thermal efuse data are 0 */
- else
- golden_temp = (svsp->tefuse[0] >> 24) & GENMASK(7, 0);
+ if (ft_pgm == 0)
+ svsb->volt_flags |= SVSB_INIT01_VOLT_IGNORE;
- for (idx = 0; idx < svsp->bank_max; idx++) {
- svsb = &svsp->banks[idx];
- svsb->mts = 500;
- svsb->bts = (((500 * golden_temp + 250460) / 1000) - 25) * 4;
+ svsb->mtdes = svs_get_fuse_val(svsp->efuse, &dfmap[BDEV_MTDES], 8);
+ svsb->bdes = svs_get_fuse_val(svsp->efuse, &dfmap[BDEV_BDES], 8);
+ svsb->mdes = svs_get_fuse_val(svsp->efuse, &dfmap[BDEV_MDES], 8);
+ svsb->dcbdet = svs_get_fuse_val(svsp->efuse, &dfmap[BDEV_DCBDET], 8);
+ svsb->dcmdet = svs_get_fuse_val(svsp->efuse, &dfmap[BDEV_DCMDET], 8);
+ svsb->vmax += svsb->dvt_fixed;
+
+ svsb->mts = (svsp->ts_coeff * 2) / 1000;
+ svsb->bts = (((500 * golden_temp + svsp->ts_coeff) / 1000) - 25) * 4;
}
return true;
}
-static bool svs_mt8183_efuse_parsing(struct svs_platform *svsp)
+static bool svs_mt8183_efuse_parsing(struct svs_platform *svsp,
+ const struct svs_platform_data *pdata)
{
struct svs_bank *svsb;
+ const struct svs_bank_pdata *bdata;
int format[6], x_roomt[6], o_vtsmcu[5], o_vtsabb, tb_roomt = 0;
int adc_ge_t, adc_oe_t, ge, oe, gain, degc_cali, adc_cali_en_t;
int o_slope, o_slope_sign, ts_id;
u32 idx, i, ft_pgm, mts, temp0, temp1, temp2;
- int ret;
for (i = 0; i < svsp->efuse_max; i++)
if (svsp->efuse[i])
@@ -1937,74 +1976,48 @@ static bool svs_mt8183_efuse_parsing(struct svs_platform *svsp)
}
/* Svs efuse parsing */
- ft_pgm = (svsp->efuse[0] >> 4) & GENMASK(3, 0);
+ ft_pgm = svs_get_fuse_val(svsp->efuse, &pdata->glb_fuse_map[GLB_FT_PGM], 4);
for (idx = 0; idx < svsp->bank_max; idx++) {
svsb = &svsp->banks[idx];
+ bdata = &svsb->pdata;
+ const struct svs_fusemap *dfmap = bdata->dev_fuse_map;
if (ft_pgm <= 1)
svsb->volt_flags |= SVSB_INIT01_VOLT_IGNORE;
- switch (svsb->sw_id) {
- case SVSB_CPU_LITTLE:
- svsb->bdes = svsp->efuse[16] & GENMASK(7, 0);
- svsb->mdes = (svsp->efuse[16] >> 8) & GENMASK(7, 0);
- svsb->dcbdet = (svsp->efuse[16] >> 16) & GENMASK(7, 0);
- svsb->dcmdet = (svsp->efuse[16] >> 24) & GENMASK(7, 0);
- svsb->mtdes = (svsp->efuse[17] >> 16) & GENMASK(7, 0);
+ svsb->mtdes = svs_get_fuse_val(svsp->efuse, &dfmap[BDEV_MTDES], 8);
+ svsb->bdes = svs_get_fuse_val(svsp->efuse, &dfmap[BDEV_BDES], 8);
+ svsb->mdes = svs_get_fuse_val(svsp->efuse, &dfmap[BDEV_MDES], 8);
+ svsb->dcbdet = svs_get_fuse_val(svsp->efuse, &dfmap[BDEV_DCBDET], 8);
+ svsb->dcmdet = svs_get_fuse_val(svsp->efuse, &dfmap[BDEV_DCMDET], 8);
+ switch (bdata->sw_id) {
+ case SVSB_SWID_CPU_LITTLE:
+ case SVSB_SWID_CCI:
if (ft_pgm <= 3)
svsb->volt_od += 10;
else
svsb->volt_od += 2;
break;
- case SVSB_CPU_BIG:
- svsb->bdes = svsp->efuse[18] & GENMASK(7, 0);
- svsb->mdes = (svsp->efuse[18] >> 8) & GENMASK(7, 0);
- svsb->dcbdet = (svsp->efuse[18] >> 16) & GENMASK(7, 0);
- svsb->dcmdet = (svsp->efuse[18] >> 24) & GENMASK(7, 0);
- svsb->mtdes = svsp->efuse[17] & GENMASK(7, 0);
-
+ case SVSB_SWID_CPU_BIG:
if (ft_pgm <= 3)
svsb->volt_od += 15;
else
svsb->volt_od += 12;
break;
- case SVSB_CCI:
- svsb->bdes = svsp->efuse[4] & GENMASK(7, 0);
- svsb->mdes = (svsp->efuse[4] >> 8) & GENMASK(7, 0);
- svsb->dcbdet = (svsp->efuse[4] >> 16) & GENMASK(7, 0);
- svsb->dcmdet = (svsp->efuse[4] >> 24) & GENMASK(7, 0);
- svsb->mtdes = (svsp->efuse[5] >> 16) & GENMASK(7, 0);
-
- if (ft_pgm <= 3)
- svsb->volt_od += 10;
- else
- svsb->volt_od += 2;
- break;
- case SVSB_GPU:
- svsb->bdes = svsp->efuse[6] & GENMASK(7, 0);
- svsb->mdes = (svsp->efuse[6] >> 8) & GENMASK(7, 0);
- svsb->dcbdet = (svsp->efuse[6] >> 16) & GENMASK(7, 0);
- svsb->dcmdet = (svsp->efuse[6] >> 24) & GENMASK(7, 0);
- svsb->mtdes = svsp->efuse[5] & GENMASK(7, 0);
-
- if (ft_pgm >= 2) {
+ case SVSB_SWID_GPU:
+ if (ft_pgm != FUSE_DATA_NOT_VALID && ft_pgm >= 2) {
svsb->freq_base = 800000000; /* 800MHz */
svsb->dvt_fixed = 2;
}
break;
default:
- dev_err(svsb->dev, "unknown sw_id: %u\n", svsb->sw_id);
+ dev_err(svsb->dev, "unknown sw_id: %u\n", bdata->sw_id);
return false;
}
}
- ret = svs_get_efuse_data(svsp, "t-calibration-data",
- &svsp->tefuse, &svsp->tefuse_max);
- if (ret)
- return false;
-
/* Thermal efuse parsing */
adc_ge_t = (svsp->tefuse[1] >> 22) & GENMASK(9, 0);
adc_oe_t = (svsp->tefuse[1] >> 12) & GENMASK(9, 0);
@@ -2064,23 +2077,24 @@ static bool svs_mt8183_efuse_parsing(struct svs_platform *svsp)
for (idx = 0; idx < svsp->bank_max; idx++) {
svsb = &svsp->banks[idx];
+ bdata = &svsb->pdata;
svsb->mts = mts;
- switch (svsb->sw_id) {
- case SVSB_CPU_LITTLE:
+ switch (bdata->sw_id) {
+ case SVSB_SWID_CPU_LITTLE:
tb_roomt = x_roomt[3];
break;
- case SVSB_CPU_BIG:
+ case SVSB_SWID_CPU_BIG:
tb_roomt = x_roomt[4];
break;
- case SVSB_CCI:
+ case SVSB_SWID_CCI:
tb_roomt = x_roomt[3];
break;
- case SVSB_GPU:
+ case SVSB_SWID_GPU:
tb_roomt = x_roomt[1];
break;
default:
- dev_err(svsb->dev, "unknown sw_id: %u\n", svsb->sw_id);
+ dev_err(svsb->dev, "unknown sw_id: %u\n", bdata->sw_id);
goto remove_mt8183_svsb_mon_mode;
}
@@ -2153,7 +2167,6 @@ static struct device *svs_add_device_link(struct svs_platform *svsp,
static int svs_mt8192_platform_probe(struct svs_platform *svsp)
{
struct device *dev;
- struct svs_bank *svsb;
u32 idx;
svsp->rst = devm_reset_control_get_optional(svsp->dev, "svs_rst");
@@ -2161,18 +2174,33 @@ static int svs_mt8192_platform_probe(struct svs_platform *svsp)
return dev_err_probe(svsp->dev, PTR_ERR(svsp->rst),
"cannot get svs reset control\n");
- dev = svs_add_device_link(svsp, "lvts");
+ dev = svs_add_device_link(svsp, "thermal-sensor");
if (IS_ERR(dev))
return dev_err_probe(svsp->dev, PTR_ERR(dev),
"failed to get lvts device\n");
for (idx = 0; idx < svsp->bank_max; idx++) {
- svsb = &svsp->banks[idx];
+ struct svs_bank *svsb = &svsp->banks[idx];
+ const struct svs_bank_pdata *bdata = &svsb->pdata;
- if (svsb->type == SVSB_HIGH)
- svsb->opp_dev = svs_add_device_link(svsp, "gpu");
- else if (svsb->type == SVSB_LOW)
- svsb->opp_dev = svs_get_subsys_device(svsp, "gpu");
+ switch (bdata->sw_id) {
+ case SVSB_SWID_CPU_LITTLE:
+ case SVSB_SWID_CPU_BIG:
+ svsb->opp_dev = get_cpu_device(bdata->cpu_id);
+ break;
+ case SVSB_SWID_CCI:
+ svsb->opp_dev = svs_add_device_link(svsp, "cci");
+ break;
+ case SVSB_SWID_GPU:
+ if (bdata->type == SVSB_TYPE_LOW)
+ svsb->opp_dev = svs_get_subsys_device(svsp, "gpu");
+ else
+ svsb->opp_dev = svs_add_device_link(svsp, "gpu");
+ break;
+ default:
+ dev_err(svsb->dev, "unknown sw_id: %u\n", bdata->sw_id);
+ return -EINVAL;
+ }
if (IS_ERR(svsb->opp_dev))
return dev_err_probe(svsp->dev, PTR_ERR(svsb->opp_dev),
@@ -2186,30 +2214,30 @@ static int svs_mt8192_platform_probe(struct svs_platform *svsp)
static int svs_mt8183_platform_probe(struct svs_platform *svsp)
{
struct device *dev;
- struct svs_bank *svsb;
u32 idx;
- dev = svs_add_device_link(svsp, "thermal");
+ dev = svs_add_device_link(svsp, "thermal-sensor");
if (IS_ERR(dev))
return dev_err_probe(svsp->dev, PTR_ERR(dev),
"failed to get thermal device\n");
for (idx = 0; idx < svsp->bank_max; idx++) {
- svsb = &svsp->banks[idx];
+ struct svs_bank *svsb = &svsp->banks[idx];
+ const struct svs_bank_pdata *bdata = &svsb->pdata;
- switch (svsb->sw_id) {
- case SVSB_CPU_LITTLE:
- case SVSB_CPU_BIG:
- svsb->opp_dev = get_cpu_device(svsb->cpu_id);
+ switch (bdata->sw_id) {
+ case SVSB_SWID_CPU_LITTLE:
+ case SVSB_SWID_CPU_BIG:
+ svsb->opp_dev = get_cpu_device(bdata->cpu_id);
break;
- case SVSB_CCI:
+ case SVSB_SWID_CCI:
svsb->opp_dev = svs_add_device_link(svsp, "cci");
break;
- case SVSB_GPU:
+ case SVSB_SWID_GPU:
svsb->opp_dev = svs_add_device_link(svsp, "gpu");
break;
default:
- dev_err(svsb->dev, "unknown sw_id: %u\n", svsb->sw_id);
+ dev_err(svsb->dev, "unknown sw_id: %u\n", bdata->sw_id);
return -EINVAL;
}
@@ -2222,241 +2250,544 @@ static int svs_mt8183_platform_probe(struct svs_platform *svsp)
return 0;
}
+static struct svs_bank svs_mt8195_banks[] = {
+ {
+ .pdata = (const struct svs_bank_pdata) {
+ .sw_id = SVSB_SWID_GPU,
+ .type = SVSB_TYPE_LOW,
+ .set_freq_pct = svs_set_bank_freq_pct_v3,
+ .get_volts = svs_get_bank_volts_v3,
+ .opp_count = MAX_OPP_ENTRIES,
+ .turn_freq_base = 640000000,
+ .volt_step = 6250,
+ .volt_base = 400000,
+ .age_config = 0x555555,
+ .dc_config = 0x1,
+ .vco = 0x18,
+ .chk_shift = 0x87,
+ .int_st = BIT(0),
+ .ctl0 = 0x00540003,
+ .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) {
+ { 10, 16 }, { 10, 24 }, { 10, 0 }, { 8, 0 }, { 8, 8 }
+ }
+ },
+ .mode_support = SVSB_MODE_INIT02,
+ .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT,
+ .freq_base = 640000000,
+ .core_sel = 0x0fff0100,
+ .dvt_fixed = 0x1,
+ .vmax = 0x38,
+ .vmin = 0x14,
+ },
+ {
+ .pdata = (const struct svs_bank_pdata) {
+ .sw_id = SVSB_SWID_GPU,
+ .type = SVSB_TYPE_HIGH,
+ .set_freq_pct = svs_set_bank_freq_pct_v3,
+ .get_volts = svs_get_bank_volts_v3,
+ .tzone_name = "gpu",
+ .opp_count = MAX_OPP_ENTRIES,
+ .turn_freq_base = 640000000,
+ .volt_step = 6250,
+ .volt_base = 400000,
+ .age_config = 0x555555,
+ .dc_config = 0x1,
+ .vco = 0x18,
+ .chk_shift = 0x87,
+ .int_st = BIT(1),
+ .ctl0 = 0x00540003,
+ .tzone_htemp = 85000,
+ .tzone_htemp_voffset = 0,
+ .tzone_ltemp = 25000,
+ .tzone_ltemp_voffset = 7,
+ .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) {
+ { 9, 16 }, { 9, 24 }, { 9, 0 }, { 8, 0 }, { 8, 8 }
+ },
+ },
+ .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT | SVSB_MON_VOLT_IGNORE,
+ .mode_support = SVSB_MODE_INIT02 | SVSB_MODE_MON,
+ .freq_base = 880000000,
+ .core_sel = 0x0fff0101,
+ .dvt_fixed = 0x6,
+ .vmax = 0x38,
+ .vmin = 0x14,
+ },
+};
+
static struct svs_bank svs_mt8192_banks[] = {
{
- .sw_id = SVSB_GPU,
- .type = SVSB_LOW,
- .set_freq_pct = svs_set_bank_freq_pct_v3,
- .get_volts = svs_get_bank_volts_v3,
- .tzone_name = "gpu1",
- .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT,
- .mode_support = SVSB_MODE_INIT02,
- .opp_count = MAX_OPP_ENTRIES,
- .freq_base = 688000000,
- .turn_freq_base = 688000000,
- .volt_step = 6250,
- .volt_base = 400000,
- .vmax = 0x60,
- .vmin = 0x1a,
- .age_config = 0x555555,
- .dc_config = 0x1,
- .dvt_fixed = 0x1,
- .vco = 0x18,
- .chk_shift = 0x87,
- .core_sel = 0x0fff0100,
- .int_st = BIT(0),
- .ctl0 = 0x00540003,
- .tzone_htemp = 85000,
- .tzone_htemp_voffset = 0,
- .tzone_ltemp = 25000,
- .tzone_ltemp_voffset = 7,
+ .pdata = (const struct svs_bank_pdata) {
+ .sw_id = SVSB_SWID_GPU,
+ .type = SVSB_TYPE_LOW,
+ .set_freq_pct = svs_set_bank_freq_pct_v3,
+ .get_volts = svs_get_bank_volts_v3,
+ .tzone_name = "gpu",
+ .opp_count = MAX_OPP_ENTRIES,
+ .turn_freq_base = 688000000,
+ .volt_step = 6250,
+ .volt_base = 400000,
+ .age_config = 0x555555,
+ .dc_config = 0x1,
+ .vco = 0x18,
+ .chk_shift = 0x87,
+ .int_st = BIT(0),
+ .ctl0 = 0x00540003,
+ .tzone_htemp = 85000,
+ .tzone_htemp_voffset = 0,
+ .tzone_ltemp = 25000,
+ .tzone_ltemp_voffset = 7,
+ .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) {
+ { 10, 16 }, { 10, 24 }, { 10, 0 }, { 17, 0 }, { 17, 8 }
+ }
+ },
+ .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT,
+ .mode_support = SVSB_MODE_INIT02,
+ .freq_base = 688000000,
+ .core_sel = 0x0fff0100,
+ .dvt_fixed = 0x1,
+ .vmax = 0x60,
+ .vmin = 0x1a,
},
{
- .sw_id = SVSB_GPU,
- .type = SVSB_HIGH,
- .set_freq_pct = svs_set_bank_freq_pct_v3,
- .get_volts = svs_get_bank_volts_v3,
- .tzone_name = "gpu1",
- .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT |
- SVSB_MON_VOLT_IGNORE,
- .mode_support = SVSB_MODE_INIT02 | SVSB_MODE_MON,
- .opp_count = MAX_OPP_ENTRIES,
- .freq_base = 902000000,
- .turn_freq_base = 688000000,
- .volt_step = 6250,
- .volt_base = 400000,
- .vmax = 0x60,
- .vmin = 0x1a,
- .age_config = 0x555555,
- .dc_config = 0x1,
- .dvt_fixed = 0x6,
- .vco = 0x18,
- .chk_shift = 0x87,
- .core_sel = 0x0fff0101,
- .int_st = BIT(1),
- .ctl0 = 0x00540003,
- .tzone_htemp = 85000,
- .tzone_htemp_voffset = 0,
- .tzone_ltemp = 25000,
- .tzone_ltemp_voffset = 7,
+ .pdata = (const struct svs_bank_pdata) {
+ .sw_id = SVSB_SWID_GPU,
+ .type = SVSB_TYPE_HIGH,
+ .set_freq_pct = svs_set_bank_freq_pct_v3,
+ .get_volts = svs_get_bank_volts_v3,
+ .tzone_name = "gpu",
+ .opp_count = MAX_OPP_ENTRIES,
+ .turn_freq_base = 688000000,
+ .volt_step = 6250,
+ .volt_base = 400000,
+ .age_config = 0x555555,
+ .dc_config = 0x1,
+ .vco = 0x18,
+ .chk_shift = 0x87,
+ .int_st = BIT(1),
+ .ctl0 = 0x00540003,
+ .tzone_htemp = 85000,
+ .tzone_htemp_voffset = 0,
+ .tzone_ltemp = 25000,
+ .tzone_ltemp_voffset = 7,
+ .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) {
+ { 9, 16 }, { 9, 24 }, { 17, 0 }, { 17, 16 }, { 17, 24 }
+ }
+ },
+ .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT | SVSB_MON_VOLT_IGNORE,
+ .mode_support = SVSB_MODE_INIT02 | SVSB_MODE_MON,
+ .freq_base = 902000000,
+ .core_sel = 0x0fff0101,
+ .dvt_fixed = 0x6,
+ .vmax = 0x60,
+ .vmin = 0x1a,
},
};
static struct svs_bank svs_mt8188_banks[] = {
{
- .sw_id = SVSB_GPU,
- .type = SVSB_LOW,
- .set_freq_pct = svs_set_bank_freq_pct_v3,
- .get_volts = svs_get_bank_volts_v3,
- .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT,
- .mode_support = SVSB_MODE_INIT02,
- .opp_count = MAX_OPP_ENTRIES,
- .freq_base = 640000000,
- .turn_freq_base = 640000000,
- .volt_step = 6250,
- .volt_base = 400000,
- .vmax = 0x38,
- .vmin = 0x1c,
- .age_config = 0x555555,
- .dc_config = 0x555555,
- .dvt_fixed = 0x1,
- .vco = 0x10,
- .chk_shift = 0x87,
- .core_sel = 0x0fff0000,
- .int_st = BIT(0),
- .ctl0 = 0x00100003,
+ .pdata = (const struct svs_bank_pdata) {
+ .sw_id = SVSB_SWID_GPU,
+ .type = SVSB_TYPE_LOW,
+ .set_freq_pct = svs_set_bank_freq_pct_v3,
+ .get_volts = svs_get_bank_volts_v3,
+ .opp_count = MAX_OPP_ENTRIES,
+ .turn_freq_base = 640000000,
+ .volt_step = 6250,
+ .volt_base = 400000,
+ .age_config = 0x555555,
+ .dc_config = 0x555555,
+ .vco = 0x10,
+ .chk_shift = 0x87,
+ .int_st = BIT(0),
+ .ctl0 = 0x00100003,
+ .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) {
+ { 5, 16 }, { 5, 24 }, { 5, 0 }, { 15, 16 }, { 15, 24 }
+ }
+ },
+ .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT,
+ .mode_support = SVSB_MODE_INIT02,
+ .freq_base = 640000000,
+ .core_sel = 0x0fff0000,
+ .dvt_fixed = 0x1,
+ .vmax = 0x38,
+ .vmin = 0x1c,
+ },
+ {
+ .pdata = (const struct svs_bank_pdata) {
+ .sw_id = SVSB_SWID_GPU,
+ .type = SVSB_TYPE_HIGH,
+ .set_freq_pct = svs_set_bank_freq_pct_v3,
+ .get_volts = svs_get_bank_volts_v3,
+ .tzone_name = "gpu",
+ .opp_count = MAX_OPP_ENTRIES,
+ .turn_freq_base = 640000000,
+ .volt_step = 6250,
+ .volt_base = 400000,
+ .age_config = 0x555555,
+ .dc_config = 0x555555,
+ .vco = 0x10,
+ .chk_shift = 0x87,
+ .int_st = BIT(1),
+ .ctl0 = 0x00100003,
+ .tzone_htemp = 85000,
+ .tzone_htemp_voffset = 0,
+ .tzone_ltemp = 25000,
+ .tzone_ltemp_voffset = 7,
+ .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) {
+ { 4, 16 }, { 4, 24 }, { 4, 0 }, { 14, 0 }, { 14, 8 }
+ }
+ },
+ .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT | SVSB_MON_VOLT_IGNORE,
+ .mode_support = SVSB_MODE_INIT02 | SVSB_MODE_MON,
+ .freq_base = 880000000,
+ .core_sel = 0x0fff0001,
+ .dvt_fixed = 0x4,
+ .vmax = 0x38,
+ .vmin = 0x1c,
+ },
+};
+
+static struct svs_bank svs_mt8186_banks[] = {
+ {
+ .pdata = (const struct svs_bank_pdata) {
+ .sw_id = SVSB_SWID_CPU_BIG,
+ .type = SVSB_TYPE_LOW,
+ .set_freq_pct = svs_set_bank_freq_pct_v3,
+ .get_volts = svs_get_bank_volts_v3,
+ .cpu_id = 6,
+ .opp_count = MAX_OPP_ENTRIES,
+ .turn_freq_base = 1670000000,
+ .volt_step = 6250,
+ .volt_base = 400000,
+ .age_config = 0x1,
+ .dc_config = 0x1,
+ .vco = 0x10,
+ .chk_shift = 0x87,
+ .int_st = BIT(0),
+ .ctl0 = 0x00540003,
+ .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) {
+ { 3, 16 }, { 3, 24 }, { 3, 0 }, { 14, 16 }, { 14, 24 }
+ }
+ },
+ .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT,
+ .volt_od = 4,
+ .mode_support = SVSB_MODE_INIT02,
+ .freq_base = 1670000000,
+ .core_sel = 0x0fff0100,
+ .dvt_fixed = 0x3,
+ .vmax = 0x59,
+ .vmin = 0x20,
+ },
+ {
+ .pdata = (const struct svs_bank_pdata) {
+ .sw_id = SVSB_SWID_CPU_BIG,
+ .type = SVSB_TYPE_HIGH,
+ .set_freq_pct = svs_set_bank_freq_pct_v3,
+ .get_volts = svs_get_bank_volts_v3,
+ .cpu_id = 6,
+ .tzone_name = "cpu-big",
+ .opp_count = MAX_OPP_ENTRIES,
+ .turn_freq_base = 1670000000,
+ .volt_step = 6250,
+ .volt_base = 400000,
+ .age_config = 0x1,
+ .dc_config = 0x1,
+ .vco = 0x10,
+ .chk_shift = 0x87,
+ .int_st = BIT(1),
+ .ctl0 = 0x00540003,
+ .tzone_htemp = 85000,
+ .tzone_htemp_voffset = 8,
+ .tzone_ltemp = 25000,
+ .tzone_ltemp_voffset = 8,
+ .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) {
+ { 2, 16 }, { 2, 24 }, { 2, 0 }, { 13, 0 }, { 13, 8 }
+ }
+ },
+ .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT | SVSB_MON_VOLT_IGNORE,
+ .volt_od = 4,
+ .mode_support = SVSB_MODE_INIT02 | SVSB_MODE_MON,
+ .freq_base = 2050000000,
+ .core_sel = 0x0fff0101,
+ .dvt_fixed = 0x6,
+ .vmax = 0x73,
+ .vmin = 0x20,
+ },
+ {
+ .pdata = (const struct svs_bank_pdata) {
+ .sw_id = SVSB_SWID_CPU_LITTLE,
+ .set_freq_pct = svs_set_bank_freq_pct_v2,
+ .get_volts = svs_get_bank_volts_v2,
+ .cpu_id = 0,
+ .tzone_name = "cpu-little",
+ .opp_count = MAX_OPP_ENTRIES,
+ .volt_step = 6250,
+ .volt_base = 400000,
+ .age_config = 0x1,
+ .dc_config = 0x1,
+ .vco = 0x10,
+ .chk_shift = 0x87,
+ .int_st = BIT(2),
+ .ctl0 = 0x3210000f,
+ .tzone_htemp = 85000,
+ .tzone_htemp_voffset = 8,
+ .tzone_ltemp = 25000,
+ .tzone_ltemp_voffset = 8,
+ .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) {
+ { 4, 16 }, { 4, 24 }, { 4, 0 }, { 14, 0 }, { 14, 8 }
+ }
+ },
+ .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT | SVSB_MON_VOLT_IGNORE,
+ .volt_od = 3,
+ .mode_support = SVSB_MODE_INIT02 | SVSB_MODE_MON,
+ .freq_base = 2000000000,
+ .core_sel = 0x0fff0102,
+ .dvt_fixed = 0x6,
+ .vmax = 0x65,
+ .vmin = 0x20,
},
{
- .sw_id = SVSB_GPU,
- .type = SVSB_HIGH,
- .set_freq_pct = svs_set_bank_freq_pct_v3,
- .get_volts = svs_get_bank_volts_v3,
- .tzone_name = "gpu1",
- .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT |
- SVSB_MON_VOLT_IGNORE,
- .mode_support = SVSB_MODE_INIT02 | SVSB_MODE_MON,
- .opp_count = MAX_OPP_ENTRIES,
- .freq_base = 880000000,
- .turn_freq_base = 640000000,
- .volt_step = 6250,
- .volt_base = 400000,
- .vmax = 0x38,
- .vmin = 0x1c,
- .age_config = 0x555555,
- .dc_config = 0x555555,
- .dvt_fixed = 0x4,
- .vco = 0x10,
- .chk_shift = 0x87,
- .core_sel = 0x0fff0001,
- .int_st = BIT(1),
- .ctl0 = 0x00100003,
- .tzone_htemp = 85000,
- .tzone_htemp_voffset = 0,
- .tzone_ltemp = 25000,
- .tzone_ltemp_voffset = 7,
+ .pdata = (const struct svs_bank_pdata) {
+ .sw_id = SVSB_SWID_CCI,
+ .set_freq_pct = svs_set_bank_freq_pct_v2,
+ .get_volts = svs_get_bank_volts_v2,
+ .tzone_name = "cci",
+ .opp_count = MAX_OPP_ENTRIES,
+ .volt_step = 6250,
+ .volt_base = 400000,
+ .age_config = 0x1,
+ .dc_config = 0x1,
+ .vco = 0x10,
+ .chk_shift = 0x87,
+ .int_st = BIT(3),
+ .ctl0 = 0x3210000f,
+ .tzone_htemp = 85000,
+ .tzone_htemp_voffset = 8,
+ .tzone_ltemp = 25000,
+ .tzone_ltemp_voffset = 8,
+ .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) {
+ { 5, 16 }, { 5, 24 }, { 5, 0 }, { 15, 16 }, { 15, 24 }
+ }
+ },
+ .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT | SVSB_MON_VOLT_IGNORE,
+ .volt_od = 3,
+ .mode_support = SVSB_MODE_INIT02 | SVSB_MODE_MON,
+ .freq_base = 1400000000,
+ .core_sel = 0x0fff0103,
+ .dvt_fixed = 0x6,
+ .vmax = 0x65,
+ .vmin = 0x20,
+ },
+ {
+ .pdata = (const struct svs_bank_pdata) {
+ .sw_id = SVSB_SWID_GPU,
+ .set_freq_pct = svs_set_bank_freq_pct_v2,
+ .get_volts = svs_get_bank_volts_v2,
+ .tzone_name = "gpu",
+ .opp_count = MAX_OPP_ENTRIES,
+ .volt_step = 6250,
+ .volt_base = 400000,
+ .age_config = 0x555555,
+ .dc_config = 0x1,
+ .vco = 0x10,
+ .chk_shift = 0x87,
+ .int_st = BIT(4),
+ .ctl0 = 0x00100003,
+ .tzone_htemp = 85000,
+ .tzone_htemp_voffset = 8,
+ .tzone_ltemp = 25000,
+ .tzone_ltemp_voffset = 7,
+ .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) {
+ { 6, 16 }, { 6, 24 }, { 6, 0 }, { 15, 8 }, { 15, 0 }
+ }
+ },
+ .volt_flags = SVSB_REMOVE_DVTFIXED_VOLT | SVSB_MON_VOLT_IGNORE,
+ .mode_support = SVSB_MODE_INIT02 | SVSB_MODE_MON,
+ .freq_base = 850000000,
+ .core_sel = 0x0fff0104,
+ .dvt_fixed = 0x4,
+ .vmax = 0x58,
+ .vmin = 0x20,
},
};
static struct svs_bank svs_mt8183_banks[] = {
{
- .sw_id = SVSB_CPU_LITTLE,
- .set_freq_pct = svs_set_bank_freq_pct_v2,
- .get_volts = svs_get_bank_volts_v2,
- .cpu_id = 0,
- .buck_name = "proc",
- .volt_flags = SVSB_INIT01_VOLT_INC_ONLY,
- .mode_support = SVSB_MODE_INIT01 | SVSB_MODE_INIT02,
- .opp_count = MAX_OPP_ENTRIES,
- .freq_base = 1989000000,
- .vboot = 0x30,
- .volt_step = 6250,
- .volt_base = 500000,
- .vmax = 0x64,
- .vmin = 0x18,
- .age_config = 0x555555,
- .dc_config = 0x555555,
- .dvt_fixed = 0x7,
- .vco = 0x10,
- .chk_shift = 0x77,
- .core_sel = 0x8fff0000,
- .int_st = BIT(0),
- .ctl0 = 0x00010001,
+ .pdata = (const struct svs_bank_pdata) {
+ .sw_id = SVSB_SWID_CPU_LITTLE,
+ .set_freq_pct = svs_set_bank_freq_pct_v2,
+ .get_volts = svs_get_bank_volts_v2,
+ .cpu_id = 0,
+ .buck_name = "proc",
+ .opp_count = MAX_OPP_ENTRIES,
+ .vboot = 0x30,
+ .volt_step = 6250,
+ .volt_base = 500000,
+ .age_config = 0x555555,
+ .dc_config = 0x555555,
+ .vco = 0x10,
+ .chk_shift = 0x77,
+ .int_st = BIT(0),
+ .ctl0 = 0x00010001,
+ .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) {
+ { 16, 0 }, { 16, 8 }, { 17, 16 }, { 16, 16 }, { 16, 24 }
+ }
+ },
+ .volt_flags = SVSB_INIT01_VOLT_INC_ONLY,
+ .mode_support = SVSB_MODE_INIT01 | SVSB_MODE_INIT02,
+ .freq_base = 1989000000,
+ .core_sel = 0x8fff0000,
+ .dvt_fixed = 0x7,
+ .vmax = 0x64,
+ .vmin = 0x18,
+
},
{
- .sw_id = SVSB_CPU_BIG,
- .set_freq_pct = svs_set_bank_freq_pct_v2,
- .get_volts = svs_get_bank_volts_v2,
- .cpu_id = 4,
- .buck_name = "proc",
- .volt_flags = SVSB_INIT01_VOLT_INC_ONLY,
- .mode_support = SVSB_MODE_INIT01 | SVSB_MODE_INIT02,
- .opp_count = MAX_OPP_ENTRIES,
- .freq_base = 1989000000,
- .vboot = 0x30,
- .volt_step = 6250,
- .volt_base = 500000,
- .vmax = 0x58,
- .vmin = 0x10,
- .age_config = 0x555555,
- .dc_config = 0x555555,
- .dvt_fixed = 0x7,
- .vco = 0x10,
- .chk_shift = 0x77,
- .core_sel = 0x8fff0001,
- .int_st = BIT(1),
- .ctl0 = 0x00000001,
+ .pdata = (const struct svs_bank_pdata) {
+ .sw_id = SVSB_SWID_CPU_BIG,
+ .set_freq_pct = svs_set_bank_freq_pct_v2,
+ .get_volts = svs_get_bank_volts_v2,
+ .cpu_id = 4,
+ .buck_name = "proc",
+ .opp_count = MAX_OPP_ENTRIES,
+ .vboot = 0x30,
+ .volt_step = 6250,
+ .volt_base = 500000,
+ .age_config = 0x555555,
+ .dc_config = 0x555555,
+ .vco = 0x10,
+ .chk_shift = 0x77,
+ .int_st = BIT(1),
+ .ctl0 = 0x00000001,
+ .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) {
+ { 18, 0 }, { 18, 8 }, { 17, 0 }, { 18, 16 }, { 18, 24 }
+ }
+ },
+ .volt_flags = SVSB_INIT01_VOLT_INC_ONLY,
+ .mode_support = SVSB_MODE_INIT01 | SVSB_MODE_INIT02,
+ .freq_base = 1989000000,
+ .core_sel = 0x8fff0001,
+ .dvt_fixed = 0x7,
+ .vmax = 0x58,
+ .vmin = 0x10,
+
},
{
- .sw_id = SVSB_CCI,
- .set_freq_pct = svs_set_bank_freq_pct_v2,
- .get_volts = svs_get_bank_volts_v2,
- .buck_name = "proc",
- .volt_flags = SVSB_INIT01_VOLT_INC_ONLY,
- .mode_support = SVSB_MODE_INIT01 | SVSB_MODE_INIT02,
- .opp_count = MAX_OPP_ENTRIES,
- .freq_base = 1196000000,
- .vboot = 0x30,
- .volt_step = 6250,
- .volt_base = 500000,
- .vmax = 0x64,
- .vmin = 0x18,
- .age_config = 0x555555,
- .dc_config = 0x555555,
- .dvt_fixed = 0x7,
- .vco = 0x10,
- .chk_shift = 0x77,
- .core_sel = 0x8fff0002,
- .int_st = BIT(2),
- .ctl0 = 0x00100003,
+ .pdata = (const struct svs_bank_pdata) {
+ .sw_id = SVSB_SWID_CCI,
+ .set_freq_pct = svs_set_bank_freq_pct_v2,
+ .get_volts = svs_get_bank_volts_v2,
+ .buck_name = "proc",
+ .opp_count = MAX_OPP_ENTRIES,
+ .vboot = 0x30,
+ .volt_step = 6250,
+ .volt_base = 500000,
+ .age_config = 0x555555,
+ .dc_config = 0x555555,
+ .vco = 0x10,
+ .chk_shift = 0x77,
+ .int_st = BIT(2),
+ .ctl0 = 0x00100003,
+ .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) {
+ { 4, 0 }, { 4, 8 }, { 5, 16 }, { 4, 16 }, { 4, 24 }
+ }
+ },
+ .volt_flags = SVSB_INIT01_VOLT_INC_ONLY,
+ .mode_support = SVSB_MODE_INIT01 | SVSB_MODE_INIT02,
+ .freq_base = 1196000000,
+ .core_sel = 0x8fff0002,
+ .dvt_fixed = 0x7,
+ .vmax = 0x64,
+ .vmin = 0x18,
},
{
- .sw_id = SVSB_GPU,
- .set_freq_pct = svs_set_bank_freq_pct_v2,
- .get_volts = svs_get_bank_volts_v2,
- .buck_name = "mali",
- .tzone_name = "tzts2",
- .volt_flags = SVSB_INIT01_PD_REQ |
- SVSB_INIT01_VOLT_INC_ONLY,
- .mode_support = SVSB_MODE_INIT01 | SVSB_MODE_INIT02 |
- SVSB_MODE_MON,
- .opp_count = MAX_OPP_ENTRIES,
- .freq_base = 900000000,
- .vboot = 0x30,
- .volt_step = 6250,
- .volt_base = 500000,
- .vmax = 0x40,
- .vmin = 0x14,
- .age_config = 0x555555,
- .dc_config = 0x555555,
- .dvt_fixed = 0x3,
- .vco = 0x10,
- .chk_shift = 0x77,
- .core_sel = 0x8fff0003,
- .int_st = BIT(3),
- .ctl0 = 0x00050001,
- .tzone_htemp = 85000,
- .tzone_htemp_voffset = 0,
- .tzone_ltemp = 25000,
- .tzone_ltemp_voffset = 3,
+ .pdata = (const struct svs_bank_pdata) {
+ .sw_id = SVSB_SWID_GPU,
+ .set_freq_pct = svs_set_bank_freq_pct_v2,
+ .get_volts = svs_get_bank_volts_v2,
+ .buck_name = "mali",
+ .tzone_name = "gpu",
+ .opp_count = MAX_OPP_ENTRIES,
+ .vboot = 0x30,
+ .volt_step = 6250,
+ .volt_base = 500000,
+ .age_config = 0x555555,
+ .dc_config = 0x555555,
+ .vco = 0x10,
+ .chk_shift = 0x77,
+ .int_st = BIT(3),
+ .ctl0 = 0x00050001,
+ .tzone_htemp = 85000,
+ .tzone_htemp_voffset = 0,
+ .tzone_ltemp = 25000,
+ .tzone_ltemp_voffset = 3,
+ .dev_fuse_map = (const struct svs_fusemap[BDEV_MAX]) {
+ { 6, 0 }, { 6, 8 }, { 5, 0 }, { 6, 16 }, { 6, 24 }
+ }
+ },
+ .volt_flags = SVSB_INIT01_PD_REQ | SVSB_INIT01_VOLT_INC_ONLY,
+ .mode_support = SVSB_MODE_INIT01 | SVSB_MODE_INIT02 | SVSB_MODE_MON,
+ .freq_base = 900000000,
+ .core_sel = 0x8fff0003,
+ .dvt_fixed = 0x3,
+ .vmax = 0x40,
+ .vmin = 0x14,
},
};
+static const struct svs_platform_data svs_mt8195_platform_data = {
+ .name = "mt8195-svs",
+ .banks = svs_mt8195_banks,
+ .efuse_parsing = svs_common_parse_efuse,
+ .probe = svs_mt8192_platform_probe,
+ .regs = svs_regs_v2,
+ .bank_max = ARRAY_SIZE(svs_mt8195_banks),
+ .ts_coeff = SVSB_TS_COEFF_MT8195,
+ .glb_fuse_map = (const struct svs_fusemap[GLB_MAX]) {
+ { 0, 0 }, { 19, 4 }
+ }
+};
+
static const struct svs_platform_data svs_mt8192_platform_data = {
.name = "mt8192-svs",
.banks = svs_mt8192_banks,
- .efuse_parsing = svs_mt8192_efuse_parsing,
+ .efuse_parsing = svs_common_parse_efuse,
.probe = svs_mt8192_platform_probe,
.regs = svs_regs_v2,
.bank_max = ARRAY_SIZE(svs_mt8192_banks),
+ .ts_coeff = SVSB_TS_COEFF_MT8195,
+ .glb_fuse_map = (const struct svs_fusemap[GLB_MAX]) {
+ /* FT_PGM not present */
+ { -1, 0 }, { 19, 4 }
+ }
};
static const struct svs_platform_data svs_mt8188_platform_data = {
.name = "mt8188-svs",
.banks = svs_mt8188_banks,
- .efuse_parsing = svs_mt8188_efuse_parsing,
+ .efuse_parsing = svs_common_parse_efuse,
.probe = svs_mt8192_platform_probe,
.regs = svs_regs_v2,
.bank_max = ARRAY_SIZE(svs_mt8188_banks),
+ .ts_coeff = SVSB_TS_COEFF_MT8195,
+ .glb_fuse_map = (const struct svs_fusemap[GLB_MAX]) {
+ /* FT_PGM and VMIN not present */
+ { -1, 0 }, { -1, 0 }
+ }
+};
+
+static const struct svs_platform_data svs_mt8186_platform_data = {
+ .name = "mt8186-svs",
+ .banks = svs_mt8186_banks,
+ .efuse_parsing = svs_common_parse_efuse,
+ .probe = svs_mt8192_platform_probe,
+ .regs = svs_regs_v2,
+ .bank_max = ARRAY_SIZE(svs_mt8186_banks),
+ .ts_coeff = SVSB_TS_COEFF_MT8186,
+ .glb_fuse_map = (const struct svs_fusemap[GLB_MAX]) {
+ /* FT_PGM and VMIN not present */
+ { -1, 0 }, { -1, 0 }
+ }
};
static const struct svs_platform_data svs_mt8183_platform_data = {
@@ -2466,21 +2797,19 @@ static const struct svs_platform_data svs_mt8183_platform_data = {
.probe = svs_mt8183_platform_probe,
.regs = svs_regs_v2,
.bank_max = ARRAY_SIZE(svs_mt8183_banks),
+ .glb_fuse_map = (const struct svs_fusemap[GLB_MAX]) {
+ /* VMIN not present */
+ { 0, 4 }, { -1, 0 }
+ }
};
static const struct of_device_id svs_of_match[] = {
- {
- .compatible = "mediatek,mt8192-svs",
- .data = &svs_mt8192_platform_data,
- }, {
- .compatible = "mediatek,mt8188-svs",
- .data = &svs_mt8188_platform_data,
- }, {
- .compatible = "mediatek,mt8183-svs",
- .data = &svs_mt8183_platform_data,
- }, {
- /* Sentinel */
- },
+ { .compatible = "mediatek,mt8195-svs", .data = &svs_mt8195_platform_data },
+ { .compatible = "mediatek,mt8192-svs", .data = &svs_mt8192_platform_data },
+ { .compatible = "mediatek,mt8188-svs", .data = &svs_mt8188_platform_data },
+ { .compatible = "mediatek,mt8186-svs", .data = &svs_mt8186_platform_data },
+ { .compatible = "mediatek,mt8183-svs", .data = &svs_mt8183_platform_data },
+ { /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, svs_of_match);
@@ -2500,6 +2829,7 @@ static int svs_probe(struct platform_device *pdev)
svsp->banks = svsp_data->banks;
svsp->regs = svsp_data->regs;
svsp->bank_max = svsp_data->bank_max;
+ svsp->ts_coeff = svsp_data->ts_coeff;
ret = svsp_data->probe(svsp);
if (ret)
@@ -2507,20 +2837,24 @@ static int svs_probe(struct platform_device *pdev)
ret = svs_get_efuse_data(svsp, "svs-calibration-data",
&svsp->efuse, &svsp->efuse_max);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "Cannot read SVS calibration\n");
+
+ ret = svs_get_efuse_data(svsp, "t-calibration-data",
+ &svsp->tefuse, &svsp->tefuse_max);
if (ret) {
- ret = -EPERM;
+ dev_err_probe(&pdev->dev, ret, "Cannot read SVS-Thermal calibration\n");
goto svs_probe_free_efuse;
}
- if (!svsp_data->efuse_parsing(svsp)) {
- dev_err(svsp->dev, "efuse data parsing failed\n");
- ret = -EPERM;
+ if (!svsp_data->efuse_parsing(svsp, svsp_data)) {
+ ret = dev_err_probe(svsp->dev, -EINVAL, "efuse data parsing failed\n");
goto svs_probe_free_tefuse;
}
ret = svs_bank_resource_setup(svsp);
if (ret) {
- dev_err(svsp->dev, "svs bank resource setup fail: %d\n", ret);
+ dev_err_probe(svsp->dev, ret, "svs bank resource setup fail\n");
goto svs_probe_free_tefuse;
}
@@ -2532,43 +2866,40 @@ static int svs_probe(struct platform_device *pdev)
svsp->main_clk = devm_clk_get(svsp->dev, "main");
if (IS_ERR(svsp->main_clk)) {
- dev_err(svsp->dev, "failed to get clock: %ld\n",
- PTR_ERR(svsp->main_clk));
- ret = PTR_ERR(svsp->main_clk);
+ ret = dev_err_probe(svsp->dev, PTR_ERR(svsp->main_clk),
+ "failed to get clock\n");
goto svs_probe_free_tefuse;
}
ret = clk_prepare_enable(svsp->main_clk);
if (ret) {
- dev_err(svsp->dev, "cannot enable main clk: %d\n", ret);
+ dev_err_probe(svsp->dev, ret, "cannot enable main clk\n");
goto svs_probe_free_tefuse;
}
svsp->base = of_iomap(svsp->dev->of_node, 0);
if (IS_ERR_OR_NULL(svsp->base)) {
- dev_err(svsp->dev, "cannot find svs register base\n");
- ret = -EINVAL;
+ ret = dev_err_probe(svsp->dev, -EINVAL, "cannot find svs register base\n");
goto svs_probe_clk_disable;
}
ret = devm_request_threaded_irq(svsp->dev, svsp_irq, NULL, svs_isr,
IRQF_ONESHOT, svsp_data->name, svsp);
if (ret) {
- dev_err(svsp->dev, "register irq(%d) failed: %d\n",
- svsp_irq, ret);
+ dev_err_probe(svsp->dev, ret, "register irq(%d) failed\n", svsp_irq);
goto svs_probe_iounmap;
}
ret = svs_start(svsp);
if (ret) {
- dev_err(svsp->dev, "svs start fail: %d\n", ret);
+ dev_err_probe(svsp->dev, ret, "svs start fail\n");
goto svs_probe_iounmap;
}
#ifdef CONFIG_DEBUG_FS
ret = svs_create_debug_cmds(svsp);
if (ret) {
- dev_err(svsp->dev, "svs create debug cmds fail: %d\n", ret);
+ dev_err_probe(svsp->dev, ret, "svs create debug cmds fail\n");
goto svs_probe_iounmap;
}
#endif
@@ -2577,18 +2908,12 @@ static int svs_probe(struct platform_device *pdev)
svs_probe_iounmap:
iounmap(svsp->base);
-
svs_probe_clk_disable:
clk_disable_unprepare(svsp->main_clk);
-
svs_probe_free_tefuse:
- if (!IS_ERR_OR_NULL(svsp->tefuse))
- kfree(svsp->tefuse);
-
+ kfree(svsp->tefuse);
svs_probe_free_efuse:
- if (!IS_ERR_OR_NULL(svsp->efuse))
- kfree(svsp->efuse);
-
+ kfree(svsp->efuse);
return ret;
}
@@ -2606,5 +2931,6 @@ static struct platform_driver svs_driver = {
module_platform_driver(svs_driver);
MODULE_AUTHOR("Roger Lu <roger.lu@mediatek.com>");
+MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>");
MODULE_DESCRIPTION("MediaTek SVS driver");
MODULE_LICENSE("GPL");