@@ -24,6 +24,7 @@ struct i2c_eeprom_target_data {
2424 uint32_t buffer_idx ;
2525 uint32_t idx_write_cnt ;
2626 uint8_t address_width ;
27+ bool read_only ;
2728};
2829
2930struct i2c_eeprom_target_config {
@@ -115,22 +116,26 @@ static int eeprom_target_write_received(struct i2c_target_config *config,
115116 struct i2c_eeprom_target_data ,
116117 config );
117118
118- LOG_DBG ("eeprom: write done, val=0x%x" , val );
119-
120- /* In case EEPROM wants to be R/O, return !0 here could trigger
121- * a NACK to the I2C controller, support depends on the
122- * I2C controller support
123- */
124-
125119 if (data -> idx_write_cnt < (data -> address_width >> 3 )) {
120+ LOG_DBG ("eeprom: write addr, val=0x%x" , val );
121+
126122 if (data -> idx_write_cnt == 0 ) {
127123 data -> buffer_idx = 0 ;
128124 }
129125
130126 data -> buffer_idx = val | (data -> buffer_idx << 8 );
131127 data -> idx_write_cnt ++ ;
132- } else {
128+ } else if (!data -> read_only ) {
129+ LOG_DBG ("eeprom: write data, val=0x%x" , val );
130+
133131 data -> buffer [data -> buffer_idx ++ ] = val ;
132+ } else {
133+ LOG_DBG ("eeprom: write attempt to read-only EEPROM" );
134+
135+ /* In case the EEPROM is read-only, an error code is returned
136+ * to trigger a NACK on I2C controllers that support it.
137+ */
138+ return - EIO ;
134139 }
135140
136141 data -> buffer_idx = data -> buffer_idx % data -> buffer_size ;
@@ -249,34 +254,25 @@ static int i2c_eeprom_target_init(const struct device *dev)
249254 return 0 ;
250255}
251256
252- #define I2C_EEPROM_INIT (inst ) \
253- static struct i2c_eeprom_target_data \
254- i2c_eeprom_target_##inst##_dev_data = { \
255- .address_width = DT_INST_PROP_OR(inst, \
256- address_width, 8), \
257- }; \
258- \
259- static uint8_t \
260- i2c_eeprom_target_##inst##_buffer[(DT_INST_PROP(inst, size))]; \
261- \
262- BUILD_ASSERT(DT_INST_PROP(inst, size) <= \
263- (1 << DT_INST_PROP_OR(inst, address_width, 8)), \
264- "size must be <= than 2^address_width"); \
265- \
266- static const struct i2c_eeprom_target_config \
267- i2c_eeprom_target_##inst##_cfg = { \
268- .bus = I2C_DT_SPEC_INST_GET(inst), \
269- .buffer_size = DT_INST_PROP(inst, size), \
270- .buffer = i2c_eeprom_target_##inst##_buffer \
271- }; \
272- \
273- DEVICE_DT_INST_DEFINE(inst, \
274- &i2c_eeprom_target_init, \
275- NULL, \
276- &i2c_eeprom_target_##inst##_dev_data, \
277- &i2c_eeprom_target_##inst##_cfg, \
278- POST_KERNEL, \
279- CONFIG_I2C_TARGET_INIT_PRIORITY, \
280- &api_funcs);
257+ #define I2C_EEPROM_INIT (inst ) \
258+ static struct i2c_eeprom_target_data i2c_eeprom_target_##inst##_dev_data = { \
259+ .address_width = DT_INST_PROP_OR(inst, address_width, 8), \
260+ .read_only = DT_INST_PROP_OR(inst, read_only, 8), \
261+ }; \
262+ \
263+ static uint8_t i2c_eeprom_target_##inst##_buffer[(DT_INST_PROP(inst, size))]; \
264+ \
265+ BUILD_ASSERT(DT_INST_PROP(inst, size) <= (1 << DT_INST_PROP_OR(inst, address_width, 8)), \
266+ "size must be <= than 2^address_width"); \
267+ \
268+ static const struct i2c_eeprom_target_config i2c_eeprom_target_##inst##_cfg = { \
269+ .bus = I2C_DT_SPEC_INST_GET(inst), \
270+ .buffer_size = DT_INST_PROP(inst, size), \
271+ .buffer = i2c_eeprom_target_##inst##_buffer}; \
272+ \
273+ DEVICE_DT_INST_DEFINE(inst, &i2c_eeprom_target_init, NULL, \
274+ &i2c_eeprom_target_##inst##_dev_data, \
275+ &i2c_eeprom_target_##inst##_cfg, POST_KERNEL, \
276+ CONFIG_I2C_TARGET_INIT_PRIORITY, &api_funcs);
281277
282278DT_INST_FOREACH_STATUS_OKAY (I2C_EEPROM_INIT )
0 commit comments