RT-AC66 3.0.0.4.374.130 core
[tomato.git] / release / src-rt-6.x / cfe / cfe / arch / mips / cpu / sb1250 / src / dev_sb1250_uart.c
blob9e8437c97639079bdd598e9e5a3b357427cd2fde
1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
3 *
4 * SB1250 UART driver File: dev_sb1250_uart.c
5 *
6 * This is a console device driver for the SB1250's on-chip UARTs
7 *
8 * Author: Mitch Lichtenberg (mpl@broadcom.com)
9 *
10 *********************************************************************
12 * Copyright 2000,2001,2002,2003
13 * Broadcom Corporation. All rights reserved.
15 * This software is furnished under license and may be used and
16 * copied only in accordance with the following terms and
17 * conditions. Subject to these conditions, you may download,
18 * copy, install, use, modify and distribute modified or unmodified
19 * copies of this software in source and/or binary form. No title
20 * or ownership is transferred hereby.
22 * 1) Any source code used, modified or distributed must reproduce
23 * and retain this copyright notice and list of conditions
24 * as they appear in the source file.
26 * 2) No right is granted to use any trade name, trademark, or
27 * logo of Broadcom Corporation. The "Broadcom Corporation"
28 * name may not be used to endorse or promote products derived
29 * from this software without the prior written permission of
30 * Broadcom Corporation.
32 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
33 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
34 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
35 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
36 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
37 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
40 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
42 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
43 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
44 * THE POSSIBILITY OF SUCH DAMAGE.
45 ********************************************************************* */
50 #include "cfe.h"
51 #include "sbmips.h"
52 #include "lib_types.h"
53 #include "lib_malloc.h"
54 #include "lib_printf.h"
55 #include "cfe_iocb.h"
56 #include "cfe_device.h"
57 #include "cfe_ioctl.h"
58 #include "sb1250_defs.h"
59 #include "sb1250_regs.h"
60 #include "sb1250_uart.h"
62 #include "bsp_config.h"
64 #ifdef _MAGICWID_
65 #undef V_DUART_BAUD_RATE
66 #define V_DUART_BAUD_RATE(x) ((*((uint64_t *) 0xBFC00018)*1000000)/((x)*20)-1)
67 #endif
69 #ifdef SB1250_REFCLK_HZ
70 #undef V_DUART_BAUD_RATE
71 #define V_DUART_BAUD_RATE(x) ((SB1250_REFCLK_HZ)/((x)*20)-1)
72 #endif
74 static void sb1250_uart_probe(cfe_driver_t *drv,
75 unsigned long probe_a, unsigned long probe_b,
76 void *probe_ptr);
79 static int sb1250_uart_open(cfe_devctx_t *ctx);
80 static int sb1250_uart_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
81 static int sb1250_uart_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
82 static int sb1250_uart_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
83 static int sb1250_uart_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
84 static int sb1250_uart_close(cfe_devctx_t *ctx);
86 const static cfe_devdisp_t sb1250_uart_dispatch = {
87 sb1250_uart_open,
88 sb1250_uart_read,
89 sb1250_uart_inpstat,
90 sb1250_uart_write,
91 sb1250_uart_ioctl,
92 sb1250_uart_close,
93 NULL,
94 NULL
97 const cfe_driver_t sb1250_uart = {
98 "SB1250 DUART",
99 "uart",
100 CFE_DEV_SERIAL,
101 &sb1250_uart_dispatch,
102 sb1250_uart_probe
105 typedef struct sb1250_uart_s {
106 unsigned long uart_mode_reg_1;
107 unsigned long uart_mode_reg_2;
108 unsigned long uart_clk_sel;
109 unsigned long uart_cmd;
110 unsigned long uart_imr;
111 unsigned long uart_status;
112 unsigned long uart_tx_hold;
113 unsigned long uart_rx_hold;
114 unsigned long uart_oprset;
115 int uart_speed;
116 int uart_flowcontrol;
117 int uart_channel;
118 } sb1250_uart_t;
121 #define SBDUARTWRITE(softc,reg,val) \
122 (SBREADCSR(softc->uart_mode_reg_1),SBWRITECSR(softc->reg,val))
124 #define SBDUARTREAD(softc,reg) \
125 (SBREADCSR(softc->uart_mode_reg_1),SBREADCSR(softc->reg))
127 static void sb1250_uart_probe(cfe_driver_t *drv,
128 unsigned long probe_a, unsigned long probe_b,
129 void *probe_ptr)
131 sb1250_uart_t *softc;
132 char descr[80];
135 * probe_a is the DUART base address.
136 * probe_b is the channel-number-within-duart (0 or 1)
137 * probe_ptr is unused.
140 softc = (sb1250_uart_t *) KMALLOC(sizeof(sb1250_uart_t),0);
141 if (softc) {
142 softc->uart_mode_reg_1 = probe_a + R_DUART_CHANREG(probe_b,R_DUART_MODE_REG_1);
143 softc->uart_mode_reg_2 = probe_a + R_DUART_CHANREG(probe_b,R_DUART_MODE_REG_2);
144 softc->uart_clk_sel = probe_a + R_DUART_CHANREG(probe_b,R_DUART_CLK_SEL);
145 softc->uart_cmd = probe_a + R_DUART_CHANREG(probe_b,R_DUART_CMD);
146 softc->uart_status = probe_a + R_DUART_CHANREG(probe_b,R_DUART_STATUS);
147 softc->uart_tx_hold = probe_a + R_DUART_CHANREG(probe_b,R_DUART_TX_HOLD);
148 softc->uart_rx_hold = probe_a + R_DUART_CHANREG(probe_b,R_DUART_RX_HOLD);
149 softc->uart_imr = probe_a + R_DUART_IMRREG(probe_b);
150 softc->uart_oprset = probe_a + R_DUART_SET_OPR;
151 xsprintf(descr,"%s at 0x%X channel %d",drv->drv_description,probe_a,probe_b);
152 softc->uart_speed = CFG_SERIAL_BAUD_RATE;
153 softc->uart_flowcontrol = SERIAL_FLOW_NONE;
155 cfe_attach(drv,softc,NULL,descr);
161 static void sb1250_uart_setflow(sb1250_uart_t *softc)
163 uint64_t mode1val;
164 uint64_t mode2val;
166 mode1val = SBDUARTREAD(softc,uart_mode_reg_1);
167 mode2val = SBDUARTREAD(softc,uart_mode_reg_2);
169 switch (softc->uart_flowcontrol) {
170 case SERIAL_FLOW_NONE:
171 case SERIAL_FLOW_SOFTWARE:
172 mode1val &= ~M_DUART_RX_RTS_ENA;
173 mode2val &= ~M_DUART_TX_CTS_ENA;
174 break;
175 case SERIAL_FLOW_HARDWARE:
176 mode1val |= M_DUART_RX_RTS_ENA;
177 mode2val |= M_DUART_TX_CTS_ENA;
178 break;
181 SBDUARTWRITE(softc,uart_mode_reg_1,mode1val);
182 SBDUARTWRITE(softc,uart_mode_reg_2,mode2val);
186 static int sb1250_uart_open(cfe_devctx_t *ctx)
188 sb1250_uart_t *softc = ctx->dev_softc;
190 SBDUARTWRITE(softc,uart_mode_reg_1,V_DUART_BITS_PER_CHAR_8 | V_DUART_PARITY_MODE_NONE);
191 SBDUARTWRITE(softc,uart_mode_reg_2,M_DUART_STOP_BIT_LEN_1);
192 SBDUARTWRITE(softc,uart_clk_sel, V_DUART_BAUD_RATE(CFG_SERIAL_BAUD_RATE));
193 SBDUARTWRITE(softc,uart_imr, 0); /* DISABLE all interrupts */
194 SBDUARTWRITE(softc,uart_cmd, M_DUART_RX_EN | M_DUART_TX_EN);
195 if (softc->uart_channel == 0) {
196 SBDUARTWRITE(softc,uart_oprset, M_DUART_SET_OPR0 | M_DUART_SET_OPR2); /* CTS and DTR */
198 else {
199 SBDUARTWRITE(softc,uart_oprset, M_DUART_SET_OPR1 | M_DUART_SET_OPR3); /* CTS and DTR */
201 sb1250_uart_setflow(softc);
203 return 0;
206 static int sb1250_uart_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
208 sb1250_uart_t *softc = ctx->dev_softc;
209 unsigned char *bptr;
210 int blen;
212 bptr = buffer->buf_ptr;
213 blen = buffer->buf_length;
215 while (blen > 0) {
216 if (!(SBDUARTREAD(softc,uart_status) & M_DUART_RX_RDY)) break;
217 *bptr++ = (SBDUARTREAD(softc,uart_rx_hold) & 0xFF);
218 blen--;
221 buffer->buf_retlen = buffer->buf_length - blen;
222 return 0;
225 static int sb1250_uart_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
227 sb1250_uart_t *softc = ctx->dev_softc;
229 inpstat->inp_status = (SBDUARTREAD(softc,uart_status) & M_DUART_RX_RDY) ? 1 : 0;
231 return 0;
234 static int sb1250_uart_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
236 sb1250_uart_t *softc = ctx->dev_softc;
237 unsigned char *bptr;
238 int blen;
240 bptr = buffer->buf_ptr;
241 blen = buffer->buf_length;
243 while (blen > 0) {
244 if (!(SBDUARTREAD(softc,uart_status) & M_DUART_TX_RDY)) break;
245 SBDUARTWRITE(softc,uart_tx_hold,*bptr++);
246 blen--;
249 buffer->buf_retlen = buffer->buf_length - blen;
250 return 0;
253 static int sb1250_uart_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
255 sb1250_uart_t *softc = ctx->dev_softc;
256 unsigned int *info = (unsigned int *) buffer->buf_ptr;
258 switch ((int)buffer->buf_ioctlcmd) {
259 case IOCTL_SERIAL_GETSPEED:
260 *info = softc->uart_speed;
261 break;
262 case IOCTL_SERIAL_SETSPEED:
263 softc->uart_speed = *info;
264 SBDUARTWRITE(softc,uart_clk_sel,
265 V_DUART_BAUD_RATE(softc->uart_speed));
266 break;
267 case IOCTL_SERIAL_GETFLOW:
268 *info = softc->uart_flowcontrol;
269 break;
270 case IOCTL_SERIAL_SETFLOW:
271 softc->uart_flowcontrol = *info;
272 sb1250_uart_setflow(softc);
273 break;
274 default:
275 return -1;
278 return 0;
281 static int sb1250_uart_close(cfe_devctx_t *ctx)
283 sb1250_uart_t *softc = ctx->dev_softc;
285 SBDUARTWRITE(softc,uart_cmd, 0);
286 return 0;