Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (C) 1998, 1999  Frodo Looijaard <frodol@dds.nl> and
0004  *                           Philip Edelbrock <phil@netroedge.com>
0005  * Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
0006  * Copyright (C) 2003 IBM Corp.
0007  * Copyright (C) 2004 Jean Delvare <jdelvare@suse.de>
0008  */
0009 
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/device.h>
0013 #include <linux/capability.h>
0014 #include <linux/jiffies.h>
0015 #include <linux/i2c.h>
0016 #include <linux/mutex.h>
0017 
0018 /* Addresses to scan */
0019 static const unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54,
0020                     0x55, 0x56, 0x57, I2C_CLIENT_END };
0021 
0022 
0023 /* Size of EEPROM in bytes */
0024 #define EEPROM_SIZE     256
0025 
0026 /* possible types of eeprom devices */
0027 enum eeprom_nature {
0028     UNKNOWN,
0029     VAIO,
0030 };
0031 
0032 /* Each client has this additional data */
0033 struct eeprom_data {
0034     struct mutex update_lock;
0035     u8 valid;           /* bitfield, bit!=0 if slice is valid */
0036     unsigned long last_updated[8];  /* In jiffies, 8 slices */
0037     u8 data[EEPROM_SIZE];       /* Register values */
0038     enum eeprom_nature nature;
0039 };
0040 
0041 
0042 static void eeprom_update_client(struct i2c_client *client, u8 slice)
0043 {
0044     struct eeprom_data *data = i2c_get_clientdata(client);
0045     int i;
0046 
0047     mutex_lock(&data->update_lock);
0048 
0049     if (!(data->valid & (1 << slice)) ||
0050         time_after(jiffies, data->last_updated[slice] + 300 * HZ)) {
0051         dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice);
0052 
0053         if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
0054             for (i = slice << 5; i < (slice + 1) << 5; i += 32)
0055                 if (i2c_smbus_read_i2c_block_data(client, i,
0056                             32, data->data + i)
0057                             != 32)
0058                     goto exit;
0059         } else {
0060             for (i = slice << 5; i < (slice + 1) << 5; i += 2) {
0061                 int word = i2c_smbus_read_word_data(client, i);
0062                 if (word < 0)
0063                     goto exit;
0064                 data->data[i] = word & 0xff;
0065                 data->data[i + 1] = word >> 8;
0066             }
0067         }
0068         data->last_updated[slice] = jiffies;
0069         data->valid |= (1 << slice);
0070     }
0071 exit:
0072     mutex_unlock(&data->update_lock);
0073 }
0074 
0075 static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
0076                struct bin_attribute *bin_attr,
0077                char *buf, loff_t off, size_t count)
0078 {
0079     struct i2c_client *client = kobj_to_i2c_client(kobj);
0080     struct eeprom_data *data = i2c_get_clientdata(client);
0081     u8 slice;
0082 
0083     /* Only refresh slices which contain requested bytes */
0084     for (slice = off >> 5; slice <= (off + count - 1) >> 5; slice++)
0085         eeprom_update_client(client, slice);
0086 
0087     /* Hide Vaio private settings to regular users:
0088        - BIOS passwords: bytes 0x00 to 0x0f
0089        - UUID: bytes 0x10 to 0x1f
0090        - Serial number: 0xc0 to 0xdf */
0091     if (data->nature == VAIO && !capable(CAP_SYS_ADMIN)) {
0092         int i;
0093 
0094         for (i = 0; i < count; i++) {
0095             if ((off + i <= 0x1f) ||
0096                 (off + i >= 0xc0 && off + i <= 0xdf))
0097                 buf[i] = 0;
0098             else
0099                 buf[i] = data->data[off + i];
0100         }
0101     } else {
0102         memcpy(buf, &data->data[off], count);
0103     }
0104 
0105     return count;
0106 }
0107 
0108 static const struct bin_attribute eeprom_attr = {
0109     .attr = {
0110         .name = "eeprom",
0111         .mode = S_IRUGO,
0112     },
0113     .size = EEPROM_SIZE,
0114     .read = eeprom_read,
0115 };
0116 
0117 /* Return 0 if detection is successful, -ENODEV otherwise */
0118 static int eeprom_detect(struct i2c_client *client, struct i2c_board_info *info)
0119 {
0120     struct i2c_adapter *adapter = client->adapter;
0121 
0122     /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all
0123        addresses 0x50-0x57, but we only care about 0x50. So decline
0124        attaching to addresses >= 0x51 on DDC buses */
0125     if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x51)
0126         return -ENODEV;
0127 
0128     /* There are four ways we can read the EEPROM data:
0129        (1) I2C block reads (faster, but unsupported by most adapters)
0130        (2) Word reads (128% overhead)
0131        (3) Consecutive byte reads (88% overhead, unsafe)
0132        (4) Regular byte data reads (265% overhead)
0133        The third and fourth methods are not implemented by this driver
0134        because all known adapters support one of the first two. */
0135     if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)
0136      && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK))
0137         return -ENODEV;
0138 
0139     strlcpy(info->type, "eeprom", I2C_NAME_SIZE);
0140 
0141     return 0;
0142 }
0143 
0144 static int eeprom_probe(struct i2c_client *client,
0145             const struct i2c_device_id *id)
0146 {
0147     struct i2c_adapter *adapter = client->adapter;
0148     struct eeprom_data *data;
0149 
0150     data = devm_kzalloc(&client->dev, sizeof(struct eeprom_data),
0151                 GFP_KERNEL);
0152     if (!data)
0153         return -ENOMEM;
0154 
0155     memset(data->data, 0xff, EEPROM_SIZE);
0156     i2c_set_clientdata(client, data);
0157     mutex_init(&data->update_lock);
0158     data->nature = UNKNOWN;
0159 
0160     /* Detect the Vaio nature of EEPROMs.
0161        We use the "PCG-" or "VGN-" prefix as the signature. */
0162     if (client->addr == 0x57
0163      && i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
0164         char name[4];
0165 
0166         name[0] = i2c_smbus_read_byte_data(client, 0x80);
0167         name[1] = i2c_smbus_read_byte_data(client, 0x81);
0168         name[2] = i2c_smbus_read_byte_data(client, 0x82);
0169         name[3] = i2c_smbus_read_byte_data(client, 0x83);
0170 
0171         if (!memcmp(name, "PCG-", 4) || !memcmp(name, "VGN-", 4)) {
0172             dev_info(&client->dev, "Vaio EEPROM detected, "
0173                  "enabling privacy protection\n");
0174             data->nature = VAIO;
0175         }
0176     }
0177 
0178     /* Let the users know they are using deprecated driver */
0179     dev_notice(&client->dev,
0180            "eeprom driver is deprecated, please use at24 instead\n");
0181 
0182     /* create the sysfs eeprom file */
0183     return sysfs_create_bin_file(&client->dev.kobj, &eeprom_attr);
0184 }
0185 
0186 static int eeprom_remove(struct i2c_client *client)
0187 {
0188     sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr);
0189 
0190     return 0;
0191 }
0192 
0193 static const struct i2c_device_id eeprom_id[] = {
0194     { "eeprom", 0 },
0195     { }
0196 };
0197 
0198 static struct i2c_driver eeprom_driver = {
0199     .driver = {
0200         .name   = "eeprom",
0201     },
0202     .probe      = eeprom_probe,
0203     .remove     = eeprom_remove,
0204     .id_table   = eeprom_id,
0205 
0206     .class      = I2C_CLASS_DDC | I2C_CLASS_SPD,
0207     .detect     = eeprom_detect,
0208     .address_list   = normal_i2c,
0209 };
0210 
0211 module_i2c_driver(eeprom_driver);
0212 
0213 MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and "
0214         "Philip Edelbrock <phil@netroedge.com> and "
0215         "Greg Kroah-Hartman <greg@kroah.com>");
0216 MODULE_DESCRIPTION("I2C EEPROM driver");
0217 MODULE_LICENSE("GPL");