1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (c) 2018 Synopsys, Inc. and/or its affiliates. |
4 | * |
5 | * Author: Vitor Soares <vitor.soares@synopsys.com> |
6 | */ |
7 | |
8 | #include <linux/bitops.h> |
9 | #include <linux/clk.h> |
10 | #include <linux/completion.h> |
11 | #include <linux/err.h> |
12 | #include <linux/errno.h> |
13 | #include <linux/i3c/master.h> |
14 | #include <linux/interrupt.h> |
15 | #include <linux/ioport.h> |
16 | #include <linux/iopoll.h> |
17 | #include <linux/list.h> |
18 | #include <linux/module.h> |
19 | #include <linux/of.h> |
20 | #include <linux/platform_device.h> |
21 | #include <linux/reset.h> |
22 | #include <linux/slab.h> |
23 | |
24 | #include "dw-i3c-master.h" |
25 | |
26 | #define DEVICE_CTRL 0x0 |
27 | #define DEV_CTRL_ENABLE BIT(31) |
28 | #define DEV_CTRL_RESUME BIT(30) |
29 | #define DEV_CTRL_HOT_JOIN_NACK BIT(8) |
30 | #define DEV_CTRL_I2C_SLAVE_PRESENT BIT(7) |
31 | |
32 | #define DEVICE_ADDR 0x4 |
33 | #define DEV_ADDR_DYNAMIC_ADDR_VALID BIT(31) |
34 | #define DEV_ADDR_DYNAMIC(x) (((x) << 16) & GENMASK(22, 16)) |
35 | |
36 | #define HW_CAPABILITY 0x8 |
37 | #define COMMAND_QUEUE_PORT 0xc |
38 | #define COMMAND_PORT_TOC BIT(30) |
39 | #define COMMAND_PORT_READ_TRANSFER BIT(28) |
40 | #define COMMAND_PORT_SDAP BIT(27) |
41 | #define COMMAND_PORT_ROC BIT(26) |
42 | #define COMMAND_PORT_SPEED(x) (((x) << 21) & GENMASK(23, 21)) |
43 | #define COMMAND_PORT_DEV_INDEX(x) (((x) << 16) & GENMASK(20, 16)) |
44 | #define COMMAND_PORT_CP BIT(15) |
45 | #define COMMAND_PORT_CMD(x) (((x) << 7) & GENMASK(14, 7)) |
46 | #define COMMAND_PORT_TID(x) (((x) << 3) & GENMASK(6, 3)) |
47 | |
48 | #define COMMAND_PORT_ARG_DATA_LEN(x) (((x) << 16) & GENMASK(31, 16)) |
49 | #define COMMAND_PORT_ARG_DATA_LEN_MAX 65536 |
50 | #define COMMAND_PORT_TRANSFER_ARG 0x01 |
51 | |
52 | #define COMMAND_PORT_SDA_DATA_BYTE_3(x) (((x) << 24) & GENMASK(31, 24)) |
53 | #define COMMAND_PORT_SDA_DATA_BYTE_2(x) (((x) << 16) & GENMASK(23, 16)) |
54 | #define COMMAND_PORT_SDA_DATA_BYTE_1(x) (((x) << 8) & GENMASK(15, 8)) |
55 | #define COMMAND_PORT_SDA_BYTE_STRB_3 BIT(5) |
56 | #define COMMAND_PORT_SDA_BYTE_STRB_2 BIT(4) |
57 | #define COMMAND_PORT_SDA_BYTE_STRB_1 BIT(3) |
58 | #define COMMAND_PORT_SHORT_DATA_ARG 0x02 |
59 | |
60 | #define COMMAND_PORT_DEV_COUNT(x) (((x) << 21) & GENMASK(25, 21)) |
61 | #define COMMAND_PORT_ADDR_ASSGN_CMD 0x03 |
62 | |
63 | #define RESPONSE_QUEUE_PORT 0x10 |
64 | #define RESPONSE_PORT_ERR_STATUS(x) (((x) & GENMASK(31, 28)) >> 28) |
65 | #define RESPONSE_NO_ERROR 0 |
66 | #define RESPONSE_ERROR_CRC 1 |
67 | #define RESPONSE_ERROR_PARITY 2 |
68 | #define RESPONSE_ERROR_FRAME 3 |
69 | #define RESPONSE_ERROR_IBA_NACK 4 |
70 | #define RESPONSE_ERROR_ADDRESS_NACK 5 |
71 | #define RESPONSE_ERROR_OVER_UNDER_FLOW 6 |
72 | #define RESPONSE_ERROR_TRANSF_ABORT 8 |
73 | #define RESPONSE_ERROR_I2C_W_NACK_ERR 9 |
74 | #define RESPONSE_PORT_TID(x) (((x) & GENMASK(27, 24)) >> 24) |
75 | #define RESPONSE_PORT_DATA_LEN(x) ((x) & GENMASK(15, 0)) |
76 | |
77 | #define RX_TX_DATA_PORT 0x14 |
78 | #define IBI_QUEUE_STATUS 0x18 |
79 | #define IBI_QUEUE_STATUS_IBI_ID(x) (((x) & GENMASK(15, 8)) >> 8) |
80 | #define IBI_QUEUE_STATUS_DATA_LEN(x) ((x) & GENMASK(7, 0)) |
81 | #define IBI_QUEUE_IBI_ADDR(x) (IBI_QUEUE_STATUS_IBI_ID(x) >> 1) |
82 | #define IBI_QUEUE_IBI_RNW(x) (IBI_QUEUE_STATUS_IBI_ID(x) & BIT(0)) |
83 | #define IBI_TYPE_MR(x) \ |
84 | ((IBI_QUEUE_IBI_ADDR(x) != I3C_HOT_JOIN_ADDR) && !IBI_QUEUE_IBI_RNW(x)) |
85 | #define IBI_TYPE_HJ(x) \ |
86 | ((IBI_QUEUE_IBI_ADDR(x) == I3C_HOT_JOIN_ADDR) && !IBI_QUEUE_IBI_RNW(x)) |
87 | #define IBI_TYPE_SIRQ(x) \ |
88 | ((IBI_QUEUE_IBI_ADDR(x) != I3C_HOT_JOIN_ADDR) && IBI_QUEUE_IBI_RNW(x)) |
89 | |
90 | #define QUEUE_THLD_CTRL 0x1c |
91 | #define QUEUE_THLD_CTRL_IBI_STAT_MASK GENMASK(31, 24) |
92 | #define QUEUE_THLD_CTRL_IBI_STAT(x) (((x) - 1) << 24) |
93 | #define QUEUE_THLD_CTRL_IBI_DATA_MASK GENMASK(20, 16) |
94 | #define QUEUE_THLD_CTRL_IBI_DATA(x) ((x) << 16) |
95 | #define QUEUE_THLD_CTRL_RESP_BUF_MASK GENMASK(15, 8) |
96 | #define QUEUE_THLD_CTRL_RESP_BUF(x) (((x) - 1) << 8) |
97 | |
98 | #define DATA_BUFFER_THLD_CTRL 0x20 |
99 | #define DATA_BUFFER_THLD_CTRL_RX_BUF GENMASK(11, 8) |
100 | |
101 | #define IBI_QUEUE_CTRL 0x24 |
102 | #define IBI_MR_REQ_REJECT 0x2C |
103 | #define IBI_SIR_REQ_REJECT 0x30 |
104 | #define IBI_REQ_REJECT_ALL GENMASK(31, 0) |
105 | |
106 | #define RESET_CTRL 0x34 |
107 | #define RESET_CTRL_IBI_QUEUE BIT(5) |
108 | #define RESET_CTRL_RX_FIFO BIT(4) |
109 | #define RESET_CTRL_TX_FIFO BIT(3) |
110 | #define RESET_CTRL_RESP_QUEUE BIT(2) |
111 | #define RESET_CTRL_CMD_QUEUE BIT(1) |
112 | #define RESET_CTRL_SOFT BIT(0) |
113 | |
114 | #define SLV_EVENT_CTRL 0x38 |
115 | #define INTR_STATUS 0x3c |
116 | #define INTR_STATUS_EN 0x40 |
117 | #define INTR_SIGNAL_EN 0x44 |
118 | #define INTR_FORCE 0x48 |
119 | #define INTR_BUSOWNER_UPDATE_STAT BIT(13) |
120 | #define INTR_IBI_UPDATED_STAT BIT(12) |
121 | #define INTR_READ_REQ_RECV_STAT BIT(11) |
122 | #define INTR_DEFSLV_STAT BIT(10) |
123 | #define INTR_TRANSFER_ERR_STAT BIT(9) |
124 | #define INTR_DYN_ADDR_ASSGN_STAT BIT(8) |
125 | #define INTR_CCC_UPDATED_STAT BIT(6) |
126 | #define INTR_TRANSFER_ABORT_STAT BIT(5) |
127 | #define INTR_RESP_READY_STAT BIT(4) |
128 | #define INTR_CMD_QUEUE_READY_STAT BIT(3) |
129 | #define INTR_IBI_THLD_STAT BIT(2) |
130 | #define INTR_RX_THLD_STAT BIT(1) |
131 | #define INTR_TX_THLD_STAT BIT(0) |
132 | #define INTR_ALL (INTR_BUSOWNER_UPDATE_STAT | \ |
133 | INTR_IBI_UPDATED_STAT | \ |
134 | INTR_READ_REQ_RECV_STAT | \ |
135 | INTR_DEFSLV_STAT | \ |
136 | INTR_TRANSFER_ERR_STAT | \ |
137 | INTR_DYN_ADDR_ASSGN_STAT | \ |
138 | INTR_CCC_UPDATED_STAT | \ |
139 | INTR_TRANSFER_ABORT_STAT | \ |
140 | INTR_RESP_READY_STAT | \ |
141 | INTR_CMD_QUEUE_READY_STAT | \ |
142 | INTR_IBI_THLD_STAT | \ |
143 | INTR_TX_THLD_STAT | \ |
144 | INTR_RX_THLD_STAT) |
145 | |
146 | #define INTR_MASTER_MASK (INTR_TRANSFER_ERR_STAT | \ |
147 | INTR_RESP_READY_STAT) |
148 | |
149 | #define QUEUE_STATUS_LEVEL 0x4c |
150 | #define QUEUE_STATUS_IBI_STATUS_CNT(x) (((x) & GENMASK(28, 24)) >> 24) |
151 | #define QUEUE_STATUS_IBI_BUF_BLR(x) (((x) & GENMASK(23, 16)) >> 16) |
152 | #define QUEUE_STATUS_LEVEL_RESP(x) (((x) & GENMASK(15, 8)) >> 8) |
153 | #define QUEUE_STATUS_LEVEL_CMD(x) ((x) & GENMASK(7, 0)) |
154 | |
155 | #define DATA_BUFFER_STATUS_LEVEL 0x50 |
156 | #define DATA_BUFFER_STATUS_LEVEL_TX(x) ((x) & GENMASK(7, 0)) |
157 | |
158 | #define PRESENT_STATE 0x54 |
159 | #define CCC_DEVICE_STATUS 0x58 |
160 | #define DEVICE_ADDR_TABLE_POINTER 0x5c |
161 | #define DEVICE_ADDR_TABLE_DEPTH(x) (((x) & GENMASK(31, 16)) >> 16) |
162 | #define DEVICE_ADDR_TABLE_ADDR(x) ((x) & GENMASK(7, 0)) |
163 | |
164 | #define DEV_CHAR_TABLE_POINTER 0x60 |
165 | #define VENDOR_SPECIFIC_REG_POINTER 0x6c |
166 | #define SLV_PID_VALUE 0x74 |
167 | #define SLV_CHAR_CTRL 0x78 |
168 | #define SLV_MAX_LEN 0x7c |
169 | #define MAX_READ_TURNAROUND 0x80 |
170 | #define MAX_DATA_SPEED 0x84 |
171 | #define SLV_DEBUG_STATUS 0x88 |
172 | #define SLV_INTR_REQ 0x8c |
173 | #define DEVICE_CTRL_EXTENDED 0xb0 |
174 | #define SCL_I3C_OD_TIMING 0xb4 |
175 | #define SCL_I3C_PP_TIMING 0xb8 |
176 | #define SCL_I3C_TIMING_HCNT(x) (((x) << 16) & GENMASK(23, 16)) |
177 | #define SCL_I3C_TIMING_LCNT(x) ((x) & GENMASK(7, 0)) |
178 | #define SCL_I3C_TIMING_CNT_MIN 5 |
179 | |
180 | #define SCL_I2C_FM_TIMING 0xbc |
181 | #define SCL_I2C_FM_TIMING_HCNT(x) (((x) << 16) & GENMASK(31, 16)) |
182 | #define SCL_I2C_FM_TIMING_LCNT(x) ((x) & GENMASK(15, 0)) |
183 | |
184 | #define SCL_I2C_FMP_TIMING 0xc0 |
185 | #define SCL_I2C_FMP_TIMING_HCNT(x) (((x) << 16) & GENMASK(23, 16)) |
186 | #define SCL_I2C_FMP_TIMING_LCNT(x) ((x) & GENMASK(15, 0)) |
187 | |
188 | #define SCL_EXT_LCNT_TIMING 0xc8 |
189 | #define SCL_EXT_LCNT_4(x) (((x) << 24) & GENMASK(31, 24)) |
190 | #define SCL_EXT_LCNT_3(x) (((x) << 16) & GENMASK(23, 16)) |
191 | #define SCL_EXT_LCNT_2(x) (((x) << 8) & GENMASK(15, 8)) |
192 | #define SCL_EXT_LCNT_1(x) ((x) & GENMASK(7, 0)) |
193 | |
194 | #define SCL_EXT_TERMN_LCNT_TIMING 0xcc |
195 | #define BUS_FREE_TIMING 0xd4 |
196 | #define BUS_I3C_MST_FREE(x) ((x) & GENMASK(15, 0)) |
197 | |
198 | #define BUS_IDLE_TIMING 0xd8 |
199 | #define I3C_VER_ID 0xe0 |
200 | #define I3C_VER_TYPE 0xe4 |
201 | #define EXTENDED_CAPABILITY 0xe8 |
202 | #define SLAVE_CONFIG 0xec |
203 | |
204 | #define DEV_ADDR_TABLE_IBI_MDB BIT(12) |
205 | #define DEV_ADDR_TABLE_SIR_REJECT BIT(13) |
206 | #define DEV_ADDR_TABLE_LEGACY_I2C_DEV BIT(31) |
207 | #define DEV_ADDR_TABLE_DYNAMIC_ADDR(x) (((x) << 16) & GENMASK(23, 16)) |
208 | #define DEV_ADDR_TABLE_STATIC_ADDR(x) ((x) & GENMASK(6, 0)) |
209 | #define DEV_ADDR_TABLE_LOC(start, idx) ((start) + ((idx) << 2)) |
210 | |
211 | #define I3C_BUS_SDR1_SCL_RATE 8000000 |
212 | #define I3C_BUS_SDR2_SCL_RATE 6000000 |
213 | #define I3C_BUS_SDR3_SCL_RATE 4000000 |
214 | #define I3C_BUS_SDR4_SCL_RATE 2000000 |
215 | #define I3C_BUS_I2C_FM_TLOW_MIN_NS 1300 |
216 | #define I3C_BUS_I2C_FMP_TLOW_MIN_NS 500 |
217 | #define I3C_BUS_THIGH_MAX_NS 41 |
218 | |
219 | #define XFER_TIMEOUT (msecs_to_jiffies(1000)) |
220 | |
221 | struct dw_i3c_cmd { |
222 | u32 cmd_lo; |
223 | u32 cmd_hi; |
224 | u16 tx_len; |
225 | const void *tx_buf; |
226 | u16 rx_len; |
227 | void *rx_buf; |
228 | u8 error; |
229 | }; |
230 | |
231 | struct dw_i3c_xfer { |
232 | struct list_head node; |
233 | struct completion comp; |
234 | int ret; |
235 | unsigned int ncmds; |
236 | struct dw_i3c_cmd cmds[] __counted_by(ncmds); |
237 | }; |
238 | |
239 | struct dw_i3c_i2c_dev_data { |
240 | u8 index; |
241 | struct i3c_generic_ibi_pool *ibi_pool; |
242 | }; |
243 | |
244 | static u8 even_parity(u8 p) |
245 | { |
246 | p ^= p >> 4; |
247 | p &= 0xf; |
248 | |
249 | return (0x9669 >> p) & 1; |
250 | } |
251 | |
252 | static bool dw_i3c_master_supports_ccc_cmd(struct i3c_master_controller *m, |
253 | const struct i3c_ccc_cmd *cmd) |
254 | { |
255 | if (cmd->ndests > 1) |
256 | return false; |
257 | |
258 | switch (cmd->id) { |
259 | case I3C_CCC_ENEC(true): |
260 | case I3C_CCC_ENEC(false): |
261 | case I3C_CCC_DISEC(true): |
262 | case I3C_CCC_DISEC(false): |
263 | case I3C_CCC_ENTAS(0, true): |
264 | case I3C_CCC_ENTAS(0, false): |
265 | case I3C_CCC_RSTDAA(true): |
266 | case I3C_CCC_RSTDAA(false): |
267 | case I3C_CCC_ENTDAA: |
268 | case I3C_CCC_SETMWL(true): |
269 | case I3C_CCC_SETMWL(false): |
270 | case I3C_CCC_SETMRL(true): |
271 | case I3C_CCC_SETMRL(false): |
272 | case I3C_CCC_ENTHDR(0): |
273 | case I3C_CCC_SETDASA: |
274 | case I3C_CCC_SETNEWDA: |
275 | case I3C_CCC_GETMWL: |
276 | case I3C_CCC_GETMRL: |
277 | case I3C_CCC_GETPID: |
278 | case I3C_CCC_GETBCR: |
279 | case I3C_CCC_GETDCR: |
280 | case I3C_CCC_GETSTATUS: |
281 | case I3C_CCC_GETMXDS: |
282 | case I3C_CCC_GETHDRCAP: |
283 | return true; |
284 | default: |
285 | return false; |
286 | } |
287 | } |
288 | |
289 | static inline struct dw_i3c_master * |
290 | to_dw_i3c_master(struct i3c_master_controller *master) |
291 | { |
292 | return container_of(master, struct dw_i3c_master, base); |
293 | } |
294 | |
295 | static void dw_i3c_master_disable(struct dw_i3c_master *master) |
296 | { |
297 | writel(readl(addr: master->regs + DEVICE_CTRL) & ~DEV_CTRL_ENABLE, |
298 | addr: master->regs + DEVICE_CTRL); |
299 | } |
300 | |
301 | static void dw_i3c_master_enable(struct dw_i3c_master *master) |
302 | { |
303 | writel(readl(addr: master->regs + DEVICE_CTRL) | DEV_CTRL_ENABLE, |
304 | addr: master->regs + DEVICE_CTRL); |
305 | } |
306 | |
307 | static int dw_i3c_master_get_addr_pos(struct dw_i3c_master *master, u8 addr) |
308 | { |
309 | int pos; |
310 | |
311 | for (pos = 0; pos < master->maxdevs; pos++) { |
312 | if (addr == master->devs[pos].addr) |
313 | return pos; |
314 | } |
315 | |
316 | return -EINVAL; |
317 | } |
318 | |
319 | static int dw_i3c_master_get_free_pos(struct dw_i3c_master *master) |
320 | { |
321 | if (!(master->free_pos & GENMASK(master->maxdevs - 1, 0))) |
322 | return -ENOSPC; |
323 | |
324 | return ffs(master->free_pos) - 1; |
325 | } |
326 | |
327 | static void dw_i3c_master_wr_tx_fifo(struct dw_i3c_master *master, |
328 | const u8 *bytes, int nbytes) |
329 | { |
330 | writesl(addr: master->regs + RX_TX_DATA_PORT, buffer: bytes, count: nbytes / 4); |
331 | if (nbytes & 3) { |
332 | u32 tmp = 0; |
333 | |
334 | memcpy(&tmp, bytes + (nbytes & ~3), nbytes & 3); |
335 | writesl(addr: master->regs + RX_TX_DATA_PORT, buffer: &tmp, count: 1); |
336 | } |
337 | } |
338 | |
339 | static void dw_i3c_master_read_fifo(struct dw_i3c_master *master, |
340 | int reg, u8 *bytes, int nbytes) |
341 | { |
342 | readsl(addr: master->regs + reg, buffer: bytes, count: nbytes / 4); |
343 | if (nbytes & 3) { |
344 | u32 tmp; |
345 | |
346 | readsl(addr: master->regs + reg, buffer: &tmp, count: 1); |
347 | memcpy(bytes + (nbytes & ~3), &tmp, nbytes & 3); |
348 | } |
349 | } |
350 | |
351 | static void dw_i3c_master_read_rx_fifo(struct dw_i3c_master *master, |
352 | u8 *bytes, int nbytes) |
353 | { |
354 | return dw_i3c_master_read_fifo(master, RX_TX_DATA_PORT, bytes, nbytes); |
355 | } |
356 | |
357 | static void dw_i3c_master_read_ibi_fifo(struct dw_i3c_master *master, |
358 | u8 *bytes, int nbytes) |
359 | { |
360 | return dw_i3c_master_read_fifo(master, IBI_QUEUE_STATUS, bytes, nbytes); |
361 | } |
362 | |
363 | static struct dw_i3c_xfer * |
364 | dw_i3c_master_alloc_xfer(struct dw_i3c_master *master, unsigned int ncmds) |
365 | { |
366 | struct dw_i3c_xfer *xfer; |
367 | |
368 | xfer = kzalloc(struct_size(xfer, cmds, ncmds), GFP_KERNEL); |
369 | if (!xfer) |
370 | return NULL; |
371 | |
372 | INIT_LIST_HEAD(list: &xfer->node); |
373 | xfer->ncmds = ncmds; |
374 | xfer->ret = -ETIMEDOUT; |
375 | |
376 | return xfer; |
377 | } |
378 | |
379 | static void dw_i3c_master_free_xfer(struct dw_i3c_xfer *xfer) |
380 | { |
381 | kfree(objp: xfer); |
382 | } |
383 | |
384 | static void dw_i3c_master_start_xfer_locked(struct dw_i3c_master *master) |
385 | { |
386 | struct dw_i3c_xfer *xfer = master->xferqueue.cur; |
387 | unsigned int i; |
388 | u32 thld_ctrl; |
389 | |
390 | if (!xfer) |
391 | return; |
392 | |
393 | for (i = 0; i < xfer->ncmds; i++) { |
394 | struct dw_i3c_cmd *cmd = &xfer->cmds[i]; |
395 | |
396 | dw_i3c_master_wr_tx_fifo(master, bytes: cmd->tx_buf, nbytes: cmd->tx_len); |
397 | } |
398 | |
399 | thld_ctrl = readl(addr: master->regs + QUEUE_THLD_CTRL); |
400 | thld_ctrl &= ~QUEUE_THLD_CTRL_RESP_BUF_MASK; |
401 | thld_ctrl |= QUEUE_THLD_CTRL_RESP_BUF(xfer->ncmds); |
402 | writel(val: thld_ctrl, addr: master->regs + QUEUE_THLD_CTRL); |
403 | |
404 | for (i = 0; i < xfer->ncmds; i++) { |
405 | struct dw_i3c_cmd *cmd = &xfer->cmds[i]; |
406 | |
407 | writel(val: cmd->cmd_hi, addr: master->regs + COMMAND_QUEUE_PORT); |
408 | writel(val: cmd->cmd_lo, addr: master->regs + COMMAND_QUEUE_PORT); |
409 | } |
410 | } |
411 | |
412 | static void dw_i3c_master_enqueue_xfer(struct dw_i3c_master *master, |
413 | struct dw_i3c_xfer *xfer) |
414 | { |
415 | unsigned long flags; |
416 | |
417 | init_completion(x: &xfer->comp); |
418 | spin_lock_irqsave(&master->xferqueue.lock, flags); |
419 | if (master->xferqueue.cur) { |
420 | list_add_tail(new: &xfer->node, head: &master->xferqueue.list); |
421 | } else { |
422 | master->xferqueue.cur = xfer; |
423 | dw_i3c_master_start_xfer_locked(master); |
424 | } |
425 | spin_unlock_irqrestore(lock: &master->xferqueue.lock, flags); |
426 | } |
427 | |
428 | static void dw_i3c_master_dequeue_xfer_locked(struct dw_i3c_master *master, |
429 | struct dw_i3c_xfer *xfer) |
430 | { |
431 | if (master->xferqueue.cur == xfer) { |
432 | u32 status; |
433 | |
434 | master->xferqueue.cur = NULL; |
435 | |
436 | writel(RESET_CTRL_RX_FIFO | RESET_CTRL_TX_FIFO | |
437 | RESET_CTRL_RESP_QUEUE | RESET_CTRL_CMD_QUEUE, |
438 | addr: master->regs + RESET_CTRL); |
439 | |
440 | readl_poll_timeout_atomic(master->regs + RESET_CTRL, status, |
441 | !status, 10, 1000000); |
442 | } else { |
443 | list_del_init(entry: &xfer->node); |
444 | } |
445 | } |
446 | |
447 | static void dw_i3c_master_dequeue_xfer(struct dw_i3c_master *master, |
448 | struct dw_i3c_xfer *xfer) |
449 | { |
450 | unsigned long flags; |
451 | |
452 | spin_lock_irqsave(&master->xferqueue.lock, flags); |
453 | dw_i3c_master_dequeue_xfer_locked(master, xfer); |
454 | spin_unlock_irqrestore(lock: &master->xferqueue.lock, flags); |
455 | } |
456 | |
457 | static void dw_i3c_master_end_xfer_locked(struct dw_i3c_master *master, u32 isr) |
458 | { |
459 | struct dw_i3c_xfer *xfer = master->xferqueue.cur; |
460 | int i, ret = 0; |
461 | u32 nresp; |
462 | |
463 | if (!xfer) |
464 | return; |
465 | |
466 | nresp = readl(addr: master->regs + QUEUE_STATUS_LEVEL); |
467 | nresp = QUEUE_STATUS_LEVEL_RESP(nresp); |
468 | |
469 | for (i = 0; i < nresp; i++) { |
470 | struct dw_i3c_cmd *cmd; |
471 | u32 resp; |
472 | |
473 | resp = readl(addr: master->regs + RESPONSE_QUEUE_PORT); |
474 | |
475 | cmd = &xfer->cmds[RESPONSE_PORT_TID(resp)]; |
476 | cmd->rx_len = RESPONSE_PORT_DATA_LEN(resp); |
477 | cmd->error = RESPONSE_PORT_ERR_STATUS(resp); |
478 | if (cmd->rx_len && !cmd->error) |
479 | dw_i3c_master_read_rx_fifo(master, bytes: cmd->rx_buf, |
480 | nbytes: cmd->rx_len); |
481 | } |
482 | |
483 | for (i = 0; i < nresp; i++) { |
484 | switch (xfer->cmds[i].error) { |
485 | case RESPONSE_NO_ERROR: |
486 | break; |
487 | case RESPONSE_ERROR_PARITY: |
488 | case RESPONSE_ERROR_IBA_NACK: |
489 | case RESPONSE_ERROR_TRANSF_ABORT: |
490 | case RESPONSE_ERROR_CRC: |
491 | case RESPONSE_ERROR_FRAME: |
492 | ret = -EIO; |
493 | break; |
494 | case RESPONSE_ERROR_OVER_UNDER_FLOW: |
495 | ret = -ENOSPC; |
496 | break; |
497 | case RESPONSE_ERROR_I2C_W_NACK_ERR: |
498 | case RESPONSE_ERROR_ADDRESS_NACK: |
499 | default: |
500 | ret = -EINVAL; |
501 | break; |
502 | } |
503 | } |
504 | |
505 | xfer->ret = ret; |
506 | complete(&xfer->comp); |
507 | |
508 | if (ret < 0) { |
509 | dw_i3c_master_dequeue_xfer_locked(master, xfer); |
510 | writel(readl(addr: master->regs + DEVICE_CTRL) | DEV_CTRL_RESUME, |
511 | addr: master->regs + DEVICE_CTRL); |
512 | } |
513 | |
514 | xfer = list_first_entry_or_null(&master->xferqueue.list, |
515 | struct dw_i3c_xfer, |
516 | node); |
517 | if (xfer) |
518 | list_del_init(entry: &xfer->node); |
519 | |
520 | master->xferqueue.cur = xfer; |
521 | dw_i3c_master_start_xfer_locked(master); |
522 | } |
523 | |
524 | static int dw_i3c_clk_cfg(struct dw_i3c_master *master) |
525 | { |
526 | unsigned long core_rate, core_period; |
527 | u32 scl_timing; |
528 | u8 hcnt, lcnt; |
529 | |
530 | core_rate = clk_get_rate(clk: master->core_clk); |
531 | if (!core_rate) |
532 | return -EINVAL; |
533 | |
534 | core_period = DIV_ROUND_UP(1000000000, core_rate); |
535 | |
536 | hcnt = DIV_ROUND_UP(I3C_BUS_THIGH_MAX_NS, core_period) - 1; |
537 | if (hcnt < SCL_I3C_TIMING_CNT_MIN) |
538 | hcnt = SCL_I3C_TIMING_CNT_MIN; |
539 | |
540 | lcnt = DIV_ROUND_UP(core_rate, master->base.bus.scl_rate.i3c) - hcnt; |
541 | if (lcnt < SCL_I3C_TIMING_CNT_MIN) |
542 | lcnt = SCL_I3C_TIMING_CNT_MIN; |
543 | |
544 | scl_timing = SCL_I3C_TIMING_HCNT(hcnt) | SCL_I3C_TIMING_LCNT(lcnt); |
545 | writel(val: scl_timing, addr: master->regs + SCL_I3C_PP_TIMING); |
546 | |
547 | /* |
548 | * In pure i3c mode, MST_FREE represents tCAS. In shared mode, this |
549 | * will be set up by dw_i2c_clk_cfg as tLOW. |
550 | */ |
551 | if (master->base.bus.mode == I3C_BUS_MODE_PURE) |
552 | writel(BUS_I3C_MST_FREE(lcnt), addr: master->regs + BUS_FREE_TIMING); |
553 | |
554 | lcnt = max_t(u8, |
555 | DIV_ROUND_UP(I3C_BUS_TLOW_OD_MIN_NS, core_period), lcnt); |
556 | scl_timing = SCL_I3C_TIMING_HCNT(hcnt) | SCL_I3C_TIMING_LCNT(lcnt); |
557 | writel(val: scl_timing, addr: master->regs + SCL_I3C_OD_TIMING); |
558 | |
559 | lcnt = DIV_ROUND_UP(core_rate, I3C_BUS_SDR1_SCL_RATE) - hcnt; |
560 | scl_timing = SCL_EXT_LCNT_1(lcnt); |
561 | lcnt = DIV_ROUND_UP(core_rate, I3C_BUS_SDR2_SCL_RATE) - hcnt; |
562 | scl_timing |= SCL_EXT_LCNT_2(lcnt); |
563 | lcnt = DIV_ROUND_UP(core_rate, I3C_BUS_SDR3_SCL_RATE) - hcnt; |
564 | scl_timing |= SCL_EXT_LCNT_3(lcnt); |
565 | lcnt = DIV_ROUND_UP(core_rate, I3C_BUS_SDR4_SCL_RATE) - hcnt; |
566 | scl_timing |= SCL_EXT_LCNT_4(lcnt); |
567 | writel(val: scl_timing, addr: master->regs + SCL_EXT_LCNT_TIMING); |
568 | |
569 | return 0; |
570 | } |
571 | |
572 | static int dw_i2c_clk_cfg(struct dw_i3c_master *master) |
573 | { |
574 | unsigned long core_rate, core_period; |
575 | u16 hcnt, lcnt; |
576 | u32 scl_timing; |
577 | |
578 | core_rate = clk_get_rate(clk: master->core_clk); |
579 | if (!core_rate) |
580 | return -EINVAL; |
581 | |
582 | core_period = DIV_ROUND_UP(1000000000, core_rate); |
583 | |
584 | lcnt = DIV_ROUND_UP(I3C_BUS_I2C_FMP_TLOW_MIN_NS, core_period); |
585 | hcnt = DIV_ROUND_UP(core_rate, I3C_BUS_I2C_FM_PLUS_SCL_RATE) - lcnt; |
586 | scl_timing = SCL_I2C_FMP_TIMING_HCNT(hcnt) | |
587 | SCL_I2C_FMP_TIMING_LCNT(lcnt); |
588 | writel(val: scl_timing, addr: master->regs + SCL_I2C_FMP_TIMING); |
589 | |
590 | lcnt = DIV_ROUND_UP(I3C_BUS_I2C_FM_TLOW_MIN_NS, core_period); |
591 | hcnt = DIV_ROUND_UP(core_rate, I3C_BUS_I2C_FM_SCL_RATE) - lcnt; |
592 | scl_timing = SCL_I2C_FM_TIMING_HCNT(hcnt) | |
593 | SCL_I2C_FM_TIMING_LCNT(lcnt); |
594 | writel(val: scl_timing, addr: master->regs + SCL_I2C_FM_TIMING); |
595 | |
596 | writel(BUS_I3C_MST_FREE(lcnt), addr: master->regs + BUS_FREE_TIMING); |
597 | writel(readl(addr: master->regs + DEVICE_CTRL) | DEV_CTRL_I2C_SLAVE_PRESENT, |
598 | addr: master->regs + DEVICE_CTRL); |
599 | |
600 | return 0; |
601 | } |
602 | |
603 | static int dw_i3c_master_bus_init(struct i3c_master_controller *m) |
604 | { |
605 | struct dw_i3c_master *master = to_dw_i3c_master(master: m); |
606 | struct i3c_bus *bus = i3c_master_get_bus(master: m); |
607 | struct i3c_device_info info = { }; |
608 | u32 thld_ctrl; |
609 | int ret; |
610 | |
611 | ret = master->platform_ops->init(master); |
612 | if (ret) |
613 | return ret; |
614 | |
615 | switch (bus->mode) { |
616 | case I3C_BUS_MODE_MIXED_FAST: |
617 | case I3C_BUS_MODE_MIXED_LIMITED: |
618 | ret = dw_i2c_clk_cfg(master); |
619 | if (ret) |
620 | return ret; |
621 | fallthrough; |
622 | case I3C_BUS_MODE_PURE: |
623 | ret = dw_i3c_clk_cfg(master); |
624 | if (ret) |
625 | return ret; |
626 | break; |
627 | default: |
628 | return -EINVAL; |
629 | } |
630 | |
631 | thld_ctrl = readl(addr: master->regs + QUEUE_THLD_CTRL); |
632 | thld_ctrl &= ~(QUEUE_THLD_CTRL_RESP_BUF_MASK | |
633 | QUEUE_THLD_CTRL_IBI_STAT_MASK | |
634 | QUEUE_THLD_CTRL_IBI_STAT_MASK); |
635 | thld_ctrl |= QUEUE_THLD_CTRL_IBI_STAT(1) | |
636 | QUEUE_THLD_CTRL_IBI_DATA(31); |
637 | writel(val: thld_ctrl, addr: master->regs + QUEUE_THLD_CTRL); |
638 | |
639 | thld_ctrl = readl(addr: master->regs + DATA_BUFFER_THLD_CTRL); |
640 | thld_ctrl &= ~DATA_BUFFER_THLD_CTRL_RX_BUF; |
641 | writel(val: thld_ctrl, addr: master->regs + DATA_BUFFER_THLD_CTRL); |
642 | |
643 | writel(INTR_ALL, addr: master->regs + INTR_STATUS); |
644 | writel(INTR_MASTER_MASK, addr: master->regs + INTR_STATUS_EN); |
645 | writel(INTR_MASTER_MASK, addr: master->regs + INTR_SIGNAL_EN); |
646 | |
647 | ret = i3c_master_get_free_addr(master: m, start_addr: 0); |
648 | if (ret < 0) |
649 | return ret; |
650 | |
651 | writel(DEV_ADDR_DYNAMIC_ADDR_VALID | DEV_ADDR_DYNAMIC(ret), |
652 | addr: master->regs + DEVICE_ADDR); |
653 | |
654 | memset(&info, 0, sizeof(info)); |
655 | info.dyn_addr = ret; |
656 | |
657 | ret = i3c_master_set_info(master: &master->base, info: &info); |
658 | if (ret) |
659 | return ret; |
660 | |
661 | writel(IBI_REQ_REJECT_ALL, addr: master->regs + IBI_SIR_REQ_REJECT); |
662 | writel(IBI_REQ_REJECT_ALL, addr: master->regs + IBI_MR_REQ_REJECT); |
663 | |
664 | /* For now don't support Hot-Join */ |
665 | writel(readl(addr: master->regs + DEVICE_CTRL) | DEV_CTRL_HOT_JOIN_NACK, |
666 | addr: master->regs + DEVICE_CTRL); |
667 | |
668 | dw_i3c_master_enable(master); |
669 | |
670 | return 0; |
671 | } |
672 | |
673 | static void dw_i3c_master_bus_cleanup(struct i3c_master_controller *m) |
674 | { |
675 | struct dw_i3c_master *master = to_dw_i3c_master(master: m); |
676 | |
677 | dw_i3c_master_disable(master); |
678 | } |
679 | |
680 | static int dw_i3c_ccc_set(struct dw_i3c_master *master, |
681 | struct i3c_ccc_cmd *ccc) |
682 | { |
683 | struct dw_i3c_xfer *xfer; |
684 | struct dw_i3c_cmd *cmd; |
685 | int ret, pos = 0; |
686 | |
687 | if (ccc->id & I3C_CCC_DIRECT) { |
688 | pos = dw_i3c_master_get_addr_pos(master, addr: ccc->dests[0].addr); |
689 | if (pos < 0) |
690 | return pos; |
691 | } |
692 | |
693 | xfer = dw_i3c_master_alloc_xfer(master, ncmds: 1); |
694 | if (!xfer) |
695 | return -ENOMEM; |
696 | |
697 | cmd = xfer->cmds; |
698 | cmd->tx_buf = ccc->dests[0].payload.data; |
699 | cmd->tx_len = ccc->dests[0].payload.len; |
700 | |
701 | cmd->cmd_hi = COMMAND_PORT_ARG_DATA_LEN(ccc->dests[0].payload.len) | |
702 | COMMAND_PORT_TRANSFER_ARG; |
703 | |
704 | cmd->cmd_lo = COMMAND_PORT_CP | |
705 | COMMAND_PORT_DEV_INDEX(pos) | |
706 | COMMAND_PORT_CMD(ccc->id) | |
707 | COMMAND_PORT_TOC | |
708 | COMMAND_PORT_ROC; |
709 | |
710 | dw_i3c_master_enqueue_xfer(master, xfer); |
711 | if (!wait_for_completion_timeout(x: &xfer->comp, XFER_TIMEOUT)) |
712 | dw_i3c_master_dequeue_xfer(master, xfer); |
713 | |
714 | ret = xfer->ret; |
715 | if (xfer->cmds[0].error == RESPONSE_ERROR_IBA_NACK) |
716 | ccc->err = I3C_ERROR_M2; |
717 | |
718 | dw_i3c_master_free_xfer(xfer); |
719 | |
720 | return ret; |
721 | } |
722 | |
723 | static int dw_i3c_ccc_get(struct dw_i3c_master *master, struct i3c_ccc_cmd *ccc) |
724 | { |
725 | struct dw_i3c_xfer *xfer; |
726 | struct dw_i3c_cmd *cmd; |
727 | int ret, pos; |
728 | |
729 | pos = dw_i3c_master_get_addr_pos(master, addr: ccc->dests[0].addr); |
730 | if (pos < 0) |
731 | return pos; |
732 | |
733 | xfer = dw_i3c_master_alloc_xfer(master, ncmds: 1); |
734 | if (!xfer) |
735 | return -ENOMEM; |
736 | |
737 | cmd = xfer->cmds; |
738 | cmd->rx_buf = ccc->dests[0].payload.data; |
739 | cmd->rx_len = ccc->dests[0].payload.len; |
740 | |
741 | cmd->cmd_hi = COMMAND_PORT_ARG_DATA_LEN(ccc->dests[0].payload.len) | |
742 | COMMAND_PORT_TRANSFER_ARG; |
743 | |
744 | cmd->cmd_lo = COMMAND_PORT_READ_TRANSFER | |
745 | COMMAND_PORT_CP | |
746 | COMMAND_PORT_DEV_INDEX(pos) | |
747 | COMMAND_PORT_CMD(ccc->id) | |
748 | COMMAND_PORT_TOC | |
749 | COMMAND_PORT_ROC; |
750 | |
751 | dw_i3c_master_enqueue_xfer(master, xfer); |
752 | if (!wait_for_completion_timeout(x: &xfer->comp, XFER_TIMEOUT)) |
753 | dw_i3c_master_dequeue_xfer(master, xfer); |
754 | |
755 | ret = xfer->ret; |
756 | if (xfer->cmds[0].error == RESPONSE_ERROR_IBA_NACK) |
757 | ccc->err = I3C_ERROR_M2; |
758 | dw_i3c_master_free_xfer(xfer); |
759 | |
760 | return ret; |
761 | } |
762 | |
763 | static int dw_i3c_master_send_ccc_cmd(struct i3c_master_controller *m, |
764 | struct i3c_ccc_cmd *ccc) |
765 | { |
766 | struct dw_i3c_master *master = to_dw_i3c_master(master: m); |
767 | int ret = 0; |
768 | |
769 | if (ccc->id == I3C_CCC_ENTDAA) |
770 | return -EINVAL; |
771 | |
772 | if (ccc->rnw) |
773 | ret = dw_i3c_ccc_get(master, ccc); |
774 | else |
775 | ret = dw_i3c_ccc_set(master, ccc); |
776 | |
777 | return ret; |
778 | } |
779 | |
780 | static int dw_i3c_master_daa(struct i3c_master_controller *m) |
781 | { |
782 | struct dw_i3c_master *master = to_dw_i3c_master(master: m); |
783 | struct dw_i3c_xfer *xfer; |
784 | struct dw_i3c_cmd *cmd; |
785 | u32 olddevs, newdevs; |
786 | u8 p, last_addr = 0; |
787 | int ret, pos; |
788 | |
789 | olddevs = ~(master->free_pos); |
790 | |
791 | /* Prepare DAT before launching DAA. */ |
792 | for (pos = 0; pos < master->maxdevs; pos++) { |
793 | if (olddevs & BIT(pos)) |
794 | continue; |
795 | |
796 | ret = i3c_master_get_free_addr(master: m, start_addr: last_addr + 1); |
797 | if (ret < 0) |
798 | return -ENOSPC; |
799 | |
800 | master->devs[pos].addr = ret; |
801 | p = even_parity(p: ret); |
802 | last_addr = ret; |
803 | ret |= (p << 7); |
804 | |
805 | writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(ret), |
806 | addr: master->regs + |
807 | DEV_ADDR_TABLE_LOC(master->datstartaddr, pos)); |
808 | } |
809 | |
810 | xfer = dw_i3c_master_alloc_xfer(master, ncmds: 1); |
811 | if (!xfer) |
812 | return -ENOMEM; |
813 | |
814 | pos = dw_i3c_master_get_free_pos(master); |
815 | if (pos < 0) { |
816 | dw_i3c_master_free_xfer(xfer); |
817 | return pos; |
818 | } |
819 | cmd = &xfer->cmds[0]; |
820 | cmd->cmd_hi = 0x1; |
821 | cmd->cmd_lo = COMMAND_PORT_DEV_COUNT(master->maxdevs - pos) | |
822 | COMMAND_PORT_DEV_INDEX(pos) | |
823 | COMMAND_PORT_CMD(I3C_CCC_ENTDAA) | |
824 | COMMAND_PORT_ADDR_ASSGN_CMD | |
825 | COMMAND_PORT_TOC | |
826 | COMMAND_PORT_ROC; |
827 | |
828 | dw_i3c_master_enqueue_xfer(master, xfer); |
829 | if (!wait_for_completion_timeout(x: &xfer->comp, XFER_TIMEOUT)) |
830 | dw_i3c_master_dequeue_xfer(master, xfer); |
831 | |
832 | newdevs = GENMASK(master->maxdevs - cmd->rx_len - 1, 0); |
833 | newdevs &= ~olddevs; |
834 | |
835 | for (pos = 0; pos < master->maxdevs; pos++) { |
836 | if (newdevs & BIT(pos)) |
837 | i3c_master_add_i3c_dev_locked(master: m, addr: master->devs[pos].addr); |
838 | } |
839 | |
840 | dw_i3c_master_free_xfer(xfer); |
841 | |
842 | return 0; |
843 | } |
844 | |
845 | static int dw_i3c_master_priv_xfers(struct i3c_dev_desc *dev, |
846 | struct i3c_priv_xfer *i3c_xfers, |
847 | int i3c_nxfers) |
848 | { |
849 | struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); |
850 | struct i3c_master_controller *m = i3c_dev_get_master(dev); |
851 | struct dw_i3c_master *master = to_dw_i3c_master(master: m); |
852 | unsigned int nrxwords = 0, ntxwords = 0; |
853 | struct dw_i3c_xfer *xfer; |
854 | int i, ret = 0; |
855 | |
856 | if (!i3c_nxfers) |
857 | return 0; |
858 | |
859 | if (i3c_nxfers > master->caps.cmdfifodepth) |
860 | return -ENOTSUPP; |
861 | |
862 | for (i = 0; i < i3c_nxfers; i++) { |
863 | if (i3c_xfers[i].rnw) |
864 | nrxwords += DIV_ROUND_UP(i3c_xfers[i].len, 4); |
865 | else |
866 | ntxwords += DIV_ROUND_UP(i3c_xfers[i].len, 4); |
867 | } |
868 | |
869 | if (ntxwords > master->caps.datafifodepth || |
870 | nrxwords > master->caps.datafifodepth) |
871 | return -ENOTSUPP; |
872 | |
873 | xfer = dw_i3c_master_alloc_xfer(master, ncmds: i3c_nxfers); |
874 | if (!xfer) |
875 | return -ENOMEM; |
876 | |
877 | for (i = 0; i < i3c_nxfers; i++) { |
878 | struct dw_i3c_cmd *cmd = &xfer->cmds[i]; |
879 | |
880 | cmd->cmd_hi = COMMAND_PORT_ARG_DATA_LEN(i3c_xfers[i].len) | |
881 | COMMAND_PORT_TRANSFER_ARG; |
882 | |
883 | if (i3c_xfers[i].rnw) { |
884 | cmd->rx_buf = i3c_xfers[i].data.in; |
885 | cmd->rx_len = i3c_xfers[i].len; |
886 | cmd->cmd_lo = COMMAND_PORT_READ_TRANSFER | |
887 | COMMAND_PORT_SPEED(dev->info.max_read_ds); |
888 | |
889 | } else { |
890 | cmd->tx_buf = i3c_xfers[i].data.out; |
891 | cmd->tx_len = i3c_xfers[i].len; |
892 | cmd->cmd_lo = |
893 | COMMAND_PORT_SPEED(dev->info.max_write_ds); |
894 | } |
895 | |
896 | cmd->cmd_lo |= COMMAND_PORT_TID(i) | |
897 | COMMAND_PORT_DEV_INDEX(data->index) | |
898 | COMMAND_PORT_ROC; |
899 | |
900 | if (i == (i3c_nxfers - 1)) |
901 | cmd->cmd_lo |= COMMAND_PORT_TOC; |
902 | } |
903 | |
904 | dw_i3c_master_enqueue_xfer(master, xfer); |
905 | if (!wait_for_completion_timeout(x: &xfer->comp, XFER_TIMEOUT)) |
906 | dw_i3c_master_dequeue_xfer(master, xfer); |
907 | |
908 | for (i = 0; i < i3c_nxfers; i++) { |
909 | struct dw_i3c_cmd *cmd = &xfer->cmds[i]; |
910 | |
911 | if (i3c_xfers[i].rnw) |
912 | i3c_xfers[i].len = cmd->rx_len; |
913 | } |
914 | |
915 | ret = xfer->ret; |
916 | dw_i3c_master_free_xfer(xfer); |
917 | |
918 | return ret; |
919 | } |
920 | |
921 | static int dw_i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev, |
922 | u8 old_dyn_addr) |
923 | { |
924 | struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); |
925 | struct i3c_master_controller *m = i3c_dev_get_master(dev); |
926 | struct dw_i3c_master *master = to_dw_i3c_master(master: m); |
927 | int pos; |
928 | |
929 | pos = dw_i3c_master_get_free_pos(master); |
930 | |
931 | if (data->index > pos && pos > 0) { |
932 | writel(val: 0, |
933 | addr: master->regs + |
934 | DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); |
935 | |
936 | master->devs[data->index].addr = 0; |
937 | master->free_pos |= BIT(data->index); |
938 | |
939 | data->index = pos; |
940 | master->devs[pos].addr = dev->info.dyn_addr; |
941 | master->free_pos &= ~BIT(pos); |
942 | } |
943 | |
944 | writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(dev->info.dyn_addr), |
945 | addr: master->regs + |
946 | DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); |
947 | |
948 | master->devs[data->index].addr = dev->info.dyn_addr; |
949 | |
950 | return 0; |
951 | } |
952 | |
953 | static int dw_i3c_master_attach_i3c_dev(struct i3c_dev_desc *dev) |
954 | { |
955 | struct i3c_master_controller *m = i3c_dev_get_master(dev); |
956 | struct dw_i3c_master *master = to_dw_i3c_master(master: m); |
957 | struct dw_i3c_i2c_dev_data *data; |
958 | int pos; |
959 | |
960 | pos = dw_i3c_master_get_free_pos(master); |
961 | if (pos < 0) |
962 | return pos; |
963 | |
964 | data = kzalloc(size: sizeof(*data), GFP_KERNEL); |
965 | if (!data) |
966 | return -ENOMEM; |
967 | |
968 | data->index = pos; |
969 | master->devs[pos].addr = dev->info.dyn_addr ? : dev->info.static_addr; |
970 | master->free_pos &= ~BIT(pos); |
971 | i3c_dev_set_master_data(dev, data); |
972 | |
973 | writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(master->devs[pos].addr), |
974 | addr: master->regs + |
975 | DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); |
976 | |
977 | return 0; |
978 | } |
979 | |
980 | static void dw_i3c_master_detach_i3c_dev(struct i3c_dev_desc *dev) |
981 | { |
982 | struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); |
983 | struct i3c_master_controller *m = i3c_dev_get_master(dev); |
984 | struct dw_i3c_master *master = to_dw_i3c_master(master: m); |
985 | |
986 | writel(val: 0, |
987 | addr: master->regs + |
988 | DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); |
989 | |
990 | i3c_dev_set_master_data(dev, NULL); |
991 | master->devs[data->index].addr = 0; |
992 | master->free_pos |= BIT(data->index); |
993 | kfree(objp: data); |
994 | } |
995 | |
996 | static int dw_i3c_master_i2c_xfers(struct i2c_dev_desc *dev, |
997 | const struct i2c_msg *i2c_xfers, |
998 | int i2c_nxfers) |
999 | { |
1000 | struct dw_i3c_i2c_dev_data *data = i2c_dev_get_master_data(dev); |
1001 | struct i3c_master_controller *m = i2c_dev_get_master(dev); |
1002 | struct dw_i3c_master *master = to_dw_i3c_master(master: m); |
1003 | unsigned int nrxwords = 0, ntxwords = 0; |
1004 | struct dw_i3c_xfer *xfer; |
1005 | int i, ret = 0; |
1006 | |
1007 | if (!i2c_nxfers) |
1008 | return 0; |
1009 | |
1010 | if (i2c_nxfers > master->caps.cmdfifodepth) |
1011 | return -ENOTSUPP; |
1012 | |
1013 | for (i = 0; i < i2c_nxfers; i++) { |
1014 | if (i2c_xfers[i].flags & I2C_M_RD) |
1015 | nrxwords += DIV_ROUND_UP(i2c_xfers[i].len, 4); |
1016 | else |
1017 | ntxwords += DIV_ROUND_UP(i2c_xfers[i].len, 4); |
1018 | } |
1019 | |
1020 | if (ntxwords > master->caps.datafifodepth || |
1021 | nrxwords > master->caps.datafifodepth) |
1022 | return -ENOTSUPP; |
1023 | |
1024 | xfer = dw_i3c_master_alloc_xfer(master, ncmds: i2c_nxfers); |
1025 | if (!xfer) |
1026 | return -ENOMEM; |
1027 | |
1028 | for (i = 0; i < i2c_nxfers; i++) { |
1029 | struct dw_i3c_cmd *cmd = &xfer->cmds[i]; |
1030 | |
1031 | cmd->cmd_hi = COMMAND_PORT_ARG_DATA_LEN(i2c_xfers[i].len) | |
1032 | COMMAND_PORT_TRANSFER_ARG; |
1033 | |
1034 | cmd->cmd_lo = COMMAND_PORT_TID(i) | |
1035 | COMMAND_PORT_DEV_INDEX(data->index) | |
1036 | COMMAND_PORT_ROC; |
1037 | |
1038 | if (i2c_xfers[i].flags & I2C_M_RD) { |
1039 | cmd->cmd_lo |= COMMAND_PORT_READ_TRANSFER; |
1040 | cmd->rx_buf = i2c_xfers[i].buf; |
1041 | cmd->rx_len = i2c_xfers[i].len; |
1042 | } else { |
1043 | cmd->tx_buf = i2c_xfers[i].buf; |
1044 | cmd->tx_len = i2c_xfers[i].len; |
1045 | } |
1046 | |
1047 | if (i == (i2c_nxfers - 1)) |
1048 | cmd->cmd_lo |= COMMAND_PORT_TOC; |
1049 | } |
1050 | |
1051 | dw_i3c_master_enqueue_xfer(master, xfer); |
1052 | if (!wait_for_completion_timeout(x: &xfer->comp, XFER_TIMEOUT)) |
1053 | dw_i3c_master_dequeue_xfer(master, xfer); |
1054 | |
1055 | ret = xfer->ret; |
1056 | dw_i3c_master_free_xfer(xfer); |
1057 | |
1058 | return ret; |
1059 | } |
1060 | |
1061 | static int dw_i3c_master_attach_i2c_dev(struct i2c_dev_desc *dev) |
1062 | { |
1063 | struct i3c_master_controller *m = i2c_dev_get_master(dev); |
1064 | struct dw_i3c_master *master = to_dw_i3c_master(master: m); |
1065 | struct dw_i3c_i2c_dev_data *data; |
1066 | int pos; |
1067 | |
1068 | pos = dw_i3c_master_get_free_pos(master); |
1069 | if (pos < 0) |
1070 | return pos; |
1071 | |
1072 | data = kzalloc(size: sizeof(*data), GFP_KERNEL); |
1073 | if (!data) |
1074 | return -ENOMEM; |
1075 | |
1076 | data->index = pos; |
1077 | master->devs[pos].addr = dev->addr; |
1078 | master->free_pos &= ~BIT(pos); |
1079 | i2c_dev_set_master_data(dev, data); |
1080 | |
1081 | writel(DEV_ADDR_TABLE_LEGACY_I2C_DEV | |
1082 | DEV_ADDR_TABLE_STATIC_ADDR(dev->addr), |
1083 | addr: master->regs + |
1084 | DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); |
1085 | |
1086 | return 0; |
1087 | } |
1088 | |
1089 | static void dw_i3c_master_detach_i2c_dev(struct i2c_dev_desc *dev) |
1090 | { |
1091 | struct dw_i3c_i2c_dev_data *data = i2c_dev_get_master_data(dev); |
1092 | struct i3c_master_controller *m = i2c_dev_get_master(dev); |
1093 | struct dw_i3c_master *master = to_dw_i3c_master(master: m); |
1094 | |
1095 | writel(val: 0, |
1096 | addr: master->regs + |
1097 | DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); |
1098 | |
1099 | i2c_dev_set_master_data(dev, NULL); |
1100 | master->devs[data->index].addr = 0; |
1101 | master->free_pos |= BIT(data->index); |
1102 | kfree(objp: data); |
1103 | } |
1104 | |
1105 | static int dw_i3c_master_request_ibi(struct i3c_dev_desc *dev, |
1106 | const struct i3c_ibi_setup *req) |
1107 | { |
1108 | struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); |
1109 | struct i3c_master_controller *m = i3c_dev_get_master(dev); |
1110 | struct dw_i3c_master *master = to_dw_i3c_master(master: m); |
1111 | unsigned long flags; |
1112 | |
1113 | data->ibi_pool = i3c_generic_ibi_alloc_pool(dev, req); |
1114 | if (IS_ERR(ptr: data->ibi_pool)) |
1115 | return PTR_ERR(ptr: data->ibi_pool); |
1116 | |
1117 | spin_lock_irqsave(&master->devs_lock, flags); |
1118 | master->devs[data->index].ibi_dev = dev; |
1119 | spin_unlock_irqrestore(lock: &master->devs_lock, flags); |
1120 | |
1121 | return 0; |
1122 | } |
1123 | |
1124 | static void dw_i3c_master_free_ibi(struct i3c_dev_desc *dev) |
1125 | { |
1126 | struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); |
1127 | struct i3c_master_controller *m = i3c_dev_get_master(dev); |
1128 | struct dw_i3c_master *master = to_dw_i3c_master(master: m); |
1129 | unsigned long flags; |
1130 | |
1131 | spin_lock_irqsave(&master->devs_lock, flags); |
1132 | master->devs[data->index].ibi_dev = NULL; |
1133 | spin_unlock_irqrestore(lock: &master->devs_lock, flags); |
1134 | |
1135 | i3c_generic_ibi_free_pool(pool: data->ibi_pool); |
1136 | data->ibi_pool = NULL; |
1137 | } |
1138 | |
1139 | static void dw_i3c_master_set_sir_enabled(struct dw_i3c_master *master, |
1140 | struct i3c_dev_desc *dev, |
1141 | u8 idx, bool enable) |
1142 | { |
1143 | unsigned long flags; |
1144 | u32 dat_entry, reg; |
1145 | bool global; |
1146 | |
1147 | dat_entry = DEV_ADDR_TABLE_LOC(master->datstartaddr, idx); |
1148 | |
1149 | spin_lock_irqsave(&master->devs_lock, flags); |
1150 | reg = readl(addr: master->regs + dat_entry); |
1151 | if (enable) { |
1152 | reg &= ~DEV_ADDR_TABLE_SIR_REJECT; |
1153 | if (dev->info.bcr & I3C_BCR_IBI_PAYLOAD) |
1154 | reg |= DEV_ADDR_TABLE_IBI_MDB; |
1155 | } else { |
1156 | reg |= DEV_ADDR_TABLE_SIR_REJECT; |
1157 | } |
1158 | master->platform_ops->set_dat_ibi(master, dev, enable, ®); |
1159 | writel(val: reg, addr: master->regs + dat_entry); |
1160 | |
1161 | reg = readl(addr: master->regs + IBI_SIR_REQ_REJECT); |
1162 | if (enable) { |
1163 | global = reg == 0xffffffff; |
1164 | reg &= ~BIT(idx); |
1165 | } else { |
1166 | bool hj_rejected = !!(readl(addr: master->regs + DEVICE_CTRL) & DEV_CTRL_HOT_JOIN_NACK); |
1167 | |
1168 | reg |= BIT(idx); |
1169 | global = (reg == 0xffffffff) && hj_rejected; |
1170 | } |
1171 | writel(val: reg, addr: master->regs + IBI_SIR_REQ_REJECT); |
1172 | |
1173 | if (global) { |
1174 | reg = readl(addr: master->regs + INTR_STATUS_EN); |
1175 | reg &= ~INTR_IBI_THLD_STAT; |
1176 | if (enable) |
1177 | reg |= INTR_IBI_THLD_STAT; |
1178 | writel(val: reg, addr: master->regs + INTR_STATUS_EN); |
1179 | |
1180 | reg = readl(addr: master->regs + INTR_SIGNAL_EN); |
1181 | reg &= ~INTR_IBI_THLD_STAT; |
1182 | if (enable) |
1183 | reg |= INTR_IBI_THLD_STAT; |
1184 | writel(val: reg, addr: master->regs + INTR_SIGNAL_EN); |
1185 | } |
1186 | |
1187 | spin_unlock_irqrestore(lock: &master->devs_lock, flags); |
1188 | } |
1189 | |
1190 | static int dw_i3c_master_enable_ibi(struct i3c_dev_desc *dev) |
1191 | { |
1192 | struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); |
1193 | struct i3c_master_controller *m = i3c_dev_get_master(dev); |
1194 | struct dw_i3c_master *master = to_dw_i3c_master(master: m); |
1195 | int rc; |
1196 | |
1197 | dw_i3c_master_set_sir_enabled(master, dev, idx: data->index, enable: true); |
1198 | |
1199 | rc = i3c_master_enec_locked(master: m, addr: dev->info.dyn_addr, I3C_CCC_EVENT_SIR); |
1200 | |
1201 | if (rc) |
1202 | dw_i3c_master_set_sir_enabled(master, dev, idx: data->index, enable: false); |
1203 | |
1204 | return rc; |
1205 | } |
1206 | |
1207 | static int dw_i3c_master_disable_ibi(struct i3c_dev_desc *dev) |
1208 | { |
1209 | struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); |
1210 | struct i3c_master_controller *m = i3c_dev_get_master(dev); |
1211 | struct dw_i3c_master *master = to_dw_i3c_master(master: m); |
1212 | int rc; |
1213 | |
1214 | rc = i3c_master_disec_locked(master: m, addr: dev->info.dyn_addr, I3C_CCC_EVENT_SIR); |
1215 | if (rc) |
1216 | return rc; |
1217 | |
1218 | dw_i3c_master_set_sir_enabled(master, dev, idx: data->index, enable: false); |
1219 | |
1220 | return 0; |
1221 | } |
1222 | |
1223 | static void dw_i3c_master_recycle_ibi_slot(struct i3c_dev_desc *dev, |
1224 | struct i3c_ibi_slot *slot) |
1225 | { |
1226 | struct dw_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev); |
1227 | |
1228 | i3c_generic_ibi_recycle_slot(pool: data->ibi_pool, slot); |
1229 | } |
1230 | |
1231 | static void dw_i3c_master_drain_ibi_queue(struct dw_i3c_master *master, |
1232 | int len) |
1233 | { |
1234 | int i; |
1235 | |
1236 | for (i = 0; i < DIV_ROUND_UP(len, 4); i++) |
1237 | readl(addr: master->regs + IBI_QUEUE_STATUS); |
1238 | } |
1239 | |
1240 | static void dw_i3c_master_handle_ibi_sir(struct dw_i3c_master *master, |
1241 | u32 status) |
1242 | { |
1243 | struct dw_i3c_i2c_dev_data *data; |
1244 | struct i3c_ibi_slot *slot; |
1245 | struct i3c_dev_desc *dev; |
1246 | unsigned long flags; |
1247 | u8 addr, len; |
1248 | int idx; |
1249 | |
1250 | addr = IBI_QUEUE_IBI_ADDR(status); |
1251 | len = IBI_QUEUE_STATUS_DATA_LEN(status); |
1252 | |
1253 | /* |
1254 | * We be tempted to check the error status in bit 30; however, due |
1255 | * to the PEC errata workaround on some platform implementations (see |
1256 | * ast2600_i3c_set_dat_ibi()), those will almost always have a PEC |
1257 | * error on IBI payload data, as well as losing the last byte of |
1258 | * payload. |
1259 | * |
1260 | * If we implement error status checking on that bit, we may need |
1261 | * a new platform op to validate it. |
1262 | */ |
1263 | |
1264 | spin_lock_irqsave(&master->devs_lock, flags); |
1265 | idx = dw_i3c_master_get_addr_pos(master, addr); |
1266 | if (idx < 0) { |
1267 | dev_dbg_ratelimited(&master->base.dev, |
1268 | "IBI from unknown addr 0x%x\n" , addr); |
1269 | goto err_drain; |
1270 | } |
1271 | |
1272 | dev = master->devs[idx].ibi_dev; |
1273 | if (!dev || !dev->ibi) { |
1274 | dev_dbg_ratelimited(&master->base.dev, |
1275 | "IBI from non-requested dev idx %d\n" , idx); |
1276 | goto err_drain; |
1277 | } |
1278 | |
1279 | data = i3c_dev_get_master_data(dev); |
1280 | slot = i3c_generic_ibi_get_free_slot(pool: data->ibi_pool); |
1281 | if (!slot) { |
1282 | dev_dbg_ratelimited(&master->base.dev, |
1283 | "No IBI slots available\n" ); |
1284 | goto err_drain; |
1285 | } |
1286 | |
1287 | if (dev->ibi->max_payload_len < len) { |
1288 | dev_dbg_ratelimited(&master->base.dev, |
1289 | "IBI payload len %d greater than max %d\n" , |
1290 | len, dev->ibi->max_payload_len); |
1291 | goto err_drain; |
1292 | } |
1293 | |
1294 | if (len) { |
1295 | dw_i3c_master_read_ibi_fifo(master, bytes: slot->data, nbytes: len); |
1296 | slot->len = len; |
1297 | } |
1298 | i3c_master_queue_ibi(dev, slot); |
1299 | |
1300 | spin_unlock_irqrestore(lock: &master->devs_lock, flags); |
1301 | |
1302 | return; |
1303 | |
1304 | err_drain: |
1305 | dw_i3c_master_drain_ibi_queue(master, len); |
1306 | |
1307 | spin_unlock_irqrestore(lock: &master->devs_lock, flags); |
1308 | } |
1309 | |
1310 | /* "ibis": referring to In-Band Interrupts, and not |
1311 | * https://en.wikipedia.org/wiki/Australian_white_ibis. The latter should |
1312 | * not be handled. |
1313 | */ |
1314 | static void dw_i3c_master_irq_handle_ibis(struct dw_i3c_master *master) |
1315 | { |
1316 | unsigned int i, len, n_ibis; |
1317 | u32 reg; |
1318 | |
1319 | reg = readl(addr: master->regs + QUEUE_STATUS_LEVEL); |
1320 | n_ibis = QUEUE_STATUS_IBI_STATUS_CNT(reg); |
1321 | if (!n_ibis) |
1322 | return; |
1323 | |
1324 | for (i = 0; i < n_ibis; i++) { |
1325 | reg = readl(addr: master->regs + IBI_QUEUE_STATUS); |
1326 | |
1327 | if (IBI_TYPE_SIRQ(reg)) { |
1328 | dw_i3c_master_handle_ibi_sir(master, status: reg); |
1329 | } else { |
1330 | len = IBI_QUEUE_STATUS_DATA_LEN(reg); |
1331 | dev_info(&master->base.dev, |
1332 | "unsupported IBI type 0x%lx len %d\n" , |
1333 | IBI_QUEUE_STATUS_IBI_ID(reg), len); |
1334 | dw_i3c_master_drain_ibi_queue(master, len); |
1335 | } |
1336 | } |
1337 | } |
1338 | |
1339 | static irqreturn_t dw_i3c_master_irq_handler(int irq, void *dev_id) |
1340 | { |
1341 | struct dw_i3c_master *master = dev_id; |
1342 | u32 status; |
1343 | |
1344 | status = readl(addr: master->regs + INTR_STATUS); |
1345 | |
1346 | if (!(status & readl(addr: master->regs + INTR_STATUS_EN))) { |
1347 | writel(INTR_ALL, addr: master->regs + INTR_STATUS); |
1348 | return IRQ_NONE; |
1349 | } |
1350 | |
1351 | spin_lock(lock: &master->xferqueue.lock); |
1352 | dw_i3c_master_end_xfer_locked(master, isr: status); |
1353 | if (status & INTR_TRANSFER_ERR_STAT) |
1354 | writel(INTR_TRANSFER_ERR_STAT, addr: master->regs + INTR_STATUS); |
1355 | spin_unlock(lock: &master->xferqueue.lock); |
1356 | |
1357 | if (status & INTR_IBI_THLD_STAT) |
1358 | dw_i3c_master_irq_handle_ibis(master); |
1359 | |
1360 | return IRQ_HANDLED; |
1361 | } |
1362 | |
1363 | static const struct i3c_master_controller_ops dw_mipi_i3c_ops = { |
1364 | .bus_init = dw_i3c_master_bus_init, |
1365 | .bus_cleanup = dw_i3c_master_bus_cleanup, |
1366 | .attach_i3c_dev = dw_i3c_master_attach_i3c_dev, |
1367 | .reattach_i3c_dev = dw_i3c_master_reattach_i3c_dev, |
1368 | .detach_i3c_dev = dw_i3c_master_detach_i3c_dev, |
1369 | .do_daa = dw_i3c_master_daa, |
1370 | .supports_ccc_cmd = dw_i3c_master_supports_ccc_cmd, |
1371 | .send_ccc_cmd = dw_i3c_master_send_ccc_cmd, |
1372 | .priv_xfers = dw_i3c_master_priv_xfers, |
1373 | .attach_i2c_dev = dw_i3c_master_attach_i2c_dev, |
1374 | .detach_i2c_dev = dw_i3c_master_detach_i2c_dev, |
1375 | .i2c_xfers = dw_i3c_master_i2c_xfers, |
1376 | }; |
1377 | |
1378 | static const struct i3c_master_controller_ops dw_mipi_i3c_ibi_ops = { |
1379 | .bus_init = dw_i3c_master_bus_init, |
1380 | .bus_cleanup = dw_i3c_master_bus_cleanup, |
1381 | .attach_i3c_dev = dw_i3c_master_attach_i3c_dev, |
1382 | .reattach_i3c_dev = dw_i3c_master_reattach_i3c_dev, |
1383 | .detach_i3c_dev = dw_i3c_master_detach_i3c_dev, |
1384 | .do_daa = dw_i3c_master_daa, |
1385 | .supports_ccc_cmd = dw_i3c_master_supports_ccc_cmd, |
1386 | .send_ccc_cmd = dw_i3c_master_send_ccc_cmd, |
1387 | .priv_xfers = dw_i3c_master_priv_xfers, |
1388 | .attach_i2c_dev = dw_i3c_master_attach_i2c_dev, |
1389 | .detach_i2c_dev = dw_i3c_master_detach_i2c_dev, |
1390 | .i2c_xfers = dw_i3c_master_i2c_xfers, |
1391 | .request_ibi = dw_i3c_master_request_ibi, |
1392 | .free_ibi = dw_i3c_master_free_ibi, |
1393 | .enable_ibi = dw_i3c_master_enable_ibi, |
1394 | .disable_ibi = dw_i3c_master_disable_ibi, |
1395 | .recycle_ibi_slot = dw_i3c_master_recycle_ibi_slot, |
1396 | }; |
1397 | |
1398 | /* default platform ops implementations */ |
1399 | static int dw_i3c_platform_init_nop(struct dw_i3c_master *i3c) |
1400 | { |
1401 | return 0; |
1402 | } |
1403 | |
1404 | static void dw_i3c_platform_set_dat_ibi_nop(struct dw_i3c_master *i3c, |
1405 | struct i3c_dev_desc *dev, |
1406 | bool enable, u32 *dat) |
1407 | { |
1408 | } |
1409 | |
1410 | static const struct dw_i3c_platform_ops dw_i3c_platform_ops_default = { |
1411 | .init = dw_i3c_platform_init_nop, |
1412 | .set_dat_ibi = dw_i3c_platform_set_dat_ibi_nop, |
1413 | }; |
1414 | |
1415 | int dw_i3c_common_probe(struct dw_i3c_master *master, |
1416 | struct platform_device *pdev) |
1417 | { |
1418 | const struct i3c_master_controller_ops *ops; |
1419 | int ret, irq; |
1420 | |
1421 | if (!master->platform_ops) |
1422 | master->platform_ops = &dw_i3c_platform_ops_default; |
1423 | |
1424 | master->regs = devm_platform_ioremap_resource(pdev, index: 0); |
1425 | if (IS_ERR(ptr: master->regs)) |
1426 | return PTR_ERR(ptr: master->regs); |
1427 | |
1428 | master->core_clk = devm_clk_get(dev: &pdev->dev, NULL); |
1429 | if (IS_ERR(ptr: master->core_clk)) |
1430 | return PTR_ERR(ptr: master->core_clk); |
1431 | |
1432 | master->core_rst = devm_reset_control_get_optional_exclusive(dev: &pdev->dev, |
1433 | id: "core_rst" ); |
1434 | if (IS_ERR(ptr: master->core_rst)) |
1435 | return PTR_ERR(ptr: master->core_rst); |
1436 | |
1437 | ret = clk_prepare_enable(clk: master->core_clk); |
1438 | if (ret) |
1439 | goto err_disable_core_clk; |
1440 | |
1441 | reset_control_deassert(rstc: master->core_rst); |
1442 | |
1443 | spin_lock_init(&master->xferqueue.lock); |
1444 | INIT_LIST_HEAD(list: &master->xferqueue.list); |
1445 | |
1446 | writel(INTR_ALL, addr: master->regs + INTR_STATUS); |
1447 | irq = platform_get_irq(pdev, 0); |
1448 | ret = devm_request_irq(dev: &pdev->dev, irq, |
1449 | handler: dw_i3c_master_irq_handler, irqflags: 0, |
1450 | devname: dev_name(dev: &pdev->dev), dev_id: master); |
1451 | if (ret) |
1452 | goto err_assert_rst; |
1453 | |
1454 | platform_set_drvdata(pdev, data: master); |
1455 | |
1456 | /* Information regarding the FIFOs/QUEUEs depth */ |
1457 | ret = readl(addr: master->regs + QUEUE_STATUS_LEVEL); |
1458 | master->caps.cmdfifodepth = QUEUE_STATUS_LEVEL_CMD(ret); |
1459 | |
1460 | ret = readl(addr: master->regs + DATA_BUFFER_STATUS_LEVEL); |
1461 | master->caps.datafifodepth = DATA_BUFFER_STATUS_LEVEL_TX(ret); |
1462 | |
1463 | ret = readl(addr: master->regs + DEVICE_ADDR_TABLE_POINTER); |
1464 | master->datstartaddr = ret; |
1465 | master->maxdevs = ret >> 16; |
1466 | master->free_pos = GENMASK(master->maxdevs - 1, 0); |
1467 | |
1468 | ops = &dw_mipi_i3c_ops; |
1469 | if (master->ibi_capable) |
1470 | ops = &dw_mipi_i3c_ibi_ops; |
1471 | |
1472 | ret = i3c_master_register(master: &master->base, parent: &pdev->dev, ops, secondary: false); |
1473 | if (ret) |
1474 | goto err_assert_rst; |
1475 | |
1476 | return 0; |
1477 | |
1478 | err_assert_rst: |
1479 | reset_control_assert(rstc: master->core_rst); |
1480 | |
1481 | err_disable_core_clk: |
1482 | clk_disable_unprepare(clk: master->core_clk); |
1483 | |
1484 | return ret; |
1485 | } |
1486 | EXPORT_SYMBOL_GPL(dw_i3c_common_probe); |
1487 | |
1488 | void dw_i3c_common_remove(struct dw_i3c_master *master) |
1489 | { |
1490 | i3c_master_unregister(master: &master->base); |
1491 | |
1492 | reset_control_assert(rstc: master->core_rst); |
1493 | |
1494 | clk_disable_unprepare(clk: master->core_clk); |
1495 | } |
1496 | EXPORT_SYMBOL_GPL(dw_i3c_common_remove); |
1497 | |
1498 | /* base platform implementation */ |
1499 | |
1500 | static int dw_i3c_probe(struct platform_device *pdev) |
1501 | { |
1502 | struct dw_i3c_master *master; |
1503 | |
1504 | master = devm_kzalloc(dev: &pdev->dev, size: sizeof(*master), GFP_KERNEL); |
1505 | if (!master) |
1506 | return -ENOMEM; |
1507 | |
1508 | return dw_i3c_common_probe(master, pdev); |
1509 | } |
1510 | |
1511 | static void dw_i3c_remove(struct platform_device *pdev) |
1512 | { |
1513 | struct dw_i3c_master *master = platform_get_drvdata(pdev); |
1514 | |
1515 | dw_i3c_common_remove(master); |
1516 | } |
1517 | |
1518 | static const struct of_device_id dw_i3c_master_of_match[] = { |
1519 | { .compatible = "snps,dw-i3c-master-1.00a" , }, |
1520 | {}, |
1521 | }; |
1522 | MODULE_DEVICE_TABLE(of, dw_i3c_master_of_match); |
1523 | |
1524 | static struct platform_driver dw_i3c_driver = { |
1525 | .probe = dw_i3c_probe, |
1526 | .remove_new = dw_i3c_remove, |
1527 | .driver = { |
1528 | .name = "dw-i3c-master" , |
1529 | .of_match_table = dw_i3c_master_of_match, |
1530 | }, |
1531 | }; |
1532 | module_platform_driver(dw_i3c_driver); |
1533 | |
1534 | MODULE_AUTHOR("Vitor Soares <vitor.soares@synopsys.com>" ); |
1535 | MODULE_DESCRIPTION("DesignWare MIPI I3C driver" ); |
1536 | MODULE_LICENSE("GPL v2" ); |
1537 | |