From 1761b1076a6465158079fdb61edcd75143887937 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sun, 3 Apr 2016 11:23:59 +0200 Subject: ARM: pxa: remove platform dma code As the last pxa related driver was converted to dmaengine, it's time to kill the legacy dma code, which is not used anymore. This finishes the pxa dmaengine transition. Signed-off-by: Robert Jarzmik --- arch/arm/mach-pxa/devices.h | 1 + arch/arm/mach-pxa/include/mach/dma.h | 1 - arch/arm/mach-pxa/pxa25x.c | 3 --- arch/arm/mach-pxa/pxa27x.c | 3 --- arch/arm/mach-pxa/pxa3xx.c | 3 --- 5 files changed, 1 insertion(+), 10 deletions(-) (limited to 'arch/arm/mach-pxa') diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h index 4a13c32..04580c4 100644 --- a/arch/arm/mach-pxa/devices.h +++ b/arch/arm/mach-pxa/devices.h @@ -54,3 +54,4 @@ extern struct platform_device pxa3xx_device_gpio; extern struct platform_device pxa93x_device_gpio; void __init pxa_register_device(struct platform_device *dev, void *data); +void __init pxa2xx_set_dmac_info(int nb_channels, int nb_requestors); diff --git a/arch/arm/mach-pxa/include/mach/dma.h b/arch/arm/mach-pxa/include/mach/dma.h index 5bd5589..20026bd 100644 --- a/arch/arm/mach-pxa/include/mach/dma.h +++ b/arch/arm/mach-pxa/include/mach/dma.h @@ -17,5 +17,4 @@ /* DMA Controller Registers Definitions */ #define DMAC_REGS_VIRT io_p2v(0x40000000) -#include #endif /* _ASM_ARCH_DMA_H */ diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index 823504f..ec98652 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -198,9 +198,6 @@ static int __init pxa25x_init(void) reset_status = RCSR; - if ((ret = pxa_init_dma(IRQ_DMA, 16))) - return ret; - pxa25x_init_pm(); register_syscore_ops(&pxa_irq_syscore_ops); diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 2eaa341..488d0ab 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -300,9 +300,6 @@ static int __init pxa27x_init(void) reset_status = RCSR; - if ((ret = pxa_init_dma(IRQ_DMA, 32))) - return ret; - pxa27x_init_pm(); register_syscore_ops(&pxa_irq_syscore_ops); diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index 3c9184d..6a014c8 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -438,9 +438,6 @@ static int __init pxa3xx_init(void) */ NDCR = (NDCR & ~NDCR_ND_ARB_EN) | NDCR_ND_ARB_CNTL; - if ((ret = pxa_init_dma(IRQ_DMA, 32))) - return ret; - pxa3xx_init_pm(); register_syscore_ops(&pxa_irq_syscore_ops); -- cgit v1.1 From ca5be4c678a402b7a35b2ce9a1a480b79d53f36e Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sun, 10 Apr 2016 21:29:58 +0200 Subject: ARM: pxa: prepare pxa25x interrupts for device-tree platforms Add the device-tree interrupts initialization function required to have a generic pxa25x device-tree machine. Signed-off-by: Robert Jarzmik --- arch/arm/mach-pxa/generic.h | 1 + arch/arm/mach-pxa/pxa25x.c | 6 ++++++ 2 files changed, 7 insertions(+) (limited to 'arch/arm/mach-pxa') diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h index 0b1dbb5..3f914d9 100644 --- a/arch/arm/mach-pxa/generic.h +++ b/arch/arm/mach-pxa/generic.h @@ -27,6 +27,7 @@ extern void pxa_timer_init(void); #define pxa25x_handle_irq icip_handle_irq extern int __init pxa25x_clocks_init(void); +extern void __init pxa25x_dt_init_irq(void); extern void __init pxa25x_init_irq(void); extern void __init pxa25x_map_io(void); extern void __init pxa26x_init_irq(void); diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index ec98652..3aa7aca 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -151,6 +151,12 @@ void __init pxa26x_init_irq(void) } #endif +void __init pxa25x_dt_init_irq(void) +{ + if (IS_ENABLED(CONFIG_OF)) + pxa_dt_irq_init(pxa25x_set_wake); +} + static struct map_desc pxa25x_io_desc[] __initdata = { { /* Mem Ctl */ .virtual = (unsigned long)SMEMC_VIRT, -- cgit v1.1 From d9edae44d76a20d1b999070d911e58dca53f9906 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sun, 10 Apr 2016 21:29:59 +0200 Subject: ARM: pxa: add pxa25x device-tree support Add a device-tree machine entry (DT_MACHINE_START) for pxa25x based platforms. Take the opportunity to sort the file machine descriptions by alphabetical order. Signed-off-by: Robert Jarzmik --- arch/arm/mach-pxa/Kconfig | 11 +++++++++++ arch/arm/mach-pxa/Makefile | 3 ++- arch/arm/mach-pxa/pxa-dt.c | 37 ++++++++++++++++++++++++++----------- arch/arm/mach-pxa/pxa25x.c | 12 ++++++------ 4 files changed, 45 insertions(+), 18 deletions(-) (limited to 'arch/arm/mach-pxa') diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index cd894d6..76fbc11 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -4,6 +4,17 @@ menu "Intel PXA2xx/PXA3xx Implementations" comment "Intel/Marvell Dev Platforms (sorted by hardware release time)" +config MACH_PXA25X_DT + bool "Support PXA25x platforms from device tree" + select PINCTRL + select POWER_SUPPLY + select PXA25x + select USE_OF + help + Include support for Marvell PXA25x based platforms using + the device tree. Needn't select any other machine while + MACH_PXA25x_DT is enabled. + config MACH_PXA27X_DT bool "Support PXA27x platforms from device tree" select PINCTRL diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 2ceed40..ef25dc5 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -19,8 +19,9 @@ obj-$(CONFIG_CPU_PXA930) += pxa930.o # NOTE: keep the order of boards in accordance to their order in Kconfig # Device Tree support -obj-$(CONFIG_MACH_PXA3XX_DT) += pxa-dt.o +obj-$(CONFIG_MACH_PXA25X_DT) += pxa-dt.o obj-$(CONFIG_MACH_PXA27X_DT) += pxa-dt.o +obj-$(CONFIG_MACH_PXA3XX_DT) += pxa-dt.o # Intel/Marvell Dev Platforms obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o diff --git a/arch/arm/mach-pxa/pxa-dt.c b/arch/arm/mach-pxa/pxa-dt.c index f128133a..3e331e6 100644 --- a/arch/arm/mach-pxa/pxa-dt.c +++ b/arch/arm/mach-pxa/pxa-dt.c @@ -18,20 +18,18 @@ #include "generic.h" -#ifdef CONFIG_PXA3xx -static const char *const pxa3xx_dt_board_compat[] __initconst = { - "marvell,pxa300", - "marvell,pxa310", - "marvell,pxa320", +#ifdef CONFIG_PXA25x +static const char * const pxa25x_dt_board_compat[] __initconst = { + "marvell,pxa250", NULL, }; -DT_MACHINE_START(PXA_DT, "Marvell PXA3xx (Device Tree Support)") - .map_io = pxa3xx_map_io, - .init_irq = pxa3xx_dt_init_irq, - .handle_irq = pxa3xx_handle_irq, +DT_MACHINE_START(PXA25X_DT, "Marvell PXA25x (Device Tree Support)") + .map_io = pxa25x_map_io, + .init_irq = pxa25x_dt_init_irq, + .handle_irq = pxa25x_handle_irq, .restart = pxa_restart, - .dt_compat = pxa3xx_dt_board_compat, + .dt_compat = pxa25x_dt_board_compat, MACHINE_END #endif @@ -41,7 +39,7 @@ static const char * const pxa27x_dt_board_compat[] __initconst = { NULL, }; -DT_MACHINE_START(PXA27X_DT, "Marvell PXA2xx (Device Tree Support)") +DT_MACHINE_START(PXA27X_DT, "Marvell PXA27x (Device Tree Support)") .map_io = pxa27x_map_io, .init_irq = pxa27x_dt_init_irq, .handle_irq = pxa27x_handle_irq, @@ -49,3 +47,20 @@ DT_MACHINE_START(PXA27X_DT, "Marvell PXA2xx (Device Tree Support)") .dt_compat = pxa27x_dt_board_compat, MACHINE_END #endif + +#ifdef CONFIG_PXA3xx +static const char *const pxa3xx_dt_board_compat[] __initconst = { + "marvell,pxa300", + "marvell,pxa310", + "marvell,pxa320", + NULL, +}; + +DT_MACHINE_START(PXA_DT, "Marvell PXA3xx (Device Tree Support)") + .map_io = pxa3xx_map_io, + .init_irq = pxa3xx_dt_init_irq, + .handle_irq = pxa3xx_handle_irq, + .restart = pxa_restart, + .dt_compat = pxa3xx_dt_board_compat, +MACHINE_END +#endif diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index 3aa7aca..30b4270 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -209,12 +209,12 @@ static int __init pxa25x_init(void) register_syscore_ops(&pxa_irq_syscore_ops); register_syscore_ops(&pxa2xx_mfp_syscore_ops); - pxa2xx_set_dmac_info(16, 40); - pxa_register_device(&pxa25x_device_gpio, &pxa25x_gpio_info); - ret = platform_add_devices(pxa25x_devices, - ARRAY_SIZE(pxa25x_devices)); - if (ret) - return ret; + if (!of_have_populated_dt()) { + pxa2xx_set_dmac_info(16, 40); + pxa_register_device(&pxa25x_device_gpio, &pxa25x_gpio_info); + ret = platform_add_devices(pxa25x_devices, + ARRAY_SIZE(pxa25x_devices)); + } } return ret; -- cgit v1.1 From ca26475bf02ed8562b9b46f91d3e8b52ec312541 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Tue, 2 Aug 2016 00:01:32 +0200 Subject: ARM: pxa: fix GPIO double shifts The commit 9bf448c66d4b ("ARM: pxa: use generic gpio operation instead of gpio register") from Oct 17, 2011, leads to the following static checker warning: arch/arm/mach-pxa/spitz_pm.c:172 spitz_charger_wakeup() warn: double left shift '!gpio_get_value(SPITZ_GPIO_KEY_INT) << (1 << ((SPITZ_GPIO_KEY_INT) & 31))' As Dan reported, the value is shifted three times : - once by gpio_get_value(), which returns either 0 or BIT(gpio) - once by the shift operation '<<' - a last time by GPIO_bit(gpio) which is BIT(gpio) Therefore the calculation lead to a chained or operator of : - (1 << gpio) << (1 << gpio) = (2^gpio)^gpio = 2 ^ (gpio * gpio) It is be sheer luck the former statement works, only because each gpio used is strictly smaller than 6, and therefore 2^(gpio^2) never overflows a 32 bits value, and because it is used as a boolean value to check a gpio activation. As the xxx_charger_wakeup() functions are used as a true/false detection mechanism, take that opportunity to change their prototypes from integer return value to boolean one. Fixes: 9bf448c66d4b ("ARM: pxa: use generic gpio operation instead of gpio register") Reported-by: Dan Carpenter Cc: Joe Perches Signed-off-by: Robert Jarzmik --- arch/arm/mach-pxa/corgi_pm.c | 13 ++++--------- arch/arm/mach-pxa/sharpsl_pm.c | 2 +- arch/arm/mach-pxa/sharpsl_pm.h | 2 +- arch/arm/mach-pxa/spitz_pm.c | 9 +++------ 4 files changed, 9 insertions(+), 17 deletions(-) (limited to 'arch/arm/mach-pxa') diff --git a/arch/arm/mach-pxa/corgi_pm.c b/arch/arm/mach-pxa/corgi_pm.c index d920681..c71c483 100644 --- a/arch/arm/mach-pxa/corgi_pm.c +++ b/arch/arm/mach-pxa/corgi_pm.c @@ -131,16 +131,11 @@ static int corgi_should_wakeup(unsigned int resume_on_alarm) return is_resume; } -static unsigned long corgi_charger_wakeup(void) +static bool corgi_charger_wakeup(void) { - unsigned long ret; - - ret = (!gpio_get_value(CORGI_GPIO_AC_IN) << GPIO_bit(CORGI_GPIO_AC_IN)) - | (!gpio_get_value(CORGI_GPIO_KEY_INT) - << GPIO_bit(CORGI_GPIO_KEY_INT)) - | (!gpio_get_value(CORGI_GPIO_WAKEUP) - << GPIO_bit(CORGI_GPIO_WAKEUP)); - return ret; + return !gpio_get_value(CORGI_GPIO_AC_IN) || + !gpio_get_value(CORGI_GPIO_KEY_INT) || + !gpio_get_value(CORGI_GPIO_WAKEUP); } unsigned long corgipm_read_devdata(int type) diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c index b80eab9..249b7bd 100644 --- a/arch/arm/mach-pxa/sharpsl_pm.c +++ b/arch/arm/mach-pxa/sharpsl_pm.c @@ -744,7 +744,7 @@ static int sharpsl_off_charge_battery(void) time = RCNR; while (1) { /* Check if any wakeup event had occurred */ - if (sharpsl_pm.machinfo->charger_wakeup() != 0) + if (sharpsl_pm.machinfo->charger_wakeup()) return 0; /* Check for timeout */ if ((RCNR - time) > SHARPSL_WAIT_CO_TIME) diff --git a/arch/arm/mach-pxa/sharpsl_pm.h b/arch/arm/mach-pxa/sharpsl_pm.h index 905be67..fa75b6d 100644 --- a/arch/arm/mach-pxa/sharpsl_pm.h +++ b/arch/arm/mach-pxa/sharpsl_pm.h @@ -34,7 +34,7 @@ struct sharpsl_charger_machinfo { #define SHARPSL_STATUS_LOCK 5 #define SHARPSL_STATUS_CHRGFULL 6 #define SHARPSL_STATUS_FATAL 7 - unsigned long (*charger_wakeup)(void); + bool (*charger_wakeup)(void); int (*should_wakeup)(unsigned int resume_on_alarm); void (*backlight_limit)(int); int (*backlight_get_status) (void); diff --git a/arch/arm/mach-pxa/spitz_pm.c b/arch/arm/mach-pxa/spitz_pm.c index ea9f903..4e64a14 100644 --- a/arch/arm/mach-pxa/spitz_pm.c +++ b/arch/arm/mach-pxa/spitz_pm.c @@ -165,13 +165,10 @@ static int spitz_should_wakeup(unsigned int resume_on_alarm) return is_resume; } -static unsigned long spitz_charger_wakeup(void) +static bool spitz_charger_wakeup(void) { - unsigned long ret; - ret = ((!gpio_get_value(SPITZ_GPIO_KEY_INT) - << GPIO_bit(SPITZ_GPIO_KEY_INT)) - | gpio_get_value(SPITZ_GPIO_SYNC)); - return ret; + return !gpio_get_value(SPITZ_GPIO_KEY_INT) || + gpio_get_value(SPITZ_GPIO_SYNC); } unsigned long spitzpm_read_devdata(int type) -- cgit v1.1 From e572f6491a4b8ffbf31c59e2ad0eb8ee9244bf58 Mon Sep 17 00:00:00 2001 From: Petr Cvek Date: Wed, 17 Aug 2016 12:36:13 +0200 Subject: ARM: pxa: magician: Remove duplicated I2C pins declaration Magician has GPIO117_I2C_SCL and GPIO118_I2C_SDA pins declared twice. Signed-off-by: Petr Cvek Signed-off-by: Robert Jarzmik --- arch/arm/mach-pxa/magician.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'arch/arm/mach-pxa') diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c index abc9181..6f8837e 100644 --- a/arch/arm/mach-pxa/magician.c +++ b/arch/arm/mach-pxa/magician.c @@ -121,10 +121,6 @@ static unsigned long magician_pin_config[] __initdata = { GPIO107_GPIO, /* DS1WM_IRQ */ GPIO108_GPIO, /* GSM_READY */ GPIO115_GPIO, /* nPEN_IRQ */ - - /* I2C */ - GPIO117_I2C_SCL, - GPIO118_I2C_SDA, }; /* -- cgit v1.1 From 8571110575c985b12d443288c397dba6dc7a44f5 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Thu, 25 Aug 2016 18:01:37 +0200 Subject: ARM: pxa: Use kmalloc_array() in pxa_pm_init() * A multiplication for the size determination of a memory allocation indicated that an array data structure should be processed. Thus use the corresponding function "kmalloc_array". This issue was detected by using the Coccinelle software. * Replace the specification of a data type by a pointer dereference to make the corresponding size determination a bit safer according to the Linux coding style convention. Signed-off-by: Markus Elfring Signed-off-by: Robert Jarzmik --- arch/arm/mach-pxa/pm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch/arm/mach-pxa') diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c index 388463b..e7450fb 100644 --- a/arch/arm/mach-pxa/pm.c +++ b/arch/arm/mach-pxa/pm.c @@ -104,8 +104,9 @@ static int __init pxa_pm_init(void) return -EINVAL; } - sleep_save = kmalloc(pxa_cpu_pm_fns->save_count * sizeof(unsigned long), - GFP_KERNEL); + sleep_save = kmalloc_array(pxa_cpu_pm_fns->save_count, + sizeof(*sleep_save), + GFP_KERNEL); if (!sleep_save) { printk(KERN_ERR "failed to alloc memory for pm save\n"); return -ENOMEM; -- cgit v1.1 From 32f17997c1307c44f9365ed5ff4cf2b5c1e22301 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Mon, 15 Aug 2016 00:24:55 +0200 Subject: ARM: pxa: remove irq init from dt machines The init_irq and handle_irq can be declared through standard irqchip declaration and are not necessary in machine descriptions. This is another step towards the generic kernel for the pxa architecture. Signed-off-by: Robert Jarzmik Acked-by: Arnd Bergmann --- arch/arm/mach-pxa/generic.h | 3 --- arch/arm/mach-pxa/pxa-dt.c | 6 ------ arch/arm/mach-pxa/pxa25x.c | 11 ++++++++--- arch/arm/mach-pxa/pxa27x.c | 11 ++++++++--- arch/arm/mach-pxa/pxa3xx.c | 8 +++++++- 5 files changed, 23 insertions(+), 16 deletions(-) (limited to 'arch/arm/mach-pxa') diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h index 3f914d9..75e3f61 100644 --- a/arch/arm/mach-pxa/generic.h +++ b/arch/arm/mach-pxa/generic.h @@ -27,21 +27,18 @@ extern void pxa_timer_init(void); #define pxa25x_handle_irq icip_handle_irq extern int __init pxa25x_clocks_init(void); -extern void __init pxa25x_dt_init_irq(void); extern void __init pxa25x_init_irq(void); extern void __init pxa25x_map_io(void); extern void __init pxa26x_init_irq(void); #define pxa27x_handle_irq ichp_handle_irq extern int __init pxa27x_clocks_init(void); -extern void __init pxa27x_dt_init_irq(void); extern unsigned pxa27x_get_clk_frequency_khz(int); extern void __init pxa27x_init_irq(void); extern void __init pxa27x_map_io(void); #define pxa3xx_handle_irq ichp_handle_irq extern int __init pxa3xx_clocks_init(void); -extern void __init pxa3xx_dt_init_irq(void); extern void __init pxa3xx_init_irq(void); extern void __init pxa3xx_map_io(void); diff --git a/arch/arm/mach-pxa/pxa-dt.c b/arch/arm/mach-pxa/pxa-dt.c index 3e331e6..aa9b255 100644 --- a/arch/arm/mach-pxa/pxa-dt.c +++ b/arch/arm/mach-pxa/pxa-dt.c @@ -26,8 +26,6 @@ static const char * const pxa25x_dt_board_compat[] __initconst = { DT_MACHINE_START(PXA25X_DT, "Marvell PXA25x (Device Tree Support)") .map_io = pxa25x_map_io, - .init_irq = pxa25x_dt_init_irq, - .handle_irq = pxa25x_handle_irq, .restart = pxa_restart, .dt_compat = pxa25x_dt_board_compat, MACHINE_END @@ -41,8 +39,6 @@ static const char * const pxa27x_dt_board_compat[] __initconst = { DT_MACHINE_START(PXA27X_DT, "Marvell PXA27x (Device Tree Support)") .map_io = pxa27x_map_io, - .init_irq = pxa27x_dt_init_irq, - .handle_irq = pxa27x_handle_irq, .restart = pxa_restart, .dt_compat = pxa27x_dt_board_compat, MACHINE_END @@ -58,8 +54,6 @@ static const char *const pxa3xx_dt_board_compat[] __initconst = { DT_MACHINE_START(PXA_DT, "Marvell PXA3xx (Device Tree Support)") .map_io = pxa3xx_map_io, - .init_irq = pxa3xx_dt_init_irq, - .handle_irq = pxa3xx_handle_irq, .restart = pxa_restart, .dt_compat = pxa3xx_dt_board_compat, MACHINE_END diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index 30b4270..12b9435 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -151,11 +152,15 @@ void __init pxa26x_init_irq(void) } #endif -void __init pxa25x_dt_init_irq(void) +static int __init __init +pxa25x_dt_init_irq(struct device_node *node, struct device_node *parent) { - if (IS_ENABLED(CONFIG_OF)) - pxa_dt_irq_init(pxa25x_set_wake); + pxa_dt_irq_init(pxa25x_set_wake); + set_handle_irq(ichp_handle_irq); + + return 0; } +IRQCHIP_DECLARE(pxa25x_intc, "marvell,pxa-intc", pxa25x_dt_init_irq); static struct map_desc pxa25x_io_desc[] __initdata = { { /* Mem Ctl */ diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 488d0ab..c0185c5 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -233,11 +234,15 @@ void __init pxa27x_init_irq(void) pxa_init_irq(34, pxa27x_set_wake); } -void __init pxa27x_dt_init_irq(void) +static int __init +pxa27x_dt_init_irq(struct device_node *node, struct device_node *parent) { - if (IS_ENABLED(CONFIG_OF)) - pxa_dt_irq_init(pxa27x_set_wake); + pxa_dt_irq_init(pxa27x_set_wake); + set_handle_irq(ichp_handle_irq); + + return 0; } +IRQCHIP_DECLARE(pxa27x_intc, "marvell,pxa-intc", pxa27x_dt_init_irq); static struct map_desc pxa27x_io_desc[] __initdata = { { /* Mem Ctl */ diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index 6a014c8..87acc96 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -356,11 +357,16 @@ void __init pxa3xx_init_irq(void) } #ifdef CONFIG_OF -void __init pxa3xx_dt_init_irq(void) +static int __init __init +pxa3xx_dt_init_irq(struct device_node *node, struct device_node *parent) { __pxa3xx_init_irq(); pxa_dt_irq_init(pxa3xx_set_wake); + set_handle_irq(ichp_handle_irq); + + return 0; } +IRQCHIP_DECLARE(pxa3xx_intc, "marvell,pxa-intc", pxa3xx_dt_init_irq); #endif /* CONFIG_OF */ static struct map_desc pxa3xx_io_desc[] __initdata = { -- cgit v1.1 From 9ba63e3cc849cdaf3b675c47cc51fe35419e5117 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sun, 4 Sep 2016 20:59:45 +0200 Subject: ARM: pxa: pxa_cplds: fix interrupt handling Since its initial commit, the driver is buggy for multiple interrupts handling. The translation from the former lubbock.c file was not complete, and might stall all interrupt handling when multiple interrupts occur. This is especially true when inside the interrupt handler and if a new interrupt comes and is not handled, leaving the output line still held, and not creating a transition as the GPIO block behind would expect to trigger another cplds_irq_handler() call. For the record, the hardware is working as follows. The interrupt mechanism relies on : - one status register - one mask register Let's suppose the input irq lines are called : - i_sa1111 - i_lan91x - i_mmc_cd Let's suppose the status register for each irq line is called : - status_sa1111 - status_lan91x - status_mmc_cd Let's suppose the interrupt mask for each irq line is called : - irqen_sa1111 - irqen_lan91x - irqen_mmc_cd Let's suppose the output irq line, connected to GPIO0 is called : - o_gpio0 The behavior is as follows : - o_gpio0 = not((status_sa1111 & irqen_sa1111) | (status_lan91x & irqen_lan91x) | (status_mmc_cd & irqen_mmc_cd)) => this is a N-to-1 NOR gate and multiple AND gates - irqen_* is exactly as programmed by a write to the FPGA - status_* behavior is governed by a bi-stable D flip-flop => on next FPGA clock : - if i_xxx is high, status_xxx becomes 1 - if i_xxx is low, status_xxx remains as it is - if software sets status_xxx to 0, the D flip-flop is reset => status_xxx becomes 0 => on next FPGA clock cycle, if i_xxx is high, status_xxx becomes 1 again Fixes: fc9e38c0f4d3 ("ARM: pxa: lubbock: use new pxa_cplds driver") Reported-by: Russell King Signed-off-by: Robert Jarzmik --- arch/arm/mach-pxa/pxa_cplds_irqs.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'arch/arm/mach-pxa') diff --git a/arch/arm/mach-pxa/pxa_cplds_irqs.c b/arch/arm/mach-pxa/pxa_cplds_irqs.c index 2385052..e362f86 100644 --- a/arch/arm/mach-pxa/pxa_cplds_irqs.c +++ b/arch/arm/mach-pxa/pxa_cplds_irqs.c @@ -41,30 +41,35 @@ static irqreturn_t cplds_irq_handler(int in_irq, void *d) unsigned long pending; unsigned int bit; - pending = readl(fpga->base + FPGA_IRQ_SET_CLR) & fpga->irq_mask; - for_each_set_bit(bit, &pending, CPLDS_NB_IRQ) - generic_handle_irq(irq_find_mapping(fpga->irqdomain, bit)); + do { + pending = readl(fpga->base + FPGA_IRQ_SET_CLR) & fpga->irq_mask; + for_each_set_bit(bit, &pending, CPLDS_NB_IRQ) { + generic_handle_irq(irq_find_mapping(fpga->irqdomain, + bit)); + } + } while (pending); return IRQ_HANDLED; } -static void cplds_irq_mask_ack(struct irq_data *d) +static void cplds_irq_mask(struct irq_data *d) { struct cplds *fpga = irq_data_get_irq_chip_data(d); unsigned int cplds_irq = irqd_to_hwirq(d); - unsigned int set, bit = BIT(cplds_irq); + unsigned int bit = BIT(cplds_irq); fpga->irq_mask &= ~bit; writel(fpga->irq_mask, fpga->base + FPGA_IRQ_MASK_EN); - set = readl(fpga->base + FPGA_IRQ_SET_CLR); - writel(set & ~bit, fpga->base + FPGA_IRQ_SET_CLR); } static void cplds_irq_unmask(struct irq_data *d) { struct cplds *fpga = irq_data_get_irq_chip_data(d); unsigned int cplds_irq = irqd_to_hwirq(d); - unsigned int bit = BIT(cplds_irq); + unsigned int set, bit = BIT(cplds_irq); + + set = readl(fpga->base + FPGA_IRQ_SET_CLR); + writel(set & ~bit, fpga->base + FPGA_IRQ_SET_CLR); fpga->irq_mask |= bit; writel(fpga->irq_mask, fpga->base + FPGA_IRQ_MASK_EN); @@ -72,7 +77,8 @@ static void cplds_irq_unmask(struct irq_data *d) static struct irq_chip cplds_irq_chip = { .name = "pxa_cplds", - .irq_mask_ack = cplds_irq_mask_ack, + .irq_ack = cplds_irq_mask, + .irq_mask = cplds_irq_mask, .irq_unmask = cplds_irq_unmask, .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE, }; -- cgit v1.1