Skip to content

Commit 5fc4e4c

Browse files
Bartosz GolaszewskipH5
authored andcommitted
reset: gpio: use software nodes to setup the GPIO lookup
GPIO machine lookup is a nice mechanism for associating GPIOs with consumers if we don't know what kind of device the GPIO provider is or when it will become available. However in the case of the reset-gpio, we are already holding a reference to the device and so can reference its firmware node. Let's setup a software node that references the relevant GPIO and attach it to the auxiliary device we're creating. Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de> Acked-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
1 parent 109ce74 commit 5fc4e4c

1 file changed

Lines changed: 70 additions & 49 deletions

File tree

drivers/reset/core.c

Lines changed: 70 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/export.h>
1515
#include <linux/gpio/driver.h>
1616
#include <linux/gpio/machine.h>
17+
#include <linux/gpio/property.h>
1718
#include <linux/idr.h>
1819
#include <linux/kernel.h>
1920
#include <linux/kref.h>
@@ -77,10 +78,12 @@ struct reset_control_array {
7778
/**
7879
* struct reset_gpio_lookup - lookup key for ad-hoc created reset-gpio devices
7980
* @of_args: phandle to the reset controller with all the args like GPIO number
81+
* @swnode: Software node containing the reference to the GPIO provider
8082
* @list: list entry for the reset_gpio_lookup_list
8183
*/
8284
struct reset_gpio_lookup {
8385
struct of_phandle_args of_args;
86+
struct fwnode_handle *swnode;
8487
struct list_head list;
8588
};
8689

@@ -849,61 +852,56 @@ static void __reset_control_put_internal(struct reset_control *rstc)
849852
kref_put(&rstc->refcnt, __reset_control_release);
850853
}
851854

852-
static int __reset_add_reset_gpio_lookup(struct gpio_device *gdev, int id,
853-
struct device_node *np,
854-
unsigned int gpio,
855-
unsigned int of_flags)
855+
static void reset_gpio_aux_device_release(struct device *dev)
856856
{
857-
unsigned int lookup_flags;
858-
const char *label_tmp;
857+
struct auxiliary_device *adev = to_auxiliary_dev(dev);
859858

860-
/*
861-
* Later we map GPIO flags between OF and Linux, however not all
862-
* constants from include/dt-bindings/gpio/gpio.h and
863-
* include/linux/gpio/machine.h match each other.
864-
*/
865-
if (of_flags > GPIO_ACTIVE_LOW) {
866-
pr_err("reset-gpio code does not support GPIO flags %u for GPIO %u\n",
867-
of_flags, gpio);
868-
return -EINVAL;
869-
}
870-
871-
label_tmp = gpio_device_get_label(gdev);
872-
if (!label_tmp)
873-
return -EINVAL;
859+
kfree(adev);
860+
}
874861

875-
char *label __free(kfree) = kstrdup(label_tmp, GFP_KERNEL);
876-
if (!label)
877-
return -ENOMEM;
862+
static int reset_add_gpio_aux_device(struct device *parent,
863+
struct fwnode_handle *swnode,
864+
int id, void *pdata)
865+
{
866+
struct auxiliary_device *adev;
867+
int ret;
878868

879-
/* Size: one lookup entry plus sentinel */
880-
struct gpiod_lookup_table *lookup __free(kfree) = kzalloc(struct_size(lookup, table, 2),
881-
GFP_KERNEL);
882-
if (!lookup)
869+
adev = kzalloc(sizeof(*adev), GFP_KERNEL);
870+
if (!adev)
883871
return -ENOMEM;
884872

885-
lookup->dev_id = kasprintf(GFP_KERNEL, "reset.gpio.%d", id);
886-
if (!lookup->dev_id)
887-
return -ENOMEM;
873+
adev->id = id;
874+
adev->name = "gpio";
875+
adev->dev.parent = parent;
876+
adev->dev.platform_data = pdata;
877+
adev->dev.release = reset_gpio_aux_device_release;
878+
device_set_node(&adev->dev, swnode);
888879

889-
lookup_flags = GPIO_PERSISTENT;
890-
lookup_flags |= of_flags & GPIO_ACTIVE_LOW;
891-
lookup->table[0] = GPIO_LOOKUP(no_free_ptr(label), gpio, "reset",
892-
lookup_flags);
880+
ret = auxiliary_device_init(adev);
881+
if (ret) {
882+
kfree(adev);
883+
return ret;
884+
}
893885

894-
/* Not freed on success, because it is persisent subsystem data. */
895-
gpiod_add_lookup_table(no_free_ptr(lookup));
886+
ret = __auxiliary_device_add(adev, "reset");
887+
if (ret) {
888+
auxiliary_device_uninit(adev);
889+
kfree(adev);
890+
return ret;
891+
}
896892

897-
return 0;
893+
return ret;
898894
}
899895

