if (ret)
printf("Failed to initialize caam_jr: %d\n", ret);
}
+
+ if (IS_ENABLED(CONFIG_FSL_DCP_RNG)) {
+ struct udevice *dev;
+ int ret;
+
+ ret = uclass_get_device_by_driver(UCLASS_RNG, DM_DRIVER_GET(dcp_rng), &dev);
+ if (ret)
+ printf("Failed to initialize dcp rng: %d\n", ret);
+ }
+
setup_serial_number();
return 0;
}
if (!*loadaddr)
return 0;
- if (!uclass_get_device(UCLASS_FS_FIRMWARE_LOADER, 0, &fsdev)) {
+ if (!get_fs_loader(&fsdev)) {
size = request_firmware_into_buf(fsdev, name, (void *)*loadaddr,
0, 0);
}
if (!*loadaddr)
return 0;
- if (!uclass_get_device(UCLASS_FS_FIRMWARE_LOADER, 0, &fsdev)) {
+ if (!get_fs_loader(&fsdev)) {
size = request_firmware_into_buf(fsdev, name_fw,
(void *)*loadaddr, 0, 0);
}
if ((flag & CMD_FLAG_REPEAT) == 0)
{
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
if (argc >= 2) {
mode = CONFIG_DEFAULT_SPI_MODE;
bus = dectoul(argv[1], &cp);
(e.g. NAND). This option makes the value of the 'silent'
environment variable take effect at relocation.
+config SILENT_CONSOLE_UNTIL_ENV
+ bool "Keep console silent until environment is loaded"
+ depends on SILENT_CONSOLE
+ help
+ This option makes sure U-Boot will never use the console unless the
+ environment from flash does not contain the 'silent' variable. If
+ set, the console is kept silent until after the environment was
+ loaded. Use this in combination with PRE_CONSOLE_BUFFER to print out
+ earlier messages after loading the environment when allowed.
+
config PRE_CONSOLE_BUFFER
bool "Buffer characters before the console is available"
help
initr_status_led,
#endif
/* PPC has a udelay(20) here dating from 2002. Why? */
-#if defined(CONFIG_GPIO_HOG)
- gpio_hog_probe_all,
-#endif
#ifdef CONFIG_BOARD_LATE_INIT
board_late_init,
#endif
if (!IS_ENABLED(CONFIG_SILENT_CONSOLE))
return false;
+ if (IS_ENABLED(CONFIG_SILENT_CONSOLE_UNTIL_ENV) && !(gd->flags & GD_FLG_ENV_READY)) {
+ gd->flags |= GD_FLG_SILENT;
+ return false;
+ }
+
if (env_get("silent")) {
gd->flags |= GD_FLG_SILENT;
return false;
}
}
- if (CONFIG_IS_ENABLED(GPIO_HOG))
- gpio_hog_probe_all();
-
#if CONFIG_IS_ENABLED(BOARD_INIT)
spl_board_init();
#endif
struct spl_boot_device *bootdev)
{
struct legacy_img_hdr *header;
+ int ret;
header = (struct legacy_img_hdr *)CONFIG_SPL_LOAD_FIT_ADDRESS;
if (CONFIG_IS_ENABLED(IMAGE_PRE_LOAD)) {
unsigned long addr = (unsigned long)header;
- int ret = image_pre_load(addr);
+ ret = image_pre_load(addr);
if (ret)
return ret;
debug("Found FIT\n");
load.bl_len = 1;
load.read = spl_ram_load_read;
- spl_load_simple_fit(spl_image, &load, 0, header);
+ ret = spl_load_simple_fit(spl_image, &load, 0, header);
} else {
ulong u_boot_pos = spl_get_image_pos();
}
header = (struct legacy_img_hdr *)map_sysmem(u_boot_pos, 0);
- spl_parse_image_header(spl_image, bootdev, header);
+ ret = spl_parse_image_header(spl_image, bootdev, header);
}
- return 0;
+ return ret;
}
#if CONFIG_IS_ENABLED(RAM_DEVICE)
SPL_LOAD_IMAGE_METHOD("RAM", 0, BOOT_DEVICE_RAM, spl_ram_load_image);
CONFIG_FSL_QSPI=y
CONFIG_SOFT_SPI=y
CONFIG_IMX_THERMAL=y
+CONFIG_ARCH_MISC_INIT=y
+CONFIG_DM_RNG=y
+CONFIG_CMD_RNG=y
+CONFIG_FSL_DCP_RNG=y
CONFIG_FSL_QSPI=y
CONFIG_SOFT_SPI=y
CONFIG_IMX_THERMAL=y
+CONFIG_ARCH_MISC_INIT=y
+CONFIG_DM_RNG=y
+CONFIG_CMD_RNG=y
+CONFIG_FSL_DCP_RNG=y
GPIO hog (CONFIG_GPIO_HOG)
--------
-All the GPIO hog are initialized in gpio_hog_probe_all() function called in
-board_r.c just before board_late_init() but you can also acces directly to
-the gpio with gpio_hog_lookup_name().
-
+All the GPIO hog are initialized using DM_FLAG_PROBE_AFTER_BIND DM flag
+after bind().
Example, for the device tree:
static int dm_probe_devices(struct udevice *dev, bool pre_reloc_only)
{
- u32 mask = DM_FLAG_PROBE_AFTER_BIND;
- u32 flags = dev_get_flags(dev);
+ ofnode node = dev_ofnode(dev);
struct udevice *child;
int ret;
- if (pre_reloc_only)
- mask |= DM_FLAG_PRE_RELOC;
+ if (pre_reloc_only &&
+ (!ofnode_valid(node) || !ofnode_pre_reloc(node)) &&
+ !(dev->driver->flags & DM_FLAG_PRE_RELOC))
+ goto probe_children;
- if ((flags & mask) == mask) {
+ if (dev_get_flags(dev) & DM_FLAG_PROBE_AFTER_BIND) {
ret = device_probe(dev);
if (ret)
return ret;
}
+probe_children:
list_for_each_entry(child, &dev->child_head, sibling_node)
dm_probe_devices(child, pre_reloc_only);
reseeded from the TRNG every time random data is generated.
endif
+
+config FSL_DCP_RNG
+ bool "Enable Random Number Generator support"
+ depends on DM_RNG
+ default n
+ help
+ Enable support for the hardware based random number generator
+ module of the DCP. It uses the True Random Number Generator (TRNG)
+ and a Pseudo-Random Number Generator (PRNG) to achieve a true
+ randomness and cryptographic strength.
obj-$(CONFIG_CMD_BLOB)$(CONFIG_IMX_CAAM_DEK_ENCAP) += fsl_blob.o
obj-$(CONFIG_RSA_FREESCALE_EXP) += fsl_rsa.o
obj-$(CONFIG_FSL_CAAM_RNG) += rng.o
+obj-$(CONFIG_FSL_DCP_RNG) += dcp_rng.o
obj-$(CONFIG_FSL_MFGPROT) += fsl_mfgprot.o
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * RNG driver for Freescale RNGC
+ *
+ * Copyright 2022 NXP
+ *
+ * Based on RNGC driver in drivers/char/hw_random/imx-rngc.c in Linux
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <dm.h>
+#include <rng.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <dm/root.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+
+#define DCP_RNG_MAX_FIFO_STORE_SIZE 4
+#define RNGC_VER_ID 0x0
+#define RNGC_COMMAND 0x4
+#define RNGC_CONTROL 0x8
+#define RNGC_STATUS 0xC
+#define RNGC_ERROR 0x10
+#define RNGC_FIFO 0x14
+
+/* the fields in the ver id register */
+#define RNGC_TYPE_SHIFT 28
+
+/* the rng_type field */
+#define RNGC_TYPE_RNGB 0x1
+#define RNGC_TYPE_RNGC 0x2
+
+#define RNGC_CMD_CLR_ERR 0x20
+#define RNGC_CMD_SEED 0x2
+
+#define RNGC_CTRL_AUTO_SEED 0x10
+
+#define RNGC_STATUS_ERROR 0x10000
+#define RNGC_STATUS_FIFO_LEVEL_MASK 0xf00
+#define RNGC_STATUS_FIFO_LEVEL_SHIFT 8
+#define RNGC_STATUS_SEED_DONE 0x20
+#define RNGC_STATUS_ST_DONE 0x10
+
+#define RNGC_ERROR_STATUS_STAT_ERR 0x8
+
+#define RNGC_TIMEOUT 3000000U /* 3 sec */
+
+struct imx_rngc_priv {
+ unsigned long base;
+};
+
+static int rngc_read(struct udevice *dev, void *data, size_t len)
+{
+ struct imx_rngc_priv *priv = dev_get_priv(dev);
+ u8 buffer[DCP_RNG_MAX_FIFO_STORE_SIZE];
+ u32 status, level;
+ size_t size;
+
+ while (len) {
+ status = readl(priv->base + RNGC_STATUS);
+
+ /* is there some error while reading this random number? */
+ if (status & RNGC_STATUS_ERROR)
+ break;
+ /* how many random numbers are in FIFO? [0-16] */
+ level = (status & RNGC_STATUS_FIFO_LEVEL_MASK) >>
+ RNGC_STATUS_FIFO_LEVEL_SHIFT;
+
+ if (level) {
+ /* retrieve a random number from FIFO */
+ *(u32 *)buffer = readl(priv->base + RNGC_FIFO);
+ size = min(len, sizeof(u32));
+ memcpy(data, buffer, size);
+ data += size;
+ len -= size;
+ }
+ }
+
+ return len ? -EIO : 0;
+}
+
+static int rngc_init(struct imx_rngc_priv *priv)
+{
+ u32 cmd, ctrl, status, err_reg = 0;
+ unsigned long long timeval = 0;
+ unsigned long long timeout = RNGC_TIMEOUT;
+
+ /* clear error */
+ cmd = readl(priv->base + RNGC_COMMAND);
+ writel(cmd | RNGC_CMD_CLR_ERR, priv->base + RNGC_COMMAND);
+
+ /* create seed, repeat while there is some statistical error */
+ do {
+ /* seed creation */
+ cmd = readl(priv->base + RNGC_COMMAND);
+ writel(cmd | RNGC_CMD_SEED, priv->base + RNGC_COMMAND);
+
+ udelay(1);
+ timeval += 1;
+
+ status = readl(priv->base + RNGC_STATUS);
+ err_reg = readl(priv->base + RNGC_ERROR);
+
+ if (status & (RNGC_STATUS_SEED_DONE | RNGC_STATUS_ST_DONE))
+ break;
+
+ if (timeval > timeout) {
+ debug("rngc timed out\n");
+ return -ETIMEDOUT;
+ }
+ } while (err_reg == RNGC_ERROR_STATUS_STAT_ERR);
+
+ if (err_reg)
+ return -EIO;
+
+ /*
+ * enable automatic seeding, the rngc creates a new seed automatically
+ * after serving 2^20 random 160-bit words
+ */
+ ctrl = readl(priv->base + RNGC_CONTROL);
+ ctrl |= RNGC_CTRL_AUTO_SEED;
+ writel(ctrl, priv->base + RNGC_CONTROL);
+ return 0;
+}
+
+static int rngc_probe(struct udevice *dev)
+{
+ struct imx_rngc_priv *priv = dev_get_priv(dev);
+ fdt_addr_t addr;
+ u32 ver_id;
+ u8 rng_type;
+ int ret;
+
+ addr = dev_read_addr(dev);
+ if (addr == FDT_ADDR_T_NONE) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ priv->base = addr;
+ ver_id = readl(priv->base + RNGC_VER_ID);
+ rng_type = ver_id >> RNGC_TYPE_SHIFT;
+ /*
+ * This driver supports only RNGC and RNGB. (There's a different
+ * driver for RNGA.)
+ */
+ if (rng_type != RNGC_TYPE_RNGC && rng_type != RNGC_TYPE_RNGB) {
+ ret = -ENODEV;
+ goto err;
+ }
+
+ ret = rngc_init(priv);
+ if (ret)
+ goto err;
+
+ return 0;
+
+err:
+ printf("%s error = %d\n", __func__, ret);
+ return ret;
+}
+
+static const struct dm_rng_ops rngc_ops = {
+ .read = rngc_read,
+};
+
+static const struct udevice_id rngc_dt_ids[] = {
+ { .compatible = "fsl,imx25-rngb" },
+ { }
+};
+
+U_BOOT_DRIVER(dcp_rng) = {
+ .name = "dcp_rng",
+ .id = UCLASS_RNG,
+ .of_match = rngc_dt_ids,
+ .ops = &rngc_ops,
+ .probe = rngc_probe,
+ .priv_auto = sizeof(struct imx_rngc_priv),
+ .flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
{
struct fpga_loadfs_info fpga_loadfs;
struct udevice *dev;
- int status, ret, size;
+ int status, ret;
u32 buffer = (uintptr_t)buf;
size_t buffer_sizebytes = bsize;
size_t buffer_sizebytes_ori = bsize;
size_t total_sizeof_image = 0;
ofnode node;
- const fdt32_t *phandle_p;
- u32 phandle;
node = get_fpga_mgr_ofnode(ofnode_null());
-
- if (ofnode_valid(node)) {
- phandle_p = ofnode_get_property(node, "firmware-loader", &size);
- if (!phandle_p) {
- node = ofnode_path("/chosen");
- if (!ofnode_valid(node)) {
- debug("FPGA: /chosen node was not found.\n");
- return -ENOENT;
- }
-
- phandle_p = ofnode_get_property(node, "firmware-loader",
- &size);
- if (!phandle_p) {
- debug("FPGA: firmware-loader property was not");
- debug(" found.\n");
- return -ENOENT;
- }
- }
- } else {
+ if (!ofnode_valid(node)) {
debug("FPGA: FPGA manager node was not found.\n");
return -ENOENT;
}
- phandle = fdt32_to_cpu(*phandle_p);
- ret = uclass_get_device_by_phandle_id(UCLASS_FS_FIRMWARE_LOADER,
- phandle, &dev);
+ ret = get_fs_loader(&dev);
if (ret)
return ret;
return 0;
}
-int gpio_hog_probe_all(void)
-{
- struct udevice *dev;
- int ret;
- int retval = 0;
-
- for (uclass_first_device(UCLASS_NOP, &dev);
- dev;
- uclass_find_next_device(&dev)) {
- if (dev->driver == DM_DRIVER_GET(gpio_hog)) {
- ret = device_probe(dev);
- if (ret) {
- printf("Failed to probe device %s err: %d\n",
- dev->name, ret);
- retval = ret;
- }
- }
- }
-
- return retval;
-}
-
int gpio_hog_lookup_name(const char *name, struct gpio_desc **desc)
{
struct udevice *dev;
*desc = NULL;
- gpio_hog_probe_all();
if (!uclass_get_device_by_name(UCLASS_NOP, name, &dev)) {
struct gpio_hog_priv *priv = dev_get_priv(dev);
&child);
if (ret)
return ret;
+
+ /*
+ * Make sure gpio-hogs are probed after bind
+ * since hogs can be essential to the hardware
+ * system.
+ */
+ dev_or_flags(child, DM_FLAG_PROBE_AFTER_BIND);
}
}
}
+
return 0;
}
#include <fs_loader.h>
#include <log.h>
#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <dm/root.h>
#include <linux/string.h>
#include <mapmem.h>
#include <malloc.h>
.priv_auto = sizeof(struct firmware),
};
+static struct device_plat default_plat = { 0 };
+
+int get_fs_loader(struct udevice **dev)
+{
+ int ret;
+ ofnode node = ofnode_get_chosen_node("firmware-loader");
+
+ if (ofnode_valid(node))
+ return uclass_get_device_by_ofnode(UCLASS_FS_FIRMWARE_LOADER,
+ node, dev);
+
+ /* Try the first device if none was chosen */
+ ret = uclass_first_device_err(UCLASS_FS_FIRMWARE_LOADER, dev);
+ if (ret != -ENODEV)
+ return ret;
+
+ /* Just create a new device */
+ ret = device_bind(dm_root(), DM_DRIVER_GET(fs_loader), "default-loader",
+ &default_plat, ofnode_null(), dev);
+ if (ret)
+ return ret;
+
+ return device_probe(*dev);
+}
+
UCLASS_DRIVER(fs_loader) = {
.id = UCLASS_FS_FIRMWARE_LOADER,
.name = "fs-loader",
*/
#include <common.h>
#include <env.h>
+#include <fs_loader.h>
#include <image.h>
#include <malloc.h>
#include <asm/io.h>
+#include <dm/device_compat.h>
#include <linux/errno.h>
#include <u-boot/crc.h>
#include <dm.h>
/* Init common part of FM, index is fm num# like fm as above */
#ifdef CONFIG_TFABOOT
-int fm_init_common(int index, struct ccsr_fman *reg)
+int fm_init_common(int index, struct ccsr_fman *reg, const char *firmware_name)
{
int rc;
void *addr = NULL;
return fm_init_bmi(index, ®->fm_bmi_common);
}
#else
-int fm_init_common(int index, struct ccsr_fman *reg)
+int fm_init_common(int index, struct ccsr_fman *reg, const char *firmware_name)
{
int rc;
-#if defined(CONFIG_SYS_QE_FMAN_FW_IN_NOR)
+#if defined(CONFIG_SYS_QE_FMAN_FW_IN_FS)
+ struct udevice *fs_loader;
+ void *addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH);
+
+ if (!addr)
+ return -ENOMEM;
+
+ rc = get_fs_loader(&fs_loader);
+ if (rc) {
+ debug("could not get fs loader: %d\n", rc);
+ return rc;
+ }
+
+ if (!firmware_name)
+ firmware_name = "fman.itb";
+
+ rc = request_firmware_into_buf(fs_loader, firmware_name, addr,
+ CONFIG_SYS_QE_FMAN_FW_LENGTH, 0);
+ if (rc < 0) {
+ debug("could not request %s: %d\n", firmware_name, rc);
+ return rc;
+ }
+#elif defined(CONFIG_SYS_QE_FMAN_FW_IN_NOR)
void *addr = (void *)CONFIG_SYS_FMAN_FW_ADDR;
#elif defined(CONFIG_SYS_QE_FMAN_FW_IN_NAND)
size_t fw_length = CONFIG_SYS_QE_FMAN_FW_LENGTH;
static int fman_probe(struct udevice *dev)
{
+ const char *firmware_name = NULL;
+ int ret;
struct fman_priv *priv = dev_get_priv(dev);
priv->reg = (struct ccsr_fman *)(uintptr_t)dev_read_addr(dev);
return -EINVAL;
}
- return fm_init_common(priv->fman_id, priv->reg);
+ ret = dev_read_string_index(dev, "firmware-name", 0, &firmware_name);
+ if (ret && ret != -EINVAL) {
+ dev_dbg(dev, "Could not read firmware-name\n");
+ return ret;
+ }
+
+ return fm_init_common(priv->fman_id, priv->reg, firmware_name);
}
static int fman_remove(struct udevice *dev)
void *fm_muram_alloc(int fm_idx, size_t size, ulong align);
void *fm_muram_base(int fm_idx);
-int fm_init_common(int index, struct ccsr_fman *reg);
+int fm_init_common(int index, struct ccsr_fman *reg, const char *firmware_name);
int fm_eth_initialize(struct ccsr_fman *reg, struct fm_eth_info *info);
phy_interface_t fman_port_enet_if(enum fm_port port);
void fman_disable_port(enum fm_port port);
depends on FMAN_ENET || QE
default SYS_QE_FMAN_FW_IN_ROM
+config SYS_QE_FMAN_FW_IN_FS
+ depends on FS_LOADER && FMAN_ENET
+ bool "Filesystem"
+
config SYS_QE_FMAN_FW_IN_NOR
bool "NOR flash"
int gpio_hog_lookup_name(const char *name, struct gpio_desc **desc);
/**
- * gpio_hog_probe_all() - probe all gpio devices with
- * gpio-hog subnodes.
- *
- * @return: Returns return value from device_probe()
- */
-int gpio_hog_probe_all(void);
-
-/**
* gpio_lookup_name - Look up a GPIO name and return its details
*
* This is used to convert a named GPIO into a device, offset and GPIO
"if fstype ${devtype} " \
"${devnum}:${distro_bootpart} " \
"bootfstype; then " \
+ "part uuid ${devtype} " \
+ "${devnum}:${distro_bootpart} " \
+ "distro_bootpart_uuid ; " \
"run scan_dev_for_boot; " \
"fi; " \
"done; " \
int request_firmware_into_buf(struct udevice *dev,
const char *name,
void *buf, size_t size, u32 offset);
+
+/**
+ * get_fs_loader() - Get the chosen filesystem loader
+ * @dev: Where to store the device
+ *
+ * This gets a filesystem loader device based on the value of
+ * /chosen/firmware-loader. If no such property exists, it returns a
+ * firmware loader which is configured by environmental variables.
+ *
+ * Return: 0 on success, negative value on error
+ */
+int get_fs_loader(struct udevice **dev);
#endif
}
#else
-extern unsigned long __weak timer_read_counter(void);
+extern unsigned long timer_read_counter(void);
#endif
#if CONFIG_IS_ENABLED(TIMER)