1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (C) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and
4*4882a593Smuzhiyun * Philip Edelbrock <phil@netroedge.com>
5*4882a593Smuzhiyun * Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
6*4882a593Smuzhiyun * Copyright (C) 2003 IBM Corp.
7*4882a593Smuzhiyun * Copyright (C) 2004 Jean Delvare <jdelvare@suse.de>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/kernel.h>
11*4882a593Smuzhiyun #include <linux/module.h>
12*4882a593Smuzhiyun #include <linux/device.h>
13*4882a593Smuzhiyun #include <linux/capability.h>
14*4882a593Smuzhiyun #include <linux/jiffies.h>
15*4882a593Smuzhiyun #include <linux/i2c.h>
16*4882a593Smuzhiyun #include <linux/mutex.h>
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun /* Addresses to scan */
19*4882a593Smuzhiyun static const unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54,
20*4882a593Smuzhiyun 0x55, 0x56, 0x57, I2C_CLIENT_END };
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun /* Size of EEPROM in bytes */
24*4882a593Smuzhiyun #define EEPROM_SIZE 256
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun /* possible types of eeprom devices */
27*4882a593Smuzhiyun enum eeprom_nature {
28*4882a593Smuzhiyun UNKNOWN,
29*4882a593Smuzhiyun VAIO,
30*4882a593Smuzhiyun };
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun /* Each client has this additional data */
33*4882a593Smuzhiyun struct eeprom_data {
34*4882a593Smuzhiyun struct mutex update_lock;
35*4882a593Smuzhiyun u8 valid; /* bitfield, bit!=0 if slice is valid */
36*4882a593Smuzhiyun unsigned long last_updated[8]; /* In jiffies, 8 slices */
37*4882a593Smuzhiyun u8 data[EEPROM_SIZE]; /* Register values */
38*4882a593Smuzhiyun enum eeprom_nature nature;
39*4882a593Smuzhiyun };
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun
eeprom_update_client(struct i2c_client * client,u8 slice)42*4882a593Smuzhiyun static void eeprom_update_client(struct i2c_client *client, u8 slice)
43*4882a593Smuzhiyun {
44*4882a593Smuzhiyun struct eeprom_data *data = i2c_get_clientdata(client);
45*4882a593Smuzhiyun int i;
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun mutex_lock(&data->update_lock);
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun if (!(data->valid & (1 << slice)) ||
50*4882a593Smuzhiyun time_after(jiffies, data->last_updated[slice] + 300 * HZ)) {
51*4882a593Smuzhiyun dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice);
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
54*4882a593Smuzhiyun for (i = slice << 5; i < (slice + 1) << 5; i += 32)
55*4882a593Smuzhiyun if (i2c_smbus_read_i2c_block_data(client, i,
56*4882a593Smuzhiyun 32, data->data + i)
57*4882a593Smuzhiyun != 32)
58*4882a593Smuzhiyun goto exit;
59*4882a593Smuzhiyun } else {
60*4882a593Smuzhiyun for (i = slice << 5; i < (slice + 1) << 5; i += 2) {
61*4882a593Smuzhiyun int word = i2c_smbus_read_word_data(client, i);
62*4882a593Smuzhiyun if (word < 0)
63*4882a593Smuzhiyun goto exit;
64*4882a593Smuzhiyun data->data[i] = word & 0xff;
65*4882a593Smuzhiyun data->data[i + 1] = word >> 8;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun data->last_updated[slice] = jiffies;
69*4882a593Smuzhiyun data->valid |= (1 << slice);
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun exit:
72*4882a593Smuzhiyun mutex_unlock(&data->update_lock);
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun
eeprom_read(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)75*4882a593Smuzhiyun static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
76*4882a593Smuzhiyun struct bin_attribute *bin_attr,
77*4882a593Smuzhiyun char *buf, loff_t off, size_t count)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun struct i2c_client *client = kobj_to_i2c_client(kobj);
80*4882a593Smuzhiyun struct eeprom_data *data = i2c_get_clientdata(client);
81*4882a593Smuzhiyun u8 slice;
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun /* Only refresh slices which contain requested bytes */
84*4882a593Smuzhiyun for (slice = off >> 5; slice <= (off + count - 1) >> 5; slice++)
85*4882a593Smuzhiyun eeprom_update_client(client, slice);
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun /* Hide Vaio private settings to regular users:
88*4882a593Smuzhiyun - BIOS passwords: bytes 0x00 to 0x0f
89*4882a593Smuzhiyun - UUID: bytes 0x10 to 0x1f
90*4882a593Smuzhiyun - Serial number: 0xc0 to 0xdf */
91*4882a593Smuzhiyun if (data->nature == VAIO && !capable(CAP_SYS_ADMIN)) {
92*4882a593Smuzhiyun int i;
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun for (i = 0; i < count; i++) {
95*4882a593Smuzhiyun if ((off + i <= 0x1f) ||
96*4882a593Smuzhiyun (off + i >= 0xc0 && off + i <= 0xdf))
97*4882a593Smuzhiyun buf[i] = 0;
98*4882a593Smuzhiyun else
99*4882a593Smuzhiyun buf[i] = data->data[off + i];
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun } else {
102*4882a593Smuzhiyun memcpy(buf, &data->data[off], count);
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun return count;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun static const struct bin_attribute eeprom_attr = {
109*4882a593Smuzhiyun .attr = {
110*4882a593Smuzhiyun .name = "eeprom",
111*4882a593Smuzhiyun .mode = S_IRUGO,
112*4882a593Smuzhiyun },
113*4882a593Smuzhiyun .size = EEPROM_SIZE,
114*4882a593Smuzhiyun .read = eeprom_read,
115*4882a593Smuzhiyun };
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun /* Return 0 if detection is successful, -ENODEV otherwise */
eeprom_detect(struct i2c_client * client,struct i2c_board_info * info)118*4882a593Smuzhiyun static int eeprom_detect(struct i2c_client *client, struct i2c_board_info *info)
119*4882a593Smuzhiyun {
120*4882a593Smuzhiyun struct i2c_adapter *adapter = client->adapter;
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all
123*4882a593Smuzhiyun addresses 0x50-0x57, but we only care about 0x50. So decline
124*4882a593Smuzhiyun attaching to addresses >= 0x51 on DDC buses */
125*4882a593Smuzhiyun if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x51)
126*4882a593Smuzhiyun return -ENODEV;
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun /* There are four ways we can read the EEPROM data:
129*4882a593Smuzhiyun (1) I2C block reads (faster, but unsupported by most adapters)
130*4882a593Smuzhiyun (2) Word reads (128% overhead)
131*4882a593Smuzhiyun (3) Consecutive byte reads (88% overhead, unsafe)
132*4882a593Smuzhiyun (4) Regular byte data reads (265% overhead)
133*4882a593Smuzhiyun The third and fourth methods are not implemented by this driver
134*4882a593Smuzhiyun because all known adapters support one of the first two. */
135*4882a593Smuzhiyun if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)
136*4882a593Smuzhiyun && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK))
137*4882a593Smuzhiyun return -ENODEV;
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun strlcpy(info->type, "eeprom", I2C_NAME_SIZE);
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun return 0;
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun
eeprom_probe(struct i2c_client * client,const struct i2c_device_id * id)144*4882a593Smuzhiyun static int eeprom_probe(struct i2c_client *client,
145*4882a593Smuzhiyun const struct i2c_device_id *id)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun struct i2c_adapter *adapter = client->adapter;
148*4882a593Smuzhiyun struct eeprom_data *data;
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun data = devm_kzalloc(&client->dev, sizeof(struct eeprom_data),
151*4882a593Smuzhiyun GFP_KERNEL);
152*4882a593Smuzhiyun if (!data)
153*4882a593Smuzhiyun return -ENOMEM;
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun memset(data->data, 0xff, EEPROM_SIZE);
156*4882a593Smuzhiyun i2c_set_clientdata(client, data);
157*4882a593Smuzhiyun mutex_init(&data->update_lock);
158*4882a593Smuzhiyun data->nature = UNKNOWN;
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun /* Detect the Vaio nature of EEPROMs.
161*4882a593Smuzhiyun We use the "PCG-" or "VGN-" prefix as the signature. */
162*4882a593Smuzhiyun if (client->addr == 0x57
163*4882a593Smuzhiyun && i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
164*4882a593Smuzhiyun char name[4];
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun name[0] = i2c_smbus_read_byte_data(client, 0x80);
167*4882a593Smuzhiyun name[1] = i2c_smbus_read_byte_data(client, 0x81);
168*4882a593Smuzhiyun name[2] = i2c_smbus_read_byte_data(client, 0x82);
169*4882a593Smuzhiyun name[3] = i2c_smbus_read_byte_data(client, 0x83);
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun if (!memcmp(name, "PCG-", 4) || !memcmp(name, "VGN-", 4)) {
172*4882a593Smuzhiyun dev_info(&client->dev, "Vaio EEPROM detected, "
173*4882a593Smuzhiyun "enabling privacy protection\n");
174*4882a593Smuzhiyun data->nature = VAIO;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun /* Let the users know they are using deprecated driver */
179*4882a593Smuzhiyun dev_notice(&client->dev,
180*4882a593Smuzhiyun "eeprom driver is deprecated, please use at24 instead\n");
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun /* create the sysfs eeprom file */
183*4882a593Smuzhiyun return sysfs_create_bin_file(&client->dev.kobj, &eeprom_attr);
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun
eeprom_remove(struct i2c_client * client)186*4882a593Smuzhiyun static int eeprom_remove(struct i2c_client *client)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr);
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun return 0;
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun static const struct i2c_device_id eeprom_id[] = {
194*4882a593Smuzhiyun { "eeprom", 0 },
195*4882a593Smuzhiyun { }
196*4882a593Smuzhiyun };
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun static struct i2c_driver eeprom_driver = {
199*4882a593Smuzhiyun .driver = {
200*4882a593Smuzhiyun .name = "eeprom",
201*4882a593Smuzhiyun },
202*4882a593Smuzhiyun .probe = eeprom_probe,
203*4882a593Smuzhiyun .remove = eeprom_remove,
204*4882a593Smuzhiyun .id_table = eeprom_id,
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun .class = I2C_CLASS_DDC | I2C_CLASS_SPD,
207*4882a593Smuzhiyun .detect = eeprom_detect,
208*4882a593Smuzhiyun .address_list = normal_i2c,
209*4882a593Smuzhiyun };
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun module_i2c_driver(eeprom_driver);
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and "
214*4882a593Smuzhiyun "Philip Edelbrock <phil@netroedge.com> and "
215*4882a593Smuzhiyun "Greg Kroah-Hartman <greg@kroah.com>");
216*4882a593Smuzhiyun MODULE_DESCRIPTION("I2C EEPROM driver");
217*4882a593Smuzhiyun MODULE_LICENSE("GPL");
218