X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=drivers%2Fnet%2Fmvpp2.c;h=19b9375ee27dd51dbdbc51401d11b59e563304e6;hb=cd93d625fd751d55c729c78b10f82109d56a5f1d;hp=8ffe6c84d438d396612feec0ce4be5bb995a5544;hpb=4951e9420e179977f49549e25d8fd6437b37da72;p=platform%2Fkernel%2Fu-boot.git diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index 8ffe6c8..19b9375 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -14,14 +14,22 @@ */ #include +#include #include +#include #include +#include +#include #include #include #include #include #include #include +#include +#include +#include +#include #include #include #include @@ -29,22 +37,14 @@ #include #include #include +#include #include +#include +#include +#include DECLARE_GLOBAL_DATA_PTR; -/* Some linux -> U-Boot compatibility stuff */ -#define netdev_err(dev, fmt, args...) \ - printf(fmt, ##args) -#define netdev_warn(dev, fmt, args...) \ - printf(fmt, ##args) -#define netdev_info(dev, fmt, args...) \ - printf(fmt, ##args) -#define netdev_dbg(dev, fmt, args...) \ - printf(fmt, ##args) - -#define ETH_ALEN 6 /* Octets in one ethernet addr */ - #define __verify_pcpu_ptr(ptr) \ do { \ const void __percpu *__vpp_verify = (typeof((ptr) + 0))NULL; \ @@ -66,15 +66,12 @@ do { \ #define NET_SKB_PAD max(32, MVPP2_CPU_D_CACHE_LINE_SIZE) #define CONFIG_NR_CPUS 1 -#define ETH_HLEN ETHER_HDR_SIZE /* Total octets in header */ /* 2(HW hdr) 14(MAC hdr) 4(CRC) 32(extra for cache prefetch) */ #define WRAP (2 + ETH_HLEN + 4 + 32) #define MTU 1500 #define RX_BUFFER_SIZE (ALIGN(MTU + WRAP, ARCH_DMA_MINALIGN)) -#define MVPP2_SMI_TIMEOUT 10000 - /* RX Fifo Registers */ #define MVPP2_RX_DATA_FIFO_SIZE_REG(port) (0x00 + 4 * (port)) #define MVPP2_RX_ATTR_FIFO_SIZE_REG(port) (0x20 + 4 * (port)) @@ -314,6 +311,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 +441,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) @@ -499,23 +498,8 @@ do { \ #define MVPP2_QUEUE_NEXT_DESC(q, index) \ (((index) < (q)->last_desc) ? ((index) + 1) : 0) -/* SMI: 0xc0054 -> offset 0x54 to lms_base */ -#define MVPP21_SMI 0x0054 /* PP2.2: SMI: 0x12a200 -> offset 0x1200 to iface_base */ #define MVPP22_SMI 0x1200 -#define MVPP2_PHY_REG_MASK 0x1f -/* SMI register fields */ -#define MVPP2_SMI_DATA_OFFS 0 /* Data */ -#define MVPP2_SMI_DATA_MASK (0xffff << MVPP2_SMI_DATA_OFFS) -#define MVPP2_SMI_DEV_ADDR_OFFS 16 /* PHY device address */ -#define MVPP2_SMI_REG_ADDR_OFFS 21 /* PHY device reg addr*/ -#define MVPP2_SMI_OPCODE_OFFS 26 /* Write/Read opcode */ -#define MVPP2_SMI_OPCODE_READ (1 << MVPP2_SMI_OPCODE_OFFS) -#define MVPP2_SMI_READ_VALID (1 << 27) /* Read Valid */ -#define MVPP2_SMI_BUSY (1 << 28) /* Busy */ - -#define MVPP2_PHY_ADDR_MASK 0x1f -#define MVPP2_PHY_REG_MASK 0x1f /* Additional PPv2.2 offsets */ #define MVPP22_MPCS 0x007000 @@ -604,7 +588,7 @@ enum mv_netc_lanes { /* Default number of TXQs in use */ #define MVPP2_DEFAULT_TXQ 1 -/* Dfault number of RXQs in use */ +/* Default number of RXQs in use */ #define MVPP2_DEFAULT_RXQ 1 #define CONFIG_MV_ETH_RXQ 8 /* increment by 8 */ @@ -615,10 +599,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 @@ -906,7 +890,6 @@ struct mvpp2 { void __iomem *base; void __iomem *lms_base; void __iomem *iface_base; - void __iomem *mdio_base; void __iomem *mpcs_base; void __iomem *xpcs_base; @@ -937,9 +920,8 @@ struct mvpp2 { /* Maximum number of RXQs per port */ unsigned int max_port_rxqs; - struct mii_dev *bus; - int probe_done; + u8 num_ports; }; struct mvpp2_pcpu_stats { @@ -983,8 +965,13 @@ struct mvpp2_port { struct phy_device *phy_dev; phy_interface_t phy_interface; - int phy_node; int phyaddr; + struct udevice *mdio_dev; + struct mii_dev *bus; +#if CONFIG_IS_ENABLED(DM_GPIO) + struct gpio_desc phy_reset_gpio; + struct gpio_desc phy_tx_disable_gpio; +#endif int init; unsigned int link; unsigned int duplex; @@ -2587,6 +2574,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)); @@ -2618,6 +2609,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; } @@ -2655,7 +2653,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; @@ -2841,9 +2839,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; } @@ -3050,10 +3045,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 @@ -3096,10 +3087,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; @@ -3138,10 +3125,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; @@ -3244,7 +3227,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); @@ -4472,7 +4455,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) @@ -4495,17 +4486,40 @@ static void mvpp2_stop_dev(struct mvpp2_port *port) gop_port_enable(port, 0); } -static int mvpp2_phy_connect(struct udevice *dev, struct mvpp2_port *port) +static void mvpp2_phy_connect(struct udevice *dev, struct mvpp2_port *port) { struct phy_device *phy_dev; if (!port->init || port->link == 0) { - phy_dev = phy_connect(port->priv->bus, port->phyaddr, dev, - port->phy_interface); + phy_dev = dm_mdio_phy_connect(port->mdio_dev, port->phyaddr, + dev, port->phy_interface); + + /* + * If the phy doesn't match with any existing u-boot drivers the + * phy framework will connect it to generic one which + * uid == 0xffffffff. In this case act as if the phy wouldn't be + * declared in dts. Otherwise in case of 3310 (for which the + * driver doesn't exist) the link will not be correctly + * detected. Removing phy entry from dts in case of 3310 is not + * an option because it is required for the phy_fw_down + * procedure. + */ + if (phy_dev && + phy_dev->drv->uid == 0xffffffff) {/* Generic phy */ + netdev_warn(port->dev, + "Marking phy as invalid, link will not be checked\n"); + /* set phy_addr to invalid value */ + port->phyaddr = PHY_MAX_ADDR; + mvpp2_egress_enable(port); + mvpp2_ingress_enable(port); + + return; + } + port->phy_dev = phy_dev; if (!phy_dev) { netdev_err(port->dev, "cannot connect to phy\n"); - return -ENODEV; + return; } phy_dev->supported &= PHY_GBIT_FEATURES; phy_dev->advertising = phy_dev->supported; @@ -4517,18 +4531,14 @@ static int mvpp2_phy_connect(struct udevice *dev, struct mvpp2_port *port) phy_config(phy_dev); phy_startup(phy_dev); - if (!phy_dev->link) { + if (!phy_dev->link) printf("%s: No link\n", phy_dev->dev->name); - return -1; - } - - port->init = 1; + else + port->init = 1; } else { mvpp2_egress_enable(port); mvpp2_ingress_enable(port); } - - return 0; } static int mvpp2_open(struct udevice *dev, struct mvpp2_port *port) @@ -4567,11 +4577,13 @@ static int mvpp2_open(struct udevice *dev, struct mvpp2_port *port) return err; } - err = mvpp2_phy_connect(dev, port); - if (err < 0) - return err; - - mvpp2_link_event(port); + if (port->phyaddr < PHY_MAX_ADDR) { + mvpp2_phy_connect(dev, port); + mvpp2_link_event(port); + } else { + mvpp2_egress_enable(port); + mvpp2_ingress_enable(port); + } mvpp2_start_dev(port); @@ -4666,20 +4678,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++) { @@ -4716,13 +4714,27 @@ static int phy_info_parse(struct udevice *dev, struct mvpp2_port *port) const char *phy_mode_str; int phy_node; u32 id; - u32 phyaddr; + u32 phyaddr = 0; int phy_mode = -1; + int ret; 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) { + int parent; + 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; + } + parent = fdt_parent_offset(gd->fdt_blob, phy_node); + ret = uclass_get_device_by_of_offset(UCLASS_MDIO, parent, + &port->mdio_dev); + if (ret) + return ret; + } else { + /* phy_addr is set to invalid value */ + phyaddr = PHY_MAX_ADDR; } phy_mode_str = fdt_getprop(gd->fdt_blob, port_node, "phy-mode", NULL); @@ -4739,6 +4751,13 @@ static int phy_info_parse(struct udevice *dev, struct mvpp2_port *port) return -EINVAL; } +#if CONFIG_IS_ENABLED(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 @@ -4748,20 +4767,32 @@ 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; else port->first_rxq = port->id * port->priv->max_port_rxqs; - port->phy_node = phy_node; port->phy_interface = phy_mode; port->phyaddr = phyaddr; return 0; } +#if CONFIG_IS_ENABLED(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, 1); + mdelay(10); + dm_gpio_set_value(&port->phy_reset_gpio, 0); + } + + 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, @@ -4780,7 +4811,12 @@ static int mvpp2_port_probe(struct udevice *dev, } mvpp2_port_power_up(port); +#if CONFIG_IS_ENABLED(DM_GPIO) + mvpp2_gpio_init(port); +#endif + priv->port_list[port->id] = port; + priv->num_ports++; return 0; } @@ -4945,13 +4981,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 */ @@ -4988,25 +5025,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); @@ -5030,118 +5048,6 @@ static int mvpp2_init(struct udevice *dev, struct mvpp2 *priv) return 0; } -/* SMI / MDIO functions */ - -static int smi_wait_ready(struct mvpp2 *priv) -{ - u32 timeout = MVPP2_SMI_TIMEOUT; - u32 smi_reg; - - /* wait till the SMI is not busy */ - do { - /* read smi register */ - smi_reg = readl(priv->mdio_base); - if (timeout-- == 0) { - printf("Error: SMI busy timeout\n"); - return -EFAULT; - } - } while (smi_reg & MVPP2_SMI_BUSY); - - return 0; -} - -/* - * mpp2_mdio_read - miiphy_read callback function. - * - * Returns 16bit phy register value, or 0xffff on error - */ -static int mpp2_mdio_read(struct mii_dev *bus, int addr, int devad, int reg) -{ - struct mvpp2 *priv = bus->priv; - u32 smi_reg; - u32 timeout; - - /* check parameters */ - if (addr > MVPP2_PHY_ADDR_MASK) { - printf("Error: Invalid PHY address %d\n", addr); - return -EFAULT; - } - - if (reg > MVPP2_PHY_REG_MASK) { - printf("Err: Invalid register offset %d\n", reg); - return -EFAULT; - } - - /* wait till the SMI is not busy */ - if (smi_wait_ready(priv) < 0) - return -EFAULT; - - /* fill the phy address and regiser offset and read opcode */ - smi_reg = (addr << MVPP2_SMI_DEV_ADDR_OFFS) - | (reg << MVPP2_SMI_REG_ADDR_OFFS) - | MVPP2_SMI_OPCODE_READ; - - /* write the smi register */ - writel(smi_reg, priv->mdio_base); - - /* wait till read value is ready */ - timeout = MVPP2_SMI_TIMEOUT; - - do { - /* read smi register */ - smi_reg = readl(priv->mdio_base); - if (timeout-- == 0) { - printf("Err: SMI read ready timeout\n"); - return -EFAULT; - } - } while (!(smi_reg & MVPP2_SMI_READ_VALID)); - - /* Wait for the data to update in the SMI register */ - for (timeout = 0; timeout < MVPP2_SMI_TIMEOUT; timeout++) - ; - - return readl(priv->mdio_base) & MVPP2_SMI_DATA_MASK; -} - -/* - * mpp2_mdio_write - miiphy_write callback function. - * - * Returns 0 if write succeed, -EINVAL on bad parameters - * -ETIME on timeout - */ -static int mpp2_mdio_write(struct mii_dev *bus, int addr, int devad, int reg, - u16 value) -{ - struct mvpp2 *priv = bus->priv; - u32 smi_reg; - - /* check parameters */ - if (addr > MVPP2_PHY_ADDR_MASK) { - printf("Error: Invalid PHY address %d\n", addr); - return -EFAULT; - } - - if (reg > MVPP2_PHY_REG_MASK) { - printf("Err: Invalid register offset %d\n", reg); - return -EFAULT; - } - - /* wait till the SMI is not busy */ - if (smi_wait_ready(priv) < 0) - return -EFAULT; - - /* fill the phy addr and reg offset and write opcode and data */ - smi_reg = value << MVPP2_SMI_DATA_OFFS; - smi_reg |= (addr << MVPP2_SMI_DEV_ADDR_OFFS) - | (reg << MVPP2_SMI_REG_ADDR_OFFS); - smi_reg &= ~MVPP2_SMI_OPCODE_READ; - - /* write the smi register */ - writel(smi_reg, priv->mdio_base); - - return 0; -} - static int mvpp2_recv(struct udevice *dev, int flags, uchar **packetp) { struct mvpp2_port *port = dev_get_priv(dev); @@ -5152,21 +5058,14 @@ 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; + if (port->phyaddr < PHY_MAX_ADDR) + if (!port->phy_dev->link) + return 0; /* 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); @@ -5222,21 +5121,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); @@ -5245,6 +5129,10 @@ static int mvpp2_send(struct udevice *dev, void *packet, int length) int tx_done; int timeout; + if (port->phyaddr < PHY_MAX_ADDR) + if (!port->phy_dev->link) + return 0; + txq = port->txqs[0]; aggr_txq = &port->priv->aggr_txqs[smp_processor_id()]; @@ -5280,9 +5168,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) { @@ -5292,9 +5177,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; } @@ -5309,7 +5191,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); @@ -5325,6 +5214,13 @@ static void mvpp2_stop(struct udevice *dev) mvpp2_cleanup_txqs(port); } +static int mvpp2_write_hwaddr(struct udevice *dev) +{ + struct mvpp2_port *port = dev_get_priv(dev); + + return mvpp2_prs_update_mac_da(port, port->dev_addr); +} + static int mvpp22_smi_phy_addr_cfg(struct mvpp2_port *port) { writel(port->phyaddr, port->priv->iface_base + @@ -5336,7 +5232,6 @@ static int mvpp22_smi_phy_addr_cfg(struct mvpp2_port *port) static int mvpp2_base_probe(struct udevice *dev) { struct mvpp2 *priv = dev_get_priv(dev); - struct mii_dev *bus; void *bd_space; u32 size = 0; int i; @@ -5387,23 +5282,19 @@ 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); - priv->mdio_base = priv->iface_base + MVPP22_SMI; - /* Store common base addresses for all ports */ priv->mpcs_base = priv->iface_base + MVPP22_MPCS; priv->xpcs_base = priv->iface_base + MVPP22_XPCS; @@ -5415,20 +5306,7 @@ static int mvpp2_base_probe(struct udevice *dev) else priv->max_port_rxqs = 32; - /* Finally create and register the MDIO bus driver */ - bus = mdio_alloc(); - if (!bus) { - printf("Failed to allocate MDIO bus\n"); - return -ENOMEM; - } - - bus->read = mpp2_mdio_read; - bus->write = mpp2_mdio_write; - snprintf(bus->name, sizeof(bus->name), dev->name); - bus->priv = (void *)priv; - priv->bus = bus; - - return mdio_register(bus); + return 0; } static int mvpp2_probe(struct udevice *dev) @@ -5438,12 +5316,10 @@ 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); + port->priv = priv; err = phy_info_parse(dev, port); if (err) @@ -5456,7 +5332,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); @@ -5472,17 +5348,22 @@ static int mvpp2_probe(struct udevice *dev) port->gop_id * MVPP22_PORT_OFFSET; /* Set phy address of the port */ - mvpp22_smi_phy_addr_cfg(port); + if (port->phyaddr < PHY_MAX_ADDR) + 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); @@ -5501,20 +5382,43 @@ 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, .recv = mvpp2_recv, .stop = mvpp2_stop, + .write_hwaddr = mvpp2_write_hwaddr }; 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, }; /* @@ -5558,6 +5462,10 @@ static int mvpp2_base_bind(struct udevice *parent) id += base_id_add; name = calloc(1, 16); + if (!name) { + free(plat); + return -ENOMEM; + } sprintf(name, "mvpp2-%d", id); /* Create child device UCLASS_ETH and bind it */