From: John Jacques <john.jacq...@lsi.com> Added code to support the UART on the 3500 board
Signed-off-by: John Jacques <john.jacq...@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 -- _______________________________________________ linux-yocto mailing list linux-yocto@yoctoproject.org https://lists.yoctoproject.org/listinfo/linux-yocto