Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (C) 2004 - 2006 rt2x00 SourceForge Project
0004  * <http://rt2x00.serialmonkey.com>
0005  *
0006  * Module: eeprom_93cx6
0007  * Abstract: EEPROM reader routines for 93cx6 chipsets.
0008  * Supported chipsets: 93c46 & 93c66.
0009  */
0010 
0011 #include <linux/kernel.h>
0012 #include <linux/module.h>
0013 #include <linux/delay.h>
0014 #include <linux/eeprom_93cx6.h>
0015 
0016 MODULE_AUTHOR("http://rt2x00.serialmonkey.com");
0017 MODULE_VERSION("1.0");
0018 MODULE_DESCRIPTION("EEPROM 93cx6 chip driver");
0019 MODULE_LICENSE("GPL");
0020 
0021 static inline void eeprom_93cx6_pulse_high(struct eeprom_93cx6 *eeprom)
0022 {
0023     eeprom->reg_data_clock = 1;
0024     eeprom->register_write(eeprom);
0025 
0026     /*
0027      * Add a short delay for the pulse to work.
0028      * According to the specifications the "maximum minimum"
0029      * time should be 450ns.
0030      */
0031     ndelay(450);
0032 }
0033 
0034 static inline void eeprom_93cx6_pulse_low(struct eeprom_93cx6 *eeprom)
0035 {
0036     eeprom->reg_data_clock = 0;
0037     eeprom->register_write(eeprom);
0038 
0039     /*
0040      * Add a short delay for the pulse to work.
0041      * According to the specifications the "maximum minimum"
0042      * time should be 450ns.
0043      */
0044     ndelay(450);
0045 }
0046 
0047 static void eeprom_93cx6_startup(struct eeprom_93cx6 *eeprom)
0048 {
0049     /*
0050      * Clear all flags, and enable chip select.
0051      */
0052     eeprom->register_read(eeprom);
0053     eeprom->reg_data_in = 0;
0054     eeprom->reg_data_out = 0;
0055     eeprom->reg_data_clock = 0;
0056     eeprom->reg_chip_select = 1;
0057     eeprom->drive_data = 1;
0058     eeprom->register_write(eeprom);
0059 
0060     /*
0061      * kick a pulse.
0062      */
0063     eeprom_93cx6_pulse_high(eeprom);
0064     eeprom_93cx6_pulse_low(eeprom);
0065 }
0066 
0067 static void eeprom_93cx6_cleanup(struct eeprom_93cx6 *eeprom)
0068 {
0069     /*
0070      * Clear chip_select and data_in flags.
0071      */
0072     eeprom->register_read(eeprom);
0073     eeprom->reg_data_in = 0;
0074     eeprom->reg_chip_select = 0;
0075     eeprom->register_write(eeprom);
0076 
0077     /*
0078      * kick a pulse.
0079      */
0080     eeprom_93cx6_pulse_high(eeprom);
0081     eeprom_93cx6_pulse_low(eeprom);
0082 }
0083 
0084 static void eeprom_93cx6_write_bits(struct eeprom_93cx6 *eeprom,
0085     const u16 data, const u16 count)
0086 {
0087     unsigned int i;
0088 
0089     eeprom->register_read(eeprom);
0090 
0091     /*
0092      * Clear data flags.
0093      */
0094     eeprom->reg_data_in = 0;
0095     eeprom->reg_data_out = 0;
0096     eeprom->drive_data = 1;
0097 
0098     /*
0099      * Start writing all bits.
0100      */
0101     for (i = count; i > 0; i--) {
0102         /*
0103          * Check if this bit needs to be set.
0104          */
0105         eeprom->reg_data_in = !!(data & (1 << (i - 1)));
0106 
0107         /*
0108          * Write the bit to the eeprom register.
0109          */
0110         eeprom->register_write(eeprom);
0111 
0112         /*
0113          * Kick a pulse.
0114          */
0115         eeprom_93cx6_pulse_high(eeprom);
0116         eeprom_93cx6_pulse_low(eeprom);
0117     }
0118 
0119     eeprom->reg_data_in = 0;
0120     eeprom->register_write(eeprom);
0121 }
0122 
0123 static void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom,
0124     u16 *data, const u16 count)
0125 {
0126     unsigned int i;
0127     u16 buf = 0;
0128 
0129     eeprom->register_read(eeprom);
0130 
0131     /*
0132      * Clear data flags.
0133      */
0134     eeprom->reg_data_in = 0;
0135     eeprom->reg_data_out = 0;
0136     eeprom->drive_data = 0;
0137 
0138     /*
0139      * Start reading all bits.
0140      */
0141     for (i = count; i > 0; i--) {
0142         eeprom_93cx6_pulse_high(eeprom);
0143 
0144         eeprom->register_read(eeprom);
0145 
0146         /*
0147          * Clear data_in flag.
0148          */
0149         eeprom->reg_data_in = 0;
0150 
0151         /*
0152          * Read if the bit has been set.
0153          */
0154         if (eeprom->reg_data_out)
0155             buf |= (1 << (i - 1));
0156 
0157         eeprom_93cx6_pulse_low(eeprom);
0158     }
0159 
0160     *data = buf;
0161 }
0162 
0163 /**
0164  * eeprom_93cx6_read - Read a word from eeprom
0165  * @eeprom: Pointer to eeprom structure
0166  * @word: Word index from where we should start reading
0167  * @data: target pointer where the information will have to be stored
0168  *
0169  * This function will read the eeprom data as host-endian word
0170  * into the given data pointer.
0171  */
0172 void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom, const u8 word,
0173     u16 *data)
0174 {
0175     u16 command;
0176 
0177     /*
0178      * Initialize the eeprom register
0179      */
0180     eeprom_93cx6_startup(eeprom);
0181 
0182     /*
0183      * Select the read opcode and the word to be read.
0184      */
0185     command = (PCI_EEPROM_READ_OPCODE << eeprom->width) | word;
0186     eeprom_93cx6_write_bits(eeprom, command,
0187         PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
0188 
0189     /*
0190      * Read the requested 16 bits.
0191      */
0192     eeprom_93cx6_read_bits(eeprom, data, 16);
0193 
0194     /*
0195      * Cleanup eeprom register.
0196      */
0197     eeprom_93cx6_cleanup(eeprom);
0198 }
0199 EXPORT_SYMBOL_GPL(eeprom_93cx6_read);
0200 
0201 /**
0202  * eeprom_93cx6_multiread - Read multiple words from eeprom
0203  * @eeprom: Pointer to eeprom structure
0204  * @word: Word index from where we should start reading
0205  * @data: target pointer where the information will have to be stored
0206  * @words: Number of words that should be read.
0207  *
0208  * This function will read all requested words from the eeprom,
0209  * this is done by calling eeprom_93cx6_read() multiple times.
0210  * But with the additional change that while the eeprom_93cx6_read
0211  * will return host ordered bytes, this method will return little
0212  * endian words.
0213  */
0214 void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom, const u8 word,
0215     __le16 *data, const u16 words)
0216 {
0217     unsigned int i;
0218     u16 tmp;
0219 
0220     for (i = 0; i < words; i++) {
0221         tmp = 0;
0222         eeprom_93cx6_read(eeprom, word + i, &tmp);
0223         data[i] = cpu_to_le16(tmp);
0224     }
0225 }
0226 EXPORT_SYMBOL_GPL(eeprom_93cx6_multiread);
0227 
0228 /**
0229  * eeprom_93cx6_readb - Read a byte from eeprom
0230  * @eeprom: Pointer to eeprom structure
0231  * @byte: Byte index from where we should start reading
0232  * @data: target pointer where the information will have to be stored
0233  *
0234  * This function will read a byte of the eeprom data
0235  * into the given data pointer.
0236  */
0237 void eeprom_93cx6_readb(struct eeprom_93cx6 *eeprom, const u8 byte,
0238     u8 *data)
0239 {
0240     u16 command;
0241     u16 tmp;
0242 
0243     /*
0244      * Initialize the eeprom register
0245      */
0246     eeprom_93cx6_startup(eeprom);
0247 
0248     /*
0249      * Select the read opcode and the byte to be read.
0250      */
0251     command = (PCI_EEPROM_READ_OPCODE << (eeprom->width + 1)) | byte;
0252     eeprom_93cx6_write_bits(eeprom, command,
0253         PCI_EEPROM_WIDTH_OPCODE + eeprom->width + 1);
0254 
0255     /*
0256      * Read the requested 8 bits.
0257      */
0258     eeprom_93cx6_read_bits(eeprom, &tmp, 8);
0259     *data = tmp & 0xff;
0260 
0261     /*
0262      * Cleanup eeprom register.
0263      */
0264     eeprom_93cx6_cleanup(eeprom);
0265 }
0266 EXPORT_SYMBOL_GPL(eeprom_93cx6_readb);
0267 
0268 /**
0269  * eeprom_93cx6_multireadb - Read multiple bytes from eeprom
0270  * @eeprom: Pointer to eeprom structure
0271  * @byte: Index from where we should start reading
0272  * @data: target pointer where the information will have to be stored
0273  * @bytes: Number of bytes that should be read.
0274  *
0275  * This function will read all requested bytes from the eeprom,
0276  * this is done by calling eeprom_93cx6_readb() multiple times.
0277  */
0278 void eeprom_93cx6_multireadb(struct eeprom_93cx6 *eeprom, const u8 byte,
0279     u8 *data, const u16 bytes)
0280 {
0281     unsigned int i;
0282 
0283     for (i = 0; i < bytes; i++)
0284         eeprom_93cx6_readb(eeprom, byte + i, &data[i]);
0285 }
0286 EXPORT_SYMBOL_GPL(eeprom_93cx6_multireadb);
0287 
0288 /**
0289  * eeprom_93cx6_wren - set the write enable state
0290  * @eeprom: Pointer to eeprom structure
0291  * @enable: true to enable writes, otherwise disable writes
0292  *
0293  * Set the EEPROM write enable state to either allow or deny
0294  * writes depending on the @enable value.
0295  */
0296 void eeprom_93cx6_wren(struct eeprom_93cx6 *eeprom, bool enable)
0297 {
0298     u16 command;
0299 
0300     /* start the command */
0301     eeprom_93cx6_startup(eeprom);
0302 
0303     /* create command to enable/disable */
0304 
0305     command = enable ? PCI_EEPROM_EWEN_OPCODE : PCI_EEPROM_EWDS_OPCODE;
0306     command <<= (eeprom->width - 2);
0307 
0308     eeprom_93cx6_write_bits(eeprom, command,
0309                 PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
0310 
0311     eeprom_93cx6_cleanup(eeprom);
0312 }
0313 EXPORT_SYMBOL_GPL(eeprom_93cx6_wren);
0314 
0315 /**
0316  * eeprom_93cx6_write - write data to the EEPROM
0317  * @eeprom: Pointer to eeprom structure
0318  * @addr: Address to write data to.
0319  * @data: The data to write to address @addr.
0320  *
0321  * Write the @data to the specified @addr in the EEPROM and
0322  * waiting for the device to finish writing.
0323  *
0324  * Note, since we do not expect large number of write operations
0325  * we delay in between parts of the operation to avoid using excessive
0326  * amounts of CPU time busy waiting.
0327  */
0328 void eeprom_93cx6_write(struct eeprom_93cx6 *eeprom, u8 addr, u16 data)
0329 {
0330     int timeout = 100;
0331     u16 command;
0332 
0333     /* start the command */
0334     eeprom_93cx6_startup(eeprom);
0335 
0336     command = PCI_EEPROM_WRITE_OPCODE << eeprom->width;
0337     command |= addr;
0338 
0339     /* send write command */
0340     eeprom_93cx6_write_bits(eeprom, command,
0341                 PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
0342 
0343     /* send data */
0344     eeprom_93cx6_write_bits(eeprom, data, 16);
0345 
0346     /* get ready to check for busy */
0347     eeprom->drive_data = 0;
0348     eeprom->reg_chip_select = 1;
0349     eeprom->register_write(eeprom);
0350 
0351     /* wait at-least 250ns to get DO to be the busy signal */
0352     usleep_range(1000, 2000);
0353 
0354     /* wait for DO to go high to signify finish */
0355 
0356     while (true) {
0357         eeprom->register_read(eeprom);
0358 
0359         if (eeprom->reg_data_out)
0360             break;
0361 
0362         usleep_range(1000, 2000);
0363 
0364         if (--timeout <= 0) {
0365             printk(KERN_ERR "%s: timeout\n", __func__);
0366             break;
0367         }
0368     }
0369 
0370     eeprom_93cx6_cleanup(eeprom);
0371 }
0372 EXPORT_SYMBOL_GPL(eeprom_93cx6_write);