1*0f9e9ec2Sjsg /* $OpenBSD: if_mvpp.c,v 1.53 2024/05/13 01:15:50 jsg Exp $ */
21a945772Spatrick /*
31a945772Spatrick * Copyright (c) 2008, 2019 Mark Kettenis <kettenis@openbsd.org>
41a945772Spatrick * Copyright (c) 2017, 2020 Patrick Wildt <patrick@blueri.se>
51a945772Spatrick *
61a945772Spatrick * Permission to use, copy, modify, and distribute this software for any
71a945772Spatrick * purpose with or without fee is hereby granted, provided that the above
81a945772Spatrick * copyright notice and this permission notice appear in all copies.
91a945772Spatrick *
101a945772Spatrick * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
111a945772Spatrick * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
121a945772Spatrick * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
131a945772Spatrick * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
141a945772Spatrick * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
151a945772Spatrick * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
161a945772Spatrick * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
171a945772Spatrick */
181a945772Spatrick /*
191a945772Spatrick * Copyright (C) 2016 Marvell International Ltd.
201a945772Spatrick *
211a945772Spatrick * Marvell BSD License Option
221a945772Spatrick *
231a945772Spatrick * If you received this File from Marvell, you may opt to use, redistribute
241a945772Spatrick * and/or modify this File under the following licensing terms.
251a945772Spatrick * Redistribution and use in source and binary forms, with or without
261a945772Spatrick * modification, are permitted provided that the following conditions are met:
271a945772Spatrick *
281a945772Spatrick * * Redistributions of source code must retain the above copyright notice,
291a945772Spatrick * this list of conditions and the following disclaimer.
301a945772Spatrick *
311a945772Spatrick * * Redistributions in binary form must reproduce the above copyright
321a945772Spatrick * notice, this list of conditions and the following disclaimer in the
331a945772Spatrick * documentation and/or other materials provided with the distribution.
341a945772Spatrick *
351a945772Spatrick * * Neither the name of Marvell nor the names of its contributors may be
361a945772Spatrick * used to endorse or promote products derived from this software without
371a945772Spatrick * specific prior written permission.
381a945772Spatrick *
391a945772Spatrick * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
401a945772Spatrick * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
411a945772Spatrick * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
421a945772Spatrick * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
431a945772Spatrick * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
441a945772Spatrick * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
451a945772Spatrick * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
461a945772Spatrick * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
471a945772Spatrick * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
481a945772Spatrick * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
491a945772Spatrick * POSSIBILITY OF SUCH DAMAGE.
501a945772Spatrick */
511a945772Spatrick
521a945772Spatrick #include "bpfilter.h"
531a945772Spatrick
541a945772Spatrick #include <sys/param.h>
551a945772Spatrick #include <sys/systm.h>
561a945772Spatrick #include <sys/device.h>
571a945772Spatrick #include <sys/kernel.h>
581a945772Spatrick #include <sys/malloc.h>
591a945772Spatrick #include <sys/mbuf.h>
601a945772Spatrick #include <sys/queue.h>
611a945772Spatrick #include <sys/socket.h>
621a945772Spatrick #include <sys/sockio.h>
631a945772Spatrick #include <sys/timeout.h>
641a945772Spatrick
6509e5d825Spatrick #include <uvm/uvm_extern.h>
6609e5d825Spatrick
6709e5d825Spatrick #include <machine/cpufunc.h>
681a945772Spatrick #include <machine/bus.h>
691a945772Spatrick #include <machine/fdt.h>
701a945772Spatrick
711a945772Spatrick #include <net/if.h>
721a945772Spatrick #include <net/if_media.h>
73e042150eSpatrick #include <net/ppp_defs.h>
741a945772Spatrick
751a945772Spatrick #include <dev/ofw/openfirm.h>
761a945772Spatrick #include <dev/ofw/ofw_clock.h>
771a945772Spatrick #include <dev/ofw/ofw_gpio.h>
781a945772Spatrick #include <dev/ofw/ofw_misc.h>
791a945772Spatrick #include <dev/ofw/ofw_pinctrl.h>
801a945772Spatrick #include <dev/ofw/ofw_regulator.h>
811a945772Spatrick #include <dev/ofw/fdt.h>
821a945772Spatrick
831a945772Spatrick #include <dev/mii/mii.h>
841a945772Spatrick #include <dev/mii/miivar.h>
851a945772Spatrick
861a945772Spatrick #if NBPFILTER > 0
871a945772Spatrick #include <net/bpf.h>
881a945772Spatrick #endif
891a945772Spatrick
901a945772Spatrick #include <netinet/in.h>
911a945772Spatrick #include <netinet/ip.h>
921a945772Spatrick #include <netinet/if_ether.h>
931a945772Spatrick
941a945772Spatrick #include <netinet6/in6_var.h>
951a945772Spatrick #include <netinet/ip6.h>
961a945772Spatrick
971a945772Spatrick #include <dev/fdt/if_mvppreg.h>
981a945772Spatrick
991a945772Spatrick struct mvpp2_buf {
1001a945772Spatrick bus_dmamap_t mb_map;
1011a945772Spatrick struct mbuf *mb_m;
1021a945772Spatrick };
1031a945772Spatrick
1041a945772Spatrick #define MVPP2_NTXDESC 512
1051a945772Spatrick #define MVPP2_NTXSEGS 16
1061a945772Spatrick #define MVPP2_NRXDESC 512
1071a945772Spatrick
1081a945772Spatrick struct mvpp2_bm_pool {
1091a945772Spatrick struct mvpp2_dmamem *bm_mem;
1101a945772Spatrick struct mvpp2_buf *rxbuf;
111be107da9Spatrick uint32_t *freelist;
112be107da9Spatrick int free_prod;
113be107da9Spatrick int free_cons;
1141a945772Spatrick };
1151a945772Spatrick
1161a945772Spatrick #define MVPP2_BM_SIZE 64
1171a945772Spatrick #define MVPP2_BM_POOL_PTR_ALIGN 128
1181a945772Spatrick #define MVPP2_BM_POOLS_NUM 8
1191a945772Spatrick #define MVPP2_BM_ALIGN 32
1201a945772Spatrick
1211a945772Spatrick struct mvpp2_tx_queue {
1221a945772Spatrick uint8_t id;
1231a945772Spatrick uint8_t log_id;
1241a945772Spatrick struct mvpp2_dmamem *ring;
1251a945772Spatrick struct mvpp2_buf *buf;
1261a945772Spatrick struct mvpp2_tx_desc *descs;
1271a945772Spatrick int prod;
1281a945772Spatrick int cons;
1291a945772Spatrick
1301a945772Spatrick uint32_t done_pkts_coal;
1311a945772Spatrick };
1321a945772Spatrick
1331a945772Spatrick struct mvpp2_rx_queue {
1341a945772Spatrick uint8_t id;
1351a945772Spatrick struct mvpp2_dmamem *ring;
1361a945772Spatrick struct mvpp2_rx_desc *descs;
1371a945772Spatrick int prod;
1381a945772Spatrick struct if_rxring rxring;
1391a945772Spatrick int cons;
1401a945772Spatrick
1411a945772Spatrick uint32_t pkts_coal;
1421a945772Spatrick uint32_t time_coal;
1431a945772Spatrick };
1441a945772Spatrick
1451a945772Spatrick struct mvpp2_dmamem {
1461a945772Spatrick bus_dmamap_t mdm_map;
1471a945772Spatrick bus_dma_segment_t mdm_seg;
1481a945772Spatrick size_t mdm_size;
1491a945772Spatrick caddr_t mdm_kva;
1501a945772Spatrick };
1511a945772Spatrick #define MVPP2_DMA_MAP(_mdm) ((_mdm)->mdm_map)
1521a945772Spatrick #define MVPP2_DMA_LEN(_mdm) ((_mdm)->mdm_size)
1531a945772Spatrick #define MVPP2_DMA_DVA(_mdm) ((_mdm)->mdm_map->dm_segs[0].ds_addr)
1541a945772Spatrick #define MVPP2_DMA_KVA(_mdm) ((void *)(_mdm)->mdm_kva)
1551a945772Spatrick
1561a945772Spatrick struct mvpp2_port;
1571a945772Spatrick struct mvpp2_softc {
1581a945772Spatrick struct device sc_dev;
1591a945772Spatrick int sc_node;
1601a945772Spatrick bus_space_tag_t sc_iot;
1611a945772Spatrick bus_space_handle_t sc_ioh_base;
1621a945772Spatrick bus_space_handle_t sc_ioh_iface;
16309e5d825Spatrick paddr_t sc_ioh_paddr;
1641a945772Spatrick bus_size_t sc_iosize_base;
1651a945772Spatrick bus_size_t sc_iosize_iface;
1661a945772Spatrick bus_dma_tag_t sc_dmat;
16709e5d825Spatrick struct regmap *sc_rm;
1681a945772Spatrick
1691a945772Spatrick uint32_t sc_tclk;
1701a945772Spatrick
171be107da9Spatrick struct mvpp2_bm_pool *sc_bm_pools;
172be107da9Spatrick int sc_npools;
1731a945772Spatrick
1741a945772Spatrick struct mvpp2_prs_shadow *sc_prs_shadow;
1751a945772Spatrick uint8_t *sc_prs_double_vlans;
1761a945772Spatrick
1771a945772Spatrick int sc_aggr_ntxq;
1781a945772Spatrick struct mvpp2_tx_queue *sc_aggr_txqs;
1791a945772Spatrick
1801a945772Spatrick struct mvpp2_port **sc_ports;
1811a945772Spatrick };
1821a945772Spatrick
1831a945772Spatrick struct mvpp2_port {
1841a945772Spatrick struct device sc_dev;
1851a945772Spatrick struct mvpp2_softc *sc;
1861a945772Spatrick int sc_node;
1871a945772Spatrick bus_dma_tag_t sc_dmat;
1881a945772Spatrick int sc_id;
1891a945772Spatrick int sc_gop_id;
1901a945772Spatrick
1911a945772Spatrick struct arpcom sc_ac;
1921a945772Spatrick #define sc_lladdr sc_ac.ac_enaddr
1931a945772Spatrick struct mii_data sc_mii;
1941a945772Spatrick #define sc_media sc_mii.mii_media
195120fed02Spatrick struct mii_bus *sc_mdio;
1961a945772Spatrick
1971a945772Spatrick enum {
1981a945772Spatrick PHY_MODE_XAUI,
1991a945772Spatrick PHY_MODE_10GBASER,
2001a945772Spatrick PHY_MODE_2500BASEX,
2011a945772Spatrick PHY_MODE_1000BASEX,
2021a945772Spatrick PHY_MODE_SGMII,
2031a945772Spatrick PHY_MODE_RGMII,
2041a945772Spatrick PHY_MODE_RGMII_ID,
2051a945772Spatrick PHY_MODE_RGMII_RXID,
2061a945772Spatrick PHY_MODE_RGMII_TXID,
2071a945772Spatrick } sc_phy_mode;
2081a945772Spatrick int sc_fixed_link;
2091a945772Spatrick int sc_inband_status;
2101a945772Spatrick int sc_link;
2111a945772Spatrick int sc_phyloc;
2121a945772Spatrick int sc_sfp;
2131a945772Spatrick
2141a945772Spatrick int sc_ntxq;
2151a945772Spatrick int sc_nrxq;
2161a945772Spatrick
2171a945772Spatrick struct mvpp2_tx_queue *sc_txqs;
2181a945772Spatrick struct mvpp2_rx_queue *sc_rxqs;
2191a945772Spatrick
2201a945772Spatrick struct timeout sc_tick;
2211a945772Spatrick
2221a945772Spatrick uint32_t sc_tx_time_coal;
2231a945772Spatrick };
2241a945772Spatrick
2251a945772Spatrick #define MVPP2_MAX_PORTS 4
2261a945772Spatrick
2271a945772Spatrick struct mvpp2_attach_args {
2281a945772Spatrick int ma_node;
2291a945772Spatrick bus_dma_tag_t ma_dmat;
2301a945772Spatrick };
2311a945772Spatrick
2321a945772Spatrick #define DEVNAME(_s) ((_s)->sc_dev.dv_xname)
2331a945772Spatrick
2341a945772Spatrick static struct rwlock mvpp2_sff_lock = RWLOCK_INITIALIZER("mvpp2sff");
2351a945772Spatrick
2361a945772Spatrick int mvpp2_match(struct device *, void *, void *);
2371a945772Spatrick void mvpp2_attach(struct device *, struct device *, void *);
2381a945772Spatrick void mvpp2_attach_deferred(struct device *);
2391a945772Spatrick
240471aeecfSnaddy const struct cfattach mvppc_ca = {
2411a945772Spatrick sizeof(struct mvpp2_softc), mvpp2_match, mvpp2_attach
2421a945772Spatrick };
2431a945772Spatrick
2441a945772Spatrick struct cfdriver mvppc_cd = {
2451a945772Spatrick NULL, "mvppc", DV_DULL
2461a945772Spatrick };
2471a945772Spatrick
2481a945772Spatrick int mvpp2_port_match(struct device *, void *, void *);
2491a945772Spatrick void mvpp2_port_attach(struct device *, struct device *, void *);
2501a945772Spatrick
251471aeecfSnaddy const struct cfattach mvpp_ca = {
2521a945772Spatrick sizeof(struct mvpp2_port), mvpp2_port_match, mvpp2_port_attach
2531a945772Spatrick };
2541a945772Spatrick
2551a945772Spatrick struct cfdriver mvpp_cd = {
2561a945772Spatrick NULL, "mvpp", DV_IFNET
2571a945772Spatrick };
2581a945772Spatrick
259a02f2d56Skettenis void mvpp2_port_attach_sfp(struct device *);
260a02f2d56Skettenis
2611a945772Spatrick uint32_t mvpp2_read(struct mvpp2_softc *, bus_addr_t);
2621a945772Spatrick void mvpp2_write(struct mvpp2_softc *, bus_addr_t, uint32_t);
2631a945772Spatrick uint32_t mvpp2_gmac_read(struct mvpp2_port *, bus_addr_t);
2641a945772Spatrick void mvpp2_gmac_write(struct mvpp2_port *, bus_addr_t, uint32_t);
2651a945772Spatrick uint32_t mvpp2_xlg_read(struct mvpp2_port *, bus_addr_t);
2661a945772Spatrick void mvpp2_xlg_write(struct mvpp2_port *, bus_addr_t, uint32_t);
2671a945772Spatrick uint32_t mvpp2_xpcs_read(struct mvpp2_port *, bus_addr_t);
2681a945772Spatrick void mvpp2_xpcs_write(struct mvpp2_port *, bus_addr_t, uint32_t);
2691a945772Spatrick uint32_t mvpp2_mpcs_read(struct mvpp2_port *, bus_addr_t);
2701a945772Spatrick void mvpp2_mpcs_write(struct mvpp2_port *, bus_addr_t, uint32_t);
2711a945772Spatrick
2721a945772Spatrick int mvpp2_ioctl(struct ifnet *, u_long, caddr_t);
2731a945772Spatrick void mvpp2_start(struct ifnet *);
2741a945772Spatrick int mvpp2_rxrinfo(struct mvpp2_port *, struct if_rxrinfo *);
2751a945772Spatrick void mvpp2_watchdog(struct ifnet *);
2761a945772Spatrick
2771a945772Spatrick int mvpp2_media_change(struct ifnet *);
2781a945772Spatrick void mvpp2_media_status(struct ifnet *, struct ifmediareq *);
2791a945772Spatrick
2801a945772Spatrick int mvpp2_mii_readreg(struct device *, int, int);
2811a945772Spatrick void mvpp2_mii_writereg(struct device *, int, int, int);
2821a945772Spatrick void mvpp2_mii_statchg(struct device *);
2831a945772Spatrick void mvpp2_inband_statchg(struct mvpp2_port *);
2841a945772Spatrick void mvpp2_port_change(struct mvpp2_port *);
2851a945772Spatrick
2861a945772Spatrick void mvpp2_tick(void *);
2871a945772Spatrick
2881a945772Spatrick int mvpp2_link_intr(void *);
2891a945772Spatrick int mvpp2_intr(void *);
2901a945772Spatrick void mvpp2_tx_proc(struct mvpp2_port *, uint8_t);
29163ca77e8Spatrick void mvpp2_txq_proc(struct mvpp2_port *, struct mvpp2_tx_queue *);
2921a945772Spatrick void mvpp2_rx_proc(struct mvpp2_port *, uint8_t);
2931a945772Spatrick void mvpp2_rxq_proc(struct mvpp2_port *, struct mvpp2_rx_queue *);
294be107da9Spatrick void mvpp2_rx_refill(struct mvpp2_port *);
2951a945772Spatrick
2961a945772Spatrick void mvpp2_up(struct mvpp2_port *);
2971a945772Spatrick void mvpp2_down(struct mvpp2_port *);
2981a945772Spatrick void mvpp2_iff(struct mvpp2_port *);
2991a945772Spatrick
3001a945772Spatrick void mvpp2_aggr_txq_hw_init(struct mvpp2_softc *, struct mvpp2_tx_queue *);
3011a945772Spatrick void mvpp2_txq_hw_init(struct mvpp2_port *, struct mvpp2_tx_queue *);
3021a945772Spatrick void mvpp2_rxq_hw_init(struct mvpp2_port *, struct mvpp2_rx_queue *);
3031a945772Spatrick void mvpp2_txq_hw_deinit(struct mvpp2_port *, struct mvpp2_tx_queue *);
3048801406bSpatrick void mvpp2_rxq_hw_drop(struct mvpp2_port *, struct mvpp2_rx_queue *);
3051a945772Spatrick void mvpp2_rxq_hw_deinit(struct mvpp2_port *, struct mvpp2_rx_queue *);
3061a945772Spatrick void mvpp2_rxq_long_pool_set(struct mvpp2_port *, int, int);
3071a945772Spatrick void mvpp2_rxq_short_pool_set(struct mvpp2_port *, int, int);
3081a945772Spatrick
309c56f4c70Spatrick void mvpp2_mac_reset_assert(struct mvpp2_port *);
310c56f4c70Spatrick void mvpp2_pcs_reset_assert(struct mvpp2_port *);
311c56f4c70Spatrick void mvpp2_pcs_reset_deassert(struct mvpp2_port *);
3121a945772Spatrick void mvpp2_mac_config(struct mvpp2_port *);
3131a945772Spatrick void mvpp2_xlg_config(struct mvpp2_port *);
3141a945772Spatrick void mvpp2_gmac_config(struct mvpp2_port *);
315c56f4c70Spatrick void mvpp2_comphy_config(struct mvpp2_port *, int);
31609e5d825Spatrick void mvpp2_gop_config(struct mvpp2_port *);
317c56f4c70Spatrick void mvpp2_gop_intr_mask(struct mvpp2_port *);
318c56f4c70Spatrick void mvpp2_gop_intr_unmask(struct mvpp2_port *);
3191a945772Spatrick
3201a945772Spatrick struct mvpp2_dmamem *
3211a945772Spatrick mvpp2_dmamem_alloc(struct mvpp2_softc *, bus_size_t, bus_size_t);
3221a945772Spatrick void mvpp2_dmamem_free(struct mvpp2_softc *, struct mvpp2_dmamem *);
3231a945772Spatrick struct mbuf *mvpp2_alloc_mbuf(struct mvpp2_softc *, bus_dmamap_t);
3241a945772Spatrick
3251a945772Spatrick void mvpp2_interrupts_enable(struct mvpp2_port *, int);
3261a945772Spatrick void mvpp2_interrupts_disable(struct mvpp2_port *, int);
3271a945772Spatrick int mvpp2_egress_port(struct mvpp2_port *);
3281a945772Spatrick int mvpp2_txq_phys(int, int);
3291a945772Spatrick void mvpp2_defaults_set(struct mvpp2_port *);
3301a945772Spatrick void mvpp2_ingress_enable(struct mvpp2_port *);
3311a945772Spatrick void mvpp2_ingress_disable(struct mvpp2_port *);
3321a945772Spatrick void mvpp2_egress_enable(struct mvpp2_port *);
3331a945772Spatrick void mvpp2_egress_disable(struct mvpp2_port *);
3341a945772Spatrick void mvpp2_port_enable(struct mvpp2_port *);
3351a945772Spatrick void mvpp2_port_disable(struct mvpp2_port *);
3361a945772Spatrick void mvpp2_rxq_status_update(struct mvpp2_port *, int, int, int);
3371a945772Spatrick int mvpp2_rxq_received(struct mvpp2_port *, int);
3381a945772Spatrick void mvpp2_rxq_offset_set(struct mvpp2_port *, int, int);
3391a945772Spatrick void mvpp2_txp_max_tx_size_set(struct mvpp2_port *);
3401a945772Spatrick void mvpp2_rx_pkts_coal_set(struct mvpp2_port *, struct mvpp2_rx_queue *,
3411a945772Spatrick uint32_t);
3421a945772Spatrick void mvpp2_tx_pkts_coal_set(struct mvpp2_port *, struct mvpp2_tx_queue *,
3431a945772Spatrick uint32_t);
3441a945772Spatrick void mvpp2_rx_time_coal_set(struct mvpp2_port *, struct mvpp2_rx_queue *,
3451a945772Spatrick uint32_t);
3461a945772Spatrick void mvpp2_tx_time_coal_set(struct mvpp2_port *, uint32_t);
3471a945772Spatrick
3481a945772Spatrick void mvpp2_axi_config(struct mvpp2_softc *);
3491a945772Spatrick void mvpp2_bm_pool_init(struct mvpp2_softc *);
3501a945772Spatrick void mvpp2_rx_fifo_init(struct mvpp2_softc *);
3511a945772Spatrick void mvpp2_tx_fifo_init(struct mvpp2_softc *);
3521a945772Spatrick int mvpp2_prs_default_init(struct mvpp2_softc *);
3531a945772Spatrick void mvpp2_prs_hw_inv(struct mvpp2_softc *, int);
3541a945772Spatrick void mvpp2_prs_hw_port_init(struct mvpp2_softc *, int, int, int, int);
3551a945772Spatrick void mvpp2_prs_def_flow_init(struct mvpp2_softc *);
3561a945772Spatrick void mvpp2_prs_mh_init(struct mvpp2_softc *);
3571a945772Spatrick void mvpp2_prs_mac_init(struct mvpp2_softc *);
3581a945772Spatrick void mvpp2_prs_dsa_init(struct mvpp2_softc *);
3591a945772Spatrick int mvpp2_prs_etype_init(struct mvpp2_softc *);
3601a945772Spatrick int mvpp2_prs_vlan_init(struct mvpp2_softc *);
3611a945772Spatrick int mvpp2_prs_pppoe_init(struct mvpp2_softc *);
3621a945772Spatrick int mvpp2_prs_ip6_init(struct mvpp2_softc *);
3631a945772Spatrick int mvpp2_prs_ip4_init(struct mvpp2_softc *);
3641a945772Spatrick void mvpp2_prs_shadow_ri_set(struct mvpp2_softc *, int,
3651a945772Spatrick uint32_t, uint32_t);
3661a945772Spatrick void mvpp2_prs_tcam_lu_set(struct mvpp2_prs_entry *, uint32_t);
3671a945772Spatrick void mvpp2_prs_tcam_port_set(struct mvpp2_prs_entry *, uint32_t, int);
3681a945772Spatrick void mvpp2_prs_tcam_port_map_set(struct mvpp2_prs_entry *, uint32_t);
3691a945772Spatrick uint32_t mvpp2_prs_tcam_port_map_get(struct mvpp2_prs_entry *);
3701a945772Spatrick void mvpp2_prs_tcam_data_byte_set(struct mvpp2_prs_entry *, uint32_t,
3711a945772Spatrick uint8_t, uint8_t);
3721a945772Spatrick void mvpp2_prs_tcam_data_byte_get(struct mvpp2_prs_entry *, uint32_t,
3731a945772Spatrick uint8_t *, uint8_t *);
3741a945772Spatrick int mvpp2_prs_tcam_data_cmp(struct mvpp2_prs_entry *, int, uint16_t);
3751a945772Spatrick void mvpp2_prs_tcam_ai_update(struct mvpp2_prs_entry *, uint32_t, uint32_t);
3761a945772Spatrick int mvpp2_prs_sram_ai_get(struct mvpp2_prs_entry *);
3771a945772Spatrick int mvpp2_prs_tcam_ai_get(struct mvpp2_prs_entry *);
3781a945772Spatrick void mvpp2_prs_tcam_data_word_get(struct mvpp2_prs_entry *, uint32_t,
3791a945772Spatrick uint32_t *, uint32_t *);
3801a945772Spatrick void mvpp2_prs_match_etype(struct mvpp2_prs_entry *, uint32_t, uint16_t);
3811a945772Spatrick int mvpp2_prs_sram_ri_get(struct mvpp2_prs_entry *);
3821a945772Spatrick void mvpp2_prs_sram_ai_update(struct mvpp2_prs_entry *, uint32_t, uint32_t);
3831a945772Spatrick void mvpp2_prs_sram_ri_update(struct mvpp2_prs_entry *, uint32_t, uint32_t);
3841a945772Spatrick void mvpp2_prs_sram_bits_set(struct mvpp2_prs_entry *, uint32_t, uint32_t);
3851a945772Spatrick void mvpp2_prs_sram_bits_clear(struct mvpp2_prs_entry *, uint32_t, uint32_t);
3861a945772Spatrick void mvpp2_prs_sram_shift_set(struct mvpp2_prs_entry *, int, uint32_t);
3871a945772Spatrick void mvpp2_prs_sram_offset_set(struct mvpp2_prs_entry *, uint32_t, int,
3881a945772Spatrick uint32_t);
3891a945772Spatrick void mvpp2_prs_sram_next_lu_set(struct mvpp2_prs_entry *, uint32_t);
3901a945772Spatrick void mvpp2_prs_shadow_set(struct mvpp2_softc *, int, uint32_t);
3911a945772Spatrick int mvpp2_prs_hw_write(struct mvpp2_softc *, struct mvpp2_prs_entry *);
392fad015d2Spatrick int mvpp2_prs_hw_read(struct mvpp2_softc *, struct mvpp2_prs_entry *, int);
393fef01367Spatrick int mvpp2_prs_flow_find(struct mvpp2_softc *, int);
3941a945772Spatrick int mvpp2_prs_tcam_first_free(struct mvpp2_softc *, uint8_t, uint8_t);
3951a945772Spatrick void mvpp2_prs_mac_drop_all_set(struct mvpp2_softc *, uint32_t, int);
39641cd246cSpatrick void mvpp2_prs_mac_promisc_set(struct mvpp2_softc *, uint32_t, int, int);
3971a945772Spatrick void mvpp2_prs_dsa_tag_set(struct mvpp2_softc *, uint32_t, int, int, int);
3981a945772Spatrick void mvpp2_prs_dsa_tag_ethertype_set(struct mvpp2_softc *, uint32_t,
3991a945772Spatrick int, int, int);
4001a945772Spatrick struct mvpp2_prs_entry *mvpp2_prs_vlan_find(struct mvpp2_softc *, uint16_t,
4011a945772Spatrick int);
4021a945772Spatrick int mvpp2_prs_vlan_add(struct mvpp2_softc *, uint16_t, int, uint32_t);
4031a945772Spatrick int mvpp2_prs_double_vlan_ai_free_get(struct mvpp2_softc *);
4041a945772Spatrick struct mvpp2_prs_entry *mvpp2_prs_double_vlan_find(struct mvpp2_softc *,
4051a945772Spatrick uint16_t, uint16_t);
4061a945772Spatrick int mvpp2_prs_double_vlan_add(struct mvpp2_softc *, uint16_t, uint16_t,
4071a945772Spatrick uint32_t);
4081a945772Spatrick int mvpp2_prs_ip4_proto(struct mvpp2_softc *, uint16_t, uint32_t, uint32_t);
4091a945772Spatrick int mvpp2_prs_ip4_cast(struct mvpp2_softc *, uint16_t);
4101a945772Spatrick int mvpp2_prs_ip6_proto(struct mvpp2_softc *, uint16_t, uint32_t, uint32_t);
4111a945772Spatrick int mvpp2_prs_ip6_cast(struct mvpp2_softc *, uint16_t);
41241cd246cSpatrick int mvpp2_prs_mac_da_range_find(struct mvpp2_softc *, int, const uint8_t *,
41341cd246cSpatrick uint8_t *, int);
4141a945772Spatrick int mvpp2_prs_mac_range_equals(struct mvpp2_prs_entry *, const uint8_t *,
4151a945772Spatrick uint8_t *);
41641cd246cSpatrick int mvpp2_prs_mac_da_accept(struct mvpp2_port *, const uint8_t *, int);
417ce595ab8Spatrick void mvpp2_prs_mac_del_all(struct mvpp2_port *);
4181a945772Spatrick int mvpp2_prs_tag_mode_set(struct mvpp2_softc *, int, int);
4191a945772Spatrick int mvpp2_prs_def_flow(struct mvpp2_port *);
4201a945772Spatrick void mvpp2_cls_flow_write(struct mvpp2_softc *, struct mvpp2_cls_flow_entry *);
4211a945772Spatrick void mvpp2_cls_lookup_write(struct mvpp2_softc *, struct mvpp2_cls_lookup_entry *);
4221a945772Spatrick void mvpp2_cls_init(struct mvpp2_softc *);
4231a945772Spatrick void mvpp2_cls_port_config(struct mvpp2_port *);
4241a945772Spatrick void mvpp2_cls_oversize_rxq_set(struct mvpp2_port *);
4251a945772Spatrick
4261a945772Spatrick int
mvpp2_match(struct device * parent,void * cfdata,void * aux)4271a945772Spatrick mvpp2_match(struct device *parent, void *cfdata, void *aux)
4281a945772Spatrick {
4291a945772Spatrick struct fdt_attach_args *faa = aux;
4301a945772Spatrick
4311a945772Spatrick return OF_is_compatible(faa->fa_node, "marvell,armada-7k-pp22");
4321a945772Spatrick }
4331a945772Spatrick
4341a945772Spatrick void
mvpp2_attach(struct device * parent,struct device * self,void * aux)4351a945772Spatrick mvpp2_attach(struct device *parent, struct device *self, void *aux)
4361a945772Spatrick {
4371a945772Spatrick struct mvpp2_softc *sc = (void *)self;
4381a945772Spatrick struct fdt_attach_args *faa = aux;
4391a945772Spatrick
4401a945772Spatrick if (faa->fa_nreg < 2) {
4411a945772Spatrick printf(": no registers\n");
4421a945772Spatrick return;
4431a945772Spatrick }
4441a945772Spatrick
4451a945772Spatrick sc->sc_node = faa->fa_node;
4461a945772Spatrick sc->sc_iot = faa->fa_iot;
4471a945772Spatrick sc->sc_dmat = faa->fa_dmat;
4481a945772Spatrick
4491a945772Spatrick if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
4501a945772Spatrick faa->fa_reg[0].size, 0, &sc->sc_ioh_base)) {
4511a945772Spatrick printf(": can't map registers\n");
4521a945772Spatrick return;
4531a945772Spatrick }
4541a945772Spatrick sc->sc_iosize_base = faa->fa_reg[0].size;
4551a945772Spatrick
456983593c5Skettenis sc->sc_ioh_paddr = bus_space_mmap(sc->sc_iot, faa->fa_reg[0].addr,
457983593c5Skettenis 0, PROT_READ | PROT_WRITE, 0);
458983593c5Skettenis KASSERT(sc->sc_ioh_paddr != -1);
459983593c5Skettenis sc->sc_ioh_paddr &= PMAP_PA_MASK;
46009e5d825Spatrick
4611a945772Spatrick if (bus_space_map(sc->sc_iot, faa->fa_reg[1].addr,
4621a945772Spatrick faa->fa_reg[1].size, 0, &sc->sc_ioh_iface)) {
4631a945772Spatrick printf(": can't map registers\n");
4641a945772Spatrick bus_space_unmap(sc->sc_iot, sc->sc_ioh_base,
4651a945772Spatrick sc->sc_iosize_base);
4661a945772Spatrick return;
4671a945772Spatrick }
4681a945772Spatrick sc->sc_iosize_iface = faa->fa_reg[1].size;
4691a945772Spatrick
47009e5d825Spatrick sc->sc_rm = regmap_byphandle(OF_getpropint(faa->fa_node,
47109e5d825Spatrick "marvell,system-controller", 0));
47209e5d825Spatrick
4731a945772Spatrick clock_enable_all(faa->fa_node);
4741a945772Spatrick sc->sc_tclk = clock_get_frequency(faa->fa_node, "pp_clk");
4751a945772Spatrick
4761a945772Spatrick printf("\n");
4771a945772Spatrick
4781a945772Spatrick config_defer(self, mvpp2_attach_deferred);
4791a945772Spatrick }
4801a945772Spatrick
4811a945772Spatrick void
mvpp2_attach_deferred(struct device * self)4821a945772Spatrick mvpp2_attach_deferred(struct device *self)
4831a945772Spatrick {
4841a945772Spatrick struct mvpp2_softc *sc = (void *)self;
4851a945772Spatrick struct mvpp2_attach_args maa;
4861a945772Spatrick struct mvpp2_tx_queue *txq;
4871a945772Spatrick int i, node;
4881a945772Spatrick
4891a945772Spatrick mvpp2_axi_config(sc);
4901a945772Spatrick
491b3a1ec52Spatrick bus_space_write_4(sc->sc_iot, sc->sc_ioh_iface, MVPP22_SMI_MISC_CFG_REG,
492b3a1ec52Spatrick bus_space_read_4(sc->sc_iot, sc->sc_ioh_iface,
493b3a1ec52Spatrick MVPP22_SMI_MISC_CFG_REG) & ~MVPP22_SMI_POLLING_EN);
494b3a1ec52Spatrick
4951a945772Spatrick sc->sc_aggr_ntxq = 1;
4961a945772Spatrick sc->sc_aggr_txqs = mallocarray(sc->sc_aggr_ntxq,
4971a945772Spatrick sizeof(*sc->sc_aggr_txqs), M_DEVBUF, M_WAITOK | M_ZERO);
4981a945772Spatrick
4991a945772Spatrick for (i = 0; i < sc->sc_aggr_ntxq; i++) {
5001a945772Spatrick txq = &sc->sc_aggr_txqs[i];
5011a945772Spatrick txq->id = i;
5021a945772Spatrick mvpp2_aggr_txq_hw_init(sc, txq);
5031a945772Spatrick }
5041a945772Spatrick
5051a945772Spatrick mvpp2_rx_fifo_init(sc);
5061a945772Spatrick mvpp2_tx_fifo_init(sc);
5071a945772Spatrick
5081a945772Spatrick mvpp2_write(sc, MVPP2_TX_SNOOP_REG, 0x1);
5091a945772Spatrick
5101a945772Spatrick mvpp2_bm_pool_init(sc);
5111a945772Spatrick
5121a945772Spatrick sc->sc_prs_shadow = mallocarray(MVPP2_PRS_TCAM_SRAM_SIZE,
5131a945772Spatrick sizeof(*sc->sc_prs_shadow), M_DEVBUF, M_WAITOK | M_ZERO);
5141a945772Spatrick
5151a945772Spatrick mvpp2_prs_default_init(sc);
5161a945772Spatrick mvpp2_cls_init(sc);
5171a945772Spatrick
5181a945772Spatrick memset(&maa, 0, sizeof(maa));
5191a945772Spatrick for (node = OF_child(sc->sc_node); node; node = OF_peer(node)) {
5201a945772Spatrick maa.ma_node = node;
5211a945772Spatrick maa.ma_dmat = sc->sc_dmat;
5221a945772Spatrick config_found(self, &maa, NULL);
5231a945772Spatrick }
5241a945772Spatrick }
5251a945772Spatrick
5261a945772Spatrick void
mvpp2_axi_config(struct mvpp2_softc * sc)5271a945772Spatrick mvpp2_axi_config(struct mvpp2_softc *sc)
5281a945772Spatrick {
5291a945772Spatrick uint32_t reg;
5301a945772Spatrick
53113d9cc68Spatrick mvpp2_write(sc, MVPP22_BM_ADDR_HIGH_RLS_REG, 0);
5321a945772Spatrick
5331a945772Spatrick reg = (MVPP22_AXI_CODE_CACHE_WR_CACHE << MVPP22_AXI_ATTR_CACHE_OFFS) |
5341a945772Spatrick (MVPP22_AXI_CODE_DOMAIN_OUTER_DOM << MVPP22_AXI_ATTR_DOMAIN_OFFS);
5351a945772Spatrick mvpp2_write(sc, MVPP22_AXI_BM_WR_ATTR_REG, reg);
5361a945772Spatrick mvpp2_write(sc, MVPP22_AXI_TXQ_DESCR_WR_ATTR_REG, reg);
5371a945772Spatrick mvpp2_write(sc, MVPP22_AXI_RXQ_DESCR_WR_ATTR_REG, reg);
5381a945772Spatrick mvpp2_write(sc, MVPP22_AXI_RX_DATA_WR_ATTR_REG, reg);
5391a945772Spatrick
5401a945772Spatrick reg = (MVPP22_AXI_CODE_CACHE_RD_CACHE << MVPP22_AXI_ATTR_CACHE_OFFS) |
5411a945772Spatrick (MVPP22_AXI_CODE_DOMAIN_OUTER_DOM << MVPP22_AXI_ATTR_DOMAIN_OFFS);
5421a945772Spatrick mvpp2_write(sc, MVPP22_AXI_BM_RD_ATTR_REG, reg);
5431a945772Spatrick mvpp2_write(sc, MVPP22_AXI_AGGRQ_DESCR_RD_ATTR_REG, reg);
5441a945772Spatrick mvpp2_write(sc, MVPP22_AXI_TXQ_DESCR_RD_ATTR_REG, reg);
5451a945772Spatrick mvpp2_write(sc, MVPP22_AXI_TX_DATA_RD_ATTR_REG, reg);
5461a945772Spatrick
5471a945772Spatrick reg = (MVPP22_AXI_CODE_CACHE_NON_CACHE << MVPP22_AXI_CODE_CACHE_OFFS) |
5481a945772Spatrick (MVPP22_AXI_CODE_DOMAIN_SYSTEM << MVPP22_AXI_CODE_DOMAIN_OFFS);
5491a945772Spatrick mvpp2_write(sc, MVPP22_AXI_RD_NORMAL_CODE_REG, reg);
5501a945772Spatrick mvpp2_write(sc, MVPP22_AXI_WR_NORMAL_CODE_REG, reg);
5511a945772Spatrick
5521a945772Spatrick reg = (MVPP22_AXI_CODE_CACHE_RD_CACHE << MVPP22_AXI_CODE_CACHE_OFFS) |
5531a945772Spatrick (MVPP22_AXI_CODE_DOMAIN_OUTER_DOM << MVPP22_AXI_CODE_DOMAIN_OFFS);
5541a945772Spatrick mvpp2_write(sc, MVPP22_AXI_RD_SNOOP_CODE_REG, reg);
5551a945772Spatrick
5561a945772Spatrick reg = (MVPP22_AXI_CODE_CACHE_WR_CACHE << MVPP22_AXI_CODE_CACHE_OFFS) |
5571a945772Spatrick (MVPP22_AXI_CODE_DOMAIN_OUTER_DOM << MVPP22_AXI_CODE_DOMAIN_OFFS);
5581a945772Spatrick mvpp2_write(sc, MVPP22_AXI_WR_SNOOP_CODE_REG, reg);
5591a945772Spatrick }
5601a945772Spatrick
5611a945772Spatrick void
mvpp2_bm_pool_init(struct mvpp2_softc * sc)5621a945772Spatrick mvpp2_bm_pool_init(struct mvpp2_softc *sc)
5631a945772Spatrick {
5641a945772Spatrick struct mvpp2_bm_pool *bm;
5651a945772Spatrick struct mvpp2_buf *rxb;
5661a945772Spatrick uint64_t phys, virt;
5676d508037Spatrick int i, j, inuse;
5681a945772Spatrick
5691a945772Spatrick for (i = 0; i < MVPP2_BM_POOLS_NUM; i++) {
5701a945772Spatrick mvpp2_write(sc, MVPP2_BM_INTR_MASK_REG(i), 0);
5711a945772Spatrick mvpp2_write(sc, MVPP2_BM_INTR_CAUSE_REG(i), 0);
5721a945772Spatrick }
5731a945772Spatrick
574be107da9Spatrick sc->sc_npools = ncpus;
575be107da9Spatrick sc->sc_npools = min(sc->sc_npools, MVPP2_BM_POOLS_NUM);
576be107da9Spatrick
577be107da9Spatrick sc->sc_bm_pools = mallocarray(sc->sc_npools, sizeof(*sc->sc_bm_pools),
578be107da9Spatrick M_DEVBUF, M_WAITOK | M_ZERO);
579be107da9Spatrick
580be107da9Spatrick for (i = 0; i < sc->sc_npools; i++) {
5811a945772Spatrick bm = &sc->sc_bm_pools[i];
5821a945772Spatrick bm->bm_mem = mvpp2_dmamem_alloc(sc,
5831a945772Spatrick MVPP2_BM_SIZE * sizeof(uint64_t) * 2,
5841a945772Spatrick MVPP2_BM_POOL_PTR_ALIGN);
5857262ae33Spatrick KASSERT(bm->bm_mem != NULL);
5861a945772Spatrick bus_dmamap_sync(sc->sc_dmat, MVPP2_DMA_MAP(bm->bm_mem), 0,
5871a945772Spatrick MVPP2_DMA_LEN(bm->bm_mem),
5881a945772Spatrick BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
5891a945772Spatrick
5906d508037Spatrick mvpp2_write(sc, MVPP2_BM_POOL_CTRL_REG(i),
5916d508037Spatrick mvpp2_read(sc, MVPP2_BM_POOL_CTRL_REG(i)) |
5926d508037Spatrick MVPP2_BM_STOP_MASK);
5936d508037Spatrick
5941a945772Spatrick mvpp2_write(sc, MVPP2_BM_POOL_BASE_REG(i),
5954f6c1c9bSpatrick (uint64_t)MVPP2_DMA_DVA(bm->bm_mem) & 0xffffffff);
5961a945772Spatrick mvpp2_write(sc, MVPP22_BM_POOL_BASE_HIGH_REG,
5974f6c1c9bSpatrick ((uint64_t)MVPP2_DMA_DVA(bm->bm_mem) >> 32)
5981a945772Spatrick & MVPP22_BM_POOL_BASE_HIGH_MASK);
5991a945772Spatrick mvpp2_write(sc, MVPP2_BM_POOL_SIZE_REG(i),
6001a945772Spatrick MVPP2_BM_SIZE);
6011a945772Spatrick
6021a945772Spatrick mvpp2_write(sc, MVPP2_BM_POOL_CTRL_REG(i),
6031a945772Spatrick mvpp2_read(sc, MVPP2_BM_POOL_CTRL_REG(i)) |
6041a945772Spatrick MVPP2_BM_START_MASK);
6051a945772Spatrick
6066d508037Spatrick /*
6076d508037Spatrick * U-Boot might not have cleaned its pools. The pool needs
6086d508037Spatrick * to be empty before we fill it, otherwise our packets are
6096d508037Spatrick * written to wherever U-Boot allocated memory. Cleaning it
6106d508037Spatrick * up ourselves is worrying as well, since the BM's pages are
6116d508037Spatrick * probably in our own memory. Best we can do is stop the BM,
6126d508037Spatrick * set new memory and drain the pool.
6136d508037Spatrick */
6146d508037Spatrick inuse = mvpp2_read(sc, MVPP2_BM_POOL_PTRS_NUM_REG(i)) &
6156d508037Spatrick MVPP2_BM_POOL_PTRS_NUM_MASK;
6166d508037Spatrick inuse += mvpp2_read(sc, MVPP2_BM_BPPI_PTRS_NUM_REG(i)) &
6176d508037Spatrick MVPP2_BM_BPPI_PTRS_NUM_MASK;
6186d508037Spatrick if (inuse)
6196d508037Spatrick inuse++;
6206d508037Spatrick for (j = 0; j < inuse; j++)
6216d508037Spatrick mvpp2_read(sc, MVPP2_BM_PHY_ALLOC_REG(i));
6226d508037Spatrick
6231a945772Spatrick mvpp2_write(sc, MVPP2_POOL_BUF_SIZE_REG(i),
6241a945772Spatrick roundup(MCLBYTES, 1 << MVPP2_POOL_BUF_SIZE_OFFSET));
6251a945772Spatrick
6261a945772Spatrick bm->rxbuf = mallocarray(MVPP2_BM_SIZE, sizeof(struct mvpp2_buf),
6271a945772Spatrick M_DEVBUF, M_WAITOK);
628be107da9Spatrick bm->freelist = mallocarray(MVPP2_BM_SIZE, sizeof(*bm->freelist),
629be107da9Spatrick M_DEVBUF, M_WAITOK | M_ZERO);
6301a945772Spatrick
6311a945772Spatrick for (j = 0; j < MVPP2_BM_SIZE; j++) {
6321a945772Spatrick rxb = &bm->rxbuf[j];
6331a945772Spatrick bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
6341a945772Spatrick MCLBYTES, 0, BUS_DMA_WAITOK, &rxb->mb_map);
635be107da9Spatrick rxb->mb_m = NULL;
6361a945772Spatrick }
6371a945772Spatrick
638be107da9Spatrick /* Use pool-id and rxbuf index as cookie. */
639be107da9Spatrick for (j = 0; j < MVPP2_BM_SIZE; j++)
640be107da9Spatrick bm->freelist[j] = (i << 16) | (j << 0);
641be107da9Spatrick
6421a945772Spatrick for (j = 0; j < MVPP2_BM_SIZE; j++) {
6431a945772Spatrick rxb = &bm->rxbuf[j];
6441a945772Spatrick rxb->mb_m = mvpp2_alloc_mbuf(sc, rxb->mb_map);
6451a945772Spatrick if (rxb->mb_m == NULL)
6461a945772Spatrick break;
647be107da9Spatrick
648be107da9Spatrick KASSERT(bm->freelist[bm->free_cons] != -1);
649be107da9Spatrick virt = bm->freelist[bm->free_cons];
650be107da9Spatrick bm->freelist[bm->free_cons] = -1;
651be107da9Spatrick bm->free_cons = (bm->free_cons + 1) % MVPP2_BM_SIZE;
652be107da9Spatrick
6531a945772Spatrick phys = rxb->mb_map->dm_segs[0].ds_addr;
65413d9cc68Spatrick mvpp2_write(sc, MVPP22_BM_ADDR_HIGH_RLS_REG,
6551a945772Spatrick (((virt >> 32) & MVPP22_ADDR_HIGH_MASK)
65613d9cc68Spatrick << MVPP22_BM_ADDR_HIGH_VIRT_RLS_SHIFT) |
65713d9cc68Spatrick ((phys >> 32) & MVPP22_ADDR_HIGH_MASK));
6581a945772Spatrick mvpp2_write(sc, MVPP2_BM_VIRT_RLS_REG,
6591a945772Spatrick virt & 0xffffffff);
6601a945772Spatrick mvpp2_write(sc, MVPP2_BM_PHY_RLS_REG(i),
6611a945772Spatrick phys & 0xffffffff);
6621a945772Spatrick }
6631a945772Spatrick }
6641a945772Spatrick }
6651a945772Spatrick
6661a945772Spatrick void
mvpp2_rx_fifo_init(struct mvpp2_softc * sc)6671a945772Spatrick mvpp2_rx_fifo_init(struct mvpp2_softc *sc)
6681a945772Spatrick {
6691a945772Spatrick int i;
6701a945772Spatrick
6711a945772Spatrick mvpp2_write(sc, MVPP2_RX_DATA_FIFO_SIZE_REG(0),
6721a945772Spatrick MVPP2_RX_FIFO_PORT_DATA_SIZE_32KB);
6731a945772Spatrick mvpp2_write(sc, MVPP2_RX_ATTR_FIFO_SIZE_REG(0),
6741a945772Spatrick MVPP2_RX_FIFO_PORT_ATTR_SIZE_32KB);
6751a945772Spatrick
6761a945772Spatrick mvpp2_write(sc, MVPP2_RX_DATA_FIFO_SIZE_REG(1),
6771a945772Spatrick MVPP2_RX_FIFO_PORT_DATA_SIZE_8KB);
6781a945772Spatrick mvpp2_write(sc, MVPP2_RX_ATTR_FIFO_SIZE_REG(1),
6791a945772Spatrick MVPP2_RX_FIFO_PORT_ATTR_SIZE_8KB);
6801a945772Spatrick
6811a945772Spatrick for (i = 2; i < MVPP2_MAX_PORTS; i++) {
6821a945772Spatrick mvpp2_write(sc, MVPP2_RX_DATA_FIFO_SIZE_REG(i),
6831a945772Spatrick MVPP2_RX_FIFO_PORT_DATA_SIZE_4KB);
6841a945772Spatrick mvpp2_write(sc, MVPP2_RX_ATTR_FIFO_SIZE_REG(i),
6851a945772Spatrick MVPP2_RX_FIFO_PORT_ATTR_SIZE_4KB);
6861a945772Spatrick }
6871a945772Spatrick
6881a945772Spatrick mvpp2_write(sc, MVPP2_RX_MIN_PKT_SIZE_REG, MVPP2_RX_FIFO_PORT_MIN_PKT);
6891a945772Spatrick mvpp2_write(sc, MVPP2_RX_FIFO_INIT_REG, 0x1);
6901a945772Spatrick }
6911a945772Spatrick
6921a945772Spatrick void
mvpp2_tx_fifo_init(struct mvpp2_softc * sc)6931a945772Spatrick mvpp2_tx_fifo_init(struct mvpp2_softc *sc)
6941a945772Spatrick {
6951a945772Spatrick int i;
6961a945772Spatrick
6971a945772Spatrick mvpp2_write(sc, MVPP22_TX_FIFO_SIZE_REG(0),
6981a945772Spatrick MVPP22_TX_FIFO_DATA_SIZE_10KB);
6991a945772Spatrick mvpp2_write(sc, MVPP22_TX_FIFO_THRESH_REG(0),
7001a945772Spatrick MVPP2_TX_FIFO_THRESHOLD_10KB);
7011a945772Spatrick
7021a945772Spatrick for (i = 1; i < MVPP2_MAX_PORTS; i++) {
7031a945772Spatrick mvpp2_write(sc, MVPP22_TX_FIFO_SIZE_REG(i),
7041a945772Spatrick MVPP22_TX_FIFO_DATA_SIZE_3KB);
7051a945772Spatrick mvpp2_write(sc, MVPP22_TX_FIFO_THRESH_REG(i),
7061a945772Spatrick MVPP2_TX_FIFO_THRESHOLD_3KB);
7071a945772Spatrick }
7081a945772Spatrick }
7091a945772Spatrick
7101a945772Spatrick int
mvpp2_prs_default_init(struct mvpp2_softc * sc)7111a945772Spatrick mvpp2_prs_default_init(struct mvpp2_softc *sc)
7121a945772Spatrick {
7131a945772Spatrick int i, j, ret;
7141a945772Spatrick
7151a945772Spatrick mvpp2_write(sc, MVPP2_PRS_TCAM_CTRL_REG, MVPP2_PRS_TCAM_EN_MASK);
7161a945772Spatrick
7171a945772Spatrick for (i = 0; i < MVPP2_PRS_TCAM_SRAM_SIZE; i++) {
7181a945772Spatrick mvpp2_write(sc, MVPP2_PRS_TCAM_IDX_REG, i);
7191a945772Spatrick for (j = 0; j < MVPP2_PRS_TCAM_WORDS; j++)
7201a945772Spatrick mvpp2_write(sc, MVPP2_PRS_TCAM_DATA_REG(j), 0);
7211a945772Spatrick
7221a945772Spatrick mvpp2_write(sc, MVPP2_PRS_SRAM_IDX_REG, i);
7231a945772Spatrick for (j = 0; j < MVPP2_PRS_SRAM_WORDS; j++)
7241a945772Spatrick mvpp2_write(sc, MVPP2_PRS_SRAM_DATA_REG(j), 0);
7251a945772Spatrick }
7261a945772Spatrick
7271a945772Spatrick for (i = 0; i < MVPP2_PRS_TCAM_SRAM_SIZE; i++)
7281a945772Spatrick mvpp2_prs_hw_inv(sc, i);
7291a945772Spatrick
7301a945772Spatrick for (i = 0; i < MVPP2_MAX_PORTS; i++)
7311a945772Spatrick mvpp2_prs_hw_port_init(sc, i, MVPP2_PRS_LU_MH,
7321a945772Spatrick MVPP2_PRS_PORT_LU_MAX, 0);
7331a945772Spatrick
7341a945772Spatrick mvpp2_prs_def_flow_init(sc);
7351a945772Spatrick mvpp2_prs_mh_init(sc);
7361a945772Spatrick mvpp2_prs_mac_init(sc);
7371a945772Spatrick mvpp2_prs_dsa_init(sc);
7381a945772Spatrick ret = mvpp2_prs_etype_init(sc);
7391a945772Spatrick if (ret)
7401a945772Spatrick return ret;
7411a945772Spatrick ret = mvpp2_prs_vlan_init(sc);
7421a945772Spatrick if (ret)
7431a945772Spatrick return ret;
7441a945772Spatrick ret = mvpp2_prs_pppoe_init(sc);
7451a945772Spatrick if (ret)
7461a945772Spatrick return ret;
7471a945772Spatrick ret = mvpp2_prs_ip6_init(sc);
7481a945772Spatrick if (ret)
7491a945772Spatrick return ret;
7501a945772Spatrick ret = mvpp2_prs_ip4_init(sc);
7511a945772Spatrick if (ret)
7521a945772Spatrick return ret;
7531a945772Spatrick
7541a945772Spatrick return 0;
7551a945772Spatrick }
7561a945772Spatrick
7571a945772Spatrick void
mvpp2_prs_hw_inv(struct mvpp2_softc * sc,int index)7581a945772Spatrick mvpp2_prs_hw_inv(struct mvpp2_softc *sc, int index)
7591a945772Spatrick {
7601a945772Spatrick mvpp2_write(sc, MVPP2_PRS_TCAM_IDX_REG, index);
7611a945772Spatrick mvpp2_write(sc, MVPP2_PRS_TCAM_DATA_REG(MVPP2_PRS_TCAM_INV_WORD),
7621a945772Spatrick MVPP2_PRS_TCAM_INV_MASK);
7631a945772Spatrick }
7641a945772Spatrick
7651a945772Spatrick void
mvpp2_prs_hw_port_init(struct mvpp2_softc * sc,int port,int lu_first,int lu_max,int offset)7661a945772Spatrick mvpp2_prs_hw_port_init(struct mvpp2_softc *sc, int port,
7671a945772Spatrick int lu_first, int lu_max, int offset)
7681a945772Spatrick {
7691a945772Spatrick uint32_t reg;
7701a945772Spatrick
7711a945772Spatrick reg = mvpp2_read(sc, MVPP2_PRS_INIT_LOOKUP_REG);
7721a945772Spatrick reg &= ~MVPP2_PRS_PORT_LU_MASK(port);
7731a945772Spatrick reg |= MVPP2_PRS_PORT_LU_VAL(port, lu_first);
7741a945772Spatrick mvpp2_write(sc, MVPP2_PRS_INIT_LOOKUP_REG, reg);
7751a945772Spatrick
7761a945772Spatrick reg = mvpp2_read(sc, MVPP2_PRS_MAX_LOOP_REG(port));
7771a945772Spatrick reg &= ~MVPP2_PRS_MAX_LOOP_MASK(port);
7781a945772Spatrick reg |= MVPP2_PRS_MAX_LOOP_VAL(port, lu_max);
7791a945772Spatrick mvpp2_write(sc, MVPP2_PRS_MAX_LOOP_REG(port), reg);
7801a945772Spatrick
7811a945772Spatrick reg = mvpp2_read(sc, MVPP2_PRS_INIT_OFFS_REG(port));
7821a945772Spatrick reg &= ~MVPP2_PRS_INIT_OFF_MASK(port);
7831a945772Spatrick reg |= MVPP2_PRS_INIT_OFF_VAL(port, offset);
7841a945772Spatrick mvpp2_write(sc, MVPP2_PRS_INIT_OFFS_REG(port), reg);
7851a945772Spatrick }
7861a945772Spatrick
7871a945772Spatrick void
mvpp2_prs_def_flow_init(struct mvpp2_softc * sc)7881a945772Spatrick mvpp2_prs_def_flow_init(struct mvpp2_softc *sc)
7891a945772Spatrick {
7901a945772Spatrick struct mvpp2_prs_entry pe;
7911a945772Spatrick int i;
7921a945772Spatrick
7931a945772Spatrick for (i = 0; i < MVPP2_MAX_PORTS; i++) {
7941a945772Spatrick memset(&pe, 0, sizeof(pe));
7951a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
7961a945772Spatrick pe.index = MVPP2_PE_FIRST_DEFAULT_FLOW - i;
7971a945772Spatrick mvpp2_prs_tcam_port_map_set(&pe, 0);
7981a945772Spatrick mvpp2_prs_sram_ai_update(&pe, i, MVPP2_PRS_FLOW_ID_MASK);
7991a945772Spatrick mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_DONE_BIT, 1);
8001a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_FLOWS);
8011a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
8021a945772Spatrick }
8031a945772Spatrick }
8041a945772Spatrick
8051a945772Spatrick void
mvpp2_prs_mh_init(struct mvpp2_softc * sc)8061a945772Spatrick mvpp2_prs_mh_init(struct mvpp2_softc *sc)
8071a945772Spatrick {
8081a945772Spatrick struct mvpp2_prs_entry pe;
8091a945772Spatrick
8101a945772Spatrick memset(&pe, 0, sizeof(pe));
8111a945772Spatrick pe.index = MVPP2_PE_MH_DEFAULT;
8121a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MH);
8131a945772Spatrick mvpp2_prs_sram_shift_set(&pe, MVPP2_MH_SIZE,
8141a945772Spatrick MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
8151a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_MAC);
8161a945772Spatrick mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
8171a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_MH);
8181a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
8191a945772Spatrick }
8201a945772Spatrick
8211a945772Spatrick void
mvpp2_prs_mac_init(struct mvpp2_softc * sc)8221a945772Spatrick mvpp2_prs_mac_init(struct mvpp2_softc *sc)
8231a945772Spatrick {
8241a945772Spatrick struct mvpp2_prs_entry pe;
8251a945772Spatrick
8261a945772Spatrick memset(&pe, 0, sizeof(pe));
8271a945772Spatrick pe.index = MVPP2_PE_MAC_NON_PROMISCUOUS;
8281a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC);
8291a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_DROP_MASK,
8301a945772Spatrick MVPP2_PRS_RI_DROP_MASK);
8311a945772Spatrick mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
8321a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
8331a945772Spatrick mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
8341a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_MAC);
8351a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
8361a945772Spatrick mvpp2_prs_mac_drop_all_set(sc, 0, 0);
83741cd246cSpatrick mvpp2_prs_mac_promisc_set(sc, 0, MVPP2_PRS_L2_UNI_CAST, 0);
83841cd246cSpatrick mvpp2_prs_mac_promisc_set(sc, 0, MVPP2_PRS_L2_MULTI_CAST, 0);
8391a945772Spatrick }
8401a945772Spatrick
8411a945772Spatrick void
mvpp2_prs_dsa_init(struct mvpp2_softc * sc)8421a945772Spatrick mvpp2_prs_dsa_init(struct mvpp2_softc *sc)
8431a945772Spatrick {
8441a945772Spatrick struct mvpp2_prs_entry pe;
8451a945772Spatrick
8461a945772Spatrick mvpp2_prs_dsa_tag_set(sc, 0, 0, MVPP2_PRS_UNTAGGED, MVPP2_PRS_EDSA);
8471a945772Spatrick mvpp2_prs_dsa_tag_set(sc, 0, 0, MVPP2_PRS_TAGGED, MVPP2_PRS_EDSA);
8481a945772Spatrick mvpp2_prs_dsa_tag_set(sc, 0, 0, MVPP2_PRS_UNTAGGED, MVPP2_PRS_DSA);
8491a945772Spatrick mvpp2_prs_dsa_tag_set(sc, 0, 0, MVPP2_PRS_TAGGED, MVPP2_PRS_DSA);
8501a945772Spatrick mvpp2_prs_dsa_tag_ethertype_set(sc, 0, 0, MVPP2_PRS_UNTAGGED, MVPP2_PRS_EDSA);
8511a945772Spatrick mvpp2_prs_dsa_tag_ethertype_set(sc, 0, 0, MVPP2_PRS_TAGGED, MVPP2_PRS_EDSA);
8521a945772Spatrick mvpp2_prs_dsa_tag_ethertype_set(sc, 0, 1, MVPP2_PRS_UNTAGGED, MVPP2_PRS_DSA);
8531a945772Spatrick mvpp2_prs_dsa_tag_ethertype_set(sc, 0, 1, MVPP2_PRS_TAGGED, MVPP2_PRS_DSA);
8541a945772Spatrick memset(&pe, 0, sizeof(pe));
8551a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_DSA);
8561a945772Spatrick pe.index = MVPP2_PE_DSA_DEFAULT;
8571a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_VLAN);
8581a945772Spatrick mvpp2_prs_sram_shift_set(&pe, 0, MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
8591a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_MAC);
8601a945772Spatrick mvpp2_prs_sram_ai_update(&pe, 0, MVPP2_PRS_SRAM_AI_MASK);
8611a945772Spatrick mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
8621a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
8631a945772Spatrick }
8641a945772Spatrick
8651a945772Spatrick int
mvpp2_prs_etype_init(struct mvpp2_softc * sc)8661a945772Spatrick mvpp2_prs_etype_init(struct mvpp2_softc *sc)
8671a945772Spatrick {
8681a945772Spatrick struct mvpp2_prs_entry pe;
8691a945772Spatrick int tid;
8701a945772Spatrick
8711a945772Spatrick /* Ethertype: PPPoE */
8721a945772Spatrick tid = mvpp2_prs_tcam_first_free(sc, MVPP2_PE_FIRST_FREE_TID,
8731a945772Spatrick MVPP2_PE_LAST_FREE_TID);
8741a945772Spatrick if (tid < 0)
8751a945772Spatrick return tid;
8761a945772Spatrick memset(&pe, 0, sizeof(pe));
8771a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_L2);
8781a945772Spatrick pe.index = tid;
879e042150eSpatrick mvpp2_prs_match_etype(&pe, 0, ETHERTYPE_PPPOE);
8801a945772Spatrick mvpp2_prs_sram_shift_set(&pe, MVPP2_PPPOE_HDR_SIZE,
8811a945772Spatrick MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
8821a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_PPPOE);
8831a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_PPPOE_MASK,
8841a945772Spatrick MVPP2_PRS_RI_PPPOE_MASK);
8851a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_L2);
8861a945772Spatrick sc->sc_prs_shadow[pe.index].udf = MVPP2_PRS_UDF_L2_DEF;
8871a945772Spatrick sc->sc_prs_shadow[pe.index].finish = 0;
8881a945772Spatrick mvpp2_prs_shadow_ri_set(sc, pe.index, MVPP2_PRS_RI_PPPOE_MASK,
8891a945772Spatrick MVPP2_PRS_RI_PPPOE_MASK);
8901a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
8911a945772Spatrick
8921a945772Spatrick /* Ethertype: ARP */
8931a945772Spatrick tid = mvpp2_prs_tcam_first_free(sc, MVPP2_PE_FIRST_FREE_TID,
8941a945772Spatrick MVPP2_PE_LAST_FREE_TID);
8951a945772Spatrick if (tid < 0)
8961a945772Spatrick return tid;
8971a945772Spatrick memset(&pe, 0, sizeof(pe));
8981a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_L2);
8991a945772Spatrick pe.index = tid;
900e042150eSpatrick mvpp2_prs_match_etype(&pe, 0, ETHERTYPE_ARP);
9011a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
9021a945772Spatrick mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
9031a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_ARP,
9041a945772Spatrick MVPP2_PRS_RI_L3_PROTO_MASK);
9051a945772Spatrick mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
9061a945772Spatrick MVPP2_ETH_TYPE_LEN, MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
9071a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_L2);
9081a945772Spatrick sc->sc_prs_shadow[pe.index].udf = MVPP2_PRS_UDF_L2_DEF;
9091a945772Spatrick sc->sc_prs_shadow[pe.index].finish = 1;
9101a945772Spatrick mvpp2_prs_shadow_ri_set(sc, pe.index, MVPP2_PRS_RI_L3_ARP,
9111a945772Spatrick MVPP2_PRS_RI_L3_PROTO_MASK);
9121a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
9131a945772Spatrick
9141a945772Spatrick /* Ethertype: LBTD */
9151a945772Spatrick tid = mvpp2_prs_tcam_first_free(sc, MVPP2_PE_FIRST_FREE_TID,
9161a945772Spatrick MVPP2_PE_LAST_FREE_TID);
9171a945772Spatrick if (tid < 0)
9181a945772Spatrick return tid;
9191a945772Spatrick memset(&pe, 0, sizeof(pe));
9201a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_L2);
9211a945772Spatrick pe.index = tid;
9221a945772Spatrick mvpp2_prs_match_etype(&pe, 0, MVPP2_IP_LBDT_TYPE);
9231a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
9241a945772Spatrick mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
9251a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_CPU_CODE_RX_SPEC |
9261a945772Spatrick MVPP2_PRS_RI_UDF3_RX_SPECIAL, MVPP2_PRS_RI_CPU_CODE_MASK |
9271a945772Spatrick MVPP2_PRS_RI_UDF3_MASK);
9281a945772Spatrick mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
9291a945772Spatrick MVPP2_ETH_TYPE_LEN, MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
9301a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_L2);
9311a945772Spatrick sc->sc_prs_shadow[pe.index].udf = MVPP2_PRS_UDF_L2_DEF;
9321a945772Spatrick sc->sc_prs_shadow[pe.index].finish = 1;
9331a945772Spatrick mvpp2_prs_shadow_ri_set(sc, pe.index, MVPP2_PRS_RI_CPU_CODE_RX_SPEC |
9341a945772Spatrick MVPP2_PRS_RI_UDF3_RX_SPECIAL, MVPP2_PRS_RI_CPU_CODE_MASK |
9351a945772Spatrick MVPP2_PRS_RI_UDF3_MASK);
9361a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
9371a945772Spatrick
9381a945772Spatrick /* Ethertype: IPv4 without options */
9391a945772Spatrick tid = mvpp2_prs_tcam_first_free(sc, MVPP2_PE_FIRST_FREE_TID,
9401a945772Spatrick MVPP2_PE_LAST_FREE_TID);
9411a945772Spatrick if (tid < 0)
9421a945772Spatrick return tid;
9431a945772Spatrick memset(&pe, 0, sizeof(pe));
9441a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_L2);
9451a945772Spatrick pe.index = tid;
946e042150eSpatrick mvpp2_prs_match_etype(&pe, 0, ETHERTYPE_IP);
9471a945772Spatrick mvpp2_prs_tcam_data_byte_set(&pe, MVPP2_ETH_TYPE_LEN,
9481a945772Spatrick MVPP2_PRS_IPV4_HEAD | MVPP2_PRS_IPV4_IHL,
9491a945772Spatrick MVPP2_PRS_IPV4_HEAD_MASK | MVPP2_PRS_IPV4_IHL_MASK);
9501a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP4);
9511a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_IP4,
9521a945772Spatrick MVPP2_PRS_RI_L3_PROTO_MASK);
9531a945772Spatrick mvpp2_prs_sram_shift_set(&pe, MVPP2_ETH_TYPE_LEN + 4,
9541a945772Spatrick MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
9551a945772Spatrick mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
9561a945772Spatrick MVPP2_ETH_TYPE_LEN, MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
9571a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_L2);
9581a945772Spatrick sc->sc_prs_shadow[pe.index].udf = MVPP2_PRS_UDF_L2_DEF;
9591a945772Spatrick sc->sc_prs_shadow[pe.index].finish = 0;
9601a945772Spatrick mvpp2_prs_shadow_ri_set(sc, pe.index, MVPP2_PRS_RI_L3_IP4,
9611a945772Spatrick MVPP2_PRS_RI_L3_PROTO_MASK);
9621a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
9631a945772Spatrick
9641a945772Spatrick /* Ethertype: IPv4 with options */
9651a945772Spatrick tid = mvpp2_prs_tcam_first_free(sc, MVPP2_PE_FIRST_FREE_TID,
9661a945772Spatrick MVPP2_PE_LAST_FREE_TID);
9671a945772Spatrick if (tid < 0)
9681a945772Spatrick return tid;
9691a945772Spatrick pe.index = tid;
9701a945772Spatrick
9711a945772Spatrick pe.tcam.byte[MVPP2_PRS_TCAM_DATA_BYTE(MVPP2_ETH_TYPE_LEN)] = 0x0;
9721a945772Spatrick pe.tcam.byte[MVPP2_PRS_TCAM_DATA_BYTE_EN(MVPP2_ETH_TYPE_LEN)] = 0x0;
9731a945772Spatrick mvpp2_prs_tcam_data_byte_set(&pe, MVPP2_ETH_TYPE_LEN,
9741a945772Spatrick MVPP2_PRS_IPV4_HEAD, MVPP2_PRS_IPV4_HEAD_MASK);
9751a945772Spatrick pe.sram.word[MVPP2_PRS_SRAM_RI_WORD] = 0x0;
9761a945772Spatrick pe.sram.word[MVPP2_PRS_SRAM_RI_CTRL_WORD] = 0x0;
9771a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_IP4_OPT,
9781a945772Spatrick MVPP2_PRS_RI_L3_PROTO_MASK);
9791a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_L2);
9801a945772Spatrick sc->sc_prs_shadow[pe.index].udf = MVPP2_PRS_UDF_L2_DEF;
9811a945772Spatrick sc->sc_prs_shadow[pe.index].finish = 0;
9821a945772Spatrick mvpp2_prs_shadow_ri_set(sc, pe.index, MVPP2_PRS_RI_L3_IP4_OPT,
9831a945772Spatrick MVPP2_PRS_RI_L3_PROTO_MASK);
9841a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
9851a945772Spatrick
9861a945772Spatrick /* Ethertype: IPv6 without options */
9871a945772Spatrick tid = mvpp2_prs_tcam_first_free(sc, MVPP2_PE_FIRST_FREE_TID,
9881a945772Spatrick MVPP2_PE_LAST_FREE_TID);
9891a945772Spatrick if (tid < 0)
9901a945772Spatrick return tid;
9911a945772Spatrick memset(&pe, 0, sizeof(pe));
9921a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_L2);
9931a945772Spatrick pe.index = tid;
994e042150eSpatrick mvpp2_prs_match_etype(&pe, 0, ETHERTYPE_IPV6);
9951a945772Spatrick mvpp2_prs_sram_shift_set(&pe, MVPP2_ETH_TYPE_LEN + 8 +
9961a945772Spatrick MVPP2_MAX_L3_ADDR_SIZE, MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
9971a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP6);
9981a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_IP6,
9991a945772Spatrick MVPP2_PRS_RI_L3_PROTO_MASK);
10001a945772Spatrick mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
10011a945772Spatrick MVPP2_ETH_TYPE_LEN, MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
10021a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_L2);
10031a945772Spatrick sc->sc_prs_shadow[pe.index].udf = MVPP2_PRS_UDF_L2_DEF;
10041a945772Spatrick sc->sc_prs_shadow[pe.index].finish = 0;
10051a945772Spatrick mvpp2_prs_shadow_ri_set(sc, pe.index, MVPP2_PRS_RI_L3_IP6,
10061a945772Spatrick MVPP2_PRS_RI_L3_PROTO_MASK);
10071a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
10081a945772Spatrick
10091a945772Spatrick /* Default entry for MVPP2_PRS_LU_L2 - Unknown ethtype */
1010ce2a9341Spatrick memset(&pe, 0, sizeof(pe));
10111a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_L2);
10121a945772Spatrick pe.index = MVPP2_PE_ETH_TYPE_UN;
10131a945772Spatrick mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
10141a945772Spatrick mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
10151a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
10161a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_UN,
10171a945772Spatrick MVPP2_PRS_RI_L3_PROTO_MASK);
10181a945772Spatrick mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
10191a945772Spatrick MVPP2_ETH_TYPE_LEN, MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
10201a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_L2);
10211a945772Spatrick sc->sc_prs_shadow[pe.index].udf = MVPP2_PRS_UDF_L2_DEF;
10221a945772Spatrick sc->sc_prs_shadow[pe.index].finish = 1;
10231a945772Spatrick mvpp2_prs_shadow_ri_set(sc, pe.index, MVPP2_PRS_RI_L3_UN,
10241a945772Spatrick MVPP2_PRS_RI_L3_PROTO_MASK);
10251a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
10261a945772Spatrick
10271a945772Spatrick return 0;
10281a945772Spatrick }
10291a945772Spatrick
10301a945772Spatrick int
mvpp2_prs_vlan_init(struct mvpp2_softc * sc)10311a945772Spatrick mvpp2_prs_vlan_init(struct mvpp2_softc *sc)
10321a945772Spatrick {
10331a945772Spatrick struct mvpp2_prs_entry pe;
10341a945772Spatrick int ret;
10351a945772Spatrick
10361a945772Spatrick sc->sc_prs_double_vlans = mallocarray(MVPP2_PRS_DBL_VLANS_MAX,
10371a945772Spatrick sizeof(*sc->sc_prs_double_vlans), M_DEVBUF, M_WAITOK | M_ZERO);
10381a945772Spatrick
1039e042150eSpatrick ret = mvpp2_prs_double_vlan_add(sc, ETHERTYPE_VLAN, ETHERTYPE_QINQ,
10401a945772Spatrick MVPP2_PRS_PORT_MASK);
10411a945772Spatrick if (ret)
10421a945772Spatrick return ret;
1043e042150eSpatrick ret = mvpp2_prs_double_vlan_add(sc, ETHERTYPE_VLAN, ETHERTYPE_VLAN,
10441a945772Spatrick MVPP2_PRS_PORT_MASK);
10451a945772Spatrick if (ret)
10461a945772Spatrick return ret;
1047e042150eSpatrick ret = mvpp2_prs_vlan_add(sc, ETHERTYPE_QINQ, MVPP2_PRS_SINGLE_VLAN_AI,
10481a945772Spatrick MVPP2_PRS_PORT_MASK);
10491a945772Spatrick if (ret)
10501a945772Spatrick return ret;
1051e042150eSpatrick ret = mvpp2_prs_vlan_add(sc, ETHERTYPE_VLAN, MVPP2_PRS_SINGLE_VLAN_AI,
10521a945772Spatrick MVPP2_PRS_PORT_MASK);
10531a945772Spatrick if (ret)
10541a945772Spatrick return ret;
10551a945772Spatrick
1056ce2a9341Spatrick memset(&pe, 0, sizeof(pe));
10571a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_VLAN);
10581a945772Spatrick pe.index = MVPP2_PE_VLAN_DBL;
10591a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_L2);
10601a945772Spatrick mvpp2_prs_sram_ai_update(&pe, 0, MVPP2_PRS_SRAM_AI_MASK);
10611a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_VLAN_DOUBLE,
10621a945772Spatrick MVPP2_PRS_RI_VLAN_MASK);
10631a945772Spatrick mvpp2_prs_tcam_ai_update(&pe, MVPP2_PRS_DBL_VLAN_AI_BIT,
10641a945772Spatrick MVPP2_PRS_DBL_VLAN_AI_BIT);
10651a945772Spatrick mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
10661a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_VLAN);
10671a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
10681a945772Spatrick
1069ce2a9341Spatrick memset(&pe, 0, sizeof(pe));
10701a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_VLAN);
10711a945772Spatrick pe.index = MVPP2_PE_VLAN_NONE;
10721a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_L2);
1073e7c76d8bSpatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_VLAN_NONE,
1074e7c76d8bSpatrick MVPP2_PRS_RI_VLAN_MASK);
10751a945772Spatrick mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
10761a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_VLAN);
10771a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
10781a945772Spatrick
10791a945772Spatrick return 0;
10801a945772Spatrick }
10811a945772Spatrick
10821a945772Spatrick int
mvpp2_prs_pppoe_init(struct mvpp2_softc * sc)10831a945772Spatrick mvpp2_prs_pppoe_init(struct mvpp2_softc *sc)
10841a945772Spatrick {
10851a945772Spatrick struct mvpp2_prs_entry pe;
10861a945772Spatrick int tid;
10871a945772Spatrick
10881a945772Spatrick tid = mvpp2_prs_tcam_first_free(sc, MVPP2_PE_FIRST_FREE_TID,
10891a945772Spatrick MVPP2_PE_LAST_FREE_TID);
10901a945772Spatrick if (tid < 0)
10911a945772Spatrick return tid;
10921a945772Spatrick
1093ce2a9341Spatrick memset(&pe, 0, sizeof(pe));
10941a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_PPPOE);
10951a945772Spatrick pe.index = tid;
1096e042150eSpatrick mvpp2_prs_match_etype(&pe, 0, PPP_IP);
10971a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP4);
10981a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_IP4_OPT,
10991a945772Spatrick MVPP2_PRS_RI_L3_PROTO_MASK);
11001a945772Spatrick mvpp2_prs_sram_shift_set(&pe, MVPP2_ETH_TYPE_LEN + 4,
11011a945772Spatrick MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
11021a945772Spatrick mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
11031a945772Spatrick MVPP2_ETH_TYPE_LEN, MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
11041a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_PPPOE);
11051a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
11061a945772Spatrick
11071a945772Spatrick tid = mvpp2_prs_tcam_first_free(sc, MVPP2_PE_FIRST_FREE_TID,
11081a945772Spatrick MVPP2_PE_LAST_FREE_TID);
11091a945772Spatrick if (tid < 0)
11101a945772Spatrick return tid;
11111a945772Spatrick
11121a945772Spatrick pe.index = tid;
11131a945772Spatrick mvpp2_prs_tcam_data_byte_set(&pe, MVPP2_ETH_TYPE_LEN,
11141a945772Spatrick MVPP2_PRS_IPV4_HEAD | MVPP2_PRS_IPV4_IHL,
11151a945772Spatrick MVPP2_PRS_IPV4_HEAD_MASK | MVPP2_PRS_IPV4_IHL_MASK);
11161a945772Spatrick pe.sram.word[MVPP2_PRS_SRAM_RI_WORD] = 0x0;
11171a945772Spatrick pe.sram.word[MVPP2_PRS_SRAM_RI_CTRL_WORD] = 0x0;
11181a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_IP4, MVPP2_PRS_RI_L3_PROTO_MASK);
11191a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_PPPOE);
11201a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
11211a945772Spatrick
11221a945772Spatrick tid = mvpp2_prs_tcam_first_free(sc, MVPP2_PE_FIRST_FREE_TID,
11231a945772Spatrick MVPP2_PE_LAST_FREE_TID);
11241a945772Spatrick if (tid < 0)
11251a945772Spatrick return tid;
11261a945772Spatrick
1127ce2a9341Spatrick memset(&pe, 0, sizeof(pe));
11281a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_PPPOE);
11291a945772Spatrick pe.index = tid;
1130e042150eSpatrick mvpp2_prs_match_etype(&pe, 0, PPP_IPV6);
11311a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP6);
11321a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_IP6,
11331a945772Spatrick MVPP2_PRS_RI_L3_PROTO_MASK);
11341a945772Spatrick mvpp2_prs_sram_shift_set(&pe, MVPP2_ETH_TYPE_LEN + 4,
11351a945772Spatrick MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
11361a945772Spatrick mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
11371a945772Spatrick MVPP2_ETH_TYPE_LEN, MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
11381a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_PPPOE);
11391a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
11401a945772Spatrick
11411a945772Spatrick tid = mvpp2_prs_tcam_first_free(sc, MVPP2_PE_FIRST_FREE_TID,
11421a945772Spatrick MVPP2_PE_LAST_FREE_TID);
11431a945772Spatrick if (tid < 0)
11441a945772Spatrick return tid;
11451a945772Spatrick
1146ce2a9341Spatrick memset(&pe, 0, sizeof(pe));
11471a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_PPPOE);
11481a945772Spatrick pe.index = tid;
11491a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_UN,
11501a945772Spatrick MVPP2_PRS_RI_L3_PROTO_MASK);
11511a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
11521a945772Spatrick mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
11531a945772Spatrick mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
11541a945772Spatrick MVPP2_ETH_TYPE_LEN, MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
11551a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_PPPOE);
11561a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
11571a945772Spatrick
11581a945772Spatrick return 0;
11591a945772Spatrick }
11601a945772Spatrick
11611a945772Spatrick int
mvpp2_prs_ip6_init(struct mvpp2_softc * sc)11621a945772Spatrick mvpp2_prs_ip6_init(struct mvpp2_softc *sc)
11631a945772Spatrick {
11641a945772Spatrick struct mvpp2_prs_entry pe;
11651a945772Spatrick int tid, ret;
11661a945772Spatrick
1167e042150eSpatrick ret = mvpp2_prs_ip6_proto(sc, IPPROTO_TCP, MVPP2_PRS_RI_L4_TCP,
11681a945772Spatrick MVPP2_PRS_RI_L4_PROTO_MASK);
11691a945772Spatrick if (ret)
11701a945772Spatrick return ret;
1171e042150eSpatrick ret = mvpp2_prs_ip6_proto(sc, IPPROTO_UDP, MVPP2_PRS_RI_L4_UDP,
11721a945772Spatrick MVPP2_PRS_RI_L4_PROTO_MASK);
11731a945772Spatrick if (ret)
11741a945772Spatrick return ret;
1175e042150eSpatrick ret = mvpp2_prs_ip6_proto(sc, IPPROTO_ICMPV6,
11761a945772Spatrick MVPP2_PRS_RI_CPU_CODE_RX_SPEC | MVPP2_PRS_RI_UDF3_RX_SPECIAL,
11771a945772Spatrick MVPP2_PRS_RI_CPU_CODE_MASK | MVPP2_PRS_RI_UDF3_MASK);
11781a945772Spatrick if (ret)
11791a945772Spatrick return ret;
1180e042150eSpatrick ret = mvpp2_prs_ip6_proto(sc, IPPROTO_IPIP, MVPP2_PRS_RI_UDF7_IP6_LITE,
11811a945772Spatrick MVPP2_PRS_RI_UDF7_MASK);
11821a945772Spatrick if (ret)
11831a945772Spatrick return ret;
11841a945772Spatrick ret = mvpp2_prs_ip6_cast(sc, MVPP2_PRS_L3_MULTI_CAST);
11851a945772Spatrick if (ret)
11861a945772Spatrick return ret;
11871a945772Spatrick
11881a945772Spatrick tid = mvpp2_prs_tcam_first_free(sc, MVPP2_PE_FIRST_FREE_TID,
11891a945772Spatrick MVPP2_PE_LAST_FREE_TID);
11901a945772Spatrick if (tid < 0)
11911a945772Spatrick return tid;
11921a945772Spatrick
1193ce2a9341Spatrick memset(&pe, 0, sizeof(pe));
11941a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP6);
11951a945772Spatrick pe.index = tid;
11961a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
11971a945772Spatrick mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
11981a945772Spatrick mvpp2_prs_sram_ri_update(&pe,
11991a945772Spatrick MVPP2_PRS_RI_L3_UN | MVPP2_PRS_RI_DROP_MASK,
12001a945772Spatrick MVPP2_PRS_RI_L3_PROTO_MASK | MVPP2_PRS_RI_DROP_MASK);
12011a945772Spatrick mvpp2_prs_tcam_data_byte_set(&pe, 1, 0x00, MVPP2_PRS_IPV6_HOP_MASK);
12021a945772Spatrick mvpp2_prs_tcam_ai_update(&pe, MVPP2_PRS_IPV6_NO_EXT_AI_BIT,
12031a945772Spatrick MVPP2_PRS_IPV6_NO_EXT_AI_BIT);
12041a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_IP4);
12051a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
12061a945772Spatrick
1207ce2a9341Spatrick memset(&pe, 0, sizeof(pe));
12081a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP6);
12091a945772Spatrick pe.index = MVPP2_PE_IP6_PROTO_UN;
12101a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
12111a945772Spatrick mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
12121a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L4_OTHER,
12131a945772Spatrick MVPP2_PRS_RI_L4_PROTO_MASK);
12141a945772Spatrick mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L4,
12151a945772Spatrick sizeof(struct ip6_hdr) - 6, MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
12161a945772Spatrick mvpp2_prs_tcam_ai_update(&pe, MVPP2_PRS_IPV6_NO_EXT_AI_BIT,
12171a945772Spatrick MVPP2_PRS_IPV6_NO_EXT_AI_BIT);
12181a945772Spatrick mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
12191a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_IP4);
12201a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
12211a945772Spatrick
1222ce2a9341Spatrick memset(&pe, 0, sizeof(pe));
12231a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP6);
12241a945772Spatrick pe.index = MVPP2_PE_IP6_EXT_PROTO_UN;
12251a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
12261a945772Spatrick mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
12271a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L4_OTHER,
12281a945772Spatrick MVPP2_PRS_RI_L4_PROTO_MASK);
12291a945772Spatrick mvpp2_prs_tcam_ai_update(&pe, MVPP2_PRS_IPV6_EXT_AI_BIT,
12301a945772Spatrick MVPP2_PRS_IPV6_EXT_AI_BIT);
12311a945772Spatrick mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
12321a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_IP4);
12331a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
12341a945772Spatrick
1235ce2a9341Spatrick memset(&pe, 0, sizeof(pe));
12361a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP6);
12371a945772Spatrick pe.index = MVPP2_PE_IP6_ADDR_UN;
12381a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP6);
12391a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_UCAST,
12401a945772Spatrick MVPP2_PRS_RI_L3_ADDR_MASK);
12411a945772Spatrick mvpp2_prs_sram_ai_update(&pe, MVPP2_PRS_IPV6_NO_EXT_AI_BIT,
12421a945772Spatrick MVPP2_PRS_IPV6_NO_EXT_AI_BIT);
12431a945772Spatrick mvpp2_prs_sram_shift_set(&pe, -18, MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
12441a945772Spatrick mvpp2_prs_tcam_ai_update(&pe, 0, MVPP2_PRS_IPV6_NO_EXT_AI_BIT);
12451a945772Spatrick mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
12461a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_IP6);
12471a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
12481a945772Spatrick
12491a945772Spatrick return 0;
12501a945772Spatrick }
12511a945772Spatrick
12521a945772Spatrick int
mvpp2_prs_ip4_init(struct mvpp2_softc * sc)12531a945772Spatrick mvpp2_prs_ip4_init(struct mvpp2_softc *sc)
12541a945772Spatrick {
12551a945772Spatrick struct mvpp2_prs_entry pe;
12561a945772Spatrick int ret;
12571a945772Spatrick
1258e042150eSpatrick ret = mvpp2_prs_ip4_proto(sc, IPPROTO_TCP, MVPP2_PRS_RI_L4_TCP,
12591a945772Spatrick MVPP2_PRS_RI_L4_PROTO_MASK);
12601a945772Spatrick if (ret)
12611a945772Spatrick return ret;
1262e042150eSpatrick ret = mvpp2_prs_ip4_proto(sc, IPPROTO_UDP, MVPP2_PRS_RI_L4_UDP,
12631a945772Spatrick MVPP2_PRS_RI_L4_PROTO_MASK);
12641a945772Spatrick if (ret)
12651a945772Spatrick return ret;
1266e042150eSpatrick ret = mvpp2_prs_ip4_proto(sc, IPPROTO_IGMP,
12671a945772Spatrick MVPP2_PRS_RI_CPU_CODE_RX_SPEC | MVPP2_PRS_RI_UDF3_RX_SPECIAL,
12681a945772Spatrick MVPP2_PRS_RI_CPU_CODE_MASK | MVPP2_PRS_RI_UDF3_MASK);
12691a945772Spatrick if (ret)
12701a945772Spatrick return ret;
12711a945772Spatrick ret = mvpp2_prs_ip4_cast(sc, MVPP2_PRS_L3_BROAD_CAST);
12721a945772Spatrick if (ret)
12731a945772Spatrick return ret;
12741a945772Spatrick ret = mvpp2_prs_ip4_cast(sc, MVPP2_PRS_L3_MULTI_CAST);
12751a945772Spatrick if (ret)
12761a945772Spatrick return ret;
12771a945772Spatrick
1278ce2a9341Spatrick memset(&pe, 0, sizeof(pe));
12791a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP4);
12801a945772Spatrick pe.index = MVPP2_PE_IP4_PROTO_UN;
12811a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP4);
12821a945772Spatrick mvpp2_prs_sram_shift_set(&pe, 12, MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
12831a945772Spatrick mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L4,
12841a945772Spatrick sizeof(struct ip) - 4, MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
12851a945772Spatrick mvpp2_prs_sram_ai_update(&pe, MVPP2_PRS_IPV4_DIP_AI_BIT,
12861a945772Spatrick MVPP2_PRS_IPV4_DIP_AI_BIT);
12871a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L4_OTHER,
12881a945772Spatrick MVPP2_PRS_RI_L4_PROTO_MASK);
12891a945772Spatrick mvpp2_prs_tcam_ai_update(&pe, 0, MVPP2_PRS_IPV4_DIP_AI_BIT);
12901a945772Spatrick mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
12911a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_IP4);
12921a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
12931a945772Spatrick
1294ce2a9341Spatrick memset(&pe, 0, sizeof(pe));
12951a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP4);
12961a945772Spatrick pe.index = MVPP2_PE_IP4_ADDR_UN;
12971a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
12981a945772Spatrick mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
12991a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_UCAST,
13001a945772Spatrick MVPP2_PRS_RI_L3_ADDR_MASK);
13011a945772Spatrick mvpp2_prs_tcam_ai_update(&pe, MVPP2_PRS_IPV4_DIP_AI_BIT,
13021a945772Spatrick MVPP2_PRS_IPV4_DIP_AI_BIT);
13031a945772Spatrick mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
13041a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_IP4);
13051a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
13061a945772Spatrick
13071a945772Spatrick return 0;
13081a945772Spatrick }
13091a945772Spatrick
13101a945772Spatrick int
mvpp2_port_match(struct device * parent,void * cfdata,void * aux)13111a945772Spatrick mvpp2_port_match(struct device *parent, void *cfdata, void *aux)
13121a945772Spatrick {
13131a945772Spatrick struct mvpp2_attach_args *maa = aux;
13141a945772Spatrick char buf[32];
13151a945772Spatrick
13161a945772Spatrick if (OF_getprop(maa->ma_node, "status", buf, sizeof(buf)) > 0 &&
13171a945772Spatrick strcmp(buf, "disabled") == 0)
13181a945772Spatrick return 0;
13191a945772Spatrick
13201a945772Spatrick return 1;
13211a945772Spatrick }
13221a945772Spatrick
13231a945772Spatrick void
mvpp2_port_attach(struct device * parent,struct device * self,void * aux)13241a945772Spatrick mvpp2_port_attach(struct device *parent, struct device *self, void *aux)
13251a945772Spatrick {
13261a945772Spatrick struct mvpp2_port *sc = (void *)self;
13271a945772Spatrick struct mvpp2_attach_args *maa = aux;
13281a945772Spatrick struct mvpp2_tx_queue *txq;
13291a945772Spatrick struct mvpp2_rx_queue *rxq;
13301a945772Spatrick struct ifnet *ifp;
13311a945772Spatrick uint32_t phy, reg;
13321a945772Spatrick int i, idx, len, node;
1333755c7aeaSpatrick int mii_flags = 0;
13341a945772Spatrick char *phy_mode;
13351a945772Spatrick char *managed;
13361a945772Spatrick
13371a945772Spatrick sc->sc = (void *)parent;
13381a945772Spatrick sc->sc_node = maa->ma_node;
13391a945772Spatrick sc->sc_dmat = maa->ma_dmat;
13401a945772Spatrick
13411a945772Spatrick sc->sc_id = OF_getpropint(sc->sc_node, "port-id", 0);
13421a945772Spatrick sc->sc_gop_id = OF_getpropint(sc->sc_node, "gop-port-id", 0);
13431a945772Spatrick sc->sc_sfp = OF_getpropint(sc->sc_node, "sfp", 0);
13441a945772Spatrick
13451a945772Spatrick len = OF_getproplen(sc->sc_node, "phy-mode");
13461a945772Spatrick if (len <= 0) {
13471a945772Spatrick printf("%s: cannot extract phy-mode\n", self->dv_xname);
13481a945772Spatrick return;
13491a945772Spatrick }
13501a945772Spatrick
13511a945772Spatrick phy_mode = malloc(len, M_TEMP, M_WAITOK);
13521a945772Spatrick OF_getprop(sc->sc_node, "phy-mode", phy_mode, len);
13537d13f3eaSkettenis if (!strncmp(phy_mode, "10gbase-r", strlen("10gbase-r")))
13547d13f3eaSkettenis sc->sc_phy_mode = PHY_MODE_10GBASER;
13557d13f3eaSkettenis else if (!strncmp(phy_mode, "10gbase-kr", strlen("10gbase-kr")))
13561a945772Spatrick sc->sc_phy_mode = PHY_MODE_10GBASER;
13571a945772Spatrick else if (!strncmp(phy_mode, "2500base-x", strlen("2500base-x")))
13581a945772Spatrick sc->sc_phy_mode = PHY_MODE_2500BASEX;
13591a945772Spatrick else if (!strncmp(phy_mode, "1000base-x", strlen("1000base-x")))
13601a945772Spatrick sc->sc_phy_mode = PHY_MODE_1000BASEX;
13611a945772Spatrick else if (!strncmp(phy_mode, "sgmii", strlen("sgmii")))
13621a945772Spatrick sc->sc_phy_mode = PHY_MODE_SGMII;
13631a945772Spatrick else if (!strncmp(phy_mode, "rgmii-rxid", strlen("rgmii-rxid")))
13641a945772Spatrick sc->sc_phy_mode = PHY_MODE_RGMII_RXID;
13651a945772Spatrick else if (!strncmp(phy_mode, "rgmii-txid", strlen("rgmii-txid")))
13661a945772Spatrick sc->sc_phy_mode = PHY_MODE_RGMII_TXID;
13671a945772Spatrick else if (!strncmp(phy_mode, "rgmii-id", strlen("rgmii-id")))
13681a945772Spatrick sc->sc_phy_mode = PHY_MODE_RGMII_ID;
13691a945772Spatrick else if (!strncmp(phy_mode, "rgmii", strlen("rgmii")))
13701a945772Spatrick sc->sc_phy_mode = PHY_MODE_RGMII;
13711a945772Spatrick else {
13721a945772Spatrick printf("%s: cannot use phy-mode %s\n", self->dv_xname,
13731a945772Spatrick phy_mode);
13741a945772Spatrick return;
13751a945772Spatrick }
13761a945772Spatrick free(phy_mode, M_TEMP, len);
13771a945772Spatrick
13781a945772Spatrick /* Lookup PHY. */
13791a945772Spatrick phy = OF_getpropint(sc->sc_node, "phy", 0);
13801a945772Spatrick if (phy) {
13811a945772Spatrick node = OF_getnodebyphandle(phy);
13821a945772Spatrick if (!node) {
13831a945772Spatrick printf(": no phy\n");
13841a945772Spatrick return;
13851a945772Spatrick }
13861a945772Spatrick sc->sc_mdio = mii_byphandle(phy);
13871a945772Spatrick sc->sc_phyloc = OF_getpropint(node, "reg", MII_PHY_ANY);
13881a945772Spatrick sc->sc_sfp = OF_getpropint(node, "sfp", sc->sc_sfp);
1389a69db676Spatrick sc->sc_mii.mii_node = node;
13901a945772Spatrick }
13911a945772Spatrick
1392a02f2d56Skettenis if (sc->sc_sfp)
1393a02f2d56Skettenis config_mountroot(self, mvpp2_port_attach_sfp);
1394a02f2d56Skettenis
13951a945772Spatrick if ((len = OF_getproplen(sc->sc_node, "managed")) >= 0) {
13961a945772Spatrick managed = malloc(len, M_TEMP, M_WAITOK);
13971a945772Spatrick OF_getprop(sc->sc_node, "managed", managed, len);
13981a945772Spatrick if (!strncmp(managed, "in-band-status",
13991a945772Spatrick strlen("in-band-status")))
14001a945772Spatrick sc->sc_inband_status = 1;
14011a945772Spatrick free(managed, M_TEMP, len);
14021a945772Spatrick }
14031a945772Spatrick
14041a945772Spatrick if (OF_getprop(sc->sc_node, "local-mac-address",
14051a945772Spatrick &sc->sc_lladdr, ETHER_ADDR_LEN) != ETHER_ADDR_LEN)
14061a945772Spatrick memset(sc->sc_lladdr, 0xff, sizeof(sc->sc_lladdr));
14071a945772Spatrick printf(": address %s\n", ether_sprintf(sc->sc_lladdr));
14081a945772Spatrick
14091a945772Spatrick sc->sc_ntxq = sc->sc_nrxq = 1;
14101a945772Spatrick sc->sc_txqs = mallocarray(sc->sc_ntxq, sizeof(*sc->sc_txqs),
14111a945772Spatrick M_DEVBUF, M_WAITOK | M_ZERO);
14121a945772Spatrick sc->sc_rxqs = mallocarray(sc->sc_nrxq, sizeof(*sc->sc_rxqs),
14131a945772Spatrick M_DEVBUF, M_WAITOK | M_ZERO);
14141a945772Spatrick
14151a945772Spatrick for (i = 0; i < sc->sc_ntxq; i++) {
14161a945772Spatrick txq = &sc->sc_txqs[i];
14171a945772Spatrick txq->id = mvpp2_txq_phys(sc->sc_id, i);
14181a945772Spatrick txq->log_id = i;
14191a945772Spatrick txq->done_pkts_coal = MVPP2_TXDONE_COAL_PKTS_THRESH;
14201a945772Spatrick }
14211a945772Spatrick
14221a945772Spatrick sc->sc_tx_time_coal = MVPP2_TXDONE_COAL_USEC;
14231a945772Spatrick
14241a945772Spatrick for (i = 0; i < sc->sc_nrxq; i++) {
14251a945772Spatrick rxq = &sc->sc_rxqs[i];
14261a945772Spatrick rxq->id = sc->sc_id * 32 + i;
14271a945772Spatrick rxq->pkts_coal = MVPP2_RX_COAL_PKTS;
14281a945772Spatrick rxq->time_coal = MVPP2_RX_COAL_USEC;
14291a945772Spatrick }
14301a945772Spatrick
14311a945772Spatrick mvpp2_egress_disable(sc);
14321a945772Spatrick mvpp2_port_disable(sc);
14331a945772Spatrick
14341a945772Spatrick mvpp2_write(sc->sc, MVPP2_ISR_RXQ_GROUP_INDEX_REG,
14351a945772Spatrick sc->sc_id << MVPP2_ISR_RXQ_GROUP_INDEX_GROUP_SHIFT |
14361a945772Spatrick 0 /* queue vector id */);
14371a945772Spatrick mvpp2_write(sc->sc, MVPP2_ISR_RXQ_SUB_GROUP_CONFIG_REG,
14381a945772Spatrick sc->sc_nrxq << MVPP2_ISR_RXQ_SUB_GROUP_CONFIG_SIZE_SHIFT |
14391a945772Spatrick 0 /* first rxq */);
14401a945772Spatrick
14411a945772Spatrick mvpp2_ingress_disable(sc);
14421a945772Spatrick mvpp2_defaults_set(sc);
14431a945772Spatrick
14441a945772Spatrick mvpp2_cls_oversize_rxq_set(sc);
14451a945772Spatrick mvpp2_cls_port_config(sc);
14461a945772Spatrick
1447be107da9Spatrick /*
1448be107da9Spatrick * We have one pool per core, so all RX queues on a specific
1449be107da9Spatrick * core share that pool. Also long and short uses the same
1450be107da9Spatrick * pool.
1451be107da9Spatrick */
14521a945772Spatrick for (i = 0; i < sc->sc_nrxq; i++) {
1453be107da9Spatrick mvpp2_rxq_long_pool_set(sc, i, i);
1454be107da9Spatrick mvpp2_rxq_short_pool_set(sc, i, i);
14551a945772Spatrick }
14561a945772Spatrick
1457c56f4c70Spatrick mvpp2_mac_reset_assert(sc);
1458c56f4c70Spatrick mvpp2_pcs_reset_assert(sc);
14591a945772Spatrick
14601a945772Spatrick timeout_set(&sc->sc_tick, mvpp2_tick, sc);
14611a945772Spatrick
14621a945772Spatrick ifp = &sc->sc_ac.ac_if;
14631a945772Spatrick ifp->if_softc = sc;
14641a945772Spatrick ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
14651a945772Spatrick ifp->if_ioctl = mvpp2_ioctl;
14661a945772Spatrick ifp->if_start = mvpp2_start;
14671a945772Spatrick ifp->if_watchdog = mvpp2_watchdog;
1468cf96265bSbluhm ifq_init_maxlen(&ifp->if_snd, MVPP2_NTXDESC - 1);
14691a945772Spatrick bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
14701a945772Spatrick
14711a945772Spatrick ifp->if_capabilities = IFCAP_VLAN_MTU;
14721a945772Spatrick
14731a945772Spatrick sc->sc_mii.mii_ifp = ifp;
14741a945772Spatrick sc->sc_mii.mii_readreg = mvpp2_mii_readreg;
14751a945772Spatrick sc->sc_mii.mii_writereg = mvpp2_mii_writereg;
14761a945772Spatrick sc->sc_mii.mii_statchg = mvpp2_mii_statchg;
14771a945772Spatrick
14781a945772Spatrick ifmedia_init(&sc->sc_media, 0, mvpp2_media_change, mvpp2_media_status);
14791a945772Spatrick
14801a945772Spatrick if (sc->sc_mdio) {
1481755c7aeaSpatrick switch (sc->sc_phy_mode) {
1482755c7aeaSpatrick case PHY_MODE_1000BASEX:
1483755c7aeaSpatrick mii_flags |= MIIF_IS_1000X;
1484755c7aeaSpatrick break;
1485755c7aeaSpatrick case PHY_MODE_SGMII:
1486755c7aeaSpatrick mii_flags |= MIIF_SGMII;
1487755c7aeaSpatrick break;
1488755c7aeaSpatrick case PHY_MODE_RGMII_ID:
1489755c7aeaSpatrick mii_flags |= MIIF_RXID | MIIF_TXID;
1490755c7aeaSpatrick break;
1491755c7aeaSpatrick case PHY_MODE_RGMII_RXID:
1492755c7aeaSpatrick mii_flags |= MIIF_RXID;
1493755c7aeaSpatrick break;
1494755c7aeaSpatrick case PHY_MODE_RGMII_TXID:
1495755c7aeaSpatrick mii_flags |= MIIF_TXID;
1496755c7aeaSpatrick break;
1497755c7aeaSpatrick default:
1498755c7aeaSpatrick break;
1499755c7aeaSpatrick }
15001a945772Spatrick mii_attach(self, &sc->sc_mii, 0xffffffff, sc->sc_phyloc,
1501755c7aeaSpatrick (sc->sc_phyloc == MII_PHY_ANY) ? 0 : MII_OFFSET_ANY,
1502755c7aeaSpatrick mii_flags);
15031a945772Spatrick if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
15041a945772Spatrick printf("%s: no PHY found!\n", self->dv_xname);
15051a945772Spatrick ifmedia_add(&sc->sc_mii.mii_media,
15061a945772Spatrick IFM_ETHER|IFM_MANUAL, 0, NULL);
15071a945772Spatrick ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_MANUAL);
15081a945772Spatrick } else
15091a945772Spatrick ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
15101a945772Spatrick } else {
15111a945772Spatrick ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO, 0, NULL);
15121a945772Spatrick ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
15131a945772Spatrick
15141a945772Spatrick if (sc->sc_inband_status) {
15159b4ffe48Skettenis switch (sc->sc_phy_mode) {
15169b4ffe48Skettenis case PHY_MODE_1000BASEX:
15179b4ffe48Skettenis sc->sc_mii.mii_media_active =
15189b4ffe48Skettenis IFM_ETHER|IFM_1000_KX|IFM_FDX;
15199b4ffe48Skettenis break;
15209b4ffe48Skettenis case PHY_MODE_2500BASEX:
15219b4ffe48Skettenis sc->sc_mii.mii_media_active =
15229b4ffe48Skettenis IFM_ETHER|IFM_2500_KX|IFM_FDX;
15239b4ffe48Skettenis break;
15249b4ffe48Skettenis case PHY_MODE_10GBASER:
15259b4ffe48Skettenis sc->sc_mii.mii_media_active =
15269b4ffe48Skettenis IFM_ETHER|IFM_10G_KR|IFM_FDX;
15279b4ffe48Skettenis break;
15289b4ffe48Skettenis default:
15299b4ffe48Skettenis break;
15309b4ffe48Skettenis }
15311a945772Spatrick mvpp2_inband_statchg(sc);
15321a945772Spatrick } else {
15331a945772Spatrick sc->sc_mii.mii_media_status = IFM_AVALID|IFM_ACTIVE;
15341a945772Spatrick sc->sc_mii.mii_media_active = IFM_ETHER|IFM_1000_T|IFM_FDX;
15351a945772Spatrick mvpp2_mii_statchg(self);
15361a945772Spatrick }
15371a945772Spatrick
15381a945772Spatrick ifp->if_baudrate = ifmedia_baudrate(sc->sc_mii.mii_media_active);
15391a945772Spatrick ifp->if_link_state = LINK_STATE_FULL_DUPLEX;
15401a945772Spatrick }
15411a945772Spatrick
15421a945772Spatrick if_attach(ifp);
15431a945772Spatrick ether_ifattach(ifp);
15441a945772Spatrick
15451a945772Spatrick if (sc->sc_phy_mode == PHY_MODE_2500BASEX ||
15461a945772Spatrick sc->sc_phy_mode == PHY_MODE_1000BASEX ||
15471a945772Spatrick sc->sc_phy_mode == PHY_MODE_SGMII ||
15481a945772Spatrick sc->sc_phy_mode == PHY_MODE_RGMII ||
15491a945772Spatrick sc->sc_phy_mode == PHY_MODE_RGMII_ID ||
15501a945772Spatrick sc->sc_phy_mode == PHY_MODE_RGMII_RXID ||
15511a945772Spatrick sc->sc_phy_mode == PHY_MODE_RGMII_TXID) {
1552b137aaecSpatrick reg = mvpp2_gmac_read(sc, MVPP2_GMAC_INT_MASK_REG);
1553b137aaecSpatrick reg |= MVPP2_GMAC_INT_CAUSE_LINK_CHANGE;
1554b137aaecSpatrick mvpp2_gmac_write(sc, MVPP2_GMAC_INT_MASK_REG, reg);
15551a945772Spatrick }
15561a945772Spatrick
15571a945772Spatrick if (sc->sc_gop_id == 0) {
15581a945772Spatrick reg = mvpp2_xlg_read(sc, MV_XLG_INTERRUPT_MASK_REG);
15594d0a0269Spatrick reg |= MV_XLG_INTERRUPT_LINK_CHANGE;
15601a945772Spatrick mvpp2_xlg_write(sc, MV_XLG_INTERRUPT_MASK_REG, reg);
15611a945772Spatrick }
15621a945772Spatrick
1563c56f4c70Spatrick mvpp2_gop_intr_unmask(sc);
1564c56f4c70Spatrick
15651a945772Spatrick idx = OF_getindex(sc->sc_node, "link", "interrupt-names");
15661a945772Spatrick if (idx >= 0)
15671a945772Spatrick fdt_intr_establish_idx(sc->sc_node, idx, IPL_NET,
15681a945772Spatrick mvpp2_link_intr, sc, sc->sc_dev.dv_xname);
15691a945772Spatrick idx = OF_getindex(sc->sc_node, "hif0", "interrupt-names");
15701a945772Spatrick if (idx < 0)
15711a945772Spatrick idx = OF_getindex(sc->sc_node, "tx-cpu0", "interrupt-names");
15721a945772Spatrick if (idx >= 0)
15731a945772Spatrick fdt_intr_establish_idx(sc->sc_node, idx, IPL_NET,
15741a945772Spatrick mvpp2_intr, sc, sc->sc_dev.dv_xname);
15751a945772Spatrick }
15761a945772Spatrick
1577a02f2d56Skettenis void
mvpp2_port_attach_sfp(struct device * self)1578a02f2d56Skettenis mvpp2_port_attach_sfp(struct device *self)
1579a02f2d56Skettenis {
1580a02f2d56Skettenis struct mvpp2_port *sc = (struct mvpp2_port *)self;
1581d2cd8f33Skettenis uint32_t reg;
1582a02f2d56Skettenis
1583a02f2d56Skettenis rw_enter(&mvpp2_sff_lock, RW_WRITE);
158488474739Skettenis sfp_disable(sc->sc_sfp);
1585a02f2d56Skettenis sfp_add_media(sc->sc_sfp, &sc->sc_mii);
1586a02f2d56Skettenis rw_exit(&mvpp2_sff_lock);
1587d2cd8f33Skettenis
1588d2cd8f33Skettenis switch (IFM_SUBTYPE(sc->sc_mii.mii_media_active)) {
15899e9e5947Skettenis case IFM_10G_SR:
15909e9e5947Skettenis case IFM_10G_LR:
15919e9e5947Skettenis case IFM_10G_LRM:
15929e9e5947Skettenis case IFM_10G_ER:
15939e9e5947Skettenis case IFM_10G_SFP_CU:
15949e9e5947Skettenis sc->sc_phy_mode = PHY_MODE_10GBASER;
15959e9e5947Skettenis sc->sc_mii.mii_media_status = IFM_AVALID;
15969e9e5947Skettenis sc->sc_inband_status = 1;
15979e9e5947Skettenis break;
1598d2cd8f33Skettenis case IFM_2500_SX:
1599d2cd8f33Skettenis sc->sc_phy_mode = PHY_MODE_2500BASEX;
1600d2cd8f33Skettenis sc->sc_mii.mii_media_status = IFM_AVALID;
1601d2cd8f33Skettenis sc->sc_inband_status = 1;
1602d2cd8f33Skettenis break;
1603d2cd8f33Skettenis case IFM_1000_CX:
1604d2cd8f33Skettenis case IFM_1000_LX:
1605d2cd8f33Skettenis case IFM_1000_SX:
1606d2cd8f33Skettenis case IFM_1000_T:
1607d2cd8f33Skettenis sc->sc_phy_mode = PHY_MODE_1000BASEX;
1608d2cd8f33Skettenis sc->sc_mii.mii_media_status = IFM_AVALID;
1609d2cd8f33Skettenis sc->sc_inband_status = 1;
1610d2cd8f33Skettenis break;
1611d2cd8f33Skettenis }
1612d2cd8f33Skettenis
1613d2cd8f33Skettenis if (sc->sc_inband_status) {
1614d2cd8f33Skettenis reg = mvpp2_gmac_read(sc, MVPP2_GMAC_INT_MASK_REG);
1615d2cd8f33Skettenis reg |= MVPP2_GMAC_INT_CAUSE_LINK_CHANGE;
1616d2cd8f33Skettenis mvpp2_gmac_write(sc, MVPP2_GMAC_INT_MASK_REG, reg);
1617d2cd8f33Skettenis }
1618a02f2d56Skettenis }
1619a02f2d56Skettenis
16201a945772Spatrick uint32_t
mvpp2_read(struct mvpp2_softc * sc,bus_addr_t addr)16211a945772Spatrick mvpp2_read(struct mvpp2_softc *sc, bus_addr_t addr)
16221a945772Spatrick {
16231a945772Spatrick return bus_space_read_4(sc->sc_iot, sc->sc_ioh_base, addr);
16241a945772Spatrick }
16251a945772Spatrick
16261a945772Spatrick void
mvpp2_write(struct mvpp2_softc * sc,bus_addr_t addr,uint32_t data)16271a945772Spatrick mvpp2_write(struct mvpp2_softc *sc, bus_addr_t addr, uint32_t data)
16281a945772Spatrick {
16291a945772Spatrick bus_space_write_4(sc->sc_iot, sc->sc_ioh_base, addr, data);
16301a945772Spatrick }
16311a945772Spatrick
16321a945772Spatrick uint32_t
mvpp2_gmac_read(struct mvpp2_port * sc,bus_addr_t addr)16331a945772Spatrick mvpp2_gmac_read(struct mvpp2_port *sc, bus_addr_t addr)
16341a945772Spatrick {
16351a945772Spatrick return bus_space_read_4(sc->sc->sc_iot, sc->sc->sc_ioh_iface,
16361a945772Spatrick MVPP22_GMAC_OFFSET + sc->sc_gop_id * MVPP22_GMAC_REG_SIZE + addr);
16371a945772Spatrick }
16381a945772Spatrick
16391a945772Spatrick void
mvpp2_gmac_write(struct mvpp2_port * sc,bus_addr_t addr,uint32_t data)16401a945772Spatrick mvpp2_gmac_write(struct mvpp2_port *sc, bus_addr_t addr, uint32_t data)
16411a945772Spatrick {
16421a945772Spatrick bus_space_write_4(sc->sc->sc_iot, sc->sc->sc_ioh_iface,
16431a945772Spatrick MVPP22_GMAC_OFFSET + sc->sc_gop_id * MVPP22_GMAC_REG_SIZE + addr,
16441a945772Spatrick data);
16451a945772Spatrick }
16461a945772Spatrick
16471a945772Spatrick uint32_t
mvpp2_xlg_read(struct mvpp2_port * sc,bus_addr_t addr)16481a945772Spatrick mvpp2_xlg_read(struct mvpp2_port *sc, bus_addr_t addr)
16491a945772Spatrick {
16501a945772Spatrick return bus_space_read_4(sc->sc->sc_iot, sc->sc->sc_ioh_iface,
16511a945772Spatrick MVPP22_XLG_OFFSET + sc->sc_gop_id * MVPP22_XLG_REG_SIZE + addr);
16521a945772Spatrick }
16531a945772Spatrick
16541a945772Spatrick void
mvpp2_xlg_write(struct mvpp2_port * sc,bus_addr_t addr,uint32_t data)16551a945772Spatrick mvpp2_xlg_write(struct mvpp2_port *sc, bus_addr_t addr, uint32_t data)
16561a945772Spatrick {
16571a945772Spatrick bus_space_write_4(sc->sc->sc_iot, sc->sc->sc_ioh_iface,
16581a945772Spatrick MVPP22_XLG_OFFSET + sc->sc_gop_id * MVPP22_XLG_REG_SIZE + addr,
16591a945772Spatrick data);
16601a945772Spatrick }
16611a945772Spatrick
16621a945772Spatrick uint32_t
mvpp2_mpcs_read(struct mvpp2_port * sc,bus_addr_t addr)16631a945772Spatrick mvpp2_mpcs_read(struct mvpp2_port *sc, bus_addr_t addr)
16641a945772Spatrick {
16651a945772Spatrick return bus_space_read_4(sc->sc->sc_iot, sc->sc->sc_ioh_iface,
16661a945772Spatrick MVPP22_MPCS_OFFSET + sc->sc_gop_id * MVPP22_MPCS_REG_SIZE + addr);
16671a945772Spatrick }
16681a945772Spatrick
16691a945772Spatrick void
mvpp2_mpcs_write(struct mvpp2_port * sc,bus_addr_t addr,uint32_t data)16701a945772Spatrick mvpp2_mpcs_write(struct mvpp2_port *sc, bus_addr_t addr, uint32_t data)
16711a945772Spatrick {
16721a945772Spatrick bus_space_write_4(sc->sc->sc_iot, sc->sc->sc_ioh_iface,
16731a945772Spatrick MVPP22_MPCS_OFFSET + sc->sc_gop_id * MVPP22_MPCS_REG_SIZE + addr,
16741a945772Spatrick data);
16751a945772Spatrick }
16761a945772Spatrick
16771a945772Spatrick uint32_t
mvpp2_xpcs_read(struct mvpp2_port * sc,bus_addr_t addr)16781a945772Spatrick mvpp2_xpcs_read(struct mvpp2_port *sc, bus_addr_t addr)
16791a945772Spatrick {
16801a945772Spatrick return bus_space_read_4(sc->sc->sc_iot, sc->sc->sc_ioh_iface,
16811a945772Spatrick MVPP22_XPCS_OFFSET + sc->sc_gop_id * MVPP22_XPCS_REG_SIZE + addr);
16821a945772Spatrick }
16831a945772Spatrick
16841a945772Spatrick void
mvpp2_xpcs_write(struct mvpp2_port * sc,bus_addr_t addr,uint32_t data)16851a945772Spatrick mvpp2_xpcs_write(struct mvpp2_port *sc, bus_addr_t addr, uint32_t data)
16861a945772Spatrick {
16871a945772Spatrick bus_space_write_4(sc->sc->sc_iot, sc->sc->sc_ioh_iface,
16881a945772Spatrick MVPP22_XPCS_OFFSET + sc->sc_gop_id * MVPP22_XPCS_REG_SIZE + addr,
16891a945772Spatrick data);
16901a945772Spatrick }
16911a945772Spatrick
169253d582d1Spatrick static inline int
mvpp2_load_mbuf(bus_dma_tag_t dmat,bus_dmamap_t map,struct mbuf * m)169353d582d1Spatrick mvpp2_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m)
169453d582d1Spatrick {
169553d582d1Spatrick int error;
169653d582d1Spatrick
169753d582d1Spatrick error = bus_dmamap_load_mbuf(dmat, map, m, BUS_DMA_NOWAIT);
169853d582d1Spatrick if (error != EFBIG)
169953d582d1Spatrick return (error);
170053d582d1Spatrick
170153d582d1Spatrick error = m_defrag(m, M_DONTWAIT);
170253d582d1Spatrick if (error != 0)
170353d582d1Spatrick return (error);
170453d582d1Spatrick
170553d582d1Spatrick return bus_dmamap_load_mbuf(dmat, map, m, BUS_DMA_NOWAIT);
170653d582d1Spatrick }
170753d582d1Spatrick
17081a945772Spatrick void
mvpp2_start(struct ifnet * ifp)17091a945772Spatrick mvpp2_start(struct ifnet *ifp)
17101a945772Spatrick {
17111a945772Spatrick struct mvpp2_port *sc = ifp->if_softc;
17121a945772Spatrick struct mvpp2_tx_queue *txq = &sc->sc->sc_aggr_txqs[0];
171353d582d1Spatrick struct mvpp2_tx_desc *txd;
17141a945772Spatrick struct mbuf *m;
171553d582d1Spatrick bus_dmamap_t map;
171653d582d1Spatrick uint32_t command;
171753d582d1Spatrick int i, current, first, last;
171853d582d1Spatrick int free, prod, used;
17191a945772Spatrick
17201a945772Spatrick if (!(ifp->if_flags & IFF_RUNNING))
17211a945772Spatrick return;
17221a945772Spatrick if (ifq_is_oactive(&ifp->if_snd))
17231a945772Spatrick return;
17240cae21bdSpatrick if (ifq_empty(&ifp->if_snd))
17251a945772Spatrick return;
17261a945772Spatrick if (!sc->sc_link)
17271a945772Spatrick return;
17281a945772Spatrick
172953d582d1Spatrick used = 0;
173053d582d1Spatrick prod = txq->prod;
173153d582d1Spatrick free = txq->cons;
173253d582d1Spatrick if (free <= prod)
173353d582d1Spatrick free += MVPP2_AGGR_TXQ_SIZE;
173453d582d1Spatrick free -= prod;
173553d582d1Spatrick
173653d582d1Spatrick for (;;) {
173753d582d1Spatrick if (free <= MVPP2_NTXSEGS) {
173853d582d1Spatrick ifq_set_oactive(&ifp->if_snd);
173953d582d1Spatrick break;
174053d582d1Spatrick }
174153d582d1Spatrick
17421a945772Spatrick m = ifq_dequeue(&ifp->if_snd);
17431a945772Spatrick if (m == NULL)
17441a945772Spatrick break;
17451a945772Spatrick
174653d582d1Spatrick first = last = current = prod;
17471a945772Spatrick map = txq->buf[current].mb_map;
17481a945772Spatrick
174953d582d1Spatrick if (mvpp2_load_mbuf(sc->sc_dmat, map, m) != 0) {
175053d582d1Spatrick ifp->if_oerrors++;
175153d582d1Spatrick m_freem(m);
175253d582d1Spatrick continue;
17531a945772Spatrick }
17541a945772Spatrick
17551a945772Spatrick bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
17561a945772Spatrick BUS_DMASYNC_PREWRITE);
17571a945772Spatrick
17581a945772Spatrick command = MVPP2_TXD_L4_CSUM_NOT |
17591a945772Spatrick MVPP2_TXD_IP_CSUM_DISABLE;
17601a945772Spatrick for (i = 0; i < map->dm_nsegs; i++) {
17611a945772Spatrick txd = &txq->descs[current];
17621a945772Spatrick memset(txd, 0, sizeof(*txd));
17631a945772Spatrick txd->buf_phys_addr_hw_cmd2 =
17641a945772Spatrick map->dm_segs[i].ds_addr & ~0x1f;
17651a945772Spatrick txd->packet_offset =
17661a945772Spatrick map->dm_segs[i].ds_addr & 0x1f;
17671a945772Spatrick txd->data_size = map->dm_segs[i].ds_len;
17681a945772Spatrick txd->phys_txq = sc->sc_txqs[0].id;
17691a945772Spatrick txd->command = command |
17701a945772Spatrick MVPP2_TXD_PADDING_DISABLE;
17711a945772Spatrick if (i == 0)
17721a945772Spatrick txd->command |= MVPP2_TXD_F_DESC;
17731a945772Spatrick if (i == (map->dm_nsegs - 1))
17741a945772Spatrick txd->command |= MVPP2_TXD_L_DESC;
17751a945772Spatrick
17761a945772Spatrick bus_dmamap_sync(sc->sc_dmat, MVPP2_DMA_MAP(txq->ring),
17771a945772Spatrick current * sizeof(*txd), sizeof(*txd),
17781a945772Spatrick BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
17791a945772Spatrick
17801a945772Spatrick last = current;
1781f230dab5Spatrick current = (current + 1) % MVPP2_AGGR_TXQ_SIZE;
17821a945772Spatrick KASSERT(current != txq->cons);
17831a945772Spatrick }
17841a945772Spatrick
17851a945772Spatrick KASSERT(txq->buf[last].mb_m == NULL);
17861a945772Spatrick txq->buf[first].mb_map = txq->buf[last].mb_map;
17871a945772Spatrick txq->buf[last].mb_map = map;
17881a945772Spatrick txq->buf[last].mb_m = m;
17891a945772Spatrick
179053d582d1Spatrick #if NBPFILTER > 0
179153d582d1Spatrick if (ifp->if_bpf)
179253d582d1Spatrick bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
179353d582d1Spatrick #endif
17941a945772Spatrick
179553d582d1Spatrick free -= map->dm_nsegs;
179653d582d1Spatrick used += map->dm_nsegs;
179753d582d1Spatrick prod = current;
179853d582d1Spatrick }
17991a945772Spatrick
180053d582d1Spatrick if (used)
180153d582d1Spatrick mvpp2_write(sc->sc, MVPP2_AGGR_TXQ_UPDATE_REG, used);
180253d582d1Spatrick
180353d582d1Spatrick if (txq->prod != prod)
180453d582d1Spatrick txq->prod = prod;
18051a945772Spatrick }
18061a945772Spatrick
18071a945772Spatrick int
mvpp2_ioctl(struct ifnet * ifp,u_long cmd,caddr_t addr)18081a945772Spatrick mvpp2_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr)
18091a945772Spatrick {
18101a945772Spatrick struct mvpp2_port *sc = ifp->if_softc;
18111a945772Spatrick struct ifreq *ifr = (struct ifreq *)addr;
18121a945772Spatrick int error = 0, s;
18131a945772Spatrick
18141a945772Spatrick s = splnet();
18151a945772Spatrick
18161a945772Spatrick switch (cmd) {
18171a945772Spatrick case SIOCSIFADDR:
18181a945772Spatrick ifp->if_flags |= IFF_UP;
18191a945772Spatrick /* FALLTHROUGH */
18201a945772Spatrick case SIOCSIFFLAGS:
18211a945772Spatrick if (ifp->if_flags & IFF_UP) {
18221a945772Spatrick if (ifp->if_flags & IFF_RUNNING)
18231a945772Spatrick error = ENETRESET;
18241a945772Spatrick else
18251a945772Spatrick mvpp2_up(sc);
18261a945772Spatrick } else {
18271a945772Spatrick if (ifp->if_flags & IFF_RUNNING)
18281a945772Spatrick mvpp2_down(sc);
18291a945772Spatrick }
18301a945772Spatrick break;
18311a945772Spatrick
18321a945772Spatrick case SIOCGIFMEDIA:
18331a945772Spatrick case SIOCSIFMEDIA:
18341a945772Spatrick error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
18351a945772Spatrick break;
18361a945772Spatrick
18371a945772Spatrick case SIOCGIFRXR:
18381a945772Spatrick error = mvpp2_rxrinfo(sc, (struct if_rxrinfo *)ifr->ifr_data);
18391a945772Spatrick break;
18401a945772Spatrick
18411a945772Spatrick case SIOCGIFSFFPAGE:
18421a945772Spatrick error = rw_enter(&mvpp2_sff_lock, RW_WRITE|RW_INTR);
18431a945772Spatrick if (error != 0)
18441a945772Spatrick break;
18451a945772Spatrick
18461a945772Spatrick error = sfp_get_sffpage(sc->sc_sfp, (struct if_sffpage *)addr);
18471a945772Spatrick rw_exit(&mvpp2_sff_lock);
18481a945772Spatrick break;
18491a945772Spatrick
18501a945772Spatrick default:
18511a945772Spatrick error = ether_ioctl(ifp, &sc->sc_ac, cmd, addr);
18521a945772Spatrick break;
18531a945772Spatrick }
18541a945772Spatrick
18551a945772Spatrick if (error == ENETRESET) {
18561a945772Spatrick if (ifp->if_flags & IFF_RUNNING)
18571a945772Spatrick mvpp2_iff(sc);
18581a945772Spatrick error = 0;
18591a945772Spatrick }
18601a945772Spatrick
18611a945772Spatrick splx(s);
18621a945772Spatrick return (error);
18631a945772Spatrick }
18641a945772Spatrick
18651a945772Spatrick int
mvpp2_rxrinfo(struct mvpp2_port * sc,struct if_rxrinfo * ifri)18661a945772Spatrick mvpp2_rxrinfo(struct mvpp2_port *sc, struct if_rxrinfo *ifri)
18671a945772Spatrick {
18681a945772Spatrick struct mvpp2_rx_queue *rxq;
18691a945772Spatrick struct if_rxring_info *ifrs, *ifr;
18701a945772Spatrick unsigned int i;
18711a945772Spatrick int error;
18721a945772Spatrick
18731a945772Spatrick ifrs = mallocarray(sc->sc_nrxq, sizeof(*ifrs), M_TEMP,
18741a945772Spatrick M_WAITOK|M_ZERO|M_CANFAIL);
18751a945772Spatrick if (ifrs == NULL)
18761a945772Spatrick return (ENOMEM);
18771a945772Spatrick
18781a945772Spatrick for (i = 0; i < sc->sc_nrxq; i++) {
18791a945772Spatrick rxq = &sc->sc_rxqs[i];
18801a945772Spatrick ifr = &ifrs[i];
18811a945772Spatrick
18821a945772Spatrick snprintf(ifr->ifr_name, sizeof(ifr->ifr_name), "%u", i);
18831a945772Spatrick ifr->ifr_size = MCLBYTES;
18841a945772Spatrick ifr->ifr_info = rxq->rxring;
18851a945772Spatrick }
18861a945772Spatrick
18871a945772Spatrick error = if_rxr_info_ioctl(ifri, i, ifrs);
18881a945772Spatrick free(ifrs, M_TEMP, i * sizeof(*ifrs));
18891a945772Spatrick
18901a945772Spatrick return (error);
18911a945772Spatrick }
18921a945772Spatrick
18931a945772Spatrick void
mvpp2_watchdog(struct ifnet * ifp)18941a945772Spatrick mvpp2_watchdog(struct ifnet *ifp)
18951a945772Spatrick {
18961a945772Spatrick printf("%s\n", __func__);
18971a945772Spatrick }
18981a945772Spatrick
18991a945772Spatrick int
mvpp2_media_change(struct ifnet * ifp)19001a945772Spatrick mvpp2_media_change(struct ifnet *ifp)
19011a945772Spatrick {
19021a945772Spatrick struct mvpp2_port *sc = ifp->if_softc;
19031a945772Spatrick
19041a945772Spatrick if (LIST_FIRST(&sc->sc_mii.mii_phys))
19051a945772Spatrick mii_mediachg(&sc->sc_mii);
19061a945772Spatrick
19071a945772Spatrick return (0);
19081a945772Spatrick }
19091a945772Spatrick
19101a945772Spatrick void
mvpp2_media_status(struct ifnet * ifp,struct ifmediareq * ifmr)19111a945772Spatrick mvpp2_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
19121a945772Spatrick {
19131a945772Spatrick struct mvpp2_port *sc = ifp->if_softc;
19141a945772Spatrick
19151a945772Spatrick if (LIST_FIRST(&sc->sc_mii.mii_phys))
19161a945772Spatrick mii_pollstat(&sc->sc_mii);
19171a945772Spatrick
19181a945772Spatrick ifmr->ifm_active = sc->sc_mii.mii_media_active;
19191a945772Spatrick ifmr->ifm_status = sc->sc_mii.mii_media_status;
19201a945772Spatrick }
19211a945772Spatrick
19221a945772Spatrick int
mvpp2_mii_readreg(struct device * self,int phy,int reg)19231a945772Spatrick mvpp2_mii_readreg(struct device *self, int phy, int reg)
19241a945772Spatrick {
19251a945772Spatrick struct mvpp2_port *sc = (void *)self;
19261a945772Spatrick return sc->sc_mdio->md_readreg(sc->sc_mdio->md_cookie, phy, reg);
19271a945772Spatrick }
19281a945772Spatrick
19291a945772Spatrick void
mvpp2_mii_writereg(struct device * self,int phy,int reg,int val)19301a945772Spatrick mvpp2_mii_writereg(struct device *self, int phy, int reg, int val)
19311a945772Spatrick {
19321a945772Spatrick struct mvpp2_port *sc = (void *)self;
19331a945772Spatrick return sc->sc_mdio->md_writereg(sc->sc_mdio->md_cookie, phy, reg, val);
19341a945772Spatrick }
19351a945772Spatrick
19361a945772Spatrick void
mvpp2_mii_statchg(struct device * self)19371a945772Spatrick mvpp2_mii_statchg(struct device *self)
19381a945772Spatrick {
19391a945772Spatrick struct mvpp2_port *sc = (void *)self;
19401a945772Spatrick mvpp2_port_change(sc);
19411a945772Spatrick }
19421a945772Spatrick
19431a945772Spatrick void
mvpp2_inband_statchg(struct mvpp2_port * sc)19441a945772Spatrick mvpp2_inband_statchg(struct mvpp2_port *sc)
19451a945772Spatrick {
1946d2cd8f33Skettenis uint64_t subtype = IFM_SUBTYPE(sc->sc_mii.mii_media_active);
19471a945772Spatrick uint32_t reg;
19481a945772Spatrick
19491a945772Spatrick sc->sc_mii.mii_media_status = IFM_AVALID;
19501a945772Spatrick sc->sc_mii.mii_media_active = IFM_ETHER;
19511a945772Spatrick
19521a945772Spatrick if (sc->sc_gop_id == 0 && (sc->sc_phy_mode == PHY_MODE_10GBASER ||
19531a945772Spatrick sc->sc_phy_mode == PHY_MODE_XAUI)) {
19541a945772Spatrick reg = mvpp2_xlg_read(sc, MV_XLG_MAC_PORT_STATUS_REG);
19554d0a0269Spatrick if (reg & MV_XLG_MAC_PORT_STATUS_LINKSTATUS)
19561a945772Spatrick sc->sc_mii.mii_media_status |= IFM_ACTIVE;
19571a945772Spatrick sc->sc_mii.mii_media_active |= IFM_FDX;
19589e9e5947Skettenis sc->sc_mii.mii_media_active |= subtype;
19591a945772Spatrick } else {
19601a945772Spatrick reg = mvpp2_gmac_read(sc, MVPP2_PORT_STATUS0_REG);
19614d0a0269Spatrick if (reg & MVPP2_PORT_STATUS0_LINKUP)
19621a945772Spatrick sc->sc_mii.mii_media_status |= IFM_ACTIVE;
19634d0a0269Spatrick if (reg & MVPP2_PORT_STATUS0_FULLDX)
19641a945772Spatrick sc->sc_mii.mii_media_active |= IFM_FDX;
19651a945772Spatrick if (sc->sc_phy_mode == PHY_MODE_2500BASEX)
1966d2cd8f33Skettenis sc->sc_mii.mii_media_active |= subtype;
19671a945772Spatrick else if (sc->sc_phy_mode == PHY_MODE_1000BASEX)
1968d2cd8f33Skettenis sc->sc_mii.mii_media_active |= subtype;
19694d0a0269Spatrick else if (reg & MVPP2_PORT_STATUS0_GMIISPEED)
19701a945772Spatrick sc->sc_mii.mii_media_active |= IFM_1000_T;
19714d0a0269Spatrick else if (reg & MVPP2_PORT_STATUS0_MIISPEED)
19721a945772Spatrick sc->sc_mii.mii_media_active |= IFM_100_TX;
19731a945772Spatrick else
19741a945772Spatrick sc->sc_mii.mii_media_active |= IFM_10_T;
19751a945772Spatrick }
19761a945772Spatrick
19771a945772Spatrick mvpp2_port_change(sc);
19781a945772Spatrick }
19791a945772Spatrick
19801a945772Spatrick void
mvpp2_port_change(struct mvpp2_port * sc)19811a945772Spatrick mvpp2_port_change(struct mvpp2_port *sc)
19821a945772Spatrick {
19831a945772Spatrick uint32_t reg;
19841a945772Spatrick
1985c56f4c70Spatrick sc->sc_link = !!(sc->sc_mii.mii_media_status & IFM_ACTIVE);
19861a945772Spatrick
19871a945772Spatrick if (sc->sc_inband_status)
19881a945772Spatrick return;
19891a945772Spatrick
19901a945772Spatrick if (sc->sc_link) {
19911a945772Spatrick if (sc->sc_phy_mode == PHY_MODE_10GBASER ||
19921a945772Spatrick sc->sc_phy_mode == PHY_MODE_XAUI) {
19931a945772Spatrick reg = mvpp2_xlg_read(sc, MV_XLG_PORT_MAC_CTRL0_REG);
19944d0a0269Spatrick reg &= ~MV_XLG_MAC_CTRL0_FORCELINKDOWN;
19954d0a0269Spatrick reg |= MV_XLG_MAC_CTRL0_FORCELINKPASS;
19961a945772Spatrick mvpp2_xlg_write(sc, MV_XLG_PORT_MAC_CTRL0_REG, reg);
19971a945772Spatrick } else {
19981a945772Spatrick reg = mvpp2_gmac_read(sc, MVPP2_GMAC_AUTONEG_CONFIG);
19991a945772Spatrick reg &= ~MVPP2_GMAC_FORCE_LINK_DOWN;
20001a945772Spatrick reg |= MVPP2_GMAC_FORCE_LINK_PASS;
20011a945772Spatrick reg &= ~MVPP2_GMAC_CONFIG_MII_SPEED;
20021a945772Spatrick reg &= ~MVPP2_GMAC_CONFIG_GMII_SPEED;
20031a945772Spatrick reg &= ~MVPP2_GMAC_CONFIG_FULL_DUPLEX;
20049b4ffe48Skettenis if (IFM_SUBTYPE(sc->sc_mii.mii_media_active) == IFM_2500_KX ||
20059b4ffe48Skettenis IFM_SUBTYPE(sc->sc_mii.mii_media_active) == IFM_2500_SX ||
2006d2cd8f33Skettenis IFM_SUBTYPE(sc->sc_mii.mii_media_active) == IFM_1000_CX ||
2007d2cd8f33Skettenis IFM_SUBTYPE(sc->sc_mii.mii_media_active) == IFM_1000_LX ||
20089b4ffe48Skettenis IFM_SUBTYPE(sc->sc_mii.mii_media_active) == IFM_1000_KX ||
20091a945772Spatrick IFM_SUBTYPE(sc->sc_mii.mii_media_active) == IFM_1000_SX ||
20101a945772Spatrick IFM_SUBTYPE(sc->sc_mii.mii_media_active) == IFM_1000_T)
20111a945772Spatrick reg |= MVPP2_GMAC_CONFIG_GMII_SPEED;
20121a945772Spatrick if (IFM_SUBTYPE(sc->sc_mii.mii_media_active) == IFM_100_TX)
20131a945772Spatrick reg |= MVPP2_GMAC_CONFIG_MII_SPEED;
20141a945772Spatrick if ((sc->sc_mii.mii_media_active & IFM_GMASK) == IFM_FDX)
20151a945772Spatrick reg |= MVPP2_GMAC_CONFIG_FULL_DUPLEX;
20161a945772Spatrick mvpp2_gmac_write(sc, MVPP2_GMAC_AUTONEG_CONFIG, reg);
20171a945772Spatrick }
20181a945772Spatrick } else {
20191a945772Spatrick if (sc->sc_phy_mode == PHY_MODE_10GBASER ||
20201a945772Spatrick sc->sc_phy_mode == PHY_MODE_XAUI) {
20211a945772Spatrick reg = mvpp2_xlg_read(sc, MV_XLG_PORT_MAC_CTRL0_REG);
20224d0a0269Spatrick reg &= ~MV_XLG_MAC_CTRL0_FORCELINKPASS;
20234d0a0269Spatrick reg |= MV_XLG_MAC_CTRL0_FORCELINKDOWN;
20241a945772Spatrick mvpp2_xlg_write(sc, MV_XLG_PORT_MAC_CTRL0_REG, reg);
20251a945772Spatrick } else {
20261a945772Spatrick reg = mvpp2_gmac_read(sc, MVPP2_GMAC_AUTONEG_CONFIG);
20271a945772Spatrick reg &= ~MVPP2_GMAC_FORCE_LINK_PASS;
20281a945772Spatrick reg |= MVPP2_GMAC_FORCE_LINK_DOWN;
20291a945772Spatrick mvpp2_gmac_write(sc, MVPP2_GMAC_AUTONEG_CONFIG, reg);
20301a945772Spatrick }
20311a945772Spatrick }
20321a945772Spatrick }
20331a945772Spatrick
20341a945772Spatrick void
mvpp2_tick(void * arg)20351a945772Spatrick mvpp2_tick(void *arg)
20361a945772Spatrick {
20371a945772Spatrick struct mvpp2_port *sc = arg;
20381a945772Spatrick int s;
20391a945772Spatrick
20401a945772Spatrick s = splnet();
20411a945772Spatrick mii_tick(&sc->sc_mii);
20421a945772Spatrick splx(s);
20431a945772Spatrick
20441a945772Spatrick timeout_add_sec(&sc->sc_tick, 1);
20451a945772Spatrick }
20461a945772Spatrick
20471a945772Spatrick int
mvpp2_link_intr(void * arg)20481a945772Spatrick mvpp2_link_intr(void *arg)
20491a945772Spatrick {
20501a945772Spatrick struct mvpp2_port *sc = arg;
20511a945772Spatrick uint32_t reg;
20521a945772Spatrick int event = 0;
20531a945772Spatrick
20541a945772Spatrick if (sc->sc_gop_id == 0 && (sc->sc_phy_mode == PHY_MODE_10GBASER ||
20551a945772Spatrick sc->sc_phy_mode == PHY_MODE_XAUI)) {
20561a945772Spatrick reg = mvpp2_xlg_read(sc, MV_XLG_INTERRUPT_CAUSE_REG);
20574d0a0269Spatrick if (reg & MV_XLG_INTERRUPT_LINK_CHANGE)
20581a945772Spatrick event = 1;
20591a945772Spatrick } else if (sc->sc_phy_mode == PHY_MODE_2500BASEX ||
20601a945772Spatrick sc->sc_phy_mode == PHY_MODE_1000BASEX ||
20611a945772Spatrick sc->sc_phy_mode == PHY_MODE_SGMII ||
20621a945772Spatrick sc->sc_phy_mode == PHY_MODE_RGMII ||
20631a945772Spatrick sc->sc_phy_mode == PHY_MODE_RGMII_ID ||
20641a945772Spatrick sc->sc_phy_mode == PHY_MODE_RGMII_RXID ||
20651a945772Spatrick sc->sc_phy_mode == PHY_MODE_RGMII_TXID) {
2066b137aaecSpatrick reg = mvpp2_gmac_read(sc, MVPP2_GMAC_INT_CAUSE_REG);
2067b137aaecSpatrick if (reg & MVPP2_GMAC_INT_CAUSE_LINK_CHANGE)
20681a945772Spatrick event = 1;
20691a945772Spatrick }
20701a945772Spatrick
20711a945772Spatrick if (event && sc->sc_inband_status)
20721a945772Spatrick mvpp2_inband_statchg(sc);
20731a945772Spatrick
20741a945772Spatrick return (1);
20751a945772Spatrick }
20761a945772Spatrick
20771a945772Spatrick int
mvpp2_intr(void * arg)20781a945772Spatrick mvpp2_intr(void *arg)
20791a945772Spatrick {
20801a945772Spatrick struct mvpp2_port *sc = arg;
20811a945772Spatrick uint32_t reg;
20821a945772Spatrick
20831a945772Spatrick reg = mvpp2_read(sc->sc, MVPP2_ISR_RX_TX_CAUSE_REG(sc->sc_id));
20841a945772Spatrick if (reg & MVPP2_CAUSE_MISC_SUM_MASK) {
20851a945772Spatrick mvpp2_write(sc->sc, MVPP2_ISR_MISC_CAUSE_REG, 0);
20861a945772Spatrick mvpp2_write(sc->sc, MVPP2_ISR_RX_TX_CAUSE_REG(sc->sc_id),
20871a945772Spatrick reg & ~MVPP2_CAUSE_MISC_SUM_MASK);
20881a945772Spatrick }
20891a945772Spatrick if (reg & MVPP2_CAUSE_TXQ_OCCUP_DESC_ALL_MASK)
20901a945772Spatrick mvpp2_tx_proc(sc,
20911a945772Spatrick (reg & MVPP2_CAUSE_TXQ_OCCUP_DESC_ALL_MASK) >>
20921a945772Spatrick MVPP2_CAUSE_TXQ_OCCUP_DESC_ALL_OFFSET);
20931a945772Spatrick
20941a945772Spatrick if (reg & MVPP2_CAUSE_RXQ_OCCUP_DESC_ALL_MASK)
20951a945772Spatrick mvpp2_rx_proc(sc,
20961a945772Spatrick reg & MVPP2_CAUSE_RXQ_OCCUP_DESC_ALL_MASK);
20971a945772Spatrick
20981a945772Spatrick return (1);
20991a945772Spatrick }
21001a945772Spatrick
21011a945772Spatrick void
mvpp2_tx_proc(struct mvpp2_port * sc,uint8_t queues)21021a945772Spatrick mvpp2_tx_proc(struct mvpp2_port *sc, uint8_t queues)
21031a945772Spatrick {
21041a945772Spatrick struct mvpp2_tx_queue *txq;
21051a945772Spatrick int i;
21061a945772Spatrick
21071a945772Spatrick for (i = 0; i < sc->sc_ntxq; i++) {
21081a945772Spatrick txq = &sc->sc_txqs[i];
21091a945772Spatrick if ((queues & (1 << i)) == 0)
21101a945772Spatrick continue;
211163ca77e8Spatrick mvpp2_txq_proc(sc, txq);
211263ca77e8Spatrick }
21131a945772Spatrick }
21141a945772Spatrick
211563ca77e8Spatrick void
mvpp2_txq_proc(struct mvpp2_port * sc,struct mvpp2_tx_queue * txq)211663ca77e8Spatrick mvpp2_txq_proc(struct mvpp2_port *sc, struct mvpp2_tx_queue *txq)
211763ca77e8Spatrick {
211863ca77e8Spatrick struct ifnet *ifp = &sc->sc_ac.ac_if;
211963ca77e8Spatrick struct mvpp2_tx_queue *aggr_txq = &sc->sc->sc_aggr_txqs[0];
212063ca77e8Spatrick struct mvpp2_buf *txb;
212163ca77e8Spatrick int i, idx, nsent;
212263ca77e8Spatrick
212353d582d1Spatrick /* XXX: this is a percpu register! */
212463ca77e8Spatrick nsent = (mvpp2_read(sc->sc, MVPP2_TXQ_SENT_REG(txq->id)) &
212563ca77e8Spatrick MVPP2_TRANSMITTED_COUNT_MASK) >>
212663ca77e8Spatrick MVPP2_TRANSMITTED_COUNT_OFFSET;
212763ca77e8Spatrick
212863ca77e8Spatrick for (i = 0; i < nsent; i++) {
212963ca77e8Spatrick idx = aggr_txq->cons;
213063ca77e8Spatrick KASSERT(idx < MVPP2_AGGR_TXQ_SIZE);
213163ca77e8Spatrick
213263ca77e8Spatrick txb = &aggr_txq->buf[idx];
213363ca77e8Spatrick if (txb->mb_m) {
213463ca77e8Spatrick bus_dmamap_sync(sc->sc_dmat, txb->mb_map, 0,
213563ca77e8Spatrick txb->mb_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
213663ca77e8Spatrick bus_dmamap_unload(sc->sc_dmat, txb->mb_map);
213763ca77e8Spatrick
213863ca77e8Spatrick m_freem(txb->mb_m);
213963ca77e8Spatrick txb->mb_m = NULL;
214063ca77e8Spatrick }
214163ca77e8Spatrick
214263ca77e8Spatrick aggr_txq->cons = (aggr_txq->cons + 1) % MVPP2_AGGR_TXQ_SIZE;
214363ca77e8Spatrick }
214463ca77e8Spatrick
214563ca77e8Spatrick if (ifq_is_oactive(&ifp->if_snd))
214663ca77e8Spatrick ifq_restart(&ifp->if_snd);
21471a945772Spatrick }
21481a945772Spatrick
21491a945772Spatrick void
mvpp2_rx_proc(struct mvpp2_port * sc,uint8_t queues)21501a945772Spatrick mvpp2_rx_proc(struct mvpp2_port *sc, uint8_t queues)
21511a945772Spatrick {
21521a945772Spatrick struct mvpp2_rx_queue *rxq;
21531a945772Spatrick int i;
21541a945772Spatrick
21551a945772Spatrick for (i = 0; i < sc->sc_nrxq; i++) {
21561a945772Spatrick rxq = &sc->sc_rxqs[i];
21571a945772Spatrick if ((queues & (1 << i)) == 0)
21581a945772Spatrick continue;
21591a945772Spatrick mvpp2_rxq_proc(sc, rxq);
21601a945772Spatrick }
2161be107da9Spatrick
2162be107da9Spatrick mvpp2_rx_refill(sc);
21631a945772Spatrick }
21641a945772Spatrick
21651a945772Spatrick void
mvpp2_rxq_proc(struct mvpp2_port * sc,struct mvpp2_rx_queue * rxq)21661a945772Spatrick mvpp2_rxq_proc(struct mvpp2_port *sc, struct mvpp2_rx_queue *rxq)
21671a945772Spatrick {
21681a945772Spatrick struct ifnet *ifp = &sc->sc_ac.ac_if;
21691a945772Spatrick struct mbuf_list ml = MBUF_LIST_INITIALIZER();
21701a945772Spatrick struct mvpp2_rx_desc *rxd;
21711a945772Spatrick struct mvpp2_bm_pool *bm;
21721a945772Spatrick struct mvpp2_buf *rxb;
21731a945772Spatrick struct mbuf *m;
21741a945772Spatrick uint64_t virt;
2175be107da9Spatrick uint32_t i, nrecv, pool;
21761a945772Spatrick
21771a945772Spatrick nrecv = mvpp2_rxq_received(sc, rxq->id);
21781a945772Spatrick if (!nrecv)
21791a945772Spatrick return;
21801a945772Spatrick
2181be107da9Spatrick pool = curcpu()->ci_cpuid;
2182be107da9Spatrick KASSERT(pool < sc->sc->sc_npools);
2183be107da9Spatrick bm = &sc->sc->sc_bm_pools[pool];
21841a945772Spatrick
21851a945772Spatrick bus_dmamap_sync(sc->sc_dmat, MVPP2_DMA_MAP(rxq->ring), 0,
21861a945772Spatrick MVPP2_DMA_LEN(rxq->ring),
21871a945772Spatrick BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
21881a945772Spatrick
21891a945772Spatrick for (i = 0; i < nrecv; i++) {
21901a945772Spatrick rxd = &rxq->descs[rxq->cons];
21911a945772Spatrick virt = rxd->buf_cookie_bm_qset_cls_info;
2192be107da9Spatrick KASSERT(((virt >> 16) & 0xffff) == pool);
2193be107da9Spatrick KASSERT((virt & 0xffff) < MVPP2_BM_SIZE);
21941a945772Spatrick rxb = &bm->rxbuf[virt & 0xffff];
2195be107da9Spatrick KASSERT(rxb->mb_m != NULL);
21961a945772Spatrick
21971a945772Spatrick bus_dmamap_sync(sc->sc_dmat, rxb->mb_map, 0,
21981a945772Spatrick rxd->data_size, BUS_DMASYNC_POSTREAD);
21991a945772Spatrick bus_dmamap_unload(sc->sc_dmat, rxb->mb_map);
22001a945772Spatrick
22011a945772Spatrick m = rxb->mb_m;
22021a945772Spatrick rxb->mb_m = NULL;
22031a945772Spatrick
22041a945772Spatrick m->m_pkthdr.len = m->m_len = rxd->data_size;
22051a945772Spatrick m_adj(m, MVPP2_MH_SIZE);
22061a945772Spatrick ml_enqueue(&ml, m);
22071a945772Spatrick
2208be107da9Spatrick KASSERT(bm->freelist[bm->free_prod] == -1);
2209be107da9Spatrick bm->freelist[bm->free_prod] = virt & 0xffffffff;
2210be107da9Spatrick bm->free_prod = (bm->free_prod + 1) % MVPP2_BM_SIZE;
2211be107da9Spatrick
22121a945772Spatrick rxq->cons = (rxq->cons + 1) % MVPP2_NRXDESC;
22131a945772Spatrick }
22141a945772Spatrick
22151a945772Spatrick bus_dmamap_sync(sc->sc_dmat, MVPP2_DMA_MAP(rxq->ring), 0,
22161a945772Spatrick MVPP2_DMA_LEN(rxq->ring),
22171a945772Spatrick BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
22181a945772Spatrick
22191a945772Spatrick mvpp2_rxq_status_update(sc, rxq->id, nrecv, nrecv);
22201a945772Spatrick
22211a945772Spatrick if_input(ifp, &ml);
22221a945772Spatrick }
22231a945772Spatrick
2224be107da9Spatrick /*
2225be107da9Spatrick * We have a pool per core, and since we should not assume that
2226be107da9Spatrick * RX buffers are always used in order, keep a list of rxbuf[]
2227be107da9Spatrick * indices that should be filled with an mbuf, if possible.
2228be107da9Spatrick */
2229be107da9Spatrick void
mvpp2_rx_refill(struct mvpp2_port * sc)2230be107da9Spatrick mvpp2_rx_refill(struct mvpp2_port *sc)
2231be107da9Spatrick {
2232be107da9Spatrick struct mvpp2_bm_pool *bm;
2233be107da9Spatrick struct mvpp2_buf *rxb;
2234be107da9Spatrick uint64_t phys, virt;
2235be107da9Spatrick int pool;
2236be107da9Spatrick
2237be107da9Spatrick pool = curcpu()->ci_cpuid;
2238be107da9Spatrick KASSERT(pool < sc->sc->sc_npools);
2239be107da9Spatrick bm = &sc->sc->sc_bm_pools[pool];
2240be107da9Spatrick
224181fd8658Spatrick while (bm->freelist[bm->free_cons] != -1) {
2242be107da9Spatrick virt = bm->freelist[bm->free_cons];
2243be107da9Spatrick KASSERT(((virt >> 16) & 0xffff) == pool);
2244be107da9Spatrick KASSERT((virt & 0xffff) < MVPP2_BM_SIZE);
2245be107da9Spatrick rxb = &bm->rxbuf[virt & 0xffff];
2246be107da9Spatrick KASSERT(rxb->mb_m == NULL);
2247be107da9Spatrick
2248be107da9Spatrick rxb->mb_m = mvpp2_alloc_mbuf(sc->sc, rxb->mb_map);
2249be107da9Spatrick if (rxb->mb_m == NULL)
2250be107da9Spatrick break;
2251be107da9Spatrick
2252be107da9Spatrick bm->freelist[bm->free_cons] = -1;
2253be107da9Spatrick bm->free_cons = (bm->free_cons + 1) % MVPP2_BM_SIZE;
2254be107da9Spatrick
2255be107da9Spatrick phys = rxb->mb_map->dm_segs[0].ds_addr;
225613d9cc68Spatrick mvpp2_write(sc->sc, MVPP22_BM_ADDR_HIGH_RLS_REG,
2257be107da9Spatrick (((virt >> 32) & MVPP22_ADDR_HIGH_MASK)
225813d9cc68Spatrick << MVPP22_BM_ADDR_HIGH_VIRT_RLS_SHIFT) |
225913d9cc68Spatrick ((phys >> 32) & MVPP22_ADDR_HIGH_MASK));
2260be107da9Spatrick mvpp2_write(sc->sc, MVPP2_BM_VIRT_RLS_REG,
2261be107da9Spatrick virt & 0xffffffff);
2262be107da9Spatrick mvpp2_write(sc->sc, MVPP2_BM_PHY_RLS_REG(pool),
2263be107da9Spatrick phys & 0xffffffff);
2264be107da9Spatrick }
2265be107da9Spatrick }
2266be107da9Spatrick
22671a945772Spatrick void
mvpp2_up(struct mvpp2_port * sc)22681a945772Spatrick mvpp2_up(struct mvpp2_port *sc)
22691a945772Spatrick {
22701a945772Spatrick struct ifnet *ifp = &sc->sc_ac.ac_if;
22711a945772Spatrick int i;
22721a945772Spatrick
227388474739Skettenis if (sc->sc_sfp) {
227488474739Skettenis rw_enter(&mvpp2_sff_lock, RW_WRITE);
227588474739Skettenis sfp_enable(sc->sc_sfp);
227688474739Skettenis rw_exit(&mvpp2_sff_lock);
227788474739Skettenis }
227888474739Skettenis
227941cd246cSpatrick mvpp2_prs_mac_da_accept(sc, etherbroadcastaddr, 1);
2280ce595ab8Spatrick mvpp2_prs_mac_da_accept(sc, sc->sc_lladdr, 1);
22811a945772Spatrick mvpp2_prs_tag_mode_set(sc->sc, sc->sc_id, MVPP2_TAG_TYPE_MH);
22821a945772Spatrick mvpp2_prs_def_flow(sc);
22831a945772Spatrick
22841a945772Spatrick for (i = 0; i < sc->sc_ntxq; i++)
22851a945772Spatrick mvpp2_txq_hw_init(sc, &sc->sc_txqs[i]);
22861a945772Spatrick
22871a945772Spatrick mvpp2_tx_time_coal_set(sc, sc->sc_tx_time_coal);
22881a945772Spatrick
22891a945772Spatrick for (i = 0; i < sc->sc_nrxq; i++)
22901a945772Spatrick mvpp2_rxq_hw_init(sc, &sc->sc_rxqs[i]);
22911a945772Spatrick
22921a945772Spatrick /* FIXME: rx buffer fill */
22931a945772Spatrick
22941a945772Spatrick /* Configure media. */
22951a945772Spatrick if (LIST_FIRST(&sc->sc_mii.mii_phys))
22961a945772Spatrick mii_mediachg(&sc->sc_mii);
22971a945772Spatrick
22981a945772Spatrick /* Program promiscuous mode and multicast filters. */
22991a945772Spatrick mvpp2_iff(sc);
23001a945772Spatrick
23011a945772Spatrick ifp->if_flags |= IFF_RUNNING;
23021a945772Spatrick ifq_clr_oactive(&ifp->if_snd);
23031a945772Spatrick
23041a945772Spatrick mvpp2_txp_max_tx_size_set(sc);
23051a945772Spatrick
23061a945772Spatrick /* XXX: single vector */
23071a945772Spatrick mvpp2_write(sc->sc, MVPP2_ISR_RX_TX_MASK_REG(sc->sc_id),
23081a945772Spatrick MVPP2_CAUSE_RXQ_OCCUP_DESC_ALL_MASK |
23091a945772Spatrick MVPP2_CAUSE_TXQ_OCCUP_DESC_ALL_MASK |
23101a945772Spatrick MVPP2_CAUSE_MISC_SUM_MASK);
23111a945772Spatrick mvpp2_interrupts_enable(sc, (1 << 0));
23121a945772Spatrick
23131a945772Spatrick mvpp2_mac_config(sc);
23141a945772Spatrick mvpp2_egress_enable(sc);
23151a945772Spatrick mvpp2_ingress_enable(sc);
23161a945772Spatrick
23171a945772Spatrick timeout_add_sec(&sc->sc_tick, 1);
23181a945772Spatrick }
23191a945772Spatrick
23201a945772Spatrick void
mvpp2_aggr_txq_hw_init(struct mvpp2_softc * sc,struct mvpp2_tx_queue * txq)23211a945772Spatrick mvpp2_aggr_txq_hw_init(struct mvpp2_softc *sc, struct mvpp2_tx_queue *txq)
23221a945772Spatrick {
23231a945772Spatrick struct mvpp2_buf *txb;
23241a945772Spatrick int i;
23251a945772Spatrick
23261a945772Spatrick txq->ring = mvpp2_dmamem_alloc(sc,
23271a945772Spatrick MVPP2_AGGR_TXQ_SIZE * sizeof(struct mvpp2_tx_desc), 32);
23287262ae33Spatrick KASSERT(txq->ring != NULL);
23291a945772Spatrick txq->descs = MVPP2_DMA_KVA(txq->ring);
23301a945772Spatrick
23311a945772Spatrick txq->buf = mallocarray(MVPP2_AGGR_TXQ_SIZE, sizeof(struct mvpp2_buf),
23321a945772Spatrick M_DEVBUF, M_WAITOK);
23331a945772Spatrick
23341a945772Spatrick for (i = 0; i < MVPP2_AGGR_TXQ_SIZE; i++) {
23351a945772Spatrick txb = &txq->buf[i];
23361a945772Spatrick bus_dmamap_create(sc->sc_dmat, MCLBYTES, MVPP2_NTXSEGS,
23371a945772Spatrick MCLBYTES, 0, BUS_DMA_WAITOK, &txb->mb_map);
23381a945772Spatrick txb->mb_m = NULL;
23391a945772Spatrick }
23401a945772Spatrick
23411a945772Spatrick bus_dmamap_sync(sc->sc_dmat, MVPP2_DMA_MAP(txq->ring), 0,
23421a945772Spatrick MVPP2_DMA_LEN(txq->ring), BUS_DMASYNC_PREWRITE);
23431a945772Spatrick
23441a945772Spatrick txq->prod = mvpp2_read(sc, MVPP2_AGGR_TXQ_INDEX_REG(txq->id));
23451a945772Spatrick mvpp2_write(sc, MVPP2_AGGR_TXQ_DESC_ADDR_REG(txq->id),
23464d0a0269Spatrick MVPP2_DMA_DVA(txq->ring) >> MVPP22_DESC_ADDR_OFFS);
23471a945772Spatrick mvpp2_write(sc, MVPP2_AGGR_TXQ_DESC_SIZE_REG(txq->id),
23481a945772Spatrick MVPP2_AGGR_TXQ_SIZE);
23491a945772Spatrick }
23501a945772Spatrick
23511a945772Spatrick void
mvpp2_txq_hw_init(struct mvpp2_port * sc,struct mvpp2_tx_queue * txq)23521a945772Spatrick mvpp2_txq_hw_init(struct mvpp2_port *sc, struct mvpp2_tx_queue *txq)
23531a945772Spatrick {
23541a945772Spatrick struct mvpp2_buf *txb;
23551a945772Spatrick int desc, desc_per_txq;
23561a945772Spatrick uint32_t reg;
23571a945772Spatrick int i;
23581a945772Spatrick
235953d582d1Spatrick txq->prod = txq->cons = 0;
23601a945772Spatrick // txq->last_desc = txq->size - 1;
23611a945772Spatrick
23621a945772Spatrick txq->ring = mvpp2_dmamem_alloc(sc->sc,
23631a945772Spatrick MVPP2_NTXDESC * sizeof(struct mvpp2_tx_desc), 32);
23647262ae33Spatrick KASSERT(txq->ring != NULL);
23651a945772Spatrick txq->descs = MVPP2_DMA_KVA(txq->ring);
23661a945772Spatrick
23671a945772Spatrick txq->buf = mallocarray(MVPP2_NTXDESC, sizeof(struct mvpp2_buf),
23681a945772Spatrick M_DEVBUF, M_WAITOK);
23691a945772Spatrick
23701a945772Spatrick for (i = 0; i < MVPP2_NTXDESC; i++) {
23711a945772Spatrick txb = &txq->buf[i];
23721a945772Spatrick bus_dmamap_create(sc->sc_dmat, MCLBYTES, MVPP2_NTXSEGS,
23731a945772Spatrick MCLBYTES, 0, BUS_DMA_WAITOK, &txb->mb_map);
23741a945772Spatrick txb->mb_m = NULL;
23751a945772Spatrick }
23761a945772Spatrick
23771a945772Spatrick bus_dmamap_sync(sc->sc_dmat, MVPP2_DMA_MAP(txq->ring), 0,
23781a945772Spatrick MVPP2_DMA_LEN(txq->ring), BUS_DMASYNC_PREWRITE);
23791a945772Spatrick
23801a945772Spatrick mvpp2_write(sc->sc, MVPP2_TXQ_NUM_REG, txq->id);
23811a945772Spatrick mvpp2_write(sc->sc, MVPP2_TXQ_DESC_ADDR_REG,
23821a945772Spatrick MVPP2_DMA_DVA(txq->ring));
23831a945772Spatrick mvpp2_write(sc->sc, MVPP2_TXQ_DESC_SIZE_REG,
23841a945772Spatrick MVPP2_NTXDESC & MVPP2_TXQ_DESC_SIZE_MASK);
23851a945772Spatrick mvpp2_write(sc->sc, MVPP2_TXQ_INDEX_REG, 0);
23861a945772Spatrick mvpp2_write(sc->sc, MVPP2_TXQ_RSVD_CLR_REG,
23871a945772Spatrick txq->id << MVPP2_TXQ_RSVD_CLR_OFFSET);
23881a945772Spatrick reg = mvpp2_read(sc->sc, MVPP2_TXQ_PENDING_REG);
23891a945772Spatrick reg &= ~MVPP2_TXQ_PENDING_MASK;
23901a945772Spatrick mvpp2_write(sc->sc, MVPP2_TXQ_PENDING_REG, reg);
23911a945772Spatrick
23921a945772Spatrick desc_per_txq = 16;
23931a945772Spatrick desc = (sc->sc_id * MVPP2_MAX_TXQ * desc_per_txq) +
23941a945772Spatrick (txq->log_id * desc_per_txq);
23951a945772Spatrick
23961a945772Spatrick mvpp2_write(sc->sc, MVPP2_TXQ_PREF_BUF_REG,
23971a945772Spatrick MVPP2_PREF_BUF_PTR(desc) | MVPP2_PREF_BUF_SIZE_16 |
23981a945772Spatrick MVPP2_PREF_BUF_THRESH(desc_per_txq / 2));
23991a945772Spatrick
24001a945772Spatrick /* WRR / EJP configuration - indirect access */
24011a945772Spatrick mvpp2_write(sc->sc, MVPP2_TXP_SCHED_PORT_INDEX_REG,
24021a945772Spatrick mvpp2_egress_port(sc));
24031a945772Spatrick
24041a945772Spatrick reg = mvpp2_read(sc->sc, MVPP2_TXQ_SCHED_REFILL_REG(txq->log_id));
24051a945772Spatrick reg &= ~MVPP2_TXQ_REFILL_PERIOD_ALL_MASK;
24061a945772Spatrick reg |= MVPP2_TXQ_REFILL_PERIOD_MASK(1);
24071a945772Spatrick reg |= MVPP2_TXQ_REFILL_TOKENS_ALL_MASK;
24081a945772Spatrick mvpp2_write(sc->sc, MVPP2_TXQ_SCHED_REFILL_REG(txq->log_id), reg);
24091a945772Spatrick
24101a945772Spatrick mvpp2_write(sc->sc, MVPP2_TXQ_SCHED_TOKEN_SIZE_REG(txq->log_id),
24111a945772Spatrick MVPP2_TXQ_TOKEN_SIZE_MAX);
24121a945772Spatrick
24131a945772Spatrick mvpp2_tx_pkts_coal_set(sc, txq, txq->done_pkts_coal);
2414af1bab90Spatrick
2415af1bab90Spatrick mvpp2_read(sc->sc, MVPP2_TXQ_SENT_REG(txq->id));
24161a945772Spatrick }
24171a945772Spatrick
24181a945772Spatrick void
mvpp2_rxq_hw_init(struct mvpp2_port * sc,struct mvpp2_rx_queue * rxq)24191a945772Spatrick mvpp2_rxq_hw_init(struct mvpp2_port *sc, struct mvpp2_rx_queue *rxq)
24201a945772Spatrick {
24211a945772Spatrick rxq->prod = rxq->cons = 0;
24221a945772Spatrick
24231a945772Spatrick rxq->ring = mvpp2_dmamem_alloc(sc->sc,
24241a945772Spatrick MVPP2_NRXDESC * sizeof(struct mvpp2_rx_desc), 32);
24257262ae33Spatrick KASSERT(rxq->ring != NULL);
24261a945772Spatrick rxq->descs = MVPP2_DMA_KVA(rxq->ring);
24271a945772Spatrick
24281a945772Spatrick bus_dmamap_sync(sc->sc_dmat, MVPP2_DMA_MAP(rxq->ring),
24291a945772Spatrick 0, MVPP2_DMA_LEN(rxq->ring),
24301a945772Spatrick BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
24311a945772Spatrick
24321a945772Spatrick mvpp2_write(sc->sc, MVPP2_RXQ_STATUS_REG(rxq->id), 0);
24331a945772Spatrick mvpp2_write(sc->sc, MVPP2_RXQ_NUM_REG, rxq->id);
24341a945772Spatrick mvpp2_write(sc->sc, MVPP2_RXQ_DESC_ADDR_REG,
24354d0a0269Spatrick MVPP2_DMA_DVA(rxq->ring) >> MVPP22_DESC_ADDR_OFFS);
24361a945772Spatrick mvpp2_write(sc->sc, MVPP2_RXQ_DESC_SIZE_REG, MVPP2_NRXDESC);
24371a945772Spatrick mvpp2_write(sc->sc, MVPP2_RXQ_INDEX_REG, 0);
24381a945772Spatrick mvpp2_rxq_offset_set(sc, rxq->id, 0);
24391a945772Spatrick mvpp2_rx_pkts_coal_set(sc, rxq, rxq->pkts_coal);
24401a945772Spatrick mvpp2_rx_time_coal_set(sc, rxq, rxq->time_coal);
24411a945772Spatrick mvpp2_rxq_status_update(sc, rxq->id, 0, MVPP2_NRXDESC);
24421a945772Spatrick }
24431a945772Spatrick
24441a945772Spatrick void
mvpp2_mac_reset_assert(struct mvpp2_port * sc)2445c56f4c70Spatrick mvpp2_mac_reset_assert(struct mvpp2_port *sc)
24461a945772Spatrick {
24471a945772Spatrick mvpp2_gmac_write(sc, MVPP2_PORT_CTRL2_REG,
24481a945772Spatrick mvpp2_gmac_read(sc, MVPP2_PORT_CTRL2_REG) |
24494d0a0269Spatrick MVPP2_PORT_CTRL2_PORTMACRESET);
2450c56f4c70Spatrick if (sc->sc_gop_id == 0)
24511a945772Spatrick mvpp2_xlg_write(sc, MV_XLG_PORT_MAC_CTRL0_REG,
24521a945772Spatrick mvpp2_xlg_read(sc, MV_XLG_PORT_MAC_CTRL0_REG) &
24534d0a0269Spatrick ~MV_XLG_MAC_CTRL0_MACRESETN);
2454c56f4c70Spatrick }
2455c56f4c70Spatrick
2456c56f4c70Spatrick void
mvpp2_pcs_reset_assert(struct mvpp2_port * sc)2457c56f4c70Spatrick mvpp2_pcs_reset_assert(struct mvpp2_port *sc)
2458c56f4c70Spatrick {
2459c56f4c70Spatrick uint32_t reg;
2460c56f4c70Spatrick
2461c56f4c70Spatrick if (sc->sc_gop_id != 0)
2462c56f4c70Spatrick return;
2463c56f4c70Spatrick
24641a945772Spatrick reg = mvpp2_mpcs_read(sc, MVPP22_MPCS_CLOCK_RESET);
24654d0a0269Spatrick reg |= MVPP22_MPCS_CLK_DIV_PHASE_SET;
24664d0a0269Spatrick reg &= ~MVPP22_MPCS_TX_SD_CLK_RESET;
24674d0a0269Spatrick reg &= ~MVPP22_MPCS_RX_SD_CLK_RESET;
24684d0a0269Spatrick reg &= ~MVPP22_MPCS_MAC_CLK_RESET;
24691a945772Spatrick mvpp2_mpcs_write(sc, MVPP22_MPCS_CLOCK_RESET, reg);
247009e5d825Spatrick reg = mvpp2_xpcs_read(sc, MVPP22_XPCS_GLOBAL_CFG_0_REG);
247109e5d825Spatrick reg &= ~MVPP22_XPCS_PCSRESET;
247209e5d825Spatrick mvpp2_xpcs_write(sc, MVPP22_XPCS_GLOBAL_CFG_0_REG, reg);
24731a945772Spatrick }
24741a945772Spatrick
2475c56f4c70Spatrick void
mvpp2_pcs_reset_deassert(struct mvpp2_port * sc)2476c56f4c70Spatrick mvpp2_pcs_reset_deassert(struct mvpp2_port *sc)
2477c56f4c70Spatrick {
2478c56f4c70Spatrick uint32_t reg;
247909e5d825Spatrick
2480c56f4c70Spatrick if (sc->sc_gop_id != 0)
2481c56f4c70Spatrick return;
2482c56f4c70Spatrick
24831a945772Spatrick if (sc->sc_phy_mode == PHY_MODE_10GBASER) {
24841a945772Spatrick reg = mvpp2_mpcs_read(sc, MVPP22_MPCS_CLOCK_RESET);
24854d0a0269Spatrick reg &= ~MVPP22_MPCS_CLK_DIV_PHASE_SET;
24864d0a0269Spatrick reg |= MVPP22_MPCS_TX_SD_CLK_RESET;
24874d0a0269Spatrick reg |= MVPP22_MPCS_RX_SD_CLK_RESET;
24884d0a0269Spatrick reg |= MVPP22_MPCS_MAC_CLK_RESET;
24891a945772Spatrick mvpp2_mpcs_write(sc, MVPP22_MPCS_CLOCK_RESET, reg);
249009e5d825Spatrick } else if (sc->sc_phy_mode == PHY_MODE_XAUI) {
249109e5d825Spatrick reg = mvpp2_xpcs_read(sc, MVPP22_XPCS_GLOBAL_CFG_0_REG);
249209e5d825Spatrick reg |= MVPP22_XPCS_PCSRESET;
249309e5d825Spatrick mvpp2_xpcs_write(sc, MVPP22_XPCS_GLOBAL_CFG_0_REG, reg);
249409e5d825Spatrick }
2495c56f4c70Spatrick }
24961a945772Spatrick
2497c56f4c70Spatrick void
mvpp2_mac_config(struct mvpp2_port * sc)2498c56f4c70Spatrick mvpp2_mac_config(struct mvpp2_port *sc)
2499c56f4c70Spatrick {
2500c56f4c70Spatrick uint32_t reg;
2501c56f4c70Spatrick
2502c56f4c70Spatrick reg = mvpp2_gmac_read(sc, MVPP2_GMAC_AUTONEG_CONFIG);
2503c56f4c70Spatrick reg &= ~MVPP2_GMAC_FORCE_LINK_PASS;
2504c56f4c70Spatrick reg |= MVPP2_GMAC_FORCE_LINK_DOWN;
2505c56f4c70Spatrick mvpp2_gmac_write(sc, MVPP2_GMAC_AUTONEG_CONFIG, reg);
2506c56f4c70Spatrick if (sc->sc_gop_id == 0) {
2507c56f4c70Spatrick reg = mvpp2_xlg_read(sc, MV_XLG_PORT_MAC_CTRL0_REG);
2508c56f4c70Spatrick reg &= ~MV_XLG_MAC_CTRL0_FORCELINKPASS;
2509c56f4c70Spatrick reg |= MV_XLG_MAC_CTRL0_FORCELINKDOWN;
2510c56f4c70Spatrick mvpp2_xlg_write(sc, MV_XLG_PORT_MAC_CTRL0_REG, reg);
2511c56f4c70Spatrick }
2512c56f4c70Spatrick
2513c56f4c70Spatrick mvpp2_port_disable(sc);
2514c56f4c70Spatrick
251595237283Skettenis mvpp2_mac_reset_assert(sc);
251695237283Skettenis mvpp2_pcs_reset_assert(sc);
251795237283Skettenis
2518c56f4c70Spatrick mvpp2_gop_intr_mask(sc);
2519c56f4c70Spatrick mvpp2_comphy_config(sc, 0);
2520c56f4c70Spatrick
2521c56f4c70Spatrick if (sc->sc_gop_id == 0 && (sc->sc_phy_mode == PHY_MODE_10GBASER ||
2522c56f4c70Spatrick sc->sc_phy_mode == PHY_MODE_XAUI))
2523c56f4c70Spatrick mvpp2_xlg_config(sc);
2524c56f4c70Spatrick else
2525c56f4c70Spatrick mvpp2_gmac_config(sc);
2526c56f4c70Spatrick
2527c56f4c70Spatrick mvpp2_comphy_config(sc, 1);
2528c56f4c70Spatrick mvpp2_gop_config(sc);
2529c56f4c70Spatrick
2530c56f4c70Spatrick mvpp2_pcs_reset_deassert(sc);
2531c56f4c70Spatrick
2532c56f4c70Spatrick if (sc->sc_gop_id == 0) {
25331a945772Spatrick reg = mvpp2_xlg_read(sc, MV_XLG_PORT_MAC_CTRL3_REG);
25341a945772Spatrick reg &= ~MV_XLG_MAC_CTRL3_MACMODESELECT_MASK;
25351a945772Spatrick if (sc->sc_phy_mode == PHY_MODE_10GBASER ||
25361a945772Spatrick sc->sc_phy_mode == PHY_MODE_XAUI)
25371a945772Spatrick reg |= MV_XLG_MAC_CTRL3_MACMODESELECT_10G;
25381a945772Spatrick else
25391a945772Spatrick reg |= MV_XLG_MAC_CTRL3_MACMODESELECT_GMAC;
25401a945772Spatrick mvpp2_xlg_write(sc, MV_XLG_PORT_MAC_CTRL3_REG, reg);
25411a945772Spatrick }
25421a945772Spatrick
25431a945772Spatrick if (sc->sc_gop_id == 0 && (sc->sc_phy_mode == PHY_MODE_10GBASER ||
25441a945772Spatrick sc->sc_phy_mode == PHY_MODE_XAUI)) {
25451a945772Spatrick reg = mvpp2_xlg_read(sc, MV_XLG_PORT_MAC_CTRL1_REG);
25461a945772Spatrick reg &= ~MV_XLG_MAC_CTRL1_FRAMESIZELIMIT_MASK;
25471a945772Spatrick reg |= ((MCLBYTES - MVPP2_MH_SIZE) / 2) <<
25481a945772Spatrick MV_XLG_MAC_CTRL1_FRAMESIZELIMIT_OFFS;
25491a945772Spatrick mvpp2_xlg_write(sc, MV_XLG_PORT_MAC_CTRL1_REG, reg);
25501a945772Spatrick } else {
25511a945772Spatrick reg = mvpp2_gmac_read(sc, MVPP2_GMAC_CTRL_0_REG);
25521a945772Spatrick reg &= ~MVPP2_GMAC_MAX_RX_SIZE_MASK;
25531a945772Spatrick reg |= ((MCLBYTES - MVPP2_MH_SIZE) / 2) <<
25541a945772Spatrick MVPP2_GMAC_MAX_RX_SIZE_OFFS;
25551a945772Spatrick mvpp2_gmac_write(sc, MVPP2_GMAC_CTRL_0_REG, reg);
25561a945772Spatrick }
25571a945772Spatrick
2558c56f4c70Spatrick mvpp2_gop_intr_unmask(sc);
2559c56f4c70Spatrick
2560c56f4c70Spatrick if (!(sc->sc_phy_mode == PHY_MODE_10GBASER ||
2561c56f4c70Spatrick sc->sc_phy_mode == PHY_MODE_XAUI)) {
2562c56f4c70Spatrick mvpp2_gmac_write(sc, MVPP2_PORT_CTRL2_REG,
2563c56f4c70Spatrick mvpp2_gmac_read(sc, MVPP2_PORT_CTRL2_REG) &
2564c56f4c70Spatrick ~MVPP2_PORT_CTRL2_PORTMACRESET);
2565c56f4c70Spatrick while (mvpp2_gmac_read(sc, MVPP2_PORT_CTRL2_REG) &
2566c56f4c70Spatrick MVPP2_PORT_CTRL2_PORTMACRESET)
2567c56f4c70Spatrick ;
2568c56f4c70Spatrick }
25691a945772Spatrick
25701a945772Spatrick mvpp2_port_enable(sc);
2571c56f4c70Spatrick
2572c56f4c70Spatrick if (sc->sc_inband_status) {
2573c56f4c70Spatrick reg = mvpp2_gmac_read(sc, MVPP2_GMAC_AUTONEG_CONFIG);
2574c56f4c70Spatrick reg &= ~MVPP2_GMAC_FORCE_LINK_PASS;
2575c56f4c70Spatrick reg &= ~MVPP2_GMAC_FORCE_LINK_DOWN;
2576c56f4c70Spatrick mvpp2_gmac_write(sc, MVPP2_GMAC_AUTONEG_CONFIG, reg);
2577c56f4c70Spatrick if (sc->sc_gop_id == 0) {
2578c56f4c70Spatrick reg = mvpp2_xlg_read(sc, MV_XLG_PORT_MAC_CTRL0_REG);
2579c56f4c70Spatrick reg &= ~MV_XLG_MAC_CTRL0_FORCELINKPASS;
2580c56f4c70Spatrick reg &= ~MV_XLG_MAC_CTRL0_FORCELINKDOWN;
2581c56f4c70Spatrick mvpp2_xlg_write(sc, MV_XLG_PORT_MAC_CTRL0_REG, reg);
2582c56f4c70Spatrick }
2583c56f4c70Spatrick } else
2584c56f4c70Spatrick mvpp2_port_change(sc);
25851a945772Spatrick }
25861a945772Spatrick
25871a945772Spatrick void
mvpp2_xlg_config(struct mvpp2_port * sc)25881a945772Spatrick mvpp2_xlg_config(struct mvpp2_port *sc)
25891a945772Spatrick {
25901a945772Spatrick uint32_t ctl0, ctl4;
25911a945772Spatrick
25921a945772Spatrick ctl0 = mvpp2_xlg_read(sc, MV_XLG_PORT_MAC_CTRL0_REG);
25931a945772Spatrick ctl4 = mvpp2_xlg_read(sc, MV_XLG_PORT_MAC_CTRL4_REG);
25941a945772Spatrick
25954d0a0269Spatrick ctl0 |= MV_XLG_MAC_CTRL0_MACRESETN;
25961a945772Spatrick ctl4 &= ~MV_XLG_MAC_CTRL4_EN_IDLE_CHECK_FOR_LINK;
25974d0a0269Spatrick ctl4 |= MV_XLG_MAC_CTRL4_FORWARD_PFC_EN;
25984d0a0269Spatrick ctl4 |= MV_XLG_MAC_CTRL4_FORWARD_802_3X_FC_EN;
25991a945772Spatrick
26001a945772Spatrick mvpp2_xlg_write(sc, MV_XLG_PORT_MAC_CTRL0_REG, ctl0);
2601256d46b8Sjsg mvpp2_xlg_write(sc, MV_XLG_PORT_MAC_CTRL4_REG, ctl4);
26021a945772Spatrick
26031a945772Spatrick /* Port reset */
26041a945772Spatrick while ((mvpp2_xlg_read(sc, MV_XLG_PORT_MAC_CTRL0_REG) &
26054d0a0269Spatrick MV_XLG_MAC_CTRL0_MACRESETN) == 0)
26061a945772Spatrick ;
26071a945772Spatrick }
26081a945772Spatrick
26091a945772Spatrick void
mvpp2_gmac_config(struct mvpp2_port * sc)26101a945772Spatrick mvpp2_gmac_config(struct mvpp2_port *sc)
26111a945772Spatrick {
26121a945772Spatrick uint32_t ctl0, ctl2, ctl4, panc;
26131a945772Spatrick
26141a945772Spatrick /* Setup phy. */
26151a945772Spatrick ctl0 = mvpp2_gmac_read(sc, MVPP2_PORT_CTRL0_REG);
26161a945772Spatrick ctl2 = mvpp2_gmac_read(sc, MVPP2_PORT_CTRL2_REG);
26171a945772Spatrick ctl4 = mvpp2_gmac_read(sc, MVPP2_PORT_CTRL4_REG);
26181a945772Spatrick panc = mvpp2_gmac_read(sc, MVPP2_GMAC_AUTONEG_CONFIG);
26191a945772Spatrick
26201a945772Spatrick ctl0 &= ~MVPP2_GMAC_PORT_TYPE_MASK;
26211a945772Spatrick ctl2 &= ~(MVPP2_GMAC_PORT_RESET_MASK | MVPP2_GMAC_PCS_ENABLE_MASK |
26221a945772Spatrick MVPP2_GMAC_INBAND_AN_MASK);
26231a945772Spatrick panc &= ~(MVPP2_GMAC_AN_DUPLEX_EN | MVPP2_GMAC_FLOW_CTRL_AUTONEG |
26241a945772Spatrick MVPP2_GMAC_FC_ADV_ASM_EN | MVPP2_GMAC_FC_ADV_EN |
26251a945772Spatrick MVPP2_GMAC_AN_SPEED_EN | MVPP2_GMAC_IN_BAND_AUTONEG_BYPASS |
26261a945772Spatrick MVPP2_GMAC_IN_BAND_AUTONEG);
26271a945772Spatrick
26281a945772Spatrick switch (sc->sc_phy_mode) {
26291a945772Spatrick case PHY_MODE_XAUI:
26301a945772Spatrick case PHY_MODE_10GBASER:
26311a945772Spatrick break;
26321a945772Spatrick case PHY_MODE_2500BASEX:
26331a945772Spatrick case PHY_MODE_1000BASEX:
26341a945772Spatrick ctl2 |= MVPP2_GMAC_PCS_ENABLE_MASK;
26354d0a0269Spatrick ctl4 &= ~MVPP2_PORT_CTRL4_EXT_PIN_GMII_SEL;
26364d0a0269Spatrick ctl4 |= MVPP2_PORT_CTRL4_SYNC_BYPASS;
26374d0a0269Spatrick ctl4 |= MVPP2_PORT_CTRL4_DP_CLK_SEL;
26384d0a0269Spatrick ctl4 |= MVPP2_PORT_CTRL4_QSGMII_BYPASS_ACTIVE;
26391a945772Spatrick break;
26401a945772Spatrick case PHY_MODE_SGMII:
26411a945772Spatrick ctl2 |= MVPP2_GMAC_PCS_ENABLE_MASK;
26421a945772Spatrick ctl2 |= MVPP2_GMAC_INBAND_AN_MASK;
26434d0a0269Spatrick ctl4 &= ~MVPP2_PORT_CTRL4_EXT_PIN_GMII_SEL;
26444d0a0269Spatrick ctl4 |= MVPP2_PORT_CTRL4_SYNC_BYPASS;
26454d0a0269Spatrick ctl4 |= MVPP2_PORT_CTRL4_DP_CLK_SEL;
26464d0a0269Spatrick ctl4 |= MVPP2_PORT_CTRL4_QSGMII_BYPASS_ACTIVE;
26471a945772Spatrick break;
26481a945772Spatrick case PHY_MODE_RGMII:
26491a945772Spatrick case PHY_MODE_RGMII_ID:
26501a945772Spatrick case PHY_MODE_RGMII_RXID:
26511a945772Spatrick case PHY_MODE_RGMII_TXID:
26524d0a0269Spatrick ctl4 &= ~MVPP2_PORT_CTRL4_DP_CLK_SEL;
26534d0a0269Spatrick ctl4 |= MVPP2_PORT_CTRL4_EXT_PIN_GMII_SEL;
26544d0a0269Spatrick ctl4 |= MVPP2_PORT_CTRL4_SYNC_BYPASS;
26554d0a0269Spatrick ctl4 |= MVPP2_PORT_CTRL4_QSGMII_BYPASS_ACTIVE;
26561a945772Spatrick break;
26571a945772Spatrick }
26581a945772Spatrick
26591a945772Spatrick /* Use Auto-Negotiation for Inband Status only */
26601a945772Spatrick if (sc->sc_inband_status) {
26611a945772Spatrick panc &= ~MVPP2_GMAC_CONFIG_MII_SPEED;
26621a945772Spatrick panc &= ~MVPP2_GMAC_CONFIG_GMII_SPEED;
26631a945772Spatrick panc &= ~MVPP2_GMAC_CONFIG_FULL_DUPLEX;
26641a945772Spatrick panc |= MVPP2_GMAC_IN_BAND_AUTONEG;
26651a945772Spatrick /* TODO: read mode from SFP */
2666c56f4c70Spatrick if (sc->sc_phy_mode == PHY_MODE_SGMII) {
2667c56f4c70Spatrick /* SGMII */
2668c56f4c70Spatrick panc |= MVPP2_GMAC_AN_SPEED_EN;
2669c56f4c70Spatrick panc |= MVPP2_GMAC_AN_DUPLEX_EN;
2670c56f4c70Spatrick } else {
26711a945772Spatrick /* 802.3z */
26721a945772Spatrick ctl0 |= MVPP2_GMAC_PORT_TYPE_MASK;
26731a945772Spatrick panc |= MVPP2_GMAC_CONFIG_GMII_SPEED;
26741a945772Spatrick panc |= MVPP2_GMAC_CONFIG_FULL_DUPLEX;
26751a945772Spatrick }
26761a945772Spatrick }
26771a945772Spatrick
26781a945772Spatrick mvpp2_gmac_write(sc, MVPP2_PORT_CTRL0_REG, ctl0);
26791a945772Spatrick mvpp2_gmac_write(sc, MVPP2_PORT_CTRL2_REG, ctl2);
26801a945772Spatrick mvpp2_gmac_write(sc, MVPP2_PORT_CTRL4_REG, ctl4);
26811a945772Spatrick mvpp2_gmac_write(sc, MVPP2_GMAC_AUTONEG_CONFIG, panc);
26821a945772Spatrick }
26831a945772Spatrick
268409e5d825Spatrick #define COMPHY_BASE 0x120000
268509e5d825Spatrick #define COMPHY_SIP_POWER_ON 0x82000001
268609e5d825Spatrick #define COMPHY_SIP_POWER_OFF 0x82000002
268709e5d825Spatrick #define COMPHY_SPEED(x) ((x) << 2)
268809e5d825Spatrick #define COMPHY_SPEED_1_25G 0 /* SGMII 1G */
268909e5d825Spatrick #define COMPHY_SPEED_2_5G 1
269009e5d825Spatrick #define COMPHY_SPEED_3_125G 2 /* SGMII 2.5G */
269109e5d825Spatrick #define COMPHY_SPEED_5G 3
269209e5d825Spatrick #define COMPHY_SPEED_5_15625G 4 /* XFI 5G */
269309e5d825Spatrick #define COMPHY_SPEED_6G 5
269409e5d825Spatrick #define COMPHY_SPEED_10_3125G 6 /* XFI 10G */
269509e5d825Spatrick #define COMPHY_UNIT(x) ((x) << 8)
269609e5d825Spatrick #define COMPHY_MODE(x) ((x) << 12)
269709e5d825Spatrick #define COMPHY_MODE_SATA 1
269809e5d825Spatrick #define COMPHY_MODE_SGMII 2 /* SGMII 1G */
269909e5d825Spatrick #define COMPHY_MODE_HS_SGMII 3 /* SGMII 2.5G */
270009e5d825Spatrick #define COMPHY_MODE_USB3H 4
270109e5d825Spatrick #define COMPHY_MODE_USB3D 5
270209e5d825Spatrick #define COMPHY_MODE_PCIE 6
270309e5d825Spatrick #define COMPHY_MODE_RXAUI 7
270409e5d825Spatrick #define COMPHY_MODE_XFI 8
270509e5d825Spatrick #define COMPHY_MODE_SFI 9
270609e5d825Spatrick #define COMPHY_MODE_USB3 10
270709e5d825Spatrick #define COMPHY_MODE_AP 11
270809e5d825Spatrick
270909e5d825Spatrick void
mvpp2_comphy_config(struct mvpp2_port * sc,int on)2710c56f4c70Spatrick mvpp2_comphy_config(struct mvpp2_port *sc, int on)
271109e5d825Spatrick {
271209e5d825Spatrick int node, phys[2], lane, unit;
271309e5d825Spatrick uint32_t mode;
271409e5d825Spatrick
271509e5d825Spatrick if (OF_getpropintarray(sc->sc_node, "phys", phys, sizeof(phys)) !=
271609e5d825Spatrick sizeof(phys))
271709e5d825Spatrick return;
271809e5d825Spatrick node = OF_getnodebyphandle(phys[0]);
271909e5d825Spatrick if (!node)
272009e5d825Spatrick return;
272109e5d825Spatrick
272209e5d825Spatrick lane = OF_getpropint(node, "reg", 0);
272309e5d825Spatrick unit = phys[1];
272409e5d825Spatrick
272509e5d825Spatrick switch (sc->sc_phy_mode) {
272609e5d825Spatrick case PHY_MODE_XAUI:
272709e5d825Spatrick mode = COMPHY_MODE(COMPHY_MODE_RXAUI) |
272809e5d825Spatrick COMPHY_UNIT(unit);
272909e5d825Spatrick break;
273009e5d825Spatrick case PHY_MODE_10GBASER:
273109e5d825Spatrick mode = COMPHY_MODE(COMPHY_MODE_XFI) |
273209e5d825Spatrick COMPHY_SPEED(COMPHY_SPEED_10_3125G) |
273309e5d825Spatrick COMPHY_UNIT(unit);
273409e5d825Spatrick break;
273509e5d825Spatrick case PHY_MODE_2500BASEX:
273609e5d825Spatrick mode = COMPHY_MODE(COMPHY_MODE_HS_SGMII) |
273709e5d825Spatrick COMPHY_SPEED(COMPHY_SPEED_3_125G) |
273809e5d825Spatrick COMPHY_UNIT(unit);
273909e5d825Spatrick break;
274009e5d825Spatrick case PHY_MODE_1000BASEX:
274109e5d825Spatrick case PHY_MODE_SGMII:
274209e5d825Spatrick mode = COMPHY_MODE(COMPHY_MODE_SGMII) |
274309e5d825Spatrick COMPHY_SPEED(COMPHY_SPEED_1_25G) |
274409e5d825Spatrick COMPHY_UNIT(unit);
274509e5d825Spatrick break;
274609e5d825Spatrick default:
274709e5d825Spatrick return;
274809e5d825Spatrick }
274909e5d825Spatrick
2750c56f4c70Spatrick if (on)
275109e5d825Spatrick smc_call(COMPHY_SIP_POWER_ON, sc->sc->sc_ioh_paddr + COMPHY_BASE,
275209e5d825Spatrick lane, mode);
2753c56f4c70Spatrick else
2754c56f4c70Spatrick smc_call(COMPHY_SIP_POWER_OFF, sc->sc->sc_ioh_paddr + COMPHY_BASE,
2755c56f4c70Spatrick lane, 0);
275609e5d825Spatrick }
275709e5d825Spatrick
275809e5d825Spatrick void
mvpp2_gop_config(struct mvpp2_port * sc)275909e5d825Spatrick mvpp2_gop_config(struct mvpp2_port *sc)
276009e5d825Spatrick {
276109e5d825Spatrick uint32_t reg;
276209e5d825Spatrick
276309e5d825Spatrick if (sc->sc->sc_rm == NULL)
276409e5d825Spatrick return;
276509e5d825Spatrick
276609e5d825Spatrick if (sc->sc_phy_mode == PHY_MODE_RGMII ||
276709e5d825Spatrick sc->sc_phy_mode == PHY_MODE_RGMII_ID ||
276809e5d825Spatrick sc->sc_phy_mode == PHY_MODE_RGMII_RXID ||
276909e5d825Spatrick sc->sc_phy_mode == PHY_MODE_RGMII_TXID) {
277009e5d825Spatrick if (sc->sc_gop_id == 0)
277109e5d825Spatrick return;
277209e5d825Spatrick reg = regmap_read_4(sc->sc->sc_rm, GENCONF_PORT_CTRL0);
277309e5d825Spatrick reg |= GENCONF_PORT_CTRL0_BUS_WIDTH_SELECT;
277409e5d825Spatrick regmap_write_4(sc->sc->sc_rm, GENCONF_PORT_CTRL0, reg);
277509e5d825Spatrick reg = regmap_read_4(sc->sc->sc_rm, GENCONF_CTRL0);
277609e5d825Spatrick if (sc->sc_gop_id == 2)
277709e5d825Spatrick reg |= GENCONF_CTRL0_PORT0_RGMII |
277809e5d825Spatrick GENCONF_CTRL0_PORT1_RGMII;
277909e5d825Spatrick else if (sc->sc_gop_id == 3)
278009e5d825Spatrick reg |= GENCONF_CTRL0_PORT1_RGMII_MII;
278109e5d825Spatrick regmap_write_4(sc->sc->sc_rm, GENCONF_CTRL0, reg);
278209e5d825Spatrick } else if (sc->sc_phy_mode == PHY_MODE_2500BASEX ||
278309e5d825Spatrick sc->sc_phy_mode == PHY_MODE_1000BASEX ||
278409e5d825Spatrick sc->sc_phy_mode == PHY_MODE_SGMII) {
278509e5d825Spatrick reg = regmap_read_4(sc->sc->sc_rm, GENCONF_PORT_CTRL0);
278609e5d825Spatrick reg |= GENCONF_PORT_CTRL0_BUS_WIDTH_SELECT |
278709e5d825Spatrick GENCONF_PORT_CTRL0_RX_DATA_SAMPLE;
278809e5d825Spatrick regmap_write_4(sc->sc->sc_rm, GENCONF_PORT_CTRL0, reg);
278909e5d825Spatrick if (sc->sc_gop_id > 1) {
279009e5d825Spatrick reg = regmap_read_4(sc->sc->sc_rm, GENCONF_CTRL0);
279109e5d825Spatrick if (sc->sc_gop_id == 2)
279209e5d825Spatrick reg &= ~GENCONF_CTRL0_PORT0_RGMII;
279309e5d825Spatrick else if (sc->sc_gop_id == 3)
279409e5d825Spatrick reg &= ~GENCONF_CTRL0_PORT1_RGMII_MII;
279509e5d825Spatrick regmap_write_4(sc->sc->sc_rm, GENCONF_CTRL0, reg);
279609e5d825Spatrick }
279709e5d825Spatrick } else if (sc->sc_phy_mode == PHY_MODE_10GBASER) {
279809e5d825Spatrick if (sc->sc_gop_id != 0)
279909e5d825Spatrick return;
280009e5d825Spatrick reg = mvpp2_xpcs_read(sc, MVPP22_XPCS_GLOBAL_CFG_0_REG);
280109e5d825Spatrick reg &= ~MVPP22_XPCS_PCSMODE_MASK;
280209e5d825Spatrick reg &= ~MVPP22_XPCS_LANEACTIVE_MASK;
280309e5d825Spatrick reg |= 2 << MVPP22_XPCS_LANEACTIVE_OFFS;
280409e5d825Spatrick mvpp2_xpcs_write(sc, MVPP22_XPCS_GLOBAL_CFG_0_REG, reg);
280509e5d825Spatrick reg = mvpp2_mpcs_read(sc, MVPP22_MPCS40G_COMMON_CONTROL);
280609e5d825Spatrick reg &= ~MVPP22_MPCS_FORWARD_ERROR_CORRECTION_MASK;
280709e5d825Spatrick mvpp2_mpcs_write(sc, MVPP22_MPCS40G_COMMON_CONTROL, reg);
280809e5d825Spatrick reg = mvpp2_mpcs_read(sc, MVPP22_MPCS_CLOCK_RESET);
280909e5d825Spatrick reg &= ~MVPP22_MPCS_CLK_DIVISION_RATIO_MASK;
281009e5d825Spatrick reg |= MVPP22_MPCS_CLK_DIVISION_RATIO_DEFAULT;
281109e5d825Spatrick mvpp2_mpcs_write(sc, MVPP22_MPCS_CLOCK_RESET, reg);
281209e5d825Spatrick } else
281309e5d825Spatrick return;
281409e5d825Spatrick
281509e5d825Spatrick reg = regmap_read_4(sc->sc->sc_rm, GENCONF_PORT_CTRL1);
281609e5d825Spatrick reg |= GENCONF_PORT_CTRL1_RESET(sc->sc_gop_id) |
281709e5d825Spatrick GENCONF_PORT_CTRL1_EN(sc->sc_gop_id);
281809e5d825Spatrick regmap_write_4(sc->sc->sc_rm, GENCONF_PORT_CTRL1, reg);
281909e5d825Spatrick
282009e5d825Spatrick reg = regmap_read_4(sc->sc->sc_rm, GENCONF_PORT_CTRL0);
282109e5d825Spatrick reg |= GENCONF_PORT_CTRL0_CLK_DIV_PHASE_CLR;
282209e5d825Spatrick regmap_write_4(sc->sc->sc_rm, GENCONF_PORT_CTRL0, reg);
282309e5d825Spatrick
282409e5d825Spatrick reg = regmap_read_4(sc->sc->sc_rm, GENCONF_SOFT_RESET1);
282509e5d825Spatrick reg |= GENCONF_SOFT_RESET1_GOP;
282609e5d825Spatrick regmap_write_4(sc->sc->sc_rm, GENCONF_SOFT_RESET1, reg);
282709e5d825Spatrick }
282809e5d825Spatrick
28291a945772Spatrick void
mvpp2_gop_intr_mask(struct mvpp2_port * sc)2830c56f4c70Spatrick mvpp2_gop_intr_mask(struct mvpp2_port *sc)
2831c56f4c70Spatrick {
2832c56f4c70Spatrick uint32_t reg;
2833c56f4c70Spatrick
2834c56f4c70Spatrick if (sc->sc_gop_id == 0) {
2835c56f4c70Spatrick reg = mvpp2_xlg_read(sc, MV_XLG_EXTERNAL_INTERRUPT_MASK_REG);
2836c56f4c70Spatrick reg &= ~MV_XLG_EXTERNAL_INTERRUPT_LINK_CHANGE_XLG;
2837c56f4c70Spatrick reg &= ~MV_XLG_EXTERNAL_INTERRUPT_LINK_CHANGE_GIG;
2838c56f4c70Spatrick mvpp2_xlg_write(sc, MV_XLG_EXTERNAL_INTERRUPT_MASK_REG, reg);
2839c56f4c70Spatrick }
2840c56f4c70Spatrick
2841c56f4c70Spatrick reg = mvpp2_gmac_read(sc, MVPP2_GMAC_INT_SUM_MASK_REG);
2842c56f4c70Spatrick reg &= ~MVPP2_GMAC_INT_SUM_CAUSE_LINK_CHANGE;
2843c56f4c70Spatrick mvpp2_gmac_write(sc, MVPP2_GMAC_INT_SUM_MASK_REG, reg);
2844c56f4c70Spatrick }
2845c56f4c70Spatrick
2846c56f4c70Spatrick void
mvpp2_gop_intr_unmask(struct mvpp2_port * sc)2847c56f4c70Spatrick mvpp2_gop_intr_unmask(struct mvpp2_port *sc)
2848c56f4c70Spatrick {
2849c56f4c70Spatrick uint32_t reg;
2850c56f4c70Spatrick
2851c56f4c70Spatrick reg = mvpp2_gmac_read(sc, MVPP2_GMAC_INT_SUM_MASK_REG);
2852c56f4c70Spatrick reg |= MVPP2_GMAC_INT_SUM_CAUSE_LINK_CHANGE;
2853c56f4c70Spatrick mvpp2_gmac_write(sc, MVPP2_GMAC_INT_SUM_MASK_REG, reg);
2854c56f4c70Spatrick
2855c56f4c70Spatrick if (sc->sc_gop_id == 0) {
2856c56f4c70Spatrick reg = mvpp2_xlg_read(sc, MV_XLG_EXTERNAL_INTERRUPT_MASK_REG);
2857c56f4c70Spatrick if (sc->sc_phy_mode == PHY_MODE_10GBASER ||
2858c56f4c70Spatrick sc->sc_phy_mode == PHY_MODE_XAUI)
2859c56f4c70Spatrick reg |= MV_XLG_EXTERNAL_INTERRUPT_LINK_CHANGE_XLG;
2860c56f4c70Spatrick else
2861c56f4c70Spatrick reg |= MV_XLG_EXTERNAL_INTERRUPT_LINK_CHANGE_GIG;
2862c56f4c70Spatrick mvpp2_xlg_write(sc, MV_XLG_EXTERNAL_INTERRUPT_MASK_REG, reg);
2863c56f4c70Spatrick }
2864c56f4c70Spatrick }
2865c56f4c70Spatrick
2866c56f4c70Spatrick void
mvpp2_down(struct mvpp2_port * sc)28671a945772Spatrick mvpp2_down(struct mvpp2_port *sc)
28681a945772Spatrick {
28691a945772Spatrick struct ifnet *ifp = &sc->sc_ac.ac_if;
28701a945772Spatrick uint32_t reg;
28711a945772Spatrick int i;
28721a945772Spatrick
28731a945772Spatrick timeout_del(&sc->sc_tick);
28741a945772Spatrick
28751a945772Spatrick ifp->if_flags &= ~IFF_RUNNING;
28761a945772Spatrick ifq_clr_oactive(&ifp->if_snd);
28771a945772Spatrick
28781a945772Spatrick mvpp2_egress_disable(sc);
28791a945772Spatrick mvpp2_ingress_disable(sc);
2880c56f4c70Spatrick
2881c56f4c70Spatrick mvpp2_mac_reset_assert(sc);
2882c56f4c70Spatrick mvpp2_pcs_reset_assert(sc);
28831a945772Spatrick
28841a945772Spatrick /* XXX: single vector */
28851a945772Spatrick mvpp2_interrupts_disable(sc, (1 << 0));
28861a945772Spatrick mvpp2_write(sc->sc, MVPP2_ISR_RX_TX_MASK_REG(sc->sc_id), 0);
28871a945772Spatrick
28881a945772Spatrick reg = mvpp2_read(sc->sc, MVPP2_TX_PORT_FLUSH_REG);
28891a945772Spatrick reg |= MVPP2_TX_PORT_FLUSH_MASK(sc->sc_id);
28901a945772Spatrick mvpp2_write(sc->sc, MVPP2_TX_PORT_FLUSH_REG, reg);
28911a945772Spatrick
28921a945772Spatrick for (i = 0; i < sc->sc_ntxq; i++)
28931a945772Spatrick mvpp2_txq_hw_deinit(sc, &sc->sc_txqs[i]);
28941a945772Spatrick
28951a945772Spatrick reg &= ~MVPP2_TX_PORT_FLUSH_MASK(sc->sc_id);
28961a945772Spatrick mvpp2_write(sc->sc, MVPP2_TX_PORT_FLUSH_REG, reg);
28971a945772Spatrick
28981a945772Spatrick for (i = 0; i < sc->sc_nrxq; i++)
28991a945772Spatrick mvpp2_rxq_hw_deinit(sc, &sc->sc_rxqs[i]);
29001a945772Spatrick
290188474739Skettenis if (sc->sc_sfp) {
290288474739Skettenis rw_enter(&mvpp2_sff_lock, RW_WRITE);
290388474739Skettenis sfp_disable(sc->sc_sfp);
290488474739Skettenis rw_exit(&mvpp2_sff_lock);
290588474739Skettenis }
29061a945772Spatrick }
29071a945772Spatrick
29081a945772Spatrick void
mvpp2_txq_hw_deinit(struct mvpp2_port * sc,struct mvpp2_tx_queue * txq)29091a945772Spatrick mvpp2_txq_hw_deinit(struct mvpp2_port *sc, struct mvpp2_tx_queue *txq)
29101a945772Spatrick {
29111a945772Spatrick struct mvpp2_buf *txb;
29121a945772Spatrick int i, pending;
29131a945772Spatrick uint32_t reg;
29141a945772Spatrick
29151a945772Spatrick mvpp2_write(sc->sc, MVPP2_TXQ_NUM_REG, txq->id);
29161a945772Spatrick reg = mvpp2_read(sc->sc, MVPP2_TXQ_PREF_BUF_REG);
29171a945772Spatrick reg |= MVPP2_TXQ_DRAIN_EN_MASK;
29181a945772Spatrick mvpp2_write(sc->sc, MVPP2_TXQ_PREF_BUF_REG, reg);
29191a945772Spatrick
29201a945772Spatrick /*
29211a945772Spatrick * the queue has been stopped so wait for all packets
29221a945772Spatrick * to be transmitted.
29231a945772Spatrick */
29241a945772Spatrick i = 0;
29251a945772Spatrick do {
29261a945772Spatrick if (i >= MVPP2_TX_PENDING_TIMEOUT_MSEC) {
29271a945772Spatrick printf("%s: port %d: cleaning queue %d timed out\n",
29281a945772Spatrick sc->sc_dev.dv_xname, sc->sc_id, txq->log_id);
29291a945772Spatrick break;
29301a945772Spatrick }
29311a945772Spatrick delay(1000);
29321a945772Spatrick i++;
29331a945772Spatrick
29341a945772Spatrick pending = mvpp2_read(sc->sc, MVPP2_TXQ_PENDING_REG) &
29351a945772Spatrick MVPP2_TXQ_PENDING_MASK;
29361a945772Spatrick } while (pending);
29371a945772Spatrick
29381a945772Spatrick reg &= ~MVPP2_TXQ_DRAIN_EN_MASK;
29391a945772Spatrick mvpp2_write(sc->sc, MVPP2_TXQ_PREF_BUF_REG, reg);
29401a945772Spatrick
2941385d82b1Spatrick mvpp2_write(sc->sc, MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(txq->log_id), 0);
29421a945772Spatrick mvpp2_write(sc->sc, MVPP2_TXQ_NUM_REG, txq->id);
29431a945772Spatrick mvpp2_write(sc->sc, MVPP2_TXQ_DESC_ADDR_REG, 0);
29441a945772Spatrick mvpp2_write(sc->sc, MVPP2_TXQ_DESC_SIZE_REG, 0);
2945af1bab90Spatrick mvpp2_read(sc->sc, MVPP2_TXQ_SENT_REG(txq->id));
29461a945772Spatrick
29471a945772Spatrick for (i = 0; i < MVPP2_NTXDESC; i++) {
29481a945772Spatrick txb = &txq->buf[i];
29491a945772Spatrick if (txb->mb_m) {
29501a945772Spatrick bus_dmamap_sync(sc->sc_dmat, txb->mb_map, 0,
29511a945772Spatrick txb->mb_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
29521a945772Spatrick bus_dmamap_unload(sc->sc_dmat, txb->mb_map);
29531a945772Spatrick m_freem(txb->mb_m);
29541a945772Spatrick }
29551a945772Spatrick bus_dmamap_destroy(sc->sc_dmat, txb->mb_map);
29561a945772Spatrick }
29571a945772Spatrick
29581a945772Spatrick mvpp2_dmamem_free(sc->sc, txq->ring);
29591a945772Spatrick free(txq->buf, M_DEVBUF, sizeof(struct mvpp2_buf) *
29601a945772Spatrick MVPP2_NTXDESC);
29611a945772Spatrick }
29621a945772Spatrick
29631a945772Spatrick void
mvpp2_rxq_hw_drop(struct mvpp2_port * sc,struct mvpp2_rx_queue * rxq)29648801406bSpatrick mvpp2_rxq_hw_drop(struct mvpp2_port *sc, struct mvpp2_rx_queue *rxq)
29651a945772Spatrick {
29668801406bSpatrick struct mvpp2_rx_desc *rxd;
29678801406bSpatrick struct mvpp2_bm_pool *bm;
29688801406bSpatrick uint64_t phys, virt;
29698801406bSpatrick uint32_t i, nrecv, pool;
29708801406bSpatrick struct mvpp2_buf *rxb;
29711a945772Spatrick
29721a945772Spatrick nrecv = mvpp2_rxq_received(sc, rxq->id);
29738801406bSpatrick if (!nrecv)
29748801406bSpatrick return;
29758801406bSpatrick
29768801406bSpatrick bus_dmamap_sync(sc->sc_dmat, MVPP2_DMA_MAP(rxq->ring), 0,
29778801406bSpatrick MVPP2_DMA_LEN(rxq->ring),
29788801406bSpatrick BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
29798801406bSpatrick
29808801406bSpatrick for (i = 0; i < nrecv; i++) {
29818801406bSpatrick rxd = &rxq->descs[rxq->cons];
29828801406bSpatrick virt = rxd->buf_cookie_bm_qset_cls_info;
29838801406bSpatrick pool = (virt >> 16) & 0xffff;
29848801406bSpatrick KASSERT(pool < sc->sc->sc_npools);
29858801406bSpatrick bm = &sc->sc->sc_bm_pools[pool];
29868801406bSpatrick KASSERT((virt & 0xffff) < MVPP2_BM_SIZE);
29878801406bSpatrick rxb = &bm->rxbuf[virt & 0xffff];
29888801406bSpatrick KASSERT(rxb->mb_m != NULL);
29898801406bSpatrick virt &= 0xffffffff;
29908801406bSpatrick phys = rxb->mb_map->dm_segs[0].ds_addr;
29918801406bSpatrick mvpp2_write(sc->sc, MVPP22_BM_ADDR_HIGH_RLS_REG,
29928801406bSpatrick (((virt >> 32) & MVPP22_ADDR_HIGH_MASK)
29938801406bSpatrick << MVPP22_BM_ADDR_HIGH_VIRT_RLS_SHIFT) |
29948801406bSpatrick ((phys >> 32) & MVPP22_ADDR_HIGH_MASK));
29958801406bSpatrick mvpp2_write(sc->sc, MVPP2_BM_VIRT_RLS_REG,
29968801406bSpatrick virt & 0xffffffff);
29978801406bSpatrick mvpp2_write(sc->sc, MVPP2_BM_PHY_RLS_REG(pool),
29988801406bSpatrick phys & 0xffffffff);
29998801406bSpatrick rxq->cons = (rxq->cons + 1) % MVPP2_NRXDESC;
30008801406bSpatrick }
30018801406bSpatrick
30028801406bSpatrick bus_dmamap_sync(sc->sc_dmat, MVPP2_DMA_MAP(rxq->ring), 0,
30038801406bSpatrick MVPP2_DMA_LEN(rxq->ring),
30048801406bSpatrick BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
30058801406bSpatrick
30061a945772Spatrick mvpp2_rxq_status_update(sc, rxq->id, nrecv, nrecv);
30078801406bSpatrick }
30088801406bSpatrick
30098801406bSpatrick void
mvpp2_rxq_hw_deinit(struct mvpp2_port * sc,struct mvpp2_rx_queue * rxq)30108801406bSpatrick mvpp2_rxq_hw_deinit(struct mvpp2_port *sc, struct mvpp2_rx_queue *rxq)
30118801406bSpatrick {
30128801406bSpatrick mvpp2_rxq_hw_drop(sc, rxq);
30131a945772Spatrick
30141a945772Spatrick mvpp2_write(sc->sc, MVPP2_RXQ_STATUS_REG(rxq->id), 0);
30151a945772Spatrick mvpp2_write(sc->sc, MVPP2_RXQ_NUM_REG, rxq->id);
30161a945772Spatrick mvpp2_write(sc->sc, MVPP2_RXQ_DESC_ADDR_REG, 0);
30171a945772Spatrick mvpp2_write(sc->sc, MVPP2_RXQ_DESC_SIZE_REG, 0);
30181a945772Spatrick
30191a945772Spatrick mvpp2_dmamem_free(sc->sc, rxq->ring);
30201a945772Spatrick }
30211a945772Spatrick
30221a945772Spatrick void
mvpp2_rxq_long_pool_set(struct mvpp2_port * port,int lrxq,int pool)30231a945772Spatrick mvpp2_rxq_long_pool_set(struct mvpp2_port *port, int lrxq, int pool)
30241a945772Spatrick {
30251a945772Spatrick uint32_t val;
30261a945772Spatrick int prxq;
30271a945772Spatrick
30281a945772Spatrick /* get queue physical ID */
30291a945772Spatrick prxq = port->sc_rxqs[lrxq].id;
30301a945772Spatrick
30311a945772Spatrick val = mvpp2_read(port->sc, MVPP2_RXQ_CONFIG_REG(prxq));
30321a945772Spatrick val &= ~MVPP2_RXQ_POOL_LONG_MASK;
30331a945772Spatrick val |= ((pool << MVPP2_RXQ_POOL_LONG_OFFS) & MVPP2_RXQ_POOL_LONG_MASK);
30341a945772Spatrick
30351a945772Spatrick mvpp2_write(port->sc, MVPP2_RXQ_CONFIG_REG(prxq), val);
30361a945772Spatrick }
30371a945772Spatrick
30381a945772Spatrick void
mvpp2_rxq_short_pool_set(struct mvpp2_port * port,int lrxq,int pool)30391a945772Spatrick mvpp2_rxq_short_pool_set(struct mvpp2_port *port, int lrxq, int pool)
30401a945772Spatrick {
30411a945772Spatrick uint32_t val;
30421a945772Spatrick int prxq;
30431a945772Spatrick
30441a945772Spatrick /* get queue physical ID */
30451a945772Spatrick prxq = port->sc_rxqs[lrxq].id;
30461a945772Spatrick
30471a945772Spatrick val = mvpp2_read(port->sc, MVPP2_RXQ_CONFIG_REG(prxq));
30481a945772Spatrick val &= ~MVPP2_RXQ_POOL_SHORT_MASK;
30491a945772Spatrick val |= ((pool << MVPP2_RXQ_POOL_SHORT_OFFS) & MVPP2_RXQ_POOL_SHORT_MASK);
30501a945772Spatrick
30511a945772Spatrick mvpp2_write(port->sc, MVPP2_RXQ_CONFIG_REG(prxq), val);
30521a945772Spatrick }
30531a945772Spatrick
30541a945772Spatrick void
mvpp2_iff(struct mvpp2_port * sc)30551a945772Spatrick mvpp2_iff(struct mvpp2_port *sc)
30561a945772Spatrick {
3057ce595ab8Spatrick struct arpcom *ac = &sc->sc_ac;
3058ce595ab8Spatrick struct ifnet *ifp = &sc->sc_ac.ac_if;
3059ce595ab8Spatrick struct ether_multi *enm;
3060ce595ab8Spatrick struct ether_multistep step;
30611a945772Spatrick
3062ce595ab8Spatrick ifp->if_flags &= ~IFF_ALLMULTI;
3063ce595ab8Spatrick
3064ce595ab8Spatrick /* Removes all but broadcast and (new) lladdr */
3065ce595ab8Spatrick mvpp2_prs_mac_del_all(sc);
3066ce595ab8Spatrick
3067ce595ab8Spatrick if (ifp->if_flags & IFF_PROMISC) {
3068ce595ab8Spatrick mvpp2_prs_mac_promisc_set(sc->sc, sc->sc_id,
3069ce595ab8Spatrick MVPP2_PRS_L2_UNI_CAST, 1);
3070ce595ab8Spatrick mvpp2_prs_mac_promisc_set(sc->sc, sc->sc_id,
3071ce595ab8Spatrick MVPP2_PRS_L2_MULTI_CAST, 1);
3072ce595ab8Spatrick return;
3073ce595ab8Spatrick }
3074ce595ab8Spatrick
3075ce595ab8Spatrick mvpp2_prs_mac_promisc_set(sc->sc, sc->sc_id,
3076ce595ab8Spatrick MVPP2_PRS_L2_UNI_CAST, 0);
3077ce595ab8Spatrick mvpp2_prs_mac_promisc_set(sc->sc, sc->sc_id,
3078ce595ab8Spatrick MVPP2_PRS_L2_MULTI_CAST, 0);
3079ce595ab8Spatrick
3080ce595ab8Spatrick if (ac->ac_multirangecnt > 0 ||
3081ce595ab8Spatrick ac->ac_multicnt > MVPP2_PRS_MAC_MC_FILT_MAX) {
3082ce595ab8Spatrick ifp->if_flags |= IFF_ALLMULTI;
3083ce595ab8Spatrick mvpp2_prs_mac_promisc_set(sc->sc, sc->sc_id,
3084ce595ab8Spatrick MVPP2_PRS_L2_MULTI_CAST, 1);
3085ce595ab8Spatrick } else {
3086ce595ab8Spatrick ETHER_FIRST_MULTI(step, ac, enm);
3087ce595ab8Spatrick while (enm != NULL) {
3088ce595ab8Spatrick mvpp2_prs_mac_da_accept(sc, enm->enm_addrlo, 1);
3089ce595ab8Spatrick ETHER_NEXT_MULTI(step, enm);
3090ce595ab8Spatrick }
309141cd246cSpatrick }
30921a945772Spatrick }
30931a945772Spatrick
30941a945772Spatrick struct mvpp2_dmamem *
mvpp2_dmamem_alloc(struct mvpp2_softc * sc,bus_size_t size,bus_size_t align)30951a945772Spatrick mvpp2_dmamem_alloc(struct mvpp2_softc *sc, bus_size_t size, bus_size_t align)
30961a945772Spatrick {
30971a945772Spatrick struct mvpp2_dmamem *mdm;
30981a945772Spatrick int nsegs;
30991a945772Spatrick
31001a945772Spatrick mdm = malloc(sizeof(*mdm), M_DEVBUF, M_WAITOK | M_ZERO);
31011a945772Spatrick mdm->mdm_size = size;
31021a945772Spatrick
31031a945772Spatrick if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
31041a945772Spatrick BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &mdm->mdm_map) != 0)
31051a945772Spatrick goto mdmfree;
31061a945772Spatrick
31071a945772Spatrick if (bus_dmamem_alloc(sc->sc_dmat, size, align, 0, &mdm->mdm_seg, 1,
31081a945772Spatrick &nsegs, BUS_DMA_WAITOK) != 0)
31091a945772Spatrick goto destroy;
31101a945772Spatrick
31111a945772Spatrick if (bus_dmamem_map(sc->sc_dmat, &mdm->mdm_seg, nsegs, size,
31121a945772Spatrick &mdm->mdm_kva, BUS_DMA_WAITOK | BUS_DMA_COHERENT) != 0)
31131a945772Spatrick goto free;
31141a945772Spatrick
31151a945772Spatrick if (bus_dmamap_load(sc->sc_dmat, mdm->mdm_map, mdm->mdm_kva, size,
31161a945772Spatrick NULL, BUS_DMA_WAITOK) != 0)
31171a945772Spatrick goto unmap;
31181a945772Spatrick
31191a945772Spatrick bzero(mdm->mdm_kva, size);
31201a945772Spatrick
31211a945772Spatrick return (mdm);
31221a945772Spatrick
31231a945772Spatrick unmap:
31241a945772Spatrick bus_dmamem_unmap(sc->sc_dmat, mdm->mdm_kva, size);
31251a945772Spatrick free:
31261a945772Spatrick bus_dmamem_free(sc->sc_dmat, &mdm->mdm_seg, 1);
31271a945772Spatrick destroy:
31281a945772Spatrick bus_dmamap_destroy(sc->sc_dmat, mdm->mdm_map);
31291a945772Spatrick mdmfree:
31301a945772Spatrick free(mdm, M_DEVBUF, 0);
31311a945772Spatrick
31321a945772Spatrick return (NULL);
31331a945772Spatrick }
31341a945772Spatrick
31351a945772Spatrick void
mvpp2_dmamem_free(struct mvpp2_softc * sc,struct mvpp2_dmamem * mdm)31361a945772Spatrick mvpp2_dmamem_free(struct mvpp2_softc *sc, struct mvpp2_dmamem *mdm)
31371a945772Spatrick {
31381a945772Spatrick bus_dmamem_unmap(sc->sc_dmat, mdm->mdm_kva, mdm->mdm_size);
31391a945772Spatrick bus_dmamem_free(sc->sc_dmat, &mdm->mdm_seg, 1);
31401a945772Spatrick bus_dmamap_destroy(sc->sc_dmat, mdm->mdm_map);
31411a945772Spatrick free(mdm, M_DEVBUF, 0);
31421a945772Spatrick }
31431a945772Spatrick
31441a945772Spatrick struct mbuf *
mvpp2_alloc_mbuf(struct mvpp2_softc * sc,bus_dmamap_t map)31451a945772Spatrick mvpp2_alloc_mbuf(struct mvpp2_softc *sc, bus_dmamap_t map)
31461a945772Spatrick {
31471a945772Spatrick struct mbuf *m = NULL;
31481a945772Spatrick
3149471f2571Sjan m = MCLGETL(NULL, M_DONTWAIT, MCLBYTES);
31501a945772Spatrick if (!m)
31511a945772Spatrick return (NULL);
31521a945772Spatrick m->m_len = m->m_pkthdr.len = MCLBYTES;
31531a945772Spatrick
31541a945772Spatrick if (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, BUS_DMA_NOWAIT) != 0) {
31551a945772Spatrick printf("%s: could not load mbuf DMA map", DEVNAME(sc));
31561a945772Spatrick m_freem(m);
31571a945772Spatrick return (NULL);
31581a945772Spatrick }
31591a945772Spatrick
31601a945772Spatrick bus_dmamap_sync(sc->sc_dmat, map, 0,
31611a945772Spatrick m->m_pkthdr.len, BUS_DMASYNC_PREREAD);
31621a945772Spatrick
31631a945772Spatrick return (m);
31641a945772Spatrick }
31651a945772Spatrick
31661a945772Spatrick void
mvpp2_interrupts_enable(struct mvpp2_port * port,int cpu_mask)31671a945772Spatrick mvpp2_interrupts_enable(struct mvpp2_port *port, int cpu_mask)
31681a945772Spatrick {
31691a945772Spatrick mvpp2_write(port->sc, MVPP2_ISR_ENABLE_REG(port->sc_id),
31701a945772Spatrick MVPP2_ISR_ENABLE_INTERRUPT(cpu_mask));
31711a945772Spatrick }
31721a945772Spatrick
31731a945772Spatrick void
mvpp2_interrupts_disable(struct mvpp2_port * port,int cpu_mask)31741a945772Spatrick mvpp2_interrupts_disable(struct mvpp2_port *port, int cpu_mask)
31751a945772Spatrick {
31761a945772Spatrick mvpp2_write(port->sc, MVPP2_ISR_ENABLE_REG(port->sc_id),
31771a945772Spatrick MVPP2_ISR_DISABLE_INTERRUPT(cpu_mask));
31781a945772Spatrick }
31791a945772Spatrick
31801a945772Spatrick int
mvpp2_egress_port(struct mvpp2_port * port)31811a945772Spatrick mvpp2_egress_port(struct mvpp2_port *port)
31821a945772Spatrick {
31831a945772Spatrick return MVPP2_MAX_TCONT + port->sc_id;
31841a945772Spatrick }
31851a945772Spatrick
31861a945772Spatrick int
mvpp2_txq_phys(int port,int txq)31871a945772Spatrick mvpp2_txq_phys(int port, int txq)
31881a945772Spatrick {
31891a945772Spatrick return (MVPP2_MAX_TCONT + port) * MVPP2_MAX_TXQ + txq;
31901a945772Spatrick }
31911a945772Spatrick
31921a945772Spatrick void
mvpp2_defaults_set(struct mvpp2_port * port)31931a945772Spatrick mvpp2_defaults_set(struct mvpp2_port *port)
31941a945772Spatrick {
3195385d82b1Spatrick int val, queue;
31961a945772Spatrick
31971a945772Spatrick mvpp2_write(port->sc, MVPP2_TXP_SCHED_PORT_INDEX_REG,
31981a945772Spatrick mvpp2_egress_port(port));
31991a945772Spatrick mvpp2_write(port->sc, MVPP2_TXP_SCHED_CMD_1_REG, 0);
32001a945772Spatrick
3201385d82b1Spatrick for (queue = 0; queue < MVPP2_MAX_TXQ; queue++)
3202385d82b1Spatrick mvpp2_write(port->sc, MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(queue), 0);
32031a945772Spatrick
32041a945772Spatrick mvpp2_write(port->sc, MVPP2_TXP_SCHED_PERIOD_REG, port->sc->sc_tclk /
32051a945772Spatrick (1000 * 1000));
32061a945772Spatrick val = mvpp2_read(port->sc, MVPP2_TXP_SCHED_REFILL_REG);
32071a945772Spatrick val &= ~MVPP2_TXP_REFILL_PERIOD_ALL_MASK;
32081a945772Spatrick val |= MVPP2_TXP_REFILL_PERIOD_MASK(1);
32091a945772Spatrick val |= MVPP2_TXP_REFILL_TOKENS_ALL_MASK;
32101a945772Spatrick mvpp2_write(port->sc, MVPP2_TXP_SCHED_REFILL_REG, val);
32111a945772Spatrick val = MVPP2_TXP_TOKEN_SIZE_MAX;
32121a945772Spatrick mvpp2_write(port->sc, MVPP2_TXP_SCHED_TOKEN_SIZE_REG, val);
32131a945772Spatrick
32141a945772Spatrick /* set maximum_low_latency_packet_size value to 256 */
32151a945772Spatrick mvpp2_write(port->sc, MVPP2_RX_CTRL_REG(port->sc_id),
32161a945772Spatrick MVPP2_RX_USE_PSEUDO_FOR_CSUM_MASK |
32171a945772Spatrick MVPP2_RX_LOW_LATENCY_PKT_SIZE(256));
32181a945772Spatrick
32191a945772Spatrick /* mask all interrupts to all present cpus */
32201a945772Spatrick mvpp2_interrupts_disable(port, (0xf << 0));
32211a945772Spatrick }
32221a945772Spatrick
32231a945772Spatrick void
mvpp2_ingress_enable(struct mvpp2_port * port)32241a945772Spatrick mvpp2_ingress_enable(struct mvpp2_port *port)
32251a945772Spatrick {
32261a945772Spatrick uint32_t val;
32271a945772Spatrick int lrxq, queue;
32281a945772Spatrick
32291a945772Spatrick for (lrxq = 0; lrxq < port->sc_nrxq; lrxq++) {
32301a945772Spatrick queue = port->sc_rxqs[lrxq].id;
32311a945772Spatrick val = mvpp2_read(port->sc, MVPP2_RXQ_CONFIG_REG(queue));
32321a945772Spatrick val &= ~MVPP2_RXQ_DISABLE_MASK;
32331a945772Spatrick mvpp2_write(port->sc, MVPP2_RXQ_CONFIG_REG(queue), val);
32341a945772Spatrick }
32351a945772Spatrick }
32361a945772Spatrick
32371a945772Spatrick void
mvpp2_ingress_disable(struct mvpp2_port * port)32381a945772Spatrick mvpp2_ingress_disable(struct mvpp2_port *port)
32391a945772Spatrick {
32401a945772Spatrick uint32_t val;
32411a945772Spatrick int lrxq, queue;
32421a945772Spatrick
32431a945772Spatrick for (lrxq = 0; lrxq < port->sc_nrxq; lrxq++) {
32441a945772Spatrick queue = port->sc_rxqs[lrxq].id;
32451a945772Spatrick val = mvpp2_read(port->sc, MVPP2_RXQ_CONFIG_REG(queue));
32461a945772Spatrick val |= MVPP2_RXQ_DISABLE_MASK;
32471a945772Spatrick mvpp2_write(port->sc, MVPP2_RXQ_CONFIG_REG(queue), val);
32481a945772Spatrick }
32491a945772Spatrick }
32501a945772Spatrick
32511a945772Spatrick void
mvpp2_egress_enable(struct mvpp2_port * port)32521a945772Spatrick mvpp2_egress_enable(struct mvpp2_port *port)
32531a945772Spatrick {
32541a945772Spatrick struct mvpp2_tx_queue *txq;
32551a945772Spatrick uint32_t qmap;
32561a945772Spatrick int queue;
32571a945772Spatrick
32581a945772Spatrick qmap = 0;
32591a945772Spatrick for (queue = 0; queue < port->sc_ntxq; queue++) {
32601a945772Spatrick txq = &port->sc_txqs[queue];
32611a945772Spatrick
32621a945772Spatrick if (txq->descs != NULL) {
32631a945772Spatrick qmap |= (1 << queue);
32641a945772Spatrick }
32651a945772Spatrick }
32661a945772Spatrick
32671a945772Spatrick mvpp2_write(port->sc, MVPP2_TXP_SCHED_PORT_INDEX_REG,
32681a945772Spatrick mvpp2_egress_port(port));
32691a945772Spatrick mvpp2_write(port->sc, MVPP2_TXP_SCHED_Q_CMD_REG, qmap);
32701a945772Spatrick }
32711a945772Spatrick
32721a945772Spatrick void
mvpp2_egress_disable(struct mvpp2_port * port)32731a945772Spatrick mvpp2_egress_disable(struct mvpp2_port *port)
32741a945772Spatrick {
32751a945772Spatrick uint32_t reg_data;
32761a945772Spatrick int i;
32771a945772Spatrick
32781a945772Spatrick mvpp2_write(port->sc, MVPP2_TXP_SCHED_PORT_INDEX_REG,
32791a945772Spatrick mvpp2_egress_port(port));
32801a945772Spatrick reg_data = (mvpp2_read(port->sc, MVPP2_TXP_SCHED_Q_CMD_REG)) &
32811a945772Spatrick MVPP2_TXP_SCHED_ENQ_MASK;
32821a945772Spatrick if (reg_data)
3283687cc71bSpatrick mvpp2_write(port->sc, MVPP2_TXP_SCHED_Q_CMD_REG,
3284687cc71bSpatrick reg_data << MVPP2_TXP_SCHED_DISQ_OFFSET);
32851a945772Spatrick
32861a945772Spatrick i = 0;
32871a945772Spatrick do {
32881a945772Spatrick if (i >= MVPP2_TX_DISABLE_TIMEOUT_MSEC) {
32891a945772Spatrick printf("%s: tx stop timed out, status=0x%08x\n",
32901a945772Spatrick port->sc_dev.dv_xname, reg_data);
32911a945772Spatrick break;
32921a945772Spatrick }
32931a945772Spatrick delay(1000);
32941a945772Spatrick i++;
32951a945772Spatrick reg_data = mvpp2_read(port->sc, MVPP2_TXP_SCHED_Q_CMD_REG);
32961a945772Spatrick } while (reg_data & MVPP2_TXP_SCHED_ENQ_MASK);
32971a945772Spatrick }
32981a945772Spatrick
32991a945772Spatrick void
mvpp2_port_enable(struct mvpp2_port * port)33001a945772Spatrick mvpp2_port_enable(struct mvpp2_port *port)
33011a945772Spatrick {
33021a945772Spatrick uint32_t val;
33031a945772Spatrick
33041a945772Spatrick if (port->sc_gop_id == 0 && (port->sc_phy_mode == PHY_MODE_10GBASER ||
33051a945772Spatrick port->sc_phy_mode == PHY_MODE_XAUI)) {
33061a945772Spatrick val = mvpp2_xlg_read(port, MV_XLG_PORT_MAC_CTRL0_REG);
33074d0a0269Spatrick val |= MV_XLG_MAC_CTRL0_PORTEN;
33084d0a0269Spatrick val &= ~MV_XLG_MAC_CTRL0_MIBCNTDIS;
33091a945772Spatrick mvpp2_xlg_write(port, MV_XLG_PORT_MAC_CTRL0_REG, val);
33101a945772Spatrick } else {
33111a945772Spatrick val = mvpp2_gmac_read(port, MVPP2_GMAC_CTRL_0_REG);
33121a945772Spatrick val |= MVPP2_GMAC_PORT_EN_MASK;
33131a945772Spatrick val |= MVPP2_GMAC_MIB_CNTR_EN_MASK;
33141a945772Spatrick mvpp2_gmac_write(port, MVPP2_GMAC_CTRL_0_REG, val);
33151a945772Spatrick }
33161a945772Spatrick }
33171a945772Spatrick
33181a945772Spatrick void
mvpp2_port_disable(struct mvpp2_port * port)33191a945772Spatrick mvpp2_port_disable(struct mvpp2_port *port)
33201a945772Spatrick {
33211a945772Spatrick uint32_t val;
33221a945772Spatrick
33231a945772Spatrick if (port->sc_gop_id == 0 && (port->sc_phy_mode == PHY_MODE_10GBASER ||
33241a945772Spatrick port->sc_phy_mode == PHY_MODE_XAUI)) {
33251a945772Spatrick val = mvpp2_xlg_read(port, MV_XLG_PORT_MAC_CTRL0_REG);
33264d0a0269Spatrick val &= ~MV_XLG_MAC_CTRL0_PORTEN;
33271a945772Spatrick mvpp2_xlg_write(port, MV_XLG_PORT_MAC_CTRL0_REG, val);
33281a945772Spatrick }
33291a945772Spatrick
33301a945772Spatrick val = mvpp2_gmac_read(port, MVPP2_GMAC_CTRL_0_REG);
33311a945772Spatrick val &= ~MVPP2_GMAC_PORT_EN_MASK;
33321a945772Spatrick mvpp2_gmac_write(port, MVPP2_GMAC_CTRL_0_REG, val);
33331a945772Spatrick }
33341a945772Spatrick
33351a945772Spatrick int
mvpp2_rxq_received(struct mvpp2_port * port,int rxq_id)33361a945772Spatrick mvpp2_rxq_received(struct mvpp2_port *port, int rxq_id)
33371a945772Spatrick {
33381a945772Spatrick uint32_t val = mvpp2_read(port->sc, MVPP2_RXQ_STATUS_REG(rxq_id));
33391a945772Spatrick
33401a945772Spatrick return val & MVPP2_RXQ_OCCUPIED_MASK;
33411a945772Spatrick }
33421a945772Spatrick
33431a945772Spatrick void
mvpp2_rxq_status_update(struct mvpp2_port * port,int rxq_id,int used_count,int free_count)33441a945772Spatrick mvpp2_rxq_status_update(struct mvpp2_port *port, int rxq_id,
33451a945772Spatrick int used_count, int free_count)
33461a945772Spatrick {
33471a945772Spatrick uint32_t val = used_count | (free_count << MVPP2_RXQ_NUM_NEW_OFFSET);
33481a945772Spatrick mvpp2_write(port->sc, MVPP2_RXQ_STATUS_UPDATE_REG(rxq_id), val);
33491a945772Spatrick }
33501a945772Spatrick
33511a945772Spatrick void
mvpp2_rxq_offset_set(struct mvpp2_port * port,int prxq,int offset)33521a945772Spatrick mvpp2_rxq_offset_set(struct mvpp2_port *port, int prxq, int offset)
33531a945772Spatrick {
33541a945772Spatrick uint32_t val;
33551a945772Spatrick
33561a945772Spatrick offset = offset >> 5;
33571a945772Spatrick val = mvpp2_read(port->sc, MVPP2_RXQ_CONFIG_REG(prxq));
33581a945772Spatrick val &= ~MVPP2_RXQ_PACKET_OFFSET_MASK;
33591a945772Spatrick val |= ((offset << MVPP2_RXQ_PACKET_OFFSET_OFFS) &
33601a945772Spatrick MVPP2_RXQ_PACKET_OFFSET_MASK);
33611a945772Spatrick mvpp2_write(port->sc, MVPP2_RXQ_CONFIG_REG(prxq), val);
33621a945772Spatrick }
33631a945772Spatrick
33641a945772Spatrick void
mvpp2_txp_max_tx_size_set(struct mvpp2_port * port)33651a945772Spatrick mvpp2_txp_max_tx_size_set(struct mvpp2_port *port)
33661a945772Spatrick {
33671a945772Spatrick uint32_t val, size, mtu;
33681a945772Spatrick int txq;
33691a945772Spatrick
33701a945772Spatrick mtu = MCLBYTES * 8;
33711a945772Spatrick if (mtu > MVPP2_TXP_MTU_MAX)
33721a945772Spatrick mtu = MVPP2_TXP_MTU_MAX;
33731a945772Spatrick
33741a945772Spatrick /* WA for wrong token bucket update: set MTU value = 3*real MTU value */
33751a945772Spatrick mtu = 3 * mtu;
33761a945772Spatrick
33771a945772Spatrick /* indirect access to reg_valisters */
33781a945772Spatrick mvpp2_write(port->sc, MVPP2_TXP_SCHED_PORT_INDEX_REG,
33791a945772Spatrick mvpp2_egress_port(port));
33801a945772Spatrick
33811a945772Spatrick /* set MTU */
33821a945772Spatrick val = mvpp2_read(port->sc, MVPP2_TXP_SCHED_MTU_REG);
33831a945772Spatrick val &= ~MVPP2_TXP_MTU_MAX;
33841a945772Spatrick val |= mtu;
33851a945772Spatrick mvpp2_write(port->sc, MVPP2_TXP_SCHED_MTU_REG, val);
33861a945772Spatrick
33871a945772Spatrick /* TXP token size and all TXqs token size must be larger that MTU */
33881a945772Spatrick val = mvpp2_read(port->sc, MVPP2_TXP_SCHED_TOKEN_SIZE_REG);
33891a945772Spatrick size = val & MVPP2_TXP_TOKEN_SIZE_MAX;
33901a945772Spatrick if (size < mtu) {
33911a945772Spatrick size = mtu;
33921a945772Spatrick val &= ~MVPP2_TXP_TOKEN_SIZE_MAX;
33931a945772Spatrick val |= size;
33941a945772Spatrick mvpp2_write(port->sc, MVPP2_TXP_SCHED_TOKEN_SIZE_REG, val);
33951a945772Spatrick }
33961a945772Spatrick
33971a945772Spatrick for (txq = 0; txq < port->sc_ntxq; txq++) {
33981a945772Spatrick val = mvpp2_read(port->sc, MVPP2_TXQ_SCHED_TOKEN_SIZE_REG(txq));
33991a945772Spatrick size = val & MVPP2_TXQ_TOKEN_SIZE_MAX;
34001a945772Spatrick
34011a945772Spatrick if (size < mtu) {
34021a945772Spatrick size = mtu;
34031a945772Spatrick val &= ~MVPP2_TXQ_TOKEN_SIZE_MAX;
34041a945772Spatrick val |= size;
34051a945772Spatrick mvpp2_write(port->sc, MVPP2_TXQ_SCHED_TOKEN_SIZE_REG(txq), val);
34061a945772Spatrick }
34071a945772Spatrick }
34081a945772Spatrick }
34091a945772Spatrick
34101a945772Spatrick void
mvpp2_rx_pkts_coal_set(struct mvpp2_port * port,struct mvpp2_rx_queue * rxq,uint32_t pkts)34111a945772Spatrick mvpp2_rx_pkts_coal_set(struct mvpp2_port *port, struct mvpp2_rx_queue *rxq,
34121a945772Spatrick uint32_t pkts)
34131a945772Spatrick {
34141a945772Spatrick rxq->pkts_coal =
34151a945772Spatrick pkts <= MVPP2_OCCUPIED_THRESH_MASK ?
34161a945772Spatrick pkts : MVPP2_OCCUPIED_THRESH_MASK;
34171a945772Spatrick
34181a945772Spatrick mvpp2_write(port->sc, MVPP2_RXQ_NUM_REG, rxq->id);
34191a945772Spatrick mvpp2_write(port->sc, MVPP2_RXQ_THRESH_REG, rxq->pkts_coal);
34201a945772Spatrick
34211a945772Spatrick }
34221a945772Spatrick
34231a945772Spatrick void
mvpp2_tx_pkts_coal_set(struct mvpp2_port * port,struct mvpp2_tx_queue * txq,uint32_t pkts)34241a945772Spatrick mvpp2_tx_pkts_coal_set(struct mvpp2_port *port, struct mvpp2_tx_queue *txq,
34251a945772Spatrick uint32_t pkts)
34261a945772Spatrick {
34271a945772Spatrick txq->done_pkts_coal =
34281a945772Spatrick pkts <= MVPP2_TRANSMITTED_THRESH_MASK ?
34291a945772Spatrick pkts : MVPP2_TRANSMITTED_THRESH_MASK;
34301a945772Spatrick
34311a945772Spatrick mvpp2_write(port->sc, MVPP2_TXQ_NUM_REG, txq->id);
34321a945772Spatrick mvpp2_write(port->sc, MVPP2_TXQ_THRESH_REG,
34331a945772Spatrick txq->done_pkts_coal << MVPP2_TRANSMITTED_THRESH_OFFSET);
34341a945772Spatrick }
34351a945772Spatrick
34361a945772Spatrick void
mvpp2_rx_time_coal_set(struct mvpp2_port * port,struct mvpp2_rx_queue * rxq,uint32_t usec)34371a945772Spatrick mvpp2_rx_time_coal_set(struct mvpp2_port *port, struct mvpp2_rx_queue *rxq,
34381a945772Spatrick uint32_t usec)
34391a945772Spatrick {
34401a945772Spatrick uint32_t val;
34411a945772Spatrick
34421a945772Spatrick val = (port->sc->sc_tclk / (1000 * 1000)) * usec;
34431a945772Spatrick mvpp2_write(port->sc, MVPP2_ISR_RX_THRESHOLD_REG(rxq->id), val);
34441a945772Spatrick
34451a945772Spatrick rxq->time_coal = usec;
34461a945772Spatrick }
34471a945772Spatrick
34481a945772Spatrick void
mvpp2_tx_time_coal_set(struct mvpp2_port * port,uint32_t usec)34491a945772Spatrick mvpp2_tx_time_coal_set(struct mvpp2_port *port, uint32_t usec)
34501a945772Spatrick {
34511a945772Spatrick uint32_t val;
34521a945772Spatrick
34531a945772Spatrick val = (port->sc->sc_tclk / (1000 * 1000)) * usec;
34541a945772Spatrick mvpp2_write(port->sc, MVPP2_ISR_TX_THRESHOLD_REG(port->sc_id), val);
34551a945772Spatrick
34561a945772Spatrick port->sc_tx_time_coal = usec;
34571a945772Spatrick }
34581a945772Spatrick
34591a945772Spatrick void
mvpp2_prs_shadow_ri_set(struct mvpp2_softc * sc,int index,uint32_t ri,uint32_t ri_mask)34601a945772Spatrick mvpp2_prs_shadow_ri_set(struct mvpp2_softc *sc, int index,
34611a945772Spatrick uint32_t ri, uint32_t ri_mask)
34621a945772Spatrick {
34631a945772Spatrick sc->sc_prs_shadow[index].ri_mask = ri_mask;
34641a945772Spatrick sc->sc_prs_shadow[index].ri = ri;
34651a945772Spatrick }
34661a945772Spatrick
34671a945772Spatrick void
mvpp2_prs_tcam_lu_set(struct mvpp2_prs_entry * pe,uint32_t lu)34681a945772Spatrick mvpp2_prs_tcam_lu_set(struct mvpp2_prs_entry *pe, uint32_t lu)
34691a945772Spatrick {
34701a945772Spatrick int enable_off = MVPP2_PRS_TCAM_EN_OFFS(MVPP2_PRS_TCAM_LU_BYTE);
34711a945772Spatrick
34721a945772Spatrick pe->tcam.byte[MVPP2_PRS_TCAM_LU_BYTE] = lu;
34731a945772Spatrick pe->tcam.byte[enable_off] = MVPP2_PRS_LU_MASK;
34741a945772Spatrick }
34751a945772Spatrick
34761a945772Spatrick void
mvpp2_prs_tcam_port_set(struct mvpp2_prs_entry * pe,uint32_t port,int add)34771a945772Spatrick mvpp2_prs_tcam_port_set(struct mvpp2_prs_entry *pe, uint32_t port, int add)
34781a945772Spatrick {
34791a945772Spatrick int enable_off = MVPP2_PRS_TCAM_EN_OFFS(MVPP2_PRS_TCAM_PORT_BYTE);
34801a945772Spatrick
34811a945772Spatrick if (add)
34821a945772Spatrick pe->tcam.byte[enable_off] &= ~(1 << port);
34831a945772Spatrick else
34841a945772Spatrick pe->tcam.byte[enable_off] |= (1 << port);
34851a945772Spatrick }
34861a945772Spatrick
34871a945772Spatrick void
mvpp2_prs_tcam_port_map_set(struct mvpp2_prs_entry * pe,uint32_t port_mask)34881a945772Spatrick mvpp2_prs_tcam_port_map_set(struct mvpp2_prs_entry *pe, uint32_t port_mask)
34891a945772Spatrick {
34901a945772Spatrick int enable_off = MVPP2_PRS_TCAM_EN_OFFS(MVPP2_PRS_TCAM_PORT_BYTE);
34911a945772Spatrick uint8_t mask = MVPP2_PRS_PORT_MASK;
34921a945772Spatrick
34931a945772Spatrick pe->tcam.byte[MVPP2_PRS_TCAM_PORT_BYTE] = 0;
34941a945772Spatrick pe->tcam.byte[enable_off] &= ~mask;
34951a945772Spatrick pe->tcam.byte[enable_off] |= ~port_mask & MVPP2_PRS_PORT_MASK;
34961a945772Spatrick }
34971a945772Spatrick
34981a945772Spatrick uint32_t
mvpp2_prs_tcam_port_map_get(struct mvpp2_prs_entry * pe)34991a945772Spatrick mvpp2_prs_tcam_port_map_get(struct mvpp2_prs_entry *pe)
35001a945772Spatrick {
35011a945772Spatrick int enable_off = MVPP2_PRS_TCAM_EN_OFFS(MVPP2_PRS_TCAM_PORT_BYTE);
35021a945772Spatrick
35031a945772Spatrick return ~(pe->tcam.byte[enable_off]) & MVPP2_PRS_PORT_MASK;
35041a945772Spatrick }
35051a945772Spatrick
35061a945772Spatrick void
mvpp2_prs_tcam_data_byte_set(struct mvpp2_prs_entry * pe,uint32_t offs,uint8_t byte,uint8_t enable)35071a945772Spatrick mvpp2_prs_tcam_data_byte_set(struct mvpp2_prs_entry *pe, uint32_t offs,
35081a945772Spatrick uint8_t byte, uint8_t enable)
35091a945772Spatrick {
35101a945772Spatrick pe->tcam.byte[MVPP2_PRS_TCAM_DATA_BYTE(offs)] = byte;
35111a945772Spatrick pe->tcam.byte[MVPP2_PRS_TCAM_DATA_BYTE_EN(offs)] = enable;
35121a945772Spatrick }
35131a945772Spatrick
35141a945772Spatrick void
mvpp2_prs_tcam_data_byte_get(struct mvpp2_prs_entry * pe,uint32_t offs,uint8_t * byte,uint8_t * enable)35151a945772Spatrick mvpp2_prs_tcam_data_byte_get(struct mvpp2_prs_entry *pe, uint32_t offs,
35161a945772Spatrick uint8_t *byte, uint8_t *enable)
35171a945772Spatrick {
35181a945772Spatrick *byte = pe->tcam.byte[MVPP2_PRS_TCAM_DATA_BYTE(offs)];
35191a945772Spatrick *enable = pe->tcam.byte[MVPP2_PRS_TCAM_DATA_BYTE_EN(offs)];
35201a945772Spatrick }
35211a945772Spatrick
35221a945772Spatrick int
mvpp2_prs_tcam_data_cmp(struct mvpp2_prs_entry * pe,int offset,uint16_t data)35231a945772Spatrick mvpp2_prs_tcam_data_cmp(struct mvpp2_prs_entry *pe, int offset, uint16_t data)
35241a945772Spatrick {
35251a945772Spatrick int byte_offset = MVPP2_PRS_TCAM_DATA_BYTE(offset);
35261a945772Spatrick uint16_t tcam_data;
35271a945772Spatrick
35281a945772Spatrick tcam_data = (pe->tcam.byte[byte_offset + 1] << 8) |
35291a945772Spatrick pe->tcam.byte[byte_offset];
353047d131caSpatrick return tcam_data == data;
35311a945772Spatrick }
35321a945772Spatrick
35331a945772Spatrick void
mvpp2_prs_tcam_ai_update(struct mvpp2_prs_entry * pe,uint32_t bits,uint32_t enable)35341a945772Spatrick mvpp2_prs_tcam_ai_update(struct mvpp2_prs_entry *pe, uint32_t bits, uint32_t enable)
35351a945772Spatrick {
35361a945772Spatrick int i, ai_idx = MVPP2_PRS_TCAM_AI_BYTE;
35371a945772Spatrick
35381a945772Spatrick for (i = 0; i < MVPP2_PRS_AI_BITS; i++) {
35394896f12aSpatrick if (!(enable & BIT(i)))
35401a945772Spatrick continue;
35411a945772Spatrick
35424896f12aSpatrick if (bits & BIT(i))
35434896f12aSpatrick pe->tcam.byte[ai_idx] |= BIT(i);
35441a945772Spatrick else
35454896f12aSpatrick pe->tcam.byte[ai_idx] &= ~BIT(i);
35461a945772Spatrick }
35471a945772Spatrick
35481a945772Spatrick pe->tcam.byte[MVPP2_PRS_TCAM_EN_OFFS(ai_idx)] |= enable;
35491a945772Spatrick }
35501a945772Spatrick
35511a945772Spatrick int
mvpp2_prs_tcam_ai_get(struct mvpp2_prs_entry * pe)35521a945772Spatrick mvpp2_prs_tcam_ai_get(struct mvpp2_prs_entry *pe)
35531a945772Spatrick {
35541a945772Spatrick return pe->tcam.byte[MVPP2_PRS_TCAM_AI_BYTE];
35551a945772Spatrick }
35561a945772Spatrick
35571a945772Spatrick void
mvpp2_prs_tcam_data_word_get(struct mvpp2_prs_entry * pe,uint32_t data_offset,uint32_t * word,uint32_t * enable)35581a945772Spatrick mvpp2_prs_tcam_data_word_get(struct mvpp2_prs_entry *pe, uint32_t data_offset,
35591a945772Spatrick uint32_t *word, uint32_t *enable)
35601a945772Spatrick {
35611a945772Spatrick int index, position;
35621a945772Spatrick uint8_t byte, mask;
35631a945772Spatrick
35641a945772Spatrick for (index = 0; index < 4; index++) {
35651a945772Spatrick position = (data_offset * sizeof(int)) + index;
35661a945772Spatrick mvpp2_prs_tcam_data_byte_get(pe, position, &byte, &mask);
35671a945772Spatrick ((uint8_t *)word)[index] = byte;
35681a945772Spatrick ((uint8_t *)enable)[index] = mask;
35691a945772Spatrick }
35701a945772Spatrick }
35711a945772Spatrick
35721a945772Spatrick void
mvpp2_prs_match_etype(struct mvpp2_prs_entry * pe,uint32_t offs,uint16_t ether_type)35731a945772Spatrick mvpp2_prs_match_etype(struct mvpp2_prs_entry *pe, uint32_t offs,
35741a945772Spatrick uint16_t ether_type)
35751a945772Spatrick {
35761a945772Spatrick mvpp2_prs_tcam_data_byte_set(pe, offs + 0, ether_type >> 8, 0xff);
35771a945772Spatrick mvpp2_prs_tcam_data_byte_set(pe, offs + 1, ether_type & 0xff, 0xff);
35781a945772Spatrick }
35791a945772Spatrick
35801a945772Spatrick void
mvpp2_prs_sram_bits_set(struct mvpp2_prs_entry * pe,uint32_t bit,uint32_t val)35811a945772Spatrick mvpp2_prs_sram_bits_set(struct mvpp2_prs_entry *pe, uint32_t bit, uint32_t val)
35821a945772Spatrick {
35831a945772Spatrick pe->sram.byte[bit / 8] |= (val << (bit % 8));
35841a945772Spatrick }
35851a945772Spatrick
35861a945772Spatrick void
mvpp2_prs_sram_bits_clear(struct mvpp2_prs_entry * pe,uint32_t bit,uint32_t val)35871a945772Spatrick mvpp2_prs_sram_bits_clear(struct mvpp2_prs_entry *pe, uint32_t bit, uint32_t val)
35881a945772Spatrick {
35891a945772Spatrick pe->sram.byte[bit / 8] &= ~(val << (bit % 8));
35901a945772Spatrick }
35911a945772Spatrick
35921a945772Spatrick void
mvpp2_prs_sram_ri_update(struct mvpp2_prs_entry * pe,uint32_t bits,uint32_t mask)35931a945772Spatrick mvpp2_prs_sram_ri_update(struct mvpp2_prs_entry *pe, uint32_t bits, uint32_t mask)
35941a945772Spatrick {
35951a945772Spatrick int i;
35961a945772Spatrick
35971a945772Spatrick for (i = 0; i < MVPP2_PRS_SRAM_RI_CTRL_BITS; i++) {
3598af1244a6Spatrick if (!(mask & BIT(i)))
35991a945772Spatrick continue;
36001a945772Spatrick
3601af1244a6Spatrick if (bits & BIT(i))
360298c4121bSpatrick mvpp2_prs_sram_bits_set(pe,
360398c4121bSpatrick MVPP2_PRS_SRAM_RI_OFFS + i, 1);
36041a945772Spatrick else
360598c4121bSpatrick mvpp2_prs_sram_bits_clear(pe,
360698c4121bSpatrick MVPP2_PRS_SRAM_RI_OFFS + i, 1);
36071a945772Spatrick
36081a945772Spatrick mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_RI_CTRL_OFFS + i, 1);
36091a945772Spatrick }
36101a945772Spatrick }
36111a945772Spatrick
36121a945772Spatrick int
mvpp2_prs_sram_ri_get(struct mvpp2_prs_entry * pe)36131a945772Spatrick mvpp2_prs_sram_ri_get(struct mvpp2_prs_entry *pe)
36141a945772Spatrick {
36151a945772Spatrick return pe->sram.word[MVPP2_PRS_SRAM_RI_WORD];
36161a945772Spatrick }
36171a945772Spatrick
36181a945772Spatrick void
mvpp2_prs_sram_ai_update(struct mvpp2_prs_entry * pe,uint32_t bits,uint32_t mask)36191a945772Spatrick mvpp2_prs_sram_ai_update(struct mvpp2_prs_entry *pe, uint32_t bits, uint32_t mask)
36201a945772Spatrick {
36211a945772Spatrick int i;
36221a945772Spatrick
36231a945772Spatrick for (i = 0; i < MVPP2_PRS_SRAM_AI_CTRL_BITS; i++) {
3624af1244a6Spatrick if (!(mask & BIT(i)))
36251a945772Spatrick continue;
36261a945772Spatrick
3627af1244a6Spatrick if (bits & BIT(i))
362898c4121bSpatrick mvpp2_prs_sram_bits_set(pe,
362998c4121bSpatrick MVPP2_PRS_SRAM_AI_OFFS + i, 1);
36301a945772Spatrick else
363198c4121bSpatrick mvpp2_prs_sram_bits_clear(pe,
363298c4121bSpatrick MVPP2_PRS_SRAM_AI_OFFS + i, 1);
36331a945772Spatrick
36341a945772Spatrick mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_AI_CTRL_OFFS + i, 1);
36351a945772Spatrick }
36361a945772Spatrick }
36371a945772Spatrick
36381a945772Spatrick int
mvpp2_prs_sram_ai_get(struct mvpp2_prs_entry * pe)36391a945772Spatrick mvpp2_prs_sram_ai_get(struct mvpp2_prs_entry *pe)
36401a945772Spatrick {
36411a945772Spatrick uint8_t bits;
36421a945772Spatrick int ai_off = MVPP2_BIT_TO_BYTE(MVPP2_PRS_SRAM_AI_OFFS);
36431a945772Spatrick int ai_en_off = ai_off + 1;
36441a945772Spatrick int ai_shift = MVPP2_PRS_SRAM_AI_OFFS % 8;
36451a945772Spatrick
36461a945772Spatrick bits = (pe->sram.byte[ai_off] >> ai_shift) |
36471a945772Spatrick (pe->sram.byte[ai_en_off] << (8 - ai_shift));
36481a945772Spatrick
36491a945772Spatrick return bits;
36501a945772Spatrick }
36511a945772Spatrick
36521a945772Spatrick void
mvpp2_prs_sram_shift_set(struct mvpp2_prs_entry * pe,int shift,uint32_t op)36531a945772Spatrick mvpp2_prs_sram_shift_set(struct mvpp2_prs_entry *pe, int shift, uint32_t op)
36541a945772Spatrick {
36551a945772Spatrick if (shift < 0) {
36561a945772Spatrick mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_SHIFT_SIGN_BIT, 1);
36571a945772Spatrick shift = -shift;
36581a945772Spatrick } else {
36591a945772Spatrick mvpp2_prs_sram_bits_clear(pe, MVPP2_PRS_SRAM_SHIFT_SIGN_BIT, 1);
36601a945772Spatrick }
36611a945772Spatrick
36621a945772Spatrick pe->sram.byte[MVPP2_BIT_TO_BYTE(MVPP2_PRS_SRAM_SHIFT_OFFS)] |=
36631a945772Spatrick shift & MVPP2_PRS_SRAM_SHIFT_MASK;
36641a945772Spatrick mvpp2_prs_sram_bits_clear(pe, MVPP2_PRS_SRAM_OP_SEL_SHIFT_OFFS,
36651a945772Spatrick MVPP2_PRS_SRAM_OP_SEL_SHIFT_MASK);
36661a945772Spatrick mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_OP_SEL_SHIFT_OFFS, op);
36671a945772Spatrick mvpp2_prs_sram_bits_clear(pe, MVPP2_PRS_SRAM_OP_SEL_BASE_OFFS, 1);
36681a945772Spatrick }
36691a945772Spatrick
36701a945772Spatrick void
mvpp2_prs_sram_offset_set(struct mvpp2_prs_entry * pe,uint32_t type,int offset,uint32_t op)36711a945772Spatrick mvpp2_prs_sram_offset_set(struct mvpp2_prs_entry *pe, uint32_t type, int offset,
36721a945772Spatrick uint32_t op)
36731a945772Spatrick {
36741a945772Spatrick uint8_t udf_byte, udf_byte_offset;
36751a945772Spatrick uint8_t op_sel_udf_byte, op_sel_udf_byte_offset;
36761a945772Spatrick
36771a945772Spatrick udf_byte = MVPP2_BIT_TO_BYTE(MVPP2_PRS_SRAM_UDF_OFFS +
36781a945772Spatrick MVPP2_PRS_SRAM_UDF_BITS);
36791a945772Spatrick udf_byte_offset = (8 - (MVPP2_PRS_SRAM_UDF_OFFS % 8));
36801a945772Spatrick op_sel_udf_byte = MVPP2_BIT_TO_BYTE(MVPP2_PRS_SRAM_OP_SEL_UDF_OFFS +
36811a945772Spatrick MVPP2_PRS_SRAM_OP_SEL_UDF_BITS);
36821a945772Spatrick op_sel_udf_byte_offset = (8 - (MVPP2_PRS_SRAM_OP_SEL_UDF_OFFS % 8));
36831a945772Spatrick
36841a945772Spatrick if (offset < 0) {
36851a945772Spatrick mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_UDF_SIGN_BIT, 1);
36861a945772Spatrick offset = -offset;
36871a945772Spatrick } else {
36881a945772Spatrick mvpp2_prs_sram_bits_clear(pe, MVPP2_PRS_SRAM_UDF_SIGN_BIT, 1);
36891a945772Spatrick }
36901a945772Spatrick
36911a945772Spatrick mvpp2_prs_sram_bits_clear(pe, MVPP2_PRS_SRAM_UDF_OFFS,
36921a945772Spatrick MVPP2_PRS_SRAM_UDF_MASK);
36931a945772Spatrick mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_UDF_OFFS, offset);
36941a945772Spatrick pe->sram.byte[udf_byte] &= ~(MVPP2_PRS_SRAM_UDF_MASK >> udf_byte_offset);
36951a945772Spatrick pe->sram.byte[udf_byte] |= (offset >> udf_byte_offset);
36961a945772Spatrick mvpp2_prs_sram_bits_clear(pe, MVPP2_PRS_SRAM_UDF_TYPE_OFFS,
36971a945772Spatrick MVPP2_PRS_SRAM_UDF_TYPE_MASK);
36981a945772Spatrick mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_UDF_TYPE_OFFS, type);
36991a945772Spatrick mvpp2_prs_sram_bits_clear(pe, MVPP2_PRS_SRAM_OP_SEL_UDF_OFFS,
37001a945772Spatrick MVPP2_PRS_SRAM_OP_SEL_UDF_MASK);
37011a945772Spatrick mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_OP_SEL_UDF_OFFS, op);
37021a945772Spatrick pe->sram.byte[op_sel_udf_byte] &= ~(MVPP2_PRS_SRAM_OP_SEL_UDF_MASK >>
37031a945772Spatrick op_sel_udf_byte_offset);
37041a945772Spatrick pe->sram.byte[op_sel_udf_byte] |= (op >> op_sel_udf_byte_offset);
37051a945772Spatrick mvpp2_prs_sram_bits_clear(pe, MVPP2_PRS_SRAM_OP_SEL_BASE_OFFS, 1);
37061a945772Spatrick }
37071a945772Spatrick
37081a945772Spatrick void
mvpp2_prs_sram_next_lu_set(struct mvpp2_prs_entry * pe,uint32_t lu)37091a945772Spatrick mvpp2_prs_sram_next_lu_set(struct mvpp2_prs_entry *pe, uint32_t lu)
37101a945772Spatrick {
37111a945772Spatrick int sram_next_off = MVPP2_PRS_SRAM_NEXT_LU_OFFS;
37121a945772Spatrick
37131a945772Spatrick mvpp2_prs_sram_bits_clear(pe, sram_next_off, MVPP2_PRS_SRAM_NEXT_LU_MASK);
37141a945772Spatrick mvpp2_prs_sram_bits_set(pe, sram_next_off, lu);
37151a945772Spatrick }
37161a945772Spatrick
37171a945772Spatrick void
mvpp2_prs_shadow_set(struct mvpp2_softc * sc,int index,uint32_t lu)37181a945772Spatrick mvpp2_prs_shadow_set(struct mvpp2_softc *sc, int index, uint32_t lu)
37191a945772Spatrick {
37201a945772Spatrick sc->sc_prs_shadow[index].valid = 1;
37211a945772Spatrick sc->sc_prs_shadow[index].lu = lu;
37221a945772Spatrick }
37231a945772Spatrick
37241a945772Spatrick int
mvpp2_prs_hw_write(struct mvpp2_softc * sc,struct mvpp2_prs_entry * pe)37251a945772Spatrick mvpp2_prs_hw_write(struct mvpp2_softc *sc, struct mvpp2_prs_entry *pe)
37261a945772Spatrick {
37271a945772Spatrick int i;
37281a945772Spatrick
37291a945772Spatrick if (pe->index > MVPP2_PRS_TCAM_SRAM_SIZE - 1)
37301a945772Spatrick return EINVAL;
37311a945772Spatrick
37321a945772Spatrick pe->tcam.word[MVPP2_PRS_TCAM_INV_WORD] &= ~MVPP2_PRS_TCAM_INV_MASK;
37331a945772Spatrick mvpp2_write(sc, MVPP2_PRS_TCAM_IDX_REG, pe->index);
37341a945772Spatrick for (i = 0; i < MVPP2_PRS_TCAM_WORDS; i++)
37351a945772Spatrick mvpp2_write(sc, MVPP2_PRS_TCAM_DATA_REG(i), pe->tcam.word[i]);
37361a945772Spatrick mvpp2_write(sc, MVPP2_PRS_SRAM_IDX_REG, pe->index);
37371a945772Spatrick for (i = 0; i < MVPP2_PRS_SRAM_WORDS; i++)
37381a945772Spatrick mvpp2_write(sc, MVPP2_PRS_SRAM_DATA_REG(i), pe->sram.word[i]);
37391a945772Spatrick
37401a945772Spatrick return 0;
37411a945772Spatrick }
37421a945772Spatrick
37431a945772Spatrick int
mvpp2_prs_hw_read(struct mvpp2_softc * sc,struct mvpp2_prs_entry * pe,int tid)3744fad015d2Spatrick mvpp2_prs_hw_read(struct mvpp2_softc *sc, struct mvpp2_prs_entry *pe, int tid)
37451a945772Spatrick {
37461a945772Spatrick int i;
37471a945772Spatrick
3748fad015d2Spatrick if (tid > MVPP2_PRS_TCAM_SRAM_SIZE - 1)
37491a945772Spatrick return EINVAL;
37501a945772Spatrick
3751fad015d2Spatrick memset(pe, 0, sizeof(*pe));
3752fad015d2Spatrick pe->index = tid;
3753fad015d2Spatrick
37541a945772Spatrick mvpp2_write(sc, MVPP2_PRS_TCAM_IDX_REG, pe->index);
37551a945772Spatrick pe->tcam.word[MVPP2_PRS_TCAM_INV_WORD] =
37561a945772Spatrick mvpp2_read(sc, MVPP2_PRS_TCAM_DATA_REG(MVPP2_PRS_TCAM_INV_WORD));
37571a945772Spatrick if (pe->tcam.word[MVPP2_PRS_TCAM_INV_WORD] & MVPP2_PRS_TCAM_INV_MASK)
37581a945772Spatrick return EINVAL;
37591a945772Spatrick for (i = 0; i < MVPP2_PRS_TCAM_WORDS; i++)
37601a945772Spatrick pe->tcam.word[i] =
37611a945772Spatrick mvpp2_read(sc, MVPP2_PRS_TCAM_DATA_REG(i));
37621a945772Spatrick
37631a945772Spatrick mvpp2_write(sc, MVPP2_PRS_SRAM_IDX_REG, pe->index);
37641a945772Spatrick for (i = 0; i < MVPP2_PRS_SRAM_WORDS; i++)
37651a945772Spatrick pe->sram.word[i] =
37661a945772Spatrick mvpp2_read(sc, MVPP2_PRS_SRAM_DATA_REG(i));
37671a945772Spatrick
37681a945772Spatrick return 0;
37691a945772Spatrick }
37701a945772Spatrick
3771fef01367Spatrick int
mvpp2_prs_flow_find(struct mvpp2_softc * sc,int flow)37721a945772Spatrick mvpp2_prs_flow_find(struct mvpp2_softc *sc, int flow)
37731a945772Spatrick {
3774fef01367Spatrick struct mvpp2_prs_entry pe;
37751a945772Spatrick uint8_t bits;
37761a945772Spatrick int tid;
37771a945772Spatrick
37781a945772Spatrick for (tid = MVPP2_PRS_TCAM_SRAM_SIZE - 1; tid >= 0; tid--) {
37791a945772Spatrick if (!sc->sc_prs_shadow[tid].valid ||
37801a945772Spatrick sc->sc_prs_shadow[tid].lu != MVPP2_PRS_LU_FLOWS)
37811a945772Spatrick continue;
37821a945772Spatrick
3783fad015d2Spatrick mvpp2_prs_hw_read(sc, &pe, tid);
3784fef01367Spatrick bits = mvpp2_prs_sram_ai_get(&pe);
37851a945772Spatrick
37861a945772Spatrick if ((bits & MVPP2_PRS_FLOW_ID_MASK) == flow)
3787fef01367Spatrick return tid;
37881a945772Spatrick }
37891a945772Spatrick
3790fef01367Spatrick return -1;
37911a945772Spatrick }
37921a945772Spatrick
37931a945772Spatrick int
mvpp2_prs_tcam_first_free(struct mvpp2_softc * sc,uint8_t start,uint8_t end)37941a945772Spatrick mvpp2_prs_tcam_first_free(struct mvpp2_softc *sc, uint8_t start, uint8_t end)
37951a945772Spatrick {
37961a945772Spatrick uint8_t tmp;
37971a945772Spatrick int tid;
37981a945772Spatrick
37991a945772Spatrick if (start > end) {
38001a945772Spatrick tmp = end;
38011a945772Spatrick end = start;
38021a945772Spatrick start = tmp;
38031a945772Spatrick }
38041a945772Spatrick
38051a945772Spatrick for (tid = start; tid <= end; tid++) {
38061a945772Spatrick if (!sc->sc_prs_shadow[tid].valid)
38071a945772Spatrick return tid;
38081a945772Spatrick }
38091a945772Spatrick
38109da20cfaSpatrick return -1;
38111a945772Spatrick }
38121a945772Spatrick
38131a945772Spatrick void
mvpp2_prs_mac_drop_all_set(struct mvpp2_softc * sc,uint32_t port,int add)38141a945772Spatrick mvpp2_prs_mac_drop_all_set(struct mvpp2_softc *sc, uint32_t port, int add)
38151a945772Spatrick {
38161a945772Spatrick struct mvpp2_prs_entry pe;
38171a945772Spatrick
38181a945772Spatrick if (sc->sc_prs_shadow[MVPP2_PE_DROP_ALL].valid) {
3819fad015d2Spatrick mvpp2_prs_hw_read(sc, &pe, MVPP2_PE_DROP_ALL);
38201a945772Spatrick } else {
38211a945772Spatrick memset(&pe, 0, sizeof(pe));
38221a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC);
38231a945772Spatrick pe.index = MVPP2_PE_DROP_ALL;
38241a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_DROP_MASK,
38251a945772Spatrick MVPP2_PRS_RI_DROP_MASK);
38261a945772Spatrick mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
38271a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
38281a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_MAC);
38291a945772Spatrick mvpp2_prs_tcam_port_map_set(&pe, 0);
38301a945772Spatrick }
38311a945772Spatrick
38321a945772Spatrick mvpp2_prs_tcam_port_set(&pe, port, add);
38331a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
38341a945772Spatrick }
38351a945772Spatrick
38361a945772Spatrick void
mvpp2_prs_mac_promisc_set(struct mvpp2_softc * sc,uint32_t port,int l2_cast,int add)383741cd246cSpatrick mvpp2_prs_mac_promisc_set(struct mvpp2_softc *sc, uint32_t port, int l2_cast,
383841cd246cSpatrick int add)
38391a945772Spatrick {
38401a945772Spatrick struct mvpp2_prs_entry pe;
384141cd246cSpatrick uint8_t cast_match;
384241cd246cSpatrick uint32_t ri;
384341cd246cSpatrick int tid;
38441a945772Spatrick
384541cd246cSpatrick if (l2_cast == MVPP2_PRS_L2_UNI_CAST) {
384641cd246cSpatrick cast_match = MVPP2_PRS_UCAST_VAL;
384741cd246cSpatrick tid = MVPP2_PE_MAC_UC_PROMISCUOUS;
384841cd246cSpatrick ri = MVPP2_PRS_RI_L2_UCAST;
384941cd246cSpatrick } else {
385041cd246cSpatrick cast_match = MVPP2_PRS_MCAST_VAL;
385141cd246cSpatrick tid = MVPP2_PE_MAC_MC_PROMISCUOUS;
385241cd246cSpatrick ri = MVPP2_PRS_RI_L2_MCAST;
385341cd246cSpatrick }
385441cd246cSpatrick
385541cd246cSpatrick if (sc->sc_prs_shadow[tid].valid) {
385641cd246cSpatrick mvpp2_prs_hw_read(sc, &pe, tid);
38571a945772Spatrick } else {
38581a945772Spatrick memset(&pe, 0, sizeof(pe));
38591a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC);
386041cd246cSpatrick pe.index = tid;
38611a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_DSA);
386241cd246cSpatrick mvpp2_prs_sram_ri_update(&pe, ri, MVPP2_PRS_RI_L2_CAST_MASK);
386341cd246cSpatrick mvpp2_prs_tcam_data_byte_set(&pe, 0, cast_match,
386441cd246cSpatrick MVPP2_PRS_CAST_MASK);
38651a945772Spatrick mvpp2_prs_sram_shift_set(&pe, 2 * ETHER_ADDR_LEN,
38661a945772Spatrick MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
38671a945772Spatrick mvpp2_prs_tcam_port_map_set(&pe, 0);
38681a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_MAC);
38691a945772Spatrick }
38701a945772Spatrick
38711a945772Spatrick mvpp2_prs_tcam_port_set(&pe, port, add);
38721a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
38731a945772Spatrick }
38741a945772Spatrick
38751a945772Spatrick void
mvpp2_prs_dsa_tag_set(struct mvpp2_softc * sc,uint32_t port,int add,int tagged,int extend)38761a945772Spatrick mvpp2_prs_dsa_tag_set(struct mvpp2_softc *sc, uint32_t port, int add,
38771a945772Spatrick int tagged, int extend)
38781a945772Spatrick {
38791a945772Spatrick struct mvpp2_prs_entry pe;
38801a945772Spatrick int32_t tid, shift;
38811a945772Spatrick
38821a945772Spatrick if (extend) {
38831a945772Spatrick tid = tagged ? MVPP2_PE_EDSA_TAGGED : MVPP2_PE_EDSA_UNTAGGED;
38841a945772Spatrick shift = 8;
38851a945772Spatrick } else {
38861a945772Spatrick tid = tagged ? MVPP2_PE_DSA_TAGGED : MVPP2_PE_DSA_UNTAGGED;
38871a945772Spatrick shift = 4;
38881a945772Spatrick }
38891a945772Spatrick
38901a945772Spatrick if (sc->sc_prs_shadow[tid].valid) {
3891fad015d2Spatrick mvpp2_prs_hw_read(sc, &pe, tid);
38921a945772Spatrick } else {
38931a945772Spatrick memset(&pe, 0, sizeof(pe));
38941a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_DSA);
38951a945772Spatrick pe.index = tid;
38961a945772Spatrick mvpp2_prs_sram_shift_set(&pe, shift,
38971a945772Spatrick MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
38981a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_DSA);
38991a945772Spatrick if (tagged) {
39001a945772Spatrick mvpp2_prs_tcam_data_byte_set(&pe, 0,
39011a945772Spatrick MVPP2_PRS_TCAM_DSA_TAGGED_BIT,
39021a945772Spatrick MVPP2_PRS_TCAM_DSA_TAGGED_BIT);
39031a945772Spatrick mvpp2_prs_sram_ai_update(&pe, 0, MVPP2_PRS_SRAM_AI_MASK);
39041a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_VLAN);
39051a945772Spatrick } else {
39061a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_VLAN_NONE,
39071a945772Spatrick MVPP2_PRS_RI_VLAN_MASK);
39081a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_L2);
39091a945772Spatrick }
39101a945772Spatrick mvpp2_prs_tcam_port_map_set(&pe, 0);
39111a945772Spatrick }
39121a945772Spatrick
39131a945772Spatrick mvpp2_prs_tcam_port_set(&pe, port, add);
39141a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
39151a945772Spatrick }
39161a945772Spatrick
39171a945772Spatrick void
mvpp2_prs_dsa_tag_ethertype_set(struct mvpp2_softc * sc,uint32_t port,int add,int tagged,int extend)39181a945772Spatrick mvpp2_prs_dsa_tag_ethertype_set(struct mvpp2_softc *sc, uint32_t port,
39191a945772Spatrick int add, int tagged, int extend)
39201a945772Spatrick {
39211a945772Spatrick struct mvpp2_prs_entry pe;
39221a945772Spatrick int32_t tid, shift, port_mask;
39231a945772Spatrick
39241a945772Spatrick if (extend) {
39251a945772Spatrick tid = tagged ? MVPP2_PE_EDSA_TAGGED : MVPP2_PE_EDSA_UNTAGGED;
39261a945772Spatrick port_mask = 0;
39271a945772Spatrick shift = 8;
39281a945772Spatrick } else {
39291a945772Spatrick tid = tagged ? MVPP2_PE_DSA_TAGGED : MVPP2_PE_DSA_UNTAGGED;
39301a945772Spatrick port_mask = MVPP2_PRS_PORT_MASK;
39311a945772Spatrick shift = 4;
39321a945772Spatrick }
39331a945772Spatrick
39341a945772Spatrick if (sc->sc_prs_shadow[tid].valid) {
3935fad015d2Spatrick mvpp2_prs_hw_read(sc, &pe, tid);
39361a945772Spatrick } else {
39371a945772Spatrick memset(&pe, 0, sizeof(pe));
39381a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_DSA);
39391a945772Spatrick pe.index = tid;
3940e042150eSpatrick mvpp2_prs_match_etype(&pe, 0, 0xdada);
39411a945772Spatrick mvpp2_prs_match_etype(&pe, 2, 0);
39421a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_DSA_MASK,
39431a945772Spatrick MVPP2_PRS_RI_DSA_MASK);
39441a945772Spatrick mvpp2_prs_sram_shift_set(&pe, 2 * ETHER_ADDR_LEN + shift,
39451a945772Spatrick MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
39461a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_DSA);
39471a945772Spatrick if (tagged) {
39481a945772Spatrick mvpp2_prs_tcam_data_byte_set(&pe,
39491a945772Spatrick MVPP2_ETH_TYPE_LEN + 2 + 3,
39501a945772Spatrick MVPP2_PRS_TCAM_DSA_TAGGED_BIT,
39511a945772Spatrick MVPP2_PRS_TCAM_DSA_TAGGED_BIT);
39521a945772Spatrick mvpp2_prs_sram_ai_update(&pe, 0, MVPP2_PRS_SRAM_AI_MASK);
39531a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_VLAN);
39541a945772Spatrick } else {
39551a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_VLAN_NONE,
39561a945772Spatrick MVPP2_PRS_RI_VLAN_MASK);
39571a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_L2);
39581a945772Spatrick }
39591a945772Spatrick mvpp2_prs_tcam_port_map_set(&pe, port_mask);
39601a945772Spatrick }
39611a945772Spatrick
39621a945772Spatrick mvpp2_prs_tcam_port_set(&pe, port, add);
39631a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
39641a945772Spatrick }
39651a945772Spatrick
39661a945772Spatrick struct mvpp2_prs_entry *
mvpp2_prs_vlan_find(struct mvpp2_softc * sc,uint16_t tpid,int ai)39671a945772Spatrick mvpp2_prs_vlan_find(struct mvpp2_softc *sc, uint16_t tpid, int ai)
39681a945772Spatrick {
39691a945772Spatrick struct mvpp2_prs_entry *pe;
39701a945772Spatrick uint32_t ri_bits, ai_bits;
39711a945772Spatrick int match, tid;
39721a945772Spatrick
39731a945772Spatrick pe = malloc(sizeof(*pe), M_TEMP, M_NOWAIT);
39741a945772Spatrick if (pe == NULL)
39751a945772Spatrick return NULL;
39761a945772Spatrick
39771a945772Spatrick mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
39781a945772Spatrick
39791a945772Spatrick for (tid = MVPP2_PE_FIRST_FREE_TID; tid <= MVPP2_PE_LAST_FREE_TID; tid++) {
39801a945772Spatrick if (!sc->sc_prs_shadow[tid].valid ||
39811a945772Spatrick sc->sc_prs_shadow[tid].lu != MVPP2_PRS_LU_VLAN)
39821a945772Spatrick continue;
3983fad015d2Spatrick mvpp2_prs_hw_read(sc, pe, tid);
39841a945772Spatrick match = mvpp2_prs_tcam_data_cmp(pe, 0, swap16(tpid));
39851a945772Spatrick if (!match)
39861a945772Spatrick continue;
39871a945772Spatrick ri_bits = mvpp2_prs_sram_ri_get(pe);
39881a945772Spatrick ri_bits &= MVPP2_PRS_RI_VLAN_MASK;
39891a945772Spatrick ai_bits = mvpp2_prs_tcam_ai_get(pe);
39901a945772Spatrick ai_bits &= ~MVPP2_PRS_DBL_VLAN_AI_BIT;
39911a945772Spatrick if (ai != ai_bits)
39921a945772Spatrick continue;
39931a945772Spatrick if (ri_bits == MVPP2_PRS_RI_VLAN_SINGLE ||
39941a945772Spatrick ri_bits == MVPP2_PRS_RI_VLAN_TRIPLE)
39951a945772Spatrick return pe;
39961a945772Spatrick }
39971a945772Spatrick
39981a945772Spatrick free(pe, M_TEMP, sizeof(*pe));
39991a945772Spatrick return NULL;
40001a945772Spatrick }
40011a945772Spatrick
40021a945772Spatrick int
mvpp2_prs_vlan_add(struct mvpp2_softc * sc,uint16_t tpid,int ai,uint32_t port_map)40031a945772Spatrick mvpp2_prs_vlan_add(struct mvpp2_softc *sc, uint16_t tpid, int ai, uint32_t port_map)
40041a945772Spatrick {
40051a945772Spatrick struct mvpp2_prs_entry *pe;
40061a945772Spatrick uint32_t ri_bits;
40071a945772Spatrick int tid_aux, tid;
40081a945772Spatrick int ret = 0;
40091a945772Spatrick
40101a945772Spatrick pe = mvpp2_prs_vlan_find(sc, tpid, ai);
40111a945772Spatrick if (pe == NULL) {
40121a945772Spatrick tid = mvpp2_prs_tcam_first_free(sc, MVPP2_PE_LAST_FREE_TID,
40131a945772Spatrick MVPP2_PE_FIRST_FREE_TID);
40141a945772Spatrick if (tid < 0)
40151a945772Spatrick return tid;
40161a945772Spatrick
40171a945772Spatrick pe = malloc(sizeof(*pe), M_TEMP, M_NOWAIT);
40181a945772Spatrick if (pe == NULL)
40191a945772Spatrick return ENOMEM;
40201a945772Spatrick
40211a945772Spatrick /* get last double vlan tid */
40221a945772Spatrick for (tid_aux = MVPP2_PE_LAST_FREE_TID;
40231a945772Spatrick tid_aux >= MVPP2_PE_FIRST_FREE_TID; tid_aux--) {
40241a945772Spatrick if (!sc->sc_prs_shadow[tid_aux].valid ||
40251a945772Spatrick sc->sc_prs_shadow[tid_aux].lu != MVPP2_PRS_LU_VLAN)
40261a945772Spatrick continue;
4027fad015d2Spatrick mvpp2_prs_hw_read(sc, pe, tid_aux);
40281a945772Spatrick ri_bits = mvpp2_prs_sram_ri_get(pe);
40291a945772Spatrick if ((ri_bits & MVPP2_PRS_RI_VLAN_MASK) ==
40301a945772Spatrick MVPP2_PRS_RI_VLAN_DOUBLE)
40311a945772Spatrick break;
40321a945772Spatrick }
40331a945772Spatrick
40341a945772Spatrick if (tid <= tid_aux) {
40351a945772Spatrick ret = EINVAL;
40361a945772Spatrick goto error;
40371a945772Spatrick }
40381a945772Spatrick
4039ce2a9341Spatrick memset(pe, 0, sizeof(*pe));
40401a945772Spatrick mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
40411a945772Spatrick pe->index = tid;
40421a945772Spatrick mvpp2_prs_match_etype(pe, 0, tpid);
40431a945772Spatrick mvpp2_prs_sram_next_lu_set(pe, MVPP2_PRS_LU_L2);
40441a945772Spatrick mvpp2_prs_sram_shift_set(pe, MVPP2_VLAN_TAG_LEN,
40451a945772Spatrick MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
40461a945772Spatrick mvpp2_prs_sram_ai_update(pe, 0, MVPP2_PRS_SRAM_AI_MASK);
40471a945772Spatrick if (ai == MVPP2_PRS_SINGLE_VLAN_AI) {
40481a945772Spatrick mvpp2_prs_sram_ri_update(pe, MVPP2_PRS_RI_VLAN_SINGLE,
40491a945772Spatrick MVPP2_PRS_RI_VLAN_MASK);
40501a945772Spatrick } else {
40511a945772Spatrick ai |= MVPP2_PRS_DBL_VLAN_AI_BIT;
40521a945772Spatrick mvpp2_prs_sram_ri_update(pe, MVPP2_PRS_RI_VLAN_TRIPLE,
40531a945772Spatrick MVPP2_PRS_RI_VLAN_MASK);
40541a945772Spatrick }
40551a945772Spatrick mvpp2_prs_tcam_ai_update(pe, ai, MVPP2_PRS_SRAM_AI_MASK);
40561a945772Spatrick mvpp2_prs_shadow_set(sc, pe->index, MVPP2_PRS_LU_VLAN);
40571a945772Spatrick }
40581a945772Spatrick
40591a945772Spatrick mvpp2_prs_tcam_port_map_set(pe, port_map);
40601a945772Spatrick mvpp2_prs_hw_write(sc, pe);
40611a945772Spatrick
40621a945772Spatrick error:
40631a945772Spatrick free(pe, M_TEMP, sizeof(*pe));
40641a945772Spatrick return ret;
40651a945772Spatrick }
40661a945772Spatrick
40671a945772Spatrick int
mvpp2_prs_double_vlan_ai_free_get(struct mvpp2_softc * sc)40681a945772Spatrick mvpp2_prs_double_vlan_ai_free_get(struct mvpp2_softc *sc)
40691a945772Spatrick {
40701a945772Spatrick int i;
40711a945772Spatrick
40721a945772Spatrick for (i = 1; i < MVPP2_PRS_DBL_VLANS_MAX; i++)
40731a945772Spatrick if (!sc->sc_prs_double_vlans[i])
40741a945772Spatrick return i;
40751a945772Spatrick
40769da20cfaSpatrick return -1;
40771a945772Spatrick }
40781a945772Spatrick
40791a945772Spatrick struct mvpp2_prs_entry *
mvpp2_prs_double_vlan_find(struct mvpp2_softc * sc,uint16_t tpid1,uint16_t tpid2)40801a945772Spatrick mvpp2_prs_double_vlan_find(struct mvpp2_softc *sc, uint16_t tpid1, uint16_t tpid2)
40811a945772Spatrick {
40821a945772Spatrick struct mvpp2_prs_entry *pe;
40831a945772Spatrick uint32_t ri_mask;
40841a945772Spatrick int match, tid;
40851a945772Spatrick
40861a945772Spatrick pe = malloc(sizeof(*pe), M_TEMP, M_NOWAIT);
40871a945772Spatrick if (pe == NULL)
40881a945772Spatrick return NULL;
40891a945772Spatrick
40901a945772Spatrick mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
40911a945772Spatrick
40921a945772Spatrick for (tid = MVPP2_PE_FIRST_FREE_TID; tid <= MVPP2_PE_LAST_FREE_TID; tid++) {
40931a945772Spatrick if (!sc->sc_prs_shadow[tid].valid ||
40941a945772Spatrick sc->sc_prs_shadow[tid].lu != MVPP2_PRS_LU_VLAN)
40951a945772Spatrick continue;
40961a945772Spatrick
4097fad015d2Spatrick mvpp2_prs_hw_read(sc, pe, tid);
40981a945772Spatrick match = mvpp2_prs_tcam_data_cmp(pe, 0, swap16(tpid1)) &&
40991a945772Spatrick mvpp2_prs_tcam_data_cmp(pe, 4, swap16(tpid2));
41001a945772Spatrick if (!match)
41011a945772Spatrick continue;
41021a945772Spatrick ri_mask = mvpp2_prs_sram_ri_get(pe) & MVPP2_PRS_RI_VLAN_MASK;
41031a945772Spatrick if (ri_mask == MVPP2_PRS_RI_VLAN_DOUBLE)
41041a945772Spatrick return pe;
41051a945772Spatrick }
41061a945772Spatrick
41071a945772Spatrick free(pe, M_TEMP, sizeof(*pe));
41081a945772Spatrick return NULL;
41091a945772Spatrick }
41101a945772Spatrick
41111a945772Spatrick int
mvpp2_prs_double_vlan_add(struct mvpp2_softc * sc,uint16_t tpid1,uint16_t tpid2,uint32_t port_map)41121a945772Spatrick mvpp2_prs_double_vlan_add(struct mvpp2_softc *sc, uint16_t tpid1, uint16_t tpid2,
41131a945772Spatrick uint32_t port_map)
41141a945772Spatrick {
41151a945772Spatrick struct mvpp2_prs_entry *pe;
41161a945772Spatrick int tid_aux, tid, ai, ret = 0;
41171a945772Spatrick uint32_t ri_bits;
41181a945772Spatrick
41191a945772Spatrick pe = mvpp2_prs_double_vlan_find(sc, tpid1, tpid2);
41201a945772Spatrick if (pe == NULL) {
41211a945772Spatrick tid = mvpp2_prs_tcam_first_free(sc, MVPP2_PE_FIRST_FREE_TID,
41221a945772Spatrick MVPP2_PE_LAST_FREE_TID);
41231a945772Spatrick if (tid < 0)
41241a945772Spatrick return tid;
41251a945772Spatrick
41261a945772Spatrick pe = malloc(sizeof(*pe), M_TEMP, M_NOWAIT);
41271a945772Spatrick if (pe == NULL)
41281a945772Spatrick return ENOMEM;
41291a945772Spatrick
41301a945772Spatrick ai = mvpp2_prs_double_vlan_ai_free_get(sc);
41311a945772Spatrick if (ai < 0) {
41321a945772Spatrick ret = ai;
41331a945772Spatrick goto error;
41341a945772Spatrick }
41351a945772Spatrick
41361a945772Spatrick for (tid_aux = MVPP2_PE_FIRST_FREE_TID;
41371a945772Spatrick tid_aux <= MVPP2_PE_LAST_FREE_TID; tid_aux++) {
41381a945772Spatrick if (!sc->sc_prs_shadow[tid_aux].valid ||
41391a945772Spatrick sc->sc_prs_shadow[tid_aux].lu != MVPP2_PRS_LU_VLAN)
41401a945772Spatrick continue;
4141fad015d2Spatrick mvpp2_prs_hw_read(sc, pe, tid_aux);
41421a945772Spatrick ri_bits = mvpp2_prs_sram_ri_get(pe);
41431a945772Spatrick ri_bits &= MVPP2_PRS_RI_VLAN_MASK;
41441a945772Spatrick if (ri_bits == MVPP2_PRS_RI_VLAN_SINGLE ||
41451a945772Spatrick ri_bits == MVPP2_PRS_RI_VLAN_TRIPLE)
41461a945772Spatrick break;
41471a945772Spatrick }
41481a945772Spatrick
41491a945772Spatrick if (tid >= tid_aux) {
41501a945772Spatrick ret = ERANGE;
41511a945772Spatrick goto error;
41521a945772Spatrick }
41531a945772Spatrick
4154ce2a9341Spatrick memset(pe, 0, sizeof(*pe));
41551a945772Spatrick mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
41561a945772Spatrick pe->index = tid;
41571a945772Spatrick sc->sc_prs_double_vlans[ai] = 1;
41581a945772Spatrick mvpp2_prs_match_etype(pe, 0, tpid1);
41591a945772Spatrick mvpp2_prs_match_etype(pe, 4, tpid2);
41601a945772Spatrick mvpp2_prs_sram_next_lu_set(pe, MVPP2_PRS_LU_VLAN);
41611a945772Spatrick mvpp2_prs_sram_shift_set(pe, 2 * MVPP2_VLAN_TAG_LEN,
41621a945772Spatrick MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
41631a945772Spatrick mvpp2_prs_sram_ri_update(pe, MVPP2_PRS_RI_VLAN_DOUBLE,
41641a945772Spatrick MVPP2_PRS_RI_VLAN_MASK);
41651a945772Spatrick mvpp2_prs_sram_ai_update(pe, ai | MVPP2_PRS_DBL_VLAN_AI_BIT,
41661a945772Spatrick MVPP2_PRS_SRAM_AI_MASK);
41671a945772Spatrick mvpp2_prs_shadow_set(sc, pe->index, MVPP2_PRS_LU_VLAN);
41681a945772Spatrick }
41691a945772Spatrick
41701a945772Spatrick mvpp2_prs_tcam_port_map_set(pe, port_map);
41711a945772Spatrick mvpp2_prs_hw_write(sc, pe);
41721a945772Spatrick
41731a945772Spatrick error:
41741a945772Spatrick free(pe, M_TEMP, sizeof(*pe));
41751a945772Spatrick return ret;
41761a945772Spatrick }
41771a945772Spatrick
41781a945772Spatrick int
mvpp2_prs_ip4_proto(struct mvpp2_softc * sc,uint16_t proto,uint32_t ri,uint32_t ri_mask)41791a945772Spatrick mvpp2_prs_ip4_proto(struct mvpp2_softc *sc, uint16_t proto, uint32_t ri,
41801a945772Spatrick uint32_t ri_mask)
41811a945772Spatrick {
41821a945772Spatrick struct mvpp2_prs_entry pe;
41831a945772Spatrick int tid;
41841a945772Spatrick
4185e042150eSpatrick if ((proto != IPPROTO_TCP) && (proto != IPPROTO_UDP) &&
4186e042150eSpatrick (proto != IPPROTO_IGMP))
41871a945772Spatrick return EINVAL;
41881a945772Spatrick
41891a945772Spatrick tid = mvpp2_prs_tcam_first_free(sc, MVPP2_PE_FIRST_FREE_TID,
41901a945772Spatrick MVPP2_PE_LAST_FREE_TID);
41911a945772Spatrick if (tid < 0)
41921a945772Spatrick return tid;
41931a945772Spatrick
4194ce2a9341Spatrick memset(&pe, 0, sizeof(pe));
41951a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP4);
41961a945772Spatrick pe.index = tid;
41971a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP4);
41981a945772Spatrick mvpp2_prs_sram_shift_set(&pe, 12, MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
41991a945772Spatrick mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L4,
42001a945772Spatrick sizeof(struct ip) - 4, MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
42011a945772Spatrick mvpp2_prs_sram_ai_update(&pe, MVPP2_PRS_IPV4_DIP_AI_BIT,
42021a945772Spatrick MVPP2_PRS_IPV4_DIP_AI_BIT);
4203e7c76d8bSpatrick mvpp2_prs_sram_ri_update(&pe, ri, ri_mask | MVPP2_PRS_RI_IP_FRAG_MASK);
4204e7c76d8bSpatrick mvpp2_prs_tcam_data_byte_set(&pe, 2, 0x00, MVPP2_PRS_TCAM_PROTO_MASK_L);
4205e7c76d8bSpatrick mvpp2_prs_tcam_data_byte_set(&pe, 3, 0x00, MVPP2_PRS_TCAM_PROTO_MASK);
42061a945772Spatrick mvpp2_prs_tcam_data_byte_set(&pe, 5, proto, MVPP2_PRS_TCAM_PROTO_MASK);
42071a945772Spatrick mvpp2_prs_tcam_ai_update(&pe, 0, MVPP2_PRS_IPV4_DIP_AI_BIT);
42081a945772Spatrick mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
42091a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_IP4);
42101a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
42111a945772Spatrick
42121a945772Spatrick tid = mvpp2_prs_tcam_first_free(sc, MVPP2_PE_FIRST_FREE_TID,
42131a945772Spatrick MVPP2_PE_LAST_FREE_TID);
42141a945772Spatrick if (tid < 0)
42151a945772Spatrick return tid;
42161a945772Spatrick
42171a945772Spatrick pe.index = tid;
42181a945772Spatrick pe.sram.word[MVPP2_PRS_SRAM_RI_WORD] = 0x0;
42191a945772Spatrick pe.sram.word[MVPP2_PRS_SRAM_RI_CTRL_WORD] = 0x0;
42201a945772Spatrick mvpp2_prs_sram_ri_update(&pe, ri, ri_mask);
4221e7c76d8bSpatrick mvpp2_prs_sram_ri_update(&pe, ri | MVPP2_PRS_RI_IP_FRAG_MASK,
4222e7c76d8bSpatrick ri_mask | MVPP2_PRS_RI_IP_FRAG_MASK);
4223e7c76d8bSpatrick mvpp2_prs_tcam_data_byte_set(&pe, 2, 0x00, 0x0);
4224e7c76d8bSpatrick mvpp2_prs_tcam_data_byte_set(&pe, 3, 0x00, 0x0);
42251a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_IP4);
42261a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
42271a945772Spatrick
42281a945772Spatrick return 0;
42291a945772Spatrick }
42301a945772Spatrick
42311a945772Spatrick int
mvpp2_prs_ip4_cast(struct mvpp2_softc * sc,uint16_t l3_cast)42321a945772Spatrick mvpp2_prs_ip4_cast(struct mvpp2_softc *sc, uint16_t l3_cast)
42331a945772Spatrick {
42341a945772Spatrick struct mvpp2_prs_entry pe;
42351a945772Spatrick int mask, tid;
42361a945772Spatrick
42371a945772Spatrick tid = mvpp2_prs_tcam_first_free(sc, MVPP2_PE_FIRST_FREE_TID,
42381a945772Spatrick MVPP2_PE_LAST_FREE_TID);
42391a945772Spatrick if (tid < 0)
42401a945772Spatrick return tid;
42411a945772Spatrick
4242ce2a9341Spatrick memset(&pe, 0, sizeof(pe));
42431a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP4);
42441a945772Spatrick pe.index = tid;
42451a945772Spatrick
42461a945772Spatrick switch (l3_cast) {
42471a945772Spatrick case MVPP2_PRS_L3_MULTI_CAST:
42481a945772Spatrick mvpp2_prs_tcam_data_byte_set(&pe, 0, MVPP2_PRS_IPV4_MC,
42491a945772Spatrick MVPP2_PRS_IPV4_MC_MASK);
42501a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_MCAST,
42511a945772Spatrick MVPP2_PRS_RI_L3_ADDR_MASK);
42521a945772Spatrick break;
42531a945772Spatrick case MVPP2_PRS_L3_BROAD_CAST:
42541a945772Spatrick mask = MVPP2_PRS_IPV4_BC_MASK;
42551a945772Spatrick mvpp2_prs_tcam_data_byte_set(&pe, 0, mask, mask);
42561a945772Spatrick mvpp2_prs_tcam_data_byte_set(&pe, 1, mask, mask);
42571a945772Spatrick mvpp2_prs_tcam_data_byte_set(&pe, 2, mask, mask);
42581a945772Spatrick mvpp2_prs_tcam_data_byte_set(&pe, 3, mask, mask);
42591a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_BCAST,
42601a945772Spatrick MVPP2_PRS_RI_L3_ADDR_MASK);
42611a945772Spatrick break;
42621a945772Spatrick default:
42631a945772Spatrick return EINVAL;
42641a945772Spatrick }
42651a945772Spatrick
42661a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
42671a945772Spatrick mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
42681a945772Spatrick mvpp2_prs_tcam_ai_update(&pe, MVPP2_PRS_IPV4_DIP_AI_BIT,
42691a945772Spatrick MVPP2_PRS_IPV4_DIP_AI_BIT);
42701a945772Spatrick mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
42711a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_IP4);
42721a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
42731a945772Spatrick
42741a945772Spatrick return 0;
42751a945772Spatrick }
42761a945772Spatrick
42771a945772Spatrick int
mvpp2_prs_ip6_proto(struct mvpp2_softc * sc,uint16_t proto,uint32_t ri,uint32_t ri_mask)42781a945772Spatrick mvpp2_prs_ip6_proto(struct mvpp2_softc *sc, uint16_t proto, uint32_t ri,
42791a945772Spatrick uint32_t ri_mask)
42801a945772Spatrick {
42811a945772Spatrick struct mvpp2_prs_entry pe;
42821a945772Spatrick int tid;
42831a945772Spatrick
4284e042150eSpatrick if ((proto != IPPROTO_TCP) && (proto != IPPROTO_UDP) &&
4285e042150eSpatrick (proto != IPPROTO_ICMPV6) && (proto != IPPROTO_IPIP))
42861a945772Spatrick return EINVAL;
42871a945772Spatrick
42881a945772Spatrick tid = mvpp2_prs_tcam_first_free(sc, MVPP2_PE_FIRST_FREE_TID,
42891a945772Spatrick MVPP2_PE_LAST_FREE_TID);
42901a945772Spatrick if (tid < 0)
42911a945772Spatrick return tid;
42921a945772Spatrick
4293ce2a9341Spatrick memset(&pe, 0, sizeof(pe));
42941a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP6);
42951a945772Spatrick pe.index = tid;
42961a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
42971a945772Spatrick mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
42981a945772Spatrick mvpp2_prs_sram_ri_update(&pe, ri, ri_mask);
42991a945772Spatrick mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L4,
43001a945772Spatrick sizeof(struct ip6_hdr) - 6, MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
43011a945772Spatrick mvpp2_prs_tcam_data_byte_set(&pe, 0, proto, MVPP2_PRS_TCAM_PROTO_MASK);
43021a945772Spatrick mvpp2_prs_tcam_ai_update(&pe, MVPP2_PRS_IPV6_NO_EXT_AI_BIT,
43031a945772Spatrick MVPP2_PRS_IPV6_NO_EXT_AI_BIT);
43041a945772Spatrick mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
43051a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_IP6);
43061a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
43071a945772Spatrick
43081a945772Spatrick return 0;
43091a945772Spatrick }
43101a945772Spatrick
43111a945772Spatrick int
mvpp2_prs_ip6_cast(struct mvpp2_softc * sc,uint16_t l3_cast)43121a945772Spatrick mvpp2_prs_ip6_cast(struct mvpp2_softc *sc, uint16_t l3_cast)
43131a945772Spatrick {
43141a945772Spatrick struct mvpp2_prs_entry pe;
43151a945772Spatrick int tid;
43161a945772Spatrick
43171a945772Spatrick if (l3_cast != MVPP2_PRS_L3_MULTI_CAST)
43181a945772Spatrick return EINVAL;
43191a945772Spatrick
4320e7c76d8bSpatrick tid = mvpp2_prs_tcam_first_free(sc, MVPP2_PE_FIRST_FREE_TID,
4321e7c76d8bSpatrick MVPP2_PE_LAST_FREE_TID);
43221a945772Spatrick if (tid < 0)
43231a945772Spatrick return tid;
43241a945772Spatrick
4325ce2a9341Spatrick memset(&pe, 0, sizeof(pe));
43261a945772Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_IP6);
43271a945772Spatrick pe.index = tid;
43281a945772Spatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP6);
43291a945772Spatrick mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_MCAST,
43301a945772Spatrick MVPP2_PRS_RI_L3_ADDR_MASK);
43311a945772Spatrick mvpp2_prs_sram_ai_update(&pe, MVPP2_PRS_IPV6_NO_EXT_AI_BIT,
43321a945772Spatrick MVPP2_PRS_IPV6_NO_EXT_AI_BIT);
43331a945772Spatrick mvpp2_prs_sram_shift_set(&pe, -18, MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
43341a945772Spatrick mvpp2_prs_tcam_data_byte_set(&pe, 0, MVPP2_PRS_IPV6_MC,
43351a945772Spatrick MVPP2_PRS_IPV6_MC_MASK);
43361a945772Spatrick mvpp2_prs_tcam_ai_update(&pe, 0, MVPP2_PRS_IPV6_NO_EXT_AI_BIT);
43371a945772Spatrick mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
43381a945772Spatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_IP6);
43391a945772Spatrick mvpp2_prs_hw_write(sc, &pe);
43401a945772Spatrick
43411a945772Spatrick return 0;
43421a945772Spatrick }
43431a945772Spatrick
43441a945772Spatrick int
mvpp2_prs_mac_range_equals(struct mvpp2_prs_entry * pe,const uint8_t * da,uint8_t * mask)43451a945772Spatrick mvpp2_prs_mac_range_equals(struct mvpp2_prs_entry *pe, const uint8_t *da,
43461a945772Spatrick uint8_t *mask)
43471a945772Spatrick {
43481a945772Spatrick uint8_t tcam_byte, tcam_mask;
43491a945772Spatrick int index;
43501a945772Spatrick
43511a945772Spatrick for (index = 0; index < ETHER_ADDR_LEN; index++) {
43521a945772Spatrick mvpp2_prs_tcam_data_byte_get(pe, index, &tcam_byte,
43531a945772Spatrick &tcam_mask);
43541a945772Spatrick if (tcam_mask != mask[index])
43551a945772Spatrick return 0;
43561a945772Spatrick if ((tcam_mask & tcam_byte) != (da[index] & mask[index]))
43571a945772Spatrick return 0;
43581a945772Spatrick }
43591a945772Spatrick
43601a945772Spatrick return 1;
43611a945772Spatrick }
43621a945772Spatrick
436341cd246cSpatrick int
mvpp2_prs_mac_da_range_find(struct mvpp2_softc * sc,int pmap,const uint8_t * da,uint8_t * mask,int udf_type)43641a945772Spatrick mvpp2_prs_mac_da_range_find(struct mvpp2_softc *sc, int pmap, const uint8_t *da,
43651a945772Spatrick uint8_t *mask, int udf_type)
43661a945772Spatrick {
436741cd246cSpatrick struct mvpp2_prs_entry pe;
43681a945772Spatrick int tid;
43691a945772Spatrick
4370ce595ab8Spatrick for (tid = MVPP2_PE_MAC_RANGE_START; tid <= MVPP2_PE_MAC_RANGE_END;
43711a945772Spatrick tid++) {
43721a945772Spatrick uint32_t entry_pmap;
43731a945772Spatrick
43741a945772Spatrick if (!sc->sc_prs_shadow[tid].valid ||
43751a945772Spatrick (sc->sc_prs_shadow[tid].lu != MVPP2_PRS_LU_MAC) ||
43761a945772Spatrick (sc->sc_prs_shadow[tid].udf != udf_type))
43771a945772Spatrick continue;
43781a945772Spatrick
437941cd246cSpatrick mvpp2_prs_hw_read(sc, &pe, tid);
438041cd246cSpatrick entry_pmap = mvpp2_prs_tcam_port_map_get(&pe);
438141cd246cSpatrick if (mvpp2_prs_mac_range_equals(&pe, da, mask) &&
43821a945772Spatrick entry_pmap == pmap)
438341cd246cSpatrick return tid;
43841a945772Spatrick }
43851a945772Spatrick
438641cd246cSpatrick return -1;
43871a945772Spatrick }
43881a945772Spatrick
43891a945772Spatrick int
mvpp2_prs_mac_da_accept(struct mvpp2_port * port,const uint8_t * da,int add)439041cd246cSpatrick mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const uint8_t *da, int add)
43911a945772Spatrick {
439241cd246cSpatrick struct mvpp2_softc *sc = port->sc;
439341cd246cSpatrick struct mvpp2_prs_entry pe;
43941a945772Spatrick uint32_t pmap, len, ri;
43951a945772Spatrick uint8_t mask[ETHER_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
43961a945772Spatrick int tid;
43971a945772Spatrick
439841cd246cSpatrick memset(&pe, 0, sizeof(pe));
439941cd246cSpatrick
440041cd246cSpatrick tid = mvpp2_prs_mac_da_range_find(sc, BIT(port->sc_id), da, mask,
44011a945772Spatrick MVPP2_PRS_UDF_MAC_DEF);
440241cd246cSpatrick if (tid < 0) {
44031a945772Spatrick if (!add)
44041a945772Spatrick return 0;
44051a945772Spatrick
4406ce595ab8Spatrick tid = mvpp2_prs_tcam_first_free(sc, MVPP2_PE_MAC_RANGE_START,
4407ce595ab8Spatrick MVPP2_PE_MAC_RANGE_END);
44081a945772Spatrick if (tid < 0)
44091a945772Spatrick return tid;
44101a945772Spatrick
441141cd246cSpatrick pe.index = tid;
441241cd246cSpatrick mvpp2_prs_tcam_port_map_set(&pe, 0);
441341cd246cSpatrick } else {
441441cd246cSpatrick mvpp2_prs_hw_read(sc, &pe, tid);
44151a945772Spatrick }
44161a945772Spatrick
441741cd246cSpatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC);
441841cd246cSpatrick
441941cd246cSpatrick mvpp2_prs_tcam_port_set(&pe, port->sc_id, add);
44201a945772Spatrick
44211a945772Spatrick /* invalidate the entry if no ports are left enabled */
442241cd246cSpatrick pmap = mvpp2_prs_tcam_port_map_get(&pe);
44231a945772Spatrick if (pmap == 0) {
442441cd246cSpatrick if (add)
44251a945772Spatrick return -1;
442641cd246cSpatrick mvpp2_prs_hw_inv(sc, pe.index);
442741cd246cSpatrick sc->sc_prs_shadow[pe.index].valid = 0;
44281a945772Spatrick return 0;
44291a945772Spatrick }
44301a945772Spatrick
443141cd246cSpatrick mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_DSA);
44321a945772Spatrick
44331a945772Spatrick len = ETHER_ADDR_LEN;
44341a945772Spatrick while (len--)
443541cd246cSpatrick mvpp2_prs_tcam_data_byte_set(&pe, len, da[len], 0xff);
44361a945772Spatrick
44371a945772Spatrick if (ETHER_IS_BROADCAST(da))
44381a945772Spatrick ri = MVPP2_PRS_RI_L2_BCAST;
44391a945772Spatrick else if (ETHER_IS_MULTICAST(da))
44401a945772Spatrick ri = MVPP2_PRS_RI_L2_MCAST;
44411a945772Spatrick else
44421a945772Spatrick ri = MVPP2_PRS_RI_L2_UCAST | MVPP2_PRS_RI_MAC_ME_MASK;
44431a945772Spatrick
444441cd246cSpatrick mvpp2_prs_sram_ri_update(&pe, ri, MVPP2_PRS_RI_L2_CAST_MASK |
44451a945772Spatrick MVPP2_PRS_RI_MAC_ME_MASK);
444641cd246cSpatrick mvpp2_prs_shadow_ri_set(sc, pe.index, ri, MVPP2_PRS_RI_L2_CAST_MASK |
44471a945772Spatrick MVPP2_PRS_RI_MAC_ME_MASK);
444841cd246cSpatrick mvpp2_prs_sram_shift_set(&pe, 2 * ETHER_ADDR_LEN,
44491a945772Spatrick MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
445041cd246cSpatrick sc->sc_prs_shadow[pe.index].udf = MVPP2_PRS_UDF_MAC_DEF;
445141cd246cSpatrick mvpp2_prs_shadow_set(sc, pe.index, MVPP2_PRS_LU_MAC);
445241cd246cSpatrick mvpp2_prs_hw_write(sc, &pe);
44531a945772Spatrick
44541a945772Spatrick return 0;
44551a945772Spatrick }
44561a945772Spatrick
4457ce595ab8Spatrick void
mvpp2_prs_mac_del_all(struct mvpp2_port * port)4458ce595ab8Spatrick mvpp2_prs_mac_del_all(struct mvpp2_port *port)
4459ce595ab8Spatrick {
4460ce595ab8Spatrick struct mvpp2_softc *sc = port->sc;
4461ce595ab8Spatrick struct mvpp2_prs_entry pe;
4462ce595ab8Spatrick uint32_t pmap;
4463ce595ab8Spatrick int index, tid;
4464ce595ab8Spatrick
4465ce595ab8Spatrick for (tid = MVPP2_PE_MAC_RANGE_START; tid <= MVPP2_PE_MAC_RANGE_END;
4466ce595ab8Spatrick tid++) {
4467ce595ab8Spatrick uint8_t da[ETHER_ADDR_LEN], da_mask[ETHER_ADDR_LEN];
4468ce595ab8Spatrick
4469ce595ab8Spatrick if (!sc->sc_prs_shadow[tid].valid ||
4470ce595ab8Spatrick (sc->sc_prs_shadow[tid].lu != MVPP2_PRS_LU_MAC) ||
4471ce595ab8Spatrick (sc->sc_prs_shadow[tid].udf != MVPP2_PRS_UDF_MAC_DEF))
4472ce595ab8Spatrick continue;
4473ce595ab8Spatrick
4474ce595ab8Spatrick mvpp2_prs_hw_read(sc, &pe, tid);
4475ce595ab8Spatrick pmap = mvpp2_prs_tcam_port_map_get(&pe);
4476ce595ab8Spatrick
4477ce595ab8Spatrick if (!(pmap & (1 << port->sc_id)))
4478ce595ab8Spatrick continue;
4479ce595ab8Spatrick
4480ce595ab8Spatrick for (index = 0; index < ETHER_ADDR_LEN; index++)
4481ce595ab8Spatrick mvpp2_prs_tcam_data_byte_get(&pe, index, &da[index],
4482ce595ab8Spatrick &da_mask[index]);
4483ce595ab8Spatrick
4484ce595ab8Spatrick if (ETHER_IS_BROADCAST(da) || ETHER_IS_EQ(da, port->sc_lladdr))
4485ce595ab8Spatrick continue;
4486ce595ab8Spatrick
4487ce595ab8Spatrick mvpp2_prs_mac_da_accept(port, da, 0);
4488ce595ab8Spatrick }
4489ce595ab8Spatrick }
4490ce595ab8Spatrick
44911a945772Spatrick int
mvpp2_prs_tag_mode_set(struct mvpp2_softc * sc,int port_id,int type)44921a945772Spatrick mvpp2_prs_tag_mode_set(struct mvpp2_softc *sc, int port_id, int type)
44931a945772Spatrick {
44941a945772Spatrick switch (type) {
44951a945772Spatrick case MVPP2_TAG_TYPE_EDSA:
44961a945772Spatrick mvpp2_prs_dsa_tag_set(sc, port_id, 1, MVPP2_PRS_TAGGED,
44971a945772Spatrick MVPP2_PRS_EDSA);
44981a945772Spatrick mvpp2_prs_dsa_tag_set(sc, port_id, 1, MVPP2_PRS_UNTAGGED,
44991a945772Spatrick MVPP2_PRS_EDSA);
45001a945772Spatrick mvpp2_prs_dsa_tag_set(sc, port_id, 0, MVPP2_PRS_TAGGED,
45011a945772Spatrick MVPP2_PRS_DSA);
45021a945772Spatrick mvpp2_prs_dsa_tag_set(sc, port_id, 0, MVPP2_PRS_UNTAGGED,
45031a945772Spatrick MVPP2_PRS_DSA);
45041a945772Spatrick break;
45051a945772Spatrick case MVPP2_TAG_TYPE_DSA:
45061a945772Spatrick mvpp2_prs_dsa_tag_set(sc, port_id, 1, MVPP2_PRS_TAGGED,
45071a945772Spatrick MVPP2_PRS_DSA);
45081a945772Spatrick mvpp2_prs_dsa_tag_set(sc, port_id, 1, MVPP2_PRS_UNTAGGED,
45091a945772Spatrick MVPP2_PRS_DSA);
45101a945772Spatrick mvpp2_prs_dsa_tag_set(sc, port_id, 0, MVPP2_PRS_TAGGED,
45111a945772Spatrick MVPP2_PRS_EDSA);
45121a945772Spatrick mvpp2_prs_dsa_tag_set(sc, port_id, 0, MVPP2_PRS_UNTAGGED,
45131a945772Spatrick MVPP2_PRS_EDSA);
45141a945772Spatrick break;
45151a945772Spatrick case MVPP2_TAG_TYPE_MH:
45161a945772Spatrick case MVPP2_TAG_TYPE_NONE:
45171a945772Spatrick mvpp2_prs_dsa_tag_set(sc, port_id, 0, MVPP2_PRS_TAGGED,
45181a945772Spatrick MVPP2_PRS_DSA);
45191a945772Spatrick mvpp2_prs_dsa_tag_set(sc, port_id, 0, MVPP2_PRS_UNTAGGED,
45201a945772Spatrick MVPP2_PRS_DSA);
45211a945772Spatrick mvpp2_prs_dsa_tag_set(sc, port_id, 0, MVPP2_PRS_TAGGED,
45221a945772Spatrick MVPP2_PRS_EDSA);
45231a945772Spatrick mvpp2_prs_dsa_tag_set(sc, port_id, 0, MVPP2_PRS_UNTAGGED,
45241a945772Spatrick MVPP2_PRS_EDSA);
45251a945772Spatrick break;
45261a945772Spatrick default:
45271a945772Spatrick if ((type < 0) || (type > MVPP2_TAG_TYPE_EDSA))
45281a945772Spatrick return EINVAL;
45291a945772Spatrick break;
45301a945772Spatrick }
45311a945772Spatrick
45321a945772Spatrick return 0;
45331a945772Spatrick }
45341a945772Spatrick
45351a945772Spatrick int
mvpp2_prs_def_flow(struct mvpp2_port * port)45361a945772Spatrick mvpp2_prs_def_flow(struct mvpp2_port *port)
45371a945772Spatrick {
4538fef01367Spatrick struct mvpp2_prs_entry pe;
45391a945772Spatrick int tid;
45401a945772Spatrick
4541fef01367Spatrick memset(&pe, 0, sizeof(pe));
4542fef01367Spatrick
4543fef01367Spatrick tid = mvpp2_prs_flow_find(port->sc, port->sc_id);
4544fef01367Spatrick if (tid < 0) {
45451a945772Spatrick tid = mvpp2_prs_tcam_first_free(port->sc,
45461a945772Spatrick MVPP2_PE_LAST_FREE_TID, MVPP2_PE_FIRST_FREE_TID);
45471a945772Spatrick if (tid < 0)
45481a945772Spatrick return tid;
45491a945772Spatrick
4550fef01367Spatrick pe.index = tid;
4551fef01367Spatrick mvpp2_prs_sram_ai_update(&pe, port->sc_id,
45521a945772Spatrick MVPP2_PRS_FLOW_ID_MASK);
4553fef01367Spatrick mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_DONE_BIT, 1);
4554fef01367Spatrick mvpp2_prs_shadow_set(port->sc, pe.index, MVPP2_PRS_LU_FLOWS);
4555fef01367Spatrick } else {
4556fad015d2Spatrick mvpp2_prs_hw_read(port->sc, &pe, tid);
45571a945772Spatrick }
45581a945772Spatrick
4559fef01367Spatrick mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
4560fef01367Spatrick mvpp2_prs_tcam_port_map_set(&pe, (1 << port->sc_id));
4561fef01367Spatrick mvpp2_prs_hw_write(port->sc, &pe);
45621a945772Spatrick return 0;
45631a945772Spatrick }
45641a945772Spatrick
45651a945772Spatrick void
mvpp2_cls_flow_write(struct mvpp2_softc * sc,struct mvpp2_cls_flow_entry * fe)45661a945772Spatrick mvpp2_cls_flow_write(struct mvpp2_softc *sc, struct mvpp2_cls_flow_entry *fe)
45671a945772Spatrick {
45681a945772Spatrick mvpp2_write(sc, MVPP2_CLS_FLOW_INDEX_REG, fe->index);
45691a945772Spatrick mvpp2_write(sc, MVPP2_CLS_FLOW_TBL0_REG, fe->data[0]);
45701a945772Spatrick mvpp2_write(sc, MVPP2_CLS_FLOW_TBL1_REG, fe->data[1]);
45711a945772Spatrick mvpp2_write(sc, MVPP2_CLS_FLOW_TBL2_REG, fe->data[2]);
45721a945772Spatrick }
45731a945772Spatrick
45741a945772Spatrick void
mvpp2_cls_lookup_write(struct mvpp2_softc * sc,struct mvpp2_cls_lookup_entry * le)45751a945772Spatrick mvpp2_cls_lookup_write(struct mvpp2_softc *sc, struct mvpp2_cls_lookup_entry *le)
45761a945772Spatrick {
45771a945772Spatrick uint32_t val;
45781a945772Spatrick
45791a945772Spatrick val = (le->way << MVPP2_CLS_LKP_INDEX_WAY_OFFS) | le->lkpid;
45801a945772Spatrick mvpp2_write(sc, MVPP2_CLS_LKP_INDEX_REG, val);
45811a945772Spatrick mvpp2_write(sc, MVPP2_CLS_LKP_TBL_REG, le->data);
45821a945772Spatrick }
45831a945772Spatrick
45841a945772Spatrick void
mvpp2_cls_init(struct mvpp2_softc * sc)45851a945772Spatrick mvpp2_cls_init(struct mvpp2_softc *sc)
45861a945772Spatrick {
45871a945772Spatrick struct mvpp2_cls_lookup_entry le;
45881a945772Spatrick struct mvpp2_cls_flow_entry fe;
45891a945772Spatrick int index;
45901a945772Spatrick
45911a945772Spatrick mvpp2_write(sc, MVPP2_CLS_MODE_REG, MVPP2_CLS_MODE_ACTIVE_MASK);
4592fbeb3de2Spatrick memset(&fe.data, 0, sizeof(fe.data));
45931a945772Spatrick for (index = 0; index < MVPP2_CLS_FLOWS_TBL_SIZE; index++) {
45941a945772Spatrick fe.index = index;
45951a945772Spatrick mvpp2_cls_flow_write(sc, &fe);
45961a945772Spatrick }
45971a945772Spatrick le.data = 0;
45981a945772Spatrick for (index = 0; index < MVPP2_CLS_LKP_TBL_SIZE; index++) {
45991a945772Spatrick le.lkpid = index;
46001a945772Spatrick le.way = 0;
46011a945772Spatrick mvpp2_cls_lookup_write(sc, &le);
46021a945772Spatrick le.way = 1;
46031a945772Spatrick mvpp2_cls_lookup_write(sc, &le);
46041a945772Spatrick }
46051a945772Spatrick }
46061a945772Spatrick
46071a945772Spatrick void
mvpp2_cls_port_config(struct mvpp2_port * port)46081a945772Spatrick mvpp2_cls_port_config(struct mvpp2_port *port)
46091a945772Spatrick {
46101a945772Spatrick struct mvpp2_cls_lookup_entry le;
46111a945772Spatrick uint32_t val;
46121a945772Spatrick
46131a945772Spatrick /* set way for the port */
46141a945772Spatrick val = mvpp2_read(port->sc, MVPP2_CLS_PORT_WAY_REG);
46151a945772Spatrick val &= ~MVPP2_CLS_PORT_WAY_MASK(port->sc_id);
46161a945772Spatrick mvpp2_write(port->sc, MVPP2_CLS_PORT_WAY_REG, val);
46171a945772Spatrick
46181a945772Spatrick /*
46191a945772Spatrick * pick the entry to be accessed in lookup ID decoding table
46201a945772Spatrick * according to the way and lkpid.
46211a945772Spatrick */
46221a945772Spatrick le.lkpid = port->sc_id;
46231a945772Spatrick le.way = 0;
46241a945772Spatrick le.data = 0;
46251a945772Spatrick
46261a945772Spatrick /* set initial CPU queue for receiving packets */
46271a945772Spatrick le.data &= ~MVPP2_CLS_LKP_TBL_RXQ_MASK;
46281a945772Spatrick le.data |= (port->sc_id * 32);
46291a945772Spatrick
46301a945772Spatrick /* disable classification engines */
46311a945772Spatrick le.data &= ~MVPP2_CLS_LKP_TBL_LOOKUP_EN_MASK;
46321a945772Spatrick
46331a945772Spatrick /* update lookup ID table entry */
46341a945772Spatrick mvpp2_cls_lookup_write(port->sc, &le);
46351a945772Spatrick }
46361a945772Spatrick
46371a945772Spatrick void
mvpp2_cls_oversize_rxq_set(struct mvpp2_port * port)46381a945772Spatrick mvpp2_cls_oversize_rxq_set(struct mvpp2_port *port)
46391a945772Spatrick {
4640a6029e6cSpatrick uint32_t val;
4641a6029e6cSpatrick
46421a945772Spatrick mvpp2_write(port->sc, MVPP2_CLS_OVERSIZE_RXQ_LOW_REG(port->sc_id),
46431a945772Spatrick (port->sc_id * 32) & MVPP2_CLS_OVERSIZE_RXQ_LOW_MASK);
4644a6029e6cSpatrick mvpp2_write(port->sc, MVPP2_CLS_SWFWD_P2HQ_REG(port->sc_id),
4645a6029e6cSpatrick (port->sc_id * 32) >> MVPP2_CLS_OVERSIZE_RXQ_LOW_BITS);
4646a6029e6cSpatrick val = mvpp2_read(port->sc, MVPP2_CLS_SWFWD_PCTRL_REG);
4647a6029e6cSpatrick val &= ~MVPP2_CLS_SWFWD_PCTRL_MASK(port->sc_id);
4648a6029e6cSpatrick mvpp2_write(port->sc, MVPP2_CLS_SWFWD_PCTRL_REG, val);
46491a945772Spatrick }
4650