From 4189373a3d7e3604f4b3991cdbfd0ea4c23a3002 Mon Sep 17 00:00:00 2001 From: Stefan Chulski Date: Wed, 9 Aug 2017 10:37:43 +0300 Subject: net: mvpp2x: Add GPIO configuration support This patch add GPIO configuration support in mvpp2x driver. Driver will handle 10G SFP gpio reset and SFP TX disable. GPIO pins should be set in device tree. Signed-off-by: Stefan Chulski Tested-by: iSoC Platform CI Reviewed-by: Kostya Porotchkin Reviewed-by: Igal Liberman Acked-by: Joe Hershberger Signed-off-by: Stefan Roese diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index 1b46218..2198b73 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -30,6 +30,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -985,6 +986,10 @@ struct mvpp2_port { phy_interface_t phy_interface; int phy_node; int phyaddr; +#ifdef CONFIG_DM_GPIO + struct gpio_desc phy_reset_gpio; + struct gpio_desc phy_tx_disable_gpio; +#endif int init; unsigned int link; unsigned int duplex; @@ -4765,6 +4770,13 @@ static int phy_info_parse(struct udevice *dev, struct mvpp2_port *port) return -EINVAL; } +#ifdef CONFIG_DM_GPIO + gpio_request_by_name(dev, "phy-reset-gpios", 0, + &port->phy_reset_gpio, GPIOD_IS_OUT); + gpio_request_by_name(dev, "marvell,sfp-tx-disable-gpio", 0, + &port->phy_tx_disable_gpio, GPIOD_IS_OUT); +#endif + /* * ToDo: * Not sure if this DT property "phy-speed" will get accepted, so @@ -4786,6 +4798,21 @@ static int phy_info_parse(struct udevice *dev, struct mvpp2_port *port) return 0; } +#ifdef CONFIG_DM_GPIO +/* Port GPIO initialization */ +static void mvpp2_gpio_init(struct mvpp2_port *port) +{ + if (dm_gpio_is_valid(&port->phy_reset_gpio)) { + dm_gpio_set_value(&port->phy_reset_gpio, 0); + udelay(1000); + dm_gpio_set_value(&port->phy_reset_gpio, 1); + } + + if (dm_gpio_is_valid(&port->phy_tx_disable_gpio)) + dm_gpio_set_value(&port->phy_tx_disable_gpio, 0); +} +#endif + /* Ports initialization */ static int mvpp2_port_probe(struct udevice *dev, struct mvpp2_port *port, @@ -4804,6 +4831,10 @@ static int mvpp2_port_probe(struct udevice *dev, } mvpp2_port_power_up(port); +#ifdef CONFIG_DM_GPIO + mvpp2_gpio_init(port); +#endif + priv->port_list[port->id] = port; return 0; } -- cgit v0.10.2 From 377883f16d360f7edf766ebf4d025db1b7f0fff0 Mon Sep 17 00:00:00 2001 From: Stefan Chulski Date: Wed, 9 Aug 2017 10:37:44 +0300 Subject: net: mvpp2x: fix phy connected to wrong mdio issue A8K marvell SoC has two South Bridge communication controllers(CP0 and CP1). Each communication controller has packet processor ports and MDIO. On MACHIATOBin board ports from CP1 are connected to mdio on CP0. Issue: Wrong base address is assigned to MDIO interface during probe. Fix: Get MDIO address from PHY handler parent base address. This should be refined in the future when MDIO driver is implemented. Signed-off-by: Stefan Chulski Tested-by: iSoC Platform CI Reviewed-by: Igal Liberman Acked-by: Joe Hershberger Signed-off-by: Stefan Roese diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index 2198b73..1264f14 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -31,6 +31,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -4739,10 +4740,11 @@ static int phy_info_parse(struct udevice *dev, struct mvpp2_port *port) { int port_node = dev_of_offset(dev); const char *phy_mode_str; - int phy_node; + int phy_node, mdio_off, cp_node; u32 id; u32 phyaddr = 0; int phy_mode = -1; + u64 mdio_addr; phy_node = fdtdec_lookup_phandle(gd->fdt_blob, port_node, "phy"); @@ -4752,6 +4754,28 @@ static int phy_info_parse(struct udevice *dev, struct mvpp2_port *port) dev_err(&pdev->dev, "could not find phy address\n"); return -1; } + mdio_off = fdt_parent_offset(gd->fdt_blob, phy_node); + + /* TODO: This WA for mdio issue. U-boot 2017 don't have + * mdio driver and on MACHIATOBin board ports from CP1 + * connected to mdio on CP0. + * WA is to get mdio address from phy handler parent + * base address. WA should be removed after + * mdio driver implementation. + */ + mdio_addr = fdtdec_get_uint(gd->fdt_blob, + mdio_off, "reg", 0); + + cp_node = fdt_parent_offset(gd->fdt_blob, mdio_off); + mdio_addr |= fdt_get_base_address((void *)gd->fdt_blob, + cp_node); + + port->priv->mdio_base = (void *)mdio_addr; + + if (port->priv->mdio_base < 0) { + dev_err(&pdev->dev, "could not find mdio base address\n"); + return -1; + } } else { phy_node = 0; } -- cgit v0.10.2 From 73f592fb724153f8afbd79098f918ff548fda7ef Mon Sep 17 00:00:00 2001 From: Stefan Chulski Date: Wed, 9 Aug 2017 10:37:45 +0300 Subject: net: mvpp2x: Enable GoP packet padding in TX This patch enables padding of packets shorter than 64B in TX(set by default). Disabling of padding causes crashes on MACCIATO board. Signed-off-by: Stefan Chulski Tested-by: iSoC Platform CI Reviewed-by: Igal Liberman Acked-by: Joe Hershberger Signed-off-by: Stefan Roese diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index 1264f14..3083111 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -3063,10 +3063,6 @@ static void gop_gmac_sgmii2_5_cfg(struct mvpp2_port *port) val |= MVPP2_GMAC_CTRL4_QSGMII_BYPASS_ACTIVE_MASK; writel(val, port->base + MVPP2_GMAC_CTRL_4_REG); - val = readl(port->base + MVPP2_GMAC_CTRL_2_REG); - val |= MVPP2_GMAC_PORT_DIS_PADING_MASK; - writel(val, port->base + MVPP2_GMAC_CTRL_2_REG); - val = readl(port->base + MVPP2_GMAC_CTRL_0_REG); /* * Configure GIG MAC to 1000Base-X mode connected to a fiber @@ -3109,10 +3105,6 @@ static void gop_gmac_sgmii_cfg(struct mvpp2_port *port) val |= MVPP2_GMAC_CTRL4_QSGMII_BYPASS_ACTIVE_MASK; writel(val, port->base + MVPP2_GMAC_CTRL_4_REG); - val = readl(port->base + MVPP2_GMAC_CTRL_2_REG); - val |= MVPP2_GMAC_PORT_DIS_PADING_MASK; - writel(val, port->base + MVPP2_GMAC_CTRL_2_REG); - val = readl(port->base + MVPP2_GMAC_CTRL_0_REG); /* configure GIG MAC to SGMII mode */ val &= ~MVPP2_GMAC_PORT_TYPE_MASK; @@ -3151,10 +3143,6 @@ static void gop_gmac_rgmii_cfg(struct mvpp2_port *port) 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_2_REG); - val &= ~MVPP2_GMAC_PORT_DIS_PADING_MASK; - writel(val, port->base + MVPP2_GMAC_CTRL_2_REG); - val = readl(port->base + MVPP2_GMAC_CTRL_0_REG); /* configure GIG MAC to SGMII mode */ val &= ~MVPP2_GMAC_PORT_TYPE_MASK; -- cgit v0.10.2 From bb915c843f28573bb31496644e7f7e2c0a066fd8 Mon Sep 17 00:00:00 2001 From: Stefan Chulski Date: Wed, 9 Aug 2017 10:37:46 +0300 Subject: net: mvpp2x: fix BM configuration overrun issue Issue: BM counters were overrun by probe that called per Network interface and caused release of wrong number of buffers during remove procedure. Fix: Use probe_done and num_ports to call init and remove procedure once per communication controller. Signed-off-by: Stefan Chulski Tested-by: iSoC Platform CI Reviewed-by: Igal Liberman Acked-by: Joe Hershberger Signed-off-by: Stefan Roese diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index 3083111..426b2c2 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -942,6 +942,7 @@ struct mvpp2 { struct mii_dev *bus; int probe_done; + u8 num_ports; }; struct mvpp2_pcpu_stats { @@ -4848,6 +4849,7 @@ static int mvpp2_port_probe(struct udevice *dev, #endif priv->port_list[port->id] = port; + priv->num_ports++; return 0; } @@ -5512,10 +5514,8 @@ static int mvpp2_probe(struct udevice *dev) int err; /* Only call the probe function for the parent once */ - if (!priv->probe_done) { + if (!priv->probe_done) err = mvpp2_base_probe(dev->parent); - priv->probe_done = 1; - } port->priv = dev_get_priv(dev->parent); @@ -5553,11 +5553,15 @@ static int mvpp2_probe(struct udevice *dev) gop_port_init(port); } - /* Initialize network controller */ - err = mvpp2_init(dev, priv); - if (err < 0) { - dev_err(&pdev->dev, "failed to initialize controller\n"); - return err; + if (!priv->probe_done) { + /* Initialize network controller */ + err = mvpp2_init(dev, priv); + if (err < 0) { + dev_err(&pdev->dev, "failed to initialize controller\n"); + return err; + } + priv->num_ports = 0; + priv->probe_done = 1; } err = mvpp2_port_probe(dev, port, dev_of_offset(dev), priv); @@ -5585,6 +5589,11 @@ static int mvpp2_remove(struct udevice *dev) struct mvpp2 *priv = port->priv; int i; + priv->num_ports--; + + if (priv->num_ports) + return 0; + for (i = 0; i < MVPP2_BM_POOLS_NUM; i++) mvpp2_bm_pool_destroy(dev, priv, &priv->bm_pools[i]); -- cgit v0.10.2 From f0e970fd2a5f802f7f2553a13a2f1e4e4bf7d5ee Mon Sep 17 00:00:00 2001 From: Stefan Chulski Date: Wed, 9 Aug 2017 10:37:47 +0300 Subject: net: mvpp2x: decrease size of AGGR_TXQ and CPU_DESC_CHUNK U-boot use single physical tx queue with size 16 descriptors. So aggregated tx queue size should be equal to physical tx queue and cpu descriptor chunk(number of descriptors delivered from physical tx queue to aggregated tx queue by one chunk) shouldn't be larger than physical tx queue. Fix: Set AGGR_TXQ and CPU_DESC_CHUNK to be 16 descriptors, same as physical TXQ. Signed-off-by: Stefan Chulski Tested-by: iSoC Platform CI Reviewed-by: Nadav Haklai Reviewed-by: Igal Liberman Acked-by: Joe Hershberger Signed-off-by: Stefan Roese diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index 426b2c2..355eb39 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -617,10 +617,10 @@ enum mv_netc_lanes { #define MVPP2_MAX_TXD 16 /* Amount of Tx descriptors that can be reserved at once by CPU */ -#define MVPP2_CPU_DESC_CHUNK 64 +#define MVPP2_CPU_DESC_CHUNK 16 /* Max number of Tx descriptors in each aggregated queue */ -#define MVPP2_AGGR_TXQ_SIZE 256 +#define MVPP2_AGGR_TXQ_SIZE 16 /* Descriptor aligned size */ #define MVPP2_DESC_ALIGNED_SIZE 32 -- cgit v0.10.2 From d4b0e0082914215daaffd6c0ee19dad934a2d90b Mon Sep 17 00:00:00 2001 From: Stefan Chulski Date: Wed, 9 Aug 2017 10:37:48 +0300 Subject: net: mvpp2x: remove MBUS configurations from MvPP22 driver MBUS driver were replaced by AXI in PPv22 and relevant only for PPv21. Signed-off-by: Stefan Chulski Tested-by: iSoC Platform CI Reviewed-by: Nadav Haklai Reviewed-by: Igal Liberman Acked-by: Joe Hershberger Signed-off-by: Stefan Roese diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index 355eb39..2e5a194 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -5014,13 +5014,14 @@ static int mvpp2_init(struct udevice *dev, struct mvpp2 *priv) return -EINVAL; } - /* MBUS windows configuration */ - dram_target_info = mvebu_mbus_dram_info(); - if (dram_target_info) - mvpp2_conf_mbus_windows(dram_target_info, priv); - if (priv->hw_version == MVPP22) mvpp2_axi_init(priv); + else { + /* MBUS windows configuration */ + dram_target_info = mvebu_mbus_dram_info(); + if (dram_target_info) + mvpp2_conf_mbus_windows(dram_target_info, priv); + } if (priv->hw_version == MVPP21) { /* Disable HW PHY polling */ -- cgit v0.10.2 From 16f18d2a4decd57aa5f6eb293f163adcb69c73da Mon Sep 17 00:00:00 2001 From: Stefan Chulski Date: Wed, 9 Aug 2017 10:37:49 +0300 Subject: net: mvpp2x: Remove IRQ configuration from U-Boot Remove IRQ configuration from U-Boot PP driver. U-Boot don't use interrupts and configuration of IRQ in U-Boot caused crashes in Linux shared interrupt mode. Also interrupt use is redundant in RX routine since a single RX queue is used. Signed-off-by: Stefan Chulski Tested-by: iSoC Platform CI Reviewed-by: Nadav Haklai Reviewed-by: Igal Liberman Acked-by: Joe Hershberger Signed-off-by: Stefan Roese diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index 2e5a194..3fca987 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -4681,20 +4681,6 @@ static int mvpp2_port_init(struct udevice *dev, struct mvpp2_port *port) port->rxqs[queue] = rxq; } - /* Configure Rx queue group interrupt for this port */ - if (priv->hw_version == MVPP21) { - mvpp2_write(priv, MVPP21_ISR_RXQ_GROUP_REG(port->id), - CONFIG_MV_ETH_RXQ); - } else { - u32 val; - - val = (port->id << MVPP22_ISR_RXQ_GROUP_INDEX_GROUP_OFFSET); - mvpp2_write(priv, MVPP22_ISR_RXQ_GROUP_INDEX_REG, val); - - val = (CONFIG_MV_ETH_RXQ << - MVPP22_ISR_RXQ_SUB_GROUP_SIZE_OFFSET); - mvpp2_write(priv, MVPP22_ISR_RXQ_SUB_GROUP_CONFIG_REG, val); - } /* Create Rx descriptor rings */ for (queue = 0; queue < rxq_number; queue++) { @@ -5058,25 +5044,6 @@ static int mvpp2_init(struct udevice *dev, struct mvpp2 *priv) if (priv->hw_version == MVPP22) mvpp2_tx_fifo_init(priv); - /* Reset Rx queue group interrupt configuration */ - for (i = 0; i < MVPP2_MAX_PORTS; i++) { - if (priv->hw_version == MVPP21) { - mvpp2_write(priv, MVPP21_ISR_RXQ_GROUP_REG(i), - CONFIG_MV_ETH_RXQ); - continue; - } else { - u32 val; - - val = (i << MVPP22_ISR_RXQ_GROUP_INDEX_GROUP_OFFSET); - mvpp2_write(priv, MVPP22_ISR_RXQ_GROUP_INDEX_REG, val); - - val = (CONFIG_MV_ETH_RXQ << - MVPP22_ISR_RXQ_SUB_GROUP_SIZE_OFFSET); - mvpp2_write(priv, - MVPP22_ISR_RXQ_SUB_GROUP_CONFIG_REG, val); - } - } - if (priv->hw_version == MVPP21) writel(MVPP2_EXT_GLOBAL_CTRL_DEFAULT, priv->lms_base + MVPP2_MNG_EXTENDED_GLOBAL_CTRL_REG); @@ -5222,21 +5189,10 @@ static int mvpp2_recv(struct udevice *dev, int flags, uchar **packetp) int pool, rx_bytes, err; int rx_received; struct mvpp2_rx_queue *rxq; - u32 cause_rx_tx, cause_rx, cause_misc; u8 *data; - cause_rx_tx = mvpp2_read(port->priv, - MVPP2_ISR_RX_TX_CAUSE_REG(port->id)); - cause_rx_tx &= ~MVPP2_CAUSE_TXQ_OCCUP_DESC_ALL_MASK; - cause_misc = cause_rx_tx & MVPP2_CAUSE_MISC_SUM_MASK; - if (!cause_rx_tx && !cause_misc) - return 0; - - cause_rx = cause_rx_tx & MVPP2_CAUSE_RXQ_OCCUP_DESC_ALL_MASK; - /* Process RX packets */ - cause_rx |= port->pending_cause_rx; - rxq = mvpp2_get_rx_queue(port, cause_rx); + rxq = port->rxqs[0]; /* Get number of received packets and clamp the to-do */ rx_received = mvpp2_rxq_received(port, rxq->id); -- cgit v0.10.2 From 783e78562d3ab55d2ca45d61b02369b198701957 Mon Sep 17 00:00:00 2001 From: Stefan Chulski Date: Wed, 9 Aug 2017 10:37:50 +0300 Subject: net: mvpp2x: Set BM pool high address MVPP22 driver support 64 Bit arch and require BM pool high address configuration. Signed-off-by: Stefan Chulski Tested-by: iSoC Platform CI Reviewed-by: Nadav Haklai Reviewed-by: Igal Liberman Acked-by: Joe Hershberger Signed-off-by: Stefan Roese diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index 3fca987..37056c2 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -316,6 +316,8 @@ do { \ #define MVPP22_BM_ADDR_HIGH_VIRT_RLS_MASK 0xff00 #define MVPP22_BM_ADDR_HIGH_VIRT_RLS_SHIFT 8 #define MVPP22_BM_MC_RLS_REG 0x64d4 +#define MVPP22_BM_POOL_BASE_HIGH_REG 0x6310 +#define MVPP22_BM_POOL_BASE_HIGH_MASK 0xff /* TX Scheduler registers */ #define MVPP2_TXP_SCHED_PORT_INDEX_REG 0x8000 @@ -2594,6 +2596,10 @@ static int mvpp2_bm_pool_create(struct udevice *dev, mvpp2_write(priv, MVPP2_BM_POOL_BASE_REG(bm_pool->id), lower_32_bits(bm_pool->dma_addr)); + if (priv->hw_version == MVPP22) + mvpp2_write(priv, MVPP22_BM_POOL_BASE_HIGH_REG, + (upper_32_bits(bm_pool->dma_addr) & + MVPP22_BM_POOL_BASE_HIGH_MASK)); mvpp2_write(priv, MVPP2_BM_POOL_SIZE_REG(bm_pool->id), size); val = mvpp2_read(priv, MVPP2_BM_POOL_CTRL_REG(bm_pool->id)); -- cgit v0.10.2 From a25962c4171a1b08dc79072fc88c277d89b3b52a Mon Sep 17 00:00:00 2001 From: Stefan Chulski Date: Wed, 9 Aug 2017 10:37:51 +0300 Subject: net: mvpp2x: remove TX drain from transmit routine TX drain in transmit procedure could cause issues due to race between drain procedure and transmition of descriptor between AGGR TXQ and physical TXQ. TXQ will be cleared before moving to Linux by stop procedure. Signed-off-by: Stefan Chulski Tested-by: iSoC Platform CI Reviewed-by: Nadav Haklai Reviewed-by: Igal Liberman Acked-by: Joe Hershberger Signed-off-by: Stefan Roese diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index 37056c2..a7077c7 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -5254,21 +5254,6 @@ static int mvpp2_recv(struct udevice *dev, int flags, uchar **packetp) return rx_bytes; } -/* Drain Txq */ -static void mvpp2_txq_drain(struct mvpp2_port *port, struct mvpp2_tx_queue *txq, - int enable) -{ - u32 val; - - mvpp2_write(port->priv, MVPP2_TXQ_NUM_REG, txq->id); - val = mvpp2_read(port->priv, MVPP2_TXQ_PREF_BUF_REG); - if (enable) - val |= MVPP2_TXQ_DRAIN_EN_MASK; - else - val &= ~MVPP2_TXQ_DRAIN_EN_MASK; - mvpp2_write(port->priv, MVPP2_TXQ_PREF_BUF_REG, val); -} - static int mvpp2_send(struct udevice *dev, void *packet, int length) { struct mvpp2_port *port = dev_get_priv(dev); @@ -5312,9 +5297,6 @@ static int mvpp2_send(struct udevice *dev, void *packet, int length) tx_done = mvpp2_txq_pend_desc_num_get(port, txq); } while (tx_done); - /* Enable TXQ drain */ - mvpp2_txq_drain(port, txq, 1); - timeout = 0; do { if (timeout++ > 10000) { @@ -5324,9 +5306,6 @@ static int mvpp2_send(struct udevice *dev, void *packet, int length) tx_done = mvpp2_txq_sent_desc_proc(port, txq); } while (!tx_done); - /* Disable TXQ drain */ - mvpp2_txq_drain(port, txq, 0); - return 0; } -- cgit v0.10.2 From ceec6c48a472514e6110d07064006258376d4537 Mon Sep 17 00:00:00 2001 From: Stefan Chulski Date: Wed, 9 Aug 2017 10:37:52 +0300 Subject: net: mvpp2x: Set BM poll size once during priv probe Set BM poll size once during priv probe and do not overwrite it during port probe procedure. Pool is common for all CP ports. Signed-off-by: Stefan Chulski Tested-by: iSoC Platform CI Reviewed-by: Nadav Haklai Reviewed-by: Igal Liberman Acked-by: Joe Hershberger Signed-off-by: Stefan Roese diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index a7077c7..233c98b 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -2675,7 +2675,7 @@ static int mvpp2_bm_pools_init(struct udevice *dev, err = mvpp2_bm_pool_create(dev, priv, bm_pool, size); if (err) goto err_unroll_pools; - mvpp2_bm_pool_bufsize_set(priv, bm_pool, 0); + mvpp2_bm_pool_bufsize_set(priv, bm_pool, RX_BUFFER_SIZE); } return 0; @@ -2861,9 +2861,6 @@ mvpp2_bm_pool_use(struct mvpp2_port *port, int pool, enum mvpp2_bm_type type, } } - mvpp2_bm_pool_bufsize_set(port->priv, new_pool, - MVPP2_RX_BUF_SIZE(new_pool->pkt_size)); - return new_pool; } -- cgit v0.10.2