[PATCH 0/3] qcom: support SPMI buttons on SM8550 and SM8650

First add PMIC gpio variant on pm8550-gpio, then rework the qcom-pmic button driver to support data structs for each PMIC variant and finally add the data for the pmk8350 button configs.
Signed-off-by: Neil Armstrong neil.armstrong@linaro.org --- Neil Armstrong (3): gpio: qcom_pmic_gpio: add support for pm8550-gpio button: qcom-pmic: move node name checks to btn_data struct button: qcom-pmic: add support for pmk8350 button configs
drivers/button/button-qcom-pmic.c | 98 ++++++++++++++++++++++++++++----------- drivers/gpio/qcom_pmic_gpio.c | 18 ++++++- 2 files changed, 86 insertions(+), 30 deletions(-) --- base-commit: f0e6aba1218bca578605697eed8aa94582bf57bb change-id: 20240404-topic-sm8x50-spmi-clients-d9a085aae979
Best regards,

Add support for PM8550 GPIO controller variant, keep read-only until the GPIO and Pinctrl setup is fixed for new PMICs.
Signed-off-by: Neil Armstrong neil.armstrong@linaro.org --- drivers/gpio/qcom_pmic_gpio.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/gpio/qcom_pmic_gpio.c b/drivers/gpio/qcom_pmic_gpio.c index 14a8210522b..dfb70faf94b 100644 --- a/drivers/gpio/qcom_pmic_gpio.c +++ b/drivers/gpio/qcom_pmic_gpio.c @@ -35,6 +35,8 @@ #define REG_SUBTYPE_GPIOC_8CH 0xd #define REG_SUBTYPE_GPIO_LV 0x10 #define REG_SUBTYPE_GPIO_MV 0x11 +#define REG_SUBTYPE_GPIO_LV_VIN2 0x12 +#define REG_SUBTYPE_GPIO_MV_VIN3 0x13
#define REG_STATUS 0x08 #define REG_STATUS_VAL_MASK 0x1 @@ -322,9 +324,20 @@ static int qcom_gpio_probe(struct udevice *dev) return log_msg_ret("bad type", -ENXIO);
val = pmic_reg_read(plat->pmic, plat->pid + REG_SUBTYPE); - if (val != REG_SUBTYPE_GPIO_4CH && val != REG_SUBTYPE_GPIOC_4CH && - val != REG_SUBTYPE_GPIO_LV && val != REG_SUBTYPE_GPIO_MV) + switch (val) { + case REG_SUBTYPE_GPIO_4CH: + case REG_SUBTYPE_GPIOC_4CH: + plat->lv_mv_type = false; + break; + case REG_SUBTYPE_GPIO_LV: + case REG_SUBTYPE_GPIO_MV: + case REG_SUBTYPE_GPIO_LV_VIN2: + case REG_SUBTYPE_GPIO_MV_VIN3: + plat->lv_mv_type = true; + break; + default: return log_msg_ret("bad subtype", -ENXIO); + }
plat->lv_mv_type = val == REG_SUBTYPE_GPIO_LV || val == REG_SUBTYPE_GPIO_MV; @@ -351,6 +364,7 @@ static const struct udevice_id qcom_gpio_ids[] = { { .compatible = "qcom,pm8994-gpio" }, /* 22 GPIO's */ { .compatible = "qcom,pm8998-gpio", .data = QCOM_PMIC_QUIRK_READONLY }, { .compatible = "qcom,pms405-gpio" }, + { .compatible = "qcom,pm8550-gpio", .data = QCOM_PMIC_QUIRK_READONLY }, { } };

