19467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn/* 2654087faf8ad0695d6b384465e3380a1d8de1cb2Arce, Abraham * Copyright (C) 2004 - 2006 rt2x00 SourceForge Project 3654087faf8ad0695d6b384465e3380a1d8de1cb2Arce, Abraham * <http://rt2x00.serialmonkey.com> 4654087faf8ad0695d6b384465e3380a1d8de1cb2Arce, Abraham * 5654087faf8ad0695d6b384465e3380a1d8de1cb2Arce, Abraham * This program is free software; you can redistribute it and/or modify 6654087faf8ad0695d6b384465e3380a1d8de1cb2Arce, Abraham * it under the terms of the GNU General Public License as published by 7654087faf8ad0695d6b384465e3380a1d8de1cb2Arce, Abraham * the Free Software Foundation; either version 2 of the License, or 8654087faf8ad0695d6b384465e3380a1d8de1cb2Arce, Abraham * (at your option) any later version. 9654087faf8ad0695d6b384465e3380a1d8de1cb2Arce, Abraham * 10654087faf8ad0695d6b384465e3380a1d8de1cb2Arce, Abraham * This program is distributed in the hope that it will be useful, 11654087faf8ad0695d6b384465e3380a1d8de1cb2Arce, Abraham * but WITHOUT ANY WARRANTY; without even the implied warranty of 12654087faf8ad0695d6b384465e3380a1d8de1cb2Arce, Abraham * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13654087faf8ad0695d6b384465e3380a1d8de1cb2Arce, Abraham * GNU General Public License for more details. 14654087faf8ad0695d6b384465e3380a1d8de1cb2Arce, Abraham * 15654087faf8ad0695d6b384465e3380a1d8de1cb2Arce, Abraham * Module: eeprom_93cx6 16654087faf8ad0695d6b384465e3380a1d8de1cb2Arce, Abraham * Abstract: EEPROM reader routines for 93cx6 chipsets. 17654087faf8ad0695d6b384465e3380a1d8de1cb2Arce, Abraham * Supported chipsets: 93c46 & 93c66. 189467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn */ 199467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 209467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn#include <linux/kernel.h> 219467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn#include <linux/module.h> 229467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn#include <linux/delay.h> 239467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn#include <linux/eeprom_93cx6.h> 249467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 259467d64b0e88763914c01f71ddf591b166c4f526Ivo van DoornMODULE_AUTHOR("http://rt2x00.serialmonkey.com"); 269467d64b0e88763914c01f71ddf591b166c4f526Ivo van DoornMODULE_VERSION("1.0"); 279467d64b0e88763914c01f71ddf591b166c4f526Ivo van DoornMODULE_DESCRIPTION("EEPROM 93cx6 chip driver"); 289467d64b0e88763914c01f71ddf591b166c4f526Ivo van DoornMODULE_LICENSE("GPL"); 299467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 309467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doornstatic inline void eeprom_93cx6_pulse_high(struct eeprom_93cx6 *eeprom) 319467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn{ 329467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->reg_data_clock = 1; 339467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->register_write(eeprom); 344b914dc0493edff19ff698a18198a173a14ba9d2Ivo van Doorn 354b914dc0493edff19ff698a18198a173a14ba9d2Ivo van Doorn /* 364b914dc0493edff19ff698a18198a173a14ba9d2Ivo van Doorn * Add a short delay for the pulse to work. 377e9400f178d291b2208c4ed9aac0f425c1364000John W. Linville * According to the specifications the "maximum minimum" 387e9400f178d291b2208c4ed9aac0f425c1364000John W. Linville * time should be 450ns. 394b914dc0493edff19ff698a18198a173a14ba9d2Ivo van Doorn */ 407e9400f178d291b2208c4ed9aac0f425c1364000John W. Linville ndelay(450); 419467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn} 429467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 439467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doornstatic inline void eeprom_93cx6_pulse_low(struct eeprom_93cx6 *eeprom) 449467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn{ 459467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->reg_data_clock = 0; 469467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->register_write(eeprom); 474b914dc0493edff19ff698a18198a173a14ba9d2Ivo van Doorn 484b914dc0493edff19ff698a18198a173a14ba9d2Ivo van Doorn /* 494b914dc0493edff19ff698a18198a173a14ba9d2Ivo van Doorn * Add a short delay for the pulse to work. 508abd531e3f77188de2fc41e677d075cc66e61631Francois Romieu * According to the specifications the "maximum minimum" 518abd531e3f77188de2fc41e677d075cc66e61631Francois Romieu * time should be 450ns. 524b914dc0493edff19ff698a18198a173a14ba9d2Ivo van Doorn */ 538abd531e3f77188de2fc41e677d075cc66e61631Francois Romieu ndelay(450); 549467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn} 559467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 569467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doornstatic void eeprom_93cx6_startup(struct eeprom_93cx6 *eeprom) 579467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn{ 589467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn /* 599467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * Clear all flags, and enable chip select. 609467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn */ 619467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->register_read(eeprom); 629467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->reg_data_in = 0; 639467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->reg_data_out = 0; 649467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->reg_data_clock = 0; 659467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->reg_chip_select = 1; 66b30f8bdcfa7dd05f4268348f3388ff903132f28eBen Dooks eeprom->drive_data = 1; 679467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->register_write(eeprom); 689467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 699467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn /* 709467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * kick a pulse. 719467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn */ 729467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom_93cx6_pulse_high(eeprom); 739467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom_93cx6_pulse_low(eeprom); 749467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn} 759467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 769467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doornstatic void eeprom_93cx6_cleanup(struct eeprom_93cx6 *eeprom) 779467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn{ 789467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn /* 799467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * Clear chip_select and data_in flags. 809467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn */ 819467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->register_read(eeprom); 829467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->reg_data_in = 0; 839467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->reg_chip_select = 0; 849467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->register_write(eeprom); 859467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 869467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn /* 879467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * kick a pulse. 889467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn */ 899467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom_93cx6_pulse_high(eeprom); 909467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom_93cx6_pulse_low(eeprom); 919467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn} 929467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 939467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doornstatic void eeprom_93cx6_write_bits(struct eeprom_93cx6 *eeprom, 949467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn const u16 data, const u16 count) 959467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn{ 969467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn unsigned int i; 979467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 989467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->register_read(eeprom); 999467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 1009467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn /* 1019467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * Clear data flags. 1029467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn */ 1039467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->reg_data_in = 0; 1049467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->reg_data_out = 0; 105b30f8bdcfa7dd05f4268348f3388ff903132f28eBen Dooks eeprom->drive_data = 1; 1069467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 1079467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn /* 1089467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * Start writing all bits. 1099467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn */ 1109467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn for (i = count; i > 0; i--) { 1119467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn /* 1129467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * Check if this bit needs to be set. 1139467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn */ 1149467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->reg_data_in = !!(data & (1 << (i - 1))); 1159467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 1169467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn /* 1179467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * Write the bit to the eeprom register. 1189467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn */ 1199467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->register_write(eeprom); 1209467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 1219467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn /* 1229467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * Kick a pulse. 1239467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn */ 1249467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom_93cx6_pulse_high(eeprom); 1259467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom_93cx6_pulse_low(eeprom); 1269467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn } 1279467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 1289467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->reg_data_in = 0; 1299467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->register_write(eeprom); 1309467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn} 1319467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 1329467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doornstatic void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom, 1339467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn u16 *data, const u16 count) 1349467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn{ 1359467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn unsigned int i; 1369467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn u16 buf = 0; 1379467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 1389467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->register_read(eeprom); 1399467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 1409467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn /* 1419467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * Clear data flags. 1429467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn */ 1439467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->reg_data_in = 0; 1449467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->reg_data_out = 0; 145b30f8bdcfa7dd05f4268348f3388ff903132f28eBen Dooks eeprom->drive_data = 0; 1469467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 1479467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn /* 1489467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * Start reading all bits. 1499467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn */ 1509467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn for (i = count; i > 0; i--) { 1519467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom_93cx6_pulse_high(eeprom); 1529467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 1539467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->register_read(eeprom); 1549467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 1559467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn /* 1569467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * Clear data_in flag. 1579467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn */ 1589467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom->reg_data_in = 0; 1599467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 1609467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn /* 1619467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * Read if the bit has been set. 1629467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn */ 1639467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn if (eeprom->reg_data_out) 1649467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn buf |= (1 << (i - 1)); 1659467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 1669467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom_93cx6_pulse_low(eeprom); 1679467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn } 1689467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 1699467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn *data = buf; 1709467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn} 1719467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 1729467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn/** 1739467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * eeprom_93cx6_read - Read multiple words from eeprom 1749467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * @eeprom: Pointer to eeprom structure 1759467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * @word: Word index from where we should start reading 1769467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * @data: target pointer where the information will have to be stored 1779467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * 1789467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * This function will read the eeprom data as host-endian word 1799467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * into the given data pointer. 1809467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn */ 1819467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doornvoid eeprom_93cx6_read(struct eeprom_93cx6 *eeprom, const u8 word, 1829467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn u16 *data) 1839467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn{ 1849467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn u16 command; 1859467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 1869467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn /* 1879467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * Initialize the eeprom register 1889467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn */ 1899467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom_93cx6_startup(eeprom); 1909467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 1919467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn /* 1929467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * Select the read opcode and the word to be read. 1939467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn */ 1949467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn command = (PCI_EEPROM_READ_OPCODE << eeprom->width) | word; 1959467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom_93cx6_write_bits(eeprom, command, 1969467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn PCI_EEPROM_WIDTH_OPCODE + eeprom->width); 1979467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 1989467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn /* 1999467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * Read the requested 16 bits. 2009467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn */ 2019467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom_93cx6_read_bits(eeprom, data, 16); 2029467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 2039467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn /* 2049467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * Cleanup eeprom register. 2059467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn */ 2069467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom_93cx6_cleanup(eeprom); 2079467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn} 2089467d64b0e88763914c01f71ddf591b166c4f526Ivo van DoornEXPORT_SYMBOL_GPL(eeprom_93cx6_read); 2099467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 2109467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn/** 2119467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * eeprom_93cx6_multiread - Read multiple words from eeprom 2129467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * @eeprom: Pointer to eeprom structure 2139467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * @word: Word index from where we should start reading 2149467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * @data: target pointer where the information will have to be stored 2159467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * @words: Number of words that should be read. 2169467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * 2179467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * This function will read all requested words from the eeprom, 2189467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * this is done by calling eeprom_93cx6_read() multiple times. 2199467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * But with the additional change that while the eeprom_93cx6_read 2209467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * will return host ordered bytes, this method will return little 2219467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn * endian words. 2229467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn */ 2239467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doornvoid eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom, const u8 word, 2249467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn __le16 *data, const u16 words) 2259467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn{ 2269467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn unsigned int i; 2279467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn u16 tmp; 2289467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 2299467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn for (i = 0; i < words; i++) { 2309467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn tmp = 0; 2319467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn eeprom_93cx6_read(eeprom, word + i, &tmp); 2329467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn data[i] = cpu_to_le16(tmp); 2339467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn } 2349467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn} 2359467d64b0e88763914c01f71ddf591b166c4f526Ivo van DoornEXPORT_SYMBOL_GPL(eeprom_93cx6_multiread); 2369467d64b0e88763914c01f71ddf591b166c4f526Ivo van Doorn 237072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks/** 238072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks * eeprom_93cx6_wren - set the write enable state 239072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks * @eeprom: Pointer to eeprom structure 240072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks * @enable: true to enable writes, otherwise disable writes 241072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks * 242072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks * Set the EEPROM write enable state to either allow or deny 243072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks * writes depending on the @enable value. 244072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks */ 245072bc80156729f853e8bcafe1b17c48c74462887Ben Dooksvoid eeprom_93cx6_wren(struct eeprom_93cx6 *eeprom, bool enable) 246072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks{ 247072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks u16 command; 248072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks 249072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks /* start the command */ 250072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks eeprom_93cx6_startup(eeprom); 251072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks 252072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks /* create command to enable/disable */ 253072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks 254072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks command = enable ? PCI_EEPROM_EWEN_OPCODE : PCI_EEPROM_EWDS_OPCODE; 255072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks command <<= (eeprom->width - 2); 256072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks 257072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks eeprom_93cx6_write_bits(eeprom, command, 258072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks PCI_EEPROM_WIDTH_OPCODE + eeprom->width); 259072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks 260072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks eeprom_93cx6_cleanup(eeprom); 261072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks} 262072bc80156729f853e8bcafe1b17c48c74462887Ben DooksEXPORT_SYMBOL_GPL(eeprom_93cx6_wren); 263072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks 264072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks/** 265072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks * eeprom_93cx6_write - write data to the EEPROM 266072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks * @eeprom: Pointer to eeprom structure 267072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks * @addr: Address to write data to. 268072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks * @data: The data to write to address @addr. 269072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks * 270072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks * Write the @data to the specified @addr in the EEPROM and 271072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks * waiting for the device to finish writing. 272072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks * 273072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks * Note, since we do not expect large number of write operations 274072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks * we delay in between parts of the operation to avoid using excessive 275072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks * amounts of CPU time busy waiting. 276072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks */ 277072bc80156729f853e8bcafe1b17c48c74462887Ben Dooksvoid eeprom_93cx6_write(struct eeprom_93cx6 *eeprom, u8 addr, u16 data) 278072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks{ 279072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks int timeout = 100; 280072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks u16 command; 281072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks 282072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks /* start the command */ 283072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks eeprom_93cx6_startup(eeprom); 284072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks 285072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks command = PCI_EEPROM_WRITE_OPCODE << eeprom->width; 286072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks command |= addr; 287072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks 288072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks /* send write command */ 289072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks eeprom_93cx6_write_bits(eeprom, command, 290072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks PCI_EEPROM_WIDTH_OPCODE + eeprom->width); 291072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks 292072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks /* send data */ 293072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks eeprom_93cx6_write_bits(eeprom, data, 16); 294072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks 295072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks /* get ready to check for busy */ 296072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks eeprom->drive_data = 0; 297072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks eeprom->reg_chip_select = 1; 298072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks eeprom->register_write(eeprom); 299072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks 300072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks /* wait at-least 250ns to get DO to be the busy signal */ 301072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks usleep_range(1000, 2000); 302072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks 303072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks /* wait for DO to go high to signify finish */ 304072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks 305072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks while (true) { 306072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks eeprom->register_read(eeprom); 307072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks 308072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks if (eeprom->reg_data_out) 309072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks break; 310072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks 311072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks usleep_range(1000, 2000); 312072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks 313072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks if (--timeout <= 0) { 314072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks printk(KERN_ERR "%s: timeout\n", __func__); 315072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks break; 316072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks } 317072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks } 318072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks 319072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks eeprom_93cx6_cleanup(eeprom); 320072bc80156729f853e8bcafe1b17c48c74462887Ben Dooks} 321072bc80156729f853e8bcafe1b17c48c74462887Ben DooksEXPORT_SYMBOL_GPL(eeprom_93cx6_write); 322