1 /*
2  * i2c-nforce2-s4985.c - i2c-nforce2 extras for the Tyan S4985 motherboard
3  *
4  * Copyright (C) 2008 Jean Delvare <jdelvare@suse.de>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  */
16 
17 /*
18  * We select the channels by sending commands to the Philips
19  * PCA9556 chip at I2C address 0x18. The main adapter is used for
20  * the non-multiplexed part of the bus, and 4 virtual adapters
21  * are defined for the multiplexed addresses: 0x50-0x53 (memory
22  * module EEPROM) located on channels 1-4. We define one virtual
23  * adapter per CPU, which corresponds to one multiplexed channel:
24  *   CPU0: virtual adapter 1, channel 1
25  *   CPU1: virtual adapter 2, channel 2
26  *   CPU2: virtual adapter 3, channel 3
27  *   CPU3: virtual adapter 4, channel 4
28  */
29 
30 #include <linux/module.h>
31 #include <linux/kernel.h>
32 #include <linux/slab.h>
33 #include <linux/init.h>
34 #include <linux/i2c.h>
35 #include <linux/mutex.h>
36 
37 extern struct i2c_adapter *nforce2_smbus;
38 
39 static struct i2c_adapter *s4985_adapter;
40 static struct i2c_algorithm *s4985_algo;
41 
42 /* Wrapper access functions for multiplexed SMBus */
43 static DEFINE_MUTEX(nforce2_lock);
44 
nforce2_access_virt0(struct i2c_adapter * adap,u16 addr,unsigned short flags,char read_write,u8 command,int size,union i2c_smbus_data * data)45 static s32 nforce2_access_virt0(struct i2c_adapter *adap, u16 addr,
46 				unsigned short flags, char read_write,
47 				u8 command, int size,
48 				union i2c_smbus_data *data)
49 {
50 	int error;
51 
52 	/* We exclude the multiplexed addresses */
53 	if ((addr & 0xfc) == 0x50 || (addr & 0xfc) == 0x30
54 	 || addr == 0x18)
55 		return -ENXIO;
56 
57 	mutex_lock(&nforce2_lock);
58 	error = nforce2_smbus->algo->smbus_xfer(adap, addr, flags, read_write,
59 						command, size, data);
60 	mutex_unlock(&nforce2_lock);
61 
62 	return error;
63 }
64 
65 /* We remember the last used channels combination so as to only switch
66    channels when it is really needed. This greatly reduces the SMBus
67    overhead, but also assumes that nobody will be writing to the PCA9556
68    in our back. */
69 static u8 last_channels;
70 
nforce2_access_channel(struct i2c_adapter * adap,u16 addr,unsigned short flags,char read_write,u8 command,int size,union i2c_smbus_data * data,u8 channels)71 static inline s32 nforce2_access_channel(struct i2c_adapter *adap, u16 addr,
72 					 unsigned short flags, char read_write,
73 					 u8 command, int size,
74 					 union i2c_smbus_data *data,
75 					 u8 channels)
76 {
77 	int error;
78 
79 	/* We exclude the non-multiplexed addresses */
80 	if ((addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30)
81 		return -ENXIO;
82 
83 	mutex_lock(&nforce2_lock);
84 	if (last_channels != channels) {
85 		union i2c_smbus_data mplxdata;
86 		mplxdata.byte = channels;
87 
88 		error = nforce2_smbus->algo->smbus_xfer(adap, 0x18, 0,
89 							I2C_SMBUS_WRITE, 0x01,
90 							I2C_SMBUS_BYTE_DATA,
91 							&mplxdata);
92 		if (error)
93 			goto UNLOCK;
94 		last_channels = channels;
95 	}
96 	error = nforce2_smbus->algo->smbus_xfer(adap, addr, flags, read_write,
97 						command, size, data);
98 
99 UNLOCK:
100 	mutex_unlock(&nforce2_lock);
101 	return error;
102 }
103 
nforce2_access_virt1(struct i2c_adapter * adap,u16 addr,unsigned short flags,char read_write,u8 command,int size,union i2c_smbus_data * data)104 static s32 nforce2_access_virt1(struct i2c_adapter *adap, u16 addr,
105 				unsigned short flags, char read_write,
106 				u8 command, int size,
107 				union i2c_smbus_data *data)
108 {
109 	/* CPU0: channel 1 enabled */
110 	return nforce2_access_channel(adap, addr, flags, read_write, command,
111 				      size, data, 0x02);
112 }
113 
nforce2_access_virt2(struct i2c_adapter * adap,u16 addr,unsigned short flags,char read_write,u8 command,int size,union i2c_smbus_data * data)114 static s32 nforce2_access_virt2(struct i2c_adapter *adap, u16 addr,
115 				unsigned short flags, char read_write,
116 				u8 command, int size,
117 				union i2c_smbus_data *data)
118 {
119 	/* CPU1: channel 2 enabled */
120 	return nforce2_access_channel(adap, addr, flags, read_write, command,
121 				      size, data, 0x04);
122 }
123 
nforce2_access_virt3(struct i2c_adapter * adap,u16 addr,unsigned short flags,char read_write,u8 command,int size,union i2c_smbus_data * data)124 static s32 nforce2_access_virt3(struct i2c_adapter *adap, u16 addr,
125 				unsigned short flags, char read_write,
126 				u8 command, int size,
127 				union i2c_smbus_data *data)
128 {
129 	/* CPU2: channel 3 enabled */
130 	return nforce2_access_channel(adap, addr, flags, read_write, command,
131 				      size, data, 0x08);
132 }
133 
nforce2_access_virt4(struct i2c_adapter * adap,u16 addr,unsigned short flags,char read_write,u8 command,int size,union i2c_smbus_data * data)134 static s32 nforce2_access_virt4(struct i2c_adapter *adap, u16 addr,
135 				unsigned short flags, char read_write,
136 				u8 command, int size,
137 				union i2c_smbus_data *data)
138 {
139 	/* CPU3: channel 4 enabled */
140 	return nforce2_access_channel(adap, addr, flags, read_write, command,
141 				      size, data, 0x10);
142 }
143 
nforce2_s4985_init(void)144 static int __init nforce2_s4985_init(void)
145 {
146 	int i, error;
147 	union i2c_smbus_data ioconfig;
148 
149 	if (!nforce2_smbus)
150 		return -ENODEV;
151 
152 	/* Configure the PCA9556 multiplexer */
153 	ioconfig.byte = 0x00; /* All I/O to output mode */
154 	error = i2c_smbus_xfer(nforce2_smbus, 0x18, 0, I2C_SMBUS_WRITE, 0x03,
155 			       I2C_SMBUS_BYTE_DATA, &ioconfig);
156 	if (error) {
157 		dev_err(&nforce2_smbus->dev, "PCA9556 configuration failed\n");
158 		error = -EIO;
159 		goto ERROR0;
160 	}
161 
162 	/* Unregister physical bus */
163 	i2c_del_adapter(nforce2_smbus);
164 
165 	printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4985\n");
166 	/* Define the 5 virtual adapters and algorithms structures */
167 	s4985_adapter = kcalloc(5, sizeof(struct i2c_adapter), GFP_KERNEL);
168 	if (!s4985_adapter) {
169 		error = -ENOMEM;
170 		goto ERROR1;
171 	}
172 	s4985_algo = kcalloc(5, sizeof(struct i2c_algorithm), GFP_KERNEL);
173 	if (!s4985_algo) {
174 		error = -ENOMEM;
175 		goto ERROR2;
176 	}
177 
178 	/* Fill in the new structures */
179 	s4985_algo[0] = *(nforce2_smbus->algo);
180 	s4985_algo[0].smbus_xfer = nforce2_access_virt0;
181 	s4985_adapter[0] = *nforce2_smbus;
182 	s4985_adapter[0].algo = s4985_algo;
183 	s4985_adapter[0].dev.parent = nforce2_smbus->dev.parent;
184 	for (i = 1; i < 5; i++) {
185 		s4985_algo[i] = *(nforce2_smbus->algo);
186 		s4985_adapter[i] = *nforce2_smbus;
187 		snprintf(s4985_adapter[i].name, sizeof(s4985_adapter[i].name),
188 			 "SMBus nForce2 adapter (CPU%d)", i - 1);
189 		s4985_adapter[i].algo = s4985_algo + i;
190 		s4985_adapter[i].dev.parent = nforce2_smbus->dev.parent;
191 	}
192 	s4985_algo[1].smbus_xfer = nforce2_access_virt1;
193 	s4985_algo[2].smbus_xfer = nforce2_access_virt2;
194 	s4985_algo[3].smbus_xfer = nforce2_access_virt3;
195 	s4985_algo[4].smbus_xfer = nforce2_access_virt4;
196 
197 	/* Register virtual adapters */
198 	for (i = 0; i < 5; i++) {
199 		error = i2c_add_adapter(s4985_adapter + i);
200 		if (error) {
201 			printk(KERN_ERR "i2c-nforce2-s4985: "
202 			       "Virtual adapter %d registration "
203 			       "failed, module not inserted\n", i);
204 			for (i--; i >= 0; i--)
205 				i2c_del_adapter(s4985_adapter + i);
206 			goto ERROR3;
207 		}
208 	}
209 
210 	return 0;
211 
212 ERROR3:
213 	kfree(s4985_algo);
214 	s4985_algo = NULL;
215 ERROR2:
216 	kfree(s4985_adapter);
217 	s4985_adapter = NULL;
218 ERROR1:
219 	/* Restore physical bus */
220 	i2c_add_adapter(nforce2_smbus);
221 ERROR0:
222 	return error;
223 }
224 
nforce2_s4985_exit(void)225 static void __exit nforce2_s4985_exit(void)
226 {
227 	if (s4985_adapter) {
228 		int i;
229 
230 		for (i = 0; i < 5; i++)
231 			i2c_del_adapter(s4985_adapter+i);
232 		kfree(s4985_adapter);
233 		s4985_adapter = NULL;
234 	}
235 	kfree(s4985_algo);
236 	s4985_algo = NULL;
237 
238 	/* Restore physical bus */
239 	if (i2c_add_adapter(nforce2_smbus))
240 		printk(KERN_ERR "i2c-nforce2-s4985: "
241 		       "Physical bus restoration failed\n");
242 }
243 
244 MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");
245 MODULE_DESCRIPTION("S4985 SMBus multiplexing");
246 MODULE_LICENSE("GPL");
247 
248 module_init(nforce2_s4985_init);
249 module_exit(nforce2_s4985_exit);
250