diff options
Diffstat (limited to 'drivers/of/base.c')
| -rw-r--r-- | drivers/of/base.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c index cf89ee6253f3..2ce58be314af 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
| @@ -870,3 +870,74 @@ int prom_update_property(struct device_node *np, | |||
| 870 | 870 | ||
| 871 | return 0; | 871 | return 0; |
| 872 | } | 872 | } |
| 873 | |||
| 874 | #if defined(CONFIG_OF_DYNAMIC) | ||
| 875 | /* | ||
| 876 | * Support for dynamic device trees. | ||
| 877 | * | ||
| 878 | * On some platforms, the device tree can be manipulated at runtime. | ||
| 879 | * The routines in this section support adding, removing and changing | ||
| 880 | * device tree nodes. | ||
| 881 | */ | ||
| 882 | |||
| 883 | /** | ||
| 884 | * of_attach_node - Plug a device node into the tree and global list. | ||
| 885 | */ | ||
| 886 | void of_attach_node(struct device_node *np) | ||
| 887 | { | ||
| 888 | unsigned long flags; | ||
| 889 | |||
| 890 | write_lock_irqsave(&devtree_lock, flags); | ||
| 891 | np->sibling = np->parent->child; | ||
| 892 | np->allnext = allnodes; | ||
| 893 | np->parent->child = np; | ||
| 894 | allnodes = np; | ||
| 895 | write_unlock_irqrestore(&devtree_lock, flags); | ||
| 896 | } | ||
| 897 | |||
| 898 | /** | ||
| 899 | * of_detach_node - "Unplug" a node from the device tree. | ||
| 900 | * | ||
| 901 | * The caller must hold a reference to the node. The memory associated with | ||
| 902 | * the node is not freed until its refcount goes to zero. | ||
| 903 | */ | ||
| 904 | void of_detach_node(struct device_node *np) | ||
| 905 | { | ||
| 906 | struct device_node *parent; | ||
| 907 | unsigned long flags; | ||
| 908 | |||
| 909 | write_lock_irqsave(&devtree_lock, flags); | ||
| 910 | |||
| 911 | parent = np->parent; | ||
| 912 | if (!parent) | ||
| 913 | goto out_unlock; | ||
| 914 | |||
| 915 | if (allnodes == np) | ||
| 916 | allnodes = np->allnext; | ||
| 917 | else { | ||
| 918 | struct device_node *prev; | ||
| 919 | for (prev = allnodes; | ||
| 920 | prev->allnext != np; | ||
| 921 | prev = prev->allnext) | ||
| 922 | ; | ||
| 923 | prev->allnext = np->allnext; | ||
| 924 | } | ||
| 925 | |||
| 926 | if (parent->child == np) | ||
| 927 | parent->child = np->sibling; | ||
| 928 | else { | ||
| 929 | struct device_node *prevsib; | ||
| 930 | for (prevsib = np->parent->child; | ||
| 931 | prevsib->sibling != np; | ||
| 932 | prevsib = prevsib->sibling) | ||
| 933 | ; | ||
| 934 | prevsib->sibling = np->sibling; | ||
| 935 | } | ||
| 936 | |||
| 937 | of_node_set_flag(np, OF_DETACHED); | ||
| 938 | |||
| 939 | out_unlock: | ||
| 940 | write_unlock_irqrestore(&devtree_lock, flags); | ||
| 941 | } | ||
| 942 | #endif /* defined(CONFIG_OF_DYNAMIC) */ | ||
| 943 | |||
