Commit 9467d64b0e88763914c01f71ddf591b166c4f526

Authored by Ivo van Doorn
Committed by Jeff Garzik
1 parent 7dcca30a32

[PATCH] Add 93cx6 eeprom library

This patch adds a library for reading from 93cx6 eeproms.

Signed-off-by: Michael Wu <flamingice@sourmilk.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

Showing 4 changed files with 307 additions and 1 deletions Side-by-side Diff

drivers/misc/Kconfig
... ... @@ -34,6 +34,11 @@
34 34 If you choose to build module, its name will be phantom. If unsure,
35 35 say N here.
36 36  
  37 +config EEPROM_93CX6
  38 + tristate "EEPROM 93CX6 support"
  39 + ---help---
  40 + This is a driver for the EEPROM chipsets 93c46 and 93c66.
  41 + The driver supports both read as well as write commands.
37 42  
38 43 If unsure, say N.
39 44  
... ... @@ -186,7 +191,6 @@
186 191 notifications when the bay lever is ejected or inserted.
187 192  
188 193 If you are not sure, say Y here.
189   -
190 194  
191 195 endmenu
drivers/misc/Makefile
... ... @@ -14,4 +14,5 @@
14 14 obj-$(CONFIG_SGI_IOC4) += ioc4.o
15 15 obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
16 16 obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
  17 +obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
drivers/misc/eeprom_93cx6.c
  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 +
  33 +MODULE_AUTHOR("http://rt2x00.serialmonkey.com");
  34 +MODULE_VERSION("1.0");
  35 +MODULE_DESCRIPTION("EEPROM 93cx6 chip driver");
  36 +MODULE_LICENSE("GPL");
  37 +
  38 +static inline void eeprom_93cx6_pulse_high(struct eeprom_93cx6 *eeprom)
  39 +{
  40 + eeprom->reg_data_clock = 1;
  41 + eeprom->register_write(eeprom);
  42 + udelay(1);
  43 +}
  44 +
  45 +static inline void eeprom_93cx6_pulse_low(struct eeprom_93cx6 *eeprom)
  46 +{
  47 + eeprom->reg_data_clock = 0;
  48 + eeprom->register_write(eeprom);
  49 + udelay(1);
  50 +}
  51 +
  52 +static void eeprom_93cx6_startup(struct eeprom_93cx6 *eeprom)
  53 +{
  54 + /*
  55 + * Clear all flags, and enable chip select.
  56 + */
  57 + eeprom->register_read(eeprom);
  58 + eeprom->reg_data_in = 0;
  59 + eeprom->reg_data_out = 0;
  60 + eeprom->reg_data_clock = 0;
  61 + eeprom->reg_chip_select = 1;
  62 + eeprom->register_write(eeprom);
  63 +
  64 + /*
  65 + * kick a pulse.
  66 + */
  67 + eeprom_93cx6_pulse_high(eeprom);
  68 + eeprom_93cx6_pulse_low(eeprom);
  69 +}
  70 +
  71 +static void eeprom_93cx6_cleanup(struct eeprom_93cx6 *eeprom)
  72 +{
  73 + /*
  74 + * Clear chip_select and data_in flags.
  75 + */
  76 + eeprom->register_read(eeprom);
  77 + eeprom->reg_data_in = 0;
  78 + eeprom->reg_chip_select = 0;
  79 + eeprom->register_write(eeprom);
  80 +
  81 + /*
  82 + * kick a pulse.
  83 + */
  84 + eeprom_93cx6_pulse_high(eeprom);
  85 + eeprom_93cx6_pulse_low(eeprom);
  86 +}
  87 +
  88 +static void eeprom_93cx6_write_bits(struct eeprom_93cx6 *eeprom,
  89 + const u16 data, const u16 count)
  90 +{
  91 + unsigned int i;
  92 +
  93 + eeprom->register_read(eeprom);
  94 +
  95 + /*
  96 + * Clear data flags.
  97 + */
  98 + eeprom->reg_data_in = 0;
  99 + eeprom->reg_data_out = 0;
  100 +
  101 + /*
  102 + * Start writing all bits.
  103 + */
  104 + for (i = count; i > 0; i--) {
  105 + /*
  106 + * Check if this bit needs to be set.
  107 + */
  108 + eeprom->reg_data_in = !!(data & (1 << (i - 1)));
  109 +
  110 + /*
  111 + * Write the bit to the eeprom register.
  112 + */
  113 + eeprom->register_write(eeprom);
  114 +
  115 + /*
  116 + * Kick a pulse.
  117 + */
  118 + eeprom_93cx6_pulse_high(eeprom);
  119 + eeprom_93cx6_pulse_low(eeprom);
  120 + }
  121 +
  122 + eeprom->reg_data_in = 0;
  123 + eeprom->register_write(eeprom);
  124 +}
  125 +
  126 +static void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom,
  127 + u16 *data, const u16 count)
  128 +{
  129 + unsigned int i;
  130 + u16 buf = 0;
  131 +
  132 + eeprom->register_read(eeprom);
  133 +
  134 + /*
  135 + * Clear data flags.
  136 + */
  137 + eeprom->reg_data_in = 0;
  138 + eeprom->reg_data_out = 0;
  139 +
  140 + /*
  141 + * Start reading all bits.
  142 + */
  143 + for (i = count; i > 0; i--) {
  144 + eeprom_93cx6_pulse_high(eeprom);
  145 +
  146 + eeprom->register_read(eeprom);
  147 +
  148 + /*
  149 + * Clear data_in flag.
  150 + */
  151 + eeprom->reg_data_in = 0;
  152 +
  153 + /*
  154 + * Read if the bit has been set.
  155 + */
  156 + if (eeprom->reg_data_out)
  157 + buf |= (1 << (i - 1));
  158 +
  159 + eeprom_93cx6_pulse_low(eeprom);
  160 + }
  161 +
  162 + *data = buf;
  163 +}
  164 +
  165 +/**
  166 + * eeprom_93cx6_read - Read multiple words from eeprom
  167 + * @eeprom: Pointer to eeprom structure
  168 + * @word: Word index from where we should start reading
  169 + * @data: target pointer where the information will have to be stored
  170 + *
  171 + * This function will read the eeprom data as host-endian word
  172 + * into the given data pointer.
  173 + */
  174 +void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom, const u8 word,
  175 + u16 *data)
  176 +{
  177 + u16 command;
  178 +
  179 + /*
  180 + * Initialize the eeprom register
  181 + */
  182 + eeprom_93cx6_startup(eeprom);
  183 +
  184 + /*
  185 + * Select the read opcode and the word to be read.
  186 + */
  187 + command = (PCI_EEPROM_READ_OPCODE << eeprom->width) | word;
  188 + eeprom_93cx6_write_bits(eeprom, command,
  189 + PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
  190 +
  191 + /*
  192 + * Read the requested 16 bits.
  193 + */
  194 + eeprom_93cx6_read_bits(eeprom, data, 16);
  195 +
  196 + /*
  197 + * Cleanup eeprom register.
  198 + */
  199 + eeprom_93cx6_cleanup(eeprom);
  200 +}
  201 +EXPORT_SYMBOL_GPL(eeprom_93cx6_read);
  202 +
  203 +/**
  204 + * eeprom_93cx6_multiread - Read multiple words from eeprom
  205 + * @eeprom: Pointer to eeprom structure
  206 + * @word: Word index from where we should start reading
  207 + * @data: target pointer where the information will have to be stored
  208 + * @words: Number of words that should be read.
  209 + *
  210 + * This function will read all requested words from the eeprom,
  211 + * this is done by calling eeprom_93cx6_read() multiple times.
  212 + * But with the additional change that while the eeprom_93cx6_read
  213 + * will return host ordered bytes, this method will return little
  214 + * endian words.
  215 + */
  216 +void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom, const u8 word,
  217 + __le16 *data, const u16 words)
  218 +{
  219 + unsigned int i;
  220 + u16 tmp;
  221 +
  222 + for (i = 0; i < words; i++) {
  223 + tmp = 0;
  224 + eeprom_93cx6_read(eeprom, word + i, &tmp);
  225 + data[i] = cpu_to_le16(tmp);
  226 + }
  227 +}
  228 +EXPORT_SYMBOL_GPL(eeprom_93cx6_multiread);
