diff options
Diffstat (limited to 'drivers/pinctrl/pinctrl-rockchip.c')
-rw-r--r-- | drivers/pinctrl/pinctrl-rockchip.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 88d40772e387..1882713e68f9 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -2710,6 +2710,57 @@ static int rockchip_gpio_direction_output(struct gpio_chip *gc, return pinctrl_gpio_direction_output(gc->base + offset); } +static void rockchip_gpio_set_debounce(struct gpio_chip *gc, + unsigned int offset, bool enable) +{ + struct rockchip_pin_bank *bank = gpiochip_get_data(gc); + void __iomem *reg = bank->reg_base + GPIO_DEBOUNCE; + unsigned long flags; + u32 data; + + clk_enable(bank->clk); + raw_spin_lock_irqsave(&bank->slock, flags); + + data = readl(reg); + if (enable) + data |= BIT(offset); + else + data &= ~BIT(offset); + writel(data, reg); + + raw_spin_unlock_irqrestore(&bank->slock, flags); + clk_disable(bank->clk); +} + +/* + * gpiolib set_config callback function. The setting of the pin + * mux function as 'gpio output' will be handled by the pinctrl subsystem + * interface. + */ +static int rockchip_gpio_set_config(struct gpio_chip *gc, unsigned int offset, + unsigned long config) +{ + enum pin_config_param param = pinconf_to_config_param(config); + + switch (param) { + case PIN_CONFIG_INPUT_DEBOUNCE: + rockchip_gpio_set_debounce(gc, offset, true); + /* + * Rockchip's gpio could only support up to one period + * of the debounce clock(pclk), which is far away from + * satisftying the requirement, as pclk is usually near + * 100MHz shared by all peripherals. So the fact is it + * has crippled debounce capability could only be useful + * to prevent any spurious glitches from waking up the system + * if the gpio is conguired as wakeup interrupt source. Let's + * still return -ENOTSUPP as before, to make sure the caller + * of gpiod_set_debounce won't change its behaviour. + */ + default: + return -ENOTSUPP; + } +} + /* * gpiolib gpio_to_irq callback function. Creates a mapping between a GPIO pin * and a virtual IRQ, if not already present. @@ -2735,6 +2786,7 @@ static const struct gpio_chip rockchip_gpiolib_chip = { .get_direction = rockchip_gpio_get_direction, .direction_input = rockchip_gpio_direction_input, .direction_output = rockchip_gpio_direction_output, + .set_config = rockchip_gpio_set_config, .to_irq = rockchip_gpio_to_irq, .owner = THIS_MODULE, }; |