* [U-Boot] [PATCH 0/4] Add Hardware Spinlock class
@ 2018-11-13 8:51 Benjamin Gaignard
2018-11-13 8:51 ` [U-Boot] [PATCH 1/4] dm: " Benjamin Gaignard
` (3 more replies)
0 siblings, 4 replies; 8+ messages in thread
From: Benjamin Gaignard @ 2018-11-13 8:51 UTC (permalink / raw)
To: u-boot
This series add a news class to support hardware spinlock.
Hardware spinlock could be used to protect critical sections of code
between multi-processors.
The proposed API remain simple with only 3 functions to be called client:
- hwspinlock_get_by_index: get a hardware spinlock by integer index from
device-tree node
- hwspinlock_lock_timeout: lock the hardware spinlock
- hwspinlock_unlock: unlock the hardware spinlock
Driver API offert 4 operations:
- of_xlate: translate a client's device-tree (OF) hardware specifier
- lock: lock the hardware spinlock
- unlock: unlock the hardware spinlock
- relax: wait time between two calls to lock operations
Benjamin Gaignard (4):
dm: Add Hardware Spinlock class
clk: stm32: add hardware spinlock clock
hwspinlock: add stm32 hardware spinlock support
pinctrl: stm32: make pinctrl use hwspinlock
arch/arm/dts/stm32mp157c-ed1.dts | 8 ++
arch/arm/dts/stm32mp157c.dtsi | 9 ++
arch/sandbox/dts/test.dts | 4 +
arch/sandbox/include/asm/state.h | 1 +
configs/sandbox_defconfig | 2 +
configs/stm32mp15_basic_defconfig | 2 +
drivers/Kconfig | 2 +
drivers/Makefile | 1 +
drivers/clk/clk_stm32mp1.c | 3 +
drivers/hwspinlock/Kconfig | 22 +++++
drivers/hwspinlock/Makefile | 7 ++
drivers/hwspinlock/hwspinlock-uclass.c | 145 ++++++++++++++++++++++++++++++++
drivers/hwspinlock/sandbox_hwspinlock.c | 56 ++++++++++++
drivers/hwspinlock/stm32_hwspinlock.c | 90 ++++++++++++++++++++
drivers/pinctrl/pinctrl_stm32.c | 22 +++++
include/dm/uclass-id.h | 1 +
include/hwspinlock.h | 140 ++++++++++++++++++++++++++++++
test/dm/Makefile | 1 +
test/dm/hwspinlock.c | 40 +++++++++
19 files changed, 556 insertions(+)
create mode 100644 drivers/hwspinlock/Kconfig
create mode 100644 drivers/hwspinlock/Makefile
create mode 100644 drivers/hwspinlock/hwspinlock-uclass.c
create mode 100644 drivers/hwspinlock/sandbox_hwspinlock.c
create mode 100644 drivers/hwspinlock/stm32_hwspinlock.c
create mode 100644 include/hwspinlock.h
create mode 100644 test/dm/hwspinlock.c
--
2.15.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [U-Boot] [PATCH 1/4] dm: Add Hardware Spinlock class
2018-11-13 8:51 [U-Boot] [PATCH 0/4] Add Hardware Spinlock class Benjamin Gaignard
@ 2018-11-13 8:51 ` Benjamin Gaignard
2018-11-13 19:53 ` Simon Glass
2018-11-13 8:51 ` [U-Boot] [PATCH 2/4] clk: stm32: add hardware spinlock clock Benjamin Gaignard
` (2 subsequent siblings)
3 siblings, 1 reply; 8+ messages in thread
From: Benjamin Gaignard @ 2018-11-13 8:51 UTC (permalink / raw)
To: u-boot
From: Benjamin Gaignard <benjamin.gaignard@linaro.org>
This is uclass for Hardware Spinlocks.
It implements two mandatory operations: lock and unlock
and one optional relax operation.
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
---
arch/sandbox/dts/test.dts | 4 +
arch/sandbox/include/asm/state.h | 1 +
configs/sandbox_defconfig | 2 +
drivers/Kconfig | 2 +
drivers/Makefile | 1 +
drivers/hwspinlock/Kconfig | 16 ++++
drivers/hwspinlock/Makefile | 6 ++
drivers/hwspinlock/hwspinlock-uclass.c | 145 ++++++++++++++++++++++++++++++++
drivers/hwspinlock/sandbox_hwspinlock.c | 56 ++++++++++++
include/dm/uclass-id.h | 1 +
include/hwspinlock.h | 140 ++++++++++++++++++++++++++++++
test/dm/Makefile | 1 +
test/dm/hwspinlock.c | 40 +++++++++
13 files changed, 415 insertions(+)
create mode 100644 drivers/hwspinlock/Kconfig
create mode 100644 drivers/hwspinlock/Makefile
create mode 100644 drivers/hwspinlock/hwspinlock-uclass.c
create mode 100644 drivers/hwspinlock/sandbox_hwspinlock.c
create mode 100644 include/hwspinlock.h
create mode 100644 test/dm/hwspinlock.c
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 57e0dd7663..50cd2f89e0 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -712,6 +712,10 @@
sandbox_tee {
compatible = "sandbox,tee";
};
+
+ hwspinlock at 0 {
+ compatible = "sandbox,hwspinlock";
+ };
};
#include "sandbox_pmic.dtsi"
diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h
index dcb6d5f568..a5d7c6aaf3 100644
--- a/arch/sandbox/include/asm/state.h
+++ b/arch/sandbox/include/asm/state.h
@@ -99,6 +99,7 @@ struct sandbox_state {
ulong next_tag; /* Next address tag to allocate */
struct list_head mapmem_head; /* struct sandbox_mapmem_entry */
+ bool hwspinlock; /* Hardware Spinlock status */
};
/* Minimum space we guarantee in the state FDT when calling read/write*/
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 2ce336fc81..36b67be2df 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -97,6 +97,8 @@ CONFIG_BOARD=y
CONFIG_BOARD_SANDBOX=y
CONFIG_PM8916_GPIO=y
CONFIG_SANDBOX_GPIO=y
+CONFIG_DM_HWSPINLOCK=y
+CONFIG_HWSPINLOCK_SANDBOX=y
CONFIG_DM_I2C_COMPAT=y
CONFIG_I2C_CROS_EC_TUNNEL=y
CONFIG_I2C_CROS_EC_LDO=y
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 927a2b87f6..7e6ca7cd3e 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -40,6 +40,8 @@ source "drivers/fpga/Kconfig"
source "drivers/gpio/Kconfig"
+source "drivers/hwspinlock/Kconfig"
+
source "drivers/i2c/Kconfig"
source "drivers/input/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index fb38b67541..0ef56fb416 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -111,4 +111,5 @@ obj-$(CONFIG_W1) += w1/
obj-$(CONFIG_W1_EEPROM) += w1-eeprom/
obj-$(CONFIG_MACH_PIC32) += ddr/microchip/
+obj-$(CONFIG_DM_HWSPINLOCK) += hwspinlock/
endif
diff --git a/drivers/hwspinlock/Kconfig b/drivers/hwspinlock/Kconfig
new file mode 100644
index 0000000000..de367fd2a9
--- /dev/null
+++ b/drivers/hwspinlock/Kconfig
@@ -0,0 +1,16 @@
+menu "Hardware Spinlock Support"
+
+config DM_HWSPINLOCK
+ bool "Enable U-Boot hardware spinlock support"
+ help
+ This option enables U-Boot hardware spinlock support
+
+config HWSPINLOCK_SANDBOX
+ bool "Enable Hardware Spinlock support for Sandbox"
+ depends on SANDBOX && DM_HWSPINLOCK
+ help
+ Enable hardware spinlock support in Sandbox. This is a dummy device that
+ can be probed and support all the methods of HWSPINLOCK, but does not
+ really do anything.
+
+endmenu
diff --git a/drivers/hwspinlock/Makefile b/drivers/hwspinlock/Makefile
new file mode 100644
index 0000000000..2704d6814f
--- /dev/null
+++ b/drivers/hwspinlock/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+#
+# Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+
+obj-$(CONFIG_DM_HWSPINLOCK) += hwspinlock-uclass.o
+obj-$(CONFIG_HWSPINLOCK_SANDBOX) += sandbox_hwspinlock.o
diff --git a/drivers/hwspinlock/hwspinlock-uclass.c b/drivers/hwspinlock/hwspinlock-uclass.c
new file mode 100644
index 0000000000..1fed24228c
--- /dev/null
+++ b/drivers/hwspinlock/hwspinlock-uclass.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <hwspinlock.h>
+#include <dm/device-internal.h>
+
+static inline const struct hwspinlock_ops *
+hwspinlock_dev_ops(struct udevice *dev)
+{
+ return (const struct hwspinlock_ops *)dev->driver->ops;
+}
+
+static int hwspinlock_of_xlate_default(struct hwspinlock *hws,
+ struct ofnode_phandle_args *args)
+{
+ if (args->args_count > 1) {
+ debug("Invaild args_count: %d\n", args->args_count);
+ return -EINVAL;
+ }
+
+ if (args->args_count)
+ hws->id = args->args[0];
+ else
+ hws->id = 0;
+
+ return 0;
+}
+
+int hwspinlock_get_by_index(struct udevice *dev, int index,
+ struct hwspinlock *hws)
+{
+ int ret;
+ struct ofnode_phandle_args args;
+ struct udevice *dev_hws;
+ const struct hwspinlock_ops *ops;
+
+ assert(hws);
+ hws->dev = NULL;
+
+ ret = dev_read_phandle_with_args(dev, "hwlocks", "#hwlock-cells", 1,
+ index, &args);
+ if (ret) {
+ dev_dbg(dev, "%s: dev_read_phandle_with_args: err=%d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ ret = uclass_get_device_by_ofnode(UCLASS_HWSPINLOCK,
+ args.node, &dev_hws);
+ if (ret) {
+ dev_dbg(dev,
+ "%s: uclass_get_device_by_of_offset failed: err=%d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ hws->dev = dev_hws;
+
+ ops = hwspinlock_dev_ops(dev_hws);
+
+ if (ops->of_xlate)
+ ret = ops->of_xlate(hws, &args);
+ else
+ ret = hwspinlock_of_xlate_default(hws, &args);
+ if (ret)
+ dev_dbg(dev, "of_xlate() failed: %d\n", ret);
+
+ return ret;
+}
+
+int hwspinlock_lock_timeout(struct hwspinlock *hws, unsigned int timeout)
+{
+ const struct hwspinlock_ops *ops;
+ ulong start;
+ int ret;
+
+ assert(hws);
+
+ if (!hws->dev)
+ return -EINVAL;
+
+ ops = hwspinlock_dev_ops(hws->dev);
+
+ if (!ops || !ops->lock)
+ return -EINVAL;
+
+ for (start = get_timer(0); get_timer(start) < timeout;) {
+ ret = ops->lock(hws->dev, hws->id);
+ if (!ret)
+ return ret;
+
+ if (ops->relax)
+ ops->relax(hws->dev);
+ }
+
+ return -ETIME;
+}
+
+int hwspinlock_unlock(struct hwspinlock *hws)
+{
+ const struct hwspinlock_ops *ops;
+
+ assert(hws);
+
+ if (!hws->dev)
+ return -EINVAL;
+
+ ops = hwspinlock_dev_ops(hws->dev);
+
+ if (!ops || !ops->unlock)
+ return -EINVAL;
+
+ return ops->unlock(hws->dev, hws->id);
+}
+
+static int hwspinlock_post_bind(struct udevice *dev)
+{
+#if defined(CONFIG_NEEDS_MANUAL_RELOC)
+ struct hwspinlock_ops *ops = device_get_ops(dev);
+ static int reloc_done;
+
+ if (!reloc_done) {
+ if (ops->lock)
+ ops->lock += gd->reloc_off;
+ if (ops->unlock)
+ ops->unlock += gd->reloc_off;
+ if (ops->relax)
+ ops->relax += gd->reloc_off;
+
+ reloc_done++;
+ }
+#endif
+ return 0;
+}
+
+UCLASS_DRIVER(hwspinlock) = {
+ .id = UCLASS_HWSPINLOCK,
+ .name = "hwspinlock",
+ .post_bind = hwspinlock_post_bind,
+};
diff --git a/drivers/hwspinlock/sandbox_hwspinlock.c b/drivers/hwspinlock/sandbox_hwspinlock.c
new file mode 100644
index 0000000000..be920f5f99
--- /dev/null
+++ b/drivers/hwspinlock/sandbox_hwspinlock.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <hwspinlock.h>
+#include <asm/state.h>
+
+static int sandbox_lock(struct udevice *dev, int index)
+{
+ struct sandbox_state *state = state_get_current();
+
+ if (index != 0)
+ return -1;
+
+ if (state->hwspinlock)
+ return -1;
+
+ state->hwspinlock = true;
+
+ return 0;
+}
+
+static int sandbox_unlock(struct udevice *dev, int index)
+{
+ struct sandbox_state *state = state_get_current();
+
+ if (index != 0)
+ return -1;
+
+ if (!state->hwspinlock)
+ return -1;
+
+ state->hwspinlock = false;
+
+ return 0;
+}
+
+static const struct hwspinlock_ops sandbox_hwspinlock_ops = {
+ .lock = sandbox_lock,
+ .unlock = sandbox_unlock,
+};
+
+static const struct udevice_id sandbox_hwspinlock_ids[] = {
+ { .compatible = "sandbox,hwspinlock" },
+ {}
+};
+
+U_BOOT_DRIVER(hwspinlock_sandbox) = {
+ .name = "hwspinlock_sandbox",
+ .id = UCLASS_HWSPINLOCK,
+ .of_match = sandbox_hwspinlock_ids,
+ .ops = &sandbox_hwspinlock_ops,
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 269a2c6e72..6193017432 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -40,6 +40,7 @@ enum uclass_id {
UCLASS_ETH, /* Ethernet device */
UCLASS_FS_FIRMWARE_LOADER, /* Generic loader */
UCLASS_GPIO, /* Bank of general-purpose I/O pins */
+ UCLASS_HWSPINLOCK, /* Hardware semaphores */
UCLASS_FIRMWARE, /* Firmware */
UCLASS_I2C, /* I2C bus */
UCLASS_I2C_EEPROM, /* I2C EEPROM device */
diff --git a/include/hwspinlock.h b/include/hwspinlock.h
new file mode 100644
index 0000000000..4671c8fce5
--- /dev/null
+++ b/include/hwspinlock.h
@@ -0,0 +1,140 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ */
+
+#ifndef _HWSPINLOCK_H_
+#define _HWSPINLOCK_H_
+
+/**
+ * Implement a hwspinlock uclass.
+ * Hardware spinlocks are used to perform hardware protection of
+ * critical sections and synchronisation between multiprocessors.
+ */
+
+struct udevice;
+
+/**
+ * struct hwspinlock - A handle to (allowing control of) a single hardware
+ * spinlock.
+ *
+ * @dev: The device which implements the hardware spinlock.
+ * @id: The hardware spinlock ID within the provider.
+ */
+struct hwspinlock {
+ struct udevice *dev;
+ unsigned long id;
+};
+
+#if CONFIG_IS_ENABLED(DM_HWSPINLOCK)
+
+/**
+ * hwspinlock_get_by_index - Get a hardware spinlock by integer index
+ *
+ * This looks up and request a hardware spinlock. The index is relative to the
+ * client device; each device is assumed to have n hardware spinlock associated
+ * with it somehow, and this function finds and requests one of them.
+ *
+ * @dev: The client device.
+ * @index: The index of the hardware spinlock to request, within the
+ * client's list of hardware spinlock.
+ * @hws: A pointer to a hardware spinlock struct to initialize.
+ * @return 0 if OK, or a negative error code.
+ */
+int hwspinlock_get_by_index(struct udevice *dev,
+ int index, struct hwspinlock *hws);
+
+/**
+ * Lock the hardware spinlock
+ *
+ * @hws: A hardware spinlock struct that previously requested by
+ * hwspinlock_get_by_index
+ * @timeout: Timeout value in msecs
+ * @return: 0 if OK, -ETIME if timeout, -ve on other errors
+ */
+int hwspinlock_lock_timeout(struct hwspinlock *hws, unsigned int timeout);
+
+/**
+ * Unlock the hardware spinlock
+ *
+ * @hws: A hardware spinlock struct that previously requested by
+ * hwspinlock_get_by_index
+ * @return: 0 if OK, -ve on error
+ */
+int hwspinlock_unlock(struct hwspinlock *hws);
+
+#else
+
+static inline int hwspinlock_get_by_index(struct udevice *dev,
+ int index,
+ struct hwspinlock *hws)
+{
+ return -ENOSYS;
+}
+
+static inline int hwspinlock_lock_timeout(struct hwspinlock *hws,
+ int timeout)
+{
+ return -ENOSYS;
+}
+
+static inline int hwspinlock_unlock(struct hwspinlock *hws)
+{
+ return -ENOSYS;
+}
+
+#endif /* CONFIG_DM_HWSPINLOCK */
+
+struct ofnode_phandle_args;
+
+/**
+ * struct hwspinlock_ops - Driver model hwspinlock operations
+ *
+ * The uclass interface is implemented by all hwspinlock devices which use
+ * driver model.
+ */
+struct hwspinlock_ops {
+ /**
+ * of_xlate - Translate a client's device-tree (OF) hardware specifier.
+ *
+ * The hardware core calls this function as the first step in
+ * implementing a client's hwspinlock_get_by_*() call.
+ *
+ * @hws: The hardware spinlock struct to hold the translation
+ * result.
+ * @args: The hardware spinlock specifier values from device tree.
+ * @return 0 if OK, or a negative error code.
+ */
+ int (*of_xlate)(struct hwspinlock *hws,
+ struct ofnode_phandle_args *args);
+
+ /**
+ * Lock the hardware spinlock
+ *
+ * @dev: hwspinlock Device
+ * @index: index of the lock to be used
+ * @return 0 if OK, -ve on error
+ */
+ int (*lock)(struct udevice *dev, int index);
+
+ /**
+ * Unlock the hardware spinlock
+ *
+ * @dev: hwspinlock Device
+ * @index: index of the lock to be unlocked
+ * @return 0 if OK, -ve on error
+ */
+ int (*unlock)(struct udevice *dev, int index);
+
+ /**
+ * Relax - optional
+ * Platform-specific relax method, called by hwspinlock core
+ * while spinning on a lock, between two successive call to
+ * lock
+ *
+ * @dev: hwspinlock Device
+ */
+ void (*relax)(struct udevice *dev);
+};
+
+#endif /* _HWSPINLOCK_H_ */
diff --git a/test/dm/Makefile b/test/dm/Makefile
index b490cf2862..9b3b0bf202 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_CLK) += clk.o
obj-$(CONFIG_DM_ETH) += eth.o
obj-$(CONFIG_FIRMWARE) += firmware.o
obj-$(CONFIG_DM_GPIO) += gpio.o
+obj-$(CONFIG_DM_HWSPINLOCK) += hwspinlock.o
obj-$(CONFIG_DM_I2C) += i2c.o
obj-$(CONFIG_LED) += led.o
obj-$(CONFIG_DM_MAILBOX) += mailbox.o
diff --git a/test/dm/hwspinlock.c b/test/dm/hwspinlock.c
new file mode 100644
index 0000000000..09ec38b4f3
--- /dev/null
+++ b/test/dm/hwspinlock.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <hwspinlock.h>
+#include <asm/state.h>
+#include <asm/test.h>
+#include <dm/test.h>
+#include <test/ut.h>
+
+/* Test that hwspinlock driver functions are called */
+static int dm_test_hwspinlock_base(struct unit_test_state *uts)
+{
+ struct sandbox_state *state = state_get_current();
+ struct hwspinlock hws;
+
+ ut_assertok(uclass_get_device(UCLASS_HWSPINLOCK, 0, &hws.dev));
+ ut_assertnonnull(hws.dev);
+ ut_asserteq(false, state->hwspinlock);
+
+ hws.id = 0;
+ ut_assertok(hwspinlock_lock_timeout(&hws, 1));
+ ut_asserteq(true, state->hwspinlock);
+
+ ut_assertok(hwspinlock_unlock(&hws));
+ ut_asserteq(false, state->hwspinlock);
+
+ ut_assertok(hwspinlock_lock_timeout(&hws, 1));
+ ut_assertok(!hwspinlock_lock_timeout(&hws, 1));
+
+ ut_assertok(hwspinlock_unlock(&hws));
+ ut_assertok(!hwspinlock_unlock(&hws));
+
+ return 0;
+}
+
+DM_TEST(dm_test_hwspinlock_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
--
2.15.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [U-Boot] [PATCH 2/4] clk: stm32: add hardware spinlock clock
2018-11-13 8:51 [U-Boot] [PATCH 0/4] Add Hardware Spinlock class Benjamin Gaignard
2018-11-13 8:51 ` [U-Boot] [PATCH 1/4] dm: " Benjamin Gaignard
@ 2018-11-13 8:51 ` Benjamin Gaignard
2018-11-13 8:51 ` [U-Boot] [PATCH 3/4] hwspinlock: add stm32 hardware spinlock support Benjamin Gaignard
2018-11-13 8:51 ` [U-Boot] [PATCH 4/4] pinctrl: stm32: make pinctrl use hwspinlock Benjamin Gaignard
3 siblings, 0 replies; 8+ messages in thread
From: Benjamin Gaignard @ 2018-11-13 8:51 UTC (permalink / raw)
To: u-boot
From: Benjamin Gaignard <benjamin.gaignard@linaro.org>
Add hardware spinlock in the list of the clocks.
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
---
drivers/clk/clk_stm32mp1.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/clk/clk_stm32mp1.c b/drivers/clk/clk_stm32mp1.c
index 6a8c7b754f..b7c5d34fe0 100644
--- a/drivers/clk/clk_stm32mp1.c
+++ b/drivers/clk/clk_stm32mp1.c
@@ -104,6 +104,7 @@
#define RCC_MP_APB2ENSETR 0XA08
#define RCC_MP_APB3ENSETR 0xA10
#define RCC_MP_AHB2ENSETR 0xA18
+#define RCC_MP_AHB3ENSETR 0xA20
#define RCC_MP_AHB4ENSETR 0xA28
/* used for most of SELR register */
@@ -534,6 +535,8 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
STM32MP1_CLK_SET_CLR(RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL),
STM32MP1_CLK_SET_CLR(RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL),
+ STM32MP1_CLK_SET_CLR(RCC_MP_AHB3ENSETR, 11, HSEM, _UNKNOWN_SEL),
+
STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL),
STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL),
STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL),
--
2.15.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [U-Boot] [PATCH 3/4] hwspinlock: add stm32 hardware spinlock support
2018-11-13 8:51 [U-Boot] [PATCH 0/4] Add Hardware Spinlock class Benjamin Gaignard
2018-11-13 8:51 ` [U-Boot] [PATCH 1/4] dm: " Benjamin Gaignard
2018-11-13 8:51 ` [U-Boot] [PATCH 2/4] clk: stm32: add hardware spinlock clock Benjamin Gaignard
@ 2018-11-13 8:51 ` Benjamin Gaignard
2018-11-13 19:53 ` Simon Glass
2018-11-13 8:51 ` [U-Boot] [PATCH 4/4] pinctrl: stm32: make pinctrl use hwspinlock Benjamin Gaignard
3 siblings, 1 reply; 8+ messages in thread
From: Benjamin Gaignard @ 2018-11-13 8:51 UTC (permalink / raw)
To: u-boot
Implement hardware spinlock support for STM32MP1.
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
---
arch/arm/dts/stm32mp157c-ed1.dts | 4 ++
arch/arm/dts/stm32mp157c.dtsi | 9 ++++
configs/stm32mp15_basic_defconfig | 2 +
drivers/hwspinlock/Kconfig | 6 +++
drivers/hwspinlock/Makefile | 1 +
drivers/hwspinlock/stm32_hwspinlock.c | 90 +++++++++++++++++++++++++++++++++++
6 files changed, 112 insertions(+)
create mode 100644 drivers/hwspinlock/stm32_hwspinlock.c
diff --git a/arch/arm/dts/stm32mp157c-ed1.dts b/arch/arm/dts/stm32mp157c-ed1.dts
index f8b7701167..fc277dd7d2 100644
--- a/arch/arm/dts/stm32mp157c-ed1.dts
+++ b/arch/arm/dts/stm32mp157c-ed1.dts
@@ -365,6 +365,10 @@
usb33d-supply = <&usb33>;
};
+&hwspinlock {
+ status = "okay";
+};
+
&usbphyc_port0 {
phy-supply = <&vdd_usb>;
vdda1v1-supply = <®11>;
diff --git a/arch/arm/dts/stm32mp157c.dtsi b/arch/arm/dts/stm32mp157c.dtsi
index 33c5981869..37cadfa30c 100644
--- a/arch/arm/dts/stm32mp157c.dtsi
+++ b/arch/arm/dts/stm32mp157c.dtsi
@@ -690,6 +690,15 @@
status = "disabled";
};
+ hwspinlock: hwspinlock at 4c000000 {
+ compatible = "st,stm32-hwspinlock";
+ #hwlock-cells = <1>;
+ reg = <0x4c000000 0x400>;
+ clocks = <&rcc HSEM>;
+ clock-names = "hwspinlock";
+ status = "disabled";
+ };
+
rcc: rcc at 50000000 {
compatible = "st,stm32mp1-rcc", "syscon";
reg = <0x50000000 0x1000>;
diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig
index 3bf7538089..c8409fd04e 100644
--- a/configs/stm32mp15_basic_defconfig
+++ b/configs/stm32mp15_basic_defconfig
@@ -32,6 +32,8 @@ CONFIG_CMD_EXT4_WRITE=y
# CONFIG_SPL_DOS_PARTITION is not set
CONFIG_DEFAULT_DEVICE_TREE="stm32mp157c-ev1"
CONFIG_STM32_ADC=y
+CONFIG_DM_HWSPINLOCK=y
+CONFIG_HWSPINLOCK_STM32=y
CONFIG_DM_I2C=y
CONFIG_SYS_I2C_STM32F7=y
CONFIG_LED=y
diff --git a/drivers/hwspinlock/Kconfig b/drivers/hwspinlock/Kconfig
index de367fd2a9..f28d582bb2 100644
--- a/drivers/hwspinlock/Kconfig
+++ b/drivers/hwspinlock/Kconfig
@@ -13,4 +13,10 @@ config HWSPINLOCK_SANDBOX
can be probed and support all the methods of HWSPINLOCK, but does not
really do anything.
+config HWSPINLOCK_STM32
+ bool "Enable Hardware Spinlock support for STM32"
+ depends on ARCH_STM32MP && DM_HWSPINLOCK
+ help
+ Enable hardware spinlock support in STM32MP.
+
endmenu
diff --git a/drivers/hwspinlock/Makefile b/drivers/hwspinlock/Makefile
index 2704d6814f..289b12a256 100644
--- a/drivers/hwspinlock/Makefile
+++ b/drivers/hwspinlock/Makefile
@@ -4,3 +4,4 @@
obj-$(CONFIG_DM_HWSPINLOCK) += hwspinlock-uclass.o
obj-$(CONFIG_HWSPINLOCK_SANDBOX) += sandbox_hwspinlock.o
+obj-$(CONFIG_HWSPINLOCK_STM32) += stm32_hwspinlock.o
diff --git a/drivers/hwspinlock/stm32_hwspinlock.c b/drivers/hwspinlock/stm32_hwspinlock.c
new file mode 100644
index 0000000000..b8f3b1632f
--- /dev/null
+++ b/drivers/hwspinlock/stm32_hwspinlock.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <linux/libfdt.h>
+#include <hwspinlock.h>
+#include <asm/io.h>
+
+#define STM32_MUTEX_COREID BIT(8)
+#define STM32_MUTEX_LOCK_BIT BIT(31)
+#define STM32_MUTEX_NUM_LOCKS 32
+
+static int stm32mp1_lock(struct udevice *dev, int index)
+{
+ fdt_addr_t *base = dev_get_priv(dev);
+ u32 status;
+
+ if (index >= STM32_MUTEX_NUM_LOCKS)
+ return -EINVAL;
+
+ status = readl(*base + index * sizeof(u32));
+ if (status == (STM32_MUTEX_LOCK_BIT | STM32_MUTEX_COREID))
+ return -EBUSY;
+
+ writel(STM32_MUTEX_LOCK_BIT | STM32_MUTEX_COREID,
+ *base + index * sizeof(u32));
+
+ status = readl(*base + index * sizeof(u32));
+ if (status != (STM32_MUTEX_LOCK_BIT | STM32_MUTEX_COREID))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int stm32mp1_unlock(struct udevice *dev, int index)
+{
+ fdt_addr_t *base = dev_get_priv(dev);
+
+ if (index >= STM32_MUTEX_NUM_LOCKS)
+ return -EINVAL;
+
+ writel(STM32_MUTEX_COREID, *base + index * sizeof(u32));
+
+ return 0;
+}
+
+static int stm32mp1_hwspinlock_probe(struct udevice *dev)
+{
+ fdt_addr_t *base = dev_get_priv(dev);
+ struct clk clk;
+ int ret;
+
+ *base = dev_read_addr(dev);
+ if (*base == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (ret)
+ return ret;
+
+ ret = clk_enable(&clk);
+ if (ret)
+ clk_free(&clk);
+
+ return ret;
+}
+
+static const struct hwspinlock_ops stm32mp1_hwspinlock_ops = {
+ .lock = stm32mp1_lock,
+ .unlock = stm32mp1_unlock,
+};
+
+static const struct udevice_id stm32mp1_hwspinlock_ids[] = {
+ { .compatible = "st,stm32-hwspinlock" },
+ {}
+};
+
+U_BOOT_DRIVER(hwspinlock_stm32mp1) = {
+ .name = "hwspinlock_stm32mp1",
+ .id = UCLASS_HWSPINLOCK,
+ .of_match = stm32mp1_hwspinlock_ids,
+ .ops = &stm32mp1_hwspinlock_ops,
+ .probe = stm32mp1_hwspinlock_probe,
+ .priv_auto_alloc_size = sizeof(fdt_addr_t),
+};
--
2.15.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [U-Boot] [PATCH 4/4] pinctrl: stm32: make pinctrl use hwspinlock
2018-11-13 8:51 [U-Boot] [PATCH 0/4] Add Hardware Spinlock class Benjamin Gaignard
` (2 preceding siblings ...)
2018-11-13 8:51 ` [U-Boot] [PATCH 3/4] hwspinlock: add stm32 hardware spinlock support Benjamin Gaignard
@ 2018-11-13 8:51 ` Benjamin Gaignard
2018-11-13 19:53 ` Simon Glass
3 siblings, 1 reply; 8+ messages in thread
From: Benjamin Gaignard @ 2018-11-13 8:51 UTC (permalink / raw)
To: u-boot
From: Benjamin Gaignard <benjamin.gaignard@linaro.org>
Protect configuration registers with a hardware spinlock
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
---
arch/arm/dts/stm32mp157c-ed1.dts | 4 ++++
drivers/pinctrl/pinctrl_stm32.c | 22 ++++++++++++++++++++++
2 files changed, 26 insertions(+)
diff --git a/arch/arm/dts/stm32mp157c-ed1.dts b/arch/arm/dts/stm32mp157c-ed1.dts
index fc277dd7d2..7a9b742d36 100644
--- a/arch/arm/dts/stm32mp157c-ed1.dts
+++ b/arch/arm/dts/stm32mp157c-ed1.dts
@@ -369,6 +369,10 @@
status = "okay";
};
+&pinctrl {
+ hwlocks = <&hwspinlock 0>;
+};
+
&usbphyc_port0 {
phy-supply = <&vdd_usb>;
vdda1v1-supply = <®11>;
diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c
index 31285cdd57..469cc0c543 100644
--- a/drivers/pinctrl/pinctrl_stm32.c
+++ b/drivers/pinctrl/pinctrl_stm32.c
@@ -1,6 +1,7 @@
#include <common.h>
#include <dm.h>
#include <dm/pinctrl.h>
+#include <hwspinlock.h>
#include <asm/arch/gpio.h>
#include <asm/gpio.h>
#include <asm/io.h>
@@ -19,12 +20,20 @@ static int stm32_gpio_config(struct gpio_desc *desc,
{
struct stm32_gpio_priv *priv = dev_get_priv(desc->dev);
struct stm32_gpio_regs *regs = priv->regs;
+ struct hwspinlock *hws = dev_get_priv(desc->dev->parent);
u32 index;
+ int ret;
if (!ctl || ctl->af > 15 || ctl->mode > 3 || ctl->otype > 1 ||
ctl->pupd > 2 || ctl->speed > 3)
return -EINVAL;
+ ret = hwspinlock_lock_timeout(hws, 1);
+ if (ret == -ETIME) {
+ dev_err(desc->dev, "HWSpinlock timeout\n");
+ return ret;
+ }
+
index = (desc->offset & 0x07) * 4;
clrsetbits_le32(®s->afr[desc->offset >> 3], AFR_MASK << index,
ctl->af << index);
@@ -39,6 +48,8 @@ static int stm32_gpio_config(struct gpio_desc *desc,
index = desc->offset;
clrsetbits_le32(®s->otyper, OTYPE_MSK << index, ctl->otype << index);
+ hwspinlock_unlock(hws);
+
return 0;
}
@@ -176,6 +187,15 @@ static int stm32_pinctrl_set_state_simple(struct udevice *dev,
}
#endif /* PINCTRL_FULL */
+static int stm32_pinctrl_probe(struct udevice *dev)
+{
+ struct hwspinlock *hws = dev_get_priv(dev);
+
+ hwspinlock_get_by_index(dev, 0, hws);
+
+ return 0;
+}
+
static struct pinctrl_ops stm32_pinctrl_ops = {
#if CONFIG_IS_ENABLED(PINCTRL_FULL)
.set_state = stm32_pinctrl_set_state,
@@ -200,4 +220,6 @@ U_BOOT_DRIVER(pinctrl_stm32) = {
.of_match = stm32_pinctrl_ids,
.ops = &stm32_pinctrl_ops,
.bind = dm_scan_fdt_dev,
+ .probe = stm32_pinctrl_probe,
+ .priv_auto_alloc_size = sizeof(struct hwspinlock),
};
--
2.15.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [U-Boot] [PATCH 1/4] dm: Add Hardware Spinlock class
2018-11-13 8:51 ` [U-Boot] [PATCH 1/4] dm: " Benjamin Gaignard
@ 2018-11-13 19:53 ` Simon Glass
0 siblings, 0 replies; 8+ messages in thread
From: Simon Glass @ 2018-11-13 19:53 UTC (permalink / raw)
To: u-boot
Hi Benjamin,
On 13 November 2018 at 01:51, Benjamin Gaignard
<benjamin.gaignard@linaro.org> wrote:
>
> From: Benjamin Gaignard <benjamin.gaignard@linaro.org>
>
> This is uclass for Hardware Spinlocks.
> It implements two mandatory operations: lock and unlock
> and one optional relax operation.
>
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
> ---
> arch/sandbox/dts/test.dts | 4 +
> arch/sandbox/include/asm/state.h | 1 +
> configs/sandbox_defconfig | 2 +
> drivers/Kconfig | 2 +
> drivers/Makefile | 1 +
> drivers/hwspinlock/Kconfig | 16 ++++
> drivers/hwspinlock/Makefile | 6 ++
> drivers/hwspinlock/hwspinlock-uclass.c | 145 ++++++++++++++++++++++++++++++++
> drivers/hwspinlock/sandbox_hwspinlock.c | 56 ++++++++++++
> include/dm/uclass-id.h | 1 +
> include/hwspinlock.h | 140 ++++++++++++++++++++++++++++++
> test/dm/Makefile | 1 +
> test/dm/hwspinlock.c | 40 +++++++++
> 13 files changed, 415 insertions(+)
> create mode 100644 drivers/hwspinlock/Kconfig
> create mode 100644 drivers/hwspinlock/Makefile
> create mode 100644 drivers/hwspinlock/hwspinlock-uclass.c
> create mode 100644 drivers/hwspinlock/sandbox_hwspinlock.c
> create mode 100644 include/hwspinlock.h
> create mode 100644 test/dm/hwspinlock.c
>
> diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
> index 57e0dd7663..50cd2f89e0 100644
> --- a/arch/sandbox/dts/test.dts
> +++ b/arch/sandbox/dts/test.dts
> @@ -712,6 +712,10 @@
> sandbox_tee {
> compatible = "sandbox,tee";
> };
> +
> + hwspinlock at 0 {
> + compatible = "sandbox,hwspinlock";
> + };
> };
>
> #include "sandbox_pmic.dtsi"
> diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h
> index dcb6d5f568..a5d7c6aaf3 100644
> --- a/arch/sandbox/include/asm/state.h
> +++ b/arch/sandbox/include/asm/state.h
> @@ -99,6 +99,7 @@ struct sandbox_state {
>
> ulong next_tag; /* Next address tag to allocate */
> struct list_head mapmem_head; /* struct sandbox_mapmem_entry */
> + bool hwspinlock; /* Hardware Spinlock status */
> };
>
> /* Minimum space we guarantee in the state FDT when calling read/write*/
> diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
> index 2ce336fc81..36b67be2df 100644
> --- a/configs/sandbox_defconfig
> +++ b/configs/sandbox_defconfig
> @@ -97,6 +97,8 @@ CONFIG_BOARD=y
> CONFIG_BOARD_SANDBOX=y
> CONFIG_PM8916_GPIO=y
> CONFIG_SANDBOX_GPIO=y
> +CONFIG_DM_HWSPINLOCK=y
> +CONFIG_HWSPINLOCK_SANDBOX=y
> CONFIG_DM_I2C_COMPAT=y
> CONFIG_I2C_CROS_EC_TUNNEL=y
> CONFIG_I2C_CROS_EC_LDO=y
> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index 927a2b87f6..7e6ca7cd3e 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -40,6 +40,8 @@ source "drivers/fpga/Kconfig"
>
> source "drivers/gpio/Kconfig"
>
> +source "drivers/hwspinlock/Kconfig"
> +
> source "drivers/i2c/Kconfig"
>
> source "drivers/input/Kconfig"
> diff --git a/drivers/Makefile b/drivers/Makefile
> index fb38b67541..0ef56fb416 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -111,4 +111,5 @@ obj-$(CONFIG_W1) += w1/
> obj-$(CONFIG_W1_EEPROM) += w1-eeprom/
>
> obj-$(CONFIG_MACH_PIC32) += ddr/microchip/
> +obj-$(CONFIG_DM_HWSPINLOCK) += hwspinlock/
> endif
> diff --git a/drivers/hwspinlock/Kconfig b/drivers/hwspinlock/Kconfig
> new file mode 100644
> index 0000000000..de367fd2a9
> --- /dev/null
> +++ b/drivers/hwspinlock/Kconfig
> @@ -0,0 +1,16 @@
> +menu "Hardware Spinlock Support"
> +
> +config DM_HWSPINLOCK
> + bool "Enable U-Boot hardware spinlock support"
> + help
> + This option enables U-Boot hardware spinlock support
> +
> +config HWSPINLOCK_SANDBOX
> + bool "Enable Hardware Spinlock support for Sandbox"
> + depends on SANDBOX && DM_HWSPINLOCK
> + help
> + Enable hardware spinlock support in Sandbox. This is a dummy device that
> + can be probed and support all the methods of HWSPINLOCK, but does not
> + really do anything.
> +
> +endmenu
> diff --git a/drivers/hwspinlock/Makefile b/drivers/hwspinlock/Makefile
> new file mode 100644
> index 0000000000..2704d6814f
> --- /dev/null
> +++ b/drivers/hwspinlock/Makefile
> @@ -0,0 +1,6 @@
> +# SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
> +#
> +# Copyright (C) 2018, STMicroelectronics - All Rights Reserved
> +
> +obj-$(CONFIG_DM_HWSPINLOCK) += hwspinlock-uclass.o
> +obj-$(CONFIG_HWSPINLOCK_SANDBOX) += sandbox_hwspinlock.o
> diff --git a/drivers/hwspinlock/hwspinlock-uclass.c b/drivers/hwspinlock/hwspinlock-uclass.c
> new file mode 100644
> index 0000000000..1fed24228c
> --- /dev/null
> +++ b/drivers/hwspinlock/hwspinlock-uclass.c
> @@ -0,0 +1,145 @@
> +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
> +/*
> + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <hwspinlock.h>
> +#include <dm/device-internal.h>
> +
> +static inline const struct hwspinlock_ops *
> +hwspinlock_dev_ops(struct udevice *dev)
> +{
> + return (const struct hwspinlock_ops *)dev->driver->ops;
> +}
> +
> +static int hwspinlock_of_xlate_default(struct hwspinlock *hws,
> + struct ofnode_phandle_args *args)
> +{
> + if (args->args_count > 1) {
> + debug("Invaild args_count: %d\n", args->args_count);
> + return -EINVAL;
> + }
> +
> + if (args->args_count)
> + hws->id = args->args[0];
> + else
> + hws->id = 0;
> +
> + return 0;
> +}
> +
> +int hwspinlock_get_by_index(struct udevice *dev, int index,
> + struct hwspinlock *hws)
> +{
> + int ret;
> + struct ofnode_phandle_args args;
> + struct udevice *dev_hws;
> + const struct hwspinlock_ops *ops;
> +
> + assert(hws);
> + hws->dev = NULL;
> +
> + ret = dev_read_phandle_with_args(dev, "hwlocks", "#hwlock-cells", 1,
> + index, &args);
> + if (ret) {
> + dev_dbg(dev, "%s: dev_read_phandle_with_args: err=%d\n",
> + __func__, ret);
> + return ret;
> + }
> +
> + ret = uclass_get_device_by_ofnode(UCLASS_HWSPINLOCK,
> + args.node, &dev_hws);
> + if (ret) {
> + dev_dbg(dev,
> + "%s: uclass_get_device_by_of_offset failed: err=%d\n",
> + __func__, ret);
> + return ret;
> + }
> +
> + hws->dev = dev_hws;
> +
> + ops = hwspinlock_dev_ops(dev_hws);
> +
> + if (ops->of_xlate)
> + ret = ops->of_xlate(hws, &args);
> + else
> + ret = hwspinlock_of_xlate_default(hws, &args);
> + if (ret)
> + dev_dbg(dev, "of_xlate() failed: %d\n", ret);
> +
> + return ret;
> +}
> +
> +int hwspinlock_lock_timeout(struct hwspinlock *hws, unsigned int timeout)
> +{
> + const struct hwspinlock_ops *ops;
> + ulong start;
> + int ret;
> +
> + assert(hws);
> +
> + if (!hws->dev)
> + return -EINVAL;
> +
> + ops = hwspinlock_dev_ops(hws->dev);
> +
Remove this blank line?
> + if (!ops || !ops->lock)
> + return -EINVAL;
-ENOSYS but please drop the !ops since that shouldn't happen.
> +
> + for (start = get_timer(0); get_timer(start) < timeout;) {
> + ret = ops->lock(hws->dev, hws->id);
> + if (!ret)
> + return ret;
> +
> + if (ops->relax)
> + ops->relax(hws->dev);
> + }
> +
> + return -ETIME;
We normally use ETIMEDOUT for this.
> +}
> +
> +int hwspinlock_unlock(struct hwspinlock *hws)
> +{
> + const struct hwspinlock_ops *ops;
> +
> + assert(hws);
> +
> + if (!hws->dev)
> + return -EINVAL;
> +
> + ops = hwspinlock_dev_ops(hws->dev);
> +
> + if (!ops || !ops->unlock)
> + return -EINVAL;
-ENOSYS
> +
> + return ops->unlock(hws->dev, hws->id);
> +}
> +
> +static int hwspinlock_post_bind(struct udevice *dev)
> +{
> +#if defined(CONFIG_NEEDS_MANUAL_RELOC)
> + struct hwspinlock_ops *ops = device_get_ops(dev);
> + static int reloc_done;
> +
> + if (!reloc_done) {
> + if (ops->lock)
> + ops->lock += gd->reloc_off;
> + if (ops->unlock)
> + ops->unlock += gd->reloc_off;
> + if (ops->relax)
> + ops->relax += gd->reloc_off;
> +
> + reloc_done++;
> + }
> +#endif
> + return 0;
> +}
> +
> +UCLASS_DRIVER(hwspinlock) = {
> + .id = UCLASS_HWSPINLOCK,
> + .name = "hwspinlock",
> + .post_bind = hwspinlock_post_bind,
> +};
> diff --git a/drivers/hwspinlock/sandbox_hwspinlock.c b/drivers/hwspinlock/sandbox_hwspinlock.c
> new file mode 100644
> index 0000000000..be920f5f99
> --- /dev/null
> +++ b/drivers/hwspinlock/sandbox_hwspinlock.c
> @@ -0,0 +1,56 @@
> +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
> +/*
> + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <hwspinlock.h>
> +#include <asm/state.h>
> +
> +static int sandbox_lock(struct udevice *dev, int index)
> +{
> + struct sandbox_state *state = state_get_current();
> +
> + if (index != 0)
> + return -1;
> +
> + if (state->hwspinlock)
> + return -1;
> +
> + state->hwspinlock = true;
> +
> + return 0;
> +}
> +
> +static int sandbox_unlock(struct udevice *dev, int index)
> +{
> + struct sandbox_state *state = state_get_current();
> +
> + if (index != 0)
> + return -1;
> +
> + if (!state->hwspinlock)
> + return -1;
> +
> + state->hwspinlock = false;
> +
> + return 0;
> +}
> +
> +static const struct hwspinlock_ops sandbox_hwspinlock_ops = {
> + .lock = sandbox_lock,
> + .unlock = sandbox_unlock,
> +};
> +
> +static const struct udevice_id sandbox_hwspinlock_ids[] = {
> + { .compatible = "sandbox,hwspinlock" },
> + {}
> +};
> +
> +U_BOOT_DRIVER(hwspinlock_sandbox) = {
> + .name = "hwspinlock_sandbox",
> + .id = UCLASS_HWSPINLOCK,
> + .of_match = sandbox_hwspinlock_ids,
> + .ops = &sandbox_hwspinlock_ops,
> +};
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index 269a2c6e72..6193017432 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -40,6 +40,7 @@ enum uclass_id {
> UCLASS_ETH, /* Ethernet device */
> UCLASS_FS_FIRMWARE_LOADER, /* Generic loader */
> UCLASS_GPIO, /* Bank of general-purpose I/O pins */
> + UCLASS_HWSPINLOCK, /* Hardware semaphores */
> UCLASS_FIRMWARE, /* Firmware */
> UCLASS_I2C, /* I2C bus */
> UCLASS_I2C_EEPROM, /* I2C EEPROM device */
> diff --git a/include/hwspinlock.h b/include/hwspinlock.h
> new file mode 100644
> index 0000000000..4671c8fce5
> --- /dev/null
> +++ b/include/hwspinlock.h
> @@ -0,0 +1,140 @@
> +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
> +/*
> + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
> + */
> +
> +#ifndef _HWSPINLOCK_H_
> +#define _HWSPINLOCK_H_
> +
> +/**
> + * Implement a hwspinlock uclass.
> + * Hardware spinlocks are used to perform hardware protection of
> + * critical sections and synchronisation between multiprocessors.
> + */
> +
> +struct udevice;
> +
> +/**
> + * struct hwspinlock - A handle to (allowing control of) a single hardware
> + * spinlock.
> + *
> + * @dev: The device which implements the hardware spinlock.
> + * @id: The hardware spinlock ID within the provider.
> + */
> +struct hwspinlock {
> + struct udevice *dev;
> + unsigned long id;
> +};
> +
> +#if CONFIG_IS_ENABLED(DM_HWSPINLOCK)
> +
> +/**
> + * hwspinlock_get_by_index - Get a hardware spinlock by integer index
> + *
> + * This looks up and request a hardware spinlock. The index is relative to the
> + * client device; each device is assumed to have n hardware spinlock associated
> + * with it somehow, and this function finds and requests one of them.
> + *
> + * @dev: The client device.
> + * @index: The index of the hardware spinlock to request, within the
> + * client's list of hardware spinlock.
> + * @hws: A pointer to a hardware spinlock struct to initialize.
> + * @return 0 if OK, or a negative error code.
> + */
> +int hwspinlock_get_by_index(struct udevice *dev,
> + int index, struct hwspinlock *hws);
> +
> +/**
> + * Lock the hardware spinlock
> + *
> + * @hws: A hardware spinlock struct that previously requested by
> + * hwspinlock_get_by_index
> + * @timeout: Timeout value in msecs
> + * @return: 0 if OK, -ETIME if timeout, -ve on other errors
-ETIMEDOUT
[..]
Regards,
Simon
^ permalink raw reply [flat|nested] 8+ messages in thread
* [U-Boot] [PATCH 3/4] hwspinlock: add stm32 hardware spinlock support
2018-11-13 8:51 ` [U-Boot] [PATCH 3/4] hwspinlock: add stm32 hardware spinlock support Benjamin Gaignard
@ 2018-11-13 19:53 ` Simon Glass
0 siblings, 0 replies; 8+ messages in thread
From: Simon Glass @ 2018-11-13 19:53 UTC (permalink / raw)
To: u-boot
Hi Benjamin,
On 13 November 2018 at 01:51, Benjamin Gaignard
<benjamin.gaignard@linaro.org> wrote:
> Implement hardware spinlock support for STM32MP1.
>
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
> ---
> arch/arm/dts/stm32mp157c-ed1.dts | 4 ++
> arch/arm/dts/stm32mp157c.dtsi | 9 ++++
> configs/stm32mp15_basic_defconfig | 2 +
> drivers/hwspinlock/Kconfig | 6 +++
> drivers/hwspinlock/Makefile | 1 +
> drivers/hwspinlock/stm32_hwspinlock.c | 90 +++++++++++++++++++++++++++++++++++
> 6 files changed, 112 insertions(+)
> create mode 100644 drivers/hwspinlock/stm32_hwspinlock.c
>
> diff --git a/arch/arm/dts/stm32mp157c-ed1.dts b/arch/arm/dts/stm32mp157c-ed1.dts
> index f8b7701167..fc277dd7d2 100644
> --- a/arch/arm/dts/stm32mp157c-ed1.dts
> +++ b/arch/arm/dts/stm32mp157c-ed1.dts
> @@ -365,6 +365,10 @@
> usb33d-supply = <&usb33>;
> };
>
> +&hwspinlock {
> + status = "okay";
> +};
> +
> &usbphyc_port0 {
> phy-supply = <&vdd_usb>;
> vdda1v1-supply = <®11>;
> diff --git a/arch/arm/dts/stm32mp157c.dtsi b/arch/arm/dts/stm32mp157c.dtsi
> index 33c5981869..37cadfa30c 100644
> --- a/arch/arm/dts/stm32mp157c.dtsi
> +++ b/arch/arm/dts/stm32mp157c.dtsi
> @@ -690,6 +690,15 @@
> status = "disabled";
> };
>
> + hwspinlock: hwspinlock at 4c000000 {
> + compatible = "st,stm32-hwspinlock";
> + #hwlock-cells = <1>;
> + reg = <0x4c000000 0x400>;
> + clocks = <&rcc HSEM>;
> + clock-names = "hwspinlock";
> + status = "disabled";
> + };
> +
> rcc: rcc at 50000000 {
> compatible = "st,stm32mp1-rcc", "syscon";
> reg = <0x50000000 0x1000>;
> diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig
> index 3bf7538089..c8409fd04e 100644
> --- a/configs/stm32mp15_basic_defconfig
> +++ b/configs/stm32mp15_basic_defconfig
> @@ -32,6 +32,8 @@ CONFIG_CMD_EXT4_WRITE=y
> # CONFIG_SPL_DOS_PARTITION is not set
> CONFIG_DEFAULT_DEVICE_TREE="stm32mp157c-ev1"
> CONFIG_STM32_ADC=y
> +CONFIG_DM_HWSPINLOCK=y
> +CONFIG_HWSPINLOCK_STM32=y
> CONFIG_DM_I2C=y
> CONFIG_SYS_I2C_STM32F7=y
> CONFIG_LED=y
> diff --git a/drivers/hwspinlock/Kconfig b/drivers/hwspinlock/Kconfig
> index de367fd2a9..f28d582bb2 100644
> --- a/drivers/hwspinlock/Kconfig
> +++ b/drivers/hwspinlock/Kconfig
> @@ -13,4 +13,10 @@ config HWSPINLOCK_SANDBOX
> can be probed and support all the methods of HWSPINLOCK, but does not
> really do anything.
>
> +config HWSPINLOCK_STM32
> + bool "Enable Hardware Spinlock support for STM32"
> + depends on ARCH_STM32MP && DM_HWSPINLOCK
> + help
> + Enable hardware spinlock support in STM32MP.
Please add more detail here - what is it used for and how does it work?
> +
> endmenu
> diff --git a/drivers/hwspinlock/Makefile b/drivers/hwspinlock/Makefile
> index 2704d6814f..289b12a256 100644
> --- a/drivers/hwspinlock/Makefile
> +++ b/drivers/hwspinlock/Makefile
> @@ -4,3 +4,4 @@
>
> obj-$(CONFIG_DM_HWSPINLOCK) += hwspinlock-uclass.o
> obj-$(CONFIG_HWSPINLOCK_SANDBOX) += sandbox_hwspinlock.o
> +obj-$(CONFIG_HWSPINLOCK_STM32) += stm32_hwspinlock.o
> diff --git a/drivers/hwspinlock/stm32_hwspinlock.c b/drivers/hwspinlock/stm32_hwspinlock.c
> new file mode 100644
> index 0000000000..b8f3b1632f
> --- /dev/null
> +++ b/drivers/hwspinlock/stm32_hwspinlock.c
> @@ -0,0 +1,90 @@
> +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
> +/*
> + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
> + */
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <fdtdec.h>
Do you need this?
> +#include <linux/libfdt.h>
Or this?
> +#include <hwspinlock.h>
> +#include <asm/io.h>
> +
> +#define STM32_MUTEX_COREID BIT(8)
> +#define STM32_MUTEX_LOCK_BIT BIT(31)
> +#define STM32_MUTEX_NUM_LOCKS 32
> +
> +static int stm32mp1_lock(struct udevice *dev, int index)
> +{
> + fdt_addr_t *base = dev_get_priv(dev);
> + u32 status;
> +
> + if (index >= STM32_MUTEX_NUM_LOCKS)
> + return -EINVAL;
> +
> + status = readl(*base + index * sizeof(u32));
> + if (status == (STM32_MUTEX_LOCK_BIT | STM32_MUTEX_COREID))
> + return -EBUSY;
> +
> + writel(STM32_MUTEX_LOCK_BIT | STM32_MUTEX_COREID,
> + *base + index * sizeof(u32));
> +
> + status = readl(*base + index * sizeof(u32));
> + if (status != (STM32_MUTEX_LOCK_BIT | STM32_MUTEX_COREID))
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> +static int stm32mp1_unlock(struct udevice *dev, int index)
> +{
> + fdt_addr_t *base = dev_get_priv(dev);
> +
> + if (index >= STM32_MUTEX_NUM_LOCKS)
> + return -EINVAL;
> +
> + writel(STM32_MUTEX_COREID, *base + index * sizeof(u32));
> +
> + return 0;
> +}
> +
> +static int stm32mp1_hwspinlock_probe(struct udevice *dev)
> +{
> + fdt_addr_t *base = dev_get_priv(dev);
> + struct clk clk;
> + int ret;
> +
> + *base = dev_read_addr(dev);
> + if (*base == FDT_ADDR_T_NONE)
> + return -EINVAL;
> +
> + ret = clk_get_by_index(dev, 0, &clk);
> + if (ret)
> + return ret;
> +
> + ret = clk_enable(&clk);
> + if (ret)
> + clk_free(&clk);
> +
> + return ret;
> +}
> +
> +static const struct hwspinlock_ops stm32mp1_hwspinlock_ops = {
> + .lock = stm32mp1_lock,
> + .unlock = stm32mp1_unlock,
> +};
> +
> +static const struct udevice_id stm32mp1_hwspinlock_ids[] = {
> + { .compatible = "st,stm32-hwspinlock" },
> + {}
> +};
> +
> +U_BOOT_DRIVER(hwspinlock_stm32mp1) = {
> + .name = "hwspinlock_stm32mp1",
> + .id = UCLASS_HWSPINLOCK,
> + .of_match = stm32mp1_hwspinlock_ids,
> + .ops = &stm32mp1_hwspinlock_ops,
> + .probe = stm32mp1_hwspinlock_probe,
> + .priv_auto_alloc_size = sizeof(fdt_addr_t),
Please use a struct with one member, instead of this
> +};
> --
> 2.15.0
>
Regards,
Simon
^ permalink raw reply [flat|nested] 8+ messages in thread
* [U-Boot] [PATCH 4/4] pinctrl: stm32: make pinctrl use hwspinlock
2018-11-13 8:51 ` [U-Boot] [PATCH 4/4] pinctrl: stm32: make pinctrl use hwspinlock Benjamin Gaignard
@ 2018-11-13 19:53 ` Simon Glass
0 siblings, 0 replies; 8+ messages in thread
From: Simon Glass @ 2018-11-13 19:53 UTC (permalink / raw)
To: u-boot
Hi Benjamin,
On 13 November 2018 at 01:51, Benjamin Gaignard
<benjamin.gaignard@linaro.org> wrote:
> From: Benjamin Gaignard <benjamin.gaignard@linaro.org>
>
> Protect configuration registers with a hardware spinlock
Can you please add a bit more detail about what problem this fixes?
>
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
> ---
> arch/arm/dts/stm32mp157c-ed1.dts | 4 ++++
> drivers/pinctrl/pinctrl_stm32.c | 22 ++++++++++++++++++++++
> 2 files changed, 26 insertions(+)
>
> diff --git a/arch/arm/dts/stm32mp157c-ed1.dts b/arch/arm/dts/stm32mp157c-ed1.dts
> index fc277dd7d2..7a9b742d36 100644
> --- a/arch/arm/dts/stm32mp157c-ed1.dts
> +++ b/arch/arm/dts/stm32mp157c-ed1.dts
> @@ -369,6 +369,10 @@
> status = "okay";
> };
>
> +&pinctrl {
> + hwlocks = <&hwspinlock 0>;
> +};
> +
> &usbphyc_port0 {
> phy-supply = <&vdd_usb>;
> vdda1v1-supply = <®11>;
> diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c
> index 31285cdd57..469cc0c543 100644
> --- a/drivers/pinctrl/pinctrl_stm32.c
> +++ b/drivers/pinctrl/pinctrl_stm32.c
> @@ -1,6 +1,7 @@
> #include <common.h>
> #include <dm.h>
> #include <dm/pinctrl.h>
> +#include <hwspinlock.h>
> #include <asm/arch/gpio.h>
> #include <asm/gpio.h>
> #include <asm/io.h>
> @@ -19,12 +20,20 @@ static int stm32_gpio_config(struct gpio_desc *desc,
> {
> struct stm32_gpio_priv *priv = dev_get_priv(desc->dev);
> struct stm32_gpio_regs *regs = priv->regs;
> + struct hwspinlock *hws = dev_get_priv(desc->dev->parent);
> u32 index;
> + int ret;
>
> if (!ctl || ctl->af > 15 || ctl->mode > 3 || ctl->otype > 1 ||
> ctl->pupd > 2 || ctl->speed > 3)
> return -EINVAL;
>
> + ret = hwspinlock_lock_timeout(hws, 1);
> + if (ret == -ETIME) {
> + dev_err(desc->dev, "HWSpinlock timeout\n");
> + return ret;
> + }
> +
> index = (desc->offset & 0x07) * 4;
> clrsetbits_le32(®s->afr[desc->offset >> 3], AFR_MASK << index,
> ctl->af << index);
> @@ -39,6 +48,8 @@ static int stm32_gpio_config(struct gpio_desc *desc,
> index = desc->offset;
> clrsetbits_le32(®s->otyper, OTYPE_MSK << index, ctl->otype << index);
>
> + hwspinlock_unlock(hws);
> +
> return 0;
> }
>
> @@ -176,6 +187,15 @@ static int stm32_pinctrl_set_state_simple(struct udevice *dev,
> }
> #endif /* PINCTRL_FULL */
>
> +static int stm32_pinctrl_probe(struct udevice *dev)
> +{
> + struct hwspinlock *hws = dev_get_priv(dev);
> +
> + hwspinlock_get_by_index(dev, 0, hws);
Need to check return value
> +
> + return 0;
> +}
> +
> static struct pinctrl_ops stm32_pinctrl_ops = {
> #if CONFIG_IS_ENABLED(PINCTRL_FULL)
> .set_state = stm32_pinctrl_set_state,
> @@ -200,4 +220,6 @@ U_BOOT_DRIVER(pinctrl_stm32) = {
> .of_match = stm32_pinctrl_ids,
> .ops = &stm32_pinctrl_ops,
> .bind = dm_scan_fdt_dev,
> + .probe = stm32_pinctrl_probe,
> + .priv_auto_alloc_size = sizeof(struct hwspinlock),
> };
> --
> 2.15.0
>
Regards,
SImon
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2018-11-13 19:53 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-13 8:51 [U-Boot] [PATCH 0/4] Add Hardware Spinlock class Benjamin Gaignard
2018-11-13 8:51 ` [U-Boot] [PATCH 1/4] dm: " Benjamin Gaignard
2018-11-13 19:53 ` Simon Glass
2018-11-13 8:51 ` [U-Boot] [PATCH 2/4] clk: stm32: add hardware spinlock clock Benjamin Gaignard
2018-11-13 8:51 ` [U-Boot] [PATCH 3/4] hwspinlock: add stm32 hardware spinlock support Benjamin Gaignard
2018-11-13 19:53 ` Simon Glass
2018-11-13 8:51 ` [U-Boot] [PATCH 4/4] pinctrl: stm32: make pinctrl use hwspinlock Benjamin Gaignard
2018-11-13 19:53 ` Simon Glass
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.