Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

reset: Add reset controller API

This adds a simple API for devices to request being reset
by separate reset controller hardware and implements the
reset signal device tree binding.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Stephen Warren <swarren@nvidia.com>
Reviewed-by: Shawn Guo <shawn.guo@linaro.org>
Reviewed-by: Marek Vasut <marex@denx.de>
Reviewed-by: Pavel Machek <pavel@ucw.cz>

+384
+2
drivers/Kconfig
··· 162 162 163 163 source "drivers/ipack/Kconfig" 164 164 165 + source "drivers/reset/Kconfig" 166 + 165 167 endmenu
+3
drivers/Makefile
··· 37 37 # regulators early, since some subsystems rely on them to initialize 38 38 obj-$(CONFIG_REGULATOR) += regulator/ 39 39 40 + # reset controllers early, since gpu drivers might rely on them to initialize 41 + obj-$(CONFIG_RESET_CONTROLLER) += reset/ 42 + 40 43 # tty/ comes before char/ so that the VT console is the boot-time 41 44 # default. 42 45 obj-y += tty/
+13
drivers/reset/Kconfig
··· 1 + config ARCH_HAS_RESET_CONTROLLER 2 + bool 3 + 4 + menuconfig RESET_CONTROLLER 5 + bool "Reset Controller Support" 6 + default y if ARCH_HAS_RESET_CONTROLLER 7 + help 8 + Generic Reset Controller support. 9 + 10 + This framework is designed to abstract reset handling of devices 11 + via GPIOs or SoC-internal reset controller modules. 12 + 13 + If unsure, say no.
+1
drivers/reset/Makefile
··· 1 + obj-$(CONFIG_RESET_CONTROLLER) += core.o
+297
drivers/reset/core.c
··· 1 + /* 2 + * Reset Controller framework 3 + * 4 + * Copyright 2013 Philipp Zabel, Pengutronix 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License as published by 8 + * the Free Software Foundation; either version 2 of the License, or 9 + * (at your option) any later version. 10 + */ 11 + #include <linux/device.h> 12 + #include <linux/err.h> 13 + #include <linux/export.h> 14 + #include <linux/kernel.h> 15 + #include <linux/module.h> 16 + #include <linux/of.h> 17 + #include <linux/reset.h> 18 + #include <linux/reset-controller.h> 19 + #include <linux/slab.h> 20 + 21 + static DEFINE_MUTEX(reset_controller_list_mutex); 22 + static LIST_HEAD(reset_controller_list); 23 + 24 + /** 25 + * struct reset_control - a reset control 26 + * @rcdev: a pointer to the reset controller device 27 + * this reset control belongs to 28 + * @id: ID of the reset controller in the reset 29 + * controller device 30 + */ 31 + struct reset_control { 32 + struct reset_controller_dev *rcdev; 33 + struct device *dev; 34 + unsigned int id; 35 + }; 36 + 37 + /** 38 + * of_reset_simple_xlate - translate reset_spec to the reset line number 39 + * @rcdev: a pointer to the reset controller device 40 + * @reset_spec: reset line specifier as found in the device tree 41 + * @flags: a flags pointer to fill in (optional) 42 + * 43 + * This simple translation function should be used for reset controllers 44 + * with 1:1 mapping, where reset lines can be indexed by number without gaps. 45 + */ 46 + int of_reset_simple_xlate(struct reset_controller_dev *rcdev, 47 + const struct of_phandle_args *reset_spec) 48 + { 49 + if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells)) 50 + return -EINVAL; 51 + 52 + if (reset_spec->args[0] >= rcdev->nr_resets) 53 + return -EINVAL; 54 + 55 + return reset_spec->args[0]; 56 + } 57 + EXPORT_SYMBOL_GPL(of_reset_simple_xlate); 58 + 59 + /** 60 + * reset_controller_register - register a reset controller device 61 + * @rcdev: a pointer to the initialized reset controller device 62 + */ 63 + int reset_controller_register(struct reset_controller_dev *rcdev) 64 + { 65 + if (!rcdev->of_xlate) { 66 + rcdev->of_reset_n_cells = 1; 67 + rcdev->of_xlate = of_reset_simple_xlate; 68 + } 69 + 70 + mutex_lock(&reset_controller_list_mutex); 71 + list_add(&rcdev->list, &reset_controller_list); 72 + mutex_unlock(&reset_controller_list_mutex); 73 + 74 + return 0; 75 + } 76 + EXPORT_SYMBOL_GPL(reset_controller_register); 77 + 78 + /** 79 + * reset_controller_unregister - unregister a reset controller device 80 + * @rcdev: a pointer to the reset controller device 81 + */ 82 + void reset_controller_unregister(struct reset_controller_dev *rcdev) 83 + { 84 + mutex_lock(&reset_controller_list_mutex); 85 + list_del(&rcdev->list); 86 + mutex_unlock(&reset_controller_list_mutex); 87 + } 88 + EXPORT_SYMBOL_GPL(reset_controller_unregister); 89 + 90 + /** 91 + * reset_control_reset - reset the controlled device 92 + * @rstc: reset controller 93 + */ 94 + int reset_control_reset(struct reset_control *rstc) 95 + { 96 + if (rstc->rcdev->ops->reset) 97 + return rstc->rcdev->ops->reset(rstc->rcdev, rstc->id); 98 + 99 + return -ENOSYS; 100 + } 101 + EXPORT_SYMBOL_GPL(reset_control_reset); 102 + 103 + /** 104 + * reset_control_assert - asserts the reset line 105 + * @rstc: reset controller 106 + */ 107 + int reset_control_assert(struct reset_control *rstc) 108 + { 109 + if (rstc->rcdev->ops->assert) 110 + return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id); 111 + 112 + return -ENOSYS; 113 + } 114 + EXPORT_SYMBOL_GPL(reset_control_assert); 115 + 116 + /** 117 + * reset_control_deassert - deasserts the reset line 118 + * @rstc: reset controller 119 + */ 120 + int reset_control_deassert(struct reset_control *rstc) 121 + { 122 + if (rstc->rcdev->ops->deassert) 123 + return rstc->rcdev->ops->deassert(rstc->rcdev, rstc->id); 124 + 125 + return -ENOSYS; 126 + } 127 + EXPORT_SYMBOL_GPL(reset_control_deassert); 128 + 129 + /** 130 + * reset_control_get - Lookup and obtain a reference to a reset controller. 131 + * @dev: device to be reset by the controller 132 + * @id: reset line name 133 + * 134 + * Returns a struct reset_control or IS_ERR() condition containing errno. 135 + * 136 + * Use of id names is optional. 137 + */ 138 + struct reset_control *reset_control_get(struct device *dev, const char *id) 139 + { 140 + struct reset_control *rstc = ERR_PTR(-EPROBE_DEFER); 141 + struct reset_controller_dev *r, *rcdev; 142 + struct of_phandle_args args; 143 + int index = 0; 144 + int rstc_id; 145 + int ret; 146 + 147 + if (!dev) 148 + return ERR_PTR(-EINVAL); 149 + 150 + if (id) 151 + index = of_property_match_string(dev->of_node, 152 + "reset-names", id); 153 + ret = of_parse_phandle_with_args(dev->of_node, "resets", "#reset-cells", 154 + index, &args); 155 + if (ret) 156 + return ERR_PTR(ret); 157 + 158 + mutex_lock(&reset_controller_list_mutex); 159 + rcdev = NULL; 160 + list_for_each_entry(r, &reset_controller_list, list) { 161 + if (args.np == r->of_node) { 162 + rcdev = r; 163 + break; 164 + } 165 + } 166 + of_node_put(args.np); 167 + 168 + if (!rcdev) { 169 + mutex_unlock(&reset_controller_list_mutex); 170 + return ERR_PTR(-ENODEV); 171 + } 172 + 173 + rstc_id = rcdev->of_xlate(rcdev, &args); 174 + if (rstc_id < 0) { 175 + mutex_unlock(&reset_controller_list_mutex); 176 + return ERR_PTR(rstc_id); 177 + } 178 + 179 + try_module_get(rcdev->owner); 180 + mutex_unlock(&reset_controller_list_mutex); 181 + 182 + rstc = kzalloc(sizeof(*rstc), GFP_KERNEL); 183 + if (!rstc) { 184 + module_put(rstc->rcdev->owner); 185 + return ERR_PTR(-ENOMEM); 186 + } 187 + 188 + rstc->dev = dev; 189 + rstc->rcdev = rcdev; 190 + rstc->id = rstc_id; 191 + 192 + return rstc; 193 + } 194 + EXPORT_SYMBOL_GPL(reset_control_get); 195 + 196 + /** 197 + * reset_control_put - free the reset controller 198 + * @rstc: reset controller 199 + */ 200 + 201 + void reset_control_put(struct reset_control *rstc) 202 + { 203 + if (IS_ERR(rstc)) 204 + return; 205 + 206 + module_put(rstc->rcdev->owner); 207 + kfree(rstc); 208 + } 209 + EXPORT_SYMBOL_GPL(reset_control_put); 210 + 211 + static void devm_reset_control_release(struct device *dev, void *res) 212 + { 213 + reset_control_put(*(struct reset_control **)res); 214 + } 215 + 216 + /** 217 + * devm_reset_control_get - resource managed reset_control_get() 218 + * @dev: device to be reset by the controller 219 + * @id: reset line name 220 + * 221 + * Managed reset_control_get(). For reset controllers returned from this 222 + * function, reset_control_put() is called automatically on driver detach. 223 + * See reset_control_get() for more information. 224 + */ 225 + struct reset_control *devm_reset_control_get(struct device *dev, const char *id) 226 + { 227 + struct reset_control **ptr, *rstc; 228 + 229 + ptr = devres_alloc(devm_reset_control_release, sizeof(*ptr), 230 + GFP_KERNEL); 231 + if (!ptr) 232 + return ERR_PTR(-ENOMEM); 233 + 234 + rstc = reset_control_get(dev, id); 235 + if (!IS_ERR(rstc)) { 236 + *ptr = rstc; 237 + devres_add(dev, ptr); 238 + } else { 239 + devres_free(ptr); 240 + } 241 + 242 + return rstc; 243 + } 244 + EXPORT_SYMBOL_GPL(devm_reset_control_get); 245 + 246 + static int devm_reset_control_match(struct device *dev, void *res, void *data) 247 + { 248 + struct reset_control **rstc = res; 249 + if (WARN_ON(!rstc || !*rstc)) 250 + return 0; 251 + return *rstc == data; 252 + } 253 + 254 + /** 255 + * devm_reset_control_put - resource managed reset_control_put() 256 + * @rstc: reset controller to free 257 + * 258 + * Deallocate a reset control allocated withd devm_reset_control_get(). 259 + * This function will not need to be called normally, as devres will take 260 + * care of freeing the resource. 261 + */ 262 + void devm_reset_control_put(struct reset_control *rstc) 263 + { 264 + int ret; 265 + 266 + ret = devres_release(rstc->dev, devm_reset_control_release, 267 + devm_reset_control_match, rstc); 268 + if (ret) 269 + WARN_ON(ret); 270 + } 271 + EXPORT_SYMBOL_GPL(devm_reset_control_put); 272 + 273 + /** 274 + * device_reset - find reset controller associated with the device 275 + * and perform reset 276 + * @dev: device to be reset by the controller 277 + * 278 + * Convenience wrapper for reset_control_get() and reset_control_reset(). 279 + * This is useful for the common case of devices with single, dedicated reset 280 + * lines. 281 + */ 282 + int device_reset(struct device *dev) 283 + { 284 + struct reset_control *rstc; 285 + int ret; 286 + 287 + rstc = reset_control_get(dev, NULL); 288 + if (IS_ERR(rstc)) 289 + return PTR_ERR(rstc); 290 + 291 + ret = reset_control_reset(rstc); 292 + 293 + reset_control_put(rstc); 294 + 295 + return ret; 296 + } 297 + EXPORT_SYMBOL_GPL(device_reset);
+51
include/linux/reset-controller.h
··· 1 + #ifndef _LINUX_RESET_CONTROLLER_H_ 2 + #define _LINUX_RESET_CONTROLLER_H_ 3 + 4 + #include <linux/list.h> 5 + 6 + struct reset_controller_dev; 7 + 8 + /** 9 + * struct reset_control_ops 10 + * 11 + * @reset: for self-deasserting resets, does all necessary 12 + * things to reset the device 13 + * @assert: manually assert the reset line, if supported 14 + * @deassert: manually deassert the reset line, if supported 15 + */ 16 + struct reset_control_ops { 17 + int (*reset)(struct reset_controller_dev *rcdev, unsigned long id); 18 + int (*assert)(struct reset_controller_dev *rcdev, unsigned long id); 19 + int (*deassert)(struct reset_controller_dev *rcdev, unsigned long id); 20 + }; 21 + 22 + struct module; 23 + struct device_node; 24 + 25 + /** 26 + * struct reset_controller_dev - reset controller entity that might 27 + * provide multiple reset controls 28 + * @ops: a pointer to device specific struct reset_control_ops 29 + * @owner: kernel module of the reset controller driver 30 + * @list: internal list of reset controller devices 31 + * @of_node: corresponding device tree node as phandle target 32 + * @of_reset_n_cells: number of cells in reset line specifiers 33 + * @of_xlate: translation function to translate from specifier as found in the 34 + * device tree to id as given to the reset control ops 35 + * @nr_resets: number of reset controls in this reset controller device 36 + */ 37 + struct reset_controller_dev { 38 + struct reset_control_ops *ops; 39 + struct module *owner; 40 + struct list_head list; 41 + struct device_node *of_node; 42 + int of_reset_n_cells; 43 + int (*of_xlate)(struct reset_controller_dev *rcdev, 44 + const struct of_phandle_args *reset_spec); 45 + unsigned int nr_resets; 46 + }; 47 + 48 + int reset_controller_register(struct reset_controller_dev *rcdev); 49 + void reset_controller_unregister(struct reset_controller_dev *rcdev); 50 + 51 + #endif
+17
include/linux/reset.h
··· 1 + #ifndef _LINUX_RESET_H_ 2 + #define _LINUX_RESET_H_ 3 + 4 + struct device; 5 + struct reset_control; 6 + 7 + int reset_control_reset(struct reset_control *rstc); 8 + int reset_control_assert(struct reset_control *rstc); 9 + int reset_control_deassert(struct reset_control *rstc); 10 + 11 + struct reset_control *reset_control_get(struct device *dev, const char *id); 12 + void reset_control_put(struct reset_control *rstc); 13 + struct reset_control *devm_reset_control_get(struct device *dev, const char *id); 14 + 15 + int device_reset(struct device *dev); 16 + 17 + #endif