Skip to content

Commit c721f18

Browse files
krzkpH5
authored andcommitted
reset: Instantiate reset GPIO controller for shared reset-gpios
Devices sharing a reset GPIO could use the reset framework for coordinated handling of that shared GPIO line. We have several cases of such needs, at least for Devicetree-based platforms. If Devicetree-based device requests a reset line, while "resets" Devicetree property is missing but there is a "reset-gpios" one, instantiate a new "reset-gpio" platform device which will handle such reset line. This allows seamless handling of such shared reset-gpios without need of changing Devicetree binding [1]. To avoid creating multiple "reset-gpio" platform devices, store the Devicetree "reset-gpios" GPIO specifiers used for new devices on a linked list. Later such Devicetree GPIO specifier (phandle to GPIO controller, GPIO number and GPIO flags) is used to check if reset controller for given GPIO was already registered. If two devices have conflicting "reset-gpios" property, e.g. with different ACTIVE_xxx flags, this would allow to spawn two separate "reset-gpio" devices, where the second would fail probing on busy GPIO request. Link: https://lore.kernel.org/all/[email protected]/ [1] Cc: Bartosz Golaszewski <[email protected]> Cc: Chris Packham <[email protected]> Cc: Sean Anderson <[email protected]> Reviewed-by: Philipp Zabel <[email protected]> Signed-off-by: Krzysztof Kozlowski <[email protected]> Acked-by: Bartosz Golaszewski <[email protected]> Acked-by: Linus Walleij <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Philipp Zabel <[email protected]>
1 parent cee544a commit c721f18

File tree

2 files changed

+215
-13
lines changed

2 files changed

+215
-13
lines changed

drivers/reset/core.c

Lines changed: 211 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,19 @@
55
* Copyright 2013 Philipp Zabel, Pengutronix
66
*/
77
#include <linux/atomic.h>
8+
#include <linux/cleanup.h>
89
#include <linux/device.h>
910
#include <linux/err.h>
1011
#include <linux/export.h>
1112
#include <linux/kernel.h>
1213
#include <linux/kref.h>
14+
#include <linux/gpio/driver.h>
15+
#include <linux/gpio/machine.h>
16+
#include <linux/idr.h>
1317
#include <linux/module.h>
1418
#include <linux/of.h>
1519
#include <linux/acpi.h>
20+
#include <linux/platform_device.h>
1621
#include <linux/reset.h>
1722
#include <linux/reset-controller.h>
1823
#include <linux/slab.h>
@@ -23,6 +28,11 @@ static LIST_HEAD(reset_controller_list);
2328
static DEFINE_MUTEX(reset_lookup_mutex);
2429
static LIST_HEAD(reset_lookup_list);
2530

31+
/* Protects reset_gpio_lookup_list */
32+
static DEFINE_MUTEX(reset_gpio_lookup_mutex);
33+
static LIST_HEAD(reset_gpio_lookup_list);
34+
static DEFINE_IDA(reset_gpio_ida);
35+
2636
/**
2737
* struct reset_control - a reset control
2838
* @rcdev: a pointer to the reset controller device
@@ -63,6 +73,16 @@ struct reset_control_array {
6373
struct reset_control *rstc[] __counted_by(num_rstcs);
6474
};
6575

76+
/**
77+
* struct reset_gpio_lookup - lookup key for ad-hoc created reset-gpio devices
78+
* @of_args: phandle to the reset controller with all the args like GPIO number
79+
* @list: list entry for the reset_gpio_lookup_list
80+
*/
81+
struct reset_gpio_lookup {
82+
struct of_phandle_args of_args;
83+
struct list_head list;
84+
};
85+
6686
static const char *rcdev_name(struct reset_controller_dev *rcdev)
6787
{
6888
if (rcdev->dev)
@@ -71,6 +91,9 @@ static const char *rcdev_name(struct reset_controller_dev *rcdev)
7191
if (rcdev->of_node)
7292
return rcdev->of_node->full_name;
7393

94+
if (rcdev->of_args)
95+
return rcdev->of_args->np->full_name;
96+
7497
return NULL;
7598
}
7699

