aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2015-12-08 05:58:09 -0500
committerGregory CLEMENT <gregory.clement@free-electrons.com>2015-12-08 07:23:14 -0500
commitc5d431e8c511788556651b91debd7d77d4508f4b (patch)
tree8461d77d858316f318b35eac78f2187eb5482f76
parent67098119abeb596823ed0a74dd8cdcfbee4c2210 (diff)
ARM: dove: convert legacy dove to PMU support
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> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/mach-dove/common.c26
-rw-r--r--arch/arm/mach-dove/include/mach/pm.h20
-rw-r--r--arch/arm/mach-dove/irq.c88
4 files changed, 33 insertions, 102 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 473c1417968a..72af9d6f8c13 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -516,6 +516,7 @@ config ARCH_DOVE
516 select PINCTRL_DOVE 516 select PINCTRL_DOVE
517 select PLAT_ORION_LEGACY 517 select PLAT_ORION_LEGACY
518 select SPARSE_IRQ 518 select SPARSE_IRQ
519 select PM_GENERIC_DOMAINS if PM
519 help 520 help
520 Support for the Marvell Dove SoC 88AP510 521 Support for the Marvell Dove SoC 88AP510
521 522
diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c
index 25a682fd444f..0cdaa3851d2e 100644
--- a/arch/arm/mach-dove/common.c
+++ b/arch/arm/mach-dove/common.c
@@ -16,6 +16,7 @@
16#include <linux/platform_data/dma-mv_xor.h> 16#include <linux/platform_data/dma-mv_xor.h>
17#include <linux/platform_data/usb-ehci-orion.h> 17#include <linux/platform_data/usb-ehci-orion.h>
18#include <linux/platform_device.h> 18#include <linux/platform_device.h>
19#include <linux/soc/dove/pmu.h>
19#include <asm/hardware/cache-tauros2.h> 20#include <asm/hardware/cache-tauros2.h>
20#include <asm/mach/arch.h> 21#include <asm/mach/arch.h>
21#include <asm/mach/map.h> 22#include <asm/mach/map.h>
@@ -392,6 +393,30 @@ static void __init __maybe_unused orion_wdt_init(void)
392 platform_device_register(&orion_wdt_device); 393 platform_device_register(&orion_wdt_device);
393} 394}
394 395
396static const struct dove_pmu_domain_initdata pmu_domains[] __initconst = {
397 {
398 .pwr_mask = PMU_PWR_VPU_PWR_DWN_MASK,
399 .rst_mask = PMU_SW_RST_VIDEO_MASK,
400 .iso_mask = PMU_ISO_VIDEO_MASK,
401 .name = "vpu-domain",
402 }, {
403 .pwr_mask = PMU_PWR_GPU_PWR_DWN_MASK,
404 .rst_mask = PMU_SW_RST_GPU_MASK,
405 .iso_mask = PMU_ISO_GPU_MASK,
406 .name = "gpu-domain",
407 }, {
408 /* sentinel */
409 },
410};
411
412static const struct dove_pmu_initdata pmu_data __initconst = {
413 .pmc_base = DOVE_PMU_VIRT_BASE,
414 .pmu_base = DOVE_PMU_VIRT_BASE + 0x8000,
415 .irq = IRQ_DOVE_PMU,
416 .irq_domain_start = IRQ_DOVE_PMU_START,
417 .domains = pmu_domains,
418};
419
395void __init dove_init(void) 420void __init dove_init(void)
396{ 421{
397 pr_info("Dove 88AP510 SoC, TCLK = %d MHz.\n", 422 pr_info("Dove 88AP510 SoC, TCLK = %d MHz.\n",
@@ -406,6 +431,7 @@ void __init dove_init(void)
406 dove_clk_init(); 431 dove_clk_init();
407 432
408 /* internal devices that every board has */ 433 /* internal devices that every board has */
434 dove_init_pmu_legacy(&pmu_data);
409 dove_rtc_init(); 435 dove_rtc_init();
410 dove_xor0_init(); 436 dove_xor0_init();
411 dove_xor1_init(); 437 dove_xor1_init();
diff --git a/arch/arm/mach-dove/include/mach/pm.h b/arch/arm/mach-dove/include/mach/pm.h
index 9834ba10cd13..d22b9b174007 100644
--- a/arch/arm/mach-dove/include/mach/pm.h
+++ b/arch/arm/mach-dove/include/mach/pm.h
@@ -51,22 +51,14 @@
51#define CLOCK_GATING_GIGA_PHY_MASK (1 << CLOCK_GATING_BIT_GIGA_PHY) 51#define CLOCK_GATING_GIGA_PHY_MASK (1 << CLOCK_GATING_BIT_GIGA_PHY)
52 52
53#define PMU_INTERRUPT_CAUSE (DOVE_PMU_VIRT_BASE + 0x50) 53#define PMU_INTERRUPT_CAUSE (DOVE_PMU_VIRT_BASE + 0x50)
54#define PMU_INTERRUPT_MASK (DOVE_PMU_VIRT_BASE + 0x54)
55 54
56static inline int pmu_to_irq(int pin) 55#define PMU_SW_RST_VIDEO_MASK BIT(16)
57{ 56#define PMU_SW_RST_GPU_MASK BIT(18)
58 if (pin < NR_PMU_IRQS)
59 return pin + IRQ_DOVE_PMU_START;
60 57
61 return -EINVAL; 58#define PMU_PWR_GPU_PWR_DWN_MASK BIT(2)
62} 59#define PMU_PWR_VPU_PWR_DWN_MASK BIT(3)
63 60
64static inline int irq_to_pmu(int irq) 61#define PMU_ISO_VIDEO_MASK BIT(0)
65{ 62#define PMU_ISO_GPU_MASK BIT(1)
66 if (IRQ_DOVE_PMU_START <= irq && irq < DOVE_NR_IRQS)
67 return irq - IRQ_DOVE_PMU_START;
68
69 return -EINVAL;
70}
71 63
72#endif 64#endif
diff --git a/arch/arm/mach-dove/irq.c b/arch/arm/mach-dove/irq.c
index ad785d34c1e7..d6627c1f7f30 100644
--- a/arch/arm/mach-dove/irq.c
+++ b/arch/arm/mach-dove/irq.c
@@ -7,88 +7,15 @@
7 * License version 2. This program is licensed "as is" without any 7 * License version 2. This program is licensed "as is" without any
8 * warranty of any kind, whether express or implied. 8 * warranty of any kind, whether express or implied.
9 */ 9 */
10
11#include <linux/kernel.h>
12#include <linux/init.h> 10#include <linux/init.h>
13#include <linux/irq.h> 11#include <linux/irq.h>
14#include <linux/gpio.h>
15#include <linux/io.h> 12#include <linux/io.h>
16#include <asm/exception.h> 13#include <asm/exception.h>
17#include <asm/mach/arch.h>
18#include <plat/irq.h> 14#include <plat/irq.h>
19#include <asm/mach/irq.h>
20#include <mach/pm.h>
21#include <mach/bridge-regs.h> 15#include <mach/bridge-regs.h>
22#include <plat/orion-gpio.h> 16#include <plat/orion-gpio.h>
23#include "common.h" 17#include "common.h"
24 18
25static void pmu_irq_mask(struct irq_data *d)
26{
27 int pin = irq_to_pmu(d->irq);
28 u32 u;
29
30 u = readl(PMU_INTERRUPT_MASK);
31 u &= ~(1 << (pin & 31));
32 writel(u, PMU_INTERRUPT_MASK);
33}
34
35static void pmu_irq_unmask(struct irq_data *d)
36{
37 int pin = irq_to_pmu(d->irq);
38 u32 u;
39
40 u = readl(PMU_INTERRUPT_MASK);
41 u |= 1 << (pin & 31);
42 writel(u, PMU_INTERRUPT_MASK);
43}
44
45static void pmu_irq_ack(struct irq_data *d)
46{
47 int pin = irq_to_pmu(d->irq);
48 u32 u;
49
50 /*
51 * The PMU mask register is not RW0C: it is RW. This means that
52 * the bits take whatever value is written to them; if you write
53 * a '1', you will set the interrupt.
54 *
55 * Unfortunately this means there is NO race free way to clear
56 * these interrupts.
57 *
58 * So, let's structure the code so that the window is as small as
59 * possible.
60 */
61 u = ~(1 << (pin & 31));
62 u &= readl_relaxed(PMU_INTERRUPT_CAUSE);
63 writel_relaxed(u, PMU_INTERRUPT_CAUSE);
64}
65
66static struct irq_chip pmu_irq_chip = {
67 .name = "pmu_irq",
68 .irq_mask = pmu_irq_mask,
69 .irq_unmask = pmu_irq_unmask,
70 .irq_ack = pmu_irq_ack,
71};
72
73static void pmu_irq_handler(struct irq_desc *desc)
74{
75 unsigned long cause = readl(PMU_INTERRUPT_CAUSE);
76 unsigned int irq;
77
78 cause &= readl(PMU_INTERRUPT_MASK);
79 if (cause == 0) {
80 do_bad_IRQ(desc);
81 return;
82 }
83
84 for (irq = 0; irq < NR_PMU_IRQS; irq++) {
85 if (!(cause & (1 << irq)))
86 continue;
87 irq = pmu_to_irq(irq);
88 generic_handle_irq(irq);
89 }
90}
91
92static int __initdata gpio0_irqs[4] = { 19static int __initdata gpio0_irqs[4] = {
93 IRQ_DOVE_GPIO_0_7, 20 IRQ_DOVE_GPIO_0_7,
94 IRQ_DOVE_GPIO_8_15, 21 IRQ_DOVE_GPIO_8_15,
@@ -135,8 +62,6 @@ __exception_irq_entry dove_legacy_handle_irq(struct pt_regs *regs)
135 62
136void __init dove_init_irq(void) 63void __init dove_init_irq(void)
137{ 64{
138 int i;
139
140 orion_irq_init(1, IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF); 65 orion_irq_init(1, IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF);
141 orion_irq_init(33, IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF); 66 orion_irq_init(33, IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF);
142 67
@@ -153,17 +78,4 @@ void __init dove_init_irq(void)
153 78
154 orion_gpio_init(NULL, 64, 8, DOVE_GPIO2_VIRT_BASE, 0, 79 orion_gpio_init(NULL, 64, 8, DOVE_GPIO2_VIRT_BASE, 0,
155 IRQ_DOVE_GPIO_START + 64, gpio2_irqs); 80 IRQ_DOVE_GPIO_START + 64, gpio2_irqs);
156
157 /*
158 * Mask and clear PMU interrupts
159 */
160 writel(0, PMU_INTERRUPT_MASK);
161 writel(0, PMU_INTERRUPT_CAUSE);
162
163 for (i = IRQ_DOVE_PMU_START; i < DOVE_NR_IRQS; i++) {
164 irq_set_chip_and_handler(i, &pmu_irq_chip, handle_level_irq);
165 irq_set_status_flags(i, IRQ_LEVEL);
166 irq_clear_status_flags(i, IRQ_NOREQUEST);
167 }
168 irq_set_chained_handler(IRQ_DOVE_PMU, pmu_irq_handler);
169} 81}