91 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright Sunplus Technology Co., Ltd.3 * All rights reserved.4 */5 6#include <linux/netdevice.h>7#include <linux/bitfield.h>8#include <linux/of_mdio.h>9 10#include "spl2sw_register.h"11#include "spl2sw_define.h"12#include "spl2sw_phy.h"13 14static void spl2sw_mii_link_change(struct net_device *ndev)15{16 struct spl2sw_mac *mac = netdev_priv(ndev);17 struct phy_device *phydev = ndev->phydev;18 struct spl2sw_common *comm = mac->comm;19 u32 reg;20 21 reg = readl(comm->l2sw_reg_base + L2SW_MAC_FORCE_MODE);22 23 if (phydev->link) {24 reg |= FIELD_PREP(MAC_FORCE_RMII_LINK, mac->lan_port);25 26 if (phydev->speed == 100) {27 reg |= FIELD_PREP(MAC_FORCE_RMII_SPD, mac->lan_port);28 } else {29 reg &= FIELD_PREP(MAC_FORCE_RMII_SPD, ~mac->lan_port) |30 ~MAC_FORCE_RMII_SPD;31 }32 33 if (phydev->duplex) {34 reg |= FIELD_PREP(MAC_FORCE_RMII_DPX, mac->lan_port);35 } else {36 reg &= FIELD_PREP(MAC_FORCE_RMII_DPX, ~mac->lan_port) |37 ~MAC_FORCE_RMII_DPX;38 }39 40 if (phydev->pause) {41 reg |= FIELD_PREP(MAC_FORCE_RMII_FC, mac->lan_port);42 } else {43 reg &= FIELD_PREP(MAC_FORCE_RMII_FC, ~mac->lan_port) |44 ~MAC_FORCE_RMII_FC;45 }46 } else {47 reg &= FIELD_PREP(MAC_FORCE_RMII_LINK, ~mac->lan_port) |48 ~MAC_FORCE_RMII_LINK;49 }50 51 writel(reg, comm->l2sw_reg_base + L2SW_MAC_FORCE_MODE);52 53 phy_print_status(phydev);54}55 56int spl2sw_phy_connect(struct spl2sw_common *comm)57{58 struct phy_device *phydev;59 struct net_device *ndev;60 struct spl2sw_mac *mac;61 int i;62 63 for (i = 0; i < MAX_NETDEV_NUM; i++)64 if (comm->ndev[i]) {65 ndev = comm->ndev[i];66 mac = netdev_priv(ndev);67 phydev = of_phy_connect(ndev, mac->phy_node, spl2sw_mii_link_change,68 0, mac->phy_mode);69 if (!phydev)70 return -ENODEV;71 72 phy_support_asym_pause(phydev);73 phy_attached_info(phydev);74 }75 76 return 0;77}78 79void spl2sw_phy_remove(struct spl2sw_common *comm)80{81 struct net_device *ndev;82 int i;83 84 for (i = 0; i < MAX_NETDEV_NUM; i++)85 if (comm->ndev[i]) {86 ndev = comm->ndev[i];87 if (ndev)88 phy_disconnect(ndev->phydev);89 }90}91