1 /* 2 * This files contains card eeprom (93c46 or 93c56) programming routines, 3 * memory is addressed by 16 bits words. 4 * 5 * This is part of rtl8180 OpenSource driver. 6 * Copyright (C) Andrea Merello 2004 <andrea.merello@gmail.com> 7 * Released under the terms of GPL (General Public Licence) 8 * 9 * Parts of this driver are based on the GPL part of the 10 * official realtek driver. 11 * 12 * Parts of this driver are based on the rtl8180 driver skeleton 13 * from Patric Schenke & Andres Salomon. 14 * 15 * Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver. 16 * 17 * We want to thank the Authors of those projects and the Ndiswrapper 18 * project Authors. 19 */ 20 21 #include "r8180_93cx6.h" 22 23 static void eprom_cs(struct net_device *dev, short bit) 24 { 25 u8 cmdreg; 26 int err; 27 28 err = read_nic_byte_E(dev, EPROM_CMD, &cmdreg); 29 if (err) 30 return; 31 if (bit) 32 /* enable EPROM */ 33 write_nic_byte_E(dev, EPROM_CMD, cmdreg | EPROM_CS_BIT); 34 else 35 /* disable EPROM */ 36 write_nic_byte_E(dev, EPROM_CMD, cmdreg & ~EPROM_CS_BIT); 37 38 force_pci_posting(dev); 39 udelay(EPROM_DELAY); 40 } 41 42 43 static void eprom_ck_cycle(struct net_device *dev) 44 { 45 u8 cmdreg; 46 int err; 47 48 err = read_nic_byte_E(dev, EPROM_CMD, &cmdreg); 49 if (err) 50 return; 51 write_nic_byte_E(dev, EPROM_CMD, cmdreg | EPROM_CK_BIT); 52 force_pci_posting(dev); 53 udelay(EPROM_DELAY); 54 55 read_nic_byte_E(dev, EPROM_CMD, &cmdreg); 56 write_nic_byte_E(dev, EPROM_CMD, cmdreg & ~EPROM_CK_BIT); 57 force_pci_posting(dev); 58 udelay(EPROM_DELAY); 59 } 60 61 62 static void eprom_w(struct net_device *dev, short bit) 63 { 64 u8 cmdreg; 65 int err; 66 67 err = read_nic_byte_E(dev, EPROM_CMD, &cmdreg); 68 if (err) 69 return; 70 if (bit) 71 write_nic_byte_E(dev, EPROM_CMD, cmdreg | EPROM_W_BIT); 72 else 73 write_nic_byte_E(dev, EPROM_CMD, cmdreg & ~EPROM_W_BIT); 74 75 force_pci_posting(dev); 76 udelay(EPROM_DELAY); 77 } 78 79 80 static short eprom_r(struct net_device *dev) 81 { 82 u8 bit; 83 int err; 84 85 err = read_nic_byte_E(dev, EPROM_CMD, &bit); 86 if (err) 87 return err; 88 89 udelay(EPROM_DELAY); 90 91 if (bit & EPROM_R_BIT) 92 return 1; 93 94 return 0; 95 } 96 97 98 static void eprom_send_bits_string(struct net_device *dev, short b[], int len) 99 { 100 int i; 101 102 for (i = 0; i < len; i++) { 103 eprom_w(dev, b[i]); 104 eprom_ck_cycle(dev); 105 } 106 } 107 108 109 int eprom_read(struct net_device *dev, u32 addr) 110 { 111 struct r8192_priv *priv = ieee80211_priv(dev); 112 short read_cmd[] = {1, 1, 0}; 113 short addr_str[8]; 114 int i; 115 int addr_len; 116 u32 ret; 117 int err; 118 119 ret = 0; 120 /* enable EPROM programming */ 121 write_nic_byte_E(dev, EPROM_CMD, 122 (EPROM_CMD_PROGRAM<<EPROM_CMD_OPERATING_MODE_SHIFT)); 123 force_pci_posting(dev); 124 udelay(EPROM_DELAY); 125 126 if (priv->epromtype == EPROM_93c56) { 127 addr_str[7] = addr & 1; 128 addr_str[6] = addr & (1<<1); 129 addr_str[5] = addr & (1<<2); 130 addr_str[4] = addr & (1<<3); 131 addr_str[3] = addr & (1<<4); 132 addr_str[2] = addr & (1<<5); 133 addr_str[1] = addr & (1<<6); 134 addr_str[0] = addr & (1<<7); 135 addr_len = 8; 136 } else { 137 addr_str[5] = addr & 1; 138 addr_str[4] = addr & (1<<1); 139 addr_str[3] = addr & (1<<2); 140 addr_str[2] = addr & (1<<3); 141 addr_str[1] = addr & (1<<4); 142 addr_str[0] = addr & (1<<5); 143 addr_len = 6; 144 } 145 eprom_cs(dev, 1); 146 eprom_ck_cycle(dev); 147 eprom_send_bits_string(dev, read_cmd, 3); 148 eprom_send_bits_string(dev, addr_str, addr_len); 149 150 /* 151 * keep chip pin D to low state while reading. 152 * I'm unsure if it is necessary, but anyway shouldn't hurt 153 */ 154 eprom_w(dev, 0); 155 156 for (i = 0; i < 16; i++) { 157 /* eeprom needs a clk cycle between writing opcode&adr 158 * and reading data. (eeprom outs a dummy 0) 159 */ 160 eprom_ck_cycle(dev); 161 err = eprom_r(dev); 162 if (err < 0) 163 return err; 164 165 ret |= err<<(15-i); 166 } 167 168 eprom_cs(dev, 0); 169 eprom_ck_cycle(dev); 170 171 /* disable EPROM programming */ 172 write_nic_byte_E(dev, EPROM_CMD, 173 (EPROM_CMD_NORMAL<<EPROM_CMD_OPERATING_MODE_SHIFT)); 174 return ret; 175 } 176