+ val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
+ /* configure GIG MAC to SGMII mode */
+ val &= ~MVPP2_GMAC_PORT_TYPE_MASK;
+ writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
+
+ /* configure AN */
+ val = MVPP2_GMAC_EN_PCS_AN |
+ MVPP2_GMAC_AN_BYPASS_EN |
+ MVPP2_GMAC_AN_SPEED_EN |
+ MVPP2_GMAC_EN_FC_AN |
+ MVPP2_GMAC_AN_DUPLEX_EN |
+ MVPP2_GMAC_CHOOSE_SAMPLE_TX_CONFIG;
+ writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+}
+
+static void gop_gmac_rgmii_cfg(struct mvpp2_port *port)
+{
+ u32 val, thresh;
+
+ /*
+ * Configure minimal level of the Tx FIFO before the lower part
+ * starts to read a packet
+ */
+ thresh = MVPP2_RGMII_TX_FIFO_MIN_TH;
+ val = readl(port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+ val &= ~MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK;
+ val |= MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(thresh);
+ writel(val, port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+
+ /* Disable bypass of sync module */
+ val = readl(port->base + MVPP2_GMAC_CTRL_4_REG);
+ val |= MVPP2_GMAC_CTRL4_SYNC_BYPASS_MASK;
+ /* configure DP clock select according to mode */
+ val &= ~MVPP2_GMAC_CTRL4_DP_CLK_SEL_MASK;
+ val |= MVPP2_GMAC_CTRL4_QSGMII_BYPASS_ACTIVE_MASK;
+ val |= MVPP2_GMAC_CTRL4_EXT_PIN_GMII_SEL_MASK;
+ writel(val, port->base + MVPP2_GMAC_CTRL_4_REG);
+
+ val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
+ /* configure GIG MAC to SGMII mode */
+ val &= ~MVPP2_GMAC_PORT_TYPE_MASK;
+ writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
+
+ /* configure AN 0xb8e8 */
+ val = MVPP2_GMAC_AN_BYPASS_EN |
+ MVPP2_GMAC_AN_SPEED_EN |
+ MVPP2_GMAC_EN_FC_AN |
+ MVPP2_GMAC_AN_DUPLEX_EN |
+ MVPP2_GMAC_CHOOSE_SAMPLE_TX_CONFIG;
+ writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
+}
+
+/* Set the internal mux's to the required MAC in the GOP */
+static int gop_gmac_mode_cfg(struct mvpp2_port *port)
+{
+ u32 val;
+
+ /* Set TX FIFO thresholds */
+ switch (port->phy_interface) {
+ case PHY_INTERFACE_MODE_SGMII:
+ if (port->phy_speed == 2500)
+ gop_gmac_sgmii2_5_cfg(port);
+ else
+ gop_gmac_sgmii_cfg(port);
+ break;
+
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ gop_gmac_rgmii_cfg(port);
+ break;
+
+ default:
+ return -1;
+ }
+
+ /* Jumbo frame support - 0x1400*2= 0x2800 bytes */
+ val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
+ val &= ~MVPP2_GMAC_MAX_RX_SIZE_MASK;
+ val |= 0x1400 << MVPP2_GMAC_MAX_RX_SIZE_OFFS;
+ writel(val, port->base + MVPP2_GMAC_CTRL_0_REG);
+
+ /* PeriodicXonEn disable */
+ val = readl(port->base + MVPP2_GMAC_CTRL_1_REG);
+ val &= ~MVPP2_GMAC_PERIODIC_XON_EN_MASK;
+ writel(val, port->base + MVPP2_GMAC_CTRL_1_REG);
+
+ return 0;
+}
+
+static void gop_xlg_2_gig_mac_cfg(struct mvpp2_port *port)
+{
+ u32 val;
+
+ /* relevant only for MAC0 (XLG0 and GMAC0) */
+ if (port->gop_id > 0)
+ return;
+
+ /* configure 1Gig MAC mode */
+ val = readl(port->base + MVPP22_XLG_CTRL3_REG);
+ val &= ~MVPP22_XLG_CTRL3_MACMODESELECT_MASK;
+ val |= MVPP22_XLG_CTRL3_MACMODESELECT_GMAC;
+ writel(val, port->base + MVPP22_XLG_CTRL3_REG);
+}
+
+static int gop_gpcs_reset(struct mvpp2_port *port, int reset)
+{
+ u32 val;
+
+ val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
+ if (reset)
+ val &= ~MVPP2_GMAC_SGMII_MODE_MASK;
+ else
+ val |= MVPP2_GMAC_SGMII_MODE_MASK;
+ writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
+
+ return 0;
+}
+
+/* Set the internal mux's to the required PCS in the PI */
+static int gop_xpcs_mode(struct mvpp2_port *port, int num_of_lanes)
+{
+ u32 val;
+ int lane;
+
+ switch (num_of_lanes) {
+ case 1:
+ lane = 0;
+ break;
+ case 2:
+ lane = 1;
+ break;
+ case 4:
+ lane = 2;
+ break;
+ default:
+ return -1;
+ }
+
+ /* configure XG MAC mode */
+ val = readl(port->priv->xpcs_base + MVPP22_XPCS_GLOBAL_CFG_0_REG);
+ val &= ~MVPP22_XPCS_PCSMODE_MASK;
+ val &= ~MVPP22_XPCS_LANEACTIVE_MASK;
+ val |= (2 * lane) << MVPP22_XPCS_LANEACTIVE_OFFS;
+ writel(val, port->priv->xpcs_base + MVPP22_XPCS_GLOBAL_CFG_0_REG);
+
+ return 0;
+}
+
+static int gop_mpcs_mode(struct mvpp2_port *port)
+{
+ u32 val;
+
+ /* configure PCS40G COMMON CONTROL */
+ val = readl(port->priv->mpcs_base + PCS40G_COMMON_CONTROL);
+ val &= ~FORWARD_ERROR_CORRECTION_MASK;
+ writel(val, port->priv->mpcs_base + PCS40G_COMMON_CONTROL);
+
+ /* configure PCS CLOCK RESET */
+ val = readl(port->priv->mpcs_base + PCS_CLOCK_RESET);
+ val &= ~CLK_DIVISION_RATIO_MASK;
+ val |= 1 << CLK_DIVISION_RATIO_OFFS;
+ writel(val, port->priv->mpcs_base + PCS_CLOCK_RESET);
+
+ val &= ~CLK_DIV_PHASE_SET_MASK;
+ val |= MAC_CLK_RESET_MASK;
+ val |= RX_SD_CLK_RESET_MASK;
+ val |= TX_SD_CLK_RESET_MASK;
+ writel(val, port->priv->mpcs_base + PCS_CLOCK_RESET);
+
+ return 0;
+}
+
+/* Set the internal mux's to the required MAC in the GOP */
+static int gop_xlg_mac_mode_cfg(struct mvpp2_port *port, int num_of_act_lanes)
+{
+ u32 val;
+
+ /* configure 10G MAC mode */
+ val = readl(port->base + MVPP22_XLG_CTRL0_REG);
+ val |= MVPP22_XLG_RX_FC_EN;
+ writel(val, port->base + MVPP22_XLG_CTRL0_REG);
+
+ val = readl(port->base + MVPP22_XLG_CTRL3_REG);
+ val &= ~MVPP22_XLG_CTRL3_MACMODESELECT_MASK;
+ val |= MVPP22_XLG_CTRL3_MACMODESELECT_10GMAC;
+ writel(val, port->base + MVPP22_XLG_CTRL3_REG);
+
+ /* read - modify - write */
+ val = readl(port->base + MVPP22_XLG_CTRL4_REG);
+ val &= ~MVPP22_XLG_MODE_DMA_1G;
+ val |= MVPP22_XLG_FORWARD_PFC_EN;
+ val |= MVPP22_XLG_FORWARD_802_3X_FC_EN;
+ val &= ~MVPP22_XLG_EN_IDLE_CHECK_FOR_LINK;
+ writel(val, port->base + MVPP22_XLG_CTRL4_REG);
+
+ /* Jumbo frame support: 0x1400 * 2 = 0x2800 bytes */
+ val = readl(port->base + MVPP22_XLG_CTRL1_REG);
+ val &= ~MVPP22_XLG_MAX_RX_SIZE_MASK;
+ val |= 0x1400 << MVPP22_XLG_MAX_RX_SIZE_OFFS;
+ writel(val, port->base + MVPP22_XLG_CTRL1_REG);
+
+ /* unmask link change interrupt */
+ val = readl(port->base + MVPP22_XLG_INTERRUPT_MASK_REG);
+ val |= MVPP22_XLG_INTERRUPT_LINK_CHANGE;
+ val |= 1; /* unmask summary bit */
+ writel(val, port->base + MVPP22_XLG_INTERRUPT_MASK_REG);
+
+ return 0;
+}
+
+/* Set PCS to reset or exit from reset */
+static int gop_xpcs_reset(struct mvpp2_port *port, int reset)
+{
+ u32 val;
+
+ /* read - modify - write */
+ val = readl(port->priv->xpcs_base + MVPP22_XPCS_GLOBAL_CFG_0_REG);
+ if (reset)
+ val &= ~MVPP22_XPCS_PCSRESET;
+ else
+ val |= MVPP22_XPCS_PCSRESET;
+ writel(val, port->priv->xpcs_base + MVPP22_XPCS_GLOBAL_CFG_0_REG);
+
+ return 0;
+}
+
+/* Set the MAC to reset or exit from reset */
+static int gop_xlg_mac_reset(struct mvpp2_port *port, int reset)
+{
+ u32 val;
+
+ /* read - modify - write */
+ val = readl(port->base + MVPP22_XLG_CTRL0_REG);
+ if (reset)
+ val &= ~MVPP22_XLG_MAC_RESETN;
+ else
+ val |= MVPP22_XLG_MAC_RESETN;
+ writel(val, port->base + MVPP22_XLG_CTRL0_REG);
+
+ return 0;
+}
+
+/*
+ * gop_port_init
+ *
+ * Init physical port. Configures the port mode and all it's elements
+ * accordingly.
+ * Does not verify that the selected mode/port number is valid at the
+ * core level.
+ */
+static int gop_port_init(struct mvpp2_port *port)
+{
+ int mac_num = port->gop_id;
+ int num_of_act_lanes;
+
+ if (mac_num >= MVPP22_GOP_MAC_NUM) {
+ netdev_err(NULL, "%s: illegal port number %d", __func__,
+ mac_num);
+ return -1;
+ }
+
+ switch (port->phy_interface) {
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ gop_gmac_reset(port, 1);
+
+ /* configure PCS */
+ gop_gpcs_mode_cfg(port, 0);
+ gop_bypass_clk_cfg(port, 1);
+
+ /* configure MAC */
+ gop_gmac_mode_cfg(port);
+ /* pcs unreset */
+ gop_gpcs_reset(port, 0);
+
+ /* mac unreset */
+ gop_gmac_reset(port, 0);
+ break;
+
+ case PHY_INTERFACE_MODE_SGMII:
+ /* configure PCS */
+ gop_gpcs_mode_cfg(port, 1);
+
+ /* configure MAC */
+ gop_gmac_mode_cfg(port);
+ /* select proper Mac mode */
+ gop_xlg_2_gig_mac_cfg(port);
+
+ /* pcs unreset */
+ gop_gpcs_reset(port, 0);
+ /* mac unreset */
+ gop_gmac_reset(port, 0);
+ break;
+
+ case PHY_INTERFACE_MODE_SFI:
+ num_of_act_lanes = 2;
+ mac_num = 0;
+ /* configure PCS */
+ gop_xpcs_mode(port, num_of_act_lanes);
+ gop_mpcs_mode(port);
+ /* configure MAC */
+ gop_xlg_mac_mode_cfg(port, num_of_act_lanes);
+
+ /* pcs unreset */
+ gop_xpcs_reset(port, 0);
+
+ /* mac unreset */
+ gop_xlg_mac_reset(port, 0);
+ break;
+
+ default:
+ netdev_err(NULL, "%s: Requested port mode (%d) not supported\n",
+ __func__, port->phy_interface);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void gop_xlg_mac_port_enable(struct mvpp2_port *port, int enable)
+{
+ u32 val;
+
+ val = readl(port->base + MVPP22_XLG_CTRL0_REG);
+ if (enable) {
+ /* Enable port and MIB counters update */
+ val |= MVPP22_XLG_PORT_EN;
+ val &= ~MVPP22_XLG_MIBCNT_DIS;
+ } else {
+ /* Disable port */
+ val &= ~MVPP22_XLG_PORT_EN;
+ }
+ writel(val, port->base + MVPP22_XLG_CTRL0_REG);
+}
+
+static void gop_port_enable(struct mvpp2_port *port, int enable)
+{
+ switch (port->phy_interface) {
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_SGMII:
+ if (enable)
+ mvpp2_port_enable(port);
+ else
+ mvpp2_port_disable(port);
+ break;
+
+ case PHY_INTERFACE_MODE_SFI:
+ gop_xlg_mac_port_enable(port, enable);
+
+ break;
+ default:
+ netdev_err(NULL, "%s: Wrong port mode (%d)\n", __func__,
+ port->phy_interface);
+ return;
+ }
+}
+
+/* RFU1 functions */
+static inline u32 gop_rfu1_read(struct mvpp2 *priv, u32 offset)
+{
+ return readl(priv->rfu1_base + offset);
+}
+
+static inline void gop_rfu1_write(struct mvpp2 *priv, u32 offset, u32 data)
+{
+ writel(data, priv->rfu1_base + offset);
+}
+
+static u32 mvpp2_netc_cfg_create(int gop_id, phy_interface_t phy_type)
+{
+ u32 val = 0;
+
+ if (gop_id == 2) {
+ if (phy_type == PHY_INTERFACE_MODE_SGMII)
+ val |= MV_NETC_GE_MAC2_SGMII;
+ }
+
+ if (gop_id == 3) {
+ if (phy_type == PHY_INTERFACE_MODE_SGMII)
+ val |= MV_NETC_GE_MAC3_SGMII;
+ else if (phy_type == PHY_INTERFACE_MODE_RGMII ||
+ phy_type == PHY_INTERFACE_MODE_RGMII_ID)
+ val |= MV_NETC_GE_MAC3_RGMII;
+ }
+
+ return val;
+}
+
+static void gop_netc_active_port(struct mvpp2 *priv, int gop_id, u32 val)
+{
+ u32 reg;
+
+ reg = gop_rfu1_read(priv, NETCOMP_PORTS_CONTROL_1_REG);
+ reg &= ~(NETC_PORTS_ACTIVE_MASK(gop_id));
+
+ val <<= NETC_PORTS_ACTIVE_OFFSET(gop_id);
+ val &= NETC_PORTS_ACTIVE_MASK(gop_id);
+
+ reg |= val;
+
+ gop_rfu1_write(priv, NETCOMP_PORTS_CONTROL_1_REG, reg);
+}
+
+static void gop_netc_mii_mode(struct mvpp2 *priv, int gop_id, u32 val)
+{
+ u32 reg;
+
+ reg = gop_rfu1_read(priv, NETCOMP_CONTROL_0_REG);
+ reg &= ~NETC_GBE_PORT1_MII_MODE_MASK;
+
+ val <<= NETC_GBE_PORT1_MII_MODE_OFFS;
+ val &= NETC_GBE_PORT1_MII_MODE_MASK;
+
+ reg |= val;
+
+ gop_rfu1_write(priv, NETCOMP_CONTROL_0_REG, reg);
+}
+
+static void gop_netc_gop_reset(struct mvpp2 *priv, u32 val)
+{
+ u32 reg;
+
+ reg = gop_rfu1_read(priv, GOP_SOFT_RESET_1_REG);
+ reg &= ~NETC_GOP_SOFT_RESET_MASK;
+
+ val <<= NETC_GOP_SOFT_RESET_OFFS;
+ val &= NETC_GOP_SOFT_RESET_MASK;
+
+ reg |= val;
+
+ gop_rfu1_write(priv, GOP_SOFT_RESET_1_REG, reg);
+}
+
+static void gop_netc_gop_clock_logic_set(struct mvpp2 *priv, u32 val)
+{
+ u32 reg;
+
+ reg = gop_rfu1_read(priv, NETCOMP_PORTS_CONTROL_0_REG);
+ reg &= ~NETC_CLK_DIV_PHASE_MASK;
+
+ val <<= NETC_CLK_DIV_PHASE_OFFS;
+ val &= NETC_CLK_DIV_PHASE_MASK;
+
+ reg |= val;
+
+ gop_rfu1_write(priv, NETCOMP_PORTS_CONTROL_0_REG, reg);
+}
+
+static void gop_netc_port_rf_reset(struct mvpp2 *priv, int gop_id, u32 val)
+{
+ u32 reg;
+
+ reg = gop_rfu1_read(priv, NETCOMP_PORTS_CONTROL_1_REG);
+ reg &= ~(NETC_PORT_GIG_RF_RESET_MASK(gop_id));
+
+ val <<= NETC_PORT_GIG_RF_RESET_OFFS(gop_id);
+ val &= NETC_PORT_GIG_RF_RESET_MASK(gop_id);
+
+ reg |= val;
+
+ gop_rfu1_write(priv, NETCOMP_PORTS_CONTROL_1_REG, reg);
+}
+
+static void gop_netc_gbe_sgmii_mode_select(struct mvpp2 *priv, int gop_id,
+ u32 val)
+{
+ u32 reg, mask, offset;
+
+ if (gop_id == 2) {
+ mask = NETC_GBE_PORT0_SGMII_MODE_MASK;
+ offset = NETC_GBE_PORT0_SGMII_MODE_OFFS;
+ } else {
+ mask = NETC_GBE_PORT1_SGMII_MODE_MASK;
+ offset = NETC_GBE_PORT1_SGMII_MODE_OFFS;
+ }
+ reg = gop_rfu1_read(priv, NETCOMP_CONTROL_0_REG);
+ reg &= ~mask;
+
+ val <<= offset;
+ val &= mask;
+
+ reg |= val;
+
+ gop_rfu1_write(priv, NETCOMP_CONTROL_0_REG, reg);
+}
+
+static void gop_netc_bus_width_select(struct mvpp2 *priv, u32 val)
+{
+ u32 reg;
+
+ reg = gop_rfu1_read(priv, NETCOMP_PORTS_CONTROL_0_REG);
+ reg &= ~NETC_BUS_WIDTH_SELECT_MASK;
+
+ val <<= NETC_BUS_WIDTH_SELECT_OFFS;
+ val &= NETC_BUS_WIDTH_SELECT_MASK;
+
+ reg |= val;
+
+ gop_rfu1_write(priv, NETCOMP_PORTS_CONTROL_0_REG, reg);
+}
+
+static void gop_netc_sample_stages_timing(struct mvpp2 *priv, u32 val)
+{
+ u32 reg;
+
+ reg = gop_rfu1_read(priv, NETCOMP_PORTS_CONTROL_0_REG);
+ reg &= ~NETC_GIG_RX_DATA_SAMPLE_MASK;
+
+ val <<= NETC_GIG_RX_DATA_SAMPLE_OFFS;
+ val &= NETC_GIG_RX_DATA_SAMPLE_MASK;
+
+ reg |= val;
+
+ gop_rfu1_write(priv, NETCOMP_PORTS_CONTROL_0_REG, reg);
+}
+
+static void gop_netc_mac_to_xgmii(struct mvpp2 *priv, int gop_id,
+ enum mv_netc_phase phase)
+{
+ switch (phase) {
+ case MV_NETC_FIRST_PHASE:
+ /* Set Bus Width to HB mode = 1 */
+ gop_netc_bus_width_select(priv, 1);
+ /* Select RGMII mode */
+ gop_netc_gbe_sgmii_mode_select(priv, gop_id, MV_NETC_GBE_XMII);
+ break;
+
+ case MV_NETC_SECOND_PHASE:
+ /* De-assert the relevant port HB reset */
+ gop_netc_port_rf_reset(priv, gop_id, 1);
+ break;
+ }
+}
+
+static void gop_netc_mac_to_sgmii(struct mvpp2 *priv, int gop_id,
+ enum mv_netc_phase phase)
+{
+ switch (phase) {
+ case MV_NETC_FIRST_PHASE:
+ /* Set Bus Width to HB mode = 1 */
+ gop_netc_bus_width_select(priv, 1);
+ /* Select SGMII mode */
+ if (gop_id >= 1) {
+ gop_netc_gbe_sgmii_mode_select(priv, gop_id,
+ MV_NETC_GBE_SGMII);
+ }
+
+ /* Configure the sample stages */
+ gop_netc_sample_stages_timing(priv, 0);
+ /* Configure the ComPhy Selector */
+ /* gop_netc_com_phy_selector_config(netComplex); */
+ break;
+
+ case MV_NETC_SECOND_PHASE:
+ /* De-assert the relevant port HB reset */
+ gop_netc_port_rf_reset(priv, gop_id, 1);
+ break;
+ }
+}
+
+static int gop_netc_init(struct mvpp2 *priv, enum mv_netc_phase phase)
+{
+ u32 c = priv->netc_config;
+
+ if (c & MV_NETC_GE_MAC2_SGMII)
+ gop_netc_mac_to_sgmii(priv, 2, phase);
+ else
+ gop_netc_mac_to_xgmii(priv, 2, phase);
+
+ if (c & MV_NETC_GE_MAC3_SGMII) {
+ gop_netc_mac_to_sgmii(priv, 3, phase);
+ } else {
+ gop_netc_mac_to_xgmii(priv, 3, phase);
+ if (c & MV_NETC_GE_MAC3_RGMII)
+ gop_netc_mii_mode(priv, 3, MV_NETC_GBE_RGMII);
+ else
+ gop_netc_mii_mode(priv, 3, MV_NETC_GBE_MII);
+ }
+
+ /* Activate gop ports 0, 2, 3 */
+ gop_netc_active_port(priv, 0, 1);
+ gop_netc_active_port(priv, 2, 1);
+ gop_netc_active_port(priv, 3, 1);
+
+ if (phase == MV_NETC_SECOND_PHASE) {
+ /* Enable the GOP internal clock logic */
+ gop_netc_gop_clock_logic_set(priv, 1);
+ /* De-assert GOP unit reset */
+ gop_netc_gop_reset(priv, 1);
+ }
+
+ return 0;
+}
+
+/* Set defaults to the MVPP2 port */
+static void mvpp2_defaults_set(struct mvpp2_port *port)
+{
+ int tx_port_num, val, queue, ptxq, lrxq;
+
+ if (port->priv->hw_version == MVPP21) {
+ /* Configure port to loopback if needed */
+ if (port->flags & MVPP2_F_LOOPBACK)
+ mvpp2_port_loopback_set(port);
+
+ /* Update TX FIFO MIN Threshold */
+ val = readl(port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+ val &= ~MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK;
+ /* Min. TX threshold must be less than minimal packet length */
+ val |= MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(64 - 4 - 2);
+ writel(val, port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+ }
+
+ /* Disable Legacy WRR, Disable EJP, Release from reset */
+ tx_port_num = mvpp2_egress_port(port);
+ mvpp2_write(port->priv, MVPP2_TXP_SCHED_PORT_INDEX_REG,
+ tx_port_num);
+ mvpp2_write(port->priv, MVPP2_TXP_SCHED_CMD_1_REG, 0);
+
+ /* Close bandwidth for all queues */
+ for (queue = 0; queue < MVPP2_MAX_TXQ; queue++) {
+ ptxq = mvpp2_txq_phys(port->id, queue);
+ mvpp2_write(port->priv,
+ MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(ptxq), 0);
+ }
+
+ /* Set refill period to 1 usec, refill tokens
+ * and bucket size to maximum
+ */
+ mvpp2_write(port->priv, MVPP2_TXP_SCHED_PERIOD_REG, 0xc8);
+ val = mvpp2_read(port->priv, MVPP2_TXP_SCHED_REFILL_REG);
+ val &= ~MVPP2_TXP_REFILL_PERIOD_ALL_MASK;
+ val |= MVPP2_TXP_REFILL_PERIOD_MASK(1);
+ val |= MVPP2_TXP_REFILL_TOKENS_ALL_MASK;
+ mvpp2_write(port->priv, MVPP2_TXP_SCHED_REFILL_REG, val);
+ val = MVPP2_TXP_TOKEN_SIZE_MAX;
+ mvpp2_write(port->priv, MVPP2_TXP_SCHED_TOKEN_SIZE_REG, val);
+
+ /* Set MaximumLowLatencyPacketSize value to 256 */
+ mvpp2_write(port->priv, MVPP2_RX_CTRL_REG(port->id),
+ MVPP2_RX_USE_PSEUDO_FOR_CSUM_MASK |
+ MVPP2_RX_LOW_LATENCY_PKT_SIZE(256));
+
+ /* Enable Rx cache snoop */
+ for (lrxq = 0; lrxq < rxq_number; lrxq++) {
+ queue = port->rxqs[lrxq]->id;
+ val = mvpp2_read(port->priv, MVPP2_RXQ_CONFIG_REG(queue));
+ val |= MVPP2_SNOOP_PKT_SIZE_MASK |
+ MVPP2_SNOOP_BUF_HDR_MASK;
+ mvpp2_write(port->priv, MVPP2_RXQ_CONFIG_REG(queue), val);
+ }
+}
+
+/* Enable/disable receiving packets */
+static void mvpp2_ingress_enable(struct mvpp2_port *port)
+{
+ u32 val;
+ int lrxq, queue;
+
+ for (lrxq = 0; lrxq < rxq_number; lrxq++) {
+ queue = port->rxqs[lrxq]->id;
+ val = mvpp2_read(port->priv, MVPP2_RXQ_CONFIG_REG(queue));
+ val &= ~MVPP2_RXQ_DISABLE_MASK;
+ mvpp2_write(port->priv, MVPP2_RXQ_CONFIG_REG(queue), val);
+ }
+}
+
+static void mvpp2_ingress_disable(struct mvpp2_port *port)
+{
+ u32 val;
+ int lrxq, queue;
+
+ for (lrxq = 0; lrxq < rxq_number; lrxq++) {
+ queue = port->rxqs[lrxq]->id;
+ val = mvpp2_read(port->priv, MVPP2_RXQ_CONFIG_REG(queue));
+ val |= MVPP2_RXQ_DISABLE_MASK;
+ mvpp2_write(port->priv, MVPP2_RXQ_CONFIG_REG(queue), val);
+ }
+}
+
+/* Enable transmit via physical egress queue
+ * - HW starts take descriptors from DRAM
+ */
+static void mvpp2_egress_enable(struct mvpp2_port *port)
+{
+ u32 qmap;
+ int queue;
+ int tx_port_num = mvpp2_egress_port(port);
+
+ /* Enable all initialized TXs. */
+ qmap = 0;
+ for (queue = 0; queue < txq_number; queue++) {
+ struct mvpp2_tx_queue *txq = port->txqs[queue];
+
+ if (txq->descs != NULL)
+ qmap |= (1 << queue);
+ }
+
+ mvpp2_write(port->priv, MVPP2_TXP_SCHED_PORT_INDEX_REG, tx_port_num);
+ mvpp2_write(port->priv, MVPP2_TXP_SCHED_Q_CMD_REG, qmap);
+}
+
+/* Disable transmit via physical egress queue
+ * - HW doesn't take descriptors from DRAM
+ */
+static void mvpp2_egress_disable(struct mvpp2_port *port)
+{
+ u32 reg_data;
+ int delay;
+ int tx_port_num = mvpp2_egress_port(port);
+
+ /* Issue stop command for active channels only */
+ mvpp2_write(port->priv, MVPP2_TXP_SCHED_PORT_INDEX_REG, tx_port_num);
+ reg_data = (mvpp2_read(port->priv, MVPP2_TXP_SCHED_Q_CMD_REG)) &
+ MVPP2_TXP_SCHED_ENQ_MASK;
+ if (reg_data != 0)
+ mvpp2_write(port->priv, MVPP2_TXP_SCHED_Q_CMD_REG,
+ (reg_data << MVPP2_TXP_SCHED_DISQ_OFFSET));
+
+ /* Wait for all Tx activity to terminate. */
+ delay = 0;
+ do {
+ if (delay >= MVPP2_TX_DISABLE_TIMEOUT_MSEC) {
+ netdev_warn(port->dev,
+ "Tx stop timed out, status=0x%08x\n",
+ reg_data);
+ break;
+ }
+ mdelay(1);
+ delay++;
+
+ /* Check port TX Command register that all
+ * Tx queues are stopped
+ */
+ reg_data = mvpp2_read(port->priv, MVPP2_TXP_SCHED_Q_CMD_REG);
+ } while (reg_data & MVPP2_TXP_SCHED_ENQ_MASK);