Skip to content

Commit 724ad89

Browse files
committed
Merge tag 'reset-for-v6.9' of git://git.pengutronix.de/pza/linux into soc/late
Reset controller updates for v6.9 Enable support for the Sophgo SG2042 reset controller via reset-simple, add a GPIO-based reset controller criver for shared GPIO resets, extract an of_phandle_args_equal() helper function out of cpufreq, and use it in reset-gpio. Based on v6.8-rc5 because reset-gpio depends on commits in the gpio-driver-h-stubs-for-v6.8-rc5 tag. * tag 'reset-for-v6.9' of git://git.pengutronix.de/pza/linux: reset: Instantiate reset GPIO controller for shared reset-gpios reset: gpio: Add GPIO-based reset controller cpufreq: do not open-code of_phandle_args_equal() of: Add of_phandle_args_equal() helper reset: simple: add support for Sophgo SG2042 dt-bindings: reset: sophgo: support SG2042 Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnd Bergmann <[email protected]>
2 parents 794f877 + c721f18 commit 724ad89

File tree

11 files changed

+492
-16
lines changed

11 files changed

+492
-16
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2+
%YAML 1.2
3+
---
4+
$id: http://devicetree.org/schemas/reset/sophgo,sg2042-reset.yaml#
5+
$schema: http://devicetree.org/meta-schemas/core.yaml#
6+
7+
title: Sophgo SG2042 SoC Reset Controller
8+
9+
maintainers:
10+
- Chen Wang <[email protected]>
11+
12+
properties:
13+
compatible:
14+
const: sophgo,sg2042-reset
15+
16+
reg:
17+
maxItems: 1
18+
19+
"#reset-cells":
20+
const: 1
21+
22+
required:
23+
- compatible
24+
- reg
25+
- "#reset-cells"
26+
27+
additionalProperties: false
28+
29+
examples:
30+
- |
31+
rstgen: reset-controller@c00 {
32+
compatible = "sophgo,sg2042-reset";
33+
reg = <0xc00 0xc>;
34+
#reset-cells = <1>;
35+
};

MAINTAINERS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8911,6 +8911,11 @@ F: Documentation/i2c/muxes/i2c-mux-gpio.rst
89118911
F: drivers/i2c/muxes/i2c-mux-gpio.c
89128912
F: include/linux/platform_data/i2c-mux-gpio.h
89138913

8914+
GENERIC GPIO RESET DRIVER
8915+
M: Krzysztof Kozlowski <[email protected]>
8916+
S: Maintained
8917+
F: drivers/reset/reset-gpio.c
8918+
89148919
GENERIC HDLC (WAN) DRIVERS
89158920
M: Krzysztof Halasa <[email protected]>
89168921
S: Maintained

drivers/reset/Kconfig

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,15 @@ config RESET_BRCMSTB_RESCAL
6666
This enables the RESCAL reset controller for SATA, PCIe0, or PCIe1 on
6767
BCM7216.
6868

69+
config RESET_GPIO
70+
tristate "GPIO reset controller"
71+
help
72+
This enables a generic reset controller for resets attached via
73+
GPIOs. Typically for OF platforms this driver expects "reset-gpios"
74+
property.
75+
76+
If compiled as module, it will be called reset-gpio.
77+
6978
config RESET_HSDK
7079
bool "Synopsys HSDK Reset Driver"
7180
depends on HAS_IOMEM
@@ -213,7 +222,7 @@ config RESET_SCMI
213222

214223
config RESET_SIMPLE
215224
bool "Simple Reset Controller Driver" if COMPILE_TEST || EXPERT
216-
default ARCH_ASPEED || ARCH_BCMBCA || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || (ARCH_INTEL_SOCFPGA && ARM64) || ARCH_SUNXI || ARC
225+
default ARCH_ASPEED || ARCH_BCMBCA || ARCH_BITMAIN || ARCH_REALTEK || ARCH_SOPHGO || ARCH_STM32 || (ARCH_INTEL_SOCFPGA && ARM64) || ARCH_SUNXI || ARC
217226
depends on HAS_IOMEM
218227
help
219228
This enables a simple reset controller driver for reset lines that
@@ -228,6 +237,7 @@ config RESET_SIMPLE
228237
- RCC reset controller in STM32 MCUs
229238
- Allwinner SoCs
230239
- SiFive FU740 SoCs
240+
- Sophgo SoCs
231241

232242
config RESET_SOCFPGA
233243
bool "SoCFPGA Reset Driver" if COMPILE_TEST && (!ARM || !ARCH_INTEL_SOCFPGA)

drivers/reset/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ obj-$(CONFIG_RESET_BCM6345) += reset-bcm6345.o
1111
obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
1212
obj-$(CONFIG_RESET_BRCMSTB) += reset-brcmstb.o
1313
obj-$(CONFIG_RESET_BRCMSTB_RESCAL) += reset-brcmstb-rescal.o
14+
obj-$(CONFIG_RESET_GPIO) += reset-gpio.o
1415
obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o
1516
obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
1617
obj-$(CONFIG_RESET_INTEL_GW) += reset-intel-gw.o

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;

0 commit comments

Comments
 (0)