Blame view

arch/arm/mach-integrator/integrator_ap.c 11.7 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  /*
   *  linux/arch/arm/mach-integrator/integrator_ap.c
   *
   *  Copyright (C) 2000-2003 Deep Blue Solutions Ltd
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   */
  #include <linux/types.h>
  #include <linux/kernel.h>
  #include <linux/init.h>
  #include <linux/list.h>
d052d1bef   Russell King   Create platform_d...
24
  #include <linux/platform_device.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
26
  #include <linux/slab.h>
  #include <linux/string.h>
b78080561   Rafael J. Wysocki   ARM / Integrator:...
27
  #include <linux/syscore_ops.h>
a62c80e55   Russell King   [ARM] Move AMBA i...
28
29
  #include <linux/amba/bus.h>
  #include <linux/amba/kmi.h>
6be4826e3   Russell King   ARM: Integrator: ...
30
31
32
  #include <linux/clocksource.h>
  #include <linux/clockchips.h>
  #include <linux/interrupt.h>
fced80c73   Russell King   [ARM] Convert asm...
33
  #include <linux/io.h>
f07e762e4   Marc Zyngier   ARM: 6908/1: Inte...
34
  #include <linux/mtd/physmap.h>
bb76079a7   Linus Walleij   ARM: 7087/2: mach...
35
  #include <linux/clk.h>
b71d8429e   Linus Walleij   mach-integrator: ...
36
  #include <video/vga.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37

a09e64fbc   Russell King   [ARM] Move includ...
38
  #include <mach/hardware.h>
a285edcf1   Russell King   ARM: Fix Versatil...
39
  #include <mach/platform.h>
6be4826e3   Russell King   ARM: Integrator: ...
40
  #include <asm/hardware/arm_timer.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
  #include <asm/irq.h>
  #include <asm/setup.h>
4e57b6817   Tim Schmielau   [PATCH] fix missi...
43
  #include <asm/param.h>		/* HZ */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
  #include <asm/mach-types.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45

a09e64fbc   Russell King   [ARM] Move includ...
46
  #include <mach/lm.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
48
  
  #include <asm/mach/arch.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
51
  #include <asm/mach/irq.h>
  #include <asm/mach/map.h>
  #include <asm/mach/time.h>
c41b16f8c   Russell King   ARM: integrator/v...
52
  #include <plat/fpga-irq.h>
98c672cf1   Russell King   ARM: Move platfor...
53
  #include "common.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
56
57
58
59
60
  /* 
   * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx
   * is the (PA >> 12).
   *
   * Setup a VA for the Integrator interrupt controller (for header #0,
   * just for now).
   */
