summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2023-05-11 08:40:33 -0400
committerTom Rini <trini@konsulko.com>2023-05-11 08:40:33 -0400
commite94fbdd2729fdcd570035d43f67adda8e0dfc115 (patch)
treefc4d5d6f989618994e0af5bb61f9918e4c8a7478 /drivers
parent0a9a4384c1483a88776bca38e28f09be51161034 (diff)
parentb982f89c583c6c03f4d1f94d29991ccf691a0f7c (diff)
downloadu-boot-e94fbdd2729fdcd570035d43f67adda8e0dfc115.tar.gz
Merge https://source.denx.de/u-boot/custodians/u-boot-x86
- Various fixes for Google chromebooks - Various minor enhancements for coreboot
Diffstat (limited to 'drivers')
-rw-r--r--drivers/core/Kconfig1
-rw-r--r--drivers/core/root.c4
-rw-r--r--drivers/cpu/microblaze_cpu.c2
-rw-r--r--drivers/input/i8042.c19
-rw-r--r--drivers/mtd/spi/sf_probe.c3
-rw-r--r--drivers/mtd/spi/spi-nor-tiny.c16
-rw-r--r--drivers/nvme/nvme_pci.c5
-rw-r--r--drivers/pci/pci-uclass.c4
-rw-r--r--drivers/serial/Kconfig10
-rw-r--r--drivers/serial/serial_coreboot.c114
-rw-r--r--drivers/sysreset/sysreset_x86.c9
11 files changed, 165 insertions, 22 deletions
diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index 0f755aa702..f0d848f45d 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -448,6 +448,7 @@ config OFNODE_MULTI_TREE_MAX
config ACPIGEN
bool "Support ACPI table generation in driver model"
+ depends on ACPI
default y if SANDBOX || (GENERATE_ACPI_TABLE && !QEMU)
select LIB_UUID
help
diff --git a/drivers/core/root.c b/drivers/core/root.c
index c4fb48548b..6775fb0b65 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -436,8 +436,8 @@ int dm_init_and_scan(bool pre_reloc_only)
return ret;
}
}
- if (CONFIG_IS_ENABLED(DM_EVENT)) {
- ret = event_notify_null(EVT_DM_POST_INIT);
+ if (CONFIG_IS_ENABLED(DM_EVENT) && !(gd->flags & GD_FLG_RELOC)) {
+ ret = event_notify_null(EVT_DM_POST_INIT_F);
if (ret)
return log_msg_ret("ev", ret);
}
diff --git a/drivers/cpu/microblaze_cpu.c b/drivers/cpu/microblaze_cpu.c
index b9d0792822..c97a89fbd5 100644
--- a/drivers/cpu/microblaze_cpu.c
+++ b/drivers/cpu/microblaze_cpu.c
@@ -29,7 +29,7 @@ static int microblaze_cpu_probe_all(void *ctx, struct event *event)
return 0;
}
-EVENT_SPY(EVT_DM_POST_INIT, microblaze_cpu_probe_all);
+EVENT_SPY(EVT_DM_POST_INIT_F, microblaze_cpu_probe_all);
static void microblaze_set_cpuinfo_pvr(struct microblaze_cpuinfo *ci)
{
diff --git a/drivers/input/i8042.c b/drivers/input/i8042.c
index 3563dc9883..e6070ca015 100644
--- a/drivers/input/i8042.c
+++ b/drivers/input/i8042.c
@@ -6,6 +6,8 @@
/* i8042.c - Intel 8042 keyboard driver routines */
+#define LOG_CATEGORY UCLASS_KEYBOARD
+
#include <common.h>
#include <dm.h>
#include <env.h>
@@ -54,6 +56,14 @@ static unsigned char ext_key_map[] = {
0x00 /* map end */
};
+/**
+ * kbd_input_empty() - Wait until the keyboard is ready for a command
+ *
+ * Checks the IBF flag (input buffer full), waiting for it to indicate that
+ * any previous command has been processed.
+ *
+ * Return: true if ready, false if it timed out
+ */
static int kbd_input_empty(void)
{
int kbd_timeout = KBD_TIMEOUT * 1000;
@@ -64,6 +74,12 @@ static int kbd_input_empty(void)
return kbd_timeout != -1;
}
+/**
+ * kbd_output_full() - Wait until the keyboard has data available
+ *
+ * Checks the OBF flag (output buffer full), waiting for it to indicate that
+ * a response to a previous command is available
+ */
static int kbd_output_full(void)
{
int kbd_timeout = KBD_TIMEOUT * 1000;
@@ -127,6 +143,9 @@ static int kbd_reset(int quirk)
{
int config;
+ if (!kbd_input_empty())
+ goto err;
+
/* controller self test */
if (kbd_cmd_read(CMD_SELF_TEST) != KBC_TEST_OK)
goto err;
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index e192f97efd..de6516f106 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -189,7 +189,8 @@ static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len)
struct mtd_info *mtd = &flash->mtd;
struct erase_info instr;
- if (offset % mtd->erasesize || len % mtd->erasesize) {
+ if (!mtd->erasesize ||
+ (offset % mtd->erasesize || len % mtd->erasesize)) {
debug("SF: Erase offset/length not multiple of erase size\n");
return -EINVAL;
}
diff --git a/drivers/mtd/spi/spi-nor-tiny.c b/drivers/mtd/spi/spi-nor-tiny.c
index 68152ce3b4..7aa24e129f 100644
--- a/drivers/mtd/spi/spi-nor-tiny.c
+++ b/drivers/mtd/spi/spi-nor-tiny.c
@@ -361,7 +361,7 @@ static int spi_nor_wait_till_ready(struct spi_nor *nor)
* Erase an address range on the nor chip. The address range may extend
* one or more erase sectors. Return an error is there is a problem erasing.
*/
-static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
+static int spi_nor_erase_tiny(struct mtd_info *mtd, struct erase_info *instr)
{
return -ENOTSUPP;
}
@@ -390,8 +390,8 @@ static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
return ERR_PTR(-EMEDIUMTYPE);
}
-static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, u_char *buf)
+static int spi_nor_read_tiny(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf)
{
struct spi_nor *nor = mtd_to_spi_nor(mtd);
int ret;
@@ -426,8 +426,8 @@ read_err:
* FLASH_PAGESIZE chunks. The address range may be any size provided
* it is within the physical boundaries.
*/
-static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const u_char *buf)
+static int spi_nor_write_tiny(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf)
{
return -ENOTSUPP;
}
@@ -741,9 +741,9 @@ int spi_nor_scan(struct spi_nor *nor)
mtd->writesize = 1;
mtd->flags = MTD_CAP_NORFLASH;
mtd->size = info->sector_size * info->n_sectors;
- mtd->_erase = spi_nor_erase;
- mtd->_read = spi_nor_read;
- mtd->_write = spi_nor_write;
+ mtd->_erase = spi_nor_erase_tiny;
+ mtd->_read = spi_nor_read_tiny;
+ mtd->_write = spi_nor_write_tiny;
nor->size = mtd->size;
diff --git a/drivers/nvme/nvme_pci.c b/drivers/nvme/nvme_pci.c
index 36bf9c5ffb..5bb43d299f 100644
--- a/drivers/nvme/nvme_pci.c
+++ b/drivers/nvme/nvme_pci.c
@@ -6,6 +6,7 @@
#include <common.h>
#include <dm.h>
+#include <init.h>
#include <pci.h>
#include "nvme.h"
@@ -30,6 +31,10 @@ static int nvme_probe(struct udevice *udev)
ndev->instance = trailing_strtol(udev->name);
ndev->bar = dm_pci_map_bar(udev, PCI_BASE_ADDRESS_0, 0, 0,
PCI_REGION_TYPE, PCI_REGION_MEM);
+
+ /* Turn on bus-mastering */
+ dm_pci_clrset_config16(udev, PCI_COMMAND, 0, PCI_COMMAND_MASTER);
+
return nvme_init(udev);
}
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index 9343cfc62a..8d27e40338 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -973,6 +973,10 @@ static int decode_regions(struct pci_controller *hose, ofnode parent_node,
int len;
int i;
+ /* handle booting from coreboot, etc. */
+ if (!ll_boot_init())
+ return 0;
+
prop = ofnode_get_property(node, "ranges", &len);
if (!prop) {
debug("%s: Cannot decode regions\n", __func__);
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 7faf678444..f4767c838f 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -669,6 +669,16 @@ config COREBOOT_SERIAL
a serial console on any platform without needing to change the
device tree, etc.
+config COREBOOT_SERIAL_FROM_DBG2
+ bool "Obtain UART from ACPI tables"
+ depends on COREBOOT_SERIAL
+ default y if !SPL
+ help
+ Select this to try to find a DBG2 record in the ACPI tables, in the
+ event that coreboot does not provide information about the UART in the
+ normal sysinfo tables. This provides a useful fallback when serial
+ is not enabled in coreboot.
+
config CORTINA_UART
bool "Cortina UART support"
depends on DM_SERIAL
diff --git a/drivers/serial/serial_coreboot.c b/drivers/serial/serial_coreboot.c
index de09c8681f..23066e4d05 100644
--- a/drivers/serial/serial_coreboot.c
+++ b/drivers/serial/serial_coreboot.c
@@ -5,25 +5,123 @@
* Copyright 2019 Google LLC
*/
+#define LOG_CATGEGORY UCLASS_SERIAL
+
#include <common.h>
#include <dm.h>
+#include <log.h>
#include <ns16550.h>
#include <serial.h>
+#include <acpi/acpi_table.h>
#include <asm/cb_sysinfo.h>
+DECLARE_GLOBAL_DATA_PTR;
+
+static int read_dbg2(struct ns16550_plat *plat)
+{
+ struct acpi_table_header *tab;
+ struct acpi_dbg2_header *hdr;
+ struct acpi_dbg2_device *dbg;
+ struct acpi_gen_regaddr *addr;
+ u32 *addr_size;
+
+ log_debug("Looking for DBG2 in ACPI tables\n");
+ if (!gd->acpi_start) {
+ log_debug("No ACPI tables\n");
+ return -ENOENT;
+ }
+
+ tab = acpi_find_table("DBG2");
+ if (!tab) {
+ log_debug("No DBG2 table\n");
+ return -ENOENT;
+ }
+ hdr = container_of(tab, struct acpi_dbg2_header, header);
+
+ /* We only use the first device, but check that there is at least one */
+ if (!hdr->devices_count) {
+ log_debug("No devices\n");
+ return -ENOENT;
+ }
+ if (hdr->devices_offset >= tab->length) {
+ log_debug("Invalid offset\n");
+ return -EINVAL;
+ }
+ dbg = (void *)hdr + hdr->devices_offset;
+ if (dbg->revision) {
+ log_debug("Invalid revision %d\n", dbg->revision);
+ return -EINVAL;
+ }
+ if (!dbg->address_count) {
+ log_debug("No addresses\n");
+ return -EINVAL;
+ }
+ if (dbg->port_type != ACPI_DBG2_SERIAL_PORT) {
+ log_debug("Not a serial port\n");
+ return -EPROTOTYPE;
+ }
+ if (dbg->port_subtype != ACPI_DBG2_16550_COMPATIBLE) {
+ log_debug("Incompatible serial port\n");
+ return -EPROTOTYPE;
+ }
+ if (dbg->base_address_offset >= dbg->length ||
+ dbg->address_size_offset >= dbg->length) {
+ log_debug("Invalid base address/size offsets %d, %d\n",
+ dbg->base_address_offset, dbg->address_size_offset);
+ return -EINVAL;
+ }
+ addr_size = (void *)dbg + dbg->address_size_offset;
+ if (!*addr_size) {
+ log_debug("Zero address size\n");
+ return -EINVAL;
+ }
+ addr = (void *)dbg + dbg->base_address_offset;
+ if (addr->space_id != ACPI_ADDRESS_SPACE_MEMORY) {
+ log_debug("Incompatible space %d\n", addr->space_id);
+ return -EPROTOTYPE;
+ }
+
+ plat->base = addr->addrl;
+
+ /* ACPI_ACCESS_SIZE_DWORD_ACCESS is 3; we want 2 */
+ plat->reg_shift = addr->access_size - 1;
+ plat->reg_width = 4; /* coreboot sets bit_width to 0 */
+ plat->clock = 1843200;
+ plat->fcr = UART_FCR_DEFVAL;
+ plat->flags = 0;
+ log_debug("Collected UART from ACPI DBG2 table\n");
+
+ 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;
+ int ret = -ENOENT;
- 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;
+ ret = 0;
+ } else if (IS_ENABLED(CONFIG_COREBOOT_SERIAL_FROM_DBG2)) {
+ ret = read_dbg2(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/drivers/sysreset/sysreset_x86.c b/drivers/sysreset/sysreset_x86.c
index 8042f3994f..4936fdb76c 100644
--- a/drivers/sysreset/sysreset_x86.c
+++ b/drivers/sysreset/sysreset_x86.c
@@ -129,8 +129,13 @@ static int x86_sysreset_probe(struct udevice *dev)
{
struct x86_sysreset_plat *plat = dev_get_plat(dev);
- /* Locate the PCH if there is one. It isn't essential */
- uclass_first_device(UCLASS_PCH, &plat->pch);
+ /*
+ * Locate the PCH if there is one. It isn't essential. Avoid this before
+ * relocation as we shouldn't need reset then and it needs a lot of
+ * memory for PCI enumeration.
+ */
+ if (gd->flags & GD_FLG_RELOC)
+ uclass_first_device(UCLASS_PCH, &plat->pch);
return 0;
}