@@ -483,6 +483,38 @@ struct device_node *__of_node_dup(const struct device_node *np,
483483 return NULL ;
484484}
485485
486+ /**
487+ * of_changeset_create_node - Dynamically create a device node and attach to
488+ * a given changeset.
489+ *
490+ * @ocs: Pointer to changeset
491+ * @parent: Pointer to parent device node
492+ * @full_name: Node full name
493+ *
494+ * Return: Pointer to the created device node or NULL in case of an error.
495+ */
496+ struct device_node * of_changeset_create_node (struct of_changeset * ocs ,
497+ struct device_node * parent ,
498+ const char * full_name )
499+ {
500+ struct device_node * np ;
501+ int ret ;
502+
503+ np = __of_node_dup (NULL , full_name );
504+ if (!np )
505+ return NULL ;
506+ np -> parent = parent ;
507+
508+ ret = of_changeset_attach_node (ocs , np );
509+ if (ret ) {
510+ of_node_put (np );
511+ return NULL ;
512+ }
513+
514+ return np ;
515+ }
516+ EXPORT_SYMBOL (of_changeset_create_node );
517+
486518static void __of_changeset_entry_destroy (struct of_changeset_entry * ce )
487519{
488520 if (ce -> action == OF_RECONFIG_ATTACH_NODE &&
@@ -875,3 +907,135 @@ int of_changeset_action(struct of_changeset *ocs, unsigned long action,
875907 return 0 ;
876908}
877909EXPORT_SYMBOL_GPL (of_changeset_action );
910+
911+ static int of_changeset_add_prop_helper (struct of_changeset * ocs ,
912+ struct device_node * np ,
913+ const struct property * pp )
914+ {
915+ struct property * new_pp ;
916+ int ret ;
917+
918+ new_pp = __of_prop_dup (pp , GFP_KERNEL );
919+ if (!new_pp )
920+ return - ENOMEM ;
921+
922+ ret = of_changeset_add_property (ocs , np , new_pp );
923+ if (ret ) {
924+ kfree (new_pp -> name );
925+ kfree (new_pp -> value );
926+ kfree (new_pp );
927+ }
928+
929+ return ret ;
930+ }
931+
932+ /**
933+ * of_changeset_add_prop_string - Add a string property to a changeset
934+ *
935+ * @ocs: changeset pointer
936+ * @np: device node pointer
937+ * @prop_name: name of the property to be added
938+ * @str: pointer to null terminated string
939+ *
940+ * Create a string property and add it to a changeset.
941+ *
942+ * Return: 0 on success, a negative error value in case of an error.
943+ */
944+ int of_changeset_add_prop_string (struct of_changeset * ocs ,
945+ struct device_node * np ,
946+ const char * prop_name , const char * str )
947+ {
948+ struct property prop ;
949+
950+ prop .name = (char * )prop_name ;
951+ prop .length = strlen (str ) + 1 ;
952+ prop .value = (void * )str ;
953+
954+ return of_changeset_add_prop_helper (ocs , np , & prop );
955+ }
956+ EXPORT_SYMBOL_GPL (of_changeset_add_prop_string );
957+
958+ /**
959+ * of_changeset_add_prop_string_array - Add a string list property to
960+ * a changeset
961+ *
962+ * @ocs: changeset pointer
963+ * @np: device node pointer
964+ * @prop_name: name of the property to be added
965+ * @str_array: pointer to an array of null terminated strings
966+ * @sz: number of string array elements
967+ *
968+ * Create a string list property and add it to a changeset.
969+ *
970+ * Return: 0 on success, a negative error value in case of an error.
971+ */
972+ int of_changeset_add_prop_string_array (struct of_changeset * ocs ,
973+ struct device_node * np ,
974+ const char * prop_name ,
975+ const char * * str_array , size_t sz )
976+ {
977+ struct property prop ;
978+ int i , ret ;
979+ char * vp ;
980+
981+ prop .name = (char * )prop_name ;
982+
983+ prop .length = 0 ;
984+ for (i = 0 ; i < sz ; i ++ )
985+ prop .length += strlen (str_array [i ]) + 1 ;
986+
987+ prop .value = kmalloc (prop .length , GFP_KERNEL );
988+ if (!prop .value )
989+ return - ENOMEM ;
990+
991+ vp = prop .value ;
992+ for (i = 0 ; i < sz ; i ++ ) {
993+ vp += snprintf (vp , (char * )prop .value + prop .length - vp , "%s" ,
994+ str_array [i ]) + 1 ;
995+ }
996+ ret = of_changeset_add_prop_helper (ocs , np , & prop );
997+ kfree (prop .value );
998+
999+ return ret ;
1000+ }
1001+ EXPORT_SYMBOL_GPL (of_changeset_add_prop_string_array );
1002+
1003+ /**
1004+ * of_changeset_add_prop_u32_array - Add a property of 32 bit integers
1005+ * property to a changeset
1006+ *
1007+ * @ocs: changeset pointer
1008+ * @np: device node pointer
1009+ * @prop_name: name of the property to be added
1010+ * @array: pointer to an array of 32 bit integers
1011+ * @sz: number of array elements
1012+ *
1013+ * Create a property of 32 bit integers and add it to a changeset.
1014+ *
1015+ * Return: 0 on success, a negative error value in case of an error.
1016+ */
1017+ int of_changeset_add_prop_u32_array (struct of_changeset * ocs ,
1018+ struct device_node * np ,
1019+ const char * prop_name ,
1020+ const u32 * array , size_t sz )
1021+ {
1022+ struct property prop ;
1023+ __be32 * val ;
1024+ int i , ret ;
1025+
1026+ val = kcalloc (sz , sizeof (__be32 ), GFP_KERNEL );
1027+ if (!val )
1028+ return - ENOMEM ;
1029+
1030+ for (i = 0 ; i < sz ; i ++ )
1031+ val [i ] = cpu_to_be32 (array [i ]);
1032+ prop .name = (char * )prop_name ;
1033+ prop .length = sizeof (u32 ) * sz ;
1034+ prop .value = (void * )val ;
1035+
1036+ ret = of_changeset_add_prop_helper (ocs , np , & prop );
1037+ kfree (val );
1038+
1039+ return ret ;
1040+ }
1041+ EXPORT_SYMBOL_GPL (of_changeset_add_prop_u32_array );
0 commit comments