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