1
2
3
4
5
6
7
8
9
10#include <linux/module.h>
11#include <linux/types.h>
12#include <linux/mm.h>
13#include <linux/ioport.h>
14#include <linux/list.h>
15#include <linux/init.h>
16#include <linux/io.h>
17#include <linux/spinlock.h>
18
19#include <asm/pgtable.h>
20#include <asm/page.h>
21#include <asm/irq.h>
22#include <asm/mach-types.h>
23#include <asm/setup.h>
24#include <asm/system_misc.h>
25#include <asm/hardware/dec21285.h>
26
27#include <asm/mach/irq.h>
28#include <asm/mach/map.h>
29#include <asm/mach/pci.h>
30
31#include "common.h"
32
33unsigned int mem_fclk_21285 = 50000000;
34
35EXPORT_SYMBOL(mem_fclk_21285);
36
37static int __init early_fclk(char *arg)
38{
39 mem_fclk_21285 = simple_strtoul(arg, NULL, 0);
40 return 0;
41}
42
43early_param("mem_fclk_21285", early_fclk);
44
45static int __init parse_tag_memclk(const struct tag *tag)
46{
47 mem_fclk_21285 = tag->u.memclk.fmemclk;
48 return 0;
49}
50
51__tagtable(ATAG_MEMCLK, parse_tag_memclk);
52
53
54
55
56
57static const int fb_irq_mask[] = {
58 IRQ_MASK_UART_RX,
59 IRQ_MASK_UART_TX,
60 IRQ_MASK_TIMER1,
61 IRQ_MASK_TIMER2,
62 IRQ_MASK_TIMER3,
63 IRQ_MASK_IN0,
64 IRQ_MASK_IN1,
65 IRQ_MASK_IN2,
66 IRQ_MASK_IN3,
67 IRQ_MASK_DOORBELLHOST,
68 IRQ_MASK_DMA1,
69 IRQ_MASK_DMA2,
70 IRQ_MASK_PCI,
71 IRQ_MASK_SDRAMPARITY,
72 IRQ_MASK_I2OINPOST,
73 IRQ_MASK_PCI_ABORT,
74 IRQ_MASK_PCI_SERR,
75 IRQ_MASK_DISCARD_TIMER,
76 IRQ_MASK_PCI_DPERR,
77 IRQ_MASK_PCI_PERR,
78};
79
80static void fb_mask_irq(struct irq_data *d)
81{
82 *CSR_IRQ_DISABLE = fb_irq_mask[_DC21285_INR(d->irq)];
83}
84
85static void fb_unmask_irq(struct irq_data *d)
86{
87 *CSR_IRQ_ENABLE = fb_irq_mask[_DC21285_INR(d->irq)];
88}
89
90static struct irq_chip fb_chip = {
91 .irq_ack = fb_mask_irq,
92 .irq_mask = fb_mask_irq,
93 .irq_unmask = fb_unmask_irq,
94};
95
96static void __init __fb_init_irq(void)
97{
98 unsigned int irq;
99
100
101
102
103 *CSR_IRQ_DISABLE = -1;
104 *CSR_FIQ_DISABLE = -1;
105
106 for (irq = _DC21285_IRQ(0); irq < _DC21285_IRQ(20); irq++) {
107 irq_set_chip_and_handler(irq, &fb_chip, handle_level_irq);
108 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
109 }
110}
111
112void __init footbridge_init_irq(void)
113{
114 __fb_init_irq();
115
116 if (!footbridge_cfn_mode())
117 return;
118
119 if (machine_is_ebsa285())
120
121
122
123
124
125 isa_init_irq(IRQ_PCI);
126
127 if (machine_is_cats())
128 isa_init_irq(IRQ_IN2);
129
130 if (machine_is_netwinder())
131 isa_init_irq(IRQ_IN3);
132}
133
134
135
136
137
138
139static struct map_desc fb_common_io_desc[] __initdata = {
140 {
141 .virtual = ARMCSR_BASE,
142 .pfn = __phys_to_pfn(DC21285_ARMCSR_BASE),
143 .length = ARMCSR_SIZE,
144 .type = MT_DEVICE,
145 }, {
146 .virtual = XBUS_BASE,
147 .pfn = __phys_to_pfn(0x40000000),
148 .length = XBUS_SIZE,
149 .type = MT_DEVICE,
150 }
151};
152
153
154
155
156
157static struct map_desc ebsa285_host_io_desc[] __initdata = {
158#if defined(CONFIG_ARCH_FOOTBRIDGE) && defined(CONFIG_FOOTBRIDGE_HOST)
159 {
160 .virtual = PCIMEM_BASE,
161 .pfn = __phys_to_pfn(DC21285_PCI_MEM),
162 .length = PCIMEM_SIZE,
163 .type = MT_DEVICE,
164 }, {
165 .virtual = PCICFG0_BASE,
166 .pfn = __phys_to_pfn(DC21285_PCI_TYPE_0_CONFIG),
167 .length = PCICFG0_SIZE,
168 .type = MT_DEVICE,
169 }, {
170 .virtual = PCICFG1_BASE,
171 .pfn = __phys_to_pfn(DC21285_PCI_TYPE_1_CONFIG),
172 .length = PCICFG1_SIZE,
173 .type = MT_DEVICE,
174 }, {
175 .virtual = PCIIACK_BASE,
176 .pfn = __phys_to_pfn(DC21285_PCI_IACK),
177 .length = PCIIACK_SIZE,
178 .type = MT_DEVICE,
179 },
180#endif
181};
182
183void __init footbridge_map_io(void)
184{
185
186
187
188
189 iotable_init(fb_common_io_desc, ARRAY_SIZE(fb_common_io_desc));
190
191
192
193
194
195 if (footbridge_cfn_mode()) {
196 iotable_init(ebsa285_host_io_desc, ARRAY_SIZE(ebsa285_host_io_desc));
197 pci_map_io_early(__phys_to_pfn(DC21285_PCI_IO));
198 }
199}
200
201void footbridge_restart(char mode, const char *cmd)
202{
203 if (mode == 's') {
204
205 soft_restart(0x41000000);
206 } else {
207
208
209
210
211
212
213
214
215
216
217
218 *CSR_SA110_CNTL &= ~(1 << 13);
219 *CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE |
220 TIMER_CNTL_AUTORELOAD |
221 TIMER_CNTL_DIV16;
222 *CSR_TIMER4_LOAD = 0x2;
223 *CSR_TIMER4_CLR = 0;
224 *CSR_SA110_CNTL |= (1 << 13);
225 }
226}
227
228#ifdef CONFIG_FOOTBRIDGE_ADDIN
229
230static inline unsigned long fb_bus_sdram_offset(void)
231{
232 return *CSR_PCISDRAMBASE & 0xfffffff0;
233}
234
235
236
237
238
239
240unsigned long __virt_to_bus(unsigned long res)
241{
242 WARN_ON(res < PAGE_OFFSET || res >= (unsigned long)high_memory);
243
244 return res + (fb_bus_sdram_offset() - PAGE_OFFSET);
245}
246EXPORT_SYMBOL(__virt_to_bus);
247
248unsigned long __bus_to_virt(unsigned long res)
249{
250 res = res - (fb_bus_sdram_offset() - PAGE_OFFSET);
251
252 WARN_ON(res < PAGE_OFFSET || res >= (unsigned long)high_memory);
253
254 return res;
255}
256EXPORT_SYMBOL(__bus_to_virt);
257
258unsigned long __pfn_to_bus(unsigned long pfn)
259{
260 return __pfn_to_phys(pfn) + (fb_bus_sdram_offset() - PHYS_OFFSET);
261}
262EXPORT_SYMBOL(__pfn_to_bus);
263
264unsigned long __bus_to_pfn(unsigned long bus)
265{
266 return __phys_to_pfn(bus - (fb_bus_sdram_offset() - PHYS_OFFSET));
267}
268EXPORT_SYMBOL(__bus_to_pfn);
269
270#endif
271