Skip to content

Commit e61f1a7

Browse files
Vishnu Reddykrzk
authored andcommitted
pinctrl: samsung: Add support for pull-up and pull-down
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 <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Krzysztof Kozlowski <[email protected]>
1 parent d59c239 commit e61f1a7

File tree

4 files changed

+126
-0
lines changed

4 files changed

+126
-0
lines changed

drivers/pinctrl/samsung/pinctrl-exynos-arm.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,19 @@ static const struct samsung_pin_bank_type bank_type_alive = {
4040
#define S5P_OTHERS_RET_MMC (1 << 29)
4141
#define S5P_OTHERS_RET_UART (1 << 28)
4242

43+
#define S5P_PIN_PULL_DISABLE 0
44+
#define S5P_PIN_PULL_DOWN 1
45+
#define S5P_PIN_PULL_UP 2
46+
47+
static void s5pv210_pud_value_init(struct samsung_pinctrl_drv_data *drvdata)
48+
{
49+
unsigned int *pud_val = drvdata->pud_val;
50+
51+
pud_val[PUD_PULL_DISABLE] = S5P_PIN_PULL_DISABLE;
52+
pud_val[PUD_PULL_DOWN] = S5P_PIN_PULL_DOWN;
53+
pud_val[PUD_PULL_UP] = S5P_PIN_PULL_UP;
54+
}
55+
4356
static void s5pv210_retention_disable(struct samsung_pinctrl_drv_data *drvdata)
4457
{
4558
void __iomem *clk_base = (void __iomem *)drvdata->retention_ctrl->priv;
@@ -133,6 +146,7 @@ static const struct samsung_pin_ctrl s5pv210_pin_ctrl[] __initconst = {
133146
.nr_banks = ARRAY_SIZE(s5pv210_pin_bank),
134147
.eint_gpio_init = exynos_eint_gpio_init,
135148
.eint_wkup_init = exynos_eint_wkup_init,
149+
.pud_value_init = s5pv210_pud_value_init,
136150
.suspend = exynos_pinctrl_suspend,
137151
.resume = exynos_pinctrl_resume,
138152
.retention_data = &s5pv210_retention_data,

drivers/pinctrl/samsung/pinctrl-s3c64xx.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@
6363
#define EINT_CON_MASK 0xF
6464
#define EINT_CON_LEN 4
6565

66+
#define S3C_PIN_PULL_DISABLE 0
67+
#define S3C_PIN_PULL_DOWN 1
68+
#define S3C_PIN_PULL_UP 2
69+
6670
static const struct samsung_pin_bank_type bank_type_4bit_off = {
6771
.fld_width = { 4, 1, 2, 0, 2, 2, },
6872
.reg_offset = { 0x00, 0x04, 0x08, 0, 0x0c, 0x10, },
@@ -255,6 +259,15 @@ static int s3c64xx_irq_get_trigger(unsigned int type)
255259
return trigger;
256260
}
257261

262+
static void s3c64xx_pud_value_init(struct samsung_pinctrl_drv_data *drvdata)
263+
{
264+
unsigned int *pud_val = drvdata->pud_val;
265+
266+
pud_val[PUD_PULL_DISABLE] = S3C_PIN_PULL_DISABLE;
267+
pud_val[PUD_PULL_DOWN] = S3C_PIN_PULL_DOWN;
268+
pud_val[PUD_PULL_UP] = S3C_PIN_PULL_UP;
269+
}
270+
258271
static void s3c64xx_irq_set_handler(struct irq_data *d, unsigned int type)
259272
{
260273
/* Edge- and level-triggered interrupts need different handlers */
@@ -797,6 +810,7 @@ static const struct samsung_pin_ctrl s3c64xx_pin_ctrl[] __initconst = {
797810
.nr_banks = ARRAY_SIZE(s3c64xx_pin_banks0),
798811
.eint_gpio_init = s3c64xx_eint_gpio_init,
799812
.eint_wkup_init = s3c64xx_eint_eint0_init,
813+
.pud_value_init = s3c64xx_pud_value_init,
800814
},
801815
};
802816

drivers/pinctrl/samsung/pinctrl-samsung.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -988,6 +988,77 @@ static int samsung_pinctrl_unregister(struct platform_device *pdev,
988988
return 0;
989989
}
990990

991+
static void samsung_pud_value_init(struct samsung_pinctrl_drv_data *drvdata)
992+
{
993+
unsigned int *pud_val = drvdata->pud_val;
994+
995+
pud_val[PUD_PULL_DISABLE] = EXYNOS_PIN_PUD_PULL_DISABLE;
996+
pud_val[PUD_PULL_DOWN] = EXYNOS_PIN_PID_PULL_DOWN;
997+
pud_val[PUD_PULL_UP] = EXYNOS_PIN_PID_PULL_UP;
998+
}
999+
1000+
/*
1001+
* Enable or Disable the pull-down and pull-up for the gpio pins in the
1002+
* PUD register.
1003+
*/
1004+
static void samsung_gpio_set_pud(struct gpio_chip *gc, unsigned int offset,
1005+
unsigned int value)
1006+
{
1007+
struct samsung_pin_bank *bank = gpiochip_get_data(gc);
1008+
const struct samsung_pin_bank_type *type = bank->type;
1009+
void __iomem *reg;
1010+
unsigned int data, mask;
1011+
1012+
reg = bank->pctl_base + bank->pctl_offset;
1013+
data = readl(reg + type->reg_offset[PINCFG_TYPE_PUD]);
1014+
mask = (1 << type->fld_width[PINCFG_TYPE_PUD]) - 1;
1015+
data &= ~(mask << (offset * type->fld_width[PINCFG_TYPE_PUD]));
1016+
data |= value << (offset * type->fld_width[PINCFG_TYPE_PUD]);
1017+
writel(data, reg + type->reg_offset[PINCFG_TYPE_PUD]);
1018+
}
1019+
1020+
/*
1021+
* Identify the type of PUD config based on the gpiolib request to enable
1022+
* or disable the PUD config.
1023+
*/
1024+
static int samsung_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
1025+
unsigned long config)
1026+
{
1027+
struct samsung_pin_bank *bank = gpiochip_get_data(gc);
1028+
struct samsung_pinctrl_drv_data *drvdata = bank->drvdata;
1029+
unsigned int value;
1030+
int ret = 0;
1031+
unsigned long flags;
1032+
1033+
switch (pinconf_to_config_param(config)) {
1034+
case PIN_CONFIG_BIAS_DISABLE:
1035+
value = drvdata->pud_val[PUD_PULL_DISABLE];
1036+
break;
1037+
case PIN_CONFIG_BIAS_PULL_DOWN:
1038+
value = drvdata->pud_val[PUD_PULL_DOWN];
1039+
break;
1040+
case PIN_CONFIG_BIAS_PULL_UP:
1041+
value = drvdata->pud_val[PUD_PULL_UP];
1042+
break;
1043+
default:
1044+
return -ENOTSUPP;
1045+
}
1046+
1047+
ret = clk_enable(drvdata->pclk);
1048+
if (ret) {
1049+
dev_err(drvdata->dev, "failed to enable clock\n");
1050+
return ret;
1051+
}
1052+
1053+
raw_spin_lock_irqsave(&bank->slock, flags);
1054+
samsung_gpio_set_pud(gc, offset, value);
1055+
raw_spin_unlock_irqrestore(&bank->slock, flags);
1056+
1057+
clk_disable(drvdata->pclk);
1058+
1059+
return ret;
1060+
}
1061+
9911062
static const struct gpio_chip samsung_gpiolib_chip = {
9921063
.request = gpiochip_generic_request,
9931064
.free = gpiochip_generic_free,
@@ -997,6 +1068,7 @@ static const struct gpio_chip samsung_gpiolib_chip = {
9971068
.direction_output = samsung_gpio_direction_output,
9981069
.to_irq = samsung_gpio_to_irq,
9991070
.add_pin_ranges = samsung_add_pin_ranges,
1071+
.set_config = samsung_gpio_set_config,
10001072
.owner = THIS_MODULE,
10011073
};
10021074

@@ -1228,6 +1300,11 @@ static int samsung_pinctrl_probe(struct platform_device *pdev)
12281300
if (ctrl->eint_wkup_init)
12291301
ctrl->eint_wkup_init(drvdata);
12301302

1303+
if (ctrl->pud_value_init)
1304+
ctrl->pud_value_init(drvdata);
1305+
else
1306+
samsung_pud_value_init(drvdata);
1307+
12311308
ret = samsung_gpiolib_register(pdev, drvdata);
12321309
if (ret)
12331310
goto err_unregister;

drivers/pinctrl/samsung/pinctrl-samsung.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,25 @@ enum pincfg_type {
6161
#define PIN_CON_FUNC_INPUT 0x0
6262
#define PIN_CON_FUNC_OUTPUT 0x1
6363

64+
/* Values for the pin PUD register */
65+
#define EXYNOS_PIN_PUD_PULL_DISABLE 0x0
66+
#define EXYNOS_PIN_PID_PULL_DOWN 0x1
67+
#define EXYNOS_PIN_PID_PULL_UP 0x3
68+
69+
/*
70+
* enum pud_index - Possible index values to access the pud_val array.
71+
* @PUD_PULL_DISABLE: Index for the value of pud disable
72+
* @PUD_PULL_DOWN: Index for the value of pull down enable
73+
* @PUD_PULL_UP: Index for the value of pull up enable
74+
* @PUD_MAX: Maximum value of the index
75+
*/
76+
enum pud_index {
77+
PUD_PULL_DISABLE,
78+
PUD_PULL_DOWN,
79+
PUD_PULL_UP,
80+
PUD_MAX,
81+
};
82+
6483
/**
6584
* enum eint_type - possible external interrupt types.
6685
* @EINT_TYPE_NONE: bank does not support external interrupts
@@ -261,6 +280,7 @@ struct samsung_pin_ctrl {
261280

262281
int (*eint_gpio_init)(struct samsung_pinctrl_drv_data *);
263282
int (*eint_wkup_init)(struct samsung_pinctrl_drv_data *);
283+
void (*pud_value_init)(struct samsung_pinctrl_drv_data *drvdata);
264284
void (*suspend)(struct samsung_pinctrl_drv_data *);
265285
void (*resume)(struct samsung_pinctrl_drv_data *);
266286
};
@@ -307,6 +327,7 @@ struct samsung_pinctrl_drv_data {
307327
struct samsung_pin_bank *pin_banks;
308328
unsigned int nr_banks;
309329
unsigned int nr_pins;
330+
unsigned int pud_val[PUD_MAX];
310331

311332
struct samsung_retention_ctrl *retention_ctrl;
312333

0 commit comments

Comments
 (0)