From 8a4e6154fb17b691917dcf7f4b0cc1d2fb8d46c6 Mon Sep 17 00:00:00 2001 From: Marco Felsch Date: Mon, 30 May 2022 11:22:26 +0200 Subject: reset: tps380x: Add TPS380x device driver supprt The TI TPS380x family [1] is a voltage supervisor with a dedicated manual reset (mr) line input and a reset output. The chip(s) have a build in reset delay, depending on the chip partnumber. This simple driver addresses this so the cosumer don't need to care about it. [1] https://www.ti.com/product/TPS3801 Signed-off-by: Marco Felsch [p.zabel@pengutronix.de: drop Todo comment about min/typ/max reset time] Signed-off-by: Philipp Zabel Link: https://lore.kernel.org/r/20220530092226.748644-2-m.felsch@pengutronix.de --- drivers/reset/reset-tps380x.c | 126 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 drivers/reset/reset-tps380x.c (limited to 'drivers/reset/reset-tps380x.c') diff --git a/drivers/reset/reset-tps380x.c b/drivers/reset/reset-tps380x.c new file mode 100644 index 000000000000..e07f5865fe30 --- /dev/null +++ b/drivers/reset/reset-tps380x.c @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * TI TPS380x Supply Voltage Supervisor and Reset Controller Driver + * + * Copyright (C) 2022 Pengutronix, Marco Felsch + * + * Based on Simple Reset Controller Driver + * + * Copyright (C) 2017 Pengutronix, Philipp Zabel + */ + +#include +#include +#include +#include +#include +#include +#include + +struct tps380x_reset { + struct reset_controller_dev rcdev; + struct gpio_desc *reset_gpio; + unsigned int reset_ms; +}; + +struct tps380x_reset_devdata { + unsigned int min_reset_ms; + unsigned int typ_reset_ms; + unsigned int max_reset_ms; +}; + +static inline +struct tps380x_reset *to_tps380x_reset(struct reset_controller_dev *rcdev) +{ + return container_of(rcdev, struct tps380x_reset, rcdev); +} + +static int +tps380x_reset_assert(struct reset_controller_dev *rcdev, unsigned long id) +{ + struct tps380x_reset *tps380x = to_tps380x_reset(rcdev); + + gpiod_set_value_cansleep(tps380x->reset_gpio, 1); + + return 0; +} + +static int +tps380x_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id) +{ + struct tps380x_reset *tps380x = to_tps380x_reset(rcdev); + + gpiod_set_value_cansleep(tps380x->reset_gpio, 0); + msleep(tps380x->reset_ms); + + return 0; +} + +static const struct reset_control_ops reset_tps380x_ops = { + .assert = tps380x_reset_assert, + .deassert = tps380x_reset_deassert, +}; + +static int tps380x_reset_of_xlate(struct reset_controller_dev *rcdev, + const struct of_phandle_args *reset_spec) +{ + /* No special handling needed, we have only one reset line per device */ + return 0; +} + +static int tps380x_reset_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + const struct tps380x_reset_devdata *devdata; + struct tps380x_reset *tps380x; + + devdata = device_get_match_data(dev); + if (!devdata) + return -EINVAL; + + tps380x = devm_kzalloc(dev, sizeof(*tps380x), GFP_KERNEL); + if (!tps380x) + return -ENOMEM; + + tps380x->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(tps380x->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(tps380x->reset_gpio), + "Failed to get GPIO\n"); + + tps380x->reset_ms = devdata->max_reset_ms; + + tps380x->rcdev.ops = &reset_tps380x_ops; + tps380x->rcdev.owner = THIS_MODULE; + tps380x->rcdev.dev = dev; + tps380x->rcdev.of_node = dev->of_node; + tps380x->rcdev.of_reset_n_cells = 0; + tps380x->rcdev.of_xlate = tps380x_reset_of_xlate; + tps380x->rcdev.nr_resets = 1; + + return devm_reset_controller_register(dev, &tps380x->rcdev); +} + +static const struct tps380x_reset_devdata tps3801_reset_data = { + .min_reset_ms = 120, + .typ_reset_ms = 200, + .max_reset_ms = 280, +}; + +static const struct of_device_id tps380x_reset_dt_ids[] = { + { .compatible = "ti,tps3801", .data = &tps3801_reset_data }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, tps380x_reset_dt_ids); + +static struct platform_driver tps380x_reset_driver = { + .probe = tps380x_reset_probe, + .driver = { + .name = "tps380x-reset", + .of_match_table = tps380x_reset_dt_ids, + }, +}; +module_platform_driver(tps380x_reset_driver); + +MODULE_AUTHOR("Marco Felsch "); +MODULE_DESCRIPTION("TI TPS380x Supply Voltags Supervisor and Reset Driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From d985db83622679fc496ed824088e066528b3a872 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 28 Jul 2022 12:05:54 +0100 Subject: reset: tps380x: Fix spelling mistake "Voltags" -> "Voltage" There is a spelling mistake in the MODULE_DESCRIPTION text. Fix it. Signed-off-by: Colin Ian King Signed-off-by: Philipp Zabel Link: https://lore.kernel.org/r/20220728110554.18320-1-colin.i.king@gmail.com --- drivers/reset/reset-tps380x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/reset/reset-tps380x.c') diff --git a/drivers/reset/reset-tps380x.c b/drivers/reset/reset-tps380x.c index e07f5865fe30..09d511f069ba 100644 --- a/drivers/reset/reset-tps380x.c +++ b/drivers/reset/reset-tps380x.c @@ -122,5 +122,5 @@ static struct platform_driver tps380x_reset_driver = { module_platform_driver(tps380x_reset_driver); MODULE_AUTHOR("Marco Felsch "); -MODULE_DESCRIPTION("TI TPS380x Supply Voltags Supervisor and Reset Driver"); +MODULE_DESCRIPTION("TI TPS380x Supply Voltage Supervisor and Reset Driver"); MODULE_LICENSE("GPL v2"); -- cgit v1.2.3