|
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