serial: 8250_uniphier: use CHAR register for canary to detect power-off

The 8250 core uses the SCR as a canary to discover if the console has
been powered-off.

This hardware does not have SCR at offset 7, but an unused register
CHAR at a different offset.  As long as the character interrupt is
disabled, the register access has no impact, so it is useful as an
alternative scratch register.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Masahiro Yamada 2017-08-08 22:48:42 +09:00 committed by Greg Kroah-Hartman
parent 39be40ce06
commit d3a9184773
1 changed files with 16 additions and 6 deletions

View File

@ -29,12 +29,13 @@
* - MMIO32 (regshift = 2)
* - FCR is not at 2, but 3
* - LCR and MCR are not at 3 and 4, they share 4
* - No SCR (Instead, CHAR can be used as a scratch register)
* - Divisor latch at 9, no divisor latch access bit
*/
#define UNIPHIER_UART_REGSHIFT 2
/* bit[15:8] = CHAR (not used), bit[7:0] = FCR */
/* bit[15:8] = CHAR, bit[7:0] = FCR */
#define UNIPHIER_UART_CHAR_FCR (3 << (UNIPHIER_UART_REGSHIFT))
/* bit[15:8] = LCR, bit[7:0] = MCR */
#define UNIPHIER_UART_LCR_MCR (4 << (UNIPHIER_UART_REGSHIFT))
@ -72,13 +73,18 @@ OF_EARLYCON_DECLARE(uniphier, "socionext,uniphier-uart",
/*
* The register map is slightly different from that of 8250.
* IO callbacks must be overridden for correct access to FCR, LCR, and MCR.
* IO callbacks must be overridden for correct access to FCR, LCR, MCR and SCR.
*/
static unsigned int uniphier_serial_in(struct uart_port *p, int offset)
{
unsigned int valshift = 0;
switch (offset) {
case UART_SCR:
/* No SCR for this hardware. Use CHAR as a scratch register */
valshift = 8;
offset = UNIPHIER_UART_CHAR_FCR;
break;
case UART_LCR:
valshift = 8;
/* fall through */
@ -91,8 +97,8 @@ static unsigned int uniphier_serial_in(struct uart_port *p, int offset)
}
/*
* The return value must be masked with 0xff because LCR and MCR reside
* in the same register that must be accessed by 32-bit write/read.
* The return value must be masked with 0xff because some registers
* share the same offset that must be accessed by 32-bit write/read.
* 8 or 16 bit access to this hardware result in unexpected behavior.
*/
return (readl(p->membase + offset) >> valshift) & 0xff;
@ -101,9 +107,13 @@ static unsigned int uniphier_serial_in(struct uart_port *p, int offset)
static void uniphier_serial_out(struct uart_port *p, int offset, int value)
{
unsigned int valshift = 0;
bool normal = true;
bool normal = false;
switch (offset) {
case UART_SCR:
/* No SCR for this hardware. Use CHAR as a scratch register */
valshift = 8;
/* fall through */
case UART_FCR:
offset = UNIPHIER_UART_CHAR_FCR;
break;
@ -114,10 +124,10 @@ static void uniphier_serial_out(struct uart_port *p, int offset, int value)
/* fall through */
case UART_MCR:
offset = UNIPHIER_UART_LCR_MCR;
normal = false;
break;
default:
offset <<= UNIPHIER_UART_REGSHIFT;
normal = true;
break;
}