[PATCH 2/4] hwspinlock: brcmstb hardware semaphore support

Kamal Dasu posted 4 patches 2 months, 3 weeks ago
There is a newer version of this series
[PATCH 2/4] hwspinlock: brcmstb hardware semaphore support
Posted by Kamal Dasu 2 months, 3 weeks ago
From: Kamal Dasu <kdasu@broadcom.com>

Added support for brmstb_hwspinlock driver that makes use of
the hwspinlock framework. Driver uses SUN_TOP_CTRL_SEMAPHORE_[1:15]
registers to implement the hardware semaphore. With this change
other brcmstb drivers can use hwspin_trylock() and hwspin_unlock()
apis and make use of this hwspinlock framework. Other driver dt nodes
just need to use a reference to the &hwspinlock and the lock id
they want to use.
e.g. hwlocks = <&hwspinlock0 0>;

Signed-off-by: Kamal Dasu <kamal.dasu@broadcom.com>
---
 drivers/hwspinlock/Kconfig              |  9 +++
 drivers/hwspinlock/Makefile             |  1 +
 drivers/hwspinlock/brcmstb_hwspinlock.c | 98 +++++++++++++++++++++++++
 3 files changed, 108 insertions(+)
 create mode 100644 drivers/hwspinlock/brcmstb_hwspinlock.c

diff --git a/drivers/hwspinlock/Kconfig b/drivers/hwspinlock/Kconfig
index 3874d15b0e9b..551afa8df2d0 100644
--- a/drivers/hwspinlock/Kconfig
+++ b/drivers/hwspinlock/Kconfig
@@ -63,4 +63,13 @@ config HSEM_U8500
 
 	  If unsure, say N.
 
+config HWSPINLOCK_BRCMSTB
+	tristate "Broadcom Setttop Hardware Semaphore functionality"
+	depends on ARCH_BRCMSTB || COMPILE_TEST
+	help
+	  Broadcom settop hwspinlock driver.
+	  Say y here to support the Broadcom Hardware Semaphore functionality, which
+	  provides a synchronisation mechanism on the SoC.
+
+	  If unsure, say N.
 endif # HWSPINLOCK
diff --git a/drivers/hwspinlock/Makefile b/drivers/hwspinlock/Makefile
index a0f16c9aaa82..4f5c05403209 100644
--- a/drivers/hwspinlock/Makefile
+++ b/drivers/hwspinlock/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_HWSPINLOCK_SPRD)		+= sprd_hwspinlock.o
 obj-$(CONFIG_HWSPINLOCK_STM32)		+= stm32_hwspinlock.o
 obj-$(CONFIG_HWSPINLOCK_SUN6I)		+= sun6i_hwspinlock.o
 obj-$(CONFIG_HSEM_U8500)		+= u8500_hsem.o
