X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fmvpp2.c;h=e3d31a560d54af4697cf8d48d678e878b4dd3fae;hb=f24e482ae0b856fcf18e8e6956ab3f6b59f3693f;hp=a2de1aefc79e99b9472545bb5c5edf97aa98e3cf;hpb=2fe23044cd7e8145dfd995d76cd6b991ad3da2a1;p=oweals%2Fu-boot.git diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index a2de1aefc7..e3d31a560d 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include DECLARE_GLOBAL_DATA_PTR; @@ -314,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 @@ -442,7 +446,7 @@ do { \ /* MPCS registers */ #define PCS40G_COMMON_CONTROL 0x14 -#define FORWARD_ERROR_CORRECTION_MASK BIT(1) +#define FORWARD_ERROR_CORRECTION_MASK BIT(10) #define PCS_CLOCK_RESET 0x14c #define TX_SD_CLK_RESET_MASK BIT(0) @@ -615,10 +619,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 @@ -940,6 +944,7 @@ struct mvpp2 { struct mii_dev *bus; int probe_done; + u8 num_ports; }; struct mvpp2_pcpu_stats { @@ -985,6 +990,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; @@ -1245,9 +1254,6 @@ struct mvpp2_bm_pool { /* Ports using BM pool */ u32 port_map; - - /* Occupied buffers indicator */ - int in_use_thresh; }; /* Static declaractions */ @@ -2590,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)); @@ -2621,6 +2631,13 @@ static void mvpp2_bm_pool_bufsize_set(struct mvpp2 *priv, static void mvpp2_bm_bufs_free(struct udevice *dev, struct mvpp2 *priv, struct mvpp2_bm_pool *bm_pool) { + int i; + + for (i = 0; i < bm_pool->buf_num; i++) { + /* Allocate buffer back from the buffer manager */ + mvpp2_read(priv, MVPP2_BM_PHY_ALLOC_REG(bm_pool->id)); + } + bm_pool->buf_num = 0; } @@ -2658,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; @@ -2792,7 +2809,6 @@ static int mvpp2_bm_bufs_add(struct mvpp2_port *port, /* Update BM driver with number of buffers added to pool */ bm_pool->buf_num += i; - bm_pool->in_use_thresh = bm_pool->buf_num / 4; return i; } @@ -2845,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; } @@ -2886,6 +2899,7 @@ static void mvpp2_port_mii_set(struct mvpp2_port *port) val |= MVPP2_GMAC_INBAND_AN_MASK; break; case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: val |= MVPP2_GMAC_PORT_RGMII_MASK; default: val &= ~MVPP2_GMAC_PCS_ENABLE_MASK; @@ -3053,10 +3067,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 @@ -3099,10 +3109,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; @@ -3141,10 +3147,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; @@ -3247,7 +3249,7 @@ static int gop_xpcs_mode(struct mvpp2_port *port, int num_of_lanes) /* configure XG MAC mode */ val = readl(port->priv->xpcs_base + MVPP22_XPCS_GLOBAL_CFG_0_REG); - val &= ~MVPP22_XPCS_PCSMODE_OFFS; + 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); @@ -4475,7 +4477,15 @@ static int mvpp2_rx_refill(struct mvpp2_port *port, /* Set hw internals when starting port */ static void mvpp2_start_dev(struct mvpp2_port *port) { - mvpp2_gmac_max_rx_size_set(port); + switch (port->phy_interface) { + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_SGMII: + mvpp2_gmac_max_rx_size_set(port); + default: + break; + } + mvpp2_txp_max_tx_size_set(port); if (port->priv->hw_version == MVPP21) @@ -4570,11 +4580,16 @@ static int mvpp2_open(struct udevice *dev, struct mvpp2_port *port) return err; } - err = mvpp2_phy_connect(dev, port); - if (err < 0) - return err; + if (port->phy_node) { + err = mvpp2_phy_connect(dev, port); + if (err < 0) + return err; - mvpp2_link_event(port); + mvpp2_link_event(port); + } else { + mvpp2_egress_enable(port); + mvpp2_ingress_enable(port); + } mvpp2_start_dev(port); @@ -4669,20 +4684,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++) { @@ -4717,15 +4718,44 @@ 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; + u32 phyaddr = 0; int phy_mode = -1; + phys_addr_t mdio_addr; phy_node = fdtdec_lookup_phandle(gd->fdt_blob, port_node, "phy"); - if (phy_node < 0) { - dev_err(&pdev->dev, "missing phy\n"); - return -ENODEV; + + if (phy_node > 0) { + phyaddr = fdtdec_get_int(gd->fdt_blob, phy_node, "reg", 0); + if (phyaddr < 0) { + 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; } phy_mode_str = fdt_getprop(gd->fdt_blob, port_node, "phy-mode", NULL); @@ -4742,6 +4772,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 @@ -4751,8 +4788,6 @@ static int phy_info_parse(struct udevice *dev, struct mvpp2_port *port) port->phy_speed = fdtdec_get_int(gd->fdt_blob, port_node, "phy-speed", 1000); - phyaddr = fdtdec_get_int(gd->fdt_blob, phy_node, "reg", 0); - port->id = id; if (port->priv->hw_version == MVPP21) port->first_rxq = port->id * rxq_number; @@ -4765,6 +4800,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, @@ -4783,7 +4833,12 @@ 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; + priv->num_ports++; return 0; } @@ -4948,22 +5003,24 @@ 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); + } - /* Disable HW PHY polling */ if (priv->hw_version == MVPP21) { + /* Disable HW PHY polling */ val = readl(priv->lms_base + MVPP2_PHY_AN_CFG0_REG); val |= MVPP2_PHY_AN_STOP_SMI0_MASK; writel(val, priv->lms_base + MVPP2_PHY_AN_CFG0_REG); } else { + /* Enable HW PHY polling */ val = readl(priv->iface_base + MVPP22_SMI_MISC_CFG_REG); - val &= ~MVPP22_SMI_POLLING_EN; + val |= MVPP22_SMI_POLLING_EN; writel(val, priv->iface_base + MVPP22_SMI_MISC_CFG_REG); } @@ -4990,25 +5047,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); @@ -5154,21 +5192,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); @@ -5224,21 +5251,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); @@ -5282,9 +5294,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) { @@ -5294,9 +5303,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; } @@ -5311,7 +5317,14 @@ static int mvpp2_start(struct udevice *dev) /* Reconfigure parser accept the original MAC address */ mvpp2_prs_update_mac_da(port, port->dev_addr); - mvpp2_port_power_up(port); + switch (port->phy_interface) { + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_SGMII: + mvpp2_port_power_up(port); + default: + break; + } mvpp2_open(dev, port); @@ -5327,6 +5340,14 @@ static void mvpp2_stop(struct udevice *dev) mvpp2_cleanup_txqs(port); } +static int mvpp22_smi_phy_addr_cfg(struct mvpp2_port *port) +{ + writel(port->phyaddr, port->priv->iface_base + + MVPP22_SMI_PHY_ADDR_REG(port->gop_id)); + + return 0; +} + static int mvpp2_base_probe(struct udevice *dev) { struct mvpp2 *priv = dev_get_priv(dev); @@ -5381,18 +5402,18 @@ static int mvpp2_base_probe(struct udevice *dev) memset(bd_space, 0, size); /* Save base addresses for later use */ - priv->base = (void *)dev_get_addr_index(dev, 0); + priv->base = (void *)devfdt_get_addr_index(dev, 0); if (IS_ERR(priv->base)) return PTR_ERR(priv->base); if (priv->hw_version == MVPP21) { - priv->lms_base = (void *)dev_get_addr_index(dev, 1); + priv->lms_base = (void *)devfdt_get_addr_index(dev, 1); if (IS_ERR(priv->lms_base)) return PTR_ERR(priv->lms_base); priv->mdio_base = priv->lms_base + MVPP21_SMI; } else { - priv->iface_base = (void *)dev_get_addr_index(dev, 1); + priv->iface_base = (void *)devfdt_get_addr_index(dev, 1); if (IS_ERR(priv->iface_base)) return PTR_ERR(priv->iface_base); @@ -5432,10 +5453,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); @@ -5450,7 +5469,7 @@ static int mvpp2_probe(struct udevice *dev) if (priv->hw_version == MVPP21) { int priv_common_regs_num = 2; - port->base = (void __iomem *)dev_get_addr_index( + port->base = (void __iomem *)devfdt_get_addr_index( dev->parent, priv_common_regs_num + port->id); if (IS_ERR(port->base)) return PTR_ERR(port->base); @@ -5465,15 +5484,23 @@ static int mvpp2_probe(struct udevice *dev) port->base = priv->iface_base + MVPP22_PORT_BASE + port->gop_id * MVPP22_PORT_OFFSET; + /* Set phy address of the port */ + if(port->phy_node) + mvpp22_smi_phy_addr_cfg(port); + /* GoP Init */ 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); @@ -5492,6 +5519,26 @@ static int mvpp2_probe(struct udevice *dev) return 0; } +/* + * Empty BM pool and stop its activity before the OS is started + */ +static int mvpp2_remove(struct udevice *dev) +{ + struct mvpp2_port *port = dev_get_priv(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]); + + return 0; +} + static const struct eth_ops mvpp2_ops = { .start = mvpp2_start, .send = mvpp2_send, @@ -5503,9 +5550,11 @@ static struct driver mvpp2_driver = { .name = "mvpp2", .id = UCLASS_ETH, .probe = mvpp2_probe, + .remove = mvpp2_remove, .ops = &mvpp2_ops, .priv_auto_alloc_size = sizeof(struct mvpp2_port), .platdata_auto_alloc_size = sizeof(struct eth_pdata), + .flags = DM_FLAG_ACTIVE_DMA, }; /*