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 | |||