|
113 | 113 | #define SVC_I3C_MWDATAHE 0x0BC |
114 | 114 | #define SVC_I3C_MRDATAB 0x0C0 |
115 | 115 | #define SVC_I3C_MRDATAH 0x0C8 |
| 116 | +#define SVC_I3C_MWDATAB1 0x0CC |
116 | 117 | #define SVC_I3C_MWMSG_SDR 0x0D0 |
117 | 118 | #define SVC_I3C_MRMSG_SDR 0x0D4 |
118 | 119 | #define SVC_I3C_MWMSG_DDR 0x0D8 |
|
133 | 134 | #define SVC_I3C_EVENT_IBI GENMASK(7, 0) |
134 | 135 | #define SVC_I3C_EVENT_HOTJOIN BIT(31) |
135 | 136 |
|
| 137 | +/* |
| 138 | + * SVC_I3C_QUIRK_FIFO_EMPTY: |
| 139 | + * I3C HW stalls the write transfer if the transmit FIFO becomes empty, |
| 140 | + * when new data is written to FIFO, I3C HW resumes the transfer but |
| 141 | + * the first transmitted data bit may have the wrong value. |
| 142 | + * Workaround: |
| 143 | + * Fill the FIFO in advance to prevent FIFO from becoming empty. |
| 144 | + */ |
| 145 | +#define SVC_I3C_QUIRK_FIFO_EMPTY BIT(0) |
| 146 | + |
136 | 147 | struct svc_i3c_cmd { |
137 | 148 | u8 addr; |
138 | 149 | bool rnw; |
@@ -236,6 +247,11 @@ struct svc_i3c_i2c_dev_data { |
236 | 247 | struct i3c_generic_ibi_pool *ibi_pool; |
237 | 248 | }; |
238 | 249 |
|
| 250 | +static inline bool svc_has_quirk(struct svc_i3c_master *master, u32 quirk) |
| 251 | +{ |
| 252 | + return (master->drvdata->quirks & quirk); |
| 253 | +} |
| 254 | + |
239 | 255 | static inline bool is_events_enabled(struct svc_i3c_master *master, u32 mask) |
240 | 256 | { |
241 | 257 | return !!(master->enabled_events & mask); |
@@ -894,7 +910,7 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master, |
894 | 910 | u8 *addrs, unsigned int *count) |
895 | 911 | { |
896 | 912 | u64 prov_id[SVC_I3C_MAX_DEVS] = {}, nacking_prov_id = 0; |
897 | | - unsigned int dev_nb = 0, last_addr = 0; |
| 913 | + unsigned int dev_nb = 0, last_addr = 0, dyn_addr; |
898 | 914 | u32 reg; |
899 | 915 | int ret, i; |
900 | 916 |
|
@@ -939,6 +955,25 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master, |
939 | 955 | if (SVC_I3C_MSTATUS_RXPEND(reg)) { |
940 | 956 | u8 data[6]; |
941 | 957 |
|
| 958 | + /* |
| 959 | + * One slave sends its ID to request for address assignment, |
| 960 | + * prefilling the dynamic address can reduce SCL clock stalls |
| 961 | + * and also fix the SVC_I3C_QUIRK_FIFO_EMPTY quirk. |
| 962 | + * |
| 963 | + * Ideally, prefilling before the processDAA command is better. |
| 964 | + * However, it requires an additional check to write the dyn_addr |
| 965 | + * at the right time because the driver needs to write the processDAA |
| 966 | + * command twice for one assignment. |
| 967 | + * Prefilling here is safe and efficient because the FIFO starts |
| 968 | + * filling within a few hundred nanoseconds, which is significantly |
| 969 | + * faster compared to the 64 SCL clock cycles. |
| 970 | + */ |
| 971 | + dyn_addr = i3c_master_get_free_addr(&master->base, last_addr + 1); |
| 972 | + if (dyn_addr < 0) |
| 973 | + return -ENOSPC; |
| 974 | + |
| 975 | + writel(dyn_addr, master->regs + SVC_I3C_MWDATAB); |
| 976 | + |
942 | 977 | /* |
943 | 978 | * We only care about the 48-bit provisioned ID yet to |
944 | 979 | * be sure a device does not nack an address twice. |
@@ -1017,21 +1052,16 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master, |
1017 | 1052 | if (ret) |
1018 | 1053 | break; |
1019 | 1054 |
|
1020 | | - /* Give the slave device a suitable dynamic address */ |
1021 | | - ret = i3c_master_get_free_addr(&master->base, last_addr + 1); |
1022 | | - if (ret < 0) |
1023 | | - break; |
1024 | | - |
1025 | | - addrs[dev_nb] = ret; |
| 1055 | + addrs[dev_nb] = dyn_addr; |
1026 | 1056 | dev_dbg(master->dev, "DAA: device %d assigned to 0x%02x\n", |
1027 | 1057 | dev_nb, addrs[dev_nb]); |
1028 | | - |
1029 | | - writel(addrs[dev_nb], master->regs + SVC_I3C_MWDATAB); |
1030 | 1058 | last_addr = addrs[dev_nb++]; |
1031 | 1059 | } |
1032 | 1060 |
|
1033 | 1061 | /* Need manual issue STOP except for Complete condition */ |
1034 | 1062 | svc_i3c_master_emit_stop(master); |
| 1063 | + svc_i3c_master_flush_fifo(master); |
| 1064 | + |
1035 | 1065 | return ret; |
1036 | 1066 | } |
1037 | 1067 |
|
@@ -1228,6 +1258,24 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master, |
1228 | 1258 | SVC_I3C_MCTRL_RDTERM(*actual_len), |
1229 | 1259 | master->regs + SVC_I3C_MCTRL); |
1230 | 1260 |
|
| 1261 | + /* |
| 1262 | + * The entire transaction can consist of multiple write transfers. |
| 1263 | + * Prefilling before EmitStartAddr causes the data to be emitted |
| 1264 | + * immediately, becoming part of the previous transfer. |
| 1265 | + * The only way to work around this hardware issue is to let the |
| 1266 | + * FIFO start filling as soon as possible after EmitStartAddr. |
| 1267 | + */ |
| 1268 | + if (svc_has_quirk(master, SVC_I3C_QUIRK_FIFO_EMPTY) && !rnw && xfer_len) { |
| 1269 | + u32 end = xfer_len > SVC_I3C_FIFO_SIZE ? 0 : SVC_I3C_MWDATAB_END; |
| 1270 | + u32 len = min_t(u32, xfer_len, SVC_I3C_FIFO_SIZE); |
| 1271 | + |
| 1272 | + writesb(master->regs + SVC_I3C_MWDATAB1, out, len - 1); |
| 1273 | + /* Mark END bit if this is the last byte */ |
| 1274 | + writel(out[len - 1] | end, master->regs + SVC_I3C_MWDATAB); |
| 1275 | + xfer_len -= len; |
| 1276 | + out += len; |
| 1277 | + } |
| 1278 | + |
1231 | 1279 | ret = readl_poll_timeout(master->regs + SVC_I3C_MSTATUS, reg, |
1232 | 1280 | SVC_I3C_MSTATUS_MCTRLDONE(reg), 0, 1000); |
1233 | 1281 | if (ret) |
@@ -1316,6 +1364,7 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master, |
1316 | 1364 | emit_stop: |
1317 | 1365 | svc_i3c_master_emit_stop(master); |
1318 | 1366 | svc_i3c_master_clear_merrwarn(master); |
| 1367 | + svc_i3c_master_flush_fifo(master); |
1319 | 1368 |
|
1320 | 1369 | return ret; |
1321 | 1370 | } |
@@ -1970,7 +2019,9 @@ static const struct dev_pm_ops svc_i3c_pm_ops = { |
1970 | 2019 | svc_i3c_runtime_resume, NULL) |
1971 | 2020 | }; |
1972 | 2021 |
|
1973 | | -static const struct svc_i3c_drvdata npcm845_drvdata = {}; |
| 2022 | +static const struct svc_i3c_drvdata npcm845_drvdata = { |
| 2023 | + .quirks = SVC_I3C_QUIRK_FIFO_EMPTY, |
| 2024 | +}; |
1974 | 2025 |
|
1975 | 2026 | static const struct svc_i3c_drvdata svc_default_drvdata = {}; |
1976 | 2027 |
|
|
0 commit comments