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