diff options
| author | Wolfram Sang <wsa+renesas@sang-engineering.com> | 2026-08-17 11:53:34 +0200 |
|---|---|---|
| committer | Geert Uytterhoeven <geert+renesas@glider.be> | 2026-09-07 10:50:10 +0200 |
| commit | 504e3ae911d1398c2941063fcbe979a2e6aa90cd (patch) | |
| tree | 784b23e06c4490e45bba8ad82163474f0eb007dc | |
| parent | 529b0be30bd97dde9fe71c0cc406e252ab1362fe (diff) | |
| download | linux-next-504e3ae911d1398c2941063fcbe979a2e6aa90cd.tar.gz linux-next-504e3ae911d1398c2941063fcbe979a2e6aa90cd.zip | |
soc: renesas: rcar-mfis: Add hwspinlock support
Every MFIS instance has a block of hardware spinlocks. Add support for
them. R-Car Gen4 has only one instance, so the base_id is always 0.
R-Car Gen5 has multiple instances, so the base_id has to be encoded in
the info description. Also being a provider, a hwspinlock-private
header needs to be included. Work to refactor the headers is on-going,
but will need many preparational steps. Until then, we need to live
with the special include.
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://patch.msgid.link/20260817095447.34693-3-wsa+renesas@sang-engineering.com
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
| -rw-r--r-- | drivers/soc/renesas/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/soc/renesas/rcar-mfis.c | 54 |
2 files changed, 54 insertions, 2 deletions
diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 817b2a1a7445..64f9e4be2f63 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -468,7 +468,7 @@ endif # RISCV config RCAR_MFIS tristate "Renesas R-Car MFIS driver" depends on ARCH_RENESAS || COMPILE_TEST - depends on MAILBOX + depends on MAILBOX && HWSPINLOCK help Select this option to enable support for the Renesas R-Car Multifunctional Interface (MFIS) device found on SoCs like R-Car. diff --git a/drivers/soc/renesas/rcar-mfis.c b/drivers/soc/renesas/rcar-mfis.c index c327a60789d0..d5bbc3077373 100644 --- a/drivers/soc/renesas/rcar-mfis.c +++ b/drivers/soc/renesas/rcar-mfis.c @@ -8,6 +8,7 @@ */ #include <dt-bindings/soc/renesas,r8a78000-mfis.h> #include <linux/device.h> +#include <linux/hwspinlock.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/kernel.h> @@ -19,12 +20,18 @@ #include <linux/platform_device.h> #include <linux/spinlock.h> +/* FIXME: hwspinlock core refactoring to not need internal header is on-going */ +#include "../../hwspinlock/hwspinlock_internal.h" + +#define MFISLCKR0 0xc0 +#define MFISLCKR8 0x0724 #define MFISWPCNTR 0x0900 #define MFISWACNTR 0x0904 #define MFIS_X5H_IICR(i) ((i) * 0x1000 + 0x00) #define MFIS_X5H_EICR(i) ((i) * 0x1000 + 0x04) +#define MFIS_NUM_LOCKS 64 #define MFIS_UNPROTECT_KEY 0xACCE0000 struct mfis_priv; @@ -42,6 +49,7 @@ struct mfis_info { unsigned int mb_tx_uses_eicr:1; unsigned int mb_channels_are_unidir:1; u32 (*mb_calc_reg)(u32 chan_num, bool tx_uses_eicr, bool is_only_rx); + int hwsp_base_id; }; struct mfis_chan_priv { @@ -59,6 +67,9 @@ struct mfis_priv { /* mailbox private data */ struct mbox_controller mbox; struct mfis_chan_priv *chan_privs; + + /* hwspinlock private data */ + struct hwspinlock_device bank; /* flex array inside, must be last! */ }; static u32 mfis_read(struct mfis_reg *mreg, unsigned int reg) @@ -87,6 +98,38 @@ static void mfis_write(struct mfis_reg *mreg, u32 reg, u32 val) } /******************************************************** + * HW Spinlocks * + ********************************************************/ + +#define MFISLCKR8_CH_OFS (MFISLCKR8 - 8 * sizeof(u32)) + +static int rcar_mfis_hwsp_trylock(struct hwspinlock *lock) +{ + struct mfis_priv *priv = lock->priv; + int id = hwlock_to_id(lock) - lock->bank->base_id; + u32 val, reg; + + reg = id * sizeof(u32) + (id < 8 ? MFISLCKR0 : MFISLCKR8_CH_OFS); + val = mfis_read(&priv->common_reg, reg); + return !val; +} + +static void rcar_mfis_hwsp_unlock(struct hwspinlock *lock) +{ + struct mfis_priv *priv = lock->priv; + int id = hwlock_to_id(lock) - lock->bank->base_id; + u32 reg; + + reg = id * sizeof(u32) + (id < 8 ? MFISLCKR0 : MFISLCKR8_CH_OFS); + mfis_write(&priv->common_reg, reg, 0); +} + +static const struct hwspinlock_ops rcar_mfis_hwsp_ops = { + .trylock = rcar_mfis_hwsp_trylock, + .unlock = rcar_mfis_hwsp_unlock, +}; + +/******************************************************** * Mailbox * ********************************************************/ @@ -314,7 +357,7 @@ static int mfis_probe(struct platform_device *pdev) struct mfis_priv *priv; int ret; - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + priv = devm_kzalloc(dev, struct_size(priv, bank.lock, MFIS_NUM_LOCKS), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -333,6 +376,14 @@ static int mfis_probe(struct platform_device *pdev) if (ret) return ret; + for (unsigned int ch = 0; ch < MFIS_NUM_LOCKS; ch++) + priv->bank.lock[ch].priv = priv; + + ret = devm_hwspin_lock_register(dev, &priv->bank, &rcar_mfis_hwsp_ops, + priv->info->hwsp_base_id, MFIS_NUM_LOCKS); + if (ret) + return ret; + return mfis_mb_probe(priv); } @@ -357,6 +408,7 @@ static const struct mfis_info mfis_info_r8a78000_scp = { .mb_tx_uses_eicr = true, .mb_channels_are_unidir = true, .mb_calc_reg = mfis_mb_r8a78000_calc_reg, + .hwsp_base_id = MFIS_NUM_LOCKS, }; static const struct of_device_id mfis_mfd_of_match[] = { |
