Message ID | E1a6FyD-0005AX-Bp@rmk-PC.arm.linux.org.uk (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi Russell, On mar., déc. 08 2015, Russell King <rmk+kernel@arm.linux.org.uk> wrote: > Since Dove has non-DT support for various facilities in the PMU, convert > the legacy support to use the new PMU driver. > > Acked-by: Arnd Bergmann <arnd@arndb.de> > Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> I applied this version on mvebu/soc and fixed trivial merge conflict with Arnd series. Thanks, Gregory > --- > arch/arm/Kconfig | 1 + > arch/arm/mach-dove/common.c | 26 +++++++++++ > arch/arm/mach-dove/include/mach/pm.h | 20 +++----- > arch/arm/mach-dove/irq.c | 88 ------------------------------------ > 4 files changed, 33 insertions(+), 102 deletions(-) > > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig > index 639411f73ca9..498783f16062 100644 > --- a/arch/arm/Kconfig > +++ b/arch/arm/Kconfig > @@ -514,6 +514,7 @@ config ARCH_DOVE > select PINCTRL > select PINCTRL_DOVE > select PLAT_ORION_LEGACY > + select PM_GENERIC_DOMAINS if PM > help > Support for the Marvell Dove SoC 88AP510 > > diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c > index 0d1a89298ece..5d01723cf062 100644 > --- a/arch/arm/mach-dove/common.c > +++ b/arch/arm/mach-dove/common.c > @@ -16,6 +16,7 @@ > #include <linux/platform_data/dma-mv_xor.h> > #include <linux/platform_data/usb-ehci-orion.h> > #include <linux/platform_device.h> > +#include <linux/soc/dove/pmu.h> > #include <asm/hardware/cache-tauros2.h> > #include <asm/mach/arch.h> > #include <asm/mach/map.h> > @@ -375,6 +376,30 @@ void __init dove_setup_cpu_wins(void) > DOVE_SCRATCHPAD_SIZE); > } > > +static const struct dove_pmu_domain_initdata pmu_domains[] __initconst = { > + { > + .pwr_mask = PMU_PWR_VPU_PWR_DWN_MASK, > + .rst_mask = PMU_SW_RST_VIDEO_MASK, > + .iso_mask = PMU_ISO_VIDEO_MASK, > + .name = "vpu-domain", > + }, { > + .pwr_mask = PMU_PWR_GPU_PWR_DWN_MASK, > + .rst_mask = PMU_SW_RST_GPU_MASK, > + .iso_mask = PMU_ISO_GPU_MASK, > + .name = "gpu-domain", > + }, { > + /* sentinel */ > + }, > +}; > + > +static const struct dove_pmu_initdata pmu_data __initconst = { > + .pmc_base = DOVE_PMU_VIRT_BASE, > + .pmu_base = DOVE_PMU_VIRT_BASE + 0x8000, > + .irq = IRQ_DOVE_PMU, > + .irq_domain_start = IRQ_DOVE_PMU_START, > + .domains = pmu_domains, > +}; > + > void __init dove_init(void) > { > pr_info("Dove 88AP510 SoC, TCLK = %d MHz.\n", > @@ -389,6 +414,7 @@ void __init dove_init(void) > dove_clk_init(); > > /* internal devices that every board has */ > + dove_init_pmu_legacy(&pmu_data); > dove_rtc_init(); > dove_xor0_init(); > dove_xor1_init(); > diff --git a/arch/arm/mach-dove/include/mach/pm.h b/arch/arm/mach-dove/include/mach/pm.h > index b47f75038686..d22b9b174007 100644 > --- a/arch/arm/mach-dove/include/mach/pm.h > +++ b/arch/arm/mach-dove/include/mach/pm.h > @@ -51,22 +51,14 @@ > #define CLOCK_GATING_GIGA_PHY_MASK (1 << CLOCK_GATING_BIT_GIGA_PHY) > > #define PMU_INTERRUPT_CAUSE (DOVE_PMU_VIRT_BASE + 0x50) > -#define PMU_INTERRUPT_MASK (DOVE_PMU_VIRT_BASE + 0x54) > > -static inline int pmu_to_irq(int pin) > -{ > - if (pin < NR_PMU_IRQS) > - return pin + IRQ_DOVE_PMU_START; > +#define PMU_SW_RST_VIDEO_MASK BIT(16) > +#define PMU_SW_RST_GPU_MASK BIT(18) > > - return -EINVAL; > -} > +#define PMU_PWR_GPU_PWR_DWN_MASK BIT(2) > +#define PMU_PWR_VPU_PWR_DWN_MASK BIT(3) > > -static inline int irq_to_pmu(int irq) > -{ > - if (IRQ_DOVE_PMU_START <= irq && irq < NR_IRQS) > - return irq - IRQ_DOVE_PMU_START; > - > - return -EINVAL; > -} > +#define PMU_ISO_VIDEO_MASK BIT(0) > +#define PMU_ISO_GPU_MASK BIT(1) > > #endif > diff --git a/arch/arm/mach-dove/irq.c b/arch/arm/mach-dove/irq.c > index bfb3703357c5..7e5a3248b82b 100644 > --- a/arch/arm/mach-dove/irq.c > +++ b/arch/arm/mach-dove/irq.c > @@ -7,87 +7,14 @@ > * License version 2. This program is licensed "as is" without any > * warranty of any kind, whether express or implied. > */ > - > -#include <linux/kernel.h> > #include <linux/init.h> > #include <linux/irq.h> > -#include <linux/gpio.h> > #include <linux/io.h> > -#include <asm/mach/arch.h> > #include <plat/irq.h> > -#include <asm/mach/irq.h> > -#include <mach/pm.h> > #include <mach/bridge-regs.h> > #include <plat/orion-gpio.h> > #include "common.h" > > -static void pmu_irq_mask(struct irq_data *d) > -{ > - int pin = irq_to_pmu(d->irq); > - u32 u; > - > - u = readl(PMU_INTERRUPT_MASK); > - u &= ~(1 << (pin & 31)); > - writel(u, PMU_INTERRUPT_MASK); > -} > - > -static void pmu_irq_unmask(struct irq_data *d) > -{ > - int pin = irq_to_pmu(d->irq); > - u32 u; > - > - u = readl(PMU_INTERRUPT_MASK); > - u |= 1 << (pin & 31); > - writel(u, PMU_INTERRUPT_MASK); > -} > - > -static void pmu_irq_ack(struct irq_data *d) > -{ > - int pin = irq_to_pmu(d->irq); > - u32 u; > - > - /* > - * The PMU mask register is not RW0C: it is RW. This means that > - * the bits take whatever value is written to them; if you write > - * a '1', you will set the interrupt. > - * > - * Unfortunately this means there is NO race free way to clear > - * these interrupts. > - * > - * So, let's structure the code so that the window is as small as > - * possible. > - */ > - u = ~(1 << (pin & 31)); > - u &= readl_relaxed(PMU_INTERRUPT_CAUSE); > - writel_relaxed(u, PMU_INTERRUPT_CAUSE); > -} > - > -static struct irq_chip pmu_irq_chip = { > - .name = "pmu_irq", > - .irq_mask = pmu_irq_mask, > - .irq_unmask = pmu_irq_unmask, > - .irq_ack = pmu_irq_ack, > -}; > - > -static void pmu_irq_handler(struct irq_desc *desc) > -{ > - unsigned long cause = readl(PMU_INTERRUPT_CAUSE); > - unsigned int irq; > - > - cause &= readl(PMU_INTERRUPT_MASK); > - if (cause == 0) { > - do_bad_IRQ(desc); > - return; > - } > - > - for (irq = 0; irq < NR_PMU_IRQS; irq++) { > - if (!(cause & (1 << irq))) > - continue; > - irq = pmu_to_irq(irq); > - generic_handle_irq(irq); > - } > -} > - > static int __initdata gpio0_irqs[4] = { > IRQ_DOVE_GPIO_0_7, > IRQ_DOVE_GPIO_8_15, > @@ -143,8 +70,6 @@ __exception_irq_entry dove_legacy_handle_irq(struct pt_regs *regs) > > void __init dove_init_irq(void) > { > - int i; > - > orion_irq_init(1, IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF); > orion_irq_init(33, IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF); > > @@ -163,17 +88,4 @@ void __init dove_init_irq(void) > > orion_gpio_init(NULL, 64, 8, DOVE_GPIO2_VIRT_BASE, 0, > IRQ_DOVE_GPIO_START + 64, gpio2_irqs); > - > - /* > - * Mask and clear PMU interrupts > - */ > - writel(0, PMU_INTERRUPT_MASK); > - writel(0, PMU_INTERRUPT_CAUSE); > - > - for (i = IRQ_DOVE_PMU_START; i < NR_IRQS; i++) { > - irq_set_chip_and_handler(i, &pmu_irq_chip, handle_level_irq); > - irq_set_status_flags(i, IRQ_LEVEL); > - irq_clear_status_flags(i, IRQ_NOREQUEST); > - } > - irq_set_chained_handler(IRQ_DOVE_PMU, pmu_irq_handler); > } > -- > 2.1.0 >
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 639411f73ca9..498783f16062 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -514,6 +514,7 @@ config ARCH_DOVE select PINCTRL select PINCTRL_DOVE select PLAT_ORION_LEGACY + select PM_GENERIC_DOMAINS if PM help Support for the Marvell Dove SoC 88AP510 diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c index 0d1a89298ece..5d01723cf062 100644 --- a/arch/arm/mach-dove/common.c +++ b/arch/arm/mach-dove/common.c @@ -16,6 +16,7 @@ #include <linux/platform_data/dma-mv_xor.h> #include <linux/platform_data/usb-ehci-orion.h> #include <linux/platform_device.h> +#include <linux/soc/dove/pmu.h> #include <asm/hardware/cache-tauros2.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -375,6 +376,30 @@ void __init dove_setup_cpu_wins(void) DOVE_SCRATCHPAD_SIZE); } +static const struct dove_pmu_domain_initdata pmu_domains[] __initconst = { + { + .pwr_mask = PMU_PWR_VPU_PWR_DWN_MASK, + .rst_mask = PMU_SW_RST_VIDEO_MASK, + .iso_mask = PMU_ISO_VIDEO_MASK, + .name = "vpu-domain", + }, { + .pwr_mask = PMU_PWR_GPU_PWR_DWN_MASK, + .rst_mask = PMU_SW_RST_GPU_MASK, + .iso_mask = PMU_ISO_GPU_MASK, + .name = "gpu-domain", + }, { + /* sentinel */ + }, +}; + +static const struct dove_pmu_initdata pmu_data __initconst = { + .pmc_base = DOVE_PMU_VIRT_BASE, + .pmu_base = DOVE_PMU_VIRT_BASE + 0x8000, + .irq = IRQ_DOVE_PMU, + .irq_domain_start = IRQ_DOVE_PMU_START, + .domains = pmu_domains, +}; + void __init dove_init(void) { pr_info("Dove 88AP510 SoC, TCLK = %d MHz.\n", @@ -389,6 +414,7 @@ void __init dove_init(void) dove_clk_init(); /* internal devices that every board has */ + dove_init_pmu_legacy(&pmu_data); dove_rtc_init(); dove_xor0_init(); dove_xor1_init(); diff --git a/arch/arm/mach-dove/include/mach/pm.h b/arch/arm/mach-dove/include/mach/pm.h index b47f75038686..d22b9b174007 100644 --- a/arch/arm/mach-dove/include/mach/pm.h +++ b/arch/arm/mach-dove/include/mach/pm.h @@ -51,22 +51,14 @@ #define CLOCK_GATING_GIGA_PHY_MASK (1 << CLOCK_GATING_BIT_GIGA_PHY) #define PMU_INTERRUPT_CAUSE (DOVE_PMU_VIRT_BASE + 0x50) -#define PMU_INTERRUPT_MASK (DOVE_PMU_VIRT_BASE + 0x54) -static inline int pmu_to_irq(int pin) -{ - if (pin < NR_PMU_IRQS) - return pin + IRQ_DOVE_PMU_START; +#define PMU_SW_RST_VIDEO_MASK BIT(16) +#define PMU_SW_RST_GPU_MASK BIT(18) - return -EINVAL; -} +#define PMU_PWR_GPU_PWR_DWN_MASK BIT(2) +#define PMU_PWR_VPU_PWR_DWN_MASK BIT(3) -static inline int irq_to_pmu(int irq) -{ - if (IRQ_DOVE_PMU_START <= irq && irq < NR_IRQS) - return irq - IRQ_DOVE_PMU_START; - - return -EINVAL; -} +#define PMU_ISO_VIDEO_MASK BIT(0) +#define PMU_ISO_GPU_MASK BIT(1) #endif diff --git a/arch/arm/mach-dove/irq.c b/arch/arm/mach-dove/irq.c index bfb3703357c5..7e5a3248b82b 100644 --- a/arch/arm/mach-dove/irq.c +++ b/arch/arm/mach-dove/irq.c @@ -7,87 +7,14 @@ * License version 2. This program is licensed "as is" without any * warranty of any kind, whether express or implied. */ - -#include <linux/kernel.h> #include <linux/init.h> #include <linux/irq.h> -#include <linux/gpio.h> #include <linux/io.h> -#include <asm/mach/arch.h> #include <plat/irq.h> -#include <asm/mach/irq.h> -#include <mach/pm.h> #include <mach/bridge-regs.h> #include <plat/orion-gpio.h> #include "common.h" -static void pmu_irq_mask(struct irq_data *d) -{ - int pin = irq_to_pmu(d->irq); - u32 u; - - u = readl(PMU_INTERRUPT_MASK); - u &= ~(1 << (pin & 31)); - writel(u, PMU_INTERRUPT_MASK); -} - -static void pmu_irq_unmask(struct irq_data *d) -{ - int pin = irq_to_pmu(d->irq); - u32 u; - - u = readl(PMU_INTERRUPT_MASK); - u |= 1 << (pin & 31); - writel(u, PMU_INTERRUPT_MASK); -} - -static void pmu_irq_ack(struct irq_data *d) -{ - int pin = irq_to_pmu(d->irq); - u32 u; - - /* - * The PMU mask register is not RW0C: it is RW. This means that - * the bits take whatever value is written to them; if you write - * a '1', you will set the interrupt. - * - * Unfortunately this means there is NO race free way to clear - * these interrupts. - * - * So, let's structure the code so that the window is as small as - * possible. - */ - u = ~(1 << (pin & 31)); - u &= readl_relaxed(PMU_INTERRUPT_CAUSE); - writel_relaxed(u, PMU_INTERRUPT_CAUSE); -} - -static struct irq_chip pmu_irq_chip = { - .name = "pmu_irq", - .irq_mask = pmu_irq_mask, - .irq_unmask = pmu_irq_unmask, - .irq_ack = pmu_irq_ack, -}; - -static void pmu_irq_handler(struct irq_desc *desc) -{ - unsigned long cause = readl(PMU_INTERRUPT_CAUSE); - unsigned int irq; - - cause &= readl(PMU_INTERRUPT_MASK); - if (cause == 0) { - do_bad_IRQ(desc); - return; - } - - for (irq = 0; irq < NR_PMU_IRQS; irq++) { - if (!(cause & (1 << irq))) - continue; - irq = pmu_to_irq(irq); - generic_handle_irq(irq); - } -} - static int __initdata gpio0_irqs[4] = { IRQ_DOVE_GPIO_0_7, IRQ_DOVE_GPIO_8_15, @@ -143,8 +70,6 @@ __exception_irq_entry dove_legacy_handle_irq(struct pt_regs *regs) void __init dove_init_irq(void) { - int i; - orion_irq_init(1, IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF); orion_irq_init(33, IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF); @@ -163,17 +88,4 @@ void __init dove_init_irq(void) orion_gpio_init(NULL, 64, 8, DOVE_GPIO2_VIRT_BASE, 0, IRQ_DOVE_GPIO_START + 64, gpio2_irqs); - - /* - * Mask and clear PMU interrupts - */ - writel(0, PMU_INTERRUPT_MASK); - writel(0, PMU_INTERRUPT_CAUSE); - - for (i = IRQ_DOVE_PMU_START; i < NR_IRQS; i++) { - irq_set_chip_and_handler(i, &pmu_irq_chip, handle_level_irq); - irq_set_status_flags(i, IRQ_LEVEL); - irq_clear_status_flags(i, IRQ_NOREQUEST); - } - irq_set_chained_handler(IRQ_DOVE_PMU, pmu_irq_handler); }