[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20191211105757.GC2070@kadam>
Date: Wed, 11 Dec 2019 13:57:57 +0300
From: Dan Carpenter <dan.carpenter@...cle.com>
To: Jack Ping CHNG <jack.ping.chng@...el.com>
Cc: devel@...verdev.osuosl.org, cheol.yong.kim@...el.com,
andriy.shevchenko@...el.com, netdev@...r.kernel.org,
linux-kernel@...r.kernel.org,
Amireddy Mallikarjuna reddy
<mallikarjunax.reddy@...ux.intel.com>, gregkh@...uxfoundation.org,
davem@...emloft.net
Subject: Re: [PATCH v2] staging: intel-gwdpa: gswip: Introduce Gigabit
Ethernet Switch (GSWIP) device driver
This should just be sent to netdev. I spotted a couple bugs.
1) enable/disable we flipped xgmac_set_xgmii_2500_speed()
2) retries wasn't reset in a couple places.
I had a few tiny style nits as well but there is no reason to send it to
staging.
regards,
dan carpenter
On Wed, Dec 11, 2019 at 04:57:28PM +0800, Jack Ping CHNG wrote:
> diff --git a/drivers/staging/intel-gwdpa/gswip/TODO b/drivers/staging/intel-gwdpa/gswip/TODO
> new file mode 100644
> index 000000000000..fa46170c8260
> --- /dev/null
> +++ b/drivers/staging/intel-gwdpa/gswip/TODO
> @@ -0,0 +1,4 @@
> +- Add debugfs for core and mac.
> +- Expand APIs for PCE, BM and PMAC tables to support
> + QoS, OMCI.
> +- Add ops for core.
None of this seems like staging material. We aren't supposed to add
new features while code is in staging, it's just for cleaning up
existing code ASAP so it can be merged. Adding new features would only
delay the merging.
> diff --git a/drivers/staging/intel-gwdpa/gswip/gswip.h b/drivers/staging/intel-gwdpa/gswip/gswip.h
> new file mode 100644
> index 000000000000..4ba967430f4e
> --- /dev/null
> +++ b/drivers/staging/intel-gwdpa/gswip/gswip.h
> @@ -0,0 +1,399 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright (c) 2016-2019 Intel Corporation. */
> +#ifndef _DATAPATH_GSWIP_H_
> +#define _DATAPATH_GSWIP_H_
> +
> +#include <linux/device.h>
> +#include <linux/bits.h>
> +
> +#define BR_PORT_MAP_NUM 16
> +#define PMAC_BSL_THRES_NUM 3
> +#define PMAC_HEADER_NUM 8
> +
> +enum gswip_cpu_parser_hdr_cfg {
> + GSWIP_CPU_PARSER_NIL,
> + GSWIP_CPU_PARSER_FLAGS,
> + GSWIP_CPU_PARSER_OFFSETS_FLAGS,
> + GSWIP_CPU_PARSER_RESERVED,
> +};
> +
> +struct gswip_cpu_port_cfg {
> + u8 lpid;
> + bool is_cpu_port;
> + bool spec_tag_ig;
> + bool spec_tag_eg;
> + bool fcs_chk;
> + bool fcs_generate;
> + enum gswip_cpu_parser_hdr_cfg no_mpe_parser_cfg;
> + enum gswip_cpu_parser_hdr_cfg mpe1_parser_cfg;
> + enum gswip_cpu_parser_hdr_cfg mpe2_parser_cfg;
> + enum gswip_cpu_parser_hdr_cfg mpe3_parser_cfg;
> + bool ts_rm_ptp_pkt;
> + bool ts_rm_non_ptp_pkt;
> +};
> +
> +enum gswip_pmac_short_frm_chk {
> + GSWIP_PMAC_SHORT_LEN_DIS,
> + GSWIP_PMAC_SHORT_LEN_ENA_UNTAG,
> + GSWIP_PMAC_SHORT_LEN_ENA_TAG,
> + GSWIP_PMAC_SHORT_LEN_RESERVED,
> +};
> +
> +enum gswip_pmac_proc_flags_eg_cfg {
> + GSWIP_PMAC_PROC_FLAGS_NONE,
> + GSWIP_PMAC_PROC_FLAGS_TC,
> + GSWIP_PMAC_PROC_FLAGS_FLAG,
> + GSWIP_PMAC_PROC_FLAGS_MIX,
> +};
> +
> +struct gswip_pmac_glb_cfg {
> + u8 pmac_id;
> + bool apad_en;
> + bool pad_en;
> + bool vpad_en;
> + bool svpad_en;
> + bool rx_fcs_dis;
> + bool tx_fcs_dis;
> + bool ip_trans_chk_reg_dis;
> + bool ip_trans_chk_ver_dis;
> + bool jumbo_en;
> + u16 max_jumbo_len;
> + u16 jumbo_thresh_len;
> + bool long_frm_chk_dis;
> + enum gswip_pmac_short_frm_chk short_frm_chk_type;
> + bool proc_flags_eg_cfg_en;
> + enum gswip_pmac_proc_flags_eg_cfg proc_flags_eg_cfg;
> + u16 bsl_thresh[PMAC_BSL_THRES_NUM];
> +};
> +
> +struct gswip_pmac_bp_map {
> + u8 pmac_id;
> + u8 tx_dma_chan_id;
> + u32 tx_q_mask;
> + u32 rx_port_mask;
> +};
> +
> +enum gswip_pmac_ig_cfg_src {
> + GSWIP_PMAC_IG_CFG_SRC_DMA_DESC,
> + GSWIP_PMAC_IG_CFG_SRC_DEF_PMAC,
> + GSWIP_PMAC_IG_CFG_SRC_PMAC,
> +};
> +
> +struct gswip_pmac_ig_cfg {
> + u8 pmac_id;
> + u8 tx_dma_chan_id;
> + bool err_pkt_disc;
> + bool class_def;
> + bool class_en;
> + enum gswip_pmac_ig_cfg_src sub_id;
> + bool src_port_id_def;
> + bool pmac_present;
> + u8 def_pmac_hdr[PMAC_HEADER_NUM];
> +};
> +
> +struct gswip_pmac_eg_cfg {
> + u8 pmac_id;
> + u8 dst_port_id;
> + u8 tc;
> + bool mpe1;
> + bool mpe2;
> + bool decrypt;
> + bool encrypt;
> + u8 flow_id_msb;
> + bool process_sel;
> + u8 rx_dma_chan_id;
> + bool rm_l2_hdr;
> + u8 num_byte_rm;
> + bool fcs_en;
> + bool pmac_en;
> + bool redir_en;
> + bool bsl_seg_disable;
> + u8 bsl_tc;
> + bool resv_dw1_en;
> + u8 resv_dw1;
> + bool resv_1dw0_en;
> + u8 resv_1dw0;
> + bool resv_2dw0_en;
> + u8 resv_2dw0;
> + bool tc_en;
> +};
> +
> +struct gswip_lpid2gpid {
> + u16 lpid;
> + u16 first_gpid;
> + u16 num_gpid;
> + u8 valid_bits;
> +};
> +
> +struct gswip_gpid2lpid {
> + u16 gpid;
> + u16 lpid;
> + u8 subif_grp_field;
> + bool subif_grp_field_ovr;
> +};
> +
> +enum gswip_ctp_port_config_mask {
> + GSWIP_CTP_PORT_CONFIG_MASK_BRIDGE_PORT_ID = BIT(0),
> + GSWIP_CTP_PORT_CONFIG_MASK_FORCE_TRAFFIC_CLASS = BIT(1),
> + GSWIP_CTP_PORT_CONFIG_MASK_INGRESS_VLAN = BIT(2),
> + GSWIP_CTP_PORT_CONFIG_MASK_INGRESS_VLAN_IGMP = BIT(3),
> + GSWIP_CTP_PORT_CONFIG_MASK_EGRESS_VLAN = BIT(4),
> + GSWIP_CTP_PORT_CONFIG_MASK_EGRESS_VLAN_IGMP = BIT(5),
> + GSWIP_CTP_PORT_CONFIG_MASK_INRESS_NTO1_VLAN = BIT(6),
> + GSWIP_CTP_PORT_CONFIG_MASK_EGRESS_NTO1_VLAN = BIT(7),
> + GSWIP_CTP_PORT_CONFIG_INGRESS_MARKING = BIT(8),
> + GSWIP_CTP_PORT_CONFIG_EGRESS_MARKING = BIT(9),
> + GSWIP_CTP_PORT_CONFIG_EGRESS_MARKING_OVERRIDE = BIT(10),
> + GSWIP_CTP_PORT_CONFIG_EGRESS_REMARKING = BIT(11),
> + GSWIP_CTP_PORT_CONFIG_INGRESS_METER = BIT(12),
> + GSWIP_CTP_PORT_CONFIG_EGRESS_METER = BIT(13),
> + GSWIP_CTP_PORT_CONFIG_BRIDGING_BYPASS = BIT(14),
> + GSWIP_CTP_PORT_CONFIG_FLOW_ENTRY = BIT(15),
> + GSWIP_CTP_PORT_CONFIG_LOOPBACK_AND_MIRROR = BIT(16),
> + GSWIP_CTP_PORT_CONFIG_MASK_FORCE = BIT(31),
> +};
> +
> +struct gswip_ctp_port_cfg {
> + u8 lpid;
> + u16 subif_id_grp;
> + u16 br_pid;
> + enum gswip_ctp_port_config_mask mask;
> + bool br_bypass;
> +};
> +
> +enum gswip_lport_mode {
> + GSWIP_LPORT_8BIT_WLAN,
> + GSWIP_LPORT_9BIT_WLAN,
> + GSWIP_LPORT_GPON,
> + GSWIP_LPORT_EPON,
> + GSWIP_LPORT_GINT,
> + GSWIP_LPORT_OTHER = 0xFF,
> +};
> +
> +struct gswip_ctp_port_info {
> + u8 lpid;
> + u16 first_pid;
> + u16 num_port;
> + enum gswip_lport_mode mode;
> + u16 br_pid;
> +};
> +
> +enum gswip_br_port_cfg_mask {
> + GSWIP_BR_PORT_CFG_MASK_BR_ID = BIT(0),
> + GSWIP_BR_PORT_CFG_MASK_IG_VLAN = BIT(1),
> + GSWIP_BR_PORT_CFG_MASK_EG_VLAN = BIT(2),
> + GSWIP_BR_PORT_CFG_MASK_IG_MARKING = BIT(3),
> + GSWIP_BR_PORT_CFG_MASK_EG_REMARKING = BIT(4),
> + GSWIP_BR_PORT_CFG_MASK_IG_METER = BIT(5),
> + GSWIP_BR_PORT_CFG_MASK_EG_SUB_METER = BIT(6),
> + GSWIP_BR_PORT_CFG_MASK_EG_CTP_MAPPING = BIT(7),
> + GSWIP_BR_PORT_CFG_MASK_BR_PORT_MAP = BIT(8),
> + GSWIP_BR_PORT_CFG_MASK_MCAST_DST_IP_LOOKUP = BIT(9),
> + GSWIP_BR_PORT_CFG_MASK_MCAST_SRC_IP_LOOKUP = BIT(10),
> + GSWIP_BR_PORT_CFG_MASK_MCAST_DST_MAC_LOOKUP = BIT(11),
> + GSWIP_BR_PORT_CFG_MASK_MCAST_SRC_MAC_LEARNING = BIT(12),
> + GSWIP_BR_PORT_CFG_MASK_MAC_SPOOFING = BIT(13),
> + GSWIP_BR_PORT_CFG_MASK_PORT_LOCK = BIT(14),
> + GSWIP_BR_PORT_CFG_MASK_MAC_LEARNING_LIMIT = BIT(15),
> + GSWIP_BR_PORT_CFG_MASK_MAC_LEARNED_COUNT = BIT(16),
> + GSWIP_BR_PORT_CFG_MASK_IG_VLAN_FILTER = BIT(17),
> + GSWIP_BR_PORT_CFG_MASK_EG_VLAN_FILTER1 = BIT(18),
> + GSWIP_BR_PORT_CFG_MASK_EG_VLAN_FILTER2 = BIT(19),
> + GSWIP_BR_PORT_CFG_MASK_FORCE = BIT(31),
> +};
> +
> +enum gswip_pmapper_mapping_mode {
> + GSWIP_PMAPPER_MAPPING_PCP,
> + GSWIP_PMAPPER_MAPPING_DSCP,
> +};
> +
> +enum gswip_br_port_eg_meter {
> + GSWIP_BR_PORT_EG_METER_BROADCAST,
> + GSWIP_BR_PORT_EG_METER_MULTICAST,
> + GSWIP_BR_PORT_EG_METER_UNKNOWN_MCAST_IP,
> + GSWIP_BR_PORT_EG_METER_UNKNOWN_MCAST_NON_IP,
> + GSWIP_BR_PORT_EG_METER_UNKNOWN_UCAST,
> + GSWIP_BR_PORT_EG_METER_OTHERS,
> + GSWIP_BR_PORT_EG_METER_MAX,
> +};
> +
> +struct gswip_br_port_alloc {
> + u8 br_id;
> + u8 br_pid;
> +};
> +
> +enum gswip_br_cfg_mask {
> + GSWIP_BR_CFG_MASK_MAC_LEARNING_LIMIT = BIT(0),
> + GSWIP_BR_CFG_MASK_MAC_LEARNED_COUNT = BIT(1),
> + GSWIP_BR_CFG_MASK_MAC_DISCARD_COUNT = BIT(2),
> + GSWIP_BR_CFG_MASK_SUB_METER = BIT(3),
> + GSWIP_BR_CFG_MASK_FORWARDING_MODE = BIT(4),
> + GSWIP_BR_CFG_MASK_FORCE = BIT(31),
> +};
> +
> +enum gswip_br_fwd_mode {
> + GSWIP_BR_FWD_FLOOD,
> + GSWIP_BR_FWD_DISCARD,
> + GSWIP_BR_FWD_CPU,
> +};
> +
> +struct gswip_br_alloc {
> + u8 br_id;
> +};
> +
> +struct gswip_br_cfg {
> + u8 br_id;
> + enum gswip_br_cfg_mask mask;
> + bool mac_lrn_limit_en;
> + u16 mac_lrn_limit;
> + u16 mac_lrn_count;
> + u32 lrn_disc_event;
> + enum gswip_br_fwd_mode fwd_bcast;
> + enum gswip_br_fwd_mode fwd_unk_mcast_ip;
> + enum gswip_br_fwd_mode fwd_unk_mcast_non_ip;
> + enum gswip_br_fwd_mode fwd_unk_ucast;
> +};
> +
> +struct gswip_qos_wred_q_cfg {
> + u8 qid;
> + u16 red_min;
> + u16 red_max;
> + u16 yellow_min;
> + u16 yellow_max;
> + u16 green_min;
> + u16 green_max;
> +};
> +
> +struct gswip_qos_wred_port_cfg {
> + u8 lpid;
> + u16 red_min;
> + u16 red_max;
> + u16 yellow_min;
> + u16 yellow_max;
> + u16 green_min;
> + u16 green_max;
> +};
> +
> +enum gswip_qos_q_map_mode {
> + GSWIP_QOS_QMAP_SINGLE_MODE,
> + GSWIP_QOS_QMAP_SUBIFID_MODE,
> +};
> +
> +struct gswip_qos_q_port {
> + u8 lpid;
> + bool extration_en;
> + enum gswip_qos_q_map_mode q_map_mode;
> + u8 tc_id;
> + u8 qid;
> + bool egress;
> + u8 redir_port_id;
> + bool en_ig_pce_bypass;
> + bool resv_port_mode;
> +};
> +
> +struct gswip_register {
> + u16 offset;
> + u16 data;
> +};
> +
> +enum {
> + SPEED_LMAC_10M,
> + SPEED_LMAC_100M,
> + SPEED_LMAC_200M,
> + SPEED_LMAC_1G,
> + SPEED_XGMAC_10M,
> + SPEED_XGMAC_100M,
> + SPEED_XGMAC_1G,
> + SPEED_XGMII_25G,
> + SPEED_XGMAC_5G,
> + SPEED_XGMAC_10G,
> + SPEED_GMII_25G,
> + SPEED_MAC_AUTO,
> +};
> +
> +enum gsw_portspeed {
> + /* 10 Mbit/s */
> + GSW_PORT_SPEED_10 = 10,
> +
> + /* 100 Mbit/s */
> + GSW_PORT_SPEED_100 = 100,
> +
> + /* 200 Mbit/s */
> + GSW_PORT_SPEED_200 = 200,
> +
> + /* 1000 Mbit/s */
> + GSW_PORT_SPEED_1000 = 1000,
> +
> + /* 2.5 Gbit/s */
> + GSW_PORT_SPEED_25000 = 25000,
> +
> + /* 10 Gbit/s */
> + GSW_PORT_SPEED_100000 = 100000,
> +};
> +
> +enum gsw_portlink_status {
> + LINK_AUTO,
> + LINK_UP,
> + LINK_DOWN,
> +};
> +
> +enum gsw_flow_control_modes {
> + FC_AUTO,
> + FC_RX,
> + FC_TX,
> + FC_RXTX,
> + FC_DIS,
> + FC_INVALID,
> +};
> +
> +/* Ethernet port interface mode. */
> +enum gsw_mii_mode {
> + /* Normal PHY interface (twisted pair), use internal MII Interface */
> + GSW_PORT_HW_MII,
> +
> + /* Reduced MII interface in normal mode */
> + GSW_PORT_HW_RMII,
> +
> + /* GMII or MII, depending upon the speed */
> + GSW_PORT_HW_GMII,
> +
> + /* RGMII mode */
> + GSW_PORT_HW_RGMII,
> +
> + /* XGMII mode */
> + GSW_PORT_HW_XGMII,
> +};
> +
> +struct gsw_mac_ops {
> + /* Initialize MAC */
> + int (*init)(struct device *dev);
> +
> + int (*set_macaddr)(struct device *dev, u8 *mac_addr);
> + u32 (*get_link_sts)(struct device *dev);
> +
> + u32 (*get_duplex)(struct device *dev);
> +
> + int (*set_speed)(struct device *dev, u8 speed);
> + u32 (*get_speed)(struct device *dev);
> +
> + u32 (*get_mtu)(struct device *dev);
> + int (*set_mtu)(struct device *dev, u32 mtu);
> +
> + u32 (*get_flowctrl)(struct device *dev);
> + int (*set_flowctrl)(struct device *dev, u32 val);
> +
> + int (*get_pfsa)(struct device *dev, u8 *addr, u32 *mode);
> + int (*set_pfsa)(struct device *dev, u8 *mac_addr, u32 macif);
> +
> + int (*get_mii_if)(struct device *dev);
> + int (*set_mii_if)(struct device *dev, u32 mii_mode);
> +
> + u32 (*get_lpi)(struct device *dev);
> +
> + int (*get_fcsgen)(struct device *dev);
> +};
> +
> +struct gsw_adap_ops {
> + int (*sw_core_enable)(struct device *dev, u32 val);
> +};
> +#endif
> diff --git a/drivers/staging/intel-gwdpa/gswip/gswip_core.c b/drivers/staging/intel-gwdpa/gswip/gswip_core.c
> new file mode 100644
> index 000000000000..17e2f0a86b0c
> --- /dev/null
> +++ b/drivers/staging/intel-gwdpa/gswip/gswip_core.c
> @@ -0,0 +1,755 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2016-2019 Intel Corporation. */
> +
> +#include <asm/unaligned.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/of_platform.h>
> +
> +#include "gswip_core.h"
> +#include "gswip_dev.h"
> +#include "gswip_reg.h"
> +#include "gswip_tbl.h"
> +
> +#define GSWIP_VER 0x32
> +
> +/* TX DMA channels for PMAC0 to PMAC2 */
> +#define PMAC0_TX_DMACHID_START 0
> +#define PMAC0_TX_DMACHID_END 16
> +#define PMAC1_TX_DMACHID_START 0
> +#define PMAC1_TX_DMACHID_END 16
> +#define PMAC2_TX_DMACHID_START 0
> +#define PMAC2_TX_DMACHID_END 16
> +
> +#define MAX_JUMBO_FRM_LEN 10000
> +
> +/* Pseudo MAC and MAC */
> +enum mac_id {
> + PMAC_0,
> + PMAC_1,
> + MAC_2,
> + MAC_3,
> + MAC_4,
> + MAC_5,
> + MAC_6,
> + MAC_7,
> + MAC_8,
> + MAC_9,
> + MAC_10,
> + PMAC_2,
> + MAC_LAST,
> +};
> +
> +/* Data Protocol Unit (DPU) */
> +enum dpu {
> + DPU,
> + NON_DPU,
> +};
> +
> +enum queue_id {
> + QUEUE0,
> + QUEUE1,
> + QUEUE2,
> + QUEUE3,
> + QUEUE4,
> + QUEUE5,
> + QUEUE6,
> + QUEUE7,
> + QUEUE8,
> + QUEUE9,
> + QUEUE10,
> +};
> +
> +enum traffic_class {
> + TC0,
> + TC1,
> + TC2,
> + TC3,
> + TC_MAX,
> +};
> +
> +struct eg_pce_bypass_path {
> + /* egress logical port id */
> + u8 eg_pid;
> + /* local extracted */
> + bool ext;
> + /* queue id */
> + u8 qid;
> + /* redirect logical port id */
> + u8 redir_pid;
> +};
> +
> +struct ig_pce_bypass_path {
> + /* ingress logical port id */
> + u8 ig_pid;
> + /* local extracted */
> + bool ext;
> + /* traffic class */
> + u8 tc_start;
> + u8 tc_end;
> + /* queue id */
> + u8 qid;
> + /* redirect logical port id */
> + u8 redir_pid;
> +};
> +
> +/* default GSWIP egress PCE bypass path Q-map */
> +static struct eg_pce_bypass_path eg_pce_byp_path[] = {
> + {MAC_2, false, QUEUE0, MAC_2 },
> + {MAC_3, false, QUEUE1, MAC_3 },
> + {MAC_4, false, QUEUE2, MAC_4 },
> + {MAC_5, false, QUEUE3, MAC_5 },
> + {MAC_6, false, QUEUE4, MAC_6 },
> + {MAC_7, false, QUEUE5, MAC_7 },
> + {MAC_8, false, QUEUE6, MAC_8 },
> + {MAC_9, false, QUEUE7, MAC_9 },
> + {MAC_10, false, QUEUE8, MAC_10},
> +};
> +
> +/* default GSWIP ingress PCE bypass path Q-map */
> +static struct ig_pce_bypass_path ig_pce_byp_path[] = {
> + {PMAC_0, false, TC0, TC_MAX, QUEUE10, PMAC_2},
> + {MAC_2, false, TC0, TC_MAX, QUEUE10, PMAC_2},
> + {MAC_3, false, TC0, TC_MAX, QUEUE10, PMAC_2},
> + {MAC_4, false, TC0, TC_MAX, QUEUE10, PMAC_2},
> + {MAC_5, false, TC0, TC_MAX, QUEUE10, PMAC_2},
> + {MAC_6, false, TC0, TC_MAX, QUEUE10, PMAC_2},
> + {MAC_7, false, TC0, TC_MAX, QUEUE10, PMAC_2},
> + {MAC_8, false, TC0, TC_MAX, QUEUE10, PMAC_2},
> + {MAC_9, false, TC0, TC_MAX, QUEUE10, PMAC_2},
> + {MAC_10, false, TC0, TC_MAX, QUEUE10, PMAC_2},
> +};
> +
> +static inline int pmac_ig_cfg(struct gswip_core_priv *priv, u8 pmac_id, u8 dpu)
> +{
> + u8 start[] = { PMAC0_TX_DMACHID_START,
> + PMAC1_TX_DMACHID_START,
> + PMAC2_TX_DMACHID_START };
> + u8 end[] = { PMAC0_TX_DMACHID_END,
> + PMAC1_TX_DMACHID_END,
> + PMAC2_TX_DMACHID_END };
> + u8 pmac[] = { PMAC_0, PMAC_1, PMAC_2 };
> + struct gswip_pmac_ig_cfg ig_cfg = {0};
> + int i, ret;
> +
> + ig_cfg.pmac_id = pmac_id;
> + ig_cfg.err_pkt_disc = true;
> + ig_cfg.class_en = true;
> +
> + for (i = start[pmac_id]; i < end[pmac_id]; i++) {
> + ig_cfg.tx_dma_chan_id = i;
> + ig_cfg.def_pmac_hdr[2] = FIELD_PREP(PMAC_IGCFG_HDR_ID,
> + pmac[pmac_id]);
> +
> + ret = gswip_pmac_ig_cfg_set(priv->dev, &ig_cfg);
> + if (ret)
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static inline int pmac_eg_cfg(struct gswip_core_priv *priv, u8 pmac_id, u8 dpu)
> +{
> + struct gswip_pmac_eg_cfg pmac_eg = {0};
> +
> + pmac_eg.pmac_id = pmac_id;
> + pmac_eg.pmac_en = true;
> + pmac_eg.bsl_seg_disable = true;
> +
> + return gswip_pmac_eg_cfg_set(priv->dev, &pmac_eg);
> +}
> +
> +static inline int pmac_glbl_cfg(struct gswip_core_priv *priv, u8 pmac_id)
> +{
> + struct gswip_pmac_glb_cfg pmac_cfg = {0};
> +
> + pmac_cfg.pmac_id = pmac_id;
> + pmac_cfg.rx_fcs_dis = true;
> + pmac_cfg.jumbo_en = true;
> + pmac_cfg.max_jumbo_len = MAX_JUMBO_FRM_LEN;
> + pmac_cfg.long_frm_chk_dis = true;
> + pmac_cfg.short_frm_chk_type = GSWIP_PMAC_SHORT_LEN_ENA_UNTAG;
> + pmac_cfg.proc_flags_eg_cfg_en = true;
> + pmac_cfg.proc_flags_eg_cfg = GSWIP_PMAC_PROC_FLAGS_MIX;
> +
> + return gswip_pmac_glb_cfg_set(priv->dev, &pmac_cfg);
> +}
> +
> +static int gswip_core_pmac_init_nondpu(struct gswip_core_priv *priv)
> +{
> + int i;
> +
> + for (i = 0; i < priv->num_pmac; i++) {
> + if (pmac_glbl_cfg(priv, i))
> + return -EINVAL;
Better to preserve the error codes.
> +
> + if (pmac_ig_cfg(priv, i, NON_DPU))
> + return -EINVAL;
> +
> + if (pmac_eg_cfg(priv, i, NON_DPU))
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int gswip_core_set_def_eg_pce_bypass_qmap(struct gswip_core_priv *priv,
> + enum gswip_qos_q_map_mode mode)
> +{
> + int num_elem = ARRAY_SIZE(eg_pce_byp_path);
> + struct gswip_qos_q_port q_map = {0};
> + int i;
> +
> + q_map.egress = true;
> + q_map.q_map_mode = mode;
> +
> + for (i = 0; i < num_elem; i++) {
> + q_map.lpid = eg_pce_byp_path[i].eg_pid;
> + q_map.extration_en = eg_pce_byp_path[i].ext;
> + q_map.qid = eg_pce_byp_path[i].qid;
> + q_map.redir_port_id = eg_pce_byp_path[i].redir_pid;
> +
> + if (gswip_qos_q_port_set(priv->dev, &q_map))
> + return -EINVAL;
Preserve.
> + }
> +
> + return 0;
> +}
> +
> +static int gswip_core_set_def_ig_pce_bypass_qmap(struct gswip_core_priv *priv)
> +{
> + int num_elem = ARRAY_SIZE(ig_pce_byp_path);
> + struct gswip_qos_q_port q_map = {0};
> + int i, j;
> +
> + q_map.en_ig_pce_bypass = true;
> +
> + for (i = 0; i < num_elem; i++) {
> + for (j = ig_pce_byp_path[i].tc_start;
> + j < ig_pce_byp_path[i].tc_end; j++) {
> + q_map.lpid = ig_pce_byp_path[i].ig_pid;
> + q_map.qid = ig_pce_byp_path[i].qid;
> + q_map.redir_port_id = ig_pce_byp_path[i].redir_pid;
> + q_map.tc_id = j;
> +
> + if (gswip_qos_q_port_set(priv->dev, &q_map))
> + return -EINVAL;
Preserve.
> + }
> + }
> +
> + return 0;
> +}
> +
> +static inline u16 pmac_reg(u16 offset, u8 id)
> +{
> + u16 pmac_offset[] = { 0, PMAC_REG_OFFSET_1, PMAC_REG_OFFSET_2 };
> +
> + return offset += pmac_offset[id];
> +}
> +
> +int gswip_pmac_glb_cfg_set(struct device *dev, struct gswip_pmac_glb_cfg *pmac)
> +{
> + struct gswip_core_priv *priv = dev_get_drvdata(dev);
> + u16 bsl_reg[] = { PMAC_BSL_LEN0, PMAC_BSL_LEN1, PMAC_BSL_LEN2 };
> + u16 ctrl_reg[] = { PMAC_CTRL_0, PMAC_CTRL_1,
> + PMAC_CTRL_2, PMAC_CTRL_4 };
> + u16 ctrl[PMAC_CTRL_NUM] = {0};
> + u8 id;
> + int i;
> +
> + if (pmac->pmac_id >= priv->num_pmac) {
> + dev_err(priv->dev, "Invalid pmac id %d\n", pmac->pmac_id);
> + return -EINVAL;
> + }
> +
> + ctrl[0] = FIELD_PREP(PMAC_CTRL_0_FCSEN, pmac->rx_fcs_dis) |
> + FIELD_PREP(PMAC_CTRL_0_APADEN, pmac->apad_en) |
> + FIELD_PREP(PMAC_CTRL_0_VPAD2EN, pmac->svpad_en) |
> + FIELD_PREP(PMAC_CTRL_0_VPADEN, pmac->vpad_en) |
> + FIELD_PREP(PMAC_CTRL_0_PADEN, pmac->pad_en) |
> + FIELD_PREP(PMAC_CTRL_0_FCS, pmac->tx_fcs_dis) |
> + FIELD_PREP(PMAC_CTRL_0_CHKREG, pmac->ip_trans_chk_reg_dis) |
> + FIELD_PREP(PMAC_CTRL_0_CHKVER, pmac->ip_trans_chk_ver_dis);
> +
> + if (pmac->jumbo_en) {
> + ctrl[1] = pmac->max_jumbo_len,
> + ctrl[2] = FIELD_PREP(PMAC_CTRL_2_MLEN, 1);
> + }
> +
> + ctrl[2] |= FIELD_PREP(PMAC_CTRL_2_LCHKL, pmac->long_frm_chk_dis);
> +
> + switch (pmac->short_frm_chk_type) {
> + case GSWIP_PMAC_SHORT_LEN_DIS:
> + ctrl[2] |= FIELD_PREP(PMAC_CTRL_2_LCHKS, 0);
> + break;
> +
> + case GSWIP_PMAC_SHORT_LEN_ENA_UNTAG:
> + ctrl[2] |= FIELD_PREP(PMAC_CTRL_2_LCHKS, 1);
> + break;
> +
> + case GSWIP_PMAC_SHORT_LEN_ENA_TAG:
> + ctrl[2] |= FIELD_PREP(PMAC_CTRL_2_LCHKS, 2);
> + break;
> +
> + case GSWIP_PMAC_SHORT_LEN_RESERVED:
> + ctrl[2] |= FIELD_PREP(PMAC_CTRL_2_LCHKS, 3);
> + break;
> + }
> +
> + switch (pmac->proc_flags_eg_cfg) {
> + case GSWIP_PMAC_PROC_FLAGS_NONE:
> + break;
> +
> + case GSWIP_PMAC_PROC_FLAGS_TC:
> + ctrl[3] |= FIELD_PREP(PMAC_CTRL_4_FLAGEN, 0);
> + break;
> +
> + case GSWIP_PMAC_PROC_FLAGS_FLAG:
> + ctrl[3] |= FIELD_PREP(PMAC_CTRL_4_FLAGEN, 1);
> + break;
> +
> + case GSWIP_PMAC_PROC_FLAGS_MIX:
> + ctrl[3] |= FIELD_PREP(PMAC_CTRL_4_FLAGEN, 2);
> + break;
> + }
> +
> + id = pmac->pmac_id;
> +
> + for (i = 0; i < PMAC_CTRL_NUM; i++)
> + regmap_write(priv->regmap, pmac_reg(ctrl_reg[i], id), ctrl[i]);
> +
> + for (i = 0; i < PMAC_BSL_NUM; i++)
> + regmap_write(priv->regmap, pmac_reg(bsl_reg[i], id),
> + pmac->bsl_thresh[i]);
> +
> + return 0;
> +}
> +
> +int gswip_pmac_bp_map_get(struct device *dev, struct gswip_pmac_bp_map *bp)
> +{
> + struct gswip_core_priv *priv = dev_get_drvdata(dev);
> + struct pmac_tbl_prog pmac_tbl = {0};
> + int ret;
> +
> + pmac_tbl.id = PMAC_BP_MAP;
> + pmac_tbl.pmac_id = bp->pmac_id;
> + pmac_tbl.addr = FIELD_GET(PMAC_BPMAP_TX_DMA_CH, bp->tx_dma_chan_id);
> + pmac_tbl.num_val = PMAC_BP_MAP_TBL_VAL_NUM;
> +
> + ret = gswip_pmac_table_read(priv, &pmac_tbl);
> + if (ret)
> + return -EINVAL;
> +
> + bp->rx_port_mask = pmac_tbl.val[0];
> + bp->tx_q_mask = pmac_tbl.val[1];
> + bp->tx_q_mask |= FIELD_PREP(PMAC_BPMAP_TX_Q_UPPER, pmac_tbl.val[2]);
> +
> + return 0;
> +}
> +
> +int gswip_pmac_ig_cfg_set(struct device *dev, struct gswip_pmac_ig_cfg *ig)
> +{
> + struct gswip_core_priv *priv = dev_get_drvdata(dev);
> + struct pmac_tbl_prog pmac_tbl = {0};
> + u16 *val;
> + u16 i;
> +
> + pmac_tbl.id = PMAC_IG_CFG;
> + pmac_tbl.pmac_id = ig->pmac_id;
> + pmac_tbl.addr = FIELD_GET(PMAC_IGCFG_TX_DMA_CH, ig->tx_dma_chan_id);
> +
> + val = &pmac_tbl.val[0];
> + for (i = 0; i < 4; i++)
> + val[i] = get_unaligned_be16(&ig->def_pmac_hdr[i * 2]);
> +
> + switch (ig->sub_id) {
> + case GSWIP_PMAC_IG_CFG_SRC_DMA_DESC:
> + break;
> +
> + case GSWIP_PMAC_IG_CFG_SRC_PMAC:
> + case GSWIP_PMAC_IG_CFG_SRC_DEF_PMAC:
> + val[4] = PMAC_IGCFG_VAL4_SUBID_MODE;
> + break;
> + }
> +
> + val[4] |= FIELD_PREP(PMAC_IGCFG_VAL4_PMAC_FLAG, ig->pmac_present) |
> + FIELD_PREP(PMAC_IGCFG_VAL4_CLASSEN_MODE, ig->class_en) |
> + FIELD_PREP(PMAC_IGCFG_VAL4_CLASS_MODE, ig->class_def) |
> + FIELD_PREP(PMAC_IGCFG_VAL4_ERR_DP, ig->err_pkt_disc) |
> + FIELD_PREP(PMAC_IGCFG_VAL4_SPPID_MODE, ig->src_port_id_def);
> +
> + pmac_tbl.num_val = PMAC_IG_CFG_TBL_VAL_NUM;
> +
> + return gswip_pmac_table_write(priv, &pmac_tbl);
> +}
> +
> +int gswip_pmac_eg_cfg_set(struct device *dev, struct gswip_pmac_eg_cfg *eg)
> +{
> + struct gswip_core_priv *priv = dev_get_drvdata(dev);
> + struct pmac_tbl_prog pmac_tbl = {0};
> + u16 ctrl, pmac_ctrl4;
> + u16 *val;
> +
> + pmac_ctrl4 = pmac_reg(PMAC_CTRL_4, eg->pmac_id);
> +
> + pmac_tbl.id = PMAC_EG_CFG;
> + pmac_tbl.pmac_id = eg->pmac_id;
> + pmac_tbl.addr = FIELD_PREP(PMAC_EGCFG_DST_PORT_ID, eg->dst_port_id)
> + | FIELD_PREP(PMAC_EGCFG_FLOW_ID_MSB,
> + eg->flow_id_msb);
> +
> + ctrl = reg_rbits(priv, pmac_ctrl4, PMAC_CTRL_4_FLAGEN);
> +
> + if (ctrl == PMAC_RX_FSM_IDLE) {
> + pmac_tbl.addr |= FIELD_PREP(PMAC_EGCFG_TC_4BITS, eg->tc);
> + } else if (ctrl == PMAC_RX_FSM_IGCFG) {
> + pmac_tbl.addr |= FIELD_PREP(PMAC_EGCFG_MPE1, eg->mpe1) |
> + FIELD_PREP(PMAC_EGCFG_MPE2, eg->mpe2) |
> + FIELD_PREP(PMAC_EGCFG_ECRYPT, eg->encrypt) |
> + FIELD_PREP(PMAC_EGCFG_DECRYPT, eg->decrypt);
> + } else if (ctrl == PMAC_RX_FSM_DASA) {
> + pmac_tbl.addr |= FIELD_PREP(PMAC_EGCFG_TC_2BITS, eg->tc) |
> + FIELD_PREP(PMAC_EGCFG_MPE1, eg->mpe1) |
> + FIELD_PREP(PMAC_EGCFG_MPE2, eg->mpe2);
> + }
> +
> + val = &pmac_tbl.val[0];
> + val[0] = FIELD_PREP(PMAC_EGCFG_VAL0_REDIR, eg->redir_en) |
> + FIELD_PREP(PMAC_EGCFG_VAL0_RES_3BITS, ctrl) |
> + FIELD_PREP(PMAC_EGCFG_VAL0_BSL, eg->bsl_tc) |
> + FIELD_PREP(PMAC_EGCFG_VAL0_RES_2BITS, eg->resv_2dw0);
> +
> + val[1] = FIELD_PREP(PMAC_EGCFG_VAL1_RX_DMA_CH, eg->rx_dma_chan_id);
> +
> + val[2] = FIELD_PREP(PMAC_EGCFG_VAL2_FCS_MODE, eg->fcs_en) |
> + FIELD_PREP(PMAC_EGCFG_VAL2_PMAC_FLAG, eg->pmac_en);
> +
> + if (eg->rm_l2_hdr) {
> + val[2] |= PMAC_EGCFG_VAL2_L2HD_RM_MODE |
> + FIELD_PREP(PMAC_EGCFG_VAL2_L2HD_RM,
> + eg->num_byte_rm);
> + }
> +
> + pmac_tbl.num_val = PMAC_EG_CFG_TBL_VAL_NUM;
> +
> + return gswip_pmac_table_write(priv, &pmac_tbl);
> +}
> +
> +int gswip_cpu_port_cfg_get(struct device *dev, struct gswip_cpu_port_cfg *cpu)
> +{
> + struct gswip_core_priv *priv = dev_get_drvdata(dev);
> + u16 lpid, val;
> +
> + lpid = cpu->lpid;
> + if (lpid >= priv->num_lport) {
> + dev_err(priv->dev, "Invalid cpu port id %d > %d\n",
> + lpid, priv->num_lport);
> + return -EINVAL;
> + }
> +
> + cpu->is_cpu_port = lpid == priv->cpu_port;
> + cpu->spec_tag_ig = reg_rbits(priv, PCE_PCTRL_0(lpid),
> + PCE_PCTRL_0_IGSTEN);
> + cpu->fcs_chk = reg_rbits(priv, SDMA_PCTRL(lpid), SDMA_PCTRL_FCSIGN);
> +
> + reg_r16(priv, FDMA_PASR, &val);
> + cpu->no_mpe_parser_cfg = FIELD_GET(FDMA_PASR_CPU, val);
> + cpu->mpe1_parser_cfg = FIELD_GET(FDMA_PASR_MPE1, val);
> + cpu->mpe2_parser_cfg = FIELD_GET(FDMA_PASR_MPE2, val);
> + cpu->mpe3_parser_cfg = FIELD_GET(FDMA_PASR_MPE3, val);
> +
> + reg_r16(priv, FDMA_PCTRL(lpid), &val);
> + cpu->spec_tag_eg = FIELD_GET(FDMA_PCTRL_STEN, val);
> + cpu->ts_rm_ptp_pkt = FIELD_GET(FDMA_PCTRL_TS_PTP, val);
> + cpu->ts_rm_non_ptp_pkt = FIELD_GET(FDMA_PCTRL_TS_NONPTP, val);
> +
> + return 0;
> +}
> +
> +int gswip_register_get(struct device *dev, struct gswip_register *param)
> +{
> + struct gswip_core_priv *priv = dev_get_drvdata(dev);
> +
> + reg_r16(priv, param->offset, ¶m->data);
> +
> + return 0;
> +}
> +
> +int gswip_register_set(struct device *dev, struct gswip_register *param)
> +{
> + struct gswip_core_priv *priv = dev_get_drvdata(dev);
> +
> + regmap_write(priv->regmap, param->offset, param->data);
> +
> + return 0;
> +}
> +
> +int gswip_lpid2gpid_set(struct device *dev, struct gswip_lpid2gpid *lp2gp)
> +{
> + struct gswip_core_priv *priv = dev_get_drvdata(dev);
> + u16 lpid, first_gpid, last_gpid, val;
> +
> + lpid = lp2gp->lpid;
> + first_gpid = lp2gp->first_gpid;
> + last_gpid = first_gpid + lp2gp->num_gpid - 1;
> +
> + if (lpid >= priv->num_lport) {
> + dev_err(priv->dev, "Invalid lpid %d >= %d\n",
> + lpid, priv->num_lport);
> + return -EINVAL;
> + }
> +
> + if (last_gpid >= priv->num_glb_port) {
> + dev_err(priv->dev, "Invalid last gpid %d >= %d\n",
> + last_gpid, priv->num_glb_port);
> + return -EINVAL;
> + }
> +
> + val = FIELD_PREP(ETHSW_GPID_STARTID_STARTID, first_gpid) |
> + FIELD_PREP(ETHSW_GPID_STARTID_BITS, lp2gp->valid_bits);
> + regmap_write(priv->regmap, ETHSW_GPID_STARTID(lpid), val);
> +
> + reg_wbits(priv, ETHSW_GPID_ENDID(lpid),
> + ETHSW_GPID_ENDID_ENDID, last_gpid);
> +
> + return 0;
> +}
> +
> +int gswip_lpid2gpid_get(struct device *dev, struct gswip_lpid2gpid *lp2gp)
> +{
> + struct gswip_core_priv *priv = dev_get_drvdata(dev);
> + u16 lpid, val;
> +
> + lpid = lp2gp->lpid;
> + if (lpid >= priv->num_lport) {
> + dev_err(priv->dev, "Invalid lpid %d >= %d\n",
> + lpid, priv->num_lport);
> + return -EINVAL;
> + }
> +
> + reg_r16(priv, ETHSW_GPID_STARTID(lpid), &val);
> + lp2gp->first_gpid = FIELD_GET(ETHSW_GPID_STARTID_STARTID, val);
> + lp2gp->valid_bits = FIELD_GET(ETHSW_GPID_STARTID_BITS, val);
> +
> + reg_r16(priv, ETHSW_GPID_ENDID(lpid), &val);
> + lp2gp->num_gpid = val - lp2gp->first_gpid + 1;
> +
> + return 0;
> +}
> +
> +int gswip_gpid2lpid_set(struct device *dev, struct gswip_gpid2lpid *gp2lp)
> +{
> + struct gswip_core_priv *priv = dev_get_drvdata(dev);
> + u16 val = 0;
> +
> + if (gp2lp->lpid >= priv->num_lport) {
> + dev_err(priv->dev, "Invalid lpid %d >= %d\n",
> + gp2lp->lpid, priv->num_lport);
> + return -EINVAL;
> + }
> +
> + if (gp2lp->gpid >= priv->num_glb_port) {
> + dev_err(priv->dev, "Invalid gpid %d >= %d\n",
> + gp2lp->gpid, priv->num_glb_port);
> + return -EINVAL;
> + }
> +
> + val = FIELD_PREP(GPID_RAM_VAL_LPID, gp2lp->lpid) |
> + FIELD_PREP(GPID_RAM_VAL_SUBID_GRP, gp2lp->subif_grp_field) |
> + FIELD_PREP(GPID_RAM_VAL_OV, gp2lp->subif_grp_field_ovr);
> +
> + regmap_write(priv->regmap, GPID_RAM_VAL, val);
> +
> + if (tbl_rw_tmout(priv, GPID_RAM_CTRL, GPID_RAM_CTRL_BAS)) {
> + dev_err(priv->dev, "failed to access gpid table\n");
> + return -EBUSY;
> + }
> +
> + reg_r16(priv, GPID_RAM_CTRL, &val);
> +
> + update_val(&val, GPID_RAM_CTRL_ADDR, gp2lp->gpid);
> + val |= FIELD_PREP(GPID_RAM_CTRL_OPMOD, 1) |
> + FIELD_PREP(GPID_RAM_CTRL_BAS, 1);
> +
> + regmap_write(priv->regmap, GPID_RAM_CTRL, val);
> +
> + if (tbl_rw_tmout(priv, GPID_RAM_CTRL, GPID_RAM_CTRL_BAS)) {
> + dev_err(priv->dev, "failed to write gpid table\n");
> + return -EBUSY;
> + }
> +
> + return 0;
> +}
> +
> +int gswip_gpid2lpid_get(struct device *dev, struct gswip_gpid2lpid *gp2lp)
> +{
> + struct gswip_core_priv *priv = dev_get_drvdata(dev);
> + u16 val;
> +
> + if (gp2lp->gpid >= priv->num_glb_port) {
> + dev_err(priv->dev, "gpid %d >= %d\n",
> + gp2lp->gpid, priv->num_glb_port);
> + return -EINVAL;
> + }
> +
> + if (tbl_rw_tmout(priv, GPID_RAM_CTRL, GPID_RAM_CTRL_BAS)) {
> + dev_err(priv->dev, "failed to access gpid table\n");
> + return -EBUSY;
> + }
> +
> + reg_r16(priv, GPID_RAM_CTRL, &val);
> +
> + update_val(&val, GPID_RAM_CTRL_ADDR, gp2lp->gpid);
> + val |= FIELD_PREP(GPID_RAM_CTRL_OPMOD, 0) |
> + FIELD_PREP(GPID_RAM_CTRL_BAS, 1);
> +
> + regmap_write(priv->regmap, GPID_RAM_CTRL, val);
> +
> + if (tbl_rw_tmout(priv, GPID_RAM_CTRL, GPID_RAM_CTRL_BAS)) {
> + dev_err(priv->dev, "failed to read gpid table\n");
> + return -EBUSY;
> + }
> +
> + reg_r16(priv, GPID_RAM_VAL, &val);
> +
> + gp2lp->lpid = FIELD_GET(GPID_RAM_VAL_LPID, val);
> + gp2lp->subif_grp_field = FIELD_GET(GPID_RAM_VAL_SUBID_GRP, val);
> + gp2lp->subif_grp_field_ovr = FIELD_GET(GPID_RAM_VAL_OV, val);
> +
> + return 0;
> +}
> +
> +int gswip_enable(struct device *dev, bool enable)
> +{
> + struct gswip_core_priv *priv = dev_get_drvdata(dev);
> + u16 i;
> +
> + for (i = 0; i < priv->num_lport; i++) {
> + reg_wbits(priv, FDMA_PCTRL(i), FDMA_PCTRL_EN, enable);
> + reg_wbits(priv, SDMA_PCTRL(i), SDMA_PCTRL_PEN, enable);
> + }
> +
> + return 0;
> +}
> +
> +static int gswip_core_get_hw_cap(struct gswip_core_priv *priv)
> +{
> + u16 val;
> +
> + priv->ver = reg_rbits(priv, ETHSW_VERSION, ETHSW_VERSION_REV_ID);
> + if (priv->ver != GSWIP_VER) {
> + dev_err(priv->dev, "Wrong hardware ip version\n");
> + return -EINVAL;
> + }
> +
> + priv->num_phy_port = reg_rbits(priv, ETHSW_CAP_1, ETHSW_CAP_1_PPORTS);
> +
> + reg_r16(priv, ETHSW_CAP_1, &val);
> + priv->num_lport = priv->num_phy_port;
> + priv->num_lport += FIELD_GET(ETHSW_CAP_1_VPORTS, val);
> + priv->num_q = FIELD_GET(ETHSW_CAP_1_QUEUE, val);
> +
> + priv->num_pmac = reg_rbits(priv, ETHSW_CAP_13, ETHSW_CAP_13_PMAC);
> +
> + reg_r16(priv, ETHSW_CAP_17, &val);
> + priv->num_br = (1 << FIELD_GET(ETHSW_CAP_17_BRG, val));
> + priv->num_br_port = (1 << FIELD_GET(ETHSW_CAP_17_BRGPT, val));
> +
> + reg_r16(priv, ETHSW_CAP_18, &priv->num_ctp);
> +
> + priv->num_glb_port = priv->num_br_port * 2;
> +
> + return 0;
> +}
> +
> +static int gswip_core_init(struct gswip_core_priv *priv)
> +{
> + priv->br_map = devm_kzalloc(priv->dev, BITS_TO_LONGS(priv->num_br),
> + GFP_KERNEL);
> + if (!priv->br_map)
> + return -ENOMEM;
> +
> + priv->br_port_map = devm_kzalloc(priv->dev,
> + BITS_TO_LONGS(priv->num_br_port),
> + GFP_KERNEL);
> + if (!priv->br_port_map)
> + return -ENOMEM;
> +
> + priv->ctp_port_map = devm_kzalloc(priv->dev,
> + BITS_TO_LONGS(priv->num_ctp),
> + GFP_KERNEL);
> + if (!priv->ctp_port_map)
> + return -ENOMEM;
> +
> + spin_lock_init(&priv->tbl_lock);
> +
> + return gswip_pce_table_init();
> +}
> +
> +static int gswip_core_setup(struct gswip_core_priv *priv)
> +{
> + if (gswip_core_set_def_eg_pce_bypass_qmap(priv,
> + GSWIP_QOS_QMAP_SINGLE_MODE))
> + return -EINVAL;
Preserve.
> +
> + if (gswip_core_set_def_ig_pce_bypass_qmap(priv))
> + return -EINVAL;
> +
> + if (gswip_core_pmac_init_nondpu(priv))
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> +static int gswip_core_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device *parent = dev->parent;
> + struct gswip_core_priv *priv;
> + struct gswip_pdata *pdata = parent->platform_data;
> + int ret;
> +
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + priv->pdev = pdev;
> + priv->dev = dev;
> + priv->regmap = pdata->core_regmap;
> +
> + platform_set_drvdata(pdev, priv);
> +
> + ret = gswip_core_get_hw_cap(priv);
> + if (ret)
> + return -EINVAL;
> +
> + ret = gswip_core_init(priv);
> + if (ret)
> + return ret;
> +
> + ret = gswip_core_setup(priv);
> + if (ret)
> + return ret;
> +
> + return 0;
> +}
> +
> +static const struct of_device_id gswip_core_of_match_table[] = {
> + { .compatible = "gswip-core" },
> + {}
> +};
> +
> +MODULE_DEVICE_TABLE(of, gswip_core);
> +
> +static struct platform_driver gswip_core_drv = {
> + .probe = gswip_core_probe,
> + .driver = {
> + .name = "gswip_core",
> + .of_match_table = gswip_core_of_match_table,
> + },
> +};
> +
> +module_platform_driver(gswip_core_drv);
> +
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/staging/intel-gwdpa/gswip/gswip_core.h b/drivers/staging/intel-gwdpa/gswip/gswip_core.h
> new file mode 100644
> index 000000000000..80e751da0c2f
> --- /dev/null
> +++ b/drivers/staging/intel-gwdpa/gswip/gswip_core.h
> @@ -0,0 +1,106 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright (c) 2016-2019 Intel Corporation. */
> +#ifndef _GSWIP_CORE_H_
> +#define _GSWIP_CORE_H_
> +
> +#include <linux/delay.h>
> +#include <linux/bitfield.h>
> +#include <linux/regmap.h>
> +
> +#include "gswip.h"
> +
> +/* table should be ready in 30 clock cycle */
> +#define TBL_BUSY_TIMEOUT_US 1
> +
> +struct gswip_core_priv {
> + struct device *dev;
> +
> + unsigned long *br_map;
> + unsigned long *br_port_map;
> + unsigned long *ctp_port_map;
> + void *pdev;
> +
> + u8 cpu_port;
> + u8 num_lport;
> + u8 num_br;
> + u8 num_br_port;
> + u16 num_ctp;
> + u16 num_glb_port;
> + u16 num_pmac;
> + u16 num_phy_port;
> + u16 num_q;
> +
> + u16 ver;
> + struct regmap *regmap;
> + /* table read/write lock */
> + spinlock_t tbl_lock;
> +};
> +
> +static inline void update_val(u16 *val, u16 mask, u16 set)
> +{
> + *val &= ~mask;
> + *val |= FIELD_PREP(mask, set);
> +}
> +
> +static inline void reg_r16(struct gswip_core_priv *priv, u16 reg, u16 *val)
> +{
> + unsigned int reg_val;
> +
> + regmap_read(priv->regmap, reg, ®_val);
> + *val = reg_val;
> +}
> +
> +static inline void reg_wbits(struct gswip_core_priv *priv,
> + u16 reg, u16 mask, u16 val)
> +{
> + regmap_update_bits(priv->regmap, reg, mask, FIELD_PREP(mask, val));
> +}
> +
> +static inline u16 reg_rbits(struct gswip_core_priv *priv, u16 reg, u16 mask)
> +{
> + unsigned int reg_val;
> +
> + regmap_read(priv->regmap, reg, ®_val);
> + return FIELD_GET(mask, reg_val);
> +}
> +
> +/* Access table with timeout */
> +static inline int tbl_rw_tmout(struct gswip_core_priv *priv, u16 reg, u16 mask)
> +{
> + unsigned int val;
> +
> + return regmap_read_poll_timeout(priv->regmap, reg, val, !(val & mask),
> + 0, TBL_BUSY_TIMEOUT_US);
> +}
> +
> +int gswip_cpu_port_cfg_get(struct device *dev, struct gswip_cpu_port_cfg *cpu);
> +int gswip_enable(struct device *dev, bool enable);
> +
> +int gswip_register_get(struct device *dev, struct gswip_register *param);
> +int gswip_register_set(struct device *dev, struct gswip_register *param);
> +
> +/* PMAC global configuration */
> +int gswip_pmac_glb_cfg_set(struct device *dev,
> + struct gswip_pmac_glb_cfg *pmac);
> +/* PMAC backpressure configuration */
> +int gswip_pmac_bp_map_get(struct device *dev, struct gswip_pmac_bp_map *bp);
> +/* PMAC ingress configuration */
> +int gswip_pmac_ig_cfg_set(struct device *dev, struct gswip_pmac_ig_cfg *ig);
> +/* PMAC egress configuration */
> +int gswip_pmac_eg_cfg_set(struct device *dev, struct gswip_pmac_eg_cfg *eg);
> +
> +/* -- Global Port ID/ Logical Port ID --*/
> +int gswip_lpid2gpid_set(struct device *dev, struct gswip_lpid2gpid *lp2gp);
> +int gswip_lpid2gpid_get(struct device *dev, struct gswip_lpid2gpid *lp2gp);
> +int gswip_gpid2lpid_set(struct device *dev, struct gswip_gpid2lpid *gp2lp);
> +int gswip_gpid2lpid_get(struct device *dev, struct gswip_gpid2lpid *gp2lp);
> +
> +int gswip_ctp_port_alloc(struct device *dev, struct gswip_ctp_port_info *ctp);
> +int gswip_ctp_port_free(struct device *dev, u8 lpid);
> +int gswip_bridge_port_alloc(struct device *dev,
> + struct gswip_br_port_alloc *bp);
> +int gswip_bridge_port_free(struct device *dev, struct gswip_br_port_alloc *bp);
> +int gswip_bridge_alloc(struct device *dev, struct gswip_br_alloc *br);
> +int gswip_bridge_free(struct device *dev, struct gswip_br_alloc *br);
> +int gswip_qos_q_port_set(struct device *dev, struct gswip_qos_q_port *qport);
> +#endif
> diff --git a/drivers/staging/intel-gwdpa/gswip/gswip_dev.c b/drivers/staging/intel-gwdpa/gswip/gswip_dev.c
> new file mode 100644
> index 000000000000..59c2baba6da5
> --- /dev/null
> +++ b/drivers/staging/intel-gwdpa/gswip/gswip_dev.c
> @@ -0,0 +1,184 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2016-2019 Intel Corporation. */
> +
> +#include <linux/clk.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/reset.h>
> +
> +#include "gswip.h"
> +#include "gswip_dev.h"
> +
> +#define GSWIP_SUBDEV_MAC_MAX 9
> +#define GSWIP_SUBDEV_CORE_MAX 1
> +#define GSWIP_MAC_DEV_NAME "gswip_mac"
> +#define GSWIP_CORE_DEV_NAME "gswip_core"
> +
> +struct gswip_priv {
> + struct device *dev;
> + u32 id;
> + int num_subdev_mac;
> + int num_subdev_core;
> + struct gswip_pdata pdata;
> +};
> +
> +static int regmap_reg_write(void *context, unsigned int reg, unsigned int val)
> +{
> + void __iomem *base = context;
> +
> + writew(val, base + reg);
> +
> + return 0;
> +}
> +
> +static int regmap_reg_read(void *context, unsigned int reg, unsigned int *val)
> +{
> + void __iomem *base = context;
> +
> + *val = readw(base + reg);
> +
> + return 0;
> +}
> +
> +static const struct regmap_config gswip_core_regmap_config = {
> + .reg_bits = 16,
> + .val_bits = 16,
> + .reg_stride = 4,
> + .reg_write = regmap_reg_write,
> + .reg_read = regmap_reg_read,
> + .fast_io = true,
> +};
> +
> +static int np_gswip_parse_dt(struct platform_device *pdev,
> + struct gswip_priv *priv)
> +{
> + struct device *dev = &pdev->dev;
> + struct device_node *node = dev->of_node;
> + struct gswip_pdata *pdata = &priv->pdata;
> + struct device_node *np;
> + void __iomem *core;
> +
> + pdata->sw = devm_platform_ioremap_resource_byname(pdev, "switch");
> + if (IS_ERR(pdata->sw))
> + return PTR_ERR(pdata->sw);
> +
> + pdata->lmac = devm_platform_ioremap_resource_byname(pdev, "lmac");
> + if (IS_ERR(pdata->lmac))
> + return PTR_ERR(pdata->lmac);
> +
> + core = devm_platform_ioremap_resource_byname(pdev, "core");
> + if (IS_ERR(core))
> + return PTR_ERR(core);
> + pdata->core_regmap = devm_regmap_init(dev, NULL, core,
> + &gswip_core_regmap_config);
> + if (IS_ERR(pdata->core_regmap))
> + return PTR_ERR(pdata->core_regmap);
> +
> + pdata->sw_irq = platform_get_irq_byname(pdev, "switch");
> + if (pdata->sw_irq < 0) {
> + dev_err(dev, "switch irq not found\n");
> + return -ENODEV;
> + }
> +
> + pdata->core_irq = platform_get_irq_byname(pdev, "core");
> + if (pdata->core_irq < 0) {
> + dev_err(dev, "core irq not found\n");
> + return -ENODEV;
> + }
> +
> + pdata->ptp_clk = devm_clk_get(dev, "ptp");
> + if (IS_ERR(pdata->ptp_clk))
> + return PTR_ERR(pdata->ptp_clk);
> +
> + pdata->sw_clk = devm_clk_get(dev, "switch");
> + if (IS_ERR(pdata->sw_clk))
> + return PTR_ERR(priv->pdata.sw_clk);
> +
> + for_each_node_by_name(node, GSWIP_MAC_DEV_NAME) {
> + priv->num_subdev_mac++;
> + if (priv->num_subdev_mac > GSWIP_SUBDEV_MAC_MAX) {
> + dev_err(dev, "too many GSWIP mac subdevices\n");
> + return -EINVAL;
> + }
> + }
> +
> + if (!priv->num_subdev_mac) {
> + dev_err(dev, "GSWIP mac subdevice not found\n");
> + return -EINVAL;
> + }
> +
> + np = of_find_node_by_name(node, GSWIP_CORE_DEV_NAME);
> + if (np) {
> + priv->num_subdev_core++;
> + of_node_put(np);
> + } else {
> + dev_err(dev, "GSWIP core subdevice not found\n");
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static const struct of_device_id gswip_of_match_table[] = {
> + { .compatible = "intel,lgm-gswip" },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, gswip_of_match_table);
> +
> +static int np_gswip_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct reset_control *rcu_reset;
> + struct gswip_priv *priv;
> + int ret;
> +
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + priv->dev = dev;
> +
> + ret = np_gswip_parse_dt(pdev, priv);
> + if (ret) {
> + dev_err(dev, "failed to parse device tree\n");
> + return ret;
> + }
> +
> + dev->id = priv->id;
> +
> + rcu_reset = devm_reset_control_get_optional(dev, NULL);
> + if (IS_ERR(rcu_reset)) {
> + dev_err(dev, "error getting reset control of gswip\n");
> + return PTR_ERR(rcu_reset);
> + }
> +
> + reset_control_assert(rcu_reset);
> + udelay(1);
> + reset_control_deassert(rcu_reset);
> +
> + dev_set_drvdata(dev, priv);
> +
> + dev->platform_data = &priv->pdata;
> +
> + ret = devm_of_platform_populate(dev);
> +
> + return ret;
> +}
> +
> +static struct platform_driver np_gswip_driver = {
> + .probe = np_gswip_probe,
> + .driver = {
> + .name = "np_gswip",
> + .of_match_table = gswip_of_match_table,
> + },
> +};
> +
> +module_platform_driver(np_gswip_driver);
> +
> +MODULE_LICENSE("GPL v2");
> +
> diff --git a/drivers/staging/intel-gwdpa/gswip/gswip_dev.h b/drivers/staging/intel-gwdpa/gswip/gswip_dev.h
> new file mode 100644
> index 000000000000..6fa4b90de65c
> --- /dev/null
> +++ b/drivers/staging/intel-gwdpa/gswip/gswip_dev.h
> @@ -0,0 +1,18 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright (c) 2016-2019 Intel Corporation. */
> +#ifndef _GSWIP_DEV_H
> +#define _GSWIP_DEV_H
> +
> +struct gswip_pdata {
> + void __iomem *sw;
> + void __iomem *lmac;
> + int sw_irq;
> + int core_irq;
> + struct clk *ptp_clk;
> + struct clk *sw_clk;
> + bool intr_flag;
> + struct regmap *core_regmap;
> +};
> +
> +#endif
> +
> diff --git a/drivers/staging/intel-gwdpa/gswip/gswip_mac.c b/drivers/staging/intel-gwdpa/gswip/gswip_mac.c
> new file mode 100644
> index 000000000000..fcb6fad2f9f6
> --- /dev/null
> +++ b/drivers/staging/intel-gwdpa/gswip/gswip_mac.c
> @@ -0,0 +1,225 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2016-2019 Intel Corporation. */
> +
> +#include <linux/bitfield.h>
> +#include <linux/types.h>
> +
> +#include "mac_common.h"
> +
> +int sw_set_corese(struct device *dev, u32 val)
"corese" is confusing. "core_enable" would be better.
> +{
> + struct gswip_mac *priv = dev_get_drvdata(dev);
> + u32 reg;
> +
> + spin_lock_bh(&priv->sw_lock);
> + reg = sw_read(priv, GSWIP_CFG);
> + reg &= ~GSWIP_CFG_CORE_SE_EN;
> + reg |= FIELD_PREP(GSWIP_CFG_CORE_SE_EN, val);
> + sw_write(priv, GSWIP_CFG, reg);
> + spin_unlock_bh(&priv->sw_lock);
> +
> + return 0;
> +}
> +
> +int sw_set_mac_rxfcs_op(struct gswip_mac *priv, u32 val)
> +{
> + u32 mac_op_cfg;
> +
> + mac_op_cfg = sw_read(priv, MAC_OP_CFG_REG(priv->mac_idx));
> + if (FIELD_GET(MAC_OP_CFG_RX_FCS, mac_op_cfg) != val) {
> + mac_op_cfg &= ~MAC_OP_CFG_RX_FCS;
> + mac_op_cfg |= FIELD_PREP(MAC_OP_CFG_RX_FCS, val);
> + sw_write(priv, MAC_OP_CFG_REG(priv->mac_idx), mac_op_cfg);
> + }
> +
> + return 0;
> +}
> +
> +int sw_set_eee_cap(struct gswip_mac *priv, u32 val)
> +{
> + u32 aneg_eee;
> +
> + aneg_eee = sw_read(priv, ANEG_EEE_REG(priv->mac_idx));
> + aneg_eee &= ~ANEG_EEE_CAP;
> + aneg_eee |= FIELD_PREP(ANEG_EEE_CAP, val);
> + sw_write(priv, ANEG_EEE_REG(priv->mac_idx), aneg_eee);
> +
> + return 0;
> +}
> +
> +int sw_set_fe_intf(struct gswip_mac *priv, u32 macif)
> +{
> + u32 mac_if_cfg;
> +
> + mac_if_cfg = sw_read(priv, MAC_IF_CFG_REG(priv->mac_idx));
> +
> + if (macif == LMAC_MII)
> + mac_if_cfg &= ~MAC_IF_CFG_CFGFE;
> + else
> + mac_if_cfg |= MAC_IF_CFG_CFGFE;
> +
> + sw_write(priv, MAC_IF_CFG_REG(priv->mac_idx), mac_if_cfg);
> +
> + return 0;
> +}
> +
> +int sw_set_1g_intf(struct gswip_mac *priv, u32 macif)
> +{
> + u32 mac_if_cfg;
> +
> + mac_if_cfg = sw_read(priv, MAC_IF_CFG_REG(priv->mac_idx));
> +
> + if (macif == LMAC_GMII)
> + mac_if_cfg &= ~MAC_IF_CFG_CFG1G;
> + else
> + mac_if_cfg |= MAC_IF_CFG_CFG1G;
> +
> + sw_write(priv, MAC_IF_CFG_REG(priv->mac_idx), mac_if_cfg);
> +
> + return 0;
> +}
> +
> +int sw_set_2G5_intf(struct gswip_mac *priv, u32 macif)
> +{
> + u32 mac_if_cfg;
> +
> + mac_if_cfg = sw_read(priv, MAC_IF_CFG_REG(priv->mac_idx));
> +
> + if (macif == XGMAC_GMII)
> + mac_if_cfg &= ~MAC_IF_CFG_CFG2G5;
> + else
> + mac_if_cfg |= MAC_IF_CFG_CFG2G5;
> +
> + sw_write(priv, MAC_IF_CFG_REG(priv->mac_idx), mac_if_cfg);
> +
> + return 0;
> +}
> +
> +int sw_set_speed(struct gswip_mac *priv, u8 speed)
> +{
> + u16 phy_mode = 0;
> + u8 speed_msb = 0, speed_lsb = 0;
> +
> + phy_mode = sw_read(priv, PHY_MODE_REG(priv->mac_idx));
> +
> + /* clear first */
> + phy_mode &= ~PHY_MODE_SPEED_MSB & ~PHY_MODE_SPEED_LSB;
> +
> + speed_msb = FIELD_GET(SPEED_MSB, speed);
> + speed_lsb = FIELD_GET(SPEED_LSB, speed);
> + phy_mode |= FIELD_PREP(PHY_MODE_SPEED_MSB, speed_msb);
> + phy_mode |= FIELD_PREP(PHY_MODE_SPEED_LSB, speed_lsb);
> +
> + sw_write(priv, PHY_MODE_REG(priv->mac_idx), phy_mode);
> +
> + return 0;
> +}
> +
> +int sw_set_duplex_mode(struct gswip_mac *priv, u32 val)
> +{
> + u16 phy_mode;
> +
> + phy_mode = sw_read(priv, PHY_MODE_REG(priv->mac_idx));
> + if (FIELD_GET(PHY_MODE_FDUP, phy_mode) != val) {
> + phy_mode &= ~PHY_MODE_FDUP;
> + phy_mode |= FIELD_PREP(PHY_MODE_FDUP, val);
> + sw_write(priv, PHY_MODE_REG(priv->mac_idx), phy_mode);
> + }
> +
> + return 0;
> +}
> +
> +u32 sw_get_duplex_mode(struct gswip_mac *priv)
> +{
> + u16 phy_mode;
> + u32 val;
> +
> + phy_mode = sw_read(priv, PHY_MODE_REG(priv->mac_idx));
> + val = FIELD_GET(PHY_MODE_FDUP, phy_mode);
> +
> + return val;
> +}
> +
> +u32 sw_get_linkstatus(struct gswip_mac *priv)
> +{
> + u16 phy_mode;
> + u32 linkst;
> +
> + phy_mode = sw_read(priv, PHY_MODE_REG(priv->mac_idx));
> + linkst = FIELD_GET(PHY_MODE_LINKST, phy_mode);
> +
> + return linkst;
> +}
> +
> +int sw_set_linkstatus(struct gswip_mac *priv, u8 linkst)
> +{
> + u16 phy_mode;
> + u8 val;
> +
> + phy_mode = sw_read(priv, PHY_MODE_REG(priv->mac_idx));
> + val = FIELD_GET(PHY_MODE_LINKST, phy_mode);
> + if (val != linkst) {
> + phy_mode &= ~PHY_MODE_LINKST;
> + phy_mode |= FIELD_PREP(PHY_MODE_LINKST, linkst);
> + sw_write(priv, PHY_MODE_REG(priv->mac_idx), phy_mode);
> + }
> +
> + return 0;
> +}
> +
> +int sw_set_flowctrl(struct gswip_mac *priv, u8 val, u32 mode)
> +{
> + u16 phy_mode;
> +
> + phy_mode = sw_read(priv, PHY_MODE_REG(priv->mac_idx));
> +
> + switch (mode) {
> + case FCONRX:
> + phy_mode &= ~PHY_MODE_FCONRX;
> + phy_mode |= FIELD_PREP(PHY_MODE_FCONRX, val);
> + break;
> +
> + case FCONTX:
> + phy_mode &= ~PHY_MODE_FCONTX;
> + phy_mode |= FIELD_PREP(PHY_MODE_FCONTX, val);
> + break;
> + }
> +
> + sw_write(priv, PHY_MODE_REG(priv->mac_idx), phy_mode);
> +
> + return 0;
> +}
> +
> +u32 sw_get_speed(struct gswip_mac *priv)
> +{
> + u16 phy_mode = 0;
> + u32 speed_msb, speed_lsb, speed;
> +
> + phy_mode = sw_read(priv, PHY_MODE_REG(priv->mac_idx));
> + speed_msb = FIELD_GET(PHY_MODE_SPEED_MSB, phy_mode);
> + speed_lsb = FIELD_GET(PHY_MODE_SPEED_LSB, phy_mode);
> + speed = (speed_msb << 2) | speed_lsb;
> +
> + return speed;
> +}
> +
> +u32 sw_mac_get_mtu(struct gswip_mac *priv)
> +{
> + u32 reg, val;
> +
> + reg = sw_read(priv, MAC_MTU_CFG_REG(priv->mac_idx));
> + val = FIELD_PREP(MAC_MTU_CFG_MTU, reg);
> +
> + return val;
> +}
> +
> +int sw_mac_set_mtu(struct gswip_mac *priv, u32 mtu)
> +{
> + u32 val;
> +
> + val = sw_mac_get_mtu(priv);
> + if (val != mtu)
> + sw_write(priv, MAC_MTU_CFG_REG(priv->mac_idx), mtu);
> +
> + return 0;
> +}
> diff --git a/drivers/staging/intel-gwdpa/gswip/gswip_port.c b/drivers/staging/intel-gwdpa/gswip/gswip_port.c
> new file mode 100644
> index 000000000000..023ec0ddfb22
> --- /dev/null
> +++ b/drivers/staging/intel-gwdpa/gswip/gswip_port.c
> @@ -0,0 +1,296 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2016-2019 Intel Corporation.*/
> +#include "gswip_core.h"
> +#include "gswip_reg.h"
> +#include "gswip_tbl.h"
> +
> +static int gswip_ctp_port_set(struct gswip_core_priv *priv,
> + struct gswip_ctp_port_info *ctp)
> +{
> + u16 val, last_port;
> +
> + val = ctp->first_pid;
> + last_port = ctp->first_pid + ctp->num_port - 1;
> +
> + switch (ctp->mode) {
> + case GSWIP_LPORT_8BIT_WLAN:
> + val |= FIELD_PREP(ETHSW_CTP_STARTID_MD, MD_WLAN8);
> + break;
> +
> + case GSWIP_LPORT_9BIT_WLAN:
> + val |= FIELD_PREP(ETHSW_CTP_STARTID_MD, MD_WLAN8);
> + break;
> + case GSWIP_LPORT_GPON:
> + case GSWIP_LPORT_EPON:
> + case GSWIP_LPORT_GINT:
> + case GSWIP_LPORT_OTHER:
> + val |= FIELD_PREP(ETHSW_CTP_STARTID_MD, MD_OTHER);
> + break;
> + }
> +
> + regmap_write(priv->regmap, ETHSW_CTP_STARTID(ctp->lpid), val);
> + regmap_write(priv->regmap, ETHSW_CTP_ENDID(ctp->lpid), last_port);
> +
> + return 0;
> +}
> +
> +static int gswip_ctp_port_get(struct gswip_core_priv *priv,
> + struct gswip_ctp_port_info *ctp)
> +{
> + u16 val, last_port;
> +
> + reg_r16(priv, ETHSW_CTP_STARTID(ctp->lpid), &val);
> +
> + ctp->mode = FIELD_GET(ETHSW_CTP_STARTID_MD, val);
> + ctp->first_pid = FIELD_GET(ETHSW_CTP_STARTID_STARTID, val);
> +
> + last_port = reg_rbits(priv, ETHSW_CTP_ENDID(ctp->lpid),
> + ETHSW_CTP_ENDID_ENDID);
> + ctp->num_port = last_port - ctp->first_pid + 1;
> +
> + return 0;
> +}
> +
> +int gswip_ctp_port_alloc(struct device *dev,
> + struct gswip_ctp_port_info *ctp)
> +{
> + struct gswip_core_priv *priv = dev_get_drvdata(dev);
> + u16 first_ctp;
> + int ret;
> +
> + if (!ctp->num_port || ctp->num_port >= priv->num_ctp) {
> + dev_err(priv->dev, "Invalid num of ctp port requested %d\n",
> + ctp->num_port);
> + return -EINVAL;
> + }
> +
> + first_ctp = bitmap_find_next_zero_area(priv->ctp_port_map,
> + priv->num_ctp, 0,
> + ctp->num_port, 0);
> + if (first_ctp >= priv->num_ctp) {
> + dev_err(priv->dev, "Failed to find contiguous ctp port\n");
> + return -EINVAL;
> + }
> +
> + bitmap_set(priv->ctp_port_map, first_ctp, ctp->num_port);
> + ctp->first_pid = first_ctp;
> +
> + ret = gswip_ctp_port_set(priv, ctp);
> + if (ret) {
> + bitmap_clear(priv->ctp_port_map, first_ctp, ctp->num_port);
> + return ret;
> + }
> +
> + reg_wbits(priv, SDMA_PCTRL(ctp->lpid), SDMA_PCTRL_PEN, ENABLE);
> +
> + return 0;
> +}
> +
> +int gswip_ctp_port_free(struct device *dev, u8 lpid)
> +{
> + struct gswip_core_priv *priv = dev_get_drvdata(dev);
> + struct gswip_ctp_port_info ctp;
> +
> + if (lpid >= priv->num_lport) {
> + dev_err(priv->dev, "Invalid lpid %d\n", lpid);
> + return -EINVAL;
> + }
> +
> + ctp.lpid = lpid;
> + gswip_ctp_port_get(priv, &ctp);
> +
> + reg_wbits(priv, SDMA_PCTRL(lpid), SDMA_PCTRL_PEN, DISABLE);
> + regmap_write(priv->regmap, ETHSW_CTP_STARTID(lpid), 0);
> + regmap_write(priv->regmap, ETHSW_CTP_ENDID(lpid), 0);
> +
> + bitmap_clear(priv->ctp_port_map, ctp.first_pid, ctp.num_port);
> +
> + return 0;
> +}
> +
> +int gswip_bridge_port_alloc(struct device *dev, struct gswip_br_port_alloc *bp)
This function is never called.
> +{
> + struct gswip_core_priv *priv = dev_get_drvdata(dev);
> + struct pce_tbl_prog pce_tbl = {0};
> + int ret;
> +
> + bp->br_pid = find_first_zero_bit(priv->br_port_map, priv->num_br_port);
> + if (bp->br_pid >= priv->num_br_port) {
> + dev_err(priv->dev, "failed to alloc bridge port\n");
> + return -EINVAL;
> + }
> +
> + set_bit(bp->br_pid, priv->br_port_map);
> +
> + pce_tbl.id = PCE_IG_BRP_CFG;
> + pce_tbl.addr = bp->br_pid;
> + pce_tbl.val[4] = PCE_MAC_LIMIT_NUM |
> + FIELD_PREP(PCE_IGBGP_VAL4_BR_ID, bp->br_id);
> +
> + ret = gswip_pce_table_write(priv, &pce_tbl);
> + if (ret) {
> + clear_bit(bp->br_pid, priv->br_port_map);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +int gswip_bridge_port_free(struct device *dev, struct gswip_br_port_alloc *bp)
Never called.
> +{
> + struct gswip_core_priv *priv = dev_get_drvdata(dev);
> + struct pce_tbl_prog pce_tbl = {0};
> + u16 br_pid;
> + int ret;
> +
> + br_pid = bp->br_pid;
> + if (br_pid >= priv->num_br_port) {
> + dev_err(priv->dev, "brige port id %d >=%d\n",
> + br_pid, priv->num_br_port);
> + return -EINVAL;
> + }
> +
> + if (!test_bit(br_pid, priv->br_port_map)) {
> + dev_err(priv->dev, "bridge port id %d is not in used\n",
> + br_pid);
> + return -EINVAL;
> + }
> +
> + pce_tbl.id = PCE_IG_BRP_CFG;
> + pce_tbl.addr = br_pid;
> + pce_tbl.val[4] = PCE_MAC_LIMIT_NUM;
> +
> + ret = gswip_pce_table_write(priv, &pce_tbl);
> + if (ret)
> + return ret;
> +
> + clear_bit(br_pid, priv->br_port_map);
> +
> + return 0;
> +}
> +
> +int gswip_bridge_alloc(struct device *dev, struct gswip_br_alloc *br)
> +{
> + struct gswip_core_priv *priv = dev_get_drvdata(dev);
> +
> + br->br_id = find_first_zero_bit(priv->br_map, priv->num_br);
> + if (br->br_id >= priv->num_br) {
> + dev_err(priv->dev, "failed to alloc bridge\n");
> + return -EINVAL;
> + }
> +
> + set_bit(br->br_id, priv->br_map);
> +
> + return 0;
> +}
> +
> +int gswip_bridge_free(struct device *dev, struct gswip_br_alloc *br)
Never called.
> +{
> + struct gswip_core_priv *priv = dev_get_drvdata(dev);
> + struct pce_tbl_prog pce_tbl = {0};
> + u16 br_id;
> + int ret;
> +
> + if (br->br_id >= priv->num_br) {
> + dev_err(priv->dev, "bridge id %d >= %d\n",
> + br->br_id, priv->num_br);
> + return -EINVAL;
> + }
> +
> + br_id = br->br_id;
> + if (!test_bit(br_id, priv->br_map)) {
> + dev_err(priv->dev, "bridge id %d not allocated\n", br_id);
> + return 0;
> + }
> +
> + pce_tbl.id = PCE_BR_CFG;
> + pce_tbl.addr = br_id;
> + pce_tbl.val[0] = PCE_MAC_LIMIT_NUM;
> +
> + ret = gswip_pce_table_write(priv, &pce_tbl);
> + if (ret)
> + return ret;
> +
> + clear_bit(br_id, priv->br_map);
> +
> + return 0;
> +}
> +
> +/*
> + * Set queue for a logical port based on egress/ingress packet.
> + * Then map the queue to an egress port.
> + * +----------------------+ +---------------------+
> + * | ingress logical port | -> queue/s -> | egress logical port |
> + * +----------------------+ +---------------------+
> + */
> +int gswip_qos_q_port_set(struct device *dev, struct gswip_qos_q_port *qport)
> +{
> + struct gswip_core_priv *priv = dev_get_drvdata(dev);
> + struct pce_tbl_prog pce_tbl = {0};
> + struct bm_tbl_prog bm_tbl = {0};
> + u16 eg_port, val;
> + u8 qid;
> + int ret;
> +
> + qid = qport->qid;
> +
> + if (qport->egress) {
> + /*
> + * Egress packet always bypass PCE.
> + * Queue identifier is set in the SDMA_BYPASS register
> + * for each logical port.
> + */
> + reg_r16(priv, SDMA_BYPASS(qport->lpid), &val);
> +
> + if (!qport->extration_en) {
> + if (qport->q_map_mode == GSWIP_QOS_QMAP_SINGLE_MODE)
> + val |= FIELD_PREP(SDMA_BYPASS_MD, 1);
> + else
> + val |= FIELD_PREP(SDMA_BYPASS_MD, 0);
> +
> + val |= FIELD_PREP(SDMA_BYPASS_NMQID, qid);
> + } else {
> + val |= FIELD_PREP(SDMA_BYPASS_EXTQID, qid);
> + }
> +
> + regmap_write(priv->regmap, SDMA_BYPASS(qport->lpid), val);
> + } else {
> + /*
> + * Ingress packet can bypass or not bypass PCE.
> + * Queue identifier is set in the Queue Mapping Table
> + * under PCE Table Programming. This table will be used
> + * for bypass/no bypass case.
> + */
> + pce_tbl.id = PCE_Q_MAP;
> + pce_tbl.addr = qport->tc_id;
> + pce_tbl.addr |= FIELD_PREP(PCE_Q_MAP_EG_PID, qport->lpid);
> +
> + if (qport->en_ig_pce_bypass || qport->resv_port_mode) {
> + pce_tbl.addr |= PCE_Q_MAP_IG_PORT_MODE;
> + } else {
> + if (qport->extration_en)
> + pce_tbl.addr |= PCE_Q_MAP_LOCAL_EXTRACT;
> + }
> +
> + pce_tbl.val[0] = qid;
> + ret = gswip_pce_table_write(priv, &pce_tbl);
> + if (ret)
> + return ret;
> +
> + reg_wbits(priv, SDMA_BYPASS(qport->lpid),
> + SDMA_BYPASS_PCEBYP, qport->en_ig_pce_bypass);
> + }
> +
> + /* Redirect port id for table is bit 4, and bit (2,0) */
> + eg_port = FIELD_GET(BM_Q_MAP_VAL4_REDIR_PID, qport->redir_port_id);
> + val = FIELD_GET(BM_Q_MAP_VAL4_REDIR_PID_MSB, qport->redir_port_id);
> + eg_port |= FIELD_PREP(BM_Q_MAP_VAL4_REDIR_PID_BIT4, val);
> +
> + /* Map queue to an egress port. */
> + bm_tbl.id = BM_Q_MAP;
> + bm_tbl.val[0] = eg_port;
> + bm_tbl.num_val = 1;
> + bm_tbl.qmap.qid = qid;
> +
> + return gswip_bm_table_write(priv, &bm_tbl);
> +}
> diff --git a/drivers/staging/intel-gwdpa/gswip/gswip_reg.h b/drivers/staging/intel-gwdpa/gswip/gswip_reg.h
> new file mode 100644
> index 000000000000..3107339871e2
> --- /dev/null
> +++ b/drivers/staging/intel-gwdpa/gswip/gswip_reg.h
> @@ -0,0 +1,487 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright (c) 2016-2019 Intel Corporation.
> + *
> + * GSWIP-O Top and Legacy MAC Register Description.
> + */
> +#ifndef _GSWIP_REG_H
> +#define _GSWIP_REG_H
> +
> +#define ENABLE 1
> +#define DISABLE 0
> +
> +#define ETHSW_CAP_1 0x001c
> +#define ETHSW_CAP_1_PPORTS GENMASK(3, 0)
> +#define ETHSW_CAP_1_VPORTS GENMASK(7, 4)
> +#define ETHSW_CAP_1_QUEUE GENMASK(14, 8)
> +#define ETHSW_CAP_1_GMAC BIT(15)
> +
> +#define ETHSW_VERSION 0x004c
> +#define ETHSW_VERSION_REV_ID GENMASK(7, 0)
> +#define ETHSW_VERSION_MOD_ID GENMASK(15, 8)
> +
> +#define ETHSW_CAP_13 0x0058
> +#define ETHSW_CAP_13_EVLAN GENMASK(3, 0)
> +#define ETHSW_CAP_13_INTRMON GENMASK(7, 4)
> +#define ETHSW_CAP_13_PAYLOAD GENMASK(11, 8)
> +#define ETHSW_CAP_13_PMAC GENMASK(15, 12)
> +
> +#define ETHSW_CAP_17 0x0068
> +#define ETHSW_CAP_17_BRGPT GENMASK(3, 0)
> +#define ETHSW_CAP_17_BRG GENMASK(7, 4)
> +#define ETHSW_CAP_17_PMAP GENMASK(11, 8)
> +
> +#define ETHSW_CAP_18 0x006c
> +#define ETHSW_CAP_18_CTP GENMASK(15, 0)
> +
> +#define BM_RAM_VAL_OFFSET 4
> +#define BM_RAM_VAL_0 0x010c
> +#define BM_RAM_VAL_0_VAL0 GENMASK(15, 0)
> +
> +#define BM_RAM_ADDR 0x0110
> +#define BM_RAM_ADDR_ADDR GENMASK(15, 0)
> +
> +#define BM_RAM_CTRL 0x0114
> +#define BM_RAM_CTRL_ADDR GENMASK(4, 0)
> +#define BM_RAM_CTRL_OPMOD BIT(5)
> +#define BM_RAM_CTRL_RMON BIT(6)
> +#define BM_RAM_CTRL_BAS BIT(15)
> +
> +#define BM_RMON_GCTRL 0x0188
> +#define BM_RMON_GCTRL_METER_RES BIT(1)
> +#define BM_RMON_GCTRL_ALLITF_RES BIT(2)
> +#define BM_RMON_GCTRL_INT_RES BIT(3)
> +#define BM_RMON_GCTRL_ITFID GENMASK(11, 4)
> +#define BM_RMON_GCTRL_PMAC_RES BIT(12)
> +#define BM_RMON_GCTRL_MRMON BIT(14)
> +#define BM_RMON_GCTRL_INTMON BIT(15)
> +
> +#define BM_PCFG_OFFSET 8
> +#define BM_PCFG(x) (0x0200 + BM_PCFG_OFFSET * (x))
> +#define BM_PCFG_CNTEN BIT(0)
> +
> +#define BM_RMON_CTRL_OFFSET 8
> +#define BM_RMON_CTRL(x) (0x0204 + BM_RMON_CTRL_OFFSET * (x))
> +#define BM_RMON_CTRL_RAM1_RES BIT(0)
> +#define BM_RMON_CTRL_RAM2_RES BIT(1)
> +
> +#define BM_PWRED_RTH_0_OFFSET 24
> +#define BM_PWRED_RTH_0(x) (0x0280 + BM_PWRED_RTH_0_OFFSET * (x))
> +#define BM_PWRED_RTH_0_MINTH GENMASK(9, 0)
> +
> +#define BM_PWRED_RTH_1_OFFSET 24
> +#define BM_PWRED_RTH_1(x) (0x0284 + BM_PWRED_RTH_1_OFFSET * (x))
> +#define BM_PWRED_RTH_1_MAXTH GENMASK(9, 0)
> +
> +#define BM_PWRED_YTH_0_OFFSET 24
> +#define BM_PWRED_YTH_0(x) (0x0288 + BM_PWRED_YTH_0_OFFSET * (x))
> +#define BM_PWRED_YTH_0_MINTH GENMASK(9, 0)
> +
> +#define BM_PWRED_YTH_1_OFFSET 24
> +#define BM_PWRED_YTH_1(x) (0x028c + BM_PWRED_YTH_1_OFFSET * (x))
> +#define BM_PWRED_YTH_1_MAXTH GENMASK(9, 0)
> +
> +#define BM_PWRED_GTH_0_OFFSET 24
> +#define BM_PWRED_GTH_0(x) (0x0290 + BM_PWRED_GTH_0_OFFSET * (x))
> +#define BM_PWRED_GTH_0_MINTH GENMASK(9, 0)
> +
> +#define BM_PWRED_GTH_1_OFFSET 24
> +#define BM_PWRED_GTH_1(x) (0x0294 + BM_PWRED_GTH_1_OFFSET * (x))
> +#define BM_PWRED_GTH_1_MAXTH GENMASK(9, 0)
> +
> +#define PCE_TBL_VAL_30 0x1014
> +#define PCE_TBL_VAL_29 0x1018
> +#define PCE_TBL_VAL_28 0x101c
> +#define PCE_TBL_VAL_27 0x1020
> +#define PCE_TBL_VAL_26 0x1024
> +
> +#define PCE_TBL_KEY_33 0x1038
> +#define PCE_TBL_KEY_32 0x103c
> +#define PCE_TBL_KEY_31 0x1040
> +#define PCE_TBL_KEY_30 0x1044
> +#define PCE_TBL_KEY_29 0x1048
> +#define PCE_TBL_KEY_28 0x104c
> +#define PCE_TBL_KEY_27 0x1050
> +#define PCE_TBL_KEY_26 0x1054
> +#define PCE_TBL_KEY_25 0x1058
> +#define PCE_TBL_KEY_24 0x105c
> +#define PCE_TBL_KEY_23 0x1060
> +#define PCE_TBL_KEY_22 0x1064
> +#define PCE_TBL_KEY_21 0x1068
> +#define PCE_TBL_KEY_20 0x106c
> +#define PCE_TBL_KEY_19 0x1070
> +#define PCE_TBL_KEY_18 0x1074
> +#define PCE_TBL_KEY_17 0x1078
> +#define PCE_TBL_KEY_16 0x107c
> +
> +#define PCE_TBL_VAL_25 0x1080
> +#define PCE_TBL_VAL_24 0x1084
> +#define PCE_TBL_VAL_23 0x1088
> +#define PCE_TBL_VAL_22 0x108c
> +#define PCE_TBL_VAL_21 0x1090
> +#define PCE_TBL_VAL_20 0x1094
> +#define PCE_TBL_VAL_19 0x1098
> +#define PCE_TBL_VAL_18 0x109c
> +#define PCE_TBL_VAL_17 0x10a0
> +#define PCE_TBL_VAL_16 0x10a4
> +
> +#define PCE_TBL_MASK_3 0x10a8
> +#define PCE_TBL_MASK_2 0x10ac
> +#define PCE_TBL_MASK_1 0x10b0
> +
> +#define PCE_TBL_VAL_15 0x10b4
> +#define PCE_TBL_VAL_14 0x10b8
> +#define PCE_TBL_VAL_13 0x10bc
> +#define PCE_TBL_VAL_12 0x10c0
> +#define PCE_TBL_VAL_11 0x10c4
> +#define PCE_TBL_VAL_10 0x10c8
> +#define PCE_TBL_VAL_9 0x10cc
> +#define PCE_TBL_VAL_8 0x10d0
> +#define PCE_TBL_VAL_7 0x10d4
> +#define PCE_TBL_VAL_6 0x10d8
> +#define PCE_TBL_VAL_5 0x10dc
> +
> +#define PCE_TBL_KEY_15 0x01e0
> +#define PCE_TBL_KEY_14 0x10e4
> +#define PCE_TBL_KEY_13 0x10e8
> +#define PCE_TBL_KEY_12 0x10ec
> +#define PCE_TBL_KEY_11 0x10f0
> +#define PCE_TBL_KEY_10 0x10f4
> +#define PCE_TBL_KEY_9 0x10f8
> +#define PCE_TBL_KEY_8 0x10fc
> +#define PCE_TBL_KEY_7 0x1100
> +#define PCE_TBL_KEY_6 0x1104
> +#define PCE_TBL_KEY_5 0x1108
> +#define PCE_TBL_KEY_4 0x110c
> +#define PCE_TBL_KEY_3 0x1110
> +#define PCE_TBL_KEY_2 0x1114
> +#define PCE_TBL_KEY_1 0x1118
> +#define PCE_TBL_KEY_0 0x111c
> +
> +#define PCE_TBL_MASK_0 0x1120
> +
> +#define PCE_TBL_VAL_4 0x1124
> +#define PCE_TBL_VAL_3 0x1128
> +#define PCE_TBL_VAL_2 0x112c
> +#define PCE_TBL_VAL_1 0x1130
> +#define PCE_TBL_VAL_0 0x1134
> +
> +#define PCE_TBL_ADDR 0x1138
> +#define PCE_TBL_ADDR_ADDR GENMASK(11, 0)
> +
> +#define PCE_TBL_CTRL 0x113c
> +#define PCE_TBL_CTRL_ADDR GENMASK(4, 0)
> +#define PCE_TBL_CTRL_OPMOD GENMASK(6, 5)
> +#define PCE_TBL_CTRL_GMAP GENMASK(10, 7)
> +#define PCE_TBL_CTRL_KEYFORM BIT(11)
> +#define PCE_TBL_CTRL_VLD BIT(12)
> +#define PCE_TBL_CTRL_TYPE BIT(13)
> +#define PCE_TBL_CTRL_EXTOP BIT(14)
> +#define PCE_TBL_CTRL_BAS BIT(15)
> +
> +#define PCE_PCTRL_OFFSET 40
> +#define PCE_PCTRL_0(x) (0x1200 + PCE_PCTRL_OFFSET * (x))
> +#define PCE_PCTRL_0_PSTATE GENMASK(2, 0)
> +#define PCE_PCTRL_0_AGEDIS BIT(3)
> +#define PCE_PCTRL_0_PLOCK BIT(4)
> +#define PCE_PCTRL_0_TVM BIT(5)
> +#define PCE_PCTRL_0_VREP BIT(6)
> +#define PCE_PCTRL_0_CMOD BIT(7)
> +#define PCE_PCTRL_0_DPEN BIT(8)
> +#define PCE_PCTRL_0_CLPEN BIT(9)
> +#define PCE_PCTRL_0_PCPEN BIT(10)
> +#define PCE_PCTRL_0_IGSTEN BIT(11)
> +#define PCE_PCTRL_0_EGSTEN BIT(12)
> +#define PCE_PCTRL_0_MCST BIT(13)
> +#define PCE_PCTRL_0_SPFDIS BIT(14)
> +#define PCE_PCTRL_0_MSTP BIT(15)
> +
> +#define FDMA_PASR 0x291c
> +#define FDMA_PASR_CPU GENMASK(1, 0)
> +#define FDMA_PASR_MPE1 GENMASK(3, 2)
> +#define FDMA_PASR_MPE2 GENMASK(5, 4)
> +#define FDMA_PASR_MPE3 GENMASK(7, 6)
> +
> +#define FDMA_PCTRL_OFFSET 24
> +#define FDMA_PCTRL(x) (0x2a00 + FDMA_PCTRL_OFFSET * (x))
> +#define FDMA_PCTRL_EN BIT(0)
> +#define FDMA_PCTRL_STEN BIT(1)
> +#define FDMA_PCTRL_DSCPRM BIT(2)
> +#define FDMA_PCTRL_VLANMOD BIT(3)
> +#define FDMA_PCTRL_TS_PTP BIT(4)
> +#define FDMA_PCTRL_TS_NONPTP BIT(5)
> +#define FDMA_PCTRL_HEADER_SHORT BIT(6)
> +#define FDMA_PCTRL_VLANTPID BIT(7)
> +
> +#define SDMA_PCTRL_OFFSET 24
> +#define SDMA_PCTRL(x) (0x2f00 + SDMA_PCTRL_OFFSET * (x))
> +#define SDMA_PCTRL_PEN BIT(0)
> +#define SDMA_PCTRL_FCEN BIT(1)
> +#define SDMA_PCTRL_MFCEN BIT(2)
> +#define SDMA_PCTRL_PAUFWD BIT(3)
> +#define SDMA_PCTRL_FCSFWD BIT(4)
> +#define SDMA_PCTRL_FCSIGN BIT(5)
> +#define SDMA_PCTRL_USFWD BIT(6)
> +#define SDMA_PCTRL_OSFWD BIT(7)
> +#define SDMA_PCTRL_LENFWD BIT(8)
> +#define SDMA_PCTRL_ALGFWD BIT(9)
> +#define SDMA_PCTRL_PHYEFWD BIT(10)
> +#define SDMA_PCTRL_PTHR GENMASK(12, 11)
> +#define SDMA_PCTRL_DTHR GENMASK(14, 13)
> +
> +#define SDMA_PRIO_OFFSET 24
> +#define SDMA_PRIO(x) (0x2f04 + SDMA_PRIO_OFFSET * (x))
> +#define SDMA_PRIO_BIT10 GENMASK(1, 0)
> +#define SDMA_PRIO_USIGN BIT(2)
> +#define SDMA_PRIO_OSIGN BIT(3)
> +#define SDMA_PRIO_LENIGN BIT(4)
> +#define SDMA_PRIO_ALGIGN BIT(5)
> +#define SDMA_PRIO_PHYEIGN BIT(6)
> +#define SDMA_PRIO_MIN_IFG GENMASK(11, 7)
> +
> +#define SDMA_BYPASS_OFFSET 24
> +#define SDMA_BYPASS(x) (0x2f10 + SDMA_BYPASS_OFFSET * (x))
> +#define SDMA_BYPASS_MD BIT(0)
> +#define SDMA_BYPASS_NMQID GENMASK(5, 1)
> +#define SDMA_BYPASS_EXTQID GENMASK(10, 6)
> +#define SDMA_BYPASS_PCEBYP BIT(11)
> +#define SDMA_BYPASS_IGMIR BIT(12)
> +#define SDMA_BYPASS_EGMIR BIT(13)
> +
> +#define PMAC_CTRL_0 0x340c
> +#define PMAC_CTRL_0_CHKVER BIT(5)
> +#define PMAC_CTRL_0_CHKREG BIT(6)
> +#define PMAC_CTRL_0_FCS BIT(7)
> +#define PMAC_CTRL_0_PADEN BIT(8)
> +#define PMAC_CTRL_0_VPADEN BIT(9)
> +#define PMAC_CTRL_0_VPAD2EN BIT(10)
> +#define PMAC_CTRL_0_APADEN BIT(11)
> +#define PMAC_CTRL_0_FCSEN BIT(12)
> +
> +#define PMAC_CTRL_1 0x3410
> +#define PMAC_CTRL_1_MLEN GENMASK(13, 0)
> +
> +#define PMAC_CTRL_2 0x3414
> +#define PMAC_CTRL_2_LCHKS GENMASK(1, 0)
> +#define PMAC_CTRL_2_LCHKL BIT(2)
> +#define PMAC_CTRL_2_MLEN BIT(3)
> +
> +#define PMAC_CTRL_4 0x341c
> +#define PMAC_CTRL_4_FLAGEN GENMASK(1, 0)
> +#define PMAC_RX_FSM_IDLE 0x00
> +#define PMAC_RX_FSM_IGCFG 0x01
> +#define PMAC_RX_FSM_DASA 0x10
> +
> +#define PMAC_CTRL_NUM 4
> +
> +#define PMAC_REG_OFFSET_1 0x200
> +#define PMAC_REG_OFFSET_2 0x600
> +
> +#define PMAC_BSL_LEN0 0x3440
> +#define PMAC_BSL_LEN0_LEN0 GENMASK(15, 0)
> +
> +#define PMAC_BSL_LEN1 0x3444
> +#define PMAC_BSL_LEN1_LEN1 GENMASK(15, 0)
> +
> +#define PMAC_BSL_LEN2 0x3448
> +#define PMAC_BSL_LEN2_LEN2 GENMASK(15, 0)
> +
> +#define PMAC_BSL_NUM 3
> +
> +#define PMAC_TBL_VAL_OFFSET 0x200
> +#define PMAC_TBL_VAL(_x) \
> + ({ typeof(_x) (x) = (_x); \
> + (0x3510 + PMAC_TBL_VAL_OFFSET * (x) * (x)); })
> +#define PMAC_TBL_VAL_0_VAL0 GENMASK(15, 0)
> +
> +#define PMAC_TBL_VAL_SFT 4
> +
> +#define PMAC_TBL_ADDR_OFFSET 0x200
> +#define PMAC_TBL_ADDR(_x) \
> + ({ typeof(_x) (x) = (_x); \
> + (0x3514 + PMAC_TBL_ADDR_OFFSET * (x) * (x)); })
> +#define PMAC_TBL_ADDR_ADDR GENMASK(11, 0)
> +
> +#define PMAC_TBL_CTRL_OFFSET 0x200
> +#define PMAC_TBL_CTRL(_x) \
> + ({ typeof(_x) (x) = (_x); \
> + (0x3518 + PMAC_TBL_CTRL_OFFSET * (x) * (x)); })
> +#define PMAC_TBL_CTRL_ADDR GENMASK(2, 0)
> +#define PMAC_TBL_CTRL_OPMOD BIT(5)
> +#define PMAC_TBL_CTRL_BAS BIT(15)
> +
> +#define ETHSW_CTP_STARTID_OFFSET 8
> +#define ETHSW_CTP_STARTID(x) \
> + (0x3a00 + ETHSW_CTP_STARTID_OFFSET * (x))
> +#define ETHSW_CTP_STARTID_STARTID GENMASK(8, 0)
> +#define ETHSW_CTP_STARTID_MD GENMASK(15, 14)
> +#define MD_WLAN8 0
> +#define MD_WLAN9 1
> +#define MD_OTHER 2
> +
> +#define ETHSW_CTP_ENDID_0 0x3a04
> +#define ETHSW_CTP_ENDID(x) \
> + (ETHSW_CTP_ENDID_0 + ETHSW_CTP_STARTID_OFFSET * (x))
> +#define ETHSW_CTP_ENDID_ENDID GENMASK(8, 0)
> +
> +#define ETHSW_GPID_STARTID_OFFSET 8
> +#define ETHSW_GPID_STARTID(x) \
> + (0x3a80 + ETHSW_GPID_STARTID_OFFSET * (x))
> +#define ETHSW_GPID_STARTID_BITS GENMASK(14, 12)
> +#define ETHSW_GPID_STARTID_STARTID GENMASK(7, 0)
> +
> +#define ETHSW_GPID_ENDID_OFFSET 8
> +#define ETHSW_GPID_ENDID(x) \
> + (0x3a84 + ETHSW_GPID_ENDID_OFFSET * (x))
> +#define ETHSW_GPID_ENDID_ENDID GENMASK(8, 0)
> +
> +#define GPID_RAM_VAL 0x3b00
> +#define GPID_RAM_VAL_OV BIT(15)
> +#define GPID_RAM_VAL_SUBID_GRP GENMASK(11, 4)
> +#define GPID_RAM_VAL_LPID GENMASK(3, 0)
> +
> +#define GPID_RAM_CTRL 0x3b04
> +#define GPID_RAM_CTRL_BAS BIT(15)
> +#define GPID_RAM_CTRL_OPMOD BIT(8)
> +#define GPID_RAM_CTRL_ADDR GENMASK(7, 0)
> +
> +/** GSWIP-O Top Register Description **/
> +#define GSWIP_CFG 0x0000
> +#define GSWIP_CFG_SS_HWRES_ON BIT(1)
> +#define GSWIP_CFG_CLK_MD GENMASK(3, 2)
> +#define GSWIP_CFG_CLK_MUX_SEL GENMASK(12, 11)
> +#define GSWIP_CFG_CORE_SE_EN BIT(15)
> +
> +#define MACSEC_EN 0x0008
> +#define GSWIPSS_IER0 0x0010
> +
> +#define GSWIPSS_ISR0 0x0014
> +#define GSWIPSS_I_XGMAC2 BIT(2)
> +#define GSWIPSS_I_XGMAC3 BIT(3)
> +#define GSWIPSS_I_XGMAC4 BIT(4)
> +#define GSWIPSS_I_XGMAC5 BIT(5)
> +#define GSWIPSS_I_XGMAC6 BIT(6)
> +#define GSWIPSS_I_XGMAC7 BIT(7)
> +#define GSWIPSS_I_XGMAC8 BIT(8)
> +#define GSWIPSS_I_XGMAC9 BIT(9)
> +#define GSWIPSS_I_XGMAC10 BIT(10)
> +
> +#define GSWIPSS_IER1 0x0018
> +#define GSWIPSS_ISR1 0x001c
> +#define GSWIPSS_SPTAG_ETYPE 0x0038
> +#define GSWIPSS_1588_CFG0 0x0050
> +#define GSWIPSS_1588_CFG1 0x0054
> +#define GSWIPSS_NCO1_LSB 0x0060
> +#define GSWIPSS_NCO1_USB 0x0064
> +#define GSWIPSS_NCO2_LSB 0x0068
> +#define GSWIPSS_NC02_MSB 0x006c
> +#define GSWIPSS_NCO3_LSB 0x0070
> +#define GSWIPSS_NCO3_MSB 0x0074
> +#define GSWIPSS_NC04_LSB 0x0078
> +#define GSWIPSS_NC04_MSB 0x007c
> +#define GSWIP_MEMLS0 0x0080
> +#define GSWIP_MEMLS1 0x0084
> +
> +/* GSWIP-O Top: MAC Registers */
> +#define MAC_IF_CFG 0X1200
> +#define MAC_IF_CFG_CFG2G5 BIT(0)
> +#define MAC_IF_CFG_CFG1G BIT(1)
> +#define MAC_IF_CFG_CFGFE BIT(2)
> +#define MAC_IF_CFG_PTP_DIS BIT(11)
> +#define MAC_IF_CFG_MAC_EN BIT(12)
> +#define MAC_IF_CFG_XGMAC_RES BIT(13)
> +#define MAC_IF_CFG_LMAC_RES BIT(14)
> +#define MAC_IF_CFG_ADAP_RES BIT(15)
> +
> +#define MAC_OP_CFG 0X1204
> +#define MAC_OP_CFG_RX_SPTAG GENMASK(1, 0)
> +#define MAC_OP_CFG_RX_TIME GENMASK(3, 2)
> +#define MAC_OP_CFG_RX_FCS GENMASK(5, 4)
> +#define MAC_OP_CFG_RX_FCS_M0 0x00
> +#define MAC_OP_CFG_RX_FCS_M1 0x01
> +#define MAC_OP_CFG_RX_FCS_M2 0X02
> +#define MAC_OP_CFG_RX_FCS_M3 0x03
> +
> +#define MAC_MTU_CFG 0X1208
> +#define MAC_MTU_CFG_MTU GENMASK(13, 0)
> +
> +#define PHY_MODE 0x1270
> +#define PHY_MODE_FCONRX GENMASK(6, 5)
> +#define PHY_MODE_FCONTX GENMASK(8, 7)
> +#define PHY_MODE_FCON_AUTO 0x00
> +#define PHY_MODE_FCON_EN 0x01
> +#define PHY_MODE_FCON_DIS 0x11
> +#define PHY_MODE_FDUP GENMASK(10, 9)
> +#define PHY_MODE_FDUP_AUTO 0x00
> +#define PHY_MODE_FDUP_FD 0x01
> +#define PHY_MODE_FDUP_HD 0x11
> +#define PHY_MODE_SPEED_LSB GENMASK(12, 11)
> +#define PHY_MODE_LINKST GENMASK(14, 13)
> +#define PHY_MODE_LINKST_AUTO 0x00
> +#define PHY_MODE_LINKST_UP 0x01
> +#define PHY_MODE_LINKST_DOWN 0x10
> +#define PHY_MODE_SPEED_MSB BIT(15)
> +#define PHY_MODE_SPEED_10M 0x000
> +#define PHY_MODE_SPEED_100M 0x001
> +#define PHY_MODE_SPEED_1G 0x010
> +#define PHY_MODE_SPEED_10G 0x011
> +#define PHY_MODE_SPEED_2G5 0x100
> +#define PHY_MODE_SPEED_5G 0x101
> +#define PHY_MODE_SPEED_FLEX 0x110
> +#define PHY_MODE_SPEED_AUTO 0x111
> +
> +#define ANEG_EEE 0x1278
> +#define ANEG_EEE_CAP GENMASK(1, 0)
> +#define ANEG_EEE_CAP_AUTO 0x00
> +#define ANEG_EEE_CAP_ON 0x01
> +#define ANEG_EEE_CAP_OFF 0x11
> +#define ANEG_EEE_CLK_STOP_CAP GENMASK(3, 2)
> +
> +#define MAC_Q_INC 0x100
> +#define MAC_IF_CFG_REG(x) (MAC_IF_CFG + ((x) - MAC2) * MAC_Q_INC)
> +#define MAC_OP_CFG_REG(x) (MAC_OP_CFG + ((x) - MAC2) * MAC_Q_INC)
> +#define MAC_MTU_CFG_REG(x) \
> + (MAC_MTU_CFG + ((x) - MAC2) * MAC_Q_INC)
> +#define PHY_MODE_REG(x) (PHY_MODE + ((x) - MAC2) * MAC_Q_INC)
> +#define ANEG_EEE_REG(x) (ANEG_EEE + ((x) - MAC2) * MAC_Q_INC)
> +
> +/* GSWIP-O TOP: XGMAC indirect access */
> +#define XGMAC_CTRL 0x1280
> +#define XGMAC_REGACC_DATA0 0x1290
> +#define XGMAC_REGACC_DATA1 0x1294
> +
> +#define XGMAC_REGACC_CTRL 0x1298
> +#define XGMAC_REGACC_CTRL_ADDR GENMASK(13, 0)
> +#define XGMAC_REGACC_CTRL_OPMOD_WR BIT(14)
> +#define XGMAC_REGACC_CTRL_ADDR_BAS BIT(15)
> +
> +/** Legacy MAC Register Description **/
> +
> +/* Legacy MAC: Common Registers */
> +#define MAC_TEST 0x0300
> +#define MAC_PFAD_CFG 0x0304
> +#define MAC_PFSA_0 0x0308
> +#define MAC_PFSA_1 0x030c
> +#define MAC_PFSA_2 0x0310
> +#define LMAC_IER 0x0320
> +#define LMAC_ISR 0x0324
> +#define LMAC_I_MAC2 BIT(0)
> +
> +#define LMAC_CNT_LSB 0x0328
> +#define LMAC_CNT_MSB 0x032c
> +#define LMAC_CNT_ACC 0x0330
> +
> +/* Legacy MAC: Single MAC Registers */
> +#define MAC_CTRL0 0x040c
> +#define MAC_CTRL0_GMII GENMASK(1, 0)
> +#define MAC_CTRL0_FDUP GENMASK(3, 2)
> +#define MAC_CTRL0_FCON GENMASK(5, 4)
> +#define MAC_CTRL0_FCS BIT(7)
> +#define MAC_CTRL0_PADEN BIT(8)
> +#define MAC_CTRL0_VPADEN BIT(9)
> +#define MAC_CTRL0_VPAD2EN BIT(10)
> +#define MAC_CTRL0_APADEN BIT(11)
> +
> +#define LMAC_Q_INC 0x30
> +#define MAC_CTRL0_REG(x) (MAC_CTRL0 + ((x) - MAC2) * LMAC_Q_INC)
> +
> +#endif /* _GSWIP_REG_H_ */
> diff --git a/drivers/staging/intel-gwdpa/gswip/gswip_tbl.c b/drivers/staging/intel-gwdpa/gswip/gswip_tbl.c
> new file mode 100644
> index 000000000000..d665b50c11e2
> --- /dev/null
> +++ b/drivers/staging/intel-gwdpa/gswip/gswip_tbl.c
> @@ -0,0 +1,345 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2016-2019 Intel Corporation.*/
> +#include <linux/kernel.h>
> +
> +#include "gswip_core.h"
> +#include "gswip_reg.h"
> +#include "gswip_tbl.h"
> +
> +enum tbl_opmode {
> + TBL_RD,
> + TBL_WR,
> +};
> +
> +enum tbl_busy_indication {
> + TBL_READY,
> + TBL_BUSY,
> +};
> +
> +enum pce_tbl_opmode {
> + /* Address-based read access */
> + PCE_OPMODE_ADRD,
> + /* Address-based write access */
> + PCE_OPMODE_ADWR,
> + /* Key-based read access */
> + PCE_OPMODE_KSRD,
> + /* Key-based write access */
> + PCE_OPMODE_KSWR
> +};
> +
> +struct pce_tbl_config {
> + u16 num_key;
> + u16 num_mask;
> + u16 num_val;
> +};
> +
> +struct pce_tbl_reg_map {
> + const u16 *key;
> + const u16 *mask;
> + const u16 *value;
> +};
> +
> +static const u16 pce_tbl_key[] = {
> + PCE_TBL_KEY_0, PCE_TBL_KEY_1, PCE_TBL_KEY_2, PCE_TBL_KEY_3,
> + PCE_TBL_KEY_4, PCE_TBL_KEY_5, PCE_TBL_KEY_6, PCE_TBL_KEY_7,
> + PCE_TBL_KEY_8, PCE_TBL_KEY_9, PCE_TBL_KEY_10, PCE_TBL_KEY_11,
> + PCE_TBL_KEY_12, PCE_TBL_KEY_13, PCE_TBL_KEY_14, PCE_TBL_KEY_15,
> + PCE_TBL_KEY_16, PCE_TBL_KEY_17, PCE_TBL_KEY_18, PCE_TBL_KEY_19,
> + PCE_TBL_KEY_20, PCE_TBL_KEY_21, PCE_TBL_KEY_22, PCE_TBL_KEY_23,
> + PCE_TBL_KEY_24, PCE_TBL_KEY_25, PCE_TBL_KEY_26, PCE_TBL_KEY_27,
> + PCE_TBL_KEY_28, PCE_TBL_KEY_29, PCE_TBL_KEY_30, PCE_TBL_KEY_31,
> + PCE_TBL_KEY_32, PCE_TBL_KEY_33,
> +};
> +
> +static const u16 pce_tbl_mask[] = {
> + PCE_TBL_MASK_0, PCE_TBL_MASK_1, PCE_TBL_MASK_2, PCE_TBL_MASK_3,
> +};
> +
> +static const u16 pce_tbl_value[] = {
> + PCE_TBL_VAL_0, PCE_TBL_VAL_1, PCE_TBL_VAL_2, PCE_TBL_VAL_3,
> + PCE_TBL_VAL_4, PCE_TBL_VAL_5, PCE_TBL_VAL_6, PCE_TBL_VAL_7,
> + PCE_TBL_VAL_8, PCE_TBL_VAL_9, PCE_TBL_VAL_10, PCE_TBL_VAL_11,
> + PCE_TBL_VAL_12, PCE_TBL_VAL_13, PCE_TBL_VAL_14, PCE_TBL_VAL_15,
> + PCE_TBL_VAL_16, PCE_TBL_VAL_17, PCE_TBL_VAL_18, PCE_TBL_VAL_19,
> + PCE_TBL_VAL_20, PCE_TBL_VAL_21, PCE_TBL_VAL_22, PCE_TBL_VAL_23,
> + PCE_TBL_VAL_24, PCE_TBL_VAL_25, PCE_TBL_VAL_26, PCE_TBL_VAL_27,
> + PCE_TBL_VAL_28, PCE_TBL_VAL_29, PCE_TBL_VAL_30,
> +};
> +
> +/* PCE table default entries for Key, Mask and Value.
> + * Only minimum entries settings are required by default.
> + */
> +static const struct pce_tbl_config pce_tbl_def_cfg[] = {
> + /* Parser ucode table */
> + { 0, 0, 4 },
> + /* Dummy */
> + { 0, 0, 0 },
> + /* VLAN filter table */
> + { 1, 0, 1 },
> + /* PPPoE table */
> + { 1, 0, 0 },
> + /* Protocol table */
> + { 1, 1, 0 },
> + /* Application table */
> + { 1, 1, 0 },
> + /* IP DA/SA MSB table */
> + { 4, 4, 0 },
> + /* IP DA/SA LSB table */
> + { 4, 4, 0 },
> + /* Packet length table */
> + { 1, 1, 0 },
> + /* Inner PCP/DEI table */
> + { 0, 0, 1 },
> + /* DSCP table */
> + { 0, 0, 1 },
> + /* MAC bridging table */
> + { 4, 0, 10},
> + /* DSCP2PCP configuration table */
> + { 0, 0, 2 },
> + /* Multicast SW table */
> + { 19, 0, 10},
> + /* Dummy */
> + { 0, 0, 0 },
> + /* Traffic Flow table */
> + { 34, 0, 31},
> + /* PBB tunnel template configuration table */
> + { 0, 0, 11},
> + /* Queue mapping table */
> + { 0, 0, 1 },
> + /* Ingress CTP port configuration table */
> + { 0, 0, 9 },
> + /* Egress CTP port configuration table */
> + { 0, 0, 7 },
> + /* Ingress bridge port configuration table */
> + { 0, 0, 18},
> + /* Egress bridge port configuration table */
> + { 0, 0, 14},
> + /* MAC DA table */
> + { 3, 1, 0 },
> + /* MAC SA table */
> + { 3, 1, 0 },
> + /* Flags table */
> + { 1, 1, 0 },
> + /* Bridge configuration table */
> + { 0, 0, 10},
> + /* Outer PCP/DEI table */
> + { 0, 0, 1 },
> + /* Color marking table */
> + { 0, 0, 1 },
> + /* Color remarking table */
> + { 0, 0, 1 },
> + /* Payload table */
> + { 1, 1, 0 },
> + /* Extended VLAN operation table */
> + { 4, 0, 6 },
> + /* P-mapping configuration table */
> + { 0, 0, 1 },
> +};
> +
> +static const struct pce_tbl_config *pce_tbl_cfg;
> +static struct pce_tbl_reg_map pce_tbl_reg;
> +
> +int gswip_pce_table_init(void)
> +{
> + pce_tbl_reg.key = pce_tbl_key;
> + pce_tbl_reg.mask = pce_tbl_mask;
> + pce_tbl_reg.value = pce_tbl_value;
> + pce_tbl_cfg = pce_tbl_def_cfg;
These globals are ugly. It would be slightly better to pass them
as a parameter. Or maybe just set this up directly in probe() instead
of hidden in a function like this.
> +
> + return 0;
> +}
> +
> +int gswip_pce_table_write(struct gswip_core_priv *priv,
> + struct pce_tbl_prog *pce_tbl)
> +{
> + struct regmap *regmap = priv->regmap;
> + u16 i, ctrl;
> +
> + spin_lock(&priv->tbl_lock);
> +
> + /* update key registers */
> + for (i = 0; i < pce_tbl_cfg[pce_tbl->id].num_key; i++)
> + regmap_write(regmap, pce_tbl_reg.key[i], pce_tbl->key[i]);
> +
> + /* update mask registers */
> + for (i = 0; i < pce_tbl_cfg[pce_tbl->id].num_mask; i++)
> + regmap_write(regmap, pce_tbl_reg.mask[i], pce_tbl->mask[i]);
> +
> + /* update value registers */
> + for (i = 0; i < pce_tbl_cfg[pce_tbl->id].num_val; i++)
> + regmap_write(regmap, pce_tbl_reg.value[i], pce_tbl->val[i]);
> +
> + ctrl = FIELD_PREP(PCE_TBL_CTRL_ADDR, pce_tbl->id) |
> + FIELD_PREP(PCE_TBL_CTRL_OPMOD, PCE_OPMODE_ADWR) |
> + FIELD_PREP(PCE_TBL_CTRL_BAS, TBL_BUSY);
> +
> + /* update the pce table */
> + regmap_write(regmap, PCE_TBL_ADDR, pce_tbl->addr);
> + regmap_write(regmap, PCE_TBL_CTRL, ctrl);
> +
> + if (tbl_rw_tmout(priv, PCE_TBL_CTRL, PCE_TBL_CTRL_BAS)) {
> + dev_err(priv->dev, "failed to write pce table\n");
> + spin_unlock(&priv->tbl_lock);
> + return -EBUSY;
> + }
> +
> + spin_unlock(&priv->tbl_lock);
> +
> + return 0;
> +}
> +
> +int gswip_pce_table_read(struct gswip_core_priv *priv,
> + struct pce_tbl_prog *pce_tbl)
> +{
> + u16 i, ctrl;
> +
> + spin_lock(&priv->tbl_lock);
> +
> + regmap_write(priv->regmap, PCE_TBL_ADDR, pce_tbl->addr);
> +
> + ctrl = FIELD_PREP(PCE_TBL_CTRL_ADDR, pce_tbl->id) |
> + FIELD_PREP(PCE_TBL_CTRL_OPMOD, PCE_OPMODE_ADRD) |
> + FIELD_PREP(PCE_TBL_CTRL_BAS, TBL_BUSY);
> + regmap_write(priv->regmap, PCE_TBL_CTRL, ctrl);
> +
> + if (tbl_rw_tmout(priv, PCE_TBL_CTRL, PCE_TBL_CTRL_BAS)) {
> + dev_err(priv->dev, "failed to read pce table\n");
> + spin_unlock(&priv->tbl_lock);
> + return -EBUSY;
> + }
> +
> + for (i = 0; i < pce_tbl_cfg[pce_tbl->id].num_key; i++)
> + reg_r16(priv, pce_tbl_reg.key[i], &pce_tbl->key[i]);
> +
> + for (i = 0; i < pce_tbl_cfg[pce_tbl->id].num_mask; i++)
> + reg_r16(priv, pce_tbl_reg.mask[i], &pce_tbl->mask[i]);
> +
> + for (i = 0; i < pce_tbl_cfg[pce_tbl->id].num_val; i++)
> + reg_r16(priv, pce_tbl_reg.value[i], &pce_tbl->val[i]);
> +
> + spin_unlock(&priv->tbl_lock);
> +
> + return 0;
> +}
> +
> +int gswip_bm_table_write(struct gswip_core_priv *priv,
> + struct bm_tbl_prog *bm_tbl)
> +{
> + struct regmap *regmap = priv->regmap;
> + u16 ctrl;
> + int i;
> +
> + spin_lock(&priv->tbl_lock);
> +
> + for (i = 0; i < bm_tbl->num_val; i++)
> + regmap_write(regmap, (BM_RAM_VAL_0 - i * BM_RAM_VAL_OFFSET),
> + bm_tbl->val[i]);
> +
> + regmap_write(regmap, BM_RAM_ADDR, bm_tbl->addr);
> +
> + ctrl = bm_tbl->id;
> + ctrl |= FIELD_PREP(BM_RAM_CTRL_OPMOD, TBL_WR);
> + ctrl |= FIELD_PREP(BM_RAM_CTRL_BAS, TBL_BUSY);
> + regmap_write(regmap, BM_RAM_CTRL, ctrl);
> +
> + if (tbl_rw_tmout(priv, BM_RAM_CTRL, BM_RAM_CTRL_BAS)) {
> + dev_err(priv->dev, "failed to write bm table\n");
> + spin_unlock(&priv->tbl_lock);
> + return -EBUSY;
> + }
> +
> + spin_unlock(&priv->tbl_lock);
> +
> + return 0;
> +}
> +
> +int gswip_bm_table_read(struct gswip_core_priv *priv,
> + struct bm_tbl_prog *bm_tbl)
> +{
> + u16 ctrl;
> + int i;
> +
> + spin_lock(&priv->tbl_lock);
> +
> + regmap_write(priv->regmap, BM_RAM_ADDR, bm_tbl->addr);
> +
> + ctrl = FIELD_PREP(BM_RAM_CTRL_ADDR, bm_tbl->id) |
> + FIELD_PREP(BM_RAM_CTRL_OPMOD, TBL_RD) |
> + FIELD_PREP(BM_RAM_CTRL_BAS, TBL_BUSY);
> + regmap_write(priv->regmap, BM_RAM_CTRL, ctrl);
> +
> + if (tbl_rw_tmout(priv, BM_RAM_CTRL, BM_RAM_CTRL_BAS)) {
> + dev_err(priv->dev, "failed to read bm table\n");
> + spin_unlock(&priv->tbl_lock);
> + return -EBUSY;
> + }
> +
> + for (i = 0; i < bm_tbl->num_val; i++)
> + reg_r16(priv, (BM_RAM_VAL_0 - i * BM_RAM_VAL_OFFSET),
> + &bm_tbl->val[i]);
> +
> + spin_unlock(&priv->tbl_lock);
> +
> + return 0;
> +}
> +
> +int gswip_pmac_table_write(struct gswip_core_priv *priv,
> + struct pmac_tbl_prog *pmac_tbl)
> +{
> + u16 pmac_id = pmac_tbl->pmac_id, ctrl;
> + int i;
> +
> + spin_lock(&priv->tbl_lock);
> +
> + for (i = 0; i < pmac_tbl->num_val; i++)
> + regmap_write(priv->regmap,
> + (PMAC_TBL_VAL(pmac_id) - i * PMAC_TBL_VAL_SFT),
> + pmac_tbl->val[i]);
> +
> + regmap_write(priv->regmap, PMAC_TBL_ADDR(pmac_id), pmac_tbl->addr);
> +
> + ctrl = FIELD_PREP(PMAC_TBL_CTRL_ADDR, pmac_tbl->id) |
> + FIELD_PREP(PMAC_TBL_CTRL_OPMOD, TBL_WR) |
> + FIELD_PREP(PMAC_TBL_CTRL_BAS, TBL_BUSY);
> + regmap_write(priv->regmap, PMAC_TBL_CTRL(pmac_id), ctrl);
> +
> + if (tbl_rw_tmout(priv, PMAC_TBL_CTRL(pmac_id), PMAC_TBL_CTRL_BAS)) {
> + dev_err(priv->dev, "failed to write pmac table\n");
> + spin_unlock(&priv->tbl_lock);
> + return -EBUSY;
> + }
> +
> + spin_unlock(&priv->tbl_lock);
> +
> + return 0;
> +}
> +
> +int gswip_pmac_table_read(struct gswip_core_priv *priv,
> + struct pmac_tbl_prog *pmac_tbl)
> +{
> + u16 pmac_id = pmac_tbl->pmac_id, ctrl;
> + int i;
> +
> + spin_lock(&priv->tbl_lock);
> +
> + regmap_write(priv->regmap, PMAC_TBL_ADDR(pmac_id), pmac_tbl->addr);
> +
> + ctrl = FIELD_PREP(PMAC_TBL_CTRL_ADDR, pmac_tbl->id) |
> + FIELD_PREP(PMAC_TBL_CTRL_OPMOD, TBL_RD) |
> + FIELD_PREP(PMAC_TBL_CTRL_BAS, TBL_BUSY);
> + regmap_write(priv->regmap, PMAC_TBL_CTRL(pmac_id), ctrl);
> +
> + if (tbl_rw_tmout(priv, PMAC_TBL_CTRL(pmac_id), PMAC_TBL_CTRL_BAS)) {
> + dev_err(priv->dev, "failed to read pmac table\n");
> + spin_unlock(&priv->tbl_lock);
> + return -EBUSY;
> + }
> +
> + for (i = 0; i < pmac_tbl->num_val; i++)
> + reg_r16(priv, (PMAC_TBL_VAL(pmac_id) - i * PMAC_TBL_VAL_SFT),
> + &pmac_tbl->val[i]);
> +
> + spin_unlock(&priv->tbl_lock);
> +
> + return 0;
> +}
> diff --git a/drivers/staging/intel-gwdpa/gswip/gswip_tbl.h b/drivers/staging/intel-gwdpa/gswip/gswip_tbl.h
> new file mode 100644
> index 000000000000..4bd92951e7ae
> --- /dev/null
> +++ b/drivers/staging/intel-gwdpa/gswip/gswip_tbl.h
> @@ -0,0 +1,195 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright (c) 2016-2019 Intel Corporation. */
> +#ifndef _GSW_TBL_RW_H_
> +#define _GSW_TBL_RW_H_
> +
> +#define PCE_TBL_KEY_NUM 34
> +#define PCE_TBL_VAL_NUM 31
> +#define PCE_TBL_MASK_NUM 4
> +#define PCE_MAC_LIMIT_NUM 255
> +
> +/* PCE queue mapping table */
> +#define PCE_Q_MAP_LOCAL_EXTRACT BIT(8)
> +#define PCE_Q_MAP_IG_PORT_MODE BIT(9)
> +#define PCE_Q_MAP_EG_PID GENMASK(7, 4)
> +
> +/* PCE ingress CTP port configuration table */
> +#define PCE_IGCTP_VAL4_BYPASS_BR BIT(15)
> +
> +/* PCE ingress bridge port configuration table */
> +#define PCE_IGBGP_VAL10_PORT_MAP_0 10
> +#define PCE_IGBGP_VAL4_LRN_LIMIT GENMASK(7, 0)
> +#define PCE_IGBGP_VAL4_BR_ID GENMASK(13, 8)
> +
> +/* PCE EGBGP table */
> +#define PCE_EGBGP_VAL4_DST_SUBIF_ID_GRP GENMASK(7, 0)
> +#define PCE_EGBGP_VAL4_DST_LPID GENMASK(11, 8)
> +#define PCE_EGBGP_VAL4_PMAPPER BIT(14)
> +
> +/* PCE_BRGCFG table */
> +#define PCE_BRGCFG_VAL1_BCAST_FW_MODE GENMASK(1, 0)
> +#define PCE_BRGCFG_VAL1_UCAST_FW_MODE GENMASK(3, 2)
> +#define PCE_BRGCFG_VAL1_MCAST_NIP_FW_MODE GENMASK(5, 4)
> +#define PCE_BRGCFG_VAL1_MCAST_IP_FW_MODE GENMASK(7, 6)
> +#define PCE_BRGCFG_VAL3_LRN_DISC_CNT GENMASK(31, 16)
> +
> +/* BM_PQM_THRES table */
> +#define BM_PQM_THRES_Q_NUM GENMASK(7, 3)
> +
> +/* BM_Q_MAP table */
> +#define BM_Q_MAP_VAL4_REDIR_PID GENMASK(2, 0)
> +#define BM_Q_MAP_VAL4_REDIR_PID_MSB BIT(3)
> +#define BM_Q_MAP_VAL4_REDIR_PID_BIT4 BIT(4)
> +
> +enum pce_tbl_id {
> + PCE_TFLOW = 0x0f,
> + PCE_Q_MAP = 0x11,
> + PCE_IG_CTP_CFG = 0x12,
> + PCE_EG_CTP_CFG = 0x13,
> + PCE_IG_BRP_CFG = 0x14,
> + PCE_EG_BRP_CFG = 0x15,
> + PCE_BR_CFG = 0x19,
> + PCE_PMAP = 0x1f,
> +};
> +
> +#define PCE_TBL_KEY_NUM 34
> +#define PCE_TBL_VAL_NUM 31
> +#define PCE_TBL_MASK_NUM 4
> +
> +/* PCE programming table */
> +struct pce_tbl_prog {
> + enum pce_tbl_id id;
> + u16 val[PCE_TBL_VAL_NUM];
> + u16 key[PCE_TBL_KEY_NUM];
> + u16 mask[PCE_TBL_MASK_NUM];
> + u16 addr;
> +};
> +
> +/* BM programming table */
> +enum bm_tbl_id {
> + BM_CTP_RX_RMON = 0x00,
> + BM_CTP_TX_RMON = 0x01,
> + BM_BR_RX_RMON = 0x02,
> + BM_BR_TX_RMON = 0x03,
> + BM_CTP_PCE_BYPASS_RMON = 0x04,
> + BM_TFLOW_RX_RMON = 0x05,
> + BM_TFLOW_TX_RMON = 0x06,
> + BM_WFQ_PARAM = 0x07,
> + BM_PQM_THRES = 0x09,
> + BM_Q_MAP = 0x0e,
> + BM_PMAC_CNTR = 0x1c
> +};
> +
> +#define BM_RAM_VAL_MAX 10
> +
> +struct rmon_cntr_tbl {
> + u16 ctr_offset : 6;
> + u16 port_offset : 10;
> +};
> +
> +struct qmap_tbl {
> + u16 qid : 6;
> + u16 reserved : 10;
> +};
> +
> +struct pmac_cntr_tbl {
> + u16 addr : 5;
> + u16 ctr_offset : 3;
> + u16 pmac_id : 3;
> + u16 reserved : 1;
> + u16 ctr_offset_hdr : 1;
> + u16 reserved1 : 3;
> +};
> +
> +struct bm_tbl_prog {
> + enum bm_tbl_id id;
> + union {
> + struct rmon_cntr_tbl rmon_cntr;
> + struct qmap_tbl qmap;
> + struct pmac_cntr_tbl pmac_cntr;
> + u16 addr;
> + };
> + u16 val[BM_RAM_VAL_MAX];
> + u32 num_val;
> +};
> +
> +/* PMAC programming table */
> +enum pmac_tbl_id {
> + PMAC_BP_MAP,
> + PMAC_IG_CFG,
> + PMAC_EG_CFG,
> +};
> +
> +#define PMAC_BP_MAP_TBL_VAL_NUM 3
> +#define PMAC_IG_CFG_TBL_VAL_NUM 5
> +#define PMAC_EG_CFG_TBL_VAL_NUM 3
> +#define PMAC_TBL_VAL_MAX 11
> +
> +/* PMAC_BP_MAP table */
> +/* Table Control */
> +#define PMAC_BPMAP_TX_DMA_CH GENMASK(4, 0)
> +/* PMAC_TBL_VAL_2 */
> +#define PMAC_BPMAP_TX_Q_UPPER GENMASK(31, 16)
> +
> +/* PMAC_IG_CFG table */
> +/* Table Control */
> +#define PMAC_IGCFG_TX_DMA_CH GENMASK(4, 0)
> +/* PMAC_TBL_VAL_2 */
> +#define PMAC_IGCFG_HDR_ID GENMASK(7, 4)
> +/* PMAC_TBL_VAL_4 */
> +#define PMAC_IGCFG_VAL4_PMAC_FLAG BIT(0)
> +#define PMAC_IGCFG_VAL4_SPPID_MODE BIT(1)
> +#define PMAC_IGCFG_VAL4_SUBID_MODE BIT(2)
> +#define PMAC_IGCFG_VAL4_CLASSEN_MODE BIT(3)
> +#define PMAC_IGCFG_VAL4_CLASS_MODE BIT(5)
> +#define PMAC_IGCFG_VAL4_ERR_DP BIT(7)
> +
> +/* PMAC_EG_CFG table */
> +/* Table Control */
> +#define PMAC_EGCFG_DST_PORT_ID GENMASK(3, 0)
> +#define PMAC_EGCFG_MPE1 BIT(4)
> +#define PMAC_EGCFG_MPE2 BIT(5)
> +#define PMAC_EGCFG_ECRYPT BIT(6)
> +#define PMAC_EGCFG_DECRYPT BIT(7)
> +#define PMAC_EGCFG_TC_4BITS GENMASK(7, 4)
> +#define PMAC_EGCFG_TC_2BITS GENMASK(7, 6)
> +#define PMAC_EGCFG_FLOW_ID_MSB GENMASK(9, 8)
> +/* PMAC_TBL_VAL_0 */
> +#define PMAC_EGCFG_VAL0_RES_2BITS GENMASK(1, 0)
> +#define PMAC_EGCFG_VAL0_RES_3BITS GENMASK(4, 2)
> +#define PMAC_EGCFG_VAL0_REDIR BIT(4)
> +#define PMAC_EGCFG_VAL0_BSL GENMASK(7, 5)
> +/* PMAC_TBL_VAL_1 */
> +#define PMAC_EGCFG_VAL1_RX_DMA_CH GENMASK(3, 0)
> +/* PMAC_TBL_VAL_2 */
> +#define PMAC_EGCFG_VAL2_PMAC_FLAG BIT(0)
> +#define PMAC_EGCFG_VAL2_FCS_MODE BIT(1)
> +#define PMAC_EGCFG_VAL2_L2HD_RM_MODE BIT(2)
> +#define PMAC_EGCFG_VAL2_L2HD_RM GENMASK(15, 8)
> +
> +struct pmac_tbl_prog {
> + u16 pmac_id;
> + enum pmac_tbl_id id;
> + u16 val[PMAC_TBL_VAL_MAX];
> + u8 num_val;
> + u16 addr;
> +};
> +
> +struct gswip_core_priv;
> +
> +int gswip_pce_table_init(void);
> +int gswip_pce_table_write(struct gswip_core_priv *priv,
> + struct pce_tbl_prog *pce_tbl);
> +int gswip_pce_table_read(struct gswip_core_priv *priv,
> + struct pce_tbl_prog *pce_tbl);
> +int gswip_bm_table_read(struct gswip_core_priv *priv,
> + struct bm_tbl_prog *bm_tbl);
> +int gswip_bm_table_write(struct gswip_core_priv *priv,
> + struct bm_tbl_prog *bm_tbl);
> +int gswip_pmac_table_read(struct gswip_core_priv *priv,
> + struct pmac_tbl_prog *pmac_tbl);
> +int gswip_pmac_table_write(struct gswip_core_priv *priv,
> + struct pmac_tbl_prog *pmac_tbl);
> +
> +#endif
> +
> diff --git a/drivers/staging/intel-gwdpa/gswip/lmac.c b/drivers/staging/intel-gwdpa/gswip/lmac.c
> new file mode 100644
> index 000000000000..2fef9eaeeadc
> --- /dev/null
> +++ b/drivers/staging/intel-gwdpa/gswip/lmac.c
> @@ -0,0 +1,46 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2016-2019 Intel Corporation. */
> +
> +#include <linux/bitfield.h>
> +#include <linux/types.h>
> +
> +#include "mac_common.h"
> +
> +int lmac_set_duplex_mode(struct gswip_mac *priv, u32 val)
> +{
> + u32 mac_ctrl0 = lmac_read(priv, MAC_CTRL0_REG(priv->mac_idx));
> +
> + if (FIELD_GET(MAC_CTRL0_FDUP, mac_ctrl0) != val) {
> + mac_ctrl0 &= ~MAC_CTRL0_FDUP;
> + mac_ctrl0 |= FIELD_PREP(MAC_CTRL0_FDUP, val);
> + lmac_write(priv, MAC_CTRL0_REG(priv->mac_idx), mac_ctrl0);
> + }
> +
> + return 0;
> +}
> +
> +int lmac_set_flowcon_mode(struct gswip_mac *priv, u32 val)
> +{
> + u32 mac_ctrl0 = lmac_read(priv, MAC_CTRL0_REG(priv->mac_idx));
> +
> + if (FIELD_GET(MAC_CTRL0_FCON, mac_ctrl0) != val) {
> + mac_ctrl0 &= ~MAC_CTRL0_FCON;
> + mac_ctrl0 |= FIELD_PREP(MAC_CTRL0_FCON, val);
> + lmac_write(priv, MAC_CTRL0_REG(priv->mac_idx), mac_ctrl0);
> + }
> +
> + return 0;
> +}
> +
> +int lmac_set_intf_mode(struct gswip_mac *priv, u32 val)
> +{
> + u32 mac_ctrl0 = lmac_read(priv, MAC_CTRL0_REG(priv->mac_idx));
> +
> + if (FIELD_GET(MAC_CTRL0_GMII, mac_ctrl0) != val) {
> + mac_ctrl0 &= ~MAC_CTRL0_GMII;
> + mac_ctrl0 |= FIELD_PREP(MAC_CTRL0_GMII, val);
> + lmac_write(priv, MAC_CTRL0_REG(priv->mac_idx), mac_ctrl0);
> + }
> +
> + return 0;
> +}
> diff --git a/drivers/staging/intel-gwdpa/gswip/mac_cfg.c b/drivers/staging/intel-gwdpa/gswip/mac_cfg.c
> new file mode 100644
> index 000000000000..7930f297762f
> --- /dev/null
> +++ b/drivers/staging/intel-gwdpa/gswip/mac_cfg.c
> @@ -0,0 +1,491 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2016-2019 Intel Corporation. */
> +
> +#include <linux/bitfield.h>
> +#include "mac_common.h"
> +
> +u32 mac_get_speed(struct device *dev)
> +{
> + struct gswip_mac *priv = dev_get_drvdata(dev);
> + u32 mac_speed;
> +
> + spin_lock_bh(&priv->mac_lock);
> + mac_speed = sw_get_speed(priv);
> + spin_unlock_bh(&priv->mac_lock);
> +
> + return mac_speed;
> +}
> +
> +int mac_set_physpeed(struct gswip_mac *priv, u32 phy_speed)
> +{
> + spin_lock_bh(&priv->mac_lock);
> + xgmac_set_extcfg(priv, 1);
> +
> + switch (phy_speed) {
> + default:
> + case SPEED_MAC_AUTO:
> + sw_set_speed(priv, SPEED_AUTO);
> + break;
> +
> + case SPEED_XGMAC_10G:
> + xgmac_set_xgmii_speed(priv);
> + sw_set_speed(priv, SPEED_10G);
> + break;
> +
> + case SPEED_GMII_25G:
> + sw_set_speed(priv, SPEED_2G5);
> + sw_set_2G5_intf(priv, XGMAC_GMII);
> + xgmac_set_gmii_2500_speed(priv);
> + break;
> +
> + case SPEED_XGMII_25G:
> + sw_set_speed(priv, SPEED_2G5);
> + sw_set_2G5_intf(priv, XGMAC_XGMII);
> + xgmac_set_xgmii_2500_speed(priv);
> + break;
> +
> + case SPEED_XGMAC_1G:
> + sw_set_speed(priv, SPEED_1G);
> + sw_set_1g_intf(priv, XGMAC_GMII);
> + xgmac_set_gmii_speed(priv);
> + xgmac_set_extcfg(priv, 1);
> + break;
> +
> + case SPEED_XGMAC_10M:
> + sw_set_speed(priv, SPEED_10M);
> +
> + case SPEED_XGMAC_100M:
> + if (phy_speed != SPEED_XGMAC_10M)
> + sw_set_speed(priv, SPEED_100M);
> +
> + sw_set_fe_intf(priv, XGMAC_GMII);
> + sw_set_1g_intf(priv, XGMAC_GMII);
> + xgmac_set_gmii_speed(priv);
> + break;
> +
> + case SPEED_LMAC_10M:
> + sw_set_speed(priv, SPEED_10M);
> +
> + case SPEED_LMAC_100M:
> + if (phy_speed != SPEED_LMAC_10M)
> + sw_set_speed(priv, SPEED_100M);
> +
> + sw_set_fe_intf(priv, LMAC_MII);
> + lmac_set_intf_mode(priv, 1);
> + break;
> +
> + case SPEED_LMAC_1G:
> + sw_set_speed(priv, SPEED_1G);
> + sw_set_1g_intf(priv, LMAC_GMII);
> + lmac_set_intf_mode(priv, 2);
> + break;
> + }
> + spin_unlock_bh(&priv->mac_lock);
> +
> + return 0;
> +}
> +
> +int mac_set_duplex(struct gswip_mac *priv, u32 mode)
> +{
> + u32 val;
> +
> + spin_lock_bh(&priv->mac_lock);
> + switch (mode) {
> + default:
> + case GSW_DUPLEX_AUTO:
> + val = PHY_MODE_FDUP_AUTO;
> + break;
> + case GSW_DUPLEX_HALF:
> + val = PHY_MODE_FDUP_HD;
> + break;
> + case GSW_DUPLEX_FULL:
> + val = PHY_MODE_FDUP_FD;
> + break;
> + }
> +
> + sw_set_duplex_mode(priv, val);
> + lmac_set_duplex_mode(priv, val);
> + spin_unlock_bh(&priv->mac_lock);
> +
> + return 0;
> +}
> +
> +u32 mac_get_duplex(struct device *dev)
> +{
> + struct gswip_mac *priv = dev_get_drvdata(dev);
> + u32 val;
> +
> + spin_lock_bh(&priv->mac_lock);
> + val = sw_get_duplex_mode(priv);
> + spin_unlock_bh(&priv->mac_lock);
> +
> + return val;
> +}
> +
> +u32 mac_get_linksts(struct device *dev)
> +{
> + struct gswip_mac *priv = dev_get_drvdata(dev);
> + u32 linksts;
> +
> + spin_lock_bh(&priv->mac_lock);
> + linksts = sw_get_linkstatus(priv);
> + spin_unlock_bh(&priv->mac_lock);
> +
> + return linksts;
> +}
> +
> +int mac_set_linksts(struct gswip_mac *priv, u32 mode)
> +{
> + u8 val;
> +
> + spin_lock_bh(&priv->mac_lock);
> + switch (mode) {
> + default:
> + case LINK_AUTO:
> + val = PHY_MODE_LINKST_AUTO;
> + break;
> +
> + case LINK_UP:
> + val = PHY_MODE_LINKST_UP;
> + break;
> +
> + case LINK_DOWN:
> + val = PHY_MODE_LINKST_DOWN;
> + break;
> + }
> + sw_set_linkstatus(priv, val);
> + spin_unlock_bh(&priv->mac_lock);
> +
> + return 0;
> +}
> +
> +int mac_set_flowctrl(struct device *dev, u32 val)
> +{
> + struct gswip_mac *priv = dev_get_drvdata(dev);
> +
> + if (val >= FC_INVALID)
> + return -EINVAL;
> +
> + spin_lock_bh(&priv->mac_lock);
> + lmac_set_flowcon_mode(priv, val);
> +
> + switch (val) {
> + default:
> + case FC_AUTO:
> + xgmac_tx_flow_ctl(priv, priv->pause_time, XGMAC_FC_EN);
> + xgmac_rx_flow_ctl(priv, XGMAC_FC_EN);
> + sw_set_flowctrl(priv, PHY_MODE_FCON_AUTO, FCONRX);
> + sw_set_flowctrl(priv, PHY_MODE_FCON_AUTO, FCONTX);
> + break;
> +
> + case FC_RX:
> + /* Disable TX in XGMAC and GSWSS */
> + xgmac_tx_flow_ctl(priv, priv->pause_time, XGMAC_FC_DIS);
> + sw_set_flowctrl(priv, PHY_MODE_FCON_DIS, FCONTX);
> +
> + /* Enable RX in XGMAC and GSWSS */
> + xgmac_rx_flow_ctl(priv, XGMAC_FC_EN);
> +
> + sw_set_flowctrl(priv, PHY_MODE_FCON_EN, FCONRX);
> + break;
> +
> + case FC_TX:
> + /* Disable RX in XGMAC and GSWSS */
> + xgmac_rx_flow_ctl(priv, XGMAC_FC_DIS);
> + sw_set_flowctrl(priv, PHY_MODE_FCON_DIS, FCONTX);
> +
> + /* Enable TX in XGMAC and GSWSS */
> + xgmac_tx_flow_ctl(priv, priv->pause_time, XGMAC_FC_EN);
> + sw_set_flowctrl(priv, PHY_MODE_FCON_EN, FCONTX);
> + break;
> +
> + case FC_RXTX:
> + xgmac_tx_flow_ctl(priv, priv->pause_time, XGMAC_FC_EN);
> + xgmac_rx_flow_ctl(priv, XGMAC_FC_EN);
> + sw_set_flowctrl(priv, PHY_MODE_FCON_EN, FCONRX);
> + sw_set_flowctrl(priv, PHY_MODE_FCON_EN, FCONTX);
> + break;
> +
> + case FC_DIS:
> + xgmac_tx_flow_ctl(priv, priv->pause_time, XGMAC_FC_DIS);
> + xgmac_rx_flow_ctl(priv, XGMAC_FC_DIS);
> + sw_set_flowctrl(priv, PHY_MODE_FCON_DIS, FCONRX);
> + sw_set_flowctrl(priv, PHY_MODE_FCON_EN, FCONTX);
> + break;
> + }
> + spin_unlock_bh(&priv->mac_lock);
> +
> + return 0;
> +}
> +
> +inline int get_2G5_intf(struct gswip_mac *priv)
> +{
> + u32 mac_if_cfg, macif;
> + int ret;
> +
> + mac_if_cfg = sw_read(priv, MAC_IF_CFG_REG(priv->mac_idx));
> + macif = FIELD_PREP(MAC_IF_CFG_CFG2G5, mac_if_cfg);
> +
> + if (macif == 0)
> + ret = XGMAC_GMII;
> + else if (macif == 1)
> + ret = XGMAC_XGMII;
> + else
> + ret = -EINVAL;
> +
> + return ret;
> +}
> +
> +inline int get_1g_intf(struct gswip_mac *priv)
> +{
> + u32 mac_if_cfg, macif;
> + int ret;
> +
> + mac_if_cfg = sw_read(priv, MAC_IF_CFG_REG(priv->mac_idx));
> + macif = FIELD_GET(MAC_IF_CFG_CFG1G, mac_if_cfg);
> +
> + if (macif == 0)
> + ret = LMAC_GMII;
> + else if (macif == 1)
> + ret = XGMAC_GMII;
> + else
> + ret = -EINVAL;
> +
> + return ret;
> +}
> +
> +inline int get_fe_intf(struct gswip_mac *priv)
> +{
> + u32 mac_if_cfg, macif;
> + int ret;
> +
> + mac_if_cfg = sw_read(priv, MAC_IF_CFG_REG(priv->mac_idx));
> + macif = FIELD_GET(MAC_IF_CFG_CFGFE, mac_if_cfg);
> +
> + if (macif == 0)
> + ret = LMAC_MII;
> + else if (macif == 1)
> + ret = XGMAC_GMII;
> + else
> + ret = -EINVAL;
> +
> + return ret;
> +}
> +
> +static int mac_get_mii_interface(struct device *dev)
> +{
> + struct gswip_mac *priv = dev_get_drvdata(dev);
> + int intf, ret;
> + u8 mac_speed;
> +
> + spin_lock_bh(&priv->mac_lock);
> + mac_speed = sw_get_speed(priv);
> + switch (mac_speed) {
> + case SPEED_10M:
> + case SPEED_100M:
> + intf = get_fe_intf(priv);
> + if (intf == XGMAC_GMII)
> + ret = GSW_PORT_HW_GMII;
> + else if (intf == LMAC_MII)
> + ret = GSW_PORT_HW_MII;
> + else
> + ret = -EINVAL;
> + break;
> +
> + case SPEED_1G:
> + intf = get_1g_intf(priv);
> + if (intf == LMAC_GMII || intf == XGMAC_GMII)
> + ret = GSW_PORT_HW_GMII;
> + else
> + ret = -EINVAL;
> + break;
> +
> + case SPEED_2G5:
> + intf = get_2G5_intf(priv);
> + if (intf == XGMAC_GMII || intf == XGMAC_GMII)
> + ret = GSW_PORT_HW_GMII;
> + else
> + ret = -EINVAL;
> + break;
> +
> + case SPEED_10G:
> + ret = GSW_PORT_HW_XGMII;
> + break;
> +
> + case SPEED_AUTO:
> + ret = GSW_PORT_HW_XGMII;
> + break;
> +
> + default:
> + ret = -EINVAL;
> + }
> + spin_unlock_bh(&priv->mac_lock);
> +
> + return ret;
> +}
> +
> +inline u32 set_mii_if_fe(u32 mode)
> +{
> + u32 val = 0;
> +
> + switch (mode) {
> + default:
> + case LMAC_MII:
> + val &= ~MAC_IF_CFG_CFGFE;
> + break;
> +
> + case XGMAC_GMII:
> + val |= MAC_IF_CFG_CFGFE;
> + break;
> + }
> +
> + return val;
> +}
> +
> +inline u32 set_mii_if_1g(u32 mode)
> +{
> + u32 val = 0;
> +
> + switch (mode) {
> + default:
> + case LMAC_GMII:
> + val &= ~MAC_IF_CFG_CFG1G;
> + break;
> +
> + case XGMAC_GMII:
> + val |= MAC_IF_CFG_CFG1G;
> + break;
> + }
> +
> + return val;
> +}
> +
> +inline u32 set_mii_if_2G5(u32 mode)
> +{
> + u32 val = 0;
> +
> + switch (mode) {
> + default:
> + case XGMAC_GMII:
> + val &= ~MAC_IF_CFG_CFG2G5;
> + break;
> +
> + case XGMAC_XGMII:
> + val |= MAC_IF_CFG_CFG2G5;
> + break;
> + }
> +
> + return val;
> +}
> +
> +static int mac_set_mii_interface(struct device *dev, u32 mii_mode)
> +{
> + struct gswip_mac *priv = dev_get_drvdata(dev);
> + u32 reg_val = 0;
> +
> + spin_lock_bh(&priv->mac_lock);
> + reg_val = sw_read(priv, MAC_IF_CFG_REG(priv->mac_idx));
> +
> + /* Default modes...
> + * 2.5G - XGMAC_GMII
> + * 1G - LMAC_GMII
> + * FE - LMAC_MII
> + */
> + switch (mii_mode) {
> + default:
> + case GSW_PORT_HW_XGMII:
> + reg_val |= set_mii_if_2G5(XGMAC_XGMII);
> + break;
> +
> + case GSW_PORT_HW_GMII:
> + reg_val |= set_mii_if_1g(XGMAC_GMII);
> + reg_val |= set_mii_if_fe(XGMAC_GMII);
> + reg_val |= set_mii_if_2G5(XGMAC_GMII);
> + break;
> +
> + case GSW_PORT_HW_MII:
> + reg_val |= set_mii_if_fe(LMAC_MII);
> + break;
> + }
> +
> + sw_write(priv, MAC_IF_CFG_REG(priv->mac_idx), reg_val);
> + spin_unlock_bh(&priv->mac_lock);
> +
> + return 0;
> +}
> +
> +static u32 mac_get_mtu(struct device *dev)
> +{
> + struct gswip_mac *priv = dev_get_drvdata(dev);
> + u32 val;
> +
> + spin_lock_bh(&priv->mac_lock);
> + val = sw_mac_get_mtu(priv);
> + spin_unlock_bh(&priv->mac_lock);
> +
> + return val;
> +}
> +
> +static int mac_set_mtu(struct device *dev, u32 mtu)
> +{
> + struct gswip_mac *priv = dev_get_drvdata(dev);
> +
> + if (mtu > LGM_MAX_MTU)
> + return -EINVAL;
> +
> + spin_lock_bh(&priv->mac_lock);
> + sw_mac_set_mtu(priv, mtu);
> + xgmac_config_pkt(priv, mtu);
> + spin_unlock_bh(&priv->mac_lock);
> +
> + return 0;
> +}
> +
> +static int mac_init(struct device *dev)
> +{
> + struct gswip_mac *priv = dev_get_drvdata(dev);
> +
> + xgmac_set_mac_address(priv, priv->mac_addr);
> + mac_set_mtu(dev, priv->mtu);
> + xgmac_config_packet_filter(priv, PROMISC);
> + xgmac_config_packet_filter(priv, PASS_ALL_MULTICAST);
> + mac_set_mii_interface(dev, GSW_PORT_HW_GMII);
> + mac_set_flowctrl(dev, FC_RXTX);
> + mac_set_linksts(priv, LINK_UP);
> + mac_set_duplex(priv, GSW_DUPLEX_FULL);
> + xgmac_set_mac_lpitx(priv, LPITX_EN);
> + mac_set_physpeed(priv, SPEED_XGMAC_10G);
> + /* Enable XMAC Tx/Rx */
> + xgmac_enable(priv);
> + xgmac_pause_frame_filter(priv, 1);
> + sw_set_eee_cap(priv, ANEG_EEE_CAP_OFF);
> + sw_set_mac_rxfcs_op(priv, MAC_OP_CFG_RX_FCS_M3);
> + xgmac_mdio_set_clause(priv, MDIO_CLAUSE22, (priv->mac_idx - MAC2));
> + xgmac_mdio_register(priv);
> +
> + return 0;
> +}
> +
> +static const struct gsw_mac_ops lgm_mac_ops = {
> + .init = mac_init,
> + .set_mtu = mac_set_mtu,
> + .get_mtu = mac_get_mtu,
> + .set_mii_if = mac_set_mii_interface,
> + .get_mii_if = mac_get_mii_interface,
> + .set_flowctrl = mac_set_flowctrl,
> + .get_link_sts = mac_get_linksts,
> + .get_duplex = mac_get_duplex,
> + .get_speed = mac_get_speed,
> +};
> +
> +static const struct gsw_adap_ops lgm_adap_ops = {
> + .sw_core_enable = sw_set_corese,
> +};
> +
> +void mac_init_ops(struct device *dev)
> +{
> + struct gswip_mac *priv = dev_get_drvdata(dev);
> +
> + priv->mac_ops = &lgm_mac_ops;
> + priv->adap_ops = &lgm_adap_ops;
> +}
> diff --git a/drivers/staging/intel-gwdpa/gswip/mac_common.h b/drivers/staging/intel-gwdpa/gswip/mac_common.h
> new file mode 100644
> index 000000000000..6cf61f37c85a
> --- /dev/null
> +++ b/drivers/staging/intel-gwdpa/gswip/mac_common.h
> @@ -0,0 +1,237 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright (c) 2016-2019 Intel Corporation. */
> +
> +#ifndef _MAC_COMMON_H
> +#define _MAC_COMMON_H
> +
> +#include <linux/kernel.h>
> +#include <linux/platform_device.h>
> +#include <linux/spinlock.h>
> +
> +#include "gswip.h"
> +#include "gswip_reg.h"
> +#include "gswip_dev.h"
> +
> +#define LGM_MAX_MTU 10000
> +#define LPITX_EN 1
> +#define SPEED_LSB GENMASK(1, 0)
> +#define SPEED_MSB BIT(2)
> +#define MDIO_CLAUSE22 1
> +#define MDIO_CLAUSE45 0
> +
> +/* MAC Index */
> +enum mac_index {
> + PMAC0 = 0,
> + PMAC1,
> + MAC2,
> + MAC3,
> + MAC4,
> + MAC5,
> + MAC6,
> + MAC7,
> + MAC8,
> + MAC9,
> + MAC10,
> + PMAC2,
> + MAC_LAST,
> +};
This enum is basically a duplicate of mac_id. Only MAC2 is used. Can't
we just use MAC_2 and delete this? Is MAX_MAC related to these values
somehow? Why do we have priv->mac_max when it's always MAX_MAC?
> +
> +enum packet_flilter_mode {
> + PROMISC = 0,
> + PASS_ALL_MULTICAST,
> + PKT_FR_DEF,
> +};
> +
> +enum mii_interface {
> + LMAC_MII = 0,
> + LMAC_GMII,
> + XGMAC_GMII,
> + XGMAC_XGMII,
> +};
> +
> +enum speed_interface {
> + SPEED_10M = 0,
> + SPEED_100M,
> + SPEED_1G,
> + SPEED_10G,
> + SPEED_2G5,
> + SPEED_5G,
> + SPEED_FLEX,
> + SPEED_AUTO
> +};
> +
> +enum gsw_fcon {
> + FCONRX = 0,
> + FCONTX,
> + FDUP,
> +};
> +
> +enum xgmac_fcon_on_off {
> + XGMAC_FC_EN = 0,
> + XGMAC_FC_DIS,
> +};
> +
> +enum gsw_portduplex_mode {
> + GSW_DUPLEX_AUTO = 0,
> + GSW_DUPLEX_HALF,
> + GSW_DUPLEX_FULL,
> +};
> +
> +struct xgmac_hw_features {
> + /* HW version */
> + u32 version;
> +
> + /* HW Feature0 Register: core */
> + u32 gmii; /* 1000 Mbps support */
> + u32 vlhash; /* VLAN Hash Filter */
> + u32 sma; /* SMA(MDIO) Interface */
> + u32 rwk; /* PMT remote wake-up packet */
> + u32 mgk; /* PMT magic packet */
> + u32 mmc; /* RMON module */
> + u32 aoe; /* ARP Offload */
> + u32 ts; /* IEEE 1588-2008 Advanced Timestamp */
> + u32 eee; /* Energy Efficient Ethernet */
> + u32 tx_coe; /* Tx Checksum Offload */
> + u32 rx_coe; /* Rx Checksum Offload */
> + u32 addn_mac; /* Additional MAC Addresses */
> + u32 ts_src; /* Timestamp Source */
> + u32 sa_vlan_ins;/* Source Address or VLAN Insertion */
> + u32 vxn; /* VxLAN/NVGRE Support */
> + u32 ediffc; /* Different Descriptor Cache */
> + u32 edma; /* Enhanced DMA */
> +
> + /* HW Feature1 Register: DMA and MTL */
> + u32 rx_fifo_size; /* MTL Receive FIFO Size */
> + u32 tx_fifo_size; /* MTL Transmit FIFO Size */
> + u32 osten; /* One-Step Timestamping Enable */
> + u32 ptoen; /* PTP Offload Enable */
> + u32 adv_ts_hi; /* Advance Timestamping High Word */
> + u32 dma_width; /* DMA width */
> + u32 dcb; /* DCB Feature */
> + u32 sph; /* Split Header Feature */
> + u32 tso; /* TCP Segmentation Offload */
> + u32 dma_debug; /* DMA Debug Registers */
> + u32 rss; /* Receive Side Scaling */
> + u32 tc_cnt; /* Number of Traffic Classes */
> + u32 hash_table_size; /* Hash Table Size */
> + u32 l3l4_filter_num; /* Number of L3-L4 Filters */
> +
> + /* HW Feature2 Register: Channels(DMA) and Queues(MTL) */
> + u32 rx_q_cnt; /* Number of MTL Receive Queues */
> + u32 tx_q_cnt; /* Number of MTL Transmit Queues */
> + u32 rx_ch_cnt; /* Number of DMA Receive Channels */
> + u32 tx_ch_cnt; /* Number of DMA Transmit Channels */
> + u32 pps_out_num; /* Number of PPS outputs */
> + u32 aux_snap_num; /* Number of Aux snapshot inputs */
> +};
> +
> +struct gswip_mac {
> + void __iomem *sw; /* adaption layer */
> + void __iomem *lmac; /* legacy mac */
> +
> + /* XGMAC registers for indirect accessing */
> + u32 xgmac_ctrl_reg;
> + u32 xgmac_data0_reg;
> + u32 xgmac_data1_reg;
> +
> + u32 sw_irq;
> + struct clk *ptp_clk;
> + struct clk *sw_clk;
> +
> + struct device *dev;
> + struct device *parent;
> +
> + spinlock_t mac_lock; /* MAC spin lock*/
> + spinlock_t irw_lock; /* lock for Indirect read/write */
> + spinlock_t sw_lock; /* adaption lock */
> +
> + /* Phy status */
> + u32 phy_speed;
> + const char *phy_mode;
> +
> + u32 ver;
> + /* Index to point XGMAC 2/3/4/.. */
> + u32 mac_idx;
> + u32 mac_max;
> + u32 ptp_clk_rate;
> +
> + struct xgmac_hw_features hw_feat;
> + const struct gsw_mac_ops *mac_ops;
> +
> + const struct gsw_adap_ops *adap_ops;
> + u32 core_en_cnt;
> + struct mii_bus *mii;
> +
> + u8 mac_addr[6];
> + u32 mtu;
> + bool promisc_mode;
> + bool all_mcast_mode;
> + u32 pause_time;
> +};
> +
> +/* GSWIP-O Top Register write */
> +static inline void sw_write(struct gswip_mac *priv, u32 reg, u32 val)
> +{
> + writel(val, priv->sw + reg);
> +}
> +
> +/* GSWIP-O Top Register read */
> +static inline int sw_read(struct gswip_mac *priv, u32 reg)
> +{
> + return readl(priv->sw + reg);
> +}
> +
> +/* Legacy MAC Register read */
> +static inline void lmac_write(struct gswip_mac *priv, u32 reg, u32 val)
> +{
> + writel(val, priv->lmac + reg);
> +}
> +
> +/* Legacy MAC Register write */
> +static inline int lmac_read(struct gswip_mac *priv, u32 reg)
> +{
> + return readl(priv->lmac + reg);
> +}
> +
> +/* prototype */
> +void mac_init_ops(struct device *dev);
> +void xgmac_init_priv(struct gswip_mac *priv);
> +void xgmac_get_hw_features(struct gswip_mac *priv);
> +void xgmac_set_mac_address(struct gswip_mac *priv, u8 *mac_addr);
> +void xgmac_config_pkt(struct gswip_mac *priv, u32 mtu);
> +void xgmac_config_packet_filter(struct gswip_mac *priv, u32 mode);
> +void xgmac_tx_flow_ctl(struct gswip_mac *priv, u32 pause_time, u32 mode);
> +void xgmac_rx_flow_ctl(struct gswip_mac *priv, u32 mode);
> +int xgmac_set_mac_lpitx(struct gswip_mac *priv, u32 val);
> +int xgmac_enable(struct gswip_mac *priv);
> +int xgmac_disable(struct gswip_mac *priv);
> +int xgmac_pause_frame_filter(struct gswip_mac *priv, u32 val);
> +int xgmac_set_extcfg(struct gswip_mac *priv, u32 val);
> +int xgmac_set_xgmii_speed(struct gswip_mac *priv);
> +int xgmac_set_gmii_2500_speed(struct gswip_mac *priv);
> +int xgmac_set_xgmii_2500_speed(struct gswip_mac *priv);
> +int xgmac_set_gmii_speed(struct gswip_mac *priv);
> +int xgmac_mdio_set_clause(struct gswip_mac *priv, u32 clause, u32 phy_id);
> +int xgmac_mdio_register(struct gswip_mac *priv);
> +
> +int sw_mac_set_mtu(struct gswip_mac *priv, u32 mtu);
> +u32 sw_mac_get_mtu(struct gswip_mac *priv);
> +u32 sw_get_speed(struct gswip_mac *priv);
> +int sw_set_flowctrl(struct gswip_mac *priv, u8 val, u32 mode);
> +u32 sw_get_linkstatus(struct gswip_mac *priv);
> +int sw_set_linkstatus(struct gswip_mac *priv, u8 linkst);
> +u32 sw_get_duplex_mode(struct gswip_mac *priv);
> +int sw_set_duplex_mode(struct gswip_mac *priv, u32 val);
> +int sw_set_speed(struct gswip_mac *priv, u8 speed);
> +int sw_set_2G5_intf(struct gswip_mac *priv, u32 macif);
> +int sw_set_1g_intf(struct gswip_mac *priv, u32 macif);
> +int sw_set_fe_intf(struct gswip_mac *priv, u32 macif);
> +int sw_set_eee_cap(struct gswip_mac *priv, u32 val);
> +int sw_set_mac_rxfcs_op(struct gswip_mac *priv, u32 val);
> +
> +int lmac_set_flowcon_mode(struct gswip_mac *priv, u32 val);
> +int lmac_set_duplex_mode(struct gswip_mac *priv, u32 val);
> +int lmac_set_intf_mode(struct gswip_mac *priv, u32 val);
> +
> +int sw_set_corese(struct device *dev, u32 val);
> +#endif
> diff --git a/drivers/staging/intel-gwdpa/gswip/mac_dev.c b/drivers/staging/intel-gwdpa/gswip/mac_dev.c
> new file mode 100644
> index 000000000000..08989281cecc
> --- /dev/null
> +++ b/drivers/staging/intel-gwdpa/gswip/mac_dev.c
> @@ -0,0 +1,265 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2016-2019 Intel Corporation.
> + *
> + * GSWIP MAC controller driver.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/err.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/spinlock.h>
> +
> +#include "mac_common.h"
> +
> +#define MAX_MAC 9
> +
> +static char *get_speed_info(u32 speed)
> +{
> + char *status;
> +
> + switch (speed) {
> + case SPEED_10M:
> + status = "10 Mbps";
> + break;
The break is missing a tab. It's deliberate and done in the next
functions as well, but please don't.
> +
> + case SPEED_100M:
> + status = "100 Mbps";
> + break;
> +
> + case SPEED_1G:
> + status = "1 Gbps";
> + break;
> +
> + case SPEED_10G:
> + status = "10 Gbps";
> + break;
> +
> + case SPEED_2G5:
> + status = "2.5 Gbps";
> + break;
> +
> + case SPEED_5G:
> + status = "5 Gbps";
> + break;
> +
> + case SPEED_FLEX:
> + status = "flexible";
> + break;
> +
> + case SPEED_AUTO:
> + status = "AUTO";
> + break;
> +
> + default:
> + status = "UNKNOWN";
> + }
> +
> + return status;
> +}
> +
> +static char *get_duplex_info(u32 duplex)
> +{
> + char *status;
> +
> + switch (duplex) {
> + case PHY_MODE_FDUP_AUTO:
> + status = "AUTO";
> + break;
> +
> + case PHY_MODE_FDUP_FD:
> + status = "FULL";
> + break;
> +
> + case PHY_MODE_FDUP_HD:
> + status = "HALF";
> + break;
> +
> + default:
> + status = "UNKNOWN";
> + }
> +
> + return status;
> +}
> +
> +static char *get_link_info(u32 linksts)
> +{
> + char *status;
> +
> + switch (linksts) {
> + case PHY_MODE_LINKST_AUTO:
> + status = "AUTO";
> + break;
> +
> + case PHY_MODE_LINKST_UP:
> + status = "UP";
> + break;
> +
> + case PHY_MODE_LINKST_DOWN:
> + status = "DOWN";
> + break;
> +
> + default:
> + status = "UNKNOWN";
> + }
> +
> + return status;
> +}
> +
> +static void gswss_update_interrupt(struct gswip_mac *priv, u32 mask, u32 set)
> +{
> + u32 val;
> +
> + val = (sw_read(priv, GSWIPSS_IER0) & ~mask) | set;
> + sw_write(priv, GSWIPSS_IER0, val);
> +}
> +
> +static void lmac_update_interrupt(struct gswip_mac *priv, u32 mask, u32 set)
> +{
> + u32 val;
> +
> + val = (lmac_read(priv, LMAC_IER) & ~mask) | set;
> + lmac_write(priv, LMAC_IER, val);
> +}
> +
> +static void gswss_clear_interrupt_all(struct gswip_mac *priv)
> +{
> + unsigned long xgmac_status, lmac_status;
> + u32 pos;
> +
> + xgmac_status = sw_read(priv, GSWIPSS_ISR0);
> + lmac_status = lmac_read(priv, LMAC_ISR);
> +
> + pos = GSWIPSS_I_XGMAC2;
> + for_each_set_bit_from(pos, &xgmac_status, priv->mac_max)
> + gswss_update_interrupt(priv, BIT(pos), 0);
> +
> + pos = LMAC_I_MAC2;
> + for_each_set_bit_from(pos, &lmac_status, priv->mac_max)
> + lmac_update_interrupt(priv, BIT(pos), 0);
> +}
> +
> +static irqreturn_t mac_interrupt(int irq, void *data)
> +{
> + struct gswip_mac *priv = data;
> +
> + /* clear all interrupts */
> + gswss_clear_interrupt_all(priv);
> +
> + return IRQ_HANDLED;
> +}
> +
> +/* All MAC instances have one interrupt line and need to register only once. */
> +static int mac_irq_init(struct gswip_mac *priv)
> +{
> + return devm_request_irq(priv->dev, priv->sw_irq, mac_interrupt, 0,
> + "gswip_mac", priv);
> +}
> +
> +static int get_mac_index(struct device_node *node, u32 *idx)
> +{
> + if (!strstr(node->full_name, "@"))
> + return -EINVAL;
> +
> + return kstrtou32(node->full_name + strlen(node->name) + 1, 0, idx);
> +}
> +
> +static int mac_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + u32 linksts, duplex, speed;
> + struct gswip_pdata *pdata;
> + struct device_node *node;
> + struct gswip_mac *priv;
> + int ret;
> +
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + node = dev->of_node;
> + pdata = dev_get_platdata(dev->parent);
> +
> + /* get the platform data */
> + priv->dev = &pdev->dev;
> + priv->parent = dev->parent;
> + priv->sw = pdata->sw;
> + priv->lmac = pdata->lmac;
> + priv->sw_irq = pdata->sw_irq;
> + priv->ptp_clk = pdata->ptp_clk;
> + priv->sw_clk = pdata->sw_clk;
> +
> + /* Initialize spin lock */
> + spin_lock_init(&priv->mac_lock);
> + spin_lock_init(&priv->irw_lock);
> + spin_lock_init(&priv->sw_lock);
> +
> + priv->mac_max = MAX_MAC;
> + ret = get_mac_index(node, &priv->mac_idx);
> + if (ret)
> + return ret;
> +
> + /* check the mac index range */
> + if (priv->mac_idx < 0 || priv->mac_idx > priv->mac_max) {
> + dev_err(dev, "Mac index Error!!\n");
> + return -EINVAL;
> + }
> +
> + priv->ptp_clk_rate = clk_get_rate(priv->ptp_clk);
> +
> + ret = of_property_read_string(node, "phy-mode", &priv->phy_mode);
> + if (ret)
> + return ret;
> +
> + ret = of_property_read_u32(node, "speed", &priv->phy_speed);
> + if (ret)
> + return ret;
> +
> + /* Request IRQ on first MAC instance */
> + if (!pdata->intr_flag) {
> + ret = mac_irq_init(priv);
> + if (ret)
> + return ret;
> + pdata->intr_flag = true;
> + }
> +
> + dev_set_drvdata(dev, priv);
> + xgmac_init_priv(priv);
> + xgmac_get_hw_features(priv);
> + mac_init_ops(dev);
> +
> + /* Initialize MAC */
> + priv->mac_ops->init(dev);
> +
> + linksts = priv->mac_ops->get_link_sts(dev);
> + duplex = priv->mac_ops->get_duplex(dev);
> + speed = priv->mac_ops->get_speed(dev);
> +
> + priv->adap_ops->sw_core_enable(dev, 1);
> +
> + dev_info(dev, "Init done - Rev:%x Mac_id:%d Speed=%s Link=%s Duplex=%s\n",
> + priv->ver, priv->mac_idx, get_speed_info(speed),
> + get_link_info(linksts), get_duplex_info(duplex));
> +
> + return 0;
> +}
> +
> +static const struct of_device_id gswip_mac_match[] = {
> + { .compatible = "gswip-mac" },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, gswip_mac_match);
> +
> +static struct platform_driver gswip_mac_driver = {
> + .probe = mac_probe,
> + .driver = {
> + .name = "gswip-mac",
> + .of_match_table = gswip_mac_match,
> + },
> +};
> +
> +module_platform_driver(gswip_mac_driver);
> diff --git a/drivers/staging/intel-gwdpa/gswip/xgmac.c b/drivers/staging/intel-gwdpa/gswip/xgmac.c
> new file mode 100644
> index 000000000000..f345ba8911de
> --- /dev/null
> +++ b/drivers/staging/intel-gwdpa/gswip/xgmac.c
> @@ -0,0 +1,636 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2016-2019 Intel Corporation. */
> +
> +#include <linux/bitfield.h>
> +#include <linux/device.h>
> +#include <linux/of_mdio.h>
> +#include <linux/phy.h>
> +
> +#include "mac_common.h"
> +#include "xgmac.h"
> +
> +/**
> + * xgmac_reg_rw - XGMAC register indirect read and write access.
> + * @priv: mac private data.
> + * @reg: register offset.
> + * @val:
> + * read - pointer variable to read the value into.
> + * write - pointer variable to the write value.
> + * @rd_wr: boolean value, true/false.
> + * false - read.
> + * true - write.
> + */
> +static inline void xgmac_reg_rw(struct gswip_mac *priv, u16 reg, u32 *val,
> + bool rd_wr)
> +{
> + void __iomem *xgmac_ctrl_reg = priv->sw + priv->xgmac_ctrl_reg;
> + void __iomem *xgmac_data0_reg = priv->sw + priv->xgmac_data0_reg;
> + void __iomem *xgmac_data1_reg = priv->sw + priv->xgmac_data1_reg;
> + u32 access = XGMAC_REGACC_CTRL_ADDR_BAS;
> + u32 retries = MAX_RETRY;
This MAX_RETRY is only used here. Just use a literal for these. We all
know that 2000 is just a made up number.
> +
> + spin_lock_bh(&priv->irw_lock);
> + access &= ~XGMAC_REGACC_CTRL_OPMOD_WR;
> + if (rd_wr) {
> + writel(FIELD_GET(MASK_HIGH, *val), xgmac_data1_reg);
> + writel(FIELD_GET(MASK_LOW, *val), xgmac_data0_reg);
> + access |= XGMAC_REGACC_CTRL_OPMOD_WR;
> + }
> +
> + writel(access | reg, xgmac_ctrl_reg);
> +
> + do {
> + if (!(readl(xgmac_ctrl_reg) & XGMAC_REGACC_CTRL_ADDR_BAS))
> + break;
> + cpu_relax();
> + } while (--retries);
> + if (!retries)
> + dev_warn(priv->dev, "Xgmac register %s failed for Offset %x\n",
> + rd_wr ? "write" : "read", reg);
> +
> + if (!rd_wr)
> + *val = FIELD_PREP(MASK_HIGH, readl(xgmac_data1_reg)) |
> + readl(xgmac_data0_reg);
> + spin_unlock_bh(&priv->irw_lock);
> +}
> +
> +void xgmac_get_hw_features(struct gswip_mac *priv)
> +{
> + struct xgmac_hw_features *hw_feat = &priv->hw_feat;
> + u32 mac_hfr0, mac_hfr1, mac_hfr2;
> +
> + xgmac_reg_rw(priv, MAC_HW_F0, &mac_hfr0, false);
> + xgmac_reg_rw(priv, MAC_HW_F1, &mac_hfr1, false);
> + xgmac_reg_rw(priv, MAC_HW_F2, &mac_hfr2, false);
> + xgmac_reg_rw(priv, MAC_VER, &hw_feat->version, false);
> +
> + priv->ver = FIELD_GET(MAC_VER_USERVER, hw_feat->version);
> +
> + /* Hardware feature0 regiter*/
> + hw_feat->gmii = FIELD_GET(MAC_HW_F0_GMIISEL, mac_hfr0);
> + hw_feat->vlhash = FIELD_GET(MAC_HW_F0_VLHASH, mac_hfr0);
> + hw_feat->sma = FIELD_GET(MAC_HW_F0_SMASEL, mac_hfr0);
> + hw_feat->rwk = FIELD_GET(MAC_HW_F0_RWKSEL, mac_hfr0);
> + hw_feat->mgk = FIELD_GET(MAC_HW_F0_MGKSEL, mac_hfr0);
> + hw_feat->mmc = FIELD_GET(MAC_HW_F0_MMCSEL, mac_hfr0);
> + hw_feat->aoe = FIELD_GET(MAC_HW_F0_ARPOFFSEL, mac_hfr0);
> + hw_feat->ts = FIELD_GET(MAC_HW_F0_TSSEL, mac_hfr0);
> + hw_feat->eee = FIELD_GET(MAC_HW_F0_EEESEL, mac_hfr0);
> + hw_feat->tx_coe = FIELD_GET(MAC_HW_F0_TXCOESEL, mac_hfr0);
> + hw_feat->rx_coe = FIELD_GET(MAC_HW_F0_RXCOESEL, mac_hfr0);
> + hw_feat->addn_mac = FIELD_GET(MAC_HW_F0_ADDMACADRSEL, mac_hfr0);
> + hw_feat->ts_src = FIELD_GET(MAC_HW_F0_TSSTSSEL, mac_hfr0);
> + hw_feat->sa_vlan_ins = FIELD_GET(MAC_HW_F0_SAVLANINS, mac_hfr0);
> + hw_feat->vxn = FIELD_GET(MAC_HW_F0_VXN, mac_hfr0);
> + hw_feat->ediffc = FIELD_GET(MAC_HW_F0_EDIFFC, mac_hfr0);
> + hw_feat->edma = FIELD_GET(MAC_HW_F0_EDMA, mac_hfr0);
> +
> + /* Hardware feature1 register*/
> + hw_feat->rx_fifo_size = FIELD_GET(MAC_HW_F1_RXFIFOSIZE, mac_hfr1);
> + hw_feat->tx_fifo_size = FIELD_GET(MAC_HW_F1_TXFIFOSIZE, mac_hfr1);
> + hw_feat->osten = FIELD_GET(MAC_HW_F1_OSTEN, mac_hfr1);
> + hw_feat->ptoen = FIELD_GET(MAC_HW_F1_PTOEN, mac_hfr1);
> + hw_feat->adv_ts_hi = FIELD_GET(MAC_HW_F1_ADVTHWORD, mac_hfr1);
> + hw_feat->dma_width = FIELD_GET(MAC_HW_F1_ADDR64, mac_hfr1);
> + hw_feat->dcb = FIELD_GET(MAC_HW_F1_DCBEN, mac_hfr1);
> + hw_feat->sph = FIELD_GET(MAC_HW_F1_SPHEN, mac_hfr1);
> + hw_feat->tso = FIELD_GET(MAC_HW_F1_TSOEN, mac_hfr1);
> + hw_feat->dma_debug = FIELD_GET(MAC_HW_F1_DBGMEMA, mac_hfr1);
> + hw_feat->rss = FIELD_GET(MAC_HW_F1_RSSEN, mac_hfr1);
> + hw_feat->tc_cnt = FIELD_GET(MAC_HW_F1_NUMTC, mac_hfr1);
> + hw_feat->hash_table_size = FIELD_GET(MAC_HW_F1_HASHTBLSZ, mac_hfr1);
> + hw_feat->l3l4_filter_num = FIELD_GET(MAC_HW_F1_L3L4FNUM, mac_hfr1);
> +
> + /* Hardware feature2 register*/
> + hw_feat->rx_q_cnt = FIELD_GET(MAC_HW_F2_RXCHCNT, mac_hfr2);
> + hw_feat->tx_q_cnt = FIELD_GET(MAC_HW_F2_TXQCNT, mac_hfr2);
> + hw_feat->rx_ch_cnt = FIELD_GET(MAC_HW_F2_RXCHCNT, mac_hfr2);
> + hw_feat->tx_ch_cnt = FIELD_GET(MAC_HW_F2_TXCHCNT, mac_hfr2);
> + hw_feat->pps_out_num = FIELD_GET(MAC_HW_F2_PPSOUTNUM, mac_hfr2);
> + hw_feat->aux_snap_num = FIELD_GET(MAC_HW_F2_AUXSNAPNUM, mac_hfr2);
> +
> + /* TC and Queue are zero based so increment to get the actual number */
> + hw_feat->tc_cnt++;
> + hw_feat->rx_q_cnt++;
> + hw_feat->tx_q_cnt++;
> +}
> +
> +void xgmac_init_priv(struct gswip_mac *priv)
> +{
> + u8 mac_addr[6] = {0x00, 0x00, 0x94, 0x00, 0x00, 0x08};
> +
> + priv->mac_idx += MAC2;
> +
> + priv->xgmac_ctrl_reg = XGMAC_CTRL_REG(priv->mac_idx);
> + priv->xgmac_data1_reg = XGMAC_DATA1_REG(priv->mac_idx);
> + priv->xgmac_data0_reg = XGMAC_DATA0_REG(priv->mac_idx);
> +
> + /* Temp mac addr, Later eth driver will update */
> + mac_addr[5] = priv->mac_idx;
> + memcpy(priv->mac_addr, mac_addr, 6);
> +
> + priv->mtu = LGM_MAX_MTU;
> + priv->promisc_mode = true;
> + priv->all_mcast_mode = true;
> +}
> +
> +void xgmac_set_mac_address(struct gswip_mac *priv, u8 *mac_addr)
> +{
> + u32 mac_addr_hi, mac_addr_low;
> + u32 val;
> +
> + mac_addr_hi = (mac_addr[5] << 8) | (mac_addr[4] << 0);
> + mac_addr_low = (mac_addr[3] << 24) | (mac_addr[2] << 16) |
> + (mac_addr[1] << 8) | (mac_addr[0] << 0);
> +
> + xgmac_reg_rw(priv, MAC_MACA0HR, &mac_addr_hi, true);
> +
> + xgmac_reg_rw(priv, MAC_MACA0LR, &val, false);
> + if (val != mac_addr_low)
> + xgmac_reg_rw(priv, MAC_MACA0LR, &mac_addr_low, true);
> +}
> +
> +inline void xgmac_prep_pkt_jumbo(u32 mtu, u32 *mac_rcr, u32 *mac_tcr)
> +{
> + if (mtu < XGMAC_MAX_GPSL) { /* upto 9018 configuration */
> + *mac_rcr |= MAC_RX_CFG_JE;
> + *mac_rcr &= ~MAC_RX_CFG_WD & ~MAC_RX_CFG_GPSLCE;
> + *mac_tcr &= ~MAC_TX_CFG_JD;
> +
> + } else { /* upto 16K configuration */
> + *mac_rcr &= ~MAC_RX_CFG_JE;
> + *mac_rcr |= MAC_RX_CFG_WD | MAC_RX_CFG_GPSLCE |
> + FIELD_PREP(MAC_RX_CFG_GPSL,
> + XGMAC_MAX_SUPPORTED_MTU);
> + *mac_tcr |= MAC_TX_CFG_JD;
> + }
> +}
> +
> +inline void xgmac_prep_pkt_standard(u32 *mac_rcr, u32 *mac_tcr)
> +{
> + *mac_rcr &= ~MAC_RX_CFG_JE & ~MAC_RX_CFG_WD & ~MAC_RX_CFG_GPSLCE;
> + *mac_tcr &= ~MAC_TX_CFG_JD;
> +}
> +
> +void xgmac_config_pkt(struct gswip_mac *priv, u32 mtu)
> +{
> + u32 mac_rcr, mac_tcr;
> +
> + xgmac_reg_rw(priv, MAC_RX_CFG, &mac_rcr, false);
> + xgmac_reg_rw(priv, MAC_TX_CFG, &mac_tcr, false);
> +
> + if (mtu > XGMAC_MAX_STD_PACKET)
> + xgmac_prep_pkt_jumbo(mtu, &mac_rcr, &mac_tcr);
> + else
> + xgmac_prep_pkt_standard(&mac_rcr, &mac_tcr);
> +
> + xgmac_reg_rw(priv, MAC_RX_CFG, &mac_rcr, true);
> + xgmac_reg_rw(priv, MAC_TX_CFG, &mac_tcr, true);
> +}
> +
> +void xgmac_config_packet_filter(struct gswip_mac *priv, u32 mode)
> +{
> + u32 reg_val, temp = 0;
"temp" stands for temperature. "tmp" is temporary. Just get rid of
it and use reg_val directly.
> +
> + xgmac_reg_rw(priv, MAC_PKT_FR, ®_val, false);
> +
> + switch (mode) {
> + case PROMISC:
> + reg_val &= ~MAC_PKT_FR_PR;
> + temp |= FIELD_PREP(MAC_PKT_FR_PR, priv->promisc_mode);
reg_val |= FIELD_PREP(MAC_PKT_FR_PR, priv->promisc_mode);
> + break;
> +
> + case PASS_ALL_MULTICAST:
> + reg_val &= ~MAC_PKT_FR_PM;
> + temp |= FIELD_PREP(MAC_PKT_FR_PM, priv->all_mcast_mode);
> + break;
> +
> + default:
> + reg_val &= ~MAC_PKT_FR_PR & ~MAC_PKT_FR_PM;
> + temp |= FIELD_PREP(MAC_PKT_FR_PR, priv->promisc_mode) |
> + FIELD_PREP(MAC_PKT_FR_PM, priv->all_mcast_mode);
> + }
> + reg_val |= temp;
> +
> + xgmac_reg_rw(priv, MAC_PKT_FR, ®_val, true);
> +}
> +
> +void xgmac_tx_flow_ctl(struct gswip_mac *priv, u32 pause_time, u32 mode)
> +{
> + u32 reg_val = 0;
> +
> + xgmac_reg_rw(priv, MAC_TX_FCR, ®_val, false);
> +
> + switch (mode) {
> + case XGMAC_FC_EN:
> + /* enable tx flow control */
> + reg_val |= MAC_TX_FCR_TFE;
> +
> + /* Set pause time */
> + reg_val &= ~MAC_TX_FCR_PT;
> + reg_val |= FIELD_PREP(MAC_TX_FCR_PT, pause_time);
> + break;
> +
> + case XGMAC_FC_DIS:
> + reg_val &= ~MAC_TX_FCR_TFE;
> + break;
> + }
> +
> + xgmac_reg_rw(priv, MAC_TX_FCR, ®_val, true);
> +}
> +
> +void xgmac_rx_flow_ctl(struct gswip_mac *priv, u32 mode)
> +{
> + u32 reg_val = 0;
> +
> + xgmac_reg_rw(priv, MAC_RX_FCR, ®_val, false);
> +
> + switch (mode) {
> + case XGMAC_FC_EN:
> + /* rx fc enable */
> + reg_val |= MAC_RX_FCR_RFE;
> + reg_val &= ~MAC_RX_FCR_PFCE;
> + break;
> +
> + case XGMAC_FC_DIS:
> + reg_val &= ~MAC_RX_FCR_RFE;
> + break;
> + }
> +
> + xgmac_reg_rw(priv, MAC_RX_FCR, ®_val, true);
> +}
> +
> +int xgmac_set_mac_lpitx(struct gswip_mac *priv, u32 val)
> +{
> + u32 lpiate;
> +
> + xgmac_reg_rw(priv, MAC_LPI_CSR, &lpiate, false);
> +
> + if (FIELD_GET(MAC_LPI_CSR_LPIATE, lpiate) != val) {
> + lpiate &= ~MAC_LPI_CSR_LPIATE;
> + lpiate |= FIELD_PREP(MAC_LPI_CSR_LPIATE, val);
> + }
> +
> + if (FIELD_GET(MAC_LPI_CSR_LPITXA, lpiate) != val) {
> + lpiate &= ~MAC_LPI_CSR_LPITXA;
> + lpiate |= FIELD_PREP(MAC_LPI_CSR_LPITXA, val);
> + }
> +
> + xgmac_reg_rw(priv, MAC_LPI_CSR, &lpiate, true);
> +
> + return 0;
> +}
> +
> +int xgmac_enable(struct gswip_mac *priv)
> +{
> + u32 mac_tcr, mac_rcr, mac_pfr;
> +
> + xgmac_reg_rw(priv, MAC_TX_CFG, &mac_tcr, false);
> + xgmac_reg_rw(priv, MAC_RX_CFG, &mac_rcr, false);
> + xgmac_reg_rw(priv, MAC_PKT_FR, &mac_pfr, false);
> +
> + /* Enable MAC Tx */
> + if (!FIELD_GET(MAC_TX_CFG_TE, mac_tcr)) {
> + mac_tcr |= MAC_TX_CFG_TE;
> + xgmac_reg_rw(priv, MAC_TX_CFG, &mac_tcr, true);
> + }
> +
> + /* Enable MAC Rx */
> + if (!FIELD_GET(MAC_RX_CFG_RE, mac_rcr)) {
> + mac_rcr |= MAC_RX_CFG_RE;
> + xgmac_reg_rw(priv, MAC_RX_CFG, &mac_rcr, true);
> + }
> +
> + /* Enable MAC Filter Rx All */
> + if (!FIELD_GET(MAC_PKT_FR_RA, mac_pfr)) {
> + mac_pfr |= MAC_PKT_FR_RA;
> + xgmac_reg_rw(priv, MAC_PKT_FR, &mac_pfr, true);
> + }
> +
> + return 0;
> +}
> +
> +int xgmac_disable(struct gswip_mac *priv)
> +{
> + u32 mac_tcr, mac_rcr, mac_pfr;
> +
> + xgmac_reg_rw(priv, MAC_TX_CFG, &mac_tcr, false);
> + xgmac_reg_rw(priv, MAC_RX_CFG, &mac_rcr, false);
> + xgmac_reg_rw(priv, MAC_PKT_FR, &mac_pfr, false);
> +
> + /* Disable MAC Tx */
> + if (FIELD_GET(MAC_TX_CFG_TE, mac_tcr) != 0) {
> + mac_tcr &= ~MAC_TX_CFG_TE;
> + xgmac_reg_rw(priv, MAC_TX_CFG, &mac_tcr, true);
> + }
> +
> + /* Disable MAC Rx */
> + if (FIELD_GET(MAC_RX_CFG_RE, mac_rcr) != 0) {
> + mac_rcr &= ~MAC_RX_CFG_RE;
> + xgmac_reg_rw(priv, MAC_RX_CFG, &mac_rcr, true);
> + }
> +
> + /* Disable MAC Filter Rx All */
> + if (FIELD_GET(MAC_PKT_FR_RA, mac_pfr) != 0) {
> + mac_pfr &= ~MAC_PKT_FR_RA;
> + xgmac_reg_rw(priv, MAC_PKT_FR, &mac_pfr, true);
> + }
> +
> + return 0;
> +}
> +
> +int xgmac_pause_frame_filter(struct gswip_mac *priv, u32 val)
> +{
> + u32 mac_pfr;
> +
> + xgmac_reg_rw(priv, MAC_PKT_FR, &mac_pfr, false);
> +
> + if (FIELD_GET(MAC_PKT_FR_PCF, mac_pfr) != val) {
> + /* Pause filtering */
> + mac_pfr &= ~MAC_PKT_FR_PCF;
> + mac_pfr |= FIELD_PREP(MAC_PKT_FR_PCF, val);
> + }
> +
> + /* The Receiver module passes only those packets to the application
> + * that pass the SA or DA address filter.
> + */
> + if (FIELD_GET(MAC_PKT_FR_RA, mac_pfr) == 1)
> + mac_pfr &= ~MAC_PKT_FR_RA;
> +
> + xgmac_reg_rw(priv, MAC_PKT_FR, &mac_pfr, true);
> +
> + return 0;
> +}
> +
> +int xgmac_set_extcfg(struct gswip_mac *priv, u32 val)
> +{
> + u32 mac_extcfg;
> +
> + xgmac_reg_rw(priv, MAC_EXTCFG, &mac_extcfg, false);
> +
> + if (FIELD_GET(MAC_EXTCFG_SBDIOEN, mac_extcfg) != val) {
> + mac_extcfg &= ~MAC_EXTCFG_SBDIOEN;
> + mac_extcfg |= FIELD_PREP(MAC_EXTCFG_SBDIOEN, val);
> + xgmac_reg_rw(priv, MAC_EXTCFG, &mac_extcfg, true);
> + }
> +
> + return 0;
> +}
> +
> +int xgmac_set_xgmii_speed(struct gswip_mac *priv)
> +{
> + u32 mac_tcr;
> +
> + xgmac_disable(priv);
> + xgmac_reg_rw(priv, MAC_TX_CFG, &mac_tcr, false);
> +
> + if (FIELD_GET(MAC_TX_CFG_USS, mac_tcr) != 0)
> + mac_tcr &= ~MAC_TX_CFG_USS;
> +
> + if (FIELD_GET(MAC_TX_CFG_SS, mac_tcr) != 0)
> + mac_tcr &= ~MAC_TX_CFG_SS;
> +
> + xgmac_reg_rw(priv, MAC_TX_CFG, &mac_tcr, true);
> + xgmac_enable(priv);
> +
> + return 0;
> +}
> +
> +int xgmac_set_gmii_2500_speed(struct gswip_mac *priv)
> +{
> + u32 mac_tcr;
> +
> + xgmac_disable(priv);
> + xgmac_reg_rw(priv, MAC_TX_CFG, &mac_tcr, false);
> +
> + if (FIELD_GET(MAC_TX_CFG_USS, mac_tcr) != 0)
> + mac_tcr &= ~MAC_TX_CFG_USS;
> +
> + if (FIELD_GET(MAC_TX_CFG_SS, mac_tcr) != 0x2) {
> + mac_tcr &= ~MAC_TX_CFG_SS;
> + mac_tcr |= FIELD_PREP(MAC_TX_CFG_SS, 0x2);
> + }
> +
> + xgmac_reg_rw(priv, MAC_TX_CFG, &mac_tcr, true);
> + xgmac_enable(priv);
> +
> + return 0;
> +}
> +
> +int xgmac_set_xgmii_2500_speed(struct gswip_mac *priv)
> +{
> + u32 mac_tcr;
> +
> + xgmac_enable(priv);
It looks like the xgmac_enable/disable are reversed. We want to pause
briefly while we change the hardware and then restart. It seems that
this code was never tested so you could look at adding that to your
test cases.
> + xgmac_reg_rw(priv, MAC_TX_CFG, &mac_tcr, false);
> +
> + if (FIELD_GET(MAC_TX_CFG_USS, mac_tcr) != 1)
> + mac_tcr |= MAC_TX_CFG_USS;
> +
> + if (FIELD_GET(MAC_TX_CFG_SS, mac_tcr) != 0x2) {
> + mac_tcr &= ~MAC_TX_CFG_SS;
> + mac_tcr |= FIELD_PREP(MAC_TX_CFG_SS, 0x2);
> + }
> +
> + xgmac_reg_rw(priv, MAC_TX_CFG, &mac_tcr, true);
> + xgmac_disable(priv);
^^^^^^^^^^^^^^^^^^^
We're leaving the hardeware in a paused state.
> +
> + return 0;
> +}
> +
> +int xgmac_set_gmii_speed(struct gswip_mac *priv)
> +{
> + u32 mac_tcr;
> +
> + xgmac_disable(priv);
> + xgmac_reg_rw(priv, MAC_TX_CFG, &mac_tcr, false);
> +
> + if (FIELD_GET(MAC_TX_CFG_USS, mac_tcr) != 0)
> + mac_tcr &= MAC_TX_CFG_USS;
> +
> + if (FIELD_GET(MAC_TX_CFG_SS, mac_tcr) != 0x3) {
> + mac_tcr &= ~MAC_TX_CFG_SS;
> + mac_tcr |= FIELD_PREP(MAC_TX_CFG_SS, 0x3);
> + }
> +
> + xgmac_reg_rw(priv, MAC_TX_CFG, &mac_tcr, true);
> + xgmac_enable(priv);
> +
> + return 0;
> +}
> +
> +int xgmac_mdio_set_clause(struct gswip_mac *priv, u32 clause, u32 phy_id)
> +{
> + u32 mdio_c22p = 0;
> +
> + xgmac_reg_rw(priv, MDIO_C22P, &mdio_c22p, false);
> +
> + if (clause == MDIO_CLAUSE22)
> + mdio_c22p |= MDIO_C22P_PORT(phy_id);
> + else
> + mdio_c22p &= ~MDIO_C22P_PORT(phy_id);
> +
> + /* Select port 0, 1, 2 and 3 as Clause 22/45 ports */
> + xgmac_reg_rw(priv, MDIO_C22P, &mdio_c22p, true);
> +
> + return 0;
> +}
> +
> +int xgmac_mdio_single_wr(struct gswip_mac *priv, u32 dev_adr, u32 phy_id,
> + u32 phy_reg, u32 phy_reg_data)
> +{
> + u32 mdio_sccdr, mdio_scar;
> + u32 retries = 100;
> +
> + /* wait for any previous MDIO read/write operation to complete */
> + /*Poll*/
> + do {
> + xgmac_reg_rw(priv, MDIO_SCCDR, &mdio_sccdr, false);
> + if (!FIELD_GET(MDIO_SCCDR_BUSY, mdio_sccdr))
> + break;
> + cpu_relax();
> + } while (--retries);
> + if (!retries)
> + dev_warn(priv->dev, "Xgmac MDIO rd/wr operation failed\n");
> +
> + xgmac_reg_rw(priv, MDIO_SCAR, &mdio_scar, false);
> + mdio_scar &= ~MDIO_SCAR_DA & ~MDIO_SCAR_PA & ~MDIO_SCAR_RA;
> + mdio_scar |= FIELD_PREP(MDIO_SCAR_DA, dev_adr);
> + mdio_scar |= FIELD_PREP(MDIO_SCAR_PA, phy_id);
> + mdio_scar |= FIELD_PREP(MDIO_SCAR_RA, phy_reg);
> + xgmac_reg_rw(priv, MDIO_SCAR, &mdio_scar, true);
> +
> + xgmac_reg_rw(priv, MDIO_SCCDR, &mdio_sccdr, false);
> + mdio_sccdr &= ~MDIO_SCCDR_SDATA & ~MDIO_SCCDR_CMD;
> + mdio_sccdr |= FIELD_PREP(MDIO_SCCDR_SDATA, phy_reg_data);
> + mdio_sccdr |= MDIO_SCCDR_BUSY;
> + mdio_sccdr &= ~MDIO_SCCDR_SADDR;
> + mdio_sccdr |= FIELD_PREP(MDIO_SCCDR_CMD, 1);
> + xgmac_reg_rw(priv, MDIO_SCCDR, &mdio_sccdr, true);
> +
> + /* wait for MDIO read operation to complete */
> + /*Poll*/
retries = 100;
> + do {
> + xgmac_reg_rw(priv, MDIO_SCCDR, &mdio_sccdr, false);
> + if (!FIELD_GET(MDIO_SCCDR_BUSY, mdio_sccdr))
> + break;
> + cpu_relax();
> + } while (--retries);
"retries" wasn't reset to 100 so this could loop for a UINT_MAX
iterations.
> + if (!retries)
> + dev_warn(priv->dev, "Xgmac MDIO rd/wr operation failed\n");
> +
> + return 0;
> +}
> +
> +int xgmac_mdio_single_rd(struct gswip_mac *priv, u32 dev_adr, u32 phy_id,
> + u32 phy_reg)
> +{
> + u32 mdio_sccdr, mdio_scar;
> + u32 retries = 100;
> + int phy_reg_data;
> +
> + /* wait for any previous MDIO read/write operation to complete */
> + /*Poll*/
> + do {
> + xgmac_reg_rw(priv, MDIO_SCCDR, &mdio_sccdr, false);
> + if (!FIELD_GET(MDIO_SCCDR_BUSY, mdio_sccdr))
> + break;
> + cpu_relax();
> + } while (--retries);
> + if (!retries)
> + dev_warn(priv->dev, "Xgmac MDIO rd/wr operation failed\n");
> +
> + /* initiate the MDIO read operation by updating desired bits
> + * PA - phy address/id (0 - 31)
> + * RA - phy register offset
> + */
> +
> + xgmac_reg_rw(priv, MDIO_SCAR, &mdio_scar, false);
> + mdio_scar &= ~MDIO_SCAR_DA & ~MDIO_SCAR_PA & ~MDIO_SCAR_RA;
> + mdio_scar |= FIELD_PREP(MDIO_SCAR_DA, dev_adr);
> + mdio_scar |= FIELD_PREP(MDIO_SCAR_PA, phy_id);
> + mdio_scar |= FIELD_PREP(MDIO_SCAR_RA, phy_reg);
> + xgmac_reg_rw(priv, MDIO_SCAR, &mdio_scar, true);
> +
> + xgmac_reg_rw(priv, MDIO_SCCDR, &mdio_sccdr, false);
> + mdio_sccdr &= ~MDIO_SCCDR_CMD & ~MDIO_SCCDR_SDATA;
> + mdio_sccdr |= MDIO_SCCDR_BUSY;
> + mdio_sccdr &= ~MDIO_SCCDR_SADDR;
> + mdio_sccdr |= FIELD_PREP(MDIO_SCCDR_CMD, 3);
> + mdio_sccdr |= FIELD_PREP(MDIO_SCCDR_SDATA, 0);
> + xgmac_reg_rw(priv, MDIO_SCCDR, &mdio_sccdr, true);
> +
> + /* wait for MDIO read operation to complete */
> + /*Poll*/
retries = 100;
> + do {
> + xgmac_reg_rw(priv, MDIO_SCCDR, &mdio_sccdr, false);
> + if (!FIELD_GET(MDIO_SCCDR_BUSY, mdio_sccdr))
> + break;
> + cpu_relax();
> + } while (--retries);
> + if (!retries)
> + dev_warn(priv->dev, "Xgmac MDIO rd/wr operation failed\n");
> +
> + /* read the data */
> + xgmac_reg_rw(priv, MDIO_SCCDR, &mdio_sccdr, false);
> + phy_reg_data = FIELD_GET(MDIO_SCCDR_SDATA, mdio_sccdr);
> +
> + return phy_reg_data;
> +}
> +
> +static int xgmac_mdio_read(struct mii_bus *bus, int phyadr, int phyreg)
> +{
> + struct gswip_mac *priv = bus->priv;
> +
> + return xgmac_mdio_single_rd(priv, 0, phyadr, phyreg);
> +}
> +
> +static int xgmac_mdio_write(struct mii_bus *bus, int phyadr, int phyreg,
> + u16 phydata)
> +{
> + struct gswip_mac *priv = bus->priv;
> +
> + xgmac_mdio_single_wr(priv, 0, phyadr, phyreg, phydata);
> +
> + return 0;
> +}
> +
> +int xgmac_mdio_register(struct gswip_mac *priv)
> +{
> + struct device_node *mdio_np;
> + struct mii_bus *bus;
> + int ret;
> +
> + mdio_np = of_get_child_by_name(priv->dev->of_node, "mdio");
> + if (!mdio_np)
> + return -ENOLINK;
> +
> + bus = mdiobus_alloc();
> + if (!bus)
> + return -ENOMEM;
> +
> + bus->name = "xgmac_phy";
> + bus->read = xgmac_mdio_read;
> + bus->write = xgmac_mdio_write;
> + bus->reset = NULL;
> + snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%x", bus->name, priv->mac_idx);
> + bus->priv = priv;
> + bus->parent = priv->dev;
> +
> + /* At this moment gphy is not yet up (firmware not yet loaded), so we
> + * avoid auto mdio scan.
> + */
> + bus->phy_mask = 0xFFFFFFFF;
> +
> + ret = of_mdiobus_register(bus, mdio_np);
> + if (ret) {
> + mdiobus_free(bus);
> + return ret;
> + }
> +
> + priv->mii = bus;
> + dev_info(priv->dev, "XGMAC %d: MDIO register Successful\n",
> + priv->mac_idx);
> +
> + return ret;
return 0; is equivalent but more readable to return ret;
> +}
regards,
dan carpenter
Powered by blists - more mailing lists