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