]> Git Repo - linux.git/blob - drivers/net/ethernet/sunplus/spl2sw_phy.c
Linux 6.14-rc3
[linux.git] / drivers / net / ethernet / sunplus / spl2sw_phy.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* 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
14 static 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
56 int 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
79 void 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 }
This page took 0.035229 seconds and 4 git commands to generate.