mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Ricardo Rivera-Matos via B4 Relay <devnull+rriveram.opensource.cirrus.com@kernel.org>
To: David Rhodes <david.rhodes@cirrus.com>,
	 Richard Fitzgerald <rf@opensource.cirrus.com>,
	 Liam Girdwood <lgirdwood@gmail.com>,
	Mark Brown <broonie@kernel.org>,  Rob Herring <robh@kernel.org>,
	Krzysztof Kozlowski <krzk+dt@kernel.org>,
	 Conor Dooley <conor+dt@kernel.org>,
	Jaroslav Kysela <perex@perex.cz>,  Takashi Iwai <tiwai@suse.com>
Cc: linux-sound@vger.kernel.org, patches@opensource.cirrus.com,
	 devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	 Ricardo Rivera-Matos <rriveram@opensource.cirrus.com>
Subject: [PATCH 4/4] ASoC: cs35l45: Adds Boost BPE configuration
Date: Mon, 09 Nov 2026 11:57:06 -0600	[thread overview]
Message-ID: <20261109-cs35l45-bpe-v1-4-9d7bc95a90a4@opensource.cirrus.com> (raw)
In-Reply-To: <20261109-cs35l45-bpe-v1-0-9d7bc95a90a4@opensource.cirrus.com>

From: Ricardo Rivera-Matos <rriveram@opensource.cirrus.com>

Adds support for boot time configuration of the boost
brownout prevention engine (BBPE). The engine monitors the
battery voltage and the current through the boost inductor
and applies a limit to the output current of the boost
converter via its controller logic.

Signed-off-by: Ricardo Rivera-Matos <rriveram@opensource.cirrus.com>
---
 sound/soc/codecs/cs35l45-tables.c |  47 +++++
 sound/soc/codecs/cs35l45.c        | 378 ++++++++++++++++++++++++++++++++++++++
 sound/soc/codecs/cs35l45.h        | 144 +++++++++++++++
 3 files changed, 569 insertions(+)

diff --git a/sound/soc/codecs/cs35l45-tables.c b/sound/soc/codecs/cs35l45-tables.c
index 95c39788b71b..599415812bf5 100644
--- a/sound/soc/codecs/cs35l45-tables.c
+++ b/sound/soc/codecs/cs35l45-tables.c
@@ -54,6 +54,18 @@ static const struct reg_default cs35l45_defaults[] = {
 	{ CS35L45_SYNC_TX_RX_ENABLES,		0x00000200 },
 	{ CS35L45_SYNC_SW_TX_ID,		0x00000000 },
 	{ CS35L45_BOOST_LPMODE_CFG,		0x00000002 },
+	{ CS35L45_BST_BPE_INST_THLD,		0x5A46321E },
+	{ CS35L45_BST_BPE_INST_ILIM,		0x3C140C04 },
+	{ CS35L45_BST_BPE_INST_ATK_RATE,	0x06060600 },
+	{ CS35L45_BST_BPE_INST_HOLD_TIME,	0x02020202 },
+	{ CS35L45_BST_BPE_INST_RLS_RATE,	0x06060606 },
+	{ CS35L45_BST_BPE_MISC_CONFIG,		0x00008000 },
+	{ CS35L45_BST_BPE_IL_LIM_THLD,		0x0006022C },
+	{ CS35L45_BST_BPE_IL_LIM_DLY,		0x0000040C },
+	{ CS35L45_BST_BPE_IL_LIM_ATK_RATE,	0x00000000 },
+	{ CS35L45_BST_BPE_IL_LIM_RLS_RATE,	0x00000000 },
+	{ CS35L45_BST_BPE_OUT_ATK_RATE,		0x00000002 },
+	{ CS35L45_BST_BPE_OUT_RLS_RATE,		0x00000002 },
 	{ CS35L45_ASP_ENABLES1,			0x00000000 },
 	{ CS35L45_ASP_CONTROL1,			0x00000028 },
 	{ CS35L45_ASP_CONTROL2,			0x18180200 },
@@ -143,6 +155,18 @@ static bool cs35l45_readable_reg(struct device *dev, unsigned int reg)
 	case CS35L45_WKI2C_CTL:
 	case CS35L45_PWRMGT_STS:
 	case CS35L45_REFCLK_INPUT:
+	case CS35L45_BST_BPE_INST_THLD:
+	case CS35L45_BST_BPE_INST_ILIM:
+	case CS35L45_BST_BPE_INST_ATK_RATE:
+	case CS35L45_BST_BPE_INST_HOLD_TIME:
+	case CS35L45_BST_BPE_INST_RLS_RATE:
+	case CS35L45_BST_BPE_MISC_CONFIG:
+	case CS35L45_BST_BPE_IL_LIM_THLD:
+	case CS35L45_BST_BPE_IL_LIM_DLY:
+	case CS35L45_BST_BPE_IL_LIM_ATK_RATE:
+	case CS35L45_BST_BPE_IL_LIM_RLS_RATE:
+	case CS35L45_BST_BPE_OUT_ATK_RATE:
+	case CS35L45_BST_BPE_OUT_RLS_RATE:
 	case CS35L45_GLOBAL_SAMPLE_RATE:
 	case CS35L45_SYNC_TX_RX_ENABLES:
 	case CS35L45_SYNC_SW_TX_ID:
@@ -440,3 +464,26 @@ const char *cs35l45_bpe_get_attn_prop(const enum bpe_modes mode)
 	return cs35l45_bpe_attenuation_props[mode];
 }
 EXPORT_SYMBOL_NS_GPL(cs35l45_bpe_get_attn_prop, "SND_SOC_CS35L45");
