diff options
Diffstat (limited to 'drivers')
35 files changed, 608 insertions, 208 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig index ed8a39c994..b1ada1cb7f 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -30,8 +30,6 @@ source "drivers/ddr/Kconfig" source "drivers/demo/Kconfig" -source "drivers/board/Kconfig" - source "drivers/ddr/fsl/Kconfig" source "drivers/dfu/Kconfig" @@ -114,6 +112,8 @@ source "drivers/spi/Kconfig" source "drivers/spmi/Kconfig" +source "drivers/sysinfo/Kconfig" + source "drivers/sysreset/Kconfig" source "drivers/tee/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 33f1d536cd..e371bc32bb 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -27,9 +27,9 @@ obj-$(CONFIG_$(SPL_TPL_)TIMER) += timer/ obj-$(CONFIG_$(SPL_TPL_)VIRTIO) += virtio/ obj-$(CONFIG_$(SPL_)DM_MAILBOX) += mailbox/ obj-$(CONFIG_$(SPL_)REMOTEPROC) += remoteproc/ +obj-$(CONFIG_$(SPL_)SYSINFO) += sysinfo/ obj-$(CONFIG_$(SPL_TPL_)TPM) += tpm/ obj-$(CONFIG_$(SPL_TPL_)ACPI_PMC) += power/acpi_pmc/ -obj-$(CONFIG_$(SPL_)BOARD) += board/ obj-$(CONFIG_XEN) += xen/ obj-$(CONFIG_$(SPL_)FPGA) += fpga/ diff --git a/drivers/board/Kconfig b/drivers/board/Kconfig deleted file mode 100644 index 254f657049..0000000000 --- a/drivers/board/Kconfig +++ /dev/null @@ -1,25 +0,0 @@ -menuconfig BOARD - bool "Device Information" - help - Support methods to query hardware configurations from internal - mechanisms (e.g. reading GPIO values, determining the presence of - devices on busses, etc.). This enables the usage of U-Boot with - modular board architectures. - -if BOARD - -config SPL_BOARD - depends on SPL_DM - bool "Enable board driver support in SPL" - -config BOARD_GAZERBEAM - bool "Enable board driver for the Gazerbeam board" - help - Support querying device information for the gdsys Gazerbeam board. - -config BOARD_SANDBOX - bool "Enable board driver for the Sandbox board" - help - Support querying device information for the Sandbox boards. - -endif diff --git a/drivers/board/Makefile b/drivers/board/Makefile deleted file mode 100644 index cc16361755..0000000000 --- a/drivers/board/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0+ -# -# (C) Copyright 2017 -# Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc -obj-y += board-uclass.o -obj-$(CONFIG_BOARD_GAZERBEAM) += gazerbeam.o -obj-$(CONFIG_BOARD_SANDBOX) += sandbox.o diff --git a/drivers/board/board-uclass.c b/drivers/board/board-uclass.c deleted file mode 100644 index b5485e9895..0000000000 --- a/drivers/board/board-uclass.c +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * (C) Copyright 2017 - * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc - */ - -#include <common.h> -#include <dm.h> -#include <board.h> - -int board_get(struct udevice **devp) -{ - return uclass_first_device_err(UCLASS_BOARD, devp); -} - -int board_detect(struct udevice *dev) -{ - struct board_ops *ops = board_get_ops(dev); - - if (!ops->detect) - return -ENOSYS; - - return ops->detect(dev); -} - -int board_get_fit_loadable(struct udevice *dev, int index, - const char *type, const char **strp) -{ - struct board_ops *ops = board_get_ops(dev); - - if (!ops->get_fit_loadable) - return -ENOSYS; - - return ops->get_fit_loadable(dev, index, type, strp); -} - -int board_get_bool(struct udevice *dev, int id, bool *val) -{ - struct board_ops *ops = board_get_ops(dev); - - if (!ops->get_bool) - return -ENOSYS; - - return ops->get_bool(dev, id, val); -} - -int board_get_int(struct udevice *dev, int id, int *val) -{ - struct board_ops *ops = board_get_ops(dev); - - if (!ops->get_int) - return -ENOSYS; - - return ops->get_int(dev, id, val); -} - -int board_get_str(struct udevice *dev, int id, size_t size, char *val) -{ - struct board_ops *ops = board_get_ops(dev); - - if (!ops->get_str) - return -ENOSYS; - - return ops->get_str(dev, id, size, val); -} - -UCLASS_DRIVER(board) = { - .id = UCLASS_BOARD, - .name = "board", - .post_bind = dm_scan_fdt_dev, -}; diff --git a/drivers/bootcount/Kconfig b/drivers/bootcount/Kconfig index c8e6fa7f89..b5ccea0d9c 100644 --- a/drivers/bootcount/Kconfig +++ b/drivers/bootcount/Kconfig @@ -108,6 +108,16 @@ config DM_BOOTCOUNT_I2C_EEPROM pointing to the underlying i2c eeprom device) and an optional 'offset' property are supported. +config DM_BOOTCOUNT_SPI_FLASH + bool "Support SPI flash devices as a backing store for bootcount" + depends on DM_SPI_FLASH + help + Enabled reading/writing the bootcount in a DM SPI flash device. + The wrapper device is to be specified with the compatible string + 'u-boot,bootcount-spi-flash' and the 'spi-flash'-property (a phandle + pointing to the underlying SPI flash device) and an optional 'offset' + property are supported. + config BOOTCOUNT_MEM bool "Support memory based bootcounter" help diff --git a/drivers/bootcount/Makefile b/drivers/bootcount/Makefile index 059d40d16b..51d860b00e 100644 --- a/drivers/bootcount/Makefile +++ b/drivers/bootcount/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_BOOTCOUNT_EXT) += bootcount_ext.o obj-$(CONFIG_DM_BOOTCOUNT) += bootcount-uclass.o obj-$(CONFIG_DM_BOOTCOUNT_RTC) += rtc.o obj-$(CONFIG_DM_BOOTCOUNT_I2C_EEPROM) += i2c-eeprom.o +obj-$(CONFIG_DM_BOOTCOUNT_SPI_FLASH) += spi-flash.o diff --git a/drivers/bootcount/spi-flash.c b/drivers/bootcount/spi-flash.c new file mode 100644 index 0000000000..7cd388e661 --- /dev/null +++ b/drivers/bootcount/spi-flash.c @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2019 Collabora + * (C) Copyright 2019 GE + */ + +#include <common.h> +#include <bootcount.h> +#include <dm.h> +#include <spi_flash.h> + +static const u8 bootcount_magic = 0xbc; + +struct bootcount_spi_flash_priv { + struct udevice *spi_flash; + u32 offset; +}; + +static int bootcount_spi_flash_update(struct udevice *dev, u32 offset, u32 len, const void *buf) +{ + struct spi_flash *flash = dev_get_uclass_priv(dev); + u32 sector_size = flash->sector_size; + u32 sector_offset = offset % sector_size; + u32 sector = offset - sector_offset; + int err = 0; + + /* code only supports updating a single sector */ + if (sector_offset + len > sector_size) + return -ENOSYS; + + u8 *buffer = malloc(sector_size); + if (!buffer) + return -ENOMEM; + + err = spi_flash_read_dm(dev, sector, sector_size, buffer); + if (err < 0) + goto out; + + memcpy(buffer + sector_offset, buf, len); + + err = spi_flash_erase_dm(dev, sector, sector_size); + if (err < 0) + goto out; + + err = spi_flash_write_dm(dev, sector, sector_size, buffer); + if (err < 0) + goto out; + +out: + free(buffer); + return err; +} + +static int bootcount_spi_flash_set(struct udevice *dev, const u32 a) +{ + struct bootcount_spi_flash_priv *priv = dev_get_priv(dev); + const u16 val = bootcount_magic << 8 | (a & 0xff); + + if (bootcount_spi_flash_update(priv->spi_flash, priv->offset, 2, &val) < 0) { + debug("%s: write failed\n", __func__); + return -EIO; + } + + return 0; +} + +static int bootcount_spi_flash_get(struct udevice *dev, u32 *a) +{ + struct bootcount_spi_flash_priv *priv = dev_get_priv(dev); + u16 val; + + if (spi_flash_read_dm(priv->spi_flash, priv->offset, 2, &val) < 0) { + debug("%s: read failed\n", __func__); + return -EIO; + } + + if (val >> 8 == bootcount_magic) { + *a = val & 0xff; + return 0; + } + + debug("%s: bootcount magic does not match on %04x\n", __func__, val); + return -EIO; +} + +static int bootcount_spi_flash_probe(struct udevice *dev) +{ + struct ofnode_phandle_args phandle_args; + struct bootcount_spi_flash_priv *priv = dev_get_priv(dev); + struct udevice *spi_flash; + + if (dev_read_phandle_with_args(dev, "spi-flash", NULL, 0, 0, &phandle_args)) { + debug("%s: spi-flash backing device not specified\n", dev->name); + return -ENOENT; + } + + if (uclass_get_device_by_ofnode(UCLASS_SPI_FLASH, phandle_args.node, &spi_flash)) { + debug("%s: could not get backing device\n", dev->name); + return -ENODEV; + } + + priv->spi_flash = spi_flash; + priv->offset = dev_read_u32_default(dev, "offset", 0); + + return 0; +} + +static const struct bootcount_ops bootcount_spi_flash_ops = { + .get = bootcount_spi_flash_get, + .set = bootcount_spi_flash_set, +}; + +static const struct udevice_id bootcount_spi_flash_ids[] = { + { .compatible = "u-boot,bootcount-spi-flash" }, + { } +}; + +U_BOOT_DRIVER(bootcount_spi_flash) = { + .name = "bootcount-spi-flash", + .id = UCLASS_BOOTCOUNT, + .priv_auto_alloc_size = sizeof(struct bootcount_spi_flash_priv), + .probe = bootcount_spi_flash_probe, + .of_match = bootcount_spi_flash_ids, + .ops = &bootcount_spi_flash_ops, +}; diff --git a/drivers/core/acpi.c b/drivers/core/acpi.c index 7fe93992b5..63a791f335 100644 --- a/drivers/core/acpi.c +++ b/drivers/core/acpi.c @@ -268,8 +268,7 @@ int acpi_recurse_method(struct acpi_ctx *ctx, struct udevice *parent, if (func) { void *start = ctx->current; - log_debug("\n"); - log_debug("- %s %p\n", parent->name, func); + log_debug("- method %d, %s %p\n", method, parent->name, func); ret = device_ofdata_to_platdata(parent); if (ret) return log_msg_ret("ofdata", ret); @@ -299,7 +298,6 @@ int acpi_fill_ssdt(struct acpi_ctx *ctx) int ret; log_debug("Writing SSDT tables\n"); - item_count = 0; ret = acpi_recurse_method(ctx, dm_root(), METHOD_FILL_SSDT, TYPE_SSDT); log_debug("Writing SSDT finished, err=%d\n", ret); ret = sort_acpi_item_type(ctx, start, TYPE_SSDT); @@ -315,7 +313,6 @@ int acpi_inject_dsdt(struct acpi_ctx *ctx) int ret; log_debug("Writing DSDT tables\n"); - item_count = 0; ret = acpi_recurse_method(ctx, dm_root(), METHOD_INJECT_DSDT, TYPE_DSDT); log_debug("Writing DSDT finished, err=%d\n", ret); @@ -326,6 +323,11 @@ int acpi_inject_dsdt(struct acpi_ctx *ctx) return ret; } +void acpi_reset_items(void) +{ + item_count = 0; +} + int acpi_write_dev_tables(struct acpi_ctx *ctx) { int ret; diff --git a/drivers/gpio/intel_gpio.c b/drivers/gpio/intel_gpio.c index 6a3a8c4cfa..c3b67f24d8 100644 --- a/drivers/gpio/intel_gpio.c +++ b/drivers/gpio/intel_gpio.c @@ -193,8 +193,8 @@ static const struct udevice_id intel_intel_gpio_ids[] = { { } }; -U_BOOT_DRIVER(gpio_intel) = { - .name = "gpio_intel", +U_BOOT_DRIVER(intel_gpio) = { + .name = "intel_gpio", .id = UCLASS_GPIO, .of_match = intel_intel_gpio_ids, .ops = &gpio_intel_ops, diff --git a/drivers/misc/cros_ec_i2c.c b/drivers/misc/cros_ec_i2c.c index c00f5f764a..664bd2b938 100644 --- a/drivers/misc/cros_ec_i2c.c +++ b/drivers/misc/cros_ec_i2c.c @@ -231,8 +231,8 @@ static const struct udevice_id cros_ec_ids[] = { { } }; -U_BOOT_DRIVER(cros_ec_i2c) = { - .name = "cros_ec_i2c", +U_BOOT_DRIVER(google_cros_ec_i2c) = { + .name = "google_cros_ec_i2c", .id = UCLASS_CROS_EC, .of_match = cros_ec_ids, .probe = cros_ec_probe, diff --git a/drivers/misc/cros_ec_lpc.c b/drivers/misc/cros_ec_lpc.c index 4ad6c8ca66..63702f90fb 100644 --- a/drivers/misc/cros_ec_lpc.c +++ b/drivers/misc/cros_ec_lpc.c @@ -243,8 +243,8 @@ static const struct udevice_id cros_ec_ids[] = { { } }; -U_BOOT_DRIVER(cros_ec_lpc) = { - .name = "cros_ec_lpc", +U_BOOT_DRIVER(google_cros_ec_lpc) = { + .name = "google_cros_ec_lpc", .id = UCLASS_CROS_EC, .of_match = cros_ec_ids, .probe = cros_ec_probe, diff --git a/drivers/misc/cros_ec_spi.c b/drivers/misc/cros_ec_spi.c index 153f971bde..bbc96301ae 100644 --- a/drivers/misc/cros_ec_spi.c +++ b/drivers/misc/cros_ec_spi.c @@ -184,8 +184,8 @@ static const struct udevice_id cros_ec_ids[] = { { } }; -U_BOOT_DRIVER(cros_ec_spi) = { - .name = "cros_ec_spi", +U_BOOT_DRIVER(google_cros_ec_spi) = { + .name = "google_cros_ec_spi", .id = UCLASS_CROS_EC, .of_match = cros_ec_ids, .probe = cros_ec_probe, diff --git a/drivers/pinctrl/intel/pinctrl.c b/drivers/pinctrl/intel/pinctrl.c index ba21c9dcc2..e3d2464634 100644 --- a/drivers/pinctrl/intel/pinctrl.c +++ b/drivers/pinctrl/intel/pinctrl.c @@ -154,7 +154,7 @@ static int pinctrl_get_device(uint pad, struct udevice **devp) return 0; } } - printf("pad %d not found\n", pad); + log_debug("pad %d not found\n", pad); return -ENOTBLK; } diff --git a/drivers/pinctrl/intel/pinctrl_apl.c b/drivers/pinctrl/intel/pinctrl_apl.c index 7624a9974f..727bacfd04 100644 --- a/drivers/pinctrl/intel/pinctrl_apl.c +++ b/drivers/pinctrl/intel/pinctrl_apl.c @@ -174,7 +174,7 @@ static const struct udevice_id apl_gpio_ids[] = { { } }; -U_BOOT_DRIVER(apl_pinctrl_drv) = { +U_BOOT_DRIVER(intel_apl_pinctrl) = { .name = "intel_apl_pinctrl", .id = UCLASS_PINCTRL, .of_match = apl_gpio_ids, diff --git a/drivers/rtc/m41t62.c b/drivers/rtc/m41t62.c index 94a6b523aa..0a4e12d698 100644 --- a/drivers/rtc/m41t62.c +++ b/drivers/rtc/m41t62.c @@ -22,6 +22,8 @@ #include <log.h> #include <rtc.h> #include <i2c.h> +#include <linux/log2.h> +#include <linux/delay.h> #define M41T62_REG_SSEC 0 #define M41T62_REG_SEC 1 @@ -47,8 +49,14 @@ #define M41T62_ALMON_SQWE (1 << 6) /* SQWE: SQW Enable Bit */ #define M41T62_ALHOUR_HT (1 << 6) /* HT: Halt Update Bit */ #define M41T62_FLAGS_AF (1 << 6) /* AF: Alarm Flag Bit */ +#define M41T62_FLAGS_OF (1 << 2) /* OF: Oscillator Flag Bit */ #define M41T62_FLAGS_BATT_LOW (1 << 4) /* BL: Battery Low Bit */ +#define M41T62_WDAY_SQW_FREQ_MASK 0xf0 +#define M41T62_WDAY_SQW_FREQ_SHIFT 4 + +#define M41T62_SQW_MAX_FREQ 32768 + #define M41T62_FEATURE_HT (1 << 0) #define M41T62_FEATURE_BL (1 << 1) @@ -139,21 +147,140 @@ static int m41t62_rtc_set(struct udevice *dev, const struct rtc_time *tm) return 0; } -static int m41t62_rtc_reset(struct udevice *dev) +static int m41t62_sqw_enable(struct udevice *dev, bool enable) { u8 val; + int ret; + + ret = dm_i2c_read(dev, M41T62_REG_ALARM_MON, &val, sizeof(val)); + if (ret) + return ret; + + if (enable) + val |= M41T62_ALMON_SQWE; + else + val &= ~M41T62_ALMON_SQWE; + + return dm_i2c_write(dev, M41T62_REG_ALARM_MON, &val, sizeof(val)); +} + +static int m41t62_sqw_set_rate(struct udevice *dev, unsigned int rate) +{ + u8 val, newval, sqwrateval; + int ret; + + if (rate >= M41T62_SQW_MAX_FREQ) + sqwrateval = 1; + else if (rate >= M41T62_SQW_MAX_FREQ / 4) + sqwrateval = 2; + else if (rate) + sqwrateval = 15 - ilog2(rate); + + ret = dm_i2c_read(dev, M41T62_REG_WDAY, &val, sizeof(val)); + if (ret) + return ret; + + newval = val; + newval &= ~M41T62_WDAY_SQW_FREQ_MASK; + newval |= (sqwrateval << M41T62_WDAY_SQW_FREQ_SHIFT); + + /* + * Try to avoid writing unchanged values. Writing to this register + * will reset the internal counter pipeline and thus affect system + * time. + */ + if (newval == val) + return 0; + + return dm_i2c_write(dev, M41T62_REG_WDAY, &newval, sizeof(newval)); +} + +static int m41t62_rtc_restart_osc(struct udevice *dev) +{ + u8 val; + int ret; + + /* 0. check if oscillator failure happened */ + ret = dm_i2c_read(dev, M41T62_REG_FLAGS, &val, sizeof(val)); + if (ret) + return ret; + if (!(val & M41T62_FLAGS_OF)) + return 0; + + ret = dm_i2c_read(dev, M41T62_REG_SEC, &val, sizeof(val)); + if (ret) + return ret; + + /* 1. Set stop bit */ + val |= M41T62_SEC_ST; + ret = dm_i2c_write(dev, M41T62_REG_ALARM_HOUR, &val, sizeof(val)); + if (ret) + return ret; + + /* 2. Clear stop bit */ + val &= ~M41T62_SEC_ST; + ret = dm_i2c_write(dev, M41T62_REG_ALARM_HOUR, &val, sizeof(val)); + if (ret) + return ret; + + /* 3. wait 4 seconds */ + mdelay(4000); + + ret = dm_i2c_read(dev, M41T62_REG_FLAGS, &val, sizeof(val)); + if (ret) + return ret; + + /* 4. clear M41T62_FLAGS_OF bit */ + val &= ~M41T62_FLAGS_OF; + ret = dm_i2c_write(dev, M41T62_REG_FLAGS, &val, sizeof(val)); + if (ret) + return ret; + + return 0; +} + +static int m41t62_rtc_clear_ht(struct udevice *dev) +{ + u8 val; + int ret; /* * M41T82: Make sure HT (Halt Update) bit is cleared. * This bit is 0 in M41T62 so its save to clear it always. */ - int ret = dm_i2c_read(dev, M41T62_REG_ALARM_HOUR, &val, sizeof(val)); - + ret = dm_i2c_read(dev, M41T62_REG_ALARM_HOUR, &val, sizeof(val)); + if (ret) + return ret; val &= ~M41T80_ALHOUR_HT; - ret |= dm_i2c_write(dev, M41T62_REG_ALARM_HOUR, &val, sizeof(val)); + ret = dm_i2c_write(dev, M41T62_REG_ALARM_HOUR, &val, sizeof(val)); + if (ret) + return ret; + + return 0; +} + +static int m41t62_rtc_reset(struct udevice *dev) +{ + int ret; + + ret = m41t62_rtc_restart_osc(dev); + if (ret) + return ret; + + ret = m41t62_rtc_clear_ht(dev); + if (ret) + return ret; - return ret; + /* + * Some boards feed the square wave as clock input into + * the SoC. This enables a 32.768kHz square wave, which is + * also the hardware default after power-loss. + */ + ret = m41t62_sqw_set_rate(dev, 32768); + if (ret) + return ret; + return m41t62_sqw_enable(dev, true); } /* @@ -162,7 +289,7 @@ static int m41t62_rtc_reset(struct udevice *dev) */ static int m41t62_rtc_probe(struct udevice *dev) { - return m41t62_rtc_reset(dev); + return m41t62_rtc_clear_ht(dev); } static const struct rtc_ops m41t62_rtc_ops = { diff --git a/drivers/rtc/mc146818.c b/drivers/rtc/mc146818.c index b98c39d821..71f96e282e 100644 --- a/drivers/rtc/mc146818.c +++ b/drivers/rtc/mc146818.c @@ -246,8 +246,8 @@ static const struct udevice_id rtc_mc146818_ids[] = { { } }; -U_BOOT_DRIVER(rtc_mc146818) = { - .name = "rtc_mc146818", +U_BOOT_DRIVER(motorola_mc146818) = { + .name = "motorola_mc146818", .id = UCLASS_RTC, .of_match = rtc_mc146818_ids, .probe = rtc_mc146818_probe, diff --git a/drivers/sound/da7219.c b/drivers/sound/da7219.c index 6bc1ad0036..8d674bcb4f 100644 --- a/drivers/sound/da7219.c +++ b/drivers/sound/da7219.c @@ -54,13 +54,13 @@ static int da7219_acpi_fill_ssdt(const struct udevice *dev, acpigen_write_name(ctx, "_CRS"); acpigen_write_resourcetemplate_header(ctx); ret = acpi_device_write_i2c_dev(ctx, dev); - if (ret) + if (ret < 0) return log_msg_ret("i2c", ret); /* Use either Interrupt() or GpioInt() */ ret = acpi_device_write_interrupt_or_gpio(ctx, (struct udevice *)dev, "req-gpios"); - if (ret) + if (ret < 0) return log_msg_ret("irq_gpio", ret); acpigen_write_resourcetemplate_footer(ctx); diff --git a/drivers/sound/max98357a.c b/drivers/sound/max98357a.c index 827262d235..b3d27a3616 100644 --- a/drivers/sound/max98357a.c +++ b/drivers/sound/max98357a.c @@ -69,7 +69,7 @@ static int max98357a_acpi_fill_ssdt(const struct udevice *dev, acpigen_write_name(ctx, "_CRS"); acpigen_write_resourcetemplate_header(ctx); ret = acpi_device_write_gpio_desc(ctx, &priv->sdmode_gpio); - if (ret) + if (ret < 0) return log_msg_ret("gpio", ret); acpigen_write_resourcetemplate_footer(ctx); diff --git a/drivers/sysinfo/Kconfig b/drivers/sysinfo/Kconfig new file mode 100644 index 0000000000..85c1e81e41 --- /dev/null +++ b/drivers/sysinfo/Kconfig @@ -0,0 +1,33 @@ +menuconfig SYSINFO + bool "Device System Information" + help + Support methods to query hardware configurations from internal + mechanisms (e.g. reading GPIO values, determining the presence of + devices on busses, etc.). This enables the usage of U-Boot with + modular board architectures. + +if SYSINFO + +config SPL_SYSINFO + depends on SPL_DM + bool "Enable board driver support in SPL" + +config SYSINFO_GAZERBEAM + bool "Enable sysinfo driver for the Gazerbeam board" + help + Support querying device information for the gdsys Gazerbeam board. + +config SYSINFO_SANDBOX + bool "Enable sysinfo driver for the Sandbox board" + help + Support querying device information for the Sandbox boards. + +config SYSINFO_SMBIOS + bool "Provide a default sysinfo driver for SMBIOS information" + help + Some boards want to specify the manufacturer or product name but do + not need to have their own sysinfo driver. This includes a default + one which provides a way to specify this SMBIOS information in the + devicetree, without needing any board-specific functionality. + +endif diff --git a/drivers/sysinfo/Makefile b/drivers/sysinfo/Makefile new file mode 100644 index 0000000000..6d04fcba1d --- /dev/null +++ b/drivers/sysinfo/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2017 +# Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc +obj-y += sysinfo-uclass.o +obj-$(CONFIG_SYSINFO_GAZERBEAM) += gazerbeam.o +obj-$(CONFIG_SYSINFO_SANDBOX) += sandbox.o +obj-$(CONFIG_SYSINFO_SMBIOS) += smbios.o diff --git a/drivers/board/gazerbeam.c b/drivers/sysinfo/gazerbeam.c index ed50fc530c..9e7a496655 100644 --- a/drivers/board/gazerbeam.c +++ b/drivers/sysinfo/gazerbeam.c @@ -6,7 +6,7 @@ #include <common.h> #include <dm.h> -#include <board.h> +#include <sysinfo.h> #include <i2c.h> #include <log.h> #include <asm/gpio.h> @@ -27,16 +27,16 @@ static const int SC_GPIO_NO; static const int CON_GPIO_NO = 1; /** - * struct board_gazerbeam_priv - Private data structure for the gazerbeam board - * driver. - * @reset_gpios: GPIOs for the board's reset GPIOs. - * @var_gpios: GPIOs for the board's hardware variant GPIOs - * @ver_gpios: GPIOs for the board's hardware version GPIOs - * @variant: Container for the board's hardware variant (CON/CPU) - * @multichannel: Container for the board's multichannel variant (MC4/MC2/SC) - * @hwversion: Container for the board's hardware version + * struct sysinfo_gazerbeam_priv - Private data structure for the gazerbeam + * sysinfo driver + * @reset_gpios: GPIOs for the sysinfo's reset GPIOs. + * @var_gpios: GPIOs for the sysinfo's hardware variant GPIOs + * @ver_gpios: GPIOs for the sysinfo's hardware version GPIOs + * @variant: Container for the sysinfo's hardware variant (CON/CPU) + * @multichannel: Container for the sysinfo's multichannel variant (MC4/MC2/SC) + * @hwversion: Container for the sysinfo's hardware version */ -struct board_gazerbeam_priv { +struct sysinfo_gazerbeam_priv { struct gpio_desc reset_gpios[2]; struct gpio_desc var_gpios[2]; struct gpio_desc ver_gpios[4]; @@ -46,19 +46,19 @@ struct board_gazerbeam_priv { }; /** - * _read_board_variant_data() - Read variant information from the hardware. - * @dev: The board device for which to determine the multichannel and device + * _read_sysinfo_variant_data() - Read variant information from the hardware. + * @dev: The sysinfo device for which to determine the multichannel and device * type information. * - * The data read from the board's hardware (mostly hard-wired GPIOs) is stored + * The data read from the sysinfo's hardware (mostly hard-wired GPIOs) is stored * in the private data structure of the driver to be used by other driver * methods. * * Return: 0 if OK, -ve on error. */ -static int _read_board_variant_data(struct udevice *dev) +static int _read_sysinfo_variant_data(struct udevice *dev) { - struct board_gazerbeam_priv *priv = dev_get_priv(dev); + struct sysinfo_gazerbeam_priv *priv = dev_get_priv(dev); struct udevice *i2c_bus; struct udevice *dummy; char *listname; @@ -129,10 +129,10 @@ static int _read_board_variant_data(struct udevice *dev) } /** - * _read_hwversion() - Read the hardware version from the board. - * @dev: The board device for which to read the hardware version. + * _read_hwversion() - Read the hardware version from the sysinfo. + * @dev: The sysinfo device for which to read the hardware version. * - * The hardware version read from the board (from hard-wired GPIOs) is stored + * The hardware version read from the sysinfo (from hard-wired GPIOs) is stored * in the private data structure of the driver to be used by other driver * methods. * @@ -140,7 +140,7 @@ static int _read_board_variant_data(struct udevice *dev) */ static int _read_hwversion(struct udevice *dev) { - struct board_gazerbeam_priv *priv = dev_get_priv(dev); + struct sysinfo_gazerbeam_priv *priv = dev_get_priv(dev); int res; res = gpio_request_list_by_name(dev, "ver-gpios", priv->ver_gpios, @@ -172,11 +172,11 @@ static int _read_hwversion(struct udevice *dev) return 0; } -static int board_gazerbeam_detect(struct udevice *dev) +static int sysinfo_gazerbeam_detect(struct udevice *dev) { int res; - res = _read_board_variant_data(dev); + res = _read_sysinfo_variant_data(dev); if (res) { debug("%s: Error reading multichannel variant (err = %d)\n", dev->name, res); @@ -193,9 +193,9 @@ static int board_gazerbeam_detect(struct udevice *dev) return 0; } -static int board_gazerbeam_get_int(struct udevice *dev, int id, int *val) +static int sysinfo_gazerbeam_get_int(struct udevice *dev, int id, int *val) { - struct board_gazerbeam_priv *priv = dev_get_priv(dev); + struct sysinfo_gazerbeam_priv *priv = dev_get_priv(dev); switch (id) { case BOARD_MULTICHANNEL: @@ -215,19 +215,19 @@ static int board_gazerbeam_get_int(struct udevice *dev, int id, int *val) return 0; } -static const struct udevice_id board_gazerbeam_ids[] = { - { .compatible = "gdsys,board_gazerbeam" }, +static const struct udevice_id sysinfo_gazerbeam_ids[] = { + { .compatible = "gdsys,sysinfo-gazerbeam" }, { /* sentinel */ } }; -static const struct board_ops board_gazerbeam_ops = { - .detect = board_gazerbeam_detect, - .get_int = board_gazerbeam_get_int, +static const struct sysinfo_ops sysinfo_gazerbeam_ops = { + .detect = sysinfo_gazerbeam_detect, + .get_int = sysinfo_gazerbeam_get_int, }; -static int board_gazerbeam_probe(struct udevice *dev) +static int sysinfo_gazerbeam_probe(struct udevice *dev) { - struct board_gazerbeam_priv *priv = dev_get_priv(dev); + struct sysinfo_gazerbeam_priv *priv = dev_get_priv(dev); int gpio_num, i; gpio_num = gpio_request_list_by_name(dev, "reset-gpios", @@ -255,11 +255,11 @@ static int board_gazerbeam_probe(struct udevice *dev) return 0; } -U_BOOT_DRIVER(board_gazerbeam) = { - .name = "board_gazerbeam", - .id = UCLASS_BOARD, - .of_match = board_gazerbeam_ids, - .ops = &board_gazerbeam_ops, - .priv_auto_alloc_size = sizeof(struct board_gazerbeam_priv), - .probe = board_gazerbeam_probe, +U_BOOT_DRIVER(sysinfo_gazerbeam) = { + .name = "sysinfo_gazerbeam", + .id = UCLASS_SYSINFO, + .of_match = sysinfo_gazerbeam_ids, + .ops = &sysinfo_gazerbeam_ops, + .priv_auto_alloc_size = sizeof(struct sysinfo_gazerbeam_priv), + .probe = sysinfo_gazerbeam_probe, }; diff --git a/drivers/board/gazerbeam.h b/drivers/sysinfo/gazerbeam.h index 171729d203..171729d203 100644 --- a/drivers/board/gazerbeam.h +++ b/drivers/sysinfo/gazerbeam.h diff --git a/drivers/board/sandbox.c b/drivers/sysinfo/sandbox.c index 50621e47a4..62a1cb4ac6 100644 --- a/drivers/board/sandbox.c +++ b/drivers/sysinfo/sandbox.c @@ -6,11 +6,11 @@ #include <common.h> #include <dm.h> -#include <board.h> +#include <sysinfo.h> #include "sandbox.h" -struct board_sandbox_priv { +struct sysinfo_sandbox_priv { bool called_detect; int test_i1; int test_i2; @@ -19,9 +19,9 @@ struct board_sandbox_priv { char vacation_spots[][64] = {"R'lyeh", "Dreamlands", "Plateau of Leng", "Carcosa", "Yuggoth", "The Nameless City"}; -int board_sandbox_detect(struct udevice *dev) +int sysinfo_sandbox_detect(struct udevice *dev) { - struct board_sandbox_priv *priv = dev_get_priv(dev); + struct sysinfo_sandbox_priv *priv = dev_get_priv(dev); priv->called_detect = true; priv->test_i2 = 100; @@ -29,9 +29,9 @@ int board_sandbox_detect(struct udevice *dev) return 0; } -int board_sandbox_get_bool(struct udevice *dev, int id, bool *val) +int sysinfo_sandbox_get_bool(struct udevice *dev, int id, bool *val) { - struct board_sandbox_priv *priv = dev_get_priv(dev); + struct sysinfo_sandbox_priv *priv = dev_get_priv(dev); switch (id) { case BOOL_CALLED_DETECT: @@ -43,9 +43,9 @@ int board_sandbox_get_bool(struct udevice *dev, int id, bool *val) return -ENOENT; } -int board_sandbox_get_int(struct udevice *dev, int id, int *val) +int sysinfo_sandbox_get_int(struct udevice *dev, int id, int *val) { - struct board_sandbox_priv *priv = dev_get_priv(dev); + struct sysinfo_sandbox_priv *priv = dev_get_priv(dev); switch (id) { case INT_TEST1: @@ -63,9 +63,9 @@ int board_sandbox_get_int(struct udevice *dev, int id, int *val) return -ENOENT; } -int board_sandbox_get_str(struct udevice *dev, int id, size_t size, char *val) +int sysinfo_sandbox_get_str(struct udevice *dev, int id, size_t size, char *val) { - struct board_sandbox_priv *priv = dev_get_priv(dev); + struct sysinfo_sandbox_priv *priv = dev_get_priv(dev); int i1 = priv->test_i1; int i2 = priv->test_i2; int index = (i1 * i2) % ARRAY_SIZE(vacation_spots); @@ -80,28 +80,28 @@ int board_sandbox_get_str(struct udevice *dev, int id, size_t size, char *val) return -ENOENT; } -static const struct udevice_id board_sandbox_ids[] = { - { .compatible = "sandbox,board_sandbox" }, +static const struct udevice_id sysinfo_sandbox_ids[] = { + { .compatible = "sandbox,sysinfo-sandbox" }, { /* sentinel */ } }; -static const struct board_ops board_sandbox_ops = { - .detect = board_sandbox_detect, - .get_bool = board_sandbox_get_bool, - .get_int = board_sandbox_get_int, - .get_str = board_sandbox_get_str, +static const struct sysinfo_ops sysinfo_sandbox_ops = { + .detect = sysinfo_sandbox_detect, + .get_bool = sysinfo_sandbox_get_bool, + .get_int = sysinfo_sandbox_get_int, + .get_str = sysinfo_sandbox_get_str, }; -int board_sandbox_probe(struct udevice *dev) +int sysinfo_sandbox_probe(struct udevice *dev) { return 0; } -U_BOOT_DRIVER(board_sandbox) = { - .name = "board_sandbox", - .id = UCLASS_BOARD, - .of_match = board_sandbox_ids, - .ops = &board_sandbox_ops, - .priv_auto_alloc_size = sizeof(struct board_sandbox_priv), - .probe = board_sandbox_probe, +U_BOOT_DRIVER(sysinfo_sandbox) = { + .name = "sysinfo_sandbox", + .id = UCLASS_SYSINFO, + .of_match = sysinfo_sandbox_ids, + .ops = &sysinfo_sandbox_ops, + .priv_auto_alloc_size = sizeof(struct sysinfo_sandbox_priv), + .probe = sysinfo_sandbox_probe, }; diff --git a/drivers/board/sandbox.h b/drivers/sysinfo/sandbox.h index 2cff494f56..2cff494f56 100644 --- a/drivers/board/sandbox.h +++ b/drivers/sysinfo/sandbox.h diff --git a/drivers/sysinfo/smbios.c b/drivers/sysinfo/smbios.c new file mode 100644 index 0000000000..80ebd1921d --- /dev/null +++ b/drivers/sysinfo/smbios.c @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2020 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <dm.h> +#include <sysinfo.h> + +static const struct udevice_id sysinfo_smbios_ids[] = { + { .compatible = "u-boot,sysinfo-smbios" }, + { /* sentinel */ } +}; + +static const struct sysinfo_ops sysinfo_smbios_ops = { +}; + +U_BOOT_DRIVER(sysinfo_smbios) = { + .name = "sysinfo_smbios", + .id = UCLASS_SYSINFO, + .of_match = sysinfo_smbios_ids, + .ops = &sysinfo_smbios_ops, +}; diff --git a/drivers/sysinfo/sysinfo-uclass.c b/drivers/sysinfo/sysinfo-uclass.c new file mode 100644 index 0000000000..6df58fe160 --- /dev/null +++ b/drivers/sysinfo/sysinfo-uclass.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2017 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc + */ + +#include <common.h> +#include <dm.h> +#include <sysinfo.h> + +int sysinfo_get(struct udevice **devp) +{ + return uclass_first_device_err(UCLASS_SYSINFO, devp); +} + +int sysinfo_detect(struct udevice *dev) +{ + struct sysinfo_ops *ops = sysinfo_get_ops(dev); + + if (!ops->detect) + return -ENOSYS; + + return ops->detect(dev); +} + +int sysinfo_get_fit_loadable(struct udevice *dev, int index, const char *type, + const char **strp) +{ + struct sysinfo_ops *ops = sysinfo_get_ops(dev); + + if (!ops->get_fit_loadable) + return -ENOSYS; + + return ops->get_fit_loadable(dev, index, type, strp); +} + +int sysinfo_get_bool(struct udevice *dev, int id, bool *val) +{ + struct sysinfo_ops *ops = sysinfo_get_ops(dev); + + if (!ops->get_bool) + return -ENOSYS; + + return ops->get_bool(dev, id, val); +} + +int sysinfo_get_int(struct udevice *dev, int id, int *val) +{ + struct sysinfo_ops *ops = sysinfo_get_ops(dev); + + if (!ops->get_int) + return -ENOSYS; + + return ops->get_int(dev, id, val); +} + +int sysinfo_get_str(struct udevice *dev, int id, size_t size, char *val) +{ + struct sysinfo_ops *ops = sysinfo_get_ops(dev); + + if (!ops->get_str) + return -ENOSYS; + + return ops->get_str(dev, id, size, val); +} + +UCLASS_DRIVER(sysinfo) = { + .id = UCLASS_SYSINFO, + .name = "sysinfo", + .post_bind = dm_scan_fdt_dev, +}; diff --git a/drivers/sysreset/Kconfig b/drivers/sysreset/Kconfig index 70692f07e7..0e5c7c9971 100644 --- a/drivers/sysreset/Kconfig +++ b/drivers/sysreset/Kconfig @@ -43,6 +43,13 @@ config SYSRESET_CMD_POWEROFF endif +config POWEROFF_GPIO + bool "Enable support for GPIO poweroff driver" + select DM_GPIO + help + Support for system poweroff using a GPIO pin. This can be used + for systems having a single GPIO to trigger a system poweroff. + config SYSRESET_GPIO bool "Enable support for GPIO reset driver" select DM_GPIO diff --git a/drivers/sysreset/Makefile b/drivers/sysreset/Makefile index 920c69233f..de81c399d7 100644 --- a/drivers/sysreset/Makefile +++ b/drivers/sysreset/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_ARCH_ASPEED) += sysreset_ast.o obj-$(CONFIG_ARCH_ROCKCHIP) += sysreset_rockchip.o obj-$(CONFIG_ARCH_STI) += sysreset_sti.o obj-$(CONFIG_SANDBOX) += sysreset_sandbox.o +obj-$(CONFIG_POWEROFF_GPIO) += poweroff_gpio.o obj-$(CONFIG_SYSRESET_GPIO) += sysreset_gpio.o obj-$(CONFIG_SYSRESET_MPC83XX) += sysreset_mpc83xx.o obj-$(CONFIG_SYSRESET_MICROBLAZE) += sysreset_microblaze.o diff --git a/drivers/sysreset/poweroff_gpio.c b/drivers/sysreset/poweroff_gpio.c new file mode 100644 index 0000000000..ac482c37f4 --- /dev/null +++ b/drivers/sysreset/poweroff_gpio.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Toggles a GPIO pin to power down a device + * + * Created using the Linux driver as reference, which + * has been written by: + * + * Jamie Lentin <jm@lentin.co.uk> + * Andrew Lunn <andrew@lunn.ch> + * + * Copyright (C) 2012 Jamie Lentin + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <log.h> +#include <sysreset.h> + +#include <asm/gpio.h> +#include <linux/delay.h> + +struct poweroff_gpio_info { + struct gpio_desc gpio; + u32 active_delay_ms; + u32 inactive_delay_ms; + u32 timeout_ms; +}; + +static int poweroff_gpio_request(struct udevice *dev, enum sysreset_t type) +{ + struct poweroff_gpio_info *priv = dev_get_priv(dev); + int r; + + if (type != SYSRESET_POWER_OFF) + return -ENOSYS; + + debug("GPIO poweroff\n"); + + /* drive it active, also inactive->active edge */ + r = dm_gpio_set_value(&priv->gpio, 1); + if (r < 0) + return r; + mdelay(priv->active_delay_ms); + + /* drive inactive, also active->inactive edge */ + r = dm_gpio_set_value(&priv->gpio, 0); + if (r < 0) + return r; + mdelay(priv->inactive_delay_ms); + + /* drive it active, also inactive->active edge */ + r = dm_gpio_set_value(&priv->gpio, 1); + if (r < 0) + return r; + + /* give it some time */ + mdelay(priv->timeout_ms); + + return -EINPROGRESS; +} + +static int poweroff_gpio_probe(struct udevice *dev) +{ + struct poweroff_gpio_info *priv = dev_get_priv(dev); + int flags; + + flags = dev_read_bool(dev, "input") ? GPIOD_IS_IN : GPIOD_IS_OUT; + priv->active_delay_ms = dev_read_u32_default(dev, "active-delay-ms", 100); + priv->inactive_delay_ms = dev_read_u32_default(dev, "inactive-delay-ms", 100); + priv->timeout_ms = dev_read_u32_default(dev, "timeout-ms", 3000); + + return gpio_request_by_name(dev, "gpios", 0, &priv->gpio, flags); +} + +static struct sysreset_ops poweroff_gpio_ops = { + .request = poweroff_gpio_request, +}; + +static const struct udevice_id poweroff_gpio_ids[] = { + { .compatible = "gpio-poweroff", }, + {}, +}; + +U_BOOT_DRIVER(poweroff_gpio) = { + .name = "poweroff-gpio", + .id = UCLASS_SYSRESET, + .ops = &poweroff_gpio_ops, + .probe = poweroff_gpio_probe, + .priv_auto_alloc_size = sizeof(struct poweroff_gpio_info), + .of_match = poweroff_gpio_ids, +}; diff --git a/drivers/sysreset/sysreset_x86.c b/drivers/sysreset/sysreset_x86.c index bc91143560..7682ffbd29 100644 --- a/drivers/sysreset/sysreset_x86.c +++ b/drivers/sysreset/sysreset_x86.c @@ -148,8 +148,8 @@ static struct sysreset_ops x86_sysreset_ops = { .get_last = x86_sysreset_get_last, }; -U_BOOT_DRIVER(x86_sysreset) = { - .name = "x86-sysreset", +U_BOOT_DRIVER(x86_reset) = { + .name = "x86_reset", .id = UCLASS_SYSRESET, .of_match = x86_sysreset_ids, .ops = &x86_sysreset_ops, diff --git a/drivers/thermal/imx_tmu.c b/drivers/thermal/imx_tmu.c index 4ca22089b8..936068c6cb 100644 --- a/drivers/thermal/imx_tmu.c +++ b/drivers/thermal/imx_tmu.c @@ -14,6 +14,7 @@ #include <dm/device.h> #include <errno.h> #include <fuse.h> +#include <linux/delay.h> #include <malloc.h> #include <thermal.h> diff --git a/drivers/timer/mpc83xx_timer.c b/drivers/timer/mpc83xx_timer.c index ba7704225a..6139252a73 100644 --- a/drivers/timer/mpc83xx_timer.c +++ b/drivers/timer/mpc83xx_timer.c @@ -5,12 +5,12 @@ */ #include <common.h> -#include <board.h> #include <clk.h> #include <dm.h> #include <irq_func.h> #include <log.h> #include <status_led.h> +#include <sysinfo.h> #include <time.h> #include <timer.h> #include <watchdog.h> @@ -97,7 +97,7 @@ int interrupt_init(void) { immap_t *immr = (immap_t *)CONFIG_SYS_IMMR; struct udevice *csb; - struct udevice *board; + struct udevice *sysinfo; struct udevice *timer; struct mpc83xx_timer_priv *timer_priv; struct clk clock; @@ -112,12 +112,12 @@ int interrupt_init(void) timer_priv = dev_get_priv(timer); - if (board_get(&board)) { - debug("%s: board device could not be fetched.\n", __func__); + if (sysinfo_get(&sysinfo)) { + debug("%s: sysinfo device could not be fetched.\n", __func__); return -ENOENT; } - ret = uclass_get_device_by_phandle(UCLASS_SIMPLE_BUS, board, + ret = uclass_get_device_by_phandle(UCLASS_SIMPLE_BUS, sysinfo, "csb", &csb); if (ret) { debug("%s: Could not retrieve CSB device (error: %d)", diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index abc0a1da05..e3677704b3 100644 --- a/drivers/timer/tsc_timer.c +++ b/drivers/timer/tsc_timer.c @@ -482,8 +482,8 @@ static const struct udevice_id tsc_timer_ids[] = { { } }; -U_BOOT_DRIVER(tsc_timer) = { - .name = "tsc_timer", +U_BOOT_DRIVER(x86_tsc_timer) = { + .name = "x86_tsc_timer", .id = UCLASS_TIMER, .of_match = tsc_timer_ids, .probe = tsc_timer_probe, diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 210d9f8093..4532a40e45 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -21,12 +21,6 @@ config WATCHDOG_TIMEOUT_MSECS config HW_WATCHDOG bool -config WATCHDOG_RESET_DISABLE - bool "Disable reset watchdog" - help - Disable reset watchdog, which can let WATCHDOG_RESET invalid, so - that the watchdog will not be fed in u-boot. - config IMX_WATCHDOG bool "Enable Watchdog Timer support for IMX and LSCH2 of NXP" select HW_WATCHDOG if !WDT @@ -34,6 +28,13 @@ config IMX_WATCHDOG Select this to enable the IMX and LSCH2 of Layerscape watchdog driver. +config WATCHDOG_RESET_DISABLE + bool "Disable reset watchdog" + depends on IMX_WATCHDOG + help + Disable reset watchdog, which can let WATCHDOG_RESET invalid, so + that the watchdog will not be fed in u-boot. + config OMAP_WATCHDOG bool "TI OMAP watchdog driver" depends on ARCH_OMAP2PLUS |