1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * TI TPS380x Supply Voltage Supervisor and Reset Controller Driver
5 * Copyright (C) 2022 Pengutronix, Marco Felsch <kernel@pengutronix.de>
7 * Based on Simple Reset Controller Driver
9 * Copyright (C) 2017 Pengutronix, Philipp Zabel <kernel@pengutronix.de>
12 #include <linux/delay.h>
13 #include <linux/gpio/consumer.h>
14 #include <linux/module.h>
16 #include <linux/platform_device.h>
17 #include <linux/property.h>
18 #include <linux/reset-controller.h>
20 struct tps380x_reset
{
21 struct reset_controller_dev rcdev
;
22 struct gpio_desc
*reset_gpio
;
23 unsigned int reset_ms
;
26 struct tps380x_reset_devdata
{
27 unsigned int min_reset_ms
;
28 unsigned int typ_reset_ms
;
29 unsigned int max_reset_ms
;
33 struct tps380x_reset
*to_tps380x_reset(struct reset_controller_dev
*rcdev
)
35 return container_of(rcdev
, struct tps380x_reset
, rcdev
);
39 tps380x_reset_assert(struct reset_controller_dev
*rcdev
, unsigned long id
)
41 struct tps380x_reset
*tps380x
= to_tps380x_reset(rcdev
);
43 gpiod_set_value_cansleep(tps380x
->reset_gpio
, 1);
49 tps380x_reset_deassert(struct reset_controller_dev
*rcdev
, unsigned long id
)
51 struct tps380x_reset
*tps380x
= to_tps380x_reset(rcdev
);
53 gpiod_set_value_cansleep(tps380x
->reset_gpio
, 0);
54 msleep(tps380x
->reset_ms
);
59 static const struct reset_control_ops reset_tps380x_ops
= {
60 .assert = tps380x_reset_assert
,
61 .deassert
= tps380x_reset_deassert
,
64 static int tps380x_reset_of_xlate(struct reset_controller_dev
*rcdev
,
65 const struct of_phandle_args
*reset_spec
)
67 /* No special handling needed, we have only one reset line per device */
71 static int tps380x_reset_probe(struct platform_device
*pdev
)
73 struct device
*dev
= &pdev
->dev
;
74 const struct tps380x_reset_devdata
*devdata
;
75 struct tps380x_reset
*tps380x
;
77 devdata
= device_get_match_data(dev
);
81 tps380x
= devm_kzalloc(dev
, sizeof(*tps380x
), GFP_KERNEL
);
85 tps380x
->reset_gpio
= devm_gpiod_get(dev
, "reset", GPIOD_OUT_HIGH
);
86 if (IS_ERR(tps380x
->reset_gpio
))
87 return dev_err_probe(dev
, PTR_ERR(tps380x
->reset_gpio
),
88 "Failed to get GPIO\n");
90 tps380x
->reset_ms
= devdata
->max_reset_ms
;
92 tps380x
->rcdev
.ops
= &reset_tps380x_ops
;
93 tps380x
->rcdev
.owner
= THIS_MODULE
;
94 tps380x
->rcdev
.dev
= dev
;
95 tps380x
->rcdev
.of_node
= dev
->of_node
;
96 tps380x
->rcdev
.of_reset_n_cells
= 0;
97 tps380x
->rcdev
.of_xlate
= tps380x_reset_of_xlate
;
98 tps380x
->rcdev
.nr_resets
= 1;
100 return devm_reset_controller_register(dev
, &tps380x
->rcdev
);
103 static const struct tps380x_reset_devdata tps3801_reset_data
= {
109 static const struct of_device_id tps380x_reset_dt_ids
[] = {
110 { .compatible
= "ti,tps3801", .data
= &tps3801_reset_data
},
113 MODULE_DEVICE_TABLE(of
, tps380x_reset_dt_ids
);
115 static struct platform_driver tps380x_reset_driver
= {
116 .probe
= tps380x_reset_probe
,
118 .name
= "tps380x-reset",
119 .of_match_table
= tps380x_reset_dt_ids
,
122 module_platform_driver(tps380x_reset_driver
);
124 MODULE_AUTHOR("Marco Felsch <kernel@pengutronix.de>");
125 MODULE_DESCRIPTION("TI TPS380x Supply Voltage Supervisor and Reset Driver");
126 MODULE_LICENSE("GPL v2");