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