Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright Sunplus Technology Co., Ltd.
0003  *       All rights reserved.
0004  */
0005 
0006 #include <linux/netdevice.h>
0007 #include <linux/bitfield.h>
0008 #include <linux/of_mdio.h>
0009 
0010 #include "spl2sw_register.h"
0011 #include "spl2sw_define.h"
0012 #include "spl2sw_phy.h"
0013 
0014 static void spl2sw_mii_link_change(struct net_device *ndev)
0015 {
0016     struct spl2sw_mac *mac = netdev_priv(ndev);
0017     struct phy_device *phydev = ndev->phydev;
0018     struct spl2sw_common *comm = mac->comm;
0019     u32 reg;
0020 
0021     reg = readl(comm->l2sw_reg_base + L2SW_MAC_FORCE_MODE);
0022 
0023     if (phydev->link) {
0024         reg |= FIELD_PREP(MAC_FORCE_RMII_LINK, mac->lan_port);
0025 
0026         if (phydev->speed == 100) {
0027             reg |= FIELD_PREP(MAC_FORCE_RMII_SPD, mac->lan_port);
0028         } else {
0029             reg &= FIELD_PREP(MAC_FORCE_RMII_SPD, ~mac->lan_port) |
0030                    ~MAC_FORCE_RMII_SPD;
0031         }
0032 
0033         if (phydev->duplex) {
0034             reg |= FIELD_PREP(MAC_FORCE_RMII_DPX, mac->lan_port);
0035         } else {
0036             reg &= FIELD_PREP(MAC_FORCE_RMII_DPX, ~mac->lan_port) |
0037                    ~MAC_FORCE_RMII_DPX;
0038         }
0039 
0040         if (phydev->pause) {
0041             reg |= FIELD_PREP(MAC_FORCE_RMII_FC, mac->lan_port);
0042         } else {
0043             reg &= FIELD_PREP(MAC_FORCE_RMII_FC, ~mac->lan_port) |
0044                    ~MAC_FORCE_RMII_FC;
0045         }
0046     } else {
0047         reg &= FIELD_PREP(MAC_FORCE_RMII_LINK, ~mac->lan_port) |
0048                ~MAC_FORCE_RMII_LINK;
0049     }
0050 
0051     writel(reg, comm->l2sw_reg_base + L2SW_MAC_FORCE_MODE);
0052 
0053     phy_print_status(phydev);
0054 }
0055 
0056 int spl2sw_phy_connect(struct spl2sw_common *comm)
0057 {
0058     struct phy_device *phydev;
0059     struct net_device *ndev;
0060     struct spl2sw_mac *mac;
0061     int i;
0062 
0063     for (i = 0; i < MAX_NETDEV_NUM; i++)
0064         if (comm->ndev[i]) {
0065             ndev = comm->ndev[i];
0066             mac = netdev_priv(ndev);
0067             phydev = of_phy_connect(ndev, mac->phy_node, spl2sw_mii_link_change,
0068                         0, mac->phy_mode);
0069             if (!phydev)
0070                 return -ENODEV;
0071 
0072             phy_support_asym_pause(phydev);
0073             phy_attached_info(phydev);
0074         }
0075 
0076     return 0;
0077 }
0078 
0079 void spl2sw_phy_remove(struct spl2sw_common *comm)
0080 {
0081     struct net_device *ndev;
0082     int i;
0083 
0084     for (i = 0; i < MAX_NETDEV_NUM; i++)
0085         if (comm->ndev[i]) {
0086             ndev = comm->ndev[i];
0087             if (ndev) {
0088                 phy_disconnect(ndev->phydev);
0089                 ndev->phydev = NULL;
0090             }
0091         }
0092 }