18fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang/* 28fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang This files contains card eeprom (93c46 or 93c56) programming routines, 38fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memory is addressed by 16 bits words. 48fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 58fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang This is part of rtl8180 OpenSource driver. 68fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang Copyright (C) Andrea Merello 2004 <andreamrl@tiscali.it> 78fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang Released under the terms of GPL (General Public Licence) 88fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 98fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang Parts of this driver are based on the GPL part of the 108fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang official realtek driver. 118fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 128fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang Parts of this driver are based on the rtl8180 driver skeleton 138fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang from Patric Schenke & Andres Salomon. 148fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 158fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver. 168fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 178fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang We want to tanks the Authors of those projects and the Ndiswrapper 188fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang project Authors. 198fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang*/ 208fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 218fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include "r8180_93cx6.h" 228fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 238fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangvoid eprom_cs(struct net_device *dev, short bit) 248fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 258fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(bit) 268fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang write_nic_byte_E(dev, EPROM_CMD, 278fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang (1<<EPROM_CS_SHIFT) | \ 288fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang read_nic_byte_E(dev, EPROM_CMD)); //enable EPROM 298fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang else 308fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang write_nic_byte_E(dev, EPROM_CMD, read_nic_byte_E(dev, EPROM_CMD)\ 318fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang &~(1<<EPROM_CS_SHIFT)); //disable EPROM 328fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 338fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang force_pci_posting(dev); 348fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang udelay(EPROM_DELAY); 358fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 368fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 378fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 388fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangvoid eprom_ck_cycle(struct net_device *dev) 398fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 408fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang write_nic_byte_E(dev, EPROM_CMD, 418fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang (1<<EPROM_CK_SHIFT) | read_nic_byte_E(dev,EPROM_CMD)); 428fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang force_pci_posting(dev); 438fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang udelay(EPROM_DELAY); 448fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang write_nic_byte_E(dev, EPROM_CMD, 458fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang read_nic_byte_E(dev, EPROM_CMD) &~ (1<<EPROM_CK_SHIFT)); 468fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang force_pci_posting(dev); 478fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang udelay(EPROM_DELAY); 488fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 498fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 508fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 518fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangvoid eprom_w(struct net_device *dev,short bit) 528fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 538fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(bit) 548fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang write_nic_byte_E(dev, EPROM_CMD, (1<<EPROM_W_SHIFT) | \ 558fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang read_nic_byte_E(dev,EPROM_CMD)); 568fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang else 578fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang write_nic_byte_E(dev, EPROM_CMD, read_nic_byte_E(dev,EPROM_CMD)\ 588fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang &~(1<<EPROM_W_SHIFT)); 598fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 608fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang force_pci_posting(dev); 618fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang udelay(EPROM_DELAY); 628fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 638fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 648fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 658fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangshort eprom_r(struct net_device *dev) 668fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 678fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang short bit; 688fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 698fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang bit=(read_nic_byte_E(dev, EPROM_CMD) & (1<<EPROM_R_SHIFT) ); 708fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang udelay(EPROM_DELAY); 718fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 728fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(bit) return 1; 738fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return 0; 748fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 758fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 768fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 778fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangvoid eprom_send_bits_string(struct net_device *dev, short b[], int len) 788fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 798fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang int i; 808fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 818fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang for(i=0; i<len; i++){ 828fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang eprom_w(dev, b[i]); 838fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang eprom_ck_cycle(dev); 848fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 858fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 868fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 878fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 888fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangu32 eprom_read(struct net_device *dev, u32 addr) 898fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 908fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct r8192_priv *priv = ieee80211_priv(dev); 918fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang short read_cmd[]={1,1,0}; 928fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang short addr_str[8]; 938fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang int i; 948fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang int addr_len; 958fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u32 ret; 968fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 978fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ret=0; 988fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang //enable EPROM programming 998fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang write_nic_byte_E(dev, EPROM_CMD, 1008fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang (EPROM_CMD_PROGRAM<<EPROM_CMD_OPERATING_MODE_SHIFT)); 1018fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang force_pci_posting(dev); 1028fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang udelay(EPROM_DELAY); 1038fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1048fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (priv->epromtype==EPROM_93c56){ 1058fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang addr_str[7]=addr & 1; 1068fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang addr_str[6]=addr & (1<<1); 1078fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang addr_str[5]=addr & (1<<2); 1088fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang addr_str[4]=addr & (1<<3); 1098fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang addr_str[3]=addr & (1<<4); 1108fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang addr_str[2]=addr & (1<<5); 1118fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang addr_str[1]=addr & (1<<6); 1128fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang addr_str[0]=addr & (1<<7); 1138fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang addr_len=8; 1148fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang }else{ 1158fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang addr_str[5]=addr & 1; 1168fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang addr_str[4]=addr & (1<<1); 1178fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang addr_str[3]=addr & (1<<2); 1188fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang addr_str[2]=addr & (1<<3); 1198fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang addr_str[1]=addr & (1<<4); 1208fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang addr_str[0]=addr & (1<<5); 1218fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang addr_len=6; 1228fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 1238fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang eprom_cs(dev, 1); 1248fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang eprom_ck_cycle(dev); 1258fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang eprom_send_bits_string(dev, read_cmd, 3); 1268fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang eprom_send_bits_string(dev, addr_str, addr_len); 1278fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1288fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang //keep chip pin D to low state while reading. 1298fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang //I'm unsure if it is necessary, but anyway shouldn't hurt 1308fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang eprom_w(dev, 0); 1318fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1328fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang for(i=0;i<16;i++){ 1338fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang //eeprom needs a clk cycle between writing opcode&adr 1348fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang //and reading data. (eeprom outs a dummy 0) 1358fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang eprom_ck_cycle(dev); 1368fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ret |= (eprom_r(dev)<<(15-i)); 1378fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 1388fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1398fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang eprom_cs(dev, 0); 1408fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang eprom_ck_cycle(dev); 1418fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1428fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang //disable EPROM programming 1438fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang write_nic_byte_E(dev, EPROM_CMD, 1448fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang (EPROM_CMD_NORMAL<<EPROM_CMD_OPERATING_MODE_SHIFT)); 1458fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return ret; 1468fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 147