1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2008 Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
4  */
5 
6 #include <common.h>
7 #include "rtl8169.h"
8 
9 static unsigned char *PCI_MEMR;
10 
11 static void mac_delay(unsigned int cnt)
12 {
13 	udelay(cnt);
14 }
15 
16 static void mac_pci_setup(void)
17 {
18 	unsigned long pci_data;
19 
20 	PCI_PAR = 0x00000010;
21 	PCI_PDR = 0x00001000;
22 	PCI_PAR = 0x00000004;
23 	pci_data = PCI_PDR;
24 	PCI_PDR = pci_data | 0x00000007;
25 	PCI_PAR = 0x00000010;
26 
27 	PCI_MEMR = (unsigned char *)((PCI_PDR | 0xFE240050) & 0xFFFFFFF0);
28 }
29 
30 static void EECS(int level)
31 {
32 	unsigned char data = *PCI_MEMR;
33 
34 	if (level)
35 		*PCI_MEMR = data | 0x08;
36 	else
37 		*PCI_MEMR = data & 0xf7;
38 }
39 
40 static void EECLK(int level)
41 {
42 	unsigned char data = *PCI_MEMR;
43 
44 	if (level)
45 		*PCI_MEMR = data | 0x04;
46 	else
47 		*PCI_MEMR = data & 0xfb;
48 }
49 
50 static void EEDI(int level)
51 {
52 	unsigned char data = *PCI_MEMR;
53 
54 	if (level)
55 		*PCI_MEMR = data | 0x02;
56 	else
57 		*PCI_MEMR = data & 0xfd;
58 }
59 
60 static inline void sh7785lcr_bitset(unsigned short bit)
61 {
62 	if (bit)
63 		EEDI(HIGH);
64 	else
65 		EEDI(LOW);
66 
67 	EECLK(LOW);
68 	mac_delay(TIME1);
69 	EECLK(HIGH);
70 	mac_delay(TIME1);
71 	EEDI(LOW);
72 }
73 
74 static inline unsigned char sh7785lcr_bitget(void)
75 {
76 	unsigned char bit;
77 
78 	EECLK(LOW);
79 	mac_delay(TIME1);
80 	bit = *PCI_MEMR & 0x01;
81 	EECLK(HIGH);
82 	mac_delay(TIME1);
83 
84 	return bit;
85 }
86 
87 static inline void sh7785lcr_setcmd(unsigned char command)
88 {
89 	sh7785lcr_bitset(BIT_DUMMY);
90 	switch (command) {
91 	case MAC_EEP_READ:
92 		sh7785lcr_bitset(1);
93 		sh7785lcr_bitset(1);
94 		sh7785lcr_bitset(0);
95 		break;
96 	case MAC_EEP_WRITE:
97 		sh7785lcr_bitset(1);
98 		sh7785lcr_bitset(0);
99 		sh7785lcr_bitset(1);
100 		break;
101 	case MAC_EEP_ERACE:
102 		sh7785lcr_bitset(1);
103 		sh7785lcr_bitset(1);
104 		sh7785lcr_bitset(1);
105 		break;
106 	case MAC_EEP_EWEN:
107 		sh7785lcr_bitset(1);
108 		sh7785lcr_bitset(0);
109 		sh7785lcr_bitset(0);
110 		break;
111 	case MAC_EEP_EWDS:
112 		sh7785lcr_bitset(1);
113 		sh7785lcr_bitset(0);
114 		sh7785lcr_bitset(0);
115 		break;
116 	default:
117 		break;
118 	}
119 }
120 
121 static inline unsigned short sh7785lcr_getdt(void)
122 {
123 	unsigned short data = 0;
124 	int i;
125 
126 	sh7785lcr_bitget();			/* DUMMY */
127 	for (i = 0 ; i < 16 ; i++) {
128 		data <<= 1;
129 		data |= sh7785lcr_bitget();
130 	}
131 	return data;
132 }
133 
134 static inline void sh7785lcr_setadd(unsigned short address)
135 {
136 	sh7785lcr_bitset(address & 0x0020);	/* A5 */
137 	sh7785lcr_bitset(address & 0x0010);	/* A4 */
138 	sh7785lcr_bitset(address & 0x0008);	/* A3 */
139 	sh7785lcr_bitset(address & 0x0004);	/* A2 */
140 	sh7785lcr_bitset(address & 0x0002);	/* A1 */
141 	sh7785lcr_bitset(address & 0x0001);	/* A0 */
142 }
143 
144 static inline void sh7785lcr_setdata(unsigned short data)
145 {
146 	sh7785lcr_bitset(data & 0x8000);
147 	sh7785lcr_bitset(data & 0x4000);
148 	sh7785lcr_bitset(data & 0x2000);
149 	sh7785lcr_bitset(data & 0x1000);
150 	sh7785lcr_bitset(data & 0x0800);
151 	sh7785lcr_bitset(data & 0x0400);
152 	sh7785lcr_bitset(data & 0x0200);
153 	sh7785lcr_bitset(data & 0x0100);
154 	sh7785lcr_bitset(data & 0x0080);
155 	sh7785lcr_bitset(data & 0x0040);
156 	sh7785lcr_bitset(data & 0x0020);
157 	sh7785lcr_bitset(data & 0x0010);
158 	sh7785lcr_bitset(data & 0x0008);
159 	sh7785lcr_bitset(data & 0x0004);
160 	sh7785lcr_bitset(data & 0x0002);
161 	sh7785lcr_bitset(data & 0x0001);
162 }
163 
164 static void sh7785lcr_datawrite(const unsigned short *data, unsigned short address,
165 			 unsigned int count)
166 {
167 	unsigned int i;
168 
169 	for (i = 0; i < count; i++) {
170 		EECS(HIGH);
171 		EEDI(LOW);
172 		mac_delay(TIME1);
173 
174 		sh7785lcr_setcmd(MAC_EEP_WRITE);
175 		sh7785lcr_setadd(address++);
176 		sh7785lcr_setdata(*(data + i));
177 
178 		EECLK(LOW);
179 		EEDI(LOW);
180 		EECS(LOW);
181 		mac_delay(TIME2);
182 	}
183 }
184 
185 static void sh7785lcr_macerase(void)
186 {
187 	unsigned int i;
188 	unsigned short pci_address = 7;
189 
190 	for (i = 0; i < 3; i++) {
191 		EECS(HIGH);
192 		EEDI(LOW);
193 		mac_delay(TIME1);
194 		sh7785lcr_setcmd(MAC_EEP_ERACE);
195 		sh7785lcr_setadd(pci_address++);
196 		mac_delay(TIME1);
197 		EECLK(LOW);
198 		EEDI(LOW);
199 		EECS(LOW);
200 	}
201 
202 	mac_delay(TIME2);
203 
204 	printf("\n\nErace End\n");
205 	for (i = 0; i < 10; i++)
206 		mac_delay(TIME2);
207 }
208 
209 static void sh7785lcr_macwrite(unsigned short *data)
210 {
211 	sh7785lcr_macerase();
212 
213 	sh7785lcr_datawrite(EEPROM_W_Data_8169_A, 0x0000, 7);
214 	sh7785lcr_datawrite(data, PCI_EEP_ADDRESS, PCI_MAC_ADDRESS_SIZE);
215 	sh7785lcr_datawrite(EEPROM_W_Data_8169_B, 0x000a, 54);
216 }
217 
218 void sh7785lcr_macdtrd(unsigned char *buf, unsigned short address, unsigned int count)
219 {
220 	unsigned int i;
221 	unsigned short wk;
222 
223 	for (i = 0 ; i < count; i++) {
224 		EECS(HIGH);
225 		EEDI(LOW);
226 		mac_delay(TIME1);
227 		sh7785lcr_setcmd(MAC_EEP_READ);
228 		sh7785lcr_setadd(address++);
229 		wk = sh7785lcr_getdt();
230 
231 		*buf++ = (unsigned char)(wk & 0xff);
232 		*buf++ = (unsigned char)((wk >> 8) & 0xff);
233 		EECLK(LOW);
234 		EEDI(LOW);
235 		EECS(LOW);
236 	}
237 }
238 
239 static void sh7785lcr_macadrd(unsigned char *buf)
240 {
241 	*PCI_MEMR = PCI_PROG;
242 
243 	sh7785lcr_macdtrd(buf, PCI_EEP_ADDRESS, PCI_MAC_ADDRESS_SIZE);
244 }
245 
246 static void sh7785lcr_eepewen(void)
247 {
248 	*PCI_MEMR = PCI_PROG;
249 	mac_delay(TIME1);
250 	EECS(LOW);
251 	EECLK(LOW);
252 	EEDI(LOW);
253 	EECS(HIGH);
254 	mac_delay(TIME1);
255 
256 	sh7785lcr_setcmd(MAC_EEP_EWEN);
257 	sh7785lcr_bitset(1);
258 	sh7785lcr_bitset(1);
259 	sh7785lcr_bitset(BIT_DUMMY);
260 	sh7785lcr_bitset(BIT_DUMMY);
261 	sh7785lcr_bitset(BIT_DUMMY);
262 	sh7785lcr_bitset(BIT_DUMMY);
263 
264 	EECLK(LOW);
265 	EEDI(LOW);
266 	EECS(LOW);
267 	mac_delay(TIME1);
268 }
269 
270 void mac_write(unsigned short *data)
271 {
272 	mac_pci_setup();
273 	sh7785lcr_eepewen();
274 	sh7785lcr_macwrite(data);
275 }
276 
277 void mac_read(void)
278 {
279 	unsigned char data[6];
280 
281 	mac_pci_setup();
282 	sh7785lcr_macadrd(data);
283 	printf("Mac = %02x:%02x:%02x:%02x:%02x:%02x\n",
284 		data[0], data[1], data[2], data[3], data[4], data[5]);
285 }
286 
287 int do_set_mac(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
288 {
289 	int i;
290 	unsigned char mac[6];
291 	char *s, *e;
292 
293 	if (argc != 2)
294 		return cmd_usage(cmdtp);
295 
296 	s = argv[1];
297 
298 	for (i = 0; i < 6; i++) {
299 		mac[i] = s ? simple_strtoul(s, &e, 16) : 0;
300 		if (s)
301 			s = (*e) ? e + 1 : e;
302 	}
303 	mac_write((unsigned short *)mac);
304 
305 	return 0;
306 }
307 
308 U_BOOT_CMD(
309 	setmac,	2,	1,	do_set_mac,
310 	"write MAC address for RTL8110SCL",
311 	"\n"
312 	"setmac <mac address> - write MAC address for RTL8110SCL"
313 );
314 
315 int do_print_mac(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
316 {
317 	if (argc != 1)
318 		return cmd_usage(cmdtp);
319 
320 	mac_read();
321 
322 	return 0;
323 }
324 
325 U_BOOT_CMD(
326 	printmac,	1,	1,	do_print_mac,
327 	"print MAC address for RTL8110",
328 	"\n"
329 	"    - print MAC address for RTL8110"
330 );
331