c41b16f8c   Russell King   ARM: integrator/v...
61
62
63
64
  #define VA_IC_BASE	__io_address(INTEGRATOR_IC_BASE)
  #define VA_SC_BASE	__io_address(INTEGRATOR_SC_BASE)
  #define VA_EBI_BASE	__io_address(INTEGRATOR_EBI_BASE)
  #define VA_CMIC_BASE	__io_address(INTEGRATOR_HDR_IC)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
  
  /*
   * Logical      Physical
   * e8000000	40000000	PCI memory		PHYS_PCI_MEM_BASE	(max 512M)
   * ec000000	61000000	PCI config space	PHYS_PCI_CONFIG_BASE	(max 16M)
   * ed000000	62000000	PCI V3 regs		PHYS_PCI_V3_BASE	(max 64k)
   * ee000000	60000000	PCI IO			PHYS_PCI_IO_BASE	(max 16M)
   * ef000000			Cache flush
   * f1000000	10000000	Core module registers
   * f1100000	11000000	System controller registers
   * f1200000	12000000	EBI registers
   * f1300000	13000000	Counter/Timer
   * f1400000	14000000	Interrupt controller
   * f1600000	16000000	UART 0
   * f1700000	17000000	UART 1
   * f1a00000	1a000000	Debug LEDs
   * f1b00000	1b000000	GPIO
   */
  
  static struct map_desc ap_io_desc[] __initdata = {
c8d272985   Deepak Saxena   [ARM] 3001/1: Rep...
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
  	{
  		.virtual	= IO_ADDRESS(INTEGRATOR_HDR_BASE),
  		.pfn		= __phys_to_pfn(INTEGRATOR_HDR_BASE),
  		.length		= SZ_4K,
  		.type		= MT_DEVICE
  	}, {
  		.virtual	= IO_ADDRESS(INTEGRATOR_SC_BASE),
  		.pfn		= __phys_to_pfn(INTEGRATOR_SC_BASE),
  		.length		= SZ_4K,
  		.type		= MT_DEVICE
  	}, {
  		.virtual	= IO_ADDRESS(INTEGRATOR_EBI_BASE),
  		.pfn		= __phys_to_pfn(INTEGRATOR_EBI_BASE),
  		.length		= SZ_4K,
  		.type		= MT_DEVICE
  	}, {
  		.virtual	= IO_ADDRESS(INTEGRATOR_CT_BASE),
  		.pfn		= __phys_to_pfn(INTEGRATOR_CT_BASE),
  		.length		= SZ_4K,
  		.type		= MT_DEVICE
  	}, {
  		.virtual	= IO_ADDRESS(INTEGRATOR_IC_BASE),
  		.pfn		= __phys_to_pfn(INTEGRATOR_IC_BASE),
  		.length		= SZ_4K,
  		.type		= MT_DEVICE
  	}, {
  		.virtual	= IO_ADDRESS(INTEGRATOR_UART0_BASE),
  		.pfn		= __phys_to_pfn(INTEGRATOR_UART0_BASE),
  		.length		= SZ_4K,
  		.type		= MT_DEVICE
  	}, {
  		.virtual	= IO_ADDRESS(INTEGRATOR_UART1_BASE),
  		.pfn		= __phys_to_pfn(INTEGRATOR_UART1_BASE),
  		.length		= SZ_4K,
  		.type		= MT_DEVICE
  	}, {
  		.virtual	= IO_ADDRESS(INTEGRATOR_DBG_BASE),
  		.pfn		= __phys_to_pfn(INTEGRATOR_DBG_BASE),
  		.length		= SZ_4K,
  		.type		= MT_DEVICE
  	}, {
da7ba956c   Russell King   ARM: Integrator: ...
126
127
  		.virtual	= IO_ADDRESS(INTEGRATOR_AP_GPIO_BASE),
  		.pfn		= __phys_to_pfn(INTEGRATOR_AP_GPIO_BASE),
c8d272985   Deepak Saxena   [ARM] 3001/1: Rep...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
  		.length		= SZ_4K,
  		.type		= MT_DEVICE
  	}, {
  		.virtual	= PCI_MEMORY_VADDR,
  		.pfn		= __phys_to_pfn(PHYS_PCI_MEM_BASE),
  		.length		= SZ_16M,
  		.type		= MT_DEVICE
  	}, {
  		.virtual	= PCI_CONFIG_VADDR,
  		.pfn		= __phys_to_pfn(PHYS_PCI_CONFIG_BASE),
  		.length		= SZ_16M,
  		.type		= MT_DEVICE
  	}, {
  		.virtual	= PCI_V3_VADDR,
  		.pfn		= __phys_to_pfn(PHYS_PCI_V3_BASE),
  		.length		= SZ_64K,
  		.type		= MT_DEVICE
  	}, {
  		.virtual	= PCI_IO_VADDR,
  		.pfn		= __phys_to_pfn(PHYS_PCI_IO_BASE),
  		.length		= SZ_64K,
  		.type		= MT_DEVICE
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
152
153
154
155
  };
  
  static void __init ap_map_io(void)
  {
  	iotable_init(ap_io_desc, ARRAY_SIZE(ap_io_desc));
b71d8429e   Linus Walleij   mach-integrator: ...
156
  	vga_base = PCI_MEMORY_VADDR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157
158
159
  }
  
  #define INTEGRATOR_SC_VALID_INT	0x003fffff
c41b16f8c   Russell King   ARM: integrator/v...
160
161
162
163
  static struct fpga_irq_data sc_irq_data = {
  	.base		= VA_IC_BASE,
  	.irq_start	= 0,
  	.chip.name	= "SC",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
166
167
  };
  
  static void __init ap_init_irq(void)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
169
170
171
172
173
174
  	/* Disable all interrupts initially. */
  	/* Do the core module ones */
  	writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
  
  	/* do the header card stuff next */
  	writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
  	writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
c41b16f8c   Russell King   ARM: integrator/v...
175
  	fpga_irq_init(-1, INTEGRATOR_SC_VALID_INT, &sc_irq_data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
177
178
179
  }
  
  #ifdef CONFIG_PM
  static unsigned long ic_irq_enable;
b78080561   Rafael J. Wysocki   ARM / Integrator:...
180
  static int irq_suspend(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
182
183
184
  {
  	ic_irq_enable = readl(VA_IC_BASE + IRQ_ENABLE);
  	return 0;
  }
b78080561   Rafael J. Wysocki   ARM / Integrator:...
185
  static void irq_resume(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
187
188
189
190
191
192
  {
  	/* disable all irq sources */
  	writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
  	writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
  	writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
  
  	writel(ic_irq_enable, VA_IC_BASE + IRQ_ENABLE_SET);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
194
195
196
197
  }
  #else
  #define irq_suspend NULL
  #define irq_resume NULL
  #endif
b78080561   Rafael J. Wysocki   ARM / Integrator:...
198
  static struct syscore_ops irq_syscore_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
201
  	.suspend	= irq_suspend,
  	.resume		= irq_resume,
  };
b78080561   Rafael J. Wysocki   ARM / Integrator:...
202
  static int __init irq_syscore_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203
  {
b78080561   Rafael J. Wysocki   ARM / Integrator:...
204
205
206
  	register_syscore_ops(&irq_syscore_ops);
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
  }
b78080561   Rafael J. Wysocki   ARM / Integrator:...
208
  device_initcall(irq_syscore_init);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
210
211
212
213
214
215
216
  
  /*
   * Flash handling.
   */
  #define SC_CTRLC (VA_SC_BASE + INTEGRATOR_SC_CTRLC_OFFSET)
  #define SC_CTRLS (VA_SC_BASE + INTEGRATOR_SC_CTRLS_OFFSET)
  #define EBI_CSR1 (VA_EBI_BASE + INTEGRATOR_EBI_CSR1_OFFSET)
  #define EBI_LOCK (VA_EBI_BASE + INTEGRATOR_EBI_LOCK_OFFSET)
f07e762e4   Marc Zyngier   ARM: 6908/1: Inte...
217
  static int ap_flash_init(struct platform_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
  {
  	u32 tmp;
  
  	writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC);
  
  	tmp = readl(EBI_CSR1) | INTEGRATOR_EBI_WRITE_ENABLE;
  	writel(tmp, EBI_CSR1);
  
  	if (!(readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE)) {
  		writel(0xa05f, EBI_LOCK);
  		writel(tmp, EBI_CSR1);
  		writel(0, EBI_LOCK);
  	}
  	return 0;
  }
f07e762e4   Marc Zyngier   ARM: 6908/1: Inte...
233
  static void ap_flash_exit(struct platform_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
235
236
237
238
239
240
241
242
243
244
245
246
247
  {
  	u32 tmp;
  
  	writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC);
  
  	tmp = readl(EBI_CSR1) & ~INTEGRATOR_EBI_WRITE_ENABLE;
  	writel(tmp, EBI_CSR1);
  
  	if (readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE) {
  		writel(0xa05f, EBI_LOCK);
  		writel(tmp, EBI_CSR1);
  		writel(0, EBI_LOCK);
  	}
  }
667f390be   Marc Zyngier   ARM: 6910/1: MTD:...
248
  static void ap_flash_set_vpp(struct platform_device *pdev, int on)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
  {
c41b16f8c   Russell King   ARM: integrator/v...
250
  	void __iomem *reg = on ? SC_CTRLS : SC_CTRLC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251
252
253
  
  	writel(INTEGRATOR_SC_CTRL_nFLVPPEN, reg);
  }
f07e762e4   Marc Zyngier   ARM: 6908/1: Inte...
254
  static struct physmap_flash_data ap_flash_data = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
256
257
258
259
260
261
262
263
264
265
266
267
  	.width		= 4,
  	.init		= ap_flash_init,
  	.exit		= ap_flash_exit,
  	.set_vpp	= ap_flash_set_vpp,
  };
  
  static struct resource cfi_flash_resource = {
  	.start		= INTEGRATOR_FLASH_BASE,
  	.end		= INTEGRATOR_FLASH_BASE + INTEGRATOR_FLASH_SIZE - 1,
  	.flags		= IORESOURCE_MEM,
  };
  
  static struct platform_device cfi_flash_device = {
f07e762e4   Marc Zyngier   ARM: 6908/1: Inte...
268
  	.name		= "physmap-flash",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
  	.id		= 0,
  	.dev		= {
  		.platform_data	= &ap_flash_data,
  	},
  	.num_resources	= 1,
  	.resource	= &cfi_flash_resource,
  };
  
  static void __init ap_init(void)
  {
  	unsigned long sc_dec;
  	int i;
  
  	platform_device_register(&cfi_flash_device);
  
  	sc_dec = readl(VA_SC_BASE + INTEGRATOR_SC_DEC_OFFSET);
  	for (i = 0; i < 4; i++) {
  		struct lm_device *lmdev;
  
  		if ((sc_dec & (16 << i)) == 0)
  			continue;
d2a02b93c   Russell King   [ARM] Convert kma...
290
  		lmdev = kzalloc(sizeof(struct lm_device), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291
292
  		if (!lmdev)
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
294
295
296
297
298
299
300
301
  		lmdev->resource.start = 0xc0000000 + 0x10000000 * i;
  		lmdev->resource.end = lmdev->resource.start + 0x0fffffff;
  		lmdev->resource.flags = IORESOURCE_MEM;
  		lmdev->irq = IRQ_AP_EXPINT0 + i;
  		lmdev->id = i;
  
  		lm_device_register(lmdev);
  	}
  }
6be4826e3   Russell King   ARM: Integrator: ...
302
303
304
305
306
307
  /*
   * Where is the timer (VA)?
   */
  #define TIMER0_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER0_BASE)
  #define TIMER1_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER1_BASE)
  #define TIMER2_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER2_BASE)
6be4826e3   Russell King   ARM: Integrator: ...
308
  static unsigned long timer_reload;
bb76079a7   Linus Walleij   ARM: 7087/2: mach...
309
  static void integrator_clocksource_init(unsigned long inrate)
6be4826e3   Russell King   ARM: Integrator: ...
310
  {
c5039f523   Russell King   clocksource: conv...
311
  	void __iomem *base = (void __iomem *)TIMER2_VA_BASE;
bb9ea7784   Linus Walleij   ARM: 7081/1: mach...
312
  	u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC;
bb76079a7   Linus Walleij   ARM: 7087/2: mach...
313
  	unsigned long rate = inrate;
6be4826e3   Russell King   ARM: Integrator: ...
314

bb76079a7   Linus Walleij   ARM: 7087/2: mach...
315
316
  	if (rate >= 1500000) {
  		rate /= 16;
bb9ea7784   Linus Walleij   ARM: 7081/1: mach...
317
  		ctrl |= TIMER_CTRL_DIV16;
6be4826e3   Russell King   ARM: Integrator: ...
318
  	}
6be4826e3   Russell King   ARM: Integrator: ...
319
  	writel(0xffff, base + TIMER_LOAD);
bb9ea7784   Linus Walleij   ARM: 7081/1: mach...
320
  	writel(ctrl, base + TIMER_CTRL);
6be4826e3   Russell King   ARM: Integrator: ...
321

c5039f523   Russell King   clocksource: conv...
322
  	clocksource_mmio_init(base + TIMER_VALUE, "timer2",
bb76079a7   Linus Walleij   ARM: 7087/2: mach...
323
  			rate, 200, 16, clocksource_mmio_readl_down);
6be4826e3   Russell King   ARM: Integrator: ...
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
  }
  
  static void __iomem * const clkevt_base = (void __iomem *)TIMER1_VA_BASE;
  
  /*
   * IRQ handler for the timer
   */
  static irqreturn_t integrator_timer_interrupt(int irq, void *dev_id)
  {
  	struct clock_event_device *evt = dev_id;
  
  	/* clear the interrupt */
  	writel(1, clkevt_base + TIMER_INTCLR);
  
  	evt->event_handler(evt);
  
  	return IRQ_HANDLED;
  }
  
  static void clkevt_set_mode(enum clock_event_mode mode, struct clock_event_device *evt)
  {
  	u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE;
02f563212   Linus Walleij   ARM: 7085/2: mach...
346
347
  	/* Disable timer */
  	writel(ctrl, clkevt_base + TIMER_CTRL);
6be4826e3   Russell King   ARM: Integrator: ...
348

02f563212   Linus Walleij   ARM: 7085/2: mach...
349
350
351
  	switch (mode) {
  	case CLOCK_EVT_MODE_PERIODIC:
  		/* Enable the timer and start the periodic tick */
6be4826e3   Russell King   ARM: Integrator: ...
352
353
  		writel(timer_reload, clkevt_base + TIMER_LOAD);
  		ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
02f563212   Linus Walleij   ARM: 7085/2: mach...
354
355
356
357
358
359
360
361
362
363
364
365
366
  		writel(ctrl, clkevt_base + TIMER_CTRL);
  		break;
  	case CLOCK_EVT_MODE_ONESHOT:
  		/* Leave the timer disabled, .set_next_event will enable it */
  		ctrl &= ~TIMER_CTRL_PERIODIC;
  		writel(ctrl, clkevt_base + TIMER_CTRL);
  		break;
  	case CLOCK_EVT_MODE_UNUSED:
  	case CLOCK_EVT_MODE_SHUTDOWN:
  	case CLOCK_EVT_MODE_RESUME:
  	default:
  		/* Just leave in disabled state */
  		break;
6be4826e3   Russell King   ARM: Integrator: ...
367
  	}
6be4826e3   Russell King   ARM: Integrator: ...
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
  }
  
  static int clkevt_set_next_event(unsigned long next, struct clock_event_device *evt)
  {
  	unsigned long ctrl = readl(clkevt_base + TIMER_CTRL);
  
  	writel(ctrl & ~TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
  	writel(next, clkevt_base + TIMER_LOAD);
  	writel(ctrl | TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
  
  	return 0;
  }
  
  static struct clock_event_device integrator_clockevent = {
  	.name		= "timer1",
02f563212   Linus Walleij   ARM: 7085/2: mach...
383
  	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
6be4826e3   Russell King   ARM: Integrator: ...
384
385
386
  	.set_mode	= clkevt_set_mode,
  	.set_next_event	= clkevt_set_next_event,
  	.rating		= 300,
6be4826e3   Russell King   ARM: Integrator: ...
387
388
389
390
391
392
393
394
  };
  
  static struct irqaction integrator_timer_irq = {
  	.name		= "timer",
  	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
  	.handler	= integrator_timer_interrupt,
  	.dev_id		= &integrator_clockevent,
  };
bb76079a7   Linus Walleij   ARM: 7087/2: mach...
395
  static void integrator_clockevent_init(unsigned long inrate)
6be4826e3   Russell King   ARM: Integrator: ...
396
  {
bb76079a7   Linus Walleij   ARM: 7087/2: mach...
397
  	unsigned long rate = inrate;
6be4826e3   Russell King   ARM: Integrator: ...
398
  	unsigned int ctrl = 0;
6d8ce7129   Linus Walleij   ARM: 7086/2: mach...
399
  	/* Calculate and program a divisor */
bb76079a7   Linus Walleij   ARM: 7087/2: mach...
400
401
  	if (rate > 0x100000 * HZ) {
  		rate /= 256;
6be4826e3   Russell King   ARM: Integrator: ...
402
  		ctrl |= TIMER_CTRL_DIV256;
bb76079a7   Linus Walleij   ARM: 7087/2: mach...
403
404
  	} else if (rate > 0x10000 * HZ) {
  		rate /= 16;
6be4826e3   Russell King   ARM: Integrator: ...
405
406
  		ctrl |= TIMER_CTRL_DIV16;
  	}
bb76079a7   Linus Walleij   ARM: 7087/2: mach...
407
  	timer_reload = rate / HZ;
6be4826e3   Russell King   ARM: Integrator: ...
408
  	writel(ctrl, clkevt_base + TIMER_CTRL);
6be4826e3   Russell King   ARM: Integrator: ...
409
  	setup_irq(IRQ_TIMERINT1, &integrator_timer_irq);
6d8ce7129   Linus Walleij   ARM: 7086/2: mach...
410
  	clockevents_config_and_register(&integrator_clockevent,
bb76079a7   Linus Walleij   ARM: 7087/2: mach...
411
  					rate,
6d8ce7129   Linus Walleij   ARM: 7086/2: mach...
412
413
  					1,
  					0xffffU);
6be4826e3   Russell King   ARM: Integrator: ...
414
415
416
417
418
  }
  
  /*
   * Set up timer(s).
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
420
  static void __init ap_init_timer(void)
  {
bb76079a7   Linus Walleij   ARM: 7087/2: mach...
421
422
423
424
425
426
427
  	struct clk *clk;
  	unsigned long rate;
  
  	clk = clk_get_sys("ap_timer", NULL);
  	BUG_ON(IS_ERR(clk));
  	clk_enable(clk);
  	rate = clk_get_rate(clk);
6be4826e3   Russell King   ARM: Integrator: ...
428
429
430
431
  
  	writel(0, TIMER0_VA_BASE + TIMER_CTRL);
  	writel(0, TIMER1_VA_BASE + TIMER_CTRL);
  	writel(0, TIMER2_VA_BASE + TIMER_CTRL);
bb76079a7   Linus Walleij   ARM: 7087/2: mach...
432
433
  	integrator_clocksource_init(rate);
  	integrator_clockevent_init(rate);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434
435
436
437
  }
  
  static struct sys_timer ap_timer = {
  	.init		= ap_init_timer,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
439
440
  };
  
  MACHINE_START(INTEGRATOR, "ARM-Integrator")
e9dea0c65   Russell King   [PATCH] ARM: Remo...
441
  	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
c5e587a2b   Nicolas Pitre   ARM: mach-integra...
442
  	.atag_offset	= 0x100,
98c672cf1   Russell King   ARM: Move platfor...
443
  	.reserve	= integrator_reserve,
c735c9873   Russell King   ARM: integrator: ...
444
445
  	.map_io		= ap_map_io,
  	.init_early	= integrator_init_early,
e9dea0c65   Russell King   [PATCH] ARM: Remo...
446
  	.init_irq	= ap_init_irq,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
447
  	.timer		= &ap_timer,
e9dea0c65   Russell King   [PATCH] ARM: Remo...
448
  	.init_machine	= ap_init,
6338b66f8   Russell King   ARM: restart: int...
449
  	.restart	= integrator_restart,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450
  MACHINE_END