Skip to content

Commit 5cfbd0e

Browse files
author
Bartosz Golaszewski
committed
gpio: sim: use fwnode-based GPIO hogs
Convert gpio-sim to using software nodes for setting up simulated hogs instead of legacy machine hogs. Reviewed-by: Linus Walleij <linusw@kernel.org> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Link: https://patch.msgid.link/20260309-gpio-hog-fwnode-v2-3-4e61f3dbf06a@oss.qualcomm.com Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
1 parent d1d564e commit 5cfbd0e

1 file changed

Lines changed: 56 additions & 106 deletions

File tree

drivers/gpio/gpio-sim.c

Lines changed: 56 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
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

4546
static 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-
873776
static struct fwnode_handle *
874777
gpio_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+
920872
static 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

Comments
 (0)