1 /*
2 * Copyright (c) 2026 Justin Hibbits
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7 #ifndef DPAA_COMMON_H
8 #define DPAA_COMMON_H
9
10 #include <machine/atomic.h>
11
12 int dpaa_map_private_memory(device_t dev, int idx, const char *compat,
13 vm_paddr_t *addrp, size_t *sizep);
14
15 struct dpaa_fd {
16 uint64_t liodn:8;
17 uint64_t bpid:8;
18 uint64_t eliodn:4;
19 uint64_t _rsvd1:4;
20 uint64_t addr:40;
21 uint32_t format:3;
22 uint32_t offset:9;
23 uint32_t length:20;
24 uint32_t cmd_stat;
25 } __packed;
26
27 #define DPAA_FD_FORMAT_SHORT_MBSF 4
28
29 #define DPAA_FD_RX_STATUS_DCL4C 0x10000000
30 #define DPAA_FD_RX_STATUS_DME 0x01000000
31 #define DPAA_FD_RX_STATUS_IPRE_M 0x00300000
32 #define DPAA_FD_RX_STATUS_FPE 0x00080000
33 #define DPAA_FD_RX_STATUS_FSE 0x00040000
34 #define DPAA_FD_RX_STATUS_DIS 0x00020000
35 #define DPAA_FD_RX_STATUS_EOF 0x00008000
36 #define DPAA_FD_RX_STATUS_NSS 0x00004000
37 #define DPAA_FD_RX_STATUS_KSO 0x00002000
38 #define DPAA_FD_RX_STATUS_FCL_M 0x00000c00
39 #define DPAA_FD_RX_STATUS_IPP 0x00000200
40 #define DPAA_FD_RX_STATUS_FLM 0x00000100
41 #define DPAA_FD_RX_STATUS_PTE 0x00000080
42 #define DPAA_FD_RX_STATUS_ISP 0x00000040
43 #define DPAA_FD_RX_STATUS_PHE 0x00000020
44 #define DPAA_FD_RX_STATUS_FRDR 0x00000010
45 #define DPAA_FD_RX_STATUS_BLE 0x00000008
46 #define DPAA_FD_RX_STATUS_L4CV 0x00000004
47 #define DPAA_FD_RX_STATUS_IPR 0x00000001
48
49 #define DPAA_FD_TX_CMD_RPD 0x40000000
50 #define DPAA_FD_TX_CMD_DTC 0x10000000
51 #define DPAA_FD_TX_STATUS_UFD 0x04000000
52 #define DPAA_FD_TX_STATUS_LGE 0x02000000
53 #define DPAA_FD_TX_STATUS_DME 0x01000000
54
55 /* Most of the above are error flags, but some aren't */
56 #define DPAA_FD_CMD_STAT_ERR_M 0x010ce3e8
57 #define DPAA_FD_TX_STAT_ERR_M 0x03000000
58
59 #define DPAA_FD_GET_ADDR(fd) ((void *)PHYS_TO_DMAP(fd->addr))
60
61 struct dpaa_sgte {
62 uint64_t addr;
63 uint32_t extension:1;
64 uint32_t final:1;
65 uint32_t length:30;
66 uint16_t bpid;
67 uint16_t offset;
68 } __packed;
69 struct qman_fqr;
70
71
72 #define DPAA_NUM_OF_SG_TABLE_ENTRY 16
73
74 /*
75 * Ring API infrastructure
76 *
77 * BMan and QMan both use cache-enabled rings. Abstract this away to a more
78 * generalized interface to reduce code copying.
79 *
80 * Requirements:
81 * - Before calling <ring>_init() the ring base (ring->ring) must be initialized
82 * to the base of the ring.
83 */
84 #define DPAA_RING_DECLARE(pfx) \
85 struct pfx##_ring { \
86 struct pfx##_entry *ring; \
87 struct pfx##_entry *cursor; \
88 uint8_t vbit; \
89 uint8_t avail; \
90 uint8_t ci; \
91 uint8_t ithresh; \
92 }
93
94 /*
95 * Ring functions:
96 *
97 * ring_cyc_diff() -- get the (circular) difference of `l - f`
98 * ring_ring_init() -- Set up the ring structures. Portal must be
99 * initialized beforehand, and ring->ring must be nonzero.
100 * ring_CARRYCLEAR() -- stealth math to do circular roll-over
101 * ring_INC() -- Increment the cursor within the ring
102 * ring_update() -- Update ring entry availability count
103 * ring_start() -- Reserve the next entry in the ring if available.
104 * ring_commit() -- Commit the reserved ring entry by setting the verb and
105 * AVB bit
106 */
107 #define DPAA_RING(pfx,sz,pi_e,ci_e,pi_i,ci_i) \
108 static inline int \
109 pfx##_cyc_diff(uint8_t size, uint8_t f, uint8_t l) \
110 { \
111 if (f <= l) \
112 return (uint8_t)(l - f); \
113 return (uint8_t)(l + size - f); \
114 } \
115 static inline void \
116 pfx##_ring_init(struct pfx##_ring *ring, struct dpaa_portal_softc *portal)\
117 { \
118 uint32_t pi = *(uint32_t*)(portal->sc_ci_va + pi_i) & (sz - 1); \
119 uint32_t ci = *(uint32_t*)(portal->sc_ci_va + ci_i); \
120 ring->ci = ci & (sz - 1); \
121 ring->vbit = !!(ci & sz) << 7; \
122 ring->cursor = ring->ring + pi; \
123 ring->avail = sz - 1 - pfx##_cyc_diff(sz, ring->ci, pi); \
124 } \
125 static inline void * \
126 pfx##_CARRYCLEAR(struct pfx##_entry *p) \
127 { \
128 return ((void *)((uintptr_t)p & (~(uintptr_t)(sz << 6)))); \
129 } \
130 static inline void \
131 pfx##_INC(struct pfx##_ring *ring) \
132 { \
133 struct pfx##_entry *partial = ring->cursor + 1; \
134 ring->cursor = pfx##_CARRYCLEAR(partial); \
135 if (partial != ring->cursor) \
136 ring->vbit ^= 0x80; \
137 } \
138 static inline uint8_t \
139 pfx##_update(struct pfx##_ring *ring, struct dpaa_portal_softc *portal) \
140 { \
141 uint8_t diff, old_ci = ring->ci; \
142 ring->ci = *(uint32_t*)(portal->sc_ci_va + ci_i) & (sz - 1); \
143 diff = pfx##_cyc_diff(sz, old_ci, ring->ci); \
144 ring->avail += diff; \
145 return (diff); \
146 } \
147 static inline struct pfx##_entry * __unused \
148 pfx##_start(struct pfx##_ring *ring, struct dpaa_portal_softc *portal) \
149 { \
150 if (ring->avail <= 1) { \
151 pfx##_update(ring, portal); \
152 if (ring->avail == 0) \
153 return (NULL); \
154 } \
155 dpaa_zero_line(ring->cursor); \
156 return (ring->cursor); \
157 } \
158 static inline void __unused \
159 pfx##_commit(struct pfx##_ring *ring, uint8_t verb) \
160 { \
161 struct pfx##_entry *entry = ring->cursor; \
162 dpaa_lw_barrier(); \
163 entry->verb = verb | ring->vbit; \
164 dpaa_flush_line(entry); \
165 pfx##_INC(ring); \
166 ring->avail--; \
167 } struct hack
168
169 #ifdef __powerpc__
170 static inline void
dpaa_flush_line(void * line)171 dpaa_flush_line(void *line)
172 {
173 __asm __volatile ("dcbf 0, %0" :: "r"(line) : "memory");
174 }
175
176 static inline void
dpaa_zero_line(void * line)177 dpaa_zero_line(void *line)
178 {
179 __asm __volatile ("dcbz 0, %0" :: "r"(line) : "memory");
180 }
181
182 static inline void
dpaa_touch_line(void * line)183 dpaa_touch_line(void *line)
184 {
185 __asm __volatile ("dcbt 0, %0" :: "r"(line) : "memory");
186 }
187
188 static inline void
dpaa_lw_barrier(void)189 dpaa_lw_barrier(void)
190 {
191 powerpc_lwsync();
192 }
193 #endif
194
195 #endif
196