mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
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>
This commit is contained in:
parent
529b0be30b
commit
504e3ae911
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -86,6 +97,38 @@ static void mfis_write(struct mfis_reg *mreg, u32 reg, u32 val)
|
|||
raw_spin_unlock_irqrestore(&priv->unprotect_lock, flags);
|
||||
}
|
||||
|
||||
/********************************************************
|
||||
* 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[] = {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user