]>
Commit | Line | Data |
---|---|---|
432f66fe GS |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * TI K3 AM65x NAVSS Ring accelerator Manager (RA) subsystem driver | |
4 | * | |
a94a4071 | 5 | * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com |
432f66fe GS |
6 | */ |
7 | ||
d678a59d | 8 | #include <common.h> |
9d32a94b | 9 | #include <cpu_func.h> |
f7ae49fc | 10 | #include <log.h> |
90526e9f | 11 | #include <asm/cache.h> |
432f66fe GS |
12 | #include <asm/io.h> |
13 | #include <malloc.h> | |
432f66fe GS |
14 | #include <asm/bitops.h> |
15 | #include <dm.h> | |
336d4615 | 16 | #include <dm/device_compat.h> |
61b29b82 | 17 | #include <dm/devres.h> |
432f66fe GS |
18 | #include <dm/read.h> |
19 | #include <dm/uclass.h> | |
cd93d625 | 20 | #include <linux/bitops.h> |
432f66fe | 21 | #include <linux/compat.h> |
9d86b89c | 22 | #include <linux/dma-mapping.h> |
61b29b82 | 23 | #include <linux/err.h> |
1e94b46f | 24 | #include <linux/printk.h> |
432f66fe GS |
25 | #include <linux/soc/ti/k3-navss-ringacc.h> |
26 | #include <linux/soc/ti/ti_sci_protocol.h> | |
c409b493 | 27 | #include <linux/soc/ti/cppi5.h> |
432f66fe GS |
28 | |
29 | #define set_bit(bit, bitmap) __set_bit(bit, bitmap) | |
30 | #define clear_bit(bit, bitmap) __clear_bit(bit, bitmap) | |
31 | #define dma_free_coherent(dev, size, cpu_addr, dma_handle) \ | |
32 | dma_free_coherent(cpu_addr) | |
33 | #define dma_zalloc_coherent(dev, size, dma_handle, flag) \ | |
34 | ({ \ | |
35 | void *ring_mem_virt; \ | |
36 | ring_mem_virt = dma_alloc_coherent((size), \ | |
37 | (unsigned long *)(dma_handle)); \ | |
38 | if (ring_mem_virt) \ | |
39 | memset(ring_mem_virt, 0, (size)); \ | |
40 | ring_mem_virt; \ | |
41 | }) | |
42 | ||
43 | static LIST_HEAD(k3_nav_ringacc_list); | |
44 | ||
45 | static void ringacc_writel(u32 v, void __iomem *reg) | |
46 | { | |
47 | pr_debug("WRITEL(32): v(%08X)-->reg(%p)\n", v, reg); | |
48 | writel(v, reg); | |
49 | } | |
50 | ||
51 | static u32 ringacc_readl(void __iomem *reg) | |
52 | { | |
53 | u32 v; | |
54 | ||
55 | v = readl(reg); | |
56 | pr_debug("READL(32): v(%08X)<--reg(%p)\n", v, reg); | |
57 | return v; | |
58 | } | |
59 | ||
60 | #define KNAV_RINGACC_CFG_RING_SIZE_ELCNT_MASK GENMASK(19, 0) | |
c409b493 | 61 | #define K3_DMARING_RING_CFG_RING_SIZE_ELCNT_MASK GENMASK(15, 0) |
432f66fe GS |
62 | |
63 | /** | |
64 | * struct k3_nav_ring_rt_regs - The RA Control/Status Registers region | |
65 | */ | |
66 | struct k3_nav_ring_rt_regs { | |
67 | u32 resv_16[4]; | |
68 | u32 db; /* RT Ring N Doorbell Register */ | |
69 | u32 resv_4[1]; | |
70 | u32 occ; /* RT Ring N Occupancy Register */ | |
71 | u32 indx; /* RT Ring N Current Index Register */ | |
72 | u32 hwocc; /* RT Ring N Hardware Occupancy Register */ | |
73 | u32 hwindx; /* RT Ring N Current Index Register */ | |
74 | }; | |
75 | ||
76 | #define KNAV_RINGACC_RT_REGS_STEP 0x1000 | |
c409b493 VR |
77 | #define K3_DMARING_RING_RT_REGS_STEP 0x2000 |
78 | #define K3_DMARING_RING_RT_REGS_REVERSE_OFS 0x1000 | |
79 | #define KNAV_RINGACC_RT_OCC_MASK GENMASK(20, 0) | |
80 | #define K3_DMARING_RING_RT_OCC_TDOWN_COMPLETE BIT(31) | |
81 | #define K3_DMARING_RING_RT_DB_ENTRY_MASK GENMASK(7, 0) | |
82 | #define K3_DMARING_RING_RT_DB_TDOWN_ACK BIT(31) | |
83 | ||
432f66fe GS |
84 | |
85 | /** | |
86 | * struct k3_nav_ring_fifo_regs - The Ring Accelerator Queues Registers region | |
87 | */ | |
88 | struct k3_nav_ring_fifo_regs { | |
89 | u32 head_data[128]; /* Ring Head Entry Data Registers */ | |
90 | u32 tail_data[128]; /* Ring Tail Entry Data Registers */ | |
91 | u32 peek_head_data[128]; /* Ring Peek Head Entry Data Regs */ | |
92 | u32 peek_tail_data[128]; /* Ring Peek Tail Entry Data Regs */ | |
93 | }; | |
94 | ||
432f66fe GS |
95 | #define KNAV_RINGACC_FIFO_WINDOW_SIZE_BYTES (512U) |
96 | #define KNAV_RINGACC_FIFO_REGS_STEP 0x1000 | |
97 | #define KNAV_RINGACC_MAX_DB_RING_CNT (127U) | |
98 | ||
99 | /** | |
100 | * struct k3_nav_ring_ops - Ring operations | |
101 | */ | |
102 | struct k3_nav_ring_ops { | |
103 | int (*push_tail)(struct k3_nav_ring *ring, void *elm); | |
104 | int (*push_head)(struct k3_nav_ring *ring, void *elm); | |
105 | int (*pop_tail)(struct k3_nav_ring *ring, void *elm); | |
106 | int (*pop_head)(struct k3_nav_ring *ring, void *elm); | |
107 | }; | |
108 | ||
db08a1df VR |
109 | /** |
110 | * struct k3_nav_ring_state - Internal state tracking structure | |
111 | * | |
112 | * @free: Number of free entries | |
113 | * @occ: Occupancy | |
114 | * @windex: Write index | |
115 | * @rindex: Read index | |
116 | */ | |
117 | struct k3_nav_ring_state { | |
118 | u32 free; | |
119 | u32 occ; | |
120 | u32 windex; | |
121 | u32 rindex; | |
122 | u32 tdown_complete:1; | |
123 | }; | |
124 | ||
432f66fe GS |
125 | /** |
126 | * struct k3_nav_ring - RA Ring descriptor | |
127 | * | |
86e58800 | 128 | * @cfg - Ring configuration registers |
432f66fe GS |
129 | * @rt - Ring control/status registers |
130 | * @fifos - Ring queues registers | |
432f66fe GS |
131 | * @ring_mem_dma - Ring buffer dma address |
132 | * @ring_mem_virt - Ring buffer virt address | |
133 | * @ops - Ring operations | |
134 | * @size - Ring size in elements | |
135 | * @elm_size - Size of the ring element | |
136 | * @mode - Ring mode | |
137 | * @flags - flags | |
432f66fe GS |
138 | * @ring_id - Ring Id |
139 | * @parent - Pointer on struct @k3_nav_ringacc | |
140 | * @use_count - Use count for shared rings | |
432f66fe GS |
141 | */ |
142 | struct k3_nav_ring { | |
86e58800 | 143 | struct k3_nav_ring_cfg_regs __iomem *cfg; |
432f66fe GS |
144 | struct k3_nav_ring_rt_regs __iomem *rt; |
145 | struct k3_nav_ring_fifo_regs __iomem *fifos; | |
432f66fe GS |
146 | dma_addr_t ring_mem_dma; |
147 | void *ring_mem_virt; | |
148 | struct k3_nav_ring_ops *ops; | |
149 | u32 size; | |
150 | enum k3_nav_ring_size elm_size; | |
151 | enum k3_nav_ring_mode mode; | |
152 | u32 flags; | |
153 | #define KNAV_RING_FLAG_BUSY BIT(1) | |
154 | #define K3_NAV_RING_FLAG_SHARED BIT(2) | |
c409b493 | 155 | #define K3_NAV_RING_FLAG_REVERSE BIT(3) |
db08a1df | 156 | struct k3_nav_ring_state state; |
432f66fe GS |
157 | u32 ring_id; |
158 | struct k3_nav_ringacc *parent; | |
159 | u32 use_count; | |
432f66fe GS |
160 | }; |
161 | ||
b3f95997 VR |
162 | struct k3_nav_ringacc_ops { |
163 | int (*init)(struct udevice *dev, struct k3_nav_ringacc *ringacc); | |
164 | }; | |
165 | ||
432f66fe GS |
166 | /** |
167 | * struct k3_nav_ringacc - Rings accelerator descriptor | |
168 | * | |
169 | * @dev - pointer on RA device | |
432f66fe GS |
170 | * @num_rings - number of ring in RA |
171 | * @rm_gp_range - general purpose rings range from tisci | |
172 | * @dma_ring_reset_quirk - DMA reset w/a enable | |
173 | * @num_proxies - number of RA proxies | |
174 | * @rings - array of rings descriptors (struct @k3_nav_ring) | |
175 | * @list - list of RAs in the system | |
176 | * @tisci - pointer ti-sci handle | |
177 | * @tisci_ring_ops - ti-sci rings ops | |
178 | * @tisci_dev_id - ti-sci device id | |
b3f95997 | 179 | * @ops: SoC specific ringacc operation |
c409b493 | 180 | * @dual_ring: indicate k3_dmaring dual ring support |
432f66fe GS |
181 | */ |
182 | struct k3_nav_ringacc { | |
183 | struct udevice *dev; | |
432f66fe GS |
184 | u32 num_rings; /* number of rings in Ringacc module */ |
185 | unsigned long *rings_inuse; | |
186 | struct ti_sci_resource *rm_gp_range; | |
187 | bool dma_ring_reset_quirk; | |
188 | u32 num_proxies; | |
432f66fe GS |
189 | |
190 | struct k3_nav_ring *rings; | |
191 | struct list_head list; | |
192 | ||
193 | const struct ti_sci_handle *tisci; | |
194 | const struct ti_sci_rm_ringacc_ops *tisci_ring_ops; | |
195 | u32 tisci_dev_id; | |
b3f95997 VR |
196 | |
197 | const struct k3_nav_ringacc_ops *ops; | |
c409b493 | 198 | bool dual_ring; |
432f66fe GS |
199 | }; |
200 | ||
86e58800 VR |
201 | #include "k3-navss-ringacc-u-boot.c" |
202 | ||
c409b493 VR |
203 | static int k3_nav_ringacc_ring_read_occ(struct k3_nav_ring *ring) |
204 | { | |
205 | return readl(&ring->rt->occ) & KNAV_RINGACC_RT_OCC_MASK; | |
206 | } | |
207 | ||
208 | static void k3_nav_ringacc_ring_update_occ(struct k3_nav_ring *ring) | |
209 | { | |
210 | u32 val; | |
211 | ||
212 | val = readl(&ring->rt->occ); | |
213 | ||
214 | ring->state.occ = val & KNAV_RINGACC_RT_OCC_MASK; | |
215 | ring->state.tdown_complete = !!(val & K3_DMARING_RING_RT_OCC_TDOWN_COMPLETE); | |
216 | } | |
217 | ||
432f66fe GS |
218 | static void *k3_nav_ringacc_get_elm_addr(struct k3_nav_ring *ring, u32 idx) |
219 | { | |
220 | return (idx * (4 << ring->elm_size) + ring->ring_mem_virt); | |
221 | } | |
222 | ||
223 | static int k3_nav_ringacc_ring_push_mem(struct k3_nav_ring *ring, void *elem); | |
224 | static int k3_nav_ringacc_ring_pop_mem(struct k3_nav_ring *ring, void *elem); | |
c409b493 VR |
225 | static int k3_dmaring_ring_fwd_pop_mem(struct k3_nav_ring *ring, void *elem); |
226 | static int k3_dmaring_ring_reverse_pop_mem(struct k3_nav_ring *ring, void *elem); | |
432f66fe GS |
227 | |
228 | static struct k3_nav_ring_ops k3_nav_mode_ring_ops = { | |
229 | .push_tail = k3_nav_ringacc_ring_push_mem, | |
230 | .pop_head = k3_nav_ringacc_ring_pop_mem, | |
231 | }; | |
232 | ||
c409b493 VR |
233 | static struct k3_nav_ring_ops k3_dmaring_fwd_ring_ops = { |
234 | .push_tail = k3_nav_ringacc_ring_push_mem, | |
235 | .pop_head = k3_dmaring_ring_fwd_pop_mem, | |
236 | }; | |
237 | ||
238 | static struct k3_nav_ring_ops k3_dmaring_reverse_ring_ops = { | |
239 | .pop_head = k3_dmaring_ring_reverse_pop_mem, | |
240 | }; | |
241 | ||
432f66fe GS |
242 | struct udevice *k3_nav_ringacc_get_dev(struct k3_nav_ringacc *ringacc) |
243 | { | |
244 | return ringacc->dev; | |
245 | } | |
246 | ||
247 | struct k3_nav_ring *k3_nav_ringacc_request_ring(struct k3_nav_ringacc *ringacc, | |
f1e97c70 | 248 | int id) |
432f66fe | 249 | { |
432f66fe GS |
250 | if (id == K3_NAV_RINGACC_RING_ID_ANY) { |
251 | /* Request for any general purpose ring */ | |
252 | struct ti_sci_resource_desc *gp_rings = | |
253 | &ringacc->rm_gp_range->desc[0]; | |
254 | unsigned long size; | |
255 | ||
256 | size = gp_rings->start + gp_rings->num; | |
257 | id = find_next_zero_bit(ringacc->rings_inuse, | |
258 | size, gp_rings->start); | |
259 | if (id == size) | |
260 | goto error; | |
261 | } else if (id < 0) { | |
262 | goto error; | |
263 | } | |
264 | ||
265 | if (test_bit(id, ringacc->rings_inuse) && | |
266 | !(ringacc->rings[id].flags & K3_NAV_RING_FLAG_SHARED)) | |
267 | goto error; | |
268 | else if (ringacc->rings[id].flags & K3_NAV_RING_FLAG_SHARED) | |
269 | goto out; | |
270 | ||
432f66fe GS |
271 | if (!try_module_get(ringacc->dev->driver->owner)) |
272 | goto error; | |
273 | ||
f1e97c70 | 274 | pr_debug("Giving ring#%d\n", id); |
432f66fe GS |
275 | |
276 | set_bit(id, ringacc->rings_inuse); | |
277 | out: | |
278 | ringacc->rings[id].use_count++; | |
279 | return &ringacc->rings[id]; | |
280 | ||
281 | error: | |
282 | return NULL; | |
283 | } | |
284 | ||
c409b493 VR |
285 | static int k3_dmaring_ring_request_rings_pair(struct k3_nav_ringacc *ringacc, |
286 | int fwd_id, int compl_id, | |
287 | struct k3_nav_ring **fwd_ring, | |
288 | struct k3_nav_ring **compl_ring) | |
289 | { | |
290 | /* k3_dmaring: fwd_id == compl_id, so we ignore compl_id */ | |
291 | if (fwd_id < 0) | |
292 | return -EINVAL; | |
293 | ||
294 | if (test_bit(fwd_id, ringacc->rings_inuse)) | |
295 | return -EBUSY; | |
296 | ||
297 | *fwd_ring = &ringacc->rings[fwd_id]; | |
298 | *compl_ring = &ringacc->rings[fwd_id + ringacc->num_rings]; | |
299 | set_bit(fwd_id, ringacc->rings_inuse); | |
300 | ringacc->rings[fwd_id].use_count++; | |
301 | dev_dbg(ringacc->dev, "Giving ring#%d\n", fwd_id); | |
302 | ||
303 | return 0; | |
304 | } | |
305 | ||
5d257849 VR |
306 | int k3_nav_ringacc_request_rings_pair(struct k3_nav_ringacc *ringacc, |
307 | int fwd_id, int compl_id, | |
308 | struct k3_nav_ring **fwd_ring, | |
309 | struct k3_nav_ring **compl_ring) | |
310 | { | |
311 | int ret = 0; | |
312 | ||
313 | if (!fwd_ring || !compl_ring) | |
314 | return -EINVAL; | |
315 | ||
c409b493 VR |
316 | if (ringacc->dual_ring) |
317 | return k3_dmaring_ring_request_rings_pair(ringacc, fwd_id, compl_id, | |
318 | fwd_ring, compl_ring); | |
319 | ||
f1e97c70 | 320 | *fwd_ring = k3_nav_ringacc_request_ring(ringacc, fwd_id); |
5d257849 VR |
321 | if (!(*fwd_ring)) |
322 | return -ENODEV; | |
323 | ||
f1e97c70 | 324 | *compl_ring = k3_nav_ringacc_request_ring(ringacc, compl_id); |
5d257849 VR |
325 | if (!(*compl_ring)) { |
326 | k3_nav_ringacc_ring_free(*fwd_ring); | |
327 | ret = -ENODEV; | |
328 | } | |
329 | ||
330 | return ret; | |
331 | } | |
332 | ||
432f66fe GS |
333 | static void k3_ringacc_ring_reset_sci(struct k3_nav_ring *ring) |
334 | { | |
335 | struct k3_nav_ringacc *ringacc = ring->parent; | |
336 | int ret; | |
337 | ||
86e58800 VR |
338 | if (IS_ENABLED(CONFIG_K3_DM_FW)) |
339 | return k3_ringacc_ring_reset_raw(ring); | |
340 | ||
432f66fe GS |
341 | ret = ringacc->tisci_ring_ops->config( |
342 | ringacc->tisci, | |
343 | TI_SCI_MSG_VALUE_RM_RING_COUNT_VALID, | |
344 | ringacc->tisci_dev_id, | |
345 | ring->ring_id, | |
346 | 0, | |
347 | 0, | |
348 | ring->size, | |
349 | 0, | |
350 | 0, | |
351 | 0); | |
352 | if (ret) | |
353 | dev_err(ringacc->dev, "TISCI reset ring fail (%d) ring_idx %d\n", | |
354 | ret, ring->ring_id); | |
355 | } | |
356 | ||
357 | void k3_nav_ringacc_ring_reset(struct k3_nav_ring *ring) | |
358 | { | |
359 | if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY)) | |
360 | return; | |
361 | ||
db08a1df | 362 | memset(&ring->state, 0, sizeof(ring->state)); |
432f66fe GS |
363 | |
364 | k3_ringacc_ring_reset_sci(ring); | |
365 | } | |
366 | ||
367 | static void k3_ringacc_ring_reconfig_qmode_sci(struct k3_nav_ring *ring, | |
368 | enum k3_nav_ring_mode mode) | |
369 | { | |
370 | struct k3_nav_ringacc *ringacc = ring->parent; | |
371 | int ret; | |
372 | ||
86e58800 VR |
373 | if (IS_ENABLED(CONFIG_K3_DM_FW)) |
374 | return k3_ringacc_ring_reconfig_qmode_raw(ring, mode); | |
375 | ||
432f66fe GS |
376 | ret = ringacc->tisci_ring_ops->config( |
377 | ringacc->tisci, | |
378 | TI_SCI_MSG_VALUE_RM_RING_MODE_VALID, | |
379 | ringacc->tisci_dev_id, | |
380 | ring->ring_id, | |
381 | 0, | |
382 | 0, | |
383 | 0, | |
384 | mode, | |
385 | 0, | |
386 | 0); | |
387 | if (ret) | |
388 | dev_err(ringacc->dev, "TISCI reconf qmode fail (%d) ring_idx %d\n", | |
389 | ret, ring->ring_id); | |
390 | } | |
391 | ||
392 | void k3_nav_ringacc_ring_reset_dma(struct k3_nav_ring *ring, u32 occ) | |
393 | { | |
394 | if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY)) | |
395 | return; | |
396 | ||
62a96201 VR |
397 | if (!ring->parent->dma_ring_reset_quirk) { |
398 | k3_nav_ringacc_ring_reset(ring); | |
432f66fe | 399 | return; |
62a96201 | 400 | } |
432f66fe GS |
401 | |
402 | if (!occ) | |
403 | occ = ringacc_readl(&ring->rt->occ); | |
404 | ||
405 | if (occ) { | |
406 | u32 db_ring_cnt, db_ring_cnt_cur; | |
407 | ||
408 | pr_debug("%s %u occ: %u\n", __func__, | |
409 | ring->ring_id, occ); | |
410 | /* 2. Reset the ring */ | |
411 | k3_ringacc_ring_reset_sci(ring); | |
412 | ||
413 | /* | |
414 | * 3. Setup the ring in ring/doorbell mode | |
415 | * (if not already in this mode) | |
416 | */ | |
417 | if (ring->mode != K3_NAV_RINGACC_RING_MODE_RING) | |
418 | k3_ringacc_ring_reconfig_qmode_sci( | |
419 | ring, K3_NAV_RINGACC_RING_MODE_RING); | |
420 | /* | |
81f3a665 | 421 | * 4. Ring the doorbell 2**22 - ringOcc times. |
432f66fe GS |
422 | * This will wrap the internal UDMAP ring state occupancy |
423 | * counter (which is 21-bits wide) to 0. | |
424 | */ | |
425 | db_ring_cnt = (1U << 22) - occ; | |
426 | ||
427 | while (db_ring_cnt != 0) { | |
428 | /* | |
429 | * Ring the doorbell with the maximum count each | |
430 | * iteration if possible to minimize the total | |
431 | * of writes | |
432 | */ | |
433 | if (db_ring_cnt > KNAV_RINGACC_MAX_DB_RING_CNT) | |
434 | db_ring_cnt_cur = KNAV_RINGACC_MAX_DB_RING_CNT; | |
435 | else | |
436 | db_ring_cnt_cur = db_ring_cnt; | |
437 | ||
438 | writel(db_ring_cnt_cur, &ring->rt->db); | |
439 | db_ring_cnt -= db_ring_cnt_cur; | |
440 | } | |
441 | ||
442 | /* 5. Restore the original ring mode (if not ring mode) */ | |
443 | if (ring->mode != K3_NAV_RINGACC_RING_MODE_RING) | |
444 | k3_ringacc_ring_reconfig_qmode_sci(ring, ring->mode); | |
445 | } | |
446 | ||
447 | /* 2. Reset the ring */ | |
448 | k3_nav_ringacc_ring_reset(ring); | |
449 | } | |
450 | ||
451 | static void k3_ringacc_ring_free_sci(struct k3_nav_ring *ring) | |
452 | { | |
453 | struct k3_nav_ringacc *ringacc = ring->parent; | |
454 | int ret; | |
455 | ||
86e58800 VR |
456 | if (IS_ENABLED(CONFIG_K3_DM_FW)) |
457 | return k3_ringacc_ring_free_raw(ring); | |
458 | ||
432f66fe GS |
459 | ret = ringacc->tisci_ring_ops->config( |
460 | ringacc->tisci, | |
461 | TI_SCI_MSG_VALUE_RM_ALL_NO_ORDER, | |
462 | ringacc->tisci_dev_id, | |
463 | ring->ring_id, | |
464 | 0, | |
465 | 0, | |
466 | 0, | |
467 | 0, | |
468 | 0, | |
469 | 0); | |
470 | if (ret) | |
471 | dev_err(ringacc->dev, "TISCI ring free fail (%d) ring_idx %d\n", | |
472 | ret, ring->ring_id); | |
473 | } | |
474 | ||
475 | int k3_nav_ringacc_ring_free(struct k3_nav_ring *ring) | |
476 | { | |
477 | struct k3_nav_ringacc *ringacc; | |
478 | ||
479 | if (!ring) | |
480 | return -EINVAL; | |
481 | ||
482 | ringacc = ring->parent; | |
483 | ||
c409b493 VR |
484 | /* |
485 | * k3_dmaring: rings shared memory and configuration, only forward ring is | |
486 | * configured and reverse ring considered as slave. | |
487 | */ | |
488 | if (ringacc->dual_ring && (ring->flags & K3_NAV_RING_FLAG_REVERSE)) | |
489 | return 0; | |
490 | ||
432f66fe GS |
491 | pr_debug("%s flags: 0x%08x\n", __func__, ring->flags); |
492 | ||
493 | if (!test_bit(ring->ring_id, ringacc->rings_inuse)) | |
494 | return -EINVAL; | |
495 | ||
496 | if (--ring->use_count) | |
497 | goto out; | |
498 | ||
499 | if (!(ring->flags & KNAV_RING_FLAG_BUSY)) | |
500 | goto no_init; | |
501 | ||
502 | k3_ringacc_ring_free_sci(ring); | |
503 | ||
504 | dma_free_coherent(ringacc->dev, | |
505 | ring->size * (4 << ring->elm_size), | |
506 | ring->ring_mem_virt, ring->ring_mem_dma); | |
507 | ring->flags &= ~KNAV_RING_FLAG_BUSY; | |
508 | ring->ops = NULL; | |
432f66fe GS |
509 | |
510 | no_init: | |
511 | clear_bit(ring->ring_id, ringacc->rings_inuse); | |
512 | ||
513 | module_put(ringacc->dev->driver->owner); | |
514 | ||
515 | out: | |
516 | return 0; | |
517 | } | |
518 | ||
519 | u32 k3_nav_ringacc_get_ring_id(struct k3_nav_ring *ring) | |
520 | { | |
521 | if (!ring) | |
522 | return -EINVAL; | |
523 | ||
524 | return ring->ring_id; | |
525 | } | |
526 | ||
527 | static int k3_nav_ringacc_ring_cfg_sci(struct k3_nav_ring *ring) | |
528 | { | |
529 | struct k3_nav_ringacc *ringacc = ring->parent; | |
530 | u32 ring_idx; | |
531 | int ret; | |
532 | ||
533 | if (!ringacc->tisci) | |
534 | return -EINVAL; | |
535 | ||
536 | ring_idx = ring->ring_id; | |
537 | ret = ringacc->tisci_ring_ops->config( | |
538 | ringacc->tisci, | |
539 | TI_SCI_MSG_VALUE_RM_ALL_NO_ORDER, | |
540 | ringacc->tisci_dev_id, | |
541 | ring_idx, | |
542 | lower_32_bits(ring->ring_mem_dma), | |
543 | upper_32_bits(ring->ring_mem_dma), | |
544 | ring->size, | |
545 | ring->mode, | |
546 | ring->elm_size, | |
547 | 0); | |
86e58800 | 548 | if (ret) { |
432f66fe GS |
549 | dev_err(ringacc->dev, "TISCI config ring fail (%d) ring_idx %d\n", |
550 | ret, ring_idx); | |
86e58800 VR |
551 | return ret; |
552 | } | |
432f66fe | 553 | |
86e58800 VR |
554 | /* |
555 | * Above TI SCI call handles firewall configuration, cfg | |
556 | * register configuration still has to be done locally in | |
557 | * absence of RM services. | |
558 | */ | |
559 | if (IS_ENABLED(CONFIG_K3_DM_FW)) | |
560 | k3_nav_ringacc_ring_cfg_raw(ring); | |
561 | ||
562 | return 0; | |
432f66fe GS |
563 | } |
564 | ||
c409b493 VR |
565 | static int k3_dmaring_ring_cfg(struct k3_nav_ring *ring, struct k3_nav_ring_cfg *cfg) |
566 | { | |
567 | struct k3_nav_ringacc *ringacc; | |
568 | struct k3_nav_ring *reverse_ring; | |
569 | int ret = 0; | |
570 | ||
571 | if (cfg->elm_size != K3_NAV_RINGACC_RING_ELSIZE_8 || | |
572 | cfg->mode != K3_NAV_RINGACC_RING_MODE_RING || | |
573 | cfg->size & ~K3_DMARING_RING_CFG_RING_SIZE_ELCNT_MASK) | |
574 | return -EINVAL; | |
575 | ||
576 | ringacc = ring->parent; | |
577 | ||
578 | /* | |
579 | * k3_dmaring: rings shared memory and configuration, only forward ring is | |
580 | * configured and reverse ring considered as slave. | |
581 | */ | |
582 | if (ringacc->dual_ring && (ring->flags & K3_NAV_RING_FLAG_REVERSE)) | |
583 | return 0; | |
584 | ||
585 | if (!test_bit(ring->ring_id, ringacc->rings_inuse)) | |
586 | return -EINVAL; | |
587 | ||
588 | ring->size = cfg->size; | |
589 | ring->elm_size = cfg->elm_size; | |
590 | ring->mode = cfg->mode; | |
591 | memset(&ring->state, 0, sizeof(ring->state)); | |
592 | ||
593 | ring->ops = &k3_dmaring_fwd_ring_ops; | |
594 | ||
595 | ring->ring_mem_virt = | |
596 | dma_alloc_coherent(ring->size * (4 << ring->elm_size), | |
597 | (unsigned long *)&ring->ring_mem_dma); | |
598 | if (!ring->ring_mem_virt) { | |
599 | dev_err(ringacc->dev, "Failed to alloc ring mem\n"); | |
600 | ret = -ENOMEM; | |
601 | goto err_free_ops; | |
602 | } | |
603 | ||
604 | ret = k3_nav_ringacc_ring_cfg_sci(ring); | |
605 | if (ret) | |
606 | goto err_free_mem; | |
607 | ||
608 | ring->flags |= KNAV_RING_FLAG_BUSY; | |
609 | ||
610 | /* k3_dmaring: configure reverse ring */ | |
611 | reverse_ring = &ringacc->rings[ring->ring_id + ringacc->num_rings]; | |
612 | reverse_ring->size = cfg->size; | |
613 | reverse_ring->elm_size = cfg->elm_size; | |
614 | reverse_ring->mode = cfg->mode; | |
615 | memset(&reverse_ring->state, 0, sizeof(reverse_ring->state)); | |
616 | reverse_ring->ops = &k3_dmaring_reverse_ring_ops; | |
617 | ||
618 | reverse_ring->ring_mem_virt = ring->ring_mem_virt; | |
619 | reverse_ring->ring_mem_dma = ring->ring_mem_dma; | |
620 | reverse_ring->flags |= KNAV_RING_FLAG_BUSY; | |
621 | ||
622 | return 0; | |
623 | ||
624 | err_free_mem: | |
625 | dma_free_coherent(ringacc->dev, | |
626 | ring->size * (4 << ring->elm_size), | |
627 | ring->ring_mem_virt, | |
628 | ring->ring_mem_dma); | |
629 | err_free_ops: | |
630 | ring->ops = NULL; | |
c409b493 VR |
631 | return ret; |
632 | } | |
633 | ||
432f66fe GS |
634 | int k3_nav_ringacc_ring_cfg(struct k3_nav_ring *ring, |
635 | struct k3_nav_ring_cfg *cfg) | |
636 | { | |
637 | struct k3_nav_ringacc *ringacc = ring->parent; | |
638 | int ret = 0; | |
639 | ||
640 | if (!ring || !cfg) | |
641 | return -EINVAL; | |
c409b493 VR |
642 | |
643 | if (ringacc->dual_ring) | |
644 | return k3_dmaring_ring_cfg(ring, cfg); | |
645 | ||
432f66fe GS |
646 | if (cfg->elm_size > K3_NAV_RINGACC_RING_ELSIZE_256 || |
647 | cfg->mode > K3_NAV_RINGACC_RING_MODE_QM || | |
648 | cfg->size & ~KNAV_RINGACC_CFG_RING_SIZE_ELCNT_MASK || | |
649 | !test_bit(ring->ring_id, ringacc->rings_inuse)) | |
650 | return -EINVAL; | |
651 | ||
652 | if (ring->use_count != 1) | |
653 | return 0; | |
654 | ||
655 | ring->size = cfg->size; | |
656 | ring->elm_size = cfg->elm_size; | |
657 | ring->mode = cfg->mode; | |
db08a1df | 658 | memset(&ring->state, 0, sizeof(ring->state)); |
432f66fe | 659 | |
432f66fe GS |
660 | switch (ring->mode) { |
661 | case K3_NAV_RINGACC_RING_MODE_RING: | |
662 | ring->ops = &k3_nav_mode_ring_ops; | |
663 | break; | |
432f66fe GS |
664 | default: |
665 | ring->ops = NULL; | |
666 | ret = -EINVAL; | |
f1e97c70 | 667 | goto err_free_ops; |
432f66fe GS |
668 | }; |
669 | ||
670 | ring->ring_mem_virt = | |
671 | dma_zalloc_coherent(ringacc->dev, | |
672 | ring->size * (4 << ring->elm_size), | |
673 | &ring->ring_mem_dma, GFP_KERNEL); | |
674 | if (!ring->ring_mem_virt) { | |
675 | dev_err(ringacc->dev, "Failed to alloc ring mem\n"); | |
676 | ret = -ENOMEM; | |
677 | goto err_free_ops; | |
678 | } | |
679 | ||
680 | ret = k3_nav_ringacc_ring_cfg_sci(ring); | |
681 | ||
682 | if (ret) | |
683 | goto err_free_mem; | |
684 | ||
685 | ring->flags |= KNAV_RING_FLAG_BUSY; | |
686 | ring->flags |= (cfg->flags & K3_NAV_RINGACC_RING_SHARED) ? | |
687 | K3_NAV_RING_FLAG_SHARED : 0; | |
688 | ||
689 | return 0; | |
690 | ||
691 | err_free_mem: | |
692 | dma_free_coherent(ringacc->dev, | |
693 | ring->size * (4 << ring->elm_size), | |
694 | ring->ring_mem_virt, | |
695 | ring->ring_mem_dma); | |
696 | err_free_ops: | |
697 | ring->ops = NULL; | |
432f66fe GS |
698 | return ret; |
699 | } | |
700 | ||
701 | u32 k3_nav_ringacc_ring_get_size(struct k3_nav_ring *ring) | |
702 | { | |
703 | if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY)) | |
704 | return -EINVAL; | |
705 | ||
706 | return ring->size; | |
707 | } | |
708 | ||
709 | u32 k3_nav_ringacc_ring_get_free(struct k3_nav_ring *ring) | |
710 | { | |
711 | if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY)) | |
712 | return -EINVAL; | |
713 | ||
db08a1df VR |
714 | if (!ring->state.free) |
715 | ring->state.free = ring->size - ringacc_readl(&ring->rt->occ); | |
432f66fe | 716 | |
db08a1df | 717 | return ring->state.free; |
432f66fe GS |
718 | } |
719 | ||
720 | u32 k3_nav_ringacc_ring_get_occ(struct k3_nav_ring *ring) | |
721 | { | |
722 | if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY)) | |
723 | return -EINVAL; | |
724 | ||
725 | return ringacc_readl(&ring->rt->occ); | |
726 | } | |
727 | ||
728 | u32 k3_nav_ringacc_ring_is_full(struct k3_nav_ring *ring) | |
729 | { | |
730 | return !k3_nav_ringacc_ring_get_free(ring); | |
731 | } | |
732 | ||
733 | enum k3_ringacc_access_mode { | |
734 | K3_RINGACC_ACCESS_MODE_PUSH_HEAD, | |
735 | K3_RINGACC_ACCESS_MODE_POP_HEAD, | |
736 | K3_RINGACC_ACCESS_MODE_PUSH_TAIL, | |
737 | K3_RINGACC_ACCESS_MODE_POP_TAIL, | |
738 | K3_RINGACC_ACCESS_MODE_PEEK_HEAD, | |
739 | K3_RINGACC_ACCESS_MODE_PEEK_TAIL, | |
740 | }; | |
741 | ||
c409b493 VR |
742 | static int k3_dmaring_ring_fwd_pop_mem(struct k3_nav_ring *ring, void *elem) |
743 | { | |
744 | void *elem_ptr; | |
745 | u32 elem_idx; | |
746 | ||
747 | /* | |
748 | * k3_dmaring: forward ring is always tied DMA channel and HW does not | |
749 | * maintain any state data required for POP operation and its unknown | |
750 | * how much elements were consumed by HW. So, to actually | |
751 | * do POP, the read pointer has to be recalculated every time. | |
752 | */ | |
753 | ring->state.occ = k3_nav_ringacc_ring_read_occ(ring); | |
754 | if (ring->state.windex >= ring->state.occ) | |
755 | elem_idx = ring->state.windex - ring->state.occ; | |
756 | else | |
757 | elem_idx = ring->size - (ring->state.occ - ring->state.windex); | |
758 | ||
759 | elem_ptr = k3_nav_ringacc_get_elm_addr(ring, elem_idx); | |
760 | invalidate_dcache_range((unsigned long)ring->ring_mem_virt, | |
761 | ALIGN((unsigned long)ring->ring_mem_virt + | |
762 | ring->size * (4 << ring->elm_size), | |
763 | ARCH_DMA_MINALIGN)); | |
764 | ||
765 | memcpy(elem, elem_ptr, (4 << ring->elm_size)); | |
766 | ||
767 | ring->state.occ--; | |
768 | writel(-1, &ring->rt->db); | |
769 | ||
770 | dev_dbg(ring->parent->dev, "%s: occ%d Windex%d Rindex%d pos_ptr%px\n", | |
771 | __func__, ring->state.occ, ring->state.windex, elem_idx, | |
772 | elem_ptr); | |
773 | return 0; | |
774 | } | |
775 | ||
776 | static int k3_dmaring_ring_reverse_pop_mem(struct k3_nav_ring *ring, void *elem) | |
777 | { | |
778 | void *elem_ptr; | |
779 | ||
780 | elem_ptr = k3_nav_ringacc_get_elm_addr(ring, ring->state.rindex); | |
781 | ||
782 | if (ring->state.occ) { | |
783 | invalidate_dcache_range((unsigned long)ring->ring_mem_virt, | |
784 | ALIGN((unsigned long)ring->ring_mem_virt + | |
785 | ring->size * (4 << ring->elm_size), | |
786 | ARCH_DMA_MINALIGN)); | |
787 | ||
788 | memcpy(elem, elem_ptr, (4 << ring->elm_size)); | |
789 | ring->state.rindex = (ring->state.rindex + 1) % ring->size; | |
790 | ring->state.occ--; | |
791 | writel(-1 & K3_DMARING_RING_RT_DB_ENTRY_MASK, &ring->rt->db); | |
792 | } | |
793 | ||
794 | dev_dbg(ring->parent->dev, "%s: occ%d index%d pos_ptr%px\n", | |
795 | __func__, ring->state.occ, ring->state.rindex, elem_ptr); | |
796 | return 0; | |
797 | } | |
798 | ||
432f66fe GS |
799 | static int k3_nav_ringacc_ring_push_mem(struct k3_nav_ring *ring, void *elem) |
800 | { | |
801 | void *elem_ptr; | |
802 | ||
db08a1df | 803 | elem_ptr = k3_nav_ringacc_get_elm_addr(ring, ring->state.windex); |
432f66fe GS |
804 | |
805 | memcpy(elem_ptr, elem, (4 << ring->elm_size)); | |
806 | ||
9d32a94b VR |
807 | flush_dcache_range((unsigned long)ring->ring_mem_virt, |
808 | ALIGN((unsigned long)ring->ring_mem_virt + | |
809 | ring->size * (4 << ring->elm_size), | |
810 | ARCH_DMA_MINALIGN)); | |
811 | ||
db08a1df VR |
812 | ring->state.windex = (ring->state.windex + 1) % ring->size; |
813 | ring->state.free--; | |
432f66fe GS |
814 | ringacc_writel(1, &ring->rt->db); |
815 | ||
816 | pr_debug("ring_push_mem: free%d index%d\n", | |
db08a1df | 817 | ring->state.free, ring->state.windex); |
432f66fe GS |
818 | |
819 | return 0; | |
820 | } | |
821 | ||
822 | static int k3_nav_ringacc_ring_pop_mem(struct k3_nav_ring *ring, void *elem) | |
823 | { | |
824 | void *elem_ptr; | |
825 | ||
db08a1df | 826 | elem_ptr = k3_nav_ringacc_get_elm_addr(ring, ring->state.rindex); |
432f66fe | 827 | |
9d32a94b VR |
828 | invalidate_dcache_range((unsigned long)ring->ring_mem_virt, |
829 | ALIGN((unsigned long)ring->ring_mem_virt + | |
830 | ring->size * (4 << ring->elm_size), | |
831 | ARCH_DMA_MINALIGN)); | |
832 | ||
432f66fe GS |
833 | memcpy(elem, elem_ptr, (4 << ring->elm_size)); |
834 | ||
db08a1df VR |
835 | ring->state.rindex = (ring->state.rindex + 1) % ring->size; |
836 | ring->state.occ--; | |
432f66fe GS |
837 | ringacc_writel(-1, &ring->rt->db); |
838 | ||
839 | pr_debug("ring_pop_mem: occ%d index%d pos_ptr%p\n", | |
db08a1df | 840 | ring->state.occ, ring->state.rindex, elem_ptr); |
432f66fe GS |
841 | return 0; |
842 | } | |
843 | ||
844 | int k3_nav_ringacc_ring_push(struct k3_nav_ring *ring, void *elem) | |
845 | { | |
846 | int ret = -EOPNOTSUPP; | |
847 | ||
848 | if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY)) | |
849 | return -EINVAL; | |
850 | ||
851 | pr_debug("ring_push%d: free%d index%d\n", | |
db08a1df | 852 | ring->ring_id, ring->state.free, ring->state.windex); |
432f66fe GS |
853 | |
854 | if (k3_nav_ringacc_ring_is_full(ring)) | |
855 | return -ENOMEM; | |
856 | ||
857 | if (ring->ops && ring->ops->push_tail) | |
858 | ret = ring->ops->push_tail(ring, elem); | |
859 | ||
860 | return ret; | |
861 | } | |
862 | ||
863 | int k3_nav_ringacc_ring_push_head(struct k3_nav_ring *ring, void *elem) | |
864 | { | |
865 | int ret = -EOPNOTSUPP; | |
866 | ||
867 | if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY)) | |
868 | return -EINVAL; | |
869 | ||
870 | pr_debug("ring_push_head: free%d index%d\n", | |
db08a1df | 871 | ring->state.free, ring->state.windex); |
432f66fe GS |
872 | |
873 | if (k3_nav_ringacc_ring_is_full(ring)) | |
874 | return -ENOMEM; | |
875 | ||
876 | if (ring->ops && ring->ops->push_head) | |
877 | ret = ring->ops->push_head(ring, elem); | |
878 | ||
879 | return ret; | |
880 | } | |
881 | ||
882 | int k3_nav_ringacc_ring_pop(struct k3_nav_ring *ring, void *elem) | |
883 | { | |
884 | int ret = -EOPNOTSUPP; | |
885 | ||
886 | if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY)) | |
887 | return -EINVAL; | |
888 | ||
db08a1df | 889 | if (!ring->state.occ) |
c409b493 | 890 | k3_nav_ringacc_ring_update_occ(ring); |
432f66fe GS |
891 | |
892 | pr_debug("ring_pop%d: occ%d index%d\n", | |
db08a1df | 893 | ring->ring_id, ring->state.occ, ring->state.rindex); |
432f66fe | 894 | |
db08a1df | 895 | if (!ring->state.occ && !ring->state.tdown_complete) |
432f66fe GS |
896 | return -ENODATA; |
897 | ||
898 | if (ring->ops && ring->ops->pop_head) | |
899 | ret = ring->ops->pop_head(ring, elem); | |
900 | ||
901 | return ret; | |
902 | } | |
903 | ||
904 | int k3_nav_ringacc_ring_pop_tail(struct k3_nav_ring *ring, void *elem) | |
905 | { | |
906 | int ret = -EOPNOTSUPP; | |
907 | ||
908 | if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY)) | |
909 | return -EINVAL; | |
910 | ||
db08a1df | 911 | if (!ring->state.occ) |
c409b493 | 912 | k3_nav_ringacc_ring_update_occ(ring); |
432f66fe GS |
913 | |
914 | pr_debug("ring_pop_tail: occ%d index%d\n", | |
db08a1df | 915 | ring->state.occ, ring->state.rindex); |
432f66fe | 916 | |
db08a1df | 917 | if (!ring->state.occ) |
432f66fe GS |
918 | return -ENODATA; |
919 | ||
920 | if (ring->ops && ring->ops->pop_tail) | |
921 | ret = ring->ops->pop_tail(ring, elem); | |
922 | ||
923 | return ret; | |
924 | } | |
925 | ||
926 | static int k3_nav_ringacc_probe_dt(struct k3_nav_ringacc *ringacc) | |
927 | { | |
928 | struct udevice *dev = ringacc->dev; | |
c409b493 | 929 | struct udevice *devp = dev; |
432f66fe GS |
930 | struct udevice *tisci_dev = NULL; |
931 | int ret; | |
932 | ||
933 | ringacc->num_rings = dev_read_u32_default(dev, "ti,num-rings", 0); | |
934 | if (!ringacc->num_rings) { | |
935 | dev_err(dev, "ti,num-rings read failure %d\n", ret); | |
936 | return -EINVAL; | |
937 | } | |
938 | ||
939 | ringacc->dma_ring_reset_quirk = | |
940 | dev_read_bool(dev, "ti,dma-ring-reset-quirk"); | |
941 | ||
c409b493 | 942 | ret = uclass_get_device_by_phandle(UCLASS_FIRMWARE, devp, |
ec0aeacf | 943 | "ti,sci", &tisci_dev); |
432f66fe GS |
944 | if (ret) { |
945 | pr_debug("TISCI RA RM get failed (%d)\n", ret); | |
946 | ringacc->tisci = NULL; | |
947 | return -ENODEV; | |
948 | } | |
949 | ringacc->tisci = (struct ti_sci_handle *) | |
950 | (ti_sci_get_handle_from_sysfw(tisci_dev)); | |
951 | ||
c409b493 | 952 | ret = dev_read_u32_default(devp, "ti,sci", 0); |
432f66fe GS |
953 | if (!ret) { |
954 | dev_err(dev, "TISCI RA RM disabled\n"); | |
955 | ringacc->tisci = NULL; | |
956 | return ret; | |
957 | } | |
958 | ||
c409b493 | 959 | ret = dev_read_u32(devp, "ti,sci-dev-id", &ringacc->tisci_dev_id); |
432f66fe GS |
960 | if (ret) { |
961 | dev_err(dev, "ti,sci-dev-id read failure %d\n", ret); | |
962 | ringacc->tisci = NULL; | |
963 | return ret; | |
964 | } | |
965 | ||
966 | ringacc->rm_gp_range = devm_ti_sci_get_of_resource( | |
967 | ringacc->tisci, dev, | |
968 | ringacc->tisci_dev_id, | |
969 | "ti,sci-rm-range-gp-rings"); | |
970 | if (IS_ERR(ringacc->rm_gp_range)) | |
971 | ret = PTR_ERR(ringacc->rm_gp_range); | |
972 | ||
973 | return 0; | |
974 | } | |
975 | ||
b3f95997 | 976 | static int k3_nav_ringacc_init(struct udevice *dev, struct k3_nav_ringacc *ringacc) |
432f66fe | 977 | { |
86e58800 | 978 | void __iomem *base_cfg, *base_rt; |
432f66fe GS |
979 | int ret, i; |
980 | ||
432f66fe GS |
981 | ret = k3_nav_ringacc_probe_dt(ringacc); |
982 | if (ret) | |
983 | return ret; | |
984 | ||
86e58800 VR |
985 | base_cfg = dev_remap_addr_name(dev, "cfg"); |
986 | pr_debug("cfg %p\n", base_cfg); | |
987 | if (!base_cfg) | |
988 | return -EINVAL; | |
989 | ||
5fecea17 | 990 | base_rt = dev_read_addr_name_ptr(dev, "rt"); |
432f66fe | 991 | pr_debug("rt %p\n", base_rt); |
5fecea17 MS |
992 | if (!base_rt) |
993 | return -EINVAL; | |
432f66fe | 994 | |
432f66fe GS |
995 | ringacc->rings = devm_kzalloc(dev, |
996 | sizeof(*ringacc->rings) * | |
997 | ringacc->num_rings, | |
998 | GFP_KERNEL); | |
999 | ringacc->rings_inuse = devm_kcalloc(dev, | |
1000 | BITS_TO_LONGS(ringacc->num_rings), | |
1001 | sizeof(unsigned long), GFP_KERNEL); | |
432f66fe | 1002 | |
f1e97c70 | 1003 | if (!ringacc->rings || !ringacc->rings_inuse) |
432f66fe GS |
1004 | return -ENOMEM; |
1005 | ||
1006 | for (i = 0; i < ringacc->num_rings; i++) { | |
86e58800 VR |
1007 | ringacc->rings[i].cfg = base_cfg + |
1008 | KNAV_RINGACC_CFG_REGS_STEP * i; | |
432f66fe GS |
1009 | ringacc->rings[i].rt = base_rt + |
1010 | KNAV_RINGACC_RT_REGS_STEP * i; | |
432f66fe GS |
1011 | ringacc->rings[i].parent = ringacc; |
1012 | ringacc->rings[i].ring_id = i; | |
432f66fe GS |
1013 | } |
1014 | dev_set_drvdata(dev, ringacc); | |
1015 | ||
1016 | ringacc->tisci_ring_ops = &ringacc->tisci->ops.rm_ring_ops; | |
1017 | ||
1018 | list_add_tail(&ringacc->list, &k3_nav_ringacc_list); | |
1019 | ||
1020 | dev_info(dev, "Ring Accelerator probed rings:%u, gp-rings[%u,%u] sci-dev-id:%u\n", | |
1021 | ringacc->num_rings, | |
1022 | ringacc->rm_gp_range->desc[0].start, | |
1023 | ringacc->rm_gp_range->desc[0].num, | |
1024 | ringacc->tisci_dev_id); | |
1025 | dev_info(dev, "dma-ring-reset-quirk: %s\n", | |
1026 | ringacc->dma_ring_reset_quirk ? "enabled" : "disabled"); | |
432f66fe GS |
1027 | return 0; |
1028 | } | |
1029 | ||
c409b493 VR |
1030 | struct k3_nav_ringacc *k3_ringacc_dmarings_init(struct udevice *dev, |
1031 | struct k3_ringacc_init_data *data) | |
1032 | { | |
1033 | struct k3_nav_ringacc *ringacc; | |
1034 | void __iomem *base_rt; | |
1035 | int i; | |
1036 | ||
1037 | ringacc = devm_kzalloc(dev, sizeof(*ringacc), GFP_KERNEL); | |
1038 | if (!ringacc) | |
1039 | return ERR_PTR(-ENOMEM); | |
1040 | ||
1041 | ringacc->dual_ring = true; | |
1042 | ||
1043 | ringacc->dev = dev; | |
1044 | ringacc->num_rings = data->num_rings; | |
1045 | ringacc->tisci = data->tisci; | |
1046 | ringacc->tisci_dev_id = data->tisci_dev_id; | |
1047 | ||
5fecea17 MS |
1048 | base_rt = dev_read_addr_name_ptr(dev, "ringrt"); |
1049 | if (!base_rt) | |
1050 | return ERR_PTR(-EINVAL); | |
c409b493 VR |
1051 | |
1052 | ringacc->rings = devm_kzalloc(dev, | |
1053 | sizeof(*ringacc->rings) * | |
1054 | ringacc->num_rings * 2, | |
1055 | GFP_KERNEL); | |
1056 | ringacc->rings_inuse = devm_kcalloc(dev, | |
1057 | BITS_TO_LONGS(ringacc->num_rings), | |
1058 | sizeof(unsigned long), GFP_KERNEL); | |
1059 | ||
1060 | if (!ringacc->rings || !ringacc->rings_inuse) | |
1061 | return ERR_PTR(-ENOMEM); | |
1062 | ||
1063 | for (i = 0; i < ringacc->num_rings; i++) { | |
1064 | struct k3_nav_ring *ring = &ringacc->rings[i]; | |
1065 | ||
1066 | ring->rt = base_rt + K3_DMARING_RING_RT_REGS_STEP * i; | |
1067 | ring->parent = ringacc; | |
1068 | ring->ring_id = i; | |
c409b493 VR |
1069 | |
1070 | ring = &ringacc->rings[ringacc->num_rings + i]; | |
1071 | ring->rt = base_rt + K3_DMARING_RING_RT_REGS_STEP * i + | |
1072 | K3_DMARING_RING_RT_REGS_REVERSE_OFS; | |
1073 | ring->parent = ringacc; | |
1074 | ring->ring_id = i; | |
c409b493 VR |
1075 | ring->flags = K3_NAV_RING_FLAG_REVERSE; |
1076 | } | |
1077 | ||
1078 | ringacc->tisci_ring_ops = &ringacc->tisci->ops.rm_ring_ops; | |
1079 | ||
1080 | dev_info(dev, "k3_dmaring Ring probed rings:%u, sci-dev-id:%u\n", | |
1081 | ringacc->num_rings, | |
1082 | ringacc->tisci_dev_id); | |
1083 | dev_info(dev, "dma-ring-reset-quirk: %s\n", | |
1084 | ringacc->dma_ring_reset_quirk ? "enabled" : "disabled"); | |
1085 | ||
1086 | return ringacc; | |
1087 | } | |
1088 | ||
b3f95997 VR |
1089 | struct ringacc_match_data { |
1090 | struct k3_nav_ringacc_ops ops; | |
1091 | }; | |
1092 | ||
1093 | static struct ringacc_match_data k3_nav_ringacc_data = { | |
1094 | .ops = { | |
1095 | .init = k3_nav_ringacc_init, | |
1096 | }, | |
1097 | }; | |
1098 | ||
432f66fe | 1099 | static const struct udevice_id knav_ringacc_ids[] = { |
b3f95997 | 1100 | { .compatible = "ti,am654-navss-ringacc", .data = (ulong)&k3_nav_ringacc_data, }, |
432f66fe GS |
1101 | {}, |
1102 | }; | |
1103 | ||
b3f95997 VR |
1104 | static int k3_nav_ringacc_probe(struct udevice *dev) |
1105 | { | |
1106 | struct k3_nav_ringacc *ringacc; | |
1107 | int ret; | |
1108 | const struct ringacc_match_data *match_data; | |
1109 | ||
1110 | match_data = (struct ringacc_match_data *)dev_get_driver_data(dev); | |
1111 | ||
1112 | ringacc = dev_get_priv(dev); | |
1113 | if (!ringacc) | |
1114 | return -ENOMEM; | |
1115 | ||
1116 | ringacc->dev = dev; | |
1117 | ringacc->ops = &match_data->ops; | |
1118 | ret = ringacc->ops->init(dev, ringacc); | |
1119 | if (ret) | |
1120 | return ret; | |
1121 | ||
1122 | return 0; | |
1123 | } | |
1124 | ||
432f66fe GS |
1125 | U_BOOT_DRIVER(k3_navss_ringacc) = { |
1126 | .name = "k3-navss-ringacc", | |
1127 | .id = UCLASS_MISC, | |
1128 | .of_match = knav_ringacc_ids, | |
1129 | .probe = k3_nav_ringacc_probe, | |
41575d8e | 1130 | .priv_auto = sizeof(struct k3_nav_ringacc), |
432f66fe | 1131 | }; |