Skip to content

Commit

Permalink
omap: Serial: Define register access modes in LCR
Browse files Browse the repository at this point in the history
Access to some registers depends on register access mode
Three different modes are available for OMAP (at least)
• Operational mode     LCR_REG[7] = 0x0
• Configuration mode A LCR_REG[7] = 0x1 and LCR_REG[7:0]! = 0xBF
• Configuration mode B LCR_REG[7] = 0x1 and LCR_REG[7:0]  = 0xBF

Define access modes and remove redefinitions and magic numbers
in serial drivers (and later in bluetooth driver).

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
Acked-by: Govindraj.R <govindraj.raja@ti.com>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Tony Lindgren <tony@atomide.com>
  • Loading branch information
Andrei Emeltchenko authored and Tony Lindgren committed Nov 30, 2010
1 parent 498cb95 commit 662b083
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 45 deletions.
12 changes: 6 additions & 6 deletions arch/arm/mach-omap2/serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,15 +219,15 @@ static void omap_uart_save_context(struct omap_uart_state *uart)
return;

lcr = serial_read_reg(uart, UART_LCR);
serial_write_reg(uart, UART_LCR, 0xBF);
serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
uart->dll = serial_read_reg(uart, UART_DLL);
uart->dlh = serial_read_reg(uart, UART_DLM);
serial_write_reg(uart, UART_LCR, lcr);
uart->ier = serial_read_reg(uart, UART_IER);
uart->sysc = serial_read_reg(uart, UART_OMAP_SYSC);
uart->scr = serial_read_reg(uart, UART_OMAP_SCR);
uart->wer = serial_read_reg(uart, UART_OMAP_WER);
serial_write_reg(uart, UART_LCR, 0x80);
serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_A);
uart->mcr = serial_read_reg(uart, UART_MCR);
serial_write_reg(uart, UART_LCR, lcr);

Expand All @@ -251,19 +251,19 @@ static void omap_uart_restore_context(struct omap_uart_state *uart)
else
serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);

serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */
serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
efr = serial_read_reg(uart, UART_EFR);
serial_write_reg(uart, UART_EFR, UART_EFR_ECB);
serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */
serial_write_reg(uart, UART_IER, 0x0);
serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */
serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
serial_write_reg(uart, UART_DLL, uart->dll);
serial_write_reg(uart, UART_DLM, uart->dlh);
serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */
serial_write_reg(uart, UART_IER, uart->ier);
serial_write_reg(uart, UART_LCR, 0x80);
serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_A);
serial_write_reg(uart, UART_MCR, uart->mcr);
serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */
serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
serial_write_reg(uart, UART_EFR, efr);
serial_write_reg(uart, UART_LCR, UART_LCR_WLEN8);
serial_write_reg(uart, UART_OMAP_SCR, uart->scr);
Expand Down
9 changes: 0 additions & 9 deletions arch/arm/plat-omap/include/plat/omap-serial.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,6 @@

#define OMAP_MODE13X_SPEED 230400

/*
* LCR = 0XBF: Switch to Configuration Mode B.
* In configuration mode b allow access
* to EFR,DLL,DLH.
* Reference OMAP TRM Chapter 17
* Section: 1.4.3 Mode Selection
*/
#define OMAP_UART_LCR_CONF_MDB 0XBF

/* WER = 0x7F
* Enable module level wakeup in WER reg
*/
Expand Down
26 changes: 13 additions & 13 deletions drivers/serial/8250.c
Original file line number Diff line number Diff line change
Expand Up @@ -653,13 +653,13 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
{
if (p->capabilities & UART_CAP_SLEEP) {
if (p->capabilities & UART_CAP_EFR) {
serial_outp(p, UART_LCR, 0xBF);
serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_B);
serial_outp(p, UART_EFR, UART_EFR_ECB);
serial_outp(p, UART_LCR, 0);
}
serial_outp(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
if (p->capabilities & UART_CAP_EFR) {
serial_outp(p, UART_LCR, 0xBF);
serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_B);
serial_outp(p, UART_EFR, 0);
serial_outp(p, UART_LCR, 0);
}
Expand Down Expand Up @@ -752,7 +752,7 @@ static int size_fifo(struct uart_8250_port *up)
serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
serial_outp(up, UART_MCR, UART_MCR_LOOP);
serial_outp(up, UART_LCR, UART_LCR_DLAB);
serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
old_dl = serial_dl_read(up);
serial_dl_write(up, 0x0001);
serial_outp(up, UART_LCR, 0x03);
Expand All @@ -764,7 +764,7 @@ static int size_fifo(struct uart_8250_port *up)
serial_inp(up, UART_RX);
serial_outp(up, UART_FCR, old_fcr);
serial_outp(up, UART_MCR, old_mcr);
serial_outp(up, UART_LCR, UART_LCR_DLAB);
serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
serial_dl_write(up, old_dl);
serial_outp(up, UART_LCR, old_lcr);

Expand All @@ -782,7 +782,7 @@ static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p)
unsigned int id;

