diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/reset/spacemit/Kconfig | 17 | ||||
| -rw-r--r-- | drivers/reset/spacemit/Makefile | 2 | ||||
| -rw-r--r-- | drivers/reset/spacemit/reset-spacemit-common.c | 77 | ||||
| -rw-r--r-- | drivers/reset/spacemit/reset-spacemit-common.h | 42 | ||||
| -rw-r--r-- | drivers/reset/spacemit/reset-spacemit-k1.c | 107 |
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"); |
