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:
parent
39be40ce06
commit
d3a9184773
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue