From 62dec0a878fb837c415faad268c2c57941c1638e Mon Sep 17 00:00:00 2001 From: Ye Zhang Date: Wed, 7 Aug 2024 17:14:03 +0800 Subject: [PATCH] rockchip: gpio: fix debounce config error 1. Prevent data from crossing boundaries 2. Support GPIO_TYPE_V2_2 debounce config Signed-off-by: Ye Zhang Change-Id: I57e295806a4f0f4002527daf77fe41f584a7e9e1 --- drivers/gpio/gpio-rockchip.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c index 8469eb76813e..5a47cf11ecd2 100644 --- a/drivers/gpio/gpio-rockchip.c +++ b/drivers/gpio/gpio-rockchip.c @@ -84,7 +84,7 @@ static inline void rockchip_gpio_writel(struct rockchip_pin_bank *bank, { void __iomem *reg = bank->reg_base + offset; - if (bank->gpio_type == GPIO_TYPE_V2) + if (bank->gpio_type >= GPIO_TYPE_V2) gpio_writel_v2(value, reg); else writel(value, reg); @@ -96,7 +96,7 @@ static inline u32 rockchip_gpio_readl(struct rockchip_pin_bank *bank, void __iomem *reg = bank->reg_base + offset; u32 value; - if (bank->gpio_type == GPIO_TYPE_V2) + if (bank->gpio_type >= GPIO_TYPE_V2) value = gpio_readl_v2(reg); else value = readl(reg); @@ -111,7 +111,7 @@ static inline void rockchip_gpio_writel_bit(struct rockchip_pin_bank *bank, void __iomem *reg = bank->reg_base + offset; u32 data; - if (bank->gpio_type == GPIO_TYPE_V2) { + if (bank->gpio_type >= GPIO_TYPE_V2) { if (value) data = BIT(bit % 16) | BIT(bit % 16 + 16); else @@ -132,7 +132,7 @@ static inline u32 rockchip_gpio_readl_bit(struct rockchip_pin_bank *bank, void __iomem *reg = bank->reg_base + offset; u32 data; - if (bank->gpio_type == GPIO_TYPE_V2) { + if (bank->gpio_type >= GPIO_TYPE_V2) { data = readl(bit >= 16 ? reg + 0x4 : reg); data >>= bit % 16; } else { @@ -209,17 +209,24 @@ static int rockchip_gpio_set_debounce(struct gpio_chip *gc, unsigned int cur_div_reg; u64 div; - if (bank->gpio_type == GPIO_TYPE_V2 && !IS_ERR(bank->db_clk)) { + if (bank->gpio_type >= GPIO_TYPE_V2 && !IS_ERR(bank->db_clk)) { div_debounce_support = true; freq = clk_get_rate(bank->db_clk); if (!freq) return -EINVAL; - max_debounce = (GENMASK(23, 0) + 1) * 2 * 1000000 / freq; + div = (u64)(GENMASK(23, 0) + 1) * 1000000; + if (bank->gpio_type == GPIO_TYPE_V2) + max_debounce = DIV_ROUND_CLOSEST_ULL(div, freq); + else + max_debounce = DIV_ROUND_CLOSEST_ULL(div, 2 * freq); if ((unsigned long)debounce > max_debounce) return -EINVAL; - div = debounce * freq; - div_reg = DIV_ROUND_CLOSEST_ULL(div, 2 * USEC_PER_SEC) - 1; + div = (u64)debounce * freq; + if (bank->gpio_type == GPIO_TYPE_V2) + div_reg = DIV_ROUND_CLOSEST_ULL(div, USEC_PER_SEC) - 1; + else + div_reg = DIV_ROUND_CLOSEST_ULL(div, USEC_PER_SEC / 2) - 1; } else { div_debounce_support = false; } @@ -417,7 +424,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) polarity = rockchip_gpio_readl(bank, bank->gpio_regs->int_polarity); if (type == IRQ_TYPE_EDGE_BOTH) { - if (bank->gpio_type == GPIO_TYPE_V2) { + if (bank->gpio_type >= GPIO_TYPE_V2) { rockchip_gpio_writel_bit(bank, d->hwirq, 1, bank->gpio_regs->int_bothedge); goto out; @@ -436,7 +443,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) polarity |= mask; } } else { - if (bank->gpio_type == GPIO_TYPE_V2) { + if (bank->gpio_type >= GPIO_TYPE_V2) { rockchip_gpio_writel_bit(bank, d->hwirq, 0, bank->gpio_regs->int_bothedge); } else { @@ -544,7 +551,7 @@ static int rockchip_interrupts_register(struct rockchip_pin_bank *bank) } gc = irq_get_domain_generic_chip(bank->domain, 0); - if (bank->gpio_type == GPIO_TYPE_V2) { + if (bank->gpio_type >= GPIO_TYPE_V2) { gc->reg_writel = gpio_writel_v2; gc->reg_readl = gpio_readl_v2; } @@ -633,10 +640,13 @@ static void rockchip_gpio_get_ver(struct rockchip_pin_bank *bank) switch (id) { case GPIO_TYPE_V2: case GPIO_TYPE_V2_1: - case GPIO_TYPE_V2_2: bank->gpio_regs = &gpio_regs_v2; bank->gpio_type = GPIO_TYPE_V2; break; + case GPIO_TYPE_V2_2: + bank->gpio_regs = &gpio_regs_v2; + bank->gpio_type = GPIO_TYPE_V2_2; + break; default: bank->gpio_regs = &gpio_regs_v1; bank->gpio_type = GPIO_TYPE_V1;