diff options
Diffstat (limited to 'drivers/pinctrl/pinctrl-st.c')
-rw-r--r-- | drivers/pinctrl/pinctrl-st.c | 85 |
1 files changed, 72 insertions, 13 deletions
diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c index 9e5ec00084bb..65bf73b70e34 100644 --- a/drivers/pinctrl/pinctrl-st.c +++ b/drivers/pinctrl/pinctrl-st.c @@ -206,6 +206,8 @@ #define gpio_chip_to_bank(chip) \ container_of(chip, struct st_gpio_bank, gpio_chip) +#define pc_to_bank(pc) \ + container_of(pc, struct st_gpio_bank, pc) enum st_retime_style { st_retime_style_none, @@ -398,6 +400,16 @@ static const struct st_pctl_data stih407_flashdata = { .rt = 100, }; +static struct st_pio_control *st_get_pio_control( + struct pinctrl_dev *pctldev, int pin) +{ + struct pinctrl_gpio_range *range = + pinctrl_find_gpio_range_from_pin(pctldev, pin); + struct st_gpio_bank *bank = gpio_range_to_bank(range); + + return &bank->pc; +} + /* Low level functions.. */ static inline int st_gpio_bank(int gpio) { @@ -460,6 +472,20 @@ static void st_pctl_set_function(struct st_pio_control *pc, regmap_field_write(alt, val); } +static unsigned int st_pctl_get_pin_function(struct st_pio_control *pc, int pin) +{ + struct regmap_field *alt = pc->alt; + unsigned int val; + int offset = pin * 4; + + if (!alt) + return 0; + + regmap_field_read(alt, &val); + + return (val >> offset) & 0xf; +} + static unsigned long st_pinconf_delay_to_bit(unsigned int delay, const struct st_pctl_data *data, unsigned long config) { @@ -757,6 +783,35 @@ static int st_gpio_direction_output(struct gpio_chip *chip, return 0; } +static int st_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +{ + struct st_gpio_bank *bank = gpio_chip_to_bank(chip); + struct st_pio_control pc = bank->pc; + unsigned long config; + unsigned int direction = 0; + unsigned int function; + unsigned int value; + int i = 0; + + /* Alternate function direction is handled by Pinctrl */ + function = st_pctl_get_pin_function(&pc, offset); + if (function) { + st_pinconf_get_direction(&pc, offset, &config); + return !ST_PINCONF_UNPACK_OE(config); + } + + /* + * GPIO direction is handled differently + * - See st_gpio_direction() above for an explanation + */ + for (i = 0; i <= 2; i++) { + value = readl(bank->base + REG_PIO_PC(i)); + direction |= ((value >> offset) & 0x1) << i; + } + + return (direction == ST_GPIO_DIRECTION_IN); +} + static int st_gpio_xlate(struct gpio_chip *gc, const struct of_phandle_args *gpiospec, u32 *flags) { @@ -904,16 +959,6 @@ static int st_pmx_get_groups(struct pinctrl_dev *pctldev, return 0; } -static struct st_pio_control *st_get_pio_control( - struct pinctrl_dev *pctldev, int pin) -{ - struct pinctrl_gpio_range *range = - pinctrl_find_gpio_range_from_pin(pctldev, pin); - struct st_gpio_bank *bank = gpio_range_to_bank(range); - - return &bank->pc; -} - static int st_pmx_set_mux(struct pinctrl_dev *pctldev, unsigned fselector, unsigned group) { @@ -1011,17 +1056,30 @@ static int st_pinconf_get(struct pinctrl_dev *pctldev, static void st_pinconf_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, unsigned pin_id) { + struct st_pio_control *pc; unsigned long config; + unsigned int function; + int offset = st_gpio_pin(pin_id); + char f[16]; mutex_unlock(&pctldev->mutex); + pc = st_get_pio_control(pctldev, pin_id); st_pinconf_get(pctldev, pin_id, &config); mutex_lock(&pctldev->mutex); - seq_printf(s, "[OE:%ld,PU:%ld,OD:%ld]\n" + + function = st_pctl_get_pin_function(pc, offset); + if (function) + snprintf(f, 10, "Alt Fn %d", function); + else + snprintf(f, 5, "GPIO"); + + seq_printf(s, "[OE:%d,PU:%ld,OD:%ld]\t%s\n" "\t\t[retime:%ld,invclk:%ld,clknotdat:%ld," "de:%ld,rt-clk:%ld,rt-delay:%ld]", - ST_PINCONF_UNPACK_OE(config), + !st_gpio_get_direction(&pc_to_bank(pc)->gpio_chip, offset), ST_PINCONF_UNPACK_PU(config), ST_PINCONF_UNPACK_OD(config), + f, ST_PINCONF_UNPACK_RT(config), ST_PINCONF_UNPACK_RT_INVERTCLK(config), ST_PINCONF_UNPACK_RT_CLKNOTDATA(config), @@ -1438,6 +1496,7 @@ static struct gpio_chip st_gpio_template = { .set = st_gpio_set, .direction_input = st_gpio_direction_input, .direction_output = st_gpio_direction_output, + .get_direction = st_gpio_get_direction, .ngpio = ST_GPIO_PINS_PER_BANK, .of_gpio_n_cells = 1, .of_xlate = st_gpio_xlate, @@ -1531,7 +1590,7 @@ static int st_gpiolib_register_bank(struct st_pinctrl *info, return 0; } -static struct of_device_id st_pctl_of_match[] = { +static const struct of_device_id st_pctl_of_match[] = { { .compatible = "st,stih415-sbc-pinctrl", .data = &stih415_sbc_data }, { .compatible = "st,stih415-rear-pinctrl", .data = &stih415_rear_data }, { .compatible = "st,stih415-left-pinctrl", .data = &stih415_left_data }, |