blob: fac05775faf2472121bb6edd8d1ec55d2709d356 [file] [log] [blame]
Angel Pons0612b272020-04-05 15:46:56 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Furquan Shaikha8198eb2017-08-04 16:12:19 -07002
Furquan Shaikh76cedd22020-05-02 10:24:23 -07003#include <acpi/acpi.h>
Kyösti Mälkki5daa1d32020-06-14 12:01:58 +03004#include <acpi/acpi_gnvs.h>
Subrata Banikafa07f72018-05-24 12:21:06 +05305#include <console/uart.h>
Aamir Bohra83f7bae2017-04-26 19:30:41 +05306#include <device/device.h>
7#include <device/pci.h>
Aamir Bohra01d75f42017-03-30 20:12:21 +05308#include <device/pci_def.h>
Aamir Bohra83f7bae2017-04-26 19:30:41 +05309#include <device/pci_ids.h>
Furquan Shaikha8198eb2017-08-04 16:12:19 -070010#include <device/pci_ops.h>
Aamir Bohra01d75f42017-03-30 20:12:21 +053011#include <intelblocks/lpss.h>
12#include <intelblocks/uart.h>
Subrata Banikafa07f72018-05-24 12:21:06 +053013#include <soc/pci_devs.h>
14#include <soc/iomap.h>
15#include <soc/nvs.h>
Aamir Bohra01d75f42017-03-30 20:12:21 +053016
Furquan Shaikha8198eb2017-08-04 16:12:19 -070017#define UART_PCI_ENABLE (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER)
Subrata Banikafa07f72018-05-24 12:21:06 +053018#define UART_CONSOLE_INVALID_INDEX 0xFF
19
20extern const struct uart_gpio_pad_config uart_gpio_pads[];
21extern const int uart_max_index;
Furquan Shaikha8198eb2017-08-04 16:12:19 -070022
Usha P5e59a822019-08-09 18:42:00 +053023static void uart_lpss_init(const struct device *dev, uintptr_t baseaddr)
Furquan Shaikh3406dd62017-08-04 15:58:26 -070024{
Usha P5e59a822019-08-09 18:42:00 +053025 /* Ensure controller is in D0 state */
26 lpss_set_power_state(dev, STATE_D0);
27
Furquan Shaikh3406dd62017-08-04 15:58:26 -070028 /* Take UART out of reset */
29 lpss_reset_release(baseaddr);
30
31 /* Set M and N divisor inputs and enable clock */
32 lpss_clk_update(baseaddr, CONFIG_SOC_INTEL_COMMON_LPSS_UART_CLK_M_VAL,
33 CONFIG_SOC_INTEL_COMMON_LPSS_UART_CLK_N_VAL);
34}
35
Nico Huber62ddc492019-05-29 18:39:31 +020036#if CONFIG(INTEL_LPSS_UART_FOR_CONSOLE)
Subrata Banikafa07f72018-05-24 12:21:06 +053037uintptr_t uart_platform_base(int idx)
Aamir Bohra01d75f42017-03-30 20:12:21 +053038{
Nico Huberce8eebd2019-05-29 18:33:35 +020039 if (idx == CONFIG_UART_FOR_CONSOLE)
Nico Huber99954182019-05-29 23:33:06 +020040 return CONFIG_CONSOLE_UART_BASE_ADDRESS;
Nico Huberce8eebd2019-05-29 18:33:35 +020041 return 0;
Subrata Banikafa07f72018-05-24 12:21:06 +053042}
43#endif
44
45static int uart_get_valid_index(void)
46{
47 int index;
48
49 for (index = 0; index < uart_max_index; index++) {
50 if (uart_gpio_pads[index].console_index ==
51 CONFIG_UART_FOR_CONSOLE)
52 return index;
53 }
54 /* For valid index, code should not reach here */
55 return UART_CONSOLE_INVALID_INDEX;
56}
57
Aamir Bohra17cfba62019-07-25 20:56:54 +053058void uart_common_init(const struct device *device, uintptr_t baseaddr)
Subrata Banikafa07f72018-05-24 12:21:06 +053059{
60#if defined(__SIMPLE_DEVICE__)
Aamir Bohra17cfba62019-07-25 20:56:54 +053061 pci_devfn_t dev = PCI_BDF(device);
Subrata Banikafa07f72018-05-24 12:21:06 +053062#else
Aamir Bohra17cfba62019-07-25 20:56:54 +053063 const struct device *dev = device;
Subrata Banikafa07f72018-05-24 12:21:06 +053064#endif
Subrata Banikafa07f72018-05-24 12:21:06 +053065
Aamir Bohra01d75f42017-03-30 20:12:21 +053066 /* Set UART base address */
67 pci_write_config32(dev, PCI_BASE_ADDRESS_0, baseaddr);
68
69 /* Enable memory access and bus master */
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +020070 pci_write_config16(dev, PCI_COMMAND, UART_PCI_ENABLE);
Aamir Bohra01d75f42017-03-30 20:12:21 +053071
Usha P5e59a822019-08-09 18:42:00 +053072 uart_lpss_init(device, baseaddr);
Furquan Shaikha8198eb2017-08-04 16:12:19 -070073}
Aamir Bohra01d75f42017-03-30 20:12:21 +053074
Aamir Bohra17cfba62019-07-25 20:56:54 +053075const struct device *uart_get_device(void)
Furquan Shaikha8198eb2017-08-04 16:12:19 -070076{
77 /*
Nico Hubera96e66a2018-11-11 02:51:14 +010078 * This function will get called even if INTEL_LPSS_UART_FOR_CONSOLE
79 * config option is not selected.
80 * By default return NULL in this case to avoid compilation errors.
Furquan Shaikha8198eb2017-08-04 16:12:19 -070081 */
Julius Wernercd49cce2019-03-05 16:53:33 -080082 if (!CONFIG(INTEL_LPSS_UART_FOR_CONSOLE))
Subrata Banikafa07f72018-05-24 12:21:06 +053083 return NULL;
84
85 int console_index = uart_get_valid_index();
86
87 if (console_index != UART_CONSOLE_INVALID_INDEX)
88 return soc_uart_console_to_device(CONFIG_UART_FOR_CONSOLE);
89 else
90 return NULL;
Furquan Shaikha8198eb2017-08-04 16:12:19 -070091}
92
Subrata Banikafa07f72018-05-24 12:21:06 +053093bool uart_is_controller_initialized(void)
Furquan Shaikha8198eb2017-08-04 16:12:19 -070094{
Furquan Shaikha8198eb2017-08-04 16:12:19 -070095 uintptr_t base;
Aamir Bohra17cfba62019-07-25 20:56:54 +053096 const struct device *dev_uart = uart_get_device();
97
98 if (!dev_uart)
99 return false;
Furquan Shaikha8198eb2017-08-04 16:12:19 -0700100
Subrata Banikafa07f72018-05-24 12:21:06 +0530101#if defined(__SIMPLE_DEVICE__)
Aamir Bohra17cfba62019-07-25 20:56:54 +0530102 pci_devfn_t dev = PCI_BDF(dev_uart);
Subrata Banikafa07f72018-05-24 12:21:06 +0530103#else
Aamir Bohra17cfba62019-07-25 20:56:54 +0530104 const struct device *dev = dev_uart;
Subrata Banikafa07f72018-05-24 12:21:06 +0530105#endif
Furquan Shaikha8198eb2017-08-04 16:12:19 -0700106
107 base = pci_read_config32(dev, PCI_BASE_ADDRESS_0) & ~0xFFF;
108 if (!base)
109 return false;
110
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +0200111 if ((pci_read_config16(dev, PCI_COMMAND) & UART_PCI_ENABLE)
Furquan Shaikha8198eb2017-08-04 16:12:19 -0700112 != UART_PCI_ENABLE)
113 return false;
114
115 return !lpss_is_controller_in_reset(base);
Aamir Bohra01d75f42017-03-30 20:12:21 +0530116}
Aamir Bohra83f7bae2017-04-26 19:30:41 +0530117
Subrata Banikafa07f72018-05-24 12:21:06 +0530118static void uart_configure_gpio_pads(void)
Aamir Bohra83f7bae2017-04-26 19:30:41 +0530119{
Subrata Banikafa07f72018-05-24 12:21:06 +0530120 int index = uart_get_valid_index();
121
122 if (index != UART_CONSOLE_INVALID_INDEX)
123 gpio_configure_pads(uart_gpio_pads[index].gpios,
124 MAX_GPIO_PAD_PER_UART);
Aamir Bohra83f7bae2017-04-26 19:30:41 +0530125}
126
Subrata Banikafa07f72018-05-24 12:21:06 +0530127void uart_bootblock_init(void)
Furquan Shaikha8198eb2017-08-04 16:12:19 -0700128{
Aamir Bohra17cfba62019-07-25 20:56:54 +0530129 const struct device *dev_uart;
130
131 dev_uart = uart_get_device();
132
133 if (!dev_uart)
134 return;
135
Subrata Banikafa07f72018-05-24 12:21:06 +0530136 /* Program UART BAR0, command, reset and clock register */
Aamir Bohra17cfba62019-07-25 20:56:54 +0530137 uart_common_init(dev_uart, CONFIG_CONSOLE_UART_BASE_ADDRESS);
Subrata Banikafa07f72018-05-24 12:21:06 +0530138
Subrata Banikafa07f72018-05-24 12:21:06 +0530139 /* Configure the 2 pads per UART. */
140 uart_configure_gpio_pads();
141}
142
143#if ENV_RAMSTAGE
144
145static void uart_read_resources(struct device *dev)
146{
147 pci_dev_read_resources(dev);
148
149 /* Set the configured UART base address for the debug port */
Julius Wernercd49cce2019-03-05 16:53:33 -0800150 if (CONFIG(INTEL_LPSS_UART_FOR_CONSOLE) &&
Nico Hubera96e66a2018-11-11 02:51:14 +0100151 uart_is_debug_controller(dev)) {
Subrata Banikafa07f72018-05-24 12:21:06 +0530152 struct resource *res = find_resource(dev, PCI_BASE_ADDRESS_0);
153 /* Need to set the base and size for the resource allocator. */
Nico Huber99954182019-05-29 23:33:06 +0200154 res->base = CONFIG_CONSOLE_UART_BASE_ADDRESS;
155 res->size = 0x1000;
Subrata Banikafa07f72018-05-24 12:21:06 +0530156 res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED |
157 IORESOURCE_FIXED;
158 }
159}
160
161/*
162 * Check if UART debug port controller needs to be initialized on resume.
163 *
164 * Returns:
165 * true = when SoC wants debug port initialization on resume
166 * false = otherwise
167 */
168static bool pch_uart_init_debug_controller_on_resume(void)
169{
Kyösti Mälkki0c1dd9c2020-06-17 23:37:49 +0300170 struct global_nvs *gnvs = acpi_get_gnvs();
Subrata Banikafa07f72018-05-24 12:21:06 +0530171
172 if (gnvs)
173 return !!gnvs->uior;
174
Furquan Shaikha8198eb2017-08-04 16:12:19 -0700175 return false;
176}
177
178bool uart_is_debug_controller(struct device *dev)
179{
Subrata Banikafa07f72018-05-24 12:21:06 +0530180 return dev == uart_get_device();
Furquan Shaikha8198eb2017-08-04 16:12:19 -0700181}
182
183/*
184 * This is a workaround to enable UART controller for the debug port if:
185 * 1. CONSOLE_SERIAL is not enabled in coreboot, and
186 * 2. This boot is S3 resume, and
187 * 3. SoC wants to initialize debug UART controller.
188 *
189 * This workaround is required because Linux kernel hangs on resume if console
190 * is not enabled in coreboot, but it is enabled in kernel and not suspended.
191 */
192static bool uart_controller_needs_init(struct device *dev)
193{
194 /*
Jonathan Neuschäfer5268b762018-02-12 12:24:25 +0100195 * If coreboot has CONSOLE_SERIAL enabled, the skip re-initializing
Furquan Shaikha8198eb2017-08-04 16:12:19 -0700196 * controller here.
197 */
Julius Wernercd49cce2019-03-05 16:53:33 -0800198 if (CONFIG(CONSOLE_SERIAL))
Furquan Shaikha8198eb2017-08-04 16:12:19 -0700199 return false;
200
201 /* If this device does not correspond to debug port, then skip. */
202 if (!uart_is_debug_controller(dev))
203 return false;
204
205 /* Initialize UART controller only on S3 resume. */
206 if (!acpi_is_wakeup_s3())
207 return false;
208
209 /*
Subrata Banikafa07f72018-05-24 12:21:06 +0530210 * check if SOC wants to initialize UART on resume
Furquan Shaikha8198eb2017-08-04 16:12:19 -0700211 */
212 return pch_uart_init_debug_controller_on_resume();
213}
214
215static void uart_common_enable_resources(struct device *dev)
216{
217 pci_dev_enable_resources(dev);
218
219 if (uart_controller_needs_init(dev)) {
220 uintptr_t base;
221
222 base = pci_read_config32(dev, PCI_BASE_ADDRESS_0) & ~0xFFF;
223 if (base)
Usha P5e59a822019-08-09 18:42:00 +0530224 uart_lpss_init(dev, base);
Furquan Shaikha8198eb2017-08-04 16:12:19 -0700225 }
226}
227
Aamir Bohra83f7bae2017-04-26 19:30:41 +0530228static struct device_operations device_ops = {
Elyes HAOUAS1d191272018-11-27 12:23:48 +0100229 .read_resources = uart_read_resources,
230 .set_resources = pci_dev_set_resources,
231 .enable_resources = uart_common_enable_resources,
Subrata Banik6bbc91a2017-12-07 14:55:51 +0530232 .ops_pci = &pci_dev_ops_pci,
Aamir Bohra83f7bae2017-04-26 19:30:41 +0530233};
234
235static const unsigned short pci_device_ids[] = {
236 PCI_DEVICE_ID_INTEL_SPT_UART0,
237 PCI_DEVICE_ID_INTEL_SPT_UART1,
238 PCI_DEVICE_ID_INTEL_SPT_UART2,
V Sowmya7c150472018-01-23 14:44:45 +0530239 PCI_DEVICE_ID_INTEL_SPT_H_UART0,
240 PCI_DEVICE_ID_INTEL_SPT_H_UART1,
241 PCI_DEVICE_ID_INTEL_SPT_H_UART2,
V Sowmyaacc2a482018-01-23 15:27:23 +0530242 PCI_DEVICE_ID_INTEL_KBP_H_UART0,
243 PCI_DEVICE_ID_INTEL_KBP_H_UART1,
244 PCI_DEVICE_ID_INTEL_KBP_H_UART2,
Aamir Bohra83f7bae2017-04-26 19:30:41 +0530245 PCI_DEVICE_ID_INTEL_APL_UART0,
246 PCI_DEVICE_ID_INTEL_APL_UART1,
247 PCI_DEVICE_ID_INTEL_APL_UART2,
248 PCI_DEVICE_ID_INTEL_APL_UART3,
Lijian Zhaobbedef92017-07-29 16:38:38 -0700249 PCI_DEVICE_ID_INTEL_CNL_UART0,
250 PCI_DEVICE_ID_INTEL_CNL_UART1,
251 PCI_DEVICE_ID_INTEL_CNL_UART2,
Hannah Williamsf7149652017-05-13 16:18:02 -0700252 PCI_DEVICE_ID_INTEL_GLK_UART0,
253 PCI_DEVICE_ID_INTEL_GLK_UART1,
254 PCI_DEVICE_ID_INTEL_GLK_UART2,
255 PCI_DEVICE_ID_INTEL_GLK_UART3,
praveen hodagatta praneshe26c4a42018-09-20 03:49:45 +0800256 PCI_DEVICE_ID_INTEL_CNP_H_UART0,
257 PCI_DEVICE_ID_INTEL_CNP_H_UART1,
258 PCI_DEVICE_ID_INTEL_CNP_H_UART2,
Aamir Bohra9eac0392018-06-30 12:07:04 +0530259 PCI_DEVICE_ID_INTEL_ICP_UART0,
260 PCI_DEVICE_ID_INTEL_ICP_UART1,
261 PCI_DEVICE_ID_INTEL_ICP_UART2,
Ronak Kanabarda7ffb482019-02-05 01:51:13 +0530262 PCI_DEVICE_ID_INTEL_CMP_UART0,
263 PCI_DEVICE_ID_INTEL_CMP_UART1,
264 PCI_DEVICE_ID_INTEL_CMP_UART2,
Gaggery Tsai12a651c2019-12-05 11:23:20 -0800265 PCI_DEVICE_ID_INTEL_CMP_H_UART0,
266 PCI_DEVICE_ID_INTEL_CMP_H_UART1,
267 PCI_DEVICE_ID_INTEL_CMP_H_UART2,
Ravi Sarawadi6b5bf402019-10-21 22:25:04 -0700268 PCI_DEVICE_ID_INTEL_TGP_UART0,
269 PCI_DEVICE_ID_INTEL_TGP_UART1,
270 PCI_DEVICE_ID_INTEL_TGP_UART2,
Tan, Lean Sheng26136092020-01-20 19:13:56 -0800271 PCI_DEVICE_ID_INTEL_MCC_UART0,
272 PCI_DEVICE_ID_INTEL_MCC_UART1,
273 PCI_DEVICE_ID_INTEL_MCC_UART2,
Meera Ravindranath3f4af0d2020-02-12 16:01:22 +0530274 PCI_DEVICE_ID_INTEL_JSP_UART0,
275 PCI_DEVICE_ID_INTEL_JSP_UART1,
276 PCI_DEVICE_ID_INTEL_JSP_UART2,
Hannah Williamsf7149652017-05-13 16:18:02 -0700277 0,
Aamir Bohra83f7bae2017-04-26 19:30:41 +0530278};
279
280static const struct pci_driver pch_uart __pci_driver = {
Subrata Banikafa07f72018-05-24 12:21:06 +0530281 .ops = &device_ops,
282 .vendor = PCI_VENDOR_ID_INTEL,
Aamir Bohra83f7bae2017-04-26 19:30:41 +0530283 .devices = pci_device_ids,
284};
285#endif /* ENV_RAMSTAGE */