diff options
author | Shawn Guo <shawn.guo@linaro.org> | 2011-09-06 02:39:44 -0400 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2011-10-31 09:26:23 -0400 |
commit | 9fbbe6890c88aa332efe61d5894108dd8b932530 (patch) | |
tree | b27bedc317d68e969e9220cb93de8bc9fc5c62e8 /arch/arm/mach-imx/gpc.c | |
parent | 1103643c266ae45c7098e0f7f3ee0b68e3e7c7cc (diff) |
arm/imx6q: add core drivers clock, gpc, mmdc and src
It adds a number of core drivers support for imx6q, including clock,
General Power Controller (gpc), Multi Mode DDR Controller(mmdc) and
System Reset Controller (src).
Signed-off-by: Ranjani Vaidyanathan <ra5478@freescale.com>
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Diffstat (limited to 'arch/arm/mach-imx/gpc.c')
-rw-r--r-- | arch/arm/mach-imx/gpc.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c new file mode 100644 index 000000000000..e1537f9e45b8 --- /dev/null +++ b/arch/arm/mach-imx/gpc.c | |||
@@ -0,0 +1,113 @@ | |||
1 | /* | ||
2 | * Copyright 2011 Freescale Semiconductor, Inc. | ||
3 | * Copyright 2011 Linaro Ltd. | ||
4 | * | ||
5 | * The code contained herein is licensed under the GNU General Public | ||
6 | * License. You may obtain a copy of the GNU General Public License | ||
7 | * Version 2 or later at the following locations: | ||
8 | * | ||
9 | * http://www.opensource.org/licenses/gpl-license.html | ||
10 | * http://www.gnu.org/copyleft/gpl.html | ||
11 | */ | ||
12 | |||
13 | #include <linux/io.h> | ||
14 | #include <linux/irq.h> | ||
15 | #include <linux/of.h> | ||
16 | #include <linux/of_address.h> | ||
17 | #include <linux/of_irq.h> | ||
18 | #include <asm/hardware/gic.h> | ||
19 | |||
20 | #define GPC_IMR1 0x008 | ||
21 | #define GPC_PGC_CPU_PDN 0x2a0 | ||
22 | |||
23 | #define IMR_NUM 4 | ||
24 | |||
25 | static void __iomem *gpc_base; | ||
26 | static u32 gpc_wake_irqs[IMR_NUM]; | ||
27 | static u32 gpc_saved_imrs[IMR_NUM]; | ||
28 | |||
29 | void imx_gpc_pre_suspend(void) | ||
30 | { | ||
31 | void __iomem *reg_imr1 = gpc_base + GPC_IMR1; | ||
32 | int i; | ||
33 | |||
34 | /* Tell GPC to power off ARM core when suspend */ | ||
35 | writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN); | ||
36 | |||
37 | for (i = 0; i < IMR_NUM; i++) { | ||
38 | gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4); | ||
39 | writel_relaxed(~gpc_wake_irqs[i], reg_imr1 + i * 4); | ||
40 | } | ||
41 | } | ||
42 | |||
43 | void imx_gpc_post_resume(void) | ||
44 | { | ||
45 | void __iomem *reg_imr1 = gpc_base + GPC_IMR1; | ||
46 | int i; | ||
47 | |||
48 | /* Keep ARM core powered on for other low-power modes */ | ||
49 | writel_relaxed(0x0, gpc_base + GPC_PGC_CPU_PDN); | ||
50 | |||
51 | for (i = 0; i < IMR_NUM; i++) | ||
52 | writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4); | ||
53 | } | ||
54 | |||
55 | static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on) | ||
56 | { | ||
57 | unsigned int idx = d->irq / 32 - 1; | ||
58 | u32 mask; | ||
59 | |||
60 | /* Sanity check for SPI irq */ | ||
61 | if (d->irq < 32) | ||
62 | return -EINVAL; | ||
63 | |||
64 | mask = 1 << d->irq % 32; | ||
65 | gpc_wake_irqs[idx] = on ? gpc_wake_irqs[idx] | mask : | ||
66 | gpc_wake_irqs[idx] & ~mask; | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static void imx_gpc_irq_unmask(struct irq_data *d) | ||
72 | { | ||
73 | void __iomem *reg; | ||
74 | u32 val; | ||
75 | |||
76 | /* Sanity check for SPI irq */ | ||
77 | if (d->irq < 32) | ||
78 | return; | ||
79 | |||
80 | reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4; | ||
81 | val = readl_relaxed(reg); | ||
82 | val &= ~(1 << d->irq % 32); | ||
83 | writel_relaxed(val, reg); | ||
84 | } | ||
85 | |||
86 | static void imx_gpc_irq_mask(struct irq_data *d) | ||
87 | { | ||
88 | void __iomem *reg; | ||
89 | u32 val; | ||
90 | |||
91 | /* Sanity check for SPI irq */ | ||
92 | if (d->irq < 32) | ||
93 | return; | ||
94 | |||
95 | reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4; | ||
96 | val = readl_relaxed(reg); | ||
97 | val |= 1 << (d->irq % 32); | ||
98 | writel_relaxed(val, reg); | ||
99 | } | ||
100 | |||
101 | void __init imx_gpc_init(void) | ||
102 | { | ||
103 | struct device_node *np; | ||
104 | |||
105 | np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc"); | ||
106 | gpc_base = of_iomap(np, 0); | ||
107 | WARN_ON(!gpc_base); | ||
108 | |||
109 | /* Register GPC as the secondary interrupt controller behind GIC */ | ||
110 | gic_arch_extn.irq_mask = imx_gpc_irq_mask; | ||
111 | gic_arch_extn.irq_unmask = imx_gpc_irq_unmask; | ||
112 | gic_arch_extn.irq_set_wake = imx_gpc_irq_set_wake; | ||
113 | } | ||