| From 651022e78f414dc8b77558f54971dbd026d481df Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 5 Jan 2021 16:28:12 +0530 |
| Subject: misc: eeprom_93xx46: Add quirk to support Microchip 93LC46B eeprom |
| |
| From: Aswath Govindraju <a-govindraju@ti.com> |
| |
| [ Upstream commit f6f1f8e6e3eea25f539105d48166e91f0ab46dd1 ] |
| |
| A dummy zero bit is sent preceding the data during a read transfer by the |
| Microchip 93LC46B eeprom (section 2.7 of[1]). This results in right shift |
| of data during a read. In order to ignore this bit a quirk can be added to |
| send an extra zero bit after the read address. |
| |
| Add a quirk to ignore the zero bit sent before data by adding a zero bit |
| after the read address. |
| |
| [1] - https://www.mouser.com/datasheet/2/268/20001749K-277859.pdf |
| |
| Signed-off-by: Aswath Govindraju <a-govindraju@ti.com> |
| Link: https://lore.kernel.org/r/20210105105817.17644-3-a-govindraju@ti.com |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/misc/eeprom/eeprom_93xx46.c | 15 +++++++++++++++ |
| include/linux/eeprom_93xx46.h | 2 ++ |
| 2 files changed, 17 insertions(+) |
| |
| diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c |
| index a3248ebd28c6..182feab6da25 100644 |
| --- a/drivers/misc/eeprom/eeprom_93xx46.c |
| +++ b/drivers/misc/eeprom/eeprom_93xx46.c |
| @@ -38,6 +38,10 @@ static const struct eeprom_93xx46_devtype_data atmel_at93c46d_data = { |
| EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH, |
| }; |
| |
| +static const struct eeprom_93xx46_devtype_data microchip_93lc46b_data = { |
| + .quirks = EEPROM_93XX46_QUIRK_EXTRA_READ_CYCLE, |
| +}; |
| + |
| struct eeprom_93xx46_dev { |
| struct spi_device *spi; |
| struct eeprom_93xx46_platform_data *pdata; |
| @@ -58,6 +62,11 @@ static inline bool has_quirk_instruction_length(struct eeprom_93xx46_dev *edev) |
| return edev->pdata->quirks & EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH; |
| } |
| |
| +static inline bool has_quirk_extra_read_cycle(struct eeprom_93xx46_dev *edev) |
| +{ |
| + return edev->pdata->quirks & EEPROM_93XX46_QUIRK_EXTRA_READ_CYCLE; |
| +} |
| + |
| static int eeprom_93xx46_read(void *priv, unsigned int off, |
| void *val, size_t count) |
| { |
| @@ -99,6 +108,11 @@ static int eeprom_93xx46_read(void *priv, unsigned int off, |
| dev_dbg(&edev->spi->dev, "read cmd 0x%x, %d Hz\n", |
| cmd_addr, edev->spi->max_speed_hz); |
| |
| + if (has_quirk_extra_read_cycle(edev)) { |
| + cmd_addr <<= 1; |
| + bits += 1; |
| + } |
| + |
| spi_message_init(&m); |
| |
| t[0].tx_buf = (char *)&cmd_addr; |
| @@ -366,6 +380,7 @@ static void select_deassert(void *context) |
| static const struct of_device_id eeprom_93xx46_of_table[] = { |
| { .compatible = "eeprom-93xx46", }, |
| { .compatible = "atmel,at93c46d", .data = &atmel_at93c46d_data, }, |
| + { .compatible = "microchip,93lc46b", .data = µchip_93lc46b_data, }, |
| {} |
| }; |
| MODULE_DEVICE_TABLE(of, eeprom_93xx46_of_table); |
| diff --git a/include/linux/eeprom_93xx46.h b/include/linux/eeprom_93xx46.h |
| index eec7928ff8fe..99580c22f91a 100644 |
| --- a/include/linux/eeprom_93xx46.h |
| +++ b/include/linux/eeprom_93xx46.h |
| @@ -16,6 +16,8 @@ struct eeprom_93xx46_platform_data { |
| #define EEPROM_93XX46_QUIRK_SINGLE_WORD_READ (1 << 0) |
| /* Instructions such as EWEN are (addrlen + 2) in length. */ |
| #define EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH (1 << 1) |
| +/* Add extra cycle after address during a read */ |
| +#define EEPROM_93XX46_QUIRK_EXTRA_READ_CYCLE BIT(2) |
| |
| /* |
| * optional hooks to control additional logic |
| -- |
| 2.30.1 |
| |