[linux-yocto] [PATCH 37/39] LSI drivers/tty: Axxia Serial Driver Update
Charlie Paul
cpaul.windriver at gmail.com
Tue Apr 22 13:59:49 PDT 2014
From: John Jacques <john.jacques at lsi.com>
Updated to work with the 3500 variant.
Signed-off-by: John Jacques <john.jacques at lsi.com>
---
drivers/tty/serial/lsi_acp_serial.c | 103 ++++++++++++++++++++---------------
1 file changed, 58 insertions(+), 45 deletions(-)
diff --git a/drivers/tty/serial/lsi_acp_serial.c b/drivers/tty/serial/lsi_acp_serial.c
index f9676ca..c03f29b 100644
--- a/drivers/tty/serial/lsi_acp_serial.c
+++ b/drivers/tty/serial/lsi_acp_serial.c
@@ -81,9 +81,8 @@ struct uart_acp_port {
unsigned int interrupt_mask;
unsigned int old_status;
void *timer_base;
- unsigned long divisor;
- unsigned char ibrd;
- unsigned char fbrd;
+ unsigned short ibrd;
+ unsigned short fbrd;
};
/*
@@ -119,25 +118,10 @@ struct uart_acp_port {
static int
get_clock_stuff(struct uart_acp_port *port, int baud_rate)
{
- unsigned long divisor;
unsigned long ibrd;
unsigned long fbrd;
- /*
- Since the IBDR (integer part of the baud rate
- divisor) is a 16 bit quatity, find the minimum load
- value that will let the IBDR/FBDR result in the
- desired baud rate.
- */
-
- if (1000000 < per_clock) {
- divisor = per_clock / 25000000;
- ibrd = 25000000 / (16 * baud_rate);
- } else {
- /* Emulation is much slower... */
- divisor = per_clock / 3250000;
- ibrd = 3250000 / (16 * baud_rate);
- }
+ ibrd = per_clock / (16 * baud_rate);
/*
* The following formula is from the ARM document (ARM DDI 0183E).
@@ -164,36 +148,15 @@ get_clock_stuff(struct uart_acp_port *port, int baud_rate)
* 2 * (16 * baud_rate)
*/
- port->port.uartclk = (per_clock / divisor);
+ port->port.uartclk = per_clock;
fbrd = port->port.uartclk % (16 * baud_rate);
fbrd *= 128;
fbrd += (16 * baud_rate);
fbrd /= (2 * (16 * baud_rate));
- port->divisor = (divisor - 1);
- port->ibrd = (unsigned char) ibrd;
- port->fbrd = (unsigned char) fbrd;
-
- if (port->divisor != in_le32(port->timer_base + TIMER_LOAD)) {
- while (0 ==
- (in_le32((const volatile unsigned *)
- (port->port.membase + UART01x_FR)) &
- UART011_FR_TXFE))
- ;
-
- while (0 !=
- (in_le32((const volatile unsigned *)
- (port->port.membase + UART01x_FR)) &
- UART01x_FR_BUSY))
- ;
-
- out_le32((port->timer_base + TIMER_CONTROL), 0);
- out_le32((port->timer_base + TIMER_LOAD), port->divisor);
- out_le32((port->timer_base + TIMER_CONTROL),
- (TIMER_CONTROL_ENABLE |
- TIMER_CONTROL_MODE));
- }
+ port->ibrd = (unsigned short) ibrd;
+ port->fbrd = (unsigned short) fbrd;
return 0;
}
@@ -461,7 +424,7 @@ unsigned int acp_serial_get_mctrl(struct uart_port *port)
#define TIOCMBIT(uartbit, tiocmbit) do { \
if (status & (uartbit)) \
result |= (tiocmbit); \
-} while (0);
+} while (0)
TIOCMBIT(UART01x_FR_DCD, TIOCM_CAR);
TIOCMBIT(UART01x_FR_DSR, TIOCM_DSR);
TIOCMBIT(UART01x_FR_CTS, TIOCM_CTS);
@@ -482,7 +445,7 @@ void acp_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
cr |= uartbit; \
else \
cr &= ~uartbit; \
-} while (0);
+} while (0)
TIOCMBIT(TIOCM_RTS, UART011_CR_RTS);
TIOCMBIT(TIOCM_DTR, UART011_CR_DTR);
@@ -766,8 +729,13 @@ acp_serial_set_termios(struct uart_port *port, struct ktermios *termios,
out_le32((u32 *)(uap->port.membase + UART011_CR), 0);
/* Set baud rate */
+#if 1
out_le32((u32 *)(uap->port.membase + UART011_FBRD), uap->fbrd);
out_le32((u32 *)(uap->port.membase + UART011_IBRD), uap->ibrd);
+#else
+ out_le32((u32 *)(uap->port.membase + UART011_FBRD), 0x13);
+ out_le32((u32 *)(uap->port.membase + UART011_IBRD), 0x598);
+#endif
/*
* ----------v----------v----------v----------v-----
@@ -1134,6 +1102,51 @@ acp_serial_add_ports(struct uart_driver *driver)
ret = -ENOMEM;
}
+ np = of_find_compatible_node(NULL, NULL, "lsi,acp3500");
+
+ if (NULL == np) {
+ unsigned long divisor;
+
+ /*
+ In the 3500 case, the peripheral clock is connected
+ directly to the UART. If this isn't 3500, set up
+ the second timer (which is in between the peripheral
+ clock and the UART) and adjust per_clock
+ accordingly.
+ */
+
+ if (1000000 < per_clock) {
+ divisor = per_clock / 25000000;
+ per_clock = 25000000;
+ } else {
+ /* Emulation is much slower... */
+ divisor = per_clock / 3250000;
+ per_clock = 3250000;
+ }
+
+ --divisor;
+
+ if (divisor != in_le32(uap->timer_base + TIMER_LOAD)) {
+ while (0 ==
+ (in_le32((const volatile unsigned *)
+ (uap->port.membase + UART01x_FR)) &
+ UART011_FR_TXFE))
+ ;
+
+ while (0 !=
+ (in_le32((const volatile unsigned *)
+ (uap->port.membase + UART01x_FR)) &
+ UART01x_FR_BUSY))
+ ;
+
+ out_le32((uap->timer_base + TIMER_CONTROL), 0);
+ out_le32((uap->timer_base + TIMER_LOAD), divisor);
+ out_le32((uap->timer_base + TIMER_CONTROL),
+ (TIMER_CONTROL_ENABLE |
+ TIMER_CONTROL_MODE));
+ }
+ }
+
dt_baud_rate = baud_rate;
uap->port.iotype = UPIO_MEM;
uap->port.fifosize = 16;
--
1.7.9.5
More information about the linux-yocto
mailing list