From: wuhuaye wuhuaye@huawei.com
ascend inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I4DLVR CVE: NA
-------------------------------------------------
Hi everyone, This patch add some special gpio register configuration.
It is necessary to configure some gpio register when gpio-dwapb function is enable in Ascend platform.
Signed-off-by: wuhuaye wuhuaye@huawei.com Reviewed-by: Ding Tianhong dingtianhong@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- arch/arm64/mm/init.c | 17 ++++++++++ drivers/gpio/gpio-dwapb.c | 66 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 82 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 2399a257eaf33..8cdf92626c2c6 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -944,6 +944,12 @@ __setup("keepinitrd", keepinitrd_setup);
void ascend_enable_all_features(void) { +#ifdef CONFIG_GPIO_DWAPB + extern bool enable_ascend_gpio_dwapb; + + enable_ascend_gpio_dwapb = true; +#endif + if (IS_ENABLED(CONFIG_ASCEND_DVPP_MMAP)) enable_mmap_dvpp = 1;
@@ -981,6 +987,17 @@ static int __init ascend_enable_setup(char *__unused) }
early_param("ascend_enable_all", ascend_enable_setup); + +static int __init ascend_mini_enable_setup(char *s) +{ +#ifdef CONFIG_GPIO_DWAPB + extern bool enable_ascend_mini_gpio_dwapb; + + enable_ascend_mini_gpio_dwapb = true; +#endif + return 1; +} +__setup("ascend_mini_enable", ascend_mini_enable_setup); #endif
diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index 2a56efced7988..4c332f0ed8524 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -50,6 +50,9 @@ #define GPIO_EXT_PORTB 0x54 #define GPIO_EXT_PORTC 0x58 #define GPIO_EXT_PORTD 0x5c +#define GPIO_INTCOMB_MASK 0xffc +#define GPIO_INT_MASK_REG 0x3804 +#define MEM_PERI_SUBCTRL_IOBASE 0x1
#define DWAPB_DRIVER_NAME "gpio-dwapb" #define DWAPB_MAX_PORTS 4 @@ -66,6 +69,8 @@ #define GPIO_INTSTATUS_V2 0x3c #define GPIO_PORTA_EOI_V2 0x40
+bool enable_ascend_mini_gpio_dwapb; +bool enable_ascend_gpio_dwapb; struct dwapb_gpio;
#ifdef CONFIG_PM_SLEEP @@ -79,10 +84,11 @@ struct dwapb_context { u32 int_type; u32 int_pol; u32 int_deb; + u32 int_comb_mask; u32 wake_en; }; #endif - +static void __iomem *peri_subctrl_base_addr; struct dwapb_gpio_port { struct gpio_chip gc; bool is_registered; @@ -234,6 +240,11 @@ static void dwapb_irq_enable(struct irq_data *d) val = dwapb_read(gpio, GPIO_INTEN); val |= BIT(d->hwirq); dwapb_write(gpio, GPIO_INTEN, val); + if (enable_ascend_gpio_dwapb) { + val = dwapb_read(gpio, GPIO_INTMASK); + val &= ~BIT(d->hwirq); + dwapb_write(gpio, GPIO_INTMASK, val); + } spin_unlock_irqrestore(&gc->bgpio_lock, flags); }
@@ -246,6 +257,11 @@ static void dwapb_irq_disable(struct irq_data *d) u32 val;
spin_lock_irqsave(&gc->bgpio_lock, flags); + if (enable_ascend_gpio_dwapb) { + val = dwapb_read(gpio, GPIO_INTMASK); + val |= BIT(d->hwirq); + dwapb_write(gpio, GPIO_INTMASK, val); + } val = dwapb_read(gpio, GPIO_INTEN); val &= ~BIT(d->hwirq); dwapb_write(gpio, GPIO_INTEN, val); @@ -395,6 +411,7 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio, unsigned int hwirq, ngpio = gc->ngpio; struct irq_chip_type *ct; int err, i; + u32 val;
gpio->domain = irq_domain_create_linear(fwnode, ngpio, &irq_generic_chip_ops, gpio); @@ -472,6 +489,12 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio, irq_create_mapping(gpio->domain, hwirq);
port->gc.to_irq = dwapb_gpio_to_irq; + + if (enable_ascend_gpio_dwapb) { + val = dwapb_read(gpio, GPIO_INTCOMB_MASK); + val |= BIT(0); + dwapb_write(gpio, GPIO_INTCOMB_MASK, val); + } }
static void dwapb_irq_teardown(struct dwapb_gpio *gpio) @@ -480,6 +503,7 @@ static void dwapb_irq_teardown(struct dwapb_gpio *gpio) struct gpio_chip *gc = &port->gc; unsigned int ngpio = gc->ngpio; irq_hw_number_t hwirq; + u32 val;
if (!gpio->domain) return; @@ -489,6 +513,12 @@ static void dwapb_irq_teardown(struct dwapb_gpio *gpio)
irq_domain_remove(gpio->domain); gpio->domain = NULL; + + if (enable_ascend_gpio_dwapb) { + val = dwapb_read(gpio, GPIO_INTCOMB_MASK); + val &= ~BIT(0); + dwapb_write(gpio, GPIO_INTCOMB_MASK, val); + } }
static int dwapb_gpio_add_port(struct dwapb_gpio *gpio, @@ -669,6 +699,22 @@ static int dwapb_gpio_probe(struct platform_device *pdev) int err; struct device *dev = &pdev->dev; struct dwapb_platform_data *pdata = dev_get_platdata(dev); + struct device_node *np = dev->of_node; + unsigned int value; + + if (enable_ascend_mini_gpio_dwapb && enable_ascend_gpio_dwapb) { + peri_subctrl_base_addr = of_iomap(np, MEM_PERI_SUBCTRL_IOBASE); + if (!peri_subctrl_base_addr) { + dev_err(&pdev->dev, "sysctrl iomap not find!\n"); + } else { + dev_dbg(&pdev->dev, "sysctrl iomap find!\n"); + value = readl(peri_subctrl_base_addr + + GPIO_INT_MASK_REG); + value &= ~1UL; + writel(value, peri_subctrl_base_addr + + GPIO_INT_MASK_REG); + } + }
if (!pdata) { pdata = dwapb_gpio_get_pdata(dev); @@ -751,6 +797,10 @@ static int dwapb_gpio_remove(struct platform_device *pdev) reset_control_assert(gpio->rst); clk_disable_unprepare(gpio->clk);
+ if ((peri_subctrl_base_addr != NULL) && enable_ascend_mini_gpio_dwapb && + enable_ascend_gpio_dwapb) + iounmap(peri_subctrl_base_addr); + return 0; }
@@ -787,6 +837,9 @@ static int dwapb_gpio_suspend(struct device *dev) ctx->int_pol = dwapb_read(gpio, GPIO_INT_POLARITY); ctx->int_type = dwapb_read(gpio, GPIO_INTTYPE_LEVEL); ctx->int_deb = dwapb_read(gpio, GPIO_PORTA_DEBOUNCE); + if (enable_ascend_gpio_dwapb) + ctx->int_comb_mask = + dwapb_read(gpio, GPIO_INTCOMB_MASK);
/* Mask out interrupts */ dwapb_write(gpio, GPIO_INTMASK, @@ -807,6 +860,7 @@ static int dwapb_gpio_resume(struct device *dev) struct gpio_chip *gc = &gpio->ports[0].gc; unsigned long flags; int i; + unsigned int value;
if (!IS_ERR(gpio->clk)) clk_prepare_enable(gpio->clk); @@ -835,6 +889,9 @@ static int dwapb_gpio_resume(struct device *dev) dwapb_write(gpio, GPIO_PORTA_DEBOUNCE, ctx->int_deb); dwapb_write(gpio, GPIO_INTEN, ctx->int_en); dwapb_write(gpio, GPIO_INTMASK, ctx->int_mask); + if (enable_ascend_gpio_dwapb) + dwapb_write(gpio, + GPIO_INTCOMB_MASK, ctx->int_comb_mask);
/* Clear out spurious interrupts */ dwapb_write(gpio, GPIO_PORTA_EOI, 0xffffffff); @@ -842,6 +899,13 @@ static int dwapb_gpio_resume(struct device *dev) } spin_unlock_irqrestore(&gc->bgpio_lock, flags);
+ if ((peri_subctrl_base_addr != NULL) && enable_ascend_mini_gpio_dwapb && + enable_ascend_gpio_dwapb) { + value = readl(peri_subctrl_base_addr + GPIO_INT_MASK_REG); + value &= ~1UL; + writel(value, peri_subctrl_base_addr + GPIO_INT_MASK_REG); + } + return 0; } #endif