📄 dw_16550.c
字号:
/*******************************************************************************
* Copyright 2002, GALILEO TECHNOLOGY, LTD. *
* THIS CODE CONTAINS CONFIDENTIAL INFORMATION OF MARVELL. *
* NO RIGHTS ARE GRANTED HEREIN UNDER ANY PATENT, MASK WORK RIGHT OR COPYRIGHT *
* OF MARVELL OR ANY THIRD PARTY. MARVELL RESERVES THE RIGHT AT ITS SOLE *
* DISCRETION TO REQUEST THAT THIS CODE BE IMMEDIATELY RETURNED TO MARVELL. *
* THIS CODE IS PROVIDED "AS IS". MARVELL MAKES NO WARRANTIES, EXPRESSED, *
* IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, COMPLETENESS OR PERFORMANCE. *
* *
* MARVELL COMPRISES MARVELL TECHNOLOGY GROUP LTD. (MTGL) AND ITS SUBSIDIARIES, *
* MARVELL INTERNATIONAL LTD. (MIL), MARVELL TECHNOLOGY, INC. (MTI), MARVELL *
* SEMICONDUCTOR, INC. (MSI), MARVELL ASIA PTE LTD. (MAPL), MARVELL JAPAN K.K. *
* (MJKK), GALILEO TECHNOLOGY LTD. (GTL) AND GALILEO TECHNOLOGY, INC. (GTI). *
********************************************************************************
* DW_16550.c - functions for DW_16550 UART.
*
* DESCRIPTION:
* This is the unit driver for the DW_16550 UART - SIU unit.
* The DW_16550 is a parameterizable, synthesizable, and programmable
* Universal Asynchronous Receiver/Transmitter (UART), modeled after the
* industry standard 16550.
* The DW_16550 UART contains registers to control the word size, baud
* rate, parity generation/checking, and interrupt generation.
*
* For calculating the baudrate we use the xtal - field in the SW data
* structure (DW_16550_CHAN). Xtal default value is zero and it must be
* changed by the user. Make sure that you insert a non-zero xtal.
*
* You can use this driver in two phases, the initialization phase
* (dw16550InitChannel) and the operation phase (dw16550StartChannel).
* During the initialization phase, the default values are entered in the
* DW_16550_CHAN struct. During the operation phase, the values assigned
* during the initialization phase are written to the appropriate
* registers.
* An intermediate phase can be added after the initialization phase, in
* which the default values can be changed.
* Note: The initialization phase is not necessary to start this driver.
* The software struct can be started manually with the desired values.
* The function dw16550StartChannel must be called in order to work with
* this driver.
*
*******************************************************************************/
#include "DW_16550.h"
/*******************************************************************************
* dw16550InitChannel - initialize DW_16550 UART.
*
* DESCRIPTION:
* This routine performs initialization of the DW_16550 UART
* channel struct with default values.
*
* INPUT:
* *pChan - Pointer to DW_16550 struct describing channel.
*
* OUTPUT:
* Set DW_16550 struct with default values.
*
* RETURN: N/A
*
* COMMENTS:
* After calling to this function you must call to function
* dw16550StartChannel which put the struct default values into the
* relevant registers.
*
*******************************************************************************/
void dw16550InitChannel(DW_16550_CHAN * pChan)
{
pChan->lcr = DEFAULT_LCR_VALUE;
pChan->xtal = DEFAULT_XTAL_VALUE;
pChan->ier = DEFAULT_IER_VALUE;
}
/*******************************************************************************
*
* dw16550StartChannel - Start UART channel with relevant values.
*
* DESCRIPTION:
* The function takes values from DW_16550_CHAN struct and writes to the
* appropriate registers.
* For calculating the baud rate divisor the function calls
* dw16550SetBaudrate.
* INPUT:
* *pChan - Pointer to DW_16550 struct describing channel.
* baudrate - value of baudrate.
*
* OUTPUT:
* Writes registers' value' from DW_16550_CHAN struct to the actual
* registers.
*
* RETURN:
* False for an invalid baud rate, or true on success.
* COMMENTS:
* This function must to be called to enable working with DW_16550 UART.
*
*******************************************************************************/
bool dw16550StartChannel (DW_16550_CHAN *pChan, unsigned int baudrate)
{
bool status; /* status to return */
/* Reset/Enable the FIFOs */
DW_16550_REG_WRITE(pChan, FCR, FCR_RXCLR | FCR_TXCLR | FCR_EN);
DW_16550_REG_WRITE(pChan, IER, pChan->ier);
DW_16550_REG_WRITE(pChan, LCR, pChan->lcr);
status = dw16550SetBaudrate(pChan,baudrate);
return status;
}
/*******************************************************************************
* dw16550SetBaudrate - Set baud rate of DW_16550 UART.
*
* DESCRIPTION:
* This function calculates the baud rate divisor and updates the divisor
* value in the DLL and DLH registers.
* Baudrate divisor must be non-zero and must fit in a 16-bit register.
* INPUT:
* *pChan - Pointer to DW_16550 struct describing channel.
* baudrate - value of baudrate.
*
* OUTPUT:
* pChan->lcr - changed to enable access to divisor latches.
*
* RETURN:
* False for an invalid baud rate, or true on success.
*
* COMMENTS:
* NOne.
*
*******************************************************************************/
bool dw16550SetBaudrate(DW_16550_CHAN * pChan, unsigned int baudrate)
{
unsigned int divisor;
unsigned int brdReal;
unsigned int brdDelta;
if(pChan->xtal <= 0)
return false; /* Clock frequency invalid */
divisor = pChan->xtal/(16*baudrate); /* calculate baudrate divisor */
if ((divisor < 1) || (divisor > 0xFFFF))
return false; /* baud rae out of range */
brdReal = ((pChan->xtal)/(16*divisor));
brdDelta = brdReal - baudrate;
/* Checking for maximum 1% of error in baudrate */
if (((brdDelta*100)/baudrate) != 0)
return false;
/* Enable access to the divisor latches by setting DLAB in LCR. */
DW_16550_REG_WRITE(pChan, LCR , (LCR_DLAB) | (pChan->lcr));
/* Set divisor latches. */
DW_16550_REG_WRITE(pChan, DLL, divisor);
DW_16550_REG_WRITE(pChan, DLH, divisor >> 8);
/* Disable the access to the divisor latches */
DW_16550_REG_WRITE(pChan, LCR, pChan->lcr);
return true;
}
/*******************************************************************************
* dw16550SetMode - Set Interrupt or polling mode.
*
* DESCRIPTION:
* This function writes to the IER register. It enables or disables the
* interrupts as defined by the user.
* INPUT:
* *pChan - Pointer to DW_16550 struct describing channel.
* channelMode - Interrupt or polling mode. See typdef enum CHAN_MODE.
*
* OUTPUT:
* Writes registers' value' from DW_16550_CHAN struct into the actual
* registers.
*
* RETURN:
* False for an invalid CHAN_MODE or true otherwise.
* COMMENTS:
* NOne.
*
*******************************************************************************/
bool dw16550SetMode (DW_16550_CHAN *pChan,CHAN_MODE channelMode)
{
/* Checking for invalid CHAN_MODE */
if ((channelMode != CHAN_MODE_POLL) && (channelMode != CHAN_MODE_INT))
return false;
if (channelMode == CHAN_MODE_INT)
/* Enable appropriate interrupts */
DW_16550_REG_WRITE(pChan,IER,pChan->ier|IER_ERBFI|IER_ETHREI);
else
/* Disable the interrupts */
DW_16550_REG_WRITE(pChan, IER, 0);
/* Make a copy of IER to DW_16550 struct */
pChan->ier = DW_16550_REGREAD(pChan,IER);
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -