18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2004 - 2006 rt2x00 SourceForge Project 48c2ecf20Sopenharmony_ci * <http://rt2x00.serialmonkey.com> 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Module: eeprom_93cx6 78c2ecf20Sopenharmony_ci * Abstract: EEPROM reader routines for 93cx6 chipsets. 88c2ecf20Sopenharmony_ci * Supported chipsets: 93c46 & 93c66. 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/kernel.h> 128c2ecf20Sopenharmony_ci#include <linux/module.h> 138c2ecf20Sopenharmony_ci#include <linux/delay.h> 148c2ecf20Sopenharmony_ci#include <linux/eeprom_93cx6.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ciMODULE_AUTHOR("http://rt2x00.serialmonkey.com"); 178c2ecf20Sopenharmony_ciMODULE_VERSION("1.0"); 188c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("EEPROM 93cx6 chip driver"); 198c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cistatic inline void eeprom_93cx6_pulse_high(struct eeprom_93cx6 *eeprom) 228c2ecf20Sopenharmony_ci{ 238c2ecf20Sopenharmony_ci eeprom->reg_data_clock = 1; 248c2ecf20Sopenharmony_ci eeprom->register_write(eeprom); 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci /* 278c2ecf20Sopenharmony_ci * Add a short delay for the pulse to work. 288c2ecf20Sopenharmony_ci * According to the specifications the "maximum minimum" 298c2ecf20Sopenharmony_ci * time should be 450ns. 308c2ecf20Sopenharmony_ci */ 318c2ecf20Sopenharmony_ci ndelay(450); 328c2ecf20Sopenharmony_ci} 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistatic inline void eeprom_93cx6_pulse_low(struct eeprom_93cx6 *eeprom) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci eeprom->reg_data_clock = 0; 378c2ecf20Sopenharmony_ci eeprom->register_write(eeprom); 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci /* 408c2ecf20Sopenharmony_ci * Add a short delay for the pulse to work. 418c2ecf20Sopenharmony_ci * According to the specifications the "maximum minimum" 428c2ecf20Sopenharmony_ci * time should be 450ns. 438c2ecf20Sopenharmony_ci */ 448c2ecf20Sopenharmony_ci ndelay(450); 458c2ecf20Sopenharmony_ci} 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cistatic void eeprom_93cx6_startup(struct eeprom_93cx6 *eeprom) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci /* 508c2ecf20Sopenharmony_ci * Clear all flags, and enable chip select. 518c2ecf20Sopenharmony_ci */ 528c2ecf20Sopenharmony_ci eeprom->register_read(eeprom); 538c2ecf20Sopenharmony_ci eeprom->reg_data_in = 0; 548c2ecf20Sopenharmony_ci eeprom->reg_data_out = 0; 558c2ecf20Sopenharmony_ci eeprom->reg_data_clock = 0; 568c2ecf20Sopenharmony_ci eeprom->reg_chip_select = 1; 578c2ecf20Sopenharmony_ci eeprom->drive_data = 1; 588c2ecf20Sopenharmony_ci eeprom->register_write(eeprom); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci /* 618c2ecf20Sopenharmony_ci * kick a pulse. 628c2ecf20Sopenharmony_ci */ 638c2ecf20Sopenharmony_ci eeprom_93cx6_pulse_high(eeprom); 648c2ecf20Sopenharmony_ci eeprom_93cx6_pulse_low(eeprom); 658c2ecf20Sopenharmony_ci} 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic void eeprom_93cx6_cleanup(struct eeprom_93cx6 *eeprom) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci /* 708c2ecf20Sopenharmony_ci * Clear chip_select and data_in flags. 718c2ecf20Sopenharmony_ci */ 728c2ecf20Sopenharmony_ci eeprom->register_read(eeprom); 738c2ecf20Sopenharmony_ci eeprom->reg_data_in = 0; 748c2ecf20Sopenharmony_ci eeprom->reg_chip_select = 0; 758c2ecf20Sopenharmony_ci eeprom->register_write(eeprom); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci /* 788c2ecf20Sopenharmony_ci * kick a pulse. 798c2ecf20Sopenharmony_ci */ 808c2ecf20Sopenharmony_ci eeprom_93cx6_pulse_high(eeprom); 818c2ecf20Sopenharmony_ci eeprom_93cx6_pulse_low(eeprom); 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistatic void eeprom_93cx6_write_bits(struct eeprom_93cx6 *eeprom, 858c2ecf20Sopenharmony_ci const u16 data, const u16 count) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci unsigned int i; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci eeprom->register_read(eeprom); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci /* 928c2ecf20Sopenharmony_ci * Clear data flags. 938c2ecf20Sopenharmony_ci */ 948c2ecf20Sopenharmony_ci eeprom->reg_data_in = 0; 958c2ecf20Sopenharmony_ci eeprom->reg_data_out = 0; 968c2ecf20Sopenharmony_ci eeprom->drive_data = 1; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci /* 998c2ecf20Sopenharmony_ci * Start writing all bits. 1008c2ecf20Sopenharmony_ci */ 1018c2ecf20Sopenharmony_ci for (i = count; i > 0; i--) { 1028c2ecf20Sopenharmony_ci /* 1038c2ecf20Sopenharmony_ci * Check if this bit needs to be set. 1048c2ecf20Sopenharmony_ci */ 1058c2ecf20Sopenharmony_ci eeprom->reg_data_in = !!(data & (1 << (i - 1))); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci /* 1088c2ecf20Sopenharmony_ci * Write the bit to the eeprom register. 1098c2ecf20Sopenharmony_ci */ 1108c2ecf20Sopenharmony_ci eeprom->register_write(eeprom); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci /* 1138c2ecf20Sopenharmony_ci * Kick a pulse. 1148c2ecf20Sopenharmony_ci */ 1158c2ecf20Sopenharmony_ci eeprom_93cx6_pulse_high(eeprom); 1168c2ecf20Sopenharmony_ci eeprom_93cx6_pulse_low(eeprom); 1178c2ecf20Sopenharmony_ci } 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci eeprom->reg_data_in = 0; 1208c2ecf20Sopenharmony_ci eeprom->register_write(eeprom); 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom, 1248c2ecf20Sopenharmony_ci u16 *data, const u16 count) 1258c2ecf20Sopenharmony_ci{ 1268c2ecf20Sopenharmony_ci unsigned int i; 1278c2ecf20Sopenharmony_ci u16 buf = 0; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci eeprom->register_read(eeprom); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci /* 1328c2ecf20Sopenharmony_ci * Clear data flags. 1338c2ecf20Sopenharmony_ci */ 1348c2ecf20Sopenharmony_ci eeprom->reg_data_in = 0; 1358c2ecf20Sopenharmony_ci eeprom->reg_data_out = 0; 1368c2ecf20Sopenharmony_ci eeprom->drive_data = 0; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci /* 1398c2ecf20Sopenharmony_ci * Start reading all bits. 1408c2ecf20Sopenharmony_ci */ 1418c2ecf20Sopenharmony_ci for (i = count; i > 0; i--) { 1428c2ecf20Sopenharmony_ci eeprom_93cx6_pulse_high(eeprom); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci eeprom->register_read(eeprom); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci /* 1478c2ecf20Sopenharmony_ci * Clear data_in flag. 1488c2ecf20Sopenharmony_ci */ 1498c2ecf20Sopenharmony_ci eeprom->reg_data_in = 0; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci /* 1528c2ecf20Sopenharmony_ci * Read if the bit has been set. 1538c2ecf20Sopenharmony_ci */ 1548c2ecf20Sopenharmony_ci if (eeprom->reg_data_out) 1558c2ecf20Sopenharmony_ci buf |= (1 << (i - 1)); 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci eeprom_93cx6_pulse_low(eeprom); 1588c2ecf20Sopenharmony_ci } 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci *data = buf; 1618c2ecf20Sopenharmony_ci} 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci/** 1648c2ecf20Sopenharmony_ci * eeprom_93cx6_read - Read a word from eeprom 1658c2ecf20Sopenharmony_ci * @eeprom: Pointer to eeprom structure 1668c2ecf20Sopenharmony_ci * @word: Word index from where we should start reading 1678c2ecf20Sopenharmony_ci * @data: target pointer where the information will have to be stored 1688c2ecf20Sopenharmony_ci * 1698c2ecf20Sopenharmony_ci * This function will read the eeprom data as host-endian word 1708c2ecf20Sopenharmony_ci * into the given data pointer. 1718c2ecf20Sopenharmony_ci */ 1728c2ecf20Sopenharmony_civoid eeprom_93cx6_read(struct eeprom_93cx6 *eeprom, const u8 word, 1738c2ecf20Sopenharmony_ci u16 *data) 1748c2ecf20Sopenharmony_ci{ 1758c2ecf20Sopenharmony_ci u16 command; 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci /* 1788c2ecf20Sopenharmony_ci * Initialize the eeprom register 1798c2ecf20Sopenharmony_ci */ 1808c2ecf20Sopenharmony_ci eeprom_93cx6_startup(eeprom); 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci /* 1838c2ecf20Sopenharmony_ci * Select the read opcode and the word to be read. 1848c2ecf20Sopenharmony_ci */ 1858c2ecf20Sopenharmony_ci command = (PCI_EEPROM_READ_OPCODE << eeprom->width) | word; 1868c2ecf20Sopenharmony_ci eeprom_93cx6_write_bits(eeprom, command, 1878c2ecf20Sopenharmony_ci PCI_EEPROM_WIDTH_OPCODE + eeprom->width); 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci /* 1908c2ecf20Sopenharmony_ci * Read the requested 16 bits. 1918c2ecf20Sopenharmony_ci */ 1928c2ecf20Sopenharmony_ci eeprom_93cx6_read_bits(eeprom, data, 16); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci /* 1958c2ecf20Sopenharmony_ci * Cleanup eeprom register. 1968c2ecf20Sopenharmony_ci */ 1978c2ecf20Sopenharmony_ci eeprom_93cx6_cleanup(eeprom); 1988c2ecf20Sopenharmony_ci} 1998c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(eeprom_93cx6_read); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci/** 2028c2ecf20Sopenharmony_ci * eeprom_93cx6_multiread - Read multiple words from eeprom 2038c2ecf20Sopenharmony_ci * @eeprom: Pointer to eeprom structure 2048c2ecf20Sopenharmony_ci * @word: Word index from where we should start reading 2058c2ecf20Sopenharmony_ci * @data: target pointer where the information will have to be stored 2068c2ecf20Sopenharmony_ci * @words: Number of words that should be read. 2078c2ecf20Sopenharmony_ci * 2088c2ecf20Sopenharmony_ci * This function will read all requested words from the eeprom, 2098c2ecf20Sopenharmony_ci * this is done by calling eeprom_93cx6_read() multiple times. 2108c2ecf20Sopenharmony_ci * But with the additional change that while the eeprom_93cx6_read 2118c2ecf20Sopenharmony_ci * will return host ordered bytes, this method will return little 2128c2ecf20Sopenharmony_ci * endian words. 2138c2ecf20Sopenharmony_ci */ 2148c2ecf20Sopenharmony_civoid eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom, const u8 word, 2158c2ecf20Sopenharmony_ci __le16 *data, const u16 words) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci unsigned int i; 2188c2ecf20Sopenharmony_ci u16 tmp; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci for (i = 0; i < words; i++) { 2218c2ecf20Sopenharmony_ci tmp = 0; 2228c2ecf20Sopenharmony_ci eeprom_93cx6_read(eeprom, word + i, &tmp); 2238c2ecf20Sopenharmony_ci data[i] = cpu_to_le16(tmp); 2248c2ecf20Sopenharmony_ci } 2258c2ecf20Sopenharmony_ci} 2268c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(eeprom_93cx6_multiread); 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci/** 2298c2ecf20Sopenharmony_ci * eeprom_93cx6_readb - Read a byte from eeprom 2308c2ecf20Sopenharmony_ci * @eeprom: Pointer to eeprom structure 2318c2ecf20Sopenharmony_ci * @byte: Byte index from where we should start reading 2328c2ecf20Sopenharmony_ci * @data: target pointer where the information will have to be stored 2338c2ecf20Sopenharmony_ci * 2348c2ecf20Sopenharmony_ci * This function will read a byte of the eeprom data 2358c2ecf20Sopenharmony_ci * into the given data pointer. 2368c2ecf20Sopenharmony_ci */ 2378c2ecf20Sopenharmony_civoid eeprom_93cx6_readb(struct eeprom_93cx6 *eeprom, const u8 byte, 2388c2ecf20Sopenharmony_ci u8 *data) 2398c2ecf20Sopenharmony_ci{ 2408c2ecf20Sopenharmony_ci u16 command; 2418c2ecf20Sopenharmony_ci u16 tmp; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci /* 2448c2ecf20Sopenharmony_ci * Initialize the eeprom register 2458c2ecf20Sopenharmony_ci */ 2468c2ecf20Sopenharmony_ci eeprom_93cx6_startup(eeprom); 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci /* 2498c2ecf20Sopenharmony_ci * Select the read opcode and the byte to be read. 2508c2ecf20Sopenharmony_ci */ 2518c2ecf20Sopenharmony_ci command = (PCI_EEPROM_READ_OPCODE << (eeprom->width + 1)) | byte; 2528c2ecf20Sopenharmony_ci eeprom_93cx6_write_bits(eeprom, command, 2538c2ecf20Sopenharmony_ci PCI_EEPROM_WIDTH_OPCODE + eeprom->width + 1); 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci /* 2568c2ecf20Sopenharmony_ci * Read the requested 8 bits. 2578c2ecf20Sopenharmony_ci */ 2588c2ecf20Sopenharmony_ci eeprom_93cx6_read_bits(eeprom, &tmp, 8); 2598c2ecf20Sopenharmony_ci *data = tmp & 0xff; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci /* 2628c2ecf20Sopenharmony_ci * Cleanup eeprom register. 2638c2ecf20Sopenharmony_ci */ 2648c2ecf20Sopenharmony_ci eeprom_93cx6_cleanup(eeprom); 2658c2ecf20Sopenharmony_ci} 2668c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(eeprom_93cx6_readb); 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci/** 2698c2ecf20Sopenharmony_ci * eeprom_93cx6_multireadb - Read multiple bytes from eeprom 2708c2ecf20Sopenharmony_ci * @eeprom: Pointer to eeprom structure 2718c2ecf20Sopenharmony_ci * @byte: Index from where we should start reading 2728c2ecf20Sopenharmony_ci * @data: target pointer where the information will have to be stored 2738c2ecf20Sopenharmony_ci * @bytes: Number of bytes that should be read. 2748c2ecf20Sopenharmony_ci * 2758c2ecf20Sopenharmony_ci * This function will read all requested bytes from the eeprom, 2768c2ecf20Sopenharmony_ci * this is done by calling eeprom_93cx6_readb() multiple times. 2778c2ecf20Sopenharmony_ci */ 2788c2ecf20Sopenharmony_civoid eeprom_93cx6_multireadb(struct eeprom_93cx6 *eeprom, const u8 byte, 2798c2ecf20Sopenharmony_ci u8 *data, const u16 bytes) 2808c2ecf20Sopenharmony_ci{ 2818c2ecf20Sopenharmony_ci unsigned int i; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci for (i = 0; i < bytes; i++) 2848c2ecf20Sopenharmony_ci eeprom_93cx6_readb(eeprom, byte + i, &data[i]); 2858c2ecf20Sopenharmony_ci} 2868c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(eeprom_93cx6_multireadb); 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci/** 2898c2ecf20Sopenharmony_ci * eeprom_93cx6_wren - set the write enable state 2908c2ecf20Sopenharmony_ci * @eeprom: Pointer to eeprom structure 2918c2ecf20Sopenharmony_ci * @enable: true to enable writes, otherwise disable writes 2928c2ecf20Sopenharmony_ci * 2938c2ecf20Sopenharmony_ci * Set the EEPROM write enable state to either allow or deny 2948c2ecf20Sopenharmony_ci * writes depending on the @enable value. 2958c2ecf20Sopenharmony_ci */ 2968c2ecf20Sopenharmony_civoid eeprom_93cx6_wren(struct eeprom_93cx6 *eeprom, bool enable) 2978c2ecf20Sopenharmony_ci{ 2988c2ecf20Sopenharmony_ci u16 command; 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci /* start the command */ 3018c2ecf20Sopenharmony_ci eeprom_93cx6_startup(eeprom); 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci /* create command to enable/disable */ 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci command = enable ? PCI_EEPROM_EWEN_OPCODE : PCI_EEPROM_EWDS_OPCODE; 3068c2ecf20Sopenharmony_ci command <<= (eeprom->width - 2); 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci eeprom_93cx6_write_bits(eeprom, command, 3098c2ecf20Sopenharmony_ci PCI_EEPROM_WIDTH_OPCODE + eeprom->width); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci eeprom_93cx6_cleanup(eeprom); 3128c2ecf20Sopenharmony_ci} 3138c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(eeprom_93cx6_wren); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci/** 3168c2ecf20Sopenharmony_ci * eeprom_93cx6_write - write data to the EEPROM 3178c2ecf20Sopenharmony_ci * @eeprom: Pointer to eeprom structure 3188c2ecf20Sopenharmony_ci * @addr: Address to write data to. 3198c2ecf20Sopenharmony_ci * @data: The data to write to address @addr. 3208c2ecf20Sopenharmony_ci * 3218c2ecf20Sopenharmony_ci * Write the @data to the specified @addr in the EEPROM and 3228c2ecf20Sopenharmony_ci * waiting for the device to finish writing. 3238c2ecf20Sopenharmony_ci * 3248c2ecf20Sopenharmony_ci * Note, since we do not expect large number of write operations 3258c2ecf20Sopenharmony_ci * we delay in between parts of the operation to avoid using excessive 3268c2ecf20Sopenharmony_ci * amounts of CPU time busy waiting. 3278c2ecf20Sopenharmony_ci */ 3288c2ecf20Sopenharmony_civoid eeprom_93cx6_write(struct eeprom_93cx6 *eeprom, u8 addr, u16 data) 3298c2ecf20Sopenharmony_ci{ 3308c2ecf20Sopenharmony_ci int timeout = 100; 3318c2ecf20Sopenharmony_ci u16 command; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci /* start the command */ 3348c2ecf20Sopenharmony_ci eeprom_93cx6_startup(eeprom); 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci command = PCI_EEPROM_WRITE_OPCODE << eeprom->width; 3378c2ecf20Sopenharmony_ci command |= addr; 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci /* send write command */ 3408c2ecf20Sopenharmony_ci eeprom_93cx6_write_bits(eeprom, command, 3418c2ecf20Sopenharmony_ci PCI_EEPROM_WIDTH_OPCODE + eeprom->width); 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci /* send data */ 3448c2ecf20Sopenharmony_ci eeprom_93cx6_write_bits(eeprom, data, 16); 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci /* get ready to check for busy */ 3478c2ecf20Sopenharmony_ci eeprom->drive_data = 0; 3488c2ecf20Sopenharmony_ci eeprom->reg_chip_select = 1; 3498c2ecf20Sopenharmony_ci eeprom->register_write(eeprom); 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci /* wait at-least 250ns to get DO to be the busy signal */ 3528c2ecf20Sopenharmony_ci usleep_range(1000, 2000); 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci /* wait for DO to go high to signify finish */ 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci while (true) { 3578c2ecf20Sopenharmony_ci eeprom->register_read(eeprom); 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci if (eeprom->reg_data_out) 3608c2ecf20Sopenharmony_ci break; 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci usleep_range(1000, 2000); 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci if (--timeout <= 0) { 3658c2ecf20Sopenharmony_ci printk(KERN_ERR "%s: timeout\n", __func__); 3668c2ecf20Sopenharmony_ci break; 3678c2ecf20Sopenharmony_ci } 3688c2ecf20Sopenharmony_ci } 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci eeprom_93cx6_cleanup(eeprom); 3718c2ecf20Sopenharmony_ci} 3728c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(eeprom_93cx6_write); 373