+
+static const u32 cs35l45_bst_bpe_hold_times_us[] = {
+	0, 5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000,
+};
+
+int cs35l45_bst_bpe_pack_hold_times(const u32 *hold_times, u32 *packed_code)
+{
+	int i, j;
+
+	for (i = 0; i < CS35L45_BST_BPE_NUM_LEVELS; i++) {
+		for (j = 0; j < ARRAY_SIZE(cs35l45_bst_bpe_hold_times_us); j++)
+			if (hold_times[i] == cs35l45_bst_bpe_hold_times_us[j])
+				break;
+
+		if (j == ARRAY_SIZE(cs35l45_bst_bpe_hold_times_us))
+			return -EINVAL;
+
+		*packed_code |= CS35L45_BST_BPE_PACK_CODE(j, i);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_NS_GPL(cs35l45_bst_bpe_pack_hold_times, "SND_SOC_CS35L45");
diff --git a/sound/soc/codecs/cs35l45.c b/sound/soc/codecs/cs35l45.c
index 72f4ab1b89be..c087f9db6ea7 100644
--- a/sound/soc/codecs/cs35l45.c
+++ b/sound/soc/codecs/cs35l45.c
@@ -1367,6 +1367,380 @@ static int cs35l45_apply_abpe_config(struct cs35l45_private *cs35l45)
 	return regmap_set_bits(cs35l45->regmap, CS35L45_BLOCK_ENABLES2, CS35L45_ABPE_EN_MASK);
 }
 
+static int cs35l45_bst_bpe_pack_array(struct cs35l45_private *cs35l45, const char *property,
+				      size_t count, unsigned int first_lane, u32 min, u32 max,
+				      u32 step, u32 *packed)
+{
+	u32 code, values[CS35L45_BST_BPE_NUM_LEVELS];
+	unsigned int i;
+	int ret;
+
+	if (!step || (first_lane + count) > ARRAY_SIZE(values))
+		return -EINVAL;
+
+	ret = cs35l45_bpe_read_array(cs35l45, property, values, count);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < count; i++) {
+		if (values[i] < min || values[i] > max)
+			return dev_err_probe(cs35l45->dev, -EINVAL,
+					     "Invalid %s value %u at index %u\n",
+					     property, values[i], i);
+
+		code = (values[i] - min) / step;
+
+		*packed |= CS35L45_BST_BPE_PACK_CODE(code, first_lane + i);
+	}
+
+	return 0;
+}
+
+static int cs35l45_bst_bpe_pack_scalar(struct cs35l45_private *cs35l45, const char *property,
+				       u32 field_mask, unsigned int shift, u32 min, u32 max,
+				       u32 step, u32 *packed)
+{
+	u32 value, code;
+	int ret;
+
+	if (!device_property_present(cs35l45->dev, property))
+		return -EINVAL;
+
+	ret = device_property_read_u32(cs35l45->dev, property, &value);
+	if (ret)
+		return dev_err_probe(cs35l45->dev, ret, "Failed to read %s\n", property);
+
+	if (!step || value < min || value > max)
+		return dev_err_probe(cs35l45->dev, -EINVAL, "Invalid %s value %u\n",
+				     property, value);
+
+	code = (value - min) / step;
+	if (code > field_mask >> shift)
+		return dev_err_probe(cs35l45->dev, -EINVAL,
+				     "%s value %u does not fit its field\n", property, value);
+
+	*packed |= code << shift;
+
+	return 0;
+}
+
+static int cs35l45_bst_bpe_set_inst_thld(struct cs35l45_private *cs35l45)
+{
+	u32 packed = 0;
+	int ret;
+
+	ret = cs35l45_bst_bpe_pack_array(cs35l45, "cirrus,boost-bpe-battery-thresholds-microvolt",
+					 CS35L45_BST_BPE_NUM_VOLTAGE_LEVELS, 0,
+					 CS35L45_BST_BPE_INST_THLD_MIN_UV,
+					 CS35L45_BST_BPE_INST_THLD_MAX_UV,
+					 CS35L45_BST_BPE_INST_THLD_STEP_UV, &packed);
+	if (ret)
+		return ret;
+
+	return regmap_write(cs35l45->regmap, CS35L45_BST_BPE_INST_THLD, packed);
+}
+
+static int cs35l45_bst_bpe_set_inst_ilim(struct cs35l45_private *cs35l45)
+{
+	u32 packed = 0;
+	int ret;
+
+	ret = cs35l45_bst_bpe_pack_array(cs35l45, "cirrus,boost-bpe-battery-limits-microamp",
+					 CS35L45_BST_BPE_NUM_VOLTAGE_LEVELS, 0,
+					 CS35L45_BST_BPE_INST_ILIM_MIN_UA,
+					 CS35L45_BST_BPE_INST_ILIM_MAX_UA,
+					 CS35L45_BST_BPE_INST_ILIM_STEP_UA, &packed);
+	if (ret)
+		return ret;
+
+	return regmap_write(cs35l45->regmap, CS35L45_BST_BPE_INST_ILIM, packed);
+}
+
+static int cs35l45_bst_bpe_set_inst_atk_rate(struct cs35l45_private *cs35l45)
+{
+	u32 packed = 0;
+	int ret;
+
+	ret = cs35l45_bst_bpe_pack_array(cs35l45, "cirrus,boost-bpe-battery-attack-rates",
+					 CS35L45_BST_BPE_NUM_VOLTAGE_ATTACK_LEVELS, 1, 0,
+					 CS35L45_BST_BPE_ATTACK_RATE_3P90625MA_PER_US, 1, &packed);
+	if (ret)
+		return ret;
+
+	return regmap_write(cs35l45->regmap, CS35L45_BST_BPE_INST_ATK_RATE, packed);
+}
+
+static int cs35l45_bst_bpe_set_inst_hold_time(struct cs35l45_private *cs35l45)
+{
+	u32 values[CS35L45_BST_BPE_NUM_VOLTAGE_LEVELS];
+	u32 packed = 0;
+	int ret;
+
+	ret = cs35l45_bpe_read_array(cs35l45, "cirrus,boost-bpe-battery-hold-times-us", values,
+				     ARRAY_SIZE(values));
+	if (ret < 0)
+		return ret;
+
+	ret = cs35l45_bst_bpe_pack_hold_times(values, &packed);
+	if (ret)
+		return dev_err_probe(cs35l45->dev, ret, "Invalid Boost BPE hold time\n");
+
+	return regmap_write(cs35l45->regmap, CS35L45_BST_BPE_INST_HOLD_TIME, packed);
+}
+
+static int cs35l45_bst_bpe_set_inst_rls_rate(struct cs35l45_private *cs35l45)
+{
+	u32 packed = 0;
+	int ret;
+
+	ret = cs35l45_bst_bpe_pack_array(cs35l45, "cirrus,boost-bpe-battery-release-rates",
+					 CS35L45_BST_BPE_NUM_VOLTAGE_LEVELS, 0, 0,
+					 CS35L45_BST_BPE_RELEASE_RATE_0P001907MA_PER_US, 1,
+					 &packed);
+	if (ret)
+		return ret;
+
+	return regmap_write(cs35l45->regmap, CS35L45_BST_BPE_INST_RLS_RATE, packed);
+}
+
+static int cs35l45_bst_bpe_set_out_atk_rate(struct cs35l45_private *cs35l45)
+{
+	u32 value;
+	int ret;
+
+	ret = device_property_read_u32(cs35l45->dev, "cirrus,boost-bpe-output-attack-rate",
+				       &value);
+	if (ret)
+		return ret;
+
+	if (value > CS35L45_BST_BPE_ATTACK_RATE_3P90625MA_PER_US)
+		return -EINVAL;
+
+	return regmap_write(cs35l45->regmap, CS35L45_BST_BPE_OUT_ATK_RATE, value);
+}
+
+static int cs35l45_bst_bpe_set_out_rls_rate(struct cs35l45_private *cs35l45)
+{
+	u32 value;
+	int ret;
+
+	ret = device_property_read_u32(cs35l45->dev, "cirrus,boost-bpe-output-release-rate",
+				       &value);
+	if (ret)
+		return ret;
+
+	if (value > CS35L45_BST_BPE_RELEASE_RATE_0P001907MA_PER_US)
+		return -EINVAL;
+
+	return regmap_write(cs35l45->regmap, CS35L45_BST_BPE_OUT_RLS_RATE, value);
+}
+
+static int cs35l45_bst_bpe_set_il_lim_thld(struct cs35l45_private *cs35l45)
+{
+	u32 packed = 0;
+	int ret;
+
+	ret = cs35l45_bst_bpe_pack_scalar(cs35l45, "cirrus,boost-bpe-inductor-threshold-microamp",
+					  CS35L45_BST_BPE_IL_LIM1_THLD_MASK,
+					  CS35L45_BST_BPE_IL_LIM1_THLD_SHIFT,
+					  CS35L45_BST_BPE_IL_LIM_THLD_MIN_UA,
+					  CS35L45_BST_BPE_IL_LIM_THLD_MAX_UA,
+					  CS35L45_BST_BPE_IL_LIM_THLD_STEP_UA, &packed);
+	if (ret)
+		return ret;
+
+	ret = cs35l45_bst_bpe_pack_array(cs35l45,
+					 "cirrus,boost-bpe-inductor-threshold-deltas-microamp",
+					 CS35L45_BST_BPE_NUM_CURRENT_LEVELS, 1,
+					 CS35L45_BST_BPE_IL_LIM_THLD_DEL_MIN_UA,
+					 CS35L45_BST_BPE_IL_LIM_THLD_DEL_MAX_UA,
+					 CS35L45_BST_BPE_IL_LIM_THLD_DEL_STEP_UA, &packed);
+	if (ret)
+		return ret;
+
+	ret = cs35l45_bst_bpe_pack_scalar(cs35l45,
+					  "cirrus,boost-bpe-inductor-threshold-hysteresis-microamp",
+					  CS35L45_BST_BPE_IL_LIM_THLD_HYST_MASK,
+					  CS35L45_BST_BPE_IL_LIM_THLD_HYST_SHIFT,
+					  CS35L45_BST_BPE_IL_LIM_THLD_HYST_MIN_UA,
+					  CS35L45_BST_BPE_IL_LIM_THLD_HYST_MAX_UA,
+					  CS35L45_BST_BPE_IL_LIM_THLD_HYST_STEP_UA, &packed);
+	if (ret)
+		return ret;
+
+	return regmap_write(cs35l45->regmap, CS35L45_BST_BPE_IL_LIM_THLD, packed);
+}
+
+static int cs35l45_bst_bpe_set_il_lim_dly(struct cs35l45_private *cs35l45)
+{
+	u32 packed = 0;
+	int ret;
+
+	ret = cs35l45_bst_bpe_pack_scalar(cs35l45, "cirrus,boost-bpe-inductor-delay-hysteresis-us",
+					  CS35L45_BST_BPE_IL_LIM_DLY_HYST_MASK,
+					  CS35L45_BST_BPE_IL_LIM_DLY_HYST_SHIFT,
+					  CS35L45_BST_BPE_IL_LIM_DLY_HYST_MIN_US,
+					  CS35L45_BST_BPE_IL_LIM_DLY_HYST_MAX_US,
+					  CS35L45_BST_BPE_IL_LIM_DLY_HYST_STEP_US, &packed);
+	if (ret)
+		return ret;
+
+	ret = cs35l45_bst_bpe_pack_array(cs35l45, "cirrus,boost-bpe-inductor-delays-ms",
+					 CS35L45_BST_BPE_NUM_CURRENT_LEVELS, 0,
+					 CS35L45_BST_BPE_IL_LIM_DLY_MIN_MS,
+					 CS35L45_BST_BPE_IL_LIM_DLY_MAX_MS,
+					 CS35L45_BST_BPE_IL_LIM_DLY_STEP_MS, &packed);
+	if (ret)
+		return ret;
+
+	return regmap_write(cs35l45->regmap, CS35L45_BST_BPE_IL_LIM_DLY, packed);
+}
+
+static int cs35l45_bst_bpe_set_il_lim_atk_rate(struct cs35l45_private *cs35l45)
+{
+	u32 packed = 0;
+	int ret;
+
+	ret = cs35l45_bst_bpe_pack_array(cs35l45, "cirrus,boost-bpe-inductor-attack-rates",
+					 CS35L45_BST_BPE_NUM_CURRENT_LEVELS, 0, 0,
+					 CS35L45_BST_BPE_ATTACK_RATE_3P90625MA_PER_US, 1, &packed);
+	if (ret)
+		return ret;
+
+	return regmap_write(cs35l45->regmap, CS35L45_BST_BPE_IL_LIM_ATK_RATE, packed);
+}
+
+static int cs35l45_bst_bpe_set_il_lim_rls_rate(struct cs35l45_private *cs35l45)
+{
+	u32 packed = 0;
+	int ret;
+
+	ret = cs35l45_bst_bpe_pack_array(cs35l45, "cirrus,boost-bpe-inductor-release-rates",
+					 CS35L45_BST_BPE_NUM_CURRENT_LEVELS, 0, 0,
+					 CS35L45_BST_BPE_RELEASE_RATE_0P001907MA_PER_US, 1,
+					 &packed);
+	if (ret)
+		return ret;
+
+	return regmap_write(cs35l45->regmap, CS35L45_BST_BPE_IL_LIM_RLS_RATE, packed);
+}
+
+static int cs35l45_bst_bpe_set_mode(struct cs35l45_private *cs35l45, u32 *output_mode)
+{
+	u32 release_mode, mask, packed;
+	int ret;
+
+	ret = device_property_read_u32(cs35l45->dev, "cirrus,boost-bpe-output-operating-mode",
+				       output_mode);
+	if (ret)
+		return dev_err_probe(cs35l45->dev, ret, "Failed to read boost BPE op mode\n");
+
+	if ((*output_mode != CS35L45_BST_BPE_OUTPUT_MODE_BOTH) &&
+	    (*output_mode != CS35L45_BST_BPE_OUTPUT_MODE_VOLTAGE_ONLY))
+		return dev_err_probe(cs35l45->dev, -EINVAL, "Invalid boost BPE op mode found\n");
+
+	mask = CS35L45_BST_BPE_OUT_OPMODE_SEL_MASK;
+	packed = FIELD_PREP(CS35L45_BST_BPE_OUT_OPMODE_SEL_MASK, *output_mode);
+
+	if (*output_mode == CS35L45_BST_BPE_OUTPUT_MODE_BOTH) {
+		ret = device_property_read_u32(cs35l45->dev,
+					       "cirrus,boost-bpe-inductor-release-mode",
+					       &release_mode);
+		if (ret)
+			return dev_err_probe(cs35l45->dev, ret,
+					     "Failed to read inductor response release mode\n");
+
+		if ((release_mode != CS35L45_BST_BPE_IL_RELEASE_MODE_INSTANT) &&
+		    (release_mode != CS35L45_BST_BPE_IL_RELEASE_MODE_COUNTER))
+			return dev_err_probe(cs35l45->dev, -EINVAL,
+					     "Invalid boost BPE indductor current release mode\n");
+
+		mask |= CS35L45_BST_BPE_IL_LIM_MODE_MASK;
+		packed |= FIELD_PREP(CS35L45_BST_BPE_IL_LIM_MODE_MASK, release_mode);
+	}
+
+	return regmap_update_bits(cs35l45->regmap, CS35L45_BST_BPE_MISC_CONFIG, mask, packed);
+}
+
+static int cs35l45_bst_bpe_set_il_lim_limiter(struct cs35l45_private *cs35l45)
+{
+	int ret;
+
+	ret = cs35l45_bst_bpe_set_il_lim_thld(cs35l45);
+	if (ret)
+		return ret;
+
+	ret = cs35l45_bst_bpe_set_il_lim_dly(cs35l45);
+	if (ret)
+		return ret;
+
+	ret = cs35l45_bst_bpe_set_il_lim_atk_rate(cs35l45);
+	if (ret)
+		return ret;
+
+	return cs35l45_bst_bpe_set_il_lim_rls_rate(cs35l45);
+}
+
+static int cs35l45_bst_bpe_set_inst_limiter(struct cs35l45_private *cs35l45)
+{
+	int ret;
+
+	ret = cs35l45_bst_bpe_set_inst_thld(cs35l45);
+	if (ret)
+		return ret;
+
+	ret = cs35l45_bst_bpe_set_inst_ilim(cs35l45);
+	if (ret)
+		return ret;
+
+	ret = cs35l45_bst_bpe_set_inst_atk_rate(cs35l45);
+	if (ret)
+		return ret;
+
+	ret = cs35l45_bst_bpe_set_inst_hold_time(cs35l45);
+	if (ret)
+		return ret;
+
+	return cs35l45_bst_bpe_set_inst_rls_rate(cs35l45);
+}
+
+static int cs35l45_apply_boost_bpe_config(struct cs35l45_private *cs35l45)
+{
+	u32 output_mode;
+	int ret;
+
+	if (!device_property_read_bool(cs35l45->dev, "cirrus,boost-bpe-enable"))
+		return 0;
+
+	ret = cs35l45_bst_bpe_set_mode(cs35l45, &output_mode);
+	if (ret)
+		return ret;
+
+	ret = cs35l45_bst_bpe_set_inst_limiter(cs35l45);
+	if (ret)
+		return ret;
+
+	ret = cs35l45_bst_bpe_set_out_atk_rate(cs35l45);
+	if (ret)
+		return ret;
+
+	ret = cs35l45_bst_bpe_set_out_rls_rate(cs35l45);
+	if (ret)
+		return ret;
+
+	if (output_mode == CS35L45_BST_BPE_OUTPUT_MODE_BOTH) {
+		ret = cs35l45_bst_bpe_set_il_lim_limiter(cs35l45);
+		if (ret)
+			return ret;
+	}
+
+	ret = regmap_set_bits(cs35l45->regmap, CS35L45_BLOCK_ENABLES2, CS35L45_BBPE_EN_MASK);
+	if (ret)
+		return dev_err_probe(cs35l45->dev, ret, "Failed to enable Boost BPE\n");
+
+	return 0;
+}
+
 static int cs35l45_apply_ldpm_config(struct cs35l45_private *cs35l45)
 {
 	char prop_name[CS35L45_LDPM_PROP_NAME_MAX];
@@ -1518,6 +1892,10 @@ static int cs35l45_apply_property_config(struct cs35l45_private *cs35l45)
 				   val << CS35L45_ASP_DOUT_HIZ_CTRL_SHIFT);
 	}
 
+	ret = cs35l45_apply_boost_bpe_config(cs35l45);
+	if (ret < 0)
+		return ret;
+
 	ret = cs35l45_apply_ldpm_config(cs35l45);
 	if (ret < 0)
 		return ret;
diff --git a/sound/soc/codecs/cs35l45.h b/sound/soc/codecs/cs35l45.h
index 573595924365..8c94a7f42c65 100644
--- a/sound/soc/codecs/cs35l45.h
+++ b/sound/soc/codecs/cs35l45.h
@@ -41,6 +41,18 @@
 #define CS35L45_BOOST_LPMODE_CFG		0x00003810
 #define CS35L45_BOOST_DCM_CFG			0x0000380C
 #define CS35L45_BOOST_OV_CFG			0x0000382C
+#define CS35L45_BST_BPE_INST_THLD		0x00003C00
+#define CS35L45_BST_BPE_INST_ILIM		0x00003C04
+#define CS35L45_BST_BPE_INST_ATK_RATE		0x00003C0C
+#define CS35L45_BST_BPE_INST_HOLD_TIME		0x00003C10
+#define CS35L45_BST_BPE_INST_RLS_RATE		0x00003C14
+#define CS35L45_BST_BPE_MISC_CONFIG		0x00003C20
+#define CS35L45_BST_BPE_IL_LIM_THLD		0x00003C24
+#define CS35L45_BST_BPE_IL_LIM_DLY		0x00003C28
+#define CS35L45_BST_BPE_IL_LIM_ATK_RATE	0x00003C2C
+#define CS35L45_BST_BPE_IL_LIM_RLS_RATE	0x00003C30
+#define CS35L45_BST_BPE_OUT_ATK_RATE		0x00003C34
+#define CS35L45_BST_BPE_OUT_RLS_RATE		0x00003C38
 #define CS35L45_ASP_ENABLES1			0x00004800
 #define CS35L45_ASP_CONTROL1			0x00004804
 #define CS35L45_ASP_CONTROL2			0x00004808
