1 /* 2 * Copyright (C) 2004 - 2006 rt2x00 SourceForge Project 3 * <http://rt2x00.serialmonkey.com> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * Module: eeprom_93cx6 16 * Abstract: EEPROM reader routines for 93cx6 chipsets. 17 * Supported chipsets: 93c46 & 93c66. 18 */ 19 20 #include <linux/kernel.h> 21 #include <linux/module.h> 22 #include <linux/delay.h> 23 #include <linux/eeprom_93cx6.h> 24 25 MODULE_AUTHOR("http://rt2x00.serialmonkey.com"); 26 MODULE_VERSION("1.0"); 27 MODULE_DESCRIPTION("EEPROM 93cx6 chip driver"); 28 MODULE_LICENSE("GPL"); 29 30 static inline void eeprom_93cx6_pulse_high(struct eeprom_93cx6 *eeprom) 31 { 32 eeprom->reg_data_clock = 1; 33 eeprom->register_write(eeprom); 34 35 /* 36 * Add a short delay for the pulse to work. 37 * According to the specifications the "maximum minimum" 38 * time should be 450ns. 39 */ 40 ndelay(450); 41 } 42 43 static inline void eeprom_93cx6_pulse_low(struct eeprom_93cx6 *eeprom) 44 { 45 eeprom->reg_data_clock = 0; 46 eeprom->register_write(eeprom); 47 48 /* 49 * Add a short delay for the pulse to work. 50 * According to the specifications the "maximum minimum" 51 * time should be 450ns. 52 */ 53 ndelay(450); 54 } 55 56 static void eeprom_93cx6_startup(struct eeprom_93cx6 *eeprom) 57 { 58 /* 59 * Clear all flags, and enable chip select. 60 */ 61 eeprom->register_read(eeprom); 62 eeprom->reg_data_in = 0; 63 eeprom->reg_data_out = 0; 64 eeprom->reg_data_clock = 0; 65 eeprom->reg_chip_select = 1; 66 eeprom->register_write(eeprom); 67 68 /* 69 * kick a pulse. 70 */ 71 eeprom_93cx6_pulse_high(eeprom); 72 eeprom_93cx6_pulse_low(eeprom); 73 } 74 75 static void eeprom_93cx6_cleanup(struct eeprom_93cx6 *eeprom) 76 { 77 /* 78 * Clear chip_select and data_in flags. 79 */ 80 eeprom->register_read(eeprom); 81 eeprom->reg_data_in = 0; 82 eeprom->reg_chip_select = 0; 83 eeprom->register_write(eeprom); 84 85 /* 86 * kick a pulse. 87 */ 88 eeprom_93cx6_pulse_high(eeprom); 89 eeprom_93cx6_pulse_low(eeprom); 90 } 91 92 static void eeprom_93cx6_write_bits(struct eeprom_93cx6 *eeprom, 93 const u16 data, const u16 count) 94 { 95 unsigned int i; 96 97 eeprom->register_read(eeprom); 98 99 /* 100 * Clear data flags. 101 */ 102 eeprom->reg_data_in = 0; 103 eeprom->reg_data_out = 0; 104 105 /* 106 * Start writing all bits. 107 */ 108 for (i = count; i > 0; i--) { 109 /* 110 * Check if this bit needs to be set. 111 */ 112 eeprom->reg_data_in = !!(data & (1 << (i - 1))); 113 114 /* 115 * Write the bit to the eeprom register. 116 */ 117 eeprom->register_write(eeprom); 118 119 /* 120 * Kick a pulse. 121 */ 122 eeprom_93cx6_pulse_high(eeprom); 123 eeprom_93cx6_pulse_low(eeprom); 124 } 125 126 eeprom->reg_data_in = 0; 127 eeprom->register_write(eeprom); 128 } 129 130 static void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom, 131 u16 *data, const u16 count) 132 { 133 unsigned int i; 134 u16 buf = 0; 135 136 eeprom->register_read(eeprom); 137 138 /* 139 * Clear data flags. 140 */ 141 eeprom->reg_data_in = 0; 142 eeprom->reg_data_out = 0; 143 144 /* 145 * Start reading all bits. 146 */ 147 for (i = count; i > 0; i--) { 148 eeprom_93cx6_pulse_high(eeprom); 149 150 eeprom->register_read(eeprom); 151 152 /* 153 * Clear data_in flag. 154 */ 155 eeprom->reg_data_in = 0; 156 157 /* 158 * Read if the bit has been set. 159 */ 160 if (eeprom->reg_data_out) 161 buf |= (1 << (i - 1)); 162 163 eeprom_93cx6_pulse_low(eeprom); 164 } 165 166 *data = buf; 167 } 168 169 /** 170 * eeprom_93cx6_read - Read multiple words from eeprom 171 * @eeprom: Pointer to eeprom structure 172 * @word: Word index from where we should start reading 173 * @data: target pointer where the information will have to be stored 174 * 175 * This function will read the eeprom data as host-endian word 176 * into the given data pointer. 177 */ 178 void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom, const u8 word, 179 u16 *data) 180 { 181 u16 command; 182 183 /* 184 * Initialize the eeprom register 185 */ 186 eeprom_93cx6_startup(eeprom); 187 188 /* 189 * Select the read opcode and the word to be read. 190 */ 191 command = (PCI_EEPROM_READ_OPCODE << eeprom->width) | word; 192 eeprom_93cx6_write_bits(eeprom, command, 193 PCI_EEPROM_WIDTH_OPCODE + eeprom->width); 194 195 /* 196 * Read the requested 16 bits. 197 */ 198 eeprom_93cx6_read_bits(eeprom, data, 16); 199 200 /* 201 * Cleanup eeprom register. 202 */ 203 eeprom_93cx6_cleanup(eeprom); 204 } 205 EXPORT_SYMBOL_GPL(eeprom_93cx6_read); 206 207 /** 208 * eeprom_93cx6_multiread - Read multiple words from eeprom 209 * @eeprom: Pointer to eeprom structure 210 * @word: Word index from where we should start reading 211 * @data: target pointer where the information will have to be stored 212 * @words: Number of words that should be read. 213 * 214 * This function will read all requested words from the eeprom, 215 * this is done by calling eeprom_93cx6_read() multiple times. 216 * But with the additional change that while the eeprom_93cx6_read 217 * will return host ordered bytes, this method will return little 218 * endian words. 219 */ 220 void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom, const u8 word, 221 __le16 *data, const u16 words) 222 { 223 unsigned int i; 224 u16 tmp; 225 226 for (i = 0; i < words; i++) { 227 tmp = 0; 228 eeprom_93cx6_read(eeprom, word + i, &tmp); 229 data[i] = cpu_to_le16(tmp); 230 } 231 } 232 EXPORT_SYMBOL_GPL(eeprom_93cx6_multiread); 233 234