Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d3a91847 authored by Masahiro Yamada's avatar Masahiro Yamada Committed by Greg Kroah-Hartman
Browse files

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: default avatarMasahiro Yamada <yamada.masahiro@socionext.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 39be40ce
Loading
Loading
Loading
Loading
+16 −6
Original line number Original line Diff line number Diff line
@@ -29,12 +29,13 @@
 *   - MMIO32 (regshift = 2)
 *   - MMIO32 (regshift = 2)
 *   - FCR is not at 2, but 3
 *   - FCR is not at 2, but 3
 *   - LCR and MCR are not at 3 and 4, they share 4
 *   - 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
 *   - Divisor latch at 9, no divisor latch access bit
 */
 */


#define UNIPHIER_UART_REGSHIFT		2
#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))
#define UNIPHIER_UART_CHAR_FCR		(3 << (UNIPHIER_UART_REGSHIFT))
/* bit[15:8] = LCR, bit[7:0] = MCR */
/* bit[15:8] = LCR, bit[7:0] = MCR */
#define UNIPHIER_UART_LCR_MCR		(4 << (UNIPHIER_UART_REGSHIFT))
#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.
 * 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)
static unsigned int uniphier_serial_in(struct uart_port *p, int offset)
{
{
	unsigned int valshift = 0;
	unsigned int valshift = 0;


	switch (offset) {
	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:
	case UART_LCR:
		valshift = 8;
		valshift = 8;
		/* fall through */
		/* 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
	 * The return value must be masked with 0xff because some registers
	 * in the same register that must be accessed by 32-bit write/read.
	 * 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.
	 * 8 or 16 bit access to this hardware result in unexpected behavior.
	 */
	 */
	return (readl(p->membase + offset) >> valshift) & 0xff;
	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)
static void uniphier_serial_out(struct uart_port *p, int offset, int value)
{
{
	unsigned int valshift = 0;
	unsigned int valshift = 0;
	bool normal = true;
	bool normal = false;


	switch (offset) {
	switch (offset) {
	case UART_SCR:
		/* No SCR for this hardware.  Use CHAR as a scratch register */
		valshift = 8;
		/* fall through */
	case UART_FCR:
	case UART_FCR:
		offset = UNIPHIER_UART_CHAR_FCR;
		offset = UNIPHIER_UART_CHAR_FCR;
		break;
		break;
@@ -114,10 +124,10 @@ static void uniphier_serial_out(struct uart_port *p, int offset, int value)
		/* fall through */
		/* fall through */
	case UART_MCR:
	case UART_MCR:
		offset = UNIPHIER_UART_LCR_MCR;
		offset = UNIPHIER_UART_LCR_MCR;
		normal = false;
		break;
		break;
	default:
	default:
		offset <<= UNIPHIER_UART_REGSHIFT;
		offset <<= UNIPHIER_UART_REGSHIFT;
		normal = true;
		break;
		break;
	}
	}