@@ -191,6 +203,8 @@
 #define CS35L45_BST_ENABLE			0x02
 
 /* BLOCK_ENABLES2 */
+#define CS35L45_BBPE_EN_SHIFT			13
+#define CS35L45_BBPE_EN_MASK			BIT(13)
 #define CS35L45_ASP_EN_SHIFT			27
 #define CS35L45_AMP_DRE_EN_SHIFT		20
 #define CS35L45_AMP_DRE_EN_MASK		BIT(20)
@@ -282,6 +296,126 @@
 /* BOOST_LPMODE_CFG */
 #define CS35L45_BST_LPMODE_SEL			GENMASK(1, 0)
 
+/* BST_BPE_INST_THLD */
+#define CS35L45_BST_BPE_INST_L3_THLD_SHIFT	24
+#define CS35L45_BST_BPE_INST_L3_THLD_MASK	GENMASK(31, 24)
+#define CS35L45_BST_BPE_INST_L2_THLD_SHIFT	16
+#define CS35L45_BST_BPE_INST_L2_THLD_MASK	GENMASK(23, 16)
+#define CS35L45_BST_BPE_INST_L1_THLD_SHIFT	8
+#define CS35L45_BST_BPE_INST_L1_THLD_MASK	GENMASK(15, 8)
+#define CS35L45_BST_BPE_INST_L0_THLD_SHIFT	0
+#define CS35L45_BST_BPE_INST_L0_THLD_MASK	GENMASK(7, 0)
+
+#define CS35L45_BST_BPE_INST_THLD_MIN_UV	2300000
+#define CS35L45_BST_BPE_INST_THLD_MAX_UV	4500000
+#define CS35L45_BST_BPE_INST_THLD_STEP_UV	10000
+
+/* BST_BPE_INST_ILIM */
+#define CS35L45_BST_BPE_INST_L4_ILIM_SHIFT	24
+#define CS35L45_BST_BPE_INST_L4_ILIM_MASK	GENMASK(30, 24)
+#define CS35L45_BST_BPE_INST_L3_ILIM_SHIFT	16
+#define CS35L45_BST_BPE_INST_L3_ILIM_MASK	GENMASK(22, 16)
+#define CS35L45_BST_BPE_INST_L2_ILIM_SHIFT	8
+#define CS35L45_BST_BPE_INST_L2_ILIM_MASK	GENMASK(14, 8)
+#define CS35L45_BST_BPE_INST_L1_ILIM_SHIFT	0
+#define CS35L45_BST_BPE_INST_L1_ILIM_MASK	GENMASK(6, 0)
+
+#define CS35L45_BST_BPE_INST_ILIM_MIN_UA	250000
+#define CS35L45_BST_BPE_INST_ILIM_MAX_UA	4625000
+#define CS35L45_BST_BPE_INST_ILIM_STEP_UA	62500
+
+/* BST_BPE_INST_ATK_RATE */
+#define CS35L45_BST_BPE_INST_L3_ATK_RATE_SHIFT	24
+#define CS35L45_BST_BPE_INST_L3_ATK_RATE_MASK	GENMASK(26, 24)
+#define CS35L45_BST_BPE_INST_L2_ATK_RATE_SHIFT	16
+#define CS35L45_BST_BPE_INST_L2_ATK_RATE_MASK	GENMASK(18, 16)
+#define CS35L45_BST_BPE_INST_L1_ATK_RATE_SHIFT	8
+#define CS35L45_BST_BPE_INST_L1_ATK_RATE_MASK	GENMASK(10, 8)
+
+/* BST_BPE_INST_HOLD_TIME */
+#define CS35L45_BST_BPE_INST_L3_HOLD_TIME_SHIFT	24
+#define CS35L45_BST_BPE_INST_L3_HOLD_TIME_MASK		GENMASK(27, 24)
+#define CS35L45_BST_BPE_INST_L2_HOLD_TIME_SHIFT	16
+#define CS35L45_BST_BPE_INST_L2_HOLD_TIME_MASK		GENMASK(19, 16)
+#define CS35L45_BST_BPE_INST_L1_HOLD_TIME_SHIFT	8
+#define CS35L45_BST_BPE_INST_L1_HOLD_TIME_MASK		GENMASK(11, 8)
+#define CS35L45_BST_BPE_INST_L0_HOLD_TIME_SHIFT	0
+#define CS35L45_BST_BPE_INST_L0_HOLD_TIME_MASK		GENMASK(3, 0)
+
+/* BST_BPE_INST_RLS_RATE */
+#define CS35L45_BST_BPE_INST_L3_RLS_RATE_SHIFT	24
+#define CS35L45_BST_BPE_INST_L3_RLS_RATE_MASK	GENMASK(28, 24)
+#define CS35L45_BST_BPE_INST_L2_RLS_RATE_SHIFT	16
+#define CS35L45_BST_BPE_INST_L2_RLS_RATE_MASK	GENMASK(20, 16)
+#define CS35L45_BST_BPE_INST_L1_RLS_RATE_SHIFT	8
+#define CS35L45_BST_BPE_INST_L1_RLS_RATE_MASK	GENMASK(12, 8)
+#define CS35L45_BST_BPE_INST_L0_RLS_RATE_SHIFT	0
+#define CS35L45_BST_BPE_INST_L0_RLS_RATE_MASK	GENMASK(4, 0)
+
+/* BST_BPE_MISC_CONFIG */
+#define CS35L45_BST_BPE_IL_LIM_MODE_SHIFT	15
+#define CS35L45_BST_BPE_IL_LIM_MODE_MASK	BIT(15)
+#define CS35L45_BST_BPE_OUT_OPMODE_SEL_SHIFT	12
+#define CS35L45_BST_BPE_OUT_OPMODE_SEL_MASK	GENMASK(13, 12)
+
+/* BST_BPE_IL_LIM_THLD */
+#define CS35L45_BST_BPE_IL_LIM_THLD_HYST_SHIFT	24
+#define CS35L45_BST_BPE_IL_LIM_THLD_HYST_MASK	GENMASK(28, 24)
+#define CS35L45_BST_BPE_IL_LIM_THLD_DEL2_SHIFT	16
+#define CS35L45_BST_BPE_IL_LIM_THLD_DEL2_MASK	GENMASK(23, 16)
+#define CS35L45_BST_BPE_IL_LIM_THLD_DEL1_SHIFT	8
+#define CS35L45_BST_BPE_IL_LIM_THLD_DEL1_MASK	GENMASK(15, 8)
+#define CS35L45_BST_BPE_IL_LIM1_THLD_SHIFT	0
+#define CS35L45_BST_BPE_IL_LIM1_THLD_MASK	GENMASK(7, 0)
+
+#define CS35L45_BST_BPE_IL_LIM_THLD_MIN_UA	250000
+#define CS35L45_BST_BPE_IL_LIM_THLD_MAX_UA	4000000
+#define CS35L45_BST_BPE_IL_LIM_THLD_STEP_UA	62500
+
+#define CS35L45_BST_BPE_IL_LIM_THLD_DEL_MIN_UA		0
+#define CS35L45_BST_BPE_IL_LIM_THLD_DEL_MAX_UA		3750000
+#define CS35L45_BST_BPE_IL_LIM_THLD_DEL_STEP_UA	62500
+
+#define CS35L45_BST_BPE_IL_LIM_THLD_HYST_MIN_UA	0
+#define CS35L45_BST_BPE_IL_LIM_THLD_HYST_MAX_UA	968750
+#define CS35L45_BST_BPE_IL_LIM_THLD_HYST_STEP_UA	31250
+
+/* BST_BPE_IL_LIM_DLY */
+#define CS35L45_BST_BPE_IL_LIM_DLY_HYST_SHIFT	16
+#define CS35L45_BST_BPE_IL_LIM_DLY_HYST_MASK	GENMASK(20, 16)
+#define CS35L45_BST_BPE_IL_LIM2_DLY_SHIFT	8
+#define CS35L45_BST_BPE_IL_LIM2_DLY_MASK	GENMASK(15, 8)
+#define CS35L45_BST_BPE_IL_LIM1_DLY_SHIFT	0
+#define CS35L45_BST_BPE_IL_LIM1_DLY_MASK	GENMASK(7, 0)
+
+#define CS35L45_BST_BPE_IL_LIM_DLY_HYST_MIN_US		0
+#define CS35L45_BST_BPE_IL_LIM_DLY_HYST_MAX_US		992
+#define CS35L45_BST_BPE_IL_LIM_DLY_HYST_STEP_US	32
+
+#define CS35L45_BST_BPE_IL_LIM_DLY_MIN_MS	0
+#define CS35L45_BST_BPE_IL_LIM_DLY_MAX_MS	100
+#define CS35L45_BST_BPE_IL_LIM_DLY_STEP_MS	1
+
+/* BST_BPE_IL_LIM_ATK_RATE */
+#define CS35L45_BST_BPE_IL_LIM2_ATK_RATE_SHIFT	8
+#define CS35L45_BST_BPE_IL_LIM2_ATK_RATE_MASK	GENMASK(10, 8)
+#define CS35L45_BST_BPE_IL_LIM1_ATK_RATE_SHIFT	0
+#define CS35L45_BST_BPE_IL_LIM1_ATK_RATE_MASK	GENMASK(2, 0)
+
+/* BST_BPE_IL_LIM_RLS_RATE */
+#define CS35L45_BST_BPE_IL_LIM2_RLS_RATE_SHIFT	8
+#define CS35L45_BST_BPE_IL_LIM2_RLS_RATE_MASK	GENMASK(12, 8)
+#define CS35L45_BST_BPE_IL_LIM1_RLS_RATE_SHIFT	0
+#define CS35L45_BST_BPE_IL_LIM1_RLS_RATE_MASK	GENMASK(4, 0)
+
+/* BST_BPE_OUT_ATK_RATE */
+#define CS35L45_BST_BPE_OUT_ATK_RATE_SHIFT	0
+#define CS35L45_BST_BPE_OUT_ATK_RATE_MASK	GENMASK(2, 0)
+
+/* BST_BPE_OUT_RLS_RATE */
+#define CS35L45_BST_BPE_OUT_RLS_RATE_SHIFT	0
+#define CS35L45_BST_BPE_OUT_RLS_RATE_MASK	GENMASK(4, 0)
+
 /* ASP_ENABLES_1 */
 #define CS35L45_ASP_RX2_EN_SHIFT		17
 #define CS35L45_ASP_RX1_EN_SHIFT		16
