Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * max6875.c - driver for MAX6874/MAX6875
0004  *
0005  * Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com>
0006  *
0007  * Based on eeprom.c
0008  *
0009  * The MAX6875 has a bank of registers and two banks of EEPROM.
0010  * Address ranges are defined as follows:
0011  *  * 0x0000 - 0x0046 = configuration registers
0012  *  * 0x8000 - 0x8046 = configuration EEPROM
0013  *  * 0x8100 - 0x82FF = user EEPROM
0014  *
0015  * This driver makes the user EEPROM available for read.
0016  *
0017  * The registers & config EEPROM should be accessed via i2c-dev.
0018  *
0019  * The MAX6875 ignores the lowest address bit, so each chip responds to
0020  * two addresses - 0x50/0x51 and 0x52/0x53.
0021  *
0022  * Note that the MAX6875 uses i2c_smbus_write_byte_data() to set the read
0023  * address, so this driver is destructive if loaded for the wrong EEPROM chip.
0024  */
0025 
0026 #include <linux/kernel.h>
0027 #include <linux/module.h>
0028 #include <linux/slab.h>
0029 #include <linux/i2c.h>
0030 #include <linux/mutex.h>
0031 
0032 /* The MAX6875 can only read/write 16 bytes at a time */
0033 #define SLICE_SIZE          16
0034 #define SLICE_BITS          4
0035 
0036 /* USER EEPROM is at addresses 0x8100 - 0x82FF */
0037 #define USER_EEPROM_BASE        0x8100
0038 #define USER_EEPROM_SIZE        0x0200
0039 #define USER_EEPROM_SLICES      32
0040 
0041 /* MAX6875 commands */
0042 #define MAX6875_CMD_BLK_READ        0x84
0043 
0044 /* Each client has this additional data */
0045 struct max6875_data {
0046     struct i2c_client   *fake_client;
0047     struct mutex        update_lock;
0048 
0049     u32         valid;
0050     u8          data[USER_EEPROM_SIZE];
0051     unsigned long       last_updated[USER_EEPROM_SLICES];
0052 };
0053 
0054 static void max6875_update_slice(struct i2c_client *client, int slice)
0055 {
0056     struct max6875_data *data = i2c_get_clientdata(client);
0057     int i, j, addr;
0058     u8 *buf;
0059 
0060     if (slice >= USER_EEPROM_SLICES)
0061         return;
0062 
0063     mutex_lock(&data->update_lock);
0064 
0065     buf = &data->data[slice << SLICE_BITS];
0066 
0067     if (!(data->valid & (1 << slice)) ||
0068         time_after(jiffies, data->last_updated[slice])) {
0069 
0070         dev_dbg(&client->dev, "Starting update of slice %u\n", slice);
0071 
0072         data->valid &= ~(1 << slice);
0073 
0074         addr = USER_EEPROM_BASE + (slice << SLICE_BITS);
0075 
0076         /* select the eeprom address */
0077         if (i2c_smbus_write_byte_data(client, addr >> 8, addr & 0xFF)) {
0078             dev_err(&client->dev, "address set failed\n");
0079             goto exit_up;
0080         }
0081 
0082         if (i2c_check_functionality(client->adapter,
0083                         I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
0084             if (i2c_smbus_read_i2c_block_data(client,
0085                               MAX6875_CMD_BLK_READ,
0086                               SLICE_SIZE,
0087                               buf) != SLICE_SIZE) {
0088                 goto exit_up;
0089             }
0090         } else {
0091             for (i = 0; i < SLICE_SIZE; i++) {
0092                 j = i2c_smbus_read_byte(client);
0093                 if (j < 0) {
0094                     goto exit_up;
0095                 }
0096                 buf[i] = j;
0097             }
0098         }
0099         data->last_updated[slice] = jiffies;
0100         data->valid |= (1 << slice);
0101     }
0102 exit_up:
0103     mutex_unlock(&data->update_lock);
0104 }
0105 
0106 static ssize_t max6875_read(struct file *filp, struct kobject *kobj,
0107                 struct bin_attribute *bin_attr,
0108                 char *buf, loff_t off, size_t count)
0109 {
0110     struct i2c_client *client = kobj_to_i2c_client(kobj);
0111     struct max6875_data *data = i2c_get_clientdata(client);
0112     int slice, max_slice;
0113 
0114     /* refresh slices which contain requested bytes */
0115     max_slice = (off + count - 1) >> SLICE_BITS;
0116     for (slice = (off >> SLICE_BITS); slice <= max_slice; slice++)
0117         max6875_update_slice(client, slice);
0118 
0119     memcpy(buf, &data->data[off], count);
0120 
0121     return count;
0122 }
0123 
0124 static const struct bin_attribute user_eeprom_attr = {
0125     .attr = {
0126         .name = "eeprom",
0127         .mode = S_IRUGO,
0128     },
0129     .size = USER_EEPROM_SIZE,
0130     .read = max6875_read,
0131 };
0132 
0133 static int max6875_probe(struct i2c_client *client,
0134              const struct i2c_device_id *id)
0135 {
0136     struct i2c_adapter *adapter = client->adapter;
0137     struct max6875_data *data;
0138     int err;
0139 
0140     if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA
0141                      | I2C_FUNC_SMBUS_READ_BYTE))
0142         return -ENODEV;
0143 
0144     /* Only bind to even addresses */
0145     if (client->addr & 1)
0146         return -ENODEV;
0147 
0148     data = kzalloc(sizeof(struct max6875_data), GFP_KERNEL);
0149     if (!data)
0150         return -ENOMEM;
0151 
0152     /* A fake client is created on the odd address */
0153     data->fake_client = i2c_new_dummy_device(client->adapter, client->addr + 1);
0154     if (IS_ERR(data->fake_client)) {
0155         err = PTR_ERR(data->fake_client);
0156         goto exit_kfree;
0157     }
0158 
0159     /* Init real i2c_client */
0160     i2c_set_clientdata(client, data);
0161     mutex_init(&data->update_lock);
0162 
0163     err = sysfs_create_bin_file(&client->dev.kobj, &user_eeprom_attr);
0164     if (err)
0165         goto exit_remove_fake;
0166 
0167     return 0;
0168 
0169 exit_remove_fake:
0170     i2c_unregister_device(data->fake_client);
0171 exit_kfree:
0172     kfree(data);
0173     return err;
0174 }
0175 
0176 static int max6875_remove(struct i2c_client *client)
0177 {
0178     struct max6875_data *data = i2c_get_clientdata(client);
0179 
0180     i2c_unregister_device(data->fake_client);
0181 
0182     sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr);
0183     kfree(data);
0184 
0185     return 0;
0186 }
0187 
0188 static const struct i2c_device_id max6875_id[] = {
0189     { "max6875", 0 },
0190     { }
0191 };
0192 MODULE_DEVICE_TABLE(i2c, max6875_id);
0193 
0194 static struct i2c_driver max6875_driver = {
0195     .driver = {
0196         .name   = "max6875",
0197     },
0198     .probe      = max6875_probe,
0199     .remove     = max6875_remove,
0200     .id_table   = max6875_id,
0201 };
0202 
0203 module_i2c_driver(max6875_driver);
0204 
0205 MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
0206 MODULE_DESCRIPTION("MAX6875 driver");
0207 MODULE_LICENSE("GPL");