4040
4141#define GPIO_SIM_NGPIO_MAX 1024
4242#define GPIO_SIM_PROP_MAX 5 /* Max 4 properties + sentinel. */
43+ #define GPIO_SIM_HOG_PROP_MAX 5
4344#define GPIO_SIM_NUM_ATTRS 3 /* value, pull and sentinel */
4445
4546static DEFINE_IDA (gpio_sim_ida );
@@ -561,8 +562,6 @@ struct gpio_sim_device {
561562 */
562563 struct mutex lock ;
563564
564- struct gpiod_hog * hogs ;
565-
566565 struct list_head bank_list ;
567566};
568567
@@ -774,102 +773,6 @@ static void gpio_sim_set_reserved_ranges(struct gpio_sim_bank *bank,
774773 }
775774}
776775
777- static void gpio_sim_remove_hogs (struct gpio_sim_device * dev )
778- {
779- struct gpiod_hog * hog ;
780-
781- if (!dev -> hogs )
782- return ;
783-
784- gpiod_remove_hogs (dev -> hogs );
785-
786- for (hog = dev -> hogs ; hog -> chip_label ; hog ++ ) {
787- kfree (hog -> chip_label );
788- kfree (hog -> line_name );
789- }
790-
791- kfree (dev -> hogs );
792- dev -> hogs = NULL ;
793- }
794-
795- static int gpio_sim_add_hogs (struct gpio_sim_device * dev )
796- {
797- unsigned int num_hogs = 0 , idx = 0 ;
798- struct gpio_sim_bank * bank ;
799- struct gpio_sim_line * line ;
800- struct gpiod_hog * hog ;
801-
802- list_for_each_entry (bank , & dev -> bank_list , siblings ) {
803- list_for_each_entry (line , & bank -> line_list , siblings ) {
804- if (line -> offset >= bank -> num_lines )
805- continue ;
806-
807- if (line -> hog )
808- num_hogs ++ ;
809- }
810- }
811-
812- if (!num_hogs )
813- return 0 ;
814-
815- /* Allocate one more for the sentinel. */
816- dev -> hogs = kzalloc_objs (* dev -> hogs , num_hogs + 1 );
817- if (!dev -> hogs )
818- return - ENOMEM ;
819-
820- list_for_each_entry (bank , & dev -> bank_list , siblings ) {
821- list_for_each_entry (line , & bank -> line_list , siblings ) {
822- if (line -> offset >= bank -> num_lines )
823- continue ;
824-
825- if (!line -> hog )
826- continue ;
827-
828- hog = & dev -> hogs [idx ++ ];
829-
830- /*
831- * We need to make this string manually because at this
832- * point the device doesn't exist yet and so dev_name()
833- * is not available.
834- */
835- if (gpio_sim_bank_has_label (bank ))
836- hog -> chip_label = kstrdup (bank -> label ,
837- GFP_KERNEL );
838- else
839- hog -> chip_label = kasprintf (GFP_KERNEL ,
840- "gpio-sim.%u:%pfwP" ,
841- dev -> id ,
842- bank -> swnode );
843- if (!hog -> chip_label ) {
844- gpio_sim_remove_hogs (dev );
845- return - ENOMEM ;
846- }
847-
848- /*
849- * We need to duplicate this because the hog config
850- * item can be removed at any time (and we can't block
851- * it) and gpiolib doesn't make a deep copy of the hog
852- * data.
853- */
854- if (line -> hog -> name ) {
855- hog -> line_name = kstrdup (line -> hog -> name ,
856- GFP_KERNEL );
857- if (!hog -> line_name ) {
858- gpio_sim_remove_hogs (dev );
859- return - ENOMEM ;
860- }
861- }
862-
863- hog -> chip_hwnum = line -> offset ;
864- hog -> dflags = line -> hog -> dir ;
865- }
866- }
867-
868- gpiod_add_hogs (dev -> hogs );
869-
870- return 0 ;
871- }
872-
873776static struct fwnode_handle *
874777gpio_sim_make_bank_swnode (struct gpio_sim_bank * bank ,
875778 struct fwnode_handle * parent )
@@ -917,12 +820,61 @@ gpio_sim_make_bank_swnode(struct gpio_sim_bank *bank,
917820 return fwnode_create_software_node (properties , parent );
918821}
919822
823+ static int gpio_sim_bank_add_hogs (struct gpio_sim_bank * bank )
824+ {
825+ struct property_entry properties [GPIO_SIM_HOG_PROP_MAX ];
826+ struct fwnode_handle * swnode ;
827+ struct gpio_sim_line * line ;
828+ struct gpio_sim_hog * hog ;
829+ unsigned int idx ;
830+ u32 gpios [2 ];
831+
832+ list_for_each_entry (line , & bank -> line_list , siblings ) {
833+ if (!line -> hog )
834+ continue ;
835+
836+ hog = line -> hog ;
837+
838+ gpios [0 ] = line -> offset ;
839+ gpios [1 ] = 0 ;
840+
841+ memset (properties , 0 , sizeof (properties ));
842+
843+ idx = 0 ;
844+ properties [idx ++ ] = PROPERTY_ENTRY_BOOL ("gpio-hog" );
845+ properties [idx ++ ] = PROPERTY_ENTRY_U32_ARRAY ("gpios" , gpios );
846+ properties [idx ++ ] = PROPERTY_ENTRY_STRING ("line-name" , hog -> name );
847+
848+ switch (hog -> dir ) {
849+ case GPIOD_IN :
850+ properties [idx ++ ] = PROPERTY_ENTRY_BOOL ("input" );
851+ break ;
852+ case GPIOD_OUT_HIGH :
853+ properties [idx ++ ] = PROPERTY_ENTRY_BOOL ("output-high" );
854+ break ;
855+ case GPIOD_OUT_LOW :
856+ properties [idx ++ ] = PROPERTY_ENTRY_BOOL ("output-low" );
857+ break ;
858+ default :
859+ /* Would have been validated at configfs store. */
860+ WARN (1 , "Unexpected hog direction value: %d" , hog -> dir );
861+ return - EINVAL ;
862+ }
863+
864+ swnode = fwnode_create_software_node (properties , bank -> swnode );
865+ if (IS_ERR (swnode ))
866+ return PTR_ERR (swnode );
867+ }
868+
869+ return 0 ;
870+ }
871+
920872static void gpio_sim_remove_swnode_recursive (struct fwnode_handle * swnode )
921873{
922874 struct fwnode_handle * child ;
923875
924876 fwnode_for_each_child_node (swnode , child )
925- fwnode_remove_software_node (child );
877+ gpio_sim_remove_swnode_recursive (child );
926878
927879 fwnode_remove_software_node (swnode );
928880}
@@ -977,12 +929,12 @@ static int gpio_sim_device_activate(struct gpio_sim_device *dev)
977929 gpio_sim_remove_swnode_recursive (swnode );
978930 return ret ;
979931 }
980- }
981932
982- ret = gpio_sim_add_hogs (dev );
983- if (ret ) {
984- gpio_sim_remove_swnode_recursive (swnode );
985- return ret ;
933+ ret = gpio_sim_bank_add_hogs (bank );
934+ if (ret ) {
935+ gpio_sim_remove_swnode_recursive (swnode );
936+ return ret ;
937+ }
986938 }
987939
988940 pdevinfo .name = "gpio-sim" ;
@@ -991,7 +943,6 @@ static int gpio_sim_device_activate(struct gpio_sim_device *dev)
991943
992944 ret = dev_sync_probe_register (& dev -> probe_data , & pdevinfo );
993945 if (ret ) {
994- gpio_sim_remove_hogs (dev );
995946 gpio_sim_remove_swnode_recursive (swnode );
996947 return ret ;
997948 }
@@ -1007,7 +958,6 @@ static void gpio_sim_device_deactivate(struct gpio_sim_device *dev)
1007958
1008959 swnode = dev_fwnode (& dev -> probe_data .pdev -> dev );
1009960 dev_sync_probe_unregister (& dev -> probe_data );
1010- gpio_sim_remove_hogs (dev );
1011961 gpio_sim_remove_swnode_recursive (swnode );
1012962}
1013963
0 commit comments