]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/acpi/spcr.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc
[karo-tx-linux.git] / drivers / acpi / spcr.c
1 /*
2  * Copyright (c) 2012, Intel Corporation
3  * Copyright (c) 2015, Red Hat, Inc.
4  * Copyright (c) 2015, 2016 Linaro Ltd.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  */
11
12 #define pr_fmt(fmt) "ACPI: SPCR: " fmt
13
14 #include <linux/acpi.h>
15 #include <linux/console.h>
16 #include <linux/kernel.h>
17 #include <linux/serial_core.h>
18
19 /*
20  * Some Qualcomm Datacenter Technologies SoCs have a defective UART BUSY bit.
21  * Detect them by examining the OEM fields in the SPCR header, similiar to PCI
22  * quirk detection in pci_mcfg.c.
23  */
24 static bool qdf2400_erratum_44_present(struct acpi_table_header *h)
25 {
26         if (memcmp(h->oem_id, "QCOM  ", ACPI_OEM_ID_SIZE))
27                 return false;
28
29         if (!memcmp(h->oem_table_id, "QDF2432 ", ACPI_OEM_TABLE_ID_SIZE))
30                 return true;
31
32         if (!memcmp(h->oem_table_id, "QDF2400 ", ACPI_OEM_TABLE_ID_SIZE) &&
33                         h->oem_revision == 1)
34                 return true;
35
36         return false;
37 }
38
39 /*
40  * APM X-Gene v1 and v2 UART hardware is an 16550 like device but has its
41  * register aligned to 32-bit. In addition, the BIOS also encoded the
42  * access width to be 8 bits. This function detects this errata condition.
43  */
44 static bool xgene_8250_erratum_present(struct acpi_table_spcr *tb)
45 {
46         if (tb->interface_type != ACPI_DBG2_16550_COMPATIBLE)
47                 return false;
48
49         if (memcmp(tb->header.oem_id, "APMC0D", ACPI_OEM_ID_SIZE))
50                 return false;
51
52         if (!memcmp(tb->header.oem_table_id, "XGENESPC",
53             ACPI_OEM_TABLE_ID_SIZE) && tb->header.oem_revision == 0)
54                 return true;
55
56         return false;
57 }
58
59 /**
60  * parse_spcr() - parse ACPI SPCR table and add preferred console
61  *
62  * @earlycon: set up earlycon for the console specified by the table
63  *
64  * For the architectures with support for ACPI, CONFIG_ACPI_SPCR_TABLE may be
65  * defined to parse ACPI SPCR table.  As a result of the parsing preferred
66  * console is registered and if @earlycon is true, earlycon is set up.
67  *
68  * When CONFIG_ACPI_SPCR_TABLE is defined, this function should be called
69  * from arch initialization code as soon as the DT/ACPI decision is made.
70  *
71  */
72 int __init parse_spcr(bool earlycon)
73 {
74         static char opts[64];
75         struct acpi_table_spcr *table;
76         acpi_status status;
77         char *uart;
78         char *iotype;
79         int baud_rate;
80         int err;
81
82         if (acpi_disabled)
83                 return -ENODEV;
84
85         status = acpi_get_table(ACPI_SIG_SPCR, 0,
86                                 (struct acpi_table_header **)&table);
87
88         if (ACPI_FAILURE(status))
89                 return -ENOENT;
90
91         if (table->header.revision < 2) {
92                 err = -ENOENT;
93                 pr_err("wrong table version\n");
94                 goto done;
95         }
96
97         if (table->serial_port.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
98                 switch (table->serial_port.access_width) {
99                 default:
100                         pr_err("Unexpected SPCR Access Width.  Defaulting to byte size\n");
101                 case ACPI_ACCESS_SIZE_BYTE:
102                         iotype = "mmio";
103                         break;
104                 case ACPI_ACCESS_SIZE_WORD:
105                         iotype = "mmio16";
106                         break;
107                 case ACPI_ACCESS_SIZE_DWORD:
108                         iotype = "mmio32";
109                         break;
110                 }
111         } else
112                 iotype = "io";
113
114         switch (table->interface_type) {
115         case ACPI_DBG2_ARM_SBSA_32BIT:
116                 iotype = "mmio32";
117                 /* fall through */
118         case ACPI_DBG2_ARM_PL011:
119         case ACPI_DBG2_ARM_SBSA_GENERIC:
120         case ACPI_DBG2_BCM2835:
121                 uart = "pl011";
122                 break;
123         case ACPI_DBG2_16550_COMPATIBLE:
124         case ACPI_DBG2_16550_SUBSET:
125                 uart = "uart";
126                 break;
127         default:
128                 err = -ENOENT;
129                 goto done;
130         }
131
132         switch (table->baud_rate) {
133         case 3:
134                 baud_rate = 9600;
135                 break;
136         case 4:
137                 baud_rate = 19200;
138                 break;
139         case 6:
140                 baud_rate = 57600;
141                 break;
142         case 7:
143                 baud_rate = 115200;
144                 break;
145         default:
146                 err = -ENOENT;
147                 goto done;
148         }
149
150         if (qdf2400_erratum_44_present(&table->header))
151                 uart = "qdf2400_e44";
152         if (xgene_8250_erratum_present(table))
153                 iotype = "mmio32";
154
155         snprintf(opts, sizeof(opts), "%s,%s,0x%llx,%d", uart, iotype,
156                  table->serial_port.address, baud_rate);
157
158         pr_info("console: %s\n", opts);
159
160         if (earlycon)
161                 setup_earlycon(opts);
162
163         err = add_preferred_console(uart, 0, opts + strlen(uart) + 1);
164
165 done:
166         acpi_put_table((struct acpi_table_header *)table);
167         return err;
168 }