⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dev_sb1250_uart.c

📁 一个很好的嵌入式linux平台下的bootloader
💻 C
字号:
/*  *********************************************************************    *  Broadcom Common Firmware Environment (CFE)    *      *  SB1250 UART driver			File: dev_sb1250_uart.c    *      *  This is a console device driver for the SB1250's on-chip UARTs    *      *  Author:  Mitch Lichtenberg    *      *********************************************************************      *    *  Copyright 2000,2001,2002,2003    *  Broadcom Corporation. All rights reserved.    *      *  This software is furnished under license and may be used and     *  copied only in accordance with the following terms and     *  conditions.  Subject to these conditions, you may download,     *  copy, install, use, modify and distribute modified or unmodified     *  copies of this software in source and/or binary form.  No title     *  or ownership is transferred hereby.    *      *  1) Any source code used, modified or distributed must reproduce     *     and retain this copyright notice and list of conditions     *     as they appear in the source file.    *      *  2) No right is granted to use any trade name, trademark, or     *     logo of Broadcom Corporation.  The "Broadcom Corporation"     *     name may not be used to endorse or promote products derived     *     from this software without the prior written permission of     *     Broadcom Corporation.    *      *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR     *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT     *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN     *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES     *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY     *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF     *     THE POSSIBILITY OF SUCH DAMAGE.    ********************************************************************* */#undef SIBYTE_HDR_FEATURES	/* we want all constants here */#include "cfe.h"#include "sbmips.h"#include "sb1250_defs.h"#include "sb1250_regs.h"#include "sb1250_uart.h"#ifdef _MAGICWID_#undef V_DUART_BAUD_RATE#define V_DUART_BAUD_RATE(x) ((*((uint64_t *) 0xBFC00018)*1000000)/((x)*20)-1)#endif#ifdef SB1250_REFCLK_HZ#undef V_DUART_BAUD_RATE#define V_DUART_BAUD_RATE(x) ((SB1250_REFCLK_HZ)/((x)*20)-1)#endifstatic void sb1250_uart_probe(cfe_driver_t *drv,			      unsigned long probe_a, unsigned long probe_b, 			      void *probe_ptr);static int sb1250_uart_open(cfe_devctx_t *ctx);static int sb1250_uart_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);static int sb1250_uart_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);static int sb1250_uart_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);static int sb1250_uart_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);static int sb1250_uart_close(cfe_devctx_t *ctx);const static cfe_devdisp_t sb1250_uart_dispatch = {    sb1250_uart_open,    sb1250_uart_read,    sb1250_uart_inpstat,    sb1250_uart_write,    sb1250_uart_ioctl,    sb1250_uart_close,	    NULL,    NULL};const cfe_driver_t sb1250_uart = {    "SiByte DUART",    "uart",    CFE_DEV_SERIAL,    &sb1250_uart_dispatch,    sb1250_uart_probe};typedef struct sb1250_uart_s {    unsigned long uart_mode_reg_1;    unsigned long uart_mode_reg_2;    unsigned long uart_clk_sel;    unsigned long uart_cmd;    unsigned long uart_imr;    unsigned long uart_status;    unsigned long uart_tx_hold;    unsigned long uart_rx_hold;    unsigned long uart_oprset;    int uart_speed;    int uart_flowcontrol;    int uart_channel;} sb1250_uart_t;/* * Errata 1956 workaround: Do an access to the mode_reg_1 before * each CSR access work around a synchronization problem. */#define SBDUARTWRITE(softc,reg,val) \     (SBREADCSR(softc->uart_mode_reg_1),SBWRITECSR(softc->reg,val))#define SBDUARTREAD(softc,reg) \     (SBREADCSR(softc->uart_mode_reg_1),SBREADCSR(softc->reg))static void sb1250_uart_probe(cfe_driver_t *drv,			      unsigned long probe_a, unsigned long probe_b, 			      void *probe_ptr){    sb1250_uart_t *softc;    char descr[80];    /*      * probe_a is the DUART base address.     * probe_b is the channel-number-within-duart (0 or 1)     * probe_ptr is unused.     */    softc = (sb1250_uart_t *) KMALLOC(sizeof(sb1250_uart_t),0);    if (softc) {	softc->uart_mode_reg_1 = probe_a + R_DUART_CHANREG(probe_b,R_DUART_MODE_REG_1);	softc->uart_mode_reg_2 = probe_a + R_DUART_CHANREG(probe_b,R_DUART_MODE_REG_2);	softc->uart_clk_sel    = probe_a + R_DUART_CHANREG(probe_b,R_DUART_CLK_SEL);	softc->uart_cmd        = probe_a + R_DUART_CHANREG(probe_b,R_DUART_CMD);	softc->uart_status     = probe_a + R_DUART_CHANREG(probe_b,R_DUART_STATUS);	softc->uart_tx_hold    = probe_a + R_DUART_CHANREG(probe_b,R_DUART_TX_HOLD);	softc->uart_rx_hold    = probe_a + R_DUART_CHANREG(probe_b,R_DUART_RX_HOLD);		softc->uart_imr        = probe_a + R_DUART_IMRREG(probe_b);	softc->uart_oprset     = probe_a + R_DUART_SET_OPR;	xsprintf(descr,"%s at 0x%X channel %d",drv->drv_description,probe_a,probe_b);	softc->uart_speed = CFG_SERIAL_BAUD_RATE;	softc->uart_flowcontrol = SERIAL_FLOW_NONE;    	cfe_attach(drv,softc,NULL,descr);	}}static void sb1250_uart_setflow(sb1250_uart_t *softc){    uint64_t mode1val;    uint64_t mode2val;    mode1val = SBDUARTREAD(softc,uart_mode_reg_1);    mode2val = SBDUARTREAD(softc,uart_mode_reg_2);    switch (softc->uart_flowcontrol) {	case SERIAL_FLOW_NONE:	case SERIAL_FLOW_SOFTWARE:	    mode1val &= ~M_DUART_RX_RTS_ENA;	    mode2val &= ~M_DUART_TX_CTS_ENA;	    break;	case SERIAL_FLOW_HARDWARE:	    mode1val |= M_DUART_RX_RTS_ENA;	    mode2val |= M_DUART_TX_CTS_ENA;	    break;	}    SBDUARTWRITE(softc,uart_mode_reg_1,mode1val);    SBDUARTWRITE(softc,uart_mode_reg_2,mode2val);}static int sb1250_uart_open(cfe_devctx_t *ctx){    sb1250_uart_t *softc = ctx->dev_softc;    SBDUARTWRITE(softc,uart_mode_reg_1,V_DUART_BITS_PER_CHAR_8 | V_DUART_PARITY_MODE_NONE);    SBDUARTWRITE(softc,uart_mode_reg_2,M_DUART_STOP_BIT_LEN_1);    SBDUARTWRITE(softc,uart_clk_sel,   V_DUART_BAUD_RATE(CFG_SERIAL_BAUD_RATE));    SBDUARTWRITE(softc,uart_imr,       0);		/* DISABLE all interrupts */    SBDUARTWRITE(softc,uart_cmd,       M_DUART_RX_EN | M_DUART_TX_EN);    if (softc->uart_channel == 0) {	SBDUARTWRITE(softc,uart_oprset,    M_DUART_SET_OPR0 | M_DUART_SET_OPR2);	/* CTS and DTR */	}    else {	SBDUARTWRITE(softc,uart_oprset,    M_DUART_SET_OPR1 | M_DUART_SET_OPR3);	/* CTS and DTR */	}    sb1250_uart_setflow(softc);    return 0;}static int sb1250_uart_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer){    sb1250_uart_t *softc = ctx->dev_softc;    unsigned char *bptr;    int blen;    bptr = buffer->buf_ptr;    blen = buffer->buf_length;    while (blen > 0) {	if (!(SBDUARTREAD(softc,uart_status) & M_DUART_RX_RDY)) break;	*bptr++ = (SBDUARTREAD(softc,uart_rx_hold) & 0xFF);	blen--;	}    buffer->buf_retlen = buffer->buf_length - blen;    return 0;}static int sb1250_uart_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat){    sb1250_uart_t *softc = ctx->dev_softc;    inpstat->inp_status = (SBDUARTREAD(softc,uart_status) & M_DUART_RX_RDY) ? 1 : 0;    return 0;}static int sb1250_uart_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer){    sb1250_uart_t *softc = ctx->dev_softc;    unsigned char *bptr;    int blen;    bptr = buffer->buf_ptr;    blen = buffer->buf_length;    while (blen > 0) {#ifndef _VERILOG_	/* If running in simulation, just blast data out without checking */	if (!(SBDUARTREAD(softc,uart_status) & M_DUART_TX_RDY)) break;#endif	SBDUARTWRITE(softc,uart_tx_hold,*bptr++);	blen--;	}    buffer->buf_retlen = buffer->buf_length - blen;    return 0;}static int sb1250_uart_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer) {    sb1250_uart_t *softc = ctx->dev_softc;    unsigned int *info = (unsigned int *) buffer->buf_ptr;    switch ((int)buffer->buf_ioctlcmd) {	case IOCTL_SERIAL_GETSPEED:	    *info = softc->uart_speed;	    break;	case IOCTL_SERIAL_SETSPEED:	    softc->uart_speed = *info;	    SBDUARTWRITE(softc,uart_clk_sel,		       V_DUART_BAUD_RATE(softc->uart_speed));	    break;	case IOCTL_SERIAL_GETFLOW:	    *info = softc->uart_flowcontrol;	    break;	case IOCTL_SERIAL_SETFLOW:	    softc->uart_flowcontrol = *info;	    sb1250_uart_setflow(softc);	    break;	default:	    return -1;	}    return 0;}static int sb1250_uart_close(cfe_devctx_t *ctx){    sb1250_uart_t *softc = ctx->dev_softc;    SBDUARTWRITE(softc,uart_cmd,       0);    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -