diff options
Diffstat (limited to 'arch/arm/mach-stmp37xx/stmp37xx.c')
-rw-r--r-- | arch/arm/mach-stmp37xx/stmp37xx.c | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/arch/arm/mach-stmp37xx/stmp37xx.c b/arch/arm/mach-stmp37xx/stmp37xx.c new file mode 100644 index 000000000000..8c7d6fb191a3 --- /dev/null +++ b/arch/arm/mach-stmp37xx/stmp37xx.c | |||
@@ -0,0 +1,219 @@ | |||
1 | /* | ||
2 | * Freescale STMP37XX platform support | ||
3 | * | ||
4 | * Embedded Alley Solutions, Inc <source@embeddedalley.com> | ||
5 | * | ||
6 | * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved. | ||
7 | * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * The code contained herein is licensed under the GNU General Public | ||
12 | * License. You may obtain a copy of the GNU General Public License | ||
13 | * Version 2 or later at the following locations: | ||
14 | * | ||
15 | * http://www.opensource.org/licenses/gpl-license.html | ||
16 | * http://www.gnu.org/copyleft/gpl.html | ||
17 | */ | ||
18 | #include <linux/types.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/device.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/irq.h> | ||
24 | #include <linux/io.h> | ||
25 | |||
26 | #include <asm/setup.h> | ||
27 | #include <asm/mach-types.h> | ||
28 | |||
29 | #include <asm/mach/arch.h> | ||
30 | #include <asm/mach/irq.h> | ||
31 | #include <asm/mach/map.h> | ||
32 | #include <asm/mach/time.h> | ||
33 | |||
34 | #include <mach/stmp3xxx.h> | ||
35 | #include <mach/dma.h> | ||
36 | |||
37 | #include <mach/platform.h> | ||
38 | #include <mach/regs-icoll.h> | ||
39 | #include <mach/regs-apbh.h> | ||
40 | #include <mach/regs-apbx.h> | ||
41 | #include "stmp37xx.h" | ||
42 | |||
43 | /* | ||
44 | * IRQ handling | ||
45 | */ | ||
46 | static void stmp37xx_ack_irq(unsigned int irq) | ||
47 | { | ||
48 | /* Disable IRQ */ | ||
49 | stmp3xxx_clearl(0x04 << ((irq % 4) * 8), | ||
50 | REGS_ICOLL_BASE + HW_ICOLL_PRIORITYn + irq / 4 * 0x10); | ||
51 | |||
52 | /* ACK current interrupt */ | ||
53 | __raw_writel(1, REGS_ICOLL_BASE + HW_ICOLL_LEVELACK); | ||
54 | |||
55 | /* Barrier */ | ||
56 | (void)__raw_readl(REGS_ICOLL_BASE + HW_ICOLL_STAT); | ||
57 | } | ||
58 | |||
59 | static void stmp37xx_mask_irq(unsigned int irq) | ||
60 | { | ||
61 | /* IRQ disable */ | ||
62 | stmp3xxx_clearl(0x04 << ((irq % 4) * 8), | ||
63 | REGS_ICOLL_BASE + HW_ICOLL_PRIORITYn + irq / 4 * 0x10); | ||
64 | } | ||
65 | |||
66 | static void stmp37xx_unmask_irq(unsigned int irq) | ||
67 | { | ||
68 | /* IRQ enable */ | ||
69 | stmp3xxx_setl(0x04 << ((irq % 4) * 8), | ||
70 | REGS_ICOLL_BASE + HW_ICOLL_PRIORITYn + irq / 4 * 0x10); | ||
71 | } | ||
72 | |||
73 | static struct irq_chip stmp37xx_chip = { | ||
74 | .ack = stmp37xx_ack_irq, | ||
75 | .mask = stmp37xx_mask_irq, | ||
76 | .unmask = stmp37xx_unmask_irq, | ||
77 | }; | ||
78 | |||
79 | void __init stmp37xx_init_irq(void) | ||
80 | { | ||
81 | stmp3xxx_init_irq(&stmp37xx_chip); | ||
82 | } | ||
83 | |||
84 | /* | ||
85 | * DMA interrupt handling | ||
86 | */ | ||
87 | void stmp3xxx_arch_dma_enable_interrupt(int channel) | ||
88 | { | ||
89 | switch (STMP3XXX_DMA_BUS(channel)) { | ||
90 | case STMP3XXX_BUS_APBH: | ||
91 | stmp3xxx_setl(1 << (8 + STMP3XXX_DMA_CHANNEL(channel)), | ||
92 | REGS_APBH_BASE + HW_APBH_CTRL1); | ||
93 | break; | ||
94 | |||
95 | case STMP3XXX_BUS_APBX: | ||
96 | stmp3xxx_setl(1 << (8 + STMP3XXX_DMA_CHANNEL(channel)), | ||
97 | REGS_APBX_BASE + HW_APBX_CTRL1); | ||
98 | break; | ||
99 | } | ||
100 | } | ||
101 | EXPORT_SYMBOL(stmp3xxx_arch_dma_enable_interrupt); | ||
102 | |||
103 | void stmp3xxx_arch_dma_clear_interrupt(int channel) | ||
104 | { | ||
105 | switch (STMP3XXX_DMA_BUS(channel)) { | ||
106 | case STMP3XXX_BUS_APBH: | ||
107 | stmp3xxx_clearl(1 << STMP3XXX_DMA_CHANNEL(channel), | ||
108 | REGS_APBH_BASE + HW_APBH_CTRL1); | ||
109 | break; | ||
110 | |||
111 | case STMP3XXX_BUS_APBX: | ||
112 | stmp3xxx_clearl(1 << STMP3XXX_DMA_CHANNEL(channel), | ||
113 | REGS_APBX_BASE + HW_APBX_CTRL1); | ||
114 | break; | ||
115 | } | ||
116 | } | ||
117 | EXPORT_SYMBOL(stmp3xxx_arch_dma_clear_interrupt); | ||
118 | |||
119 | int stmp3xxx_arch_dma_is_interrupt(int channel) | ||
120 | { | ||
121 | int r = 0; | ||
122 | |||
123 | switch (STMP3XXX_DMA_BUS(channel)) { | ||
124 | case STMP3XXX_BUS_APBH: | ||
125 | r = __raw_readl(REGS_APBH_BASE + HW_APBH_CTRL1) & | ||
126 | (1 << STMP3XXX_DMA_CHANNEL(channel)); | ||
127 | break; | ||
128 | |||
129 | case STMP3XXX_BUS_APBX: | ||
130 | r = __raw_readl(REGS_APBH_BASE + HW_APBH_CTRL1) & | ||
131 | (1 << STMP3XXX_DMA_CHANNEL(channel)); | ||
132 | break; | ||
133 | } | ||
134 | return r; | ||
135 | } | ||
136 | EXPORT_SYMBOL(stmp3xxx_arch_dma_is_interrupt); | ||
137 | |||
138 | void stmp3xxx_arch_dma_reset_channel(int channel) | ||
139 | { | ||
140 | unsigned chbit = 1 << STMP3XXX_DMA_CHANNEL(channel); | ||
141 | |||
142 | switch (STMP3XXX_DMA_BUS(channel)) { | ||
143 | case STMP3XXX_BUS_APBH: | ||
144 | /* Reset channel and wait for it to complete */ | ||
145 | stmp3xxx_setl(chbit << BP_APBH_CTRL0_RESET_CHANNEL, | ||
146 | REGS_APBH_BASE + HW_APBH_CTRL0); | ||
147 | while (__raw_readl(REGS_APBH_BASE + HW_APBH_CTRL0) & | ||
148 | (chbit << BP_APBH_CTRL0_RESET_CHANNEL)) | ||
149 | cpu_relax(); | ||
150 | break; | ||
151 | |||
152 | case STMP3XXX_BUS_APBX: | ||
153 | stmp3xxx_setl(chbit << BP_APBX_CTRL0_RESET_CHANNEL, | ||
154 | REGS_APBX_BASE + HW_APBX_CTRL0); | ||
155 | while (__raw_readl(REGS_APBX_BASE + HW_APBX_CTRL0) & | ||
156 | (chbit << BP_APBX_CTRL0_RESET_CHANNEL)) | ||
157 | cpu_relax(); | ||
158 | break; | ||
159 | } | ||
160 | } | ||
161 | EXPORT_SYMBOL(stmp3xxx_arch_dma_reset_channel); | ||
162 | |||
163 | void stmp3xxx_arch_dma_freeze(int channel) | ||
164 | { | ||
165 | unsigned chbit = 1 << STMP3XXX_DMA_CHANNEL(channel); | ||
166 | |||
167 | switch (STMP3XXX_DMA_BUS(channel)) { | ||
168 | case STMP3XXX_BUS_APBH: | ||
169 | stmp3xxx_setl(1 << chbit, REGS_APBH_BASE + HW_APBH_CTRL0); | ||
170 | break; | ||
171 | case STMP3XXX_BUS_APBX: | ||
172 | stmp3xxx_setl(1 << chbit, REGS_APBH_BASE + HW_APBH_CTRL0); | ||
173 | break; | ||
174 | } | ||
175 | } | ||
176 | EXPORT_SYMBOL(stmp3xxx_arch_dma_freeze); | ||
177 | |||
178 | void stmp3xxx_arch_dma_unfreeze(int channel) | ||
179 | { | ||
180 | unsigned chbit = 1 << STMP3XXX_DMA_CHANNEL(channel); | ||
181 | |||
182 | switch (STMP3XXX_DMA_BUS(channel)) { | ||
183 | case STMP3XXX_BUS_APBH: | ||
184 | stmp3xxx_clearl(1 << chbit, REGS_APBH_BASE + HW_APBH_CTRL0); | ||
185 | break; | ||
186 | case STMP3XXX_BUS_APBX: | ||
187 | stmp3xxx_clearl(1 << chbit, REGS_APBH_BASE + HW_APBH_CTRL0); | ||
188 | break; | ||
189 | } | ||
190 | } | ||
191 | EXPORT_SYMBOL(stmp3xxx_arch_dma_unfreeze); | ||
192 | |||
193 | /* | ||
194 | * The registers are all very closely mapped, so we might as well map them all | ||
195 | * with a single mapping | ||
196 | * | ||
197 | * Logical Physical | ||
198 | * f0000000 80000000 On-chip registers | ||
199 | * f1000000 00000000 32k on-chip SRAM | ||
200 | */ | ||
201 | static struct map_desc stmp37xx_io_desc[] __initdata = { | ||
202 | { | ||
203 | .virtual = (u32)STMP3XXX_REGS_BASE, | ||
204 | .pfn = __phys_to_pfn(STMP3XXX_REGS_PHBASE), | ||
205 | .length = SZ_1M, | ||
206 | .type = MT_DEVICE | ||
207 | }, | ||
208 | { | ||
209 | .virtual = (u32)STMP3XXX_OCRAM_BASE, | ||
210 | .pfn = __phys_to_pfn(STMP3XXX_OCRAM_PHBASE), | ||
211 | .length = STMP3XXX_OCRAM_SIZE, | ||
212 | .type = MT_DEVICE, | ||
213 | }, | ||
214 | }; | ||
215 | |||
216 | void __init stmp37xx_map_io(void) | ||
217 | { | ||
218 | iotable_init(stmp37xx_io_desc, ARRAY_SIZE(stmp37xx_io_desc)); | ||
219 | } | ||