#include <linux/bitfield.h>
#include <linux/firmware.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/sysfs.h>
struct eeprom_data { … };
#define I2C_SLAVE_BYTELEN …
#define I2C_SLAVE_FLAG_ADDR16 …
#define I2C_SLAVE_FLAG_RO …
#define I2C_SLAVE_DEVICE_MAGIC(_len, _flags) …
static int i2c_slave_eeprom_slave_cb(struct i2c_client *client,
enum i2c_slave_event event, u8 *val)
{ … }
static ssize_t i2c_slave_eeprom_bin_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr, char *buf, loff_t off, size_t count)
{ … }
static ssize_t i2c_slave_eeprom_bin_write(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr, char *buf, loff_t off, size_t count)
{ … }
static int i2c_slave_init_eeprom_data(struct eeprom_data *eeprom, struct i2c_client *client,
unsigned int size)
{ … }
static int i2c_slave_eeprom_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct eeprom_data *eeprom;
int ret;
unsigned int size = FIELD_GET(I2C_SLAVE_BYTELEN, id->driver_data) + 1;
unsigned int flag_addr16 = FIELD_GET(I2C_SLAVE_FLAG_ADDR16, id->driver_data);
eeprom = devm_kzalloc(&client->dev, sizeof(struct eeprom_data) + size, GFP_KERNEL);
if (!eeprom)
return -ENOMEM;
eeprom->num_address_bytes = flag_addr16 ? 2 : 1;
eeprom->address_mask = size - 1;
eeprom->read_only = FIELD_GET(I2C_SLAVE_FLAG_RO, id->driver_data);
spin_lock_init(&eeprom->buffer_lock);
i2c_set_clientdata(client, eeprom);
ret = i2c_slave_init_eeprom_data(eeprom, client, size);
if (ret)
return ret;
sysfs_bin_attr_init(&eeprom->bin);
eeprom->bin.attr.name = "slave-eeprom";
eeprom->bin.attr.mode = S_IRUSR | S_IWUSR;
eeprom->bin.read = i2c_slave_eeprom_bin_read;
eeprom->bin.write = i2c_slave_eeprom_bin_write;
eeprom->bin.size = size;
ret = sysfs_create_bin_file(&client->dev.kobj, &eeprom->bin);
if (ret)
return ret;
ret = i2c_slave_register(client, i2c_slave_eeprom_slave_cb);
if (ret) {
sysfs_remove_bin_file(&client->dev.kobj, &eeprom->bin);
return ret;
}
return 0;
};
static void i2c_slave_eeprom_remove(struct i2c_client *client)
{ … }
static const struct i2c_device_id i2c_slave_eeprom_id[] = …;
MODULE_DEVICE_TABLE(i2c, i2c_slave_eeprom_id);
static struct i2c_driver i2c_slave_eeprom_driver = …;
module_i2c_driver(…) …;
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_LICENSE(…) …;