summaryrefslogtreecommitdiffstats
path: root/drivers/i2c/i2c-slave-eeprom.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/i2c-slave-eeprom.c')
-rw-r--r--drivers/i2c/i2c-slave-eeprom.c42
1 files changed, 31 insertions, 11 deletions
diff --git a/drivers/i2c/i2c-slave-eeprom.c b/drivers/i2c/i2c-slave-eeprom.c
index be65d3842878..92ff9991bae8 100644
--- a/drivers/i2c/i2c-slave-eeprom.c
+++ b/drivers/i2c/i2c-slave-eeprom.c
@@ -11,6 +11,13 @@
11 * pointer, yet implementation is deferred until the need actually arises. 11 * pointer, yet implementation is deferred until the need actually arises.
12 */ 12 */
13 13
14/*
15 * FIXME: What to do if only 8 bits of a 16 bit address are sent?
16 * The ST-M24C64 sends only 0xff then. Needs verification with other
17 * EEPROMs, though. We currently use the 8 bit as a valid address.
18 */
19
20#include <linux/bitfield.h>
14#include <linux/i2c.h> 21#include <linux/i2c.h>
15#include <linux/init.h> 22#include <linux/init.h>
16#include <linux/module.h> 23#include <linux/module.h>
@@ -21,12 +28,18 @@
21 28
22struct eeprom_data { 29struct eeprom_data {
23 struct bin_attribute bin; 30 struct bin_attribute bin;
24 bool first_write;
25 spinlock_t buffer_lock; 31 spinlock_t buffer_lock;
26 u8 buffer_idx; 32 u16 buffer_idx;
33 u16 address_mask;
34 u8 num_address_bytes;
35 u8 idx_write_cnt;
27 u8 buffer[]; 36 u8 buffer[];
28}; 37};
29 38
39#define I2C_SLAVE_BYTELEN GENMASK(15, 0)
40#define I2C_SLAVE_FLAG_ADDR16 BIT(16)
41#define I2C_SLAVE_DEVICE_MAGIC(_len, _flags) ((_flags) | (_len))
42
30static int i2c_slave_eeprom_slave_cb(struct i2c_client *client, 43static int i2c_slave_eeprom_slave_cb(struct i2c_client *client,
31 enum i2c_slave_event event, u8 *val) 44 enum i2c_slave_event event, u8 *val)
32{ 45{
@@ -34,12 +47,14 @@ static int i2c_slave_eeprom_slave_cb(struct i2c_client *client,
34 47
35 switch (event) { 48 switch (event) {
36 case I2C_SLAVE_WRITE_RECEIVED: 49 case I2C_SLAVE_WRITE_RECEIVED:
37 if (eeprom->first_write) { 50 if (eeprom->idx_write_cnt < eeprom->num_address_bytes) {
38 eeprom->buffer_idx = *val; 51 if (eeprom->idx_write_cnt == 0)
39 eeprom->first_write = false; 52 eeprom->buffer_idx = 0;
53 eeprom->buffer_idx = *val | (eeprom->buffer_idx << 8);
54 eeprom->idx_write_cnt++;
40 } else { 55 } else {
41 spin_lock(&eeprom->buffer_lock); 56 spin_lock(&eeprom->buffer_lock);
42 eeprom->buffer[eeprom->buffer_idx++] = *val; 57 eeprom->buffer[eeprom->buffer_idx++ & eeprom->address_mask] = *val;
43 spin_unlock(&eeprom->buffer_lock); 58 spin_unlock(&eeprom->buffer_lock);
44 } 59 }
45 break; 60 break;
@@ -50,7 +65,7 @@ static int i2c_slave_eeprom_slave_cb(struct i2c_client *client,
50 /* fallthrough */ 65 /* fallthrough */
51 case I2C_SLAVE_READ_REQUESTED: 66 case I2C_SLAVE_READ_REQUESTED:
52 spin_lock(&eeprom->buffer_lock); 67 spin_lock(&eeprom->buffer_lock);
53 *val = eeprom->buffer[eeprom->buffer_idx]; 68 *val = eeprom->buffer[eeprom->buffer_idx & eeprom->address_mask];
54 spin_unlock(&eeprom->buffer_lock); 69 spin_unlock(&eeprom->buffer_lock);
55 /* 70 /*
56 * Do not increment buffer_idx here, because we don't know if 71 * Do not increment buffer_idx here, because we don't know if
@@ -61,7 +76,7 @@ static int i2c_slave_eeprom_slave_cb(struct i2c_client *client,
61 76
62 case I2C_SLAVE_STOP: 77 case I2C_SLAVE_STOP:
63 case I2C_SLAVE_WRITE_REQUESTED: 78 case I2C_SLAVE_WRITE_REQUESTED:
64 eeprom->first_write = true; 79 eeprom->idx_write_cnt = 0;
65 break; 80 break;
66 81
67 default: 82 default:
@@ -105,13 +120,16 @@ static int i2c_slave_eeprom_probe(struct i2c_client *client, const struct i2c_de
105{ 120{
106 struct eeprom_data *eeprom; 121 struct eeprom_data *eeprom;
107 int ret; 122 int ret;
108 unsigned size = id->driver_data; 123 unsigned int size = FIELD_GET(I2C_SLAVE_BYTELEN, id->driver_data);
124 unsigned int flag_addr16 = FIELD_GET(I2C_SLAVE_FLAG_ADDR16, id->driver_data);
109 125
110 eeprom = devm_kzalloc(&client->dev, sizeof(struct eeprom_data) + size, GFP_KERNEL); 126 eeprom = devm_kzalloc(&client->dev, sizeof(struct eeprom_data) + size, GFP_KERNEL);
111 if (!eeprom) 127 if (!eeprom)
112 return -ENOMEM; 128 return -ENOMEM;
113 129
114 eeprom->first_write = true; 130 eeprom->idx_write_cnt = 0;
131 eeprom->num_address_bytes = flag_addr16 ? 2 : 1;
132 eeprom->address_mask = size - 1;
115 spin_lock_init(&eeprom->buffer_lock); 133 spin_lock_init(&eeprom->buffer_lock);
116 i2c_set_clientdata(client, eeprom); 134 i2c_set_clientdata(client, eeprom);
117 135
@@ -146,7 +164,9 @@ static int i2c_slave_eeprom_remove(struct i2c_client *client)
146} 164}
147 165
148static const struct i2c_device_id i2c_slave_eeprom_id[] = { 166static const struct i2c_device_id i2c_slave_eeprom_id[] = {
149 { "slave-24c02", 2048 / 8 }, 167 { "slave-24c02", I2C_SLAVE_DEVICE_MAGIC(2048 / 8, 0) },
168 { "slave-24c32", I2C_SLAVE_DEVICE_MAGIC(32768 / 8, I2C_SLAVE_FLAG_ADDR16) },
169 { "slave-24c64", I2C_SLAVE_DEVICE_MAGIC(65536 / 8, I2C_SLAVE_FLAG_ADDR16) },
150 { } 170 { }
151}; 171};
152MODULE_DEVICE_TABLE(i2c, i2c_slave_eeprom_id); 172MODULE_DEVICE_TABLE(i2c, i2c_slave_eeprom_id);