http://downloads.netgear.com/files/GPL/GPL_Source_V361j_DM111PSP_series_consumer_rele...
[bcm963xx.git] / kernel / linux / arch / arm / mach-sa1100 / trizeps.c
1 /*
2  * linux/arch/arm/mach-sa1100/trizeps.c
3  *
4  * Authors:
5  * Andreas Hofer <ho@dsa-ac.de>,
6  * Peter Lueg <pl@dsa-ac.de>,
7  * Guennadi Liakhovetski <gl@dsa-ac.de>
8  *
9  * This file contains all Trizeps-specific tweaks.
10  *
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.
14  */
15 #include <linux/init.h>
16 #include <linux/kernel.h>
17 #include <linux/sched.h>
18 #include <linux/tty.h>
19 #include <linux/module.h>
20 #include <linux/errno.h>
21 #include <linux/delay.h>
22 #include <linux/pm.h>
23
24 #include <asm/mach-types.h>
25 #include <asm/hardware.h>
26 #include <asm/arch/trizeps.h>
27 #include <asm/setup.h>
28 #include <asm/page.h>
29 #include <asm/pgtable.h>
30
31 #include <asm/mach/arch.h>
32 #include <asm/mach/map.h>
33 #include <asm/mach/irq.h>
34 #include <asm/mach/serial_sa1100.h>
35 #include <linux/serial_core.h>
36 #include <linux/serial_reg.h>
37 #include <asm/arch/serial.h>
38
39 #include <asm/io.h>
40 #include <asm/irq.h>
41 #include <asm/arch/irqs.h>
42
43 #include "generic.h"
44
45 #undef DEBUG_TRIZEPS
46 #ifdef DEBUG_TRIZEPS
47 #define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
48 #else
49 #define DPRINTK( x... )
50 #endif
51
52 static struct tri_uart_cts_data_t tri_uart_cts_data[] = {
53         { TRIZEPS_GPIO_UART1_CTS, 0, NULL, NULL,"int. UART1 cts" },
54         { TRIZEPS_GPIO_UART2_CTS, 0, NULL, NULL,"int. UART2 cts" },
55         { TRIZEPS_GPIO_UART3_CTS, 0, NULL, NULL,"int. UART3 cts" }
56 };
57
58 static void trizeps_cts_intr(int irq, void *dev_id, struct pt_regs *regs)
59 {
60         struct tri_uart_cts_data_t * uart_data = (struct tri_uart_cts_data_t *)dev_id;
61         int cts = (!(GPLR & uart_data->cts_gpio));
62
63         /* NOTE: I suppose that we will not get any interrupts
64            if the GPIO is not changed, so maybe
65            the cts_prev_state can be removed ... */
66         if (cts != uart_data->cts_prev_state) {
67
68                 uart_data->cts_prev_state = cts;
69                 uart_handle_cts_change(uart_data->port, cts);
70                 DPRINTK("(IRQ %d) changed (cts=%d) stop=%d\n",
71                         irq, cts, uart_data->info->tty->hw_stopped);
72         }
73 }
74
75 static int
76 trizeps_register_cts_intr(int gpio,
77                           int irq,
78                           struct tri_uart_cts_data_t *uart_data)
79 {
80         int ret = 0;
81
82         if(irq != NO_IRQ)
83         {
84                 set_irq_type(irq, IRQT_BOTHEDGE);
85
86                 ret = request_irq(irq, trizeps_cts_intr,
87                                   SA_INTERRUPT, uart_data->name, uart_data);
88                 if (ret)
89                         printk(KERN_ERR "uart_open: failed to register CTS irq (%d)\n", ret);
90         }
91         return ret;
92 }
93
94 static void trizeps_set_mctrl(struct uart_port *port, u_int mctrl)
95 {
96         if (port->mapbase == _Ser1UTCR0)
97         {
98                 /**** ttySA1  ****/
99                 if (mctrl & TIOCM_RTS)
100                         GPCR |= TRIZEPS_GPIO_UART1_RTS;
101                 else
102                         GPSR |= TRIZEPS_GPIO_UART1_RTS;
103
104                 DPRINTK("2 ttySA%d Set RTS %s\n",port->line,
105                         mctrl & TIOCM_RTS ? "low" : "high");
106
107         }
108         else if (port->mapbase == _Ser3UTCR0)
109         {
110                 /**** ttySA0  ****/
111         }
112         else
113         {
114                 /**** ttySA2  ****/
115         }
116 }
117
118 static u_int trizeps_get_mctrl(struct uart_port *port)
119 {
120         int result = TIOCM_CD | TIOCM_DSR;
121
122         if (port->mapbase == _Ser1UTCR0)
123         {
124                 if (!(GPLR & TRIZEPS_GPIO_UART1_CTS))
125                         result |= TIOCM_CTS;
126         }
127         else if (port->mapbase == _Ser2UTCR0)
128         {
129                 result |= TIOCM_CTS;
130         }
131         else if (port->mapbase == _Ser3UTCR0)
132         {
133                 result |= TIOCM_CTS;
134         }
135         else
136         {
137                 result = TIOCM_CTS;
138         }
139
140         DPRINTK(" ttySA%d %s%s%s\n",port->line,
141                 result & TIOCM_CD  ? "CD "  : "",
142                 result & TIOCM_CTS ? "CTS " : "",
143                 result & TIOCM_DSR ? "DSR " : "");
144
145         return result;
146 }
147
148 static struct sa1100_port_fns trizeps_port_fns __initdata = {
149         .set_mctrl =    trizeps_set_mctrl,
150         .get_mctrl =    trizeps_get_mctrl,
151 };
152
153 static void trizeps_power_off(void)
154 {
155         printk("trizeps power off\n");
156         mdelay(100);
157         cli();
158         /* disable internal oscillator, float CS lines */
159         PCFR = (PCFR_OPDE | PCFR_FP | PCFR_FS);
160         /* enable wake-up on GPIO0 (Assabet...) */
161         PWER = GFER = GRER = 1;
162         /*
163          * set scratchpad to zero, just in case it is used as a
164          * restart address by the bootloader.
165          */
166         PSPR = 0;
167
168         /*
169          *  Power off
170          *  -> disconnect AKku
171          */
172         TRIZEPS_BCR_set(TRIZEPS_BCR0, TRIZEPS_MFT_OFF);
173
174         /*
175          * if power supply no Akku
176          * -> enter sleep mode
177          */
178         PMCR = PMCR_SF;
179 }
180
181 static int __init trizeps_init(void)
182 {
183         if (!machine_is_trizeps())
184                 return -EINVAL;
185
186         DPRINTK(" \n");
187         pm_power_off = trizeps_power_off;
188
189         // Init UART2 for IrDA
190 //      PPDR |= PPC_TXD2;           // Set TXD2 as output
191         Ser2UTCR4 = UTCR4_HSE;      // enable HSE
192         Ser2HSCR0 = 0;
193         Ser2HSSR0 = HSSR0_EIF | HSSR0_TUR | HSSR0_RAB | HSSR0_FRE;
194
195         /* Init MECR */
196         MECR = 0x00060006;
197
198         /* Set up external serial IRQs */
199         GAFR &= ~(GPIO_GPIO16 | GPIO_GPIO17);  // no alternate function
200         GPDR &= ~(GPIO_GPIO16 | GPIO_GPIO17);  // Set to Input
201         set_irq_type(IRQ_GPIO16, IRQT_RISING);
202         set_irq_type(IRQ_GPIO17, IRQT_RISING);
203
204         return 0;
205 }
206
207 __initcall(trizeps_init);
208
209 static struct map_desc trizeps_io_desc[] __initdata = {
210         /* virtual      physical        length  type */
211         { 0xF0000000l, 0x30000000l, 0x00800000l, MT_DEVICE },
212         { 0xF2000000l, 0x38000000l, 0x00800000l, MT_DEVICE },
213 };
214
215 static void __init trizeps_map_io(void)
216 {
217         sa1100_map_io();
218         iotable_init(trizeps_io_desc, ARRAY_SIZE(trizeps_io_desc));
219
220         sa1100_register_uart_fns(&trizeps_port_fns);
221         sa1100_register_uart(0, 3);
222         sa1100_register_uart(1, 1);
223         sa1100_register_uart(2, 2);
224 }
225
226 MACHINE_START(TRIZEPS, "TRIZEPS")
227         MAINTAINER("DSA")
228         BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
229         MAPIO(trizeps_map_io)
230         INITIRQ(sa1100_init_irq)
231         INITTIME(sa1100_init_time)
232 MACHINE_END