aboutsummaryrefslogtreecommitdiff
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/core.c215
-rw-r--r--drivers/reset/reset-raspberrypi.c2
-rw-r--r--drivers/reset/reset-scmi.c33
4 files changed, 240 insertions, 17 deletions
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 4171c6f76385..3e7f55e44d84 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -183,7 +183,7 @@ config RESET_SCMI
config RESET_SIMPLE
bool "Simple Reset Controller Driver" if COMPILE_TEST
- default ARCH_AGILEX || ARCH_ASPEED || ARCH_BCM4908 || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARC
+ default ARCH_ASPEED || ARCH_BCM4908 || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || (ARCH_INTEL_SOCFPGA && ARM64) || ARCH_SUNXI || ARC
help
This enables a simple reset controller driver for reset lines that
that can be asserted and deasserted by toggling bits in a contiguous,
@@ -197,6 +197,7 @@ config RESET_SIMPLE
- RCC reset controller in STM32 MCUs
- Allwinner SoCs
- ZTE's zx2967 family
+ - SiFive FU740 SoCs
config RESET_STM32MP157
bool "STM32MP157 Reset Driver" if COMPILE_TEST
@@ -205,8 +206,8 @@ config RESET_STM32MP157
This enables the RCC reset controller driver for STM32 MPUs.
config RESET_SOCFPGA
- bool "SoCFPGA Reset Driver" if COMPILE_TEST && !ARCH_SOCFPGA
- default ARCH_SOCFPGA
+ bool "SoCFPGA Reset Driver" if COMPILE_TEST && (!ARM || !ARCH_INTEL_SOCFPGA)
+ default ARM && ARCH_INTEL_SOCFPGA
select RESET_SIMPLE
help
This enables the reset driver for the SoCFPGA ARMv7 platforms. This
diff --git a/drivers/reset/core.c b/drivers/reset/core.c
index dbf881b586d9..71c1c8264b2d 100644
--- a/drivers/reset/core.c
+++ b/drivers/reset/core.c
@@ -359,6 +359,30 @@ int reset_control_reset(struct reset_control *rstc)
EXPORT_SYMBOL_GPL(reset_control_reset);
/**
+ * reset_control_bulk_reset - reset the controlled devices in order
+ * @num_rstcs: number of entries in rstcs array
+ * @rstcs: array of struct reset_control_bulk_data with reset controls set
+ *
+ * Issue a reset on all provided reset controls, in order.
+ *
+ * See also: reset_control_reset()
+ */
+int reset_control_bulk_reset(int num_rstcs,
+ struct reset_control_bulk_data *rstcs)
+{
+ int ret, i;
+
+ for (i = 0; i < num_rstcs; i++) {
+ ret = reset_control_reset(rstcs[i].rstc);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(reset_control_bulk_reset);
+
+/**
* reset_control_rearm - allow shared reset line to be re-triggered"
* @rstc: reset controller
*
@@ -462,6 +486,36 @@ int reset_control_assert(struct reset_control *rstc)
EXPORT_SYMBOL_GPL(reset_control_assert);
/**
+ * reset_control_bulk_assert - asserts the reset lines in order
+ * @num_rstcs: number of entries in rstcs array
+ * @rstcs: array of struct reset_control_bulk_data with reset controls set
+ *
+ * Assert the reset lines for all provided reset controls, in order.
+ * If an assertion fails, already asserted resets are deasserted again.
+ *
+ * See also: reset_control_assert()
+ */
+int reset_control_bulk_assert(int num_rstcs,
+ struct reset_control_bulk_data *rstcs)
+{
+ int ret, i;
+
+ for (i = 0; i < num_rstcs; i++) {
+ ret = reset_control_assert(rstcs[i].rstc);
+ if (ret)
+ goto err;
+ }
+
+ return 0;
+
+err:
+ while (i--)
+ reset_control_deassert(rstcs[i].rstc);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(reset_control_bulk_assert);
+
+/**
* reset_control_deassert - deasserts the reset line
* @rstc: reset controller
*
@@ -512,6 +566,36 @@ int reset_control_deassert(struct reset_control *rstc)
EXPORT_SYMBOL_GPL(reset_control_deassert);
/**
+ * reset_control_bulk_deassert - deasserts the reset lines in reverse order
+ * @num_rstcs: number of entries in rstcs array
+ * @rstcs: array of struct reset_control_bulk_data with reset controls set
+ *
+ * Deassert the reset lines for all provided reset controls, in reverse order.
+ * If a deassertion fails, already deasserted resets are asserted again.
+ *
+ * See also: reset_control_deassert()
+ */
+int reset_control_bulk_deassert(int num_rstcs,
+ struct reset_control_bulk_data *rstcs)
+{
+ int ret, i;
+
+ for (i = num_rstcs - 1; i >= 0; i--) {
+ ret = reset_control_deassert(rstcs[i].rstc);
+ if (ret)
+ goto err;
+ }
+
+ return 0;
+
+err:
+ while (i < num_rstcs)
+ reset_control_assert(rstcs[i++].rstc);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(reset_control_bulk_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 or if the desc is NULL (optional reset).
@@ -589,6 +673,36 @@ int reset_control_acquire(struct reset_control *rstc)
EXPORT_SYMBOL_GPL(reset_control_acquire);
/**
+ * reset_control_bulk_acquire - acquires reset controls for exclusive use
+ * @num_rstcs: number of entries in rstcs array
+ * @rstcs: array of struct reset_control_bulk_data with reset controls set
+ *
+ * This is used to explicitly acquire reset controls requested with
+ * reset_control_bulk_get_exclusive_release() for temporary exclusive use.
+ *
+ * See also: reset_control_acquire(), reset_control_bulk_release()
+ */
+int reset_control_bulk_acquire(int num_rstcs,
+ struct reset_control_bulk_data *rstcs)
+{
+ int ret, i;
+
+ for (i = 0; i < num_rstcs; i++) {
+ ret = reset_control_acquire(rstcs[i].rstc);
+ if (ret)
+ goto err;
+ }
+
+ return 0;
+
+err:
+ while (i--)
+ reset_control_release(rstcs[i].rstc);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(reset_control_bulk_acquire);
+
+/**
* reset_control_release() - releases exclusive access to a reset control
* @rstc: reset control
*
@@ -610,6 +724,26 @@ void reset_control_release(struct reset_control *rstc)
}
EXPORT_SYMBOL_GPL(reset_control_release);
+/**
+ * reset_control_bulk_release() - releases exclusive access to reset controls
+ * @num_rstcs: number of entries in rstcs array
+ * @rstcs: array of struct reset_control_bulk_data with reset controls set
+ *
+ * Releases exclusive access right to reset controls previously obtained by a
+ * call to reset_control_bulk_acquire().
+ *
+ * See also: reset_control_release(), reset_control_bulk_acquire()
+ */
+void reset_control_bulk_release(int num_rstcs,
+ struct reset_control_bulk_data *rstcs)
+{
+ int i;
+
+ for (i = 0; i < num_rstcs; i++)
+ reset_control_release(rstcs[i].rstc);
+}
+EXPORT_SYMBOL_GPL(reset_control_bulk_release);
+
static struct reset_control *__reset_control_get_internal(
struct reset_controller_dev *rcdev,
unsigned int index, bool shared, bool acquired)
@@ -814,6 +948,32 @@ struct reset_control *__reset_control_get(struct device *dev, const char *id,
}
EXPORT_SYMBOL_GPL(__reset_control_get);
+int __reset_control_bulk_get(struct device *dev, int num_rstcs,
+ struct reset_control_bulk_data *rstcs,
+ bool shared, bool optional, bool acquired)
+{
+ int ret, i;
+
+ for (i = 0; i < num_rstcs; i++) {
+ rstcs[i].rstc = __reset_control_get(dev, rstcs[i].id, 0,
+ shared, optional, acquired);
+ if (IS_ERR(rstcs[i].rstc)) {
+ ret = PTR_ERR(rstcs[i].rstc);
+ goto err;
+ }
+ }
+
+ return 0;
+
+err:
+ mutex_lock(&reset_list_mutex);
+ while (i--)
+ __reset_control_put_internal(rstcs[i].rstc);
+ mutex_unlock(&reset_list_mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(__reset_control_bulk_get);
+
static void reset_control_array_put(struct reset_control_array *resets)
{
int i;
@@ -845,6 +1005,23 @@ void reset_control_put(struct reset_control *rstc)
}
EXPORT_SYMBOL_GPL(reset_control_put);
+/**
+ * reset_control_bulk_put - free the reset controllers
+ * @num_rstcs: number of entries in rstcs array
+ * @rstcs: array of struct reset_control_bulk_data with reset controls set
+ */
+void reset_control_bulk_put(int num_rstcs, struct reset_control_bulk_data *rstcs)
+{
+ mutex_lock(&reset_list_mutex);
+ while (num_rstcs--) {
+ if (IS_ERR_OR_NULL(rstcs[num_rstcs].rstc))
+ continue;
+ __reset_control_put_internal(rstcs[num_rstcs].rstc);
+ }
+ mutex_unlock(&reset_list_mutex);
+}
+EXPORT_SYMBOL_GPL(reset_control_bulk_put);
+
static void devm_reset_control_release(struct device *dev, void *res)
{
reset_control_put(*(struct reset_control **)res);
@@ -874,6 +1051,44 @@ struct reset_control *__devm_reset_control_get(struct device *dev,
}
EXPORT_SYMBOL_GPL(__devm_reset_control_get);
+struct reset_control_bulk_devres {
+ int num_rstcs;
+ struct reset_control_bulk_data *rstcs;
+};
+
+static void devm_reset_control_bulk_release(struct device *dev, void *res)
+{
+ struct reset_control_bulk_devres *devres = res;
+
+ reset_control_bulk_put(devres->num_rstcs, devres->rstcs);
+}
+
+int __devm_reset_control_bulk_get(struct device *dev, int num_rstcs,
+ struct reset_control_bulk_data *rstcs,
+ bool shared, bool optional, bool acquired)
+{
+ struct reset_control_bulk_devres *ptr;
+ int ret;
+
+ ptr = devres_alloc(devm_reset_control_bulk_release, sizeof(*ptr),
+ GFP_KERNEL);
+ if (!ptr)
+ return -ENOMEM;
+
+ ret = __reset_control_bulk_get(dev, num_rstcs, rstcs, shared, optional, acquired);
+ if (ret < 0) {
+ devres_free(ptr);
+ return ret;
+ }
+
+ ptr->num_rstcs = num_rstcs;
+ ptr->rstcs = rstcs;
+ devres_add(dev, ptr);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(__devm_reset_control_bulk_get);
+
/**
* __device_reset - find reset controller associated with the device
* and perform reset
diff --git a/drivers/reset/reset-raspberrypi.c b/drivers/reset/reset-raspberrypi.c
index 02f59c06f69b..fa23db554bcf 100644
--- a/drivers/reset/reset-raspberrypi.c
+++ b/drivers/reset/reset-raspberrypi.c
@@ -82,7 +82,7 @@ static int rpi_reset_probe(struct platform_device *pdev)
return -ENOENT;
}
- fw = rpi_firmware_get(np);
+ fw = devm_rpi_firmware_get(&pdev->dev, np);
of_node_put(np);
if (!fw)
return -EPROBE_DEFER;
diff --git a/drivers/reset/reset-scmi.c b/drivers/reset/reset-scmi.c
index 8d3a858e3b19..4335811e0cfa 100644
--- a/drivers/reset/reset-scmi.c
+++ b/drivers/reset/reset-scmi.c
@@ -2,7 +2,7 @@
/*
* ARM System Control and Management Interface (ARM SCMI) reset driver
*
- * Copyright (C) 2019 ARM Ltd.
+ * Copyright (C) 2019-2021 ARM Ltd.
*/
#include <linux/module.h>
@@ -11,18 +11,20 @@
#include <linux/reset-controller.h>
#include <linux/scmi_protocol.h>
+static const struct scmi_reset_proto_ops *reset_ops;
+
/**
* struct scmi_reset_data - reset controller information structure
* @rcdev: reset controller entity
- * @handle: ARM SCMI handle used for communication with system controller
+ * @ph: ARM SCMI protocol handle used for communication with system controller
*/
struct scmi_reset_data {
struct reset_controller_dev rcdev;
- const struct scmi_handle *handle;
+ const struct scmi_protocol_handle *ph;
};
#define to_scmi_reset_data(p) container_of((p), struct scmi_reset_data, rcdev)
-#define to_scmi_handle(p) (to_scmi_reset_data(p)->handle)
+#define to_scmi_handle(p) (to_scmi_reset_data(p)->ph)
/**
* scmi_reset_assert() - assert device reset
@@ -37,9 +39,9 @@ struct scmi_reset_data {
static int
scmi_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
{
- const struct scmi_handle *handle = to_scmi_handle(rcdev);
+ const struct scmi_protocol_handle *ph = to_scmi_handle(rcdev);
- return handle->reset_ops->assert(handle, id);
+ return reset_ops->assert(ph, id);
}
/**
@@ -55,9 +57,9 @@ scmi_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
static int
scmi_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
{
- const struct scmi_handle *handle = to_scmi_handle(rcdev);
+ const struct scmi_protocol_handle *ph = to_scmi_handle(rcdev);
- return handle->reset_ops->deassert(handle, id);
+ return reset_ops->deassert(ph, id);
}
/**
@@ -73,9 +75,9 @@ scmi_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
static int
scmi_reset_reset(struct reset_controller_dev *rcdev, unsigned long id)
{
- const struct scmi_handle *handle = to_scmi_handle(rcdev);
+ const struct scmi_protocol_handle *ph = to_scmi_handle(rcdev);
- return handle->reset_ops->reset(handle, id);
+ return reset_ops->reset(ph, id);
}
static const struct reset_control_ops scmi_reset_ops = {
@@ -90,10 +92,15 @@ static int scmi_reset_probe(struct scmi_device *sdev)
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 || !handle->reset_ops)
+ if (!handle)
return -ENODEV;
+ reset_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_RESET, &ph);
+ if (IS_ERR(reset_ops))
+ return PTR_ERR(reset_ops);
+
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -101,8 +108,8 @@ static int scmi_reset_probe(struct scmi_device *sdev)
data->rcdev.ops = &scmi_reset_ops;
data->rcdev.owner = THIS_MODULE;
data->rcdev.of_node = np;
- data->rcdev.nr_resets = handle->reset_ops->num_domains_get(handle);
- data->handle = handle;
+ data->rcdev.nr_resets = reset_ops->num_domains_get(ph);
+ data->ph = ph;
return devm_reset_controller_register(dev, &data->rcdev);
}