Skip to content

Commit cd77b0d

Browse files
committed
Merge tag 'samsung-pinctrl-6.12' of https://git.kernel.org/pub/scm/linux/kernel/git/pinctrl/samsung into devel
Samsung pinctrl drivers changes for v6.12 1. Few cleanups: use more appropriate of_property_present(), use scoped OF nodes handling and switch to kmemdup_array(). 2. Implement configuring pull-up and pull-down via GPIOLIB. Signed-off-by: Linus Walleij <[email protected]>
2 parents 9b82ec8 + 39dbbd4 commit cd77b0d

File tree

5 files changed

+141
-32
lines changed

5 files changed

+141
-32
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-exynos.c

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,7 @@ static void exynos_irq_demux_eint16_31(struct irq_desc *desc)
662662
__init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
663663
{
664664
struct device *dev = d->dev;
665-
struct device_node *wkup_np = NULL;
665+
struct device_node *wkup_np __free(device_node) = NULL;
666666
struct device_node *np;
667667
struct samsung_pin_bank *bank;
668668
struct exynos_weint_data *weint_data;
@@ -692,17 +692,14 @@ __init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
692692

693693
bank->irq_chip = devm_kmemdup(dev, irq_chip, sizeof(*irq_chip),
694694
GFP_KERNEL);
695-
if (!bank->irq_chip) {
696-
of_node_put(wkup_np);
695+
if (!bank->irq_chip)
697696
return -ENOMEM;
698-
}
699697
bank->irq_chip->chip.name = bank->name;
700698

701699
bank->irq_domain = irq_domain_create_linear(bank->fwnode,
702700
bank->nr_pins, &exynos_eint_irqd_ops, bank);
703701
if (!bank->irq_domain) {
704702
dev_err(dev, "wkup irq domain add failed\n");
705-
of_node_put(wkup_np);
706703
return -ENXIO;
707704
}
708705

@@ -715,10 +712,8 @@ __init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
715712
weint_data = devm_kcalloc(dev,
716713
bank->nr_pins, sizeof(*weint_data),
717714
GFP_KERNEL);
718-
if (!weint_data) {
719-
of_node_put(wkup_np);
715+
if (!weint_data)
720716
return -ENOMEM;
721-
}
722717

723718
for (idx = 0; idx < bank->nr_pins; ++idx) {
724719
irq = irq_of_parse_and_map(to_of_node(bank->fwnode), idx);
@@ -735,13 +730,10 @@ __init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
735730
}
736731
}
737732

738-
if (!muxed_banks) {
739-
of_node_put(wkup_np);
733+
if (!muxed_banks)
740734
return 0;
741-
}
742735

743736
irq = irq_of_parse_and_map(wkup_np, 0);
744-
of_node_put(wkup_np);
745737
if (!irq) {
746738
dev_err(dev, "irq number for muxed EINTs not found\n");
747739
return 0;

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: 88 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,8 @@ static int add_map_configs(struct device *dev, struct pinctrl_map **map,
122122
if (WARN_ON(*num_maps == *reserved_maps))
123123
return -ENOSPC;
124124

125-
dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs),
126-
GFP_KERNEL);
125+
dup_configs = kmemdup_array(configs, num_configs, sizeof(*dup_configs),
126+
GFP_KERNEL);
127127
if (!dup_configs)
128128
return -ENOMEM;
129129

@@ -251,7 +251,6 @@ static int samsung_dt_node_to_map(struct pinctrl_dev *pctldev,
251251
{
252252
struct samsung_pinctrl_drv_data *drvdata;
253253
unsigned reserved_maps;
254-
struct device_node *np;
255254
int ret;
256255

257256
drvdata = pinctrl_dev_get_drvdata(pctldev);
@@ -266,12 +265,11 @@ static int samsung_dt_node_to_map(struct pinctrl_dev *pctldev,
266265
&reserved_maps,
267266
num_maps);
268267

269-
for_each_child_of_node(np_config, np) {
268+
for_each_child_of_node_scoped(np_config, np) {
270269
ret = samsung_dt_subnode_to_map(drvdata, pctldev->dev, np, map,
271270
&reserved_maps, num_maps);
272271
if (ret < 0) {
273272
samsung_dt_free_map(pctldev, *map, *num_maps);
274-
of_node_put(np);
275273
return ret;
276274
}
277275
}
@@ -823,16 +821,16 @@ static struct samsung_pmx_func *samsung_pinctrl_create_functions(
823821
struct device_node *func_np;
824822

825823
if (!of_get_child_count(cfg_np)) {
826-
if (!of_find_property(cfg_np,
827-
"samsung,pin-function", NULL))
824+
if (!of_property_present(cfg_np,
825+
"samsung,pin-function"))
828826
continue;
829827
++func_cnt;
830828
continue;
831829
}
832830

833831
for_each_child_of_node(cfg_np, func_np) {
834-
if (!of_find_property(func_np,
835-
"samsung,pin-function", NULL))
832+
if (!of_property_present(func_np,
833+
"samsung,pin-function"))
836834
continue;
837835
++func_cnt;
838836
}
@@ -849,31 +847,24 @@ static struct samsung_pmx_func *samsung_pinctrl_create_functions(
849847
* and create pin groups and pin function lists.
850848
*/
851849
func_cnt = 0;
852-
for_each_child_of_node(dev_np, cfg_np) {
853-
struct device_node *func_np;
854-
850+
for_each_child_of_node_scoped(dev_np, cfg_np) {
855851
if (!of_get_child_count(cfg_np)) {
856852
ret = samsung_pinctrl_create_function(dev, drvdata,
857853
cfg_np, func);
858-
if (ret < 0) {
859-
of_node_put(cfg_np);
854+
if (ret < 0)
860855
return ERR_PTR(ret);
861-
}
862856
if (ret > 0) {
863857
++func;
864858
++func_cnt;
865859
}
866860
continue;
867861
}
868862

869-
for_each_child_of_node(cfg_np, func_np) {
863+
for_each_child_of_node_scoped(cfg_np, func_np) {
870864
ret = samsung_pinctrl_create_function(dev, drvdata,
871865
func_np, func);
872-
if (ret < 0) {
873-
of_node_put(func_np);
874-
of_node_put(cfg_np);
866+
if (ret < 0)
875867
return ERR_PTR(ret);
876-
}
877868
if (ret > 0) {
878869
++func;
879870
++func_cnt;
@@ -997,6 +988,77 @@ static int samsung_pinctrl_unregister(struct platform_device *pdev,
997988
return 0;
998989
}
999990

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+
10001062
static const struct gpio_chip samsung_gpiolib_chip = {
10011063
.request = gpiochip_generic_request,
10021064
.free = gpiochip_generic_free,
@@ -1006,6 +1068,7 @@ static const struct gpio_chip samsung_gpiolib_chip = {
10061068
.direction_output = samsung_gpio_direction_output,
10071069
.to_irq = samsung_gpio_to_irq,
10081070
.add_pin_ranges = samsung_add_pin_ranges,
1071+
.set_config = samsung_gpio_set_config,
10091072
.owner = THIS_MODULE,
10101073
};
10111074

@@ -1237,6 +1300,11 @@ static int samsung_pinctrl_probe(struct platform_device *pdev)
12371300
if (ctrl->eint_wkup_init)
12381301
ctrl->eint_wkup_init(drvdata);
12391302

1303+
if (ctrl->pud_value_init)
1304+
ctrl->pud_value_init(drvdata);
1305+
else
1306+
samsung_pud_value_init(drvdata);
1307+
12401308
ret = samsung_gpiolib_register(pdev, drvdata);
12411309
if (ret)
12421310
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)