This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / drivers / serial / cpm_uart / cpm_uart_cpm1.c
1 /*
2  *  linux/drivers/serial/cpm_uart.c
3  *
4  *  Driver for CPM (SCC/SMC) serial ports; CPM1 definitions
5  *
6  *  Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2)
7  *              Pantelis Antoniou (panto@intracom.gr) (CPM1)
8  * 
9  *  Copyright (C) 2004 Freescale Semiconductor, Inc.
10  *            (C) 2004 Intracom, S.A.
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25  *
26  */
27
28 #include <linux/config.h>
29 #include <linux/module.h>
30 #include <linux/tty.h>
31 #include <linux/ioport.h>
32 #include <linux/init.h>
33 #include <linux/serial.h>
34 #include <linux/console.h>
35 #include <linux/sysrq.h>
36 #include <linux/device.h>
37 #include <linux/bootmem.h>
38 #include <linux/dma-mapping.h>
39
40 #include <asm/io.h>
41 #include <asm/irq.h>
42
43 #include <linux/serial_core.h>
44 #include <linux/kernel.h>
45
46 #include "cpm_uart.h"
47
48 /**************************************************************/
49
50 void cpm_line_cr_cmd(int line, int cmd)
51 {
52         ushort val;
53         volatile cpm8xx_t *cp = cpmp;
54
55         switch (line) {
56         case UART_SMC1:
57                 val = mk_cr_cmd(CPM_CR_CH_SMC1, cmd) | CPM_CR_FLG;
58                 break;
59         case UART_SMC2:
60                 val = mk_cr_cmd(CPM_CR_CH_SMC2, cmd) | CPM_CR_FLG;
61                 break;
62         case UART_SCC1:
63                 val = mk_cr_cmd(CPM_CR_CH_SCC1, cmd) | CPM_CR_FLG;
64                 break;
65         case UART_SCC2:
66                 val = mk_cr_cmd(CPM_CR_CH_SCC2, cmd) | CPM_CR_FLG;
67                 break;
68         case UART_SCC3:
69                 val = mk_cr_cmd(CPM_CR_CH_SCC3, cmd) | CPM_CR_FLG;
70                 break;
71         case UART_SCC4:
72                 val = mk_cr_cmd(CPM_CR_CH_SCC4, cmd) | CPM_CR_FLG;
73                 break;
74         default:
75                 return;
76
77         }
78         cp->cp_cpcr = val;
79         while (cp->cp_cpcr & CPM_CR_FLG) ;
80 }
81
82 void smc1_lineif(struct uart_cpm_port *pinfo)
83 {
84         volatile cpm8xx_t *cp = cpmp;
85
86         cp->cp_pbpar |= 0x000000c0;
87         cp->cp_pbdir &= ~0x000000c0;
88         cp->cp_pbodr &= ~0x000000c0;
89
90         pinfo->brg = 1;
91 }
92
93 void smc2_lineif(struct uart_cpm_port *pinfo)
94 {
95         /* XXX SMC2: insert port configuration here */
96         pinfo->brg = 2;
97 }
98
99 void scc1_lineif(struct uart_cpm_port *pinfo)
100 {
101         /* XXX SCC1: insert port configuration here */
102         pinfo->brg = 1;
103 }
104
105 void scc2_lineif(struct uart_cpm_port *pinfo)
106 {
107         /* XXX SCC2: insert port configuration here */
108         pinfo->brg = 2;
109 }
110
111 void scc3_lineif(struct uart_cpm_port *pinfo)
112 {
113         /* XXX SCC3: insert port configuration here */
114         pinfo->brg = 3;
115 }
116
117 void scc4_lineif(struct uart_cpm_port *pinfo)
118 {
119         /* XXX SCC4: insert port configuration here */
120         pinfo->brg = 4;
121 }
122
123 /*
124  * Allocate DP-Ram and memory buffers. We need to allocate a transmit and 
125  * receive buffer descriptors from dual port ram, and a character
126  * buffer area from host mem. If we are allocating for the console we need
127  * to do it from bootmem
128  */
129 int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
130 {
131         int dpmemsz, memsz;
132         u8 *dp_mem;
133         uint dp_addr;
134         u8 *mem_addr;
135         dma_addr_t dma_addr;
136
137         pr_debug("CPM uart[%d]:allocbuf\n", pinfo->port.line);
138
139         dpmemsz = sizeof(cbd_t) * (pinfo->rx_nrfifos + pinfo->tx_nrfifos);
140         dp_mem = m8xx_cpm_dpalloc(dpmemsz);
141         if (dp_mem == NULL) {
142                 printk(KERN_ERR
143                        "cpm_uart_cpm1.c: could not allocate buffer descriptors\n");
144                 return -ENOMEM;
145         }
146         dp_addr = m8xx_cpm_dpram_offset(dp_mem);
147
148         memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
149             L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
150         if (is_con) {
151                 mem_addr = (u8 *) m8xx_cpm_hostalloc(memsz);
152                 dma_addr = 0;
153         } else
154                 mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
155                                               GFP_KERNEL);
156
157         if (mem_addr == NULL) {
158                 m8xx_cpm_dpfree(dp_mem);
159                 printk(KERN_ERR
160                        "cpm_uart_cpm1.c: could not allocate coherent memory\n");
161                 return -ENOMEM;
162         }
163
164         pinfo->dp_addr = dp_addr;
165         pinfo->mem_addr = mem_addr;
166         pinfo->dma_addr = dma_addr;
167
168         pinfo->rx_buf = mem_addr;
169         pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
170                                                        * pinfo->rx_fifosize);
171
172         pinfo->rx_bd_base = (volatile cbd_t *)dp_mem;
173         pinfo->tx_bd_base = pinfo->rx_bd_base + pinfo->rx_nrfifos;
174
175         return 0;
176 }
177
178 void cpm_uart_freebuf(struct uart_cpm_port *pinfo)
179 {
180         dma_free_coherent(NULL, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
181                                                pinfo->rx_fifosize) +
182                           L1_CACHE_ALIGN(pinfo->tx_nrfifos *
183                                          pinfo->tx_fifosize), pinfo->mem_addr,
184                           pinfo->dma_addr);
185
186         m8xx_cpm_dpfree(m8xx_cpm_dpram_addr(pinfo->dp_addr));
187 }
188
189 /* Setup any dynamic params in the uart desc */
190 int cpm_uart_init_portdesc(void)
191 {
192         pr_debug("CPM uart[-]:init portdesc\n");
193
194         cpm_uart_nr = 0;
195 #ifdef CONFIG_SERIAL_CPM_SMC1
196         cpm_uart_ports[UART_SMC1].smcp = &cpmp->cp_smc[0];
197         cpm_uart_ports[UART_SMC1].smcup =
198             (smc_uart_t *) & cpmp->cp_dparam[PROFF_SMC1];
199         cpm_uart_ports[UART_SMC1].port.mapbase =
200             (unsigned long)&cpmp->cp_smc[0];
201         cpm_uart_ports[UART_SMC1].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
202         cpm_uart_ports[UART_SMC1].smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
203         cpm_uart_ports[UART_SMC1].port.uartclk = (((bd_t *) __res)->bi_intfreq);
204         cpm_uart_port_map[cpm_uart_nr++] = UART_SMC1;
205 #endif
206
207 #ifdef CONFIG_SERIAL_CPM_SMC2
208         cpm_uart_ports[UART_SMC2].smcp = &cpmp->cp_smc[1];
209         cpm_uart_ports[UART_SMC2].smcup =
210             (smc_uart_t *) & cpmp->cp_dparam[PROFF_SMC2];
211         cpm_uart_ports[UART_SMC2].port.mapbase =
212             (unsigned long)&cpmp->cp_smc[1];
213         cpm_uart_ports[UART_SMC2].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
214         cpm_uart_ports[UART_SMC2].smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
215         cpm_uart_ports[UART_SMC2].port.uartclk = (((bd_t *) __res)->bi_intfreq);
216         cpm_uart_port_map[cpm_uart_nr++] = UART_SMC2;
217 #endif
218
219 #ifdef CONFIG_SERIAL_CPM_SCC1
220         cpm_uart_ports[UART_SCC1].sccp = &cpmp->cp_scc[0];
221         cpm_uart_ports[UART_SCC1].sccup =
222             (scc_uart_t *) & cpmp->cp_dparam[PROFF_SCC1];
223         cpm_uart_ports[UART_SCC1].port.mapbase =
224             (unsigned long)&cpmp->cp_scc[0];
225         cpm_uart_ports[UART_SCC1].sccp->scc_sccm &=
226             ~(UART_SCCM_TX | UART_SCCM_RX);
227         cpm_uart_ports[UART_SCC1].sccp->scc_gsmrl &=
228             ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
229         cpm_uart_ports[UART_SCC1].port.uartclk = (((bd_t *) __res)->bi_intfreq);
230         cpm_uart_port_map[cpm_uart_nr++] = UART_SCC1;
231 #endif
232
233 #ifdef CONFIG_SERIAL_CPM_SCC2
234         cpm_uart_ports[UART_SCC2].sccp = &cpmp->cp_scc[1];
235         cpm_uart_ports[UART_SCC2].sccup =
236             (scc_uart_t *) & cpmp->cp_dparam[PROFF_SCC2];
237         cpm_uart_ports[UART_SCC2].port.mapbase =
238             (unsigned long)&cpmp->cp_scc[1];
239         cpm_uart_ports[UART_SCC2].sccp->scc_sccm &=
240             ~(UART_SCCM_TX | UART_SCCM_RX);
241         cpm_uart_ports[UART_SCC2].sccp->scc_gsmrl &=
242             ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
243         cpm_uart_ports[UART_SCC2].port.uartclk = (((bd_t *) __res)->bi_intfreq);
244         cpm_uart_port_map[cpm_uart_nr++] = UART_SCC2;
245 #endif
246
247 #ifdef CONFIG_SERIAL_CPM_SCC3
248         cpm_uart_ports[UART_SCC3].sccp = &cpmp->cp_scc[2];
249         cpm_uart_ports[UART_SCC3].sccup =
250             (scc_uart_t *) & cpmp->cp_dparam[PROFF_SCC3];
251         cpm_uart_ports[UART_SCC3].port.mapbase =
252             (unsigned long)&cpmp->cp_scc[2];
253         cpm_uart_ports[UART_SCC3].sccp->scc_sccm &=
254             ~(UART_SCCM_TX | UART_SCCM_RX);
255         cpm_uart_ports[UART_SCC3].sccp->scc_gsmrl &=
256             ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
257         cpm_uart_ports[UART_SCC3].port.uartclk = (((bd_t *) __res)->bi_intfreq);
258         cpm_uart_port_map[cpm_uart_nr++] = UART_SCC3;
259 #endif
260
261 #ifdef CONFIG_SERIAL_CPM_SCC4
262         cpm_uart_ports[UART_SCC4].sccp = &cpmp->cp_scc[3];
263         cpm_uart_ports[UART_SCC4].sccup =
264             (scc_uart_t *) & cpmp->cp_dparam[PROFF_SCC4];
265         cpm_uart_ports[UART_SCC4].port.mapbase =
266             (unsigned long)&cpmp->cp_scc[3];
267         cpm_uart_ports[UART_SCC4].sccp->scc_sccm &=
268             ~(UART_SCCM_TX | UART_SCCM_RX);
269         cpm_uart_ports[UART_SCC4].sccp->scc_gsmrl &=
270             ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
271         cpm_uart_ports[UART_SCC4].port.uartclk = (((bd_t *) __res)->bi_intfreq);
272         cpm_uart_port_map[cpm_uart_nr++] = UART_SCC4;
273 #endif
274         return 0;
275 }