1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2ad1696f6SAleksey Makarov /*
3ad1696f6SAleksey Makarov * Copyright (c) 2012, Intel Corporation
4ad1696f6SAleksey Makarov * Copyright (c) 2015, Red Hat, Inc.
5ad1696f6SAleksey Makarov * Copyright (c) 2015, 2016 Linaro Ltd.
6ad1696f6SAleksey Makarov */
7ad1696f6SAleksey Makarov
8ad1696f6SAleksey Makarov #define pr_fmt(fmt) "ACPI: SPCR: " fmt
9ad1696f6SAleksey Makarov
10ad1696f6SAleksey Makarov #include <linux/acpi.h>
11ad1696f6SAleksey Makarov #include <linux/console.h>
12ad1696f6SAleksey Makarov #include <linux/kernel.h>
13ad1696f6SAleksey Makarov #include <linux/serial_core.h>
14ad1696f6SAleksey Makarov
15d8a4995bSChristopher Covington /*
1637ef38f3STimur Tabi * Erratum 44 for QDF2432v1 and QDF2400v1 SoCs describes the BUSY bit as
1737ef38f3STimur Tabi * occasionally getting stuck as 1. To avoid the potential for a hang, check
1837ef38f3STimur Tabi * TXFE == 0 instead of BUSY == 1. This may not be suitable for all UART
1937ef38f3STimur Tabi * implementations, so only do so if an affected platform is detected in
200231d000SPrarit Bhargava * acpi_parse_spcr().
2137ef38f3STimur Tabi */
2237ef38f3STimur Tabi bool qdf2400_e44_present;
2337ef38f3STimur Tabi EXPORT_SYMBOL(qdf2400_e44_present);
2437ef38f3STimur Tabi
2537ef38f3STimur Tabi /*
26d8a4995bSChristopher Covington * Some Qualcomm Datacenter Technologies SoCs have a defective UART BUSY bit.
27603fadf3SBjorn Helgaas * Detect them by examining the OEM fields in the SPCR header, similar to PCI
28d8a4995bSChristopher Covington * quirk detection in pci_mcfg.c.
29d8a4995bSChristopher Covington */
qdf2400_erratum_44_present(struct acpi_table_header * h)30d8a4995bSChristopher Covington static bool qdf2400_erratum_44_present(struct acpi_table_header *h)
31d8a4995bSChristopher Covington {
32d8a4995bSChristopher Covington if (memcmp(h->oem_id, "QCOM ", ACPI_OEM_ID_SIZE))
33d8a4995bSChristopher Covington return false;
34d8a4995bSChristopher Covington
35d8a4995bSChristopher Covington if (!memcmp(h->oem_table_id, "QDF2432 ", ACPI_OEM_TABLE_ID_SIZE))
36d8a4995bSChristopher Covington return true;
37d8a4995bSChristopher Covington
38d8a4995bSChristopher Covington if (!memcmp(h->oem_table_id, "QDF2400 ", ACPI_OEM_TABLE_ID_SIZE) &&
39542ed784STimur Tabi h->oem_revision == 1)
40d8a4995bSChristopher Covington return true;
41d8a4995bSChristopher Covington
42d8a4995bSChristopher Covington return false;
43d8a4995bSChristopher Covington }
44d8a4995bSChristopher Covington
4579a64832SLoc Ho /*
4679a64832SLoc Ho * APM X-Gene v1 and v2 UART hardware is an 16550 like device but has its
4779a64832SLoc Ho * register aligned to 32-bit. In addition, the BIOS also encoded the
4879a64832SLoc Ho * access width to be 8 bits. This function detects this errata condition.
4979a64832SLoc Ho */
xgene_8250_erratum_present(struct acpi_table_spcr * tb)5079a64832SLoc Ho static bool xgene_8250_erratum_present(struct acpi_table_spcr *tb)
5179a64832SLoc Ho {
52dee82bc1SGraeme Gregory bool xgene_8250 = false;
53dee82bc1SGraeme Gregory
5479a64832SLoc Ho if (tb->interface_type != ACPI_DBG2_16550_COMPATIBLE)
5579a64832SLoc Ho return false;
5679a64832SLoc Ho
57dee82bc1SGraeme Gregory if (memcmp(tb->header.oem_id, "APMC0D", ACPI_OEM_ID_SIZE) &&
58dee82bc1SGraeme Gregory memcmp(tb->header.oem_id, "HPE ", ACPI_OEM_ID_SIZE))
5979a64832SLoc Ho return false;
6079a64832SLoc Ho
6179a64832SLoc Ho if (!memcmp(tb->header.oem_table_id, "XGENESPC",
6279a64832SLoc Ho ACPI_OEM_TABLE_ID_SIZE) && tb->header.oem_revision == 0)
63dee82bc1SGraeme Gregory xgene_8250 = true;
6479a64832SLoc Ho
65dee82bc1SGraeme Gregory if (!memcmp(tb->header.oem_table_id, "ProLiant",
66dee82bc1SGraeme Gregory ACPI_OEM_TABLE_ID_SIZE) && tb->header.oem_revision == 1)
67dee82bc1SGraeme Gregory xgene_8250 = true;
68dee82bc1SGraeme Gregory
69dee82bc1SGraeme Gregory return xgene_8250;
7079a64832SLoc Ho }
7179a64832SLoc Ho
72ad1696f6SAleksey Makarov /**
730231d000SPrarit Bhargava * acpi_parse_spcr() - parse ACPI SPCR table and add preferred console
740231d000SPrarit Bhargava * @enable_earlycon: set up earlycon for the console specified by the table
750231d000SPrarit Bhargava * @enable_console: setup the console specified by the table.
76ad1696f6SAleksey Makarov *
77ad1696f6SAleksey Makarov * For the architectures with support for ACPI, CONFIG_ACPI_SPCR_TABLE may be
78ad1696f6SAleksey Makarov * defined to parse ACPI SPCR table. As a result of the parsing preferred
790231d000SPrarit Bhargava * console is registered and if @enable_earlycon is true, earlycon is set up.
800231d000SPrarit Bhargava * If @enable_console is true the system console is also configured.
81ad1696f6SAleksey Makarov *
82ad1696f6SAleksey Makarov * When CONFIG_ACPI_SPCR_TABLE is defined, this function should be called
83183b8021SMasahiro Yamada * from arch initialization code as soon as the DT/ACPI decision is made.
84ad1696f6SAleksey Makarov */
acpi_parse_spcr(bool enable_earlycon,bool enable_console)850231d000SPrarit Bhargava int __init acpi_parse_spcr(bool enable_earlycon, bool enable_console)
86ad1696f6SAleksey Makarov {
87ad1696f6SAleksey Makarov static char opts[64];
88ad1696f6SAleksey Makarov struct acpi_table_spcr *table;
89ad1696f6SAleksey Makarov acpi_status status;
90ad1696f6SAleksey Makarov char *uart;
91ad1696f6SAleksey Makarov char *iotype;
92ad1696f6SAleksey Makarov int baud_rate;
93ad1696f6SAleksey Makarov int err;
94ad1696f6SAleksey Makarov
95ad1696f6SAleksey Makarov if (acpi_disabled)
96ad1696f6SAleksey Makarov return -ENODEV;
97ad1696f6SAleksey Makarov
98*dcf0c2e0SAndy Shevchenko status = acpi_get_table(ACPI_SIG_SPCR, 0, (struct acpi_table_header **)&table);
99ad1696f6SAleksey Makarov if (ACPI_FAILURE(status))
100ad1696f6SAleksey Makarov return -ENOENT;
101ad1696f6SAleksey Makarov
1020231d000SPrarit Bhargava if (table->header.revision < 2)
1030231d000SPrarit Bhargava pr_info("SPCR table version %d\n", table->header.revision);
104ad1696f6SAleksey Makarov
1052bece493SLoc Ho if (table->serial_port.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
106ee3fe99fSMark Langsdorf u32 bit_width = table->serial_port.access_width;
107ee3fe99fSMark Langsdorf
108ee3fe99fSMark Langsdorf if (bit_width > ACPI_ACCESS_BIT_MAX) {
109da30a34aSAndy Shevchenko pr_err(FW_BUG "Unacceptable wide SPCR Access Width. Defaulting to byte size\n");
110ee3fe99fSMark Langsdorf bit_width = ACPI_ACCESS_BIT_DEFAULT;
111ee3fe99fSMark Langsdorf }
112ee3fe99fSMark Langsdorf switch (ACPI_ACCESS_BIT_WIDTH((bit_width))) {
1132bece493SLoc Ho default:
114da30a34aSAndy Shevchenko pr_err(FW_BUG "Unexpected SPCR Access Width. Defaulting to byte size\n");
11557d2dd4bSGustavo A. R. Silva fallthrough;
1164eebedd8SLv Zheng case 8:
1172bece493SLoc Ho iotype = "mmio";
1182bece493SLoc Ho break;
1194eebedd8SLv Zheng case 16:
1202bece493SLoc Ho iotype = "mmio16";
1212bece493SLoc Ho break;
1224eebedd8SLv Zheng case 32:
1232bece493SLoc Ho iotype = "mmio32";
1242bece493SLoc Ho break;
1252bece493SLoc Ho }
1262bece493SLoc Ho } else
1272bece493SLoc Ho iotype = "io";
128ad1696f6SAleksey Makarov
129ad1696f6SAleksey Makarov switch (table->interface_type) {
130ad1696f6SAleksey Makarov case ACPI_DBG2_ARM_SBSA_32BIT:
131ad1696f6SAleksey Makarov iotype = "mmio32";
13257d2dd4bSGustavo A. R. Silva fallthrough;
133ad1696f6SAleksey Makarov case ACPI_DBG2_ARM_PL011:
134ad1696f6SAleksey Makarov case ACPI_DBG2_ARM_SBSA_GENERIC:
135ad1696f6SAleksey Makarov case ACPI_DBG2_BCM2835:
136ad1696f6SAleksey Makarov uart = "pl011";
137ad1696f6SAleksey Makarov break;
138ad1696f6SAleksey Makarov case ACPI_DBG2_16550_COMPATIBLE:
139ad1696f6SAleksey Makarov case ACPI_DBG2_16550_SUBSET:
1402aaea6a1SMarcin Wojtas case ACPI_DBG2_16550_WITH_GAS:
1413a506ca2SJeff Brasen case ACPI_DBG2_16550_NVIDIA:
142ad1696f6SAleksey Makarov uart = "uart";
143ad1696f6SAleksey Makarov break;
144ad1696f6SAleksey Makarov default:
145ad1696f6SAleksey Makarov err = -ENOENT;
146ad1696f6SAleksey Makarov goto done;
147ad1696f6SAleksey Makarov }
148ad1696f6SAleksey Makarov
149ad1696f6SAleksey Makarov switch (table->baud_rate) {
150b413b1abSAndy Shevchenko case 0:
151b413b1abSAndy Shevchenko /*
152b413b1abSAndy Shevchenko * SPCR 1.04 defines 0 as a preconfigured state of UART.
153b413b1abSAndy Shevchenko * Assume firmware or bootloader configures console correctly.
154b413b1abSAndy Shevchenko */
155b413b1abSAndy Shevchenko baud_rate = 0;
156b413b1abSAndy Shevchenko break;
157ad1696f6SAleksey Makarov case 3:
158ad1696f6SAleksey Makarov baud_rate = 9600;
159ad1696f6SAleksey Makarov break;
160ad1696f6SAleksey Makarov case 4:
161ad1696f6SAleksey Makarov baud_rate = 19200;
162ad1696f6SAleksey Makarov break;
163ad1696f6SAleksey Makarov case 6:
164ad1696f6SAleksey Makarov baud_rate = 57600;
165ad1696f6SAleksey Makarov break;
166ad1696f6SAleksey Makarov case 7:
167ad1696f6SAleksey Makarov baud_rate = 115200;
168ad1696f6SAleksey Makarov break;
169ad1696f6SAleksey Makarov default:
170ad1696f6SAleksey Makarov err = -ENOENT;
171ad1696f6SAleksey Makarov goto done;
172ad1696f6SAleksey Makarov }
173ad1696f6SAleksey Makarov
17437ef38f3STimur Tabi /*
17537ef38f3STimur Tabi * If the E44 erratum is required, then we need to tell the pl011
17637ef38f3STimur Tabi * driver to implement the work-around.
17737ef38f3STimur Tabi *
17837ef38f3STimur Tabi * The global variable is used by the probe function when it
17937ef38f3STimur Tabi * creates the UARTs, whether or not they're used as a console.
18037ef38f3STimur Tabi *
18137ef38f3STimur Tabi * If the user specifies "traditional" earlycon, the qdf2400_e44
18237ef38f3STimur Tabi * console name matches the EARLYCON_DECLARE() statement, and
18337ef38f3STimur Tabi * SPCR is not used. Parameter "earlycon" is false.
18437ef38f3STimur Tabi *
18537ef38f3STimur Tabi * If the user specifies "SPCR" earlycon, then we need to update
18637ef38f3STimur Tabi * the console name so that it also says "qdf2400_e44". Parameter
18737ef38f3STimur Tabi * "earlycon" is true.
18837ef38f3STimur Tabi *
18937ef38f3STimur Tabi * For consistency, if we change the console name, then we do it
19037ef38f3STimur Tabi * for everyone, not just earlycon.
19137ef38f3STimur Tabi */
19237ef38f3STimur Tabi if (qdf2400_erratum_44_present(&table->header)) {
19337ef38f3STimur Tabi qdf2400_e44_present = true;
1940231d000SPrarit Bhargava if (enable_earlycon)
195d8a4995bSChristopher Covington uart = "qdf2400_e44";
19637ef38f3STimur Tabi }
19737ef38f3STimur Tabi
19803c3876fSGraeme Gregory if (xgene_8250_erratum_present(table)) {
19979a64832SLoc Ho iotype = "mmio32";
200d8a4995bSChristopher Covington
201*dcf0c2e0SAndy Shevchenko /*
202*dcf0c2e0SAndy Shevchenko * For xgene v1 and v2 we don't know the clock rate of the
20303c3876fSGraeme Gregory * UART so don't attempt to change to the baud rate state
20403c3876fSGraeme Gregory * in the table because driver cannot calculate the dividers
20503c3876fSGraeme Gregory */
206b413b1abSAndy Shevchenko baud_rate = 0;
207b413b1abSAndy Shevchenko }
208b413b1abSAndy Shevchenko
209b413b1abSAndy Shevchenko if (!baud_rate) {
21003c3876fSGraeme Gregory snprintf(opts, sizeof(opts), "%s,%s,0x%llx", uart, iotype,
21103c3876fSGraeme Gregory table->serial_port.address);
21203c3876fSGraeme Gregory } else {
213ad1696f6SAleksey Makarov snprintf(opts, sizeof(opts), "%s,%s,0x%llx,%d", uart, iotype,
214ad1696f6SAleksey Makarov table->serial_port.address, baud_rate);
21503c3876fSGraeme Gregory }
216ad1696f6SAleksey Makarov
217ad1696f6SAleksey Makarov pr_info("console: %s\n", opts);
218ad1696f6SAleksey Makarov
2190231d000SPrarit Bhargava if (enable_earlycon)
220ad1696f6SAleksey Makarov setup_earlycon(opts);
221ad1696f6SAleksey Makarov
2220231d000SPrarit Bhargava if (enable_console)
223ad1696f6SAleksey Makarov err = add_preferred_console(uart, 0, opts + strlen(uart) + 1);
2240231d000SPrarit Bhargava else
2250231d000SPrarit Bhargava err = 0;
226ad1696f6SAleksey Makarov done:
2276b11d1d6SLv Zheng acpi_put_table((struct acpi_table_header *)table);
228ad1696f6SAleksey Makarov return err;
229ad1696f6SAleksey Makarov }
230