1
0
Fork 0

Merge branch 'master' of git://git.denx.de/u-boot-dm

utp
Tom Rini 2015-04-23 13:53:09 -04:00
commit 5f757cdcc6
36 changed files with 814 additions and 216 deletions

View File

@ -2,6 +2,8 @@
* U-Boot additions to enable a generic Exynos GPIO driver
*
* Copyright (c) 2014 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
/{

View File

@ -2,6 +2,8 @@
* U-Boot additions to enable a generic Exynos GPIO driver
*
* Copyright (c) 2014 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
/{

View File

@ -2,6 +2,8 @@
* U-Boot additions to enable a generic Exynos GPIO driver
*
* Copyright (c) 2014 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
/{

View File

@ -2,6 +2,8 @@
* U-Boot additions to enable a generic Exynos GPIO driver
*
* Copyright (c) 2014 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
/{

View File

@ -2,6 +2,8 @@
* U-Boot additions to enable a generic Exynos GPIO driver
*
* Copyright (c) 2014 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
/ {

View File

@ -2,6 +2,8 @@
* U-Boot additions to enable a generic Exynos GPIO driver
*
* Copyright (c) 2014 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
/ {

View File

@ -6,6 +6,7 @@
#include <common.h>
#include <dm/root.h>
#include <os.h>
#include <asm/io.h>
#include <asm/state.h>
DECLARE_GLOBAL_DATA_PTR;
@ -97,3 +98,43 @@ phys_addr_t map_to_sysmem(const void *ptr)
void flush_dcache_range(unsigned long start, unsigned long stop)
{
}
int sandbox_read_fdt_from_file(void)
{
struct sandbox_state *state = state_get_current();
const char *fname = state->fdt_fname;
void *blob;
loff_t size;
int err;
int fd;
blob = map_sysmem(CONFIG_SYS_FDT_LOAD_ADDR, 0);
if (!state->fdt_fname) {
err = fdt_create_empty_tree(blob, 256);
if (!err)
goto done;
printf("Unable to create empty FDT: %s\n", fdt_strerror(err));
return -EINVAL;
}
err = os_get_filesize(fname, &size);
if (err < 0) {
printf("Failed to file FDT file '%s'\n", fname);
return err;
}
fd = os_open(fname, OS_O_RDONLY);
if (fd < 0) {
printf("Failed to open FDT file '%s'\n", fname);
return -EACCES;
}
if (os_read(fd, blob, size) != size) {
os_close(fd);
return -EIO;
}
os_close(fd);
done:
gd->fdt_blob = blob;
return 0;
}

View File

@ -1,6 +1,8 @@
/*
* Copyright (c) 2011 The Chromium OS Authors.
*
* Modified from Linux arch/arm/include/asm/bitops.h
*
* Copyright 1995, Russell King.
* Various bits and pieces copyrights include:
* Linus Torvalds (test_bit).

View File

@ -75,4 +75,12 @@ int pci_unmap_physmem(const void *addr, unsigned long len,
*/
void sandbox_set_enable_pci_map(int enable);
/**
* sandbox_read_fdt_from_file() - Read a device tree from a file
*
* Read a device tree file from a host file and set it up for use as the
* control FDT.
*/
int sandbox_read_fdt_from_file(void);
#endif /* _U_BOOT_SANDBOX_H_ */

View File

@ -23,6 +23,7 @@
#include <i2c.h>
#include <initcall.h>
#include <logbuff.h>
#include <malloc.h>
#include <mapmem.h>
/* TODO: Can we move these into arch/ headers? */
@ -282,49 +283,6 @@ __weak int arch_cpu_init(void)
return 0;
}
#ifdef CONFIG_OF_HOSTFILE
static int read_fdt_from_file(void)
{
struct sandbox_state *state = state_get_current();
const char *fname = state->fdt_fname;
void *blob;
loff_t size;
int err;
int fd;
blob = map_sysmem(CONFIG_SYS_FDT_LOAD_ADDR, 0);
if (!state->fdt_fname) {
err = fdt_create_empty_tree(blob, 256);
if (!err)
goto done;
printf("Unable to create empty FDT: %s\n", fdt_strerror(err));
return -EINVAL;
}
err = os_get_filesize(fname, &size);
if (err < 0) {
printf("Failed to file FDT file '%s'\n", fname);
return err;
}
fd = os_open(fname, OS_O_RDONLY);
if (fd < 0) {
printf("Failed to open FDT file '%s'\n", fname);
return -EACCES;
}
if (os_read(fd, blob, size) != size) {
os_close(fd);
return -EIO;
}
os_close(fd);
done:
gd->fdt_blob = blob;
return 0;
}
#endif
#ifdef CONFIG_SANDBOX
static int setup_ram_buf(void)
{
@ -337,28 +295,6 @@ static int setup_ram_buf(void)
}
#endif
static int setup_fdt(void)
{
#ifdef CONFIG_OF_CONTROL
# ifdef CONFIG_OF_EMBED
/* Get a pointer to the FDT */
gd->fdt_blob = __dtb_dt_begin;
# elif defined CONFIG_OF_SEPARATE
/* FDT is at end of image */
gd->fdt_blob = (ulong *)&_end;
# elif defined(CONFIG_OF_HOSTFILE)
if (read_fdt_from_file()) {
puts("Failed to read control FDT\n");
return -1;
}
# endif
/* Allow the early environment to override the fdt address */
gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,
(uintptr_t)gd->fdt_blob);
#endif
return 0;
}
/* Get the top of usable RAM */
__weak ulong board_get_usable_ram_top(ulong total_size)
{
@ -786,17 +722,6 @@ static int mark_bootstage(void)
return 0;
}
static int initf_malloc(void)
{
#ifdef CONFIG_SYS_MALLOC_F_LEN
assert(gd->malloc_base); /* Set up by crt0.S */
gd->malloc_limit = gd->malloc_base + CONFIG_SYS_MALLOC_F_LEN;
gd->malloc_ptr = 0;
#endif
return 0;
}
static int initf_dm(void)
{
#if defined(CONFIG_DM) && defined(CONFIG_SYS_MALLOC_F_LEN)
@ -826,7 +751,9 @@ static init_fnc_t init_sequence_f[] = {
setup_ram_buf,
#endif
setup_mon_len,
setup_fdt,
#ifdef CONFIG_OF_CONTROL
fdtdec_setup,
#endif
#ifdef CONFIG_TRACE
trace_early_init,
#endif
@ -837,9 +764,6 @@ static init_fnc_t init_sequence_f[] = {
#endif
arch_cpu_init, /* basic arch cpu dependent setup */
mark_bootstage,
#ifdef CONFIG_OF_CONTROL
fdtdec_check_fdt,
#endif
initf_dm,
arch_cpu_init_dm,
#if defined(CONFIG_BOARD_EARLY_INIT_F)

View File

@ -3261,6 +3261,17 @@ int mALLOPt(param_number, value) int param_number; int value;
}
}
int initf_malloc(void)
{
#ifdef CONFIG_SYS_MALLOC_F_LEN
assert(gd->malloc_base); /* Set up by crt0.S */
gd->malloc_limit = CONFIG_SYS_MALLOC_F_LEN;
gd->malloc_ptr = 0;
#endif
return 0;
}
/*
History:

View File

@ -151,6 +151,8 @@ static void spl_ram_load_image(void)
void board_init_r(gd_t *dummy1, ulong dummy2)
{
u32 boot_device;
int ret;
debug(">>spl:board_init_r()\n");
#if defined(CONFIG_SYS_SPL_MALLOC_START)
@ -158,12 +160,24 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
CONFIG_SYS_SPL_MALLOC_SIZE);
gd->flags |= GD_FLG_FULL_MALLOC_INIT;
#elif defined(CONFIG_SYS_MALLOC_F_LEN)
gd->malloc_limit = gd->malloc_base + CONFIG_SYS_MALLOC_F_LEN;
gd->malloc_limit = CONFIG_SYS_MALLOC_F_LEN;
gd->malloc_ptr = 0;
#endif
#ifdef CONFIG_SPL_DM
dm_init_and_scan(true);
#endif
if (IS_ENABLED(CONFIG_OF_CONTROL) &&
!IS_ENABLED(CONFIG_SPL_DISABLE_OF_CONTROL)) {
ret = fdtdec_setup();
if (ret) {
debug("fdtdec_setup() returned error %d\n", ret);
hang();
}
}
if (IS_ENABLED(CONFIG_SPL_DM)) {
ret = dm_init_and_scan(true);
if (ret) {
debug("dm_init_and_scan() returned error %d\n", ret);
hang();
}
}
#ifndef CONFIG_PPC
/*

View File

@ -95,43 +95,82 @@ are provided in test/dm. To run them, try:
You should see something like this:
<...U-Boot banner...>
Running 29 driver model tests
Running 53 driver model tests
Test: dm_test_autobind
Test: dm_test_autoprobe
Test: dm_test_bus_child_post_bind
Test: dm_test_bus_child_post_bind_uclass
Test: dm_test_bus_child_pre_probe_uclass
Test: dm_test_bus_children
Device 'd-test': seq 3 is in use by 'b-test'
Device 'c-test@0': seq 0 is in use by 'a-test'
Device 'c-test@1': seq 1 is in use by 'd-test'
Device 'c-test@0': seq 0 is in use by 'd-test'
Device 'c-test@1': seq 1 is in use by 'f-test'
Test: dm_test_bus_children_funcs
Test: dm_test_bus_children_iterators
Test: dm_test_bus_parent_data
Test: dm_test_bus_parent_data_uclass
Test: dm_test_bus_parent_ops
Test: dm_test_bus_parent_platdata
Test: dm_test_bus_parent_platdata_uclass
Test: dm_test_children
Test: dm_test_device_get_uclass_id
Test: dm_test_eth
Using eth@10002000 device
Using eth@10003000 device
Using eth@10004000 device
Test: dm_test_eth_alias
Using eth@10002000 device
Using eth@10004000 device
Using eth@10002000 device
Using eth@10003000 device
Test: dm_test_eth_prime
Using eth@10003000 device
Using eth@10002000 device
Test: dm_test_eth_rotate
Error: eth@10004000 address not set.
Error: eth@10004000 address not set.
Using eth@10002000 device
Error: eth@10004000 address not set.
Error: eth@10004000 address not set.
Using eth@10004000 device
Test: dm_test_fdt
Device 'd-test': seq 3 is in use by 'b-test'
Test: dm_test_fdt_offset
Test: dm_test_fdt_pre_reloc
Test: dm_test_fdt_uclass_seq
Device 'd-test': seq 3 is in use by 'b-test'
Device 'a-test': seq 0 is in use by 'd-test'
Test: dm_test_gpio
extra-gpios: get_value: error: gpio b5 not reserved
Test: dm_test_gpio_anon
Test: dm_test_gpio_copy
Test: dm_test_gpio_leak
extra-gpios: get_value: error: gpio b5 not reserved
Test: dm_test_gpio_phandles
Test: dm_test_gpio_requestf
Test: dm_test_i2c_bytewise
Test: dm_test_i2c_find
Test: dm_test_i2c_offset
Test: dm_test_i2c_offset_len
Test: dm_test_i2c_probe_empty
Test: dm_test_i2c_read_write
Test: dm_test_i2c_speed
Test: dm_test_leak
Test: dm_test_lifecycle
Test: dm_test_net_retry
Using eth@10004000 device
Using eth@10002000 device
Using eth@10004000 device
Test: dm_test_operations
Test: dm_test_ordering
Test: dm_test_pci_base
Test: dm_test_pci_swapcase
Test: dm_test_platdata
Test: dm_test_pre_reloc
Test: dm_test_remove
Test: dm_test_spi_find
Invalid chip select 0:0 (err=-19)
SF: Failed to get idcodes
Device 'name-emul': seq 0 is in use by 'name-emul'
SF: Detected M25P16 with page size 256 Bytes, erase size 64 KiB, total 2 MiB
Test: dm_test_spi_flash
2097152 bytes written in 0 ms
@ -150,6 +189,9 @@ You should see something like this:
SF: Detected M25P16 with page size 256 Bytes, erase size 64 KiB, total 2 MiB
Test: dm_test_uclass
Test: dm_test_uclass_before_ready
Test: dm_test_usb_base
Test: dm_test_usb_flash
USB-1: scanning bus 1 for devices... 2 USB Device(s) found
Failures: 0

View File

@ -46,3 +46,12 @@ config DM_STDIO
Normally serial drivers register with stdio so that they can be used
as normal output devices. In SPL we don't normally use stdio, so
we can omit this feature.
config DM_SEQ_ALIAS
bool "Support numbered aliases in device tree"
depends on DM
default y
help
Most boards will have a '/aliases' node containing the path to
numbered devices (e.g. serial0 = &serial0). This feature can be
disabled if it is not required, to save code space in SPL.

View File

@ -92,6 +92,10 @@ int device_unbind(struct udevice *dev)
free(dev->platdata);
dev->platdata = NULL;
}
if (dev->flags & DM_FLAG_ALLOC_UCLASS_PDATA) {
free(dev->uclass_platdata);
dev->uclass_platdata = NULL;
}
if (dev->flags & DM_FLAG_ALLOC_PARENT_PDATA) {
free(dev->parent_platdata);
dev->parent_platdata = NULL;

View File

@ -30,7 +30,7 @@ int device_bind(struct udevice *parent, const struct driver *drv,
{
struct udevice *dev;
struct uclass *uc;
int ret = 0;
int size, ret = 0;
*devp = NULL;
if (!name)
@ -56,21 +56,23 @@ int device_bind(struct udevice *parent, const struct driver *drv,
dev->seq = -1;
dev->req_seq = -1;
#ifdef CONFIG_OF_CONTROL
/*
* Some devices, such as a SPI bus, I2C bus and serial ports are
* numbered using aliases.
*
* This is just a 'requested' sequence, and will be
* resolved (and ->seq updated) when the device is probed.
*/
if (uc->uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS) {
if (uc->uc_drv->name && of_offset != -1) {
fdtdec_get_alias_seq(gd->fdt_blob, uc->uc_drv->name,
of_offset, &dev->req_seq);
if (IS_ENABLED(CONFIG_OF_CONTROL) && IS_ENABLED(CONFIG_DM_SEQ_ALIAS)) {
/*
* Some devices, such as a SPI bus, I2C bus and serial ports
* are numbered using aliases.
*
* This is just a 'requested' sequence, and will be
* resolved (and ->seq updated) when the device is probed.
*/
if (uc->uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS) {
if (uc->uc_drv->name && of_offset != -1) {
fdtdec_get_alias_seq(gd->fdt_blob,
uc->uc_drv->name, of_offset,
&dev->req_seq);
}
}
}
#endif
if (!dev->platdata && drv->platdata_auto_alloc_size) {
dev->flags |= DM_FLAG_ALLOC_PDATA;
dev->platdata = calloc(1, drv->platdata_auto_alloc_size);
@ -79,9 +81,19 @@ int device_bind(struct udevice *parent, const struct driver *drv,
goto fail_alloc1;
}
}
if (parent) {
int size = parent->driver->per_child_platdata_auto_alloc_size;
size = uc->uc_drv->per_device_platdata_auto_alloc_size;
if (size) {
dev->flags |= DM_FLAG_ALLOC_UCLASS_PDATA;
dev->uclass_platdata = calloc(1, size);
if (!dev->uclass_platdata) {
ret = -ENOMEM;
goto fail_alloc2;
}
}
if (parent) {
size = parent->driver->per_child_platdata_auto_alloc_size;
if (!size) {
size = parent->uclass->uc_drv->
per_child_platdata_auto_alloc_size;
@ -91,7 +103,7 @@ int device_bind(struct udevice *parent, const struct driver *drv,
dev->parent_platdata = calloc(1, size);
if (!dev->parent_platdata) {
ret = -ENOMEM;
goto fail_alloc2;
goto fail_alloc3;
}
}
}
@ -123,21 +135,32 @@ int device_bind(struct udevice *parent, const struct driver *drv,
return 0;
fail_child_post_bind:
if (drv->unbind && drv->unbind(dev)) {
dm_warn("unbind() method failed on dev '%s' on error path\n",
dev->name);
if (IS_ENABLED(DM_DEVICE_REMOVE)) {
if (drv->unbind && drv->unbind(dev)) {
dm_warn("unbind() method failed on dev '%s' on error path\n",
dev->name);
}
}
fail_bind:
if (uclass_unbind_device(dev)) {
dm_warn("Failed to unbind dev '%s' on error path\n",
dev->name);
if (IS_ENABLED(DM_DEVICE_REMOVE)) {
if (uclass_unbind_device(dev)) {
dm_warn("Failed to unbind dev '%s' on error path\n",
dev->name);
}
}
fail_uclass_bind:
list_del(&dev->sibling_node);
if (dev->flags & DM_FLAG_ALLOC_PARENT_PDATA) {
free(dev->parent_platdata);
dev->parent_platdata = NULL;
if (IS_ENABLED(DM_DEVICE_REMOVE)) {
list_del(&dev->sibling_node);
if (dev->flags & DM_FLAG_ALLOC_PARENT_PDATA) {
free(dev->parent_platdata);
dev->parent_platdata = NULL;
}
}
fail_alloc3:
if (dev->flags & DM_FLAG_ALLOC_UCLASS_PDATA) {
free(dev->uclass_platdata);
dev->uclass_platdata = NULL;
}
fail_alloc2:
if (dev->flags & DM_FLAG_ALLOC_PDATA) {
@ -314,6 +337,16 @@ void *dev_get_parent_platdata(struct udevice *dev)
return dev->parent_platdata;
}
void *dev_get_uclass_platdata(struct udevice *dev)
{
if (!dev) {
dm_warn("%s: null device", __func__);
return NULL;
}
return dev->uclass_platdata;
}
void *dev_get_priv(struct udevice *dev)
{
if (!dev) {
@ -474,11 +507,27 @@ ulong dev_get_driver_data(struct udevice *dev)
return dev->driver_data;
}
const void *dev_get_driver_ops(struct udevice *dev)
{
if (!dev || !dev->driver->ops)
return NULL;
return dev->driver->ops;
}
enum uclass_id device_get_uclass_id(struct udevice *dev)
{
return dev->uclass->uc_drv->id;
}
const char *dev_get_uclass_name(struct udevice *dev)
{
if (!dev)
return NULL;
return dev->uclass->uc_drv->name;
}
#ifdef CONFIG_OF_CONTROL
fdt_addr_t dev_get_addr(struct udevice *dev)
{

View File

@ -197,13 +197,15 @@ int dm_init_and_scan(bool pre_reloc_only)
debug("dm_scan_platdata() failed: %d\n", ret);
return ret;
}
#ifdef CONFIG_OF_CONTROL
ret = dm_scan_fdt(gd->fdt_blob, pre_reloc_only);
if (ret) {
debug("dm_scan_fdt() failed: %d\n", ret);
return ret;
if (OF_CONTROL) {
ret = dm_scan_fdt(gd->fdt_blob, pre_reloc_only);
if (ret) {
debug("dm_scan_fdt() failed: %d\n", ret);
return ret;
}
}
#endif
ret = dm_scan_other(pre_reloc_only);
if (ret)
return ret;

View File

@ -99,10 +99,18 @@ fail_mem:
int uclass_destroy(struct uclass *uc)
{
struct uclass_driver *uc_drv;
struct udevice *dev, *tmp;
struct udevice *dev;
int ret;
list_for_each_entry_safe(dev, tmp, &uc->dev_head, uclass_node) {
/*
* We cannot use list_for_each_entry_safe() here. If a device in this
* uclass has a child device also in this uclass, it will be also be
* unbound (by the recursion in the call to device_unbind() below).
* We can loop until the list is empty.
*/
while (!list_empty(&uc->dev_head)) {
dev = list_first_entry(&uc->dev_head, struct udevice,
uclass_node);
ret = device_remove(dev);
if (ret)
return ret;
@ -156,6 +164,60 @@ int uclass_find_device(enum uclass_id id, int index, struct udevice **devp)
return -ENODEV;
}
int uclass_find_first_device(enum uclass_id id, struct udevice **devp)
{
struct uclass *uc;
int ret;
*devp = NULL;
ret = uclass_get(id, &uc);
if (ret)
return ret;
if (list_empty(&uc->dev_head))
return 0;
*devp = list_first_entry(&uc->dev_head, struct udevice, uclass_node);
return 0;
}
int uclass_find_next_device(struct udevice **devp)
{
struct udevice *dev = *devp;
*devp = NULL;
if (list_is_last(&dev->uclass_node, &dev->uclass->dev_head))
return 0;
*devp = list_entry(dev->uclass_node.next, struct udevice, uclass_node);
return 0;
}
int uclass_find_device_by_name(enum uclass_id id, const char *name,
struct udevice **devp)
{
struct uclass *uc;
struct udevice *dev;
int ret;
*devp = NULL;
if (!name)
return -EINVAL;
ret = uclass_get(id, &uc);
if (ret)
return ret;
list_for_each_entry(dev, &uc->dev_head, uclass_node) {
if (!strncmp(dev->name, name, strlen(name))) {
*devp = dev;
return 0;
}
}
return -ENODEV;
}
int uclass_find_device_by_seq(enum uclass_id id, int seq_or_req_seq,
bool find_req_seq, struct udevice **devp)
{
@ -209,17 +271,7 @@ static int uclass_find_device_by_of_offset(enum uclass_id id, int node,
return -ENODEV;
}
/**
* uclass_get_device_tail() - handle the end of a get_device call
*
* This handles returning an error or probing a device as needed.
*
* @dev: Device that needs to be probed
* @ret: Error to return. If non-zero then the device is not probed
* @devp: Returns the value of 'dev' if there is no error
* @return ret, if non-zero, else the result of the device_probe() call
*/
static int uclass_get_device_tail(struct udevice *dev, int ret,
int uclass_get_device_tail(struct udevice *dev, int ret,
struct udevice **devp)
{
if (ret)
@ -244,6 +296,17 @@ int uclass_get_device(enum uclass_id id, int index, struct udevice **devp)
return uclass_get_device_tail(dev, ret, devp);
}
int uclass_get_device_by_name(enum uclass_id id, const char *name,
struct udevice **devp)
{
struct udevice *dev;
int ret;
*devp = NULL;
ret = uclass_find_device_by_name(id, name, &dev);
return uclass_get_device_tail(dev, ret, devp);
}
int uclass_get_device_by_seq(enum uclass_id id, int seq, struct udevice **devp)
{
struct udevice *dev;
@ -274,24 +337,12 @@ int uclass_get_device_by_of_offset(enum uclass_id id, int node,
int uclass_first_device(enum uclass_id id, struct udevice **devp)
{
struct uclass *uc;
struct udevice *dev;
int ret;
*devp = NULL;
ret = uclass_get(id, &uc);
if (ret)
return ret;
if (list_empty(&uc->dev_head))
return 0;
dev = list_first_entry(&uc->dev_head, struct udevice, uclass_node);
ret = device_probe(dev);
if (ret)
return ret;
*devp = dev;
return 0;
ret = uclass_find_first_device(id, &dev);
return uclass_get_device_tail(dev, ret, devp);
}
int uclass_next_device(struct udevice **devp)
@ -300,17 +351,8 @@ int uclass_next_device(struct udevice **devp)
int ret;
*devp = NULL;
if (list_is_last(&dev->uclass_node, &dev->uclass->dev_head))
return 0;
dev = list_entry(dev->uclass_node.next, struct udevice,
uclass_node);
ret = device_probe(dev);
if (ret)
return ret;
*devp = dev;
return 0;
ret = uclass_find_next_device(&dev);
return uclass_get_device_tail(dev, ret, devp);
}
int uclass_bind_device(struct udevice *dev)
@ -344,6 +386,7 @@ err:
return ret;
}
#ifdef CONFIG_DM_DEVICE_REMOVE
int uclass_unbind_device(struct udevice *dev)
{
struct uclass *uc;
@ -359,6 +402,7 @@ int uclass_unbind_device(struct udevice *dev)
list_del(&dev->uclass_node);
return 0;
}
#endif
int uclass_resolve_seq(struct udevice *dev)
{
@ -422,6 +466,7 @@ int uclass_post_probe_device(struct udevice *dev)
return 0;
}
#ifdef CONFIG_DM_DEVICE_REMOVE
int uclass_pre_remove_device(struct udevice *dev)
{
struct uclass_driver *uc_drv;
@ -443,3 +488,4 @@ int uclass_pre_remove_device(struct udevice *dev)
return 0;
}
#endif

View File

@ -66,6 +66,16 @@ config DEBUG_UART_CLOCK
A default should be provided by your board, but if not you will need
to use the correct value here.
config DEBUG_UART_SHIFT
int "UART register shift"
depends on DEBUG_UART
default 0 if DEBUG_UART
help
Some UARTs (notably ns16550) support different register layouts
where the registers are spaced either as bytes, words or some other
value. Use this value to specify the shift to use, where 0=byte
registers, 2=32-bit word registers, etc.
config UNIPHIER_SERIAL
bool "UniPhier on-chip UART support"
depends on ARCH_UNIPHIER && DM_SERIAL

View File

@ -57,7 +57,7 @@ DECLARE_GLOBAL_DATA_PTR;
#ifdef CONFIG_DM_SERIAL
static inline void serial_out_shift(unsigned char *addr, int shift, int value)
static inline void serial_out_shift(void *addr, int shift, int value)
{
#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
outb(value, (ulong)addr);
@ -72,7 +72,7 @@ static inline void serial_out_shift(unsigned char *addr, int shift, int value)
#endif
}
static inline int serial_in_shift(unsigned char *addr, int shift)
static inline int serial_in_shift(void *addr, int shift)
{
#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
return inb((ulong)addr);
@ -114,9 +114,11 @@ static int ns16550_readb(NS16550_t port, int offset)
/* We can clean these up once everything is moved to driver model */
#define serial_out(value, addr) \
ns16550_writeb(com_port, addr - (unsigned char *)com_port, value)
ns16550_writeb(com_port, \
(unsigned char *)addr - (unsigned char *)com_port, value)
#define serial_in(addr) \
ns16550_readb(com_port, addr - (unsigned char *)com_port)
ns16550_readb(com_port, \
(unsigned char *)addr - (unsigned char *)com_port)
#endif
static inline int calc_divisor(NS16550_t port, int clock, int baudrate)
@ -173,7 +175,6 @@ void NS16550_init(NS16550_t com_port, int baud_divisor)
defined(CONFIG_TI81XX) || defined(CONFIG_AM43XX)
serial_out(0x7, &com_port->mdr1); /* mode select reset TL16C750*/
#endif
NS16550_setbrg(com_port, 0);
serial_out(UART_MCRVAL, &com_port->mcr);
serial_out(UART_FCRVAL, &com_port->fcr);
if (baud_divisor != -1)
@ -254,15 +255,20 @@ void debug_uart_init(void)
*/
baud_divisor = calc_divisor(com_port, CONFIG_DEBUG_UART_CLOCK,
CONFIG_BAUDRATE);
baud_divisor = 13;
serial_out_shift(&com_port->ier, CONFIG_DEBUG_UART_SHIFT,
CONFIG_SYS_NS16550_IER);
serial_out_shift(&com_port->mcr, CONFIG_DEBUG_UART_SHIFT, UART_MCRVAL);
serial_out_shift(&com_port->fcr, CONFIG_DEBUG_UART_SHIFT, UART_FCRVAL);
serial_out_shift(&com_port->ier, 0, CONFIG_SYS_NS16550_IER);
serial_out_shift(&com_port->mcr, 0, UART_MCRVAL);
serial_out_shift(&com_port->fcr, 0, UART_FCRVAL);
serial_out_shift(&com_port->lcr, 0, UART_LCR_BKSE | UART_LCRVAL);
serial_out_shift(&com_port->dll, 0, baud_divisor & 0xff);
serial_out_shift(&com_port->dlm, 0, (baud_divisor >> 8) & 0xff);
serial_out_shift(&com_port->lcr, 0, UART_LCRVAL);
serial_out_shift(&com_port->lcr, CONFIG_DEBUG_UART_SHIFT,
UART_LCR_BKSE | UART_LCRVAL);
serial_out_shift(&com_port->dll, CONFIG_DEBUG_UART_SHIFT,
baud_divisor & 0xff);
serial_out_shift(&com_port->dlm, CONFIG_DEBUG_UART_SHIFT,
(baud_divisor >> 8) & 0xff);
serial_out_shift(&com_port->lcr, CONFIG_DEBUG_UART_SHIFT,
UART_LCRVAL);
}
static inline void _debug_uart_putc(int ch)
@ -271,7 +277,7 @@ static inline void _debug_uart_putc(int ch)
while (!(serial_in_shift(&com_port->lsr, 0) & UART_LSR_THRE))
;
serial_out_shift(&com_port->thr, 0, ch);
serial_out_shift(&com_port->thr, CONFIG_DEBUG_UART_SHIFT, ch);
}
DEBUG_UART_FUNCS

View File

@ -70,7 +70,7 @@ static void serial_find_console_or_panic(void)
if (uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &dev) &&
uclass_get_device(UCLASS_SERIAL, INDEX, &dev) &&
(uclass_first_device(UCLASS_SERIAL, &dev) || !dev))
panic("No serial driver found");
panic_str("No serial driver found");
#undef INDEX
gd->cur_serial_dev = dev;
}

View File

@ -32,6 +32,7 @@ static struct usb_string hub_strings[] = {
{STRING_MANUFACTURER, "sandbox"},
{STRING_PRODUCT, "hub"},
{STRING_SERIAL, "2345"},
{},
};
static struct usb_device_descriptor hub_device_desc = {

View File

@ -1,9 +1,6 @@
#
# Device Tree Control
#
# TODO:
# This feature is not currently supported for SPL,
# but this restriction should be removed in the future.
config SUPPORT_OF_CONTROL
bool
@ -17,6 +14,14 @@ config OF_CONTROL
This feature provides for run-time configuration of U-Boot
via a flattened device tree.
config SPL_DISABLE_OF_CONTROL
bool "Disable run-time configuration via Device Tree in SPL"
depends on OF_CONTROL
help
Some boards use device tree in U-Boot but only have 4KB of SRAM
which is not enough to support device tree. Enable this option to
allow such boards to be supported by U-Boot SPL.
choice
prompt "Provider of DTB for DT control"
depends on OF_CONTROL

View File

@ -31,6 +31,7 @@
#undef CONFIG_DM_WARN
#undef CONFIG_DM_DEVICE_REMOVE
#undef CONFIG_DM_SEQ_ALIAS
#undef CONFIG_DM_STDIO
#endif /* CONFIG_SPL_BUILD */

View File

@ -30,8 +30,11 @@ struct driver_info;
/* DM is responsible for allocating and freeing parent_platdata */
#define DM_FLAG_ALLOC_PARENT_PDATA (1 << 3)
/* DM is responsible for allocating and freeing uclass_platdata */
#define DM_FLAG_ALLOC_UCLASS_PDATA (1 << 4)
/* Allocate driver private data on a DMA boundary */
#define DM_FLAG_ALLOC_PRIV_DMA (1 << 4)
#define DM_FLAG_ALLOC_PRIV_DMA (1 << 5)
/**
* struct udevice - An instance of a driver
@ -54,6 +57,7 @@ struct driver_info;
* @name: Name of device, typically the FDT node name
* @platdata: Configuration data for this device
* @parent_platdata: The parent bus's configuration data for this device
* @uclass_platdata: The uclass's configuration data for this device
* @of_offset: Device tree node offset for this device (- for none)
* @driver_data: Driver data word for the entry that matched this device with
* its driver
@ -75,6 +79,7 @@ struct udevice {
const char *name;
void *platdata;
void *parent_platdata;
void *uclass_platdata;
int of_offset;
ulong driver_data;
struct udevice *parent;
@ -209,6 +214,16 @@ void *dev_get_platdata(struct udevice *dev);
*/
void *dev_get_parent_platdata(struct udevice *dev);
/**
* dev_get_uclass_platdata() - Get the uclass platform data for a device
*
* This checks that dev is not NULL, but no other checks for now
*
* @dev Device to check
* @return uclass's platform data, or NULL if none
*/
void *dev_get_uclass_platdata(struct udevice *dev);
/**
* dev_get_parentdata() - Get the parent data for a device
*
@ -265,6 +280,17 @@ void *dev_get_uclass_priv(struct udevice *dev);
*/
ulong dev_get_driver_data(struct udevice *dev);
/**
* dev_get_driver_ops() - get the device's driver's operations
*
* This checks that dev is not NULL, and returns the pointer to device's
* driver's operations.
*
* @dev: Device to check
* @return void pointer to driver's operations or NULL for NULL-dev or NULL-ops
*/
const void *dev_get_driver_ops(struct udevice *dev);
/*
* device_get_uclass_id() - return the uclass ID of a device
*
@ -273,6 +299,16 @@ ulong dev_get_driver_data(struct udevice *dev);
*/
enum uclass_id device_get_uclass_id(struct udevice *dev);
/*
* dev_get_uclass_name() - return the uclass name of a device
*
* This checks that dev is not NULL.
*
* @dev: Device to check
* @return pointer to the uclass name for the device
*/
const char *dev_get_uclass_name(struct udevice *dev);
/**
* device_get_child() - Get the child of a device by index
*

View File

@ -98,6 +98,26 @@ struct dm_test_parent_data {
int flag;
};
/* Test values for test device's uclass platform data */
enum {
TEST_UC_PDATA_INTVAL1 = 2,
TEST_UC_PDATA_INTVAL2 = 334,
TEST_UC_PDATA_INTVAL3 = 789452,
};
/**
* struct dm_test_uclass_platda - uclass's information on each device
*
* @intval1: set to TEST_UC_PDATA_INTVAL1 in .post_bind method of test uclass
* @intval2: set to TEST_UC_PDATA_INTVAL2 in .post_bind method of test uclass
* @intval3: set to TEST_UC_PDATA_INTVAL3 in .post_bind method of test uclass
*/
struct dm_test_perdev_uc_pdata {
int intval1;
int intval2;
int intval3;
};
/*
* Operation counts for the test driver, used to check that each method is
* called correctly

View File

@ -10,19 +10,94 @@
#ifndef _DM_UCLASS_INTERNAL_H
#define _DM_UCLASS_INTERNAL_H
/**
* uclass_get_device_tail() - handle the end of a get_device call
*
* This handles returning an error or probing a device as needed.
*
* @dev: Device that needs to be probed
* @ret: Error to return. If non-zero then the device is not probed
* @devp: Returns the value of 'dev' if there is no error
* @return ret, if non-zero, else the result of the device_probe() call
*/
int uclass_get_device_tail(struct udevice *dev, int ret, struct udevice **devp);
/**
* uclass_find_device() - Return n-th child of uclass
* @id: Id number of the uclass
* @index: Position of the child in uclass's list
* #devp: Returns pointer to device, or NULL on error
*
* The device is not prepared for use - this is an internal function
* The device is not prepared for use - this is an internal function.
* The function uclass_get_device_tail() can be used to probe the device.
*
* @return the uclass pointer of a child at the given index or
* return NULL on error.
*/
int uclass_find_device(enum uclass_id id, int index, struct udevice **devp);
/**
* uclass_find_first_device() - Return the first device in a uclass
* @id: Id number of the uclass
* #devp: Returns pointer to device, or NULL on error
*
* The device is not prepared for use - this is an internal function.
* The function uclass_get_device_tail() can be used to probe the device.
*
* @return 0 if OK (found or not found), -1 on error
*/
int uclass_find_first_device(enum uclass_id id, struct udevice **devp);
/**
* uclass_find_next_device() - Return the next device in a uclass
* @devp: On entry, pointer to device to lookup. On exit, returns pointer
* to the next device in the same uclass, or NULL if none
*
* The device is not prepared for use - this is an internal function.
* The function uclass_get_device_tail() can be used to probe the device.
*
* @return 0 if OK (found or not found), -1 on error
*/
int uclass_find_next_device(struct udevice **devp);
/**
* uclass_find_device_by_name() - Find uclass device based on ID and name
*
* This searches for a device with the exactly given name.
*
* The device is NOT probed, it is merely returned.
*
* @id: ID to look up
* @name: name of a device to find
* @devp: Returns pointer to device (the first one with the name)
* @return 0 if OK, -ve on error
*/
int uclass_find_device_by_name(enum uclass_id id, const char *name,
struct udevice **devp);
/**
* uclass_find_device_by_seq() - Find uclass device based on ID and sequence
*
* This searches for a device with the given seq or req_seq.
*
* For seq, if an active device has this sequence it will be returned.
* If there is no such device then this will return -ENODEV.
*
* For req_seq, if a device (whether activated or not) has this req_seq
* value, that device will be returned. This is a strong indication that
* the device will receive that sequence when activated.
*
* The device is NOT probed, it is merely returned.
*
* @id: ID to look up
* @seq_or_req_seq: Sequence number to find (0=first)
* @find_req_seq: true to find req_seq, false to find seq
* @devp: Returns pointer to device (there is only one per for each seq)
* @return 0 if OK, -ve on error
*/
int uclass_find_device_by_seq(enum uclass_id id, int seq_or_req_seq,
bool find_req_seq, struct udevice **devp);
/**
* uclass_bind_device() - Associate device with a uclass
*
@ -41,7 +116,11 @@ int uclass_bind_device(struct udevice *dev);
* @dev: Pointer to the device
* #return 0 on success, -ve on error
*/
#ifdef CONFIG_DM_DEVICE_REMOVE
int uclass_unbind_device(struct udevice *dev);
#else
static inline int uclass_unbind_device(struct udevice *dev) { return 0; }
#endif
/**
* uclass_pre_probe_device() - Deal with a device that is about to be probed
@ -74,7 +153,11 @@ int uclass_post_probe_device(struct udevice *dev);
* @dev: Pointer to the device
* #return 0 on success, -ve on error
*/
#ifdef CONFIG_DM_DEVICE_REMOVE
int uclass_pre_remove_device(struct udevice *dev);
#else
static inline int uclass_pre_remove_device(struct udevice *dev) { return 0; }
#endif
/**
* uclass_find() - Find uclass by its id
@ -94,27 +177,4 @@ struct uclass *uclass_find(enum uclass_id key);
*/
int uclass_destroy(struct uclass *uc);
/**
* uclass_find_device_by_seq() - Find uclass device based on ID and sequence
*
* This searches for a device with the given seq or req_seq.
*
* For seq, if an active device has this sequence it will be returned.
* If there is no such device then this will return -ENODEV.
*
* For req_seq, if a device (whether activated or not) has this req_seq
* value, that device will be returned. This is a strong indication that
* the device will receive that sequence when activated.
*
* The device is NOT probed, it is merely returned.
*
* @id: ID to look up
* @seq_or_req_seq: Sequence number to find (0=first)
* @find_req_seq: true to find req_seq, false to find seq
* @devp: Returns pointer to device (there is only one per for each seq)
* @return 0 if OK, -ve on error
*/
int uclass_find_device_by_seq(enum uclass_id id, int seq_or_req_seq,
bool find_req_seq, struct udevice **devp);
#endif

View File

@ -65,6 +65,9 @@ struct udevice;
* @per_device_auto_alloc_size: Each device can hold private data owned
* by the uclass. If required this will be automatically allocated if this
* value is non-zero.
* @per_device_platdata_auto_alloc_size: Each device can hold platform data
* owned by the uclass as 'dev->uclass_platdata'. If the value is non-zero,
* then this will be automatically allocated.
* @per_child_auto_alloc_size: Each child device (of a parent in this
* uclass) can hold parent data for the device/uclass. This value is only
* used as a falback if this member is 0 in the driver.
@ -90,6 +93,7 @@ struct uclass_driver {
int (*destroy)(struct uclass *class);
int priv_auto_alloc_size;
int per_device_auto_alloc_size;
int per_device_platdata_auto_alloc_size;
int per_child_auto_alloc_size;
int per_child_platdata_auto_alloc_size;
const void *ops;
@ -125,6 +129,21 @@ int uclass_get(enum uclass_id key, struct uclass **ucp);
*/
int uclass_get_device(enum uclass_id id, int index, struct udevice **devp);
/**
* uclass_get_device_by_name() - Get a uclass device by it's name
*
* This searches the devices in the uclass for one with the exactly given name.
*
* The device is probed to activate it ready for use.
*
* @id: ID to look up
* @name: name of a device to get
* @devp: Returns pointer to device (the first one with the name)
* @return 0 if OK, -ve on error
*/
int uclass_get_device_by_name(enum uclass_id id, const char *name,
struct udevice **devp);
/**
* uclass_get_device_by_seq() - Get a uclass device based on an ID and sequence
*

View File

@ -41,6 +41,16 @@ struct fdt_memory {
fdt_addr_t end;
};
#ifdef CONFIG_OF_CONTROL
# if defined(CONFIG_SPL_BUILD) && defined(SPL_DISABLE_OF_CONTROL)
# define OF_CONTROL 0
# else
# define OF_CONTROL 1
# endif
#else
# define OF_CONTROL 0
#endif
/*
* Information about a resource. start is the first address of the resource
* and end is the last address (inclusive). The length of the resource will
@ -793,4 +803,10 @@ int fdt_get_named_resource(const void *fdt, int node, const char *property,
int fdtdec_decode_memory_region(const void *blob, int node,
const char *mem_type, const char *suffix,
fdt_addr_t *basep, fdt_size_t *sizep);
/**
* Set up the device tree ready for use
*/
int fdtdec_setup(void);
#endif

View File

@ -906,6 +906,9 @@ void *realloc_simple(void *ptr, size_t size);
#endif
/* Set up pre-relocation malloc() ready for use */
int initf_malloc(void);
/* Public routines */
/* Simple versions which can be used when space is tight */

View File

@ -39,9 +39,32 @@ int strict_strtoul(const char *cp, unsigned int base, unsigned long *res);
unsigned long long simple_strtoull(const char *cp, char **endp,
unsigned int base);
long simple_strtol(const char *cp, char **endp, unsigned int base);
/**
* panic() - Print a message and reset/hang
*
* Prints a message on the console(s) and then resets. If CONFIG_PANIC_HANG is
* defined, then it will hang instead of reseting.
*
* @param fmt: printf() format string for message, which should not include
* \n, followed by arguments
*/
void panic(const char *fmt, ...)
__attribute__ ((format (__printf__, 1, 2), noreturn));
/**
* panic_str() - Print a message and reset/hang
*
* Prints a message on the console(s) and then resets. If CONFIG_PANIC_HANG is
* defined, then it will hang instead of reseting.
*
* This function can be used instead of panic() when your board does not
* already use printf(), * to keep code size small.
*
* @param fmt: string to display, which should not include \n
*/
void panic_str(const char *str) __attribute__ ((noreturn));
/**
* Format a string and place it in a buffer
*

View File

@ -44,6 +44,12 @@ obj-$(CONFIG_BITREVERSE) += bitrev.o
obj-y += list_sort.o
endif
ifndef CONFIG_SPL_DISABLE_OF_CONTROL
obj-$(CONFIG_OF_LIBFDT) += libfdt/
obj-$(CONFIG_OF_CONTROL) += fdtdec_common.o
obj-$(CONFIG_OF_CONTROL) += fdtdec.o
endif
ifdef CONFIG_SPL_BUILD
obj-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16.o
obj-$(CONFIG_SPL_NET_SUPPORT) += net_utils.o

View File

@ -9,6 +9,7 @@
#include <serial.h>
#include <libfdt.h>
#include <fdtdec.h>
#include <asm/sections.h>
#include <linux/ctype.h>
DECLARE_GLOBAL_DATA_PTR;
@ -565,9 +566,11 @@ int fdtdec_prepare_fdt(void)
{
if (!gd->fdt_blob || ((uintptr_t)gd->fdt_blob & 3) ||
fdt_check_header(gd->fdt_blob)) {
printf("No valid FDT found - please append one to U-Boot "
"binary, use u-boot-dtb.bin or define "
"CONFIG_OF_EMBED. For sandbox, use -d <file.dtb>\n");
#ifdef CONFIG_SPL_BUILD
puts("Missing DTB\n");
#else
puts("No valid device tree binary found - please append one to U-Boot binary, use u-boot-dtb.bin or define CONFIG_OF_EMBED. For sandbox, use -d <file.dtb>\n");
#endif
return -1;
}
return 0;
@ -1035,4 +1038,34 @@ int fdtdec_decode_memory_region(const void *blob, int config_node,
return 0;
}
int fdtdec_setup(void)
{
#ifdef CONFIG_OF_CONTROL
# ifdef CONFIG_OF_EMBED
/* Get a pointer to the FDT */
gd->fdt_blob = __dtb_dt_begin;
# elif defined CONFIG_OF_SEPARATE
# ifdef CONFIG_SPL_BUILD
/* FDT is at end of BSS */
gd->fdt_blob = (ulong *)&__bss_end;
# else
/* FDT is at end of image */
gd->fdt_blob = (ulong *)&_end;
#endif
# elif defined(CONFIG_OF_HOSTFILE)
if (sandbox_read_fdt_from_file()) {
puts("Failed to read control FDT\n");
return -1;
}
# endif
# ifndef CONFIG_SPL_BUILD
/* Allow the early environment to override the fdt address */
gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,
(uintptr_t)gd->fdt_blob);
# endif
#endif
return fdtdec_prepare_fdt();
}
#endif /* !USE_HOSTCC */

View File

@ -842,13 +842,11 @@ int sprintf(char *buf, const char *fmt, ...)
return i;
}
void panic(const char *fmt, ...)
static void panic_finish(void) __attribute__ ((noreturn));
static void panic_finish(void)
{
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
putc('\n');
va_end(args);
#if defined(CONFIG_PANIC_HANG)
hang();
#else
@ -859,6 +857,21 @@ void panic(const char *fmt, ...)
;
}
void panic_str(const char *str)
{
puts(str);
panic_finish();
}
void panic(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
panic_finish();
}
void __assert_fail(const char *assertion, const char *file, unsigned line,
const char *function)
{

View File

@ -129,6 +129,61 @@ static int dm_test_autobind(struct dm_test_state *dms)
}
DM_TEST(dm_test_autobind, 0);
/* Test that binding with uclass platdata allocation occurs correctly */
static int dm_test_autobind_uclass_pdata_alloc(struct dm_test_state *dms)
{
struct dm_test_perdev_uc_pdata *uc_pdata;
struct udevice *dev;
struct uclass *uc;
ut_assertok(uclass_get(UCLASS_TEST, &uc));
ut_assert(uc);
/**
* Test if test uclass driver requires allocation for the uclass
* platform data and then check the dev->uclass_platdata pointer.
*/
ut_assert(uc->uc_drv->per_device_platdata_auto_alloc_size);
for (uclass_find_first_device(UCLASS_TEST, &dev);
dev;
uclass_find_next_device(&dev)) {
ut_assert(dev);
uc_pdata = dev_get_uclass_platdata(dev);
ut_assert(uc_pdata);
}
return 0;
}
DM_TEST(dm_test_autobind_uclass_pdata_alloc, DM_TESTF_SCAN_PDATA);
/* Test that binding with uclass platdata setting occurs correctly */
static int dm_test_autobind_uclass_pdata_valid(struct dm_test_state *dms)
{
struct dm_test_perdev_uc_pdata *uc_pdata;
struct udevice *dev;
/**
* In the test_postbind() method of test uclass driver, the uclass
* platform data should be set to three test int values - test it.
*/
for (uclass_find_first_device(UCLASS_TEST, &dev);
dev;
uclass_find_next_device(&dev)) {
ut_assert(dev);
uc_pdata = dev_get_uclass_platdata(dev);
ut_assert(uc_pdata);
ut_assert(uc_pdata->intval1 == TEST_UC_PDATA_INTVAL1);
ut_assert(uc_pdata->intval2 == TEST_UC_PDATA_INTVAL2);
ut_assert(uc_pdata->intval3 == TEST_UC_PDATA_INTVAL3);
}
return 0;
}
DM_TEST(dm_test_autobind_uclass_pdata_valid, DM_TESTF_SCAN_PDATA);
/* Test that autoprobe finds all the expected devices */
static int dm_test_autoprobe(struct dm_test_state *dms)
{
@ -596,14 +651,130 @@ static int dm_test_uclass_before_ready(struct dm_test_state *dms)
ut_assertok(uclass_get(UCLASS_TEST, &uc));
memset(gd, '\0', sizeof(*gd));
gd->dm_root = NULL;
gd->dm_root_f = NULL;
memset(&gd->uclass_root, '\0', sizeof(gd->uclass_root));
ut_asserteq_ptr(NULL, uclass_find(UCLASS_TEST));
return 0;
}
DM_TEST(dm_test_uclass_before_ready, 0);
static int dm_test_uclass_devices_find(struct dm_test_state *dms)
{
struct udevice *dev;
int ret;
for (ret = uclass_find_first_device(UCLASS_TEST, &dev);
dev;
ret = uclass_find_next_device(&dev)) {
ut_assert(!ret);
ut_assert(dev);
}
return 0;
}
DM_TEST(dm_test_uclass_devices_find, DM_TESTF_SCAN_PDATA);
static int dm_test_uclass_devices_find_by_name(struct dm_test_state *dms)
{
struct udevice *finddev;
struct udevice *testdev;
int findret, ret;
/*
* For each test device found in fdt like: "a-test", "b-test", etc.,
* use its name and try to find it by uclass_find_device_by_name().
* Then, on success check if:
* - current 'testdev' name is equal to the returned 'finddev' name
* - current 'testdev' pointer is equal to the returned 'finddev'
*
* We assume that, each uclass's device name is unique, so if not, then
* this will fail on checking condition: testdev == finddev, since the
* uclass_find_device_by_name(), returns the first device by given name.
*/
for (ret = uclass_find_first_device(UCLASS_TEST_FDT, &testdev);
testdev;
ret = uclass_find_next_device(&testdev)) {
ut_assertok(ret);
ut_assert(testdev);
findret = uclass_find_device_by_name(UCLASS_TEST_FDT,
testdev->name,
&finddev);
ut_assertok(findret);
ut_assert(testdev);
ut_asserteq_str(testdev->name, finddev->name);
ut_asserteq_ptr(testdev, finddev);
}
return 0;
}
DM_TEST(dm_test_uclass_devices_find_by_name, DM_TESTF_SCAN_FDT);
static int dm_test_uclass_devices_get(struct dm_test_state *dms)
{
struct udevice *dev;
int ret;
for (ret = uclass_first_device(UCLASS_TEST, &dev);
dev;
ret = uclass_next_device(&dev)) {
ut_assert(!ret);
ut_assert(dev);
ut_assert(device_active(dev));
}
return 0;
}
DM_TEST(dm_test_uclass_devices_get, DM_TESTF_SCAN_PDATA);
static int dm_test_uclass_devices_get_by_name(struct dm_test_state *dms)
{
struct udevice *finddev;
struct udevice *testdev;
int ret, findret;
/*
* For each test device found in fdt like: "a-test", "b-test", etc.,
* use its name and try to get it by uclass_get_device_by_name().
* On success check if:
* - returned finddev' is active
* - current 'testdev' name is equal to the returned 'finddev' name
* - current 'testdev' pointer is equal to the returned 'finddev'
*
* We asserts that the 'testdev' is active on each loop entry, so we
* could be sure that the 'finddev' is activated too, but for sure
* we check it again.
*
* We assume that, each uclass's device name is unique, so if not, then
* this will fail on checking condition: testdev == finddev, since the
* uclass_get_device_by_name(), returns the first device by given name.
*/
for (ret = uclass_first_device(UCLASS_TEST_FDT, &testdev);
testdev;
ret = uclass_next_device(&testdev)) {
ut_assertok(ret);
ut_assert(testdev);
ut_assert(device_active(testdev));
findret = uclass_get_device_by_name(UCLASS_TEST_FDT,
testdev->name,
&finddev);
ut_assertok(findret);
ut_assert(finddev);
ut_assert(device_active(finddev));
ut_asserteq_str(testdev->name, finddev->name);
ut_asserteq_ptr(testdev, finddev);
}
return 0;
}
DM_TEST(dm_test_uclass_devices_get_by_name, DM_TESTF_SCAN_FDT);
static int dm_test_device_get_uclass_id(struct dm_test_state *dms)
{
struct udevice *dev;

View File

@ -30,9 +30,18 @@ int test_ping(struct udevice *dev, int pingval, int *pingret)
static int test_post_bind(struct udevice *dev)
{
struct dm_test_perdev_uc_pdata *uc_pdata;
dm_testdrv_op_count[DM_TEST_OP_POST_BIND]++;
ut_assert(!device_active(dev));
uc_pdata = dev_get_uclass_platdata(dev);
ut_assert(uc_pdata);
uc_pdata->intval1 = TEST_UC_PDATA_INTVAL1;
uc_pdata->intval2 = TEST_UC_PDATA_INTVAL2;
uc_pdata->intval3 = TEST_UC_PDATA_INTVAL3;
return 0;
}
@ -115,4 +124,6 @@ UCLASS_DRIVER(test) = {
.destroy = test_destroy,
.priv_auto_alloc_size = sizeof(struct dm_test_uclass_priv),
.per_device_auto_alloc_size = sizeof(struct dm_test_uclass_perdev_priv),
.per_device_platdata_auto_alloc_size =
sizeof(struct dm_test_perdev_uc_pdata),
};