[PATCH v2] pinctrl: samsung: Add support for pull-up and pull-down

Vishnu Reddy vishnu.reddy at samsung.com
Thu Jun 20 03:34:10 PDT 2024


gpiolib framework has the implementation of setting up the
PUD configuration for GPIO pins but there is no driver support.

Add support to handle the PUD configuration request from the
userspace in samsung pinctrl driver.

Signed-off-by: Vishnu Reddy <vishnu.reddy at samsung.com>
---
Verified the offset from the user manual of following Exynos SoC series
and found the current code is taking care of correct offset for pull-up
and pull-down

Exynos-3250
Exynos-3470
Exynos-4412
Exynos-4415
Exynos-5250
Exynos-5260
Exynos-5410
Exynos-5420
Exynos-5422
Exynos-7420
Exynos-7580
Exynos-7880
Exynos-9820
Exynos-9830
Exynos-4210
Exynos-S5PC210
Exynos-S5PV310

This patch is tested on FSD platform

 drivers/pinctrl/samsung/pinctrl-samsung.c | 53 +++++++++++++++++++++++
 drivers/pinctrl/samsung/pinctrl-samsung.h |  7 +++
 2 files changed, 60 insertions(+)

diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index 623df65a5d6f..13e8109d002a 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -997,6 +997,58 @@ static int samsung_pinctrl_unregister(struct platform_device *pdev,
 	return 0;
 }
 
+/*
+ * samsung_gpio_set_pud will enable or disable the pull-down and
+ * pull-up for the gpio pins in the PUD register.
+ */
+static void samsung_gpio_set_pud(struct gpio_chip *gc, unsigned int offset,
+				 unsigned int value)
+{
+	struct samsung_pin_bank *bank = gpiochip_get_data(gc);
+	const struct samsung_pin_bank_type *type = bank->type;
+	void __iomem *reg;
+	unsigned int data, mask;
+
+	reg = bank->pctl_base + bank->pctl_offset;
+	data = readl(reg + type->reg_offset[PINCFG_TYPE_PUD]);
+	mask = (1 << type->fld_width[PINCFG_TYPE_PUD]) - 1;
+	data &= ~(mask << (offset * type->fld_width[PINCFG_TYPE_PUD]));
+	data |= value << (offset * type->fld_width[PINCFG_TYPE_PUD]);
+	writel(data, reg + type->reg_offset[PINCFG_TYPE_PUD]);
+}
+
+/*
+ * samsung_gpio_set_config will identify the type of PUD config based
+ * on the gpiolib request to enable or disable the PUD configuration.
+ */
+static int samsung_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
+				   unsigned long config)
+{
+	struct samsung_pin_bank *bank = gpiochip_get_data(gc);
+	unsigned long flags;
+	unsigned int value = 0;
+
+	switch (pinconf_to_config_param(config)) {
+	case PIN_CONFIG_BIAS_DISABLE:
+		value = PIN_PUD_PULL_UP_DOWN_DISABLE;
+		break;
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		value = PIN_PUD_PULL_DOWN_ENABLE;
+		break;
+	case PIN_CONFIG_BIAS_PULL_UP:
+		value = PIN_PUD_PULL_UP_ENABLE;
+		break;
+	default:
+		return -ENOTSUPP;
+	}
+
+	raw_spin_lock_irqsave(&bank->slock, flags);
+	samsung_gpio_set_pud(gc, offset, value);
+	raw_spin_unlock_irqrestore(&bank->slock, flags);
+
+	return 0;
+}
+
 static const struct gpio_chip samsung_gpiolib_chip = {
 	.request = gpiochip_generic_request,
 	.free = gpiochip_generic_free,
@@ -1006,6 +1058,7 @@ static const struct gpio_chip samsung_gpiolib_chip = {
 	.direction_output = samsung_gpio_direction_output,
 	.to_irq = samsung_gpio_to_irq,
 	.add_pin_ranges = samsung_add_pin_ranges,
+	.set_config = samsung_gpio_set_config,
 	.owner = THIS_MODULE,
 };
 
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h
index d50ba6f07d5d..758b623a4bea 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.h
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.h
@@ -61,6 +61,13 @@ enum pincfg_type {
 #define PIN_CON_FUNC_INPUT		0x0
 #define PIN_CON_FUNC_OUTPUT		0x1
 
+/*
+ * Values for the pin PUD register.
+ */
+#define PIN_PUD_PULL_UP_DOWN_DISABLE	0x0
+#define PIN_PUD_PULL_DOWN_ENABLE	0x1
+#define PIN_PUD_PULL_UP_ENABLE		0x3
+
 /**
  * enum eint_type - possible external interrupt types.
  * @EINT_TYPE_NONE: bank does not support external interrupts
-- 
2.17.1




More information about the linux-arm-kernel mailing list