Commit | Line | Data |
---|---|---|
7dc7967f | 1 | // SPDX-License-Identifier: GPL-2.0+ |
11011c03 GN |
2 | /* |
3 | * KPC2000 i2c driver | |
4 | * | |
5 | * Adapted i2c-i801.c for use with Kadoka hardware. | |
6 | * | |
7 | * Copyright (C) 1998 - 2002 | |
8 | * Frodo Looijaard <frodol@dds.nl>, | |
9 | * Philip Edelbrock <phil@netroedge.com>, | |
10 | * Mark D. Studebaker <mdsxyz123@yahoo.com> | |
11 | * Copyright (C) 2007 - 2012 | |
12 | * Jean Delvare <khali@linux-fr.org> | |
13 | * Copyright (C) 2010 Intel Corporation | |
14 | * David Woodhouse <dwmw2@infradead.org> | |
15 | * Copyright (C) 2014-2018 Daktronics | |
16 | * Matt Sickler <matt.sickler@daktronics.com>, | |
17 | * Jordon Hofer <jordon.hofer@daktronics.com> | |
18 | */ | |
7dc7967f GKH |
19 | #include <linux/init.h> |
20 | #include <linux/module.h> | |
21 | #include <linux/types.h> | |
32806b33 | 22 | #include <linux/io.h> |
91b6cb72 | 23 | #include <linux/io-64-nonatomic-lo-hi.h> |
7dc7967f GKH |
24 | #include <linux/export.h> |
25 | #include <linux/slab.h> | |
26 | #include <linux/platform_device.h> | |
27 | #include <linux/fs.h> | |
7dc7967f GKH |
28 | #include <linux/delay.h> |
29 | #include <linux/i2c.h> | |
8cac7b35 | 30 | #include "kpc.h" |
7dc7967f GKH |
31 | |
32 | MODULE_LICENSE("GPL"); | |
33 | MODULE_AUTHOR("Matt.Sickler@Daktronics.com"); | |
7dc7967f | 34 | |
b5909c6d | 35 | struct kpc_i2c { |
8459b544 GN |
36 | unsigned long smba; |
37 | struct i2c_adapter adapter; | |
8459b544 | 38 | unsigned int features; |
7dc7967f GKH |
39 | }; |
40 | ||
41 | /***************************** | |
42 | *** Part 1 - i2c Handlers *** | |
43 | *****************************/ | |
44 | ||
45 | #define REG_SIZE 8 | |
46 | ||
47 | /* I801 SMBus address offsets */ | |
48 | #define SMBHSTSTS(p) ((0 * REG_SIZE) + (p)->smba) | |
49 | #define SMBHSTCNT(p) ((2 * REG_SIZE) + (p)->smba) | |
50 | #define SMBHSTCMD(p) ((3 * REG_SIZE) + (p)->smba) | |
51 | #define SMBHSTADD(p) ((4 * REG_SIZE) + (p)->smba) | |
52 | #define SMBHSTDAT0(p) ((5 * REG_SIZE) + (p)->smba) | |
53 | #define SMBHSTDAT1(p) ((6 * REG_SIZE) + (p)->smba) | |
54 | #define SMBBLKDAT(p) ((7 * REG_SIZE) + (p)->smba) | |
55 | #define SMBPEC(p) ((8 * REG_SIZE) + (p)->smba) /* ICH3 and later */ | |
56 | #define SMBAUXSTS(p) ((12 * REG_SIZE) + (p)->smba) /* ICH4 and later */ | |
57 | #define SMBAUXCTL(p) ((13 * REG_SIZE) + (p)->smba) /* ICH4 and later */ | |
58 | ||
59 | /* PCI Address Constants */ | |
60 | #define SMBBAR 4 | |
61 | #define SMBHSTCFG 0x040 | |
62 | ||
63 | /* Host configuration bits for SMBHSTCFG */ | |
64 | #define SMBHSTCFG_HST_EN 1 | |
65 | #define SMBHSTCFG_SMB_SMI_EN 2 | |
66 | #define SMBHSTCFG_I2C_EN 4 | |
67 | ||
68 | /* Auxiliary control register bits, ICH4+ only */ | |
69 | #define SMBAUXCTL_CRC 1 | |
70 | #define SMBAUXCTL_E32B 2 | |
71 | ||
72 | /* kill bit for SMBHSTCNT */ | |
73 | #define SMBHSTCNT_KILL 2 | |
74 | ||
75 | /* Other settings */ | |
76 | #define MAX_RETRIES 400 | |
77 | #define ENABLE_INT9 0 /* set to 0x01 to enable - untested */ | |
78 | ||
79 | /* I801 command constants */ | |
80 | #define I801_QUICK 0x00 | |
81 | #define I801_BYTE 0x04 | |
82 | #define I801_BYTE_DATA 0x08 | |
83 | #define I801_WORD_DATA 0x0C | |
84 | #define I801_PROC_CALL 0x10 /* unimplemented */ | |
85 | #define I801_BLOCK_DATA 0x14 | |
86 | #define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */ | |
87 | #define I801_BLOCK_LAST 0x34 | |
88 | #define I801_I2C_BLOCK_LAST 0x38 /* ICH5 and later */ | |
89 | #define I801_START 0x40 | |
90 | #define I801_PEC_EN 0x80 /* ICH3 and later */ | |
91 | ||
92 | /* I801 Hosts Status register bits */ | |
93 | #define SMBHSTSTS_BYTE_DONE 0x80 | |
94 | #define SMBHSTSTS_INUSE_STS 0x40 | |
95 | #define SMBHSTSTS_SMBALERT_STS 0x20 | |
96 | #define SMBHSTSTS_FAILED 0x10 | |
97 | #define SMBHSTSTS_BUS_ERR 0x08 | |
98 | #define SMBHSTSTS_DEV_ERR 0x04 | |
99 | #define SMBHSTSTS_INTR 0x02 | |
100 | #define SMBHSTSTS_HOST_BUSY 0x01 | |
101 | ||
9535e71e JS |
102 | #define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_FAILED | \ |
103 | SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | SMBHSTSTS_INTR) | |
7dc7967f GKH |
104 | |
105 | /* Older devices have their ID defined in <linux/pci_ids.h> */ | |
106 | #define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22 | |
107 | #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22 | |
108 | /* Patsburg also has three 'Integrated Device Function' SMBus controllers */ | |
109 | #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0 0x1d70 | |
110 | #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1 0x1d71 | |
111 | #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2 0x1d72 | |
112 | #define PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS 0x1e22 | |
113 | #define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330 | |
114 | #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30 | |
115 | #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22 | |
116 | #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS 0x9c22 | |
117 | ||
c5164e56 GN |
118 | #define FEATURE_SMBUS_PEC BIT(0) |
119 | #define FEATURE_BLOCK_BUFFER BIT(1) | |
120 | #define FEATURE_BLOCK_PROC BIT(2) | |
121 | #define FEATURE_I2C_BLOCK_READ BIT(3) | |
7dc7967f | 122 | /* Not really a feature, but it's convenient to handle it as such */ |
c5164e56 | 123 | #define FEATURE_IDF BIT(15) |
7dc7967f | 124 | |
7dc7967f GKH |
125 | // FIXME! |
126 | #undef inb_p | |
1327d35a | 127 | #define inb_p(a) readq((void __iomem *)a) |
7dc7967f | 128 | #undef outb_p |
1327d35a | 129 | #define outb_p(d, a) writeq(d, (void __iomem *)a) |
7dc7967f GKH |
130 | |
131 | /* Make sure the SMBus host is ready to start transmitting. | |
7ac3e13a GN |
132 | * Return 0 if it is, -EBUSY if it is not. |
133 | */ | |
b5909c6d | 134 | static int i801_check_pre(struct kpc_i2c *priv) |
7dc7967f | 135 | { |
8459b544 GN |
136 | int status; |
137 | ||
8459b544 GN |
138 | status = inb_p(SMBHSTSTS(priv)); |
139 | if (status & SMBHSTSTS_HOST_BUSY) { | |
9535e71e JS |
140 | dev_err(&priv->adapter.dev, |
141 | "SMBus is busy, can't use it! (status=%x)\n", status); | |
8459b544 GN |
142 | return -EBUSY; |
143 | } | |
144 | ||
145 | status &= STATUS_FLAGS; | |
146 | if (status) { | |
8459b544 GN |
147 | outb_p(status, SMBHSTSTS(priv)); |
148 | status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS; | |
149 | if (status) { | |
9535e71e JS |
150 | dev_err(&priv->adapter.dev, |
151 | "Failed clearing status flags (%02x)\n", status); | |
8459b544 GN |
152 | return -EBUSY; |
153 | } | |
154 | } | |
155 | return 0; | |
7dc7967f GKH |
156 | } |
157 | ||
158 | /* Convert the status register to an error code, and clear it. */ | |
b5909c6d | 159 | static int i801_check_post(struct kpc_i2c *priv, int status, int timeout) |
7dc7967f | 160 | { |
8459b544 GN |
161 | int result = 0; |
162 | ||
8459b544 GN |
163 | /* If the SMBus is still busy, we give up */ |
164 | if (timeout) { | |
165 | dev_err(&priv->adapter.dev, "Transaction timeout\n"); | |
166 | /* try to stop the current command */ | |
9535e71e JS |
167 | dev_dbg(&priv->adapter.dev, |
168 | "Terminating the current operation\n"); | |
169 | outb_p(inb_p(SMBHSTCNT(priv)) | SMBHSTCNT_KILL, | |
170 | SMBHSTCNT(priv)); | |
8459b544 | 171 | usleep_range(1000, 2000); |
9535e71e JS |
172 | outb_p(inb_p(SMBHSTCNT(priv)) & (~SMBHSTCNT_KILL), |
173 | SMBHSTCNT(priv)); | |
8459b544 GN |
174 | |
175 | /* Check if it worked */ | |
176 | status = inb_p(SMBHSTSTS(priv)); | |
9535e71e JS |
177 | if ((status & SMBHSTSTS_HOST_BUSY) || |
178 | !(status & SMBHSTSTS_FAILED)) | |
179 | dev_err(&priv->adapter.dev, | |
180 | "Failed terminating the transaction\n"); | |
8459b544 GN |
181 | outb_p(STATUS_FLAGS, SMBHSTSTS(priv)); |
182 | return -ETIMEDOUT; | |
183 | } | |
184 | ||
185 | if (status & SMBHSTSTS_FAILED) { | |
186 | result = -EIO; | |
187 | dev_err(&priv->adapter.dev, "Transaction failed\n"); | |
188 | } | |
189 | if (status & SMBHSTSTS_DEV_ERR) { | |
190 | result = -ENXIO; | |
191 | dev_dbg(&priv->adapter.dev, "No response\n"); | |
192 | } | |
193 | if (status & SMBHSTSTS_BUS_ERR) { | |
194 | result = -EAGAIN; | |
195 | dev_dbg(&priv->adapter.dev, "Lost arbitration\n"); | |
196 | } | |
197 | ||
198 | if (result) { | |
199 | /* Clear error flags */ | |
200 | outb_p(status & STATUS_FLAGS, SMBHSTSTS(priv)); | |
201 | status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS; | |
953bb9e5 | 202 | if (status) |
47b6079e NK |
203 | dev_warn(&priv->adapter.dev, |
204 | "Failed clearing status flags at end of transaction (%02x)\n", | |
205 | status); | |
8459b544 GN |
206 | } |
207 | ||
208 | return result; | |
7dc7967f GKH |
209 | } |
210 | ||
b5909c6d | 211 | static int i801_transaction(struct kpc_i2c *priv, int xact) |
7dc7967f | 212 | { |
8459b544 GN |
213 | int status; |
214 | int result; | |
215 | int timeout = 0; | |
216 | ||
8459b544 | 217 | result = i801_check_pre(priv); |
953bb9e5 | 218 | if (result < 0) |
8459b544 | 219 | return result; |
8459b544 | 220 | /* the current contents of SMBHSTCNT can be overwritten, since PEC, |
7ac3e13a GN |
221 | * INTREN, SMBSCMD are passed in xact |
222 | */ | |
8459b544 GN |
223 | outb_p(xact | I801_START, SMBHSTCNT(priv)); |
224 | ||
225 | /* We will always wait for a fraction of a second! */ | |
226 | do { | |
227 | usleep_range(250, 500); | |
228 | status = inb_p(SMBHSTSTS(priv)); | |
229 | } while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_RETRIES)); | |
230 | ||
231 | result = i801_check_post(priv, status, timeout > MAX_RETRIES); | |
953bb9e5 | 232 | if (result < 0) |
8459b544 | 233 | return result; |
8459b544 GN |
234 | |
235 | outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv)); | |
236 | return 0; | |
7dc7967f GKH |
237 | } |
238 | ||
239 | /* wait for INTR bit as advised by Intel */ | |
b5909c6d | 240 | static void i801_wait_hwpec(struct kpc_i2c *priv) |
7dc7967f | 241 | { |
8459b544 GN |
242 | int timeout = 0; |
243 | int status; | |
244 | ||
8459b544 GN |
245 | do { |
246 | usleep_range(250, 500); | |
247 | status = inb_p(SMBHSTSTS(priv)); | |
248 | } while ((!(status & SMBHSTSTS_INTR)) && (timeout++ < MAX_RETRIES)); | |
249 | ||
953bb9e5 | 250 | if (timeout > MAX_RETRIES) |
8459b544 | 251 | dev_dbg(&priv->adapter.dev, "PEC Timeout!\n"); |
8459b544 GN |
252 | |
253 | outb_p(status, SMBHSTSTS(priv)); | |
7dc7967f GKH |
254 | } |
255 | ||
b5909c6d | 256 | static int i801_block_transaction_by_block(struct kpc_i2c *priv, |
9535e71e JS |
257 | union i2c_smbus_data *data, |
258 | char read_write, int hwpec) | |
7dc7967f | 259 | { |
8459b544 GN |
260 | int i, len; |
261 | int status; | |
262 | ||
8459b544 GN |
263 | inb_p(SMBHSTCNT(priv)); /* reset the data buffer index */ |
264 | ||
265 | /* Use 32-byte buffer to process this transaction */ | |
266 | if (read_write == I2C_SMBUS_WRITE) { | |
267 | len = data->block[0]; | |
268 | outb_p(len, SMBHSTDAT0(priv)); | |
953bb9e5 | 269 | for (i = 0; i < len; i++) |
03c1feff | 270 | outb_p(data->block[i + 1], SMBBLKDAT(priv)); |
8459b544 GN |
271 | } |
272 | ||
9535e71e | 273 | status = i801_transaction(priv, |
bba80c84 | 274 | I801_BLOCK_DATA | ENABLE_INT9 | I801_PEC_EN * hwpec); |
953bb9e5 | 275 | if (status) |
8459b544 | 276 | return status; |
8459b544 GN |
277 | |
278 | if (read_write == I2C_SMBUS_READ) { | |
279 | len = inb_p(SMBHSTDAT0(priv)); | |
953bb9e5 | 280 | if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) |
8459b544 | 281 | return -EPROTO; |
8459b544 GN |
282 | |
283 | data->block[0] = len; | |
953bb9e5 | 284 | for (i = 0; i < len; i++) |
8459b544 | 285 | data->block[i + 1] = inb_p(SMBBLKDAT(priv)); |
8459b544 GN |
286 | } |
287 | return 0; | |
7dc7967f GKH |
288 | } |
289 | ||
b5909c6d | 290 | static int i801_block_transaction_byte_by_byte(struct kpc_i2c *priv, |
9535e71e JS |
291 | union i2c_smbus_data *data, |
292 | char read_write, int command, | |
293 | int hwpec) | |
7dc7967f | 294 | { |
8459b544 GN |
295 | int i, len; |
296 | int smbcmd; | |
297 | int status; | |
298 | int result; | |
299 | int timeout; | |
300 | ||
8459b544 | 301 | result = i801_check_pre(priv); |
953bb9e5 | 302 | if (result < 0) |
8459b544 | 303 | return result; |
8459b544 GN |
304 | |
305 | len = data->block[0]; | |
306 | ||
307 | if (read_write == I2C_SMBUS_WRITE) { | |
308 | outb_p(len, SMBHSTDAT0(priv)); | |
309 | outb_p(data->block[1], SMBBLKDAT(priv)); | |
310 | } | |
311 | ||
312 | for (i = 1; i <= len; i++) { | |
313 | if (i == len && read_write == I2C_SMBUS_READ) { | |
953bb9e5 | 314 | if (command == I2C_SMBUS_I2C_BLOCK_DATA) |
8459b544 | 315 | smbcmd = I801_I2C_BLOCK_LAST; |
953bb9e5 | 316 | else |
8459b544 | 317 | smbcmd = I801_BLOCK_LAST; |
8459b544 | 318 | } else { |
9535e71e JS |
319 | if (command == I2C_SMBUS_I2C_BLOCK_DATA && |
320 | read_write == I2C_SMBUS_READ) | |
8459b544 | 321 | smbcmd = I801_I2C_BLOCK_DATA; |
953bb9e5 | 322 | else |
8459b544 | 323 | smbcmd = I801_BLOCK_DATA; |
8459b544 GN |
324 | } |
325 | outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT(priv)); | |
326 | ||
953bb9e5 | 327 | if (i == 1) |
9535e71e JS |
328 | outb_p(inb(SMBHSTCNT(priv)) | I801_START, |
329 | SMBHSTCNT(priv)); | |
8459b544 GN |
330 | /* We will always wait for a fraction of a second! */ |
331 | timeout = 0; | |
332 | do { | |
333 | usleep_range(250, 500); | |
334 | status = inb_p(SMBHSTSTS(priv)); | |
9535e71e JS |
335 | } while (!(status & SMBHSTSTS_BYTE_DONE) && |
336 | (timeout++ < MAX_RETRIES)); | |
8459b544 GN |
337 | |
338 | result = i801_check_post(priv, status, timeout > MAX_RETRIES); | |
953bb9e5 | 339 | if (result < 0) |
8459b544 | 340 | return result; |
9535e71e JS |
341 | if (i == 1 && read_write == I2C_SMBUS_READ && |
342 | command != I2C_SMBUS_I2C_BLOCK_DATA) { | |
8459b544 GN |
343 | len = inb_p(SMBHSTDAT0(priv)); |
344 | if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) { | |
9535e71e JS |
345 | dev_err(&priv->adapter.dev, |
346 | "Illegal SMBus block read size %d\n", | |
347 | len); | |
8459b544 | 348 | /* Recover */ |
9535e71e JS |
349 | while (inb_p(SMBHSTSTS(priv)) & |
350 | SMBHSTSTS_HOST_BUSY) | |
351 | outb_p(SMBHSTSTS_BYTE_DONE, | |
352 | SMBHSTSTS(priv)); | |
353 | outb_p(SMBHSTSTS_INTR, | |
354 | SMBHSTSTS(priv)); | |
8459b544 GN |
355 | return -EPROTO; |
356 | } | |
357 | data->block[0] = len; | |
358 | } | |
359 | ||
360 | /* Retrieve/store value in SMBBLKDAT */ | |
953bb9e5 | 361 | if (read_write == I2C_SMBUS_READ) |
8459b544 | 362 | data->block[i] = inb_p(SMBBLKDAT(priv)); |
03c1feff SS |
363 | if (read_write == I2C_SMBUS_WRITE && i + 1 <= len) |
364 | outb_p(data->block[i + 1], SMBBLKDAT(priv)); | |
8459b544 GN |
365 | /* signals SMBBLKDAT ready */ |
366 | outb_p(SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR, SMBHSTSTS(priv)); | |
367 | } | |
368 | ||
369 | return 0; | |
7dc7967f GKH |
370 | } |
371 | ||
b5909c6d | 372 | static int i801_set_block_buffer_mode(struct kpc_i2c *priv) |
7dc7967f | 373 | { |
8459b544 | 374 | outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_E32B, SMBAUXCTL(priv)); |
953bb9e5 | 375 | if ((inb_p(SMBAUXCTL(priv)) & SMBAUXCTL_E32B) == 0) |
8459b544 | 376 | return -EIO; |
8459b544 | 377 | return 0; |
7dc7967f GKH |
378 | } |
379 | ||
380 | /* Block transaction function */ | |
b5909c6d | 381 | static int i801_block_transaction(struct kpc_i2c *priv, |
9535e71e JS |
382 | union i2c_smbus_data *data, char read_write, |
383 | int command, int hwpec) | |
7dc7967f | 384 | { |
8459b544 GN |
385 | int result = 0; |
386 | //unsigned char hostc; | |
387 | ||
8459b544 GN |
388 | if (command == I2C_SMBUS_I2C_BLOCK_DATA) { |
389 | if (read_write == I2C_SMBUS_WRITE) { | |
390 | /* set I2C_EN bit in configuration register */ | |
391 | //TODO: Figure out the right thing to do here... | |
392 | //pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &hostc); | |
393 | //pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc | SMBHSTCFG_I2C_EN); | |
394 | } else if (!(priv->features & FEATURE_I2C_BLOCK_READ)) { | |
9535e71e JS |
395 | dev_err(&priv->adapter.dev, |
396 | "I2C block read is unsupported!\n"); | |
8459b544 GN |
397 | return -EOPNOTSUPP; |
398 | } | |
399 | } | |
400 | ||
9535e71e JS |
401 | if (read_write == I2C_SMBUS_WRITE || |
402 | command == I2C_SMBUS_I2C_BLOCK_DATA) { | |
953bb9e5 | 403 | if (data->block[0] < 1) |
8459b544 | 404 | data->block[0] = 1; |
953bb9e5 | 405 | if (data->block[0] > I2C_SMBUS_BLOCK_MAX) |
8459b544 | 406 | data->block[0] = I2C_SMBUS_BLOCK_MAX; |
8459b544 GN |
407 | } else { |
408 | data->block[0] = 32; /* max for SMBus block reads */ | |
409 | } | |
410 | ||
411 | /* Experience has shown that the block buffer can only be used for | |
7ac3e13a GN |
412 | * SMBus (not I2C) block transactions, even though the datasheet |
413 | * doesn't mention this limitation. | |
414 | */ | |
9535e71e JS |
415 | if ((priv->features & FEATURE_BLOCK_BUFFER) && |
416 | command != I2C_SMBUS_I2C_BLOCK_DATA && | |
417 | i801_set_block_buffer_mode(priv) == 0) { | |
418 | result = i801_block_transaction_by_block(priv, data, | |
419 | read_write, hwpec); | |
420 | } else { | |
421 | result = i801_block_transaction_byte_by_byte(priv, data, | |
422 | read_write, | |
423 | command, hwpec); | |
424 | } | |
425 | ||
953bb9e5 | 426 | if (result == 0 && hwpec) |
8459b544 | 427 | i801_wait_hwpec(priv); |
9535e71e JS |
428 | if (command == I2C_SMBUS_I2C_BLOCK_DATA && |
429 | read_write == I2C_SMBUS_WRITE) { | |
8459b544 GN |
430 | /* restore saved configuration register value */ |
431 | //TODO: Figure out the right thing to do here... | |
432 | //pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc); | |
433 | } | |
434 | return result; | |
7dc7967f GKH |
435 | } |
436 | ||
437 | /* Return negative errno on error. */ | |
9535e71e JS |
438 | static s32 i801_access(struct i2c_adapter *adap, u16 addr, |
439 | unsigned short flags, char read_write, u8 command, | |
440 | int size, union i2c_smbus_data *data) | |
7dc7967f | 441 | { |
8459b544 GN |
442 | int hwpec; |
443 | int block = 0; | |
444 | int ret, xact = 0; | |
b5909c6d | 445 | struct kpc_i2c *priv = i2c_get_adapdata(adap); |
8459b544 | 446 | |
9535e71e JS |
447 | hwpec = (priv->features & FEATURE_SMBUS_PEC) && |
448 | (flags & I2C_CLIENT_PEC) && | |
449 | size != I2C_SMBUS_QUICK && size != I2C_SMBUS_I2C_BLOCK_DATA; | |
8459b544 GN |
450 | |
451 | switch (size) { | |
452 | case I2C_SMBUS_QUICK: | |
453 | dev_dbg(&priv->adapter.dev, " [acc] SMBUS_QUICK\n"); | |
9535e71e JS |
454 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), |
455 | SMBHSTADD(priv)); | |
456 | ||
8459b544 GN |
457 | xact = I801_QUICK; |
458 | break; | |
459 | case I2C_SMBUS_BYTE: | |
460 | dev_dbg(&priv->adapter.dev, " [acc] SMBUS_BYTE\n"); | |
461 | ||
9535e71e JS |
462 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), |
463 | SMBHSTADD(priv)); | |
953bb9e5 | 464 | if (read_write == I2C_SMBUS_WRITE) |
8459b544 | 465 | outb_p(command, SMBHSTCMD(priv)); |
8459b544 GN |
466 | xact = I801_BYTE; |
467 | break; | |
468 | case I2C_SMBUS_BYTE_DATA: | |
469 | dev_dbg(&priv->adapter.dev, " [acc] SMBUS_BYTE_DATA\n"); | |
9535e71e JS |
470 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), |
471 | SMBHSTADD(priv)); | |
472 | ||
8459b544 | 473 | outb_p(command, SMBHSTCMD(priv)); |
953bb9e5 | 474 | if (read_write == I2C_SMBUS_WRITE) |
8459b544 | 475 | outb_p(data->byte, SMBHSTDAT0(priv)); |
8459b544 GN |
476 | xact = I801_BYTE_DATA; |
477 | break; | |
478 | case I2C_SMBUS_WORD_DATA: | |
479 | dev_dbg(&priv->adapter.dev, " [acc] SMBUS_WORD_DATA\n"); | |
9535e71e JS |
480 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), |
481 | SMBHSTADD(priv)); | |
482 | ||
8459b544 GN |
483 | outb_p(command, SMBHSTCMD(priv)); |
484 | if (read_write == I2C_SMBUS_WRITE) { | |
485 | outb_p(data->word & 0xff, SMBHSTDAT0(priv)); | |
486 | outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1(priv)); | |
487 | } | |
488 | xact = I801_WORD_DATA; | |
489 | break; | |
490 | case I2C_SMBUS_BLOCK_DATA: | |
491 | dev_dbg(&priv->adapter.dev, " [acc] SMBUS_BLOCK_DATA\n"); | |
9535e71e JS |
492 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), |
493 | SMBHSTADD(priv)); | |
494 | ||
8459b544 GN |
495 | outb_p(command, SMBHSTCMD(priv)); |
496 | block = 1; | |
497 | break; | |
498 | case I2C_SMBUS_I2C_BLOCK_DATA: | |
499 | dev_dbg(&priv->adapter.dev, " [acc] SMBUS_I2C_BLOCK_DATA\n"); | |
500 | /* NB: page 240 of ICH5 datasheet shows that the R/#W | |
7ac3e13a GN |
501 | * bit should be cleared here, even when reading |
502 | */ | |
8459b544 GN |
503 | outb_p((addr & 0x7f) << 1, SMBHSTADD(priv)); |
504 | if (read_write == I2C_SMBUS_READ) { | |
505 | /* NB: page 240 of ICH5 datasheet also shows | |
7ac3e13a GN |
506 | * that DATA1 is the cmd field when reading |
507 | */ | |
8459b544 GN |
508 | outb_p(command, SMBHSTDAT1(priv)); |
509 | } else { | |
510 | outb_p(command, SMBHSTCMD(priv)); | |
511 | } | |
512 | block = 1; | |
513 | break; | |
514 | default: | |
9535e71e JS |
515 | dev_dbg(&priv->adapter.dev, |
516 | " [acc] Unsupported transaction %d\n", size); | |
8459b544 GN |
517 | return -EOPNOTSUPP; |
518 | } | |
519 | ||
520 | if (hwpec) { /* enable/disable hardware PEC */ | |
521 | dev_dbg(&priv->adapter.dev, " [acc] hwpec: yes\n"); | |
522 | outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_CRC, SMBAUXCTL(priv)); | |
523 | } else { | |
524 | dev_dbg(&priv->adapter.dev, " [acc] hwpec: no\n"); | |
9535e71e JS |
525 | outb_p(inb_p(SMBAUXCTL(priv)) & |
526 | (~SMBAUXCTL_CRC), SMBAUXCTL(priv)); | |
8459b544 GN |
527 | } |
528 | ||
529 | if (block) { | |
8459b544 | 530 | dev_dbg(&priv->adapter.dev, " [acc] block: yes\n"); |
9535e71e JS |
531 | ret = i801_block_transaction(priv, data, read_write, size, |
532 | hwpec); | |
8459b544 GN |
533 | } else { |
534 | dev_dbg(&priv->adapter.dev, " [acc] block: no\n"); | |
535 | ret = i801_transaction(priv, xact | ENABLE_INT9); | |
536 | } | |
537 | ||
538 | /* Some BIOSes don't like it when PEC is enabled at reboot or resume | |
7ac3e13a GN |
539 | * time, so we forcibly disable it after every transaction. Turn off |
540 | * E32B for the same reason. | |
541 | */ | |
8459b544 GN |
542 | if (hwpec || block) { |
543 | dev_dbg(&priv->adapter.dev, " [acc] hwpec || block\n"); | |
9535e71e JS |
544 | outb_p(inb_p(SMBAUXCTL(priv)) & ~(SMBAUXCTL_CRC | |
545 | SMBAUXCTL_E32B), SMBAUXCTL(priv)); | |
8459b544 GN |
546 | } |
547 | if (block) { | |
548 | dev_dbg(&priv->adapter.dev, " [acc] block\n"); | |
549 | return ret; | |
550 | } | |
551 | if (ret) { | |
552 | dev_dbg(&priv->adapter.dev, " [acc] ret %d\n", ret); | |
553 | return ret; | |
554 | } | |
555 | if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK)) { | |
9535e71e JS |
556 | dev_dbg(&priv->adapter.dev, |
557 | " [acc] I2C_SMBUS_WRITE || I801_QUICK -> ret 0\n"); | |
8459b544 GN |
558 | return 0; |
559 | } | |
560 | ||
561 | switch (xact & 0x7f) { | |
562 | case I801_BYTE: /* Result put in SMBHSTDAT0 */ | |
563 | case I801_BYTE_DATA: | |
9535e71e JS |
564 | dev_dbg(&priv->adapter.dev, |
565 | " [acc] I801_BYTE or I801_BYTE_DATA\n"); | |
8459b544 GN |
566 | data->byte = inb_p(SMBHSTDAT0(priv)); |
567 | break; | |
568 | case I801_WORD_DATA: | |
569 | dev_dbg(&priv->adapter.dev, " [acc] I801_WORD_DATA\n"); | |
9535e71e JS |
570 | data->word = inb_p(SMBHSTDAT0(priv)) + |
571 | (inb_p(SMBHSTDAT1(priv)) << 8); | |
8459b544 GN |
572 | break; |
573 | } | |
574 | return 0; | |
7dc7967f GKH |
575 | } |
576 | ||
27f391a5 FCR |
577 | #define enable_flag(x) (x) |
578 | #define disable_flag(x) 0 | |
579 | #define enable_flag_if(x, cond) ((cond) ? (x) : 0) | |
580 | ||
7dc7967f GKH |
581 | static u32 i801_func(struct i2c_adapter *adapter) |
582 | { | |
b5909c6d | 583 | struct kpc_i2c *priv = i2c_get_adapdata(adapter); |
8459b544 GN |
584 | |
585 | /* original settings | |
7ac3e13a GN |
586 | * u32 f = I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | |
587 | * I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | | |
588 | * I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK | | |
589 | * ((priv->features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) | | |
590 | * ((priv->features & FEATURE_I2C_BLOCK_READ) ? | |
591 | * I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0); | |
592 | */ | |
8459b544 GN |
593 | |
594 | // http://lxr.free-electrons.com/source/include/uapi/linux/i2c.h#L85 | |
595 | ||
596 | u32 f = | |
27f391a5 FCR |
597 | enable_flag(I2C_FUNC_I2C) | /* 0x00000001(I enabled this one) */ |
598 | disable_flag(I2C_FUNC_10BIT_ADDR) | /* 0x00000002 */ | |
599 | disable_flag(I2C_FUNC_PROTOCOL_MANGLING) | /* 0x00000004 */ | |
600 | enable_flag_if(I2C_FUNC_SMBUS_PEC, | |
601 | priv->features & FEATURE_SMBUS_PEC) | | |
602 | /* 0x00000008 */ | |
603 | disable_flag(I2C_FUNC_SMBUS_BLOCK_PROC_CALL) | /* 0x00008000 */ | |
604 | enable_flag(I2C_FUNC_SMBUS_QUICK) | /* 0x00010000 */ | |
605 | disable_flag(I2C_FUNC_SMBUS_READ_BYTE) | /* 0x00020000 */ | |
606 | disable_flag(I2C_FUNC_SMBUS_WRITE_BYTE) | /* 0x00040000 */ | |
607 | disable_flag(I2C_FUNC_SMBUS_READ_BYTE_DATA) | /* 0x00080000 */ | |
608 | disable_flag(I2C_FUNC_SMBUS_WRITE_BYTE_DATA) | /* 0x00100000 */ | |
609 | disable_flag(I2C_FUNC_SMBUS_READ_WORD_DATA) | /* 0x00200000 */ | |
610 | disable_flag(I2C_FUNC_SMBUS_WRITE_WORD_DATA) | /* 0x00400000 */ | |
611 | disable_flag(I2C_FUNC_SMBUS_PROC_CALL) | /* 0x00800000 */ | |
612 | disable_flag(I2C_FUNC_SMBUS_READ_BLOCK_DATA) | /* 0x01000000 */ | |
613 | disable_flag(I2C_FUNC_SMBUS_WRITE_BLOCK_DATA) | /* 0x02000000 */ | |
614 | enable_flag_if(I2C_FUNC_SMBUS_READ_I2C_BLOCK, | |
615 | priv->features & FEATURE_I2C_BLOCK_READ) | | |
616 | /* 0x04000000 */ | |
617 | enable_flag(I2C_FUNC_SMBUS_WRITE_I2C_BLOCK) | /* 0x08000000 */ | |
618 | ||
619 | enable_flag(I2C_FUNC_SMBUS_BYTE) | /* _READ_BYTE _WRITE_BYTE */ | |
620 | enable_flag(I2C_FUNC_SMBUS_BYTE_DATA) | /* _READ_BYTE_DATA | |
621 | * _WRITE_BYTE_DATA | |
622 | */ | |
623 | enable_flag(I2C_FUNC_SMBUS_WORD_DATA) | /* _READ_WORD_DATA | |
624 | * _WRITE_WORD_DATA | |
625 | */ | |
626 | enable_flag(I2C_FUNC_SMBUS_BLOCK_DATA) | /* _READ_BLOCK_DATA | |
627 | * _WRITE_BLOCK_DATA | |
628 | */ | |
629 | disable_flag(I2C_FUNC_SMBUS_I2C_BLOCK) | /* _READ_I2C_BLOCK | |
630 | * _WRITE_I2C_BLOCK | |
631 | */ | |
632 | disable_flag(I2C_FUNC_SMBUS_EMUL); /* _QUICK _BYTE | |
9535e71e JS |
633 | * _BYTE_DATA _WORD_DATA |
634 | * _PROC_CALL | |
635 | * _WRITE_BLOCK_DATA | |
636 | * _I2C_BLOCK _PEC | |
637 | */ | |
8459b544 | 638 | return f; |
7dc7967f GKH |
639 | } |
640 | ||
27f391a5 FCR |
641 | #undef enable_flag |
642 | #undef disable_flag | |
643 | #undef enable_flag_if | |
644 | ||
7dc7967f | 645 | static const struct i2c_algorithm smbus_algorithm = { |
8459b544 GN |
646 | .smbus_xfer = i801_access, |
647 | .functionality = i801_func, | |
7dc7967f GKH |
648 | }; |
649 | ||
7dc7967f GKH |
650 | /******************************** |
651 | *** Part 2 - Driver Handlers *** | |
652 | ********************************/ | |
b5909c6d | 653 | static int kpc_i2c_probe(struct platform_device *pldev) |
7dc7967f | 654 | { |
8459b544 | 655 | int err; |
b5909c6d | 656 | struct kpc_i2c *priv; |
8459b544 GN |
657 | struct resource *res; |
658 | ||
63306de0 | 659 | priv = devm_kzalloc(&pldev->dev, sizeof(*priv), GFP_KERNEL); |
953bb9e5 | 660 | if (!priv) |
8459b544 | 661 | return -ENOMEM; |
8459b544 GN |
662 | |
663 | i2c_set_adapdata(&priv->adapter, priv); | |
664 | priv->adapter.owner = THIS_MODULE; | |
665 | priv->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; | |
666 | priv->adapter.algo = &smbus_algorithm; | |
667 | ||
668 | res = platform_get_resource(pldev, IORESOURCE_MEM, 0); | |
4ff74031 GN |
669 | if (!res) |
670 | return -ENXIO; | |
671 | ||
4bdc0d67 | 672 | priv->smba = (unsigned long)devm_ioremap(&pldev->dev, |
299672a7 GN |
673 | res->start, |
674 | resource_size(res)); | |
e621c8a1 GN |
675 | if (!priv->smba) |
676 | return -ENOMEM; | |
8459b544 | 677 | |
09197189 | 678 | platform_set_drvdata(pldev, priv); |
8459b544 GN |
679 | |
680 | priv->features |= FEATURE_IDF; | |
681 | priv->features |= FEATURE_I2C_BLOCK_READ; | |
682 | priv->features |= FEATURE_SMBUS_PEC; | |
683 | priv->features |= FEATURE_BLOCK_BUFFER; | |
684 | ||
685 | //init_MUTEX(&lddata->sem); | |
8459b544 GN |
686 | |
687 | /* set up the sysfs linkage to our parent device */ | |
688 | priv->adapter.dev.parent = &pldev->dev; | |
689 | ||
690 | /* Retry up to 3 times on lost arbitration */ | |
691 | priv->adapter.retries = 3; | |
692 | ||
9535e71e JS |
693 | snprintf(priv->adapter.name, sizeof(priv->adapter.name), |
694 | "Fake SMBus I801 adapter"); | |
8459b544 GN |
695 | |
696 | err = i2c_add_adapter(&priv->adapter); | |
697 | if (err) { | |
698 | dev_err(&priv->adapter.dev, "Failed to add SMBus adapter\n"); | |
699 | return err; | |
700 | } | |
701 | ||
702 | return 0; | |
7dc7967f GKH |
703 | } |
704 | ||
b5909c6d | 705 | static int kpc_i2c_remove(struct platform_device *pldev) |
7dc7967f | 706 | { |
b5909c6d | 707 | struct kpc_i2c *lddev; |
953bb9e5 | 708 | |
b5909c6d | 709 | lddev = (struct kpc_i2c *)platform_get_drvdata(pldev); |
8459b544 GN |
710 | |
711 | i2c_del_adapter(&lddev->adapter); | |
712 | ||
713 | //TODO: Figure out the right thing to do here... | |
714 | //pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg); | |
715 | //pci_release_region(dev, SMBBAR); | |
716 | //pci_set_drvdata(dev, NULL); | |
717 | ||
718 | //cdev_del(&lddev->cdev); | |
8459b544 GN |
719 | |
720 | return 0; | |
7dc7967f GKH |
721 | } |
722 | ||
b5909c6d JL |
723 | static struct platform_driver kpc_i2c_driver = { |
724 | .probe = kpc_i2c_probe, | |
725 | .remove = kpc_i2c_remove, | |
8459b544 GN |
726 | .driver = { |
727 | .name = KP_DRIVER_NAME_I2C, | |
8459b544 | 728 | }, |
7dc7967f GKH |
729 | }; |
730 | ||
b5909c6d | 731 | module_platform_driver(kpc_i2c_driver); |