* based on - Driver for MV64360X ethernet ports
* Copyright (C) 2002 rabeeh@galileo.co.il
*
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
+ * SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/arch/cpu.h>
#if defined(CONFIG_KIRKWOOD)
-#include <asm/arch/kirkwood.h>
+#include <asm/arch/soc.h>
#elif defined(CONFIG_ORION5X)
#include <asm/arch/orion5x.h>
+#elif defined(CONFIG_DOVE)
+#include <asm/arch/dove.h>
#endif
#include "mvgbe.h"
DECLARE_GLOBAL_DATA_PTR;
+#ifndef CONFIG_MVGBE_PORTS
+# define CONFIG_MVGBE_PORTS {0, 0}
+#endif
+
#define MV_PHY_ADR_REQUEST 0xee
#define MVGBE_SMI_REG (((struct mvgbe_registers *)MVGBE0_BASE)->smi)
+#if defined(CONFIG_PHYLIB) || defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
/*
* smi_reg_read - miiphy_read callback function.
*
/* check parameters */
if (phy_adr > PHYADR_MASK) {
printf("Err..(%s) Invalid PHY address %d\n",
- __FUNCTION__, phy_adr);
+ __func__, phy_adr);
return -EFAULT;
}
if (reg_ofs > PHYREG_MASK) {
printf("Err..(%s) Invalid register offset %d\n",
- __FUNCTION__, reg_ofs);
+ __func__, reg_ofs);
return -EFAULT;
}
/* read smi register */
smi_reg = MVGBE_REG_RD(MVGBE_SMI_REG);
if (timeout-- == 0) {
- printf("Err..(%s) SMI busy timeout\n", __FUNCTION__);
+ printf("Err..(%s) SMI busy timeout\n", __func__);
return -EFAULT;
}
} while (smi_reg & MVGBE_PHY_SMI_BUSY_MASK);
smi_reg = MVGBE_REG_RD(MVGBE_SMI_REG);
if (timeout-- == 0) {
printf("Err..(%s) SMI read ready timeout\n",
- __FUNCTION__);
+ __func__);
return -EFAULT;
}
} while (!(smi_reg & MVGBE_PHY_SMI_READ_VALID_MASK));
*data = (u16) (MVGBE_REG_RD(MVGBE_SMI_REG) & MVGBE_PHY_SMI_DATA_MASK);
- debug("%s:(adr %d, off %d) value= %04x\n", __FUNCTION__, phy_adr,
- reg_ofs, *data);
+ debug("%s:(adr %d, off %d) value= %04x\n", __func__, phy_adr, reg_ofs,
+ *data);
return 0;
}
/* check parameters */
if (phy_adr > PHYADR_MASK) {
- printf("Err..(%s) Invalid phy address\n", __FUNCTION__);
+ printf("Err..(%s) Invalid phy address\n", __func__);
return -EINVAL;
}
if (reg_ofs > PHYREG_MASK) {
- printf("Err..(%s) Invalid register offset\n", __FUNCTION__);
+ printf("Err..(%s) Invalid register offset\n", __func__);
return -EINVAL;
}
/* read smi register */
smi_reg = MVGBE_REG_RD(MVGBE_SMI_REG);
if (timeout-- == 0) {
- printf("Err..(%s) SMI busy timeout\n", __FUNCTION__);
+ printf("Err..(%s) SMI busy timeout\n", __func__);
return -ETIME;
}
} while (smi_reg & MVGBE_PHY_SMI_BUSY_MASK);
return 0;
}
+#endif
+
+#if defined(CONFIG_PHYLIB)
+int mvgbe_phy_read(struct mii_dev *bus, int phy_addr, int dev_addr,
+ int reg_addr)
+{
+ u16 data;
+ int ret;
+ ret = smi_reg_read(bus->name, phy_addr, reg_addr, &data);
+ if (ret)
+ return ret;
+ return data;
+}
+
+int mvgbe_phy_write(struct mii_dev *bus, int phy_addr, int dev_addr,
+ int reg_addr, u16 data)
+{
+ return smi_reg_write(bus->name, phy_addr, reg_addr, data);
+}
+#endif
/* Stop and checks all queues */
static void stop_queue(u32 * qreg)
{
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
struct mvgbe_registers *regs = dmvgbe->regs;
-#if (defined (CONFIG_MII) || defined (CONFIG_CMD_MII)) \
- && defined (CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
+#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \
+ !defined(CONFIG_PHYLIB) && \
+ defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
int i;
#endif
/* setup RX rings */
/* Enable port Rx. */
MVGBE_REG_WR(regs->rqc, (1 << RXUQ));
-#if (defined (CONFIG_MII) || defined (CONFIG_CMD_MII)) \
- && defined (CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
+#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \
+ !defined(CONFIG_PHYLIB) && \
+ defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
/* Wait up to 5s for the link status */
for (i = 0; i < 5; i++) {
u16 phyadr;
return 0;
}
-static int mvgbe_send(struct eth_device *dev, void *dataptr,
- int datasize)
+static int mvgbe_send(struct eth_device *dev, void *dataptr, int datasize)
{
struct mvgbe_device *dmvgbe = to_mvgbe(dev);
struct mvgbe_registers *regs = dmvgbe->regs;
if ((cmd_sts & (MVGBE_ERROR_SUMMARY | MVGBE_TX_LAST_FRAME)) ==
(MVGBE_ERROR_SUMMARY | MVGBE_TX_LAST_FRAME) &&
cmd_sts & (MVGBE_UR_ERROR | MVGBE_RL_ERROR)) {
- printf("Err..(%s) in xmit packet\n", __FUNCTION__);
+ printf("Err..(%s) in xmit packet\n", __func__);
return -1;
}
cmd_sts = readl(&p_txdesc->cmd_sts);
if (timeout < MVGBE_PHY_SMI_TIMEOUT)
timeout++;
else {
- debug("%s time out...\n", __FUNCTION__);
+ debug("%s time out...\n", __func__);
return -1;
}
} while (readl(&p_rxdesc_curr->cmd_sts) & MVGBE_BUFFER_OWNED_BY_DMA);
if (p_rxdesc_curr->byte_cnt != 0) {
debug("%s: Received %d byte Packet @ 0x%x (cmd_sts= %08x)\n",
- __FUNCTION__, (u32) p_rxdesc_curr->byte_cnt,
+ __func__, (u32) p_rxdesc_curr->byte_cnt,
(u32) p_rxdesc_curr->buf_ptr,
(u32) p_rxdesc_curr->cmd_sts);
}
!= (MVGBE_RX_FIRST_DESC | MVGBE_RX_LAST_DESC)) {
printf("Err..(%s) Dropping packet spread on"
- " multiple descriptors\n", __FUNCTION__);
+ " multiple descriptors\n", __func__);
} else if (cmd_sts & MVGBE_ERROR_SUMMARY) {
printf("Err..(%s) Dropping packet with errors\n",
- __FUNCTION__);
+ __func__);
} else {
/* !!! call higher layer processing */
debug("%s: Sending Received packet to"
- " upper layer (NetReceive)\n", __FUNCTION__);
+ " upper layer (net_process_received_packet)\n",
+ __func__);
/* let the upper layer handle the packet */
- NetReceive((p_rxdesc_curr->buf_ptr + RX_BUF_OFFSET),
- (int)(p_rxdesc_curr->byte_cnt - RX_BUF_OFFSET));
+ net_process_received_packet((p_rxdesc_curr->buf_ptr +
+ RX_BUF_OFFSET),
+ (int)(p_rxdesc_curr->byte_cnt -
+ RX_BUF_OFFSET));
}
/*
* free these descriptors and point next in the ring
return 0;
}
+#if defined(CONFIG_PHYLIB)
+int mvgbe_phylib_init(struct eth_device *dev, int phyid)
+{
+ struct mii_dev *bus;
+ struct phy_device *phydev;
+ int ret;
+
+ bus = mdio_alloc();
+ if (!bus) {
+ printf("mdio_alloc failed\n");
+ return -ENOMEM;
+ }
+ bus->read = mvgbe_phy_read;
+ bus->write = mvgbe_phy_write;
+ sprintf(bus->name, dev->name);
+
+ ret = mdio_register(bus);
+ if (ret) {
+ printf("mdio_register failed\n");
+ free(bus);
+ return -ENOMEM;
+ }
+
+ /* Set phy address of the port */
+ mvgbe_phy_write(bus, MV_PHY_ADR_REQUEST, 0, MV_PHY_ADR_REQUEST, phyid);
+
+ phydev = phy_connect(bus, phyid, dev, PHY_INTERFACE_MODE_RGMII);
+ if (!phydev) {
+ printf("phy_connect failed\n");
+ return -ENODEV;
+ }
+
+ phy_config(phydev);
+ phy_startup(phydev);
+
+ return 0;
+}
+#endif
+
int mvgbe_initialize(bd_t *bis)
{
struct mvgbe_device *dmvgbe;
free(dmvgbe);
error1:
printf("Err.. %s Failed to allocate memory\n",
- __FUNCTION__);
+ __func__);
return -1;
}
#endif
default: /* this should never happen */
printf("Err..(%s) Invalid device number %d\n",
- __FUNCTION__, devnum);
+ __func__, devnum);
return -1;
}
eth_register(dev);
-#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+#if defined(CONFIG_PHYLIB)
+ mvgbe_phylib_init(dev, PHY_BASE_ADR + devnum);
+#elif defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
miiphy_register(dev->name, smi_reg_read, smi_reg_write);
/* Set phy address of the port */
miiphy_write(dev->name, MV_PHY_ADR_REQUEST,