Reset controller changes for v4.7
- add support for shared reset controls - remove global variables from the lpc18xx driver -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJW+/1XAAoJEFDCiBxwnmDrRzEQAO0GQqAEPPKMLYTIhGYPBG3M XGv7kcFNy3AJAXrHyDVuZ2lDc1M2nM2jk80YFcddtapeFAl3EHRqwdigwfpo7sK/ uKamcY/yeOlG+EWFyC4V4ULkZk4ZT4LmW9qqI/o4GFUIF7mAuOt/6+fbLhLGzVyy lhPbpMeZLaLxaa6ig2MECc01XHhZRtnlDaQ3LgMkht6C5S0VvIPt+ykstYmW11UZ vHvdenG0rz/LV5GaXadj2F9tv1hhKbQ77qusvOmMdHF476XQNpXOKdZdcdzAYZrc cT8ZjFdkr1QLFBjEMl8uOV8giGNvxzzGk5JcG812nolkRbT+g+wUkUB2vXYF1+a7 HugmkG1AMu6C8ib1sComGvB0sM8e4vlEznWl8B3/6BR9alyrFTrdlBdHHgTcvYQD 2QxcUCadcjrhMCuPk7r8HgqmG2890X4oCZtAr+G/MhRiuDxj7AIcPrXT7IrFa/9x QgwIA0ZyDfe7tii6YqnKYMIlXettNUVGA+hxq/5KWQ52q2orHI4a4WsXTf30VpEu coBQA2d2pvUXU6vwGz12ocK2j8CqHIMKN+H8/p+qiIqbENLD1sz2jYQZfJTS4TYT gR+b3hjqUe1r7jJph/+lsTpMdN3U8Ky8pAJWTG5UVybb8ic0de8d9HxRslyXD07Z /yV4L9BrVctBF1bBRNyI =T/DD -----END PGP SIGNATURE----- Merge tag 'reset-for-4.7' of git://git.pengutronix.de/git/pza/linux into next/drivers Reset controller changes for v4.7 - add support for shared reset controls - remove global variables from the lpc18xx driver * tag 'reset-for-4.7' of git://git.pengutronix.de/git/pza/linux: reset: lpc18xx: get rid of global variables for restart notifier reset: Add support for shared reset controls reset: Share struct reset_control between reset_control_get calls reset: Make [of_]reset_control_get[_foo] functions wrappers Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
commit
f8ed1e1a45
|
@ -8,6 +8,7 @@
|
|||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/export.h>
|
||||
|
@ -18,19 +19,27 @@
|
|||
#include <linux/reset-controller.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
static DEFINE_MUTEX(reset_controller_list_mutex);
|
||||
static DEFINE_MUTEX(reset_list_mutex);
|
||||
static LIST_HEAD(reset_controller_list);
|
||||
|
||||
/**
|
||||
* struct reset_control - a reset control
|
||||
* @rcdev: a pointer to the reset controller device
|
||||
* this reset control belongs to
|
||||
* @list: list entry for the rcdev's reset controller list
|
||||
* @id: ID of the reset controller in the reset
|
||||
* controller device
|
||||
* @refcnt: Number of gets of this reset_control
|
||||
* @shared: Is this a shared (1), or an exclusive (0) reset_control?
|
||||
* @deassert_cnt: Number of times this reset line has been deasserted
|
||||
*/
|
||||
struct reset_control {
|
||||
struct reset_controller_dev *rcdev;
|
||||
struct list_head list;
|
||||
unsigned int id;
|
||||
unsigned int refcnt;
|
||||
int shared;
|
||||
atomic_t deassert_count;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -62,9 +71,11 @@ int reset_controller_register(struct reset_controller_dev *rcdev)
|
|||
rcdev->of_xlate = of_reset_simple_xlate;
|
||||
}
|
||||
|
||||
mutex_lock(&reset_controller_list_mutex);
|
||||
INIT_LIST_HEAD(&rcdev->reset_control_head);
|
||||
|
||||
mutex_lock(&reset_list_mutex);
|
||||
list_add(&rcdev->list, &reset_controller_list);
|
||||
mutex_unlock(&reset_controller_list_mutex);
|
||||
mutex_unlock(&reset_list_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -76,18 +87,23 @@ EXPORT_SYMBOL_GPL(reset_controller_register);
|
|||
*/
|
||||
void reset_controller_unregister(struct reset_controller_dev *rcdev)
|
||||
{
|
||||
mutex_lock(&reset_controller_list_mutex);
|
||||
mutex_lock(&reset_list_mutex);
|
||||
list_del(&rcdev->list);
|
||||
mutex_unlock(&reset_controller_list_mutex);
|
||||
mutex_unlock(&reset_list_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reset_controller_unregister);
|
||||
|
||||
/**
|
||||
* reset_control_reset - reset the controlled device
|
||||
* @rstc: reset controller
|
||||
*
|
||||
* Calling this on a shared reset controller is an error.
|
||||
*/
|
||||
int reset_control_reset(struct reset_control *rstc)
|
||||
{
|
||||
if (WARN_ON(rstc->shared))
|
||||
return -EINVAL;
|
||||
|
||||
if (rstc->rcdev->ops->reset)
|
||||
return rstc->rcdev->ops->reset(rstc->rcdev, rstc->id);
|
||||
|
||||
|
@ -98,26 +114,48 @@ EXPORT_SYMBOL_GPL(reset_control_reset);
|
|||
/**
|
||||
* reset_control_assert - asserts the reset line
|
||||
* @rstc: reset controller
|
||||
*
|
||||
* Calling this on an exclusive reset controller guarantees that the reset
|
||||
* will be asserted. When called on a shared reset controller the line may
|
||||
* still be deasserted, as long as other users keep it so.
|
||||
*
|
||||
* For shared reset controls a driver cannot expect the hw's registers and
|
||||
* internal state to be reset, but must be prepared for this to happen.
|
||||
*/
|
||||
int reset_control_assert(struct reset_control *rstc)
|
||||
{
|
||||
if (rstc->rcdev->ops->assert)
|
||||
return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id);
|
||||
if (!rstc->rcdev->ops->assert)
|
||||
return -ENOTSUPP;
|
||||
|
||||
return -ENOTSUPP;
|
||||
if (rstc->shared) {
|
||||
if (WARN_ON(atomic_read(&rstc->deassert_count) == 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (atomic_dec_return(&rstc->deassert_count) != 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reset_control_assert);
|
||||
|
||||
/**
|
||||
* reset_control_deassert - deasserts the reset line
|
||||
* @rstc: reset controller
|
||||
*
|
||||
* After calling this function, the reset is guaranteed to be deasserted.
|
||||
*/
|
||||
int reset_control_deassert(struct reset_control *rstc)
|
||||
{
|
||||
if (rstc->rcdev->ops->deassert)
|
||||
return rstc->rcdev->ops->deassert(rstc->rcdev, rstc->id);
|
||||
if (!rstc->rcdev->ops->deassert)
|
||||
return -ENOTSUPP;
|
||||
|
||||
return -ENOTSUPP;
|
||||
if (rstc->shared) {
|
||||
if (atomic_inc_return(&rstc->deassert_count) != 1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rstc->rcdev->ops->deassert(rstc->rcdev, rstc->id);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reset_control_deassert);
|
||||
|
||||
|
@ -136,18 +174,54 @@ int reset_control_status(struct reset_control *rstc)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(reset_control_status);
|
||||
|
||||
/**
|
||||
* of_reset_control_get_by_index - Lookup and obtain a reference to a reset
|
||||
* controller by index.
|
||||
* @node: device to be reset by the controller
|
||||
* @index: index of the reset controller
|
||||
*
|
||||
* This is to be used to perform a list of resets for a device or power domain
|
||||
* in whatever order. Returns a struct reset_control or IS_ERR() condition
|
||||
* containing errno.
|
||||
*/
|
||||
struct reset_control *of_reset_control_get_by_index(struct device_node *node,
|
||||
int index)
|
||||
static struct reset_control *__reset_control_get(
|
||||
struct reset_controller_dev *rcdev,
|
||||
unsigned int index, int shared)
|
||||
{
|
||||
struct reset_control *rstc;
|
||||
|
||||
lockdep_assert_held(&reset_list_mutex);
|
||||
|
||||
list_for_each_entry(rstc, &rcdev->reset_control_head, list) {
|
||||
if (rstc->id == index) {
|
||||
if (WARN_ON(!rstc->shared || !shared))
|
||||
return ERR_PTR(-EBUSY);
|
||||
|
||||
rstc->refcnt++;
|
||||
return rstc;
|
||||
}
|
||||
}
|
||||
|
||||
rstc = kzalloc(sizeof(*rstc), GFP_KERNEL);
|
||||
if (!rstc)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
try_module_get(rcdev->owner);
|
||||
|
||||
rstc->rcdev = rcdev;
|
||||
list_add(&rstc->list, &rcdev->reset_control_head);
|
||||
rstc->id = index;
|
||||
rstc->refcnt = 1;
|
||||
rstc->shared = shared;
|
||||
|
||||
return rstc;
|
||||
}
|
||||
|
||||
static void __reset_control_put(struct reset_control *rstc)
|
||||
{
|
||||
lockdep_assert_held(&reset_list_mutex);
|
||||
|
||||
if (--rstc->refcnt)
|
||||
return;
|
||||
|
||||
module_put(rstc->rcdev->owner);
|
||||
|
||||
list_del(&rstc->list);
|
||||
kfree(rstc);
|
||||
}
|
||||
|
||||
struct reset_control *__of_reset_control_get(struct device_node *node,
|
||||
const char *id, int index, int shared)
|
||||
{
|
||||
struct reset_control *rstc;
|
||||
struct reset_controller_dev *r, *rcdev;
|
||||
|
@ -155,12 +229,22 @@ struct reset_control *of_reset_control_get_by_index(struct device_node *node,
|
|||
int rstc_id;
|
||||
int ret;
|
||||
|
||||
if (!node)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (id) {
|
||||
index = of_property_match_string(node,
|
||||
"reset-names", id);
|
||||
if (index < 0)
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
|
||||
ret = of_parse_phandle_with_args(node, "resets", "#reset-cells",
|
||||
index, &args);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
mutex_lock(&reset_controller_list_mutex);
|
||||
mutex_lock(&reset_list_mutex);
|
||||
rcdev = NULL;
|
||||
list_for_each_entry(r, &reset_controller_list, list) {
|
||||
if (args.np == r->of_node) {
|
||||
|
@ -171,78 +255,29 @@ struct reset_control *of_reset_control_get_by_index(struct device_node *node,
|
|||
of_node_put(args.np);
|
||||
|
||||
if (!rcdev) {
|
||||
mutex_unlock(&reset_controller_list_mutex);
|
||||
mutex_unlock(&reset_list_mutex);
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
|
||||
if (WARN_ON(args.args_count != rcdev->of_reset_n_cells)) {
|
||||
mutex_unlock(&reset_controller_list_mutex);
|
||||
mutex_unlock(&reset_list_mutex);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
rstc_id = rcdev->of_xlate(rcdev, &args);
|
||||
if (rstc_id < 0) {
|
||||
mutex_unlock(&reset_controller_list_mutex);
|
||||
mutex_unlock(&reset_list_mutex);
|
||||
return ERR_PTR(rstc_id);
|
||||
}
|
||||
|
||||
try_module_get(rcdev->owner);
|
||||
mutex_unlock(&reset_controller_list_mutex);
|
||||
/* reset_list_mutex also protects the rcdev's reset_control list */
|
||||
rstc = __reset_control_get(rcdev, rstc_id, shared);
|
||||
|
||||
rstc = kzalloc(sizeof(*rstc), GFP_KERNEL);
|
||||
if (!rstc) {
|
||||
module_put(rcdev->owner);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
rstc->rcdev = rcdev;
|
||||
rstc->id = rstc_id;
|
||||
mutex_unlock(&reset_list_mutex);
|
||||
|
||||
return rstc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_reset_control_get_by_index);
|
||||
|
||||
/**
|
||||
* of_reset_control_get - Lookup and obtain a reference to a reset controller.
|
||||
* @node: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Returns a struct reset_control or IS_ERR() condition containing errno.
|
||||
*
|
||||
* Use of id names is optional.
|
||||
*/
|
||||
struct reset_control *of_reset_control_get(struct device_node *node,
|
||||
const char *id)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
if (id) {
|
||||
index = of_property_match_string(node,
|
||||
"reset-names", id);
|
||||
if (index < 0)
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
return of_reset_control_get_by_index(node, index);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_reset_control_get);
|
||||
|
||||
/**
|
||||
* reset_control_get - Lookup and obtain a reference to a reset controller.
|
||||
* @dev: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Returns a struct reset_control or IS_ERR() condition containing errno.
|
||||
*
|
||||
* Use of id names is optional.
|
||||
*/
|
||||
struct reset_control *reset_control_get(struct device *dev, const char *id)
|
||||
{
|
||||
if (!dev)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return of_reset_control_get(dev->of_node, id);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reset_control_get);
|
||||
EXPORT_SYMBOL_GPL(__of_reset_control_get);
|
||||
|
||||
/**
|
||||
* reset_control_put - free the reset controller
|
||||
|
@ -254,8 +289,9 @@ void reset_control_put(struct reset_control *rstc)
|
|||
if (IS_ERR(rstc))
|
||||
return;
|
||||
|
||||
module_put(rstc->rcdev->owner);
|
||||
kfree(rstc);
|
||||
mutex_lock(&reset_list_mutex);
|
||||
__reset_control_put(rstc);
|
||||
mutex_unlock(&reset_list_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(reset_control_put);
|
||||
|
||||
|
@ -264,16 +300,8 @@ static void devm_reset_control_release(struct device *dev, void *res)
|
|||
reset_control_put(*(struct reset_control **)res);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_get - resource managed reset_control_get()
|
||||
* @dev: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Managed reset_control_get(). For reset controllers returned from this
|
||||
* function, reset_control_put() is called automatically on driver detach.
|
||||
* See reset_control_get() for more information.
|
||||
*/
|
||||
struct reset_control *devm_reset_control_get(struct device *dev, const char *id)
|
||||
struct reset_control *__devm_reset_control_get(struct device *dev,
|
||||
const char *id, int index, int shared)
|
||||
{
|
||||
struct reset_control **ptr, *rstc;
|
||||
|
||||
|
@ -282,7 +310,8 @@ struct reset_control *devm_reset_control_get(struct device *dev, const char *id)
|
|||
if (!ptr)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
rstc = reset_control_get(dev, id);
|
||||
rstc = __of_reset_control_get(dev ? dev->of_node : NULL,
|
||||
id, index, shared);
|
||||
if (!IS_ERR(rstc)) {
|
||||
*ptr = rstc;
|
||||
devres_add(dev, ptr);
|
||||
|
@ -292,7 +321,7 @@ struct reset_control *devm_reset_control_get(struct device *dev, const char *id)
|
|||
|
||||
return rstc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_reset_control_get);
|
||||
EXPORT_SYMBOL_GPL(__devm_reset_control_get);
|
||||
|
||||
/**
|
||||
* device_reset - find reset controller associated with the device
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
struct lpc18xx_rgu_data {
|
||||
struct reset_controller_dev rcdev;
|
||||
struct notifier_block restart_nb;
|
||||
struct clk *clk_delay;
|
||||
struct clk *clk_reg;
|
||||
void __iomem *base;
|
||||
|
@ -44,12 +45,13 @@ struct lpc18xx_rgu_data {
|
|||
|
||||
#define to_rgu_data(p) container_of(p, struct lpc18xx_rgu_data, rcdev)
|
||||
|
||||
static void __iomem *rgu_base;
|
||||
|
||||
static int lpc18xx_rgu_restart(struct notifier_block *this, unsigned long mode,
|
||||
static int lpc18xx_rgu_restart(struct notifier_block *nb, unsigned long mode,
|
||||
void *cmd)
|
||||
{
|
||||
writel(BIT(LPC18XX_RGU_CORE_RST), rgu_base + LPC18XX_RGU_CTRL0);
|
||||
struct lpc18xx_rgu_data *rc = container_of(nb, struct lpc18xx_rgu_data,
|
||||
restart_nb);
|
||||
|
||||
writel(BIT(LPC18XX_RGU_CORE_RST), rc->base + LPC18XX_RGU_CTRL0);
|
||||
mdelay(2000);
|
||||
|
||||
pr_emerg("%s: unable to restart system\n", __func__);
|
||||
|
@ -57,11 +59,6 @@ static int lpc18xx_rgu_restart(struct notifier_block *this, unsigned long mode,
|
|||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block lpc18xx_rgu_restart_nb = {
|
||||
.notifier_call = lpc18xx_rgu_restart,
|
||||
.priority = 192,
|
||||
};
|
||||
|
||||
/*
|
||||
* The LPC18xx RGU has mostly self-deasserting resets except for the
|
||||
* two reset lines going to the internal Cortex-M0 cores.
|
||||
|
@ -205,8 +202,9 @@ static int lpc18xx_rgu_probe(struct platform_device *pdev)
|
|||
goto dis_clks;
|
||||
}
|
||||
|
||||
rgu_base = rc->base;
|
||||
ret = register_restart_handler(&lpc18xx_rgu_restart_nb);
|
||||
rc->restart_nb.priority = 192,
|
||||
rc->restart_nb.notifier_call = lpc18xx_rgu_restart,
|
||||
ret = register_restart_handler(&rc->restart_nb);
|
||||
if (ret)
|
||||
dev_warn(&pdev->dev, "failed to register restart handler\n");
|
||||
|
||||
|
@ -225,7 +223,7 @@ static int lpc18xx_rgu_remove(struct platform_device *pdev)
|
|||
struct lpc18xx_rgu_data *rc = platform_get_drvdata(pdev);
|
||||
int ret;
|
||||
|
||||
ret = unregister_restart_handler(&lpc18xx_rgu_restart_nb);
|
||||
ret = unregister_restart_handler(&rc->restart_nb);
|
||||
if (ret)
|
||||
dev_warn(&pdev->dev, "failed to unregister restart handler\n");
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ struct of_phandle_args;
|
|||
* @ops: a pointer to device specific struct reset_control_ops
|
||||
* @owner: kernel module of the reset controller driver
|
||||
* @list: internal list of reset controller devices
|
||||
* @reset_control_head: head of internal list of requested reset controls
|
||||
* @of_node: corresponding device tree node as phandle target
|
||||
* @of_reset_n_cells: number of cells in reset line specifiers
|
||||
* @of_xlate: translation function to translate from specifier as found in the
|
||||
|
@ -41,6 +42,7 @@ struct reset_controller_dev {
|
|||
const struct reset_control_ops *ops;
|
||||
struct module *owner;
|
||||
struct list_head list;
|
||||
struct list_head reset_control_head;
|
||||
struct device_node *of_node;
|
||||
int of_reset_n_cells;
|
||||
int (*of_xlate)(struct reset_controller_dev *rcdev,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef _LINUX_RESET_H_
|
||||
#define _LINUX_RESET_H_
|
||||
|
||||
struct device;
|
||||
struct device_node;
|
||||
#include <linux/device.h>
|
||||
|
||||
struct reset_control;
|
||||
|
||||
#ifdef CONFIG_RESET_CONTROLLER
|
||||
|
@ -12,9 +12,11 @@ int reset_control_assert(struct reset_control *rstc);
|
|||
int reset_control_deassert(struct reset_control *rstc);
|
||||
int reset_control_status(struct reset_control *rstc);
|
||||
|
||||
struct reset_control *reset_control_get(struct device *dev, const char *id);
|
||||
struct reset_control *__of_reset_control_get(struct device_node *node,
|
||||
const char *id, int index, int shared);
|
||||
void reset_control_put(struct reset_control *rstc);
|
||||
struct reset_control *devm_reset_control_get(struct device *dev, const char *id);
|
||||
struct reset_control *__devm_reset_control_get(struct device *dev,
|
||||
const char *id, int index, int shared);
|
||||
|
||||
int __must_check device_reset(struct device *dev);
|
||||
|
||||
|
@ -23,24 +25,6 @@ static inline int device_reset_optional(struct device *dev)
|
|||
return device_reset(dev);
|
||||
}
|
||||
|
||||
static inline struct reset_control *reset_control_get_optional(
|
||||
struct device *dev, const char *id)
|
||||
{
|
||||
return reset_control_get(dev, id);
|
||||
}
|
||||
|
||||
static inline struct reset_control *devm_reset_control_get_optional(
|
||||
struct device *dev, const char *id)
|
||||
{
|
||||
return devm_reset_control_get(dev, id);
|
||||
}
|
||||
|
||||
struct reset_control *of_reset_control_get(struct device_node *node,
|
||||
const char *id);
|
||||
|
||||
struct reset_control *of_reset_control_get_by_index(
|
||||
struct device_node *node, int index);
|
||||
|
||||
#else
|
||||
|
||||
static inline int reset_control_reset(struct reset_control *rstc)
|
||||
|
@ -77,44 +61,180 @@ static inline int device_reset_optional(struct device *dev)
|
|||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static inline struct reset_control *__must_check reset_control_get(
|
||||
struct device *dev, const char *id)
|
||||
static inline struct reset_control *__of_reset_control_get(
|
||||
struct device_node *node,
|
||||
const char *id, int index, int shared)
|
||||
{
|
||||
WARN_ON(1);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static inline struct reset_control *__must_check devm_reset_control_get(
|
||||
static inline struct reset_control *__devm_reset_control_get(
|
||||
struct device *dev,
|
||||
const char *id, int index, int shared)
|
||||
{
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_RESET_CONTROLLER */
|
||||
|
||||
/**
|
||||
* reset_control_get - Lookup and obtain an exclusive reference to a
|
||||
* reset controller.
|
||||
* @dev: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Returns a struct reset_control or IS_ERR() condition containing errno.
|
||||
* If this function is called more then once for the same reset_control it will
|
||||
* return -EBUSY.
|
||||
*
|
||||
* See reset_control_get_shared for details on shared references to
|
||||
* reset-controls.
|
||||
*
|
||||
* Use of id names is optional.
|
||||
*/
|
||||
static inline struct reset_control *__must_check reset_control_get(
|
||||
struct device *dev, const char *id)
|
||||
{
|
||||
#ifndef CONFIG_RESET_CONTROLLER
|
||||
WARN_ON(1);
|
||||
return ERR_PTR(-EINVAL);
|
||||
#endif
|
||||
return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, 0);
|
||||
}
|
||||
|
||||
static inline struct reset_control *reset_control_get_optional(
|
||||
struct device *dev, const char *id)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* reset_control_get_shared - Lookup and obtain a shared reference to a
|
||||
* reset controller.
|
||||
* @dev: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Returns a struct reset_control or IS_ERR() condition containing errno.
|
||||
* This function is intended for use with reset-controls which are shared
|
||||
* between hardware-blocks.
|
||||
*
|
||||
* When a reset-control is shared, the behavior of reset_control_assert /
|
||||
* deassert is changed, the reset-core will keep track of a deassert_count
|
||||
* and only (re-)assert the reset after reset_control_assert has been called
|
||||
* as many times as reset_control_deassert was called. Also see the remark
|
||||
* about shared reset-controls in the reset_control_assert docs.
|
||||
*
|
||||
* Calling reset_control_assert without first calling reset_control_deassert
|
||||
* is not allowed on a shared reset control. Calling reset_control_reset is
|
||||
* also not allowed on a shared reset control.
|
||||
*
|
||||
* Use of id names is optional.
|
||||
*/
|
||||
static inline struct reset_control *reset_control_get_shared(
|
||||
struct device *dev, const char *id)
|
||||
{
|
||||
return __of_reset_control_get(dev ? dev->of_node : NULL, id, 0, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* of_reset_control_get - Lookup and obtain an exclusive reference to a
|
||||
* reset controller.
|
||||
* @node: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Returns a struct reset_control or IS_ERR() condition containing errno.
|
||||
*
|
||||
* Use of id names is optional.
|
||||
*/
|
||||
static inline struct reset_control *of_reset_control_get(
|
||||
struct device_node *node, const char *id)
|
||||
{
|
||||
return __of_reset_control_get(node, id, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* of_reset_control_get_by_index - Lookup and obtain an exclusive reference to
|
||||
* a reset controller by index.
|
||||
* @node: device to be reset by the controller
|
||||
* @index: index of the reset controller
|
||||
*
|
||||
* This is to be used to perform a list of resets for a device or power domain
|
||||
* in whatever order. Returns a struct reset_control or IS_ERR() condition
|
||||
* containing errno.
|
||||
*/
|
||||
static inline struct reset_control *of_reset_control_get_by_index(
|
||||
struct device_node *node, int index)
|
||||
{
|
||||
return __of_reset_control_get(node, NULL, index, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_get - resource managed reset_control_get()
|
||||
* @dev: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Managed reset_control_get(). For reset controllers returned from this
|
||||
* function, reset_control_put() is called automatically on driver detach.
|
||||
* See reset_control_get() for more information.
|
||||
*/
|
||||
static inline struct reset_control *__must_check devm_reset_control_get(
|
||||
struct device *dev, const char *id)
|
||||
{
|
||||
#ifndef CONFIG_RESET_CONTROLLER
|
||||
WARN_ON(1);
|
||||
#endif
|
||||
return __devm_reset_control_get(dev, id, 0, 0);
|
||||
}
|
||||
|
||||
static inline struct reset_control *devm_reset_control_get_optional(
|
||||
struct device *dev, const char *id)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
return __devm_reset_control_get(dev, id, 0, 0);
|
||||
}
|
||||
|
||||
static inline struct reset_control *of_reset_control_get(
|
||||
struct device_node *node, const char *id)
|
||||
/**
|
||||
* devm_reset_control_get_by_index - resource managed reset_control_get
|
||||
* @dev: device to be reset by the controller
|
||||
* @index: index of the reset controller
|
||||
*
|
||||
* Managed reset_control_get(). For reset controllers returned from this
|
||||
* function, reset_control_put() is called automatically on driver detach.
|
||||
* See reset_control_get() for more information.
|
||||
*/
|
||||
static inline struct reset_control *devm_reset_control_get_by_index(
|
||||
struct device *dev, int index)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
return __devm_reset_control_get(dev, NULL, index, 0);
|
||||
}
|
||||
|
||||
static inline struct reset_control *of_reset_control_get_by_index(
|
||||
struct device_node *node, int index)
|
||||
/**
|
||||
* devm_reset_control_get_shared - resource managed reset_control_get_shared()
|
||||
* @dev: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Managed reset_control_get_shared(). For reset controllers returned from
|
||||
* this function, reset_control_put() is called automatically on driver detach.
|
||||
* See reset_control_get_shared() for more information.
|
||||
*/
|
||||
static inline struct reset_control *devm_reset_control_get_shared(
|
||||
struct device *dev, const char *id)
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
return __devm_reset_control_get(dev, id, 0, 1);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_RESET_CONTROLLER */
|
||||
/**
|
||||
* devm_reset_control_get_shared_by_index - resource managed
|
||||
* reset_control_get_shared
|
||||
* @dev: device to be reset by the controller
|
||||
* @index: index of the reset controller
|
||||
*
|
||||
* Managed reset_control_get_shared(). For reset controllers returned from
|
||||
* this function, reset_control_put() is called automatically on driver detach.
|
||||
* See reset_control_get_shared() for more information.
|
||||
*/
|
||||
static inline struct reset_control *devm_reset_control_get_shared_by_index(
|
||||
struct device *dev, int index)
|
||||
{
|
||||
return __devm_reset_control_get(dev, NULL, index, 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue