1*6a8a5dc4Sgoda.yusuke /* 2*6a8a5dc4Sgoda.yusuke * AX88796L(NE2000) support 3*6a8a5dc4Sgoda.yusuke * 4*6a8a5dc4Sgoda.yusuke * (c) 2007 Nobuhiro Iwamatsu <iwamatsu@nigauri.org> 5*6a8a5dc4Sgoda.yusuke * 6*6a8a5dc4Sgoda.yusuke * This program is free software; you can redistribute it and/or 7*6a8a5dc4Sgoda.yusuke * modify it under the terms of the GNU General Public License as 8*6a8a5dc4Sgoda.yusuke * published by the Free Software Foundation; either version 2 of 9*6a8a5dc4Sgoda.yusuke * the License, or (at your option) any later version. 10*6a8a5dc4Sgoda.yusuke * 11*6a8a5dc4Sgoda.yusuke * This program is distributed in the hope that it will be useful, 12*6a8a5dc4Sgoda.yusuke * but WITHOUT ANY WARRANTY; without even the implied warranty of 13*6a8a5dc4Sgoda.yusuke * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*6a8a5dc4Sgoda.yusuke * GNU General Public License for more details. 15*6a8a5dc4Sgoda.yusuke * 16*6a8a5dc4Sgoda.yusuke * You should have received a copy of the GNU General Public License 17*6a8a5dc4Sgoda.yusuke * along with this program; if not, write to the Free Software 18*6a8a5dc4Sgoda.yusuke * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 19*6a8a5dc4Sgoda.yusuke * MA 02111-1307 USA 20*6a8a5dc4Sgoda.yusuke * 21*6a8a5dc4Sgoda.yusuke */ 22*6a8a5dc4Sgoda.yusuke 23*6a8a5dc4Sgoda.yusuke #ifndef __DRIVERS_AX88796L_H__ 24*6a8a5dc4Sgoda.yusuke #define __DRIVERS_AX88796L_H__ 25*6a8a5dc4Sgoda.yusuke 26*6a8a5dc4Sgoda.yusuke #define DP_DATA (0x10 << 1) 27*6a8a5dc4Sgoda.yusuke #define START_PG 0x40 /* First page of TX buffer */ 28*6a8a5dc4Sgoda.yusuke #define START_PG2 0x48 29*6a8a5dc4Sgoda.yusuke #define STOP_PG 0x80 /* Last page +1 of RX ring */ 30*6a8a5dc4Sgoda.yusuke #define TX_PAGES 12 31*6a8a5dc4Sgoda.yusuke #define RX_START (START_PG+TX_PAGES) 32*6a8a5dc4Sgoda.yusuke #define RX_END STOP_PG 33*6a8a5dc4Sgoda.yusuke 34*6a8a5dc4Sgoda.yusuke #define AX88796L_BASE_ADDRESS CONFIG_DRIVER_NE2000_BASE 35*6a8a5dc4Sgoda.yusuke #define AX88796L_BYTE_ACCESS 0x00001000 36*6a8a5dc4Sgoda.yusuke #define AX88796L_OFFSET 0x00000400 37*6a8a5dc4Sgoda.yusuke #define AX88796L_ADDRESS_BYTE AX88796L_BASE_ADDRESS + \ 38*6a8a5dc4Sgoda.yusuke AX88796L_BYTE_ACCESS + AX88796L_OFFSET 39*6a8a5dc4Sgoda.yusuke #define AX88796L_REG_MEMR AX88796L_ADDRESS_BYTE + (0x14<<1) 40*6a8a5dc4Sgoda.yusuke #define AX88796L_REG_CR AX88796L_ADDRESS_BYTE + (0x00<<1) 41*6a8a5dc4Sgoda.yusuke 42*6a8a5dc4Sgoda.yusuke #define AX88796L_CR (*(vu_short *)(AX88796L_REG_CR)) 43*6a8a5dc4Sgoda.yusuke #define AX88796L_MEMR (*(vu_short *)(AX88796L_REG_MEMR)) 44*6a8a5dc4Sgoda.yusuke 45*6a8a5dc4Sgoda.yusuke #define EECS_HIGH (AX88796L_MEMR |= 0x10) 46*6a8a5dc4Sgoda.yusuke #define EECS_LOW (AX88796L_MEMR &= 0xef) 47*6a8a5dc4Sgoda.yusuke #define EECLK_HIGH (AX88796L_MEMR |= 0x80) 48*6a8a5dc4Sgoda.yusuke #define EECLK_LOW (AX88796L_MEMR &= 0x7f) 49*6a8a5dc4Sgoda.yusuke #define EEDI_HIGH (AX88796L_MEMR |= 0x20) 50*6a8a5dc4Sgoda.yusuke #define EEDI_LOW (AX88796L_MEMR &= 0xdf) 51*6a8a5dc4Sgoda.yusuke #define EEDO ((AX88796L_MEMR & 0x40)>>6) 52*6a8a5dc4Sgoda.yusuke 53*6a8a5dc4Sgoda.yusuke #define PAGE0_SET (AX88796L_CR &= 0x3f) 54*6a8a5dc4Sgoda.yusuke #define PAGE1_SET (AX88796L_CR = (AX88796L_CR & 0x3f) | 0x40) 55*6a8a5dc4Sgoda.yusuke 56*6a8a5dc4Sgoda.yusuke #define BIT_DUMMY 0 57*6a8a5dc4Sgoda.yusuke #define MAC_EEP_READ 1 58*6a8a5dc4Sgoda.yusuke #define MAC_EEP_WRITE 2 59*6a8a5dc4Sgoda.yusuke #define MAC_EEP_ERACE 3 60*6a8a5dc4Sgoda.yusuke #define MAC_EEP_EWEN 4 61*6a8a5dc4Sgoda.yusuke #define MAC_EEP_EWDS 5 62*6a8a5dc4Sgoda.yusuke 63*6a8a5dc4Sgoda.yusuke /* R7780MP Specific code */ 64*6a8a5dc4Sgoda.yusuke #if defined(CONFIG_R7780MP) 65*6a8a5dc4Sgoda.yusuke #define ISA_OFFSET 0x1400 66*6a8a5dc4Sgoda.yusuke #define DP_IN(_b_, _o_, _d_) (_d_) = \ 67*6a8a5dc4Sgoda.yusuke *( (vu_short *) ((_b_) + ((_o_) * 2) + ISA_OFFSET)) 68*6a8a5dc4Sgoda.yusuke #define DP_OUT(_b_, _o_, _d_) \ 69*6a8a5dc4Sgoda.yusuke *((vu_short *)((_b_) + ((_o_) * 2) + ISA_OFFSET)) = (_d_) 70*6a8a5dc4Sgoda.yusuke #define DP_IN_DATA(_b_, _d_) (_d_) = *( (vu_short *) ((_b_) + ISA_OFFSET)) 71*6a8a5dc4Sgoda.yusuke #define DP_OUT_DATA(_b_, _d_) *( (vu_short *) ((_b_)+ISA_OFFSET)) = (_d_) 72*6a8a5dc4Sgoda.yusuke #else 73*6a8a5dc4Sgoda.yusuke /* Please change for your target boards */ 74*6a8a5dc4Sgoda.yusuke #define ISA_OFFSET 0x0000 75*6a8a5dc4Sgoda.yusuke #define DP_IN(_b_, _o_, _d_) (_d_) = *( (vu_short *)((_b_)+(_o_ )+ISA_OFFSET)) 76*6a8a5dc4Sgoda.yusuke #define DP_OUT(_b_, _o_, _d_) *((vu_short *)((_b_)+(_o_)+ISA_OFFSET)) = (_d_) 77*6a8a5dc4Sgoda.yusuke #define DP_IN_DATA(_b_, _d_) (_d_) = *( (vu_short *) ((_b_)+ISA_OFFSET)) 78*6a8a5dc4Sgoda.yusuke #define DP_OUT_DATA(_b_, _d_) *( (vu_short *) ((_b_)+ISA_OFFSET)) = (_d_) 79*6a8a5dc4Sgoda.yusuke #endif 80*6a8a5dc4Sgoda.yusuke 81*6a8a5dc4Sgoda.yusuke 82*6a8a5dc4Sgoda.yusuke /* 83*6a8a5dc4Sgoda.yusuke * Set 1 bit data 84*6a8a5dc4Sgoda.yusuke */ 85*6a8a5dc4Sgoda.yusuke static void ax88796_bitset(u32 bit) 86*6a8a5dc4Sgoda.yusuke { 87*6a8a5dc4Sgoda.yusuke /* DATA1 */ 88*6a8a5dc4Sgoda.yusuke if( bit ) 89*6a8a5dc4Sgoda.yusuke EEDI_HIGH; 90*6a8a5dc4Sgoda.yusuke else 91*6a8a5dc4Sgoda.yusuke EEDI_LOW; 92*6a8a5dc4Sgoda.yusuke 93*6a8a5dc4Sgoda.yusuke EECLK_LOW; 94*6a8a5dc4Sgoda.yusuke udelay(1000); 95*6a8a5dc4Sgoda.yusuke EECLK_HIGH; 96*6a8a5dc4Sgoda.yusuke udelay(1000); 97*6a8a5dc4Sgoda.yusuke EEDI_LOW; 98*6a8a5dc4Sgoda.yusuke } 99*6a8a5dc4Sgoda.yusuke 100*6a8a5dc4Sgoda.yusuke /* 101*6a8a5dc4Sgoda.yusuke * Get 1 bit data 102*6a8a5dc4Sgoda.yusuke */ 103*6a8a5dc4Sgoda.yusuke static u8 ax88796_bitget(void) 104*6a8a5dc4Sgoda.yusuke { 105*6a8a5dc4Sgoda.yusuke u8 bit; 106*6a8a5dc4Sgoda.yusuke 107*6a8a5dc4Sgoda.yusuke EECLK_LOW; 108*6a8a5dc4Sgoda.yusuke udelay(1000); 109*6a8a5dc4Sgoda.yusuke /* DATA */ 110*6a8a5dc4Sgoda.yusuke bit = EEDO; 111*6a8a5dc4Sgoda.yusuke EECLK_HIGH; 112*6a8a5dc4Sgoda.yusuke udelay(1000); 113*6a8a5dc4Sgoda.yusuke 114*6a8a5dc4Sgoda.yusuke return bit; 115*6a8a5dc4Sgoda.yusuke } 116*6a8a5dc4Sgoda.yusuke 117*6a8a5dc4Sgoda.yusuke /* 118*6a8a5dc4Sgoda.yusuke * Send COMMAND to EEPROM 119*6a8a5dc4Sgoda.yusuke */ 120*6a8a5dc4Sgoda.yusuke static void ax88796_eep_cmd(u8 cmd) 121*6a8a5dc4Sgoda.yusuke { 122*6a8a5dc4Sgoda.yusuke ax88796_bitset(BIT_DUMMY); 123*6a8a5dc4Sgoda.yusuke switch(cmd){ 124*6a8a5dc4Sgoda.yusuke case MAC_EEP_READ: 125*6a8a5dc4Sgoda.yusuke ax88796_bitset(1); 126*6a8a5dc4Sgoda.yusuke ax88796_bitset(1); 127*6a8a5dc4Sgoda.yusuke ax88796_bitset(0); 128*6a8a5dc4Sgoda.yusuke break; 129*6a8a5dc4Sgoda.yusuke 130*6a8a5dc4Sgoda.yusuke case MAC_EEP_WRITE: 131*6a8a5dc4Sgoda.yusuke ax88796_bitset(1); 132*6a8a5dc4Sgoda.yusuke ax88796_bitset(0); 133*6a8a5dc4Sgoda.yusuke ax88796_bitset(1); 134*6a8a5dc4Sgoda.yusuke break; 135*6a8a5dc4Sgoda.yusuke 136*6a8a5dc4Sgoda.yusuke case MAC_EEP_ERACE: 137*6a8a5dc4Sgoda.yusuke ax88796_bitset(1); 138*6a8a5dc4Sgoda.yusuke ax88796_bitset(1); 139*6a8a5dc4Sgoda.yusuke ax88796_bitset(1); 140*6a8a5dc4Sgoda.yusuke break; 141*6a8a5dc4Sgoda.yusuke 142*6a8a5dc4Sgoda.yusuke case MAC_EEP_EWEN: 143*6a8a5dc4Sgoda.yusuke ax88796_bitset(1); 144*6a8a5dc4Sgoda.yusuke ax88796_bitset(0); 145*6a8a5dc4Sgoda.yusuke ax88796_bitset(0); 146*6a8a5dc4Sgoda.yusuke break; 147*6a8a5dc4Sgoda.yusuke 148*6a8a5dc4Sgoda.yusuke case MAC_EEP_EWDS: 149*6a8a5dc4Sgoda.yusuke ax88796_bitset(1); 150*6a8a5dc4Sgoda.yusuke ax88796_bitset(0); 151*6a8a5dc4Sgoda.yusuke ax88796_bitset(0); 152*6a8a5dc4Sgoda.yusuke break; 153*6a8a5dc4Sgoda.yusuke default: 154*6a8a5dc4Sgoda.yusuke break; 155*6a8a5dc4Sgoda.yusuke } 156*6a8a5dc4Sgoda.yusuke } 157*6a8a5dc4Sgoda.yusuke 158*6a8a5dc4Sgoda.yusuke static void ax88796_eep_setaddr(u16 addr) 159*6a8a5dc4Sgoda.yusuke { 160*6a8a5dc4Sgoda.yusuke int i ; 161*6a8a5dc4Sgoda.yusuke for( i = 7 ; i >= 0 ; i-- ) 162*6a8a5dc4Sgoda.yusuke ax88796_bitset(addr & (1 << i)); 163*6a8a5dc4Sgoda.yusuke } 164*6a8a5dc4Sgoda.yusuke 165*6a8a5dc4Sgoda.yusuke /* 166*6a8a5dc4Sgoda.yusuke * Get data from EEPROM 167*6a8a5dc4Sgoda.yusuke */ 168*6a8a5dc4Sgoda.yusuke static u16 ax88796_eep_getdata(void) 169*6a8a5dc4Sgoda.yusuke { 170*6a8a5dc4Sgoda.yusuke ushort data = 0; 171*6a8a5dc4Sgoda.yusuke int i; 172*6a8a5dc4Sgoda.yusuke 173*6a8a5dc4Sgoda.yusuke ax88796_bitget(); /* DUMMY */ 174*6a8a5dc4Sgoda.yusuke for( i = 0 ; i < 16 ; i++ ){ 175*6a8a5dc4Sgoda.yusuke data <<= 1; 176*6a8a5dc4Sgoda.yusuke data |= ax88796_bitget(); 177*6a8a5dc4Sgoda.yusuke } 178*6a8a5dc4Sgoda.yusuke return data; 179*6a8a5dc4Sgoda.yusuke } 180*6a8a5dc4Sgoda.yusuke 181*6a8a5dc4Sgoda.yusuke static void ax88796_mac_read(u8 *buff) 182*6a8a5dc4Sgoda.yusuke { 183*6a8a5dc4Sgoda.yusuke int i ; 184*6a8a5dc4Sgoda.yusuke u16 data, addr = 0; 185*6a8a5dc4Sgoda.yusuke 186*6a8a5dc4Sgoda.yusuke for( i = 0 ; i < 3; i++ ) 187*6a8a5dc4Sgoda.yusuke { 188*6a8a5dc4Sgoda.yusuke EECS_HIGH; 189*6a8a5dc4Sgoda.yusuke EEDI_LOW; 190*6a8a5dc4Sgoda.yusuke udelay(1000); 191*6a8a5dc4Sgoda.yusuke /* READ COMMAND */ 192*6a8a5dc4Sgoda.yusuke ax88796_eep_cmd(MAC_EEP_READ); 193*6a8a5dc4Sgoda.yusuke /* ADDRESS */ 194*6a8a5dc4Sgoda.yusuke ax88796_eep_setaddr(addr++); 195*6a8a5dc4Sgoda.yusuke /* GET DATA */ 196*6a8a5dc4Sgoda.yusuke data = ax88796_eep_getdata(); 197*6a8a5dc4Sgoda.yusuke *buff++ = (uchar)(data & 0xff); 198*6a8a5dc4Sgoda.yusuke *buff++ = (uchar)((data >> 8) & 0xff); 199*6a8a5dc4Sgoda.yusuke EECLK_LOW; 200*6a8a5dc4Sgoda.yusuke EEDI_LOW; 201*6a8a5dc4Sgoda.yusuke EECS_LOW; 202*6a8a5dc4Sgoda.yusuke } 203*6a8a5dc4Sgoda.yusuke } 204*6a8a5dc4Sgoda.yusuke 205*6a8a5dc4Sgoda.yusuke int get_prom(u8* mac_addr) 206*6a8a5dc4Sgoda.yusuke { 207*6a8a5dc4Sgoda.yusuke u8 prom[32]; 208*6a8a5dc4Sgoda.yusuke int i; 209*6a8a5dc4Sgoda.yusuke 210*6a8a5dc4Sgoda.yusuke ax88796_mac_read(prom); 211*6a8a5dc4Sgoda.yusuke for (i = 0; i < 6; i++){ 212*6a8a5dc4Sgoda.yusuke mac_addr[i] = prom[i]; 213*6a8a5dc4Sgoda.yusuke } 214*6a8a5dc4Sgoda.yusuke return 1; 215*6a8a5dc4Sgoda.yusuke } 216*6a8a5dc4Sgoda.yusuke 217*6a8a5dc4Sgoda.yusuke #endif /* __DRIVERS_AX88796L_H__ */ 218