diff options
Diffstat (limited to 'drivers/pinctrl/pinctrl-at91-pio4.c')
-rw-r--r-- | drivers/pinctrl/pinctrl-at91-pio4.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c index 67e4d9ffa6b1..8f061971a7d1 100644 --- a/drivers/pinctrl/pinctrl-at91-pio4.c +++ b/drivers/pinctrl/pinctrl-at91-pio4.c @@ -14,6 +14,7 @@ * GNU General Public License for more details. */ +#include <dt-bindings/pinctrl/at91.h> #include <linux/clk.h> #include <linux/gpio/driver.h> /* FIXME: needed for gpio_to_irq(), get rid of this */ @@ -49,6 +50,8 @@ #define ATMEL_PIO_IFSCEN_MASK BIT(13) #define ATMEL_PIO_OPD_MASK BIT(14) #define ATMEL_PIO_SCHMITT_MASK BIT(15) +#define ATMEL_PIO_DRVSTR_MASK GENMASK(17, 16) +#define ATMEL_PIO_DRVSTR_OFFSET 16 #define ATMEL_PIO_CFGR_EVTSEL_MASK GENMASK(26, 24) #define ATMEL_PIO_CFGR_EVTSEL_FALLING (0 << 24) #define ATMEL_PIO_CFGR_EVTSEL_RISING (1 << 24) @@ -75,6 +78,9 @@ #define ATMEL_GET_PIN_FUNC(pinfunc) ((pinfunc >> 16) & 0xf) #define ATMEL_GET_PIN_IOSET(pinfunc) ((pinfunc >> 20) & 0xf) +/* Custom pinconf parameters */ +#define ATMEL_PIN_CONFIG_DRIVE_STRENGTH (PIN_CONFIG_END + 1) + struct atmel_pioctrl_data { unsigned nbanks; }; @@ -139,6 +145,10 @@ static const char * const atmel_functions[] = { "GPIO", "A", "B", "C", "D", "E", "F", "G" }; +static const struct pinconf_generic_params atmel_custom_bindings[] = { + {"atmel,drive-strength", ATMEL_PIN_CONFIG_DRIVE_STRENGTH, 0}, +}; + /* --- GPIO --- */ static unsigned int atmel_gpio_read(struct atmel_pioctrl *atmel_pioctrl, unsigned int bank, unsigned int reg) @@ -692,6 +702,11 @@ static int atmel_conf_pin_config_group_get(struct pinctrl_dev *pctldev, return -EINVAL; arg = 1; break; + case ATMEL_PIN_CONFIG_DRIVE_STRENGTH: + if (!(res & ATMEL_PIO_DRVSTR_MASK)) + return -EINVAL; + arg = (res & ATMEL_PIO_DRVSTR_MASK) >> ATMEL_PIO_DRVSTR_OFFSET; + break; default: return -ENOTSUPP; } @@ -777,6 +792,18 @@ static int atmel_conf_pin_config_group_set(struct pinctrl_dev *pctldev, ATMEL_PIO_SODR); } break; + case ATMEL_PIN_CONFIG_DRIVE_STRENGTH: + switch (arg) { + case ATMEL_PIO_DRVSTR_LO: + case ATMEL_PIO_DRVSTR_ME: + case ATMEL_PIO_DRVSTR_HI: + conf &= (~ATMEL_PIO_DRVSTR_MASK); + conf |= arg << ATMEL_PIO_DRVSTR_OFFSET; + break; + default: + dev_warn(pctldev->dev, "drive strength not updated (incorrect value)\n"); + } + break; default: dev_warn(pctldev->dev, "unsupported configuration parameter: %u\n", @@ -816,6 +843,19 @@ static void atmel_conf_pin_config_dbg_show(struct pinctrl_dev *pctldev, seq_printf(s, "%s ", "open-drain"); if (conf & ATMEL_PIO_SCHMITT_MASK) seq_printf(s, "%s ", "schmitt"); + if (conf & ATMEL_PIO_DRVSTR_MASK) { + switch ((conf & ATMEL_PIO_DRVSTR_MASK) >> ATMEL_PIO_DRVSTR_OFFSET) { + case ATMEL_PIO_DRVSTR_ME: + seq_printf(s, "%s ", "medium-drive"); + break; + case ATMEL_PIO_DRVSTR_HI: + seq_printf(s, "%s ", "high-drive"); + break; + /* ATMEL_PIO_DRVSTR_LO and 0 which is the default value at reset */ + default: + seq_printf(s, "%s ", "low-drive"); + } + } } static const struct pinconf_ops atmel_confops = { @@ -958,6 +998,8 @@ static int atmel_pinctrl_probe(struct platform_device *pdev) return -ENOMEM; atmel_pinctrl_desc.pins = pin_desc; atmel_pinctrl_desc.npins = atmel_pioctrl->npins; + atmel_pinctrl_desc.num_custom_params = ARRAY_SIZE(atmel_custom_bindings); + atmel_pinctrl_desc.custom_params = atmel_custom_bindings; /* One pin is one group since a pin can achieve all functions. */ group_names = devm_kcalloc(dev, |