@@ -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+
9911062static 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 ;
0 commit comments