Commit 15fd1b7903a3090a03cfe453f661822a613a91ee

Authored by Tom Rini

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

Showing 19 changed files Side-by-side Diff

arch/arm/mach-rockchip/rk3188-board-spl.c
... ... @@ -49,7 +49,7 @@
49 49 debug("node=%d\n", node);
50 50 goto fallback;
51 51 }
52   - ret = device_get_global_by_of_offset(node, &dev);
  52 + ret = device_get_global_by_ofnode(offset_to_ofnode(node), &dev);
53 53 if (ret) {
54 54 debug("device at node %s/%d not found: %d\n", bootdev, node,
55 55 ret);
arch/arm/mach-rockchip/rk3288-board-spl.c
... ... @@ -51,7 +51,7 @@
51 51 debug("node=%d\n", node);
52 52 goto fallback;
53 53 }
54   - ret = device_get_global_by_of_offset(node, &dev);
  54 + ret = device_get_global_by_ofnode(offset_to_ofnode(node), &dev);
55 55 if (ret) {
56 56 debug("device at node %s/%d not found: %d\n", bootdev, node,
57 57 ret);
arch/sandbox/dts/test.dts
... ... @@ -61,6 +61,17 @@
61 61 reg = <2 1>;
62 62 };
63 63  
  64 + bind-test {
  65 + bind-test-child1 {
  66 + compatible = "sandbox,phy";
  67 + #phy-cells = <1>;
  68 + };
  69 +
  70 + bind-test-child2 {
  71 + compatible = "simple-bus";
  72 + };
  73 + };
  74 +
64 75 b-test {
65 76 reg = <3 1>;
66 77 compatible = "denx,u-boot-fdt-test";
... ... @@ -615,6 +615,15 @@
615 615 Shows ADC device info and permit printing one-shot analog converted
616 616 data from a named Analog to Digital Converter.
617 617  
  618 +config CMD_BIND
  619 + bool "bind/unbind - Bind or unbind a device to/from a driver"
  620 + depends on DM
  621 + help
  622 + Bind or unbind a device to/from a driver from the command line.
  623 + This is useful in situations where a device may be handled by several
  624 + drivers. For example, this can be used to bind a UDC to the usb ether
  625 + gadget driver from the command line.
  626 +
618 627 config CMD_CLK
619 628 bool "clk - Show clock frequencies"
620 629 help
... ... @@ -19,6 +19,7 @@
19 19 obj-$(CONFIG_CMD_SOURCE) += source.o
20 20 obj-$(CONFIG_CMD_BDI) += bdinfo.o
21 21 obj-$(CONFIG_CMD_BEDBUG) += bedbug.o
  22 +obj-$(CONFIG_CMD_BIND) += bind.o
22 23 obj-$(CONFIG_CMD_BINOP) += binop.o
23 24 obj-$(CONFIG_CMD_BLOCK_CACHE) += blkcache.o
24 25 obj-$(CONFIG_CMD_BMP) += bmp.o
  1 +// SPDX-License-Identifier: GPL-2.0+
  2 +/*
  3 + * Copyright (c) 2018 JJ Hiblot <jjhiblot@ti.com>
  4 + */
  5 +
  6 +#include <common.h>
  7 +#include <dm.h>
  8 +#include <dm/device-internal.h>
  9 +#include <dm/lists.h>
  10 +#include <dm/uclass-internal.h>
  11 +
  12 +static int bind_by_class_index(const char *uclass, int index,
  13 + const char *drv_name)
  14 +{
  15 + static enum uclass_id uclass_id;
  16 + struct udevice *dev;
  17 + struct udevice *parent;
  18 + int ret;
  19 + struct driver *drv;
  20 +
  21 + drv = lists_driver_lookup_name(drv_name);
  22 + if (!drv) {
  23 + printf("Cannot find driver '%s'\n", drv_name);
  24 + return -ENOENT;
  25 + }
  26 +
  27 + uclass_id = uclass_get_by_name(uclass);
  28 + if (uclass_id == UCLASS_INVALID) {
  29 + printf("%s is not a valid uclass\n", uclass);
  30 + return -EINVAL;
  31 + }
  32 +
  33 + ret = uclass_find_device(uclass_id, index, &parent);
  34 + if (!parent || ret) {
  35 + printf("Cannot find device %d of class %s\n", index, uclass);
  36 + return ret;
  37 + }
  38 +
  39 + ret = device_bind_with_driver_data(parent, drv, drv->name, 0,
  40 + ofnode_null(), &dev);
  41 + if (!dev || ret) {
  42 + printf("Unable to bind. err:%d\n", ret);
  43 + return ret;
  44 + }
  45 +
  46 + return 0;
  47 +}
  48 +
  49 +static int find_dev(const char *uclass, int index, struct udevice **devp)
  50 +{
  51 + static enum uclass_id uclass_id;
  52 + int rc;
  53 +
  54 + uclass_id = uclass_get_by_name(uclass);
  55 + if (uclass_id == UCLASS_INVALID) {
  56 + printf("%s is not a valid uclass\n", uclass);
  57 + return -EINVAL;
  58 + }
  59 +
  60 + rc = uclass_find_device(uclass_id, index, devp);
  61 + if (!*devp || rc) {
  62 + printf("Cannot find device %d of class %s\n", index, uclass);
  63 + return rc;
  64 + }
  65 +
  66 + return 0;
  67 +}
  68 +
  69 +static int unbind_by_class_index(const char *uclass, int index)
  70 +{
  71 + int ret;
  72 + struct udevice *dev;
  73 +
  74 + ret = find_dev(uclass, index, &dev);
  75 + if (ret)
  76 + return ret;
  77 +
  78 + ret = device_remove(dev, DM_REMOVE_NORMAL);
  79 + if (ret) {
  80 + printf("Unable to remove. err:%d\n", ret);
  81 + return ret;
  82 + }
  83 +
  84 + ret = device_unbind(dev);
  85 + if (ret) {
  86 + printf("Unable to unbind. err:%d\n", ret);
  87 + return ret;
  88 + }
  89 +
  90 + return 0;
  91 +}
  92 +
  93 +static int unbind_child_by_class_index(const char *uclass, int index,
  94 + const char *drv_name)
  95 +{
  96 + struct udevice *parent;
  97 + int ret;
  98 + struct driver *drv;
  99 +
  100 + drv = lists_driver_lookup_name(drv_name);
  101 + if (!drv) {
  102 + printf("Cannot find driver '%s'\n", drv_name);
  103 + return -ENOENT;
  104 + }
  105 +
  106 + ret = find_dev(uclass, index, &parent);
  107 + if (ret)
  108 + return ret;
  109 +
  110 + ret = device_chld_remove(parent, drv, DM_REMOVE_NORMAL);
  111 + if (ret)
  112 + printf("Unable to remove all. err:%d\n", ret);
  113 +
  114 + ret = device_chld_unbind(parent, drv);
  115 + if (ret)
  116 + printf("Unable to unbind all. err:%d\n", ret);
  117 +
  118 + return ret;
  119 +}
  120 +
  121 +static int bind_by_node_path(const char *path, const char *drv_name)
  122 +{
  123 + struct udevice *dev;
  124 + struct udevice *parent = NULL;
  125 + int ret;
  126 + ofnode ofnode;
  127 + struct driver *drv;
  128 +
  129 + drv = lists_driver_lookup_name(drv_name);
  130 + if (!drv) {
  131 + printf("%s is not a valid driver name\n", drv_name);
  132 + return -ENOENT;
  133 + }
  134 +
  135 + ofnode = ofnode_path(path);
  136 + if (!ofnode_valid(ofnode)) {
  137 + printf("%s is not a valid node path\n", path);
  138 + return -EINVAL;
  139 + }
  140 +
  141 + while (ofnode_valid(ofnode)) {
  142 + if (!device_find_global_by_ofnode(ofnode, &parent))
  143 + break;
  144 + ofnode = ofnode_get_parent(ofnode);
  145 + }
  146 +
  147 + if (!parent) {
  148 + printf("Cannot find a parent device for node path %s\n", path);
  149 + return -ENODEV;
  150 + }
  151 +
  152 + ofnode = ofnode_path(path);
  153 + ret = device_bind_with_driver_data(parent, drv, ofnode_get_name(ofnode),
  154 + 0, ofnode, &dev);
  155 + if (!dev || ret) {
  156 + printf("Unable to bind. err:%d\n", ret);
  157 + return ret;
  158 + }
  159 +
  160 + return 0;
  161 +}
  162 +
  163 +static int unbind_by_node_path(const char *path)
  164 +{
  165 + struct udevice *dev;
  166 + int ret;
  167 + ofnode ofnode;
  168 +
  169 + ofnode = ofnode_path(path);
  170 + if (!ofnode_valid(ofnode)) {
  171 + printf("%s is not a valid node path\n", path);
  172 + return -EINVAL;
  173 + }
  174 +
  175 + ret = device_find_global_by_ofnode(ofnode, &dev);
  176 +
  177 + if (!dev || ret) {
  178 + printf("Cannot find a device with path %s\n", path);
  179 + return -ENODEV;
  180 + }
  181 +
  182 + ret = device_remove(dev, DM_REMOVE_NORMAL);
  183 + if (ret) {
  184 + printf("Unable to remove. err:%d\n", ret);
  185 + return ret;
  186 + }
  187 +
  188 + ret = device_unbind(dev);
  189 + if (ret) {
  190 + printf("Unable to unbind. err:%d\n", ret);
  191 + return ret;
  192 + }
  193 +
  194 + return 0;
  195 +}
  196 +
  197 +static int do_bind_unbind(cmd_tbl_t *cmdtp, int flag, int argc,
  198 + char * const argv[])
  199 +{
  200 + int ret = 0;
  201 + bool bind;
  202 + bool by_node;
  203 +
  204 + if (argc < 2)
  205 + return CMD_RET_USAGE;
  206 +
  207 + bind = (argv[0][0] == 'b');
  208 + by_node = (argv[1][0] == '/');
  209 +
  210 + if (by_node && bind) {
  211 + if (argc != 3)
  212 + return CMD_RET_USAGE;
  213 + ret = bind_by_node_path(argv[1], argv[2]);
  214 + } else if (by_node && !bind) {
  215 + if (argc != 2)
  216 + return CMD_RET_USAGE;
  217 + ret = unbind_by_node_path(argv[1]);
  218 + } else if (!by_node && bind) {
  219 + int index = (argc > 2) ? simple_strtoul(argv[2], NULL, 10) : 0;
  220 +
  221 + if (argc != 4)
  222 + return CMD_RET_USAGE;
  223 + ret = bind_by_class_index(argv[1], index, argv[3]);
  224 + } else if (!by_node && !bind) {
  225 + int index = (argc > 2) ? simple_strtoul(argv[2], NULL, 10) : 0;
  226 +
  227 + if (argc == 3)
  228 + ret = unbind_by_class_index(argv[1], index);
  229 + else if (argc == 4)
  230 + ret = unbind_child_by_class_index(argv[1], index,
  231 + argv[3]);
  232 + else
  233 + return CMD_RET_USAGE;
  234 + }
  235 +
  236 + if (ret)
  237 + return CMD_RET_FAILURE;
  238 + else
  239 + return CMD_RET_SUCCESS;
  240 +}
  241 +
  242 +U_BOOT_CMD(
  243 + bind, 4, 0, do_bind_unbind,
  244 + "Bind a device to a driver",
  245 + "<node path> <driver>\n"
  246 + "bind <class> <index> <driver>\n"
  247 +);
  248 +
  249 +U_BOOT_CMD(
  250 + unbind, 4, 0, do_bind_unbind,
  251 + "Unbind a device from a driver",
  252 + "<node path>\n"
  253 + "unbind <class> <index>\n"
  254 + "unbind <class> <index> <driver>\n"
  255 +);
... ... @@ -38,13 +38,18 @@
38 38 #if CONFIG_IS_ENABLED(USB_FUNCTION_FASTBOOT)
39 39 int controller_index;
40 40 char *usb_controller;
  41 + char *endp;
41 42 int ret;
42 43  
43 44 if (argc < 2)
44 45 return CMD_RET_USAGE;
45 46  
46 47 usb_controller = argv[1];
47   - controller_index = simple_strtoul(usb_controller, NULL, 0);
  48 + controller_index = simple_strtoul(usb_controller, &endp, 0);
  49 + if (*endp != '\0') {
  50 + pr_err("Error: Wrong USB controller index format\n");
  51 + return CMD_RET_FAILURE;
  52 + }
48 53  
49 54 ret = board_usb_init(controller_index, USB_INIT_DEVICE);
50 55 if (ret) {
... ... @@ -118,6 +123,12 @@
118 123 }
119 124 NXTARG:
120 125 ;
  126 + }
  127 +
  128 + /* Handle case when USB controller param is just '-' */
  129 + if (argc == 1) {
  130 + pr_err("Error: Incorrect USB controller index\n");
  131 + return CMD_RET_USAGE;
121 132 }
122 133  
123 134 fastboot_init((void *)buf_addr, buf_size);
configs/sandbox_defconfig
... ... @@ -34,6 +34,7 @@
34 34 CONFIG_CMD_MEMINFO=y
35 35 CONFIG_CMD_MEMTEST=y
36 36 CONFIG_CMD_MX_CYCLIC=y
  37 +CONFIG_CMD_BIND=y
