[linux-yocto] [PATCH 126/161] arch/powerpc: Updated the UART Driver to Support 3500
Cristian Bercaru
cristian.bercaru at windriver.com
Thu May 21 12:21:48 PDT 2015
From: John Jacques <john.jacques at lsi.com>
Added code to support the UART on the 3500 board
Signed-off-by: John Jacques <john.jacques at lsi.com>
---
drivers/tty/serial/lsi_acp_serial.c | 94 +++++++++++++++++++----------------
1 file changed, 51 insertions(+), 43 deletions(-)
diff --git a/drivers/tty/serial/lsi_acp_serial.c b/drivers/tty/serial/lsi_acp_serial.c
index a41eab2..0f9f7ce 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;
}
@@ -1135,6 +1098,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