diff options
| author | Tom Rini <[email protected]> | 2022-07-11 10:18:13 -0400 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2022-07-11 14:58:57 -0400 |
| commit | 36b661dc919da318c163a45f4a220d2e3d9db608 (patch) | |
| tree | 268703050f58280feb3287d48eb0cedc974730e1 /drivers/misc | |
| parent | e092e3250270a1016c877da7bdd9384f14b1321e (diff) | |
| parent | 05a4859637567b13219efd6f1707fb236648b1b7 (diff) | |
Merge branch 'next'
Diffstat (limited to 'drivers/misc')
| -rw-r--r-- | drivers/misc/Kconfig | 82 | ||||
| -rw-r--r-- | drivers/misc/Makefile | 4 | ||||
| -rw-r--r-- | drivers/misc/i2c_eeprom.c | 11 | ||||
| -rw-r--r-- | drivers/misc/i2c_eeprom_emul.c | 4 | ||||
| -rw-r--r-- | drivers/misc/ls2_sfp.c | 350 | ||||
| -rw-r--r-- | drivers/misc/misc_sandbox.c | 3 | ||||
| -rw-r--r-- | drivers/misc/npcm_host_intf.c | 110 | ||||
| -rw-r--r-- | drivers/misc/npcm_otp.c | 512 | ||||
| -rw-r--r-- | drivers/misc/nvmem.c | 142 | ||||
| -rw-r--r-- | drivers/misc/qfw_sandbox.c | 2 | ||||
| -rw-r--r-- | drivers/misc/stm32_rcc.c | 6 | ||||
| -rw-r--r-- | drivers/misc/test_drv.c | 6 |
12 files changed, 1209 insertions, 23 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 007c72819fb..e839c08c191 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -43,6 +43,22 @@ config VPL_MISC set of generic read, write and ioctl methods may be used to access the device. +config NVMEM + bool "NVMEM support" + help + This adds support for a common interface to different types of + non-volatile memory. Consumers can use nvmem-cells properties to look + up hardware configuration data such as MAC addresses and calibration + settings. + +config SPL_NVMEM + bool "NVMEM support in SPL" + help + This adds support for a common interface to different types of + non-volatile memory. Consumers can use nvmem-cells properties to look + up hardware configuration data such as MAC addresses and calibration + settings. + config ALTERA_SYSID bool "Altera Sysid support" depends on MISC @@ -125,7 +141,7 @@ config CROS_EC config SPL_CROS_EC bool "Enable Chrome OS EC in SPL" - depends on SPL + depends on SPL_MISC help Enable access to the Chrome OS EC in SPL. This is a separate microcontroller typically available on a SPI bus on Chromebooks. It @@ -135,7 +151,7 @@ config SPL_CROS_EC config TPL_CROS_EC bool "Enable Chrome OS EC in TPL" - depends on TPL + depends on TPL_MISC help Enable access to the Chrome OS EC in TPL. This is a separate microcontroller typically available on a SPI bus on Chromebooks. It @@ -145,7 +161,7 @@ config TPL_CROS_EC config VPL_CROS_EC bool "Enable Chrome OS EC in VPL" - depends on VPL + depends on VPL_MISC help Enable access to the Chrome OS EC in VPL. This is a separate microcontroller typically available on a SPI bus on Chromebooks. It @@ -173,7 +189,7 @@ config CROS_EC_LPC config SPL_CROS_EC_LPC bool "Enable Chrome OS EC LPC driver in SPL" - depends on CROS_EC + depends on CROS_EC && SPL_MISC help Enable I2C access to the Chrome OS EC. This is used on x86 Chromebooks such as link and falco. The keyboard is provided @@ -182,7 +198,7 @@ config SPL_CROS_EC_LPC config TPL_CROS_EC_LPC bool "Enable Chrome OS EC LPC driver in TPL" - depends on CROS_EC + depends on CROS_EC && TPL_MISC help Enable I2C access to the Chrome OS EC. This is used on x86 Chromebooks such as link and falco. The keyboard is provided @@ -191,7 +207,7 @@ config TPL_CROS_EC_LPC config VPL_CROS_EC_LPC bool "Enable Chrome OS EC LPC driver in VPL" - depends on CROS_EC + depends on CROS_EC && VPL_MISC help Enable I2C access to the Chrome OS EC. This is used on x86 Chromebooks such as link and falco. The keyboard is provided @@ -259,6 +275,20 @@ config FSL_SEC_MON Security Monitor can be transitioned on any security failures, like software violations or hardware security violations. +choice + prompt "Security monitor interaction endianess" + depends on FSL_SEC_MON + default SYS_FSL_SEC_MON_BE if PPC + default SYS_FSL_SEC_MON_LE + +config SYS_FSL_SEC_MON_LE + bool "Security monitor interactions are little endian" + +config SYS_FSL_SEC_MON_BE + bool "Security monitor interactions are big endian" + +endchoice + config IRQ bool "Interrupt controller" help @@ -273,6 +303,20 @@ config JZ4780_EFUSE help This selects support for the eFUSE on Ingenic JZ4780 SoCs. +config LS2_SFP + bool "Layerscape Security Fuse Processor" + depends on FSL_LSCH2 || ARCH_LS1021A + depends on MISC + imply DM_REGULATOR + help + This adds support for the Security Fuse Processor found on Layerscape + SoCs. It contains various fuses related to secure boot, including the + Super Root Key hash, One-Time-Programmable Master Key, Debug + Challenge/Response values, and others. Fuses are numbered according + to their four-byte offset from the start of the bank. + + If you don't need to read/program fuses, say 'n'. + config MXC_OCOTP bool "Enable MXC OCOTP Driver" depends on ARCH_IMX8M || ARCH_MX6 || ARCH_MX7 || ARCH_MX7ULP || ARCH_VF610 @@ -282,15 +326,30 @@ config MXC_OCOTP Programmable memory pages that are stored on the some Freescale i.MX processors. +config NPCM_HOST + bool "Enable support espi or LPC for Host" + depends on REGMAP && SYSCON + help + Enable NPCM BMC espi or LPC support for Host reading and writing. + config SPL_MXC_OCOTP bool "Enable MXC OCOTP driver in SPL" - depends on SPL && (ARCH_IMX8M || ARCH_MX6 || ARCH_MX7 || ARCH_MX7ULP || ARCH_VF610) + depends on SPL_MISC && (ARCH_IMX8M || ARCH_MX6 || ARCH_MX7 || ARCH_MX7ULP || ARCH_VF610) default y help If you say Y here, you will get support for the One Time Programmable memory pages, that are stored on some Freescale i.MX processors, in SPL. +config NPCM_OTP + bool "Nnvoton NPCM BMC On-Chip OTP Memory Support" + depends on (ARM && ARCH_NPCM) + default n + help + Support NPCM BMC OTP memory (fuse). + To compile this driver as a module, choose M here: the module + will be called npcm_otp. + config NUVOTON_NCT6102D bool "Enable Nuvoton NCT6102D Super I/O driver" help @@ -314,7 +373,7 @@ config P2SB config SPL_P2SB bool "Intel Primary to Sideband Bridge in SPL" - depends on SPL && (X86 || SANDBOX) + depends on SPL_MISC && (X86 || SANDBOX) help The Primary to Sideband Bridge is used to access various peripherals through memory-mapped I/O in a large chunk of PCI space. The space is @@ -324,7 +383,7 @@ config SPL_P2SB config TPL_P2SB bool "Intel Primary to Sideband Bridge in TPL" - depends on TPL && (X86 || SANDBOX) + depends on TPL_MISC && (X86 || SANDBOX) help The Primary to Sideband Bridge is used to access various peripherals through memory-mapped I/O in a large chunk of PCI space. The space is @@ -343,7 +402,7 @@ config PWRSEQ config SPL_PWRSEQ bool "Enable power-sequencing drivers for SPL" - depends on PWRSEQ + depends on SPL_MISC && PWRSEQ help Power-sequencing drivers provide support for controlling power for devices. They are typically referenced by a phandle from another @@ -460,7 +519,7 @@ config I2C_EEPROM config SPL_I2C_EEPROM bool "Enable driver for generic I2C-attached EEPROMs for SPL" - depends on MISC && SPL && SPL_DM + depends on SPL_MISC help This option is an SPL-variant of the I2C_EEPROM option. See the help of I2C_EEPROM for details. @@ -513,6 +572,7 @@ config FS_LOADER config SPL_FS_LOADER bool "Enable loader driver for file system" + depends on SPL help This is file system generic loader which can be used to load the file image from the storage into target such as memory. diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index b9c54bdd99b..022e54e0650 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -4,6 +4,7 @@ # Wolfgang Denk, DENX Software Engineering, [email protected]. obj-$(CONFIG_$(SPL_TPL_)MISC) += misc-uclass.o +obj-$(CONFIG_$(SPL_TPL_)NVMEM) += nvmem.o obj-$(CONFIG_$(SPL_TPL_)CROS_EC) += cros_ec.o obj-$(CONFIG_$(SPL_TPL_)CROS_EC_SANDBOX) += cros_ec_sandbox.o @@ -52,8 +53,11 @@ obj-$(CONFIG_IMX8ULP) += imx8ulp/ obj-$(CONFIG_LED_STATUS) += status_led.o obj-$(CONFIG_LED_STATUS_GPIO) += gpio_led.o obj-$(CONFIG_MPC83XX_SERDES) += mpc83xx_serdes.o +obj-$(CONFIG_$(SPL_TPL_)LS2_SFP) += ls2_sfp.o obj-$(CONFIG_$(SPL_)MXC_OCOTP) += mxc_ocotp.o obj-$(CONFIG_MXS_OCOTP) += mxs_ocotp.o +obj-$(CONFIG_NPCM_OTP) += npcm_otp.o +obj-$(CONFIG_NPCM_HOST) += npcm_host_intf.o obj-$(CONFIG_NUVOTON_NCT6102D) += nuvoton_nct6102d.o obj-$(CONFIG_P2SB) += p2sb-uclass.o obj-$(CONFIG_PCA9551_LED) += pca9551_led.o diff --git a/drivers/misc/i2c_eeprom.c b/drivers/misc/i2c_eeprom.c index 89a450d0f8d..bdd7e018cc6 100644 --- a/drivers/misc/i2c_eeprom.c +++ b/drivers/misc/i2c_eeprom.c @@ -33,7 +33,8 @@ int i2c_eeprom_read(struct udevice *dev, int offset, uint8_t *buf, int size) return ops->read(dev, offset, buf, size); } -int i2c_eeprom_write(struct udevice *dev, int offset, uint8_t *buf, int size) +int i2c_eeprom_write(struct udevice *dev, int offset, const uint8_t *buf, + int size) { const struct i2c_eeprom_ops *ops = device_get_ops(dev); @@ -169,13 +170,6 @@ static const struct i2c_eeprom_drv_data eeprom_data = { .offset_len = 1, }; -static const struct i2c_eeprom_drv_data mc24aa02e48_data = { - .size = 256, - .pagesize = 8, - .addr_offset_mask = 0, - .offset_len = 1, -}; - static const struct i2c_eeprom_drv_data atmel24c01a_data = { .size = 128, .pagesize = 8, @@ -263,7 +257,6 @@ static const struct i2c_eeprom_drv_data atmel24c512_data = { static const struct udevice_id i2c_eeprom_std_ids[] = { { .compatible = "i2c-eeprom", (ulong)&eeprom_data }, - { .compatible = "microchip,24aa02e48", (ulong)&mc24aa02e48_data }, { .compatible = "atmel,24c01", (ulong)&atmel24c01a_data }, { .compatible = "atmel,24c01a", (ulong)&atmel24c01a_data }, { .compatible = "atmel,24c02", (ulong)&atmel24c02_data }, diff --git a/drivers/misc/i2c_eeprom_emul.c b/drivers/misc/i2c_eeprom_emul.c index 85b127c406c..6f32087ede5 100644 --- a/drivers/misc/i2c_eeprom_emul.c +++ b/drivers/misc/i2c_eeprom_emul.c @@ -171,11 +171,15 @@ static int sandbox_i2c_eeprom_probe(struct udevice *dev) { struct sandbox_i2c_flash_plat_data *plat = dev_get_plat(dev); struct sandbox_i2c_flash *priv = dev_get_priv(dev); + /* For eth3 */ + const u8 mac[] = { 0x02, 0x00, 0x11, 0x22, 0x33, 0x45 }; priv->data = calloc(1, plat->size); if (!priv->data) return -ENOMEM; + memcpy(&priv->data[24], mac, sizeof(mac)); + return 0; } diff --git a/drivers/misc/ls2_sfp.c b/drivers/misc/ls2_sfp.c new file mode 100644 index 00000000000..dd104962c28 --- /dev/null +++ b/drivers/misc/ls2_sfp.c @@ -0,0 +1,350 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2022 Sean Anderson <[email protected]> + * + * This driver supports the Security Fuse Processor device found on some + * Layerscape processors. At the moment, we only support a few processors. + * This driver was written with reference to the Layerscape SDK User + * Guide [1] and the ATF SFP driver [2]. + * + * [1] https://docs.nxp.com/bundle/GUID-487B2E69-BB19-42CB-AC38-7EF18C0FE3AE/page/GUID-27FC40AD-3321-4A82-B29E-7BB49EE94F23.html + * [2] https://source.codeaurora.org/external/qoriq/qoriq-components/atf/tree/drivers/nxp/sfp?h=github.com/master + */ + +#define LOG_CATEGORY UCLASS_MISC +#include <common.h> +#include <clk.h> +#include <fuse.h> +#include <misc.h> +#include <asm/io.h> +#include <dm/device_compat.h> +#include <dm/read.h> +#include <linux/bitfield.h> +#include <power/regulator.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define SFP_INGR 0x20 +#define SFP_SVHESR 0x24 +#define SFP_SFPCR 0x28 + +#define SFP_START 0x200 +#define SFP_END 0x284 +#define SFP_SIZE (SFP_END - SFP_START + 4) + +#define SFP_INGR_ERR BIT(8) +#define SFP_INGR_INST GENMASK(7, 0) + +#define SFP_INGR_READFB 0x01 +#define SFP_INGR_PROGFB 0x02 + +#define SFP_SFPCR_PPW GENMASK(15, 0) + +enum ls2_sfp_ioctl { + LS2_SFP_IOCTL_READ, + LS2_SFP_IOCTL_PROG, +}; + +/** + * struct ls2_sfp_priv - private data for LS2 SFP + * @base: Base address of SFP + * @supply: The (optional) supply for TA_PROG_SFP + * @programmed: Whether we've already programmed the fuses since the last + * reset. The SFP has a *very* limited amount of programming + * cycles (two to six, depending on the model), so we try and + * prevent accidentally performing additional programming + * cycles. + * @dirty: Whether the mirror registers have been written to (overridden) + * since we've last read the fuses (either as part of the reset + * process or using a READFB instruction). There is a much larger, + * but still finite, limit on the number of SFP read cycles (around + * 300,000), so we try and minimize reads as well. + */ +struct ls2_sfp_priv { + void __iomem *base; + struct udevice *supply; + bool programmed, dirty; +}; + +static u32 ls2_sfp_readl(struct ls2_sfp_priv *priv, ulong off) +{ + u32 val = be32_to_cpu(readl(priv->base + off)); + + log_debug("%08x = readl(%p)\n", val, priv->base + off); + return val; +} + +static void ls2_sfp_writel(struct ls2_sfp_priv *priv, ulong val, ulong off) +{ + log_debug("writel(%08lx, %p)\n", val, priv->base + off); + writel(cpu_to_be32(val), priv->base + off); +} + +static bool ls2_sfp_validate(struct udevice *dev, int offset, int size) +{ + if (offset < 0 || size < 0) { + dev_notice(dev, "size and offset must be positive\n"); + return false; + } + + if (offset & 3 || size & 3) { + dev_notice(dev, "size and offset must be multiples of 4\n"); + return false; + } + + if (offset + size > SFP_SIZE) { + dev_notice(dev, "size + offset must be <= %#x\n", SFP_SIZE); + return false; + } + + return true; +} + +static int ls2_sfp_read(struct udevice *dev, int offset, void *buf_bytes, + int size) +{ + int i; + struct ls2_sfp_priv *priv = dev_get_priv(dev); + u32 *buf = buf_bytes; + + if (!ls2_sfp_validate(dev, offset, size)) + return -EINVAL; + + for (i = 0; i < size; i += 4) + buf[i >> 2] = ls2_sfp_readl(priv, SFP_START + offset + i); + + return size; +} + +static int ls2_sfp_write(struct udevice *dev, int offset, + const void *buf_bytes, int size) +{ + int i; + struct ls2_sfp_priv *priv = dev_get_priv(dev); + const u32 *buf = buf_bytes; + + if (!ls2_sfp_validate(dev, offset, size)) + return -EINVAL; + + for (i = 0; i < size; i += 4) + ls2_sfp_writel(priv, buf[i >> 2], SFP_START + offset + i); + + priv->dirty = true; + return size; +} + +static int ls2_sfp_check_secret(struct udevice *dev) +{ + struct ls2_sfp_priv *priv = dev_get_priv(dev); + u32 svhesr = ls2_sfp_readl(priv, SFP_SVHESR); + + if (svhesr) { + dev_warn(dev, "secret value hamming error not zero: %08x\n", + svhesr); + return -EIO; + } + return 0; +} + +static int ls2_sfp_transaction(struct ls2_sfp_priv *priv, ulong inst) +{ + u32 ingr; + + ls2_sfp_writel(priv, inst, SFP_INGR); + + do { + ingr = ls2_sfp_readl(priv, SFP_INGR); + } while (FIELD_GET(SFP_INGR_INST, ingr)); + + return FIELD_GET(SFP_INGR_ERR, ingr) ? -EIO : 0; +} + +static int ls2_sfp_ioctl(struct udevice *dev, unsigned long request, void *buf) +{ + int ret; + struct ls2_sfp_priv *priv = dev_get_priv(dev); + + switch (request) { + case LS2_SFP_IOCTL_READ: + if (!priv->dirty) { + dev_dbg(dev, "ignoring read request, since fuses are not dirty\n"); + return 0; + } + + ret = ls2_sfp_transaction(priv, SFP_INGR_READFB); + if (ret) { + dev_err(dev, "error reading fuses\n"); + return ret; + } + + ls2_sfp_check_secret(dev); + priv->dirty = false; + return 0; + case LS2_SFP_IOCTL_PROG: + if (priv->programmed) { + dev_warn(dev, "fuses already programmed\n"); + return -EPERM; + } + + ret = ls2_sfp_check_secret(dev); + if (ret) + return ret; + + if (priv->supply) { + ret = regulator_set_enable(priv->supply, true); + if (ret) + return ret; + } + + ret = ls2_sfp_transaction(priv, SFP_INGR_PROGFB); + priv->programmed = true; + if (priv->supply) + regulator_set_enable(priv->supply, false); + + if (ret) + dev_err(dev, "error programming fuses\n"); + return ret; + default: + dev_dbg(dev, "unknown ioctl %lu\n", request); + return -EINVAL; + } +} + +static const struct misc_ops ls2_sfp_ops = { + .read = ls2_sfp_read, + .write = ls2_sfp_write, + .ioctl = ls2_sfp_ioctl, +}; + +static int ls2_sfp_probe(struct udevice *dev) +{ + int ret; + struct clk clk; + struct ls2_sfp_priv *priv = dev_get_priv(dev); + ulong rate; + + priv->base = dev_read_addr_ptr(dev); + if (!priv->base) { + dev_dbg(dev, "could not read register base\n"); + return -EINVAL; + } + + ret = device_get_supply_regulator(dev, "ta-sfp-prog", &priv->supply); + if (ret && ret != -ENODEV && ret != -ENOSYS) { + dev_dbg(dev, "problem getting supply (err %d)\n", ret); + return ret; + } + + ret = clk_get_by_name(dev, "sfp", &clk); + if (ret == -ENOSYS) { + rate = gd->bus_clk / 4; + } else if (ret) { + dev_dbg(dev, "could not get clock (err %d)\n", ret); + return ret; + } else { + ret = clk_enable(&clk); + if (ret) { + dev_dbg(dev, "could not enable clock (err %d)\n", ret); + return ret; + } + + rate = clk_get_rate(&clk); + clk_free(&clk); + if (!rate || IS_ERR_VALUE(rate)) { + ret = rate ? rate : -ENOENT; + dev_dbg(dev, "could not get clock rate (err %d)\n", + ret); + return ret; + } + } + + /* sfp clock in MHz * 12 */ + ls2_sfp_writel(priv, FIELD_PREP(SFP_SFPCR_PPW, rate * 12 / 1000000), + SFP_SFPCR); + + ls2_sfp_check_secret(dev); + return 0; +} + +static const struct udevice_id ls2_sfp_ids[] = { + { .compatible = "fsl,ls1021a-sfp" }, + { } +}; + +U_BOOT_DRIVER(ls2_sfp) = { + .name = "ls2_sfp", + .id = UCLASS_MISC, + .of_match = ls2_sfp_ids, + .probe = ls2_sfp_probe, + .ops = &ls2_sfp_ops, + .priv_auto = sizeof(struct ls2_sfp_priv), +}; + +static int ls2_sfp_device(struct udevice **dev) +{ + int ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_DRIVER_GET(ls2_sfp), dev); + + if (ret) + log_debug("device not found (err %d)\n", ret); + return ret; +} + +int fuse_read(u32 bank, u32 word, u32 *val) +{ + int ret; + struct udevice *dev; + + ret = ls2_sfp_device(&dev); + if (ret) + return ret; + + ret = misc_ioctl(dev, LS2_SFP_IOCTL_READ, NULL); + if (ret) + return ret; + + ret = misc_read(dev, word << 2, val, sizeof(*val)); + return ret < 0 ? ret : 0; +} + +int fuse_sense(u32 bank, u32 word, u32 *val) +{ + int ret; + struct udevice *dev; + + ret = ls2_sfp_device(&dev); + if (ret) + return ret; + + ret = misc_read(dev, word << 2, val, sizeof(*val)); + return ret < 0 ? ret : 0; +} + +int fuse_prog(u32 bank, u32 word, u32 val) +{ + int ret; + struct udevice *dev; + + ret = ls2_sfp_device(&dev); + if (ret) + return ret; + + ret = misc_write(dev, word << 2, &val, sizeof(val)); + if (ret < 0) + return ret; + + return misc_ioctl(dev, LS2_SFP_IOCTL_PROG, NULL); +} + +int fuse_override(u32 bank, u32 word, u32 val) +{ + int ret; + struct udevice *dev; + + ret = ls2_sfp_device(&dev); + if (ret) + return ret; + + ret = misc_write(dev, word << 2, &val, sizeof(val)); + return ret < 0 ? ret : 0; +} diff --git a/drivers/misc/misc_sandbox.c b/drivers/misc/misc_sandbox.c index 0e4292fd0aa..31cde2dbac0 100644 --- a/drivers/misc/misc_sandbox.c +++ b/drivers/misc/misc_sandbox.c @@ -112,8 +112,11 @@ static const struct misc_ops misc_sandbox_ops = { int misc_sandbox_probe(struct udevice *dev) { struct misc_sandbox_priv *priv = dev_get_priv(dev); + /* For eth5 */ + const u8 mac[] = { 0x02, 0x00, 0x11, 0x22, 0x33, 0x46 }; priv->enabled = true; + memcpy(&priv->mem[16], mac, sizeof(mac)); return 0; } diff --git a/drivers/misc/npcm_host_intf.c b/drivers/misc/npcm_host_intf.c new file mode 100644 index 00000000000..0244e404570 --- /dev/null +++ b/drivers/misc/npcm_host_intf.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Host interface (LPC or eSPI) configuration on Nuvoton BMC + * Copyright (c) 2022 Nuvoton Technology Corp. + */ + +#include <common.h> +#include <dm.h> +#include <regmap.h> +#include <syscon.h> +#include <asm/io.h> +#include <dm/device_compat.h> +#include <linux/bitfield.h> + +#define SMC_CTL_REG_ADDR 0xc0001001 +#define SMC_CTL_HOSTWAIT 0x80 + +/* GCR Register Offsets */ +#define HIFCR 0x50 +#define MFSEL1 0x260 +#define MFSEL4 0x26c + +/* ESPI Register offsets */ +#define ESPICFG 0x4 +#define ESPIHINDP 0x80 + +/* MFSEL bit fileds */ +#define MFSEL1_LPCSEL BIT(26) +#define MFSEL4_ESPISEL BIT(8) + +/* ESPICFG bit fileds */ +#define CHSUPP_MASK GENMASK(27, 24) +#define IOMODE_MASK GENMASK(9, 8) +#define IOMODE_SDQ FIELD_PREP(IOMODE_MASK, 3) +#define MAXFREQ_MASK GENMASK(12, 10) +#define MAXFREQ_33MHZ FIELD_PREP(MAXFREQ_MASK, 2) + +/* ESPIHINDP bit fileds */ +#define AUTO_SBLD BIT(4) +#define AUTO_HS1 BIT(8) +#define AUTO_HS2 BIT(12) +#define AUTO_HS3 BIT(16) + +static int npcm_host_intf_bind(struct udevice *dev) +{ + struct regmap *syscon; + void __iomem *base; + u32 ch_supp, val; + u32 ioaddr; + const char *type; + int ret; + + /* Release host wait */ + setbits_8(SMC_CTL_REG_ADDR, SMC_CTL_HOSTWAIT); + + syscon = syscon_regmap_lookup_by_phandle(dev, "syscon"); + if (IS_ERR(syscon)) { + dev_err(dev, "%s: unable to get syscon, dev %s\n", __func__, dev->name); + return PTR_ERR(syscon); + } + + ioaddr = dev_read_u32_default(dev, "ioaddr", 0); + if (ioaddr) + regmap_write(syscon, HIFCR, ioaddr); + + type = dev_read_string(dev, "type"); + if (!type) + return -EINVAL; + + if (!strcmp(type, "espi")) { + base = dev_read_addr_ptr(dev); + if (!base) + return -EINVAL; + + ret = dev_read_u32(dev, "channel-support", &ch_supp); + if (ret) + return ret; + + /* Select eSPI pins function */ + regmap_update_bits(syscon, MFSEL1, MFSEL1_LPCSEL, 0); + regmap_update_bits(syscon, MFSEL4, MFSEL4_ESPISEL, MFSEL4_ESPISEL); + + val = AUTO_SBLD | AUTO_HS1 | AUTO_HS2 | AUTO_HS3 | ch_supp; + writel(val, base + ESPIHINDP); + + val = readl(base + ESPICFG); + val &= ~(CHSUPP_MASK | IOMODE_MASK | MAXFREQ_MASK); + val |= IOMODE_SDQ | MAXFREQ_33MHZ | FIELD_PREP(CHSUPP_MASK, ch_supp); + writel(val, base + ESPICFG); + } else if (!strcmp(type, "lpc")) { + /* Select LPC pin function */ + regmap_update_bits(syscon, MFSEL4, MFSEL4_ESPISEL, 0); + regmap_update_bits(syscon, MFSEL1, MFSEL1_LPCSEL, MFSEL1_LPCSEL); + } + + return 0; +} + +static const struct udevice_id npcm_hostintf_ids[] = { + { .compatible = "nuvoton,npcm750-host-intf" }, + { .compatible = "nuvoton,npcm845-host-intf" }, + { } +}; + +U_BOOT_DRIVER(npcm_host_intf) = { + .name = "npcm_host_intf", + .id = UCLASS_MISC, + .of_match = npcm_hostintf_ids, + .bind = npcm_host_intf_bind, +}; diff --git a/drivers/misc/npcm_otp.c b/drivers/misc/npcm_otp.c new file mode 100644 index 00000000000..304910888bb --- /dev/null +++ b/drivers/misc/npcm_otp.c @@ -0,0 +1,512 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2021 Nuvoton Technology Corp. + */ + +#include <clk.h> +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <fuse.h> +#include <asm/io.h> +#include <linux/delay.h> +#include <asm/arch/otp.h> + +struct npcm_otp_priv { + struct npcm_otp_regs *regs[2]; +}; + +static struct npcm_otp_priv *otp_priv; + +/*----------------------------------------------------------------------------*/ +/* Function: npcm_otp_check_inputs */ +/* */ +/* Parameters: arr - fuse array number to check */ +/* word - fuse word (offset) to check */ +/* Returns: int */ +/* Side effects: */ +/* Description: Checks is arr and word are illegal and do not exceed */ +/* their range. Return 0 if they are legal, -1 if not */ +/*----------------------------------------------------------------------------*/ +static int npcm_otp_check_inputs(u32 arr, u32 word) +{ + if (arr >= NPCM_NUM_OF_SA) { + if (IS_ENABLED(CONFIG_ARCH_NPCM8XX)) + printf("\nError: npcm8XX otp includs only one bank: 0\n"); + if (IS_ENABLED(CONFIG_ARCH_NPCM7XX)) + printf("\nError: npcm7XX otp includs only two banks: 0 and 1\n"); + return -1; + } + + if (word >= NPCM_OTP_ARR_BYTE_SIZE) { + printf("\nError: npcm otp array comprises only %d bytes, numbered from 0 to %d\n", + NPCM_OTP_ARR_BYTE_SIZE, NPCM_OTP_ARR_BYTE_SIZE - 1); + return -1; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/* Function: npcm_otp_wait_for_otp_ready */ +/* */ +/* Parameters: array - fuse array to wait for */ +/* Returns: int */ +/* Side effects: */ +/* Description: Initialize the Fuse HW module. */ +/*----------------------------------------------------------------------------*/ +static int npcm_otp_wait_for_otp_ready(u32 arr, u32 timeout) +{ + struct npcm_otp_regs *regs = otp_priv->regs[arr]; + u32 time = timeout; + + /*------------------------------------------------------------------------*/ + /* check parameters validity */ + /*------------------------------------------------------------------------*/ + if (arr > NPCM_FUSE_SA) + return -EINVAL; + + while (--time > 1) { + if (readl(®s->fst) & FST_RDY) { + /* fuse is ready, clear the status. */ + writel(readl(®s->fst) | FST_RDST, ®s->fst); + return 0; + } + } + + /* try to clear the status in case it was set */ + writel(readl(®s->fst) | FST_RDST, ®s->fst); + + return -EINVAL; +} + +/*----------------------------------------------------------------------------*/ +/* Function: npcm_otp_read_byte */ +/* */ +/* Parameters: arr - Storage Array type [input]. */ +/* addr - Byte-address to read from [input]. */ +/* data - Pointer to result [output]. */ +/* Returns: none */ +/* Side effects: */ +/* Description: Read 8-bit data from an OTP storage array. */ +/*----------------------------------------------------------------------------*/ +static void npcm_otp_read_byte(u32 arr, u32 addr, u8 *data) +{ + struct npcm_otp_regs *regs = otp_priv->regs[arr]; + + /* Wait for the Fuse Box Idle */ + npcm_otp_wait_for_otp_ready(arr, 0xDEADBEEF); + + /* Configure the byte address in the fuse array for read operation */ + writel(FADDR_VAL(addr, 0), ®s->faddr); + + /* Initiate a read cycle */ + writel(READ_INIT, ®s->fctl); + + /* Wait for read operation completion */ + npcm_otp_wait_for_otp_ready(arr, 0xDEADBEEF); + + /* Read the result */ + *data = readl(®s->fdata) & FDATA_MASK; + + /* Clean FDATA contents to prevent unauthorized software from reading + * sensitive information + */ + writel(FDATA_CLEAN_VALUE, ®s->fdata); +} + +/*----------------------------------------------------------------------------*/ +/* Function: npcm_otp_bit_is_programmed */ +/* */ +/* Parameters: arr - Storage Array type [input]. */ +/* byte_offset - Byte offset in array [input]. */ +/* bit_offset - Bit offset in byte [input]. */ +/* Returns: Nonzero if bit is programmed, zero otherwise. */ +/* Side effects: */ +/* Description: Check if a bit is programmed in an OTP storage array. */ +/*----------------------------------------------------------------------------*/ +static bool npcm_otp_bit_is_programmed(u32 arr, + u32 byte_offset, u8 bit_offset) +{ + u32 data = 0; + + /* Read the entire byte you wish to program */ + npcm_otp_read_byte(arr, byte_offset, (u8 *)&data); + + /* Check whether the bit is already programmed */ + if (data & (1 << bit_offset)) + return true; + + return false; +} + +/*----------------------------------------------------------------------------*/ +/* Function: npcm_otp_program_bit */ +/* */ +/* Parameters: arr - Storage Array type [input]. */ +/* byte)offset - Byte offset in array [input]. */ +/* bit_offset - Bit offset in byte [input]. */ +/* Returns: int */ +/* Side effects: */ +/* Description: Program (set to 1) a bit in an OTP storage array. */ +/*----------------------------------------------------------------------------*/ +static int npcm_otp_program_bit(u32 arr, u32 byte_offset, + u8 bit_offset) +{ + struct npcm_otp_regs *regs = otp_priv->regs[arr]; + int count; + u8 read_data; + + /* Wait for the Fuse Box Idle */ + npcm_otp_wait_for_otp_ready(arr, 0xDEADBEEF); + + /* Make sure the bit is not already programmed */ + if (npcm_otp_bit_is_programmed(arr, byte_offset, bit_offset)) + return 0; + + /* Configure the bit address in the fuse array for program operation */ + writel(FADDR_VAL(byte_offset, bit_offset), ®s->faddr); + writel(readl(®s->faddr) | FADDR_IN_PROG, ®s->faddr); + + // program up to MAX_PROGRAM_PULSES + for (count = 1; count <= MAX_PROGRAM_PULSES; count++) { + /* Initiate a program cycle */ + writel(PROGRAM_ARM, ®s->fctl); + writel(PROGRAM_INIT, ®s->fctl); + + /* Wait for program operation completion */ + npcm_otp_wait_for_otp_ready(arr, 0xDEADBEEF); + + // after MIN_PROGRAM_PULSES start verifying the result + if (count >= MIN_PROGRAM_PULSES) { + /* Initiate a read cycle */ + writel(READ_INIT, ®s->fctl); + + /* Wait for read operation completion */ + npcm_otp_wait_for_otp_ready(arr, 0xDEADBEEF); + + /* Read the result */ + read_data = readl(®s->fdata) & FDATA_MASK; + + /* If the bit is set the sequence ended correctly */ + if (read_data & (1 << bit_offset)) + break; + } + } + + // check if programmking failed + if (count > MAX_PROGRAM_PULSES) { + printf("program fail\n"); + return -EINVAL; + } + + /* + * Clean FDATA contents to prevent unauthorized software from reading + * sensitive information + */ + writel(FDATA_CLEAN_VALUE, ®s->fdata); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/* Function: npcm_otp_program_byte */ +/* */ +/* Parameters: arr - Storage Array type [input]. */ +/* byte_offset - Byte offset in array [input]. */ +/* value - Byte to program [input]. */ +/* Returns: int */ +/* Side effects: */ +/* Description: Program (set to 1) a given byte's relevant bits in an */ +/* OTP storage array. */ +/*----------------------------------------------------------------------------*/ +static int npcm_otp_program_byte(u32 arr, u32 byte_offset, + u8 value) +{ + int status = 0; + unsigned int i; + u8 data = 0; + int rc; + + rc = npcm_otp_check_inputs(arr, byte_offset); + if (rc != 0) + return rc; + + /* Wait for the Fuse Box Idle */ + npcm_otp_wait_for_otp_ready(arr, 0xDEADBEEF); + + /* Read the entire byte you wish to program */ + npcm_otp_read_byte(arr, byte_offset, &data); + + /* In case all relevant bits are already programmed - nothing to do */ + if ((~data & value) == 0) + return status; + + /* Program unprogrammed bits. */ + for (i = 0; i < 8; i++) { + if (value & (1 << i)) { + /* Program (set to 1) the relevant bit */ + int last_status = npcm_otp_program_bit(arr, byte_offset, (u8)i); + + if (last_status != 0) + status = last_status; + } + } + return status; +} + +/*----------------------------------------------------------------------------*/ +/* Function: npcm_otp_is_fuse_array_disabled */ +/* */ +/* Parameters: arr - Storage Array type [input]. */ +/* Returns: bool */ +/* Side effects: */ +/* Description: Return true if access to the first 2048 bits of the */ +/* specified fuse array is disabled, false if not */ +/*----------------------------------------------------------------------------*/ +bool npcm_otp_is_fuse_array_disabled(u32 arr) +{ + struct npcm_otp_regs *regs = otp_priv->regs[arr]; + + return (readl(®s->fcfg) & FCFG_FDIS) != 0; +} + +int npcm_otp_select_key(u8 key_index) +{ + struct npcm_otp_regs *regs = otp_priv->regs[NPCM_KEY_SA]; + u32 idx = 0; + u32 time = 0xDAEDBEEF; + + if (key_index >= 4) + return -1; + + /* Do not destroy ECCDIS bit */ + idx = readl(®s->fustrap_fkeyind); + + /* Configure the key size */ + idx &= ~FKEYIND_KSIZE_MASK; + idx |= FKEYIND_KSIZE_256; + + /* Configure the key index (0 to 3) */ + idx &= ~FKEYIND_KIND_MASK; + idx |= FKEYIND_KIND_KEY(key_index); + + writel(idx, ®s->fustrap_fkeyind); + + /* Wait for selection completetion */ + while (--time > 1) { + if (readl(®s->fustrap_fkeyind) & FKEYIND_KVAL) + return 0; + udelay(1); + } + + return -1; +} + +/*----------------------------------------------------------------------------*/ +/* Function: npcm_otp_nibble_parity_ecc_encode */ +/* */ +/* Parameters: datain - pointer to decoded data buffer */ +/* dataout - pointer to encoded data buffer (buffer size */ +/* should be 2 x dataout) */ +/* size - size of encoded data (decoded data x 2) */ +/* Returns: none */ +/* Side effects: */ +/* Description: Decodes the data according to nibble parity ECC scheme. */ +/* Size specifies the encoded data size. */ +/* Decodes whole bytes only */ +/*----------------------------------------------------------------------------*/ +void npcm_otp_nibble_parity_ecc_encode(u8 *datain, u8 *dataout, u32 size) +{ + u32 i, idx; + u8 E0, E1, E2, E3; + + for (i = 0; i < (size / 2); i++) { + E0 = (datain[i] >> 0) & 0x01; + E1 = (datain[i] >> 1) & 0x01; + E2 = (datain[i] >> 2) & 0x01; + E3 = (datain[i] >> 3) & 0x01; + + idx = i * 2; + dataout[idx] = datain[i] & 0x0f; + dataout[idx] |= (E0 ^ E1) << 4; + dataout[idx] |= (E2 ^ E3) << 5; + dataout[idx] |= (E0 ^ E2) << 6; + dataout[idx] |= (E1 ^ E3) << 7; + + E0 = (datain[i] >> 4) & 0x01; + E1 = (datain[i] >> 5) & 0x01; + E2 = (datain[i] >> 6) & 0x01; + E3 = (datain[i] >> 7) & 0x01; + + idx = i * 2 + 1; + dataout[idx] = (datain[i] & 0xf0) >> 4; + dataout[idx] |= (E0 ^ E1) << 4; + dataout[idx] |= (E2 ^ E3) << 5; + dataout[idx] |= (E0 ^ E2) << 6; + dataout[idx] |= (E1 ^ E3) << 7; + } +} + +/*----------------------------------------------------------------------------*/ +/* Function: npcm_otp_majority_rule_ecc_encode */ +/* */ +/* Parameters: datain - pointer to decoded data buffer */ +/* dataout - pointer to encoded data buffer (buffer size */ +/* should be 3 x dataout) */ +/* size - size of encoded data (decoded data x 3) */ +/* Returns: none */ +/* Side effects: */ +/* Description: Decodes the data according to Major Rule ECC scheme. */ +/* Size specifies the encoded data size. */ +/* Decodes whole bytes only */ +/*----------------------------------------------------------------------------*/ +void npcm_otp_majority_rule_ecc_encode(u8 *datain, u8 *dataout, u32 size) +{ + u32 byte; + u32 bit; + u8 bit_val; + u32 decoded_size = size / 3; + + for (byte = 0; byte < decoded_size; byte++) { + for (bit = 0; bit < 8; bit++) { + bit_val = (datain[byte] >> bit) & 0x01; + + if (bit_val) { + dataout[byte] |= (1 << bit); + dataout[decoded_size + byte] |= (1 << bit); + dataout[decoded_size * 2 + byte] |= (1 << bit); + } else { + dataout[byte] &= ~(1 << bit); + dataout[decoded_size + byte] &= ~(1 << bit); + dataout[decoded_size * 2 + byte] &= ~(1 << bit); + } + } + } +} + +/*----------------------------------------------------------------------------*/ +/* Function: fuse_program_data */ +/* */ +/* Parameters: bank - Storage Array type [input]. */ +/* word - Byte offset in array [input]. */ +/* data - Pointer to data buffer to program. */ +/* size - Number of bytes to program. */ +/* Returns: none */ +/* Side effects: */ +/* Description: Programs the given byte array (size bytes) to the given */ +/* OTP storage array, starting from offset word. */ +/*----------------------------------------------------------------------------*/ +int fuse_program_data(u32 bank, u32 word, u8 *data, u32 size) +{ + u32 arr = (u32)bank; + u32 byte; + int rc; + + rc = npcm_otp_check_inputs(bank, word + size - 1); + if (rc != 0) + return rc; + + for (byte = 0; byte < size; byte++) { + u8 val; + + val = data[byte]; + if (val == 0) // optimization + continue; + + rc = npcm_otp_program_byte(arr, word + byte, data[byte]); + if (rc != 0) + return rc; + + // verify programming of every '1' bit + val = 0; + npcm_otp_read_byte((u32)bank, byte, &val); + if ((data[byte] & ~val) != 0) + return -1; + } + + return 0; +} + +int fuse_prog_image(u32 bank, uintptr_t address) +{ + return fuse_program_data(bank, 0, (u8 *)address, NPCM_OTP_ARR_BYTE_SIZE); +} + +int fuse_read(u32 bank, u32 word, u32 *val) +{ + int rc = npcm_otp_check_inputs(bank, word); + + if (rc != 0) + return rc; + + *val = 0; + npcm_otp_read_byte((u32)bank, word, (u8 *)val); + + return 0; +} + +int fuse_sense(u32 bank, u32 word, u32 *val) +{ + /* We do not support overriding */ + return -EINVAL; +} + +int fuse_prog(u32 bank, u32 word, u32 val) +{ + int rc; + + rc = npcm_otp_check_inputs(bank, word); + if (rc != 0) + return rc; + + return npcm_otp_program_byte(bank, word, (u8)val); +} + +int fuse_override(u32 bank, u32 word, u32 val) +{ + /* We do not support overriding */ + return -EINVAL; +} + +static int npcm_otp_bind(struct udevice *dev) +{ + struct npcm_otp_regs *regs; + + otp_priv = calloc(1, sizeof(struct npcm_otp_priv)); + if (!otp_priv) + return -ENOMEM; + + regs = dev_remap_addr_index(dev, 0); + if (!regs) { + printf("Cannot find reg address (arr #0), binding failed\n"); + return -EINVAL; + } + otp_priv->regs[0] = regs; + + if (IS_ENABLED(CONFIG_ARCH_NPCM7xx)) { + regs = dev_remap_addr_index(dev, 1); + if (!regs) { + printf("Cannot find reg address (arr #1), binding failed\n"); + return -EINVAL; + } + otp_priv->regs[1] = regs; + } + printf("OTP: NPCM OTP module bind OK\n"); + + return 0; +} + +static const struct udevice_id npcm_otp_ids[] = { + { .compatible = "nuvoton,npcm845-otp" }, + { .compatible = "nuvoton,npcm750-otp" }, + { } +}; + +U_BOOT_DRIVER(npcm_otp) = { + .name = "npcm_otp", + .id = UCLASS_MISC, + .of_match = npcm_otp_ids, + .priv_auto = sizeof(struct npcm_otp_priv), + .bind = npcm_otp_bind, +}; diff --git a/drivers/misc/nvmem.c b/drivers/misc/nvmem.c new file mode 100644 index 00000000000..5a2bd1f9f72 --- /dev/null +++ b/drivers/misc/nvmem.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2022 Sean Anderson <[email protected]> + */ + +#include <common.h> +#include <i2c_eeprom.h> +#include <linker_lists.h> +#include <misc.h> +#include <nvmem.h> +#include <rtc.h> +#include <dm/device_compat.h> +#include <dm/ofnode.h> +#include <dm/read.h> +#include <dm/uclass.h> + +int nvmem_cell_read(struct nvmem_cell *cell, void *buf, size_t size) +{ + dev_dbg(cell->nvmem, "%s: off=%u size=%zu\n", __func__, cell->offset, size); + if (size != cell->size) + return -EINVAL; + + switch (cell->nvmem->driver->id) { + case UCLASS_I2C_EEPROM: + return i2c_eeprom_read(cell->nvmem, cell->offset, buf, size); + case UCLASS_MISC: { + int ret = misc_read(cell->nvmem, cell->offset, buf, size); + + if (ret < 0) + return ret; + if (ret != size) + return -EIO; + return 0; + } + case UCLASS_RTC: + return dm_rtc_read(cell->nvmem, cell->offset, buf, size); + default: + return -ENOSYS; + } +} + +int nvmem_cell_write(struct nvmem_cell *cell, const void *buf, size_t size) +{ + dev_dbg(cell->nvmem, "%s: off=%u size=%zu\n", __func__, cell->offset, size); + if (size != cell->size) + return -EINVAL; + + switch (cell->nvmem->driver->id) { + case UCLASS_I2C_EEPROM: + return i2c_eeprom_write(cell->nvmem, cell->offset, buf, size); + case UCLASS_MISC: { + int ret = misc_write(cell->nvmem, cell->offset, buf, size); + + if (ret < 0) + return ret; + if (ret != size) + return -EIO; + return 0; + } + case UCLASS_RTC: + return dm_rtc_write(cell->nvmem, cell->offset, buf, size); + default: + return -ENOSYS; + } +} + +/** + * nvmem_get_device() - Get an nvmem device for a cell + * @node: ofnode of the nvmem device + * @cell: Cell to look up + * + * Try to find a nvmem-compatible device by going through the nvmem interfaces. + * + * Return: + * * 0 on success + * * -ENODEV if we didn't find anything + * * A negative error if there was a problem looking up the device + */ +static int nvmem_get_device(ofnode node, struct nvmem_cell *cell) +{ + int i, ret; + enum uclass_id ids[] = { + UCLASS_I2C_EEPROM, + UCLASS_MISC, + UCLASS_RTC, + }; + + for (i = 0; i < ARRAY_SIZE(ids); i++) { + ret = uclass_get_device_by_ofnode(ids[i], node, &cell->nvmem); + if (!ret) + return 0; + if (ret != -ENODEV && ret != -EPFNOSUPPORT) + return ret; + } + + return -ENODEV; +} + +int nvmem_cell_get_by_index(struct udevice *dev, int index, + struct nvmem_cell *cell) +{ + fdt_addr_t offset; + fdt_size_t size = FDT_SIZE_T_NONE; + int ret; + struct ofnode_phandle_args args; + + dev_dbg(dev, "%s: index=%d\n", __func__, index); + + ret = dev_read_phandle_with_args(dev, "nvmem-cells", NULL, 0, index, + &args); + if (ret) + return ret; + + ret = nvmem_get_device(ofnode_get_parent(args.node), cell); + if (ret) + return ret; + + offset = ofnode_get_addr_size_index_notrans(args.node, 0, &size); + if (offset == FDT_ADDR_T_NONE || size == FDT_SIZE_T_NONE) { + dev_dbg(cell->nvmem, "missing address or size for %s\n", + ofnode_get_name(args.node)); + return -EINVAL; + } + + cell->offset = offset; + cell->size = size; + return 0; +} + +int nvmem_cell_get_by_name(struct udevice *dev, const char *name, + struct nvmem_cell *cell) +{ + int index; + + dev_dbg(dev, "%s, name=%s\n", __func__, name); + + index = dev_read_stringlist_search(dev, "nvmem-cell-names", name); + if (index < 0) + return index; + + return nvmem_cell_get_by_index(dev, index, cell); +} diff --git a/drivers/misc/qfw_sandbox.c b/drivers/misc/qfw_sandbox.c index b09974d33bd..1002df75339 100644 --- a/drivers/misc/qfw_sandbox.c +++ b/drivers/misc/qfw_sandbox.c @@ -48,7 +48,7 @@ static void qfw_sandbox_read_entry_dma(struct udevice *dev, struct qfw_dma *dma) { u16 entry; u32 control = be32_to_cpu(dma->control); - void *address = (void *)be64_to_cpu(dma->address); + void *address = (void *)(uintptr_t)be64_to_cpu(dma->address); u32 length = be32_to_cpu(dma->length); struct qfw_sandbox_plat *plat = dev_get_plat(dev); struct fw_cfg_file *file; diff --git a/drivers/misc/stm32_rcc.c b/drivers/misc/stm32_rcc.c index f14d6e26d9c..b816503bfa2 100644 --- a/drivers/misc/stm32_rcc.c +++ b/drivers/misc/stm32_rcc.c @@ -39,6 +39,11 @@ struct stm32_rcc_clk stm32_rcc_clk_mp1 = { .soc = STM32MP1, }; +struct stm32_rcc_clk stm32_rcc_clk_mp13 = { + .drv_name = "stm32mp13_clk", + .soc = STM32MP1, +}; + static int stm32_rcc_bind(struct udevice *dev) { struct udevice *child; @@ -79,6 +84,7 @@ static const struct udevice_id stm32_rcc_ids[] = { {.compatible = "st,stm32f746-rcc", .data = (ulong)&stm32_rcc_clk_f7 }, {.compatible = "st,stm32h743-rcc", .data = (ulong)&stm32_rcc_clk_h7 }, {.compatible = "st,stm32mp1-rcc", .data = (ulong)&stm32_rcc_clk_mp1 }, + {.compatible = "st,stm32mp13-rcc", .data = (ulong)&stm32_rcc_clk_mp13 }, { } }; diff --git a/drivers/misc/test_drv.c b/drivers/misc/test_drv.c index 5d72982f258..927618256f0 100644 --- a/drivers/misc/test_drv.c +++ b/drivers/misc/test_drv.c @@ -108,8 +108,10 @@ UCLASS_DRIVER(testbus) = { .child_pre_probe = testbus_child_pre_probe_uclass, .child_post_probe = testbus_child_post_probe_uclass, - /* This is for dtoc testing only */ - .per_device_plat_auto = sizeof(struct dm_test_uclass_priv), + .per_device_auto = sizeof(struct dm_test_uclass_priv), + + /* Note: this is for dtoc testing as well as tags*/ + .per_device_plat_auto = sizeof(struct dm_test_uclass_plat), }; static int testfdt_drv_ping(struct udevice *dev, int pingval, int *pingret) |
