#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/capability.h>
#include <linux/jiffies.h>
static const unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54,
0x55, 0x56, 0x57, I2C_CLIENT_END };
struct mutex update_lock;
unsigned long last_updated[8];
enum eeprom_nature nature;
static void eeprom_update_client(struct i2c_client *client, u8 slice)
struct eeprom_data *data = i2c_get_clientdata(client);
mutex_lock(&data->update_lock);
if (!(data->valid & (1 << slice)) ||
time_after(jiffies, data->last_updated[slice] + 300 * HZ)) {
dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice);
if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
for (i = slice << 5; i < (slice + 1) << 5; i += 32)
if (i2c_smbus_read_i2c_block_data(client, i,
for (i = slice << 5; i < (slice + 1) << 5; i += 2) {
int word = i2c_smbus_read_word_data(client, i);
data->data[i] = word & 0xff;
data->data[i + 1] = word >> 8;
data->last_updated[slice] = jiffies;
data->valid |= (1 << slice);
mutex_unlock(&data->update_lock);
static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
struct i2c_client *client = to_i2c_client(kobj_to_dev(kobj));
struct eeprom_data *data = i2c_get_clientdata(client);
for (slice = off >> 5; slice <= (off + count - 1) >> 5; slice++)
eeprom_update_client(client, slice);
if (data->nature == VAIO && !capable(CAP_SYS_ADMIN)) {