Message ID | 20181114090114.7727-4-benjamin.gaignard@st.com |
---|---|
State | Superseded |
Headers | show |
Series | Add Hardware Spinlock class | expand |
On 14 November 2018 at 01:01, Benjamin Gaignard <benjamin.gaignard@linaro.org> wrote: > Implement hardware spinlock support for STM32MP1. > > Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com> > --- > version 2: > - remove useless include > - add a private structure to store base address > - be more verbose in configuration flag description > > arch/arm/dts/stm32mp157c-ed1.dts | 4 ++ > arch/arm/dts/stm32mp157c.dtsi | 9 ++++ > configs/stm32mp15_basic_defconfig | 2 + > drivers/hwspinlock/Kconfig | 8 +++ > drivers/hwspinlock/Makefile | 1 + > drivers/hwspinlock/stm32_hwspinlock.c | 92 +++++++++++++++++++++++++++++++++++ > 6 files changed, 116 insertions(+) > create mode 100644 drivers/hwspinlock/stm32_hwspinlock.c Reviewed-by: Simon Glass <sjg@chromium.org>
Hi Benjamin On 11/14/18 10:01 AM, Benjamin Gaignard wrote: > Implement hardware spinlock support for STM32MP1. > > Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com> > --- > version 2: > - remove useless include > - add a private structure to store base address > - be more verbose in configuration flag description > > arch/arm/dts/stm32mp157c-ed1.dts | 4 ++ > arch/arm/dts/stm32mp157c.dtsi | 9 ++++ > configs/stm32mp15_basic_defconfig | 2 + > drivers/hwspinlock/Kconfig | 8 +++ > drivers/hwspinlock/Makefile | 1 + > drivers/hwspinlock/stm32_hwspinlock.c | 92 +++++++++++++++++++++++++++++++++++ > 6 files changed, 116 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@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>; > 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..96d4f5d6ca 100644 > --- a/drivers/hwspinlock/Kconfig > +++ b/drivers/hwspinlock/Kconfig > @@ -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 > 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..a32bde4906 > --- /dev/null > +++ b/drivers/hwspinlock/stm32_hwspinlock.c > @@ -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), > +}; > Reviewed-by: Patrice Chotard <patrice.chotard@st.com> Thanks
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@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>; 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..96d4f5d6ca 100644 --- a/drivers/hwspinlock/Kconfig +++ b/drivers/hwspinlock/Kconfig @@ -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 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..a32bde4906 --- /dev/null +++ b/drivers/hwspinlock/stm32_hwspinlock.c @@ -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), +};
Implement hardware spinlock support for STM32MP1. Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com> --- version 2: - remove useless include - add a private structure to store base address - be more verbose in configuration flag description arch/arm/dts/stm32mp157c-ed1.dts | 4 ++ arch/arm/dts/stm32mp157c.dtsi | 9 ++++ configs/stm32mp15_basic_defconfig | 2 + drivers/hwspinlock/Kconfig | 8 +++ drivers/hwspinlock/Makefile | 1 + drivers/hwspinlock/stm32_hwspinlock.c | 92 +++++++++++++++++++++++++++++++++++ 6 files changed, 116 insertions(+) create mode 100644 drivers/hwspinlock/stm32_hwspinlock.c