summaryrefslogtreecommitdiff
path: root/drivers/reset
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/reset')
-rw-r--r--drivers/reset/Kconfig7
-rw-r--r--drivers/reset/Makefile2
-rw-r--r--drivers/reset/core.c116
-rw-r--r--drivers/reset/hisilicon/Kconfig7
-rw-r--r--drivers/reset/hisilicon/Makefile1
-rw-r--r--drivers/reset/hisilicon/reset-hi3660.c126
-rw-r--r--drivers/reset/reset-berlin.c12
-rw-r--r--drivers/reset/reset-lpc18xx.c32
-rw-r--r--drivers/reset/reset-oxnas.c1
-rw-r--r--drivers/reset/reset-socfpga.c10
-rw-r--r--drivers/reset/reset-sunxi.c9
-rw-r--r--drivers/reset/reset-ti-syscon.c6
-rw-r--r--drivers/reset/reset-uniphier.c4
-rw-r--r--drivers/reset/reset-zx2967.c99
-rw-r--r--drivers/reset/reset-zynq.c10
-rw-r--r--drivers/reset/sti/Kconfig8
-rw-r--r--drivers/reset/sti/Makefile2
-rw-r--r--drivers/reset/sti/reset-stih415.c112
-rw-r--r--drivers/reset/sti/reset-stih416.c143
-rw-r--r--drivers/reset/tegra/Kconfig2
-rw-r--r--drivers/reset/tegra/Makefile1
-rw-r--r--drivers/reset/tegra/reset-bpmp.c71
22 files changed, 436 insertions, 345 deletions
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 06d9fa2f3bc0..f4cdfe94b9ec 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -86,6 +86,12 @@ config RESET_UNIPHIER
Say Y if you want to control reset signals provided by System Control
block, Media I/O block, Peripheral Block.
+config RESET_ZX2967
+ bool "ZTE ZX2967 Reset Driver"
+ depends on ARCH_ZX || COMPILE_TEST
+ help
+ This enables the reset controller driver for ZTE's zx2967 family.
+
config RESET_ZYNQ
bool "ZYNQ Reset Driver" if COMPILE_TEST
default ARCH_ZYNQ
@@ -94,5 +100,6 @@ config RESET_ZYNQ
source "drivers/reset/sti/Kconfig"
source "drivers/reset/hisilicon/Kconfig"
+source "drivers/reset/tegra/Kconfig"
endif
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index bbe7026617fc..2cd3f6c45165 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -1,6 +1,7 @@
obj-y += core.o
obj-y += hisilicon/
obj-$(CONFIG_ARCH_STI) += sti/
+obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
@@ -12,4 +13,5 @@ obj-$(CONFIG_RESET_STM32) += reset-stm32.o
obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
obj-$(CONFIG_TI_SYSCON_RESET) += reset-ti-syscon.o
obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
+obj-$(CONFIG_RESET_ZX2967) += reset-zx2967.o
obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
diff --git a/drivers/reset/core.c b/drivers/reset/core.c
index b8ae1dbd4c17..cd739d2fa160 100644
--- a/drivers/reset/core.c
+++ b/drivers/reset/core.c
@@ -32,14 +32,18 @@ static LIST_HEAD(reset_controller_list);
* @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
+ * @triggered_count: Number of times this reset line has been reset. Currently
+ * only used for shared resets, which means that the value
+ * will be either 0 or 1.
*/
struct reset_control {
struct reset_controller_dev *rcdev;
struct list_head list;
unsigned int id;
unsigned int refcnt;
- int shared;
+ bool shared;
atomic_t deassert_count;
+ atomic_t triggered_count;
};
/**
@@ -134,18 +138,41 @@ EXPORT_SYMBOL_GPL(devm_reset_controller_register);
* reset_control_reset - reset the controlled device
* @rstc: reset controller
*
- * Calling this on a shared reset controller is an error.
+ * On a shared reset line the actual reset pulse is only triggered once for the
+ * lifetime of the reset_control instance: for all but the first caller this is
+ * a no-op.
+ * Consumers must not use reset_control_(de)assert on shared reset lines when
+ * reset_control_reset has been used.
+ *
+ * If rstc is NULL it is an optional reset and the function will just
+ * return 0.
*/
int reset_control_reset(struct reset_control *rstc)
{
- if (WARN_ON(IS_ERR_OR_NULL(rstc)) ||
- WARN_ON(rstc->shared))
+ int ret;
+
+ if (!rstc)
+ return 0;
+
+ if (WARN_ON(IS_ERR(rstc)))
return -EINVAL;
- if (rstc->rcdev->ops->reset)
- return rstc->rcdev->ops->reset(rstc->rcdev, rstc->id);
+ if (!rstc->rcdev->ops->reset)
+ return -ENOTSUPP;
- return -ENOTSUPP;
+ if (rstc->shared) {
+ if (WARN_ON(atomic_read(&rstc->deassert_count) != 0))
+ return -EINVAL;
+
+ if (atomic_inc_return(&rstc->triggered_count) != 1)
+ return 0;
+ }
+
+ ret = rstc->rcdev->ops->reset(rstc->rcdev, rstc->id);
+ if (rstc->shared && ret)
+ atomic_dec(&rstc->triggered_count);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(reset_control_reset);
@@ -159,16 +186,28 @@ EXPORT_SYMBOL_GPL(reset_control_reset);
*
* 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.
+ * Consumers must not use reset_control_reset on shared reset lines when
+ * reset_control_(de)assert has been used.
+ * return 0.
+ *
+ * If rstc is NULL it is an optional reset and the function will just
+ * return 0.
*/
int reset_control_assert(struct reset_control *rstc)
{
- if (WARN_ON(IS_ERR_OR_NULL(rstc)))
+ if (!rstc)
+ return 0;
+
+ if (WARN_ON(IS_ERR(rstc)))
return -EINVAL;
if (!rstc->rcdev->ops->assert)
return -ENOTSUPP;
if (rstc->shared) {
+ if (WARN_ON(atomic_read(&rstc->triggered_count) != 0))
+ return -EINVAL;
+
if (WARN_ON(atomic_read(&rstc->deassert_count) == 0))
return -EINVAL;
@@ -185,16 +224,28 @@ EXPORT_SYMBOL_GPL(reset_control_assert);
* @rstc: reset controller
*
* After calling this function, the reset is guaranteed to be deasserted.
+ * Consumers must not use reset_control_reset on shared reset lines when
+ * reset_control_(de)assert has been used.
+ * return 0.
+ *
+ * If rstc is NULL it is an optional reset and the function will just
+ * return 0.
*/
int reset_control_deassert(struct reset_control *rstc)
{
- if (WARN_ON(IS_ERR_OR_NULL(rstc)))
+ if (!rstc)
+ return 0;
+
+ if (WARN_ON(IS_ERR(rstc)))
return -EINVAL;
if (!rstc->rcdev->ops->deassert)
return -ENOTSUPP;
if (rstc->shared) {
+ if (WARN_ON(atomic_read(&rstc->triggered_count) != 0))
+ return -EINVAL;
+
if (atomic_inc_return(&rstc->deassert_count) != 1)
return 0;
}
@@ -206,12 +257,15 @@ EXPORT_SYMBOL_GPL(reset_control_deassert);
/**
* reset_control_status - returns a negative errno if not supported, a
* positive value if the reset line is asserted, or zero if the reset
- * line is not asserted.
+ * line is not asserted or if the desc is NULL (optional reset).
* @rstc: reset controller
*/
int reset_control_status(struct reset_control *rstc)
{
- if (WARN_ON(IS_ERR_OR_NULL(rstc)))
+ if (!rstc)
+ return 0;
+
+ if (WARN_ON(IS_ERR(rstc)))
return -EINVAL;
if (rstc->rcdev->ops->status)
@@ -221,9 +275,9 @@ int reset_control_status(struct reset_control *rstc)
}
EXPORT_SYMBOL_GPL(reset_control_status);
-static struct reset_control *__reset_control_get(
+static struct reset_control *__reset_control_get_internal(
struct reset_controller_dev *rcdev,
- unsigned int index, int shared)
+ unsigned int index, bool shared)
{
struct reset_control *rstc;
@@ -254,7 +308,7 @@ static struct reset_control *__reset_control_get(
return rstc;
}
-static void __reset_control_put(struct reset_control *rstc)
+static void __reset_control_put_internal(struct reset_control *rstc)
{
lockdep_assert_held(&reset_list_mutex);
@@ -268,7 +322,8 @@ static void __reset_control_put(struct reset_control *rstc)
}
struct reset_control *__of_reset_control_get(struct device_node *node,
- const char *id, int index, int shared)
+ const char *id, int index, bool shared,
+ bool optional)
{
struct reset_control *rstc;
struct reset_controller_dev *r, *rcdev;
@@ -282,14 +337,18 @@ struct reset_control *__of_reset_control_get(struct device_node *node,
if (id) {
index = of_property_match_string(node,
"reset-names", id);
+ if (index == -EILSEQ)
+ return ERR_PTR(index);
if (index < 0)
- return ERR_PTR(-ENOENT);
+ return optional ? NULL : ERR_PTR(-ENOENT);
}
ret = of_parse_phandle_with_args(node, "resets", "#reset-cells",
index, &args);
- if (ret)
+ if (ret == -EINVAL)
return ERR_PTR(ret);
+ if (ret)
+ return optional ? NULL : ERR_PTR(ret);
mutex_lock(&reset_list_mutex);
rcdev = NULL;
@@ -318,7 +377,7 @@ struct reset_control *__of_reset_control_get(struct device_node *node,
}
/* reset_list_mutex also protects the rcdev's reset_control list */
- rstc = __reset_control_get(rcdev, rstc_id, shared);
+ rstc = __reset_control_get_internal(rcdev, rstc_id, shared);
mutex_unlock(&reset_list_mutex);
@@ -326,6 +385,17 @@ struct reset_control *__of_reset_control_get(struct device_node *node,
}
EXPORT_SYMBOL_GPL(__of_reset_control_get);
+struct reset_control *__reset_control_get(struct device *dev, const char *id,
+ int index, bool shared, bool optional)
+{
+ if (dev->of_node)
+ return __of_reset_control_get(dev->of_node, id, index, shared,
+ optional);
+
+ return optional ? NULL : ERR_PTR(-EINVAL);
+}
+EXPORT_SYMBOL_GPL(__reset_control_get);
+
/**
* reset_control_put - free the reset controller
* @rstc: reset controller
@@ -333,11 +403,11 @@ EXPORT_SYMBOL_GPL(__of_reset_control_get);
void reset_control_put(struct reset_control *rstc)
{
- if (IS_ERR(rstc))
+ if (IS_ERR_OR_NULL(rstc))
return;
mutex_lock(&reset_list_mutex);
- __reset_control_put(rstc);
+ __reset_control_put_internal(rstc);
mutex_unlock(&reset_list_mutex);
}
EXPORT_SYMBOL_GPL(reset_control_put);
@@ -348,7 +418,8 @@ static void devm_reset_control_release(struct device *dev, void *res)
}
struct reset_control *__devm_reset_control_get(struct device *dev,
- const char *id, int index, int shared)
+ const char *id, int index, bool shared,
+ bool optional)
{
struct reset_control **ptr, *rstc;
@@ -357,8 +428,7 @@ struct reset_control *__devm_reset_control_get(struct device *dev,
if (!ptr)
return ERR_PTR(-ENOMEM);
- rstc = __of_reset_control_get(dev ? dev->of_node : NULL,
- id, index, shared);
+ rstc = __reset_control_get(dev, id, index, shared, optional);
if (!IS_ERR(rstc)) {
*ptr = rstc;
devres_add(dev, ptr);
diff --git a/drivers/reset/hisilicon/Kconfig b/drivers/reset/hisilicon/Kconfig
index 1ff8b0c80980..10134dc03fe0 100644
--- a/drivers/reset/hisilicon/Kconfig
+++ b/drivers/reset/hisilicon/Kconfig
@@ -1,3 +1,10 @@
+config COMMON_RESET_HI3660
+ tristate "Hi3660 Reset Driver"
+ depends on ARCH_HISI || COMPILE_TEST
+ default ARCH_HISI
+ help
+ Build the Hisilicon Hi3660 reset driver.
+
config COMMON_RESET_HI6220
tristate "Hi6220 Reset Driver"
depends on ARCH_HISI || COMPILE_TEST
diff --git a/drivers/reset/hisilicon/Makefile b/drivers/reset/hisilicon/Makefile
index c932f86e2f10..ab8a7bfcbd8d 100644
--- a/drivers/reset/hisilicon/Makefile
+++ b/drivers/reset/hisilicon/Makefile
@@ -1 +1,2 @@
obj-$(CONFIG_COMMON_RESET_HI6220) += hi6220_reset.o
+obj-$(CONFIG_COMMON_RESET_HI3660) += reset-hi3660.o
diff --git a/drivers/reset/hisilicon/reset-hi3660.c b/drivers/reset/hisilicon/reset-hi3660.c
new file mode 100644
index 000000000000..17d8bb128e6e
--- /dev/null
+++ b/drivers/reset/hisilicon/reset-hi3660.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2016-2017 Linaro Ltd.
+ * Copyright (c) 2016-2017 HiSilicon Technologies Co., Ltd.
+ *
+ * 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/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+struct hi3660_reset_controller {
+ struct reset_controller_dev rst;
+ struct regmap *map;
+};
+
+#define to_hi3660_reset_controller(_rst) \
+ container_of(_rst, struct hi3660_reset_controller, rst)
+
+static int hi3660_reset_program_hw(struct reset_controller_dev *rcdev,
+ unsigned long idx, bool assert)
+{
+ struct hi3660_reset_controller *rc = to_hi3660_reset_controller(rcdev);
+ unsigned int offset = idx >> 8;
+ unsigned int mask = BIT(idx & 0x1f);
+
+ if (assert)
+ return regmap_write(rc->map, offset, mask);
+ else
+ return regmap_write(rc->map, offset + 4, mask);
+}
+
+static int hi3660_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long idx)
+{
+ return hi3660_reset_program_hw(rcdev, idx, true);
+}
+
+static int hi3660_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long idx)
+{
+ return hi3660_reset_program_hw(rcdev, idx, false);
+}
+
+static int hi3660_reset_dev(struct reset_controller_dev *rcdev,
+ unsigned long idx)
+{
+ int err;
+
+ err = hi3660_reset_assert(rcdev, idx);
+ if (err)
+ return err;
+
+ return hi3660_reset_deassert(rcdev, idx);
+}
+
+static struct reset_control_ops hi3660_reset_ops = {
+ .reset = hi3660_reset_dev,
+ .assert = hi3660_reset_assert,
+ .deassert = hi3660_reset_deassert,
+};
+
+static int hi3660_reset_xlate(struct reset_controller_dev *rcdev,
+ const struct of_phandle_args *reset_spec)
+{
+ unsigned int offset, bit;
+
+ offset = reset_spec->args[0];
+ bit = reset_spec->args[1];
+
+ return (offset << 8) | bit;
+}
+
+static int hi3660_reset_probe(struct platform_device *pdev)
+{
+ struct hi3660_reset_controller *rc;
+ struct device_node *np = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
+
+ rc = devm_kzalloc(dev, sizeof(*rc), GFP_KERNEL);
+ if (!rc)
+ return -ENOMEM;
+
+ rc->map = syscon_regmap_lookup_by_phandle(np, "hisi,rst-syscon");
+ if (IS_ERR(rc->map)) {
+ dev_err(dev, "failed to get hi3660,rst-syscon\n");
+ return PTR_ERR(rc->map);
+ }
+
+ rc->rst.ops = &hi3660_reset_ops,
+ rc->rst.of_node = np;
+ rc->rst.of_reset_n_cells = 2;
+ rc->rst.of_xlate = hi3660_reset_xlate;
+
+ return reset_controller_register(&rc->rst);
+}
+
+static const struct of_device_id hi3660_reset_match[] = {
+ { .compatible = "hisilicon,hi3660-reset", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, hi3660_reset_match);
+
+static struct platform_driver hi3660_reset_driver = {
+ .probe = hi3660_reset_probe,
+ .driver = {
+ .name = "hi3660-reset",
+ .of_match_table = hi3660_reset_match,
+ },
+};
+
+static int __init hi3660_reset_init(void)
+{
+ return platform_driver_register(&hi3660_reset_driver);
+}
+arch_initcall(hi3660_reset_init);
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:hi3660-reset");
+MODULE_DESCRIPTION("HiSilicon Hi3660 Reset Driver");
diff --git a/drivers/reset/reset-berlin.c b/drivers/reset/reset-berlin.c
index 369f3917fd8e..371197bbd055 100644
--- a/drivers/reset/reset-berlin.c
+++ b/drivers/reset/reset-berlin.c
@@ -1,6 +1,8 @@
/*
* Copyright (C) 2014 Marvell Technology Group Ltd.
*
+ * Marvell Berlin reset driver
+ *
* Antoine Tenart <antoine.tenart@free-electrons.com>
* Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
*
@@ -12,7 +14,7 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/mfd/syscon.h>
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
@@ -91,7 +93,6 @@ static const struct of_device_id berlin_reset_dt_match[] = {
{ .compatible = "marvell,berlin2-reset" },
{ },
};
-MODULE_DEVICE_TABLE(of, berlin_reset_dt_match);
static struct platform_driver berlin_reset_driver = {
.probe = berlin2_reset_probe,
@@ -100,9 +101,4 @@ static struct platform_driver berlin_reset_driver = {
.of_match_table = berlin_reset_dt_match,
},
};
-module_platform_driver(berlin_reset_driver);
-
-MODULE_AUTHOR("Antoine Tenart <antoine.tenart@free-electrons.com>");
-MODULE_AUTHOR("Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>");
-MODULE_DESCRIPTION("Marvell Berlin reset driver");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(berlin_reset_driver);
diff --git a/drivers/reset/reset-lpc18xx.c b/drivers/reset/reset-lpc18xx.c
index 54cca0055171..a62ad52e262b 100644
--- a/drivers/reset/reset-lpc18xx.c
+++ b/drivers/reset/reset-lpc18xx.c
@@ -13,7 +13,7 @@
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/reboot.h>
@@ -218,39 +218,17 @@ dis_clk_reg:
return ret;
}
-static int lpc18xx_rgu_remove(struct platform_device *pdev)
-{
- struct lpc18xx_rgu_data *rc = platform_get_drvdata(pdev);
- int ret;
-
- ret = unregister_restart_handler(&rc->restart_nb);
- if (ret)
- dev_warn(&pdev->dev, "failed to unregister restart handler\n");
-
- reset_controller_unregister(&rc->rcdev);
-
- clk_disable_unprepare(rc->clk_delay);
- clk_disable_unprepare(rc->clk_reg);
-
- return 0;
-}
-
static const struct of_device_id lpc18xx_rgu_match[] = {
{ .compatible = "nxp,lpc1850-rgu" },
{ }
};
-MODULE_DEVICE_TABLE(of, lpc18xx_rgu_match);
static struct platform_driver lpc18xx_rgu_driver = {
.probe = lpc18xx_rgu_probe,
- .remove = lpc18xx_rgu_remove,
.driver = {
- .name = "lpc18xx-reset",
- .of_match_table = lpc18xx_rgu_match,
+ .name = "lpc18xx-reset",
+ .of_match_table = lpc18xx_rgu_match,
+ .suppress_bind_attrs = true,
},
};
-module_platform_driver(lpc18xx_rgu_driver);
-
-MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
-MODULE_DESCRIPTION("Reset driver for LPC18xx/43xx RGU");
-MODULE_LICENSE("GPL v2");
+builtin_platform_driver(lpc18xx_rgu_driver);
diff --git a/drivers/reset/reset-oxnas.c b/drivers/reset/reset-oxnas.c
index 944980572f79..0d9036dea010 100644
--- a/drivers/reset/reset-oxnas.c
+++ b/drivers/reset/reset-oxnas.c
@@ -80,6 +80,7 @@ static const struct reset_control_ops oxnas_reset_ops = {
static const struct of_device_id oxnas_reset_dt_ids[] = {
{ .compatible = "oxsemi,ox810se-reset", },
+ { .compatible = "oxsemi,ox820-reset", },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, oxnas_reset_dt_ids);
diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c
index 78ebf8424375..43e4a9f39b9b 100644
--- a/drivers/reset/reset-socfpga.c
+++ b/drivers/reset/reset-socfpga.c
@@ -1,4 +1,6 @@
/*
+ * Socfpga Reset Controller Driver
+ *
* Copyright 2014 Steffen Trumtrar <s.trumtrar@pengutronix.de>
*
* based on
@@ -16,7 +18,7 @@
#include <linux/err.h>
#include <linux/io.h>
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
@@ -148,8 +150,4 @@ static struct platform_driver socfpga_reset_driver = {
.of_match_table = socfpga_reset_dt_ids,
},
};
-module_platform_driver(socfpga_reset_driver);
-
-MODULE_AUTHOR("Steffen Trumtrar <s.trumtrar@pengutronix.de");
-MODULE_DESCRIPTION("Socfpga Reset Controller Driver");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(socfpga_reset_driver);
diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c
index 3080190b3f90..b44f6b5f87b6 100644
--- a/drivers/reset/reset-sunxi.c
+++ b/drivers/reset/reset-sunxi.c
@@ -13,7 +13,7 @@
#include <linux/err.h>
#include <linux/io.h>
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
@@ -142,7 +142,6 @@ static const struct of_device_id sunxi_reset_dt_ids[] = {
{ .compatible = "allwinner,sun6i-a31-clock-reset", },
{ /* sentinel */ },
};
-MODULE_DEVICE_TABLE(of, sunxi_reset_dt_ids);
static int sunxi_reset_probe(struct platform_device *pdev)
{
@@ -175,8 +174,4 @@ static struct platform_driver sunxi_reset_driver = {
.of_match_table = sunxi_reset_dt_ids,
},
};
-module_platform_driver(sunxi_reset_driver);
-
-MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
-MODULE_DESCRIPTION("Allwinner SoCs Reset Controller Driver");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(sunxi_reset_driver);
diff --git a/drivers/reset/reset-ti-syscon.c b/drivers/reset/reset-ti-syscon.c
index 47f0ffd3b013..99520b0a1329 100644
--- a/drivers/reset/reset-ti-syscon.c
+++ b/drivers/reset/reset-ti-syscon.c
@@ -154,11 +154,11 @@ static int ti_syscon_reset_status(struct reset_controller_dev *rcdev,
if (ret)
return ret;
- return (reset_state & BIT(control->status_bit)) &&
- (control->flags & STATUS_SET);
+ return !(reset_state & BIT(control->status_bit)) ==
+ !(control->flags & STATUS_SET);
}
-static struct reset_control_ops ti_syscon_reset_ops = {
+static const struct reset_control_ops ti_syscon_reset_ops = {
.assert = ti_syscon_reset_assert,
.deassert = ti_syscon_reset_deassert,
.status = ti_syscon_reset_status,
diff --git a/drivers/reset/reset-uniphier.c b/drivers/reset/reset-uniphier.c
index 968c3ae4535c..9c11be3d3450 100644
--- a/drivers/reset/reset-uniphier.c
+++ b/drivers/reset/reset-uniphier.c
@@ -390,6 +390,10 @@ static const struct of_device_id uniphier_reset_match[] = {
.data = uniphier_sld3_mio_reset_data,
},
{
+ .compatible = "socionext,uniphier-ld11-sd-reset",
+ .data = uniphier_pro5_sd_reset_data,
+ },
+ {
.compatible = "socionext,uniphier-ld20-sd-reset",
.data = uniphier_pro5_sd_reset_data,
},
diff --git a/drivers/reset/reset-zx2967.c b/drivers/reset/reset-zx2967.c
new file mode 100644
index 000000000000..4dabb9ec4841
--- /dev/null
+++ b/drivers/reset/reset-zx2967.c
@@ -0,0 +1,99 @@
+/*
+ * ZTE's zx2967 family reset controller driver
+ *
+ * Copyright (C) 2017 ZTE Ltd.
+ *
+ * Author: Baoyou Xie <baoyou.xie@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+
+struct zx2967_reset {
+ void __iomem *reg_base;
+ spinlock_t lock;
+ struct reset_controller_dev rcdev;
+};
+
+static int zx2967_reset_act(struct reset_controller_dev *rcdev,
+ unsigned long id, bool assert)
+{
+ struct zx2967_reset *reset = NULL;
+ int bank = id / 32;
+ int offset = id % 32;
+ u32 reg;
+ unsigned long flags;
+
+ reset = container_of(rcdev, struct zx2967_reset, rcdev);
+
+ spin_lock_irqsave(&reset->lock, flags);
+
+ reg = readl_relaxed(reset->reg_base + (bank * 4));
+ if (assert)
+ reg &= ~BIT(offset);
+ else
+ reg |= BIT(offset);
+ writel_relaxed(reg, reset->reg_base + (bank * 4));
+
+ spin_unlock_irqrestore(&reset->lock, flags);
+
+ return 0;
+}
+
+static int zx2967_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return zx2967_reset_act(rcdev, id, true);
+}
+
+static int zx2967_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return zx2967_reset_act(rcdev, id, false);
+}
+
+static struct reset_control_ops zx2967_reset_ops = {
+ .assert = zx2967_reset_assert,
+ .deassert = zx2967_reset_deassert,
+};
+
+static int zx2967_reset_probe(struct platform_device *pdev)
+{
+ struct zx2967_reset *reset;
+ struct resource *res;
+
+ reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL);
+ if (!reset)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ reset->reg_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(reset->reg_base))
+ return PTR_ERR(reset->reg_base);
+
+ spin_lock_init(&reset->lock);
+
+ reset->rcdev.owner = THIS_MODULE;
+ reset->rcdev.nr_resets = resource_size(res) * 8;
+ reset->rcdev.ops = &zx2967_reset_ops;
+ reset->rcdev.of_node = pdev->dev.of_node;
+
+ return devm_reset_controller_register(&pdev->dev, &reset->rcdev);
+}
+
+static const struct of_device_id zx2967_reset_dt_ids[] = {
+ { .compatible = "zte,zx296718-reset", },
+ {},
+};
+
+static struct platform_driver zx2967_reset_driver = {
+ .probe = zx2967_reset_probe,
+ .driver = {
+ .name = "zx2967-reset",
+ .of_match_table = zx2967_reset_dt_ids,
+ },
+};
+builtin_platform_driver(zx2967_reset_driver);
diff --git a/drivers/reset/reset-zynq.c b/drivers/reset/reset-zynq.c
index 138f2f205662..87a4e355578f 100644
--- a/drivers/reset/reset-zynq.c
+++ b/drivers/reset/reset-zynq.c
@@ -3,6 +3,8 @@
*
* Xilinx Zynq Reset controller driver
*
+ * Author: Moritz Fischer <moritz.fischer@ettus.com>
+ *
* 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; version 2 of the License.
@@ -15,7 +17,7 @@
#include <linux/err.h>
#include <linux/io.h>
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/platform_device.h>
@@ -137,8 +139,4 @@ static struct platform_driver zynq_reset_driver = {
.of_match_table = zynq_reset_dt_ids,
},
};
-module_platform_driver(zynq_reset_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Moritz Fischer <moritz.fischer@ettus.com>");
-MODULE_DESCRIPTION("Zynq Reset Controller Driver");
+builtin_platform_driver(zynq_reset_driver);
diff --git a/drivers/reset/sti/Kconfig b/drivers/reset/sti/Kconfig
index 613178553612..71592b5bfd14 100644
--- a/drivers/reset/sti/Kconfig
+++ b/drivers/reset/sti/Kconfig
@@ -3,14 +3,6 @@ if ARCH_STI
config STI_RESET_SYSCFG
bool
-config STIH415_RESET
- bool
- select STI_RESET_SYSCFG
-
-config STIH416_RESET
- bool
- select STI_RESET_SYSCFG
-
config STIH407_RESET
bool
select STI_RESET_SYSCFG
diff --git a/drivers/reset/sti/Makefile b/drivers/reset/sti/Makefile
index dc85dfbe56a9..f9d82411f29e 100644
--- a/drivers/reset/sti/Makefile
+++ b/drivers/reset/sti/Makefile
@@ -1,5 +1,3 @@
obj-$(CONFIG_STI_RESET_SYSCFG) += reset-syscfg.o
-obj-$(CONFIG_STIH415_RESET) += reset-stih415.o
-obj-$(CONFIG_STIH416_RESET) += reset-stih416.o
obj-$(CONFIG_STIH407_RESET) += reset-stih407.o
diff --git a/drivers/reset/sti/reset-stih415.c b/drivers/reset/sti/reset-stih415.c
deleted file mode 100644
index 6f220cdbef46..000000000000
--- a/drivers/reset/sti/reset-stih415.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2013 STMicroelectronics (R&D) Limited
- * Author: Stephen Gallimore <stephen.gallimore@st.com>
- * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
- *
- * 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/module.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-
-#include <dt-bindings/reset/stih415-resets.h>
-
-#include "reset-syscfg.h"
-
-/*
- * STiH415 Peripheral powerdown definitions.
- */
-static const char stih415_front[] = "st,stih415-front-syscfg";
-static const char stih415_rear[] = "st,stih415-rear-syscfg";
-static const char stih415_sbc[] = "st,stih415-sbc-syscfg";
-static const char stih415_lpm[] = "st,stih415-lpm-syscfg";
-
-#define STIH415_PDN_FRONT(_bit) \
- _SYSCFG_RST_CH(stih415_front, SYSCFG_114, _bit, SYSSTAT_187, _bit)
-
-#define STIH415_PDN_REAR(_cntl, _stat) \
- _SYSCFG_RST_CH(stih415_rear, SYSCFG_336, _cntl, SYSSTAT_384, _stat)
-
-#define STIH415_SRST_REAR(_reg, _bit) \
- _SYSCFG_RST_CH_NO_ACK(stih415_rear, _reg, _bit)
-
-#define STIH415_SRST_SBC(_reg, _bit) \
- _SYSCFG_RST_CH_NO_ACK(stih415_sbc, _reg, _bit)
-
-#define STIH415_SRST_FRONT(_reg, _bit) \
- _SYSCFG_RST_CH_NO_ACK(stih415_front, _reg, _bit)
-
-#define STIH415_SRST_LPM(_reg, _bit) \
- _SYSCFG_RST_CH_NO_ACK(stih415_lpm, _reg, _bit)
-
-#define SYSCFG_114 0x38 /* Powerdown request EMI/NAND/Keyscan */
-#define SYSSTAT_187 0x15c /* Powerdown status EMI/NAND/Keyscan */
-
-#define SYSCFG_336 0x90 /* Powerdown request USB/SATA/PCIe */
-#define SYSSTAT_384 0x150 /* Powerdown status USB/SATA/PCIe */
-
-#define SYSCFG_376 0x130 /* Reset generator 0 control 0 */
-#define SYSCFG_166 0x108 /* Softreset Ethernet 0 */
-#define SYSCFG_31 0x7c /* Softreset Ethernet 1 */
-#define LPM_SYSCFG_1 0x4 /* Softreset IRB */
-
-static const struct syscfg_reset_channel_data stih415_powerdowns[] = {
- [STIH415_EMISS_POWERDOWN] = STIH415_PDN_FRONT(0),
- [STIH415_NAND_POWERDOWN] = STIH415_PDN_FRONT(1),
- [STIH415_KEYSCAN_POWERDOWN] = STIH415_PDN_FRONT(2),
- [STIH415_USB0_POWERDOWN] = STIH415_PDN_REAR(0, 0),
- [STIH415_USB1_POWERDOWN] = STIH415_PDN_REAR(1, 1),
- [STIH415_USB2_POWERDOWN] = STIH415_PDN_REAR(2, 2),
- [STIH415_SATA0_POWERDOWN] = STIH415_PDN_REAR(3, 3),
- [STIH415_SATA1_POWERDOWN] = STIH415_PDN_REAR(4, 4),
- [STIH415_PCIE_POWERDOWN] = STIH415_PDN_REAR(5, 8),
-};
-
-static const struct syscfg_reset_channel_data stih415_softresets[] = {
- [STIH415_ETH0_SOFTRESET] = STIH415_SRST_FRONT(SYSCFG_166, 0),
- [STIH415_ETH1_SOFTRESET] = STIH415_SRST_SBC(SYSCFG_31, 0),
- [STIH415_IRB_SOFTRESET] = STIH415_SRST_LPM(LPM_SYSCFG_1, 6),
- [STIH415_USB0_SOFTRESET] = STIH415_SRST_REAR(SYSCFG_376, 9),
- [STIH415_USB1_SOFTRESET] = STIH415_SRST_REAR(SYSCFG_376, 10),
- [STIH415_USB2_SOFTRESET] = STIH415_SRST_REAR(SYSCFG_376, 11),
- [STIH415_KEYSCAN_SOFTRESET] = STIH415_SRST_LPM(LPM_SYSCFG_1, 8),
-};
-
-static struct syscfg_reset_controller_data stih415_powerdown_controller = {
- .wait_for_ack = true,
- .nr_channels = ARRAY_SIZE(stih415_powerdowns),
- .channels = stih415_powerdowns,
-};
-
-static struct syscfg_reset_controller_data stih415_softreset_controller = {
- .wait_for_ack = false,
- .active_low = true,
- .nr_channels = ARRAY_SIZE(stih415_softresets),
- .channels = stih415_softresets,
-};
-
-static const struct of_device_id stih415_reset_match[] = {
- { .compatible = "st,stih415-powerdown",
- .data = &stih415_powerdown_controller, },
- { .compatible = "st,stih415-softreset",
- .data = &stih415_softreset_controller, },
- {},
-};
-
-static struct platform_driver stih415_reset_driver = {
- .probe = syscfg_reset_probe,
- .driver = {
- .name = "reset-stih415",
- .of_match_table = stih415_reset_match,
- },
-};
-
-static int __init stih415_reset_init(void)
-{
- return platform_driver_register(&stih415_reset_driver);
-}
-arch_initcall(stih415_reset_init);
diff --git a/drivers/reset/sti/reset-stih416.c b/drivers/reset/sti/reset-stih416.c
deleted file mode 100644
index c581d606ef0f..000000000000
--- a/drivers/reset/sti/reset-stih416.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2013 STMicroelectronics (R&D) Limited
- * Author: Stephen Gallimore <stephen.gallimore@st.com>
- * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
- *
- * 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/module.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-
-#include <dt-bindings/reset/stih416-resets.h>
-
-#include "reset-syscfg.h"
-
-/*
- * STiH416 Peripheral powerdown definitions.
- */
-static const char stih416_front[] = "st,stih416-front-syscfg";
-static const char stih416_rear[] = "st,stih416-rear-syscfg";
-static const char stih416_sbc[] = "st,stih416-sbc-syscfg";
-static const char stih416_lpm[] = "st,stih416-lpm-syscfg";
-static const char stih416_cpu[] = "st,stih416-cpu-syscfg";
-
-#define STIH416_PDN_FRONT(_bit) \
- _SYSCFG_RST_CH(stih416_front, SYSCFG_1500, _bit, SYSSTAT_1578, _bit)
-
-#define STIH416_PDN_REAR(_cntl, _stat) \
- _SYSCFG_RST_CH(stih416_rear, SYSCFG_2525, _cntl, SYSSTAT_2583, _stat)
-
-#define SYSCFG_1500 0x7d0 /* Powerdown request EMI/NAND/Keyscan */
-#define SYSSTAT_1578 0x908 /* Powerdown status EMI/NAND/Keyscan */
-
-#define SYSCFG_2525 0x834 /* Powerdown request USB/SATA/PCIe */
-#define SYSSTAT_2583 0x91c /* Powerdown status USB/SATA/PCIe */
-
-#define SYSCFG_2552 0x8A0 /* Reset Generator control 0 */
-#define SYSCFG_1539 0x86c /* Softreset Ethernet 0 */
-#define SYSCFG_510 0x7f8 /* Softreset Ethernet 1 */
-#define LPM_SYSCFG_1 0x4 /* Softreset IRB */
-#define SYSCFG_2553 0x8a4 /* Softreset SATA0/1, PCIE0/1 */
-#define SYSCFG_7563 0x8cc /* MPE softresets 0 */
-#define SYSCFG_7564 0x8d0 /* MPE softresets 1 */
-
-#define STIH416_SRST_CPU(_reg, _bit) \
- _SYSCFG_RST_CH_NO_ACK(stih416_cpu, _reg, _bit)
-
-#define STIH416_SRST_FRONT(_reg, _bit) \
- _SYSCFG_RST_CH_NO_ACK(stih416_front, _reg, _bit)
-
-#define STIH416_SRST_REAR(_reg, _bit) \
- _SYSCFG_RST_CH_NO_ACK(stih416_rear, _reg, _bit)
-
-#define STIH416_SRST_LPM(_reg, _bit) \
- _SYSCFG_RST_CH_NO_ACK(stih416_lpm, _reg, _bit)
-
-#define STIH416_SRST_SBC(_reg, _bit) \
- _SYSCFG_RST_CH_NO_ACK(stih416_sbc, _reg, _bit)
-
-static const struct syscfg_reset_channel_data stih416_powerdowns[] = {
- [STIH416_EMISS_POWERDOWN] = STIH416_PDN_FRONT(0),
- [STIH416_NAND_POWERDOWN] = STIH416_PDN_FRONT(1),
- [STIH416_KEYSCAN_POWERDOWN] = STIH416_PDN_FRONT(2),
- [STIH416_USB0_POWERDOWN] = STIH416_PDN_REAR(0, 0),
- [STIH416_USB1_POWERDOWN] = STIH416_PDN_REAR(1, 1),
- [STIH416_USB2_POWERDOWN] = STIH416_PDN_REAR(2, 2),
- [STIH416_USB3_POWERDOWN] = STIH416_PDN_REAR(6, 5),
- [STIH416_SATA0_POWERDOWN] = STIH416_PDN_REAR(3, 3),
- [STIH416_SATA1_POWERDOWN] = STIH416_PDN_REAR(4, 4),
- [STIH416_PCIE0_POWERDOWN] = STIH416_PDN_REAR(7, 9),
- [STIH416_PCIE1_POWERDOWN] = STIH416_PDN_REAR(5, 8),
-};
-
-static const struct syscfg_reset_channel_data stih416_softresets[] = {
- [STIH416_ETH0_SOFTRESET] = STIH416_SRST_FRONT(SYSCFG_1539, 0),
- [STIH416_ETH1_SOFTRESET] = STIH416_SRST_SBC(SYSCFG_510, 0),
- [STIH416_IRB_SOFTRESET] = STIH416_SRST_LPM(LPM_SYSCFG_1, 6),
- [STIH416_USB0_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2552, 9),
- [STIH416_USB1_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2552, 10),
- [STIH416_USB2_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2552, 11),
- [STIH416_USB3_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2552, 28),
- [STIH416_SATA0_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2553, 7),
- [STIH416_SATA1_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2553, 3),
- [STIH416_PCIE0_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2553, 15),
- [STIH416_PCIE1_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2553, 2),
- [STIH416_AUD_DAC_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2553, 14),
- [STIH416_HDTVOUT_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2552, 5),
- [STIH416_VTAC_M_RX_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2552, 25),
- [STIH416_VTAC_A_RX_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2552, 26),
- [STIH416_SYNC_HD_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2553, 5),
- [STIH416_SYNC_SD_SOFTRESET] = STIH416_SRST_REAR(SYSCFG_2553, 6),
- [STIH416_BLITTER_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7563, 10),
- [STIH416_GPU_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7563, 11),
- [STIH416_VTAC_M_TX_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7563, 18),
- [STIH416_VTAC_A_TX_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7563, 19),
- [STIH416_VTG_AUX_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7563, 21),
- [STIH416_JPEG_DEC_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7563, 23),
- [STIH416_HVA_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7564, 2),
- [STIH416_COMPO_M_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7564, 3),
- [STIH416_COMPO_A_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7564, 4),
- [STIH416_VP8_DEC_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7564, 10),
- [STIH416_VTG_MAIN_SOFTRESET] = STIH416_SRST_CPU(SYSCFG_7564, 16),
- [STIH416_KEYSCAN_SOFTRESET] = STIH416_SRST_LPM(LPM_SYSCFG_1, 8),
-};
-
-static struct syscfg_reset_controller_data stih416_powerdown_controller = {
- .wait_for_ack = true,
- .nr_channels = ARRAY_SIZE(stih416_powerdowns),
- .channels = stih416_powerdowns,
-};
-
-static struct syscfg_reset_controller_data stih416_softreset_controller = {
- .wait_for_ack = false,
- .active_low = true,
- .nr_channels = ARRAY_SIZE(stih416_softresets),
- .channels = stih416_softresets,
-};
-
-static const struct of_device_id stih416_reset_match[] = {
- { .compatible = "st,stih416-powerdown",
- .data = &stih416_powerdown_controller, },
- { .compatible = "st,stih416-softreset",
- .data = &stih416_softreset_controller, },
- {},
-};
-
-static struct platform_driver stih416_reset_driver = {
- .probe = syscfg_reset_probe,
- .driver = {
- .name = "reset-stih416",
- .of_match_table = stih416_reset_match,
- },
-};
-
-static int __init stih416_reset_init(void)
-{
- return platform_driver_register(&stih416_reset_driver);
-}
-arch_initcall(stih416_reset_init);
diff --git a/drivers/reset/tegra/Kconfig b/drivers/reset/tegra/Kconfig
new file mode 100644
index 000000000000..d2afa293df7d
--- /dev/null
+++ b/drivers/reset/tegra/Kconfig
@@ -0,0 +1,2 @@
+config RESET_TEGRA_BPMP
+ def_bool TEGRA_BPMP
diff --git a/drivers/reset/tegra/Makefile b/drivers/reset/tegra/Makefile
new file mode 100644
index 000000000000..775243ab7383
--- /dev/null
+++ b/drivers/reset/tegra/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_RESET_TEGRA_BPMP) += reset-bpmp.o
diff --git a/drivers/reset/tegra/reset-bpmp.c b/drivers/reset/tegra/reset-bpmp.c
new file mode 100644
index 000000000000..5daf2ee1a396
--- /dev/null
+++ b/drivers/reset/tegra/reset-bpmp.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2016 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/reset-controller.h>
+
+#include <soc/tegra/bpmp.h>
+#include <soc/tegra/bpmp-abi.h>
+
+static struct tegra_bpmp *to_tegra_bpmp(struct reset_controller_dev *rstc)
+{
+ return container_of(rstc, struct tegra_bpmp, rstc);
+}
+
+static int tegra_bpmp_reset_common(struct reset_controller_dev *rstc,
+ enum mrq_reset_commands command,
+ unsigned int id)
+{
+ struct tegra_bpmp *bpmp = to_tegra_bpmp(rstc);
+ struct mrq_reset_request request;
+ struct tegra_bpmp_message msg;
+
+ memset(&request, 0, sizeof(request));
+ request.cmd = command;
+ request.reset_id = id;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.mrq = MRQ_RESET;
+ msg.tx.data = &request;
+ msg.tx.size = sizeof(request);
+
+ return tegra_bpmp_transfer(bpmp, &msg);
+}
+
+static int tegra_bpmp_reset_module(struct reset_controller_dev *rstc,
+ unsigned long id)
+{
+ return tegra_bpmp_reset_common(rstc, CMD_RESET_MODULE, id);
+}
+
+static int tegra_bpmp_reset_assert(struct reset_controller_dev *rstc,
+ unsigned long id)
+{
+ return tegra_bpmp_reset_common(rstc, CMD_RESET_ASSERT, id);
+}
+
+static int tegra_bpmp_reset_deassert(struct reset_controller_dev *rstc,
+ unsigned long id)
+{
+ return tegra_bpmp_reset_common(rstc, CMD_RESET_DEASSERT, id);
+}
+
+static const struct reset_control_ops tegra_bpmp_reset_ops = {
+ .reset = tegra_bpmp_reset_module,
+ .assert = tegra_bpmp_reset_assert,
+ .deassert = tegra_bpmp_reset_deassert,
+};
+
+int tegra_bpmp_init_resets(struct tegra_bpmp *bpmp)
+{
+ bpmp->rstc.ops = &tegra_bpmp_reset_ops;
+ bpmp->rstc.owner = THIS_MODULE;
+ bpmp->rstc.of_node = bpmp->dev->of_node;
+ bpmp->rstc.nr_resets = bpmp->soc->num_resets;
+
+ return devm_reset_controller_register(bpmp->dev, &bpmp->rstc);
+}