Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+42 -9
+42 -9
drivers/i3c/master/svc-i3c-master.c
··· 92 92 #define SVC_I3C_MINTCLR 0x094 93 93 #define SVC_I3C_MINTMASKED 0x098 94 94 #define SVC_I3C_MERRWARN 0x09C 95 + #define SVC_I3C_MERRWARN_NACK BIT(2) 95 96 #define SVC_I3C_MDMACTRL 0x0A0 96 97 #define SVC_I3C_MDATACTRL 0x0AC 97 98 #define SVC_I3C_MDATACTRL_FLUSHTB BIT(0) ··· 146 145 struct svc_i3c_cmd cmds[]; 147 146 }; 148 147 148 + struct svc_i3c_regs_save { 149 + u32 mconfig; 150 + u32 mdynaddr; 151 + }; 152 + 149 153 /** 150 154 * struct svc_i3c_master - Silvaco I3C Master structure 151 155 * @base: I3C master controller ··· 179 173 struct i3c_master_controller base; 180 174 struct device *dev; 181 175 void __iomem *regs; 176 + struct svc_i3c_regs_save saved_regs; 182 177 u32 free_slots; 183 178 u8 addrs[SVC_I3C_MAX_DEVS]; 184 179 struct i3c_dev_desc *descs[SVC_I3C_MAX_DEVS]; ··· 1015 1008 if (ret) 1016 1009 goto emit_stop; 1017 1010 1011 + if (readl(master->regs + SVC_I3C_MERRWARN) & SVC_I3C_MERRWARN_NACK) { 1012 + ret = -ENXIO; 1013 + goto emit_stop; 1014 + } 1015 + 1018 1016 if (rnw) 1019 1017 ret = svc_i3c_master_read(master, in, xfer_len); 1020 1018 else ··· 1102 1090 if (!xfer) 1103 1091 return; 1104 1092 1105 - ret = pm_runtime_resume_and_get(master->dev); 1106 - if (ret < 0) { 1107 - dev_err(master->dev, "<%s> Cannot get runtime PM.\n", __func__); 1108 - return; 1109 - } 1110 - 1111 1093 svc_i3c_master_clear_merrwarn(master); 1112 1094 svc_i3c_master_flush_fifo(master); 1113 1095 ··· 1115 1109 if (ret) 1116 1110 break; 1117 1111 } 1118 - 1119 - pm_runtime_mark_last_busy(master->dev); 1120 - pm_runtime_put_autosuspend(master->dev); 1121 1112 1122 1113 xfer->ret = ret; 1123 1114 complete(&xfer->comp); ··· 1136 1133 struct svc_i3c_xfer *xfer) 1137 1134 { 1138 1135 unsigned long flags; 1136 + int ret; 1137 + 1138 + ret = pm_runtime_resume_and_get(master->dev); 1139 + if (ret < 0) { 1140 + dev_err(master->dev, "<%s> Cannot get runtime PM.\n", __func__); 1141 + return; 1142 + } 1139 1143 1140 1144 init_completion(&xfer->comp); 1141 1145 spin_lock_irqsave(&master->xferqueue.lock, flags); ··· 1153 1143 svc_i3c_master_start_xfer_locked(master); 1154 1144 } 1155 1145 spin_unlock_irqrestore(&master->xferqueue.lock, flags); 1146 + 1147 + pm_runtime_mark_last_busy(master->dev); 1148 + pm_runtime_put_autosuspend(master->dev); 1156 1149 } 1157 1150 1158 1151 static bool ··· 1592 1579 pm_runtime_disable(&pdev->dev); 1593 1580 } 1594 1581 1582 + static void svc_i3c_save_regs(struct svc_i3c_master *master) 1583 + { 1584 + master->saved_regs.mconfig = readl(master->regs + SVC_I3C_MCONFIG); 1585 + master->saved_regs.mdynaddr = readl(master->regs + SVC_I3C_MDYNADDR); 1586 + } 1587 + 1588 + static void svc_i3c_restore_regs(struct svc_i3c_master *master) 1589 + { 1590 + if (readl(master->regs + SVC_I3C_MDYNADDR) != 1591 + master->saved_regs.mdynaddr) { 1592 + writel(master->saved_regs.mconfig, 1593 + master->regs + SVC_I3C_MCONFIG); 1594 + writel(master->saved_regs.mdynaddr, 1595 + master->regs + SVC_I3C_MDYNADDR); 1596 + } 1597 + } 1598 + 1595 1599 static int __maybe_unused svc_i3c_runtime_suspend(struct device *dev) 1596 1600 { 1597 1601 struct svc_i3c_master *master = dev_get_drvdata(dev); 1598 1602 1603 + svc_i3c_save_regs(master); 1599 1604 svc_i3c_master_unprepare_clks(master); 1600 1605 pinctrl_pm_select_sleep_state(dev); 1601 1606 ··· 1626 1595 1627 1596 pinctrl_pm_select_default_state(dev); 1628 1597 svc_i3c_master_prepare_clks(master); 1598 + 1599 + svc_i3c_restore_regs(master); 1629 1600 1630 1601 return 0; 1631 1602 }