From b170e0be99f30b9f7f8332392764b3e374d5d962 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sat, 5 May 2007 12:43:03 +0000 Subject: [PATCH] Delete all kernel bus drivers, documentation and references. We are moving to a user-space-only package, all the drivers are maintained in the Linux kernel tree itself. git-svn-id: http://lm-sensors.org/svn/lm-sensors/branches/lm-sensors-3.0.0@4386 7894878c-1315-0410-8ee3-d5d059ff63e0 --- BUGS | 8 - CHANGES | 1 + Makefile | 4 +- README | 21 - README.directories | 2 +- doc/busses/i2c-ali1535 | 53 -- doc/busses/i2c-ali15x3 | 135 ----- doc/busses/i2c-amd756 | 30 -- doc/busses/i2c-amd8111 | 48 -- doc/busses/i2c-hydra | 35 -- doc/busses/i2c-i801 | 107 ---- doc/busses/i2c-i810 | 66 --- doc/busses/i2c-ipmb | 55 -- doc/busses/i2c-ipmi | 61 --- doc/busses/i2c-nforce2 | 53 -- doc/busses/i2c-piix4 | 100 ---- doc/busses/i2c-savage4 | 42 -- doc/busses/i2c-sis5595 | 56 --- doc/busses/i2c-sis630 | 63 --- doc/busses/i2c-sis645 | 85 ---- doc/busses/i2c-tsunami | 46 -- doc/busses/i2c-via | 50 -- doc/busses/i2c-viapro | 61 --- doc/busses/i2c-virtual | 102 ---- doc/busses/i2c-voodoo3 | 83 --- doc/modules | 11 +- kernel/busses/Module.mk | 127 ----- kernel/busses/dmi_scan.c | 249 --------- kernel/busses/i2c-ali1535.c | 529 ------------------- kernel/busses/i2c-ali1563.c | 464 ----------------- kernel/busses/i2c-ali15x3.c | 548 -------------------- kernel/busses/i2c-amd756-s4882.c | 264 ---------- kernel/busses/i2c-amd756.c | 444 ---------------- kernel/busses/i2c-amd8111.c | 424 ---------------- kernel/busses/i2c-hydra.c | 191 ------- kernel/busses/i2c-i801.c | 737 --------------------------- kernel/busses/i2c-i810.c | 327 ------------ kernel/busses/i2c-ipmb.c | 380 -------------- kernel/busses/i2c-ipmi.c | 251 ---------- kernel/busses/i2c-isa.c | 88 ---- kernel/busses/i2c-keywest.c | 619 ----------------------- kernel/busses/i2c-keywest.h | 113 ----- kernel/busses/i2c-nforce2.c | 430 ---------------- kernel/busses/i2c-piix4.c | 584 --------------------- kernel/busses/i2c-savage4.c | 243 --------- kernel/busses/i2c-sis5595.c | 495 ------------------ kernel/busses/i2c-sis630.c | 544 -------------------- kernel/busses/i2c-sis645.c | 605 ---------------------- kernel/busses/i2c-tsunami.c | 170 ------- kernel/busses/i2c-via.c | 199 -------- kernel/busses/i2c-viapro.c | 564 --------------------- kernel/busses/i2c-virtual.c | 430 ---------------- kernel/busses/i2c-voodoo3.c | 296 ----------- kernel/chips/pca954x.c | 836 ------------------------------- kernel/include/i2c-virtual.h | 71 --- lm_sensors.lsm | 5 +- 56 files changed, 10 insertions(+), 12595 deletions(-) delete mode 100644 doc/busses/i2c-ali1535 delete mode 100644 doc/busses/i2c-ali15x3 delete mode 100644 doc/busses/i2c-amd756 delete mode 100644 doc/busses/i2c-amd8111 delete mode 100644 doc/busses/i2c-hydra delete mode 100644 doc/busses/i2c-i801 delete mode 100644 doc/busses/i2c-i810 delete mode 100644 doc/busses/i2c-ipmb delete mode 100644 doc/busses/i2c-ipmi delete mode 100644 doc/busses/i2c-nforce2 delete mode 100644 doc/busses/i2c-piix4 delete mode 100644 doc/busses/i2c-savage4 delete mode 100644 doc/busses/i2c-sis5595 delete mode 100644 doc/busses/i2c-sis630 delete mode 100644 doc/busses/i2c-sis645 delete mode 100644 doc/busses/i2c-tsunami delete mode 100644 doc/busses/i2c-via delete mode 100644 doc/busses/i2c-viapro delete mode 100644 doc/busses/i2c-virtual delete mode 100644 doc/busses/i2c-voodoo3 delete mode 100644 kernel/busses/Module.mk delete mode 100644 kernel/busses/dmi_scan.c delete mode 100644 kernel/busses/i2c-ali1535.c delete mode 100644 kernel/busses/i2c-ali1563.c delete mode 100644 kernel/busses/i2c-ali15x3.c delete mode 100644 kernel/busses/i2c-amd756-s4882.c delete mode 100644 kernel/busses/i2c-amd756.c delete mode 100644 kernel/busses/i2c-amd8111.c delete mode 100644 kernel/busses/i2c-hydra.c delete mode 100644 kernel/busses/i2c-i801.c delete mode 100644 kernel/busses/i2c-i810.c delete mode 100644 kernel/busses/i2c-ipmb.c delete mode 100644 kernel/busses/i2c-ipmi.c delete mode 100644 kernel/busses/i2c-isa.c delete mode 100644 kernel/busses/i2c-keywest.c delete mode 100644 kernel/busses/i2c-keywest.h delete mode 100644 kernel/busses/i2c-nforce2.c delete mode 100644 kernel/busses/i2c-piix4.c delete mode 100644 kernel/busses/i2c-savage4.c delete mode 100644 kernel/busses/i2c-sis5595.c delete mode 100644 kernel/busses/i2c-sis630.c delete mode 100644 kernel/busses/i2c-sis645.c delete mode 100644 kernel/busses/i2c-tsunami.c delete mode 100644 kernel/busses/i2c-via.c delete mode 100644 kernel/busses/i2c-viapro.c delete mode 100644 kernel/busses/i2c-virtual.c delete mode 100644 kernel/busses/i2c-voodoo3.c delete mode 100644 kernel/chips/pca954x.c delete mode 100644 kernel/include/i2c-virtual.h diff --git a/BUGS b/BUGS index b584ba98..9126dd8c 100644 --- a/BUGS +++ b/BUGS @@ -77,11 +77,3 @@ lock bit for the base address registers. Also, the temperature reading in sis5595 is usually wrong. Different formulas are required for different versions of the chip and different motherboards. - -================================ -bus drivers (all) - -Rmmod'ing a bus driver when the /proc directory for a chip -driver on that bus is in use may cause a kernel oops, because -the chip driver gets removed too. See ticket #331 for details. -Not likely to happen. No obvious way to fix. diff --git a/CHANGES b/CHANGES index 557ed876..065109f0 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,7 @@ lm_sensors CHANGES file ----------------------- SVN HEAD + All bus modules and documentation: Delete File doc/version-2: Delete, obsolete File sensors.conf.eg: Add a dme1737 section File lm_sensors.sysconfig: Delete, now generated by sensors-detect diff --git a/Makefile b/Makefile index 0f82fe1e..eeb8af9c 100644 --- a/Makefile +++ b/Makefile @@ -176,7 +176,7 @@ ifneq ($(MAKECMDGOALS),user_uninstall) ifneq ($(MAKECMDGOALS),package) ifneq ($(MAKECMDGOALS),userpackage) ifneq ($(MAKECMDGOALS),manhtml) -SRCDIRS += kernel kernel/busses kernel/chips +SRCDIRS += kernel kernel/chips endif endif endif @@ -367,9 +367,7 @@ userpackage: version clean $(KERNELINCLUDEDIR)/sensors.h find $$lmpackage/ -type f | grep -v ^$$lmpackage/$$lmpackage$$ | \ grep -v ^$$lmpackage/$$lmpackage.tar$$ | \ grep -v ^$$lmpackage/doc/chips | \ - grep -v ^$$lmpackage/doc/busses | \ grep -v ^$$lmpackage/kernel/chips | \ - grep -v ^$$lmpackage/kernel/busses | \ grep -v ^$$lmpackage/$$ | \ grep -v /CVS | \ grep -v /\\.# | \ diff --git a/README b/README index c8fc488b..8ba5687d 100644 --- a/README +++ b/README @@ -42,27 +42,6 @@ See the lm_sensors download page for further guidance: ============================================================================= -At least the following I2C/SMBus adapters are supported: - Acer Labs M1533, M1535, M1543C and M1563 - AMD 756, 766, 768 and 8111 - AMD 8111 SMBus 2.0 - Apple Hydra (used on some PPC machines) - ATI IXP200, IXP300, IXP400, SB600 - DEC 21272/21274 (Tsunami/Typhoon - on Alpha boards) - Intel ICH/ICH0/ICH2/ICH3/ICH4/ICH5/ICH6/ICH7/ICH8/ICH9 (82801xx) - Intel 6300ESB, 631xESB/632xESB (ESB2) - Intel PIIX4 (used in many Intel chipsets) - Intel I810/I810E/I815/I845G GMCH - Intel 82443MX (440MX) - NVidia nForce, nForce2, nForce3, nForce4 - ServerWorks OSB4, CSB5, CSB6, HT-1000 - SiS 5595, 630, 645, 655, 730 - SMSC Victory66 - 3Dfx Voodoo 3 and Banshee - VIA Technologies VT82C586B, VT82C596A/B, VT82C686A/B, VT8231, - VT8233, VT8233A, VT8235, VT8237R/A, VT8251, CX700 - - At least the following hardware sensor chips are supported: Analog Devices ADM1021, ADM1021A, ADM1022, ADM1023, ADM1024, ADM1025, ADM1026, ADM1027, ADM1030, ADM1031, diff --git a/README.directories b/README.directories index 00adce1a..37a50074 100644 --- a/README.directories +++ b/README.directories @@ -5,7 +5,7 @@ The directories within this package: * etc A sample configuration file for the 'sensors' program. * kernel - The kernel modules: I2C/SMBus master drivers, and sensor chip drivers. + The kernel modules: sensor chip drivers. * lib The user-space sensors support library code. * prog diff --git a/doc/busses/i2c-ali1535 b/doc/busses/i2c-ali1535 deleted file mode 100644 index 17612e44..00000000 --- a/doc/busses/i2c-ali1535 +++ /dev/null @@ -1,53 +0,0 @@ -Kernel driver `i2c-ali1535.o' - -Status: Beta; block reads/writes untested (not used by any current chip - driver) - -Supported adapters: - * Acer Labs, Inc. ALI 1535 (south bridge) - Datasheet: Available at the Acer Labs website (password may be required) - -Author: Frodo Looijaard , Philip Edelbrock - , Mark D. Studebaker and - Dan Eaton - -License: GPL - - -Module Parameters ------------------ - -(none) - - -Description ------------ - -This is the driver for the SMB Host controller on -Acer Labs Inc. (ALI) M1535 South Bridge. - -The M1535 is a South bridge for portable systems. -It is very similar to the M15x3 South bridges also produced -by Acer Labs Inc. Some of the registers within the part -have moved and some have been redefined slightly. Additionally, -the sequencing of the SMBus transactions has been modified -to be more consistent with the sequencing recommended by -the manufacturer and observed through testing. These -changes are reflected in this driver and can be identified -by comparing this driver to the i2c-ali15x3 driver. -For an overview of these chips see http://www.acerlabs.com - -The SMB controller is part of the 7101 device, which is an -ACPI-compliant Power Management Unit (PMU). - -The whole 7101 device has to be enabled for the SMB to work. -You can't just enable the SMB alone. -The SMB and the ACPI have separate I/O spaces. -We make sure that the SMB is enabled. We leave the ACPI alone. - - -Features --------- - -This driver controls the SMB Host only. -This driver does not use interrupts. diff --git a/doc/busses/i2c-ali15x3 b/doc/busses/i2c-ali15x3 deleted file mode 100644 index e531694f..00000000 --- a/doc/busses/i2c-ali15x3 +++ /dev/null @@ -1,135 +0,0 @@ -Kernel driver `i2c-ali15x3.o' - -Status: Complete and tested; block reads/writes untested (not used by any - current chip driver) - -Supported adapters: - * Acer Labs, Inc. ALI 1533 and 1543C (south bridge) - Datasheet: Available at the Acer Labs website (password required) - -Author: Frodo Looijaard , Philip Edelbrock - , and Mark D. Studebaker - -License: GPL - - -Module Parameters ------------------ - -* force_addr: int - Initialize the base address of the i2c controller - - -Notes ------ - -The force_addr parameter is useful for boards that don't set the address -in the BIOS. Does not do a PCI force; the device must still be present -in lspci. Don't use this unless the driver complains that the -base address is not set. -Example: 'modprobe i2c-ali15x3 force_addr=0xe800' - -SMBus periodically hangs on ASUS P5A motherboards and can only be -cleared by a power cycle. Cause unknown (see Issues below). - - -Description ------------ - -This is the driver for the SMB Host controller on -Acer Labs Inc. (ALI) M1541 and M1543C South Bridges. - -The M1543C is a South bridge for desktop systems. -The M1541 is a South bridge for portable systems. -They are part of the following ALI chipsets: - "Aladdin Pro 2": Includes the M1621 Slot 1 North bridge - with AGP and 100MHz CPU Front Side bus - - "Aladdin V": Includes the M1541 Socket 7 North bridge - with AGP and 100MHz CPU Front Side bus - Some Aladdin V motherboards: - Asus P5A - Atrend ATC-5220 - BCM/GVC VP1541 - Biostar M5ALA - Gigabyte GA-5AX (** Generally doesn't work because the BIOS doesn't - enable the 7101 device! **) - Iwill XA100 Plus - Micronics C200 - Microstar (MSI) MS-5169 - - "Aladdin IV": Includes the M1541 Socket 7 North bridge - with host bus up to 83.3 MHz. - -For an overview of these chips see http://www.acerlabs.com -At this time the full data sheets on the web site are password protected, -however if you contact the ALI office in San Jose -they may give you the password. - -The M1533/M1543C devices appear as FOUR separate devices -on the PCI bus. An output of lspci will show something similar -to the following: - - 00:02.0 USB Controller: Acer Laboratories Inc. M5237 (rev 03) - 00:03.0 Bridge: Acer Laboratories Inc. M7101 <= THIS IS THE ONE WE NEED - 00:07.0 ISA bridge: Acer Laboratories Inc. M1533 (rev c3) - 00:0f.0 IDE interface: Acer Laboratories Inc. M5229 (rev c1) - -** IMPORTANT ** -** If you have a 1533 or 1543C on the board and you get -** "ali15x3.o: Error: Can't detect ali15x3!" -** then run lspci. -** If you see the 1533 and 5229 devices but NOT the 7101 device, -** then you must enable ACPI, the PMU, SMB, or something similar -** in the BIOS. If you can't figure out how to enable the -** 7101 device in the BIOS, you can try one of the "hotplug" modules - -** see below. -** The driver won't work if it can't find the 7101 device. - -The SMB controller is part of the 7101 device, which is an -ACPI-compliant Power Management Unit (PMU). - -The whole 7101 device has to be enabled for the SMB to work. -You can't just enable the SMB alone. -The SMB and the ACPI have separate I/O spaces. -We make sure that the SMB is enabled. We leave the ACPI alone. - - -Features --------- -This driver controls the SMB Host only. -The SMB Slave controller on the M15X3 is not enabled. -This driver does not use interrupts. - - -Issues ------- -This driver requests the I/O space for only the SMB -registers. It doesn't use the ACPI region. - -On the ASUS P5A motherboard, there are several reports that -the SMBus will hang and this can only be resolved by -powering off the computer. It appears to be worse when the board -gets hot, for example under heavy CPU load, or in the summer. -There may be electrical problems on this board. -On the P5A, the W83781D sensor chip is on both the ISA and -SMBus. Therefore the SMBus hangs can generally be avoided -by accessing the W83781D on the ISA bus only. - - -Hot Plug Modules ----------------- - -There are EXPERIMENTAL "hotplug" modules which will enable the -m7101 device if it is not enabled on your motherboard. -Use these at your own risk. Read the README file carefully. - -m7101 Version 0.1 for 2.2 and early 2.3 kernels: - README: http://www.netroedge.com/~lm78/misc/README-m7101.txt - source and README: http://www.netroedge.com/~lm78/misc/m7101-0.1.tar.gz - -m7101 Version 0.2 for 2.4 and later 2.3 kernels: - In the directory prog/hotplug in this package. - Must be built separately. - - diff --git a/doc/busses/i2c-amd756 b/doc/busses/i2c-amd756 deleted file mode 100644 index 77b02350..00000000 --- a/doc/busses/i2c-amd756 +++ /dev/null @@ -1,30 +0,0 @@ -Kernel driver `i2c-amd756.o' - -Status: Complete and somewhat tested - -Supported adapters: - * AMD 756 - * AMD 766 - * AMD 768 - * AMD 8111 - Datasheets: Publicly available on AMD website - - * nVidia nForce - Datasheet: Unavailable - - -Module Parameters ------------------ - -(none) - - -Description ------------ - -This driver supports the AMD 756, 766, 768 and 8111 Peripheral Bus Controllers, and -the nVidia nForce. - -Note that for the 8111, there are two SMBus adapters. The SMBus 1.0 adapter is -supported by this driver, and the SMBus 2.0 adapter is supported -by the i2c-amd8111 driver. diff --git a/doc/busses/i2c-amd8111 b/doc/busses/i2c-amd8111 deleted file mode 100644 index 784883bb..00000000 --- a/doc/busses/i2c-amd8111 +++ /dev/null @@ -1,48 +0,0 @@ -Kernel driver `i2c-adm8111.o' - -Status: Slightly tested. - -Supported adapters: - * AMD-8111 SMBus 2.0 PCI interface - -Datasheets: - AMD datasheet not yet available, but almost everything can be found - in the publicly available ACPI 2.0 specification, which the adapter - follows. - -Author: Vojtech Pavlik - -Module Parameters ------------------ - -None. - -Description ------------ - -If you see something like this: - -00:07.2 SMBus: Advanced Micro Devices [AMD] AMD-8111 SMBus 2.0 (rev 02) - Subsystem: Advanced Micro Devices [AMD] AMD-8111 SMBus 2.0 - Flags: medium devsel, IRQ 19 - I/O ports at d400 [size=32] - -in your 'lspci -v', then this driver is for your chipset. - -Process Call Support --------------------- - -Supported. - -SMBus 2.0 Support ------------------ - -Supported. Both PEC and block process call support is implemented. -Slave mode or host notification are not yet implemented. - -Notes ------ - -Note that for the 8111, there are two SMBus adapters. The SMBus 2.0 adapter is -supported by this driver, and the SMBus 1.0 adapter is supported -by the i2c-amd756 driver. diff --git a/doc/busses/i2c-hydra b/doc/busses/i2c-hydra deleted file mode 100644 index 55bee71e..00000000 --- a/doc/busses/i2c-hydra +++ /dev/null @@ -1,35 +0,0 @@ -Kernel driver `i2c-hydra.o' - -Status: Complete and somewhat tested - -Supported adapters: - * Apple `Hydra' Mac I/O - Datasheet: Was publicly available from the Apple website, now seems to - have disappeared?!? - -Author: Geert Uytterhoeven - - -Module Parameters ------------------ - -(none) - - -Description ------------ - -i2c-hydra is an i2c bus driver for CHRP motherboards with the Apple Hydra Mac -I/O. - -Your /proc/pci or lspci listing must show this : - - Unknown class: Apple Hydra (rev 2) - -To install this driver, simply do - # modprobe i2c-hydra - -This driver uses the i2c-algo-bit module which must be -modprobed and/or enabled in your kernel -(Character Devices -> I2C Support -> I2C Bit-Banging Interfaces). - diff --git a/doc/busses/i2c-i801 b/doc/busses/i2c-i801 deleted file mode 100644 index ec218287..00000000 --- a/doc/busses/i2c-i801 +++ /dev/null @@ -1,107 +0,0 @@ -Kernel driver `i2c-i801.o' - -Status: Tested and stable. - Block reads/writes lightly tested. - HW PEC support Beta. - I2C Block Read support Beta. - -Supported adapters: - * Intel 82801AA and 82801AB (ICH and ICH0 - part of the - '810' and '810E' chipsets) - * Intel 82801BA (ICH2 - part of the '815E' chipset) - * Intel 82801CA/CAM (ICH3) - * Intel 82801DB (ICH4) - * Intel 82801EB/ER (ICH5) - * Intel 6300ESB/ESB2 - * Intel 82801FB/FR/FW/FRW (ICH6) - * Intel ICH7/ICH8/ICH9 - Datasheets: Publicly available at the Intel website - -Authors: Frodo Looijaard , Philip Edelbrock - , and Mark Studebaker - - -Module Parameters ------------------ - -* force_addr: int - Forcibly enable the ICH at the given address. EXTREMELY DANGEROUS! - - -Description ------------ - -The ICH (properly known as the 82801AA), ICH0 (82801AB), -ICH2 (82801BA), ICH3 (82801CA/CAM) and later devices -are Intel chips that are a part of -Intel's '810' chipset for Celeron-based PCs, -'810E' chipset for Pentium-based PCs, '815E' chipset, and others. - -The ICH chips contain at least SEVEN separate PCI functions -in TWO logical PCI devices. -An output of lspci will show something similar to the following: - - 00:1e.0 PCI bridge: Intel Corporation: Unknown device 2418 (rev 01) - 00:1f.0 ISA bridge: Intel Corporation: Unknown device 2410 (rev 01) - 00:1f.1 IDE interface: Intel Corporation: Unknown device 2411 (rev 01) - 00:1f.2 USB Controller: Intel Corporation: Unknown device 2412 (rev 01) - 00:1f.3 Unknown class [0c05]: Intel Corporation: Unknown device 2413 (rev 01) - -The SMBus controller is function 3 in device 1f. -Class 0c05 is SMBus Serial Controller. - -If you do NOT see the 24x3 device at function 3, and you can't -figure out any way in the BIOS to enable it, -(and especially if you have an Asus P4B board), -see prog/hotplug/README.p4b. - -The ICH chips are quite similar to Intel's PIIX4 chip, -at least in the SMBus controller. - -See the file i2c-piix4 for some additional information. - - -Process Call Support --------------------- - -Not supported. - - -I2C Block Read Support ----------------------- - -The ICH4 supports a special 3-byte address (command code -plus 2 more bytes) I2C block read. -The driver and the kernel i2c protocol stack do not -support this. -The ICH5 and higher support a standard 1-byte address (command code) -I2C block read. The driver does support this. - - -SMBus 2.0 Support ------------------ - -The 82801DB (ICH4) and later chips support several SMBus 2.0 features. -Kernel and driver support are as follows: - -Feature Kernel Driver -Slave mode no no -Host notify no no -Block PEC yes yes -Hardware PEC yes yes - - -Other ICH4 and later Features ------------------------------ - -The following additional features are also _not_ supported: - -32 Byte buffer - - -********************** -The lm_sensors project gratefully acknowledges the support of -Texas Instruments in the initial development of this driver. - -The lm_sensors project gratefully acknowledges the support of -Intel in the development of SMBus 2.0 / ICH4 features of this driver. diff --git a/doc/busses/i2c-i810 b/doc/busses/i2c-i810 deleted file mode 100644 index fcc44ffa..00000000 --- a/doc/busses/i2c-i810 +++ /dev/null @@ -1,66 +0,0 @@ -Kernel driver `i2c-i810.o' - -Status: Stable - -Supported adapters: - * Intel 82810, 82810-DC100, 82810E, and 82815 (GMCH) - * Intel 82845G (GMCH) - -Author: Frodo Looijaard , Philip Edelbrock - , - Kyösti Mälkki , - and Mark D. Studebaker - -Main contact: Mark Studebaker - - -Module Parameters ------------------ -(none) - - -Description ------------ -This driver uses the i2c-algo-bit module which must be -modprobed and/or enabled in your kernel -(Character Devices -> I2C Support -> I2C Bit-Banging Interfaces). - -WARNING: If you have an '810' or '815' motherboard, your standard I2C -temperature sensors are most likely on the 801's I2C bus. -You want the i2c-i801.o driver for those, not this driver. - -Now for the i2c-i810... - -The GMCH chip contains two I2C interfaces. - -The first interface is used for DDC (Data Display Channel) -which is a serial channel through the VGA monitor connector -to a DDC-compliant monitor. This interface is defined by the -Video Electronics Standards Association (VESA). The standards -are available for purchase at http://www.vesa.org . - -The second interface is a general-purpose I2C bus. -It may be connected to a TV-out chip such as the BT869 or possibly -to a digital flat-panel display. - -Stability ---------- -Apparently stable. - - -Supported Devices ------------------ -See above. - - -Features --------- -Both busses use the i2c-algo-bit driver for 'bit banging' and support -for specific transactions is provided by i2c-algo-bit. - - -Issues ------- -If you enable bus testing in i2c-algo-bit (insmod i2c-algo-bit bit_test=1), -the test may fail; if so, the i2c-i810 driver won't be inserted. -However, we think this has been fixed. diff --git a/doc/busses/i2c-ipmb b/doc/busses/i2c-ipmb deleted file mode 100644 index 06d3a026..00000000 --- a/doc/busses/i2c-ipmb +++ /dev/null @@ -1,55 +0,0 @@ -Kernel driver `i2c-ipmb.o' - -Status: IN DEVELOPMENT - DOESN'T WORK AT ALL - DON'T BOTHER TRYING IT - -Supported adapters: - * IPMI BMC - -Author: Mark D. Studebaker - - -Module Parameters ------------------ -(none) - - -Description ------------ -This is an adapter which provides access to the IPMB -(Intelligent Platform Management Bus) and other I2C / SMBus busses -behind the BMC (Baseboard Management Controller) via -IPMI (Intelligent Platform Management Interface). - -This provides low-level access to all devices on busses -behind the BMC. For high-level access to sensors known -to the BMC, use the i2c-ipmi and bmcsensors modules. - -This module REQUIRES the IPMI kernel patch by Corey Minyard, -v13 or higher, available at http://openipmi.sourceforge.net . -Other IPMI drivers are not supported. - -See http://www.intel.com/design/servers/ipmi/ for -IPMI standards information. - -You must configure the following features in your kernel -(under Character Devices): - IPMI top-level message handler - IPMI KCS handler -The IPMI device interface and IPMI watchdog handler are not required. - -If the KCS handler (ipmi_kcs_drv) is configured as a module, -you must modprobe it separately, it will not load automatically -when you modprobe i2c-ipmi or ipmi_msghandler (unless you set up -/etc/modules.conf to load ipmi_kcs_drv when ipmi_msghandler is loaded). - -Issues ------- -Only one BMC is supported - shouldn't be a problem. - -Alpha! - - - -********************** -The lm_sensors project gratefully acknowledges the support of -Hewlett Packard (Ft. Collins) in the development of this driver. diff --git a/doc/busses/i2c-ipmi b/doc/busses/i2c-ipmi deleted file mode 100644 index 7832c776..00000000 --- a/doc/busses/i2c-ipmi +++ /dev/null @@ -1,61 +0,0 @@ -Kernel driver `i2c-ipmi.o' - -Status: Alpha - -Supported adapters: - * IPMI BMC - -Author: Mark D. Studebaker - - -Module Parameters ------------------ -(none) - - -Description ------------ -This is a "dummy" adapter which provides access to the -BMC (Baseboard Management Controller) via IPMI (Intelligent Platform -Management Interface). It is used by the bmcsensors module. - -Together with the bmcsensors module, this provides high-level -access to sensors known by the BMC. For low-level access to -IPMB (I2C/SMBus) busses behind the BMC, use the i2c-ipmb module. - -This module REQUIRES the IPMI kernel patch by Corey Minyard, -v13 or higher, available at http://openipmi.sourceforge.net . -Other IPMI drivers are not supported. - -See http://www.intel.com/design/servers/ipmi/ for -IPMI standards information. - -You must configure the following features in your kernel -(under Character Devices): - IPMI top-level message handler - IPMI KCS handler -The IPMI device interface and IPMI watchdog handler are not required. - -If the KCS handler (ipmi_kcs_drv) is configured as a module, -you must modprobe it separately, it will not load automatically -when you modprobe i2c-ipmi or ipmi_msghandler (unless you set up -/etc/modules.conf to load ipmi_kcs_drv when ipmi_msghandler is loaded). - -Issues ------- -Only one BMC is supported - shouldn't be a problem. - -Only one client is supported - to be fixed. - -Libsensors was hacked to support this dummy driver; only -the ISA dummy driver was supported previously. -The library needs further enhancements for full -dummy driver support. - -Alpha! - - - -********************** -The lm_sensors project gratefully acknowledges the support of -Hewlett Packard (Ft. Collins) in the development of this driver. diff --git a/doc/busses/i2c-nforce2 b/doc/busses/i2c-nforce2 deleted file mode 100644 index c9213298..00000000 --- a/doc/busses/i2c-nforce2 +++ /dev/null @@ -1,53 +0,0 @@ -Kernel driver i2c-nforce2 -------------------------- - -Status: Well tested - -Supported adapters: - * nVidia nForce2 SMBus PCI interface - (10de:0064, included in nForce2 MCP, - 10de:0084, included in nForce2 Ultra 400 MCP) - Datasheet: not publicly available, but seems to be similar to the - AMD-8111 SMBus 2.0 adapter. - - * nVidia nForce3 SMBus PCI interface - (10de:00d4, included in nForce3 Pro150 MCP, - 10de:00e4, included in nForce3 250Gb MCP) - Datasheet: same as for nForce2 SMBus PCI interface - - * nVidia nForce4 SMBus PCI interface - (10de:0052, included in nForce4 MCP) - (10de:0034, included in nForce4 MCP-04) - (10de:0264, included in nForce4 MCP51) - (10de:0368, included in nForce4 MCP55) - Datasheet: same as for nForce2 SMBus PCI interface - -Author: Hans-Frieder Vogt - - -Description ------------ - -i2c-nforce2 is a driver for the SMBuses included in the nVidia nForce2, -nForce3 and nForce4 MCP. - -If your 'lspci -v' listing shows something like the following, - -00:01.1 SMBus: nVidia Corporation: Unknown device 0064 (rev a2) - Subsystem: Asustek Computer, Inc.: Unknown device 0c11 - Flags: 66Mhz, fast devsel, IRQ 5 - I/O ports at c000 [size=32] - Capabilities: - -then this driver should support the SMBuses of your motherboard. - - -Notes ------ - -The SMBus adapter in the nForce2/3/4 chipset seems to be very similar to the -SMBus 2.0 adapter in the AMD-8111 southbridge. However, I could only get the -driver to work with direct I/O access, which is different to the EC interface -of the AMD-8111. -Tested on Asus A7N8X. The ACPI DSDT table of the Asus A7N8X lists two SMBuses, -both of which are supported by this driver. diff --git a/doc/busses/i2c-piix4 b/doc/busses/i2c-piix4 deleted file mode 100644 index d7cce66e..00000000 --- a/doc/busses/i2c-piix4 +++ /dev/null @@ -1,100 +0,0 @@ -Kernel driver `i2c-piix4.o' - -Status: Complete and well-tested - except for Victory66 support which is Alpha. - -Supported adapters: - * Intel 82371AB PIIX4 and PIIX4E - * Intel 82443MX (440MX) - Datasheet: Publicly available at the Intel website - * ServerWorks OSB4, CSB5, CSB6 and HT-1000 southbridges - Datasheet: Only available via NDA from ServerWorks - * ATI IXP200, IXP300, IXP400 and SB600 southbridges - Datasheet: Not publicly available - * Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge - Datasheet: Publicly available at the SMSC website http://www.smsc.com - -Author: Frodo Looijaard and Philip Edelbrock - - - -Module Parameters ------------------ - -* force: int - Forcibly enable the PIIX4. DANGEROUS! -* force_addr: int - Forcibly enable the PIIX4 at the given address. EXTREMELY DANGEROUS! - - -Description ------------ - -The PIIX4 (properly known as the 82371AB) is an Intel chip with a lot of -functionality. Among other things, it implements the PCI bus. One of its -minor functions is implementing a System Management Bus. This is a true -SMBus - you can not access it on I2C levels. The good news is that it -natively understands SMBus commands and you do not have to worry about -timing problems. The bad news is that non-SMBus devices connected to it -can confuse it mightily. Yes, this is known to happen... - -Cat /proc/pci, and see whether it contains an entry like this: - - Bus 0, device 1, function 3: - Bridge: Intel 82371AB PIIX4 ACPI (rev 1). - Medium devsel. Fast back-to-back capable. - -Bus and device numbers may differ, but the function number must be identical -(like many PCI devices, the PIIX4 incorporates a number of different -'functions', which can be considered as separate devices). If you find such -an entry, you have a PIIX4 SMBus controller. - -On some computers (most notably, some Dells), the SMBus is disabled by -default. If you use the insmod parameter 'force=1', the kernel module - will try to enable it. THIS IS VERY DANGEROUS! If the BIOS did not -set up a correct address for this module, you could get in big trouble -(read: crashes, data corruption, etc.). Try this only as a last resort -(try BIOS updates first, for example), and backup first! An even more -dangerous option is 'force_addr='. This will not only enable the -PIIX4 like 'force' foes, but it will also set a new base I/O port address. -The SMBus parts of the PIIX4 needs a range of 8 of these addresses to -function correctly. If these addresses are already reserved by some other -device, you will get into big trouble! DON'T USE THIS IF YOU ARE NOT VERY -SURE ABOUT WHAT YOU ARE DOING! - -The PIIX4E is just an new version of the PIIX4; it is supported as well. The -PIIX/PIIX3 does not implement an SMBus or I2C bus, so you can't use this -driver on those mainboards. - -The ServerWorks Southbridges, the Intel 440MX, -and the Victory66 are identical to the PIIX4 in I2C/SMBus support. - -If you own Force CPCI735 motherboard or other OSB4 based systems you may need -to change the SMBus Interrupt Select register so the SMBus controller uses -the SMI mode. - -1) Use lspci command and locate the PCI device with the SMBus controller: - 00:0f.0 ISA bridge: ServerWorks OSB4 South Bridge (rev 4f) - The line may vary for different chipsets. Please consult the driver source - for all possible PCI ids (and lspci -n to match them). Lets assume the - device is located at 00:0f.0. -2) Now you just need to change the value in 0xD2 register. Get it first with - command: lspci -xxx -s 00:0f.0 - If the value is 0x3 then you need to change it to 0x1 - setpci -s 00:0f.0 d2.b=1 - -Please note that you don't need to do that in all cases, just when the SMBus is -not working properly. - - -Hardware-specific issues ------------------------- - -This driver will refuse to load on IBM systems with an Intel PIIX4 SMBus. -Some of these machines have an RFID EEPROM (24RF08) connected to the SMBus, -which can easily get corrupted due to a state machine bug. These are mostly -Thinkpad laptops, but desktop systems may also be affected. We have no list -of all affected systems, so the only safe solution was to prevent access to -the SMBus on all IBM systems (detected using DMI data.) - -For additional information, read README.thinkpad. diff --git a/doc/busses/i2c-savage4 b/doc/busses/i2c-savage4 deleted file mode 100644 index bce8110b..00000000 --- a/doc/busses/i2c-savage4 +++ /dev/null @@ -1,42 +0,0 @@ -Kernel driver `i2c-savage4.o' - -Status: Alpha - -Supported adapters: - * Savage4 - * Savage2000 - -Author: Frodo Looijaard , Philip Edelbrock - , Ralph Metzler , - Alexander Wold, and Mark D. Studebaker - -Main contact: Sensors mailing list - - -Module Parameters ------------------ - -(none) - - -Description ------------ - -The Savage4 chips contain two I2C interfaces (aka a I2C 'master' -or 'host'). - -The first interface is used for DDC (Data Display Channel) -which is a serial channel through the VGA monitor connector -to a DDC-compliant monitor. This interface is defined by the -Video Electronics Standards Association (VESA). The standards -are available for purchase at http://www.vesa.org . -The DDC bus is not yet supported because its register is not -directly memory-mapped. - -The second interface is a general-purpose I2C bus. -This is the only interface supported by the driver at the moment. - -This driver uses the i2c-algo-bit module which must be -modprobed and/or enabled in your kernel -(Character Devices -> I2C Support -> I2C Bit-Banging Interfaces). - diff --git a/doc/busses/i2c-sis5595 b/doc/busses/i2c-sis5595 deleted file mode 100644 index 9997d32d..00000000 --- a/doc/busses/i2c-sis5595 +++ /dev/null @@ -1,56 +0,0 @@ -Kernel driver `i2c-sis5595.o' - -Status: Beta - -Supported adapters: - * Silicon Integrated Systems Corp. SiS5595 Southbridge - Datasheet: Publicly available at the Silicon Integrated Systems Corp. site. - -Author: Frodo Looijaard and - Mark D. Studebaker - - Note: all have mfr. ID 0x1039. - SUPPORTED PCI ID - 5595 0008 - - Note: The chips below contain a 0008 device which is incompatible with the - 5595. We recognize these by the presence of the listed - "blacklist" PCI ID and refuse to load. - - NOT SUPPORTED PCI ID BLACKLIST PCI ID - 540 0008 0540 - 550 0008 0550 - 5513 0008 5511 - 5581 0008 5597 - 5582 0008 5597 - 5597 0008 5597 - 5598 0008 5597/5598 - 630 0008 0630 - 645 0008 0645 - 730 0008 0730 - 735 0008 0735 - -Module Parameters ------------------ - -force_addr=0xaddr Set the I/O base address. Useful for boards - that don't set the address in the BIOS. Does not do a - PCI force; the device must still be present in lspci. - Don't use this unless the driver complains that the - base address is not set. - Example: 'modprobe i2c-sis5595 force_addr=0x290' - - -Description ------------ - -i2c-sis5595 is a true SMBus host driver for motherboards with the -SiS5595 southbridges. - -WARNING: If you are trying to access the integrated sensors on the -SiS5595 chip, you want the sis5595.o driver for those, not this driver. -This driver is a BUS driver, not a CHIP driver. -A BUS driver is used by other CHIP drivers to access chips on the bus. - -To install this driver, simply do - # modprobe i2c-sis5595 diff --git a/doc/busses/i2c-sis630 b/doc/busses/i2c-sis630 deleted file mode 100644 index 40a73761..00000000 --- a/doc/busses/i2c-sis630 +++ /dev/null @@ -1,63 +0,0 @@ -Kernel driver `i2c-sis630.o' - -Status: beta - -Supported adapters: - * Silicon Integrated Systems Corp (SiS) - 630 chipset (Datasheet: available at http://amalysh.bei.t-online.de/docs/SIS/) - 730 chipset - * Possible other SiS chipsets ? - -Author: Alexander Malysh - - -License: GPL - - -Module Parameters ------------------ - -force = [1|0] Forcibly enable the SIS630. DANGEROUS! - This can be interesting for chipsets not named - above to check if it works for you chipset, but DANGEROUS! -high_clock = [1|0] Forcibly set Host Master Clock to 56KHz (default,what your BIOS use). - DANGEROUS! This should be a bit faster, but freeze some systems (i.e. - my Laptop). - - -Description ------------ - -This SMBus only driver is known to work on motherboards with the above named -chipsets. - -If you see something like this: - -00:00.0 Host bridge: Silicon Integrated Systems [SiS] 630 Host (rev 31) -00:01.0 ISA bridge: Silicon Integrated Systems [SiS] 85C503/5513 - -or like this: - -00:00.0 Host bridge: Silicon Integrated Systems [SiS] 730 Host (rev 02) -00:01.0 ISA bridge: Silicon Integrated Systems [SiS] 85C503/5513 - -in your 'lspci' output , then this driver is for your chipset. - -Note: kernel versions later than 2.4.18 not tested. - -If anyone owns a board with those chips AND is willing to risk crashing & -burning an otherwise well-behaved kernel in the name of progress... please -contact me at or via the project's mailing list: see -http://www.lm-sensors.org/wiki/AuthorsAndContributors. Please send bug reports -and/or success stories as well. - - -Thank Yous ------------ -Philip Edelbrock -- testing SiS730 support -Mark M. Hoffman -- bug fixes - -To anyone else which I forgot here ;), thanks! - diff --git a/doc/busses/i2c-sis645 b/doc/busses/i2c-sis645 deleted file mode 100644 index 2bdcbfed..00000000 --- a/doc/busses/i2c-sis645 +++ /dev/null @@ -1,85 +0,0 @@ -Kernel driver `i2c-sis645.o' - -Status: Beta - -Supported adapters: - * Silicon Integrated Systems Corp (SiS) - Any combination of these host bridges: - 645, 645DX (aka 646), 648, 650, 651, 655, 735, 745, 746 - and these south bridges: - 961, 962, 963(L) - -Author: Mark M. Hoffman - -License: GPL - - -Module Parameters ------------------ - -(none) - - -Description ------------ - -This SMBus only driver is known to work on motherboards with the above named -chipset combinations. The driver was developed without benefit of a proper -datasheet from SiS. The SMBus registers are assumed compatible with those of -the SiS630, although they are located in a completely different place. Thanks -to Alexander Malysh for providing the SiS630 datasheet (and -driver). - -The command "lspci" as root should produce something like these lines: - -00:00.0 Host bridge: Silicon Integrated Systems [SiS]: Unknown device 0645 -00:02.0 ISA bridge: Silicon Integrated Systems [SiS] 85C503/5513 -00:02.1 SMBus: Silicon Integrated Systems [SiS]: Unknown device 0016 - -or perhaps this... - -00:00.0 Host bridge: Silicon Integrated Systems [SiS]: Unknown device 0645 (rev 02) -00:02.0 ISA bridge: Silicon Integrated Systems [SiS]: Unknown device 0961 -00:02.1 SMBus: Silicon Integrated Systems [SiS]: Unknown device 0016 - -(kernel versions later than 2.4.18 may fill in the "Unknown"s) - -If the SMBus line is missing, then the BIOS on the board has disabled the -device. This driver is capable of enabling it, as long as the kernel has -CONFIG_HOTPLUG enabled. In that case, the SMBus device will appear in "lspci" -after the driver is loaded. Note that you need to rebuild lm_sensors AFTER -running "make config" or equivalent on your kernel, otherwise the i2c-sis645 -driver will not build in this support. - -I suspect that this driver could be made to work for the following SiS chipsets -as well: 635, and 635T. -If anyone owns a board with those chips AND is willing to risk crashing & -burning an otherwise well-behaved kernel in the name of progress... please -contact me at or via the project's mailing list: -see http://www.lm-sensors.org/wiki/AuthorsAndContributors. Please send bug reports -and/or success stories as well. - - -TO DOs ------------ -* The driver does not support SMBus block reads/writes; I may add them if a -scenario is found where they're needed. - - -Thank Yous ------------ -Mark D. Studebaker - - design hints and bug fixes -Alexander Maylsh - - ditto, plus an important datasheet... almost the one I really wanted -Hans-Günter Lütke Uphues - - patch for SiS735 -Robert Zwerus - - testing for SiS645DX -Kianusch Sayah Karadji - - patch for SiS645DX/962 -Ken Healy - - patch for Sis655 - -To anyone else who has written w/ feedback, thanks! - diff --git a/doc/busses/i2c-tsunami b/doc/busses/i2c-tsunami deleted file mode 100644 index 7679ab9c..00000000 --- a/doc/busses/i2c-tsunami +++ /dev/null @@ -1,46 +0,0 @@ -Kernel driver `i2c-tsunami.o' - -Status: Stable - -Supported adapters: - * DEC Tsunami 21272/Typhoon 21274 based boards - -Author: Oleg I. Vdovikin - -Main contact: Oleg I. Vdovikin - - -Module Parameters ------------------ -(none) - - -Description ------------ -The Tsunami/Typhoon chipsets' "Cchip" supports I2C busses via MPD registers -and appropriate open drain pins. This bus is usually used to read -SPD SDRAM DIMMs, however there may be other devices on -the bus also. These chips are used with wide range of 21264A boards. - -This driver uses the i2c-algo-bit module which must be -modprobed and/or enabled in your kernel -(Character Devices -> I2C Support -> I2C Bit-Banging Interfaces). - - -Stability ---------- -Apparently stable. - -Supported Devices ------------------ -This driver was written and tested on the 'API UP2000(+) -boards'. As seems it should work with any Tsunami based system. - -Features --------- -I2C busses use the i2c-algo-bit driver for 'bit banging' and support -for specific transactions is provided by i2c-algo-bit. - -Issues ------- -Not known. diff --git a/doc/busses/i2c-via b/doc/busses/i2c-via deleted file mode 100644 index b484b509..00000000 --- a/doc/busses/i2c-via +++ /dev/null @@ -1,50 +0,0 @@ -Kernel driver `i2c-via.o' - -Status: Complete and well-tested - -Supported adapters: - * VIA Technologies, InC. VT82C586B - Datasheet: Publicly available at the VIA website - -Author: Kyösti Mälkki - - -Module Parameters ------------------ - -(none) - - -Description ------------ - -i2c-via is an i2c bus driver for motherboards with VIA chipset. - -The following VIA pci chipsets are supported: - - MVP3, VP3, VP2/97, VPX/97 - - others with South bridge VT82C586B - -Your /proc/pci or lspci listing must show this : - - Bridge: VIA Technologies, Inc. VT82C586B ACPI (rev 10) - -To install this driver, simply do - # modprobe i2c-via - -This driver uses the i2c-algo-bit module which must be -modprobed and/or enabled in your kernel -(Character Devices -> I2C Support -> I2C Bit-Banging Interfaces). - - Problems? - - Q: You have VT82C586B on the motherboard, but not in the listing. - - A: Go to your BIOS setup, section PCI devices or similar. - Turn USB support on, and try again. - - Q: No error messages, but still i2c doesn't seem to work. - - A: This can happen. This driver uses the pins VIA recommends in their - datasheets, but there are several ways the motherboard manufacturer - can actually wire the lines. - diff --git a/doc/busses/i2c-viapro b/doc/busses/i2c-viapro deleted file mode 100644 index 375d305d..00000000 --- a/doc/busses/i2c-viapro +++ /dev/null @@ -1,61 +0,0 @@ -Kernel driver `i2c-viapro.o' - -Status: Stable - -Supported adapters: - * VIA Technologies, Inc. VT82C596A/B - Datasheet: Sometimes available at the VIA website - - * VIA Technologies, Inc. VT82C686A/B - Datasheet: Sometimes available at the VIA website - - * VIA Technologies, Inc. VT8231, VT8233, VT8233A, VT8235, VT8237R/A, VT8251 - Datasheet: available on request and under NDA from VIA - - * VIA Technologies, Inc. CX700 - Datasheet: available on request and under NDA from VIA - -Authors: - Kyösti Mälkki - Mark D. Studebaker - Jean Delvare - - -Module Parameters ------------------ - -* force: int - Forcibly enable the SMBus controller. DANGEROUS! -* force_addr: int - Forcibly enable the SMBus at the given address. EXTREMELY DANGEROUS! - - -Description ------------ - -i2c-viapro is a true SMBus host driver for motherboards with one of the -supported VIA south bridges. - -Your /proc/pci or lspci -n listing must show one of these : - - device 1106:3050 (VT82C596A function 3) - device 1106:3051 (VT82C596B function 3) - device 1106:3057 (VT82C686 function 4) - device 1106:3074 (VT8233) - device 1106:3147 (VT8233A) - device 1106:8235 (VT8231 function 4) - device 1106:3177 (VT8235) - device 1106:3227 (VT8237R) - device 1106:3337 (VT8237A) - device 1106:3287 (VT8251) - device 1106:8324 (CX700) - -If none of these show up, you should look in the BIOS for settings like -enable ACPI / SMBus or even USB. - -Except for the oldest chips (VT82C596A/B, VT82C686A and most probably -VT8231), this driver supports I2C block transactions. Such transactions -are mainly useful to read from and write to EEPROMs. - -The CX700 additionally appears to support SMBus PEC, although this driver -doesn't implement it. diff --git a/doc/busses/i2c-virtual b/doc/busses/i2c-virtual deleted file mode 100644 index 45341505..00000000 --- a/doc/busses/i2c-virtual +++ /dev/null @@ -1,102 +0,0 @@ -Virtual i2c bus -Brian Kuschak - - -I2C devices must have a unique 7 bit address on the bus to which they -are attached. Many I2C chips have one or more input lines which can be -used to configure one or more of their address bits. This allows the -hardware designer to include multiple chips on a single bus by selecting -different addresses for each one. However, some chips have fixed addresses -which present a problem if more than one of them are required on a board. -Also, sometimes there are more devices than there are selectable addresses. - -A common solution is to break the i2c bus into disjoint segments, by using -a multiplexor or i2c bus switch. This electrically isolates the individual -bus segments. Then the devices with duplicate addresses are placed on -separate bus segments, to prevent address conflicts. - -This seems to be a very common approach in certain types of applications, -such as bladed chassis, where many identical 'blades' or cards are inserted -into a common backplane. The I2C bus on each blade is then located behind -a mux or i2c bus switch. This solution works great from the hardware -perspective, but presents some complexities for software. - -The 'virtual i2c adapter' driver is an attempt to provide a flexible software -abstraction to simiplify these issues, while minimizing the impact on -existing code and fitting nicely into the i2c driver framework. - - -What is a 'virtual i2c adapter' -=============================== - -Think of this adapter as a layer above the existing algorithm and adapter -drivers. The virtual i2c adapter is the handle by which you access a -specific multiplexed bus segment. Each disjoint bus segment becomes a new -virtual bus. The virtual adapter is associated with a 'real' adapter and a -set of multiplexor control variables. - -For example: you have an i2c-0 bus with one multiplexor or i2c bus switch, -and the mux has four outputs which can be electrically connected to the -i2c-0 bus. You would register four virtual i2c busses, one for each position -of the mux. As part of the registration, you provide callback functions to -select and deselect the mux as well as the selector values to be passed to -these functions. - - --------- <--------> i2c-1 virtual - | i2c mux | <--------> i2c-2 virtual - i2c-0 <-------> | | <--------> i2c-3 virtual - ibm_ocp | 0x74 | <--------> i2c-4 virtual - --------- - ^ - | - +--- (or externally controlled) - -The mux may be i2c-controlled, in which case the mux_addr is set to the -slave address (0x74) and the mux_val would be the port number to select (0-3). -Alternatively, the mux could be controlled by some fixed memory-mapped register -in which case only the mux_val would be needed. The callback functions -are hardware specific and written by the user. - -Once the virtual busses are registered, you may talk to any devices behind -the mux simply the using the i2c-1, i2c-2, i2c-3, etc. adapters instead of -the i2c-0 adapter. This makes the mux essentially transparent to the -i2c_client. - -The great advantage of course is that all the existing sensor drivers and -other i2c client drivers automatically work, and the mux becomes transparent -to them. - - -Additional capabilities -======================= - -This driver also supports multiple levels of muxing, by allowing the -user to register a virtual bus which has a different virtual bus as its -'real' adapter. In addition, each virtual bus may have different kinds of -multiplexors, with each bus having its own set of callback functions. -This allows you to easily support some very complex topologies. - -In addition to multiplexing, some systems require that you obtain hardware -access to the bus behind the mux before talking on it. (Again, bladed chassis -typically 'fence' other blades off the bus to prevent a crashed blade from -bringing down the whole backplane.) Before talking on this bus, you have to -arbitrate with the other blades to acquire exclusive access to the bus. This -requirement is met by the addition of two new function pointers to the -algorithm drivers, acquire_exclusive() and release_exclusive(). Traditional -adapters will not use these and they can safely be left NULL. If they are -non-null, the virtual bus driver will call the acquire_exclusive() function -before attempting any operations on that virtual bus. This function may block, -and this is done before acquiring the lock on the underlying 'real' bus to -allow transactions on the real bus to continue unimpeded while waiting for -arbitrartion. In addition the ownership is only held for as long as it takes -to complete the transfer. - - -Files -===== - -drivers/i2c/i2c-virtual.c: The 'algorithm' and 'adapter' driver -include/linux/i2c-virtual.h: Header file with the mux control structure - and callback prototypes. - - diff --git a/doc/busses/i2c-voodoo3 b/doc/busses/i2c-voodoo3 deleted file mode 100644 index bc1ca497..00000000 --- a/doc/busses/i2c-voodoo3 +++ /dev/null @@ -1,83 +0,0 @@ -Kernel driver `i2c-voodoo3.o' - -Status: 'Beta' and still under development and testing - -Supported adapters: - * 3dfx Voodoo3 based cards - * Voodoo Banshee based cards - -Author: Frodo Looijaard , Philip Edelbrock - , Ralph Metzler , - and Mark D. Studebaker - -Main contact: Philip Edelbrock - -The code is based upon Ralph's test code (he did the hard stuff ;') - - -Module Parameters ------------------ - -(none) - - -Description ------------ - -The 3dfx Voodoo3 chip contains two I2C interfaces (aka a I2C 'master' -or 'host'). - -The first interface is used for DDC (Data Display Channel) -which is a serial channel through the VGA monitor connector -to a DDC-compliant monitor. This interface is defined by the -Video Electronics Standards Association (VESA). The standards -are available for purchase at http://www.vesa.org . - -The second interface is a general-purpose I2C bus. -The intent by 3dfx was to allow manufacturers to add extra -chips to the video card such as a TV-out chip such as the BT869 or possibly -even I2C based temperature sensors like the ADM1021 or LM75. - -The 'feature' set of this driver is based on the i2c-piix4 (SMBus) -features. I.e., SMBus byte reads and writes, as well as detected faults in -transmission. Quick reads/writes, block transactions, word transactions, -are yet unwritten but are probably not too hard to add. - -This driver uses the i2c-algo-bit module which must be -modprobed and/or enabled in your kernel -(Character Devices -> I2C Support -> I2C Bit-Banging Interfaces). - -Stability ---------- -Seems to be stable on the test machine, but needs more testing on other -machines. - -Simultaneous accesses of the DDC and I2C busses may cause errors. - - -Supported Devices ------------------ -Specifically, this driver was written and tested on the '3dfx Voodoo3 AGP -3000' which has a tv-out feature (s-video or composite). According to the -docs and discussions, this code should work for any Voodoo3 based cards as -well as Voodoo Banshee based cards. The DDC interface has been tested -on a Voodoo Banshee card. - -Features --------- -This driver controls the I2C controller of the Voodoo3 chip. 'byte read' -transactions and 'data_byte write' transactions are supported, but all else -is not (but is probably easy to add if the need arises). - -Issues ------- -Probably many, but it seems to work OK on my system. :') - - -External Device Connection --------------------------- -The digital video input jumpers give availability to the I2C bus. -Specifically, pins 13 and 25 (bottom row middle, and bottom right-end) are -the I2C clock and I2C data lines, respectively. +5V and GND are probably -also easily available making the addition of extra I2C/SMBus devices easy -to implement. diff --git a/doc/modules b/doc/modules index 395743d2..fd685dd1 100644 --- a/doc/modules +++ b/doc/modules @@ -1,15 +1,14 @@ Installing Modules ================== -'make install' will install the kernel modules modules in the -subdirectories /lib/modules/$version/kernel/drivers/i2c and -/lib/modules/$version/kernel/drivers/sensors. This puts the modules -in the same location as a kernel 'make modules_install' does so -that there will be no duplicate modules. +'make install' will install the kernel modules in the +subdirectory /lib/modules/$version/kernel/drivers/i2c/chips. +This puts the modules in the same location as a kernel +'make modules_install' does so that there will be no duplicate modules. If 'make install' fails, particularly on Mandrake kernels, see FAQ #3.8 (fix MODPREF in the Makefile) and #3.9. For details on options that apply to most modules, see doc/chips/MODPARMS. For details on options specific to particular -modules, see the documentation in doc/chips/ and doc/busses/. +modules, see the documentation in doc/chips/. diff --git a/kernel/busses/Module.mk b/kernel/busses/Module.mk deleted file mode 100644 index 4b6fc1ff..00000000 --- a/kernel/busses/Module.mk +++ /dev/null @@ -1,127 +0,0 @@ -# Module.mk - Makefile for a Linux module for reading sensor data. -# Copyright (c) 1998, 1999 Frodo Looijaard -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -# Note that MODULE_DIR (the directory in which this file resides) is a -# 'simply expanded variable'. That means that its value is substituted -# verbatim in the rules, until it is redefined. -MODULE_DIR := kernel/busses -KERNELBUSSESDIR := $(MODULE_DIR) - -# Regrettably, even 'simply expanded variables' will not put their currently -# defined value verbatim into the command-list of rules... -KERNELBUSSESTARGETS := -ifeq ($(shell if grep -q '^CONFIG_IPMI_HANDLER=' $(LINUX)/.config; then echo 1; fi),1) -#doesn't work yet -#KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-ipmb.o -KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-ipmi.o -endif - -ifneq ($(shell if grep -q '^CONFIG_I2C_ALI1535=y' $(LINUX)/.config; then echo 1; fi),1) -KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-ali1535.o -endif -ifneq ($(shell if grep -q '^CONFIG_I2C_ALI15X3=y' $(LINUX)/.config; then echo 1; fi),1) -KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-ali15x3.o -endif -ifneq ($(shell if grep -q '^CONFIG_I2C_ALI1563=y' $(LINUX)/.config; then echo 1; fi),1) -KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-ali1563.o -endif -ifneq ($(shell if grep -q '^CONFIG_I2C_AMD756=y' $(LINUX)/.config; then echo 1; fi),1) -KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-amd756.o -endif -ifneq ($(shell if grep -q '^CONFIG_I2C_AMD756_S4882=y' $(LINUX)/.config; then echo 1; fi),1) -KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-amd756-s4882.o -endif -ifneq ($(shell if grep -q '^CONFIG_I2C_AMD8111=y' $(LINUX)/.config; then echo 1; fi),1) -KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-amd8111.o -endif -ifneq ($(shell if grep -q '^CONFIG_I2C_HYDRA=y' $(LINUX)/.config; then echo 1; fi),1) -KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-hydra.o -endif -ifneq ($(shell if grep -q '^CONFIG_I2C_I801=y' $(LINUX)/.config; then echo 1; fi),1) -KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-i801.o -endif -ifneq ($(shell if grep -q '^CONFIG_I2C_I810=y' $(LINUX)/.config; then echo 1; fi),1) -KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-i810.o -endif -ifneq ($(shell if grep -q '^CONFIG_I2C_ISA=y' $(LINUX)/.config; then echo 1; fi),1) -KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-isa.o -endif -ifneq ($(shell if grep -q '^CONFIG_I2C_NFORCE2=y' $(LINUX)/.config; then echo 1; fi),1) -KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-nforce2.o -endif -ifneq ($(shell if grep -q '^CONFIG_I2C_SIS5595=y' $(LINUX)/.config; then echo 1; fi),1) -KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-sis5595.o -endif -ifneq ($(shell if grep -q '^CONFIG_I2C_SIS630=y' $(LINUX)/.config; then echo 1; fi),1) -KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-sis630.o -endif -ifneq ($(shell if grep -q '^CONFIG_I2C_SIS645=y' $(LINUX)/.config; then echo 1; fi),1) -KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-sis645.o -endif -# don't compile dmi_scan unless x86 because it needs isa access -ifneq ($(shell if grep -q '^CONFIG_I2C_PIIX4=y' $(LINUX)/.config; then echo 1; fi),1) -KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-piix4.o -ifeq ($(shell if grep -q '^CONFIG_X86=y' $(LINUX)/.config; then echo 1; fi),1) -KERNELBUSSESTARGETS += $(MODULE_DIR)/dmi_scan.o -endif -endif -ifneq ($(shell if grep -q '^CONFIG_I2C_SAVAGE4=y' $(LINUX)/.config; then echo 1; fi),1) -KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-savage4.o -endif -# don't compile unless alpha because of kernel include-file dependencies -ifeq ($(MACHINE),alpha) -ifneq ($(shell if grep -q '^CONFIG_I2C_TSUNAMI=y' $(LINUX)/.config; then echo 1; fi),1) -KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-tsunami.o -endif -endif -ifneq ($(shell if grep -q '^CONFIG_I2C_VIA=y' $(LINUX)/.config; then echo 1; fi),1) -KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-via.o -endif -ifneq ($(shell if grep -q '^CONFIG_I2C_VIAPRO=y' $(LINUX)/.config; then echo 1; fi),1) -KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-viapro.o -endif -ifneq ($(shell if grep -q '^CONFIG_I2C_VOODOO3=y' $(LINUX)/.config; then echo 1; fi),1) -KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-voodoo3.o -endif - -# Include all dependency files -INCLUDEFILES += $(KERNELBUSSESTARGETS:.o=.d) - -all-kernel-busses: $(KERNELBUSSESTARGETS) -all :: all-kernel-busses - -# -# If $MODPREF/kernel exists, we presume the new (2.4.0) /lib/modules/x.y.z directory -# layout, so we install in kernel/drivers/i2c/busses and remove old versions in misc/ -# and kernel/drivers/i2c/ . Otherwise we install in misc/ as before. -# -install-kernel-busses: all-kernel-busses - if [ -n "$(KERNELBUSSESTARGETS)" ] ; then \ - $(MKDIR) $(DESTDIR)$(MODPREF)/kernel/drivers/i2c/busses ; \ - $(INSTALL) -m 644 $(KERNELBUSSESTARGETS) $(DESTDIR)$(MODPREF)/kernel/drivers/i2c/busses ; \ - for i in $(KERNELBUSSESTARGETS) ; do \ - $(RM) $(DESTDIR)$(MODPREF)/misc/`basename $$i` $(DESTDIR)$(MODPREF)/kernel/drivers/i2c/`basename $$i` \ - $(DESTDIR)$(MODPREF)/kernel/drivers/i2c/`basename $$i`.gz $(DESTDIR)$(MODPREF)/kernel/drivers/i2c/busses/`basename $$i`.gz ; \ - done ; \ - $(RMDIR) $(DESTDIR)$(MODPREF)/misc 2> /dev/null || true ; \ - fi - -install :: install-kernel-busses - -clean-kernel-busses: - $(RM) $(KERNELBUSSESDIR)/*.o $(KERNELBUSSESDIR)/*.d -clean :: clean-kernel-busses diff --git a/kernel/busses/dmi_scan.c b/kernel/busses/dmi_scan.c deleted file mode 100644 index 7d2748c7..00000000 --- a/kernel/busses/dmi_scan.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - Taken from arch/i386/kernel/dmi_scan.c. - Changes dmi_ident to be non-static so we can access. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "version.h" - -int is_unsafe_smbus; -EXPORT_SYMBOL(is_unsafe_smbus); - -struct dmi_header -{ - u8 type; - u8 length; - u16 handle; -}; - -enum -{ - DMI_BIOS_VENDOR, - DMI_BIOS_VERSION, - DMI_BIOS_DATE, - DMI_SYS_VENDOR, - DMI_PRODUCT_NAME, - DMI_PRODUCT_VERSION, - DMI_BOARD_VENDOR, - DMI_BOARD_NAME, - DMI_BOARD_VERSION, - DMI_STRING_MAX -}; - -#define dmi_printk(x) -//#define dmi_printk(x) printk x - -static char * __init dmi_string(struct dmi_header *dm, u8 s) -{ - u8 *bp=(u8 *)dm; - bp+=dm->length; - if(!s) - return ""; - s--; - while(s>0 && *bp) - { - bp+=strlen(bp); - bp++; - s--; - } - return bp; -} - -/* - * We have to be cautious here. We have seen BIOSes with DMI pointers - * pointing to completely the wrong place for example - */ - -static int __init dmi_table(u32 base, int len, int num, void (*decode)(struct dmi_header *)) -{ - u8 *buf; - struct dmi_header *dm; - u8 *data; - int i=0; - - buf = ioremap(base, len); - if(buf==NULL) - return -1; - - data = buf; - - /* - * Stop when we see all the items the table claimed to have - * OR we run off the end of the table (also happens) - */ - - while(ilength; - while(data-buf>4, buf[14]&0x0F)); - else - dmi_printk((KERN_INFO "DMI present.\n")); - dmi_printk((KERN_INFO "%d structures occupying %d bytes.\n", - num, len)); - dmi_printk((KERN_INFO "DMI table at 0x%08X.\n", - base)); - if(dmi_table(base,len, num, decode)==0) - return 0; - } - fp+=16; - } - return -1; -} - - -char *dmi_ident[DMI_STRING_MAX]; - -/* - * Save a DMI string - */ - -static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string) -{ - char *d = (char*)dm; - char *p = dmi_string(dm, d[string]); - if(p==NULL || *p == 0) - return; - if (dmi_ident[slot]) - return; - dmi_ident[slot] = kmalloc(strlen(p)+1, GFP_KERNEL); - if(dmi_ident[slot]) - strcpy(dmi_ident[slot], p); - else - printk(KERN_ERR "dmi_save_ident: out of memory.\n"); -} - -/* - * Process a DMI table entry. Right now all we care about are the BIOS - * and machine entries. For 2.5 we should pull the smbus controller info - * out of here. - */ - -static void __init dmi_decode(struct dmi_header *dm) -{ - switch(dm->type) - { - case 0: - dmi_printk(("BIOS Vendor: %s\n", - dmi_string(dm, data[4]))); - dmi_save_ident(dm, DMI_BIOS_VENDOR, 4); - dmi_printk(("BIOS Version: %s\n", - dmi_string(dm, data[5]))); - dmi_save_ident(dm, DMI_BIOS_VERSION, 5); - dmi_printk(("BIOS Release: %s\n", - dmi_string(dm, data[8]))); - dmi_save_ident(dm, DMI_BIOS_DATE, 8); - break; - case 1: - dmi_printk(("System Vendor: %s\n", - dmi_string(dm, data[4]))); - dmi_save_ident(dm, DMI_SYS_VENDOR, 4); - dmi_printk(("Product Name: %s\n", - dmi_string(dm, data[5]))); - dmi_save_ident(dm, DMI_PRODUCT_NAME, 5); - dmi_printk(("Version: %s\n", - dmi_string(dm, data[6]))); - dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6); - dmi_printk(("Serial Number: %s\n", - dmi_string(dm, data[7]))); - break; - case 2: - dmi_printk(("Board Vendor: %s\n", - dmi_string(dm, data[4]))); - dmi_save_ident(dm, DMI_BOARD_VENDOR, 4); - dmi_printk(("Board Name: %s\n", - dmi_string(dm, data[5]))); - dmi_save_ident(dm, DMI_BOARD_NAME, 5); - dmi_printk(("Board Version: %s\n", - dmi_string(dm, data[6]))); - dmi_save_ident(dm, DMI_BOARD_VERSION, 6); - break; - } -} - -int __init dmi_scan_mach(void) -{ - int err; - printk("dmi_scan.o version %s (%s)\n", LM_VERSION, LM_DATE); - err = dmi_iterate(dmi_decode); - if(err) - printk("dmi_scan.o: SM BIOS not found\n"); - else - printk("dmi_scan.o: SM BIOS found\n"); - - if(dmi_ident[DMI_SYS_VENDOR] != NULL - && strncmp(dmi_ident[DMI_SYS_VENDOR], "IBM", 3) == 0) - is_unsafe_smbus = 1; - return 0; -} - -MODULE_DESCRIPTION("SM BIOS DMI Scanner"); -MODULE_LICENSE("GPL"); - -module_init(dmi_scan_mach); diff --git a/kernel/busses/i2c-ali1535.c b/kernel/busses/i2c-ali1535.c deleted file mode 100644 index ca3d15b3..00000000 --- a/kernel/busses/i2c-ali1535.c +++ /dev/null @@ -1,529 +0,0 @@ -/* - i2c-ali1535.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 2000 Frodo Looijaard , - Philip Edelbrock , - Mark D. Studebaker , - Dan Eaton and - Stephen Rousset - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - This is the driver for the SMB Host controller on - Acer Labs Inc. (ALI) M1535 South Bridge. - - The M1535 is a South bridge for portable systems. - It is very similar to the M15x3 South bridges also produced - by Acer Labs Inc. Some of the registers within the part - have moved and some have been redefined slightly. Additionally, - the sequencing of the SMBus transactions has been modified - to be more consistent with the sequencing recommended by - the manufacturer and observed through testing. These - changes are reflected in this driver and can be identified - by comparing this driver to the i2c-ali15x3 driver. - For an overview of these chips see http://www.acerlabs.com - - The SMB controller is part of the 7101 device, which is an - ACPI-compliant Power Management Unit (PMU). - - The whole 7101 device has to be enabled for the SMB to work. - You can't just enable the SMB alone. - The SMB and the ACPI have separate I/O spaces. - We make sure that the SMB is enabled. We leave the ACPI alone. - - This driver controls the SMB Host only. - - This driver does not use interrupts. -*/ - - -/* Note: we assume there can only be one ALI1535, with one SMBus interface */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "version.h" -#include "sensors_compat.h" - - -/* ALI1535 SMBus address offsets */ -#define SMBHSTSTS (0 + ali1535_smba) -#define SMBHSTTYP (1 + ali1535_smba) -#define SMBHSTPORT (2 + ali1535_smba) -#define SMBHSTCMD (7 + ali1535_smba) -#define SMBHSTADD (3 + ali1535_smba) -#define SMBHSTDAT0 (4 + ali1535_smba) -#define SMBHSTDAT1 (5 + ali1535_smba) -#define SMBBLKDAT (6 + ali1535_smba) - -/* PCI Address Constants */ -#define SMBCOM 0x004 -#define SMBREV 0x008 -#define SMBCFG 0x0D1 -#define SMBBA 0x0E2 -#define SMBHSTCFG 0x0F0 -#define SMBCLK 0x0F2 - -/* Other settings */ -#define MAX_TIMEOUT 500 /* times 1/100 sec */ -#define ALI1535_SMB_IOSIZE 32 - -/* -*/ -#define ALI1535_SMB_DEFAULTBASE 0x8040 - -/* ALI1535 address lock bits */ -#define ALI1535_LOCK 0x06 < dwe > - -/* ALI1535 command constants */ -#define ALI1535_QUICK 0x00 -#define ALI1535_BYTE 0x10 -#define ALI1535_BYTE_DATA 0x20 -#define ALI1535_WORD_DATA 0x30 -#define ALI1535_BLOCK_DATA 0x40 -#define ALI1535_I2C_READ 0x60 - -#define ALI1535_DEV10B_EN 0x80 /* Enable 10-bit addressing in */ - /* I2C read */ -#define ALI1535_T_OUT 0x08 /* Time-out Command (write) */ -#define ALI1535_A_HIGH_BIT9 0x08 /* Bit 9 of 10-bit address in */ - /* Alert-Response-Address */ - /* (read) */ -#define ALI1535_KILL 0x04 /* Kill Command (write) */ -#define ALI1535_A_HIGH_BIT8 0x04 /* Bit 8 of 10-bit address in */ - /* Alert-Response-Address */ - /* (read) */ - -#define ALI1535_D_HI_MASK 0x03 /* Mask for isolating bits 9-8 */ - /* of 10-bit address in I2C */ - /* Read Command */ - -/* ALI1535 status register bits */ -#define ALI1535_STS_IDLE 0x04 -#define ALI1535_STS_BUSY 0x08 /* host busy */ -#define ALI1535_STS_DONE 0x10 /* transaction complete */ -#define ALI1535_STS_DEV 0x20 /* device error */ -#define ALI1535_STS_BUSERR 0x40 /* bus error */ -#define ALI1535_STS_FAIL 0x80 /* failed bus transaction */ -#define ALI1535_STS_ERR 0xE0 /* all the bad error bits */ - -#define ALI1535_BLOCK_CLR 0x04 /* reset block data index */ - -/* ALI1535 device address register bits */ -#define ALI1535_RD_ADDR 0x01 /* Read/Write Bit in Device */ - /* Address field */ - /* -> Write = 0 */ - /* -> Read = 1 */ -#define ALI1535_SMBIO_EN 0x04 /* SMB I/O Space enable */ - - -static struct pci_driver ali1535_driver; -static unsigned short ali1535_smba = 0; - - -/* Detect whether a ALI1535 can be found, and initialize it, where necessary. - Note the differences between kernels with the old PCI BIOS interface and - newer kernels with the real PCI interface. In compat.h some things are - defined to make the transition easier. */ -int ali1535_setup(struct pci_dev *ALI1535_dev) -{ - int error_return = 0; - unsigned char temp; - -/* Check the following things: - - SMB I/O address is initialized - - Device is enabled - - We can use the addresses -*/ - -/* Determine the address of the SMBus area */ - pci_read_config_word(ALI1535_dev, SMBBA, &ali1535_smba); - ali1535_smba &= (0xffff & ~(ALI1535_SMB_IOSIZE - 1)); - if (ali1535_smba == 0) { - printk - ("i2c-ali1535.o: ALI1535_smb region uninitialized - upgrade BIOS?\n"); - error_return = -ENODEV; - } - - if (error_return == -ENODEV) - goto END; - - if (check_region(ali1535_smba, ALI1535_SMB_IOSIZE)) { - printk - ("i2c-ali1535.o: ALI1535_smb region 0x%x already in use!\n", - ali1535_smba); - error_return = -ENODEV; - } - - if (error_return == -ENODEV) - goto END; - - /* check if whole device is enabled */ - pci_read_config_byte(ALI1535_dev, SMBCFG, &temp); - if ((temp & ALI1535_SMBIO_EN) == 0) { - printk - ("i2c-ali1535.o: SMB device not enabled - upgrade BIOS?\n"); - error_return = -ENODEV; - goto END; - } - -/* Is SMB Host controller enabled? */ - pci_read_config_byte(ALI1535_dev, SMBHSTCFG, &temp); - if ((temp & 1) == 0) { - printk - ("i2c-ali1535.o: SMBus controller not enabled - upgrade BIOS?\n"); - error_return = -ENODEV; - goto END; - } - -/* set SMB clock to 74KHz as recommended in data sheet */ - pci_write_config_byte(ALI1535_dev, SMBCLK, 0x20); - - /* Everything is happy, let's grab the memory and set things up. */ - request_region(ali1535_smba, ALI1535_SMB_IOSIZE, ali1535_driver.name); - -#ifdef DEBUG -/* - The interrupt routing for SMB is set up in register 0x77 in the - 1533 ISA Bridge device, NOT in the 7101 device. - Don't bother with finding the 1533 device and reading the register. - if ((....... & 0x0F) == 1) - printk("i2c-ali1535.o: ALI1535 using Interrupt 9 for SMBus.\n"); -*/ - pci_read_config_byte(ALI1535_dev, SMBREV, &temp); - printk("i2c-ali1535.o: SMBREV = 0x%X\n", temp); - printk("i2c-ali1535.o: ALI1535_smba = 0x%X\n", ali1535_smba); -#endif /* DEBUG */ - - END: - return error_return; -} - - -#define MAX_TIMEOUT_HEROS 100 -#define MAX_TIMEOUT_BLOCK_HEROS 500 -#define MAX_TRY_HEROS 3 - -/* believe it or not this is the delay technique recommended by ALI */ -static void ali1535_delay_loop(void) -{ - int i; - - for(i=0;i<30;i++) - outb_p(0,0xEB); -} - -static int ali1535_wait_for_status(int count,int status) -{ - int i; - int dat; - - for (i = 0; i < count; i++) { - ali1535_delay_loop(); - dat = inb_p(SMBHSTSTS); - if (dat == status) - break; - } - - return i == count ? 1 : 0; -} - -/* Return -1 on error. */ -s32 ali1535_access(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, u8 command, - int size, union i2c_smbus_data * data) -{ - int i, len; - s32 result = 0; - int timeout = 0; - int oldsize = size; - -repeat: - if(timeout++ > MAX_TRY_HEROS) { - result = -1; - goto EXIT; - } - - /* clear status */ - outb_p(0xFF, SMBHSTSTS); - - if (ali1535_wait_for_status(MAX_TIMEOUT_HEROS,ALI1535_STS_IDLE)) - goto repeat; - - outb_p(ALI1535_KILL,SMBHSTTYP); - - if (ali1535_wait_for_status(MAX_TIMEOUT_HEROS,ALI1535_STS_FAIL)) - goto repeat; - - /* clear status */ - outb_p(0xFF, SMBHSTSTS); - - if (ali1535_wait_for_status(MAX_TIMEOUT_HEROS,ALI1535_STS_IDLE)) - goto repeat; - - switch (size) { - case I2C_SMBUS_QUICK: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD); - ali1535_delay_loop(); - size = ALI1535_QUICK; - outb_p(size, SMBHSTTYP); /* output command */ - ali1535_delay_loop(); - break; - case I2C_SMBUS_BYTE: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD); - ali1535_delay_loop(); - size = ALI1535_BYTE; - outb_p(size, SMBHSTTYP); /* output command */ - ali1535_delay_loop(); - if (read_write == I2C_SMBUS_WRITE) { - outb_p(command, SMBHSTCMD); - ali1535_delay_loop(); - } - break; - case I2C_SMBUS_BYTE_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD); - ali1535_delay_loop(); - size = ALI1535_BYTE_DATA; - outb_p(size, SMBHSTTYP); /* output command */ - ali1535_delay_loop(); - outb_p(command, SMBHSTCMD); - ali1535_delay_loop(); - if (read_write == I2C_SMBUS_WRITE) { - outb_p(data->byte, SMBHSTDAT0); - ali1535_delay_loop(); - } - break; - case I2C_SMBUS_WORD_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD); - ali1535_delay_loop(); - size = ALI1535_WORD_DATA; - outb_p(size, SMBHSTTYP); /* output command */ - outb_p(command, SMBHSTCMD); - ali1535_delay_loop(); - if (read_write == I2C_SMBUS_WRITE) { - outb_p(data->word & 0xff, SMBHSTDAT0); - ali1535_delay_loop(); - outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); - ali1535_delay_loop(); - } - break; - case I2C_SMBUS_BLOCK_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD); - ali1535_delay_loop(); - size = ALI1535_BLOCK_DATA; - outb_p(size, SMBHSTTYP); /* output command */ - outb_p(command, SMBHSTCMD); - ali1535_delay_loop(); - if (read_write == I2C_SMBUS_WRITE) { - len = data->block[0]; - if (len < 0) { - len = 0; - data->block[0] = len; - } - if (len > 32) { - len = 32; - data->block[0] = len; - } - outb_p(len, SMBHSTDAT0); - ali1535_delay_loop(); - { - int val; - - val = inb_p(SMBHSTTYP) | ALI1535_BLOCK_CLR; - ali1535_delay_loop(); - outb_p(val, SMBHSTTYP); /* Reset SMBBLKDAT */ - ali1535_delay_loop(); - } - for (i = 1; i <= len; i++) { - outb_p(data->block[i], SMBBLKDAT); - ali1535_delay_loop(); - } - } - break; - default: - printk - (KERN_WARNING "i2c-ali1535.o: Unsupported transaction %d\n", size); - result = -1; - goto EXIT; - } - - /* start the transaction */ - outb_p(0xFF, SMBHSTPORT); - ali1535_delay_loop(); - - if (ali1535_wait_for_status(size == ALI1535_BLOCK_DATA ? - MAX_TIMEOUT_BLOCK_HEROS : - MAX_TIMEOUT_HEROS , - ALI1535_STS_IDLE | ALI1535_STS_DONE)) { - size = oldsize; - goto repeat; - } - - /* clear status */ - outb_p(0xFF, SMBHSTSTS); - ali1535_delay_loop(); - - if(inb_p(SMBHSTSTS) != ALI1535_STS_IDLE) { - size = oldsize; - goto repeat; - } - - if ((read_write == I2C_SMBUS_WRITE) || (size == ALI1535_QUICK)) { - result = 0; - goto EXIT; - } - - switch (size) { - case ALI1535_BYTE: /* Result put in SMBHSTDAT0 */ - data->byte = inb_p(SMBHSTDAT0); - ali1535_delay_loop(); - break; - case ALI1535_BYTE_DATA: - data->byte = inb_p(SMBHSTDAT0); - ali1535_delay_loop(); - break; - case ALI1535_WORD_DATA: - data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); - ali1535_delay_loop(); - break; - case ALI1535_BLOCK_DATA: - len = inb_p(SMBHSTDAT0); - ali1535_delay_loop(); - if (len > 32) - len = 32; - data->block[0] = len; - { - int val; - - val = inb_p(SMBHSTTYP) | ALI1535_BLOCK_CLR; - ali1535_delay_loop(); - outb_p(val, SMBHSTTYP); /* Reset SMBBLKDAT */ - ali1535_delay_loop(); - } - for (i = 1; i <= data->block[0]; i++) { - data->block[i] = inb_p(SMBBLKDAT); - ali1535_delay_loop(); -#ifdef DEBUG - printk - ("i2c-ali1535.o: Blk: len=%d, i=%d, data=%02x\n", - len, i, data->block[i]); -#endif /* DEBUG */ - } - break; - } -EXIT: - return result; -} - -static void ali1535_inc(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -static void ali1535_dec(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - -u32 ali1535_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA; -} - -static struct i2c_algorithm smbus_algorithm = { - .name = "Non-i2c SMBus adapter", - .id = I2C_ALGO_SMBUS, - .smbus_xfer = ali1535_access, - .functionality = ali1535_func, -}; - -static struct i2c_adapter ali1535_adapter = { - .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_ALI1535, - .algo = &smbus_algorithm, - .inc_use = ali1535_inc, - .dec_use = ali1535_dec, -}; - - -static struct pci_device_id ali1535_ids[] __devinitdata = { - { - .vendor = PCI_VENDOR_ID_AL, - .device = PCI_DEVICE_ID_AL_M7101, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { 0, } -}; - -static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - if (ali1535_setup(dev)) { - printk - ("i2c-ali1535.o: ALI1535 not detected, module not inserted.\n"); - return -ENODEV; - } - - sprintf(ali1535_adapter.name, "SMBus ALI1535 adapter at %04x", - ali1535_smba); - return i2c_add_adapter(&ali1535_adapter); -} - -static void __devexit ali1535_remove(struct pci_dev *dev) -{ - i2c_del_adapter(&ali1535_adapter); - release_region(ali1535_smba, ALI1535_SMB_IOSIZE); -} - - -static struct pci_driver ali1535_driver = { - .name = "ali1535 smbus", - .id_table = ali1535_ids, - .probe = ali1535_probe, - .remove = __devexit_p(ali1535_remove), -}; - -static int __init i2c_ali1535_init(void) -{ - printk("i2c-ali1535.o version %s (%s)\n", LM_VERSION, LM_DATE); - return pci_module_init(&ali1535_driver); -} - -static void __exit i2c_ali1535_exit(void) -{ - pci_unregister_driver(&ali1535_driver); -} - -MODULE_AUTHOR - ("Frodo Looijaard , Philip Edelbrock , " - "Mark D. Studebaker and Dan Eaton "); -MODULE_DESCRIPTION("ALI1535 SMBus driver"); -MODULE_LICENSE("GPL"); - -module_init(i2c_ali1535_init); -module_exit(i2c_ali1535_exit); diff --git a/kernel/busses/i2c-ali1563.c b/kernel/busses/i2c-ali1563.c deleted file mode 100644 index 87cc2d2c..00000000 --- a/kernel/busses/i2c-ali1563.c +++ /dev/null @@ -1,464 +0,0 @@ -/** - * i2c-ali1563.c - i2c driver for the ALi 1563 Southbridge - * - * Copyright (C) 2004, 2005 Patrick Mochel, Chunhao Huang - * - * The 1563 southbridge is deceptively similar to the 1533, with a - * few notable exceptions. One of those happens to be the fact they - * upgraded the i2c core to be 2.0 compliant, and happens to be almost - * identical to the i2c controller found in the Intel 801 south - * bridges. - * - * This driver is based on a mix of the 15x3, 1535, and i801 drivers, - * with a little help from the ALi 1563 spec. - * - * Chunhao Huang / Winbond - * Backport to linux-2.4 from linux-2.6 on Mar.2005 - * - * This file is released under the GPLv2 - */ - -#include -#include -#include -#include -#include -#include "version.h" -#include "sensors_compat.h" - -#ifndef PCI_DEVICE_ID_AL_M1563 -#define PCI_DEVICE_ID_AL_M1563 0x1563 -#endif - -#define ALI1563_MAX_TIMEOUT 500 -#define ALI1563_SMBBA 0x80 -#define ALI1563_SMB_IOEN 1 -#define ALI1563_SMB_HOSTEN 2 -#define ALI1563_SMB_IOSIZE 16 - -#define SMB_HST_STS (ali1563_smba + 0) -#define SMB_HST_CNTL1 (ali1563_smba + 1) -#define SMB_HST_CNTL2 (ali1563_smba + 2) -#define SMB_HST_CMD (ali1563_smba + 3) -#define SMB_HST_ADD (ali1563_smba + 4) -#define SMB_HST_DAT0 (ali1563_smba + 5) -#define SMB_HST_DAT1 (ali1563_smba + 6) -#define SMB_BLK_DAT (ali1563_smba + 7) - -#define HST_STS_BUSY 0x01 -#define HST_STS_INTR 0x02 -#define HST_STS_DEVERR 0x04 -#define HST_STS_BUSERR 0x08 -#define HST_STS_FAIL 0x10 -#define HST_STS_DONE 0x80 -#define HST_STS_BAD 0x1c - - -#define HST_CNTL1_TIMEOUT 0x80 -#define HST_CNTL1_LAST 0x40 - -#define HST_CNTL2_KILL 0x04 -#define HST_CNTL2_START 0x40 -#define HST_CNTL2_QUICK 0x00 -#define HST_CNTL2_BYTE 0x01 -#define HST_CNTL2_BYTE_DATA 0x02 -#define HST_CNTL2_WORD_DATA 0x03 -#define HST_CNTL2_BLOCK 0x05 -#define HST_CNTL2_SIZEMASK 0x38 - -static struct pci_driver ali1563_pci_driver; -static unsigned short ali1563_smba; - -static int ali1563_transaction(struct i2c_adapter * a) -{ - u32 data; - int timeout; - - printk(KERN_DEBUG "ali1563: Transaction (pre): STS=%02x, CNTL1=%02x, " - "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", - inb_p(SMB_HST_STS), inb_p(SMB_HST_CNTL1), inb_p(SMB_HST_CNTL2), - inb_p(SMB_HST_CMD), inb_p(SMB_HST_ADD), inb_p(SMB_HST_DAT0), - inb_p(SMB_HST_DAT1)); - - data = inb_p(SMB_HST_STS); - if (data & HST_STS_BAD) { - printk(KERN_WARNING "ali1563: Trying to reset busy device\n"); - outb_p(data | HST_STS_BAD,SMB_HST_STS); - data = inb_p(SMB_HST_STS); - if (data & HST_STS_BAD){ - return -EBUSY; - } - } - outb_p(inb_p(SMB_HST_CNTL2) | HST_CNTL2_START, SMB_HST_CNTL2); - - timeout = ALI1563_MAX_TIMEOUT; - do - i2c_delay(1); - while (((data = inb_p(SMB_HST_STS)) & HST_STS_BUSY) && --timeout); - - printk(KERN_DEBUG "ali1563: Transaction (post): STS=%02x, CNTL1=%02x, " - "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", - inb_p(SMB_HST_STS), inb_p(SMB_HST_CNTL1), inb_p(SMB_HST_CNTL2), - inb_p(SMB_HST_CMD), inb_p(SMB_HST_ADD), inb_p(SMB_HST_DAT0), - inb_p(SMB_HST_DAT1)); - - if (timeout && !(data & HST_STS_BAD)) { - return 0; - } - - /* modified by Rudolf */ - if (!timeout) { - printk(KERN_ERR "ali1563: Timeout - Trying to KILL transaction!\n"); - /* Issue 'kill' to host controller */ - outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2); - data = inb_p(SMB_HST_STS); - } - - /* device error - probably missing ACK */ - if (data & HST_STS_DEVERR) { - printk(KERN_DEBUG "ali1563: Device error!\n"); - } - - /* bus collision */ - if (data & HST_STS_BUSERR) { - printk(KERN_ERR "ali1563: Bus collision!\n"); - /* Issue timeout, hoping it helps */ - outb_p(HST_CNTL1_TIMEOUT,SMB_HST_CNTL1); - } - - if (data & HST_STS_FAIL) { - printk(KERN_ERR "ali1563: Cleaning fail after KILL!\n"); - outb_p(0x0,SMB_HST_CNTL2); - } - - return -1; -} - -static int ali1563_block_start(struct i2c_adapter * a) -{ - u32 data; - int timeout; - - printk(KERN_DEBUG "ali1563: Block (pre): STS=%02x, CNTL1=%02x, " - "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", - inb_p(SMB_HST_STS), inb_p(SMB_HST_CNTL1), inb_p(SMB_HST_CNTL2), - inb_p(SMB_HST_CMD), inb_p(SMB_HST_ADD), inb_p(SMB_HST_DAT0), - inb_p(SMB_HST_DAT1)); - - data = inb_p(SMB_HST_STS); - if (data & HST_STS_BAD) { - printk(KERN_WARNING "ali1563: Trying to reset busy device\n"); - outb_p(data | HST_STS_BAD,SMB_HST_STS); - data = inb_p(SMB_HST_STS); - if (data & HST_STS_BAD){ - return -EBUSY; - } - } - - /* Clear byte-ready bit */ - outb_p(data | HST_STS_DONE, SMB_HST_STS); - - /* Start transaction and wait for byte-ready bit to be set */ - outb_p(inb_p(SMB_HST_CNTL2) | HST_CNTL2_START, SMB_HST_CNTL2); - - timeout = ALI1563_MAX_TIMEOUT; - do - i2c_delay(1); - while (!((data = inb_p(SMB_HST_STS)) & HST_STS_DONE) && --timeout); - - printk(KERN_DEBUG "ali1563: Block (post): STS=%02x, CNTL1=%02x, " - "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", - inb_p(SMB_HST_STS), inb_p(SMB_HST_CNTL1), inb_p(SMB_HST_CNTL2), - inb_p(SMB_HST_CMD), inb_p(SMB_HST_ADD), inb_p(SMB_HST_DAT0), - inb_p(SMB_HST_DAT1)); - - if (timeout && !(data & HST_STS_BAD)){ - return 0; - } - printk(KERN_WARNING "ali1563: SMBus Error: %s%s%s%s%s\n", - timeout ? "Timeout " : "", - data & HST_STS_FAIL ? "Transaction Failed " : "", - data & HST_STS_BUSERR ? "No response or Bus Collision " : "", - data & HST_STS_DEVERR ? "Device Error " : "", - !(data & HST_STS_DONE) ? "Transaction Never Finished " : ""); - return -1; -} - -static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8 rw) -{ - int i, len; - int error = 0; - - /* Do we need this? */ - outb_p(HST_CNTL1_LAST,SMB_HST_CNTL1); - - if (rw == I2C_SMBUS_WRITE) { - len = data->block[0]; - if (len < 1) - len = 1; - else if (len > 32) - len = 32; - outb_p(len,SMB_HST_DAT0); - outb_p(data->block[1],SMB_BLK_DAT); - } else - len = 32; - - outb_p(inb_p(SMB_HST_CNTL2) | HST_CNTL2_BLOCK, SMB_HST_CNTL2); - - for (i = 0; i < len; i++) { - if (rw == I2C_SMBUS_WRITE) { - outb_p(data->block[i + 1], SMB_BLK_DAT); - if ((error = ali1563_block_start(a))) - break; - } else { - if ((error = ali1563_block_start(a))) - break; - if (i == 0) { - len = inb_p(SMB_HST_DAT0); - if (len < 1) - len = 1; - else if (len > 32) - len = 32; - } - data->block[i+1] = inb_p(SMB_BLK_DAT); - } - } - /* Do we need this? */ - outb_p(HST_CNTL1_LAST,SMB_HST_CNTL1); - return error; -} - -static s32 ali1563_access(struct i2c_adapter * a, u16 addr, - unsigned short flags, char rw, u8 cmd, - int size, union i2c_smbus_data * data) -{ - int error = 0; - int timeout; - u32 reg; - - for (timeout = ALI1563_MAX_TIMEOUT; timeout; timeout--) { - if (!(reg = inb_p(SMB_HST_STS) & HST_STS_BUSY)) - break; - } - if (!timeout) - printk(KERN_WARNING "ali1563: SMBus not idle. HST_STS = %02x\n",reg); - outb_p(0xff,SMB_HST_STS); - - /* Map the size to what the chip understands */ - switch (size) { - case I2C_SMBUS_PROC_CALL: - printk(KERN_ERR "ali1563: I2C_SMBUS_PROC_CALL not supported!\n"); - error = -EINVAL; - break; - case I2C_SMBUS_QUICK: - size = HST_CNTL2_QUICK; - break; - case I2C_SMBUS_BYTE: - size = HST_CNTL2_BYTE; - break; - case I2C_SMBUS_BYTE_DATA: - size = HST_CNTL2_BYTE_DATA; - break; - case I2C_SMBUS_WORD_DATA: - size = HST_CNTL2_WORD_DATA; - break; - case I2C_SMBUS_BLOCK_DATA: - size = HST_CNTL2_BLOCK; - break; - } - - outb_p(((addr & 0x7f) << 1) | (rw & 0x01), SMB_HST_ADD); - outb_p( (inb_p(SMB_HST_CNTL2)&~HST_CNTL2_SIZEMASK) | (size << 3), SMB_HST_CNTL2); - - /* Write the command register */ - switch(size) { - case HST_CNTL2_BYTE: - if (rw== I2C_SMBUS_WRITE) - /* outb_p(cmd, SMB_HST_CMD); */ - outb_p(cmd, SMB_HST_DAT0); /* modify by Rudolf */ - break; - case HST_CNTL2_BYTE_DATA: - outb_p(cmd, SMB_HST_CMD); - if (rw == I2C_SMBUS_WRITE) - outb_p(data->byte, SMB_HST_DAT0); - break; - case HST_CNTL2_WORD_DATA: - outb_p(cmd, SMB_HST_CMD); - if (rw == I2C_SMBUS_WRITE) { - outb_p(data->word & 0xff, SMB_HST_DAT0); - outb_p((data->word & 0xff00) >> 8, SMB_HST_DAT1); - } - break; - case HST_CNTL2_BLOCK: - outb_p(cmd, SMB_HST_CMD); - error = ali1563_block(a,data,rw); - goto Done; - } - - if ((error = ali1563_transaction(a))){ - goto Done; - } - - if ((rw == I2C_SMBUS_WRITE) || (size == HST_CNTL2_QUICK)){ - goto Done; - } - - switch (size) { - case HST_CNTL2_BYTE: /* Result put in SMBHSTDAT0 */ - data->byte = inb_p(SMB_HST_DAT0); - break; - case HST_CNTL2_BYTE_DATA: - data->byte = inb_p(SMB_HST_DAT0); - break; - case HST_CNTL2_WORD_DATA: - data->word = inb_p(SMB_HST_DAT0) + (inb_p(SMB_HST_DAT1) << 8); - break; - } -Done: - return error; -} - -static u32 ali1563_func(struct i2c_adapter * a) -{ - return ( I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA ); -} - - -static int __devinit ali1563_setup(struct pci_dev * dev) -{ - u16 ctrl; - - pci_read_config_word(dev,ALI1563_SMBBA,&ctrl); - - /* SMB I/O Base in high 12 bits and must be aligned with the - * size of the I/O space. */ - ali1563_smba = ctrl & ~(ALI1563_SMB_IOSIZE - 1); - if (!ali1563_smba) { - printk(KERN_WARNING "ali1563: ali1563_smba Uninitialized\n"); - goto Err; - } - - /* Check if device is enabled */ - if (!(ctrl & ALI1563_SMB_HOSTEN)) { - printk(KERN_WARNING "ali1563: Host Controller not enabled\n"); - goto Err; - } - if (!(ctrl & ALI1563_SMB_IOEN)) { - printk(KERN_WARNING "I/O space not enabled, trying manually\n"); - pci_write_config_word(dev, ALI1563_SMBBA, - ctrl | ALI1563_SMB_IOEN); - pci_read_config_word(dev, ALI1563_SMBBA, &ctrl); - if (!(ctrl & ALI1563_SMB_IOEN)) { - printk(KERN_WARNING "I/O space still not enabled, " - "giving up\n"); - goto Err; - } - } - - if (!request_region(ali1563_smba, ALI1563_SMB_IOSIZE, - ali1563_pci_driver.name)) { - printk(KERN_WARNING "ali1563: Could not allocate I/O space " - "at 0x%04x\n", ali1563_smba); - goto Err; - } - printk(KERN_INFO "ali1563: Found ALi1563 SMBus at 0x%04x\n", - ali1563_smba); - - return 0; -Err: - return -ENODEV; -} - -static void ali1563_shutdown(struct pci_dev *dev) -{ - release_region(ali1563_smba,ALI1563_SMB_IOSIZE); -} - -static void ali1563_inc(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -static void ali1563_dec(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - -static struct i2c_algorithm ali1563_algorithm = { - .name = "Non-i2c SMBus adapter", - .id = I2C_ALGO_SMBUS, - .smbus_xfer = ali1563_access, - .functionality = ali1563_func, -}; - -static struct i2c_adapter ali1563_adapter = { - .algo = &ali1563_algorithm, - .inc_use = ali1563_inc, - .dec_use = ali1563_dec, -}; - -static int __devinit ali1563_probe(struct pci_dev * dev, - const struct pci_device_id * id_table) -{ - int error; - - if ((error = ali1563_setup(dev))) { - printk(KERN_WARNING "ali1563: ALi1563 SMBus probe failed " - "(%d)\n", error); - return error; - } - sprintf(ali1563_adapter.name,"SMBus ALi 1563 Adapter @ %04x", - ali1563_smba); - if ((error = i2c_add_adapter(&ali1563_adapter))) - ali1563_shutdown(dev); - return error; -} - -static void __devexit ali1563_remove(struct pci_dev * dev) -{ - i2c_del_adapter(&ali1563_adapter); - ali1563_shutdown(dev); -} - -static struct pci_device_id ali1563_ids[] __devinitdata = { - { - .vendor = PCI_VENDOR_ID_AL, - .device = PCI_DEVICE_ID_AL_M1563, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { 0, } -}; - -static struct pci_driver ali1563_pci_driver = { - .name = "ali1563 smbus", - .id_table = ali1563_ids, - .probe = ali1563_probe, - .remove = __devexit_p(ali1563_remove), -}; - -static int __init ali1563_init(void) -{ - printk("i2c-ali1563.o version %s (%s)\n", LM_VERSION, LM_DATE); - return pci_module_init(&ali1563_pci_driver); -} - -module_init(ali1563_init); - -static void __exit ali1563_exit(void) -{ - pci_unregister_driver(&ali1563_pci_driver); -} - -module_exit(ali1563_exit); - -MODULE_AUTHOR("Patrick Mochel , Chunhao Huang"); -MODULE_DESCRIPTION("ALi M1563 southbridge driver for linux-2.4, backported by Chunhao Huang from linux-2.6"); -MODULE_LICENSE("GPL"); - diff --git a/kernel/busses/i2c-ali15x3.c b/kernel/busses/i2c-ali15x3.c deleted file mode 100644 index 19c40207..00000000 --- a/kernel/busses/i2c-ali15x3.c +++ /dev/null @@ -1,548 +0,0 @@ -/* - ali15x3.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1999 Frodo Looijaard and - Philip Edelbrock and - Mark D. Studebaker - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - This is the driver for the SMB Host controller on - Acer Labs Inc. (ALI) M1541 and M1543C South Bridges. - - The M1543C is a South bridge for desktop systems. - The M1533 is a South bridge for portable systems. - They are part of the following ALI chipsets: - "Aladdin Pro 2": Includes the M1621 Slot 1 North bridge - with AGP and 100MHz CPU Front Side bus - "Aladdin V": Includes the M1541 Socket 7 North bridge - with AGP and 100MHz CPU Front Side bus - "Aladdin IV": Includes the M1541 Socket 7 North bridge - with host bus up to 83.3 MHz. - For an overview of these chips see http://www.acerlabs.com - - The M1533/M1543C devices appear as FOUR separate devices - on the PCI bus. An output of lspci will show something similar - to the following: - - 00:02.0 USB Controller: Acer Laboratories Inc. M5237 - 00:03.0 Bridge: Acer Laboratories Inc. M7101 - 00:07.0 ISA bridge: Acer Laboratories Inc. M1533 - 00:0f.0 IDE interface: Acer Laboratories Inc. M5229 - - The SMB controller is part of the 7101 device, which is an - ACPI-compliant Power Management Unit (PMU). - - The whole 7101 device has to be enabled for the SMB to work. - You can't just enable the SMB alone. - The SMB and the ACPI have separate I/O spaces. - We make sure that the SMB is enabled. We leave the ACPI alone. - - This driver controls the SMB Host only. - The SMB Slave controller on the M15X3 is not enabled. - - This driver does not use interrupts. -*/ - -/* Note: we assume there can only be one ALI15X3, with one SMBus interface */ - -/* #define DEBUG 1 */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "version.h" -#include "sensors_compat.h" - -/* ALI15X3 SMBus address offsets */ -#define SMBHSTSTS (0 + ali15x3_smba) -#define SMBHSTCNT (1 + ali15x3_smba) -#define SMBHSTSTART (2 + ali15x3_smba) -#define SMBHSTCMD (7 + ali15x3_smba) -#define SMBHSTADD (3 + ali15x3_smba) -#define SMBHSTDAT0 (4 + ali15x3_smba) -#define SMBHSTDAT1 (5 + ali15x3_smba) -#define SMBBLKDAT (6 + ali15x3_smba) - -/* PCI Address Constants */ -#define SMBCOM 0x004 -#define SMBBA 0x014 -#define SMBATPC 0x05B /* used to unlock xxxBA registers */ -#define SMBHSTCFG 0x0E0 -#define SMBSLVC 0x0E1 -#define SMBCLK 0x0E2 -#define SMBREV 0x008 - -/* Other settings */ -#define MAX_TIMEOUT 200 /* times 1/100 sec */ -#define ALI15X3_SMB_IOSIZE 32 - -/* this is what the Award 1004 BIOS sets them to on a ASUS P5A MB. - We don't use these here. If the bases aren't set to some value we - tell user to upgrade BIOS and we fail. -*/ -#define ALI15X3_SMB_DEFAULTBASE 0xE800 - -/* ALI15X3 address lock bits */ -#define ALI15X3_LOCK 0x06 - -/* ALI15X3 command constants */ -#define ALI15X3_ABORT 0x02 -#define ALI15X3_T_OUT 0x04 -#define ALI15X3_QUICK 0x00 -#define ALI15X3_BYTE 0x10 -#define ALI15X3_BYTE_DATA 0x20 -#define ALI15X3_WORD_DATA 0x30 -#define ALI15X3_BLOCK_DATA 0x40 -#define ALI15X3_BLOCK_CLR 0x80 - -/* ALI15X3 status register bits */ -#define ALI15X3_STS_IDLE 0x04 -#define ALI15X3_STS_BUSY 0x08 -#define ALI15X3_STS_DONE 0x10 -#define ALI15X3_STS_DEV 0x20 /* device error */ -#define ALI15X3_STS_COLL 0x40 /* collision or no response */ -#define ALI15X3_STS_TERM 0x80 /* terminated by abort */ -#define ALI15X3_STS_ERR 0xE0 /* all the bad error bits */ - - -/* If force_addr is set to anything different from 0, we forcibly enable - the device at the given address. */ -static int force_addr = 0; -MODULE_PARM(force_addr, "i"); -MODULE_PARM_DESC(force_addr, - "Initialize the base address of the i2c controller"); - -static struct pci_driver ali15x3_driver; -static unsigned short ali15x3_smba = 0; - -static int ali15x3_setup(struct pci_dev *ALI15X3_dev) -{ - u16 a; - unsigned char temp; - - /* Check the following things: - - SMB I/O address is initialized - - Device is enabled - - We can use the addresses - */ - - /* Unlock the register. - The data sheet says that the address registers are read-only - if the lock bits are 1, but in fact the address registers - are zero unless you clear the lock bits. - */ - pci_read_config_byte(ALI15X3_dev, SMBATPC, &temp); - if (temp & ALI15X3_LOCK) { - temp &= ~ALI15X3_LOCK; - pci_write_config_byte(ALI15X3_dev, SMBATPC, temp); - } - - /* Determine the address of the SMBus area */ - pci_read_config_word(ALI15X3_dev, SMBBA, &ali15x3_smba); - ali15x3_smba &= (0xffff & ~(ALI15X3_SMB_IOSIZE - 1)); - if (ali15x3_smba == 0 && force_addr == 0) { - dev_err(ALI15X3_dev, "ALI15X3_smb region uninitialized " - "- upgrade BIOS or use force_addr=0xaddr\n"); - return -ENODEV; - } - - if(force_addr) - ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1); - - if (!request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, - ali15x3_driver.name)) { - dev_err(ALI15X3_dev, - "ALI15X3_smb region 0x%x already in use!\n", - ali15x3_smba); - return -ENODEV; - } - - if(force_addr) { - dev_info(ALI15X3_dev, "forcing ISA address 0x%04X\n", - ali15x3_smba); - if (PCIBIOS_SUCCESSFUL != - pci_write_config_word(ALI15X3_dev, SMBBA, ali15x3_smba)) - return -ENODEV; - if (PCIBIOS_SUCCESSFUL != - pci_read_config_word(ALI15X3_dev, SMBBA, &a)) - return -ENODEV; - if ((a & ~(ALI15X3_SMB_IOSIZE - 1)) != ali15x3_smba) { - /* make sure it works */ - dev_err(ALI15X3_dev, - "force address failed - not supported?\n"); - return -ENODEV; - } - } - /* check if whole device is enabled */ - pci_read_config_byte(ALI15X3_dev, SMBCOM, &temp); - if ((temp & 1) == 0) { - dev_info(ALI15X3_dev, "enabling SMBus device\n"); - pci_write_config_byte(ALI15X3_dev, SMBCOM, temp | 0x01); - } - - /* Is SMB Host controller enabled? */ - pci_read_config_byte(ALI15X3_dev, SMBHSTCFG, &temp); - if ((temp & 1) == 0) { - dev_info(ALI15X3_dev, "enabling SMBus controller\n"); - pci_write_config_byte(ALI15X3_dev, SMBHSTCFG, temp | 0x01); - } - - /* set SMB clock to 74KHz as recommended in data sheet */ - pci_write_config_byte(ALI15X3_dev, SMBCLK, 0x20); - - /* - The interrupt routing for SMB is set up in register 0x77 in the - 1533 ISA Bridge device, NOT in the 7101 device. - Don't bother with finding the 1533 device and reading the register. - if ((....... & 0x0F) == 1) - dev_dbg(ALI15X3_dev, "ALI15X3 using Interrupt 9 for SMBus.\n"); - */ - pci_read_config_byte(ALI15X3_dev, SMBREV, &temp); - dev_dbg(ALI15X3_dev, "SMBREV = 0x%X\n", temp); - dev_dbg(ALI15X3_dev, "iALI15X3_smba = 0x%X\n", ali15x3_smba); - - return 0; -} - -/* Another internally used function */ -static int ali15x3_transaction(struct i2c_adapter *adap) -{ - int temp; - int result = 0; - int timeout = 0; - - dev_dbg(adap, "Transaction (pre): STS=%02x, CNT=%02x, CMD=%02x, " - "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS), - inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), - inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); - - /* get status */ - temp = inb_p(SMBHSTSTS); - - /* Make sure the SMBus host is ready to start transmitting */ - /* Check the busy bit first */ - if (temp & ALI15X3_STS_BUSY) { - /* - If the host controller is still busy, it may have timed out in the - previous transaction, resulting in a "SMBus Timeout" Dev. - I've tried the following to reset a stuck busy bit. - 1. Reset the controller with an ABORT command. - (this doesn't seem to clear the controller if an external - device is hung) - 2. Reset the controller and the other SMBus devices with a - T_OUT command. (this clears the host busy bit if an - external device is hung, but it comes back upon a new access - to a device) - 3. Disable and reenable the controller in SMBHSTCFG - Worst case, nothing seems to work except power reset. - */ - /* Abort - reset the host controller */ - /* - Try resetting entire SMB bus, including other devices - - This may not work either - it clears the BUSY bit but - then the BUSY bit may come back on when you try and use the chip again. - If that's the case you are stuck. - */ - dev_info(adap, "Resetting entire SMB Bus to " - "clear busy condition (%02x)\n", temp); - outb_p(ALI15X3_T_OUT, SMBHSTCNT); - temp = inb_p(SMBHSTSTS); - } - - /* now check the error bits and the busy bit */ - if (temp & (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) { - /* do a clear-on-write */ - outb_p(0xFF, SMBHSTSTS); - if ((temp = inb_p(SMBHSTSTS)) & - (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) { - /* this is probably going to be correctable only by a power reset - as one of the bits now appears to be stuck */ - /* This may be a bus or device with electrical problems. */ - dev_err(adap, "SMBus reset failed! (0x%02x) - " - "controller or device on bus is probably hung\n", - temp); - return -1; - } - } else { - /* check and clear done bit */ - if (temp & ALI15X3_STS_DONE) { - outb_p(temp, SMBHSTSTS); - } - } - - /* start the transaction by writing anything to the start register */ - outb_p(0xFF, SMBHSTSTART); - - /* We will always wait for a fraction of a second! */ - timeout = 0; - do { - i2c_delay(1); - temp = inb_p(SMBHSTSTS); - } while ((!(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE))) - && (timeout++ < MAX_TIMEOUT)); - - /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { - result = -1; - dev_err(adap, "SMBus Timeout!\n"); - } - - if (temp & ALI15X3_STS_TERM) { - result = -1; - dev_dbg(adap, "Error: Failed bus transaction\n"); - } - - /* - Unfortunately the ALI SMB controller maps "no response" and "bus - collision" into a single bit. No reponse is the usual case so don't - do a printk. - This means that bus collisions go unreported. - */ - if (temp & ALI15X3_STS_COLL) { - result = -1; - dev_dbg(adap, - "Error: no response or bus collision ADD=%02x\n", - inb_p(SMBHSTADD)); - } - - /* haven't ever seen this */ - if (temp & ALI15X3_STS_DEV) { - result = -1; - dev_err(adap, "Error: device error\n"); - } - dev_dbg(adap, "Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, " - "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS), - inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), - inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); - return result; -} - -/* Return -1 on error. */ -static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, u8 command, - int size, union i2c_smbus_data * data) -{ - int i, len; - int temp; - int timeout; - - /* clear all the bits (clear-on-write) */ - outb_p(0xFF, SMBHSTSTS); - /* make sure SMBus is idle */ - temp = inb_p(SMBHSTSTS); - for (timeout = 0; - (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE); - timeout++) { - i2c_delay(1); - temp = inb_p(SMBHSTSTS); - } - if (timeout >= MAX_TIMEOUT) { - dev_err(adap, "Idle wait Timeout! STS=0x%02x\n", temp); - } - - switch (size) { - case I2C_SMBUS_QUICK: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - size = ALI15X3_QUICK; - break; - case I2C_SMBUS_BYTE: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - if (read_write == I2C_SMBUS_WRITE) - outb_p(command, SMBHSTCMD); - size = ALI15X3_BYTE; - break; - case I2C_SMBUS_BYTE_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) - outb_p(data->byte, SMBHSTDAT0); - size = ALI15X3_BYTE_DATA; - break; - case I2C_SMBUS_WORD_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) { - outb_p(data->word & 0xff, SMBHSTDAT0); - outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); - } - size = ALI15X3_WORD_DATA; - break; - case I2C_SMBUS_BLOCK_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) { - len = data->block[0]; - if (len < 0) { - len = 0; - data->block[0] = len; - } - if (len > 32) { - len = 32; - data->block[0] = len; - } - outb_p(len, SMBHSTDAT0); - /* Reset SMBBLKDAT */ - outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT); - for (i = 1; i <= len; i++) - outb_p(data->block[i], SMBBLKDAT); - } - size = ALI15X3_BLOCK_DATA; - break; - default: - printk - (KERN_WARNING "i2c-ali15x3.o: Unsupported transaction %d\n", size); - return -1; - } - - outb_p(size, SMBHSTCNT); /* output command */ - - if (ali15x3_transaction(adap)) /* Error in transaction */ - return -1; - - if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK)) - return 0; - - - switch (size) { - case ALI15X3_BYTE: /* Result put in SMBHSTDAT0 */ - data->byte = inb_p(SMBHSTDAT0); - break; - case ALI15X3_BYTE_DATA: - data->byte = inb_p(SMBHSTDAT0); - break; - case ALI15X3_WORD_DATA: - data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); - break; - case ALI15X3_BLOCK_DATA: - len = inb_p(SMBHSTDAT0); - if (len > 32) - len = 32; - data->block[0] = len; - /* Reset SMBBLKDAT */ - outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT); - for (i = 1; i <= data->block[0]; i++) { - data->block[i] = inb_p(SMBBLKDAT); - dev_dbg(adap, "Blk: len=%d, i=%d, data=%02x\n", - len, i, data->block[i]); - } - break; - } - return 0; -} - -static void ali15x3_inc(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -static void ali15x3_dec(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - -static u32 ali15x3_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA; -} - -static struct i2c_algorithm smbus_algorithm = { - .name = "Non-I2C SMBus adapter", - .id = I2C_ALGO_SMBUS, - .smbus_xfer = ali15x3_access, - .functionality = ali15x3_func, -}; - -static struct i2c_adapter ali15x3_adapter = { - .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_ALI15X3, - .algo = &smbus_algorithm, - .inc_use = ali15x3_inc, - .dec_use = ali15x3_dec, -}; - -static struct pci_device_id ali15x3_ids[] __devinitdata = { - { - .vendor = PCI_VENDOR_ID_AL, - .device = PCI_DEVICE_ID_AL_M7101, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { 0, } -}; - -static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - if (ali15x3_setup(dev)) { - dev_err(dev, - "ALI15X3 not detected, module not inserted.\n"); - return -ENODEV; - } - - snprintf(ali15x3_adapter.name, 32, - "SMBus ALI15X3 adapter at %04x", ali15x3_smba); - return i2c_add_adapter(&ali15x3_adapter); -} - -static void __devexit ali15x3_remove(struct pci_dev *dev) -{ - i2c_del_adapter(&ali15x3_adapter); - release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE); -} - -static struct pci_driver ali15x3_driver = { - .name = "ali15x3 smbus", - .id_table = ali15x3_ids, - .probe = ali15x3_probe, - .remove = __devexit_p(ali15x3_remove), -}; - -static int __init i2c_ali15x3_init(void) -{ - printk("i2c-ali15x3.o version %s (%s)\n", LM_VERSION, LM_DATE); - return pci_module_init(&ali15x3_driver); -} - -static void __exit i2c_ali15x3_exit(void) -{ - pci_unregister_driver(&ali15x3_driver); -} - -MODULE_AUTHOR ("Frodo Looijaard , " - "Philip Edelbrock , " - "and Mark D. Studebaker "); -MODULE_DESCRIPTION("ALI15X3 SMBus driver"); -MODULE_LICENSE("GPL"); - -module_init(i2c_ali15x3_init); -module_exit(i2c_ali15x3_exit); diff --git a/kernel/busses/i2c-amd756-s4882.c b/kernel/busses/i2c-amd756-s4882.c deleted file mode 100644 index 0707c1dc..00000000 --- a/kernel/busses/i2c-amd756-s4882.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * i2c-amd756-s4882.c - i2c-amd756 extras for the Tyan S4882 motherboard - * - * Copyright (C) 2004 Jean Delvare - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * We select the channels by sending commands to the Philips - * PCA9556 chip at I2C address 0x18. The main adapter is used for - * the non-multiplexed part of the bus, and 4 virtual adapters - * are defined for the multiplexed addresses: 0x50-0x53 (memory - * module EEPROM) located on channels 1-4, and 0x4c (LM63) - * located on multiplexed channels 0 and 5-7. We define one - * virtual adapter per CPU, which corresponds to two multiplexed - * channels: - * CPU0: virtual adapter 1, channels 1 and 0 - * CPU1: virtual adapter 2, channels 2 and 5 - * CPU2: virtual adapter 3, channels 3 and 6 - * CPU3: virtual adapter 4, channels 4 and 7 - */ - -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "i2c-amd756-s4882" - -extern struct i2c_adapter amd756_smbus; - -static struct i2c_adapter *s4882_adapter; -static struct i2c_algorithm *s4882_algo; - -/* Wrapper access functions for multiplexed SMBus */ -static DECLARE_MUTEX(amd756_lock); - -static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, - union i2c_smbus_data * data) -{ - int error; - - /* We exclude the multiplexed addresses */ - if (addr == 0x4c || (addr & 0xfc) == 0x50 || (addr & 0xfc) == 0x30 - || addr == 0x18) - return -1; - - down(&amd756_lock); - - error = amd756_smbus.algo->smbus_xfer(adap, addr, flags, read_write, - command, size, data); - - up(&amd756_lock); - - return error; -} - -/* We remember the last used channels combination so as to only switch - channels when it is really needed. This greatly reduces the SMBus - overhead, but also assumes that nobody will be writing to the PCA9556 - in our back. */ -static u8 last_channels; - -static inline s32 amd756_access_channel(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, - union i2c_smbus_data * data, - u8 channels) -{ - int error; - - /* We exclude the non-multiplexed addresses */ - if (addr != 0x4c && (addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30) - return -1; - - down(&amd756_lock); - - if (last_channels != channels) { - union i2c_smbus_data mplxdata; - mplxdata.byte = channels; - - error = amd756_smbus.algo->smbus_xfer(adap, 0x18, 0, - I2C_SMBUS_WRITE, 0x01, - I2C_SMBUS_BYTE_DATA, - &mplxdata); - if (error) - goto UNLOCK; - last_channels = channels; - } - error = amd756_smbus.algo->smbus_xfer(adap, addr, flags, read_write, - command, size, data); - -UNLOCK: - up(&amd756_lock); - return error; -} - -static s32 amd756_access_virt1(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, - union i2c_smbus_data * data) -{ - /* CPU0: channels 1 and 0 enabled */ - return amd756_access_channel(adap, addr, flags, read_write, command, - size, data, 0x03); -} - -static s32 amd756_access_virt2(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, - union i2c_smbus_data * data) -{ - /* CPU1: channels 2 and 5 enabled */ - return amd756_access_channel(adap, addr, flags, read_write, command, - size, data, 0x24); -} - -static s32 amd756_access_virt3(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, - union i2c_smbus_data * data) -{ - /* CPU2: channels 3 and 6 enabled */ - return amd756_access_channel(adap, addr, flags, read_write, command, - size, data, 0x48); -} - -static s32 amd756_access_virt4(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, - union i2c_smbus_data * data) -{ - /* CPU3: channels 4 and 7 enabled */ - return amd756_access_channel(adap, addr, flags, read_write, command, - size, data, 0x90); -} - -static int __init amd756_s4882_init(void) -{ - int i, error; - union i2c_smbus_data ioconfig; - - /* Unregister physical bus */ - error = i2c_del_adapter(&amd756_smbus); - if (error) { - if (error != -ENODEV) - printk(KERN_ERR DRV_NAME ": Physical bus removal " - "failed\n"); - goto ERROR0; - } - - printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4882\n"); - - /* Define the 5 virtual adapters and algorithms structures */ - if (!(s4882_adapter = kmalloc(5 * sizeof(struct i2c_adapter), - GFP_KERNEL))) { - error = -ENOMEM; - goto ERROR1; - } - if (!(s4882_algo = kmalloc(5 * sizeof(struct i2c_algorithm), - GFP_KERNEL))) { - error = -ENOMEM; - goto ERROR2; - } - - /* Fill in the new structures */ - s4882_algo[0] = *(amd756_smbus.algo); - s4882_algo[0].smbus_xfer = amd756_access_virt0; - s4882_adapter[0] = amd756_smbus; - s4882_adapter[0].algo = s4882_algo; - for (i = 1; i < 5; i++) { - s4882_algo[i] = *(amd756_smbus.algo); - s4882_adapter[i] = amd756_smbus; - sprintf(s4882_adapter[i].name, - "SMBus 8111 adapter (CPU%d)", i-1); - s4882_adapter[i].algo = s4882_algo+i; - } - s4882_algo[1].smbus_xfer = amd756_access_virt1; - s4882_algo[2].smbus_xfer = amd756_access_virt2; - s4882_algo[3].smbus_xfer = amd756_access_virt3; - s4882_algo[4].smbus_xfer = amd756_access_virt4; - - /* Configure the PCA9556 multiplexer */ - ioconfig.byte = 0x00; /* All I/O to output mode */ - error = amd756_smbus.algo->smbus_xfer(&amd756_smbus, 0x18, 0, - I2C_SMBUS_WRITE, 0x03, - I2C_SMBUS_BYTE_DATA, &ioconfig); - if (error) { - printk(KERN_ERR DRV_NAME ": PCA9556 configuration failed\n"); - error = -EIO; - goto ERROR3; - } - - /* Register virtual adapters */ - for (i = 0; i < 5; i++) { - error = i2c_add_adapter(s4882_adapter+i); - if (error) { - printk(KERN_ERR DRV_NAME - ": Virtual adapter %d registration " - "failed, module not inserted\n", i); - for (i--; i >= 0; i--) - i2c_del_adapter(s4882_adapter+i); - goto ERROR3; - } - } - - return 0; - -ERROR3: - kfree(s4882_algo); - s4882_algo = NULL; -ERROR2: - kfree(s4882_adapter); - s4882_adapter = NULL; -ERROR1: - i2c_del_adapter(&amd756_smbus); -ERROR0: - return error; -} - -static void __exit amd756_s4882_exit(void) -{ - if (s4882_adapter) { - int i; - - for (i = 0; i < 5; i++) - i2c_del_adapter(s4882_adapter+i); - kfree(s4882_adapter); - s4882_adapter = NULL; - } - if (s4882_algo) { - kfree(s4882_algo); - s4882_algo = NULL; - } - - /* Restore physical bus */ - if (i2c_add_adapter(&amd756_smbus)) - printk(KERN_ERR DRV_NAME ": Physical bus restoration " - "failed\n"); -} - -MODULE_AUTHOR("Jean Delvare "); -MODULE_DESCRIPTION("S4882 SMBus multiplexing"); -MODULE_LICENSE("GPL"); - -module_init(amd756_s4882_init); -module_exit(amd756_s4882_exit); diff --git a/kernel/busses/i2c-amd756.c b/kernel/busses/i2c-amd756.c deleted file mode 100644 index 5f93255b..00000000 --- a/kernel/busses/i2c-amd756.c +++ /dev/null @@ -1,444 +0,0 @@ -/* - amd756.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - - Copyright (c) 1999-2002 Merlin Hughes - - Shamelessly ripped from i2c-piix4.c: - - Copyright (c) 1998, 1999 Frodo Looijaard and - Philip Edelbrock - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - 2002-04-08: Added nForce support. (Csaba Halasz) - 2002-10-03: Fixed nForce PnP I/O port. (Michael Steil) - 2002-12-28: Rewritten into something that resembles a Linux driver (hch) - 2003-11-29: Added back AMD8111 removed by the previous rewrite. - (Philip Pokorny) - 2004-02-15: Don't register driver to avoid driver conflicts. - (Daniel Rune Jensen) -*/ - -/* - Supports AMD756, AMD766, AMD768, AMD8111 and nVidia nForce - Note: we assume there can only be one device, with one SMBus interface. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "version.h" - -#define DRV_NAME "i2c-amd756" - -/* AMD756 SMBus address offsets */ -#define SMB_ADDR_OFFSET 0xE0 -#define SMB_IOSIZE 16 -#define SMB_GLOBAL_STATUS (0x0 + amd756_ioport) -#define SMB_GLOBAL_ENABLE (0x2 + amd756_ioport) -#define SMB_HOST_ADDRESS (0x4 + amd756_ioport) -#define SMB_HOST_DATA (0x6 + amd756_ioport) -#define SMB_HOST_COMMAND (0x8 + amd756_ioport) -#define SMB_HOST_BLOCK_DATA (0x9 + amd756_ioport) -#define SMB_HAS_DATA (0xA + amd756_ioport) -#define SMB_HAS_DEVICE_ADDRESS (0xC + amd756_ioport) -#define SMB_HAS_HOST_ADDRESS (0xE + amd756_ioport) -#define SMB_SNOOP_ADDRESS (0xF + amd756_ioport) - -/* PCI Address Constants */ - -/* address of I/O space */ -#define SMBBA 0x058 /* mh */ -#define SMBBANFORCE 0x014 - -/* general configuration */ -#define SMBGCFG 0x041 /* mh */ - -/* silicon revision code */ -#define SMBREV 0x008 - -/* Other settings */ -#define MAX_TIMEOUT 500 - -/* AMD756 constants */ -#define AMD756_QUICK 0x00 -#define AMD756_BYTE 0x01 -#define AMD756_BYTE_DATA 0x02 -#define AMD756_WORD_DATA 0x03 -#define AMD756_PROCESS_CALL 0x04 -#define AMD756_BLOCK_DATA 0x05 - - -static unsigned short amd756_ioport = 0; - -/* - SMBUS event = I/O 28-29 bit 11 - see E0 for the status bits and enabled in E2 - -*/ - -#define GS_ABRT_STS (1 << 0) -#define GS_COL_STS (1 << 1) -#define GS_PRERR_STS (1 << 2) -#define GS_HST_STS (1 << 3) -#define GS_HCYC_STS (1 << 4) -#define GS_TO_STS (1 << 5) -#define GS_SMB_STS (1 << 11) - -#define GS_CLEAR_STS (GS_ABRT_STS | GS_COL_STS | GS_PRERR_STS | \ - GS_HCYC_STS | GS_TO_STS ) - -#define GE_CYC_TYPE_MASK (7) -#define GE_HOST_STC (1 << 3) -#define GE_ABORT (1 << 5) - - -static int amd756_transaction(void) -{ - int temp; - int result = 0; - int timeout = 0; - - pr_debug(DRV_NAME - ": Transaction (pre): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n", - inw_p(SMB_GLOBAL_STATUS), inw_p(SMB_GLOBAL_ENABLE), - inw_p(SMB_HOST_ADDRESS), inb_p(SMB_HOST_DATA)); - - /* Make sure the SMBus host is ready to start transmitting */ - if ((temp = inw_p(SMB_GLOBAL_STATUS)) & (GS_HST_STS | GS_SMB_STS)) { - pr_debug(DRV_NAME ": SMBus busy (%04x). Waiting...\n", temp); - do { - i2c_delay(1); - temp = inw_p(SMB_GLOBAL_STATUS); - } while ((temp & (GS_HST_STS | GS_SMB_STS)) && - (timeout++ < MAX_TIMEOUT)); - /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { - pr_debug(DRV_NAME ": Busy wait timeout (%04x)\n", temp); - goto abort; - } - timeout = 0; - } - - /* start the transaction by setting the start bit */ - outw_p(inw(SMB_GLOBAL_ENABLE) | GE_HOST_STC, SMB_GLOBAL_ENABLE); - - /* We will always wait for a fraction of a second! */ - do { - i2c_delay(1); - temp = inw_p(SMB_GLOBAL_STATUS); - } while ((temp & GS_HST_STS) && (timeout++ < MAX_TIMEOUT)); - - /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { - pr_debug(DRV_NAME ": Completion timeout!\n"); - goto abort; - } - - if (temp & GS_PRERR_STS) { - result = -1; - pr_debug(DRV_NAME ": SMBus Protocol error (no response)!\n"); - } - - if (temp & GS_COL_STS) { - result = -1; - printk(KERN_WARNING DRV_NAME ": SMBus collision!\n"); - } - - if (temp & GS_TO_STS) { - result = -1; - pr_debug(DRV_NAME ": SMBus protocol timeout!\n"); - } - - if (temp & GS_HCYC_STS) - pr_debug(DRV_NAME ": SMBus protocol success!\n"); - - outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS); - -#ifdef DEBUG - if (((temp = inw_p(SMB_GLOBAL_STATUS)) & GS_CLEAR_STS) != 0x00) { - pr_debug(DRV_NAME - ": Failed reset at end of transaction (%04x)\n", temp); - } - - pr_debug(DRV_NAME - ": Transaction (post): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n", - inw_p(SMB_GLOBAL_STATUS), inw_p(SMB_GLOBAL_ENABLE), - inw_p(SMB_HOST_ADDRESS), inb_p(SMB_HOST_DATA)); -#endif - - return result; - - abort: - printk(KERN_WARNING DRV_NAME ": Sending abort.\n"); - outw_p(inw(SMB_GLOBAL_ENABLE) | GE_ABORT, SMB_GLOBAL_ENABLE); - i2c_delay(100); - outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS); - return -1; -} - -/* Return -1 on error. */ - -static s32 amd756_access(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data * data) -{ - int i, len; - - /** TODO: Should I supporte the 10-bit transfers? */ - switch (size) { - /* TODO: proc call is supported, I'm just not sure what to do here... */ - case I2C_SMBUS_QUICK: - outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMB_HOST_ADDRESS); - size = AMD756_QUICK; - break; - case I2C_SMBUS_BYTE: - outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMB_HOST_ADDRESS); - if (read_write == I2C_SMBUS_WRITE) - outb_p(command, SMB_HOST_DATA); - size = AMD756_BYTE; - break; - case I2C_SMBUS_BYTE_DATA: - outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMB_HOST_ADDRESS); - outb_p(command, SMB_HOST_COMMAND); - if (read_write == I2C_SMBUS_WRITE) - outw_p(data->byte, SMB_HOST_DATA); - size = AMD756_BYTE_DATA; - break; - case I2C_SMBUS_WORD_DATA: - outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMB_HOST_ADDRESS); - outb_p(command, SMB_HOST_COMMAND); - if (read_write == I2C_SMBUS_WRITE) - outw_p(data->word, SMB_HOST_DATA); /* TODO: endian???? */ - size = AMD756_WORD_DATA; - break; - case I2C_SMBUS_BLOCK_DATA: - outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMB_HOST_ADDRESS); - outb_p(command, SMB_HOST_COMMAND); - if (read_write == I2C_SMBUS_WRITE) { - len = data->block[0]; - if (len < 0) - len = 0; - if (len > 32) - len = 32; - outw_p(len, SMB_HOST_DATA); - /* i = inw_p(SMBHSTCNT); Reset SMBBLKDAT */ - for (i = 1; i <= len; i++) - outb_p(data->block[i], - SMB_HOST_BLOCK_DATA); - } - size = AMD756_BLOCK_DATA; - break; - default: - printk - (KERN_WARNING "i2c-amd756.o: Unsupported transaction %d\n", size); - return -1; - } - - /* How about enabling interrupts... */ - outw_p(size & GE_CYC_TYPE_MASK, SMB_GLOBAL_ENABLE); - - if (amd756_transaction()) /* Error in transaction */ - return -1; - - if ((read_write == I2C_SMBUS_WRITE) || (size == AMD756_QUICK)) - return 0; - - - switch (size) { - case AMD756_BYTE: - data->byte = inw_p(SMB_HOST_DATA); - break; - case AMD756_BYTE_DATA: - data->byte = inw_p(SMB_HOST_DATA); - break; - case AMD756_WORD_DATA: - data->word = inw_p(SMB_HOST_DATA); /* TODO: endian???? */ - break; - case AMD756_BLOCK_DATA: - data->block[0] = inw_p(SMB_HOST_DATA) & 0x3f; - if(data->block[0] > 32) - data->block[0] = 32; - /* i = inw_p(SMBHSTCNT); Reset SMBBLKDAT */ - for (i = 1; i <= data->block[0]; i++) - data->block[i] = inb_p(SMB_HOST_BLOCK_DATA); - break; - } - - return 0; -} - -static void amd756_inc(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -static void amd756_dec(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - -static u32 amd756_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL; -} - -static struct i2c_algorithm smbus_algorithm = { - .name = "Non-I2C SMBus adapter", - .id = I2C_ALGO_SMBUS, - .smbus_xfer = amd756_access, - .functionality = amd756_func, -}; - -struct i2c_adapter amd756_smbus = { - .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_AMD756, - .algo = &smbus_algorithm, - .inc_use = amd756_inc, - .dec_use = amd756_dec, -}; - -enum chiptype { AMD756, AMD766, AMD768, NFORCE, AMD8111 }; -static const char* chipname[] = { - "AMD756", "AMD766", "AMD768", - "nVidia nForce", "AMD8111", -}; - -static struct pci_device_id amd756_ids[] __devinitdata = { - {PCI_VENDOR_ID_AMD, 0x740B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD756 }, - {PCI_VENDOR_ID_AMD, 0x7413, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD766 }, - {PCI_VENDOR_ID_AMD, 0x7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD768 }, - {PCI_VENDOR_ID_AMD, 0x746B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD8111 }, - {PCI_VENDOR_ID_NVIDIA, 0x01B4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE }, - { 0, } -}; - -static int __devinit amd756_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - int nforce = (id->driver_data == NFORCE); - int error; - u8 temp; - - if (amd756_ioport) { - printk(KERN_ERR DRV_NAME ": Only one device supported. " - "(you have a strange motherboard, btw..)\n"); - return -ENODEV; - } - - if (nforce) { - if (PCI_FUNC(pdev->devfn) != 1) - return -ENODEV; - - pci_read_config_word(pdev, SMBBANFORCE, &amd756_ioport); - amd756_ioport &= 0xfffc; - } else { /* amd */ - if (PCI_FUNC(pdev->devfn) != 3) - return -ENODEV; - - pci_read_config_byte(pdev, SMBGCFG, &temp); - if ((temp & 128) == 0) { - printk(KERN_ERR DRV_NAME - ": Error: SMBus controller I/O not enabled!\n"); - return -ENODEV; - } - - /* Determine the address of the SMBus areas */ - /* Technically it is a dword but... */ - pci_read_config_word(pdev, SMBBA, &amd756_ioport); - amd756_ioport &= 0xff00; - amd756_ioport += SMB_ADDR_OFFSET; - } - - if (!request_region(amd756_ioport, SMB_IOSIZE, "amd756-smbus")) { - printk(KERN_ERR DRV_NAME - ": SMB region 0x%x already in use!\n", amd756_ioport); - return -ENODEV; - } - -#ifdef DEBUG - pci_read_config_byte(pdev, SMBREV, &temp); - printk(KERN_DEBUG DRV_NAME ": SMBREV = 0x%X\n", temp); - printk(KERN_DEBUG DRV_NAME ": AMD756_smba = 0x%X\n", amd756_ioport); -#endif - - sprintf(amd756_smbus.name, "SMBus %s adapter at %04x", - chipname[id->driver_data], amd756_ioport); - - error = i2c_add_adapter(&amd756_smbus); - if (error) { - printk(KERN_ERR DRV_NAME - ": Adapter registration failed, module not inserted.\n"); - goto out_err; - } - - return 0; - - out_err: - release_region(amd756_ioport, SMB_IOSIZE); - return error; -} - - -static int __init i2c_amd756_init(void) -{ - struct pci_dev *dev; - const struct pci_device_id *id; - - printk(KERN_INFO "i2c-amd756.o version %s (%s)\n", LM_VERSION, LM_DATE); - - pci_for_each_dev(dev) { - id = pci_match_device(amd756_ids, dev); - if (id && amd756_probe(dev, id) >= 0) - return 0; - } - - return -ENODEV; -} - - -static void __exit i2c_amd756_exit(void) -{ - i2c_del_adapter(&amd756_smbus); - release_region(amd756_ioport, SMB_IOSIZE); -} - -MODULE_AUTHOR("Merlin Hughes "); -MODULE_DESCRIPTION("AMD756/766/768/8111 and nVidia nForce SMBus driver"); -MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(amd756_smbus); - -module_init(i2c_amd756_init) -module_exit(i2c_amd756_exit) diff --git a/kernel/busses/i2c-amd8111.c b/kernel/busses/i2c-amd8111.c deleted file mode 100644 index a6bc973a..00000000 --- a/kernel/busses/i2c-amd8111.c +++ /dev/null @@ -1,424 +0,0 @@ -/* - * SMBus 2.0 driver for AMD-8111 IO-Hub. - * - * Copyright (c) 2002 Vojtech Pavlik - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "version.h" -#include "sensors_compat.h" - -#ifndef I2C_HW_SMBUS_AMD8111 -#error Your i2c is too old - i2c-2.7.0 or greater required! -#endif - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR ("Vojtech Pavlik "); -MODULE_DESCRIPTION("AMD8111 SMBus 2.0 driver"); - -struct amd_smbus { - struct pci_dev *dev; - struct i2c_adapter adapter; - int base; - int size; -}; - -static struct pci_driver amd8111_driver; - -/* - * AMD PCI control registers definitions. - */ - -#define AMD_PCI_MISC 0x48 - -#define AMD_PCI_MISC_SCI 0x04 /* deliver SCI */ -#define AMD_PCI_MISC_INT 0x02 /* deliver PCI IRQ */ -#define AMD_PCI_MISC_SPEEDUP 0x01 /* 16x clock speedup */ - -/* - * ACPI 2.0 chapter 13 PCI interface definitions. - */ - -#define AMD_EC_DATA 0x00 /* data register */ -#define AMD_EC_SC 0x04 /* status of controller */ -#define AMD_EC_CMD 0x04 /* command register */ -#define AMD_EC_ICR 0x08 /* interrupt control register */ - -#define AMD_EC_SC_SMI 0x04 /* smi event pending */ -#define AMD_EC_SC_SCI 0x02 /* sci event pending */ -#define AMD_EC_SC_BURST 0x01 /* burst mode enabled */ -#define AMD_EC_SC_CMD 0x08 /* byte in data reg is command */ -#define AMD_EC_SC_IBF 0x02 /* data ready for embedded controller */ -#define AMD_EC_SC_OBF 0x01 /* data ready for host */ - -#define AMD_EC_CMD_RD 0x80 /* read EC */ -#define AMD_EC_CMD_WR 0x81 /* write EC */ -#define AMD_EC_CMD_BE 0x82 /* enable burst mode */ -#define AMD_EC_CMD_BD 0x83 /* disable burst mode */ -#define AMD_EC_CMD_QR 0x84 /* query EC */ - -/* - * ACPI 2.0 chapter 13 access of registers of the EC - */ - -unsigned int amd_ec_wait_write(struct amd_smbus *smbus) -{ - int timeout = 500; - - while (timeout-- && (inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_IBF)) - udelay(1); - - if (!timeout) { - printk(KERN_WARNING "i2c-amd8111.c: Timeout while waiting for IBF to clear\n"); - return -1; - } - - return 0; -} - -unsigned int amd_ec_wait_read(struct amd_smbus *smbus) -{ - int timeout = 500; - - while (timeout-- && (~inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_OBF)) - udelay(1); - - if (!timeout) { - printk(KERN_WARNING "i2c-amd8111.c: Timeout while waiting for OBF to set\n"); - return -1; - } - - return 0; -} - -unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address, unsigned char *data) -{ - if (amd_ec_wait_write(smbus)) - return -1; - outb(AMD_EC_CMD_RD, smbus->base + AMD_EC_CMD); - - if (amd_ec_wait_write(smbus)) - return -1; - outb(address, smbus->base + AMD_EC_DATA); - - if (amd_ec_wait_read(smbus)) - return -1; - *data = inb(smbus->base + AMD_EC_DATA); - - return 0; -} - -unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address, unsigned char data) -{ - if (amd_ec_wait_write(smbus)) - return -1; - outb(AMD_EC_CMD_WR, smbus->base + AMD_EC_CMD); - - if (amd_ec_wait_write(smbus)) - return -1; - outb(address, smbus->base + AMD_EC_DATA); - - if (amd_ec_wait_write(smbus)) - return -1; - outb(data, smbus->base + AMD_EC_DATA); - - return 0; -} - -/* - * ACPI 2.0 chapter 13 SMBus 2.0 EC register model - */ - -#define AMD_SMB_PRTCL 0x00 /* protocol, PEC */ -#define AMD_SMB_STS 0x01 /* status */ -#define AMD_SMB_ADDR 0x02 /* address */ -#define AMD_SMB_CMD 0x03 /* command */ -#define AMD_SMB_DATA 0x04 /* 32 data registers */ -#define AMD_SMB_BCNT 0x24 /* number of data bytes */ -#define AMD_SMB_ALRM_A 0x25 /* alarm address */ -#define AMD_SMB_ALRM_D 0x26 /* 2 bytes alarm data */ - -#define AMD_SMB_STS_DONE 0x80 -#define AMD_SMB_STS_ALRM 0x40 -#define AMD_SMB_STS_RES 0x20 -#define AMD_SMB_STS_STATUS 0x1f - -#define AMD_SMB_STATUS_OK 0x00 -#define AMD_SMB_STATUS_FAIL 0x07 -#define AMD_SMB_STATUS_DNAK 0x10 -#define AMD_SMB_STATUS_DERR 0x11 -#define AMD_SMB_STATUS_CMD_DENY 0x12 -#define AMD_SMB_STATUS_UNKNOWN 0x13 -#define AMD_SMB_STATUS_ACC_DENY 0x17 -#define AMD_SMB_STATUS_TIMEOUT 0x18 -#define AMD_SMB_STATUS_NOTSUP 0x19 -#define AMD_SMB_STATUS_BUSY 0x1A -#define AMD_SMB_STATUS_PEC 0x1F - -#define AMD_SMB_PRTCL_WRITE 0x00 -#define AMD_SMB_PRTCL_READ 0x01 -#define AMD_SMB_PRTCL_QUICK 0x02 -#define AMD_SMB_PRTCL_BYTE 0x04 -#define AMD_SMB_PRTCL_BYTE_DATA 0x06 -#define AMD_SMB_PRTCL_WORD_DATA 0x08 -#define AMD_SMB_PRTCL_BLOCK_DATA 0x0a -#define AMD_SMB_PRTCL_PROC_CALL 0x0c -#define AMD_SMB_PRTCL_BLOCK_PROC_CALL 0x0d -#define AMD_SMB_PRTCL_I2C_BLOCK_DATA 0x4a -#define AMD_SMB_PRTCL_PEC 0x80 - - -s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, - char read_write, u8 command, int size, union i2c_smbus_data * data) -{ - struct amd_smbus *smbus = adap->algo_data; - unsigned char protocol, len, pec, temp[2]; - int i; - - protocol = (read_write == I2C_SMBUS_READ) ? AMD_SMB_PRTCL_READ : AMD_SMB_PRTCL_WRITE; - pec = (flags & I2C_CLIENT_PEC) ? AMD_SMB_PRTCL_PEC : 0; - - switch (size) { - - case I2C_SMBUS_QUICK: - protocol |= AMD_SMB_PRTCL_QUICK; - read_write = I2C_SMBUS_WRITE; - break; - - case I2C_SMBUS_BYTE: - if (read_write == I2C_SMBUS_WRITE) - amd_ec_write(smbus, AMD_SMB_CMD, command); - protocol |= AMD_SMB_PRTCL_BYTE; - break; - - case I2C_SMBUS_BYTE_DATA: - amd_ec_write(smbus, AMD_SMB_CMD, command); - if (read_write == I2C_SMBUS_WRITE) - amd_ec_write(smbus, AMD_SMB_DATA, data->byte); - protocol |= AMD_SMB_PRTCL_BYTE_DATA; - break; - - case I2C_SMBUS_WORD_DATA: - amd_ec_write(smbus, AMD_SMB_CMD, command); - if (read_write == I2C_SMBUS_WRITE) { - amd_ec_write(smbus, AMD_SMB_DATA, data->word & 0xff); - amd_ec_write(smbus, AMD_SMB_DATA + 1, data->word >> 8); - } - protocol |= AMD_SMB_PRTCL_WORD_DATA | pec; - break; - - case I2C_SMBUS_BLOCK_DATA: - amd_ec_write(smbus, AMD_SMB_CMD, command); - if (read_write == I2C_SMBUS_WRITE) { - len = min_t(u8, data->block[0], I2C_SMBUS_BLOCK_MAX); - amd_ec_write(smbus, AMD_SMB_BCNT, len); - for (i = 0; i < len; i++) - amd_ec_write(smbus, AMD_SMB_DATA + i, data->block[i + 1]); - } - protocol |= AMD_SMB_PRTCL_BLOCK_DATA | pec; - break; - - case I2C_SMBUS_I2C_BLOCK_DATA: - len = min_t(u8, data->block[0], I2C_SMBUS_BLOCK_MAX); - amd_ec_write(smbus, AMD_SMB_CMD, command); - amd_ec_write(smbus, AMD_SMB_BCNT, len); - if (read_write == I2C_SMBUS_WRITE) - for (i = 0; i < len; i++) - amd_ec_write(smbus, AMD_SMB_DATA + i, data->block[i + 1]); - protocol |= AMD_SMB_PRTCL_I2C_BLOCK_DATA; - break; - - case I2C_SMBUS_PROC_CALL: - amd_ec_write(smbus, AMD_SMB_CMD, command); - amd_ec_write(smbus, AMD_SMB_DATA, data->word & 0xff); - amd_ec_write(smbus, AMD_SMB_DATA + 1, data->word >> 8); - protocol = AMD_SMB_PRTCL_PROC_CALL | pec; - read_write = I2C_SMBUS_READ; - break; - - case I2C_SMBUS_BLOCK_PROC_CALL: - len = min_t(u8, data->block[0], I2C_SMBUS_BLOCK_MAX - 1); - amd_ec_write(smbus, AMD_SMB_CMD, command); - amd_ec_write(smbus, AMD_SMB_BCNT, len); - for (i = 0; i < len; i++) - amd_ec_write(smbus, AMD_SMB_DATA + i, data->block[i + 1]); - protocol = AMD_SMB_PRTCL_BLOCK_PROC_CALL | pec; - read_write = I2C_SMBUS_READ; - break; - - default: - printk(KERN_WARNING "i2c-amd8111.c: Unsupported transaction %d\n", size); - return -1; - } - - amd_ec_write(smbus, AMD_SMB_ADDR, addr << 1); - amd_ec_write(smbus, AMD_SMB_PRTCL, protocol); - - amd_ec_read(smbus, AMD_SMB_STS, temp + 0); - - if (~temp[0] & AMD_SMB_STS_DONE) { - udelay(500); - amd_ec_read(smbus, AMD_SMB_STS, temp + 0); - } - - if (~temp[0] & AMD_SMB_STS_DONE) { - i2c_delay(HZ/100); - amd_ec_read(smbus, AMD_SMB_STS, temp + 0); - } - - if ((~temp[0] & AMD_SMB_STS_DONE) || (temp[0] & AMD_SMB_STS_STATUS)) - return -1; - - if (read_write == I2C_SMBUS_WRITE) - return 0; - - switch (size) { - - case I2C_SMBUS_BYTE: - case I2C_SMBUS_BYTE_DATA: - amd_ec_read(smbus, AMD_SMB_DATA, &data->byte); - break; - - case I2C_SMBUS_WORD_DATA: - case I2C_SMBUS_PROC_CALL: - amd_ec_read(smbus, AMD_SMB_DATA, temp + 0); - amd_ec_read(smbus, AMD_SMB_DATA + 1, temp + 1); - data->word = (temp[1] << 8) | temp[0]; - break; - - case I2C_SMBUS_BLOCK_DATA: - case I2C_SMBUS_BLOCK_PROC_CALL: - amd_ec_read(smbus, AMD_SMB_BCNT, &len); - len = min_t(u8, len, I2C_SMBUS_BLOCK_MAX); - case I2C_SMBUS_I2C_BLOCK_DATA: - for (i = 0; i < len; i++) - amd_ec_read(smbus, AMD_SMB_DATA + i, data->block + i + 1); - data->block[0] = len; - break; - } - - return 0; -} - -static void amd8111_inc(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -static void amd8111_dec(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - -u32 amd8111_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA | - I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_PROC_CALL | - I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HWPEC_CALC; -} - -static struct i2c_algorithm smbus_algorithm = { - .name = "Non-I2C SMBus 2.0 adapter", - .id = I2C_ALGO_SMBUS, - .smbus_xfer = amd8111_access, - .functionality = amd8111_func, -}; - - -static struct pci_device_id amd8111_ids[] __devinitdata = { - { 0x1022, 0x746a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { 0, } -}; - -static int __devinit amd8111_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - struct amd_smbus *smbus; - int error; - - if (!(pci_resource_flags(dev, 0) & IORESOURCE_IO)) - return -ENODEV; - - if (!(smbus = kmalloc(sizeof(struct amd_smbus), GFP_KERNEL))) - return -ENOMEM; - memset(smbus, 0, sizeof(struct amd_smbus)); - - pci_set_drvdata(dev, smbus); - smbus->dev = dev; - smbus->base = pci_resource_start(dev, 0); - smbus->size = pci_resource_len(dev, 0); - - if (!request_region(smbus->base, smbus->size, amd8111_driver.name)) { - kfree(smbus); - return -EBUSY; - } - - sprintf(smbus->adapter.name, "SMBus2 AMD8111 adapter at %04x", smbus->base); - smbus->adapter.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_AMD8111; - smbus->adapter.algo = &smbus_algorithm; - smbus->adapter.algo_data = smbus; - smbus->adapter.inc_use = amd8111_inc; - smbus->adapter.dec_use = amd8111_dec; - - pci_write_config_dword(smbus->dev, AMD_PCI_MISC, 0); - - error = i2c_add_adapter(&smbus->adapter); - if (error) { - printk(KERN_WARNING "i2c-amd8111.c: Failed to register adapter.\n"); - release_region(smbus->base, smbus->size); - kfree(smbus); - return error; - } - - printk(KERN_INFO "i2c-amd8111.c: AMD8111 SMBus 2.0 adapter at %#x\n", smbus->base); - return 0; -} - - -static void __devexit amd8111_remove(struct pci_dev *dev) -{ - struct amd_smbus *smbus = (void*) pci_get_drvdata(dev); - i2c_del_adapter(&smbus->adapter); - release_region(smbus->base, smbus->size); - kfree(smbus); -} - -static struct pci_driver amd8111_driver = { - .name = "amd8111 smbus 2.0", - .id_table = amd8111_ids, - .probe = amd8111_probe, - .remove = __devexit_p(amd8111_remove), -}; - -static int __init i2c_amd8111_init(void) -{ - printk(KERN_INFO "i2c-amd8111.o version %s (%s)\n", LM_VERSION, LM_DATE); - return pci_module_init(&amd8111_driver); -} - - -static void __exit i2c_amd8111_exit(void) -{ - pci_unregister_driver(&amd8111_driver); -} - -module_init(i2c_amd8111_init); -module_exit(i2c_amd8111_exit); diff --git a/kernel/busses/i2c-hydra.c b/kernel/busses/i2c-hydra.c deleted file mode 100644 index eb904e9f..00000000 --- a/kernel/busses/i2c-hydra.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - i2c-hydra.c - Part of lm_sensors, Linux kernel modules - for hardware monitoring - - i2c Support for the Apple `Hydra' Mac I/O - - Copyright (c) 1999 Geert Uytterhoeven - - Based on i2c Support for Via Technologies 82C586B South Bridge - Copyright (c) 1998, 1999 Kyösti Mälkki - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for HZ */ -#include "sensors_compat.h" - -MODULE_LICENSE("GPL"); - - -#define HYDRA_CACHE_PD 0x00000030 - -#define HYDRA_CPD_PD0 0x00000001 /* CachePD lines */ -#define HYDRA_CPD_PD1 0x00000002 -#define HYDRA_CPD_PD2 0x00000004 -#define HYDRA_CPD_PD3 0x00000008 - -#define HYDRA_SCLK HYDRA_CPD_PD0 -#define HYDRA_SDAT HYDRA_CPD_PD1 -#define HYDRA_SCLK_OE 0x00000010 -#define HYDRA_SDAT_OE 0x00000020 - -static unsigned long hydra_base; - -static inline void pdregw(u32 val) -{ - writel(val, hydra_base + HYDRA_CACHE_PD); -} - -static inline u32 pdregr(void) -{ - u32 val = readl(hydra_base + HYDRA_CACHE_PD); - return val; -} - -static void bit_hydra_setscl(void *data, int state) -{ - u32 val = pdregr(); - if (state) - val &= ~HYDRA_SCLK_OE; - else { - val &= ~HYDRA_SCLK; - val |= HYDRA_SCLK_OE; - } - pdregw(val); - pdregr(); /* flush posted write */ -} - -static void bit_hydra_setsda(void *data, int state) -{ - u32 val = pdregr(); - if (state) - val &= ~HYDRA_SDAT_OE; - else { - val &= ~HYDRA_SDAT; - val |= HYDRA_SDAT_OE; - } - pdregw(val); - pdregr(); /* flush posted write */ -} - -static int bit_hydra_getscl(void *data) -{ - return (pdregr() & HYDRA_SCLK) != 0; -} - -static int bit_hydra_getsda(void *data) -{ - return (pdregr() & HYDRA_SDAT) != 0; -} - -static void bit_hydra_inc(struct i2c_adapter *adap) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -static void bit_hydra_dec(struct i2c_adapter *adap) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - -/* ------------------------------------------------------------------------ */ - -static struct i2c_algo_bit_data bit_hydra_data = { - .setsda = bit_hydra_setsda, - .setscl = bit_hydra_setscl, - .getsda = bit_hydra_getsda, - .getscl = bit_hydra_getscl, - .udelay = 5, - .mdelay = 5, - .timeout = HZ -}; - -static struct i2c_adapter bit_hydra_ops = { - .name = "Hydra i2c", - .id = I2C_HW_B_HYDRA, - .algo_data = &bit_hydra_data, - .inc_use = bit_hydra_inc, - .dec_use = bit_hydra_dec, -}; - -static struct pci_device_id hydra_ids[] __devinitdata = { - { - .vendor = PCI_VENDOR_ID_APPLE, - .device = PCI_DEVICE_ID_APPLE_HYDRA, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { 0, } -}; - -static int __devinit hydra_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - unsigned int base_addr; - - base_addr = dev->resource[0].start; - hydra_base = (unsigned long) ioremap(base_addr, 0x100); - - pdregw(0); /* clear SCLK_OE and SDAT_OE */ - return i2c_bit_add_bus(&bit_hydra_ops); -} - -static void __devexit hydra_remove(struct pci_dev *dev) -{ - pdregw(0); /* clear SCLK_OE and SDAT_OE */ - i2c_bit_del_bus(&bit_hydra_ops); - iounmap((void *) hydra_base); -} - - -static struct pci_driver hydra_driver = { - .name = "hydra smbus", - .id_table = hydra_ids, - .probe = hydra_probe, - .remove = __devexit_p(hydra_remove), -}; - -static int __init i2c_hydra_init(void) -{ - return pci_module_init(&hydra_driver); -} - - -static void __exit i2c_hydra_exit(void) -{ - pci_unregister_driver(&hydra_driver); -} - - - -MODULE_AUTHOR("Geert Uytterhoeven "); -MODULE_DESCRIPTION("i2c for Apple Hydra Mac I/O"); - -module_init(i2c_hydra_init); -module_exit(i2c_hydra_exit); - diff --git a/kernel/busses/i2c-i801.c b/kernel/busses/i2c-i801.c deleted file mode 100644 index a85889ef..00000000 --- a/kernel/busses/i2c-i801.c +++ /dev/null @@ -1,737 +0,0 @@ -/* - i2c-i801.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998 - 2002 Frodo Looijaard , - Philip Edelbrock , and Mark D. Studebaker - - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - SUPPORTED DEVICES PCI ID - 82801AA 2413 - 82801AB 2423 - 82801BA 2443 - 82801CA/CAM 2483 - 82801DB 24C3 (HW PEC supported, 32 byte buffer not supported) - 82801EB 24D3 (HW PEC supported, 32 byte buffer not supported) - 6300ESB 25A4 ("") - ICH6 266A ("") - ICH7 27DA ("") - ESB2 269B ("") - ICH8 283E ("") - ICH9 2930 ("") - - This driver supports several versions of Intel's I/O Controller Hubs (ICH). - For SMBus support, they are similar to the PIIX4 and are part - of Intel's '810' and other chipsets. - See the doc/busses/i2c-i801 file for details. - I2C Block Read supported for ICH5 and higher. - Block Process Call are not supported. -*/ - -/* Note: we assume there can only be one I801, with one SMBus interface */ - -/* #define DEBUG 1 */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "version.h" -#include "sensors_compat.h" - -/* 82801CA is undefined before kernel 2.4.13 */ -#ifndef PCI_DEVICE_ID_INTEL_82801CA_3 -#define PCI_DEVICE_ID_INTEL_82801CA_3 0x2483 -#endif - -/* 82801DB is undefined before kernel 2.4.19 */ -#ifndef PCI_DEVICE_ID_INTEL_82801DB_3 -#define PCI_DEVICE_ID_INTEL_82801DB_3 0x24c3 -#endif - -/* 82801EB is undefined before kernel 2.4.21 */ -#ifndef PCI_DEVICE_ID_INTEL_82801EB_3 -#define PCI_DEVICE_ID_INTEL_82801EB_3 0x24d3 -#endif - -/* ESB is undefined before kernel 2.4.22 */ -#ifndef PCI_DEVICE_ID_INTEL_ESB_4 -#define PCI_DEVICE_ID_INTEL_ESB_4 0x25a4 -#endif - -/* ESB2 - Enterprise Southbridge is undefined */ -#ifndef PCI_DEVICE_ID_INTEL_ESB2_17 -#define PCI_DEVICE_ID_INTEL_ESB2_17 0x269b -#endif - -/* ICH6 is undefined */ -#ifndef PCI_DEVICE_ID_INTEL_ICH6_16 -#define PCI_DEVICE_ID_INTEL_ICH6_16 0x266a -#endif - -/* ICH7 is undefined */ -#ifndef PCI_DEVICE_ID_INTEL_ICH7_17 -#define PCI_DEVICE_ID_INTEL_ICH7_17 0x27da -#endif - -/* ICH8 is undefined */ -#ifndef PCI_DEVICE_ID_INTEL_ICH8_5 -#define PCI_DEVICE_ID_INTEL_ICH8_5 0x283e -#endif - -/* ICH9 is undefined */ -#ifndef PCI_DEVICE_ID_INTEL_ICH9_6 -#define PCI_DEVICE_ID_INTEL_ICH9_6 0x2930 -#endif - -#ifdef I2C_CLIENT_PEC -#define HAVE_PEC -#endif - -/* I801 SMBus address offsets */ -#define SMBHSTSTS (0 + i801_smba) -#define SMBHSTCNT (2 + i801_smba) -#define SMBHSTCMD (3 + i801_smba) -#define SMBHSTADD (4 + i801_smba) -#define SMBHSTDAT0 (5 + i801_smba) -#define SMBHSTDAT1 (6 + i801_smba) -#define SMBBLKDAT (7 + i801_smba) -#define SMBPEC (8 + i801_smba) /* ICH4 only */ -#define SMBAUXSTS (12 + i801_smba) /* ICH4 only */ -#define SMBAUXCTL (13 + i801_smba) /* ICH4 only */ - -/* PCI Address Constants */ -#define SMBBA 0x020 -#define SMBHSTCFG 0x040 -#define SMBREV 0x008 - -/* Host configuration bits for SMBHSTCFG */ -#define SMBHSTCFG_HST_EN 1 -#define SMBHSTCFG_SMB_SMI_EN 2 -#define SMBHSTCFG_I2C_EN 4 - -/* Other settings */ -#define MAX_TIMEOUT 100 -#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */ - -/* I801 command constants */ -#define I801_QUICK 0x00 -#define I801_BYTE 0x04 -#define I801_BYTE_DATA 0x08 -#define I801_WORD_DATA 0x0C -#define I801_PROC_CALL 0x10 /* later chips only, unimplemented */ -#define I801_BLOCK_DATA 0x14 -#define I801_I2C_BLOCK_DATA 0x18 /* ich4 and later */ -#define I801_BLOCK_LAST 0x34 -#define I801_I2C_BLOCK_LAST 0x38 /* unimplemented */ -#define I801_START 0x40 -#define I801_PEC_EN 0x80 /* ich4 and later */ - -/* insmod parameters */ - -/* If force_addr is set to anything different from 0, we forcibly enable - the I801 at the given address. VERY DANGEROUS! */ -static int force_addr = 0; -MODULE_PARM(force_addr, "i"); -MODULE_PARM_DESC(force_addr, - "Forcibly enable the I801 at the given address. " - "EXTREMELY DANGEROUS!"); - -static int i801_transaction(void); -static int i801_block_transaction(union i2c_smbus_data *data, char read_write, - int command, int hwpec); - -static unsigned short i801_smba; -static struct pci_driver i801_driver; -static struct pci_dev *I801_dev; -static int isich4; /* is PEC supported? */ -static int isich5; /* is i2c block read supported? */ - -static int __devinit i801_setup(struct pci_dev *dev) -{ - unsigned char temp; - - I801_dev = dev; - if (dev->device == PCI_DEVICE_ID_INTEL_82801DB_3 || - dev->device == PCI_DEVICE_ID_INTEL_82801EB_3 || - dev->device == PCI_DEVICE_ID_INTEL_ESB_4 || - dev->device == PCI_DEVICE_ID_INTEL_ESB2_17 || - dev->device == PCI_DEVICE_ID_INTEL_ICH6_16 || - dev->device == PCI_DEVICE_ID_INTEL_ICH7_17 || - dev->device == PCI_DEVICE_ID_INTEL_ICH8_5 || - dev->device == PCI_DEVICE_ID_INTEL_ICH9_6) - isich4 = 1; - else - isich4 = 0; - isich5 = isich4 && dev->device != PCI_DEVICE_ID_INTEL_82801DB_3; - - /* Determine the address of the SMBus area */ - if (force_addr) { - i801_smba = force_addr & 0xfff0; - } else { - pci_read_config_word(I801_dev, SMBBA, &i801_smba); - i801_smba &= 0xfff0; - if(i801_smba == 0) { - dev_err(dev, "SMB base address uninitialized " - "- upgrade BIOS or use force_addr=0xaddr\n"); - return -ENODEV; - } - } - - if (!request_region(i801_smba, (isich4 ? 16 : 8), i801_driver.name)) { - dev_err(dev, "I801_smb region 0x%x already in use!\n", - i801_smba); - return -EBUSY; - } - - pci_read_config_byte(I801_dev, SMBHSTCFG, &temp); - temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */ - pci_write_config_byte(I801_dev, SMBHSTCFG, temp); - - /* If force_addr is set, we program the new address here. Just to make - sure, we disable the device first. */ - if (force_addr) { - pci_write_config_byte(I801_dev, SMBHSTCFG, - temp & ~SMBHSTCFG_HST_EN); - pci_write_config_word(I801_dev, SMBBA, i801_smba); - pci_write_config_byte(I801_dev, SMBHSTCFG, - temp | SMBHSTCFG_HST_EN); - dev_warn(dev, "WARNING: I801 SMBus interface set to " - "new address %04x!\n", i801_smba); - } else if (!(temp & SMBHSTCFG_HST_EN)) { - pci_write_config_byte(I801_dev, SMBHSTCFG, - temp | SMBHSTCFG_HST_EN); - dev_warn(dev, "enabling SMBus device\n"); - } - - if (temp & SMBHSTCFG_SMB_SMI_EN) - dev_dbg(dev, "I801 using Interrupt SMI# for SMBus.\n"); - else - dev_dbg(dev, "I801 using PCI Interrupt for SMBus.\n"); - - pci_read_config_byte(I801_dev, SMBREV, &temp); - dev_dbg(dev, "SMBREV = 0x%X\n", temp); - dev_dbg(dev, "I801_smba = 0x%X\n", i801_smba); - - return 0; -} - - -static int i801_transaction(void) -{ - int temp; - int result = 0; - int timeout = 0; - - dev_dbg(I801_dev, "Transaction (pre): CNT=%02x, CMD=%02x, " - "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), - inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), - inb_p(SMBHSTDAT1)); - - /* Make sure the SMBus host is ready to start transmitting */ - /* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ - if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { - dev_dbg(I801_dev, "SMBus busy (%02x). Resetting...\n", - temp); - outb_p(temp, SMBHSTSTS); - if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { - dev_dbg(I801_dev, "Failed! (%02x)\n", temp); - return -1; - } else { - dev_dbg(I801_dev, "Successful!\n"); - } - } - - outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT); - - /* We will always wait for a fraction of a second! */ - do { - i2c_delay(1); - temp = inb_p(SMBHSTSTS); - } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT)); - - /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { - dev_dbg(I801_dev, "SMBus Timeout!\n"); - result = -1; - } - - if (temp & 0x10) { - result = -1; - dev_dbg(I801_dev, "Error: Failed bus transaction\n"); - } - - if (temp & 0x08) { - result = -1; - dev_err(I801_dev, "Bus collision! SMBus may be locked " - "until next hard reset. (sorry!)\n"); - /* Clock stops and slave is stuck in mid-transmission */ - } - - if (temp & 0x04) { - result = -1; - dev_dbg(I801_dev, "Error: no response!\n"); - } - - if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00) - outb_p(inb(SMBHSTSTS), SMBHSTSTS); - - if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { - dev_dbg(I801_dev, "Failed reset at end of transaction " - "(%02x)\n", temp); - } - dev_dbg(I801_dev, "Transaction (post): CNT=%02x, CMD=%02x, " - "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), - inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), - inb_p(SMBHSTDAT1)); - return result; -} - -/* All-inclusive block transaction function */ -static int i801_block_transaction(union i2c_smbus_data *data, char read_write, - int command, int hwpec) -{ - int i, len; - int smbcmd; - int temp; - int result = 0; - int timeout; - unsigned char hostc, errmask; - - if (command == I2C_SMBUS_I2C_BLOCK_DATA) { - if (read_write == I2C_SMBUS_WRITE) { - /* set I2C_EN bit in configuration register */ - pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc); - pci_write_config_byte(I801_dev, SMBHSTCFG, - hostc | SMBHSTCFG_I2C_EN); - } else if (!isich5) { - dev_err(I801_dev, - "I2C_SMBUS_I2C_BLOCK_READ unsupported!\n"); - return -1; - } - } - - if (read_write == I2C_SMBUS_WRITE) { - len = data->block[0]; - if (len < 1) - len = 1; - if (len > 32) - len = 32; - outb_p(len, SMBHSTDAT0); - outb_p(data->block[1], SMBBLKDAT); - } else { - len = 32; /* max for reads */ - } - - if(isich4 && command != I2C_SMBUS_I2C_BLOCK_DATA) { - /* set 32 byte buffer */ - } - - for (i = 1; i <= len; i++) { - if (i == len && read_write == I2C_SMBUS_READ) - smbcmd = I801_BLOCK_LAST; - else if (command == I2C_SMBUS_I2C_BLOCK_DATA && - read_write == I2C_SMBUS_READ) - smbcmd = I801_I2C_BLOCK_DATA; - else - smbcmd = I801_BLOCK_DATA; - outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT); - - dev_dbg(I801_dev, "Block (pre %d): CNT=%02x, CMD=%02x, " - "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i, - inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), - inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT)); - - /* Make sure the SMBus host is ready to start transmitting */ - temp = inb_p(SMBHSTSTS); - if (i == 1) { - /* Erronenous conditions before transaction: - * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ - errmask=0x9f; - } else { - /* Erronenous conditions during transaction: - * Failed, Bus_Err, Dev_Err, Intr */ - errmask=0x1e; - } - if (temp & errmask) { - dev_dbg(I801_dev, "SMBus busy (%02x). " - "Resetting...\n", temp); - outb_p(temp, SMBHSTSTS); - if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) { - dev_err(I801_dev, - "Reset failed! (%02x)\n", temp); - result = -1; - goto END; - } - if (i != 1) { - /* if die in middle of block transaction, fail */ - result = -1; - goto END; - } - } - - if (i == 1) - outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT); - - /* We will always wait for a fraction of a second! */ - timeout = 0; - do { - i2c_delay(1); - temp = inb_p(SMBHSTSTS); - } - while ((!(temp & 0x80)) - && (timeout++ < MAX_TIMEOUT)); - - /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { - result = -1; - dev_dbg(I801_dev, "SMBus Timeout!\n"); - } - - if (temp & 0x10) { - result = -1; - dev_dbg(I801_dev, - "Error: Failed bus transaction\n"); - } else if (temp & 0x08) { - result = -1; - dev_err(I801_dev, "Bus collision!\n"); - } else if (temp & 0x04) { - result = -1; - dev_dbg(I801_dev, "Error: no response!\n"); - } - - if (i == 1 && read_write == I2C_SMBUS_READ) { - if (command != I2C_SMBUS_I2C_BLOCK_DATA) { - len = inb_p(SMBHSTDAT0); - if (len < 1) - len = 1; - if (len > 32) - len = 32; - data->block[0] = len; - } else { - /* if slave returns < 32 bytes transaction will fail */ - data->block[0] = 32; - } - } - - /* Retrieve/store value in SMBBLKDAT */ - if (read_write == I2C_SMBUS_READ) - data->block[i] = inb_p(SMBBLKDAT); - if (read_write == I2C_SMBUS_WRITE && i+1 <= len) - outb_p(data->block[i+1], SMBBLKDAT); - if ((temp & 0x9e) != 0x00) - outb_p(temp, SMBHSTSTS); /* signals SMBBLKDAT ready */ - - if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) { - dev_dbg(I801_dev, - "Bad status (%02x) at end of transaction\n", - temp); - } - dev_dbg(I801_dev, "Block (post %d): CNT=%02x, CMD=%02x, " - "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i, - inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), - inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT)); - - if (result < 0) - goto END; - } - - if (hwpec) { - /* wait for INTR bit as advised by Intel */ - timeout = 0; - do { - i2c_delay(1); - temp = inb_p(SMBHSTSTS); - } while ((!(temp & 0x02)) - && (timeout++ < MAX_TIMEOUT)); - - if (timeout >= MAX_TIMEOUT) { - dev_dbg(I801_dev, "PEC Timeout!\n"); - } - outb_p(temp, SMBHSTSTS); - } - result = 0; -END: - if (command == I2C_SMBUS_I2C_BLOCK_DATA && - read_write == I2C_SMBUS_WRITE) { - /* restore saved configuration register value */ - pci_write_config_byte(I801_dev, SMBHSTCFG, hostc); - } - return result; -} - -/* Return -1 on error. */ -static s32 i801_access(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, u8 command, - int size, union i2c_smbus_data * data) -{ - int hwpec = 0; - int block = 0; - int ret, xact = 0; - -#ifdef HAVE_PEC - hwpec = isich4 && (flags & I2C_CLIENT_PEC) - && size != I2C_SMBUS_QUICK - && size != I2C_SMBUS_I2C_BLOCK_DATA; -#endif - - switch (size) { - case I2C_SMBUS_QUICK: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - xact = I801_QUICK; - break; - case I2C_SMBUS_BYTE: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - if (read_write == I2C_SMBUS_WRITE) - outb_p(command, SMBHSTCMD); - xact = I801_BYTE; - break; - case I2C_SMBUS_BYTE_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) - outb_p(data->byte, SMBHSTDAT0); - xact = I801_BYTE_DATA; - break; - case I2C_SMBUS_WORD_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) { - outb_p(data->word & 0xff, SMBHSTDAT0); - outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); - } - xact = I801_WORD_DATA; - break; - case I2C_SMBUS_BLOCK_DATA: - case I2C_SMBUS_I2C_BLOCK_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - outb_p(command, SMBHSTCMD); - block = 1; - break; - case I2C_SMBUS_PROC_CALL: - default: - dev_err(I801_dev, "Unsupported transaction %d\n", size); - return -1; - } - - outb_p(hwpec, SMBAUXCTL); /* enable/disable hardware PEC */ - - if(block) - ret = i801_block_transaction(data, read_write, size, hwpec); - else { - outb_p(xact | ENABLE_INT9, SMBHSTCNT); - ret = i801_transaction(); - } - - /* Some BIOSes don't like it when PEC is enabled at reboot or resume - time, so we forcibly disable it after every transaction. */ - if (hwpec) - outb_p(0, SMBAUXCTL); - - if(block) - return ret; - if(ret) - return -1; - if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK)) - return 0; - - switch (xact & 0x7f) { - case I801_BYTE: /* Result put in SMBHSTDAT0 */ - case I801_BYTE_DATA: - data->byte = inb_p(SMBHSTDAT0); - break; - case I801_WORD_DATA: - data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); - break; - } - return 0; -} - -static void i801_inc(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -static void i801_dec(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - -static u32 i801_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK -#ifdef HAVE_PEC - | (isich4 ? I2C_FUNC_SMBUS_HWPEC_CALC : 0) -#endif -#if 0 - | (isich5 ? I2C_FUNC_SMBUS_READ_I2C_BLOCK - : 0) -#endif - ; -} - -static struct i2c_algorithm smbus_algorithm = { - .name = "Non-I2C SMBus adapter", - .id = I2C_ALGO_SMBUS, - .smbus_xfer = i801_access, - .functionality = i801_func, -}; - -static struct i2c_adapter i801_adapter = { - .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_I801, - .algo = &smbus_algorithm, - .inc_use = i801_inc, - .dec_use = i801_dec, -}; - -static struct pci_device_id i801_ids[] __devinitdata = { - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801AA_3, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801AB_3, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801BA_2, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801CA_3, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801DB_3, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801EB_3, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_ESB_4, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_ESB2_17, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_ICH6_16, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_ICH7_17, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_ICH8_5, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_ICH9_6, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { 0, } -}; - -static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - int err; - - if ((err = i801_setup(dev))) - return err; - - snprintf(i801_adapter.name, 32, - "SMBus I801 adapter at %04x", i801_smba); - return i2c_add_adapter(&i801_adapter); -} - -static void __devexit i801_remove(struct pci_dev *dev) -{ - i2c_del_adapter(&i801_adapter); - release_region(i801_smba, (isich4 ? 16 : 8)); -} - -static struct pci_driver i801_driver = { - .name = "i801 smbus", - .id_table = i801_ids, - .probe = i801_probe, - .remove = __devexit_p(i801_remove), -}; - -static int __init i2c_i801_init(void) -{ - printk(KERN_INFO "i2c-i801 version %s (%s)\n", LM_VERSION, LM_DATE); - return pci_module_init(&i801_driver); -} - -static void __exit i2c_i801_exit(void) -{ - pci_unregister_driver(&i801_driver); -} - -MODULE_AUTHOR ("Frodo Looijaard , " - "Philip Edelbrock , " - "and Mark D. Studebaker "); -MODULE_DESCRIPTION("I801 SMBus driver"); -MODULE_LICENSE("GPL"); - -module_init(i2c_i801_init); -module_exit(i2c_i801_exit); diff --git a/kernel/busses/i2c-i810.c b/kernel/busses/i2c-i810.c deleted file mode 100644 index 804890ee..00000000 --- a/kernel/busses/i2c-i810.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - i2c-i810.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998, 1999, 2000 Frodo Looijaard , - Philip Edelbrock , - Ralph Metzler , and - Mark D. Studebaker - - Based on code written by Ralph Metzler and - Simon Vogl - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ -/* - This interfaces to the I810/I815 to provide access to - the DDC Bus and the I2C Bus. - - SUPPORTED DEVICES PCI ID - i810AA 7121 - i810AB 7123 - i810E 7125 - i815 1132 - i845G 2562 -*/ - - -#include -#include -#include -#include -#include -#include -#include /* for HZ */ -#include "version.h" -#include "sensors_compat.h" - -MODULE_LICENSE("GPL"); - -/* Not defined by any Linux 2.4 kernel */ -#define PCI_DEVICE_ID_INTEL_82810E_IG 0x7125 -#define PCI_DEVICE_ID_INTEL_82815_CGC 0x1132 -#define PCI_DEVICE_ID_INTEL_82845G_IG 0x2562 - -/* GPIO register locations */ -#define I810_IOCONTROL_OFFSET 0x5000 -#define I810_HVSYNC 0x00 /* not used */ -#define I810_GPIOA 0x10 -#define I810_GPIOB 0x14 - -/* bit locations in the registers */ -#define SCL_DIR_MASK 0x0001 -#define SCL_DIR 0x0002 -#define SCL_VAL_MASK 0x0004 -#define SCL_VAL_OUT 0x0008 -#define SCL_VAL_IN 0x0010 -#define SDA_DIR_MASK 0x0100 -#define SDA_DIR 0x0200 -#define SDA_VAL_MASK 0x0400 -#define SDA_VAL_OUT 0x0800 -#define SDA_VAL_IN 0x1000 - -/* initialization states */ -#define INIT1 0x1 -#define INIT2 0x2 -#define INIT3 0x4 - -/* delays */ -#define CYCLE_DELAY 10 -#define TIMEOUT (HZ / 2) - - -static void config_i810(struct pci_dev *dev); - - -static unsigned long ioaddr; - -/* The i810 GPIO registers have individual masks for each bit - so we never have to read before writing. Nice. */ - -static void bit_i810i2c_setscl(void *data, int val) -{ - writel((val ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK, - ioaddr + I810_GPIOB); - readl(ioaddr + I810_GPIOB); /* flush posted write */ -} - -static void bit_i810i2c_setsda(void *data, int val) -{ - writel((val ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK, - ioaddr + I810_GPIOB); - readl(ioaddr + I810_GPIOB); /* flush posted write */ -} - -/* The GPIO pins are open drain, so the pins could always remain outputs. - However, some chip versions don't latch the inputs unless they - are set as inputs. - We rely on the i2c-algo-bit routines to set the pins high before - reading the input from other chips. Following guidance in the 815 - prog. ref. guide, we do a "dummy write" of 0 to the register before - reading which forces the input value to be latched. We presume this - applies to the 810 as well; shouldn't hurt anyway. This is necessary to get - i2c_algo_bit bit_test=1 to pass. */ - -static int bit_i810i2c_getscl(void *data) -{ - writel(SCL_DIR_MASK, ioaddr + I810_GPIOB); - writel(0, ioaddr + I810_GPIOB); - return (0 != (readl(ioaddr + I810_GPIOB) & SCL_VAL_IN)); -} - -static int bit_i810i2c_getsda(void *data) -{ - writel(SDA_DIR_MASK, ioaddr + I810_GPIOB); - writel(0, ioaddr + I810_GPIOB); - return (0 != (readl(ioaddr + I810_GPIOB) & SDA_VAL_IN)); -} - -static void bit_i810ddc_setscl(void *data, int val) -{ - writel((val ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK, - ioaddr + I810_GPIOA); - readl(ioaddr + I810_GPIOA); /* flush posted write */ -} - -static void bit_i810ddc_setsda(void *data, int val) -{ - writel((val ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK, - ioaddr + I810_GPIOA); - readl(ioaddr + I810_GPIOA); /* flush posted write */ -} - -static int bit_i810ddc_getscl(void *data) -{ - writel(SCL_DIR_MASK, ioaddr + I810_GPIOA); - writel(0, ioaddr + I810_GPIOA); - return (0 != (readl(ioaddr + I810_GPIOA) & SCL_VAL_IN)); -} - -static int bit_i810ddc_getsda(void *data) -{ - writel(SDA_DIR_MASK, ioaddr + I810_GPIOA); - writel(0, ioaddr + I810_GPIOA); - return (0 != (readl(ioaddr + I810_GPIOA) & SDA_VAL_IN)); -} - - -/* Configures the chip */ -void config_i810(struct pci_dev *dev) -{ - unsigned long cadr; - - /* map I810 memory */ - cadr = dev->resource[1].start; - cadr += I810_IOCONTROL_OFFSET; - cadr &= PCI_BASE_ADDRESS_MEM_MASK; - ioaddr = (unsigned long)ioremap_nocache(cadr, 0x1000); - if(ioaddr) { - bit_i810i2c_setscl(NULL, 1); - bit_i810i2c_setsda(NULL, 1); - bit_i810ddc_setscl(NULL, 1); - bit_i810ddc_setsda(NULL, 1); - } -} - -static void i810_inc(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -static void i810_dec(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - -static struct i2c_algo_bit_data i810_i2c_bit_data = { - .setsda = bit_i810i2c_setsda, - .setscl = bit_i810i2c_setscl, - .getsda = bit_i810i2c_getsda, - .getscl = bit_i810i2c_getscl, - .udelay = CYCLE_DELAY, - .mdelay = CYCLE_DELAY, - .timeout = TIMEOUT, -}; - -static struct i2c_adapter i810_i2c_adapter = { - .name = "I810/I815 I2C Adapter", - .id = I2C_HW_B_I810, - .algo_data = &i810_i2c_bit_data, - .inc_use = i810_inc, - .dec_use = i810_dec, -}; - -static struct i2c_algo_bit_data i810_ddc_bit_data = { - .setsda = bit_i810ddc_setsda, - .setscl = bit_i810ddc_setscl, - .getsda = bit_i810ddc_getsda, - .getscl = bit_i810ddc_getscl, - .udelay = CYCLE_DELAY, - .mdelay = CYCLE_DELAY, - .timeout = TIMEOUT, -}; - -static struct i2c_adapter i810_ddc_adapter = { - .name = "I810/I815 DDC Adapter", - .id = I2C_HW_B_I810, - .algo_data = &i810_ddc_bit_data, - .inc_use = i810_inc, - .dec_use = i810_dec, -}; - - -static struct pci_device_id i810_ids[] __devinitdata = { - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82810_IG1, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82810_IG3, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82810E_IG, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82815_CGC, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82845G_IG, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { 0, } -}; - -static int __devinit i810_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - int retval; - - config_i810(dev); - printk("i2c-i810.o: i810/i815 found.\n"); - - retval = i2c_bit_add_bus(&i810_i2c_adapter); - if(retval) - return retval; - retval = i2c_bit_add_bus(&i810_ddc_adapter); - if(retval) - i2c_bit_del_bus(&i810_i2c_adapter); - return retval; -} - -static void __devexit i810_remove(struct pci_dev *dev) -{ - i2c_bit_del_bus(&i810_ddc_adapter); - i2c_bit_del_bus(&i810_i2c_adapter); -} - - -/* Don't register driver to avoid driver conflicts */ -/* -static struct pci_driver i810_driver = { - .name = "i810 smbus", - .id_table = i810_ids, - .probe = i810_probe, - .remove = __devexit_p(i810_remove), -}; -*/ - -static int __init i2c_i810_init(void) -{ - struct pci_dev *dev; - const struct pci_device_id *id; - - printk("i2c-i810.o version %s (%s)\n", LM_VERSION, LM_DATE); -/* - return pci_module_init(&i810_driver); -*/ - pci_for_each_dev(dev) { - id = pci_match_device(i810_ids, dev); - if(id) - if(i810_probe(dev, id) >= 0) - return 0; - } - return -ENODEV; -} - -static void __exit i2c_i810_exit(void) -{ -/* - pci_unregister_driver(&i810_driver); -*/ - i810_remove(NULL); - iounmap((void *)ioaddr); -} - -MODULE_AUTHOR - ("Frodo Looijaard , Philip Edelbrock , Ralph Metzler , and Mark D. Studebaker "); -MODULE_DESCRIPTION("I810/I815 I2C/DDC driver"); - -module_init(i2c_i810_init); -module_exit(i2c_i810_exit); diff --git a/kernel/busses/i2c-ipmb.c b/kernel/busses/i2c-ipmb.c deleted file mode 100644 index b11b0d0b..00000000 --- a/kernel/busses/i2c-ipmb.c +++ /dev/null @@ -1,380 +0,0 @@ -/* - i2c-ipmb.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 2002 Mark D. Studebaker - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - THIS DOESN'T WORK YET - DON'T BOTHER TRYING IT. - This implements an i2c adapter for the BMC IPMB. -*/ - -#include -#include -#include -#include -#include -#include "version.h" - - -static u32 i2c_ipmb_func(struct i2c_adapter *adapter); -int ipmb_access(struct i2c_adapter *adap,struct i2c_msg msgs[], - int num); - - -/* I2C Data */ -static struct i2c_algorithm i2c_ipmb_algorithm = { - .name = "IPMB algorithm", - .id = I2C_ALGO_IPMB, - .master_xfer = ipmb_access, - .functionality = i2c_ipmb_func, -}; - -#define MAX_IPMB_ADAPTERS 8 -static struct i2c_adapter i2c_ipmb_adapter[MAX_IPMB_ADAPTERS]; - -/* IPMI Data */ -#define IPMI_IPMB_CHANNEL 0 -static ipmi_user_t i2c_ipmb_user; -static unsigned char ipmi_version_major; -static unsigned char ipmi_version_minor; -static const char msgdata[IPMI_MAX_ADDR_SIZE]; /* ?? */ -static struct ipmi_system_interface_addr address = { - IPMI_SYSTEM_INTERFACE_ADDR_TYPE, - IPMI_BMC_CHANNEL, - 0 -}; /* send address */ -static struct ipmi_ipmb_addr ipmb_address = { - IPMI_IPMB_ADDR_TYPE, - IPMI_IPMB_CHANNEL, - 0, - 0 -}; /* send address */ -static long msgid; /* message ID */ -static int interfaces; /* number of BMC's found */ -static struct ipmi_msg tx_message; /* send message */ -static unsigned char tx_msg_data[IPMI_MAX_MSG_LENGTH + 50]; -static unsigned char rx_msg_data[IPMI_MAX_MSG_LENGTH + 50]; /* sloppy */ - -/* IPMI Message defs */ -/* Network Function Codes */ -#define IPMI_NETFN_APP 0x06 -/* Commands */ -#define IPMI_ENABLE_CHANNEL 0x32 -#define IPMI_SEND_MSG 0x34 -#define IPMI_GET_CHANNEL_INFO 0x42 /* unfortunately, IPMI 1.5 only */ -#define IPMI_MASTER_WR 0x52 - - -/************** Message Sending **************/ - -static void ipmb_i2c_send_message(struct ipmi_addr *address, - int id, struct ipmi_msg * msg) -{ - int err; - -#ifdef IPMI_RESPONSE_RESPONSE_TYPE - err = ipmi_request(i2c_ipmb_user, address, id, msg, NULL, 0); -#else - err = ipmi_request(i2c_ipmb_user, address, id, msg, 0); -#endif - if (err) - printk(KERN_INFO "i2c-ipmb.o: ipmi_request error %d\n", - err); -} - -/* not used */ -static void ipmb_i2c_bmc_send_message(int id, struct ipmi_msg * msg) -{ - address.channel = IPMI_BMC_CHANNEL; - ipmb_i2c_send_message((struct ipmi_addr *) &address, id, msg); -} - -/* this is for sending commands like master w/r */ -static void ipmb_i2c_ipmb_send_message(int id, struct ipmi_msg * msg) -{ -/* - address.channel = IPMI_IPMB_CHANNEL; -*/ - address.channel = IPMI_BMC_CHANNEL; - ipmb_i2c_send_message((struct ipmi_addr *) &address, id, msg); -} - -#if 0 -/* not used */ -/* this is for an smi message, not for things like master w/r */ -static void ipmb_i2c_ipmb_send_smi(int addr, int id, struct ipmi_msg * msg) -{ - ipmb_address.slave_addr = addr; - ipmb_address.lun = 0; /* pass in */ - ipmb_i2c_send_message((struct ipmi_addr *) &ipmb_address, id, msg); -} - -/* not used */ -/* Compose and send a "Enable Channel Receive" message */ -static void ipmb_enable_channel_rcv(int channel, int code) -{ - tx_message.netfn = IPMI_NETFN_APP; - tx_message.cmd = IPMI_ENABLE_CHANNEL; - tx_message.data_len = 2; - tx_message.data = tx_msg_data; - tx_msg_data[0] = channel; - tx_msg_data[1] = code; - ipmb_i2c_bmc_send_message(msgid++, &tx_message); -} - -/* not used */ -/* Compose and send a "Get Channel Info" message (1.5 only) */ -static void ipmb_get_channel_info(int channel) -{ - tx_message.netfn = IPMI_NETFN_APP; - tx_message.cmd = IPMI_GET_CHANNEL_INFO; - tx_message.data_len = 1; - tx_message.data = tx_msg_data; - tx_msg_data[0] = channel; - ipmb_i2c_bmc_send_message(msgid++, &tx_message); -} -#endif /* 0 */ - -/* Compose and send a "Master W/R" message */ -static void ipmb_master_wr(int bus, u8 addr, u8 rdcount, - u8 wrcount, u8 *wrdata) -{ - printk(KERN_INFO "i2c-ipmb.o: trying bus %d ...\n", bus); - tx_message.netfn = IPMI_NETFN_APP; - tx_message.cmd = IPMI_MASTER_WR; - tx_message.data_len = 3 + wrcount; - tx_msg_data[0] = bus & 0x0f; - tx_msg_data[1] = addr << 1; - tx_msg_data[2] = rdcount; - if(wrcount > 0) - memcpy(tx_msg_data + 3, wrdata, wrcount); - tx_message.data = tx_msg_data; - ipmb_i2c_ipmb_send_message(msgid++, &tx_message); -} - -int xchan; -int xbus; -/* look for channels. IPMI 1.5 defines multiple channels and an - easy way to get the information. - We don't bother using SDR type 14 for IPMI 1.0; that isn't - always present anyway. We could try "enable message channel receive" - with a channel state = 2 (query) but 1.0 is likely to have only - IPMB busses anyway. Therefore, we assume there is only - the IPMB at channel 0. -*/ -static void ipmb_get_all_channel_info(void) - -{ -#if 0 - if(ipmi_version_major > 1 || - (ipmi_version_major == 1 && ipmi_version_minor >= 5)) - ipmb_get_channel_info(0); -#endif -/* - else - scan SDR's for type 14 - else { - for all xchan 0-15 - ipmb_enable_channel_rcv(xchan, 2); -*/ - xbus = 0; - ipmb_master_wr(xbus, 0x2d, 1, 1, "\0"); -/* -*/ -/* - else - assume IPMB at channel 0 only -*/ -} - -/************** Message Receiving **************/ - -/* not used */ -static void ipmb_rcv_channel_info(struct ipmi_msg *msg) -{ - u8 channel, type, protocol; - - channel = msg->data[1] & 0x0f; - type = msg->data[2] & 0x7f; - protocol = msg->data[3] & 0x1f; - printk(KERN_INFO "i2c-ipmb.o: Channel %d; type 0x%x; protocol 0x%x\n", - channel, type, protocol); -} -/* - return i2c_add_adapter(&i2c_ipmb_adapter); - if (error) { - printk(KERN_ERR "i2c-ipmb.o: Adapter registration failed, " - "module i2c-ipmb.o is not inserted\n."); - return; - } -*/ -/* - if(channel < 7) - ipmb_get_channel_info(channel + 1); -*/ -static void ipmb_rcv_master_resp(struct ipmi_msg *msg) -{ - if(++xbus > 0x0f) - return; - ipmb_master_wr(xbus, 0x2d, 1, 1, "\0"); -} - -#if 0 -/* not used */ -static void ipmb_rcv_channel_enable(struct ipmi_msg *msg) -{ - int state; - - state = msg->data[2] & 1; - - printk(KERN_INFO "i2c-ipmb.o: Channel %d; state %d\n", - xchan, state); - if(++xchan > 0x0f) - return; - ipmb_enable_channel_rcv(xchan, 2); -} -#endif /* 0 */ - -static void ipmb_i2c_msg_handler(struct ipmi_recv_msg *msg, - void *handler_data) -{ - int rcvid = msg->msgid & 0xffffff; - int client = (msg->msgid >> 24) & 0xf; - - if (msg->msg.data[0] != 0) - printk(KERN_WARNING "i2c-ipmb.o: Error 0x%x on cmd 0x%x/0x%x\n", - msg->msg.data[0], msg->msg.netfn & 0xfe, msg->msg.cmd); -/* - else -*/ - ipmb_rcv_master_resp(&(msg->msg)); - - - - - - ipmi_free_recv_msg(msg); -} - -static struct ipmi_user_hndl ipmb_hndlrs = -{ - .ipmi_recv_hndl = ipmb_i2c_msg_handler, -}; - -/*************** I2C funtions *******************/ - -/* Return -1 on error. */ -int ipmb_access(struct i2c_adapter *adap,struct i2c_msg msgs[], - int num) -{ - - - - - - -} - -static u32 i2c_ipmb_func(struct i2c_adapter *adapter) -{ - return 0; /* fixme */ -} - -/**************** Initialization ****************/ - -/* callback for each BMC found */ -static void ipmb_register(int ipmi_intf) -{ - unsigned long flags; - int rv; - - if(interfaces > 0) { /* 1 max for now */ - printk(KERN_INFO - "i2c-ipmb.o: Additional IPMI interface %d not supported\n", - ipmi_intf); - return; - } - - rv = ipmi_create_user(ipmi_intf, &ipmb_hndlrs, NULL, &i2c_ipmb_user); - if (rv < 0) { - printk(KERN_ERR "i2c-ipmb.o: Unable to register with ipmi\n"); - return; - } - - ipmi_get_version(i2c_ipmb_user, &ipmi_version_major, - &ipmi_version_minor); - printk(KERN_INFO - "i2c-ipmb.o: Registered IPMI interface %d with version %d.%d\n", - ipmi_intf, ipmi_version_major, ipmi_version_minor); - interfaces++; - - ipmb_get_all_channel_info(); -} - -static void ipmb_new_smi(int if_num) -{ - ipmb_register(if_num); -} - -static void ipmb_smi_gone(int if_num) -{ - if (interfaces >= 1) { -/* - i2c_del_adapter(&i2c_ipmb_adapter); -*/ - ipmi_destroy_user(i2c_ipmb_user); - interfaces--; - } -} - -static struct ipmi_smi_watcher smi_watcher = -{ - .new_smi = ipmb_new_smi, - .smi_gone = ipmb_smi_gone -}; - -static int __init i2c_ipmb_init(void) -{ - int rv; - - printk(KERN_INFO "i2c-ipmb.o version %s (%s)\n", LM_VERSION, LM_DATE); - - rv = ipmi_smi_watcher_register(&smi_watcher); - if (rv) { - printk(KERN_WARNING - "ipmi_watchdog: can't register smi watcher\n"); - return rv; - } - - printk(KERN_INFO "i2c-ipmb.o: BMC access for i2c modules initialized.\n"); - return 0; -} - - -static void __exit i2c_ipmi_exit(void) -{ - ipmi_smi_watcher_unregister(&smi_watcher); - ipmb_smi_gone(0); -} - -MODULE_AUTHOR("M. D. Studebaker "); -MODULE_DESCRIPTION("IPMB-BMC access through i2c"); -MODULE_LICENSE("GPL"); - -module_init(i2c_ipmb_init); -module_exit(i2c_ipmi_exit); diff --git a/kernel/busses/i2c-ipmi.c b/kernel/busses/i2c-ipmi.c deleted file mode 100644 index cae78e36..00000000 --- a/kernel/busses/i2c-ipmi.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - i2c-ipmi.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 2002 Mark D. Studebaker - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - This implements a "dummy" i2c adapter for clients to access the - BMC via IPMI messages. Supports only one BMC and one client for now! -*/ - -#include -#include -#include -#include -#include -#include "version.h" - - -static u32 i2c_ipmi_func(struct i2c_adapter *adapter); -static int bmcclient_i2c_send_message(struct i2c_adapter *, char *, int); - -static void i2c_ipmi_inc_use(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -static void i2c_ipmi_dec_use(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - -/* I2C Data */ -static struct i2c_algorithm i2c_ipmi_algorithm = { - .name = "IPMI algorithm", - .id = I2C_ALGO_IPMI, - .slave_send = &bmcclient_i2c_send_message, - .functionality = &i2c_ipmi_func, -}; - -static struct i2c_adapter i2c_ipmi_adapter = { - .name = "IPMI adapter", - .id = I2C_ALGO_IPMI | I2C_HW_IPMI, - .algo = &i2c_ipmi_algorithm, - .inc_use = &i2c_ipmi_inc_use, - .dec_use = &i2c_ipmi_dec_use, -}; - -/* IPMI Data */ -static ipmi_user_t i2c_ipmi_user; -static unsigned char ipmi_version_major; -static unsigned char ipmi_version_minor; -static const char msgdata[IPMI_MAX_ADDR_SIZE]; /* ?? */ -static struct ipmi_addr address = { - IPMI_SYSTEM_INTERFACE_ADDR_TYPE, - IPMI_BMC_CHANNEL, - {0} -}; /* send address */ -static int interfaces; /* number of BMC's found */ - - -/* Dummy adapter... */ -static u32 i2c_ipmi_func(struct i2c_adapter *adapter) -{ - return 0; -} - -/************** Message Sending **************/ - -static int find_client(struct i2c_client * client) -{ - int i; - - for (i = 0; i < I2C_CLIENT_MAX; i++) - if (client == i2c_ipmi_adapter.clients[i]) - return i; - return -1; -} - -static void ipmi_i2c_send_message(int id, struct ipmi_msg * msg) -{ -#ifdef IPMI_RESPONSE_RESPONSE_TYPE - ipmi_request(i2c_ipmi_user, &address, (long) id, msg, NULL, 0); -#else - ipmi_request(i2c_ipmi_user, &address, (long) id, msg, 0); -#endif -} - -/* This is the message send function exported to the client - via the i2c_adapter struct. - We use the existing (but unused) slave_send function pointer. - Hence the ugly casts. */ -static int bmcclient_i2c_send_message(struct i2c_adapter *clnt, - char * mesg, int id) -{ - struct ipmi_msg *msg = (struct ipmi_msg *) mesg; - struct i2c_client *client = (struct i2c_client *) clnt; - int clientid; - -#ifdef DEBUG - if(msg->data == NULL) - printk(KERN_INFO "i2c-ipmi.o: Send 0x%x\n", msg->cmd); - else - printk(KERN_INFO "i2c-ipmi.o: Send 0x%x 0x%x 0x%x\n", msg->cmd, msg->data[0], msg->data[1]); -#endif - /* save the client number in the upper 8 bits of the message id */ - if((clientid = find_client(client)) < 0) { - printk(KERN_WARNING "i2c-ipmi.o: Request from unknown client\n"); - return -1; - } - - id = (id & 0xffffff) | (clientid << 24); - ipmi_i2c_send_message(id, msg); - return 0; -} - -/************** Message Receiving **************/ - -static void ipmi_i2c_msg_handler(struct ipmi_recv_msg *msg, - void *handler_data) -{ - int rcvid = msg->msgid & 0xffffff; - int clientid = (msg->msgid >> 24) & 0xff; - -#ifdef DEBUG - if (msg->msg.data[0] != 0) - printk(KERN_WARNING "i2c-ipmi.o: Error 0x%x on cmd 0x%x/0x%x\n", - msg->msg.data[0], msg->msg.netfn, msg->msg.cmd); -#endif - /* Protect ourselves here; verify the client and its callback - since the client may have gone away since - the message was sent! */ - if(clientid < I2C_CLIENT_MAX && - i2c_ipmi_adapter.clients[clientid] != NULL && - i2c_ipmi_adapter.clients[clientid]->driver->command != NULL) - (* i2c_ipmi_adapter.clients[clientid]->driver->command) - (i2c_ipmi_adapter.clients[clientid], rcvid, msg); - else { - printk(KERN_WARNING "i2c-ipmi.o: Response for unknown client\n"); - ipmi_free_recv_msg(msg); - } -} - -static struct ipmi_user_hndl ipmi_hndlrs = -{ - .ipmi_recv_hndl = ipmi_i2c_msg_handler, -}; - -/**************** Initialization ****************/ - -/* callback for each BMC found */ -static void ipmi_register_bmc(int ipmi_intf) -{ - int error; - - if(interfaces > 0) { /* 1 max for now */ - printk(KERN_INFO - "i2c-ipmi.o: Additional IPMI interface %d not supported\n", - ipmi_intf); - return; - } - - error = ipmi_create_user(ipmi_intf, &ipmi_hndlrs, NULL, &i2c_ipmi_user); - if (error < 0) { - printk(KERN_ERR "i2c-ipmi.o: Unable to register with ipmi\n"); - return; - } - - error = i2c_add_adapter(&i2c_ipmi_adapter); - if (error) { - printk(KERN_ERR "i2c-ipmi.o: Adapter registration failed, " - "module i2c-ipmi.o is not inserted\n."); - return; - } - - ipmi_get_version(i2c_ipmi_user, &ipmi_version_major, - &ipmi_version_minor); - printk(KERN_INFO - "i2c-ipmi.o: Registered IPMI interface %d with version %d.%d\n", - ipmi_intf, ipmi_version_major, ipmi_version_minor); - interfaces++; -} - -static void ipmi_new_smi(int if_num) -{ - ipmi_register_bmc(if_num); -} - -static void ipmi_smi_gone(int if_num) -{ - if (interfaces >= 1) { - i2c_del_adapter(&i2c_ipmi_adapter); - ipmi_destroy_user(i2c_ipmi_user); - interfaces--; - } -} - -static struct ipmi_smi_watcher smi_watcher = -{ - .new_smi = ipmi_new_smi, - .smi_gone = ipmi_smi_gone -}; - -static int __init i2c_ipmi_init(void) -{ - int rv; - - printk(KERN_INFO "i2c-ipmi.o version %s (%s)\n", LM_VERSION, LM_DATE); - - rv = ipmi_smi_watcher_register(&smi_watcher); - if (rv) { - printk(KERN_WARNING - "ipmi_watchdog: can't register smi watcher\n"); - return rv; - } - - printk(KERN_INFO "i2c-ipmi.o: BMC access for i2c modules initialized.\n"); - return 0; -} - - -static void __exit i2c_ipmi_exit(void) -{ - ipmi_smi_watcher_unregister(&smi_watcher); - ipmi_smi_gone(0); -} - -MODULE_AUTHOR("M. D. Studebaker "); -MODULE_DESCRIPTION("IPMI-BMC access through i2c"); -MODULE_LICENSE("GPL"); - -module_init(i2c_ipmi_init); -module_exit(i2c_ipmi_exit); diff --git a/kernel/busses/i2c-isa.c b/kernel/busses/i2c-isa.c deleted file mode 100644 index 517cef67..00000000 --- a/kernel/busses/i2c-isa.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - i2c-isa.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998, 1999 Frodo Looijaard - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* This implements an i2c algorithm/adapter for ISA bus. Not that this is - on first sight very useful; almost no functionality is preserved. - Except that it makes writing drivers for chips which can be on both - the SMBus and the ISA bus very much easier. See lm78.c for an example - of this. */ - -#include -#include -#include -#include -#include -#include "version.h" - -static u32 isa_func(struct i2c_adapter *adapter); - -/* This is the actual algorithm we define */ -static struct i2c_algorithm isa_algorithm = { - .name = "ISA bus algorithm", - .id = I2C_ALGO_ISA, - .functionality = isa_func, -}; - -static void isa_inc_use(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -static void isa_dec_use(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - -/* There can only be one... */ -static struct i2c_adapter isa_adapter = { - .name = "ISA main adapter", - .id = I2C_ALGO_ISA | I2C_HW_ISA, - .algo = &isa_algorithm, - .inc_use = isa_inc_use, - .dec_use = isa_dec_use, -}; - -/* We can't do a thing... */ -static u32 isa_func(struct i2c_adapter *adapter) -{ - return 0; -} - -static int __init i2c_isa_init(void) -{ - printk("i2c-isa.o version %s (%s)\n", LM_VERSION, LM_DATE); - return i2c_add_adapter(&isa_adapter); -} - -static void __exit i2c_isa_exit(void) -{ - i2c_del_adapter(&isa_adapter); -} - -MODULE_AUTHOR("Frodo Looijaard "); -MODULE_DESCRIPTION("ISA bus access through i2c"); -MODULE_LICENSE("GPL"); - -module_init(i2c_isa_init); -module_exit(i2c_isa_exit); diff --git a/kernel/busses/i2c-keywest.c b/kernel/busses/i2c-keywest.c deleted file mode 100644 index 02ee7245..00000000 --- a/kernel/busses/i2c-keywest.c +++ /dev/null @@ -1,619 +0,0 @@ -/* - i2c Support for Apple Keywest I2C Bus Controller - - Copyright (c) 2001 Benjamin Herrenschmidt - - Original work by - - Copyright (c) 2000 Philip Edelbrock - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Changes: - - 2001/12/13 BenH New implementation - 2001/12/15 BenH Add support for "byte" and "quick" - transfers. Add i2c_xfer routine. - - My understanding of the various modes supported by keywest are: - - - Dumb mode : not implemented, probably direct tweaking of lines - - Standard mode : simple i2c transaction of type - S Addr R/W A Data A Data ... T - - Standard sub mode : combined 8 bit subaddr write with data read - S Addr R/W A SubAddr A Data A Data ... T - - Combined mode : Subaddress and Data sequences appended with no stop - S Addr R/W A SubAddr S Addr R/W A Data A Data ... T - - Currently, this driver uses only Standard mode for i2c xfer, and - smbus byte & quick transfers ; and uses StandardSub mode for - other smbus transfers instead of combined as we need that for the - sound driver to be happy -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "i2c-keywest.h" - -#define DBG(x...) do {\ - if (debug > 0) \ - printk(KERN_DEBUG "KW:" x); \ - } while(0) - - -MODULE_AUTHOR("Benjamin Herrenschmidt "); -MODULE_DESCRIPTION("I2C driver for Apple's Keywest"); -MODULE_LICENSE("GPL"); -MODULE_PARM(debug, "i"); - -int debug = 0; - -static struct keywest_iface *ifaces = NULL; - - -static void -do_stop(struct keywest_iface* iface, int result) -{ - write_reg(reg_control, read_reg(reg_control) | KW_I2C_CTL_STOP); - iface->state = state_stop; - iface->result = result; -} - -/* Main state machine for standard & standard sub mode */ -static int -handle_interrupt(struct keywest_iface *iface, u8 isr) -{ - int ack; - int rearm_timer = 1; - - DBG("handle_interrupt(), got: %x, status: %x, state: %d\n", - isr, read_reg(reg_status), iface->state); - if (isr == 0 && iface->state != state_stop) { - do_stop(iface, -1); - return rearm_timer; - } - if (isr & KW_I2C_IRQ_STOP && iface->state != state_stop) { - iface->result = -1; - iface->state = state_stop; - } - switch(iface->state) { - case state_addr: - if (!(isr & KW_I2C_IRQ_ADDR)) { - do_stop(iface, -1); - break; - } - ack = read_reg(reg_status); - DBG("ack on set address: %x\n", ack); - if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { - do_stop(iface, -1); - break; - } - /* Handle rw "quick" mode */ - if (iface->datalen == 0) - do_stop(iface, 0); - else if (iface->read_write == I2C_SMBUS_READ) { - iface->state = state_read; - if (iface->datalen > 1) - write_reg(reg_control, read_reg(reg_control) - | KW_I2C_CTL_AAK); - } else { - iface->state = state_write; - DBG("write byte: %x\n", *(iface->data)); - write_reg(reg_data, *(iface->data++)); - iface->datalen--; - } - - break; - case state_read: - if (!(isr & KW_I2C_IRQ_DATA)) { - do_stop(iface, -1); - break; - } - *(iface->data++) = read_reg(reg_data); - DBG("read byte: %x\n", *(iface->data-1)); - iface->datalen--; - if (iface->datalen == 0) - iface->state = state_stop; - else - write_reg(reg_control, 0); - break; - case state_write: - if (!(isr & KW_I2C_IRQ_DATA)) { - do_stop(iface, -1); - break; - } - /* Check ack status */ - ack = read_reg(reg_status); - DBG("ack on data write: %x\n", ack); - if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { - do_stop(iface, -1); - break; - } - if (iface->datalen) { - DBG("write byte: %x\n", *(iface->data)); - write_reg(reg_data, *(iface->data++)); - iface->datalen--; - } else - do_stop(iface, 0); - break; - - case state_stop: - if (!(isr & KW_I2C_IRQ_STOP) && (++iface->stopretry) < 10) - do_stop(iface, -1); - else { - rearm_timer = 0; - iface->state = state_idle; - write_reg(reg_control, 0x00); - write_reg(reg_ier, 0x00); - complete(&iface->complete); - } - break; - } - - write_reg(reg_isr, isr); - - return rearm_timer; -} - -/* Interrupt handler */ -static void -keywest_irq(int irq, void *dev_id, struct pt_regs *regs) -{ - struct keywest_iface *iface = (struct keywest_iface *)dev_id; - - spin_lock(&iface->lock); - del_timer(&iface->timeout_timer); - if (handle_interrupt(iface, read_reg(reg_isr))) { - iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; - add_timer(&iface->timeout_timer); - } - spin_unlock(&iface->lock); -} - -static void -keywest_timeout(unsigned long data) -{ - struct keywest_iface *iface = (struct keywest_iface *)data; - - DBG("timeout !\n"); - spin_lock_irq(&iface->lock); - if (iface->state != state_idle) { - iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; - add_timer(&iface->timeout_timer); - } - spin_unlock(&iface->lock); -} - -/* - * SMBUS-type transfer entrypoint - */ -static s32 -keywest_smbus_xfer( struct i2c_adapter* adap, - u16 addr, - unsigned short flags, - char read_write, - u8 command, - int size, - union i2c_smbus_data* data) -{ - struct keywest_chan* chan = (struct keywest_chan*)adap->data; - struct keywest_iface* iface = chan->iface; - int len; - u8* buffer; - u16 cur_word; - int rc = 0; - - if (iface->state == state_dead) - return -1; - - /* Prepare datas & select mode */ - iface->cur_mode &= ~KW_I2C_MODE_MODE_MASK; - switch (size) { - case I2C_SMBUS_QUICK: - len = 0; - buffer = NULL; - iface->cur_mode |= KW_I2C_MODE_STANDARD; - break; - case I2C_SMBUS_BYTE: - len = 1; - buffer = &data->byte; - iface->cur_mode |= KW_I2C_MODE_STANDARD; - break; - case I2C_SMBUS_BYTE_DATA: - len = 1; - buffer = &data->byte; - iface->cur_mode |= KW_I2C_MODE_STANDARDSUB; - //iface->cur_mode |= KW_I2C_MODE_COMBINED; - break; - case I2C_SMBUS_WORD_DATA: - len = 2; - cur_word = cpu_to_le16(data->word); - buffer = (u8 *)&cur_word; - iface->cur_mode |= KW_I2C_MODE_STANDARDSUB; - //iface->cur_mode |= KW_I2C_MODE_COMBINED; - break; - case I2C_SMBUS_BLOCK_DATA: - len = data->block[0]; - buffer = &data->block[1]; - iface->cur_mode |= KW_I2C_MODE_STANDARDSUB; - //iface->cur_mode |= KW_I2C_MODE_COMBINED; - break; - default: - return -1; - } - - /* Original driver had this limitation */ - if (len > 32) - len = 32; - - down(&iface->sem); - - DBG("chan: %d, addr: 0x%x, transfer len: %d, read: %d\n", - chan->chan_no, addr, len, read_write == I2C_SMBUS_READ); - - iface->data = buffer; - iface->datalen = len; - iface->state = state_addr; - iface->result = 0; - iface->stopretry = 0; - iface->read_write = read_write; - - /* Setup channel & clear pending irqs */ - write_reg(reg_mode, iface->cur_mode | (chan->chan_no << 4)); - write_reg(reg_isr, read_reg(reg_isr)); - write_reg(reg_status, 0); - - /* Set up address and r/w bit */ - write_reg(reg_addr, - (addr << 1) | ((read_write == I2C_SMBUS_READ) ? 0x01 : 0x00)); - - /* Set up the sub address */ - if ((iface->cur_mode & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_STANDARDSUB - || (iface->cur_mode & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_COMBINED) - write_reg(reg_subaddr, command); - - /* Arm timeout */ - iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; - add_timer(&iface->timeout_timer); - - /* Start sending address & enable interrupt*/ - write_reg(reg_control, read_reg(reg_control) | KW_I2C_CTL_XADDR); - write_reg(reg_ier, KW_I2C_IRQ_MASK); - - wait_for_completion(&iface->complete); - - rc = iface->result; - DBG("transfer done, result: %d\n", rc); - - if (rc == 0 && size == I2C_SMBUS_WORD_DATA && read_write == I2C_SMBUS_READ) - data->word = le16_to_cpu(cur_word); - - /* Release sem */ - up(&iface->sem); - - return rc; -} - -/* - * Generic i2c master transfer entrypoint - */ -static int -keywest_xfer( struct i2c_adapter *adap, - struct i2c_msg msgs[], - int num) -{ - struct keywest_chan* chan = (struct keywest_chan*)adap->data; - struct keywest_iface* iface = chan->iface; - struct i2c_msg *pmsg; - int i, completed; - int rc = 0; - - down(&iface->sem); - - /* Set adapter to standard mode */ - iface->cur_mode &= ~KW_I2C_MODE_MODE_MASK; - iface->cur_mode |= KW_I2C_MODE_STANDARD; - - completed = 0; - for (i = 0; rc >= 0 && i < num;) { - u8 addr; - - pmsg = &msgs[i++]; - addr = pmsg->addr; - if (pmsg->flags & I2C_M_TEN) { - printk(KERN_ERR "i2c-keywest: 10 bits addr not supported !\n"); - rc = -EINVAL; - break; - } - DBG("xfer: chan: %d, doing %s %d bytes to 0x%02x - %d of %d messages\n", - chan->chan_no, - pmsg->flags & I2C_M_RD ? "read" : "write", - pmsg->len, addr, i, num); - - /* Setup channel & clear pending irqs */ - write_reg(reg_mode, iface->cur_mode | (chan->chan_no << 4)); - write_reg(reg_isr, read_reg(reg_isr)); - write_reg(reg_status, 0); - - iface->data = pmsg->buf; - iface->datalen = pmsg->len; - iface->state = state_addr; - iface->result = 0; - iface->stopretry = 0; - if (pmsg->flags & I2C_M_RD) - iface->read_write = I2C_SMBUS_READ; - else - iface->read_write = I2C_SMBUS_WRITE; - - /* Set up address and r/w bit */ - if (pmsg->flags & I2C_M_REV_DIR_ADDR) - addr ^= 1; - write_reg(reg_addr, - (addr << 1) | - ((iface->read_write == I2C_SMBUS_READ) ? 0x01 : 0x00)); - - /* Arm timeout */ - iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; - add_timer(&iface->timeout_timer); - - /* Start sending address & enable interrupt*/ - write_reg(reg_control, read_reg(reg_control) | KW_I2C_CTL_XADDR); - write_reg(reg_ier, KW_I2C_IRQ_MASK); - - wait_for_completion(&iface->complete); - - rc = iface->result; - if (rc == 0) - completed++; - DBG("transfer done, result: %d\n", rc); - } - - /* Release sem */ - up(&iface->sem); - - return completed; -} - -static u32 -keywest_func(struct i2c_adapter * adapter) -{ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA; -} - -static void -keywest_inc(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -static void -keywest_dec(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - -/* For now, we only handle combined mode (smbus) */ -static struct i2c_algorithm keywest_algorithm = { - .name = "Keywest i2c", - .id = I2C_ALGO_SMBUS, - .smbus_xfer = keywest_smbus_xfer, - .master_xfer = keywest_xfer, - .functionality = keywest_func, -}; - - -static int __init -create_iface(struct device_node* np) -{ - unsigned long steps, *psteps, *prate; - unsigned bsteps, tsize, i, nchan, addroffset; - struct keywest_iface* iface; - int error; - - psteps = (unsigned long *)get_property(np, "AAPL,address-step", NULL); - steps = psteps ? (*psteps) : 0x10; - - /* Hrm... maybe we can be smarter here */ - for (bsteps = 0; (steps & 0x01) == 0; bsteps++) - steps >>= 1; - - if (!strcmp(np->parent->name, "uni-n")) { - nchan = 2; - addroffset = 3; - } else { - addroffset = 0; - nchan = 1; - } - - tsize = sizeof(struct keywest_iface) + - (sizeof(struct keywest_chan) + 4) * nchan; - iface = kmalloc(tsize, GFP_KERNEL); - if (iface == NULL) { - printk(KERN_ERR "i2c-keywest: can't allocate inteface !\n"); - return -ENOMEM; - } - memset(iface, 0, tsize); - init_MUTEX(&iface->sem); - spin_lock_init(&iface->lock); - init_completion(&iface->complete); - iface->bsteps = bsteps; - iface->chan_count = nchan; - iface->state = state_idle; - iface->irq = np->intrs[0].line; - iface->channels = (struct keywest_chan *) - (((unsigned long)(iface + 1) + 3UL) & ~3UL); - iface->base = (unsigned long)ioremap(np->addrs[0].address + addroffset, - np->addrs[0].size); - if (iface->base == 0) { - printk(KERN_ERR "i2c-keywest: can't map inteface !\n"); - kfree(iface); - return -ENOMEM; - } - - init_timer(&iface->timeout_timer); - iface->timeout_timer.function = keywest_timeout; - iface->timeout_timer.data = (unsigned long)iface; - - /* Select interface rate */ - iface->cur_mode = KW_I2C_MODE_100KHZ; - prate = (unsigned long *)get_property(np, "AAPL,i2c-rate", NULL); - if (prate) switch(*prate) { - case 100: - iface->cur_mode = KW_I2C_MODE_100KHZ; - break; - case 50: - iface->cur_mode = KW_I2C_MODE_50KHZ; - break; - case 25: - iface->cur_mode = KW_I2C_MODE_25KHZ; - break; - default: - printk(KERN_WARNING "i2c-keywest: unknown rate %ldKhz, using 100KHz\n", - *prate); - } - - /* Select standard mode by default */ - iface->cur_mode |= KW_I2C_MODE_STANDARD; - - /* Write mode */ - write_reg(reg_mode, iface->cur_mode); - - /* Switch interrupts off & clear them*/ - write_reg(reg_ier, 0x00); - write_reg(reg_isr, KW_I2C_IRQ_MASK); - - /* Request chip interrupt */ - error = request_irq(iface->irq, keywest_irq, 0, "keywest i2c", iface); - if (error) { - printk(KERN_ERR "i2c-keywest: can't get IRQ %d !\n", iface->irq); - iounmap((void *)iface->base); - kfree(iface); - return -ENODEV; - } - - for (i=0; ichannels[i]; - - sprintf(chan->adapter.name, "%s %d", np->parent->name, i); - chan->iface = iface; - chan->chan_no = i; - chan->adapter.id = I2C_ALGO_SMBUS; - chan->adapter.algo = &keywest_algorithm; - chan->adapter.algo_data = NULL; - chan->adapter.inc_use = keywest_inc; - chan->adapter.dec_use = keywest_dec; - chan->adapter.client_register = NULL; - chan->adapter.client_unregister = NULL; - chan->adapter.data = chan; - - error = i2c_add_adapter(&chan->adapter); - if (error) { - printk("i2c-keywest.c: Adapter %s registration failed\n", - chan->adapter.name); - chan->adapter.data = NULL; - } - } - - printk(KERN_INFO "Found KeyWest i2c on \"%s\", %d channel%s, stepping: %d bits\n", - np->parent->name, nchan, nchan > 1 ? "s" : "", bsteps); - - iface->next = ifaces; - ifaces = iface; - return 0; -} - -static void __exit -dispose_iface(struct keywest_iface *iface) -{ - int i, error; - - ifaces = iface->next; - - /* Make sure we stop all activity */ - down(&iface->sem); - spin_lock_irq(&iface->lock); - while (iface->state != state_idle) { - spin_unlock_irq(&iface->lock); - set_task_state(current,TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/10); - spin_lock_irq(&iface->lock); - } - iface->state = state_dead; - spin_unlock_irq(&iface->lock); - free_irq(iface->irq, iface); - up(&iface->sem); - - /* Release all channels */ - for (i=0; ichan_count; i++) { - struct keywest_chan* chan = &iface->channels[i]; - if (!chan->adapter.data) - continue; - i2c_del_adapter(&chan->adapter); - chan->adapter.data = NULL; - /* We aren't that prepared to deal with this... */ - if (error) - printk("i2c-keywest.c: i2c_del_adapter failed, that's bad !\n"); - } - iounmap((void *)iface->base); - kfree(iface); -} - -static int __init i2c_keywest_init(void) -{ - struct device_node *np; - int error = -ENODEV; - - np = find_compatible_devices("i2c", "keywest"); - while (np != 0) { - if (np->n_addrs >= 1 && np->n_intrs >= 1) - error = create_iface(np); - np = np->next; - } - if (ifaces) - error = 0; - return error; -} - -static void __exit i2c_keywest_exit(void) -{ - while(ifaces) - dispose_iface(ifaces); -} - -module_init(i2c_keywest_init); -module_exit(i2c_keywest_exit); diff --git a/kernel/busses/i2c-keywest.h b/kernel/busses/i2c-keywest.h deleted file mode 100644 index 906a6f12..00000000 --- a/kernel/busses/i2c-keywest.h +++ /dev/null @@ -1,113 +0,0 @@ -#ifndef __I2C_KEYWEST_H__ -#define __I2C_KEYWEST_H__ - -#include - -/* The Tumbler audio equalizer can be really slow sometimes */ -#define POLL_TIMEOUT (2*HZ) - -/* Register indices */ -typedef enum { - reg_mode = 0, - reg_control, - reg_status, - reg_isr, - reg_ier, - reg_addr, - reg_subaddr, - reg_data -} reg_t; - - -/* Mode register */ -#define KW_I2C_MODE_100KHZ 0x00 -#define KW_I2C_MODE_50KHZ 0x01 -#define KW_I2C_MODE_25KHZ 0x02 -#define KW_I2C_MODE_DUMB 0x00 -#define KW_I2C_MODE_STANDARD 0x04 -#define KW_I2C_MODE_STANDARDSUB 0x08 -#define KW_I2C_MODE_COMBINED 0x0C -#define KW_I2C_MODE_MODE_MASK 0x0C -#define KW_I2C_MODE_CHAN_MASK 0xF0 - -/* Control register */ -#define KW_I2C_CTL_AAK 0x01 -#define KW_I2C_CTL_XADDR 0x02 -#define KW_I2C_CTL_STOP 0x04 -#define KW_I2C_CTL_START 0x08 - -/* Status register */ -#define KW_I2C_STAT_BUSY 0x01 -#define KW_I2C_STAT_LAST_AAK 0x02 -#define KW_I2C_STAT_LAST_RW 0x04 -#define KW_I2C_STAT_SDA 0x08 -#define KW_I2C_STAT_SCL 0x10 - -/* IER & ISR registers */ -#define KW_I2C_IRQ_DATA 0x01 -#define KW_I2C_IRQ_ADDR 0x02 -#define KW_I2C_IRQ_STOP 0x04 -#define KW_I2C_IRQ_START 0x08 -#define KW_I2C_IRQ_MASK 0x0F - -/* Physical interface */ -struct keywest_iface -{ - unsigned long base; - unsigned bsteps; - int irq; - struct semaphore sem; - spinlock_t lock; - struct keywest_chan* channels; - unsigned chan_count; - u8 cur_mode; - char read_write; - u8* data; - unsigned datalen; - int state; - int result; - int stopretry; - struct timer_list timeout_timer; - struct completion complete; - struct keywest_iface* next; -}; - -enum { - state_idle, - state_addr, - state_read, - state_write, - state_stop, - state_dead -}; - -/* Channel on an interface */ -struct keywest_chan -{ - struct i2c_adapter adapter; - struct keywest_iface* iface; - unsigned chan_no; -}; - -/* Register access */ - -static inline u8 __read_reg(struct keywest_iface *iface, reg_t reg) -{ - return in_8(((volatile u8 *)iface->base) - + (((unsigned)reg) << iface->bsteps)); -} - -static inline void __write_reg(struct keywest_iface *iface, reg_t reg, u8 val) -{ - out_8(((volatile u8 *)iface->base) - + (((unsigned)reg) << iface->bsteps), val); - (void)__read_reg(iface, reg); - udelay(10); -} - -#define write_reg(reg, val) __write_reg(iface, reg, val) -#define read_reg(reg) __read_reg(iface, reg) - - - -#endif /* __I2C_KEYWEST_H__ */ diff --git a/kernel/busses/i2c-nforce2.c b/kernel/busses/i2c-nforce2.c deleted file mode 100644 index b8ed6cf0..00000000 --- a/kernel/busses/i2c-nforce2.c +++ /dev/null @@ -1,430 +0,0 @@ -/* - SMBus driver for nVidia nForce2 MCP - - Copyright (c) 2003 Hans-Frieder Vogt , - Based on - SMBus 2.0 driver for AMD-8111 IO-Hub - Copyright (c) 2002 Vojtech Pavlik - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - SUPPORTED DEVICES PCI ID - nForce2 MCP 0064 - nForce2 Ultra 400 MCP 0084 - nForce3 Pro150 MCP 00D4 - nForce3 250Gb MCP 00E4 - nForce4 MCP 0052 - nForce4 MCP-04 0034 - nForce4 MCP51 0264 - nForce4 MCP55 0368 - - This driver supports the 2 SMBuses that are included in the MCP of the - nForce2/3/4 chipsets. -*/ - -/* Note: we assume there can only be one nForce2, with two SMBus interfaces */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "version.h" -#include "sensors_compat.h" - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR ("Hans-Frieder Vogt "); -MODULE_DESCRIPTION("nForce2 SMBus driver"); - -#ifndef PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS -#define PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS 0x0064 -#endif - -#ifndef PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS -#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS 0x0084 -#endif - -#ifndef PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS -#define PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS 0x00D4 -#endif - -#ifndef PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS -#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS 0x00E4 -#endif - -#ifndef PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS -#define PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS 0x0052 -#endif - -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS 0x0034 -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS 0x0264 -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS 0x0368 - - -struct nforce2_smbus { - struct i2c_adapter adapter; - int base; - int size; -}; - - -/* - * nVidia nForce2 SMBus control register definitions - * (Newer incarnations use standard BARs 4 and 5 instead) - */ -#define NFORCE_PCI_SMB1 0x50 -#define NFORCE_PCI_SMB2 0x54 - - -/* - * ACPI 2.0 chapter 13 SMBus 2.0 EC register model - */ -#define NVIDIA_SMB_PRTCL (smbus->base + 0x00) /* protocol, PEC */ -#define NVIDIA_SMB_STS (smbus->base + 0x01) /* status */ -#define NVIDIA_SMB_ADDR (smbus->base + 0x02) /* address */ -#define NVIDIA_SMB_CMD (smbus->base + 0x03) /* command */ -#define NVIDIA_SMB_DATA (smbus->base + 0x04) /* 32 data registers */ -#define NVIDIA_SMB_BCNT (smbus->base + 0x24) /* number of data bytes */ -#define NVIDIA_SMB_ALRM_A (smbus->base + 0x25) /* alarm address */ -#define NVIDIA_SMB_ALRM_D (smbus->base + 0x26) /* 2 bytes alarm data */ - -#define NVIDIA_SMB_STS_DONE 0x80 -#define NVIDIA_SMB_STS_ALRM 0x40 -#define NVIDIA_SMB_STS_RES 0x20 -#define NVIDIA_SMB_STS_STATUS 0x1f - -#define NVIDIA_SMB_PRTCL_WRITE 0x00 -#define NVIDIA_SMB_PRTCL_READ 0x01 -#define NVIDIA_SMB_PRTCL_QUICK 0x02 -#define NVIDIA_SMB_PRTCL_BYTE 0x04 -#define NVIDIA_SMB_PRTCL_BYTE_DATA 0x06 -#define NVIDIA_SMB_PRTCL_WORD_DATA 0x08 -#define NVIDIA_SMB_PRTCL_BLOCK_DATA 0x0a -#define NVIDIA_SMB_PRTCL_PROC_CALL 0x0c -#define NVIDIA_SMB_PRTCL_BLOCK_PROC_CALL 0x0d -#define NVIDIA_SMB_PRTCL_I2C_BLOCK_DATA 0x4a -#define NVIDIA_SMB_PRTCL_PEC 0x80 - -static struct pci_driver nforce2_driver; - -static s32 nforce2_access(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data *data); -/* -static int nforce2_block_transaction(union i2c_smbus_data *data, - char read_write, int i2c_enable); - */ -static u32 nforce2_func(struct i2c_adapter *adapter); - - -static struct i2c_algorithm smbus_algorithm = { - .name = "Non-I2C SMBus adapter", - .id = I2C_ALGO_SMBUS, - .smbus_xfer = nforce2_access, - .functionality = nforce2_func, -}; - -/* Return -1 on error. See smbus.h for more information */ -s32 nforce2_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, - char read_write, u8 command, int size, - union i2c_smbus_data * data) -{ - struct nforce2_smbus *smbus = adap->algo_data; - unsigned char protocol, pec, temp; - unsigned char len = 0; /* to keep the compiler quiet */ - int i; - - protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ : NVIDIA_SMB_PRTCL_WRITE; - pec = (flags & I2C_CLIENT_PEC) ? NVIDIA_SMB_PRTCL_PEC : 0; - - switch (size) { - - case I2C_SMBUS_QUICK: - protocol |= NVIDIA_SMB_PRTCL_QUICK; - read_write = I2C_SMBUS_WRITE; - break; - - case I2C_SMBUS_BYTE: - if (read_write == I2C_SMBUS_WRITE) - outb_p(command, NVIDIA_SMB_CMD); - protocol |= NVIDIA_SMB_PRTCL_BYTE; - break; - - case I2C_SMBUS_BYTE_DATA: - outb_p(command, NVIDIA_SMB_CMD); - if (read_write == I2C_SMBUS_WRITE) - outb_p(data->byte, NVIDIA_SMB_DATA); - protocol |= NVIDIA_SMB_PRTCL_BYTE_DATA; - break; - - case I2C_SMBUS_WORD_DATA: - outb_p(command, NVIDIA_SMB_CMD); - if (read_write == I2C_SMBUS_WRITE) { - outb_p(data->word, NVIDIA_SMB_DATA); - outb_p(data->word >> 8, NVIDIA_SMB_DATA+1); - } - protocol |= NVIDIA_SMB_PRTCL_WORD_DATA | pec; - break; - - case I2C_SMBUS_BLOCK_DATA: - outb_p(command, NVIDIA_SMB_CMD); - if (read_write == I2C_SMBUS_WRITE) { - len = min_t(u8, data->block[0], 32); - outb_p(len, NVIDIA_SMB_BCNT); - for (i = 0; i < len; i++) - outb_p(data->block[i + 1], NVIDIA_SMB_DATA+i); - } - protocol |= NVIDIA_SMB_PRTCL_BLOCK_DATA | pec; - break; - - case I2C_SMBUS_I2C_BLOCK_DATA: - len = min_t(u8, data->block[0], 32); - outb_p(command, NVIDIA_SMB_CMD); - outb_p(len, NVIDIA_SMB_BCNT); - if (read_write == I2C_SMBUS_WRITE) - for (i = 0; i < len; i++) - outb_p(data->block[i + 1], NVIDIA_SMB_DATA+i); - protocol |= NVIDIA_SMB_PRTCL_I2C_BLOCK_DATA; - break; - - case I2C_SMBUS_PROC_CALL: - printk(KERN_WARNING "i2c-nforce2.o: I2C_SMBUS_PROC_CALL not supported!\n"); - return -1; - - case I2C_SMBUS_BLOCK_PROC_CALL: - printk(KERN_WARNING "i2c-nforce2.o: I2C_SMBUS_BLOCK_PROC_CALL not supported!\n"); - return -1; - - default: - printk(KERN_WARNING "i2c-nforce2.c: Unsupported transaction %d\n", size); - return -1; - } - - outb_p((addr & 0x7f) << 1, NVIDIA_SMB_ADDR); - outb_p(protocol, NVIDIA_SMB_PRTCL); - - temp = inb_p(NVIDIA_SMB_STS); - - if (~temp & NVIDIA_SMB_STS_DONE) { - udelay(500); - temp = inb_p(NVIDIA_SMB_STS); - } - if (~temp & NVIDIA_SMB_STS_DONE) { - i2c_delay(HZ/100); - temp = inb_p(NVIDIA_SMB_STS); - } - - if ((~temp & NVIDIA_SMB_STS_DONE) || (temp & NVIDIA_SMB_STS_STATUS)) { - printk(KERN_DEBUG "i2c-nforce2.o: SMBus Timeout! (0x%02x)\n", - temp); - return -1; - } - - if (read_write == I2C_SMBUS_WRITE) - return 0; - - switch (size) { - - case I2C_SMBUS_BYTE: - case I2C_SMBUS_BYTE_DATA: - data->byte = inb_p(NVIDIA_SMB_DATA); - break; - - case I2C_SMBUS_WORD_DATA: - /* case I2C_SMBUS_PROC_CALL: not supported */ - data->word = inb_p(NVIDIA_SMB_DATA) | (inb_p(NVIDIA_SMB_DATA+1) << 8); - break; - - case I2C_SMBUS_BLOCK_DATA: - /* case I2C_SMBUS_BLOCK_PROC_CALL: not supported */ - len = inb_p(NVIDIA_SMB_BCNT); - len = min_t(u8, len, 32); - case I2C_SMBUS_I2C_BLOCK_DATA: - for (i = 0; i < len; i++) - data->block[i+1] = inb_p(NVIDIA_SMB_DATA + i); - data->block[0] = len; - break; - } - - return 0; -} - - -u32 nforce2_func(struct i2c_adapter *adapter) -{ - /* other functionality might be possible, but is not tested */ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA /* | - I2C_FUNC_SMBUS_BLOCK_DATA */; -} - -static void nforce2_inc(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -static void nforce2_dec(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - -static struct pci_device_id nforce2_ids[] = { - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { 0 } -}; - - -static int __devinit nforce2_probe_smb(struct pci_dev *dev, int bar, - int alt_reg, struct nforce2_smbus *smbus, char *name) -{ - int error; - - smbus->base = pci_resource_start(dev, bar); - if (smbus->base) { - smbus->size = pci_resource_len(dev, bar); - } else { - /* Older incarnations of the device used non-standard BARs */ - u16 iobase; - - if (pci_read_config_word(dev, alt_reg, &iobase) - != PCIBIOS_SUCCESSFUL) { - printk(KERN_ERR "i2c-nforce2.o: Error reading PCI " - "config for %s\n", name); - return -1; - } - - smbus->base = iobase & PCI_BASE_ADDRESS_IO_MASK; - smbus->size = 8; - } - - if (!request_region(smbus->base, smbus->size, nforce2_driver.name)) { - printk (KERN_ERR "i2c-nforce2.o: Error requesting region %02x .. %02X for %s\n", smbus->base, smbus->base+smbus->size-1, name); - return -1; - } - - sprintf(smbus->adapter.name, "SMBus nForce2 adapter at %04x", smbus->base); - smbus->adapter.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_NFORCE2; - smbus->adapter.algo = &smbus_algorithm; - smbus->adapter.algo_data = smbus; - smbus->adapter.inc_use = nforce2_inc; - smbus->adapter.dec_use = nforce2_dec; - - error = i2c_add_adapter(&smbus->adapter); - if (error) { - printk(KERN_WARNING "i2c-nforce2.o: Failed to register adapter.\n"); - release_region(smbus->base, smbus->size); - return -1; - } - printk(KERN_INFO "i2c-nforce2.o: nForce2 SMBus adapter at %#x\n", smbus->base); - return 0; -} - - -static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - struct nforce2_smbus *smbuses; - int res1, res2; - - /* we support 2 SMBus adapters */ - if (!(smbuses = kmalloc(2*sizeof(struct nforce2_smbus), GFP_KERNEL))) - return -ENOMEM; - memset (smbuses, 0, 2*sizeof(struct nforce2_smbus)); - pci_set_drvdata(dev, smbuses); - - /* SMBus adapter 1 */ - res1 = nforce2_probe_smb(dev, 4, NFORCE_PCI_SMB1, &smbuses[0], "SMB1"); - if (res1 < 0) { - printk (KERN_ERR "i2c-nforce2.o: Error probing SMB1.\n"); - smbuses[0].base = 0; /* to have a check value */ - } - /* SMBus adapter 2 */ - res2 = nforce2_probe_smb(dev, 5, NFORCE_PCI_SMB2, &smbuses[1], "SMB2"); - if (res2 < 0) { - printk (KERN_ERR "i2c-nforce2.o: Error probing SMB2.\n"); - smbuses[1].base = 0; /* to have a check value */ - } - if ((res1 < 0) && (res2 < 0)) { - /* we did not find even one of the SMBuses, so we give up */ - kfree(smbuses); - return -ENODEV; - } - - return 0; -} - - -static void __devexit nforce2_remove(struct pci_dev *dev) -{ - struct nforce2_smbus *smbuses = (void*) pci_get_drvdata(dev); - - if (smbuses[0].base) { - i2c_del_adapter(&smbuses[0].adapter); - release_region(smbuses[0].base, smbuses[0].size); - } - if (smbuses[1].base) { - i2c_del_adapter(&smbuses[1].adapter); - release_region(smbuses[1].base, smbuses[1].size); - } - kfree(smbuses); -} - -static struct pci_driver nforce2_driver = { - .name = "nForce2 SMBus", - .id_table = nforce2_ids, - .probe = nforce2_probe, - .remove = __devexit_p(nforce2_remove), -}; - -int __init nforce2_init(void) -{ - printk(KERN_INFO "i2c-nforce2.o version %s (%s)\n", LM_VERSION, LM_DATE); - return pci_module_init(&nforce2_driver); -} - -void __exit nforce2_exit(void) -{ - pci_unregister_driver(&nforce2_driver); -} - -module_init(nforce2_init); -module_exit(nforce2_exit); - diff --git a/kernel/busses/i2c-piix4.c b/kernel/busses/i2c-piix4.c deleted file mode 100644 index 94a4c301..00000000 --- a/kernel/busses/i2c-piix4.c +++ /dev/null @@ -1,584 +0,0 @@ -/* - piix4.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998 - 2002 Frodo Looijaard and - Philip Edelbrock - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - Supports: - Intel PIIX4, 440MX - Serverworks OSB4, CSB5, CSB6, HT-1000 - ATI IXP200, IXP300, IXP400, SB600 - SMSC Victory66 - - Note: we assume there can only be one device, with one SMBus interface. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "version.h" -#include "sensors_compat.h" - - -struct sd { - const unsigned short mfr; - const unsigned short dev; - const unsigned char fn; - const char *name; -}; - -/* PIIX4 SMBus address offsets */ -#define SMBHSTSTS (0 + piix4_smba) -#define SMBHSLVSTS (1 + piix4_smba) -#define SMBHSTCNT (2 + piix4_smba) -#define SMBHSTCMD (3 + piix4_smba) -#define SMBHSTADD (4 + piix4_smba) -#define SMBHSTDAT0 (5 + piix4_smba) -#define SMBHSTDAT1 (6 + piix4_smba) -#define SMBBLKDAT (7 + piix4_smba) -#define SMBSLVCNT (8 + piix4_smba) -#define SMBSHDWCMD (9 + piix4_smba) -#define SMBSLVEVT (0xA + piix4_smba) -#define SMBSLVDAT (0xC + piix4_smba) - -/* count for request_region */ -#define SMBIOSIZE 8 - -/* PCI Address Constants */ -#define SMBBA 0x090 -#define SMBHSTCFG 0x0D2 -#define SMBSLVC 0x0D3 -#define SMBSHDW1 0x0D4 -#define SMBSHDW2 0x0D5 -#define SMBREV 0x0D6 - -/* Other settings */ -#define MAX_TIMEOUT 500 -#define ENABLE_INT9 0 - -/* PIIX4 constants */ -#define PIIX4_QUICK 0x00 -#define PIIX4_BYTE 0x04 -#define PIIX4_BYTE_DATA 0x08 -#define PIIX4_WORD_DATA 0x0C -#define PIIX4_BLOCK_DATA 0x14 - -/* insmod parameters */ - -/* If force is set to anything different from 0, we forcibly enable the - PIIX4. DANGEROUS! */ -static int force = 0; -MODULE_PARM(force, "i"); -MODULE_PARM_DESC(force, "Forcibly enable the PIIX4. DANGEROUS!"); - -/* If force_addr is set to anything different from 0, we forcibly enable - the PIIX4 at the given address. VERY DANGEROUS! */ -static int force_addr = 0; -MODULE_PARM(force_addr, "i"); -MODULE_PARM_DESC(force_addr, - "Forcibly enable the PIIX4 at the given address. " - "EXTREMELY DANGEROUS!"); - -static int piix4_transaction(void); - -static unsigned short piix4_smba = 0; -static struct pci_driver piix4_driver; - -#ifdef CONFIG_X86 -/* - * Get DMI information. - */ - -static int __devinit ibm_dmi_probe(void) -{ - extern int is_unsafe_smbus; - return is_unsafe_smbus; -} -#endif - -/* Detect whether a PIIX4 can be found, and initialize it, where necessary. - Note the differences between kernels with the old PCI BIOS interface and - newer kernels with the real PCI interface. In compat.h some things are - defined to make the transition easier. */ -static int __devinit piix4_setup(struct pci_dev *PIIX4_dev, - const struct pci_device_id *id) -{ - unsigned char temp; - - /* match up the function */ - if (PCI_FUNC(PIIX4_dev->devfn) != id->driver_data) - return -ENODEV; - - printk(KERN_INFO "Found %s device\n", PIIX4_dev->name); - -#ifdef CONFIG_X86 - if(ibm_dmi_probe() && PIIX4_dev->vendor == PCI_VENDOR_ID_INTEL) { - printk(KERN_ERR "i2c-piix4.o: IBM system detected; this module " - "may corrupt your serial eeprom! Refusing to load " - "module!\n"); - return -EPERM; - } -#endif - - /* Determine the address of the SMBus areas */ - if (force_addr) { - piix4_smba = force_addr & 0xfff0; - force = 0; - } else { - pci_read_config_word(PIIX4_dev, SMBBA, &piix4_smba); - piix4_smba &= 0xfff0; - if(piix4_smba == 0) { - printk(KERN_ERR "i2c-piix4.o: SMB base address " - "uninitialized - upgrade BIOS or use " - "force_addr=0xaddr\n"); - return -ENODEV; - } - } - - if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) { - printk(KERN_ERR "i2c-piix4.o: SMB region 0x%x already in " - "use!\n", piix4_smba); - return -ENODEV; - } - - pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp); - - /* If force_addr is set, we program the new address here. Just to make - sure, we disable the PIIX4 first. */ - if (force_addr) { - pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp & 0xfe); - pci_write_config_word(PIIX4_dev, SMBBA, piix4_smba); - pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp | 0x01); - printk(KERN_INFO "i2c-piix4.o: WARNING: SMBus interface set to " - "new address %04x!\n", piix4_smba); - } else if ((temp & 1) == 0) { - if (force) { - /* This should never need to be done, but has been - * noted that many Dell machines have the SMBus - * interface on the PIIX4 disabled!? NOTE: This assumes - * I/O space and other allocations WERE done by the - * Bios! Don't complain if your hardware does weird - * things after enabling this. :') Check for Bios - * updates before resorting to this. - */ - pci_write_config_byte(PIIX4_dev, SMBHSTCFG, - temp | 1); - printk(KERN_NOTICE "i2c-piix4.o: WARNING: SMBus " - "interface has been FORCEFULLY ENABLED!\n"); - } else { - printk(KERN_ERR "i2c-piix4.o: Host SMBus controller " - "not enabled!\n"); - release_region(piix4_smba, SMBIOSIZE); - piix4_smba = 0; - return -ENODEV; - } - } - -#ifdef DEBUG - if (((temp & 0x0E) == 8) || ((temp & 0x0E) == 2)) - printk(KERN_DEBUG "i2c-piix4.o: Using Interrupt 9 for " - "SMBus.\n"); - else if ((temp & 0x0E) == 0) - printk(KERN_DEBUG "i2c-piix4.o: Using Interrupt SMI# " - "for SMBus.\n"); - else - printk(KERN_ERR "i2c-piix4.o: Illegal Interrupt configuration " - "(or code out of date)!\n"); - - pci_read_config_byte(PIIX4_dev, SMBREV, &temp); - printk(KERN_DEBUG "i2c-piix4.o: SMBREV = 0x%X\n", temp); - printk(KERN_DEBUG "i2c-piix4.o: SMBA = 0x%X\n", piix4_smba); -#endif /* DEBUG */ - - return 0; -} - - -/* Another internally used function */ -int piix4_transaction(void) -{ - int temp; - int result = 0; - int timeout = 0; - -#ifdef DEBUG - printk - (KERN_DEBUG "i2c-piix4.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, " - "DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), - inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); -#endif - - /* Make sure the SMBus host is ready to start transmitting */ - if ((temp = inb_p(SMBHSTSTS)) != 0x00) { -#ifdef DEBUG - printk(KERN_DEBUG "i2c-piix4.o: SMBus busy (%02x). Resetting...\n", - temp); -#endif - outb_p(temp, SMBHSTSTS); - if ((temp = inb_p(SMBHSTSTS)) != 0x00) { -#ifdef DEBUG - printk(KERN_ERR "i2c-piix4.o: Failed! (%02x)\n", temp); -#endif - return -1; - } else { -#ifdef DEBUG - printk(KERN_DEBUG "i2c-piix4.o: Successful!\n"); -#endif - } - } - - /* start the transaction by setting bit 6 */ - outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT); - - /* We will always wait for a fraction of a second! (See PIIX4 docs errata) */ - do { - i2c_delay(1); - temp = inb_p(SMBHSTSTS); - } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT)); - -#ifdef DEBUG - /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { - printk(KERN_ERR "i2c-piix4.o: SMBus Timeout!\n"); - result = -1; - } -#endif - - if (temp & 0x10) { - result = -1; -#ifdef DEBUG - printk(KERN_ERR "i2c-piix4.o: Error: Failed bus transaction\n"); -#endif - } - - if (temp & 0x08) { - result = -1; - printk - (KERN_ERR "i2c-piix4.o: Bus collision! SMBus may be locked until next hard\n" - "reset. (sorry!)\n"); - /* Clock stops and slave is stuck in mid-transmission */ - } - - if (temp & 0x04) { - result = -1; -#ifdef DEBUG - printk(KERN_ERR "i2c-piix4.o: Error: no response!\n"); -#endif - } - - if (inb_p(SMBHSTSTS) != 0x00) - outb_p(inb(SMBHSTSTS), SMBHSTSTS); - -#ifdef DEBUG - if ((temp = inb_p(SMBHSTSTS)) != 0x00) { - printk - (KERN_ERR "i2c-piix4.o: Failed reset at end of transaction (%02x)\n", - temp); - } - printk - (KERN_DEBUG "i2c-piix4.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, " - "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), - inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); -#endif - return result; -} - -/* Return -1 on error. */ -s32 piix4_access(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data * data) -{ - int i, len; - - switch (size) { - case I2C_SMBUS_QUICK: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - size = PIIX4_QUICK; - break; - case I2C_SMBUS_BYTE: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - if (read_write == I2C_SMBUS_WRITE) - outb_p(command, SMBHSTCMD); - size = PIIX4_BYTE; - break; - case I2C_SMBUS_BYTE_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) - outb_p(data->byte, SMBHSTDAT0); - size = PIIX4_BYTE_DATA; - break; - case I2C_SMBUS_WORD_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) { - outb_p(data->word & 0xff, SMBHSTDAT0); - outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); - } - size = PIIX4_WORD_DATA; - break; - case I2C_SMBUS_BLOCK_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) { - len = data->block[0]; - if (len < 0) - len = 0; - if (len > 32) - len = 32; - outb_p(len, SMBHSTDAT0); - i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ - for (i = 1; i <= len; i++) - outb_p(data->block[i], SMBBLKDAT); - } - size = PIIX4_BLOCK_DATA; - break; - default: - printk - (KERN_WARNING "i2c-piix4.o: Unsupported transaction %d\n", size); - return -1; - } - - outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT); - - if (piix4_transaction()) /* Error in transaction */ - return -1; - - if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK)) - return 0; - - - switch (size) { - case PIIX4_BYTE: /* Where is the result put? I assume here it is in - SMBHSTDAT0 but it might just as well be in the - SMBHSTCMD. No clue in the docs */ - - data->byte = inb_p(SMBHSTDAT0); - break; - case PIIX4_BYTE_DATA: - data->byte = inb_p(SMBHSTDAT0); - break; - case PIIX4_WORD_DATA: - data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); - break; - case PIIX4_BLOCK_DATA: - data->block[0] = inb_p(SMBHSTDAT0); - i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ - for (i = 1; i <= data->block[0]; i++) - data->block[i] = inb_p(SMBBLKDAT); - break; - } - return 0; -} - -static void piix4_inc(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -static void piix4_dec(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - -u32 piix4_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA; -} - -static struct i2c_algorithm smbus_algorithm = { - .name = "Non-I2C SMBus adapter", - .id = I2C_ALGO_SMBUS, - .smbus_xfer = piix4_access, - .functionality = piix4_func, -}; - -static struct i2c_adapter piix4_adapter = { - .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_PIIX4, - .algo = &smbus_algorithm, - .inc_use = piix4_inc, - .dec_use = piix4_dec, -}; - -#define PCI_DEVICE_ID_ATI_IXP200_SMBUS 0x4353 -#define PCI_DEVICE_ID_ATI_IXP300_SMBUS 0x4363 -#define PCI_DEVICE_ID_ATI_IXP400_SMBUS 0x4372 -#define PCI_DEVICE_ID_ATI_IXP600_SMBUS 0x4385 - -#ifndef PCI_DEVICE_ID_SERVERWORKS_CSB6 -#define PCI_DEVICE_ID_SERVERWORKS_CSB6 0x0203 -#endif - -#define PCI_DEVICE_ID_SERVERWORKS_HT1000SB 0x0205 - -static struct pci_device_id piix4_ids[] __devinitdata = { - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82371AB_3, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = 3 - }, - { - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_IXP200_SMBUS, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = 0, - }, - { - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_IXP300_SMBUS, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = 0, - }, - { - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_IXP400_SMBUS, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = 0, - }, - { - .vendor = PCI_VENDOR_ID_ATI, - .device = PCI_DEVICE_ID_ATI_IXP600_SMBUS, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = 0, - }, - { - .vendor = PCI_VENDOR_ID_SERVERWORKS, - .device = PCI_DEVICE_ID_SERVERWORKS_OSB4, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = 0, - }, - { - .vendor = PCI_VENDOR_ID_SERVERWORKS, - .device = PCI_DEVICE_ID_SERVERWORKS_CSB5, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = 0, - }, - { - .vendor = PCI_VENDOR_ID_SERVERWORKS, - .device = PCI_DEVICE_ID_SERVERWORKS_CSB6, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = 0, - }, - { - .vendor = PCI_VENDOR_ID_SERVERWORKS, - .device = PCI_DEVICE_ID_SERVERWORKS_HT1000SB, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = 0, - }, - { - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82443MX_3, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = 3, - }, - { - .vendor = PCI_VENDOR_ID_EFAR, - .device = PCI_DEVICE_ID_EFAR_SLC90E66_3, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = 0, - }, - { 0, } -}; - -static int __devinit piix4_probe(struct pci_dev *dev, - const struct pci_device_id *id) -{ - int retval; - - retval = piix4_setup(dev, id); - if (retval) - return retval; - - sprintf(piix4_adapter.name, "SMBus PIIX4 adapter at %04x", - piix4_smba); - - if ((retval = i2c_add_adapter(&piix4_adapter))) { - printk(KERN_ERR "i2c-piix4.o: Couldn't register adapter!\n"); - release_region(piix4_smba, SMBIOSIZE); - piix4_smba = 0; - } - - return retval; -} - -static void __devexit piix4_remove(struct pci_dev *dev) -{ - if (piix4_smba) { - i2c_del_adapter(&piix4_adapter); - release_region(piix4_smba, SMBIOSIZE); - piix4_smba = 0; - } -} - -static struct pci_driver piix4_driver = { - .name = "piix4 smbus", - .id_table = piix4_ids, - .probe = piix4_probe, - .remove = __devexit_p(piix4_remove), -}; - -static int __init i2c_piix4_init(void) -{ - printk("i2c-piix4.o version %s (%s)\n", LM_VERSION, LM_DATE); - return pci_module_init(&piix4_driver); -} - -static void __exit i2c_piix4_exit(void) -{ - pci_unregister_driver(&piix4_driver); -} - -MODULE_AUTHOR("Frodo Looijaard and " - "Philip Edelbrock "); -MODULE_DESCRIPTION("PIIX4 SMBus driver"); -MODULE_LICENSE("GPL"); - -module_init(i2c_piix4_init); -module_exit(i2c_piix4_exit); diff --git a/kernel/busses/i2c-savage4.c b/kernel/busses/i2c-savage4.c deleted file mode 100644 index b34239f0..00000000 --- a/kernel/busses/i2c-savage4.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - i2c-savage4.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (C) 1998-2003 The LM Sensors Team - Alexander Wold - Mark D. Studebaker - - Based on i2c-voodoo3.c. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* This interfaces to the I2C bus of the Savage4 to gain access to - the BT869 and possibly other I2C devices. The DDC bus is not - yet supported because its register is not memory-mapped. - However we leave the DDC code here, commented out, to make - it easier to add later. -*/ - -#include -#include -#include -#include -#include -#include -#include /* for HZ */ -#include "version.h" -#include "sensors_compat.h" - -/* 3DFX defines */ -/* #define PCI_VENDOR_ID_S3 0x5333 */ -#define PCI_CHIP_SAVAGE3D 0x8A20 -#define PCI_CHIP_SAVAGE3D_MV 0x8A21 -#define PCI_CHIP_SAVAGE4 0x8A22 -#define PCI_CHIP_SAVAGE2000 0x9102 -#define PCI_CHIP_PROSAVAGE_PM 0x8A25 -#define PCI_CHIP_PROSAVAGE_KM 0x8A26 -#define PCI_CHIP_SAVAGE_MX_MV 0x8c10 -#define PCI_CHIP_SAVAGE_MX 0x8c11 -#define PCI_CHIP_SAVAGE_IX_MV 0x8c12 -#define PCI_CHIP_SAVAGE_IX 0x8c13 - -#define REG 0xff20 /* Serial Port 1 Register */ - -/* bit locations in the register */ -//#define DDC_ENAB 0x00040000 -//#define DDC_SCL_OUT 0x00080000 -//#define DDC_SDA_OUT 0x00100000 -//#define DDC_SCL_IN 0x00200000 -//#define DDC_SDA_IN 0x00400000 -#define I2C_ENAB 0x00000020 -#define I2C_SCL_OUT 0x00000001 -#define I2C_SDA_OUT 0x00000002 -#define I2C_SCL_IN 0x00000008 -#define I2C_SDA_IN 0x00000010 - -/* initialization states */ -#define INIT2 0x20 -/* #define INIT3 0x4 */ - -/* delays */ -#define CYCLE_DELAY 10 -#define TIMEOUT (HZ / 2) - - -static void config_s4(struct pci_dev *dev); - -static unsigned long ioaddr; - -/* The sav GPIO registers don't have individual masks for each bit - so we always have to read before writing. */ - -static void bit_savi2c_setscl(void *data, int val) -{ - unsigned int r; - r = readl(ioaddr + REG); - if(val) - r |= I2C_SCL_OUT; - else - r &= ~I2C_SCL_OUT; - writel(r, ioaddr + REG); - readl(ioaddr + REG); /* flush posted write */ -} - -static void bit_savi2c_setsda(void *data, int val) -{ - unsigned int r; - r = readl(ioaddr + REG); - if(val) - r |= I2C_SDA_OUT; - else - r &= ~I2C_SDA_OUT; - writel(r, ioaddr + REG); - readl(ioaddr + REG); /* flush posted write */ -} - -/* The GPIO pins are open drain, so the pins always remain outputs. - We rely on the i2c-algo-bit routines to set the pins high before - reading the input from other chips. */ - -static int bit_savi2c_getscl(void *data) -{ - return (0 != (readl(ioaddr + REG) & I2C_SCL_IN)); -} - -static int bit_savi2c_getsda(void *data) -{ - return (0 != (readl(ioaddr + REG) & I2C_SDA_IN)); -} - -/* Configures the chip */ - -void config_s4(struct pci_dev *dev) -{ - unsigned int cadr; - - /* map memory */ - cadr = dev->resource[0].start; - cadr &= PCI_BASE_ADDRESS_MEM_MASK; - ioaddr = (unsigned long)ioremap_nocache(cadr, 0x0080000); - if(ioaddr) { -// writel(0x8160, ioaddr + REG2); - writel(0x00000020, ioaddr + REG); - printk("i2c-savage4: Using Savage4 at 0x%lx\n", ioaddr); - } -} - -static void savage4_inc(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -static void savage4_dec(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - -static struct i2c_algo_bit_data sav_i2c_bit_data = { - .setsda = bit_savi2c_setsda, - .setscl = bit_savi2c_setscl, - .getsda = bit_savi2c_getsda, - .getscl = bit_savi2c_getscl, - .udelay = CYCLE_DELAY, - .mdelay = CYCLE_DELAY, - .timeout = TIMEOUT -}; - -static struct i2c_adapter savage4_i2c_adapter = { - .name = "I2C Savage4 adapter", - .id = I2C_HW_B_SAVG, - .algo_data = &sav_i2c_bit_data, - .inc_use = savage4_inc, - .dec_use = savage4_dec, -}; - -static struct pci_device_id savage4_ids[] __devinitdata = { - { - .vendor = PCI_VENDOR_ID_S3, - .device = PCI_CHIP_SAVAGE4, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .vendor = PCI_VENDOR_ID_S3, - .device = PCI_CHIP_SAVAGE2000, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { 0, } -}; - -static int __devinit savage4_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - config_s4(dev); - return i2c_bit_add_bus(&savage4_i2c_adapter); -} - -static void __devexit savage4_remove(struct pci_dev *dev) -{ - i2c_bit_del_bus(&savage4_i2c_adapter); -} - - -/* Don't register driver to avoid driver conflicts */ -/* -static struct pci_driver savage4_driver = { - .name = "savage4 smbus", - .id_table = savage4_ids, - .probe = savage4_probe, - .remove = __devexit_p(savage4_remove), -}; -*/ - -static int __init i2c_savage4_init(void) -{ - struct pci_dev *dev; - const struct pci_device_id *id; - - printk("i2c-savage4.o version %s (%s)\n", LM_VERSION, LM_DATE); -/* - return pci_module_init(&savage4_driver); -*/ - pci_for_each_dev(dev) { - id = pci_match_device(savage4_ids, dev); - if(id) - if(savage4_probe(dev, id) >= 0) - return 0; - } - return -ENODEV; -} - -static void __exit i2c_savage4_exit(void) -{ -/* - pci_unregister_driver(&savage4_driver); -*/ - savage4_remove(NULL); - iounmap((void *)ioaddr); -} - -MODULE_AUTHOR("Alexander Wold " - "and Mark D. Studebaker "); -MODULE_DESCRIPTION("Savage4 I2C/SMBus driver"); -MODULE_LICENSE("GPL"); - -module_init(i2c_savage4_init); -module_exit(i2c_savage4_exit); diff --git a/kernel/busses/i2c-sis5595.c b/kernel/busses/i2c-sis5595.c deleted file mode 100644 index e0c8b6ce..00000000 --- a/kernel/busses/i2c-sis5595.c +++ /dev/null @@ -1,495 +0,0 @@ -/* - sis5595.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998, 1999 Frodo Looijaard and - Philip Edelbrock - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* Note: we assume there can only be one SIS5595 with one SMBus interface */ - -/* - Note: all have mfr. ID 0x1039. - SUPPORTED PCI ID - 5595 0008 - - Note: these chips contain a 0008 device which is incompatible with the - 5595. We recognize these by the presence of the listed - "blacklist" PCI ID and refuse to load. - - NOT SUPPORTED PCI ID BLACKLIST PCI ID - 540 0008 0540 - 550 0008 0550 - 5513 0008 5511 - 5581 0008 5597 - 5582 0008 5597 - 5597 0008 5597 - 5598 0008 5597/5598 - 630 0008 0630 - 645 0008 0645 - 646 0008 0646 - 648 0008 0648 - 650 0008 0650 - 651 0008 0651 - 730 0008 0730 - 735 0008 0735 - 745 0008 0745 - 746 0008 0746 -*/ - -/* TO DO: - * Add Block Transfers (ugly, but supported by the adapter) - * Add adapter resets - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "version.h" -#include "sensors_compat.h" - -MODULE_LICENSE("GPL"); - -static int blacklist[] = { - PCI_DEVICE_ID_SI_540, - PCI_DEVICE_ID_SI_550, - PCI_DEVICE_ID_SI_630, - PCI_DEVICE_ID_SI_730, - PCI_DEVICE_ID_SI_5511, /* 5513 chip has the 0008 device but - that ID shows up in other chips so we - use the 5511 ID for recognition */ - PCI_DEVICE_ID_SI_5597, - PCI_DEVICE_ID_SI_5598, - 0x645, - 0x646, - 0x648, - 0x650, - 0x651, - 0x735, - 0x745, - 0x746, - 0 }; - -/* Length of ISA address segment */ -#define SIS5595_EXTENT 8 -/* SIS5595 SMBus registers */ -#define SMB_STS_LO 0x00 -#define SMB_STS_HI 0x01 -#define SMB_CTL_LO 0x02 -#define SMB_CTL_HI 0x03 -#define SMB_ADDR 0x04 -#define SMB_CMD 0x05 -#define SMB_PCNT 0x06 -#define SMB_CNT 0x07 -#define SMB_BYTE 0x08 -#define SMB_DEV 0x10 -#define SMB_DB0 0x11 -#define SMB_DB1 0x12 -#define SMB_HAA 0x13 - -/* PCI Address Constants */ -#define SMB_INDEX 0x38 -#define SMB_DAT 0x39 -#define SIS5595_ENABLE_REG 0x40 -#define ACPI_BASE 0x90 - -/* Other settings */ -#define MAX_TIMEOUT 500 - -/* SIS5595 constants */ -#define SIS5595_QUICK 0x00 -#define SIS5595_BYTE 0x02 -#define SIS5595_BYTE_DATA 0x04 -#define SIS5595_WORD_DATA 0x06 -#define SIS5595_PROC_CALL 0x08 -#define SIS5595_BLOCK_DATA 0x0A - -/* insmod parameters */ - -/* If force_addr is set to anything different from 0, we forcibly enable - the device at the given address. */ -static int force_addr = 0; -MODULE_PARM(force_addr, "i"); -MODULE_PARM_DESC(force_addr, - "Initialize the base address of the i2c controller"); - -static int sis5595_transaction(void); - -static struct pci_driver sis5595_driver; -static unsigned short sis5595_base = 0; - -static u8 sis5595_read(u8 reg) -{ - outb(reg, sis5595_base + SMB_INDEX); - return inb(sis5595_base + SMB_DAT); -} - -static void sis5595_write(u8 reg, u8 data) -{ - outb(reg, sis5595_base + SMB_INDEX); - outb(data, sis5595_base + SMB_DAT); -} - - -/* Detect whether a SIS5595 can be found, and initialize it, where necessary. - Note the differences between kernels with the old PCI BIOS interface and - newer kernels with the real PCI interface. In compat.h some things are - defined to make the transition easier. */ -int sis5595_setup(struct pci_dev *SIS5595_dev) -{ - u16 a; - u8 val; - int *i; - - /* Look for imposters */ - for(i = blacklist; *i != 0; i++) { - if (pci_find_device(PCI_VENDOR_ID_SI, *i, NULL)) { - printk("i2c-sis5595.o: Error: Looked for SIS5595 but found unsupported device %.4X\n", *i); - return -ENODEV; - } - } - -/* Determine the address of the SMBus areas */ - pci_read_config_word(SIS5595_dev, ACPI_BASE, &sis5595_base); - if(sis5595_base == 0 && force_addr == 0) { - printk("i2c-sis5595.o: ACPI base address uninitialized - upgrade BIOS or use force_addr=0xaddr\n"); - return -ENODEV; - } - - if(force_addr) - sis5595_base = force_addr & ~(SIS5595_EXTENT - 1); -#ifdef DEBUG - printk("ACPI Base address: %04x\n", sis5595_base); -#endif - /* NB: We grab just the two SMBus registers here, but this may still - * interfere with ACPI :-( */ - if (check_region(sis5595_base + SMB_INDEX, 2)) { - printk - ("i2c-sis5595.o: SMBus registers 0x%04x-0x%04x already in use!\n", - sis5595_base + SMB_INDEX, - sis5595_base + SMB_INDEX + 1); - return -ENODEV; - } - - if(force_addr) { - printk("i2c-sis5595.o: forcing ISA address 0x%04X\n", sis5595_base); - if (PCIBIOS_SUCCESSFUL != - pci_write_config_word(SIS5595_dev, ACPI_BASE, sis5595_base)) - return -ENODEV; - if (PCIBIOS_SUCCESSFUL != - pci_read_config_word(SIS5595_dev, ACPI_BASE, &a)) - return -ENODEV; - if ((a & ~(SIS5595_EXTENT - 1)) != sis5595_base) { - /* doesn't work for some chips! */ - printk("i2c-sis5595.o: force address failed - not supported?\n"); - return -ENODEV; - } - } - - if (PCIBIOS_SUCCESSFUL != - pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val)) - return -ENODEV; - if((val & 0x80) == 0) { - printk("sis5595.o: enabling ACPI\n"); - if (PCIBIOS_SUCCESSFUL != - pci_write_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, - val | 0x80)) - return -ENODEV; - if (PCIBIOS_SUCCESSFUL != - pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val)) - return -ENODEV; - if((val & 0x80) == 0) { /* doesn't work for some chips? */ - printk("sis5595.o: ACPI enable failed - not supported?\n"); - return -ENODEV; - } - } - - /* Everything is happy, let's grab the memory and set things up. */ - request_region(sis5595_base + SMB_INDEX, 2, sis5595_driver.name); - return(0); -} - - -/* Another internally used function */ -int sis5595_transaction(void) -{ - int temp; - int result = 0; - int timeout = 0; - - /* Make sure the SMBus host is ready to start transmitting */ - if ( - (temp = - sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) != - 0x00) { -#ifdef DEBUG - printk("i2c-sis5595.o: SMBus busy (%04x). Resetting...\n", - temp); -#endif - sis5595_write(SMB_STS_LO, temp & 0xff); - sis5595_write(SMB_STS_HI, temp >> 8); - if ( - (temp = - sis5595_read(SMB_STS_LO) + - (sis5595_read(SMB_STS_HI) << 8)) != 0x00) { -#ifdef DEBUG - printk("i2c-sis5595.o: Failed! (%02x)\n", temp); -#endif - return -1; - } else { -#ifdef DEBUG - printk("i2c-sis5595.o: Successful!\n"); -#endif - } - } - - /* start the transaction by setting bit 4 */ - sis5595_write(SMB_CTL_LO, sis5595_read(SMB_CTL_LO) | 0x10); - - /* We will always wait for a fraction of a second! */ - do { - i2c_delay(1); - temp = sis5595_read(SMB_STS_LO); - } while (!(temp & 0x40) && (timeout++ < MAX_TIMEOUT)); - - /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { -#ifdef DEBUG - printk("i2c-sis5595.o: SMBus Timeout!\n"); -#endif - result = -1; - } - - if (temp & 0x10) { - result = -1; -#ifdef DEBUG - printk("i2c-sis5595.o: Error: Failed bus transaction\n"); -#endif - } - - if (temp & 0x20) { - result = -1; - printk - ("i2c-sis5595.o: Bus collision! SMBus may be locked until next hard\n" - "reset (or not...)\n"); - /* Clock stops and slave is stuck in mid-transmission */ - } - - if ( - (temp = - sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) != - 0x00) { - sis5595_write(SMB_STS_LO, temp & 0xff); - sis5595_write(SMB_STS_HI, temp >> 8); - } - - if ( - (temp = - sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) != - 0x00) { - -#ifdef DEBUG - printk - ("i2c-sis5595.o: Failed reset at end of transaction (%02x)\n", - temp); -#endif - } - return result; -} - -/* Return -1 on error. */ -s32 sis5595_access(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data * data) -{ - switch (size) { - case I2C_SMBUS_QUICK: - sis5595_write(SMB_ADDR, - ((addr & 0x7f) << 1) | (read_write & 0x01)); - size = SIS5595_QUICK; - break; - case I2C_SMBUS_BYTE: - sis5595_write(SMB_ADDR, - ((addr & 0x7f) << 1) | (read_write & 0x01)); - if (read_write == I2C_SMBUS_WRITE) - sis5595_write(SMB_CMD, command); - size = SIS5595_BYTE; - break; - case I2C_SMBUS_BYTE_DATA: - sis5595_write(SMB_ADDR, - ((addr & 0x7f) << 1) | (read_write & 0x01)); - sis5595_write(SMB_CMD, command); - if (read_write == I2C_SMBUS_WRITE) - sis5595_write(SMB_BYTE, data->byte); - size = SIS5595_BYTE_DATA; - break; - case I2C_SMBUS_PROC_CALL: - case I2C_SMBUS_WORD_DATA: - sis5595_write(SMB_ADDR, - ((addr & 0x7f) << 1) | (read_write & 0x01)); - sis5595_write(SMB_CMD, command); - if (read_write == I2C_SMBUS_WRITE) { - sis5595_write(SMB_BYTE, data->word & 0xff); - sis5595_write(SMB_BYTE + 1, - (data->word & 0xff00) >> 8); - } - size = - (size == - I2C_SMBUS_PROC_CALL) ? SIS5595_PROC_CALL : - SIS5595_WORD_DATA; - break; -/* - case I2C_SMBUS_BLOCK_DATA: - printk("sis5595.o: Block data not yet implemented!\n"); - return -1; - break; -*/ - default: - printk - (KERN_WARNING "sis5595.o: Unsupported transaction %d\n", size); - return -1; - } - - sis5595_write(SMB_CTL_LO, ((size & 0x0E))); - - if (sis5595_transaction()) /* Error in transaction */ - return -1; - - if ((size != SIS5595_PROC_CALL) && - ((read_write == I2C_SMBUS_WRITE) || (size == SIS5595_QUICK))) - return 0; - - - switch (size) { - case SIS5595_BYTE: /* Where is the result put? I assume here it is in - SMB_DATA but it might just as well be in the - SMB_CMD. No clue in the docs */ - case SIS5595_BYTE_DATA: - data->byte = sis5595_read(SMB_BYTE); - break; - case SIS5595_WORD_DATA: - case SIS5595_PROC_CALL: - data->word = - sis5595_read(SMB_BYTE) + - (sis5595_read(SMB_BYTE + 1) << 8); - break; - } - return 0; -} - -static void sis5595_inc(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -static void sis5595_dec(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - -u32 sis5595_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_PROC_CALL; -} - - -static struct i2c_algorithm smbus_algorithm = { - .name = "Non-I2C SMBus adapter", - .id = I2C_ALGO_SMBUS, - .smbus_xfer = sis5595_access, - .functionality = sis5595_func, -}; - -static struct i2c_adapter sis5595_adapter = { - .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_SIS5595, - .algo = &smbus_algorithm, - .inc_use = sis5595_inc, - .dec_use = sis5595_dec, -}; - - -static struct pci_device_id sis5595_ids[] __devinitdata = { - { - .vendor = PCI_VENDOR_ID_SI, - .device = PCI_DEVICE_ID_SI_503, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { 0, } -}; - -static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - - if (sis5595_setup(dev)) { - printk - ("i2c-sis5595.o: SIS5595 not detected, module not inserted.\n"); - - return -ENODEV; - } - - sprintf(sis5595_adapter.name, "SMBus SIS5595 adapter at %04x", - sis5595_base + SMB_INDEX); - i2c_add_adapter(&sis5595_adapter); - - return 0; -} - -static void __devexit sis5595_remove(struct pci_dev *dev) -{ - i2c_del_adapter(&sis5595_adapter); - release_region(sis5595_base + SMB_INDEX, 2); -} - - -static struct pci_driver sis5595_driver = { - .name = "sis5595 smbus", - .id_table = sis5595_ids, - .probe = sis5595_probe, - .remove = __devexit_p(sis5595_remove), -}; - -static int __init i2c_sis5595_init(void) -{ - printk("i2c-sis5595.o version %s (%s)\n", LM_VERSION, LM_DATE); - return pci_module_init(&sis5595_driver); -} - - -static void __exit i2c_sis5595_exit(void) -{ - pci_unregister_driver(&sis5595_driver); -} - - - -MODULE_AUTHOR("Frodo Looijaard "); -MODULE_DESCRIPTION("SIS5595 SMBus driver"); - -module_init(i2c_sis5595_init); -module_exit(i2c_sis5595_exit); diff --git a/kernel/busses/i2c-sis630.c b/kernel/busses/i2c-sis630.c deleted file mode 100644 index 88c02d9f..00000000 --- a/kernel/busses/i2c-sis630.c +++ /dev/null @@ -1,544 +0,0 @@ -/* - i2c-sis630.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - - Copyright (c) 2002,2003 Alexander Malysh - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - Changes: - 24.08.2002 - Fixed the typo in sis630_access (Thanks to Mark M. Hoffman) - Changed sis630_transaction.(Thanks to Mark M. Hoffman) - 18.09.2002 - Added SIS730 as supported. - 21.09.2002 - Added high_clock module option.If this option is set - used Host Master Clock 56KHz (default 14KHz).For now we save old Host - Master Clock and after transaction completed restore (otherwise - it's confuse BIOS and hung Machine). - 24.09.2002 - Fixed typo in sis630_access - Fixed logical error by restoring of Host Master Clock - 31.07.2003 - Added block data read/write support. -*/ - -/* - Status: beta - - Supports: - SIS 630 - SIS 730 - - Note: we assume there can only be one device, with one SMBus interface. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "version.h" -#include "sensors_compat.h" - - -#ifdef DEBUG -#define DBG(x...) printk(KERN_DEBUG "i2c-sis630.o: " x) -#else -#define DBG(x...) -#endif - -/* SIS630 SMBus registers */ -#define SMB_STS 0x80 /* status */ -#define SMB_EN 0x81 /* status enable */ -#define SMB_CNT 0x82 -#define SMBHOST_CNT 0x83 -#define SMB_ADDR 0x84 -#define SMB_CMD 0x85 -#define SMB_PCOUNT 0x86 /* processed count */ -#define SMB_COUNT 0x87 -#define SMB_BYTE 0x88 /* ~0x8F data byte field */ -#define SMBDEV_ADDR 0x90 -#define SMB_DB0 0x91 -#define SMB_DB1 0x92 -#define SMB_SAA 0x93 - -/* register count for request_region */ -#define SIS630_SMB_IOREGION 20 - -/* PCI address constants */ -/* acpi base address register */ -#define SIS630_ACPI_BASE_REG 0x74 -/* bios control register */ -#define SIS630_BIOS_CTL_REG 0x40 - -/* Other settings */ -#define MAX_TIMEOUT 500 - -/* SIS630 constants */ -#define SIS630_QUICK 0x00 -#define SIS630_BYTE 0x01 -#define SIS630_BYTE_DATA 0x02 -#define SIS630_WORD_DATA 0x03 -#define SIS630_PCALL 0x04 -#define SIS630_BLOCK_DATA 0x05 - -static struct pci_driver sis630_driver; - -/* insmod parameters */ -static int high_clock = 0; -static int force = 0; -MODULE_PARM(high_clock, "i"); -MODULE_PARM_DESC(high_clock, "Set Host Master Clock to 56KHz (default 14KHz)."); -MODULE_PARM(force, "i"); -MODULE_PARM_DESC(force, "Forcibly enable the SIS630. DANGEROUS!"); - -/* acpi base address */ -static unsigned short acpi_base = 0; - -/* supported chips */ -static int supported[] = { - PCI_DEVICE_ID_SI_630, - PCI_DEVICE_ID_SI_730, - 0 /* terminates the list */ -}; - -static inline u8 sis630_read(u8 reg) { - return inb(acpi_base + reg); -} - -static inline void sis630_write(u8 reg, u8 data) { - outb(data, acpi_base + reg); -} - -static int sis630_transaction_start(int size, u8 *oldclock) { - int temp; - - /* - Make sure the SMBus host is ready to start transmitting. - */ - if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) { - DBG("SMBus busy (%02x).Resetting...\n",temp); - /* kill smbus transaction */ - sis630_write(SMBHOST_CNT, 0x20); - - if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) { - DBG("Failed! (%02x)\n", temp); - return -1; - } else { - DBG("Successful!\n"); - } - } - - /* save old clock, so we can prevent machine for hung */ - *oldclock = sis630_read(SMB_CNT); - - DBG("saved clock 0x%02x\n", *oldclock); - - /* disable timeout interrupt , set Host Master Clock to 56KHz if requested */ - if (high_clock > 0) - sis630_write(SMB_CNT, 0x20); - else - sis630_write(SMB_CNT, (*oldclock & ~0x40)); - - /* clear all sticky bits */ - temp = sis630_read(SMB_STS); - sis630_write(SMB_STS, temp & 0x1e); - - /* start the transaction by setting bit 4 and size */ - sis630_write(SMBHOST_CNT,0x10 | (size & 0x07)); - - return 0; -} - -static int sis630_transaction_wait(int size) { - int temp, result = 0, timeout = 0; - - /* We will always wait for a fraction of a second! */ - do { - i2c_delay(1); - temp = sis630_read(SMB_STS); - /* check if block transmitted */ - if (size == SIS630_BLOCK_DATA && (temp & 0x10)) - break; - } while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT)); - - /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { - DBG("SMBus Timeout!\n"); - result = -1; - } - - if (temp & 0x02) { - result = -1; - DBG("Error: Failed bus transaction\n"); - } - - if (temp & 0x04) { - result = -1; - printk(KERN_ERR "i2c-sis630.o: Bus collision!\n"); - /* - TBD: Datasheet say: - the software should clear this bit and restart SMBUS operation. - Should we do it or user start request again? - */ - } - - return result; -} - -static void sis630_transaction_end(u8 oldclock) { - int temp = 0; - - /* clear all status "sticky" bits */ - sis630_write(SMB_STS, temp); - - DBG("SMB_CNT before clock restore 0x%02x\n", sis630_read(SMB_CNT)); - - /* - * restore old Host Master Clock if high_clock is set - * and oldclock was not 56KHz - */ - if (high_clock > 0 && !(oldclock & 0x20)) - sis630_write(SMB_CNT,(sis630_read(SMB_CNT) & ~0x20)); - - DBG("SMB_CNT after clock restore 0x%02x\n", sis630_read(SMB_CNT)); -} - -static int sis630_transaction(int size) { - int result = 0; - u8 oldclock = 0; - - if (!(result = sis630_transaction_start(size, &oldclock))) { - result = sis630_transaction_wait(size); - sis630_transaction_end(oldclock); - } - - return result; -} - -static int sis630_block_data(union i2c_smbus_data * data, int read_write) { - int i, len = 0, rc = 0; - u8 oldclock = 0; - - if (read_write == I2C_SMBUS_WRITE) { - len = data->block[0]; - if (len < 0) - len = 0; - else if (len > 32) - len = 32; - sis630_write(SMB_COUNT, len); - for (i=1; i <= len; i++) { - DBG("set data 0x%02x\n", data->block[i]); - /* set data */ - sis630_write(SMB_BYTE+(i-1)%8, data->block[i]); - if (i==8 || (len<8 && i==len)) { - DBG("start trans len=%d i=%d\n",len ,i); - /* first transaction */ - if (sis630_transaction_start(SIS630_BLOCK_DATA, &oldclock)) - return -1; - } - else if ((i-1)%8 == 7 || i==len) { - DBG("trans_wait len=%d i=%d\n",len,i); - if (i>8) { - DBG("clear smbary_sts len=%d i=%d\n",len,i); - /* - If this is not first transaction, - we must clear sticky bit. - clear SMBARY_STS - */ - sis630_write(SMB_STS,0x10); - } - if (sis630_transaction_wait(SIS630_BLOCK_DATA)) { - DBG("trans_wait failed\n"); - rc = -1; - break; - } - - } - } - } - else { /* read request */ - data->block[0] = len = 0; - if (sis630_transaction_start(SIS630_BLOCK_DATA, &oldclock)) { - return -1; - } - do { - if (sis630_transaction_wait(SIS630_BLOCK_DATA)) { - DBG("trans_wait failed\n"); - rc = -1; - break; - } - /* if this first transaction then read byte count */ - if (len == 0) - data->block[0] = sis630_read(SMB_COUNT); - - /* just to be sure */ - if (data->block[0] > 32) - data->block[0] = 32; - - DBG("block data read len=0x%x\n", data->block[0]); - - for (i=0; i < 8 && len < data->block[0]; i++,len++) { - DBG("read i=%d len=%d\n", i, len); - data->block[len+1] = sis630_read(SMB_BYTE+i); - } - - DBG("clear smbary_sts len=%d i=%d\n",len,i); - - /* clear SMBARY_STS */ - sis630_write(SMB_STS,0x10); - } while(len < data->block[0]); - } - - sis630_transaction_end(oldclock); - - return rc; -} - -/* Return -1 on error. */ -static s32 sis630_access(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data * data) -{ - - switch (size) { - case I2C_SMBUS_QUICK: - sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); - size = SIS630_QUICK; - break; - case I2C_SMBUS_BYTE: - sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); - if (read_write == I2C_SMBUS_WRITE) - sis630_write(SMB_CMD, command); - size = SIS630_BYTE; - break; - case I2C_SMBUS_BYTE_DATA: - sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); - sis630_write(SMB_CMD, command); - if (read_write == I2C_SMBUS_WRITE) - sis630_write(SMB_BYTE, data->byte); - size = SIS630_BYTE_DATA; - break; - case I2C_SMBUS_PROC_CALL: - case I2C_SMBUS_WORD_DATA: - sis630_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01)); - sis630_write(SMB_CMD, command); - if (read_write == I2C_SMBUS_WRITE) { - sis630_write(SMB_BYTE, data->word & 0xff); - sis630_write(SMB_BYTE + 1,(data->word & 0xff00) >> 8); - } - size = (size == I2C_SMBUS_PROC_CALL ? SIS630_PCALL : SIS630_WORD_DATA); - break; - case I2C_SMBUS_BLOCK_DATA: - sis630_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01)); - sis630_write(SMB_CMD, command); - size = SIS630_BLOCK_DATA; - return sis630_block_data(data, read_write); - default: - printk("Unsupported I2C size\n"); - return -1; - break; - } - - - if (sis630_transaction(size)) - return -1; - - if ((size != SIS630_PCALL) && - ((read_write == I2C_SMBUS_WRITE) || (size == SIS630_QUICK))) { - return 0; - } - - switch(size) { - case SIS630_BYTE: - case SIS630_BYTE_DATA: - data->byte = sis630_read(SMB_BYTE); - break; - case SIS630_PCALL: - case SIS630_WORD_DATA: - data->word = sis630_read(SMB_BYTE) + (sis630_read(SMB_BYTE + 1) << 8); - break; - default: - return -1; - break; - } - - return 0; -} - -static void sis630_inc(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -static void sis630_dec(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - - -static u32 sis630_func(struct i2c_adapter *adapter) { - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL | - I2C_FUNC_SMBUS_BLOCK_DATA; -} - -static int __devinit sis630_setup(struct pci_dev *sis630_dev) { - unsigned char b; - struct pci_dev *dummy = NULL; - int i; - - /* check for supported SiS devices */ - for (i=0; supported[i] > 0; i++) { - if ((dummy = pci_find_device(PCI_VENDOR_ID_SI, supported[i], dummy))) - break; /* found */ - } - - if (!dummy && force > 0) { - printk(KERN_ERR "i2c-sis630.o: WARNING: Can't detect SIS630 compatible device, but " - "loading because of force option enabled\n"); - } - else if (!dummy) { - return -ENODEV; - } - - /* - Enable ACPI first , so we can accsess reg 74-75 - in acpi io space and read acpi base addr - */ - if (PCIBIOS_SUCCESSFUL != - pci_read_config_byte(sis630_dev, SIS630_BIOS_CTL_REG,&b)) { - printk(KERN_ERR "i2c-sis630.o: Error: Can't read bios ctl reg\n"); - return -ENODEV; - } - - /* if ACPI already enabled , do nothing */ - if (!(b & 0x80) && - PCIBIOS_SUCCESSFUL != - pci_write_config_byte(sis630_dev,SIS630_BIOS_CTL_REG,b|0x80)) { - printk(KERN_ERR "i2c-sis630.o: Error: Can't enable ACPI\n"); - return -ENODEV; - } - /* Determine the ACPI base address */ - if (PCIBIOS_SUCCESSFUL != - pci_read_config_word(sis630_dev,SIS630_ACPI_BASE_REG,&acpi_base)) { - printk(KERN_ERR "i2c-sis630.o: Error: Can't determine ACPI base address\n"); - return -ENODEV; - } - - DBG("ACPI base at 0x%04x\n", acpi_base); - - /* Everything is happy, let's grab the memory and set things up. */ - if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION, - sis630_driver.name)){ - printk(KERN_ERR "i2c-sis630.o: SMBus registers 0x%04x-0x%04x " - "already in use!\n",acpi_base + SMB_STS, acpi_base + SMB_SAA); - acpi_base = 0; /* reset acpi_base */ - return -ENODEV; - } - - return 0; -} - - -static struct i2c_algorithm smbus_algorithm = { - .name = "Non-I2C SMBus adapter", - .id = I2C_ALGO_SMBUS, - .smbus_xfer = sis630_access, - .functionality = sis630_func, -}; - -static struct i2c_adapter sis630_adapter = { - .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_SIS630, - .algo = &smbus_algorithm, - .inc_use = sis630_inc, - .dec_use = sis630_dec, -}; - - -static struct pci_device_id sis630_ids[] __devinitdata = { - { - .vendor = PCI_VENDOR_ID_SI, - .device = PCI_DEVICE_ID_SI_503, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { 0, } -}; - -static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - if (sis630_setup(dev)) { - printk(KERN_ERR "i2c-sis630.o: SIS630 comp. bus not detected, module not inserted.\n"); - return -ENODEV; - } - - sprintf(sis630_adapter.name, "SMBus SIS630 adapter at %04x", - acpi_base + SMB_STS); - - return i2c_add_adapter(&sis630_adapter); -} - -static void __devexit sis630_remove(struct pci_dev *dev) -{ - if (acpi_base) { - i2c_del_adapter(&sis630_adapter); - release_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION); - acpi_base = 0; - } -} - - -static struct pci_driver sis630_driver = { - .name = "sis630 smbus", - .id_table = sis630_ids, - .probe = sis630_probe, - .remove = __devexit_p(sis630_remove), -}; - -static int __init i2c_sis630_init(void) -{ - printk("i2c-sis630.o version %s (%s)\n", LM_VERSION, LM_DATE); - return pci_module_init(&sis630_driver); -} - - -static void __exit i2c_sis630_exit(void) -{ - pci_unregister_driver(&sis630_driver); -} - - - - -MODULE_LICENSE("GPL"); - -MODULE_AUTHOR("Alexander Malysh "); -MODULE_DESCRIPTION("SIS630 SMBus driver"); - -module_init(i2c_sis630_init); -module_exit(i2c_sis630_exit); diff --git a/kernel/busses/i2c-sis645.c b/kernel/busses/i2c-sis645.c deleted file mode 100644 index 52916cf8..00000000 --- a/kernel/busses/i2c-sis645.c +++ /dev/null @@ -1,605 +0,0 @@ -/* - sis645.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - - Copyright (c) 2003 Mark M. Hoffman - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - This module must be considered BETA unless and until - the chipset manufacturer releases a datasheet. - - The register definitions are based on the SiS630. - The method for *finding* the registers is based on trial and error. - - A history of changes to this file is available by SVN: - http://www.lm-sensors.org/wiki/Download -*/ - -/* 25th March 2004 - Support for Sis655 chipsets added by Ken Healy -*/ - -/* - Note: we assume there can only be one SiS645 with one SMBus interface -*/ - -/* #define DEBUG 1 */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "version.h" -#include "sensors_compat.h" - -#define DRV_NAME "i2c-sis645" - -/* SiS645DX north bridge (defined in 2.4.21) */ -#ifndef PCI_DEVICE_ID_SI_646 -#define PCI_DEVICE_ID_SI_646 0x0646 -#endif - -/* SiS648 north bridge (defined in 2.4.21) */ -#ifndef PCI_DEVICE_ID_SI_648 -#define PCI_DEVICE_ID_SI_648 0x0648 -#endif - -/* SiS650 north bridge (defined in 2.4.19) */ -#ifndef PCI_DEVICE_ID_SI_650 -#define PCI_DEVICE_ID_SI_650 0x0650 -#endif - -/* SiS651 north bridge (defined in 2.4.21)*/ -#ifndef PCI_DEVICE_ID_SI_651 -#define PCI_DEVICE_ID_SI_651 0x0651 -#endif - -/* SiS655 north bridge (defined in 2.4.22)*/ -#ifndef PCI_DEVICE_ID_SI_655 -#define PCI_DEVICE_ID_SI_655 0x0655 -#endif - -/* SiS746 north bridge (defined in 2.4.21) */ -#ifndef PCI_DEVICE_ID_SI_746 -#define PCI_DEVICE_ID_SI_746 0x0746 -#endif - -/* SiS85C503/5513 (LPC Bridge) */ -#ifndef PCI_DEVICE_ID_SI_LPC -#define PCI_DEVICE_ID_SI_LPC 0x0018 -#endif - -/* SiS961 south bridge */ -#ifndef PCI_DEVICE_ID_SI_961 -#define PCI_DEVICE_ID_SI_961 0x0961 -#endif - -/* SiS962 south bridge */ -#ifndef PCI_DEVICE_ID_SI_962 -#define PCI_DEVICE_ID_SI_962 0x0962 -#endif - -/* SiS963 south bridge */ -#ifndef PCI_DEVICE_ID_SI_963 -#define PCI_DEVICE_ID_SI_963 0x0963 -#endif - -/* SMBus ID */ -#ifndef PCI_DEVICE_ID_SI_SMBUS -#define PCI_DEVICE_ID_SI_SMBUS 0x16 -#endif - -/* base address register in PCI config space */ -#define SIS645_BAR 0x04 - -/* SiS645 SMBus registers */ -#define SMB_STS 0x00 -#define SMB_EN 0x01 -#define SMB_CNT 0x02 -#define SMB_HOST_CNT 0x03 -#define SMB_ADDR 0x04 -#define SMB_CMD 0x05 -#define SMB_PCOUNT 0x06 -#define SMB_COUNT 0x07 -#define SMB_BYTE 0x08 -#define SMB_DEV_ADDR 0x10 -#define SMB_DB0 0x11 -#define SMB_DB1 0x12 -#define SMB_SAA 0x13 - -/* register count for request_region */ -#define SMB_IOSIZE 0x20 - -/* Other settings */ -#define MAX_TIMEOUT 500 - -/* SiS645 SMBus constants */ -#define SIS645_QUICK 0x00 -#define SIS645_BYTE 0x01 -#define SIS645_BYTE_DATA 0x02 -#define SIS645_WORD_DATA 0x03 -#define SIS645_PROC_CALL 0x04 -#define SIS645_BLOCK_DATA 0x05 - -static struct pci_driver sis645_driver; -static struct i2c_adapter sis645_adapter; -static u16 sis645_smbus_base = 0; - -static inline u8 sis645_read(u8 reg) -{ - return inb(sis645_smbus_base + reg) ; -} - -static inline void sis645_write(u8 reg, u8 data) -{ - outb(data, sis645_smbus_base + reg) ; -} - -#ifdef CONFIG_HOTPLUG - -/* Turns on SMBus device if it is not; return 0 iff successful - */ -static int __devinit sis645_enable_smbus(struct pci_dev *dev) -{ - u8 val = 0; - - pci_read_config_byte(dev, 0x77, &val); - -#ifdef DEBUG - printk(KERN_DEBUG DRV_NAME ": Config byte was 0x%02x.\n", val); -#endif - - pci_write_config_byte(dev, 0x77, val & ~0x10); - - pci_read_config_byte(dev, 0x77, &val); - - if (val & 0x10) { -#ifdef DEBUG - printk(KERN_DEBUG DRV_NAME ": Config byte stuck!\n"); -#endif - return -1; - } - - return 0; -} - -/* Builds the basic pci_dev for SiS645 SMBus - */ -static int __devinit sis645_build_dev(struct pci_dev **smbus_dev, - struct pci_dev *bridge_dev) -{ - struct pci_dev temp_dev; - u16 vid = 0, did = 0; - int ret; - - /* fill in the device structure for search */ - memset(&temp_dev, 0, sizeof(temp_dev)); - temp_dev.bus = bridge_dev->bus; - temp_dev.sysdata = bridge_dev->bus->sysdata; - temp_dev.hdr_type = PCI_HEADER_TYPE_NORMAL; - - /* the SMBus device is function 1 on the same unit as the ISA bridge */ - temp_dev.devfn = bridge_dev->devfn + 1; - - /* query to make sure */ - ret = pci_read_config_word(&temp_dev, PCI_VENDOR_ID, &vid); - if (ret || PCI_VENDOR_ID_SI != vid) { - printk(KERN_ERR DRV_NAME ": Couldn't find SMBus device!\n"); - return ret; - } - temp_dev.vendor = vid; - - ret = pci_read_config_word(&temp_dev, PCI_DEVICE_ID, &did); - if (ret || PCI_DEVICE_ID_SI_SMBUS != did) { - printk(KERN_ERR DRV_NAME ": Couldn't find SMBus device!\n"); - return ret; - } - temp_dev.device = did; - - /* ok, we've got it... request some memory and finish it off */ - *smbus_dev = kmalloc(sizeof(**smbus_dev), GFP_ATOMIC); - if (NULL == *smbus_dev) { - printk(KERN_ERR DRV_NAME ": Out of memory!\n"); - return -ENOMEM; - } - - **smbus_dev = temp_dev; - - ret = pci_setup_device(*smbus_dev); - if (ret) { - printk(KERN_ERR DRV_NAME ": pci_setup_device failed (0x%08x)\n",ret); - } - return ret; -} - -/* See if a SMBus can be found, and enable it if possible. - */ -static int __devinit sis645_hotplug_smbus(void) -{ - int ret; - struct pci_dev *smbus_dev, *bridge_dev ; - - if ((bridge_dev = pci_find_device(PCI_VENDOR_ID_SI, - PCI_DEVICE_ID_SI_961, NULL))) - printk(KERN_INFO DRV_NAME ": Found SiS961 south bridge.\n"); - - else if ((bridge_dev = pci_find_device(PCI_VENDOR_ID_SI, - PCI_DEVICE_ID_SI_962, NULL))) - printk(KERN_INFO DRV_NAME ": Found SiS962 [MuTIOL Media IO].\n"); - - else if ((bridge_dev = pci_find_device(PCI_VENDOR_ID_SI, - PCI_DEVICE_ID_SI_963, NULL))) - printk(KERN_INFO DRV_NAME ": Found SiS963 [MuTIOL Media IO].\n"); - - else if ((bridge_dev = pci_find_device(PCI_VENDOR_ID_SI, - PCI_DEVICE_ID_SI_503, NULL)) || - (bridge_dev = pci_find_device(PCI_VENDOR_ID_SI, - PCI_DEVICE_ID_SI_LPC, NULL))) { - - printk(KERN_INFO DRV_NAME ": Found SiS south bridge in compatability mode(?)\n"); - - /* look for known compatible north bridges */ - if ((NULL == pci_find_device(PCI_VENDOR_ID_SI, - PCI_DEVICE_ID_SI_645, NULL)) - && (NULL == pci_find_device(PCI_VENDOR_ID_SI, - PCI_DEVICE_ID_SI_646, NULL)) - && (NULL == pci_find_device(PCI_VENDOR_ID_SI, - PCI_DEVICE_ID_SI_648, NULL)) - && (NULL == pci_find_device(PCI_VENDOR_ID_SI, - PCI_DEVICE_ID_SI_650, NULL)) - && (NULL == pci_find_device(PCI_VENDOR_ID_SI, - PCI_DEVICE_ID_SI_651, NULL)) - && (NULL == pci_find_device(PCI_VENDOR_ID_SI, - PCI_DEVICE_ID_SI_655, NULL)) - && (NULL == pci_find_device(PCI_VENDOR_ID_SI, - PCI_DEVICE_ID_SI_735, NULL)) - && (NULL == pci_find_device(PCI_VENDOR_ID_SI, - PCI_DEVICE_ID_SI_745, NULL)) - && (NULL == pci_find_device(PCI_VENDOR_ID_SI, - PCI_DEVICE_ID_SI_746, NULL))) { - printk(KERN_ERR DRV_NAME ": Can't find suitable host bridge!\n"); - return -ENODEV; - } - } else { - printk(KERN_ERR DRV_NAME ": Can't find suitable south bridge!\n"); - return -ENODEV; - } - - /* if we get this far, we think the smbus device is present */ - - if ((ret = sis645_enable_smbus(bridge_dev))) - return ret; - - if ((ret = sis645_build_dev(&smbus_dev, bridge_dev))) - return ret; - - if ((ret = pci_enable_device(smbus_dev))) { - printk(KERN_ERR DRV_NAME ": Can't pci_enable SMBus device!" - " (0x%08x)\n", ret); - return ret; - } - - pci_insert_device(smbus_dev, smbus_dev->bus); - - return 0; -} -#endif /* CONFIG_HOTPLUG */ - -/* Execute a SMBus transaction. - int size is from SIS645_QUICK to SIS645_BLOCK_DATA - */ -static int sis645_transaction(int size) -{ - int temp; - int result = 0; - int timeout = 0; - - /* Make sure the SMBus host is ready to start transmitting */ - if (((temp = sis645_read(SMB_CNT)) & 0x03) != 0x00) { -#ifdef DEBUG - printk(KERN_DEBUG DRV_NAME ": SMBus busy (0x%02x). Resetting...\n", - temp); -#endif - - /* kill the transaction */ - sis645_write(SMB_HOST_CNT, 0x20); - - /* check it again */ - if (((temp = sis645_read(SMB_CNT)) & 0x03) != 0x00) { -#ifdef DEBUG - printk(KERN_DEBUG DRV_NAME ": Failed! (0x%02x)\n", temp); -#endif - return -1; - } else { -#ifdef DEBUG - printk(KERN_DEBUG DRV_NAME ": Successful!\n"); -#endif - } - } - - /* Turn off timeout interrupts, set fast host clock */ - sis645_write(SMB_CNT, 0x20); - - /* clear all (sticky) status flags */ - temp = sis645_read(SMB_STS); - sis645_write(SMB_STS, temp & 0x1e); - - /* start the transaction by setting bit 4 and size bits */ - sis645_write(SMB_HOST_CNT, 0x10 | (size & 0x07)); - - /* We will always wait for a fraction of a second! */ - do { - i2c_delay(1); - temp = sis645_read(SMB_STS); - } while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT)); - - /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { - printk(KERN_DEBUG DRV_NAME ": SMBus Timeout! (0x%02x)\n",temp); - result = -1; - } - - /* device error - probably missing ACK */ - if (temp & 0x02) { -#ifdef DEBUG - printk(KERN_DEBUG DRV_NAME ": Failed bus transaction!\n"); -#endif - result = -1; - } - - /* bus collision */ - if (temp & 0x04) { -#ifdef DEBUG - printk(KERN_DEBUG DRV_NAME ": Bus collision!\n"); -#endif - result = -1; - } - - /* Finish up by resetting the bus */ - sis645_write(SMB_STS, temp); - if ((temp = sis645_read(SMB_STS))) { -#ifdef DEBUG - printk(KERN_DEBUG DRV_NAME ": Failed reset at end of transaction!" - " (0x%02x)\n", temp); -#endif - } - - return result; -} - -/* Return -1 on error. */ -static s32 sis645_access(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data * data) -{ - - switch (size) { - case I2C_SMBUS_QUICK: - sis645_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); - size = SIS645_QUICK; - break; - - case I2C_SMBUS_BYTE: - sis645_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); - if (read_write == I2C_SMBUS_WRITE) - sis645_write(SMB_CMD, command); - size = SIS645_BYTE; - break; - - case I2C_SMBUS_BYTE_DATA: - sis645_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); - sis645_write(SMB_CMD, command); - if (read_write == I2C_SMBUS_WRITE) - sis645_write(SMB_BYTE, data->byte); - size = SIS645_BYTE_DATA; - break; - - case I2C_SMBUS_PROC_CALL: - case I2C_SMBUS_WORD_DATA: - sis645_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); - sis645_write(SMB_CMD, command); - if (read_write == I2C_SMBUS_WRITE) { - sis645_write(SMB_BYTE, data->word & 0xff); - sis645_write(SMB_BYTE + 1, (data->word & 0xff00) >> 8); - } - size = (size == I2C_SMBUS_PROC_CALL ? SIS645_PROC_CALL : SIS645_WORD_DATA); - break; - - case I2C_SMBUS_BLOCK_DATA: - /* TO DO: */ - printk(KERN_INFO DRV_NAME ": SMBus block not implemented!\n"); - return -1; - break; - - default: - printk(KERN_INFO DRV_NAME ": Unsupported I2C size\n"); - return -1; - break; - } - - if (sis645_transaction(size)) - return -1; - - if ((size != SIS645_PROC_CALL) && - ((read_write == I2C_SMBUS_WRITE) || (size == SIS645_QUICK))) - return 0; - - switch (size) { - case SIS645_BYTE: - case SIS645_BYTE_DATA: - data->byte = sis645_read(SMB_BYTE); - break; - - case SIS645_WORD_DATA: - case SIS645_PROC_CALL: - data->word = sis645_read(SMB_BYTE) + - (sis645_read(SMB_BYTE + 1) << 8); - break; - } - return 0; -} - -static void sis645_inc(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -static void sis645_dec(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - -static u32 sis645_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_PROC_CALL; -} - -static struct i2c_algorithm smbus_algorithm = { - .name = "Non-I2C SMBus adapter", - .id = I2C_ALGO_SMBUS, - .smbus_xfer = sis645_access, - .functionality = sis645_func, -}; - -static struct i2c_adapter sis645_adapter = { - .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_SIS645, - .algo = &smbus_algorithm, - .inc_use = sis645_inc, - .dec_use = sis645_dec, -}; - -static struct pci_device_id sis645_ids[] __devinitdata = { - { - .vendor = PCI_VENDOR_ID_SI, - .device = PCI_DEVICE_ID_SI_SMBUS, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { 0, } -}; - -static int __devinit sis645_probe(struct pci_dev *dev, - const struct pci_device_id *id) -{ - u16 ww = 0; - int retval; - - if (sis645_smbus_base) { - dev_err(dev, "Only one device supported.\n"); - return -EBUSY; - } - - pci_read_config_word(dev, PCI_CLASS_DEVICE, &ww); - if (PCI_CLASS_SERIAL_SMBUS != ww) { - dev_err(dev, "Unsupported device class 0x%04x!\n", ww); - return -ENODEV; - } - - sis645_smbus_base = pci_resource_start(dev, SIS645_BAR); - if (!sis645_smbus_base) { - dev_err(dev, "SiS645 SMBus base address " - "not initialized!\n"); - return -EINVAL; - } - dev_info(dev, "SiS645 SMBus base address: 0x%04x\n", - sis645_smbus_base); - - /* Everything is happy, let's grab the memory and set things up. */ - if (!request_region(sis645_smbus_base, SMB_IOSIZE, - sis645_driver.name)) { - dev_err(dev, "SMBus registers 0x%04x-0x%04x " - "already in use!\n", sis645_smbus_base, - sis645_smbus_base + SMB_IOSIZE - 1); - - sis645_smbus_base = 0; - return -EINVAL; - } - - sprintf(sis645_adapter.name, "SiS645 SMBus adapter at 0x%04x", - sis645_smbus_base); - - if ((retval = i2c_add_adapter(&sis645_adapter))) { - dev_err(dev, "Couldn't register adapter!\n"); - release_region(sis645_smbus_base, SMB_IOSIZE); - sis645_smbus_base = 0; - } - - return retval; -} - -static void __devexit sis645_remove(struct pci_dev *dev) -{ - if (sis645_smbus_base) { - i2c_del_adapter(&sis645_adapter); - release_region(sis645_smbus_base, SMB_IOSIZE); - sis645_smbus_base = 0; - } -} - -static struct pci_driver sis645_driver = { - .name = "sis645 smbus", - .id_table = sis645_ids, - .probe = sis645_probe, - .remove = __devexit_p(sis645_remove), -}; - -static int __init i2c_sis645_init(void) -{ - printk(KERN_INFO DRV_NAME ".o version %s (%s)\n", LM_VERSION, LM_DATE); - - /* if the required device id is not present, try to HOTPLUG it first */ - if (!pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_SMBUS, NULL)) { - - printk(KERN_INFO DRV_NAME ": " - "Attempting to enable SiS645 SMBus device\n"); - -#ifdef CONFIG_HOTPLUG - sis645_hotplug_smbus(); -#else - printk(KERN_INFO DRV_NAME ": " - "Requires kernel with CONFIG_HOTPLUG, sorry!\n"); -#endif - } - - return pci_module_init(&sis645_driver); -} - -static void __exit i2c_sis645_exit(void) -{ - pci_unregister_driver(&sis645_driver); -} - -MODULE_AUTHOR("Mark M. Hoffman "); -MODULE_DESCRIPTION("SiS645 SMBus driver"); -MODULE_LICENSE("GPL"); - -/* Register initialization functions using helper macros */ -module_init(i2c_sis645_init); -module_exit(i2c_sis645_exit); diff --git a/kernel/busses/i2c-tsunami.c b/kernel/busses/i2c-tsunami.c deleted file mode 100644 index 7b27c56b..00000000 --- a/kernel/busses/i2c-tsunami.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - i2c-tsunami.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 2001 Oleg Vdovikin - - Based on code written by Ralph Metzler and - Simon Vogl - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* This interfaces to the I2C bus of the Tsunami/Typhoon 21272 chipsets - to gain access to the on-board I2C devices. - - For more information refer to Compaq's - "Tsunami/Typhoon 21272 Chipset Hardware Reference Manual" - Order Number: DS-0025-TE -*/ - -#include -#include -#include -#include -#include -#include -#include -#include "version.h" -#include "sensors_compat.h" - -MODULE_LICENSE("GPL"); - -/* Memory Presence Detect Register (MPD-RW) bits - with except of reserved RAZ bits */ - -#define MPD_DR 0x8 /* Data receive - RO */ -#define MPD_CKR 0x4 /* Clock receive - RO */ -#define MPD_DS 0x2 /* Data send - Must be a 1 to receive - WO */ -#define MPD_CKS 0x1 /* Clock send - WO */ - -static inline void writempd(unsigned long value) -{ - TSUNAMI_cchip->mpd.csr = value; - mb(); -} - -static inline unsigned long readmpd(void) -{ - return TSUNAMI_cchip->mpd.csr; -} - -static void bit_tsunami_setscl(void *data, int val) -{ - /* read currently setted bits to modify them */ - unsigned long bits = readmpd() >> 2; /* assume output == input */ - - if (val) - bits |= MPD_CKS; - else - bits &= ~MPD_CKS; - - writempd(bits); -} - -static void bit_tsunami_setsda(void *data, int val) -{ - /* read currently setted bits to modify them */ - unsigned long bits = readmpd() >> 2; /* assume output == input */ - - if (val) - bits |= MPD_DS; - else - bits &= ~MPD_DS; - - writempd(bits); -} - -/* The MPD pins are open drain, so the pins always remain outputs. - We rely on the i2c-algo-bit routines to set the pins high before - reading the input from other chips. */ - -static int bit_tsunami_getscl(void *data) -{ - return (0 != (readmpd() & MPD_CKR)); -} - -static int bit_tsunami_getsda(void *data) -{ - return (0 != (readmpd() & MPD_DR)); -} - -static void i2c_tsunami_inc(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -static void i2c_tsunami_dec(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - -static struct i2c_algo_bit_data tsunami_i2c_bit_data = { - .setsda = bit_tsunami_setsda, - .setscl = bit_tsunami_setscl, - .getsda = bit_tsunami_getsda, - .getscl = bit_tsunami_getscl, - .udelay = 10, - .mdelay = 10, - .timeout = HZ/2 -}; - -static struct i2c_adapter tsunami_i2c_adapter = { - .name = "I2C Tsunami/Typhoon adapter", - .id = I2C_HW_B_TSUNA, - .algo_data = &tsunami_i2c_bit_data, - .inc_use = i2c_tsunami_inc, - .dec_use = i2c_tsunami_dec, -}; - - -#if 0 -static struct pci_driver tsunami_driver = { - .name = "tsunami smbus", - .id_table = tsunami_ids, - .probe = tsunami_probe, - .remove = __devexit_p(tsunami_remove), -}; -#endif - -static int __init i2c_tsunami_init(void) -{ - printk("i2c-tsunami.o version %s (%s)\n", LM_VERSION, LM_DATE); - - if (hwrpb->sys_type != ST_DEC_TSUNAMI) { - printk("i2c-tsunami.o: not Tsunami based system (%ld), module not inserted.\n", hwrpb->sys_type); - return -ENXIO; - } else { - printk("i2c-tsunami.o: using Cchip MPD at 0x%lx.\n", (long) &TSUNAMI_cchip->mpd); - } - return i2c_bit_add_bus(&tsunami_i2c_adapter); -} - - -static void __exit i2c_tsunami_exit(void) -{ - i2c_bit_del_bus(&tsunami_i2c_adapter); -} - - - -MODULE_AUTHOR("Oleg I. Vdovikin "); -MODULE_DESCRIPTION("Tsunami I2C/SMBus driver"); - -module_init(i2c_tsunami_init); -module_exit(i2c_tsunami_exit); diff --git a/kernel/busses/i2c-via.c b/kernel/busses/i2c-via.c deleted file mode 100644 index efe4f54a..00000000 --- a/kernel/busses/i2c-via.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - i2c-via.c - Part of lm_sensors, Linux kernel modules - for hardware monitoring - - i2c Support for Via Technologies 82C586B South Bridge - - Copyright (c) 1998, 1999 Kyösti Mälkki - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for HZ */ -#include "version.h" -#include "sensors_compat.h" - -/* Power management registers */ - -#define PM_CFG_REVID 0x08 /* silicon revision code */ -#define PM_CFG_IOBASE0 0x20 -#define PM_CFG_IOBASE1 0x48 - -#define I2C_DIR (pm_io_base+0x40) -#define I2C_OUT (pm_io_base+0x42) -#define I2C_IN (pm_io_base+0x44) -#define I2C_SCL 0x02 /* clock bit in DIR/OUT/IN register */ -#define I2C_SDA 0x04 - -/* io-region reservation */ -#define IOSPACE 0x06 -#define IOTEXT "via-i2c" - -static u16 pm_io_base = 0; - -/* - It does not appear from the datasheet that the GPIO pins are - open drain. So a we set a low value by setting the direction to - output and a high value by setting the direction to input and - relying on the required I2C pullup. The data value is initialized - to 0 in via_init() and never changed. -*/ - -static void bit_via_setscl(void *data, int state) -{ - outb(state ? inb(I2C_DIR) & ~I2C_SCL : inb(I2C_DIR) | I2C_SCL, - I2C_DIR); -} - -static void bit_via_setsda(void *data, int state) -{ - outb(state ? inb(I2C_DIR) & ~I2C_SDA : inb(I2C_DIR) | I2C_SDA, - I2C_DIR); -} - -static int bit_via_getscl(void *data) -{ - return (0 != (inb(I2C_IN) & I2C_SCL)); -} - -static int bit_via_getsda(void *data) -{ - return (0 != (inb(I2C_IN) & I2C_SDA)); -} - -static void bit_via_inc(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -static void bit_via_dec(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - -static struct i2c_algo_bit_data bit_data = { - .setsda = bit_via_setsda, - .setscl = bit_via_setscl, - .getsda = bit_via_getsda, - .getscl = bit_via_getscl, - .udelay = 5, - .mdelay = 5, - .timeout = HZ -}; - -static struct i2c_adapter vt586b_adapter = { - .name = "VIA i2c", - .id = I2C_HW_B_VIA, - .algo_data = &bit_data, - .inc_use = bit_via_inc, - .dec_use = bit_via_dec, -}; - - -static struct pci_device_id vt586b_ids[] __initdata = { - { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { 0, } -}; - -static int __init vt586b_probe(struct pci_dev *dev, - const struct pci_device_id *id) -{ - u16 base; - u8 rev; - int res; - - if (pm_io_base) { - printk(KERN_ERR "i2c-via.o: Will only support one host\n"); - return -EBUSY; - } - - pci_read_config_byte(dev, PM_CFG_REVID, &rev); - - switch (rev) { - case 0x00: - base = PM_CFG_IOBASE0; - break; - case 0x01: - case 0x10: - base = PM_CFG_IOBASE1; - break; - - default: - base = PM_CFG_IOBASE1; - /* later revision */ - } - - pci_read_config_word(dev, base, &pm_io_base); - pm_io_base &= (0xff << 8); - - if (! request_region(I2C_DIR, IOSPACE, IOTEXT)) { - printk("i2c-via.o: IO 0x%x-0x%x already in use\n", - I2C_DIR, I2C_DIR + IOSPACE); - return -EBUSY; - } - outb(inb(I2C_DIR) & ~(I2C_SDA | I2C_SCL), I2C_DIR); - outb(inb(I2C_OUT) & ~(I2C_SDA | I2C_SCL), I2C_OUT); - - res = i2c_bit_add_bus(&vt586b_adapter); - if ( res < 0 ) { - release_region(I2C_DIR, IOSPACE); - pm_io_base = 0; - return res; - } - return 0; -} - -static int __init i2c_vt586b_init(void) -{ - struct pci_dev *dev; - const struct pci_device_id *id; - - printk("i2c-via.o version %s (%s)\n", LM_VERSION, LM_DATE); - pci_for_each_dev(dev) { - id = pci_match_device(vt586b_ids, dev); - if(id) - if(vt586b_probe(dev, id) >= 0) - return 0; - } - return -ENODEV; -} - - -static void __exit i2c_vt586b_exit(void) -{ - i2c_bit_del_bus(&vt586b_adapter); - release_region(I2C_DIR, IOSPACE); -} - - -MODULE_AUTHOR("Kyösti Mälkki "); -MODULE_DESCRIPTION("i2c for Via vt82c586b southbridge"); -MODULE_LICENSE("GPL"); - -module_init(i2c_vt586b_init); -module_exit(i2c_vt586b_exit); diff --git a/kernel/busses/i2c-viapro.c b/kernel/busses/i2c-viapro.c deleted file mode 100644 index 3a6d70f2..00000000 --- a/kernel/busses/i2c-viapro.c +++ /dev/null @@ -1,564 +0,0 @@ -/* - i2c-viapro.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998 - 2002 Frodo Looijaard , - Philip Edelbrock , Kyösti Mälkki , - Mark D. Studebaker - Copyright (C) 2005 - 2007 Jean Delvare - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - Supports the following VIA south bridges: - - Chip name PCI ID REV I2C block - VT82C596A 0x3050 no - VT82C596B 0x3051 no - VT82C686A 0x3057 0x30 no - VT82C686B 0x3057 0x40 yes - VT8231 0x8235 no? - VT8233 0x3074 yes - VT8233A 0x3147 yes? - VT8235 0x3177 yes - VT8237R 0x3227 yes - VT8237A 0x3337 yes - VT8251 0x3287 yes - CX700 0x8324 yes - - Note: we assume there can only be one device, with one SMBus interface. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "version.h" -#include "sensors_compat.h" - -/* 8233A is undefined before kernel 2.4.19 */ -#ifndef PCI_DEVICE_ID_VIA_8233A -#define PCI_DEVICE_ID_VIA_8233A 0x3147 -#endif -/* 8235 is undefined before kernel 2.4.21 */ -#ifndef PCI_DEVICE_ID_VIA_8235 -#define PCI_DEVICE_ID_VIA_8235 0x3177 -#endif -/* 8237 is undefined before kernel 2.4.21 */ -#ifndef PCI_DEVICE_ID_VIA_8237 -#define PCI_DEVICE_ID_VIA_8237 0x3227 -#endif -/* 8237A is undefined */ -#ifndef PCI_DEVICE_ID_VIA_8237A -#define PCI_DEVICE_ID_VIA_8237A 0x3337 -#endif -/* 8251 is undefined */ -#ifndef PCI_DEVICE_ID_VIA_8251 -#define PCI_DEVICE_ID_VIA_8251 0x3287 -#endif -/* CX700 is undefined */ -#ifndef PCI_DEVICE_ID_VIA_CX700 -#define PCI_DEVICE_ID_VIA_CX700 0x8324 -#endif - -#define SMBBA1 0x90 -#define SMBBA2 0x80 -#define SMBBA3 0xD0 - -/* SMBus address offsets */ -static unsigned short vt596_smba; -#define SMBHSTSTS (vt596_smba + 0) -#define SMBHSTCNT (vt596_smba + 2) -#define SMBHSTCMD (vt596_smba + 3) -#define SMBHSTADD (vt596_smba + 4) -#define SMBHSTDAT0 (vt596_smba + 5) -#define SMBHSTDAT1 (vt596_smba + 6) -#define SMBBLKDAT (vt596_smba + 7) - -/* PCI Address Constants */ - -/* SMBus data in configuration space can be found in two places, - We try to select the better one */ - -static unsigned short SMBHSTCFG = 0xD2; - -/* Other settings */ -#define MAX_TIMEOUT 500 - -/* VT82C596 constants */ -#define VT596_QUICK 0x00 -#define VT596_BYTE 0x04 -#define VT596_BYTE_DATA 0x08 -#define VT596_WORD_DATA 0x0C -#define VT596_BLOCK_DATA 0x14 -#define VT596_I2C_BLOCK_DATA 0x34 - - -/* If force is set to anything different from 0, we forcibly enable the - VT596. DANGEROUS! */ -static int force; -MODULE_PARM(force, "i"); -MODULE_PARM_DESC(force, "Forcibly enable the SMBus. DANGEROUS!"); - -/* If force_addr is set to anything different from 0, we forcibly enable - the VT596 at the given address. VERY DANGEROUS! */ -static int force_addr; -MODULE_PARM(force_addr, "i"); -MODULE_PARM_DESC(force_addr, - "Forcibly enable the SMBus at the given address. " - "EXTREMELY DANGEROUS!"); - - -static struct i2c_adapter vt596_adapter; - -#define FEATURE_I2CBLOCK (1<<0) -static unsigned int vt596_features; - -#ifdef DEBUG -static void vt596_dump_regs(const char *msg, u8 size) -{ - dev_dbg(&vt596_adapter, "%s: STS=%02x CNT=%02x CMD=%02x ADD=%02x " - "DAT=%02x,%02x\n", msg, inb_p(SMBHSTSTS), inb_p(SMBHSTCNT), - inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), - inb_p(SMBHSTDAT1)); - - if (size == VT596_BLOCK_DATA - || size == VT596_I2C_BLOCK_DATA) { - int i; - - dev_dbg(&vt596_adapter, "BLK="); - for (i = 0; i < I2C_SMBUS_BLOCK_MAX / 2; i++) - printk("%02x,", inb_p(SMBBLKDAT)); - printk("\n"); - dev_dbg(&vt596_adapter, " "); - for (; i < I2C_SMBUS_BLOCK_MAX - 1; i++) - printk("%02x,", inb_p(SMBBLKDAT)); - printk("%02x\n", inb_p(SMBBLKDAT)); - } -} -#else -static inline void vt596_dump_regs(const char *msg, u8 size) { } -#endif - -/* Return -1 on error, 0 on success */ -static int vt596_transaction(u8 size) -{ - int temp; - int result = 0; - int timeout = 0; - - vt596_dump_regs("Transaction (pre)", size); - - /* Make sure the SMBus host is ready to start transmitting */ - if ((temp = inb_p(SMBHSTSTS)) & 0x1F) { - dev_dbg(&vt596_adapter, "SMBus busy (0x%02x). " - "Resetting...\n", temp); - - outb_p(temp, SMBHSTSTS); - if ((temp = inb_p(SMBHSTSTS)) & 0x1F) { - dev_err(&vt596_adapter, "SMBus reset failed! " - "(0x%02x)\n", temp); - return -1; - } - } - - /* Start the transaction by setting bit 6 */ - outb_p(0x40 | size, SMBHSTCNT); - - /* We will always wait for a fraction of a second */ - do { - i2c_delay(1); - temp = inb_p(SMBHSTSTS); - } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT)); - - /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { - result = -1; - dev_err(&vt596_adapter, "SMBus Timeout!\n"); - } - - if (temp & 0x10) { - result = -1; - dev_err(&vt596_adapter, "Transaction failed (0x%02x)\n", size); - } - - if (temp & 0x08) { - result = -1; - dev_err(&vt596_adapter, "SMBus collision!\n"); - } - - if (temp & 0x04) { - int read = inb_p(SMBHSTADD) & 0x01; - result = -1; - /* The quick and receive byte commands are used to probe - for chips, so errors are expected, and we don't want - to frighten the user. */ - if (!((size == VT596_QUICK && !read) || - (size == VT596_BYTE && read))) - dev_err(&vt596_adapter, "Transaction error!\n"); - } - - /* Resetting status register */ - if (temp & 0x1F) - outb_p(temp, SMBHSTSTS); - - vt596_dump_regs("Transaction (post)", size); - - return result; -} - -/* Return -1 on error, 0 on success */ -static s32 vt596_access(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, u8 command, - int size, union i2c_smbus_data *data) -{ - int i; - - switch (size) { - case I2C_SMBUS_QUICK: - size = VT596_QUICK; - break; - case I2C_SMBUS_BYTE: - if (read_write == I2C_SMBUS_WRITE) - outb_p(command, SMBHSTCMD); - size = VT596_BYTE; - break; - case I2C_SMBUS_BYTE_DATA: - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) - outb_p(data->byte, SMBHSTDAT0); - size = VT596_BYTE_DATA; - break; - case I2C_SMBUS_WORD_DATA: - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) { - outb_p(data->word & 0xff, SMBHSTDAT0); - outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); - } - size = VT596_WORD_DATA; - break; - case I2C_SMBUS_I2C_BLOCK_DATA: - if (!(vt596_features & FEATURE_I2CBLOCK)) - goto exit_unsupported; - if (read_write == I2C_SMBUS_READ) - outb_p(I2C_SMBUS_BLOCK_MAX, SMBHSTDAT0); - /* Fall through */ - case I2C_SMBUS_BLOCK_DATA: - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) { - u8 len = data->block[0]; - if (len > I2C_SMBUS_BLOCK_MAX) - len = I2C_SMBUS_BLOCK_MAX; - outb_p(len, SMBHSTDAT0); - inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ - for (i = 1; i <= len; i++) - outb_p(data->block[i], SMBBLKDAT); - } - size = (size == I2C_SMBUS_I2C_BLOCK_DATA) ? - VT596_I2C_BLOCK_DATA : VT596_BLOCK_DATA; - break; - default: - goto exit_unsupported; - } - - outb_p(((addr & 0x7f) << 1) | read_write, SMBHSTADD); - - if (vt596_transaction(size)) /* Error in transaction */ - return -1; - - if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK)) - return 0; - - switch (size) { - case VT596_BYTE: - case VT596_BYTE_DATA: - data->byte = inb_p(SMBHSTDAT0); - break; - case VT596_WORD_DATA: - data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); - break; - case VT596_I2C_BLOCK_DATA: - case VT596_BLOCK_DATA: - data->block[0] = inb_p(SMBHSTDAT0); - if (data->block[0] > I2C_SMBUS_BLOCK_MAX) - data->block[0] = I2C_SMBUS_BLOCK_MAX; - inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ - for (i = 1; i <= data->block[0]; i++) - data->block[i] = inb_p(SMBBLKDAT); - break; - } - return 0; - -exit_unsupported: - dev_warn(&vt596_adapter, "Unsupported command invoked! (0x%02x)\n", - size); - return -1; -} - -static void vt596_inc(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -static void vt596_dec(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - -static u32 vt596_func(struct i2c_adapter *adapter) -{ - u32 func = I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA; - - if (vt596_features & FEATURE_I2CBLOCK) - func |= I2C_FUNC_SMBUS_I2C_BLOCK; - return func; -} - -static struct i2c_algorithm smbus_algorithm = { - .name = "Non-I2C SMBus adapter", - .id = I2C_ALGO_SMBUS, - .smbus_xfer = vt596_access, - .functionality = vt596_func, -}; - -static struct i2c_adapter vt596_adapter = { - .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_VIA2, - .algo = &smbus_algorithm, - .inc_use = vt596_inc, - .dec_use = vt596_dec, -}; - -static int __init vt596_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - unsigned char temp; - int error = -ENODEV; - - /* Determine the address of the SMBus areas */ - if (force_addr) { - vt596_smba = force_addr & 0xfff0; - force = 0; - goto found; - } - - if ((pci_read_config_word(pdev, id->driver_data, &vt596_smba)) || - !(vt596_smba & 0x0001)) { - /* try 2nd address and config reg. for 596 */ - if (id->device == PCI_DEVICE_ID_VIA_82C596_3 && - !pci_read_config_word(pdev, SMBBA2, &vt596_smba) && - (vt596_smba & 0x0001)) { - SMBHSTCFG = 0x84; - } else { - /* no matches at all */ - dev_err(pdev, "Cannot configure " - "SMBus I/O Base address\n"); - return -ENODEV; - } - } - - vt596_smba &= 0xfff0; - if (vt596_smba == 0) { - dev_err(pdev, "SMBus base address " - "uninitialized - upgrade BIOS or use " - "force_addr=0xaddr\n"); - return -ENODEV; - } - -found: - if (!request_region(vt596_smba, 8, "viapro-smbus")) { - dev_err(pdev, "SMBus region 0x%x already in use!\n", - vt596_smba); - return -ENODEV; - } - - pci_read_config_byte(pdev, SMBHSTCFG, &temp); - /* If force_addr is set, we program the new address here. Just to make - sure, we disable the VT596 first. */ - if (force_addr) { - pci_write_config_byte(pdev, SMBHSTCFG, temp & 0xfe); - pci_write_config_word(pdev, id->driver_data, vt596_smba); - pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01); - dev_warn(pdev, "WARNING: SMBus interface set to new " - "address 0x%04x!\n", vt596_smba); - } else if (!(temp & 0x01)) { - if (force) { - /* NOTE: This assumes I/O space and other allocations - * WERE done by the Bios! Don't complain if your - * hardware does weird things after enabling this. - * :') Check for Bios updates before resorting to - * this. - */ - pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01); - dev_info(pdev, "Enabling SMBus device\n"); - } else { - dev_err(pdev, "SMBUS: Error: Host SMBus " - "controller not enabled! - upgrade BIOS or " - "use force=1\n"); - goto release_region; - } - } - - dev_dbg(pdev, "VT596_smba = 0x%X\n", vt596_smba); - - switch (id->device) { - case PCI_DEVICE_ID_VIA_CX700: - case PCI_DEVICE_ID_VIA_8251: - case PCI_DEVICE_ID_VIA_8237: - case PCI_DEVICE_ID_VIA_8237A: - case PCI_DEVICE_ID_VIA_8235: - case PCI_DEVICE_ID_VIA_8233A: - case PCI_DEVICE_ID_VIA_8233_0: - vt596_features |= FEATURE_I2CBLOCK; - break; - case PCI_DEVICE_ID_VIA_82C686_4: - /* The VT82C686B (rev 0x40) does support I2C block - transactions, but the VT82C686A (rev 0x30) doesn't */ - if (!pci_read_config_byte(pdev, PCI_REVISION_ID, &temp) - && temp >= 0x40) - vt596_features |= FEATURE_I2CBLOCK; - break; - } - - snprintf(vt596_adapter.name, 32, - "SMBus Via Pro adapter at %04x", vt596_smba); - - return i2c_add_adapter(&vt596_adapter); - -release_region: - release_region(vt596_smba, 8); - return error; -} - -static struct pci_device_id vt596_ids[] __initdata = { - { - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_82C596_3, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = SMBBA1, - }, - { - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_82C596B_3, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = SMBBA1, - }, - { - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_82C686_4, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = SMBBA1, - }, - { - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_8233_0, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = SMBBA3 - }, - { - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_8233A, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = SMBBA3, - }, - { - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_8235, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = SMBBA3 - }, - { - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_8237, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = SMBBA3 - }, - { - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_8237A, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = SMBBA3 - }, - { - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_8231_4, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = SMBBA1, - }, - { - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_8251, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = SMBBA3 - }, - { - .vendor = PCI_VENDOR_ID_VIA, - .device = PCI_DEVICE_ID_VIA_CX700, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = SMBBA3 - }, - { 0, } -}; - -static int __init i2c_vt596_init(void) -{ - struct pci_dev *dev; - const struct pci_device_id *id; - - printk("i2c-viapro.o version %s (%s)\n", LM_VERSION, LM_DATE); - pci_for_each_dev(dev) { - id = pci_match_device(vt596_ids, dev); - if(id) - if(vt596_probe(dev, id) >= 0) - return 0; - } - return -ENODEV; -} - - -static void __exit i2c_vt596_exit(void) -{ - i2c_del_adapter(&vt596_adapter); - release_region(vt596_smba, 8); -} - -MODULE_AUTHOR("Kyosti Malkki , " - "Mark D. Studebaker and " - "Jean Delvare "); -MODULE_DESCRIPTION("vt82c596 SMBus driver"); -MODULE_LICENSE("GPL"); - -module_init(i2c_vt596_init); -module_exit(i2c_vt596_exit); diff --git a/kernel/busses/i2c-virtual.c b/kernel/busses/i2c-virtual.c deleted file mode 100644 index 7af5c1df..00000000 --- a/kernel/busses/i2c-virtual.c +++ /dev/null @@ -1,430 +0,0 @@ -/* - * i2c-virtual.c - Virtual I2C bus driver. - * - * Simplifies access to complex multiplexed I2C bus topologies, by presenting - * each multiplexed bus segment as a virtual I2C adapter. Supports multi-level - * mux'ing (mux behind a mux), as well as arbitration for exclusive bus access - * for those systems which require it (some bladed chassis for example). - * - * Copyright (c) 2004 Google, Inc. (Ken Harrenstien) - * - * Based on: - * i2c-virtual.c from Brian Kuschak - * which was: - * Adapted from i2c-adap-ibm_ocp.c - * Original file Copyright 2000-2002 MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "i2c-virtual.h" -#include -#include -#include - -#include -#include -#include - -#ifdef DEBUG -# define DBG(x) x -#else -# define DBG(x) {} -#endif - -#define I2C_VIRT_PROCMAP 0 /* 1 for /proc/driver/i2c/virtual_i2c_map */ - -#define VIRT_TIMEOUT (HZ/2) /* 500msec */ -#define VIRT_RETRIES 3 - -/* exclusive access to the bus */ -#define I2C_LOCK(adap) down(&adap->bus) -#define I2C_UNLOCK(adap) up(&adap->bus) - -#if I2C_VIRT_PROCMAP -/* pointer to the list of i2c_bus_mappings */ -static LIST_HEAD(i2c_map_list); -struct i2c_bus_mapping { - struct i2c_adapter *parent; - struct i2c_adapter *virt; - unsigned long mux_addr; - unsigned long mux_val; - struct list_head list; -}; -static void *i2c_virt_add_map(struct i2c_adapter *parent, - struct i2c_adapter *virt, - unsigned long mux_addr, - unsigned long mux_val); -#endif - -/* First the I2C 'algorithm' driver code: */ - -/* - * Description: acquire exclusive access (if needed), select the mux, - * perform the transfer on the parent i2c adapter, deselect mux and drop - * exclusive access. - */ -static int -i2c_virt_master_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) -{ - struct i2c_virt_priv *priv = (struct i2c_virt_priv *)adap->data; - struct i2c_adapter *parent = priv->parent_adap; - int ret; - - -#ifdef I2C_REQUIRE_ARBITRATION - /* Acquire exclusive access to a shared I2C bus _before_ taking the - local I2C lock to prevent stalling local I2C transactions while - waiting for exclusive access. - */ - if(parent->algo->acquire_exclusive) - if ((ret = parent->algo->acquire_exclusive(parent)) < 0) - return ret; -#endif - /* Grab the lock for the parent adapter. We already hold the lock for - the virtual adapter. Then select the right mux port and perform - the transfer. - */ - DBG(printk(KERN_DEBUG "%s: Locking parent bus %0lX\n", - __FUNCTION__, (unsigned long)parent)); - I2C_LOCK(parent); - if ((ret = priv->mux.select(parent, &priv->mux)) == 0) { - ret = parent->algo->master_xfer(parent, msgs, num); - } - (void) priv->mux.deselect(parent, &priv->mux); - I2C_UNLOCK(parent); - DBG(printk(KERN_DEBUG "%s: Unlocked parent bus %0lX\n", - __FUNCTION__, (unsigned long)parent)); - -#ifdef I2C_REQUIRE_ARBITRATION - { - int ret2; - /* Release exclusive bus access */ - if(parent->algo->release_exclusive) - if ((ret2 = parent->algo->release_exclusive(parent)) < 0) - return ret2; - } -#endif - return ret; -} - -static int -i2c_virt_smbus_xfer(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data * data) -{ - struct i2c_virt_priv *priv = (struct i2c_virt_priv *)adap->data; - struct i2c_adapter *parent = priv->parent_adap; - int ret; - -#ifdef I2C_REQUIRE_ARBITRATION - /* Acquire exclusive access to a shared I2C bus _before_ taking the - local I2C lock to prevent stalling local I2C transactions while - waiting for exclusive access. - */ - if(parent->algo->acquire_exclusive) - if ((ret = parent->algo->acquire_exclusive(parent)) < 0) - return ret; -#endif - /* Grab the lock for the parent adapter. We already hold the lock for - the virtual adapter. Then select the right mux port and perform - the transfer. - */ - DBG(printk(KERN_DEBUG "%s: Locking parent bus %0lX\n", - __FUNCTION__, (unsigned long)parent)); - I2C_LOCK(parent); - if ((ret = priv->mux.select(parent, &priv->mux)) == 0) { - ret = parent->algo->smbus_xfer(parent, addr, flags, - read_write, command, size, data); - } - (void) priv->mux.deselect(parent, &priv->mux); - I2C_UNLOCK(parent); - DBG(printk(KERN_DEBUG "%s: Unlocked parent bus %0lX\n", - __FUNCTION__, (unsigned long)parent)); - -#ifdef I2C_REQUIRE_ARBITRATION - { - int ret2; - /* Release exclusive bus access */ - if(parent->algo->release_exclusive) - if ((ret2 = parent->algo->release_exclusive(parent)) < 0) - return ret2; - } -#endif - return ret; -} - -/* - * Description: Implements device specific ioctls. - * We don't support any yet. - */ -static int -i2c_virt_algo_control(struct i2c_adapter *adap, unsigned int cmd, - unsigned long arg) -{ - return 0; -} - -/* Virtual adapter functionality; returns functionality of parent adapter. - * OK if parent itself is virtual, as this will go all the way up to the - * real adapter. - */ -static u32 -i2c_virt_functionality(struct i2c_adapter *adap) -{ - struct i2c_virt_priv *priv = (struct i2c_virt_priv *)adap->data; - struct i2c_adapter *parent = priv->parent_adap; - - return parent->algo->functionality(parent); -} - -/* ===================================================================== */ - -/* The 'adapter' driver code: */ - -static int -i2c_virt_reg(struct i2c_client *client) -{ - return 0; -} -static int -i2c_virt_unreg(struct i2c_client *client) -{ - return 0; -} - - -/* - * Called to create a 'virtual' i2c bus which represents a multiplexed bus - * segment. Client and mux_val are passed to the select and deselect - * callback functions to perform hardware-specific mux control. - */ -struct i2c_adapter *i2c_virt_create_adapter(struct i2c_adapter *parent_adap, - struct i2c_client *client, - unsigned long mux_val, - void *select_cb, - void *deselect_cb) -{ - struct i2c_adapter *adap; - struct i2c_virt_priv *priv; - struct i2c_algorithm *algo; - - if (!(adap = kmalloc(sizeof (struct i2c_adapter) - + sizeof(struct i2c_virt_priv) - + sizeof(struct i2c_algorithm), - GFP_KERNEL))) { - printk(KERN_ERR "i2c_virt_register_adap: Failed allocation\n"); - return NULL; - } - - memset(adap, 0, sizeof(struct i2c_adapter) - + sizeof(struct i2c_virt_priv) - + sizeof(struct i2c_algorithm)); - priv = (struct i2c_virt_priv *) (adap+1); - algo = (struct i2c_algorithm *) (priv+1); - - /* Set up private adapter data */ - priv->parent_adap = parent_adap; - priv->mux.client = client; - priv->mux.addr = client->addr; - priv->mux.value = mux_val; - priv->mux.select = select_cb; - priv->mux.deselect = deselect_cb; - - /* Need to do algo dynamically because we don't know ahead - of time what sort of physical adapter we'll be dealing with. - */ - algo->id = I2C_ALGO_VIRT; - strcpy(algo->name, "Virtual I2C algorithm driver"); - algo->master_xfer = (parent_adap->algo->master_xfer - ? i2c_virt_master_xfer : NULL); - algo->smbus_xfer = (parent_adap->algo->smbus_xfer - ? i2c_virt_smbus_xfer : NULL); - algo->slave_send = NULL; - algo->slave_recv = NULL; - algo->algo_control = i2c_virt_algo_control; - algo->functionality = i2c_virt_functionality; -#ifdef I2C_REQUIRE_ARBITRATION - algo->acquire_exclusive = NULL; - algo->release_exclusive = NULL; -#endif - - /* Now fill out new adapter structure */ - adap->inc_use = NULL; - adap->dec_use = NULL; - snprintf(adap->name, sizeof(adap->name), - "Virtual I2C (i2c-%d, mux %02lx:%02lx)", - i2c_adapter_id(parent_adap), - (unsigned long)client->addr, mux_val); - adap->id = I2C_HW_VIRT | algo->id; - adap->algo = algo; - adap->algo_data = NULL; /* XXX: Use this?? */ - adap->client_register = i2c_virt_reg; - adap->client_unregister = i2c_virt_unreg; - adap->data = priv; - adap->flags = 0; - adap->timeout = VIRT_TIMEOUT; - adap->retries = VIRT_RETRIES; - - DBG(printk(KERN_DEBUG "%s: Adding virt bus %0lX\n", - __FUNCTION__, (unsigned long)adap)); - - if (i2c_add_adapter_nolock(adap) < 0) { - kfree(adap); - return NULL; - } - - printk(KERN_NOTICE "i2c%d: Virtual I2C bus " - "(Physical bus i2c%d, multiplexer %02lx port %ld)\n", - i2c_adapter_id(adap), i2c_adapter_id(parent_adap), - priv->mux.addr, mux_val); - -#if I2C_VIRT_PROCMAP - i2c_virt_add_map(priv->parent_adap, adap, - priv->mux.addr, priv->value); -#endif - - MOD_INC_USE_COUNT; - DBG(printk(KERN_DEBUG "%s: Added virt bus %0lX\n", - __FUNCTION__, (unsigned long)adap)); - - return adap; -} - -int i2c_virt_remove_adapter(struct i2c_adapter *adap) -{ - int ret; - - DBG(printk(KERN_DEBUG "%s: Removing virt bus %0lX\n", - __FUNCTION__, (unsigned long)adap)); - - if ((ret = i2c_del_adapter_nolock(adap)) < 0) - return ret; - kfree(adap); - - MOD_DEC_USE_COUNT; - return 0; -} - - -/* ------------------------------------------------------------------ */ - -#if I2C_VIRT_PROCMAP -/* Dubious stuff to implement a /proc/driver/i2c/virtual_i2c_map - * listing of all virtual busses. - * - * XXX: LOCKING??? - */ -static int i2c_virt_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len; - char *buf = page; - struct list_head *l; - struct i2c_bus_mapping *pmap; - - /* XXX: BUFFER BOUNDS CHECKING? */ - - buf += sprintf(buf, "i2c bus_mapping\n"); - - list_for_each(l, &i2c_map_list) { - pmap = list_entry(l, struct i2c_bus_mapping, list); - - if(pmap) - buf += sprintf(buf, "base=iic%d mux_addr=%02hx, mux_val=%02hx => iic%d\n", - i2c_adapter_id(pmap->parent), - pmap->mux_addr, pmap->mux_val, - i2c_adapter_id(pmap->virt)); - } - - len = buf - page; - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; -} - - -static void *i2c_virt_add_map(struct i2c_adapter *parent, - struct i2c_adapter *virt, - unsigned long mux_addr, - unsigned long mux_val) -{ - struct i2c_bus_mapping *pmap; - - if((pmap = kmalloc(sizeof(struct i2c_bus_mapping), GFP_KERNEL)) - == NULL) { - printk(KERN_ERR "%s: Failed to allocate bus mapping\n", - __FUNCTION__); - return; - } - pmap->virt = virt; - pmap->parent = parent; - pmap->mux_addr = mux_addr; - pmap->mux_val = mux_val; - - if (list_empty(&i2c_map_list)) { - /* If first time, ensure proc entry exists */ - /* XXX: Maybe do this with module_init() */ - create_proc_read_entry("driver/i2c/virtual_i2c_map", 0, NULL, - &i2c_virt_read_proc, NULL); - } - list_add_tail(&pmap->list, &i2c_map_list); -} - - -#if 0 /* Not used by anything, but kept for a while in case */ - -/* Called to find out which i2c bus to use to get to a specific bus segment. - */ -struct i2c_adapter *i2c_lookup_adapter(struct i2c_adapter *base, - unsigned long mux_addr, - unsigned long mux_val) -{ - struct list_head *l; - struct i2c_bus_mapping *pmap; - - list_for_each(l, &i2c_map_list) { - pmap = list_entry(l, struct i2c_bus_mapping, list); - if(pmap->parent == base - && pmap->mux_addr == mux_addr - && pmap->mux_val == mux_val) - return pmap->virt; - } - return NULL; /* none found */ -} - -EXPORT_SYMBOL(i2c_lookup_adapter); -#endif /* 0 */ - - -#endif /* I2C_VIRT_PROCMAP */ - -EXPORT_SYMBOL(i2c_virt_create_adapter); -EXPORT_SYMBOL(i2c_virt_remove_adapter); - -MODULE_AUTHOR("Ken Harrenstien (from Brian Kuschak)"); -MODULE_DESCRIPTION("Virtual I2C driver for multiplexed I2C busses"); -MODULE_LICENSE("GPL"); diff --git a/kernel/busses/i2c-voodoo3.c b/kernel/busses/i2c-voodoo3.c deleted file mode 100644 index 567ba9ea..00000000 --- a/kernel/busses/i2c-voodoo3.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - voodoo3.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 1998, 1999 Frodo Looijaard , - Philip Edelbrock , - Ralph Metzler , and - Mark D. Studebaker - - Based on code written by Ralph Metzler and - Simon Vogl - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* This interfaces to the I2C bus of the Voodoo3 to gain access to - the BT869 and possibly other I2C devices. */ - -#include -#include -#include -#include -#include -#include -#include /* for HZ */ -#include "version.h" -#include "sensors_compat.h" - -MODULE_LICENSE("GPL"); - -/* the only registers we use */ -#define REG 0x78 -#define REG2 0x70 - -/* bit locations in the register */ -#define DDC_ENAB 0x00040000 -#define DDC_SCL_OUT 0x00080000 -#define DDC_SDA_OUT 0x00100000 -#define DDC_SCL_IN 0x00200000 -#define DDC_SDA_IN 0x00400000 -#define I2C_ENAB 0x00800000 -#define I2C_SCL_OUT 0x01000000 -#define I2C_SDA_OUT 0x02000000 -#define I2C_SCL_IN 0x04000000 -#define I2C_SDA_IN 0x08000000 - -/* initialization states */ -#define INIT2 0x2 -#define INIT3 0x4 - -/* delays */ -#define CYCLE_DELAY 10 -#define TIMEOUT (HZ / 2) - - -static void config_v3(struct pci_dev *dev); - -static unsigned long ioaddr; - -/* The voo GPIO registers don't have individual masks for each bit - so we always have to read before writing. */ - -static void bit_vooi2c_setscl(void *data, int val) -{ - unsigned int r; - r = readl(ioaddr + REG); - if(val) - r |= I2C_SCL_OUT; - else - r &= ~I2C_SCL_OUT; - writel(r, ioaddr + REG); - readl(ioaddr + REG); /* flush posted write */ -} - -static void bit_vooi2c_setsda(void *data, int val) -{ - unsigned int r; - r = readl(ioaddr + REG); - if(val) - r |= I2C_SDA_OUT; - else - r &= ~I2C_SDA_OUT; - writel(r, ioaddr + REG); - readl(ioaddr + REG); /* flush posted write */ -} - -/* The GPIO pins are open drain, so the pins always remain outputs. - We rely on the i2c-algo-bit routines to set the pins high before - reading the input from other chips. */ - -static int bit_vooi2c_getscl(void *data) -{ - return (0 != (readl(ioaddr + REG) & I2C_SCL_IN)); -} - -static int bit_vooi2c_getsda(void *data) -{ - return (0 != (readl(ioaddr + REG) & I2C_SDA_IN)); -} - -static void bit_vooddc_setscl(void *data, int val) -{ - unsigned int r; - r = readl(ioaddr + REG); - if(val) - r |= DDC_SCL_OUT; - else - r &= ~DDC_SCL_OUT; - writel(r, ioaddr + REG); - readl(ioaddr + REG); /* flush posted write */ -} - -static void bit_vooddc_setsda(void *data, int val) -{ - unsigned int r; - r = readl(ioaddr + REG); - if(val) - r |= DDC_SDA_OUT; - else - r &= ~DDC_SDA_OUT; - writel(r, ioaddr + REG); - readl(ioaddr + REG); /* flush posted write */ -} - -static int bit_vooddc_getscl(void *data) -{ - return (0 != (readl(ioaddr + REG) & DDC_SCL_IN)); -} - -static int bit_vooddc_getsda(void *data) -{ - return (0 != (readl(ioaddr + REG) & DDC_SDA_IN)); -} - - -/* Configures the chip */ - -void config_v3(struct pci_dev *dev) -{ - unsigned int cadr; - - /* map Voodoo3 memory */ - cadr = dev->resource[0].start; - cadr &= PCI_BASE_ADDRESS_MEM_MASK; - ioaddr = (unsigned long)ioremap_nocache(cadr, 0x1000); - if(ioaddr) { - writel(0x8160, ioaddr + REG2); - writel(0xcffc0020, ioaddr + REG); - printk("i2c-voodoo3: Using Banshee/Voodoo3 at 0x%lx\n", ioaddr); - } -} - -static void voodoo3_inc(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif -} - -void voodoo3_dec(struct i2c_adapter *adapter) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif -} - -static struct i2c_algo_bit_data voo_i2c_bit_data = { - .setsda = bit_vooi2c_setsda, - .setscl = bit_vooi2c_setscl, - .getsda = bit_vooi2c_getsda, - .getscl = bit_vooi2c_getscl, - .udelay = CYCLE_DELAY, - .mdelay = CYCLE_DELAY, - .timeout = TIMEOUT -}; - -static struct i2c_adapter voodoo3_i2c_adapter = { - .name = "I2C Voodoo3/Banshee adapter", - .id = I2C_HW_B_VOO, - .algo_data = &voo_i2c_bit_data, - .inc_use = voodoo3_inc, - .dec_use = voodoo3_dec, -}; - -static struct i2c_algo_bit_data voo_ddc_bit_data = { - .setsda = bit_vooddc_setsda, - .setscl = bit_vooddc_setscl, - .getsda = bit_vooddc_getsda, - .getscl = bit_vooddc_getscl, - .udelay = CYCLE_DELAY, - .mdelay = CYCLE_DELAY, - .timeout = TIMEOUT -}; - -static struct i2c_adapter voodoo3_ddc_adapter = { - .name = "DDC Voodoo3/Banshee adapter", - .id = I2C_HW_B_VOO, - .algo_data = &voo_ddc_bit_data, - .inc_use = voodoo3_inc, - .dec_use = voodoo3_dec, -}; - - -static struct pci_device_id voodoo3_ids[] __devinitdata = { - { - .vendor = PCI_VENDOR_ID_3DFX, - .device = PCI_DEVICE_ID_3DFX_VOODOO3, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { - .vendor = PCI_VENDOR_ID_3DFX, - .device = PCI_DEVICE_ID_3DFX_BANSHEE, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { 0, } -}; - -static int __devinit voodoo3_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - int retval; - - config_v3(dev); - retval = i2c_bit_add_bus(&voodoo3_i2c_adapter); - if(retval) - return retval; - retval = i2c_bit_add_bus(&voodoo3_ddc_adapter); - if(retval) - i2c_bit_del_bus(&voodoo3_i2c_adapter); - return retval; -} - -static void __devexit voodoo3_remove(struct pci_dev *dev) -{ - i2c_bit_del_bus(&voodoo3_i2c_adapter); - i2c_bit_del_bus(&voodoo3_ddc_adapter); -} - - -/* Don't register driver to avoid driver conflicts */ -/* -static struct pci_driver voodoo3_driver = { - .name = "voodoo3 smbus", - .id_table = voodoo3_ids, - .probe = voodoo3_probe, - .remove = __devexit_p(voodoo3_remove), -}; -*/ - -static int __init i2c_voodoo3_init(void) -{ - struct pci_dev *dev; - const struct pci_device_id *id; - - printk("i2c-voodoo3.o version %s (%s)\n", LM_VERSION, LM_DATE); -/* - return pci_module_init(&voodoo3_driver); -*/ - pci_for_each_dev(dev) { - id = pci_match_device(voodoo3_ids, dev); - if(id) - if(voodoo3_probe(dev, id) >= 0) - return 0; - } - return -ENODEV; -} - - -static void __exit i2c_voodoo3_exit(void) -{ -/* - pci_unregister_driver(&voodoo3_driver); -*/ - voodoo3_remove(NULL); - iounmap((void *)ioaddr); -} - - -MODULE_AUTHOR - ("Frodo Looijaard , Philip Edelbrock , Ralph Metzler , and Mark D. Studebaker "); -MODULE_DESCRIPTION("Voodoo3 I2C/SMBus driver"); - -module_init(i2c_voodoo3_init); -module_exit(i2c_voodoo3_exit); diff --git a/kernel/chips/pca954x.c b/kernel/chips/pca954x.c deleted file mode 100644 index 7e1cbb9d..00000000 --- a/kernel/chips/pca954x.c +++ /dev/null @@ -1,836 +0,0 @@ -/* - * pca954x.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * This module supports the PCA954x series of I2C multiplexer/switch chips - * made by Philips Semiconductors. This includes the - * PCA9540, PCA9542, PCA9543, PCA9544, PCA9545, PCA9546, and PCA9548. - * - * Copyright (c) 2004 Google, Inc. (Ken Harrenstien) - * - * Based on: - * i2c-virtual_cb.c from Brian Kuschak - * and - * pca9540.c from Jean Delvare , which was - * based on pcf8574.c from the same project by Frodo Looijaard, - * Philip Edelbrock, Dan Eaton and Aurelien Jarno. - * - * These chips are all controlled via the I2C bus itself, and all have a - * single 8-bit register (normally at 0x70). The upstream "parent" bus fans - * out to two, four, or eight downstream busses or channels; which of these - * are selected is determined by the chip type and register contents. A - * mux can select only one sub-bus at a time; a switch can select any - * combination simultaneously. - * - * See Documentation/i2c/virtual_i2c for details on the virtual bus/adapter - * mechanism. - * - ********************************************************************* - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include "i2c-virtual.h" -#include "version.h" - -MODULE_LICENSE("GPL"); - -#define DEBUG 1 /* XXX: Comment out before release? */ -#ifdef DEBUG -# define DBG(x) if (pca954x_debug > 0) { x; } else -#else -# define DBG(x) {} -#endif - -#define PCA954X_NCHANS 8 /* Max # of channels (PCA9548) */ - -/* Addresses to scan */ -static unsigned short normal_i2c[] = { /*0x70,*/ SENSORS_I2C_END }; -static unsigned short normal_i2c_range[] = { SENSORS_I2C_END }; -static unsigned int normal_isa[] = { SENSORS_ISA_END }; -static unsigned int normal_isa_range[] = { SENSORS_ISA_END }; - -/* Insmod/modprobe parameters */ - -/* Chip type must normally be specified using a parameter of the form - "force_pca9544=0,0x70" - The following declares the possible types. -*/ -SENSORS_INSMOD_7(pca9540,pca9542,pca9543,pca9544,pca9545,pca9546,pca9548); - -static int pca954x_debug; -MODULE_PARM(pca954x_debug, "i"); -MODULE_PARM_DESC(pca954x_debug, "Debug output level (0 = none)"); - -#if 0 /* Considered adding this, but too many issues. See doc. */ -static int pca954x_selmask[32]; /* Max # chips supported, sigh */ -MODULE_PARM(pca954x_selmask, "1-32i"); -MODULE_PARM_DESC(pca954x_selmask, "List of selmask settings for each mux/swi"); -#endif - -/* Provide specs for the PCA954x types we know about - */ -static struct pca954x_chipdef { - enum chips type; - const char *type_name; - int pcanum; - int nchans; - enum muxtype { pca954x_ismux=0, pca954x_isswi } muxtype; -} pca954x_chipdefs[] = { - { pca9540, "pca9540", 9540, 2, pca954x_ismux }, - { pca9542, "pca9542", 9542, 2, pca954x_ismux }, - { pca9543, "pca9543", 9543, 2, pca954x_isswi }, - { pca9544, "pca9544", 9544, 4, pca954x_ismux }, - { pca9545, "pca9545", 9545, 4, pca954x_isswi }, - { pca9546, "pca9546", 9546, 4, pca954x_isswi }, - { pca9548, "pca9548", 9548, 8, pca954x_isswi }, -}; -#define PCA954X_MUX_ENA 0x04 /* Mux enable bit */ - -/* Each client has this additional data. - Note the two conventions for identifying a chip's channel (sub-bus): - "channel" 0 to N-1, where N is the number of channels supported - "bitmask" 1 to 1 << N-1, so bit 0 is channel 0. - This use of "channel" is consistent with that in the Philips PCA954X doc. - */ -struct pca954x_data { - struct i2c_client client; - int sysctl_id; - enum chips type; - enum muxtype muxtype; - int pcanum; /* PCA chip number */ - int nchans; /* # of channels (busses) this chip controls */ - int nchmask; /* Mask of all channels */ - - struct semaphore update_lock; - int selmask; /* Bitmask of chans OK to leave on (chn1 == bit0) */ - int curmask; /* Bitmask of chans currently selected */ - - u8 regval; /* Current chip register value */ - u8 origval; /* Original value at initialization */ - - struct i2c_adapter *virt_adapters[PCA954X_NCHANS]; -}; - -static int pca954x_attach_adapter(struct i2c_adapter *adapter); -static int pca954x_detect(struct i2c_adapter *adapter, int address, - unsigned short flags, int kind); -static int pca954x_detach_client(struct i2c_client *client); -static void pca954x_pe_busses(struct i2c_client *client, int operation, - int ctl_name, int *nrels_mag, long *results); -static void pca954x_pe_debug(struct i2c_client *client, int operation, - int ctl_name, int *nrels_mag, long *results); -static void pca954x_pe_regval(struct i2c_client *client, int operation, - int ctl_name, int *nrels_mag, long *results); -static void pca954x_pe_selbus(struct i2c_client *client, int operation, - int ctl_name, int *nrels_mag, long *results); -static void pca954x_pe_selmask(struct i2c_client *client, int operation, - int ctl_name, int *nrels_mag, long *results); -static void pca954x_pe_type(struct i2c_client *client, int operation, - int ctl_name, int *nrels_mag, long *results); -static void pca954x_set_selmask(struct i2c_client *client, int mask); -static u8 pca954x_mask2val(struct i2c_client *client, int mask); -static int pca954x_val2mask(struct i2c_client *client, u8 val); - -static int pca954x_select_mux(struct i2c_adapter *adap, - struct i2c_mux_ctrl *mux); -static int pca954x_deselect_mux(struct i2c_adapter *adap, - struct i2c_mux_ctrl *mux); -static int pca954x_select_chan(struct i2c_adapter *adap, - struct i2c_client *client, unsigned long chan); -static int pca954x_xfer(struct i2c_adapter *adap, - struct i2c_client *client, - int read_write, u8 *val); - - -/* This is the driver that will be inserted */ -static struct i2c_driver pca954x_driver = { - .name = "PCA954X I2C mux/switch driver", - .flags = I2C_DF_NOTIFY, - .attach_adapter = pca954x_attach_adapter, - .detach_client = pca954x_detach_client, -}; - - -/* -- SENSORS SYSCTL START -- */ - -#define PCA954X_SYSCTL_BUSSES 1000 -#define PCA954X_SYSCTL_DEBUG 1001 -#define PCA954X_SYSCTL_REGVAL 1002 -#define PCA954X_SYSCTL_SELBUS 1003 -#define PCA954X_SYSCTL_SELMASK 1004 -#define PCA954X_SYSCTL_TYPE 1005 - -/* -- SENSORS SYSCTL END -- */ - -static ctl_table pca954x_dir_table_template[] = { - {PCA954X_SYSCTL_BUSSES, "busses", NULL, 0, 0444, NULL, - &i2c_proc_real, &i2c_sysctl_real, NULL, &pca954x_pe_busses}, - {PCA954X_SYSCTL_DEBUG, "debug", NULL, 0, 0644, NULL, - &i2c_proc_real, &i2c_sysctl_real, NULL, &pca954x_pe_debug}, - {PCA954X_SYSCTL_REGVAL, "regval", NULL, 0, 0444, NULL, - &i2c_proc_real, &i2c_sysctl_real, NULL, &pca954x_pe_regval}, - {PCA954X_SYSCTL_SELBUS, "selbus", NULL, 0, 0644, NULL, - &i2c_proc_real, &i2c_sysctl_real, NULL, &pca954x_pe_selbus}, - {PCA954X_SYSCTL_SELMASK, "selmask", NULL, 0, 0644, NULL, - &i2c_proc_real, &i2c_sysctl_real, NULL, &pca954x_pe_selmask}, - {PCA954X_SYSCTL_TYPE, "type", NULL, 0, 0444, NULL, - &i2c_proc_real, &i2c_sysctl_real, NULL, &pca954x_pe_type}, - {0} -}; - -static int pca954x_id = 0; - -static int __init pca954x_init(void) -{ - printk("pca954x.o version %s (%s)\n", LM_VERSION, LM_DATE); - - /* Because we've set I2C_DF_NOTIFY in our driver struct, - * this call results in calling pca954x_attach_adapter() for - * every adapter currently known, both real and virtual. - */ - return i2c_add_driver(&pca954x_driver); -} - -static void __exit pca954x_exit(void) -{ - i2c_del_driver(&pca954x_driver); -} - -/* This function is called whenever a new bus/adapter is added, OR when - the driver itself is added (for all existing adapters), to see if - the driver can find a chip address it's responsible for. - */ -static int pca954x_attach_adapter(struct i2c_adapter *adapter) -{ - DBG(printk(KERN_DEBUG "%s: %0lX\n", - __FUNCTION__, (unsigned long)adapter)); - - /* Apply standard lookup via parameters or probing. - "addr_data" is defined by the SENSORS_INSMOD_n macro. - */ - return i2c_detect(adapter, &addr_data, pca954x_detect); -} - -/* This function is called by i2c_detect and must be of type - "i2c_found_addr_proc" as defined in i2c-proc.h. - For the PCA954x series this should only happen due to "force" parameters - given to insmod/modprobe, as there is no way to autodetect what flavor - of chip we have (and the differences matter!) - - Thus, we should never get a "kind" of -1. - - Note the unique potential for infinite recursion here because we are - creating new adapters (one for each muxed virtual bus). This will cause - our attach_adapter() function to be called twice for each new adapter, - because: - - (1) The call to i2c_add_adapter results in calling the attach_adapter() - function of all known chip drivers, including this one. - - (2) Because normally this is first called via i2c_add_driver calling - i2c_add_adapter, each new virtual bus/adapter created here will create - a new entry in i2c-core's master adapter list at a point that hasn't - yet been reached by i2c_add_driver's scan, and thus i2c_add_driver - will cause yet another call to our attach_adapter for each of these - new bus/adapters. - - Each call to our attach_adapter() causes another call to i2c_detect, - which would detect the mux all over again if an actual probe was made. - - This is prevented in two ways. The first line of defense is - i2c_check_addr() which is called by both i2c-proc.c:i2c_detect() - and i2c-core.c:i2c_probe() to make sure a bus/addr pair has not already - been seen; that function now knows how to verify this on all parent - busses as well. - - The second line of defense is to never put anything in the "normal_i2c" - or "normal_i2c_range" tables that would induce i2c_detect() to probe - a PCA954x address. - */ -int pca954x_detect(struct i2c_adapter *adapter, int address, - unsigned short flags, int kind) -{ - int i, n; - struct i2c_client *client; - struct pca954x_data *data; - const char *type_name = ""; - int err = 0; - - DBG(printk(KERN_DEBUG "%s: %0lX %0x %0x %d\n", - __FUNCTION__, (unsigned long)adapter, - address, flags, kind)); - - /* XXX: Remove this after verifying that no more recursion - is happening! - */ - if (adapter->algo->id == I2C_ALGO_VIRT) { - - printk(KERN_ERR "%s: Avoiding recursion! %0lX %0x %0x %d\n", - __FUNCTION__, (unsigned long)adapter, - address, flags, kind); - goto ERROR0; - } - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) - goto ERROR0; - - /* OK. For now, we presume we have a valid client. We now create the - client structure, even though we cannot fill it completely yet. */ - if (!(data = kmalloc(sizeof(struct pca954x_data), GFP_KERNEL))) { - err = -ENOMEM; - goto ERROR0; - } - memset(data, 0, sizeof(struct pca954x_data)); - - client = &data->client; - client->addr = address; - client->data = data; - client->adapter = adapter; - client->driver = &pca954x_driver; - client->flags = 0; - - /* The detection is very weak. In fact, we have no way of - * telling what kind of mux/swi is there, and the differences matter, - * so if asked to figure it out we just complain instead. - */ - if (kind < 0) { - printk(KERN_ERR "%s: Attempted ill-advised probe at addr %0x", - __FUNCTION__, address); - goto ERROR1; - } - - /* Read the mux register at addr. This does two things: it verifies - that the mux is in fact present, and fetches its current - contents for possible use with a future deselect algorithm. - */ - if ((i = i2c_smbus_read_byte(client)) < 0) { - printk(KERN_WARNING - "i2c-%d: pca954x.o failed to read reg at %0x", - i2c_adapter_id(adapter), address); - goto ERROR1; - } - data->origval = i; - - if (kind == any_chip) { - printk(KERN_WARNING - "i2c-%d: pca954x.o needs advice on chip type -" - " wildly guessing %0x is a PCA9540", - i2c_adapter_id(adapter), address); - kind = pca9540; /* Make "any" default to PCA9540 */ - } - - /* Look up in table */ - for (i = sizeof(pca954x_chipdefs)/sizeof(pca954x_chipdefs[0]); - --i >= 0;) { - if (pca954x_chipdefs[i].type == kind) - break; - } - if (i < 0) { - printk(KERN_ERR "%s: Internal error: unknown kind (%d)", - __FUNCTION__, kind); - goto ERROR1; - } - data->type = kind; - type_name = pca954x_chipdefs[i].type_name; - data->pcanum = pca954x_chipdefs[i].pcanum; - data->nchans = pca954x_chipdefs[i].nchans; - data->muxtype = pca954x_chipdefs[i].muxtype; - data->nchmask = (1 << data->nchans) - 1; - - /* Now that we know the mux/swi type, we can analyze the - pca954x_selmask parameter, if one was specified. - - XXX: Not yet. Still uncertain whether there is a good way - to initialize selmask and still continue to detect other chips - correctly on the right busses, or whether the original reg - setting (origval) should be retained in case BIOS depends on it. - */ - - /* Fill in remaining client fields and put it into the global list */ - snprintf(client->name, sizeof(client->name), - "PCA%d I2C %d-chan %s chip", - data->pcanum, data->nchans, - (data->muxtype == pca954x_ismux ? "mux" : "switch")); - client->id = pca954x_id++; - init_MUTEX(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(client))) - goto ERROR1; - - /* Register new /proc directory entries with module sensors */ - if ((i = i2c_register_entry(client, type_name, - pca954x_dir_table_template, - THIS_MODULE)) < 0) { - err = i; - goto ERROR2; - } - data->sysctl_id = i; - - /* Initialize the PCA954X chip. - For now, force unselected. This had better happen BEFORE any - other sensors modules are loaded, or their chip addresses will - stop working if they were actually behind the mux chip. - */ - pca954x_set_selmask(client, 0); - - /* Now create virtual busses and adapters for them */ - -#ifdef I2C_REQUIRE_ARBITRATION - /* This doesn't actually do anything yet; kept as a - placeholder from the original i2c-virtual_cb.c - */ - adapter->algo->acquire_exclusive = &acquire_shared_bus; - adapter->algo->release_exclusive = &release_shared_bus; -#endif - - DBG(printk(KERN_DEBUG "%s: creating %d virt busses\n", - __FUNCTION__, data->nchans)); - - for (i = 0, n = 0; i < data->nchans; ++i) { - struct i2c_adapter *virt; - virt = i2c_virt_create_adapter(adapter, client, i, - &pca954x_select_mux, - &pca954x_deselect_mux); - if ((data->virt_adapters[i] = virt) != NULL) - ++n; - } - printk("i2c-%d: Registered %d of %d virtual busses for I2C mux %s\n", - i2c_adapter_id(adapter), n, i, type_name); - - return 0; - - ERROR2: - i2c_detach_client(client); - ERROR1: - kfree(data); - ERROR0: - return err; -} - -static int pca954x_detach_client(struct i2c_client *client) -{ - struct pca954x_data *data = (struct pca954x_data *)(client->data); - int i, err; - - DBG(printk(KERN_DEBUG "%s: %0lX\n", - __FUNCTION__, (unsigned long)client)); - - /* Must flush everything attached to our channels! - */ - for (i = 0; i < data->nchans; ++i) { - if (data->virt_adapters[i]) { - err = i2c_virt_remove_adapter(data->virt_adapters[i]); - if (err != 0) { - printk(KERN_ERR "pca954x.o: Bus deregistration failed, " - "client not detached.\n"); - return err; - } - data->virt_adapters[i] = NULL; - } - } - - i2c_deregister_entry(data->sysctl_id); - - if ((err = i2c_detach_client(client))) { - printk(KERN_ERR "pca954x.o: Client deregistration failed, " - "client not detached.\n"); - return err; - } - - kfree(client->data); - - return 0; -} - - -/* Implement /proc "regval" - the actual contents of the chip register. - * This is READ-ONLY. - */ -void pca954x_pe_regval(struct i2c_client *client, int operation, - int ctl_name, int *nrels_mag, long *results) -{ - struct pca954x_data *data = client->data; - - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 0; - else if (operation == SENSORS_PROC_REAL_READ) { -#if 0 /* XXX: For now, always use cached value */ - static void pca954x_update_client(struct i2c_client *client); - pca954x_update_client(client); -#endif - results[0] = data->regval; - *nrels_mag = 1; - } -} - -/* Implement /proc "debug" - a non-zero value enables debug output, if - * the code was compiled with it. This actually applies to all mux chips, - * not just a single instance, but that's OK. - */ -void pca954x_pe_debug(struct i2c_client *client, int operation, - int ctl_name, int *nrels_mag, long *results) -{ - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 0; - else if (operation == SENSORS_PROC_REAL_READ) { - results[0] = pca954x_debug; - *nrels_mag = 1; - } else if (operation == SENSORS_PROC_REAL_WRITE) { - if (*nrels_mag >= 1) { - pca954x_debug = results[0]; - } - } -} - -/* Implement /proc "busses" - list of (virtual) adapter IDs that constitute - the busses that this chip connects to. - This is READ-ONLY. - */ -void pca954x_pe_busses(struct i2c_client *client, int operation, - int ctl_name, int *nrels_mag, long *results) -{ - struct pca954x_data *data = client->data; - - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 0; - else if (operation == SENSORS_PROC_REAL_READ) { - int i, lasti; - if ((lasti = data->nchans) > *nrels_mag) - lasti = *nrels_mag; - for (i = 0; i < lasti; ++i) { - results[i] = i2c_adapter_id(data->virt_adapters[i]); - } - *nrels_mag = lasti; - } -} - -/* Implement /proc "selmask" - the value specifies the current default - * channel mask. Sub-bus 0 == bit 0. - # A value of 0 means "none" - */ -void pca954x_pe_selmask(struct i2c_client *client, int operation, - int ctl_name, int *nrels_mag, long *results) -{ - struct pca954x_data *data = client->data; - - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 0; - else if (operation == SENSORS_PROC_REAL_READ) { - results[0] = data->selmask; - *nrels_mag = 1; - } else if (operation == SENSORS_PROC_REAL_WRITE) { - if (*nrels_mag >= 1) { - pca954x_set_selmask(client, results[0]); - } - } -} - - -/* Implement /proc "selbus" - the list of values is considered to be virtual - adapter IDs, as an alternative representation of the select mask. - No values at all means "none". - */ -void pca954x_pe_selbus(struct i2c_client *client, int operation, - int ctl_name, int *nrels_mag, long *results) -{ - struct pca954x_data *data = client->data; - int i, nres; - - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 0; - else if (operation == SENSORS_PROC_REAL_READ) { - for (i = 0, nres = 0; i < data->nchans; ++i) { - if ((data->selmask & (1<virt_adapters[i]); - ++nres; - } - } - *nrels_mag = nres; - } else if (operation == SENSORS_PROC_REAL_WRITE) { - int newmask = 0; - for (nres = 0; nres < *nrels_mag; ++nres) { - /* Ugly, but shouldn't happen very often */ - for (i = 0; i < data->nchans; ++i) { - if (results[nres] - == i2c_adapter_id(data->virt_adapters[i])) { - newmask |= (1<data; - - if (operation == SENSORS_PROC_REAL_INFO) - *nrels_mag = 0; - else if (operation == SENSORS_PROC_REAL_READ) { - if (*nrels_mag >= 3) { - results[0] = data->pcanum; - results[1] = data->muxtype; - results[2] = data->nchans; - *nrels_mag = 3; - } - } -} - - -/* Set default select mask. - Since this can be executed while something else is using the mux or - one of its sub-busses, the main consideration is making sure we don't - mess up anything in progress. - - This is accomplished by locking the parent bus that the mux resides on, - and then calling our internal write function. - - It would not work to just call i2c_smbus_write_byte() because - by the time that returns, the values we're trying to update - could already be wrong. This can happen if something else grabs - the bus and writes to the mux (eg for doing I/O to a sub-bus - device), leading to a race condition for updating - selmask, regval, and curmask. - - It doesn't help to use an update_lock for those values because - you still have to contend with other threads trying to select - sub-busses and would encounter deadlocks. - - */ -static void pca954x_set_selmask(struct i2c_client *client, int mask) -{ - struct pca954x_data *data = client->data; - - DBG(printk(KERN_DEBUG - "%s: Locking bus %d mux %d (%0lX) " - "for write of selmask %0x\n", - __FUNCTION__, i2c_adapter_id(client->adapter), - client->id, (unsigned long)client, mask)); - - down(&client->adapter->bus); - DBG(printk(KERN_DEBUG "%s: Starting write.\n", __FUNCTION__)); - data->selmask = (mask & data->nchmask); - (void) pca954x_select_chan(client->adapter, client, -1); - up(&client->adapter->bus); - - DBG(printk(KERN_DEBUG "%s: Unlocked mux (%0lX) for write.\n", - __FUNCTION__, (unsigned long)client)); -} - -#if 0 /* Not needed at the moment; see pca954x_pe_regval() */ - -/* Read pca954x register into cached value - */ -static void pca954x_update_client(struct i2c_client *client) -{ - struct pca954x_data *data = client->data; - - DBG(printk(KERN_DEBUG - "%s: Locking bus %d mux %d (%0lX) for read\n", - __FUNCTION__, i2c_adapter_id(client->adapter), - client->id, (unsigned long)client)); - - down(&client->adapter->bus); - DBG(printk(KERN_DEBUG "%s: Starting read.\n", __FUNCTION__)); - pca954x_xfer(client->adapter, client, I2C_SMBUS_READ, &data->regval); - data->curmask = pca954x_val2mask(client, data->regval); - up(&client->adapter->bus); - - DBG(printk(KERN_DEBUG "%s: Unlocked mux (%0lX) for read.\n", - __FUNCTION__, (unsigned long)client)); -} -#endif - - -static u8 pca954x_mask2val(struct i2c_client *client, int mask) -{ - struct pca954x_data *data = (struct pca954x_data *)(client->data); - int i; - - mask &= data->nchmask; /* Sanitize mask */ - if (mask == 0) - return 0; /* Deselecting all, turn off */ - if (data->muxtype == pca954x_isswi) - return mask; /* Switch, can enable all at once! */ - - /* Mux, can only pick one. Select lowest chan bit */ - for (i=0; (mask & (1<data); - - if (data->muxtype == pca954x_isswi) - return val & data->nchmask; /* Switch val is == mask */ - - /* Mux - mask off low bits to get 0-based chan # as bit shift */ - if (val & PCA954X_MUX_ENA) - return 1 << (val & (data->nchans-1)); - return 0; -} - -/***************************************************************************** - * All of the following functions should only be called after the parent - * adapter bus semaphore (adapter->bus) has been acquired, so we cannot - * call the high-level i2c_smbus_write_byte() function -- it will deadlock - * attempting to acquire the same bus lock. Instead do directly what it - * would do, by means of pca954x_xfer(). Sigh! - * - * These functions are allowed to block. - * - *****************************************************************************/ - - -static int pca954x_select_mux(struct i2c_adapter *adap, - struct i2c_mux_ctrl *mux) -{ - return pca954x_select_chan(adap, mux->client, mux->value); -} - -static int pca954x_deselect_mux(struct i2c_adapter *adap, - struct i2c_mux_ctrl *mux) -{ - return pca954x_select_chan(adap, mux->client, -1); -} - -/* Select channel. - * PCA954x I2C-controlled bus mux/switch chips mainly differ in - * whether the chip is a mux or a switch: - * Mux: value addressed, only 1 bus can be selected. - * Swi: bitmask selected, any/all busses can be selected. - */ -static int pca954x_select_chan(struct i2c_adapter *adap, - struct i2c_client *client, - unsigned long chan) -{ - struct pca954x_data *data = (struct pca954x_data *)(client->data); - int maskbit; - u8 newregval; - int ret; - - if (chan == -1) { /* Op: clever deselect (to selmask) */ - if ((data->muxtype == pca954x_ismux) - && (data->curmask & data->selmask)) { - /* If mux, and current chan allowed by selmask, do nothing */ - newregval = data->regval; /* No change */ - } else { - /* Anything else just reverts to selmask */ - newregval = pca954x_mask2val(client, data->selmask); - } - - } else { /* Op: select chan */ - maskbit = 1 << chan; - if (maskbit & data->curmask) { /* If already selected, */ - newregval = data->regval; /* no change */ - } else if ((data->muxtype == pca954x_ismux) - || !(maskbit & data->selmask)) { - newregval = pca954x_mask2val(client, maskbit); - } else - newregval = pca954x_mask2val(client, data->selmask); - } - - /* Only clobber control reg when value changes, to avoid - unnecessary mux writes. For safety and initialization, - ALWAYS force the write if 0 is desired. - */ - ret = (!newregval || (data->regval != newregval)); - DBG(printk(KERN_DEBUG - "%s: Mux %d: chan %d, val %02x - %s\n", - __FUNCTION__, - client->id, (int)chan, newregval, - (ret ? "writing" : "skipping" ) )); - if (ret) { - ret = pca954x_xfer(adap, client, I2C_SMBUS_WRITE, &newregval); - - if (ret < 0) { - printk(KERN_ERR "%s: I2C mux %d select failed " - "(addr=%02x, val=%02x, err=%d)!\n", - __FUNCTION__, client->id, - client->addr, newregval, ret); - } else { - data->regval = newregval; - data->curmask = pca954x_val2mask(client, newregval); - } - } - return ret; -} - - -static int pca954x_xfer(struct i2c_adapter *adap, - struct i2c_client *client, - int read_write, u8 *val) -{ - int ret; - - if (adap->algo->master_xfer) { - /* Use I2C transfer */ - struct i2c_msg msg; - char buf[1]; - - msg.addr = client->addr; - msg.flags = (read_write == I2C_SMBUS_READ ? I2C_M_RD : 0); - msg.len = 1; - buf[0] = *val; - msg.buf = buf; - ret = adap->algo->master_xfer(adap, &msg, 1); - if (!ret && (read_write == I2C_SMBUS_READ)) - *val = buf[0]; - - } else if (adap->algo->smbus_xfer) { - /* Use SMBus transfer */ - union i2c_smbus_data data; - ret = adap->algo->smbus_xfer(adap, - client->addr, - client->flags & I2C_M_TEN, - read_write, - *val, - I2C_SMBUS_BYTE, &data); - if (!ret && (read_write == I2C_SMBUS_READ)) - *val = data.byte; - } else { - printk(KERN_ERR "%s: no smbus_xfer or master_xfer for " - "adapter %0lX, client %0lX\n", - __FUNCTION__, (unsigned long)adap, (unsigned long)client); - ret = -1; - } - return ret; -} - - -/* ------------------ */ - -MODULE_AUTHOR("Ken Harrenstien "); -MODULE_DESCRIPTION("PCA954X I2C mux/switch driver"); - -module_init(pca954x_init); -module_exit(pca954x_exit); diff --git a/kernel/include/i2c-virtual.h b/kernel/include/i2c-virtual.h deleted file mode 100644 index 4bca2f1a..00000000 --- a/kernel/include/i2c-virtual.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * i2c-virtual.h - Header file for the 'virtual i2c' adapter driver. - * - * Copyright (c) 2004 Google, Inc. - * - * Based on: - * i2c-virtual.h from Brian Kuschak - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#ifndef __I2C_VIRTUAL_H -#define __I2C_VIRTUAL_H - -#include - -struct i2c_mux_ctrl { - struct i2c_client *client; /* The mux chip/device */ - - unsigned long addr; - unsigned long value; /* Channel # */ - - /* fn which enables the mux */ - int (*select)(struct i2c_adapter *adap, struct i2c_mux_ctrl *mux); - - /* fn which disables the mux */ - int (*deselect)(struct i2c_adapter *adap, struct i2c_mux_ctrl *mux); -}; - -/* This has to be exposed, since the code which assigns the callbacks must - use it. - */ -struct i2c_virt_priv { - struct i2c_adapter *parent_adap; /* pointer to parent adapter */ - struct i2c_mux_ctrl mux; /* MUX settings for this adapter */ -}; - - -static inline struct i2c_adapter *i2c_virt_parent(struct i2c_adapter *adap) -{ - if (adap->algo && (adap->algo->id == I2C_ALGO_VIRT)) { - return ((struct i2c_virt_priv *)(adap->data))->parent_adap; - } - return NULL; -} - -/* - * Called to create a 'virtual' i2c bus which represents a multiplexed bus - * segment. The client and mux_val are passed to the select and deselect - * callback functions to perform hardware-specific mux control. - */ -struct i2c_adapter *i2c_virt_create_adapter(struct i2c_adapter *parent_adap, - struct i2c_client *client, - unsigned long mux_val, - void *select_cb, - void *deselect_cb); -int i2c_virt_remove_adapter(struct i2c_adapter *adap); - - -#endif /* __I2C_VIRTUAL_H */ diff --git a/lm_sensors.lsm b/lm_sensors.lsm index 13d37e4c..96b1f3cb 100644 --- a/lm_sensors.lsm +++ b/lm_sensors.lsm @@ -7,10 +7,9 @@ Description: Hardware health monitoring package for Linux. It consists of of a library to allow applications to read this data more easily, and of an example program to pretty print this data. LM78, LM79, LM80, W83781D and GL518SM sensor chips are - supported, among others. PIIX4 and VIA chipset SMBus - implementations are supported, as well as many I2C busses. + supported, among others. Version 2 is a complete non-compatible modular rewrite of this - package, with full I2C and SMBus support. + package. Keywords: kernel module SMBus sensors LM78 health Author: frodol@dds.nl (Frodo Looijaard) phil@netroedge.com (Philip Edelbrock)