hwspinlock: add stm32 hardware spinlock support

Implement hardware spinlock support for STM32MP1.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
This commit is contained in:
Benjamin Gaignard 2018-11-27 13:49:52 +01:00 committed by Tom Rini
parent 283bcd9a34
commit 9119f547d3
6 changed files with 116 additions and 0 deletions

View file

@ -365,6 +365,10 @@
usb33d-supply = <&usb33>;
};
&hwspinlock {
status = "okay";
};
&usbphyc_port0 {
phy-supply = <&vdd_usb>;
vdda1v1-supply = <&reg11>;

View file

@ -690,6 +690,15 @@
status = "disabled";
};
hwspinlock: hwspinlock@4c000000 {
compatible = "st,stm32-hwspinlock";
#hwlock-cells = <1>;
reg = <0x4c000000 0x400>;
clocks = <&rcc HSEM>;
clock-names = "hwspinlock";
status = "disabled";
};
rcc: rcc@50000000 {
compatible = "st,stm32mp1-rcc", "syscon";
reg = <0x50000000 0x1000>;

View file

@ -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

View file

@ -13,4 +13,12 @@ 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. Hardware spinlocks are
hardware mutex which provide a synchronisation mechanism for the
various processors on the SoC.
endmenu

View file

@ -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

View file

@ -0,0 +1,92 @@
// 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 <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
struct stm32mp1_hws_priv {
fdt_addr_t base;
};
static int stm32mp1_lock(struct udevice *dev, int index)
{
struct stm32mp1_hws_priv *priv = dev_get_priv(dev);
u32 status;
if (index >= STM32_MUTEX_NUM_LOCKS)
return -EINVAL;
status = readl(priv->base + index * sizeof(u32));
if (status == (STM32_MUTEX_LOCK_BIT | STM32_MUTEX_COREID))
return -EBUSY;
writel(STM32_MUTEX_LOCK_BIT | STM32_MUTEX_COREID,
priv->base + index * sizeof(u32));
status = readl(priv->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)
{
struct stm32mp1_hws_priv *priv = dev_get_priv(dev);
if (index >= STM32_MUTEX_NUM_LOCKS)
return -EINVAL;
writel(STM32_MUTEX_COREID, priv->base + index * sizeof(u32));
return 0;
}
static int stm32mp1_hwspinlock_probe(struct udevice *dev)
{
struct stm32mp1_hws_priv *priv = dev_get_priv(dev);
struct clk clk;
int ret;
priv->base = dev_read_addr(dev);
if (priv->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(struct stm32mp1_hws_priv),
};