diff options
Diffstat (limited to 'drivers/reset')
-rw-r--r-- | drivers/reset/Kconfig | 1 | ||||
-rw-r--r-- | drivers/reset/core.c | 168 | ||||
-rw-r--r-- | drivers/reset/reset-imx7.c | 11 | ||||
-rw-r--r-- | drivers/reset/reset-scmi.c | 6 | ||||
-rw-r--r-- | drivers/reset/reset-simple.c | 7 | ||||
-rw-r--r-- | drivers/reset/reset-socfpga.c | 7 | ||||
-rw-r--r-- | drivers/reset/reset-starfive-vic.c | 7 |
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, |