Merge /spare/repo/linux-2.6/
[cascardo/linux.git] / arch / arm / mach-omap1 / serial.c
1 /*
2  * linux/arch/arm/mach-omap1/id.c
3  *
4  * OMAP1 CPU identification code
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10
11 #include <linux/config.h>
12 #include <linux/module.h>
13 #include <linux/kernel.h>
14 #include <linux/init.h>
15 #include <linux/delay.h>
16 #include <linux/serial.h>
17 #include <linux/tty.h>
18 #include <linux/serial_8250.h>
19 #include <linux/serial_reg.h>
20
21 #include <asm/io.h>
22 #include <asm/mach-types.h>
23 #include <asm/hardware/clock.h>
24
25 #include <asm/arch/board.h>
26 #include <asm/arch/mux.h>
27 #include <asm/arch/fpga.h>
28
29 static struct clk * uart1_ck = NULL;
30 static struct clk * uart2_ck = NULL;
31 static struct clk * uart3_ck = NULL;
32
33 static inline unsigned int omap_serial_in(struct plat_serial8250_port *up,
34                                           int offset)
35 {
36         offset <<= up->regshift;
37         return (unsigned int)__raw_readb(up->membase + offset);
38 }
39
40 static inline void omap_serial_outp(struct plat_serial8250_port *p, int offset,
41                                     int value)
42 {
43         offset <<= p->regshift;
44         __raw_writeb(value, p->membase + offset);
45 }
46
47 /*
48  * Internal UARTs need to be initialized for the 8250 autoconfig to work
49  * properly. Note that the TX watermark initialization may not be needed
50  * once the 8250.c watermark handling code is merged.
51  */
52 static void __init omap_serial_reset(struct plat_serial8250_port *p)
53 {
54         omap_serial_outp(p, UART_OMAP_MDR1, 0x07);      /* disable UART */
55         omap_serial_outp(p, UART_OMAP_SCR, 0x08);       /* TX watermark */
56         omap_serial_outp(p, UART_OMAP_MDR1, 0x00);      /* enable UART */
57
58         if (!cpu_is_omap1510()) {
59                 omap_serial_outp(p, UART_OMAP_SYSC, 0x01);
60                 while (!(omap_serial_in(p, UART_OMAP_SYSC) & 0x01));
61         }
62 }
63
64 static struct plat_serial8250_port serial_platform_data[] = {
65         {
66                 .membase        = (char*)IO_ADDRESS(OMAP_UART1_BASE),
67                 .mapbase        = (unsigned long)OMAP_UART1_BASE,
68                 .irq            = INT_UART1,
69                 .flags          = UPF_BOOT_AUTOCONF,
70                 .iotype         = UPIO_MEM,
71                 .regshift       = 2,
72                 .uartclk        = OMAP16XX_BASE_BAUD * 16,
73         },
74         {
75                 .membase        = (char*)IO_ADDRESS(OMAP_UART2_BASE),
76                 .mapbase        = (unsigned long)OMAP_UART2_BASE,
77                 .irq            = INT_UART2,
78                 .flags          = UPF_BOOT_AUTOCONF,
79                 .iotype         = UPIO_MEM,
80                 .regshift       = 2,
81                 .uartclk        = OMAP16XX_BASE_BAUD * 16,
82         },
83         {
84                 .membase        = (char*)IO_ADDRESS(OMAP_UART3_BASE),
85                 .mapbase        = (unsigned long)OMAP_UART3_BASE,
86                 .irq            = INT_UART3,
87                 .flags          = UPF_BOOT_AUTOCONF,
88                 .iotype         = UPIO_MEM,
89                 .regshift       = 2,
90                 .uartclk        = OMAP16XX_BASE_BAUD * 16,
91         },
92         { },
93 };
94
95 static struct platform_device serial_device = {
96         .name                   = "serial8250",
97         .id                     = 0,
98         .dev                    = {
99                 .platform_data  = serial_platform_data,
100         },
101 };
102
103 /*
104  * Note that on Innovator-1510 UART2 pins conflict with USB2.
105  * By default UART2 does not work on Innovator-1510 if you have
106  * USB OHCI enabled. To use UART2, you must disable USB2 first.
107  */
108 void __init omap_serial_init(int ports[OMAP_MAX_NR_PORTS])
109 {
110         int i;
111
112         if (cpu_is_omap730()) {
113                 serial_platform_data[0].regshift = 0;
114                 serial_platform_data[1].regshift = 0;
115                 serial_platform_data[0].irq = INT_730_UART_MODEM_1;
116                 serial_platform_data[1].irq = INT_730_UART_MODEM_IRDA_2;
117         }
118
119         if (cpu_is_omap1510()) {
120                 serial_platform_data[0].uartclk = OMAP1510_BASE_BAUD * 16;
121                 serial_platform_data[1].uartclk = OMAP1510_BASE_BAUD * 16;
122                 serial_platform_data[2].uartclk = OMAP1510_BASE_BAUD * 16;
123         }
124
125         for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
126                 unsigned char reg;
127
128                 if (ports[i] == 0) {
129                         serial_platform_data[i].membase = NULL;
130                         serial_platform_data[i].mapbase = 0;
131                         continue;
132                 }
133
134                 switch (i) {
135                 case 0:
136                         uart1_ck = clk_get(NULL, "uart1_ck");
137                         if (IS_ERR(uart1_ck))
138                                 printk("Could not get uart1_ck\n");
139                         else {
140                                 clk_use(uart1_ck);
141                                 if (cpu_is_omap1510())
142                                         clk_set_rate(uart1_ck, 12000000);
143                         }
144                         if (cpu_is_omap1510()) {
145                                 omap_cfg_reg(UART1_TX);
146                                 omap_cfg_reg(UART1_RTS);
147                                 if (machine_is_omap_innovator()) {
148                                         reg = fpga_read(OMAP1510_FPGA_POWER);
149                                         reg |= OMAP1510_FPGA_PCR_COM1_EN;
150                                         fpga_write(reg, OMAP1510_FPGA_POWER);
151                                         udelay(10);
152                                 }
153                         }
154                         break;
155                 case 1:
156                         uart2_ck = clk_get(NULL, "uart2_ck");
157                         if (IS_ERR(uart2_ck))
158                                 printk("Could not get uart2_ck\n");
159                         else {
160                                 clk_use(uart2_ck);
161                                 if (cpu_is_omap1510())
162                                         clk_set_rate(uart2_ck, 12000000);
163                                 else
164                                         clk_set_rate(uart2_ck, 48000000);
165                         }
166                         if (cpu_is_omap1510()) {
167                                 omap_cfg_reg(UART2_TX);
168                                 omap_cfg_reg(UART2_RTS);
169                                 if (machine_is_omap_innovator()) {
170                                         reg = fpga_read(OMAP1510_FPGA_POWER);
171                                         reg |= OMAP1510_FPGA_PCR_COM2_EN;
172                                         fpga_write(reg, OMAP1510_FPGA_POWER);
173                                         udelay(10);
174                                 }
175                         }
176                         break;
177                 case 2:
178                         uart3_ck = clk_get(NULL, "uart3_ck");
179                         if (IS_ERR(uart3_ck))
180                                 printk("Could not get uart3_ck\n");
181                         else {
182                                 clk_use(uart3_ck);
183                                 if (cpu_is_omap1510())
184                                         clk_set_rate(uart3_ck, 12000000);
185                         }
186                         if (cpu_is_omap1510()) {
187                                 omap_cfg_reg(UART3_TX);
188                                 omap_cfg_reg(UART3_RX);
189                         }
190                         break;
191                 }
192                 omap_serial_reset(&serial_platform_data[i]);
193         }
194 }
195
196 static int __init omap_init(void)
197 {
198         return platform_device_register(&serial_device);
199 }
200 arch_initcall(omap_init);