@@ -99,6 +122,9 @@ static int of_reset_simple_xlate(struct reset_controller_dev *rcdev,
99122
*/
100123
int reset_controller_register(struct reset_controller_dev *rcdev)
101124
{
125+
if (rcdev->of_node && rcdev->of_args)
126+
return -EINVAL;
127+
102128
if (!rcdev->of_xlate) {
103129
rcdev->of_reset_n_cells = 1;
104130
rcdev->of_xlate = of_reset_simple_xlate;
@@ -813,12 +839,171 @@ static void __reset_control_put_internal(struct reset_control *rstc)
813839
kref_put(&rstc->refcnt, __reset_control_release);
814840
}
815841

842+
static int __reset_add_reset_gpio_lookup(int id, struct device_node *np,
843+
unsigned int gpio,
844+
unsigned int of_flags)
845+
{
846+
const struct fwnode_handle *fwnode = of_fwnode_handle(np);
847+
unsigned int lookup_flags;
848+
const char *label_tmp;
849+
850+
/*
851+
* Later we map GPIO flags between OF and Linux, however not all
852+
* constants from include/dt-bindings/gpio/gpio.h and
853+
* include/linux/gpio/machine.h match each other.
854+
*/
855+
if (of_flags > GPIO_ACTIVE_LOW) {
856+
pr_err("reset-gpio code does not support GPIO flags %u for GPIO %u\n",
857+
of_flags, gpio);
858+
return -EINVAL;
859+
}
860+
861+
struct gpio_device *gdev __free(gpio_device_put) = gpio_device_find_by_fwnode(fwnode);
862+
if (!gdev)
863+
return -EPROBE_DEFER;
864+
865+
label_tmp = gpio_device_get_label(gdev);
866+
if (!label_tmp)
867+
return -EINVAL;
868+
869+
char *label __free(kfree) = kstrdup(label_tmp, GFP_KERNEL);
870+
if (!label)
871+
return -ENOMEM;
872+
873+
/* Size: one lookup entry plus sentinel */
874+
struct gpiod_lookup_table *lookup __free(kfree) = kzalloc(struct_size(lookup, table, 2),
875+
GFP_KERNEL);
876+
if (!lookup)
877+
return -ENOMEM;
878+
879+
lookup->dev_id = kasprintf(GFP_KERNEL, "reset-gpio.%d", id);
880+
if (!lookup->dev_id)
881+
return -ENOMEM;
882+
883+
lookup_flags = GPIO_PERSISTENT;
884+
lookup_flags |= of_flags & GPIO_ACTIVE_LOW;
885+
lookup->table[0] = GPIO_LOOKUP(no_free_ptr(label), gpio, "reset",
886+
lookup_flags);
887+
888+
/* Not freed on success, because it is persisent subsystem data. */
889+
gpiod_add_lookup_table(no_free_ptr(lookup));
890+
891+
return 0;
892+
}
893+
894+
/*
895+
* @args: phandle to the GPIO provider with all the args like GPIO number
896+
*/
897+
static int __reset_add_reset_gpio_device(const struct of_phandle_args *args)
898+
{
899+
struct reset_gpio_lookup *rgpio_dev;
900+
struct platform_device *pdev;
901+
int id, ret;
902+
903+
/*
904+
* Currently only #gpio-cells=2 is supported with the meaning of:
905+
* args[0]: GPIO number
906+
* args[1]: GPIO flags
907+
* TODO: Handle other cases.
908+
*/
909+
if (args->args_count != 2)
910+
return -ENOENT;
911+
912+
/*
913+
* Registering reset-gpio device might cause immediate
914+
* bind, resulting in its probe() registering new reset controller thus
915+
* taking reset_list_mutex lock via reset_controller_register().
916+
*/
917+
lockdep_assert_not_held(&reset_list_mutex);
918+
919+
mutex_lock(&reset_gpio_lookup_mutex);
920+
921+
list_for_each_entry(rgpio_dev, &reset_gpio_lookup_list, list) {
922+
if (args->np == rgpio_dev->of_args.np) {
923+
if (of_phandle_args_equal(args, &rgpio_dev->of_args))
924+
goto out; /* Already on the list, done */
925+
}
926+
}
927+
928+
id = ida_alloc(&reset_gpio_ida, GFP_KERNEL);
929+
if (id < 0) {
930+
ret = id;
931+
goto err_unlock;
932+
}
933+
934+
/* Not freed on success, because it is persisent subsystem data. */
935+
rgpio_dev = kzalloc(sizeof(*rgpio_dev), GFP_KERNEL);
936+
if (!rgpio_dev) {
937+
ret = -ENOMEM;
938+
goto err_ida_free;
939+
}
940+
941+
ret = __reset_add_reset_gpio_lookup(id, args->np, args->args[0],
942+
args->args[1]);
943+
if (ret < 0)
944+
goto err_kfree;
945+
946+
rgpio_dev->of_args = *args;
947+
/*
948+
* We keep the device_node reference, but of_args.np is put at the end
949+
* of __of_reset_control_get(), so get it one more time.
950+
* Hold reference as long as rgpio_dev memory is valid.
951+
*/
952+
of_node_get(rgpio_dev->of_args.np);
953+
pdev = platform_device_register_data(NULL, "reset-gpio", id,
954+
&rgpio_dev->of_args,
955+
sizeof(rgpio_dev->of_args));
956+
ret = PTR_ERR_OR_ZERO(pdev);
957+
if (ret)
958+
goto err_put;
959+
960+
list_add(&rgpio_dev->list, &reset_gpio_lookup_list);
961+
962+
out:
963+
mutex_unlock(&reset_gpio_lookup_mutex);
964+
965+
return 0;
966+
967+
err_put:
968+
of_node_put(rgpio_dev->of_args.np);
969+
err_kfree:
970+
kfree(rgpio_dev);
971+
err_ida_free:
972+
ida_free(&reset_gpio_ida, id);
973+
err_unlock:
974+
mutex_unlock(&reset_gpio_lookup_mutex);
975+
976+
return ret;
977+
}
978+
979+
static struct reset_controller_dev *__reset_find_rcdev(const struct of_phandle_args *args,
980+
bool gpio_fallback)
981+
{
982+
struct reset_controller_dev *rcdev;
983+
984+
lockdep_assert_held(&reset_list_mutex);
985+
986+
list_for_each_entry(rcdev, &reset_controller_list, list) {
987+
if (gpio_fallback) {
988+
if (rcdev->of_args && of_phandle_args_equal(args,
989+
rcdev->of_args))
990+
return rcdev;
991+
} else {
992+
if (args->np == rcdev->of_node)
993+
return rcdev;
994+
}
995+
}
996+
997+
return NULL;
998+
}
999+
8161000
struct reset_control *
8171001
__of_reset_control_get(struct device_node *node, const char *id, int index,
8181002
bool shared, bool optional, bool acquired)
8191003
{
1004+
bool gpio_fallback = false;
8201005
struct reset_control *rstc;
821-
struct reset_controller_dev *r, *rcdev;
1006+
struct reset_controller_dev *rcdev;
8221007
struct of_phandle_args args;
8231008
int rstc_id;
8241009
int ret;
@@ -839,39 +1024,52 @@ __of_reset_control_get(struct device_node *node, const char *id, int index,
8391024
index, &args);
8401025
if (ret == -EINVAL)
8411026
return ERR_PTR(ret);
842-
if (ret)
843-
return optional ? NULL : ERR_PTR(ret);
1027+
if (ret) {
1028+
if (!IS_ENABLED(CONFIG_RESET_GPIO))
1029+
return optional ? NULL : ERR_PTR(ret);
8441030

845-
mutex_lock(&reset_list_mutex);
846-
rcdev = NULL;
847-
list_for_each_entry(r, &reset_controller_list, list) {
848-
if (args.np == r->of_node) {
849-
rcdev = r;
850-
break;
1031+
/*
1032+
* There can be only one reset-gpio for regular devices, so
1033+
* don't bother with the "reset-gpios" phandle index.
1034+
*/
1035+
ret = of_parse_phandle_with_args(node, "reset-gpios", "#gpio-cells",
1036+
0, &args);
1037+
if (ret)
1038+
return optional ? NULL : ERR_PTR(ret);
1039+
1040+
gpio_fallback = true;
1041+
1042+
ret = __reset_add_reset_gpio_device(&args);
1043+
if (ret) {
1044+
rstc = ERR_PTR(ret);
1045+
goto out_put;
8511046
}
8521047
}
8531048

1049+
mutex_lock(&reset_list_mutex);
1050+
rcdev = __reset_find_rcdev(&args, gpio_fallback);
8541051
if (!rcdev) {
8551052
rstc = ERR_PTR(-EPROBE_DEFER);
856-
goto out;
1053+
goto out_unlock;
8571054
}
8581055

8591056
if (WARN_ON(args.args_count != rcdev->of_reset_n_cells)) {
8601057
rstc = ERR_PTR(-EINVAL);
861-
goto out;
1058+
goto out_unlock;
8621059
}
8631060

8641061
rstc_id = rcdev->of_xlate(rcdev, &args);
8651062
if (rstc_id < 0) {
8661063
rstc = ERR_PTR(rstc_id);
867-
goto out;
1064+
goto out_unlock;
8681065
}
8691066

8701067
/* reset_list_mutex also protects the rcdev's reset_control list */
8711068
rstc = __reset_control_get_internal(rcdev, rstc_id, shared, acquired);
8721069

873-
out:
1070+
out_unlock:
8741071
mutex_unlock(&reset_list_mutex);
1072+
out_put:
8751073
of_node_put(args.np);
8761074

8771075
return rstc;

include/linux/reset-controller.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ struct reset_control_lookup {
6060
* @reset_control_head: head of internal list of requested reset controls
6161
* @dev: corresponding driver model device struct
6262
* @of_node: corresponding device tree node as phandle target
63+
* @of_args: for reset-gpios controllers: corresponding phandle args with
64+
* of_node and GPIO number complementing of_node; either this or
65+
* of_node should be present
6366
* @of_reset_n_cells: number of cells in reset line specifiers
6467
* @of_xlate: translation function to translate from specifier as found in the
6568
* device tree to id as given to the reset control ops, defaults
@@ -73,6 +76,7 @@ struct reset_controller_dev {
7376
struct list_head reset_control_head;
7477
struct device *dev;
7578
struct device_node *of_node;
79+
const struct of_phandle_args *of_args;
7680
int of_reset_n_cells;
7781
int (*of_xlate)(struct reset_controller_dev *rcdev,
7882
const struct of_phandle_args *reset_spec);

0 commit comments

Comments
 (0)