include/linux/eeprom_93cx6.h
  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 datastructures for 93cx6 chipsets.
  24 + Supported chipsets: 93c46 & 93c66.
  25 + */
  26 +
  27 +/*
  28 + * EEPROM operation defines.
  29 + */
  30 +#define PCI_EEPROM_WIDTH_93C46 6
  31 +#define PCI_EEPROM_WIDTH_93C66 8
  32 +#define PCI_EEPROM_WIDTH_OPCODE 3
  33 +#define PCI_EEPROM_WRITE_OPCODE 0x05
  34 +#define PCI_EEPROM_READ_OPCODE 0x06
  35 +#define PCI_EEPROM_EWDS_OPCODE 0x10
  36 +#define PCI_EEPROM_EWEN_OPCODE 0x13
  37 +
  38 +/**
  39 + * struct eeprom_93cx6 - control structure for setting the commands
  40 + * for reading the eeprom data.
  41 + * @data: private pointer for the driver.
  42 + * @register_read(struct eeprom_93cx6 *eeprom): handler to
  43 + * read the eeprom register, this function should set all reg_* fields.
  44 + * @register_write(struct eeprom_93cx6 *eeprom): handler to
  45 + * write to the eeprom register by using all reg_* fields.
  46 + * @width: eeprom width, should be one of the PCI_EEPROM_WIDTH_* defines
  47 + * @reg_data_in: register field to indicate data input
  48 + * @reg_data_out: register field to indicate data output
  49 + * @reg_data_clock: register field to set the data clock
  50 + * @reg_chip_select: register field to set the chip select
  51 + *
  52 + * This structure is used for the communication between the driver
  53 + * and the eeprom_93cx6 handlers for reading the eeprom.
  54 + */
  55 +struct eeprom_93cx6 {
  56 + void *data;
  57 +
  58 + void (*register_read)(struct eeprom_93cx6 *eeprom);
  59 + void (*register_write)(struct eeprom_93cx6 *eeprom);
  60 +
  61 + int width;
  62 +
  63 + char reg_data_in;
  64 + char reg_data_out;
  65 + char reg_data_clock;
  66 + char reg_chip_select;
  67 +};
  68 +
  69 +extern void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom,
  70 + const u8 word, u16 *data);
  71 +extern void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom,
  72 + const u8 word, __le16 *data, const u16 words);