Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

misc: eeprom: eeprom_93cx6: Add quirk for extra read clock cycle

Add a quirk similar to eeprom_93xx46 to add an extra clock cycle before
reading data from the EEPROM.

The 93Cx6 family of EEPROMs output a "dummy 0 bit" between the writing
of the op-code/address from the host to the EEPROM and the reading of
the actual data from the EEPROM.

More info can be found on page 6 of the AT93C46 datasheet (linked below).
Similar notes are found in other 93xx6 datasheets.

In summary the read operation for a 93Cx6 EEPROM is:
Write to EEPROM: 110[A5-A0] (9 bits)
Read from EEPROM: 0[D15-D0] (17 bits)

Where:
110 is the start bit and READ OpCode
[A5-A0] is the address to read from
0 is a "dummy bit" preceding the actual data
[D15-D0] is the actual data.

Looking at the READ timing diagrams in the 93Cx6 datasheets the dummy
bit should be clocked out on the last address bit clock cycle meaning it
should be discarded naturally.

However, depending on the hardware configuration sometimes this dummy
bit is not discarded. This is the case with Exar PCI UARTs which require
an extra clock cycle between sending the address and reading the data.

Datasheet: https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-5193-SEEPROM-AT93C46D-Datasheet.pdf
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Parker Newman <pnewman@connecttech.com>
Link: https://lore.kernel.org/r/0f23973efefccd2544705a0480b4ad4c2353e407.1727880931.git.pnewman@connecttech.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Parker Newman and committed by
Greg Kroah-Hartman
7738a7ab 70acca67

+21
+10
drivers/misc/eeprom/eeprom_93cx6.c
··· 186 186 eeprom_93cx6_write_bits(eeprom, command, 187 187 PCI_EEPROM_WIDTH_OPCODE + eeprom->width); 188 188 189 + if (has_quirk_extra_read_cycle(eeprom)) { 190 + eeprom_93cx6_pulse_high(eeprom); 191 + eeprom_93cx6_pulse_low(eeprom); 192 + } 193 + 189 194 /* 190 195 * Read the requested 16 bits. 191 196 */ ··· 256 251 command = (PCI_EEPROM_READ_OPCODE << (eeprom->width + 1)) | byte; 257 252 eeprom_93cx6_write_bits(eeprom, command, 258 253 PCI_EEPROM_WIDTH_OPCODE + eeprom->width + 1); 254 + 255 + if (has_quirk_extra_read_cycle(eeprom)) { 256 + eeprom_93cx6_pulse_high(eeprom); 257 + eeprom_93cx6_pulse_low(eeprom); 258 + } 259 259 260 260 /* 261 261 * Read the requested 8 bits.
+11
include/linux/eeprom_93cx6.h
··· 11 11 Supported chipsets: 93c46, 93c56 and 93c66. 12 12 */ 13 13 14 + #include <linux/bits.h> 15 + 14 16 /* 15 17 * EEPROM operation defines. 16 18 */ ··· 36 34 * @register_write(struct eeprom_93cx6 *eeprom): handler to 37 35 * write to the eeprom register by using all reg_* fields. 38 36 * @width: eeprom width, should be one of the PCI_EEPROM_WIDTH_* defines 37 + * @quirks: eeprom or controller quirks 39 38 * @drive_data: Set if we're driving the data line. 40 39 * @reg_data_in: register field to indicate data input 41 40 * @reg_data_out: register field to indicate data output ··· 53 50 void (*register_write)(struct eeprom_93cx6 *eeprom); 54 51 55 52 int width; 53 + unsigned int quirks; 54 + /* Some EEPROMs require an extra clock cycle before reading */ 55 + #define PCI_EEPROM_QUIRK_EXTRA_READ_CYCLE BIT(0) 56 56 57 57 char drive_data; 58 58 char reg_data_in; ··· 77 71 78 72 extern void eeprom_93cx6_write(struct eeprom_93cx6 *eeprom, 79 73 u8 addr, u16 data); 74 + 75 + static inline bool has_quirk_extra_read_cycle(struct eeprom_93cx6 *eeprom) 76 + { 77 + return eeprom->quirks & PCI_EEPROM_QUIRK_EXTRA_READ_CYCLE; 78 + }