2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright © 2007 Atheros Communications, Inc., All Rights Reserved.
10 * Manage the atheros ethernet PHY.
12 * All definitions in this file are operating system independent!
16 #include <linux/types.h>
20 #include <asm/addrspace.h>
21 #include "ar7240_soc.h"
22 #include "ar7240_s26_phy.h"
24 /* PHY selections and access functions */
25 #define DRV_PRINT(DBG_SW,X)
27 #define ATHR_LAN_PORT_VLAN 1
28 #define ATHR_WAN_PORT_VLAN 2
29 #define ENET_UNIT_LAN 1
30 #define ENET_UNIT_WAN 0
32 #define ATHR_PHY0_ADDR 0x0
33 #define ATHR_PHY1_ADDR 0x1
34 #define ATHR_PHY2_ADDR 0x2
35 #define ATHR_PHY3_ADDR 0x3
36 #define ATHR_PHY4_ADDR 0x4
42 * Track per-PHY port information.
45 int isEnetPort; /* normal enet port */
46 int isPhyAlive; /* last known state of link */
47 int ethUnit; /* MAC associated with this phy port */
49 uint32_t phyAddr; /* PHY registers associated with this phy port */
50 uint32_t VLANTableSetting; /* Value to be written to VLAN table */
54 * Per-PHY information, indexed by PHY unit number.
56 static athrPhyInfo_t athrPhyInfo[] = {
57 /* port 1 -- LAN port 1 */
58 { TRUE, FALSE, ENET_UNIT_LAN, 0, ATHR_PHY0_ADDR, ATHR_LAN_PORT_VLAN },
60 /* port 2 -- LAN port 2 */
61 { TRUE, FALSE, ENET_UNIT_LAN, 0, ATHR_PHY1_ADDR, ATHR_LAN_PORT_VLAN },
63 /* port 3 -- LAN port 3 */
64 { TRUE, FALSE, ENET_UNIT_LAN, 0, ATHR_PHY2_ADDR, ATHR_LAN_PORT_VLAN },
66 /* port 4 -- LAN port 4 */
67 { TRUE, FALSE, ENET_UNIT_LAN, 0, ATHR_PHY3_ADDR, ATHR_LAN_PORT_VLAN },
69 /* port 5 -- WAN Port 5 */
70 { TRUE, FALSE, ENET_UNIT_WAN, 0, ATHR_PHY4_ADDR, ATHR_LAN_PORT_VLAN },
72 /* port 0 -- cpu port 0 */
73 { FALSE, TRUE, ENET_UNIT_LAN, 0, 0x00, ATHR_LAN_PORT_VLAN },
76 static uint8_t athr26_init_flag = 0;
77 static uint8_t athr26_init_flag1 = 0;
79 /* Range of valid PHY IDs is [MIN..MAX] */
80 #define ATHR_PHY_MAX 5
82 #define ATHR_ID_MAX (ATHR_PHY_MAX-1)
84 /* Convenience macros to access myPhyInfo */
85 #define ATHR_IS_ENET_PORT(phyUnit) (athrPhyInfo[phyUnit].isEnetPort)
86 #define ATHR_IS_PHY_ALIVE(phyUnit) (athrPhyInfo[phyUnit].isPhyAlive)
87 #define ATHR_ETHUNIT(phyUnit) (athrPhyInfo[phyUnit].ethUnit)
88 #define ATHR_PHYBASE(phyUnit) (athrPhyInfo[phyUnit].phyBase)
89 #define ATHR_PHYADDR(phyUnit) (athrPhyInfo[phyUnit].phyAddr)
90 #define ATHR_VLAN_TABLE_SETTING(phyUnit) (athrPhyInfo[phyUnit].VLANTableSetting)
91 #define ATHR_IS_ETHUNIT(phyUnit, ethUnit) (ATHR_IS_ENET_PORT(phyUnit) && ATHR_ETHUNIT(phyUnit) == (ethUnit))
92 #define ATHR_IS_WAN_PORT(phyUnit) (!(ATHR_ETHUNIT(phyUnit) == ENET_UNIT_LAN))
94 /* Forward references */
95 int athrs26_phy_is_link_alive(int phyUnit);
96 uint32_t athrs26_reg_read(uint32_t reg_addr);
97 unsigned int s26_rd_phy(unsigned int phy_addr, unsigned int reg_addr);
98 void athrs26_reg_write(uint32_t reg_addr, uint32_t reg_val);
99 void s26_wr_phy(unsigned int phy_addr, unsigned int reg_addr, unsigned int write_data);
101 void athrs26_powersave_off(int phy_addr){
102 s26_wr_phy(phy_addr, ATHR_DEBUG_PORT_ADDRESS, 0x29);
103 s26_wr_phy(phy_addr, ATHR_DEBUG_PORT_DATA, 0x36c0);
106 void athrs26_sleep_off(int phy_addr){
107 s26_wr_phy(phy_addr, ATHR_DEBUG_PORT_ADDRESS, 0xb);
108 s26_wr_phy(phy_addr, ATHR_DEBUG_PORT_DATA, 0x3c00);
111 void athrs26_reg_init(void){
112 uint32_t ar7240_revid;
117 /* if using header for register configuration, we have to */
118 /* configure s26 register after frame transmission is enabled */
119 if(athr26_init_flag){
123 ar7240_revid = ar7240_reg_rd(AR7240_REV_ID) & AR7240_REV_ID_MASK;
125 if(ar7240_revid == AR7240_REV_1_0){
126 #ifdef S26_FORCE_100M
127 s26_wr_phy(ATHR_PHY4_ADDR, ATHR_PHY_FUNC_CONTROL, 0x800);
128 s26_wr_phy(ATHR_PHY4_ADDR, ATHR_PHY_CONTROL, 0xa100);
131 athrs26_powersave_off(ATHR_PHY4_ADDR);
132 athrs26_sleep_off(ATHR_PHY4_ADDR);
133 s26_wr_phy(ATHR_PHY4_ADDR,ATHR_PHY_FUNC_CONTROL,0x800);
134 s26_wr_phy(ATHR_PHY4_ADDR,ATHR_PHY_CONTROL,0x8100);
135 s26_wr_phy(ATHR_PHY4_ADDR,ATHR_DEBUG_PORT_ADDRESS,0x0);
136 s26_wr_phy(ATHR_PHY4_ADDR,ATHR_DEBUG_PORT_DATA,0x12ee);
137 s26_wr_phy(ATHR_PHY4_ADDR,ATHR_DEBUG_PORT_ADDRESS,0x3);
138 s26_wr_phy(ATHR_PHY4_ADDR,ATHR_DEBUG_PORT_DATA,0x3bf0);
139 s26_wr_phy(ATHR_PHY4_ADDR,ATHR_PHY_CONTROL,0x8100);
142 s26_wr_phy(ATHR_PHY4_ADDR, ATHR_PHY_CONTROL, 0x9000);
146 rd_val = s26_rd_phy(ATHR_PHY4_ADDR,ATHR_PHY_FUNC_CONTROL);
147 printf("S26 PHY FUNC CTRL (%d) :%x\n",ATHR_PHY4_ADDR, rd_val);
149 rd_val = s26_rd_phy(ATHR_PHY4_ADDR,ATHR_PHY_CONTROL);
150 printf("S26 PHY CTRL (%d) :%x\n",ATHR_PHY4_ADDR, rd_val);
153 athr26_init_flag = 1;
156 void athrs26_reg_init_lan(void){
159 //uint32_t phyBase = 0;
160 uint32_t phyAddr = 0;
161 uint32_t ar7240_revid;
166 /* if using header for register configuration, we have to */
167 /* configure s26 register after frame transmission is enabled */
168 if(athr26_init_flag1){
173 athrs26_reg_write(0x0, athrs26_reg_read(0x0) | 0x80000000);
180 if(!(athrs26_reg_read(0x0) & 0x80000000)){
185 for(phyUnit = 0; phyUnit < ATHR_PHY_MAX - 1; phyUnit++){
186 //phyBase = ATHR_PHYBASE(phyUnit);
187 phyAddr = ATHR_PHYADDR(phyUnit);
189 ar7240_revid = ar7240_reg_rd(AR7240_REV_ID) & AR7240_REV_ID_MASK;
190 if(ar7240_revid == AR7240_REV_1_0){
191 #ifdef S26_FORCE_100M
193 * Force MDI and MDX to alternate ports
198 s26_wr_phy(phyAddr, ATHR_PHY_FUNC_CONTROL, 0x820);
200 s26_wr_phy(phyAddr, ATHR_PHY_FUNC_CONTROL, 0x800);
203 s26_wr_phy(phyAddr, ATHR_PHY_CONTROL, 0xa100);
208 * Force MDI and MDX to alternate ports
213 s26_wr_phy(phyAddr,ATHR_PHY_FUNC_CONTROL,0x820);
215 s26_wr_phy(phyAddr,ATHR_PHY_FUNC_CONTROL,0x800);
218 athrs26_powersave_off(phyAddr);
219 athrs26_sleep_off(phyAddr);
221 s26_wr_phy(phyAddr,ATHR_PHY_CONTROL,0x8100);
222 s26_wr_phy(phyAddr,ATHR_DEBUG_PORT_ADDRESS,0x0);
223 s26_wr_phy(phyAddr,ATHR_DEBUG_PORT_DATA,0x12ee);
224 s26_wr_phy(phyAddr,ATHR_DEBUG_PORT_ADDRESS,0x3);
225 s26_wr_phy(phyAddr,ATHR_DEBUG_PORT_DATA,0x3bf0);
226 s26_wr_phy(phyAddr,ATHR_PHY_CONTROL,0x8100);
229 s26_wr_phy(phyAddr, ATHR_PHY_CONTROL, 0x9000);
233 rd_val = s26_rd_phy(phyAddr,ATHR_PHY_ID1);
234 printf("S26 PHY ID (%d) :%x\n",phyAddr,rd_val);
236 rd_val = s26_rd_phy(phyAddr,ATHR_PHY_CONTROL);
237 printf("S26 PHY CTRL (%d) :%x\n",phyAddr,rd_val);
239 rd_val = s26_rd_phy(phyAddr,ATHR_PHY_STATUS);
240 printf("S26 ATHR PHY STATUS (%d) :%x\n",phyAddr,rd_val);
247 athrs26_reg_write(CPU_PORT_REGISTER, (1 << 8));
250 * status[1:0]=2'h2; - (0x10 - 1000 Mbps , 0x0 - 10 Mbps)
251 * status[2]=1'h1; - Tx Mac En
252 * status[3]=1'h1; - Rx Mac En
253 * status[4]=1'h1; - Tx Flow Ctrl En
254 * status[5]=1'h1; - Rx Flow Ctrl En
255 * status[6]=1'h1; - Duplex Mode
257 athrs26_reg_write(PORT_STATUS_REGISTER1, 0x200); /* LAN - 1 */
258 athrs26_reg_write(PORT_STATUS_REGISTER2, 0x200); /* LAN - 2 */
259 athrs26_reg_write(PORT_STATUS_REGISTER3, 0x200); /* LAN - 3 */
260 athrs26_reg_write(PORT_STATUS_REGISTER4, 0x200); /* LAN - 4 */
263 athrs26_reg_write(0x38, 0xc000050e);
266 * status[11]=1'h0; - CPU Disable
267 * status[7] = 1'b1; - Learn One Lock
268 * status[14] = 1'b0; - Learn Enable
270 /* Atheros Header Disable */
271 athrs26_reg_write(PORT_CONTROL_REGISTER0, 0x4004);
273 /* Tag Priority Mapping */
274 athrs26_reg_write(0x70, 0xfa50);
276 /* Enable ARP packets to CPU port */
277 athrs26_reg_write(S26_ARL_TBL_CTRL_REG, (athrs26_reg_read(S26_ARL_TBL_CTRL_REG) | 0x100000));
279 /* Enable Broadcast packets to CPU port */
280 athrs26_reg_write(S26_FLD_MASK_REG, (athrs26_reg_read(S26_FLD_MASK_REG) | S26_ENABLE_CPU_BROADCAST));
283 rd_val = athrs26_reg_read ( CPU_PORT_REGISTER );
284 printf("S26 CPU_PORT_REGISTER :%x\n",rd_val);
286 rd_val = athrs26_reg_read ( PORT_STATUS_REGISTER0 );
287 printf("S26 PORT_STATUS_REGISTER0 :%x\n",rd_val);
289 rd_val = athrs26_reg_read ( PORT_STATUS_REGISTER1 );
290 printf("S26 PORT_STATUS_REGISTER1 :%x\n",rd_val);
292 rd_val = athrs26_reg_read ( PORT_STATUS_REGISTER2 );
293 printf("S26 PORT_STATUS_REGISTER2 :%x\n",rd_val);
295 rd_val = athrs26_reg_read ( PORT_STATUS_REGISTER3 );
296 printf("S26 PORT_STATUS_REGISTER3 :%x\n",rd_val);
298 rd_val = athrs26_reg_read ( PORT_STATUS_REGISTER4 );
299 printf("S26 PORT_STATUS_REGISTER4 :%x\n",rd_val);
301 rd_val = athrs26_reg_read ( PORT_CONTROL_REGISTER0 );
302 printf("S26 PORT_CONTROL_REGISTER0 :%x\n",rd_val);
304 rd_val = athrs26_reg_read ( PORT_CONTROL_REGISTER1 );
305 printf("S26 PORT_CONTROL_REGISTER1 :%x\n",rd_val);
307 rd_val = athrs26_reg_read ( PORT_CONTROL_REGISTER2 );
308 printf("S26 PORT_CONTROL_REGISTER2 :%x\n",rd_val);
310 rd_val = athrs26_reg_read ( PORT_CONTROL_REGISTER3 );
311 printf("S26 PORT_CONTROL_REGISTER3 :%x\n",rd_val);
313 rd_val = athrs26_reg_read ( PORT_CONTROL_REGISTER4 );
314 printf("S26 PORT_CONTROL_REGISTER4 :%x\n",rd_val);
317 athr26_init_flag1 = 1;
320 /******************************************************************************
322 * athrs26_phy_is_link_alive - test to see if the specified link is alive
325 * TRUE --> link is alive
326 * FALSE --> link is down
328 int athrs26_phy_is_link_alive(int phyUnit){
329 uint16_t phyHwStatus;
333 //phyBase = ATHR_PHYBASE(phyUnit);
334 phyAddr = ATHR_PHYADDR(phyUnit);
336 phyHwStatus = s26_rd_phy(phyAddr, ATHR_PHY_SPEC_STATUS);
338 if(phyHwStatus & ATHR_STATUS_LINK_PASS){
345 /******************************************************************************
347 * athrs26_phy_setup - reset and setup the PHY associated with
348 * the specified MAC unit number.
350 * Resets the associated PHY port.
353 * TRUE --> associated PHY is alive
354 * FALSE --> no LINKs on this ethernet unit
356 int athrs26_phy_setup(int ethUnit){
359 uint16_t phyHwStatus;
361 //uint32_t phyBase = 0;
362 uint32_t phyAddr = 0;
363 uint32_t ar7240_revid;
364 int foundPhy = FALSE;
369 /* See if there's any configuration data for this enet */
370 /* start auto negogiation on each phy */
371 for(phyUnit = 0; phyUnit < ATHR_PHY_MAX; phyUnit++){
372 if(!ATHR_IS_ETHUNIT(phyUnit, ethUnit)){
377 //phyBase = ATHR_PHYBASE(phyUnit);
378 phyAddr = ATHR_PHYADDR(phyUnit);
380 s26_wr_phy(phyAddr, ATHR_AUTONEG_ADVERT, ATHR_ADVERTISE_ALL);
383 rd_val = s26_rd_phy(phyAddr,ATHR_AUTONEG_ADVERT );
384 printf("%s ATHR_AUTONEG_ADVERT %d :%x\n",__func__,phyAddr, rd_val);
387 ar7240_revid = ar7240_reg_rd(AR7240_REV_ID) & AR7240_REV_ID_MASK;
389 if(ar7240_revid != AR7240_REV_1_0){
390 s26_wr_phy(phyAddr, ATHR_PHY_CONTROL, ATHR_CTRL_AUTONEGOTIATION_ENABLE | ATHR_CTRL_SOFTWARE_RESET);
394 rd_val = s26_rd_phy(phyAddr,ATHR_AUTONEG_ADVERT );
395 rd_val = s26_rd_phy(phyAddr,ATHR_PHY_CONTROL);
396 printf("%s ATHR_PHY_CONTROL %d :%x\n",__func__,phyAddr, rd_val);
401 /* No PHY's configured for this ethUnit */
406 * After the phy is reset, it takes a little while before
407 * it can respond properly.
410 if(ethUnit == ENET_UNIT_LAN){
418 * Wait up to 3 seconds for ALL associated PHYs to finish
419 * autonegotiation. The only way we get out of here sooner is
420 * if ALL PHYs are connected AND finish autonegotiation.
422 for(phyUnit = 0; (phyUnit < ATHR_PHY_MAX); phyUnit++){
423 if(!ATHR_IS_ETHUNIT(phyUnit, ethUnit)){
430 phyHwStatus = s26_rd_phy(phyAddr, ATHR_PHY_CONTROL);
432 if(ATHR_RESET_DONE(phyHwStatus)){
433 DRV_PRINT(DRV_DEBUG_PHYSETUP, ("Port %d, Neg Success\n", phyUnit));
438 DRV_PRINT(DRV_DEBUG_PHYSETUP, ("Port %d, Negogiation timeout\n", phyUnit));
443 DRV_PRINT(DRV_DEBUG_PHYSETUP, ("Port %d, Negogiation timeout\n", phyUnit));
453 s26_wr_phy(phyUnit, 29, 0x14);
454 s26_wr_phy(phyUnit, 30, 0x1352);
457 //turn off power saving
458 s26_wr_phy(phyUnit, 29, 41);
459 s26_wr_phy(phyUnit, 30, 0);
460 printf("def_ S26_VER_1_0\n");
465 * All PHYs have had adequate time to autonegotiate.
466 * Now initialize software status.
468 * It's possible that some ports may take a bit longer
469 * to autonegotiate; but we can't wait forever. They'll
470 * get noticed by mv_phyCheckStatusChange during regular
471 * polling activities.
473 for(phyUnit = 0; phyUnit < ATHR_PHY_MAX; phyUnit++){
474 if(!ATHR_IS_ETHUNIT(phyUnit, ethUnit)){
478 if(athrs26_phy_is_link_alive(phyUnit)){
480 ATHR_IS_PHY_ALIVE(phyUnit) = TRUE;
482 ATHR_IS_PHY_ALIVE(phyUnit) = FALSE;
485 DRV_PRINT(DRV_DEBUG_PHYSETUP, ("eth%d: Phy Specific Status=%4.4x\n", ethUnit, s26_rd_phy(ATHR_PHYADDR(phyUnit),ATHR_PHY_SPEC_STATUS)));
488 return(liveLinks > 0);
491 /******************************************************************************
493 * athrs26_phy_is_fdx - Determines whether the phy ports associated with the
494 * specified device are FULL or HALF duplex.
500 int athrs26_phy_is_fdx(int ethUnit){
504 uint16_t phyHwStatus;
507 if(ethUnit == ENET_UNIT_LAN){
511 for(phyUnit = 0; phyUnit < ATHR_PHY_MAX; phyUnit++){
512 if(!ATHR_IS_ETHUNIT(phyUnit, ethUnit)){
516 if(athrs26_phy_is_link_alive(phyUnit)){
518 //phyBase = ATHR_PHYBASE(phyUnit);
519 //phyAddr = ATHR_PHYADDR(phyUnit);
522 phyHwStatus = s26_rd_phy(ATHR_PHYADDR(phyUnit), ATHR_PHY_SPEC_STATUS);
524 } while((!(phyHwStatus & ATHR_STATUS_RESOVLED)) && --ii);
526 if(phyHwStatus & ATHER_STATUS_FULL_DEPLEX){
535 /******************************************************************************
537 * athrs26_phy_speed - Determines the speed of phy ports associated with the
541 * _10BASET, _100BASET;
545 int athrs26_phy_speed(int ethUnit){
547 uint16_t phyHwStatus;
552 if(ethUnit == ENET_UNIT_LAN){
556 for(phyUnit = 0; phyUnit < ATHR_PHY_MAX; phyUnit++){
557 if(!ATHR_IS_ETHUNIT(phyUnit, ethUnit)){
561 if(athrs26_phy_is_link_alive(phyUnit)){
563 //phyBase = ATHR_PHYBASE(phyUnit);
564 phyAddr = ATHR_PHYADDR(phyUnit);
566 phyHwStatus = s26_rd_phy(ATHR_PHYADDR(phyUnit), ATHR_PHY_SPEC_STATUS);
568 } while((!(phyHwStatus & ATHR_STATUS_RESOVLED)) && --ii);
570 phyHwStatus = ((phyHwStatus & ATHER_STATUS_LINK_MASK) >> ATHER_STATUS_LINK_SHIFT);
576 #ifdef CONFIG_MACH_HORNET
577 /* For IEEE 100M voltage test */
578 s26_wr_phy(phyAddr, ATHR_DEBUG_PORT_ADDRESS, 0x4);
579 s26_wr_phy(phyAddr, ATHR_DEBUG_PORT_DATA, 0xebbb);
580 s26_wr_phy(phyAddr, ATHR_DEBUG_PORT_ADDRESS, 0x5);
581 s26_wr_phy(phyAddr, ATHR_DEBUG_PORT_DATA, 0x2c47);
582 #endif /* CONFIG_MACH_HORNET */
587 printf("## Error: unknown eth speed!\n");
595 /*****************************************************************************
597 * athr_phy_is_up -- checks for significant changes in PHY state.
599 * A "significant change" is:
600 * dropped link (e.g. ethernet cable unplugged) OR
601 * autonegotiation completed + link (e.g. ethernet cable plugged in)
603 * When a PHY is plugged in, phyLinkGained is called.
604 * When a PHY is unplugged, phyLinkLost is called.
607 int athrs26_phy_is_up(int ethUnit){
612 uint16_t phyHwStatus, phyHwControl;
613 athrPhyInfo_t *lastStatus;
617 for(phyUnit = 0; phyUnit < ATHR_PHY_MAX; phyUnit++){
618 if(!ATHR_IS_ETHUNIT(phyUnit, ethUnit)){
622 //phyBase = ATHR_PHYBASE(phyUnit);
623 //phyAddr = ATHR_PHYADDR(phyUnit);
625 lastStatus = &athrPhyInfo[phyUnit];
627 if(lastStatus->isPhyAlive){ /* last known link status was ALIVE */
629 phyHwStatus = s26_rd_phy(ATHR_PHYADDR(phyUnit), ATHR_PHY_SPEC_STATUS);
631 /* See if we've lost link */
632 if(phyHwStatus & ATHR_STATUS_LINK_PASS){ /* check realtime link */
635 phyHwStatus = s26_rd_phy(ATHR_PHYADDR(phyUnit), ATHR_PHY_STATUS);
636 /* If realtime failed check link in latch register before
637 * asserting link down.
639 if(phyHwStatus & ATHR_LATCH_LINK_PASS){
645 DRV_PRINT(DRV_DEBUG_PHYCHANGE,("\nenet%d port%d down\n", ethUnit, phyUnit));
646 lastStatus->isPhyAlive = FALSE;
648 } else { /* last known link status was DEAD */
650 /* Check for reset complete */
651 phyHwStatus = s26_rd_phy(ATHR_PHYADDR(phyUnit), ATHR_PHY_STATUS);
653 if(!ATHR_RESET_DONE(phyHwStatus)){
657 phyHwControl = s26_rd_phy(ATHR_PHYADDR(phyUnit), ATHR_PHY_CONTROL);
659 /* Check for AutoNegotiation complete */
660 if((!(phyHwControl & ATHR_CTRL_AUTONEGOTIATION_ENABLE)) || ATHR_AUTONEG_DONE(phyHwStatus)){
661 phyHwStatus = s26_rd_phy(ATHR_PHYADDR(phyUnit), ATHR_PHY_SPEC_STATUS);
663 if(phyHwStatus & ATHR_STATUS_LINK_PASS){
666 DRV_PRINT(DRV_DEBUG_PHYCHANGE,("\nenet%d port%d up\n", ethUnit, phyUnit));
667 lastStatus->isPhyAlive = TRUE;
678 /* We just lost the last link for this MAC */
679 phyLinkLost(ethUnit);
682 if(gainedLinks == linkCount){
683 /* We just gained our first link(s) for this MAC */
684 phyLinkGained(ethUnit);
690 uint32_t athrs26_reg_read(unsigned int s26_addr){
691 unsigned int addr_temp;
692 unsigned int s26_rd_csr_low, s26_rd_csr_high, s26_rd_csr;
693 unsigned int data, unit = 0;
694 unsigned int phy_address, reg_address;
696 addr_temp = (s26_addr & 0xfffffffc) >> 2;
697 data = addr_temp >> 7;
704 } else if(is_ar7241() || is_ar7242() || is_ar933x()){
708 phy_reg_write(unit, phy_address, reg_address, data);
710 phy_address = (0x17 & ((addr_temp >> 4) | 0x10));
711 reg_address = ((addr_temp << 1) & 0x1e);
712 s26_rd_csr_low = (uint32_t)phy_reg_read(unit, phy_address, reg_address);
714 reg_address = reg_address | 0x1;
715 s26_rd_csr_high = (uint32_t)phy_reg_read(unit, phy_address, reg_address);
716 s26_rd_csr = (s26_rd_csr_high << 16) | s26_rd_csr_low;
721 void athrs26_reg_write(unsigned int s26_addr, unsigned int s26_write_data){
722 unsigned int addr_temp;
723 unsigned int data, unit = 0;
724 unsigned int phy_address, reg_address;
726 addr_temp = (s26_addr & 0xfffffffc) >> 2;
727 data = addr_temp >> 7;
734 } else if(is_ar7241() || is_ar7242() || is_ar933x()){
738 #ifdef CONFIG_MACH_HORNET
739 //The write sequence , 0x98: L->H, 0x40 H->L, 0x50 H->L , others should not care.
741 //printf("[%s:%d] unit=%d\n",__FUNCTION__,__LINE__,unit);
742 phy_reg_write(unit, phy_address, reg_address, data);
744 phy_address = 0x17 & ((addr_temp >> 4) | 0x10);
745 reg_address = ((addr_temp << 1) & 0x1e) | 0x1;
746 data = s26_write_data >> 16;
747 phy_reg_write(unit, phy_address, reg_address, data);
749 reg_address = reg_address & 0x1e;
750 data = s26_write_data & 0xffff;
751 phy_reg_write(unit, phy_address, reg_address, data);
753 phy_reg_write(unit, phy_address, reg_address, data);
755 phy_address = (0x17 & ((addr_temp >> 4) | 0x10));
756 reg_address = ((addr_temp << 1) & 0x1e);
758 data = s26_write_data & 0xffff;
759 phy_reg_write(unit, phy_address, reg_address, data);
761 reg_address = (((addr_temp << 1) & 0x1e) | 0x1);
762 data = s26_write_data >> 16;
763 phy_reg_write(unit, phy_address, reg_address, data);
766 phy_reg_write(unit, phy_address, reg_address, data);
768 phy_address = (0x17 & ((addr_temp >> 4) | 0x10));
769 reg_address = ((addr_temp << 1) & 0x1e);
770 data = s26_write_data & 0xffff;
771 phy_reg_write(unit, phy_address, reg_address, data);
773 reg_address = (((addr_temp << 1) & 0x1e) | 0x1);
774 data = s26_write_data >> 16;
775 phy_reg_write(unit, phy_address, reg_address, data);
779 unsigned int s26_rd_phy(unsigned int phy_addr, unsigned int reg_addr){
783 // MDIO_CMD is set for read
784 rddata = athrs26_reg_read(0x98);
785 rddata = (rddata & 0x0) | (reg_addr << 16) | (phy_addr << 21) | (1 << 27) | (1 << 30) | (1 << 31);
786 athrs26_reg_write(0x98, rddata);
788 rddata = athrs26_reg_read(0x98);
789 rddata = rddata & (1 << 31);
791 // Check MDIO_BUSY status
793 // TODO: do we need this?
797 printf("## Error: MDIO_BUSY!\n");
801 rddata = athrs26_reg_read(0x98);
802 rddata = rddata & (1 << 31);
805 // Read the data from phy
806 rddata = athrs26_reg_read(0x98) & 0xffff;
811 void s26_wr_phy(unsigned int phy_addr, unsigned int reg_addr, unsigned int write_data){
815 // MDIO_CMD is set for read
816 rddata = athrs26_reg_read(0x98);
817 rddata = (rddata & 0x0) | (write_data & 0xffff) | (reg_addr << 16) | (phy_addr << 21) | (0 << 27) | (1 << 30) | (1 << 31);
818 athrs26_reg_write(0x98, rddata);
820 rddata = athrs26_reg_read(0x98);
821 rddata = rddata & (1 << 31);
823 // Check MDIO_BUSY status
825 // TODO: do we need this?
829 printf("## Error: MDIO_BUSY!\n");
833 rddata = athrs26_reg_read(0x98);
834 rddata = rddata & (1 << 31);
839 int athrs26_mdc_check(void){
842 for(i = 0; i < 4000; i++){
843 if(athrs26_reg_read(0x10c) != 0x18007fff){