old_lcr = serial_inp(p, UART_LCR);
serial_outp(p, UART_LCR, UART_LCR_DLAB);
serial_outp(p, UART_LCR, UART_LCR_CONF_MODE_A);

old_dll = serial_inp(p, UART_DLL);
old_dlm = serial_inp(p, UART_DLM);
Expand Down Expand Up @@ -836,7 +836,7 @@ static void autoconfig_has_efr(struct uart_8250_port *up)
* recommended for new designs).
*/
up->acr = 0;
serial_out(up, UART_LCR, 0xBF);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
serial_out(up, UART_EFR, UART_EFR_ECB);
serial_out(up, UART_LCR, 0x00);
id1 = serial_icr_read(up, UART_ID1);
Expand Down Expand Up @@ -945,7 +945,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
* Check for presence of the EFR when DLAB is set.
* Only ST16C650V1 UARTs pass this test.
*/
serial_outp(up, UART_LCR, UART_LCR_DLAB);
serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
if (serial_in(up, UART_EFR) == 0) {
serial_outp(up, UART_EFR, 0xA8);
if (serial_in(up, UART_EFR) != 0) {
Expand All @@ -963,7 +963,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
* Maybe it requires 0xbf to be written to the LCR.
* (other ST16C650V2 UARTs, TI16C752A, etc)
*/
serial_outp(up, UART_LCR, 0xBF);
serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) {
DEBUG_AUTOCONF("EFRv2 ");
autoconfig_has_efr(up);
Expand Down Expand Up @@ -1024,7 +1024,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
status1 = serial_in(up, UART_IIR) >> 5;
serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
serial_outp(up, UART_LCR, UART_LCR_DLAB);
serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_A);
serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
status2 = serial_in(up, UART_IIR) >> 5;
serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
Expand Down Expand Up @@ -1183,7 +1183,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
* We also initialise the EFR (if any) to zero for later. The
* EFR occupies the same register location as the FCR and IIR.
*/
serial_outp(up, UART_LCR, 0xBF);
serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
serial_outp(up, UART_EFR, 0);
serial_outp(up, UART_LCR, 0);

Expand Down Expand Up @@ -1952,7 +1952,7 @@ static int serial8250_startup(struct uart_port *port)
if (up->port.type == PORT_16C950) {
/* Wake up and initialize UART */
up->acr = 0;
serial_outp(up, UART_LCR, 0xBF);
serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
serial_outp(up, UART_EFR, UART_EFR_ECB);
serial_outp(up, UART_IER, 0);
serial_outp(up, UART_LCR, 0);
Expand Down Expand Up @@ -2002,7 +2002,7 @@ static int serial8250_startup(struct uart_port *port)
if (up->port.type == PORT_16850) {
unsigned char fctr;

serial_outp(up, UART_LCR, 0xbf);
serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);

fctr = serial_inp(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX);
serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_RX);
Expand Down Expand Up @@ -2363,7 +2363,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
if (termios->c_cflag & CRTSCTS)
efr |= UART_EFR_CTS;

serial_outp(up, UART_LCR, 0xBF);
serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B);
serial_outp(up, UART_EFR, efr);
}

Expand Down
34 changes: 17 additions & 17 deletions drivers/serial/omap-serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,7 @@ serial_omap_configure_xonxoff
unsigned char efr = 0;

up->lcr = serial_in(up, UART_LCR);
serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
up->efr = serial_in(up, UART_EFR);
serial_out(up, UART_EFR, up->efr & ~UART_EFR_ECB);

Expand Down Expand Up @@ -598,7 +598,7 @@ serial_omap_configure_xonxoff
efr |= OMAP_UART_SW_RX;

serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
serial_out(up, UART_LCR, UART_LCR_DLAB);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);

up->mcr = serial_in(up, UART_MCR);

Expand All @@ -612,14 +612,14 @@ serial_omap_configure_xonxoff
up->mcr |= UART_MCR_XONANY;

serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
/* Enable special char function UARTi.EFR_REG[5] and
* load the new software flow control mode IXON or IXOFF
* and restore the UARTi.EFR_REG[4] ENHANCED_EN value.
*/
serial_out(up, UART_EFR, efr | UART_EFR_SCD);
serial_out(up, UART_LCR, UART_LCR_DLAB);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);

serial_out(up, UART_MCR, up->mcr & ~UART_MCR_TCRTLR);
serial_out(up, UART_LCR, up->lcr);
Expand Down Expand Up @@ -724,22 +724,22 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
* baud clock is not running
* DLL_REG and DLH_REG set to 0.
*/
serial_out(up, UART_LCR, UART_LCR_DLAB);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
serial_out(up, UART_DLL, 0);
serial_out(up, UART_DLM, 0);
serial_out(up, UART_LCR, 0);

serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);

up->efr = serial_in(up, UART_EFR);
serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);

serial_out(up, UART_LCR, UART_LCR_DLAB);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
up->mcr = serial_in(up, UART_MCR);
serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
/* FIFO ENABLE, DMA MODE */
serial_out(up, UART_FCR, up->fcr);
serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);

if (up->use_dma) {
serial_out(up, UART_TI752_TLR, 0);
Expand All @@ -748,27 +748,27 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
}

serial_out(up, UART_EFR, up->efr);
serial_out(up, UART_LCR, UART_LCR_DLAB);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
serial_out(up, UART_MCR, up->mcr);

/* Protocol, Baud Rate, and Interrupt Settings */

serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);

up->efr = serial_in(up, UART_EFR);
serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);

serial_out(up, UART_LCR, 0);
serial_out(up, UART_IER, 0);
serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);

serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */
serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */

serial_out(up, UART_LCR, 0);
serial_out(up, UART_IER, up->ier);
serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);

serial_out(up, UART_EFR, up->efr);
serial_out(up, UART_LCR, cval);
Expand All @@ -782,18 +782,18 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,

if (termios->c_cflag & CRTSCTS) {
efr |= (UART_EFR_CTS | UART_EFR_RTS);
serial_out(up, UART_LCR, UART_LCR_DLAB);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);

up->mcr = serial_in(up, UART_MCR);
serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);

serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
up->efr = serial_in(up, UART_EFR);
serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);

serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
serial_out(up, UART_EFR, efr); /* Enable AUTORTS and AUTOCTS */
serial_out(up, UART_LCR, UART_LCR_DLAB);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
serial_out(up, UART_MCR, up->mcr | UART_MCR_RTS);
serial_out(up, UART_LCR, cval);
}
Expand All @@ -815,13 +815,13 @@ serial_omap_pm(struct uart_port *port, unsigned int state,
unsigned char efr;

dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->pdev->id);
serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
efr = serial_in(up, UART_EFR);
serial_out(up, UART_EFR, efr | UART_EFR_ECB);
serial_out(up, UART_LCR, 0);

serial_out(up, UART_IER, (state != 0) ? UART_IERX_SLEEP : 0);
serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
serial_out(up, UART_EFR, efr);
serial_out(up, UART_LCR, 0);
/* Enable module level wake up */
Expand Down
7 changes: 7 additions & 0 deletions include/linux/serial_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,13 @@
#define UART_LCR_WLEN7 0x02 /* Wordlength: 7 bits */
#define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */

/*
* Access to some registers depends on register access / configuration
* mode.
*/
#define UART_LCR_CONF_MODE_A UART_LCR_DLAB /* Configutation mode A */
#define UART_LCR_CONF_MODE_B 0xBF /* Configutation mode B */

#define UART_MCR 4 /* Out: Modem Control Register */
#define UART_MCR_CLKSEL 0x80 /* Divide clock by 4 (TI16C752, EFR[4]=1) */
#define UART_MCR_TCRTLR 0x40 /* Access TCR/TLR (TI16C752, EFR[4]=1) */
Expand Down

0 comments on commit 662b083

Please sign in to comment.