Messages in this thread Patch in this message | | | From | Baolin Wang <> | Subject | [RFC PATCH 3/3] soc: sprd: Add Spreadtrum special bits updating support | Date | Thu, 9 Apr 2020 16:57:59 +0800 |
| |
The spreadtrum platform uses a special set/clear method to update registers' bits, which can remove the race of updating the global registers between the multiple subsystems.
Signed-off-by: Baolin Wang <baolin.wang7@gmail.com> --- drivers/soc/Kconfig | 1 + drivers/soc/Makefile | 1 + drivers/soc/sprd/Kconfig | 16 +++++++++++++ drivers/soc/sprd/Makefile | 2 ++ drivers/soc/sprd/sprd_syscon.c | 51 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 71 insertions(+) create mode 100644 drivers/soc/sprd/Kconfig create mode 100644 drivers/soc/sprd/Makefile create mode 100644 drivers/soc/sprd/sprd_syscon.c
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig index 1778f8c..a19cead 100644 --- a/drivers/soc/Kconfig +++ b/drivers/soc/Kconfig @@ -22,5 +22,6 @@ source "drivers/soc/ux500/Kconfig" source "drivers/soc/versatile/Kconfig" source "drivers/soc/xilinx/Kconfig" source "drivers/soc/zte/Kconfig" +source "drivers/soc/sprd/Kconfig" endmenu diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile index a39f17c..e3f6b1c 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile @@ -28,3 +28,4 @@ obj-$(CONFIG_ARCH_U8500) += ux500/ obj-$(CONFIG_PLAT_VERSATILE) += versatile/ obj-y += xilinx/ obj-$(CONFIG_ARCH_ZX) += zte/ +obj-$(CONFIG_ARCH_SPRD) += sprd/ diff --git a/drivers/soc/sprd/Kconfig b/drivers/soc/sprd/Kconfig new file mode 100644 index 0000000..38d1f59 --- /dev/null +++ b/drivers/soc/sprd/Kconfig @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# SPRD SoC drivers +# + +menu "Spreadtrum SoC drivers" + depends on ARCH_SPRD || COMPILE_TEST + +config SPRD_SYSCON + tristate "Spreadtrum syscon support" + depends on ARCH_SPRD || COMPILE_TEST + help + Say yes here to add support for the Spreadtrum syscon driver, + which is used to implement the atomic method of bits updating. + +endmenu diff --git a/drivers/soc/sprd/Makefile b/drivers/soc/sprd/Makefile new file mode 100644 index 0000000..4d77155 --- /dev/null +++ b/drivers/soc/sprd/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-$(CONFIG_SPRD_SYSCON) += sprd_syscon.o diff --git a/drivers/soc/sprd/sprd_syscon.c b/drivers/soc/sprd/sprd_syscon.c new file mode 100644 index 0000000..00acf88 --- /dev/null +++ b/drivers/soc/sprd/sprd_syscon.c @@ -0,0 +1,51 @@ +//SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Spreadtrum Communications Inc. + */ +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mfd/syscon.h> + +#define SPRD_REG_SET_OFFSET 0x1000 +#define SPRD_REG_CLR_OFFSET 0x2000 + +/* + * The Spreadtrum platform defines a special set/clear method to update + * registers' bits, which means it can write values to the register's SET + * address (offset is 0x1000) to set bits, and write values to the register's + * CLEAR address (offset is 0x2000) to clear bits. + * + * This set/clear method can help to remove the race of accessing the global + * registers between the multiple subsystems instead of using hardware + * spinlocks. + */ +static int sprd_syscon_update_bits(void *context, unsigned int reg, + unsigned int mask, unsigned int val) +{ + void __iomem *base = context; + unsigned int set, clr; + + set = val & mask; + clr = ~set & mask; + + if (set) + writel(set, base + reg + SPRD_REG_SET_OFFSET); + + if (clr) + writel(clr, base + reg + SPRD_REG_CLR_OFFSET); + + return 0; +} + +static int sprd_syscon_init(void) +{ + syscon_register_reg_update_bits(sprd_syscon_update_bits); + + return 0; +} +core_initcall_sync(sprd_syscon_init); + +MODULE_DESCRIPTION("Spreadtrum syscon support"); +MODULE_AUTHOR("Baolin Wang <baolin.wang@unisoc.com>"); +MODULE_LICENSE("GPL v2"); -- 1.9.1
| |