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 582439e4bfSJean-Christophe PLAGNIOL-VILLARD TODO: Homerun NIC and longrun NIC are not functional, only internal at the 592439e4bfSJean-Christophe PLAGNIOL-VILLARD moment. 602439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 612439e4bfSJean-Christophe PLAGNIOL-VILLARD 622439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <common.h> 632439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <command.h> 642439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <net.h> 652439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <asm/io.h> 662439e4bfSJean-Christophe PLAGNIOL-VILLARD 672439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_DRIVER_DM9000 682439e4bfSJean-Christophe PLAGNIOL-VILLARD 692439e4bfSJean-Christophe PLAGNIOL-VILLARD #include "dm9000x.h" 702439e4bfSJean-Christophe PLAGNIOL-VILLARD 712439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Board/System/Debug information/definition ---------------- */ 722439e4bfSJean-Christophe PLAGNIOL-VILLARD 732439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9801_NOISE_FLOOR 0x08 742439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9802_NOISE_FLOOR 0x05 752439e4bfSJean-Christophe PLAGNIOL-VILLARD 762439e4bfSJean-Christophe PLAGNIOL-VILLARD /* #define CONFIG_DM9000_DEBUG */ 772439e4bfSJean-Christophe PLAGNIOL-VILLARD 782439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_DM9000_DEBUG 792439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_DBG(fmt,args...) printf(fmt, ##args) 80134e2662SRemy Bohmer #define DM9000_DMP_PACKET(func,packet,length) \ 81134e2662SRemy Bohmer do { \ 82134e2662SRemy Bohmer int i; \ 83134e2662SRemy Bohmer printf(func ": length: %d\n", length); \ 84134e2662SRemy Bohmer for (i = 0; i < length; i++) { \ 85134e2662SRemy Bohmer if (i % 8 == 0) \ 86134e2662SRemy Bohmer printf("\n%s: %02x: ", func, i); \ 87134e2662SRemy Bohmer printf("%02x ", ((unsigned char *) packet)[i]); \ 88134e2662SRemy Bohmer } printf("\n"); \ 89134e2662SRemy Bohmer } while(0) 90134e2662SRemy Bohmer #else 912439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_DBG(fmt,args...) 92134e2662SRemy Bohmer #define DM9000_DMP_PACKET(func,packet,length) 93134e2662SRemy Bohmer #endif 94134e2662SRemy Bohmer 952439e4bfSJean-Christophe PLAGNIOL-VILLARD enum DM9000_PHY_mode { DM9000_10MHD = 0, DM9000_100MHD = 962439e4bfSJean-Christophe PLAGNIOL-VILLARD 1, DM9000_10MFD = 4, DM9000_100MFD = 5, DM9000_AUTO = 972439e4bfSJean-Christophe PLAGNIOL-VILLARD 8, DM9000_1M_HPNA = 0x10 982439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 992439e4bfSJean-Christophe PLAGNIOL-VILLARD enum DM9000_NIC_TYPE { FASTETHER_NIC = 0, HOMERUN_NIC = 1, LONGRUN_NIC = 2 1002439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 1012439e4bfSJean-Christophe PLAGNIOL-VILLARD 1022439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Structure/enum declaration ------------------------------- */ 1032439e4bfSJean-Christophe PLAGNIOL-VILLARD typedef struct board_info { 1042439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 runt_length_counter; /* counter: RX length < 64byte */ 1052439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 long_length_counter; /* counter: RX length > 1514byte */ 1062439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 reset_counter; /* counter: RESET */ 1072439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 reset_tx_timeout; /* RESET caused by TX Timeout */ 1082439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 reset_rx_status; /* RESET caused by RX Statsus wrong */ 1092439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 tx_pkt_cnt; 1102439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 queue_start_addr; 1112439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 dbug_cnt; 1122439e4bfSJean-Christophe PLAGNIOL-VILLARD u8 phy_addr; 1132439e4bfSJean-Christophe PLAGNIOL-VILLARD u8 device_wait_reset; /* device state */ 1142439e4bfSJean-Christophe PLAGNIOL-VILLARD u8 nic_type; /* NIC type */ 1152439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned char srom[128]; 116*0e38c938SRemy Bohmer void (*outblk)(volatile void *data_ptr, int count); 117a101361bSRemy Bohmer void (*inblk)(void *data_ptr, int count); 118a101361bSRemy Bohmer void (*rx_status)(u16 *RxStatus, u16 *RxLen); 1192439e4bfSJean-Christophe PLAGNIOL-VILLARD } board_info_t; 120a101361bSRemy Bohmer static board_info_t dm9000_info; 1212439e4bfSJean-Christophe PLAGNIOL-VILLARD 1222439e4bfSJean-Christophe PLAGNIOL-VILLARD /* For module input parameter */ 1232439e4bfSJean-Christophe PLAGNIOL-VILLARD static int media_mode = DM9000_AUTO; 1242439e4bfSJean-Christophe PLAGNIOL-VILLARD static u8 nfloor = 0; 1252439e4bfSJean-Christophe PLAGNIOL-VILLARD 1262439e4bfSJean-Christophe PLAGNIOL-VILLARD /* function declaration ------------------------------------- */ 1272439e4bfSJean-Christophe PLAGNIOL-VILLARD int eth_init(bd_t * bd); 1282439e4bfSJean-Christophe PLAGNIOL-VILLARD int eth_send(volatile void *, int); 1292439e4bfSJean-Christophe PLAGNIOL-VILLARD int eth_rx(void); 1302439e4bfSJean-Christophe PLAGNIOL-VILLARD void eth_halt(void); 1312439e4bfSJean-Christophe PLAGNIOL-VILLARD static int dm9000_probe(void); 1322439e4bfSJean-Christophe PLAGNIOL-VILLARD static u16 phy_read(int); 1332439e4bfSJean-Christophe PLAGNIOL-VILLARD static void phy_write(int, u16); 1342439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 read_srom_word(int); 1352439e4bfSJean-Christophe PLAGNIOL-VILLARD static u8 DM9000_ior(int); 1362439e4bfSJean-Christophe PLAGNIOL-VILLARD static void DM9000_iow(int reg, u8 value); 1372439e4bfSJean-Christophe PLAGNIOL-VILLARD 1382439e4bfSJean-Christophe PLAGNIOL-VILLARD /* DM9000 network board routine ---------------------------- */ 1392439e4bfSJean-Christophe PLAGNIOL-VILLARD 1402439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_outb(d,r) ( *(volatile u8 *)r = d ) 1412439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_outw(d,r) ( *(volatile u16 *)r = d ) 1422439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_outl(d,r) ( *(volatile u32 *)r = d ) 1432439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_inb(r) (*(volatile u8 *)r) 1442439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_inw(r) (*(volatile u16 *)r) 1452439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_inl(r) (*(volatile u32 *)r) 1462439e4bfSJean-Christophe PLAGNIOL-VILLARD 1472439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_DM9000_DEBUG 1482439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 1492439e4bfSJean-Christophe PLAGNIOL-VILLARD dump_regs(void) 1502439e4bfSJean-Christophe PLAGNIOL-VILLARD { 1512439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("\n"); 1522439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("NCR (0x00): %02x\n", DM9000_ior(0)); 1532439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("NSR (0x01): %02x\n", DM9000_ior(1)); 1542439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("TCR (0x02): %02x\n", DM9000_ior(2)); 1552439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("TSRI (0x03): %02x\n", DM9000_ior(3)); 1562439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("TSRII (0x04): %02x\n", DM9000_ior(4)); 1572439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("RCR (0x05): %02x\n", DM9000_ior(5)); 1582439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("RSR (0x06): %02x\n", DM9000_ior(6)); 159134e2662SRemy Bohmer DM9000_DBG("ISR (0xFE): %02x\n", DM9000_ior(DM9000_ISR)); 1602439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("\n"); 1612439e4bfSJean-Christophe PLAGNIOL-VILLARD } 162a101361bSRemy Bohmer #endif 163a101361bSRemy Bohmer 164*0e38c938SRemy Bohmer static void dm9000_outblk_8bit(volatile void *data_ptr, int count) 165a101361bSRemy Bohmer { 166a101361bSRemy Bohmer int i; 167a101361bSRemy Bohmer for (i = 0; i < count; i++) 168a101361bSRemy Bohmer DM9000_outb((((u8 *) data_ptr)[i] & 0xff), DM9000_DATA); 169a101361bSRemy Bohmer } 170a101361bSRemy Bohmer 171*0e38c938SRemy Bohmer static void dm9000_outblk_16bit(volatile void *data_ptr, int count) 172a101361bSRemy Bohmer { 173a101361bSRemy Bohmer int i; 174a101361bSRemy Bohmer u32 tmplen = (count + 1) / 2; 175a101361bSRemy Bohmer 176a101361bSRemy Bohmer for (i = 0; i < tmplen; i++) 177a101361bSRemy Bohmer DM9000_outw(((u16 *) data_ptr)[i], DM9000_DATA); 178a101361bSRemy Bohmer } 179*0e38c938SRemy Bohmer static void dm9000_outblk_32bit(volatile void *data_ptr, int count) 180a101361bSRemy Bohmer { 181a101361bSRemy Bohmer int i; 182a101361bSRemy Bohmer u32 tmplen = (count + 3) / 4; 183a101361bSRemy Bohmer 184a101361bSRemy Bohmer for (i = 0; i < tmplen; i++) 185a101361bSRemy Bohmer DM9000_outl(((u32 *) data_ptr)[i], DM9000_DATA); 186a101361bSRemy Bohmer } 187a101361bSRemy Bohmer 188a101361bSRemy Bohmer static void dm9000_inblk_8bit(void *data_ptr, int count) 189a101361bSRemy Bohmer { 190a101361bSRemy Bohmer int i; 191a101361bSRemy Bohmer for (i = 0; i < count; i++) 192a101361bSRemy Bohmer ((u8 *) data_ptr)[i] = DM9000_inb(DM9000_DATA); 193a101361bSRemy Bohmer } 194a101361bSRemy Bohmer 195a101361bSRemy Bohmer static void dm9000_inblk_16bit(void *data_ptr, int count) 196a101361bSRemy Bohmer { 197a101361bSRemy Bohmer int i; 198a101361bSRemy Bohmer u32 tmplen = (count + 1) / 2; 199a101361bSRemy Bohmer 200a101361bSRemy Bohmer for (i = 0; i < tmplen; i++) 201a101361bSRemy Bohmer ((u16 *) data_ptr)[i] = DM9000_inw(DM9000_DATA); 202a101361bSRemy Bohmer } 203a101361bSRemy Bohmer static void dm9000_inblk_32bit(void *data_ptr, int count) 204a101361bSRemy Bohmer { 205a101361bSRemy Bohmer int i; 206a101361bSRemy Bohmer u32 tmplen = (count + 3) / 4; 207a101361bSRemy Bohmer 208a101361bSRemy Bohmer for (i = 0; i < tmplen; i++) 209a101361bSRemy Bohmer ((u32 *) data_ptr)[i] = DM9000_inl(DM9000_DATA); 210a101361bSRemy Bohmer } 211a101361bSRemy Bohmer 212a101361bSRemy Bohmer static void dm9000_rx_status_32bit(u16 *RxStatus, u16 *RxLen) 213a101361bSRemy Bohmer { 214d6ee5fa4SRemy Bohmer u32 tmpdata; 215a101361bSRemy Bohmer 216a101361bSRemy Bohmer DM9000_outb(DM9000_MRCMD, DM9000_IO); 217a101361bSRemy Bohmer 218d6ee5fa4SRemy Bohmer tmpdata = DM9000_inl(DM9000_DATA); 219a101361bSRemy Bohmer *RxStatus = tmpdata; 220a101361bSRemy Bohmer *RxLen = tmpdata >> 16; 221a101361bSRemy Bohmer } 222a101361bSRemy Bohmer 223a101361bSRemy Bohmer static void dm9000_rx_status_16bit(u16 *RxStatus, u16 *RxLen) 224a101361bSRemy Bohmer { 225a101361bSRemy Bohmer DM9000_outb(DM9000_MRCMD, DM9000_IO); 226a101361bSRemy Bohmer 227a101361bSRemy Bohmer *RxStatus = DM9000_inw(DM9000_DATA); 228a101361bSRemy Bohmer *RxLen = DM9000_inw(DM9000_DATA); 229a101361bSRemy Bohmer } 230a101361bSRemy Bohmer 231a101361bSRemy Bohmer static void dm9000_rx_status_8bit(u16 *RxStatus, u16 *RxLen) 232a101361bSRemy Bohmer { 233a101361bSRemy Bohmer DM9000_outb(DM9000_MRCMD, DM9000_IO); 234a101361bSRemy Bohmer 235a101361bSRemy Bohmer *RxStatus = DM9000_inb(DM9000_DATA) + (DM9000_inb(DM9000_DATA) << 8); 236a101361bSRemy Bohmer *RxLen = DM9000_inb(DM9000_DATA) + (DM9000_inb(DM9000_DATA) << 8); 237a101361bSRemy Bohmer } 2382439e4bfSJean-Christophe PLAGNIOL-VILLARD 2392439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 2402439e4bfSJean-Christophe PLAGNIOL-VILLARD Search DM9000 board, allocate space and register it 2412439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 2422439e4bfSJean-Christophe PLAGNIOL-VILLARD int 2432439e4bfSJean-Christophe PLAGNIOL-VILLARD dm9000_probe(void) 2442439e4bfSJean-Christophe PLAGNIOL-VILLARD { 2452439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 id_val; 2462439e4bfSJean-Christophe PLAGNIOL-VILLARD id_val = DM9000_ior(DM9000_VIDL); 2472439e4bfSJean-Christophe PLAGNIOL-VILLARD id_val |= DM9000_ior(DM9000_VIDH) << 8; 2482439e4bfSJean-Christophe PLAGNIOL-VILLARD id_val |= DM9000_ior(DM9000_PIDL) << 16; 2492439e4bfSJean-Christophe PLAGNIOL-VILLARD id_val |= DM9000_ior(DM9000_PIDH) << 24; 2502439e4bfSJean-Christophe PLAGNIOL-VILLARD if (id_val == DM9000_ID) { 2512439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("dm9000 i/o: 0x%x, id: 0x%x \n", CONFIG_DM9000_BASE, 2522439e4bfSJean-Christophe PLAGNIOL-VILLARD id_val); 2532439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 2542439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 2552439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("dm9000 not found at 0x%08x id: 0x%08x\n", 2562439e4bfSJean-Christophe PLAGNIOL-VILLARD CONFIG_DM9000_BASE, id_val); 2572439e4bfSJean-Christophe PLAGNIOL-VILLARD return -1; 2582439e4bfSJean-Christophe PLAGNIOL-VILLARD } 2592439e4bfSJean-Christophe PLAGNIOL-VILLARD } 2602439e4bfSJean-Christophe PLAGNIOL-VILLARD 2612439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set PHY operationg mode 2622439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 2632439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 2642439e4bfSJean-Christophe PLAGNIOL-VILLARD set_PHY_mode(void) 2652439e4bfSJean-Christophe PLAGNIOL-VILLARD { 2662439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 phy_reg4 = 0x01e1, phy_reg0 = 0x1000; 2672439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!(media_mode & DM9000_AUTO)) { 2682439e4bfSJean-Christophe PLAGNIOL-VILLARD switch (media_mode) { 2692439e4bfSJean-Christophe PLAGNIOL-VILLARD case DM9000_10MHD: 2702439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_reg4 = 0x21; 2712439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_reg0 = 0x0000; 2722439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 2732439e4bfSJean-Christophe PLAGNIOL-VILLARD case DM9000_10MFD: 2742439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_reg4 = 0x41; 2752439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_reg0 = 0x1100; 2762439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 2772439e4bfSJean-Christophe PLAGNIOL-VILLARD case DM9000_100MHD: 2782439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_reg4 = 0x81; 2792439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_reg0 = 0x2000; 2802439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 2812439e4bfSJean-Christophe PLAGNIOL-VILLARD case DM9000_100MFD: 2822439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_reg4 = 0x101; 2832439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_reg0 = 0x3100; 2842439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 2852439e4bfSJean-Christophe PLAGNIOL-VILLARD } 2862439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_write(4, phy_reg4); /* Set PHY media mode */ 2872439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_write(0, phy_reg0); /* Tmp */ 2882439e4bfSJean-Christophe PLAGNIOL-VILLARD } 2892439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_GPCR, 0x01); /* Let GPIO0 output */ 2902439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_GPR, 0x00); /* Enable PHY */ 2912439e4bfSJean-Christophe PLAGNIOL-VILLARD } 2922439e4bfSJean-Christophe PLAGNIOL-VILLARD 2932439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 2942439e4bfSJean-Christophe PLAGNIOL-VILLARD Init HomeRun DM9801 2952439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 2962439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 2972439e4bfSJean-Christophe PLAGNIOL-VILLARD program_dm9801(u16 HPNA_rev) 2982439e4bfSJean-Christophe PLAGNIOL-VILLARD { 2992439e4bfSJean-Christophe PLAGNIOL-VILLARD __u16 reg16, reg17, reg24, reg25; 3002439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!nfloor) 3012439e4bfSJean-Christophe PLAGNIOL-VILLARD nfloor = DM9801_NOISE_FLOOR; 3022439e4bfSJean-Christophe PLAGNIOL-VILLARD reg16 = phy_read(16); 3032439e4bfSJean-Christophe PLAGNIOL-VILLARD reg17 = phy_read(17); 3042439e4bfSJean-Christophe PLAGNIOL-VILLARD reg24 = phy_read(24); 3052439e4bfSJean-Christophe PLAGNIOL-VILLARD reg25 = phy_read(25); 3062439e4bfSJean-Christophe PLAGNIOL-VILLARD switch (HPNA_rev) { 3072439e4bfSJean-Christophe PLAGNIOL-VILLARD case 0xb900: /* DM9801 E3 */ 3082439e4bfSJean-Christophe PLAGNIOL-VILLARD reg16 |= 0x1000; 3092439e4bfSJean-Christophe PLAGNIOL-VILLARD reg25 = ((reg24 + nfloor) & 0x00ff) | 0xf000; 3102439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 3112439e4bfSJean-Christophe PLAGNIOL-VILLARD case 0xb901: /* DM9801 E4 */ 3122439e4bfSJean-Christophe PLAGNIOL-VILLARD reg25 = ((reg24 + nfloor) & 0x00ff) | 0xc200; 3132439e4bfSJean-Christophe PLAGNIOL-VILLARD reg17 = (reg17 & 0xfff0) + nfloor + 3; 3142439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 3152439e4bfSJean-Christophe PLAGNIOL-VILLARD case 0xb902: /* DM9801 E5 */ 3162439e4bfSJean-Christophe PLAGNIOL-VILLARD case 0xb903: /* DM9801 E6 */ 3172439e4bfSJean-Christophe PLAGNIOL-VILLARD default: 3182439e4bfSJean-Christophe PLAGNIOL-VILLARD reg16 |= 0x1000; 3192439e4bfSJean-Christophe PLAGNIOL-VILLARD reg25 = ((reg24 + nfloor - 3) & 0x00ff) | 0xc200; 3202439e4bfSJean-Christophe PLAGNIOL-VILLARD reg17 = (reg17 & 0xfff0) + nfloor; 3212439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3222439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_write(16, reg16); 3232439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_write(17, reg17); 3242439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_write(25, reg25); 3252439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3262439e4bfSJean-Christophe PLAGNIOL-VILLARD 3272439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 3282439e4bfSJean-Christophe PLAGNIOL-VILLARD Init LongRun DM9802 3292439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 3302439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 3312439e4bfSJean-Christophe PLAGNIOL-VILLARD program_dm9802(void) 3322439e4bfSJean-Christophe PLAGNIOL-VILLARD { 3332439e4bfSJean-Christophe PLAGNIOL-VILLARD __u16 reg25; 3342439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!nfloor) 3352439e4bfSJean-Christophe PLAGNIOL-VILLARD nfloor = DM9802_NOISE_FLOOR; 3362439e4bfSJean-Christophe PLAGNIOL-VILLARD reg25 = phy_read(25); 3372439e4bfSJean-Christophe PLAGNIOL-VILLARD reg25 = (reg25 & 0xff00) + nfloor; 3382439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_write(25, reg25); 3392439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3402439e4bfSJean-Christophe PLAGNIOL-VILLARD 3412439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Identify NIC type 3422439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 3432439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 3442439e4bfSJean-Christophe PLAGNIOL-VILLARD identify_nic(void) 3452439e4bfSJean-Christophe PLAGNIOL-VILLARD { 346a101361bSRemy Bohmer struct board_info *db = &dm9000_info; 3472439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 phy_reg3; 3482439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_NCR, NCR_EXT_PHY); 3492439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_reg3 = phy_read(3); 3502439e4bfSJean-Christophe PLAGNIOL-VILLARD switch (phy_reg3 & 0xfff0) { 3512439e4bfSJean-Christophe PLAGNIOL-VILLARD case 0xb900: 3522439e4bfSJean-Christophe PLAGNIOL-VILLARD if (phy_read(31) == 0x4404) { 3532439e4bfSJean-Christophe PLAGNIOL-VILLARD db->nic_type = HOMERUN_NIC; 3542439e4bfSJean-Christophe PLAGNIOL-VILLARD program_dm9801(phy_reg3); 3552439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("found homerun NIC\n"); 3562439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 3572439e4bfSJean-Christophe PLAGNIOL-VILLARD db->nic_type = LONGRUN_NIC; 3582439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("found longrun NIC\n"); 3592439e4bfSJean-Christophe PLAGNIOL-VILLARD program_dm9802(); 3602439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3612439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 3622439e4bfSJean-Christophe PLAGNIOL-VILLARD default: 3632439e4bfSJean-Christophe PLAGNIOL-VILLARD db->nic_type = FASTETHER_NIC; 3642439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 3652439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3662439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_NCR, 0); 3672439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3682439e4bfSJean-Christophe PLAGNIOL-VILLARD 3692439e4bfSJean-Christophe PLAGNIOL-VILLARD /* General Purpose dm9000 reset routine */ 3702439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 3712439e4bfSJean-Christophe PLAGNIOL-VILLARD dm9000_reset(void) 3722439e4bfSJean-Christophe PLAGNIOL-VILLARD { 373fbcb7eceSRemy Bohmer DM9000_DBG("resetting DM9000\n"); 374fbcb7eceSRemy Bohmer 375fbcb7eceSRemy Bohmer /* Reset DM9000, 376fbcb7eceSRemy Bohmer see DM9000 Application Notes V1.22 Jun 11, 2004 page 29 */ 377fbcb7eceSRemy Bohmer 378fbcb7eceSRemy Bohmer /* DEBUG: Make all GPIO pins outputs */ 379fbcb7eceSRemy Bohmer DM9000_iow(DM9000_GPCR, 0x0F); 380fbcb7eceSRemy Bohmer /* Step 1: Power internal PHY by writing 0 to GPIO0 pin */ 381fbcb7eceSRemy Bohmer DM9000_iow(DM9000_GPR, 0); 382fbcb7eceSRemy Bohmer /* Step 2: Software reset */ 383fbcb7eceSRemy Bohmer DM9000_iow(DM9000_NCR, 3); 384fbcb7eceSRemy Bohmer 385fbcb7eceSRemy Bohmer do { 386fbcb7eceSRemy Bohmer DM9000_DBG("resetting the DM9000, 1st reset\n"); 387fbcb7eceSRemy Bohmer udelay(25); /* Wait at least 20 us */ 388fbcb7eceSRemy Bohmer } while (DM9000_ior(DM9000_NCR) & 1); 389fbcb7eceSRemy Bohmer 390fbcb7eceSRemy Bohmer DM9000_iow(DM9000_NCR, 0); 391fbcb7eceSRemy Bohmer DM9000_iow(DM9000_NCR, 3); /* Issue a second reset */ 392fbcb7eceSRemy Bohmer 393fbcb7eceSRemy Bohmer do { 394fbcb7eceSRemy Bohmer DM9000_DBG("resetting the DM9000, 2nd reset\n"); 395fbcb7eceSRemy Bohmer udelay(25); /* Wait at least 20 us */ 396fbcb7eceSRemy Bohmer } while (DM9000_ior(DM9000_NCR) & 1); 397fbcb7eceSRemy Bohmer 398fbcb7eceSRemy Bohmer /* Check whether the ethernet controller is present */ 399fbcb7eceSRemy Bohmer if ((DM9000_ior(DM9000_PIDL) != 0x0) || 400fbcb7eceSRemy Bohmer (DM9000_ior(DM9000_PIDH) != 0x90)) 401fbcb7eceSRemy Bohmer printf("ERROR: resetting DM9000 -> not responding\n"); 4022439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4032439e4bfSJean-Christophe PLAGNIOL-VILLARD 4042439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Initilize dm9000 board 4052439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 4062439e4bfSJean-Christophe PLAGNIOL-VILLARD int 4072439e4bfSJean-Christophe PLAGNIOL-VILLARD eth_init(bd_t * bd) 4082439e4bfSJean-Christophe PLAGNIOL-VILLARD { 4092439e4bfSJean-Christophe PLAGNIOL-VILLARD int i, oft, lnk; 410a101361bSRemy Bohmer u8 io_mode; 411a101361bSRemy Bohmer struct board_info *db = &dm9000_info; 412a101361bSRemy Bohmer 4132439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("eth_init()\n"); 4142439e4bfSJean-Christophe PLAGNIOL-VILLARD 4152439e4bfSJean-Christophe PLAGNIOL-VILLARD /* RESET device */ 4162439e4bfSJean-Christophe PLAGNIOL-VILLARD dm9000_reset(); 4172439e4bfSJean-Christophe PLAGNIOL-VILLARD dm9000_probe(); 4182439e4bfSJean-Christophe PLAGNIOL-VILLARD 419a101361bSRemy Bohmer /* Auto-detect 8/16/32 bit mode, ISR Bit 6+7 indicate bus width */ 420a101361bSRemy Bohmer io_mode = DM9000_ior(DM9000_ISR) >> 6; 421a101361bSRemy Bohmer 422a101361bSRemy Bohmer switch (io_mode) { 423a101361bSRemy Bohmer case 0x0: /* 16-bit mode */ 424a101361bSRemy Bohmer printf("DM9000: running in 16 bit mode\n"); 425a101361bSRemy Bohmer db->outblk = dm9000_outblk_16bit; 426a101361bSRemy Bohmer db->inblk = dm9000_inblk_16bit; 427a101361bSRemy Bohmer db->rx_status = dm9000_rx_status_16bit; 428a101361bSRemy Bohmer break; 429a101361bSRemy Bohmer case 0x01: /* 32-bit mode */ 430a101361bSRemy Bohmer printf("DM9000: running in 32 bit mode\n"); 431a101361bSRemy Bohmer db->outblk = dm9000_outblk_32bit; 432a101361bSRemy Bohmer db->inblk = dm9000_inblk_32bit; 433a101361bSRemy Bohmer db->rx_status = dm9000_rx_status_32bit; 434a101361bSRemy Bohmer break; 435a101361bSRemy Bohmer case 0x02: /* 8 bit mode */ 436a101361bSRemy Bohmer printf("DM9000: running in 8 bit mode\n"); 437a101361bSRemy Bohmer db->outblk = dm9000_outblk_8bit; 438a101361bSRemy Bohmer db->inblk = dm9000_inblk_8bit; 439a101361bSRemy Bohmer db->rx_status = dm9000_rx_status_8bit; 440a101361bSRemy Bohmer break; 441a101361bSRemy Bohmer default: 442a101361bSRemy Bohmer /* Assume 8 bit mode, will probably not work anyway */ 443a101361bSRemy Bohmer printf("DM9000: Undefined IO-mode:0x%x\n", io_mode); 444a101361bSRemy Bohmer db->outblk = dm9000_outblk_8bit; 445a101361bSRemy Bohmer db->inblk = dm9000_inblk_8bit; 446a101361bSRemy Bohmer db->rx_status = dm9000_rx_status_8bit; 447a101361bSRemy Bohmer break; 448a101361bSRemy Bohmer } 449a101361bSRemy Bohmer 4502439e4bfSJean-Christophe PLAGNIOL-VILLARD /* NIC Type: FASTETHER, HOMERUN, LONGRUN */ 4512439e4bfSJean-Christophe PLAGNIOL-VILLARD identify_nic(); 4522439e4bfSJean-Christophe PLAGNIOL-VILLARD 4532439e4bfSJean-Christophe PLAGNIOL-VILLARD /* GPIO0 on pre-activate PHY */ 4542439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_GPR, 0x00); /*REG_1F bit0 activate phyxcer */ 4552439e4bfSJean-Christophe PLAGNIOL-VILLARD 4562439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set PHY */ 4572439e4bfSJean-Christophe PLAGNIOL-VILLARD set_PHY_mode(); 4582439e4bfSJean-Christophe PLAGNIOL-VILLARD 45998291e2eSRemy Bohmer /* Program operating register, only intern phy supported by now */ 46098291e2eSRemy Bohmer DM9000_iow(DM9000_NCR, 0x0); 46198291e2eSRemy Bohmer /* TX Polling clear */ 46298291e2eSRemy Bohmer DM9000_iow(DM9000_TCR, 0); 46398291e2eSRemy Bohmer /* Less 3Kb, 200us */ 46498291e2eSRemy Bohmer DM9000_iow(DM9000_BPTR, 0x3f); 46598291e2eSRemy Bohmer /* Flow Control : High/Low Water */ 46698291e2eSRemy Bohmer DM9000_iow(DM9000_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8)); 46798291e2eSRemy Bohmer /* SH FIXME: This looks strange! Flow Control */ 46898291e2eSRemy Bohmer DM9000_iow(DM9000_FCR, 0x0); 46998291e2eSRemy Bohmer /* Special Mode */ 47098291e2eSRemy Bohmer DM9000_iow(DM9000_SMCR, 0); 47198291e2eSRemy Bohmer /* clear TX status */ 47298291e2eSRemy Bohmer DM9000_iow(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END); 47398291e2eSRemy Bohmer /* Clear interrupt status */ 47498291e2eSRemy Bohmer DM9000_iow(DM9000_ISR, 0x0f); 4752439e4bfSJean-Christophe PLAGNIOL-VILLARD 4762439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set Node address */ 4772439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < 6; i++) 4782439e4bfSJean-Christophe PLAGNIOL-VILLARD ((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i); 4792439e4bfSJean-Christophe PLAGNIOL-VILLARD 4802439e4bfSJean-Christophe PLAGNIOL-VILLARD if (is_zero_ether_addr(bd->bi_enetaddr) || 4812439e4bfSJean-Christophe PLAGNIOL-VILLARD is_multicast_ether_addr(bd->bi_enetaddr)) { 4822439e4bfSJean-Christophe PLAGNIOL-VILLARD /* try reading from environment */ 4832439e4bfSJean-Christophe PLAGNIOL-VILLARD u8 i; 4842439e4bfSJean-Christophe PLAGNIOL-VILLARD char *s, *e; 4852439e4bfSJean-Christophe PLAGNIOL-VILLARD s = getenv ("ethaddr"); 4862439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < 6; ++i) { 4872439e4bfSJean-Christophe PLAGNIOL-VILLARD bd->bi_enetaddr[i] = s ? 4882439e4bfSJean-Christophe PLAGNIOL-VILLARD simple_strtoul (s, &e, 16) : 0; 4892439e4bfSJean-Christophe PLAGNIOL-VILLARD if (s) 4902439e4bfSJean-Christophe PLAGNIOL-VILLARD s = (*e) ? e + 1 : e; 4912439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4922439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4932439e4bfSJean-Christophe PLAGNIOL-VILLARD 4942439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", bd->bi_enetaddr[0], 4952439e4bfSJean-Christophe PLAGNIOL-VILLARD bd->bi_enetaddr[1], bd->bi_enetaddr[2], bd->bi_enetaddr[3], 4962439e4bfSJean-Christophe PLAGNIOL-VILLARD bd->bi_enetaddr[4], bd->bi_enetaddr[5]); 4972439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0, oft = 0x10; i < 6; i++, oft++) 4982439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(oft, bd->bi_enetaddr[i]); 4992439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0, oft = 0x16; i < 8; i++, oft++) 5002439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(oft, 0xff); 5012439e4bfSJean-Christophe PLAGNIOL-VILLARD 5022439e4bfSJean-Christophe PLAGNIOL-VILLARD /* read back mac, just to be sure */ 5032439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0, oft = 0x10; i < 6; i++, oft++) 5042439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("%02x:", DM9000_ior(oft)); 5052439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("\n"); 5062439e4bfSJean-Christophe PLAGNIOL-VILLARD 5072439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Activate DM9000 */ 50898291e2eSRemy Bohmer /* RX enable */ 50998291e2eSRemy Bohmer DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN); 51098291e2eSRemy Bohmer /* Enable TX/RX interrupt mask */ 51198291e2eSRemy Bohmer DM9000_iow(DM9000_IMR, IMR_PAR); 51298291e2eSRemy Bohmer 5132439e4bfSJean-Christophe PLAGNIOL-VILLARD i = 0; 5142439e4bfSJean-Christophe PLAGNIOL-VILLARD while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */ 5152439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1000); 5162439e4bfSJean-Christophe PLAGNIOL-VILLARD i++; 5172439e4bfSJean-Christophe PLAGNIOL-VILLARD if (i == 10000) { 5182439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("could not establish link\n"); 5192439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 5202439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5212439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5222439e4bfSJean-Christophe PLAGNIOL-VILLARD 5232439e4bfSJean-Christophe PLAGNIOL-VILLARD /* see what we've got */ 5242439e4bfSJean-Christophe PLAGNIOL-VILLARD lnk = phy_read(17) >> 12; 5252439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("operating at "); 5262439e4bfSJean-Christophe PLAGNIOL-VILLARD switch (lnk) { 5272439e4bfSJean-Christophe PLAGNIOL-VILLARD case 1: 5282439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("10M half duplex "); 5292439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 5302439e4bfSJean-Christophe PLAGNIOL-VILLARD case 2: 5312439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("10M full duplex "); 5322439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 5332439e4bfSJean-Christophe PLAGNIOL-VILLARD case 4: 5342439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("100M half duplex "); 5352439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 5362439e4bfSJean-Christophe PLAGNIOL-VILLARD case 8: 5372439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("100M full duplex "); 5382439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 5392439e4bfSJean-Christophe PLAGNIOL-VILLARD default: 5402439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("unknown: %d ", lnk); 5412439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 5422439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5432439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("mode\n"); 5442439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 5452439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5462439e4bfSJean-Christophe PLAGNIOL-VILLARD 5472439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 5482439e4bfSJean-Christophe PLAGNIOL-VILLARD Hardware start transmission. 5492439e4bfSJean-Christophe PLAGNIOL-VILLARD Send a packet to media from the upper layer. 5502439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 5512439e4bfSJean-Christophe PLAGNIOL-VILLARD int 5522439e4bfSJean-Christophe PLAGNIOL-VILLARD eth_send(volatile void *packet, int length) 5532439e4bfSJean-Christophe PLAGNIOL-VILLARD { 5542439e4bfSJean-Christophe PLAGNIOL-VILLARD int tmo; 555a101361bSRemy Bohmer struct board_info *db = &dm9000_info; 556a101361bSRemy Bohmer 557134e2662SRemy Bohmer DM9000_DMP_PACKET("eth_send", packet, length); 5582439e4bfSJean-Christophe PLAGNIOL-VILLARD 559acba3184SRemy Bohmer DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */ 560acba3184SRemy Bohmer 5612439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Move data to DM9000 TX RAM */ 562acba3184SRemy Bohmer DM9000_outb(DM9000_MWCMD, DM9000_IO); /* Prepare for TX-data */ 5632439e4bfSJean-Christophe PLAGNIOL-VILLARD 564a101361bSRemy Bohmer /* push the data to the TX-fifo */ 565*0e38c938SRemy Bohmer (db->outblk)(packet, length); 5662439e4bfSJean-Christophe PLAGNIOL-VILLARD 5672439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set TX length to DM9000 */ 5682439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_TXPLL, length & 0xff); 5692439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_TXPLH, (length >> 8) & 0xff); 5702439e4bfSJean-Christophe PLAGNIOL-VILLARD 5712439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Issue TX polling command */ 5722439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */ 5732439e4bfSJean-Christophe PLAGNIOL-VILLARD 5742439e4bfSJean-Christophe PLAGNIOL-VILLARD /* wait for end of transmission */ 5752439e4bfSJean-Christophe PLAGNIOL-VILLARD tmo = get_timer(0) + 5 * CFG_HZ; 576acba3184SRemy Bohmer while ( !(DM9000_ior(DM9000_NSR) & (NSR_TX1END | NSR_TX2END)) || 577acba3184SRemy Bohmer !(DM9000_ior(DM9000_ISR) & IMR_PTM) ) { 5782439e4bfSJean-Christophe PLAGNIOL-VILLARD if (get_timer(0) >= tmo) { 5792439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("transmission timeout\n"); 5802439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 5812439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5822439e4bfSJean-Christophe PLAGNIOL-VILLARD } 583acba3184SRemy Bohmer DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */ 584acba3184SRemy Bohmer 5852439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("transmit done\n\n"); 5862439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 5872439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5882439e4bfSJean-Christophe PLAGNIOL-VILLARD 5892439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 5902439e4bfSJean-Christophe PLAGNIOL-VILLARD Stop the interface. 5912439e4bfSJean-Christophe PLAGNIOL-VILLARD The interface is stopped when it is brought. 5922439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 5932439e4bfSJean-Christophe PLAGNIOL-VILLARD void 5942439e4bfSJean-Christophe PLAGNIOL-VILLARD eth_halt(void) 5952439e4bfSJean-Christophe PLAGNIOL-VILLARD { 5962439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("eth_halt\n"); 5972439e4bfSJean-Christophe PLAGNIOL-VILLARD 5982439e4bfSJean-Christophe PLAGNIOL-VILLARD /* RESET devie */ 5992439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_write(0, 0x8000); /* PHY RESET */ 6002439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_GPR, 0x01); /* Power-Down PHY */ 6012439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_IMR, 0x80); /* Disable all interrupt */ 6022439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_RCR, 0x00); /* Disable RX */ 6032439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6042439e4bfSJean-Christophe PLAGNIOL-VILLARD 6052439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 6062439e4bfSJean-Christophe PLAGNIOL-VILLARD Received a packet and pass to upper layer 6072439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 6082439e4bfSJean-Christophe PLAGNIOL-VILLARD int 6092439e4bfSJean-Christophe PLAGNIOL-VILLARD eth_rx(void) 6102439e4bfSJean-Christophe PLAGNIOL-VILLARD { 6112439e4bfSJean-Christophe PLAGNIOL-VILLARD u8 rxbyte, *rdptr = (u8 *) NetRxPackets[0]; 6122439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 RxStatus, RxLen = 0; 613a101361bSRemy Bohmer struct board_info *db = &dm9000_info; 6142439e4bfSJean-Christophe PLAGNIOL-VILLARD 615850ba755SRemy Bohmer /* Check packet ready or not, we must check 616850ba755SRemy Bohmer the ISR status first for DM9000A */ 617850ba755SRemy Bohmer if (!(DM9000_ior(DM9000_ISR) & 0x01)) /* Rx-ISR bit must be set. */ 6182439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 6192439e4bfSJean-Christophe PLAGNIOL-VILLARD 620850ba755SRemy Bohmer DM9000_iow(DM9000_ISR, 0x01); /* clear PR status latched in bit 0 */ 621850ba755SRemy Bohmer 622850ba755SRemy Bohmer /* There is _at least_ 1 package in the fifo, read them all */ 623850ba755SRemy Bohmer for (;;) { 624850ba755SRemy Bohmer DM9000_ior(DM9000_MRCMDX); /* Dummy read */ 625850ba755SRemy Bohmer 626*0e38c938SRemy Bohmer /* Get most updated data, 627*0e38c938SRemy Bohmer only look at bits 0:1, See application notes DM9000 */ 628*0e38c938SRemy Bohmer rxbyte = DM9000_inb(DM9000_DATA) & 0x03; 629850ba755SRemy Bohmer 6302439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Status check: this byte must be 0 or 1 */ 631850ba755SRemy Bohmer if (rxbyte > DM9000_PKT_RDY) { 6322439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_RCR, 0x00); /* Stop Device */ 6332439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_ISR, 0x80); /* Stop INT request */ 634850ba755SRemy Bohmer printf("DM9000 error: status check fail: 0x%x\n", 635850ba755SRemy Bohmer rxbyte); 636850ba755SRemy Bohmer return 0; 6372439e4bfSJean-Christophe PLAGNIOL-VILLARD } 638850ba755SRemy Bohmer 639850ba755SRemy Bohmer if (rxbyte != DM9000_PKT_RDY) 640850ba755SRemy Bohmer return 0; /* No packet received, ignore */ 641850ba755SRemy Bohmer 6422439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("receiving packet\n"); 6432439e4bfSJean-Christophe PLAGNIOL-VILLARD 6442439e4bfSJean-Christophe PLAGNIOL-VILLARD /* A packet ready now & Get status/length */ 645a101361bSRemy Bohmer (db->rx_status)(&RxStatus, &RxLen); 6462439e4bfSJean-Christophe PLAGNIOL-VILLARD 6472439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("rx status: 0x%04x rx len: %d\n", RxStatus, RxLen); 6482439e4bfSJean-Christophe PLAGNIOL-VILLARD 6492439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Move data from DM9000 */ 6502439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Read received packet from RX SRAM */ 651a101361bSRemy Bohmer (db->inblk)(rdptr, RxLen); 6522439e4bfSJean-Christophe PLAGNIOL-VILLARD 6532439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((RxStatus & 0xbf00) || (RxLen < 0x40) 6542439e4bfSJean-Christophe PLAGNIOL-VILLARD || (RxLen > DM9000_PKT_MAX)) { 6552439e4bfSJean-Christophe PLAGNIOL-VILLARD if (RxStatus & 0x100) { 6562439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("rx fifo error\n"); 6572439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6582439e4bfSJean-Christophe PLAGNIOL-VILLARD if (RxStatus & 0x200) { 6592439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("rx crc error\n"); 6602439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6612439e4bfSJean-Christophe PLAGNIOL-VILLARD if (RxStatus & 0x8000) { 6622439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("rx length error\n"); 6632439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6642439e4bfSJean-Christophe PLAGNIOL-VILLARD if (RxLen > DM9000_PKT_MAX) { 6652439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("rx length too big\n"); 6662439e4bfSJean-Christophe PLAGNIOL-VILLARD dm9000_reset(); 6672439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6682439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 669134e2662SRemy Bohmer DM9000_DMP_PACKET("eth_rx", rdptr, RxLen); 6702439e4bfSJean-Christophe PLAGNIOL-VILLARD 6712439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("passing packet to upper layer\n"); 6722439e4bfSJean-Christophe PLAGNIOL-VILLARD NetReceive(NetRxPackets[0], RxLen); 673850ba755SRemy Bohmer } 6742439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6752439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 6762439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6772439e4bfSJean-Christophe PLAGNIOL-VILLARD 6782439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 6792439e4bfSJean-Christophe PLAGNIOL-VILLARD Read a word data from SROM 6802439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 6812439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 6822439e4bfSJean-Christophe PLAGNIOL-VILLARD read_srom_word(int offset) 6832439e4bfSJean-Christophe PLAGNIOL-VILLARD { 6842439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPAR, offset); 6852439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPCR, 0x4); 6862439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(8000); 6872439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPCR, 0x0); 6882439e4bfSJean-Christophe PLAGNIOL-VILLARD return (DM9000_ior(DM9000_EPDRL) + (DM9000_ior(DM9000_EPDRH) << 8)); 6892439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6902439e4bfSJean-Christophe PLAGNIOL-VILLARD 6912439e4bfSJean-Christophe PLAGNIOL-VILLARD void 6922439e4bfSJean-Christophe PLAGNIOL-VILLARD write_srom_word(int offset, u16 val) 6932439e4bfSJean-Christophe PLAGNIOL-VILLARD { 6942439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPAR, offset); 6952439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPDRH, ((val >> 8) & 0xff)); 6962439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPDRL, (val & 0xff)); 6972439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPCR, 0x12); 6982439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(8000); 6992439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPCR, 0); 7002439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7012439e4bfSJean-Christophe PLAGNIOL-VILLARD 7022439e4bfSJean-Christophe PLAGNIOL-VILLARD 7032439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 7042439e4bfSJean-Christophe PLAGNIOL-VILLARD Read a byte from I/O port 7052439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 7062439e4bfSJean-Christophe PLAGNIOL-VILLARD static u8 7072439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_ior(int reg) 7082439e4bfSJean-Christophe PLAGNIOL-VILLARD { 7092439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_outb(reg, DM9000_IO); 7102439e4bfSJean-Christophe PLAGNIOL-VILLARD return DM9000_inb(DM9000_DATA); 7112439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7122439e4bfSJean-Christophe PLAGNIOL-VILLARD 7132439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 7142439e4bfSJean-Christophe PLAGNIOL-VILLARD Write a byte to I/O port 7152439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 7162439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 7172439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(int reg, u8 value) 7182439e4bfSJean-Christophe PLAGNIOL-VILLARD { 7192439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_outb(reg, DM9000_IO); 7202439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_outb(value, DM9000_DATA); 7212439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7222439e4bfSJean-Christophe PLAGNIOL-VILLARD 7232439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 7242439e4bfSJean-Christophe PLAGNIOL-VILLARD Read a word from phyxcer 7252439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 7262439e4bfSJean-Christophe PLAGNIOL-VILLARD static u16 7272439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_read(int reg) 7282439e4bfSJean-Christophe PLAGNIOL-VILLARD { 7292439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 val; 7302439e4bfSJean-Christophe PLAGNIOL-VILLARD 7312439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Fill the phyxcer register into REG_0C */ 7322439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPAR, DM9000_PHY | reg); 7332439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPCR, 0xc); /* Issue phyxcer read command */ 7342439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(100); /* Wait read complete */ 7352439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer read command */ 7362439e4bfSJean-Christophe PLAGNIOL-VILLARD val = (DM9000_ior(DM9000_EPDRH) << 8) | DM9000_ior(DM9000_EPDRL); 7372439e4bfSJean-Christophe PLAGNIOL-VILLARD 7382439e4bfSJean-Christophe PLAGNIOL-VILLARD /* The read data keeps on REG_0D & REG_0E */ 739134e2662SRemy Bohmer DM9000_DBG("phy_read(0x%x): 0x%x\n", reg, val); 7402439e4bfSJean-Christophe PLAGNIOL-VILLARD return val; 7412439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7422439e4bfSJean-Christophe PLAGNIOL-VILLARD 7432439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 7442439e4bfSJean-Christophe PLAGNIOL-VILLARD Write a word to phyxcer 7452439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 7462439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 7472439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_write(int reg, u16 value) 7482439e4bfSJean-Christophe PLAGNIOL-VILLARD { 7492439e4bfSJean-Christophe PLAGNIOL-VILLARD 7502439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Fill the phyxcer register into REG_0C */ 7512439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPAR, DM9000_PHY | reg); 7522439e4bfSJean-Christophe PLAGNIOL-VILLARD 7532439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Fill the written data into REG_0D & REG_0E */ 7542439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPDRL, (value & 0xff)); 7552439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPDRH, ((value >> 8) & 0xff)); 7562439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPCR, 0xa); /* Issue phyxcer write command */ 7572439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(500); /* Wait write complete */ 7582439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer write command */ 759134e2662SRemy Bohmer DM9000_DBG("phy_write(reg:0x%x, value:0x%x)\n", reg, value); 7602439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7612439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif /* CONFIG_DRIVER_DM9000 */ 762