1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 ################################################################################
4 #
5 # r8168 is the Linux device driver released for Realtek Gigabit Ethernet
6 # controllers with PCI-Express interface.
7 #
8 # Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved.
9 #
10 # This program is free software; you can redistribute it and/or modify it
11 # under the terms of the GNU General Public License as published by the Free
12 # Software Foundation; either version 2 of the License, or (at your option)
13 # any later version.
14 #
15 # This program is distributed in the hope that it will be useful, but WITHOUT
16 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 # more details.
19 #
20 # You should have received a copy of the GNU General Public License along with
21 # this program; if not, see <http://www.gnu.org/licenses/>.
22 #
23 # Author:
24 # Realtek NIC software team <nicfae@realtek.com>
25 # No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
26 #
27 ################################################################################
28 */
29
30 /************************************************************************************
31 * This product is covered by one or more of the following patents:
32 * US6,570,884, US6,115,776, and US6,327,625.
33 ***********************************************************************************/
34
35 #include <linux/init.h>
36 #include <linux/module.h>
37 #include <linux/version.h>
38 #include <linux/ethtool.h>
39 #include <linux/netdevice.h>
40 #include <linux/delay.h>
41
42 #include <asm/io.h>
43
44 #include "r8168.h"
45 #include "rtl_eeprom.h"
46
47 //-------------------------------------------------------------------
48 //rtl8168_eeprom_type():
49 // tell the eeprom type
50 //return value:
51 // 0: the eeprom type is 93C46
52 // 1: the eeprom type is 93C56 or 93C66
53 //-------------------------------------------------------------------
rtl8168_eeprom_type(struct rtl8168_private * tp)54 void rtl8168_eeprom_type(struct rtl8168_private *tp)
55 {
56 u16 magic = 0;
57
58 if (tp->mcfg == CFG_METHOD_DEFAULT)
59 goto out_no_eeprom;
60
61 if(RTL_R8(tp, 0xD2)&0x04) {
62 //not support
63 //tp->eeprom_type = EEPROM_TWSI;
64 //tp->eeprom_len = 256;
65 goto out_no_eeprom;
66 } else if(RTL_R32(tp, RxConfig) & RxCfg_9356SEL) {
67 tp->eeprom_type = EEPROM_TYPE_93C56;
68 tp->eeprom_len = 256;
69 } else {
70 tp->eeprom_type = EEPROM_TYPE_93C46;
71 tp->eeprom_len = 128;
72 }
73
74 magic = rtl8168_eeprom_read_sc(tp, 0);
75
76 out_no_eeprom:
77 if ((magic != 0x8129) && (magic != 0x8128)) {
78 tp->eeprom_type = EEPROM_TYPE_NONE;
79 tp->eeprom_len = 0;
80 }
81 }
82
rtl8168_eeprom_cleanup(struct rtl8168_private * tp)83 void rtl8168_eeprom_cleanup(struct rtl8168_private *tp)
84 {
85 u8 x;
86
87 x = RTL_R8(tp, Cfg9346);
88 x &= ~(Cfg9346_EEDI | Cfg9346_EECS);
89
90 RTL_W8(tp, Cfg9346, x);
91
92 rtl8168_raise_clock(tp, &x);
93 rtl8168_lower_clock(tp, &x);
94 }
95
rtl8168_eeprom_cmd_done(struct rtl8168_private * tp)96 int rtl8168_eeprom_cmd_done(struct rtl8168_private *tp)
97 {
98 u8 x;
99 int i;
100
101 rtl8168_stand_by(tp);
102
103 for (i = 0; i < 50000; i++) {
104 x = RTL_R8(tp, Cfg9346);
105
106 if (x & Cfg9346_EEDO) {
107 udelay(RTL_CLOCK_RATE * 2 * 3);
108 return 0;
109 }
110 udelay(1);
111 }
112
113 return -1;
114 }
115
116 //-------------------------------------------------------------------
117 //rtl8168_eeprom_read_sc():
118 // read one word from eeprom
119 //-------------------------------------------------------------------
rtl8168_eeprom_read_sc(struct rtl8168_private * tp,u16 reg)120 u16 rtl8168_eeprom_read_sc(struct rtl8168_private *tp, u16 reg)
121 {
122 int addr_sz = 6;
123 u8 x;
124 u16 data;
125
126 if(tp->eeprom_type == EEPROM_TYPE_NONE) {
127 return -1;
128 }
129
130 if (tp->eeprom_type==EEPROM_TYPE_93C46)
131 addr_sz = 6;
132 else if (tp->eeprom_type==EEPROM_TYPE_93C56)
133 addr_sz = 8;
134
135 x = Cfg9346_EEM1 | Cfg9346_EECS;
136 RTL_W8(tp, Cfg9346, x);
137
138 rtl8168_shift_out_bits(tp, RTL_EEPROM_READ_OPCODE, 3);
139 rtl8168_shift_out_bits(tp, reg, addr_sz);
140
141 data = rtl8168_shift_in_bits(tp);
142
143 rtl8168_eeprom_cleanup(tp);
144
145 RTL_W8(tp, Cfg9346, 0);
146
147 return data;
148 }
149
150 //-------------------------------------------------------------------
151 //rtl8168_eeprom_write_sc():
152 // write one word to a specific address in the eeprom
153 //-------------------------------------------------------------------
rtl8168_eeprom_write_sc(struct rtl8168_private * tp,u16 reg,u16 data)154 void rtl8168_eeprom_write_sc(struct rtl8168_private *tp, u16 reg, u16 data)
155 {
156 u8 x;
157 int addr_sz = 6;
158 int w_dummy_addr = 4;
159
160 if(tp->eeprom_type == EEPROM_TYPE_NONE) {
161 return ;
162 }
163
164 if (tp->eeprom_type==EEPROM_TYPE_93C46) {
165 addr_sz = 6;
166 w_dummy_addr = 4;
167 } else if (tp->eeprom_type==EEPROM_TYPE_93C56) {
168 addr_sz = 8;
169 w_dummy_addr = 6;
170 }
171
172 x = Cfg9346_EEM1 | Cfg9346_EECS;
173 RTL_W8(tp, Cfg9346, x);
174
175 rtl8168_shift_out_bits(tp, RTL_EEPROM_EWEN_OPCODE, 5);
176 rtl8168_shift_out_bits(tp, reg, w_dummy_addr);
177 rtl8168_stand_by(tp);
178
179 rtl8168_shift_out_bits(tp, RTL_EEPROM_ERASE_OPCODE, 3);
180 rtl8168_shift_out_bits(tp, reg, addr_sz);
181 if (rtl8168_eeprom_cmd_done(tp) < 0) {
182 return;
183 }
184 rtl8168_stand_by(tp);
185
186 rtl8168_shift_out_bits(tp, RTL_EEPROM_WRITE_OPCODE, 3);
187 rtl8168_shift_out_bits(tp, reg, addr_sz);
188 rtl8168_shift_out_bits(tp, data, 16);
189 if (rtl8168_eeprom_cmd_done(tp) < 0) {
190 return;
191 }
192 rtl8168_stand_by(tp);
193
194 rtl8168_shift_out_bits(tp, RTL_EEPROM_EWDS_OPCODE, 5);
195 rtl8168_shift_out_bits(tp, reg, w_dummy_addr);
196
197 rtl8168_eeprom_cleanup(tp);
198 RTL_W8(tp, Cfg9346, 0);
199 }
200
rtl8168_raise_clock(struct rtl8168_private * tp,u8 * x)201 void rtl8168_raise_clock(struct rtl8168_private *tp, u8 *x)
202 {
203 *x = *x | Cfg9346_EESK;
204 RTL_W8(tp, Cfg9346, *x);
205 udelay(RTL_CLOCK_RATE);
206 }
207
rtl8168_lower_clock(struct rtl8168_private * tp,u8 * x)208 void rtl8168_lower_clock(struct rtl8168_private *tp, u8 *x)
209 {
210
211 *x = *x & ~Cfg9346_EESK;
212 RTL_W8(tp, Cfg9346, *x);
213 udelay(RTL_CLOCK_RATE);
214 }
215
rtl8168_shift_out_bits(struct rtl8168_private * tp,int data,int count)216 void rtl8168_shift_out_bits(struct rtl8168_private *tp, int data, int count)
217 {
218 u8 x;
219 int mask;
220
221 mask = 0x01 << (count - 1);
222 x = RTL_R8(tp, Cfg9346);
223 x &= ~(Cfg9346_EEDI | Cfg9346_EEDO);
224
225 do {
226 if (data & mask)
227 x |= Cfg9346_EEDI;
228 else
229 x &= ~Cfg9346_EEDI;
230
231 RTL_W8(tp, Cfg9346, x);
232 udelay(RTL_CLOCK_RATE);
233 rtl8168_raise_clock(tp, &x);
234 rtl8168_lower_clock(tp, &x);
235 mask = mask >> 1;
236 } while(mask);
237
238 x &= ~Cfg9346_EEDI;
239 RTL_W8(tp, Cfg9346, x);
240 }
241
rtl8168_shift_in_bits(struct rtl8168_private * tp)242 u16 rtl8168_shift_in_bits(struct rtl8168_private *tp)
243 {
244 u8 x;
245 u16 d, i;
246
247 x = RTL_R8(tp, Cfg9346);
248 x &= ~(Cfg9346_EEDI | Cfg9346_EEDO);
249
250 d = 0;
251
252 for (i = 0; i < 16; i++) {
253 d = d << 1;
254 rtl8168_raise_clock(tp, &x);
255
256 x = RTL_R8(tp, Cfg9346);
257 x &= ~Cfg9346_EEDI;
258
259 if (x & Cfg9346_EEDO)
260 d |= 1;
261
262 rtl8168_lower_clock(tp, &x);
263 }
264
265 return d;
266 }
267
rtl8168_stand_by(struct rtl8168_private * tp)268 void rtl8168_stand_by(struct rtl8168_private *tp)
269 {
270 u8 x;
271
272 x = RTL_R8(tp, Cfg9346);
273 x &= ~(Cfg9346_EECS | Cfg9346_EESK);
274 RTL_W8(tp, Cfg9346, x);
275 udelay(RTL_CLOCK_RATE);
276
277 x |= Cfg9346_EECS;
278 RTL_W8(tp, Cfg9346, x);
279 }
280
rtl8168_set_eeprom_sel_low(struct rtl8168_private * tp)281 void rtl8168_set_eeprom_sel_low(struct rtl8168_private *tp)
282 {
283 RTL_W8(tp, Cfg9346, Cfg9346_EEM1);
284 RTL_W8(tp, Cfg9346, Cfg9346_EEM1 | Cfg9346_EESK);
285
286 udelay(20);
287
288 RTL_W8(tp, Cfg9346, Cfg9346_EEM1);
289 }
290