1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * SB1250 UART driver File: dev_sb1250_uart.c
6 * This is a console device driver for the SB1250's on-chip UARTs
8 * Author: Mitch Lichtenberg (mpl@broadcom.com)
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 ********************************************************************* */
52 #include "lib_types.h"
53 #include "lib_malloc.h"
54 #include "lib_printf.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"
65 #undef V_DUART_BAUD_RATE
66 #define V_DUART_BAUD_RATE(x) ((*((uint64_t *) 0xBFC00018)*1000000)/((x)*20)-1)
69 #ifdef SB1250_REFCLK_HZ
70 #undef V_DUART_BAUD_RATE
71 #define V_DUART_BAUD_RATE(x) ((SB1250_REFCLK_HZ)/((x)*20)-1)
74 static void sb1250_uart_probe(cfe_driver_t
*drv
,
75 unsigned long probe_a
, unsigned long probe_b
,
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
= {
97 const cfe_driver_t sb1250_uart
= {
101 &sb1250_uart_dispatch
,
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
;
116 int uart_flowcontrol
;
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
,
131 sb1250_uart_t
*softc
;
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);
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
)
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
;
175 case SERIAL_FLOW_HARDWARE
:
176 mode1val
|= M_DUART_RX_RTS_ENA
;
177 mode2val
|= M_DUART_TX_CTS_ENA
;
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 */
199 SBDUARTWRITE(softc
,uart_oprset
, M_DUART_SET_OPR1
| M_DUART_SET_OPR3
); /* CTS and DTR */
201 sb1250_uart_setflow(softc
);
206 static int sb1250_uart_read(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
)
208 sb1250_uart_t
*softc
= ctx
->dev_softc
;
212 bptr
= buffer
->buf_ptr
;
213 blen
= buffer
->buf_length
;
216 if (!(SBDUARTREAD(softc
,uart_status
) & M_DUART_RX_RDY
)) break;
217 *bptr
++ = (SBDUARTREAD(softc
,uart_rx_hold
) & 0xFF);
221 buffer
->buf_retlen
= buffer
->buf_length
- blen
;
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;
234 static int sb1250_uart_write(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
)
236 sb1250_uart_t
*softc
= ctx
->dev_softc
;
240 bptr
= buffer
->buf_ptr
;
241 blen
= buffer
->buf_length
;
244 if (!(SBDUARTREAD(softc
,uart_status
) & M_DUART_TX_RDY
)) break;
245 SBDUARTWRITE(softc
,uart_tx_hold
,*bptr
++);
249 buffer
->buf_retlen
= buffer
->buf_length
- blen
;
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
;
262 case IOCTL_SERIAL_SETSPEED
:
263 softc
->uart_speed
= *info
;
264 SBDUARTWRITE(softc
,uart_clk_sel
,
265 V_DUART_BAUD_RATE(softc
->uart_speed
));
267 case IOCTL_SERIAL_GETFLOW
:
268 *info
= softc
->uart_flowcontrol
;
270 case IOCTL_SERIAL_SETFLOW
:
271 softc
->uart_flowcontrol
= *info
;
272 sb1250_uart_setflow(softc
);
281 static int sb1250_uart_close(cfe_devctx_t
*ctx
)
283 sb1250_uart_t
*softc
= ctx
->dev_softc
;
285 SBDUARTWRITE(softc
,uart_cmd
, 0);