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