summaryrefslogtreecommitdiffstats
path: root/drivers/reset
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/reset')
-rw-r--r--drivers/reset/Kconfig1
-rw-r--r--drivers/reset/core.c168
-rw-r--r--drivers/reset/reset-imx7.c11
-rw-r--r--drivers/reset/reset-scmi.c6
-rw-r--r--drivers/reset/reset-simple.c7
-rw-r--r--drivers/reset/reset-socfpga.c7
-rw-r--r--drivers/reset/reset-starfive-vic.c7
7 files changed, 171 insertions, 36 deletions
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 913b309eac..16c05d50f0 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -41,6 +41,7 @@ config RESET_IMX7
config RESET_STARFIVE
bool "StarFive Controller Driver" if COMPILE_TEST
+ depends on COMMON_CLK
default SOC_STARFIVE
help
This enables the reset controller driver for the StarFive JH7100.
diff --git a/drivers/reset/core.c b/drivers/reset/core.c
index 4355c3415e..94bfad2067 100644
--- a/drivers/reset/core.c
+++ b/drivers/reset/core.c
@@ -29,8 +29,21 @@ struct reset_control {
int gpio;
int gpio_active_high;
- struct device_d *dev;
+ struct device *dev;
unsigned int id;
+ bool array;
+};
+
+/**
+ * struct reset_control_array - an array of reset controls
+ * @base: reset control for compatibility with reset control API functions
+ * @num_rstcs: number of reset controls
+ * @rstc: array of reset controls
+ */
+struct reset_control_array {
+ struct reset_control base;
+ unsigned int num_rstcs;
+ struct reset_control *rstc[];
};
/**
@@ -102,6 +115,65 @@ int reset_control_status(struct reset_control *rstc)
}
EXPORT_SYMBOL_GPL(reset_control_status);
+static inline struct reset_control_array *
+rstc_to_array(struct reset_control *rstc) {
+ return container_of(rstc, struct reset_control_array, base);
+}
+
+static int reset_control_array_reset(struct reset_control_array *resets)
+{
+ int ret, i;
+
+ for (i = 0; i < resets->num_rstcs; i++) {
+ ret = reset_control_reset(resets->rstc[i]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int reset_control_array_assert(struct reset_control_array *resets)
+{
+ int ret, i;
+
+ for (i = 0; i < resets->num_rstcs; i++) {
+ ret = reset_control_assert(resets->rstc[i]);
+ if (ret)
+ goto err;
+ }
+
+ return 0;
+
+err:
+ while (i--)
+ reset_control_deassert(resets->rstc[i]);
+ return ret;
+}
+
+static int reset_control_array_deassert(struct reset_control_array *resets)
+{
+ int ret, i;
+
+ for (i = 0; i < resets->num_rstcs; i++) {
+ ret = reset_control_deassert(resets->rstc[i]);
+ if (ret)
+ goto err;
+ }
+
+ return 0;
+
+err:
+ while (i--)
+ reset_control_assert(resets->rstc[i]);
+ return ret;
+}
+
+static inline bool reset_control_is_array(struct reset_control *rstc)
+{
+ return rstc->array;
+}
+
/**
* reset_control_reset - reset the controlled device
* @rstc: reset controller
@@ -111,6 +183,9 @@ int reset_control_reset(struct reset_control *rstc)
if (!rstc)
return 0;
+ if (reset_control_is_array(rstc))
+ return reset_control_array_reset(rstc_to_array(rstc));
+
if (rstc->rcdev->ops->reset)
return rstc->rcdev->ops->reset(rstc->rcdev, rstc->id);
@@ -127,6 +202,9 @@ int reset_control_assert(struct reset_control *rstc)
if (!rstc)
return 0;
+ if (reset_control_is_array(rstc))
+ return reset_control_array_assert(rstc_to_array(rstc));
+
if (rstc->gpio >= 0)
return gpio_direction_output(rstc->gpio, rstc->gpio_active_high);
@@ -146,6 +224,9 @@ int reset_control_deassert(struct reset_control *rstc)
if (!rstc)
return 0;
+ if (reset_control_is_array(rstc))
+ return reset_control_array_deassert(rstc_to_array(rstc));
+
if (rstc->gpio >= 0)
return gpio_direction_output(rstc->gpio, !rstc->gpio_active_high);
@@ -157,14 +238,15 @@ int reset_control_deassert(struct reset_control *rstc)
EXPORT_SYMBOL_GPL(reset_control_deassert);
/**
- * of_reset_control_count - Count reset lines
- * @node: device node
+ * reset_control_get_count - Count reset lines
+ * @dev: device
*
* Returns number of resets, 0 if none specified
*/
-static int of_reset_control_count(struct device_node *node)
+int reset_control_get_count(struct device *dev)
{
- return of_count_phandle_with_args(node, "resets", "#reset-cells");
+ return of_count_phandle_with_args(dev->of_node, "resets",
+ "#reset-cells");
}
/**
@@ -191,9 +273,8 @@ static struct reset_control *of_reset_control_get_by_index(struct device_node *n
if (ret)
return ERR_PTR(ret);
- ret = of_device_ensure_probed(args.np);
- if (ret)
- return ERR_PTR(ret);
+ /* Ignore error, as CLK_OF_DECLARE resets have no proper driver. */
+ of_device_ensure_probed(args.np);
rcdev = NULL;
list_for_each_entry(r, &reset_controller_list, list) {
@@ -236,14 +317,17 @@ struct reset_control *of_reset_control_get(struct device_node *node,
{
int index = 0;
- if (id)
+ 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);
}
static struct reset_control *
-gpio_reset_control_get(struct device_d *dev, const char *id)
+gpio_reset_control_get(struct device *dev, const char *id)
{
struct reset_control *rc;
int gpio;
@@ -252,10 +336,10 @@ gpio_reset_control_get(struct device_d *dev, const char *id)
if (id)
return ERR_PTR(-EINVAL);
- if (!of_get_property(dev->device_node, "reset-gpios", NULL))
+ if (!of_get_property(dev->of_node, "reset-gpios", NULL))
return NULL;
- gpio = of_get_named_gpio_flags(dev->device_node, "reset-gpios", 0, &flags);
+ gpio = of_get_named_gpio_flags(dev->of_node, "reset-gpios", 0, &flags);
if (gpio < 0)
return ERR_PTR(gpio);
@@ -275,14 +359,14 @@ gpio_reset_control_get(struct device_d *dev, const char *id)
*
* Use of id names is optional.
*/
-struct reset_control *reset_control_get(struct device_d *dev, const char *id)
+struct reset_control *reset_control_get(struct device *dev, const char *id)
{
struct reset_control *rstc;
if (!dev)
return ERR_PTR(-EINVAL);
- rstc = of_reset_control_get(dev->device_node, id);
+ rstc = of_reset_control_get(dev->of_node, id);
if (IS_ERR(rstc))
return ERR_CAST(rstc);
@@ -328,7 +412,7 @@ EXPORT_SYMBOL_GPL(reset_control_put);
* This is useful for the common case of devices with single, dedicated reset
* lines.
*/
-int device_reset(struct device_d *dev)
+int device_reset(struct device *dev)
{
struct reset_control *rstc;
int ret;
@@ -349,15 +433,61 @@ int device_reset(struct device_d *dev)
}
EXPORT_SYMBOL_GPL(device_reset);
-int device_reset_all(struct device_d *dev)
+/*
+ * APIs to manage an array of reset controls.
+ */
+
+/**
+ * reset_control_array_get - Get a list of reset controls
+ *
+ * @dev: device that requests the reset controls array
+ *
+ * Returns pointer to allocated reset_control on success or error on failure
+ */
+struct reset_control *reset_control_array_get(struct device *dev)
+{
+ struct reset_control_array *resets;
+ struct reset_control *rstc;
+ struct device_node *np = dev->of_node;
+ int num, i;
+
+ num = reset_control_get_count(dev);
+ if (num < 0)
+ return ERR_PTR(num);
+
+ resets = kzalloc(struct_size(resets, rstc, num), GFP_KERNEL);
+ if (!resets)
+ return ERR_PTR(-ENOMEM);
+
+ for (i = 0; i < num; i++) {
+ rstc = of_reset_control_get_by_index(np, i);
+ if (IS_ERR(rstc))
+ goto err_rst;
+ resets->rstc[i] = rstc;
+ }
+ resets->num_rstcs = num;
+ resets->base.array = true;
+
+ return &resets->base;
+
+err_rst:
+ while (--i >= 0)
+ reset_control_put(resets->rstc[i]);
+
+ kfree(resets);
+
+ return rstc;
+}
+
+int device_reset_all(struct device *dev)
{
struct reset_control *rstc;
int ret, i;
- for (i = 0; i < of_reset_control_count(dev->device_node); i++) {
+ for (i = 0; i < reset_control_get_count(dev); i++) {
int ret;
- rstc = of_reset_control_get_by_index(dev->device_node, i);
+ rstc = of_reset_control_get_by_index(dev->of_node, i);
if (IS_ERR(rstc))
return PTR_ERR(rstc);
@@ -382,7 +512,7 @@ int device_reset_all(struct device_d *dev)
}
EXPORT_SYMBOL_GPL(device_reset_all);
-int device_reset_us(struct device_d *dev, int us)
+int device_reset_us(struct device *dev, int us)
{
struct reset_control *rstc;
int ret;
diff --git a/drivers/reset/reset-imx7.c b/drivers/reset/reset-imx7.c
index 1591ace2cd..c6c38f48a8 100644
--- a/drivers/reset/reset-imx7.c
+++ b/drivers/reset/reset-imx7.c
@@ -14,7 +14,7 @@
#include <linux/err.h>
#include <linux/reset-controller.h>
#include <mfd/syscon.h>
-#include <regmap.h>
+#include <linux/regmap.h>
#include <of_device.h>
struct imx7_src_signal {
@@ -253,14 +253,14 @@ static const struct imx7_src_variant variant_imx8mq = {
},
};
-static int imx7_reset_probe(struct device_d *dev)
+static int imx7_reset_probe(struct device *dev)
{
struct imx7_src *imx7src;
const struct imx7_src_variant *variant = of_device_get_match_data(dev);
imx7src = xzalloc(sizeof(*imx7src));
imx7src->signals = variant->signals;
- imx7src->regmap = syscon_node_to_regmap(dev->device_node);
+ imx7src->regmap = syscon_node_to_regmap(dev->of_node);
if (IS_ERR(imx7src->regmap)) {
dev_err(dev, "Unable to get imx7-src regmap");
return PTR_ERR(imx7src->regmap);
@@ -268,7 +268,7 @@ static int imx7_reset_probe(struct device_d *dev)
imx7src->rcdev.nr_resets = variant->signals_num;
imx7src->rcdev.ops = &variant->ops;
- imx7src->rcdev.of_node = dev->device_node;
+ imx7src->rcdev.of_node = dev->of_node;
return reset_controller_register(&imx7src->rcdev);
}
@@ -278,8 +278,9 @@ static const struct of_device_id imx7_reset_dt_ids[] = {
{ .compatible = "fsl,imx8mq-src", .data = &variant_imx8mq },
{ /* sentinel */ },
};
+MODULE_DEVICE_TABLE(of, imx7_reset_dt_ids);
-static struct driver_d imx7_reset_driver = {
+static struct driver imx7_reset_driver = {
.name = "imx7d-src",
.probe = imx7_reset_probe,
.of_compatible = DRV_OF_COMPAT(imx7_reset_dt_ids),
diff --git a/drivers/reset/reset-scmi.c b/drivers/reset/reset-scmi.c
index c33bbc5c8a..d8c4734f1b 100644
--- a/drivers/reset/reset-scmi.c
+++ b/drivers/reset/reset-scmi.c
@@ -89,15 +89,15 @@ static const struct reset_control_ops scmi_reset_ops = {
static int scmi_reset_probe(struct scmi_device *sdev)
{
struct scmi_reset_data *data;
- struct device_d *dev = &sdev->dev;
- struct device_node *np = dev->device_node;
+ struct device *dev = &sdev->dev;
+ struct device_node *np = dev->of_node;
const struct scmi_handle *handle = sdev->handle;
struct scmi_protocol_handle *ph;
if (!handle)
return -ENODEV;
- reset_ops = handle->protocol_get(sdev, SCMI_PROTOCOL_RESET, &ph);
+ reset_ops = handle->dev_protocol_get(sdev, SCMI_PROTOCOL_RESET, &ph);
if (IS_ERR(reset_ops))
return PTR_ERR(reset_ops);
diff --git a/drivers/reset/reset-simple.c b/drivers/reset/reset-simple.c
index 9db00f64f4..20f3df18f4 100644
--- a/drivers/reset/reset-simple.c
+++ b/drivers/reset/reset-simple.c
@@ -146,8 +146,9 @@ static const struct of_device_id reset_simple_dt_ids[] = {
.data = &reset_simple_active_low },
{ /* sentinel */ },
};
+MODULE_DEVICE_TABLE(of, reset_simple_dt_ids);
-static int reset_simple_probe(struct device_d *dev)
+static int reset_simple_probe(struct device *dev)
{
const struct reset_simple_devdata *devdata;
struct reset_simple_data *data;
@@ -167,7 +168,7 @@ static int reset_simple_probe(struct device_d *dev)
data->membase = IOMEM(res->start);
data->rcdev.nr_resets = resource_size(res) * BITS_PER_BYTE;
data->rcdev.ops = &reset_simple_ops;
- data->rcdev.of_node = dev->device_node;
+ data->rcdev.of_node = dev->of_node;
if (devdata) {
reg_offset = devdata->reg_offset;
@@ -182,7 +183,7 @@ static int reset_simple_probe(struct device_d *dev)
return reset_controller_register(&data->rcdev);
}
-static struct driver_d reset_simple_driver = {
+static struct driver reset_simple_driver = {
.probe = reset_simple_probe,
.name = "simple-reset",
.of_compatible = reset_simple_dt_ids,
diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c
index 146cc92eb3..d214ce503e 100644
--- a/drivers/reset/reset-socfpga.c
+++ b/drivers/reset/reset-socfpga.c
@@ -74,11 +74,11 @@ static const struct reset_control_ops socfpga_reset_ops = {
.deassert = socfpga_reset_deassert,
};
-static int socfpga_reset_probe(struct device_d *dev)
+static int socfpga_reset_probe(struct device *dev)
{
struct socfpga_reset_data *data;
struct resource *res;
- struct device_node *np = dev->device_node;
+ struct device_node *np = dev->of_node;
u32 modrst_offset;
data = xzalloc(sizeof(*data));
@@ -108,8 +108,9 @@ static const struct of_device_id socfpga_reset_dt_ids[] = {
{ .compatible = "altr,rst-mgr", },
{ /* sentinel */ },
};
+MODULE_DEVICE_TABLE(of, socfpga_reset_dt_ids);
-static struct driver_d socfpga_reset_driver = {
+static struct driver socfpga_reset_driver = {
.name = "socfpga_reset",
.probe = socfpga_reset_probe,
.of_compatible = DRV_OF_COMPAT(socfpga_reset_dt_ids),
diff --git a/drivers/reset/reset-starfive-vic.c b/drivers/reset/reset-starfive-vic.c
index 960e82e824..3e9e367215 100644
--- a/drivers/reset/reset-starfive-vic.c
+++ b/drivers/reset/reset-starfive-vic.c
@@ -196,7 +196,7 @@ static const struct reset_control_ops starfive_rstgen_ops = {
.reset = starfive_reset,
};
-static int starfive_rstgen_probe(struct device_d *dev)
+static int starfive_rstgen_probe(struct device *dev)
{
struct starfive_rstgen *priv;
struct resource *iores;
@@ -216,7 +216,7 @@ static int starfive_rstgen_probe(struct device_d *dev)
priv->base = IOMEM(iores->start);
priv->rcdev.nr_resets = RSTN_END;
priv->rcdev.ops = &starfive_rstgen_ops;
- priv->rcdev.of_node = dev->device_node;
+ priv->rcdev.of_node = dev->of_node;
return reset_controller_register(&priv->rcdev);
}
@@ -225,8 +225,9 @@ static const struct of_device_id starfive_rstgen_reset_dt_ids[] = {
{ .compatible = "starfive,jh7100-rstgen", .data = jh7110_rstgen_sync_resets },
{ /* sentinel */ },
};
+MODULE_DEVICE_TABLE(of, starfive_rstgen_reset_dt_ids);
-static struct driver_d starfive_rstgen_reset_driver = {
+static struct driver starfive_rstgen_reset_driver = {
.name = "starfive_rstgen",
.probe = starfive_rstgen_probe,
.of_compatible = starfive_rstgen_reset_dt_ids,