Move node name checks to a proper data struct with all information for the supported subnodes.
Replace the key offset defines with the Linux driver ones.
Signed-off-by: Neil Armstrong neil.armstrong@linaro.org --- drivers/button/button-qcom-pmic.c | 84 ++++++++++++++++++++++++++------------- 1 file changed, 56 insertions(+), 28 deletions(-)
diff --git a/drivers/button/button-qcom-pmic.c b/drivers/button/button-qcom-pmic.c index bad445efa86..f6da958097c 100644 --- a/drivers/button/button-qcom-pmic.c +++ b/drivers/button/button-qcom-pmic.c @@ -19,6 +19,13 @@ #define REG_TYPE 0x4 #define REG_SUBTYPE 0x5
+struct qcom_pmic_btn_data { + char *compatible; + unsigned int status_bit; + int code; + char *label; +}; + struct qcom_pmic_btn_priv { u32 base; u32 status_bit; @@ -27,11 +34,8 @@ struct qcom_pmic_btn_priv { };
#define PON_INT_RT_STS 0x10 -#define KPDPWR_ON_INT_BIT 0 -#define RESIN_ON_INT_BIT 1 - -#define NODE_IS_PWRKEY(node) (!strncmp(ofnode_get_name(node), "pwrkey", strlen("pwrkey"))) -#define NODE_IS_RESIN(node) (!strncmp(ofnode_get_name(node), "resin", strlen("resin"))) +#define PON_KPDPWR_N_SET 0 +#define PON_RESIN_N_SET 1
static enum button_state_t qcom_pwrkey_get_state(struct udevice *dev) { @@ -52,10 +56,39 @@ static int qcom_pwrkey_get_code(struct udevice *dev) return priv->code; }
+static const struct qcom_pmic_btn_data qcom_pmic_btn_data_table[] = { + { + .compatible = "qcom,pm8941-pwrkey", + .status_bit = PON_KPDPWR_N_SET, + .code = KEY_ENTER, + .label = "pwrkey", + }, + { + .compatible = "qcom,pm8941-resin", + .status_bit = PON_RESIN_N_SET, + .code = KEY_DOWN, + .label = "vol_down", + }, +}; + +static const struct qcom_pmic_btn_data *button_qcom_pmic_match(ofnode node) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(qcom_pmic_btn_data_table); ++i) { + if (ofnode_device_is_compatible(node, + qcom_pmic_btn_data_table[i].compatible)) + return &qcom_pmic_btn_data_table[i]; + } + + return NULL; +} + static int qcom_pwrkey_probe(struct udevice *dev) { struct button_uc_plat *uc_plat = dev_get_uclass_plat(dev); struct qcom_pmic_btn_priv *priv = dev_get_priv(dev); + const struct qcom_pmic_btn_data *btn_data; ofnode node = dev_ofnode(dev); int ret; u64 base; @@ -64,6 +97,14 @@ static int qcom_pwrkey_probe(struct udevice *dev) if (!uc_plat->label) return 0;
+ /* Get the data for the node compatible */ + btn_data = button_qcom_pmic_match(node); + if (!btn_data) + return -EINVAL; + + priv->status_bit = btn_data->status_bit; + priv->code = btn_data->code; + /* the pwrkey and resin nodes are children of the "pon" node, get the * PMIC device to use in pmic_reg_* calls. */ @@ -87,23 +128,10 @@ static int qcom_pwrkey_probe(struct udevice *dev)
ret = pmic_reg_read(priv->pmic, priv->base + REG_SUBTYPE); if (ret < 0 || (ret & 0x7) == 0) { - printf("%s: unexpected PMCI function subtype %d\n", dev->name, ret); + printf("%s: unexpected PMIC function subtype %d\n", dev->name, ret); return -ENXIO; }
- if (NODE_IS_PWRKEY(node)) { - priv->status_bit = 0; - priv->code = KEY_ENTER; - } else if (NODE_IS_RESIN(node)) { - priv->status_bit = 1; - priv->code = KEY_DOWN; - } else { - /* Should not get here! */ - printf("Invalid pon node '%s' should be 'pwrkey' or 'resin'\n", - ofnode_get_name(node)); - return -EINVAL; - } - return 0; }
@@ -114,12 +142,20 @@ static int button_qcom_pmic_bind(struct udevice *parent) int ret;
dev_for_each_subnode(node, parent) { + const struct qcom_pmic_btn_data *btn_data; struct button_uc_plat *uc_plat; const char *label;
if (!ofnode_is_enabled(node)) continue;
+ /* Get the data for the node compatible */ + btn_data = button_qcom_pmic_match(node); + if (!btn_data) { + debug("Unknown button node '%s'\n", ofnode_get_name(node)); + continue; + } + ret = device_bind_driver_to_node(parent, "qcom_pwrkey", ofnode_get_name(node), node, &dev); @@ -128,15 +164,7 @@ static int button_qcom_pmic_bind(struct udevice *parent) return ret; } uc_plat = dev_get_uclass_plat(dev); - if (NODE_IS_PWRKEY(node)) { - uc_plat->label = "pwrkey"; - } else if (NODE_IS_RESIN(node)) { - uc_plat->label = "vol_down"; - } else { - debug("Unknown button node '%s' should be 'pwrkey' or 'resin'\n", - ofnode_get_name(node)); - device_unbind(dev); - } + uc_plat->label = btn_data->label; }
return 0;