@@ -532,6 +666,15 @@ enum bpe_modes {
 
 #define CS35L45_BPE_PACK_CODE(_code, _idx) (_code << (24 - (8 * _idx)))
 
+#define CS35L45_BST_BPE_NUM_VOLTAGE_LEVELS		4
+#define CS35L45_BST_BPE_NUM_VOLTAGE_ATTACK_LEVELS	3
+#define CS35L45_BST_BPE_NUM_CURRENT_LEVELS		2
+#define CS35L45_BST_BPE_NUM_LEVELS			CS35L45_BST_BPE_NUM_VOLTAGE_LEVELS
+#define CS35L45_BST_BPE_NUM_HOLD_TIMES			12
+
+/* Boost BPE levels use ascending byte lanes; some arrays start at lane 1. */
+#define CS35L45_BST_BPE_PACK_CODE(_code, _idx) ((_code) << (8 * (_idx)))
+
 /*
  * IRQs
  */
@@ -609,6 +752,7 @@ int cs35l45_get_clk_freq_id(unsigned int freq);
 int cs35l45_get_ldpm_pcm_thld(int pcm_thld_db);
 int cs35l45_get_ldpm_delay(u32 delay_ms);
 int cs35l45_bpe_pack_hold_times(u32 *hold_times, u32 *packed_code);
+int cs35l45_bst_bpe_pack_hold_times(const u32 *hold_times, u32 *packed_code);
 const char *cs35l45_bpe_get_attn_prop(const enum bpe_modes mode);
 int cs35l45_probe(struct cs35l45_private *cs35l45);
 void cs35l45_remove(struct cs35l45_private *cs35l45);

-- 
2.43.0



      parent reply	other threads:[~2026-11-09 17:57 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-09 17:57 [PATCH 0/4] ASoC: cs35l45: Adds support for brownout prevention engines Ricardo Rivera-Matos via B4 Relay
2026-11-09 17:57 ` [PATCH 1/4] ASoC: dt-bindings: cs35l45: Adds ABPE properties Ricardo Rivera-Matos via B4 Relay
2026-11-09 17:57 ` [PATCH 2/4] ASoC: cs35l45: Adds support for ABPE feature Ricardo Rivera-Matos via B4 Relay
2026-11-09 17:57 ` [PATCH 3/4] ASoC: dt-bindings: cs35l45: Adds Boost BPE properties Ricardo Rivera-Matos via B4 Relay
2026-11-09 17:57 ` Ricardo Rivera-Matos via B4 Relay [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261109-cs35l45-bpe-v1-4-9d7bc95a90a4@opensource.cirrus.com \
    --to=devnull+rriveram.opensource.cirrus.com@kernel.org \
    --cc=broonie@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=david.rhodes@cirrus.com \
    --cc=devicetree@vger.kernel.org \
    --cc=krzk+dt@kernel.org \
    --cc=lgirdwood@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-sound@vger.kernel.org \
    --cc=patches@opensource.cirrus.com \
    --cc=perex@perex.cz \
    --cc=rf@opensource.cirrus.com \
    --cc=robh@kernel.org \
    --cc=rriveram@opensource.cirrus.com \
    --cc=tiwai@suse.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®