|
32 | 32 | #define SVC_I3C_MCONFIG_ODBAUD(x) FIELD_PREP(GENMASK(23, 16), (x))
|
33 | 33 | #define SVC_I3C_MCONFIG_ODHPP(x) FIELD_PREP(BIT(24), (x))
|
34 | 34 | #define SVC_I3C_MCONFIG_SKEW(x) FIELD_PREP(GENMASK(27, 25), (x))
|
| 35 | +#define SVC_I3C_MCONFIG_SKEW_MASK GENMASK(27, 25) |
35 | 36 | #define SVC_I3C_MCONFIG_I2CBAUD(x) FIELD_PREP(GENMASK(31, 28), (x))
|
36 | 37 |
|
37 | 38 | #define SVC_I3C_MCTRL 0x084
|
|
150 | 151 | * If it is a true SlvStart, the MSTATUS state is SLVREQ.
|
151 | 152 | */
|
152 | 153 | #define SVC_I3C_QUIRK_FALSE_SLVSTART BIT(1)
|
| 154 | +/* |
| 155 | + * SVC_I3C_QUIRK_DAA_CORRUPT: |
| 156 | + * When MCONFIG.SKEW=0 and MCONFIG.ODHPP=0, the ENTDAA transaction gets |
| 157 | + * corrupted and results in a no repeated-start condition at the end of |
| 158 | + * address assignment. |
| 159 | + * Workaround: |
| 160 | + * Set MCONFIG.SKEW to 1 before initiating the DAA process. After the DAA |
| 161 | + * process is completed, return MCONFIG.SKEW to its previous value. |
| 162 | + */ |
| 163 | +#define SVC_I3C_QUIRK_DAA_CORRUPT BIT(2) |
153 | 164 |
|
154 | 165 | struct svc_i3c_cmd {
|
155 | 166 | u8 addr;
|
@@ -259,6 +270,13 @@ static inline bool svc_has_quirk(struct svc_i3c_master *master, u32 quirk)
|
259 | 270 | return (master->drvdata->quirks & quirk);
|
260 | 271 | }
|
261 | 272 |
|
| 273 | +static inline bool svc_has_daa_corrupt(struct svc_i3c_master *master) |
| 274 | +{ |
| 275 | + return ((master->drvdata->quirks & SVC_I3C_QUIRK_DAA_CORRUPT) && |
| 276 | + !(master->mctrl_config & |
| 277 | + (SVC_I3C_MCONFIG_SKEW_MASK | SVC_I3C_MCONFIG_ODHPP(1)))); |
| 278 | +} |
| 279 | + |
262 | 280 | static inline bool is_events_enabled(struct svc_i3c_master *master, u32 mask)
|
263 | 281 | {
|
264 | 282 | return !!(master->enabled_events & mask);
|
@@ -1146,7 +1164,16 @@ static int svc_i3c_master_do_daa(struct i3c_master_controller *m)
|
1146 | 1164 | }
|
1147 | 1165 |
|
1148 | 1166 | spin_lock_irqsave(&master->xferqueue.lock, flags);
|
| 1167 | + |
| 1168 | + if (svc_has_daa_corrupt(master)) |
| 1169 | + writel(master->mctrl_config | SVC_I3C_MCONFIG_SKEW(1), |
| 1170 | + master->regs + SVC_I3C_MCONFIG); |
| 1171 | + |
1149 | 1172 | ret = svc_i3c_master_do_daa_locked(master, addrs, &dev_nb);
|
| 1173 | + |
| 1174 | + if (svc_has_daa_corrupt(master)) |
| 1175 | + writel(master->mctrl_config, master->regs + SVC_I3C_MCONFIG); |
| 1176 | + |
1150 | 1177 | spin_unlock_irqrestore(&master->xferqueue.lock, flags);
|
1151 | 1178 |
|
1152 | 1179 | svc_i3c_master_clear_merrwarn(master);
|
@@ -2033,7 +2060,8 @@ static const struct dev_pm_ops svc_i3c_pm_ops = {
|
2033 | 2060 |
|
2034 | 2061 | static const struct svc_i3c_drvdata npcm845_drvdata = {
|
2035 | 2062 | .quirks = SVC_I3C_QUIRK_FIFO_EMPTY |
|
2036 |
| - SVC_I3C_QUIRK_FALSE_SLVSTART, |
| 2063 | + SVC_I3C_QUIRK_FALSE_SLVSTART | |
| 2064 | + SVC_I3C_QUIRK_DAA_CORRUPT, |
2037 | 2065 | };
|
2038 | 2066 |
|
2039 | 2067 | static const struct svc_i3c_drvdata svc_default_drvdata = {};
|
|
0 commit comments