core: Add dev_{disable,enable}_by_path
We cannot use device structures to disable devices, since getting them with the API functions would bind and activate the device, which would fail if the underlying device does not exist. Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
2ea4d0db73
commit
e4c98a59db
@ -516,6 +516,33 @@ static int device_get_device_tail(struct udevice *dev, int ret,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* device_find_by_ofnode() - Return device associated with given ofnode
|
||||
*
|
||||
* The returned device is *not* activated.
|
||||
*
|
||||
* @node: The ofnode for which a associated device should be looked up
|
||||
* @devp: Pointer to structure to hold the found device
|
||||
* Return: 0 if OK, -ve on error
|
||||
*/
|
||||
static int device_find_by_ofnode(ofnode node, struct udevice **devp)
|
||||
{
|
||||
struct uclass *uc;
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
|
||||
list_for_each_entry(uc, &gd->uclass_root, sibling_node) {
|
||||
ret = uclass_find_device_by_ofnode(uc->uc_drv->id, node,
|
||||
&dev);
|
||||
if (!ret || dev) {
|
||||
*devp = dev;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int device_get_child(struct udevice *parent, int index, struct udevice **devp)
|
||||
{
|
||||
struct udevice *dev;
|
||||
@ -739,3 +766,54 @@ bool of_machine_is_compatible(const char *compat)
|
||||
|
||||
return !fdt_node_check_compatible(fdt, 0, compat);
|
||||
}
|
||||
|
||||
int dev_disable_by_path(const char *path)
|
||||
{
|
||||
struct uclass *uc;
|
||||
ofnode node = ofnode_path(path);
|
||||
struct udevice *dev;
|
||||
int ret = 1;
|
||||
|
||||
if (!of_live_active())
|
||||
return -ENOSYS;
|
||||
|
||||
list_for_each_entry(uc, &gd->uclass_root, sibling_node) {
|
||||
ret = uclass_find_device_by_ofnode(uc->uc_drv->id, node, &dev);
|
||||
if (!ret)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = device_remove(dev, DM_REMOVE_NORMAL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = device_unbind(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ofnode_set_enabled(node, false);
|
||||
}
|
||||
|
||||
int dev_enable_by_path(const char *path)
|
||||
{
|
||||
ofnode node = ofnode_path(path);
|
||||
ofnode pnode = ofnode_get_parent(node);
|
||||
struct udevice *parent;
|
||||
int ret = 1;
|
||||
|
||||
if (!of_live_active())
|
||||
return -ENOSYS;
|
||||
|
||||
ret = device_find_by_ofnode(pnode, &parent);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ofnode_set_enabled(node, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return lists_bind_fdt(parent, node, NULL);
|
||||
}
|
||||
|
@ -600,6 +600,22 @@ bool device_is_compatible(struct udevice *dev, const char *compat);
|
||||
*/
|
||||
bool of_machine_is_compatible(const char *compat);
|
||||
|
||||
/**
|
||||
* dev_disable_by_path() - Disable a device given its device tree path
|
||||
*
|
||||
* @path: The device tree path identifying the device to be disabled
|
||||
* @return 0 on success, -ve on error
|
||||
*/
|
||||
int dev_disable_by_path(const char *path);
|
||||
|
||||
/**
|
||||
* dev_enable_by_path() - Enable a device given its device tree path
|
||||
*
|
||||
* @path: The device tree path identifying the device to be enabled
|
||||
* @return 0 on success, -ve on error
|
||||
*/
|
||||
int dev_enable_by_path(const char *path);
|
||||
|
||||
/**
|
||||
* device_is_on_pci_bus - Test if a device is on a PCI bus
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user