45d91080 |
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 | |
98f420b2 |
37 | #include <mach/platform.h> |
45d91080 |
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 */ |
98f420b2 |
49 | stmp3xxx_clearl(0x04 << ((irq % 4) * 8), |
50 | REGS_ICOLL_BASE + HW_ICOLL_PRIORITYn + irq / 4 * 0x10); |
45d91080 |
51 | |
52 | /* ACK current interrupt */ |
98f420b2 |
53 | __raw_writel(1, REGS_ICOLL_BASE + HW_ICOLL_LEVELACK); |
45d91080 |
54 | |
55 | /* Barrier */ |
98f420b2 |
56 | (void)__raw_readl(REGS_ICOLL_BASE + HW_ICOLL_STAT); |
45d91080 |
57 | } |
58 | |
59 | static void stmp37xx_mask_irq(unsigned int irq) |
60 | { |
61 | /* IRQ disable */ |
98f420b2 |
62 | stmp3xxx_clearl(0x04 << ((irq % 4) * 8), |
63 | REGS_ICOLL_BASE + HW_ICOLL_PRIORITYn + irq / 4 * 0x10); |
45d91080 |
64 | } |
65 | |
66 | static void stmp37xx_unmask_irq(unsigned int irq) |
67 | { |
68 | /* IRQ enable */ |
98f420b2 |
69 | stmp3xxx_setl(0x04 << ((irq % 4) * 8), |
70 | REGS_ICOLL_BASE + HW_ICOLL_PRIORITYn + irq / 4 * 0x10); |
45d91080 |
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 | { |
98f420b2 |
89 | switch (STMP3XXX_DMA_BUS(channel)) { |
45d91080 |
90 | case STMP3XXX_BUS_APBH: |
98f420b2 |
91 | stmp3xxx_setl(1 << (8 + STMP3XXX_DMA_CHANNEL(channel)), |
92 | REGS_APBH_BASE + HW_APBH_CTRL1); |
45d91080 |
93 | break; |
94 | |
95 | case STMP3XXX_BUS_APBX: |
98f420b2 |
96 | stmp3xxx_setl(1 << (8 + STMP3XXX_DMA_CHANNEL(channel)), |
97 | REGS_APBX_BASE + HW_APBX_CTRL1); |
45d91080 |
98 | break; |
99 | } |
100 | } |
101 | EXPORT_SYMBOL(stmp3xxx_arch_dma_enable_interrupt); |
102 | |
103 | void stmp3xxx_arch_dma_clear_interrupt(int channel) |
104 | { |
98f420b2 |
105 | switch (STMP3XXX_DMA_BUS(channel)) { |
45d91080 |
106 | case STMP3XXX_BUS_APBH: |
98f420b2 |
107 | stmp3xxx_clearl(1 << STMP3XXX_DMA_CHANNEL(channel), |
108 | REGS_APBH_BASE + HW_APBH_CTRL1); |
45d91080 |
109 | break; |
110 | |
111 | case STMP3XXX_BUS_APBX: |
98f420b2 |
112 | stmp3xxx_clearl(1 << STMP3XXX_DMA_CHANNEL(channel), |
113 | REGS_APBX_BASE + HW_APBX_CTRL1); |
45d91080 |
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 | |
98f420b2 |
123 | switch (STMP3XXX_DMA_BUS(channel)) { |
45d91080 |
124 | case STMP3XXX_BUS_APBH: |
98f420b2 |
125 | r = __raw_readl(REGS_APBH_BASE + HW_APBH_CTRL1) & |
126 | (1 << STMP3XXX_DMA_CHANNEL(channel)); |
45d91080 |
127 | break; |
128 | |
129 | case STMP3XXX_BUS_APBX: |
98f420b2 |
130 | r = __raw_readl(REGS_APBH_BASE + HW_APBH_CTRL1) & |
131 | (1 << STMP3XXX_DMA_CHANNEL(channel)); |
45d91080 |
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 | { |
98f420b2 |
140 | unsigned chbit = 1 << STMP3XXX_DMA_CHANNEL(channel); |
45d91080 |
141 | |
98f420b2 |
142 | switch (STMP3XXX_DMA_BUS(channel)) { |
45d91080 |
143 | case STMP3XXX_BUS_APBH: |
144 | /* Reset channel and wait for it to complete */ |
98f420b2 |
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) & |
45d91080 |
148 | (chbit << BP_APBH_CTRL0_RESET_CHANNEL)) |
98f420b2 |
149 | cpu_relax(); |
45d91080 |
150 | break; |
151 | |
152 | case STMP3XXX_BUS_APBX: |
98f420b2 |
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) & |
45d91080 |
156 | (chbit << BP_APBX_CTRL0_RESET_CHANNEL)) |
98f420b2 |
157 | cpu_relax(); |
45d91080 |
158 | break; |
159 | } |
160 | } |
161 | EXPORT_SYMBOL(stmp3xxx_arch_dma_reset_channel); |
162 | |
163 | void stmp3xxx_arch_dma_freeze(int channel) |
164 | { |
98f420b2 |
165 | unsigned chbit = 1 << STMP3XXX_DMA_CHANNEL(channel); |
45d91080 |
166 | |
98f420b2 |
167 | switch (STMP3XXX_DMA_BUS(channel)) { |
45d91080 |
168 | case STMP3XXX_BUS_APBH: |
98f420b2 |
169 | stmp3xxx_setl(1 << chbit, REGS_APBH_BASE + HW_APBH_CTRL0); |
45d91080 |
170 | break; |
171 | case STMP3XXX_BUS_APBX: |
98f420b2 |
172 | stmp3xxx_setl(1 << chbit, REGS_APBH_BASE + HW_APBH_CTRL0); |
45d91080 |
173 | break; |
174 | } |
175 | } |
176 | EXPORT_SYMBOL(stmp3xxx_arch_dma_freeze); |
177 | |
178 | void stmp3xxx_arch_dma_unfreeze(int channel) |
179 | { |
98f420b2 |
180 | unsigned chbit = 1 << STMP3XXX_DMA_CHANNEL(channel); |
45d91080 |
181 | |
98f420b2 |
182 | switch (STMP3XXX_DMA_BUS(channel)) { |
45d91080 |
183 | case STMP3XXX_BUS_APBH: |
98f420b2 |
184 | stmp3xxx_clearl(1 << chbit, REGS_APBH_BASE + HW_APBH_CTRL0); |
45d91080 |
185 | break; |
186 | case STMP3XXX_BUS_APBX: |
98f420b2 |
187 | stmp3xxx_clearl(1 << chbit, REGS_APBH_BASE + HW_APBH_CTRL0); |
45d91080 |
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 |
98f420b2 |
199 | * f1000000 00000000 32k on-chip SRAM |
45d91080 |
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 | } |