| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- // SPDX-License-Identifier: GPL-2.0
- /* Copyright Sunplus Technology Co., Ltd.
- * All rights reserved.
- */
- #include <linux/netdevice.h>
- #include <linux/bitfield.h>
- #include <linux/of_mdio.h>
- #include "spl2sw_register.h"
- #include "spl2sw_define.h"
- #include "spl2sw_phy.h"
- static void spl2sw_mii_link_change(struct net_device *ndev)
- {
- struct spl2sw_mac *mac = netdev_priv(ndev);
- struct phy_device *phydev = ndev->phydev;
- struct spl2sw_common *comm = mac->comm;
- u32 reg;
- reg = readl(comm->l2sw_reg_base + L2SW_MAC_FORCE_MODE);
- if (phydev->link) {
- reg |= FIELD_PREP(MAC_FORCE_RMII_LINK, mac->lan_port);
- if (phydev->speed == 100) {
- reg |= FIELD_PREP(MAC_FORCE_RMII_SPD, mac->lan_port);
- } else {
- reg &= FIELD_PREP(MAC_FORCE_RMII_SPD, ~mac->lan_port) |
- ~MAC_FORCE_RMII_SPD;
- }
- if (phydev->duplex) {
- reg |= FIELD_PREP(MAC_FORCE_RMII_DPX, mac->lan_port);
- } else {
- reg &= FIELD_PREP(MAC_FORCE_RMII_DPX, ~mac->lan_port) |
- ~MAC_FORCE_RMII_DPX;
- }
- if (phydev->pause) {
- reg |= FIELD_PREP(MAC_FORCE_RMII_FC, mac->lan_port);
- } else {
- reg &= FIELD_PREP(MAC_FORCE_RMII_FC, ~mac->lan_port) |
- ~MAC_FORCE_RMII_FC;
- }
- } else {
- reg &= FIELD_PREP(MAC_FORCE_RMII_LINK, ~mac->lan_port) |
- ~MAC_FORCE_RMII_LINK;
- }
- writel(reg, comm->l2sw_reg_base + L2SW_MAC_FORCE_MODE);
- phy_print_status(phydev);
- }
- int spl2sw_phy_connect(struct spl2sw_common *comm)
- {
- struct phy_device *phydev;
- struct net_device *ndev;
- struct spl2sw_mac *mac;
- int i;
- for (i = 0; i < MAX_NETDEV_NUM; i++)
- if (comm->ndev[i]) {
- ndev = comm->ndev[i];
- mac = netdev_priv(ndev);
- phydev = of_phy_connect(ndev, mac->phy_node, spl2sw_mii_link_change,
- 0, mac->phy_mode);
- if (!phydev)
- return -ENODEV;
- phy_support_asym_pause(phydev);
- phy_attached_info(phydev);
- }
- return 0;
- }
- void spl2sw_phy_remove(struct spl2sw_common *comm)
- {
- struct net_device *ndev;
- int i;
- for (i = 0; i < MAX_NETDEV_NUM; i++)
- if (comm->ndev[i]) {
- ndev = comm->ndev[i];
- if (ndev)
- phy_disconnect(ndev->phydev);
- }
- }
|