+obj-$(CONFIG_HWSPINLOCK_BRCMSTB)	+= brcmstb_hwspinlock.o
diff --git a/drivers/hwspinlock/brcmstb_hwspinlock.c b/drivers/hwspinlock/brcmstb_hwspinlock.c
new file mode 100644
index 000000000000..c27d53e06edf
--- /dev/null
+++ b/drivers/hwspinlock/brcmstb_hwspinlock.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * brcmstb HWSEM driver
+ *
+ * Copyright (C) 2025 Broadcom
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/hwspinlock.h>
+#include <linux/platform_device.h>
+#include <linux/mod_devicetable.h>
+#include "hwspinlock_internal.h"
+
+#define BRCMSTB_MAX_SEMAPHORES		16
+#define RESET_SEMAPHORE			0
+
+#define HWSPINLOCK_VAL			'L'
+
+static int brcmstb_hwspinlock_trylock(struct hwspinlock *lock)
+{
+	void __iomem *lock_addr = lock->priv;
+
+	writel(HWSPINLOCK_VAL, lock_addr);
+
+	return (readl(lock_addr) == HWSPINLOCK_VAL);
+}
+
+static void brcmstb_hwspinlock_unlock(struct hwspinlock *lock)
+{
+	void __iomem *lock_addr = lock->priv;
+
+	/* release the lock by writing 0 to it */
+	writel(RESET_SEMAPHORE, lock_addr);
+}
+
+static void brcmstb_hwspinlock_relax(struct hwspinlock *lock)
+{
+	ndelay(50);
+}
+
+static const struct hwspinlock_ops brcmstb_hwspinlock_ops = {
+	.trylock	= brcmstb_hwspinlock_trylock,
+	.unlock		= brcmstb_hwspinlock_unlock,
+	.relax		= brcmstb_hwspinlock_relax,
+};
+
+static int brcmstb_hwspinlock_probe(struct platform_device *pdev)
+{
+	struct hwspinlock_device *bank;
+	struct hwspinlock *hwlock;
+	void __iomem *io_base;
+	int i, num_locks = BRCMSTB_MAX_SEMAPHORES;
+
+	io_base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(io_base)) {
+		dev_err(&pdev->dev, "semaphore iobase mapping error\n");
+		return PTR_ERR(io_base);
+	}
+
+	bank = devm_kzalloc(&pdev->dev, struct_size(bank, lock, num_locks),
+			    GFP_KERNEL);
+	if (!bank)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, bank);
+
+	for (i = 0, hwlock = &bank->lock[0]; i < num_locks; i++, hwlock++)
+		hwlock->priv = io_base + sizeof(u32) * i;
+
+	return devm_hwspin_lock_register(&pdev->dev, bank,
+					 &brcmstb_hwspinlock_ops,
+					 0, num_locks);
+}
+
+static const struct of_device_id brcmstb_hwspinlock_ids[] = {
+	{ .compatible = "brcm,brcmstb-hwspinlock", },
+	{ /* end */ },
+};
+MODULE_DEVICE_TABLE(of, brcmstb_hwspinlock_ids);
+
+static struct platform_driver brcmstb_hwspinlock_driver = {
+	.probe		= brcmstb_hwspinlock_probe,
+	.driver		= {
+		.name	= "brcmstb_hwspinlock",
+		.of_match_table = brcmstb_hwspinlock_ids,
+	},
+};
+
+module_platform_driver(brcmstb_hwspinlock_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Hardware Spinlock driver for brcmstb");
+MODULE_AUTHOR("Kamal Dasu <kdasu@broadcom.com>");
-- 
2.34.1
Re: [PATCH 2/4] hwspinlock: brcmstb hardware semaphore support
Posted by kernel test robot 2 months, 3 weeks ago
Hi Kamal,

kernel test robot noticed the following build warnings:

[auto build test WARNING on robh/for-next]
[also build test WARNING on linus/master v6.16-rc5 next-20250711]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Kamal-Dasu/dt-bindings-brcmstb-hwspinlock-support-for-hwspinlock/20250712-034624
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
patch link:    https://lore.kernel.org/r/20250711154221.928164-4-kamal.dasu%40broadcom.com
patch subject: [PATCH 2/4] hwspinlock: brcmstb hardware semaphore support
config: arc-randconfig-r111-20250713 (https://download.01.org/0day-ci/archive/20250713/202507131422.6eIuyxUJ-lkp@intel.com/config)
compiler: arc-linux-gcc (GCC) 12.4.0
reproduce: (https://download.01.org/0day-ci/archive/20250713/202507131422.6eIuyxUJ-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202507131422.6eIuyxUJ-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/hwspinlock/brcmstb_hwspinlock.c:26:39: sparse: sparse: incorrect type in initializer (different address spaces) @@     expected void [noderef] __iomem *lock_addr @@     got void *priv @@
   drivers/hwspinlock/brcmstb_hwspinlock.c:26:39: sparse:     expected void [noderef] __iomem *lock_addr
   drivers/hwspinlock/brcmstb_hwspinlock.c:26:39: sparse:     got void *priv
   drivers/hwspinlock/brcmstb_hwspinlock.c:35:39: sparse: sparse: incorrect type in initializer (different address spaces) @@     expected void [noderef] __iomem *lock_addr @@     got void *priv @@
   drivers/hwspinlock/brcmstb_hwspinlock.c:35:39: sparse:     expected void [noderef] __iomem *lock_addr
   drivers/hwspinlock/brcmstb_hwspinlock.c:35:39: sparse:     got void *priv
>> drivers/hwspinlock/brcmstb_hwspinlock.c:73:30: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected void *priv @@     got void [noderef] __iomem * @@
   drivers/hwspinlock/brcmstb_hwspinlock.c:73:30: sparse:     expected void *priv
   drivers/hwspinlock/brcmstb_hwspinlock.c:73:30: sparse:     got void [noderef] __iomem *

vim +26 drivers/hwspinlock/brcmstb_hwspinlock.c

    23	
    24	static int brcmstb_hwspinlock_trylock(struct hwspinlock *lock)
    25	{
  > 26		void __iomem *lock_addr = lock->priv;
    27	
    28		writel(HWSPINLOCK_VAL, lock_addr);
    29	
    30		return (readl(lock_addr) == HWSPINLOCK_VAL);
    31	}
    32	
    33	static void brcmstb_hwspinlock_unlock(struct hwspinlock *lock)
    34	{
    35		void __iomem *lock_addr = lock->priv;
    36	
    37		/* release the lock by writing 0 to it */
    38		writel(RESET_SEMAPHORE, lock_addr);
    39	}
    40	
    41	static void brcmstb_hwspinlock_relax(struct hwspinlock *lock)
    42	{
    43		ndelay(50);
    44	}
    45	
    46	static const struct hwspinlock_ops brcmstb_hwspinlock_ops = {
    47		.trylock	= brcmstb_hwspinlock_trylock,
    48		.unlock		= brcmstb_hwspinlock_unlock,
    49		.relax		= brcmstb_hwspinlock_relax,
    50	};
    51	
    52	static int brcmstb_hwspinlock_probe(struct platform_device *pdev)
    53	{
    54		struct hwspinlock_device *bank;
    55		struct hwspinlock *hwlock;
    56		void __iomem *io_base;
    57		int i, num_locks = BRCMSTB_MAX_SEMAPHORES;
    58	
    59		io_base = devm_platform_ioremap_resource(pdev, 0);
    60		if (IS_ERR(io_base)) {
    61			dev_err(&pdev->dev, "semaphore iobase mapping error\n");
    62			return PTR_ERR(io_base);
    63		}
    64	
    65		bank = devm_kzalloc(&pdev->dev, struct_size(bank, lock, num_locks),
    66				    GFP_KERNEL);
    67		if (!bank)
    68			return -ENOMEM;
    69	
    70		platform_set_drvdata(pdev, bank);
    71	
    72		for (i = 0, hwlock = &bank->lock[0]; i < num_locks; i++, hwlock++)
  > 73			hwlock->priv = io_base + sizeof(u32) * i;
    74	
    75		return devm_hwspin_lock_register(&pdev->dev, bank,
    76						 &brcmstb_hwspinlock_ops,
    77						 0, num_locks);
    78	}
    79	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki