Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  1/* SPDX-License-Identifier: GPL-2.0+ */
  2
  3#ifndef _FDMA_API_H_
  4#define _FDMA_API_H_
  5
  6#include <linux/bits.h>
  7#include <linux/etherdevice.h>
  8#include <linux/types.h>
  9
 10/* This provides a common set of functions and data structures for interacting
 11 * with the Frame DMA engine on multiple Microchip switchcores.
 12 *
 13 * Frame DMA DCB format:
 14 *
 15 * +---------------------------+
 16 * |         Next Ptr          |
 17 * +---------------------------+
 18 * |   Reserved  |    Info     |
 19 * +---------------------------+
 20 * |         Data0 Ptr         |
 21 * +---------------------------+
 22 * |   Reserved  |    Status0  |
 23 * +---------------------------+
 24 * |         Data1 Ptr         |
 25 * +---------------------------+
 26 * |   Reserved  |    Status1  |
 27 * +---------------------------+
 28 * |         Data2 Ptr         |
 29 * +---------------------------+
 30 * |   Reserved  |    Status2  |
 31 * |-------------|-------------|
 32 * |                           |
 33 * |                           |
 34 * |                           |
 35 * |                           |
 36 * |                           |
 37 * |---------------------------|
 38 * |         Data14 Ptr        |
 39 * +-------------|-------------+
 40 * |   Reserved  |    Status14 |
 41 * +-------------|-------------+
 42 *
 43 * The data pointers points to the actual frame data to be received or sent. The
 44 * addresses of the data pointers can, as of writing, be either a: DMA address,
 45 * physical address or mapped address.
 46 *
 47 */
 48
 49#define FDMA_DCB_INFO_DATAL(x)		((x) & GENMASK(15, 0))
 50#define FDMA_DCB_INFO_TOKEN		BIT(17)
 51#define FDMA_DCB_INFO_INTR		BIT(18)
 52#define FDMA_DCB_INFO_SW(x)		(((x) << 24) & GENMASK(31, 24))
 53
 54#define FDMA_DCB_STATUS_BLOCKL(x)	((x) & GENMASK(15, 0))
 55#define FDMA_DCB_STATUS_SOF		BIT(16)
 56#define FDMA_DCB_STATUS_EOF		BIT(17)
 57#define FDMA_DCB_STATUS_INTR		BIT(18)
 58#define FDMA_DCB_STATUS_DONE		BIT(19)
 59#define FDMA_DCB_STATUS_BLOCKO(x)	(((x) << 20) & GENMASK(31, 20))
 60#define FDMA_DCB_INVALID_DATA		0x1
 61
 62#define FDMA_DB_MAX			15 /* Max number of DB's on Sparx5 */
 63
 64struct fdma;
 65
 66struct fdma_db {
 67	u64 dataptr;
 68	u64 status;
 69};
 70
 71struct fdma_dcb {
 72	u64 nextptr;
 73	u64 info;
 74	struct fdma_db db[FDMA_DB_MAX];
 75};
 76
 77struct fdma_ops {
 78	/* User-provided callback to set the dataptr */
 79	int (*dataptr_cb)(struct fdma *fdma, int dcb_idx, int db_idx, u64 *ptr);
 80	/* User-provided callback to set the nextptr */
 81	int (*nextptr_cb)(struct fdma *fdma, int dcb_idx, u64 *ptr);
 82};
 83
 84struct fdma {
 85	void *priv;
 86
 87	/* Virtual addresses */
 88	struct fdma_dcb *dcbs;
 89	struct fdma_dcb *last_dcb;
 90
 91	/* DMA address */
 92	dma_addr_t dma;
 93
 94	/* Size of DCB + DB memory */
 95	int size;
 96
 97	/* Indexes used to access the next-to-be-used DCB or DB */
 98	int db_index;
 99	int dcb_index;
100
101	/* Number of DCB's and DB's */
102	u32 n_dcbs;
103	u32 n_dbs;
104
105	/* Size of DB's */
106	u32 db_size;
107
108	/* Channel id this FDMA object operates on */
109	u32 channel_id;
110
111	struct fdma_ops ops;
112};
113
114/* Advance the DCB index and wrap if required. */
115static inline void fdma_dcb_advance(struct fdma *fdma)
116{
117	fdma->dcb_index++;
118	if (fdma->dcb_index >= fdma->n_dcbs)
119		fdma->dcb_index = 0;
120}
121
122/* Advance the DB index. */
123static inline void fdma_db_advance(struct fdma *fdma)
124{
125	fdma->db_index++;
126}
127
128/* Reset the db index to zero. */
129static inline void fdma_db_reset(struct fdma *fdma)
130{
131	fdma->db_index = 0;
132}
133
134/* Check if a DCB can be reused in case of multiple DB's per DCB. */
135static inline bool fdma_dcb_is_reusable(struct fdma *fdma)
136{
137	return fdma->db_index != fdma->n_dbs;
138}
139
140/* Check if the FDMA has marked this DB as done. */
141static inline bool fdma_db_is_done(struct fdma_db *db)
142{
143	return db->status & FDMA_DCB_STATUS_DONE;
144}
145
146/* Get the length of a DB. */
147static inline int fdma_db_len_get(struct fdma_db *db)
148{
149	return FDMA_DCB_STATUS_BLOCKL(db->status);
150}
151
152/* Set the length of a DB. */
153static inline void fdma_dcb_len_set(struct fdma_dcb *dcb, u32 len)
154{
155	dcb->info = FDMA_DCB_INFO_DATAL(len);
156}
157
158/* Get a DB by index. */
159static inline struct fdma_db *fdma_db_get(struct fdma *fdma, int dcb_idx,
160					  int db_idx)
161{
162	return &fdma->dcbs[dcb_idx].db[db_idx];
163}
164
165/* Get the next DB. */
166static inline struct fdma_db *fdma_db_next_get(struct fdma *fdma)
167{
168	return fdma_db_get(fdma, fdma->dcb_index, fdma->db_index);
169}
170
171/* Get a DCB by index. */
172static inline struct fdma_dcb *fdma_dcb_get(struct fdma *fdma, int dcb_idx)
173{
174	return &fdma->dcbs[dcb_idx];
175}
176
177/* Get the next DCB. */
178static inline struct fdma_dcb *fdma_dcb_next_get(struct fdma *fdma)
179{
180	return fdma_dcb_get(fdma, fdma->dcb_index);
181}
182
183/* Check if the FDMA has frames ready for extraction. */
184static inline bool fdma_has_frames(struct fdma *fdma)
185{
186	return fdma_db_is_done(fdma_db_next_get(fdma));
187}
188
189/* Get a nextptr by index */
190static inline int fdma_nextptr_cb(struct fdma *fdma, int dcb_idx, u64 *nextptr)
191{
192	*nextptr = fdma->dma + (sizeof(struct fdma_dcb) * dcb_idx);
193	return 0;
194}
195
196/* Get the DMA address of a dataptr, by index. This function is only applicable
197 * if the dataptr addresses and DCB's are in contiguous memory and the driver
198 * supports XDP.
199 */
200static inline u64 fdma_dataptr_get_contiguous(struct fdma *fdma, int dcb_idx,
201					      int db_idx)
202{
203	return fdma->dma + (sizeof(struct fdma_dcb) * fdma->n_dcbs) +
204	       (dcb_idx * fdma->n_dbs + db_idx) * fdma->db_size +
205	       XDP_PACKET_HEADROOM;
206}
207
208/* Get the virtual address of a dataptr, by index. This function is only
209 * applicable if the dataptr addresses and DCB's are in contiguous memory and
210 * the driver supports XDP.
211 */
212static inline void *fdma_dataptr_virt_get_contiguous(struct fdma *fdma,
213						     int dcb_idx, int db_idx)
214{
215	return (u8 *)fdma->dcbs + (sizeof(struct fdma_dcb) * fdma->n_dcbs) +
216	       (dcb_idx * fdma->n_dbs + db_idx) * fdma->db_size +
217	       XDP_PACKET_HEADROOM;
218}
219
220/* Check if this DCB is the last used DCB. */
221static inline bool fdma_is_last(struct fdma *fdma, struct fdma_dcb *dcb)
222{
223	return dcb == fdma->last_dcb;
224}
225
226int fdma_dcbs_init(struct fdma *fdma, u64 info, u64 status);
227int fdma_db_add(struct fdma *fdma, int dcb_idx, int db_idx, u64 status);
228int fdma_dcb_add(struct fdma *fdma, int dcb_idx, u64 info, u64 status);
229int __fdma_dcb_add(struct fdma *fdma, int dcb_idx, u64 info, u64 status,
230		   int (*dcb_cb)(struct fdma *fdma, int dcb_idx, u64 *nextptr),
231		   int (*db_cb)(struct fdma *fdma, int dcb_idx, int db_idx,
232				u64 *dataptr));
233
234int fdma_alloc_coherent(struct device *dev, struct fdma *fdma);
235int fdma_alloc_phys(struct fdma *fdma);
236
237void fdma_free_coherent(struct device *dev, struct fdma *fdma);
238void fdma_free_phys(struct fdma *fdma);
239
240u32 fdma_get_size(struct fdma *fdma);
241u32 fdma_get_size_contiguous(struct fdma *fdma);
242
243#endif