Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.9.
  1/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
  2/*
  3 * Microsemi SoCs FDMA driver
  4 *
  5 * Copyright (c) 2021 Microchip
  6 */
  7#ifndef _MSCC_OCELOT_FDMA_H_
  8#define _MSCC_OCELOT_FDMA_H_
  9
 10#include "ocelot.h"
 11
 12#define MSCC_FDMA_DCB_STAT_BLOCKO(x)	(((x) << 20) & GENMASK(31, 20))
 13#define MSCC_FDMA_DCB_STAT_BLOCKO_M	GENMASK(31, 20)
 14#define MSCC_FDMA_DCB_STAT_BLOCKO_X(x)	(((x) & GENMASK(31, 20)) >> 20)
 15#define MSCC_FDMA_DCB_STAT_PD		BIT(19)
 16#define MSCC_FDMA_DCB_STAT_ABORT	BIT(18)
 17#define MSCC_FDMA_DCB_STAT_EOF		BIT(17)
 18#define MSCC_FDMA_DCB_STAT_SOF		BIT(16)
 19#define MSCC_FDMA_DCB_STAT_BLOCKL_M	GENMASK(15, 0)
 20#define MSCC_FDMA_DCB_STAT_BLOCKL(x)	((x) & GENMASK(15, 0))
 21
 22#define MSCC_FDMA_DCB_LLP(x)		((x) * 4 + 0x0)
 23#define MSCC_FDMA_DCB_LLP_PREV(x)	((x) * 4 + 0xA0)
 24#define MSCC_FDMA_CH_SAFE		0xcc
 25#define MSCC_FDMA_CH_ACTIVATE		0xd0
 26#define MSCC_FDMA_CH_DISABLE		0xd4
 27#define MSCC_FDMA_CH_FORCEDIS		0xd8
 28#define MSCC_FDMA_EVT_ERR		0x164
 29#define MSCC_FDMA_EVT_ERR_CODE		0x168
 30#define MSCC_FDMA_INTR_LLP		0x16c
 31#define MSCC_FDMA_INTR_LLP_ENA		0x170
 32#define MSCC_FDMA_INTR_FRM		0x174
 33#define MSCC_FDMA_INTR_FRM_ENA		0x178
 34#define MSCC_FDMA_INTR_ENA		0x184
 35#define MSCC_FDMA_INTR_IDENT		0x188
 36
 37#define MSCC_FDMA_INJ_CHAN		2
 38#define MSCC_FDMA_XTR_CHAN		0
 39
 40#define OCELOT_FDMA_WEIGHT		32
 41
 42#define OCELOT_FDMA_CH_SAFE_TIMEOUT_US	10
 43
 44#define OCELOT_FDMA_RX_RING_SIZE	512
 45#define OCELOT_FDMA_TX_RING_SIZE	128
 46
 47#define OCELOT_FDMA_RX_DCB_SIZE		(OCELOT_FDMA_RX_RING_SIZE * \
 48					 sizeof(struct ocelot_fdma_dcb))
 49#define OCELOT_FDMA_TX_DCB_SIZE		(OCELOT_FDMA_TX_RING_SIZE * \
 50					 sizeof(struct ocelot_fdma_dcb))
 51/* +4 allows for word alignment after allocation */
 52#define OCELOT_DCBS_HW_ALLOC_SIZE	(OCELOT_FDMA_RX_DCB_SIZE + \
 53					 OCELOT_FDMA_TX_DCB_SIZE + \
 54					 4)
 55
 56#define OCELOT_FDMA_RX_SIZE		(PAGE_SIZE / 2)
 57
 58#define OCELOT_FDMA_SKBFRAG_OVR		(4 + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
 59#define OCELOT_FDMA_RXB_SIZE		ALIGN_DOWN(OCELOT_FDMA_RX_SIZE - OCELOT_FDMA_SKBFRAG_OVR, 4)
 60#define OCELOT_FDMA_SKBFRAG_SIZE	(OCELOT_FDMA_RXB_SIZE + OCELOT_FDMA_SKBFRAG_OVR)
 61
 62DECLARE_STATIC_KEY_FALSE(ocelot_fdma_enabled);
 63
 64struct ocelot_fdma_dcb {
 65	u32 llp;
 66	u32 datap;
 67	u32 datal;
 68	u32 stat;
 69} __packed;
 70
 71/**
 72 * struct ocelot_fdma_tx_buf - TX buffer structure
 73 * @skb: SKB currently used in the corresponding DCB.
 74 * @dma_addr: SKB DMA mapped address.
 75 */
 76struct ocelot_fdma_tx_buf {
 77	struct sk_buff *skb;
 78	DEFINE_DMA_UNMAP_ADDR(dma_addr);
 79};
 80
 81/**
 82 * struct ocelot_fdma_tx_ring - TX ring description of DCBs
 83 *
 84 * @dcbs: DCBs allocated for the ring
 85 * @dcbs_dma: DMA base address of the DCBs
 86 * @bufs: List of TX buffer associated to the DCBs
 87 * @xmit_lock: lock for concurrent xmit access
 88 * @next_to_clean: Next DCB to be cleaned in tx_cleanup
 89 * @next_to_use: Next available DCB to send SKB
 90 */
 91struct ocelot_fdma_tx_ring {
 92	struct ocelot_fdma_dcb *dcbs;
 93	dma_addr_t dcbs_dma;
 94	struct ocelot_fdma_tx_buf bufs[OCELOT_FDMA_TX_RING_SIZE];
 95	/* Protect concurrent xmit calls */
 96	spinlock_t xmit_lock;
 97	u16 next_to_clean;
 98	u16 next_to_use;
 99};
