Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * TI TPS380x Supply Voltage Supervisor and Reset Controller Driver
0004  *
0005  * Copyright (C) 2022 Pengutronix, Marco Felsch <kernel@pengutronix.de>
0006  *
0007  * Based on Simple Reset Controller Driver
0008  *
0009  * Copyright (C) 2017 Pengutronix, Philipp Zabel <kernel@pengutronix.de>
0010  */
0011 
0012 #include <linux/delay.h>
0013 #include <linux/gpio/consumer.h>
0014 #include <linux/module.h>
0015 #include <linux/of.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/property.h>
0018 #include <linux/reset-controller.h>
0019 
0020 struct tps380x_reset {
0021     struct reset_controller_dev rcdev;
0022     struct gpio_desc        *reset_gpio;
0023     unsigned int            reset_ms;
0024 };
0025 
0026 struct tps380x_reset_devdata {
0027     unsigned int min_reset_ms;
0028     unsigned int typ_reset_ms;
0029     unsigned int max_reset_ms;
0030 };
0031 
0032 static inline
0033 struct tps380x_reset *to_tps380x_reset(struct reset_controller_dev *rcdev)
0034 {
0035     return container_of(rcdev, struct tps380x_reset, rcdev);
0036 }
0037 
0038 static int
0039 tps380x_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
0040 {
0041     struct tps380x_reset *tps380x = to_tps380x_reset(rcdev);
0042 
0043     gpiod_set_value_cansleep(tps380x->reset_gpio, 1);
0044 
0045     return 0;
0046 }
0047 
0048 static int
0049 tps380x_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
0050 {
0051     struct tps380x_reset *tps380x = to_tps380x_reset(rcdev);
0052 
0053     gpiod_set_value_cansleep(tps380x->reset_gpio, 0);
0054     msleep(tps380x->reset_ms);
0055 
0056     return 0;
0057 }
0058 
0059 static const struct reset_control_ops reset_tps380x_ops = {
0060     .assert     = tps380x_reset_assert,
0061     .deassert   = tps380x_reset_deassert,
0062 };
0063 
0064 static int tps380x_reset_of_xlate(struct reset_controller_dev *rcdev,
0065                   const struct of_phandle_args *reset_spec)
0066 {
0067     /* No special handling needed, we have only one reset line per device */
0068     return 0;
0069 }
0070 
0071 static int tps380x_reset_probe(struct platform_device *pdev)
0072 {
0073     struct device *dev = &pdev->dev;
0074     const struct tps380x_reset_devdata *devdata;
0075     struct tps380x_reset *tps380x;
0076 
0077     devdata = device_get_match_data(dev);
0078     if (!devdata)
0079         return -EINVAL;
0080 
0081     tps380x = devm_kzalloc(dev, sizeof(*tps380x), GFP_KERNEL);
0082     if (!tps380x)
0083         return -ENOMEM;
0084 
0085     tps380x->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
0086     if (IS_ERR(tps380x->reset_gpio))
0087         return dev_err_probe(dev, PTR_ERR(tps380x->reset_gpio),
0088                      "Failed to get GPIO\n");
0089 
0090     tps380x->reset_ms = devdata->max_reset_ms;
0091 
0092     tps380x->rcdev.ops = &reset_tps380x_ops;
0093     tps380x->rcdev.owner = THIS_MODULE;
0094     tps380x->rcdev.dev = dev;
0095     tps380x->rcdev.of_node = dev->of_node;
0096     tps380x->rcdev.of_reset_n_cells = 0;
0097     tps380x->rcdev.of_xlate = tps380x_reset_of_xlate;
0098     tps380x->rcdev.nr_resets = 1;
0099 
0100     return devm_reset_controller_register(dev, &tps380x->rcdev);
0101 }
0102 
0103 static const struct tps380x_reset_devdata tps3801_reset_data = {
0104     .min_reset_ms = 120,
0105     .typ_reset_ms = 200,
0106     .max_reset_ms = 280,
0107 };
0108 
0109 static const struct of_device_id tps380x_reset_dt_ids[] = {
0110     { .compatible = "ti,tps3801", .data = &tps3801_reset_data },
0111     { /* sentinel */ },
0112 };
0113 MODULE_DEVICE_TABLE(of, tps380x_reset_dt_ids);
0114 
0115 static struct platform_driver tps380x_reset_driver = {
0116     .probe  = tps380x_reset_probe,
0117     .driver = {
0118         .name       = "tps380x-reset",
0119         .of_match_table = tps380x_reset_dt_ids,
0120     },
0121 };
0122 module_platform_driver(tps380x_reset_driver);
0123 
0124 MODULE_AUTHOR("Marco Felsch <kernel@pengutronix.de>");
0125 MODULE_DESCRIPTION("TI TPS380x Supply Voltage Supervisor and Reset Driver");
0126 MODULE_LICENSE("GPL v2");