blob: 3c607e5ab62551c326faf0b987fd1a3add136af9 [file] [log] [blame]
Angel Pons0612b272020-04-05 15:46:56 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Furquan Shaikha8198eb2017-08-04 16:12:19 -07003
Furquan Shaikh76cedd22020-05-02 10:24:23 -07004#include <acpi/acpi.h>
Subrata Banikafa07f72018-05-24 12:21:06 +05305#include <cbmem.h>
6#include <console/uart.h>
Aamir Bohra83f7bae2017-04-26 19:30:41 +05307#include <device/device.h>
8#include <device/pci.h>
Aamir Bohra01d75f42017-03-30 20:12:21 +05309#include <device/pci_def.h>
Aamir Bohra83f7bae2017-04-26 19:30:41 +053010#include <device/pci_ids.h>
Furquan Shaikha8198eb2017-08-04 16:12:19 -070011#include <device/pci_ops.h>
Aamir Bohra01d75f42017-03-30 20:12:21 +053012#include <intelblocks/lpss.h>
13#include <intelblocks/uart.h>
Subrata Banikafa07f72018-05-24 12:21:06 +053014#include <soc/pci_devs.h>
15#include <soc/iomap.h>
16#include <soc/nvs.h>
Aamir Bohra01d75f42017-03-30 20:12:21 +053017
Furquan Shaikha8198eb2017-08-04 16:12:19 -070018#define UART_PCI_ENABLE (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER)
Subrata Banikafa07f72018-05-24 12:21:06 +053019#define UART_CONSOLE_INVALID_INDEX 0xFF
20
21extern const struct uart_gpio_pad_config uart_gpio_pads[];
22extern const int uart_max_index;
Furquan Shaikha8198eb2017-08-04 16:12:19 -070023
Usha P5e59a822019-08-09 18:42:00 +053024static void uart_lpss_init(const struct device *dev, uintptr_t baseaddr)
Furquan Shaikh3406dd62017-08-04 15:58:26 -070025{
Usha P5e59a822019-08-09 18:42:00 +053026 /* Ensure controller is in D0 state */
27 lpss_set_power_state(dev, STATE_D0);
28
Furquan Shaikh3406dd62017-08-04 15:58:26 -070029 /* Take UART out of reset */
30 lpss_reset_release(baseaddr);
31
32 /* Set M and N divisor inputs and enable clock */
33 lpss_clk_update(baseaddr, CONFIG_SOC_INTEL_COMMON_LPSS_UART_CLK_M_VAL,
34 CONFIG_SOC_INTEL_COMMON_LPSS_UART_CLK_N_VAL);
35}
36
Nico Huber62ddc492019-05-29 18:39:31 +020037#if CONFIG(INTEL_LPSS_UART_FOR_CONSOLE)
Subrata Banikafa07f72018-05-24 12:21:06 +053038uintptr_t uart_platform_base(int idx)
Aamir Bohra01d75f42017-03-30 20:12:21 +053039{
Nico Huberce8eebd2019-05-29 18:33:35 +020040 if (idx == CONFIG_UART_FOR_CONSOLE)
Nico Huber99954182019-05-29 23:33:06 +020041 return CONFIG_CONSOLE_UART_BASE_ADDRESS;
Nico Huberce8eebd2019-05-29 18:33:35 +020042 return 0;
Subrata Banikafa07f72018-05-24 12:21:06 +053043}
44#endif
45
46static int uart_get_valid_index(void)
47{
48 int index;
49
50 for (index = 0; index < uart_max_index; index++) {
51 if (uart_gpio_pads[index].console_index ==
52 CONFIG_UART_FOR_CONSOLE)
53 return index;
54 }
55 /* For valid index, code should not reach here */
56 return UART_CONSOLE_INVALID_INDEX;
57}
58
Aamir Bohra17cfba62019-07-25 20:56:54 +053059void uart_common_init(const struct device *device, uintptr_t baseaddr)
Subrata Banikafa07f72018-05-24 12:21:06 +053060{
61#if defined(__SIMPLE_DEVICE__)
Aamir Bohra17cfba62019-07-25 20:56:54 +053062 pci_devfn_t dev = PCI_BDF(device);
Subrata Banikafa07f72018-05-24 12:21:06 +053063#else
Aamir Bohra17cfba62019-07-25 20:56:54 +053064 const struct device *dev = device;
Subrata Banikafa07f72018-05-24 12:21:06 +053065#endif
Subrata Banikafa07f72018-05-24 12:21:06 +053066
Aamir Bohra01d75f42017-03-30 20:12:21 +053067 /* Set UART base address */
68 pci_write_config32(dev, PCI_BASE_ADDRESS_0, baseaddr);
69
70 /* Enable memory access and bus master */
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +020071 pci_write_config16(dev, PCI_COMMAND, UART_PCI_ENABLE);
Aamir Bohra01d75f42017-03-30 20:12:21 +053072
Usha P5e59a822019-08-09 18:42:00 +053073 uart_lpss_init(device, baseaddr);
Furquan Shaikha8198eb2017-08-04 16:12:19 -070074}
Aamir Bohra01d75f42017-03-30 20:12:21 +053075
Aamir Bohra17cfba62019-07-25 20:56:54 +053076const struct device *uart_get_device(void)
Furquan Shaikha8198eb2017-08-04 16:12:19 -070077{
78 /*
Nico Hubera96e66a2018-11-11 02:51:14 +010079 * This function will get called even if INTEL_LPSS_UART_FOR_CONSOLE
80 * config option is not selected.
81 * By default return NULL in this case to avoid compilation errors.
Furquan Shaikha8198eb2017-08-04 16:12:19 -070082 */
Julius Wernercd49cce2019-03-05 16:53:33 -080083 if (!CONFIG(INTEL_LPSS_UART_FOR_CONSOLE))
Subrata Banikafa07f72018-05-24 12:21:06 +053084 return NULL;
85
86 int console_index = uart_get_valid_index();
87
88 if (console_index != UART_CONSOLE_INVALID_INDEX)
89 return soc_uart_console_to_device(CONFIG_UART_FOR_CONSOLE);
90 else
91 return NULL;
Furquan Shaikha8198eb2017-08-04 16:12:19 -070092}
93
Subrata Banikafa07f72018-05-24 12:21:06 +053094bool uart_is_controller_initialized(void)
Furquan Shaikha8198eb2017-08-04 16:12:19 -070095{
Furquan Shaikha8198eb2017-08-04 16:12:19 -070096 uintptr_t base;
Aamir Bohra17cfba62019-07-25 20:56:54 +053097 const struct device *dev_uart = uart_get_device();
98
99 if (!dev_uart)
100 return false;
Furquan Shaikha8198eb2017-08-04 16:12:19 -0700101
Subrata Banikafa07f72018-05-24 12:21:06 +0530102#if defined(__SIMPLE_DEVICE__)
Aamir Bohra17cfba62019-07-25 20:56:54 +0530103 pci_devfn_t dev = PCI_BDF(dev_uart);
Subrata Banikafa07f72018-05-24 12:21:06 +0530104#else
Aamir Bohra17cfba62019-07-25 20:56:54 +0530105 const struct device *dev = dev_uart;
Subrata Banikafa07f72018-05-24 12:21:06 +0530106#endif
Furquan Shaikha8198eb2017-08-04 16:12:19 -0700107
108 base = pci_read_config32(dev, PCI_BASE_ADDRESS_0) & ~0xFFF;
109 if (!base)
110 return false;
111
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +0200112 if ((pci_read_config16(dev, PCI_COMMAND) & UART_PCI_ENABLE)
Furquan Shaikha8198eb2017-08-04 16:12:19 -0700113 != UART_PCI_ENABLE)
114 return false;
115
116 return !lpss_is_controller_in_reset(base);
Aamir Bohra01d75f42017-03-30 20:12:21 +0530117}
Aamir Bohra83f7bae2017-04-26 19:30:41 +0530118
Subrata Banikafa07f72018-05-24 12:21:06 +0530119static void uart_configure_gpio_pads(void)
Aamir Bohra83f7bae2017-04-26 19:30:41 +0530120{
Subrata Banikafa07f72018-05-24 12:21:06 +0530121 int index = uart_get_valid_index();
122
123 if (index != UART_CONSOLE_INVALID_INDEX)
124 gpio_configure_pads(uart_gpio_pads[index].gpios,
125 MAX_GPIO_PAD_PER_UART);
Aamir Bohra83f7bae2017-04-26 19:30:41 +0530126}
127
Subrata Banikafa07f72018-05-24 12:21:06 +0530128void uart_bootblock_init(void)
Furquan Shaikha8198eb2017-08-04 16:12:19 -0700129{
Aamir Bohra17cfba62019-07-25 20:56:54 +0530130 const struct device *dev_uart;
131
132 dev_uart = uart_get_device();
133
134 if (!dev_uart)
135 return;
136
Subrata Banikafa07f72018-05-24 12:21:06 +0530137 /* Program UART BAR0, command, reset and clock register */
Aamir Bohra17cfba62019-07-25 20:56:54 +0530138 uart_common_init(dev_uart, CONFIG_CONSOLE_UART_BASE_ADDRESS);
Subrata Banikafa07f72018-05-24 12:21:06 +0530139
Subrata Banikafa07f72018-05-24 12:21:06 +0530140 /* Configure the 2 pads per UART. */
141 uart_configure_gpio_pads();
142}
143
144#if ENV_RAMSTAGE
145
146static void uart_read_resources(struct device *dev)
147{
148 pci_dev_read_resources(dev);
149
150 /* Set the configured UART base address for the debug port */
Julius Wernercd49cce2019-03-05 16:53:33 -0800151 if (CONFIG(INTEL_LPSS_UART_FOR_CONSOLE) &&
Nico Hubera96e66a2018-11-11 02:51:14 +0100152 uart_is_debug_controller(dev)) {
Subrata Banikafa07f72018-05-24 12:21:06 +0530153 struct resource *res = find_resource(dev, PCI_BASE_ADDRESS_0);
154 /* Need to set the base and size for the resource allocator. */
Nico Huber99954182019-05-29 23:33:06 +0200155 res->base = CONFIG_CONSOLE_UART_BASE_ADDRESS;
156 res->size = 0x1000;
Subrata Banikafa07f72018-05-24 12:21:06 +0530157 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED |
158 IORESOURCE_FIXED;
159 }
160}
161
162/*
163 * Check if UART debug port controller needs to be initialized on resume.
164 *
165 * Returns:
166 * true = when SoC wants debug port initialization on resume
167 * false = otherwise
168 */
169static bool pch_uart_init_debug_controller_on_resume(void)
170{
171 global_nvs_t *gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS);
172
173 if (gnvs)
174 return !!gnvs->uior;
175
Furquan Shaikha8198eb2017-08-04 16:12:19 -0700176 return false;
177}
178
179bool uart_is_debug_controller(struct device *dev)
180{
Subrata Banikafa07f72018-05-24 12:21:06 +0530181 return dev == uart_get_device();
Furquan Shaikha8198eb2017-08-04 16:12:19 -0700182}
183
184/*
185 * This is a workaround to enable UART controller for the debug port if:
186 * 1. CONSOLE_SERIAL is not enabled in coreboot, and
187 * 2. This boot is S3 resume, and
188 * 3. SoC wants to initialize debug UART controller.
189 *
190 * This workaround is required because Linux kernel hangs on resume if console
191 * is not enabled in coreboot, but it is enabled in kernel and not suspended.
192 */
193static bool uart_controller_needs_init(struct device *dev)
194{
195 /*
Jonathan Neuschäfer5268b762018-02-12 12:24:25 +0100196 * If coreboot has CONSOLE_SERIAL enabled, the skip re-initializing
Furquan Shaikha8198eb2017-08-04 16:12:19 -0700197 * controller here.
198 */
Julius Wernercd49cce2019-03-05 16:53:33 -0800199 if (CONFIG(CONSOLE_SERIAL))
Furquan Shaikha8198eb2017-08-04 16:12:19 -0700200 return false;
201
202 /* If this device does not correspond to debug port, then skip. */
203 if (!uart_is_debug_controller(dev))
204 return false;
205
206 /* Initialize UART controller only on S3 resume. */
207 if (!acpi_is_wakeup_s3())
208 return false;
209
210 /*
Subrata Banikafa07f72018-05-24 12:21:06 +0530211 * check if SOC wants to initialize UART on resume
Furquan Shaikha8198eb2017-08-04 16:12:19 -0700212 */
213 return pch_uart_init_debug_controller_on_resume();
214}
215
216static void uart_common_enable_resources(struct device *dev)
217{
218 pci_dev_enable_resources(dev);
219
220 if (uart_controller_needs_init(dev)) {
221 uintptr_t base;
222
223 base = pci_read_config32(dev, PCI_BASE_ADDRESS_0) & ~0xFFF;
224 if (base)
Usha P5e59a822019-08-09 18:42:00 +0530225 uart_lpss_init(dev, base);
Furquan Shaikha8198eb2017-08-04 16:12:19 -0700226 }
227}
228
Aamir Bohra83f7bae2017-04-26 19:30:41 +0530229static struct device_operations device_ops = {
Elyes HAOUAS1d191272018-11-27 12:23:48 +0100230 .read_resources = uart_read_resources,
231 .set_resources = pci_dev_set_resources,
232 .enable_resources = uart_common_enable_resources,
Subrata Banik6bbc91a2017-12-07 14:55:51 +0530233 .ops_pci = &pci_dev_ops_pci,
Aamir Bohra83f7bae2017-04-26 19:30:41 +0530234};
235
236static const unsigned short pci_device_ids[] = {
237 PCI_DEVICE_ID_INTEL_SPT_UART0,
238 PCI_DEVICE_ID_INTEL_SPT_UART1,
239 PCI_DEVICE_ID_INTEL_SPT_UART2,
V Sowmya7c150472018-01-23 14:44:45 +0530240 PCI_DEVICE_ID_INTEL_SPT_H_UART0,
241 PCI_DEVICE_ID_INTEL_SPT_H_UART1,
242 PCI_DEVICE_ID_INTEL_SPT_H_UART2,
V Sowmyaacc2a482018-01-23 15:27:23 +0530243 PCI_DEVICE_ID_INTEL_KBP_H_UART0,
244 PCI_DEVICE_ID_INTEL_KBP_H_UART1,
245 PCI_DEVICE_ID_INTEL_KBP_H_UART2,
Aamir Bohra83f7bae2017-04-26 19:30:41 +0530246 PCI_DEVICE_ID_INTEL_APL_UART0,
247 PCI_DEVICE_ID_INTEL_APL_UART1,
248 PCI_DEVICE_ID_INTEL_APL_UART2,
249 PCI_DEVICE_ID_INTEL_APL_UART3,
Lijian Zhaobbedef92017-07-29 16:38:38 -0700250 PCI_DEVICE_ID_INTEL_CNL_UART0,
251 PCI_DEVICE_ID_INTEL_CNL_UART1,
252 PCI_DEVICE_ID_INTEL_CNL_UART2,
Hannah Williamsf7149652017-05-13 16:18:02 -0700253 PCI_DEVICE_ID_INTEL_GLK_UART0,
254 PCI_DEVICE_ID_INTEL_GLK_UART1,
255 PCI_DEVICE_ID_INTEL_GLK_UART2,
256 PCI_DEVICE_ID_INTEL_GLK_UART3,
praveen hodagatta praneshe26c4a42018-09-20 03:49:45 +0800257 PCI_DEVICE_ID_INTEL_CNP_H_UART0,
258 PCI_DEVICE_ID_INTEL_CNP_H_UART1,
259 PCI_DEVICE_ID_INTEL_CNP_H_UART2,
Aamir Bohra9eac0392018-06-30 12:07:04 +0530260 PCI_DEVICE_ID_INTEL_ICP_UART0,
261 PCI_DEVICE_ID_INTEL_ICP_UART1,
262 PCI_DEVICE_ID_INTEL_ICP_UART2,
Ronak Kanabarda7ffb482019-02-05 01:51:13 +0530263 PCI_DEVICE_ID_INTEL_CMP_UART0,
264 PCI_DEVICE_ID_INTEL_CMP_UART1,
265 PCI_DEVICE_ID_INTEL_CMP_UART2,
Gaggery Tsai12a651c2019-12-05 11:23:20 -0800266 PCI_DEVICE_ID_INTEL_CMP_H_UART0,
267 PCI_DEVICE_ID_INTEL_CMP_H_UART1,
268 PCI_DEVICE_ID_INTEL_CMP_H_UART2,
Ravi Sarawadi6b5bf402019-10-21 22:25:04 -0700269 PCI_DEVICE_ID_INTEL_TGP_UART0,
270 PCI_DEVICE_ID_INTEL_TGP_UART1,
271 PCI_DEVICE_ID_INTEL_TGP_UART2,
Tan, Lean Sheng26136092020-01-20 19:13:56 -0800272 PCI_DEVICE_ID_INTEL_MCC_UART0,
273 PCI_DEVICE_ID_INTEL_MCC_UART1,
274 PCI_DEVICE_ID_INTEL_MCC_UART2,
Meera Ravindranath3f4af0d2020-02-12 16:01:22 +0530275 PCI_DEVICE_ID_INTEL_JSP_UART0,
276 PCI_DEVICE_ID_INTEL_JSP_UART1,
277 PCI_DEVICE_ID_INTEL_JSP_UART2,
Hannah Williamsf7149652017-05-13 16:18:02 -0700278 0,
Aamir Bohra83f7bae2017-04-26 19:30:41 +0530279};
280
281static const struct pci_driver pch_uart __pci_driver = {
Subrata Banikafa07f72018-05-24 12:21:06 +0530282 .ops = &device_ops,
283 .vendor = PCI_VENDOR_ID_INTEL,
Aamir Bohra83f7bae2017-04-26 19:30:41 +0530284 .devices = pci_device_ids,
285};
286#endif /* ENV_RAMSTAGE */