[linux-yocto] [PATCH 22/28] arch/powerpc: Updated the UART Driver to Support 3500

Charlie Paul cpaul.windriver at gmail.com
Fri May 2 12:16:59 PDT 2014


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