1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * NS16550 UART driver File: dev_ns16550.c
6 * This is a console device driver for an NS16550 UART, either
7 * on-board or as a PCI-device. In the case of a PCI device,
8 * our probe routine is called from the PCI probe code
9 * over in dev_ns16550_pci.c
11 * Author: Mitch Lichtenberg (mpl@broadcom.com)
13 *********************************************************************
15 * Copyright 2000,2001,2002,2003
16 * Broadcom Corporation. All rights reserved.
18 * This software is furnished under license and may be used and
19 * copied only in accordance with the following terms and
20 * conditions. Subject to these conditions, you may download,
21 * copy, install, use, modify and distribute modified or unmodified
22 * copies of this software in source and/or binary form. No title
23 * or ownership is transferred hereby.
25 * 1) Any source code used, modified or distributed must reproduce
26 * and retain this copyright notice and list of conditions
27 * as they appear in the source file.
29 * 2) No right is granted to use any trade name, trademark, or
30 * logo of Broadcom Corporation. The "Broadcom Corporation"
31 * name may not be used to endorse or promote products derived
32 * from this software without the prior written permission of
33 * Broadcom Corporation.
35 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
36 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
37 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
38 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
39 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
40 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
41 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
43 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
44 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
45 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
46 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
47 * THE POSSIBILITY OF SUCH DAMAGE.
48 ********************************************************************* */
50 #if CFG_SIM && CFG_SIM_CONSOLE
53 #endif /* CFG_SIM && CFG_SIM_CONSOLE */
55 #include "lib_types.h"
56 #include "lib_malloc.h"
57 #include "lib_printf.h"
59 #include "cfe_device.h"
60 #include "cfe_ioctl.h"
62 #include "lib_physio.h"
64 #include "bsp_config.h"
69 #define WRITECSR(softc, offset, value) do { \
70 phys_write8((softc)->uart_base + ((offset) << (softc)->reg_shift), (value)); \
71 phys_read8(0x18000000); \
74 #define WRITECSR(softc, offset, value) \
75 phys_write8((softc)->uart_base + ((offset) << (softc)->reg_shift), (value))
78 #define READCSR(softc, offset) \
79 phys_read8((softc)->uart_base + ((offset) << (softc)->reg_shift))
81 static int ns16550_uart_open(cfe_devctx_t
*ctx
);
82 static int ns16550_uart_read(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
);
83 static int ns16550_uart_inpstat(cfe_devctx_t
*ctx
,iocb_inpstat_t
*inpstat
);
84 static int ns16550_uart_write(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
);
85 static int ns16550_uart_ioctl(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
);
86 static int ns16550_uart_close(cfe_devctx_t
*ctx
);
88 void ns16550_uart_probe(cfe_driver_t
*drv
,
89 unsigned long probe_a
, unsigned long probe_b
,
93 const cfe_devdisp_t ns16550_uart_dispatch
= {
104 const cfe_driver_t ns16550_uart
= {
108 &ns16550_uart_dispatch
,
112 typedef struct ns16550_uart_s
{
113 physaddr_t uart_base
;
114 int uart_flowcontrol
;
122 * NS16550-compatible UART.
123 * probe_a: physical address of UART
126 void ns16550_uart_probe(cfe_driver_t
*drv
,
127 unsigned long probe_a
, unsigned long probe_b
,
130 ns16550_uart_t
*softc
;
133 softc
= (ns16550_uart_t
*) KMALLOC(sizeof(ns16550_uart_t
),0);
135 softc
->uart_base
= probe_a
;
136 softc
->baud_base
= probe_b
? : NS16550_HZ
;
137 softc
->reg_shift
= probe_ptr
? *(int*)probe_ptr
: 0;
138 softc
->uart_speed
= CFG_SERIAL_BAUD_RATE
;
139 softc
->uart_flowcontrol
= SERIAL_FLOW_NONE
;
140 xsprintf(descr
, "%s at 0x%X", drv
->drv_description
, (uint32_t)probe_a
);
142 cfe_attach(drv
, softc
, NULL
, descr
);
146 #if !defined(MIPS33xx)
148 #define DELAY(n) delay(n)
149 extern int32_t _getticks(void);
150 static void delay(int ticks
)
154 t
= _getticks() + ticks
;
155 while (_getticks() < t
)
158 #endif /* !MIPS33xx */
160 static void ns16550_uart_setflow(ns16550_uart_t
*softc
)
166 static int ns16550_uart_open(cfe_devctx_t
*ctx
)
168 ns16550_uart_t
*softc
= ctx
->dev_softc
;
171 brtc
= BRTC(softc
->baud_base
, softc
->uart_speed
);
173 WRITECSR(softc
,R_UART_CFCR
,CFCR_DLAB
);
174 WRITECSR(softc
,R_UART_DATA
,brtc
& 0xFF);
175 WRITECSR(softc
,R_UART_IER
,brtc
>>8);
176 WRITECSR(softc
,R_UART_CFCR
,CFCR_8BITS
);
178 #if !defined(NS16550_NO_FLOW)
180 WRITECSR(softc
,R_UART_CFCR
,CFCR_DLAB
);
181 WRITECSR(softc
,R_UART_DATA
,brtc
& 0xFF);
182 WRITECSR(softc
,R_UART_IER
,brtc
>>8);
183 WRITECSR(softc
,R_UART_CFCR
,CFCR_8BITS
);
184 #if !defined(_BCM94702_CPCI_)
185 WRITECSR(softc
,R_UART_MCR
,MCR_DTR
| MCR_RTS
| MCR_IENABLE
);
187 WRITECSR(softc
,R_UART_IER
,0);
189 WRITECSR(softc
,R_UART_FIFO
,FIFO_ENABLE
);
191 WRITECSR(softc
,R_UART_FIFO
,
192 FIFO_ENABLE
| FIFO_RCV_RST
| FIFO_XMT_RST
| FIFO_TRIGGER_1
);
195 if ((READCSR(softc
,R_UART_IIR
) & IIR_FIFO_MASK
) !=
197 WRITECSR(softc
,R_UART_FIFO
,0);
199 #endif /* !NS16550_NO_FLOW */
201 ns16550_uart_setflow(softc
);
206 static int ns16550_uart_read(cfe_devctx_t
*ctx
, iocb_buffer_t
*buffer
)
208 ns16550_uart_t
*softc
= ctx
->dev_softc
;
212 bptr
= buffer
->buf_ptr
;
213 blen
= buffer
->buf_length
;
215 while ((blen
> 0) && (READCSR(softc
,R_UART_LSR
) & LSR_RXRDY
)) {
216 *bptr
++ = (READCSR(softc
,R_UART_DATA
) & 0xFF);
220 buffer
->buf_retlen
= buffer
->buf_length
- blen
;
224 static int ns16550_uart_inpstat(cfe_devctx_t
*ctx
, iocb_inpstat_t
*inpstat
)
226 ns16550_uart_t
*softc
= ctx
->dev_softc
;
228 inpstat
->inp_status
= (READCSR(softc
,R_UART_LSR
) & LSR_RXRDY
) ? 1 : 0;
234 #define LOG_BUF_LEN (4096)
235 #define LOG_BUF_MASK (LOG_BUF_LEN-1)
236 char log_buf
[LOG_BUF_LEN
];
237 unsigned long log_start
;
240 #define UNCACHED(a) (((unsigned long)(a) & 0x1fffffff) | 0xa0000000)
242 #define UNCACHED(a) ((unsigned long)(a))
245 #define WRITEBUF(c) \
247 *((char*)UNCACHED(&log_buf[log_start])) = c; \
248 log_start = (log_start + 1) & LOG_BUF_MASK; \
253 static int ns16550_uart_write(cfe_devctx_t
*ctx
, iocb_buffer_t
*buffer
)
255 ns16550_uart_t
*softc
= ctx
->dev_softc
;
259 bptr
= buffer
->buf_ptr
;
260 blen
= buffer
->buf_length
;
261 while ((blen
> 0) && (READCSR(softc
,R_UART_LSR
) & LSR_TXRDY
)) {
265 WRITECSR(softc
,R_UART_DATA
, *bptr
++);
267 #if CFG_SIM && CFG_SIM_CONSOLE
269 #endif /* CFG_SIM && CFG_SIM_CONSOLE */
272 buffer
->buf_retlen
= buffer
->buf_length
- blen
;
276 static int ns16550_uart_ioctl(cfe_devctx_t
*ctx
, iocb_buffer_t
*buffer
)
278 ns16550_uart_t
*softc
= ctx
->dev_softc
;
280 unsigned int *info
= (unsigned int *) buffer
->buf_ptr
;
282 switch ((int)buffer
->buf_ioctlcmd
) {
283 case IOCTL_SERIAL_GETSPEED
:
284 *info
= softc
->uart_speed
;
286 case IOCTL_SERIAL_SETSPEED
:
287 softc
->uart_speed
= *info
;
290 case IOCTL_SERIAL_GETFLOW
:
291 *info
= softc
->uart_flowcontrol
;
293 case IOCTL_SERIAL_SETFLOW
:
294 softc
->uart_flowcontrol
= *info
;
295 ns16550_uart_setflow(softc
);
304 static int ns16550_uart_close(cfe_devctx_t
*ctx
)
306 ns16550_uart_t
*softc
= ctx
->dev_softc
;
308 WRITECSR(softc
,R_UART_MCR
,0);