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>; usb33d-supply = <&usb33>;
}; };
&hwspinlock {
status = "okay";
};
&usbphyc_port0 { &usbphyc_port0 {
phy-supply = <&vdd_usb>; phy-supply = <&vdd_usb>;
vdda1v1-supply = <&reg11>; vdda1v1-supply = <&reg11>;

View File

@ -690,6 +690,15 @@
status = "disabled"; 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 { rcc: rcc@50000000 {
compatible = "st,stm32mp1-rcc", "syscon"; compatible = "st,stm32mp1-rcc", "syscon";
reg = <0x50000000 0x1000>; reg = <0x50000000 0x1000>;

View File

@ -32,6 +32,8 @@ CONFIG_CMD_EXT4_WRITE=y
# CONFIG_SPL_DOS_PARTITION is not set # CONFIG_SPL_DOS_PARTITION is not set
CONFIG_DEFAULT_DEVICE_TREE="stm32mp157c-ev1" CONFIG_DEFAULT_DEVICE_TREE="stm32mp157c-ev1"
CONFIG_STM32_ADC=y CONFIG_STM32_ADC=y
CONFIG_DM_HWSPINLOCK=y
CONFIG_HWSPINLOCK_STM32=y
CONFIG_DM_I2C=y CONFIG_DM_I2C=y
CONFIG_SYS_I2C_STM32F7=y CONFIG_SYS_I2C_STM32F7=y
CONFIG_LED=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 can be probed and support all the methods of HWSPINLOCK, but does not
really do anything. 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 endmenu

View File

@ -4,3 +4,4 @@
obj-$(CONFIG_DM_HWSPINLOCK) += hwspinlock-uclass.o obj-$(CONFIG_DM_HWSPINLOCK) += hwspinlock-uclass.o
obj-$(CONFIG_HWSPINLOCK_SANDBOX) += sandbox_hwspinlock.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),
};