forked from Imagelibrary/rtems
libchip: Add support for NS16550 with FDR
This commit is contained in:
@@ -93,7 +93,7 @@ console_tbl Console_Configuration_Ports [] = {
|
|||||||
#ifdef LPC24XX_CONFIG_CONSOLE
|
#ifdef LPC24XX_CONFIG_CONSOLE
|
||||||
{
|
{
|
||||||
.sDeviceName = "/dev/ttyS0",
|
.sDeviceName = "/dev/ttyS0",
|
||||||
.deviceType = SERIAL_NS16550,
|
.deviceType = SERIAL_NS16550_WITH_FDR,
|
||||||
.pDeviceFns = &ns16550_fns,
|
.pDeviceFns = &ns16550_fns,
|
||||||
.deviceProbe = NULL,
|
.deviceProbe = NULL,
|
||||||
.pDeviceFlow = NULL,
|
.pDeviceFlow = NULL,
|
||||||
@@ -114,7 +114,7 @@ console_tbl Console_Configuration_Ports [] = {
|
|||||||
#ifdef LPC24XX_CONFIG_UART_1
|
#ifdef LPC24XX_CONFIG_UART_1
|
||||||
{
|
{
|
||||||
.sDeviceName = "/dev/ttyS1",
|
.sDeviceName = "/dev/ttyS1",
|
||||||
.deviceType = SERIAL_NS16550,
|
.deviceType = SERIAL_NS16550_WITH_FDR,
|
||||||
.pDeviceFns = &ns16550_fns,
|
.pDeviceFns = &ns16550_fns,
|
||||||
.deviceProbe = lpc24xx_uart_probe_1,
|
.deviceProbe = lpc24xx_uart_probe_1,
|
||||||
.pDeviceFlow = NULL,
|
.pDeviceFlow = NULL,
|
||||||
@@ -135,7 +135,7 @@ console_tbl Console_Configuration_Ports [] = {
|
|||||||
#ifdef LPC24XX_CONFIG_UART_2
|
#ifdef LPC24XX_CONFIG_UART_2
|
||||||
{
|
{
|
||||||
.sDeviceName = "/dev/ttyS2",
|
.sDeviceName = "/dev/ttyS2",
|
||||||
.deviceType = SERIAL_NS16550,
|
.deviceType = SERIAL_NS16550_WITH_FDR,
|
||||||
.pDeviceFns = &ns16550_fns,
|
.pDeviceFns = &ns16550_fns,
|
||||||
.deviceProbe = lpc24xx_uart_probe_2,
|
.deviceProbe = lpc24xx_uart_probe_2,
|
||||||
.pDeviceFlow = NULL,
|
.pDeviceFlow = NULL,
|
||||||
@@ -156,7 +156,7 @@ console_tbl Console_Configuration_Ports [] = {
|
|||||||
#ifdef LPC24XX_CONFIG_UART_3
|
#ifdef LPC24XX_CONFIG_UART_3
|
||||||
{
|
{
|
||||||
.sDeviceName = "/dev/ttyS3",
|
.sDeviceName = "/dev/ttyS3",
|
||||||
.deviceType = SERIAL_NS16550,
|
.deviceType = SERIAL_NS16550_WITH_FDR,
|
||||||
.pDeviceFns = &ns16550_fns,
|
.pDeviceFns = &ns16550_fns,
|
||||||
.deviceProbe = lpc24xx_uart_probe_3,
|
.deviceProbe = lpc24xx_uart_probe_3,
|
||||||
.pDeviceFlow = NULL,
|
.pDeviceFlow = NULL,
|
||||||
|
|||||||
@@ -95,6 +95,40 @@ console_fns ns16550_fns_polled = {
|
|||||||
false /* deviceOutputUsesInterrupts */
|
false /* deviceOutputUsesInterrupts */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static uint32_t NS16550_GetBaudDivisor(const console_tbl *c, uint32_t baud)
|
||||||
|
{
|
||||||
|
uint32_t clock = c->ulClock;
|
||||||
|
uint32_t baudDivisor = (clock != 0 ? clock : 115200) / (baud * 16);
|
||||||
|
|
||||||
|
if (c->deviceType == SERIAL_NS16550_WITH_FDR) {
|
||||||
|
uint32_t fractionalDivider = 0x10;
|
||||||
|
uint32_t err = baud;
|
||||||
|
uint32_t mulVal;
|
||||||
|
uint32_t divAddVal;
|
||||||
|
|
||||||
|
clock /= 16 * baudDivisor;
|
||||||
|
for (mulVal = 1; mulVal < 16; ++mulVal) {
|
||||||
|
for (divAddVal = 0; divAddVal < mulVal; ++divAddVal) {
|
||||||
|
uint32_t actual = (mulVal * clock) / (mulVal + divAddVal);
|
||||||
|
uint32_t newErr = actual > baud ? actual - baud : baud - actual;
|
||||||
|
|
||||||
|
if (newErr < err) {
|
||||||
|
err = newErr;
|
||||||
|
fractionalDivider = (mulVal << 4) | divAddVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(*c->setRegister)(
|
||||||
|
c->ulCtrlPort1,
|
||||||
|
NS16550_FRACTIONAL_DIVIDER,
|
||||||
|
fractionalDivider
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return baudDivisor;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ns16550_init
|
* ns16550_init
|
||||||
*/
|
*/
|
||||||
@@ -133,10 +167,7 @@ NS16550_STATIC void ns16550_init(int minor)
|
|||||||
|
|
||||||
/* Set the divisor latch and set the baud rate. */
|
/* Set the divisor latch and set the baud rate. */
|
||||||
|
|
||||||
ulBaudDivisor = NS16550_Baud(
|
ulBaudDivisor = NS16550_GetBaudDivisor(c, (uintptr_t) c->pDeviceParams);
|
||||||
(uint32_t) c->ulClock,
|
|
||||||
(uint32_t) ((uintptr_t)c->pDeviceParams)
|
|
||||||
);
|
|
||||||
ucDataByte = SP_LINE_DLAB;
|
ucDataByte = SP_LINE_DLAB;
|
||||||
(*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte);
|
(*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte);
|
||||||
|
|
||||||
@@ -413,23 +444,18 @@ NS16550_STATIC int ns16550_set_attributes(
|
|||||||
setRegister_f setReg;
|
setRegister_f setReg;
|
||||||
getRegister_f getReg;
|
getRegister_f getReg;
|
||||||
uint32_t Irql;
|
uint32_t Irql;
|
||||||
|
const console_tbl *c = Console_Port_Tbl [minor];
|
||||||
|
|
||||||
pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
|
pNS16550 = c->ulCtrlPort1;
|
||||||
setReg = Console_Port_Tbl[minor]->setRegister;
|
setReg = c->setRegister;
|
||||||
getReg = Console_Port_Tbl[minor]->getRegister;
|
getReg = c->getRegister;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculate the baud rate divisor
|
* Calculate the baud rate divisor
|
||||||
*/
|
*/
|
||||||
|
|
||||||
baud_requested = t->c_cflag & CBAUD;
|
baud_requested = rtems_termios_baud_to_number(t->c_cflag);
|
||||||
if (!baud_requested)
|
ulBaudDivisor = NS16550_GetBaudDivisor(c, baud_requested);
|
||||||
baud_requested = B9600; /* default to 9600 baud */
|
|
||||||
|
|
||||||
ulBaudDivisor = NS16550_Baud(
|
|
||||||
(uint32_t) Console_Port_Tbl[minor]->ulClock,
|
|
||||||
rtems_termios_baud_to_number(baud_requested)
|
|
||||||
);
|
|
||||||
|
|
||||||
ucLineControl = 0;
|
ucLineControl = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ extern "C" {
|
|||||||
#define NS16550_LINE_STATUS 5
|
#define NS16550_LINE_STATUS 5
|
||||||
#define NS16550_MODEM_STATUS 6
|
#define NS16550_MODEM_STATUS 6
|
||||||
#define NS16550_SCRATCH_PAD 7
|
#define NS16550_SCRATCH_PAD 7
|
||||||
|
#define NS16550_FRACTIONAL_DIVIDER 10
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define serial port interrupt enable register structure.
|
* Define serial port interrupt enable register structure.
|
||||||
@@ -105,13 +106,6 @@ extern "C" {
|
|||||||
#define SEVEN_BITS 0x2 /* seven bits per character */
|
#define SEVEN_BITS 0x2 /* seven bits per character */
|
||||||
#define EIGHT_BITS 0x3 /* eight bits per character */
|
#define EIGHT_BITS 0x3 /* eight bits per character */
|
||||||
|
|
||||||
/*
|
|
||||||
* Line speed divisor definition.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define NS16550_Baud(_clock, _baud_rate) \
|
|
||||||
((((_clock) == 0) ? 115200 : (_clock))/(_baud_rate*16))
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define serial port modem control register structure.
|
* Define serial port modem control register structure.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -104,6 +104,8 @@ typedef struct _console_flow {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
SERIAL_MC68681, /* Motorola MC68681 or Exar 88681 */
|
SERIAL_MC68681, /* Motorola MC68681 or Exar 88681 */
|
||||||
SERIAL_NS16550, /* National Semiconductor NS16550 */
|
SERIAL_NS16550, /* National Semiconductor NS16550 */
|
||||||
|
SERIAL_NS16550_WITH_FDR, /* National Semiconductor NS16550
|
||||||
|
with Fractional Divider Register (FDR) */
|
||||||
SERIAL_Z85C30, /* Zilog Z85C30 */
|
SERIAL_Z85C30, /* Zilog Z85C30 */
|
||||||
SERIAL_CUSTOM /* BSP specific driver */
|
SERIAL_CUSTOM /* BSP specific driver */
|
||||||
} console_devs;
|
} console_devs;
|
||||||
|
|||||||
Reference in New Issue
Block a user