12439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 22439e4bfSJean-Christophe PLAGNIOL-VILLARD dm9000.c: Version 1.2 12/15/2003 32439e4bfSJean-Christophe PLAGNIOL-VILLARD 42439e4bfSJean-Christophe PLAGNIOL-VILLARD A Davicom DM9000 ISA NIC fast Ethernet driver for Linux. 52439e4bfSJean-Christophe PLAGNIOL-VILLARD Copyright (C) 1997 Sten Wang 62439e4bfSJean-Christophe PLAGNIOL-VILLARD 72439e4bfSJean-Christophe PLAGNIOL-VILLARD This program is free software; you can redistribute it and/or 82439e4bfSJean-Christophe PLAGNIOL-VILLARD modify it under the terms of the GNU General Public License 92439e4bfSJean-Christophe PLAGNIOL-VILLARD as published by the Free Software Foundation; either version 2 102439e4bfSJean-Christophe PLAGNIOL-VILLARD of the License, or (at your option) any later version. 112439e4bfSJean-Christophe PLAGNIOL-VILLARD 122439e4bfSJean-Christophe PLAGNIOL-VILLARD This program is distributed in the hope that it will be useful, 132439e4bfSJean-Christophe PLAGNIOL-VILLARD but WITHOUT ANY WARRANTY; without even the implied warranty of 142439e4bfSJean-Christophe PLAGNIOL-VILLARD MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 152439e4bfSJean-Christophe PLAGNIOL-VILLARD GNU General Public License for more details. 162439e4bfSJean-Christophe PLAGNIOL-VILLARD 172439e4bfSJean-Christophe PLAGNIOL-VILLARD (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved. 182439e4bfSJean-Christophe PLAGNIOL-VILLARD 192439e4bfSJean-Christophe PLAGNIOL-VILLARD V0.11 06/20/2001 REG_0A bit3=1, default enable BP with DA match 202439e4bfSJean-Christophe PLAGNIOL-VILLARD 06/22/2001 Support DM9801 progrmming 212439e4bfSJean-Christophe PLAGNIOL-VILLARD E3: R25 = ((R24 + NF) & 0x00ff) | 0xf000 222439e4bfSJean-Christophe PLAGNIOL-VILLARD E4: R25 = ((R24 + NF) & 0x00ff) | 0xc200 232439e4bfSJean-Christophe PLAGNIOL-VILLARD R17 = (R17 & 0xfff0) | NF + 3 242439e4bfSJean-Christophe PLAGNIOL-VILLARD E5: R25 = ((R24 + NF - 3) & 0x00ff) | 0xc200 252439e4bfSJean-Christophe PLAGNIOL-VILLARD R17 = (R17 & 0xfff0) | NF 262439e4bfSJean-Christophe PLAGNIOL-VILLARD 272439e4bfSJean-Christophe PLAGNIOL-VILLARD v1.00 modify by simon 2001.9.5 282439e4bfSJean-Christophe PLAGNIOL-VILLARD change for kernel 2.4.x 292439e4bfSJean-Christophe PLAGNIOL-VILLARD 302439e4bfSJean-Christophe PLAGNIOL-VILLARD v1.1 11/09/2001 fix force mode bug 312439e4bfSJean-Christophe PLAGNIOL-VILLARD 322439e4bfSJean-Christophe PLAGNIOL-VILLARD v1.2 03/18/2003 Weilun Huang <weilun_huang@davicom.com.tw>: 332439e4bfSJean-Christophe PLAGNIOL-VILLARD Fixed phy reset. 342439e4bfSJean-Christophe PLAGNIOL-VILLARD Added tx/rx 32 bit mode. 352439e4bfSJean-Christophe PLAGNIOL-VILLARD Cleaned up for kernel merge. 362439e4bfSJean-Christophe PLAGNIOL-VILLARD 372439e4bfSJean-Christophe PLAGNIOL-VILLARD -------------------------------------- 382439e4bfSJean-Christophe PLAGNIOL-VILLARD 39a101361bSRemy Bohmer 12/15/2003 Initial port to u-boot by 40a101361bSRemy Bohmer Sascha Hauer <saschahauer@web.de> 41a101361bSRemy Bohmer 42a101361bSRemy Bohmer 06/03/2008 Remy Bohmer <linux@bohmer.net> 43850ba755SRemy Bohmer - Fixed the driver to work with DM9000A. 44850ba755SRemy Bohmer (check on ISR receive status bit before reading the 45850ba755SRemy Bohmer FIFO as described in DM9000 programming guide and 46850ba755SRemy Bohmer application notes) 47a101361bSRemy Bohmer - Added autodetect of databus width. 48134e2662SRemy Bohmer - Made debug code compile again. 49acba3184SRemy Bohmer - Adapt eth_send such that it matches the DM9000* 50acba3184SRemy Bohmer application notes. Needed to make it work properly 51acba3184SRemy Bohmer for DM9000A. 52fbcb7eceSRemy Bohmer - Adapted reset procedure to match DM9000 application 53fbcb7eceSRemy Bohmer notes (i.e. double reset) 5498291e2eSRemy Bohmer - some minor code cleanups 55a101361bSRemy Bohmer These changes are tested with DM9000{A,EP,E} together 56a101361bSRemy Bohmer with a 200MHz Atmel AT91SAM92161 core 572439e4bfSJean-Christophe PLAGNIOL-VILLARD 58*d26b739aSAndrew Dyer TODO: external MII is not functional, only internal at the moment. 592439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 602439e4bfSJean-Christophe PLAGNIOL-VILLARD 612439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <common.h> 622439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <command.h> 632439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <net.h> 642439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <asm/io.h> 652439e4bfSJean-Christophe PLAGNIOL-VILLARD 662439e4bfSJean-Christophe PLAGNIOL-VILLARD #include "dm9000x.h" 672439e4bfSJean-Christophe PLAGNIOL-VILLARD 682439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Board/System/Debug information/definition ---------------- */ 692439e4bfSJean-Christophe PLAGNIOL-VILLARD 702439e4bfSJean-Christophe PLAGNIOL-VILLARD /* #define CONFIG_DM9000_DEBUG */ 712439e4bfSJean-Christophe PLAGNIOL-VILLARD 722439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_DM9000_DEBUG 732439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_DBG(fmt,args...) printf(fmt, ##args) 74134e2662SRemy Bohmer #define DM9000_DMP_PACKET(func,packet,length) \ 75134e2662SRemy Bohmer do { \ 76134e2662SRemy Bohmer int i; \ 77134e2662SRemy Bohmer printf(func ": length: %d\n", length); \ 78134e2662SRemy Bohmer for (i = 0; i < length; i++) { \ 79134e2662SRemy Bohmer if (i % 8 == 0) \ 80134e2662SRemy Bohmer printf("\n%s: %02x: ", func, i); \ 81134e2662SRemy Bohmer printf("%02x ", ((unsigned char *) packet)[i]); \ 82134e2662SRemy Bohmer } printf("\n"); \ 83134e2662SRemy Bohmer } while(0) 84134e2662SRemy Bohmer #else 852439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_DBG(fmt,args...) 86134e2662SRemy Bohmer #define DM9000_DMP_PACKET(func,packet,length) 87134e2662SRemy Bohmer #endif 88134e2662SRemy Bohmer 892439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Structure/enum declaration ------------------------------- */ 902439e4bfSJean-Christophe PLAGNIOL-VILLARD typedef struct board_info { 912439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 runt_length_counter; /* counter: RX length < 64byte */ 922439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 long_length_counter; /* counter: RX length > 1514byte */ 932439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 reset_counter; /* counter: RESET */ 942439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 reset_tx_timeout; /* RESET caused by TX Timeout */ 952439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 reset_rx_status; /* RESET caused by RX Statsus wrong */ 962439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 tx_pkt_cnt; 972439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 queue_start_addr; 982439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 dbug_cnt; 992439e4bfSJean-Christophe PLAGNIOL-VILLARD u8 phy_addr; 1002439e4bfSJean-Christophe PLAGNIOL-VILLARD u8 device_wait_reset; /* device state */ 1012439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned char srom[128]; 1020e38c938SRemy Bohmer void (*outblk)(volatile void *data_ptr, int count); 103a101361bSRemy Bohmer void (*inblk)(void *data_ptr, int count); 104a101361bSRemy Bohmer void (*rx_status)(u16 *RxStatus, u16 *RxLen); 1052439e4bfSJean-Christophe PLAGNIOL-VILLARD } board_info_t; 106a101361bSRemy Bohmer static board_info_t dm9000_info; 1072439e4bfSJean-Christophe PLAGNIOL-VILLARD 1082439e4bfSJean-Christophe PLAGNIOL-VILLARD /* function declaration ------------------------------------- */ 1092439e4bfSJean-Christophe PLAGNIOL-VILLARD int eth_init(bd_t * bd); 1102439e4bfSJean-Christophe PLAGNIOL-VILLARD int eth_send(volatile void *, int); 1112439e4bfSJean-Christophe PLAGNIOL-VILLARD int eth_rx(void); 1122439e4bfSJean-Christophe PLAGNIOL-VILLARD void eth_halt(void); 1132439e4bfSJean-Christophe PLAGNIOL-VILLARD static int dm9000_probe(void); 1142439e4bfSJean-Christophe PLAGNIOL-VILLARD static u16 phy_read(int); 1152439e4bfSJean-Christophe PLAGNIOL-VILLARD static void phy_write(int, u16); 1162439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 read_srom_word(int); 1172439e4bfSJean-Christophe PLAGNIOL-VILLARD static u8 DM9000_ior(int); 1182439e4bfSJean-Christophe PLAGNIOL-VILLARD static void DM9000_iow(int reg, u8 value); 1192439e4bfSJean-Christophe PLAGNIOL-VILLARD 1202439e4bfSJean-Christophe PLAGNIOL-VILLARD /* DM9000 network board routine ---------------------------- */ 1212439e4bfSJean-Christophe PLAGNIOL-VILLARD 1222439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_outb(d,r) ( *(volatile u8 *)r = d ) 1232439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_outw(d,r) ( *(volatile u16 *)r = d ) 1242439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_outl(d,r) ( *(volatile u32 *)r = d ) 1252439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_inb(r) (*(volatile u8 *)r) 1262439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_inw(r) (*(volatile u16 *)r) 1272439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_inl(r) (*(volatile u32 *)r) 1282439e4bfSJean-Christophe PLAGNIOL-VILLARD 1292439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_DM9000_DEBUG 1302439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 1312439e4bfSJean-Christophe PLAGNIOL-VILLARD dump_regs(void) 1322439e4bfSJean-Christophe PLAGNIOL-VILLARD { 1332439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("\n"); 1342439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("NCR (0x00): %02x\n", DM9000_ior(0)); 1352439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("NSR (0x01): %02x\n", DM9000_ior(1)); 1362439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("TCR (0x02): %02x\n", DM9000_ior(2)); 1372439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("TSRI (0x03): %02x\n", DM9000_ior(3)); 1382439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("TSRII (0x04): %02x\n", DM9000_ior(4)); 1392439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("RCR (0x05): %02x\n", DM9000_ior(5)); 1402439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("RSR (0x06): %02x\n", DM9000_ior(6)); 141134e2662SRemy Bohmer DM9000_DBG("ISR (0xFE): %02x\n", DM9000_ior(DM9000_ISR)); 1422439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("\n"); 1432439e4bfSJean-Christophe PLAGNIOL-VILLARD } 144a101361bSRemy Bohmer #endif 145a101361bSRemy Bohmer 1460e38c938SRemy Bohmer static void dm9000_outblk_8bit(volatile void *data_ptr, int count) 147a101361bSRemy Bohmer { 148a101361bSRemy Bohmer int i; 149a101361bSRemy Bohmer for (i = 0; i < count; i++) 150a101361bSRemy Bohmer DM9000_outb((((u8 *) data_ptr)[i] & 0xff), DM9000_DATA); 151a101361bSRemy Bohmer } 152a101361bSRemy Bohmer 1530e38c938SRemy Bohmer static void dm9000_outblk_16bit(volatile void *data_ptr, int count) 154a101361bSRemy Bohmer { 155a101361bSRemy Bohmer int i; 156a101361bSRemy Bohmer u32 tmplen = (count + 1) / 2; 157a101361bSRemy Bohmer 158a101361bSRemy Bohmer for (i = 0; i < tmplen; i++) 159a101361bSRemy Bohmer DM9000_outw(((u16 *) data_ptr)[i], DM9000_DATA); 160a101361bSRemy Bohmer } 1610e38c938SRemy Bohmer static void dm9000_outblk_32bit(volatile void *data_ptr, int count) 162a101361bSRemy Bohmer { 163a101361bSRemy Bohmer int i; 164a101361bSRemy Bohmer u32 tmplen = (count + 3) / 4; 165a101361bSRemy Bohmer 166a101361bSRemy Bohmer for (i = 0; i < tmplen; i++) 167a101361bSRemy Bohmer DM9000_outl(((u32 *) data_ptr)[i], DM9000_DATA); 168a101361bSRemy Bohmer } 169a101361bSRemy Bohmer 170a101361bSRemy Bohmer static void dm9000_inblk_8bit(void *data_ptr, int count) 171a101361bSRemy Bohmer { 172a101361bSRemy Bohmer int i; 173a101361bSRemy Bohmer for (i = 0; i < count; i++) 174a101361bSRemy Bohmer ((u8 *) data_ptr)[i] = DM9000_inb(DM9000_DATA); 175a101361bSRemy Bohmer } 176a101361bSRemy Bohmer 177a101361bSRemy Bohmer static void dm9000_inblk_16bit(void *data_ptr, int count) 178a101361bSRemy Bohmer { 179a101361bSRemy Bohmer int i; 180a101361bSRemy Bohmer u32 tmplen = (count + 1) / 2; 181a101361bSRemy Bohmer 182a101361bSRemy Bohmer for (i = 0; i < tmplen; i++) 183a101361bSRemy Bohmer ((u16 *) data_ptr)[i] = DM9000_inw(DM9000_DATA); 184a101361bSRemy Bohmer } 185a101361bSRemy Bohmer static void dm9000_inblk_32bit(void *data_ptr, int count) 186a101361bSRemy Bohmer { 187a101361bSRemy Bohmer int i; 188a101361bSRemy Bohmer u32 tmplen = (count + 3) / 4; 189a101361bSRemy Bohmer 190a101361bSRemy Bohmer for (i = 0; i < tmplen; i++) 191a101361bSRemy Bohmer ((u32 *) data_ptr)[i] = DM9000_inl(DM9000_DATA); 192a101361bSRemy Bohmer } 193a101361bSRemy Bohmer 194a101361bSRemy Bohmer static void dm9000_rx_status_32bit(u16 *RxStatus, u16 *RxLen) 195a101361bSRemy Bohmer { 196d6ee5fa4SRemy Bohmer u32 tmpdata; 197a101361bSRemy Bohmer 198a101361bSRemy Bohmer DM9000_outb(DM9000_MRCMD, DM9000_IO); 199a101361bSRemy Bohmer 200d6ee5fa4SRemy Bohmer tmpdata = DM9000_inl(DM9000_DATA); 201943b825bSTsiChung Liew *RxStatus = __le16_to_cpu(tmpdata); 202943b825bSTsiChung Liew *RxLen = __le16_to_cpu(tmpdata >> 16); 203a101361bSRemy Bohmer } 204a101361bSRemy Bohmer 205a101361bSRemy Bohmer static void dm9000_rx_status_16bit(u16 *RxStatus, u16 *RxLen) 206a101361bSRemy Bohmer { 207a101361bSRemy Bohmer DM9000_outb(DM9000_MRCMD, DM9000_IO); 208a101361bSRemy Bohmer 209943b825bSTsiChung Liew *RxStatus = __le16_to_cpu(DM9000_inw(DM9000_DATA)); 210943b825bSTsiChung Liew *RxLen = __le16_to_cpu(DM9000_inw(DM9000_DATA)); 211a101361bSRemy Bohmer } 212a101361bSRemy Bohmer 213a101361bSRemy Bohmer static void dm9000_rx_status_8bit(u16 *RxStatus, u16 *RxLen) 214a101361bSRemy Bohmer { 215a101361bSRemy Bohmer DM9000_outb(DM9000_MRCMD, DM9000_IO); 216a101361bSRemy Bohmer 217943b825bSTsiChung Liew *RxStatus = 218943b825bSTsiChung Liew __le16_to_cpu(DM9000_inb(DM9000_DATA) + 219943b825bSTsiChung Liew (DM9000_inb(DM9000_DATA) << 8)); 220943b825bSTsiChung Liew *RxLen = 221943b825bSTsiChung Liew __le16_to_cpu(DM9000_inb(DM9000_DATA) + 222943b825bSTsiChung Liew (DM9000_inb(DM9000_DATA) << 8)); 223a101361bSRemy Bohmer } 2242439e4bfSJean-Christophe PLAGNIOL-VILLARD 2252439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 2262439e4bfSJean-Christophe PLAGNIOL-VILLARD Search DM9000 board, allocate space and register it 2272439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 2282439e4bfSJean-Christophe PLAGNIOL-VILLARD int 2292439e4bfSJean-Christophe PLAGNIOL-VILLARD dm9000_probe(void) 2302439e4bfSJean-Christophe PLAGNIOL-VILLARD { 2312439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 id_val; 2322439e4bfSJean-Christophe PLAGNIOL-VILLARD id_val = DM9000_ior(DM9000_VIDL); 2332439e4bfSJean-Christophe PLAGNIOL-VILLARD id_val |= DM9000_ior(DM9000_VIDH) << 8; 2342439e4bfSJean-Christophe PLAGNIOL-VILLARD id_val |= DM9000_ior(DM9000_PIDL) << 16; 2352439e4bfSJean-Christophe PLAGNIOL-VILLARD id_val |= DM9000_ior(DM9000_PIDH) << 24; 2362439e4bfSJean-Christophe PLAGNIOL-VILLARD if (id_val == DM9000_ID) { 2372439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("dm9000 i/o: 0x%x, id: 0x%x \n", CONFIG_DM9000_BASE, 2382439e4bfSJean-Christophe PLAGNIOL-VILLARD id_val); 2392439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 2402439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 2412439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("dm9000 not found at 0x%08x id: 0x%08x\n", 2422439e4bfSJean-Christophe PLAGNIOL-VILLARD CONFIG_DM9000_BASE, id_val); 2432439e4bfSJean-Christophe PLAGNIOL-VILLARD return -1; 2442439e4bfSJean-Christophe PLAGNIOL-VILLARD } 2452439e4bfSJean-Christophe PLAGNIOL-VILLARD } 2462439e4bfSJean-Christophe PLAGNIOL-VILLARD 2472439e4bfSJean-Christophe PLAGNIOL-VILLARD /* General Purpose dm9000 reset routine */ 2482439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 2492439e4bfSJean-Christophe PLAGNIOL-VILLARD dm9000_reset(void) 2502439e4bfSJean-Christophe PLAGNIOL-VILLARD { 251fbcb7eceSRemy Bohmer DM9000_DBG("resetting DM9000\n"); 252fbcb7eceSRemy Bohmer 253fbcb7eceSRemy Bohmer /* Reset DM9000, 254fbcb7eceSRemy Bohmer see DM9000 Application Notes V1.22 Jun 11, 2004 page 29 */ 255fbcb7eceSRemy Bohmer 256*d26b739aSAndrew Dyer /* DEBUG: Make all GPIO0 outputs, all others inputs */ 257*d26b739aSAndrew Dyer DM9000_iow(DM9000_GPCR, GPCR_GPIO0_OUT); 258fbcb7eceSRemy Bohmer /* Step 1: Power internal PHY by writing 0 to GPIO0 pin */ 259fbcb7eceSRemy Bohmer DM9000_iow(DM9000_GPR, 0); 260fbcb7eceSRemy Bohmer /* Step 2: Software reset */ 261*d26b739aSAndrew Dyer DM9000_iow(DM9000_NCR, (NCR_LBK_INT_MAC | NCR_RST)); 262fbcb7eceSRemy Bohmer 263fbcb7eceSRemy Bohmer do { 264fbcb7eceSRemy Bohmer DM9000_DBG("resetting the DM9000, 1st reset\n"); 265fbcb7eceSRemy Bohmer udelay(25); /* Wait at least 20 us */ 266fbcb7eceSRemy Bohmer } while (DM9000_ior(DM9000_NCR) & 1); 267fbcb7eceSRemy Bohmer 268fbcb7eceSRemy Bohmer DM9000_iow(DM9000_NCR, 0); 269*d26b739aSAndrew Dyer DM9000_iow(DM9000_NCR, (NCR_LBK_INT_MAC | NCR_RST)); /* Issue a second reset */ 270fbcb7eceSRemy Bohmer 271fbcb7eceSRemy Bohmer do { 272fbcb7eceSRemy Bohmer DM9000_DBG("resetting the DM9000, 2nd reset\n"); 273fbcb7eceSRemy Bohmer udelay(25); /* Wait at least 20 us */ 274fbcb7eceSRemy Bohmer } while (DM9000_ior(DM9000_NCR) & 1); 275fbcb7eceSRemy Bohmer 276fbcb7eceSRemy Bohmer /* Check whether the ethernet controller is present */ 277fbcb7eceSRemy Bohmer if ((DM9000_ior(DM9000_PIDL) != 0x0) || 278fbcb7eceSRemy Bohmer (DM9000_ior(DM9000_PIDH) != 0x90)) 279fbcb7eceSRemy Bohmer printf("ERROR: resetting DM9000 -> not responding\n"); 2802439e4bfSJean-Christophe PLAGNIOL-VILLARD } 2812439e4bfSJean-Christophe PLAGNIOL-VILLARD 2822439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Initilize dm9000 board 2832439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 2842439e4bfSJean-Christophe PLAGNIOL-VILLARD int 2852439e4bfSJean-Christophe PLAGNIOL-VILLARD eth_init(bd_t * bd) 2862439e4bfSJean-Christophe PLAGNIOL-VILLARD { 2872439e4bfSJean-Christophe PLAGNIOL-VILLARD int i, oft, lnk; 288a101361bSRemy Bohmer u8 io_mode; 289a101361bSRemy Bohmer struct board_info *db = &dm9000_info; 290a101361bSRemy Bohmer 2912439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("eth_init()\n"); 2922439e4bfSJean-Christophe PLAGNIOL-VILLARD 2932439e4bfSJean-Christophe PLAGNIOL-VILLARD /* RESET device */ 2942439e4bfSJean-Christophe PLAGNIOL-VILLARD dm9000_reset(); 295*d26b739aSAndrew Dyer 296*d26b739aSAndrew Dyer if (dm9000_probe() < 0) 297*d26b739aSAndrew Dyer return -1; 2982439e4bfSJean-Christophe PLAGNIOL-VILLARD 299a101361bSRemy Bohmer /* Auto-detect 8/16/32 bit mode, ISR Bit 6+7 indicate bus width */ 300a101361bSRemy Bohmer io_mode = DM9000_ior(DM9000_ISR) >> 6; 301a101361bSRemy Bohmer 302a101361bSRemy Bohmer switch (io_mode) { 303a101361bSRemy Bohmer case 0x0: /* 16-bit mode */ 304a101361bSRemy Bohmer printf("DM9000: running in 16 bit mode\n"); 305a101361bSRemy Bohmer db->outblk = dm9000_outblk_16bit; 306a101361bSRemy Bohmer db->inblk = dm9000_inblk_16bit; 307a101361bSRemy Bohmer db->rx_status = dm9000_rx_status_16bit; 308a101361bSRemy Bohmer break; 309a101361bSRemy Bohmer case 0x01: /* 32-bit mode */ 310a101361bSRemy Bohmer printf("DM9000: running in 32 bit mode\n"); 311a101361bSRemy Bohmer db->outblk = dm9000_outblk_32bit; 312a101361bSRemy Bohmer db->inblk = dm9000_inblk_32bit; 313a101361bSRemy Bohmer db->rx_status = dm9000_rx_status_32bit; 314a101361bSRemy Bohmer break; 315a101361bSRemy Bohmer case 0x02: /* 8 bit mode */ 316a101361bSRemy Bohmer printf("DM9000: running in 8 bit mode\n"); 317a101361bSRemy Bohmer db->outblk = dm9000_outblk_8bit; 318a101361bSRemy Bohmer db->inblk = dm9000_inblk_8bit; 319a101361bSRemy Bohmer db->rx_status = dm9000_rx_status_8bit; 320a101361bSRemy Bohmer break; 321a101361bSRemy Bohmer default: 322a101361bSRemy Bohmer /* Assume 8 bit mode, will probably not work anyway */ 323a101361bSRemy Bohmer printf("DM9000: Undefined IO-mode:0x%x\n", io_mode); 324a101361bSRemy Bohmer db->outblk = dm9000_outblk_8bit; 325a101361bSRemy Bohmer db->inblk = dm9000_inblk_8bit; 326a101361bSRemy Bohmer db->rx_status = dm9000_rx_status_8bit; 327a101361bSRemy Bohmer break; 328a101361bSRemy Bohmer } 329a101361bSRemy Bohmer 330*d26b739aSAndrew Dyer /* Program operating register, only internal phy supported */ 33198291e2eSRemy Bohmer DM9000_iow(DM9000_NCR, 0x0); 33298291e2eSRemy Bohmer /* TX Polling clear */ 33398291e2eSRemy Bohmer DM9000_iow(DM9000_TCR, 0); 33498291e2eSRemy Bohmer /* Less 3Kb, 200us */ 335*d26b739aSAndrew Dyer DM9000_iow(DM9000_BPTR, BPTR_BPHW(3) | BPTR_JPT_600US); 33698291e2eSRemy Bohmer /* Flow Control : High/Low Water */ 33798291e2eSRemy Bohmer DM9000_iow(DM9000_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8)); 33898291e2eSRemy Bohmer /* SH FIXME: This looks strange! Flow Control */ 33998291e2eSRemy Bohmer DM9000_iow(DM9000_FCR, 0x0); 34098291e2eSRemy Bohmer /* Special Mode */ 34198291e2eSRemy Bohmer DM9000_iow(DM9000_SMCR, 0); 34298291e2eSRemy Bohmer /* clear TX status */ 34398291e2eSRemy Bohmer DM9000_iow(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END); 34498291e2eSRemy Bohmer /* Clear interrupt status */ 345*d26b739aSAndrew Dyer DM9000_iow(DM9000_ISR, ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS); 3462439e4bfSJean-Christophe PLAGNIOL-VILLARD 3472439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set Node address */ 348*d26b739aSAndrew Dyer #if !defined(CONFIG_AT91SAM9261EK) 3492439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < 6; i++) 3502439e4bfSJean-Christophe PLAGNIOL-VILLARD ((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i); 351d99a8ff6SStelian Pop #endif 3522439e4bfSJean-Christophe PLAGNIOL-VILLARD 3532439e4bfSJean-Christophe PLAGNIOL-VILLARD if (is_zero_ether_addr(bd->bi_enetaddr) || 3542439e4bfSJean-Christophe PLAGNIOL-VILLARD is_multicast_ether_addr(bd->bi_enetaddr)) { 3552439e4bfSJean-Christophe PLAGNIOL-VILLARD /* try reading from environment */ 3562439e4bfSJean-Christophe PLAGNIOL-VILLARD u8 i; 3572439e4bfSJean-Christophe PLAGNIOL-VILLARD char *s, *e; 3582439e4bfSJean-Christophe PLAGNIOL-VILLARD s = getenv ("ethaddr"); 3592439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < 6; ++i) { 3602439e4bfSJean-Christophe PLAGNIOL-VILLARD bd->bi_enetaddr[i] = s ? 3612439e4bfSJean-Christophe PLAGNIOL-VILLARD simple_strtoul (s, &e, 16) : 0; 3622439e4bfSJean-Christophe PLAGNIOL-VILLARD if (s) 3632439e4bfSJean-Christophe PLAGNIOL-VILLARD s = (*e) ? e + 1 : e; 3642439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3652439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3662439e4bfSJean-Christophe PLAGNIOL-VILLARD 3672439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", bd->bi_enetaddr[0], 3682439e4bfSJean-Christophe PLAGNIOL-VILLARD bd->bi_enetaddr[1], bd->bi_enetaddr[2], bd->bi_enetaddr[3], 3692439e4bfSJean-Christophe PLAGNIOL-VILLARD bd->bi_enetaddr[4], bd->bi_enetaddr[5]); 370*d26b739aSAndrew Dyer 371*d26b739aSAndrew Dyer /* fill device MAC address registers */ 372*d26b739aSAndrew Dyer for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++) 3732439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(oft, bd->bi_enetaddr[i]); 3742439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0, oft = 0x16; i < 8; i++, oft++) 3752439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(oft, 0xff); 3762439e4bfSJean-Christophe PLAGNIOL-VILLARD 3772439e4bfSJean-Christophe PLAGNIOL-VILLARD /* read back mac, just to be sure */ 3782439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0, oft = 0x10; i < 6; i++, oft++) 3792439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("%02x:", DM9000_ior(oft)); 3802439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("\n"); 3812439e4bfSJean-Christophe PLAGNIOL-VILLARD 3822439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Activate DM9000 */ 38398291e2eSRemy Bohmer /* RX enable */ 38498291e2eSRemy Bohmer DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN); 38598291e2eSRemy Bohmer /* Enable TX/RX interrupt mask */ 38698291e2eSRemy Bohmer DM9000_iow(DM9000_IMR, IMR_PAR); 38798291e2eSRemy Bohmer 3882439e4bfSJean-Christophe PLAGNIOL-VILLARD i = 0; 3892439e4bfSJean-Christophe PLAGNIOL-VILLARD while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */ 3902439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1000); 3912439e4bfSJean-Christophe PLAGNIOL-VILLARD i++; 3922439e4bfSJean-Christophe PLAGNIOL-VILLARD if (i == 10000) { 3932439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("could not establish link\n"); 3942439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 3952439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3962439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3972439e4bfSJean-Christophe PLAGNIOL-VILLARD 3982439e4bfSJean-Christophe PLAGNIOL-VILLARD /* see what we've got */ 3992439e4bfSJean-Christophe PLAGNIOL-VILLARD lnk = phy_read(17) >> 12; 4002439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("operating at "); 4012439e4bfSJean-Christophe PLAGNIOL-VILLARD switch (lnk) { 4022439e4bfSJean-Christophe PLAGNIOL-VILLARD case 1: 4032439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("10M half duplex "); 4042439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 4052439e4bfSJean-Christophe PLAGNIOL-VILLARD case 2: 4062439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("10M full duplex "); 4072439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 4082439e4bfSJean-Christophe PLAGNIOL-VILLARD case 4: 4092439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("100M half duplex "); 4102439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 4112439e4bfSJean-Christophe PLAGNIOL-VILLARD case 8: 4122439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("100M full duplex "); 4132439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 4142439e4bfSJean-Christophe PLAGNIOL-VILLARD default: 4152439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("unknown: %d ", lnk); 4162439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 4172439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4182439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("mode\n"); 4192439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 4202439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4212439e4bfSJean-Christophe PLAGNIOL-VILLARD 4222439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 4232439e4bfSJean-Christophe PLAGNIOL-VILLARD Hardware start transmission. 4242439e4bfSJean-Christophe PLAGNIOL-VILLARD Send a packet to media from the upper layer. 4252439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 4262439e4bfSJean-Christophe PLAGNIOL-VILLARD int 4272439e4bfSJean-Christophe PLAGNIOL-VILLARD eth_send(volatile void *packet, int length) 4282439e4bfSJean-Christophe PLAGNIOL-VILLARD { 4292439e4bfSJean-Christophe PLAGNIOL-VILLARD int tmo; 430a101361bSRemy Bohmer struct board_info *db = &dm9000_info; 431a101361bSRemy Bohmer 432134e2662SRemy Bohmer DM9000_DMP_PACKET("eth_send", packet, length); 4332439e4bfSJean-Christophe PLAGNIOL-VILLARD 434acba3184SRemy Bohmer DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */ 435acba3184SRemy Bohmer 4362439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Move data to DM9000 TX RAM */ 437acba3184SRemy Bohmer DM9000_outb(DM9000_MWCMD, DM9000_IO); /* Prepare for TX-data */ 4382439e4bfSJean-Christophe PLAGNIOL-VILLARD 439a101361bSRemy Bohmer /* push the data to the TX-fifo */ 4400e38c938SRemy Bohmer (db->outblk)(packet, length); 4412439e4bfSJean-Christophe PLAGNIOL-VILLARD 4422439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set TX length to DM9000 */ 4432439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_TXPLL, length & 0xff); 4442439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_TXPLH, (length >> 8) & 0xff); 4452439e4bfSJean-Christophe PLAGNIOL-VILLARD 4462439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Issue TX polling command */ 4472439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */ 4482439e4bfSJean-Christophe PLAGNIOL-VILLARD 4492439e4bfSJean-Christophe PLAGNIOL-VILLARD /* wait for end of transmission */ 4502439e4bfSJean-Christophe PLAGNIOL-VILLARD tmo = get_timer(0) + 5 * CFG_HZ; 451acba3184SRemy Bohmer while ( !(DM9000_ior(DM9000_NSR) & (NSR_TX1END | NSR_TX2END)) || 452acba3184SRemy Bohmer !(DM9000_ior(DM9000_ISR) & IMR_PTM) ) { 4532439e4bfSJean-Christophe PLAGNIOL-VILLARD if (get_timer(0) >= tmo) { 4542439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("transmission timeout\n"); 4552439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 4562439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4572439e4bfSJean-Christophe PLAGNIOL-VILLARD } 458acba3184SRemy Bohmer DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */ 459acba3184SRemy Bohmer 4602439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("transmit done\n\n"); 4612439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 4622439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4632439e4bfSJean-Christophe PLAGNIOL-VILLARD 4642439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 4652439e4bfSJean-Christophe PLAGNIOL-VILLARD Stop the interface. 4662439e4bfSJean-Christophe PLAGNIOL-VILLARD The interface is stopped when it is brought. 4672439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 4682439e4bfSJean-Christophe PLAGNIOL-VILLARD void 4692439e4bfSJean-Christophe PLAGNIOL-VILLARD eth_halt(void) 4702439e4bfSJean-Christophe PLAGNIOL-VILLARD { 4712439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("eth_halt\n"); 4722439e4bfSJean-Christophe PLAGNIOL-VILLARD 4732439e4bfSJean-Christophe PLAGNIOL-VILLARD /* RESET devie */ 4742439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_write(0, 0x8000); /* PHY RESET */ 4752439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_GPR, 0x01); /* Power-Down PHY */ 4762439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_IMR, 0x80); /* Disable all interrupt */ 4772439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_RCR, 0x00); /* Disable RX */ 4782439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4792439e4bfSJean-Christophe PLAGNIOL-VILLARD 4802439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 4812439e4bfSJean-Christophe PLAGNIOL-VILLARD Received a packet and pass to upper layer 4822439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 4832439e4bfSJean-Christophe PLAGNIOL-VILLARD int 4842439e4bfSJean-Christophe PLAGNIOL-VILLARD eth_rx(void) 4852439e4bfSJean-Christophe PLAGNIOL-VILLARD { 4862439e4bfSJean-Christophe PLAGNIOL-VILLARD u8 rxbyte, *rdptr = (u8 *) NetRxPackets[0]; 4872439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 RxStatus, RxLen = 0; 488a101361bSRemy Bohmer struct board_info *db = &dm9000_info; 4892439e4bfSJean-Christophe PLAGNIOL-VILLARD 490850ba755SRemy Bohmer /* Check packet ready or not, we must check 491850ba755SRemy Bohmer the ISR status first for DM9000A */ 492850ba755SRemy Bohmer if (!(DM9000_ior(DM9000_ISR) & 0x01)) /* Rx-ISR bit must be set. */ 4932439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 4942439e4bfSJean-Christophe PLAGNIOL-VILLARD 495850ba755SRemy Bohmer DM9000_iow(DM9000_ISR, 0x01); /* clear PR status latched in bit 0 */ 496850ba755SRemy Bohmer 497850ba755SRemy Bohmer /* There is _at least_ 1 package in the fifo, read them all */ 498850ba755SRemy Bohmer for (;;) { 499850ba755SRemy Bohmer DM9000_ior(DM9000_MRCMDX); /* Dummy read */ 500850ba755SRemy Bohmer 5010e38c938SRemy Bohmer /* Get most updated data, 5020e38c938SRemy Bohmer only look at bits 0:1, See application notes DM9000 */ 5030e38c938SRemy Bohmer rxbyte = DM9000_inb(DM9000_DATA) & 0x03; 504850ba755SRemy Bohmer 5052439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Status check: this byte must be 0 or 1 */ 506850ba755SRemy Bohmer if (rxbyte > DM9000_PKT_RDY) { 5072439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_RCR, 0x00); /* Stop Device */ 5082439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_ISR, 0x80); /* Stop INT request */ 509850ba755SRemy Bohmer printf("DM9000 error: status check fail: 0x%x\n", 510850ba755SRemy Bohmer rxbyte); 511850ba755SRemy Bohmer return 0; 5122439e4bfSJean-Christophe PLAGNIOL-VILLARD } 513850ba755SRemy Bohmer 514850ba755SRemy Bohmer if (rxbyte != DM9000_PKT_RDY) 515850ba755SRemy Bohmer return 0; /* No packet received, ignore */ 516850ba755SRemy Bohmer 5172439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("receiving packet\n"); 5182439e4bfSJean-Christophe PLAGNIOL-VILLARD 5192439e4bfSJean-Christophe PLAGNIOL-VILLARD /* A packet ready now & Get status/length */ 520a101361bSRemy Bohmer (db->rx_status)(&RxStatus, &RxLen); 5212439e4bfSJean-Christophe PLAGNIOL-VILLARD 5222439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("rx status: 0x%04x rx len: %d\n", RxStatus, RxLen); 5232439e4bfSJean-Christophe PLAGNIOL-VILLARD 5242439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Move data from DM9000 */ 5252439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Read received packet from RX SRAM */ 526a101361bSRemy Bohmer (db->inblk)(rdptr, RxLen); 5272439e4bfSJean-Christophe PLAGNIOL-VILLARD 5282439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((RxStatus & 0xbf00) || (RxLen < 0x40) 5292439e4bfSJean-Christophe PLAGNIOL-VILLARD || (RxLen > DM9000_PKT_MAX)) { 5302439e4bfSJean-Christophe PLAGNIOL-VILLARD if (RxStatus & 0x100) { 5312439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("rx fifo error\n"); 5322439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5332439e4bfSJean-Christophe PLAGNIOL-VILLARD if (RxStatus & 0x200) { 5342439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("rx crc error\n"); 5352439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5362439e4bfSJean-Christophe PLAGNIOL-VILLARD if (RxStatus & 0x8000) { 5372439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("rx length error\n"); 5382439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5392439e4bfSJean-Christophe PLAGNIOL-VILLARD if (RxLen > DM9000_PKT_MAX) { 5402439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("rx length too big\n"); 5412439e4bfSJean-Christophe PLAGNIOL-VILLARD dm9000_reset(); 5422439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5432439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 544134e2662SRemy Bohmer DM9000_DMP_PACKET("eth_rx", rdptr, RxLen); 5452439e4bfSJean-Christophe PLAGNIOL-VILLARD 5462439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("passing packet to upper layer\n"); 5472439e4bfSJean-Christophe PLAGNIOL-VILLARD NetReceive(NetRxPackets[0], RxLen); 548850ba755SRemy Bohmer } 5492439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5502439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 5512439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5522439e4bfSJean-Christophe PLAGNIOL-VILLARD 5532439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 5542439e4bfSJean-Christophe PLAGNIOL-VILLARD Read a word data from SROM 5552439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 5562439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 5572439e4bfSJean-Christophe PLAGNIOL-VILLARD read_srom_word(int offset) 5582439e4bfSJean-Christophe PLAGNIOL-VILLARD { 5592439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPAR, offset); 5602439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPCR, 0x4); 5612439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(8000); 5622439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPCR, 0x0); 5632439e4bfSJean-Christophe PLAGNIOL-VILLARD return (DM9000_ior(DM9000_EPDRL) + (DM9000_ior(DM9000_EPDRH) << 8)); 5642439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5652439e4bfSJean-Christophe PLAGNIOL-VILLARD 5662439e4bfSJean-Christophe PLAGNIOL-VILLARD void 5672439e4bfSJean-Christophe PLAGNIOL-VILLARD write_srom_word(int offset, u16 val) 5682439e4bfSJean-Christophe PLAGNIOL-VILLARD { 5692439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPAR, offset); 5702439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPDRH, ((val >> 8) & 0xff)); 5712439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPDRL, (val & 0xff)); 5722439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPCR, 0x12); 5732439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(8000); 5742439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPCR, 0); 5752439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5762439e4bfSJean-Christophe PLAGNIOL-VILLARD 5772439e4bfSJean-Christophe PLAGNIOL-VILLARD 5782439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 5792439e4bfSJean-Christophe PLAGNIOL-VILLARD Read a byte from I/O port 5802439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 5812439e4bfSJean-Christophe PLAGNIOL-VILLARD static u8 5822439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_ior(int reg) 5832439e4bfSJean-Christophe PLAGNIOL-VILLARD { 5842439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_outb(reg, DM9000_IO); 5852439e4bfSJean-Christophe PLAGNIOL-VILLARD return DM9000_inb(DM9000_DATA); 5862439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5872439e4bfSJean-Christophe PLAGNIOL-VILLARD 5882439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 5892439e4bfSJean-Christophe PLAGNIOL-VILLARD Write a byte to I/O port 5902439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 5912439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 5922439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(int reg, u8 value) 5932439e4bfSJean-Christophe PLAGNIOL-VILLARD { 5942439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_outb(reg, DM9000_IO); 5952439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_outb(value, DM9000_DATA); 5962439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5972439e4bfSJean-Christophe PLAGNIOL-VILLARD 5982439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 5992439e4bfSJean-Christophe PLAGNIOL-VILLARD Read a word from phyxcer 6002439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 6012439e4bfSJean-Christophe PLAGNIOL-VILLARD static u16 6022439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_read(int reg) 6032439e4bfSJean-Christophe PLAGNIOL-VILLARD { 6042439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 val; 6052439e4bfSJean-Christophe PLAGNIOL-VILLARD 6062439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Fill the phyxcer register into REG_0C */ 6072439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPAR, DM9000_PHY | reg); 6082439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPCR, 0xc); /* Issue phyxcer read command */ 6092439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(100); /* Wait read complete */ 6102439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer read command */ 6112439e4bfSJean-Christophe PLAGNIOL-VILLARD val = (DM9000_ior(DM9000_EPDRH) << 8) | DM9000_ior(DM9000_EPDRL); 6122439e4bfSJean-Christophe PLAGNIOL-VILLARD 6132439e4bfSJean-Christophe PLAGNIOL-VILLARD /* The read data keeps on REG_0D & REG_0E */ 614134e2662SRemy Bohmer DM9000_DBG("phy_read(0x%x): 0x%x\n", reg, val); 6152439e4bfSJean-Christophe PLAGNIOL-VILLARD return val; 6162439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6172439e4bfSJean-Christophe PLAGNIOL-VILLARD 6182439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 6192439e4bfSJean-Christophe PLAGNIOL-VILLARD Write a word to phyxcer 6202439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 6212439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 6222439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_write(int reg, u16 value) 6232439e4bfSJean-Christophe PLAGNIOL-VILLARD { 6242439e4bfSJean-Christophe PLAGNIOL-VILLARD 6252439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Fill the phyxcer register into REG_0C */ 6262439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPAR, DM9000_PHY | reg); 6272439e4bfSJean-Christophe PLAGNIOL-VILLARD 6282439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Fill the written data into REG_0D & REG_0E */ 6292439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPDRL, (value & 0xff)); 6302439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPDRH, ((value >> 8) & 0xff)); 6312439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPCR, 0xa); /* Issue phyxcer write command */ 6322439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(500); /* Wait write complete */ 6332439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer write command */ 634134e2662SRemy Bohmer DM9000_DBG("phy_write(reg:0x%x, value:0x%x)\n", reg, value); 6352439e4bfSJean-Christophe PLAGNIOL-VILLARD } 636