100
101/**
102 * struct ocelot_fdma_rx_buf - RX buffer structure
103 * @page: Struct page used in this buffer
104 * @page_offset: Current page offset (either 0 or PAGE_SIZE/2)
105 * @dma_addr: DMA address of the page
106 */
107struct ocelot_fdma_rx_buf {
108	struct page *page;
109	u32 page_offset;
110	dma_addr_t dma_addr;
111};
112
113/**
114 * struct ocelot_fdma_rx_ring - TX ring description of DCBs
115 *
116 * @dcbs: DCBs allocated for the ring
117 * @dcbs_dma: DMA base address of the DCBs
118 * @bufs: List of RX buffer associated to the DCBs
119 * @skb: SKB currently received by the netdev
120 * @next_to_clean: Next DCB to be cleaned NAPI polling
121 * @next_to_use: Next available DCB to send SKB
122 * @next_to_alloc: Next buffer that needs to be allocated (page reuse or alloc)
123 */
124struct ocelot_fdma_rx_ring {
125	struct ocelot_fdma_dcb *dcbs;
126	dma_addr_t dcbs_dma;
127	struct ocelot_fdma_rx_buf bufs[OCELOT_FDMA_RX_RING_SIZE];
128	struct sk_buff *skb;
129	u16 next_to_clean;
130	u16 next_to_use;
131	u16 next_to_alloc;
132};
133
134/**
135 * struct ocelot_fdma - FDMA context
136 *
137 * @irq: FDMA interrupt
138 * @ndev: Net device used to initialize NAPI
139 * @dcbs_base: Memory coherent DCBs
140 * @dcbs_dma_base: DMA base address of memory coherent DCBs
141 * @tx_ring: Injection ring
142 * @rx_ring: Extraction ring
143 * @napi: NAPI context
144 * @ocelot: Back-pointer to ocelot struct
145 */
146struct ocelot_fdma {
147	int irq;
148	struct net_device *ndev;
149	struct ocelot_fdma_dcb *dcbs_base;
150	dma_addr_t dcbs_dma_base;
151	struct ocelot_fdma_tx_ring tx_ring;
152	struct ocelot_fdma_rx_ring rx_ring;
153	struct napi_struct napi;
154	struct ocelot *ocelot;
155};
156
157void ocelot_fdma_init(struct platform_device *pdev, struct ocelot *ocelot);
158void ocelot_fdma_start(struct ocelot *ocelot);
159void ocelot_fdma_deinit(struct ocelot *ocelot);
160int ocelot_fdma_inject_frame(struct ocelot *fdma, int port, u32 rew_op,
161			     struct sk_buff *skb, struct net_device *dev);
162void ocelot_fdma_netdev_init(struct ocelot *ocelot, struct net_device *dev);
163void ocelot_fdma_netdev_deinit(struct ocelot *ocelot,
164			       struct net_device *dev);
165
166#endif