• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  *
4  * This program is free software; you can redistribute  it and/or modify it
5  * under  the terms of  the GNU General  Public License as published by the
6  * Free Software Foundation;  either version 2 of the  License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  *
17  * Description: Hieth mdio operation
18  */
19 
20 #define HIETH_SFV300
21 
22 #include "hieth.h"
23 #include "mdio.h"
24 
25 /* write mdio registers reset value */
mdio_reg_reset(struct hieth_netdev_local * ld)26 static void mdio_reg_reset(struct hieth_netdev_local *ld)
27 {
28 	hieth_writel(ld, 0x00008000, MDIO_RWCTRL);
29 	hieth_writel(ld, 0x00000001, U_MDIO_PHYADDR);
30 	hieth_writel(ld, 0x00000001, D_MDIO_PHYADDR);
31 	hieth_writel(ld, 0x04631EA9, U_MDIO_ANEG_CTRL);
32 	hieth_writel(ld, 0x04631EA9, D_MDIO_ANEG_CTRL);
33 	hieth_writel(ld, 0x00000000, U_MDIO_IRQENA);
34 	hieth_writel(ld, 0x00000000, D_MDIO_IRQENA);
35 }
36 
wait_mdio_ready(struct hieth_netdev_local * ld)37 static int wait_mdio_ready(struct hieth_netdev_local *ld)
38 {
39 	int timeout_us = 5000;
40 
41 	while (--timeout_us && !test_mdio_ready(ld))
42 		udelay(50);  /* delay 50us */
43 
44 	return timeout_us;
45 }
46 
hieth_mdio_read(struct hieth_netdev_local * ld,int phy_addr,unsigned int regnum)47 int hieth_mdio_read(struct hieth_netdev_local *ld, int phy_addr, unsigned int regnum)
48 {
49 	int val = 0;
50 	hieth_assert((!((unsigned int)phy_addr & (~0x1F))) && (!(regnum & (~0x1F))));
51 
52 	local_lock(ld);
53 
54 	if (!wait_mdio_ready(ld)) {
55 		hieth_error("mdio busy");
56 		goto error_exit;
57 	}
58 
59 	mdio_start_phyread(ld, (unsigned int)phy_addr, regnum);
60 
61 	if (wait_mdio_ready(ld) != 0) {
62 		val = mdio_get_phyread_val(ld);
63 	} else {
64 		hieth_error("read timeout");
65 	}
66 
67 error_exit:
68 
69 	local_unlock(ld);
70 
71 	hieth_trace(HIETH_TRACE_MDIO, "phy_addr = %d, regnum = %d, val = 0x%04x", phy_addr,
72 				(int)regnum, val);
73 
74 	return val;
75 }
76 
hieth_mdio_write(struct hieth_netdev_local * ld,int phy_addr,int regnum,int val)77 int hieth_mdio_write(struct hieth_netdev_local *ld, int phy_addr, int regnum, int val)
78 {
79 	hieth_assert((!((unsigned int)phy_addr & (~0x1F))) && (!((unsigned int)regnum & (~0x1F))));
80 
81 	hieth_trace(HIETH_TRACE_MDIO, "phy_addr = %d, regnum = %d", phy_addr, regnum);
82 
83 	local_lock(ld);
84 
85 	if (!wait_mdio_ready(ld)) {
86 		hieth_error("mdio busy");
87 		val = -1;
88 		goto error_exit;
89 	}
90 
91 	mdio_phywrite(ld, (unsigned int)phy_addr, (unsigned int)regnum, (unsigned int)val);
92 
93 error_exit:
94 
95 	local_unlock(ld);
96 
97 	return val;
98 }
99 
hieth_mdio_reset(struct hieth_netdev_local * ld)100 int hieth_mdio_reset(struct hieth_netdev_local *ld)
101 {
102 	mdio_reg_reset(ld);
103 
104 	return 0;
105 }
106 
hieth_mdio_init(struct hieth_netdev_local * ld)107 int hieth_mdio_init(struct hieth_netdev_local *ld)
108 {
109 	local_lock_init(ld);
110 
111 	hieth_mdio_reset(ld);
112 
113 	return 0;
114 }
115 
hieth_mdio_exit(struct hieth_netdev_local * ld)116 void hieth_mdio_exit(struct hieth_netdev_local *ld)
117 {
118 	local_lock_exit(ld);
119 }
120