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 | |
62 | DECLARE_STATIC_KEY_FALSE(ocelot_fdma_enabled); |
63 | |
64 | struct 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 | */ |
76 | struct 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 | */ |
91 | struct 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 | */ |
107 | struct 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 | */ |
124 | struct 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 | */ |
146 | struct 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 | |
157 | void ocelot_fdma_init(struct platform_device *pdev, struct ocelot *ocelot); |
158 | void ocelot_fdma_start(struct ocelot *ocelot); |
159 | void ocelot_fdma_deinit(struct ocelot *ocelot); |
160 | int ocelot_fdma_inject_frame(struct ocelot *fdma, int port, u32 rew_op, |
161 | struct sk_buff *skb, struct net_device *dev); |
162 | void ocelot_fdma_netdev_init(struct ocelot *ocelot, struct net_device *dev); |
163 | void ocelot_fdma_netdev_deinit(struct ocelot *ocelot, |
164 | struct net_device *dev); |
165 | |
166 | #endif |
167 | |