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