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