Use extended crashkernel command line on sh
[linux-2.6] / arch / arm / mach-realview / core.c
1 /*
2  *  linux/arch/arm/mach-realview/core.c
3  *
4  *  Copyright (C) 1999 - 2003 ARM Limited
5  *  Copyright (C) 2000 Deep Blue Solutions Ltd
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21 #include <linux/init.h>
22 #include <linux/platform_device.h>
23 #include <linux/dma-mapping.h>
24 #include <linux/sysdev.h>
25 #include <linux/interrupt.h>
26 #include <linux/amba/bus.h>
27 #include <linux/amba/clcd.h>
28
29 #include <asm/system.h>
30 #include <asm/hardware.h>
31 #include <asm/io.h>
32 #include <asm/irq.h>
33 #include <asm/leds.h>
34 #include <asm/hardware/arm_timer.h>
35 #include <asm/hardware/icst307.h>
36
37 #include <asm/mach/arch.h>
38 #include <asm/mach/flash.h>
39 #include <asm/mach/irq.h>
40 #include <asm/mach/time.h>
41 #include <asm/mach/map.h>
42 #include <asm/mach/mmc.h>
43
44 #include <asm/hardware/gic.h>
45
46 #include "core.h"
47 #include "clock.h"
48
49 #define REALVIEW_REFCOUNTER     (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_24MHz_OFFSET)
50
51 /*
52  * This is the RealView sched_clock implementation.  This has
53  * a resolution of 41.7ns, and a maximum value of about 179s.
54  */
55 unsigned long long sched_clock(void)
56 {
57         unsigned long long v;
58
59         v = (unsigned long long)readl(REALVIEW_REFCOUNTER) * 125;
60         do_div(v, 3);
61
62         return v;
63 }
64
65
66 #define REALVIEW_FLASHCTRL    (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_FLASH_OFFSET)
67
68 static int realview_flash_init(void)
69 {
70         u32 val;
71
72         val = __raw_readl(REALVIEW_FLASHCTRL);
73         val &= ~REALVIEW_FLASHPROG_FLVPPEN;
74         __raw_writel(val, REALVIEW_FLASHCTRL);
75
76         return 0;
77 }
78
79 static void realview_flash_exit(void)
80 {
81         u32 val;
82
83         val = __raw_readl(REALVIEW_FLASHCTRL);
84         val &= ~REALVIEW_FLASHPROG_FLVPPEN;
85         __raw_writel(val, REALVIEW_FLASHCTRL);
86 }
87
88 static void realview_flash_set_vpp(int on)
89 {
90         u32 val;
91
92         val = __raw_readl(REALVIEW_FLASHCTRL);
93         if (on)
94                 val |= REALVIEW_FLASHPROG_FLVPPEN;
95         else
96                 val &= ~REALVIEW_FLASHPROG_FLVPPEN;
97         __raw_writel(val, REALVIEW_FLASHCTRL);
98 }
99
100 static struct flash_platform_data realview_flash_data = {
101         .map_name               = "cfi_probe",
102         .width                  = 4,
103         .init                   = realview_flash_init,
104         .exit                   = realview_flash_exit,
105         .set_vpp                = realview_flash_set_vpp,
106 };
107
108 static struct resource realview_flash_resource = {
109         .start                  = REALVIEW_FLASH_BASE,
110         .end                    = REALVIEW_FLASH_BASE + REALVIEW_FLASH_SIZE,
111         .flags                  = IORESOURCE_MEM,
112 };
113
114 struct platform_device realview_flash_device = {
115         .name                   = "armflash",
116         .id                     = 0,
117         .dev                    = {
118                 .platform_data  = &realview_flash_data,
119         },
120         .num_resources          = 1,
121         .resource               = &realview_flash_resource,
122 };
123
124 static struct resource realview_smc91x_resources[] = {
125         [0] = {
126                 .start          = REALVIEW_ETH_BASE,
127                 .end            = REALVIEW_ETH_BASE + SZ_64K - 1,
128                 .flags          = IORESOURCE_MEM,
129         },
130         [1] = {
131                 .start          = IRQ_ETH,
132                 .end            = IRQ_ETH,
133                 .flags          = IORESOURCE_IRQ,
134         },
135 };
136
137 struct platform_device realview_smc91x_device = {
138         .name           = "smc91x",
139         .id             = 0,
140         .num_resources  = ARRAY_SIZE(realview_smc91x_resources),
141         .resource       = realview_smc91x_resources,
142 };
143
144 static struct resource realview_i2c_resource = {
145         .start          = REALVIEW_I2C_BASE,
146         .end            = REALVIEW_I2C_BASE + SZ_4K - 1,
147         .flags          = IORESOURCE_MEM,
148 };
149
150 struct platform_device realview_i2c_device = {
151         .name           = "versatile-i2c",
152         .id             = -1,
153         .num_resources  = 1,
154         .resource       = &realview_i2c_resource,
155 };
156
157 #define REALVIEW_SYSMCI (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_MCI_OFFSET)
158
159 static unsigned int realview_mmc_status(struct device *dev)
160 {
161         struct amba_device *adev = container_of(dev, struct amba_device, dev);
162         u32 mask;
163
164         if (adev->res.start == REALVIEW_MMCI0_BASE)
165                 mask = 1;
166         else
167                 mask = 2;
168
169         return readl(REALVIEW_SYSMCI) & mask;
170 }
171
172 struct mmc_platform_data realview_mmc0_plat_data = {
173         .ocr_mask       = MMC_VDD_32_33|MMC_VDD_33_34,
174         .status         = realview_mmc_status,
175 };
176
177 struct mmc_platform_data realview_mmc1_plat_data = {
178         .ocr_mask       = MMC_VDD_32_33|MMC_VDD_33_34,
179         .status         = realview_mmc_status,
180 };
181
182 /*
183  * Clock handling
184  */
185 static const struct icst307_params realview_oscvco_params = {
186         .ref            = 24000,
187         .vco_max        = 200000,
188         .vd_min         = 4 + 8,
189         .vd_max         = 511 + 8,
190         .rd_min         = 1 + 2,
191         .rd_max         = 127 + 2,
192 };
193
194 static void realview_oscvco_set(struct clk *clk, struct icst307_vco vco)
195 {
196         void __iomem *sys_lock = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_LOCK_OFFSET;
197         void __iomem *sys_osc = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_OSC4_OFFSET;
198         u32 val;
199
200         val = readl(sys_osc) & ~0x7ffff;
201         val |= vco.v | (vco.r << 9) | (vco.s << 16);
202
203         writel(0xa05f, sys_lock);
204         writel(val, sys_osc);
205         writel(0, sys_lock);
206 }
207
208 struct clk realview_clcd_clk = {
209         .name   = "CLCDCLK",
210         .params = &realview_oscvco_params,
211         .setvco = realview_oscvco_set,
212 };
213
214 /*
215  * CLCD support.
216  */
217 #define SYS_CLCD_NLCDIOON       (1 << 2)
218 #define SYS_CLCD_VDDPOSSWITCH   (1 << 3)
219 #define SYS_CLCD_PWR3V5SWITCH   (1 << 4)
220 #define SYS_CLCD_ID_MASK        (0x1f << 8)
221 #define SYS_CLCD_ID_SANYO_3_8   (0x00 << 8)
222 #define SYS_CLCD_ID_UNKNOWN_8_4 (0x01 << 8)
223 #define SYS_CLCD_ID_EPSON_2_2   (0x02 << 8)
224 #define SYS_CLCD_ID_SANYO_2_5   (0x07 << 8)
225 #define SYS_CLCD_ID_VGA         (0x1f << 8)
226
227 static struct clcd_panel vga = {
228         .mode           = {
229                 .name           = "VGA",
230                 .refresh        = 60,
231                 .xres           = 640,
232                 .yres           = 480,
233                 .pixclock       = 39721,
234                 .left_margin    = 40,
235                 .right_margin   = 24,
236                 .upper_margin   = 32,
237                 .lower_margin   = 11,
238                 .hsync_len      = 96,
239                 .vsync_len      = 2,
240                 .sync           = 0,
241                 .vmode          = FB_VMODE_NONINTERLACED,
242         },
243         .width          = -1,
244         .height         = -1,
245         .tim2           = TIM2_BCD | TIM2_IPC,
246         .cntl           = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
247         .bpp            = 16,
248 };
249
250 static struct clcd_panel sanyo_3_8_in = {
251         .mode           = {
252                 .name           = "Sanyo QVGA",
253                 .refresh        = 116,
254                 .xres           = 320,
255                 .yres           = 240,
256                 .pixclock       = 100000,
257                 .left_margin    = 6,
258                 .right_margin   = 6,
259                 .upper_margin   = 5,
260                 .lower_margin   = 5,
261                 .hsync_len      = 6,
262                 .vsync_len      = 6,
263                 .sync           = 0,
264                 .vmode          = FB_VMODE_NONINTERLACED,
265         },
266         .width          = -1,
267         .height         = -1,
268         .tim2           = TIM2_BCD,
269         .cntl           = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
270         .bpp            = 16,
271 };
272
273 static struct clcd_panel sanyo_2_5_in = {
274         .mode           = {
275                 .name           = "Sanyo QVGA Portrait",
276                 .refresh        = 116,
277                 .xres           = 240,
278                 .yres           = 320,
279                 .pixclock       = 100000,
280                 .left_margin    = 20,
281                 .right_margin   = 10,
282                 .upper_margin   = 2,
283                 .lower_margin   = 2,
284                 .hsync_len      = 10,
285                 .vsync_len      = 2,
286                 .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
287                 .vmode          = FB_VMODE_NONINTERLACED,
288         },
289         .width          = -1,
290         .height         = -1,
291         .tim2           = TIM2_IVS | TIM2_IHS | TIM2_IPC,
292         .cntl           = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
293         .bpp            = 16,
294 };
295
296 static struct clcd_panel epson_2_2_in = {
297         .mode           = {
298                 .name           = "Epson QCIF",
299                 .refresh        = 390,
300                 .xres           = 176,
301                 .yres           = 220,
302                 .pixclock       = 62500,
303                 .left_margin    = 3,
304                 .right_margin   = 2,
305                 .upper_margin   = 1,
306                 .lower_margin   = 0,
307                 .hsync_len      = 3,
308                 .vsync_len      = 2,
309                 .sync           = 0,
310                 .vmode          = FB_VMODE_NONINTERLACED,
311         },
312         .width          = -1,
313         .height         = -1,
314         .tim2           = TIM2_BCD | TIM2_IPC,
315         .cntl           = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
316         .bpp            = 16,
317 };
318
319 /*
320  * Detect which LCD panel is connected, and return the appropriate
321  * clcd_panel structure.  Note: we do not have any information on
322  * the required timings for the 8.4in panel, so we presently assume
323  * VGA timings.
324  */
325 static struct clcd_panel *realview_clcd_panel(void)
326 {
327         void __iomem *sys_clcd = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_CLCD_OFFSET;
328         struct clcd_panel *panel = &vga;
329         u32 val;
330
331         val = readl(sys_clcd) & SYS_CLCD_ID_MASK;
332         if (val == SYS_CLCD_ID_SANYO_3_8)
333                 panel = &sanyo_3_8_in;
334         else if (val == SYS_CLCD_ID_SANYO_2_5)
335                 panel = &sanyo_2_5_in;
336         else if (val == SYS_CLCD_ID_EPSON_2_2)
337                 panel = &epson_2_2_in;
338         else if (val == SYS_CLCD_ID_VGA)
339                 panel = &vga;
340         else {
341                 printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n",
342                         val);
343                 panel = &vga;
344         }
345
346         return panel;
347 }
348
349 /*
350  * Disable all display connectors on the interface module.
351  */
352 static void realview_clcd_disable(struct clcd_fb *fb)
353 {
354         void __iomem *sys_clcd = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_CLCD_OFFSET;
355         u32 val;
356
357         val = readl(sys_clcd);
358         val &= ~SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH;
359         writel(val, sys_clcd);
360 }
361
362 /*
363  * Enable the relevant connector on the interface module.
364  */
365 static void realview_clcd_enable(struct clcd_fb *fb)
366 {
367         void __iomem *sys_clcd = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_CLCD_OFFSET;
368         u32 val;
369
370         /*
371          * Enable the PSUs
372          */
373         val = readl(sys_clcd);
374         val |= SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH;
375         writel(val, sys_clcd);
376 }
377
378 static unsigned long framesize = SZ_1M;
379
380 static int realview_clcd_setup(struct clcd_fb *fb)
381 {
382         dma_addr_t dma;
383
384         fb->panel               = realview_clcd_panel();
385
386         fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
387                                                     &dma, GFP_KERNEL);
388         if (!fb->fb.screen_base) {
389                 printk(KERN_ERR "CLCD: unable to map framebuffer\n");
390                 return -ENOMEM;
391         }
392
393         fb->fb.fix.smem_start   = dma;
394         fb->fb.fix.smem_len     = framesize;
395
396         return 0;
397 }
398
399 static int realview_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
400 {
401         return dma_mmap_writecombine(&fb->dev->dev, vma,
402                                      fb->fb.screen_base,
403                                      fb->fb.fix.smem_start,
404                                      fb->fb.fix.smem_len);
405 }
406
407 static void realview_clcd_remove(struct clcd_fb *fb)
408 {
409         dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
410                               fb->fb.screen_base, fb->fb.fix.smem_start);
411 }
412
413 struct clcd_board clcd_plat_data = {
414         .name           = "RealView",
415         .check          = clcdfb_check,
416         .decode         = clcdfb_decode,
417         .disable        = realview_clcd_disable,
418         .enable         = realview_clcd_enable,
419         .setup          = realview_clcd_setup,
420         .mmap           = realview_clcd_mmap,
421         .remove         = realview_clcd_remove,
422 };
423
424 #ifdef CONFIG_LEDS
425 #define VA_LEDS_BASE (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_LED_OFFSET)
426
427 void realview_leds_event(led_event_t ledevt)
428 {
429         unsigned long flags;
430         u32 val;
431
432         local_irq_save(flags);
433         val = readl(VA_LEDS_BASE);
434
435         switch (ledevt) {
436         case led_idle_start:
437                 val = val & ~REALVIEW_SYS_LED0;
438                 break;
439
440         case led_idle_end:
441                 val = val | REALVIEW_SYS_LED0;
442                 break;
443
444         case led_timer:
445                 val = val ^ REALVIEW_SYS_LED1;
446                 break;
447
448         case led_halted:
449                 val = 0;
450                 break;
451
452         default:
453                 break;
454         }
455
456         writel(val, VA_LEDS_BASE);
457         local_irq_restore(flags);
458 }
459 #endif  /* CONFIG_LEDS */
460
461 /*
462  * Where is the timer (VA)?
463  */
464 #define TIMER0_VA_BASE           __io_address(REALVIEW_TIMER0_1_BASE)
465 #define TIMER1_VA_BASE          (__io_address(REALVIEW_TIMER0_1_BASE) + 0x20)
466 #define TIMER2_VA_BASE           __io_address(REALVIEW_TIMER2_3_BASE)
467 #define TIMER3_VA_BASE          (__io_address(REALVIEW_TIMER2_3_BASE) + 0x20)
468
469 /*
470  * How long is the timer interval?
471  */
472 #define TIMER_INTERVAL  (TICKS_PER_uSEC * mSEC_10)
473 #if TIMER_INTERVAL >= 0x100000
474 #define TIMER_RELOAD    (TIMER_INTERVAL >> 8)
475 #define TIMER_DIVISOR   (TIMER_CTRL_DIV256)
476 #define TICKS2USECS(x)  (256 * (x) / TICKS_PER_uSEC)
477 #elif TIMER_INTERVAL >= 0x10000
478 #define TIMER_RELOAD    (TIMER_INTERVAL >> 4)           /* Divide by 16 */
479 #define TIMER_DIVISOR   (TIMER_CTRL_DIV16)
480 #define TICKS2USECS(x)  (16 * (x) / TICKS_PER_uSEC)
481 #else
482 #define TIMER_RELOAD    (TIMER_INTERVAL)
483 #define TIMER_DIVISOR   (TIMER_CTRL_DIV1)
484 #define TICKS2USECS(x)  ((x) / TICKS_PER_uSEC)
485 #endif
486
487 /*
488  * Returns number of ms since last clock interrupt.  Note that interrupts
489  * will have been disabled by do_gettimeoffset()
490  */
491 static unsigned long realview_gettimeoffset(void)
492 {
493         unsigned long ticks1, ticks2, status;
494
495         /*
496          * Get the current number of ticks.  Note that there is a race
497          * condition between us reading the timer and checking for
498          * an interrupt.  We get around this by ensuring that the
499          * counter has not reloaded between our two reads.
500          */
501         ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
502         do {
503                 ticks1 = ticks2;
504                 status = __raw_readl(__io_address(REALVIEW_GIC_DIST_BASE + GIC_DIST_PENDING_SET)
505                                      + ((IRQ_TIMERINT0_1 >> 5) << 2));
506                 ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
507         } while (ticks2 > ticks1);
508
509         /*
510          * Number of ticks since last interrupt.
511          */
512         ticks1 = TIMER_RELOAD - ticks2;
513
514         /*
515          * Interrupt pending?  If so, we've reloaded once already.
516          *
517          * FIXME: Need to check this is effectively timer 0 that expires
518          */
519         if (status & IRQMASK_TIMERINT0_1)
520                 ticks1 += TIMER_RELOAD;
521
522         /*
523          * Convert the ticks to usecs
524          */
525         return TICKS2USECS(ticks1);
526 }
527
528 /*
529  * IRQ handler for the timer
530  */
531 static irqreturn_t realview_timer_interrupt(int irq, void *dev_id)
532 {
533         write_seqlock(&xtime_lock);
534
535         // ...clear the interrupt
536         writel(1, TIMER0_VA_BASE + TIMER_INTCLR);
537
538         timer_tick();
539
540 #if defined(CONFIG_SMP) && !defined(CONFIG_LOCAL_TIMERS)
541         smp_send_timer();
542         update_process_times(user_mode(get_irq_regs()));
543 #endif
544
545         write_sequnlock(&xtime_lock);
546
547         return IRQ_HANDLED;
548 }
549
550 static struct irqaction realview_timer_irq = {
551         .name           = "RealView Timer Tick",
552         .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
553         .handler        = realview_timer_interrupt,
554 };
555
556 /*
557  * Set up timer interrupt, and return the current time in seconds.
558  */
559 static void __init realview_timer_init(void)
560 {
561         u32 val;
562
563         /* 
564          * set clock frequency: 
565          *      REALVIEW_REFCLK is 32KHz
566          *      REALVIEW_TIMCLK is 1MHz
567          */
568         val = readl(__io_address(REALVIEW_SCTL_BASE));
569         writel((REALVIEW_TIMCLK << REALVIEW_TIMER1_EnSel) |
570                (REALVIEW_TIMCLK << REALVIEW_TIMER2_EnSel) | 
571                (REALVIEW_TIMCLK << REALVIEW_TIMER3_EnSel) |
572                (REALVIEW_TIMCLK << REALVIEW_TIMER4_EnSel) | val,
573                __io_address(REALVIEW_SCTL_BASE));
574
575         /*
576          * Initialise to a known state (all timers off)
577          */
578         writel(0, TIMER0_VA_BASE + TIMER_CTRL);
579         writel(0, TIMER1_VA_BASE + TIMER_CTRL);
580         writel(0, TIMER2_VA_BASE + TIMER_CTRL);
581         writel(0, TIMER3_VA_BASE + TIMER_CTRL);
582
583         writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
584         writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_VALUE);
585         writel(TIMER_DIVISOR | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC |
586                TIMER_CTRL_IE, TIMER0_VA_BASE + TIMER_CTRL);
587
588         /* 
589          * Make irqs happen for the system timer
590          */
591         setup_irq(IRQ_TIMERINT0_1, &realview_timer_irq);
592 }
593
594 struct sys_timer realview_timer = {
595         .init           = realview_timer_init,
596         .offset         = realview_gettimeoffset,
597 };