Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * i2c-nforce2-s4985.c - i2c-nforce2 extras for the Tyan S4985 motherboard
0004  *
0005  * Copyright (C) 2008 Jean Delvare <jdelvare@suse.de>
0006  */
0007 
0008 /*
0009  * We select the channels by sending commands to the Philips
0010  * PCA9556 chip at I2C address 0x18. The main adapter is used for
0011  * the non-multiplexed part of the bus, and 4 virtual adapters
0012  * are defined for the multiplexed addresses: 0x50-0x53 (memory
0013  * module EEPROM) located on channels 1-4. We define one virtual
0014  * adapter per CPU, which corresponds to one multiplexed channel:
0015  *   CPU0: virtual adapter 1, channel 1
0016  *   CPU1: virtual adapter 2, channel 2
0017  *   CPU2: virtual adapter 3, channel 3
0018  *   CPU3: virtual adapter 4, channel 4
0019  */
0020 
0021 #include <linux/module.h>
0022 #include <linux/kernel.h>
0023 #include <linux/slab.h>
0024 #include <linux/init.h>
0025 #include <linux/i2c.h>
0026 #include <linux/mutex.h>
0027 
0028 extern struct i2c_adapter *nforce2_smbus;
0029 
0030 static struct i2c_adapter *s4985_adapter;
0031 static struct i2c_algorithm *s4985_algo;
0032 
0033 /* Wrapper access functions for multiplexed SMBus */
0034 static DEFINE_MUTEX(nforce2_lock);
0035 
0036 static s32 nforce2_access_virt0(struct i2c_adapter *adap, u16 addr,
0037                 unsigned short flags, char read_write,
0038                 u8 command, int size,
0039                 union i2c_smbus_data *data)
0040 {
0041     int error;
0042 
0043     /* We exclude the multiplexed addresses */
0044     if ((addr & 0xfc) == 0x50 || (addr & 0xfc) == 0x30
0045      || addr == 0x18)
0046         return -ENXIO;
0047 
0048     mutex_lock(&nforce2_lock);
0049     error = nforce2_smbus->algo->smbus_xfer(adap, addr, flags, read_write,
0050                         command, size, data);
0051     mutex_unlock(&nforce2_lock);
0052 
0053     return error;
0054 }
0055 
0056 /* We remember the last used channels combination so as to only switch
0057    channels when it is really needed. This greatly reduces the SMBus
0058    overhead, but also assumes that nobody will be writing to the PCA9556
0059    in our back. */
0060 static u8 last_channels;
0061 
0062 static inline s32 nforce2_access_channel(struct i2c_adapter *adap, u16 addr,
0063                      unsigned short flags, char read_write,
0064                      u8 command, int size,
0065                      union i2c_smbus_data *data,
0066                      u8 channels)
0067 {
0068     int error;
0069 
0070     /* We exclude the non-multiplexed addresses */
0071     if ((addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30)
0072         return -ENXIO;
0073 
0074     mutex_lock(&nforce2_lock);
0075     if (last_channels != channels) {
0076         union i2c_smbus_data mplxdata;
0077         mplxdata.byte = channels;
0078 
0079         error = nforce2_smbus->algo->smbus_xfer(adap, 0x18, 0,
0080                             I2C_SMBUS_WRITE, 0x01,
0081                             I2C_SMBUS_BYTE_DATA,
0082                             &mplxdata);
0083         if (error)
0084             goto UNLOCK;
0085         last_channels = channels;
0086     }
0087     error = nforce2_smbus->algo->smbus_xfer(adap, addr, flags, read_write,
0088                         command, size, data);
0089 
0090 UNLOCK:
0091     mutex_unlock(&nforce2_lock);
0092     return error;
0093 }
0094 
0095 static s32 nforce2_access_virt1(struct i2c_adapter *adap, u16 addr,
0096                 unsigned short flags, char read_write,
0097                 u8 command, int size,
0098                 union i2c_smbus_data *data)
0099 {
0100     /* CPU0: channel 1 enabled */
0101     return nforce2_access_channel(adap, addr, flags, read_write, command,
0102                       size, data, 0x02);
0103 }
0104 
0105 static s32 nforce2_access_virt2(struct i2c_adapter *adap, u16 addr,
0106                 unsigned short flags, char read_write,
0107                 u8 command, int size,
0108                 union i2c_smbus_data *data)
0109 {
0110     /* CPU1: channel 2 enabled */
0111     return nforce2_access_channel(adap, addr, flags, read_write, command,
0112                       size, data, 0x04);
0113 }
0114 
0115 static s32 nforce2_access_virt3(struct i2c_adapter *adap, u16 addr,
0116                 unsigned short flags, char read_write,
0117                 u8 command, int size,
0118                 union i2c_smbus_data *data)
0119 {
0120     /* CPU2: channel 3 enabled */
0121     return nforce2_access_channel(adap, addr, flags, read_write, command,
0122                       size, data, 0x08);
0123 }
0124 
0125 static s32 nforce2_access_virt4(struct i2c_adapter *adap, u16 addr,
0126                 unsigned short flags, char read_write,
0127                 u8 command, int size,
0128                 union i2c_smbus_data *data)
0129 {
0130     /* CPU3: channel 4 enabled */
0131     return nforce2_access_channel(adap, addr, flags, read_write, command,
0132                       size, data, 0x10);
0133 }
0134 
0135 static int __init nforce2_s4985_init(void)
0136 {
0137     int i, error;
0138     union i2c_smbus_data ioconfig;
0139 
0140     if (!nforce2_smbus)
0141         return -ENODEV;
0142 
0143     /* Configure the PCA9556 multiplexer */
0144     ioconfig.byte = 0x00; /* All I/O to output mode */
0145     error = i2c_smbus_xfer(nforce2_smbus, 0x18, 0, I2C_SMBUS_WRITE, 0x03,
0146                    I2C_SMBUS_BYTE_DATA, &ioconfig);
0147     if (error) {
0148         dev_err(&nforce2_smbus->dev, "PCA9556 configuration failed\n");
0149         error = -EIO;
0150         goto ERROR0;
0151     }
0152 
0153     /* Unregister physical bus */
0154     i2c_del_adapter(nforce2_smbus);
0155 
0156     printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4985\n");
0157     /* Define the 5 virtual adapters and algorithms structures */
0158     s4985_adapter = kcalloc(5, sizeof(struct i2c_adapter), GFP_KERNEL);
0159     if (!s4985_adapter) {
0160         error = -ENOMEM;
0161         goto ERROR1;
0162     }
0163     s4985_algo = kcalloc(5, sizeof(struct i2c_algorithm), GFP_KERNEL);
0164     if (!s4985_algo) {
0165         error = -ENOMEM;
0166         goto ERROR2;
0167     }
0168 
0169     /* Fill in the new structures */
0170     s4985_algo[0] = *(nforce2_smbus->algo);
0171     s4985_algo[0].smbus_xfer = nforce2_access_virt0;
0172     s4985_adapter[0] = *nforce2_smbus;
0173     s4985_adapter[0].algo = s4985_algo;
0174     s4985_adapter[0].dev.parent = nforce2_smbus->dev.parent;
0175     for (i = 1; i < 5; i++) {
0176         s4985_algo[i] = *(nforce2_smbus->algo);
0177         s4985_adapter[i] = *nforce2_smbus;
0178         snprintf(s4985_adapter[i].name, sizeof(s4985_adapter[i].name),
0179              "SMBus nForce2 adapter (CPU%d)", i - 1);
0180         s4985_adapter[i].algo = s4985_algo + i;
0181         s4985_adapter[i].dev.parent = nforce2_smbus->dev.parent;
0182     }
0183     s4985_algo[1].smbus_xfer = nforce2_access_virt1;
0184     s4985_algo[2].smbus_xfer = nforce2_access_virt2;
0185     s4985_algo[3].smbus_xfer = nforce2_access_virt3;
0186     s4985_algo[4].smbus_xfer = nforce2_access_virt4;
0187 
0188     /* Register virtual adapters */
0189     for (i = 0; i < 5; i++) {
0190         error = i2c_add_adapter(s4985_adapter + i);
0191         if (error) {
0192             printk(KERN_ERR "i2c-nforce2-s4985: "
0193                    "Virtual adapter %d registration "
0194                    "failed, module not inserted\n", i);
0195             for (i--; i >= 0; i--)
0196                 i2c_del_adapter(s4985_adapter + i);
0197             goto ERROR3;
0198         }
0199     }
0200 
0201     return 0;
0202 
0203 ERROR3:
0204     kfree(s4985_algo);
0205     s4985_algo = NULL;
0206 ERROR2:
0207     kfree(s4985_adapter);
0208     s4985_adapter = NULL;
0209 ERROR1:
0210     /* Restore physical bus */
0211     i2c_add_adapter(nforce2_smbus);
0212 ERROR0:
0213     return error;
0214 }
0215 
0216 static void __exit nforce2_s4985_exit(void)
0217 {
0218     if (s4985_adapter) {
0219         int i;
0220 
0221         for (i = 0; i < 5; i++)
0222             i2c_del_adapter(s4985_adapter+i);
0223         kfree(s4985_adapter);
0224         s4985_adapter = NULL;
0225     }
0226     kfree(s4985_algo);
0227     s4985_algo = NULL;
0228 
0229     /* Restore physical bus */
0230     if (i2c_add_adapter(nforce2_smbus))
0231         printk(KERN_ERR "i2c-nforce2-s4985: "
0232                "Physical bus restoration failed\n");
0233 }
0234 
0235 MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");
0236 MODULE_DESCRIPTION("S4985 SMBus multiplexing");
0237 MODULE_LICENSE("GPL");
0238 
0239 module_init(nforce2_s4985_init);
0240 module_exit(nforce2_s4985_exit);