From mboxrd@z Thu Jan 1 00:00:00 1970 From: Simon Glass Date: Wed, 7 Apr 2021 16:32:13 +1200 Subject: [PATCH 03/17] x86: Allow coreboot serial driver to guess the UART In-Reply-To: <20210407043228.2268429-1-sjg@chromium.org> References: <20210407043228.2268429-1-sjg@chromium.org> Message-ID: <20210407163159.3.I967ea8c85e009f870c7aa944372d32c990f1b14a@changeid> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de At present this driver relies on coreboot to provide information about the console UART. However if coreboot is not compiled with the UART enabled, the information is left out. This configuration is quite common, e.g. with shipping x86-based Chrome OS Chromebooks. Add a way to determine the UART settings in this case, using a hard-coded list of PCI IDs. Signed-off-by: Simon Glass --- drivers/serial/serial_coreboot.c | 68 ++++++++++++++++++++++++++++---- include/pci_ids.h | 1 + 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/drivers/serial/serial_coreboot.c b/drivers/serial/serial_coreboot.c index de09c8681f5..4b4619432d8 100644 --- a/drivers/serial/serial_coreboot.c +++ b/drivers/serial/serial_coreboot.c @@ -11,19 +11,71 @@ #include #include +static const struct pci_device_id ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_APL_UART2) }, + {}, +}; + +/* + * Coreboot only sets up the UART if it uses it and doesn't bother to put the + * details in sysinfo if it doesn't. Try to guess in that case, using devices + * we know about + * + * @plat: Platform data to fill in + * @return 0 if found, -ve if no UART was found + */ +static int guess_uart(struct ns16550_plat *plat) +{ + struct udevice *bus, *dev; + ulong addr; + int index; + int ret; + + ret = uclass_first_device_err(UCLASS_PCI, &bus); + if (ret) + return ret; + index = 0; + ret = pci_bus_find_devices(bus, ids, &index, &dev); + if (ret) + return ret; + addr = dm_pci_read_bar32(dev, 0); + plat->base = addr; + plat->reg_shift = 2; + plat->reg_width = 4; + plat->clock = 1843200; + plat->fcr = UART_FCR_DEFVAL; + plat->flags = 0; + + return 0; +} + static int coreboot_of_to_plat(struct udevice *dev) { struct ns16550_plat *plat = dev_get_plat(dev); struct cb_serial *cb_info = lib_sysinfo.serial; - plat->base = cb_info->baseaddr; - plat->reg_shift = cb_info->regwidth == 4 ? 2 : 0; - plat->reg_width = cb_info->regwidth; - plat->clock = cb_info->input_hertz; - plat->fcr = UART_FCR_DEFVAL; - plat->flags = 0; - if (cb_info->type == CB_SERIAL_TYPE_IO_MAPPED) - plat->flags |= NS16550_FLAG_IO; + if (cb_info) { + plat->base = cb_info->baseaddr; + plat->reg_shift = cb_info->regwidth == 4 ? 2 : 0; + plat->reg_width = cb_info->regwidth; + plat->clock = cb_info->input_hertz; + plat->fcr = UART_FCR_DEFVAL; + plat->flags = 0; + if (cb_info->type == CB_SERIAL_TYPE_IO_MAPPED) + plat->flags |= NS16550_FLAG_IO; + } else if (CONFIG_IS_ENABLED(PCI)) { + int ret; + + ret = guess_uart(plat); + if (ret) { + /* + * Returning an error will cause U-Boot to complain that + * there is no UART, which may panic. So stay silent and + * pray that the video console will work. + */ + log_debug("Cannot detect UART\n"); + } + } return 0; } diff --git a/include/pci_ids.h b/include/pci_ids.h index 7ecedc7f04c..d91c1d08f1a 100644 --- a/include/pci_ids.h +++ b/include/pci_ids.h @@ -2987,6 +2987,7 @@ #define PCI_DEVICE_ID_INTEL_UNC_R3QPI1 0x3c45 #define PCI_DEVICE_ID_INTEL_JAKETOWN_UBOX 0x3ce0 #define PCI_DEVICE_ID_INTEL_IOAT_SNB 0x402f +#define PCI_DEVICE_ID_INTEL_APL_UART2 0x5ac0 #define PCI_DEVICE_ID_INTEL_5100_16 0x65f0 #define PCI_DEVICE_ID_INTEL_5100_19 0x65f3 #define PCI_DEVICE_ID_INTEL_5100_21 0x65f5 -- 2.31.0.208.g409f899ff0-goog