Updates the API and types to match updated I2C terminology. Replaces master with controller and slave with target. Updates all drivers to match the changed macros, types, and API signatures. Signed-off-by: Tom Burdick <thomas.burdick@intel.com>
222 lines
5.3 KiB
C
222 lines
5.3 KiB
C
/*
|
|
* Copyright (c) 2017 BayLibre, SAS
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#define DT_DRV_COMPAT atmel_at24
|
|
|
|
#include <zephyr/sys/util.h>
|
|
#include <zephyr/kernel.h>
|
|
#include <errno.h>
|
|
#include <zephyr/drivers/i2c.h>
|
|
#include <string.h>
|
|
#include <zephyr/drivers/i2c/target/eeprom.h>
|
|
|
|
#define LOG_LEVEL CONFIG_I2C_LOG_LEVEL
|
|
#include <zephyr/logging/log.h>
|
|
LOG_MODULE_REGISTER(i2c_target);
|
|
|
|
struct i2c_eeprom_target_data {
|
|
struct i2c_target_config config;
|
|
uint32_t buffer_size;
|
|
uint8_t *buffer;
|
|
uint32_t buffer_idx;
|
|
bool first_write;
|
|
};
|
|
|
|
struct i2c_eeprom_target_config {
|
|
struct i2c_dt_spec bus;
|
|
uint32_t buffer_size;
|
|
uint8_t *buffer;
|
|
};
|
|
|
|
int eeprom_target_program(const struct device *dev, const uint8_t *eeprom_data,
|
|
unsigned int length)
|
|
{
|
|
struct i2c_eeprom_target_data *data = dev->data;
|
|
|
|
if (length > data->buffer_size) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
memcpy(data->buffer, eeprom_data, length);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int eeprom_target_read(const struct device *dev, uint8_t *eeprom_data,
|
|
unsigned int offset)
|
|
{
|
|
struct i2c_eeprom_target_data *data = dev->data;
|
|
|
|
if (!data || offset >= data->buffer_size) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
*eeprom_data = data->buffer[offset];
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int eeprom_target_write_requested(struct i2c_target_config *config)
|
|
{
|
|
struct i2c_eeprom_target_data *data = CONTAINER_OF(config,
|
|
struct i2c_eeprom_target_data,
|
|
config);
|
|
|
|
LOG_DBG("eeprom: write req");
|
|
|
|
data->first_write = true;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int eeprom_target_read_requested(struct i2c_target_config *config,
|
|
uint8_t *val)
|
|
{
|
|
struct i2c_eeprom_target_data *data = CONTAINER_OF(config,
|
|
struct i2c_eeprom_target_data,
|
|
config);
|
|
|
|
*val = data->buffer[data->buffer_idx];
|
|
|
|
LOG_DBG("eeprom: read req, val=0x%x", *val);
|
|
|
|
/* Increment will be done in the read_processed callback */
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int eeprom_target_write_received(struct i2c_target_config *config,
|
|
uint8_t val)
|
|
{
|
|
struct i2c_eeprom_target_data *data = CONTAINER_OF(config,
|
|
struct i2c_eeprom_target_data,
|
|
config);
|
|
|
|
LOG_DBG("eeprom: write done, val=0x%x", val);
|
|
|
|
/* In case EEPROM wants to be R/O, return !0 here could trigger
|
|
* a NACK to the I2C controller, support depends on the
|
|
* I2C controller support
|
|
*/
|
|
|
|
if (data->first_write) {
|
|
data->buffer_idx = val;
|
|
data->first_write = false;
|
|
} else {
|
|
data->buffer[data->buffer_idx++] = val;
|
|
}
|
|
|
|
data->buffer_idx = data->buffer_idx % data->buffer_size;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int eeprom_target_read_processed(struct i2c_target_config *config,
|
|
uint8_t *val)
|
|
{
|
|
struct i2c_eeprom_target_data *data = CONTAINER_OF(config,
|
|
struct i2c_eeprom_target_data,
|
|
config);
|
|
|
|
/* Increment here */
|
|
data->buffer_idx = (data->buffer_idx + 1) % data->buffer_size;
|
|
|
|
*val = data->buffer[data->buffer_idx];
|
|
|
|
LOG_DBG("eeprom: read done, val=0x%x", *val);
|
|
|
|
/* Increment will be done in the next read_processed callback
|
|
* In case of STOP, the byte won't be taken in account
|
|
*/
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int eeprom_target_stop(struct i2c_target_config *config)
|
|
{
|
|
struct i2c_eeprom_target_data *data = CONTAINER_OF(config,
|
|
struct i2c_eeprom_target_data,
|
|
config);
|
|
|
|
LOG_DBG("eeprom: stop");
|
|
|
|
data->first_write = true;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int eeprom_target_register(const struct device *dev)
|
|
{
|
|
const struct i2c_eeprom_target_config *cfg = dev->config;
|
|
struct i2c_eeprom_target_data *data = dev->data;
|
|
|
|
return i2c_target_register(cfg->bus.bus, &data->config);
|
|
}
|
|
|
|
static int eeprom_target_unregister(const struct device *dev)
|
|
{
|
|
const struct i2c_eeprom_target_config *cfg = dev->config;
|
|
struct i2c_eeprom_target_data *data = dev->data;
|
|
|
|
return i2c_target_unregister(cfg->bus.bus, &data->config);
|
|
}
|
|
|
|
static const struct i2c_target_driver_api api_funcs = {
|
|
.driver_register = eeprom_target_register,
|
|
.driver_unregister = eeprom_target_unregister,
|
|
};
|
|
|
|
static const struct i2c_target_callbacks eeprom_callbacks = {
|
|
.write_requested = eeprom_target_write_requested,
|
|
.read_requested = eeprom_target_read_requested,
|
|
.write_received = eeprom_target_write_received,
|
|
.read_processed = eeprom_target_read_processed,
|
|
.stop = eeprom_target_stop,
|
|
};
|
|
|
|
static int i2c_eeprom_target_init(const struct device *dev)
|
|
{
|
|
struct i2c_eeprom_target_data *data = dev->data;
|
|
const struct i2c_eeprom_target_config *cfg = dev->config;
|
|
|
|
if (!device_is_ready(cfg->bus.bus)) {
|
|
LOG_ERR("I2C controller device not ready");
|
|
return -ENODEV;
|
|
}
|
|
|
|
data->buffer_size = cfg->buffer_size;
|
|
data->buffer = cfg->buffer;
|
|
data->config.address = cfg->bus.addr;
|
|
data->config.callbacks = &eeprom_callbacks;
|
|
|
|
return 0;
|
|
}
|
|
|
|
#define I2C_EEPROM_INIT(inst) \
|
|
static struct i2c_eeprom_target_data \
|
|
i2c_eeprom_target_##inst##_dev_data; \
|
|
\
|
|
static uint8_t \
|
|
i2c_eeprom_target_##inst##_buffer[(DT_INST_PROP(inst, size))]; \
|
|
\
|
|
static const struct i2c_eeprom_target_config \
|
|
i2c_eeprom_target_##inst##_cfg = { \
|
|
.bus = I2C_DT_SPEC_INST_GET(inst), \
|
|
.buffer_size = DT_INST_PROP(inst, size), \
|
|
.buffer = i2c_eeprom_target_##inst##_buffer \
|
|
}; \
|
|
\
|
|
DEVICE_DT_INST_DEFINE(inst, \
|
|
&i2c_eeprom_target_init, \
|
|
NULL, \
|
|
&i2c_eeprom_target_##inst##_dev_data, \
|
|
&i2c_eeprom_target_##inst##_cfg, \
|
|
POST_KERNEL, \
|
|
CONFIG_I2C_TARGET_INIT_PRIORITY, \
|
|
&api_funcs);
|
|
|
|
DT_INST_FOREACH_STATUS_OKAY(I2C_EEPROM_INIT)
|