37 38 CONFIG_CMD_DEMO=y
38 39 CONFIG_CMD_GPIO=y
39 40 CONFIG_CMD_GPT=y
drivers/core/device-remove.c
... ... @@ -17,16 +17,7 @@
17 17 #include <dm/uclass-internal.h>
18 18 #include <dm/util.h>
19 19  
20   -/**
21   - * device_chld_unbind() - Unbind all device's children from the device
22   - *
23   - * On error, the function continues to unbind all children, and reports the
24   - * first error.
25   - *
26   - * @dev: The device that is to be stripped of its children
27   - * @return 0 on success, -ve on error
28   - */
29   -static int device_chld_unbind(struct udevice *dev)
  20 +int device_chld_unbind(struct udevice *dev, struct driver *drv)
30 21 {
31 22 struct udevice *pos, *n;
32 23 int ret, saved_ret = 0;
... ... @@ -34,6 +25,9 @@
34 25 assert(dev);
35 26  
36 27 list_for_each_entry_safe(pos, n, &dev->child_head, sibling_node) {
  28 + if (drv && (pos->driver != drv))
  29 + continue;
  30 +
37 31 ret = device_unbind(pos);
38 32 if (ret && !saved_ret)
39 33 saved_ret = ret;
... ... @@ -42,13 +36,8 @@
42 36 return saved_ret;
43 37 }
44 38  
45   -/**
46   - * device_chld_remove() - Stop all device's children
47   - * @dev: The device whose children are to be removed
48   - * @pre_os_remove: Flag, if this functions is called in the pre-OS stage
49   - * @return 0 on success, -ve on error
50   - */
51   -static int device_chld_remove(struct udevice *dev, uint flags)
  39 +int device_chld_remove(struct udevice *dev, struct driver *drv,
  40 + uint flags)
52 41 {
53 42 struct udevice *pos, *n;
54 43 int ret;
... ... @@ -56,6 +45,9 @@
56 45 assert(dev);
57 46  
58 47 list_for_each_entry_safe(pos, n, &dev->child_head, sibling_node) {
  48 + if (drv && (pos->driver != drv))
  49 + continue;
  50 +
59 51 ret = device_remove(pos, flags);
60 52 if (ret)
61 53 return ret;
... ... @@ -87,7 +79,7 @@
87 79 return ret;
88 80 }
89 81  
90   - ret = device_chld_unbind(dev);
  82 + ret = device_chld_unbind(dev, NULL);
91 83 if (ret)
92 84 return ret;
93 85  
... ... @@ -178,7 +170,7 @@
178 170 if (ret)
179 171 return ret;
180 172  
181   - ret = device_chld_remove(dev, flags);
  173 + ret = device_chld_remove(dev, NULL, flags);
182 174 if (ret)
183 175 goto err;
184 176  
drivers/core/device.c
... ... @@ -594,16 +594,16 @@
594 594 return device_get_device_tail(dev, ret, devp);
595 595 }
596 596  
597   -static struct udevice *_device_find_global_by_of_offset(struct udevice *parent,
598   - int of_offset)
  597 +static struct udevice *_device_find_global_by_ofnode(struct udevice *parent,
  598 + ofnode ofnode)
599 599 {
600 600 struct udevice *dev, *found;
601 601  
602   - if (dev_of_offset(parent) == of_offset)
  602 + if (ofnode_equal(dev_ofnode(parent), ofnode))
603 603 return parent;
604 604  
605 605 list_for_each_entry(dev, &parent->child_head, sibling_node) {
606   - found = _device_find_global_by_of_offset(dev, of_offset);
  606 + found = _device_find_global_by_ofnode(dev, ofnode);
607 607 if (found)
608 608 return found;
609 609 }
610 610  
611 611  
... ... @@ -611,11 +611,18 @@
611 611 return NULL;
612 612 }
613 613  
614   -int device_get_global_by_of_offset(int of_offset, struct udevice **devp)
  614 +int device_find_global_by_ofnode(ofnode ofnode, struct udevice **devp)
615 615 {
  616 + *devp = _device_find_global_by_ofnode(gd->dm_root, ofnode);
  617 +
  618 + return *devp ? 0 : -ENOENT;
  619 +}
  620 +
  621 +int device_get_global_by_ofnode(ofnode ofnode, struct udevice **devp)
  622 +{
616 623 struct udevice *dev;
617 624  
618   - dev = _device_find_global_by_of_offset(gd->dm_root, of_offset);
  625 + dev = _device_find_global_by_ofnode(gd->dm_root, ofnode);
619 626 return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
620 627 }
621 628  
... ... @@ -8,6 +8,7 @@
8 8 #include <mapmem.h>
9 9 #include <dm/root.h>
10 10 #include <dm/util.h>
  11 +#include <dm/uclass-internal.h>
11 12  
12 13 static void show_devices(struct udevice *dev, int depth, int last_flag)
13 14 {
... ... @@ -15,7 +16,8 @@
15 16 struct udevice *child;
16 17  
17 18 /* print the first 11 characters to not break the tree-format. */
18   - printf(" %-10.10s [ %c ] %-10.10s ", dev->uclass->uc_drv->name,
  19 + printf(" %-10.10s %d [ %c ] %-10.10s ", dev->uclass->uc_drv->name,
  20 + dev_get_uclass_index(dev, NULL),
19 21 dev->flags & DM_FLAG_ACTIVATED ? '+' : ' ', dev->driver->name);
20 22  
21 23 for (i = depth; i >= 0; i--) {
... ... @@ -47,8 +49,8 @@
47 49  
48 50 root = dm_root();
49 51 if (root) {
50   - printf(" Class Probed Driver Name\n");
51   - printf("----------------------------------------\n");
  52 + printf(" Class index Probed Driver Name\n");
  53 + printf("-----------------------------------------\n");
52 54 show_devices(root, -1, 0);
53 55 }
54 56 }
55 57  
... ... @@ -60,9 +62,9 @@
60 62 *
61 63 * @dev: Device to display
62 64 */
63   -static void dm_display_line(struct udevice *dev)
  65 +static void dm_display_line(struct udevice *dev, int index)
64 66 {
65   - printf("- %c %s @ %08lx",
  67 + printf("%i %c %s @ %08lx", index,
66 68 dev->flags & DM_FLAG_ACTIVATED ? '*' : ' ',
67 69 dev->name, (ulong)map_to_sysmem(dev));
68 70 if (dev->seq != -1 || dev->req_seq != -1)
... ... @@ -78,6 +80,7 @@
78 80  
79 81 for (id = 0; id < UCLASS_COUNT; id++) {
80 82 struct udevice *dev;
  83 + int i = 0;
81 84  
82 85 ret = uclass_get(id, &uc);
83 86 if (ret)
... ... @@ -87,7 +90,8 @@
87 90 if (list_empty(&uc->dev_head))
88 91 continue;
89 92 list_for_each_entry(dev, &uc->dev_head, uclass_node) {
90   - dm_display_line(dev);
  93 + dm_display_line(dev, i);
  94 + i++;
91 95 }
92 96 puts("\n");
93 97 }
drivers/core/uclass.c
... ... @@ -171,6 +171,27 @@
171 171 return UCLASS_INVALID;
172 172 }
173 173  
  174 +int dev_get_uclass_index(struct udevice *dev, struct uclass **ucp)
  175 +{
  176 + struct udevice *iter;
  177 + struct uclass *uc = dev->uclass;
  178 + int i = 0;
  179 +
  180 + if (list_empty(&uc->dev_head))
  181 + return -ENODEV;
  182 +
  183 + list_for_each_entry(iter, &uc->dev_head, uclass_node) {
  184 + if (iter == dev) {
  185 + if (ucp)
  186 + *ucp = uc;
  187 + return i;
  188 + }
  189 + i++;
  190 + }
  191 +
  192 + return -ENODEV;
  193 +}
  194 +
174 195 int uclass_find_device(enum uclass_id id, int index, struct udevice **devp)
175 196 {
176 197 struct uclass *uc;
drivers/usb/gadget/gadget_chips.h
... ... @@ -206,6 +206,8 @@
206 206 return 0x21;
207 207 else if (gadget_is_fotg210(gadget))
208 208 return 0x22;
  209 + else if (gadget_is_dwc3(gadget))
  210 + return 0x23;
209 211 return -ENOENT;
210 212 }
drivers/usb/musb-new/omap2430.c
... ... @@ -8,202 +8,20 @@
8 8 *
9 9 * This file is part of the Inventra Controller Driver for Linux.
10 10 */
11   -#ifndef __UBOOT__
12   -#include <linux/module.h>
13   -#include <linux/kernel.h>
14   -#include <linux/sched.h>
15   -#include <linux/init.h>
16   -#include <linux/list.h>
17   -#include <linux/io.h>
18   -#include <linux/platform_device.h>
19   -#include <linux/dma-mapping.h>
20   -#include <linux/pm_runtime.h>
21   -#include <linux/err.h>
22   -#include <linux/usb/musb-omap.h>
23   -#else
24 11 #include <common.h>
  12 +#include <dm.h>
  13 +#include <dm/device-internal.h>
  14 +#include <dm/lists.h>
  15 +#include <linux/usb/otg.h>
25 16 #include <asm/omap_common.h>
26 17 #include <asm/omap_musb.h>
27 18 #include <twl4030.h>
28 19 #include <twl6030.h>
29 20 #include "linux-compat.h"
30   -#endif
31   -
32 21 #include "musb_core.h"
33 22 #include "omap2430.h"
  23 +#include "musb_uboot.h"
34 24  
35   -#ifndef __UBOOT__
36   -struct omap2430_glue {
37   - struct device *dev;
38   - struct platform_device *musb;
39   - enum omap_musb_vbus_id_status status;
40   - struct work_struct omap_musb_mailbox_work;
41   -};
42   -#define glue_to_musb(g) platform_get_drvdata(g->musb)
43   -
44   -struct omap2430_glue *_glue;
45   -
46   -static struct timer_list musb_idle_timer;
47   -
48   -static void musb_do_idle(unsigned long _musb)
49   -{
50   - struct musb *musb = (void *)_musb;
51   - unsigned long flags;
52   - u8 power;
53   - u8 devctl;
54   -
55   - spin_lock_irqsave(&musb->lock, flags);
56   -
57   - switch (musb->xceiv->state) {
58   - case OTG_STATE_A_WAIT_BCON:
59   -
60   - devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
61   - if (devctl & MUSB_DEVCTL_BDEVICE) {
62   - musb->xceiv->state = OTG_STATE_B_IDLE;
63   - MUSB_DEV_MODE(musb);
64   - } else {
65   - musb->xceiv->state = OTG_STATE_A_IDLE;
66   - MUSB_HST_MODE(musb);
67   - }
68   - break;
69   - case OTG_STATE_A_SUSPEND:
70   - /* finish RESUME signaling? */
71   - if (musb->port1_status & MUSB_PORT_STAT_RESUME) {
72   - power = musb_readb(musb->mregs, MUSB_POWER);
73   - power &= ~MUSB_POWER_RESUME;
74   - dev_dbg(musb->controller, "root port resume stopped, power %02x\n", power);
75   - musb_writeb(musb->mregs, MUSB_POWER, power);
76   - musb->is_active = 1;
77   - musb->port1_status &= ~(USB_PORT_STAT_SUSPEND
78   - | MUSB_PORT_STAT_RESUME);
79   - musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16;
80   - usb_hcd_poll_rh_status(musb_to_hcd(musb));
81   - /* NOTE: it might really be A_WAIT_BCON ... */
82   - musb->xceiv->state = OTG_STATE_A_HOST;
83   - }
84   - break;
85   - case OTG_STATE_A_HOST:
86   - devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
87   - if (devctl & MUSB_DEVCTL_BDEVICE)
88   - musb->xceiv->state = OTG_STATE_B_IDLE;
89   - else
90   - musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
91   - default:
92   - break;
93   - }
94   - spin_unlock_irqrestore(&musb->lock, flags);
95   -}
96   -
97   -
98   -static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout)
99   -{
100   - unsigned long default_timeout = jiffies + msecs_to_jiffies(3);
101   - static unsigned long last_timer;
102   -
103   - if (timeout == 0)
104   - timeout = default_timeout;
105   -
106   - /* Never idle if active, or when VBUS timeout is not set as host */
107   - if (musb->is_active || ((musb->a_wait_bcon == 0)
108   - && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) {
109   - dev_dbg(musb->controller, "%s active, deleting timer\n",
110   - otg_state_string(musb->xceiv->state));
111   - del_timer(&musb_idle_timer);
112   - last_timer = jiffies;
113   - return;
114   - }
115   -
116   - if (time_after(last_timer, timeout)) {
117   - if (!timer_pending(&musb_idle_timer))
118   - last_timer = timeout;
119   - else {
120   - dev_dbg(musb->controller, "Longer idle timer already pending, ignoring\n");
121   - return;
122   - }
123   - }
124   - last_timer = timeout;
125   -
126   - dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n",
127   - otg_state_string(musb->xceiv->state),
128   - (unsigned long)jiffies_to_msecs(timeout - jiffies));
129   - mod_timer(&musb_idle_timer, timeout);
130   -}
131   -
132   -static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
133   -{
134   - struct usb_otg *otg = musb->xceiv->otg;
135   - u8 devctl;
136   - unsigned long timeout = jiffies + msecs_to_jiffies(1000);
137   - int ret = 1;
138   - /* HDRC controls CPEN, but beware current surges during device
139   - * connect. They can trigger transient overcurrent conditions
140   - * that must be ignored.
141   - */
142   -
143   - devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
144   -
145   - if (is_on) {
146   - if (musb->xceiv->state == OTG_STATE_A_IDLE) {
147   - /* start the session */
148   - devctl |= MUSB_DEVCTL_SESSION;
149   - musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
150   - /*
151   - * Wait for the musb to set as A device to enable the
152   - * VBUS
153   - */
154   - while (musb_readb(musb->mregs, MUSB_DEVCTL) & 0x80) {
155   -
156   - cpu_relax();
157   -
158   - if (time_after(jiffies, timeout)) {
159   - dev_err(musb->controller,
160   - "configured as A device timeout");
161   - ret = -EINVAL;
162   - break;
163   - }
164   - }
165   -
166   - if (ret && otg->set_vbus)
167   - otg_set_vbus(otg, 1);
168   - } else {
169   - musb->is_active = 1;
170   - otg->default_a = 1;
171   - musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
172   - devctl |= MUSB_DEVCTL_SESSION;
173   - MUSB_HST_MODE(musb);
174   - }
175   - } else {
176   - musb->is_active = 0;
177   -
178   - /* NOTE: we're skipping A_WAIT_VFALL -> A_IDLE and
179   - * jumping right to B_IDLE...
180   - */
181   -
182   - otg->default_a = 0;
183   - musb->xceiv->state = OTG_STATE_B_IDLE;
184   - devctl &= ~MUSB_DEVCTL_SESSION;
185   -
186   - MUSB_DEV_MODE(musb);
187   - }
188   - musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
189   -
190   - dev_dbg(musb->controller, "VBUS %s, devctl %02x "
191   - /* otg %3x conf %08x prcm %08x */ "\n",
192   - otg_state_string(musb->xceiv->state),
193   - musb_readb(musb->mregs, MUSB_DEVCTL));
194   -}
195   -
196   -static int omap2430_musb_set_mode(struct musb *musb, u8 musb_mode)
197   -{
198   - u8 devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
199   -
200   - devctl |= MUSB_DEVCTL_SESSION;
201   - musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
202   -
203   - return 0;
204   -}
205   -#endif
206   -
207 25 static inline void omap2430_low_level_exit(struct musb *musb)
208 26 {
209 27 u32 l;
210 28  
211 29  
212 30  
... ... @@ -223,100 +41,15 @@
223 41 musb_writel(musb->mregs, OTG_FORCESTDBY, l);
224 42 }
225 43  
226   -#ifndef __UBOOT__
227   -void omap_musb_mailbox(enum omap_musb_vbus_id_status status)
228   -{
229   - struct omap2430_glue *glue = _glue;
230   - struct musb *musb = glue_to_musb(glue);
231 44  
232   - glue->status = status;
233   - if (!musb) {
234   - dev_err(glue->dev, "musb core is not yet ready\n");
235   - return;
236   - }
237   -
238   - schedule_work(&glue->omap_musb_mailbox_work);
239   -}
240   -EXPORT_SYMBOL_GPL(omap_musb_mailbox);
241   -
242   -static void omap_musb_set_mailbox(struct omap2430_glue *glue)
243   -{
244   - struct musb *musb = glue_to_musb(glue);
245   - struct device *dev = musb->controller;
246   - struct musb_hdrc_platform_data *pdata = dev->platform_data;
247   - struct omap_musb_board_data *data = pdata->board_data;
248   - struct usb_otg *otg = musb->xceiv->otg;
249   -
250   - switch (glue->status) {
251   - case OMAP_MUSB_ID_GROUND:
252   - dev_dbg(dev, "ID GND\n");
253   -
254   - otg->default_a = true;
255   - musb->xceiv->state = OTG_STATE_A_IDLE;
256   - musb->xceiv->last_event = USB_EVENT_ID;
257   - if (!is_otg_enabled(musb) || musb->gadget_driver) {
258   - pm_runtime_get_sync(dev);
259   - usb_phy_init(musb->xceiv);
260   - omap2430_musb_set_vbus(musb, 1);
261   - }
262   - break;
263   -
264   - case OMAP_MUSB_VBUS_VALID:
265   - dev_dbg(dev, "VBUS Connect\n");
266   -
267   - otg->default_a = false;
268   - musb->xceiv->state = OTG_STATE_B_IDLE;
269   - musb->xceiv->last_event = USB_EVENT_VBUS;
270   - if (musb->gadget_driver)
271   - pm_runtime_get_sync(dev);
272   - usb_phy_init(musb->xceiv);
273   - break;
274   -
275   - case OMAP_MUSB_ID_FLOAT:
276   - case OMAP_MUSB_VBUS_OFF:
277   - dev_dbg(dev, "VBUS Disconnect\n");
278   -
279   - musb->xceiv->last_event = USB_EVENT_NONE;
280   - if (is_otg_enabled(musb) || is_peripheral_enabled(musb))
281   - if (musb->gadget_driver) {
282   - pm_runtime_mark_last_busy(dev);
283   - pm_runtime_put_autosuspend(dev);
284   - }
285   -
286   - if (data->interface_type == MUSB_INTERFACE_UTMI) {
287   - if (musb->xceiv->otg->set_vbus)
288   - otg_set_vbus(musb->xceiv->otg, 0);
289   - }
290   - usb_phy_shutdown(musb->xceiv);
291   - break;
292   - default:
293   - dev_dbg(dev, "ID float\n");
294   - }
295   -}
296   -
297   -
298   -static void omap_musb_mailbox_work(struct work_struct *mailbox_work)
299   -{
300   - struct omap2430_glue *glue = container_of(mailbox_work,
301   - struct omap2430_glue, omap_musb_mailbox_work);
302   - omap_musb_set_mailbox(glue);
303   -}
304   -#endif
305   -
306 45 static int omap2430_musb_init(struct musb *musb)
307 46 {
308 47 u32 l;
309 48 int status = 0;
310 49 unsigned long int start;
311   -#ifndef __UBOOT__
312   - struct device *dev = musb->controller;
313   - struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
314   - struct musb_hdrc_platform_data *plat = dev->platform_data;
315   - struct omap_musb_board_data *data = plat->board_data;
316   -#else
  50 +
317 51 struct omap_musb_board_data *data =
318 52 (struct omap_musb_board_data *)musb->controller;
319   -#endif
320 53  
321 54 /* Reset the controller */
322 55 musb_writel(musb->mregs, OTG_SYSCONFIG, SOFTRST);
... ... @@ -334,24 +67,6 @@
334 67 }
335 68 }
336 69  
337   -#ifndef __UBOOT__
338   - /* We require some kind of external transceiver, hooked
339   - * up through ULPI. TWL4030-family PMICs include one,
340   - * which needs a driver, drivers aren't always needed.
341   - */
342   - musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
343   - if (IS_ERR_OR_NULL(musb->xceiv)) {
344   - pr_err("HS USB OTG: no transceiver configured\n");
345   - return -ENODEV;
346   - }
347   -
348   - status = pm_runtime_get_sync(dev);
349   - if (status < 0) {
350   - dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status);
351   - goto err1;
352   - }
353   -#endif
354   -
355 70 l = musb_readl(musb->mregs, OTG_INTERFSEL);
356 71  
357 72 if (data->interface_type == MUSB_INTERFACE_UTMI) {
358 73  
359 74  
360 75  
... ... @@ -371,64 +86,14 @@
371 86 musb_readl(musb->mregs, OTG_SYSSTATUS),
372 87 musb_readl(musb->mregs, OTG_INTERFSEL),
373 88 musb_readl(musb->mregs, OTG_SIMENABLE));
374   -
375   -#ifndef __UBOOT__
376   - setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
377   -
378   - if (glue->status != OMAP_MUSB_UNKNOWN)
379   - omap_musb_set_mailbox(glue);
380   -
381   - pm_runtime_put_noidle(musb->controller);
382   -#endif
383 89 return 0;
384 90  
385 91 err1:
386 92 return status;
387 93 }
388 94  
389   -#ifndef __UBOOT__
390   -static void omap2430_musb_enable(struct musb *musb)
391   -#else
392 95 static int omap2430_musb_enable(struct musb *musb)
393   -#endif
394 96 {
395   -#ifndef __UBOOT__
396   - u8 devctl;
397   - unsigned long timeout = jiffies + msecs_to_jiffies(1000);
398   - struct device *dev = musb->controller;
399   - struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
400   - struct musb_hdrc_platform_data *pdata = dev->platform_data;
401   - struct omap_musb_board_data *data = pdata->board_data;
402   -
403   - switch (glue->status) {
404   -
405   - case OMAP_MUSB_ID_GROUND:
406   - usb_phy_init(musb->xceiv);
407   - if (data->interface_type != MUSB_INTERFACE_UTMI)
408   - break;
409   - devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
410   - /* start the session */
411   - devctl |= MUSB_DEVCTL_SESSION;
412   - musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
413   - while (musb_readb(musb->mregs, MUSB_DEVCTL) &
414   - MUSB_DEVCTL_BDEVICE) {
415   - cpu_relax();
416   -
417   - if (time_after(jiffies, timeout)) {
418   - dev_err(dev, "configured as A device timeout");
419   - break;
420   - }
421   - }
422   - break;
423   -
424   - case OMAP_MUSB_VBUS_VALID:
425   - usb_phy_init(musb->xceiv);
426   - break;
427   -
428   - default:
429   - break;
430   - }
431   -#else
432 97 #ifdef CONFIG_TWL4030_USB
433 98 if (twl4030_usb_ulpi_init()) {
434 99 serial_printf("ERROR: %s Could not initialize PHY\n",
435 100  
436 101  
... ... @@ -447,18 +112,11 @@
447 112 #endif
448 113  
449 114 return 0;
450   -#endif
451 115 }
452 116  
453 117 static void omap2430_musb_disable(struct musb *musb)
454 118 {
455   -#ifndef __UBOOT__
456   - struct device *dev = musb->controller;
457   - struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
458 119  
459   - if (glue->status != OMAP_MUSB_UNKNOWN)
460   - usb_phy_shutdown(musb->xceiv);
461   -#endif
462 120 }
463 121  
464 122 static int omap2430_musb_exit(struct musb *musb)
465 123  
466 124  
467 125  
468 126  
469 127  
470 128  
471 129  
472 130  
473 131  
474 132  
475 133  
476 134  
477 135  
478 136  
479 137  
480 138  
481 139  
482 140  
483 141  
484 142  
485 143  
486 144  
487 145  
488 146  
489 147  
490 148  
491 149  
... ... @@ -470,175 +128,153 @@
470 128 return 0;
471 129 }
472 130  
473   -#ifndef __UBOOT__
474   -static const struct musb_platform_ops omap2430_ops = {
475   -#else
476 131 const struct musb_platform_ops omap2430_ops = {
477   -#endif
478 132 .init = omap2430_musb_init,
479 133 .exit = omap2430_musb_exit,
480   -
481   -#ifndef __UBOOT__
482   - .set_mode = omap2430_musb_set_mode,
483   - .try_idle = omap2430_musb_try_idle,
484   -
485   - .set_vbus = omap2430_musb_set_vbus,
486   -#endif
487   -
488 134 .enable = omap2430_musb_enable,
489 135 .disable = omap2430_musb_disable,
490 136 };
491 137  
492   -#ifndef __UBOOT__
493   -static u64 omap2430_dmamask = DMA_BIT_MASK(32);
  138 +#if defined(CONFIG_DM_USB)
494 139  
495   -static int __devinit omap2430_probe(struct platform_device *pdev)
  140 +struct omap2430_musb_platdata {
  141 + void *base;
  142 + void *ctrl_mod_base;
  143 + struct musb_hdrc_platform_data plat;
  144 + struct musb_hdrc_config musb_config;
  145 + struct omap_musb_board_data otg_board_data;
  146 +};
  147 +
  148 +static int omap2430_musb_ofdata_to_platdata(struct udevice *dev)
496 149 {
497   - struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
498   - struct platform_device *musb;
499   - struct omap2430_glue *glue;
500   - int ret = -ENOMEM;
  150 + struct omap2430_musb_platdata *platdata = dev_get_platdata(dev);
  151 + const void *fdt = gd->fdt_blob;
  152 + int node = dev_of_offset(dev);
501 153  
502   - glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
503   - if (!glue) {
504   - dev_err(&pdev->dev, "failed to allocate glue context\n");
505   - goto err0;
  154 + platdata->base = (void *)dev_read_addr_ptr(dev);
  155 +
  156 + platdata->musb_config.multipoint = fdtdec_get_int(fdt, node,
  157 + "multipoint",
  158 + -1);
  159 + if (platdata->musb_config.multipoint < 0) {
  160 + pr_err("MUSB multipoint DT entry missing\n");
  161 + return -ENOENT;
506 162 }
507 163  
508   - musb = platform_device_alloc("musb-hdrc", -1);
509   - if (!musb) {
510   - dev_err(&pdev->dev, "failed to allocate musb device\n");
511   - goto err0;
  164 + platdata->musb_config.dyn_fifo = 1;
  165 + platdata->musb_config.num_eps = fdtdec_get_int(fdt, node,
  166 + "num-eps", -1);
  167 + if (platdata->musb_config.num_eps < 0) {
  168 + pr_err("MUSB num-eps DT entry missing\n");
  169 + return -ENOENT;
512 170 }
513 171  
514   - musb->dev.parent = &pdev->dev;
515   - musb->dev.dma_mask = &omap2430_dmamask;
516   - musb->dev.coherent_dma_mask = omap2430_dmamask;
517   -
518   - glue->dev = &pdev->dev;
519   - glue->musb = musb;
520   - glue->status = OMAP_MUSB_UNKNOWN;
521   -
522   - pdata->platform_ops = &omap2430_ops;
523   -
524   - platform_set_drvdata(pdev, glue);
525   -
526   - /*
527   - * REVISIT if we ever have two instances of the wrapper, we will be
528   - * in big trouble
529   - */
530   - _glue = glue;
531   -
532   - INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work);
533   -
534   - ret = platform_device_add_resources(musb, pdev->resource,
535   - pdev->num_resources);
536   - if (ret) {
537   - dev_err(&pdev->dev, "failed to add resources\n");
538   - goto err1;
  172 + platdata->musb_config.ram_bits = fdtdec_get_int(fdt, node,
  173 + "ram-bits", -1);
  174 + if (platdata->musb_config.ram_bits < 0) {
  175 + pr_err("MUSB ram-bits DT entry missing\n");
  176 + return -ENOENT;
539 177 }
540 178  
541   - ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
542   - if (ret) {
543   - dev_err(&pdev->dev, "failed to add platform_data\n");
544   - goto err1;
  179 + platdata->plat.power = fdtdec_get_int(fdt, node,
  180 + "power", -1);
  181 + if (platdata->plat.power < 0) {
  182 + pr_err("MUSB power DT entry missing\n");
  183 + return -ENOENT;
545 184 }
546 185  
547   - pm_runtime_enable(&pdev->dev);
548   -
549   - ret = platform_device_add(musb);
550   - if (ret) {
551   - dev_err(&pdev->dev, "failed to register musb device\n");
552   - goto err1;
  186 + platdata->otg_board_data.interface_type = fdtdec_get_int(fdt, node,
  187 + "interface-type", -1);
  188 + if (platdata->otg_board_data.interface_type < 0) {
  189 + pr_err("MUSB interface-type DT entry missing\n");
  190 + return -ENOENT;
553 191 }
554 192  
  193 +#if 0 /* In a perfect world, mode would be set to OTG, mode 3 from DT */
  194 + platdata->plat.mode = fdtdec_get_int(fdt, node,
  195 + "mode", -1);
  196 + if (platdata->plat.mode < 0) {
  197 + pr_err("MUSB mode DT entry missing\n");
  198 + return -ENOENT;
  199 + }
  200 +#else /* MUSB_OTG, it doesn't work */
  201 +#ifdef CONFIG_USB_MUSB_HOST /* Host seems to be the only option that works */
  202 + platdata->plat.mode = MUSB_HOST;
  203 +#else /* For that matter, MUSB_PERIPHERAL doesn't either */
  204 + platdata->plat.mode = MUSB_PERIPHERAL;
  205 +#endif
  206 +#endif
  207 + platdata->otg_board_data.dev = dev;
  208 + platdata->plat.config = &platdata->musb_config;
  209 + platdata->plat.platform_ops = &omap2430_ops;
  210 + platdata->plat.board_data = &platdata->otg_board_data;
555 211 return 0;
556   -
557   -err1:
558   - platform_device_put(musb);
559   -
560   -err0:
561   - return ret;
562 212 }
563 213  
564   -static int __devexit omap2430_remove(struct platform_device *pdev)
  214 +static int omap2430_musb_probe(struct udevice *dev)
565 215 {
566   - struct omap2430_glue *glue = platform_get_drvdata(pdev);
  216 +#ifdef CONFIG_USB_MUSB_HOST
  217 + struct musb_host_data *host = dev_get_priv(dev);
  218 +#endif
  219 + struct omap2430_musb_platdata *platdata = dev_get_platdata(dev);
  220 + struct usb_bus_priv *priv = dev_get_uclass_priv(dev);
  221 + struct omap_musb_board_data *otg_board_data;
  222 + int ret;
  223 + void *base = dev_read_addr_ptr(dev);
567 224  
568   - cancel_work_sync(&glue->omap_musb_mailbox_work);
569   - platform_device_del(glue->musb);
570   - platform_device_put(glue->musb);
  225 + priv->desc_before_addr = true;
571 226  
572   - return 0;
573   -}
  227 + otg_board_data = &platdata->otg_board_data;
574 228  
575   -#ifdef CONFIG_PM
576   -
577   -static int omap2430_runtime_suspend(struct device *dev)
578   -{
579   - struct omap2430_glue *glue = dev_get_drvdata(dev);
580   - struct musb *musb = glue_to_musb(glue);
581   -
582   - if (musb) {
583   - musb->context.otg_interfsel = musb_readl(musb->mregs,
584   - OTG_INTERFSEL);
585   -
586   - omap2430_low_level_exit(musb);
587   - usb_phy_set_suspend(musb->xceiv, 1);
  229 +#ifdef CONFIG_USB_MUSB_HOST
  230 + host->host = musb_init_controller(&platdata->plat,
  231 + (struct device *)otg_board_data,
  232 + platdata->base);
  233 + if (!host->host) {
  234 + return -EIO;
588 235 }
589 236  
590   - return 0;
  237 + ret = musb_lowlevel_init(host);
  238 +#else
  239 + ret = musb_register(&platdata->plat,
  240 + (struct device *)otg_board_data,
  241 + platdata->base);
  242 +#endif
  243 + return ret;
591 244 }
592 245  
593   -static int omap2430_runtime_resume(struct device *dev)
  246 +static int omap2430_musb_remove(struct udevice *dev)
594 247 {
595   - struct omap2430_glue *glue = dev_get_drvdata(dev);
596   - struct musb *musb = glue_to_musb(glue);
  248 + struct musb_host_data *host = dev_get_priv(dev);
597 249  
598   - if (musb) {
599   - omap2430_low_level_init(musb);
600   - musb_writel(musb->mregs, OTG_INTERFSEL,
601   - musb->context.otg_interfsel);
  250 + musb_stop(host->host);
602 251  
603   - usb_phy_set_suspend(musb->xceiv, 0);
604   - }
605   -
606 252 return 0;
607 253 }
608 254  
609   -static struct dev_pm_ops omap2430_pm_ops = {
610   - .runtime_suspend = omap2430_runtime_suspend,
611   - .runtime_resume = omap2430_runtime_resume,
  255 +static const struct udevice_id omap2430_musb_ids[] = {
  256 + { .compatible = "ti,omap3-musb" },
  257 + { .compatible = "ti,omap4-musb" },
  258 + { }
612 259 };
613 260  
614   -#define DEV_PM_OPS (&omap2430_pm_ops)
  261 +U_BOOT_DRIVER(omap2430_musb) = {
  262 + .name = "omap2430-musb",
  263 +#ifdef CONFIG_USB_MUSB_HOST
  264 + .id = UCLASS_USB,
615 265 #else
616   -#define DEV_PM_OPS NULL
  266 + .id = UCLASS_USB_DEV_GENERIC,
617 267 #endif
618   -
619   -static struct platform_driver omap2430_driver = {
620   - .probe = omap2430_probe,
621   - .remove = __devexit_p(omap2430_remove),
622   - .driver = {
623   - .name = "musb-omap2430",
624   - .pm = DEV_PM_OPS,
625   - },
  268 + .of_match = omap2430_musb_ids,
  269 + .ofdata_to_platdata = omap2430_musb_ofdata_to_platdata,
  270 + .probe = omap2430_musb_probe,
  271 + .remove = omap2430_musb_remove,
  272 +#ifdef CONFIG_USB_MUSB_HOST
  273 + .ops = &musb_usb_ops,
  274 +#endif
  275 + .platdata_auto_alloc_size = sizeof(struct omap2430_musb_platdata),
  276 + .priv_auto_alloc_size = sizeof(struct musb_host_data),
626 277 };
627 278  
628   -MODULE_DESCRIPTION("OMAP2PLUS MUSB Glue Layer");
629   -MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
630   -MODULE_LICENSE("GPL v2");
631   -
632   -static int __init omap2430_init(void)
633   -{
634   - return platform_driver_register(&omap2430_driver);
635   -}
636   -subsys_initcall(omap2430_init);
637   -
638   -static void __exit omap2430_exit(void)
639   -{
640   - platform_driver_unregister(&omap2430_driver);
641   -}
642   -module_exit(omap2430_exit);
643   -#endif
  279 +#endif /* CONFIG_DM_USB */
include/dm/device-internal.h
... ... @@ -131,6 +131,44 @@
131 131 #endif
132 132  
133 133 /**
  134 + * device_chld_unbind() - Unbind all device's children from the device if bound
  135 + * to drv
  136 + *
  137 + * On error, the function continues to unbind all children, and reports the
  138 + * first error.
  139 + *
  140 + * @dev: The device that is to be stripped of its children
  141 + * @drv: The targeted driver
  142 + * @return 0 on success, -ve on error
  143 + */
  144 +#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
  145 +int device_chld_unbind(struct udevice *dev, struct driver *drv);
  146 +#else
  147 +static inline int device_chld_unbind(struct udevice *dev, struct driver *drv)
  148 +{
  149 + return 0;
  150 +}
  151 +#endif
  152 +
  153 +/**
  154 + * device_chld_remove() - Stop all device's children
  155 + * @dev: The device whose children are to be removed
  156 + * @drv: The targeted driver
  157 + * @flags: Flag, if this functions is called in the pre-OS stage
  158 + * @return 0 on success, -ve on error
  159 + */
  160 +#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
  161 +int device_chld_remove(struct udevice *dev, struct driver *drv,
  162 + uint flags);
  163 +#else
  164 +static inline int device_chld_remove(struct udevice *dev, struct driver *drv,
  165 + uint flags)
  166 +{
  167 + return 0;
  168 +}
  169 +#endif
  170 +
  171 +/**
134 172 * simple_bus_translate() - translate a bus address to a system address
135 173 *
136 174 * This handles the 'ranges' property in a simple bus. It translates the
... ... @@ -473,18 +473,33 @@
473 473 struct udevice **devp);
474 474  
475 475 /**
476   - * device_get_global_by_of_offset() - Get a device based on FDT offset
  476 + * device_find_global_by_ofnode() - Get a device based on ofnode
477 477 *
478   - * Locates a device by its device tree offset, searching globally throughout
  478 + * Locates a device by its device tree ofnode, searching globally throughout
479 479 * the all driver model devices.
480 480 *
  481 + * The device is NOT probed
  482 + *
  483 + * @node: Device tree ofnode to find
  484 + * @devp: Returns pointer to device if found, otherwise this is set to NULL
  485 + * @return 0 if OK, -ve on error
  486 + */
  487 +
  488 +int device_find_global_by_ofnode(ofnode node, struct udevice **devp);
  489 +
  490 +/**
  491 + * device_get_global_by_ofnode() - Get a device based on ofnode
  492 + *
  493 + * Locates a device by its device tree ofnode, searching globally throughout
  494 + * the all driver model devices.
  495 + *
481 496 * The device is probed to activate it ready for use.
482 497 *
483   - * @of_offset: Device tree offset to find
  498 + * @node: Device tree ofnode to find
484 499 * @devp: Returns pointer to device if found, otherwise this is set to NULL
485 500 * @return 0 if OK, -ve on error
486 501 */
487   -int device_get_global_by_of_offset(int of_offset, struct udevice **devp);
  502 +int device_get_global_by_ofnode(ofnode node, struct udevice **devp);
488 503  
489 504 /**
490 505 * device_find_first_child() - Find the first child of a device
include/dm/uclass-internal.h
... ... @@ -24,6 +24,17 @@
24 24 int uclass_get_device_tail(struct udevice *dev, int ret, struct udevice **devp);
25 25  
26 26 /**
  27 + * dev_get_uclass_index() - Get uclass and index of device
  28 + * @dev: - in - Device that we want the uclass/index of
  29 + * @ucp: - out - A pointer to the uclass the device belongs to
  30 + *
  31 + * The device is not prepared for use - this is an internal function.
  32 + *
  33 + * @return the index of the device in the uclass list or -ENODEV if not found.
  34 + */
  35 +int dev_get_uclass_index(struct udevice *dev, struct uclass **ucp);
  36 +
  37 +/**
27 38 * uclass_find_device() - Return n-th child of uclass
28 39 * @id: Id number of the uclass
29 40 * @index: Position of the child in uclass's list
... ... @@ -312,7 +312,8 @@
312 312  
313 313 eth_get_ops(current)->stop(current);
314 314 priv = current->uclass_priv;
315   - priv->state = ETH_STATE_PASSIVE;
  315 + if (priv)
  316 + priv->state = ETH_STATE_PASSIVE;
316 317 }
317 318  
318 319 int eth_is_active(struct udevice *dev)
test/py/tests/test_bind.py
  1 +# SPDX-License-Identifier: GPL-2.0
  2 +# Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
  3 +
  4 +import os.path
  5 +import pytest
  6 +import re
  7 +
  8 +def in_tree(response, name, uclass, drv, depth, last_child):
  9 + lines = [x.strip() for x in response.splitlines()]
  10 + leaf = ' ' * 4 * depth;
  11 + if not last_child:
  12 + leaf = leaf + '\|'
  13 + else:
  14 + leaf = leaf + '`'
  15 + leaf = leaf + '-- ' + name
  16 + line = ' *{:10.10} [0-9]* \[ [ +] \] {:10.10} {}$'.format(uclass, drv,leaf)
  17 + prog = re.compile(line)
  18 + for l in lines:
  19 + if prog.match(l):
  20 + return True
  21 + return False
  22 +
  23 +
  24 +@pytest.mark.buildconfigspec('cmd_bind')
  25 +def test_bind_unbind_with_node(u_boot_console):
  26 +
  27 + #bind /bind-test. Device should come up as well as its children
  28 + response = u_boot_console.run_command("bind /bind-test generic_simple_bus")
  29 + assert response == ''
  30 + tree = u_boot_console.run_command("dm tree")
  31 + assert in_tree(tree, "bind-test", "simple_bus", "generic_simple", 0, True)
  32 + assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, False)
  33 + assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple", 1, True)
  34 +
  35 + #Unbind child #1. No error expected and all devices should be there except for bind-test-child1
  36 + response = u_boot_console.run_command("unbind /bind-test/bind-test-child1")
  37 + assert response == ''
  38 + tree = u_boot_console.run_command("dm tree")
  39 + assert in_tree(tree, "bind-test", "simple_bus", "generic_simple", 0, True)
  40 + assert "bind-test-child1" not in tree
  41 + assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple", 1, True)
  42 +
  43 + #bind child #1. No error expected and all devices should be there
  44 + response = u_boot_console.run_command("bind /bind-test/bind-test-child1 phy_sandbox")
  45 + assert response == ''
  46 + tree = u_boot_console.run_command("dm tree")
  47 + assert in_tree(tree, "bind-test", "simple_bus", "generic_simple", 0, True)
  48 + assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, True)
  49 + assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple", 1, False)
  50 +
  51 + #Unbind child #2. No error expected and all devices should be there except for bind-test-child2
  52 + response = u_boot_console.run_command("unbind /bind-test/bind-test-child2")
  53 + assert response == ''
  54 + tree = u_boot_console.run_command("dm tree")
  55 + assert in_tree(tree, "bind-test", "simple_bus", "generic_simple", 0, True)
  56 + assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, True)
  57 + assert "bind-test-child2" not in tree
  58 +
  59 +
  60 + #Bind child #2. No error expected and all devices should be there
  61 + response = u_boot_console.run_command("bind /bind-test/bind-test-child2 generic_simple_bus")
  62 + assert response == ''
  63 + tree = u_boot_console.run_command("dm tree")
  64 + assert in_tree(tree, "bind-test", "simple_bus", "generic_simple", 0, True)
  65 + assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, False)
  66 + assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple", 1, True)
  67 +
  68 + #Unbind parent. No error expected. All devices should be removed and unbound
  69 + response = u_boot_console.run_command("unbind /bind-test")
  70 + assert response == ''
  71 + tree = u_boot_console.run_command("dm tree")
  72 + assert "bind-test" not in tree
  73 + assert "bind-test-child1" not in tree
  74 + assert "bind-test-child2" not in tree
  75 +
  76 + #try binding invalid node with valid driver
  77 + response = u_boot_console.run_command("bind /not-a-valid-node generic_simple_bus")
  78 + assert response != ''
  79 + tree = u_boot_console.run_command("dm tree")
  80 + assert "not-a-valid-node" not in tree
  81 +
  82 + #try binding valid node with invalid driver
  83 + response = u_boot_console.run_command("bind /bind-test not_a_driver")
  84 + assert response != ''
  85 + tree = u_boot_console.run_command("dm tree")
  86 + assert "bind-test" not in tree
  87 +
  88 + #bind /bind-test. Device should come up as well as its children
  89 + response = u_boot_console.run_command("bind /bind-test generic_simple_bus")
  90 + assert response == ''
  91 + tree = u_boot_console.run_command("dm tree")
  92 + assert in_tree(tree, "bind-test", "simple_bus", "generic_simple", 0, True)
  93 + assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, False)
  94 + assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple", 1, True)
  95 +
  96 + response = u_boot_console.run_command("unbind /bind-test")
  97 + assert response == ''
  98 +
  99 +def get_next_line(tree, name):
  100 + treelines = [x.strip() for x in tree.splitlines() if x.strip()]
  101 + child_line = ""
  102 + for idx, line in enumerate(treelines):
  103 + if ("-- " + name) in line:
  104 + try:
  105 + child_line = treelines[idx+1]
  106 + except:
  107 + pass
  108 + break
  109 + return child_line
  110 +
  111 +@pytest.mark.buildconfigspec('cmd_bind')
  112 +def test_bind_unbind_with_uclass(u_boot_console):
  113 + #bind /bind-test
  114 + response = u_boot_console.run_command("bind /bind-test generic_simple_bus")
  115 + assert response == ''
  116 +
  117 + #make sure bind-test-child2 is there and get its uclass/index pair
  118 + tree = u_boot_console.run_command("dm tree")
  119 + child2_line = [x.strip() for x in tree.splitlines() if "-- bind-test-child2" in x]
  120 + assert len(child2_line) == 1
  121 +
  122 + child2_uclass = child2_line[0].split()[0]
  123 + child2_index = int(child2_line[0].split()[1])
  124 +
  125 + #bind generic_simple_bus as a child of bind-test-child2
  126 + response = u_boot_console.run_command("bind {} {} generic_simple_bus".format(child2_uclass, child2_index, "generic_simple_bus"))
  127 +
  128 + #check that the child is there and its uclass/index pair is right
  129 + tree = u_boot_console.run_command("dm tree")
  130 +
  131 + child_of_child2_line = get_next_line(tree, "bind-test-child2")
  132 + assert child_of_child2_line
  133 + child_of_child2_index = int(child_of_child2_line.split()[1])
  134 + assert in_tree(tree, "generic_simple_bus", "simple_bus", "generic_simple_bus", 2, True)
  135 + assert child_of_child2_index == child2_index + 1
  136 +
  137 + #unbind the child and check it has been removed
  138 + response = u_boot_console.run_command("unbind simple_bus {}".format(child_of_child2_index))
  139 + assert response == ''
  140 + tree = u_boot_console.run_command("dm tree")
  141 + assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple", 1, True)
  142 + assert not in_tree(tree, "generic_simple_bus", "simple_bus", "generic_simple_bus", 2, True)
  143 + child_of_child2_line = get_next_line(tree, "bind-test-child2")
  144 + assert child_of_child2_line == ""
  145 +
  146 + #bind generic_simple_bus as a child of bind-test-child2
  147 + response = u_boot_console.run_command("bind {} {} generic_simple_bus".format(child2_uclass, child2_index, "generic_simple_bus"))
  148 +
  149 + #check that the child is there and its uclass/index pair is right
  150 + tree = u_boot_console.run_command("dm tree")
  151 + treelines = [x.strip() for x in tree.splitlines() if x.strip()]
  152 +
  153 + child_of_child2_line = get_next_line(tree, "bind-test-child2")
  154 + assert child_of_child2_line
  155 + child_of_child2_index = int(child_of_child2_line.split()[1])
  156 + assert in_tree(tree, "generic_simple_bus", "simple_bus", "generic_simple_bus", 2, True)
  157 + assert child_of_child2_index == child2_index + 1
  158 +
  159 + #unbind the child and check it has been removed
  160 + response = u_boot_console.run_command("unbind {} {} generic_simple_bus".format(child2_uclass, child2_index, "generic_simple_bus"))
  161 + assert response == ''
  162 +
  163 + tree = u_boot_console.run_command("dm tree")
  164 + assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple", 1, True)
  165 +
  166 + child_of_child2_line = get_next_line(tree, "bind-test-child2")
  167 + assert child_of_child2_line == ""
  168 +
  169 + #unbind the child again and check it doesn't change the tree
  170 + tree_old = u_boot_console.run_command("dm tree")
  171 + response = u_boot_console.run_command("unbind {} {} generic_simple_bus".format(child2_uclass, child2_index, "generic_simple_bus"))
  172 + tree_new = u_boot_console.run_command("dm tree")
  173 +
  174 + assert response == ''
  175 + assert tree_old == tree_new
  176 +
  177 + response = u_boot_console.run_command("unbind /bind-test")
  178 + assert response == ''