Lines Matching +full:sparx5 +full:- +full:switch +full:- +full:reset
1 // SPDX-License-Identifier: GPL-2.0+
2 /* Microchip Sparx5 Switch driver
6 * The Sparx5 Chip Register Model can be browsed at this location:
7 * https://github.com/microchip-ung/sparx-5_reginfo
15 #include <linux/dma-mapping.h>
27 *dataptr = fdma->dma + (sizeof(struct fdma_dcb) * fdma->n_dcbs) + in sparx5_fdma_tx_dataptr_cb()
28 ((dcb * fdma->n_dbs + db) * fdma->db_size); in sparx5_fdma_tx_dataptr_cb()
36 struct sparx5 *sparx5 = fdma->priv; in sparx5_fdma_rx_dataptr_cb() local
37 struct sparx5_rx *rx = &sparx5->rx; in sparx5_fdma_rx_dataptr_cb()
40 skb = __netdev_alloc_skb(rx->ndev, fdma->db_size, GFP_ATOMIC); in sparx5_fdma_rx_dataptr_cb()
42 return -ENOMEM; in sparx5_fdma_rx_dataptr_cb()
44 *dataptr = virt_to_phys(skb->data); in sparx5_fdma_rx_dataptr_cb()
46 rx->skb[dcb][db] = skb; in sparx5_fdma_rx_dataptr_cb()
51 static void sparx5_fdma_rx_activate(struct sparx5 *sparx5, struct sparx5_rx *rx) in sparx5_fdma_rx_activate() argument
53 struct fdma *fdma = &rx->fdma; in sparx5_fdma_rx_activate()
56 spx5_wr(((u64)fdma->dma) & GENMASK(31, 0), sparx5, in sparx5_fdma_rx_activate()
57 FDMA_DCB_LLP(fdma->channel_id)); in sparx5_fdma_rx_activate()
58 spx5_wr(((u64)fdma->dma) >> 32, sparx5, in sparx5_fdma_rx_activate()
59 FDMA_DCB_LLP1(fdma->channel_id)); in sparx5_fdma_rx_activate()
61 /* Set the number of RX DBs to be used, and DB end-of-frame interrupt */ in sparx5_fdma_rx_activate()
62 spx5_wr(FDMA_CH_CFG_CH_DCB_DB_CNT_SET(fdma->n_dbs) | in sparx5_fdma_rx_activate()
65 sparx5, FDMA_CH_CFG(fdma->channel_id)); in sparx5_fdma_rx_activate()
69 sparx5, in sparx5_fdma_rx_activate()
74 sparx5, FDMA_PORT_CTRL(0)); in sparx5_fdma_rx_activate()
77 spx5_rmw(BIT(fdma->channel_id), in sparx5_fdma_rx_activate()
78 BIT(fdma->channel_id) & FDMA_INTR_DB_ENA_INTR_DB_ENA, in sparx5_fdma_rx_activate()
79 sparx5, FDMA_INTR_DB_ENA); in sparx5_fdma_rx_activate()
82 spx5_wr(BIT(fdma->channel_id), sparx5, FDMA_CH_ACTIVATE); in sparx5_fdma_rx_activate()
85 static void sparx5_fdma_rx_deactivate(struct sparx5 *sparx5, struct sparx5_rx *rx) in sparx5_fdma_rx_deactivate() argument
87 struct fdma *fdma = &rx->fdma; in sparx5_fdma_rx_deactivate()
90 spx5_rmw(0, BIT(fdma->channel_id) & FDMA_CH_ACTIVATE_CH_ACTIVATE, in sparx5_fdma_rx_deactivate()
91 sparx5, FDMA_CH_ACTIVATE); in sparx5_fdma_rx_deactivate()
94 spx5_rmw(0, BIT(fdma->channel_id) & FDMA_INTR_DB_ENA_INTR_DB_ENA, in sparx5_fdma_rx_deactivate()
95 sparx5, FDMA_INTR_DB_ENA); in sparx5_fdma_rx_deactivate()
99 sparx5, FDMA_PORT_CTRL(0)); in sparx5_fdma_rx_deactivate()
102 static void sparx5_fdma_tx_activate(struct sparx5 *sparx5, struct sparx5_tx *tx) in sparx5_fdma_tx_activate() argument
104 struct fdma *fdma = &tx->fdma; in sparx5_fdma_tx_activate()
107 spx5_wr(((u64)fdma->dma) & GENMASK(31, 0), sparx5, in sparx5_fdma_tx_activate()
108 FDMA_DCB_LLP(fdma->channel_id)); in sparx5_fdma_tx_activate()
109 spx5_wr(((u64)fdma->dma) >> 32, sparx5, in sparx5_fdma_tx_activate()
110 FDMA_DCB_LLP1(fdma->channel_id)); in sparx5_fdma_tx_activate()
112 /* Set the number of TX DBs to be used, and DB end-of-frame interrupt */ in sparx5_fdma_tx_activate()
113 spx5_wr(FDMA_CH_CFG_CH_DCB_DB_CNT_SET(fdma->n_dbs) | in sparx5_fdma_tx_activate()
116 sparx5, FDMA_CH_CFG(fdma->channel_id)); in sparx5_fdma_tx_activate()
120 sparx5, FDMA_PORT_CTRL(0)); in sparx5_fdma_tx_activate()
123 spx5_wr(BIT(fdma->channel_id), sparx5, FDMA_CH_ACTIVATE); in sparx5_fdma_tx_activate()
126 static void sparx5_fdma_tx_deactivate(struct sparx5 *sparx5, struct sparx5_tx *tx) in sparx5_fdma_tx_deactivate() argument
129 spx5_rmw(0, BIT(tx->fdma.channel_id) & FDMA_CH_ACTIVATE_CH_ACTIVATE, in sparx5_fdma_tx_deactivate()
130 sparx5, FDMA_CH_ACTIVATE); in sparx5_fdma_tx_deactivate()
133 void sparx5_fdma_reload(struct sparx5 *sparx5, struct fdma *fdma) in sparx5_fdma_reload() argument
136 spx5_wr(BIT(fdma->channel_id), sparx5, FDMA_CH_RELOAD); in sparx5_fdma_reload()
139 static bool sparx5_fdma_rx_get_frame(struct sparx5 *sparx5, struct sparx5_rx *rx) in sparx5_fdma_rx_get_frame() argument
141 struct fdma *fdma = &rx->fdma; in sparx5_fdma_rx_get_frame()
151 skb = rx->skb[fdma->dcb_index][fdma->db_index]; in sparx5_fdma_rx_get_frame()
154 sparx5_ifh_parse(sparx5, (u32 *)skb->data, &fi); in sparx5_fdma_rx_get_frame()
156 port = fi.src_port < sparx5->data->consts->n_ports ? in sparx5_fdma_rx_get_frame()
157 sparx5->ports[fi.src_port] : in sparx5_fdma_rx_get_frame()
159 if (!port || !port->ndev) { in sparx5_fdma_rx_get_frame()
160 dev_err(sparx5->dev, "Data on inactive port %d\n", fi.src_port); in sparx5_fdma_rx_get_frame()
161 sparx5_xtr_flush(sparx5, XTR_QUEUE); in sparx5_fdma_rx_get_frame()
164 skb->dev = port->ndev; in sparx5_fdma_rx_get_frame()
166 if (likely(!(skb->dev->features & NETIF_F_RXFCS))) in sparx5_fdma_rx_get_frame()
167 skb_trim(skb, skb->len - ETH_FCS_LEN); in sparx5_fdma_rx_get_frame()
169 sparx5_ptp_rxtstamp(sparx5, skb, fi.timestamp); in sparx5_fdma_rx_get_frame()
170 skb->protocol = eth_type_trans(skb, skb->dev); in sparx5_fdma_rx_get_frame()
174 if (test_bit(port->portno, sparx5->bridge_mask)) in sparx5_fdma_rx_get_frame()
175 skb->offload_fwd_mark = 1; in sparx5_fdma_rx_get_frame()
176 skb->dev->stats.rx_bytes += skb->len; in sparx5_fdma_rx_get_frame()
177 skb->dev->stats.rx_packets++; in sparx5_fdma_rx_get_frame()
178 rx->packets++; in sparx5_fdma_rx_get_frame()
186 struct sparx5 *sparx5 = container_of(rx, struct sparx5, rx); in sparx5_fdma_napi_callback() local
187 struct fdma *fdma = &rx->fdma; in sparx5_fdma_napi_callback()
190 while (counter < weight && sparx5_fdma_rx_get_frame(sparx5, rx)) { in sparx5_fdma_napi_callback()
196 fdma_dcb_add(fdma, fdma->dcb_index, in sparx5_fdma_napi_callback()
197 FDMA_DCB_INFO_DATAL(fdma->db_size), in sparx5_fdma_napi_callback()
203 napi_complete_done(&rx->napi, counter); in sparx5_fdma_napi_callback()
204 spx5_rmw(BIT(fdma->channel_id), in sparx5_fdma_napi_callback()
205 BIT(fdma->channel_id) & FDMA_INTR_DB_ENA_INTR_DB_ENA, in sparx5_fdma_napi_callback()
206 sparx5, FDMA_INTR_DB_ENA); in sparx5_fdma_napi_callback()
209 sparx5_fdma_reload(sparx5, fdma); in sparx5_fdma_napi_callback()
213 int sparx5_fdma_xmit(struct sparx5 *sparx5, u32 *ifh, struct sk_buff *skb, in sparx5_fdma_xmit() argument
216 struct sparx5_tx *tx = &sparx5->tx; in sparx5_fdma_xmit()
217 struct fdma *fdma = &tx->fdma; in sparx5_fdma_xmit()
221 if (!fdma_db_is_done(fdma_db_get(fdma, fdma->dcb_index, 0))) in sparx5_fdma_xmit()
222 return -EINVAL; in sparx5_fdma_xmit()
225 virt_addr = ((u8 *)fdma->dcbs + in sparx5_fdma_xmit()
226 (sizeof(struct fdma_dcb) * fdma->n_dcbs) + in sparx5_fdma_xmit()
227 ((fdma->dcb_index * fdma->n_dbs) * fdma->db_size)); in sparx5_fdma_xmit()
230 memcpy(virt_addr + IFH_LEN * 4, skb->data, skb->len); in sparx5_fdma_xmit()
232 fdma_dcb_add(fdma, fdma->dcb_index, 0, in sparx5_fdma_xmit()
236 FDMA_DCB_STATUS_BLOCKL(skb->len + IFH_LEN * 4 + 4)); in sparx5_fdma_xmit()
238 sparx5_fdma_reload(sparx5, fdma); in sparx5_fdma_xmit()
243 static int sparx5_fdma_rx_alloc(struct sparx5 *sparx5) in sparx5_fdma_rx_alloc() argument
245 struct sparx5_rx *rx = &sparx5->rx; in sparx5_fdma_rx_alloc()
246 struct fdma *fdma = &rx->fdma; in sparx5_fdma_rx_alloc()
253 fdma_dcbs_init(fdma, FDMA_DCB_INFO_DATAL(fdma->db_size), in sparx5_fdma_rx_alloc()
259 static int sparx5_fdma_tx_alloc(struct sparx5 *sparx5) in sparx5_fdma_tx_alloc() argument
261 struct sparx5_tx *tx = &sparx5->tx; in sparx5_fdma_tx_alloc()
262 struct fdma *fdma = &tx->fdma; in sparx5_fdma_tx_alloc()
269 fdma_dcbs_init(fdma, FDMA_DCB_INFO_DATAL(fdma->db_size), in sparx5_fdma_tx_alloc()
275 static void sparx5_fdma_rx_init(struct sparx5 *sparx5, in sparx5_fdma_rx_init() argument
278 struct fdma *fdma = &rx->fdma; in sparx5_fdma_rx_init()
281 fdma->channel_id = channel; in sparx5_fdma_rx_init()
282 fdma->n_dcbs = FDMA_DCB_MAX; in sparx5_fdma_rx_init()
283 fdma->n_dbs = FDMA_RX_DCB_MAX_DBS; in sparx5_fdma_rx_init()
284 fdma->priv = sparx5; in sparx5_fdma_rx_init()
285 fdma->db_size = ALIGN(FDMA_XTR_BUFFER_SIZE, PAGE_SIZE); in sparx5_fdma_rx_init()
286 fdma->size = fdma_get_size(&sparx5->rx.fdma); in sparx5_fdma_rx_init()
287 fdma->ops.dataptr_cb = &sparx5_fdma_rx_dataptr_cb; in sparx5_fdma_rx_init()
288 fdma->ops.nextptr_cb = &fdma_nextptr_cb; in sparx5_fdma_rx_init()
290 for (idx = 0; idx < sparx5->data->consts->n_ports; ++idx) { in sparx5_fdma_rx_init()
291 struct sparx5_port *port = sparx5->ports[idx]; in sparx5_fdma_rx_init()
293 if (port && port->ndev) { in sparx5_fdma_rx_init()
294 rx->ndev = port->ndev; in sparx5_fdma_rx_init()
300 static void sparx5_fdma_tx_init(struct sparx5 *sparx5, in sparx5_fdma_tx_init() argument
303 struct fdma *fdma = &tx->fdma; in sparx5_fdma_tx_init()
305 fdma->channel_id = channel; in sparx5_fdma_tx_init()
306 fdma->n_dcbs = FDMA_DCB_MAX; in sparx5_fdma_tx_init()
307 fdma->n_dbs = FDMA_TX_DCB_MAX_DBS; in sparx5_fdma_tx_init()
308 fdma->priv = sparx5; in sparx5_fdma_tx_init()
309 fdma->db_size = ALIGN(FDMA_XTR_BUFFER_SIZE, PAGE_SIZE); in sparx5_fdma_tx_init()
310 fdma->size = fdma_get_size_contiguous(&sparx5->tx.fdma); in sparx5_fdma_tx_init()
311 fdma->ops.dataptr_cb = &sparx5_fdma_tx_dataptr_cb; in sparx5_fdma_tx_init()
312 fdma->ops.nextptr_cb = &fdma_nextptr_cb; in sparx5_fdma_tx_init()
317 struct sparx5 *sparx5 = args; in sparx5_fdma_handler() local
320 db = spx5_rd(sparx5, FDMA_INTR_DB); in sparx5_fdma_handler()
321 err = spx5_rd(sparx5, FDMA_INTR_ERR); in sparx5_fdma_handler()
324 spx5_wr(0, sparx5, FDMA_INTR_DB_ENA); in sparx5_fdma_handler()
325 spx5_wr(db, sparx5, FDMA_INTR_DB); in sparx5_fdma_handler()
326 napi_schedule(&sparx5->rx.napi); in sparx5_fdma_handler()
329 u32 err_type = spx5_rd(sparx5, FDMA_ERRORS); in sparx5_fdma_handler()
331 dev_err_ratelimited(sparx5->dev, in sparx5_fdma_handler()
334 spx5_wr(err, sparx5, FDMA_INTR_ERR); in sparx5_fdma_handler()
335 spx5_wr(err_type, sparx5, FDMA_ERRORS); in sparx5_fdma_handler()
340 void sparx5_fdma_injection_mode(struct sparx5 *sparx5) in sparx5_fdma_injection_mode() argument
350 sparx5, QS_XTR_GRP_CFG(XTR_QUEUE)); in sparx5_fdma_injection_mode()
353 sparx5, QS_INJ_GRP_CFG(INJ_QUEUE)); in sparx5_fdma_injection_mode()
356 for (portno = sparx5_get_internal_port(sparx5, SPX5_PORT_CPU_0); in sparx5_fdma_injection_mode()
357 portno <= sparx5_get_internal_port(sparx5, SPX5_PORT_CPU_1); in sparx5_fdma_injection_mode()
363 sparx5, ASM_PORT_CFG(portno)); in sparx5_fdma_injection_mode()
365 /* Reset WM cnt to unclog queued frames */ in sparx5_fdma_injection_mode()
368 sparx5, in sparx5_fdma_injection_mode()
374 sparx5, in sparx5_fdma_injection_mode()
378 urgency = sparx5_port_fwd_urg(sparx5, SPEED_2500); in sparx5_fdma_injection_mode()
383 sparx5, in sparx5_fdma_injection_mode()
391 sparx5, in sparx5_fdma_injection_mode()
397 sparx5, in sparx5_fdma_injection_mode()
402 int sparx5_fdma_init(struct sparx5 *sparx5) in sparx5_fdma_init() argument
406 /* Reset FDMA state */ in sparx5_fdma_init()
407 spx5_wr(FDMA_CTRL_NRESET_SET(0), sparx5, FDMA_CTRL); in sparx5_fdma_init()
408 spx5_wr(FDMA_CTRL_NRESET_SET(1), sparx5, FDMA_CTRL); in sparx5_fdma_init()
417 sparx5, CPU_PROC_CTRL); in sparx5_fdma_init()
419 sparx5_fdma_injection_mode(sparx5); in sparx5_fdma_init()
420 sparx5_fdma_rx_init(sparx5, &sparx5->rx, FDMA_XTR_CHANNEL); in sparx5_fdma_init()
421 sparx5_fdma_tx_init(sparx5, &sparx5->tx, FDMA_INJ_CHANNEL); in sparx5_fdma_init()
422 err = sparx5_fdma_rx_alloc(sparx5); in sparx5_fdma_init()
424 dev_err(sparx5->dev, "Could not allocate RX buffers: %d\n", err); in sparx5_fdma_init()
427 err = sparx5_fdma_tx_alloc(sparx5); in sparx5_fdma_init()
429 dev_err(sparx5->dev, "Could not allocate TX buffers: %d\n", err); in sparx5_fdma_init()
435 int sparx5_fdma_deinit(struct sparx5 *sparx5) in sparx5_fdma_deinit() argument
437 sparx5_fdma_stop(sparx5); in sparx5_fdma_deinit()
438 fdma_free_phys(&sparx5->rx.fdma); in sparx5_fdma_deinit()
439 fdma_free_phys(&sparx5->tx.fdma); in sparx5_fdma_deinit()
444 static u32 sparx5_fdma_port_ctrl(struct sparx5 *sparx5) in sparx5_fdma_port_ctrl() argument
446 return spx5_rd(sparx5, FDMA_PORT_CTRL(0)); in sparx5_fdma_port_ctrl()
449 int sparx5_fdma_start(struct sparx5 *sparx5) in sparx5_fdma_start() argument
451 const struct sparx5_ops *ops = sparx5->data->ops; in sparx5_fdma_start()
452 struct sparx5_rx *rx = &sparx5->rx; in sparx5_fdma_start()
453 struct sparx5_tx *tx = &sparx5->tx; in sparx5_fdma_start()
455 netif_napi_add_weight(rx->ndev, in sparx5_fdma_start()
456 &rx->napi, in sparx5_fdma_start()
457 ops->fdma_poll, in sparx5_fdma_start()
460 napi_enable(&rx->napi); in sparx5_fdma_start()
462 sparx5_fdma_rx_activate(sparx5, rx); in sparx5_fdma_start()
463 sparx5_fdma_tx_activate(sparx5, tx); in sparx5_fdma_start()
468 int sparx5_fdma_stop(struct sparx5 *sparx5) in sparx5_fdma_stop() argument
470 struct sparx5_rx *rx = &sparx5->rx; in sparx5_fdma_stop()
471 struct sparx5_tx *tx = &sparx5->tx; in sparx5_fdma_stop()
474 napi_disable(&rx->napi); in sparx5_fdma_stop()
477 sparx5_fdma_rx_deactivate(sparx5, rx); in sparx5_fdma_stop()
478 sparx5_fdma_tx_deactivate(sparx5, tx); in sparx5_fdma_stop()
483 500, 10000, 0, sparx5); in sparx5_fdma_stop()