mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-13 15:03:58 +03:00
Merge branch 'master' of git://git.denx.de/u-boot-dm
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
Reference in New Issue
Block a user