Commit 072bc80156729f853e8bcafe1b17c48c74462887

Authored by Ben Dooks
Committed by David S. Miller
1 parent b30f8bdcfa

eeprom_93cx6: Add write support

Add support for writing data to EEPROM.

Signed-off-by: Ben Dooks <ben@simtec.co.uk>
Cc: Wolfram Sang <w.sang@pengutronix.de>
Cc: Jean Delvare <khali@linux-fr.org>
Cc: Linux Kernel <linux-kernel@vger.kernel.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 2 changed files with 91 additions and 0 deletions Side-by-side Diff

drivers/misc/eeprom/eeprom_93cx6.c
... ... @@ -233,4 +233,90 @@
233 233 }
234 234 }
235 235 EXPORT_SYMBOL_GPL(eeprom_93cx6_multiread);
  236 +
  237 +/**
  238 + * eeprom_93cx6_wren - set the write enable state
  239 + * @eeprom: Pointer to eeprom structure
  240 + * @enable: true to enable writes, otherwise disable writes
  241 + *
  242 + * Set the EEPROM write enable state to either allow or deny
  243 + * writes depending on the @enable value.
  244 + */
  245 +void eeprom_93cx6_wren(struct eeprom_93cx6 *eeprom, bool enable)
  246 +{
  247 + u16 command;
  248 +
  249 + /* start the command */
  250 + eeprom_93cx6_startup(eeprom);
  251 +
  252 + /* create command to enable/disable */
  253 +
  254 + command = enable ? PCI_EEPROM_EWEN_OPCODE : PCI_EEPROM_EWDS_OPCODE;
  255 + command <<= (eeprom->width - 2);
  256 +
  257 + eeprom_93cx6_write_bits(eeprom, command,
  258 + PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
  259 +
  260 + eeprom_93cx6_cleanup(eeprom);
  261 +}
  262 +EXPORT_SYMBOL_GPL(eeprom_93cx6_wren);
  263 +
  264 +/**
  265 + * eeprom_93cx6_write - write data to the EEPROM
  266 + * @eeprom: Pointer to eeprom structure
  267 + * @addr: Address to write data to.
  268 + * @data: The data to write to address @addr.
  269 + *
  270 + * Write the @data to the specified @addr in the EEPROM and
  271 + * waiting for the device to finish writing.
  272 + *
  273 + * Note, since we do not expect large number of write operations
  274 + * we delay in between parts of the operation to avoid using excessive
  275 + * amounts of CPU time busy waiting.
  276 + */
  277 +void eeprom_93cx6_write(struct eeprom_93cx6 *eeprom, u8 addr, u16 data)
  278 +{
  279 + int timeout = 100;
  280 + u16 command;
  281 +
  282 + /* start the command */
  283 + eeprom_93cx6_startup(eeprom);
  284 +
  285 + command = PCI_EEPROM_WRITE_OPCODE << eeprom->width;
  286 + command |= addr;
  287 +
  288 + /* send write command */
  289 + eeprom_93cx6_write_bits(eeprom, command,
  290 + PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
  291 +
  292 + /* send data */
  293 + eeprom_93cx6_write_bits(eeprom, data, 16);
  294 +
  295 + /* get ready to check for busy */
  296 + eeprom->drive_data = 0;
  297 + eeprom->reg_chip_select = 1;
  298 + eeprom->register_write(eeprom);
  299 +
  300 + /* wait at-least 250ns to get DO to be the busy signal */
  301 + usleep_range(1000, 2000);
  302 +
  303 + /* wait for DO to go high to signify finish */
  304 +
  305 + while (true) {
  306 + eeprom->register_read(eeprom);
  307 +
  308 + if (eeprom->reg_data_out)
  309 + break;
  310 +
  311 + usleep_range(1000, 2000);
  312 +
  313 + if (--timeout <= 0) {
  314 + printk(KERN_ERR "%s: timeout\n", __func__);
  315 + break;
  316 + }
  317 + }
  318 +
  319 + eeprom_93cx6_cleanup(eeprom);
  320 +}
  321 +EXPORT_SYMBOL_GPL(eeprom_93cx6_write);
include/linux/eeprom_93cx6.h
... ... @@ -33,6 +33,7 @@
33 33 #define PCI_EEPROM_WIDTH_93C86 8
34 34 #define PCI_EEPROM_WIDTH_OPCODE 3
35 35 #define PCI_EEPROM_WRITE_OPCODE 0x05
  36 +#define PCI_EEPROM_ERASE_OPCODE 0x07
36 37 #define PCI_EEPROM_READ_OPCODE 0x06
37 38 #define PCI_EEPROM_EWDS_OPCODE 0x10
38 39 #define PCI_EEPROM_EWEN_OPCODE 0x13
... ... @@ -74,4 +75,9 @@
74 75 const u8 word, u16 *data);
75 76 extern void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom,
76 77 const u8 word, __le16 *data, const u16 words);
  78 +
  79 +extern void eeprom_93cx6_wren(struct eeprom_93cx6 *eeprom, bool enable);
  80 +
  81 +extern void eeprom_93cx6_write(struct eeprom_93cx6 *eeprom,
  82 + u8 addr, u16 data);