summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/reset/spacemit/Kconfig17
-rw-r--r--drivers/reset/spacemit/Makefile2
-rw-r--r--drivers/reset/spacemit/reset-spacemit-common.c77
-rw-r--r--drivers/reset/spacemit/reset-spacemit-common.h42
-rw-r--r--drivers/reset/spacemit/reset-spacemit-k1.c107
5 files changed, 144 insertions, 101 deletions
diff --git a/drivers/reset/spacemit/Kconfig b/drivers/reset/spacemit/Kconfig
index 552884e8b72a..56a4858b30e1 100644
--- a/drivers/reset/spacemit/Kconfig
+++ b/drivers/reset/spacemit/Kconfig
@@ -1,10 +1,20 @@
# SPDX-License-Identifier: GPL-2.0-only
-config RESET_SPACEMIT_K1
- tristate "SpacemiT K1 reset driver"
+menu "Reset support for SpacemiT platforms"
depends on ARCH_SPACEMIT || COMPILE_TEST
- depends on SPACEMIT_K1_CCU
+
+config RESET_SPACEMIT_COMMON
+ tristate
select AUXILIARY_BUS
+ help
+ Common reset controller infrastructure for SpacemiT SoCs.
+ This provides shared code and helper functions used by
+ reset drivers for various SpacemiT SoC families.
+
+config RESET_SPACEMIT_K1
+ tristate "Support for SpacemiT K1 SoC"
+ depends on SPACEMIT_K1_CCU
+ select RESET_SPACEMIT_COMMON
default SPACEMIT_K1_CCU
help
Support for reset controller in SpacemiT K1 SoC.
@@ -12,3 +22,4 @@ config RESET_SPACEMIT_K1
unit (CCU) driver to provide reset control functionality
for various peripherals and subsystems in the SoC.
+endmenu
diff --git a/drivers/reset/spacemit/Makefile b/drivers/reset/spacemit/Makefile
index 34e3350136bb..0b056e8661ec 100644
--- a/drivers/reset/spacemit/Makefile
+++ b/drivers/reset/spacemit/Makefile
@@ -1,2 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_RESET_SPACEMIT_COMMON) += reset-spacemit-common.o
+
obj-$(CONFIG_RESET_SPACEMIT_K1) += reset-spacemit-k1.o
diff --git a/drivers/reset/spacemit/reset-spacemit-common.c b/drivers/reset/spacemit/reset-spacemit-common.c
new file mode 100644
index 000000000000..0626633a5e7d
--- /dev/null
+++ b/drivers/reset/spacemit/reset-spacemit-common.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/* SpacemiT reset controller driver - common implementation */
+
+#include <linux/container_of.h>
+#include <linux/device.h>
+#include <linux/module.h>
+
+#include <soc/spacemit/ccu.h>
+
+#include "reset-spacemit-common.h"
+
+static int spacemit_reset_update(struct reset_controller_dev *rcdev,
+ unsigned long id, bool assert)
+{
+ struct ccu_reset_controller *controller;
+ const struct ccu_reset_data *data;
+ u32 mask;
+ u32 val;
+
+ controller = container_of(rcdev, struct ccu_reset_controller, rcdev);
+ data = &controller->data->reset_data[id];
+ mask = data->assert_mask | data->deassert_mask;
+ val = assert ? data->assert_mask : data->deassert_mask;
+
+ return regmap_update_bits(controller->regmap, data->offset, mask, val);
+}
+
+static int spacemit_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return spacemit_reset_update(rcdev, id, true);
+}
+
+static int spacemit_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return spacemit_reset_update(rcdev, id, false);
+}
+
+static const struct reset_control_ops spacemit_reset_control_ops = {
+ .assert = spacemit_reset_assert,
+ .deassert = spacemit_reset_deassert,
+};
+
+static int spacemit_reset_controller_register(struct device *dev,
+ struct ccu_reset_controller *controller)
+{
+ struct reset_controller_dev *rcdev = &controller->rcdev;
+
+ rcdev->ops = &spacemit_reset_control_ops;
+ rcdev->owner = dev->driver->owner;
+ rcdev->of_node = dev->of_node;
+ rcdev->nr_resets = controller->data->count;
+
+ return devm_reset_controller_register(dev, &controller->rcdev);
+}
+
+int spacemit_reset_probe(struct auxiliary_device *adev,
+ const struct auxiliary_device_id *id)
+{
+ struct spacemit_ccu_adev *rdev = to_spacemit_ccu_adev(adev);
+ struct ccu_reset_controller *controller;
+ struct device *dev = &adev->dev;
+
+ controller = devm_kzalloc(dev, sizeof(*controller), GFP_KERNEL);
+ if (!controller)
+ return -ENOMEM;
+ controller->data = (const struct ccu_reset_controller_data *)id->driver_data;
+ controller->regmap = rdev->regmap;
+
+ return spacemit_reset_controller_register(dev, controller);
+}
+EXPORT_SYMBOL_NS_GPL(spacemit_reset_probe, "RESET_SPACEMIT");
+
+MODULE_DESCRIPTION("SpacemiT reset controller driver - common code");
+MODULE_LICENSE("GPL");
diff --git a/drivers/reset/spacemit/reset-spacemit-common.h b/drivers/reset/spacemit/reset-spacemit-common.h
new file mode 100644
index 000000000000..ffaf2f86eb39
--- /dev/null
+++ b/drivers/reset/spacemit/reset-spacemit-common.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * SpacemiT reset controller driver - common definitions
+ */
+
+#ifndef _RESET_SPACEMIT_COMMON_H_
+#define _RESET_SPACEMIT_COMMON_H_
+
+#include <linux/auxiliary_bus.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+#include <linux/types.h>
+
+struct ccu_reset_data {
+ u32 offset;
+ u32 assert_mask;
+ u32 deassert_mask;
+};
+
+struct ccu_reset_controller_data {
+ const struct ccu_reset_data *reset_data; /* array */
+ size_t count;
+};
+
+struct ccu_reset_controller {
+ struct reset_controller_dev rcdev;
+ const struct ccu_reset_controller_data *data;
+ struct regmap *regmap;
+};
+
+#define RESET_DATA(_offset, _assert_mask, _deassert_mask) \
+ { \
+ .offset = (_offset), \
+ .assert_mask = (_assert_mask), \
+ .deassert_mask = (_deassert_mask), \
+ }
+
+/* Common probe function */
+int spacemit_reset_probe(struct auxiliary_device *adev,
+ const struct auxiliary_device_id *id);
+
+#endif /* _RESET_SPACEMIT_COMMON_H_ */
diff --git a/drivers/reset/spacemit/reset-spacemit-k1.c b/drivers/reset/spacemit/reset-spacemit-k1.c
index cc7fd1f8750d..8f3b5329ea5f 100644
--- a/drivers/reset/spacemit/reset-spacemit-k1.c
+++ b/drivers/reset/spacemit/reset-spacemit-k1.c
@@ -1,41 +1,13 @@
// SPDX-License-Identifier: GPL-2.0-only
-/* SpacemiT reset controller driver */
+/* SpacemiT K1 reset controller driver */
-#include <linux/auxiliary_bus.h>
-#include <linux/container_of.h>
-#include <linux/device.h>
#include <linux/module.h>
-#include <linux/regmap.h>
-#include <linux/reset-controller.h>
-#include <linux/types.h>
-#include <soc/spacemit/k1-syscon.h>
#include <dt-bindings/clock/spacemit,k1-syscon.h>
+#include <soc/spacemit/k1-syscon.h>
-struct ccu_reset_data {
- u32 offset;
- u32 assert_mask;
- u32 deassert_mask;
-};
-
-struct ccu_reset_controller_data {
- const struct ccu_reset_data *reset_data; /* array */
- size_t count;
-};
-
-struct ccu_reset_controller {
- struct reset_controller_dev rcdev;
- const struct ccu_reset_controller_data *data;
- struct regmap *regmap;
-};
-
-#define RESET_DATA(_offset, _assert_mask, _deassert_mask) \
- { \
- .offset = (_offset), \
- .assert_mask = (_assert_mask), \
- .deassert_mask = (_deassert_mask), \
- }
+#include "reset-spacemit-common.h"
static const struct ccu_reset_data k1_mpmu_resets[] = {
[RESET_WDT] = RESET_DATA(MPMU_WDTPCR, BIT(2), 0),
@@ -214,91 +186,30 @@ static const struct ccu_reset_controller_data k1_apbc2_reset_data = {
.count = ARRAY_SIZE(k1_apbc2_resets),
};
-static int spacemit_reset_update(struct reset_controller_dev *rcdev,
- unsigned long id, bool assert)
-{
- struct ccu_reset_controller *controller;
- const struct ccu_reset_data *data;
- u32 mask;
- u32 val;
-
- controller = container_of(rcdev, struct ccu_reset_controller, rcdev);
- data = &controller->data->reset_data[id];
- mask = data->assert_mask | data->deassert_mask;
- val = assert ? data->assert_mask : data->deassert_mask;
-
- return regmap_update_bits(controller->regmap, data->offset, mask, val);
-}
-
-static int spacemit_reset_assert(struct reset_controller_dev *rcdev,
- unsigned long id)
-{
- return spacemit_reset_update(rcdev, id, true);
-}
-
-static int spacemit_reset_deassert(struct reset_controller_dev *rcdev,
- unsigned long id)
-{
- return spacemit_reset_update(rcdev, id, false);
-}
-
-static const struct reset_control_ops spacemit_reset_control_ops = {
- .assert = spacemit_reset_assert,
- .deassert = spacemit_reset_deassert,
-};
-
-static int spacemit_reset_controller_register(struct device *dev,
- struct ccu_reset_controller *controller)
-{
- struct reset_controller_dev *rcdev = &controller->rcdev;
-
- rcdev->ops = &spacemit_reset_control_ops;
- rcdev->owner = THIS_MODULE;
- rcdev->of_node = dev->of_node;
- rcdev->nr_resets = controller->data->count;
-
- return devm_reset_controller_register(dev, &controller->rcdev);
-}
-
-static int spacemit_reset_probe(struct auxiliary_device *adev,
- const struct auxiliary_device_id *id)
-{
- struct spacemit_ccu_adev *rdev = to_spacemit_ccu_adev(adev);
- struct ccu_reset_controller *controller;
- struct device *dev = &adev->dev;
-
- controller = devm_kzalloc(dev, sizeof(*controller), GFP_KERNEL);
- if (!controller)
- return -ENOMEM;
- controller->data = (const struct ccu_reset_controller_data *)id->driver_data;
- controller->regmap = rdev->regmap;
-
- return spacemit_reset_controller_register(dev, controller);
-}
-
#define K1_AUX_DEV_ID(_unit) \
{ \
.name = "spacemit_ccu.k1-" #_unit "-reset", \
.driver_data = (kernel_ulong_t)&k1_ ## _unit ## _reset_data, \
}
-static const struct auxiliary_device_id spacemit_reset_ids[] = {
+static const struct auxiliary_device_id spacemit_k1_reset_ids[] = {
K1_AUX_DEV_ID(mpmu),
K1_AUX_DEV_ID(apbc),
K1_AUX_DEV_ID(apmu),
K1_AUX_DEV_ID(rcpu),
K1_AUX_DEV_ID(rcpu2),
K1_AUX_DEV_ID(apbc2),
- { },
+ { /* sentinel */ }
};
-MODULE_DEVICE_TABLE(auxiliary, spacemit_reset_ids);
+MODULE_DEVICE_TABLE(auxiliary, spacemit_k1_reset_ids);
static struct auxiliary_driver spacemit_k1_reset_driver = {
.probe = spacemit_reset_probe,
- .id_table = spacemit_reset_ids,
+ .id_table = spacemit_k1_reset_ids,
};
module_auxiliary_driver(spacemit_k1_reset_driver);
+MODULE_IMPORT_NS("RESET_SPACEMIT");
MODULE_AUTHOR("Alex Elder <elder@kernel.org>");
-MODULE_DESCRIPTION("SpacemiT reset controller driver");
+MODULE_DESCRIPTION("SpacemiT K1 reset controller driver");
MODULE_LICENSE("GPL");