Skip to content

Commit 483db38

Browse files
committed
pinctrl: at91-pio4: add support for drive strength
Add support for the drive strength configuration. Usually, this value is expressed in mA. Since the numeric value depends on VDDIOP voltage, a value we can't retrieve at runtime, the controller uses low, medium and high to define the drive strength. The PIO controller accepts two values for the low drive configuration: 0 and 1. Most of the time, we don't care about the drive strength. So we keep the default value which is 0. The drive strength is advertised through the sysfs only when it has been explicitly set in the device tree i.e. if its value is different from 0. Signed-off-by: Ludovic Desroches <ludovic.desroches@microchip.com> Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
1 parent a16134b commit 483db38

3 files changed

Lines changed: 49 additions & 0 deletions

File tree

Documentation/devicetree/bindings/pinctrl/atmel,at91-pio4-pinctrl.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ Optional properties:
3636
- GENERIC_PINCONFIG: generic pinconfig options to use, bias-disable,
3737
bias-pull-down, bias-pull-up, drive-open-drain, input-schmitt-enable,
3838
input-debounce, output-low, output-high.
39+
- atmel,drive-strength: 0 or 1 for low drive, 2 for medium drive and 3 for
40+
high drive. The default value is low drive.
3941

4042
Example:
4143

@@ -66,6 +68,7 @@ Example:
6668
pinmux = <PIN_PB0>,
6769
<PIN_PB5>;
6870
bias-pull-up;
71+
atmel,drive-strength = <ATMEL_PIO_DRVSTR_ME>;
6972
};
7073

7174
pinctrl_sdmmc1_default: sdmmc1_default {

drivers/pinctrl/pinctrl-at91-pio4.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* GNU General Public License for more details.
1515
*/
1616

17+
#include <dt-bindings/pinctrl/at91.h>
1718
#include <linux/clk.h>
1819
#include <linux/gpio/driver.h>
1920
/* FIXME: needed for gpio_to_irq(), get rid of this */
@@ -49,6 +50,8 @@
4950
#define ATMEL_PIO_IFSCEN_MASK BIT(13)
5051
#define ATMEL_PIO_OPD_MASK BIT(14)
5152
#define ATMEL_PIO_SCHMITT_MASK BIT(15)
53+
#define ATMEL_PIO_DRVSTR_MASK GENMASK(17, 16)
54+
#define ATMEL_PIO_DRVSTR_OFFSET 16
5255
#define ATMEL_PIO_CFGR_EVTSEL_MASK GENMASK(26, 24)
5356
#define ATMEL_PIO_CFGR_EVTSEL_FALLING (0 << 24)
5457
#define ATMEL_PIO_CFGR_EVTSEL_RISING (1 << 24)
@@ -75,6 +78,9 @@
7578
#define ATMEL_GET_PIN_FUNC(pinfunc) ((pinfunc >> 16) & 0xf)
7679
#define ATMEL_GET_PIN_IOSET(pinfunc) ((pinfunc >> 20) & 0xf)
7780

81+
/* Custom pinconf parameters */
82+
#define ATMEL_PIN_CONFIG_DRIVE_STRENGTH (PIN_CONFIG_END + 1)
83+
7884
struct atmel_pioctrl_data {
7985
unsigned nbanks;
8086
};
@@ -139,6 +145,10 @@ static const char * const atmel_functions[] = {
139145
"GPIO", "A", "B", "C", "D", "E", "F", "G"
140146
};
141147

148+
static const struct pinconf_generic_params atmel_custom_bindings[] = {
149+
{"atmel,drive-strength", ATMEL_PIN_CONFIG_DRIVE_STRENGTH, 0},
150+
};
151+
142152
/* --- GPIO --- */
143153
static unsigned int atmel_gpio_read(struct atmel_pioctrl *atmel_pioctrl,
144154
unsigned int bank, unsigned int reg)
@@ -690,6 +700,11 @@ static int atmel_conf_pin_config_group_get(struct pinctrl_dev *pctldev,
690700
return -EINVAL;
691701
arg = 1;
692702
break;
703+
case ATMEL_PIN_CONFIG_DRIVE_STRENGTH:
704+
if (!(res & ATMEL_PIO_DRVSTR_MASK))
705+
return -EINVAL;
706+
arg = (res & ATMEL_PIO_DRVSTR_MASK) >> ATMEL_PIO_DRVSTR_OFFSET;
707+
break;
693708
default:
694709
return -ENOTSUPP;
695710
}
@@ -775,6 +790,18 @@ static int atmel_conf_pin_config_group_set(struct pinctrl_dev *pctldev,
775790
ATMEL_PIO_SODR);
776791
}
777792
break;
793+
case ATMEL_PIN_CONFIG_DRIVE_STRENGTH:
794+
switch (arg) {
795+
case ATMEL_PIO_DRVSTR_LO:
796+
case ATMEL_PIO_DRVSTR_ME:
797+
case ATMEL_PIO_DRVSTR_HI:
798+
conf &= (~ATMEL_PIO_DRVSTR_MASK);
799+
conf |= arg << ATMEL_PIO_DRVSTR_OFFSET;
800+
break;
801+
default:
802+
dev_warn(pctldev->dev, "drive strength not updated (incorrect value)\n");
803+
}
804+
break;
778805
default:
779806
dev_warn(pctldev->dev,
780807
"unsupported configuration parameter: %u\n",
@@ -814,6 +841,19 @@ static void atmel_conf_pin_config_dbg_show(struct pinctrl_dev *pctldev,
814841
seq_printf(s, "%s ", "open-drain");
815842
if (conf & ATMEL_PIO_SCHMITT_MASK)
816843
seq_printf(s, "%s ", "schmitt");
844+
if (conf & ATMEL_PIO_DRVSTR_MASK) {
845+
switch ((conf & ATMEL_PIO_DRVSTR_MASK) >> ATMEL_PIO_DRVSTR_OFFSET) {
846+
case ATMEL_PIO_DRVSTR_ME:
847+
seq_printf(s, "%s ", "medium-drive");
848+
break;
849+
case ATMEL_PIO_DRVSTR_HI:
850+
seq_printf(s, "%s ", "high-drive");
851+
break;
852+
/* ATMEL_PIO_DRVSTR_LO and 0 which is the default value at reset */
853+
default:
854+
seq_printf(s, "%s ", "low-drive");
855+
}
856+
}
817857
}
818858

819859
static const struct pinconf_ops atmel_confops = {
@@ -954,6 +994,8 @@ static int atmel_pinctrl_probe(struct platform_device *pdev)
954994
return -ENOMEM;
955995
atmel_pinctrl_desc.pins = pin_desc;
956996
atmel_pinctrl_desc.npins = atmel_pioctrl->npins;
997+
atmel_pinctrl_desc.num_custom_params = ARRAY_SIZE(atmel_custom_bindings);
998+
atmel_pinctrl_desc.custom_params = atmel_custom_bindings;
957999

9581000
/* One pin is one group since a pin can achieve all functions. */
9591001
group_names = devm_kzalloc(dev, sizeof(*group_names)

include/dt-bindings/pinctrl/at91.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,8 @@
3939
#define AT91_PERIPH_C 3
4040
#define AT91_PERIPH_D 4
4141

42+
#define ATMEL_PIO_DRVSTR_LO 1
43+
#define ATMEL_PIO_DRVSTR_ME 2
44+
#define ATMEL_PIO_DRVSTR_HI 3
45+
4246
#endif /* __DT_BINDINGS_AT91_PINCTRL_H__ */

0 commit comments

Comments
 (0)