diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/i2c/busses |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/i2c/busses')
47 files changed, 15628 insertions, 0 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig new file mode 100644 index 000000000000..edf8051da3b4 --- /dev/null +++ b/drivers/i2c/busses/Kconfig | |||
@@ -0,0 +1,499 @@ | |||
1 | # | ||
2 | # Sensor device configuration | ||
3 | # | ||
4 | |||
5 | menu "I2C Hardware Bus support" | ||
6 | depends on I2C | ||
7 | |||
8 | config I2C_ALI1535 | ||
9 | tristate "ALI 1535" | ||
10 | depends on I2C && PCI && EXPERIMENTAL | ||
11 | help | ||
12 | If you say yes to this option, support will be included for the SMB | ||
13 | Host controller on Acer Labs Inc. (ALI) M1535 South Bridges. The SMB | ||
14 | controller is part of the 7101 device, which is an ACPI-compliant | ||
15 | Power Management Unit (PMU). | ||
16 | |||
17 | This driver can also be built as a module. If so, the module | ||
18 | will be called i2c-ali1535. | ||
19 | |||
20 | config I2C_ALI1563 | ||
21 | tristate "ALI 1563" | ||
22 | depends on I2C && PCI && EXPERIMENTAL | ||
23 | help | ||
24 | If you say yes to this option, support will be included for the SMB | ||
25 | Host controller on Acer Labs Inc. (ALI) M1563 South Bridges. The SMB | ||
26 | controller is part of the 7101 device, which is an ACPI-compliant | ||
27 | Power Management Unit (PMU). | ||
28 | |||
29 | This driver can also be built as a module. If so, the module | ||
30 | will be called i2c-ali1563. | ||
31 | |||
32 | config I2C_ALI15X3 | ||
33 | tristate "ALI 15x3" | ||
34 | depends on I2C && PCI && EXPERIMENTAL | ||
35 | help | ||
36 | If you say yes to this option, support will be included for the | ||
37 | Acer Labs Inc. (ALI) M1514 and M1543 motherboard I2C interfaces. | ||
38 | |||
39 | This driver can also be built as a module. If so, the module | ||
40 | will be called i2c-ali15x3. | ||
41 | |||
42 | config I2C_AMD756 | ||
43 | tristate "AMD 756/766/768/8111 and nVidia nForce" | ||
44 | depends on I2C && PCI && EXPERIMENTAL | ||
45 | help | ||
46 | If you say yes to this option, support will be included for the AMD | ||
47 | 756/766/768 mainboard I2C interfaces. The driver also includes | ||
48 | support for the first (SMBus 1.0) I2C interface of the AMD 8111 and | ||
49 | the nVidia nForce I2C interface. | ||
50 | |||
51 | This driver can also be built as a module. If so, the module | ||
52 | will be called i2c-amd756. | ||
53 | |||
54 | config I2C_AMD756_S4882 | ||
55 | tristate "SMBus multiplexing on the Tyan S4882" | ||
56 | depends on I2C_AMD756 && EXPERIMENTAL | ||
57 | help | ||
58 | Enabling this option will add specific SMBus support for the Tyan | ||
59 | S4882 motherboard. On this 4-CPU board, the SMBus is multiplexed | ||
60 | over 8 different channels, where the various memory module EEPROMs | ||
61 | and temperature sensors live. Saying yes here will give you access | ||
62 | to these in addition to the trunk. | ||
63 | |||
64 | This driver can also be built as a module. If so, the module | ||
65 | will be called i2c-amd756-s4882. | ||
66 | |||
67 | config I2C_AMD8111 | ||
68 | tristate "AMD 8111" | ||
69 | depends on I2C && PCI && EXPERIMENTAL | ||
70 | help | ||
71 | If you say yes to this option, support will be included for the | ||
72 | second (SMBus 2.0) AMD 8111 mainboard I2C interface. | ||
73 | |||
74 | This driver can also be built as a module. If so, the module | ||
75 | will be called i2c-amd8111. | ||
76 | |||
77 | config I2C_AU1550 | ||
78 | tristate "Au1550 SMBus interface" | ||
79 | depends on I2C && SOC_AU1550 | ||
80 | help | ||
81 | If you say yes to this option, support will be included for the | ||
82 | Au1550 SMBus interface. | ||
83 | |||
84 | This driver can also be built as a module. If so, the module | ||
85 | will be called i2c-au1550. | ||
86 | |||
87 | config I2C_ELEKTOR | ||
88 | tristate "Elektor ISA card" | ||
89 | depends on I2C && ISA && BROKEN_ON_SMP | ||
90 | select I2C_ALGOPCF | ||
91 | help | ||
92 | This supports the PCF8584 ISA bus I2C adapter. Say Y if you own | ||
93 | such an adapter. | ||
94 | |||
95 | This support is also available as a module. If so, the module | ||
96 | will be called i2c-elektor. | ||
97 | |||
98 | config I2C_HYDRA | ||
99 | tristate "CHRP Apple Hydra Mac I/O I2C interface" | ||
100 | depends on I2C && PCI && PPC_CHRP && EXPERIMENTAL | ||
101 | select I2C_ALGOBIT | ||
102 | help | ||
103 | This supports the use of the I2C interface in the Apple Hydra Mac | ||
104 | I/O chip on some CHRP machines (e.g. the LongTrail). Say Y if you | ||
105 | have such a machine. | ||
106 | |||
107 | This support is also available as a module. If so, the module | ||
108 | will be called i2c-hydra. | ||
109 | |||
110 | config I2C_I801 | ||
111 | tristate "Intel 82801 (ICH)" | ||
112 | depends on I2C && PCI && EXPERIMENTAL | ||
113 | help | ||
114 | If you say yes to this option, support will be included for the Intel | ||
115 | 801 family of mainboard I2C interfaces. Specifically, the following | ||
116 | versions of the chipset are supported: | ||
117 | 82801AA | ||
118 | 82801AB | ||
119 | 82801BA | ||
120 | 82801CA/CAM | ||
121 | 82801DB | ||
122 | 82801EB/ER (ICH5/ICH5R) | ||
123 | 6300ESB | ||
124 | ICH6 | ||
125 | ICH7 | ||
126 | |||
127 | This driver can also be built as a module. If so, the module | ||
128 | will be called i2c-i801. | ||
129 | |||
130 | config I2C_I810 | ||
131 | tristate "Intel 810/815" | ||
132 | depends on I2C && PCI && EXPERIMENTAL | ||
133 | select I2C_ALGOBIT | ||
134 | help | ||
135 | If you say yes to this option, support will be included for the Intel | ||
136 | 810/815 family of mainboard I2C interfaces. Specifically, the | ||
137 | following versions of the chipset is supported: | ||
138 | i810AA | ||
139 | i810AB | ||
140 | i810E | ||
141 | i815 | ||
142 | |||
143 | This driver can also be built as a module. If so, the module | ||
144 | will be called i2c-i810. | ||
145 | |||
146 | config I2C_PIIX4 | ||
147 | tristate "Intel PIIX4" | ||
148 | depends on I2C && PCI | ||
149 | help | ||
150 | If you say yes to this option, support will be included for the Intel | ||
151 | PIIX4 family of mainboard I2C interfaces. Specifically, the following | ||
152 | versions of the chipset are supported: | ||
153 | Intel PIIX4 | ||
154 | Intel 440MX | ||
155 | Serverworks OSB4 | ||
156 | Serverworks CSB5 | ||
157 | Serverworks CSB6 | ||
158 | SMSC Victory66 | ||
159 | |||
160 | This driver can also be built as a module. If so, the module | ||
161 | will be called i2c-piix4. | ||
162 | |||
163 | config I2C_IBM_IIC | ||
164 | tristate "IBM PPC 4xx on-chip I2C interface" | ||
165 | depends on IBM_OCP && I2C | ||
166 | help | ||
167 | Say Y here if you want to use IIC peripheral found on | ||
168 | embedded IBM PPC 4xx based systems. | ||
169 | |||
170 | This driver can also be built as a module. If so, the module | ||
171 | will be called i2c-ibm_iic. | ||
172 | |||
173 | config I2C_IOP3XX | ||
174 | tristate "Intel IOP3xx and IXP4xx on-chip I2C interface" | ||
175 | depends on (ARCH_IOP3XX || ARCH_IXP4XX) && I2C | ||
176 | help | ||
177 | Say Y here if you want to use the IIC bus controller on | ||
178 | the Intel IOP3xx I/O Processors or IXP4xx Network Processors. | ||
179 | |||
180 | This driver can also be built as a module. If so, the module | ||
181 | will be called i2c-iop3xx. | ||
182 | |||
183 | config I2C_ISA | ||
184 | tristate "ISA Bus support" | ||
185 | depends on I2C && EXPERIMENTAL | ||
186 | help | ||
187 | If you say yes to this option, support will be included for i2c | ||
188 | interfaces that are on the ISA bus. | ||
189 | |||
190 | This driver can also be built as a module. If so, the module | ||
191 | will be called i2c-isa. | ||
192 | |||
193 | config I2C_ITE | ||
194 | tristate "ITE I2C Adapter" | ||
195 | depends on I2C && MIPS_ITE8172 | ||
196 | select I2C_ALGOITE | ||
197 | help | ||
198 | This supports the ITE8172 I2C peripheral found on some MIPS | ||
199 | systems. Say Y if you have one of these. You should also say Y for | ||
200 | the ITE I2C driver algorithm support above. | ||
201 | |||
202 | This support is also available as a module. If so, the module | ||
203 | will be called i2c-ite. | ||
204 | |||
205 | config I2C_IXP4XX | ||
206 | tristate "IXP4xx GPIO-Based I2C Interface" | ||
207 | depends on I2C && ARCH_IXP4XX | ||
208 | select I2C_ALGOBIT | ||
209 | help | ||
210 | Say Y here if you have an Intel IXP4xx(420,421,422,425) based | ||
211 | system and are using GPIO lines for an I2C bus. | ||
212 | |||
213 | This support is also available as a module. If so, the module | ||
214 | will be called i2c-ixp4xx. | ||
215 | |||
216 | config I2C_IXP2000 | ||
217 | tristate "IXP2000 GPIO-Based I2C Interface" | ||
218 | depends on I2C && ARCH_IXP2000 | ||
219 | select I2C_ALGOBIT | ||
220 | help | ||
221 | Say Y here if you have an Intel IXP2000(2400, 2800, 2850) based | ||
222 | system and are using GPIO lines for an I2C bus. | ||
223 | |||
224 | This support is also available as a module. If so, the module | ||
225 | will be called i2c-ixp2000. | ||
226 | |||
227 | config I2C_KEYWEST | ||
228 | tristate "Powermac Keywest I2C interface" | ||
229 | depends on I2C && PPC_PMAC | ||
230 | help | ||
231 | This supports the use of the I2C interface in the combo-I/O | ||
232 | chip on recent Apple machines. Say Y if you have such a machine. | ||
233 | |||
234 | This support is also available as a module. If so, the module | ||
235 | will be called i2c-keywest. | ||
236 | |||
237 | config I2C_MPC | ||
238 | tristate "MPC107/824x/85xx/52xx" | ||
239 | depends on I2C && PPC | ||
240 | help | ||
241 | If you say yes to this option, support will be included for the | ||
242 | built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and | ||
243 | MPC85xx family processors. The driver may also work on 52xx | ||
244 | family processors, though interrupts are known not to work. | ||
245 | |||
246 | This driver can also be built as a module. If so, the module | ||
247 | will be called i2c-mpc. | ||
248 | |||
249 | config I2C_NFORCE2 | ||
250 | tristate "Nvidia Nforce2" | ||
251 | depends on I2C && PCI && EXPERIMENTAL | ||
252 | help | ||
253 | If you say yes to this option, support will be included for the Nvidia | ||
254 | Nforce2 family of mainboard I2C interfaces. | ||
255 | This driver also supports the nForce3 Pro 150 MCP. | ||
256 | |||
257 | This driver can also be built as a module. If so, the module | ||
258 | will be called i2c-nforce2. | ||
259 | |||
260 | config I2C_PARPORT | ||
261 | tristate "Parallel port adapter" | ||
262 | depends on I2C && PARPORT | ||
263 | select I2C_ALGOBIT | ||
264 | help | ||
265 | This supports parallel port I2C adapters such as the ones made by | ||
266 | Philips or Velleman, Analog Devices evaluation boards, and more. | ||
267 | Basically any adapter using the parallel port as an I2C bus with | ||
268 | no extra chipset is supported by this driver, or could be. | ||
269 | |||
270 | This driver is a replacement for (and was inspired by) an older | ||
271 | driver named i2c-philips-par. The new driver supports more devices, | ||
272 | and makes it easier to add support for new devices. | ||
273 | |||
274 | Another driver exists, named i2c-parport-light, which doesn't depend | ||
275 | on the parport driver. This is meant for embedded systems. Don't say | ||
276 | Y here if you intend to say Y or M there. | ||
277 | |||
278 | This support is also available as a module. If so, the module | ||
279 | will be called i2c-parport. | ||
280 | |||
281 | config I2C_PARPORT_LIGHT | ||
282 | tristate "Parallel port adapter (light)" | ||
283 | depends on I2C | ||
284 | select I2C_ALGOBIT | ||
285 | help | ||
286 | This supports parallel port I2C adapters such as the ones made by | ||
287 | Philips or Velleman, Analog Devices evaluation boards, and more. | ||
288 | Basically any adapter using the parallel port as an I2C bus with | ||
289 | no extra chipset is supported by this driver, or could be. | ||
290 | |||
291 | This driver is a light version of i2c-parport. It doesn't depend | ||
292 | on the parport driver, and uses direct I/O access instead. This | ||
293 | might be prefered on embedded systems where wasting memory for | ||
294 | the clean but heavy parport handling is not an option. The | ||
295 | drawback is a reduced portability and the impossibility to | ||
296 | dasiy-chain other parallel port devices. | ||
297 | |||
298 | Don't say Y here if you said Y or M to i2c-parport. Saying M to | ||
299 | both is possible but both modules should not be loaded at the same | ||
300 | time. | ||
301 | |||
302 | This support is also available as a module. If so, the module | ||
303 | will be called i2c-parport-light. | ||
304 | |||
305 | config I2C_PROSAVAGE | ||
306 | tristate "S3/VIA (Pro)Savage" | ||
307 | depends on I2C && PCI && EXPERIMENTAL | ||
308 | select I2C_ALGOBIT | ||
309 | help | ||
310 | If you say yes to this option, support will be included for the | ||
311 | I2C bus and DDC bus of the S3VIA embedded Savage4 and ProSavage8 | ||
312 | graphics processors. | ||
313 | chipsets supported: | ||
314 | S3/VIA KM266/VT8375 aka ProSavage8 | ||
315 | S3/VIA KM133/VT8365 aka Savage4 | ||
316 | |||
317 | This support is also available as a module. If so, the module | ||
318 | will be called i2c-prosavage. | ||
319 | |||
320 | config I2C_RPXLITE | ||
321 | tristate "Embedded Planet RPX Lite/Classic support" | ||
322 | depends on (RPXLITE || RPXCLASSIC) && I2C | ||
323 | select I2C_ALGO8XX | ||
324 | |||
325 | config I2C_S3C2410 | ||
326 | tristate "S3C2410 I2C Driver" | ||
327 | depends on I2C && ARCH_S3C2410 | ||
328 | help | ||
329 | Say Y here to include support for I2C controller in the | ||
330 | Samsung S3C2410 based System-on-Chip devices. | ||
331 | |||
332 | config I2C_SAVAGE4 | ||
333 | tristate "S3 Savage 4" | ||
334 | depends on I2C && PCI && EXPERIMENTAL | ||
335 | select I2C_ALGOBIT | ||
336 | help | ||
337 | If you say yes to this option, support will be included for the | ||
338 | S3 Savage 4 I2C interface. | ||
339 | |||
340 | This driver can also be built as a module. If so, the module | ||
341 | will be called i2c-savage4. | ||
342 | |||
343 | config I2C_SIBYTE | ||
344 | tristate "SiByte SMBus interface" | ||
345 | depends on SIBYTE_SB1xxx_SOC && I2C | ||
346 | help | ||
347 | Supports the SiByte SOC on-chip I2C interfaces (2 channels). | ||
348 | |||
349 | config SCx200_I2C | ||
350 | tristate "NatSemi SCx200 I2C using GPIO pins" | ||
351 | depends on SCx200_GPIO && I2C | ||
352 | select I2C_ALGOBIT | ||
353 | help | ||
354 | Enable the use of two GPIO pins of a SCx200 processor as an I2C bus. | ||
355 | |||
356 | If you don't know what to do here, say N. | ||
357 | |||
358 | This support is also available as a module. If so, the module | ||
359 | will be called scx200_i2c. | ||
360 | |||
361 | config SCx200_I2C_SCL | ||
362 | int "GPIO pin used for SCL" | ||
363 | depends on SCx200_I2C | ||
364 | default "12" | ||
365 | help | ||
366 | Enter the GPIO pin number used for the SCL signal. This value can | ||
367 | also be specified with a module parameter. | ||
368 | |||
369 | config SCx200_I2C_SDA | ||
370 | int "GPIO pin used for SDA" | ||
371 | depends on SCx200_I2C | ||
372 | default "13" | ||
373 | help | ||
374 | Enter the GPIO pin number used for the SSA signal. This value can | ||
375 | also be specified with a module parameter. | ||
376 | |||
377 | config SCx200_ACB | ||
378 | tristate "NatSemi SCx200 ACCESS.bus" | ||
379 | depends on I2C && PCI | ||
380 | help | ||
381 | Enable the use of the ACCESS.bus controllers of a SCx200 processor. | ||
382 | |||
383 | If you don't know what to do here, say N. | ||
384 | |||
385 | This support is also available as a module. If so, the module | ||
386 | will be called scx200_acb. | ||
387 | |||
388 | config I2C_SIS5595 | ||
389 | tristate "SiS 5595" | ||
390 | depends on I2C && PCI && EXPERIMENTAL | ||
391 | help | ||
392 | If you say yes to this option, support will be included for the | ||
393 | SiS5595 SMBus (a subset of I2C) interface. | ||
394 | |||
395 | This driver can also be built as a module. If so, the module | ||
396 | will be called i2c-sis5595. | ||
397 | |||
398 | config I2C_SIS630 | ||
399 | tristate "SiS 630/730" | ||
400 | depends on I2C && PCI && EXPERIMENTAL | ||
401 | help | ||
402 | If you say yes to this option, support will be included for the | ||
403 | SiS630 and SiS730 SMBus (a subset of I2C) interface. | ||
404 | |||
405 | This driver can also be built as a module. If so, the module | ||
406 | will be called i2c-sis630. | ||
407 | |||
408 | config I2C_SIS96X | ||
409 | tristate "SiS 96x" | ||
410 | depends on I2C && PCI && EXPERIMENTAL | ||
411 | help | ||
412 | If you say yes to this option, support will be included for the SiS | ||
413 | 96x SMBus (a subset of I2C) interfaces. Specifically, the following | ||
414 | chipsets are supported: | ||
415 | 645/961 | ||
416 | 645DX/961 | ||
417 | 645DX/962 | ||
418 | 648/961 | ||
419 | 650/961 | ||
420 | 735 | ||
421 | |||
422 | This driver can also be built as a module. If so, the module | ||
423 | will be called i2c-sis96x. | ||
424 | |||
425 | config I2C_STUB | ||
426 | tristate "I2C/SMBus Test Stub" | ||
427 | depends on I2C && EXPERIMENTAL && 'm' | ||
428 | default 'n' | ||
429 | help | ||
430 | This module may be useful to developers of SMBus client drivers, | ||
431 | especially for certain kinds of sensor chips. | ||
432 | |||
433 | If you do build this module, be sure to read the notes and warnings | ||
434 | in <file:Documentation/i2c/i2c-stub>. | ||
435 | |||
436 | If you don't know what to do here, definitely say N. | ||
437 | |||
438 | config I2C_VIA | ||
439 | tristate "VIA 82C586B" | ||
440 | depends on I2C && PCI && EXPERIMENTAL | ||
441 | select I2C_ALGOBIT | ||
442 | help | ||
443 | If you say yes to this option, support will be included for the VIA | ||
444 | 82C586B I2C interface | ||
445 | |||
446 | This driver can also be built as a module. If so, the module | ||
447 | will be called i2c-via. | ||
448 | |||
449 | config I2C_VIAPRO | ||
450 | tristate "VIA 82C596/82C686/823x" | ||
451 | depends on I2C && PCI && EXPERIMENTAL | ||
452 | help | ||
453 | If you say yes to this option, support will be included for the VIA | ||
454 | 82C596/82C686/823x I2C interfaces. Specifically, the following | ||
455 | chipsets are supported: | ||
456 | 82C596A/B | ||
457 | 82C686A/B | ||
458 | 8231 | ||
459 | 8233 | ||
460 | 8233A | ||
461 | 8235 | ||
462 | 8237 | ||
463 | |||
464 | This driver can also be built as a module. If so, the module | ||
465 | will be called i2c-viapro. | ||
466 | |||
467 | config I2C_VOODOO3 | ||
468 | tristate "Voodoo 3" | ||
469 | depends on I2C && PCI && EXPERIMENTAL | ||
470 | select I2C_ALGOBIT | ||
471 | help | ||
472 | If you say yes to this option, support will be included for the | ||
473 | Voodoo 3 I2C interface. | ||
474 | |||
475 | This driver can also be built as a module. If so, the module | ||
476 | will be called i2c-voodoo3. | ||
477 | |||
478 | config I2C_PCA_ISA | ||
479 | tristate "PCA9564 on an ISA bus" | ||
480 | depends on I2C | ||
481 | select I2C_ALGOPCA | ||
482 | help | ||
483 | This driver supports ISA boards using the Philips PCA 9564 | ||
484 | Parallel bus to I2C bus controller | ||
485 | |||
486 | This driver can also be built as a module. If so, the module | ||
487 | will be called i2c-pca-isa. | ||
488 | |||
489 | config I2C_MV64XXX | ||
490 | tristate "Marvell mv64xxx I2C Controller" | ||
491 | depends on I2C && MV64X60 && EXPERIMENTAL | ||
492 | help | ||
493 | If you say yes to this option, support will be included for the | ||
494 | built-in I2C interface on the Marvell 64xxx line of host bridges. | ||
495 | |||
496 | This driver can also be built as a module. If so, the module | ||
497 | will be called i2c-mv64xxx. | ||
498 | |||
499 | endmenu | ||
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile new file mode 100644 index 000000000000..42d6d814da72 --- /dev/null +++ b/drivers/i2c/busses/Makefile | |||
@@ -0,0 +1,47 @@ | |||
1 | # | ||
2 | # Makefile for the i2c bus drivers. | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_I2C_ALI1535) += i2c-ali1535.o | ||
6 | obj-$(CONFIG_I2C_ALI1563) += i2c-ali1563.o | ||
7 | obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o | ||
8 | obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o | ||
9 | obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o | ||
10 | obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o | ||
11 | obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o | ||
12 | obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o | ||
13 | obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o | ||
14 | obj-$(CONFIG_I2C_I801) += i2c-i801.o | ||
15 | obj-$(CONFIG_I2C_I810) += i2c-i810.o | ||
16 | obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o | ||
17 | obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o | ||
18 | obj-$(CONFIG_I2C_ISA) += i2c-isa.o | ||
19 | obj-$(CONFIG_I2C_ITE) += i2c-ite.o | ||
20 | obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o | ||
21 | obj-$(CONFIG_I2C_IXP4XX) += i2c-ixp4xx.o | ||
22 | obj-$(CONFIG_I2C_KEYWEST) += i2c-keywest.o | ||
23 | obj-$(CONFIG_I2C_MPC) += i2c-mpc.o | ||
24 | obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o | ||
25 | obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o | ||
26 | obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o | ||
27 | obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o | ||
28 | obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o | ||
29 | obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o | ||
30 | obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o | ||
31 | obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o | ||
32 | obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o | ||
33 | obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o | ||
34 | obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o | ||
35 | obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o | ||
36 | obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o | ||
37 | obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o | ||
38 | obj-$(CONFIG_I2C_STUB) += i2c-stub.o | ||
39 | obj-$(CONFIG_I2C_VIA) += i2c-via.o | ||
40 | obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o | ||
41 | obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o | ||
42 | obj-$(CONFIG_SCx200_ACB) += scx200_acb.o | ||
43 | obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o | ||
44 | |||
45 | ifeq ($(CONFIG_I2C_DEBUG_BUS),y) | ||
46 | EXTRA_CFLAGS += -DDEBUG | ||
47 | endif | ||
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c new file mode 100644 index 000000000000..b00cd4098221 --- /dev/null +++ b/drivers/i2c/busses/i2c-ali1535.c | |||
@@ -0,0 +1,543 @@ | |||
1 | /* | ||
2 | i2c-ali1535.c - Part of lm_sensors, Linux kernel modules for hardware | ||
3 | monitoring | ||
4 | Copyright (c) 2000 Frodo Looijaard <frodol@dds.nl>, | ||
5 | Philip Edelbrock <phil@netroedge.com>, | ||
6 | Mark D. Studebaker <mdsxyz123@yahoo.com>, | ||
7 | Dan Eaton <dan.eaton@rocketlogix.com> and | ||
8 | Stephen Rousset<stephen.rousset@rocketlogix.com> | ||
9 | |||
10 | This program is free software; you can redistribute it and/or modify | ||
11 | it under the terms of the GNU General Public License as published by | ||
12 | the Free Software Foundation; either version 2 of the License, or | ||
13 | (at your option) any later version. | ||
14 | |||
15 | This program is distributed in the hope that it will be useful, | ||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | GNU General Public License for more details. | ||
19 | |||
20 | You should have received a copy of the GNU General Public License | ||
21 | along with this program; if not, write to the Free Software | ||
22 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | */ | ||
24 | |||
25 | /* | ||
26 | This is the driver for the SMB Host controller on | ||
27 | Acer Labs Inc. (ALI) M1535 South Bridge. | ||
28 | |||
29 | The M1535 is a South bridge for portable systems. | ||
30 | It is very similar to the M15x3 South bridges also produced | ||
31 | by Acer Labs Inc. Some of the registers within the part | ||
32 | have moved and some have been redefined slightly. Additionally, | ||
33 | the sequencing of the SMBus transactions has been modified | ||
34 | to be more consistent with the sequencing recommended by | ||
35 | the manufacturer and observed through testing. These | ||
36 | changes are reflected in this driver and can be identified | ||
37 | by comparing this driver to the i2c-ali15x3 driver. | ||
38 | For an overview of these chips see http://www.acerlabs.com | ||
39 | |||
40 | The SMB controller is part of the 7101 device, which is an | ||
41 | ACPI-compliant Power Management Unit (PMU). | ||
42 | |||
43 | The whole 7101 device has to be enabled for the SMB to work. | ||
44 | You can't just enable the SMB alone. | ||
45 | The SMB and the ACPI have separate I/O spaces. | ||
46 | We make sure that the SMB is enabled. We leave the ACPI alone. | ||
47 | |||
48 | This driver controls the SMB Host only. | ||
49 | |||
50 | This driver does not use interrupts. | ||
51 | */ | ||
52 | |||
53 | |||
54 | /* Note: we assume there can only be one ALI1535, with one SMBus interface */ | ||
55 | |||
56 | #include <linux/config.h> | ||
57 | #include <linux/module.h> | ||
58 | #include <linux/pci.h> | ||
59 | #include <linux/kernel.h> | ||
60 | #include <linux/stddef.h> | ||
61 | #include <linux/sched.h> | ||
62 | #include <linux/delay.h> | ||
63 | #include <linux/ioport.h> | ||
64 | #include <linux/i2c.h> | ||
65 | #include <linux/init.h> | ||
66 | #include <asm/io.h> | ||
67 | #include <asm/semaphore.h> | ||
68 | |||
69 | |||
70 | /* ALI1535 SMBus address offsets */ | ||
71 | #define SMBHSTSTS (0 + ali1535_smba) | ||
72 | #define SMBHSTTYP (1 + ali1535_smba) | ||
73 | #define SMBHSTPORT (2 + ali1535_smba) | ||
74 | #define SMBHSTCMD (7 + ali1535_smba) | ||
75 | #define SMBHSTADD (3 + ali1535_smba) | ||
76 | #define SMBHSTDAT0 (4 + ali1535_smba) | ||
77 | #define SMBHSTDAT1 (5 + ali1535_smba) | ||
78 | #define SMBBLKDAT (6 + ali1535_smba) | ||
79 | |||
80 | /* PCI Address Constants */ | ||
81 | #define SMBCOM 0x004 | ||
82 | #define SMBREV 0x008 | ||
83 | #define SMBCFG 0x0D1 | ||
84 | #define SMBBA 0x0E2 | ||
85 | #define SMBHSTCFG 0x0F0 | ||
86 | #define SMBCLK 0x0F2 | ||
87 | |||
88 | /* Other settings */ | ||
89 | #define MAX_TIMEOUT 500 /* times 1/100 sec */ | ||
90 | #define ALI1535_SMB_IOSIZE 32 | ||
91 | |||
92 | #define ALI1535_SMB_DEFAULTBASE 0x8040 | ||
93 | |||
94 | /* ALI1535 address lock bits */ | ||
95 | #define ALI1535_LOCK 0x06 /* dwe */ | ||
96 | |||
97 | /* ALI1535 command constants */ | ||
98 | #define ALI1535_QUICK 0x00 | ||
99 | #define ALI1535_BYTE 0x10 | ||
100 | #define ALI1535_BYTE_DATA 0x20 | ||
101 | #define ALI1535_WORD_DATA 0x30 | ||
102 | #define ALI1535_BLOCK_DATA 0x40 | ||
103 | #define ALI1535_I2C_READ 0x60 | ||
104 | |||
105 | #define ALI1535_DEV10B_EN 0x80 /* Enable 10-bit addressing in */ | ||
106 | /* I2C read */ | ||
107 | #define ALI1535_T_OUT 0x08 /* Time-out Command (write) */ | ||
108 | #define ALI1535_A_HIGH_BIT9 0x08 /* Bit 9 of 10-bit address in */ | ||
109 | /* Alert-Response-Address */ | ||
110 | /* (read) */ | ||
111 | #define ALI1535_KILL 0x04 /* Kill Command (write) */ | ||
112 | #define ALI1535_A_HIGH_BIT8 0x04 /* Bit 8 of 10-bit address in */ | ||
113 | /* Alert-Response-Address */ | ||
114 | /* (read) */ | ||
115 | |||
116 | #define ALI1535_D_HI_MASK 0x03 /* Mask for isolating bits 9-8 */ | ||
117 | /* of 10-bit address in I2C */ | ||
118 | /* Read Command */ | ||
119 | |||
120 | /* ALI1535 status register bits */ | ||
121 | #define ALI1535_STS_IDLE 0x04 | ||
122 | #define ALI1535_STS_BUSY 0x08 /* host busy */ | ||
123 | #define ALI1535_STS_DONE 0x10 /* transaction complete */ | ||
124 | #define ALI1535_STS_DEV 0x20 /* device error */ | ||
125 | #define ALI1535_STS_BUSERR 0x40 /* bus error */ | ||
126 | #define ALI1535_STS_FAIL 0x80 /* failed bus transaction */ | ||
127 | #define ALI1535_STS_ERR 0xE0 /* all the bad error bits */ | ||
128 | |||
129 | #define ALI1535_BLOCK_CLR 0x04 /* reset block data index */ | ||
130 | |||
131 | /* ALI1535 device address register bits */ | ||
132 | #define ALI1535_RD_ADDR 0x01 /* Read/Write Bit in Device */ | ||
133 | /* Address field */ | ||
134 | /* -> Write = 0 */ | ||
135 | /* -> Read = 1 */ | ||
136 | #define ALI1535_SMBIO_EN 0x04 /* SMB I/O Space enable */ | ||
137 | |||
138 | |||
139 | static unsigned short ali1535_smba; | ||
140 | static DECLARE_MUTEX(i2c_ali1535_sem); | ||
141 | |||
142 | /* Detect whether a ALI1535 can be found, and initialize it, where necessary. | ||
143 | Note the differences between kernels with the old PCI BIOS interface and | ||
144 | newer kernels with the real PCI interface. In compat.h some things are | ||
145 | defined to make the transition easier. */ | ||
146 | static int ali1535_setup(struct pci_dev *dev) | ||
147 | { | ||
148 | int retval = -ENODEV; | ||
149 | unsigned char temp; | ||
150 | |||
151 | /* Check the following things: | ||
152 | - SMB I/O address is initialized | ||
153 | - Device is enabled | ||
154 | - We can use the addresses | ||
155 | */ | ||
156 | |||
157 | /* Determine the address of the SMBus area */ | ||
158 | pci_read_config_word(dev, SMBBA, &ali1535_smba); | ||
159 | ali1535_smba &= (0xffff & ~(ALI1535_SMB_IOSIZE - 1)); | ||
160 | if (ali1535_smba == 0) { | ||
161 | dev_warn(&dev->dev, | ||
162 | "ALI1535_smb region uninitialized - upgrade BIOS?\n"); | ||
163 | goto exit; | ||
164 | } | ||
165 | |||
166 | if (!request_region(ali1535_smba, ALI1535_SMB_IOSIZE, "ali1535-smb")) { | ||
167 | dev_err(&dev->dev, "ALI1535_smb region 0x%x already in use!\n", | ||
168 | ali1535_smba); | ||
169 | goto exit; | ||
170 | } | ||
171 | |||
172 | /* check if whole device is enabled */ | ||
173 | pci_read_config_byte(dev, SMBCFG, &temp); | ||
174 | if ((temp & ALI1535_SMBIO_EN) == 0) { | ||
175 | dev_err(&dev->dev, "SMB device not enabled - upgrade BIOS?\n"); | ||
176 | goto exit_free; | ||
177 | } | ||
178 | |||
179 | /* Is SMB Host controller enabled? */ | ||
180 | pci_read_config_byte(dev, SMBHSTCFG, &temp); | ||
181 | if ((temp & 1) == 0) { | ||
182 | dev_err(&dev->dev, "SMBus controller not enabled - upgrade BIOS?\n"); | ||
183 | goto exit_free; | ||
184 | } | ||
185 | |||
186 | /* set SMB clock to 74KHz as recommended in data sheet */ | ||
187 | pci_write_config_byte(dev, SMBCLK, 0x20); | ||
188 | |||
189 | /* | ||
190 | The interrupt routing for SMB is set up in register 0x77 in the | ||
191 | 1533 ISA Bridge device, NOT in the 7101 device. | ||
192 | Don't bother with finding the 1533 device and reading the register. | ||
193 | if ((....... & 0x0F) == 1) | ||
194 | dev_dbg(&dev->dev, "ALI1535 using Interrupt 9 for SMBus.\n"); | ||
195 | */ | ||
196 | pci_read_config_byte(dev, SMBREV, &temp); | ||
197 | dev_dbg(&dev->dev, "SMBREV = 0x%X\n", temp); | ||
198 | dev_dbg(&dev->dev, "ALI1535_smba = 0x%X\n", ali1535_smba); | ||
199 | |||
200 | retval = 0; | ||
201 | exit: | ||
202 | return retval; | ||
203 | |||
204 | exit_free: | ||
205 | release_region(ali1535_smba, ALI1535_SMB_IOSIZE); | ||
206 | return retval; | ||
207 | } | ||
208 | |||
209 | static int ali1535_transaction(struct i2c_adapter *adap) | ||
210 | { | ||
211 | int temp; | ||
212 | int result = 0; | ||
213 | int timeout = 0; | ||
214 | |||
215 | dev_dbg(&adap->dev, "Transaction (pre): STS=%02x, TYP=%02x, " | ||
216 | "CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", | ||
217 | inb_p(SMBHSTSTS), inb_p(SMBHSTTYP), inb_p(SMBHSTCMD), | ||
218 | inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); | ||
219 | |||
220 | /* get status */ | ||
221 | temp = inb_p(SMBHSTSTS); | ||
222 | |||
223 | /* Make sure the SMBus host is ready to start transmitting */ | ||
224 | /* Check the busy bit first */ | ||
225 | if (temp & ALI1535_STS_BUSY) { | ||
226 | /* If the host controller is still busy, it may have timed out | ||
227 | * in the previous transaction, resulting in a "SMBus Timeout" | ||
228 | * printk. I've tried the following to reset a stuck busy bit. | ||
229 | * 1. Reset the controller with an KILL command. (this | ||
230 | * doesn't seem to clear the controller if an external | ||
231 | * device is hung) | ||
232 | * 2. Reset the controller and the other SMBus devices with a | ||
233 | * T_OUT command. (this clears the host busy bit if an | ||
234 | * external device is hung, but it comes back upon a new | ||
235 | * access to a device) | ||
236 | * 3. Disable and reenable the controller in SMBHSTCFG. Worst | ||
237 | * case, nothing seems to work except power reset. | ||
238 | */ | ||
239 | |||
240 | /* Try resetting entire SMB bus, including other devices - This | ||
241 | * may not work either - it clears the BUSY bit but then the | ||
242 | * BUSY bit may come back on when you try and use the chip | ||
243 | * again. If that's the case you are stuck. | ||
244 | */ | ||
245 | dev_info(&adap->dev, | ||
246 | "Resetting entire SMB Bus to clear busy condition (%02x)\n", | ||
247 | temp); | ||
248 | outb_p(ALI1535_T_OUT, SMBHSTTYP); | ||
249 | temp = inb_p(SMBHSTSTS); | ||
250 | } | ||
251 | |||
252 | /* now check the error bits and the busy bit */ | ||
253 | if (temp & (ALI1535_STS_ERR | ALI1535_STS_BUSY)) { | ||
254 | /* do a clear-on-write */ | ||
255 | outb_p(0xFF, SMBHSTSTS); | ||
256 | if ((temp = inb_p(SMBHSTSTS)) & | ||
257 | (ALI1535_STS_ERR | ALI1535_STS_BUSY)) { | ||
258 | /* This is probably going to be correctable only by a | ||
259 | * power reset as one of the bits now appears to be | ||
260 | * stuck */ | ||
261 | /* This may be a bus or device with electrical problems. */ | ||
262 | dev_err(&adap->dev, | ||
263 | "SMBus reset failed! (0x%02x) - controller or " | ||
264 | "device on bus is probably hung\n", temp); | ||
265 | return -1; | ||
266 | } | ||
267 | } else { | ||
268 | /* check and clear done bit */ | ||
269 | if (temp & ALI1535_STS_DONE) { | ||
270 | outb_p(temp, SMBHSTSTS); | ||
271 | } | ||
272 | } | ||
273 | |||
274 | /* start the transaction by writing anything to the start register */ | ||
275 | outb_p(0xFF, SMBHSTPORT); | ||
276 | |||
277 | /* We will always wait for a fraction of a second! */ | ||
278 | timeout = 0; | ||
279 | do { | ||
280 | msleep(1); | ||
281 | temp = inb_p(SMBHSTSTS); | ||
282 | } while (((temp & ALI1535_STS_BUSY) && !(temp & ALI1535_STS_IDLE)) | ||
283 | && (timeout++ < MAX_TIMEOUT)); | ||
284 | |||
285 | /* If the SMBus is still busy, we give up */ | ||
286 | if (timeout >= MAX_TIMEOUT) { | ||
287 | result = -1; | ||
288 | dev_err(&adap->dev, "SMBus Timeout!\n"); | ||
289 | } | ||
290 | |||
291 | if (temp & ALI1535_STS_FAIL) { | ||
292 | result = -1; | ||
293 | dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); | ||
294 | } | ||
295 | |||
296 | /* Unfortunately the ALI SMB controller maps "no response" and "bus | ||
297 | * collision" into a single bit. No reponse is the usual case so don't | ||
298 | * do a printk. This means that bus collisions go unreported. | ||
299 | */ | ||
300 | if (temp & ALI1535_STS_BUSERR) { | ||
301 | result = -1; | ||
302 | dev_dbg(&adap->dev, | ||
303 | "Error: no response or bus collision ADD=%02x\n", | ||
304 | inb_p(SMBHSTADD)); | ||
305 | } | ||
306 | |||
307 | /* haven't ever seen this */ | ||
308 | if (temp & ALI1535_STS_DEV) { | ||
309 | result = -1; | ||
310 | dev_err(&adap->dev, "Error: device error\n"); | ||
311 | } | ||
312 | |||
313 | /* check to see if the "command complete" indication is set */ | ||
314 | if (!(temp & ALI1535_STS_DONE)) { | ||
315 | result = -1; | ||
316 | dev_err(&adap->dev, "Error: command never completed\n"); | ||
317 | } | ||
318 | |||
319 | dev_dbg(&adap->dev, "Transaction (post): STS=%02x, TYP=%02x, " | ||
320 | "CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", | ||
321 | inb_p(SMBHSTSTS), inb_p(SMBHSTTYP), inb_p(SMBHSTCMD), | ||
322 | inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); | ||
323 | |||
324 | /* take consequent actions for error conditions */ | ||
325 | if (!(temp & ALI1535_STS_DONE)) { | ||
326 | /* issue "kill" to reset host controller */ | ||
327 | outb_p(ALI1535_KILL,SMBHSTTYP); | ||
328 | outb_p(0xFF,SMBHSTSTS); | ||
329 | } else if (temp & ALI1535_STS_ERR) { | ||
330 | /* issue "timeout" to reset all devices on bus */ | ||
331 | outb_p(ALI1535_T_OUT,SMBHSTTYP); | ||
332 | outb_p(0xFF,SMBHSTSTS); | ||
333 | } | ||
334 | |||
335 | return result; | ||
336 | } | ||
337 | |||
338 | /* Return -1 on error. */ | ||
339 | static s32 ali1535_access(struct i2c_adapter *adap, u16 addr, | ||
340 | unsigned short flags, char read_write, u8 command, | ||
341 | int size, union i2c_smbus_data *data) | ||
342 | { | ||
343 | int i, len; | ||
344 | int temp; | ||
345 | int timeout; | ||
346 | s32 result = 0; | ||
347 | |||
348 | down(&i2c_ali1535_sem); | ||
349 | /* make sure SMBus is idle */ | ||
350 | temp = inb_p(SMBHSTSTS); | ||
351 | for (timeout = 0; | ||
352 | (timeout < MAX_TIMEOUT) && !(temp & ALI1535_STS_IDLE); | ||
353 | timeout++) { | ||
354 | msleep(1); | ||
355 | temp = inb_p(SMBHSTSTS); | ||
356 | } | ||
357 | if (timeout >= MAX_TIMEOUT) | ||
358 | dev_warn(&adap->dev, "Idle wait Timeout! STS=0x%02x\n", temp); | ||
359 | |||
360 | /* clear status register (clear-on-write) */ | ||
361 | outb_p(0xFF, SMBHSTSTS); | ||
362 | |||
363 | switch (size) { | ||
364 | case I2C_SMBUS_PROC_CALL: | ||
365 | dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n"); | ||
366 | result = -1; | ||
367 | goto EXIT; | ||
368 | case I2C_SMBUS_QUICK: | ||
369 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
370 | SMBHSTADD); | ||
371 | size = ALI1535_QUICK; | ||
372 | outb_p(size, SMBHSTTYP); /* output command */ | ||
373 | break; | ||
374 | case I2C_SMBUS_BYTE: | ||
375 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
376 | SMBHSTADD); | ||
377 | size = ALI1535_BYTE; | ||
378 | outb_p(size, SMBHSTTYP); /* output command */ | ||
379 | if (read_write == I2C_SMBUS_WRITE) | ||
380 | outb_p(command, SMBHSTCMD); | ||
381 | break; | ||
382 | case I2C_SMBUS_BYTE_DATA: | ||
383 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
384 | SMBHSTADD); | ||
385 | size = ALI1535_BYTE_DATA; | ||
386 | outb_p(size, SMBHSTTYP); /* output command */ | ||
387 | outb_p(command, SMBHSTCMD); | ||
388 | if (read_write == I2C_SMBUS_WRITE) | ||
389 | outb_p(data->byte, SMBHSTDAT0); | ||
390 | break; | ||
391 | case I2C_SMBUS_WORD_DATA: | ||
392 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
393 | SMBHSTADD); | ||
394 | size = ALI1535_WORD_DATA; | ||
395 | outb_p(size, SMBHSTTYP); /* output command */ | ||
396 | outb_p(command, SMBHSTCMD); | ||
397 | if (read_write == I2C_SMBUS_WRITE) { | ||
398 | outb_p(data->word & 0xff, SMBHSTDAT0); | ||
399 | outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); | ||
400 | } | ||
401 | break; | ||
402 | case I2C_SMBUS_BLOCK_DATA: | ||
403 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
404 | SMBHSTADD); | ||
405 | size = ALI1535_BLOCK_DATA; | ||
406 | outb_p(size, SMBHSTTYP); /* output command */ | ||
407 | outb_p(command, SMBHSTCMD); | ||
408 | if (read_write == I2C_SMBUS_WRITE) { | ||
409 | len = data->block[0]; | ||
410 | if (len < 0) { | ||
411 | len = 0; | ||
412 | data->block[0] = len; | ||
413 | } | ||
414 | if (len > 32) { | ||
415 | len = 32; | ||
416 | data->block[0] = len; | ||
417 | } | ||
418 | outb_p(len, SMBHSTDAT0); | ||
419 | /* Reset SMBBLKDAT */ | ||
420 | outb_p(inb_p(SMBHSTTYP) | ALI1535_BLOCK_CLR, SMBHSTTYP); | ||
421 | for (i = 1; i <= len; i++) | ||
422 | outb_p(data->block[i], SMBBLKDAT); | ||
423 | } | ||
424 | break; | ||
425 | } | ||
426 | |||
427 | if (ali1535_transaction(adap)) { | ||
428 | /* Error in transaction */ | ||
429 | result = -1; | ||
430 | goto EXIT; | ||
431 | } | ||
432 | |||
433 | if ((read_write == I2C_SMBUS_WRITE) || (size == ALI1535_QUICK)) { | ||
434 | result = 0; | ||
435 | goto EXIT; | ||
436 | } | ||
437 | |||
438 | switch (size) { | ||
439 | case ALI1535_BYTE: /* Result put in SMBHSTDAT0 */ | ||
440 | data->byte = inb_p(SMBHSTDAT0); | ||
441 | break; | ||
442 | case ALI1535_BYTE_DATA: | ||
443 | data->byte = inb_p(SMBHSTDAT0); | ||
444 | break; | ||
445 | case ALI1535_WORD_DATA: | ||
446 | data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); | ||
447 | break; | ||
448 | case ALI1535_BLOCK_DATA: | ||
449 | len = inb_p(SMBHSTDAT0); | ||
450 | if (len > 32) | ||
451 | len = 32; | ||
452 | data->block[0] = len; | ||
453 | /* Reset SMBBLKDAT */ | ||
454 | outb_p(inb_p(SMBHSTTYP) | ALI1535_BLOCK_CLR, SMBHSTTYP); | ||
455 | for (i = 1; i <= data->block[0]; i++) { | ||
456 | data->block[i] = inb_p(SMBBLKDAT); | ||
457 | dev_dbg(&adap->dev, "Blk: len=%d, i=%d, data=%02x\n", | ||
458 | len, i, data->block[i]); | ||
459 | } | ||
460 | break; | ||
461 | } | ||
462 | EXIT: | ||
463 | up(&i2c_ali1535_sem); | ||
464 | return result; | ||
465 | } | ||
466 | |||
467 | |||
468 | static u32 ali1535_func(struct i2c_adapter *adapter) | ||
469 | { | ||
470 | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | | ||
471 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | | ||
472 | I2C_FUNC_SMBUS_BLOCK_DATA; | ||
473 | } | ||
474 | |||
475 | static struct i2c_algorithm smbus_algorithm = { | ||
476 | .name = "Non-i2c SMBus adapter", | ||
477 | .id = I2C_ALGO_SMBUS, | ||
478 | .smbus_xfer = ali1535_access, | ||
479 | .functionality = ali1535_func, | ||
480 | }; | ||
481 | |||
482 | static struct i2c_adapter ali1535_adapter = { | ||
483 | .owner = THIS_MODULE, | ||
484 | .class = I2C_CLASS_HWMON, | ||
485 | .algo = &smbus_algorithm, | ||
486 | .name = "unset", | ||
487 | }; | ||
488 | |||
489 | static struct pci_device_id ali1535_ids[] = { | ||
490 | { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) }, | ||
491 | { }, | ||
492 | }; | ||
493 | |||
494 | MODULE_DEVICE_TABLE (pci, ali1535_ids); | ||
495 | |||
496 | static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id) | ||
497 | { | ||
498 | if (ali1535_setup(dev)) { | ||
499 | dev_warn(&dev->dev, | ||
500 | "ALI1535 not detected, module not inserted.\n"); | ||
501 | return -ENODEV; | ||
502 | } | ||
503 | |||
504 | /* set up the driverfs linkage to our parent device */ | ||
505 | ali1535_adapter.dev.parent = &dev->dev; | ||
506 | |||
507 | snprintf(ali1535_adapter.name, I2C_NAME_SIZE, | ||
508 | "SMBus ALI1535 adapter at %04x", ali1535_smba); | ||
509 | return i2c_add_adapter(&ali1535_adapter); | ||
510 | } | ||
511 | |||
512 | static void __devexit ali1535_remove(struct pci_dev *dev) | ||
513 | { | ||
514 | i2c_del_adapter(&ali1535_adapter); | ||
515 | release_region(ali1535_smba, ALI1535_SMB_IOSIZE); | ||
516 | } | ||
517 | |||
518 | static struct pci_driver ali1535_driver = { | ||
519 | .name = "ali1535_smbus", | ||
520 | .id_table = ali1535_ids, | ||
521 | .probe = ali1535_probe, | ||
522 | .remove = __devexit_p(ali1535_remove), | ||
523 | }; | ||
524 | |||
525 | static int __init i2c_ali1535_init(void) | ||
526 | { | ||
527 | return pci_register_driver(&ali1535_driver); | ||
528 | } | ||
529 | |||
530 | static void __exit i2c_ali1535_exit(void) | ||
531 | { | ||
532 | pci_unregister_driver(&ali1535_driver); | ||
533 | } | ||
534 | |||
535 | MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, " | ||
536 | "Philip Edelbrock <phil@netroedge.com>, " | ||
537 | "Mark D. Studebaker <mdsxyz123@yahoo.com> " | ||
538 | "and Dan Eaton <dan.eaton@rocketlogix.com>"); | ||
539 | MODULE_DESCRIPTION("ALI1535 SMBus driver"); | ||
540 | MODULE_LICENSE("GPL"); | ||
541 | |||
542 | module_init(i2c_ali1535_init); | ||
543 | module_exit(i2c_ali1535_exit); | ||
diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c new file mode 100644 index 000000000000..35710818fe47 --- /dev/null +++ b/drivers/i2c/busses/i2c-ali1563.c | |||
@@ -0,0 +1,415 @@ | |||
1 | /** | ||
2 | * i2c-ali1563.c - i2c driver for the ALi 1563 Southbridge | ||
3 | * | ||
4 | * Copyright (C) 2004 Patrick Mochel | ||
5 | * | ||
6 | * The 1563 southbridge is deceptively similar to the 1533, with a | ||
7 | * few notable exceptions. One of those happens to be the fact they | ||
8 | * upgraded the i2c core to be 2.0 compliant, and happens to be almost | ||
9 | * identical to the i2c controller found in the Intel 801 south | ||
10 | * bridges. | ||
11 | * | ||
12 | * This driver is based on a mix of the 15x3, 1535, and i801 drivers, | ||
13 | * with a little help from the ALi 1563 spec. | ||
14 | * | ||
15 | * This file is released under the GPLv2 | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/pci.h> | ||
22 | #include <linux/init.h> | ||
23 | |||
24 | #define ALI1563_MAX_TIMEOUT 500 | ||
25 | #define ALI1563_SMBBA 0x80 | ||
26 | #define ALI1563_SMB_IOEN 1 | ||
27 | #define ALI1563_SMB_HOSTEN 2 | ||
28 | #define ALI1563_SMB_IOSIZE 16 | ||
29 | |||
30 | #define SMB_HST_STS (ali1563_smba + 0) | ||
31 | #define SMB_HST_CNTL1 (ali1563_smba + 1) | ||
32 | #define SMB_HST_CNTL2 (ali1563_smba + 2) | ||
33 | #define SMB_HST_CMD (ali1563_smba + 3) | ||
34 | #define SMB_HST_ADD (ali1563_smba + 4) | ||
35 | #define SMB_HST_DAT0 (ali1563_smba + 5) | ||
36 | #define SMB_HST_DAT1 (ali1563_smba + 6) | ||
37 | #define SMB_BLK_DAT (ali1563_smba + 7) | ||
38 | |||
39 | #define HST_STS_BUSY 0x01 | ||
40 | #define HST_STS_INTR 0x02 | ||
41 | #define HST_STS_DEVERR 0x04 | ||
42 | #define HST_STS_BUSERR 0x08 | ||
43 | #define HST_STS_FAIL 0x10 | ||
44 | #define HST_STS_DONE 0x80 | ||
45 | #define HST_STS_BAD 0x1c | ||
46 | |||
47 | |||
48 | #define HST_CNTL1_TIMEOUT 0x80 | ||
49 | #define HST_CNTL1_LAST 0x40 | ||
50 | |||
51 | #define HST_CNTL2_KILL 0x04 | ||
52 | #define HST_CNTL2_START 0x40 | ||
53 | #define HST_CNTL2_QUICK 0x00 | ||
54 | #define HST_CNTL2_BYTE 0x01 | ||
55 | #define HST_CNTL2_BYTE_DATA 0x02 | ||
56 | #define HST_CNTL2_WORD_DATA 0x03 | ||
57 | #define HST_CNTL2_BLOCK 0x05 | ||
58 | |||
59 | |||
60 | |||
61 | static unsigned short ali1563_smba; | ||
62 | |||
63 | static int ali1563_transaction(struct i2c_adapter * a) | ||
64 | { | ||
65 | u32 data; | ||
66 | int timeout; | ||
67 | |||
68 | dev_dbg(&a->dev, "Transaction (pre): STS=%02x, CNTL1=%02x, " | ||
69 | "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", | ||
70 | inb_p(SMB_HST_STS), inb_p(SMB_HST_CNTL1), inb_p(SMB_HST_CNTL2), | ||
71 | inb_p(SMB_HST_CMD), inb_p(SMB_HST_ADD), inb_p(SMB_HST_DAT0), | ||
72 | inb_p(SMB_HST_DAT1)); | ||
73 | |||
74 | data = inb_p(SMB_HST_STS); | ||
75 | if (data & HST_STS_BAD) { | ||
76 | dev_warn(&a->dev,"ali1563: Trying to reset busy device\n"); | ||
77 | outb_p(data | HST_STS_BAD,SMB_HST_STS); | ||
78 | data = inb_p(SMB_HST_STS); | ||
79 | if (data & HST_STS_BAD) | ||
80 | return -EBUSY; | ||
81 | } | ||
82 | outb_p(inb_p(SMB_HST_CNTL2) | HST_CNTL2_START, SMB_HST_CNTL2); | ||
83 | |||
84 | timeout = ALI1563_MAX_TIMEOUT; | ||
85 | do | ||
86 | msleep(1); | ||
87 | while (((data = inb_p(SMB_HST_STS)) & HST_STS_BUSY) && --timeout); | ||
88 | |||
89 | dev_dbg(&a->dev, "Transaction (post): STS=%02x, CNTL1=%02x, " | ||
90 | "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", | ||
91 | inb_p(SMB_HST_STS), inb_p(SMB_HST_CNTL1), inb_p(SMB_HST_CNTL2), | ||
92 | inb_p(SMB_HST_CMD), inb_p(SMB_HST_ADD), inb_p(SMB_HST_DAT0), | ||
93 | inb_p(SMB_HST_DAT1)); | ||
94 | |||
95 | if (timeout && !(data & HST_STS_BAD)) | ||
96 | return 0; | ||
97 | dev_warn(&a->dev, "SMBus Error: %s%s%s%s%s\n", | ||
98 | timeout ? "Timeout " : "", | ||
99 | data & HST_STS_FAIL ? "Transaction Failed " : "", | ||
100 | data & HST_STS_BUSERR ? "No response or Bus Collision " : "", | ||
101 | data & HST_STS_DEVERR ? "Device Error " : "", | ||
102 | !(data & HST_STS_DONE) ? "Transaction Never Finished " : ""); | ||
103 | |||
104 | if (!(data & HST_STS_DONE)) | ||
105 | /* Issue 'kill' to host controller */ | ||
106 | outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2); | ||
107 | else | ||
108 | /* Issue timeout to reset all devices on bus */ | ||
109 | outb_p(HST_CNTL1_TIMEOUT,SMB_HST_CNTL1); | ||
110 | return -1; | ||
111 | } | ||
112 | |||
113 | static int ali1563_block_start(struct i2c_adapter * a) | ||
114 | { | ||
115 | u32 data; | ||
116 | int timeout; | ||
117 | |||
118 | dev_dbg(&a->dev, "Block (pre): STS=%02x, CNTL1=%02x, " | ||
119 | "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", | ||
120 | inb_p(SMB_HST_STS), inb_p(SMB_HST_CNTL1), inb_p(SMB_HST_CNTL2), | ||
121 | inb_p(SMB_HST_CMD), inb_p(SMB_HST_ADD), inb_p(SMB_HST_DAT0), | ||
122 | inb_p(SMB_HST_DAT1)); | ||
123 | |||
124 | data = inb_p(SMB_HST_STS); | ||
125 | if (data & HST_STS_BAD) { | ||
126 | dev_warn(&a->dev,"ali1563: Trying to reset busy device\n"); | ||
127 | outb_p(data | HST_STS_BAD,SMB_HST_STS); | ||
128 | data = inb_p(SMB_HST_STS); | ||
129 | if (data & HST_STS_BAD) | ||
130 | return -EBUSY; | ||
131 | } | ||
132 | |||
133 | /* Clear byte-ready bit */ | ||
134 | outb_p(data | HST_STS_DONE, SMB_HST_STS); | ||
135 | |||
136 | /* Start transaction and wait for byte-ready bit to be set */ | ||
137 | outb_p(inb_p(SMB_HST_CNTL2) | HST_CNTL2_START, SMB_HST_CNTL2); | ||
138 | |||
139 | timeout = ALI1563_MAX_TIMEOUT; | ||
140 | do | ||
141 | msleep(1); | ||
142 | while (!((data = inb_p(SMB_HST_STS)) & HST_STS_DONE) && --timeout); | ||
143 | |||
144 | dev_dbg(&a->dev, "Block (post): STS=%02x, CNTL1=%02x, " | ||
145 | "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", | ||
146 | inb_p(SMB_HST_STS), inb_p(SMB_HST_CNTL1), inb_p(SMB_HST_CNTL2), | ||
147 | inb_p(SMB_HST_CMD), inb_p(SMB_HST_ADD), inb_p(SMB_HST_DAT0), | ||
148 | inb_p(SMB_HST_DAT1)); | ||
149 | |||
150 | if (timeout && !(data & HST_STS_BAD)) | ||
151 | return 0; | ||
152 | dev_warn(&a->dev, "SMBus Error: %s%s%s%s%s\n", | ||
153 | timeout ? "Timeout " : "", | ||
154 | data & HST_STS_FAIL ? "Transaction Failed " : "", | ||
155 | data & HST_STS_BUSERR ? "No response or Bus Collision " : "", | ||
156 | data & HST_STS_DEVERR ? "Device Error " : "", | ||
157 | !(data & HST_STS_DONE) ? "Transaction Never Finished " : ""); | ||
158 | return -1; | ||
159 | } | ||
160 | |||
161 | static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8 rw) | ||
162 | { | ||
163 | int i, len; | ||
164 | int error = 0; | ||
165 | |||
166 | /* Do we need this? */ | ||
167 | outb_p(HST_CNTL1_LAST,SMB_HST_CNTL1); | ||
168 | |||
169 | if (rw == I2C_SMBUS_WRITE) { | ||
170 | len = data->block[0]; | ||
171 | if (len < 1) | ||
172 | len = 1; | ||
173 | else if (len > 32) | ||
174 | len = 32; | ||
175 | outb_p(len,SMB_HST_DAT0); | ||
176 | outb_p(data->block[1],SMB_BLK_DAT); | ||
177 | } else | ||
178 | len = 32; | ||
179 | |||
180 | outb_p(inb_p(SMB_HST_CNTL2) | HST_CNTL2_BLOCK, SMB_HST_CNTL2); | ||
181 | |||
182 | for (i = 0; i < len; i++) { | ||
183 | if (rw == I2C_SMBUS_WRITE) { | ||
184 | outb_p(data->block[i + 1], SMB_BLK_DAT); | ||
185 | if ((error = ali1563_block_start(a))) | ||
186 | break; | ||
187 | } else { | ||
188 | if ((error = ali1563_block_start(a))) | ||
189 | break; | ||
190 | if (i == 0) { | ||
191 | len = inb_p(SMB_HST_DAT0); | ||
192 | if (len < 1) | ||
193 | len = 1; | ||
194 | else if (len > 32) | ||
195 | len = 32; | ||
196 | } | ||
197 | data->block[i+1] = inb_p(SMB_BLK_DAT); | ||
198 | } | ||
199 | } | ||
200 | /* Do we need this? */ | ||
201 | outb_p(HST_CNTL1_LAST,SMB_HST_CNTL1); | ||
202 | return error; | ||
203 | } | ||
204 | |||
205 | static s32 ali1563_access(struct i2c_adapter * a, u16 addr, | ||
206 | unsigned short flags, char rw, u8 cmd, | ||
207 | int size, union i2c_smbus_data * data) | ||
208 | { | ||
209 | int error = 0; | ||
210 | int timeout; | ||
211 | u32 reg; | ||
212 | |||
213 | for (timeout = ALI1563_MAX_TIMEOUT; timeout; timeout--) { | ||
214 | if (!(reg = inb_p(SMB_HST_STS) & HST_STS_BUSY)) | ||
215 | break; | ||
216 | } | ||
217 | if (!timeout) | ||
218 | dev_warn(&a->dev,"SMBus not idle. HST_STS = %02x\n",reg); | ||
219 | outb_p(0xff,SMB_HST_STS); | ||
220 | |||
221 | /* Map the size to what the chip understands */ | ||
222 | switch (size) { | ||
223 | case I2C_SMBUS_PROC_CALL: | ||
224 | dev_err(&a->dev, "I2C_SMBUS_PROC_CALL not supported!\n"); | ||
225 | error = -EINVAL; | ||
226 | break; | ||
227 | case I2C_SMBUS_QUICK: | ||
228 | size = HST_CNTL2_QUICK; | ||
229 | break; | ||
230 | case I2C_SMBUS_BYTE: | ||
231 | size = HST_CNTL2_BYTE; | ||
232 | break; | ||
233 | case I2C_SMBUS_BYTE_DATA: | ||
234 | size = HST_CNTL2_BYTE_DATA; | ||
235 | break; | ||
236 | case I2C_SMBUS_WORD_DATA: | ||
237 | size = HST_CNTL2_WORD_DATA; | ||
238 | break; | ||
239 | case I2C_SMBUS_BLOCK_DATA: | ||
240 | size = HST_CNTL2_BLOCK; | ||
241 | break; | ||
242 | } | ||
243 | |||
244 | outb_p(((addr & 0x7f) << 1) | (rw & 0x01), SMB_HST_ADD); | ||
245 | outb_p(inb_p(SMB_HST_CNTL2) | (size << 3), SMB_HST_CNTL2); | ||
246 | |||
247 | /* Write the command register */ | ||
248 | switch(size) { | ||
249 | case HST_CNTL2_BYTE: | ||
250 | if (rw== I2C_SMBUS_WRITE) | ||
251 | outb_p(cmd, SMB_HST_CMD); | ||
252 | break; | ||
253 | case HST_CNTL2_BYTE_DATA: | ||
254 | outb_p(cmd, SMB_HST_CMD); | ||
255 | if (rw == I2C_SMBUS_WRITE) | ||
256 | outb_p(data->byte, SMB_HST_DAT0); | ||
257 | break; | ||
258 | case HST_CNTL2_WORD_DATA: | ||
259 | outb_p(cmd, SMB_HST_CMD); | ||
260 | if (rw == I2C_SMBUS_WRITE) { | ||
261 | outb_p(data->word & 0xff, SMB_HST_DAT0); | ||
262 | outb_p((data->word & 0xff00) >> 8, SMB_HST_DAT1); | ||
263 | } | ||
264 | break; | ||
265 | case HST_CNTL2_BLOCK: | ||
266 | outb_p(cmd, SMB_HST_CMD); | ||
267 | error = ali1563_block(a,data,rw); | ||
268 | goto Done; | ||
269 | } | ||
270 | |||
271 | if ((error = ali1563_transaction(a))) | ||
272 | goto Done; | ||
273 | |||
274 | if ((rw == I2C_SMBUS_WRITE) || (size == HST_CNTL2_QUICK)) | ||
275 | goto Done; | ||
276 | |||
277 | switch (size) { | ||
278 | case HST_CNTL2_BYTE: /* Result put in SMBHSTDAT0 */ | ||
279 | data->byte = inb_p(SMB_HST_DAT0); | ||
280 | break; | ||
281 | case HST_CNTL2_BYTE_DATA: | ||
282 | data->byte = inb_p(SMB_HST_DAT0); | ||
283 | break; | ||
284 | case HST_CNTL2_WORD_DATA: | ||
285 | data->word = inb_p(SMB_HST_DAT0) + (inb_p(SMB_HST_DAT1) << 8); | ||
286 | break; | ||
287 | } | ||
288 | Done: | ||
289 | return error; | ||
290 | } | ||
291 | |||
292 | static u32 ali1563_func(struct i2c_adapter * a) | ||
293 | { | ||
294 | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | | ||
295 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | | ||
296 | I2C_FUNC_SMBUS_BLOCK_DATA; | ||
297 | } | ||
298 | |||
299 | |||
300 | static void ali1563_enable(struct pci_dev * dev) | ||
301 | { | ||
302 | u16 ctrl; | ||
303 | |||
304 | pci_read_config_word(dev,ALI1563_SMBBA,&ctrl); | ||
305 | ctrl |= 0x7; | ||
306 | pci_write_config_word(dev,ALI1563_SMBBA,ctrl); | ||
307 | } | ||
308 | |||
309 | static int __devinit ali1563_setup(struct pci_dev * dev) | ||
310 | { | ||
311 | u16 ctrl; | ||
312 | |||
313 | pci_read_config_word(dev,ALI1563_SMBBA,&ctrl); | ||
314 | printk("ali1563: SMBus control = %04x\n",ctrl); | ||
315 | |||
316 | /* Check if device is even enabled first */ | ||
317 | if (!(ctrl & ALI1563_SMB_IOEN)) { | ||
318 | dev_warn(&dev->dev,"I/O space not enabled, trying manually\n"); | ||
319 | ali1563_enable(dev); | ||
320 | } | ||
321 | if (!(ctrl & ALI1563_SMB_IOEN)) { | ||
322 | dev_warn(&dev->dev,"I/O space still not enabled, giving up\n"); | ||
323 | goto Err; | ||
324 | } | ||
325 | if (!(ctrl & ALI1563_SMB_HOSTEN)) { | ||
326 | dev_warn(&dev->dev,"Host Controller not enabled\n"); | ||
327 | goto Err; | ||
328 | } | ||
329 | |||
330 | /* SMB I/O Base in high 12 bits and must be aligned with the | ||
331 | * size of the I/O space. */ | ||
332 | ali1563_smba = ctrl & ~(ALI1563_SMB_IOSIZE - 1); | ||
333 | if (!ali1563_smba) { | ||
334 | dev_warn(&dev->dev,"ali1563_smba Uninitialized\n"); | ||
335 | goto Err; | ||
336 | } | ||
337 | if (!request_region(ali1563_smba,ALI1563_SMB_IOSIZE,"i2c-ali1563")) { | ||
338 | dev_warn(&dev->dev,"Could not allocate I/O space"); | ||
339 | goto Err; | ||
340 | } | ||
341 | |||
342 | return 0; | ||
343 | Err: | ||
344 | return -ENODEV; | ||
345 | } | ||
346 | |||
347 | static void ali1563_shutdown(struct pci_dev *dev) | ||
348 | { | ||
349 | release_region(ali1563_smba,ALI1563_SMB_IOSIZE); | ||
350 | } | ||
351 | |||
352 | static struct i2c_algorithm ali1563_algorithm = { | ||
353 | .name = "Non-i2c SMBus adapter", | ||
354 | .id = I2C_ALGO_SMBUS, | ||
355 | .smbus_xfer = ali1563_access, | ||
356 | .functionality = ali1563_func, | ||
357 | }; | ||
358 | |||
359 | static struct i2c_adapter ali1563_adapter = { | ||
360 | .owner = THIS_MODULE, | ||
361 | .class = I2C_CLASS_HWMON, | ||
362 | .algo = &ali1563_algorithm, | ||
363 | }; | ||
364 | |||
365 | static int __devinit ali1563_probe(struct pci_dev * dev, | ||
366 | const struct pci_device_id * id_table) | ||
367 | { | ||
368 | int error; | ||
369 | |||
370 | if ((error = ali1563_setup(dev))) | ||
371 | return error; | ||
372 | ali1563_adapter.dev.parent = &dev->dev; | ||
373 | sprintf(ali1563_adapter.name,"SMBus ALi 1563 Adapter @ %04x", | ||
374 | ali1563_smba); | ||
375 | if ((error = i2c_add_adapter(&ali1563_adapter))) | ||
376 | ali1563_shutdown(dev); | ||
377 | printk("%s: Returning %d\n",__FUNCTION__,error); | ||
378 | return error; | ||
379 | } | ||
380 | |||
381 | static void __devexit ali1563_remove(struct pci_dev * dev) | ||
382 | { | ||
383 | i2c_del_adapter(&ali1563_adapter); | ||
384 | ali1563_shutdown(dev); | ||
385 | } | ||
386 | |||
387 | static struct pci_device_id __devinitdata ali1563_id_table[] = { | ||
388 | { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1563) }, | ||
389 | {}, | ||
390 | }; | ||
391 | |||
392 | MODULE_DEVICE_TABLE (pci, ali1563_id_table); | ||
393 | |||
394 | static struct pci_driver ali1563_pci_driver = { | ||
395 | .name = "ali1563_i2c", | ||
396 | .id_table = ali1563_id_table, | ||
397 | .probe = ali1563_probe, | ||
398 | .remove = __devexit_p(ali1563_remove), | ||
399 | }; | ||
400 | |||
401 | static int __init ali1563_init(void) | ||
402 | { | ||
403 | return pci_register_driver(&ali1563_pci_driver); | ||
404 | } | ||
405 | |||
406 | module_init(ali1563_init); | ||
407 | |||
408 | static void __exit ali1563_exit(void) | ||
409 | { | ||
410 | pci_unregister_driver(&ali1563_pci_driver); | ||
411 | } | ||
412 | |||
413 | module_exit(ali1563_exit); | ||
414 | |||
415 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c new file mode 100644 index 000000000000..5bd6a4a77c1e --- /dev/null +++ b/drivers/i2c/busses/i2c-ali15x3.c | |||
@@ -0,0 +1,532 @@ | |||
1 | /* | ||
2 | ali15x3.c - Part of lm_sensors, Linux kernel modules for hardware | ||
3 | monitoring | ||
4 | Copyright (c) 1999 Frodo Looijaard <frodol@dds.nl> and | ||
5 | Philip Edelbrock <phil@netroedge.com> and | ||
6 | Mark D. Studebaker <mdsxyz123@yahoo.com> | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | This is the driver for the SMB Host controller on | ||
25 | Acer Labs Inc. (ALI) M1541 and M1543C South Bridges. | ||
26 | |||
27 | The M1543C is a South bridge for desktop systems. | ||
28 | The M1533 is a South bridge for portable systems. | ||
29 | They are part of the following ALI chipsets: | ||
30 | "Aladdin Pro 2": Includes the M1621 Slot 1 North bridge | ||
31 | with AGP and 100MHz CPU Front Side bus | ||
32 | "Aladdin V": Includes the M1541 Socket 7 North bridge | ||
33 | with AGP and 100MHz CPU Front Side bus | ||
34 | "Aladdin IV": Includes the M1541 Socket 7 North bridge | ||
35 | with host bus up to 83.3 MHz. | ||
36 | For an overview of these chips see http://www.acerlabs.com | ||
37 | |||
38 | The M1533/M1543C devices appear as FOUR separate devices | ||
39 | on the PCI bus. An output of lspci will show something similar | ||
40 | to the following: | ||
41 | |||
42 | 00:02.0 USB Controller: Acer Laboratories Inc. M5237 | ||
43 | 00:03.0 Bridge: Acer Laboratories Inc. M7101 | ||
44 | 00:07.0 ISA bridge: Acer Laboratories Inc. M1533 | ||
45 | 00:0f.0 IDE interface: Acer Laboratories Inc. M5229 | ||
46 | |||
47 | The SMB controller is part of the 7101 device, which is an | ||
48 | ACPI-compliant Power Management Unit (PMU). | ||
49 | |||
50 | The whole 7101 device has to be enabled for the SMB to work. | ||
51 | You can't just enable the SMB alone. | ||
52 | The SMB and the ACPI have separate I/O spaces. | ||
53 | We make sure that the SMB is enabled. We leave the ACPI alone. | ||
54 | |||
55 | This driver controls the SMB Host only. | ||
56 | The SMB Slave controller on the M15X3 is not enabled. | ||
57 | |||
58 | This driver does not use interrupts. | ||
59 | */ | ||
60 | |||
61 | /* Note: we assume there can only be one ALI15X3, with one SMBus interface */ | ||
62 | |||
63 | #include <linux/config.h> | ||
64 | #include <linux/module.h> | ||
65 | #include <linux/pci.h> | ||
66 | #include <linux/kernel.h> | ||
67 | #include <linux/stddef.h> | ||
68 | #include <linux/sched.h> | ||
69 | #include <linux/ioport.h> | ||
70 | #include <linux/delay.h> | ||
71 | #include <linux/i2c.h> | ||
72 | #include <linux/init.h> | ||
73 | #include <asm/io.h> | ||
74 | |||
75 | /* ALI15X3 SMBus address offsets */ | ||
76 | #define SMBHSTSTS (0 + ali15x3_smba) | ||
77 | #define SMBHSTCNT (1 + ali15x3_smba) | ||
78 | #define SMBHSTSTART (2 + ali15x3_smba) | ||
79 | #define SMBHSTCMD (7 + ali15x3_smba) | ||
80 | #define SMBHSTADD (3 + ali15x3_smba) | ||
81 | #define SMBHSTDAT0 (4 + ali15x3_smba) | ||
82 | #define SMBHSTDAT1 (5 + ali15x3_smba) | ||
83 | #define SMBBLKDAT (6 + ali15x3_smba) | ||
84 | |||
85 | /* PCI Address Constants */ | ||
86 | #define SMBCOM 0x004 | ||
87 | #define SMBBA 0x014 | ||
88 | #define SMBATPC 0x05B /* used to unlock xxxBA registers */ | ||
89 | #define SMBHSTCFG 0x0E0 | ||
90 | #define SMBSLVC 0x0E1 | ||
91 | #define SMBCLK 0x0E2 | ||
92 | #define SMBREV 0x008 | ||
93 | |||
94 | /* Other settings */ | ||
95 | #define MAX_TIMEOUT 200 /* times 1/100 sec */ | ||
96 | #define ALI15X3_SMB_IOSIZE 32 | ||
97 | |||
98 | /* this is what the Award 1004 BIOS sets them to on a ASUS P5A MB. | ||
99 | We don't use these here. If the bases aren't set to some value we | ||
100 | tell user to upgrade BIOS and we fail. | ||
101 | */ | ||
102 | #define ALI15X3_SMB_DEFAULTBASE 0xE800 | ||
103 | |||
104 | /* ALI15X3 address lock bits */ | ||
105 | #define ALI15X3_LOCK 0x06 | ||
106 | |||
107 | /* ALI15X3 command constants */ | ||
108 | #define ALI15X3_ABORT 0x02 | ||
109 | #define ALI15X3_T_OUT 0x04 | ||
110 | #define ALI15X3_QUICK 0x00 | ||
111 | #define ALI15X3_BYTE 0x10 | ||
112 | #define ALI15X3_BYTE_DATA 0x20 | ||
113 | #define ALI15X3_WORD_DATA 0x30 | ||
114 | #define ALI15X3_BLOCK_DATA 0x40 | ||
115 | #define ALI15X3_BLOCK_CLR 0x80 | ||
116 | |||
117 | /* ALI15X3 status register bits */ | ||
118 | #define ALI15X3_STS_IDLE 0x04 | ||
119 | #define ALI15X3_STS_BUSY 0x08 | ||
120 | #define ALI15X3_STS_DONE 0x10 | ||
121 | #define ALI15X3_STS_DEV 0x20 /* device error */ | ||
122 | #define ALI15X3_STS_COLL 0x40 /* collision or no response */ | ||
123 | #define ALI15X3_STS_TERM 0x80 /* terminated by abort */ | ||
124 | #define ALI15X3_STS_ERR 0xE0 /* all the bad error bits */ | ||
125 | |||
126 | |||
127 | /* If force_addr is set to anything different from 0, we forcibly enable | ||
128 | the device at the given address. */ | ||
129 | static u16 force_addr = 0; | ||
130 | module_param(force_addr, ushort, 0); | ||
131 | MODULE_PARM_DESC(force_addr, | ||
132 | "Initialize the base address of the i2c controller"); | ||
133 | |||
134 | static unsigned short ali15x3_smba = 0; | ||
135 | |||
136 | static int ali15x3_setup(struct pci_dev *ALI15X3_dev) | ||
137 | { | ||
138 | u16 a; | ||
139 | unsigned char temp; | ||
140 | |||
141 | /* Check the following things: | ||
142 | - SMB I/O address is initialized | ||
143 | - Device is enabled | ||
144 | - We can use the addresses | ||
145 | */ | ||
146 | |||
147 | /* Unlock the register. | ||
148 | The data sheet says that the address registers are read-only | ||
149 | if the lock bits are 1, but in fact the address registers | ||
150 | are zero unless you clear the lock bits. | ||
151 | */ | ||
152 | pci_read_config_byte(ALI15X3_dev, SMBATPC, &temp); | ||
153 | if (temp & ALI15X3_LOCK) { | ||
154 | temp &= ~ALI15X3_LOCK; | ||
155 | pci_write_config_byte(ALI15X3_dev, SMBATPC, temp); | ||
156 | } | ||
157 | |||
158 | /* Determine the address of the SMBus area */ | ||
159 | pci_read_config_word(ALI15X3_dev, SMBBA, &ali15x3_smba); | ||
160 | ali15x3_smba &= (0xffff & ~(ALI15X3_SMB_IOSIZE - 1)); | ||
161 | if (ali15x3_smba == 0 && force_addr == 0) { | ||
162 | dev_err(&ALI15X3_dev->dev, "ALI15X3_smb region uninitialized " | ||
163 | "- upgrade BIOS or use force_addr=0xaddr\n"); | ||
164 | return -ENODEV; | ||
165 | } | ||
166 | |||
167 | if(force_addr) | ||
168 | ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1); | ||
169 | |||
170 | if (!request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, "ali15x3-smb")) { | ||
171 | dev_err(&ALI15X3_dev->dev, | ||
172 | "ALI15X3_smb region 0x%x already in use!\n", | ||
173 | ali15x3_smba); | ||
174 | return -ENODEV; | ||
175 | } | ||
176 | |||
177 | if(force_addr) { | ||
178 | dev_info(&ALI15X3_dev->dev, "forcing ISA address 0x%04X\n", | ||
179 | ali15x3_smba); | ||
180 | if (PCIBIOS_SUCCESSFUL != pci_write_config_word(ALI15X3_dev, | ||
181 | SMBBA, | ||
182 | ali15x3_smba)) | ||
183 | goto error; | ||
184 | if (PCIBIOS_SUCCESSFUL != pci_read_config_word(ALI15X3_dev, | ||
185 | SMBBA, &a)) | ||
186 | goto error; | ||
187 | if ((a & ~(ALI15X3_SMB_IOSIZE - 1)) != ali15x3_smba) { | ||
188 | /* make sure it works */ | ||
189 | dev_err(&ALI15X3_dev->dev, | ||
190 | "force address failed - not supported?\n"); | ||
191 | goto error; | ||
192 | } | ||
193 | } | ||
194 | /* check if whole device is enabled */ | ||
195 | pci_read_config_byte(ALI15X3_dev, SMBCOM, &temp); | ||
196 | if ((temp & 1) == 0) { | ||
197 | dev_info(&ALI15X3_dev->dev, "enabling SMBus device\n"); | ||
198 | pci_write_config_byte(ALI15X3_dev, SMBCOM, temp | 0x01); | ||
199 | } | ||
200 | |||
201 | /* Is SMB Host controller enabled? */ | ||
202 | pci_read_config_byte(ALI15X3_dev, SMBHSTCFG, &temp); | ||
203 | if ((temp & 1) == 0) { | ||
204 | dev_info(&ALI15X3_dev->dev, "enabling SMBus controller\n"); | ||
205 | pci_write_config_byte(ALI15X3_dev, SMBHSTCFG, temp | 0x01); | ||
206 | } | ||
207 | |||
208 | /* set SMB clock to 74KHz as recommended in data sheet */ | ||
209 | pci_write_config_byte(ALI15X3_dev, SMBCLK, 0x20); | ||
210 | |||
211 | /* | ||
212 | The interrupt routing for SMB is set up in register 0x77 in the | ||
213 | 1533 ISA Bridge device, NOT in the 7101 device. | ||
214 | Don't bother with finding the 1533 device and reading the register. | ||
215 | if ((....... & 0x0F) == 1) | ||
216 | dev_dbg(&ALI15X3_dev->dev, "ALI15X3 using Interrupt 9 for SMBus.\n"); | ||
217 | */ | ||
218 | pci_read_config_byte(ALI15X3_dev, SMBREV, &temp); | ||
219 | dev_dbg(&ALI15X3_dev->dev, "SMBREV = 0x%X\n", temp); | ||
220 | dev_dbg(&ALI15X3_dev->dev, "iALI15X3_smba = 0x%X\n", ali15x3_smba); | ||
221 | |||
222 | return 0; | ||
223 | error: | ||
224 | release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE); | ||
225 | return -ENODEV; | ||
226 | } | ||
227 | |||
228 | /* Another internally used function */ | ||
229 | static int ali15x3_transaction(struct i2c_adapter *adap) | ||
230 | { | ||
231 | int temp; | ||
232 | int result = 0; | ||
233 | int timeout = 0; | ||
234 | |||
235 | dev_dbg(&adap->dev, "Transaction (pre): STS=%02x, CNT=%02x, CMD=%02x, " | ||
236 | "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS), | ||
237 | inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), | ||
238 | inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); | ||
239 | |||
240 | /* get status */ | ||
241 | temp = inb_p(SMBHSTSTS); | ||
242 | |||
243 | /* Make sure the SMBus host is ready to start transmitting */ | ||
244 | /* Check the busy bit first */ | ||
245 | if (temp & ALI15X3_STS_BUSY) { | ||
246 | /* | ||
247 | If the host controller is still busy, it may have timed out in the | ||
248 | previous transaction, resulting in a "SMBus Timeout" Dev. | ||
249 | I've tried the following to reset a stuck busy bit. | ||
250 | 1. Reset the controller with an ABORT command. | ||
251 | (this doesn't seem to clear the controller if an external | ||
252 | device is hung) | ||
253 | 2. Reset the controller and the other SMBus devices with a | ||
254 | T_OUT command. (this clears the host busy bit if an | ||
255 | external device is hung, but it comes back upon a new access | ||
256 | to a device) | ||
257 | 3. Disable and reenable the controller in SMBHSTCFG | ||
258 | Worst case, nothing seems to work except power reset. | ||
259 | */ | ||
260 | /* Abort - reset the host controller */ | ||
261 | /* | ||
262 | Try resetting entire SMB bus, including other devices - | ||
263 | This may not work either - it clears the BUSY bit but | ||
264 | then the BUSY bit may come back on when you try and use the chip again. | ||
265 | If that's the case you are stuck. | ||
266 | */ | ||
267 | dev_info(&adap->dev, "Resetting entire SMB Bus to " | ||
268 | "clear busy condition (%02x)\n", temp); | ||
269 | outb_p(ALI15X3_T_OUT, SMBHSTCNT); | ||
270 | temp = inb_p(SMBHSTSTS); | ||
271 | } | ||
272 | |||
273 | /* now check the error bits and the busy bit */ | ||
274 | if (temp & (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) { | ||
275 | /* do a clear-on-write */ | ||
276 | outb_p(0xFF, SMBHSTSTS); | ||
277 | if ((temp = inb_p(SMBHSTSTS)) & | ||
278 | (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) { | ||
279 | /* this is probably going to be correctable only by a power reset | ||
280 | as one of the bits now appears to be stuck */ | ||
281 | /* This may be a bus or device with electrical problems. */ | ||
282 | dev_err(&adap->dev, "SMBus reset failed! (0x%02x) - " | ||
283 | "controller or device on bus is probably hung\n", | ||
284 | temp); | ||
285 | return -1; | ||
286 | } | ||
287 | } else { | ||
288 | /* check and clear done bit */ | ||
289 | if (temp & ALI15X3_STS_DONE) { | ||
290 | outb_p(temp, SMBHSTSTS); | ||
291 | } | ||
292 | } | ||
293 | |||
294 | /* start the transaction by writing anything to the start register */ | ||
295 | outb_p(0xFF, SMBHSTSTART); | ||
296 | |||
297 | /* We will always wait for a fraction of a second! */ | ||
298 | timeout = 0; | ||
299 | do { | ||
300 | msleep(1); | ||
301 | temp = inb_p(SMBHSTSTS); | ||
302 | } while ((!(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE))) | ||
303 | && (timeout++ < MAX_TIMEOUT)); | ||
304 | |||
305 | /* If the SMBus is still busy, we give up */ | ||
306 | if (timeout >= MAX_TIMEOUT) { | ||
307 | result = -1; | ||
308 | dev_err(&adap->dev, "SMBus Timeout!\n"); | ||
309 | } | ||
310 | |||
311 | if (temp & ALI15X3_STS_TERM) { | ||
312 | result = -1; | ||
313 | dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); | ||
314 | } | ||
315 | |||
316 | /* | ||
317 | Unfortunately the ALI SMB controller maps "no response" and "bus | ||
318 | collision" into a single bit. No reponse is the usual case so don't | ||
319 | do a printk. | ||
320 | This means that bus collisions go unreported. | ||
321 | */ | ||
322 | if (temp & ALI15X3_STS_COLL) { | ||
323 | result = -1; | ||
324 | dev_dbg(&adap->dev, | ||
325 | "Error: no response or bus collision ADD=%02x\n", | ||
326 | inb_p(SMBHSTADD)); | ||
327 | } | ||
328 | |||
329 | /* haven't ever seen this */ | ||
330 | if (temp & ALI15X3_STS_DEV) { | ||
331 | result = -1; | ||
332 | dev_err(&adap->dev, "Error: device error\n"); | ||
333 | } | ||
334 | dev_dbg(&adap->dev, "Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, " | ||
335 | "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS), | ||
336 | inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), | ||
337 | inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); | ||
338 | return result; | ||
339 | } | ||
340 | |||
341 | /* Return -1 on error. */ | ||
342 | static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, | ||
343 | unsigned short flags, char read_write, u8 command, | ||
344 | int size, union i2c_smbus_data * data) | ||
345 | { | ||
346 | int i, len; | ||
347 | int temp; | ||
348 | int timeout; | ||
349 | |||
350 | /* clear all the bits (clear-on-write) */ | ||
351 | outb_p(0xFF, SMBHSTSTS); | ||
352 | /* make sure SMBus is idle */ | ||
353 | temp = inb_p(SMBHSTSTS); | ||
354 | for (timeout = 0; | ||
355 | (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE); | ||
356 | timeout++) { | ||
357 | msleep(1); | ||
358 | temp = inb_p(SMBHSTSTS); | ||
359 | } | ||
360 | if (timeout >= MAX_TIMEOUT) { | ||
361 | dev_err(&adap->dev, "Idle wait Timeout! STS=0x%02x\n", temp); | ||
362 | } | ||
363 | |||
364 | switch (size) { | ||
365 | case I2C_SMBUS_PROC_CALL: | ||
366 | dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n"); | ||
367 | return -1; | ||
368 | case I2C_SMBUS_QUICK: | ||
369 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
370 | SMBHSTADD); | ||
371 | size = ALI15X3_QUICK; | ||
372 | break; | ||
373 | case I2C_SMBUS_BYTE: | ||
374 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
375 | SMBHSTADD); | ||
376 | if (read_write == I2C_SMBUS_WRITE) | ||
377 | outb_p(command, SMBHSTCMD); | ||
378 | size = ALI15X3_BYTE; | ||
379 | break; | ||
380 | case I2C_SMBUS_BYTE_DATA: | ||
381 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
382 | SMBHSTADD); | ||
383 | outb_p(command, SMBHSTCMD); | ||
384 | if (read_write == I2C_SMBUS_WRITE) | ||
385 | outb_p(data->byte, SMBHSTDAT0); | ||
386 | size = ALI15X3_BYTE_DATA; | ||
387 | break; | ||
388 | case I2C_SMBUS_WORD_DATA: | ||
389 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
390 | SMBHSTADD); | ||
391 | outb_p(command, SMBHSTCMD); | ||
392 | if (read_write == I2C_SMBUS_WRITE) { | ||
393 | outb_p(data->word & 0xff, SMBHSTDAT0); | ||
394 | outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); | ||
395 | } | ||
396 | size = ALI15X3_WORD_DATA; | ||
397 | break; | ||
398 | case I2C_SMBUS_BLOCK_DATA: | ||
399 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
400 | SMBHSTADD); | ||
401 | outb_p(command, SMBHSTCMD); | ||
402 | if (read_write == I2C_SMBUS_WRITE) { | ||
403 | len = data->block[0]; | ||
404 | if (len < 0) { | ||
405 | len = 0; | ||
406 | data->block[0] = len; | ||
407 | } | ||
408 | if (len > 32) { | ||
409 | len = 32; | ||
410 | data->block[0] = len; | ||
411 | } | ||
412 | outb_p(len, SMBHSTDAT0); | ||
413 | /* Reset SMBBLKDAT */ | ||
414 | outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT); | ||
415 | for (i = 1; i <= len; i++) | ||
416 | outb_p(data->block[i], SMBBLKDAT); | ||
417 | } | ||
418 | size = ALI15X3_BLOCK_DATA; | ||
419 | break; | ||
420 | } | ||
421 | |||
422 | outb_p(size, SMBHSTCNT); /* output command */ | ||
423 | |||
424 | if (ali15x3_transaction(adap)) /* Error in transaction */ | ||
425 | return -1; | ||
426 | |||
427 | if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK)) | ||
428 | return 0; | ||
429 | |||
430 | |||
431 | switch (size) { | ||
432 | case ALI15X3_BYTE: /* Result put in SMBHSTDAT0 */ | ||
433 | data->byte = inb_p(SMBHSTDAT0); | ||
434 | break; | ||
435 | case ALI15X3_BYTE_DATA: | ||
436 | data->byte = inb_p(SMBHSTDAT0); | ||
437 | break; | ||
438 | case ALI15X3_WORD_DATA: | ||
439 | data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); | ||
440 | break; | ||
441 | case ALI15X3_BLOCK_DATA: | ||
442 | len = inb_p(SMBHSTDAT0); | ||
443 | if (len > 32) | ||
444 | len = 32; | ||
445 | data->block[0] = len; | ||
446 | /* Reset SMBBLKDAT */ | ||
447 | outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT); | ||
448 | for (i = 1; i <= data->block[0]; i++) { | ||
449 | data->block[i] = inb_p(SMBBLKDAT); | ||
450 | dev_dbg(&adap->dev, "Blk: len=%d, i=%d, data=%02x\n", | ||
451 | len, i, data->block[i]); | ||
452 | } | ||
453 | break; | ||
454 | } | ||
455 | return 0; | ||
456 | } | ||
457 | |||
458 | static u32 ali15x3_func(struct i2c_adapter *adapter) | ||
459 | { | ||
460 | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | | ||
461 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | | ||
462 | I2C_FUNC_SMBUS_BLOCK_DATA; | ||
463 | } | ||
464 | |||
465 | static struct i2c_algorithm smbus_algorithm = { | ||
466 | .name = "Non-I2C SMBus adapter", | ||
467 | .id = I2C_ALGO_SMBUS, | ||
468 | .smbus_xfer = ali15x3_access, | ||
469 | .functionality = ali15x3_func, | ||
470 | }; | ||
471 | |||
472 | static struct i2c_adapter ali15x3_adapter = { | ||
473 | .owner = THIS_MODULE, | ||
474 | .class = I2C_CLASS_HWMON, | ||
475 | .algo = &smbus_algorithm, | ||
476 | .name = "unset", | ||
477 | }; | ||
478 | |||
479 | static struct pci_device_id ali15x3_ids[] = { | ||
480 | { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) }, | ||
481 | { 0, } | ||
482 | }; | ||
483 | |||
484 | MODULE_DEVICE_TABLE (pci, ali15x3_ids); | ||
485 | |||
486 | static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id) | ||
487 | { | ||
488 | if (ali15x3_setup(dev)) { | ||
489 | dev_err(&dev->dev, | ||
490 | "ALI15X3 not detected, module not inserted.\n"); | ||
491 | return -ENODEV; | ||
492 | } | ||
493 | |||
494 | /* set up the driverfs linkage to our parent device */ | ||
495 | ali15x3_adapter.dev.parent = &dev->dev; | ||
496 | |||
497 | snprintf(ali15x3_adapter.name, I2C_NAME_SIZE, | ||
498 | "SMBus ALI15X3 adapter at %04x", ali15x3_smba); | ||
499 | return i2c_add_adapter(&ali15x3_adapter); | ||
500 | } | ||
501 | |||
502 | static void __devexit ali15x3_remove(struct pci_dev *dev) | ||
503 | { | ||
504 | i2c_del_adapter(&ali15x3_adapter); | ||
505 | release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE); | ||
506 | } | ||
507 | |||
508 | static struct pci_driver ali15x3_driver = { | ||
509 | .name = "ali15x3_smbus", | ||
510 | .id_table = ali15x3_ids, | ||
511 | .probe = ali15x3_probe, | ||
512 | .remove = __devexit_p(ali15x3_remove), | ||
513 | }; | ||
514 | |||
515 | static int __init i2c_ali15x3_init(void) | ||
516 | { | ||
517 | return pci_register_driver(&ali15x3_driver); | ||
518 | } | ||
519 | |||
520 | static void __exit i2c_ali15x3_exit(void) | ||
521 | { | ||
522 | pci_unregister_driver(&ali15x3_driver); | ||
523 | } | ||
524 | |||
525 | MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, " | ||
526 | "Philip Edelbrock <phil@netroedge.com>, " | ||
527 | "and Mark D. Studebaker <mdsxyz123@yahoo.com>"); | ||
528 | MODULE_DESCRIPTION("ALI15X3 SMBus driver"); | ||
529 | MODULE_LICENSE("GPL"); | ||
530 | |||
531 | module_init(i2c_ali15x3_init); | ||
532 | module_exit(i2c_ali15x3_exit); | ||
diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c new file mode 100644 index 000000000000..4e553e8c5cba --- /dev/null +++ b/drivers/i2c/busses/i2c-amd756-s4882.c | |||
@@ -0,0 +1,264 @@ | |||
1 | /* | ||
2 | * i2c-amd756-s4882.c - i2c-amd756 extras for the Tyan S4882 motherboard | ||
3 | * | ||
4 | * Copyright (C) 2004 Jean Delvare <khali@linux-fr.org> | ||
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 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | * We select the channels by sending commands to the Philips | ||
23 | * PCA9556 chip at I2C address 0x18. The main adapter is used for | ||
24 | * the non-multiplexed part of the bus, and 4 virtual adapters | ||
25 | * are defined for the multiplexed addresses: 0x50-0x53 (memory | ||
26 | * module EEPROM) located on channels 1-4, and 0x4c (LM63) | ||
27 | * located on multiplexed channels 0 and 5-7. We define one | ||
28 | * virtual adapter per CPU, which corresponds to two multiplexed | ||
29 | * channels: | ||
30 | * CPU0: virtual adapter 1, channels 1 and 0 | ||
31 | * CPU1: virtual adapter 2, channels 2 and 5 | ||
32 | * CPU2: virtual adapter 3, channels 3 and 6 | ||
33 | * CPU3: virtual adapter 4, channels 4 and 7 | ||
34 | */ | ||
35 | |||
36 | #include <linux/module.h> | ||
37 | #include <linux/kernel.h> | ||
38 | #include <linux/slab.h> | ||
39 | #include <linux/init.h> | ||
40 | #include <linux/i2c.h> | ||
41 | |||
42 | extern struct i2c_adapter amd756_smbus; | ||
43 | |||
44 | static struct i2c_adapter *s4882_adapter; | ||
45 | static struct i2c_algorithm *s4882_algo; | ||
46 | |||
47 | /* Wrapper access functions for multiplexed SMBus */ | ||
48 | static struct semaphore amd756_lock; | ||
49 | |||
50 | static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr, | ||
51 | unsigned short flags, char read_write, | ||
52 | u8 command, int size, | ||
53 | union i2c_smbus_data * data) | ||
54 | { | ||
55 | int error; | ||
56 | |||
57 | /* We exclude the multiplexed addresses */ | ||
58 | if (addr == 0x4c || (addr & 0xfc) == 0x50 || (addr & 0xfc) == 0x30 | ||
59 | || addr == 0x18) | ||
60 | return -1; | ||
61 | |||
62 | down(&amd756_lock); | ||
63 | |||
64 | error = amd756_smbus.algo->smbus_xfer(adap, addr, flags, read_write, | ||
65 | command, size, data); | ||
66 | |||
67 | up(&amd756_lock); | ||
68 | |||
69 | return error; | ||
70 | } | ||
71 | |||
72 | /* We remember the last used channels combination so as to only switch | ||
73 | channels when it is really needed. This greatly reduces the SMBus | ||
74 | overhead, but also assumes that nobody will be writing to the PCA9556 | ||
75 | in our back. */ | ||
76 | static u8 last_channels; | ||
77 | |||
78 | static inline s32 amd756_access_channel(struct i2c_adapter * adap, u16 addr, | ||
79 | unsigned short flags, char read_write, | ||
80 | u8 command, int size, | ||
81 | union i2c_smbus_data * data, | ||
82 | u8 channels) | ||
83 | { | ||
84 | int error; | ||
85 | |||
86 | /* We exclude the non-multiplexed addresses */ | ||
87 | if (addr != 0x4c && (addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30) | ||
88 | return -1; | ||
89 | |||
90 | down(&amd756_lock); | ||
91 | |||
92 | if (last_channels != channels) { | ||
93 | union i2c_smbus_data mplxdata; | ||
94 | mplxdata.byte = channels; | ||
95 | |||
96 | error = amd756_smbus.algo->smbus_xfer(adap, 0x18, 0, | ||
97 | I2C_SMBUS_WRITE, 0x01, | ||
98 | I2C_SMBUS_BYTE_DATA, | ||
99 | &mplxdata); | ||
100 | if (error) | ||
101 | goto UNLOCK; | ||
102 | last_channels = channels; | ||
103 | } | ||
104 | error = amd756_smbus.algo->smbus_xfer(adap, addr, flags, read_write, | ||
105 | command, size, data); | ||
106 | |||
107 | UNLOCK: | ||
108 | up(&amd756_lock); | ||
109 | return error; | ||
110 | } | ||
111 | |||
112 | static s32 amd756_access_virt1(struct i2c_adapter * adap, u16 addr, | ||
113 | unsigned short flags, char read_write, | ||
114 | u8 command, int size, | ||
115 | union i2c_smbus_data * data) | ||
116 | { | ||
117 | /* CPU0: channels 1 and 0 enabled */ | ||
118 | return amd756_access_channel(adap, addr, flags, read_write, command, | ||
119 | size, data, 0x03); | ||
120 | } | ||
121 | |||
122 | static s32 amd756_access_virt2(struct i2c_adapter * adap, u16 addr, | ||
123 | unsigned short flags, char read_write, | ||
124 | u8 command, int size, | ||
125 | union i2c_smbus_data * data) | ||
126 | { | ||
127 | /* CPU1: channels 2 and 5 enabled */ | ||
128 | return amd756_access_channel(adap, addr, flags, read_write, command, | ||
129 | size, data, 0x24); | ||
130 | } | ||
131 | |||
132 | static s32 amd756_access_virt3(struct i2c_adapter * adap, u16 addr, | ||
133 | unsigned short flags, char read_write, | ||
134 | u8 command, int size, | ||
135 | union i2c_smbus_data * data) | ||
136 | { | ||
137 | /* CPU2: channels 3 and 6 enabled */ | ||
138 | return amd756_access_channel(adap, addr, flags, read_write, command, | ||
139 | size, data, 0x48); | ||
140 | } | ||
141 | |||
142 | static s32 amd756_access_virt4(struct i2c_adapter * adap, u16 addr, | ||
143 | unsigned short flags, char read_write, | ||
144 | u8 command, int size, | ||
145 | union i2c_smbus_data * data) | ||
146 | { | ||
147 | /* CPU3: channels 4 and 7 enabled */ | ||
148 | return amd756_access_channel(adap, addr, flags, read_write, command, | ||
149 | size, data, 0x90); | ||
150 | } | ||
151 | |||
152 | static int __init amd756_s4882_init(void) | ||
153 | { | ||
154 | int i, error; | ||
155 | union i2c_smbus_data ioconfig; | ||
156 | |||
157 | /* Unregister physical bus */ | ||
158 | error = i2c_del_adapter(&amd756_smbus); | ||
159 | if (error) { | ||
160 | if (error == -EINVAL) | ||
161 | error = -ENODEV; | ||
162 | else | ||
163 | dev_err(&amd756_smbus.dev, "Physical bus removal " | ||
164 | "failed\n"); | ||
165 | goto ERROR0; | ||
166 | } | ||
167 | |||
168 | printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4882\n"); | ||
169 | init_MUTEX(&amd756_lock); | ||
170 | |||
171 | /* Define the 5 virtual adapters and algorithms structures */ | ||
172 | if (!(s4882_adapter = kmalloc(5 * sizeof(struct i2c_adapter), | ||
173 | GFP_KERNEL))) { | ||
174 | error = -ENOMEM; | ||
175 | goto ERROR1; | ||
176 | } | ||
177 | if (!(s4882_algo = kmalloc(5 * sizeof(struct i2c_algorithm), | ||
178 | GFP_KERNEL))) { | ||
179 | error = -ENOMEM; | ||
180 | goto ERROR2; | ||
181 | } | ||
182 | |||
183 | /* Fill in the new structures */ | ||
184 | s4882_algo[0] = *(amd756_smbus.algo); | ||
185 | s4882_algo[0].smbus_xfer = amd756_access_virt0; | ||
186 | s4882_adapter[0] = amd756_smbus; | ||
187 | s4882_adapter[0].algo = s4882_algo; | ||
188 | for (i = 1; i < 5; i++) { | ||
189 | s4882_algo[i] = *(amd756_smbus.algo); | ||
190 | s4882_adapter[i] = amd756_smbus; | ||
191 | sprintf(s4882_adapter[i].name, | ||
192 | "SMBus 8111 adapter (CPU%d)", i-1); | ||
193 | s4882_adapter[i].algo = s4882_algo+i; | ||
194 | } | ||
195 | s4882_algo[1].smbus_xfer = amd756_access_virt1; | ||
196 | s4882_algo[2].smbus_xfer = amd756_access_virt2; | ||
197 | s4882_algo[3].smbus_xfer = amd756_access_virt3; | ||
198 | s4882_algo[4].smbus_xfer = amd756_access_virt4; | ||
199 | |||
200 | /* Configure the PCA9556 multiplexer */ | ||
201 | ioconfig.byte = 0x00; /* All I/O to output mode */ | ||
202 | error = amd756_smbus.algo->smbus_xfer(&amd756_smbus, 0x18, 0, | ||
203 | I2C_SMBUS_WRITE, 0x03, | ||
204 | I2C_SMBUS_BYTE_DATA, &ioconfig); | ||
205 | if (error) { | ||
206 | dev_err(&amd756_smbus.dev, "PCA9556 configuration failed\n"); | ||
207 | error = -EIO; | ||
208 | goto ERROR3; | ||
209 | } | ||
210 | |||
211 | /* Register virtual adapters */ | ||
212 | for (i = 0; i < 5; i++) { | ||
213 | error = i2c_add_adapter(s4882_adapter+i); | ||
214 | if (error) { | ||
215 | dev_err(&amd756_smbus.dev, | ||
216 | "Virtual adapter %d registration " | ||
217 | "failed, module not inserted\n", i); | ||
218 | for (i--; i >= 0; i--) | ||
219 | i2c_del_adapter(s4882_adapter+i); | ||
220 | goto ERROR3; | ||
221 | } | ||
222 | } | ||
223 | |||
224 | return 0; | ||
225 | |||
226 | ERROR3: | ||
227 | kfree(s4882_algo); | ||
228 | s4882_algo = NULL; | ||
229 | ERROR2: | ||
230 | kfree(s4882_adapter); | ||
231 | s4882_adapter = NULL; | ||
232 | ERROR1: | ||
233 | i2c_del_adapter(&amd756_smbus); | ||
234 | ERROR0: | ||
235 | return error; | ||
236 | } | ||
237 | |||
238 | static void __exit amd756_s4882_exit(void) | ||
239 | { | ||
240 | if (s4882_adapter) { | ||
241 | int i; | ||
242 | |||
243 | for (i = 0; i < 5; i++) | ||
244 | i2c_del_adapter(s4882_adapter+i); | ||
245 | kfree(s4882_adapter); | ||
246 | s4882_adapter = NULL; | ||
247 | } | ||
248 | if (s4882_algo) { | ||
249 | kfree(s4882_algo); | ||
250 | s4882_algo = NULL; | ||
251 | } | ||
252 | |||
253 | /* Restore physical bus */ | ||
254 | if (i2c_add_adapter(&amd756_smbus)) | ||
255 | dev_err(&amd756_smbus.dev, "Physical bus restoration " | ||
256 | "failed\n"); | ||
257 | } | ||
258 | |||
259 | MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); | ||
260 | MODULE_DESCRIPTION("S4882 SMBus multiplexing"); | ||
261 | MODULE_LICENSE("GPL"); | ||
262 | |||
263 | module_init(amd756_s4882_init); | ||
264 | module_exit(amd756_s4882_exit); | ||
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c new file mode 100644 index 000000000000..eca5ed3738b8 --- /dev/null +++ b/drivers/i2c/busses/i2c-amd756.c | |||
@@ -0,0 +1,431 @@ | |||
1 | /* | ||
2 | amd756.c - Part of lm_sensors, Linux kernel modules for hardware | ||
3 | monitoring | ||
4 | |||
5 | Copyright (c) 1999-2002 Merlin Hughes <merlin@merlin.org> | ||
6 | |||
7 | Shamelessly ripped from i2c-piix4.c: | ||
8 | |||
9 | Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and | ||
10 | Philip Edelbrock <phil@netroedge.com> | ||
11 | |||
12 | This program is free software; you can redistribute it and/or modify | ||
13 | it under the terms of the GNU General Public License as published by | ||
14 | the Free Software Foundation; either version 2 of the License, or | ||
15 | (at your option) any later version. | ||
16 | |||
17 | This program is distributed in the hope that it will be useful, | ||
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | GNU General Public License for more details. | ||
21 | |||
22 | You should have received a copy of the GNU General Public License | ||
23 | along with this program; if not, write to the Free Software | ||
24 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | /* | ||
28 | 2002-04-08: Added nForce support. (Csaba Halasz) | ||
29 | 2002-10-03: Fixed nForce PnP I/O port. (Michael Steil) | ||
30 | 2002-12-28: Rewritten into something that resembles a Linux driver (hch) | ||
31 | 2003-11-29: Added back AMD8111 removed by the previous rewrite. | ||
32 | (Philip Pokorny) | ||
33 | */ | ||
34 | |||
35 | /* | ||
36 | Supports AMD756, AMD766, AMD768, AMD8111 and nVidia nForce | ||
37 | Note: we assume there can only be one device, with one SMBus interface. | ||
38 | */ | ||
39 | |||
40 | #include <linux/config.h> | ||
41 | #include <linux/module.h> | ||
42 | #include <linux/pci.h> | ||
43 | #include <linux/kernel.h> | ||
44 | #include <linux/delay.h> | ||
45 | #include <linux/stddef.h> | ||
46 | #include <linux/sched.h> | ||
47 | #include <linux/ioport.h> | ||
48 | #include <linux/i2c.h> | ||
49 | #include <linux/init.h> | ||
50 | #include <asm/io.h> | ||
51 | |||
52 | /* AMD756 SMBus address offsets */ | ||
53 | #define SMB_ADDR_OFFSET 0xE0 | ||
54 | #define SMB_IOSIZE 16 | ||
55 | #define SMB_GLOBAL_STATUS (0x0 + amd756_ioport) | ||
56 | #define SMB_GLOBAL_ENABLE (0x2 + amd756_ioport) | ||
57 | #define SMB_HOST_ADDRESS (0x4 + amd756_ioport) | ||
58 | #define SMB_HOST_DATA (0x6 + amd756_ioport) | ||
59 | #define SMB_HOST_COMMAND (0x8 + amd756_ioport) | ||
60 | #define SMB_HOST_BLOCK_DATA (0x9 + amd756_ioport) | ||
61 | #define SMB_HAS_DATA (0xA + amd756_ioport) | ||
62 | #define SMB_HAS_DEVICE_ADDRESS (0xC + amd756_ioport) | ||
63 | #define SMB_HAS_HOST_ADDRESS (0xE + amd756_ioport) | ||
64 | #define SMB_SNOOP_ADDRESS (0xF + amd756_ioport) | ||
65 | |||
66 | /* PCI Address Constants */ | ||
67 | |||
68 | /* address of I/O space */ | ||
69 | #define SMBBA 0x058 /* mh */ | ||
70 | #define SMBBANFORCE 0x014 | ||
71 | |||
72 | /* general configuration */ | ||
73 | #define SMBGCFG 0x041 /* mh */ | ||
74 | |||
75 | /* silicon revision code */ | ||
76 | #define SMBREV 0x008 | ||
77 | |||
78 | /* Other settings */ | ||
79 | #define MAX_TIMEOUT 500 | ||
80 | |||
81 | /* AMD756 constants */ | ||
82 | #define AMD756_QUICK 0x00 | ||
83 | #define AMD756_BYTE 0x01 | ||
84 | #define AMD756_BYTE_DATA 0x02 | ||
85 | #define AMD756_WORD_DATA 0x03 | ||
86 | #define AMD756_PROCESS_CALL 0x04 | ||
87 | #define AMD756_BLOCK_DATA 0x05 | ||
88 | |||
89 | |||
90 | static unsigned short amd756_ioport = 0; | ||
91 | |||
92 | /* | ||
93 | SMBUS event = I/O 28-29 bit 11 | ||
94 | see E0 for the status bits and enabled in E2 | ||
95 | |||
96 | */ | ||
97 | #define GS_ABRT_STS (1 << 0) | ||
98 | #define GS_COL_STS (1 << 1) | ||
99 | #define GS_PRERR_STS (1 << 2) | ||
100 | #define GS_HST_STS (1 << 3) | ||
101 | #define GS_HCYC_STS (1 << 4) | ||
102 | #define GS_TO_STS (1 << 5) | ||
103 | #define GS_SMB_STS (1 << 11) | ||
104 | |||
105 | #define GS_CLEAR_STS (GS_ABRT_STS | GS_COL_STS | GS_PRERR_STS | \ | ||
106 | GS_HCYC_STS | GS_TO_STS ) | ||
107 | |||
108 | #define GE_CYC_TYPE_MASK (7) | ||
109 | #define GE_HOST_STC (1 << 3) | ||
110 | #define GE_ABORT (1 << 5) | ||
111 | |||
112 | |||
113 | static int amd756_transaction(struct i2c_adapter *adap) | ||
114 | { | ||
115 | int temp; | ||
116 | int result = 0; | ||
117 | int timeout = 0; | ||
118 | |||
119 | dev_dbg(&adap->dev, "Transaction (pre): GS=%04x, GE=%04x, ADD=%04x, " | ||
120 | "DAT=%04x\n", inw_p(SMB_GLOBAL_STATUS), | ||
121 | inw_p(SMB_GLOBAL_ENABLE), inw_p(SMB_HOST_ADDRESS), | ||
122 | inb_p(SMB_HOST_DATA)); | ||
123 | |||
124 | /* Make sure the SMBus host is ready to start transmitting */ | ||
125 | if ((temp = inw_p(SMB_GLOBAL_STATUS)) & (GS_HST_STS | GS_SMB_STS)) { | ||
126 | dev_dbg(&adap->dev, "SMBus busy (%04x). Waiting...\n", temp); | ||
127 | do { | ||
128 | msleep(1); | ||
129 | temp = inw_p(SMB_GLOBAL_STATUS); | ||
130 | } while ((temp & (GS_HST_STS | GS_SMB_STS)) && | ||
131 | (timeout++ < MAX_TIMEOUT)); | ||
132 | /* If the SMBus is still busy, we give up */ | ||
133 | if (timeout >= MAX_TIMEOUT) { | ||
134 | dev_dbg(&adap->dev, "Busy wait timeout (%04x)\n", temp); | ||
135 | goto abort; | ||
136 | } | ||
137 | timeout = 0; | ||
138 | } | ||
139 | |||
140 | /* start the transaction by setting the start bit */ | ||
141 | outw_p(inw(SMB_GLOBAL_ENABLE) | GE_HOST_STC, SMB_GLOBAL_ENABLE); | ||
142 | |||
143 | /* We will always wait for a fraction of a second! */ | ||
144 | do { | ||
145 | msleep(1); | ||
146 | temp = inw_p(SMB_GLOBAL_STATUS); | ||
147 | } while ((temp & GS_HST_STS) && (timeout++ < MAX_TIMEOUT)); | ||
148 | |||
149 | /* If the SMBus is still busy, we give up */ | ||
150 | if (timeout >= MAX_TIMEOUT) { | ||
151 | dev_dbg(&adap->dev, "Completion timeout!\n"); | ||
152 | goto abort; | ||
153 | } | ||
154 | |||
155 | if (temp & GS_PRERR_STS) { | ||
156 | result = -1; | ||
157 | dev_dbg(&adap->dev, "SMBus Protocol error (no response)!\n"); | ||
158 | } | ||
159 | |||
160 | if (temp & GS_COL_STS) { | ||
161 | result = -1; | ||
162 | dev_warn(&adap->dev, "SMBus collision!\n"); | ||
163 | } | ||
164 | |||
165 | if (temp & GS_TO_STS) { | ||
166 | result = -1; | ||
167 | dev_dbg(&adap->dev, "SMBus protocol timeout!\n"); | ||
168 | } | ||
169 | |||
170 | if (temp & GS_HCYC_STS) | ||
171 | dev_dbg(&adap->dev, "SMBus protocol success!\n"); | ||
172 | |||
173 | outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS); | ||
174 | |||
175 | #ifdef DEBUG | ||
176 | if (((temp = inw_p(SMB_GLOBAL_STATUS)) & GS_CLEAR_STS) != 0x00) { | ||
177 | dev_dbg(&adap->dev, | ||
178 | "Failed reset at end of transaction (%04x)\n", temp); | ||
179 | } | ||
180 | #endif | ||
181 | |||
182 | dev_dbg(&adap->dev, | ||
183 | "Transaction (post): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n", | ||
184 | inw_p(SMB_GLOBAL_STATUS), inw_p(SMB_GLOBAL_ENABLE), | ||
185 | inw_p(SMB_HOST_ADDRESS), inb_p(SMB_HOST_DATA)); | ||
186 | |||
187 | return result; | ||
188 | |||
189 | abort: | ||
190 | dev_warn(&adap->dev, "Sending abort\n"); | ||
191 | outw_p(inw(SMB_GLOBAL_ENABLE) | GE_ABORT, SMB_GLOBAL_ENABLE); | ||
192 | msleep(100); | ||
193 | outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS); | ||
194 | return -1; | ||
195 | } | ||
196 | |||
197 | /* Return -1 on error. */ | ||
198 | static s32 amd756_access(struct i2c_adapter * adap, u16 addr, | ||
199 | unsigned short flags, char read_write, | ||
200 | u8 command, int size, union i2c_smbus_data * data) | ||
201 | { | ||
202 | int i, len; | ||
203 | |||
204 | /** TODO: Should I supporte the 10-bit transfers? */ | ||
205 | switch (size) { | ||
206 | case I2C_SMBUS_PROC_CALL: | ||
207 | dev_dbg(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n"); | ||
208 | /* TODO: Well... It is supported, I'm just not sure what to do here... */ | ||
209 | return -1; | ||
210 | case I2C_SMBUS_QUICK: | ||
211 | outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
212 | SMB_HOST_ADDRESS); | ||
213 | size = AMD756_QUICK; | ||
214 | break; | ||
215 | case I2C_SMBUS_BYTE: | ||
216 | outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
217 | SMB_HOST_ADDRESS); | ||
218 | if (read_write == I2C_SMBUS_WRITE) | ||
219 | outb_p(command, SMB_HOST_DATA); | ||
220 | size = AMD756_BYTE; | ||
221 | break; | ||
222 | case I2C_SMBUS_BYTE_DATA: | ||
223 | outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
224 | SMB_HOST_ADDRESS); | ||
225 | outb_p(command, SMB_HOST_COMMAND); | ||
226 | if (read_write == I2C_SMBUS_WRITE) | ||
227 | outw_p(data->byte, SMB_HOST_DATA); | ||
228 | size = AMD756_BYTE_DATA; | ||
229 | break; | ||
230 | case I2C_SMBUS_WORD_DATA: | ||
231 | outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
232 | SMB_HOST_ADDRESS); | ||
233 | outb_p(command, SMB_HOST_COMMAND); | ||
234 | if (read_write == I2C_SMBUS_WRITE) | ||
235 | outw_p(data->word, SMB_HOST_DATA); /* TODO: endian???? */ | ||
236 | size = AMD756_WORD_DATA; | ||
237 | break; | ||
238 | case I2C_SMBUS_BLOCK_DATA: | ||
239 | outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
240 | SMB_HOST_ADDRESS); | ||
241 | outb_p(command, SMB_HOST_COMMAND); | ||
242 | if (read_write == I2C_SMBUS_WRITE) { | ||
243 | len = data->block[0]; | ||
244 | if (len < 0) | ||
245 | len = 0; | ||
246 | if (len > 32) | ||
247 | len = 32; | ||
248 | outw_p(len, SMB_HOST_DATA); | ||
249 | /* i = inw_p(SMBHSTCNT); Reset SMBBLKDAT */ | ||
250 | for (i = 1; i <= len; i++) | ||
251 | outb_p(data->block[i], | ||
252 | SMB_HOST_BLOCK_DATA); | ||
253 | } | ||
254 | size = AMD756_BLOCK_DATA; | ||
255 | break; | ||
256 | } | ||
257 | |||
258 | /* How about enabling interrupts... */ | ||
259 | outw_p(size & GE_CYC_TYPE_MASK, SMB_GLOBAL_ENABLE); | ||
260 | |||
261 | if (amd756_transaction(adap)) /* Error in transaction */ | ||
262 | return -1; | ||
263 | |||
264 | if ((read_write == I2C_SMBUS_WRITE) || (size == AMD756_QUICK)) | ||
265 | return 0; | ||
266 | |||
267 | |||
268 | switch (size) { | ||
269 | case AMD756_BYTE: | ||
270 | data->byte = inw_p(SMB_HOST_DATA); | ||
271 | break; | ||
272 | case AMD756_BYTE_DATA: | ||
273 | data->byte = inw_p(SMB_HOST_DATA); | ||
274 | break; | ||
275 | case AMD756_WORD_DATA: | ||
276 | data->word = inw_p(SMB_HOST_DATA); /* TODO: endian???? */ | ||
277 | break; | ||
278 | case AMD756_BLOCK_DATA: | ||
279 | data->block[0] = inw_p(SMB_HOST_DATA) & 0x3f; | ||
280 | if(data->block[0] > 32) | ||
281 | data->block[0] = 32; | ||
282 | /* i = inw_p(SMBHSTCNT); Reset SMBBLKDAT */ | ||
283 | for (i = 1; i <= data->block[0]; i++) | ||
284 | data->block[i] = inb_p(SMB_HOST_BLOCK_DATA); | ||
285 | break; | ||
286 | } | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static u32 amd756_func(struct i2c_adapter *adapter) | ||
292 | { | ||
293 | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | | ||
294 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | | ||
295 | I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL; | ||
296 | } | ||
297 | |||
298 | static struct i2c_algorithm smbus_algorithm = { | ||
299 | .name = "Non-I2C SMBus adapter", | ||
300 | .id = I2C_ALGO_SMBUS, | ||
301 | .smbus_xfer = amd756_access, | ||
302 | .functionality = amd756_func, | ||
303 | }; | ||
304 | |||
305 | struct i2c_adapter amd756_smbus = { | ||
306 | .owner = THIS_MODULE, | ||
307 | .class = I2C_CLASS_HWMON, | ||
308 | .algo = &smbus_algorithm, | ||
309 | .name = "unset", | ||
310 | }; | ||
311 | |||
312 | enum chiptype { AMD756, AMD766, AMD768, NFORCE, AMD8111 }; | ||
313 | static const char* chipname[] = { | ||
314 | "AMD756", "AMD766", "AMD768", | ||
315 | "nVidia nForce", "AMD8111", | ||
316 | }; | ||
317 | |||
318 | static struct pci_device_id amd756_ids[] = { | ||
319 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_740B), | ||
320 | .driver_data = AMD756 }, | ||
321 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413), | ||
322 | .driver_data = AMD766 }, | ||
323 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7443), | ||
324 | .driver_data = AMD768 }, | ||
325 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS), | ||
326 | .driver_data = AMD8111 }, | ||
327 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS), | ||
328 | .driver_data = NFORCE }, | ||
329 | { 0, } | ||
330 | }; | ||
331 | |||
332 | MODULE_DEVICE_TABLE (pci, amd756_ids); | ||
333 | |||
334 | static int __devinit amd756_probe(struct pci_dev *pdev, | ||
335 | const struct pci_device_id *id) | ||
336 | { | ||
337 | int nforce = (id->driver_data == NFORCE); | ||
338 | int error; | ||
339 | u8 temp; | ||
340 | |||
341 | if (amd756_ioport) { | ||
342 | dev_err(&pdev->dev, "Only one device supported " | ||
343 | "(you have a strange motherboard, btw)\n"); | ||
344 | return -ENODEV; | ||
345 | } | ||
346 | |||
347 | if (nforce) { | ||
348 | if (PCI_FUNC(pdev->devfn) != 1) | ||
349 | return -ENODEV; | ||
350 | |||
351 | pci_read_config_word(pdev, SMBBANFORCE, &amd756_ioport); | ||
352 | amd756_ioport &= 0xfffc; | ||
353 | } else { /* amd */ | ||
354 | if (PCI_FUNC(pdev->devfn) != 3) | ||
355 | return -ENODEV; | ||
356 | |||
357 | pci_read_config_byte(pdev, SMBGCFG, &temp); | ||
358 | if ((temp & 128) == 0) { | ||
359 | dev_err(&pdev->dev, | ||
360 | "Error: SMBus controller I/O not enabled!\n"); | ||
361 | return -ENODEV; | ||
362 | } | ||
363 | |||
364 | /* Determine the address of the SMBus areas */ | ||
365 | /* Technically it is a dword but... */ | ||
366 | pci_read_config_word(pdev, SMBBA, &amd756_ioport); | ||
367 | amd756_ioport &= 0xff00; | ||
368 | amd756_ioport += SMB_ADDR_OFFSET; | ||
369 | } | ||
370 | |||
371 | if (!request_region(amd756_ioport, SMB_IOSIZE, "amd756-smbus")) { | ||
372 | dev_err(&pdev->dev, "SMB region 0x%x already in use!\n", | ||
373 | amd756_ioport); | ||
374 | return -ENODEV; | ||
375 | } | ||
376 | |||
377 | pci_read_config_byte(pdev, SMBREV, &temp); | ||
378 | dev_dbg(&pdev->dev, "SMBREV = 0x%X\n", temp); | ||
379 | dev_dbg(&pdev->dev, "AMD756_smba = 0x%X\n", amd756_ioport); | ||
380 | |||
381 | /* set up the driverfs linkage to our parent device */ | ||
382 | amd756_smbus.dev.parent = &pdev->dev; | ||
383 | |||
384 | sprintf(amd756_smbus.name, "SMBus %s adapter at %04x", | ||
385 | chipname[id->driver_data], amd756_ioport); | ||
386 | |||
387 | error = i2c_add_adapter(&amd756_smbus); | ||
388 | if (error) { | ||
389 | dev_err(&pdev->dev, | ||
390 | "Adapter registration failed, module not inserted\n"); | ||
391 | goto out_err; | ||
392 | } | ||
393 | |||
394 | return 0; | ||
395 | |||
396 | out_err: | ||
397 | release_region(amd756_ioport, SMB_IOSIZE); | ||
398 | return error; | ||
399 | } | ||
400 | |||
401 | static void __devexit amd756_remove(struct pci_dev *dev) | ||
402 | { | ||
403 | i2c_del_adapter(&amd756_smbus); | ||
404 | release_region(amd756_ioport, SMB_IOSIZE); | ||
405 | } | ||
406 | |||
407 | static struct pci_driver amd756_driver = { | ||
408 | .name = "amd756_smbus", | ||
409 | .id_table = amd756_ids, | ||
410 | .probe = amd756_probe, | ||
411 | .remove = __devexit_p(amd756_remove), | ||
412 | }; | ||
413 | |||
414 | static int __init amd756_init(void) | ||
415 | { | ||
416 | return pci_register_driver(&amd756_driver); | ||
417 | } | ||
418 | |||
419 | static void __exit amd756_exit(void) | ||
420 | { | ||
421 | pci_unregister_driver(&amd756_driver); | ||
422 | } | ||
423 | |||
424 | MODULE_AUTHOR("Merlin Hughes <merlin@merlin.org>"); | ||
425 | MODULE_DESCRIPTION("AMD756/766/768/8111 and nVidia nForce SMBus driver"); | ||
426 | MODULE_LICENSE("GPL"); | ||
427 | |||
428 | EXPORT_SYMBOL(amd756_smbus); | ||
429 | |||
430 | module_init(amd756_init) | ||
431 | module_exit(amd756_exit) | ||
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c new file mode 100644 index 000000000000..af22b401a38b --- /dev/null +++ b/drivers/i2c/busses/i2c-amd8111.c | |||
@@ -0,0 +1,415 @@ | |||
1 | /* | ||
2 | * SMBus 2.0 driver for AMD-8111 IO-Hub. | ||
3 | * | ||
4 | * Copyright (c) 2002 Vojtech Pavlik | ||
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 version 2. | ||
9 | */ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/pci.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/stddef.h> | ||
16 | #include <linux/sched.h> | ||
17 | #include <linux/ioport.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/i2c.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <asm/io.h> | ||
22 | |||
23 | MODULE_LICENSE("GPL"); | ||
24 | MODULE_AUTHOR ("Vojtech Pavlik <vojtech@suse.cz>"); | ||
25 | MODULE_DESCRIPTION("AMD8111 SMBus 2.0 driver"); | ||
26 | |||
27 | struct amd_smbus { | ||
28 | struct pci_dev *dev; | ||
29 | struct i2c_adapter adapter; | ||
30 | int base; | ||
31 | int size; | ||
32 | }; | ||
33 | |||
34 | /* | ||
35 | * AMD PCI control registers definitions. | ||
36 | */ | ||
37 | |||
38 | #define AMD_PCI_MISC 0x48 | ||
39 | |||
40 | #define AMD_PCI_MISC_SCI 0x04 /* deliver SCI */ | ||
41 | #define AMD_PCI_MISC_INT 0x02 /* deliver PCI IRQ */ | ||
42 | #define AMD_PCI_MISC_SPEEDUP 0x01 /* 16x clock speedup */ | ||
43 | |||
44 | /* | ||
45 | * ACPI 2.0 chapter 13 PCI interface definitions. | ||
46 | */ | ||
47 | |||
48 | #define AMD_EC_DATA 0x00 /* data register */ | ||
49 | #define AMD_EC_SC 0x04 /* status of controller */ | ||
50 | #define AMD_EC_CMD 0x04 /* command register */ | ||
51 | #define AMD_EC_ICR 0x08 /* interrupt control register */ | ||
52 | |||
53 | #define AMD_EC_SC_SMI 0x04 /* smi event pending */ | ||
54 | #define AMD_EC_SC_SCI 0x02 /* sci event pending */ | ||
55 | #define AMD_EC_SC_BURST 0x01 /* burst mode enabled */ | ||
56 | #define AMD_EC_SC_CMD 0x08 /* byte in data reg is command */ | ||
57 | #define AMD_EC_SC_IBF 0x02 /* data ready for embedded controller */ | ||
58 | #define AMD_EC_SC_OBF 0x01 /* data ready for host */ | ||
59 | |||
60 | #define AMD_EC_CMD_RD 0x80 /* read EC */ | ||
61 | #define AMD_EC_CMD_WR 0x81 /* write EC */ | ||
62 | #define AMD_EC_CMD_BE 0x82 /* enable burst mode */ | ||
63 | #define AMD_EC_CMD_BD 0x83 /* disable burst mode */ | ||
64 | #define AMD_EC_CMD_QR 0x84 /* query EC */ | ||
65 | |||
66 | /* | ||
67 | * ACPI 2.0 chapter 13 access of registers of the EC | ||
68 | */ | ||
69 | |||
70 | static unsigned int amd_ec_wait_write(struct amd_smbus *smbus) | ||
71 | { | ||
72 | int timeout = 500; | ||
73 | |||
74 | while (timeout-- && (inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_IBF)) | ||
75 | udelay(1); | ||
76 | |||
77 | if (!timeout) { | ||
78 | dev_warn(&smbus->dev->dev, "Timeout while waiting for IBF to clear\n"); | ||
79 | return -1; | ||
80 | } | ||
81 | |||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | static unsigned int amd_ec_wait_read(struct amd_smbus *smbus) | ||
86 | { | ||
87 | int timeout = 500; | ||
88 | |||
89 | while (timeout-- && (~inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_OBF)) | ||
90 | udelay(1); | ||
91 | |||
92 | if (!timeout) { | ||
93 | dev_warn(&smbus->dev->dev, "Timeout while waiting for OBF to set\n"); | ||
94 | return -1; | ||
95 | } | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address, unsigned char *data) | ||
101 | { | ||
102 | if (amd_ec_wait_write(smbus)) | ||
103 | return -1; | ||
104 | outb(AMD_EC_CMD_RD, smbus->base + AMD_EC_CMD); | ||
105 | |||
106 | if (amd_ec_wait_write(smbus)) | ||
107 | return -1; | ||
108 | outb(address, smbus->base + AMD_EC_DATA); | ||
109 | |||
110 | if (amd_ec_wait_read(smbus)) | ||
111 | return -1; | ||
112 | *data = inb(smbus->base + AMD_EC_DATA); | ||
113 | |||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | static unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address, unsigned char data) | ||
118 | { | ||
119 | if (amd_ec_wait_write(smbus)) | ||
120 | return -1; | ||
121 | outb(AMD_EC_CMD_WR, smbus->base + AMD_EC_CMD); | ||
122 | |||
123 | if (amd_ec_wait_write(smbus)) | ||
124 | return -1; | ||
125 | outb(address, smbus->base + AMD_EC_DATA); | ||
126 | |||
127 | if (amd_ec_wait_write(smbus)) | ||
128 | return -1; | ||
129 | outb(data, smbus->base + AMD_EC_DATA); | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * ACPI 2.0 chapter 13 SMBus 2.0 EC register model | ||
136 | */ | ||
137 | |||
138 | #define AMD_SMB_PRTCL 0x00 /* protocol, PEC */ | ||
139 | #define AMD_SMB_STS 0x01 /* status */ | ||
140 | #define AMD_SMB_ADDR 0x02 /* address */ | ||
141 | #define AMD_SMB_CMD 0x03 /* command */ | ||
142 | #define AMD_SMB_DATA 0x04 /* 32 data registers */ | ||
143 | #define AMD_SMB_BCNT 0x24 /* number of data bytes */ | ||
144 | #define AMD_SMB_ALRM_A 0x25 /* alarm address */ | ||
145 | #define AMD_SMB_ALRM_D 0x26 /* 2 bytes alarm data */ | ||
146 | |||
147 | #define AMD_SMB_STS_DONE 0x80 | ||
148 | #define AMD_SMB_STS_ALRM 0x40 | ||
149 | #define AMD_SMB_STS_RES 0x20 | ||
150 | #define AMD_SMB_STS_STATUS 0x1f | ||
151 | |||
152 | #define AMD_SMB_STATUS_OK 0x00 | ||
153 | #define AMD_SMB_STATUS_FAIL 0x07 | ||
154 | #define AMD_SMB_STATUS_DNAK 0x10 | ||
155 | #define AMD_SMB_STATUS_DERR 0x11 | ||
156 | #define AMD_SMB_STATUS_CMD_DENY 0x12 | ||
157 | #define AMD_SMB_STATUS_UNKNOWN 0x13 | ||
158 | #define AMD_SMB_STATUS_ACC_DENY 0x17 | ||
159 | #define AMD_SMB_STATUS_TIMEOUT 0x18 | ||
160 | #define AMD_SMB_STATUS_NOTSUP 0x19 | ||
161 | #define AMD_SMB_STATUS_BUSY 0x1A | ||
162 | #define AMD_SMB_STATUS_PEC 0x1F | ||
163 | |||
164 | #define AMD_SMB_PRTCL_WRITE 0x00 | ||
165 | #define AMD_SMB_PRTCL_READ 0x01 | ||
166 | #define AMD_SMB_PRTCL_QUICK 0x02 | ||
167 | #define AMD_SMB_PRTCL_BYTE 0x04 | ||
168 | #define AMD_SMB_PRTCL_BYTE_DATA 0x06 | ||
169 | #define AMD_SMB_PRTCL_WORD_DATA 0x08 | ||
170 | #define AMD_SMB_PRTCL_BLOCK_DATA 0x0a | ||
171 | #define AMD_SMB_PRTCL_PROC_CALL 0x0c | ||
172 | #define AMD_SMB_PRTCL_BLOCK_PROC_CALL 0x0d | ||
173 | #define AMD_SMB_PRTCL_I2C_BLOCK_DATA 0x4a | ||
174 | #define AMD_SMB_PRTCL_PEC 0x80 | ||
175 | |||
176 | |||
177 | static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, | ||
178 | char read_write, u8 command, int size, union i2c_smbus_data * data) | ||
179 | { | ||
180 | struct amd_smbus *smbus = adap->algo_data; | ||
181 | unsigned char protocol, len, pec, temp[2]; | ||
182 | int i; | ||
183 | |||
184 | protocol = (read_write == I2C_SMBUS_READ) ? AMD_SMB_PRTCL_READ : AMD_SMB_PRTCL_WRITE; | ||
185 | pec = (flags & I2C_CLIENT_PEC) ? AMD_SMB_PRTCL_PEC : 0; | ||
186 | |||
187 | switch (size) { | ||
188 | |||
189 | case I2C_SMBUS_QUICK: | ||
190 | protocol |= AMD_SMB_PRTCL_QUICK; | ||
191 | read_write = I2C_SMBUS_WRITE; | ||
192 | break; | ||
193 | |||
194 | case I2C_SMBUS_BYTE: | ||
195 | if (read_write == I2C_SMBUS_WRITE) | ||
196 | amd_ec_write(smbus, AMD_SMB_CMD, command); | ||
197 | protocol |= AMD_SMB_PRTCL_BYTE; | ||
198 | break; | ||
199 | |||
200 | case I2C_SMBUS_BYTE_DATA: | ||
201 | amd_ec_write(smbus, AMD_SMB_CMD, command); | ||
202 | if (read_write == I2C_SMBUS_WRITE) | ||
203 | amd_ec_write(smbus, AMD_SMB_DATA, data->byte); | ||
204 | protocol |= AMD_SMB_PRTCL_BYTE_DATA; | ||
205 | break; | ||
206 | |||
207 | case I2C_SMBUS_WORD_DATA: | ||
208 | amd_ec_write(smbus, AMD_SMB_CMD, command); | ||
209 | if (read_write == I2C_SMBUS_WRITE) { | ||
210 | amd_ec_write(smbus, AMD_SMB_DATA, data->word); | ||
211 | amd_ec_write(smbus, AMD_SMB_DATA + 1, data->word >> 8); | ||
212 | } | ||
213 | protocol |= AMD_SMB_PRTCL_WORD_DATA | pec; | ||
214 | break; | ||
215 | |||
216 | case I2C_SMBUS_BLOCK_DATA: | ||
217 | amd_ec_write(smbus, AMD_SMB_CMD, command); | ||
218 | if (read_write == I2C_SMBUS_WRITE) { | ||
219 | len = min_t(u8, data->block[0], 32); | ||
220 | amd_ec_write(smbus, AMD_SMB_BCNT, len); | ||
221 | for (i = 0; i < len; i++) | ||
222 | amd_ec_write(smbus, AMD_SMB_DATA + i, data->block[i + 1]); | ||
223 | } | ||
224 | protocol |= AMD_SMB_PRTCL_BLOCK_DATA | pec; | ||
225 | break; | ||
226 | |||
227 | case I2C_SMBUS_I2C_BLOCK_DATA: | ||
228 | len = min_t(u8, data->block[0], 32); | ||
229 | amd_ec_write(smbus, AMD_SMB_CMD, command); | ||
230 | amd_ec_write(smbus, AMD_SMB_BCNT, len); | ||
231 | if (read_write == I2C_SMBUS_WRITE) | ||
232 | for (i = 0; i < len; i++) | ||
233 | amd_ec_write(smbus, AMD_SMB_DATA + i, data->block[i + 1]); | ||
234 | protocol |= AMD_SMB_PRTCL_I2C_BLOCK_DATA; | ||
235 | break; | ||
236 | |||
237 | case I2C_SMBUS_PROC_CALL: | ||
238 | amd_ec_write(smbus, AMD_SMB_CMD, command); | ||
239 | amd_ec_write(smbus, AMD_SMB_DATA, data->word); | ||
240 | amd_ec_write(smbus, AMD_SMB_DATA + 1, data->word >> 8); | ||
241 | protocol = AMD_SMB_PRTCL_PROC_CALL | pec; | ||
242 | read_write = I2C_SMBUS_READ; | ||
243 | break; | ||
244 | |||
245 | case I2C_SMBUS_BLOCK_PROC_CALL: | ||
246 | protocol |= pec; | ||
247 | len = min_t(u8, data->block[0], 31); | ||
248 | amd_ec_write(smbus, AMD_SMB_CMD, command); | ||
249 | amd_ec_write(smbus, AMD_SMB_BCNT, len); | ||
250 | for (i = 0; i < len; i++) | ||
251 | amd_ec_write(smbus, AMD_SMB_DATA + i, data->block[i + 1]); | ||
252 | protocol = AMD_SMB_PRTCL_BLOCK_PROC_CALL | pec; | ||
253 | read_write = I2C_SMBUS_READ; | ||
254 | break; | ||
255 | |||
256 | case I2C_SMBUS_WORD_DATA_PEC: | ||
257 | case I2C_SMBUS_BLOCK_DATA_PEC: | ||
258 | case I2C_SMBUS_PROC_CALL_PEC: | ||
259 | case I2C_SMBUS_BLOCK_PROC_CALL_PEC: | ||
260 | dev_warn(&adap->dev, "Unexpected software PEC transaction %d\n.", size); | ||
261 | return -1; | ||
262 | |||
263 | default: | ||
264 | dev_warn(&adap->dev, "Unsupported transaction %d\n", size); | ||
265 | return -1; | ||
266 | } | ||
267 | |||
268 | amd_ec_write(smbus, AMD_SMB_ADDR, addr << 1); | ||
269 | amd_ec_write(smbus, AMD_SMB_PRTCL, protocol); | ||
270 | |||
271 | amd_ec_read(smbus, AMD_SMB_STS, temp + 0); | ||
272 | |||
273 | if (~temp[0] & AMD_SMB_STS_DONE) { | ||
274 | udelay(500); | ||
275 | amd_ec_read(smbus, AMD_SMB_STS, temp + 0); | ||
276 | } | ||
277 | |||
278 | if (~temp[0] & AMD_SMB_STS_DONE) { | ||
279 | msleep(1); | ||
280 | amd_ec_read(smbus, AMD_SMB_STS, temp + 0); | ||
281 | } | ||
282 | |||
283 | if ((~temp[0] & AMD_SMB_STS_DONE) || (temp[0] & AMD_SMB_STS_STATUS)) | ||
284 | return -1; | ||
285 | |||
286 | if (read_write == I2C_SMBUS_WRITE) | ||
287 | return 0; | ||
288 | |||
289 | switch (size) { | ||
290 | |||
291 | case I2C_SMBUS_BYTE: | ||
292 | case I2C_SMBUS_BYTE_DATA: | ||
293 | amd_ec_read(smbus, AMD_SMB_DATA, &data->byte); | ||
294 | break; | ||
295 | |||
296 | case I2C_SMBUS_WORD_DATA: | ||
297 | case I2C_SMBUS_PROC_CALL: | ||
298 | amd_ec_read(smbus, AMD_SMB_DATA, temp + 0); | ||
299 | amd_ec_read(smbus, AMD_SMB_DATA + 1, temp + 1); | ||
300 | data->word = (temp[1] << 8) | temp[0]; | ||
301 | break; | ||
302 | |||
303 | case I2C_SMBUS_BLOCK_DATA: | ||
304 | case I2C_SMBUS_BLOCK_PROC_CALL: | ||
305 | amd_ec_read(smbus, AMD_SMB_BCNT, &len); | ||
306 | len = min_t(u8, len, 32); | ||
307 | case I2C_SMBUS_I2C_BLOCK_DATA: | ||
308 | for (i = 0; i < len; i++) | ||
309 | amd_ec_read(smbus, AMD_SMB_DATA + i, data->block + i + 1); | ||
310 | data->block[0] = len; | ||
311 | break; | ||
312 | } | ||
313 | |||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | |||
318 | static u32 amd8111_func(struct i2c_adapter *adapter) | ||
319 | { | ||
320 | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | | ||
321 | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA | | ||
322 | I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_PROC_CALL | | ||
323 | I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HWPEC_CALC; | ||
324 | } | ||
325 | |||
326 | static struct i2c_algorithm smbus_algorithm = { | ||
327 | .name = "Non-I2C SMBus 2.0 adapter", | ||
328 | .id = I2C_ALGO_SMBUS, | ||
329 | .smbus_xfer = amd8111_access, | ||
330 | .functionality = amd8111_func, | ||
331 | }; | ||
332 | |||
333 | |||
334 | static struct pci_device_id amd8111_ids[] = { | ||
335 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS2) }, | ||
336 | { 0, } | ||
337 | }; | ||
338 | |||
339 | MODULE_DEVICE_TABLE (pci, amd8111_ids); | ||
340 | |||
341 | static int __devinit amd8111_probe(struct pci_dev *dev, const struct pci_device_id *id) | ||
342 | { | ||
343 | struct amd_smbus *smbus; | ||
344 | int error = -ENODEV; | ||
345 | |||
346 | if (~pci_resource_flags(dev, 0) & IORESOURCE_IO) | ||
347 | return -ENODEV; | ||
348 | |||
349 | smbus = kmalloc(sizeof(struct amd_smbus), GFP_KERNEL); | ||
350 | if (!smbus) | ||
351 | return -ENOMEM; | ||
352 | memset(smbus, 0, sizeof(struct amd_smbus)); | ||
353 | |||
354 | smbus->dev = dev; | ||
355 | smbus->base = pci_resource_start(dev, 0); | ||
356 | smbus->size = pci_resource_len(dev, 0); | ||
357 | |||
358 | if (!request_region(smbus->base, smbus->size, "amd8111 SMBus 2.0")) | ||
359 | goto out_kfree; | ||
360 | |||
361 | smbus->adapter.owner = THIS_MODULE; | ||
362 | snprintf(smbus->adapter.name, I2C_NAME_SIZE, | ||
363 | "SMBus2 AMD8111 adapter at %04x", smbus->base); | ||
364 | smbus->adapter.class = I2C_CLASS_HWMON; | ||
365 | smbus->adapter.algo = &smbus_algorithm; | ||
366 | smbus->adapter.algo_data = smbus; | ||
367 | |||
368 | /* set up the driverfs linkage to our parent device */ | ||
369 | smbus->adapter.dev.parent = &dev->dev; | ||
370 | |||
371 | error = i2c_add_adapter(&smbus->adapter); | ||
372 | if (error) | ||
373 | goto out_release_region; | ||
374 | |||
375 | pci_write_config_dword(smbus->dev, AMD_PCI_MISC, 0); | ||
376 | pci_set_drvdata(dev, smbus); | ||
377 | return 0; | ||
378 | |||
379 | out_release_region: | ||
380 | release_region(smbus->base, smbus->size); | ||
381 | out_kfree: | ||
382 | kfree(smbus); | ||
383 | return -1; | ||
384 | } | ||
385 | |||
386 | |||
387 | static void __devexit amd8111_remove(struct pci_dev *dev) | ||
388 | { | ||
389 | struct amd_smbus *smbus = pci_get_drvdata(dev); | ||
390 | |||
391 | i2c_del_adapter(&smbus->adapter); | ||
392 | release_region(smbus->base, smbus->size); | ||
393 | kfree(smbus); | ||
394 | } | ||
395 | |||
396 | static struct pci_driver amd8111_driver = { | ||
397 | .name = "amd8111_smbus2", | ||
398 | .id_table = amd8111_ids, | ||
399 | .probe = amd8111_probe, | ||
400 | .remove = __devexit_p(amd8111_remove), | ||
401 | }; | ||
402 | |||
403 | static int __init i2c_amd8111_init(void) | ||
404 | { | ||
405 | return pci_register_driver(&amd8111_driver); | ||
406 | } | ||
407 | |||
408 | |||
409 | static void __exit i2c_amd8111_exit(void) | ||
410 | { | ||
411 | pci_unregister_driver(&amd8111_driver); | ||
412 | } | ||
413 | |||
414 | module_init(i2c_amd8111_init); | ||
415 | module_exit(i2c_amd8111_exit); | ||
diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c new file mode 100644 index 000000000000..75831a20b0bd --- /dev/null +++ b/drivers/i2c/busses/i2c-au1550.c | |||
@@ -0,0 +1,435 @@ | |||
1 | /* | ||
2 | * i2c-au1550.c: SMBus (i2c) adapter for Alchemy PSC interface | ||
3 | * Copyright (C) 2004 Embedded Edge, LLC <dan@embeddededge.com> | ||
4 | * | ||
5 | * 2.6 port by Matt Porter <mporter@kernel.crashing.org> | ||
6 | * | ||
7 | * The documentation describes this as an SMBus controller, but it doesn't | ||
8 | * understand any of the SMBus protocol in hardware. It's really an I2C | ||
9 | * controller that could emulate most of the SMBus in software. | ||
10 | * | ||
11 | * This is just a skeleton adapter to use with the Au1550 PSC | ||
12 | * algorithm. It was developed for the Pb1550, but will work with | ||
13 | * any Au1550 board that has a similar PSC configuration. | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or | ||
16 | * modify it under the terms of the GNU General Public License | ||
17 | * as published by the Free Software Foundation; either version 2 | ||
18 | * of the License, or (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, write to the Free Software | ||
27 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
28 | */ | ||
29 | |||
30 | #include <linux/config.h> | ||
31 | #include <linux/delay.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/init.h> | ||
35 | #include <linux/errno.h> | ||
36 | #include <linux/i2c.h> | ||
37 | |||
38 | #include <asm/mach-au1x00/au1000.h> | ||
39 | #include <asm/mach-pb1x00/pb1550.h> | ||
40 | #include <asm/mach-au1x00/au1xxx_psc.h> | ||
41 | |||
42 | #include "i2c-au1550.h" | ||
43 | |||
44 | static int | ||
45 | wait_xfer_done(struct i2c_au1550_data *adap) | ||
46 | { | ||
47 | u32 stat; | ||
48 | int i; | ||
49 | volatile psc_smb_t *sp; | ||
50 | |||
51 | sp = (volatile psc_smb_t *)(adap->psc_base); | ||
52 | |||
53 | /* Wait for Tx FIFO Underflow. | ||
54 | */ | ||
55 | for (i = 0; i < adap->xfer_timeout; i++) { | ||
56 | stat = sp->psc_smbevnt; | ||
57 | au_sync(); | ||
58 | if ((stat & PSC_SMBEVNT_TU) != 0) { | ||
59 | /* Clear it. */ | ||
60 | sp->psc_smbevnt = PSC_SMBEVNT_TU; | ||
61 | au_sync(); | ||
62 | return 0; | ||
63 | } | ||
64 | udelay(1); | ||
65 | } | ||
66 | |||
67 | return -ETIMEDOUT; | ||
68 | } | ||
69 | |||
70 | static int | ||
71 | wait_ack(struct i2c_au1550_data *adap) | ||
72 | { | ||
73 | u32 stat; | ||
74 | volatile psc_smb_t *sp; | ||
75 | |||
76 | if (wait_xfer_done(adap)) | ||
77 | return -ETIMEDOUT; | ||
78 | |||
79 | sp = (volatile psc_smb_t *)(adap->psc_base); | ||
80 | |||
81 | stat = sp->psc_smbevnt; | ||
82 | au_sync(); | ||
83 | |||
84 | if ((stat & (PSC_SMBEVNT_DN | PSC_SMBEVNT_AN | PSC_SMBEVNT_AL)) != 0) | ||
85 | return -ETIMEDOUT; | ||
86 | |||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static int | ||
91 | wait_master_done(struct i2c_au1550_data *adap) | ||
92 | { | ||
93 | u32 stat; | ||
94 | int i; | ||
95 | volatile psc_smb_t *sp; | ||
96 | |||
97 | sp = (volatile psc_smb_t *)(adap->psc_base); | ||
98 | |||
99 | /* Wait for Master Done. | ||
100 | */ | ||
101 | for (i = 0; i < adap->xfer_timeout; i++) { | ||
102 | stat = sp->psc_smbevnt; | ||
103 | au_sync(); | ||
104 | if ((stat & PSC_SMBEVNT_MD) != 0) | ||
105 | return 0; | ||
106 | udelay(1); | ||
107 | } | ||
108 | |||
109 | return -ETIMEDOUT; | ||
110 | } | ||
111 | |||
112 | static int | ||
113 | do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd) | ||
114 | { | ||
115 | volatile psc_smb_t *sp; | ||
116 | u32 stat; | ||
117 | |||
118 | sp = (volatile psc_smb_t *)(adap->psc_base); | ||
119 | |||
120 | /* Reset the FIFOs, clear events. | ||
121 | */ | ||
122 | sp->psc_smbpcr = PSC_SMBPCR_DC; | ||
123 | sp->psc_smbevnt = PSC_SMBEVNT_ALLCLR; | ||
124 | au_sync(); | ||
125 | do { | ||
126 | stat = sp->psc_smbpcr; | ||
127 | au_sync(); | ||
128 | } while ((stat & PSC_SMBPCR_DC) != 0); | ||
129 | |||
130 | /* Write out the i2c chip address and specify operation | ||
131 | */ | ||
132 | addr <<= 1; | ||
133 | if (rd) | ||
134 | addr |= 1; | ||
135 | |||
136 | /* Put byte into fifo, start up master. | ||
137 | */ | ||
138 | sp->psc_smbtxrx = addr; | ||
139 | au_sync(); | ||
140 | sp->psc_smbpcr = PSC_SMBPCR_MS; | ||
141 | au_sync(); | ||
142 | if (wait_ack(adap)) | ||
143 | return -EIO; | ||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static u32 | ||
148 | wait_for_rx_byte(struct i2c_au1550_data *adap, u32 *ret_data) | ||
149 | { | ||
150 | int j; | ||
151 | u32 data, stat; | ||
152 | volatile psc_smb_t *sp; | ||
153 | |||
154 | if (wait_xfer_done(adap)) | ||
155 | return -EIO; | ||
156 | |||
157 | sp = (volatile psc_smb_t *)(adap->psc_base); | ||
158 | |||
159 | j = adap->xfer_timeout * 100; | ||
160 | do { | ||
161 | j--; | ||
162 | if (j <= 0) | ||
163 | return -EIO; | ||
164 | |||
165 | stat = sp->psc_smbstat; | ||
166 | au_sync(); | ||
167 | if ((stat & PSC_SMBSTAT_RE) == 0) | ||
168 | j = 0; | ||
169 | else | ||
170 | udelay(1); | ||
171 | } while (j > 0); | ||
172 | data = sp->psc_smbtxrx; | ||
173 | au_sync(); | ||
174 | *ret_data = data; | ||
175 | |||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static int | ||
180 | i2c_read(struct i2c_au1550_data *adap, unsigned char *buf, | ||
181 | unsigned int len) | ||
182 | { | ||
183 | int i; | ||
184 | u32 data; | ||
185 | volatile psc_smb_t *sp; | ||
186 | |||
187 | if (len == 0) | ||
188 | return 0; | ||
189 | |||
190 | /* A read is performed by stuffing the transmit fifo with | ||
191 | * zero bytes for timing, waiting for bytes to appear in the | ||
192 | * receive fifo, then reading the bytes. | ||
193 | */ | ||
194 | |||
195 | sp = (volatile psc_smb_t *)(adap->psc_base); | ||
196 | |||
197 | i = 0; | ||
198 | while (i < (len-1)) { | ||
199 | sp->psc_smbtxrx = 0; | ||
200 | au_sync(); | ||
201 | if (wait_for_rx_byte(adap, &data)) | ||
202 | return -EIO; | ||
203 | |||
204 | buf[i] = data; | ||
205 | i++; | ||
206 | } | ||
207 | |||
208 | /* The last byte has to indicate transfer done. | ||
209 | */ | ||
210 | sp->psc_smbtxrx = PSC_SMBTXRX_STP; | ||
211 | au_sync(); | ||
212 | if (wait_master_done(adap)) | ||
213 | return -EIO; | ||
214 | |||
215 | data = sp->psc_smbtxrx; | ||
216 | au_sync(); | ||
217 | buf[i] = data; | ||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static int | ||
222 | i2c_write(struct i2c_au1550_data *adap, unsigned char *buf, | ||
223 | unsigned int len) | ||
224 | { | ||
225 | int i; | ||
226 | u32 data; | ||
227 | volatile psc_smb_t *sp; | ||
228 | |||
229 | if (len == 0) | ||
230 | return 0; | ||
231 | |||
232 | sp = (volatile psc_smb_t *)(adap->psc_base); | ||
233 | |||
234 | i = 0; | ||
235 | while (i < (len-1)) { | ||
236 | data = buf[i]; | ||
237 | sp->psc_smbtxrx = data; | ||
238 | au_sync(); | ||
239 | if (wait_ack(adap)) | ||
240 | return -EIO; | ||
241 | i++; | ||
242 | } | ||
243 | |||
244 | /* The last byte has to indicate transfer done. | ||
245 | */ | ||
246 | data = buf[i]; | ||
247 | data |= PSC_SMBTXRX_STP; | ||
248 | sp->psc_smbtxrx = data; | ||
249 | au_sync(); | ||
250 | if (wait_master_done(adap)) | ||
251 | return -EIO; | ||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | static int | ||
256 | au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) | ||
257 | { | ||
258 | struct i2c_au1550_data *adap = i2c_adap->algo_data; | ||
259 | struct i2c_msg *p; | ||
260 | int i, err = 0; | ||
261 | |||
262 | for (i = 0; !err && i < num; i++) { | ||
263 | p = &msgs[i]; | ||
264 | err = do_address(adap, p->addr, p->flags & I2C_M_RD); | ||
265 | if (err || !p->len) | ||
266 | continue; | ||
267 | if (p->flags & I2C_M_RD) | ||
268 | err = i2c_read(adap, p->buf, p->len); | ||
269 | else | ||
270 | err = i2c_write(adap, p->buf, p->len); | ||
271 | } | ||
272 | |||
273 | /* Return the number of messages processed, or the error code. | ||
274 | */ | ||
275 | if (err == 0) | ||
276 | err = num; | ||
277 | return err; | ||
278 | } | ||
279 | |||
280 | static u32 | ||
281 | au1550_func(struct i2c_adapter *adap) | ||
282 | { | ||
283 | return I2C_FUNC_I2C; | ||
284 | } | ||
285 | |||
286 | static struct i2c_algorithm au1550_algo = { | ||
287 | .name = "Au1550 algorithm", | ||
288 | .id = I2C_ALGO_AU1550, | ||
289 | .master_xfer = au1550_xfer, | ||
290 | .functionality = au1550_func, | ||
291 | }; | ||
292 | |||
293 | /* | ||
294 | * registering functions to load algorithms at runtime | ||
295 | * Prior to calling us, the 50MHz clock frequency and routing | ||
296 | * must have been set up for the PSC indicated by the adapter. | ||
297 | */ | ||
298 | int | ||
299 | i2c_au1550_add_bus(struct i2c_adapter *i2c_adap) | ||
300 | { | ||
301 | struct i2c_au1550_data *adap = i2c_adap->algo_data; | ||
302 | volatile psc_smb_t *sp; | ||
303 | u32 stat; | ||
304 | |||
305 | i2c_adap->algo = &au1550_algo; | ||
306 | |||
307 | /* Now, set up the PSC for SMBus PIO mode. | ||
308 | */ | ||
309 | sp = (volatile psc_smb_t *)(adap->psc_base); | ||
310 | sp->psc_ctrl = PSC_CTRL_DISABLE; | ||
311 | au_sync(); | ||
312 | sp->psc_sel = PSC_SEL_PS_SMBUSMODE; | ||
313 | sp->psc_smbcfg = 0; | ||
314 | au_sync(); | ||
315 | sp->psc_ctrl = PSC_CTRL_ENABLE; | ||
316 | au_sync(); | ||
317 | do { | ||
318 | stat = sp->psc_smbstat; | ||
319 | au_sync(); | ||
320 | } while ((stat & PSC_SMBSTAT_SR) == 0); | ||
321 | |||
322 | sp->psc_smbcfg = (PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 | | ||
323 | PSC_SMBCFG_DD_DISABLE); | ||
324 | |||
325 | /* Divide by 8 to get a 6.25 MHz clock. The later protocol | ||
326 | * timings are based on this clock. | ||
327 | */ | ||
328 | sp->psc_smbcfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8); | ||
329 | sp->psc_smbmsk = PSC_SMBMSK_ALLMASK; | ||
330 | au_sync(); | ||
331 | |||
332 | /* Set the protocol timer values. See Table 71 in the | ||
333 | * Au1550 Data Book for standard timing values. | ||
334 | */ | ||
335 | sp->psc_smbtmr = PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(15) | \ | ||
336 | PSC_SMBTMR_SET_PU(15) | PSC_SMBTMR_SET_SH(15) | \ | ||
337 | PSC_SMBTMR_SET_SU(15) | PSC_SMBTMR_SET_CL(15) | \ | ||
338 | PSC_SMBTMR_SET_CH(15); | ||
339 | au_sync(); | ||
340 | |||
341 | sp->psc_smbcfg |= PSC_SMBCFG_DE_ENABLE; | ||
342 | do { | ||
343 | stat = sp->psc_smbstat; | ||
344 | au_sync(); | ||
345 | } while ((stat & PSC_SMBSTAT_DR) == 0); | ||
346 | |||
347 | return i2c_add_adapter(i2c_adap); | ||
348 | } | ||
349 | |||
350 | |||
351 | int | ||
352 | i2c_au1550_del_bus(struct i2c_adapter *adap) | ||
353 | { | ||
354 | return i2c_del_adapter(adap); | ||
355 | } | ||
356 | |||
357 | static int | ||
358 | pb1550_reg(struct i2c_client *client) | ||
359 | { | ||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static int | ||
364 | pb1550_unreg(struct i2c_client *client) | ||
365 | { | ||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | static struct i2c_au1550_data pb1550_i2c_info = { | ||
370 | SMBUS_PSC_BASE, 200, 200 | ||
371 | }; | ||
372 | |||
373 | static struct i2c_adapter pb1550_board_adapter = { | ||
374 | name: "pb1550 adapter", | ||
375 | id: I2C_HW_AU1550_PSC, | ||
376 | algo: NULL, | ||
377 | algo_data: &pb1550_i2c_info, | ||
378 | client_register: pb1550_reg, | ||
379 | client_unregister: pb1550_unreg, | ||
380 | }; | ||
381 | |||
382 | /* BIG hack to support the control interface on the Wolfson WM8731 | ||
383 | * audio codec on the Pb1550 board. We get an address and two data | ||
384 | * bytes to write, create an i2c message, and send it across the | ||
385 | * i2c transfer function. We do this here because we have access to | ||
386 | * the i2c adapter structure. | ||
387 | */ | ||
388 | static struct i2c_msg wm_i2c_msg; /* We don't want this stuff on the stack */ | ||
389 | static u8 i2cbuf[2]; | ||
390 | |||
391 | int | ||
392 | pb1550_wm_codec_write(u8 addr, u8 reg, u8 val) | ||
393 | { | ||
394 | wm_i2c_msg.addr = addr; | ||
395 | wm_i2c_msg.flags = 0; | ||
396 | wm_i2c_msg.buf = i2cbuf; | ||
397 | wm_i2c_msg.len = 2; | ||
398 | i2cbuf[0] = reg; | ||
399 | i2cbuf[1] = val; | ||
400 | |||
401 | return pb1550_board_adapter.algo->master_xfer(&pb1550_board_adapter, &wm_i2c_msg, 1); | ||
402 | } | ||
403 | |||
404 | static int __init | ||
405 | i2c_au1550_init(void) | ||
406 | { | ||
407 | printk(KERN_INFO "Au1550 I2C: "); | ||
408 | |||
409 | /* This is where we would set up a 50MHz clock source | ||
410 | * and routing. On the Pb1550, the SMBus is PSC2, which | ||
411 | * uses a shared clock with USB. This has been already | ||
412 | * configured by Yamon as a 48MHz clock, close enough | ||
413 | * for our work. | ||
414 | */ | ||
415 | if (i2c_au1550_add_bus(&pb1550_board_adapter) < 0) { | ||
416 | printk("failed to initialize.\n"); | ||
417 | return -ENODEV; | ||
418 | } | ||
419 | |||
420 | printk("initialized.\n"); | ||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | static void __exit | ||
425 | i2c_au1550_exit(void) | ||
426 | { | ||
427 | i2c_au1550_del_bus(&pb1550_board_adapter); | ||
428 | } | ||
429 | |||
430 | MODULE_AUTHOR("Dan Malek, Embedded Edge, LLC."); | ||
431 | MODULE_DESCRIPTION("SMBus adapter Alchemy pb1550"); | ||
432 | MODULE_LICENSE("GPL"); | ||
433 | |||
434 | module_init (i2c_au1550_init); | ||
435 | module_exit (i2c_au1550_exit); | ||
diff --git a/drivers/i2c/busses/i2c-au1550.h b/drivers/i2c/busses/i2c-au1550.h new file mode 100644 index 000000000000..fce15d161ae7 --- /dev/null +++ b/drivers/i2c/busses/i2c-au1550.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004 Embedded Edge, LLC <dan@embeddededge.com> | ||
3 | * 2.6 port by Matt Porter <mporter@kernel.crashing.org> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #ifndef I2C_AU1550_H | ||
21 | #define I2C_AU1550_H | ||
22 | |||
23 | struct i2c_au1550_data { | ||
24 | u32 psc_base; | ||
25 | int xfer_timeout; | ||
26 | int ack_timeout; | ||
27 | }; | ||
28 | |||
29 | int i2c_au1550_add_bus(struct i2c_adapter *); | ||
30 | int i2c_au1550_del_bus(struct i2c_adapter *); | ||
31 | |||
32 | #endif /* I2C_AU1550_H */ | ||
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c new file mode 100644 index 000000000000..0a7720000a0c --- /dev/null +++ b/drivers/i2c/busses/i2c-elektor.c | |||
@@ -0,0 +1,295 @@ | |||
1 | /* ------------------------------------------------------------------------- */ | ||
2 | /* i2c-elektor.c i2c-hw access for PCF8584 style isa bus adaptes */ | ||
3 | /* ------------------------------------------------------------------------- */ | ||
4 | /* Copyright (C) 1995-97 Simon G. Vogl | ||
5 | 1998-99 Hans Berglund | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
20 | /* ------------------------------------------------------------------------- */ | ||
21 | |||
22 | /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even | ||
23 | Frodo Looijaard <frodol@dds.nl> */ | ||
24 | |||
25 | /* Partialy rewriten by Oleg I. Vdovikin for mmapped support of | ||
26 | for Alpha Processor Inc. UP-2000(+) boards */ | ||
27 | |||
28 | #include <linux/config.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/ioport.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <linux/init.h> | ||
35 | #include <linux/interrupt.h> | ||
36 | #include <linux/pci.h> | ||
37 | #include <linux/wait.h> | ||
38 | |||
39 | #include <linux/i2c.h> | ||
40 | #include <linux/i2c-algo-pcf.h> | ||
41 | |||
42 | #include <asm/io.h> | ||
43 | #include <asm/irq.h> | ||
44 | |||
45 | #include "../algos/i2c-algo-pcf.h" | ||
46 | |||
47 | #define DEFAULT_BASE 0x330 | ||
48 | |||
49 | static int base; | ||
50 | static int irq; | ||
51 | static int clock = 0x1c; | ||
52 | static int own = 0x55; | ||
53 | static int mmapped; | ||
54 | |||
55 | /* vdovikin: removed static struct i2c_pcf_isa gpi; code - | ||
56 | this module in real supports only one device, due to missing arguments | ||
57 | in some functions, called from the algo-pcf module. Sometimes it's | ||
58 | need to be rewriten - but for now just remove this for simpler reading */ | ||
59 | |||
60 | static wait_queue_head_t pcf_wait; | ||
61 | static int pcf_pending; | ||
62 | static spinlock_t lock; | ||
63 | |||
64 | /* ----- local functions ---------------------------------------------- */ | ||
65 | |||
66 | static void pcf_isa_setbyte(void *data, int ctl, int val) | ||
67 | { | ||
68 | int address = ctl ? (base + 1) : base; | ||
69 | |||
70 | /* enable irq if any specified for serial operation */ | ||
71 | if (ctl && irq && (val & I2C_PCF_ESO)) { | ||
72 | val |= I2C_PCF_ENI; | ||
73 | } | ||
74 | |||
75 | pr_debug("i2c-elektor: Write 0x%X 0x%02X\n", address, val & 255); | ||
76 | |||
77 | switch (mmapped) { | ||
78 | case 0: /* regular I/O */ | ||
79 | outb(val, address); | ||
80 | break; | ||
81 | case 2: /* double mapped I/O needed for UP2000 board, | ||
82 | I don't know why this... */ | ||
83 | writeb(val, (void *)address); | ||
84 | /* fall */ | ||
85 | case 1: /* memory mapped I/O */ | ||
86 | writeb(val, (void *)address); | ||
87 | break; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | static int pcf_isa_getbyte(void *data, int ctl) | ||
92 | { | ||
93 | int address = ctl ? (base + 1) : base; | ||
94 | int val = mmapped ? readb((void *)address) : inb(address); | ||
95 | |||
96 | pr_debug("i2c-elektor: Read 0x%X 0x%02X\n", address, val); | ||
97 | |||
98 | return (val); | ||
99 | } | ||
100 | |||
101 | static int pcf_isa_getown(void *data) | ||
102 | { | ||
103 | return (own); | ||
104 | } | ||
105 | |||
106 | |||
107 | static int pcf_isa_getclock(void *data) | ||
108 | { | ||
109 | return (clock); | ||
110 | } | ||
111 | |||
112 | static void pcf_isa_waitforpin(void) { | ||
113 | DEFINE_WAIT(wait); | ||
114 | int timeout = 2; | ||
115 | unsigned long flags; | ||
116 | |||
117 | if (irq > 0) { | ||
118 | spin_lock_irqsave(&lock, flags); | ||
119 | if (pcf_pending == 0) { | ||
120 | spin_unlock_irqrestore(&lock, flags); | ||
121 | prepare_to_wait(&pcf_wait, &wait, TASK_INTERRUPTIBLE); | ||
122 | if (schedule_timeout(timeout*HZ)) { | ||
123 | spin_lock_irqsave(&lock, flags); | ||
124 | if (pcf_pending == 1) { | ||
125 | pcf_pending = 0; | ||
126 | } | ||
127 | spin_unlock_irqrestore(&lock, flags); | ||
128 | } | ||
129 | finish_wait(&pcf_wait, &wait); | ||
130 | } else { | ||
131 | pcf_pending = 0; | ||
132 | spin_unlock_irqrestore(&lock, flags); | ||
133 | } | ||
134 | } else { | ||
135 | udelay(100); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | |||
140 | static irqreturn_t pcf_isa_handler(int this_irq, void *dev_id, struct pt_regs *regs) { | ||
141 | spin_lock(&lock); | ||
142 | pcf_pending = 1; | ||
143 | spin_unlock(&lock); | ||
144 | wake_up_interruptible(&pcf_wait); | ||
145 | return IRQ_HANDLED; | ||
146 | } | ||
147 | |||
148 | |||
149 | static int pcf_isa_init(void) | ||
150 | { | ||
151 | spin_lock_init(&lock); | ||
152 | if (!mmapped) { | ||
153 | if (!request_region(base, 2, "i2c (isa bus adapter)")) { | ||
154 | printk(KERN_ERR | ||
155 | "i2c-elektor: requested I/O region (0x%X:2) " | ||
156 | "is in use.\n", base); | ||
157 | return -ENODEV; | ||
158 | } | ||
159 | } | ||
160 | if (irq > 0) { | ||
161 | if (request_irq(irq, pcf_isa_handler, 0, "PCF8584", NULL) < 0) { | ||
162 | printk(KERN_ERR "i2c-elektor: Request irq%d failed\n", irq); | ||
163 | irq = 0; | ||
164 | } else | ||
165 | enable_irq(irq); | ||
166 | } | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | /* ------------------------------------------------------------------------ | ||
171 | * Encapsulate the above functions in the correct operations structure. | ||
172 | * This is only done when more than one hardware adapter is supported. | ||
173 | */ | ||
174 | static struct i2c_algo_pcf_data pcf_isa_data = { | ||
175 | .setpcf = pcf_isa_setbyte, | ||
176 | .getpcf = pcf_isa_getbyte, | ||
177 | .getown = pcf_isa_getown, | ||
178 | .getclock = pcf_isa_getclock, | ||
179 | .waitforpin = pcf_isa_waitforpin, | ||
180 | .udelay = 10, | ||
181 | .mdelay = 10, | ||
182 | .timeout = 100, | ||
183 | }; | ||
184 | |||
185 | static struct i2c_adapter pcf_isa_ops = { | ||
186 | .owner = THIS_MODULE, | ||
187 | .class = I2C_CLASS_HWMON, | ||
188 | .id = I2C_HW_P_ELEK, | ||
189 | .algo_data = &pcf_isa_data, | ||
190 | .name = "PCF8584 ISA adapter", | ||
191 | }; | ||
192 | |||
193 | static int __init i2c_pcfisa_init(void) | ||
194 | { | ||
195 | #ifdef __alpha__ | ||
196 | /* check to see we have memory mapped PCF8584 connected to the | ||
197 | Cypress cy82c693 PCI-ISA bridge as on UP2000 board */ | ||
198 | if (base == 0) { | ||
199 | struct pci_dev *cy693_dev; | ||
200 | |||
201 | cy693_dev = pci_get_device(PCI_VENDOR_ID_CONTAQ, | ||
202 | PCI_DEVICE_ID_CONTAQ_82C693, NULL); | ||
203 | if (cy693_dev) { | ||
204 | char config; | ||
205 | /* yeap, we've found cypress, let's check config */ | ||
206 | if (!pci_read_config_byte(cy693_dev, 0x47, &config)) { | ||
207 | |||
208 | pr_debug("i2c-elektor: found cy82c693, config register 0x47 = 0x%02x.\n", config); | ||
209 | |||
210 | /* UP2000 board has this register set to 0xe1, | ||
211 | but the most significant bit as seems can be | ||
212 | reset during the proper initialisation | ||
213 | sequence if guys from API decides to do that | ||
214 | (so, we can even enable Tsunami Pchip | ||
215 | window for the upper 1 Gb) */ | ||
216 | |||
217 | /* so just check for ROMCS at 0xe0000, | ||
218 | ROMCS enabled for writes | ||
219 | and external XD Bus buffer in use. */ | ||
220 | if ((config & 0x7f) == 0x61) { | ||
221 | /* seems to be UP2000 like board */ | ||
222 | base = 0xe0000; | ||
223 | /* I don't know why we need to | ||
224 | write twice */ | ||
225 | mmapped = 2; | ||
226 | /* UP2000 drives ISA with | ||
227 | 8.25 MHz (PCI/4) clock | ||
228 | (this can be read from cypress) */ | ||
229 | clock = I2C_PCF_CLK | I2C_PCF_TRNS90; | ||
230 | printk(KERN_INFO "i2c-elektor: found API UP2000 like board, will probe PCF8584 later.\n"); | ||
231 | } | ||
232 | } | ||
233 | pci_dev_put(cy693_dev); | ||
234 | } | ||
235 | } | ||
236 | #endif | ||
237 | |||
238 | /* sanity checks for mmapped I/O */ | ||
239 | if (mmapped && base < 0xc8000) { | ||
240 | printk(KERN_ERR "i2c-elektor: incorrect base address (0x%0X) specified for mmapped I/O.\n", base); | ||
241 | return -ENODEV; | ||
242 | } | ||
243 | |||
244 | printk(KERN_INFO "i2c-elektor: i2c pcf8584-isa adapter driver\n"); | ||
245 | |||
246 | if (base == 0) { | ||
247 | base = DEFAULT_BASE; | ||
248 | } | ||
249 | |||
250 | init_waitqueue_head(&pcf_wait); | ||
251 | if (pcf_isa_init()) | ||
252 | return -ENODEV; | ||
253 | if (i2c_pcf_add_bus(&pcf_isa_ops) < 0) | ||
254 | goto fail; | ||
255 | |||
256 | printk(KERN_ERR "i2c-elektor: found device at %#x.\n", base); | ||
257 | |||
258 | return 0; | ||
259 | |||
260 | fail: | ||
261 | if (irq > 0) { | ||
262 | disable_irq(irq); | ||
263 | free_irq(irq, NULL); | ||
264 | } | ||
265 | |||
266 | if (!mmapped) | ||
267 | release_region(base , 2); | ||
268 | return -ENODEV; | ||
269 | } | ||
270 | |||
271 | static void i2c_pcfisa_exit(void) | ||
272 | { | ||
273 | i2c_pcf_del_bus(&pcf_isa_ops); | ||
274 | |||
275 | if (irq > 0) { | ||
276 | disable_irq(irq); | ||
277 | free_irq(irq, NULL); | ||
278 | } | ||
279 | |||
280 | if (!mmapped) | ||
281 | release_region(base , 2); | ||
282 | } | ||
283 | |||
284 | MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>"); | ||
285 | MODULE_DESCRIPTION("I2C-Bus adapter routines for PCF8584 ISA bus adapter"); | ||
286 | MODULE_LICENSE("GPL"); | ||
287 | |||
288 | module_param(base, int, 0); | ||
289 | module_param(irq, int, 0); | ||
290 | module_param(clock, int, 0); | ||
291 | module_param(own, int, 0); | ||
292 | module_param(mmapped, int, 0); | ||
293 | |||
294 | module_init(i2c_pcfisa_init); | ||
295 | module_exit(i2c_pcfisa_exit); | ||
diff --git a/drivers/i2c/busses/i2c-frodo.c b/drivers/i2c/busses/i2c-frodo.c new file mode 100644 index 000000000000..e093829a0bf7 --- /dev/null +++ b/drivers/i2c/busses/i2c-frodo.c | |||
@@ -0,0 +1,86 @@ | |||
1 | |||
2 | /* | ||
3 | * linux/drivers/i2c/i2c-frodo.c | ||
4 | * | ||
5 | * Author: Abraham van der Merwe <abraham@2d3d.co.za> | ||
6 | * | ||
7 | * An I2C adapter driver for the 2d3D, Inc. StrongARM SA-1110 | ||
8 | * Development board (Frodo). | ||
9 | * | ||
10 | * This source code is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * version 2 as published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/config.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/i2c-algo-bit.h> | ||
22 | #include <asm/hardware.h> | ||
23 | |||
24 | |||
25 | static void frodo_setsda (void *data,int state) | ||
26 | { | ||
27 | if (state) | ||
28 | FRODO_CPLD_I2C |= FRODO_I2C_SDA_OUT; | ||
29 | else | ||
30 | FRODO_CPLD_I2C &= ~FRODO_I2C_SDA_OUT; | ||
31 | } | ||
32 | |||
33 | static void frodo_setscl (void *data,int state) | ||
34 | { | ||
35 | if (state) | ||
36 | FRODO_CPLD_I2C |= FRODO_I2C_SCL_OUT; | ||
37 | else | ||
38 | FRODO_CPLD_I2C &= ~FRODO_I2C_SCL_OUT; | ||
39 | } | ||
40 | |||
41 | static int frodo_getsda (void *data) | ||
42 | { | ||
43 | return ((FRODO_CPLD_I2C & FRODO_I2C_SDA_IN) != 0); | ||
44 | } | ||
45 | |||
46 | static int frodo_getscl (void *data) | ||
47 | { | ||
48 | return ((FRODO_CPLD_I2C & FRODO_I2C_SCL_IN) != 0); | ||
49 | } | ||
50 | |||
51 | static struct i2c_algo_bit_data bit_frodo_data = { | ||
52 | .setsda = frodo_setsda, | ||
53 | .setscl = frodo_setscl, | ||
54 | .getsda = frodo_getsda, | ||
55 | .getscl = frodo_getscl, | ||
56 | .udelay = 80, | ||
57 | .mdelay = 80, | ||
58 | .timeout = HZ | ||
59 | }; | ||
60 | |||
61 | static struct i2c_adapter frodo_ops = { | ||
62 | .owner = THIS_MODULE, | ||
63 | .id = I2C_HW_B_FRODO, | ||
64 | .algo_data = &bit_frodo_data, | ||
65 | .dev = { | ||
66 | .name = "Frodo adapter driver", | ||
67 | }, | ||
68 | }; | ||
69 | |||
70 | static int __init i2c_frodo_init (void) | ||
71 | { | ||
72 | return i2c_bit_add_bus(&frodo_ops); | ||
73 | } | ||
74 | |||
75 | static void __exit i2c_frodo_exit (void) | ||
76 | { | ||
77 | i2c_bit_del_bus(&frodo_ops); | ||
78 | } | ||
79 | |||
80 | MODULE_AUTHOR ("Abraham van der Merwe <abraham@2d3d.co.za>"); | ||
81 | MODULE_DESCRIPTION ("I2C-Bus adapter routines for Frodo"); | ||
82 | MODULE_LICENSE ("GPL"); | ||
83 | |||
84 | module_init (i2c_frodo_init); | ||
85 | module_exit (i2c_frodo_exit); | ||
86 | |||
diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c new file mode 100644 index 000000000000..e0cb3b0f92fa --- /dev/null +++ b/drivers/i2c/busses/i2c-hydra.c | |||
@@ -0,0 +1,183 @@ | |||
1 | /* | ||
2 | i2c-hydra.c - Part of lm_sensors, Linux kernel modules | ||
3 | for hardware monitoring | ||
4 | |||
5 | i2c Support for the Apple `Hydra' Mac I/O | ||
6 | |||
7 | Copyright (c) 1999-2004 Geert Uytterhoeven <geert@linux-m68k.org> | ||
8 | |||
9 | Based on i2c Support for Via Technologies 82C586B South Bridge | ||
10 | Copyright (c) 1998, 1999 Kyösti Mälkki <kmalkki@cc.hut.fi> | ||
11 | |||
12 | This program is free software; you can redistribute it and/or modify | ||
13 | it under the terms of the GNU General Public License as published by | ||
14 | the Free Software Foundation; either version 2 of the License, or | ||
15 | (at your option) any later version. | ||
16 | |||
17 | This program is distributed in the hope that it will be useful, | ||
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | GNU General Public License for more details. | ||
21 | |||
22 | You should have received a copy of the GNU General Public License | ||
23 | along with this program; if not, write to the Free Software | ||
24 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/pci.h> | ||
30 | #include <linux/types.h> | ||
31 | #include <linux/i2c.h> | ||
32 | #include <linux/i2c-algo-bit.h> | ||
33 | #include <linux/init.h> | ||
34 | #include <asm/io.h> | ||
35 | #include <asm/hydra.h> | ||
36 | |||
37 | |||
38 | #define HYDRA_CPD_PD0 0x00000001 /* CachePD lines */ | ||
39 | #define HYDRA_CPD_PD1 0x00000002 | ||
40 | #define HYDRA_CPD_PD2 0x00000004 | ||
41 | #define HYDRA_CPD_PD3 0x00000008 | ||
42 | |||
43 | #define HYDRA_SCLK HYDRA_CPD_PD0 | ||
44 | #define HYDRA_SDAT HYDRA_CPD_PD1 | ||
45 | #define HYDRA_SCLK_OE 0x00000010 | ||
46 | #define HYDRA_SDAT_OE 0x00000020 | ||
47 | |||
48 | static inline void pdregw(void *data, u32 val) | ||
49 | { | ||
50 | struct Hydra *hydra = (struct Hydra *)data; | ||
51 | writel(val, &hydra->CachePD); | ||
52 | } | ||
53 | |||
54 | static inline u32 pdregr(void *data) | ||
55 | { | ||
56 | struct Hydra *hydra = (struct Hydra *)data; | ||
57 | return readl(&hydra->CachePD); | ||
58 | } | ||
59 | |||
60 | static void hydra_bit_setscl(void *data, int state) | ||
61 | { | ||
62 | u32 val = pdregr(data); | ||
63 | if (state) | ||
64 | val &= ~HYDRA_SCLK_OE; | ||
65 | else { | ||
66 | val &= ~HYDRA_SCLK; | ||
67 | val |= HYDRA_SCLK_OE; | ||
68 | } | ||
69 | pdregw(data, val); | ||
70 | } | ||
71 | |||
72 | static void hydra_bit_setsda(void *data, int state) | ||
73 | { | ||
74 | u32 val = pdregr(data); | ||
75 | if (state) | ||
76 | val &= ~HYDRA_SDAT_OE; | ||
77 | else { | ||
78 | val &= ~HYDRA_SDAT; | ||
79 | val |= HYDRA_SDAT_OE; | ||
80 | } | ||
81 | pdregw(data, val); | ||
82 | } | ||
83 | |||
84 | static int hydra_bit_getscl(void *data) | ||
85 | { | ||
86 | return (pdregr(data) & HYDRA_SCLK) != 0; | ||
87 | } | ||
88 | |||
89 | static int hydra_bit_getsda(void *data) | ||
90 | { | ||
91 | return (pdregr(data) & HYDRA_SDAT) != 0; | ||
92 | } | ||
93 | |||
94 | /* ------------------------------------------------------------------------ */ | ||
95 | |||
96 | static struct i2c_algo_bit_data hydra_bit_data = { | ||
97 | .setsda = hydra_bit_setsda, | ||
98 | .setscl = hydra_bit_setscl, | ||
99 | .getsda = hydra_bit_getsda, | ||
100 | .getscl = hydra_bit_getscl, | ||
101 | .udelay = 5, | ||
102 | .mdelay = 5, | ||
103 | .timeout = HZ | ||
104 | }; | ||
105 | |||
106 | static struct i2c_adapter hydra_adap = { | ||
107 | .owner = THIS_MODULE, | ||
108 | .name = "Hydra i2c", | ||
109 | .id = I2C_HW_B_HYDRA, | ||
110 | .algo_data = &hydra_bit_data, | ||
111 | }; | ||
112 | |||
113 | static struct pci_device_id hydra_ids[] = { | ||
114 | { PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_HYDRA) }, | ||
115 | { 0, } | ||
116 | }; | ||
117 | |||
118 | MODULE_DEVICE_TABLE (pci, hydra_ids); | ||
119 | |||
120 | static int __devinit hydra_probe(struct pci_dev *dev, | ||
121 | const struct pci_device_id *id) | ||
122 | { | ||
123 | unsigned long base = pci_resource_start(dev, 0); | ||
124 | int res; | ||
125 | |||
126 | if (!request_mem_region(base+offsetof(struct Hydra, CachePD), 4, | ||
127 | hydra_adap.name)) | ||
128 | return -EBUSY; | ||
129 | |||
130 | hydra_bit_data.data = ioremap(base, pci_resource_len(dev, 0)); | ||
131 | if (hydra_bit_data.data == NULL) { | ||
132 | release_mem_region(base+offsetof(struct Hydra, CachePD), 4); | ||
133 | return -ENODEV; | ||
134 | } | ||
135 | |||
136 | pdregw(hydra_bit_data.data, 0); /* clear SCLK_OE and SDAT_OE */ | ||
137 | hydra_adap.dev.parent = &dev->dev; | ||
138 | res = i2c_bit_add_bus(&hydra_adap); | ||
139 | if (res < 0) { | ||
140 | iounmap(hydra_bit_data.data); | ||
141 | release_mem_region(base+offsetof(struct Hydra, CachePD), 4); | ||
142 | return res; | ||
143 | } | ||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static void __devexit hydra_remove(struct pci_dev *dev) | ||
148 | { | ||
149 | pdregw(hydra_bit_data.data, 0); /* clear SCLK_OE and SDAT_OE */ | ||
150 | i2c_bit_del_bus(&hydra_adap); | ||
151 | iounmap(hydra_bit_data.data); | ||
152 | release_mem_region(pci_resource_start(dev, 0)+ | ||
153 | offsetof(struct Hydra, CachePD), 4); | ||
154 | } | ||
155 | |||
156 | |||
157 | static struct pci_driver hydra_driver = { | ||
158 | .name = "hydra_smbus", | ||
159 | .id_table = hydra_ids, | ||
160 | .probe = hydra_probe, | ||
161 | .remove = __devexit_p(hydra_remove), | ||
162 | }; | ||
163 | |||
164 | static int __init i2c_hydra_init(void) | ||
165 | { | ||
166 | return pci_register_driver(&hydra_driver); | ||
167 | } | ||
168 | |||
169 | |||
170 | static void __exit i2c_hydra_exit(void) | ||
171 | { | ||
172 | pci_unregister_driver(&hydra_driver); | ||
173 | } | ||
174 | |||
175 | |||
176 | |||
177 | MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>"); | ||
178 | MODULE_DESCRIPTION("i2c for Apple Hydra Mac I/O"); | ||
179 | MODULE_LICENSE("GPL"); | ||
180 | |||
181 | module_init(i2c_hydra_init); | ||
182 | module_exit(i2c_hydra_exit); | ||
183 | |||
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c new file mode 100644 index 000000000000..6ec8b21965e2 --- /dev/null +++ b/drivers/i2c/busses/i2c-i801.c | |||
@@ -0,0 +1,613 @@ | |||
1 | /* | ||
2 | i801.c - Part of lm_sensors, Linux kernel modules for hardware | ||
3 | monitoring | ||
4 | Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>, | ||
5 | Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker | ||
6 | <mdsxyz123@yahoo.com> | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | SUPPORTED DEVICES PCI ID | ||
25 | 82801AA 2413 | ||
26 | 82801AB 2423 | ||
27 | 82801BA 2443 | ||
28 | 82801CA/CAM 2483 | ||
29 | 82801DB 24C3 (HW PEC supported, 32 byte buffer not supported) | ||
30 | 82801EB 24D3 (HW PEC supported, 32 byte buffer not supported) | ||
31 | 6300ESB 25A4 | ||
32 | ICH6 266A | ||
33 | ICH7 27DA | ||
34 | This driver supports several versions of Intel's I/O Controller Hubs (ICH). | ||
35 | For SMBus support, they are similar to the PIIX4 and are part | ||
36 | of Intel's '810' and other chipsets. | ||
37 | See the doc/busses/i2c-i801 file for details. | ||
38 | I2C Block Read and Process Call are not supported. | ||
39 | */ | ||
40 | |||
41 | /* Note: we assume there can only be one I801, with one SMBus interface */ | ||
42 | |||
43 | #include <linux/config.h> | ||
44 | #include <linux/module.h> | ||
45 | #include <linux/pci.h> | ||
46 | #include <linux/kernel.h> | ||
47 | #include <linux/stddef.h> | ||
48 | #include <linux/delay.h> | ||
49 | #include <linux/sched.h> | ||
50 | #include <linux/ioport.h> | ||
51 | #include <linux/init.h> | ||
52 | #include <linux/i2c.h> | ||
53 | #include <asm/io.h> | ||
54 | |||
55 | #ifdef I2C_FUNC_SMBUS_BLOCK_DATA_PEC | ||
56 | #define HAVE_PEC | ||
57 | #endif | ||
58 | |||
59 | /* I801 SMBus address offsets */ | ||
60 | #define SMBHSTSTS (0 + i801_smba) | ||
61 | #define SMBHSTCNT (2 + i801_smba) | ||
62 | #define SMBHSTCMD (3 + i801_smba) | ||
63 | #define SMBHSTADD (4 + i801_smba) | ||
64 | #define SMBHSTDAT0 (5 + i801_smba) | ||
65 | #define SMBHSTDAT1 (6 + i801_smba) | ||
66 | #define SMBBLKDAT (7 + i801_smba) | ||
67 | #define SMBPEC (8 + i801_smba) /* ICH4 only */ | ||
68 | #define SMBAUXSTS (12 + i801_smba) /* ICH4 only */ | ||
69 | #define SMBAUXCTL (13 + i801_smba) /* ICH4 only */ | ||
70 | |||
71 | /* PCI Address Constants */ | ||
72 | #define SMBBA 0x020 | ||
73 | #define SMBHSTCFG 0x040 | ||
74 | #define SMBREV 0x008 | ||
75 | |||
76 | /* Host configuration bits for SMBHSTCFG */ | ||
77 | #define SMBHSTCFG_HST_EN 1 | ||
78 | #define SMBHSTCFG_SMB_SMI_EN 2 | ||
79 | #define SMBHSTCFG_I2C_EN 4 | ||
80 | |||
81 | /* Other settings */ | ||
82 | #define MAX_TIMEOUT 100 | ||
83 | #define ENABLE_INT9 0 /* set to 0x01 to enable - untested */ | ||
84 | |||
85 | /* I801 command constants */ | ||
86 | #define I801_QUICK 0x00 | ||
87 | #define I801_BYTE 0x04 | ||
88 | #define I801_BYTE_DATA 0x08 | ||
89 | #define I801_WORD_DATA 0x0C | ||
90 | #define I801_PROC_CALL 0x10 /* later chips only, unimplemented */ | ||
91 | #define I801_BLOCK_DATA 0x14 | ||
92 | #define I801_I2C_BLOCK_DATA 0x18 /* unimplemented */ | ||
93 | #define I801_BLOCK_LAST 0x34 | ||
94 | #define I801_I2C_BLOCK_LAST 0x38 /* unimplemented */ | ||
95 | #define I801_START 0x40 | ||
96 | #define I801_PEC_EN 0x80 /* ICH4 only */ | ||
97 | |||
98 | /* insmod parameters */ | ||
99 | |||
100 | /* If force_addr is set to anything different from 0, we forcibly enable | ||
101 | the I801 at the given address. VERY DANGEROUS! */ | ||
102 | static u16 force_addr; | ||
103 | module_param(force_addr, ushort, 0); | ||
104 | MODULE_PARM_DESC(force_addr, | ||
105 | "Forcibly enable the I801 at the given address. " | ||
106 | "EXTREMELY DANGEROUS!"); | ||
107 | |||
108 | static int i801_transaction(void); | ||
109 | static int i801_block_transaction(union i2c_smbus_data *data, | ||
110 | char read_write, int command); | ||
111 | |||
112 | static unsigned short i801_smba; | ||
113 | static struct pci_dev *I801_dev; | ||
114 | static int isich4; | ||
115 | |||
116 | static int i801_setup(struct pci_dev *dev) | ||
117 | { | ||
118 | int error_return = 0; | ||
119 | unsigned char temp; | ||
120 | |||
121 | /* Note: we keep on searching until we have found 'function 3' */ | ||
122 | if(PCI_FUNC(dev->devfn) != 3) | ||
123 | return -ENODEV; | ||
124 | |||
125 | I801_dev = dev; | ||
126 | if ((dev->device == PCI_DEVICE_ID_INTEL_82801DB_3) || | ||
127 | (dev->device == PCI_DEVICE_ID_INTEL_82801EB_3) || | ||
128 | (dev->device == PCI_DEVICE_ID_INTEL_ESB_4)) | ||
129 | isich4 = 1; | ||
130 | else | ||
131 | isich4 = 0; | ||
132 | |||
133 | /* Determine the address of the SMBus areas */ | ||
134 | if (force_addr) { | ||
135 | i801_smba = force_addr & 0xfff0; | ||
136 | } else { | ||
137 | pci_read_config_word(I801_dev, SMBBA, &i801_smba); | ||
138 | i801_smba &= 0xfff0; | ||
139 | if(i801_smba == 0) { | ||
140 | dev_err(&dev->dev, "SMB base address uninitialized" | ||
141 | "- upgrade BIOS or use force_addr=0xaddr\n"); | ||
142 | return -ENODEV; | ||
143 | } | ||
144 | } | ||
145 | |||
146 | if (!request_region(i801_smba, (isich4 ? 16 : 8), "i801-smbus")) { | ||
147 | dev_err(&dev->dev, "I801_smb region 0x%x already in use!\n", | ||
148 | i801_smba); | ||
149 | error_return = -EBUSY; | ||
150 | goto END; | ||
151 | } | ||
152 | |||
153 | pci_read_config_byte(I801_dev, SMBHSTCFG, &temp); | ||
154 | temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */ | ||
155 | pci_write_config_byte(I801_dev, SMBHSTCFG, temp); | ||
156 | |||
157 | /* If force_addr is set, we program the new address here. Just to make | ||
158 | sure, we disable the device first. */ | ||
159 | if (force_addr) { | ||
160 | pci_write_config_byte(I801_dev, SMBHSTCFG, temp & 0xfe); | ||
161 | pci_write_config_word(I801_dev, SMBBA, i801_smba); | ||
162 | pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 0x01); | ||
163 | dev_warn(&dev->dev, "WARNING: I801 SMBus interface set to " | ||
164 | "new address %04x!\n", i801_smba); | ||
165 | } else if ((temp & 1) == 0) { | ||
166 | pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 1); | ||
167 | dev_warn(&dev->dev, "enabling SMBus device\n"); | ||
168 | } | ||
169 | |||
170 | if (temp & 0x02) | ||
171 | dev_dbg(&dev->dev, "I801 using Interrupt SMI# for SMBus.\n"); | ||
172 | else | ||
173 | dev_dbg(&dev->dev, "I801 using PCI Interrupt for SMBus.\n"); | ||
174 | |||
175 | pci_read_config_byte(I801_dev, SMBREV, &temp); | ||
176 | dev_dbg(&dev->dev, "SMBREV = 0x%X\n", temp); | ||
177 | dev_dbg(&dev->dev, "I801_smba = 0x%X\n", i801_smba); | ||
178 | |||
179 | END: | ||
180 | return error_return; | ||
181 | } | ||
182 | |||
183 | static int i801_transaction(void) | ||
184 | { | ||
185 | int temp; | ||
186 | int result = 0; | ||
187 | int timeout = 0; | ||
188 | |||
189 | dev_dbg(&I801_dev->dev, "Transaction (pre): CNT=%02x, CMD=%02x," | ||
190 | "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), | ||
191 | inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), | ||
192 | inb_p(SMBHSTDAT1)); | ||
193 | |||
194 | /* Make sure the SMBus host is ready to start transmitting */ | ||
195 | /* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ | ||
196 | if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { | ||
197 | dev_dbg(&I801_dev->dev, "SMBus busy (%02x). Resetting... \n", | ||
198 | temp); | ||
199 | outb_p(temp, SMBHSTSTS); | ||
200 | if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { | ||
201 | dev_dbg(&I801_dev->dev, "Failed! (%02x)\n", temp); | ||
202 | return -1; | ||
203 | } else { | ||
204 | dev_dbg(&I801_dev->dev, "Successfull!\n"); | ||
205 | } | ||
206 | } | ||
207 | |||
208 | outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT); | ||
209 | |||
210 | /* We will always wait for a fraction of a second! */ | ||
211 | do { | ||
212 | msleep(1); | ||
213 | temp = inb_p(SMBHSTSTS); | ||
214 | } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT)); | ||
215 | |||
216 | /* If the SMBus is still busy, we give up */ | ||
217 | if (timeout >= MAX_TIMEOUT) { | ||
218 | dev_dbg(&I801_dev->dev, "SMBus Timeout!\n"); | ||
219 | result = -1; | ||
220 | } | ||
221 | |||
222 | if (temp & 0x10) { | ||
223 | result = -1; | ||
224 | dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n"); | ||
225 | } | ||
226 | |||
227 | if (temp & 0x08) { | ||
228 | result = -1; | ||
229 | dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked " | ||
230 | "until next hard reset. (sorry!)\n"); | ||
231 | /* Clock stops and slave is stuck in mid-transmission */ | ||
232 | } | ||
233 | |||
234 | if (temp & 0x04) { | ||
235 | result = -1; | ||
236 | dev_dbg(&I801_dev->dev, "Error: no response!\n"); | ||
237 | } | ||
238 | |||
239 | if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00) | ||
240 | outb_p(inb(SMBHSTSTS), SMBHSTSTS); | ||
241 | |||
242 | if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { | ||
243 | dev_dbg(&I801_dev->dev, "Failed reset at end of transaction" | ||
244 | "(%02x)\n", temp); | ||
245 | } | ||
246 | dev_dbg(&I801_dev->dev, "Transaction (post): CNT=%02x, CMD=%02x, " | ||
247 | "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), | ||
248 | inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), | ||
249 | inb_p(SMBHSTDAT1)); | ||
250 | return result; | ||
251 | } | ||
252 | |||
253 | /* All-inclusive block transaction function */ | ||
254 | static int i801_block_transaction(union i2c_smbus_data *data, char read_write, | ||
255 | int command) | ||
256 | { | ||
257 | int i, len; | ||
258 | int smbcmd; | ||
259 | int temp; | ||
260 | int result = 0; | ||
261 | int timeout; | ||
262 | unsigned char hostc, errmask; | ||
263 | |||
264 | if (command == I2C_SMBUS_I2C_BLOCK_DATA) { | ||
265 | if (read_write == I2C_SMBUS_WRITE) { | ||
266 | /* set I2C_EN bit in configuration register */ | ||
267 | pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc); | ||
268 | pci_write_config_byte(I801_dev, SMBHSTCFG, | ||
269 | hostc | SMBHSTCFG_I2C_EN); | ||
270 | } else { | ||
271 | dev_err(&I801_dev->dev, | ||
272 | "I2C_SMBUS_I2C_BLOCK_READ not DB!\n"); | ||
273 | return -1; | ||
274 | } | ||
275 | } | ||
276 | |||
277 | if (read_write == I2C_SMBUS_WRITE) { | ||
278 | len = data->block[0]; | ||
279 | if (len < 1) | ||
280 | len = 1; | ||
281 | if (len > 32) | ||
282 | len = 32; | ||
283 | outb_p(len, SMBHSTDAT0); | ||
284 | outb_p(data->block[1], SMBBLKDAT); | ||
285 | } else { | ||
286 | len = 32; /* max for reads */ | ||
287 | } | ||
288 | |||
289 | if(isich4 && command != I2C_SMBUS_I2C_BLOCK_DATA) { | ||
290 | /* set 32 byte buffer */ | ||
291 | } | ||
292 | |||
293 | for (i = 1; i <= len; i++) { | ||
294 | if (i == len && read_write == I2C_SMBUS_READ) | ||
295 | smbcmd = I801_BLOCK_LAST; | ||
296 | else | ||
297 | smbcmd = I801_BLOCK_DATA; | ||
298 | outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT); | ||
299 | |||
300 | dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, " | ||
301 | "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i, | ||
302 | inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), | ||
303 | inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT)); | ||
304 | |||
305 | /* Make sure the SMBus host is ready to start transmitting */ | ||
306 | temp = inb_p(SMBHSTSTS); | ||
307 | if (i == 1) { | ||
308 | /* Erronenous conditions before transaction: | ||
309 | * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ | ||
310 | errmask=0x9f; | ||
311 | } else { | ||
312 | /* Erronenous conditions during transaction: | ||
313 | * Failed, Bus_Err, Dev_Err, Intr */ | ||
314 | errmask=0x1e; | ||
315 | } | ||
316 | if (temp & errmask) { | ||
317 | dev_dbg(&I801_dev->dev, "SMBus busy (%02x). " | ||
318 | "Resetting... \n", temp); | ||
319 | outb_p(temp, SMBHSTSTS); | ||
320 | if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) { | ||
321 | dev_err(&I801_dev->dev, | ||
322 | "Reset failed! (%02x)\n", temp); | ||
323 | result = -1; | ||
324 | goto END; | ||
325 | } | ||
326 | if (i != 1) { | ||
327 | /* if die in middle of block transaction, fail */ | ||
328 | result = -1; | ||
329 | goto END; | ||
330 | } | ||
331 | } | ||
332 | |||
333 | if (i == 1) | ||
334 | outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT); | ||
335 | |||
336 | /* We will always wait for a fraction of a second! */ | ||
337 | timeout = 0; | ||
338 | do { | ||
339 | temp = inb_p(SMBHSTSTS); | ||
340 | msleep(1); | ||
341 | } | ||
342 | while ((!(temp & 0x80)) | ||
343 | && (timeout++ < MAX_TIMEOUT)); | ||
344 | |||
345 | /* If the SMBus is still busy, we give up */ | ||
346 | if (timeout >= MAX_TIMEOUT) { | ||
347 | result = -1; | ||
348 | dev_dbg(&I801_dev->dev, "SMBus Timeout!\n"); | ||
349 | } | ||
350 | |||
351 | if (temp & 0x10) { | ||
352 | result = -1; | ||
353 | dev_dbg(&I801_dev->dev, | ||
354 | "Error: Failed bus transaction\n"); | ||
355 | } else if (temp & 0x08) { | ||
356 | result = -1; | ||
357 | dev_err(&I801_dev->dev, "Bus collision!\n"); | ||
358 | } else if (temp & 0x04) { | ||
359 | result = -1; | ||
360 | dev_dbg(&I801_dev->dev, "Error: no response!\n"); | ||
361 | } | ||
362 | |||
363 | if (i == 1 && read_write == I2C_SMBUS_READ) { | ||
364 | len = inb_p(SMBHSTDAT0); | ||
365 | if (len < 1) | ||
366 | len = 1; | ||
367 | if (len > 32) | ||
368 | len = 32; | ||
369 | data->block[0] = len; | ||
370 | } | ||
371 | |||
372 | /* Retrieve/store value in SMBBLKDAT */ | ||
373 | if (read_write == I2C_SMBUS_READ) | ||
374 | data->block[i] = inb_p(SMBBLKDAT); | ||
375 | if (read_write == I2C_SMBUS_WRITE && i+1 <= len) | ||
376 | outb_p(data->block[i+1], SMBBLKDAT); | ||
377 | if ((temp & 0x9e) != 0x00) | ||
378 | outb_p(temp, SMBHSTSTS); /* signals SMBBLKDAT ready */ | ||
379 | |||
380 | if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) { | ||
381 | dev_dbg(&I801_dev->dev, | ||
382 | "Bad status (%02x) at end of transaction\n", | ||
383 | temp); | ||
384 | } | ||
385 | dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, " | ||
386 | "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i, | ||
387 | inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), | ||
388 | inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT)); | ||
389 | |||
390 | if (result < 0) | ||
391 | goto END; | ||
392 | } | ||
393 | |||
394 | #ifdef HAVE_PEC | ||
395 | if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC) { | ||
396 | /* wait for INTR bit as advised by Intel */ | ||
397 | timeout = 0; | ||
398 | do { | ||
399 | temp = inb_p(SMBHSTSTS); | ||
400 | msleep(1); | ||
401 | } while ((!(temp & 0x02)) | ||
402 | && (timeout++ < MAX_TIMEOUT)); | ||
403 | |||
404 | if (timeout >= MAX_TIMEOUT) { | ||
405 | dev_dbg(&I801_dev->dev, "PEC Timeout!\n"); | ||
406 | } | ||
407 | outb_p(temp, SMBHSTSTS); | ||
408 | } | ||
409 | #endif | ||
410 | result = 0; | ||
411 | END: | ||
412 | if (command == I2C_SMBUS_I2C_BLOCK_DATA) { | ||
413 | /* restore saved configuration register value */ | ||
414 | pci_write_config_byte(I801_dev, SMBHSTCFG, hostc); | ||
415 | } | ||
416 | return result; | ||
417 | } | ||
418 | |||
419 | /* Return -1 on error. */ | ||
420 | static s32 i801_access(struct i2c_adapter * adap, u16 addr, | ||
421 | unsigned short flags, char read_write, u8 command, | ||
422 | int size, union i2c_smbus_data * data) | ||
423 | { | ||
424 | int hwpec = 0; | ||
425 | int block = 0; | ||
426 | int ret, xact = 0; | ||
427 | |||
428 | #ifdef HAVE_PEC | ||
429 | if(isich4) | ||
430 | hwpec = (flags & I2C_CLIENT_PEC) != 0; | ||
431 | #endif | ||
432 | |||
433 | switch (size) { | ||
434 | case I2C_SMBUS_QUICK: | ||
435 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
436 | SMBHSTADD); | ||
437 | xact = I801_QUICK; | ||
438 | break; | ||
439 | case I2C_SMBUS_BYTE: | ||
440 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
441 | SMBHSTADD); | ||
442 | if (read_write == I2C_SMBUS_WRITE) | ||
443 | outb_p(command, SMBHSTCMD); | ||
444 | xact = I801_BYTE; | ||
445 | break; | ||
446 | case I2C_SMBUS_BYTE_DATA: | ||
447 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
448 | SMBHSTADD); | ||
449 | outb_p(command, SMBHSTCMD); | ||
450 | if (read_write == I2C_SMBUS_WRITE) | ||
451 | outb_p(data->byte, SMBHSTDAT0); | ||
452 | xact = I801_BYTE_DATA; | ||
453 | break; | ||
454 | case I2C_SMBUS_WORD_DATA: | ||
455 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
456 | SMBHSTADD); | ||
457 | outb_p(command, SMBHSTCMD); | ||
458 | if (read_write == I2C_SMBUS_WRITE) { | ||
459 | outb_p(data->word & 0xff, SMBHSTDAT0); | ||
460 | outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); | ||
461 | } | ||
462 | xact = I801_WORD_DATA; | ||
463 | break; | ||
464 | case I2C_SMBUS_BLOCK_DATA: | ||
465 | case I2C_SMBUS_I2C_BLOCK_DATA: | ||
466 | #ifdef HAVE_PEC | ||
467 | case I2C_SMBUS_BLOCK_DATA_PEC: | ||
468 | if(hwpec && size == I2C_SMBUS_BLOCK_DATA) | ||
469 | size = I2C_SMBUS_BLOCK_DATA_PEC; | ||
470 | #endif | ||
471 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
472 | SMBHSTADD); | ||
473 | outb_p(command, SMBHSTCMD); | ||
474 | block = 1; | ||
475 | break; | ||
476 | case I2C_SMBUS_PROC_CALL: | ||
477 | default: | ||
478 | dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size); | ||
479 | return -1; | ||
480 | } | ||
481 | |||
482 | #ifdef HAVE_PEC | ||
483 | if(isich4 && hwpec) { | ||
484 | if(size != I2C_SMBUS_QUICK && | ||
485 | size != I2C_SMBUS_I2C_BLOCK_DATA) | ||
486 | outb_p(1, SMBAUXCTL); /* enable HW PEC */ | ||
487 | } | ||
488 | #endif | ||
489 | if(block) | ||
490 | ret = i801_block_transaction(data, read_write, size); | ||
491 | else { | ||
492 | outb_p(xact | ENABLE_INT9, SMBHSTCNT); | ||
493 | ret = i801_transaction(); | ||
494 | } | ||
495 | |||
496 | #ifdef HAVE_PEC | ||
497 | if(isich4 && hwpec) { | ||
498 | if(size != I2C_SMBUS_QUICK && | ||
499 | size != I2C_SMBUS_I2C_BLOCK_DATA) | ||
500 | outb_p(0, SMBAUXCTL); | ||
501 | } | ||
502 | #endif | ||
503 | |||
504 | if(block) | ||
505 | return ret; | ||
506 | if(ret) | ||
507 | return -1; | ||
508 | if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK)) | ||
509 | return 0; | ||
510 | |||
511 | switch (xact & 0x7f) { | ||
512 | case I801_BYTE: /* Result put in SMBHSTDAT0 */ | ||
513 | case I801_BYTE_DATA: | ||
514 | data->byte = inb_p(SMBHSTDAT0); | ||
515 | break; | ||
516 | case I801_WORD_DATA: | ||
517 | data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); | ||
518 | break; | ||
519 | } | ||
520 | return 0; | ||
521 | } | ||
522 | |||
523 | |||
524 | static u32 i801_func(struct i2c_adapter *adapter) | ||
525 | { | ||
526 | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | | ||
527 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | | ||
528 | I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK | ||
529 | #ifdef HAVE_PEC | ||
530 | | (isich4 ? I2C_FUNC_SMBUS_BLOCK_DATA_PEC | | ||
531 | I2C_FUNC_SMBUS_HWPEC_CALC | ||
532 | : 0) | ||
533 | #endif | ||
534 | ; | ||
535 | } | ||
536 | |||
537 | static struct i2c_algorithm smbus_algorithm = { | ||
538 | .name = "Non-I2C SMBus adapter", | ||
539 | .id = I2C_ALGO_SMBUS, | ||
540 | .smbus_xfer = i801_access, | ||
541 | .functionality = i801_func, | ||
542 | }; | ||
543 | |||
544 | static struct i2c_adapter i801_adapter = { | ||
545 | .owner = THIS_MODULE, | ||
546 | .class = I2C_CLASS_HWMON, | ||
547 | .algo = &smbus_algorithm, | ||
548 | .name = "unset", | ||
549 | }; | ||
550 | |||
551 | static struct pci_device_id i801_ids[] = { | ||
552 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) }, | ||
553 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) }, | ||
554 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) }, | ||
555 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_3) }, | ||
556 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_3) }, | ||
557 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_3) }, | ||
558 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_4) }, | ||
559 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) }, | ||
560 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) }, | ||
561 | { 0, } | ||
562 | }; | ||
563 | |||
564 | MODULE_DEVICE_TABLE (pci, i801_ids); | ||
565 | |||
566 | static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id) | ||
567 | { | ||
568 | |||
569 | if (i801_setup(dev)) { | ||
570 | dev_warn(&dev->dev, | ||
571 | "I801 not detected, module not inserted.\n"); | ||
572 | return -ENODEV; | ||
573 | } | ||
574 | |||
575 | /* set up the driverfs linkage to our parent device */ | ||
576 | i801_adapter.dev.parent = &dev->dev; | ||
577 | |||
578 | snprintf(i801_adapter.name, I2C_NAME_SIZE, | ||
579 | "SMBus I801 adapter at %04x", i801_smba); | ||
580 | return i2c_add_adapter(&i801_adapter); | ||
581 | } | ||
582 | |||
583 | static void __devexit i801_remove(struct pci_dev *dev) | ||
584 | { | ||
585 | i2c_del_adapter(&i801_adapter); | ||
586 | release_region(i801_smba, (isich4 ? 16 : 8)); | ||
587 | } | ||
588 | |||
589 | static struct pci_driver i801_driver = { | ||
590 | .name = "i801_smbus", | ||
591 | .id_table = i801_ids, | ||
592 | .probe = i801_probe, | ||
593 | .remove = __devexit_p(i801_remove), | ||
594 | }; | ||
595 | |||
596 | static int __init i2c_i801_init(void) | ||
597 | { | ||
598 | return pci_register_driver(&i801_driver); | ||
599 | } | ||
600 | |||
601 | static void __exit i2c_i801_exit(void) | ||
602 | { | ||
603 | pci_unregister_driver(&i801_driver); | ||
604 | } | ||
605 | |||
606 | MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, " | ||
607 | "Philip Edelbrock <phil@netroedge.com>, " | ||
608 | "and Mark D. Studebaker <mdsxyz123@yahoo.com>"); | ||
609 | MODULE_DESCRIPTION("I801 SMBus driver"); | ||
610 | MODULE_LICENSE("GPL"); | ||
611 | |||
612 | module_init(i2c_i801_init); | ||
613 | module_exit(i2c_i801_exit); | ||
diff --git a/drivers/i2c/busses/i2c-i810.c b/drivers/i2c/busses/i2c-i810.c new file mode 100644 index 000000000000..ef358bd9c3da --- /dev/null +++ b/drivers/i2c/busses/i2c-i810.c | |||
@@ -0,0 +1,260 @@ | |||
1 | /* | ||
2 | i2c-i810.c - Part of lm_sensors, Linux kernel modules for hardware | ||
3 | monitoring | ||
4 | Copyright (c) 1998, 1999, 2000 Frodo Looijaard <frodol@dds.nl>, | ||
5 | Philip Edelbrock <phil@netroedge.com>, | ||
6 | Ralph Metzler <rjkm@thp.uni-koeln.de>, and | ||
7 | Mark D. Studebaker <mdsxyz123@yahoo.com> | ||
8 | |||
9 | Based on code written by Ralph Metzler <rjkm@thp.uni-koeln.de> and | ||
10 | Simon Vogl | ||
11 | |||
12 | This program is free software; you can redistribute it and/or modify | ||
13 | it under the terms of the GNU General Public License as published by | ||
14 | the Free Software Foundation; either version 2 of the License, or | ||
15 | (at your option) any later version. | ||
16 | |||
17 | This program is distributed in the hope that it will be useful, | ||
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | GNU General Public License for more details. | ||
21 | |||
22 | You should have received a copy of the GNU General Public License | ||
23 | along with this program; if not, write to the Free Software | ||
24 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | /* | ||
27 | This interfaces to the I810/I815 to provide access to | ||
28 | the DDC Bus and the I2C Bus. | ||
29 | |||
30 | SUPPORTED DEVICES PCI ID | ||
31 | i810AA 7121 | ||
32 | i810AB 7123 | ||
33 | i810E 7125 | ||
34 | i815 1132 | ||
35 | */ | ||
36 | |||
37 | #include <linux/config.h> | ||
38 | #include <linux/kernel.h> | ||
39 | #include <linux/module.h> | ||
40 | #include <linux/init.h> | ||
41 | #include <linux/pci.h> | ||
42 | #include <linux/i2c.h> | ||
43 | #include <linux/i2c-algo-bit.h> | ||
44 | #include <asm/io.h> | ||
45 | |||
46 | /* GPIO register locations */ | ||
47 | #define I810_IOCONTROL_OFFSET 0x5000 | ||
48 | #define I810_HVSYNC 0x00 /* not used */ | ||
49 | #define I810_GPIOA 0x10 | ||
50 | #define I810_GPIOB 0x14 | ||
51 | |||
52 | /* bit locations in the registers */ | ||
53 | #define SCL_DIR_MASK 0x0001 | ||
54 | #define SCL_DIR 0x0002 | ||
55 | #define SCL_VAL_MASK 0x0004 | ||
56 | #define SCL_VAL_OUT 0x0008 | ||
57 | #define SCL_VAL_IN 0x0010 | ||
58 | #define SDA_DIR_MASK 0x0100 | ||
59 | #define SDA_DIR 0x0200 | ||
60 | #define SDA_VAL_MASK 0x0400 | ||
61 | #define SDA_VAL_OUT 0x0800 | ||
62 | #define SDA_VAL_IN 0x1000 | ||
63 | |||
64 | /* initialization states */ | ||
65 | #define INIT1 0x1 | ||
66 | #define INIT2 0x2 | ||
67 | #define INIT3 0x4 | ||
68 | |||
69 | /* delays */ | ||
70 | #define CYCLE_DELAY 10 | ||
71 | #define TIMEOUT (HZ / 2) | ||
72 | |||
73 | static void __iomem *ioaddr; | ||
74 | |||
75 | /* The i810 GPIO registers have individual masks for each bit | ||
76 | so we never have to read before writing. Nice. */ | ||
77 | |||
78 | static void bit_i810i2c_setscl(void *data, int val) | ||
79 | { | ||
80 | writel((val ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK, | ||
81 | ioaddr + I810_GPIOB); | ||
82 | readl(ioaddr + I810_GPIOB); /* flush posted write */ | ||
83 | } | ||
84 | |||
85 | static void bit_i810i2c_setsda(void *data, int val) | ||
86 | { | ||
87 | writel((val ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK, | ||
88 | ioaddr + I810_GPIOB); | ||
89 | readl(ioaddr + I810_GPIOB); /* flush posted write */ | ||
90 | } | ||
91 | |||
92 | /* The GPIO pins are open drain, so the pins could always remain outputs. | ||
93 | However, some chip versions don't latch the inputs unless they | ||
94 | are set as inputs. | ||
95 | We rely on the i2c-algo-bit routines to set the pins high before | ||
96 | reading the input from other chips. Following guidance in the 815 | ||
97 | prog. ref. guide, we do a "dummy write" of 0 to the register before | ||
98 | reading which forces the input value to be latched. We presume this | ||
99 | applies to the 810 as well; shouldn't hurt anyway. This is necessary to get | ||
100 | i2c_algo_bit bit_test=1 to pass. */ | ||
101 | |||
102 | static int bit_i810i2c_getscl(void *data) | ||
103 | { | ||
104 | writel(SCL_DIR_MASK, ioaddr + I810_GPIOB); | ||
105 | writel(0, ioaddr + I810_GPIOB); | ||
106 | return (0 != (readl(ioaddr + I810_GPIOB) & SCL_VAL_IN)); | ||
107 | } | ||
108 | |||
109 | static int bit_i810i2c_getsda(void *data) | ||
110 | { | ||
111 | writel(SDA_DIR_MASK, ioaddr + I810_GPIOB); | ||
112 | writel(0, ioaddr + I810_GPIOB); | ||
113 | return (0 != (readl(ioaddr + I810_GPIOB) & SDA_VAL_IN)); | ||
114 | } | ||
115 | |||
116 | static void bit_i810ddc_setscl(void *data, int val) | ||
117 | { | ||
118 | writel((val ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK, | ||
119 | ioaddr + I810_GPIOA); | ||
120 | readl(ioaddr + I810_GPIOA); /* flush posted write */ | ||
121 | } | ||
122 | |||
123 | static void bit_i810ddc_setsda(void *data, int val) | ||
124 | { | ||
125 | writel((val ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK, | ||
126 | ioaddr + I810_GPIOA); | ||
127 | readl(ioaddr + I810_GPIOA); /* flush posted write */ | ||
128 | } | ||
129 | |||
130 | static int bit_i810ddc_getscl(void *data) | ||
131 | { | ||
132 | writel(SCL_DIR_MASK, ioaddr + I810_GPIOA); | ||
133 | writel(0, ioaddr + I810_GPIOA); | ||
134 | return (0 != (readl(ioaddr + I810_GPIOA) & SCL_VAL_IN)); | ||
135 | } | ||
136 | |||
137 | static int bit_i810ddc_getsda(void *data) | ||
138 | { | ||
139 | writel(SDA_DIR_MASK, ioaddr + I810_GPIOA); | ||
140 | writel(0, ioaddr + I810_GPIOA); | ||
141 | return (0 != (readl(ioaddr + I810_GPIOA) & SDA_VAL_IN)); | ||
142 | } | ||
143 | |||
144 | static int config_i810(struct pci_dev *dev) | ||
145 | { | ||
146 | unsigned long cadr; | ||
147 | |||
148 | /* map I810 memory */ | ||
149 | cadr = dev->resource[1].start; | ||
150 | cadr += I810_IOCONTROL_OFFSET; | ||
151 | cadr &= PCI_BASE_ADDRESS_MEM_MASK; | ||
152 | ioaddr = ioremap_nocache(cadr, 0x1000); | ||
153 | if (ioaddr) { | ||
154 | bit_i810i2c_setscl(NULL, 1); | ||
155 | bit_i810i2c_setsda(NULL, 1); | ||
156 | bit_i810ddc_setscl(NULL, 1); | ||
157 | bit_i810ddc_setsda(NULL, 1); | ||
158 | return 0; | ||
159 | } | ||
160 | return -ENODEV; | ||
161 | } | ||
162 | |||
163 | static struct i2c_algo_bit_data i810_i2c_bit_data = { | ||
164 | .setsda = bit_i810i2c_setsda, | ||
165 | .setscl = bit_i810i2c_setscl, | ||
166 | .getsda = bit_i810i2c_getsda, | ||
167 | .getscl = bit_i810i2c_getscl, | ||
168 | .udelay = CYCLE_DELAY, | ||
169 | .mdelay = CYCLE_DELAY, | ||
170 | .timeout = TIMEOUT, | ||
171 | }; | ||
172 | |||
173 | static struct i2c_adapter i810_i2c_adapter = { | ||
174 | .owner = THIS_MODULE, | ||
175 | .name = "I810/I815 I2C Adapter", | ||
176 | .algo_data = &i810_i2c_bit_data, | ||
177 | }; | ||
178 | |||
179 | static struct i2c_algo_bit_data i810_ddc_bit_data = { | ||
180 | .setsda = bit_i810ddc_setsda, | ||
181 | .setscl = bit_i810ddc_setscl, | ||
182 | .getsda = bit_i810ddc_getsda, | ||
183 | .getscl = bit_i810ddc_getscl, | ||
184 | .udelay = CYCLE_DELAY, | ||
185 | .mdelay = CYCLE_DELAY, | ||
186 | .timeout = TIMEOUT, | ||
187 | }; | ||
188 | |||
189 | static struct i2c_adapter i810_ddc_adapter = { | ||
190 | .owner = THIS_MODULE, | ||
191 | .name = "I810/I815 DDC Adapter", | ||
192 | .algo_data = &i810_ddc_bit_data, | ||
193 | }; | ||
194 | |||
195 | static struct pci_device_id i810_ids[] __devinitdata = { | ||
196 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG1) }, | ||
197 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3) }, | ||
198 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810E_IG) }, | ||
199 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_CGC) }, | ||
200 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845G_IG) }, | ||
201 | { 0, }, | ||
202 | }; | ||
203 | |||
204 | MODULE_DEVICE_TABLE (pci, i810_ids); | ||
205 | |||
206 | static int __devinit i810_probe(struct pci_dev *dev, const struct pci_device_id *id) | ||
207 | { | ||
208 | int retval; | ||
209 | |||
210 | retval = config_i810(dev); | ||
211 | if (retval) | ||
212 | return retval; | ||
213 | dev_info(&dev->dev, "i810/i815 i2c device found.\n"); | ||
214 | |||
215 | /* set up the sysfs linkage to our parent device */ | ||
216 | i810_i2c_adapter.dev.parent = &dev->dev; | ||
217 | i810_ddc_adapter.dev.parent = &dev->dev; | ||
218 | |||
219 | retval = i2c_bit_add_bus(&i810_i2c_adapter); | ||
220 | if (retval) | ||
221 | return retval; | ||
222 | retval = i2c_bit_add_bus(&i810_ddc_adapter); | ||
223 | if (retval) | ||
224 | i2c_bit_del_bus(&i810_i2c_adapter); | ||
225 | return retval; | ||
226 | } | ||
227 | |||
228 | static void __devexit i810_remove(struct pci_dev *dev) | ||
229 | { | ||
230 | i2c_bit_del_bus(&i810_ddc_adapter); | ||
231 | i2c_bit_del_bus(&i810_i2c_adapter); | ||
232 | iounmap(ioaddr); | ||
233 | } | ||
234 | |||
235 | static struct pci_driver i810_driver = { | ||
236 | .name = "i810_smbus", | ||
237 | .id_table = i810_ids, | ||
238 | .probe = i810_probe, | ||
239 | .remove = __devexit_p(i810_remove), | ||
240 | }; | ||
241 | |||
242 | static int __init i2c_i810_init(void) | ||
243 | { | ||
244 | return pci_register_driver(&i810_driver); | ||
245 | } | ||
246 | |||
247 | static void __exit i2c_i810_exit(void) | ||
248 | { | ||
249 | pci_unregister_driver(&i810_driver); | ||
250 | } | ||
251 | |||
252 | MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, " | ||
253 | "Philip Edelbrock <phil@netroedge.com>, " | ||
254 | "Ralph Metzler <rjkm@thp.uni-koeln.de>, " | ||
255 | "and Mark D. Studebaker <mdsxyz123@yahoo.com>"); | ||
256 | MODULE_DESCRIPTION("I810/I815 I2C/DDC driver"); | ||
257 | MODULE_LICENSE("GPL"); | ||
258 | |||
259 | module_init(i2c_i810_init); | ||
260 | module_exit(i2c_i810_exit); | ||
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c new file mode 100644 index 000000000000..bb885215c08d --- /dev/null +++ b/drivers/i2c/busses/i2c-ibm_iic.c | |||
@@ -0,0 +1,819 @@ | |||
1 | /* | ||
2 | * drivers/i2c/i2c-ibm_iic.c | ||
3 | * | ||
4 | * Support for the IIC peripheral on IBM PPC 4xx | ||
5 | * | ||
6 | * Copyright (c) 2003, 2004 Zultys Technologies. | ||
7 | * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> | ||
8 | * | ||
9 | * Based on original work by | ||
10 | * Ian DaSilva <idasilva@mvista.com> | ||
11 | * Armin Kuster <akuster@mvista.com> | ||
12 | * Matt Porter <mporter@mvista.com> | ||
13 | * | ||
14 | * Copyright 2000-2003 MontaVista Software Inc. | ||
15 | * | ||
16 | * Original driver version was highly leveraged from i2c-elektor.c | ||
17 | * | ||
18 | * Copyright 1995-97 Simon G. Vogl | ||
19 | * 1998-99 Hans Berglund | ||
20 | * | ||
21 | * With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> | ||
22 | * and even Frodo Looijaard <frodol@dds.nl> | ||
23 | * | ||
24 | * This program is free software; you can redistribute it and/or modify it | ||
25 | * under the terms of the GNU General Public License as published by the | ||
26 | * Free Software Foundation; either version 2 of the License, or (at your | ||
27 | * option) any later version. | ||
28 | * | ||
29 | */ | ||
30 | |||
31 | #include <linux/config.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/kernel.h> | ||
34 | #include <linux/ioport.h> | ||
35 | #include <linux/delay.h> | ||
36 | #include <linux/slab.h> | ||
37 | #include <linux/init.h> | ||
38 | #include <linux/interrupt.h> | ||
39 | #include <asm/irq.h> | ||
40 | #include <asm/io.h> | ||
41 | #include <linux/i2c.h> | ||
42 | #include <linux/i2c-id.h> | ||
43 | #include <asm/ocp.h> | ||
44 | #include <asm/ibm4xx.h> | ||
45 | |||
46 | #include "i2c-ibm_iic.h" | ||
47 | |||
48 | #define DRIVER_VERSION "2.1" | ||
49 | |||
50 | MODULE_DESCRIPTION("IBM IIC driver v" DRIVER_VERSION); | ||
51 | MODULE_LICENSE("GPL"); | ||
52 | |||
53 | static int iic_force_poll; | ||
54 | module_param(iic_force_poll, bool, 0); | ||
55 | MODULE_PARM_DESC(iic_force_poll, "Force polling mode"); | ||
56 | |||
57 | static int iic_force_fast; | ||
58 | module_param(iic_force_fast, bool, 0); | ||
59 | MODULE_PARM_DESC(iic_fast_poll, "Force fast mode (400 kHz)"); | ||
60 | |||
61 | #define DBG_LEVEL 0 | ||
62 | |||
63 | #ifdef DBG | ||
64 | #undef DBG | ||
65 | #endif | ||
66 | |||
67 | #ifdef DBG2 | ||
68 | #undef DBG2 | ||
69 | #endif | ||
70 | |||
71 | #if DBG_LEVEL > 0 | ||
72 | # define DBG(f,x...) printk(KERN_DEBUG "ibm-iic" f, ##x) | ||
73 | #else | ||
74 | # define DBG(f,x...) ((void)0) | ||
75 | #endif | ||
76 | #if DBG_LEVEL > 1 | ||
77 | # define DBG2(f,x...) DBG(f, ##x) | ||
78 | #else | ||
79 | # define DBG2(f,x...) ((void)0) | ||
80 | #endif | ||
81 | #if DBG_LEVEL > 2 | ||
82 | static void dump_iic_regs(const char* header, struct ibm_iic_private* dev) | ||
83 | { | ||
84 | volatile struct iic_regs __iomem *iic = dev->vaddr; | ||
85 | printk(KERN_DEBUG "ibm-iic%d: %s\n", dev->idx, header); | ||
86 | printk(KERN_DEBUG " cntl = 0x%02x, mdcntl = 0x%02x\n" | ||
87 | KERN_DEBUG " sts = 0x%02x, extsts = 0x%02x\n" | ||
88 | KERN_DEBUG " clkdiv = 0x%02x, xfrcnt = 0x%02x\n" | ||
89 | KERN_DEBUG " xtcntlss = 0x%02x, directcntl = 0x%02x\n", | ||
90 | in_8(&iic->cntl), in_8(&iic->mdcntl), in_8(&iic->sts), | ||
91 | in_8(&iic->extsts), in_8(&iic->clkdiv), in_8(&iic->xfrcnt), | ||
92 | in_8(&iic->xtcntlss), in_8(&iic->directcntl)); | ||
93 | } | ||
94 | # define DUMP_REGS(h,dev) dump_iic_regs((h),(dev)) | ||
95 | #else | ||
96 | # define DUMP_REGS(h,dev) ((void)0) | ||
97 | #endif | ||
98 | |||
99 | /* Bus timings (in ns) for bit-banging */ | ||
100 | static struct i2c_timings { | ||
101 | unsigned int hd_sta; | ||
102 | unsigned int su_sto; | ||
103 | unsigned int low; | ||
104 | unsigned int high; | ||
105 | unsigned int buf; | ||
106 | } timings [] = { | ||
107 | /* Standard mode (100 KHz) */ | ||
108 | { | ||
109 | .hd_sta = 4000, | ||
110 | .su_sto = 4000, | ||
111 | .low = 4700, | ||
112 | .high = 4000, | ||
113 | .buf = 4700, | ||
114 | }, | ||
115 | /* Fast mode (400 KHz) */ | ||
116 | { | ||
117 | .hd_sta = 600, | ||
118 | .su_sto = 600, | ||
119 | .low = 1300, | ||
120 | .high = 600, | ||
121 | .buf = 1300, | ||
122 | }}; | ||
123 | |||
124 | /* Enable/disable interrupt generation */ | ||
125 | static inline void iic_interrupt_mode(struct ibm_iic_private* dev, int enable) | ||
126 | { | ||
127 | out_8(&dev->vaddr->intmsk, enable ? INTRMSK_EIMTC : 0); | ||
128 | } | ||
129 | |||
130 | /* | ||
131 | * Initialize IIC interface. | ||
132 | */ | ||
133 | static void iic_dev_init(struct ibm_iic_private* dev) | ||
134 | { | ||
135 | volatile struct iic_regs __iomem *iic = dev->vaddr; | ||
136 | |||
137 | DBG("%d: init\n", dev->idx); | ||
138 | |||
139 | /* Clear master address */ | ||
140 | out_8(&iic->lmadr, 0); | ||
141 | out_8(&iic->hmadr, 0); | ||
142 | |||
143 | /* Clear slave address */ | ||
144 | out_8(&iic->lsadr, 0); | ||
145 | out_8(&iic->hsadr, 0); | ||
146 | |||
147 | /* Clear status & extended status */ | ||
148 | out_8(&iic->sts, STS_SCMP | STS_IRQA); | ||
149 | out_8(&iic->extsts, EXTSTS_IRQP | EXTSTS_IRQD | EXTSTS_LA | ||
150 | | EXTSTS_ICT | EXTSTS_XFRA); | ||
151 | |||
152 | /* Set clock divider */ | ||
153 | out_8(&iic->clkdiv, dev->clckdiv); | ||
154 | |||
155 | /* Clear transfer count */ | ||
156 | out_8(&iic->xfrcnt, 0); | ||
157 | |||
158 | /* Clear extended control and status */ | ||
159 | out_8(&iic->xtcntlss, XTCNTLSS_SRC | XTCNTLSS_SRS | XTCNTLSS_SWC | ||
160 | | XTCNTLSS_SWS); | ||
161 | |||
162 | /* Clear control register */ | ||
163 | out_8(&iic->cntl, 0); | ||
164 | |||
165 | /* Enable interrupts if possible */ | ||
166 | iic_interrupt_mode(dev, dev->irq >= 0); | ||
167 | |||
168 | /* Set mode control */ | ||
169 | out_8(&iic->mdcntl, MDCNTL_FMDB | MDCNTL_EINT | MDCNTL_EUBS | ||
170 | | (dev->fast_mode ? MDCNTL_FSM : 0)); | ||
171 | |||
172 | DUMP_REGS("iic_init", dev); | ||
173 | } | ||
174 | |||
175 | /* | ||
176 | * Reset IIC interface | ||
177 | */ | ||
178 | static void iic_dev_reset(struct ibm_iic_private* dev) | ||
179 | { | ||
180 | volatile struct iic_regs __iomem *iic = dev->vaddr; | ||
181 | int i; | ||
182 | u8 dc; | ||
183 | |||
184 | DBG("%d: soft reset\n", dev->idx); | ||
185 | DUMP_REGS("reset", dev); | ||
186 | |||
187 | /* Place chip in the reset state */ | ||
188 | out_8(&iic->xtcntlss, XTCNTLSS_SRST); | ||
189 | |||
190 | /* Check if bus is free */ | ||
191 | dc = in_8(&iic->directcntl); | ||
192 | if (!DIRCTNL_FREE(dc)){ | ||
193 | DBG("%d: trying to regain bus control\n", dev->idx); | ||
194 | |||
195 | /* Try to set bus free state */ | ||
196 | out_8(&iic->directcntl, DIRCNTL_SDAC | DIRCNTL_SCC); | ||
197 | |||
198 | /* Wait until we regain bus control */ | ||
199 | for (i = 0; i < 100; ++i){ | ||
200 | dc = in_8(&iic->directcntl); | ||
201 | if (DIRCTNL_FREE(dc)) | ||
202 | break; | ||
203 | |||
204 | /* Toggle SCL line */ | ||
205 | dc ^= DIRCNTL_SCC; | ||
206 | out_8(&iic->directcntl, dc); | ||
207 | udelay(10); | ||
208 | dc ^= DIRCNTL_SCC; | ||
209 | out_8(&iic->directcntl, dc); | ||
210 | |||
211 | /* be nice */ | ||
212 | cond_resched(); | ||
213 | } | ||
214 | } | ||
215 | |||
216 | /* Remove reset */ | ||
217 | out_8(&iic->xtcntlss, 0); | ||
218 | |||
219 | /* Reinitialize interface */ | ||
220 | iic_dev_init(dev); | ||
221 | } | ||
222 | |||
223 | /* | ||
224 | * Do 0-length transaction using bit-banging through IIC_DIRECTCNTL register. | ||
225 | */ | ||
226 | |||
227 | /* Wait for SCL and/or SDA to be high */ | ||
228 | static int iic_dc_wait(volatile struct iic_regs __iomem *iic, u8 mask) | ||
229 | { | ||
230 | unsigned long x = jiffies + HZ / 28 + 2; | ||
231 | while ((in_8(&iic->directcntl) & mask) != mask){ | ||
232 | if (unlikely(time_after(jiffies, x))) | ||
233 | return -1; | ||
234 | cond_resched(); | ||
235 | } | ||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static int iic_smbus_quick(struct ibm_iic_private* dev, const struct i2c_msg* p) | ||
240 | { | ||
241 | volatile struct iic_regs __iomem *iic = dev->vaddr; | ||
242 | const struct i2c_timings* t = &timings[dev->fast_mode ? 1 : 0]; | ||
243 | u8 mask, v, sda; | ||
244 | int i, res; | ||
245 | |||
246 | /* Only 7-bit addresses are supported */ | ||
247 | if (unlikely(p->flags & I2C_M_TEN)){ | ||
248 | DBG("%d: smbus_quick - 10 bit addresses are not supported\n", | ||
249 | dev->idx); | ||
250 | return -EINVAL; | ||
251 | } | ||
252 | |||
253 | DBG("%d: smbus_quick(0x%02x)\n", dev->idx, p->addr); | ||
254 | |||
255 | /* Reset IIC interface */ | ||
256 | out_8(&iic->xtcntlss, XTCNTLSS_SRST); | ||
257 | |||
258 | /* Wait for bus to become free */ | ||
259 | out_8(&iic->directcntl, DIRCNTL_SDAC | DIRCNTL_SCC); | ||
260 | if (unlikely(iic_dc_wait(iic, DIRCNTL_MSDA | DIRCNTL_MSC))) | ||
261 | goto err; | ||
262 | ndelay(t->buf); | ||
263 | |||
264 | /* START */ | ||
265 | out_8(&iic->directcntl, DIRCNTL_SCC); | ||
266 | sda = 0; | ||
267 | ndelay(t->hd_sta); | ||
268 | |||
269 | /* Send address */ | ||
270 | v = (u8)((p->addr << 1) | ((p->flags & I2C_M_RD) ? 1 : 0)); | ||
271 | for (i = 0, mask = 0x80; i < 8; ++i, mask >>= 1){ | ||
272 | out_8(&iic->directcntl, sda); | ||
273 | ndelay(t->low / 2); | ||
274 | sda = (v & mask) ? DIRCNTL_SDAC : 0; | ||
275 | out_8(&iic->directcntl, sda); | ||
276 | ndelay(t->low / 2); | ||
277 | |||
278 | out_8(&iic->directcntl, DIRCNTL_SCC | sda); | ||
279 | if (unlikely(iic_dc_wait(iic, DIRCNTL_MSC))) | ||
280 | goto err; | ||
281 | ndelay(t->high); | ||
282 | } | ||
283 | |||
284 | /* ACK */ | ||
285 | out_8(&iic->directcntl, sda); | ||
286 | ndelay(t->low / 2); | ||
287 | out_8(&iic->directcntl, DIRCNTL_SDAC); | ||
288 | ndelay(t->low / 2); | ||
289 | out_8(&iic->directcntl, DIRCNTL_SDAC | DIRCNTL_SCC); | ||
290 | if (unlikely(iic_dc_wait(iic, DIRCNTL_MSC))) | ||
291 | goto err; | ||
292 | res = (in_8(&iic->directcntl) & DIRCNTL_MSDA) ? -EREMOTEIO : 1; | ||
293 | ndelay(t->high); | ||
294 | |||
295 | /* STOP */ | ||
296 | out_8(&iic->directcntl, 0); | ||
297 | ndelay(t->low); | ||
298 | out_8(&iic->directcntl, DIRCNTL_SCC); | ||
299 | if (unlikely(iic_dc_wait(iic, DIRCNTL_MSC))) | ||
300 | goto err; | ||
301 | ndelay(t->su_sto); | ||
302 | out_8(&iic->directcntl, DIRCNTL_SDAC | DIRCNTL_SCC); | ||
303 | |||
304 | ndelay(t->buf); | ||
305 | |||
306 | DBG("%d: smbus_quick -> %s\n", dev->idx, res ? "NACK" : "ACK"); | ||
307 | out: | ||
308 | /* Remove reset */ | ||
309 | out_8(&iic->xtcntlss, 0); | ||
310 | |||
311 | /* Reinitialize interface */ | ||
312 | iic_dev_init(dev); | ||
313 | |||
314 | return res; | ||
315 | err: | ||
316 | DBG("%d: smbus_quick - bus is stuck\n", dev->idx); | ||
317 | res = -EREMOTEIO; | ||
318 | goto out; | ||
319 | } | ||
320 | |||
321 | /* | ||
322 | * IIC interrupt handler | ||
323 | */ | ||
324 | static irqreturn_t iic_handler(int irq, void *dev_id, struct pt_regs *regs) | ||
325 | { | ||
326 | struct ibm_iic_private* dev = (struct ibm_iic_private*)dev_id; | ||
327 | volatile struct iic_regs __iomem *iic = dev->vaddr; | ||
328 | |||
329 | DBG2("%d: irq handler, STS = 0x%02x, EXTSTS = 0x%02x\n", | ||
330 | dev->idx, in_8(&iic->sts), in_8(&iic->extsts)); | ||
331 | |||
332 | /* Acknowledge IRQ and wakeup iic_wait_for_tc */ | ||
333 | out_8(&iic->sts, STS_IRQA | STS_SCMP); | ||
334 | wake_up_interruptible(&dev->wq); | ||
335 | |||
336 | return IRQ_HANDLED; | ||
337 | } | ||
338 | |||
339 | /* | ||
340 | * Get master transfer result and clear errors if any. | ||
341 | * Returns the number of actually transferred bytes or error (<0) | ||
342 | */ | ||
343 | static int iic_xfer_result(struct ibm_iic_private* dev) | ||
344 | { | ||
345 | volatile struct iic_regs __iomem *iic = dev->vaddr; | ||
346 | |||
347 | if (unlikely(in_8(&iic->sts) & STS_ERR)){ | ||
348 | DBG("%d: xfer error, EXTSTS = 0x%02x\n", dev->idx, | ||
349 | in_8(&iic->extsts)); | ||
350 | |||
351 | /* Clear errors and possible pending IRQs */ | ||
352 | out_8(&iic->extsts, EXTSTS_IRQP | EXTSTS_IRQD | | ||
353 | EXTSTS_LA | EXTSTS_ICT | EXTSTS_XFRA); | ||
354 | |||
355 | /* Flush master data buffer */ | ||
356 | out_8(&iic->mdcntl, in_8(&iic->mdcntl) | MDCNTL_FMDB); | ||
357 | |||
358 | /* Is bus free? | ||
359 | * If error happened during combined xfer | ||
360 | * IIC interface is usually stuck in some strange | ||
361 | * state, the only way out - soft reset. | ||
362 | */ | ||
363 | if ((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE){ | ||
364 | DBG("%d: bus is stuck, resetting\n", dev->idx); | ||
365 | iic_dev_reset(dev); | ||
366 | } | ||
367 | return -EREMOTEIO; | ||
368 | } | ||
369 | else | ||
370 | return in_8(&iic->xfrcnt) & XFRCNT_MTC_MASK; | ||
371 | } | ||
372 | |||
373 | /* | ||
374 | * Try to abort active transfer. | ||
375 | */ | ||
376 | static void iic_abort_xfer(struct ibm_iic_private* dev) | ||
377 | { | ||
378 | volatile struct iic_regs __iomem *iic = dev->vaddr; | ||
379 | unsigned long x; | ||
380 | |||
381 | DBG("%d: iic_abort_xfer\n", dev->idx); | ||
382 | |||
383 | out_8(&iic->cntl, CNTL_HMT); | ||
384 | |||
385 | /* | ||
386 | * Wait for the abort command to complete. | ||
387 | * It's not worth to be optimized, just poll (timeout >= 1 tick) | ||
388 | */ | ||
389 | x = jiffies + 2; | ||
390 | while ((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE){ | ||
391 | if (time_after(jiffies, x)){ | ||
392 | DBG("%d: abort timeout, resetting...\n", dev->idx); | ||
393 | iic_dev_reset(dev); | ||
394 | return; | ||
395 | } | ||
396 | schedule(); | ||
397 | } | ||
398 | |||
399 | /* Just to clear errors */ | ||
400 | iic_xfer_result(dev); | ||
401 | } | ||
402 | |||
403 | /* | ||
404 | * Wait for master transfer to complete. | ||
405 | * It puts current process to sleep until we get interrupt or timeout expires. | ||
406 | * Returns the number of transferred bytes or error (<0) | ||
407 | */ | ||
408 | static int iic_wait_for_tc(struct ibm_iic_private* dev){ | ||
409 | |||
410 | volatile struct iic_regs __iomem *iic = dev->vaddr; | ||
411 | int ret = 0; | ||
412 | |||
413 | if (dev->irq >= 0){ | ||
414 | /* Interrupt mode */ | ||
415 | ret = wait_event_interruptible_timeout(dev->wq, | ||
416 | !(in_8(&iic->sts) & STS_PT), dev->adap.timeout * HZ); | ||
417 | |||
418 | if (unlikely(ret < 0)) | ||
419 | DBG("%d: wait interrupted\n", dev->idx); | ||
420 | else if (unlikely(in_8(&iic->sts) & STS_PT)){ | ||
421 | DBG("%d: wait timeout\n", dev->idx); | ||
422 | ret = -ETIMEDOUT; | ||
423 | } | ||
424 | } | ||
425 | else { | ||
426 | /* Polling mode */ | ||
427 | unsigned long x = jiffies + dev->adap.timeout * HZ; | ||
428 | |||
429 | while (in_8(&iic->sts) & STS_PT){ | ||
430 | if (unlikely(time_after(jiffies, x))){ | ||
431 | DBG("%d: poll timeout\n", dev->idx); | ||
432 | ret = -ETIMEDOUT; | ||
433 | break; | ||
434 | } | ||
435 | |||
436 | if (unlikely(signal_pending(current))){ | ||
437 | DBG("%d: poll interrupted\n", dev->idx); | ||
438 | ret = -ERESTARTSYS; | ||
439 | break; | ||
440 | } | ||
441 | schedule(); | ||
442 | } | ||
443 | } | ||
444 | |||
445 | if (unlikely(ret < 0)) | ||
446 | iic_abort_xfer(dev); | ||
447 | else | ||
448 | ret = iic_xfer_result(dev); | ||
449 | |||
450 | DBG2("%d: iic_wait_for_tc -> %d\n", dev->idx, ret); | ||
451 | |||
452 | return ret; | ||
453 | } | ||
454 | |||
455 | /* | ||
456 | * Low level master transfer routine | ||
457 | */ | ||
458 | static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm, | ||
459 | int combined_xfer) | ||
460 | { | ||
461 | volatile struct iic_regs __iomem *iic = dev->vaddr; | ||
462 | char* buf = pm->buf; | ||
463 | int i, j, loops, ret = 0; | ||
464 | int len = pm->len; | ||
465 | |||
466 | u8 cntl = (in_8(&iic->cntl) & CNTL_AMD) | CNTL_PT; | ||
467 | if (pm->flags & I2C_M_RD) | ||
468 | cntl |= CNTL_RW; | ||
469 | |||
470 | loops = (len + 3) / 4; | ||
471 | for (i = 0; i < loops; ++i, len -= 4){ | ||
472 | int count = len > 4 ? 4 : len; | ||
473 | u8 cmd = cntl | ((count - 1) << CNTL_TCT_SHIFT); | ||
474 | |||
475 | if (!(cntl & CNTL_RW)) | ||
476 | for (j = 0; j < count; ++j) | ||
477 | out_8((void __iomem *)&iic->mdbuf, *buf++); | ||
478 | |||
479 | if (i < loops - 1) | ||
480 | cmd |= CNTL_CHT; | ||
481 | else if (combined_xfer) | ||
482 | cmd |= CNTL_RPST; | ||
483 | |||
484 | DBG2("%d: xfer_bytes, %d, CNTL = 0x%02x\n", dev->idx, count, cmd); | ||
485 | |||
486 | /* Start transfer */ | ||
487 | out_8(&iic->cntl, cmd); | ||
488 | |||
489 | /* Wait for completion */ | ||
490 | ret = iic_wait_for_tc(dev); | ||
491 | |||
492 | if (unlikely(ret < 0)) | ||
493 | break; | ||
494 | else if (unlikely(ret != count)){ | ||
495 | DBG("%d: xfer_bytes, requested %d, transfered %d\n", | ||
496 | dev->idx, count, ret); | ||
497 | |||
498 | /* If it's not a last part of xfer, abort it */ | ||
499 | if (combined_xfer || (i < loops - 1)) | ||
500 | iic_abort_xfer(dev); | ||
501 | |||
502 | ret = -EREMOTEIO; | ||
503 | break; | ||
504 | } | ||
505 | |||
506 | if (cntl & CNTL_RW) | ||
507 | for (j = 0; j < count; ++j) | ||
508 | *buf++ = in_8((void __iomem *)&iic->mdbuf); | ||
509 | } | ||
510 | |||
511 | return ret > 0 ? 0 : ret; | ||
512 | } | ||
513 | |||
514 | /* | ||
515 | * Set target slave address for master transfer | ||
516 | */ | ||
517 | static inline void iic_address(struct ibm_iic_private* dev, struct i2c_msg* msg) | ||
518 | { | ||
519 | volatile struct iic_regs __iomem *iic = dev->vaddr; | ||
520 | u16 addr = msg->addr; | ||
521 | |||
522 | DBG2("%d: iic_address, 0x%03x (%d-bit)\n", dev->idx, | ||
523 | addr, msg->flags & I2C_M_TEN ? 10 : 7); | ||
524 | |||
525 | if (msg->flags & I2C_M_TEN){ | ||
526 | out_8(&iic->cntl, CNTL_AMD); | ||
527 | out_8(&iic->lmadr, addr); | ||
528 | out_8(&iic->hmadr, 0xf0 | ((addr >> 7) & 0x06)); | ||
529 | } | ||
530 | else { | ||
531 | out_8(&iic->cntl, 0); | ||
532 | out_8(&iic->lmadr, addr << 1); | ||
533 | } | ||
534 | } | ||
535 | |||
536 | static inline int iic_invalid_address(const struct i2c_msg* p) | ||
537 | { | ||
538 | return (p->addr > 0x3ff) || (!(p->flags & I2C_M_TEN) && (p->addr > 0x7f)); | ||
539 | } | ||
540 | |||
541 | static inline int iic_address_neq(const struct i2c_msg* p1, | ||
542 | const struct i2c_msg* p2) | ||
543 | { | ||
544 | return (p1->addr != p2->addr) | ||
545 | || ((p1->flags & I2C_M_TEN) != (p2->flags & I2C_M_TEN)); | ||
546 | } | ||
547 | |||
548 | /* | ||
549 | * Generic master transfer entrypoint. | ||
550 | * Returns the number of processed messages or error (<0) | ||
551 | */ | ||
552 | static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) | ||
553 | { | ||
554 | struct ibm_iic_private* dev = (struct ibm_iic_private*)(i2c_get_adapdata(adap)); | ||
555 | volatile struct iic_regs __iomem *iic = dev->vaddr; | ||
556 | int i, ret = 0; | ||
557 | |||
558 | DBG2("%d: iic_xfer, %d msg(s)\n", dev->idx, num); | ||
559 | |||
560 | if (!num) | ||
561 | return 0; | ||
562 | |||
563 | /* Check the sanity of the passed messages. | ||
564 | * Uhh, generic i2c layer is more suitable place for such code... | ||
565 | */ | ||
566 | if (unlikely(iic_invalid_address(&msgs[0]))){ | ||
567 | DBG("%d: invalid address 0x%03x (%d-bit)\n", dev->idx, | ||
568 | msgs[0].addr, msgs[0].flags & I2C_M_TEN ? 10 : 7); | ||
569 | return -EINVAL; | ||
570 | } | ||
571 | for (i = 0; i < num; ++i){ | ||
572 | if (unlikely(msgs[i].len <= 0)){ | ||
573 | if (num == 1 && !msgs[0].len){ | ||
574 | /* Special case for I2C_SMBUS_QUICK emulation. | ||
575 | * IBM IIC doesn't support 0-length transactions | ||
576 | * so we have to emulate them using bit-banging. | ||
577 | */ | ||
578 | return iic_smbus_quick(dev, &msgs[0]); | ||
579 | } | ||
580 | DBG("%d: invalid len %d in msg[%d]\n", dev->idx, | ||
581 | msgs[i].len, i); | ||
582 | return -EINVAL; | ||
583 | } | ||
584 | if (unlikely(iic_address_neq(&msgs[0], &msgs[i]))){ | ||
585 | DBG("%d: invalid addr in msg[%d]\n", dev->idx, i); | ||
586 | return -EINVAL; | ||
587 | } | ||
588 | } | ||
589 | |||
590 | /* Check bus state */ | ||
591 | if (unlikely((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE)){ | ||
592 | DBG("%d: iic_xfer, bus is not free\n", dev->idx); | ||
593 | |||
594 | /* Usually it means something serious has happend. | ||
595 | * We *cannot* have unfinished previous transfer | ||
596 | * so it doesn't make any sense to try to stop it. | ||
597 | * Probably we were not able to recover from the | ||
598 | * previous error. | ||
599 | * The only *reasonable* thing I can think of here | ||
600 | * is soft reset. --ebs | ||
601 | */ | ||
602 | iic_dev_reset(dev); | ||
603 | |||
604 | if ((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE){ | ||
605 | DBG("%d: iic_xfer, bus is still not free\n", dev->idx); | ||
606 | return -EREMOTEIO; | ||
607 | } | ||
608 | } | ||
609 | else { | ||
610 | /* Flush master data buffer (just in case) */ | ||
611 | out_8(&iic->mdcntl, in_8(&iic->mdcntl) | MDCNTL_FMDB); | ||
612 | } | ||
613 | |||
614 | /* Load slave address */ | ||
615 | iic_address(dev, &msgs[0]); | ||
616 | |||
617 | /* Do real transfer */ | ||
618 | for (i = 0; i < num && !ret; ++i) | ||
619 | ret = iic_xfer_bytes(dev, &msgs[i], i < num - 1); | ||
620 | |||
621 | return ret < 0 ? ret : num; | ||
622 | } | ||
623 | |||
624 | static u32 iic_func(struct i2c_adapter *adap) | ||
625 | { | ||
626 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR; | ||
627 | } | ||
628 | |||
629 | static struct i2c_algorithm iic_algo = { | ||
630 | .name = "IBM IIC algorithm", | ||
631 | .id = I2C_ALGO_OCP, | ||
632 | .master_xfer = iic_xfer, | ||
633 | .functionality = iic_func | ||
634 | }; | ||
635 | |||
636 | /* | ||
637 | * Calculates IICx_CLCKDIV value for a specific OPB clock frequency | ||
638 | */ | ||
639 | static inline u8 iic_clckdiv(unsigned int opb) | ||
640 | { | ||
641 | /* Compatibility kludge, should go away after all cards | ||
642 | * are fixed to fill correct value for opbfreq. | ||
643 | * Previous driver version used hardcoded divider value 4, | ||
644 | * it corresponds to OPB frequency from the range (40, 50] MHz | ||
645 | */ | ||
646 | if (!opb){ | ||
647 | printk(KERN_WARNING "ibm-iic: using compatibility value for OPB freq," | ||
648 | " fix your board specific setup\n"); | ||
649 | opb = 50000000; | ||
650 | } | ||
651 | |||
652 | /* Convert to MHz */ | ||
653 | opb /= 1000000; | ||
654 | |||
655 | if (opb < 20 || opb > 150){ | ||
656 | printk(KERN_CRIT "ibm-iic: invalid OPB clock frequency %u MHz\n", | ||
657 | opb); | ||
658 | opb = opb < 20 ? 20 : 150; | ||
659 | } | ||
660 | return (u8)((opb + 9) / 10 - 1); | ||
661 | } | ||
662 | |||
663 | /* | ||
664 | * Register single IIC interface | ||
665 | */ | ||
666 | static int __devinit iic_probe(struct ocp_device *ocp){ | ||
667 | |||
668 | struct ibm_iic_private* dev; | ||
669 | struct i2c_adapter* adap; | ||
670 | struct ocp_func_iic_data* iic_data = ocp->def->additions; | ||
671 | int ret; | ||
672 | |||
673 | if (!iic_data) | ||
674 | printk(KERN_WARNING"ibm-iic%d: missing additional data!\n", | ||
675 | ocp->def->index); | ||
676 | |||
677 | if (!(dev = kmalloc(sizeof(*dev), GFP_KERNEL))){ | ||
678 | printk(KERN_CRIT "ibm-iic%d: failed to allocate device data\n", | ||
679 | ocp->def->index); | ||
680 | return -ENOMEM; | ||
681 | } | ||
682 | |||
683 | memset(dev, 0, sizeof(*dev)); | ||
684 | dev->idx = ocp->def->index; | ||
685 | ocp_set_drvdata(ocp, dev); | ||
686 | |||
687 | if (!(dev->vaddr = ioremap(ocp->def->paddr, sizeof(struct iic_regs)))){ | ||
688 | printk(KERN_CRIT "ibm-iic%d: failed to ioremap device registers\n", | ||
689 | dev->idx); | ||
690 | ret = -ENXIO; | ||
691 | goto fail2; | ||
692 | } | ||
693 | |||
694 | init_waitqueue_head(&dev->wq); | ||
695 | |||
696 | dev->irq = iic_force_poll ? -1 : ocp->def->irq; | ||
697 | if (dev->irq >= 0){ | ||
698 | /* Disable interrupts until we finish intialization, | ||
699 | assumes level-sensitive IRQ setup... | ||
700 | */ | ||
701 | iic_interrupt_mode(dev, 0); | ||
702 | if (request_irq(dev->irq, iic_handler, 0, "IBM IIC", dev)){ | ||
703 | printk(KERN_ERR "ibm-iic%d: request_irq %d failed\n", | ||
704 | dev->idx, dev->irq); | ||
705 | /* Fallback to the polling mode */ | ||
706 | dev->irq = -1; | ||
707 | } | ||
708 | } | ||
709 | |||
710 | if (dev->irq < 0) | ||
711 | printk(KERN_WARNING "ibm-iic%d: using polling mode\n", | ||
712 | dev->idx); | ||
713 | |||
714 | /* Board specific settings */ | ||
715 | dev->fast_mode = iic_force_fast ? 1 : (iic_data ? iic_data->fast_mode : 0); | ||
716 | |||
717 | /* clckdiv is the same for *all* IIC interfaces, | ||
718 | * but I'd rather make a copy than introduce another global. --ebs | ||
719 | */ | ||
720 | dev->clckdiv = iic_clckdiv(ocp_sys_info.opb_bus_freq); | ||
721 | DBG("%d: clckdiv = %d\n", dev->idx, dev->clckdiv); | ||
722 | |||
723 | /* Initialize IIC interface */ | ||
724 | iic_dev_init(dev); | ||
725 | |||
726 | /* Register it with i2c layer */ | ||
727 | adap = &dev->adap; | ||
728 | strcpy(adap->name, "IBM IIC"); | ||
729 | i2c_set_adapdata(adap, dev); | ||
730 | adap->id = I2C_HW_OCP | iic_algo.id; | ||
731 | adap->algo = &iic_algo; | ||
732 | adap->client_register = NULL; | ||
733 | adap->client_unregister = NULL; | ||
734 | adap->timeout = 1; | ||
735 | adap->retries = 1; | ||
736 | |||
737 | if ((ret = i2c_add_adapter(adap)) != 0){ | ||
738 | printk(KERN_CRIT "ibm-iic%d: failed to register i2c adapter\n", | ||
739 | dev->idx); | ||
740 | goto fail; | ||
741 | } | ||
742 | |||
743 | printk(KERN_INFO "ibm-iic%d: using %s mode\n", dev->idx, | ||
744 | dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)"); | ||
745 | |||
746 | return 0; | ||
747 | |||
748 | fail: | ||
749 | if (dev->irq >= 0){ | ||
750 | iic_interrupt_mode(dev, 0); | ||
751 | free_irq(dev->irq, dev); | ||
752 | } | ||
753 | |||
754 | iounmap(dev->vaddr); | ||
755 | fail2: | ||
756 | ocp_set_drvdata(ocp, NULL); | ||
757 | kfree(dev); | ||
758 | return ret; | ||
759 | } | ||
760 | |||
761 | /* | ||
762 | * Cleanup initialized IIC interface | ||
763 | */ | ||
764 | static void __devexit iic_remove(struct ocp_device *ocp) | ||
765 | { | ||
766 | struct ibm_iic_private* dev = (struct ibm_iic_private*)ocp_get_drvdata(ocp); | ||
767 | BUG_ON(dev == NULL); | ||
768 | if (i2c_del_adapter(&dev->adap)){ | ||
769 | printk(KERN_CRIT "ibm-iic%d: failed to delete i2c adapter :(\n", | ||
770 | dev->idx); | ||
771 | /* That's *very* bad, just shutdown IRQ ... */ | ||
772 | if (dev->irq >= 0){ | ||
773 | iic_interrupt_mode(dev, 0); | ||
774 | free_irq(dev->irq, dev); | ||
775 | dev->irq = -1; | ||
776 | } | ||
777 | } else { | ||
778 | if (dev->irq >= 0){ | ||
779 | iic_interrupt_mode(dev, 0); | ||
780 | free_irq(dev->irq, dev); | ||
781 | } | ||
782 | iounmap(dev->vaddr); | ||
783 | kfree(dev); | ||
784 | } | ||
785 | } | ||
786 | |||
787 | static struct ocp_device_id ibm_iic_ids[] __devinitdata = | ||
788 | { | ||
789 | { .vendor = OCP_VENDOR_IBM, .function = OCP_FUNC_IIC }, | ||
790 | { .vendor = OCP_VENDOR_INVALID } | ||
791 | }; | ||
792 | |||
793 | MODULE_DEVICE_TABLE(ocp, ibm_iic_ids); | ||
794 | |||
795 | static struct ocp_driver ibm_iic_driver = | ||
796 | { | ||
797 | .name = "iic", | ||
798 | .id_table = ibm_iic_ids, | ||
799 | .probe = iic_probe, | ||
800 | .remove = __devexit_p(iic_remove), | ||
801 | #if defined(CONFIG_PM) | ||
802 | .suspend = NULL, | ||
803 | .resume = NULL, | ||
804 | #endif | ||
805 | }; | ||
806 | |||
807 | static int __init iic_init(void) | ||
808 | { | ||
809 | printk(KERN_INFO "IBM IIC driver v" DRIVER_VERSION "\n"); | ||
810 | return ocp_register_driver(&ibm_iic_driver); | ||
811 | } | ||
812 | |||
813 | static void __exit iic_exit(void) | ||
814 | { | ||
815 | ocp_unregister_driver(&ibm_iic_driver); | ||
816 | } | ||
817 | |||
818 | module_init(iic_init); | ||
819 | module_exit(iic_exit); | ||
diff --git a/drivers/i2c/busses/i2c-ibm_iic.h b/drivers/i2c/busses/i2c-ibm_iic.h new file mode 100644 index 000000000000..d819a955d890 --- /dev/null +++ b/drivers/i2c/busses/i2c-ibm_iic.h | |||
@@ -0,0 +1,124 @@ | |||
1 | /* | ||
2 | * drivers/i2c/i2c-ibm_iic.h | ||
3 | * | ||
4 | * Support for the IIC peripheral on IBM PPC 4xx | ||
5 | * | ||
6 | * Copyright (c) 2003 Zultys Technologies. | ||
7 | * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> | ||
8 | * | ||
9 | * Based on original work by | ||
10 | * Ian DaSilva <idasilva@mvista.com> | ||
11 | * Armin Kuster <akuster@mvista.com> | ||
12 | * Matt Porter <mporter@mvista.com> | ||
13 | * | ||
14 | * Copyright 2000-2003 MontaVista Software Inc. | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify it | ||
17 | * under the terms of the GNU General Public License as published by the | ||
18 | * Free Software Foundation; either version 2 of the License, or (at your | ||
19 | * option) any later version. | ||
20 | * | ||
21 | */ | ||
22 | #ifndef __I2C_IBM_IIC_H_ | ||
23 | #define __I2C_IBM_IIC_H_ | ||
24 | |||
25 | #include <linux/config.h> | ||
26 | #include <linux/i2c.h> | ||
27 | |||
28 | struct iic_regs { | ||
29 | u16 mdbuf; | ||
30 | u16 sbbuf; | ||
31 | u8 lmadr; | ||
32 | u8 hmadr; | ||
33 | u8 cntl; | ||
34 | u8 mdcntl; | ||
35 | u8 sts; | ||
36 | u8 extsts; | ||
37 | u8 lsadr; | ||
38 | u8 hsadr; | ||
39 | u8 clkdiv; | ||
40 | u8 intmsk; | ||
41 | u8 xfrcnt; | ||
42 | u8 xtcntlss; | ||
43 | u8 directcntl; | ||
44 | }; | ||
45 | |||
46 | struct ibm_iic_private { | ||
47 | struct i2c_adapter adap; | ||
48 | volatile struct iic_regs __iomem *vaddr; | ||
49 | wait_queue_head_t wq; | ||
50 | int idx; | ||
51 | int irq; | ||
52 | int fast_mode; | ||
53 | u8 clckdiv; | ||
54 | }; | ||
55 | |||
56 | /* IICx_CNTL register */ | ||
57 | #define CNTL_HMT 0x80 | ||
58 | #define CNTL_AMD 0x40 | ||
59 | #define CNTL_TCT_MASK 0x30 | ||
60 | #define CNTL_TCT_SHIFT 4 | ||
61 | #define CNTL_RPST 0x08 | ||
62 | #define CNTL_CHT 0x04 | ||
63 | #define CNTL_RW 0x02 | ||
64 | #define CNTL_PT 0x01 | ||
65 | |||
66 | /* IICx_MDCNTL register */ | ||
67 | #define MDCNTL_FSDB 0x80 | ||
68 | #define MDCNTL_FMDB 0x40 | ||
69 | #define MDCNTL_EGC 0x20 | ||
70 | #define MDCNTL_FSM 0x10 | ||
71 | #define MDCNTL_ESM 0x08 | ||
72 | #define MDCNTL_EINT 0x04 | ||
73 | #define MDCNTL_EUBS 0x02 | ||
74 | #define MDCNTL_HSCL 0x01 | ||
75 | |||
76 | /* IICx_STS register */ | ||
77 | #define STS_SSS 0x80 | ||
78 | #define STS_SLPR 0x40 | ||
79 | #define STS_MDBS 0x20 | ||
80 | #define STS_MDBF 0x10 | ||
81 | #define STS_SCMP 0x08 | ||
82 | #define STS_ERR 0x04 | ||
83 | #define STS_IRQA 0x02 | ||
84 | #define STS_PT 0x01 | ||
85 | |||
86 | /* IICx_EXTSTS register */ | ||
87 | #define EXTSTS_IRQP 0x80 | ||
88 | #define EXTSTS_BCS_MASK 0x70 | ||
89 | #define EXTSTS_BCS_FREE 0x40 | ||
90 | #define EXTSTS_IRQD 0x08 | ||
91 | #define EXTSTS_LA 0x04 | ||
92 | #define EXTSTS_ICT 0x02 | ||
93 | #define EXTSTS_XFRA 0x01 | ||
94 | |||
95 | /* IICx_INTRMSK register */ | ||
96 | #define INTRMSK_EIRC 0x80 | ||
97 | #define INTRMSK_EIRS 0x40 | ||
98 | #define INTRMSK_EIWC 0x20 | ||
99 | #define INTRMSK_EIWS 0x10 | ||
100 | #define INTRMSK_EIHE 0x08 | ||
101 | #define INTRMSK_EIIC 0x04 | ||
102 | #define INTRMSK_EITA 0x02 | ||
103 | #define INTRMSK_EIMTC 0x01 | ||
104 | |||
105 | /* IICx_XFRCNT register */ | ||
106 | #define XFRCNT_MTC_MASK 0x07 | ||
107 | |||
108 | /* IICx_XTCNTLSS register */ | ||
109 | #define XTCNTLSS_SRC 0x80 | ||
110 | #define XTCNTLSS_SRS 0x40 | ||
111 | #define XTCNTLSS_SWC 0x20 | ||
112 | #define XTCNTLSS_SWS 0x10 | ||
113 | #define XTCNTLSS_SRST 0x01 | ||
114 | |||
115 | /* IICx_DIRECTCNTL register */ | ||
116 | #define DIRCNTL_SDAC 0x08 | ||
117 | #define DIRCNTL_SCC 0x04 | ||
118 | #define DIRCNTL_MSDA 0x02 | ||
119 | #define DIRCNTL_MSC 0x01 | ||
120 | |||
121 | /* Check if we really control the I2C bus and bus is free */ | ||
122 | #define DIRCTNL_FREE(v) (((v) & 0x0f) == 0x0f) | ||
123 | |||
124 | #endif /* __I2C_IBM_IIC_H_ */ | ||
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c new file mode 100644 index 000000000000..c961ba4cfb32 --- /dev/null +++ b/drivers/i2c/busses/i2c-iop3xx.c | |||
@@ -0,0 +1,554 @@ | |||
1 | /* ------------------------------------------------------------------------- */ | ||
2 | /* i2c-iop3xx.c i2c driver algorithms for Intel XScale IOP3xx & IXP46x */ | ||
3 | /* ------------------------------------------------------------------------- */ | ||
4 | /* Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd | ||
5 | * <Peter dot Milne at D hyphen TACQ dot com> | ||
6 | * | ||
7 | * With acknowledgements to i2c-algo-ibm_ocp.c by | ||
8 | * Ian DaSilva, MontaVista Software, Inc. idasilva@mvista.com | ||
9 | * | ||
10 | * And i2c-algo-pcf.c, which was created by Simon G. Vogl and Hans Berglund: | ||
11 | * | ||
12 | * Copyright (C) 1995-1997 Simon G. Vogl, 1998-2000 Hans Berglund | ||
13 | * | ||
14 | * And which acknowledged Kyösti Mälkki <kmalkki@cc.hut.fi>, | ||
15 | * Frodo Looijaard <frodol@dds.nl>, Martin Bailey<mbailey@littlefeet-inc.com> | ||
16 | * | ||
17 | * Major cleanup by Deepak Saxena <dsaxena@plexity.net>, 01/2005: | ||
18 | * | ||
19 | * - Use driver model to pass per-chip info instead of hardcoding and #ifdefs | ||
20 | * - Use ioremap/__raw_readl/__raw_writel instead of direct dereference | ||
21 | * - Make it work with IXP46x chips | ||
22 | * - Cleanup function names, coding style, etc | ||
23 | * | ||
24 | * This program is free software; you can redistribute it and/or modify | ||
25 | * it under the terms of the GNU General Public License as published by | ||
26 | * the Free Software Foundation, version 2. | ||
27 | */ | ||
28 | |||
29 | #include <linux/config.h> | ||
30 | #include <linux/interrupt.h> | ||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/delay.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <linux/init.h> | ||
36 | #include <linux/errno.h> | ||
37 | #include <linux/sched.h> | ||
38 | #include <linux/device.h> | ||
39 | #include <linux/i2c.h> | ||
40 | |||
41 | #include <asm/io.h> | ||
42 | |||
43 | #include "i2c-iop3xx.h" | ||
44 | |||
45 | /* global unit counter */ | ||
46 | static int i2c_id = 0; | ||
47 | |||
48 | static inline unsigned char | ||
49 | iic_cook_addr(struct i2c_msg *msg) | ||
50 | { | ||
51 | unsigned char addr; | ||
52 | |||
53 | addr = (msg->addr << 1); | ||
54 | |||
55 | if (msg->flags & I2C_M_RD) | ||
56 | addr |= 1; | ||
57 | |||
58 | /* | ||
59 | * Read or Write? | ||
60 | */ | ||
61 | if (msg->flags & I2C_M_REV_DIR_ADDR) | ||
62 | addr ^= 1; | ||
63 | |||
64 | return addr; | ||
65 | } | ||
66 | |||
67 | static void | ||
68 | iop3xx_i2c_reset(struct i2c_algo_iop3xx_data *iop3xx_adap) | ||
69 | { | ||
70 | /* Follows devman 9.3 */ | ||
71 | __raw_writel(IOP3XX_ICR_UNIT_RESET, iop3xx_adap->ioaddr + CR_OFFSET); | ||
72 | __raw_writel(IOP3XX_ISR_CLEARBITS, iop3xx_adap->ioaddr + SR_OFFSET); | ||
73 | __raw_writel(0, iop3xx_adap->ioaddr + CR_OFFSET); | ||
74 | } | ||
75 | |||
76 | static void | ||
77 | iop3xx_i2c_set_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap) | ||
78 | { | ||
79 | __raw_writel(MYSAR, iop3xx_adap->ioaddr + SAR_OFFSET); | ||
80 | } | ||
81 | |||
82 | static void | ||
83 | iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap) | ||
84 | { | ||
85 | u32 cr = IOP3XX_ICR_GCD | IOP3XX_ICR_SCLEN | IOP3XX_ICR_UE; | ||
86 | |||
87 | /* | ||
88 | * Everytime unit enable is asserted, GPOD needs to be cleared | ||
89 | * on IOP321 to avoid data corruption on the bus. | ||
90 | */ | ||
91 | #ifdef CONFIG_ARCH_IOP321 | ||
92 | #define IOP321_GPOD_I2C0 0x00c0 /* clear these bits to enable ch0 */ | ||
93 | #define IOP321_GPOD_I2C1 0x0030 /* clear these bits to enable ch1 */ | ||
94 | |||
95 | *IOP321_GPOD &= (iop3xx_adap->id == 0) ? ~IOP321_GPOD_I2C0 : | ||
96 | ~IOP321_GPOD_I2C1; | ||
97 | #endif | ||
98 | /* NB SR bits not same position as CR IE bits :-( */ | ||
99 | iop3xx_adap->SR_enabled = | ||
100 | IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD | | ||
101 | IOP3XX_ISR_RXFULL | IOP3XX_ISR_TXEMPTY; | ||
102 | |||
103 | cr |= IOP3XX_ICR_ALD_IE | IOP3XX_ICR_BERR_IE | | ||
104 | IOP3XX_ICR_RXFULL_IE | IOP3XX_ICR_TXEMPTY_IE; | ||
105 | |||
106 | __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET); | ||
107 | } | ||
108 | |||
109 | static void | ||
110 | iop3xx_i2c_transaction_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap) | ||
111 | { | ||
112 | unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET); | ||
113 | |||
114 | cr &= ~(IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE | | ||
115 | IOP3XX_ICR_MSTOP | IOP3XX_ICR_SCLEN); | ||
116 | |||
117 | __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET); | ||
118 | } | ||
119 | |||
120 | /* | ||
121 | * NB: the handler has to clear the source of the interrupt! | ||
122 | * Then it passes the SR flags of interest to BH via adap data | ||
123 | */ | ||
124 | static irqreturn_t | ||
125 | iop3xx_i2c_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs) | ||
126 | { | ||
127 | struct i2c_algo_iop3xx_data *iop3xx_adap = dev_id; | ||
128 | u32 sr = __raw_readl(iop3xx_adap->ioaddr + SR_OFFSET); | ||
129 | |||
130 | if ((sr &= iop3xx_adap->SR_enabled)) { | ||
131 | __raw_writel(sr, iop3xx_adap->ioaddr + SR_OFFSET); | ||
132 | iop3xx_adap->SR_received |= sr; | ||
133 | wake_up_interruptible(&iop3xx_adap->waitq); | ||
134 | } | ||
135 | return IRQ_HANDLED; | ||
136 | } | ||
137 | |||
138 | /* check all error conditions, clear them , report most important */ | ||
139 | static int | ||
140 | iop3xx_i2c_error(u32 sr) | ||
141 | { | ||
142 | int rc = 0; | ||
143 | |||
144 | if ((sr & IOP3XX_ISR_BERRD)) { | ||
145 | if ( !rc ) rc = -I2C_ERR_BERR; | ||
146 | } | ||
147 | if ((sr & IOP3XX_ISR_ALD)) { | ||
148 | if ( !rc ) rc = -I2C_ERR_ALD; | ||
149 | } | ||
150 | return rc; | ||
151 | } | ||
152 | |||
153 | static inline u32 | ||
154 | iop3xx_i2c_get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap) | ||
155 | { | ||
156 | unsigned long flags; | ||
157 | u32 sr; | ||
158 | |||
159 | spin_lock_irqsave(&iop3xx_adap->lock, flags); | ||
160 | sr = iop3xx_adap->SR_received; | ||
161 | iop3xx_adap->SR_received = 0; | ||
162 | spin_unlock_irqrestore(&iop3xx_adap->lock, flags); | ||
163 | |||
164 | return sr; | ||
165 | } | ||
166 | |||
167 | /* | ||
168 | * sleep until interrupted, then recover and analyse the SR | ||
169 | * saved by handler | ||
170 | */ | ||
171 | typedef int (* compare_func)(unsigned test, unsigned mask); | ||
172 | /* returns 1 on correct comparison */ | ||
173 | |||
174 | static int | ||
175 | iop3xx_i2c_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap, | ||
176 | unsigned flags, unsigned* status, | ||
177 | compare_func compare) | ||
178 | { | ||
179 | unsigned sr = 0; | ||
180 | int interrupted; | ||
181 | int done; | ||
182 | int rc = 0; | ||
183 | |||
184 | do { | ||
185 | interrupted = wait_event_interruptible_timeout ( | ||
186 | iop3xx_adap->waitq, | ||
187 | (done = compare( sr = iop3xx_i2c_get_srstat(iop3xx_adap) ,flags )), | ||
188 | 1 * HZ; | ||
189 | ); | ||
190 | if ((rc = iop3xx_i2c_error(sr)) < 0) { | ||
191 | *status = sr; | ||
192 | return rc; | ||
193 | } else if (!interrupted) { | ||
194 | *status = sr; | ||
195 | return -ETIMEDOUT; | ||
196 | } | ||
197 | } while(!done); | ||
198 | |||
199 | *status = sr; | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | /* | ||
205 | * Concrete compare_funcs | ||
206 | */ | ||
207 | static int | ||
208 | all_bits_clear(unsigned test, unsigned mask) | ||
209 | { | ||
210 | return (test & mask) == 0; | ||
211 | } | ||
212 | |||
213 | static int | ||
214 | any_bits_set(unsigned test, unsigned mask) | ||
215 | { | ||
216 | return (test & mask) != 0; | ||
217 | } | ||
218 | |||
219 | static int | ||
220 | iop3xx_i2c_wait_tx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status) | ||
221 | { | ||
222 | return iop3xx_i2c_wait_event( | ||
223 | iop3xx_adap, | ||
224 | IOP3XX_ISR_TXEMPTY | IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD, | ||
225 | status, any_bits_set); | ||
226 | } | ||
227 | |||
228 | static int | ||
229 | iop3xx_i2c_wait_rx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status) | ||
230 | { | ||
231 | return iop3xx_i2c_wait_event( | ||
232 | iop3xx_adap, | ||
233 | IOP3XX_ISR_RXFULL | IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD, | ||
234 | status, any_bits_set); | ||
235 | } | ||
236 | |||
237 | static int | ||
238 | iop3xx_i2c_wait_idle(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status) | ||
239 | { | ||
240 | return iop3xx_i2c_wait_event( | ||
241 | iop3xx_adap, IOP3XX_ISR_UNITBUSY, status, all_bits_clear); | ||
242 | } | ||
243 | |||
244 | static int | ||
245 | iop3xx_i2c_send_target_addr(struct i2c_algo_iop3xx_data *iop3xx_adap, | ||
246 | struct i2c_msg* msg) | ||
247 | { | ||
248 | unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET); | ||
249 | int status; | ||
250 | int rc; | ||
251 | |||
252 | __raw_writel(iic_cook_addr(msg), iop3xx_adap->ioaddr + DBR_OFFSET); | ||
253 | |||
254 | cr &= ~(IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK); | ||
255 | cr |= IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE; | ||
256 | |||
257 | __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET); | ||
258 | rc = iop3xx_i2c_wait_tx_done(iop3xx_adap, &status); | ||
259 | |||
260 | return rc; | ||
261 | } | ||
262 | |||
263 | static int | ||
264 | iop3xx_i2c_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte, | ||
265 | int stop) | ||
266 | { | ||
267 | unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET); | ||
268 | int status; | ||
269 | int rc = 0; | ||
270 | |||
271 | __raw_writel(byte, iop3xx_adap->ioaddr + DBR_OFFSET); | ||
272 | cr &= ~IOP3XX_ICR_MSTART; | ||
273 | if (stop) { | ||
274 | cr |= IOP3XX_ICR_MSTOP; | ||
275 | } else { | ||
276 | cr &= ~IOP3XX_ICR_MSTOP; | ||
277 | } | ||
278 | cr |= IOP3XX_ICR_TBYTE; | ||
279 | __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET); | ||
280 | rc = iop3xx_i2c_wait_tx_done(iop3xx_adap, &status); | ||
281 | |||
282 | return rc; | ||
283 | } | ||
284 | |||
285 | static int | ||
286 | iop3xx_i2c_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char* byte, | ||
287 | int stop) | ||
288 | { | ||
289 | unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET); | ||
290 | int status; | ||
291 | int rc = 0; | ||
292 | |||
293 | cr &= ~IOP3XX_ICR_MSTART; | ||
294 | |||
295 | if (stop) { | ||
296 | cr |= IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK; | ||
297 | } else { | ||
298 | cr &= ~(IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK); | ||
299 | } | ||
300 | cr |= IOP3XX_ICR_TBYTE; | ||
301 | __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET); | ||
302 | |||
303 | rc = iop3xx_i2c_wait_rx_done(iop3xx_adap, &status); | ||
304 | |||
305 | *byte = __raw_readl(iop3xx_adap->ioaddr + DBR_OFFSET); | ||
306 | |||
307 | return rc; | ||
308 | } | ||
309 | |||
310 | static int | ||
311 | iop3xx_i2c_writebytes(struct i2c_adapter *i2c_adap, const char *buf, int count) | ||
312 | { | ||
313 | struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; | ||
314 | int ii; | ||
315 | int rc = 0; | ||
316 | |||
317 | for (ii = 0; rc == 0 && ii != count; ++ii) | ||
318 | rc = iop3xx_i2c_write_byte(iop3xx_adap, buf[ii], ii==count-1); | ||
319 | return rc; | ||
320 | } | ||
321 | |||
322 | static int | ||
323 | iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count) | ||
324 | { | ||
325 | struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; | ||
326 | int ii; | ||
327 | int rc = 0; | ||
328 | |||
329 | for (ii = 0; rc == 0 && ii != count; ++ii) | ||
330 | rc = iop3xx_i2c_read_byte(iop3xx_adap, &buf[ii], ii==count-1); | ||
331 | |||
332 | return rc; | ||
333 | } | ||
334 | |||
335 | /* | ||
336 | * Description: This function implements combined transactions. Combined | ||
337 | * transactions consist of combinations of reading and writing blocks of data. | ||
338 | * FROM THE SAME ADDRESS | ||
339 | * Each transfer (i.e. a read or a write) is separated by a repeated start | ||
340 | * condition. | ||
341 | */ | ||
342 | static int | ||
343 | iop3xx_i2c_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg) | ||
344 | { | ||
345 | struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; | ||
346 | int rc; | ||
347 | |||
348 | rc = iop3xx_i2c_send_target_addr(iop3xx_adap, pmsg); | ||
349 | if (rc < 0) { | ||
350 | return rc; | ||
351 | } | ||
352 | |||
353 | if ((pmsg->flags&I2C_M_RD)) { | ||
354 | return iop3xx_i2c_readbytes(i2c_adap, pmsg->buf, pmsg->len); | ||
355 | } else { | ||
356 | return iop3xx_i2c_writebytes(i2c_adap, pmsg->buf, pmsg->len); | ||
357 | } | ||
358 | } | ||
359 | |||
360 | /* | ||
361 | * master_xfer() - main read/write entry | ||
362 | */ | ||
363 | static int | ||
364 | iop3xx_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, | ||
365 | int num) | ||
366 | { | ||
367 | struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; | ||
368 | int im = 0; | ||
369 | int ret = 0; | ||
370 | int status; | ||
371 | |||
372 | iop3xx_i2c_wait_idle(iop3xx_adap, &status); | ||
373 | iop3xx_i2c_reset(iop3xx_adap); | ||
374 | iop3xx_i2c_enable(iop3xx_adap); | ||
375 | |||
376 | for (im = 0; ret == 0 && im != num; im++) { | ||
377 | ret = iop3xx_i2c_handle_msg(i2c_adap, &msgs[im]); | ||
378 | } | ||
379 | |||
380 | iop3xx_i2c_transaction_cleanup(iop3xx_adap); | ||
381 | |||
382 | if(ret) | ||
383 | return ret; | ||
384 | |||
385 | return im; | ||
386 | } | ||
387 | |||
388 | static int | ||
389 | iop3xx_i2c_algo_control(struct i2c_adapter *adapter, unsigned int cmd, | ||
390 | unsigned long arg) | ||
391 | { | ||
392 | return 0; | ||
393 | } | ||
394 | |||
395 | static u32 | ||
396 | iop3xx_i2c_func(struct i2c_adapter *adap) | ||
397 | { | ||
398 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | ||
399 | } | ||
400 | |||
401 | static struct i2c_algorithm iop3xx_i2c_algo = { | ||
402 | .name = "IOP3xx I2C algorithm", | ||
403 | .id = I2C_ALGO_IOP3XX, | ||
404 | .master_xfer = iop3xx_i2c_master_xfer, | ||
405 | .algo_control = iop3xx_i2c_algo_control, | ||
406 | .functionality = iop3xx_i2c_func, | ||
407 | }; | ||
408 | |||
409 | static int | ||
410 | iop3xx_i2c_remove(struct device *device) | ||
411 | { | ||
412 | struct platform_device *pdev = to_platform_device(device); | ||
413 | struct i2c_adapter *padapter = dev_get_drvdata(&pdev->dev); | ||
414 | struct i2c_algo_iop3xx_data *adapter_data = | ||
415 | (struct i2c_algo_iop3xx_data *)padapter->algo_data; | ||
416 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
417 | unsigned long cr = __raw_readl(adapter_data->ioaddr + CR_OFFSET); | ||
418 | |||
419 | /* | ||
420 | * Disable the actual HW unit | ||
421 | */ | ||
422 | cr &= ~(IOP3XX_ICR_ALD_IE | IOP3XX_ICR_BERR_IE | | ||
423 | IOP3XX_ICR_RXFULL_IE | IOP3XX_ICR_TXEMPTY_IE); | ||
424 | __raw_writel(cr, adapter_data->ioaddr + CR_OFFSET); | ||
425 | |||
426 | iounmap((void __iomem*)adapter_data->ioaddr); | ||
427 | release_mem_region(res->start, IOP3XX_I2C_IO_SIZE); | ||
428 | kfree(adapter_data); | ||
429 | kfree(padapter); | ||
430 | |||
431 | dev_set_drvdata(&pdev->dev, NULL); | ||
432 | |||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | static int | ||
437 | iop3xx_i2c_probe(struct device *dev) | ||
438 | { | ||
439 | struct platform_device *pdev = to_platform_device(dev); | ||
440 | struct resource *res; | ||
441 | int ret; | ||
442 | struct i2c_adapter *new_adapter; | ||
443 | struct i2c_algo_iop3xx_data *adapter_data; | ||
444 | |||
445 | new_adapter = kmalloc(sizeof(struct i2c_adapter), GFP_KERNEL); | ||
446 | if (!new_adapter) { | ||
447 | ret = -ENOMEM; | ||
448 | goto out; | ||
449 | } | ||
450 | memset((void*)new_adapter, 0, sizeof(*new_adapter)); | ||
451 | |||
452 | adapter_data = kmalloc(sizeof(struct i2c_algo_iop3xx_data), GFP_KERNEL); | ||
453 | if (!adapter_data) { | ||
454 | ret = -ENOMEM; | ||
455 | goto free_adapter; | ||
456 | } | ||
457 | memset((void*)adapter_data, 0, sizeof(*adapter_data)); | ||
458 | |||
459 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
460 | if (!res) { | ||
461 | ret = -ENODEV; | ||
462 | goto free_both; | ||
463 | } | ||
464 | |||
465 | if (!request_mem_region(res->start, IOP3XX_I2C_IO_SIZE, pdev->name)) { | ||
466 | ret = -EBUSY; | ||
467 | goto free_both; | ||
468 | } | ||
469 | |||
470 | /* set the adapter enumeration # */ | ||
471 | adapter_data->id = i2c_id++; | ||
472 | |||
473 | adapter_data->ioaddr = (u32)ioremap(res->start, IOP3XX_I2C_IO_SIZE); | ||
474 | if (!adapter_data->ioaddr) { | ||
475 | ret = -ENOMEM; | ||
476 | goto release_region; | ||
477 | } | ||
478 | |||
479 | res = request_irq(platform_get_irq(pdev, 0), iop3xx_i2c_irq_handler, 0, | ||
480 | pdev->name, adapter_data); | ||
481 | if (res) { | ||
482 | ret = -EIO; | ||
483 | goto unmap; | ||
484 | } | ||
485 | |||
486 | memcpy(new_adapter->name, pdev->name, strlen(pdev->name)); | ||
487 | new_adapter->id = I2C_HW_IOP3XX; | ||
488 | new_adapter->owner = THIS_MODULE; | ||
489 | new_adapter->dev.parent = &pdev->dev; | ||
490 | |||
491 | /* | ||
492 | * Default values...should these come in from board code? | ||
493 | */ | ||
494 | new_adapter->timeout = 100; | ||
495 | new_adapter->retries = 3; | ||
496 | new_adapter->algo = &iop3xx_i2c_algo; | ||
497 | |||
498 | init_waitqueue_head(&adapter_data->waitq); | ||
499 | spin_lock_init(&adapter_data->lock); | ||
500 | |||
501 | iop3xx_i2c_reset(adapter_data); | ||
502 | iop3xx_i2c_set_slave_addr(adapter_data); | ||
503 | iop3xx_i2c_enable(adapter_data); | ||
504 | |||
505 | dev_set_drvdata(&pdev->dev, new_adapter); | ||
506 | new_adapter->algo_data = adapter_data; | ||
507 | |||
508 | i2c_add_adapter(new_adapter); | ||
509 | |||
510 | return 0; | ||
511 | |||
512 | unmap: | ||
513 | iounmap((void __iomem*)adapter_data->ioaddr); | ||
514 | |||
515 | release_region: | ||
516 | release_mem_region(res->start, IOP3XX_I2C_IO_SIZE); | ||
517 | |||
518 | free_both: | ||
519 | kfree(adapter_data); | ||
520 | |||
521 | free_adapter: | ||
522 | kfree(new_adapter); | ||
523 | |||
524 | out: | ||
525 | return ret; | ||
526 | } | ||
527 | |||
528 | |||
529 | static struct device_driver iop3xx_i2c_driver = { | ||
530 | .name = "IOP3xx-I2C", | ||
531 | .bus = &platform_bus_type, | ||
532 | .probe = iop3xx_i2c_probe, | ||
533 | .remove = iop3xx_i2c_remove | ||
534 | }; | ||
535 | |||
536 | static int __init | ||
537 | i2c_iop3xx_init (void) | ||
538 | { | ||
539 | return driver_register(&iop3xx_i2c_driver); | ||
540 | } | ||
541 | |||
542 | static void __exit | ||
543 | i2c_iop3xx_exit (void) | ||
544 | { | ||
545 | driver_unregister(&iop3xx_i2c_driver); | ||
546 | return; | ||
547 | } | ||
548 | |||
549 | module_init (i2c_iop3xx_init); | ||
550 | module_exit (i2c_iop3xx_exit); | ||
551 | |||
552 | MODULE_AUTHOR("D-TACQ Solutions Ltd <www.d-tacq.com>"); | ||
553 | MODULE_DESCRIPTION("IOP3xx iic algorithm and driver"); | ||
554 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/i2c/busses/i2c-iop3xx.h b/drivers/i2c/busses/i2c-iop3xx.h new file mode 100644 index 000000000000..e46ebaea7b1e --- /dev/null +++ b/drivers/i2c/busses/i2c-iop3xx.h | |||
@@ -0,0 +1,107 @@ | |||
1 | /* ------------------------------------------------------------------------- */ | ||
2 | /* i2c-iop3xx.h algorithm driver definitions private to i2c-iop3xx.c */ | ||
3 | /* ------------------------------------------------------------------------- */ | ||
4 | /* Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd | ||
5 | * <Peter dot Milne at D hyphen TACQ dot com> | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation, version 2. | ||
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 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
19 | /* ------------------------------------------------------------------------- */ | ||
20 | |||
21 | |||
22 | #ifndef I2C_IOP3XX_H | ||
23 | #define I2C_IOP3XX_H 1 | ||
24 | |||
25 | /* | ||
26 | * iop321 hardware bit definitions | ||
27 | */ | ||
28 | #define IOP3XX_ICR_FAST_MODE 0x8000 /* 1=400kBps, 0=100kBps */ | ||
29 | #define IOP3XX_ICR_UNIT_RESET 0x4000 /* 1=RESET */ | ||
30 | #define IOP3XX_ICR_SAD_IE 0x2000 /* 1=Slave Detect Interrupt Enable */ | ||
31 | #define IOP3XX_ICR_ALD_IE 0x1000 /* 1=Arb Loss Detect Interrupt Enable */ | ||
32 | #define IOP3XX_ICR_SSD_IE 0x0800 /* 1=Slave STOP Detect Interrupt Enable */ | ||
33 | #define IOP3XX_ICR_BERR_IE 0x0400 /* 1=Bus Error Interrupt Enable */ | ||
34 | #define IOP3XX_ICR_RXFULL_IE 0x0200 /* 1=Receive Full Interrupt Enable */ | ||
35 | #define IOP3XX_ICR_TXEMPTY_IE 0x0100 /* 1=Transmit Empty Interrupt Enable */ | ||
36 | #define IOP3XX_ICR_GCD 0x0080 /* 1=General Call Disable */ | ||
37 | /* | ||
38 | * IOP3XX_ICR_GCD: 1 disables response as slave. "This bit must be set | ||
39 | * when sending a master mode general call message from the I2C unit" | ||
40 | */ | ||
41 | #define IOP3XX_ICR_UE 0x0040 /* 1=Unit Enable */ | ||
42 | /* | ||
43 | * "NOTE: To avoid I2C bus integrity problems, | ||
44 | * the user needs to ensure that the GPIO Output Data Register - | ||
45 | * GPOD bits associated with an I2C port are cleared prior to setting | ||
46 | * the enable bit for that I2C serial port. | ||
47 | * The user prepares to enable I2C port 0 and | ||
48 | * I2C port 1 by clearing GPOD bits 7:6 and GPOD bits 5:4, respectively. | ||
49 | */ | ||
50 | #define IOP3XX_ICR_SCLEN 0x0020 /* 1=SCL enable for master mode */ | ||
51 | #define IOP3XX_ICR_MABORT 0x0010 /* 1=Send a STOP with no data | ||
52 | * NB TBYTE must be clear */ | ||
53 | #define IOP3XX_ICR_TBYTE 0x0008 /* 1=Send/Receive a byte. i2c clears */ | ||
54 | #define IOP3XX_ICR_NACK 0x0004 /* 1=reply with NACK */ | ||
55 | #define IOP3XX_ICR_MSTOP 0x0002 /* 1=send a STOP after next data byte */ | ||
56 | #define IOP3XX_ICR_MSTART 0x0001 /* 1=initiate a START */ | ||
57 | |||
58 | |||
59 | #define IOP3XX_ISR_BERRD 0x0400 /* 1=BUS ERROR Detected */ | ||
60 | #define IOP3XX_ISR_SAD 0x0200 /* 1=Slave ADdress Detected */ | ||
61 | #define IOP3XX_ISR_GCAD 0x0100 /* 1=General Call Address Detected */ | ||
62 | #define IOP3XX_ISR_RXFULL 0x0080 /* 1=Receive Full */ | ||
63 | #define IOP3XX_ISR_TXEMPTY 0x0040 /* 1=Transmit Empty */ | ||
64 | #define IOP3XX_ISR_ALD 0x0020 /* 1=Arbitration Loss Detected */ | ||
65 | #define IOP3XX_ISR_SSD 0x0010 /* 1=Slave STOP Detected */ | ||
66 | #define IOP3XX_ISR_BBUSY 0x0008 /* 1=Bus BUSY */ | ||
67 | #define IOP3XX_ISR_UNITBUSY 0x0004 /* 1=Unit Busy */ | ||
68 | #define IOP3XX_ISR_NACK 0x0002 /* 1=Unit Rx or Tx a NACK */ | ||
69 | #define IOP3XX_ISR_RXREAD 0x0001 /* 1=READ 0=WRITE (R/W bit of slave addr */ | ||
70 | |||
71 | #define IOP3XX_ISR_CLEARBITS 0x07f0 | ||
72 | |||
73 | #define IOP3XX_ISAR_SAMASK 0x007f | ||
74 | |||
75 | #define IOP3XX_IDBR_MASK 0x00ff | ||
76 | |||
77 | #define IOP3XX_IBMR_SCL 0x0002 | ||
78 | #define IOP3XX_IBMR_SDA 0x0001 | ||
79 | |||
80 | #define IOP3XX_GPOD_I2C0 0x00c0 /* clear these bits to enable ch0 */ | ||
81 | #define IOP3XX_GPOD_I2C1 0x0030 /* clear these bits to enable ch1 */ | ||
82 | |||
83 | #define MYSAR 0x02 /* SWAG a suitable slave address */ | ||
84 | |||
85 | #define I2C_ERR 321 | ||
86 | #define I2C_ERR_BERR (I2C_ERR+0) | ||
87 | #define I2C_ERR_ALD (I2C_ERR+1) | ||
88 | |||
89 | |||
90 | #define CR_OFFSET 0 | ||
91 | #define SR_OFFSET 0x4 | ||
92 | #define SAR_OFFSET 0x8 | ||
93 | #define DBR_OFFSET 0xc | ||
94 | #define CCR_OFFSET 0x10 | ||
95 | #define BMR_OFFSET 0x14 | ||
96 | |||
97 | #define IOP3XX_I2C_IO_SIZE 0x18 | ||
98 | |||
99 | struct i2c_algo_iop3xx_data { | ||
100 | u32 ioaddr; | ||
101 | wait_queue_head_t waitq; | ||
102 | spinlock_t lock; | ||
103 | u32 SR_enabled, SR_received; | ||
104 | int id; | ||
105 | }; | ||
106 | |||
107 | #endif /* I2C_IOP3XX_H */ | ||
diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c new file mode 100644 index 000000000000..0f54a2a0afa5 --- /dev/null +++ b/drivers/i2c/busses/i2c-isa.c | |||
@@ -0,0 +1,72 @@ | |||
1 | /* | ||
2 | i2c-isa.c - Part of lm_sensors, Linux kernel modules for hardware | ||
3 | monitoring | ||
4 | Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> | ||
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 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | /* This implements an i2c algorithm/adapter for ISA bus. Not that this is | ||
22 | on first sight very useful; almost no functionality is preserved. | ||
23 | Except that it makes writing drivers for chips which can be on both | ||
24 | the SMBus and the ISA bus very much easier. See lm78.c for an example | ||
25 | of this. */ | ||
26 | |||
27 | #include <linux/config.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/errno.h> | ||
32 | #include <linux/i2c.h> | ||
33 | |||
34 | static u32 isa_func(struct i2c_adapter *adapter); | ||
35 | |||
36 | /* This is the actual algorithm we define */ | ||
37 | static struct i2c_algorithm isa_algorithm = { | ||
38 | .name = "ISA bus algorithm", | ||
39 | .id = I2C_ALGO_ISA, | ||
40 | .functionality = isa_func, | ||
41 | }; | ||
42 | |||
43 | /* There can only be one... */ | ||
44 | static struct i2c_adapter isa_adapter = { | ||
45 | .owner = THIS_MODULE, | ||
46 | .class = I2C_CLASS_HWMON, | ||
47 | .algo = &isa_algorithm, | ||
48 | .name = "ISA main adapter", | ||
49 | }; | ||
50 | |||
51 | /* We can't do a thing... */ | ||
52 | static u32 isa_func(struct i2c_adapter *adapter) | ||
53 | { | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static int __init i2c_isa_init(void) | ||
58 | { | ||
59 | return i2c_add_adapter(&isa_adapter); | ||
60 | } | ||
61 | |||
62 | static void __exit i2c_isa_exit(void) | ||
63 | { | ||
64 | i2c_del_adapter(&isa_adapter); | ||
65 | } | ||
66 | |||
67 | MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"); | ||
68 | MODULE_DESCRIPTION("ISA bus access through i2c"); | ||
69 | MODULE_LICENSE("GPL"); | ||
70 | |||
71 | module_init(i2c_isa_init); | ||
72 | module_exit(i2c_isa_exit); | ||
diff --git a/drivers/i2c/busses/i2c-ite.c b/drivers/i2c/busses/i2c-ite.c new file mode 100644 index 000000000000..702e3def1b81 --- /dev/null +++ b/drivers/i2c/busses/i2c-ite.c | |||
@@ -0,0 +1,282 @@ | |||
1 | /* | ||
2 | ------------------------------------------------------------------------- | ||
3 | i2c-adap-ite.c i2c-hw access for the IIC peripheral on the ITE MIPS system | ||
4 | ------------------------------------------------------------------------- | ||
5 | Hai-Pao Fan, MontaVista Software, Inc. | ||
6 | hpfan@mvista.com or source@mvista.com | ||
7 | |||
8 | Copyright 2001 MontaVista Software Inc. | ||
9 | |||
10 | ---------------------------------------------------------------------------- | ||
11 | This file was highly leveraged from i2c-elektor.c, which was created | ||
12 | by Simon G. Vogl and Hans Berglund: | ||
13 | |||
14 | |||
15 | Copyright (C) 1995-97 Simon G. Vogl | ||
16 | 1998-99 Hans Berglund | ||
17 | |||
18 | This program is free software; you can redistribute it and/or modify | ||
19 | it under the terms of the GNU General Public License as published by | ||
20 | the Free Software Foundation; either version 2 of the License, or | ||
21 | (at your option) any later version. | ||
22 | |||
23 | This program is distributed in the hope that it will be useful, | ||
24 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
25 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
26 | GNU General Public License for more details. | ||
27 | |||
28 | You should have received a copy of the GNU General Public License | ||
29 | along with this program; if not, write to the Free Software | ||
30 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
31 | /* ------------------------------------------------------------------------- */ | ||
32 | |||
33 | /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even | ||
34 | Frodo Looijaard <frodol@dds.nl> */ | ||
35 | |||
36 | #include <linux/config.h> | ||
37 | #include <linux/kernel.h> | ||
38 | #include <linux/ioport.h> | ||
39 | #include <linux/module.h> | ||
40 | #include <linux/delay.h> | ||
41 | #include <linux/slab.h> | ||
42 | #include <linux/init.h> | ||
43 | #include <linux/wait.h> | ||
44 | #include <asm/irq.h> | ||
45 | #include <asm/io.h> | ||
46 | |||
47 | #include <linux/i2c.h> | ||
48 | #include <linux/i2c-algo-ite.h> | ||
49 | #include <linux/i2c-adap-ite.h> | ||
50 | #include "../i2c-ite.h" | ||
51 | |||
52 | #define DEFAULT_BASE 0x14014030 | ||
53 | #define ITE_IIC_IO_SIZE 0x40 | ||
54 | #define DEFAULT_IRQ 0 | ||
55 | #define DEFAULT_CLOCK 0x1b0e /* default 16MHz/(27+14) = 400KHz */ | ||
56 | #define DEFAULT_OWN 0x55 | ||
57 | |||
58 | static int base; | ||
59 | static int irq; | ||
60 | static int clock; | ||
61 | static int own; | ||
62 | |||
63 | static struct iic_ite gpi; | ||
64 | static wait_queue_head_t iic_wait; | ||
65 | static int iic_pending; | ||
66 | static spinlock_t lock; | ||
67 | |||
68 | /* ----- local functions ---------------------------------------------- */ | ||
69 | |||
70 | static void iic_ite_setiic(void *data, int ctl, short val) | ||
71 | { | ||
72 | unsigned long j = jiffies + 10; | ||
73 | |||
74 | pr_debug(" Write 0x%02x to 0x%x\n",(unsigned short)val, ctl&0xff); | ||
75 | #ifdef DEBUG | ||
76 | while (time_before(jiffies, j)) | ||
77 | schedule(); | ||
78 | #endif | ||
79 | outw(val,ctl); | ||
80 | } | ||
81 | |||
82 | static short iic_ite_getiic(void *data, int ctl) | ||
83 | { | ||
84 | short val; | ||
85 | |||
86 | val = inw(ctl); | ||
87 | pr_debug("Read 0x%02x from 0x%x\n",(unsigned short)val, ctl&0xff); | ||
88 | return (val); | ||
89 | } | ||
90 | |||
91 | /* Return our slave address. This is the address | ||
92 | * put on the I2C bus when another master on the bus wants to address us | ||
93 | * as a slave | ||
94 | */ | ||
95 | static int iic_ite_getown(void *data) | ||
96 | { | ||
97 | return (gpi.iic_own); | ||
98 | } | ||
99 | |||
100 | |||
101 | static int iic_ite_getclock(void *data) | ||
102 | { | ||
103 | return (gpi.iic_clock); | ||
104 | } | ||
105 | |||
106 | |||
107 | /* Put this process to sleep. We will wake up when the | ||
108 | * IIC controller interrupts. | ||
109 | */ | ||
110 | static void iic_ite_waitforpin(void) { | ||
111 | DEFINE_WAIT(wait); | ||
112 | int timeout = 2; | ||
113 | long flags; | ||
114 | |||
115 | /* If interrupts are enabled (which they are), then put the process to | ||
116 | * sleep. This process will be awakened by two events -- either the | ||
117 | * the IIC peripheral interrupts or the timeout expires. | ||
118 | * If interrupts are not enabled then delay for a reasonable amount | ||
119 | * of time and return. | ||
120 | */ | ||
121 | if (gpi.iic_irq > 0) { | ||
122 | spin_lock_irqsave(&lock, flags); | ||
123 | if (iic_pending == 0) { | ||
124 | spin_unlock_irqrestore(&lock, flags); | ||
125 | prepare_to_wait(&iic_wait, &wait, TASK_INTERRUPTIBLE); | ||
126 | if (schedule_timeout(timeout*HZ)) { | ||
127 | spin_lock_irqsave(&lock, flags); | ||
128 | if (iic_pending == 1) { | ||
129 | iic_pending = 0; | ||
130 | } | ||
131 | spin_unlock_irqrestore(&lock, flags); | ||
132 | } | ||
133 | finish_wait(&iic_wait, &wait); | ||
134 | } else { | ||
135 | iic_pending = 0; | ||
136 | spin_unlock_irqrestore(&lock, flags); | ||
137 | } | ||
138 | } else { | ||
139 | udelay(100); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | |||
144 | static irqreturn_t iic_ite_handler(int this_irq, void *dev_id, | ||
145 | struct pt_regs *regs) | ||
146 | { | ||
147 | spin_lock(&lock); | ||
148 | iic_pending = 1; | ||
149 | spin_unlock(&lock); | ||
150 | |||
151 | wake_up_interruptible(&iic_wait); | ||
152 | |||
153 | return IRQ_HANDLED; | ||
154 | } | ||
155 | |||
156 | |||
157 | /* Lock the region of memory where I/O registers exist. Request our | ||
158 | * interrupt line and register its associated handler. | ||
159 | */ | ||
160 | static int iic_hw_resrc_init(void) | ||
161 | { | ||
162 | if (!request_region(gpi.iic_base, ITE_IIC_IO_SIZE, "i2c")) | ||
163 | return -ENODEV; | ||
164 | |||
165 | if (gpi.iic_irq <= 0) | ||
166 | return 0; | ||
167 | |||
168 | if (request_irq(gpi.iic_irq, iic_ite_handler, 0, "ITE IIC", 0) < 0) | ||
169 | gpi.iic_irq = 0; | ||
170 | else | ||
171 | enable_irq(gpi.iic_irq); | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | |||
177 | static void iic_ite_release(void) | ||
178 | { | ||
179 | if (gpi.iic_irq > 0) { | ||
180 | disable_irq(gpi.iic_irq); | ||
181 | free_irq(gpi.iic_irq, 0); | ||
182 | } | ||
183 | release_region(gpi.iic_base , 2); | ||
184 | } | ||
185 | |||
186 | /* ------------------------------------------------------------------------ | ||
187 | * Encapsulate the above functions in the correct operations structure. | ||
188 | * This is only done when more than one hardware adapter is supported. | ||
189 | */ | ||
190 | static struct i2c_algo_iic_data iic_ite_data = { | ||
191 | NULL, | ||
192 | iic_ite_setiic, | ||
193 | iic_ite_getiic, | ||
194 | iic_ite_getown, | ||
195 | iic_ite_getclock, | ||
196 | iic_ite_waitforpin, | ||
197 | 80, 80, 100, /* waits, timeout */ | ||
198 | }; | ||
199 | |||
200 | static struct i2c_adapter iic_ite_ops = { | ||
201 | .owner = THIS_MODULE, | ||
202 | .id = I2C_HW_I_IIC, | ||
203 | .algo_data = &iic_ite_data, | ||
204 | .dev = { | ||
205 | .name = "ITE IIC adapter", | ||
206 | }, | ||
207 | }; | ||
208 | |||
209 | /* Called when the module is loaded. This function starts the | ||
210 | * cascade of calls up through the hierarchy of i2c modules (i.e. up to the | ||
211 | * algorithm layer and into to the core layer) | ||
212 | */ | ||
213 | static int __init iic_ite_init(void) | ||
214 | { | ||
215 | |||
216 | struct iic_ite *piic = &gpi; | ||
217 | |||
218 | printk(KERN_INFO "Initialize ITE IIC adapter module\n"); | ||
219 | if (base == 0) | ||
220 | piic->iic_base = DEFAULT_BASE; | ||
221 | else | ||
222 | piic->iic_base = base; | ||
223 | |||
224 | if (irq == 0) | ||
225 | piic->iic_irq = DEFAULT_IRQ; | ||
226 | else | ||
227 | piic->iic_irq = irq; | ||
228 | |||
229 | if (clock == 0) | ||
230 | piic->iic_clock = DEFAULT_CLOCK; | ||
231 | else | ||
232 | piic->iic_clock = clock; | ||
233 | |||
234 | if (own == 0) | ||
235 | piic->iic_own = DEFAULT_OWN; | ||
236 | else | ||
237 | piic->iic_own = own; | ||
238 | |||
239 | iic_ite_data.data = (void *)piic; | ||
240 | init_waitqueue_head(&iic_wait); | ||
241 | spin_lock_init(&lock); | ||
242 | if (iic_hw_resrc_init() == 0) { | ||
243 | if (i2c_iic_add_bus(&iic_ite_ops) < 0) | ||
244 | return -ENODEV; | ||
245 | } else { | ||
246 | return -ENODEV; | ||
247 | } | ||
248 | printk(KERN_INFO " found device at %#x irq %d.\n", | ||
249 | piic->iic_base, piic->iic_irq); | ||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | |||
254 | static void iic_ite_exit(void) | ||
255 | { | ||
256 | i2c_iic_del_bus(&iic_ite_ops); | ||
257 | iic_ite_release(); | ||
258 | } | ||
259 | |||
260 | /* If modules is NOT defined when this file is compiled, then the MODULE_* | ||
261 | * macros will resolve to nothing | ||
262 | */ | ||
263 | MODULE_AUTHOR("MontaVista Software <www.mvista.com>"); | ||
264 | MODULE_DESCRIPTION("I2C-Bus adapter routines for ITE IIC bus adapter"); | ||
265 | MODULE_LICENSE("GPL"); | ||
266 | |||
267 | module_param(base, int, 0); | ||
268 | module_param(irq, int, 0); | ||
269 | module_param(clock, int, 0); | ||
270 | module_param(own, int, 0); | ||
271 | |||
272 | |||
273 | /* Called when module is loaded or when kernel is initialized. | ||
274 | * If MODULES is defined when this file is compiled, then this function will | ||
275 | * resolve to init_module (the function called when insmod is invoked for a | ||
276 | * module). Otherwise, this function is called early in the boot, when the | ||
277 | * kernel is intialized. Check out /include/init.h to see how this works. | ||
278 | */ | ||
279 | module_init(iic_ite_init); | ||
280 | |||
281 | /* Resolves to module_cleanup when MODULES is defined. */ | ||
282 | module_exit(iic_ite_exit); | ||
diff --git a/drivers/i2c/busses/i2c-ixp2000.c b/drivers/i2c/busses/i2c-ixp2000.c new file mode 100644 index 000000000000..21cd54d02302 --- /dev/null +++ b/drivers/i2c/busses/i2c-ixp2000.c | |||
@@ -0,0 +1,171 @@ | |||
1 | /* | ||
2 | * drivers/i2c/busses/i2c-ixp2000.c | ||
3 | * | ||
4 | * I2C adapter for IXP2000 systems using GPIOs for I2C bus | ||
5 | * | ||
6 | * Author: Deepak Saxena <dsaxena@plexity.net> | ||
7 | * Based on IXDP2400 code by: Naeem M. Afzal <naeem.m.afzal@intel.com> | ||
8 | * Made generic by: Jeff Daly <jeffrey.daly@intel.com> | ||
9 | * | ||
10 | * Copyright (c) 2003-2004 MontaVista Software Inc. | ||
11 | * | ||
12 | * This file is licensed under the terms of the GNU General Public | ||
13 | * License version 2. This program is licensed "as is" without any | ||
14 | * warranty of any kind, whether express or implied. | ||
15 | * | ||
16 | * From Jeff Daly: | ||
17 | * | ||
18 | * I2C adapter driver for Intel IXDP2xxx platforms. This should work for any | ||
19 | * IXP2000 platform if it uses the HW GPIO in the same manner. Basically, | ||
20 | * SDA and SCL GPIOs have external pullups. Setting the respective GPIO to | ||
21 | * an input will make the signal a '1' via the pullup. Setting them to | ||
22 | * outputs will pull them down. | ||
23 | * | ||
24 | * The GPIOs are open drain signals and are used as configuration strap inputs | ||
25 | * during power-up so there's generally a buffer on the board that needs to be | ||
26 | * 'enabled' to drive the GPIOs. | ||
27 | */ | ||
28 | |||
29 | #include <linux/config.h> | ||
30 | #ifdef CONFIG_I2C_DEBUG_BUS | ||
31 | #define DEBUG 1 | ||
32 | #endif | ||
33 | |||
34 | #include <linux/kernel.h> | ||
35 | #include <linux/init.h> | ||
36 | #include <linux/device.h> | ||
37 | #include <linux/module.h> | ||
38 | #include <linux/i2c.h> | ||
39 | #include <linux/i2c-algo-bit.h> | ||
40 | |||
41 | #include <asm/hardware.h> /* Pick up IXP42000-specific bits */ | ||
42 | |||
43 | static inline int ixp2000_scl_pin(void *data) | ||
44 | { | ||
45 | return ((struct ixp2000_i2c_pins*)data)->scl_pin; | ||
46 | } | ||
47 | |||
48 | static inline int ixp2000_sda_pin(void *data) | ||
49 | { | ||
50 | return ((struct ixp2000_i2c_pins*)data)->sda_pin; | ||
51 | } | ||
52 | |||
53 | |||
54 | static void ixp2000_bit_setscl(void *data, int val) | ||
55 | { | ||
56 | int i = 5000; | ||
57 | |||
58 | if (val) { | ||
59 | gpio_line_config(ixp2000_scl_pin(data), GPIO_IN); | ||
60 | while(!gpio_line_get(ixp2000_scl_pin(data)) && i--); | ||
61 | } else { | ||
62 | gpio_line_config(ixp2000_scl_pin(data), GPIO_OUT); | ||
63 | } | ||
64 | } | ||
65 | |||
66 | static void ixp2000_bit_setsda(void *data, int val) | ||
67 | { | ||
68 | if (val) { | ||
69 | gpio_line_config(ixp2000_sda_pin(data), GPIO_IN); | ||
70 | } else { | ||
71 | gpio_line_config(ixp2000_sda_pin(data), GPIO_OUT); | ||
72 | } | ||
73 | } | ||
74 | |||
75 | static int ixp2000_bit_getscl(void *data) | ||
76 | { | ||
77 | return gpio_line_get(ixp2000_scl_pin(data)); | ||
78 | } | ||
79 | |||
80 | static int ixp2000_bit_getsda(void *data) | ||
81 | { | ||
82 | return gpio_line_get(ixp2000_sda_pin(data)); | ||
83 | } | ||
84 | |||
85 | struct ixp2000_i2c_data { | ||
86 | struct ixp2000_i2c_pins *gpio_pins; | ||
87 | struct i2c_adapter adapter; | ||
88 | struct i2c_algo_bit_data algo_data; | ||
89 | }; | ||
90 | |||
91 | static int ixp2000_i2c_remove(struct device *dev) | ||
92 | { | ||
93 | struct platform_device *plat_dev = to_platform_device(dev); | ||
94 | struct ixp2000_i2c_data *drv_data = dev_get_drvdata(&plat_dev->dev); | ||
95 | |||
96 | dev_set_drvdata(&plat_dev->dev, NULL); | ||
97 | |||
98 | i2c_bit_del_bus(&drv_data->adapter); | ||
99 | |||
100 | kfree(drv_data); | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static int ixp2000_i2c_probe(struct device *dev) | ||
106 | { | ||
107 | int err; | ||
108 | struct platform_device *plat_dev = to_platform_device(dev); | ||
109 | struct ixp2000_i2c_pins *gpio = plat_dev->dev.platform_data; | ||
110 | struct ixp2000_i2c_data *drv_data = | ||
111 | kmalloc(sizeof(struct ixp2000_i2c_data), GFP_KERNEL); | ||
112 | |||
113 | if (!drv_data) | ||
114 | return -ENOMEM; | ||
115 | memzero(drv_data, sizeof(*drv_data)); | ||
116 | drv_data->gpio_pins = gpio; | ||
117 | |||
118 | drv_data->algo_data.data = gpio; | ||
119 | drv_data->algo_data.setsda = ixp2000_bit_setsda; | ||
120 | drv_data->algo_data.setscl = ixp2000_bit_setscl; | ||
121 | drv_data->algo_data.getsda = ixp2000_bit_getsda; | ||
122 | drv_data->algo_data.getscl = ixp2000_bit_getscl; | ||
123 | drv_data->algo_data.udelay = 6; | ||
124 | drv_data->algo_data.mdelay = 6; | ||
125 | drv_data->algo_data.timeout = 100; | ||
126 | |||
127 | drv_data->adapter.id = I2C_HW_B_IXP2000, | ||
128 | drv_data->adapter.algo_data = &drv_data->algo_data, | ||
129 | |||
130 | drv_data->adapter.dev.parent = &plat_dev->dev; | ||
131 | |||
132 | gpio_line_config(gpio->sda_pin, GPIO_IN); | ||
133 | gpio_line_config(gpio->scl_pin, GPIO_IN); | ||
134 | gpio_line_set(gpio->scl_pin, 0); | ||
135 | gpio_line_set(gpio->sda_pin, 0); | ||
136 | |||
137 | if ((err = i2c_bit_add_bus(&drv_data->adapter)) != 0) { | ||
138 | dev_err(dev, "Could not install, error %d\n", err); | ||
139 | kfree(drv_data); | ||
140 | return err; | ||
141 | } | ||
142 | |||
143 | dev_set_drvdata(&plat_dev->dev, drv_data); | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static struct device_driver ixp2000_i2c_driver = { | ||
149 | .name = "IXP2000-I2C", | ||
150 | .bus = &platform_bus_type, | ||
151 | .probe = ixp2000_i2c_probe, | ||
152 | .remove = ixp2000_i2c_remove, | ||
153 | }; | ||
154 | |||
155 | static int __init ixp2000_i2c_init(void) | ||
156 | { | ||
157 | return driver_register(&ixp2000_i2c_driver); | ||
158 | } | ||
159 | |||
160 | static void __exit ixp2000_i2c_exit(void) | ||
161 | { | ||
162 | driver_unregister(&ixp2000_i2c_driver); | ||
163 | } | ||
164 | |||
165 | module_init(ixp2000_i2c_init); | ||
166 | module_exit(ixp2000_i2c_exit); | ||
167 | |||
168 | MODULE_AUTHOR ("Deepak Saxena <dsaxena@plexity.net>"); | ||
169 | MODULE_DESCRIPTION("IXP2000 GPIO-based I2C bus driver"); | ||
170 | MODULE_LICENSE("GPL"); | ||
171 | |||
diff --git a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c new file mode 100644 index 000000000000..8c55eafc3a09 --- /dev/null +++ b/drivers/i2c/busses/i2c-ixp4xx.c | |||
@@ -0,0 +1,181 @@ | |||
1 | /* | ||
2 | * drivers/i2c/i2c-adap-ixp4xx.c | ||
3 | * | ||
4 | * Intel's IXP4xx XScale NPU chipsets (IXP420, 421, 422, 425) do not have | ||
5 | * an on board I2C controller but provide 16 GPIO pins that are often | ||
6 | * used to create an I2C bus. This driver provides an i2c_adapter | ||
7 | * interface that plugs in under algo_bit and drives the GPIO pins | ||
8 | * as instructed by the alogorithm driver. | ||
9 | * | ||
10 | * Author: Deepak Saxena <dsaxena@plexity.net> | ||
11 | * | ||
12 | * Copyright (c) 2003-2004 MontaVista Software Inc. | ||
13 | * | ||
14 | * This file is licensed under the terms of the GNU General Public | ||
15 | * License version 2. This program is licensed "as is" without any | ||
16 | * warranty of any kind, whether express or implied. | ||
17 | * | ||
18 | * NOTE: Since different platforms will use different GPIO pins for | ||
19 | * I2C, this driver uses an IXP4xx-specific platform_data | ||
20 | * pointer to pass the GPIO numbers to the driver. This | ||
21 | * allows us to support all the different IXP4xx platforms | ||
22 | * w/o having to put #ifdefs in this driver. | ||
23 | * | ||
24 | * See arch/arm/mach-ixp4xx/ixdp425.c for an example of building a | ||
25 | * device list and filling in the ixp4xx_i2c_pins data structure | ||
26 | * that is passed as the platform_data to this driver. | ||
27 | */ | ||
28 | |||
29 | #include <linux/config.h> | ||
30 | #ifdef CONFIG_I2C_DEBUG_BUS | ||
31 | #define DEBUG 1 | ||
32 | #endif | ||
33 | |||
34 | #include <linux/kernel.h> | ||
35 | #include <linux/init.h> | ||
36 | #include <linux/device.h> | ||
37 | #include <linux/module.h> | ||
38 | #include <linux/i2c.h> | ||
39 | #include <linux/i2c-algo-bit.h> | ||
40 | |||
41 | #include <asm/hardware.h> /* Pick up IXP4xx-specific bits */ | ||
42 | |||
43 | static inline int ixp4xx_scl_pin(void *data) | ||
44 | { | ||
45 | return ((struct ixp4xx_i2c_pins*)data)->scl_pin; | ||
46 | } | ||
47 | |||
48 | static inline int ixp4xx_sda_pin(void *data) | ||
49 | { | ||
50 | return ((struct ixp4xx_i2c_pins*)data)->sda_pin; | ||
51 | } | ||
52 | |||
53 | static void ixp4xx_bit_setscl(void *data, int val) | ||
54 | { | ||
55 | gpio_line_set(ixp4xx_scl_pin(data), 0); | ||
56 | gpio_line_config(ixp4xx_scl_pin(data), | ||
57 | val ? IXP4XX_GPIO_IN : IXP4XX_GPIO_OUT ); | ||
58 | } | ||
59 | |||
60 | static void ixp4xx_bit_setsda(void *data, int val) | ||
61 | { | ||
62 | gpio_line_set(ixp4xx_sda_pin(data), 0); | ||
63 | gpio_line_config(ixp4xx_sda_pin(data), | ||
64 | val ? IXP4XX_GPIO_IN : IXP4XX_GPIO_OUT ); | ||
65 | } | ||
66 | |||
67 | static int ixp4xx_bit_getscl(void *data) | ||
68 | { | ||
69 | int scl; | ||
70 | |||
71 | gpio_line_config(ixp4xx_scl_pin(data), IXP4XX_GPIO_IN ); | ||
72 | gpio_line_get(ixp4xx_scl_pin(data), &scl); | ||
73 | |||
74 | return scl; | ||
75 | } | ||
76 | |||
77 | static int ixp4xx_bit_getsda(void *data) | ||
78 | { | ||
79 | int sda; | ||
80 | |||
81 | gpio_line_config(ixp4xx_sda_pin(data), IXP4XX_GPIO_IN ); | ||
82 | gpio_line_get(ixp4xx_sda_pin(data), &sda); | ||
83 | |||
84 | return sda; | ||
85 | } | ||
86 | |||
87 | struct ixp4xx_i2c_data { | ||
88 | struct ixp4xx_i2c_pins *gpio_pins; | ||
89 | struct i2c_adapter adapter; | ||
90 | struct i2c_algo_bit_data algo_data; | ||
91 | }; | ||
92 | |||
93 | static int ixp4xx_i2c_remove(struct device *dev) | ||
94 | { | ||
95 | struct platform_device *plat_dev = to_platform_device(dev); | ||
96 | struct ixp4xx_i2c_data *drv_data = dev_get_drvdata(&plat_dev->dev); | ||
97 | |||
98 | dev_set_drvdata(&plat_dev->dev, NULL); | ||
99 | |||
100 | i2c_bit_del_bus(&drv_data->adapter); | ||
101 | |||
102 | kfree(drv_data); | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static int ixp4xx_i2c_probe(struct device *dev) | ||
108 | { | ||
109 | int err; | ||
110 | struct platform_device *plat_dev = to_platform_device(dev); | ||
111 | struct ixp4xx_i2c_pins *gpio = plat_dev->dev.platform_data; | ||
112 | struct ixp4xx_i2c_data *drv_data = | ||
113 | kmalloc(sizeof(struct ixp4xx_i2c_data), GFP_KERNEL); | ||
114 | |||
115 | if(!drv_data) | ||
116 | return -ENOMEM; | ||
117 | |||
118 | memzero(drv_data, sizeof(struct ixp4xx_i2c_data)); | ||
119 | drv_data->gpio_pins = gpio; | ||
120 | |||
121 | /* | ||
122 | * We could make a lot of these structures static, but | ||
123 | * certain platforms may have multiple GPIO-based I2C | ||
124 | * buses for various device domains, so we need per-device | ||
125 | * algo_data->data. | ||
126 | */ | ||
127 | drv_data->algo_data.data = gpio; | ||
128 | drv_data->algo_data.setsda = ixp4xx_bit_setsda; | ||
129 | drv_data->algo_data.setscl = ixp4xx_bit_setscl; | ||
130 | drv_data->algo_data.getsda = ixp4xx_bit_getsda; | ||
131 | drv_data->algo_data.getscl = ixp4xx_bit_getscl; | ||
132 | drv_data->algo_data.udelay = 10; | ||
133 | drv_data->algo_data.mdelay = 10; | ||
134 | drv_data->algo_data.timeout = 100; | ||
135 | |||
136 | drv_data->adapter.id = I2C_HW_B_IXP4XX; | ||
137 | drv_data->adapter.algo_data = &drv_data->algo_data; | ||
138 | |||
139 | drv_data->adapter.dev.parent = &plat_dev->dev; | ||
140 | |||
141 | gpio_line_config(gpio->scl_pin, IXP4XX_GPIO_IN); | ||
142 | gpio_line_config(gpio->sda_pin, IXP4XX_GPIO_IN); | ||
143 | gpio_line_set(gpio->scl_pin, 0); | ||
144 | gpio_line_set(gpio->sda_pin, 0); | ||
145 | |||
146 | if ((err = i2c_bit_add_bus(&drv_data->adapter) != 0)) { | ||
147 | printk(KERN_ERR "ERROR: Could not install %s\n", dev->bus_id); | ||
148 | |||
149 | kfree(drv_data); | ||
150 | return err; | ||
151 | } | ||
152 | |||
153 | dev_set_drvdata(&plat_dev->dev, drv_data); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static struct device_driver ixp4xx_i2c_driver = { | ||
159 | .name = "IXP4XX-I2C", | ||
160 | .bus = &platform_bus_type, | ||
161 | .probe = ixp4xx_i2c_probe, | ||
162 | .remove = ixp4xx_i2c_remove, | ||
163 | }; | ||
164 | |||
165 | static int __init ixp4xx_i2c_init(void) | ||
166 | { | ||
167 | return driver_register(&ixp4xx_i2c_driver); | ||
168 | } | ||
169 | |||
170 | static void __exit ixp4xx_i2c_exit(void) | ||
171 | { | ||
172 | driver_unregister(&ixp4xx_i2c_driver); | ||
173 | } | ||
174 | |||
175 | module_init(ixp4xx_i2c_init); | ||
176 | module_exit(ixp4xx_i2c_exit); | ||
177 | |||
178 | MODULE_DESCRIPTION("GPIO-based I2C adapter for IXP4xx systems"); | ||
179 | MODULE_LICENSE("GPL"); | ||
180 | MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>"); | ||
181 | |||
diff --git a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c new file mode 100644 index 000000000000..dd0d4c463146 --- /dev/null +++ b/drivers/i2c/busses/i2c-keywest.c | |||
@@ -0,0 +1,763 @@ | |||
1 | /* | ||
2 | i2c Support for Apple Keywest I2C Bus Controller | ||
3 | |||
4 | Copyright (c) 2001 Benjamin Herrenschmidt <benh@kernel.crashing.org> | ||
5 | |||
6 | Original work by | ||
7 | |||
8 | Copyright (c) 2000 Philip Edelbrock <phil@stimpy.netroedge.com> | ||
9 | |||
10 | This program is free software; you can redistribute it and/or modify | ||
11 | it under the terms of the GNU General Public License as published by | ||
12 | the Free Software Foundation; either version 2 of the License, or | ||
13 | (at your option) any later version. | ||
14 | |||
15 | This program is distributed in the hope that it will be useful, | ||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | GNU General Public License for more details. | ||
19 | |||
20 | You should have received a copy of the GNU General Public License | ||
21 | along with this program; if not, write to the Free Software | ||
22 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | |||
24 | Changes: | ||
25 | |||
26 | 2001/12/13 BenH New implementation | ||
27 | 2001/12/15 BenH Add support for "byte" and "quick" | ||
28 | transfers. Add i2c_xfer routine. | ||
29 | 2003/09/21 BenH Rework state machine with Paulus help | ||
30 | 2004/01/21 BenH Merge in Greg KH changes, polled mode is back | ||
31 | 2004/02/05 BenH Merge 64 bits fixes from the g5 ppc64 tree | ||
32 | |||
33 | My understanding of the various modes supported by keywest are: | ||
34 | |||
35 | - Dumb mode : not implemented, probably direct tweaking of lines | ||
36 | - Standard mode : simple i2c transaction of type | ||
37 | S Addr R/W A Data A Data ... T | ||
38 | - Standard sub mode : combined 8 bit subaddr write with data read | ||
39 | S Addr R/W A SubAddr A Data A Data ... T | ||
40 | - Combined mode : Subaddress and Data sequences appended with no stop | ||
41 | S Addr R/W A SubAddr S Addr R/W A Data A Data ... T | ||
42 | |||
43 | Currently, this driver uses only Standard mode for i2c xfer, and | ||
44 | smbus byte & quick transfers ; and uses StandardSub mode for | ||
45 | other smbus transfers instead of combined as we need that for the | ||
46 | sound driver to be happy | ||
47 | */ | ||
48 | |||
49 | #include <linux/config.h> | ||
50 | #include <linux/module.h> | ||
51 | #include <linux/kernel.h> | ||
52 | #include <linux/ioport.h> | ||
53 | #include <linux/pci.h> | ||
54 | #include <linux/types.h> | ||
55 | #include <linux/delay.h> | ||
56 | #include <linux/i2c.h> | ||
57 | #include <linux/init.h> | ||
58 | #include <linux/mm.h> | ||
59 | #include <linux/timer.h> | ||
60 | #include <linux/spinlock.h> | ||
61 | #include <linux/completion.h> | ||
62 | #include <linux/interrupt.h> | ||
63 | |||
64 | #include <asm/io.h> | ||
65 | #include <asm/prom.h> | ||
66 | #include <asm/machdep.h> | ||
67 | #include <asm/pmac_feature.h> | ||
68 | #include <asm/pmac_low_i2c.h> | ||
69 | |||
70 | #include "i2c-keywest.h" | ||
71 | |||
72 | #undef POLLED_MODE | ||
73 | |||
74 | /* Some debug macros */ | ||
75 | #define WRONG_STATE(name) do {\ | ||
76 | pr_debug("KW: wrong state. Got %s, state: %s (isr: %02x)\n", \ | ||
77 | name, __kw_state_names[iface->state], isr); \ | ||
78 | } while(0) | ||
79 | |||
80 | #ifdef DEBUG | ||
81 | static const char *__kw_state_names[] = { | ||
82 | "state_idle", | ||
83 | "state_addr", | ||
84 | "state_read", | ||
85 | "state_write", | ||
86 | "state_stop", | ||
87 | "state_dead" | ||
88 | }; | ||
89 | #endif /* DEBUG */ | ||
90 | |||
91 | static int probe; | ||
92 | |||
93 | MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>"); | ||
94 | MODULE_DESCRIPTION("I2C driver for Apple's Keywest"); | ||
95 | MODULE_LICENSE("GPL"); | ||
96 | module_param(probe, bool, 0); | ||
97 | |||
98 | #ifdef POLLED_MODE | ||
99 | /* Don't schedule, the g5 fan controller is too | ||
100 | * timing sensitive | ||
101 | */ | ||
102 | static u8 | ||
103 | wait_interrupt(struct keywest_iface* iface) | ||
104 | { | ||
105 | int i; | ||
106 | u8 isr; | ||
107 | |||
108 | for (i = 0; i < 200000; i++) { | ||
109 | isr = read_reg(reg_isr) & KW_I2C_IRQ_MASK; | ||
110 | if (isr != 0) | ||
111 | return isr; | ||
112 | udelay(10); | ||
113 | } | ||
114 | return isr; | ||
115 | } | ||
116 | #endif /* POLLED_MODE */ | ||
117 | |||
118 | static void | ||
119 | do_stop(struct keywest_iface* iface, int result) | ||
120 | { | ||
121 | write_reg(reg_control, KW_I2C_CTL_STOP); | ||
122 | iface->state = state_stop; | ||
123 | iface->result = result; | ||
124 | } | ||
125 | |||
126 | /* Main state machine for standard & standard sub mode */ | ||
127 | static void | ||
128 | handle_interrupt(struct keywest_iface *iface, u8 isr) | ||
129 | { | ||
130 | int ack; | ||
131 | |||
132 | if (isr == 0) { | ||
133 | if (iface->state != state_stop) { | ||
134 | pr_debug("KW: Timeout !\n"); | ||
135 | do_stop(iface, -EIO); | ||
136 | } | ||
137 | if (iface->state == state_stop) { | ||
138 | ack = read_reg(reg_status); | ||
139 | if (!(ack & KW_I2C_STAT_BUSY)) { | ||
140 | iface->state = state_idle; | ||
141 | write_reg(reg_ier, 0x00); | ||
142 | #ifndef POLLED_MODE | ||
143 | complete(&iface->complete); | ||
144 | #endif /* POLLED_MODE */ | ||
145 | } | ||
146 | } | ||
147 | return; | ||
148 | } | ||
149 | |||
150 | if (isr & KW_I2C_IRQ_ADDR) { | ||
151 | ack = read_reg(reg_status); | ||
152 | if (iface->state != state_addr) { | ||
153 | write_reg(reg_isr, KW_I2C_IRQ_ADDR); | ||
154 | WRONG_STATE("KW_I2C_IRQ_ADDR"); | ||
155 | do_stop(iface, -EIO); | ||
156 | return; | ||
157 | } | ||
158 | if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { | ||
159 | iface->state = state_stop; | ||
160 | iface->result = -ENODEV; | ||
161 | pr_debug("KW: NAK on address\n"); | ||
162 | } else { | ||
163 | /* Handle rw "quick" mode */ | ||
164 | if (iface->datalen == 0) { | ||
165 | do_stop(iface, 0); | ||
166 | } else if (iface->read_write == I2C_SMBUS_READ) { | ||
167 | iface->state = state_read; | ||
168 | if (iface->datalen > 1) | ||
169 | write_reg(reg_control, KW_I2C_CTL_AAK); | ||
170 | } else { | ||
171 | iface->state = state_write; | ||
172 | write_reg(reg_data, *(iface->data++)); | ||
173 | iface->datalen--; | ||
174 | } | ||
175 | } | ||
176 | write_reg(reg_isr, KW_I2C_IRQ_ADDR); | ||
177 | } | ||
178 | |||
179 | if (isr & KW_I2C_IRQ_DATA) { | ||
180 | if (iface->state == state_read) { | ||
181 | *(iface->data++) = read_reg(reg_data); | ||
182 | write_reg(reg_isr, KW_I2C_IRQ_DATA); | ||
183 | iface->datalen--; | ||
184 | if (iface->datalen == 0) | ||
185 | iface->state = state_stop; | ||
186 | else if (iface->datalen == 1) | ||
187 | write_reg(reg_control, 0); | ||
188 | } else if (iface->state == state_write) { | ||
189 | /* Check ack status */ | ||
190 | ack = read_reg(reg_status); | ||
191 | if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { | ||
192 | pr_debug("KW: nack on data write (%x): %x\n", | ||
193 | iface->data[-1], ack); | ||
194 | do_stop(iface, -EIO); | ||
195 | } else if (iface->datalen) { | ||
196 | write_reg(reg_data, *(iface->data++)); | ||
197 | iface->datalen--; | ||
198 | } else { | ||
199 | write_reg(reg_control, KW_I2C_CTL_STOP); | ||
200 | iface->state = state_stop; | ||
201 | iface->result = 0; | ||
202 | } | ||
203 | write_reg(reg_isr, KW_I2C_IRQ_DATA); | ||
204 | } else { | ||
205 | write_reg(reg_isr, KW_I2C_IRQ_DATA); | ||
206 | WRONG_STATE("KW_I2C_IRQ_DATA"); | ||
207 | if (iface->state != state_stop) | ||
208 | do_stop(iface, -EIO); | ||
209 | } | ||
210 | } | ||
211 | |||
212 | if (isr & KW_I2C_IRQ_STOP) { | ||
213 | write_reg(reg_isr, KW_I2C_IRQ_STOP); | ||
214 | if (iface->state != state_stop) { | ||
215 | WRONG_STATE("KW_I2C_IRQ_STOP"); | ||
216 | iface->result = -EIO; | ||
217 | } | ||
218 | iface->state = state_idle; | ||
219 | write_reg(reg_ier, 0x00); | ||
220 | #ifndef POLLED_MODE | ||
221 | complete(&iface->complete); | ||
222 | #endif /* POLLED_MODE */ | ||
223 | } | ||
224 | |||
225 | if (isr & KW_I2C_IRQ_START) | ||
226 | write_reg(reg_isr, KW_I2C_IRQ_START); | ||
227 | } | ||
228 | |||
229 | #ifndef POLLED_MODE | ||
230 | |||
231 | /* Interrupt handler */ | ||
232 | static irqreturn_t | ||
233 | keywest_irq(int irq, void *dev_id, struct pt_regs *regs) | ||
234 | { | ||
235 | struct keywest_iface *iface = (struct keywest_iface *)dev_id; | ||
236 | unsigned long flags; | ||
237 | |||
238 | spin_lock_irqsave(&iface->lock, flags); | ||
239 | del_timer(&iface->timeout_timer); | ||
240 | handle_interrupt(iface, read_reg(reg_isr)); | ||
241 | if (iface->state != state_idle) { | ||
242 | iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; | ||
243 | add_timer(&iface->timeout_timer); | ||
244 | } | ||
245 | spin_unlock_irqrestore(&iface->lock, flags); | ||
246 | return IRQ_HANDLED; | ||
247 | } | ||
248 | |||
249 | static void | ||
250 | keywest_timeout(unsigned long data) | ||
251 | { | ||
252 | struct keywest_iface *iface = (struct keywest_iface *)data; | ||
253 | unsigned long flags; | ||
254 | |||
255 | pr_debug("timeout !\n"); | ||
256 | spin_lock_irqsave(&iface->lock, flags); | ||
257 | handle_interrupt(iface, read_reg(reg_isr)); | ||
258 | if (iface->state != state_idle) { | ||
259 | iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; | ||
260 | add_timer(&iface->timeout_timer); | ||
261 | } | ||
262 | spin_unlock_irqrestore(&iface->lock, flags); | ||
263 | } | ||
264 | |||
265 | #endif /* POLLED_MODE */ | ||
266 | |||
267 | /* | ||
268 | * SMBUS-type transfer entrypoint | ||
269 | */ | ||
270 | static s32 | ||
271 | keywest_smbus_xfer( struct i2c_adapter* adap, | ||
272 | u16 addr, | ||
273 | unsigned short flags, | ||
274 | char read_write, | ||
275 | u8 command, | ||
276 | int size, | ||
277 | union i2c_smbus_data* data) | ||
278 | { | ||
279 | struct keywest_chan* chan = i2c_get_adapdata(adap); | ||
280 | struct keywest_iface* iface = chan->iface; | ||
281 | int len; | ||
282 | u8* buffer; | ||
283 | u16 cur_word; | ||
284 | int rc = 0; | ||
285 | |||
286 | if (iface->state == state_dead) | ||
287 | return -ENXIO; | ||
288 | |||
289 | /* Prepare datas & select mode */ | ||
290 | iface->cur_mode &= ~KW_I2C_MODE_MODE_MASK; | ||
291 | switch (size) { | ||
292 | case I2C_SMBUS_QUICK: | ||
293 | len = 0; | ||
294 | buffer = NULL; | ||
295 | iface->cur_mode |= KW_I2C_MODE_STANDARD; | ||
296 | break; | ||
297 | case I2C_SMBUS_BYTE: | ||
298 | len = 1; | ||
299 | buffer = &data->byte; | ||
300 | iface->cur_mode |= KW_I2C_MODE_STANDARD; | ||
301 | break; | ||
302 | case I2C_SMBUS_BYTE_DATA: | ||
303 | len = 1; | ||
304 | buffer = &data->byte; | ||
305 | iface->cur_mode |= KW_I2C_MODE_STANDARDSUB; | ||
306 | break; | ||
307 | case I2C_SMBUS_WORD_DATA: | ||
308 | len = 2; | ||
309 | cur_word = cpu_to_le16(data->word); | ||
310 | buffer = (u8 *)&cur_word; | ||
311 | iface->cur_mode |= KW_I2C_MODE_STANDARDSUB; | ||
312 | break; | ||
313 | case I2C_SMBUS_BLOCK_DATA: | ||
314 | len = data->block[0]; | ||
315 | buffer = &data->block[1]; | ||
316 | iface->cur_mode |= KW_I2C_MODE_STANDARDSUB; | ||
317 | break; | ||
318 | default: | ||
319 | return -1; | ||
320 | } | ||
321 | |||
322 | /* Turn a standardsub read into a combined mode access */ | ||
323 | if (read_write == I2C_SMBUS_READ | ||
324 | && (iface->cur_mode & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_STANDARDSUB) { | ||
325 | iface->cur_mode &= ~KW_I2C_MODE_MODE_MASK; | ||
326 | iface->cur_mode |= KW_I2C_MODE_COMBINED; | ||
327 | } | ||
328 | |||
329 | /* Original driver had this limitation */ | ||
330 | if (len > 32) | ||
331 | len = 32; | ||
332 | |||
333 | if (pmac_low_i2c_lock(iface->node)) | ||
334 | return -ENXIO; | ||
335 | |||
336 | pr_debug("chan: %d, addr: 0x%x, transfer len: %d, read: %d\n", | ||
337 | chan->chan_no, addr, len, read_write == I2C_SMBUS_READ); | ||
338 | |||
339 | iface->data = buffer; | ||
340 | iface->datalen = len; | ||
341 | iface->state = state_addr; | ||
342 | iface->result = 0; | ||
343 | iface->read_write = read_write; | ||
344 | |||
345 | /* Setup channel & clear pending irqs */ | ||
346 | write_reg(reg_isr, read_reg(reg_isr)); | ||
347 | write_reg(reg_mode, iface->cur_mode | (chan->chan_no << 4)); | ||
348 | write_reg(reg_status, 0); | ||
349 | |||
350 | /* Set up address and r/w bit */ | ||
351 | write_reg(reg_addr, | ||
352 | (addr << 1) | ((read_write == I2C_SMBUS_READ) ? 0x01 : 0x00)); | ||
353 | |||
354 | /* Set up the sub address */ | ||
355 | if ((iface->cur_mode & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_STANDARDSUB | ||
356 | || (iface->cur_mode & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_COMBINED) | ||
357 | write_reg(reg_subaddr, command); | ||
358 | |||
359 | #ifndef POLLED_MODE | ||
360 | /* Arm timeout */ | ||
361 | iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; | ||
362 | add_timer(&iface->timeout_timer); | ||
363 | #endif | ||
364 | |||
365 | /* Start sending address & enable interrupt*/ | ||
366 | write_reg(reg_control, KW_I2C_CTL_XADDR); | ||
367 | write_reg(reg_ier, KW_I2C_IRQ_MASK); | ||
368 | |||
369 | #ifdef POLLED_MODE | ||
370 | pr_debug("using polled mode...\n"); | ||
371 | /* State machine, to turn into an interrupt handler */ | ||
372 | while(iface->state != state_idle) { | ||
373 | unsigned long flags; | ||
374 | |||
375 | u8 isr = wait_interrupt(iface); | ||
376 | spin_lock_irqsave(&iface->lock, flags); | ||
377 | handle_interrupt(iface, isr); | ||
378 | spin_unlock_irqrestore(&iface->lock, flags); | ||
379 | } | ||
380 | #else /* POLLED_MODE */ | ||
381 | pr_debug("using interrupt mode...\n"); | ||
382 | wait_for_completion(&iface->complete); | ||
383 | #endif /* POLLED_MODE */ | ||
384 | |||
385 | rc = iface->result; | ||
386 | pr_debug("transfer done, result: %d\n", rc); | ||
387 | |||
388 | if (rc == 0 && size == I2C_SMBUS_WORD_DATA && read_write == I2C_SMBUS_READ) | ||
389 | data->word = le16_to_cpu(cur_word); | ||
390 | |||
391 | /* Release sem */ | ||
392 | pmac_low_i2c_unlock(iface->node); | ||
393 | |||
394 | return rc; | ||
395 | } | ||
396 | |||
397 | /* | ||
398 | * Generic i2c master transfer entrypoint | ||
399 | */ | ||
400 | static int | ||
401 | keywest_xfer( struct i2c_adapter *adap, | ||
402 | struct i2c_msg *msgs, | ||
403 | int num) | ||
404 | { | ||
405 | struct keywest_chan* chan = i2c_get_adapdata(adap); | ||
406 | struct keywest_iface* iface = chan->iface; | ||
407 | struct i2c_msg *pmsg; | ||
408 | int i, completed; | ||
409 | int rc = 0; | ||
410 | |||
411 | if (iface->state == state_dead) | ||
412 | return -ENXIO; | ||
413 | |||
414 | if (pmac_low_i2c_lock(iface->node)) | ||
415 | return -ENXIO; | ||
416 | |||
417 | /* Set adapter to standard mode */ | ||
418 | iface->cur_mode &= ~KW_I2C_MODE_MODE_MASK; | ||
419 | iface->cur_mode |= KW_I2C_MODE_STANDARD; | ||
420 | |||
421 | completed = 0; | ||
422 | for (i = 0; rc >= 0 && i < num;) { | ||
423 | u8 addr; | ||
424 | |||
425 | pmsg = &msgs[i++]; | ||
426 | addr = pmsg->addr; | ||
427 | if (pmsg->flags & I2C_M_TEN) { | ||
428 | printk(KERN_ERR "i2c-keywest: 10 bits addr not supported !\n"); | ||
429 | rc = -EINVAL; | ||
430 | break; | ||
431 | } | ||
432 | pr_debug("xfer: chan: %d, doing %s %d bytes to 0x%02x - %d of %d messages\n", | ||
433 | chan->chan_no, | ||
434 | pmsg->flags & I2C_M_RD ? "read" : "write", | ||
435 | pmsg->len, addr, i, num); | ||
436 | |||
437 | /* Setup channel & clear pending irqs */ | ||
438 | write_reg(reg_mode, iface->cur_mode | (chan->chan_no << 4)); | ||
439 | write_reg(reg_isr, read_reg(reg_isr)); | ||
440 | write_reg(reg_status, 0); | ||
441 | |||
442 | iface->data = pmsg->buf; | ||
443 | iface->datalen = pmsg->len; | ||
444 | iface->state = state_addr; | ||
445 | iface->result = 0; | ||
446 | if (pmsg->flags & I2C_M_RD) | ||
447 | iface->read_write = I2C_SMBUS_READ; | ||
448 | else | ||
449 | iface->read_write = I2C_SMBUS_WRITE; | ||
450 | |||
451 | /* Set up address and r/w bit */ | ||
452 | if (pmsg->flags & I2C_M_REV_DIR_ADDR) | ||
453 | addr ^= 1; | ||
454 | write_reg(reg_addr, | ||
455 | (addr << 1) | | ||
456 | ((iface->read_write == I2C_SMBUS_READ) ? 0x01 : 0x00)); | ||
457 | |||
458 | #ifndef POLLED_MODE | ||
459 | /* Arm timeout */ | ||
460 | iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; | ||
461 | add_timer(&iface->timeout_timer); | ||
462 | #endif | ||
463 | |||
464 | /* Start sending address & enable interrupt*/ | ||
465 | write_reg(reg_ier, KW_I2C_IRQ_MASK); | ||
466 | write_reg(reg_control, KW_I2C_CTL_XADDR); | ||
467 | |||
468 | #ifdef POLLED_MODE | ||
469 | pr_debug("using polled mode...\n"); | ||
470 | /* State machine, to turn into an interrupt handler */ | ||
471 | while(iface->state != state_idle) { | ||
472 | u8 isr = wait_interrupt(iface); | ||
473 | handle_interrupt(iface, isr); | ||
474 | } | ||
475 | #else /* POLLED_MODE */ | ||
476 | pr_debug("using interrupt mode...\n"); | ||
477 | wait_for_completion(&iface->complete); | ||
478 | #endif /* POLLED_MODE */ | ||
479 | |||
480 | rc = iface->result; | ||
481 | if (rc == 0) | ||
482 | completed++; | ||
483 | pr_debug("transfer done, result: %d\n", rc); | ||
484 | } | ||
485 | |||
486 | /* Release sem */ | ||
487 | pmac_low_i2c_unlock(iface->node); | ||
488 | |||
489 | return completed; | ||
490 | } | ||
491 | |||
492 | static u32 | ||
493 | keywest_func(struct i2c_adapter * adapter) | ||
494 | { | ||
495 | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | | ||
496 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | | ||
497 | I2C_FUNC_SMBUS_BLOCK_DATA; | ||
498 | } | ||
499 | |||
500 | /* For now, we only handle combined mode (smbus) */ | ||
501 | static struct i2c_algorithm keywest_algorithm = { | ||
502 | .name = "Keywest i2c", | ||
503 | .id = I2C_ALGO_SMBUS, | ||
504 | .smbus_xfer = keywest_smbus_xfer, | ||
505 | .master_xfer = keywest_xfer, | ||
506 | .functionality = keywest_func, | ||
507 | }; | ||
508 | |||
509 | |||
510 | static int | ||
511 | create_iface(struct device_node *np, struct device *dev) | ||
512 | { | ||
513 | unsigned long steps; | ||
514 | unsigned bsteps, tsize, i, nchan, addroffset; | ||
515 | struct keywest_iface* iface; | ||
516 | u32 *psteps, *prate; | ||
517 | int rc; | ||
518 | |||
519 | if (pmac_low_i2c_lock(np)) | ||
520 | return -ENODEV; | ||
521 | |||
522 | psteps = (u32 *)get_property(np, "AAPL,address-step", NULL); | ||
523 | steps = psteps ? (*psteps) : 0x10; | ||
524 | |||
525 | /* Hrm... maybe we can be smarter here */ | ||
526 | for (bsteps = 0; (steps & 0x01) == 0; bsteps++) | ||
527 | steps >>= 1; | ||
528 | |||
529 | if (np->parent->name[0] == 'u') { | ||
530 | nchan = 2; | ||
531 | addroffset = 3; | ||
532 | } else { | ||
533 | addroffset = 0; | ||
534 | nchan = 1; | ||
535 | } | ||
536 | |||
537 | tsize = sizeof(struct keywest_iface) + | ||
538 | (sizeof(struct keywest_chan) + 4) * nchan; | ||
539 | iface = (struct keywest_iface *) kmalloc(tsize, GFP_KERNEL); | ||
540 | if (iface == NULL) { | ||
541 | printk(KERN_ERR "i2c-keywest: can't allocate inteface !\n"); | ||
542 | pmac_low_i2c_unlock(np); | ||
543 | return -ENOMEM; | ||
544 | } | ||
545 | memset(iface, 0, tsize); | ||
546 | spin_lock_init(&iface->lock); | ||
547 | init_completion(&iface->complete); | ||
548 | iface->node = of_node_get(np); | ||
549 | iface->bsteps = bsteps; | ||
550 | iface->chan_count = nchan; | ||
551 | iface->state = state_idle; | ||
552 | iface->irq = np->intrs[0].line; | ||
553 | iface->channels = (struct keywest_chan *) | ||
554 | (((unsigned long)(iface + 1) + 3UL) & ~3UL); | ||
555 | iface->base = ioremap(np->addrs[0].address + addroffset, | ||
556 | np->addrs[0].size); | ||
557 | if (!iface->base) { | ||
558 | printk(KERN_ERR "i2c-keywest: can't map inteface !\n"); | ||
559 | kfree(iface); | ||
560 | pmac_low_i2c_unlock(np); | ||
561 | return -ENOMEM; | ||
562 | } | ||
563 | |||
564 | #ifndef POLLED_MODE | ||
565 | init_timer(&iface->timeout_timer); | ||
566 | iface->timeout_timer.function = keywest_timeout; | ||
567 | iface->timeout_timer.data = (unsigned long)iface; | ||
568 | #endif | ||
569 | |||
570 | /* Select interface rate */ | ||
571 | iface->cur_mode = KW_I2C_MODE_100KHZ; | ||
572 | prate = (u32 *)get_property(np, "AAPL,i2c-rate", NULL); | ||
573 | if (prate) switch(*prate) { | ||
574 | case 100: | ||
575 | iface->cur_mode = KW_I2C_MODE_100KHZ; | ||
576 | break; | ||
577 | case 50: | ||
578 | iface->cur_mode = KW_I2C_MODE_50KHZ; | ||
579 | break; | ||
580 | case 25: | ||
581 | iface->cur_mode = KW_I2C_MODE_25KHZ; | ||
582 | break; | ||
583 | default: | ||
584 | printk(KERN_WARNING "i2c-keywest: unknown rate %ldKhz, using 100KHz\n", | ||
585 | (long)*prate); | ||
586 | } | ||
587 | |||
588 | /* Select standard mode by default */ | ||
589 | iface->cur_mode |= KW_I2C_MODE_STANDARD; | ||
590 | |||
591 | /* Write mode */ | ||
592 | write_reg(reg_mode, iface->cur_mode); | ||
593 | |||
594 | /* Switch interrupts off & clear them*/ | ||
595 | write_reg(reg_ier, 0x00); | ||
596 | write_reg(reg_isr, KW_I2C_IRQ_MASK); | ||
597 | |||
598 | #ifndef POLLED_MODE | ||
599 | /* Request chip interrupt */ | ||
600 | rc = request_irq(iface->irq, keywest_irq, SA_INTERRUPT, "keywest i2c", iface); | ||
601 | if (rc) { | ||
602 | printk(KERN_ERR "i2c-keywest: can't get IRQ %d !\n", iface->irq); | ||
603 | iounmap(iface->base); | ||
604 | kfree(iface); | ||
605 | pmac_low_i2c_unlock(np); | ||
606 | return -ENODEV; | ||
607 | } | ||
608 | #endif /* POLLED_MODE */ | ||
609 | |||
610 | pmac_low_i2c_unlock(np); | ||
611 | dev_set_drvdata(dev, iface); | ||
612 | |||
613 | for (i=0; i<nchan; i++) { | ||
614 | struct keywest_chan* chan = &iface->channels[i]; | ||
615 | u8 addr; | ||
616 | |||
617 | sprintf(chan->adapter.name, "%s %d", np->parent->name, i); | ||
618 | chan->iface = iface; | ||
619 | chan->chan_no = i; | ||
620 | chan->adapter.id = I2C_ALGO_SMBUS; | ||
621 | chan->adapter.algo = &keywest_algorithm; | ||
622 | chan->adapter.algo_data = NULL; | ||
623 | chan->adapter.client_register = NULL; | ||
624 | chan->adapter.client_unregister = NULL; | ||
625 | i2c_set_adapdata(&chan->adapter, chan); | ||
626 | chan->adapter.dev.parent = dev; | ||
627 | |||
628 | rc = i2c_add_adapter(&chan->adapter); | ||
629 | if (rc) { | ||
630 | printk("i2c-keywest.c: Adapter %s registration failed\n", | ||
631 | chan->adapter.name); | ||
632 | i2c_set_adapdata(&chan->adapter, NULL); | ||
633 | } | ||
634 | if (probe) { | ||
635 | printk("Probe: "); | ||
636 | for (addr = 0x00; addr <= 0x7f; addr++) { | ||
637 | if (i2c_smbus_xfer(&chan->adapter,addr, | ||
638 | 0,0,0,I2C_SMBUS_QUICK,NULL) >= 0) | ||
639 | printk("%02x ", addr); | ||
640 | } | ||
641 | printk("\n"); | ||
642 | } | ||
643 | } | ||
644 | |||
645 | printk(KERN_INFO "Found KeyWest i2c on \"%s\", %d channel%s, stepping: %d bits\n", | ||
646 | np->parent->name, nchan, nchan > 1 ? "s" : "", bsteps); | ||
647 | |||
648 | return 0; | ||
649 | } | ||
650 | |||
651 | static int | ||
652 | dispose_iface(struct device *dev) | ||
653 | { | ||
654 | struct keywest_iface *iface = dev_get_drvdata(dev); | ||
655 | int i, rc; | ||
656 | |||
657 | /* Make sure we stop all activity */ | ||
658 | if (pmac_low_i2c_lock(iface->node)) | ||
659 | return -ENODEV; | ||
660 | |||
661 | #ifndef POLLED_MODE | ||
662 | spin_lock_irq(&iface->lock); | ||
663 | while (iface->state != state_idle) { | ||
664 | spin_unlock_irq(&iface->lock); | ||
665 | msleep(100); | ||
666 | spin_lock_irq(&iface->lock); | ||
667 | } | ||
668 | #endif /* POLLED_MODE */ | ||
669 | iface->state = state_dead; | ||
670 | #ifndef POLLED_MODE | ||
671 | spin_unlock_irq(&iface->lock); | ||
672 | free_irq(iface->irq, iface); | ||
673 | #endif /* POLLED_MODE */ | ||
674 | |||
675 | pmac_low_i2c_unlock(iface->node); | ||
676 | |||
677 | /* Release all channels */ | ||
678 | for (i=0; i<iface->chan_count; i++) { | ||
679 | struct keywest_chan* chan = &iface->channels[i]; | ||
680 | if (i2c_get_adapdata(&chan->adapter) == NULL) | ||
681 | continue; | ||
682 | rc = i2c_del_adapter(&chan->adapter); | ||
683 | i2c_set_adapdata(&chan->adapter, NULL); | ||
684 | /* We aren't that prepared to deal with this... */ | ||
685 | if (rc) | ||
686 | printk("i2c-keywest.c: i2c_del_adapter failed, that's bad !\n"); | ||
687 | } | ||
688 | iounmap(iface->base); | ||
689 | dev_set_drvdata(dev, NULL); | ||
690 | of_node_put(iface->node); | ||
691 | kfree(iface); | ||
692 | |||
693 | return 0; | ||
694 | } | ||
695 | |||
696 | static int | ||
697 | create_iface_macio(struct macio_dev* dev, const struct of_match *match) | ||
698 | { | ||
699 | return create_iface(dev->ofdev.node, &dev->ofdev.dev); | ||
700 | } | ||
701 | |||
702 | static int | ||
703 | dispose_iface_macio(struct macio_dev* dev) | ||
704 | { | ||
705 | return dispose_iface(&dev->ofdev.dev); | ||
706 | } | ||
707 | |||
708 | static int | ||
709 | create_iface_of_platform(struct of_device* dev, const struct of_match *match) | ||
710 | { | ||
711 | return create_iface(dev->node, &dev->dev); | ||
712 | } | ||
713 | |||
714 | static int | ||
715 | dispose_iface_of_platform(struct of_device* dev) | ||
716 | { | ||
717 | return dispose_iface(&dev->dev); | ||
718 | } | ||
719 | |||
720 | static struct of_match i2c_keywest_match[] = | ||
721 | { | ||
722 | { | ||
723 | .name = OF_ANY_MATCH, | ||
724 | .type = "i2c", | ||
725 | .compatible = "keywest" | ||
726 | }, | ||
727 | {}, | ||
728 | }; | ||
729 | |||
730 | static struct macio_driver i2c_keywest_macio_driver = | ||
731 | { | ||
732 | .name = "i2c-keywest", | ||
733 | .match_table = i2c_keywest_match, | ||
734 | .probe = create_iface_macio, | ||
735 | .remove = dispose_iface_macio | ||
736 | }; | ||
737 | |||
738 | static struct of_platform_driver i2c_keywest_of_platform_driver = | ||
739 | { | ||
740 | .name = "i2c-keywest", | ||
741 | .match_table = i2c_keywest_match, | ||
742 | .probe = create_iface_of_platform, | ||
743 | .remove = dispose_iface_of_platform | ||
744 | }; | ||
745 | |||
746 | static int __init | ||
747 | i2c_keywest_init(void) | ||
748 | { | ||
749 | of_register_driver(&i2c_keywest_of_platform_driver); | ||
750 | macio_register_driver(&i2c_keywest_macio_driver); | ||
751 | |||
752 | return 0; | ||
753 | } | ||
754 | |||
755 | static void __exit | ||
756 | i2c_keywest_cleanup(void) | ||
757 | { | ||
758 | of_unregister_driver(&i2c_keywest_of_platform_driver); | ||
759 | macio_unregister_driver(&i2c_keywest_macio_driver); | ||
760 | } | ||
761 | |||
762 | module_init(i2c_keywest_init); | ||
763 | module_exit(i2c_keywest_cleanup); | ||
diff --git a/drivers/i2c/busses/i2c-keywest.h b/drivers/i2c/busses/i2c-keywest.h new file mode 100644 index 000000000000..c5022e1ca6ff --- /dev/null +++ b/drivers/i2c/busses/i2c-keywest.h | |||
@@ -0,0 +1,108 @@ | |||
1 | #ifndef __I2C_KEYWEST_H__ | ||
2 | #define __I2C_KEYWEST_H__ | ||
3 | |||
4 | /* The Tumbler audio equalizer can be really slow sometimes */ | ||
5 | #define POLL_TIMEOUT (2*HZ) | ||
6 | |||
7 | /* Register indices */ | ||
8 | typedef enum { | ||
9 | reg_mode = 0, | ||
10 | reg_control, | ||
11 | reg_status, | ||
12 | reg_isr, | ||
13 | reg_ier, | ||
14 | reg_addr, | ||
15 | reg_subaddr, | ||
16 | reg_data | ||
17 | } reg_t; | ||
18 | |||
19 | |||
20 | /* Mode register */ | ||
21 | #define KW_I2C_MODE_100KHZ 0x00 | ||
22 | #define KW_I2C_MODE_50KHZ 0x01 | ||
23 | #define KW_I2C_MODE_25KHZ 0x02 | ||
24 | #define KW_I2C_MODE_DUMB 0x00 | ||
25 | #define KW_I2C_MODE_STANDARD 0x04 | ||
26 | #define KW_I2C_MODE_STANDARDSUB 0x08 | ||
27 | #define KW_I2C_MODE_COMBINED 0x0C | ||
28 | #define KW_I2C_MODE_MODE_MASK 0x0C | ||
29 | #define KW_I2C_MODE_CHAN_MASK 0xF0 | ||
30 | |||
31 | /* Control register */ | ||
32 | #define KW_I2C_CTL_AAK 0x01 | ||
33 | #define KW_I2C_CTL_XADDR 0x02 | ||
34 | #define KW_I2C_CTL_STOP 0x04 | ||
35 | #define KW_I2C_CTL_START 0x08 | ||
36 | |||
37 | /* Status register */ | ||
38 | #define KW_I2C_STAT_BUSY 0x01 | ||
39 | #define KW_I2C_STAT_LAST_AAK 0x02 | ||
40 | #define KW_I2C_STAT_LAST_RW 0x04 | ||
41 | #define KW_I2C_STAT_SDA 0x08 | ||
42 | #define KW_I2C_STAT_SCL 0x10 | ||
43 | |||
44 | /* IER & ISR registers */ | ||
45 | #define KW_I2C_IRQ_DATA 0x01 | ||
46 | #define KW_I2C_IRQ_ADDR 0x02 | ||
47 | #define KW_I2C_IRQ_STOP 0x04 | ||
48 | #define KW_I2C_IRQ_START 0x08 | ||
49 | #define KW_I2C_IRQ_MASK 0x0F | ||
50 | |||
51 | /* Physical interface */ | ||
52 | struct keywest_iface | ||
53 | { | ||
54 | struct device_node *node; | ||
55 | void __iomem * base; | ||
56 | unsigned bsteps; | ||
57 | int irq; | ||
58 | spinlock_t lock; | ||
59 | struct keywest_chan *channels; | ||
60 | unsigned chan_count; | ||
61 | u8 cur_mode; | ||
62 | char read_write; | ||
63 | u8 *data; | ||
64 | unsigned datalen; | ||
65 | int state; | ||
66 | int result; | ||
67 | struct timer_list timeout_timer; | ||
68 | struct completion complete; | ||
69 | }; | ||
70 | |||
71 | enum { | ||
72 | state_idle, | ||
73 | state_addr, | ||
74 | state_read, | ||
75 | state_write, | ||
76 | state_stop, | ||
77 | state_dead | ||
78 | }; | ||
79 | |||
80 | /* Channel on an interface */ | ||
81 | struct keywest_chan | ||
82 | { | ||
83 | struct i2c_adapter adapter; | ||
84 | struct keywest_iface* iface; | ||
85 | unsigned chan_no; | ||
86 | }; | ||
87 | |||
88 | /* Register access */ | ||
89 | |||
90 | static inline u8 __read_reg(struct keywest_iface *iface, reg_t reg) | ||
91 | { | ||
92 | return in_8(iface->base | ||
93 | + (((unsigned)reg) << iface->bsteps)); | ||
94 | } | ||
95 | |||
96 | static inline void __write_reg(struct keywest_iface *iface, reg_t reg, u8 val) | ||
97 | { | ||
98 | out_8(iface->base | ||
99 | + (((unsigned)reg) << iface->bsteps), val); | ||
100 | (void)__read_reg(iface, reg_subaddr); | ||
101 | } | ||
102 | |||
103 | #define write_reg(reg, val) __write_reg(iface, reg, val) | ||
104 | #define read_reg(reg) __read_reg(iface, reg) | ||
105 | |||
106 | |||
107 | |||
108 | #endif /* __I2C_KEYWEST_H__ */ | ||
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c new file mode 100644 index 000000000000..75b8d867dae1 --- /dev/null +++ b/drivers/i2c/busses/i2c-mpc.c | |||
@@ -0,0 +1,496 @@ | |||
1 | /* | ||
2 | * (C) Copyright 2003-2004 | ||
3 | * Humboldt Solutions Ltd, adrian@humboldt.co.uk. | ||
4 | |||
5 | * This is a combined i2c adapter and algorithm driver for the | ||
6 | * MPC107/Tsi107 PowerPC northbridge and processors that include | ||
7 | * the same I2C unit (8240, 8245, 85xx). | ||
8 | * | ||
9 | * Release 0.8 | ||
10 | * | ||
11 | * This file is licensed under the terms of the GNU General Public | ||
12 | * License version 2. This program is licensed "as is" without any | ||
13 | * warranty of any kind, whether express or implied. | ||
14 | */ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/pci.h> | ||
22 | #include <asm/io.h> | ||
23 | #ifdef CONFIG_FSL_OCP | ||
24 | #include <asm/ocp.h> | ||
25 | #define FSL_I2C_DEV_SEPARATE_DFSRR FS_I2C_SEPARATE_DFSRR | ||
26 | #define FSL_I2C_DEV_CLOCK_5200 FS_I2C_CLOCK_5200 | ||
27 | #else | ||
28 | #include <linux/fsl_devices.h> | ||
29 | #endif | ||
30 | #include <linux/i2c.h> | ||
31 | #include <linux/interrupt.h> | ||
32 | #include <linux/delay.h> | ||
33 | |||
34 | #define MPC_I2C_ADDR 0x00 | ||
35 | #define MPC_I2C_FDR 0x04 | ||
36 | #define MPC_I2C_CR 0x08 | ||
37 | #define MPC_I2C_SR 0x0c | ||
38 | #define MPC_I2C_DR 0x10 | ||
39 | #define MPC_I2C_DFSRR 0x14 | ||
40 | #define MPC_I2C_REGION 0x20 | ||
41 | |||
42 | #define CCR_MEN 0x80 | ||
43 | #define CCR_MIEN 0x40 | ||
44 | #define CCR_MSTA 0x20 | ||
45 | #define CCR_MTX 0x10 | ||
46 | #define CCR_TXAK 0x08 | ||
47 | #define CCR_RSTA 0x04 | ||
48 | |||
49 | #define CSR_MCF 0x80 | ||
50 | #define CSR_MAAS 0x40 | ||
51 | #define CSR_MBB 0x20 | ||
52 | #define CSR_MAL 0x10 | ||
53 | #define CSR_SRW 0x04 | ||
54 | #define CSR_MIF 0x02 | ||
55 | #define CSR_RXAK 0x01 | ||
56 | |||
57 | struct mpc_i2c { | ||
58 | char *base; | ||
59 | u32 interrupt; | ||
60 | wait_queue_head_t queue; | ||
61 | struct i2c_adapter adap; | ||
62 | int irq; | ||
63 | u32 flags; | ||
64 | }; | ||
65 | |||
66 | static __inline__ void writeccr(struct mpc_i2c *i2c, u32 x) | ||
67 | { | ||
68 | writeb(x, i2c->base + MPC_I2C_CR); | ||
69 | } | ||
70 | |||
71 | static irqreturn_t mpc_i2c_isr(int irq, void *dev_id, struct pt_regs *regs) | ||
72 | { | ||
73 | struct mpc_i2c *i2c = dev_id; | ||
74 | if (readb(i2c->base + MPC_I2C_SR) & CSR_MIF) { | ||
75 | /* Read again to allow register to stabilise */ | ||
76 | i2c->interrupt = readb(i2c->base + MPC_I2C_SR); | ||
77 | writeb(0, i2c->base + MPC_I2C_SR); | ||
78 | wake_up_interruptible(&i2c->queue); | ||
79 | } | ||
80 | return IRQ_HANDLED; | ||
81 | } | ||
82 | |||
83 | static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing) | ||
84 | { | ||
85 | unsigned long orig_jiffies = jiffies; | ||
86 | u32 x; | ||
87 | int result = 0; | ||
88 | |||
89 | if (i2c->irq == 0) | ||
90 | { | ||
91 | while (!(readb(i2c->base + MPC_I2C_SR) & CSR_MIF)) { | ||
92 | schedule(); | ||
93 | if (time_after(jiffies, orig_jiffies + timeout)) { | ||
94 | pr_debug("I2C: timeout\n"); | ||
95 | result = -EIO; | ||
96 | break; | ||
97 | } | ||
98 | } | ||
99 | x = readb(i2c->base + MPC_I2C_SR); | ||
100 | writeb(0, i2c->base + MPC_I2C_SR); | ||
101 | } else { | ||
102 | /* Interrupt mode */ | ||
103 | result = wait_event_interruptible_timeout(i2c->queue, | ||
104 | (i2c->interrupt & CSR_MIF), timeout * HZ); | ||
105 | |||
106 | if (unlikely(result < 0)) | ||
107 | pr_debug("I2C: wait interrupted\n"); | ||
108 | else if (unlikely(!(i2c->interrupt & CSR_MIF))) { | ||
109 | pr_debug("I2C: wait timeout\n"); | ||
110 | result = -ETIMEDOUT; | ||
111 | } | ||
112 | |||
113 | x = i2c->interrupt; | ||
114 | i2c->interrupt = 0; | ||
115 | } | ||
116 | |||
117 | if (result < 0) | ||
118 | return result; | ||
119 | |||
120 | if (!(x & CSR_MCF)) { | ||
121 | pr_debug("I2C: unfinished\n"); | ||
122 | return -EIO; | ||
123 | } | ||
124 | |||
125 | if (x & CSR_MAL) { | ||
126 | pr_debug("I2C: MAL\n"); | ||
127 | return -EIO; | ||
128 | } | ||
129 | |||
130 | if (writing && (x & CSR_RXAK)) { | ||
131 | pr_debug("I2C: No RXAK\n"); | ||
132 | /* generate stop */ | ||
133 | writeccr(i2c, CCR_MEN); | ||
134 | return -EIO; | ||
135 | } | ||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static void mpc_i2c_setclock(struct mpc_i2c *i2c) | ||
140 | { | ||
141 | /* Set clock and filters */ | ||
142 | if (i2c->flags & FSL_I2C_DEV_SEPARATE_DFSRR) { | ||
143 | writeb(0x31, i2c->base + MPC_I2C_FDR); | ||
144 | writeb(0x10, i2c->base + MPC_I2C_DFSRR); | ||
145 | } else if (i2c->flags & FSL_I2C_DEV_CLOCK_5200) | ||
146 | writeb(0x3f, i2c->base + MPC_I2C_FDR); | ||
147 | else | ||
148 | writel(0x1031, i2c->base + MPC_I2C_FDR); | ||
149 | } | ||
150 | |||
151 | static void mpc_i2c_start(struct mpc_i2c *i2c) | ||
152 | { | ||
153 | /* Clear arbitration */ | ||
154 | writeb(0, i2c->base + MPC_I2C_SR); | ||
155 | /* Start with MEN */ | ||
156 | writeccr(i2c, CCR_MEN); | ||
157 | } | ||
158 | |||
159 | static void mpc_i2c_stop(struct mpc_i2c *i2c) | ||
160 | { | ||
161 | writeccr(i2c, CCR_MEN); | ||
162 | } | ||
163 | |||
164 | static int mpc_write(struct mpc_i2c *i2c, int target, | ||
165 | const u8 * data, int length, int restart) | ||
166 | { | ||
167 | int i; | ||
168 | unsigned timeout = i2c->adap.timeout; | ||
169 | u32 flags = restart ? CCR_RSTA : 0; | ||
170 | |||
171 | /* Start with MEN */ | ||
172 | if (!restart) | ||
173 | writeccr(i2c, CCR_MEN); | ||
174 | /* Start as master */ | ||
175 | writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags); | ||
176 | /* Write target byte */ | ||
177 | writeb((target << 1), i2c->base + MPC_I2C_DR); | ||
178 | |||
179 | if (i2c_wait(i2c, timeout, 1) < 0) | ||
180 | return -1; | ||
181 | |||
182 | for (i = 0; i < length; i++) { | ||
183 | /* Write data byte */ | ||
184 | writeb(data[i], i2c->base + MPC_I2C_DR); | ||
185 | |||
186 | if (i2c_wait(i2c, timeout, 1) < 0) | ||
187 | return -1; | ||
188 | } | ||
189 | |||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static int mpc_read(struct mpc_i2c *i2c, int target, | ||
194 | u8 * data, int length, int restart) | ||
195 | { | ||
196 | unsigned timeout = i2c->adap.timeout; | ||
197 | int i; | ||
198 | u32 flags = restart ? CCR_RSTA : 0; | ||
199 | |||
200 | /* Start with MEN */ | ||
201 | if (!restart) | ||
202 | writeccr(i2c, CCR_MEN); | ||
203 | /* Switch to read - restart */ | ||
204 | writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags); | ||
205 | /* Write target address byte - this time with the read flag set */ | ||
206 | writeb((target << 1) | 1, i2c->base + MPC_I2C_DR); | ||
207 | |||
208 | if (i2c_wait(i2c, timeout, 1) < 0) | ||
209 | return -1; | ||
210 | |||
211 | if (length) { | ||
212 | if (length == 1) | ||
213 | writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK); | ||
214 | else | ||
215 | writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA); | ||
216 | /* Dummy read */ | ||
217 | readb(i2c->base + MPC_I2C_DR); | ||
218 | } | ||
219 | |||
220 | for (i = 0; i < length; i++) { | ||
221 | if (i2c_wait(i2c, timeout, 0) < 0) | ||
222 | return -1; | ||
223 | |||
224 | /* Generate txack on next to last byte */ | ||
225 | if (i == length - 2) | ||
226 | writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK); | ||
227 | /* Generate stop on last byte */ | ||
228 | if (i == length - 1) | ||
229 | writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_TXAK); | ||
230 | data[i] = readb(i2c->base + MPC_I2C_DR); | ||
231 | } | ||
232 | |||
233 | return length; | ||
234 | } | ||
235 | |||
236 | static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) | ||
237 | { | ||
238 | struct i2c_msg *pmsg; | ||
239 | int i; | ||
240 | int ret = 0; | ||
241 | unsigned long orig_jiffies = jiffies; | ||
242 | struct mpc_i2c *i2c = i2c_get_adapdata(adap); | ||
243 | |||
244 | mpc_i2c_start(i2c); | ||
245 | |||
246 | /* Allow bus up to 1s to become not busy */ | ||
247 | while (readb(i2c->base + MPC_I2C_SR) & CSR_MBB) { | ||
248 | if (signal_pending(current)) { | ||
249 | pr_debug("I2C: Interrupted\n"); | ||
250 | return -EINTR; | ||
251 | } | ||
252 | if (time_after(jiffies, orig_jiffies + HZ)) { | ||
253 | pr_debug("I2C: timeout\n"); | ||
254 | return -EIO; | ||
255 | } | ||
256 | schedule(); | ||
257 | } | ||
258 | |||
259 | for (i = 0; ret >= 0 && i < num; i++) { | ||
260 | pmsg = &msgs[i]; | ||
261 | pr_debug("Doing %s %d bytes to 0x%02x - %d of %d messages\n", | ||
262 | pmsg->flags & I2C_M_RD ? "read" : "write", | ||
263 | pmsg->len, pmsg->addr, i + 1, num); | ||
264 | if (pmsg->flags & I2C_M_RD) | ||
265 | ret = | ||
266 | mpc_read(i2c, pmsg->addr, pmsg->buf, pmsg->len, i); | ||
267 | else | ||
268 | ret = | ||
269 | mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, i); | ||
270 | } | ||
271 | mpc_i2c_stop(i2c); | ||
272 | return (ret < 0) ? ret : num; | ||
273 | } | ||
274 | |||
275 | static u32 mpc_functionality(struct i2c_adapter *adap) | ||
276 | { | ||
277 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | ||
278 | } | ||
279 | |||
280 | static struct i2c_algorithm mpc_algo = { | ||
281 | .name = "MPC algorithm", | ||
282 | .id = I2C_ALGO_MPC107, | ||
283 | .master_xfer = mpc_xfer, | ||
284 | .functionality = mpc_functionality, | ||
285 | }; | ||
286 | |||
287 | static struct i2c_adapter mpc_ops = { | ||
288 | .owner = THIS_MODULE, | ||
289 | .name = "MPC adapter", | ||
290 | .id = I2C_ALGO_MPC107 | I2C_HW_MPC107, | ||
291 | .algo = &mpc_algo, | ||
292 | .class = I2C_CLASS_HWMON, | ||
293 | .timeout = 1, | ||
294 | .retries = 1 | ||
295 | }; | ||
296 | |||
297 | #ifdef CONFIG_FSL_OCP | ||
298 | static int __devinit mpc_i2c_probe(struct ocp_device *ocp) | ||
299 | { | ||
300 | int result = 0; | ||
301 | struct mpc_i2c *i2c; | ||
302 | |||
303 | if (!(i2c = kmalloc(sizeof(*i2c), GFP_KERNEL))) { | ||
304 | return -ENOMEM; | ||
305 | } | ||
306 | memset(i2c, 0, sizeof(*i2c)); | ||
307 | |||
308 | i2c->irq = ocp->def->irq; | ||
309 | i2c->flags = ((struct ocp_fs_i2c_data *)ocp->def->additions)->flags; | ||
310 | init_waitqueue_head(&i2c->queue); | ||
311 | |||
312 | if (!request_mem_region(ocp->def->paddr, MPC_I2C_REGION, "i2c-mpc")) { | ||
313 | printk(KERN_ERR "i2c-mpc - resource unavailable\n"); | ||
314 | return -ENODEV; | ||
315 | } | ||
316 | |||
317 | i2c->base = ioremap(ocp->def->paddr, MPC_I2C_REGION); | ||
318 | |||
319 | if (!i2c->base) { | ||
320 | printk(KERN_ERR "i2c-mpc - failed to map controller\n"); | ||
321 | result = -ENOMEM; | ||
322 | goto fail_map; | ||
323 | } | ||
324 | |||
325 | if (i2c->irq != OCP_IRQ_NA) | ||
326 | { | ||
327 | if ((result = request_irq(ocp->def->irq, mpc_i2c_isr, | ||
328 | 0, "i2c-mpc", i2c)) < 0) { | ||
329 | printk(KERN_ERR | ||
330 | "i2c-mpc - failed to attach interrupt\n"); | ||
331 | goto fail_irq; | ||
332 | } | ||
333 | } else | ||
334 | i2c->irq = 0; | ||
335 | |||
336 | i2c->adap = mpc_ops; | ||
337 | i2c_set_adapdata(&i2c->adap, i2c); | ||
338 | |||
339 | if ((result = i2c_add_adapter(&i2c->adap)) < 0) { | ||
340 | printk(KERN_ERR "i2c-mpc - failed to add adapter\n"); | ||
341 | goto fail_add; | ||
342 | } | ||
343 | |||
344 | mpc_i2c_setclock(i2c); | ||
345 | ocp_set_drvdata(ocp, i2c); | ||
346 | return result; | ||
347 | |||
348 | fail_add: | ||
349 | if (ocp->def->irq != OCP_IRQ_NA) | ||
350 | free_irq(ocp->def->irq, 0); | ||
351 | fail_irq: | ||
352 | iounmap(i2c->base); | ||
353 | fail_map: | ||
354 | release_mem_region(ocp->def->paddr, MPC_I2C_REGION); | ||
355 | kfree(i2c); | ||
356 | return result; | ||
357 | } | ||
358 | static void __devexit mpc_i2c_remove(struct ocp_device *ocp) | ||
359 | { | ||
360 | struct mpc_i2c *i2c = ocp_get_drvdata(ocp); | ||
361 | ocp_set_drvdata(ocp, NULL); | ||
362 | i2c_del_adapter(&i2c->adap); | ||
363 | |||
364 | if (ocp->def->irq != OCP_IRQ_NA) | ||
365 | free_irq(i2c->irq, i2c); | ||
366 | iounmap(i2c->base); | ||
367 | release_mem_region(ocp->def->paddr, MPC_I2C_REGION); | ||
368 | kfree(i2c); | ||
369 | } | ||
370 | |||
371 | static struct ocp_device_id mpc_iic_ids[] __devinitdata = { | ||
372 | {.vendor = OCP_VENDOR_FREESCALE,.function = OCP_FUNC_IIC}, | ||
373 | {.vendor = OCP_VENDOR_INVALID} | ||
374 | }; | ||
375 | |||
376 | MODULE_DEVICE_TABLE(ocp, mpc_iic_ids); | ||
377 | |||
378 | static struct ocp_driver mpc_iic_driver = { | ||
379 | .name = "iic", | ||
380 | .id_table = mpc_iic_ids, | ||
381 | .probe = mpc_i2c_probe, | ||
382 | .remove = __devexit_p(mpc_i2c_remove) | ||
383 | }; | ||
384 | |||
385 | static int __init iic_init(void) | ||
386 | { | ||
387 | return ocp_register_driver(&mpc_iic_driver); | ||
388 | } | ||
389 | |||
390 | static void __exit iic_exit(void) | ||
391 | { | ||
392 | ocp_unregister_driver(&mpc_iic_driver); | ||
393 | } | ||
394 | |||
395 | module_init(iic_init); | ||
396 | module_exit(iic_exit); | ||
397 | #else | ||
398 | static int fsl_i2c_probe(struct device *device) | ||
399 | { | ||
400 | int result = 0; | ||
401 | struct mpc_i2c *i2c; | ||
402 | struct platform_device *pdev = to_platform_device(device); | ||
403 | struct fsl_i2c_platform_data *pdata; | ||
404 | struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
405 | |||
406 | pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data; | ||
407 | |||
408 | if (!(i2c = kmalloc(sizeof(*i2c), GFP_KERNEL))) { | ||
409 | return -ENOMEM; | ||
410 | } | ||
411 | memset(i2c, 0, sizeof(*i2c)); | ||
412 | |||
413 | i2c->irq = platform_get_irq(pdev, 0); | ||
414 | i2c->flags = pdata->device_flags; | ||
415 | init_waitqueue_head(&i2c->queue); | ||
416 | |||
417 | i2c->base = ioremap((phys_addr_t)r->start, MPC_I2C_REGION); | ||
418 | |||
419 | if (!i2c->base) { | ||
420 | printk(KERN_ERR "i2c-mpc - failed to map controller\n"); | ||
421 | result = -ENOMEM; | ||
422 | goto fail_map; | ||
423 | } | ||
424 | |||
425 | if (i2c->irq != 0) | ||
426 | if ((result = request_irq(i2c->irq, mpc_i2c_isr, | ||
427 | 0, "fsl-i2c", i2c)) < 0) { | ||
428 | printk(KERN_ERR | ||
429 | "i2c-mpc - failed to attach interrupt\n"); | ||
430 | goto fail_irq; | ||
431 | } | ||
432 | |||
433 | i2c->adap = mpc_ops; | ||
434 | i2c_set_adapdata(&i2c->adap, i2c); | ||
435 | i2c->adap.dev.parent = &pdev->dev; | ||
436 | if ((result = i2c_add_adapter(&i2c->adap)) < 0) { | ||
437 | printk(KERN_ERR "i2c-mpc - failed to add adapter\n"); | ||
438 | goto fail_add; | ||
439 | } | ||
440 | |||
441 | mpc_i2c_setclock(i2c); | ||
442 | dev_set_drvdata(device, i2c); | ||
443 | return result; | ||
444 | |||
445 | fail_add: | ||
446 | if (i2c->irq != 0) | ||
447 | free_irq(i2c->irq, 0); | ||
448 | fail_irq: | ||
449 | iounmap(i2c->base); | ||
450 | fail_map: | ||
451 | kfree(i2c); | ||
452 | return result; | ||
453 | }; | ||
454 | |||
455 | static int fsl_i2c_remove(struct device *device) | ||
456 | { | ||
457 | struct mpc_i2c *i2c = dev_get_drvdata(device); | ||
458 | |||
459 | dev_set_drvdata(device, NULL); | ||
460 | i2c_del_adapter(&i2c->adap); | ||
461 | |||
462 | if (i2c->irq != 0) | ||
463 | free_irq(i2c->irq, i2c); | ||
464 | |||
465 | iounmap(i2c->base); | ||
466 | kfree(i2c); | ||
467 | return 0; | ||
468 | }; | ||
469 | |||
470 | /* Structure for a device driver */ | ||
471 | static struct device_driver fsl_i2c_driver = { | ||
472 | .name = "fsl-i2c", | ||
473 | .bus = &platform_bus_type, | ||
474 | .probe = fsl_i2c_probe, | ||
475 | .remove = fsl_i2c_remove, | ||
476 | }; | ||
477 | |||
478 | static int __init fsl_i2c_init(void) | ||
479 | { | ||
480 | return driver_register(&fsl_i2c_driver); | ||
481 | } | ||
482 | |||
483 | static void __exit fsl_i2c_exit(void) | ||
484 | { | ||
485 | driver_unregister(&fsl_i2c_driver); | ||
486 | } | ||
487 | |||
488 | module_init(fsl_i2c_init); | ||
489 | module_exit(fsl_i2c_exit); | ||
490 | |||
491 | #endif /* CONFIG_FSL_OCP */ | ||
492 | |||
493 | MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>"); | ||
494 | MODULE_DESCRIPTION | ||
495 | ("I2C-Bus adapter for MPC107 bridge and MPC824x/85xx/52xx processors"); | ||
496 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c new file mode 100644 index 000000000000..5b852782d2f5 --- /dev/null +++ b/drivers/i2c/busses/i2c-mv64xxx.c | |||
@@ -0,0 +1,598 @@ | |||
1 | /* | ||
2 | * drivers/i2c/busses/i2c-mv64xxx.c | ||
3 | * | ||
4 | * Driver for the i2c controller on the Marvell line of host bridges for MIPS | ||
5 | * and PPC (e.g, gt642[46]0, mv643[46]0, mv644[46]0). | ||
6 | * | ||
7 | * Author: Mark A. Greer <mgreer@mvista.com> | ||
8 | * | ||
9 | * 2005 (c) MontaVista, Software, Inc. This file is licensed under | ||
10 | * the terms of the GNU General Public License version 2. This program | ||
11 | * is licensed "as is" without any warranty of any kind, whether express | ||
12 | * or implied. | ||
13 | */ | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/spinlock.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/mv643xx.h> | ||
20 | #include <asm/io.h> | ||
21 | |||
22 | /* Register defines */ | ||
23 | #define MV64XXX_I2C_REG_SLAVE_ADDR 0x00 | ||
24 | #define MV64XXX_I2C_REG_DATA 0x04 | ||
25 | #define MV64XXX_I2C_REG_CONTROL 0x08 | ||
26 | #define MV64XXX_I2C_REG_STATUS 0x0c | ||
27 | #define MV64XXX_I2C_REG_BAUD 0x0c | ||
28 | #define MV64XXX_I2C_REG_EXT_SLAVE_ADDR 0x10 | ||
29 | #define MV64XXX_I2C_REG_SOFT_RESET 0x1c | ||
30 | |||
31 | #define MV64XXX_I2C_REG_CONTROL_ACK 0x00000004 | ||
32 | #define MV64XXX_I2C_REG_CONTROL_IFLG 0x00000008 | ||
33 | #define MV64XXX_I2C_REG_CONTROL_STOP 0x00000010 | ||
34 | #define MV64XXX_I2C_REG_CONTROL_START 0x00000020 | ||
35 | #define MV64XXX_I2C_REG_CONTROL_TWSIEN 0x00000040 | ||
36 | #define MV64XXX_I2C_REG_CONTROL_INTEN 0x00000080 | ||
37 | |||
38 | /* Ctlr status values */ | ||
39 | #define MV64XXX_I2C_STATUS_BUS_ERR 0x00 | ||
40 | #define MV64XXX_I2C_STATUS_MAST_START 0x08 | ||
41 | #define MV64XXX_I2C_STATUS_MAST_REPEAT_START 0x10 | ||
42 | #define MV64XXX_I2C_STATUS_MAST_WR_ADDR_ACK 0x18 | ||
43 | #define MV64XXX_I2C_STATUS_MAST_WR_ADDR_NO_ACK 0x20 | ||
44 | #define MV64XXX_I2C_STATUS_MAST_WR_ACK 0x28 | ||
45 | #define MV64XXX_I2C_STATUS_MAST_WR_NO_ACK 0x30 | ||
46 | #define MV64XXX_I2C_STATUS_MAST_LOST_ARB 0x38 | ||
47 | #define MV64XXX_I2C_STATUS_MAST_RD_ADDR_ACK 0x40 | ||
48 | #define MV64XXX_I2C_STATUS_MAST_RD_ADDR_NO_ACK 0x48 | ||
49 | #define MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK 0x50 | ||
50 | #define MV64XXX_I2C_STATUS_MAST_RD_DATA_NO_ACK 0x58 | ||
51 | #define MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_ACK 0xd0 | ||
52 | #define MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_NO_ACK 0xd8 | ||
53 | #define MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_ACK 0xe0 | ||
54 | #define MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_NO_ACK 0xe8 | ||
55 | #define MV64XXX_I2C_STATUS_NO_STATUS 0xf8 | ||
56 | |||
57 | /* Driver states */ | ||
58 | enum { | ||
59 | MV64XXX_I2C_STATE_INVALID, | ||
60 | MV64XXX_I2C_STATE_IDLE, | ||
61 | MV64XXX_I2C_STATE_WAITING_FOR_START_COND, | ||
62 | MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK, | ||
63 | MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK, | ||
64 | MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK, | ||
65 | MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA, | ||
66 | MV64XXX_I2C_STATE_ABORTING, | ||
67 | }; | ||
68 | |||
69 | /* Driver actions */ | ||
70 | enum { | ||
71 | MV64XXX_I2C_ACTION_INVALID, | ||
72 | MV64XXX_I2C_ACTION_CONTINUE, | ||
73 | MV64XXX_I2C_ACTION_SEND_START, | ||
74 | MV64XXX_I2C_ACTION_SEND_ADDR_1, | ||
75 | MV64XXX_I2C_ACTION_SEND_ADDR_2, | ||
76 | MV64XXX_I2C_ACTION_SEND_DATA, | ||
77 | MV64XXX_I2C_ACTION_RCV_DATA, | ||
78 | MV64XXX_I2C_ACTION_RCV_DATA_STOP, | ||
79 | MV64XXX_I2C_ACTION_SEND_STOP, | ||
80 | }; | ||
81 | |||
82 | struct mv64xxx_i2c_data { | ||
83 | int irq; | ||
84 | u32 state; | ||
85 | u32 action; | ||
86 | u32 cntl_bits; | ||
87 | void __iomem *reg_base; | ||
88 | u32 reg_base_p; | ||
89 | u32 addr1; | ||
90 | u32 addr2; | ||
91 | u32 bytes_left; | ||
92 | u32 byte_posn; | ||
93 | u32 block; | ||
94 | int rc; | ||
95 | u32 freq_m; | ||
96 | u32 freq_n; | ||
97 | wait_queue_head_t waitq; | ||
98 | spinlock_t lock; | ||
99 | struct i2c_msg *msg; | ||
100 | struct i2c_adapter adapter; | ||
101 | }; | ||
102 | |||
103 | /* | ||
104 | ***************************************************************************** | ||
105 | * | ||
106 | * Finite State Machine & Interrupt Routines | ||
107 | * | ||
108 | ***************************************************************************** | ||
109 | */ | ||
110 | static void | ||
111 | mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status) | ||
112 | { | ||
113 | /* | ||
114 | * If state is idle, then this is likely the remnants of an old | ||
115 | * operation that driver has given up on or the user has killed. | ||
116 | * If so, issue the stop condition and go to idle. | ||
117 | */ | ||
118 | if (drv_data->state == MV64XXX_I2C_STATE_IDLE) { | ||
119 | drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; | ||
120 | return; | ||
121 | } | ||
122 | |||
123 | if (drv_data->state == MV64XXX_I2C_STATE_ABORTING) { | ||
124 | drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; | ||
125 | drv_data->state = MV64XXX_I2C_STATE_IDLE; | ||
126 | return; | ||
127 | } | ||
128 | |||
129 | /* The status from the ctlr [mostly] tells us what to do next */ | ||
130 | switch (status) { | ||
131 | /* Start condition interrupt */ | ||
132 | case MV64XXX_I2C_STATUS_MAST_START: /* 0x08 */ | ||
133 | case MV64XXX_I2C_STATUS_MAST_REPEAT_START: /* 0x10 */ | ||
134 | drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_1; | ||
135 | drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK; | ||
136 | break; | ||
137 | |||
138 | /* Performing a write */ | ||
139 | case MV64XXX_I2C_STATUS_MAST_WR_ADDR_ACK: /* 0x18 */ | ||
140 | if (drv_data->msg->flags & I2C_M_TEN) { | ||
141 | drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_2; | ||
142 | drv_data->state = | ||
143 | MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK; | ||
144 | break; | ||
145 | } | ||
146 | /* FALLTHRU */ | ||
147 | case MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_ACK: /* 0xd0 */ | ||
148 | case MV64XXX_I2C_STATUS_MAST_WR_ACK: /* 0x28 */ | ||
149 | if (drv_data->bytes_left > 0) { | ||
150 | drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA; | ||
151 | drv_data->state = | ||
152 | MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK; | ||
153 | drv_data->bytes_left--; | ||
154 | } else { | ||
155 | drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; | ||
156 | drv_data->state = MV64XXX_I2C_STATE_IDLE; | ||
157 | } | ||
158 | break; | ||
159 | |||
160 | /* Performing a read */ | ||
161 | case MV64XXX_I2C_STATUS_MAST_RD_ADDR_ACK: /* 40 */ | ||
162 | if (drv_data->msg->flags & I2C_M_TEN) { | ||
163 | drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_2; | ||
164 | drv_data->state = | ||
165 | MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK; | ||
166 | break; | ||
167 | } | ||
168 | /* FALLTHRU */ | ||
169 | case MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_ACK: /* 0xe0 */ | ||
170 | if (drv_data->bytes_left == 0) { | ||
171 | drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; | ||
172 | drv_data->state = MV64XXX_I2C_STATE_IDLE; | ||
173 | break; | ||
174 | } | ||
175 | /* FALLTHRU */ | ||
176 | case MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK: /* 0x50 */ | ||
177 | if (status != MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK) | ||
178 | drv_data->action = MV64XXX_I2C_ACTION_CONTINUE; | ||
179 | else { | ||
180 | drv_data->action = MV64XXX_I2C_ACTION_RCV_DATA; | ||
181 | drv_data->bytes_left--; | ||
182 | } | ||
183 | drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA; | ||
184 | |||
185 | if (drv_data->bytes_left == 1) | ||
186 | drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_ACK; | ||
187 | break; | ||
188 | |||
189 | case MV64XXX_I2C_STATUS_MAST_RD_DATA_NO_ACK: /* 0x58 */ | ||
190 | drv_data->action = MV64XXX_I2C_ACTION_RCV_DATA_STOP; | ||
191 | drv_data->state = MV64XXX_I2C_STATE_IDLE; | ||
192 | break; | ||
193 | |||
194 | case MV64XXX_I2C_STATUS_MAST_WR_ADDR_NO_ACK: /* 0x20 */ | ||
195 | case MV64XXX_I2C_STATUS_MAST_WR_NO_ACK: /* 30 */ | ||
196 | case MV64XXX_I2C_STATUS_MAST_RD_ADDR_NO_ACK: /* 48 */ | ||
197 | /* Doesn't seem to be a device at other end */ | ||
198 | drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; | ||
199 | drv_data->state = MV64XXX_I2C_STATE_IDLE; | ||
200 | drv_data->rc = -ENODEV; | ||
201 | break; | ||
202 | |||
203 | default: | ||
204 | dev_err(&drv_data->adapter.dev, | ||
205 | "mv64xxx_i2c_fsm: Ctlr Error -- state: 0x%x, " | ||
206 | "status: 0x%x, addr: 0x%x, flags: 0x%x\n", | ||
207 | drv_data->state, status, drv_data->msg->addr, | ||
208 | drv_data->msg->flags); | ||
209 | drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; | ||
210 | drv_data->state = MV64XXX_I2C_STATE_IDLE; | ||
211 | drv_data->rc = -EIO; | ||
212 | } | ||
213 | } | ||
214 | |||
215 | static void | ||
216 | mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) | ||
217 | { | ||
218 | switch(drv_data->action) { | ||
219 | case MV64XXX_I2C_ACTION_CONTINUE: | ||
220 | writel(drv_data->cntl_bits, | ||
221 | drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); | ||
222 | break; | ||
223 | |||
224 | case MV64XXX_I2C_ACTION_SEND_START: | ||
225 | writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START, | ||
226 | drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); | ||
227 | break; | ||
228 | |||
229 | case MV64XXX_I2C_ACTION_SEND_ADDR_1: | ||
230 | writel(drv_data->addr1, | ||
231 | drv_data->reg_base + MV64XXX_I2C_REG_DATA); | ||
232 | writel(drv_data->cntl_bits, | ||
233 | drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); | ||
234 | break; | ||
235 | |||
236 | case MV64XXX_I2C_ACTION_SEND_ADDR_2: | ||
237 | writel(drv_data->addr2, | ||
238 | drv_data->reg_base + MV64XXX_I2C_REG_DATA); | ||
239 | writel(drv_data->cntl_bits, | ||
240 | drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); | ||
241 | break; | ||
242 | |||
243 | case MV64XXX_I2C_ACTION_SEND_DATA: | ||
244 | writel(drv_data->msg->buf[drv_data->byte_posn++], | ||
245 | drv_data->reg_base + MV64XXX_I2C_REG_DATA); | ||
246 | writel(drv_data->cntl_bits, | ||
247 | drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); | ||
248 | break; | ||
249 | |||
250 | case MV64XXX_I2C_ACTION_RCV_DATA: | ||
251 | drv_data->msg->buf[drv_data->byte_posn++] = | ||
252 | readl(drv_data->reg_base + MV64XXX_I2C_REG_DATA); | ||
253 | writel(drv_data->cntl_bits, | ||
254 | drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); | ||
255 | break; | ||
256 | |||
257 | case MV64XXX_I2C_ACTION_RCV_DATA_STOP: | ||
258 | drv_data->msg->buf[drv_data->byte_posn++] = | ||
259 | readl(drv_data->reg_base + MV64XXX_I2C_REG_DATA); | ||
260 | drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; | ||
261 | writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP, | ||
262 | drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); | ||
263 | drv_data->block = 0; | ||
264 | wake_up_interruptible(&drv_data->waitq); | ||
265 | break; | ||
266 | |||
267 | case MV64XXX_I2C_ACTION_INVALID: | ||
268 | default: | ||
269 | dev_err(&drv_data->adapter.dev, | ||
270 | "mv64xxx_i2c_do_action: Invalid action: %d\n", | ||
271 | drv_data->action); | ||
272 | drv_data->rc = -EIO; | ||
273 | /* FALLTHRU */ | ||
274 | case MV64XXX_I2C_ACTION_SEND_STOP: | ||
275 | drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; | ||
276 | writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP, | ||
277 | drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); | ||
278 | drv_data->block = 0; | ||
279 | wake_up_interruptible(&drv_data->waitq); | ||
280 | break; | ||
281 | } | ||
282 | } | ||
283 | |||
284 | static int | ||
285 | mv64xxx_i2c_intr(int irq, void *dev_id, struct pt_regs *regs) | ||
286 | { | ||
287 | struct mv64xxx_i2c_data *drv_data = dev_id; | ||
288 | unsigned long flags; | ||
289 | u32 status; | ||
290 | int rc = IRQ_NONE; | ||
291 | |||
292 | spin_lock_irqsave(&drv_data->lock, flags); | ||
293 | while (readl(drv_data->reg_base + MV64XXX_I2C_REG_CONTROL) & | ||
294 | MV64XXX_I2C_REG_CONTROL_IFLG) { | ||
295 | status = readl(drv_data->reg_base + MV64XXX_I2C_REG_STATUS); | ||
296 | mv64xxx_i2c_fsm(drv_data, status); | ||
297 | mv64xxx_i2c_do_action(drv_data); | ||
298 | rc = IRQ_HANDLED; | ||
299 | } | ||
300 | spin_unlock_irqrestore(&drv_data->lock, flags); | ||
301 | |||
302 | return rc; | ||
303 | } | ||
304 | |||
305 | /* | ||
306 | ***************************************************************************** | ||
307 | * | ||
308 | * I2C Msg Execution Routines | ||
309 | * | ||
310 | ***************************************************************************** | ||
311 | */ | ||
312 | static void | ||
313 | mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data, | ||
314 | struct i2c_msg *msg) | ||
315 | { | ||
316 | u32 dir = 0; | ||
317 | |||
318 | drv_data->msg = msg; | ||
319 | drv_data->byte_posn = 0; | ||
320 | drv_data->bytes_left = msg->len; | ||
321 | drv_data->rc = 0; | ||
322 | drv_data->cntl_bits = MV64XXX_I2C_REG_CONTROL_ACK | | ||
323 | MV64XXX_I2C_REG_CONTROL_INTEN | MV64XXX_I2C_REG_CONTROL_TWSIEN; | ||
324 | |||
325 | if (msg->flags & I2C_M_RD) | ||
326 | dir = 1; | ||
327 | |||
328 | if (msg->flags & I2C_M_REV_DIR_ADDR) | ||
329 | dir ^= 1; | ||
330 | |||
331 | if (msg->flags & I2C_M_TEN) { | ||
332 | drv_data->addr1 = 0xf0 | (((u32)msg->addr & 0x300) >> 7) | dir; | ||
333 | drv_data->addr2 = (u32)msg->addr & 0xff; | ||
334 | } else { | ||
335 | drv_data->addr1 = ((u32)msg->addr & 0x7f) << 1 | dir; | ||
336 | drv_data->addr2 = 0; | ||
337 | } | ||
338 | } | ||
339 | |||
340 | static void | ||
341 | mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data) | ||
342 | { | ||
343 | long time_left; | ||
344 | unsigned long flags; | ||
345 | char abort = 0; | ||
346 | |||
347 | time_left = wait_event_interruptible_timeout(drv_data->waitq, | ||
348 | !drv_data->block, msecs_to_jiffies(drv_data->adapter.timeout)); | ||
349 | |||
350 | spin_lock_irqsave(&drv_data->lock, flags); | ||
351 | if (!time_left) { /* Timed out */ | ||
352 | drv_data->rc = -ETIMEDOUT; | ||
353 | abort = 1; | ||
354 | } else if (time_left < 0) { /* Interrupted/Error */ | ||
355 | drv_data->rc = time_left; /* errno value */ | ||
356 | abort = 1; | ||
357 | } | ||
358 | |||
359 | if (abort && drv_data->block) { | ||
360 | drv_data->state = MV64XXX_I2C_STATE_ABORTING; | ||
361 | spin_unlock_irqrestore(&drv_data->lock, flags); | ||
362 | |||
363 | time_left = wait_event_timeout(drv_data->waitq, | ||
364 | !drv_data->block, | ||
365 | msecs_to_jiffies(drv_data->adapter.timeout)); | ||
366 | |||
367 | if (time_left <= 0) { | ||
368 | drv_data->state = MV64XXX_I2C_STATE_IDLE; | ||
369 | dev_err(&drv_data->adapter.dev, | ||
370 | "mv64xxx: I2C bus locked\n"); | ||
371 | } | ||
372 | } else | ||
373 | spin_unlock_irqrestore(&drv_data->lock, flags); | ||
374 | } | ||
375 | |||
376 | static int | ||
377 | mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg) | ||
378 | { | ||
379 | unsigned long flags; | ||
380 | |||
381 | spin_lock_irqsave(&drv_data->lock, flags); | ||
382 | mv64xxx_i2c_prepare_for_io(drv_data, msg); | ||
383 | |||
384 | if (unlikely(msg->flags & I2C_M_NOSTART)) { /* Skip start/addr phases */ | ||
385 | if (drv_data->msg->flags & I2C_M_RD) { | ||
386 | /* No action to do, wait for slave to send a byte */ | ||
387 | drv_data->action = MV64XXX_I2C_ACTION_CONTINUE; | ||
388 | drv_data->state = | ||
389 | MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA; | ||
390 | } else { | ||
391 | drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA; | ||
392 | drv_data->state = | ||
393 | MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK; | ||
394 | drv_data->bytes_left--; | ||
395 | } | ||
396 | } else { | ||
397 | drv_data->action = MV64XXX_I2C_ACTION_SEND_START; | ||
398 | drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND; | ||
399 | } | ||
400 | |||
401 | drv_data->block = 1; | ||
402 | mv64xxx_i2c_do_action(drv_data); | ||
403 | spin_unlock_irqrestore(&drv_data->lock, flags); | ||
404 | |||
405 | mv64xxx_i2c_wait_for_completion(drv_data); | ||
406 | return drv_data->rc; | ||
407 | } | ||
408 | |||
409 | /* | ||
410 | ***************************************************************************** | ||
411 | * | ||
412 | * I2C Core Support Routines (Interface to higher level I2C code) | ||
413 | * | ||
414 | ***************************************************************************** | ||
415 | */ | ||
416 | static u32 | ||
417 | mv64xxx_i2c_functionality(struct i2c_adapter *adap) | ||
418 | { | ||
419 | return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SMBUS_EMUL; | ||
420 | } | ||
421 | |||
422 | static int | ||
423 | mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) | ||
424 | { | ||
425 | struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap); | ||
426 | int i, rc = 0; | ||
427 | |||
428 | for (i=0; i<num; i++) | ||
429 | if ((rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i])) != 0) | ||
430 | break; | ||
431 | |||
432 | return rc; | ||
433 | } | ||
434 | |||
435 | static struct i2c_algorithm mv64xxx_i2c_algo = { | ||
436 | .name = MV64XXX_I2C_CTLR_NAME " algorithm", | ||
437 | .id = I2C_ALGO_MV64XXX, | ||
438 | .master_xfer = mv64xxx_i2c_xfer, | ||
439 | .functionality = mv64xxx_i2c_functionality, | ||
440 | }; | ||
441 | |||
442 | /* | ||
443 | ***************************************************************************** | ||
444 | * | ||
445 | * Driver Interface & Early Init Routines | ||
446 | * | ||
447 | ***************************************************************************** | ||
448 | */ | ||
449 | static void __devinit | ||
450 | mv64xxx_i2c_hw_init(struct mv64xxx_i2c_data *drv_data) | ||
451 | { | ||
452 | writel(0, drv_data->reg_base + MV64XXX_I2C_REG_SOFT_RESET); | ||
453 | writel((((drv_data->freq_m & 0xf) << 3) | (drv_data->freq_n & 0x7)), | ||
454 | drv_data->reg_base + MV64XXX_I2C_REG_BAUD); | ||
455 | writel(0, drv_data->reg_base + MV64XXX_I2C_REG_SLAVE_ADDR); | ||
456 | writel(0, drv_data->reg_base + MV64XXX_I2C_REG_EXT_SLAVE_ADDR); | ||
457 | writel(MV64XXX_I2C_REG_CONTROL_TWSIEN | MV64XXX_I2C_REG_CONTROL_STOP, | ||
458 | drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); | ||
459 | drv_data->state = MV64XXX_I2C_STATE_IDLE; | ||
460 | } | ||
461 | |||
462 | static int __devinit | ||
463 | mv64xxx_i2c_map_regs(struct platform_device *pd, | ||
464 | struct mv64xxx_i2c_data *drv_data) | ||
465 | { | ||
466 | struct resource *r; | ||
467 | |||
468 | if ((r = platform_get_resource(pd, IORESOURCE_MEM, 0)) && | ||
469 | request_mem_region(r->start, MV64XXX_I2C_REG_BLOCK_SIZE, | ||
470 | drv_data->adapter.name)) { | ||
471 | |||
472 | drv_data->reg_base = ioremap(r->start, | ||
473 | MV64XXX_I2C_REG_BLOCK_SIZE); | ||
474 | drv_data->reg_base_p = r->start; | ||
475 | } else | ||
476 | return -ENOMEM; | ||
477 | |||
478 | return 0; | ||
479 | } | ||
480 | |||
481 | static void __devexit | ||
482 | mv64xxx_i2c_unmap_regs(struct mv64xxx_i2c_data *drv_data) | ||
483 | { | ||
484 | if (drv_data->reg_base) { | ||
485 | iounmap(drv_data->reg_base); | ||
486 | release_mem_region(drv_data->reg_base_p, | ||
487 | MV64XXX_I2C_REG_BLOCK_SIZE); | ||
488 | } | ||
489 | |||
490 | drv_data->reg_base = NULL; | ||
491 | drv_data->reg_base_p = 0; | ||
492 | } | ||
493 | |||
494 | static int __devinit | ||
495 | mv64xxx_i2c_probe(struct device *dev) | ||
496 | { | ||
497 | struct platform_device *pd = to_platform_device(dev); | ||
498 | struct mv64xxx_i2c_data *drv_data; | ||
499 | struct mv64xxx_i2c_pdata *pdata = dev->platform_data; | ||
500 | int rc; | ||
501 | |||
502 | if ((pd->id != 0) || !pdata) | ||
503 | return -ENODEV; | ||
504 | |||
505 | drv_data = kmalloc(sizeof(struct mv64xxx_i2c_data), GFP_KERNEL); | ||
506 | |||
507 | if (!drv_data) | ||
508 | return -ENOMEM; | ||
509 | |||
510 | memset(drv_data, 0, sizeof(struct mv64xxx_i2c_data)); | ||
511 | |||
512 | if (mv64xxx_i2c_map_regs(pd, drv_data)) { | ||
513 | rc = -ENODEV; | ||
514 | goto exit_kfree; | ||
515 | } | ||
516 | |||
517 | strncpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter", | ||
518 | I2C_NAME_SIZE); | ||
519 | |||
520 | init_waitqueue_head(&drv_data->waitq); | ||
521 | spin_lock_init(&drv_data->lock); | ||
522 | |||
523 | drv_data->freq_m = pdata->freq_m; | ||
524 | drv_data->freq_n = pdata->freq_n; | ||
525 | drv_data->irq = platform_get_irq(pd, 0); | ||
526 | drv_data->adapter.id = I2C_ALGO_MV64XXX | I2C_HW_MV64XXX; | ||
527 | drv_data->adapter.algo = &mv64xxx_i2c_algo; | ||
528 | drv_data->adapter.owner = THIS_MODULE; | ||
529 | drv_data->adapter.class = I2C_CLASS_HWMON; | ||
530 | drv_data->adapter.timeout = pdata->timeout; | ||
531 | drv_data->adapter.retries = pdata->retries; | ||
532 | dev_set_drvdata(dev, drv_data); | ||
533 | i2c_set_adapdata(&drv_data->adapter, drv_data); | ||
534 | |||
535 | if (request_irq(drv_data->irq, mv64xxx_i2c_intr, 0, | ||
536 | MV64XXX_I2C_CTLR_NAME, drv_data)) { | ||
537 | |||
538 | dev_err(dev, "mv64xxx: Can't register intr handler " | ||
539 | "irq: %d\n", drv_data->irq); | ||
540 | rc = -EINVAL; | ||
541 | goto exit_unmap_regs; | ||
542 | } else if ((rc = i2c_add_adapter(&drv_data->adapter)) != 0) { | ||
543 | dev_err(dev, "mv64xxx: Can't add i2c adapter, rc: %d\n", -rc); | ||
544 | goto exit_free_irq; | ||
545 | } | ||
546 | |||
547 | mv64xxx_i2c_hw_init(drv_data); | ||
548 | |||
549 | return 0; | ||
550 | |||
551 | exit_free_irq: | ||
552 | free_irq(drv_data->irq, drv_data); | ||
553 | exit_unmap_regs: | ||
554 | mv64xxx_i2c_unmap_regs(drv_data); | ||
555 | exit_kfree: | ||
556 | kfree(drv_data); | ||
557 | return rc; | ||
558 | } | ||
559 | |||
560 | static int __devexit | ||
561 | mv64xxx_i2c_remove(struct device *dev) | ||
562 | { | ||
563 | struct mv64xxx_i2c_data *drv_data = dev_get_drvdata(dev); | ||
564 | int rc; | ||
565 | |||
566 | rc = i2c_del_adapter(&drv_data->adapter); | ||
567 | free_irq(drv_data->irq, drv_data); | ||
568 | mv64xxx_i2c_unmap_regs(drv_data); | ||
569 | kfree(drv_data); | ||
570 | |||
571 | return rc; | ||
572 | } | ||
573 | |||
574 | static struct device_driver mv64xxx_i2c_driver = { | ||
575 | .name = MV64XXX_I2C_CTLR_NAME, | ||
576 | .bus = &platform_bus_type, | ||
577 | .probe = mv64xxx_i2c_probe, | ||
578 | .remove = mv64xxx_i2c_remove, | ||
579 | }; | ||
580 | |||
581 | static int __init | ||
582 | mv64xxx_i2c_init(void) | ||
583 | { | ||
584 | return driver_register(&mv64xxx_i2c_driver); | ||
585 | } | ||
586 | |||
587 | static void __exit | ||
588 | mv64xxx_i2c_exit(void) | ||
589 | { | ||
590 | driver_unregister(&mv64xxx_i2c_driver); | ||
591 | } | ||
592 | |||
593 | module_init(mv64xxx_i2c_init); | ||
594 | module_exit(mv64xxx_i2c_exit); | ||
595 | |||
596 | MODULE_AUTHOR("Mark A. Greer <mgreer@mvista.com>"); | ||
597 | MODULE_DESCRIPTION("Marvell mv64xxx host bridge i2c ctlr driver"); | ||
598 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c new file mode 100644 index 000000000000..6d13127c8c4e --- /dev/null +++ b/drivers/i2c/busses/i2c-nforce2.c | |||
@@ -0,0 +1,410 @@ | |||
1 | /* | ||
2 | SMBus driver for nVidia nForce2 MCP | ||
3 | |||
4 | Added nForce3 Pro 150 Thomas Leibold <thomas@plx.com>, | ||
5 | Ported to 2.5 Patrick Dreker <patrick@dreker.de>, | ||
6 | Copyright (c) 2003 Hans-Frieder Vogt <hfvogt@arcor.de>, | ||
7 | Based on | ||
8 | SMBus 2.0 driver for AMD-8111 IO-Hub | ||
9 | Copyright (c) 2002 Vojtech Pavlik | ||
10 | |||
11 | This program is free software; you can redistribute it and/or modify | ||
12 | it under the terms of the GNU General Public License as published by | ||
13 | the Free Software Foundation; either version 2 of the License, or | ||
14 | (at your option) any later version. | ||
15 | |||
16 | This program is distributed in the hope that it will be useful, | ||
17 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | GNU General Public License for more details. | ||
20 | |||
21 | You should have received a copy of the GNU General Public License | ||
22 | along with this program; if not, write to the Free Software | ||
23 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | |||
26 | /* | ||
27 | SUPPORTED DEVICES PCI ID | ||
28 | nForce2 MCP 0064 | ||
29 | nForce2 Ultra 400 MCP 0084 | ||
30 | nForce3 Pro150 MCP 00D4 | ||
31 | nForce3 250Gb MCP 00E4 | ||
32 | nForce4 MCP 0052 | ||
33 | |||
34 | This driver supports the 2 SMBuses that are included in the MCP of the | ||
35 | nForce2/3/4 chipsets. | ||
36 | */ | ||
37 | |||
38 | /* Note: we assume there can only be one nForce2, with two SMBus interfaces */ | ||
39 | |||
40 | #include <linux/config.h> | ||
41 | #include <linux/module.h> | ||
42 | #include <linux/pci.h> | ||
43 | #include <linux/kernel.h> | ||
44 | #include <linux/stddef.h> | ||
45 | #include <linux/sched.h> | ||
46 | #include <linux/ioport.h> | ||
47 | #include <linux/init.h> | ||
48 | #include <linux/i2c.h> | ||
49 | #include <linux/delay.h> | ||
50 | #include <asm/io.h> | ||
51 | |||
52 | MODULE_LICENSE("GPL"); | ||
53 | MODULE_AUTHOR ("Hans-Frieder Vogt <hfvogt@arcor.de>"); | ||
54 | MODULE_DESCRIPTION("nForce2 SMBus driver"); | ||
55 | |||
56 | |||
57 | struct nforce2_smbus { | ||
58 | struct pci_dev *dev; | ||
59 | struct i2c_adapter adapter; | ||
60 | int base; | ||
61 | int size; | ||
62 | }; | ||
63 | |||
64 | |||
65 | /* | ||
66 | * nVidia nForce2 SMBus control register definitions | ||
67 | */ | ||
68 | #define NFORCE_PCI_SMB1 0x50 | ||
69 | #define NFORCE_PCI_SMB2 0x54 | ||
70 | |||
71 | |||
72 | /* | ||
73 | * ACPI 2.0 chapter 13 SMBus 2.0 EC register model | ||
74 | */ | ||
75 | #define NVIDIA_SMB_PRTCL (smbus->base + 0x00) /* protocol, PEC */ | ||
76 | #define NVIDIA_SMB_STS (smbus->base + 0x01) /* status */ | ||
77 | #define NVIDIA_SMB_ADDR (smbus->base + 0x02) /* address */ | ||
78 | #define NVIDIA_SMB_CMD (smbus->base + 0x03) /* command */ | ||
79 | #define NVIDIA_SMB_DATA (smbus->base + 0x04) /* 32 data registers */ | ||
80 | #define NVIDIA_SMB_BCNT (smbus->base + 0x24) /* number of data bytes */ | ||
81 | #define NVIDIA_SMB_ALRM_A (smbus->base + 0x25) /* alarm address */ | ||
82 | #define NVIDIA_SMB_ALRM_D (smbus->base + 0x26) /* 2 bytes alarm data */ | ||
83 | |||
84 | #define NVIDIA_SMB_STS_DONE 0x80 | ||
85 | #define NVIDIA_SMB_STS_ALRM 0x40 | ||
86 | #define NVIDIA_SMB_STS_RES 0x20 | ||
87 | #define NVIDIA_SMB_STS_STATUS 0x1f | ||
88 | |||
89 | #define NVIDIA_SMB_PRTCL_WRITE 0x00 | ||
90 | #define NVIDIA_SMB_PRTCL_READ 0x01 | ||
91 | #define NVIDIA_SMB_PRTCL_QUICK 0x02 | ||
92 | #define NVIDIA_SMB_PRTCL_BYTE 0x04 | ||
93 | #define NVIDIA_SMB_PRTCL_BYTE_DATA 0x06 | ||
94 | #define NVIDIA_SMB_PRTCL_WORD_DATA 0x08 | ||
95 | #define NVIDIA_SMB_PRTCL_BLOCK_DATA 0x0a | ||
96 | #define NVIDIA_SMB_PRTCL_PROC_CALL 0x0c | ||
97 | #define NVIDIA_SMB_PRTCL_BLOCK_PROC_CALL 0x0d | ||
98 | #define NVIDIA_SMB_PRTCL_I2C_BLOCK_DATA 0x4a | ||
99 | #define NVIDIA_SMB_PRTCL_PEC 0x80 | ||
100 | |||
101 | |||
102 | /* Other settings */ | ||
103 | #define MAX_TIMEOUT 256 | ||
104 | |||
105 | |||
106 | |||
107 | static s32 nforce2_access(struct i2c_adapter *adap, u16 addr, | ||
108 | unsigned short flags, char read_write, | ||
109 | u8 command, int size, union i2c_smbus_data *data); | ||
110 | static u32 nforce2_func(struct i2c_adapter *adapter); | ||
111 | |||
112 | |||
113 | static struct i2c_algorithm smbus_algorithm = { | ||
114 | .name = "Non-I2C SMBus adapter", | ||
115 | .id = I2C_ALGO_SMBUS, | ||
116 | .smbus_xfer = nforce2_access, | ||
117 | .functionality = nforce2_func, | ||
118 | }; | ||
119 | |||
120 | static struct i2c_adapter nforce2_adapter = { | ||
121 | .owner = THIS_MODULE, | ||
122 | .class = I2C_CLASS_HWMON, | ||
123 | .algo = &smbus_algorithm, | ||
124 | .name = "unset", | ||
125 | }; | ||
126 | |||
127 | /* Return -1 on error. See smbus.h for more information */ | ||
128 | static s32 nforce2_access(struct i2c_adapter * adap, u16 addr, | ||
129 | unsigned short flags, char read_write, | ||
130 | u8 command, int size, union i2c_smbus_data * data) | ||
131 | { | ||
132 | struct nforce2_smbus *smbus = adap->algo_data; | ||
133 | unsigned char protocol, pec, temp; | ||
134 | unsigned char len = 0; /* to keep the compiler quiet */ | ||
135 | int timeout = 0; | ||
136 | int i; | ||
137 | |||
138 | protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ : | ||
139 | NVIDIA_SMB_PRTCL_WRITE; | ||
140 | pec = (flags & I2C_CLIENT_PEC) ? NVIDIA_SMB_PRTCL_PEC : 0; | ||
141 | |||
142 | switch (size) { | ||
143 | |||
144 | case I2C_SMBUS_QUICK: | ||
145 | protocol |= NVIDIA_SMB_PRTCL_QUICK; | ||
146 | read_write = I2C_SMBUS_WRITE; | ||
147 | break; | ||
148 | |||
149 | case I2C_SMBUS_BYTE: | ||
150 | if (read_write == I2C_SMBUS_WRITE) | ||
151 | outb_p(command, NVIDIA_SMB_CMD); | ||
152 | protocol |= NVIDIA_SMB_PRTCL_BYTE; | ||
153 | break; | ||
154 | |||
155 | case I2C_SMBUS_BYTE_DATA: | ||
156 | outb_p(command, NVIDIA_SMB_CMD); | ||
157 | if (read_write == I2C_SMBUS_WRITE) | ||
158 | outb_p(data->byte, NVIDIA_SMB_DATA); | ||
159 | protocol |= NVIDIA_SMB_PRTCL_BYTE_DATA; | ||
160 | break; | ||
161 | |||
162 | case I2C_SMBUS_WORD_DATA: | ||
163 | outb_p(command, NVIDIA_SMB_CMD); | ||
164 | if (read_write == I2C_SMBUS_WRITE) { | ||
165 | outb_p(data->word, NVIDIA_SMB_DATA); | ||
166 | outb_p(data->word >> 8, NVIDIA_SMB_DATA+1); | ||
167 | } | ||
168 | protocol |= NVIDIA_SMB_PRTCL_WORD_DATA | pec; | ||
169 | break; | ||
170 | |||
171 | case I2C_SMBUS_BLOCK_DATA: | ||
172 | outb_p(command, NVIDIA_SMB_CMD); | ||
173 | if (read_write == I2C_SMBUS_WRITE) { | ||
174 | len = min_t(u8, data->block[0], 32); | ||
175 | outb_p(len, NVIDIA_SMB_BCNT); | ||
176 | for (i = 0; i < len; i++) | ||
177 | outb_p(data->block[i + 1], NVIDIA_SMB_DATA+i); | ||
178 | } | ||
179 | protocol |= NVIDIA_SMB_PRTCL_BLOCK_DATA | pec; | ||
180 | break; | ||
181 | |||
182 | case I2C_SMBUS_I2C_BLOCK_DATA: | ||
183 | len = min_t(u8, data->block[0], 32); | ||
184 | outb_p(command, NVIDIA_SMB_CMD); | ||
185 | outb_p(len, NVIDIA_SMB_BCNT); | ||
186 | if (read_write == I2C_SMBUS_WRITE) | ||
187 | for (i = 0; i < len; i++) | ||
188 | outb_p(data->block[i + 1], NVIDIA_SMB_DATA+i); | ||
189 | protocol |= NVIDIA_SMB_PRTCL_I2C_BLOCK_DATA; | ||
190 | break; | ||
191 | |||
192 | case I2C_SMBUS_PROC_CALL: | ||
193 | dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n"); | ||
194 | return -1; | ||
195 | /* | ||
196 | outb_p(command, NVIDIA_SMB_CMD); | ||
197 | outb_p(data->word, NVIDIA_SMB_DATA); | ||
198 | outb_p(data->word >> 8, NVIDIA_SMB_DATA + 1); | ||
199 | protocol = NVIDIA_SMB_PRTCL_PROC_CALL | pec; | ||
200 | read_write = I2C_SMBUS_READ; | ||
201 | break; | ||
202 | */ | ||
203 | |||
204 | case I2C_SMBUS_BLOCK_PROC_CALL: | ||
205 | dev_err(&adap->dev, "I2C_SMBUS_BLOCK_PROC_CALL not supported!\n"); | ||
206 | return -1; | ||
207 | /* | ||
208 | protocol |= pec; | ||
209 | len = min_t(u8, data->block[0], 31); | ||
210 | outb_p(command, NVIDIA_SMB_CMD); | ||
211 | outb_p(len, NVIDIA_SMB_BCNT); | ||
212 | for (i = 0; i < len; i++) | ||
213 | outb_p(data->block[i + 1], NVIDIA_SMB_DATA + i); | ||
214 | protocol = NVIDIA_SMB_PRTCL_BLOCK_PROC_CALL | pec; | ||
215 | read_write = I2C_SMBUS_READ; | ||
216 | break; | ||
217 | */ | ||
218 | |||
219 | case I2C_SMBUS_WORD_DATA_PEC: | ||
220 | case I2C_SMBUS_BLOCK_DATA_PEC: | ||
221 | case I2C_SMBUS_PROC_CALL_PEC: | ||
222 | case I2C_SMBUS_BLOCK_PROC_CALL_PEC: | ||
223 | dev_err(&adap->dev, "Unexpected software PEC transaction %d\n.", size); | ||
224 | return -1; | ||
225 | |||
226 | default: | ||
227 | dev_err(&adap->dev, "Unsupported transaction %d\n", size); | ||
228 | return -1; | ||
229 | } | ||
230 | |||
231 | outb_p((addr & 0x7f) << 1, NVIDIA_SMB_ADDR); | ||
232 | outb_p(protocol, NVIDIA_SMB_PRTCL); | ||
233 | |||
234 | temp = inb_p(NVIDIA_SMB_STS); | ||
235 | |||
236 | #if 0 | ||
237 | do { | ||
238 | i2c_do_pause(1); | ||
239 | temp = inb_p(NVIDIA_SMB_STS); | ||
240 | } while (((temp & NVIDIA_SMB_STS_DONE) == 0) && (timeout++ < MAX_TIMEOUT)); | ||
241 | #endif | ||
242 | if (~temp & NVIDIA_SMB_STS_DONE) { | ||
243 | udelay(500); | ||
244 | temp = inb_p(NVIDIA_SMB_STS); | ||
245 | } | ||
246 | if (~temp & NVIDIA_SMB_STS_DONE) { | ||
247 | msleep(10); | ||
248 | temp = inb_p(NVIDIA_SMB_STS); | ||
249 | } | ||
250 | |||
251 | if ((timeout >= MAX_TIMEOUT) || (~temp & NVIDIA_SMB_STS_DONE) | ||
252 | || (temp & NVIDIA_SMB_STS_STATUS)) | ||
253 | return -1; | ||
254 | |||
255 | if (read_write == I2C_SMBUS_WRITE) | ||
256 | return 0; | ||
257 | |||
258 | switch (size) { | ||
259 | |||
260 | case I2C_SMBUS_BYTE: | ||
261 | case I2C_SMBUS_BYTE_DATA: | ||
262 | data->byte = inb_p(NVIDIA_SMB_DATA); | ||
263 | break; | ||
264 | |||
265 | case I2C_SMBUS_WORD_DATA: | ||
266 | /* case I2C_SMBUS_PROC_CALL: not supported */ | ||
267 | data->word = inb_p(NVIDIA_SMB_DATA) | (inb_p(NVIDIA_SMB_DATA+1) << 8); | ||
268 | break; | ||
269 | |||
270 | case I2C_SMBUS_BLOCK_DATA: | ||
271 | /* case I2C_SMBUS_BLOCK_PROC_CALL: not supported */ | ||
272 | len = inb_p(NVIDIA_SMB_BCNT); | ||
273 | len = min_t(u8, len, 32); | ||
274 | case I2C_SMBUS_I2C_BLOCK_DATA: | ||
275 | for (i = 0; i < len; i++) | ||
276 | data->block[i+1] = inb_p(NVIDIA_SMB_DATA + i); | ||
277 | data->block[0] = len; | ||
278 | break; | ||
279 | } | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | |||
285 | static u32 nforce2_func(struct i2c_adapter *adapter) | ||
286 | { | ||
287 | /* other functionality might be possible, but is not tested */ | ||
288 | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | | ||
289 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA /* | | ||
290 | I2C_FUNC_SMBUS_BLOCK_DATA */; | ||
291 | } | ||
292 | |||
293 | |||
294 | static struct pci_device_id nforce2_ids[] = { | ||
295 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS) }, | ||
296 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS) }, | ||
297 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS) }, | ||
298 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS) }, | ||
299 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS) }, | ||
300 | { 0 } | ||
301 | }; | ||
302 | |||
303 | |||
304 | MODULE_DEVICE_TABLE (pci, nforce2_ids); | ||
305 | |||
306 | |||
307 | static int __devinit nforce2_probe_smb (struct pci_dev *dev, int reg, | ||
308 | struct nforce2_smbus *smbus, char *name) | ||
309 | { | ||
310 | u16 iobase; | ||
311 | int error; | ||
312 | |||
313 | if (pci_read_config_word(dev, reg, &iobase) != PCIBIOS_SUCCESSFUL) { | ||
314 | dev_err(&smbus->adapter.dev, "Error reading PCI config for %s\n", name); | ||
315 | return -1; | ||
316 | } | ||
317 | smbus->dev = dev; | ||
318 | smbus->base = iobase & 0xfffc; | ||
319 | smbus->size = 8; | ||
320 | |||
321 | if (!request_region(smbus->base, smbus->size, "nForce2 SMBus")) { | ||
322 | dev_err(&smbus->adapter.dev, "Error requesting region %02x .. %02X for %s\n", | ||
323 | smbus->base, smbus->base+smbus->size-1, name); | ||
324 | return -1; | ||
325 | } | ||
326 | smbus->adapter = nforce2_adapter; | ||
327 | smbus->adapter.algo_data = smbus; | ||
328 | smbus->adapter.dev.parent = &dev->dev; | ||
329 | snprintf(smbus->adapter.name, I2C_NAME_SIZE, | ||
330 | "SMBus nForce2 adapter at %04x", smbus->base); | ||
331 | |||
332 | error = i2c_add_adapter(&smbus->adapter); | ||
333 | if (error) { | ||
334 | dev_err(&smbus->adapter.dev, "Failed to register adapter.\n"); | ||
335 | release_region(smbus->base, smbus->size); | ||
336 | return -1; | ||
337 | } | ||
338 | dev_info(&smbus->adapter.dev, "nForce2 SMBus adapter at %#x\n", smbus->base); | ||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | |||
343 | static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_id *id) | ||
344 | { | ||
345 | struct nforce2_smbus *smbuses; | ||
346 | int res1, res2; | ||
347 | |||
348 | /* we support 2 SMBus adapters */ | ||
349 | if (!(smbuses = (void *)kmalloc(2*sizeof(struct nforce2_smbus), | ||
350 | GFP_KERNEL))) | ||
351 | return -ENOMEM; | ||
352 | memset (smbuses, 0, 2*sizeof(struct nforce2_smbus)); | ||
353 | pci_set_drvdata(dev, smbuses); | ||
354 | |||
355 | /* SMBus adapter 1 */ | ||
356 | res1 = nforce2_probe_smb (dev, NFORCE_PCI_SMB1, &smbuses[0], "SMB1"); | ||
357 | if (res1 < 0) { | ||
358 | dev_err(&dev->dev, "Error probing SMB1.\n"); | ||
359 | smbuses[0].base = 0; /* to have a check value */ | ||
360 | } | ||
361 | res2 = nforce2_probe_smb (dev, NFORCE_PCI_SMB2, &smbuses[1], "SMB2"); | ||
362 | if (res2 < 0) { | ||
363 | dev_err(&dev->dev, "Error probing SMB2.\n"); | ||
364 | smbuses[1].base = 0; /* to have a check value */ | ||
365 | } | ||
366 | if ((res1 < 0) && (res2 < 0)) { | ||
367 | /* we did not find even one of the SMBuses, so we give up */ | ||
368 | kfree(smbuses); | ||
369 | return -ENODEV; | ||
370 | } | ||
371 | |||
372 | return 0; | ||
373 | } | ||
374 | |||
375 | |||
376 | static void __devexit nforce2_remove(struct pci_dev *dev) | ||
377 | { | ||
378 | struct nforce2_smbus *smbuses = (void*) pci_get_drvdata(dev); | ||
379 | |||
380 | if (smbuses[0].base) { | ||
381 | i2c_del_adapter(&smbuses[0].adapter); | ||
382 | release_region(smbuses[0].base, smbuses[0].size); | ||
383 | } | ||
384 | if (smbuses[1].base) { | ||
385 | i2c_del_adapter(&smbuses[1].adapter); | ||
386 | release_region(smbuses[1].base, smbuses[1].size); | ||
387 | } | ||
388 | kfree(smbuses); | ||
389 | } | ||
390 | |||
391 | static struct pci_driver nforce2_driver = { | ||
392 | .name = "nForce2_smbus", | ||
393 | .id_table = nforce2_ids, | ||
394 | .probe = nforce2_probe, | ||
395 | .remove = __devexit_p(nforce2_remove), | ||
396 | }; | ||
397 | |||
398 | static int __init nforce2_init(void) | ||
399 | { | ||
400 | return pci_register_driver(&nforce2_driver); | ||
401 | } | ||
402 | |||
403 | static void __exit nforce2_exit(void) | ||
404 | { | ||
405 | pci_unregister_driver(&nforce2_driver); | ||
406 | } | ||
407 | |||
408 | module_init(nforce2_init); | ||
409 | module_exit(nforce2_exit); | ||
410 | |||
diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c new file mode 100644 index 000000000000..cb5e722301d8 --- /dev/null +++ b/drivers/i2c/busses/i2c-parport-light.c | |||
@@ -0,0 +1,175 @@ | |||
1 | /* ------------------------------------------------------------------------ * | ||
2 | * i2c-parport.c I2C bus over parallel port * | ||
3 | * ------------------------------------------------------------------------ * | ||
4 | Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org> | ||
5 | |||
6 | Based on older i2c-velleman.c driver | ||
7 | Copyright (C) 1995-2000 Simon G. Vogl | ||
8 | With some changes from: | ||
9 | Frodo Looijaard <frodol@dds.nl> | ||
10 | Kyösti Mälkki <kmalkki@cc.hut.fi> | ||
11 | |||
12 | This program is free software; you can redistribute it and/or modify | ||
13 | it under the terms of the GNU General Public License as published by | ||
14 | the Free Software Foundation; either version 2 of the License, or | ||
15 | (at your option) any later version. | ||
16 | |||
17 | This program is distributed in the hope that it will be useful, | ||
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | GNU General Public License for more details. | ||
21 | |||
22 | You should have received a copy of the GNU General Public License | ||
23 | along with this program; if not, write to the Free Software | ||
24 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | * ------------------------------------------------------------------------ */ | ||
26 | |||
27 | #include <linux/config.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/ioport.h> | ||
32 | #include <linux/i2c.h> | ||
33 | #include <linux/i2c-algo-bit.h> | ||
34 | #include <asm/io.h> | ||
35 | #include "i2c-parport.h" | ||
36 | |||
37 | #define DEFAULT_BASE 0x378 | ||
38 | |||
39 | static u16 base; | ||
40 | module_param(base, ushort, 0); | ||
41 | MODULE_PARM_DESC(base, "Base I/O address"); | ||
42 | |||
43 | /* ----- Low-level parallel port access ----------------------------------- */ | ||
44 | |||
45 | static inline void port_write(unsigned char p, unsigned char d) | ||
46 | { | ||
47 | outb(d, base+p); | ||
48 | } | ||
49 | |||
50 | static inline unsigned char port_read(unsigned char p) | ||
51 | { | ||
52 | return inb(base+p); | ||
53 | } | ||
54 | |||
55 | /* ----- Unified line operation functions --------------------------------- */ | ||
56 | |||
57 | static inline void line_set(int state, const struct lineop *op) | ||
58 | { | ||
59 | u8 oldval = port_read(op->port); | ||
60 | |||
61 | /* Touch only the bit(s) needed */ | ||
62 | if ((op->inverted && !state) || (!op->inverted && state)) | ||
63 | port_write(op->port, oldval | op->val); | ||
64 | else | ||
65 | port_write(op->port, oldval & ~op->val); | ||
66 | } | ||
67 | |||
68 | static inline int line_get(const struct lineop *op) | ||
69 | { | ||
70 | u8 oldval = port_read(op->port); | ||
71 | |||
72 | return ((op->inverted && (oldval & op->val) != op->val) | ||
73 | || (!op->inverted && (oldval & op->val) == op->val)); | ||
74 | } | ||
75 | |||
76 | /* ----- I2C algorithm call-back functions and structures ----------------- */ | ||
77 | |||
78 | static void parport_setscl(void *data, int state) | ||
79 | { | ||
80 | line_set(state, &adapter_parm[type].setscl); | ||
81 | } | ||
82 | |||
83 | static void parport_setsda(void *data, int state) | ||
84 | { | ||
85 | line_set(state, &adapter_parm[type].setsda); | ||
86 | } | ||
87 | |||
88 | static int parport_getscl(void *data) | ||
89 | { | ||
90 | return line_get(&adapter_parm[type].getscl); | ||
91 | } | ||
92 | |||
93 | static int parport_getsda(void *data) | ||
94 | { | ||
95 | return line_get(&adapter_parm[type].getsda); | ||
96 | } | ||
97 | |||
98 | /* Encapsulate the functions above in the correct structure | ||
99 | Note that getscl will be set to NULL by the attaching code for adapters | ||
100 | that cannot read SCL back */ | ||
101 | static struct i2c_algo_bit_data parport_algo_data = { | ||
102 | .setsda = parport_setsda, | ||
103 | .setscl = parport_setscl, | ||
104 | .getsda = parport_getsda, | ||
105 | .getscl = parport_getscl, | ||
106 | .udelay = 50, | ||
107 | .mdelay = 50, | ||
108 | .timeout = HZ, | ||
109 | }; | ||
110 | |||
111 | /* ----- I2c structure ---------------------------------------------------- */ | ||
112 | |||
113 | static struct i2c_adapter parport_adapter = { | ||
114 | .owner = THIS_MODULE, | ||
115 | .class = I2C_CLASS_HWMON, | ||
116 | .id = I2C_HW_B_LP, | ||
117 | .algo_data = &parport_algo_data, | ||
118 | .name = "Parallel port adapter (light)", | ||
119 | }; | ||
120 | |||
121 | /* ----- Module loading, unloading and information ------------------------ */ | ||
122 | |||
123 | static int __init i2c_parport_init(void) | ||
124 | { | ||
125 | int type_count; | ||
126 | |||
127 | type_count = sizeof(adapter_parm)/sizeof(struct adapter_parm); | ||
128 | if (type < 0 || type >= type_count) { | ||
129 | printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type); | ||
130 | type = 0; | ||
131 | } | ||
132 | |||
133 | if (base == 0) { | ||
134 | printk(KERN_INFO "i2c-parport: using default base 0x%x\n", DEFAULT_BASE); | ||
135 | base = DEFAULT_BASE; | ||
136 | } | ||
137 | |||
138 | if (!request_region(base, 3, "i2c-parport")) | ||
139 | return -ENODEV; | ||
140 | |||
141 | if (!adapter_parm[type].getscl.val) | ||
142 | parport_algo_data.getscl = NULL; | ||
143 | |||
144 | /* Reset hardware to a sane state (SCL and SDA high) */ | ||
145 | parport_setsda(NULL, 1); | ||
146 | parport_setscl(NULL, 1); | ||
147 | /* Other init if needed (power on...) */ | ||
148 | if (adapter_parm[type].init.val) | ||
149 | line_set(1, &adapter_parm[type].init); | ||
150 | |||
151 | if (i2c_bit_add_bus(&parport_adapter) < 0) { | ||
152 | printk(KERN_ERR "i2c-parport: Unable to register with I2C\n"); | ||
153 | release_region(base, 3); | ||
154 | return -ENODEV; | ||
155 | } | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static void __exit i2c_parport_exit(void) | ||
161 | { | ||
162 | /* Un-init if needed (power off...) */ | ||
163 | if (adapter_parm[type].init.val) | ||
164 | line_set(0, &adapter_parm[type].init); | ||
165 | |||
166 | i2c_bit_del_bus(&parport_adapter); | ||
167 | release_region(base, 3); | ||
168 | } | ||
169 | |||
170 | MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); | ||
171 | MODULE_DESCRIPTION("I2C bus over parallel port (light)"); | ||
172 | MODULE_LICENSE("GPL"); | ||
173 | |||
174 | module_init(i2c_parport_init); | ||
175 | module_exit(i2c_parport_exit); | ||
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c new file mode 100644 index 000000000000..e9560bab51c4 --- /dev/null +++ b/drivers/i2c/busses/i2c-parport.c | |||
@@ -0,0 +1,267 @@ | |||
1 | /* ------------------------------------------------------------------------ * | ||
2 | * i2c-parport.c I2C bus over parallel port * | ||
3 | * ------------------------------------------------------------------------ * | ||
4 | Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org> | ||
5 | |||
6 | Based on older i2c-philips-par.c driver | ||
7 | Copyright (C) 1995-2000 Simon G. Vogl | ||
8 | With some changes from: | ||
9 | Frodo Looijaard <frodol@dds.nl> | ||
10 | Kyösti Mälkki <kmalkki@cc.hut.fi> | ||
11 | |||
12 | This program is free software; you can redistribute it and/or modify | ||
13 | it under the terms of the GNU General Public License as published by | ||
14 | the Free Software Foundation; either version 2 of the License, or | ||
15 | (at your option) any later version. | ||
16 | |||
17 | This program is distributed in the hope that it will be useful, | ||
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | GNU General Public License for more details. | ||
21 | |||
22 | You should have received a copy of the GNU General Public License | ||
23 | along with this program; if not, write to the Free Software | ||
24 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | * ------------------------------------------------------------------------ */ | ||
26 | |||
27 | #include <linux/config.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/parport.h> | ||
32 | #include <linux/i2c.h> | ||
33 | #include <linux/i2c-algo-bit.h> | ||
34 | #include "i2c-parport.h" | ||
35 | |||
36 | /* ----- Device list ------------------------------------------------------ */ | ||
37 | |||
38 | struct i2c_par { | ||
39 | struct pardevice *pdev; | ||
40 | struct i2c_adapter adapter; | ||
41 | struct i2c_algo_bit_data algo_data; | ||
42 | struct i2c_par *next; | ||
43 | }; | ||
44 | |||
45 | static struct i2c_par *adapter_list; | ||
46 | |||
47 | /* ----- Low-level parallel port access ----------------------------------- */ | ||
48 | |||
49 | static void port_write_data(struct parport *p, unsigned char d) | ||
50 | { | ||
51 | parport_write_data(p, d); | ||
52 | } | ||
53 | |||
54 | static void port_write_control(struct parport *p, unsigned char d) | ||
55 | { | ||
56 | parport_write_control(p, d); | ||
57 | } | ||
58 | |||
59 | static unsigned char port_read_data(struct parport *p) | ||
60 | { | ||
61 | return parport_read_data(p); | ||
62 | } | ||
63 | |||
64 | static unsigned char port_read_status(struct parport *p) | ||
65 | { | ||
66 | return parport_read_status(p); | ||
67 | } | ||
68 | |||
69 | static unsigned char port_read_control(struct parport *p) | ||
70 | { | ||
71 | return parport_read_control(p); | ||
72 | } | ||
73 | |||
74 | static void (*port_write[])(struct parport *, unsigned char) = { | ||
75 | port_write_data, | ||
76 | NULL, | ||
77 | port_write_control, | ||
78 | }; | ||
79 | |||
80 | static unsigned char (*port_read[])(struct parport *) = { | ||
81 | port_read_data, | ||
82 | port_read_status, | ||
83 | port_read_control, | ||
84 | }; | ||
85 | |||
86 | /* ----- Unified line operation functions --------------------------------- */ | ||
87 | |||
88 | static inline void line_set(struct parport *data, int state, | ||
89 | const struct lineop *op) | ||
90 | { | ||
91 | u8 oldval = port_read[op->port](data); | ||
92 | |||
93 | /* Touch only the bit(s) needed */ | ||
94 | if ((op->inverted && !state) || (!op->inverted && state)) | ||
95 | port_write[op->port](data, oldval | op->val); | ||
96 | else | ||
97 | port_write[op->port](data, oldval & ~op->val); | ||
98 | } | ||
99 | |||
100 | static inline int line_get(struct parport *data, | ||
101 | const struct lineop *op) | ||
102 | { | ||
103 | u8 oldval = port_read[op->port](data); | ||
104 | |||
105 | return ((op->inverted && (oldval & op->val) != op->val) | ||
106 | || (!op->inverted && (oldval & op->val) == op->val)); | ||
107 | } | ||
108 | |||
109 | /* ----- I2C algorithm call-back functions and structures ----------------- */ | ||
110 | |||
111 | static void parport_setscl(void *data, int state) | ||
112 | { | ||
113 | line_set((struct parport *) data, state, &adapter_parm[type].setscl); | ||
114 | } | ||
115 | |||
116 | static void parport_setsda(void *data, int state) | ||
117 | { | ||
118 | line_set((struct parport *) data, state, &adapter_parm[type].setsda); | ||
119 | } | ||
120 | |||
121 | static int parport_getscl(void *data) | ||
122 | { | ||
123 | return line_get((struct parport *) data, &adapter_parm[type].getscl); | ||
124 | } | ||
125 | |||
126 | static int parport_getsda(void *data) | ||
127 | { | ||
128 | return line_get((struct parport *) data, &adapter_parm[type].getsda); | ||
129 | } | ||
130 | |||
131 | /* Encapsulate the functions above in the correct structure. | ||
132 | Note that this is only a template, from which the real structures are | ||
133 | copied. The attaching code will set getscl to NULL for adapters that | ||
134 | cannot read SCL back, and will also make the the data field point to | ||
135 | the parallel port structure. */ | ||
136 | static struct i2c_algo_bit_data parport_algo_data = { | ||
137 | .setsda = parport_setsda, | ||
138 | .setscl = parport_setscl, | ||
139 | .getsda = parport_getsda, | ||
140 | .getscl = parport_getscl, | ||
141 | .udelay = 60, | ||
142 | .mdelay = 60, | ||
143 | .timeout = HZ, | ||
144 | }; | ||
145 | |||
146 | /* ----- I2c and parallel port call-back functions and structures --------- */ | ||
147 | |||
148 | static struct i2c_adapter parport_adapter = { | ||
149 | .owner = THIS_MODULE, | ||
150 | .class = I2C_CLASS_HWMON, | ||
151 | .id = I2C_HW_B_LP, | ||
152 | .name = "Parallel port adapter", | ||
153 | }; | ||
154 | |||
155 | static void i2c_parport_attach (struct parport *port) | ||
156 | { | ||
157 | struct i2c_par *adapter; | ||
158 | |||
159 | adapter = kmalloc(sizeof(struct i2c_par), GFP_KERNEL); | ||
160 | if (adapter == NULL) { | ||
161 | printk(KERN_ERR "i2c-parport: Failed to kmalloc\n"); | ||
162 | return; | ||
163 | } | ||
164 | memset(adapter, 0x00, sizeof(struct i2c_par)); | ||
165 | |||
166 | pr_debug("i2c-parport: attaching to %s\n", port->name); | ||
167 | adapter->pdev = parport_register_device(port, "i2c-parport", | ||
168 | NULL, NULL, NULL, PARPORT_FLAG_EXCL, NULL); | ||
169 | if (!adapter->pdev) { | ||
170 | printk(KERN_ERR "i2c-parport: Unable to register with parport\n"); | ||
171 | goto ERROR0; | ||
172 | } | ||
173 | |||
174 | /* Fill the rest of the structure */ | ||
175 | adapter->adapter = parport_adapter; | ||
176 | adapter->algo_data = parport_algo_data; | ||
177 | if (!adapter_parm[type].getscl.val) | ||
178 | adapter->algo_data.getscl = NULL; | ||
179 | adapter->algo_data.data = port; | ||
180 | adapter->adapter.algo_data = &adapter->algo_data; | ||
181 | |||
182 | if (parport_claim_or_block(adapter->pdev) < 0) { | ||
183 | printk(KERN_ERR "i2c-parport: Could not claim parallel port\n"); | ||
184 | goto ERROR1; | ||
185 | } | ||
186 | |||
187 | /* Reset hardware to a sane state (SCL and SDA high) */ | ||
188 | parport_setsda(port, 1); | ||
189 | parport_setscl(port, 1); | ||
190 | /* Other init if needed (power on...) */ | ||
191 | if (adapter_parm[type].init.val) | ||
192 | line_set(port, 1, &adapter_parm[type].init); | ||
193 | |||
194 | parport_release(adapter->pdev); | ||
195 | |||
196 | if (i2c_bit_add_bus(&adapter->adapter) < 0) { | ||
197 | printk(KERN_ERR "i2c-parport: Unable to register with I2C\n"); | ||
198 | goto ERROR1; | ||
199 | } | ||
200 | |||
201 | /* Add the new adapter to the list */ | ||
202 | adapter->next = adapter_list; | ||
203 | adapter_list = adapter; | ||
204 | return; | ||
205 | |||
206 | ERROR1: | ||
207 | parport_unregister_device(adapter->pdev); | ||
208 | ERROR0: | ||
209 | kfree(adapter); | ||
210 | } | ||
211 | |||
212 | static void i2c_parport_detach (struct parport *port) | ||
213 | { | ||
214 | struct i2c_par *adapter, *prev; | ||
215 | |||
216 | /* Walk the list */ | ||
217 | for (prev = NULL, adapter = adapter_list; adapter; | ||
218 | prev = adapter, adapter = adapter->next) { | ||
219 | if (adapter->pdev->port == port) { | ||
220 | /* Un-init if needed (power off...) */ | ||
221 | if (adapter_parm[type].init.val) | ||
222 | line_set(port, 0, &adapter_parm[type].init); | ||
223 | |||
224 | i2c_bit_del_bus(&adapter->adapter); | ||
225 | parport_unregister_device(adapter->pdev); | ||
226 | if (prev) | ||
227 | prev->next = adapter->next; | ||
228 | else | ||
229 | adapter_list = adapter->next; | ||
230 | kfree(adapter); | ||
231 | return; | ||
232 | } | ||
233 | } | ||
234 | } | ||
235 | |||
236 | static struct parport_driver i2c_driver = { | ||
237 | .name = "i2c-parport", | ||
238 | .attach = i2c_parport_attach, | ||
239 | .detach = i2c_parport_detach, | ||
240 | }; | ||
241 | |||
242 | /* ----- Module loading, unloading and information ------------------------ */ | ||
243 | |||
244 | static int __init i2c_parport_init(void) | ||
245 | { | ||
246 | int type_count; | ||
247 | |||
248 | type_count = sizeof(adapter_parm)/sizeof(struct adapter_parm); | ||
249 | if (type < 0 || type >= type_count) { | ||
250 | printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type); | ||
251 | type = 0; | ||
252 | } | ||
253 | |||
254 | return parport_register_driver(&i2c_driver); | ||
255 | } | ||
256 | |||
257 | static void __exit i2c_parport_exit(void) | ||
258 | { | ||
259 | parport_unregister_driver(&i2c_driver); | ||
260 | } | ||
261 | |||
262 | MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); | ||
263 | MODULE_DESCRIPTION("I2C bus over parallel port"); | ||
264 | MODULE_LICENSE("GPL"); | ||
265 | |||
266 | module_init(i2c_parport_init); | ||
267 | module_exit(i2c_parport_exit); | ||
diff --git a/drivers/i2c/busses/i2c-parport.h b/drivers/i2c/busses/i2c-parport.h new file mode 100644 index 000000000000..f63a53779281 --- /dev/null +++ b/drivers/i2c/busses/i2c-parport.h | |||
@@ -0,0 +1,94 @@ | |||
1 | /* ------------------------------------------------------------------------ * | ||
2 | * i2c-parport.h I2C bus over parallel port * | ||
3 | * ------------------------------------------------------------------------ * | ||
4 | Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org> | ||
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 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | * ------------------------------------------------------------------------ */ | ||
20 | |||
21 | #ifdef DATA | ||
22 | #undef DATA | ||
23 | #endif | ||
24 | |||
25 | #define DATA 0 | ||
26 | #define STAT 1 | ||
27 | #define CTRL 2 | ||
28 | |||
29 | struct lineop { | ||
30 | u8 val; | ||
31 | u8 port; | ||
32 | u8 inverted; | ||
33 | }; | ||
34 | |||
35 | struct adapter_parm { | ||
36 | struct lineop setsda; | ||
37 | struct lineop setscl; | ||
38 | struct lineop getsda; | ||
39 | struct lineop getscl; | ||
40 | struct lineop init; | ||
41 | }; | ||
42 | |||
43 | static struct adapter_parm adapter_parm[] = { | ||
44 | /* type 0: Philips adapter */ | ||
45 | { | ||
46 | .setsda = { 0x80, DATA, 1 }, | ||
47 | .setscl = { 0x08, CTRL, 0 }, | ||
48 | .getsda = { 0x80, STAT, 0 }, | ||
49 | .getscl = { 0x08, STAT, 0 }, | ||
50 | }, | ||
51 | /* type 1: home brew teletext adapter */ | ||
52 | { | ||
53 | .setsda = { 0x02, DATA, 0 }, | ||
54 | .setscl = { 0x01, DATA, 0 }, | ||
55 | .getsda = { 0x80, STAT, 1 }, | ||
56 | }, | ||
57 | /* type 2: Velleman K8000 adapter */ | ||
58 | { | ||
59 | .setsda = { 0x02, CTRL, 1 }, | ||
60 | .setscl = { 0x08, CTRL, 1 }, | ||
61 | .getsda = { 0x10, STAT, 0 }, | ||
62 | }, | ||
63 | /* type 3: ELV adapter */ | ||
64 | { | ||
65 | .setsda = { 0x02, DATA, 1 }, | ||
66 | .setscl = { 0x01, DATA, 1 }, | ||
67 | .getsda = { 0x40, STAT, 1 }, | ||
68 | .getscl = { 0x08, STAT, 1 }, | ||
69 | }, | ||
70 | /* type 4: ADM1032 evaluation board */ | ||
71 | { | ||
72 | .setsda = { 0x02, DATA, 1 }, | ||
73 | .setscl = { 0x01, DATA, 1 }, | ||
74 | .getsda = { 0x10, STAT, 1 }, | ||
75 | .init = { 0xf0, DATA, 0 }, | ||
76 | }, | ||
77 | /* type 5: ADM1025, ADM1030 and ADM1031 evaluation boards */ | ||
78 | { | ||
79 | .setsda = { 0x02, DATA, 1 }, | ||
80 | .setscl = { 0x01, DATA, 1 }, | ||
81 | .getsda = { 0x10, STAT, 1 }, | ||
82 | }, | ||
83 | }; | ||
84 | |||
85 | static int type; | ||
86 | module_param(type, int, 0); | ||
87 | MODULE_PARM_DESC(type, | ||
88 | "Type of adapter:\n" | ||
89 | " 0 = Philips adapter\n" | ||
90 | " 1 = home brew teletext adapter\n" | ||
91 | " 2 = Velleman K8000 adapter\n" | ||
92 | " 3 = ELV adapter\n" | ||
93 | " 4 = ADM1032 evaluation board\n" | ||
94 | " 5 = ADM1025, ADM1030 and ADM1031 evaluation boards\n"); | ||
diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c new file mode 100644 index 000000000000..9c611134db9c --- /dev/null +++ b/drivers/i2c/busses/i2c-pca-isa.c | |||
@@ -0,0 +1,184 @@ | |||
1 | /* | ||
2 | * i2c-pca-isa.c driver for PCA9564 on ISA boards | ||
3 | * Copyright (C) 2004 Arcom Control Systems | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/config.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/ioport.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/moduleparam.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/pci.h> | ||
30 | #include <linux/wait.h> | ||
31 | |||
32 | #include <linux/i2c.h> | ||
33 | #include <linux/i2c-algo-pca.h> | ||
34 | |||
35 | #include <asm/io.h> | ||
36 | #include <asm/irq.h> | ||
37 | |||
38 | #include "../algos/i2c-algo-pca.h" | ||
39 | |||
40 | #define IO_SIZE 4 | ||
41 | |||
42 | #undef DEBUG_IO | ||
43 | //#define DEBUG_IO | ||
44 | |||
45 | static unsigned long base = 0x330; | ||
46 | static int irq = 10; | ||
47 | |||
48 | /* Data sheet recommends 59kHz for 100kHz operation due to variation | ||
49 | * in the actual clock rate */ | ||
50 | static int clock = I2C_PCA_CON_59kHz; | ||
51 | |||
52 | static int own = 0x55; | ||
53 | |||
54 | static wait_queue_head_t pca_wait; | ||
55 | |||
56 | static int pca_isa_getown(struct i2c_algo_pca_data *adap) | ||
57 | { | ||
58 | return (own); | ||
59 | } | ||
60 | |||
61 | static int pca_isa_getclock(struct i2c_algo_pca_data *adap) | ||
62 | { | ||
63 | return (clock); | ||
64 | } | ||
65 | |||
66 | static void | ||
67 | pca_isa_writebyte(struct i2c_algo_pca_data *adap, int reg, int val) | ||
68 | { | ||
69 | #ifdef DEBUG_IO | ||
70 | static char *names[] = { "T/O", "DAT", "ADR", "CON" }; | ||
71 | printk("*** write %s at %#lx <= %#04x\n", names[reg], base+reg, val); | ||
72 | #endif | ||
73 | outb(val, base+reg); | ||
74 | } | ||
75 | |||
76 | static int | ||
77 | pca_isa_readbyte(struct i2c_algo_pca_data *adap, int reg) | ||
78 | { | ||
79 | int res = inb(base+reg); | ||
80 | #ifdef DEBUG_IO | ||
81 | { | ||
82 | static char *names[] = { "STA", "DAT", "ADR", "CON" }; | ||
83 | printk("*** read %s => %#04x\n", names[reg], res); | ||
84 | } | ||
85 | #endif | ||
86 | return res; | ||
87 | } | ||
88 | |||
89 | static int pca_isa_waitforinterrupt(struct i2c_algo_pca_data *adap) | ||
90 | { | ||
91 | int ret = 0; | ||
92 | |||
93 | if (irq > -1) { | ||
94 | ret = wait_event_interruptible(pca_wait, | ||
95 | pca_isa_readbyte(adap, I2C_PCA_CON) & I2C_PCA_CON_SI); | ||
96 | } else { | ||
97 | while ((pca_isa_readbyte(adap, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0) | ||
98 | udelay(100); | ||
99 | } | ||
100 | return ret; | ||
101 | } | ||
102 | |||
103 | static irqreturn_t pca_handler(int this_irq, void *dev_id, struct pt_regs *regs) { | ||
104 | wake_up_interruptible(&pca_wait); | ||
105 | return IRQ_HANDLED; | ||
106 | } | ||
107 | |||
108 | static struct i2c_algo_pca_data pca_isa_data = { | ||
109 | .get_own = pca_isa_getown, | ||
110 | .get_clock = pca_isa_getclock, | ||
111 | .write_byte = pca_isa_writebyte, | ||
112 | .read_byte = pca_isa_readbyte, | ||
113 | .wait_for_interrupt = pca_isa_waitforinterrupt, | ||
114 | }; | ||
115 | |||
116 | static struct i2c_adapter pca_isa_ops = { | ||
117 | .owner = THIS_MODULE, | ||
118 | .id = I2C_HW_A_ISA, | ||
119 | .algo_data = &pca_isa_data, | ||
120 | .name = "PCA9564 ISA Adapter", | ||
121 | }; | ||
122 | |||
123 | static int __init pca_isa_init(void) | ||
124 | { | ||
125 | |||
126 | init_waitqueue_head(&pca_wait); | ||
127 | |||
128 | printk(KERN_INFO "i2c-pca-isa: i/o base %#08lx. irq %d\n", base, irq); | ||
129 | |||
130 | if (!request_region(base, IO_SIZE, "i2c-pca-isa")) { | ||
131 | printk(KERN_ERR "i2c-pca-isa: I/O address %#08lx is in use.\n", base); | ||
132 | goto out; | ||
133 | } | ||
134 | |||
135 | if (irq > -1) { | ||
136 | if (request_irq(irq, pca_handler, 0, "i2c-pca-isa", &pca_isa_ops) < 0) { | ||
137 | printk(KERN_ERR "i2c-pca-isa: Request irq%d failed\n", irq); | ||
138 | goto out_region; | ||
139 | } | ||
140 | } | ||
141 | |||
142 | if (i2c_pca_add_bus(&pca_isa_ops) < 0) { | ||
143 | printk(KERN_ERR "i2c-pca-isa: Failed to add i2c bus\n"); | ||
144 | goto out_irq; | ||
145 | } | ||
146 | |||
147 | return 0; | ||
148 | |||
149 | out_irq: | ||
150 | if (irq > -1) | ||
151 | free_irq(irq, &pca_isa_ops); | ||
152 | out_region: | ||
153 | release_region(base, IO_SIZE); | ||
154 | out: | ||
155 | return -ENODEV; | ||
156 | } | ||
157 | |||
158 | static void pca_isa_exit(void) | ||
159 | { | ||
160 | i2c_pca_del_bus(&pca_isa_ops); | ||
161 | |||
162 | if (irq > 0) { | ||
163 | disable_irq(irq); | ||
164 | free_irq(irq, &pca_isa_ops); | ||
165 | } | ||
166 | release_region(base, IO_SIZE); | ||
167 | } | ||
168 | |||
169 | MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>"); | ||
170 | MODULE_DESCRIPTION("ISA base PCA9564 driver"); | ||
171 | MODULE_LICENSE("GPL"); | ||
172 | |||
173 | module_param(base, ulong, 0); | ||
174 | MODULE_PARM_DESC(base, "I/O base address"); | ||
175 | |||
176 | module_param(irq, int, 0); | ||
177 | MODULE_PARM_DESC(irq, "IRQ"); | ||
178 | module_param(clock, int, 0); | ||
179 | MODULE_PARM_DESC(clock, "Clock rate as described in table 1 of PCA9564 datasheet"); | ||
180 | |||
181 | module_param(own, int, 0); /* the driver can't do slave mode, so there's no real point in this */ | ||
182 | |||
183 | module_init(pca_isa_init); | ||
184 | module_exit(pca_isa_exit); | ||
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c new file mode 100644 index 000000000000..646381b6b3bf --- /dev/null +++ b/drivers/i2c/busses/i2c-piix4.c | |||
@@ -0,0 +1,490 @@ | |||
1 | /* | ||
2 | piix4.c - Part of lm_sensors, Linux kernel modules for hardware | ||
3 | monitoring | ||
4 | Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl> and | ||
5 | Philip Edelbrock <phil@netroedge.com> | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | /* | ||
23 | Supports: | ||
24 | Intel PIIX4, 440MX | ||
25 | Serverworks OSB4, CSB5, CSB6 | ||
26 | SMSC Victory66 | ||
27 | |||
28 | Note: we assume there can only be one device, with one SMBus interface. | ||
29 | */ | ||
30 | |||
31 | #include <linux/config.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/moduleparam.h> | ||
34 | #include <linux/pci.h> | ||
35 | #include <linux/kernel.h> | ||
36 | #include <linux/delay.h> | ||
37 | #include <linux/stddef.h> | ||
38 | #include <linux/sched.h> | ||
39 | #include <linux/ioport.h> | ||
40 | #include <linux/i2c.h> | ||
41 | #include <linux/init.h> | ||
42 | #include <linux/apm_bios.h> | ||
43 | #include <linux/dmi.h> | ||
44 | #include <asm/io.h> | ||
45 | |||
46 | |||
47 | struct sd { | ||
48 | const unsigned short mfr; | ||
49 | const unsigned short dev; | ||
50 | const unsigned char fn; | ||
51 | const char *name; | ||
52 | }; | ||
53 | |||
54 | /* PIIX4 SMBus address offsets */ | ||
55 | #define SMBHSTSTS (0 + piix4_smba) | ||
56 | #define SMBHSLVSTS (1 + piix4_smba) | ||
57 | #define SMBHSTCNT (2 + piix4_smba) | ||
58 | #define SMBHSTCMD (3 + piix4_smba) | ||
59 | #define SMBHSTADD (4 + piix4_smba) | ||
60 | #define SMBHSTDAT0 (5 + piix4_smba) | ||
61 | #define SMBHSTDAT1 (6 + piix4_smba) | ||
62 | #define SMBBLKDAT (7 + piix4_smba) | ||
63 | #define SMBSLVCNT (8 + piix4_smba) | ||
64 | #define SMBSHDWCMD (9 + piix4_smba) | ||
65 | #define SMBSLVEVT (0xA + piix4_smba) | ||
66 | #define SMBSLVDAT (0xC + piix4_smba) | ||
67 | |||
68 | /* count for request_region */ | ||
69 | #define SMBIOSIZE 8 | ||
70 | |||
71 | /* PCI Address Constants */ | ||
72 | #define SMBBA 0x090 | ||
73 | #define SMBHSTCFG 0x0D2 | ||
74 | #define SMBSLVC 0x0D3 | ||
75 | #define SMBSHDW1 0x0D4 | ||
76 | #define SMBSHDW2 0x0D5 | ||
77 | #define SMBREV 0x0D6 | ||
78 | |||
79 | /* Other settings */ | ||
80 | #define MAX_TIMEOUT 500 | ||
81 | #define ENABLE_INT9 0 | ||
82 | |||
83 | /* PIIX4 constants */ | ||
84 | #define PIIX4_QUICK 0x00 | ||
85 | #define PIIX4_BYTE 0x04 | ||
86 | #define PIIX4_BYTE_DATA 0x08 | ||
87 | #define PIIX4_WORD_DATA 0x0C | ||
88 | #define PIIX4_BLOCK_DATA 0x14 | ||
89 | |||
90 | /* insmod parameters */ | ||
91 | |||
92 | /* If force is set to anything different from 0, we forcibly enable the | ||
93 | PIIX4. DANGEROUS! */ | ||
94 | static int force = 0; | ||
95 | module_param (force, int, 0); | ||
96 | MODULE_PARM_DESC(force, "Forcibly enable the PIIX4. DANGEROUS!"); | ||
97 | |||
98 | /* If force_addr is set to anything different from 0, we forcibly enable | ||
99 | the PIIX4 at the given address. VERY DANGEROUS! */ | ||
100 | static int force_addr = 0; | ||
101 | module_param (force_addr, int, 0); | ||
102 | MODULE_PARM_DESC(force_addr, | ||
103 | "Forcibly enable the PIIX4 at the given address. " | ||
104 | "EXTREMELY DANGEROUS!"); | ||
105 | |||
106 | /* If fix_hstcfg is set to anything different from 0, we reset one of the | ||
107 | registers to be a valid value. */ | ||
108 | static int fix_hstcfg = 0; | ||
109 | module_param (fix_hstcfg, int, 0); | ||
110 | MODULE_PARM_DESC(fix_hstcfg, | ||
111 | "Fix config register. Needed on some boards (Force CPCI735)."); | ||
112 | |||
113 | static int piix4_transaction(void); | ||
114 | |||
115 | static unsigned short piix4_smba = 0; | ||
116 | static struct i2c_adapter piix4_adapter; | ||
117 | |||
118 | static struct dmi_system_id __devinitdata piix4_dmi_table[] = { | ||
119 | { | ||
120 | .ident = "IBM", | ||
121 | .matches = { DMI_MATCH(DMI_SYS_VENDOR, "IBM"), }, | ||
122 | }, | ||
123 | { }, | ||
124 | }; | ||
125 | |||
126 | static int __devinit piix4_setup(struct pci_dev *PIIX4_dev, | ||
127 | const struct pci_device_id *id) | ||
128 | { | ||
129 | unsigned char temp; | ||
130 | |||
131 | /* match up the function */ | ||
132 | if (PCI_FUNC(PIIX4_dev->devfn) != id->driver_data) | ||
133 | return -ENODEV; | ||
134 | |||
135 | dev_info(&PIIX4_dev->dev, "Found %s device\n", pci_name(PIIX4_dev)); | ||
136 | |||
137 | /* Don't access SMBus on IBM systems which get corrupted eeproms */ | ||
138 | if (dmi_check_system(piix4_dmi_table) && | ||
139 | PIIX4_dev->vendor == PCI_VENDOR_ID_INTEL) { | ||
140 | dev_err(&PIIX4_dev->dev, "IBM Laptop detected; this module " | ||
141 | "may corrupt your serial eeprom! Refusing to load " | ||
142 | "module!\n"); | ||
143 | return -EPERM; | ||
144 | } | ||
145 | |||
146 | /* Determine the address of the SMBus areas */ | ||
147 | if (force_addr) { | ||
148 | piix4_smba = force_addr & 0xfff0; | ||
149 | force = 0; | ||
150 | } else { | ||
151 | pci_read_config_word(PIIX4_dev, SMBBA, &piix4_smba); | ||
152 | piix4_smba &= 0xfff0; | ||
153 | if(piix4_smba == 0) { | ||
154 | dev_err(&PIIX4_dev->dev, "SMB base address " | ||
155 | "uninitialized - upgrade BIOS or use " | ||
156 | "force_addr=0xaddr\n"); | ||
157 | return -ENODEV; | ||
158 | } | ||
159 | } | ||
160 | |||
161 | if (!request_region(piix4_smba, SMBIOSIZE, "piix4-smbus")) { | ||
162 | dev_err(&PIIX4_dev->dev, "SMB region 0x%x already in use!\n", | ||
163 | piix4_smba); | ||
164 | return -ENODEV; | ||
165 | } | ||
166 | |||
167 | pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp); | ||
168 | |||
169 | /* Some BIOS will set up the chipset incorrectly and leave a register | ||
170 | in an undefined state (causing I2C to act very strangely). */ | ||
171 | if (temp & 0x02) { | ||
172 | if (fix_hstcfg) { | ||
173 | dev_info(&PIIX4_dev->dev, "Working around buggy BIOS " | ||
174 | "(I2C)\n"); | ||
175 | temp &= 0xfd; | ||
176 | pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp); | ||
177 | } else { | ||
178 | dev_info(&PIIX4_dev->dev, "Unusual config register " | ||
179 | "value\n"); | ||
180 | dev_info(&PIIX4_dev->dev, "Try using fix_hstcfg=1 if " | ||
181 | "you experience problems\n"); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | /* If force_addr is set, we program the new address here. Just to make | ||
186 | sure, we disable the PIIX4 first. */ | ||
187 | if (force_addr) { | ||
188 | pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp & 0xfe); | ||
189 | pci_write_config_word(PIIX4_dev, SMBBA, piix4_smba); | ||
190 | pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp | 0x01); | ||
191 | dev_info(&PIIX4_dev->dev, "WARNING: SMBus interface set to " | ||
192 | "new address %04x!\n", piix4_smba); | ||
193 | } else if ((temp & 1) == 0) { | ||
194 | if (force) { | ||
195 | /* This should never need to be done, but has been | ||
196 | * noted that many Dell machines have the SMBus | ||
197 | * interface on the PIIX4 disabled!? NOTE: This assumes | ||
198 | * I/O space and other allocations WERE done by the | ||
199 | * Bios! Don't complain if your hardware does weird | ||
200 | * things after enabling this. :') Check for Bios | ||
201 | * updates before resorting to this. | ||
202 | */ | ||
203 | pci_write_config_byte(PIIX4_dev, SMBHSTCFG, | ||
204 | temp | 1); | ||
205 | dev_printk(KERN_NOTICE, &PIIX4_dev->dev, | ||
206 | "WARNING: SMBus interface has been " | ||
207 | "FORCEFULLY ENABLED!\n"); | ||
208 | } else { | ||
209 | dev_err(&PIIX4_dev->dev, | ||
210 | "Host SMBus controller not enabled!\n"); | ||
211 | release_region(piix4_smba, SMBIOSIZE); | ||
212 | piix4_smba = 0; | ||
213 | return -ENODEV; | ||
214 | } | ||
215 | } | ||
216 | |||
217 | if ((temp & 0x0E) == 8) | ||
218 | dev_dbg(&PIIX4_dev->dev, "Using Interrupt 9 for SMBus.\n"); | ||
219 | else if ((temp & 0x0E) == 0) | ||
220 | dev_dbg(&PIIX4_dev->dev, "Using Interrupt SMI# for SMBus.\n"); | ||
221 | else | ||
222 | dev_err(&PIIX4_dev->dev, "Illegal Interrupt configuration " | ||
223 | "(or code out of date)!\n"); | ||
224 | |||
225 | pci_read_config_byte(PIIX4_dev, SMBREV, &temp); | ||
226 | dev_dbg(&PIIX4_dev->dev, "SMBREV = 0x%X\n", temp); | ||
227 | dev_dbg(&PIIX4_dev->dev, "SMBA = 0x%X\n", piix4_smba); | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | /* Another internally used function */ | ||
233 | static int piix4_transaction(void) | ||
234 | { | ||
235 | int temp; | ||
236 | int result = 0; | ||
237 | int timeout = 0; | ||
238 | |||
239 | dev_dbg(&piix4_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, " | ||
240 | "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), | ||
241 | inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), | ||
242 | inb_p(SMBHSTDAT1)); | ||
243 | |||
244 | /* Make sure the SMBus host is ready to start transmitting */ | ||
245 | if ((temp = inb_p(SMBHSTSTS)) != 0x00) { | ||
246 | dev_dbg(&piix4_adapter.dev, "SMBus busy (%02x). " | ||
247 | "Resetting... \n", temp); | ||
248 | outb_p(temp, SMBHSTSTS); | ||
249 | if ((temp = inb_p(SMBHSTSTS)) != 0x00) { | ||
250 | dev_err(&piix4_adapter.dev, "Failed! (%02x)\n", temp); | ||
251 | return -1; | ||
252 | } else { | ||
253 | dev_dbg(&piix4_adapter.dev, "Successfull!\n"); | ||
254 | } | ||
255 | } | ||
256 | |||
257 | /* start the transaction by setting bit 6 */ | ||
258 | outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT); | ||
259 | |||
260 | /* We will always wait for a fraction of a second! (See PIIX4 docs errata) */ | ||
261 | do { | ||
262 | msleep(1); | ||
263 | temp = inb_p(SMBHSTSTS); | ||
264 | } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT)); | ||
265 | |||
266 | /* If the SMBus is still busy, we give up */ | ||
267 | if (timeout >= MAX_TIMEOUT) { | ||
268 | dev_err(&piix4_adapter.dev, "SMBus Timeout!\n"); | ||
269 | result = -1; | ||
270 | } | ||
271 | |||
272 | if (temp & 0x10) { | ||
273 | result = -1; | ||
274 | dev_err(&piix4_adapter.dev, "Error: Failed bus transaction\n"); | ||
275 | } | ||
276 | |||
277 | if (temp & 0x08) { | ||
278 | result = -1; | ||
279 | dev_dbg(&piix4_adapter.dev, "Bus collision! SMBus may be " | ||
280 | "locked until next hard reset. (sorry!)\n"); | ||
281 | /* Clock stops and slave is stuck in mid-transmission */ | ||
282 | } | ||
283 | |||
284 | if (temp & 0x04) { | ||
285 | result = -1; | ||
286 | dev_dbg(&piix4_adapter.dev, "Error: no response!\n"); | ||
287 | } | ||
288 | |||
289 | if (inb_p(SMBHSTSTS) != 0x00) | ||
290 | outb_p(inb(SMBHSTSTS), SMBHSTSTS); | ||
291 | |||
292 | if ((temp = inb_p(SMBHSTSTS)) != 0x00) { | ||
293 | dev_err(&piix4_adapter.dev, "Failed reset at end of " | ||
294 | "transaction (%02x)\n", temp); | ||
295 | } | ||
296 | dev_dbg(&piix4_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, " | ||
297 | "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), | ||
298 | inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), | ||
299 | inb_p(SMBHSTDAT1)); | ||
300 | return result; | ||
301 | } | ||
302 | |||
303 | /* Return -1 on error. */ | ||
304 | static s32 piix4_access(struct i2c_adapter * adap, u16 addr, | ||
305 | unsigned short flags, char read_write, | ||
306 | u8 command, int size, union i2c_smbus_data * data) | ||
307 | { | ||
308 | int i, len; | ||
309 | |||
310 | switch (size) { | ||
311 | case I2C_SMBUS_PROC_CALL: | ||
312 | dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n"); | ||
313 | return -1; | ||
314 | case I2C_SMBUS_QUICK: | ||
315 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
316 | SMBHSTADD); | ||
317 | size = PIIX4_QUICK; | ||
318 | break; | ||
319 | case I2C_SMBUS_BYTE: | ||
320 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
321 | SMBHSTADD); | ||
322 | if (read_write == I2C_SMBUS_WRITE) | ||
323 | outb_p(command, SMBHSTCMD); | ||
324 | size = PIIX4_BYTE; | ||
325 | break; | ||
326 | case I2C_SMBUS_BYTE_DATA: | ||
327 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
328 | SMBHSTADD); | ||
329 | outb_p(command, SMBHSTCMD); | ||
330 | if (read_write == I2C_SMBUS_WRITE) | ||
331 | outb_p(data->byte, SMBHSTDAT0); | ||
332 | size = PIIX4_BYTE_DATA; | ||
333 | break; | ||
334 | case I2C_SMBUS_WORD_DATA: | ||
335 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
336 | SMBHSTADD); | ||
337 | outb_p(command, SMBHSTCMD); | ||
338 | if (read_write == I2C_SMBUS_WRITE) { | ||
339 | outb_p(data->word & 0xff, SMBHSTDAT0); | ||
340 | outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); | ||
341 | } | ||
342 | size = PIIX4_WORD_DATA; | ||
343 | break; | ||
344 | case I2C_SMBUS_BLOCK_DATA: | ||
345 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
346 | SMBHSTADD); | ||
347 | outb_p(command, SMBHSTCMD); | ||
348 | if (read_write == I2C_SMBUS_WRITE) { | ||
349 | len = data->block[0]; | ||
350 | if (len < 0) | ||
351 | len = 0; | ||
352 | if (len > 32) | ||
353 | len = 32; | ||
354 | outb_p(len, SMBHSTDAT0); | ||
355 | i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ | ||
356 | for (i = 1; i <= len; i++) | ||
357 | outb_p(data->block[i], SMBBLKDAT); | ||
358 | } | ||
359 | size = PIIX4_BLOCK_DATA; | ||
360 | break; | ||
361 | } | ||
362 | |||
363 | outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT); | ||
364 | |||
365 | if (piix4_transaction()) /* Error in transaction */ | ||
366 | return -1; | ||
367 | |||
368 | if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK)) | ||
369 | return 0; | ||
370 | |||
371 | |||
372 | switch (size) { | ||
373 | case PIIX4_BYTE: /* Where is the result put? I assume here it is in | ||
374 | SMBHSTDAT0 but it might just as well be in the | ||
375 | SMBHSTCMD. No clue in the docs */ | ||
376 | |||
377 | data->byte = inb_p(SMBHSTDAT0); | ||
378 | break; | ||
379 | case PIIX4_BYTE_DATA: | ||
380 | data->byte = inb_p(SMBHSTDAT0); | ||
381 | break; | ||
382 | case PIIX4_WORD_DATA: | ||
383 | data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); | ||
384 | break; | ||
385 | case PIIX4_BLOCK_DATA: | ||
386 | data->block[0] = inb_p(SMBHSTDAT0); | ||
387 | i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ | ||
388 | for (i = 1; i <= data->block[0]; i++) | ||
389 | data->block[i] = inb_p(SMBBLKDAT); | ||
390 | break; | ||
391 | } | ||
392 | return 0; | ||
393 | } | ||
394 | |||
395 | static u32 piix4_func(struct i2c_adapter *adapter) | ||
396 | { | ||
397 | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | | ||
398 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | | ||
399 | I2C_FUNC_SMBUS_BLOCK_DATA; | ||
400 | } | ||
401 | |||
402 | static struct i2c_algorithm smbus_algorithm = { | ||
403 | .name = "Non-I2C SMBus adapter", | ||
404 | .id = I2C_ALGO_SMBUS, | ||
405 | .smbus_xfer = piix4_access, | ||
406 | .functionality = piix4_func, | ||
407 | }; | ||
408 | |||
409 | static struct i2c_adapter piix4_adapter = { | ||
410 | .owner = THIS_MODULE, | ||
411 | .class = I2C_CLASS_HWMON, | ||
412 | .algo = &smbus_algorithm, | ||
413 | .name = "unset", | ||
414 | }; | ||
415 | |||
416 | static struct pci_device_id piix4_ids[] = { | ||
417 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3), | ||
418 | .driver_data = 3 }, | ||
419 | { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4), | ||
420 | .driver_data = 0 }, | ||
421 | { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5), | ||
422 | .driver_data = 0 }, | ||
423 | { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6), | ||
424 | .driver_data = 0 }, | ||
425 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3), | ||
426 | .driver_data = 3 }, | ||
427 | { PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3), | ||
428 | .driver_data = 0 }, | ||
429 | { 0, } | ||
430 | }; | ||
431 | |||
432 | MODULE_DEVICE_TABLE (pci, piix4_ids); | ||
433 | |||
434 | static int __devinit piix4_probe(struct pci_dev *dev, | ||
435 | const struct pci_device_id *id) | ||
436 | { | ||
437 | int retval; | ||
438 | |||
439 | retval = piix4_setup(dev, id); | ||
440 | if (retval) | ||
441 | return retval; | ||
442 | |||
443 | /* set up the driverfs linkage to our parent device */ | ||
444 | piix4_adapter.dev.parent = &dev->dev; | ||
445 | |||
446 | snprintf(piix4_adapter.name, I2C_NAME_SIZE, | ||
447 | "SMBus PIIX4 adapter at %04x", piix4_smba); | ||
448 | |||
449 | if ((retval = i2c_add_adapter(&piix4_adapter))) { | ||
450 | dev_err(&dev->dev, "Couldn't register adapter!\n"); | ||
451 | release_region(piix4_smba, SMBIOSIZE); | ||
452 | piix4_smba = 0; | ||
453 | } | ||
454 | |||
455 | return retval; | ||
456 | } | ||
457 | |||
458 | static void __devexit piix4_remove(struct pci_dev *dev) | ||
459 | { | ||
460 | if (piix4_smba) { | ||
461 | i2c_del_adapter(&piix4_adapter); | ||
462 | release_region(piix4_smba, SMBIOSIZE); | ||
463 | piix4_smba = 0; | ||
464 | } | ||
465 | } | ||
466 | |||
467 | static struct pci_driver piix4_driver = { | ||
468 | .name = "piix4_smbus", | ||
469 | .id_table = piix4_ids, | ||
470 | .probe = piix4_probe, | ||
471 | .remove = __devexit_p(piix4_remove), | ||
472 | }; | ||
473 | |||
474 | static int __init i2c_piix4_init(void) | ||
475 | { | ||
476 | return pci_register_driver(&piix4_driver); | ||
477 | } | ||
478 | |||
479 | static void __exit i2c_piix4_exit(void) | ||
480 | { | ||
481 | pci_unregister_driver(&piix4_driver); | ||
482 | } | ||
483 | |||
484 | MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and " | ||
485 | "Philip Edelbrock <phil@netroedge.com>"); | ||
486 | MODULE_DESCRIPTION("PIIX4 SMBus driver"); | ||
487 | MODULE_LICENSE("GPL"); | ||
488 | |||
489 | module_init(i2c_piix4_init); | ||
490 | module_exit(i2c_piix4_exit); | ||
diff --git a/drivers/i2c/busses/i2c-prosavage.c b/drivers/i2c/busses/i2c-prosavage.c new file mode 100644 index 000000000000..13d66289933b --- /dev/null +++ b/drivers/i2c/busses/i2c-prosavage.c | |||
@@ -0,0 +1,334 @@ | |||
1 | /* | ||
2 | * kernel/busses/i2c-prosavage.c | ||
3 | * | ||
4 | * i2c bus driver for S3/VIA 8365/8375 graphics processor. | ||
5 | * Copyright (c) 2003 Henk Vergonet <henk@god.dyndns.org> | ||
6 | * Based on code written by: | ||
7 | * Frodo Looijaard <frodol@dds.nl>, | ||
8 | * Philip Edelbrock <phil@netroedge.com>, | ||
9 | * Ralph Metzler <rjkm@thp.uni-koeln.de>, and | ||
10 | * Mark D. Studebaker <mdsxyz123@yahoo.com> | ||
11 | * Simon Vogl | ||
12 | * and others | ||
13 | * | ||
14 | * Please read the lm_sensors documentation for details on use. | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License as published by | ||
18 | * the Free Software Foundation; either version 2 of the License, or | ||
19 | * (at your option) any later version. | ||
20 | * | ||
21 | * This program is distributed in the hope that it will be useful, | ||
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
24 | * GNU General Public License for more details. | ||
25 | * | ||
26 | * You should have received a copy of the GNU General Public License | ||
27 | * along with this program; if not, write to the Free Software | ||
28 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
29 | * | ||
30 | */ | ||
31 | /* 18-05-2003 HVE - created | ||
32 | * 14-06-2003 HVE - adapted for lm_sensors2 | ||
33 | * 17-06-2003 HVE - linux 2.5.xx compatible | ||
34 | * 18-06-2003 HVE - codingstyle | ||
35 | * 21-06-2003 HVE - compatibility lm_sensors2 and linux 2.5.xx | ||
36 | * codingstyle, mmio enabled | ||
37 | * | ||
38 | * This driver interfaces to the I2C bus of the VIA north bridge embedded | ||
39 | * ProSavage4/8 devices. Usefull for gaining access to the TV Encoder chips. | ||
40 | * | ||
41 | * Graphics cores: | ||
42 | * S3/VIA KM266/VT8375 aka ProSavage8 | ||
43 | * S3/VIA KM133/VT8365 aka Savage4 | ||
44 | * | ||
45 | * Two serial busses are implemented: | ||
46 | * SERIAL1 - I2C serial communications interface | ||
47 | * SERIAL2 - DDC2 monitor communications interface | ||
48 | * | ||
49 | * Tested on a FX41 mainboard, see http://www.shuttle.com | ||
50 | * | ||
51 | * | ||
52 | * TODO: | ||
53 | * - integration with prosavage framebuffer device | ||
54 | * (Additional documentation needed :( | ||
55 | */ | ||
56 | |||
57 | #include <linux/config.h> | ||
58 | #include <linux/module.h> | ||
59 | #include <linux/init.h> | ||
60 | #include <linux/pci.h> | ||
61 | #include <linux/i2c.h> | ||
62 | #include <linux/i2c-algo-bit.h> | ||
63 | #include <asm/io.h> | ||
64 | |||
65 | /* | ||
66 | * driver configuration | ||
67 | */ | ||
68 | #define MAX_BUSSES 2 | ||
69 | |||
70 | struct s_i2c_bus { | ||
71 | void __iomem *mmvga; | ||
72 | int i2c_reg; | ||
73 | int adap_ok; | ||
74 | struct i2c_adapter adap; | ||
75 | struct i2c_algo_bit_data algo; | ||
76 | }; | ||
77 | |||
78 | struct s_i2c_chip { | ||
79 | void __iomem *mmio; | ||
80 | struct s_i2c_bus i2c_bus[MAX_BUSSES]; | ||
81 | }; | ||
82 | |||
83 | |||
84 | /* | ||
85 | * i2c configuration | ||
86 | */ | ||
87 | #ifndef I2C_HW_B_S3VIA | ||
88 | #define I2C_HW_B_S3VIA 0x18 /* S3VIA ProSavage adapter */ | ||
89 | #endif | ||
90 | |||
91 | /* delays */ | ||
92 | #define CYCLE_DELAY 10 | ||
93 | #define TIMEOUT (HZ / 2) | ||
94 | |||
95 | |||
96 | /* | ||
97 | * S3/VIA 8365/8375 registers | ||
98 | */ | ||
99 | #define VGA_CR_IX 0x3d4 | ||
100 | #define VGA_CR_DATA 0x3d5 | ||
101 | |||
102 | #define CR_SERIAL1 0xa0 /* I2C serial communications interface */ | ||
103 | #define MM_SERIAL1 0xff20 | ||
104 | #define CR_SERIAL2 0xb1 /* DDC2 monitor communications interface */ | ||
105 | |||
106 | /* based on vt8365 documentation */ | ||
107 | #define I2C_ENAB 0x10 | ||
108 | #define I2C_SCL_OUT 0x01 | ||
109 | #define I2C_SDA_OUT 0x02 | ||
110 | #define I2C_SCL_IN 0x04 | ||
111 | #define I2C_SDA_IN 0x08 | ||
112 | |||
113 | #define SET_CR_IX(p, val) writeb((val), (p)->mmvga + VGA_CR_IX) | ||
114 | #define SET_CR_DATA(p, val) writeb((val), (p)->mmvga + VGA_CR_DATA) | ||
115 | #define GET_CR_DATA(p) readb((p)->mmvga + VGA_CR_DATA) | ||
116 | |||
117 | |||
118 | /* | ||
119 | * Serial bus line handling | ||
120 | * | ||
121 | * serial communications register as parameter in private data | ||
122 | * | ||
123 | * TODO: locks with other code sections accessing video registers? | ||
124 | */ | ||
125 | static void bit_s3via_setscl(void *bus, int val) | ||
126 | { | ||
127 | struct s_i2c_bus *p = (struct s_i2c_bus *)bus; | ||
128 | unsigned int r; | ||
129 | |||
130 | SET_CR_IX(p, p->i2c_reg); | ||
131 | r = GET_CR_DATA(p); | ||
132 | r |= I2C_ENAB; | ||
133 | if (val) { | ||
134 | r |= I2C_SCL_OUT; | ||
135 | } else { | ||
136 | r &= ~I2C_SCL_OUT; | ||
137 | } | ||
138 | SET_CR_DATA(p, r); | ||
139 | } | ||
140 | |||
141 | static void bit_s3via_setsda(void *bus, int val) | ||
142 | { | ||
143 | struct s_i2c_bus *p = (struct s_i2c_bus *)bus; | ||
144 | unsigned int r; | ||
145 | |||
146 | SET_CR_IX(p, p->i2c_reg); | ||
147 | r = GET_CR_DATA(p); | ||
148 | r |= I2C_ENAB; | ||
149 | if (val) { | ||
150 | r |= I2C_SDA_OUT; | ||
151 | } else { | ||
152 | r &= ~I2C_SDA_OUT; | ||
153 | } | ||
154 | SET_CR_DATA(p, r); | ||
155 | } | ||
156 | |||
157 | static int bit_s3via_getscl(void *bus) | ||
158 | { | ||
159 | struct s_i2c_bus *p = (struct s_i2c_bus *)bus; | ||
160 | |||
161 | SET_CR_IX(p, p->i2c_reg); | ||
162 | return (0 != (GET_CR_DATA(p) & I2C_SCL_IN)); | ||
163 | } | ||
164 | |||
165 | static int bit_s3via_getsda(void *bus) | ||
166 | { | ||
167 | struct s_i2c_bus *p = (struct s_i2c_bus *)bus; | ||
168 | |||
169 | SET_CR_IX(p, p->i2c_reg); | ||
170 | return (0 != (GET_CR_DATA(p) & I2C_SDA_IN)); | ||
171 | } | ||
172 | |||
173 | |||
174 | /* | ||
175 | * adapter initialisation | ||
176 | */ | ||
177 | static int i2c_register_bus(struct pci_dev *dev, struct s_i2c_bus *p, void __iomem *mmvga, u32 i2c_reg) | ||
178 | { | ||
179 | int ret; | ||
180 | p->adap.owner = THIS_MODULE; | ||
181 | p->adap.id = I2C_HW_B_S3VIA; | ||
182 | p->adap.algo_data = &p->algo; | ||
183 | p->adap.dev.parent = &dev->dev; | ||
184 | p->algo.setsda = bit_s3via_setsda; | ||
185 | p->algo.setscl = bit_s3via_setscl; | ||
186 | p->algo.getsda = bit_s3via_getsda; | ||
187 | p->algo.getscl = bit_s3via_getscl; | ||
188 | p->algo.udelay = CYCLE_DELAY; | ||
189 | p->algo.mdelay = CYCLE_DELAY; | ||
190 | p->algo.timeout = TIMEOUT; | ||
191 | p->algo.data = p; | ||
192 | p->mmvga = mmvga; | ||
193 | p->i2c_reg = i2c_reg; | ||
194 | |||
195 | ret = i2c_bit_add_bus(&p->adap); | ||
196 | if (ret) { | ||
197 | return ret; | ||
198 | } | ||
199 | |||
200 | p->adap_ok = 1; | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | |||
205 | /* | ||
206 | * Cleanup stuff | ||
207 | */ | ||
208 | static void prosavage_remove(struct pci_dev *dev) | ||
209 | { | ||
210 | struct s_i2c_chip *chip; | ||
211 | int i, ret; | ||
212 | |||
213 | chip = (struct s_i2c_chip *)pci_get_drvdata(dev); | ||
214 | |||
215 | if (!chip) { | ||
216 | return; | ||
217 | } | ||
218 | for (i = MAX_BUSSES - 1; i >= 0; i--) { | ||
219 | if (chip->i2c_bus[i].adap_ok == 0) | ||
220 | continue; | ||
221 | |||
222 | ret = i2c_bit_del_bus(&chip->i2c_bus[i].adap); | ||
223 | if (ret) { | ||
224 | dev_err(&dev->dev, "%s not removed\n", | ||
225 | chip->i2c_bus[i].adap.name); | ||
226 | } | ||
227 | } | ||
228 | if (chip->mmio) { | ||
229 | iounmap(chip->mmio); | ||
230 | } | ||
231 | kfree(chip); | ||
232 | } | ||
233 | |||
234 | |||
235 | /* | ||
236 | * Detect chip and initialize it | ||
237 | */ | ||
238 | static int __devinit prosavage_probe(struct pci_dev *dev, const struct pci_device_id *id) | ||
239 | { | ||
240 | int ret; | ||
241 | unsigned long base, len; | ||
242 | struct s_i2c_chip *chip; | ||
243 | struct s_i2c_bus *bus; | ||
244 | |||
245 | pci_set_drvdata(dev, kmalloc(sizeof(struct s_i2c_chip), GFP_KERNEL)); | ||
246 | chip = (struct s_i2c_chip *)pci_get_drvdata(dev); | ||
247 | if (chip == NULL) { | ||
248 | return -ENOMEM; | ||
249 | } | ||
250 | |||
251 | memset(chip, 0, sizeof(struct s_i2c_chip)); | ||
252 | |||
253 | base = dev->resource[0].start & PCI_BASE_ADDRESS_MEM_MASK; | ||
254 | len = dev->resource[0].end - base + 1; | ||
255 | chip->mmio = ioremap_nocache(base, len); | ||
256 | |||
257 | if (chip->mmio == NULL) { | ||
258 | dev_err(&dev->dev, "ioremap failed\n"); | ||
259 | prosavage_remove(dev); | ||
260 | return -ENODEV; | ||
261 | } | ||
262 | |||
263 | |||
264 | /* | ||
265 | * Chip initialisation | ||
266 | */ | ||
267 | /* Unlock Extended IO Space ??? */ | ||
268 | |||
269 | |||
270 | /* | ||
271 | * i2c bus registration | ||
272 | */ | ||
273 | bus = &chip->i2c_bus[0]; | ||
274 | snprintf(bus->adap.name, sizeof(bus->adap.name), | ||
275 | "ProSavage I2C bus at %02x:%02x.%x", | ||
276 | dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); | ||
277 | ret = i2c_register_bus(dev, bus, chip->mmio + 0x8000, CR_SERIAL1); | ||
278 | if (ret) { | ||
279 | goto err_adap; | ||
280 | } | ||
281 | /* | ||
282 | * ddc bus registration | ||
283 | */ | ||
284 | bus = &chip->i2c_bus[1]; | ||
285 | snprintf(bus->adap.name, sizeof(bus->adap.name), | ||
286 | "ProSavage DDC bus at %02x:%02x.%x", | ||
287 | dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); | ||
288 | ret = i2c_register_bus(dev, bus, chip->mmio + 0x8000, CR_SERIAL2); | ||
289 | if (ret) { | ||
290 | goto err_adap; | ||
291 | } | ||
292 | return 0; | ||
293 | err_adap: | ||
294 | dev_err(&dev->dev, "%s failed\n", bus->adap.name); | ||
295 | prosavage_remove(dev); | ||
296 | return ret; | ||
297 | } | ||
298 | |||
299 | |||
300 | /* | ||
301 | * Data for PCI driver interface | ||
302 | */ | ||
303 | static struct pci_device_id prosavage_pci_tbl[] = { | ||
304 | { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_SAVAGE4) }, | ||
305 | { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_PROSAVAGE8) }, | ||
306 | { 0, }, | ||
307 | }; | ||
308 | |||
309 | MODULE_DEVICE_TABLE (pci, prosavage_pci_tbl); | ||
310 | |||
311 | static struct pci_driver prosavage_driver = { | ||
312 | .name = "prosavage_smbus", | ||
313 | .id_table = prosavage_pci_tbl, | ||
314 | .probe = prosavage_probe, | ||
315 | .remove = prosavage_remove, | ||
316 | }; | ||
317 | |||
318 | static int __init i2c_prosavage_init(void) | ||
319 | { | ||
320 | return pci_register_driver(&prosavage_driver); | ||
321 | } | ||
322 | |||
323 | static void __exit i2c_prosavage_exit(void) | ||
324 | { | ||
325 | pci_unregister_driver(&prosavage_driver); | ||
326 | } | ||
327 | |||
328 | MODULE_DEVICE_TABLE(pci, prosavage_pci_tbl); | ||
329 | MODULE_AUTHOR("Henk Vergonet"); | ||
330 | MODULE_DESCRIPTION("ProSavage VIA 8365/8375 smbus driver"); | ||
331 | MODULE_LICENSE("GPL"); | ||
332 | |||
333 | module_init (i2c_prosavage_init); | ||
334 | module_exit (i2c_prosavage_exit); | ||
diff --git a/drivers/i2c/busses/i2c-rpx.c b/drivers/i2c/busses/i2c-rpx.c new file mode 100644 index 000000000000..9497b1b6852f --- /dev/null +++ b/drivers/i2c/busses/i2c-rpx.c | |||
@@ -0,0 +1,102 @@ | |||
1 | /* | ||
2 | * Embedded Planet RPX Lite MPC8xx CPM I2C interface. | ||
3 | * Copyright (c) 1999 Dan Malek (dmalek@jlc.net). | ||
4 | * | ||
5 | * moved into proper i2c interface; | ||
6 | * Brad Parker (brad@heeltoe.com) | ||
7 | * | ||
8 | * RPX lite specific parts of the i2c interface | ||
9 | * Update: There actually isn't anything RPXLite-specific about this module. | ||
10 | * This should work for most any 8xx board. The console messages have been | ||
11 | * changed to eliminate RPXLite references. | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/stddef.h> | ||
19 | #include <linux/i2c.h> | ||
20 | #include <linux/i2c-algo-8xx.h> | ||
21 | #include <asm/mpc8xx.h> | ||
22 | #include <asm/commproc.h> | ||
23 | |||
24 | |||
25 | static void | ||
26 | rpx_iic_init(struct i2c_algo_8xx_data *data) | ||
27 | { | ||
28 | volatile cpm8xx_t *cp; | ||
29 | volatile immap_t *immap; | ||
30 | |||
31 | cp = cpmp; /* Get pointer to Communication Processor */ | ||
32 | immap = (immap_t *)IMAP_ADDR; /* and to internal registers */ | ||
33 | |||
34 | data->iip = (iic_t *)&cp->cp_dparam[PROFF_IIC]; | ||
35 | |||
36 | /* Check for and use a microcode relocation patch. | ||
37 | */ | ||
38 | if ((data->reloc = data->iip->iic_rpbase)) | ||
39 | data->iip = (iic_t *)&cp->cp_dpmem[data->iip->iic_rpbase]; | ||
40 | |||
41 | data->i2c = (i2c8xx_t *)&(immap->im_i2c); | ||
42 | data->cp = cp; | ||
43 | |||
44 | /* Initialize Port B IIC pins. | ||
45 | */ | ||
46 | cp->cp_pbpar |= 0x00000030; | ||
47 | cp->cp_pbdir |= 0x00000030; | ||
48 | cp->cp_pbodr |= 0x00000030; | ||
49 | |||
50 | /* Allocate space for two transmit and two receive buffer | ||
51 | * descriptors in the DP ram. | ||
52 | */ | ||
53 | data->dp_addr = cpm_dpalloc(sizeof(cbd_t) * 4, 8); | ||
54 | |||
55 | /* ptr to i2c area */ | ||
56 | data->i2c = (i2c8xx_t *)&(((immap_t *)IMAP_ADDR)->im_i2c); | ||
57 | } | ||
58 | |||
59 | static int rpx_install_isr(int irq, void (*func)(void *, void *), void *data) | ||
60 | { | ||
61 | /* install interrupt handler */ | ||
62 | cpm_install_handler(irq, (void (*)(void *, struct pt_regs *)) func, data); | ||
63 | |||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | static struct i2c_algo_8xx_data rpx_data = { | ||
68 | .setisr = rpx_install_isr | ||
69 | }; | ||
70 | |||
71 | static struct i2c_adapter rpx_ops = { | ||
72 | .owner = THIS_MODULE, | ||
73 | .name = "m8xx", | ||
74 | .id = I2C_HW_MPC8XX_EPON, | ||
75 | .algo_data = &rpx_data, | ||
76 | }; | ||
77 | |||
78 | int __init i2c_rpx_init(void) | ||
79 | { | ||
80 | printk(KERN_INFO "i2c-rpx: i2c MPC8xx driver\n"); | ||
81 | |||
82 | /* reset hardware to sane state */ | ||
83 | rpx_iic_init(&rpx_data); | ||
84 | |||
85 | if (i2c_8xx_add_bus(&rpx_ops) < 0) { | ||
86 | printk(KERN_ERR "i2c-rpx: Unable to register with I2C\n"); | ||
87 | return -ENODEV; | ||
88 | } | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | void __exit i2c_rpx_exit(void) | ||
94 | { | ||
95 | i2c_8xx_del_bus(&rpx_ops); | ||
96 | } | ||
97 | |||
98 | MODULE_AUTHOR("Dan Malek <dmalek@jlc.net>"); | ||
99 | MODULE_DESCRIPTION("I2C-Bus adapter routines for MPC8xx boards"); | ||
100 | |||
101 | module_init(i2c_rpx_init); | ||
102 | module_exit(i2c_rpx_exit); | ||
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c new file mode 100644 index 000000000000..fcfa51c1436b --- /dev/null +++ b/drivers/i2c/busses/i2c-s3c2410.c | |||
@@ -0,0 +1,938 @@ | |||
1 | /* linux/drivers/i2c/busses/i2c-s3c2410.c | ||
2 | * | ||
3 | * Copyright (C) 2004,2005 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * S3C2410 I2C Controller | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/module.h> | ||
25 | |||
26 | #include <linux/i2c.h> | ||
27 | #include <linux/i2c-id.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/time.h> | ||
30 | #include <linux/interrupt.h> | ||
31 | #include <linux/sched.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/errno.h> | ||
34 | #include <linux/err.h> | ||
35 | #include <linux/device.h> | ||
36 | |||
37 | #include <asm/hardware.h> | ||
38 | #include <asm/irq.h> | ||
39 | #include <asm/io.h> | ||
40 | |||
41 | #include <asm/hardware/clock.h> | ||
42 | #include <asm/arch/regs-gpio.h> | ||
43 | #include <asm/arch/regs-iic.h> | ||
44 | #include <asm/arch/iic.h> | ||
45 | |||
46 | /* i2c controller state */ | ||
47 | |||
48 | enum s3c24xx_i2c_state { | ||
49 | STATE_IDLE, | ||
50 | STATE_START, | ||
51 | STATE_READ, | ||
52 | STATE_WRITE, | ||
53 | STATE_STOP | ||
54 | }; | ||
55 | |||
56 | struct s3c24xx_i2c { | ||
57 | spinlock_t lock; | ||
58 | wait_queue_head_t wait; | ||
59 | |||
60 | struct i2c_msg *msg; | ||
61 | unsigned int msg_num; | ||
62 | unsigned int msg_idx; | ||
63 | unsigned int msg_ptr; | ||
64 | |||
65 | enum s3c24xx_i2c_state state; | ||
66 | |||
67 | void __iomem *regs; | ||
68 | struct clk *clk; | ||
69 | struct device *dev; | ||
70 | struct resource *irq; | ||
71 | struct resource *ioarea; | ||
72 | struct i2c_adapter adap; | ||
73 | }; | ||
74 | |||
75 | /* default platform data to use if not supplied in the platform_device | ||
76 | */ | ||
77 | |||
78 | static struct s3c2410_platform_i2c s3c24xx_i2c_default_platform = { | ||
79 | .flags = 0, | ||
80 | .slave_addr = 0x10, | ||
81 | .bus_freq = 100*1000, | ||
82 | .max_freq = 400*1000, | ||
83 | .sda_delay = S3C2410_IICLC_SDA_DELAY5 | S3C2410_IICLC_FILTER_ON, | ||
84 | }; | ||
85 | |||
86 | /* s3c24xx_i2c_is2440() | ||
87 | * | ||
88 | * return true is this is an s3c2440 | ||
89 | */ | ||
90 | |||
91 | static inline int s3c24xx_i2c_is2440(struct s3c24xx_i2c *i2c) | ||
92 | { | ||
93 | struct platform_device *pdev = to_platform_device(i2c->dev); | ||
94 | |||
95 | return !strcmp(pdev->name, "s3c2440-i2c"); | ||
96 | } | ||
97 | |||
98 | |||
99 | /* s3c24xx_i2c_get_platformdata | ||
100 | * | ||
101 | * get the platform data associated with the given device, or return | ||
102 | * the default if there is none | ||
103 | */ | ||
104 | |||
105 | static inline struct s3c2410_platform_i2c *s3c24xx_i2c_get_platformdata(struct device *dev) | ||
106 | { | ||
107 | if (dev->platform_data != NULL) | ||
108 | return (struct s3c2410_platform_i2c *)dev->platform_data; | ||
109 | |||
110 | return &s3c24xx_i2c_default_platform; | ||
111 | } | ||
112 | |||
113 | /* s3c24xx_i2c_master_complete | ||
114 | * | ||
115 | * complete the message and wake up the caller, using the given return code, | ||
116 | * or zero to mean ok. | ||
117 | */ | ||
118 | |||
119 | static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret) | ||
120 | { | ||
121 | dev_dbg(i2c->dev, "master_complete %d\n", ret); | ||
122 | |||
123 | i2c->msg_ptr = 0; | ||
124 | i2c->msg = NULL; | ||
125 | i2c->msg_idx ++; | ||
126 | i2c->msg_num = 0; | ||
127 | if (ret) | ||
128 | i2c->msg_idx = ret; | ||
129 | |||
130 | wake_up(&i2c->wait); | ||
131 | } | ||
132 | |||
133 | static inline void s3c24xx_i2c_disable_ack(struct s3c24xx_i2c *i2c) | ||
134 | { | ||
135 | unsigned long tmp; | ||
136 | |||
137 | tmp = readl(i2c->regs + S3C2410_IICCON); | ||
138 | writel(tmp & ~S3C2410_IICCON_ACKEN, i2c->regs + S3C2410_IICCON); | ||
139 | |||
140 | } | ||
141 | |||
142 | static inline void s3c24xx_i2c_enable_ack(struct s3c24xx_i2c *i2c) | ||
143 | { | ||
144 | unsigned long tmp; | ||
145 | |||
146 | tmp = readl(i2c->regs + S3C2410_IICCON); | ||
147 | writel(tmp | S3C2410_IICCON_ACKEN, i2c->regs + S3C2410_IICCON); | ||
148 | |||
149 | } | ||
150 | |||
151 | /* irq enable/disable functions */ | ||
152 | |||
153 | static inline void s3c24xx_i2c_disable_irq(struct s3c24xx_i2c *i2c) | ||
154 | { | ||
155 | unsigned long tmp; | ||
156 | |||
157 | tmp = readl(i2c->regs + S3C2410_IICCON); | ||
158 | writel(tmp & ~S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON); | ||
159 | } | ||
160 | |||
161 | static inline void s3c24xx_i2c_enable_irq(struct s3c24xx_i2c *i2c) | ||
162 | { | ||
163 | unsigned long tmp; | ||
164 | |||
165 | tmp = readl(i2c->regs + S3C2410_IICCON); | ||
166 | writel(tmp | S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON); | ||
167 | } | ||
168 | |||
169 | |||
170 | /* s3c24xx_i2c_message_start | ||
171 | * | ||
172 | * put the start of a message onto the bus | ||
173 | */ | ||
174 | |||
175 | static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c, | ||
176 | struct i2c_msg *msg) | ||
177 | { | ||
178 | unsigned int addr = (msg->addr & 0x7f) << 1; | ||
179 | unsigned long stat; | ||
180 | unsigned long iiccon; | ||
181 | |||
182 | stat = 0; | ||
183 | stat |= S3C2410_IICSTAT_TXRXEN; | ||
184 | |||
185 | if (msg->flags & I2C_M_RD) { | ||
186 | stat |= S3C2410_IICSTAT_MASTER_RX; | ||
187 | addr |= 1; | ||
188 | } else | ||
189 | stat |= S3C2410_IICSTAT_MASTER_TX; | ||
190 | |||
191 | if (msg->flags & I2C_M_REV_DIR_ADDR) | ||
192 | addr ^= 1; | ||
193 | |||
194 | // todo - check for wether ack wanted or not | ||
195 | s3c24xx_i2c_enable_ack(i2c); | ||
196 | |||
197 | iiccon = readl(i2c->regs + S3C2410_IICCON); | ||
198 | writel(stat, i2c->regs + S3C2410_IICSTAT); | ||
199 | |||
200 | dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr); | ||
201 | writeb(addr, i2c->regs + S3C2410_IICDS); | ||
202 | |||
203 | // delay a bit and reset iiccon before setting start (per samsung) | ||
204 | udelay(1); | ||
205 | dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon); | ||
206 | writel(iiccon, i2c->regs + S3C2410_IICCON); | ||
207 | |||
208 | stat |= S3C2410_IICSTAT_START; | ||
209 | writel(stat, i2c->regs + S3C2410_IICSTAT); | ||
210 | } | ||
211 | |||
212 | static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret) | ||
213 | { | ||
214 | unsigned long iicstat = readl(i2c->regs + S3C2410_IICSTAT); | ||
215 | |||
216 | dev_dbg(i2c->dev, "STOP\n"); | ||
217 | |||
218 | /* stop the transfer */ | ||
219 | iicstat &= ~ S3C2410_IICSTAT_START; | ||
220 | writel(iicstat, i2c->regs + S3C2410_IICSTAT); | ||
221 | |||
222 | i2c->state = STATE_STOP; | ||
223 | |||
224 | s3c24xx_i2c_master_complete(i2c, ret); | ||
225 | s3c24xx_i2c_disable_irq(i2c); | ||
226 | } | ||
227 | |||
228 | /* helper functions to determine the current state in the set of | ||
229 | * messages we are sending */ | ||
230 | |||
231 | /* is_lastmsg() | ||
232 | * | ||
233 | * returns TRUE if the current message is the last in the set | ||
234 | */ | ||
235 | |||
236 | static inline int is_lastmsg(struct s3c24xx_i2c *i2c) | ||
237 | { | ||
238 | return i2c->msg_idx >= (i2c->msg_num - 1); | ||
239 | } | ||
240 | |||
241 | /* is_msglast | ||
242 | * | ||
243 | * returns TRUE if we this is the last byte in the current message | ||
244 | */ | ||
245 | |||
246 | static inline int is_msglast(struct s3c24xx_i2c *i2c) | ||
247 | { | ||
248 | return i2c->msg_ptr == i2c->msg->len-1; | ||
249 | } | ||
250 | |||
251 | /* is_msgend | ||
252 | * | ||
253 | * returns TRUE if we reached the end of the current message | ||
254 | */ | ||
255 | |||
256 | static inline int is_msgend(struct s3c24xx_i2c *i2c) | ||
257 | { | ||
258 | return i2c->msg_ptr >= i2c->msg->len; | ||
259 | } | ||
260 | |||
261 | /* i2s_s3c_irq_nextbyte | ||
262 | * | ||
263 | * process an interrupt and work out what to do | ||
264 | */ | ||
265 | |||
266 | static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) | ||
267 | { | ||
268 | unsigned long tmp; | ||
269 | unsigned char byte; | ||
270 | int ret = 0; | ||
271 | |||
272 | switch (i2c->state) { | ||
273 | |||
274 | case STATE_IDLE: | ||
275 | dev_err(i2c->dev, "%s: called in STATE_IDLE\n", __FUNCTION__); | ||
276 | goto out; | ||
277 | break; | ||
278 | |||
279 | case STATE_STOP: | ||
280 | dev_err(i2c->dev, "%s: called in STATE_STOP\n", __FUNCTION__); | ||
281 | s3c24xx_i2c_disable_irq(i2c); | ||
282 | goto out_ack; | ||
283 | |||
284 | case STATE_START: | ||
285 | /* last thing we did was send a start condition on the | ||
286 | * bus, or started a new i2c message | ||
287 | */ | ||
288 | |||
289 | if (iicstat & S3C2410_IICSTAT_LASTBIT && | ||
290 | !(i2c->msg->flags & I2C_M_IGNORE_NAK)) { | ||
291 | /* ack was not received... */ | ||
292 | |||
293 | dev_dbg(i2c->dev, "ack was not received\n"); | ||
294 | s3c24xx_i2c_stop(i2c, -EREMOTEIO); | ||
295 | goto out_ack; | ||
296 | } | ||
297 | |||
298 | if (i2c->msg->flags & I2C_M_RD) | ||
299 | i2c->state = STATE_READ; | ||
300 | else | ||
301 | i2c->state = STATE_WRITE; | ||
302 | |||
303 | /* terminate the transfer if there is nothing to do | ||
304 | * (used by the i2c probe to find devices */ | ||
305 | |||
306 | if (is_lastmsg(i2c) && i2c->msg->len == 0) { | ||
307 | s3c24xx_i2c_stop(i2c, 0); | ||
308 | goto out_ack; | ||
309 | } | ||
310 | |||
311 | if (i2c->state == STATE_READ) | ||
312 | goto prepare_read; | ||
313 | |||
314 | /* fall through to the write state, as we will need to | ||
315 | * send a byte as well */ | ||
316 | |||
317 | case STATE_WRITE: | ||
318 | /* we are writing data to the device... check for the | ||
319 | * end of the message, and if so, work out what to do | ||
320 | */ | ||
321 | |||
322 | retry_write: | ||
323 | if (!is_msgend(i2c)) { | ||
324 | byte = i2c->msg->buf[i2c->msg_ptr++]; | ||
325 | writeb(byte, i2c->regs + S3C2410_IICDS); | ||
326 | |||
327 | } else if (!is_lastmsg(i2c)) { | ||
328 | /* we need to go to the next i2c message */ | ||
329 | |||
330 | dev_dbg(i2c->dev, "WRITE: Next Message\n"); | ||
331 | |||
332 | i2c->msg_ptr = 0; | ||
333 | i2c->msg_idx ++; | ||
334 | i2c->msg++; | ||
335 | |||
336 | /* check to see if we need to do another message */ | ||
337 | if (i2c->msg->flags & I2C_M_NOSTART) { | ||
338 | |||
339 | if (i2c->msg->flags & I2C_M_RD) { | ||
340 | /* cannot do this, the controller | ||
341 | * forces us to send a new START | ||
342 | * when we change direction */ | ||
343 | |||
344 | s3c24xx_i2c_stop(i2c, -EINVAL); | ||
345 | } | ||
346 | |||
347 | goto retry_write; | ||
348 | } else { | ||
349 | |||
350 | /* send the new start */ | ||
351 | s3c24xx_i2c_message_start(i2c, i2c->msg); | ||
352 | i2c->state = STATE_START; | ||
353 | } | ||
354 | |||
355 | } else { | ||
356 | /* send stop */ | ||
357 | |||
358 | s3c24xx_i2c_stop(i2c, 0); | ||
359 | } | ||
360 | break; | ||
361 | |||
362 | case STATE_READ: | ||
363 | /* we have a byte of data in the data register, do | ||
364 | * something with it, and then work out wether we are | ||
365 | * going to do any more read/write | ||
366 | */ | ||
367 | |||
368 | if (!(i2c->msg->flags & I2C_M_IGNORE_NAK) && | ||
369 | !(is_msglast(i2c) && is_lastmsg(i2c))) { | ||
370 | |||
371 | if (iicstat & S3C2410_IICSTAT_LASTBIT) { | ||
372 | dev_dbg(i2c->dev, "READ: No Ack\n"); | ||
373 | |||
374 | s3c24xx_i2c_stop(i2c, -ECONNREFUSED); | ||
375 | goto out_ack; | ||
376 | } | ||
377 | } | ||
378 | |||
379 | byte = readb(i2c->regs + S3C2410_IICDS); | ||
380 | i2c->msg->buf[i2c->msg_ptr++] = byte; | ||
381 | |||
382 | prepare_read: | ||
383 | if (is_msglast(i2c)) { | ||
384 | /* last byte of buffer */ | ||
385 | |||
386 | if (is_lastmsg(i2c)) | ||
387 | s3c24xx_i2c_disable_ack(i2c); | ||
388 | |||
389 | } else if (is_msgend(i2c)) { | ||
390 | /* ok, we've read the entire buffer, see if there | ||
391 | * is anything else we need to do */ | ||
392 | |||
393 | if (is_lastmsg(i2c)) { | ||
394 | /* last message, send stop and complete */ | ||
395 | dev_dbg(i2c->dev, "READ: Send Stop\n"); | ||
396 | |||
397 | s3c24xx_i2c_stop(i2c, 0); | ||
398 | } else { | ||
399 | /* go to the next transfer */ | ||
400 | dev_dbg(i2c->dev, "READ: Next Transfer\n"); | ||
401 | |||
402 | i2c->msg_ptr = 0; | ||
403 | i2c->msg_idx++; | ||
404 | i2c->msg++; | ||
405 | } | ||
406 | } | ||
407 | |||
408 | break; | ||
409 | } | ||
410 | |||
411 | /* acknowlegde the IRQ and get back on with the work */ | ||
412 | |||
413 | out_ack: | ||
414 | tmp = readl(i2c->regs + S3C2410_IICCON); | ||
415 | tmp &= ~S3C2410_IICCON_IRQPEND; | ||
416 | writel(tmp, i2c->regs + S3C2410_IICCON); | ||
417 | out: | ||
418 | return ret; | ||
419 | } | ||
420 | |||
421 | /* s3c24xx_i2c_irq | ||
422 | * | ||
423 | * top level IRQ servicing routine | ||
424 | */ | ||
425 | |||
426 | static irqreturn_t s3c24xx_i2c_irq(int irqno, void *dev_id, | ||
427 | struct pt_regs *regs) | ||
428 | { | ||
429 | struct s3c24xx_i2c *i2c = dev_id; | ||
430 | unsigned long status; | ||
431 | unsigned long tmp; | ||
432 | |||
433 | status = readl(i2c->regs + S3C2410_IICSTAT); | ||
434 | |||
435 | if (status & S3C2410_IICSTAT_ARBITR) { | ||
436 | // deal with arbitration loss | ||
437 | dev_err(i2c->dev, "deal with arbitration loss\n"); | ||
438 | } | ||
439 | |||
440 | if (i2c->state == STATE_IDLE) { | ||
441 | dev_dbg(i2c->dev, "IRQ: error i2c->state == IDLE\n"); | ||
442 | |||
443 | tmp = readl(i2c->regs + S3C2410_IICCON); | ||
444 | tmp &= ~S3C2410_IICCON_IRQPEND; | ||
445 | writel(tmp, i2c->regs + S3C2410_IICCON); | ||
446 | goto out; | ||
447 | } | ||
448 | |||
449 | /* pretty much this leaves us with the fact that we've | ||
450 | * transmitted or received whatever byte we last sent */ | ||
451 | |||
452 | i2s_s3c_irq_nextbyte(i2c, status); | ||
453 | |||
454 | out: | ||
455 | return IRQ_HANDLED; | ||
456 | } | ||
457 | |||
458 | |||
459 | /* s3c24xx_i2c_set_master | ||
460 | * | ||
461 | * get the i2c bus for a master transaction | ||
462 | */ | ||
463 | |||
464 | static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c) | ||
465 | { | ||
466 | unsigned long iicstat; | ||
467 | int timeout = 400; | ||
468 | |||
469 | while (timeout-- > 0) { | ||
470 | iicstat = readl(i2c->regs + S3C2410_IICSTAT); | ||
471 | |||
472 | if (!(iicstat & S3C2410_IICSTAT_BUSBUSY)) | ||
473 | return 0; | ||
474 | |||
475 | msleep(1); | ||
476 | } | ||
477 | |||
478 | dev_dbg(i2c->dev, "timeout: GPEDAT is %08x\n", | ||
479 | __raw_readl(S3C2410_GPEDAT)); | ||
480 | |||
481 | return -ETIMEDOUT; | ||
482 | } | ||
483 | |||
484 | /* s3c24xx_i2c_doxfer | ||
485 | * | ||
486 | * this starts an i2c transfer | ||
487 | */ | ||
488 | |||
489 | static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int num) | ||
490 | { | ||
491 | unsigned long timeout; | ||
492 | int ret; | ||
493 | |||
494 | ret = s3c24xx_i2c_set_master(i2c); | ||
495 | if (ret != 0) { | ||
496 | dev_err(i2c->dev, "cannot get bus (error %d)\n", ret); | ||
497 | ret = -EAGAIN; | ||
498 | goto out; | ||
499 | } | ||
500 | |||
501 | spin_lock_irq(&i2c->lock); | ||
502 | |||
503 | i2c->msg = msgs; | ||
504 | i2c->msg_num = num; | ||
505 | i2c->msg_ptr = 0; | ||
506 | i2c->msg_idx = 0; | ||
507 | i2c->state = STATE_START; | ||
508 | |||
509 | s3c24xx_i2c_enable_irq(i2c); | ||
510 | s3c24xx_i2c_message_start(i2c, msgs); | ||
511 | spin_unlock_irq(&i2c->lock); | ||
512 | |||
513 | timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); | ||
514 | |||
515 | ret = i2c->msg_idx; | ||
516 | |||
517 | /* having these next two as dev_err() makes life very | ||
518 | * noisy when doing an i2cdetect */ | ||
519 | |||
520 | if (timeout == 0) | ||
521 | dev_dbg(i2c->dev, "timeout\n"); | ||
522 | else if (ret != num) | ||
523 | dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret); | ||
524 | |||
525 | /* ensure the stop has been through the bus */ | ||
526 | |||
527 | msleep(1); | ||
528 | |||
529 | out: | ||
530 | return ret; | ||
531 | } | ||
532 | |||
533 | /* s3c24xx_i2c_xfer | ||
534 | * | ||
535 | * first port of call from the i2c bus code when an message needs | ||
536 | * transfering across the i2c bus. | ||
537 | */ | ||
538 | |||
539 | static int s3c24xx_i2c_xfer(struct i2c_adapter *adap, | ||
540 | struct i2c_msg *msgs, int num) | ||
541 | { | ||
542 | struct s3c24xx_i2c *i2c = (struct s3c24xx_i2c *)adap->algo_data; | ||
543 | int retry; | ||
544 | int ret; | ||
545 | |||
546 | for (retry = 0; retry < adap->retries; retry++) { | ||
547 | |||
548 | ret = s3c24xx_i2c_doxfer(i2c, msgs, num); | ||
549 | |||
550 | if (ret != -EAGAIN) | ||
551 | return ret; | ||
552 | |||
553 | dev_dbg(i2c->dev, "Retrying transmission (%d)\n", retry); | ||
554 | |||
555 | udelay(100); | ||
556 | } | ||
557 | |||
558 | return -EREMOTEIO; | ||
559 | } | ||
560 | |||
561 | /* declare our i2c functionality */ | ||
562 | static u32 s3c24xx_i2c_func(struct i2c_adapter *adap) | ||
563 | { | ||
564 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING; | ||
565 | } | ||
566 | |||
567 | /* i2c bus registration info */ | ||
568 | |||
569 | static struct i2c_algorithm s3c24xx_i2c_algorithm = { | ||
570 | .name = "S3C2410-I2C-Algorithm", | ||
571 | .master_xfer = s3c24xx_i2c_xfer, | ||
572 | .functionality = s3c24xx_i2c_func, | ||
573 | }; | ||
574 | |||
575 | static struct s3c24xx_i2c s3c24xx_i2c = { | ||
576 | .lock = SPIN_LOCK_UNLOCKED, | ||
577 | .wait = __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait), | ||
578 | .adap = { | ||
579 | .name = "s3c2410-i2c", | ||
580 | .owner = THIS_MODULE, | ||
581 | .algo = &s3c24xx_i2c_algorithm, | ||
582 | .retries = 2, | ||
583 | .class = I2C_CLASS_HWMON, | ||
584 | }, | ||
585 | }; | ||
586 | |||
587 | /* s3c24xx_i2c_calcdivisor | ||
588 | * | ||
589 | * return the divisor settings for a given frequency | ||
590 | */ | ||
591 | |||
592 | static int s3c24xx_i2c_calcdivisor(unsigned long clkin, unsigned int wanted, | ||
593 | unsigned int *div1, unsigned int *divs) | ||
594 | { | ||
595 | unsigned int calc_divs = clkin / wanted; | ||
596 | unsigned int calc_div1; | ||
597 | |||
598 | if (calc_divs > (16*16)) | ||
599 | calc_div1 = 512; | ||
600 | else | ||
601 | calc_div1 = 16; | ||
602 | |||
603 | calc_divs += calc_div1-1; | ||
604 | calc_divs /= calc_div1; | ||
605 | |||
606 | if (calc_divs == 0) | ||
607 | calc_divs = 1; | ||
608 | if (calc_divs > 17) | ||
609 | calc_divs = 17; | ||
610 | |||
611 | *divs = calc_divs; | ||
612 | *div1 = calc_div1; | ||
613 | |||
614 | return clkin / (calc_divs * calc_div1); | ||
615 | } | ||
616 | |||
617 | /* freq_acceptable | ||
618 | * | ||
619 | * test wether a frequency is within the acceptable range of error | ||
620 | */ | ||
621 | |||
622 | static inline int freq_acceptable(unsigned int freq, unsigned int wanted) | ||
623 | { | ||
624 | int diff = freq - wanted; | ||
625 | |||
626 | return (diff >= -2 && diff <= 2); | ||
627 | } | ||
628 | |||
629 | /* s3c24xx_i2c_getdivisor | ||
630 | * | ||
631 | * work out a divisor for the user requested frequency setting, | ||
632 | * either by the requested frequency, or scanning the acceptable | ||
633 | * range of frequencies until something is found | ||
634 | */ | ||
635 | |||
636 | static int s3c24xx_i2c_getdivisor(struct s3c24xx_i2c *i2c, | ||
637 | struct s3c2410_platform_i2c *pdata, | ||
638 | unsigned long *iicon, | ||
639 | unsigned int *got) | ||
640 | { | ||
641 | unsigned long clkin = clk_get_rate(i2c->clk); | ||
642 | |||
643 | unsigned int divs, div1; | ||
644 | int freq; | ||
645 | int start, end; | ||
646 | |||
647 | clkin /= 1000; /* clkin now in KHz */ | ||
648 | |||
649 | dev_dbg(i2c->dev, "pdata %p, freq %lu %lu..%lu\n", | ||
650 | pdata, pdata->bus_freq, pdata->min_freq, pdata->max_freq); | ||
651 | |||
652 | if (pdata->bus_freq != 0) { | ||
653 | freq = s3c24xx_i2c_calcdivisor(clkin, pdata->bus_freq/1000, | ||
654 | &div1, &divs); | ||
655 | if (freq_acceptable(freq, pdata->bus_freq/1000)) | ||
656 | goto found; | ||
657 | } | ||
658 | |||
659 | /* ok, we may have to search for something suitable... */ | ||
660 | |||
661 | start = (pdata->max_freq == 0) ? pdata->bus_freq : pdata->max_freq; | ||
662 | end = pdata->min_freq; | ||
663 | |||
664 | start /= 1000; | ||
665 | end /= 1000; | ||
666 | |||
667 | /* search loop... */ | ||
668 | |||
669 | for (; start > end; start--) { | ||
670 | freq = s3c24xx_i2c_calcdivisor(clkin, start, &div1, &divs); | ||
671 | if (freq_acceptable(freq, start)) | ||
672 | goto found; | ||
673 | } | ||
674 | |||
675 | /* cannot find frequency spec */ | ||
676 | |||
677 | return -EINVAL; | ||
678 | |||
679 | found: | ||
680 | *got = freq; | ||
681 | *iicon |= (divs-1); | ||
682 | *iicon |= (div1 == 512) ? S3C2410_IICCON_TXDIV_512 : 0; | ||
683 | return 0; | ||
684 | } | ||
685 | |||
686 | /* s3c24xx_i2c_init | ||
687 | * | ||
688 | * initialise the controller, set the IO lines and frequency | ||
689 | */ | ||
690 | |||
691 | static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) | ||
692 | { | ||
693 | unsigned long iicon = S3C2410_IICCON_IRQEN | S3C2410_IICCON_ACKEN; | ||
694 | struct s3c2410_platform_i2c *pdata; | ||
695 | unsigned int freq; | ||
696 | |||
697 | /* get the plafrom data */ | ||
698 | |||
699 | pdata = s3c24xx_i2c_get_platformdata(i2c->adap.dev.parent); | ||
700 | |||
701 | /* inititalise the gpio */ | ||
702 | |||
703 | s3c2410_gpio_cfgpin(S3C2410_GPE15, S3C2410_GPE15_IICSDA); | ||
704 | s3c2410_gpio_cfgpin(S3C2410_GPE14, S3C2410_GPE14_IICSCL); | ||
705 | |||
706 | /* write slave address */ | ||
707 | |||
708 | writeb(pdata->slave_addr, i2c->regs + S3C2410_IICADD); | ||
709 | |||
710 | dev_info(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr); | ||
711 | |||
712 | /* we need to work out the divisors for the clock... */ | ||
713 | |||
714 | if (s3c24xx_i2c_getdivisor(i2c, pdata, &iicon, &freq) != 0) { | ||
715 | dev_err(i2c->dev, "cannot meet bus frequency required\n"); | ||
716 | return -EINVAL; | ||
717 | } | ||
718 | |||
719 | /* todo - check that the i2c lines aren't being dragged anywhere */ | ||
720 | |||
721 | dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq); | ||
722 | dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon); | ||
723 | |||
724 | writel(iicon, i2c->regs + S3C2410_IICCON); | ||
725 | |||
726 | /* check for s3c2440 i2c controller */ | ||
727 | |||
728 | if (s3c24xx_i2c_is2440(i2c)) { | ||
729 | dev_dbg(i2c->dev, "S3C2440_IICLC=%08x\n", pdata->sda_delay); | ||
730 | |||
731 | writel(pdata->sda_delay, i2c->regs + S3C2440_IICLC); | ||
732 | } | ||
733 | |||
734 | return 0; | ||
735 | } | ||
736 | |||
737 | static void s3c24xx_i2c_free(struct s3c24xx_i2c *i2c) | ||
738 | { | ||
739 | if (i2c->clk != NULL && !IS_ERR(i2c->clk)) { | ||
740 | clk_disable(i2c->clk); | ||
741 | clk_unuse(i2c->clk); | ||
742 | clk_put(i2c->clk); | ||
743 | i2c->clk = NULL; | ||
744 | } | ||
745 | |||
746 | if (i2c->regs != NULL) { | ||
747 | iounmap(i2c->regs); | ||
748 | i2c->regs = NULL; | ||
749 | } | ||
750 | |||
751 | if (i2c->ioarea != NULL) { | ||
752 | release_resource(i2c->ioarea); | ||
753 | kfree(i2c->ioarea); | ||
754 | i2c->ioarea = NULL; | ||
755 | } | ||
756 | } | ||
757 | |||
758 | /* s3c24xx_i2c_probe | ||
759 | * | ||
760 | * called by the bus driver when a suitable device is found | ||
761 | */ | ||
762 | |||
763 | static int s3c24xx_i2c_probe(struct device *dev) | ||
764 | { | ||
765 | struct platform_device *pdev = to_platform_device(dev); | ||
766 | struct s3c24xx_i2c *i2c = &s3c24xx_i2c; | ||
767 | struct resource *res; | ||
768 | int ret; | ||
769 | |||
770 | /* find the clock and enable it */ | ||
771 | |||
772 | i2c->dev = dev; | ||
773 | i2c->clk = clk_get(dev, "i2c"); | ||
774 | if (IS_ERR(i2c->clk)) { | ||
775 | dev_err(dev, "cannot get clock\n"); | ||
776 | ret = -ENOENT; | ||
777 | goto out; | ||
778 | } | ||
779 | |||
780 | dev_dbg(dev, "clock source %p\n", i2c->clk); | ||
781 | |||
782 | clk_use(i2c->clk); | ||
783 | clk_enable(i2c->clk); | ||
784 | |||
785 | /* map the registers */ | ||
786 | |||
787 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
788 | if (res == NULL) { | ||
789 | dev_err(dev, "cannot find IO resource\n"); | ||
790 | ret = -ENOENT; | ||
791 | goto out; | ||
792 | } | ||
793 | |||
794 | i2c->ioarea = request_mem_region(res->start, (res->end-res->start)+1, | ||
795 | pdev->name); | ||
796 | |||
797 | if (i2c->ioarea == NULL) { | ||
798 | dev_err(dev, "cannot request IO\n"); | ||
799 | ret = -ENXIO; | ||
800 | goto out; | ||
801 | } | ||
802 | |||
803 | i2c->regs = ioremap(res->start, (res->end-res->start)+1); | ||
804 | |||
805 | if (i2c->regs == NULL) { | ||
806 | dev_err(dev, "cannot map IO\n"); | ||
807 | ret = -ENXIO; | ||
808 | goto out; | ||
809 | } | ||
810 | |||
811 | dev_dbg(dev, "registers %p (%p, %p)\n", i2c->regs, i2c->ioarea, res); | ||
812 | |||
813 | /* setup info block for the i2c core */ | ||
814 | |||
815 | i2c->adap.algo_data = i2c; | ||
816 | i2c->adap.dev.parent = dev; | ||
817 | |||
818 | /* initialise the i2c controller */ | ||
819 | |||
820 | ret = s3c24xx_i2c_init(i2c); | ||
821 | if (ret != 0) | ||
822 | goto out; | ||
823 | |||
824 | /* find the IRQ for this unit (note, this relies on the init call to | ||
825 | * ensure no current IRQs pending | ||
826 | */ | ||
827 | |||
828 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
829 | if (res == NULL) { | ||
830 | dev_err(dev, "cannot find IRQ\n"); | ||
831 | ret = -ENOENT; | ||
832 | goto out; | ||
833 | } | ||
834 | |||
835 | ret = request_irq(res->start, s3c24xx_i2c_irq, SA_INTERRUPT, | ||
836 | pdev->name, i2c); | ||
837 | |||
838 | if (ret != 0) { | ||
839 | dev_err(dev, "cannot claim IRQ\n"); | ||
840 | goto out; | ||
841 | } | ||
842 | |||
843 | i2c->irq = res; | ||
844 | |||
845 | dev_dbg(dev, "irq resource %p (%ld)\n", res, res->start); | ||
846 | |||
847 | ret = i2c_add_adapter(&i2c->adap); | ||
848 | if (ret < 0) { | ||
849 | dev_err(dev, "failed to add bus to i2c core\n"); | ||
850 | goto out; | ||
851 | } | ||
852 | |||
853 | dev_set_drvdata(dev, i2c); | ||
854 | |||
855 | dev_info(dev, "%s: S3C I2C adapter\n", i2c->adap.dev.bus_id); | ||
856 | |||
857 | out: | ||
858 | if (ret < 0) | ||
859 | s3c24xx_i2c_free(i2c); | ||
860 | |||
861 | return ret; | ||
862 | } | ||
863 | |||
864 | /* s3c24xx_i2c_remove | ||
865 | * | ||
866 | * called when device is removed from the bus | ||
867 | */ | ||
868 | |||
869 | static int s3c24xx_i2c_remove(struct device *dev) | ||
870 | { | ||
871 | struct s3c24xx_i2c *i2c = dev_get_drvdata(dev); | ||
872 | |||
873 | if (i2c != NULL) { | ||
874 | s3c24xx_i2c_free(i2c); | ||
875 | dev_set_drvdata(dev, NULL); | ||
876 | } | ||
877 | |||
878 | return 0; | ||
879 | } | ||
880 | |||
881 | #ifdef CONFIG_PM | ||
882 | static int s3c24xx_i2c_resume(struct device *dev, u32 level) | ||
883 | { | ||
884 | struct s3c24xx_i2c *i2c = dev_get_drvdata(dev); | ||
885 | |||
886 | if (i2c != NULL && level == RESUME_ENABLE) { | ||
887 | dev_dbg(dev, "resume: level %d\n", level); | ||
888 | s3c24xx_i2c_init(i2c); | ||
889 | } | ||
890 | |||
891 | return 0; | ||
892 | } | ||
893 | |||
894 | #else | ||
895 | #define s3c24xx_i2c_resume NULL | ||
896 | #endif | ||
897 | |||
898 | /* device driver for platform bus bits */ | ||
899 | |||
900 | static struct device_driver s3c2410_i2c_driver = { | ||
901 | .name = "s3c2410-i2c", | ||
902 | .bus = &platform_bus_type, | ||
903 | .probe = s3c24xx_i2c_probe, | ||
904 | .remove = s3c24xx_i2c_remove, | ||
905 | .resume = s3c24xx_i2c_resume, | ||
906 | }; | ||
907 | |||
908 | static struct device_driver s3c2440_i2c_driver = { | ||
909 | .name = "s3c2440-i2c", | ||
910 | .bus = &platform_bus_type, | ||
911 | .probe = s3c24xx_i2c_probe, | ||
912 | .remove = s3c24xx_i2c_remove, | ||
913 | .resume = s3c24xx_i2c_resume, | ||
914 | }; | ||
915 | |||
916 | static int __init i2c_adap_s3c_init(void) | ||
917 | { | ||
918 | int ret; | ||
919 | |||
920 | ret = driver_register(&s3c2410_i2c_driver); | ||
921 | if (ret == 0) | ||
922 | ret = driver_register(&s3c2440_i2c_driver); | ||
923 | |||
924 | return ret; | ||
925 | } | ||
926 | |||
927 | static void __exit i2c_adap_s3c_exit(void) | ||
928 | { | ||
929 | driver_unregister(&s3c2410_i2c_driver); | ||
930 | driver_unregister(&s3c2440_i2c_driver); | ||
931 | } | ||
932 | |||
933 | module_init(i2c_adap_s3c_init); | ||
934 | module_exit(i2c_adap_s3c_exit); | ||
935 | |||
936 | MODULE_DESCRIPTION("S3C24XX I2C Bus driver"); | ||
937 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); | ||
938 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/i2c/busses/i2c-savage4.c b/drivers/i2c/busses/i2c-savage4.c new file mode 100644 index 000000000000..092d0323c6c6 --- /dev/null +++ b/drivers/i2c/busses/i2c-savage4.c | |||
@@ -0,0 +1,205 @@ | |||
1 | /* | ||
2 | i2c-savage4.c - Part of lm_sensors, Linux kernel modules for hardware | ||
3 | monitoring | ||
4 | Copyright (C) 1998-2003 The LM Sensors Team | ||
5 | Alexander Wold <awold@bigfoot.com> | ||
6 | Mark D. Studebaker <mdsxyz123@yahoo.com> | ||
7 | |||
8 | Based on i2c-voodoo3.c. | ||
9 | |||
10 | This program is free software; you can redistribute it and/or modify | ||
11 | it under the terms of the GNU General Public License as published by | ||
12 | the Free Software Foundation; either version 2 of the License, or | ||
13 | (at your option) any later version. | ||
14 | |||
15 | This program is distributed in the hope that it will be useful, | ||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | GNU General Public License for more details. | ||
19 | |||
20 | You should have received a copy of the GNU General Public License | ||
21 | along with this program; if not, write to the Free Software | ||
22 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | */ | ||
24 | |||
25 | /* This interfaces to the I2C bus of the Savage4 to gain access to | ||
26 | the BT869 and possibly other I2C devices. The DDC bus is not | ||
27 | yet supported because its register is not memory-mapped. | ||
28 | However we leave the DDC code here, commented out, to make | ||
29 | it easier to add later. | ||
30 | */ | ||
31 | |||
32 | #include <linux/config.h> | ||
33 | #include <linux/kernel.h> | ||
34 | #include <linux/module.h> | ||
35 | #include <linux/init.h> | ||
36 | #include <linux/pci.h> | ||
37 | #include <linux/i2c.h> | ||
38 | #include <linux/i2c-algo-bit.h> | ||
39 | #include <asm/io.h> | ||
40 | |||
41 | /* 3DFX defines */ | ||
42 | #define PCI_CHIP_SAVAGE3D 0x8A20 | ||
43 | #define PCI_CHIP_SAVAGE3D_MV 0x8A21 | ||
44 | #define PCI_CHIP_SAVAGE4 0x8A22 | ||
45 | #define PCI_CHIP_SAVAGE2000 0x9102 | ||
46 | #define PCI_CHIP_PROSAVAGE_PM 0x8A25 | ||
47 | #define PCI_CHIP_PROSAVAGE_KM 0x8A26 | ||
48 | #define PCI_CHIP_SAVAGE_MX_MV 0x8c10 | ||
49 | #define PCI_CHIP_SAVAGE_MX 0x8c11 | ||
50 | #define PCI_CHIP_SAVAGE_IX_MV 0x8c12 | ||
51 | #define PCI_CHIP_SAVAGE_IX 0x8c13 | ||
52 | |||
53 | #define REG 0xff20 /* Serial Port 1 Register */ | ||
54 | |||
55 | /* bit locations in the register */ | ||
56 | #define DDC_ENAB 0x00040000 | ||
57 | #define DDC_SCL_OUT 0x00080000 | ||
58 | #define DDC_SDA_OUT 0x00100000 | ||
59 | #define DDC_SCL_IN 0x00200000 | ||
60 | #define DDC_SDA_IN 0x00400000 | ||
61 | #define I2C_ENAB 0x00000020 | ||
62 | #define I2C_SCL_OUT 0x00000001 | ||
63 | #define I2C_SDA_OUT 0x00000002 | ||
64 | #define I2C_SCL_IN 0x00000008 | ||
65 | #define I2C_SDA_IN 0x00000010 | ||
66 | |||
67 | /* initialization states */ | ||
68 | #define INIT2 0x20 | ||
69 | #define INIT3 0x04 | ||
70 | |||
71 | /* delays */ | ||
72 | #define CYCLE_DELAY 10 | ||
73 | #define TIMEOUT (HZ / 2) | ||
74 | |||
75 | |||
76 | static void __iomem *ioaddr; | ||
77 | |||
78 | /* The sav GPIO registers don't have individual masks for each bit | ||
79 | so we always have to read before writing. */ | ||
80 | |||
81 | static void bit_savi2c_setscl(void *data, int val) | ||
82 | { | ||
83 | unsigned int r; | ||
84 | r = readl(ioaddr + REG); | ||
85 | if(val) | ||
86 | r |= I2C_SCL_OUT; | ||
87 | else | ||
88 | r &= ~I2C_SCL_OUT; | ||
89 | writel(r, ioaddr + REG); | ||
90 | readl(ioaddr + REG); /* flush posted write */ | ||
91 | } | ||
92 | |||
93 | static void bit_savi2c_setsda(void *data, int val) | ||
94 | { | ||
95 | unsigned int r; | ||
96 | r = readl(ioaddr + REG); | ||
97 | if(val) | ||
98 | r |= I2C_SDA_OUT; | ||
99 | else | ||
100 | r &= ~I2C_SDA_OUT; | ||
101 | writel(r, ioaddr + REG); | ||
102 | readl(ioaddr + REG); /* flush posted write */ | ||
103 | } | ||
104 | |||
105 | /* The GPIO pins are open drain, so the pins always remain outputs. | ||
106 | We rely on the i2c-algo-bit routines to set the pins high before | ||
107 | reading the input from other chips. */ | ||
108 | |||
109 | static int bit_savi2c_getscl(void *data) | ||
110 | { | ||
111 | return (0 != (readl(ioaddr + REG) & I2C_SCL_IN)); | ||
112 | } | ||
113 | |||
114 | static int bit_savi2c_getsda(void *data) | ||
115 | { | ||
116 | return (0 != (readl(ioaddr + REG) & I2C_SDA_IN)); | ||
117 | } | ||
118 | |||
119 | /* Configures the chip */ | ||
120 | |||
121 | static int config_s4(struct pci_dev *dev) | ||
122 | { | ||
123 | unsigned long cadr; | ||
124 | |||
125 | /* map memory */ | ||
126 | cadr = dev->resource[0].start; | ||
127 | cadr &= PCI_BASE_ADDRESS_MEM_MASK; | ||
128 | ioaddr = ioremap_nocache(cadr, 0x0080000); | ||
129 | if (ioaddr) { | ||
130 | /* writel(0x8160, ioaddr + REG2); */ | ||
131 | writel(0x00000020, ioaddr + REG); | ||
132 | dev_info(&dev->dev, "Using Savage4 at %p\n", ioaddr); | ||
133 | return 0; | ||
134 | } | ||
135 | return -ENODEV; | ||
136 | } | ||
137 | |||
138 | static struct i2c_algo_bit_data sav_i2c_bit_data = { | ||
139 | .setsda = bit_savi2c_setsda, | ||
140 | .setscl = bit_savi2c_setscl, | ||
141 | .getsda = bit_savi2c_getsda, | ||
142 | .getscl = bit_savi2c_getscl, | ||
143 | .udelay = CYCLE_DELAY, | ||
144 | .mdelay = CYCLE_DELAY, | ||
145 | .timeout = TIMEOUT | ||
146 | }; | ||
147 | |||
148 | static struct i2c_adapter savage4_i2c_adapter = { | ||
149 | .owner = THIS_MODULE, | ||
150 | .name = "I2C Savage4 adapter", | ||
151 | .algo_data = &sav_i2c_bit_data, | ||
152 | }; | ||
153 | |||
154 | static struct pci_device_id savage4_ids[] __devinitdata = { | ||
155 | { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE4) }, | ||
156 | { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE2000) }, | ||
157 | { 0, } | ||
158 | }; | ||
159 | |||
160 | MODULE_DEVICE_TABLE (pci, savage4_ids); | ||
161 | |||
162 | static int __devinit savage4_probe(struct pci_dev *dev, const struct pci_device_id *id) | ||
163 | { | ||
164 | int retval; | ||
165 | |||
166 | retval = config_s4(dev); | ||
167 | if (retval) | ||
168 | return retval; | ||
169 | |||
170 | /* set up the sysfs linkage to our parent device */ | ||
171 | savage4_i2c_adapter.dev.parent = &dev->dev; | ||
172 | |||
173 | return i2c_bit_add_bus(&savage4_i2c_adapter); | ||
174 | } | ||
175 | |||
176 | static void __devexit savage4_remove(struct pci_dev *dev) | ||
177 | { | ||
178 | i2c_bit_del_bus(&savage4_i2c_adapter); | ||
179 | iounmap(ioaddr); | ||
180 | } | ||
181 | |||
182 | static struct pci_driver savage4_driver = { | ||
183 | .name = "savage4_smbus", | ||
184 | .id_table = savage4_ids, | ||
185 | .probe = savage4_probe, | ||
186 | .remove = __devexit_p(savage4_remove), | ||
187 | }; | ||
188 | |||
189 | static int __init i2c_savage4_init(void) | ||
190 | { | ||
191 | return pci_register_driver(&savage4_driver); | ||
192 | } | ||
193 | |||
194 | static void __exit i2c_savage4_exit(void) | ||
195 | { | ||
196 | pci_unregister_driver(&savage4_driver); | ||
197 | } | ||
198 | |||
199 | MODULE_AUTHOR("Alexander Wold <awold@bigfoot.com> " | ||
200 | "and Mark D. Studebaker <mdsxyz123@yahoo.com>"); | ||
201 | MODULE_DESCRIPTION("Savage4 I2C/SMBus driver"); | ||
202 | MODULE_LICENSE("GPL"); | ||
203 | |||
204 | module_init(i2c_savage4_init); | ||
205 | module_exit(i2c_savage4_exit); | ||
diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c new file mode 100644 index 000000000000..e5dd90bdb04a --- /dev/null +++ b/drivers/i2c/busses/i2c-sibyte.c | |||
@@ -0,0 +1,71 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004 Steven J. Hill | ||
3 | * Copyright (C) 2001,2002,2003 Broadcom Corporation | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License | ||
7 | * as published by the Free Software Foundation; either version 2 | ||
8 | * of the License, or (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/config.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/i2c-algo-sibyte.h> | ||
23 | #include <asm/sibyte/sb1250_regs.h> | ||
24 | #include <asm/sibyte/sb1250_smbus.h> | ||
25 | |||
26 | static struct i2c_algo_sibyte_data sibyte_board_data[2] = { | ||
27 | { NULL, 0, (void *) (KSEG1+A_SMB_BASE(0)) }, | ||
28 | { NULL, 1, (void *) (KSEG1+A_SMB_BASE(1)) } | ||
29 | }; | ||
30 | |||
31 | static struct i2c_adapter sibyte_board_adapter[2] = { | ||
32 | { | ||
33 | .owner = THIS_MODULE, | ||
34 | .id = I2C_HW_SIBYTE, | ||
35 | .class = I2C_CLASS_HWMON, | ||
36 | .algo = NULL, | ||
37 | .algo_data = &sibyte_board_data[0], | ||
38 | .name = "SiByte SMBus 0", | ||
39 | }, | ||
40 | { | ||
41 | .owner = THIS_MODULE, | ||
42 | .id = I2C_HW_SIBYTE, | ||
43 | .class = I2C_CLASS_HWMON, | ||
44 | .algo = NULL, | ||
45 | .algo_data = &sibyte_board_data[1], | ||
46 | .name = "SiByte SMBus 1", | ||
47 | }, | ||
48 | }; | ||
49 | |||
50 | static int __init i2c_sibyte_init(void) | ||
51 | { | ||
52 | printk("i2c-swarm.o: i2c SMBus adapter module for SiByte board\n"); | ||
53 | if (i2c_sibyte_add_bus(&sibyte_board_adapter[0], K_SMB_FREQ_100KHZ) < 0) | ||
54 | return -ENODEV; | ||
55 | if (i2c_sibyte_add_bus(&sibyte_board_adapter[1], K_SMB_FREQ_400KHZ) < 0) | ||
56 | return -ENODEV; | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static void __exit i2c_sibyte_exit(void) | ||
61 | { | ||
62 | i2c_sibyte_del_bus(&sibyte_board_adapter[0]); | ||
63 | i2c_sibyte_del_bus(&sibyte_board_adapter[1]); | ||
64 | } | ||
65 | |||
66 | module_init(i2c_sibyte_init); | ||
67 | module_exit(i2c_sibyte_exit); | ||
68 | |||
69 | MODULE_AUTHOR("Kip Walker <kwalker@broadcom.com>, Steven J. Hill <sjhill@realitydiluted.com>"); | ||
70 | MODULE_DESCRIPTION("SMBus adapter routines for SiByte boards"); | ||
71 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c new file mode 100644 index 000000000000..425733b019b6 --- /dev/null +++ b/drivers/i2c/busses/i2c-sis5595.c | |||
@@ -0,0 +1,424 @@ | |||
1 | /* | ||
2 | sis5595.c - Part of lm_sensors, Linux kernel modules for hardware | ||
3 | monitoring | ||
4 | Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and | ||
5 | Philip Edelbrock <phil@netroedge.com> | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | /* Note: we assume there can only be one SIS5595 with one SMBus interface */ | ||
23 | |||
24 | /* | ||
25 | Note: all have mfr. ID 0x1039. | ||
26 | SUPPORTED PCI ID | ||
27 | 5595 0008 | ||
28 | |||
29 | Note: these chips contain a 0008 device which is incompatible with the | ||
30 | 5595. We recognize these by the presence of the listed | ||
31 | "blacklist" PCI ID and refuse to load. | ||
32 | |||
33 | NOT SUPPORTED PCI ID BLACKLIST PCI ID | ||
34 | 540 0008 0540 | ||
35 | 550 0008 0550 | ||
36 | 5513 0008 5511 | ||
37 | 5581 0008 5597 | ||
38 | 5582 0008 5597 | ||
39 | 5597 0008 5597 | ||
40 | 5598 0008 5597/5598 | ||
41 | 630 0008 0630 | ||
42 | 645 0008 0645 | ||
43 | 646 0008 0646 | ||
44 | 648 0008 0648 | ||
45 | 650 0008 0650 | ||
46 | 651 0008 0651 | ||
47 | 730 0008 0730 | ||
48 | 735 0008 0735 | ||
49 | 745 0008 0745 | ||
50 | 746 0008 0746 | ||
51 | */ | ||
52 | |||
53 | /* TO DO: | ||
54 | * Add Block Transfers (ugly, but supported by the adapter) | ||
55 | * Add adapter resets | ||
56 | */ | ||
57 | |||
58 | #include <linux/config.h> | ||
59 | #include <linux/kernel.h> | ||
60 | #include <linux/module.h> | ||
61 | #include <linux/delay.h> | ||
62 | #include <linux/pci.h> | ||
63 | #include <linux/ioport.h> | ||
64 | #include <linux/init.h> | ||
65 | #include <linux/i2c.h> | ||
66 | #include <asm/io.h> | ||
67 | |||
68 | static int blacklist[] = { | ||
69 | PCI_DEVICE_ID_SI_540, | ||
70 | PCI_DEVICE_ID_SI_550, | ||
71 | PCI_DEVICE_ID_SI_630, | ||
72 | PCI_DEVICE_ID_SI_645, | ||
73 | PCI_DEVICE_ID_SI_646, | ||
74 | PCI_DEVICE_ID_SI_648, | ||
75 | PCI_DEVICE_ID_SI_650, | ||
76 | PCI_DEVICE_ID_SI_651, | ||
77 | PCI_DEVICE_ID_SI_730, | ||
78 | PCI_DEVICE_ID_SI_735, | ||
79 | PCI_DEVICE_ID_SI_745, | ||
80 | PCI_DEVICE_ID_SI_746, | ||
81 | PCI_DEVICE_ID_SI_5511, /* 5513 chip has the 0008 device but that ID | ||
82 | shows up in other chips so we use the 5511 | ||
83 | ID for recognition */ | ||
84 | PCI_DEVICE_ID_SI_5597, | ||
85 | PCI_DEVICE_ID_SI_5598, | ||
86 | 0, /* terminates the list */ | ||
87 | }; | ||
88 | |||
89 | /* Length of ISA address segment */ | ||
90 | #define SIS5595_EXTENT 8 | ||
91 | /* SIS5595 SMBus registers */ | ||
92 | #define SMB_STS_LO 0x00 | ||
93 | #define SMB_STS_HI 0x01 | ||
94 | #define SMB_CTL_LO 0x02 | ||
95 | #define SMB_CTL_HI 0x03 | ||
96 | #define SMB_ADDR 0x04 | ||
97 | #define SMB_CMD 0x05 | ||
98 | #define SMB_PCNT 0x06 | ||
99 | #define SMB_CNT 0x07 | ||
100 | #define SMB_BYTE 0x08 | ||
101 | #define SMB_DEV 0x10 | ||
102 | #define SMB_DB0 0x11 | ||
103 | #define SMB_DB1 0x12 | ||
104 | #define SMB_HAA 0x13 | ||
105 | |||
106 | /* PCI Address Constants */ | ||
107 | #define SMB_INDEX 0x38 | ||
108 | #define SMB_DAT 0x39 | ||
109 | #define SIS5595_ENABLE_REG 0x40 | ||
110 | #define ACPI_BASE 0x90 | ||
111 | |||
112 | /* Other settings */ | ||
113 | #define MAX_TIMEOUT 500 | ||
114 | |||
115 | /* SIS5595 constants */ | ||
116 | #define SIS5595_QUICK 0x00 | ||
117 | #define SIS5595_BYTE 0x02 | ||
118 | #define SIS5595_BYTE_DATA 0x04 | ||
119 | #define SIS5595_WORD_DATA 0x06 | ||
120 | #define SIS5595_PROC_CALL 0x08 | ||
121 | #define SIS5595_BLOCK_DATA 0x0A | ||
122 | |||
123 | /* insmod parameters */ | ||
124 | |||
125 | /* If force_addr is set to anything different from 0, we forcibly enable | ||
126 | the device at the given address. */ | ||
127 | static u16 force_addr = 0; | ||
128 | module_param(force_addr, ushort, 0); | ||
129 | MODULE_PARM_DESC(force_addr, "Initialize the base address of the i2c controller"); | ||
130 | |||
131 | static unsigned short sis5595_base = 0; | ||
132 | |||
133 | static u8 sis5595_read(u8 reg) | ||
134 | { | ||
135 | outb(reg, sis5595_base + SMB_INDEX); | ||
136 | return inb(sis5595_base + SMB_DAT); | ||
137 | } | ||
138 | |||
139 | static void sis5595_write(u8 reg, u8 data) | ||
140 | { | ||
141 | outb(reg, sis5595_base + SMB_INDEX); | ||
142 | outb(data, sis5595_base + SMB_DAT); | ||
143 | } | ||
144 | |||
145 | static int sis5595_setup(struct pci_dev *SIS5595_dev) | ||
146 | { | ||
147 | u16 a; | ||
148 | u8 val; | ||
149 | int *i; | ||
150 | int retval = -ENODEV; | ||
151 | |||
152 | /* Look for imposters */ | ||
153 | for (i = blacklist; *i != 0; i++) { | ||
154 | struct pci_dev *dev; | ||
155 | dev = pci_get_device(PCI_VENDOR_ID_SI, *i, NULL); | ||
156 | if (dev) { | ||
157 | dev_err(&SIS5595_dev->dev, "Looked for SIS5595 but found unsupported device %.4x\n", *i); | ||
158 | pci_dev_put(dev); | ||
159 | return -ENODEV; | ||
160 | } | ||
161 | } | ||
162 | |||
163 | /* Determine the address of the SMBus areas */ | ||
164 | pci_read_config_word(SIS5595_dev, ACPI_BASE, &sis5595_base); | ||
165 | if (sis5595_base == 0 && force_addr == 0) { | ||
166 | dev_err(&SIS5595_dev->dev, "ACPI base address uninitialized - upgrade BIOS or use force_addr=0xaddr\n"); | ||
167 | return -ENODEV; | ||
168 | } | ||
169 | |||
170 | if (force_addr) | ||
171 | sis5595_base = force_addr & ~(SIS5595_EXTENT - 1); | ||
172 | dev_dbg(&SIS5595_dev->dev, "ACPI Base address: %04x\n", sis5595_base); | ||
173 | |||
174 | /* NB: We grab just the two SMBus registers here, but this may still | ||
175 | * interfere with ACPI :-( */ | ||
176 | if (!request_region(sis5595_base + SMB_INDEX, 2, "sis5595-smbus")) { | ||
177 | dev_err(&SIS5595_dev->dev, "SMBus registers 0x%04x-0x%04x already in use!\n", | ||
178 | sis5595_base + SMB_INDEX, sis5595_base + SMB_INDEX + 1); | ||
179 | return -ENODEV; | ||
180 | } | ||
181 | |||
182 | if (force_addr) { | ||
183 | dev_info(&SIS5595_dev->dev, "forcing ISA address 0x%04X\n", sis5595_base); | ||
184 | if (pci_write_config_word(SIS5595_dev, ACPI_BASE, sis5595_base) | ||
185 | != PCIBIOS_SUCCESSFUL) | ||
186 | goto error; | ||
187 | if (pci_read_config_word(SIS5595_dev, ACPI_BASE, &a) | ||
188 | != PCIBIOS_SUCCESSFUL) | ||
189 | goto error; | ||
190 | if ((a & ~(SIS5595_EXTENT - 1)) != sis5595_base) { | ||
191 | /* doesn't work for some chips! */ | ||
192 | dev_err(&SIS5595_dev->dev, "force address failed - not supported?\n"); | ||
193 | goto error; | ||
194 | } | ||
195 | } | ||
196 | |||
197 | if (pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val) | ||
198 | != PCIBIOS_SUCCESSFUL) | ||
199 | goto error; | ||
200 | if ((val & 0x80) == 0) { | ||
201 | dev_info(&SIS5595_dev->dev, "enabling ACPI\n"); | ||
202 | if (pci_write_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, val | 0x80) | ||
203 | != PCIBIOS_SUCCESSFUL) | ||
204 | goto error; | ||
205 | if (pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val) | ||
206 | != PCIBIOS_SUCCESSFUL) | ||
207 | goto error; | ||
208 | if ((val & 0x80) == 0) { | ||
209 | /* doesn't work for some chips? */ | ||
210 | dev_err(&SIS5595_dev->dev, "ACPI enable failed - not supported?\n"); | ||
211 | goto error; | ||
212 | } | ||
213 | } | ||
214 | |||
215 | /* Everything is happy */ | ||
216 | return 0; | ||
217 | |||
218 | error: | ||
219 | release_region(sis5595_base + SMB_INDEX, 2); | ||
220 | return retval; | ||
221 | } | ||
222 | |||
223 | static int sis5595_transaction(struct i2c_adapter *adap) | ||
224 | { | ||
225 | int temp; | ||
226 | int result = 0; | ||
227 | int timeout = 0; | ||
228 | |||
229 | /* Make sure the SMBus host is ready to start transmitting */ | ||
230 | temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8); | ||
231 | if (temp != 0x00) { | ||
232 | dev_dbg(&adap->dev, "SMBus busy (%04x). Resetting... \n", temp); | ||
233 | sis5595_write(SMB_STS_LO, temp & 0xff); | ||
234 | sis5595_write(SMB_STS_HI, temp >> 8); | ||
235 | if ((temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) != 0x00) { | ||
236 | dev_dbg(&adap->dev, "Failed! (%02x)\n", temp); | ||
237 | return -1; | ||
238 | } else { | ||
239 | dev_dbg(&adap->dev, "Successfull!\n"); | ||
240 | } | ||
241 | } | ||
242 | |||
243 | /* start the transaction by setting bit 4 */ | ||
244 | sis5595_write(SMB_CTL_LO, sis5595_read(SMB_CTL_LO) | 0x10); | ||
245 | |||
246 | /* We will always wait for a fraction of a second! */ | ||
247 | do { | ||
248 | msleep(1); | ||
249 | temp = sis5595_read(SMB_STS_LO); | ||
250 | } while (!(temp & 0x40) && (timeout++ < MAX_TIMEOUT)); | ||
251 | |||
252 | /* If the SMBus is still busy, we give up */ | ||
253 | if (timeout >= MAX_TIMEOUT) { | ||
254 | dev_dbg(&adap->dev, "SMBus Timeout!\n"); | ||
255 | result = -1; | ||
256 | } | ||
257 | |||
258 | if (temp & 0x10) { | ||
259 | dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); | ||
260 | result = -1; | ||
261 | } | ||
262 | |||
263 | if (temp & 0x20) { | ||
264 | dev_err(&adap->dev, "Bus collision! SMBus may be locked until " | ||
265 | "next hard reset (or not...)\n"); | ||
266 | /* Clock stops and slave is stuck in mid-transmission */ | ||
267 | result = -1; | ||
268 | } | ||
269 | |||
270 | temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8); | ||
271 | if (temp != 0x00) { | ||
272 | sis5595_write(SMB_STS_LO, temp & 0xff); | ||
273 | sis5595_write(SMB_STS_HI, temp >> 8); | ||
274 | } | ||
275 | |||
276 | temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8); | ||
277 | if (temp != 0x00) | ||
278 | dev_dbg(&adap->dev, "Failed reset at end of transaction (%02x)\n", temp); | ||
279 | |||
280 | return result; | ||
281 | } | ||
282 | |||
283 | /* Return -1 on error. */ | ||
284 | static s32 sis5595_access(struct i2c_adapter *adap, u16 addr, | ||
285 | unsigned short flags, char read_write, | ||
286 | u8 command, int size, union i2c_smbus_data *data) | ||
287 | { | ||
288 | switch (size) { | ||
289 | case I2C_SMBUS_QUICK: | ||
290 | sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); | ||
291 | size = SIS5595_QUICK; | ||
292 | break; | ||
293 | case I2C_SMBUS_BYTE: | ||
294 | sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); | ||
295 | if (read_write == I2C_SMBUS_WRITE) | ||
296 | sis5595_write(SMB_CMD, command); | ||
297 | size = SIS5595_BYTE; | ||
298 | break; | ||
299 | case I2C_SMBUS_BYTE_DATA: | ||
300 | sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); | ||
301 | sis5595_write(SMB_CMD, command); | ||
302 | if (read_write == I2C_SMBUS_WRITE) | ||
303 | sis5595_write(SMB_BYTE, data->byte); | ||
304 | size = SIS5595_BYTE_DATA; | ||
305 | break; | ||
306 | case I2C_SMBUS_PROC_CALL: | ||
307 | case I2C_SMBUS_WORD_DATA: | ||
308 | sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); | ||
309 | sis5595_write(SMB_CMD, command); | ||
310 | if (read_write == I2C_SMBUS_WRITE) { | ||
311 | sis5595_write(SMB_BYTE, data->word & 0xff); | ||
312 | sis5595_write(SMB_BYTE + 1, | ||
313 | (data->word & 0xff00) >> 8); | ||
314 | } | ||
315 | size = (size == I2C_SMBUS_PROC_CALL) ? SIS5595_PROC_CALL : SIS5595_WORD_DATA; | ||
316 | break; | ||
317 | /* | ||
318 | case I2C_SMBUS_BLOCK_DATA: | ||
319 | printk(KERN_WARNING "sis5595.o: Block data not yet implemented!\n"); | ||
320 | return -1; | ||
321 | break; | ||
322 | */ | ||
323 | default: | ||
324 | printk(KERN_WARNING "sis5595.o: Unsupported transaction %d\n", size); | ||
325 | return -1; | ||
326 | } | ||
327 | |||
328 | sis5595_write(SMB_CTL_LO, ((size & 0x0E))); | ||
329 | |||
330 | if (sis5595_transaction(adap)) | ||
331 | return -1; | ||
332 | |||
333 | if ((size != SIS5595_PROC_CALL) && | ||
334 | ((read_write == I2C_SMBUS_WRITE) || (size == SIS5595_QUICK))) | ||
335 | return 0; | ||
336 | |||
337 | |||
338 | switch (size) { | ||
339 | case SIS5595_BYTE: /* Where is the result put? I assume here it is in | ||
340 | SMB_DATA but it might just as well be in the | ||
341 | SMB_CMD. No clue in the docs */ | ||
342 | case SIS5595_BYTE_DATA: | ||
343 | data->byte = sis5595_read(SMB_BYTE); | ||
344 | break; | ||
345 | case SIS5595_WORD_DATA: | ||
346 | case SIS5595_PROC_CALL: | ||
347 | data->word = sis5595_read(SMB_BYTE) + (sis5595_read(SMB_BYTE + 1) << 8); | ||
348 | break; | ||
349 | } | ||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | static u32 sis5595_func(struct i2c_adapter *adapter) | ||
354 | { | ||
355 | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | | ||
356 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | | ||
357 | I2C_FUNC_SMBUS_PROC_CALL; | ||
358 | } | ||
359 | |||
360 | static struct i2c_algorithm smbus_algorithm = { | ||
361 | .name = "Non-I2C SMBus adapter", | ||
362 | .id = I2C_ALGO_SMBUS, | ||
363 | .smbus_xfer = sis5595_access, | ||
364 | .functionality = sis5595_func, | ||
365 | }; | ||
366 | |||
367 | static struct i2c_adapter sis5595_adapter = { | ||
368 | .owner = THIS_MODULE, | ||
369 | .class = I2C_CLASS_HWMON, | ||
370 | .name = "unset", | ||
371 | .algo = &smbus_algorithm, | ||
372 | }; | ||
373 | |||
374 | static struct pci_device_id sis5595_ids[] __devinitdata = { | ||
375 | { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) }, | ||
376 | { 0, } | ||
377 | }; | ||
378 | |||
379 | MODULE_DEVICE_TABLE (pci, sis5595_ids); | ||
380 | |||
381 | static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id) | ||
382 | { | ||
383 | if (sis5595_setup(dev)) { | ||
384 | dev_err(&dev->dev, "SIS5595 not detected, module not inserted.\n"); | ||
385 | return -ENODEV; | ||
386 | } | ||
387 | |||
388 | /* set up the driverfs linkage to our parent device */ | ||
389 | sis5595_adapter.dev.parent = &dev->dev; | ||
390 | |||
391 | sprintf(sis5595_adapter.name, "SMBus SIS5595 adapter at %04x", | ||
392 | sis5595_base + SMB_INDEX); | ||
393 | return i2c_add_adapter(&sis5595_adapter); | ||
394 | } | ||
395 | |||
396 | static void __devexit sis5595_remove(struct pci_dev *dev) | ||
397 | { | ||
398 | i2c_del_adapter(&sis5595_adapter); | ||
399 | release_region(sis5595_base + SMB_INDEX, 2); | ||
400 | } | ||
401 | |||
402 | static struct pci_driver sis5595_driver = { | ||
403 | .name = "sis5595_smbus", | ||
404 | .id_table = sis5595_ids, | ||
405 | .probe = sis5595_probe, | ||
406 | .remove = __devexit_p(sis5595_remove), | ||
407 | }; | ||
408 | |||
409 | static int __init i2c_sis5595_init(void) | ||
410 | { | ||
411 | return pci_register_driver(&sis5595_driver); | ||
412 | } | ||
413 | |||
414 | static void __exit i2c_sis5595_exit(void) | ||
415 | { | ||
416 | pci_unregister_driver(&sis5595_driver); | ||
417 | } | ||
418 | |||
419 | MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"); | ||
420 | MODULE_DESCRIPTION("SIS5595 SMBus driver"); | ||
421 | MODULE_LICENSE("GPL"); | ||
422 | |||
423 | module_init(i2c_sis5595_init); | ||
424 | module_exit(i2c_sis5595_exit); | ||
diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c new file mode 100644 index 000000000000..58df63df1540 --- /dev/null +++ b/drivers/i2c/busses/i2c-sis630.c | |||
@@ -0,0 +1,523 @@ | |||
1 | /* | ||
2 | i2c-sis630.c - Part of lm_sensors, Linux kernel modules for hardware | ||
3 | monitoring | ||
4 | |||
5 | Copyright (c) 2002,2003 Alexander Malysh <amalysh@web.de> | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | /* | ||
23 | Changes: | ||
24 | 24.08.2002 | ||
25 | Fixed the typo in sis630_access (Thanks to Mark M. Hoffman) | ||
26 | Changed sis630_transaction.(Thanks to Mark M. Hoffman) | ||
27 | 18.09.2002 | ||
28 | Added SIS730 as supported. | ||
29 | 21.09.2002 | ||
30 | Added high_clock module option.If this option is set | ||
31 | used Host Master Clock 56KHz (default 14KHz).For now we save old Host | ||
32 | Master Clock and after transaction completed restore (otherwise | ||
33 | it's confuse BIOS and hung Machine). | ||
34 | 24.09.2002 | ||
35 | Fixed typo in sis630_access | ||
36 | Fixed logical error by restoring of Host Master Clock | ||
37 | 31.07.2003 | ||
38 | Added block data read/write support. | ||
39 | */ | ||
40 | |||
41 | /* | ||
42 | Status: beta | ||
43 | |||
44 | Supports: | ||
45 | SIS 630 | ||
46 | SIS 730 | ||
47 | |||
48 | Note: we assume there can only be one device, with one SMBus interface. | ||
49 | */ | ||
50 | |||
51 | #include <linux/config.h> | ||
52 | #include <linux/kernel.h> | ||
53 | #include <linux/module.h> | ||
54 | #include <linux/delay.h> | ||
55 | #include <linux/pci.h> | ||
56 | #include <linux/ioport.h> | ||
57 | #include <linux/init.h> | ||
58 | #include <linux/i2c.h> | ||
59 | #include <asm/io.h> | ||
60 | |||
61 | /* SIS630 SMBus registers */ | ||
62 | #define SMB_STS 0x80 /* status */ | ||
63 | #define SMB_EN 0x81 /* status enable */ | ||
64 | #define SMB_CNT 0x82 | ||
65 | #define SMBHOST_CNT 0x83 | ||
66 | #define SMB_ADDR 0x84 | ||
67 | #define SMB_CMD 0x85 | ||
68 | #define SMB_PCOUNT 0x86 /* processed count */ | ||
69 | #define SMB_COUNT 0x87 | ||
70 | #define SMB_BYTE 0x88 /* ~0x8F data byte field */ | ||
71 | #define SMBDEV_ADDR 0x90 | ||
72 | #define SMB_DB0 0x91 | ||
73 | #define SMB_DB1 0x92 | ||
74 | #define SMB_SAA 0x93 | ||
75 | |||
76 | /* register count for request_region */ | ||
77 | #define SIS630_SMB_IOREGION 20 | ||
78 | |||
79 | /* PCI address constants */ | ||
80 | /* acpi base address register */ | ||
81 | #define SIS630_ACPI_BASE_REG 0x74 | ||
82 | /* bios control register */ | ||
83 | #define SIS630_BIOS_CTL_REG 0x40 | ||
84 | |||
85 | /* Other settings */ | ||
86 | #define MAX_TIMEOUT 500 | ||
87 | |||
88 | /* SIS630 constants */ | ||
89 | #define SIS630_QUICK 0x00 | ||
90 | #define SIS630_BYTE 0x01 | ||
91 | #define SIS630_BYTE_DATA 0x02 | ||
92 | #define SIS630_WORD_DATA 0x03 | ||
93 | #define SIS630_PCALL 0x04 | ||
94 | #define SIS630_BLOCK_DATA 0x05 | ||
95 | |||
96 | /* insmod parameters */ | ||
97 | static int high_clock; | ||
98 | static int force; | ||
99 | module_param(high_clock, bool, 0); | ||
100 | MODULE_PARM_DESC(high_clock, "Set Host Master Clock to 56KHz (default 14KHz)."); | ||
101 | module_param(force, bool, 0); | ||
102 | MODULE_PARM_DESC(force, "Forcibly enable the SIS630. DANGEROUS!"); | ||
103 | |||
104 | /* acpi base address */ | ||
105 | static unsigned short acpi_base = 0; | ||
106 | |||
107 | /* supported chips */ | ||
108 | static int supported[] = { | ||
109 | PCI_DEVICE_ID_SI_630, | ||
110 | PCI_DEVICE_ID_SI_730, | ||
111 | 0 /* terminates the list */ | ||
112 | }; | ||
113 | |||
114 | static inline u8 sis630_read(u8 reg) | ||
115 | { | ||
116 | return inb(acpi_base + reg); | ||
117 | } | ||
118 | |||
119 | static inline void sis630_write(u8 reg, u8 data) | ||
120 | { | ||
121 | outb(data, acpi_base + reg); | ||
122 | } | ||
123 | |||
124 | static int sis630_transaction_start(struct i2c_adapter *adap, int size, u8 *oldclock) | ||
125 | { | ||
126 | int temp; | ||
127 | |||
128 | /* Make sure the SMBus host is ready to start transmitting. */ | ||
129 | if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) { | ||
130 | dev_dbg(&adap->dev, "SMBus busy (%02x).Resetting...\n",temp); | ||
131 | /* kill smbus transaction */ | ||
132 | sis630_write(SMBHOST_CNT, 0x20); | ||
133 | |||
134 | if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) { | ||
135 | dev_dbg(&adap->dev, "Failed! (%02x)\n", temp); | ||
136 | return -1; | ||
137 | } else { | ||
138 | dev_dbg(&adap->dev, "Successfull!\n"); | ||
139 | } | ||
140 | } | ||
141 | |||
142 | /* save old clock, so we can prevent machine for hung */ | ||
143 | *oldclock = sis630_read(SMB_CNT); | ||
144 | |||
145 | dev_dbg(&adap->dev, "saved clock 0x%02x\n", *oldclock); | ||
146 | |||
147 | /* disable timeout interrupt , set Host Master Clock to 56KHz if requested */ | ||
148 | if (high_clock) | ||
149 | sis630_write(SMB_CNT, 0x20); | ||
150 | else | ||
151 | sis630_write(SMB_CNT, (*oldclock & ~0x40)); | ||
152 | |||
153 | /* clear all sticky bits */ | ||
154 | temp = sis630_read(SMB_STS); | ||
155 | sis630_write(SMB_STS, temp & 0x1e); | ||
156 | |||
157 | /* start the transaction by setting bit 4 and size */ | ||
158 | sis630_write(SMBHOST_CNT,0x10 | (size & 0x07)); | ||
159 | |||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | static int sis630_transaction_wait(struct i2c_adapter *adap, int size) | ||
164 | { | ||
165 | int temp, result = 0, timeout = 0; | ||
166 | |||
167 | /* We will always wait for a fraction of a second! */ | ||
168 | do { | ||
169 | msleep(1); | ||
170 | temp = sis630_read(SMB_STS); | ||
171 | /* check if block transmitted */ | ||
172 | if (size == SIS630_BLOCK_DATA && (temp & 0x10)) | ||
173 | break; | ||
174 | } while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT)); | ||
175 | |||
176 | /* If the SMBus is still busy, we give up */ | ||
177 | if (timeout >= MAX_TIMEOUT) { | ||
178 | dev_dbg(&adap->dev, "SMBus Timeout!\n"); | ||
179 | result = -1; | ||
180 | } | ||
181 | |||
182 | if (temp & 0x02) { | ||
183 | dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); | ||
184 | result = -1; | ||
185 | } | ||
186 | |||
187 | if (temp & 0x04) { | ||
188 | dev_err(&adap->dev, "Bus collision!\n"); | ||
189 | result = -1; | ||
190 | /* | ||
191 | TBD: Datasheet say: | ||
192 | the software should clear this bit and restart SMBUS operation. | ||
193 | Should we do it or user start request again? | ||
194 | */ | ||
195 | } | ||
196 | |||
197 | return result; | ||
198 | } | ||
199 | |||
200 | static void sis630_transaction_end(struct i2c_adapter *adap, u8 oldclock) | ||
201 | { | ||
202 | int temp = 0; | ||
203 | |||
204 | /* clear all status "sticky" bits */ | ||
205 | sis630_write(SMB_STS, temp); | ||
206 | |||
207 | dev_dbg(&adap->dev, "SMB_CNT before clock restore 0x%02x\n", sis630_read(SMB_CNT)); | ||
208 | |||
209 | /* | ||
210 | * restore old Host Master Clock if high_clock is set | ||
211 | * and oldclock was not 56KHz | ||
212 | */ | ||
213 | if (high_clock && !(oldclock & 0x20)) | ||
214 | sis630_write(SMB_CNT,(sis630_read(SMB_CNT) & ~0x20)); | ||
215 | |||
216 | dev_dbg(&adap->dev, "SMB_CNT after clock restore 0x%02x\n", sis630_read(SMB_CNT)); | ||
217 | } | ||
218 | |||
219 | static int sis630_transaction(struct i2c_adapter *adap, int size) | ||
220 | { | ||
221 | int result = 0; | ||
222 | u8 oldclock = 0; | ||
223 | |||
224 | result = sis630_transaction_start(adap, size, &oldclock); | ||
225 | if (!result) { | ||
226 | result = sis630_transaction_wait(adap, size); | ||
227 | sis630_transaction_end(adap, oldclock); | ||
228 | } | ||
229 | |||
230 | return result; | ||
231 | } | ||
232 | |||
233 | static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *data, int read_write) | ||
234 | { | ||
235 | int i, len = 0, rc = 0; | ||
236 | u8 oldclock = 0; | ||
237 | |||
238 | if (read_write == I2C_SMBUS_WRITE) { | ||
239 | len = data->block[0]; | ||
240 | if (len < 0) | ||
241 | len = 0; | ||
242 | else if (len > 32) | ||
243 | len = 32; | ||
244 | sis630_write(SMB_COUNT, len); | ||
245 | for (i=1; i <= len; i++) { | ||
246 | dev_dbg(&adap->dev, "set data 0x%02x\n", data->block[i]); | ||
247 | /* set data */ | ||
248 | sis630_write(SMB_BYTE+(i-1)%8, data->block[i]); | ||
249 | if (i==8 || (len<8 && i==len)) { | ||
250 | dev_dbg(&adap->dev, "start trans len=%d i=%d\n",len ,i); | ||
251 | /* first transaction */ | ||
252 | if (sis630_transaction_start(adap, SIS630_BLOCK_DATA, &oldclock)) | ||
253 | return -1; | ||
254 | } | ||
255 | else if ((i-1)%8 == 7 || i==len) { | ||
256 | dev_dbg(&adap->dev, "trans_wait len=%d i=%d\n",len,i); | ||
257 | if (i>8) { | ||
258 | dev_dbg(&adap->dev, "clear smbary_sts len=%d i=%d\n",len,i); | ||
259 | /* | ||
260 | If this is not first transaction, | ||
261 | we must clear sticky bit. | ||
262 | clear SMBARY_STS | ||
263 | */ | ||
264 | sis630_write(SMB_STS,0x10); | ||
265 | } | ||
266 | if (sis630_transaction_wait(adap, SIS630_BLOCK_DATA)) { | ||
267 | dev_dbg(&adap->dev, "trans_wait failed\n"); | ||
268 | rc = -1; | ||
269 | break; | ||
270 | } | ||
271 | } | ||
272 | } | ||
273 | } | ||
274 | else { | ||
275 | /* read request */ | ||
276 | data->block[0] = len = 0; | ||
277 | if (sis630_transaction_start(adap, SIS630_BLOCK_DATA, &oldclock)) { | ||
278 | return -1; | ||
279 | } | ||
280 | do { | ||
281 | if (sis630_transaction_wait(adap, SIS630_BLOCK_DATA)) { | ||
282 | dev_dbg(&adap->dev, "trans_wait failed\n"); | ||
283 | rc = -1; | ||
284 | break; | ||
285 | } | ||
286 | /* if this first transaction then read byte count */ | ||
287 | if (len == 0) | ||
288 | data->block[0] = sis630_read(SMB_COUNT); | ||
289 | |||
290 | /* just to be sure */ | ||
291 | if (data->block[0] > 32) | ||
292 | data->block[0] = 32; | ||
293 | |||
294 | dev_dbg(&adap->dev, "block data read len=0x%x\n", data->block[0]); | ||
295 | |||
296 | for (i=0; i < 8 && len < data->block[0]; i++,len++) { | ||
297 | dev_dbg(&adap->dev, "read i=%d len=%d\n", i, len); | ||
298 | data->block[len+1] = sis630_read(SMB_BYTE+i); | ||
299 | } | ||
300 | |||
301 | dev_dbg(&adap->dev, "clear smbary_sts len=%d i=%d\n",len,i); | ||
302 | |||
303 | /* clear SMBARY_STS */ | ||
304 | sis630_write(SMB_STS,0x10); | ||
305 | } while(len < data->block[0]); | ||
306 | } | ||
307 | |||
308 | sis630_transaction_end(adap, oldclock); | ||
309 | |||
310 | return rc; | ||
311 | } | ||
312 | |||
313 | /* Return -1 on error. */ | ||
314 | static s32 sis630_access(struct i2c_adapter *adap, u16 addr, | ||
315 | unsigned short flags, char read_write, | ||
316 | u8 command, int size, union i2c_smbus_data *data) | ||
317 | { | ||
318 | switch (size) { | ||
319 | case I2C_SMBUS_QUICK: | ||
320 | sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); | ||
321 | size = SIS630_QUICK; | ||
322 | break; | ||
323 | case I2C_SMBUS_BYTE: | ||
324 | sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); | ||
325 | if (read_write == I2C_SMBUS_WRITE) | ||
326 | sis630_write(SMB_CMD, command); | ||
327 | size = SIS630_BYTE; | ||
328 | break; | ||
329 | case I2C_SMBUS_BYTE_DATA: | ||
330 | sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); | ||
331 | sis630_write(SMB_CMD, command); | ||
332 | if (read_write == I2C_SMBUS_WRITE) | ||
333 | sis630_write(SMB_BYTE, data->byte); | ||
334 | size = SIS630_BYTE_DATA; | ||
335 | break; | ||
336 | case I2C_SMBUS_PROC_CALL: | ||
337 | case I2C_SMBUS_WORD_DATA: | ||
338 | sis630_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01)); | ||
339 | sis630_write(SMB_CMD, command); | ||
340 | if (read_write == I2C_SMBUS_WRITE) { | ||
341 | sis630_write(SMB_BYTE, data->word & 0xff); | ||
342 | sis630_write(SMB_BYTE + 1,(data->word & 0xff00) >> 8); | ||
343 | } | ||
344 | size = (size == I2C_SMBUS_PROC_CALL ? SIS630_PCALL : SIS630_WORD_DATA); | ||
345 | break; | ||
346 | case I2C_SMBUS_BLOCK_DATA: | ||
347 | sis630_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01)); | ||
348 | sis630_write(SMB_CMD, command); | ||
349 | size = SIS630_BLOCK_DATA; | ||
350 | return sis630_block_data(adap, data, read_write); | ||
351 | default: | ||
352 | printk("Unsupported I2C size\n"); | ||
353 | return -1; | ||
354 | break; | ||
355 | } | ||
356 | |||
357 | if (sis630_transaction(adap, size)) | ||
358 | return -1; | ||
359 | |||
360 | if ((size != SIS630_PCALL) && | ||
361 | ((read_write == I2C_SMBUS_WRITE) || (size == SIS630_QUICK))) { | ||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | switch(size) { | ||
366 | case SIS630_BYTE: | ||
367 | case SIS630_BYTE_DATA: | ||
368 | data->byte = sis630_read(SMB_BYTE); | ||
369 | break; | ||
370 | case SIS630_PCALL: | ||
371 | case SIS630_WORD_DATA: | ||
372 | data->word = sis630_read(SMB_BYTE) + (sis630_read(SMB_BYTE + 1) << 8); | ||
373 | break; | ||
374 | default: | ||
375 | return -1; | ||
376 | break; | ||
377 | } | ||
378 | |||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | static u32 sis630_func(struct i2c_adapter *adapter) | ||
383 | { | ||
384 | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | | ||
385 | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL | | ||
386 | I2C_FUNC_SMBUS_BLOCK_DATA; | ||
387 | } | ||
388 | |||
389 | static int sis630_setup(struct pci_dev *sis630_dev) | ||
390 | { | ||
391 | unsigned char b; | ||
392 | struct pci_dev *dummy = NULL; | ||
393 | int retval = -ENODEV, i; | ||
394 | |||
395 | /* check for supported SiS devices */ | ||
396 | for (i=0; supported[i] > 0 ; i++) { | ||
397 | if ((dummy = pci_get_device(PCI_VENDOR_ID_SI, supported[i], dummy))) | ||
398 | break; /* found */ | ||
399 | } | ||
400 | |||
401 | if (dummy) { | ||
402 | pci_dev_put(dummy); | ||
403 | } | ||
404 | else if (force) { | ||
405 | dev_err(&sis630_dev->dev, "WARNING: Can't detect SIS630 compatible device, but " | ||
406 | "loading because of force option enabled\n"); | ||
407 | } | ||
408 | else { | ||
409 | return -ENODEV; | ||
410 | } | ||
411 | |||
412 | /* | ||
413 | Enable ACPI first , so we can accsess reg 74-75 | ||
414 | in acpi io space and read acpi base addr | ||
415 | */ | ||
416 | if (pci_read_config_byte(sis630_dev, SIS630_BIOS_CTL_REG,&b)) { | ||
417 | dev_err(&sis630_dev->dev, "Error: Can't read bios ctl reg\n"); | ||
418 | goto exit; | ||
419 | } | ||
420 | /* if ACPI already enabled , do nothing */ | ||
421 | if (!(b & 0x80) && | ||
422 | pci_write_config_byte(sis630_dev, SIS630_BIOS_CTL_REG, b | 0x80)) { | ||
423 | dev_err(&sis630_dev->dev, "Error: Can't enable ACPI\n"); | ||
424 | goto exit; | ||
425 | } | ||
426 | |||
427 | /* Determine the ACPI base address */ | ||
428 | if (pci_read_config_word(sis630_dev,SIS630_ACPI_BASE_REG,&acpi_base)) { | ||
429 | dev_err(&sis630_dev->dev, "Error: Can't determine ACPI base address\n"); | ||
430 | goto exit; | ||
431 | } | ||
432 | |||
433 | dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04x\n", acpi_base); | ||
434 | |||
435 | /* Everything is happy, let's grab the memory and set things up. */ | ||
436 | if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION, "sis630-smbus")) { | ||
437 | dev_err(&sis630_dev->dev, "SMBus registers 0x%04x-0x%04x already " | ||
438 | "in use!\n", acpi_base + SMB_STS, acpi_base + SMB_SAA); | ||
439 | goto exit; | ||
440 | } | ||
441 | |||
442 | retval = 0; | ||
443 | |||
444 | exit: | ||
445 | if (retval) | ||
446 | acpi_base = 0; | ||
447 | return retval; | ||
448 | } | ||
449 | |||
450 | |||
451 | static struct i2c_algorithm smbus_algorithm = { | ||
452 | .name = "Non-I2C SMBus adapter", | ||
453 | .id = I2C_ALGO_SMBUS, | ||
454 | .smbus_xfer = sis630_access, | ||
455 | .functionality = sis630_func, | ||
456 | }; | ||
457 | |||
458 | static struct i2c_adapter sis630_adapter = { | ||
459 | .owner = THIS_MODULE, | ||
460 | .class = I2C_CLASS_HWMON, | ||
461 | .name = "unset", | ||
462 | .algo = &smbus_algorithm, | ||
463 | }; | ||
464 | |||
465 | static struct pci_device_id sis630_ids[] __devinitdata = { | ||
466 | { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) }, | ||
467 | { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC) }, | ||
468 | { 0, } | ||
469 | }; | ||
470 | |||
471 | MODULE_DEVICE_TABLE (pci, sis630_ids); | ||
472 | |||
473 | static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_id *id) | ||
474 | { | ||
475 | if (sis630_setup(dev)) { | ||
476 | dev_err(&dev->dev, "SIS630 comp. bus not detected, module not inserted.\n"); | ||
477 | return -ENODEV; | ||
478 | } | ||
479 | |||
480 | /* set up the driverfs linkage to our parent device */ | ||
481 | sis630_adapter.dev.parent = &dev->dev; | ||
482 | |||
483 | sprintf(sis630_adapter.name, "SMBus SIS630 adapter at %04x", | ||
484 | acpi_base + SMB_STS); | ||
485 | |||
486 | return i2c_add_adapter(&sis630_adapter); | ||
487 | } | ||
488 | |||
489 | static void __devexit sis630_remove(struct pci_dev *dev) | ||
490 | { | ||
491 | if (acpi_base) { | ||
492 | i2c_del_adapter(&sis630_adapter); | ||
493 | release_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION); | ||
494 | acpi_base = 0; | ||
495 | } | ||
496 | } | ||
497 | |||
498 | |||
499 | static struct pci_driver sis630_driver = { | ||
500 | .name = "sis630_smbus", | ||
501 | .id_table = sis630_ids, | ||
502 | .probe = sis630_probe, | ||
503 | .remove = __devexit_p(sis630_remove), | ||
504 | }; | ||
505 | |||
506 | static int __init i2c_sis630_init(void) | ||
507 | { | ||
508 | return pci_register_driver(&sis630_driver); | ||
509 | } | ||
510 | |||
511 | |||
512 | static void __exit i2c_sis630_exit(void) | ||
513 | { | ||
514 | pci_unregister_driver(&sis630_driver); | ||
515 | } | ||
516 | |||
517 | |||
518 | MODULE_LICENSE("GPL"); | ||
519 | MODULE_AUTHOR("Alexander Malysh <amalysh@web.de>"); | ||
520 | MODULE_DESCRIPTION("SIS630 SMBus driver"); | ||
521 | |||
522 | module_init(i2c_sis630_init); | ||
523 | module_exit(i2c_sis630_exit); | ||
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c new file mode 100644 index 000000000000..3cac6d43bce5 --- /dev/null +++ b/drivers/i2c/busses/i2c-sis96x.c | |||
@@ -0,0 +1,358 @@ | |||
1 | /* | ||
2 | sis96x.c - Part of lm_sensors, Linux kernel modules for hardware | ||
3 | monitoring | ||
4 | |||
5 | Copyright (c) 2003 Mark M. Hoffman <mhoffman@lightlink.com> | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | /* | ||
23 | This module must be considered BETA unless and until | ||
24 | the chipset manufacturer releases a datasheet. | ||
25 | The register definitions are based on the SiS630. | ||
26 | |||
27 | This module relies on quirk_sis_96x_smbus (drivers/pci/quirks.c) | ||
28 | for just about every machine for which users have reported. | ||
29 | If this module isn't detecting your 96x south bridge, have a | ||
30 | look there. | ||
31 | |||
32 | We assume there can only be one SiS96x with one SMBus interface. | ||
33 | */ | ||
34 | |||
35 | #include <linux/config.h> | ||
36 | #include <linux/module.h> | ||
37 | #include <linux/pci.h> | ||
38 | #include <linux/kernel.h> | ||
39 | #include <linux/delay.h> | ||
40 | #include <linux/stddef.h> | ||
41 | #include <linux/sched.h> | ||
42 | #include <linux/ioport.h> | ||
43 | #include <linux/i2c.h> | ||
44 | #include <linux/init.h> | ||
45 | #include <asm/io.h> | ||
46 | |||
47 | /* | ||
48 | HISTORY: | ||
49 | 2003-05-11 1.0.0 Updated from lm_sensors project for kernel 2.5 | ||
50 | (was i2c-sis645.c from lm_sensors 2.7.0) | ||
51 | */ | ||
52 | #define SIS96x_VERSION "1.0.0" | ||
53 | |||
54 | /* base address register in PCI config space */ | ||
55 | #define SIS96x_BAR 0x04 | ||
56 | |||
57 | /* SiS96x SMBus registers */ | ||
58 | #define SMB_STS 0x00 | ||
59 | #define SMB_EN 0x01 | ||
60 | #define SMB_CNT 0x02 | ||
61 | #define SMB_HOST_CNT 0x03 | ||
62 | #define SMB_ADDR 0x04 | ||
63 | #define SMB_CMD 0x05 | ||
64 | #define SMB_PCOUNT 0x06 | ||
65 | #define SMB_COUNT 0x07 | ||
66 | #define SMB_BYTE 0x08 | ||
67 | #define SMB_DEV_ADDR 0x10 | ||
68 | #define SMB_DB0 0x11 | ||
69 | #define SMB_DB1 0x12 | ||
70 | #define SMB_SAA 0x13 | ||
71 | |||
72 | /* register count for request_region */ | ||
73 | #define SMB_IOSIZE 0x20 | ||
74 | |||
75 | /* Other settings */ | ||
76 | #define MAX_TIMEOUT 500 | ||
77 | |||
78 | /* SiS96x SMBus constants */ | ||
79 | #define SIS96x_QUICK 0x00 | ||
80 | #define SIS96x_BYTE 0x01 | ||
81 | #define SIS96x_BYTE_DATA 0x02 | ||
82 | #define SIS96x_WORD_DATA 0x03 | ||
83 | #define SIS96x_PROC_CALL 0x04 | ||
84 | #define SIS96x_BLOCK_DATA 0x05 | ||
85 | |||
86 | static struct i2c_adapter sis96x_adapter; | ||
87 | static u16 sis96x_smbus_base = 0; | ||
88 | |||
89 | static inline u8 sis96x_read(u8 reg) | ||
90 | { | ||
91 | return inb(sis96x_smbus_base + reg) ; | ||
92 | } | ||
93 | |||
94 | static inline void sis96x_write(u8 reg, u8 data) | ||
95 | { | ||
96 | outb(data, sis96x_smbus_base + reg) ; | ||
97 | } | ||
98 | |||
99 | /* Execute a SMBus transaction. | ||
100 | int size is from SIS96x_QUICK to SIS96x_BLOCK_DATA | ||
101 | */ | ||
102 | static int sis96x_transaction(int size) | ||
103 | { | ||
104 | int temp; | ||
105 | int result = 0; | ||
106 | int timeout = 0; | ||
107 | |||
108 | dev_dbg(&sis96x_adapter.dev, "SMBus transaction %d\n", size); | ||
109 | |||
110 | /* Make sure the SMBus host is ready to start transmitting */ | ||
111 | if (((temp = sis96x_read(SMB_CNT)) & 0x03) != 0x00) { | ||
112 | |||
113 | dev_dbg(&sis96x_adapter.dev, "SMBus busy (0x%02x). " | ||
114 | "Resetting...\n", temp); | ||
115 | |||
116 | /* kill the transaction */ | ||
117 | sis96x_write(SMB_HOST_CNT, 0x20); | ||
118 | |||
119 | /* check it again */ | ||
120 | if (((temp = sis96x_read(SMB_CNT)) & 0x03) != 0x00) { | ||
121 | dev_dbg(&sis96x_adapter.dev, "Failed (0x%02x)\n", temp); | ||
122 | return -1; | ||
123 | } else { | ||
124 | dev_dbg(&sis96x_adapter.dev, "Successful\n"); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | /* Turn off timeout interrupts, set fast host clock */ | ||
129 | sis96x_write(SMB_CNT, 0x20); | ||
130 | |||
131 | /* clear all (sticky) status flags */ | ||
132 | temp = sis96x_read(SMB_STS); | ||
133 | sis96x_write(SMB_STS, temp & 0x1e); | ||
134 | |||
135 | /* start the transaction by setting bit 4 and size bits */ | ||
136 | sis96x_write(SMB_HOST_CNT, 0x10 | (size & 0x07)); | ||
137 | |||
138 | /* We will always wait for a fraction of a second! */ | ||
139 | do { | ||
140 | msleep(1); | ||
141 | temp = sis96x_read(SMB_STS); | ||
142 | } while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT)); | ||
143 | |||
144 | /* If the SMBus is still busy, we give up */ | ||
145 | if (timeout >= MAX_TIMEOUT) { | ||
146 | dev_dbg(&sis96x_adapter.dev, "SMBus Timeout! (0x%02x)\n", temp); | ||
147 | result = -1; | ||
148 | } | ||
149 | |||
150 | /* device error - probably missing ACK */ | ||
151 | if (temp & 0x02) { | ||
152 | dev_dbg(&sis96x_adapter.dev, "Failed bus transaction!\n"); | ||
153 | result = -1; | ||
154 | } | ||
155 | |||
156 | /* bus collision */ | ||
157 | if (temp & 0x04) { | ||
158 | dev_dbg(&sis96x_adapter.dev, "Bus collision!\n"); | ||
159 | result = -1; | ||
160 | } | ||
161 | |||
162 | /* Finish up by resetting the bus */ | ||
163 | sis96x_write(SMB_STS, temp); | ||
164 | if ((temp = sis96x_read(SMB_STS))) { | ||
165 | dev_dbg(&sis96x_adapter.dev, "Failed reset at " | ||
166 | "end of transaction! (0x%02x)\n", temp); | ||
167 | } | ||
168 | |||
169 | return result; | ||
170 | } | ||
171 | |||
172 | /* Return -1 on error. */ | ||
173 | static s32 sis96x_access(struct i2c_adapter * adap, u16 addr, | ||
174 | unsigned short flags, char read_write, | ||
175 | u8 command, int size, union i2c_smbus_data * data) | ||
176 | { | ||
177 | |||
178 | switch (size) { | ||
179 | case I2C_SMBUS_QUICK: | ||
180 | sis96x_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); | ||
181 | size = SIS96x_QUICK; | ||
182 | break; | ||
183 | |||
184 | case I2C_SMBUS_BYTE: | ||
185 | sis96x_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); | ||
186 | if (read_write == I2C_SMBUS_WRITE) | ||
187 | sis96x_write(SMB_CMD, command); | ||
188 | size = SIS96x_BYTE; | ||
189 | break; | ||
190 | |||
191 | case I2C_SMBUS_BYTE_DATA: | ||
192 | sis96x_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); | ||
193 | sis96x_write(SMB_CMD, command); | ||
194 | if (read_write == I2C_SMBUS_WRITE) | ||
195 | sis96x_write(SMB_BYTE, data->byte); | ||
196 | size = SIS96x_BYTE_DATA; | ||
197 | break; | ||
198 | |||
199 | case I2C_SMBUS_PROC_CALL: | ||
200 | case I2C_SMBUS_WORD_DATA: | ||
201 | sis96x_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); | ||
202 | sis96x_write(SMB_CMD, command); | ||
203 | if (read_write == I2C_SMBUS_WRITE) { | ||
204 | sis96x_write(SMB_BYTE, data->word & 0xff); | ||
205 | sis96x_write(SMB_BYTE + 1, (data->word & 0xff00) >> 8); | ||
206 | } | ||
207 | size = (size == I2C_SMBUS_PROC_CALL ? | ||
208 | SIS96x_PROC_CALL : SIS96x_WORD_DATA); | ||
209 | break; | ||
210 | |||
211 | case I2C_SMBUS_BLOCK_DATA: | ||
212 | /* TO DO: */ | ||
213 | dev_info(&adap->dev, "SMBus block not implemented!\n"); | ||
214 | return -1; | ||
215 | break; | ||
216 | |||
217 | default: | ||
218 | dev_info(&adap->dev, "Unsupported I2C size\n"); | ||
219 | return -1; | ||
220 | break; | ||
221 | } | ||
222 | |||
223 | if (sis96x_transaction(size)) | ||
224 | return -1; | ||
225 | |||
226 | if ((size != SIS96x_PROC_CALL) && | ||
227 | ((read_write == I2C_SMBUS_WRITE) || (size == SIS96x_QUICK))) | ||
228 | return 0; | ||
229 | |||
230 | switch (size) { | ||
231 | case SIS96x_BYTE: | ||
232 | case SIS96x_BYTE_DATA: | ||
233 | data->byte = sis96x_read(SMB_BYTE); | ||
234 | break; | ||
235 | |||
236 | case SIS96x_WORD_DATA: | ||
237 | case SIS96x_PROC_CALL: | ||
238 | data->word = sis96x_read(SMB_BYTE) + | ||
239 | (sis96x_read(SMB_BYTE + 1) << 8); | ||
240 | break; | ||
241 | } | ||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | static u32 sis96x_func(struct i2c_adapter *adapter) | ||
246 | { | ||
247 | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | | ||
248 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | | ||
249 | I2C_FUNC_SMBUS_PROC_CALL; | ||
250 | } | ||
251 | |||
252 | static struct i2c_algorithm smbus_algorithm = { | ||
253 | .name = "Non-I2C SMBus adapter", | ||
254 | .id = I2C_ALGO_SMBUS, | ||
255 | .smbus_xfer = sis96x_access, | ||
256 | .functionality = sis96x_func, | ||
257 | }; | ||
258 | |||
259 | static struct i2c_adapter sis96x_adapter = { | ||
260 | .owner = THIS_MODULE, | ||
261 | .class = I2C_CLASS_HWMON, | ||
262 | .algo = &smbus_algorithm, | ||
263 | .name = "unset", | ||
264 | }; | ||
265 | |||
266 | static struct pci_device_id sis96x_ids[] = { | ||
267 | { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_SMBUS) }, | ||
268 | { 0, } | ||
269 | }; | ||
270 | |||
271 | MODULE_DEVICE_TABLE (pci, sis96x_ids); | ||
272 | |||
273 | static int __devinit sis96x_probe(struct pci_dev *dev, | ||
274 | const struct pci_device_id *id) | ||
275 | { | ||
276 | u16 ww = 0; | ||
277 | int retval; | ||
278 | |||
279 | if (sis96x_smbus_base) { | ||
280 | dev_err(&dev->dev, "Only one device supported.\n"); | ||
281 | return -EBUSY; | ||
282 | } | ||
283 | |||
284 | pci_read_config_word(dev, PCI_CLASS_DEVICE, &ww); | ||
285 | if (PCI_CLASS_SERIAL_SMBUS != ww) { | ||
286 | dev_err(&dev->dev, "Unsupported device class 0x%04x!\n", ww); | ||
287 | return -ENODEV; | ||
288 | } | ||
289 | |||
290 | sis96x_smbus_base = pci_resource_start(dev, SIS96x_BAR); | ||
291 | if (!sis96x_smbus_base) { | ||
292 | dev_err(&dev->dev, "SiS96x SMBus base address " | ||
293 | "not initialized!\n"); | ||
294 | return -EINVAL; | ||
295 | } | ||
296 | dev_info(&dev->dev, "SiS96x SMBus base address: 0x%04x\n", | ||
297 | sis96x_smbus_base); | ||
298 | |||
299 | /* Everything is happy, let's grab the memory and set things up. */ | ||
300 | if (!request_region(sis96x_smbus_base, SMB_IOSIZE, "sis96x-smbus")) { | ||
301 | dev_err(&dev->dev, "SMBus registers 0x%04x-0x%04x " | ||
302 | "already in use!\n", sis96x_smbus_base, | ||
303 | sis96x_smbus_base + SMB_IOSIZE - 1); | ||
304 | |||
305 | sis96x_smbus_base = 0; | ||
306 | return -EINVAL; | ||
307 | } | ||
308 | |||
309 | /* set up the driverfs linkage to our parent device */ | ||
310 | sis96x_adapter.dev.parent = &dev->dev; | ||
311 | |||
312 | snprintf(sis96x_adapter.name, I2C_NAME_SIZE, | ||
313 | "SiS96x SMBus adapter at 0x%04x", sis96x_smbus_base); | ||
314 | |||
315 | if ((retval = i2c_add_adapter(&sis96x_adapter))) { | ||
316 | dev_err(&dev->dev, "Couldn't register adapter!\n"); | ||
317 | release_region(sis96x_smbus_base, SMB_IOSIZE); | ||
318 | sis96x_smbus_base = 0; | ||
319 | } | ||
320 | |||
321 | return retval; | ||
322 | } | ||
323 | |||
324 | static void __devexit sis96x_remove(struct pci_dev *dev) | ||
325 | { | ||
326 | if (sis96x_smbus_base) { | ||
327 | i2c_del_adapter(&sis96x_adapter); | ||
328 | release_region(sis96x_smbus_base, SMB_IOSIZE); | ||
329 | sis96x_smbus_base = 0; | ||
330 | } | ||
331 | } | ||
332 | |||
333 | static struct pci_driver sis96x_driver = { | ||
334 | .name = "sis96x_smbus", | ||
335 | .id_table = sis96x_ids, | ||
336 | .probe = sis96x_probe, | ||
337 | .remove = __devexit_p(sis96x_remove), | ||
338 | }; | ||
339 | |||
340 | static int __init i2c_sis96x_init(void) | ||
341 | { | ||
342 | printk(KERN_INFO "i2c-sis96x version %s\n", SIS96x_VERSION); | ||
343 | return pci_register_driver(&sis96x_driver); | ||
344 | } | ||
345 | |||
346 | static void __exit i2c_sis96x_exit(void) | ||
347 | { | ||
348 | pci_unregister_driver(&sis96x_driver); | ||
349 | } | ||
350 | |||
351 | MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>"); | ||
352 | MODULE_DESCRIPTION("SiS96x SMBus driver"); | ||
353 | MODULE_LICENSE("GPL"); | ||
354 | |||
355 | /* Register initialization functions using helper macros */ | ||
356 | module_init(i2c_sis96x_init); | ||
357 | module_exit(i2c_sis96x_exit); | ||
358 | |||
diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/busses/i2c-stub.c new file mode 100644 index 000000000000..19c805ead4d8 --- /dev/null +++ b/drivers/i2c/busses/i2c-stub.c | |||
@@ -0,0 +1,143 @@ | |||
1 | /* | ||
2 | i2c-stub.c - Part of lm_sensors, Linux kernel modules for hardware | ||
3 | monitoring | ||
4 | |||
5 | Copyright (c) 2004 Mark M. Hoffman <mhoffman@lightlink.com> | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #define DEBUG 1 | ||
23 | |||
24 | #include <linux/config.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/errno.h> | ||
29 | #include <linux/i2c.h> | ||
30 | |||
31 | static u8 stub_pointer; | ||
32 | static u8 stub_bytes[256]; | ||
33 | static u16 stub_words[256]; | ||
34 | |||
35 | /* Return -1 on error. */ | ||
36 | static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, | ||
37 | char read_write, u8 command, int size, union i2c_smbus_data * data) | ||
38 | { | ||
39 | s32 ret; | ||
40 | |||
41 | switch (size) { | ||
42 | |||
43 | case I2C_SMBUS_QUICK: | ||
44 | dev_dbg(&adap->dev, "smbus quick - addr 0x%02x\n", addr); | ||
45 | ret = 0; | ||
46 | break; | ||
47 | |||
48 | case I2C_SMBUS_BYTE: | ||
49 | if (read_write == I2C_SMBUS_WRITE) { | ||
50 | stub_pointer = command; | ||
51 | dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, " | ||
52 | "wrote 0x%02x.\n", | ||
53 | addr, command); | ||
54 | } else { | ||
55 | data->byte = stub_bytes[stub_pointer++]; | ||
56 | dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, " | ||
57 | "read 0x%02x.\n", | ||
58 | addr, data->byte); | ||
59 | } | ||
60 | |||
61 | ret = 0; | ||
62 | break; | ||
63 | |||
64 | case I2C_SMBUS_BYTE_DATA: | ||
65 | if (read_write == I2C_SMBUS_WRITE) { | ||
66 | stub_bytes[command] = data->byte; | ||
67 | dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, " | ||
68 | "wrote 0x%02x at 0x%02x.\n", | ||
69 | addr, data->byte, command); | ||
70 | } else { | ||
71 | data->byte = stub_bytes[command]; | ||
72 | dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, " | ||
73 | "read 0x%02x at 0x%02x.\n", | ||
74 | addr, data->byte, command); | ||
75 | } | ||
76 | stub_pointer = command + 1; | ||
77 | |||
78 | ret = 0; | ||
79 | break; | ||
80 | |||
81 | case I2C_SMBUS_WORD_DATA: | ||
82 | if (read_write == I2C_SMBUS_WRITE) { | ||
83 | stub_words[command] = data->word; | ||
84 | dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, " | ||
85 | "wrote 0x%04x at 0x%02x.\n", | ||
86 | addr, data->word, command); | ||
87 | } else { | ||
88 | data->word = stub_words[command]; | ||
89 | dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, " | ||
90 | "read 0x%04x at 0x%02x.\n", | ||
91 | addr, data->word, command); | ||
92 | } | ||
93 | |||
94 | ret = 0; | ||
95 | break; | ||
96 | |||
97 | default: | ||
98 | dev_dbg(&adap->dev, "Unsupported I2C/SMBus command\n"); | ||
99 | ret = -1; | ||
100 | break; | ||
101 | } /* switch (size) */ | ||
102 | |||
103 | return ret; | ||
104 | } | ||
105 | |||
106 | static u32 stub_func(struct i2c_adapter *adapter) | ||
107 | { | ||
108 | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | | ||
109 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA; | ||
110 | } | ||
111 | |||
112 | static struct i2c_algorithm smbus_algorithm = { | ||
113 | .name = "Non-I2C SMBus adapter", | ||
114 | .id = I2C_ALGO_SMBUS, | ||
115 | .functionality = stub_func, | ||
116 | .smbus_xfer = stub_xfer, | ||
117 | }; | ||
118 | |||
119 | static struct i2c_adapter stub_adapter = { | ||
120 | .owner = THIS_MODULE, | ||
121 | .class = I2C_CLASS_HWMON, | ||
122 | .algo = &smbus_algorithm, | ||
123 | .name = "SMBus stub driver", | ||
124 | }; | ||
125 | |||
126 | static int __init i2c_stub_init(void) | ||
127 | { | ||
128 | printk(KERN_INFO "i2c-stub loaded\n"); | ||
129 | return i2c_add_adapter(&stub_adapter); | ||
130 | } | ||
131 | |||
132 | static void __exit i2c_stub_exit(void) | ||
133 | { | ||
134 | i2c_del_adapter(&stub_adapter); | ||
135 | } | ||
136 | |||
137 | MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>"); | ||
138 | MODULE_DESCRIPTION("I2C stub driver"); | ||
139 | MODULE_LICENSE("GPL"); | ||
140 | |||
141 | module_init(i2c_stub_init); | ||
142 | module_exit(i2c_stub_exit); | ||
143 | |||
diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c new file mode 100644 index 000000000000..2cbc4cd22366 --- /dev/null +++ b/drivers/i2c/busses/i2c-via.c | |||
@@ -0,0 +1,185 @@ | |||
1 | /* | ||
2 | i2c-via.c - Part of lm_sensors, Linux kernel modules | ||
3 | for hardware monitoring | ||
4 | |||
5 | i2c Support for Via Technologies 82C586B South Bridge | ||
6 | |||
7 | Copyright (c) 1998, 1999 Kyösti Mälkki <kmalkki@cc.hut.fi> | ||
8 | |||
9 | This program is free software; you can redistribute it and/or modify | ||
10 | it under the terms of the GNU General Public License as published by | ||
11 | the Free Software Foundation; either version 2 of the License, or | ||
12 | (at your option) any later version. | ||
13 | |||
14 | This program is distributed in the hope that it will be useful, | ||
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | GNU General Public License for more details. | ||
18 | |||
19 | You should have received a copy of the GNU General Public License | ||
20 | along with this program; if not, write to the Free Software | ||
21 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/config.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/pci.h> | ||
28 | #include <linux/ioport.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/i2c.h> | ||
31 | #include <linux/i2c-algo-bit.h> | ||
32 | #include <asm/io.h> | ||
33 | |||
34 | /* Power management registers */ | ||
35 | #define PM_CFG_REVID 0x08 /* silicon revision code */ | ||
36 | #define PM_CFG_IOBASE0 0x20 | ||
37 | #define PM_CFG_IOBASE1 0x48 | ||
38 | |||
39 | #define I2C_DIR (pm_io_base+0x40) | ||
40 | #define I2C_OUT (pm_io_base+0x42) | ||
41 | #define I2C_IN (pm_io_base+0x44) | ||
42 | #define I2C_SCL 0x02 /* clock bit in DIR/OUT/IN register */ | ||
43 | #define I2C_SDA 0x04 | ||
44 | |||
45 | /* io-region reservation */ | ||
46 | #define IOSPACE 0x06 | ||
47 | #define IOTEXT "via-i2c" | ||
48 | |||
49 | static u16 pm_io_base = 0; | ||
50 | |||
51 | /* | ||
52 | It does not appear from the datasheet that the GPIO pins are | ||
53 | open drain. So a we set a low value by setting the direction to | ||
54 | output and a high value by setting the direction to input and | ||
55 | relying on the required I2C pullup. The data value is initialized | ||
56 | to 0 in via_init() and never changed. | ||
57 | */ | ||
58 | static void bit_via_setscl(void *data, int state) | ||
59 | { | ||
60 | outb(state ? inb(I2C_DIR) & ~I2C_SCL : inb(I2C_DIR) | I2C_SCL, I2C_DIR); | ||
61 | } | ||
62 | |||
63 | static void bit_via_setsda(void *data, int state) | ||
64 | { | ||
65 | outb(state ? inb(I2C_DIR) & ~I2C_SDA : inb(I2C_DIR) | I2C_SDA, I2C_DIR); | ||
66 | } | ||
67 | |||
68 | static int bit_via_getscl(void *data) | ||
69 | { | ||
70 | return (0 != (inb(I2C_IN) & I2C_SCL)); | ||
71 | } | ||
72 | |||
73 | static int bit_via_getsda(void *data) | ||
74 | { | ||
75 | return (0 != (inb(I2C_IN) & I2C_SDA)); | ||
76 | } | ||
77 | |||
78 | |||
79 | static struct i2c_algo_bit_data bit_data = { | ||
80 | .setsda = bit_via_setsda, | ||
81 | .setscl = bit_via_setscl, | ||
82 | .getsda = bit_via_getsda, | ||
83 | .getscl = bit_via_getscl, | ||
84 | .udelay = 5, | ||
85 | .mdelay = 5, | ||
86 | .timeout = HZ | ||
87 | }; | ||
88 | |||
89 | static struct i2c_adapter vt586b_adapter = { | ||
90 | .owner = THIS_MODULE, | ||
91 | .class = I2C_CLASS_HWMON, | ||
92 | .name = "VIA i2c", | ||
93 | .algo_data = &bit_data, | ||
94 | }; | ||
95 | |||
96 | |||
97 | static struct pci_device_id vt586b_ids[] __devinitdata = { | ||
98 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3) }, | ||
99 | { 0, } | ||
100 | }; | ||
101 | |||
102 | MODULE_DEVICE_TABLE (pci, vt586b_ids); | ||
103 | |||
104 | static int __devinit vt586b_probe(struct pci_dev *dev, const struct pci_device_id *id) | ||
105 | { | ||
106 | u16 base; | ||
107 | u8 rev; | ||
108 | int res; | ||
109 | |||
110 | if (pm_io_base) { | ||
111 | dev_err(&dev->dev, "i2c-via: Will only support one host\n"); | ||
112 | return -ENODEV; | ||
113 | } | ||
114 | |||
115 | pci_read_config_byte(dev, PM_CFG_REVID, &rev); | ||
116 | |||
117 | switch (rev) { | ||
118 | case 0x00: | ||
119 | base = PM_CFG_IOBASE0; | ||
120 | break; | ||
121 | case 0x01: | ||
122 | case 0x10: | ||
123 | base = PM_CFG_IOBASE1; | ||
124 | break; | ||
125 | |||
126 | default: | ||
127 | base = PM_CFG_IOBASE1; | ||
128 | /* later revision */ | ||
129 | } | ||
130 | |||
131 | pci_read_config_word(dev, base, &pm_io_base); | ||
132 | pm_io_base &= (0xff << 8); | ||
133 | |||
134 | if (!request_region(I2C_DIR, IOSPACE, IOTEXT)) { | ||
135 | dev_err(&dev->dev, "IO 0x%x-0x%x already in use\n", I2C_DIR, I2C_DIR + IOSPACE); | ||
136 | return -ENODEV; | ||
137 | } | ||
138 | |||
139 | outb(inb(I2C_DIR) & ~(I2C_SDA | I2C_SCL), I2C_DIR); | ||
140 | outb(inb(I2C_OUT) & ~(I2C_SDA | I2C_SCL), I2C_OUT); | ||
141 | |||
142 | /* set up the driverfs linkage to our parent device */ | ||
143 | vt586b_adapter.dev.parent = &dev->dev; | ||
144 | |||
145 | res = i2c_bit_add_bus(&vt586b_adapter); | ||
146 | if ( res < 0 ) { | ||
147 | release_region(I2C_DIR, IOSPACE); | ||
148 | pm_io_base = 0; | ||
149 | return res; | ||
150 | } | ||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static void __devexit vt586b_remove(struct pci_dev *dev) | ||
155 | { | ||
156 | i2c_bit_del_bus(&vt586b_adapter); | ||
157 | release_region(I2C_DIR, IOSPACE); | ||
158 | pm_io_base = 0; | ||
159 | } | ||
160 | |||
161 | |||
162 | static struct pci_driver vt586b_driver = { | ||
163 | .name = "vt586b_smbus", | ||
164 | .id_table = vt586b_ids, | ||
165 | .probe = vt586b_probe, | ||
166 | .remove = __devexit_p(vt586b_remove), | ||
167 | }; | ||
168 | |||
169 | static int __init i2c_vt586b_init(void) | ||
170 | { | ||
171 | return pci_register_driver(&vt586b_driver); | ||
172 | } | ||
173 | |||
174 | static void __exit i2c_vt586b_exit(void) | ||
175 | { | ||
176 | pci_unregister_driver(&vt586b_driver); | ||
177 | } | ||
178 | |||
179 | |||
180 | MODULE_AUTHOR("Kyösti Mälkki <kmalkki@cc.hut.fi>"); | ||
181 | MODULE_DESCRIPTION("i2c for Via vt82c586b southbridge"); | ||
182 | MODULE_LICENSE("GPL"); | ||
183 | |||
184 | module_init(i2c_vt586b_init); | ||
185 | module_exit(i2c_vt586b_exit); | ||
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c new file mode 100644 index 000000000000..0bb60a636e16 --- /dev/null +++ b/drivers/i2c/busses/i2c-viapro.c | |||
@@ -0,0 +1,458 @@ | |||
1 | /* | ||
2 | i2c-viapro.c - Part of lm_sensors, Linux kernel modules for hardware | ||
3 | monitoring | ||
4 | Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>, | ||
5 | Philip Edelbrock <phil@netroedge.com>, Kyösti Mälkki <kmalkki@cc.hut.fi>, | ||
6 | Mark D. Studebaker <mdsxyz123@yahoo.com> | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | Supports Via devices: | ||
25 | 82C596A/B (0x3050) | ||
26 | 82C596B (0x3051) | ||
27 | 82C686A/B | ||
28 | 8231 | ||
29 | 8233 | ||
30 | 8233A (0x3147 and 0x3177) | ||
31 | 8235 | ||
32 | 8237 | ||
33 | Note: we assume there can only be one device, with one SMBus interface. | ||
34 | */ | ||
35 | |||
36 | #include <linux/config.h> | ||
37 | #include <linux/module.h> | ||
38 | #include <linux/delay.h> | ||
39 | #include <linux/pci.h> | ||
40 | #include <linux/kernel.h> | ||
41 | #include <linux/stddef.h> | ||
42 | #include <linux/sched.h> | ||
43 | #include <linux/ioport.h> | ||
44 | #include <linux/i2c.h> | ||
45 | #include <linux/init.h> | ||
46 | #include <asm/io.h> | ||
47 | |||
48 | static struct pci_dev *vt596_pdev; | ||
49 | |||
50 | #define SMBBA1 0x90 | ||
51 | #define SMBBA2 0x80 | ||
52 | #define SMBBA3 0xD0 | ||
53 | |||
54 | /* SMBus address offsets */ | ||
55 | static unsigned short vt596_smba; | ||
56 | #define SMBHSTSTS (vt596_smba + 0) | ||
57 | #define SMBHSLVSTS (vt596_smba + 1) | ||
58 | #define SMBHSTCNT (vt596_smba + 2) | ||
59 | #define SMBHSTCMD (vt596_smba + 3) | ||
60 | #define SMBHSTADD (vt596_smba + 4) | ||
61 | #define SMBHSTDAT0 (vt596_smba + 5) | ||
62 | #define SMBHSTDAT1 (vt596_smba + 6) | ||
63 | #define SMBBLKDAT (vt596_smba + 7) | ||
64 | #define SMBSLVCNT (vt596_smba + 8) | ||
65 | #define SMBSHDWCMD (vt596_smba + 9) | ||
66 | #define SMBSLVEVT (vt596_smba + 0xA) | ||
67 | #define SMBSLVDAT (vt596_smba + 0xC) | ||
68 | |||
69 | /* PCI Address Constants */ | ||
70 | |||
71 | /* SMBus data in configuration space can be found in two places, | ||
72 | We try to select the better one*/ | ||
73 | |||
74 | static unsigned short smb_cf_hstcfg = 0xD2; | ||
75 | |||
76 | #define SMBHSTCFG (smb_cf_hstcfg) | ||
77 | #define SMBSLVC (smb_cf_hstcfg + 1) | ||
78 | #define SMBSHDW1 (smb_cf_hstcfg + 2) | ||
79 | #define SMBSHDW2 (smb_cf_hstcfg + 3) | ||
80 | #define SMBREV (smb_cf_hstcfg + 4) | ||
81 | |||
82 | /* Other settings */ | ||
83 | #define MAX_TIMEOUT 500 | ||
84 | #define ENABLE_INT9 0 | ||
85 | |||
86 | /* VT82C596 constants */ | ||
87 | #define VT596_QUICK 0x00 | ||
88 | #define VT596_BYTE 0x04 | ||
89 | #define VT596_BYTE_DATA 0x08 | ||
90 | #define VT596_WORD_DATA 0x0C | ||
91 | #define VT596_BLOCK_DATA 0x14 | ||
92 | |||
93 | |||
94 | /* If force is set to anything different from 0, we forcibly enable the | ||
95 | VT596. DANGEROUS! */ | ||
96 | static int force; | ||
97 | module_param(force, bool, 0); | ||
98 | MODULE_PARM_DESC(force, "Forcibly enable the SMBus. DANGEROUS!"); | ||
99 | |||
100 | /* If force_addr is set to anything different from 0, we forcibly enable | ||
101 | the VT596 at the given address. VERY DANGEROUS! */ | ||
102 | static u16 force_addr; | ||
103 | module_param(force_addr, ushort, 0); | ||
104 | MODULE_PARM_DESC(force_addr, | ||
105 | "Forcibly enable the SMBus at the given address. " | ||
106 | "EXTREMELY DANGEROUS!"); | ||
107 | |||
108 | |||
109 | static struct i2c_adapter vt596_adapter; | ||
110 | |||
111 | /* Another internally used function */ | ||
112 | static int vt596_transaction(void) | ||
113 | { | ||
114 | int temp; | ||
115 | int result = 0; | ||
116 | int timeout = 0; | ||
117 | |||
118 | dev_dbg(&vt596_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, " | ||
119 | "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), | ||
120 | inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), | ||
121 | inb_p(SMBHSTDAT1)); | ||
122 | |||
123 | /* Make sure the SMBus host is ready to start transmitting */ | ||
124 | if ((temp = inb_p(SMBHSTSTS)) & 0x1F) { | ||
125 | dev_dbg(&vt596_adapter.dev, "SMBus busy (0x%02x). " | ||
126 | "Resetting...\n", temp); | ||
127 | |||
128 | outb_p(temp, SMBHSTSTS); | ||
129 | if ((temp = inb_p(SMBHSTSTS)) & 0x1F) { | ||
130 | dev_dbg(&vt596_adapter.dev, "Failed! (0x%02x)\n", temp); | ||
131 | |||
132 | return -1; | ||
133 | } else { | ||
134 | dev_dbg(&vt596_adapter.dev, "Successfull!\n"); | ||
135 | } | ||
136 | } | ||
137 | |||
138 | /* start the transaction by setting bit 6 */ | ||
139 | outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT); | ||
140 | |||
141 | /* We will always wait for a fraction of a second! | ||
142 | I don't know if VIA needs this, Intel did */ | ||
143 | do { | ||
144 | msleep(1); | ||
145 | temp = inb_p(SMBHSTSTS); | ||
146 | } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT)); | ||
147 | |||
148 | /* If the SMBus is still busy, we give up */ | ||
149 | if (timeout >= MAX_TIMEOUT) { | ||
150 | result = -1; | ||
151 | dev_dbg(&vt596_adapter.dev, "SMBus Timeout!\n"); | ||
152 | } | ||
153 | |||
154 | if (temp & 0x10) { | ||
155 | result = -1; | ||
156 | dev_dbg(&vt596_adapter.dev, "Error: Failed bus transaction\n"); | ||
157 | } | ||
158 | |||
159 | if (temp & 0x08) { | ||
160 | result = -1; | ||
161 | dev_info(&vt596_adapter.dev, "Bus collision! SMBus may be " | ||
162 | "locked until next hard\nreset. (sorry!)\n"); | ||
163 | /* Clock stops and slave is stuck in mid-transmission */ | ||
164 | } | ||
165 | |||
166 | if (temp & 0x04) { | ||
167 | result = -1; | ||
168 | dev_dbg(&vt596_adapter.dev, "Error: no response!\n"); | ||
169 | } | ||
170 | |||
171 | if ((temp = inb_p(SMBHSTSTS)) & 0x1F) { | ||
172 | outb_p(temp, SMBHSTSTS); | ||
173 | if ((temp = inb_p(SMBHSTSTS)) & 0x1F) { | ||
174 | dev_warn(&vt596_adapter.dev, "Failed reset at end " | ||
175 | "of transaction (%02x)\n", temp); | ||
176 | } | ||
177 | } | ||
178 | |||
179 | dev_dbg(&vt596_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, " | ||
180 | "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), | ||
181 | inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), | ||
182 | inb_p(SMBHSTDAT1)); | ||
183 | |||
184 | return result; | ||
185 | } | ||
186 | |||
187 | /* Return -1 on error. */ | ||
188 | static s32 vt596_access(struct i2c_adapter *adap, u16 addr, | ||
189 | unsigned short flags, char read_write, u8 command, | ||
190 | int size, union i2c_smbus_data *data) | ||
191 | { | ||
192 | int i, len; | ||
193 | |||
194 | switch (size) { | ||
195 | case I2C_SMBUS_PROC_CALL: | ||
196 | dev_info(&vt596_adapter.dev, | ||
197 | "I2C_SMBUS_PROC_CALL not supported!\n"); | ||
198 | return -1; | ||
199 | case I2C_SMBUS_QUICK: | ||
200 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
201 | SMBHSTADD); | ||
202 | size = VT596_QUICK; | ||
203 | break; | ||
204 | case I2C_SMBUS_BYTE: | ||
205 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
206 | SMBHSTADD); | ||
207 | if (read_write == I2C_SMBUS_WRITE) | ||
208 | outb_p(command, SMBHSTCMD); | ||
209 | size = VT596_BYTE; | ||
210 | break; | ||
211 | case I2C_SMBUS_BYTE_DATA: | ||
212 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
213 | SMBHSTADD); | ||
214 | outb_p(command, SMBHSTCMD); | ||
215 | if (read_write == I2C_SMBUS_WRITE) | ||
216 | outb_p(data->byte, SMBHSTDAT0); | ||
217 | size = VT596_BYTE_DATA; | ||
218 | break; | ||
219 | case I2C_SMBUS_WORD_DATA: | ||
220 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
221 | SMBHSTADD); | ||
222 | outb_p(command, SMBHSTCMD); | ||
223 | if (read_write == I2C_SMBUS_WRITE) { | ||
224 | outb_p(data->word & 0xff, SMBHSTDAT0); | ||
225 | outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); | ||
226 | } | ||
227 | size = VT596_WORD_DATA; | ||
228 | break; | ||
229 | case I2C_SMBUS_BLOCK_DATA: | ||
230 | outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), | ||
231 | SMBHSTADD); | ||
232 | outb_p(command, SMBHSTCMD); | ||
233 | if (read_write == I2C_SMBUS_WRITE) { | ||
234 | len = data->block[0]; | ||
235 | if (len < 0) | ||
236 | len = 0; | ||
237 | if (len > I2C_SMBUS_BLOCK_MAX) | ||
238 | len = I2C_SMBUS_BLOCK_MAX; | ||
239 | outb_p(len, SMBHSTDAT0); | ||
240 | i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ | ||
241 | for (i = 1; i <= len; i++) | ||
242 | outb_p(data->block[i], SMBBLKDAT); | ||
243 | } | ||
244 | size = VT596_BLOCK_DATA; | ||
245 | break; | ||
246 | } | ||
247 | |||
248 | outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT); | ||
249 | |||
250 | if (vt596_transaction()) /* Error in transaction */ | ||
251 | return -1; | ||
252 | |||
253 | if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK)) | ||
254 | return 0; | ||
255 | |||
256 | switch (size) { | ||
257 | case VT596_BYTE: | ||
258 | /* Where is the result put? I assume here it is in | ||
259 | * SMBHSTDAT0 but it might just as well be in the | ||
260 | * SMBHSTCMD. No clue in the docs | ||
261 | */ | ||
262 | data->byte = inb_p(SMBHSTDAT0); | ||
263 | break; | ||
264 | case VT596_BYTE_DATA: | ||
265 | data->byte = inb_p(SMBHSTDAT0); | ||
266 | break; | ||
267 | case VT596_WORD_DATA: | ||
268 | data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); | ||
269 | break; | ||
270 | case VT596_BLOCK_DATA: | ||
271 | data->block[0] = inb_p(SMBHSTDAT0); | ||
272 | if (data->block[0] > I2C_SMBUS_BLOCK_MAX) | ||
273 | data->block[0] = I2C_SMBUS_BLOCK_MAX; | ||
274 | i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ | ||
275 | for (i = 1; i <= data->block[0]; i++) | ||
276 | data->block[i] = inb_p(SMBBLKDAT); | ||
277 | break; | ||
278 | } | ||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | static u32 vt596_func(struct i2c_adapter *adapter) | ||
283 | { | ||
284 | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | | ||
285 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | | ||
286 | I2C_FUNC_SMBUS_BLOCK_DATA; | ||
287 | } | ||
288 | |||
289 | static struct i2c_algorithm smbus_algorithm = { | ||
290 | .name = "Non-I2C SMBus adapter", | ||
291 | .id = I2C_ALGO_SMBUS, | ||
292 | .smbus_xfer = vt596_access, | ||
293 | .functionality = vt596_func, | ||
294 | }; | ||
295 | |||
296 | static struct i2c_adapter vt596_adapter = { | ||
297 | .owner = THIS_MODULE, | ||
298 | .class = I2C_CLASS_HWMON, | ||
299 | .algo = &smbus_algorithm, | ||
300 | .name = "unset", | ||
301 | }; | ||
302 | |||
303 | static int __devinit vt596_probe(struct pci_dev *pdev, | ||
304 | const struct pci_device_id *id) | ||
305 | { | ||
306 | unsigned char temp; | ||
307 | int error = -ENODEV; | ||
308 | |||
309 | /* Determine the address of the SMBus areas */ | ||
310 | if (force_addr) { | ||
311 | vt596_smba = force_addr & 0xfff0; | ||
312 | force = 0; | ||
313 | goto found; | ||
314 | } | ||
315 | |||
316 | if ((pci_read_config_word(pdev, id->driver_data, &vt596_smba)) || | ||
317 | !(vt596_smba & 0x1)) { | ||
318 | /* try 2nd address and config reg. for 596 */ | ||
319 | if (id->device == PCI_DEVICE_ID_VIA_82C596_3 && | ||
320 | !pci_read_config_word(pdev, SMBBA2, &vt596_smba) && | ||
321 | (vt596_smba & 0x1)) { | ||
322 | smb_cf_hstcfg = 0x84; | ||
323 | } else { | ||
324 | /* no matches at all */ | ||
325 | dev_err(&pdev->dev, "Cannot configure " | ||
326 | "SMBus I/O Base address\n"); | ||
327 | return -ENODEV; | ||
328 | } | ||
329 | } | ||
330 | |||
331 | vt596_smba &= 0xfff0; | ||
332 | if (vt596_smba == 0) { | ||
333 | dev_err(&pdev->dev, "SMBus base address " | ||
334 | "uninitialized - upgrade BIOS or use " | ||
335 | "force_addr=0xaddr\n"); | ||
336 | return -ENODEV; | ||
337 | } | ||
338 | |||
339 | found: | ||
340 | if (!request_region(vt596_smba, 8, "viapro-smbus")) { | ||
341 | dev_err(&pdev->dev, "SMBus region 0x%x already in use!\n", | ||
342 | vt596_smba); | ||
343 | return -ENODEV; | ||
344 | } | ||
345 | |||
346 | pci_read_config_byte(pdev, SMBHSTCFG, &temp); | ||
347 | /* If force_addr is set, we program the new address here. Just to make | ||
348 | sure, we disable the VT596 first. */ | ||
349 | if (force_addr) { | ||
350 | pci_write_config_byte(pdev, SMBHSTCFG, temp & 0xfe); | ||
351 | pci_write_config_word(pdev, id->driver_data, vt596_smba); | ||
352 | pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01); | ||
353 | dev_warn(&pdev->dev, "WARNING: SMBus interface set to new " | ||
354 | "address 0x%04x!\n", vt596_smba); | ||
355 | } else if ((temp & 1) == 0) { | ||
356 | if (force) { | ||
357 | /* NOTE: This assumes I/O space and other allocations | ||
358 | * WERE done by the Bios! Don't complain if your | ||
359 | * hardware does weird things after enabling this. | ||
360 | * :') Check for Bios updates before resorting to | ||
361 | * this. | ||
362 | */ | ||
363 | pci_write_config_byte(pdev, SMBHSTCFG, temp | 1); | ||
364 | dev_info(&pdev->dev, "Enabling SMBus device\n"); | ||
365 | } else { | ||
366 | dev_err(&pdev->dev, "SMBUS: Error: Host SMBus " | ||
367 | "controller not enabled! - upgrade BIOS or " | ||
368 | "use force=1\n"); | ||
369 | goto release_region; | ||
370 | } | ||
371 | } | ||
372 | |||
373 | if ((temp & 0x0E) == 8) | ||
374 | dev_dbg(&pdev->dev, "using Interrupt 9 for SMBus.\n"); | ||
375 | else if ((temp & 0x0E) == 0) | ||
376 | dev_dbg(&pdev->dev, "using Interrupt SMI# for SMBus.\n"); | ||
377 | else | ||
378 | dev_dbg(&pdev->dev, "Illegal Interrupt configuration " | ||
379 | "(or code out of date)!\n"); | ||
380 | |||
381 | pci_read_config_byte(pdev, SMBREV, &temp); | ||
382 | dev_dbg(&pdev->dev, "SMBREV = 0x%X\n", temp); | ||
383 | dev_dbg(&pdev->dev, "VT596_smba = 0x%X\n", vt596_smba); | ||
384 | |||
385 | vt596_adapter.dev.parent = &pdev->dev; | ||
386 | snprintf(vt596_adapter.name, I2C_NAME_SIZE, | ||
387 | "SMBus Via Pro adapter at %04x", vt596_smba); | ||
388 | |||
389 | vt596_pdev = pci_dev_get(pdev); | ||
390 | if (i2c_add_adapter(&vt596_adapter)) { | ||
391 | pci_dev_put(vt596_pdev); | ||
392 | vt596_pdev = NULL; | ||
393 | } | ||
394 | |||
395 | /* Always return failure here. This is to allow other drivers to bind | ||
396 | * to this pci device. We don't really want to have control over the | ||
397 | * pci device, we only wanted to read as few register values from it. | ||
398 | */ | ||
399 | return -ENODEV; | ||
400 | |||
401 | release_region: | ||
402 | release_region(vt596_smba, 8); | ||
403 | return error; | ||
404 | } | ||
405 | |||
406 | static struct pci_device_id vt596_ids[] = { | ||
407 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596_3), | ||
408 | .driver_data = SMBBA1 }, | ||
409 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596B_3), | ||
410 | .driver_data = SMBBA1 }, | ||
411 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4), | ||
412 | .driver_data = SMBBA1 }, | ||
413 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_0), | ||
414 | .driver_data = SMBBA3 }, | ||
415 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233A), | ||
416 | .driver_data = SMBBA3 }, | ||
417 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235), | ||
418 | .driver_data = SMBBA3 }, | ||
419 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237), | ||
420 | .driver_data = SMBBA3 }, | ||
421 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4), | ||
422 | .driver_data = SMBBA1 }, | ||
423 | { 0, } | ||
424 | }; | ||
425 | |||
426 | MODULE_DEVICE_TABLE (pci, vt596_ids); | ||
427 | |||
428 | static struct pci_driver vt596_driver = { | ||
429 | .name = "vt596_smbus", | ||
430 | .id_table = vt596_ids, | ||
431 | .probe = vt596_probe, | ||
432 | }; | ||
433 | |||
434 | static int __init i2c_vt596_init(void) | ||
435 | { | ||
436 | return pci_register_driver(&vt596_driver); | ||
437 | } | ||
438 | |||
439 | |||
440 | static void __exit i2c_vt596_exit(void) | ||
441 | { | ||
442 | pci_unregister_driver(&vt596_driver); | ||
443 | if (vt596_pdev != NULL) { | ||
444 | i2c_del_adapter(&vt596_adapter); | ||
445 | release_region(vt596_smba, 8); | ||
446 | pci_dev_put(vt596_pdev); | ||
447 | vt596_pdev = NULL; | ||
448 | } | ||
449 | } | ||
450 | |||
451 | MODULE_AUTHOR( | ||
452 | "Frodo Looijaard <frodol@dds.nl> and " | ||
453 | "Philip Edelbrock <phil@netroedge.com>"); | ||
454 | MODULE_DESCRIPTION("vt82c596 SMBus driver"); | ||
455 | MODULE_LICENSE("GPL"); | ||
456 | |||
457 | module_init(i2c_vt596_init); | ||
458 | module_exit(i2c_vt596_exit); | ||
diff --git a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c new file mode 100644 index 000000000000..3edf0e34155e --- /dev/null +++ b/drivers/i2c/busses/i2c-voodoo3.c | |||
@@ -0,0 +1,254 @@ | |||
1 | /* | ||
2 | voodoo3.c - Part of lm_sensors, Linux kernel modules for hardware | ||
3 | monitoring | ||
4 | Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>, | ||
5 | Philip Edelbrock <phil@netroedge.com>, | ||
6 | Ralph Metzler <rjkm@thp.uni-koeln.de>, and | ||
7 | Mark D. Studebaker <mdsxyz123@yahoo.com> | ||
8 | |||
9 | Based on code written by Ralph Metzler <rjkm@thp.uni-koeln.de> and | ||
10 | Simon Vogl | ||
11 | |||
12 | This program is free software; you can redistribute it and/or modify | ||
13 | it under the terms of the GNU General Public License as published by | ||
14 | the Free Software Foundation; either version 2 of the License, or | ||
15 | (at your option) any later version. | ||
16 | |||
17 | This program is distributed in the hope that it will be useful, | ||
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | GNU General Public License for more details. | ||
21 | |||
22 | You should have received a copy of the GNU General Public License | ||
23 | along with this program; if not, write to the Free Software | ||
24 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | /* This interfaces to the I2C bus of the Voodoo3 to gain access to | ||
28 | the BT869 and possibly other I2C devices. */ | ||
29 | |||
30 | #include <linux/config.h> | ||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/init.h> | ||
34 | #include <linux/pci.h> | ||
35 | #include <linux/i2c.h> | ||
36 | #include <linux/i2c-algo-bit.h> | ||
37 | #include <asm/io.h> | ||
38 | |||
39 | /* the only registers we use */ | ||
40 | #define REG 0x78 | ||
41 | #define REG2 0x70 | ||
42 | |||
43 | /* bit locations in the register */ | ||
44 | #define DDC_ENAB 0x00040000 | ||
45 | #define DDC_SCL_OUT 0x00080000 | ||
46 | #define DDC_SDA_OUT 0x00100000 | ||
47 | #define DDC_SCL_IN 0x00200000 | ||
48 | #define DDC_SDA_IN 0x00400000 | ||
49 | #define I2C_ENAB 0x00800000 | ||
50 | #define I2C_SCL_OUT 0x01000000 | ||
51 | #define I2C_SDA_OUT 0x02000000 | ||
52 | #define I2C_SCL_IN 0x04000000 | ||
53 | #define I2C_SDA_IN 0x08000000 | ||
54 | |||
55 | /* initialization states */ | ||
56 | #define INIT2 0x2 | ||
57 | #define INIT3 0x4 | ||
58 | |||
59 | /* delays */ | ||
60 | #define CYCLE_DELAY 10 | ||
61 | #define TIMEOUT (HZ / 2) | ||
62 | |||
63 | |||
64 | static void __iomem *ioaddr; | ||
65 | |||
66 | /* The voo GPIO registers don't have individual masks for each bit | ||
67 | so we always have to read before writing. */ | ||
68 | |||
69 | static void bit_vooi2c_setscl(void *data, int val) | ||
70 | { | ||
71 | unsigned int r; | ||
72 | r = readl(ioaddr + REG); | ||
73 | if (val) | ||
74 | r |= I2C_SCL_OUT; | ||
75 | else | ||
76 | r &= ~I2C_SCL_OUT; | ||
77 | writel(r, ioaddr + REG); | ||
78 | readl(ioaddr + REG); /* flush posted write */ | ||
79 | } | ||
80 | |||
81 | static void bit_vooi2c_setsda(void *data, int val) | ||
82 | { | ||
83 | unsigned int r; | ||
84 | r = readl(ioaddr + REG); | ||
85 | if (val) | ||
86 | r |= I2C_SDA_OUT; | ||
87 | else | ||
88 | r &= ~I2C_SDA_OUT; | ||
89 | writel(r, ioaddr + REG); | ||
90 | readl(ioaddr + REG); /* flush posted write */ | ||
91 | } | ||
92 | |||
93 | /* The GPIO pins are open drain, so the pins always remain outputs. | ||
94 | We rely on the i2c-algo-bit routines to set the pins high before | ||
95 | reading the input from other chips. */ | ||
96 | |||
97 | static int bit_vooi2c_getscl(void *data) | ||
98 | { | ||
99 | return (0 != (readl(ioaddr + REG) & I2C_SCL_IN)); | ||
100 | } | ||
101 | |||
102 | static int bit_vooi2c_getsda(void *data) | ||
103 | { | ||
104 | return (0 != (readl(ioaddr + REG) & I2C_SDA_IN)); | ||
105 | } | ||
106 | |||
107 | static void bit_vooddc_setscl(void *data, int val) | ||
108 | { | ||
109 | unsigned int r; | ||
110 | r = readl(ioaddr + REG); | ||
111 | if (val) | ||
112 | r |= DDC_SCL_OUT; | ||
113 | else | ||
114 | r &= ~DDC_SCL_OUT; | ||
115 | writel(r, ioaddr + REG); | ||
116 | readl(ioaddr + REG); /* flush posted write */ | ||
117 | } | ||
118 | |||
119 | static void bit_vooddc_setsda(void *data, int val) | ||
120 | { | ||
121 | unsigned int r; | ||
122 | r = readl(ioaddr + REG); | ||
123 | if (val) | ||
124 | r |= DDC_SDA_OUT; | ||
125 | else | ||
126 | r &= ~DDC_SDA_OUT; | ||
127 | writel(r, ioaddr + REG); | ||
128 | readl(ioaddr + REG); /* flush posted write */ | ||
129 | } | ||
130 | |||
131 | static int bit_vooddc_getscl(void *data) | ||
132 | { | ||
133 | return (0 != (readl(ioaddr + REG) & DDC_SCL_IN)); | ||
134 | } | ||
135 | |||
136 | static int bit_vooddc_getsda(void *data) | ||
137 | { | ||
138 | return (0 != (readl(ioaddr + REG) & DDC_SDA_IN)); | ||
139 | } | ||
140 | |||
141 | static int config_v3(struct pci_dev *dev) | ||
142 | { | ||
143 | unsigned long cadr; | ||
144 | |||
145 | /* map Voodoo3 memory */ | ||
146 | cadr = dev->resource[0].start; | ||
147 | cadr &= PCI_BASE_ADDRESS_MEM_MASK; | ||
148 | ioaddr = ioremap_nocache(cadr, 0x1000); | ||
149 | if (ioaddr) { | ||
150 | writel(0x8160, ioaddr + REG2); | ||
151 | writel(0xcffc0020, ioaddr + REG); | ||
152 | dev_info(&dev->dev, "Using Banshee/Voodoo3 I2C device at %p\n", ioaddr); | ||
153 | return 0; | ||
154 | } | ||
155 | return -ENODEV; | ||
156 | } | ||
157 | |||
158 | static struct i2c_algo_bit_data voo_i2c_bit_data = { | ||
159 | .setsda = bit_vooi2c_setsda, | ||
160 | .setscl = bit_vooi2c_setscl, | ||
161 | .getsda = bit_vooi2c_getsda, | ||
162 | .getscl = bit_vooi2c_getscl, | ||
163 | .udelay = CYCLE_DELAY, | ||
164 | .mdelay = CYCLE_DELAY, | ||
165 | .timeout = TIMEOUT | ||
166 | }; | ||
167 | |||
168 | static struct i2c_adapter voodoo3_i2c_adapter = { | ||
169 | .owner = THIS_MODULE, | ||
170 | .class = I2C_CLASS_TV_ANALOG, | ||
171 | .name = "I2C Voodoo3/Banshee adapter", | ||
172 | .algo_data = &voo_i2c_bit_data, | ||
173 | }; | ||
174 | |||
175 | static struct i2c_algo_bit_data voo_ddc_bit_data = { | ||
176 | .setsda = bit_vooddc_setsda, | ||
177 | .setscl = bit_vooddc_setscl, | ||
178 | .getsda = bit_vooddc_getsda, | ||
179 | .getscl = bit_vooddc_getscl, | ||
180 | .udelay = CYCLE_DELAY, | ||
181 | .mdelay = CYCLE_DELAY, | ||
182 | .timeout = TIMEOUT | ||
183 | }; | ||
184 | |||
185 | static struct i2c_adapter voodoo3_ddc_adapter = { | ||
186 | .owner = THIS_MODULE, | ||
187 | .class = I2C_CLASS_DDC, | ||
188 | .name = "DDC Voodoo3/Banshee adapter", | ||
189 | .algo_data = &voo_ddc_bit_data, | ||
190 | }; | ||
191 | |||
192 | static struct pci_device_id voodoo3_ids[] __devinitdata = { | ||
193 | { PCI_DEVICE(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3) }, | ||
194 | { PCI_DEVICE(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE) }, | ||
195 | { 0, } | ||
196 | }; | ||
197 | |||
198 | MODULE_DEVICE_TABLE (pci, voodoo3_ids); | ||
199 | |||
200 | static int __devinit voodoo3_probe(struct pci_dev *dev, const struct pci_device_id *id) | ||
201 | { | ||
202 | int retval; | ||
203 | |||
204 | retval = config_v3(dev); | ||
205 | if (retval) | ||
206 | return retval; | ||
207 | |||
208 | /* set up the sysfs linkage to our parent device */ | ||
209 | voodoo3_i2c_adapter.dev.parent = &dev->dev; | ||
210 | voodoo3_ddc_adapter.dev.parent = &dev->dev; | ||
211 | |||
212 | retval = i2c_bit_add_bus(&voodoo3_i2c_adapter); | ||
213 | if (retval) | ||
214 | return retval; | ||
215 | retval = i2c_bit_add_bus(&voodoo3_ddc_adapter); | ||
216 | if (retval) | ||
217 | i2c_bit_del_bus(&voodoo3_i2c_adapter); | ||
218 | return retval; | ||
219 | } | ||
220 | |||
221 | static void __devexit voodoo3_remove(struct pci_dev *dev) | ||
222 | { | ||
223 | i2c_bit_del_bus(&voodoo3_i2c_adapter); | ||
224 | i2c_bit_del_bus(&voodoo3_ddc_adapter); | ||
225 | iounmap(ioaddr); | ||
226 | } | ||
227 | |||
228 | static struct pci_driver voodoo3_driver = { | ||
229 | .name = "voodoo3_smbus", | ||
230 | .id_table = voodoo3_ids, | ||
231 | .probe = voodoo3_probe, | ||
232 | .remove = __devexit_p(voodoo3_remove), | ||
233 | }; | ||
234 | |||
235 | static int __init i2c_voodoo3_init(void) | ||
236 | { | ||
237 | return pci_register_driver(&voodoo3_driver); | ||
238 | } | ||
239 | |||
240 | static void __exit i2c_voodoo3_exit(void) | ||
241 | { | ||
242 | pci_unregister_driver(&voodoo3_driver); | ||
243 | } | ||
244 | |||
245 | |||
246 | MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, " | ||
247 | "Philip Edelbrock <phil@netroedge.com>, " | ||
248 | "Ralph Metzler <rjkm@thp.uni-koeln.de>, " | ||
249 | "and Mark D. Studebaker <mdsxyz123@yahoo.com>"); | ||
250 | MODULE_DESCRIPTION("Voodoo3 I2C/SMBus driver"); | ||
251 | MODULE_LICENSE("GPL"); | ||
252 | |||
253 | module_init(i2c_voodoo3_init); | ||
254 | module_exit(i2c_voodoo3_exit); | ||
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c new file mode 100644 index 000000000000..1c4159a93623 --- /dev/null +++ b/drivers/i2c/busses/scx200_acb.c | |||
@@ -0,0 +1,557 @@ | |||
1 | /* linux/drivers/i2c/scx200_acb.c | ||
2 | |||
3 | Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com> | ||
4 | |||
5 | National Semiconductor SCx200 ACCESS.bus support | ||
6 | |||
7 | Based on i2c-keywest.c which is: | ||
8 | Copyright (c) 2001 Benjamin Herrenschmidt <benh@kernel.crashing.org> | ||
9 | Copyright (c) 2000 Philip Edelbrock <phil@stimpy.netroedge.com> | ||
10 | |||
11 | This program is free software; you can redistribute it and/or | ||
12 | modify it under the terms of the GNU General Public License as | ||
13 | published by the Free Software Foundation; either version 2 of the | ||
14 | License, or (at your option) any later version. | ||
15 | |||
16 | This program is distributed in the hope that it will be useful, | ||
17 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
19 | General Public License for more details. | ||
20 | |||
21 | You should have received a copy of the GNU General Public License | ||
22 | along with this program; if not, write to the Free Software | ||
23 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | |||
25 | */ | ||
26 | |||
27 | #include <linux/config.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/errno.h> | ||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/i2c.h> | ||
33 | #include <linux/smp_lock.h> | ||
34 | #include <linux/pci.h> | ||
35 | #include <linux/delay.h> | ||
36 | #include <asm/io.h> | ||
37 | |||
38 | #include <linux/scx200.h> | ||
39 | |||
40 | #define NAME "scx200_acb" | ||
41 | |||
42 | MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>"); | ||
43 | MODULE_DESCRIPTION("NatSemi SCx200 ACCESS.bus Driver"); | ||
44 | MODULE_LICENSE("GPL"); | ||
45 | |||
46 | #define MAX_DEVICES 4 | ||
47 | static int base[MAX_DEVICES] = { 0x820, 0x840 }; | ||
48 | module_param_array(base, int, NULL, 0); | ||
49 | MODULE_PARM_DESC(base, "Base addresses for the ACCESS.bus controllers"); | ||
50 | |||
51 | #ifdef DEBUG | ||
52 | #define DBG(x...) printk(KERN_DEBUG NAME ": " x) | ||
53 | #else | ||
54 | #define DBG(x...) | ||
55 | #endif | ||
56 | |||
57 | /* The hardware supports interrupt driven mode too, but I haven't | ||
58 | implemented that. */ | ||
59 | #define POLLED_MODE 1 | ||
60 | #define POLL_TIMEOUT (HZ) | ||
61 | |||
62 | enum scx200_acb_state { | ||
63 | state_idle, | ||
64 | state_address, | ||
65 | state_command, | ||
66 | state_repeat_start, | ||
67 | state_quick, | ||
68 | state_read, | ||
69 | state_write, | ||
70 | }; | ||
71 | |||
72 | static const char *scx200_acb_state_name[] = { | ||
73 | "idle", | ||
74 | "address", | ||
75 | "command", | ||
76 | "repeat_start", | ||
77 | "quick", | ||
78 | "read", | ||
79 | "write", | ||
80 | }; | ||
81 | |||
82 | /* Physical interface */ | ||
83 | struct scx200_acb_iface | ||
84 | { | ||
85 | struct scx200_acb_iface *next; | ||
86 | struct i2c_adapter adapter; | ||
87 | unsigned base; | ||
88 | struct semaphore sem; | ||
89 | |||
90 | /* State machine data */ | ||
91 | enum scx200_acb_state state; | ||
92 | int result; | ||
93 | u8 address_byte; | ||
94 | u8 command; | ||
95 | u8 *ptr; | ||
96 | char needs_reset; | ||
97 | unsigned len; | ||
98 | }; | ||
99 | |||
100 | /* Register Definitions */ | ||
101 | #define ACBSDA (iface->base + 0) | ||
102 | #define ACBST (iface->base + 1) | ||
103 | #define ACBST_SDAST 0x40 /* SDA Status */ | ||
104 | #define ACBST_BER 0x20 | ||
105 | #define ACBST_NEGACK 0x10 /* Negative Acknowledge */ | ||
106 | #define ACBST_STASTR 0x08 /* Stall After Start */ | ||
107 | #define ACBST_MASTER 0x02 | ||
108 | #define ACBCST (iface->base + 2) | ||
109 | #define ACBCST_BB 0x02 | ||
110 | #define ACBCTL1 (iface->base + 3) | ||
111 | #define ACBCTL1_STASTRE 0x80 | ||
112 | #define ACBCTL1_NMINTE 0x40 | ||
113 | #define ACBCTL1_ACK 0x10 | ||
114 | #define ACBCTL1_STOP 0x02 | ||
115 | #define ACBCTL1_START 0x01 | ||
116 | #define ACBADDR (iface->base + 4) | ||
117 | #define ACBCTL2 (iface->base + 5) | ||
118 | #define ACBCTL2_ENABLE 0x01 | ||
119 | |||
120 | /************************************************************************/ | ||
121 | |||
122 | static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) | ||
123 | { | ||
124 | const char *errmsg; | ||
125 | |||
126 | DBG("state %s, status = 0x%02x\n", | ||
127 | scx200_acb_state_name[iface->state], status); | ||
128 | |||
129 | if (status & ACBST_BER) { | ||
130 | errmsg = "bus error"; | ||
131 | goto error; | ||
132 | } | ||
133 | if (!(status & ACBST_MASTER)) { | ||
134 | errmsg = "not master"; | ||
135 | goto error; | ||
136 | } | ||
137 | if (status & ACBST_NEGACK) | ||
138 | goto negack; | ||
139 | |||
140 | switch (iface->state) { | ||
141 | case state_idle: | ||
142 | dev_warn(&iface->adapter.dev, "interrupt in idle state\n"); | ||
143 | break; | ||
144 | |||
145 | case state_address: | ||
146 | /* Do a pointer write first */ | ||
147 | outb(iface->address_byte & ~1, ACBSDA); | ||
148 | |||
149 | iface->state = state_command; | ||
150 | break; | ||
151 | |||
152 | case state_command: | ||
153 | outb(iface->command, ACBSDA); | ||
154 | |||
155 | if (iface->address_byte & 1) | ||
156 | iface->state = state_repeat_start; | ||
157 | else | ||
158 | iface->state = state_write; | ||
159 | break; | ||
160 | |||
161 | case state_repeat_start: | ||
162 | outb(inb(ACBCTL1) | ACBCTL1_START, ACBCTL1); | ||
163 | /* fallthrough */ | ||
164 | |||
165 | case state_quick: | ||
166 | if (iface->address_byte & 1) { | ||
167 | if (iface->len == 1) | ||
168 | outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1); | ||
169 | else | ||
170 | outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1); | ||
171 | outb(iface->address_byte, ACBSDA); | ||
172 | |||
173 | iface->state = state_read; | ||
174 | } else { | ||
175 | outb(iface->address_byte, ACBSDA); | ||
176 | |||
177 | iface->state = state_write; | ||
178 | } | ||
179 | break; | ||
180 | |||
181 | case state_read: | ||
182 | /* Set ACK if receiving the last byte */ | ||
183 | if (iface->len == 1) | ||
184 | outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1); | ||
185 | else | ||
186 | outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1); | ||
187 | |||
188 | *iface->ptr++ = inb(ACBSDA); | ||
189 | --iface->len; | ||
190 | |||
191 | if (iface->len == 0) { | ||
192 | iface->result = 0; | ||
193 | iface->state = state_idle; | ||
194 | outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); | ||
195 | } | ||
196 | |||
197 | break; | ||
198 | |||
199 | case state_write: | ||
200 | if (iface->len == 0) { | ||
201 | iface->result = 0; | ||
202 | iface->state = state_idle; | ||
203 | outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); | ||
204 | break; | ||
205 | } | ||
206 | |||
207 | outb(*iface->ptr++, ACBSDA); | ||
208 | --iface->len; | ||
209 | |||
210 | break; | ||
211 | } | ||
212 | |||
213 | return; | ||
214 | |||
215 | negack: | ||
216 | DBG("negative acknowledge in state %s\n", | ||
217 | scx200_acb_state_name[iface->state]); | ||
218 | |||
219 | iface->state = state_idle; | ||
220 | iface->result = -ENXIO; | ||
221 | |||
222 | outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); | ||
223 | outb(ACBST_STASTR | ACBST_NEGACK, ACBST); | ||
224 | return; | ||
225 | |||
226 | error: | ||
227 | dev_err(&iface->adapter.dev, "%s in state %s\n", errmsg, | ||
228 | scx200_acb_state_name[iface->state]); | ||
229 | |||
230 | iface->state = state_idle; | ||
231 | iface->result = -EIO; | ||
232 | iface->needs_reset = 1; | ||
233 | } | ||
234 | |||
235 | static void scx200_acb_timeout(struct scx200_acb_iface *iface) | ||
236 | { | ||
237 | dev_err(&iface->adapter.dev, "timeout in state %s\n", | ||
238 | scx200_acb_state_name[iface->state]); | ||
239 | |||
240 | iface->state = state_idle; | ||
241 | iface->result = -EIO; | ||
242 | iface->needs_reset = 1; | ||
243 | } | ||
244 | |||
245 | #ifdef POLLED_MODE | ||
246 | static void scx200_acb_poll(struct scx200_acb_iface *iface) | ||
247 | { | ||
248 | u8 status = 0; | ||
249 | unsigned long timeout; | ||
250 | |||
251 | timeout = jiffies + POLL_TIMEOUT; | ||
252 | while (time_before(jiffies, timeout)) { | ||
253 | status = inb(ACBST); | ||
254 | if ((status & (ACBST_SDAST|ACBST_BER|ACBST_NEGACK)) != 0) { | ||
255 | scx200_acb_machine(iface, status); | ||
256 | return; | ||
257 | } | ||
258 | msleep(10); | ||
259 | } | ||
260 | |||
261 | scx200_acb_timeout(iface); | ||
262 | } | ||
263 | #endif /* POLLED_MODE */ | ||
264 | |||
265 | static void scx200_acb_reset(struct scx200_acb_iface *iface) | ||
266 | { | ||
267 | /* Disable the ACCESS.bus device and Configure the SCL | ||
268 | frequency: 16 clock cycles */ | ||
269 | outb(0x70, ACBCTL2); | ||
270 | /* Polling mode */ | ||
271 | outb(0, ACBCTL1); | ||
272 | /* Disable slave address */ | ||
273 | outb(0, ACBADDR); | ||
274 | /* Enable the ACCESS.bus device */ | ||
275 | outb(inb(ACBCTL2) | ACBCTL2_ENABLE, ACBCTL2); | ||
276 | /* Free STALL after START */ | ||
277 | outb(inb(ACBCTL1) & ~(ACBCTL1_STASTRE | ACBCTL1_NMINTE), ACBCTL1); | ||
278 | /* Send a STOP */ | ||
279 | outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); | ||
280 | /* Clear BER, NEGACK and STASTR bits */ | ||
281 | outb(ACBST_BER | ACBST_NEGACK | ACBST_STASTR, ACBST); | ||
282 | /* Clear BB bit */ | ||
283 | outb(inb(ACBCST) | ACBCST_BB, ACBCST); | ||
284 | } | ||
285 | |||
286 | static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, | ||
287 | u16 address, unsigned short flags, | ||
288 | char rw, u8 command, int size, | ||
289 | union i2c_smbus_data *data) | ||
290 | { | ||
291 | struct scx200_acb_iface *iface = i2c_get_adapdata(adapter); | ||
292 | int len; | ||
293 | u8 *buffer; | ||
294 | u16 cur_word; | ||
295 | int rc; | ||
296 | |||
297 | switch (size) { | ||
298 | case I2C_SMBUS_QUICK: | ||
299 | len = 0; | ||
300 | buffer = NULL; | ||
301 | break; | ||
302 | case I2C_SMBUS_BYTE: | ||
303 | if (rw == I2C_SMBUS_READ) { | ||
304 | len = 1; | ||
305 | buffer = &data->byte; | ||
306 | } else { | ||
307 | len = 1; | ||
308 | buffer = &command; | ||
309 | } | ||
310 | break; | ||
311 | case I2C_SMBUS_BYTE_DATA: | ||
312 | len = 1; | ||
313 | buffer = &data->byte; | ||
314 | break; | ||
315 | case I2C_SMBUS_WORD_DATA: | ||
316 | len = 2; | ||
317 | cur_word = cpu_to_le16(data->word); | ||
318 | buffer = (u8 *)&cur_word; | ||
319 | break; | ||
320 | case I2C_SMBUS_BLOCK_DATA: | ||
321 | len = data->block[0]; | ||
322 | buffer = &data->block[1]; | ||
323 | break; | ||
324 | default: | ||
325 | return -EINVAL; | ||
326 | } | ||
327 | |||
328 | DBG("size=%d, address=0x%x, command=0x%x, len=%d, read=%d\n", | ||
329 | size, address, command, len, rw == I2C_SMBUS_READ); | ||
330 | |||
331 | if (!len && rw == I2C_SMBUS_READ) { | ||
332 | dev_warn(&adapter->dev, "zero length read\n"); | ||
333 | return -EINVAL; | ||
334 | } | ||
335 | |||
336 | if (len && !buffer) { | ||
337 | dev_warn(&adapter->dev, "nonzero length but no buffer\n"); | ||
338 | return -EFAULT; | ||
339 | } | ||
340 | |||
341 | down(&iface->sem); | ||
342 | |||
343 | iface->address_byte = address<<1; | ||
344 | if (rw == I2C_SMBUS_READ) | ||
345 | iface->address_byte |= 1; | ||
346 | iface->command = command; | ||
347 | iface->ptr = buffer; | ||
348 | iface->len = len; | ||
349 | iface->result = -EINVAL; | ||
350 | iface->needs_reset = 0; | ||
351 | |||
352 | outb(inb(ACBCTL1) | ACBCTL1_START, ACBCTL1); | ||
353 | |||
354 | if (size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE) | ||
355 | iface->state = state_quick; | ||
356 | else | ||
357 | iface->state = state_address; | ||
358 | |||
359 | #ifdef POLLED_MODE | ||
360 | while (iface->state != state_idle) | ||
361 | scx200_acb_poll(iface); | ||
362 | #else /* POLLED_MODE */ | ||
363 | #error Interrupt driven mode not implemented | ||
364 | #endif /* POLLED_MODE */ | ||
365 | |||
366 | if (iface->needs_reset) | ||
367 | scx200_acb_reset(iface); | ||
368 | |||
369 | rc = iface->result; | ||
370 | |||
371 | up(&iface->sem); | ||
372 | |||
373 | if (rc == 0 && size == I2C_SMBUS_WORD_DATA && rw == I2C_SMBUS_READ) | ||
374 | data->word = le16_to_cpu(cur_word); | ||
375 | |||
376 | #ifdef DEBUG | ||
377 | DBG(": transfer done, result: %d", rc); | ||
378 | if (buffer) { | ||
379 | int i; | ||
380 | printk(" data:"); | ||
381 | for (i = 0; i < len; ++i) | ||
382 | printk(" %02x", buffer[i]); | ||
383 | } | ||
384 | printk("\n"); | ||
385 | #endif | ||
386 | |||
387 | return rc; | ||
388 | } | ||
389 | |||
390 | static u32 scx200_acb_func(struct i2c_adapter *adapter) | ||
391 | { | ||
392 | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | | ||
393 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | | ||
394 | I2C_FUNC_SMBUS_BLOCK_DATA; | ||
395 | } | ||
396 | |||
397 | /* For now, we only handle combined mode (smbus) */ | ||
398 | static struct i2c_algorithm scx200_acb_algorithm = { | ||
399 | .name = "NatSemi SCx200 ACCESS.bus", | ||
400 | .id = I2C_ALGO_SMBUS, | ||
401 | .smbus_xfer = scx200_acb_smbus_xfer, | ||
402 | .functionality = scx200_acb_func, | ||
403 | }; | ||
404 | |||
405 | static struct scx200_acb_iface *scx200_acb_list; | ||
406 | |||
407 | static int scx200_acb_probe(struct scx200_acb_iface *iface) | ||
408 | { | ||
409 | u8 val; | ||
410 | |||
411 | /* Disable the ACCESS.bus device and Configure the SCL | ||
412 | frequency: 16 clock cycles */ | ||
413 | outb(0x70, ACBCTL2); | ||
414 | |||
415 | if (inb(ACBCTL2) != 0x70) { | ||
416 | DBG("ACBCTL2 readback failed\n"); | ||
417 | return -ENXIO; | ||
418 | } | ||
419 | |||
420 | outb(inb(ACBCTL1) | ACBCTL1_NMINTE, ACBCTL1); | ||
421 | |||
422 | val = inb(ACBCTL1); | ||
423 | if (val) { | ||
424 | DBG("disabled, but ACBCTL1=0x%02x\n", val); | ||
425 | return -ENXIO; | ||
426 | } | ||
427 | |||
428 | outb(inb(ACBCTL2) | ACBCTL2_ENABLE, ACBCTL2); | ||
429 | |||
430 | outb(inb(ACBCTL1) | ACBCTL1_NMINTE, ACBCTL1); | ||
431 | |||
432 | val = inb(ACBCTL1); | ||
433 | if ((val & ACBCTL1_NMINTE) != ACBCTL1_NMINTE) { | ||
434 | DBG("enabled, but NMINTE won't be set, ACBCTL1=0x%02x\n", val); | ||
435 | return -ENXIO; | ||
436 | } | ||
437 | |||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | static int __init scx200_acb_create(int base, int index) | ||
442 | { | ||
443 | struct scx200_acb_iface *iface; | ||
444 | struct i2c_adapter *adapter; | ||
445 | int rc = 0; | ||
446 | char description[64]; | ||
447 | |||
448 | iface = kmalloc(sizeof(*iface), GFP_KERNEL); | ||
449 | if (!iface) { | ||
450 | printk(KERN_ERR NAME ": can't allocate memory\n"); | ||
451 | rc = -ENOMEM; | ||
452 | goto errout; | ||
453 | } | ||
454 | |||
455 | memset(iface, 0, sizeof(*iface)); | ||
456 | adapter = &iface->adapter; | ||
457 | i2c_set_adapdata(adapter, iface); | ||
458 | snprintf(adapter->name, I2C_NAME_SIZE, "SCx200 ACB%d", index); | ||
459 | adapter->owner = THIS_MODULE; | ||
460 | adapter->id = I2C_ALGO_SMBUS; | ||
461 | adapter->algo = &scx200_acb_algorithm; | ||
462 | adapter->class = I2C_CLASS_HWMON; | ||
463 | |||
464 | init_MUTEX(&iface->sem); | ||
465 | |||
466 | snprintf(description, sizeof(description), "NatSemi SCx200 ACCESS.bus [%s]", adapter->name); | ||
467 | if (request_region(base, 8, description) == 0) { | ||
468 | dev_err(&adapter->dev, "can't allocate io 0x%x-0x%x\n", | ||
469 | base, base + 8-1); | ||
470 | rc = -EBUSY; | ||
471 | goto errout; | ||
472 | } | ||
473 | iface->base = base; | ||
474 | |||
475 | rc = scx200_acb_probe(iface); | ||
476 | if (rc) { | ||
477 | dev_warn(&adapter->dev, "probe failed\n"); | ||
478 | goto errout; | ||
479 | } | ||
480 | |||
481 | scx200_acb_reset(iface); | ||
482 | |||
483 | if (i2c_add_adapter(adapter) < 0) { | ||
484 | dev_err(&adapter->dev, "failed to register\n"); | ||
485 | rc = -ENODEV; | ||
486 | goto errout; | ||
487 | } | ||
488 | |||
489 | lock_kernel(); | ||
490 | iface->next = scx200_acb_list; | ||
491 | scx200_acb_list = iface; | ||
492 | unlock_kernel(); | ||
493 | |||
494 | return 0; | ||
495 | |||
496 | errout: | ||
497 | if (iface) { | ||
498 | if (iface->base) | ||
499 | release_region(iface->base, 8); | ||
500 | kfree(iface); | ||
501 | } | ||
502 | return rc; | ||
503 | } | ||
504 | |||
505 | static struct pci_device_id scx200[] = { | ||
506 | { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE) }, | ||
507 | { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE) }, | ||
508 | { }, | ||
509 | }; | ||
510 | |||
511 | static int __init scx200_acb_init(void) | ||
512 | { | ||
513 | int i; | ||
514 | int rc; | ||
515 | |||
516 | pr_debug(NAME ": NatSemi SCx200 ACCESS.bus Driver\n"); | ||
517 | |||
518 | /* Verify that this really is a SCx200 processor */ | ||
519 | if (pci_dev_present(scx200) == 0) | ||
520 | return -ENODEV; | ||
521 | |||
522 | rc = -ENXIO; | ||
523 | for (i = 0; i < MAX_DEVICES; ++i) { | ||
524 | if (base[i] > 0) | ||
525 | rc = scx200_acb_create(base[i], i); | ||
526 | } | ||
527 | if (scx200_acb_list) | ||
528 | return 0; | ||
529 | return rc; | ||
530 | } | ||
531 | |||
532 | static void __exit scx200_acb_cleanup(void) | ||
533 | { | ||
534 | struct scx200_acb_iface *iface; | ||
535 | lock_kernel(); | ||
536 | while ((iface = scx200_acb_list) != NULL) { | ||
537 | scx200_acb_list = iface->next; | ||
538 | unlock_kernel(); | ||
539 | |||
540 | i2c_del_adapter(&iface->adapter); | ||
541 | release_region(iface->base, 8); | ||
542 | kfree(iface); | ||
543 | lock_kernel(); | ||
544 | } | ||
545 | unlock_kernel(); | ||
546 | } | ||
547 | |||
548 | module_init(scx200_acb_init); | ||
549 | module_exit(scx200_acb_cleanup); | ||
550 | |||
551 | /* | ||
552 | Local variables: | ||
553 | compile-command: "make -k -C ../.. SUBDIRS=drivers/i2c modules" | ||
554 | c-basic-offset: 8 | ||
555 | End: | ||
556 | */ | ||
557 | |||
diff --git a/drivers/i2c/busses/scx200_i2c.c b/drivers/i2c/busses/scx200_i2c.c new file mode 100644 index 000000000000..27fbfecc414f --- /dev/null +++ b/drivers/i2c/busses/scx200_i2c.c | |||
@@ -0,0 +1,131 @@ | |||
1 | /* linux/drivers/i2c/scx200_i2c.c | ||
2 | |||
3 | Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com> | ||
4 | |||
5 | National Semiconductor SCx200 I2C bus on GPIO pins | ||
6 | |||
7 | Based on i2c-velleman.c Copyright (C) 1995-96, 2000 Simon G. Vogl | ||
8 | |||
9 | This program is free software; you can redistribute it and/or modify | ||
10 | it under the terms of the GNU General Public License as published by | ||
11 | the Free Software Foundation; either version 2 of the License, or | ||
12 | (at your option) any later version. | ||
13 | |||
14 | This program is distributed in the hope that it will be useful, | ||
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | GNU General Public License for more details. | ||
18 | |||
19 | You should have received a copy of the GNU General Public License | ||
20 | along with this program; if not, write to the Free Software | ||
21 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/config.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/errno.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/i2c.h> | ||
30 | #include <linux/i2c-algo-bit.h> | ||
31 | #include <asm/io.h> | ||
32 | |||
33 | #include <linux/scx200_gpio.h> | ||
34 | |||
35 | #define NAME "scx200_i2c" | ||
36 | |||
37 | MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>"); | ||
38 | MODULE_DESCRIPTION("NatSemi SCx200 I2C Driver"); | ||
39 | MODULE_LICENSE("GPL"); | ||
40 | |||
41 | static int scl = CONFIG_SCx200_I2C_SCL; | ||
42 | static int sda = CONFIG_SCx200_I2C_SDA; | ||
43 | |||
44 | module_param(scl, int, 0); | ||
45 | MODULE_PARM_DESC(scl, "GPIO line for SCL"); | ||
46 | module_param(sda, int, 0); | ||
47 | MODULE_PARM_DESC(sda, "GPIO line for SDA"); | ||
48 | |||
49 | static void scx200_i2c_setscl(void *data, int state) | ||
50 | { | ||
51 | scx200_gpio_set(scl, state); | ||
52 | } | ||
53 | |||
54 | static void scx200_i2c_setsda(void *data, int state) | ||
55 | { | ||
56 | scx200_gpio_set(sda, state); | ||
57 | } | ||
58 | |||
59 | static int scx200_i2c_getscl(void *data) | ||
60 | { | ||
61 | return scx200_gpio_get(scl); | ||
62 | } | ||
63 | |||
64 | static int scx200_i2c_getsda(void *data) | ||
65 | { | ||
66 | return scx200_gpio_get(sda); | ||
67 | } | ||
68 | |||
69 | /* ------------------------------------------------------------------------ | ||
70 | * Encapsulate the above functions in the correct operations structure. | ||
71 | * This is only done when more than one hardware adapter is supported. | ||
72 | */ | ||
73 | |||
74 | static struct i2c_algo_bit_data scx200_i2c_data = { | ||
75 | NULL, | ||
76 | scx200_i2c_setsda, | ||
77 | scx200_i2c_setscl, | ||
78 | scx200_i2c_getsda, | ||
79 | scx200_i2c_getscl, | ||
80 | 10, 10, 100, /* waits, timeout */ | ||
81 | }; | ||
82 | |||
83 | static struct i2c_adapter scx200_i2c_ops = { | ||
84 | .owner = THIS_MODULE, | ||
85 | .algo_data = &scx200_i2c_data, | ||
86 | .name = "NatSemi SCx200 I2C", | ||
87 | }; | ||
88 | |||
89 | static int scx200_i2c_init(void) | ||
90 | { | ||
91 | pr_debug(NAME ": NatSemi SCx200 I2C Driver\n"); | ||
92 | |||
93 | if (!scx200_gpio_present()) { | ||
94 | printk(KERN_ERR NAME ": no SCx200 gpio pins available\n"); | ||
95 | return -ENODEV; | ||
96 | } | ||
97 | |||
98 | pr_debug(NAME ": SCL=GPIO%02u, SDA=GPIO%02u\n", scl, sda); | ||
99 | |||
100 | if (scl == -1 || sda == -1 || scl == sda) { | ||
101 | printk(KERN_ERR NAME ": scl and sda must be specified\n"); | ||
102 | return -EINVAL; | ||
103 | } | ||
104 | |||
105 | /* Configure GPIOs as open collector outputs */ | ||
106 | scx200_gpio_configure(scl, ~2, 5); | ||
107 | scx200_gpio_configure(sda, ~2, 5); | ||
108 | |||
109 | if (i2c_bit_add_bus(&scx200_i2c_ops) < 0) { | ||
110 | printk(KERN_ERR NAME ": adapter %s registration failed\n", | ||
111 | scx200_i2c_ops.name); | ||
112 | return -ENODEV; | ||
113 | } | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static void scx200_i2c_cleanup(void) | ||
119 | { | ||
120 | i2c_bit_del_bus(&scx200_i2c_ops); | ||
121 | } | ||
122 | |||
123 | module_init(scx200_i2c_init); | ||
124 | module_exit(scx200_i2c_cleanup); | ||
125 | |||
126 | /* | ||
127 | Local variables: | ||
128 | compile-command: "make -k -C ../.. SUBDIRS=drivers/i2c modules" | ||
129 | c-basic-offset: 8 | ||
130 | End: | ||
131 | */ | ||