Skip to content

Commit

Permalink
power: sequencing: qcom-wcn: improve support for wcn6855
Browse files Browse the repository at this point in the history
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 <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Bartosz Golaszewski <[email protected]>
  • Loading branch information
Bartosz Golaszewski committed Oct 25, 2024
1 parent f82bf3c commit bd4c8ba
Showing 1 changed file with 98 additions and 3 deletions.
101 changes: 98 additions & 3 deletions drivers/power/sequencing/pwrseq-qcom-wcn.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ struct pwrseq_qcom_wcn_pdata {
size_t num_vregs;
unsigned int pwup_delay_ms;
unsigned int gpio_enable_delay_ms;
const struct pwrseq_target_data **targets;
};

struct pwrseq_qcom_wcn_ctx {
Expand All @@ -31,6 +32,7 @@ struct pwrseq_qcom_wcn_ctx {
struct regulator_bulk_data *regs;
struct gpio_desc *bt_gpio;
struct gpio_desc *wlan_gpio;
struct gpio_desc *xo_clk_gpio;
struct clk *clk;
unsigned long last_gpio_enable_jf;
};
Expand Down Expand Up @@ -98,6 +100,33 @@ static const struct pwrseq_unit_data *pwrseq_qcom_wcn_unit_deps[] = {
NULL
};

static int pwrseq_qcom_wcn6855_clk_assert(struct pwrseq_device *pwrseq)
{
struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);

if (!ctx->xo_clk_gpio)
return 0;

msleep(1);

gpiod_set_value_cansleep(ctx->xo_clk_gpio, 1);
usleep_range(100, 200);

return 0;
}

static const struct pwrseq_unit_data pwrseq_qcom_wcn6855_xo_clk_assert = {
.name = "xo-clk-assert",
.enable = pwrseq_qcom_wcn6855_clk_assert,
};

static const struct pwrseq_unit_data *pwrseq_qcom_wcn6855_unit_deps[] = {
&pwrseq_qcom_wcn_vregs_unit_data,
&pwrseq_qcom_wcn_clk_unit_data,
&pwrseq_qcom_wcn6855_xo_clk_assert,
NULL
};

static int pwrseq_qcom_wcn_bt_enable(struct pwrseq_device *pwrseq)
{
struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
Expand Down Expand Up @@ -125,6 +154,13 @@ static const struct pwrseq_unit_data pwrseq_qcom_wcn_bt_unit_data = {
.disable = pwrseq_qcom_wcn_bt_disable,
};

static const struct pwrseq_unit_data pwrseq_qcom_wcn6855_bt_unit_data = {
.name = "wlan-enable",
.deps = pwrseq_qcom_wcn6855_unit_deps,
.enable = pwrseq_qcom_wcn_bt_enable,
.disable = pwrseq_qcom_wcn_bt_disable,
};

static int pwrseq_qcom_wcn_wlan_enable(struct pwrseq_device *pwrseq)
{
struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
Expand Down Expand Up @@ -152,6 +188,13 @@ static const struct pwrseq_unit_data pwrseq_qcom_wcn_wlan_unit_data = {
.disable = pwrseq_qcom_wcn_wlan_disable,
};

static const struct pwrseq_unit_data pwrseq_qcom_wcn6855_wlan_unit_data = {
.name = "wlan-enable",
.deps = pwrseq_qcom_wcn6855_unit_deps,
.enable = pwrseq_qcom_wcn_wlan_enable,
.disable = pwrseq_qcom_wcn_wlan_disable,
};

static int pwrseq_qcom_wcn_pwup_delay(struct pwrseq_device *pwrseq)
{
struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
Expand All @@ -162,6 +205,18 @@ static int pwrseq_qcom_wcn_pwup_delay(struct pwrseq_device *pwrseq)
return 0;
}

static int pwrseq_qcom_wcn6855_xo_clk_deassert(struct pwrseq_device *pwrseq)
{
struct pwrseq_qcom_wcn_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);

if (ctx->xo_clk_gpio) {
usleep_range(2000, 5000);
gpiod_set_value_cansleep(ctx->xo_clk_gpio, 0);
}

return pwrseq_qcom_wcn_pwup_delay(pwrseq);
}

static const struct pwrseq_target_data pwrseq_qcom_wcn_bt_target_data = {
.name = "bluetooth",
.unit = &pwrseq_qcom_wcn_bt_unit_data,
Expand All @@ -174,12 +229,30 @@ static const struct pwrseq_target_data pwrseq_qcom_wcn_wlan_target_data = {
.post_enable = pwrseq_qcom_wcn_pwup_delay,
};

static const struct pwrseq_target_data pwrseq_qcom_wcn6855_bt_target_data = {
.name = "bluetooth",
.unit = &pwrseq_qcom_wcn6855_bt_unit_data,
.post_enable = pwrseq_qcom_wcn6855_xo_clk_deassert,
};

static const struct pwrseq_target_data pwrseq_qcom_wcn6855_wlan_target_data = {
.name = "wlan",
.unit = &pwrseq_qcom_wcn6855_wlan_unit_data,
.post_enable = pwrseq_qcom_wcn6855_xo_clk_deassert,
};

static const struct pwrseq_target_data *pwrseq_qcom_wcn_targets[] = {
&pwrseq_qcom_wcn_bt_target_data,
&pwrseq_qcom_wcn_wlan_target_data,
NULL
};

static const struct pwrseq_target_data *pwrseq_qcom_wcn6855_targets[] = {
&pwrseq_qcom_wcn6855_bt_target_data,
&pwrseq_qcom_wcn6855_wlan_target_data,
NULL
};

static const char *const pwrseq_qca6390_vregs[] = {
"vddio",
"vddaon",
Expand All @@ -196,13 +269,28 @@ static const struct pwrseq_qcom_wcn_pdata pwrseq_qca6390_of_data = {
.num_vregs = ARRAY_SIZE(pwrseq_qca6390_vregs),
.pwup_delay_ms = 60,
.gpio_enable_delay_ms = 100,
.targets = pwrseq_qcom_wcn_targets,
};

static const char *const pwrseq_wcn6855_vregs[] = {
"vddio",
"vddaon",
"vddpmu",
"vddpmumx",
"vddpmucx",
"vddrfa0p95",
"vddrfa1p3",
"vddrfa1p9",
"vddpcie1p3",
"vddpcie1p9",
};

static const struct pwrseq_qcom_wcn_pdata pwrseq_wcn6855_of_data = {
.vregs = pwrseq_qca6390_vregs,
.num_vregs = ARRAY_SIZE(pwrseq_qca6390_vregs),
.vregs = pwrseq_wcn6855_vregs,
.num_vregs = ARRAY_SIZE(pwrseq_wcn6855_vregs),
.pwup_delay_ms = 50,
.gpio_enable_delay_ms = 5,
.targets = pwrseq_qcom_wcn6855_targets,
};

static const char *const pwrseq_wcn7850_vregs[] = {
Expand All @@ -219,6 +307,7 @@ static const struct pwrseq_qcom_wcn_pdata pwrseq_wcn7850_of_data = {
.vregs = pwrseq_wcn7850_vregs,
.num_vregs = ARRAY_SIZE(pwrseq_wcn7850_vregs),
.pwup_delay_ms = 50,
.targets = pwrseq_qcom_wcn_targets,
};

static int pwrseq_qcom_wcn_match(struct pwrseq_device *pwrseq,
Expand Down Expand Up @@ -295,6 +384,12 @@ static int pwrseq_qcom_wcn_probe(struct platform_device *pdev)
return dev_err_probe(dev, PTR_ERR(ctx->wlan_gpio),
"Failed to get the WLAN enable GPIO\n");

ctx->xo_clk_gpio = devm_gpiod_get_optional(dev, "xo-clk",
GPIOD_OUT_LOW);
if (IS_ERR(ctx->xo_clk_gpio))
return dev_err_probe(dev, PTR_ERR(ctx->xo_clk_gpio),
"Failed to get the XO_CLK GPIO\n");

/*
* Set direction to output but keep the current value in order to not
* disable the WLAN module accidentally if it's already powered on.
Expand All @@ -313,7 +408,7 @@ static int pwrseq_qcom_wcn_probe(struct platform_device *pdev)
config.owner = THIS_MODULE;
config.drvdata = ctx;
config.match = pwrseq_qcom_wcn_match;
config.targets = pwrseq_qcom_wcn_targets;
config.targets = ctx->pdata->targets;

ctx->pwrseq = devm_pwrseq_device_register(dev, &config);
if (IS_ERR(ctx->pwrseq))
Expand Down

0 comments on commit bd4c8ba

Please sign in to comment.