Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

power: sequencing: qcom-wcn: improve support for wcn6855

WCN6855 (also known as QCA6490) is similar to the already supported
QCA6390 but takes in two more supplies so add a new vregs list for it.

On sm8450-hdk it also requires a short assert of the xo-clk pin so add
handling for it in a dedicated unit.

As we now have a separate set of targets for this variant, store the
pointer to the targets struct associated with a model in the device
match data.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Link: https://lore.kernel.org/r/20241018-sc8280xp-pwrseq-v6-2-8da8310d9564@linaro.org
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

+98 -3
+98 -3
drivers/power/sequencing/pwrseq-qcom-wcn.c
··· 22 22 size_t num_vregs; 23 23 unsigned int pwup_delay_ms; 24 24 unsigned int gpio_enable_delay_ms; 25 + const struct pwrseq_target_data **targets; 25 26 }; 26 27 27 28 struct pwrseq_qcom_wcn_ctx { ··· 32 31 struct regulator_bulk_data *regs; 33 32 struct gpio_desc *bt_gpio; 34 33 struct gpio_desc *wlan_gpio; 34 + struct gpio_desc *xo_clk_gpio; 35 35 struct clk *clk; 36 36 unsigned long last_gpio_enable_jf; 37 37 }; ··· 100 98 NULL 101 99 }; 102 100 101 + static int pwrseq_qcom_wcn6855_clk_assert(struct pwrseq_device *pwrseq) 102 + { 103 + struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq); 104 + 105 + if (!ctx->xo_clk_gpio) 106 + return 0; 107 + 108 + msleep(1); 109 + 110 + gpiod_set_value_cansleep(ctx->xo_clk_gpio, 1); 111 + usleep_range(100, 200); 112 + 113 + return 0; 114 + } 115 + 116 + static const struct pwrseq_unit_data pwrseq_qcom_wcn6855_xo_clk_assert = { 117 + .name = "xo-clk-assert", 118 + .enable = pwrseq_qcom_wcn6855_clk_assert, 119 + }; 120 + 121 + static const struct pwrseq_unit_data *pwrseq_qcom_wcn6855_unit_deps[] = { 122 + &pwrseq_qcom_wcn_vregs_unit_data, 123 + &pwrseq_qcom_wcn_clk_unit_data, 124 + &pwrseq_qcom_wcn6855_xo_clk_assert, 125 + NULL 126 + }; 127 + 103 128 static int pwrseq_qcom_wcn_bt_enable(struct pwrseq_device *pwrseq) 104 129 { 105 130 struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq); ··· 150 121 static const struct pwrseq_unit_data pwrseq_qcom_wcn_bt_unit_data = { 151 122 .name = "bluetooth-enable", 152 123 .deps = pwrseq_qcom_wcn_unit_deps, 124 + .enable = pwrseq_qcom_wcn_bt_enable, 125 + .disable = pwrseq_qcom_wcn_bt_disable, 126 + }; 127 + 128 + static const struct pwrseq_unit_data pwrseq_qcom_wcn6855_bt_unit_data = { 129 + .name = "wlan-enable", 130 + .deps = pwrseq_qcom_wcn6855_unit_deps, 153 131 .enable = pwrseq_qcom_wcn_bt_enable, 154 132 .disable = pwrseq_qcom_wcn_bt_disable, 155 133 }; ··· 188 152 .disable = pwrseq_qcom_wcn_wlan_disable, 189 153 }; 190 154 155 + static const struct pwrseq_unit_data pwrseq_qcom_wcn6855_wlan_unit_data = { 156 + .name = "wlan-enable", 157 + .deps = pwrseq_qcom_wcn6855_unit_deps, 158 + .enable = pwrseq_qcom_wcn_wlan_enable, 159 + .disable = pwrseq_qcom_wcn_wlan_disable, 160 + }; 161 + 191 162 static int pwrseq_qcom_wcn_pwup_delay(struct pwrseq_device *pwrseq) 192 163 { 193 164 struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq); ··· 203 160 msleep(ctx->pdata->pwup_delay_ms); 204 161 205 162 return 0; 163 + } 164 + 165 + static int pwrseq_qcom_wcn6855_xo_clk_deassert(struct pwrseq_device *pwrseq) 166 + { 167 + struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq); 168 + 169 + if (ctx->xo_clk_gpio) { 170 + usleep_range(2000, 5000); 171 + gpiod_set_value_cansleep(ctx->xo_clk_gpio, 0); 172 + } 173 + 174 + return pwrseq_qcom_wcn_pwup_delay(pwrseq); 206 175 } 207 176 208 177 static const struct pwrseq_target_data pwrseq_qcom_wcn_bt_target_data = { ··· 229 174 .post_enable = pwrseq_qcom_wcn_pwup_delay, 230 175 }; 231 176 177 + static const struct pwrseq_target_data pwrseq_qcom_wcn6855_bt_target_data = { 178 + .name = "bluetooth", 179 + .unit = &pwrseq_qcom_wcn6855_bt_unit_data, 180 + .post_enable = pwrseq_qcom_wcn6855_xo_clk_deassert, 181 + }; 182 + 183 + static const struct pwrseq_target_data pwrseq_qcom_wcn6855_wlan_target_data = { 184 + .name = "wlan", 185 + .unit = &pwrseq_qcom_wcn6855_wlan_unit_data, 186 + .post_enable = pwrseq_qcom_wcn6855_xo_clk_deassert, 187 + }; 188 + 232 189 static const struct pwrseq_target_data *pwrseq_qcom_wcn_targets[] = { 233 190 &pwrseq_qcom_wcn_bt_target_data, 234 191 &pwrseq_qcom_wcn_wlan_target_data, 192 + NULL 193 + }; 194 + 195 + static const struct pwrseq_target_data *pwrseq_qcom_wcn6855_targets[] = { 196 + &pwrseq_qcom_wcn6855_bt_target_data, 197 + &pwrseq_qcom_wcn6855_wlan_target_data, 235 198 NULL 236 199 }; 237 200 ··· 269 196 .num_vregs = ARRAY_SIZE(pwrseq_qca6390_vregs), 270 197 .pwup_delay_ms = 60, 271 198 .gpio_enable_delay_ms = 100, 199 + .targets = pwrseq_qcom_wcn_targets, 200 + }; 201 + 202 + static const char *const pwrseq_wcn6855_vregs[] = { 203 + "vddio", 204 + "vddaon", 205 + "vddpmu", 206 + "vddpmumx", 207 + "vddpmucx", 208 + "vddrfa0p95", 209 + "vddrfa1p3", 210 + "vddrfa1p9", 211 + "vddpcie1p3", 212 + "vddpcie1p9", 272 213 }; 273 214 274 215 static const struct pwrseq_qcom_wcn_pdata pwrseq_wcn6855_of_data = { 275 - .vregs = pwrseq_qca6390_vregs, 276 - .num_vregs = ARRAY_SIZE(pwrseq_qca6390_vregs), 216 + .vregs = pwrseq_wcn6855_vregs, 217 + .num_vregs = ARRAY_SIZE(pwrseq_wcn6855_vregs), 277 218 .pwup_delay_ms = 50, 278 219 .gpio_enable_delay_ms = 5, 220 + .targets = pwrseq_qcom_wcn6855_targets, 279 221 }; 280 222 281 223 static const char *const pwrseq_wcn7850_vregs[] = { ··· 307 219 .vregs = pwrseq_wcn7850_vregs, 308 220 .num_vregs = ARRAY_SIZE(pwrseq_wcn7850_vregs), 309 221 .pwup_delay_ms = 50, 222 + .targets = pwrseq_qcom_wcn_targets, 310 223 }; 311 224 312 225 static int pwrseq_qcom_wcn_match(struct pwrseq_device *pwrseq, ··· 384 295 return dev_err_probe(dev, PTR_ERR(ctx->wlan_gpio), 385 296 "Failed to get the WLAN enable GPIO\n"); 386 297 298 + ctx->xo_clk_gpio = devm_gpiod_get_optional(dev, "xo-clk", 299 + GPIOD_OUT_LOW); 300 + if (IS_ERR(ctx->xo_clk_gpio)) 301 + return dev_err_probe(dev, PTR_ERR(ctx->xo_clk_gpio), 302 + "Failed to get the XO_CLK GPIO\n"); 303 + 387 304 /* 388 305 * Set direction to output but keep the current value in order to not 389 306 * disable the WLAN module accidentally if it's already powered on. ··· 408 313 config.owner = THIS_MODULE; 409 314 config.drvdata = ctx; 410 315 config.match = pwrseq_qcom_wcn_match; 411 - config.targets = pwrseq_qcom_wcn_targets; 316 + config.targets = ctx->pdata->targets; 412 317 413 318 ctx->pwrseq = devm_pwrseq_device_register(dev, &config); 414 319 if (IS_ERR(ctx->pwrseq))