summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/Kconfig12
-rw-r--r--drivers/block/Makefile2
-rw-r--r--drivers/bootcount/Kconfig6
-rw-r--r--drivers/bootcount/bootcount.c8
-rw-r--r--drivers/bootcount/bootcount_at91.c11
-rw-r--r--drivers/bootcount/bootcount_davinci.c4
-rw-r--r--drivers/bootcount/bootcount_ram.c2
-rw-r--r--drivers/core/device.c45
-rw-r--r--drivers/core/of_extra.c27
-rw-r--r--drivers/core/ofnode.c10
-rw-r--r--drivers/gpio/da8xx_gpio.c8
-rw-r--r--drivers/gpio/da8xx_gpio.h41
-rw-r--r--drivers/i2c/Kconfig7
-rw-r--r--drivers/i2c/Makefile1
-rw-r--r--drivers/input/Kconfig48
-rw-r--r--drivers/input/Makefile11
-rw-r--r--drivers/input/input.c5
-rw-r--r--drivers/misc/cros_ec.c178
-rw-r--r--drivers/misc/cros_ec_lpc.c33
-rw-r--r--drivers/misc/cros_ec_sandbox.c8
-rw-r--r--drivers/mmc/Kconfig2
-rw-r--r--drivers/mmc/tmio-common.c12
-rw-r--r--drivers/mtd/Kconfig38
-rw-r--r--drivers/mtd/mtd_uboot.c9
-rw-r--r--drivers/mtd/nand/raw/atmel_nand.c2
-rw-r--r--drivers/mtd/spi/sandbox.c194
-rw-r--r--drivers/mtd/spi/sf-uclass.c6
-rw-r--r--drivers/mtd/spi/sf_internal.h1
-rw-r--r--drivers/mtd/spi/sf_probe.c2
-rw-r--r--drivers/mtd/spi/spi_flash.c19
-rw-r--r--drivers/net/Kconfig2
-rw-r--r--drivers/net/dc2114x.c1
-rw-r--r--drivers/net/eepro100.c2
-rw-r--r--drivers/net/fsl-mc/mc.c6
-rw-r--r--drivers/net/ldpaa_eth/ldpaa_eth.c171
-rw-r--r--drivers/net/ldpaa_eth/ldpaa_eth.h1
-rw-r--r--drivers/net/ldpaa_eth/ldpaa_wriop.c69
-rw-r--r--drivers/net/mvneta.c8
-rw-r--r--drivers/net/mvpp2.c13
-rw-r--r--drivers/net/natsemi.c1
-rw-r--r--drivers/net/ns8382x.c1
-rw-r--r--drivers/net/pch_gbe.c4
-rw-r--r--drivers/net/phy/ti.c93
-rw-r--r--drivers/net/rtl8139.c4
-rw-r--r--drivers/net/rtl8169.c4
-rw-r--r--drivers/net/sandbox.c417
-rw-r--r--drivers/net/zynq_gem.c4
-rw-r--r--drivers/pci/pci-uclass.c32
-rw-r--r--drivers/pci/pci_rom.c4
-rw-r--r--drivers/pwm/sandbox_pwm.c25
-rw-r--r--drivers/rtc/Kconfig26
-rw-r--r--drivers/rtc/Makefile2
-rw-r--r--drivers/rtc/isl1208.c20
-rw-r--r--drivers/serial/Kconfig21
-rw-r--r--drivers/serial/sandbox.c24
-rw-r--r--drivers/serial/serial-uclass.c4
-rw-r--r--drivers/spi/Kconfig4
-rw-r--r--drivers/spi/davinci_spi.c47
-rw-r--r--drivers/spi/sandbox_spi.c38
-rw-r--r--drivers/spi/spi-uclass.c6
-rw-r--r--drivers/sysreset/sysreset-uclass.c34
-rw-r--r--drivers/sysreset/sysreset_sandbox.c15
-rw-r--r--drivers/timer/Kconfig13
-rw-r--r--drivers/timer/tsc_timer.c6
-rw-r--r--drivers/tpm/Makefile2
-rw-r--r--drivers/tpm/tpm-uclass.c9
-rw-r--r--drivers/tpm/tpm_tis_lpc.c2
-rw-r--r--drivers/tpm/tpm_tis_sandbox.c115
-rw-r--r--drivers/usb/eth/lan7x.h2
-rw-r--r--drivers/usb/gadget/ether.c9
-rw-r--r--drivers/usb/gadget/rndis.c6
-rw-r--r--drivers/video/backlight-uclass.c10
-rw-r--r--drivers/video/panel-uclass.c18
-rw-r--r--drivers/video/pwm_backlight.c187
-rw-r--r--drivers/video/simple_panel.c20
-rw-r--r--drivers/video/tegra124/sor.c3
-rw-r--r--drivers/video/vidconsole-uclass.c14
-rw-r--r--drivers/video/video-uclass.c10
-rw-r--r--drivers/video/video_bmp.c2
-rw-r--r--drivers/watchdog/ast_wdt.c1
80 files changed, 1597 insertions, 687 deletions
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index f9502b36ba..33f4aa2418 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -27,6 +27,18 @@ config SPL_BLK
be partitioned into several areas, called 'partitions' in U-Boot.
A filesystem can be placed in each partition.
+config TPL_BLK
+ bool "Support block devices in TPL"
+ depends on TPL_DM && BLK
+ default y
+ help
+ Enable support for block devices, such as SCSI, MMC and USB
+ flash sticks. These provide a block-level interface which permits
+ reading, writing and (in some cases) erasing blocks. Block
+ devices often have a partition table which allows the device to
+ be partitioned into several areas, called 'partitions' in U-Boot.
+ A filesystem can be placed in each partition.
+
config BLOCK_CACHE
bool "Use block device cache"
depends on BLK
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 0e80ce9405..055d42f7d4 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -11,4 +11,4 @@ endif
obj-$(CONFIG_IDE) += ide.o
obj-$(CONFIG_SANDBOX) += sandbox.o
-obj-$(CONFIG_$(SPL_)BLOCK_CACHE) += blkcache.o
+obj-$(CONFIG_$(SPL_TPL_)BLOCK_CACHE) += blkcache.o
diff --git a/drivers/bootcount/Kconfig b/drivers/bootcount/Kconfig
index 9a0bd516d9..67033637c0 100644
--- a/drivers/bootcount/Kconfig
+++ b/drivers/bootcount/Kconfig
@@ -127,4 +127,10 @@ config SYS_BOOTCOUNT_ADDR
help
Set the address used for reading and writing the boot counter.
+config SYS_BOOTCOUNT_MAGIC
+ hex "Magic value for the boot counter"
+ default 0xB001C041
+ help
+ Set the magic value used for the boot counter.
+
endif
diff --git a/drivers/bootcount/bootcount.c b/drivers/bootcount/bootcount.c
index 646c563f8a..66c1284c5b 100644
--- a/drivers/bootcount/bootcount.c
+++ b/drivers/bootcount/bootcount.c
@@ -16,13 +16,13 @@ __weak void bootcount_store(ulong a)
uintptr_t flush_end;
#if defined(CONFIG_SYS_BOOTCOUNT_SINGLEWORD)
- raw_bootcount_store(reg, (BOOTCOUNT_MAGIC & 0xffff0000) | a);
+ raw_bootcount_store(reg, (CONFIG_SYS_BOOTCOUNT_MAGIC & 0xffff0000) | a);
flush_end = roundup(CONFIG_SYS_BOOTCOUNT_ADDR + 4,
CONFIG_SYS_CACHELINE_SIZE);
#else
raw_bootcount_store(reg, a);
- raw_bootcount_store(reg + 4, BOOTCOUNT_MAGIC);
+ raw_bootcount_store(reg + 4, CONFIG_SYS_BOOTCOUNT_MAGIC);
flush_end = roundup(CONFIG_SYS_BOOTCOUNT_ADDR + 8,
CONFIG_SYS_CACHELINE_SIZE);
@@ -37,12 +37,12 @@ __weak ulong bootcount_load(void)
#if defined(CONFIG_SYS_BOOTCOUNT_SINGLEWORD)
u32 tmp = raw_bootcount_load(reg);
- if ((tmp & 0xffff0000) != (BOOTCOUNT_MAGIC & 0xffff0000))
+ if ((tmp & 0xffff0000) != (CONFIG_SYS_BOOTCOUNT_MAGIC & 0xffff0000))
return 0;
else
return (tmp & 0x0000ffff);
#else
- if (raw_bootcount_load(reg + 4) != BOOTCOUNT_MAGIC)
+ if (raw_bootcount_load(reg + 4) != CONFIG_SYS_BOOTCOUNT_MAGIC)
return 0;
else
return raw_bootcount_load(reg);
diff --git a/drivers/bootcount/bootcount_at91.c b/drivers/bootcount/bootcount_at91.c
index 3092ba56c0..c4ab5ceafa 100644
--- a/drivers/bootcount/bootcount_at91.c
+++ b/drivers/bootcount/bootcount_at91.c
@@ -6,15 +6,16 @@
#include <asm/arch/at91_gpbr.h>
/*
- * We combine the BOOTCOUNT_MAGIC and bootcount in one 32-bit register.
- * This is done so we need to use only one of the four GPBR registers.
+ * We combine the CONFIG_SYS_BOOTCOUNT_MAGIC and bootcount in one 32-bit
+ * register. This is done so we need to use only one of the four GPBR
+ * registers.
*/
void bootcount_store(ulong a)
{
at91_gpbr_t *gpbr = (at91_gpbr_t *) ATMEL_BASE_GPBR;
- writel((BOOTCOUNT_MAGIC & 0xffff0000) | (a & 0x0000ffff),
- &gpbr->reg[AT91_GPBR_INDEX_BOOTCOUNT]);
+ writel((CONFIG_SYS_BOOTCOUNT_MAGIC & 0xffff0000) | (a & 0x0000ffff),
+ &gpbr->reg[AT91_GPBR_INDEX_BOOTCOUNT]);
}
ulong bootcount_load(void)
@@ -22,7 +23,7 @@ ulong bootcount_load(void)
at91_gpbr_t *gpbr = (at91_gpbr_t *) ATMEL_BASE_GPBR;
ulong val = readl(&gpbr->reg[AT91_GPBR_INDEX_BOOTCOUNT]);
- if ((val & 0xffff0000) != (BOOTCOUNT_MAGIC & 0xffff0000))
+ if ((val & 0xffff0000) != (CONFIG_SYS_BOOTCOUNT_MAGIC & 0xffff0000))
return 0;
else
return val & 0x0000ffff;
diff --git a/drivers/bootcount/bootcount_davinci.c b/drivers/bootcount/bootcount_davinci.c
index 7101ad9413..6326957d7b 100644
--- a/drivers/bootcount/bootcount_davinci.c
+++ b/drivers/bootcount/bootcount_davinci.c
@@ -24,7 +24,7 @@ void bootcount_store(ulong a)
writel(RTC_KICK0R_WE, &reg->kick0r);
writel(RTC_KICK1R_WE, &reg->kick1r);
raw_bootcount_store(&reg->scratch2,
- (BOOTCOUNT_MAGIC & 0xffff0000) | (a & 0x0000ffff));
+ (CONFIG_SYS_BOOTCOUNT_MAGIC & 0xffff0000) | (a & 0x0000ffff));
}
ulong bootcount_load(void)
@@ -34,7 +34,7 @@ ulong bootcount_load(void)
(struct davinci_rtc *)CONFIG_SYS_BOOTCOUNT_ADDR;
val = raw_bootcount_load(&reg->scratch2);
- if ((val & 0xffff0000) != (BOOTCOUNT_MAGIC & 0xffff0000))
+ if ((val & 0xffff0000) != (CONFIG_SYS_BOOTCOUNT_MAGIC & 0xffff0000))
return 0;
else
return val & 0x0000ffff;
diff --git a/drivers/bootcount/bootcount_ram.c b/drivers/bootcount/bootcount_ram.c
index e514a57286..edef36724b 100644
--- a/drivers/bootcount/bootcount_ram.c
+++ b/drivers/bootcount/bootcount_ram.c
@@ -28,7 +28,7 @@ void bootcount_store(ulong a)
size += gd->bd->bi_dram[i].size;
save_addr = (ulong *)(size - BOOTCOUNT_ADDR);
writel(a, save_addr);
- writel(BOOTCOUNT_MAGIC, &save_addr[1]);
+ writel(CONFIG_SYS_BOOTCOUNT_MAGIC, &save_addr[1]);
for (i = 0; i < REPEAT_PATTERN; i++)
writel(patterns[i % NBR_OF_PATTERNS],
diff --git a/drivers/core/device.c b/drivers/core/device.c
index feed43c8c3..5176aa3f86 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -331,7 +331,8 @@ int device_probe(struct udevice *dev)
/* Allocate private data if requested and not reentered */
size = dev->uclass->uc_drv->per_device_auto_alloc_size;
if (size && !dev->uclass_priv) {
- dev->uclass_priv = calloc(1, size);
+ dev->uclass_priv = alloc_priv(size,
+ dev->uclass->uc_drv->flags);
if (!dev->uclass_priv) {
ret = -ENOMEM;
goto fail;
@@ -441,7 +442,7 @@ fail:
return ret;
}
-void *dev_get_platdata(struct udevice *dev)
+void *dev_get_platdata(const struct udevice *dev)
{
if (!dev) {
dm_warn("%s: null device\n", __func__);
@@ -451,7 +452,7 @@ void *dev_get_platdata(struct udevice *dev)
return dev->platdata;
}
-void *dev_get_parent_platdata(struct udevice *dev)
+void *dev_get_parent_platdata(const struct udevice *dev)
{
if (!dev) {
dm_warn("%s: null device\n", __func__);
@@ -461,7 +462,7 @@ void *dev_get_parent_platdata(struct udevice *dev)
return dev->parent_platdata;
}
-void *dev_get_uclass_platdata(struct udevice *dev)
+void *dev_get_uclass_platdata(const struct udevice *dev)
{
if (!dev) {
dm_warn("%s: null device\n", __func__);
@@ -471,7 +472,7 @@ void *dev_get_uclass_platdata(struct udevice *dev)
return dev->uclass_platdata;
}
-void *dev_get_priv(struct udevice *dev)
+void *dev_get_priv(const struct udevice *dev)
{
if (!dev) {
dm_warn("%s: null device\n", __func__);
@@ -481,7 +482,7 @@ void *dev_get_priv(struct udevice *dev)
return dev->priv;
}
-void *dev_get_uclass_priv(struct udevice *dev)
+void *dev_get_uclass_priv(const struct udevice *dev)
{
if (!dev) {
dm_warn("%s: null device\n", __func__);
@@ -491,7 +492,7 @@ void *dev_get_uclass_priv(struct udevice *dev)
return dev->uclass_priv;
}
-void *dev_get_parent_priv(struct udevice *dev)
+void *dev_get_parent_priv(const struct udevice *dev)
{
if (!dev) {
dm_warn("%s: null device\n", __func__);
@@ -680,17 +681,35 @@ int device_find_next_child(struct udevice **devp)
return 0;
}
-struct udevice *dev_get_parent(struct udevice *child)
+int device_find_first_inactive_child(struct udevice *parent,
+ enum uclass_id uclass_id,
+ struct udevice **devp)
+{
+ struct udevice *dev;
+
+ *devp = NULL;
+ list_for_each_entry(dev, &parent->child_head, sibling_node) {
+ if (!device_active(dev) &&
+ device_get_uclass_id(dev) == uclass_id) {
+ *devp = dev;
+ return 0;
+ }
+ }
+
+ return -ENODEV;
+}
+
+struct udevice *dev_get_parent(const struct udevice *child)
{
return child->parent;
}
-ulong dev_get_driver_data(struct udevice *dev)
+ulong dev_get_driver_data(const struct udevice *dev)
{
return dev->driver_data;
}
-const void *dev_get_driver_ops(struct udevice *dev)
+const void *dev_get_driver_ops(const struct udevice *dev)
{
if (!dev || !dev->driver->ops)
return NULL;
@@ -698,12 +717,12 @@ const void *dev_get_driver_ops(struct udevice *dev)
return dev->driver->ops;
}
-enum uclass_id device_get_uclass_id(struct udevice *dev)
+enum uclass_id device_get_uclass_id(const struct udevice *dev)
{
return dev->uclass->uc_drv->id;
}
-const char *dev_get_uclass_name(struct udevice *dev)
+const char *dev_get_uclass_name(const struct udevice *dev)
{
if (!dev)
return NULL;
@@ -711,7 +730,7 @@ const char *dev_get_uclass_name(struct udevice *dev)
return dev->uclass->uc_drv->name;
}
-bool device_has_children(struct udevice *dev)
+bool device_has_children(const struct udevice *dev)
{
return !list_empty(&dev->child_head);
}
diff --git a/drivers/core/of_extra.c b/drivers/core/of_extra.c
index aa48917ddd..f1f393c359 100644
--- a/drivers/core/of_extra.c
+++ b/drivers/core/of_extra.c
@@ -13,19 +13,30 @@
int ofnode_read_fmap_entry(ofnode node, struct fmap_entry *entry)
{
const char *prop;
- u32 reg[2];
- if (ofnode_read_u32_array(node, "reg", reg, 2)) {
- debug("Node '%s' has bad/missing 'reg' property\n",
+ if (ofnode_read_u32(node, "image-pos", &entry->offset)) {
+ debug("Node '%s' has bad/missing 'image-pos' property\n",
ofnode_get_name(node));
- return -log_ret(ENOENT);
+ return log_ret(-ENOENT);
+ }
+ if (ofnode_read_u32(node, "size", &entry->length)) {
+ debug("Node '%s' has bad/missing 'size' property\n",
+ ofnode_get_name(node));
+ return log_ret(-ENOENT);
}
- entry->offset = reg[0];
- entry->length = reg[1];
entry->used = ofnode_read_s32_default(node, "used", entry->length);
prop = ofnode_read_string(node, "compress");
- entry->compress_algo = prop && !strcmp(prop, "lzo") ?
- FMAP_COMPRESS_LZO : FMAP_COMPRESS_NONE;
+ if (prop) {
+ if (!strcmp(prop, "lz4"))
+ entry->compress_algo = FMAP_COMPRESS_LZ4;
+ else
+ return log_msg_ret("Unknown compression algo",
+ -EINVAL);
+ } else {
+ entry->compress_algo = FMAP_COMPRESS_NONE;
+ }
+ entry->unc_length = ofnode_read_s32_default(node, "uncomp-size",
+ entry->length);
prop = ofnode_read_string(node, "hash");
if (prop)
entry->hash_size = strlen(prop);
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index 1e354803b0..b7b7ad3a62 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -541,9 +541,13 @@ fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property,
if (!prop)
return FDT_ADDR_T_NONE;
na = of_n_addr_cells(np);
- ns = of_n_addr_cells(np);
+ ns = of_n_size_cells(np);
*sizep = of_read_number(prop + na, ns);
- return of_read_number(prop, na);
+
+ if (IS_ENABLED(CONFIG_OF_TRANSLATE) && ns > 0)
+ return of_translate_address(np, prop);
+ else
+ return of_read_number(prop, na);
} else {
return fdtdec_get_addr_size(gd->fdt_blob,
ofnode_to_offset(node), property,
@@ -695,6 +699,8 @@ bool ofnode_pre_reloc(ofnode node)
{
if (ofnode_read_bool(node, "u-boot,dm-pre-reloc"))
return true;
+ if (ofnode_read_bool(node, "u-boot,dm-pre-proper"))
+ return true;
#ifdef CONFIG_TPL_BUILD
if (ofnode_read_bool(node, "u-boot,dm-tpl"))
diff --git a/drivers/gpio/da8xx_gpio.c b/drivers/gpio/da8xx_gpio.c
index b0d49cb46f..bd79448164 100644
--- a/drivers/gpio/da8xx_gpio.c
+++ b/drivers/gpio/da8xx_gpio.c
@@ -11,11 +11,14 @@
#include <fdtdec.h>
#include <asm/io.h>
#include <asm/gpio.h>
-#include <asm/arch/hardware.h>
-#include <asm/arch/davinci_misc.h>
#include <dt-bindings/gpio/gpio.h>
+#include "da8xx_gpio.h"
+
#ifndef CONFIG_DM_GPIO
+#include <asm/arch/hardware.h>
+#include <asm/arch/davinci_misc.h>
+
static struct gpio_registry {
int is_registered;
char name[GPIO_NAME_SIZE];
@@ -530,6 +533,7 @@ static int davinci_gpio_probe(struct udevice *dev)
static const struct udevice_id davinci_gpio_ids[] = {
{ .compatible = "ti,dm6441-gpio" },
+ { .compatible = "ti,k2g-gpio" },
{ }
};
diff --git a/drivers/gpio/da8xx_gpio.h b/drivers/gpio/da8xx_gpio.h
new file mode 100644
index 0000000000..1de9ec7f6f
--- /dev/null
+++ b/drivers/gpio/da8xx_gpio.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef _GPIO_DA8XX_DEFS_H_
+#define _GPIO_DA8XX_DEFS_H_
+
+struct davinci_gpio {
+ unsigned int dir;
+ unsigned int out_data;
+ unsigned int set_data;
+ unsigned int clr_data;
+ unsigned int in_data;
+ unsigned int set_rising;
+ unsigned int clr_rising;
+ unsigned int set_falling;
+ unsigned int clr_falling;
+ unsigned int intstat;
+};
+
+struct davinci_gpio_bank {
+ int num_gpio;
+ unsigned int irq_num;
+ unsigned int irq_mask;
+ unsigned long *in_use;
+ struct davinci_gpio *base;
+};
+
+#define GPIO_NAME_SIZE 20
+#define MAX_NUM_GPIOS 144
+#define GPIO_BIT(gp) ((gp) & 0x1F)
+
+#ifdef CONFIG_DM_GPIO
+
+/* Information about a GPIO bank */
+struct davinci_gpio_platdata {
+ int bank_index;
+ ulong base; /* address of registers in physical memory */
+ const char *port_name;
+};
+#endif
+
+#endif
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index ae3b501555..1ef22e6bcd 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -416,6 +416,13 @@ config SYS_I2C_UNIPHIER_F
Support for UniPhier FIFO-builtin I2C controller driver.
This I2C controller is used on PH1-Pro4 or newer UniPhier SoCs.
+config SYS_I2C_VERSATILE
+ bool "Arm Ltd Versatile I2C bus driver"
+ depends on DM_I2C && (TARGET_VEXPRESS_CA15_TC2 || TARGET_VEXPRESS64_JUNO)
+ help
+ Add support for the Arm Ltd Versatile Express I2C driver. The I2C host
+ controller is present in the development boards manufactured by Arm Ltd.
+
config SYS_I2C_MVTWSI
bool "Marvell I2C driver"
depends on DM_I2C
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index f2cbe78c53..d3637bcd8d 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_SYS_I2C_STM32F7) += stm32f7_i2c.o
obj-$(CONFIG_SYS_I2C_TEGRA) += tegra_i2c.o
obj-$(CONFIG_SYS_I2C_UNIPHIER) += i2c-uniphier.o
obj-$(CONFIG_SYS_I2C_UNIPHIER_F) += i2c-uniphier-f.o
+obj-$(CONFIG_SYS_I2C_VERSATILE) += i2c-versatile.o
obj-$(CONFIG_SYS_I2C_ZYNQ) += zynq_i2c.o
obj-$(CONFIG_TEGRA186_BPMP_I2C) += tegra186_bpmp_i2c.o
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index 7ffb949f12..7afdafed94 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -1,3 +1,16 @@
+config INPUT
+ bool "Enable input subsystem"
+ depends on DM
+ default y
+
+config SPL_INPUT
+ bool "Enable input subsystem for SPL"
+ depends on SPL_DM
+
+config TPL_INPUT
+ bool "Enable input subsystem for TPL"
+ depends on TPL_DM
+
config DM_KEYBOARD
bool "Enable driver model keyboard support"
depends on DM
@@ -7,8 +20,43 @@ config DM_KEYBOARD
includes methods to start/stop the device, check for available
input and update LEDs if the keyboard has them.
+config SPL_DM_KEYBOARD
+ bool "Enable driver model keyboard support"
+ depends on SPL_DM
+ help
+ This adds a uclass for keyboards and implements keyboard support
+ using driver model. The API is implemented by keyboard.h and
+ includes methods to start/stop the device, check for available
+ input and update LEDs if the keyboard has them.
+
+config TPL_DM_KEYBOARD
+ bool "Enable driver model keyboard support"
+ depends on TPL_DM
+ help
+ This adds a uclass for keyboards and implements keyboard support
+ using driver model. The API is implemented by keyboard.h and
+ includes methods to start/stop the device, check for available
+ input and update LEDs if the keyboard has them.
+
config CROS_EC_KEYB
bool "Enable Chrome OS EC keyboard support"
+ depends on INPUT
+ help
+ Most ARM Chromebooks use an EC to provide access to the keyboard.
+ Messages are used to request key scans from the EC and these are
+ then decoded into keys by this driver.
+
+config SPL_CROS_EC_KEYB
+ bool "Enable Chrome OS EC keyboard support in SPL"
+ depends on SPL_INPUT
+ help
+ Most ARM Chromebooks use an EC to provide access to the keyboard.
+ Messages are used to request key scans from the EC and these are
+ then decoded into keys by this driver.
+
+config TPL_CROS_EC_KEYB
+ bool "Enable Chrome OS EC keyboard support in TPL"
+ depends on TPL_INPUT
help
Most ARM Chromebooks use an EC to provide access to the keyboard.
Messages are used to request key scans from the EC and these are
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
index d13baf3576..fd56d7b349 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -3,12 +3,15 @@
# (C) Copyright 2000-2007
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-obj-$(CONFIG_DM_KEYBOARD) += keyboard-uclass.o
+obj-y += input.o
+obj-$(CONFIG_$(SPL_TPL_)CROS_EC_KEYB) += cros_ec_keyb.o
+obj-$(CONFIG_$(SPL_TPL_)OF_CONTROL) += key_matrix.o
+obj-$(CONFIG_$(SPL_TPL_)DM_KEYBOARD) += keyboard-uclass.o
+
+ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_I8042_KEYB) += i8042.o
obj-$(CONFIG_TEGRA_KEYBOARD) += tegra-kbc.o
obj-$(CONFIG_TWL4030_INPUT) += twl4030.o
obj-$(CONFIG_TWL6030_INPUT) += twl6030.o
-obj-$(CONFIG_CROS_EC_KEYB) += cros_ec_keyb.o
-obj-y += input.o
-obj-$(CONFIG_$(SPL_)OF_CONTROL) += key_matrix.o
+endif
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 29620a9e27..4f514dba56 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -652,7 +652,7 @@ int input_stdio_register(struct stdio_dev *dev)
int error;
error = stdio_register(dev);
-
+#if !defined(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(ENV_SUPPORT)
/* check if this is the standard input device */
if (!error && strcmp(env_get("stdin"), dev->name) == 0) {
/* reassign the console */
@@ -660,6 +660,9 @@ int input_stdio_register(struct stdio_dev *dev)
console_assign(stdin, dev->name))
return -1;
}
+#else
+ error = error;
+#endif
return 0;
}
diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c
index 6f299d407a..190505c11c 100644
--- a/drivers/misc/cros_ec.c
+++ b/drivers/misc/cros_ec.c
@@ -83,15 +83,15 @@ int cros_ec_calc_checksum(const uint8_t *data, int size)
* @param dout_len Size of output data in bytes
* @return packet size in bytes, or <0 if error.
*/
-static int create_proto3_request(struct cros_ec_dev *dev,
+static int create_proto3_request(struct cros_ec_dev *cdev,
int cmd, int cmd_version,
const void *dout, int dout_len)
{
- struct ec_host_request *rq = (struct ec_host_request *)dev->dout;
+ struct ec_host_request *rq = (struct ec_host_request *)cdev->dout;
int out_bytes = dout_len + sizeof(*rq);
/* Fail if output size is too big */
- if (out_bytes > (int)sizeof(dev->dout)) {
+ if (out_bytes > (int)sizeof(cdev->dout)) {
debug("%s: Cannot send %d bytes\n", __func__, dout_len);
return -EC_RES_REQUEST_TRUNCATED;
}
@@ -108,9 +108,9 @@ static int create_proto3_request(struct cros_ec_dev *dev,
memcpy(rq + 1, dout, dout_len);
/* Write checksum field so the entire packet sums to 0 */
- rq->checksum = (uint8_t)(-cros_ec_calc_checksum(dev->dout, out_bytes));
+ rq->checksum = (uint8_t)(-cros_ec_calc_checksum(cdev->dout, out_bytes));
- cros_ec_dump_data("out", cmd, dev->dout, out_bytes);
+ cros_ec_dump_data("out", cmd, cdev->dout, out_bytes);
/* Return size of request packet */
return out_bytes;
@@ -123,12 +123,12 @@ static int create_proto3_request(struct cros_ec_dev *dev,
* @param din_len Maximum size of response in bytes
* @return maximum expected number of bytes in response, or <0 if error.
*/
-static int prepare_proto3_response_buffer(struct cros_ec_dev *dev, int din_len)
+static int prepare_proto3_response_buffer(struct cros_ec_dev *cdev, int din_len)
{
int in_bytes = din_len + sizeof(struct ec_host_response);
/* Fail if input size is too big */
- if (in_bytes > (int)sizeof(dev->din)) {
+ if (in_bytes > (int)sizeof(cdev->din)) {
debug("%s: Cannot receive %d bytes\n", __func__, din_len);
return -EC_RES_RESPONSE_TOO_BIG;
}
@@ -197,7 +197,7 @@ static int handle_proto3_response(struct cros_ec_dev *dev,
return rs->data_len;
}
-static int send_command_proto3(struct cros_ec_dev *dev,
+static int send_command_proto3(struct cros_ec_dev *cdev,
int cmd, int cmd_version,
const void *dout, int dout_len,
uint8_t **dinp, int din_len)
@@ -207,23 +207,24 @@ static int send_command_proto3(struct cros_ec_dev *dev,
int rv;
/* Create request packet */
- out_bytes = create_proto3_request(dev, cmd, cmd_version,
+ out_bytes = create_proto3_request(cdev, cmd, cmd_version,
dout, dout_len);
if (out_bytes < 0)
return out_bytes;
/* Prepare response buffer */
- in_bytes = prepare_proto3_response_buffer(dev, din_len);
+ in_bytes = prepare_proto3_response_buffer(cdev, din_len);
if (in_bytes < 0)
return in_bytes;
- ops = dm_cros_ec_get_ops(dev->dev);
- rv = ops->packet ? ops->packet(dev->dev, out_bytes, in_bytes) : -ENOSYS;
+ ops = dm_cros_ec_get_ops(cdev->dev);
+ rv = ops->packet ? ops->packet(cdev->dev, out_bytes, in_bytes) :
+ -ENOSYS;
if (rv < 0)
return rv;
/* Process the response */
- return handle_proto3_response(dev, dinp, din_len);
+ return handle_proto3_response(cdev, dinp, din_len);
}
static int send_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
@@ -262,15 +263,16 @@ static int send_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
* @param din_len Maximum size of response in bytes
* @return number of bytes in response, or -ve on error
*/
-static int ec_command_inptr(struct cros_ec_dev *dev, uint8_t cmd,
- int cmd_version, const void *dout, int dout_len, uint8_t **dinp,
- int din_len)
+static int ec_command_inptr(struct udevice *dev, uint8_t cmd,
+ int cmd_version, const void *dout, int dout_len,
+ uint8_t **dinp, int din_len)
{
+ struct cros_ec_dev *cdev = dev_get_uclass_priv(dev);
uint8_t *din = NULL;
int len;
- len = send_command(dev, cmd, cmd_version, dout, dout_len,
- &din, din_len);
+ len = send_command(cdev, cmd, cmd_version, dout, dout_len, &din,
+ din_len);
/* If the command doesn't complete, wait a while */
if (len == -EC_RES_IN_PROGRESS) {
@@ -283,9 +285,9 @@ static int ec_command_inptr(struct cros_ec_dev *dev, uint8_t cmd,
int ret;
mdelay(50); /* Insert some reasonable delay */
- ret = send_command(dev, EC_CMD_GET_COMMS_STATUS, 0,
- NULL, 0,
- (uint8_t **)&resp, sizeof(*resp));
+ ret = send_command(cdev, EC_CMD_GET_COMMS_STATUS, 0,
+ NULL, 0,
+ (uint8_t **)&resp, sizeof(*resp));
if (ret < 0)
return ret;
@@ -298,8 +300,8 @@ static int ec_command_inptr(struct cros_ec_dev *dev, uint8_t cmd,
/* OK it completed, so read the status response */
/* not sure why it was 0 for the last argument */
- len = send_command(dev, EC_CMD_RESEND_RESPONSE, 0,
- NULL, 0, &din, din_len);
+ len = send_command(cdev, EC_CMD_RESEND_RESPONSE, 0, NULL, 0,
+ &din, din_len);
}
debug("%s: len=%d, din=%p\n", __func__, len, din);
@@ -328,7 +330,7 @@ static int ec_command_inptr(struct cros_ec_dev *dev, uint8_t cmd,
* @param din_len Maximum size of response in bytes
* @return number of bytes in response, or -ve on error
*/
-static int ec_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
+static int ec_command(struct udevice *dev, uint8_t cmd, int cmd_version,
const void *dout, int dout_len,
void *din, int din_len)
{
@@ -337,7 +339,7 @@ static int ec_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
assert((din_len == 0) || din);
len = ec_command_inptr(dev, cmd, cmd_version, dout, dout_len,
- &in_buffer, din_len);
+ &in_buffer, din_len);
if (len > 0) {
/*
* If we were asked to put it somewhere, do so, otherwise just
@@ -353,16 +355,14 @@ static int ec_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
int cros_ec_scan_keyboard(struct udevice *dev, struct mbkp_keyscan *scan)
{
- struct cros_ec_dev *cdev = dev_get_uclass_priv(dev);
-
- if (ec_command(cdev, EC_CMD_MKBP_STATE, 0, NULL, 0, scan,
+ if (ec_command(dev, EC_CMD_MKBP_STATE, 0, NULL, 0, scan,
sizeof(scan->data)) != sizeof(scan->data))
return -1;
return 0;
}
-int cros_ec_read_id(struct cros_ec_dev *dev, char *id, int maxlen)
+int cros_ec_read_id(struct udevice *dev, char *id, int maxlen)
{
struct ec_response_get_version *r;
@@ -388,8 +388,8 @@ int cros_ec_read_id(struct cros_ec_dev *dev, char *id, int maxlen)
return 0;
}
-int cros_ec_read_version(struct cros_ec_dev *dev,
- struct ec_response_get_version **versionp)
+int cros_ec_read_version(struct udevice *dev,
+ struct ec_response_get_version **versionp)
{
if (ec_command_inptr(dev, EC_CMD_GET_VERSION, 0, NULL, 0,
(uint8_t **)versionp, sizeof(**versionp))
@@ -399,7 +399,7 @@ int cros_ec_read_version(struct cros_ec_dev *dev,
return 0;
}
-int cros_ec_read_build_info(struct cros_ec_dev *dev, char **strp)
+int cros_ec_read_build_info(struct udevice *dev, char **strp)
{
if (ec_command_inptr(dev, EC_CMD_GET_BUILD_INFO, 0, NULL, 0,
(uint8_t **)strp, EC_PROTO2_MAX_PARAM_SIZE) < 0)
@@ -408,8 +408,8 @@ int cros_ec_read_build_info(struct cros_ec_dev *dev, char **strp)
return 0;
}
-int cros_ec_read_current_image(struct cros_ec_dev *dev,
- enum ec_current_image *image)
+int cros_ec_read_current_image(struct udevice *dev,
+ enum ec_current_image *image)
{
struct ec_response_get_version *r;
@@ -421,8 +421,8 @@ int cros_ec_read_current_image(struct cros_ec_dev *dev,
return 0;
}
-static int cros_ec_wait_on_hash_done(struct cros_ec_dev *dev,
- struct ec_response_vboot_hash *hash)
+static int cros_ec_wait_on_hash_done(struct udevice *dev,
+ struct ec_response_vboot_hash *hash)
{
struct ec_params_vboot_hash p;
ulong start;
@@ -444,14 +444,14 @@ static int cros_ec_wait_on_hash_done(struct cros_ec_dev *dev,
return 0;
}
-
-int cros_ec_read_hash(struct cros_ec_dev *dev,
- struct ec_response_vboot_hash *hash)
+int cros_ec_read_hash(struct udevice *dev, uint hash_offset,
+ struct ec_response_vboot_hash *hash)
{
struct ec_params_vboot_hash p;
int rv;
p.cmd = EC_VBOOT_HASH_GET;
+ p.offset = hash_offset;
if (ec_command(dev, EC_CMD_VBOOT_HASH, 0, &p, sizeof(p),
hash, sizeof(*hash)) < 0)
return -1;
@@ -474,7 +474,7 @@ int cros_ec_read_hash(struct cros_ec_dev *dev,
p.cmd = EC_VBOOT_HASH_START;
p.hash_type = EC_VBOOT_HASH_TYPE_SHA256;
p.nonce_size = 0;
- p.offset = EC_VBOOT_HASH_OFFSET_RW;
+ p.offset = hash_offset;
if (ec_command(dev, EC_CMD_VBOOT_HASH, 0, &p, sizeof(p),
hash, sizeof(*hash)) < 0)
@@ -489,7 +489,7 @@ int cros_ec_read_hash(struct cros_ec_dev *dev,
return 0;
}
-static int cros_ec_invalidate_hash(struct cros_ec_dev *dev)
+static int cros_ec_invalidate_hash(struct udevice *dev)
{
struct ec_params_vboot_hash p;
struct ec_response_vboot_hash *hash;
@@ -514,8 +514,7 @@ static int cros_ec_invalidate_hash(struct cros_ec_dev *dev)
return 0;
}
-int cros_ec_reboot(struct cros_ec_dev *dev, enum ec_reboot_cmd cmd,
- uint8_t flags)
+int cros_ec_reboot(struct udevice *dev, enum ec_reboot_cmd cmd, uint8_t flags)
{
struct ec_params_reboot_ec p;
@@ -555,7 +554,7 @@ int cros_ec_interrupt_pending(struct udevice *dev)
return dm_gpio_get_value(&cdev->ec_int);
}
-int cros_ec_info(struct cros_ec_dev *dev, struct ec_response_mkbp_info *info)
+int cros_ec_info(struct udevice *dev, struct ec_response_mkbp_info *info)
{
if (ec_command(dev, EC_CMD_MKBP_INFO, 0, NULL, 0, info,
sizeof(*info)) != sizeof(*info))
@@ -564,7 +563,7 @@ int cros_ec_info(struct cros_ec_dev *dev, struct ec_response_mkbp_info *info)
return 0;
}
-int cros_ec_get_host_events(struct cros_ec_dev *dev, uint32_t *events_ptr)
+int cros_ec_get_host_events(struct udevice *dev, uint32_t *events_ptr)
{
struct ec_response_host_event_mask *resp;
@@ -583,7 +582,7 @@ int cros_ec_get_host_events(struct cros_ec_dev *dev, uint32_t *events_ptr)
return 0;
}
-int cros_ec_clear_host_events(struct cros_ec_dev *dev, uint32_t events)
+int cros_ec_clear_host_events(struct udevice *dev, uint32_t events)
{
struct ec_params_host_event_mask params;
@@ -600,9 +599,9 @@ int cros_ec_clear_host_events(struct cros_ec_dev *dev, uint32_t events)
return 0;
}
-int cros_ec_flash_protect(struct cros_ec_dev *dev,
- uint32_t set_mask, uint32_t set_flags,
- struct ec_response_flash_protect *resp)
+int cros_ec_flash_protect(struct udevice *dev, uint32_t set_mask,
+ uint32_t set_flags,
+ struct ec_response_flash_protect *resp)
{
struct ec_params_flash_protect params;
@@ -617,17 +616,18 @@ int cros_ec_flash_protect(struct cros_ec_dev *dev,
return 0;
}
-static int cros_ec_check_version(struct cros_ec_dev *dev)
+static int cros_ec_check_version(struct udevice *dev)
{
+ struct cros_ec_dev *cdev = dev_get_uclass_priv(dev);
struct ec_params_hello req;
struct ec_response_hello *resp;
struct dm_cros_ec_ops *ops;
int ret;
- ops = dm_cros_ec_get_ops(dev->dev);
+ ops = dm_cros_ec_get_ops(dev);
if (ops->check_version) {
- ret = ops->check_version(dev->dev);
+ ret = ops->check_version(dev);
if (ret)
return ret;
}
@@ -647,7 +647,7 @@ static int cros_ec_check_version(struct cros_ec_dev *dev)
*/
/* Try sending a version 3 packet */
- dev->protocol_version = 3;
+ cdev->protocol_version = 3;
req.in_data = 0;
if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req),
(uint8_t **)&resp, sizeof(*resp)) > 0) {
@@ -655,9 +655,9 @@ static int cros_ec_check_version(struct cros_ec_dev *dev)
}
/* Try sending a version 2 packet */
- dev->protocol_version = 2;
+ cdev->protocol_version = 2;
if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req),
- (uint8_t **)&resp, sizeof(*resp)) > 0) {
+ (uint8_t **)&resp, sizeof(*resp)) > 0) {
return 0;
}
@@ -667,12 +667,12 @@ static int cros_ec_check_version(struct cros_ec_dev *dev)
* version is no longer supported, and we don't know about any new
* protocol versions.
*/
- dev->protocol_version = 0;
+ cdev->protocol_version = 0;
printf("%s: ERROR: old EC interface not supported\n", __func__);
return -1;
}
-int cros_ec_test(struct cros_ec_dev *dev)
+int cros_ec_test(struct udevice *dev)
{
struct ec_params_hello req;
struct ec_response_hello *resp;
@@ -691,7 +691,7 @@ int cros_ec_test(struct cros_ec_dev *dev)
return 0;
}
-int cros_ec_flash_offset(struct cros_ec_dev *dev, enum ec_flash_region region,
+int cros_ec_flash_offset(struct udevice *dev, enum ec_flash_region region,
uint32_t *offset, uint32_t *size)
{
struct ec_params_flash_region_info p;
@@ -713,7 +713,7 @@ int cros_ec_flash_offset(struct cros_ec_dev *dev, enum ec_flash_region region,
return 0;
}
-int cros_ec_flash_erase(struct cros_ec_dev *dev, uint32_t offset, uint32_t size)
+int cros_ec_flash_erase(struct udevice *dev, uint32_t offset, uint32_t size)
{
struct ec_params_flash_erase p;
@@ -741,8 +741,8 @@ int cros_ec_flash_erase(struct cros_ec_dev *dev, uint32_t offset, uint32_t size)
* @param size Number of bytes to write
* @return 0 if ok, -1 on error
*/
-static int cros_ec_flash_write_block(struct cros_ec_dev *dev,
- const uint8_t *data, uint32_t offset, uint32_t size)
+static int cros_ec_flash_write_block(struct udevice *dev, const uint8_t *data,
+ uint32_t offset, uint32_t size)
{
struct ec_params_flash_write *p;
int ret;
@@ -767,7 +767,7 @@ static int cros_ec_flash_write_block(struct cros_ec_dev *dev,
/**
* Return optimal flash write burst size
*/
-static int cros_ec_flash_write_burst_size(struct cros_ec_dev *dev)
+static int cros_ec_flash_write_burst_size(struct udevice *dev)
{
return EC_FLASH_WRITE_VER0_SIZE;
}
@@ -801,8 +801,8 @@ static int cros_ec_data_is_erased(const uint32_t *data, int size)
* @param dev Pointer to device
* @param info Pointer to output flash info struct
*/
-int cros_ec_read_flashinfo(struct cros_ec_dev *dev,
- struct ec_response_flash_info *info)
+int cros_ec_read_flashinfo(struct udevice *dev,
+ struct ec_response_flash_info *info)
{
int ret;
@@ -814,9 +814,10 @@ int cros_ec_read_flashinfo(struct cros_ec_dev *dev,
return ret < sizeof(*info) ? -1 : 0;
}
-int cros_ec_flash_write(struct cros_ec_dev *dev, const uint8_t *data,
- uint32_t offset, uint32_t size)
+int cros_ec_flash_write(struct udevice *dev, const uint8_t *data,
+ uint32_t offset, uint32_t size)
{
+ struct cros_ec_dev *cdev = dev_get_uclass_priv(dev);
uint32_t burst = cros_ec_flash_write_burst_size(dev);
uint32_t end, off;
int ret;
@@ -831,8 +832,8 @@ int cros_ec_flash_write(struct cros_ec_dev *dev, const uint8_t *data,
/* If the data is empty, there is no point in programming it */
todo = min(end - off, burst);
- if (dev->optimise_flash_write &&
- cros_ec_data_is_erased((uint32_t *)data, todo))
+ if (cdev->optimise_flash_write &&
+ cros_ec_data_is_erased((uint32_t *)data, todo))
continue;
ret = cros_ec_flash_write_block(dev, data, off, todo);
@@ -858,8 +859,8 @@ int cros_ec_flash_write(struct cros_ec_dev *dev, const uint8_t *data,
* @param size Number of bytes to read
* @return 0 if ok, -1 on error
*/
-static int cros_ec_flash_read_block(struct cros_ec_dev *dev, uint8_t *data,
- uint32_t offset, uint32_t size)
+static int cros_ec_flash_read_block(struct udevice *dev, uint8_t *data,
+ uint32_t offset, uint32_t size)
{
struct ec_params_flash_read p;
@@ -870,8 +871,8 @@ static int cros_ec_flash_read_block(struct cros_ec_dev *dev, uint8_t *data,
&p, sizeof(p), data, size) >= 0 ? 0 : -1;
}
-int cros_ec_flash_read(struct cros_ec_dev *dev, uint8_t *data, uint32_t offset,
- uint32_t size)
+int cros_ec_flash_read(struct udevice *dev, uint8_t *data, uint32_t offset,
+ uint32_t size)
{
uint32_t burst = cros_ec_flash_write_burst_size(dev);
uint32_t end, off;
@@ -888,13 +889,14 @@ int cros_ec_flash_read(struct cros_ec_dev *dev, uint8_t *data, uint32_t offset,
return 0;
}
-int cros_ec_flash_update_rw(struct cros_ec_dev *dev,
- const uint8_t *image, int image_size)
+int cros_ec_flash_update_rw(struct udevice *dev, const uint8_t *image,
+ int image_size)
{
uint32_t rw_offset, rw_size;
int ret;
- if (cros_ec_flash_offset(dev, EC_FLASH_REGION_RW, &rw_offset, &rw_size))
+ if (cros_ec_flash_offset(dev, EC_FLASH_REGION_ACTIVE, &rw_offset,
+ &rw_size))
return -1;
if (image_size > (int)rw_size)
return -1;
@@ -927,26 +929,31 @@ int cros_ec_flash_update_rw(struct cros_ec_dev *dev,
return 0;
}
-int cros_ec_read_vbnvcontext(struct cros_ec_dev *dev, uint8_t *block)
+int cros_ec_read_nvdata(struct udevice *dev, uint8_t *block, int size)
{
struct ec_params_vbnvcontext p;
int len;
+ if (size != EC_VBNV_BLOCK_SIZE)
+ return -EINVAL;
+
p.op = EC_VBNV_CONTEXT_OP_READ;
len = ec_command(dev, EC_CMD_VBNV_CONTEXT, EC_VER_VBNV_CONTEXT,
&p, sizeof(p), block, EC_VBNV_BLOCK_SIZE);
if (len < EC_VBNV_BLOCK_SIZE)
- return -1;
+ return -EIO;
return 0;
}
-int cros_ec_write_vbnvcontext(struct cros_ec_dev *dev, const uint8_t *block)
+int cros_ec_write_nvdata(struct udevice *dev, const uint8_t *block, int size)
{
struct ec_params_vbnvcontext p;
int len;
+ if (size != EC_VBNV_BLOCK_SIZE)
+ return -EINVAL;
p.op = EC_VBNV_CONTEXT_OP_WRITE;
memcpy(p.block, block, sizeof(p.block));
@@ -960,13 +967,12 @@ int cros_ec_write_vbnvcontext(struct cros_ec_dev *dev, const uint8_t *block)
int cros_ec_set_ldo(struct udevice *dev, uint8_t index, uint8_t state)
{
- struct cros_ec_dev *cdev = dev_get_uclass_priv(dev);
struct ec_params_ldo_set params;
params.index = index;
params.state = state;
- if (ec_command_inptr(cdev, EC_CMD_LDO_SET, 0, &params, sizeof(params),
+ if (ec_command_inptr(dev, EC_CMD_LDO_SET, 0, &params, sizeof(params),
NULL, 0))
return -1;
@@ -975,13 +981,12 @@ int cros_ec_set_ldo(struct udevice *dev, uint8_t index, uint8_t state)
int cros_ec_get_ldo(struct udevice *dev, uint8_t index, uint8_t *state)
{
- struct cros_ec_dev *cdev = dev_get_uclass_priv(dev);
struct ec_params_ldo_get params;
struct ec_response_ldo_get *resp;
params.index = index;
- if (ec_command_inptr(cdev, EC_CMD_LDO_GET, 0, &params, sizeof(params),
+ if (ec_command_inptr(dev, EC_CMD_LDO_GET, 0, &params, sizeof(params),
(uint8_t **)&resp, sizeof(*resp)) !=
sizeof(*resp))
return -1;
@@ -1001,12 +1006,12 @@ int cros_ec_register(struct udevice *dev)
GPIOD_IS_IN);
cdev->optimise_flash_write = dev_read_bool(dev, "optimise-flash-write");
- if (cros_ec_check_version(cdev)) {
+ if (cros_ec_check_version(dev)) {
debug("%s: Could not detect CROS-EC version\n", __func__);
return -CROS_EC_ERR_CHECK_VERSION;
}
- if (cros_ec_read_id(cdev, id, sizeof(id))) {
+ if (cros_ec_read_id(dev, id, sizeof(id))) {
debug("%s: Could not read KBC ID\n", __func__);
return -CROS_EC_ERR_READ_ID;
}
@@ -1042,7 +1047,7 @@ int cros_ec_decode_ec_flash(struct udevice *dev, struct fdt_cros_ec *config)
if (0 == strcmp(name, "ro")) {
region = EC_FLASH_REGION_RO;
} else if (0 == strcmp(name, "rw")) {
- region = EC_FLASH_REGION_RW;
+ region = EC_FLASH_REGION_ACTIVE;
} else if (0 == strcmp(name, "wp-ro")) {
region = EC_FLASH_REGION_WP_RO;
} else {
@@ -1062,7 +1067,6 @@ int cros_ec_decode_ec_flash(struct udevice *dev, struct fdt_cros_ec *config)
int cros_ec_i2c_tunnel(struct udevice *dev, int port, struct i2c_msg *in,
int nmsgs)
{
- struct cros_ec_dev *cdev = dev_get_uclass_priv(dev);
union {
struct ec_params_i2c_passthru p;
uint8_t outbuf[EC_PROTO2_MAX_PARAM_SIZE];
@@ -1112,7 +1116,7 @@ int cros_ec_i2c_tunnel(struct udevice *dev, int port, struct i2c_msg *in,
}
}
- rv = ec_command(cdev, EC_CMD_I2C_PASSTHRU, 0, p, pdata - (uint8_t *)p,
+ rv = ec_command(dev, EC_CMD_I2C_PASSTHRU, 0, p, pdata - (uint8_t *)p,
r, sizeof(*r) + read_len);
if (rv < 0)
return rv;
diff --git a/drivers/misc/cros_ec_lpc.c b/drivers/misc/cros_ec_lpc.c
index be17adcc5a..71d03bfba2 100644
--- a/drivers/misc/cros_ec_lpc.c
+++ b/drivers/misc/cros_ec_lpc.c
@@ -40,6 +40,38 @@ static int wait_for_sync(struct cros_ec_dev *dev)
return 0;
}
+int cros_ec_lpc_packet(struct udevice *udev, int out_bytes, int in_bytes)
+{
+ struct cros_ec_dev *dev = dev_get_uclass_priv(udev);
+ uint8_t *d;
+ int i;
+
+ if (out_bytes > EC_LPC_HOST_PACKET_SIZE)
+ return log_msg_ret("Cannot send that many bytes\n", -E2BIG);
+
+ if (in_bytes > EC_LPC_HOST_PACKET_SIZE)
+ return log_msg_ret("Cannot receive that many bytes\n", -E2BIG);
+
+ if (wait_for_sync(dev))
+ return log_msg_ret("Timeout waiting ready\n", -ETIMEDOUT);
+
+ /* Write data */
+ for (i = 0, d = (uint8_t *)dev->dout; i < out_bytes; i++, d++)
+ outb(*d, EC_LPC_ADDR_HOST_PACKET + i);
+
+ /* Start the command */
+ outb(EC_COMMAND_PROTOCOL_3, EC_LPC_ADDR_HOST_CMD);
+
+ if (wait_for_sync(dev))
+ return log_msg_ret("Timeout waiting ready\n", -ETIMEDOUT);
+
+ /* Read back args */
+ for (i = 0, d = dev->din; i < in_bytes; i++, d++)
+ *d = inb(EC_LPC_ADDR_HOST_PACKET + i);
+
+ return in_bytes;
+}
+
int cros_ec_lpc_command(struct udevice *udev, uint8_t cmd, int cmd_version,
const uint8_t *dout, int dout_len,
uint8_t **dinp, int din_len)
@@ -200,6 +232,7 @@ static int cros_ec_probe(struct udevice *dev)
}
static struct dm_cros_ec_ops cros_ec_ops = {
+ .packet = cros_ec_lpc_packet,
.command = cros_ec_lpc_command,
.check_version = cros_ec_lpc_check_version,
};
diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c
index 47a9d26c3c..d741554d8a 100644
--- a/drivers/misc/cros_ec_sandbox.c
+++ b/drivers/misc/cros_ec_sandbox.c
@@ -365,7 +365,7 @@ static int process_cmd(struct ec_state *ec,
struct fmap_entry *entry;
int ret, size;
- entry = &ec->ec_config.region[EC_FLASH_REGION_RW];
+ entry = &ec->ec_config.region[EC_FLASH_REGION_ACTIVE];
switch (req->cmd) {
case EC_VBOOT_HASH_RECALC:
@@ -420,7 +420,7 @@ static int process_cmd(struct ec_state *ec,
switch (req->region) {
case EC_FLASH_REGION_RO:
- case EC_FLASH_REGION_RW:
+ case EC_FLASH_REGION_ACTIVE:
case EC_FLASH_REGION_WP_RO:
entry = &ec->ec_config.region[req->region];
resp->offset = entry->offset;
@@ -491,9 +491,9 @@ int cros_ec_sandbox_packet(struct udevice *udev, int out_bytes, int in_bytes)
return in_bytes;
}
-void cros_ec_check_keyboard(struct cros_ec_dev *dev)
+void cros_ec_check_keyboard(struct udevice *dev)
{
- struct ec_state *ec = dev_get_priv(dev->dev);
+ struct ec_state *ec = dev_get_priv(dev);
ulong start;
printf("Press keys for EC to detect on reset (ESC=recovery)...");
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 0a0d4aaf6c..27246ee465 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -538,7 +538,7 @@ config MMC_SDHCI_TEGRA
config MMC_SDHCI_ZYNQ
bool "Arasan SDHCI controller support"
- depends on ARCH_ZYNQ || ARCH_ZYNQMP
+ depends on ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_VERSAL
depends on DM_MMC && OF_CONTROL && BLK
depends on MMC_SDHCI
help
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c
index b311b80be8..138de59470 100644
--- a/drivers/mmc/tmio-common.c
+++ b/drivers/mmc/tmio-common.c
@@ -372,11 +372,19 @@ static int tmio_sd_dma_xfer(struct udevice *dev, struct mmc_data *data)
}
/* check if the address is DMA'able */
-static bool tmio_sd_addr_is_dmaable(unsigned long addr)
+static bool tmio_sd_addr_is_dmaable(const char *src)
{
+ uintptr_t addr = (uintptr_t)src;
+
if (!IS_ALIGNED(addr, TMIO_SD_DMA_MINALIGN))
return false;
+#if defined(CONFIG_RCAR_GEN3)
+ /* Gen3 DMA has 32bit limit */
+ if (addr >> 32)
+ return false;
+#endif
+
#if defined(CONFIG_ARCH_UNIPHIER) && !defined(CONFIG_ARM64) && \
defined(CONFIG_SPL_BUILD)
/*
@@ -486,7 +494,7 @@ int tmio_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
if (data) {
/* use DMA if the HW supports it and the buffer is aligned */
if (priv->caps & TMIO_SD_CAP_DMA_INTERNAL &&
- tmio_sd_addr_is_dmaable((long)data->src))
+ tmio_sd_addr_is_dmaable(data->src))
ret = tmio_sd_dma_xfer(dev, data);
else
ret = tmio_sd_pio_xfer(dev, data);
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index d98457e223..11cf12bb55 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -28,6 +28,16 @@ config MTD_PARTITIONS
Adds the MTD partitioning infrastructure from the Linux
kernel. Needed for UBI support.
+config FLASH_CFI_DRIVER
+ bool "Enable CFI Flash driver"
+ help
+ The Common Flash Interface specification was developed by Intel,
+ AMD and other flash manufactures. It provides a universal method
+ for probing the capabilities of flash devices. If you wish to
+ support any device that is CFI-compliant, you need to enable this
+ option. Visit <http://www.amd.com/products/nvd/overview/cfi.html>
+ for more information on CFI.
+
config CFI_FLASH
bool "Enable Driver Model for CFI Flash driver"
depends on MTD
@@ -39,6 +49,34 @@ config CFI_FLASH
option. Visit <http://www.amd.com/products/nvd/overview/cfi.html>
for more information on CFI.
+config SYS_FLASH_USE_BUFFER_WRITE
+ bool "Enable buffered writes to flash"
+ depends on FLASH_CFI_DRIVER
+ help
+ Use buffered writes to flash.
+
+config FLASH_CFI_MTD
+ bool "Enable CFI MTD driver"
+ depends on FLASH_CFI_DRIVER
+ help
+ This option enables the building of the cfi_mtd driver
+ in the drivers directory. The driver exports CFI flash
+ to the MTD layer.
+
+config SYS_FLASH_PROTECTION
+ bool "Use hardware flash protection"
+ depends on FLASH_CFI_DRIVER
+ help
+ If defined, hardware flash sectors protection is used
+ instead of U-Boot software protection.
+
+config SYS_FLASH_CFI
+ bool "Define extra elements in CFI for flash geometry"
+ depends on FLASH_CFI_DRIVER
+ help
+ Define if the flash driver uses extra elements in the
+ common flash structure for storing flash geometry.
+
config ALTERA_QSPI
bool "Altera Generic Quad SPI Controller"
depends on MTD
diff --git a/drivers/mtd/mtd_uboot.c b/drivers/mtd/mtd_uboot.c
index 6a211d52ff..7d7a11c990 100644
--- a/drivers/mtd/mtd_uboot.c
+++ b/drivers/mtd/mtd_uboot.c
@@ -104,7 +104,10 @@ int mtd_probe_devices(void)
mtd_probe_uclass_mtd_devs();
/* Check if mtdparts/mtdids changed since last call, otherwise: exit */
- if (!strcmp(mtdparts, old_mtdparts) && !strcmp(mtdids, old_mtdids))
+ if ((!mtdparts && !old_mtdparts && !mtdids && !old_mtdids) ||
+ (mtdparts && old_mtdparts && mtdids && old_mtdids &&
+ !strcmp(mtdparts, old_mtdparts) &&
+ !strcmp(mtdids, old_mtdids)))
return 0;
/* Update the local copy of mtdparts */
@@ -140,6 +143,10 @@ int mtd_probe_devices(void)
}
}
+ /* If either mtdparts or mtdids is empty, then exit */
+ if (!mtdparts || !mtdids)
+ return 0;
+
/* Start the parsing by ignoring the extra 'mtdparts=' prefix, if any */
if (strstr(mtdparts, "mtdparts="))
mtdparts += 9;
diff --git a/drivers/mtd/nand/raw/atmel_nand.c b/drivers/mtd/nand/raw/atmel_nand.c
index a5b76e1aa0..31ad2cfa88 100644
--- a/drivers/mtd/nand/raw/atmel_nand.c
+++ b/drivers/mtd/nand/raw/atmel_nand.c
@@ -249,7 +249,7 @@ static void pmecc_get_sigma(struct mtd_info *mtd)
int diff;
/* Init the Sigma(x) */
- memset(smu, 0, sizeof(int16_t) * ARRAY_SIZE(smu));
+ memset(smu, 0, sizeof(int16_t) * num * (cap + 2));
dmu_0_count = 0;
diff --git a/drivers/mtd/spi/sandbox.c b/drivers/mtd/spi/sandbox.c
index 1b6c028251..7fef754c63 100644
--- a/drivers/mtd/spi/sandbox.c
+++ b/drivers/mtd/spi/sandbox.c
@@ -8,6 +8,8 @@
* Licensed under the GPL-2 or later.
*/
+#define LOG_CATEGORY UCLASS_SPI_FLASH
+
#include <common.h>
#include <dm.h>
#include <malloc.h>
@@ -41,6 +43,7 @@ enum sandbox_sf_state {
SF_WRITE_STATUS, /* write the flash's status register */
};
+#if CONFIG_IS_ENABLED(LOG)
static const char *sandbox_sf_state_name(enum sandbox_sf_state state)
{
static const char * const states[] = {
@@ -49,6 +52,7 @@ static const char *sandbox_sf_state_name(enum sandbox_sf_state state)
};
return states[state];
}
+#endif /* LOG */
/* Bits for the status register */
#define STAT_WIP (1 << 0)
@@ -101,69 +105,44 @@ struct sandbox_spi_flash_plat_data {
/**
* This is a very strange probe function. If it has platform data (which may
* have come from the device tree) then this function gets the filename and
- * device type from there. Failing that it looks at the command line
- * parameter.
+ * device type from there.
*/
static int sandbox_sf_probe(struct udevice *dev)
{
/* spec = idcode:file */
struct sandbox_spi_flash *sbsf = dev_get_priv(dev);
- const char *file;
size_t len, idname_len;
const struct spi_flash_info *data;
struct sandbox_spi_flash_plat_data *pdata = dev_get_platdata(dev);
struct sandbox_state *state = state_get_current();
+ struct dm_spi_slave_platdata *slave_plat;
struct udevice *bus = dev->parent;
const char *spec = NULL;
+ struct udevice *emul;
int ret = 0;
int cs = -1;
- int i;
debug("%s: bus %d, looking for emul=%p: ", __func__, bus->seq, dev);
- if (bus->seq >= 0 && bus->seq < CONFIG_SANDBOX_SPI_MAX_BUS) {
- for (i = 0; i < CONFIG_SANDBOX_SPI_MAX_CS; i++) {
- if (state->spi[bus->seq][i].emul == dev)
- cs = i;
- }
- }
- if (cs == -1) {
+ ret = sandbox_spi_get_emul(state, bus, dev, &emul);
+ if (ret) {
printf("Error: Unknown chip select for device '%s'\n",
- dev->name);
- return -EINVAL;
+ dev->name);
+ return ret;
}
+ slave_plat = dev_get_parent_platdata(dev);
+ cs = slave_plat->cs;
debug("found at cs %d\n", cs);
if (!pdata->filename) {
- struct sandbox_state *state = state_get_current();
-
- assert(bus->seq != -1);
- if (bus->seq < CONFIG_SANDBOX_SPI_MAX_BUS)
- spec = state->spi[bus->seq][cs].spec;
- if (!spec) {
- debug("%s: No spec found for bus %d, cs %d\n",
- __func__, bus->seq, cs);
- ret = -ENOENT;
- goto error;
- }
-
- file = strchr(spec, ':');
- if (!file) {
- printf("%s: unable to parse file\n", __func__);
- ret = -EINVAL;
- goto error;
- }
- idname_len = file - spec;
- pdata->filename = file + 1;
- pdata->device_name = spec;
- ++file;
- } else {
- spec = strchr(pdata->device_name, ',');
- if (spec)
- spec++;
- else
- spec = pdata->device_name;
- idname_len = strlen(spec);
+ printf("Error: No filename available\n");
+ return -EINVAL;
}
+ spec = strchr(pdata->device_name, ',');
+ if (spec)
+ spec++;
+ else
+ spec = pdata->device_name;
+ idname_len = strlen(spec);
debug("%s: device='%s'\n", __func__, spec);
for (data = spi_flash_ids; data->name; data++) {
@@ -214,7 +193,7 @@ static void sandbox_sf_cs_activate(struct udevice *dev)
{
struct sandbox_spi_flash *sbsf = dev_get_priv(dev);
- debug("sandbox_sf: CS activated; state is fresh!\n");
+ log_content("sandbox_sf: CS activated; state is fresh!\n");
/* CS is asserted, so reset state */
sbsf->off = 0;
@@ -226,7 +205,7 @@ static void sandbox_sf_cs_activate(struct udevice *dev)
static void sandbox_sf_cs_deactivate(struct udevice *dev)
{
- debug("sandbox_sf: CS deactivated; cmd done processing!\n");
+ log_content("sandbox_sf: CS deactivated; cmd done processing!\n");
}
/*
@@ -302,8 +281,8 @@ static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx,
}
if (oldstate != sbsf->state)
- debug(" cmd: transition to %s state\n",
- sandbox_sf_state_name(sbsf->state));
+ log_content(" cmd: transition to %s state\n",
+ sandbox_sf_state_name(sbsf->state));
return 0;
}
@@ -334,8 +313,8 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen,
int bytes = bitlen / 8;
int ret;
- debug("sandbox_sf: state:%x(%s) bytes:%u\n", sbsf->state,
- sandbox_sf_state_name(sbsf->state), bytes);
+ log_content("sandbox_sf: state:%x(%s) bytes:%u\n", sbsf->state,
+ sandbox_sf_state_name(sbsf->state), bytes);
if ((flags & SPI_XFER_BEGIN))
sandbox_sf_cs_activate(dev);
@@ -354,7 +333,7 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen,
case SF_ID: {
u8 id;
- debug(" id: off:%u tx:", sbsf->off);
+ log_content(" id: off:%u tx:", sbsf->off);
if (sbsf->off < IDCODE_LEN) {
/* Extract correct byte from ID 0x00aabbcc */
id = ((JEDEC_MFR(sbsf->data) << 16) |
@@ -363,18 +342,18 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen,
} else {
id = 0;
}
- debug("%d %02x\n", sbsf->off, id);
+ log_content("%d %02x\n", sbsf->off, id);
tx[pos++] = id;
++sbsf->off;
break;
}
case SF_ADDR:
- debug(" addr: bytes:%u rx:%02x ", sbsf->addr_bytes,
- rx[pos]);
+ log_content(" addr: bytes:%u rx:%02x ",
+ sbsf->addr_bytes, rx[pos]);
if (sbsf->addr_bytes++ < SF_ADDR_LEN)
sbsf->off = (sbsf->off << 8) | rx[pos];
- debug("addr:%06x\n", sbsf->off);
+ log_content("addr:%06x\n", sbsf->off);
if (tx)
sandbox_spi_tristate(&tx[pos], 1);
@@ -403,8 +382,8 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen,
sbsf->state = SF_ERASE;
goto case_sf_erase;
}
- debug(" cmd: transition to %s state\n",
- sandbox_sf_state_name(sbsf->state));
+ log_content(" cmd: transition to %s state\n",
+ sandbox_sf_state_name(sbsf->state));
break;
case SF_READ:
/*
@@ -413,7 +392,7 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen,
*/
cnt = bytes - pos;
- debug(" tx: read(%u)\n", cnt);
+ log_content(" tx: read(%u)\n", cnt);
assert(tx);
ret = os_read(sbsf->fd, tx + pos, cnt);
if (ret < 0) {
@@ -423,19 +402,19 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen,
pos += ret;
break;
case SF_READ_STATUS:
- debug(" read status: %#x\n", sbsf->status);
+ log_content(" read status: %#x\n", sbsf->status);
cnt = bytes - pos;
memset(tx + pos, sbsf->status, cnt);
pos += cnt;
break;
case SF_READ_STATUS1:
- debug(" read status: %#x\n", sbsf->status);
+ log_content(" read status: %#x\n", sbsf->status);
cnt = bytes - pos;
memset(tx + pos, sbsf->status >> 8, cnt);
pos += cnt;
break;
case SF_WRITE_STATUS:
- debug(" write status: %#x (ignored)\n", rx[pos]);
+ log_content(" write status: %#x (ignored)\n", rx[pos]);
pos = bytes;
break;
case SF_WRITE:
@@ -451,7 +430,7 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen,
}
cnt = bytes - pos;
- debug(" rx: write(%u)\n", cnt);
+ log_content(" rx: write(%u)\n", cnt);
if (tx)
sandbox_spi_tristate(&tx[pos], cnt);
ret = os_write(sbsf->fd, rx + pos, cnt);
@@ -471,15 +450,15 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen,
/* verify address is aligned */
if (sbsf->off & (sbsf->erase_size - 1)) {
- debug(" sector erase: cmd:%#x needs align:%#x, but we got %#x\n",
- sbsf->cmd, sbsf->erase_size,
- sbsf->off);
+ log_content(" sector erase: cmd:%#x needs align:%#x, but we got %#x\n",
+ sbsf->cmd, sbsf->erase_size,
+ sbsf->off);
sbsf->status &= ~STAT_WEL;
goto done;
}
- debug(" sector erase addr: %u, size: %u\n", sbsf->off,
- sbsf->erase_size);
+ log_content(" sector erase addr: %u, size: %u\n",
+ sbsf->off, sbsf->erase_size);
cnt = bytes - pos;
if (tx)
@@ -493,13 +472,13 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen,
ret = sandbox_erase_part(sbsf, sbsf->erase_size);
sbsf->status &= ~STAT_WEL;
if (ret) {
- debug("sandbox_sf: Erase failed\n");
+ log_content("sandbox_sf: Erase failed\n");
goto done;
}
goto done;
}
default:
- debug(" ??? no idea what to do ???\n");
+ log_content(" ??? no idea what to do ???\n");
goto done;
}
}
@@ -530,31 +509,6 @@ static const struct dm_spi_emul_ops sandbox_sf_emul_ops = {
};
#ifdef CONFIG_SPI_FLASH
-static int sandbox_cmdline_cb_spi_sf(struct sandbox_state *state,
- const char *arg)
-{
- unsigned long bus, cs;
- const char *spec = sandbox_spi_parse_spec(arg, &bus, &cs);
-
- if (!spec)
- return 1;
-
- /*
- * It is safe to not make a copy of 'spec' because it comes from the
- * command line.
- *
- * TODO(sjg@chromium.org): It would be nice if we could parse the
- * spec here, but the problem is that no U-Boot init has been done
- * yet. Perhaps we can figure something out.
- */
- state->spi[bus][cs].spec = spec;
- debug("%s: Setting up spec '%s' for bus %ld, cs %ld\n", __func__,
- spec, bus, cs);
-
- return 0;
-}
-SANDBOX_CMDLINE_OPT(spi_sf, 1, "connect a SPI flash: <bus>:<cs>:<id>:<file>");
-
int sandbox_sf_bind_emul(struct sandbox_state *state, int busnum, int cs,
struct udevice *bus, ofnode node, const char *spec)
{
@@ -597,33 +551,6 @@ void sandbox_sf_unbind_emul(struct sandbox_state *state, int busnum, int cs)
state->spi[busnum][cs].emul = NULL;
}
-static int sandbox_sf_bind_bus_cs(struct sandbox_state *state, int busnum,
- int cs, const char *spec)
-{
- struct udevice *bus, *slave;
- int ret;
-
- ret = uclass_find_device_by_seq(UCLASS_SPI, busnum, true, &bus);
- if (ret) {
- printf("Invalid bus %d for spec '%s' (err=%d)\n", busnum,
- spec, ret);
- return ret;
- }
- ret = spi_find_chip_select(bus, cs, &slave);
- if (!ret) {
- printf("Chip select %d already exists for spec '%s'\n", cs,
- spec);
- return -EEXIST;
- }
-
- ret = device_bind_driver(bus, "spi_flash_std", spec, &slave);
- if (ret)
- return ret;
-
- return sandbox_sf_bind_emul(state, busnum, cs, bus, ofnode_null(),
- spec);
-}
-
int sandbox_spi_get_emul(struct sandbox_state *state,
struct udevice *bus, struct udevice *slave,
struct udevice **emulp)
@@ -650,35 +577,6 @@ int sandbox_spi_get_emul(struct sandbox_state *state,
return 0;
}
-
-int dm_scan_other(bool pre_reloc_only)
-{
- struct sandbox_state *state = state_get_current();
- int busnum, cs;
-
- if (pre_reloc_only)
- return 0;
- for (busnum = 0; busnum < CONFIG_SANDBOX_SPI_MAX_BUS; busnum++) {
- for (cs = 0; cs < CONFIG_SANDBOX_SPI_MAX_CS; cs++) {
- const char *spec = state->spi[busnum][cs].spec;
- int ret;
-
- if (spec) {
- ret = sandbox_sf_bind_bus_cs(state, busnum,
- cs, spec);
- if (ret) {
- debug("%s: Bind failed for bus %d, cs %d\n",
- __func__, busnum, cs);
- return ret;
- }
- debug("%s: Setting up spec '%s' for bus %d, cs %d\n",
- __func__, spec, busnum, cs);
- }
- }
- }
-
- return 0;
-}
#endif
static const struct udevice_id sandbox_sf_ids[] = {
diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c
index 3858f77a6d..662525f016 100644
--- a/drivers/mtd/spi/sf-uclass.c
+++ b/drivers/mtd/spi/sf-uclass.c
@@ -14,18 +14,18 @@ DECLARE_GLOBAL_DATA_PTR;
int spi_flash_read_dm(struct udevice *dev, u32 offset, size_t len, void *buf)
{
- return sf_get_ops(dev)->read(dev, offset, len, buf);
+ return log_ret(sf_get_ops(dev)->read(dev, offset, len, buf));
}
int spi_flash_write_dm(struct udevice *dev, u32 offset, size_t len,
const void *buf)
{
- return sf_get_ops(dev)->write(dev, offset, len, buf);
+ return log_ret(sf_get_ops(dev)->write(dev, offset, len, buf));
}
int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len)
{
- return sf_get_ops(dev)->erase(dev, offset, len);
+ return log_ret(sf_get_ops(dev)->erase(dev, offset, len));
}
/*
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index 4f63cacc64..26f5c7c995 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -32,6 +32,7 @@ enum spi_nor_option_flags {
/* CFI Manufacture ID's */
#define SPI_FLASH_CFI_MFR_SPANSION 0x01
#define SPI_FLASH_CFI_MFR_STMICRO 0x20
+#define SPI_FLASH_CFI_MFR_MICRON 0x2C
#define SPI_FLASH_CFI_MFR_MACRONIX 0xc2
#define SPI_FLASH_CFI_MFR_SST 0xbf
#define SPI_FLASH_CFI_MFR_WINBOND 0xef
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index 42c7cdedf6..94fde2ae7a 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -97,7 +97,7 @@ static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len,
{
struct spi_flash *flash = dev_get_uclass_priv(dev);
- return spi_flash_cmd_read_ops(flash, offset, len, buf);
+ return log_ret(spi_flash_cmd_read_ops(flash, offset, len, buf));
}
static int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len,
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index c159124259..a87bacd4ac 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -468,17 +468,17 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
size_t len, void *data)
{
struct spi_slave *spi = flash->spi;
- u8 *cmd, cmdsz;
+ u8 cmdsz;
u32 remain_len, read_len, read_addr;
int bank_sel = 0;
- int ret = -1;
+ int ret = 0;
/* Handle memory-mapped SPI */
if (flash->memory_map) {
ret = spi_claim_bus(spi);
if (ret) {
debug("SF: unable to claim SPI bus\n");
- return ret;
+ return log_ret(ret);
}
spi_xfer(spi, 0, NULL, NULL, SPI_XFER_MMAP);
spi_flash_copy_mmap(data, flash->memory_map + offset, len);
@@ -488,11 +488,7 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
}
cmdsz = SPI_FLASH_CMD_LEN + flash->dummy_byte;
- cmd = calloc(1, cmdsz);
- if (!cmd) {
- debug("SF: Failed to allocate cmd\n");
- return -ENOMEM;
- }
+ u8 cmd[cmdsz];
cmd[0] = flash->read_cmd;
while (len) {
@@ -505,7 +501,7 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
#ifdef CONFIG_SPI_FLASH_BAR
ret = write_bar(flash, read_addr);
if (ret < 0)
- return ret;
+ return log_ret(ret);
bank_sel = flash->bank_curr;
#endif
remain_len = ((SPI_FLASH_16MB_BOUN << flash->shift) *
@@ -535,8 +531,7 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
ret = clean_bar(flash);
#endif
- free(cmd);
- return ret;
+ return log_ret(ret);
}
#ifdef CONFIG_SPI_FLASH_SST
@@ -1096,6 +1091,7 @@ static int set_quad_mode(struct spi_flash *flash,
#endif
#ifdef CONFIG_SPI_FLASH_STMICRO
case SPI_FLASH_CFI_MFR_STMICRO:
+ case SPI_FLASH_CFI_MFR_MICRON:
debug("SF: QEB is volatile for %02x flash\n", JEDEC_MFR(info));
return 0;
#endif
@@ -1183,6 +1179,7 @@ int spi_flash_scan(struct spi_flash *flash)
#if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST)
/* NOR protection support for STmicro/Micron chips and similar */
if (JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_STMICRO ||
+ JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_MICRON ||
JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_SST) {
flash->flash_lock = stm_lock;
flash->flash_unlock = stm_unlock;
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 5441da47d1..f1f0e2d94e 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -344,7 +344,7 @@ config XILINX_EMACLITE
This MAC is present in Xilinx Microblaze, Zynq and ZynqMP SoCs.
config ZYNQ_GEM
- depends on DM_ETH && (ARCH_ZYNQ || ARCH_ZYNQMP)
+ depends on DM_ETH && (ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_VERSAL)
select PHYLIB
bool "Xilinx Ethernet GEM"
help
diff --git a/drivers/net/dc2114x.c b/drivers/net/dc2114x.c
index 8d7c271038..e3c403c13f 100644
--- a/drivers/net/dc2114x.c
+++ b/drivers/net/dc2114x.c
@@ -123,7 +123,6 @@
#define TOUT_LOOP 1000000
#define SETUP_FRAME_LEN 192
-#define ETH_ALEN 6
struct de4x5_desc {
volatile s32 status;
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index ae65b649bf..2fe0ba6e20 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -193,8 +193,6 @@ struct descriptor { /* A generic descriptor. */
#define TOUT_LOOP 1000000
-#define ETH_ALEN 6
-
static struct RxFD rx_ring[NUM_RX_DESC]; /* RX descriptor ring */
static struct TxFD tx_ring[NUM_TX_DESC]; /* TX descriptor ring */
static int rx_next; /* RX descriptor ring pointer */
diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c
index d9a897dc86..b245fbc681 100644
--- a/drivers/net/fsl-mc/mc.c
+++ b/drivers/net/fsl-mc/mc.c
@@ -363,8 +363,7 @@ static int mc_fixup_mac_addrs(void *blob, enum mc_fixup_type type)
for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) {
/* port not enabled */
- if ((wriop_is_enabled_dpmac(i) != 1) ||
- (wriop_get_phy_address(i) == -1))
+ if (wriop_is_enabled_dpmac(i) != 1)
continue;
snprintf(ethname, ETH_NAME_LEN, "DPMAC%d@%s", i,
@@ -886,8 +885,7 @@ int fsl_mc_ldpaa_init(bd_t *bis)
int i;
for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++)
- if ((wriop_is_enabled_dpmac(i) == 1) &&
- (wriop_get_phy_address(i) != -1))
+ if (wriop_is_enabled_dpmac(i) == 1)
ldpaa_eth_init(i, wriop_get_enet_if(i));
return 0;
}
diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c
index a25b7cd906..73b7ba29df 100644
--- a/drivers/net/ldpaa_eth/ldpaa_eth.c
+++ b/drivers/net/ldpaa_eth/ldpaa_eth.c
@@ -23,21 +23,43 @@ static int init_phy(struct eth_device *dev)
struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv;
struct phy_device *phydev = NULL;
struct mii_dev *bus;
+ int phy_addr, phy_num;
+ int ret = 0;
bus = wriop_get_mdio(priv->dpmac_id);
if (bus == NULL)
return 0;
- phydev = phy_connect(bus, wriop_get_phy_address(priv->dpmac_id),
- dev, wriop_get_enet_if(priv->dpmac_id));
- if (!phydev) {
- printf("Failed to connect\n");
- return -1;
+ for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) {
+ phy_addr = wriop_get_phy_address(priv->dpmac_id, phy_num);
+ if (phy_addr < 0)
+ continue;
+
+ phydev = phy_connect(bus, phy_addr, dev,
+ wriop_get_enet_if(priv->dpmac_id));
+ if (!phydev) {
+ printf("Failed to connect\n");
+ ret = -ENODEV;
+ break;
+ }
+ wriop_set_phy_dev(priv->dpmac_id, phy_num, phydev);
+ ret = phy_config(phydev);
+ if (ret)
+ break;
}
- priv->phydev = phydev;
+ if (ret) {
+ for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) {
+ phydev = wriop_get_phy_dev(priv->dpmac_id, phy_num);
+ if (!phydev)
+ continue;
+
+ free(phydev);
+ wriop_set_phy_dev(priv->dpmac_id, phy_num, NULL);
+ }
+ }
- return phy_config(phydev);
+ return ret;
}
#endif
@@ -377,6 +399,70 @@ error:
return err;
}
+static int ldpaa_get_dpmac_state(struct ldpaa_eth_priv *priv,
+ struct dpmac_link_state *state)
+{
+ phy_interface_t enet_if;
+ int phys_detected;
+#ifdef CONFIG_PHYLIB
+ struct phy_device *phydev = NULL;
+ int err, phy_num;
+#endif
+
+ /* let's start off with maximum capabilities */
+ enet_if = wriop_get_enet_if(priv->dpmac_id);
+ switch (enet_if) {
+ case PHY_INTERFACE_MODE_XGMII:
+ state->rate = SPEED_10000;
+ break;
+ default:
+ state->rate = SPEED_1000;
+ break;
+ }
+ state->up = 1;
+
+ phys_detected = 0;
+#ifdef CONFIG_PHYLIB
+ state->options |= DPMAC_LINK_OPT_AUTONEG;
+
+ /* start the phy devices one by one and update the dpmac state */
+ for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) {
+ phydev = wriop_get_phy_dev(priv->dpmac_id, phy_num);
+ if (!phydev)
+ continue;
+
+ phys_detected++;
+ err = phy_startup(phydev);
+ if (err) {
+ printf("%s: Could not initialize\n", phydev->dev->name);
+ state->up = 0;
+ break;
+ }
+ if (phydev->link) {
+ state->rate = min(state->rate, (uint32_t)phydev->speed);
+ if (!phydev->duplex)
+ state->options |= DPMAC_LINK_OPT_HALF_DUPLEX;
+ if (!phydev->autoneg)
+ state->options &= ~DPMAC_LINK_OPT_AUTONEG;
+ } else {
+ /* break out of loop even if one phy is down */
+ state->up = 0;
+ break;
+ }
+ }
+#endif
+ if (!phys_detected)
+ state->options &= ~DPMAC_LINK_OPT_AUTONEG;
+
+ if (!state->up) {
+ state->rate = 0;
+ state->options = 0;
+ return -ENOLINK;
+ }
+
+ return 0;
+}
+
static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd)
{
struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
@@ -385,8 +471,6 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd)
struct dpni_link_state link_state;
#endif
int err = 0;
- struct mii_dev *bus;
- phy_interface_t enet_if;
struct dpni_queue d_queue;
if (net_dev->state == ETH_STATE_ACTIVE)
@@ -407,47 +491,14 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd)
if (err < 0)
goto err_dpmac_setup;
-#ifdef CONFIG_PHYLIB
- if (priv->phydev) {
- err = phy_startup(priv->phydev);
- if (err) {
- printf("%s: Could not initialize\n",
- priv->phydev->dev->name);
- goto err_dpamc_bind;
- }
- }
-#else
- priv->phydev = (struct phy_device *)malloc(sizeof(struct phy_device));
- memset(priv->phydev, 0, sizeof(struct phy_device));
-
- priv->phydev->speed = SPEED_1000;
- priv->phydev->link = 1;
- priv->phydev->duplex = DUPLEX_FULL;
-#endif
-
- bus = wriop_get_mdio(priv->dpmac_id);
- enet_if = wriop_get_enet_if(priv->dpmac_id);
- if ((bus == NULL) &&
- (enet_if == PHY_INTERFACE_MODE_XGMII)) {
- priv->phydev = (struct phy_device *)
- malloc(sizeof(struct phy_device));
- memset(priv->phydev, 0, sizeof(struct phy_device));
-
- priv->phydev->speed = SPEED_10000;
- priv->phydev->link = 1;
- priv->phydev->duplex = DUPLEX_FULL;
- }
-
- if (!priv->phydev->link) {
- printf("%s: No link.\n", priv->phydev->dev->name);
- err = -1;
- goto err_dpamc_bind;
- }
+ err = ldpaa_get_dpmac_state(priv, &dpmac_link_state);
+ if (err < 0)
+ goto err_dpmac_bind;
/* DPMAC binding DPNI */
err = ldpaa_dpmac_bind(priv);
if (err)
- goto err_dpamc_bind;
+ goto err_dpmac_bind;
/* DPNI initialization */
err = ldpaa_dpni_setup(priv);
@@ -476,18 +527,6 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd)
return err;
}
- dpmac_link_state.rate = priv->phydev->speed;
-
- if (priv->phydev->autoneg == AUTONEG_DISABLE)
- dpmac_link_state.options &= ~DPMAC_LINK_OPT_AUTONEG;
- else
- dpmac_link_state.options |= DPMAC_LINK_OPT_AUTONEG;
-
- if (priv->phydev->duplex == DUPLEX_HALF)
- dpmac_link_state.options |= DPMAC_LINK_OPT_HALF_DUPLEX;
-
- dpmac_link_state.up = priv->phydev->link;
-
err = dpmac_set_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
priv->dpmac_handle, &dpmac_link_state);
if (err < 0) {
@@ -530,7 +569,7 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd)
goto err_qdid;
}
- return priv->phydev->link;
+ return dpmac_link_state.up;
err_qdid:
err_get_queue:
@@ -540,7 +579,7 @@ err_dpni_bind:
err_dpbp_setup:
dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
err_dpni_setup:
-err_dpamc_bind:
+err_dpmac_bind:
dpmac_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle);
dpmac_destroy(dflt_mc_io,
dflt_dprc_handle,
@@ -554,7 +593,8 @@ static void ldpaa_eth_stop(struct eth_device *net_dev)
struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
int err = 0;
#ifdef CONFIG_PHYLIB
- struct mii_dev *bus = wriop_get_mdio(priv->dpmac_id);
+ struct phy_device *phydev = NULL;
+ int phy_num;
#endif
if ((net_dev->state == ETH_STATE_PASSIVE) ||
@@ -588,11 +628,10 @@ static void ldpaa_eth_stop(struct eth_device *net_dev)
printf("dpni_disable() failed\n");
#ifdef CONFIG_PHYLIB
- if (priv->phydev && bus != NULL)
- phy_shutdown(priv->phydev);
- else {
- free(priv->phydev);
- priv->phydev = NULL;
+ for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) {
+ phydev = wriop_get_phy_dev(priv->dpmac_id, phy_num);
+ if (phydev)
+ phy_shutdown(phydev);
}
#endif
diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.h b/drivers/net/ldpaa_eth/ldpaa_eth.h
index ee784a55ee..3f9154b5bb 100644
--- a/drivers/net/ldpaa_eth/ldpaa_eth.h
+++ b/drivers/net/ldpaa_eth/ldpaa_eth.h
@@ -127,7 +127,6 @@ struct ldpaa_eth_priv {
uint16_t tx_flow_id;
enum ldpaa_eth_type type; /* 1G or 10G ethernet */
- struct phy_device *phydev;
};
struct dprc_endpoint dpmac_endpoint;
diff --git a/drivers/net/ldpaa_eth/ldpaa_wriop.c b/drivers/net/ldpaa_eth/ldpaa_wriop.c
index 0731a795c8..06a284ad68 100644
--- a/drivers/net/ldpaa_eth/ldpaa_wriop.c
+++ b/drivers/net/ldpaa_eth/ldpaa_wriop.c
@@ -22,10 +22,10 @@ __weak phy_interface_t wriop_dpmac_enet_if(int dpmac_id, int lane_prtc)
void wriop_init_dpmac(int sd, int dpmac_id, int lane_prtcl)
{
phy_interface_t enet_if;
+ int phy_num;
dpmac_info[dpmac_id].enabled = 0;
dpmac_info[dpmac_id].id = 0;
- dpmac_info[dpmac_id].phy_addr = -1;
dpmac_info[dpmac_id].enet_if = PHY_INTERFACE_MODE_NONE;
enet_if = wriop_dpmac_enet_if(dpmac_id, lane_prtcl);
@@ -34,14 +34,23 @@ void wriop_init_dpmac(int sd, int dpmac_id, int lane_prtcl)
dpmac_info[dpmac_id].id = dpmac_id;
dpmac_info[dpmac_id].enet_if = enet_if;
}
+ for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) {
+ dpmac_info[dpmac_id].phydev[phy_num] = NULL;
+ dpmac_info[dpmac_id].phy_addr[phy_num] = -1;
+ }
}
void wriop_init_dpmac_enet_if(int dpmac_id, phy_interface_t enet_if)
{
+ int phy_num;
+
dpmac_info[dpmac_id].enabled = 1;
dpmac_info[dpmac_id].id = dpmac_id;
- dpmac_info[dpmac_id].phy_addr = -1;
dpmac_info[dpmac_id].enet_if = enet_if;
+ for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) {
+ dpmac_info[dpmac_id].phydev[phy_num] = NULL;
+ dpmac_info[dpmac_id].phy_addr[phy_num] = -1;
+ }
}
@@ -58,47 +67,53 @@ static int wriop_dpmac_to_index(int dpmac_id)
return -1;
}
-void wriop_disable_dpmac(int dpmac_id)
+int wriop_disable_dpmac(int dpmac_id)
{
int i = wriop_dpmac_to_index(dpmac_id);
if (i == -1)
- return;
+ return -ENODEV;
dpmac_info[i].enabled = 0;
wriop_dpmac_disable(dpmac_id);
+
+ return 0;
}
-void wriop_enable_dpmac(int dpmac_id)
+int wriop_enable_dpmac(int dpmac_id)
{
int i = wriop_dpmac_to_index(dpmac_id);
if (i == -1)
- return;
+ return -ENODEV;
dpmac_info[i].enabled = 1;
wriop_dpmac_enable(dpmac_id);
+
+ return 0;
}
-u8 wriop_is_enabled_dpmac(int dpmac_id)
+int wriop_is_enabled_dpmac(int dpmac_id)
{
int i = wriop_dpmac_to_index(dpmac_id);
if (i == -1)
- return -1;
+ return -ENODEV;
return dpmac_info[i].enabled;
}
-void wriop_set_mdio(int dpmac_id, struct mii_dev *bus)
+int wriop_set_mdio(int dpmac_id, struct mii_dev *bus)
{
int i = wriop_dpmac_to_index(dpmac_id);
if (i == -1)
- return;
+ return -ENODEV;
dpmac_info[i].bus = bus;
+
+ return 0;
}
struct mii_dev *wriop_get_mdio(int dpmac_id)
@@ -111,44 +126,56 @@ struct mii_dev *wriop_get_mdio(int dpmac_id)
return dpmac_info[i].bus;
}
-void wriop_set_phy_address(int dpmac_id, int address)
+int wriop_set_phy_address(int dpmac_id, int phy_num, int address)
{
int i = wriop_dpmac_to_index(dpmac_id);
if (i == -1)
- return;
+ return -ENODEV;
+ if (phy_num < 0 || phy_num >= WRIOP_MAX_PHY_NUM)
+ return -EINVAL;
+
+ dpmac_info[i].phy_addr[phy_num] = address;
- dpmac_info[i].phy_addr = address;
+ return 0;
}
-int wriop_get_phy_address(int dpmac_id)
+int wriop_get_phy_address(int dpmac_id, int phy_num)
{
int i = wriop_dpmac_to_index(dpmac_id);
if (i == -1)
- return -1;
+ return -ENODEV;
+ if (phy_num < 0 || phy_num >= WRIOP_MAX_PHY_NUM)
+ return -EINVAL;
- return dpmac_info[i].phy_addr;
+ return dpmac_info[i].phy_addr[phy_num];
}
-void wriop_set_phy_dev(int dpmac_id, struct phy_device *phydev)
+int wriop_set_phy_dev(int dpmac_id, int phy_num, struct phy_device *phydev)
{
int i = wriop_dpmac_to_index(dpmac_id);
if (i == -1)
- return;
+ return -ENODEV;
+ if (phy_num < 0 || phy_num >= WRIOP_MAX_PHY_NUM)
+ return -EINVAL;
- dpmac_info[i].phydev = phydev;
+ dpmac_info[i].phydev[phy_num] = phydev;
+
+ return 0;
}
-struct phy_device *wriop_get_phy_dev(int dpmac_id)
+struct phy_device *wriop_get_phy_dev(int dpmac_id, int phy_num)
{
int i = wriop_dpmac_to_index(dpmac_id);
if (i == -1)
return NULL;
+ if (phy_num < 0 || phy_num >= WRIOP_MAX_PHY_NUM)
+ return NULL;
- return dpmac_info[i].phydev;
+ return dpmac_info[i].phydev[phy_num];
}
phy_interface_t wriop_get_enet_if(int dpmac_id)
diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c
index ab697b9bc7..8cb04b52d7 100644
--- a/drivers/net/mvneta.c
+++ b/drivers/net/mvneta.c
@@ -34,14 +34,6 @@ DECLARE_GLOBAL_DATA_PTR;
# error Marvell mvneta requires PHYLIB
#endif
-/* Some linux -> U-Boot compatibility stuff */
-#define netdev_err(dev, fmt, args...) \
- printf(fmt, ##args)
-#define netdev_warn(dev, fmt, args...) \
- printf(fmt, ##args)
-#define netdev_info(dev, fmt, args...) \
- printf(fmt, ##args)
-
#define CONFIG_NR_CPUS 1
#define ETH_HLEN 14 /* Total octets in header */
diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c
index 62c0c2be06..f34245ba77 100644
--- a/drivers/net/mvpp2.c
+++ b/drivers/net/mvpp2.c
@@ -35,18 +35,6 @@
DECLARE_GLOBAL_DATA_PTR;
-/* Some linux -> U-Boot compatibility stuff */
-#define netdev_err(dev, fmt, args...) \
- printf(fmt, ##args)
-#define netdev_warn(dev, fmt, args...) \
- printf(fmt, ##args)
-#define netdev_info(dev, fmt, args...) \
- printf(fmt, ##args)
-#define netdev_dbg(dev, fmt, args...) \
- printf(fmt, ##args)
-
-#define ETH_ALEN 6 /* Octets in one ethernet addr */
-
#define __verify_pcpu_ptr(ptr) \
do { \
const void __percpu *__vpp_verify = (typeof((ptr) + 0))NULL; \
@@ -68,7 +56,6 @@ do { \
#define NET_SKB_PAD max(32, MVPP2_CPU_D_CACHE_LINE_SIZE)
#define CONFIG_NR_CPUS 1
-#define ETH_HLEN ETHER_HDR_SIZE /* Total octets in header */
/* 2(HW hdr) 14(MAC hdr) 4(CRC) 32(extra for cache prefetch) */
#define WRAP (2 + ETH_HLEN + 4 + 32)
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 0ed9bb5765..86f689802e 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -61,7 +61,6 @@
#define EEPROM_SIZE 0xb /*12 16-bit chunks, or 24 bytes*/
#define DSIZE 0x00000FFF
-#define ETH_ALEN 6
#define CRC_SIZE 4
#define TOUT_LOOP 500000
#define TX_BUF_SIZE 1536
diff --git a/drivers/net/ns8382x.c b/drivers/net/ns8382x.c
index f941c15b27..ea7ece54b6 100644
--- a/drivers/net/ns8382x.c
+++ b/drivers/net/ns8382x.c
@@ -59,7 +59,6 @@
/* defines */
#define DSIZE 0x00000FFF
-#define ETH_ALEN 6
#define CRC_SIZE 4
#define TOUT_LOOP 500000
#define TX_BUF_SIZE 1536
diff --git a/drivers/net/pch_gbe.c b/drivers/net/pch_gbe.c
index d31c45f3b6..2286dd07e9 100644
--- a/drivers/net/pch_gbe.c
+++ b/drivers/net/pch_gbe.c
@@ -429,7 +429,7 @@ static int pch_gbe_phy_init(struct udevice *dev)
return 0;
}
-int pch_gbe_probe(struct udevice *dev)
+static int pch_gbe_probe(struct udevice *dev)
{
struct pch_gbe_priv *priv;
struct eth_pdata *plat = dev_get_platdata(dev);
@@ -464,7 +464,7 @@ int pch_gbe_probe(struct udevice *dev)
return pch_gbe_phy_init(dev);
}
-int pch_gbe_remove(struct udevice *dev)
+static int pch_gbe_remove(struct udevice *dev)
{
struct pch_gbe_priv *priv = dev_get_priv(dev);
diff --git a/drivers/net/phy/ti.c b/drivers/net/phy/ti.c
index f870e6d662..6db6edd0d0 100644
--- a/drivers/net/phy/ti.c
+++ b/drivers/net/phy/ti.c
@@ -24,6 +24,7 @@
/* Extended Registers */
#define DP83867_CFG4 0x0031
#define DP83867_RGMIICTL 0x0032
+#define DP83867_STRAP_STS1 0x006E
#define DP83867_RGMIIDCTL 0x0086
#define DP83867_IO_MUX_CFG 0x0170
@@ -48,8 +49,12 @@
#define DP83867_RGMII_TX_CLK_DELAY_EN BIT(1)
#define DP83867_RGMII_RX_CLK_DELAY_EN BIT(0)
+/* STRAP_STS1 bits */
+#define DP83867_STRAP_STS1_RESERVED BIT(11)
+
/* PHY CTRL bits */
#define DP83867_PHYCR_FIFO_DEPTH_SHIFT 14
+#define DP83867_PHYCR_RESERVED_MASK BIT(11)
#define DP83867_MDI_CROSSOVER 5
#define DP83867_MDI_CROSSOVER_AUTO 2
#define DP83867_MDI_CROSSOVER_MDIX 2
@@ -88,6 +93,18 @@
#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX 0x0
#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN 0x1f
+#define DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT 8
+#define DP83867_IO_MUX_CFG_CLK_O_SEL_MASK \
+ GENMASK(0x1f, DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT)
+
+/* CFG4 bits */
+#define DP83867_CFG4_PORT_MIRROR_EN BIT(0)
+
+enum {
+ DP83867_PORT_MIRRORING_KEEP,
+ DP83867_PORT_MIRRORING_EN,
+ DP83867_PORT_MIRRORING_DIS,
+};
struct dp83867_private {
int rx_id_delay;
@@ -95,6 +112,8 @@ struct dp83867_private {
int fifo_depth;
int io_impedance;
bool rxctrl_strap_quirk;
+ int port_mirroring;
+ int clk_output_sel;
};
/**
@@ -163,6 +182,26 @@ void phy_write_mmd_indirect(struct phy_device *phydev, int prtad,
phy_write(phydev, addr, MII_MMD_DATA, data);
}
+static int dp83867_config_port_mirroring(struct phy_device *phydev)
+{
+ struct dp83867_private *dp83867 =
+ (struct dp83867_private *)phydev->priv;
+ u16 val;
+
+ val = phy_read_mmd_indirect(phydev, DP83867_CFG4, DP83867_DEVADDR,
+ phydev->addr);
+
+ if (dp83867->port_mirroring == DP83867_PORT_MIRRORING_EN)
+ val |= DP83867_CFG4_PORT_MIRROR_EN;
+ else
+ val &= ~DP83867_CFG4_PORT_MIRROR_EN;
+
+ phy_write_mmd_indirect(phydev, DP83867_CFG4, DP83867_DEVADDR,
+ phydev->addr, val);
+
+ return 0;
+}
+
#if defined(CONFIG_DM_ETH)
/**
* dp83867_data_init - Convenience function for setting PHY specific data
@@ -173,6 +212,18 @@ static int dp83867_of_init(struct phy_device *phydev)
{
struct dp83867_private *dp83867 = phydev->priv;
ofnode node;
+ u16 val;
+
+ /* Optional configuration */
+
+ /*
+ * Keep the default value if ti,clk-output-sel is not set
+ * or to high
+ */
+
+ dp83867->clk_output_sel =
+ ofnode_read_u32_default(node, "ti,clk-output-sel",
+ DP83867_CLK_O_SEL_REF_CLK);
node = phy_get_ofnode(phydev);
if (!ofnode_valid(node))
@@ -197,6 +248,23 @@ static int dp83867_of_init(struct phy_device *phydev)
dp83867->fifo_depth = ofnode_read_u32_default(node, "ti,fifo-depth",
-1);
+ if (ofnode_read_bool(node, "enet-phy-lane-swap"))
+ dp83867->port_mirroring = DP83867_PORT_MIRRORING_EN;
+
+ if (ofnode_read_bool(node, "enet-phy-lane-no-swap"))
+ dp83867->port_mirroring = DP83867_PORT_MIRRORING_DIS;
+
+
+ /* Clock output selection if muxing property is set */
+ if (dp83867->clk_output_sel != DP83867_CLK_O_SEL_REF_CLK) {
+ val = phy_read_mmd_indirect(phydev, DP83867_IO_MUX_CFG,
+ DP83867_DEVADDR, phydev->addr);
+ val &= ~DP83867_IO_MUX_CFG_CLK_O_SEL_MASK;
+ val |= (dp83867->clk_output_sel <<
+ DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT);
+ phy_write_mmd_indirect(phydev, DP83867_IO_MUX_CFG,
+ DP83867_DEVADDR, phydev->addr, val);
+ }
return 0;
}
@@ -218,7 +286,7 @@ static int dp83867_config(struct phy_device *phydev)
{
struct dp83867_private *dp83867;
unsigned int val, delay, cfg2;
- int ret;
+ int ret, bs;
if (!phydev->priv) {
dp83867 = kzalloc(sizeof(*dp83867), GFP_KERNEL);
@@ -253,6 +321,26 @@ static int dp83867_config(struct phy_device *phydev)
(dp83867->fifo_depth << DP83867_PHYCR_FIFO_DEPTH_SHIFT));
if (ret)
goto err_out;
+
+ /* The code below checks if "port mirroring" N/A MODE4 has been
+ * enabled during power on bootstrap.
+ *
+ * Such N/A mode enabled by mistake can put PHY IC in some
+ * internal testing mode and disable RGMII transmission.
+ *
+ * In this particular case one needs to check STRAP_STS1
+ * register's bit 11 (marked as RESERVED).
+ */
+
+ bs = phy_read_mmd_indirect(phydev, DP83867_STRAP_STS1,
+ DP83867_DEVADDR, phydev->addr);
+ val = phy_read(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL);
+ if (bs & DP83867_STRAP_STS1_RESERVED) {
+ val &= ~DP83867_PHYCR_RESERVED_MASK;
+ phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL,
+ val);
+ }
+
} else if (phy_interface_is_sgmii(phydev)) {
phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR,
(BMCR_ANENABLE | BMCR_FULLDPLX | BMCR_SPEED1000));
@@ -315,6 +403,9 @@ static int dp83867_config(struct phy_device *phydev)
}
}
+ if (dp83867->port_mirroring != DP83867_PORT_MIRRORING_KEEP)
+ dp83867_config_port_mirroring(phydev);
+
genphy_config_aneg(phydev);
return 0;
diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c
index ea523435f0..590f8ce154 100644
--- a/drivers/net/rtl8139.c
+++ b/drivers/net/rtl8139.c
@@ -80,10 +80,6 @@
#define RTL_TIMEOUT 100000
-#define ETH_FRAME_LEN 1514
-#define ETH_ALEN 6
-#define ETH_ZLEN 60
-
/* PCI Tuning Parameters
Threshold is bytes transferred to chip before transmission starts. */
#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */
diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c
index e0e3a6d570..a78f3d233f 100644
--- a/drivers/net/rtl8169.c
+++ b/drivers/net/rtl8169.c
@@ -102,10 +102,6 @@ static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
#define RTL_R16(reg) readw(ioaddr + (reg))
#define RTL_R32(reg) readl(ioaddr + (reg))
-#define ETH_FRAME_LEN MAX_ETH_FRAME_SIZE
-#define ETH_ALEN MAC_ADDR_LEN
-#define ETH_ZLEN 60
-
#define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)(unsigned long)dev->priv, \
(pci_addr_t)(unsigned long)a)
#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)(unsigned long)dev->priv, \
diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
index b71c8f88d9..decce2fa59 100644
--- a/drivers/net/sandbox.c
+++ b/drivers/net/sandbox.c
@@ -10,26 +10,11 @@
#include <dm.h>
#include <malloc.h>
#include <net.h>
+#include <asm/eth.h>
#include <asm/test.h>
DECLARE_GLOBAL_DATA_PTR;
-/**
- * struct eth_sandbox_priv - memory for sandbox mock driver
- *
- * fake_host_hwaddr: MAC address of mocked machine
- * fake_host_ipaddr: IP address of mocked machine
- * recv_packet_buffer: buffer of the packet returned as received
- * recv_packet_length: length of the packet returned as received
- */
-struct eth_sandbox_priv {
- uchar fake_host_hwaddr[ARP_HLEN];
- struct in_addr fake_host_ipaddr;
- uchar *recv_packet_buffer;
- int recv_packet_length;
-};
-
-static bool disabled[8] = {false};
static bool skip_timeout;
/*
@@ -40,7 +25,16 @@ static bool skip_timeout;
*/
void sandbox_eth_disable_response(int index, bool disable)
{
- disabled[index] = disable;
+ struct udevice *dev;
+ struct eth_sandbox_priv *priv;
+ int ret;
+
+ ret = uclass_get_device(UCLASS_ETH, index, &dev);
+ if (ret)
+ return;
+
+ priv = dev_get_priv(dev);
+ priv->disabled = disable;
}
/*
@@ -53,103 +47,304 @@ void sandbox_eth_skip_timeout(void)
skip_timeout = true;
}
-static int sb_eth_start(struct udevice *dev)
+/*
+ * sandbox_eth_arp_req_to_reply()
+ *
+ * Check for an arp request to be sent. If so, inject a reply
+ *
+ * returns 0 if injected, -EAGAIN if not
+ */
+int sandbox_eth_arp_req_to_reply(struct udevice *dev, void *packet,
+ unsigned int len)
{
struct eth_sandbox_priv *priv = dev_get_priv(dev);
+ struct ethernet_hdr *eth = packet;
+ struct arp_hdr *arp;
+ struct ethernet_hdr *eth_recv;
+ struct arp_hdr *arp_recv;
- debug("eth_sandbox: Start\n");
+ if (ntohs(eth->et_protlen) != PROT_ARP)
+ return -EAGAIN;
- priv->recv_packet_buffer = net_rx_packets[0];
+ arp = packet + ETHER_HDR_SIZE;
+
+ if (ntohs(arp->ar_op) != ARPOP_REQUEST)
+ return -EAGAIN;
+
+ /* Don't allow the buffer to overrun */
+ if (priv->recv_packets >= PKTBUFSRX)
+ return 0;
+
+ /* store this as the assumed IP of the fake host */
+ priv->fake_host_ipaddr = net_read_ip(&arp->ar_tpa);
+
+ /* Formulate a fake response */
+ eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets];
+ memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN);
+ memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN);
+ eth_recv->et_protlen = htons(PROT_ARP);
+
+ arp_recv = (void *)eth_recv + ETHER_HDR_SIZE;
+ arp_recv->ar_hrd = htons(ARP_ETHER);
+ arp_recv->ar_pro = htons(PROT_IP);
+ arp_recv->ar_hln = ARP_HLEN;
+ arp_recv->ar_pln = ARP_PLEN;
+ arp_recv->ar_op = htons(ARPOP_REPLY);
+ memcpy(&arp_recv->ar_sha, priv->fake_host_hwaddr, ARP_HLEN);
+ net_write_ip(&arp_recv->ar_spa, priv->fake_host_ipaddr);
+ memcpy(&arp_recv->ar_tha, &arp->ar_sha, ARP_HLEN);
+ net_copy_ip(&arp_recv->ar_tpa, &arp->ar_spa);
+
+ priv->recv_packet_length[priv->recv_packets] =
+ ETHER_HDR_SIZE + ARP_HDR_SIZE;
+ ++priv->recv_packets;
return 0;
}
-static int sb_eth_send(struct udevice *dev, void *packet, int length)
+/*
+ * sandbox_eth_ping_req_to_reply()
+ *
+ * Check for a ping request to be sent. If so, inject a reply
+ *
+ * returns 0 if injected, -EAGAIN if not
+ */
+int sandbox_eth_ping_req_to_reply(struct udevice *dev, void *packet,
+ unsigned int len)
{
struct eth_sandbox_priv *priv = dev_get_priv(dev);
struct ethernet_hdr *eth = packet;
+ struct ip_udp_hdr *ip;
+ struct icmp_hdr *icmp;
+ struct ethernet_hdr *eth_recv;
+ struct ip_udp_hdr *ipr;
+ struct icmp_hdr *icmpr;
- debug("eth_sandbox: Send packet %d\n", length);
+ if (ntohs(eth->et_protlen) != PROT_IP)
+ return -EAGAIN;
+
+ ip = packet + ETHER_HDR_SIZE;
+
+ if (ip->ip_p != IPPROTO_ICMP)
+ return -EAGAIN;
+
+ icmp = (struct icmp_hdr *)&ip->udp_src;
+
+ if (icmp->type != ICMP_ECHO_REQUEST)
+ return -EAGAIN;
+
+ /* Don't allow the buffer to overrun */
+ if (priv->recv_packets >= PKTBUFSRX)
+ return 0;
+
+ /* reply to the ping */
+ eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets];
+ memcpy(eth_recv, packet, len);
+ ipr = (void *)eth_recv + ETHER_HDR_SIZE;
+ icmpr = (struct icmp_hdr *)&ipr->udp_src;
+ memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN);
+ memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN);
+ ipr->ip_sum = 0;
+ ipr->ip_off = 0;
+ net_copy_ip((void *)&ipr->ip_dst, &ip->ip_src);
+ net_write_ip((void *)&ipr->ip_src, priv->fake_host_ipaddr);
+ ipr->ip_sum = compute_ip_checksum(ipr, IP_HDR_SIZE);
+
+ icmpr->type = ICMP_ECHO_REPLY;
+ icmpr->checksum = 0;
+ icmpr->checksum = compute_ip_checksum(icmpr, ICMP_HDR_SIZE);
+
+ priv->recv_packet_length[priv->recv_packets] = len;
+ ++priv->recv_packets;
+
+ return 0;
+}
+
+/*
+ * sandbox_eth_recv_arp_req()
+ *
+ * Inject an ARP request for this target
+ *
+ * returns 0 if injected, -EOVERFLOW if not
+ */
+int sandbox_eth_recv_arp_req(struct udevice *dev)
+{
+ struct eth_sandbox_priv *priv = dev_get_priv(dev);
+ struct ethernet_hdr *eth_recv;
+ struct arp_hdr *arp_recv;
+
+ /* Don't allow the buffer to overrun */
+ if (priv->recv_packets >= PKTBUFSRX)
+ return -EOVERFLOW;
+
+ /* Formulate a fake request */
+ eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets];
+ memcpy(eth_recv->et_dest, net_bcast_ethaddr, ARP_HLEN);
+ memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN);
+ eth_recv->et_protlen = htons(PROT_ARP);
+
+ arp_recv = (void *)eth_recv + ETHER_HDR_SIZE;
+ arp_recv->ar_hrd = htons(ARP_ETHER);
+ arp_recv->ar_pro = htons(PROT_IP);
+ arp_recv->ar_hln = ARP_HLEN;
+ arp_recv->ar_pln = ARP_PLEN;
+ arp_recv->ar_op = htons(ARPOP_REQUEST);
+ memcpy(&arp_recv->ar_sha, priv->fake_host_hwaddr, ARP_HLEN);
+ net_write_ip(&arp_recv->ar_spa, priv->fake_host_ipaddr);
+ memcpy(&arp_recv->ar_tha, net_null_ethaddr, ARP_HLEN);
+ net_write_ip(&arp_recv->ar_tpa, net_ip);
+
+ priv->recv_packet_length[priv->recv_packets] =
+ ETHER_HDR_SIZE + ARP_HDR_SIZE;
+ ++priv->recv_packets;
+
+ return 0;
+}
+
+/*
+ * sandbox_eth_recv_ping_req()
+ *
+ * Inject a ping request for this target
+ *
+ * returns 0 if injected, -EOVERFLOW if not
+ */
+int sandbox_eth_recv_ping_req(struct udevice *dev)
+{
+ struct eth_sandbox_priv *priv = dev_get_priv(dev);
+ struct ethernet_hdr *eth_recv;
+ struct ip_udp_hdr *ipr;
+ struct icmp_hdr *icmpr;
+
+ /* Don't allow the buffer to overrun */
+ if (priv->recv_packets >= PKTBUFSRX)
+ return -EOVERFLOW;
+
+ /* Formulate a fake ping */
+ eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets];
+
+ memcpy(eth_recv->et_dest, net_ethaddr, ARP_HLEN);
+ memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN);
+ eth_recv->et_protlen = htons(PROT_IP);
+
+ ipr = (void *)eth_recv + ETHER_HDR_SIZE;
+ ipr->ip_hl_v = 0x45;
+ ipr->ip_len = htons(IP_ICMP_HDR_SIZE);
+ ipr->ip_off = htons(IP_FLAGS_DFRAG);
+ ipr->ip_p = IPPROTO_ICMP;
+ ipr->ip_sum = 0;
+ net_write_ip(&ipr->ip_src, priv->fake_host_ipaddr);
+ net_write_ip(&ipr->ip_dst, net_ip);
+ ipr->ip_sum = compute_ip_checksum(ipr, IP_HDR_SIZE);
+
+ icmpr = (struct icmp_hdr *)&ipr->udp_src;
+
+ icmpr->type = ICMP_ECHO_REQUEST;
+ icmpr->code = 0;
+ icmpr->checksum = 0;
+ icmpr->un.echo.id = 0;
+ icmpr->un.echo.sequence = htons(1);
+ icmpr->checksum = compute_ip_checksum(icmpr, ICMP_HDR_SIZE);
+
+ priv->recv_packet_length[priv->recv_packets] =
+ ETHER_HDR_SIZE + IP_ICMP_HDR_SIZE;
+ ++priv->recv_packets;
+
+ return 0;
+}
- if (dev->seq >= 0 && dev->seq < ARRAY_SIZE(disabled) &&
- disabled[dev->seq])
+/*
+ * sb_default_handler()
+ *
+ * perform typical responses to simple ping
+ *
+ * dev - device pointer
+ * pkt - "sent" packet buffer
+ * len - length of packet
+ */
+static int sb_default_handler(struct udevice *dev, void *packet,
+ unsigned int len)
+{
+ if (!sandbox_eth_arp_req_to_reply(dev, packet, len))
+ return 0;
+ if (!sandbox_eth_ping_req_to_reply(dev, packet, len))
return 0;
- if (ntohs(eth->et_protlen) == PROT_ARP) {
- struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
-
- if (ntohs(arp->ar_op) == ARPOP_REQUEST) {
- struct ethernet_hdr *eth_recv;
- struct arp_hdr *arp_recv;
-
- /* store this as the assumed IP of the fake host */
- priv->fake_host_ipaddr = net_read_ip(&arp->ar_tpa);
- /* Formulate a fake response */
- eth_recv = (void *)priv->recv_packet_buffer;
- memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN);
- memcpy(eth_recv->et_src, priv->fake_host_hwaddr,
- ARP_HLEN);
- eth_recv->et_protlen = htons(PROT_ARP);
-
- arp_recv = (void *)priv->recv_packet_buffer +
- ETHER_HDR_SIZE;
- arp_recv->ar_hrd = htons(ARP_ETHER);
- arp_recv->ar_pro = htons(PROT_IP);
- arp_recv->ar_hln = ARP_HLEN;
- arp_recv->ar_pln = ARP_PLEN;
- arp_recv->ar_op = htons(ARPOP_REPLY);
- memcpy(&arp_recv->ar_sha, priv->fake_host_hwaddr,
- ARP_HLEN);
- net_write_ip(&arp_recv->ar_spa, priv->fake_host_ipaddr);
- memcpy(&arp_recv->ar_tha, &arp->ar_sha, ARP_HLEN);
- net_copy_ip(&arp_recv->ar_tpa, &arp->ar_spa);
-
- priv->recv_packet_length = ETHER_HDR_SIZE +
- ARP_HDR_SIZE;
- }
- } else if (ntohs(eth->et_protlen) == PROT_IP) {
- struct ip_udp_hdr *ip = packet + ETHER_HDR_SIZE;
-
- if (ip->ip_p == IPPROTO_ICMP) {
- struct icmp_hdr *icmp = (struct icmp_hdr *)&ip->udp_src;
-
- if (icmp->type == ICMP_ECHO_REQUEST) {
- struct ethernet_hdr *eth_recv;
- struct ip_udp_hdr *ipr;
- struct icmp_hdr *icmpr;
-
- /* reply to the ping */
- memcpy(priv->recv_packet_buffer, packet,
- length);
- eth_recv = (void *)priv->recv_packet_buffer;
- ipr = (void *)priv->recv_packet_buffer +
- ETHER_HDR_SIZE;
- icmpr = (struct icmp_hdr *)&ipr->udp_src;
- memcpy(eth_recv->et_dest, eth->et_src,
- ARP_HLEN);
- memcpy(eth_recv->et_src, priv->fake_host_hwaddr,
- ARP_HLEN);
- ipr->ip_sum = 0;
- ipr->ip_off = 0;
- net_copy_ip((void *)&ipr->ip_dst, &ip->ip_src);
- net_write_ip((void *)&ipr->ip_src,
- priv->fake_host_ipaddr);
- ipr->ip_sum = compute_ip_checksum(ipr,
- IP_HDR_SIZE);
-
- icmpr->type = ICMP_ECHO_REPLY;
- icmpr->checksum = 0;
- icmpr->checksum = compute_ip_checksum(icmpr,
- ICMP_HDR_SIZE);
-
- priv->recv_packet_length = length;
- }
- }
+ return 0;
+}
+
+/*
+ * sandbox_eth_set_tx_handler()
+ *
+ * Set a custom response to a packet being sent through the sandbox eth test
+ * driver
+ *
+ * index - interface to set the handler for
+ * handler - The func ptr to call on send. If NULL, set to default handler
+ */
+void sandbox_eth_set_tx_handler(int index, sandbox_eth_tx_hand_f *handler)
+{
+ struct udevice *dev;
+ struct eth_sandbox_priv *priv;
+ int ret;
+
+ ret = uclass_get_device(UCLASS_ETH, index, &dev);
+ if (ret)
+ return;
+
+ priv = dev_get_priv(dev);
+ if (handler)
+ priv->tx_handler = handler;
+ else
+ priv->tx_handler = sb_default_handler;
+}
+
+/*
+ * Set priv ptr
+ *
+ * priv - priv void ptr to store in the device
+ */
+void sandbox_eth_set_priv(int index, void *priv)
+{
+ struct udevice *dev;
+ struct eth_sandbox_priv *dev_priv;
+ int ret;
+
+ ret = uclass_get_device(UCLASS_ETH, index, &dev);
+ if (ret)
+ return;
+
+ dev_priv = dev_get_priv(dev);
+
+ dev_priv->priv = priv;
+}
+
+static int sb_eth_start(struct udevice *dev)
+{
+ struct eth_sandbox_priv *priv = dev_get_priv(dev);
+
+ debug("eth_sandbox: Start\n");
+
+ priv->recv_packets = 0;
+ for (int i = 0; i < PKTBUFSRX; i++) {
+ priv->recv_packet_buffer[i] = net_rx_packets[i];
+ priv->recv_packet_length[i] = 0;
}
return 0;
}
+static int sb_eth_send(struct udevice *dev, void *packet, int length)
+{
+ struct eth_sandbox_priv *priv = dev_get_priv(dev);
+
+ debug("eth_sandbox: Send packet %d\n", length);
+
+ if (priv->disabled)
+ return 0;
+
+ return priv->tx_handler(dev, packet, length);
+}
+
static int sb_eth_recv(struct udevice *dev, int flags, uchar **packetp)
{
struct eth_sandbox_priv *priv = dev_get_priv(dev);
@@ -159,18 +354,37 @@ static int sb_eth_recv(struct udevice *dev, int flags, uchar **packetp)
skip_timeout = false;
}
- if (priv->recv_packet_length) {
- int lcl_recv_packet_length = priv->recv_packet_length;
+ if (priv->recv_packets) {
+ int lcl_recv_packet_length = priv->recv_packet_length[0];
- debug("eth_sandbox: received packet %d\n",
- priv->recv_packet_length);
- priv->recv_packet_length = 0;
- *packetp = priv->recv_packet_buffer;
+ debug("eth_sandbox: received packet[%d], %d waiting\n",
+ lcl_recv_packet_length, priv->recv_packets - 1);
+ *packetp = priv->recv_packet_buffer[0];
return lcl_recv_packet_length;
}
return 0;
}
+static int sb_eth_free_pkt(struct udevice *dev, uchar *packet, int length)
+{
+ struct eth_sandbox_priv *priv = dev_get_priv(dev);
+ int i;
+
+ if (!priv->recv_packets)
+ return 0;
+
+ --priv->recv_packets;
+ for (i = 0; i < priv->recv_packets; i++) {
+ priv->recv_packet_length[i] = priv->recv_packet_length[i + 1];
+ memcpy(priv->recv_packet_buffer[i],
+ priv->recv_packet_buffer[i + 1],
+ priv->recv_packet_length[i + 1]);
+ }
+ priv->recv_packet_length[priv->recv_packets] = 0;
+
+ return 0;
+}
+
static void sb_eth_stop(struct udevice *dev)
{
debug("eth_sandbox: Stop\n");
@@ -189,6 +403,7 @@ static const struct eth_ops sb_eth_ops = {
.start = sb_eth_start,
.send = sb_eth_send,
.recv = sb_eth_recv,
+ .free_pkt = sb_eth_free_pkt,
.stop = sb_eth_stop,
.write_hwaddr = sb_eth_write_hwaddr,
};
@@ -212,6 +427,8 @@ static int sb_eth_ofdata_to_platdata(struct udevice *dev)
return -EINVAL;
}
memcpy(priv->fake_host_hwaddr, mac, ARP_HLEN);
+ priv->disabled = false;
+ priv->tx_handler = sb_default_handler;
return 0;
}
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
index e22d048e8f..bc33126536 100644
--- a/drivers/net/zynq_gem.c
+++ b/drivers/net/zynq_gem.c
@@ -461,6 +461,7 @@ static int zynq_gem_init(struct udevice *dev)
break;
}
+#if !defined(CONFIG_ARCH_VERSAL)
ret = clk_set_rate(&priv->clk, clk_rate);
if (IS_ERR_VALUE(ret) && ret != (unsigned long)-ENOSYS) {
dev_err(dev, "failed to set tx clock rate\n");
@@ -472,6 +473,9 @@ static int zynq_gem_init(struct udevice *dev)
dev_err(dev, "failed to enable tx clock\n");
return ret;
}
+#else
+ debug("requested clk_rate %ld\n", clk_rate);
+#endif
setbits_le32(&regs->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK |
ZYNQ_GEM_NWCTRL_TXEN_MASK);
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index eb118f3496..da49c96ed5 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -90,6 +90,27 @@ int pci_get_ff(enum pci_size_t size)
}
}
+static void pci_dev_find_ofnode(struct udevice *bus, phys_addr_t bdf,
+ ofnode *rnode)
+{
+ struct fdt_pci_addr addr;
+ ofnode node;
+ int ret;
+
+ dev_for_each_subnode(node, bus) {
+ ret = ofnode_read_pci_addr(node, FDT_PCI_SPACE_CONFIG, "reg",
+ &addr);
+ if (ret)
+ continue;
+
+ if (PCI_MASK_BUS(addr.phys_hi) != PCI_MASK_BUS(bdf))
+ continue;
+
+ *rnode = node;
+ break;
+ }
+};
+
int pci_bus_find_devfn(struct udevice *bus, pci_dev_t find_devfn,
struct udevice **devp)
{
@@ -641,6 +662,7 @@ static int pci_find_and_bind_driver(struct udevice *parent,
pci_dev_t bdf, struct udevice **devp)
{
struct pci_driver_entry *start, *entry;
+ ofnode node = ofnode_null();
const char *drv;
int n_ents;
int ret;
@@ -651,6 +673,10 @@ static int pci_find_and_bind_driver(struct udevice *parent,
debug("%s: Searching for driver: vendor=%x, device=%x\n", __func__,
find_id->vendor, find_id->device);
+
+ /* Determine optional OF node */
+ pci_dev_find_ofnode(parent, bdf, &node);
+
start = ll_entry_start(struct pci_driver_entry, pci_driver_entry);
n_ents = ll_entry_count(struct pci_driver_entry, pci_driver_entry);
for (entry = start; entry != start + n_ents; entry++) {
@@ -684,8 +710,8 @@ static int pci_find_and_bind_driver(struct udevice *parent,
* find another driver. For now this doesn't seem
* necesssary, so just bind the first match.
*/
- ret = device_bind(parent, drv, drv->name, NULL, -1,
- &dev);
+ ret = device_bind_ofnode(parent, drv, drv->name, NULL,
+ node, &dev);
if (ret)
goto error;
debug("%s: Match found: %s\n", __func__, drv->name);
@@ -712,7 +738,7 @@ static int pci_find_and_bind_driver(struct udevice *parent,
return -ENOMEM;
drv = bridge ? "pci_bridge_drv" : "pci_generic_drv";
- ret = device_bind_driver(parent, drv, str, devp);
+ ret = device_bind_driver_to_node(parent, drv, str, node, devp);
if (ret) {
debug("%s: Failed to bind generic driver: %d\n", __func__, ret);
free(str);
diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c
index 29113f7958..eaacd4066e 100644
--- a/drivers/pci/pci_rom.c
+++ b/drivers/pci/pci_rom.c
@@ -247,7 +247,7 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void),
}
if (!board_should_load_oprom(dev))
- return -ENXIO;
+ return log_msg_ret("Should not load OPROM", -ENXIO);
ret = pci_rom_probe(dev, &rom);
if (ret)
@@ -328,7 +328,7 @@ int vbe_setup_video_priv(struct vesa_mode_info *vesa,
struct video_uc_platdata *plat)
{
if (!vesa->x_resolution)
- return -ENXIO;
+ return log_msg_ret("No x resolution", -ENXIO);
uc_priv->xsize = vesa->x_resolution;
uc_priv->ysize = vesa->y_resolution;
switch (vesa->bits_per_pixel) {
diff --git a/drivers/pwm/sandbox_pwm.c b/drivers/pwm/sandbox_pwm.c
index 4b50b19c61..28988187e0 100644
--- a/drivers/pwm/sandbox_pwm.c
+++ b/drivers/pwm/sandbox_pwm.c
@@ -14,6 +14,14 @@ enum {
NUM_CHANNELS = 3,
};
+/**
+ * struct sandbox_pwm_chan - a sandbox PWM channel
+ *
+ * @period_ns: Period of the PWM in nanoseconds
+ * @duty_ns: Current duty cycle of the PWM in nanoseconds
+ * @enable: true if the PWM is enabled
+ * @polarity: true if the PWM polarity is active high
+ */
struct sandbox_pwm_chan {
uint period_ns;
uint duty_ns;
@@ -25,6 +33,23 @@ struct sandbox_pwm_priv {
struct sandbox_pwm_chan chan[NUM_CHANNELS];
};
+int sandbox_pwm_get_config(struct udevice *dev, uint channel, uint *period_nsp,
+ uint *duty_nsp, bool *enablep, bool *polarityp)
+{
+ struct sandbox_pwm_priv *priv = dev_get_priv(dev);
+ struct sandbox_pwm_chan *chan;
+
+ if (channel >= NUM_CHANNELS)
+ return -ENOSPC;
+ chan = &priv->chan[channel];
+ *period_nsp = chan->period_ns;
+ *duty_nsp = chan->duty_ns;
+ *enablep = chan->enable;
+ *polarityp = chan->polarity;
+
+ return 0;
+}
+
static int sandbox_pwm_set_config(struct udevice *dev, uint channel,
uint period_ns, uint duty_ns)
{
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 54365092ec..bcc01b135e 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -13,6 +13,24 @@ config DM_RTC
drivers to perform the actual functions. See rtc.h for a
description of the API.
+config SPL_DM_RTC
+ bool "Enable Driver Model for RTC drivers in SPL"
+ depends on SPL_DM
+ help
+ Enable drver model for real-time-clock drivers. The RTC uclass
+ then provides the rtc_get()/rtc_set() interface, delegating to
+ drivers to perform the actual functions. See rtc.h for a
+ description of the API.
+
+config TPL_DM_RTC
+ bool "Enable Driver Model for RTC drivers in TPL"
+ depends on TPL_DM
+ help
+ Enable drver model for real-time-clock drivers. The RTC uclass
+ then provides the rtc_get()/rtc_set() interface, delegating to
+ drivers to perform the actual functions. See rtc.h for a
+ description of the API.
+
config RTC_PCF2127
bool "Enable PCF2127 driver"
depends on DM_RTC
@@ -68,4 +86,12 @@ config RTC_S35392A
help
Enable s35392a driver which provides rtc get and set function.
+config RTC_MC146818
+ bool "Enable MC146818 driver"
+ help
+ This is a widely used real-time clock chip originally by Motorola
+ and now available from NXP. It includes a battery-backed real-time
+ clock with a wide array of features and 50 bytes of general-purpose,
+ battery-backed RAM. The driver supports access to the clock and RAM.
+
endmenu
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 513e3ffc07..1724602f1c 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -4,7 +4,7 @@
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#ccflags-y += -DDEBUG
-obj-$(CONFIG_DM_RTC) += rtc-uclass.o
+obj-$(CONFIG_$(SPL_TPL_)DM_RTC) += rtc-uclass.o
obj-$(CONFIG_RTC_AT91SAM9_RTT) += at91sam9_rtt.o
obj-y += date.o
diff --git a/drivers/rtc/isl1208.c b/drivers/rtc/isl1208.c
index 22ac0d2b08..59a60b75b3 100644
--- a/drivers/rtc/isl1208.c
+++ b/drivers/rtc/isl1208.c
@@ -52,6 +52,24 @@
#define RTC_STAT_BIT_RTCF 0x01 /* REAL TIME CLOCK FAIL BIT */
/*
+ * Read an RTC register
+ */
+
+static int isl1208_rtc_read8(struct udevice *dev, unsigned int reg)
+{
+ return dm_i2c_reg_read(dev, reg);
+}
+
+/*
+ * Write an RTC register
+ */
+
+static int isl1208_rtc_write8(struct udevice *dev, unsigned int reg, int val)
+{
+ return dm_i2c_reg_write(dev, reg, val);
+}
+
+/*
* Get the current time from the RTC
*/
@@ -161,6 +179,8 @@ static const struct rtc_ops isl1208_rtc_ops = {
.get = isl1208_rtc_get,
.set = isl1208_rtc_set,
.reset = isl1208_rtc_reset,
+ .read8 = isl1208_rtc_read8,
+ .write8 = isl1208_rtc_write8,
};
static const struct udevice_id isl1208_rtc_ids[] = {
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 5fa27254e3..597db4b9cb 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -53,6 +53,16 @@ config SPL_SERIAL_PRESENT
This option enables the full UART in SPL, so if is it disabled,
the full UART driver will be omitted, thus saving space.
+config TPL_SERIAL_PRESENT
+ bool "Provide a serial driver in TPL"
+ depends on DM_SERIAL
+ default y
+ help
+ In very space-constrained devices even the full UART driver is too
+ large. In this case the debug UART can still be used in some cases.
+ This option enables the full UART in TPL, so if is it disabled,
+ the full UART driver will be omitted, thus saving space.
+
# Logic to allow us to use the imply keyword to set what the default port
# should be. The default is otherwise 1.
config CONS_INDEX_0
@@ -324,6 +334,15 @@ config DEBUG_UART_MXC
will need to provide parameters to make this work. The driver will
be available until the real driver model serial is running.
+config DEBUG_UART_SANDBOX
+ bool "sandbox"
+ depends on SANDBOX_SERIAL
+ help
+ Select this to enable the debug UART using the sandbox driver. This
+ provides basic serial output from the console without needing to
+ start up driver model. The driver will be available until the real
+ driver model serial is running.
+
config DEBUG_UART_STM32
bool "STMicroelectronics STM32"
depends on STM32_SERIAL
@@ -354,6 +373,7 @@ endchoice
config DEBUG_UART_BASE
hex "Base address of UART"
depends on DEBUG_UART
+ default 0 if DEBUG_UART_SANDBOX
help
This is the base address of your UART for memory-mapped UARTs.
@@ -363,6 +383,7 @@ config DEBUG_UART_BASE
config DEBUG_UART_CLOCK
int "UART input clock"
depends on DEBUG_UART
+ default 0 if DEBUG_UART_SANDBOX
help
The UART input clock determines the speed of the internal UART
circuitry. The baud rate is derived from this by dividing the input
diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c
index 94b4fdfb17..4a05ea44ce 100644
--- a/drivers/serial/sandbox.c
+++ b/drivers/serial/sandbox.c
@@ -22,6 +22,8 @@
DECLARE_GLOBAL_DATA_PTR;
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+
/*
*
* serial_buf: A buffer that holds keyboard characters for the
@@ -124,7 +126,7 @@ static int sandbox_serial_pending(struct udevice *dev, bool input)
if (next_index == serial_buf_read)
return 1; /* buffer full */
- count = os_read_no_block(0, &serial_buf[serial_buf_write], 1);
+ count = os_read(0, &serial_buf[serial_buf_write], 1);
if (count == 1)
serial_buf_write = next_index;
@@ -142,6 +144,24 @@ static int sandbox_serial_getc(struct udevice *dev)
serial_buf_read = increment_buffer_index(serial_buf_read);
return result;
}
+#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */
+
+#ifdef CONFIG_DEBUG_UART_SANDBOX
+
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ os_putc(ch);
+}
+
+DEBUG_UART_FUNCS
+
+#endif /* CONFIG_DEBUG_UART_SANDBOX */
static int sandbox_serial_setconfig(struct udevice *dev, uint serial_config)
{
@@ -156,6 +176,7 @@ static int sandbox_serial_setconfig(struct udevice *dev, uint serial_config)
return 0;
}
+#if CONFIG_IS_ENABLED(OF_CONTROL)
static const char * const ansi_colour[] = {
"black", "red", "green", "yellow", "blue", "megenta", "cyan",
"white",
@@ -215,3 +236,4 @@ U_BOOT_DEVICE(serial_sandbox_non_fdt) = {
.name = "serial_sandbox",
.platdata = &platdata_non_fdt,
};
+#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index ffdcae0931..e50f0aa851 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -26,6 +26,7 @@ static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE;
#error "Serial is required before relocation - define CONFIG_$(SPL_)SYS_MALLOC_F_LEN to make this work"
#endif
+#if CONFIG_IS_ENABLED(SERIAL_PRESENT)
static int serial_check_stdout(const void *blob, struct udevice **devp)
{
int node;
@@ -150,12 +151,15 @@ static void serial_find_console_or_panic(void)
panic_str("No serial driver found");
#endif
}
+#endif /* CONFIG_SERIAL_PRESENT */
/* Called prior to relocation */
int serial_init(void)
{
+#if CONFIG_IS_ENABLED(SERIAL_PRESENT)
serial_find_console_or_panic();
gd->flags |= GD_FLG_SERIAL_READY;
+#endif
return 0;
}
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 1df6876e9b..516188ea88 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -243,7 +243,7 @@ config XILINX_SPI
config ZYNQ_SPI
bool "Zynq SPI driver"
- depends on ARCH_ZYNQ || ARCH_ZYNQMP
+ depends on ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_VERSAL
help
Enable the Zynq SPI driver. This driver can be used to
access the SPI NOR flash on platforms embedding this Zynq
@@ -260,7 +260,7 @@ config ZYNQ_QSPI
config ZYNQMP_GQSPI
bool "Configure ZynqMP Generic QSPI"
- depends on ARCH_ZYNQMP
+ depends on ARCH_ZYNQMP || ARCH_VERSAL
help
This option is used to enable ZynqMP QSPI controller driver which
is used to communicate with qspi flash devices.
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c
index a822858323..07fa5e3b8a 100644
--- a/drivers/spi/davinci_spi.c
+++ b/drivers/spi/davinci_spi.c
@@ -14,6 +14,7 @@
#include <asm/io.h>
#include <asm/arch/hardware.h>
#include <dm.h>
+#include <dm/platform_data/spi_davinci.h>
/* SPIGCR0 */
#define SPIGCR0_SPIENA_MASK 0x1
@@ -529,50 +530,58 @@ static int davinci_spi_xfer(struct udevice *dev, unsigned int bitlen,
return __davinci_spi_xfer(ds, bitlen, dout, din, flags);
}
+static const struct dm_spi_ops davinci_spi_ops = {
+ .claim_bus = davinci_spi_claim_bus,
+ .release_bus = davinci_spi_release_bus,
+ .xfer = davinci_spi_xfer,
+ .set_speed = davinci_spi_set_speed,
+ .set_mode = davinci_spi_set_mode,
+};
+
static int davinci_spi_probe(struct udevice *bus)
{
- /* Nothing to do */
+ struct davinci_spi_slave *ds = dev_get_priv(bus);
+ struct davinci_spi_platdata *plat = bus->platdata;
+ ds->regs = plat->regs;
+ ds->num_cs = plat->num_cs;
+
return 0;
}
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
static int davinci_ofdata_to_platadata(struct udevice *bus)
{
- struct davinci_spi_slave *ds = dev_get_priv(bus);
- const void *blob = gd->fdt_blob;
- int node = dev_of_offset(bus);
+ struct davinci_spi_platdata *plat = bus->platdata;
+ fdt_addr_t addr;
- ds->regs = devfdt_map_physmem(bus, sizeof(struct davinci_spi_regs));
- if (!ds->regs) {
- printf("%s: could not map device address\n", __func__);
+ addr = devfdt_get_addr(bus);
+ if (addr == FDT_ADDR_T_NONE)
return -EINVAL;
- }
- ds->num_cs = fdtdec_get_int(blob, node, "num-cs", 4);
+
+ plat->regs = (struct davinci_spi_regs *)addr;
+ plat->num_cs = fdtdec_get_int(gd->fdt_blob, dev_of_offset(bus), "num-cs", 4);
return 0;
}
-static const struct dm_spi_ops davinci_spi_ops = {
- .claim_bus = davinci_spi_claim_bus,
- .release_bus = davinci_spi_release_bus,
- .xfer = davinci_spi_xfer,
- .set_speed = davinci_spi_set_speed,
- .set_mode = davinci_spi_set_mode,
-};
-
static const struct udevice_id davinci_spi_ids[] = {
{ .compatible = "ti,keystone-spi" },
{ .compatible = "ti,dm6441-spi" },
{ .compatible = "ti,da830-spi" },
{ }
};
+#endif
U_BOOT_DRIVER(davinci_spi) = {
.name = "davinci_spi",
.id = UCLASS_SPI,
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
.of_match = davinci_spi_ids,
- .ops = &davinci_spi_ops,
.ofdata_to_platdata = davinci_ofdata_to_platadata,
- .priv_auto_alloc_size = sizeof(struct davinci_spi_slave),
+ .platdata_auto_alloc_size = sizeof(struct davinci_spi_platdata),
+#endif
.probe = davinci_spi_probe,
+ .ops = &davinci_spi_ops,
+ .priv_auto_alloc_size = sizeof(struct davinci_spi_slave),
};
#endif
diff --git a/drivers/spi/sandbox_spi.c b/drivers/spi/sandbox_spi.c
index 75ba6a1ed7..906401ec8a 100644
--- a/drivers/spi/sandbox_spi.c
+++ b/drivers/spi/sandbox_spi.c
@@ -8,6 +8,8 @@
* Licensed under the GPL-2 or later.
*/
+#define LOG_CATEGORY UCLASS_SPI
+
#include <common.h>
#include <dm.h>
#include <malloc.h>
@@ -56,7 +58,6 @@ static int sandbox_spi_xfer(struct udevice *slave, unsigned int bitlen,
struct udevice *emul;
uint bytes = bitlen / 8, i;
int ret;
- u8 *tx = (void *)dout, *rx = din;
uint busnum, cs;
if (bitlen == 0)
@@ -87,37 +88,16 @@ static int sandbox_spi_xfer(struct udevice *slave, unsigned int bitlen,
if (ret)
return ret;
- /* make sure rx/tx buffers are full so clients can assume */
- if (!tx) {
- debug("sandbox_spi: xfer: auto-allocating tx scratch buffer\n");
- tx = malloc(bytes);
- if (!tx) {
- debug("sandbox_spi: Out of memory\n");
- return -ENOMEM;
- }
- }
- if (!rx) {
- debug("sandbox_spi: xfer: auto-allocating rx scratch buffer\n");
- rx = malloc(bytes);
- if (!rx) {
- debug("sandbox_spi: Out of memory\n");
- return -ENOMEM;
- }
- }
-
ops = spi_emul_get_ops(emul);
ret = ops->xfer(emul, bitlen, dout, din, flags);
- debug("sandbox_spi: xfer: got back %i (that's %s)\n rx:",
- ret, ret ? "bad" : "good");
- for (i = 0; i < bytes; ++i)
- debug(" %u:%02x", i, rx[i]);
- debug("\n");
-
- if (tx != dout)
- free(tx);
- if (rx != din)
- free(rx);
+ log_content("sandbox_spi: xfer: got back %i (that's %s)\n rx:",
+ ret, ret ? "bad" : "good");
+ if (din) {
+ for (i = 0; i < bytes; ++i)
+ log_content(" %u:%02x", i, ((u8 *)din)[i]);
+ }
+ log_content("\n");
return ret;
}
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index c517d066f6..b84255bd27 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -63,11 +63,11 @@ int dm_spi_claim_bus(struct udevice *dev)
int ret = spi_set_speed_mode(bus, speed, slave->mode);
if (ret)
- return ret;
+ return log_ret(ret);
slave->speed = speed;
}
- return ops->claim_bus ? ops->claim_bus(dev) : 0;
+ return log_ret(ops->claim_bus ? ops->claim_bus(dev) : 0);
}
void dm_spi_release_bus(struct udevice *dev)
@@ -92,7 +92,7 @@ int dm_spi_xfer(struct udevice *dev, unsigned int bitlen,
int spi_claim_bus(struct spi_slave *slave)
{
- return dm_spi_claim_bus(slave->dev);
+ return log_ret(dm_spi_claim_bus(slave->dev));
}
void spi_release_bus(struct spi_slave *slave)
diff --git a/drivers/sysreset/sysreset-uclass.c b/drivers/sysreset/sysreset-uclass.c
index 06ef0ed96c..ad831c703a 100644
--- a/drivers/sysreset/sysreset-uclass.c
+++ b/drivers/sysreset/sysreset-uclass.c
@@ -4,6 +4,8 @@
* Written by Simon Glass <sjg@chromium.org>
*/
+#define LOG_CATEGORY UCLASS_SYSRESET
+
#include <common.h>
#include <sysreset.h>
#include <dm.h>
@@ -34,6 +36,16 @@ int sysreset_get_status(struct udevice *dev, char *buf, int size)
return ops->get_status(dev, buf, size);
}
+int sysreset_get_last(struct udevice *dev)
+{
+ struct sysreset_ops *ops = sysreset_get_ops(dev);
+
+ if (!ops->get_last)
+ return -ENOSYS;
+
+ return ops->get_last(dev);
+}
+
int sysreset_walk(enum sysreset_t type)
{
struct udevice *dev;
@@ -53,6 +65,26 @@ int sysreset_walk(enum sysreset_t type)
return ret;
}
+int sysreset_get_last_walk(void)
+{
+ struct udevice *dev;
+ int value = -ENOENT;
+
+ for (uclass_first_device(UCLASS_SYSRESET, &dev);
+ dev;
+ uclass_next_device(&dev)) {
+ int ret;
+
+ ret = sysreset_get_last(dev);
+ if (ret >= 0) {
+ value = ret;
+ break;
+ }
+ }
+
+ return value;
+}
+
void sysreset_walk_halt(enum sysreset_t type)
{
int ret;
@@ -64,7 +96,7 @@ void sysreset_walk_halt(enum sysreset_t type)
mdelay(100);
/* Still no reset? Give up */
- debug("System reset not supported on this platform\n");
+ log_err("System reset not supported on this platform\n");
hang();
}
diff --git a/drivers/sysreset/sysreset_sandbox.c b/drivers/sysreset/sysreset_sandbox.c
index 75004d9f77..7f6d4186e1 100644
--- a/drivers/sysreset/sysreset_sandbox.c
+++ b/drivers/sysreset/sysreset_sandbox.c
@@ -36,6 +36,11 @@ int sandbox_warm_sysreset_get_status(struct udevice *dev, char *buf, int size)
return 0;
}
+int sandbox_warm_sysreset_get_last(struct udevice *dev)
+{
+ return SYSRESET_WARM;
+}
+
static int sandbox_sysreset_request(struct udevice *dev, enum sysreset_t type)
{
struct sandbox_state *state = state_get_current();
@@ -58,6 +63,9 @@ static int sandbox_sysreset_request(struct udevice *dev, enum sysreset_t type)
return -EACCES;
sandbox_exit();
break;
+ case SYSRESET_POWER_OFF:
+ if (!state->sysreset_allowed[type])
+ return -EACCES;
default:
return -ENOSYS;
}
@@ -74,9 +82,15 @@ int sandbox_sysreset_get_status(struct udevice *dev, char *buf, int size)
return 0;
}
+int sandbox_sysreset_get_last(struct udevice *dev)
+{
+ return SYSRESET_COLD;
+}
+
static struct sysreset_ops sandbox_sysreset_ops = {
.request = sandbox_sysreset_request,
.get_status = sandbox_sysreset_get_status,
+ .get_last = sandbox_sysreset_get_last,
};
static const struct udevice_id sandbox_sysreset_ids[] = {
@@ -94,6 +108,7 @@ U_BOOT_DRIVER(sysreset_sandbox) = {
static struct sysreset_ops sandbox_warm_sysreset_ops = {
.request = sandbox_warm_sysreset_request,
.get_status = sandbox_warm_sysreset_get_status,
+ .get_last = sandbox_warm_sysreset_get_last,
};
static const struct udevice_id sandbox_warm_sysreset_ids[] = {
diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig
index a7d600b6e4..d012cf71a9 100644
--- a/drivers/timer/Kconfig
+++ b/drivers/timer/Kconfig
@@ -30,6 +30,9 @@ config TPL_TIMER
config TIMER_EARLY
bool "Allow timer to be used early in U-Boot"
depends on TIMER
+ # initr_bootstage() requires a timer and is called before initr_dm()
+ # so only the early timer is available
+ default y if X86 && BOOTSTAGE
help
In some cases the timer must be accessible before driver model is
active. Examples include when using CONFIG_TRACE to trace U-Boot's
@@ -79,6 +82,16 @@ config X86_TSC_TIMER
help
Select this to enable Time-Stamp Counter (TSC) timer for x86.
+config X86_TSC_TIMER_EARLY_FREQ
+ int "x86 TSC timer frequency in MHz when used as the early timer"
+ depends on X86_TSC_TIMER
+ default 1000
+ help
+ Sets the estimated CPU frequency in MHz when TSC is used as the
+ early timer and the frequency can neither be calibrated via some
+ hardware ways, nor got from device tree at the time when device
+ tree is not available yet.
+
config OMAP_TIMER
bool "Omap timer support"
depends on TIMER
diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c
index 6473de20f1..da7c812908 100644
--- a/drivers/timer/tsc_timer.c
+++ b/drivers/timer/tsc_timer.c
@@ -341,7 +341,7 @@ static int tsc_timer_get_count(struct udevice *dev, u64 *count)
return 0;
}
-static void tsc_timer_ensure_setup(bool stop)
+static void tsc_timer_ensure_setup(bool early)
{
if (gd->arch.tsc_base)
return;
@@ -362,8 +362,8 @@ static void tsc_timer_ensure_setup(bool stop)
if (fast_calibrate)
goto done;
- if (stop)
- panic("TSC frequency is ZERO");
+ if (early)
+ fast_calibrate = CONFIG_X86_TSC_TIMER_EARLY_FREQ;
else
return;
diff --git a/drivers/tpm/Makefile b/drivers/tpm/Makefile
index af473ef662..94c337b8ed 100644
--- a/drivers/tpm/Makefile
+++ b/drivers/tpm/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0+
# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
-obj-$(CONFIG_TPM) += tpm-uclass.o
+obj-$(CONFIG_$(SPL_TPL_)TPM) += tpm-uclass.o
obj-$(CONFIG_TPM_ATMEL_TWI) += tpm_atmel_twi.o
obj-$(CONFIG_TPM_TIS_INFINEON) += tpm_tis_infineon.o
diff --git a/drivers/tpm/tpm-uclass.c b/drivers/tpm/tpm-uclass.c
index c83f53ab86..1b11c93194 100644
--- a/drivers/tpm/tpm-uclass.c
+++ b/drivers/tpm/tpm-uclass.c
@@ -126,8 +126,11 @@ int tpm_xfer(struct udevice *dev, const uint8_t *sendbuf, size_t send_size,
}
UCLASS_DRIVER(tpm) = {
- .id = UCLASS_TPM,
- .name = "tpm",
- .flags = DM_UC_FLAG_SEQ_ALIAS,
+ .id = UCLASS_TPM,
+ .name = "tpm",
+ .flags = DM_UC_FLAG_SEQ_ALIAS,
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+ .post_bind = dm_scan_fdt_dev,
+#endif
.per_device_auto_alloc_size = sizeof(struct tpm_chip_priv),
};
diff --git a/drivers/tpm/tpm_tis_lpc.c b/drivers/tpm/tpm_tis_lpc.c
index 7664bb1a60..e993fd9f83 100644
--- a/drivers/tpm/tpm_tis_lpc.c
+++ b/drivers/tpm/tpm_tis_lpc.c
@@ -164,7 +164,7 @@ static int tpm_tis_lpc_probe(struct udevice *dev)
u32 didvid;
ulong chip_type = dev_get_driver_data(dev);
- addr = devfdt_get_addr(dev);
+ addr = dev_read_addr(dev);
if (addr == FDT_ADDR_T_NONE)
return -EINVAL;
priv->regs = map_sysmem(addr, 0);
diff --git a/drivers/tpm/tpm_tis_sandbox.c b/drivers/tpm/tpm_tis_sandbox.c
index 8816d55759..79517f015a 100644
--- a/drivers/tpm/tpm_tis_sandbox.c
+++ b/drivers/tpm/tpm_tis_sandbox.c
@@ -13,6 +13,10 @@
/* TPM NVRAM location indices. */
#define FIRMWARE_NV_INDEX 0x1007
#define KERNEL_NV_INDEX 0x1008
+#define BACKUP_NV_INDEX 0x1009
+#define FWMP_NV_INDEX 0x100a
+#define REC_HASH_NV_INDEX 0x100b
+#define REC_HASH_NV_SIZE VB2_SHA256_DIGEST_SIZE
#define NV_DATA_PUBLIC_PERMISSIONS_OFFSET 60
@@ -45,18 +49,28 @@ enum {
NV_GLOBAL_LOCK,
NV_SEQ_FIRMWARE,
NV_SEQ_KERNEL,
+ NV_SEQ_BACKUP,
+ NV_SEQ_FWMP,
+ NV_SEQ_REC_HASH,
+
NV_SEQ_COUNT,
};
/* Size of each non-volatile space */
#define NV_DATA_SIZE 0x20
+struct nvdata_state {
+ bool present;
+ u8 data[NV_DATA_SIZE];
+};
+
/*
* Information about our TPM emulation. This is preserved in the sandbox
* state file if enabled.
*/
static struct tpm_state {
- uint8_t nvdata[NV_SEQ_COUNT][NV_DATA_SIZE];
+ bool valid;
+ struct nvdata_state nvdata[NV_SEQ_COUNT];
} g_state;
/**
@@ -82,9 +96,12 @@ static int sandbox_tpm_read_state(const void *blob, int node)
sprintf(prop_name, "nvdata%d", i);
prop = fdt_getprop(blob, node, prop_name, &len);
- if (prop && len == NV_DATA_SIZE)
- memcpy(g_state.nvdata[i], prop, NV_DATA_SIZE);
+ if (prop && len == NV_DATA_SIZE) {
+ memcpy(g_state.nvdata[i].data, prop, NV_DATA_SIZE);
+ g_state.nvdata[i].present = true;
+ }
}
+ g_state.valid = true;
return 0;
}
@@ -110,9 +127,11 @@ static int sandbox_tpm_write_state(void *blob, int node)
for (i = 0; i < NV_SEQ_COUNT; i++) {
char prop_name[20];
- sprintf(prop_name, "nvdata%d", i);
- fdt_setprop(blob, node, prop_name, g_state.nvdata[i],
- NV_DATA_SIZE);
+ if (g_state.nvdata[i].present) {
+ sprintf(prop_name, "nvdata%d", i);
+ fdt_setprop(blob, node, prop_name,
+ g_state.nvdata[i].data, NV_DATA_SIZE);
+ }
}
return 0;
@@ -128,6 +147,12 @@ static int index_to_seq(uint32_t index)
return NV_SEQ_FIRMWARE;
case KERNEL_NV_INDEX:
return NV_SEQ_KERNEL;
+ case BACKUP_NV_INDEX:
+ return NV_SEQ_BACKUP;
+ case FWMP_NV_INDEX:
+ return NV_SEQ_FWMP;
+ case REC_HASH_NV_INDEX:
+ return NV_SEQ_REC_HASH;
case 0:
return NV_GLOBAL_LOCK;
}
@@ -136,6 +161,21 @@ static int index_to_seq(uint32_t index)
return -1;
}
+static void handle_cap_flag_space(u8 **datap, uint index)
+{
+ struct tpm_nv_data_public pub;
+
+ /* TPM_NV_PER_PPWRITE */
+ memset(&pub, '\0', sizeof(pub));
+ pub.nv_index = __cpu_to_be32(index);
+ pub.pcr_info_read.pcr_selection.size_of_select = __cpu_to_be16(
+ sizeof(pub.pcr_info_read.pcr_selection.pcr_select));
+ pub.permission.attributes = __cpu_to_be32(1);
+ pub.pcr_info_write = pub.pcr_info_read;
+ memcpy(*datap, &pub, sizeof(pub));
+ *datap += sizeof(pub);
+}
+
static int sandbox_tpm_xfer(struct udevice *dev, const uint8_t *sendbuf,
size_t send_size, uint8_t *recvbuf,
size_t *recv_len)
@@ -151,29 +191,45 @@ static int sandbox_tpm_xfer(struct udevice *dev, const uint8_t *sendbuf,
*recv_len, code);
print_buffer(0, sendbuf, 1, send_size, 0);
switch (code) {
- case 0x65: /* get flags */
+ case TPM_CMD_GET_CAPABILITY:
type = get_unaligned_be32(sendbuf + 14);
switch (type) {
- case 4:
+ case TPM_CAP_FLAG:
index = get_unaligned_be32(sendbuf + 18);
printf("Get flags index %#02x\n", index);
*recv_len = 22;
memset(recvbuf, '\0', *recv_len);
- put_unaligned_be32(22, recvbuf +
- TPM_RESPONSE_HEADER_LENGTH);
data = recvbuf + TPM_RESPONSE_HEADER_LENGTH +
sizeof(uint32_t);
switch (index) {
case FIRMWARE_NV_INDEX:
break;
case KERNEL_NV_INDEX:
- /* TPM_NV_PER_PPWRITE */
- put_unaligned_be32(1, data +
- NV_DATA_PUBLIC_PERMISSIONS_OFFSET);
+ handle_cap_flag_space(&data, index);
+ *recv_len = data - recvbuf -
+ TPM_RESPONSE_HEADER_LENGTH -
+ sizeof(uint32_t);
+ break;
+ case TPM_CAP_FLAG_PERMANENT: {
+ struct tpm_permanent_flags *pflags;
+
+ pflags = (struct tpm_permanent_flags *)data;
+ memset(pflags, '\0', sizeof(*pflags));
+ put_unaligned_be32(TPM_TAG_PERMANENT_FLAGS,
+ &pflags->tag);
+ *recv_len = TPM_HEADER_SIZE + 4 +
+ sizeof(*pflags);
break;
}
+ default:
+ printf(" ** Unknown flags index %x\n", index);
+ return -ENOSYS;
+ }
+ put_unaligned_be32(*recv_len,
+ recvbuf +
+ TPM_RESPONSE_HEADER_LENGTH);
break;
- case 0x11: /* TPM_CAP_NV_INDEX */
+ case TPM_CAP_NV_INDEX:
index = get_unaligned_be32(sendbuf + 18);
printf("Get cap nv index %#02x\n", index);
put_unaligned_be32(22, recvbuf +
@@ -182,27 +238,29 @@ static int sandbox_tpm_xfer(struct udevice *dev, const uint8_t *sendbuf,
default:
printf(" ** Unknown 0x65 command type %#02x\n",
type);
- return -1;
+ return -ENOSYS;
}
break;
- case 0xcd: /* nvwrite */
+ case TPM_CMD_NV_WRITE_VALUE:
index = get_unaligned_be32(sendbuf + 10);
length = get_unaligned_be32(sendbuf + 18);
seq = index_to_seq(index);
if (seq < 0)
- return -1;
+ return -EINVAL;
printf("tpm: nvwrite index=%#02x, len=%#02x\n", index, length);
- memcpy(&tpm->nvdata[seq], sendbuf + 22, length);
+ memcpy(&tpm->nvdata[seq].data, sendbuf + 22, length);
+ tpm->nvdata[seq].present = true;
*recv_len = 12;
memset(recvbuf, '\0', *recv_len);
break;
- case 0xcf: /* nvread */
+ case TPM_CMD_NV_READ_VALUE: /* nvread */
index = get_unaligned_be32(sendbuf + 10);
length = get_unaligned_be32(sendbuf + 18);
seq = index_to_seq(index);
if (seq < 0)
- return -1;
- printf("tpm: nvread index=%#02x, len=%#02x\n", index, length);
+ return -EINVAL;
+ printf("tpm: nvread index=%#02x, len=%#02x, seq=%#02x\n", index,
+ length, seq);
*recv_len = TPM_RESPONSE_HEADER_LENGTH + sizeof(uint32_t) +
length;
memset(recvbuf, '\0', *recv_len);
@@ -220,24 +278,33 @@ static int sandbox_tpm_xfer(struct udevice *dev, const uint8_t *sendbuf,
offsetof(struct rollback_space_kernel,
crc8));
memcpy(data, &rsk, sizeof(rsk));
+ } else if (!tpm->nvdata[seq].present) {
+ put_unaligned_be32(TPM_BADINDEX, recvbuf +
+ sizeof(uint16_t) + sizeof(uint32_t));
} else {
memcpy(recvbuf + TPM_RESPONSE_HEADER_LENGTH +
- sizeof(uint32_t), &tpm->nvdata[seq], length);
+ sizeof(uint32_t), &tpm->nvdata[seq].data,
+ length);
}
break;
- case 0x14: /* tpm extend */
+ case TPM_CMD_EXTEND:
+ *recv_len = 30;
+ memset(recvbuf, '\0', *recv_len);
+ break;
+ case TPM_CMD_NV_DEFINE_SPACE:
case 0x15: /* pcr read */
case 0x5d: /* force clear */
case 0x6f: /* physical enable */
case 0x72: /* physical set deactivated */
case 0x99: /* startup */
+ case 0x50: /* self test full */
case 0x4000000a: /* assert physical presence */
*recv_len = 12;
memset(recvbuf, '\0', *recv_len);
break;
default:
printf("Unknown tpm command %02x\n", code);
- return -1;
+ return -ENOSYS;
}
return 0;
diff --git a/drivers/usb/eth/lan7x.h b/drivers/usb/eth/lan7x.h
index d1b1047935..7af610be37 100644
--- a/drivers/usb/eth/lan7x.h
+++ b/drivers/usb/eth/lan7x.h
@@ -94,7 +94,7 @@
#define LAN7X_MAC_RX_MAX_SIZE(mtu) \
((mtu) << 16) /* Max frame size */
#define LAN7X_MAC_RX_MAX_SIZE_DEFAULT \
- LAN7X_MAC_RX_MAX_SIZE(ETH_FRAME_LEN + 4 /* VLAN */ + 4 /* CRC */)
+ LAN7X_MAC_RX_MAX_SIZE(PKTSIZE_ALIGN + 4 /* VLAN */ + 4 /* CRC */)
/* Timeouts */
#define USB_CTRL_SET_TIMEOUT_MS 5000
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 8ab9b9fe56..90ef1f055f 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -71,11 +71,6 @@ unsigned packet_received, packet_sent;
* RNDIS specs are ambiguous and appear to be incomplete, and are also
* needlessly complex. They borrow more from CDC ACM than CDC ECM.
*/
-#define ETH_ALEN 6 /* Octets in one ethernet addr */
-#define ETH_HLEN 14 /* Total octets in header. */
-#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */
-#define ETH_DATA_LEN 1500 /* Max. octets in payload */
-#define ETH_FRAME_LEN PKTSIZE_ALIGN /* Max. octets in frame sans FCS */
#define DRIVER_DESC "Ethernet Gadget"
/* Based on linux 2.6.27 version */
@@ -529,7 +524,7 @@ static const struct usb_cdc_ether_desc ether_desc = {
/* this descriptor actually adds value, surprise! */
.iMACAddress = STRING_ETHADDR,
.bmEthernetStatistics = __constant_cpu_to_le32(0), /* no statistics */
- .wMaxSegmentSize = __constant_cpu_to_le16(ETH_FRAME_LEN),
+ .wMaxSegmentSize = __constant_cpu_to_le16(PKTSIZE_ALIGN),
.wNumberMCFilters = __constant_cpu_to_le16(0),
.bNumberPowerFilters = 0,
};
@@ -1575,7 +1570,7 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)
req->length -= length;
req->actual -= length;
}
- if (req->actual < ETH_HLEN || ETH_FRAME_LEN < req->actual) {
+ if (req->actual < ETH_HLEN || PKTSIZE_ALIGN < req->actual) {
length_err:
dev->stats.rx_errors++;
dev->stats.rx_length_errors++;
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index d47e29e447..eec639f8c0 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -35,12 +35,6 @@
#include "rndis.h"
-#define ETH_ALEN 6 /* Octets in one ethernet addr */
-#define ETH_HLEN 14 /* Total octets in header. */
-#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */
-#define ETH_DATA_LEN 1500 /* Max. octets in payload */
-#define ETH_FRAME_LEN PKTSIZE_ALIGN /* Max. octets in frame sans FCS */
-
/*
* The driver for your USB chip needs to support ep0 OUT to work with
* RNDIS, plus all three CDC Ethernet endpoints (interrupt not optional).
diff --git a/drivers/video/backlight-uclass.c b/drivers/video/backlight-uclass.c
index 92715e2f13..0aadf8a1f9 100644
--- a/drivers/video/backlight-uclass.c
+++ b/drivers/video/backlight-uclass.c
@@ -18,6 +18,16 @@ int backlight_enable(struct udevice *dev)
return ops->enable(dev);
}
+int backlight_set_brightness(struct udevice *dev, int percent)
+{
+ const struct backlight_ops *ops = backlight_get_ops(dev);
+
+ if (!ops->set_brightness)
+ return -ENOSYS;
+
+ return ops->set_brightness(dev, percent);
+}
+
UCLASS_DRIVER(backlight) = {
.id = UCLASS_PANEL_BACKLIGHT,
.name = "backlight",
diff --git a/drivers/video/panel-uclass.c b/drivers/video/panel-uclass.c
index aec44a8bf7..246d1b2836 100644
--- a/drivers/video/panel-uclass.c
+++ b/drivers/video/panel-uclass.c
@@ -18,6 +18,24 @@ int panel_enable_backlight(struct udevice *dev)
return ops->enable_backlight(dev);
}
+/**
+ * panel_set_backlight - Set brightness for the panel backlight
+ *
+ * @dev: Panel device containing the backlight to update
+ * @percent: Brightness value (0=off, 1=min brightness,
+ * 100=full brightness)
+ * @return 0 if OK, -ve on error
+ */
+int panel_set_backlight(struct udevice *dev, int percent)
+{
+ struct panel_ops *ops = panel_get_ops(dev);
+
+ if (!ops->set_backlight)
+ return -ENOSYS;
+
+ return ops->set_backlight(dev, percent);
+}
+
int panel_get_display_timing(struct udevice *dev,
struct display_timing *timings)
{
diff --git a/drivers/video/pwm_backlight.c b/drivers/video/pwm_backlight.c
index 53953179bf..c13a907709 100644
--- a/drivers/video/pwm_backlight.c
+++ b/drivers/video/pwm_backlight.c
@@ -4,6 +4,8 @@
* Written by Simon Glass <sjg@chromium.org>
*/
+#define LOG_CATEGORY UCLASS_PANEL_BACKLIGHT
+
#include <common.h>
#include <dm.h>
#include <backlight.h>
@@ -11,48 +13,156 @@
#include <asm/gpio.h>
#include <power/regulator.h>
+/**
+ * Private information for the PWM backlight
+ *
+ * If @num_levels is 0 then the levels are simple values with the backlight
+ * value going between the minimum (default 0) and the maximum (default 255).
+ * Otherwise the levels are an index into @levels (0..n-1).
+ *
+ * @reg: Regulator to enable to turn the backlight on (NULL if none)
+ * @enable, GPIO to set to enable the backlight (can be missing)
+ * @pwm: PWM to use to change the backlight brightness
+ * @channel: PWM channel to use
+ * @period_ns: Period of the backlight in nanoseconds
+ * @levels: Levels for the backlight, or NULL if not using indexed levels
+ * @num_levels: Number of levels
+ * @cur_level: Current level for the backlight (index or value)
+ * @default_level: Default level for the backlight (index or value)
+ * @min_level: Minimum level of the backlight (full off)
+ * @min_level: Maximum level of the backlight (full on)
+ * @enabled: true if backlight is enabled
+ */
struct pwm_backlight_priv {
struct udevice *reg;
struct gpio_desc enable;
struct udevice *pwm;
uint channel;
uint period_ns;
+ u32 *levels;
+ int num_levels;
uint default_level;
+ int cur_level;
uint min_level;
uint max_level;
+ bool enabled;
};
-static int pwm_backlight_enable(struct udevice *dev)
+static int set_pwm(struct pwm_backlight_priv *priv)
{
- struct pwm_backlight_priv *priv = dev_get_priv(dev);
- struct dm_regulator_uclass_platdata *plat;
uint duty_cycle;
int ret;
- if (priv->reg) {
- plat = dev_get_uclass_platdata(priv->reg);
- debug("%s: Enable '%s', regulator '%s'/'%s'\n", __func__,
- dev->name, priv->reg->name, plat->name);
- ret = regulator_set_enable(priv->reg, true);
- if (ret) {
- debug("%s: Cannot enable regulator for PWM '%s'\n",
- __func__, dev->name);
- return ret;
- }
- mdelay(120);
- }
-
- duty_cycle = priv->period_ns * (priv->default_level - priv->min_level) /
+ duty_cycle = priv->period_ns * (priv->cur_level - priv->min_level) /
(priv->max_level - priv->min_level + 1);
ret = pwm_set_config(priv->pwm, priv->channel, priv->period_ns,
duty_cycle);
+
+ return log_ret(ret);
+}
+
+static int enable_sequence(struct udevice *dev, int seq)
+{
+ struct pwm_backlight_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ switch (seq) {
+ case 0:
+ if (priv->reg) {
+ __maybe_unused struct dm_regulator_uclass_platdata
+ *plat;
+
+ plat = dev_get_uclass_platdata(priv->reg);
+ log_debug("Enable '%s', regulator '%s'/'%s'\n",
+ dev->name, priv->reg->name, plat->name);
+ ret = regulator_set_enable(priv->reg, true);
+ if (ret) {
+ log_debug("Cannot enable regulator for PWM '%s'\n",
+ __func__, dev->name);
+ return log_ret(ret);
+ }
+ mdelay(120);
+ }
+ break;
+ case 1:
+ mdelay(10);
+ dm_gpio_set_value(&priv->enable, 1);
+ break;
+ }
+
+ return 0;
+}
+
+static int pwm_backlight_enable(struct udevice *dev)
+{
+ struct pwm_backlight_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = enable_sequence(dev, 0);
+ if (ret)
+ return log_ret(ret);
+ ret = set_pwm(priv);
if (ret)
- return ret;
+ return log_ret(ret);
ret = pwm_set_enable(priv->pwm, priv->channel, true);
if (ret)
- return ret;
- mdelay(10);
- dm_gpio_set_value(&priv->enable, 1);
+ return log_ret(ret);
+ ret = enable_sequence(dev, 1);
+ if (ret)
+ return log_ret(ret);
+ priv->enabled = true;
+
+ return 0;
+}
+
+static int pwm_backlight_set_brightness(struct udevice *dev, int percent)
+{
+ struct pwm_backlight_priv *priv = dev_get_priv(dev);
+ bool disable = false;
+ int level;
+ int ret;
+
+ if (!priv->enabled) {
+ ret = enable_sequence(dev, 0);
+ if (ret)
+ return log_ret(ret);
+ }
+ if (percent == BACKLIGHT_OFF) {
+ disable = true;
+ percent = 0;
+ }
+ if (percent == BACKLIGHT_DEFAULT) {
+ level = priv->default_level;
+ } else {
+ if (priv->levels) {
+ level = priv->levels[percent * (priv->num_levels - 1)
+ / 100];
+ } else {
+ level = priv->min_level +
+ (priv->max_level - priv->min_level) *
+ percent / 100;
+ }
+ }
+ priv->cur_level = level;
+
+ ret = set_pwm(priv);
+ if (ret)
+ return log_ret(ret);
+ if (!priv->enabled) {
+ ret = enable_sequence(dev, 1);
+ if (ret)
+ return log_ret(ret);
+ priv->enabled = true;
+ }
+ if (disable) {
+ dm_gpio_set_value(&priv->enable, 0);
+ if (priv->reg) {
+ ret = regulator_set_enable(priv->reg, false);
+ if (ret)
+ return log_ret(ret);
+ }
+ priv->enabled = false;
+ }
return 0;
}
@@ -64,31 +174,32 @@ static int pwm_backlight_ofdata_to_platdata(struct udevice *dev)
int index, ret, count, len;
const u32 *cell;
- debug("%s: start\n", __func__);
+ log_debug("start\n");
ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
"power-supply", &priv->reg);
if (ret)
- debug("%s: Cannot get power supply: ret=%d\n", __func__, ret);
+ log_debug("Cannot get power supply: ret=%d\n", ret);
ret = gpio_request_by_name(dev, "enable-gpios", 0, &priv->enable,
GPIOD_IS_OUT);
if (ret) {
- debug("%s: Warning: cannot get enable GPIO: ret=%d\n",
- __func__, ret);
+ log_debug("Warning: cannot get enable GPIO: ret=%d\n", ret);
if (ret != -ENOENT)
- return ret;
+ return log_ret(ret);
}
ret = dev_read_phandle_with_args(dev, "pwms", "#pwm-cells", 0, 0,
&args);
if (ret) {
- debug("%s: Cannot get PWM phandle: ret=%d\n", __func__, ret);
- return ret;
+ log_debug("Cannot get PWM phandle: ret=%d\n", ret);
+ return log_ret(ret);
}
ret = uclass_get_device_by_ofnode(UCLASS_PWM, args.node, &priv->pwm);
if (ret) {
- debug("%s: Cannot get PWM: ret=%d\n", __func__, ret);
- return ret;
+ log_debug("Cannot get PWM: ret=%d\n", ret);
+ return log_ret(ret);
}
+ if (args.args_count < 2)
+ return log_msg_ret("Not enough arguments to pwm\n", -EINVAL);
priv->channel = args.args[0];
priv->period_ns = args.args[1];
@@ -96,13 +207,20 @@ static int pwm_backlight_ofdata_to_platdata(struct udevice *dev)
cell = dev_read_prop(dev, "brightness-levels", &len);
count = len / sizeof(u32);
if (cell && count > index) {
- priv->default_level = fdt32_to_cpu(cell[index]);
- priv->max_level = fdt32_to_cpu(cell[count - 1]);
+ priv->levels = malloc(len);
+ if (!priv->levels)
+ return log_ret(-ENOMEM);
+ dev_read_u32_array(dev, "brightness-levels", priv->levels,
+ count);
+ priv->num_levels = count;
+ priv->default_level = priv->levels[index];
+ priv->max_level = priv->levels[count - 1];
} else {
priv->default_level = index;
priv->max_level = 255;
}
- debug("%s: done\n", __func__);
+ priv->cur_level = priv->default_level;
+ log_debug("done\n");
return 0;
@@ -114,7 +232,8 @@ static int pwm_backlight_probe(struct udevice *dev)
}
static const struct backlight_ops pwm_backlight_ops = {
- .enable = pwm_backlight_enable,
+ .enable = pwm_backlight_enable,
+ .set_brightness = pwm_backlight_set_brightness,
};
static const struct udevice_id pwm_backlight_ids[] = {
diff --git a/drivers/video/simple_panel.c b/drivers/video/simple_panel.c
index 6c604f9bed..7a968e740c 100644
--- a/drivers/video/simple_panel.c
+++ b/drivers/video/simple_panel.c
@@ -32,6 +32,21 @@ static int simple_panel_enable_backlight(struct udevice *dev)
return 0;
}
+static int simple_panel_set_backlight(struct udevice *dev, int percent)
+{
+ struct simple_panel_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ debug("%s: start, backlight = '%s'\n", __func__, priv->backlight->name);
+ dm_gpio_set_value(&priv->enable, 1);
+ ret = backlight_set_brightness(priv->backlight, percent);
+ debug("%s: done, ret = %d\n", __func__, ret);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
static int simple_panel_ofdata_to_platdata(struct udevice *dev)
{
struct simple_panel_priv *priv = dev_get_priv(dev);
@@ -51,7 +66,7 @@ static int simple_panel_ofdata_to_platdata(struct udevice *dev)
"backlight", &priv->backlight);
if (ret) {
debug("%s: Cannot get backlight: ret=%d\n", __func__, ret);
- return ret;
+ return log_ret(ret);
}
ret = gpio_request_by_name(dev, "enable-gpios", 0, &priv->enable,
GPIOD_IS_OUT);
@@ -59,7 +74,7 @@ static int simple_panel_ofdata_to_platdata(struct udevice *dev)
debug("%s: Warning: cannot get enable GPIO: ret=%d\n",
__func__, ret);
if (ret != -ENOENT)
- return ret;
+ return log_ret(ret);
}
return 0;
@@ -82,6 +97,7 @@ static int simple_panel_probe(struct udevice *dev)
static const struct panel_ops simple_panel_ops = {
.enable_backlight = simple_panel_enable_backlight,
+ .set_backlight = simple_panel_set_backlight,
};
static const struct udevice_id simple_panel_ids[] = {
diff --git a/drivers/video/tegra124/sor.c b/drivers/video/tegra124/sor.c
index 91e61b5852..172bb14d6c 100644
--- a/drivers/video/tegra124/sor.c
+++ b/drivers/video/tegra124/sor.c
@@ -533,7 +533,8 @@ static int tegra_dc_sor_power_up(struct udevice *dev, int is_lvds)
#if DEBUG_SOR
static void dump_sor_reg(struct tegra_dc_sor_data *sor)
{
-#define DUMP_REG(a) printk(BIOS_INFO, "%-32s %03x %08x\n", \
+#define DUMP_REG(a) printk(BIOS_INFO, \
+ "%-32s %03x %08x\n", \
#a, a, tegra_sor_readl(sor, a));
DUMP_REG(SUPER_STATE0);
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index 7f95e9c6e5..1874887f2f 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -86,7 +86,7 @@ static int vidconsole_back(struct udevice *dev)
if (priv->ycur < 0)
priv->ycur = 0;
}
- video_sync(dev->parent);
+ video_sync(dev->parent, false);
return 0;
}
@@ -113,7 +113,7 @@ static void vidconsole_newline(struct udevice *dev)
}
priv->last_ch = 0;
- video_sync(dev->parent);
+ video_sync(dev->parent, false);
}
static const struct vid_rgb colors[VID_COLOR_COUNT] = {
@@ -293,7 +293,7 @@ static void vidconsole_escape_char(struct udevice *dev, char ch)
if (mode == 2) {
video_clear(dev->parent);
- video_sync(dev->parent);
+ video_sync(dev->parent, false);
priv->ycur = 0;
priv->xcur_frac = priv->xstart_frac;
} else {
@@ -449,7 +449,7 @@ static void vidconsole_putc(struct stdio_dev *sdev, const char ch)
struct udevice *dev = sdev->priv;
vidconsole_put_char(dev, ch);
- video_sync(dev->parent);
+ video_sync(dev->parent, false);
}
static void vidconsole_puts(struct stdio_dev *sdev, const char *s)
@@ -458,7 +458,7 @@ static void vidconsole_puts(struct stdio_dev *sdev, const char *s)
while (*s)
vidconsole_put_char(dev, *s++);
- video_sync(dev->parent);
+ video_sync(dev->parent, false);
}
/* Set up the number of rows and colours (rotated drivers override this) */
@@ -511,6 +511,8 @@ void vidconsole_position_cursor(struct udevice *dev, unsigned col, unsigned row)
struct udevice *vid_dev = dev->parent;
struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
+ col *= priv->x_charsize;
+ row *= priv->y_charsize;
priv->xcur_frac = VID_TO_POS(min_t(short, col, vid_priv->xsize - 1));
priv->ycur = min_t(short, row, vid_priv->ysize - 1);
}
@@ -547,7 +549,7 @@ static int do_video_puts(cmd_tbl_t *cmdtp, int flag, int argc,
for (s = argv[1]; *s; s++)
vidconsole_put_char(dev, *s);
- video_sync(dev->parent);
+ video_sync(dev->parent, false);
return 0;
}
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index dd0873767b..44dfa71b6f 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -86,7 +86,7 @@ int video_reserve(ulong *addrp)
return 0;
}
-void video_clear(struct udevice *dev)
+int video_clear(struct udevice *dev)
{
struct video_priv *priv = dev_get_uclass_priv(dev);
@@ -111,6 +111,8 @@ void video_clear(struct udevice *dev)
memset(priv->fb, priv->colour_bg, priv->fb_size);
break;
}
+
+ return 0;
}
void video_set_default_colors(struct video_priv *priv)
@@ -128,7 +130,7 @@ void video_set_default_colors(struct video_priv *priv)
}
/* Flush video activity to the caches */
-void video_sync(struct udevice *vid)
+void video_sync(struct udevice *vid, bool force)
{
/*
* flush_dcache_range() is declared in common.h but it seems that some
@@ -147,7 +149,7 @@ void video_sync(struct udevice *vid)
struct video_priv *priv = dev_get_uclass_priv(vid);
static ulong last_sync;
- if (get_timer(last_sync) > 10) {
+ if (force || get_timer(last_sync) > 10) {
sandbox_sdl_sync(priv->fb);
last_sync = get_timer(0);
}
@@ -162,7 +164,7 @@ void video_sync_all(void)
dev;
uclass_find_next_device(&dev)) {
if (device_active(dev))
- video_sync(dev);
+ video_sync(dev, true);
}
}
diff --git a/drivers/video/video_bmp.c b/drivers/video/video_bmp.c
index aeff65648c..1377e19081 100644
--- a/drivers/video/video_bmp.c
+++ b/drivers/video/video_bmp.c
@@ -345,7 +345,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
break;
};
- video_sync(dev);
+ video_sync(dev, false);
return 0;
}
diff --git a/drivers/watchdog/ast_wdt.c b/drivers/watchdog/ast_wdt.c
index 477605e722..59afa21efa 100644
--- a/drivers/watchdog/ast_wdt.c
+++ b/drivers/watchdog/ast_wdt.c
@@ -50,6 +50,7 @@ static int ast_wdt_stop(struct udevice *dev)
clrbits_le32(&priv->regs->ctrl, WDT_CTRL_EN);
+ writel(WDT_RESET_DEFAULT, &priv->regs->reset_mask);
return 0;
}