I3C for 6.5
Drivers: - svc: fix suspend/resume on some platforms, fix locking issues -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEBqsFVZXh8s/0O5JiY6TcMGxwOjIFAmSh880ACgkQY6TcMGxw OjJJlA//RjLxovfn5L+i2L5AZRKzvtXDeFXm+mt8UJIg6mYsolzaoo1TEaCsD2kf Ugwc57Ll355PrDi9w8qSl4dbVNfpF4c1jZg9dUm2LhdZvZ5A+OK/2Le1DvSZt9JN kQiTkWW052ZJIPw9G2d8G/JX1nuwgiObnUEvadI1LdTqFf+HZOgz7ULLbgIQ6/p+ hySOF+GAPO88KSovH5KR6N/KOMvBJtig4xzeNpGFXWhTmLEdLlKHj7aZzfU4NClP AjTnyha+p+LUQLDzWZwDQgf6cliKEDj8E8vPfPvO7Ch0FiMeo47oFIRqcK4MLp/7 NyGJWSadurq8bOF9BvYJbJoaGyYXn+lJUf8/Qczf6AXXKELdpPxFZNEBYf71bR+s /7o2UZiTj18QJxAFWugx2i3elPi9Qt/YWeyJ8TUGUs9cVZqgvEsM6rkjP7SLe1Ml JJTQhQVbTKZZ6R/gVQGGJoFWjDGU2PAwUvLXjOddaGHHCpy/tALVrP0L2l2B7Z2i D9vhmWAM0vYAsTVPsAk53OLuoKF7qMIEkK5smp7J4skmz3ozQi3FUAF7QUyHikwh IqkWC7dbfd9TzwJ/dDi8Hx6Z2Sr+ONGlS1nun0aFwNHje21ZbjSvnC2T/m9PVeuU AjXx9dlz8tDsmtf2Z46lC1DcUq2XwmQXZCsutvaWqd3ZzwK0X3I= =b+Rf -----END PGP SIGNATURE----- Merge tag 'i3c/for-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux Pull i3c updates from Alexandre Belloni: - svc: fix suspend/resume on some platforms, fix locking issues * tag 'i3c/for-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux: i3c: master: svc: add NACK check after start byte sent i3c: master: svc: fix cpu schedule in spin lock i3c: master: svc: fix i3c suspend/resume issue
This commit is contained in:
commit
a74195876b
@ -92,6 +92,7 @@
|
||||
#define SVC_I3C_MINTCLR 0x094
|
||||
#define SVC_I3C_MINTMASKED 0x098
|
||||
#define SVC_I3C_MERRWARN 0x09C
|
||||
#define SVC_I3C_MERRWARN_NACK BIT(2)
|
||||
#define SVC_I3C_MDMACTRL 0x0A0
|
||||
#define SVC_I3C_MDATACTRL 0x0AC
|
||||
#define SVC_I3C_MDATACTRL_FLUSHTB BIT(0)
|
||||
@ -145,6 +146,11 @@ struct svc_i3c_xfer {
|
||||
struct svc_i3c_cmd cmds[];
|
||||
};
|
||||
|
||||
struct svc_i3c_regs_save {
|
||||
u32 mconfig;
|
||||
u32 mdynaddr;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct svc_i3c_master - Silvaco I3C Master structure
|
||||
* @base: I3C master controller
|
||||
@ -173,6 +179,7 @@ struct svc_i3c_master {
|
||||
struct i3c_master_controller base;
|
||||
struct device *dev;
|
||||
void __iomem *regs;
|
||||
struct svc_i3c_regs_save saved_regs;
|
||||
u32 free_slots;
|
||||
u8 addrs[SVC_I3C_MAX_DEVS];
|
||||
struct i3c_dev_desc *descs[SVC_I3C_MAX_DEVS];
|
||||
@ -1008,6 +1015,11 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
|
||||
if (ret)
|
||||
goto emit_stop;
|
||||
|
||||
if (readl(master->regs + SVC_I3C_MERRWARN) & SVC_I3C_MERRWARN_NACK) {
|
||||
ret = -ENXIO;
|
||||
goto emit_stop;
|
||||
}
|
||||
|
||||
if (rnw)
|
||||
ret = svc_i3c_master_read(master, in, xfer_len);
|
||||
else
|
||||
@ -1090,12 +1102,6 @@ static void svc_i3c_master_start_xfer_locked(struct svc_i3c_master *master)
|
||||
if (!xfer)
|
||||
return;
|
||||
|
||||
ret = pm_runtime_resume_and_get(master->dev);
|
||||
if (ret < 0) {
|
||||
dev_err(master->dev, "<%s> Cannot get runtime PM.\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
svc_i3c_master_clear_merrwarn(master);
|
||||
svc_i3c_master_flush_fifo(master);
|
||||
|
||||
@ -1110,9 +1116,6 @@ static void svc_i3c_master_start_xfer_locked(struct svc_i3c_master *master)
|
||||
break;
|
||||
}
|
||||
|
||||
pm_runtime_mark_last_busy(master->dev);
|
||||
pm_runtime_put_autosuspend(master->dev);
|
||||
|
||||
xfer->ret = ret;
|
||||
complete(&xfer->comp);
|
||||
|
||||
@ -1133,6 +1136,13 @@ static void svc_i3c_master_enqueue_xfer(struct svc_i3c_master *master,
|
||||
struct svc_i3c_xfer *xfer)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_resume_and_get(master->dev);
|
||||
if (ret < 0) {
|
||||
dev_err(master->dev, "<%s> Cannot get runtime PM.\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
init_completion(&xfer->comp);
|
||||
spin_lock_irqsave(&master->xferqueue.lock, flags);
|
||||
@ -1143,6 +1153,9 @@ static void svc_i3c_master_enqueue_xfer(struct svc_i3c_master *master,
|
||||
svc_i3c_master_start_xfer_locked(master);
|
||||
}
|
||||
spin_unlock_irqrestore(&master->xferqueue.lock, flags);
|
||||
|
||||
pm_runtime_mark_last_busy(master->dev);
|
||||
pm_runtime_put_autosuspend(master->dev);
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -1579,10 +1592,28 @@ static void svc_i3c_master_remove(struct platform_device *pdev)
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
}
|
||||
|
||||
static void svc_i3c_save_regs(struct svc_i3c_master *master)
|
||||
{
|
||||
master->saved_regs.mconfig = readl(master->regs + SVC_I3C_MCONFIG);
|
||||
master->saved_regs.mdynaddr = readl(master->regs + SVC_I3C_MDYNADDR);
|
||||
}
|
||||
|
||||
static void svc_i3c_restore_regs(struct svc_i3c_master *master)
|
||||
{
|
||||
if (readl(master->regs + SVC_I3C_MDYNADDR) !=
|
||||
master->saved_regs.mdynaddr) {
|
||||
writel(master->saved_regs.mconfig,
|
||||
master->regs + SVC_I3C_MCONFIG);
|
||||
writel(master->saved_regs.mdynaddr,
|
||||
master->regs + SVC_I3C_MDYNADDR);
|
||||
}
|
||||
}
|
||||
|
||||
static int __maybe_unused svc_i3c_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct svc_i3c_master *master = dev_get_drvdata(dev);
|
||||
|
||||
svc_i3c_save_regs(master);
|
||||
svc_i3c_master_unprepare_clks(master);
|
||||
pinctrl_pm_select_sleep_state(dev);
|
||||
|
||||
@ -1596,6 +1627,8 @@ static int __maybe_unused svc_i3c_runtime_resume(struct device *dev)
|
||||
pinctrl_pm_select_default_state(dev);
|
||||
svc_i3c_master_prepare_clks(master);
|
||||
|
||||
svc_i3c_restore_regs(master);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user