Finally add the entries for the qcom,pmk8350-pwrkey and qcom,pmk8350-resin found on PMICs used with SM8350 and later SoCs.
Signed-off-by: Neil Armstrong neil.armstrong@linaro.org --- drivers/button/button-qcom-pmic.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/drivers/button/button-qcom-pmic.c b/drivers/button/button-qcom-pmic.c index f6da958097c..6153601017b 100644 --- a/drivers/button/button-qcom-pmic.c +++ b/drivers/button/button-qcom-pmic.c @@ -36,6 +36,8 @@ struct qcom_pmic_btn_priv { #define PON_INT_RT_STS 0x10 #define PON_KPDPWR_N_SET 0 #define PON_RESIN_N_SET 1 +#define PON_GEN3_RESIN_N_SET 6 +#define PON_GEN3_KPDPWR_N_SET 7
static enum button_state_t qcom_pwrkey_get_state(struct udevice *dev) { @@ -69,6 +71,18 @@ static const struct qcom_pmic_btn_data qcom_pmic_btn_data_table[] = { .code = KEY_DOWN, .label = "vol_down", }, + { + .compatible = "qcom,pmk8350-pwrkey", + .status_bit = PON_GEN3_KPDPWR_N_SET, + .code = KEY_ENTER, + .label = "pwrkey", + }, + { + .compatible = "qcom,pmk8350-resin", + .status_bit = PON_GEN3_RESIN_N_SET, + .code = KEY_DOWN, + .label = "vol_down", + }, };
static const struct qcom_pmic_btn_data *button_qcom_pmic_match(ofnode node)

On 05/04/2024 10:27, Neil Armstrong wrote:
Finally add the entries for the qcom,pmk8350-pwrkey and qcom,pmk8350-resin found on PMICs used with SM8350 and later SoCs.
Signed-off-by: Neil Armstrong neil.armstrong@linaro.org
drivers/button/button-qcom-pmic.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/drivers/button/button-qcom-pmic.c b/drivers/button/button-qcom-pmic.c index f6da958097c..6153601017b 100644 --- a/drivers/button/button-qcom-pmic.c +++ b/drivers/button/button-qcom-pmic.c @@ -36,6 +36,8 @@ struct qcom_pmic_btn_priv { #define PON_INT_RT_STS 0x10 #define PON_KPDPWR_N_SET 0 #define PON_RESIN_N_SET 1 +#define PON_GEN3_RESIN_N_SET 6 +#define PON_GEN3_KPDPWR_N_SET 7
static enum button_state_t qcom_pwrkey_get_state(struct udevice *dev) { @@ -69,6 +71,18 @@ static const struct qcom_pmic_btn_data qcom_pmic_btn_data_table[] = { .code = KEY_DOWN, .label = "vol_down", },
{
.compatible = "qcom,pmk8350-pwrkey",
.status_bit = PON_GEN3_KPDPWR_N_SET,
.code = KEY_ENTER,
.label = "pwrkey",
},
{
.compatible = "qcom,pmk8350-resin",
.status_bit = PON_GEN3_RESIN_N_SET,
.code = KEY_DOWN,
.label = "vol_down",
}, };
static const struct qcom_pmic_btn_data *button_qcom_pmic_match(ofnode node)
Missing change:
diff --git a/drivers/button/button-qcom-pmic.c b/drivers/button/button-qcom-pmic.c index 6153601017b..ad7fed3ddaa 100644 --- a/drivers/button/button-qcom-pmic.c +++ b/drivers/button/button-qcom-pmic.c @@ -193,6 +193,7 @@ static const struct udevice_id qcom_pwrkey_ids[] = { { .compatible = "qcom,pm8916-pon" }, { .compatible = "qcom,pm8941-pon" }, { .compatible = "qcom,pm8998-pon" }, + { .compatible = "qcom,pmk8350-pon" }, { } };
Will send a v2 in a few days.
Neil
participants (1)
-
Neil Armstrong