initial commit with v2.6.9
[linux-2.6.9-moxart.git] / arch / arm / mach-sa1100 / system3.c
blob76e7d36e71bcbf4a32523eb32a08889ca75b0516
1 /*
2 * linux/arch/arm/mach-sa1100/system3.c
4 * Copyright (C) 2001 Stefan Eletzhofer <stefan.eletzhofer@eletztrick.de>
6 * $Id: system3.c,v 1.1.6.1 2001/12/04 17:28:06 seletz Exp $
8 * This file contains all PT Sytsem 3 tweaks. Based on original work from
9 * Nicolas Pitre's assabet fixes
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * $Log: system3.c,v $
16 * Revision 1.1.6.1 2001/12/04 17:28:06 seletz
17 * - merged from previous branch
19 * Revision 1.1.4.3 2001/12/04 15:16:31 seletz
20 * - merged from linux_2_4_13_ac5_rmk2
22 * Revision 1.1.4.2 2001/11/19 17:18:57 seletz
23 * - more code cleanups
25 * Revision 1.1.4.1 2001/11/16 13:52:05 seletz
26 * - PT Digital Board Support Code
28 * Revision 1.1.2.2 2001/11/05 16:46:18 seletz
29 * - cleanups
31 * Revision 1.1.2.1 2001/10/15 16:00:43 seletz
32 * - first revision working with new board
37 #include <linux/config.h>
38 #include <linux/init.h>
39 #include <linux/kernel.h>
40 #include <linux/tty.h>
41 #include <linux/module.h>
42 #include <linux/errno.h>
43 #include <linux/cpufreq.h>
45 #include <asm/hardware.h>
46 #include <asm/mach-types.h>
47 #include <asm/setup.h>
48 #include <asm/irq.h>
50 #include <asm/mach/arch.h>
51 #include <asm/mach/map.h>
52 #include <asm/mach/irq.h>
53 #include <asm/mach/serial_sa1100.h>
55 #include <linux/serial_core.h>
57 #include "generic.h"
58 #include <asm/hardware/sa1111.h>
60 #define DEBUG 1
62 #ifdef DEBUG
63 # define DPRINTK( x, args... ) printk( "%s: line %d: "x, __FUNCTION__, __LINE__, ## args );
64 #else
65 # define DPRINTK( x, args... ) /* nix */
66 #endif
68 /**********************************************************************
69 * prototypes
72 /* init funcs */
73 static int __init system3_init(void);
74 static void __init system3_init_irq(void);
75 static void __init system3_map_io(void);
77 static u_int system3_get_mctrl(struct uart_port *port);
78 static void system3_set_mctrl(struct uart_port *port, u_int mctrl);
79 static void system3_uart_pm(struct uart_port *port, u_int state, u_int oldstate);
80 static int sdram_notifier(struct notifier_block *nb, unsigned long event, void *data);
82 static void system3_lcd_power(int on);
83 static void system3_backlight_power(int on);
86 /**********************************************************************
87 * global data
90 /**********************************************************************
91 * static data
94 static struct map_desc system3_io_desc[] __initdata = {
95 /* virtual physical length type */
96 { 0xf3000000, PT_CPLD_BASE, 0x00100000, MT_DEVICE }, /* System Registers */
97 { 0xf4000000, PT_SA1111_BASE, 0x00100000, MT_DEVICE } /* SA-1111 */
100 static struct sa1100_port_fns system3_port_fns __initdata = {
101 .set_mctrl = system3_set_mctrl,
102 .get_mctrl = system3_get_mctrl,
103 .pm = system3_uart_pm,
106 static struct notifier_block system3_clkchg_block = {
107 .notifier_call = sdram_notifier,
110 /**********************************************************************
111 * Static functions
114 static void __init system3_map_io(void)
116 DPRINTK( "%s\n", "START" );
117 sa1100_map_io();
118 iotable_init(system3_io_desc, ARRAY_SIZE(system3_io_desc));
120 sa1100_register_uart_fns(&system3_port_fns);
121 sa1100_register_uart(0, 1); /* com port */
122 sa1100_register_uart(1, 2);
123 sa1100_register_uart(2, 3); /* radio module */
125 Ser1SDCR0 |= SDCR0_SUS;
129 /*********************************************************************
130 * Install IRQ handler
132 static void
133 system3_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
135 u_char irr;
137 //DPRINTK( "irq=%d, desc=%p, regs=%p\n", irq, desc, regs );
139 while (1) {
140 struct irqdesc *d;
143 * Acknowledge the parent IRQ.
145 desc->chip->ack(irq);
148 * Read the interrupt reason register. Let's have all
149 * active IRQ bits high. Note: there is a typo in the
150 * Neponset user's guide for the SA1111 IRR level.
152 //irr = PT_IRQSR & (PT_IRR_LAN | PT_IRR_SA1111);
153 irr = PT_IRQSR & (PT_IRR_SA1111);
155 /* SMC IRQ is low-active, so "switch" bit over */
156 //irr ^= (PT_IRR_LAN);
158 //DPRINTK( "irr=0x%02x\n", irr );
160 if ((irr & (PT_IRR_LAN | PT_IRR_SA1111)) == 0)
161 break;
164 * Since there is no individual mask, we have to
165 * mask the parent IRQ. This is safe, since we'll
166 * recheck the register for any pending IRQs.
168 if (irr & (PT_IRR_LAN)) {
169 desc->chip->mask(irq);
171 if (irr & PT_IRR_LAN) {
172 //DPRINTK( "SMC9196, irq=%d\n", IRQ_SYSTEM3_SMC9196 );
173 d = irq_desc + IRQ_SYSTEM3_SMC9196;
174 d->handle(IRQ_SYSTEM3_SMC9196, d, regs);
177 #if 0 /* no SSP yet on system 4 */
178 if (irr & IRR_USAR) {
179 d = irq_desc + IRQ_NEPONSET_USAR;
180 d->handle(IRQ_NEPONSET_USAR, d, regs);
182 #endif
184 desc->chip->unmask(irq);
187 if (irr & PT_IRR_SA1111) {
188 //DPRINTK( "SA1111, irq=%d\n", IRQ_SYSTEM3_SA1111 );
189 d = irq_desc + IRQ_SYSTEM3_SA1111;
190 d->handle(IRQ_SYSTEM3_SA1111, d, regs);
195 static void __init system3_init_irq(void)
198 * Install handler for GPIO25.
200 set_irq_type(IRQ_GPIO25, IRQT_RISING);
201 set_irq_chained_handler(IRQ_GPIO25, system3_irq_handler);
204 * install eth irq
206 set_irq_handler(IRQ_SYSTEM3_SMC9196, do_simple_IRQ);
207 set_irq_flags(IRQ_SYSTEM3_SMC9196, IRQF_VALID | IRQF_PROBE);
210 /**********************************************************************
211 * On system 3 limit cpu frequency to 206 Mhz
213 static int sdram_notifier(struct notifier_block *nb, unsigned long event,
214 void *data)
216 struct cpufreq_policy *policy = data;
217 switch (event) {
218 case CPUFREQ_ADJUST:
219 case CPUFREQ_INCOMPATIBLE:
220 cpufreq_verify_within_limits(policy, 147500, 206000);
221 break;
222 case CPUFREQ_NOTIFY:
223 if ((policy->min < 147500) ||
224 (policy->max > 206000))
225 panic("cpufreq failed to limit the speed\n");
226 break;
228 return 0;
232 * system3_uart_pm - powermgmt callback function for system 3 UART
233 * @port: uart port structure
234 * @state: pm state
235 * @oldstate: old pm state
238 static void system3_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
240 /* TODO: switch on/off uart in powersave mode */
244 * Note! this can be called from IRQ context.
245 * FIXME: Handle PT Digital Board CTRL regs irq-safe.
247 * NB: system3 uses COM_RTS and COM_DTR for both UART1 (com port)
248 * and UART3 (radio module). We only handle them for UART1 here.
250 static void system3_set_mctrl(struct uart_port *port, u_int mctrl)
252 if (port->mapbase == _Ser1UTCR0) {
253 u_int set = 0, clear = 0;
255 if (mctrl & TIOCM_RTS)
256 set |= PT_CTRL2_RS1_RTS;
257 else
258 clear |= PT_CTRL2_RS1_RTS;
260 if (mctrl & TIOCM_DTR)
261 set |= PT_CTRL2_RS1_DTR;
262 else
263 clear |= PT_CTRL2_RS1_DTR;
265 PTCTRL2_clear(clear);
266 PTCTRL2_set(set);
270 static u_int system3_get_mctrl(struct uart_port *port)
272 u_int ret = 0;
273 u_int irqsr = PT_IRQSR;
275 /* need 2 reads to read current value */
276 irqsr = PT_IRQSR;
278 /* TODO: check IRQ source register for modem/com
279 status lines and set them correctly. */
281 ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
283 return ret;
287 * system3_lcd_backlight_on - switch system 3 lcd backlight on
290 int system3_lcd_backlight_on( void )
292 PTCTRL0_set( PT_CTRL0_LCD_BL );
293 return 0;
297 * system3_lcd_backlight_off - switch system 3 lcd backlight off
300 static void system3_lcd_backlight_off(void)
302 PTCTRL0_clear( PT_CTRL0_LCD_BL );
306 * system3_lcd_on - switch system 3 lcd on
309 static void system3_lcd_on(void)
311 DPRINTK( "%s\n", "START" );
312 PTCTRL0_set( PT_CTRL0_LCD_EN );
314 /* brightness / contrast */
315 sa1111_enable_device(SKPCR_PWMCLKEN);
316 PB_DDR = 0xFFFFFFFF;
317 SKPEN0 = 1;
318 SKPEN1 = 1;
322 * system3_lcd_off - switch system 3 lcd off
325 static void system3_lcd_off(void)
327 DPRINTK( "%s\n", "START" );
328 PTCTRL0_clear( PT_CTRL0_LCD_EN );
329 SKPEN0 = 0;
330 SKPEN1 = 0;
331 sa1111_disable_device(SKPCR_PWMCLKEN);
335 * system3_lcd_contrast - set system 3 contrast
336 * @value: the new contrast
339 static void system3_lcd_contrast(unsigned char value)
341 DPRINTK( "value=0x%02x\n", value );
342 SYS3LCDCONTR = value;
346 * system3_lcd_brightness - set system 3 brightness
347 * @value: the new brightness
350 static void system3_lcd_brightness(unsigned char value)
352 DPRINTK( "value=0x%02x\n", value );
353 SYS3LCDBRIGHT = value;
356 static void system3_lcd_power(int on)
358 if (on) {
359 system3_lcd_on();
360 } else {
361 system3_lcd_off();
365 static void system3_backlight_power(int on)
367 if (on) {
368 system3_lcd_backlight_on();
369 system3_lcd_contrast(0x95);
370 system3_lcd_brightness(240);
371 } else {
372 system3_lcd_backlight_off();
376 static struct resource sa1111_resources[] = {
377 [0] = {
378 .start = PT_SA1111_BASE,
379 .end = PT_SA1111_BASE + 0x00001fff,
380 .flags = IORESOURCE_MEM,
382 [1] = {
383 .start = IRQ_SYSTEM3_SA1111,
384 .end = IRQ_SYSTEM3_SA1111,
385 .flags = IORESOURCE_IRQ,
389 static u64 sa1111_dmamask = 0xffffffffUL;
391 static struct platform_device sa1111_device = {
392 .name = "sa1111",
393 .id = 0,
394 .dev = {
395 .dma_mask = &sa1111_dmamask,
396 .coherent_dma_mask = 0xffffffff,
398 .num_resources = ARRAY_SIZE(sa1111_resources),
399 .resource = sa1111_resources,
402 static struct platform_device *devices[] __initdata = {
403 &sa1111_device,
406 static int __init system3_init(void)
408 int ret = 0;
409 DPRINTK( "%s\n", "START" );
411 if ( !machine_is_pt_system3() ) {
412 ret = -EINVAL;
413 goto DONE;
416 sa1100fb_lcd_power = system3_lcd_power;
417 sa1100fb_backlight_power = system3_backlight_power;
419 /* init control register */
420 PT_CTRL0 = PT_CTRL0_INIT;
421 PT_CTRL1 = 0x02;
422 PT_CTRL2 = 0x00;
423 DPRINTK( "CTRL[0]=0x%02x\n", PT_CTRL0 );
424 DPRINTK( "CTRL[1]=0x%02x\n", PT_CTRL1 );
425 DPRINTK( "CTRL[2]=0x%02x\n", PT_CTRL2 );
428 * Ensure that the memory bus request/grant signals are setup,
429 * and the grant is held in its inactive state.
431 sa1110_mb_disable();
433 system3_init_irq();
436 * Probe for a SA1111.
438 ret = platform_add_devices(devices, ARRAY_SIZE(devices));
439 if (ret < 0) {
440 printk( KERN_WARNING"PT Digital Board: no SA1111 found!\n" );
441 goto DONE;
444 #ifdef CONFIG_CPU_FREQ
445 ret = cpufreq_register_notifier(&system3_clkchg_block);
446 if ( ret != 0 ) {
447 printk( KERN_WARNING"PT Digital Board: could not register clock scale callback\n" );
448 goto DONE;
450 #endif
453 ret = 0;
454 DONE:
455 DPRINTK( "ret=%d\n", ret );
456 return ret;
459 /**********************************************************************
460 * Exported Functions
463 /**********************************************************************
464 * kernel magic macros
466 arch_initcall(system3_init);
468 MACHINE_START(PT_SYSTEM3, "PT System 3")
469 BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
470 BOOT_PARAMS(0xc0000100)
471 MAPIO(system3_map_io)
472 INITIRQ(sa1100_init_irq)
473 INITTIME(sa1100_init_time)
474 MACHINE_END