Blame view
drivers/reset/gpio-reset.c
5.13 KB
6eadbeb9d reset: Add driver... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/* * GPIO Reset Controller driver * * Copyright 2013 Philipp Zabel, Pengutronix * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #include <linux/delay.h> #include <linux/err.h> #include <linux/gpio.h> #include <linux/module.h> #include <linux/of_gpio.h> #include <linux/platform_device.h> |
7ebf183b7 reset: gpio-reset... |
17 |
#include <linux/pinctrl/consumer.h> |
6eadbeb9d reset: Add driver... |
18 19 20 21 22 23 24 |
#include <linux/reset-controller.h> struct gpio_reset_data { struct reset_controller_dev rcdev; unsigned int gpio; bool active_low; s32 delay_us; |
42bc632a3 MLK-15092 reset: ... |
25 |
s32 post_delay_ms; |
6eadbeb9d reset: Add driver... |
26 27 28 29 30 31 32 33 34 35 |
}; static void gpio_reset_set(struct reset_controller_dev *rcdev, int asserted) { struct gpio_reset_data *drvdata = container_of(rcdev, struct gpio_reset_data, rcdev); int value = asserted; if (drvdata->active_low) value = !value; |
ff040dc47 MLK-14498-11 rese... |
36 |
gpio_set_value_cansleep(drvdata->gpio, value); |
6eadbeb9d reset: Add driver... |
37 38 39 40 41 42 43 44 45 46 47 48 49 |
} static int gpio_reset(struct reset_controller_dev *rcdev, unsigned long id) { struct gpio_reset_data *drvdata = container_of(rcdev, struct gpio_reset_data, rcdev); if (drvdata->delay_us < 0) return -ENOSYS; gpio_reset_set(rcdev, 1); udelay(drvdata->delay_us); gpio_reset_set(rcdev, 0); |
42bc632a3 MLK-15092 reset: ... |
50 51 52 53 |
if (drvdata->post_delay_ms < 0) return 0; msleep(drvdata->post_delay_ms); |
6eadbeb9d reset: Add driver... |
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
return 0; } static int gpio_reset_assert(struct reset_controller_dev *rcdev, unsigned long id) { gpio_reset_set(rcdev, 1); return 0; } static int gpio_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id) { gpio_reset_set(rcdev, 0); return 0; } static struct reset_control_ops gpio_reset_ops = { .reset = gpio_reset, .assert = gpio_reset_assert, .deassert = gpio_reset_deassert, }; static int of_gpio_reset_xlate(struct reset_controller_dev *rcdev, const struct of_phandle_args *reset_spec) { if (WARN_ON(reset_spec->args_count != 0)) return -EINVAL; return 0; } static int gpio_reset_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct gpio_reset_data *drvdata; enum of_gpio_flags flags; unsigned long gpio_flags; bool initially_in_reset; int ret; drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); if (drvdata == NULL) return -ENOMEM; if (of_gpio_named_count(np, "reset-gpios") != 1) { dev_err(&pdev->dev, "reset-gpios property missing, or not a single gpio "); return -EINVAL; } drvdata->gpio = of_get_named_gpio_flags(np, "reset-gpios", 0, &flags); if (drvdata->gpio == -EPROBE_DEFER) { return drvdata->gpio; } else if (!gpio_is_valid(drvdata->gpio)) { dev_err(&pdev->dev, "invalid reset gpio: %d ", drvdata->gpio); return drvdata->gpio; } drvdata->active_low = flags & OF_GPIO_ACTIVE_LOW; ret = of_property_read_u32(np, "reset-delay-us", &drvdata->delay_us); if (ret < 0) drvdata->delay_us = -1; else if (drvdata->delay_us < 0) dev_warn(&pdev->dev, "reset delay too high "); |
42bc632a3 MLK-15092 reset: ... |
125 126 127 128 129 130 |
/* It is optional. * Some devices need some milliseconds to wait after reset. */ ret = of_property_read_u32(np, "reset-post-delay-ms", &drvdata->post_delay_ms); if (ret < 0) drvdata->post_delay_ms = -1; |
6eadbeb9d reset: Add driver... |
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
initially_in_reset = of_property_read_bool(np, "initially-in-reset"); if (drvdata->active_low ^ initially_in_reset) gpio_flags = GPIOF_OUT_INIT_HIGH; else gpio_flags = GPIOF_OUT_INIT_LOW; ret = devm_gpio_request_one(&pdev->dev, drvdata->gpio, gpio_flags, NULL); if (ret < 0) { dev_err(&pdev->dev, "failed to request gpio %d: %d ", drvdata->gpio, ret); return ret; } platform_set_drvdata(pdev, drvdata); drvdata->rcdev.of_node = np; drvdata->rcdev.owner = THIS_MODULE; drvdata->rcdev.nr_resets = 1; drvdata->rcdev.ops = &gpio_reset_ops; drvdata->rcdev.of_xlate = of_gpio_reset_xlate; reset_controller_register(&drvdata->rcdev); return 0; } static int gpio_reset_remove(struct platform_device *pdev) { struct gpio_reset_data *drvdata = platform_get_drvdata(pdev); reset_controller_unregister(&drvdata->rcdev); return 0; } static struct of_device_id gpio_reset_dt_ids[] = { { .compatible = "gpio-reset" }, { } }; |
5fa306fe1 MLK-20682 reset: ... |
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
#ifdef CONFIG_PM_SLEEP static int gpio_reset_suspend(struct device *dev) { pinctrl_pm_select_sleep_state(dev); return 0; } static int gpio_reset_resume(struct device *dev) { pinctrl_pm_select_default_state(dev); return 0; } #endif static const struct dev_pm_ops gpio_reset_pm_ops = { SET_LATE_SYSTEM_SLEEP_PM_OPS(gpio_reset_suspend, gpio_reset_resume) }; |
6eadbeb9d reset: Add driver... |
188 189 190 191 192 193 194 |
static struct platform_driver gpio_reset_driver = { .probe = gpio_reset_probe, .remove = gpio_reset_remove, .driver = { .name = "gpio-reset", .owner = THIS_MODULE, .of_match_table = of_match_ptr(gpio_reset_dt_ids), |
5fa306fe1 MLK-20682 reset: ... |
195 |
.pm = &gpio_reset_pm_ops, |
6eadbeb9d reset: Add driver... |
196 197 |
}, }; |
066d08ca3 MLK-11395-1: rese... |
198 199 200 201 202 203 204 205 206 207 208 |
static int __init gpio_reset_init(void) { return platform_driver_register(&gpio_reset_driver); } arch_initcall(gpio_reset_init); static void __exit gpio_reset_exit(void) { platform_driver_unregister(&gpio_reset_driver); } module_exit(gpio_reset_exit); |
6eadbeb9d reset: Add driver... |
209 210 211 212 213 214 |
MODULE_AUTHOR("Philipp Zabel <p.zabel@pengutronix.de>"); MODULE_DESCRIPTION("gpio reset controller"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:gpio-reset"); MODULE_DEVICE_TABLE(of, gpio_reset_dt_ids); |