900896
/*
901897
* @args: phandle to the GPIO provider with all the args like GPIO number
902898
*/
903899
static int __reset_add_reset_gpio_device(const struct of_phandle_args *args)
904900
{
901+
struct property_entry properties[2] = { };
902+
unsigned int offset, of_flags, lflags;
905903
struct reset_gpio_lookup *rgpio_dev;
906-
struct auxiliary_device *adev;
904+
struct device *parent;
907905
int id, ret;
908906

909907
/*
@@ -922,6 +920,23 @@ static int __reset_add_reset_gpio_device(const struct of_phandle_args *args)
922920
*/
923921
lockdep_assert_not_held(&reset_list_mutex);
924922

923+
offset = args->args[0];
924+
of_flags = args->args[1];
925+
926+
/*
927+
* Later we map GPIO flags between OF and Linux, however not all
928+
* constants from include/dt-bindings/gpio/gpio.h and
929+
* include/linux/gpio/machine.h match each other.
930+
*
931+
* FIXME: Find a better way of translating OF flags to GPIO lookup
932+
* flags.
933+
*/
934+
if (of_flags > GPIO_ACTIVE_LOW) {
935+
pr_err("reset-gpio code does not support GPIO flags %u for GPIO %u\n",
936+
of_flags, offset);
937+
return -EINVAL;
938+
}
939+
925940
struct gpio_device *gdev __free(gpio_device_put) =
926941
gpio_device_find_by_fwnode(of_fwnode_handle(args->np));
927942
if (!gdev)
@@ -936,6 +951,10 @@ static int __reset_add_reset_gpio_device(const struct of_phandle_args *args)
936951
}
937952
}
938953

954+
lflags = GPIO_PERSISTENT | (of_flags & GPIO_ACTIVE_LOW);
955+
parent = gpio_device_to_device(gdev);
956+
properties[0] = PROPERTY_ENTRY_GPIO("reset-gpios", parent->fwnode, offset, lflags);
957+
939958
id = ida_alloc(&reset_gpio_ida, GFP_KERNEL);
940959
if (id < 0)
941960
return id;
@@ -947,31 +966,33 @@ static int __reset_add_reset_gpio_device(const struct of_phandle_args *args)
947966
goto err_ida_free;
948967
}
949968

950-
ret = __reset_add_reset_gpio_lookup(gdev, id, args->np, args->args[0],
951-
args->args[1]);
952-
if (ret < 0)
953-
goto err_kfree;
954-
955969
rgpio_dev->of_args = *args;
956970
/*
957971
* We keep the device_node reference, but of_args.np is put at the end
958972
* of __of_reset_control_get(), so get it one more time.
959973
* Hold reference as long as rgpio_dev memory is valid.
960974
*/
961975
of_node_get(rgpio_dev->of_args.np);
962-
adev = auxiliary_device_create(gpio_device_to_device(gdev), "reset",
963-
"gpio", &rgpio_dev->of_args, id);
964-
ret = PTR_ERR_OR_ZERO(adev);
976+
977+
rgpio_dev->swnode = fwnode_create_software_node(properties, NULL);
978+
if (IS_ERR(rgpio_dev->swnode)) {
979+
ret = PTR_ERR(rgpio_dev->swnode);
980+
goto err_put_of_node;
981+
}
982+
983+
ret = reset_add_gpio_aux_device(parent, rgpio_dev->swnode, id,
984+
&rgpio_dev->of_args);
965985
if (ret)
966-
goto err_put;
986+
goto err_del_swnode;
967987

968988
list_add(&rgpio_dev->list, &reset_gpio_lookup_list);
969989

970990
return 0;
971991

972-
err_put:
992+
err_del_swnode:
993+
fwnode_remove_software_node(rgpio_dev->swnode);
994+
err_put_of_node:
973995
of_node_put(rgpio_dev->of_args.np);
974-
err_kfree:
975996
kfree(rgpio_dev);
976997
err_ida_free:
977998
ida_free(&reset_gpio_ida, id);

0 commit comments

Comments
 (0)