diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/Kconfig i2c-2.5/drivers/i2c/Kconfig --- linux-2.6.0-test5/drivers/i2c/Kconfig Mon Sep 8 19:49:57 2003 +++ i2c-2.5/drivers/i2c/Kconfig Tue Sep 23 10:12:58 2003 @@ -22,10 +22,20 @@ If you want I2C support, you should say Y here and also to the specific driver for your bus adapter(s) below. - This I2C support is also available as a module. If you want to - compile it as a module, say M here and read - . - The module will be called i2c-core. + This I2C support can also be built as a module. If so, the module + will be called i2c-core. + +config I2C_CHARDEV + tristate "I2C device interface" + depends on I2C + help + Say Y here to use i2c-* device files, usually found in the /dev + directory on your system. They make it possible to have user-space + programs use the I2C bus. Information on how to do this is + contained in the file . + + This support is also available as a module. If so, the module + will be called i2c-dev. config I2C_ALGOBIT tristate "I2C bit-banging interfaces" @@ -35,105 +45,8 @@ adapters. Say Y if you own an I2C adapter belonging to this class and then say Y to the specific driver for you adapter below. - This support is also available as a module. If you want to compile - it as a module, say M here and read - . - The module will be called i2c-algo-bit. - -config I2C_PROSAVAGE - tristate "S3/VIA (Pro)Savage" - depends on I2C_ALGOBIT && PCI && EXPERIMENTAL - help - If you say yes to this option, support will be included for the - I2C bus and DDC bus of the S3VIA embedded Savage4 and ProSavage8 - graphics processors. - chipsets supported: - S3/VIA KM266/VT8375 aka ProSavage8 - S3/VIA KM133/VT8365 aka Savage4 - - This can also be built as a module which can be inserted and removed - while the kernel is running. If you want to compile it as a module, - say M here and read . - The module will be called i2c-prosavage. - - You will also need the latest user-space utilties: you can find them - in the lm_sensors package, which you can download at - http://www.lm-sensors.nu - -config I2C_PHILIPSPAR - tristate "Philips style parallel port adapter" - depends on I2C_ALGOBIT && PARPORT - ---help--- - This supports parallel-port I2C adapters made by Philips. Say Y if - you own such an adapter. - - This driver is also available as a module. If you want to compile - it as a module, say M here and read - . - The module will be called i2c-philips-par. - - Note that if you want support for different parallel port devices, - life will be much easier if you compile them all as modules. - -config I2C_ELV - tristate "ELV adapter" - depends on I2C_ALGOBIT && ISA - help - This supports parallel-port I2C adapters called ELV. Say Y if you - own such an adapter. - - This driver is also available as a module. If you want to compile - it as a module, say M here and read - . - The module will be called i2c-elv. - -config I2C_VELLEMAN - tristate "Velleman K9000 adapter" - depends on I2C_ALGOBIT && ISA - help - This supports the Velleman K9000 parallel-port I2C adapter. Say Y - if you own such an adapter. - - This driver is also available as a module. If you want to compile - it as a module, say M here and read - . - The module will be called i2c-velleman. - -config SCx200_I2C - tristate "NatSemi SCx200 I2C using GPIO pins" - depends on SCx200 && I2C_ALGOBIT - help - Enable the use of two GPIO pins of a SCx200 processor as an I2C bus. - - If you don't know what to do here, say N. - - If compiled as a module, it will be called scx200_i2c. - -config SCx200_I2C_SCL - int "GPIO pin used for SCL" - depends on SCx200_I2C - default "12" - help - Enter the GPIO pin number used for the SCL signal. This value can - also be specified with a module parameter. - -config SCx200_I2C_SDA - int "GPIO pin used for SDA" - depends on SCx200_I2C - default "13" - help - Enter the GPIO pin number used for the SSA signal. This value can - also be specified with a module parameter. - -config SCx200_ACB - tristate "NatSemi SCx200 ACCESS.bus" - depends on I2C_ALGOBIT!=n && I2C - help - Enable the use of the ACCESS.bus controllers of a SCx200 processor. - - If you don't know what to do here, say N. - - If compiled as a module, it will be called scx200_acb. + This support is also available as a module. If so, the module + will be called i2c-algo-bit. config I2C_ALGOPCF tristate "I2C PCF 8584 interfaces" @@ -143,35 +56,10 @@ Say Y if you own an I2C adapter belonging to this class and then say Y to the specific driver for you adapter below. - This support is also available as a module. If you want to compile - it as a module, say M here and read - . - The module will be called i2c-algo-pcf. - -config I2C_ELEKTOR - tristate "Elektor ISA card" - depends on I2C_ALGOPCF && BROKEN_ON_SMP - help - This supports the PCF8584 ISA bus I2C adapter. Say Y if you own - such an adapter. + This support is also available as a module. If so, the module + will be called i2c-algo-pcf. - This driver is also available as a module. If you want to compile - it as a module, say M here and read - . - The module will be called i2c-elektor. - -config I2C_KEYWEST - tristate "Powermac Keywest I2C interface" - depends on I2C && PPC_PMAC - help - This supports the use of the I2C interface in the combo-I/O - chip on recent Apple machines. Say Y if you have such a machine. - - This driver is also available as a module. If you want to compile - it as a module, say M here and read Documentation/modules.txt. - The module will be called i2c-keywest. - -config ITE_I2C_ALGO +config I2C_ALGOITE tristate "ITE I2C Algorithm" depends on MIPS_ITE8172 && I2C help @@ -179,56 +67,13 @@ systems. Say Y if you have one of these. You should also say Y for the ITE I2C peripheral driver support below. - This support is also available as a module. If you want to compile - it as a module, say M here and read Documentation/modules.txt. - The module will be called i2c-algo-ite. - -config ITE_I2C_ADAP - tristate "ITE I2C Adapter" - depends on ITE_I2C_ALGO - help - This supports the ITE8172 I2C peripheral found on some MIPS - systems. Say Y if you have one of these. You should also say Y for - the ITE I2C driver algorithm support above. - - This support is also available as a module. If you want to compile - it as a module, say M here and read Documentation/modules.txt. - The module will be called i2c-adap-ite. + This support is also available as a module. If so, the module + will be called i2c-algo-ite. config I2C_ALGO8XX tristate "MPC8xx CPM I2C interface" depends on 8xx && I2C -config I2C_RPXLITE - tristate "Embedded Planet RPX Lite/Classic suppoort" - depends on (RPXLITE || RPXCLASSIC) && I2C_ALGO8XX - -config I2C_IBM_OCP_ALGO - tristate "IBM on-chip I2C Algorithm" - depends on IBM_OCP && I2C - -config I2C_IBM_OCP_ADAP - tristate "IBM on-chip I2C Adapter" - depends on I2C_IBM_OCP_ALGO - -config I2C_IOP3XX - tristate "Intel XScale IOP3xx on-chip I2C interface" - depends on ARCH_IOP3XX && I2C - -config I2C_CHARDEV - tristate "I2C device interface" - depends on I2C - help - Say Y here to use i2c-* device files, usually found in the /dev - directory on your system. They make it possible to have user-space - programs use the I2C bus. Information on how to do this is - contained in the file . - - This code is also available as a module. If you want to compile - it as a module, say M here and read - . - The module will be called i2c-dev. - source drivers/i2c/busses/Kconfig source drivers/i2c/chips/Kconfig diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/Makefile i2c-2.5/drivers/i2c/Makefile --- linux-2.6.0-test5/drivers/i2c/Makefile Mon Sep 8 19:49:51 2003 +++ i2c-2.5/drivers/i2c/Makefile Tue Sep 23 10:12:58 2003 @@ -1,21 +1,11 @@ # -# Makefile for the kernel i2c bus driver. +# Makefile for the i2c core. # obj-$(CONFIG_I2C) += i2c-core.o obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o +obj-$(CONFIG_I2C_SENSOR) += i2c-sensor.o obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o -obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o -obj-$(CONFIG_I2C_PHILIPSPAR) += i2c-philips-par.o -obj-$(CONFIG_I2C_ELV) += i2c-elv.o -obj-$(CONFIG_I2C_VELLEMAN) += i2c-velleman.o obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o -obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o -obj-$(CONFIG_I2C_KEYWEST) += i2c-keywest.o -obj-$(CONFIG_ITE_I2C_ALGO) += i2c-algo-ite.o -obj-$(CONFIG_ITE_I2C_ADAP) += i2c-adap-ite.o -obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o -obj-$(CONFIG_SCx200_ACB) += scx200_acb.o -obj-$(CONFIG_I2C_SENSOR) += i2c-sensor.o -obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o +obj-$(CONFIG_I2C_ALGOITE) += i2c-algo-ite.o obj-y += busses/ chips/ diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/Kconfig i2c-2.5/drivers/i2c/busses/Kconfig --- linux-2.6.0-test5/drivers/i2c/busses/Kconfig Mon Sep 8 19:50:22 2003 +++ i2c-2.5/drivers/i2c/busses/Kconfig Tue Sep 23 10:12:59 2003 @@ -2,10 +2,10 @@ # Sensor device configuration # -menu "I2C Hardware Sensors Mainboard support" +menu "I2C Hardware Bus support" config I2C_ALI1535 - tristate " ALI 1535" + tristate "ALI 1535" depends on I2C && PCI && EXPERIMENTAL help If you say yes to this option, support will be included for the SMB @@ -13,63 +13,61 @@ controller is part of the 7101 device, which is an ACPI-compliant Power Management Unit (PMU). - This can also be built as a module. If so, the module will be - called i2c-ali1535. - - You will also need the latest user-space utilties: you can find them - in the lm_sensors package, which you can download at - http://www.lm-sensors.nu + This driver can also be built as a module. If so, the module + will be called i2c-ali1535. config I2C_ALI15X3 - tristate " ALI 15x3" + tristate "ALI 15x3" depends on I2C && PCI && EXPERIMENTAL help If you say yes to this option, support will be included for the Acer Labs Inc. (ALI) M1514 and M1543 motherboard I2C interfaces. - This can also be built as a module. If so, the module will be - called i2c-ali15x3. - - You will also need the latest user-space utilties: you can find them - in the lm_sensors package, which you can download at - http://www.lm-sensors.nu + This driver can also be built as a module. If so, the module + will be called i2c-ali15x3. config I2C_AMD756 - tristate " AMD 756/766" + tristate "AMD 756/766" depends on I2C && EXPERIMENTAL help If you say yes to this option, support will be included for the AMD 756/766/768 mainboard I2C interfaces. - This can also be built as a module which can be inserted and removed - while the kernel is running. If you want to compile it as a module, - say M here and read . - - The module will be called i2c-amd756. - - You will also need the latest user-space utilties: you can find them - in the lm_sensors package, which you can download at - http://www.lm-sensors.nu + This driver can also be built as a module. If so, the module + will be called i2c-amd756. config I2C_AMD8111 - tristate " AMD 8111" + tristate "AMD 8111" depends on I2C && EXPERIMENTAL help If you say yes to this option, support will be included for the AMD 8111 mainboard I2C interfaces. - This can also be built as a module which can be inserted and removed - while the kernel is running. If you want to compile it as a module, - say M here and read . - - The module will be called i2c-amd8111. - - You will also need the latest user-space utilties: you can find them - in the lm_sensors package, which you can download at - http://www.lm-sensors.nu + This driver can also be built as a module. If so, the module + will be called i2c-amd8111. + +config I2C_ELEKTOR + tristate "Elektor ISA card" + depends on I2C_ALGOPCF && BROKEN_ON_SMP + help + This supports the PCF8584 ISA bus I2C adapter. Say Y if you own + such an adapter. + + This support is also available as a module. If so, the module + will be called i2c-elektor. + +config I2C_ELV + tristate "ELV adapter" + depends on I2C_ALGOBIT && ISA + help + This supports parallel-port I2C adapters called ELV. Say Y if you + own such an adapter. + + This support is also available as a module. If so, the module + will be called i2c-elv. config I2C_I801 - tristate " Intel 801" + tristate "Intel 801" depends on I2C && PCI && EXPERIMENTAL help If you say yes to this option, support will be included for the Intel @@ -81,53 +79,84 @@ 82801CA/CAM 82801DB - This can also be built as a module which can be inserted and removed - while the kernel is running. If you want to compile it as a module, - say M here and read . - - The module will be called i2c-i801. - - You will also need the latest user-space utilties: you can find them - in the lm_sensors package, which you can download at - http://www.lm-sensors.nu + This driver can also be built as a module. If so, the module + will be called i2c-i801. + +config I2C_I810 + tristate "Intel 810/815" + depends on I2C_ALGOBIT && PCI && EXPERIMENTAL + help + If you say yes to this option, support will be included for the Intel + 810/815 family of mainboard I2C interfaces. Specifically, the + following versions of the chipset is supported: + i810AA + i810AB + i810E + i815 + + This driver can also be built as a module. If so, the module + will be called i2c-i810. + +config I2C_IBM_IIC + tristate "IBM IIC I2C" + depends on IBM_OCP && I2C + +config I2C_IOP3XX + tristate "Intel XScale IOP3xx on-chip I2C interface" + depends on ARCH_IOP3XX && I2C config I2C_ISA - tristate " ISA Bus support" + tristate "ISA Bus support" depends on I2C && ISA && EXPERIMENTAL help If you say yes to this option, support will be included for i2c interfaces that are on the ISA bus. - This can also be built as a module which can be inserted and removed - while the kernel is running. If you want to compile it as a module, - say M here and read . - - The module will be called i2c-isa. - - You will also need the latest user-space utilties: you can find them - in the lm_sensors package, which you can download at - http://www.lm-sensors.nu + This driver can also be built as a module. If so, the module + will be called i2c-isa. + +config I2C_ITE + tristate "ITE I2C Adapter" + depends on I2C_ALGOITE + help + This supports the ITE8172 I2C peripheral found on some MIPS + systems. Say Y if you have one of these. You should also say Y for + the ITE I2C driver algorithm support above. + + This support is also available as a module. If so, the module + will be called i2c-ite. + +config I2C_KEYWEST + tristate "Powermac Keywest I2C interface" + depends on I2C && PPC_PMAC + help + This supports the use of the I2C interface in the combo-I/O + chip on recent Apple machines. Say Y if you have such a machine. + + This support is also available as a module. If so, the module + will be called i2c-keywest. config I2C_NFORCE2 - tristate " Nvidia Nforce2" + tristate "Nvidia Nforce2" depends on I2C && PCI && EXPERIMENTAL help If you say yes to this option, support will be included for the Nvidia Nforce2 family of mainboard I2C interfaces. - This can also be built as a module which can be inserted and removed - while the kernel is running. If you want to compile it as a module, - say M here and read . - - The module will be called i2c-nforce2. - - You will also need the latest user-space utilties: you can find them - in the lm_sensors package, which you can download at - http://www.lm-sensors.nu + This driver can also be built as a module. If so, the module + will be called i2c-nforce2. + +config I2C_PHILIPSPAR + tristate "Philips style parallel port adapter" + depends on I2C_ALGOBIT && PARPORT + help + This supports parallel-port I2C adapters made by Philips. + This support is also available as a module. If so, the module + will be called i2c-philips-par. config I2C_PIIX4 - tristate " Intel PIIX4" + tristate "Intel PIIX4" depends on I2C && PCI && EXPERIMENTAL help If you say yes to this option, support will be included for the Intel @@ -139,19 +168,97 @@ Serverworks CSB5 SMSC Victory66 - This can also be built as a module which can be inserted and removed - while the kernel is running. If you want to compile it as a module, - say M here and read . - - The module will be called i2c-piix4. - - You will also need the latest user-space utilties: you can find them - in the lm_sensors package, which you can download at - http://www.lm-sensors.nu + This driver can also be built as a module. If so, the module + will be called i2c-piix4. + +config I2C_PROSAVAGE + tristate "S3/VIA (Pro)Savage" + depends on I2C_ALGOBIT && PCI && EXPERIMENTAL + help + If you say yes to this option, support will be included for the + I2C bus and DDC bus of the S3VIA embedded Savage4 and ProSavage8 + graphics processors. + chipsets supported: + S3/VIA KM266/VT8375 aka ProSavage8 + S3/VIA KM133/VT8365 aka Savage4 + + This support is also available as a module. If so, the module + will be called i2c-prosavage. + +config I2C_RPXLITE + tristate "Embedded Planet RPX Lite/Classic suppoort" + depends on (RPXLITE || RPXCLASSIC) && I2C_ALGO8XX + +config I2C_SAVAGE4 + tristate "S3 Savage 4" + depends on I2C_ALGOBIT && PCI && EXPERIMENTAL + help + If you say yes to this option, support will be included for the + S3 Savage 4 I2C interface. + + This driver can also be built as a module. If so, the module + will be called i2c-savage4. + +config SCx200_I2C + tristate "NatSemi SCx200 I2C using GPIO pins" + depends on SCx200 && I2C_ALGOBIT + help + Enable the use of two GPIO pins of a SCx200 processor as an I2C bus. + + If you don't know what to do here, say N. + + This support is also available as a module. If so, the module + will be called scx200_i2c. + +config SCx200_I2C_SCL + int "GPIO pin used for SCL" + depends on SCx200_I2C + default "12" + help + Enter the GPIO pin number used for the SCL signal. This value can + also be specified with a module parameter. + +config SCx200_I2C_SDA + int "GPIO pin used for SDA" + depends on SCx200_I2C + default "13" + help + Enter the GPIO pin number used for the SSA signal. This value can + also be specified with a module parameter. + +config SCx200_ACB + tristate "NatSemi SCx200 ACCESS.bus" + depends on I2C_ALGOBIT!=n && I2C + help + Enable the use of the ACCESS.bus controllers of a SCx200 processor. + + If you don't know what to do here, say N. + + This support is also available as a module. If so, the module + will be called scx200_acb. + +config I2C_SIS5595 + tristate "SiS 5595" + depends on I2C && PCI && EXPERIMENTAL + help + If you say yes to this option, support will be included for the + SiS5595 SMBus (a subset of I2C) interface. + + This driver can also be built as a module. If so, the module + will be called i2c-sis5595. + +config I2C_SIS630 + tristate "SiS 630" + depends on I2C && PCI && EXPERIMENTAL + help + If you say yes to this option, support will be included for the + SiS630 SMBus (a subset of I2C) interface. + This driver can also be built as a module. If so, the module + will be called i2c-sis630. config I2C_SIS96X - tristate " SiS 96x" + tristate "SiS 96x" depends on I2C && PCI && EXPERIMENTAL help If you say yes to this option, support will be included for the SiS @@ -164,19 +271,32 @@ 650/961 735 - This can also be built as a module which can be inserted and removed - while the kernel is running. If you want to compile it as a module, - say M here and read . - - The module will be called i2c-sis96x. - - You will also need the latest user-space utilties: you can find them - in the lm_sensors package, which you can download at - http://www.lm-sensors.nu + This driver can also be built as a module. If so, the module + will be called i2c-sis96x. +config I2C_VELLEMAN + tristate "Velleman K9000 adapter" + depends on I2C_ALGOBIT && ISA + help + This supports the Velleman K9000 parallel-port I2C adapter. Say Y + if you own such an adapter. + + This support is also available as a module. If so, the module + will be called i2c-velleman. + +config I2C_VIA + tristate "VIA 82C58B" + depends on I2C_ALGOBIT && PCI && EXPERIMENTAL + help + + If you say yes to this option, support will be included for the VIA + 82C586B I2C interface + + This driver can also be built as a module. If so, the module + will be called i2c-via. config I2C_VIAPRO - tristate " VIA 82C596/82C686/823x" + tristate "VIA 82C596/82C686/823x" depends on I2C && PCI && EXPERIMENTAL help @@ -190,15 +310,18 @@ 8233A 8235 - This can also be built as a module which can be inserted and removed - while the kernel is running. If you want to compile it as a module, - say M here and read . - - The module will be called i2c-viapro. - - You will also need the latest user-space utilties: you can find them - in the lm_sensors package, which you can download at - http://www.lm-sensors.nu + This driver can also be built as a module. If so, the module + will be called i2c-viapro. -endmenu +config I2C_VOODOO3 + tristate "Voodoo 3" + depends on I2C_ALGOBIT && PCI && EXPERIMENTAL + help + + If you say yes to this option, support will be included for the + Voodoo 3 I2C interface. + + This driver can also be built as a module. If so, the module + will be called i2c-voodoo3. +endmenu diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/Makefile i2c-2.5/drivers/i2c/busses/Makefile --- linux-2.6.0-test5/drivers/i2c/busses/Makefile Mon Sep 8 19:49:52 2003 +++ i2c-2.5/drivers/i2c/busses/Makefile Tue Sep 23 10:12:59 2003 @@ -1,14 +1,32 @@ # -# Makefile for the kernel hardware sensors bus drivers. +# Makefile for the i2c bus drivers. # obj-$(CONFIG_I2C_ALI1535) += i2c-ali1535.o obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o +obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o +obj-$(CONFIG_I2C_ELV) += i2c-elv.o obj-$(CONFIG_I2C_I801) += i2c-i801.o +obj-$(CONFIG_I2C_I810) += i2c-i810.o +obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o +obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o obj-$(CONFIG_I2C_ISA) += i2c-isa.o +obj-$(CONFIG_I2C_ITE) += i2c-ite.o +obj-$(CONFIG_I2C_KEYWEST) += i2c-keywest.o obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o +obj-$(CONFIG_I2C_PHILIPSPAR) += i2c-philips-par.o obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o +obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o +obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o +obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o +obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o +obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o +obj-$(CONFIG_I2C_VELLEMAN) += i2c-velleman.o +obj-$(CONFIG_I2C_VIA) += i2c-via.o obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o +obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o +obj-$(CONFIG_SCx200_ACB) += scx200_acb.o +obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-ali1535.c i2c-2.5/drivers/i2c/busses/i2c-ali1535.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-ali1535.c Mon Sep 8 19:50:22 2003 +++ i2c-2.5/drivers/i2c/busses/i2c-ali1535.c Tue Sep 23 10:12:59 2003 @@ -481,7 +481,6 @@ static struct i2c_adapter ali1535_adapter = { .owner = THIS_MODULE, - .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_ALI1535, .algo = &smbus_algorithm, .name = "unset", }; @@ -507,7 +506,7 @@ /* set up the driverfs linkage to our parent device */ ali1535_adapter.dev.parent = &dev->dev; - snprintf(ali1535_adapter.name, DEVICE_NAME_SIZE, + snprintf(ali1535_adapter.name, I2C_NAME_SIZE, "SMBus ALI1535 adapter at %04x", ali1535_smba); return i2c_add_adapter(&ali1535_adapter); } @@ -526,7 +525,6 @@ static int __init i2c_ali1535_init(void) { - printk(KERN_INFO "i2c-ali1535 version %s (%s)\n", I2C_VERSION, I2C_DATE); return pci_module_init(&ali1535_driver); } diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-ali15x3.c i2c-2.5/drivers/i2c/busses/i2c-ali15x3.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-ali15x3.c Mon Sep 8 19:50:06 2003 +++ i2c-2.5/drivers/i2c/busses/i2c-ali15x3.c Tue Sep 23 10:12:59 2003 @@ -471,7 +471,6 @@ static struct i2c_adapter ali15x3_adapter = { .owner = THIS_MODULE, - .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_ALI15X3, .class = I2C_ADAP_CLASS_SMBUS, .algo = &smbus_algorithm, .name = "unset", @@ -498,7 +497,7 @@ /* set up the driverfs linkage to our parent device */ ali15x3_adapter.dev.parent = &dev->dev; - snprintf(ali15x3_adapter.name, DEVICE_NAME_SIZE, + snprintf(ali15x3_adapter.name, I2C_NAME_SIZE, "SMBus ALI15X3 adapter at %04x", ali15x3_smba); return i2c_add_adapter(&ali15x3_adapter); } @@ -518,7 +517,6 @@ static int __init i2c_ali15x3_init(void) { - printk("i2c-ali15x3.o version %s (%s)\n", I2C_VERSION, I2C_DATE); return pci_module_init(&ali15x3_driver); } diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-amd756.c i2c-2.5/drivers/i2c/busses/i2c-amd756.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-amd756.c Mon Sep 8 19:50:22 2003 +++ i2c-2.5/drivers/i2c/busses/i2c-amd756.c Tue Sep 23 10:12:59 2003 @@ -37,7 +37,6 @@ /* #define DEBUG 1 */ -#include #include #include #include @@ -304,7 +303,6 @@ static struct i2c_adapter amd756_adapter = { .owner = THIS_MODULE, - .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_AMD756, .class = I2C_ADAP_CLASS_SMBUS, .algo = &smbus_algorithm, .name = "unset", @@ -369,7 +367,7 @@ /* set up the driverfs linkage to our parent device */ amd756_adapter.dev.parent = &pdev->dev; - snprintf(amd756_adapter.name, DEVICE_NAME_SIZE, + snprintf(amd756_adapter.name, I2C_NAME_SIZE, "SMBus AMD75x adapter at %04x", amd756_ioport); error = i2c_add_adapter(&amd756_adapter); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-amd8111.c i2c-2.5/drivers/i2c/busses/i2c-amd8111.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-amd8111.c Mon Sep 8 19:50:22 2003 +++ i2c-2.5/drivers/i2c/busses/i2c-amd8111.c Tue Sep 23 10:12:59 2003 @@ -356,9 +356,8 @@ goto out_kfree; smbus->adapter.owner = THIS_MODULE; - snprintf(smbus->adapter.name, DEVICE_NAME_SIZE, + snprintf(smbus->adapter.name, I2C_NAME_SIZE, "SMBus2 AMD8111 adapter at %04x", smbus->base); - smbus->adapter.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_AMD8111; smbus->adapter.class = I2C_ADAP_CLASS_SMBUS; smbus->adapter.algo = &smbus_algorithm; smbus->adapter.algo_data = smbus; diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-elektor.c i2c-2.5/drivers/i2c/busses/i2c-elektor.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-elektor.c Thu Jan 1 00:00:00 1970 +++ i2c-2.5/drivers/i2c/busses/i2c-elektor.c Tue Sep 23 10:12:59 2003 @@ -0,0 +1,286 @@ +/* ------------------------------------------------------------------------- */ +/* i2c-elektor.c i2c-hw access for PCF8584 style isa bus adaptes */ +/* ------------------------------------------------------------------------- */ +/* Copyright (C) 1995-97 Simon G. Vogl + 1998-99 Hans Berglund + + 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. */ +/* ------------------------------------------------------------------------- */ + +/* With some changes from Kyösti Mälkki and even + Frodo Looijaard */ + +/* Partialy rewriten by Oleg I. Vdovikin for mmapped support of + for Alpha Processor Inc. UP-2000(+) boards */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "../i2c-pcf8584.h" + +#define DEFAULT_BASE 0x330 + +static int base; +static int irq; +static int clock = 0x1c; +static int own = 0x55; +static int mmapped; +static int i2c_debug; + +/* vdovikin: removed static struct i2c_pcf_isa gpi; code - + this module in real supports only one device, due to missing arguments + in some functions, called from the algo-pcf module. Sometimes it's + need to be rewriten - but for now just remove this for simpler reading */ + +static wait_queue_head_t pcf_wait; +static int pcf_pending; + +/* ----- global defines ----------------------------------------------- */ +#define DEB(x) if (i2c_debug>=1) x +#define DEB2(x) if (i2c_debug>=2) x +#define DEB3(x) if (i2c_debug>=3) x +#define DEBE(x) x /* error messages */ + +/* ----- local functions ---------------------------------------------- */ + +static void pcf_isa_setbyte(void *data, int ctl, int val) +{ + int address = ctl ? (base + 1) : base; + + /* enable irq if any specified for serial operation */ + if (ctl && irq && (val & I2C_PCF_ESO)) { + val |= I2C_PCF_ENI; + } + + DEB3(printk(KERN_DEBUG "i2c-elektor: Write 0x%X 0x%02X\n", address, val & 255)); + + switch (mmapped) { + case 0: /* regular I/O */ + outb(val, address); + break; + case 2: /* double mapped I/O needed for UP2000 board, + I don't know why this... */ + writeb(val, address); + /* fall */ + case 1: /* memory mapped I/O */ + writeb(val, address); + break; + } +} + +static int pcf_isa_getbyte(void *data, int ctl) +{ + int address = ctl ? (base + 1) : base; + int val = mmapped ? readb(address) : inb(address); + + DEB3(printk(KERN_DEBUG "i2c-elektor: Read 0x%X 0x%02X\n", address, val)); + + return (val); +} + +static int pcf_isa_getown(void *data) +{ + return (own); +} + + +static int pcf_isa_getclock(void *data) +{ + return (clock); +} + +static void pcf_isa_waitforpin(void) { + + int timeout = 2; + + if (irq > 0) { + cli(); + if (pcf_pending == 0) { + interruptible_sleep_on_timeout(&pcf_wait, timeout*HZ ); + } else + pcf_pending = 0; + sti(); + } else { + udelay(100); + } +} + + +static irqreturn_t pcf_isa_handler(int this_irq, void *dev_id, struct pt_regs *regs) { + pcf_pending = 1; + wake_up_interruptible(&pcf_wait); + return IRQ_HANDLED; +} + + +static int pcf_isa_init(void) +{ + if (!mmapped) { + if (!request_region(base, 2, "i2c (isa bus adapter)")) { + printk(KERN_ERR + "i2c-elektor: requested I/O region (0x%X:2) " + "is in use.\n", base); + return -ENODEV; + } + } + if (irq > 0) { + if (request_irq(irq, pcf_isa_handler, 0, "PCF8584", 0) < 0) { + printk(KERN_ERR "i2c-elektor: Request irq%d failed\n", irq); + irq = 0; + } else + enable_irq(irq); + } + return 0; +} + +/* ------------------------------------------------------------------------ + * Encapsulate the above functions in the correct operations structure. + * This is only done when more than one hardware adapter is supported. + */ +static struct i2c_algo_pcf_data pcf_isa_data = { + .setpcf = pcf_isa_setbyte, + .getpcf = pcf_isa_getbyte, + .getown = pcf_isa_getown, + .getclock = pcf_isa_getclock, + .waitforpin = pcf_isa_waitforpin, + .udelay = 10, + .mdelay = 10, + .timeout = 100, +}; + +static struct i2c_adapter pcf_isa_ops = { + .owner = THIS_MODULE, + .id = I2C_HW_P_ELEK, + .algo_data = &pcf_isa_data, + .name = "PCF8584 ISA adapter", +}; + +static int __init i2c_pcfisa_init(void) +{ +#ifdef __alpha__ + /* check to see we have memory mapped PCF8584 connected to the + Cypress cy82c693 PCI-ISA bridge as on UP2000 board */ + if (base == 0) { + + struct pci_dev *cy693_dev = + pci_find_device(PCI_VENDOR_ID_CONTAQ, + PCI_DEVICE_ID_CONTAQ_82C693, NULL); + + if (cy693_dev) { + char config; + /* yeap, we've found cypress, let's check config */ + if (!pci_read_config_byte(cy693_dev, 0x47, &config)) { + + DEB3(printk(KERN_DEBUG "i2c-elektor: found cy82c693, config register 0x47 = 0x%02x.\n", config)); + + /* UP2000 board has this register set to 0xe1, + but the most significant bit as seems can be + reset during the proper initialisation + sequence if guys from API decides to do that + (so, we can even enable Tsunami Pchip + window for the upper 1 Gb) */ + + /* so just check for ROMCS at 0xe0000, + ROMCS enabled for writes + and external XD Bus buffer in use. */ + if ((config & 0x7f) == 0x61) { + /* seems to be UP2000 like board */ + base = 0xe0000; + /* I don't know why we need to + write twice */ + mmapped = 2; + /* UP2000 drives ISA with + 8.25 MHz (PCI/4) clock + (this can be read from cypress) */ + clock = I2C_PCF_CLK | I2C_PCF_TRNS90; + printk(KERN_INFO "i2c-elektor: found API UP2000 like board, will probe PCF8584 later.\n"); + } + } + } + } +#endif + + /* sanity checks for mmapped I/O */ + if (mmapped && base < 0xc8000) { + printk(KERN_ERR "i2c-elektor: incorrect base address (0x%0X) specified for mmapped I/O.\n", base); + return -ENODEV; + } + + printk(KERN_INFO "i2c-elektor: i2c pcf8584-isa adapter driver\n"); + + if (base == 0) { + base = DEFAULT_BASE; + } + + init_waitqueue_head(&pcf_wait); + if (pcf_isa_init()) + return -ENODEV; + if (i2c_pcf_add_bus(&pcf_isa_ops) < 0) + goto fail; + + printk(KERN_ERR "i2c-elektor: found device at %#x.\n", base); + + return 0; + + fail: + if (irq > 0) { + disable_irq(irq); + free_irq(irq, 0); + } + + if (!mmapped) + release_region(base , 2); + return -ENODEV; +} + +static void i2c_pcfisa_exit(void) +{ + i2c_pcf_del_bus(&pcf_isa_ops); + + if (irq > 0) { + disable_irq(irq); + free_irq(irq, 0); + } + + if (!mmapped) + release_region(base , 2); +} + +MODULE_AUTHOR("Hans Berglund "); +MODULE_DESCRIPTION("I2C-Bus adapter routines for PCF8584 ISA bus adapter"); +MODULE_LICENSE("GPL"); + +MODULE_PARM(base, "i"); +MODULE_PARM(irq, "i"); +MODULE_PARM(clock, "i"); +MODULE_PARM(own, "i"); +MODULE_PARM(mmapped, "i"); +MODULE_PARM(i2c_debug, "i"); + +module_init(i2c_pcfisa_init); +module_exit(i2c_pcfisa_exit); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-elv.c i2c-2.5/drivers/i2c/busses/i2c-elv.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-elv.c Thu Jan 1 00:00:00 1970 +++ i2c-2.5/drivers/i2c/busses/i2c-elv.c Tue Sep 23 10:12:59 2003 @@ -0,0 +1,173 @@ +/* ------------------------------------------------------------------------- */ +/* i2c-elv.c i2c-hw access for philips style parallel port adapters */ +/* ------------------------------------------------------------------------- */ +/* Copyright (C) 1995-2000 Simon G. 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. */ +/* ------------------------------------------------------------------------- */ + +/* With some changes from Kyösti Mälkki and even + Frodo Looijaard */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEFAULT_BASE 0x378 +static int base=0; +static unsigned char port_data = 0; + +/* ----- global defines ----------------------------------------------- */ +#define DEB(x) /* should be reasonable open, close &c. */ +#define DEB2(x) /* low level debugging - very slow */ +#define DEBE(x) x /* error messages */ +#define DEBINIT(x) x /* detection status messages */ + +/* --- Convenience defines for the parallel port: */ +#define BASE (unsigned int)(data) +#define DATA BASE /* Centronics data port */ +#define STAT (BASE+1) /* Centronics status port */ +#define CTRL (BASE+2) /* Centronics control port */ + + +/* ----- local functions ---------------------------------------------- */ + + +static void bit_elv_setscl(void *data, int state) +{ + if (state) { + port_data &= 0xfe; + } else { + port_data |=1; + } + outb(port_data, DATA); +} + +static void bit_elv_setsda(void *data, int state) +{ + if (state) { + port_data &=0xfd; + } else { + port_data |=2; + } + outb(port_data, DATA); +} + +static int bit_elv_getscl(void *data) +{ + return ( 0 == ( (inb_p(STAT)) & 0x08 ) ); +} + +static int bit_elv_getsda(void *data) +{ + return ( 0 == ( (inb_p(STAT)) & 0x40 ) ); +} + +static int bit_elv_init(void) +{ + if (!request_region(base, (base == 0x3bc) ? 3 : 8, + "i2c (ELV adapter)")) + return -ENODEV; + + if (inb(base+1) & 0x80) { /* BUSY should be high */ + DEBINIT(printk(KERN_DEBUG "i2c-elv.o: Busy was low.\n")); + goto fail; + } + + outb(0x0c,base+2); /* SLCT auf low */ + udelay(400); + if (!(inb(base+1) && 0x10)) { + outb(0x04,base+2); + DEBINIT(printk(KERN_DEBUG "i2c-elv.o: Select was high.\n")); + goto fail; + } + + port_data = 0; + bit_elv_setsda((void*)base,1); + bit_elv_setscl((void*)base,1); + return 0; + +fail: + release_region(base , (base == 0x3bc) ? 3 : 8); + return -ENODEV; +} + +/* ------------------------------------------------------------------------ + * Encapsulate the above functions in the correct operations structure. + * This is only done when more than one hardware adapter is supported. + */ +static struct i2c_algo_bit_data bit_elv_data = { + .setsda = bit_elv_setsda, + .setscl = bit_elv_setscl, + .getsda = bit_elv_getsda, + .getscl = bit_elv_getscl, + .udelay = 80, + .mdelay = 80, + .timeout = HZ +}; + +static struct i2c_adapter bit_elv_ops = { + .owner = THIS_MODULE, + .algo_data = &bit_elv_data, + .name = "ELV Parallel port adaptor", +}; + +static int __init i2c_bitelv_init(void) +{ + printk(KERN_INFO "i2c ELV parallel port adapter driver\n"); + if (base==0) { + /* probe some values */ + base=DEFAULT_BASE; + bit_elv_data.data=(void*)DEFAULT_BASE; + if (bit_elv_init()==0) { + if(i2c_bit_add_bus(&bit_elv_ops) < 0) + return -ENODEV; + } else { + return -ENODEV; + } + } else { + i2c_set_adapdata(&bit_elv_ops, (void *)base); + if (bit_elv_init()==0) { + if(i2c_bit_add_bus(&bit_elv_ops) < 0) + return -ENODEV; + } else { + return -ENODEV; + } + } + printk(KERN_DEBUG "i2c-elv.o: found device at %#x.\n",base); + return 0; +} + +static void __exit i2c_bitelv_exit(void) +{ + i2c_bit_del_bus(&bit_elv_ops); + release_region(base , (base == 0x3bc) ? 3 : 8); +} + +MODULE_AUTHOR("Simon G. Vogl "); +MODULE_DESCRIPTION("I2C-Bus adapter routines for ELV parallel port adapter"); +MODULE_LICENSE("GPL"); + +MODULE_PARM(base, "i"); + +module_init(i2c_bitelv_init); +module_exit(i2c_bitelv_exit); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-frodo.c i2c-2.5/drivers/i2c/busses/i2c-frodo.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-frodo.c Thu Jan 1 00:00:00 1970 +++ i2c-2.5/drivers/i2c/busses/i2c-frodo.c Tue Sep 23 10:12:59 2003 @@ -0,0 +1,85 @@ + +/* + * linux/drivers/i2c/i2c-frodo.c + * + * Author: Abraham van der Merwe + * + * An I2C adapter driver for the 2d3D, Inc. StrongARM SA-1110 + * Development board (Frodo). + * + * This source code is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + + +static void frodo_setsda (void *data,int state) +{ + if (state) + FRODO_CPLD_I2C |= FRODO_I2C_SDA_OUT; + else + FRODO_CPLD_I2C &= ~FRODO_I2C_SDA_OUT; +} + +static void frodo_setscl (void *data,int state) +{ + if (state) + FRODO_CPLD_I2C |= FRODO_I2C_SCL_OUT; + else + FRODO_CPLD_I2C &= ~FRODO_I2C_SCL_OUT; +} + +static int frodo_getsda (void *data) +{ + return ((FRODO_CPLD_I2C & FRODO_I2C_SDA_IN) != 0); +} + +static int frodo_getscl (void *data) +{ + return ((FRODO_CPLD_I2C & FRODO_I2C_SCL_IN) != 0); +} + +static struct i2c_algo_bit_data bit_frodo_data = { + .setsda = frodo_setsda, + .setscl = frodo_setscl, + .getsda = frodo_getsda, + .getscl = frodo_getscl, + .udelay = 80, + .mdelay = 80, + .timeout = HZ +}; + +static struct i2c_adapter frodo_ops = { + .owner = THIS_MODULE, + .id = I2C_HW_B_FRODO, + .algo_data = &bit_frodo_data, + .dev = { + .name = "Frodo adapter driver", + }, +}; + +static int __init i2c_frodo_init (void) +{ + return i2c_bit_add_bus(&frodo_ops); +} + +static void __exit i2c_frodo_exit (void) +{ + i2c_bit_del_bus(&frodo_ops); +} + +MODULE_AUTHOR ("Abraham van der Merwe "); +MODULE_DESCRIPTION ("I2C-Bus adapter routines for Frodo"); +MODULE_LICENSE ("GPL"); + +module_init (i2c_frodo_init); +module_exit (i2c_frodo_exit); + diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-i801.c i2c-2.5/drivers/i2c/busses/i2c-i801.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-i801.c Mon Sep 8 19:50:06 2003 +++ i2c-2.5/drivers/i2c/busses/i2c-i801.c Tue Sep 23 10:12:59 2003 @@ -540,7 +540,6 @@ static struct i2c_adapter i801_adapter = { .owner = THIS_MODULE, - .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_I801, .class = I2C_ADAP_CLASS_SMBUS, .algo = &smbus_algorithm, .name = "unset", @@ -598,7 +597,7 @@ /* set up the driverfs linkage to our parent device */ i801_adapter.dev.parent = &dev->dev; - snprintf(i801_adapter.name, DEVICE_NAME_SIZE, + snprintf(i801_adapter.name, I2C_NAME_SIZE, "SMBus I801 adapter at %04x", i801_smba); return i2c_add_adapter(&i801_adapter); } @@ -617,7 +616,6 @@ static int __init i2c_i801_init(void) { - printk(KERN_INFO "i2c-i801 version %s (%s)\n", I2C_VERSION, I2C_DATE); return pci_module_init(&i801_driver); } diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-i810.c i2c-2.5/drivers/i2c/busses/i2c-i810.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-i810.c Thu Jan 1 00:00:00 1970 +++ i2c-2.5/drivers/i2c/busses/i2c-i810.c Tue Sep 23 10:12:59 2003 @@ -0,0 +1,256 @@ +/* + 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 +*/ + +#include +#include +#include +#include +#include +#include + +/* 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 *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)); +} + +static int 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 = 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); + return 0; + } + return -ENODEV; +} + +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 = { + .owner = THIS_MODULE, + .name = "I810/I815 I2C Adapter", + .algo_data = &i810_i2c_bit_data, +}; + +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 = { + .owner = THIS_MODULE, + .name = "I810/I815 DDC Adapter", + .algo_data = &i810_ddc_bit_data, +}; + +static struct pci_device_id i810_ids[] __devinitdata = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG1) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810E_IG) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_CGC) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845G_IG) }, + { 0, }, +}; + +static int __devinit i810_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + int retval; + + retval = config_i810(dev); + if (retval) + return retval; + dev_info(&dev->dev, "i810/i815 i2c device found.\n"); + + /* set up the sysfs linkage to our parent device */ + i810_i2c_adapter.dev.parent = &dev->dev; + i810_ddc_adapter.dev.parent = &dev->dev; + + 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); + iounmap(ioaddr); +} + +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) +{ + return pci_module_init(&i810_driver); +} + +static void __exit i2c_i810_exit(void) +{ + pci_unregister_driver(&i810_driver); +} + +MODULE_AUTHOR("Frodo Looijaard , " + "Philip Edelbrock , " + "Ralph Metzler , " + "and Mark D. Studebaker "); +MODULE_DESCRIPTION("I810/I815 I2C/DDC driver"); +MODULE_LICENSE("GPL"); + +module_init(i2c_i810_init); +module_exit(i2c_i810_exit); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-ibm_iic.c i2c-2.5/drivers/i2c/busses/i2c-ibm_iic.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-ibm_iic.c Thu Jan 1 00:00:00 1970 +++ i2c-2.5/drivers/i2c/busses/i2c-ibm_iic.c Tue Sep 23 10:12:59 2003 @@ -0,0 +1,729 @@ +/* + * drivers/i2c/i2c-ibm_iic.c + * + * Support for the IIC peripheral on IBM PPC 4xx + * + * Copyright (c) 2003 Zultys Technologies. + * Eugene Surovegin or + * + * Based on original work by + * Ian DaSilva + * Armin Kuster + * Matt Porter + * + * Copyright 2000-2003 MontaVista Software Inc. + * + * Original driver version was highly leveraged from i2c-elektor.c + * + * Copyright 1995-97 Simon G. Vogl + * 1998-99 Hans Berglund + * + * With some changes from Kyösti Mälkki + * and even 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. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "i2c-ibm_iic.h" + +#define DRIVER_VERSION "2.0" + +MODULE_DESCRIPTION("IBM IIC driver v" DRIVER_VERSION); +MODULE_LICENSE("GPL"); + +static int iic_scan = 0; +MODULE_PARM(iic_scan, "i"); +MODULE_PARM_DESC(iic_scan, "Scan for active chips on the bus"); + +static int iic_force_poll = 0; +MODULE_PARM(iic_force_poll, "i"); +MODULE_PARM_DESC(iic_force_poll, "Force polling mode"); + +static int iic_force_fast = 0; +MODULE_PARM(iic_force_fast, "i"); +MODULE_PARM_DESC(iic_fast_poll, "Force fast mode (400 kHz)"); + +#define DBG_LEVEL 0 + +#ifdef DBG +#undef DBG +#endif + +#ifdef DBG2 +#undef DBG2 +#endif + +#if DBG_LEVEL > 0 +# define DBG(x...) printk(KERN_DEBUG "ibm-iic" ##x) +#else +# define DBG(x...) ((void)0) +#endif +#if DBG_LEVEL > 1 +# define DBG2(x...) DBG( ##x ) +#else +# define DBG2(x...) ((void)0) +#endif +#if DBG_LEVEL > 2 +static void dump_iic_regs(const char* header, struct ibm_iic_private* dev) +{ + volatile struct iic_regs *iic = dev->vaddr; + printk(KERN_DEBUG "ibm-iic%d: %s\n", dev->idx, header); + printk(KERN_DEBUG " cntl = 0x%02x, mdcntl = 0x%02x\n" + KERN_DEBUG " sts = 0x%02x, extsts = 0x%02x\n" + KERN_DEBUG " clkdiv = 0x%02x, xfrcnt = 0x%02x\n" + KERN_DEBUG " xtcntlss = 0x%02x, directcntl = 0x%02x\n", + in_8(&iic->cntl), in_8(&iic->mdcntl), in_8(&iic->sts), + in_8(&iic->extsts), in_8(&iic->clkdiv), in_8(&iic->xfrcnt), + in_8(&iic->xtcntlss), in_8(&iic->directcntl)); +} +# define DUMP_REGS(h,dev) dump_iic_regs((h),(dev)) +#else +# define DUMP_REGS(h,dev) ((void)0) +#endif + +/* Enable/disable interrupt generation */ +static inline void iic_interrupt_mode(struct ibm_iic_private* dev, int enable) +{ + out_8(&dev->vaddr->intmsk, enable ? INTRMSK_EIMTC : 0); +} + +/* + * Initialize IIC interface. + */ +static void iic_dev_init(struct ibm_iic_private* dev) +{ + volatile struct iic_regs *iic = dev->vaddr; + + DBG("%d: init\n", dev->idx); + + /* Clear master address */ + out_8(&iic->lmadr, 0); + out_8(&iic->hmadr, 0); + + /* Clear slave address */ + out_8(&iic->lsadr, 0); + out_8(&iic->hsadr, 0); + + /* Clear status & extended status */ + out_8(&iic->sts, STS_SCMP | STS_IRQA); + out_8(&iic->extsts, EXTSTS_IRQP | EXTSTS_IRQD | EXTSTS_LA + | EXTSTS_ICT | EXTSTS_XFRA); + + /* Set clock divider */ + out_8(&iic->clkdiv, dev->clckdiv); + + /* Clear transfer count */ + out_8(&iic->xfrcnt, 0); + + /* Clear extended control and status */ + out_8(&iic->xtcntlss, XTCNTLSS_SRC | XTCNTLSS_SRS | XTCNTLSS_SWC + | XTCNTLSS_SWS); + + /* Clear control register */ + out_8(&iic->cntl, 0); + + /* Enable interrupts if possible */ + iic_interrupt_mode(dev, dev->irq >= 0); + + /* Set mode control */ + out_8(&iic->mdcntl, MDCNTL_FMDB | MDCNTL_EINT | MDCNTL_EUBS + | (dev->fast_mode ? MDCNTL_FSM : 0)); + + DUMP_REGS("iic_init", dev); +} + +/* + * Reset IIC interface + */ +static void iic_dev_reset(struct ibm_iic_private* dev) +{ + volatile struct iic_regs *iic = dev->vaddr; + int i; + u8 dc; + + DBG("%d: soft reset\n", dev->idx); + DUMP_REGS("reset", dev); + + /* Place chip in the reset state */ + out_8(&iic->xtcntlss, XTCNTLSS_SRST); + + /* Check if bus is free */ + dc = in_8(&iic->directcntl); + if (!DIRCTNL_FREE(dc)){ + DBG("%d: trying to regain bus control\n", dev->idx); + + /* Try to set bus free state */ + out_8(&iic->directcntl, DIRCNTL_SDAC | DIRCNTL_SCC); + + /* Wait until we regain bus control */ + for (i = 0; i < 100; ++i){ + dc = in_8(&iic->directcntl); + if (DIRCTNL_FREE(dc)) + break; + + /* Toggle SCL line */ + dc ^= DIRCNTL_SCC; + out_8(&iic->directcntl, dc); + udelay(10); + dc ^= DIRCNTL_SCC; + out_8(&iic->directcntl, dc); + + /* be nice */ + cond_resched(); + } + } + + /* Remove reset */ + out_8(&iic->xtcntlss, 0); + + /* Reinitialize interface */ + iic_dev_init(dev); +} + +/* + * IIC interrupt handler + */ +static irqreturn_t iic_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + struct ibm_iic_private* dev = (struct ibm_iic_private*)dev_id; + volatile struct iic_regs* iic = dev->vaddr; + + DBG2("%d: irq handler, STS = 0x%02x, EXTSTS = 0x%02x\n", + dev->idx, in_8(&iic->sts), in_8(&iic->extsts)); + + /* Acknowledge IRQ and wakeup iic_wait_for_tc */ + out_8(&iic->sts, STS_IRQA | STS_SCMP); + wake_up_interruptible(&dev->wq); + + return IRQ_HANDLED; +} + +/* + * Get master transfer result and clear errors if any. + * Returns the number of actually transferred bytes or error (<0) + */ +static int iic_xfer_result(struct ibm_iic_private* dev) +{ + volatile struct iic_regs *iic = dev->vaddr; + + if (unlikely(in_8(&iic->sts) & STS_ERR)){ + DBG("%d: xfer error, EXTSTS = 0x%02x\n", dev->idx, + in_8(&iic->extsts)); + + /* Clear errors and possible pending IRQs */ + out_8(&iic->extsts, EXTSTS_IRQP | EXTSTS_IRQD | + EXTSTS_LA | EXTSTS_ICT | EXTSTS_XFRA); + + /* Flush master data buffer */ + out_8(&iic->mdcntl, in_8(&iic->mdcntl) | MDCNTL_FMDB); + + /* Is bus free? + * If error happened during combined xfer + * IIC interface is usually stuck in some strange + * state, the only way out - soft reset. + */ + if ((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE){ + DBG("%d: bus is stuck, resetting\n", dev->idx); + iic_dev_reset(dev); + } + return -EREMOTEIO; + } + else + return in_8(&iic->xfrcnt) & XFRCNT_MTC_MASK; +} + +/* + * Try to abort active transfer. + */ +static void iic_abort_xfer(struct ibm_iic_private* dev) +{ + volatile struct iic_regs *iic = dev->vaddr; + unsigned long x; + + DBG("%d: iic_abort_xfer\n", dev->idx); + + out_8(&iic->cntl, CNTL_HMT); + + /* + * Wait for the abort command to complete. + * It's not worth to be optimized, just poll (timeout >= 1 tick) + */ + x = jiffies + 2; + while ((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE){ + if (time_after(jiffies, x)){ + DBG("%d: abort timeout, resetting...\n", dev->idx); + iic_dev_reset(dev); + return; + } + schedule(); + } + + /* Just to clear errors */ + iic_xfer_result(dev); +} + +/* + * Wait for master transfer to complete. + * It puts current process to sleep until we get interrupt or timeout expires. + * Returns the number of transferred bytes or error (<0) + */ +static int iic_wait_for_tc(struct ibm_iic_private* dev){ + + volatile struct iic_regs *iic = dev->vaddr; + int ret = 0; + + if (dev->irq >= 0){ + /* Interrupt mode */ + wait_queue_t wait; + init_waitqueue_entry(&wait, current); + + add_wait_queue(&dev->wq, &wait); + set_current_state(TASK_INTERRUPTIBLE); + if (in_8(&iic->sts) & STS_PT) + schedule_timeout(dev->adap.timeout * HZ); + set_current_state(TASK_RUNNING); + remove_wait_queue(&dev->wq, &wait); + + if (unlikely(signal_pending(current))){ + DBG("%d: wait interrupted\n", dev->idx); + ret = -ERESTARTSYS; + } else if (unlikely(in_8(&iic->sts) & STS_PT)){ + DBG("%d: wait timeout\n", dev->idx); + ret = -ETIMEDOUT; + } + } + else { + /* Polling mode */ + unsigned long x = jiffies + dev->adap.timeout * HZ; + + while (in_8(&iic->sts) & STS_PT){ + if (unlikely(time_after(jiffies, x))){ + DBG("%d: poll timeout\n", dev->idx); + ret = -ETIMEDOUT; + break; + } + + if (unlikely(signal_pending(current))){ + DBG("%d: poll interrupted\n", dev->idx); + ret = -ERESTARTSYS; + break; + } + schedule(); + } + } + + if (unlikely(ret < 0)) + iic_abort_xfer(dev); + else + ret = iic_xfer_result(dev); + + DBG2("%d: iic_wait_for_tc -> %d\n", dev->idx, ret); + + return ret; +} + +/* + * Low level master transfer routine + */ +static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm, + int combined_xfer) +{ + volatile struct iic_regs *iic = dev->vaddr; + char* buf = pm->buf; + int i, j, loops, ret = 0; + int len = pm->len; + + u8 cntl = (in_8(&iic->cntl) & CNTL_AMD) | CNTL_PT; + if (pm->flags & I2C_M_RD) + cntl |= CNTL_RW; + + loops = (len + 3) / 4; + for (i = 0; i < loops; ++i, len -= 4){ + int count = len > 4 ? 4 : len; + u8 cmd = cntl | ((count - 1) << CNTL_TCT_SHIFT); + + if (!(cntl & CNTL_RW)) + for (j = 0; j < count; ++j) + out_8((volatile u8*)&iic->mdbuf, *buf++); + + if (i < loops - 1) + cmd |= CNTL_CHT; + else if (combined_xfer) + cmd |= CNTL_RPST; + + DBG2("%d: xfer_bytes, %d, CNTL = 0x%02x\n", dev->idx, count, cmd); + + /* Start transfer */ + out_8(&iic->cntl, cmd); + + /* Wait for completion */ + ret = iic_wait_for_tc(dev); + + if (unlikely(ret < 0)) + break; + else if (unlikely(ret != count)){ + DBG("%d: xfer_bytes, requested %d, transfered %d\n", + dev->idx, count, ret); + + /* If it's not a last part of xfer, abort it */ + if (combined_xfer || (i < loops - 1)) + iic_abort_xfer(dev); + + ret = -EREMOTEIO; + break; + } + + if (cntl & CNTL_RW) + for (j = 0; j < count; ++j) + *buf++ = in_8((volatile u8*)&iic->mdbuf); + } + + return ret > 0 ? 0 : ret; +} + +/* + * Set target slave address for master transfer + */ +static inline void iic_address(struct ibm_iic_private* dev, struct i2c_msg* msg) +{ + volatile struct iic_regs *iic = dev->vaddr; + u16 addr = msg->addr; + + DBG2("%d: iic_address, 0x%03x (%d-bit)\n", dev->idx, + addr, msg->flags & I2C_M_TEN ? 10 : 7); + + if (msg->flags & I2C_M_TEN){ + out_8(&iic->cntl, CNTL_AMD); + out_8(&iic->lmadr, addr); + out_8(&iic->hmadr, 0xf0 | ((addr >> 7) & 0x06)); + } + else { + out_8(&iic->cntl, 0); + out_8(&iic->lmadr, addr << 1); + } +} + +static inline int iic_invalid_address(const struct i2c_msg* p) +{ + return (p->addr > 0x3ff) || (!(p->flags & I2C_M_TEN) && (p->addr > 0x7f)); +} + +static inline int iic_address_neq(const struct i2c_msg* p1, + const struct i2c_msg* p2) +{ + return (p1->addr != p2->addr) + || ((p1->flags & I2C_M_TEN) != (p2->flags & I2C_M_TEN)); +} + +/* + * Generic master transfer entrypoint. + * Returns the number of processed messages or error (<0) + */ +static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) +{ + struct ibm_iic_private* dev = (struct ibm_iic_private*)(i2c_get_adapdata(adap)); + volatile struct iic_regs *iic = dev->vaddr; + int i, ret = 0; + + DBG2("%d: iic_xfer, %d msg(s)\n", dev->idx, num); + + if (!num) + return 0; + + /* Check the sanity of the passed messages. + * Uhh, generic i2c layer is more suitable place for such code... + */ + if (unlikely(iic_invalid_address(&msgs[0]))){ + DBG("%d: invalid address 0x%03x (%d-bit)\n", dev->idx, + msgs[0].addr, msgs[0].flags & I2C_M_TEN ? 10 : 7); + return -EINVAL; + } + for (i = 0; i < num; ++i){ + if (unlikely(msgs[i].len <= 0)){ + DBG("%d: invalid len %d in msg[%d]\n", dev->idx, + msgs[i].len, i); + return -EINVAL; + } + if (unlikely(iic_address_neq(&msgs[0], &msgs[i]))){ + DBG("%d: invalid addr in msg[%d]\n", dev->idx, i); + return -EINVAL; + } + } + + /* Check bus state */ + if (unlikely((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE)){ + DBG("%d: iic_xfer, bus is not free\n", dev->idx); + + /* Usually it means something serious has happend. + * We *cannot* have unfinished previous transfer + * so it doesn't make any sense to try to stop it. + * Probably we were not able to recover from the + * previous error. + * The only *reasonable* thing I can think of here + * is soft reset. --ebs + */ + iic_dev_reset(dev); + + if ((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE){ + DBG("%d: iic_xfer, bus is still not free\n", dev->idx); + return -EREMOTEIO; + } + } + else { + /* Flush master data buffer (just in case) */ + out_8(&iic->mdcntl, in_8(&iic->mdcntl) | MDCNTL_FMDB); + } + + /* Load slave address */ + iic_address(dev, &msgs[0]); + + /* Do real transfer */ + for (i = 0; i < num && !ret; ++i) + ret = iic_xfer_bytes(dev, &msgs[i], i < num - 1); + + return ret < 0 ? ret : num; +} + +static u32 iic_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR; +} + +static struct i2c_algorithm iic_algo = { + .name = "IBM IIC algorithm", + .id = I2C_ALGO_OCP, + .master_xfer = iic_xfer, + .smbus_xfer = NULL, + .slave_send = NULL, + .slave_recv = NULL, + .algo_control = NULL, + .functionality = iic_func +}; + +/* + * Scan bus for valid 7-bit addresses (ie things that ACK on 1 byte read) + * We only scan range [0x08 - 0x77], all other addresses are reserved anyway + */ +static void __devinit iic_scan_bus(struct ibm_iic_private* dev) +{ + int found = 0; + char dummy; + struct i2c_msg msg = { + .buf = &dummy, + .len = sizeof(dummy), + .flags = I2C_M_RD + }; + + printk(KERN_INFO "ibm-iic%d: scanning bus...\n" KERN_INFO, dev->idx); + + for (msg.addr = 8; msg.addr < 0x78; ++msg.addr) + if (iic_xfer(&dev->adap, &msg, 1) == 1){ + ++found; + printk(" 0x%02x", msg.addr); + } + + printk("%sibm-iic%d: %d device(s) detected\n", + found ? "\n" KERN_INFO : "", dev->idx, found); +} + +/* + * Calculates IICx_CLCKDIV value for a specific OPB clock frequency + */ +static inline u8 iic_clckdiv(unsigned int opb) +{ + /* Compatibility kludge, should go away after all cards + * are fixed to fill correct value for opbfreq. + * Previous driver version used hardcoded divider value 4, + * it corresponds to OPB frequency from the range (40, 50] MHz + */ + if (!opb){ + printk(KERN_WARNING "ibm-iic: using compatibility value for OPB freq," + " fix your board specific setup\n"); + opb = 50000000; + } + + /* Convert to MHz */ + opb /= 1000000; + + if (opb < 20 || opb > 150){ + printk(KERN_CRIT "ibm-iic: invalid OPB clock frequency %u MHz\n", + opb); + opb = opb < 20 ? 20 : 150; + } + return (u8)((opb + 9) / 10 - 1); +} + +/* + * Register single IIC interface + */ +static int __devinit iic_probe(struct ocp_device *ocp){ + + struct ibm_iic_private* dev; + struct i2c_adapter* adap; + int ret; + bd_t* bd = (bd_t*)&__res; + + if (!(dev = kmalloc(sizeof(*dev), GFP_KERNEL))){ + printk(KERN_CRIT "ibm-iic: failed to allocate device data\n"); + return -ENOMEM; + } + + memset(dev, 0, sizeof(*dev)); + dev->idx = ocp->num; + ocp_set_drvdata(ocp, dev); + + if (!(dev->vaddr = ioremap(ocp->paddr, sizeof(struct iic_regs)))){ + printk(KERN_CRIT "ibm-iic%d: failed to ioremap device registers\n", + dev->idx); + ret = -ENXIO; + goto fail2; + } + + init_waitqueue_head(&dev->wq); + + dev->irq = iic_force_poll ? -1 : ocp->irq; + if (dev->irq >= 0){ + /* Disable interrupts until we finish intialization, + assumes level-sensitive IRQ setup... + */ + iic_interrupt_mode(dev, 0); + if (request_irq(dev->irq, iic_handler, 0, "IBM IIC", dev)){ + printk(KERN_ERR "ibm-iic%d: request_irq %d failed\n", + dev->idx, dev->irq); + /* Fallback to the polling mode */ + dev->irq = -1; + } + } + + if (dev->irq < 0) + printk(KERN_WARNING "ibm-iic%d: using polling mode\n", + dev->idx); + + /* Board specific settings */ + BUG_ON(dev->idx >= sizeof(bd->bi_iic_fast) / sizeof(bd->bi_iic_fast[0])); + dev->fast_mode = iic_force_fast ? 1 : bd->bi_iic_fast[dev->idx]; + + /* clckdiv is the same for *all* IIC interfaces, + * but I'd rather make a copy than introduce another global. --ebs + */ + dev->clckdiv = iic_clckdiv(bd->bi_opb_busfreq); + DBG("%d: clckdiv = %d\n", dev->idx, dev->clckdiv); + + /* Initialize IIC interface */ + iic_dev_init(dev); + + /* Register it with i2c layer */ + adap = &dev->adap; + strcpy(adap->dev.name, "IBM IIC"); + i2c_set_adapdata(adap, dev); + adap->id = I2C_HW_OCP | iic_algo.id; + adap->algo = &iic_algo; + adap->client_register = NULL; + adap->client_unregister = NULL; + adap->timeout = 1; + adap->retries = 1; + + if ((ret = i2c_add_adapter(adap)) != 0){ + printk(KERN_CRIT "ibm-iic%d: failed to register i2c adapter\n", + dev->idx); + goto fail; + } + + printk(KERN_INFO "ibm-iic%d: using %s mode\n", dev->idx, + dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)"); + + /* Scan bus if requested by user */ + if (iic_scan) + iic_scan_bus(dev); + + return 0; + +fail: + if (dev->irq >= 0){ + iic_interrupt_mode(dev, 0); + free_irq(dev->irq, dev); + } + + iounmap((void*)dev->vaddr); +fail2: + ocp_set_drvdata(ocp, 0); + kfree(dev); + return ret; +} + +/* + * Cleanup initialized IIC interface + */ +static void __devexit iic_remove(struct ocp_device *ocp) +{ + struct ibm_iic_private* dev = (struct ibm_iic_private*)ocp_get_drvdata(ocp); + BUG_ON(dev == NULL); + if (i2c_del_adapter(&dev->adap)){ + printk(KERN_CRIT "ibm-iic%d: failed to delete i2c adapter :(\n", + dev->idx); + /* That's *very* bad, just shutdown IRQ ... */ + if (dev->irq >= 0){ + iic_interrupt_mode(dev, 0); + free_irq(dev->irq, dev); + dev->irq = -1; + } + } else { + if (dev->irq >= 0){ + iic_interrupt_mode(dev, 0); + free_irq(dev->irq, dev); + } + iounmap((void*)dev->vaddr); + kfree(dev); + } +} + +static struct ocp_device_id ibm_iic_ids[] __devinitdata = +{ + { .vendor = OCP_VENDOR_IBM, .device = OCP_FUNC_IIC }, + { .vendor = OCP_VENDOR_INVALID } +}; + +MODULE_DEVICE_TABLE(ocp, ibm_iic_ids); + +static struct ocp_driver ibm_iic_driver = +{ + .name = "ocp_iic", + .id_table = ibm_iic_ids, + .probe = iic_probe, + .remove = __devexit_p(iic_remove), +#if defined(CONFIG_PM) + .suspend = NULL, + .resume = NULL, +#endif +}; + +static int __init iic_init(void) +{ + printk(KERN_INFO "IBM IIC driver v" DRIVER_VERSION "\n"); + return ocp_module_init(&ibm_iic_driver); +} + +static void __exit iic_exit(void) +{ + ocp_unregister_driver(&ibm_iic_driver); +} + +module_init(iic_init); +module_exit(iic_exit); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-ibm_iic.h i2c-2.5/drivers/i2c/busses/i2c-ibm_iic.h --- linux-2.6.0-test5/drivers/i2c/busses/i2c-ibm_iic.h Thu Jan 1 00:00:00 1970 +++ i2c-2.5/drivers/i2c/busses/i2c-ibm_iic.h Tue Sep 23 10:12:59 2003 @@ -0,0 +1,124 @@ +/* + * drivers/i2c/i2c-ibm_iic.h + * + * Support for the IIC peripheral on IBM PPC 4xx + * + * Copyright (c) 2003 Zultys Technologies. + * Eugene Surovegin or + * + * Based on original work by + * Ian DaSilva + * Armin Kuster + * Matt Porter + * + * Copyright 2000-2003 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. + * + */ +#ifndef __I2C_IBM_IIC_H_ +#define __I2C_IBM_IIC_H_ + +#include +#include + +struct iic_regs { + u16 mdbuf; + u16 sbbuf; + u8 lmadr; + u8 hmadr; + u8 cntl; + u8 mdcntl; + u8 sts; + u8 extsts; + u8 lsadr; + u8 hsadr; + u8 clkdiv; + u8 intmsk; + u8 xfrcnt; + u8 xtcntlss; + u8 directcntl; +}; + +struct ibm_iic_private { + struct i2c_adapter adap; + volatile struct iic_regs *vaddr; + wait_queue_head_t wq; + int idx; + int irq; + int fast_mode; + u8 clckdiv; +}; + +/* IICx_CNTL register */ +#define CNTL_HMT 0x80 +#define CNTL_AMD 0x40 +#define CNTL_TCT_MASK 0x30 +#define CNTL_TCT_SHIFT 4 +#define CNTL_RPST 0x08 +#define CNTL_CHT 0x04 +#define CNTL_RW 0x02 +#define CNTL_PT 0x01 + +/* IICx_MDCNTL register */ +#define MDCNTL_FSDB 0x80 +#define MDCNTL_FMDB 0x40 +#define MDCNTL_EGC 0x20 +#define MDCNTL_FSM 0x10 +#define MDCNTL_ESM 0x08 +#define MDCNTL_EINT 0x04 +#define MDCNTL_EUBS 0x02 +#define MDCNTL_HSCL 0x01 + +/* IICx_STS register */ +#define STS_SSS 0x80 +#define STS_SLPR 0x40 +#define STS_MDBS 0x20 +#define STS_MDBF 0x10 +#define STS_SCMP 0x08 +#define STS_ERR 0x04 +#define STS_IRQA 0x02 +#define STS_PT 0x01 + +/* IICx_EXTSTS register */ +#define EXTSTS_IRQP 0x80 +#define EXTSTS_BCS_MASK 0x70 +#define EXTSTS_BCS_FREE 0x40 +#define EXTSTS_IRQD 0x08 +#define EXTSTS_LA 0x04 +#define EXTSTS_ICT 0x02 +#define EXTSTS_XFRA 0x01 + +/* IICx_INTRMSK register */ +#define INTRMSK_EIRC 0x80 +#define INTRMSK_EIRS 0x40 +#define INTRMSK_EIWC 0x20 +#define INTRMSK_EIWS 0x10 +#define INTRMSK_EIHE 0x08 +#define INTRMSK_EIIC 0x04 +#define INTRMSK_EITA 0x02 +#define INTRMSK_EIMTC 0x01 + +/* IICx_XFRCNT register */ +#define XFRCNT_MTC_MASK 0x07 + +/* IICx_XTCNTLSS register */ +#define XTCNTLSS_SRC 0x80 +#define XTCNTLSS_SRS 0x40 +#define XTCNTLSS_SWC 0x20 +#define XTCNTLSS_SWS 0x10 +#define XTCNTLSS_SRST 0x01 + +/* IICx_DIRECTCNTL register */ +#define DIRCNTL_SDAC 0x08 +#define DIRCNTL_SCC 0x04 +#define DIRCNTL_MSDA 0x02 +#define DIRCNTL_MSC 0x01 + +/* Check if we really control the I2C bus and bus is free */ +#define DIRCTNL_FREE(v) (((v) & 0x0f) == 0x0f) + +#endif /* __I2C_IBM_IIC_H_ */ diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-iop3xx.c i2c-2.5/drivers/i2c/busses/i2c-iop3xx.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-iop3xx.c Thu Jan 1 00:00:00 1970 +++ i2c-2.5/drivers/i2c/busses/i2c-iop3xx.c Tue Sep 23 10:12:59 2003 @@ -0,0 +1,536 @@ +/* ------------------------------------------------------------------------- */ +/* i2c-iop3xx.c i2c driver algorithms for Intel XScale IOP3xx */ +/* ------------------------------------------------------------------------- */ +/* Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd + * + + 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. + + + 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. */ +/* ------------------------------------------------------------------------- */ +/* + With acknowledgements to i2c-algo-ibm_ocp.c by + Ian DaSilva, MontaVista Software, Inc. idasilva@mvista.com + + And i2c-algo-pcf.c, which was created by Simon G. Vogl and Hans Berglund: + + Copyright (C) 1995-1997 Simon G. Vogl, 1998-2000 Hans Berglund + + And which acknowledged Kyösti Mälkki , + Frodo Looijaard , Martin Bailey + + ---------------------------------------------------------------------------*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include "i2c-iop3xx.h" + + +/* ----- global defines ----------------------------------------------- */ +#define PASSERT(x) do { if (!(x) ) \ + printk(KERN_CRIT "PASSERT %s in %s:%d\n", #x, __FILE__, __LINE__ );\ + } while (0) + + +/* ----- global variables --------------------------------------------- */ + + +static inline unsigned char iic_cook_addr(struct i2c_msg *msg) +{ + unsigned char addr; + + addr = (msg->addr << 1); + + if (msg->flags & I2C_M_RD) + addr |= 1; + + /* PGM: what is M_REV_DIR_ADDR - do we need it ?? */ + if (msg->flags & I2C_M_REV_DIR_ADDR) + addr ^= 1; + + return addr; +} + + +static inline void iop3xx_adap_reset(struct i2c_algo_iop3xx_data *iop3xx_adap) +{ + /* Follows devman 9.3 */ + *iop3xx_adap->biu->CR = IOP321_ICR_UNIT_RESET; + *iop3xx_adap->biu->SR = IOP321_ISR_CLEARBITS; + *iop3xx_adap->biu->CR = 0; +} + +static inline void iop3xx_adap_set_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap) +{ + *iop3xx_adap->biu->SAR = MYSAR; +} + +static inline void iop3xx_adap_enable(struct i2c_algo_iop3xx_data *iop3xx_adap) +{ + u32 cr = IOP321_ICR_GCD|IOP321_ICR_SCLEN|IOP321_ICR_UE; + + /* NB SR bits not same position as CR IE bits :-( */ + iop3xx_adap->biu->SR_enabled = + IOP321_ISR_ALD | IOP321_ISR_BERRD | + IOP321_ISR_RXFULL | IOP321_ISR_TXEMPTY; + + cr |= IOP321_ICR_ALDIE | IOP321_ICR_BERRIE | + IOP321_ICR_RXFULLIE | IOP321_ICR_TXEMPTYIE; + + *iop3xx_adap->biu->CR = cr; +} + +static void iop3xx_adap_transaction_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap) +{ + unsigned cr = *iop3xx_adap->biu->CR; + + cr &= ~(IOP321_ICR_MSTART | IOP321_ICR_TBYTE | + IOP321_ICR_MSTOP | IOP321_ICR_SCLEN); + *iop3xx_adap->biu->CR = cr; +} + +static void iop3xx_adap_final_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap) +{ + unsigned cr = *iop3xx_adap->biu->CR; + + cr &= ~(IOP321_ICR_ALDIE | IOP321_ICR_BERRIE | + IOP321_ICR_RXFULLIE | IOP321_ICR_TXEMPTYIE); + iop3xx_adap->biu->SR_enabled = 0; + *iop3xx_adap->biu->CR = cr; +} + +/* + * NB: the handler has to clear the source of the interrupt! + * Then it passes the SR flags of interest to BH via adap data + */ +static void iop3xx_i2c_handler(int this_irq, + void *dev_id, + struct pt_regs *regs) +{ + struct i2c_algo_iop3xx_data *iop3xx_adap = dev_id; + + u32 sr = *iop3xx_adap->biu->SR; + + if ((sr &= iop3xx_adap->biu->SR_enabled)) { + *iop3xx_adap->biu->SR = sr; + iop3xx_adap->biu->SR_received |= sr; + wake_up_interruptible(&iop3xx_adap->waitq); + } +} + +/* check all error conditions, clear them , report most important */ +static int iop3xx_adap_error(u32 sr) +{ + int rc = 0; + + if ((sr&IOP321_ISR_BERRD)) { + if ( !rc ) rc = -I2C_ERR_BERR; + } + if ((sr&IOP321_ISR_ALD)) { + if ( !rc ) rc = -I2C_ERR_ALD; + } + return rc; +} + +static inline u32 get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap) +{ + unsigned long flags; + u32 sr; + + spin_lock_irqsave(&iop3xx_adap->lock, flags); + sr = iop3xx_adap->biu->SR_received; + iop3xx_adap->biu->SR_received = 0; + spin_unlock_irqrestore(&iop3xx_adap->lock, flags); + + return sr; +} + +/* + * sleep until interrupted, then recover and analyse the SR + * saved by handler + */ +typedef int (* compare_func)(unsigned test, unsigned mask); +/* returns 1 on correct comparison */ + +static int iop3xx_adap_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap, + unsigned flags, unsigned* status, + compare_func compare) +{ + unsigned sr = 0; + int interrupted; + int done; + int rc; + + do { + interrupted = wait_event_interruptible_timeout ( + iop3xx_adap->waitq, + (done = compare( sr = get_srstat(iop3xx_adap),flags )), + iop3xx_adap->timeout + ); + if ((rc = iop3xx_adap_error(sr)) < 0) { + *status = sr; + return rc; + }else if (!interrupted) { + *status = sr; + return rc = -ETIMEDOUT; + } + } while(!done); + + *status = sr; + + return rc = 0; +} + +/* + * Concrete compare_funcs + */ +static int all_bits_clear(unsigned test, unsigned mask) +{ + return (test & mask) == 0; +} +static int any_bits_set(unsigned test, unsigned mask) +{ + return (test & mask) != 0; +} + +static int iop3xx_adap_wait_tx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status) +{ + return iop3xx_adap_wait_event( + iop3xx_adap, + IOP321_ISR_TXEMPTY|IOP321_ISR_ALD|IOP321_ISR_BERRD, + status, any_bits_set); +} + +static int iop3xx_adap_wait_rx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status) +{ + return iop3xx_adap_wait_event( + iop3xx_adap, + IOP321_ISR_RXFULL|IOP321_ISR_ALD|IOP321_ISR_BERRD, + status, any_bits_set); +} + +static int iop3xx_adap_wait_idle(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status) +{ + return iop3xx_adap_wait_event( + iop3xx_adap, IOP321_ISR_UNITBUSY, status, all_bits_clear); +} + +/* + * Description: This performs the IOP3xx initialization sequence + * Valid for IOP321. Maybe valid for IOP310?. + */ +static int iop3xx_adap_init (struct i2c_algo_iop3xx_data *iop3xx_adap) +{ + *IOP321_GPOD &= ~(iop3xx_adap->channel==0 ? + IOP321_GPOD_I2C0: + IOP321_GPOD_I2C1); + + iop3xx_adap_reset(iop3xx_adap); + iop3xx_adap_set_slave_addr(iop3xx_adap); + iop3xx_adap_enable(iop3xx_adap); + + return 0; +} + +static int iop3xx_adap_send_target_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap, + struct i2c_msg* msg) +{ + unsigned cr = *iop3xx_adap->biu->CR; + int status; + int rc; + + *iop3xx_adap->biu->DBR = iic_cook_addr(msg); + + cr &= ~(IOP321_ICR_MSTOP | IOP321_ICR_NACK); + cr |= IOP321_ICR_MSTART | IOP321_ICR_TBYTE; + + *iop3xx_adap->biu->CR = cr; + rc = iop3xx_adap_wait_tx_done(iop3xx_adap, &status); + /* this assert fires every time, contrary to IOP manual + PASSERT((status&IOP321_ISR_UNITBUSY)!=0); + */ + PASSERT((status&IOP321_ISR_RXREAD)==0); + + return rc; +} + +static int iop3xx_adap_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte, int stop) +{ + unsigned cr = *iop3xx_adap->biu->CR; + int status; + int rc; + + *iop3xx_adap->biu->DBR = byte; + cr &= ~IOP321_ICR_MSTART; + if (stop) { + cr |= IOP321_ICR_MSTOP; + } else { + cr &= ~IOP321_ICR_MSTOP; + } + *iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE; + rc = iop3xx_adap_wait_tx_done(iop3xx_adap, &status); + + return rc; +} + +static int iop3xx_adap_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, + char* byte, int stop) +{ + unsigned cr = *iop3xx_adap->biu->CR; + int status; + int rc; + + cr &= ~IOP321_ICR_MSTART; + + if (stop) { + cr |= IOP321_ICR_MSTOP|IOP321_ICR_NACK; + } else { + cr &= ~(IOP321_ICR_MSTOP|IOP321_ICR_NACK); + } + *iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE; + + rc = iop3xx_adap_wait_rx_done(iop3xx_adap, &status); + + *byte = *iop3xx_adap->biu->DBR; + + return rc; +} + +static int iop3xx_i2c_writebytes(struct i2c_adapter *i2c_adap, + const char *buf, int count) +{ + struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; + int ii; + int rc = 0; + + for (ii = 0; rc == 0 && ii != count; ++ii) { + rc = iop3xx_adap_write_byte(iop3xx_adap, buf[ii], ii==count-1); + } + return rc; +} + +static int iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap, + char *buf, int count) +{ + struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; + int ii; + int rc = 0; + + for (ii = 0; rc == 0 && ii != count; ++ii) { + rc = iop3xx_adap_read_byte(iop3xx_adap, &buf[ii], ii==count-1); + } + return rc; +} + +/* + * Description: This function implements combined transactions. Combined + * transactions consist of combinations of reading and writing blocks of data. + * FROM THE SAME ADDRESS + * Each transfer (i.e. a read or a write) is separated by a repeated start + * condition. + */ +static int iop3xx_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg) +{ + struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; + int rc; + + rc = iop3xx_adap_send_target_slave_addr(iop3xx_adap, pmsg); + if (rc < 0) { + return rc; + } + + if ((pmsg->flags&I2C_M_RD)) { + return iop3xx_i2c_readbytes(i2c_adap, pmsg->buf, pmsg->len); + } else { + return iop3xx_i2c_writebytes(i2c_adap, pmsg->buf, pmsg->len); + } +} + +/* + * master_xfer() - main read/write entry + */ +static int iop3xx_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) +{ + struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; + int im = 0; + int ret = 0; + int status; + + iop3xx_adap_wait_idle(iop3xx_adap, &status); + iop3xx_adap_reset(iop3xx_adap); + iop3xx_adap_enable(iop3xx_adap); + + for (im = 0; ret == 0 && im != num; ++im) { + ret = iop3xx_handle_msg(i2c_adap, &msgs[im]); + } + + iop3xx_adap_transaction_cleanup(iop3xx_adap); + + return ret; +} + +static int algo_control(struct i2c_adapter *adapter, unsigned int cmd, + unsigned long arg) +{ + return 0; +} + +static u32 iic_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + + +/* -----exported algorithm data: ------------------------------------- */ + +static struct i2c_algorithm iic_algo = { + .name = "IOP3xx I2C algorithm", + .id = I2C_ALGO_OCP_IOP3XX, + .master_xfer = iop3xx_master_xfer, + .algo_control = algo_control, + .functionality = iic_func, +}; + +/* + * registering functions to load algorithms at runtime + */ +static int i2c_iop3xx_add_bus(struct i2c_adapter *iic_adap) +{ + struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data; + + if (!request_region( REGION_START(iop3xx_adap), + REGION_LENGTH(iop3xx_adap), + iic_adap->name)) { + return -ENODEV; + } + + init_waitqueue_head(&iop3xx_adap->waitq); + spin_lock_init(&iop3xx_adap->lock); + + if (request_irq( + iop3xx_adap->biu->irq, + iop3xx_i2c_handler, + /* SA_SAMPLE_RANDOM */ 0, + iic_adap->name, + iop3xx_adap)) { + return -ENODEV; + } + + /* register new iic_adapter to i2c module... */ + iic_adap->id |= iic_algo.id; + iic_adap->algo = &iic_algo; + + iic_adap->timeout = 100; /* default values, should */ + iic_adap->retries = 3; /* be replaced by defines */ + + iop3xx_adap_init(iic_adap->algo_data); + i2c_add_adapter(iic_adap); + return 0; +} + +static int i2c_iop3xx_del_bus(struct i2c_adapter *iic_adap) +{ + struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data; + + iop3xx_adap_final_cleanup(iop3xx_adap); + free_irq(iop3xx_adap->biu->irq, iop3xx_adap); + + release_region(REGION_START(iop3xx_adap), REGION_LENGTH(iop3xx_adap)); + + return i2c_del_adapter(iic_adap); +} + +#ifdef CONFIG_ARCH_IOP321 + +static struct iop3xx_biu biu0 = { + .CR = IOP321_ICR0, + .SR = IOP321_ISR0, + .SAR = IOP321_ISAR0, + .DBR = IOP321_IDBR0, + .BMR = IOP321_IBMR0, + .irq = IRQ_IOP321_I2C_0, +}; + +static struct iop3xx_biu biu1 = { + .CR = IOP321_ICR1, + .SR = IOP321_ISR1, + .SAR = IOP321_ISAR1, + .DBR = IOP321_IDBR1, + .BMR = IOP321_IBMR1, + .irq = IRQ_IOP321_I2C_1, +}; + +#define ADAPTER_NAME_ROOT "IOP321 i2c biu adapter " +#else +#error Please define the BIU struct iop3xx_biu for your processor arch +#endif + +static struct i2c_algo_iop3xx_data algo_iop3xx_data0 = { + .channel = 0, + .biu = &biu0, + .timeout = 1*HZ, +}; +static struct i2c_algo_iop3xx_data algo_iop3xx_data1 = { + .channel = 1, + .biu = &biu1, + .timeout = 1*HZ, +}; + +static struct i2c_adapter iop3xx_ops0 = { + .owner = THIS_MODULE, + .name = ADAPTER_NAME_ROOT "0", + .id = I2C_HW_IOP321, + .algo_data = &algo_iop3xx_data0, +}; +static struct i2c_adapter iop3xx_ops1 = { + .owner = THIS_MODULE, + .name = ADAPTER_NAME_ROOT "1", + .id = I2C_HW_IOP321, + .algo_data = &algo_iop3xx_data1, +}; + +static int __init i2c_iop3xx_init (void) +{ + return i2c_iop3xx_add_bus(&iop3xx_ops0) || + i2c_iop3xx_add_bus(&iop3xx_ops1); +} + +static void __exit i2c_iop3xx_exit (void) +{ + i2c_iop3xx_del_bus(&iop3xx_ops0); + i2c_iop3xx_del_bus(&iop3xx_ops1); +} + +module_init (i2c_iop3xx_init); +module_exit (i2c_iop3xx_exit); + +MODULE_AUTHOR("D-TACQ Solutions Ltd "); +MODULE_DESCRIPTION("IOP3xx iic algorithm and driver"); +MODULE_LICENSE("GPL"); + +MODULE_PARM(i2c_debug,"i"); + +MODULE_PARM_DESC(i2c_debug, "debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol"); + diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-iop3xx.h i2c-2.5/drivers/i2c/busses/i2c-iop3xx.h --- linux-2.6.0-test5/drivers/i2c/busses/i2c-iop3xx.h Thu Jan 1 00:00:00 1970 +++ i2c-2.5/drivers/i2c/busses/i2c-iop3xx.h Tue Sep 23 10:12:59 2003 @@ -0,0 +1,118 @@ +/* ------------------------------------------------------------------------- */ +/* i2c-iop3xx.h algorithm driver definitions private to i2c-iop3xx.c */ +/* ------------------------------------------------------------------------- */ +/* Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd + * + + 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. + + 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_IOP3XX_H +#define I2C_IOP3XX_H 1 + +/* + * iop321 hardware bit definitions + */ +#define IOP321_ICR_FAST_MODE 0x8000 /* 1=400kBps, 0=100kBps */ +#define IOP321_ICR_UNIT_RESET 0x4000 /* 1=RESET */ +#define IOP321_ICR_SADIE 0x2000 /* 1=Slave Detect Interrupt Enable */ +#define IOP321_ICR_ALDIE 0x1000 /* 1=Arb Loss Detect Interrupt Enable */ +#define IOP321_ICR_SSDIE 0x0800 /* 1=Slave STOP Detect Interrupt Enable */ +#define IOP321_ICR_BERRIE 0x0400 /* 1=Bus Error Interrupt Enable */ +#define IOP321_ICR_RXFULLIE 0x0200 /* 1=Receive Full Interrupt Enable */ +#define IOP321_ICR_TXEMPTYIE 0x0100 /* 1=Transmit Empty Interrupt Enable */ +#define IOP321_ICR_GCD 0x0080 /* 1=General Call Disable */ +/* + * IOP321_ICR_GCD: 1 disables response as slave. "This bit must be set + * when sending a master mode general call message from the I2C unit" + */ +#define IOP321_ICR_UE 0x0040 /* 1=Unit Enable */ +/* + * "NOTE: To avoid I2C bus integrity problems, + * the user needs to ensure that the GPIO Output Data Register - + * GPOD bits associated with an I2C port are cleared prior to setting + * the enable bit for that I2C serial port. + * The user prepares to enable I2C port 0 and + * I2C port 1 by clearing GPOD bits 7:6 and GPOD bits 5:4, respectively. + */ +#define IOP321_ICR_SCLEN 0x0020 /* 1=SCL enable for master mode */ +#define IOP321_ICR_MABORT 0x0010 /* 1=Send a STOP with no data + * NB TBYTE must be clear */ +#define IOP321_ICR_TBYTE 0x0008 /* 1=Send/Receive a byte. i2c clears */ +#define IOP321_ICR_NACK 0x0004 /* 1=reply with NACK */ +#define IOP321_ICR_MSTOP 0x0002 /* 1=send a STOP after next data byte */ +#define IOP321_ICR_MSTART 0x0001 /* 1=initiate a START */ + + +#define IOP321_ISR_BERRD 0x0400 /* 1=BUS ERROR Detected */ +#define IOP321_ISR_SAD 0x0200 /* 1=Slave ADdress Detected */ +#define IOP321_ISR_GCAD 0x0100 /* 1=General Call Address Detected */ +#define IOP321_ISR_RXFULL 0x0080 /* 1=Receive Full */ +#define IOP321_ISR_TXEMPTY 0x0040 /* 1=Transmit Empty */ +#define IOP321_ISR_ALD 0x0020 /* 1=Arbitration Loss Detected */ +#define IOP321_ISR_SSD 0x0010 /* 1=Slave STOP Detected */ +#define IOP321_ISR_BBUSY 0x0008 /* 1=Bus BUSY */ +#define IOP321_ISR_UNITBUSY 0x0004 /* 1=Unit Busy */ +#define IOP321_ISR_NACK 0x0002 /* 1=Unit Rx or Tx a NACK */ +#define IOP321_ISR_RXREAD 0x0001 /* 1=READ 0=WRITE (R/W bit of slave addr */ + +#define IOP321_ISR_CLEARBITS 0x07f0 + +#define IOP321_ISAR_SAMASK 0x007f + +#define IOP321_IDBR_MASK 0x00ff + +#define IOP321_IBMR_SCL 0x0002 +#define IOP321_IBMR_SDA 0x0001 + +#define IOP321_GPOD_I2C0 0x00c0 /* clear these bits to enable ch0 */ +#define IOP321_GPOD_I2C1 0x0030 /* clear these bits to enable ch1 */ + +#define MYSAR 0x02 /* SWAG a suitable slave address */ + +#define I2C_ERR 321 +#define I2C_ERR_BERR (I2C_ERR+0) +#define I2C_ERR_ALD (I2C_ERR+1) + + +struct iop3xx_biu { /* Bus Interface Unit - the hardware */ +/* physical hardware defs - regs*/ + u32 *CR; + u32 *SR; + u32 *SAR; + u32 *DBR; + u32 *BMR; +/* irq bit vector */ + u32 irq; +/* stored flags */ + u32 SR_enabled, SR_received; +}; + +struct i2c_algo_iop3xx_data { + int channel; + + wait_queue_head_t waitq; + spinlock_t lock; + int timeout; + struct iop3xx_biu* biu; +}; + +#define REGION_START(adap) ((u32)((adap)->biu->CR)) +#define REGION_END(adap) ((u32)((adap)->biu->BMR+1)) +#define REGION_LENGTH(adap) (REGION_END(adap)-REGION_START(adap)) + +#define IRQ_STATUS_MASK(adap) (1<biu->irq) + +#endif /* I2C_IOP3XX_H */ diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-isa.c i2c-2.5/drivers/i2c/busses/i2c-isa.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-isa.c Mon Sep 8 19:50:07 2003 +++ i2c-2.5/drivers/i2c/busses/i2c-isa.c Tue Sep 23 10:12:59 2003 @@ -30,21 +30,29 @@ #include #include +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, }; /* There can only be one... */ static struct i2c_adapter isa_adapter = { .owner = THIS_MODULE, - .id = I2C_ALGO_ISA | I2C_HW_ISA, .class = I2C_ADAP_CLASS_SMBUS, .algo = &isa_algorithm, .name = "ISA main adapter", }; +/* We can't do a thing... */ +static u32 isa_func(struct i2c_adapter *adapter) +{ + return 0; +} + static int __init i2c_isa_init(void) { return i2c_add_adapter(&isa_adapter); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-ite.c i2c-2.5/drivers/i2c/busses/i2c-ite.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-ite.c Thu Jan 1 00:00:00 1970 +++ i2c-2.5/drivers/i2c/busses/i2c-ite.c Tue Sep 23 10:12:59 2003 @@ -0,0 +1,278 @@ +/* + ------------------------------------------------------------------------- + i2c-adap-ite.c i2c-hw access for the IIC peripheral on the ITE MIPS system + ------------------------------------------------------------------------- + Hai-Pao Fan, MontaVista Software, Inc. + hpfan@mvista.com or source@mvista.com + + Copyright 2001 MontaVista Software Inc. + + ---------------------------------------------------------------------------- + This file was highly leveraged from i2c-elektor.c, which was created + by Simon G. Vogl and Hans Berglund: + + + Copyright (C) 1995-97 Simon G. Vogl + 1998-99 Hans Berglund + + 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. */ +/* ------------------------------------------------------------------------- */ + +/* With some changes from Kyösti Mälkki and even + Frodo Looijaard */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "../i2c-ite.h" + +#define DEFAULT_BASE 0x14014030 +#define ITE_IIC_IO_SIZE 0x40 +#define DEFAULT_IRQ 0 +#define DEFAULT_CLOCK 0x1b0e /* default 16MHz/(27+14) = 400KHz */ +#define DEFAULT_OWN 0x55 + +static int base = 0; +static int irq = 0; +static int clock = 0; +static int own = 0; + +static int i2c_debug=0; +static struct iic_ite gpi; +static wait_queue_head_t iic_wait; +static int iic_pending; + +/* ----- global defines ----------------------------------------------- */ +#define DEB(x) if (i2c_debug>=1) x +#define DEB2(x) if (i2c_debug>=2) x +#define DEB3(x) if (i2c_debug>=3) x +#define DEBE(x) x /* error messages */ + + +/* ----- local functions ---------------------------------------------- */ + +static void iic_ite_setiic(void *data, int ctl, short val) +{ + unsigned long j = jiffies + 10; + + DEB3(printk(" Write 0x%02x to 0x%x\n",(unsigned short)val, ctl&0xff)); + DEB3({while (time_before(jiffies, j)) schedule();}) + outw(val,ctl); +} + +static short iic_ite_getiic(void *data, int ctl) +{ + short val; + + val = inw(ctl); + DEB3(printk("Read 0x%02x from 0x%x\n",(unsigned short)val, ctl&0xff)); + return (val); +} + +/* Return our slave address. This is the address + * put on the I2C bus when another master on the bus wants to address us + * as a slave + */ +static int iic_ite_getown(void *data) +{ + return (gpi.iic_own); +} + + +static int iic_ite_getclock(void *data) +{ + return (gpi.iic_clock); +} + + +#if 0 +static void iic_ite_sleep(unsigned long timeout) +{ + schedule_timeout( timeout * HZ); +} +#endif + + +/* Put this process to sleep. We will wake up when the + * IIC controller interrupts. + */ +static void iic_ite_waitforpin(void) { + + int timeout = 2; + + /* If interrupts are enabled (which they are), then put the process to + * sleep. This process will be awakened by two events -- either the + * the IIC peripheral interrupts or the timeout expires. + * If interrupts are not enabled then delay for a reasonable amount + * of time and return. + */ + if (gpi.iic_irq > 0) { + cli(); + if (iic_pending == 0) { + interruptible_sleep_on_timeout(&iic_wait, timeout*HZ ); + } else + iic_pending = 0; + sti(); + } else { + udelay(100); + } +} + + +static void iic_ite_handler(int this_irq, void *dev_id, struct pt_regs *regs) +{ + + iic_pending = 1; + + DEB2(printk("iic_ite_handler: in interrupt handler\n")); + wake_up_interruptible(&iic_wait); +} + + +/* Lock the region of memory where I/O registers exist. Request our + * interrupt line and register its associated handler. + */ +static int iic_hw_resrc_init(void) +{ + if (!request_region(gpi.iic_base, ITE_IIC_IO_SIZE, "i2c")) + return -ENODEV; + + if (gpi.iic_irq <= 0) + return 0; + + if (request_irq(gpi.iic_irq, iic_ite_handler, 0, "ITE IIC", 0) < 0) + gpi.iic_irq = 0; + else + enable_irq(gpi.iic_irq); + + return 0; +} + + +static void iic_ite_release(void) +{ + if (gpi.iic_irq > 0) { + disable_irq(gpi.iic_irq); + free_irq(gpi.iic_irq, 0); + } + release_region(gpi.iic_base , 2); +} + +/* ------------------------------------------------------------------------ + * Encapsulate the above functions in the correct operations structure. + * This is only done when more than one hardware adapter is supported. + */ +static struct i2c_algo_iic_data iic_ite_data = { + NULL, + iic_ite_setiic, + iic_ite_getiic, + iic_ite_getown, + iic_ite_getclock, + iic_ite_waitforpin, + 80, 80, 100, /* waits, timeout */ +}; + +static struct i2c_adapter iic_ite_ops = { + .owner = THIS_MODULE, + .id = I2C_HW_I_IIC, + .algo_data = &iic_ite_data, + .dev = { + .name = "ITE IIC adapter", + }, +}; + +/* Called when the module is loaded. This function starts the + * cascade of calls up through the hierarchy of i2c modules (i.e. up to the + * algorithm layer and into to the core layer) + */ +static int __init iic_ite_init(void) +{ + + struct iic_ite *piic = &gpi; + + printk(KERN_INFO "Initialize ITE IIC adapter module\n"); + if (base == 0) + piic->iic_base = DEFAULT_BASE; + else + piic->iic_base = base; + + if (irq == 0) + piic->iic_irq = DEFAULT_IRQ; + else + piic->iic_irq = irq; + + if (clock == 0) + piic->iic_clock = DEFAULT_CLOCK; + else + piic->iic_clock = clock; + + if (own == 0) + piic->iic_own = DEFAULT_OWN; + else + piic->iic_own = own; + + iic_ite_data.data = (void *)piic; + init_waitqueue_head(&iic_wait); + if (iic_hw_resrc_init() == 0) { + if (i2c_iic_add_bus(&iic_ite_ops) < 0) + return -ENODEV; + } else { + return -ENODEV; + } + printk(KERN_INFO " found device at %#x irq %d.\n", + piic->iic_base, piic->iic_irq); + return 0; +} + + +static void iic_ite_exit(void) +{ + i2c_iic_del_bus(&iic_ite_ops); + iic_ite_release(); +} + +/* If modules is NOT defined when this file is compiled, then the MODULE_* + * macros will resolve to nothing + */ +MODULE_AUTHOR("MontaVista Software "); +MODULE_DESCRIPTION("I2C-Bus adapter routines for ITE IIC bus adapter"); +MODULE_LICENSE("GPL"); + +MODULE_PARM(base, "i"); +MODULE_PARM(irq, "i"); +MODULE_PARM(clock, "i"); +MODULE_PARM(own, "i"); +MODULE_PARM(i2c_debug,"i"); + + +/* Called when module is loaded or when kernel is initialized. + * If MODULES is defined when this file is compiled, then this function will + * resolve to init_module (the function called when insmod is invoked for a + * module). Otherwise, this function is called early in the boot, when the + * kernel is intialized. Check out /include/init.h to see how this works. + */ +module_init(iic_ite_init); + +/* Resolves to module_cleanup when MODULES is defined. */ +module_exit(iic_ite_exit); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-keywest.c i2c-2.5/drivers/i2c/busses/i2c-keywest.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-keywest.c Thu Jan 1 00:00:00 1970 +++ i2c-2.5/drivers/i2c/busses/i2c-keywest.c Tue Sep 23 10:12:59 2003 @@ -0,0 +1,653 @@ +/* + 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 + +#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(probe, "i"); +MODULE_PARM(debug, "i"); + +int probe = 0; +int debug = 0; + +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 irqreturn_t +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))) + mod_timer(&iface->timeout_timer, jiffies + POLL_TIMEOUT); + spin_unlock(&iface->lock); + return IRQ_HANDLED; +} + +static void +keywest_timeout(unsigned long data) +{ + struct keywest_iface *iface = (struct keywest_iface *)data; + + DBG("timeout !\n"); + spin_lock_irq(&iface->lock); + if (handle_interrupt(iface, read_reg(reg_isr))) + mod_timer(&iface->timeout_timer, jiffies + POLL_TIMEOUT); + 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 = i2c_get_adapdata(adap); + 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; + 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; + break; + case I2C_SMBUS_BLOCK_DATA: + len = data->block[0]; + buffer = &data->block[1]; + iface->cur_mode |= KW_I2C_MODE_STANDARDSUB; + 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 */ + mod_timer(&iface->timeout_timer, jiffies + POLL_TIMEOUT); + + /* 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 interrupt operations completion */ + 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 = i2c_get_adapdata(adap); + 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 */ + mod_timer(&iface->timeout_timer, jiffies + POLL_TIMEOUT); + + /* 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 interrupt operations completion */ + 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; +} + +/* 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 +create_iface(struct device_node *np, struct device *dev) +{ + unsigned long steps, *psteps, *prate; + unsigned bsteps, tsize, i, nchan, addroffset; + struct keywest_iface* iface; + int rc; + + 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 = (struct keywest_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 sub mode */ + iface->cur_mode |= KW_I2C_MODE_STANDARDSUB; + + /* 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 */ + rc = request_irq(iface->irq, keywest_irq, 0, "keywest i2c", iface); + if (rc) { + printk(KERN_ERR "i2c-keywest: can't get IRQ %d !\n", iface->irq); + iounmap((void *)iface->base); + kfree(iface); + return -ENODEV; + } + + dev_set_drvdata(dev, iface); + + for (i=0; ichannels[i]; + u8 addr; + + 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.client_register = NULL; + chan->adapter.client_unregister = NULL; + i2c_set_adapdata(&chan->adapter, chan); + chan->adapter.dev.parent = dev; + + rc = i2c_add_adapter(&chan->adapter); + if (rc) { + printk("i2c-keywest.c: Adapter %s registration failed\n", + chan->adapter.name); + i2c_set_adapdata(&chan->adapter, NULL); + } + if (probe) { + printk("Probe: "); + for (addr = 0x00; addr <= 0x7f; addr++) { + if (i2c_smbus_xfer(&chan->adapter,addr, + 0,0,0,I2C_SMBUS_QUICK,NULL) >= 0) + printk("%02x ", addr); + } + printk("\n"); + } + } + + printk(KERN_INFO "Found KeyWest i2c on \"%s\", %d channel%s, stepping: %d bits\n", + np->parent->name, nchan, nchan > 1 ? "s" : "", bsteps); + + return 0; +} + +static int +dispose_iface(struct device *dev) +{ + struct keywest_iface *iface = dev_get_drvdata(dev); + int i, rc; + + /* 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 (i2c_get_adapdata(&chan->adapter) == NULL) + continue; + rc = i2c_del_adapter(&chan->adapter); + i2c_set_adapdata(&chan->adapter, NULL); + /* We aren't that prepared to deal with this... */ + if (rc) + printk("i2c-keywest.c: i2c_del_adapter failed, that's bad !\n"); + } + iounmap((void *)iface->base); + dev_set_drvdata(dev, NULL); + kfree(iface); + + return 0; +} + +static int +create_iface_macio(struct macio_dev* dev, const struct of_match *match) +{ + return create_iface(dev->ofdev.node, &dev->ofdev.dev); +} + +static int +dispose_iface_macio(struct macio_dev* dev) +{ + return dispose_iface(&dev->ofdev.dev); +} + +static int +create_iface_of_platform(struct of_device* dev, const struct of_match *match) +{ + return create_iface(dev->node, &dev->dev); +} + +static int +dispose_iface_of_platform(struct of_device* dev) +{ + return dispose_iface(&dev->dev); +} + +static struct of_match i2c_keywest_match[] = +{ + { + .name = OF_ANY_MATCH, + .type = "i2c", + .compatible = "keywest" + }, + {}, +}; + +static struct macio_driver i2c_keywest_macio_driver = +{ + .name = "i2c-keywest", + .match_table = i2c_keywest_match, + .probe = create_iface_macio, + .remove = dispose_iface_macio +}; + +static struct of_platform_driver i2c_keywest_of_platform_driver = +{ + .name = "i2c-keywest", + .match_table = i2c_keywest_match, + .probe = create_iface_of_platform, + .remove = dispose_iface_of_platform +}; + +static int __init +i2c_keywest_init(void) +{ + macio_register_driver(&i2c_keywest_macio_driver); + of_register_driver(&i2c_keywest_of_platform_driver); + + return 0; +} + +static void __exit +i2c_keywest_cleanup(void) +{ + macio_unregister_driver(&i2c_keywest_macio_driver); + of_unregister_driver(&i2c_keywest_of_platform_driver); +} + +module_init(i2c_keywest_init); +module_exit(i2c_keywest_cleanup); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-keywest.h i2c-2.5/drivers/i2c/busses/i2c-keywest.h --- linux-2.6.0-test5/drivers/i2c/busses/i2c-keywest.h Thu Jan 1 00:00:00 1970 +++ i2c-2.5/drivers/i2c/busses/i2c-keywest.h Tue Sep 23 10:12:59 2003 @@ -0,0 +1,110 @@ +#ifndef __I2C_KEYWEST_H__ +#define __I2C_KEYWEST_H__ + +/* 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; +}; + +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 -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-nforce2.c i2c-2.5/drivers/i2c/busses/i2c-nforce2.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-nforce2.c Mon Sep 8 19:49:54 2003 +++ i2c-2.5/drivers/i2c/busses/i2c-nforce2.c Tue Sep 23 10:12:59 2003 @@ -118,7 +118,6 @@ static struct i2c_adapter nforce2_adapter = { .owner = THIS_MODULE, - .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_NFORCE2, .class = I2C_ADAP_CLASS_SMBUS, .algo = &smbus_algorithm, .name = "unset", @@ -321,7 +320,7 @@ smbus->adapter = nforce2_adapter; smbus->adapter.algo_data = smbus; smbus->adapter.dev.parent = &dev->dev; - snprintf(smbus->adapter.name, DEVICE_NAME_SIZE, + snprintf(smbus->adapter.name, I2C_NAME_SIZE, "SMBus nForce2 adapter at %04x", smbus->base); error = i2c_add_adapter(&smbus->adapter); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-philips-par.c i2c-2.5/drivers/i2c/busses/i2c-philips-par.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-philips-par.c Thu Jan 1 00:00:00 1970 +++ i2c-2.5/drivers/i2c/busses/i2c-philips-par.c Tue Sep 23 10:12:59 2003 @@ -0,0 +1,243 @@ +/* ------------------------------------------------------------------------- */ +/* i2c-philips-par.c i2c-hw access for philips style parallel port adapters */ +/* ------------------------------------------------------------------------- */ +/* Copyright (C) 1995-2000 Simon G. 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. */ +/* ------------------------------------------------------------------------- */ + +/* With some changes from Kyösti Mälkki and even + Frodo Looijaard */ + +/* $Id$ */ + +#include +#include +#include +#include +#include +#include + +static int type; + +struct i2c_par +{ + struct pardevice *pdev; + struct i2c_adapter adapter; + struct i2c_algo_bit_data bit_lp_data; + struct i2c_par *next; +}; + +static struct i2c_par *adapter_list; + + +/* ----- printer port defines ------------------------------------------*/ + /* Pin Port Inverted name */ +#define I2C_ON 0x20 /* 12 status N paper */ + /* ... only for phil. not used */ +#define I2C_SDA 0x80 /* 9 data N data7 */ +#define I2C_SCL 0x08 /* 17 ctrl N dsel */ + +#define I2C_SDAIN 0x80 /* 11 stat Y busy */ +#define I2C_SCLIN 0x08 /* 15 stat Y enable */ + +#define I2C_DMASK 0x7f +#define I2C_CMASK 0xf7 + +/* ----- local functions ---------------------------------------------- */ + +static void bit_lp_setscl(void *data, int state) +{ + /*be cautious about state of the control register - + touch only the one bit needed*/ + if (state) { + parport_write_control((struct parport *) data, + parport_read_control((struct parport *) data)|I2C_SCL); + } else { + parport_write_control((struct parport *) data, + parport_read_control((struct parport *) data)&I2C_CMASK); + } +} + +static void bit_lp_setsda(void *data, int state) +{ + if (state) { + parport_write_data((struct parport *) data, I2C_DMASK); + } else { + parport_write_data((struct parport *) data, I2C_SDA); + } +} + +static int bit_lp_getscl(void *data) +{ + return parport_read_status((struct parport *) data) & I2C_SCLIN; +} + +static int bit_lp_getsda(void *data) +{ + return parport_read_status((struct parport *) data) & I2C_SDAIN; +} + +static void bit_lp_setscl2(void *data, int state) +{ + if (state) { + parport_write_data((struct parport *) data, + parport_read_data((struct parport *) data)|0x1); + } else { + parport_write_data((struct parport *) data, + parport_read_data((struct parport *) data)&0xfe); + } +} + +static void bit_lp_setsda2(void *data, int state) +{ + if (state) { + parport_write_data((struct parport *) data, + parport_read_data((struct parport *) data)|0x2); + } else { + parport_write_data((struct parport *) data, + parport_read_data((struct parport *) data)&0xfd); + } +} + +static int bit_lp_getsda2(void *data) +{ + return (parport_read_status((struct parport *) data) & + PARPORT_STATUS_BUSY) ? 0 : 1; +} + +/* ------------------------------------------------------------------------ + * Encapsulate the above functions in the correct operations structure. + * This is only done when more than one hardware adapter is supported. + */ + +static struct i2c_algo_bit_data bit_lp_data = { + .setsda = bit_lp_setsda, + .setscl = bit_lp_setscl, + .getsda = bit_lp_getsda, + .getscl = bit_lp_getscl, + .udelay = 80, + .mdelay = 80, + .timeout = HZ +}; + +static struct i2c_algo_bit_data bit_lp_data2 = { + .setsda = bit_lp_setsda2, + .setscl = bit_lp_setscl2, + .getsda = bit_lp_getsda2, + .udelay = 80, + .mdelay = 80, + .timeout = HZ +}; + +static struct i2c_adapter bit_lp_ops = { + .owner = THIS_MODULE, + .id = I2C_HW_B_LP, + .name = "Philips Parallel port adapter", +}; + +static void i2c_parport_attach (struct parport *port) +{ + struct i2c_par *adapter = kmalloc(sizeof(struct i2c_par), + GFP_KERNEL); + if (!adapter) { + printk(KERN_ERR "i2c-philips-par: Unable to malloc.\n"); + return; + } + memset (adapter, 0x00, sizeof(struct i2c_par)); + + /* printk(KERN_DEBUG "i2c-philips-par.o: attaching to %s\n", port->name); */ + + adapter->pdev = parport_register_device(port, "i2c-philips-par", + NULL, NULL, NULL, + PARPORT_FLAG_EXCL, + NULL); + if (!adapter->pdev) { + printk(KERN_ERR "i2c-philips-par: Unable to register with parport.\n"); + kfree(adapter); + return; + } + + adapter->adapter = bit_lp_ops; + adapter->adapter.algo_data = &adapter->bit_lp_data; + adapter->bit_lp_data = type ? bit_lp_data2 : bit_lp_data; + adapter->bit_lp_data.data = port; + + if (parport_claim_or_block(adapter->pdev) < 0 ) { + printk(KERN_ERR "i2c-philips-par: Could not claim parallel port.\n"); + kfree(adapter); + return; + } + /* reset hardware to sane state */ + bit_lp_setsda(port, 1); + bit_lp_setscl(port, 1); + parport_release(adapter->pdev); + + if (i2c_bit_add_bus(&adapter->adapter) < 0) { + printk(KERN_ERR "i2c-philips-par: Unable to register with I2C.\n"); + parport_unregister_device(adapter->pdev); + kfree(adapter); + return; /* No good */ + } + + adapter->next = adapter_list; + adapter_list = adapter; +} + +static void i2c_parport_detach (struct parport *port) +{ + struct i2c_par *adapter, *prev = NULL; + + for (adapter = adapter_list; adapter; adapter = adapter->next) { + if (adapter->pdev->port == port) { + parport_unregister_device(adapter->pdev); + i2c_bit_del_bus(&adapter->adapter); + if (prev) + prev->next = adapter->next; + else + adapter_list = adapter->next; + kfree(adapter); + return; + } + prev = adapter; + } +} + +static struct parport_driver i2c_driver = { + .name = "i2c-philips-par", + .attach = i2c_parport_attach, + .detach = i2c_parport_detach, +}; + +int __init i2c_bitlp_init(void) +{ + printk(KERN_INFO "i2c Philips parallel port adapter driver\n"); + + return parport_register_driver(&i2c_driver); +} + +void __exit i2c_bitlp_exit(void) +{ + parport_unregister_driver(&i2c_driver); +} + +MODULE_AUTHOR("Simon G. Vogl "); +MODULE_DESCRIPTION("I2C-Bus adapter routines for Philips parallel port adapter"); +MODULE_LICENSE("GPL"); + +MODULE_PARM(type, "i"); + +module_init(i2c_bitlp_init); +module_exit(i2c_bitlp_exit); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-piix4.c i2c-2.5/drivers/i2c/busses/i2c-piix4.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-piix4.c Mon Sep 8 19:49:59 2003 +++ i2c-2.5/drivers/i2c/busses/i2c-piix4.c Tue Sep 23 10:12:59 2003 @@ -395,7 +395,6 @@ static struct i2c_adapter piix4_adapter = { .owner = THIS_MODULE, - .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_PIIX4, .class = I2C_ADAP_CLASS_SMBUS, .algo = &smbus_algorithm, .name = "unset", @@ -451,7 +450,7 @@ /* set up the driverfs linkage to our parent device */ piix4_adapter.dev.parent = &dev->dev; - snprintf(piix4_adapter.name, DEVICE_NAME_SIZE, + snprintf(piix4_adapter.name, I2C_NAME_SIZE, "SMBus PIIX4 adapter at %04x", piix4_smba); retval = i2c_add_adapter(&piix4_adapter); @@ -474,7 +473,6 @@ static int __init i2c_piix4_init(void) { - printk(KERN_INFO "i2c-piix4 version %s (%s)\n", I2C_VERSION, I2C_DATE); return pci_module_init(&piix4_driver); } diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-prosavage.c i2c-2.5/drivers/i2c/busses/i2c-prosavage.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-prosavage.c Thu Jan 1 00:00:00 1970 +++ i2c-2.5/drivers/i2c/busses/i2c-prosavage.c Tue Sep 23 10:12:59 2003 @@ -0,0 +1,338 @@ +/* + * kernel/busses/i2c-prosavage.c + * + * i2c bus driver for S3/VIA 8365/8375 graphics processor. + * Copyright (c) 2003 Henk Vergonet + * Based on code written by: + * Frodo Looijaard , + * Philip Edelbrock , + * Ralph Metzler , and + * Mark D. Studebaker + * Simon Vogl + * and others + * + * Please read the lm_sensors documentation for details on use. + * + * 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. + * + */ +/* 18-05-2003 HVE - created + * 14-06-2003 HVE - adapted for lm_sensors2 + * 17-06-2003 HVE - linux 2.5.xx compatible + * 18-06-2003 HVE - codingstyle + * 21-06-2003 HVE - compatibility lm_sensors2 and linux 2.5.xx + * codingstyle, mmio enabled + * + * This driver interfaces to the I2C bus of the VIA north bridge embedded + * ProSavage4/8 devices. Usefull for gaining access to the TV Encoder chips. + * + * Graphics cores: + * S3/VIA KM266/VT8375 aka ProSavage8 + * S3/VIA KM133/VT8365 aka Savage4 + * + * Two serial busses are implemented: + * SERIAL1 - I2C serial communications interface + * SERIAL2 - DDC2 monitor communications interface + * + * Tested on a FX41 mainboard, see http://www.shuttle.com + * + * + * TODO: + * - integration with prosavage framebuffer device + * (Additional documentation needed :( + */ + +#include +#include +#include +#include +#include + + +/* + * driver configuration + */ +#define MAX_BUSSES 2 + +struct s_i2c_bus { + void *mmvga; + int i2c_reg; + int adap_ok; + struct i2c_adapter adap; + struct i2c_algo_bit_data algo; +}; + +struct s_i2c_chip { + void *mmio; + struct s_i2c_bus i2c_bus[MAX_BUSSES]; +}; + + +/* + * i2c configuration + */ +#ifndef I2C_HW_B_S3VIA +#define I2C_HW_B_S3VIA 0x18 /* S3VIA ProSavage adapter */ +#endif + +/* delays */ +#define CYCLE_DELAY 10 +#define TIMEOUT (HZ / 2) + + +/* + * S3/VIA 8365/8375 registers + */ +#ifndef PCI_DEVICE_ID_S3_SAVAGE4 +#define PCI_DEVICE_ID_S3_SAVAGE4 0x8a25 +#endif +#ifndef PCI_DEVICE_ID_S3_PROSAVAGE8 +#define PCI_DEVICE_ID_S3_PROSAVAGE8 0x8d04 +#endif + +#define VGA_CR_IX 0x3d4 +#define VGA_CR_DATA 0x3d5 + +#define CR_SERIAL1 0xa0 /* I2C serial communications interface */ +#define MM_SERIAL1 0xff20 +#define CR_SERIAL2 0xb1 /* DDC2 monitor communications interface */ + +/* based on vt8365 documentation */ +#define I2C_ENAB 0x10 +#define I2C_SCL_OUT 0x01 +#define I2C_SDA_OUT 0x02 +#define I2C_SCL_IN 0x04 +#define I2C_SDA_IN 0x08 + +#define SET_CR_IX(p, val) writeb((val), (p)->mmvga + VGA_CR_IX) +#define SET_CR_DATA(p, val) writeb((val), (p)->mmvga + VGA_CR_DATA) +#define GET_CR_DATA(p) readb((p)->mmvga + VGA_CR_DATA) + + +/* + * Serial bus line handling + * + * serial communications register as parameter in private data + * + * TODO: locks with other code sections accessing video registers? + */ +static void bit_s3via_setscl(void *bus, int val) +{ + struct s_i2c_bus *p = (struct s_i2c_bus *)bus; + unsigned int r; + + SET_CR_IX(p, p->i2c_reg); + r = GET_CR_DATA(p); + r |= I2C_ENAB; + if (val) { + r |= I2C_SCL_OUT; + } else { + r &= ~I2C_SCL_OUT; + } + SET_CR_DATA(p, r); +} + +static void bit_s3via_setsda(void *bus, int val) +{ + struct s_i2c_bus *p = (struct s_i2c_bus *)bus; + unsigned int r; + + SET_CR_IX(p, p->i2c_reg); + r = GET_CR_DATA(p); + r |= I2C_ENAB; + if (val) { + r |= I2C_SDA_OUT; + } else { + r &= ~I2C_SDA_OUT; + } + SET_CR_DATA(p, r); +} + +static int bit_s3via_getscl(void *bus) +{ + struct s_i2c_bus *p = (struct s_i2c_bus *)bus; + + SET_CR_IX(p, p->i2c_reg); + return (0 != (GET_CR_DATA(p) & I2C_SCL_IN)); +} + +static int bit_s3via_getsda(void *bus) +{ + struct s_i2c_bus *p = (struct s_i2c_bus *)bus; + + SET_CR_IX(p, p->i2c_reg); + return (0 != (GET_CR_DATA(p) & I2C_SDA_IN)); +} + + +/* + * adapter initialisation + */ +static int i2c_register_bus(struct pci_dev *dev, struct s_i2c_bus *p, u8 *mmvga, u32 i2c_reg) +{ + int ret; + p->adap.owner = THIS_MODULE; + p->adap.id = I2C_HW_B_S3VIA; + p->adap.algo_data = &p->algo; + p->adap.dev.parent = &dev->dev; + p->algo.setsda = bit_s3via_setsda; + p->algo.setscl = bit_s3via_setscl; + p->algo.getsda = bit_s3via_getsda; + p->algo.getscl = bit_s3via_getscl; + p->algo.udelay = CYCLE_DELAY; + p->algo.mdelay = CYCLE_DELAY; + p->algo.timeout = TIMEOUT; + p->algo.data = p; + p->mmvga = mmvga; + p->i2c_reg = i2c_reg; + + ret = i2c_bit_add_bus(&p->adap); + if (ret) { + return ret; + } + + p->adap_ok = 1; + return 0; +} + + +/* + * Cleanup stuff + */ +static void __devexit prosavage_remove(struct pci_dev *dev) +{ + struct s_i2c_chip *chip; + int i, ret; + + chip = (struct s_i2c_chip *)pci_get_drvdata(dev); + + if (!chip) { + return; + } + for (i = MAX_BUSSES - 1; i >= 0; i--) { + if (chip->i2c_bus[i].adap_ok == 0) + continue; + + ret = i2c_bit_del_bus(&chip->i2c_bus[i].adap); + if (ret) { + dev_err(&dev->dev, ": %s not removed\n", + chip->i2c_bus[i].adap.name); + } + } + if (chip->mmio) { + iounmap(chip->mmio); + } + kfree(chip); +} + + +/* + * Detect chip and initialize it + */ +static int __devinit prosavage_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + int ret; + unsigned long base, len; + struct s_i2c_chip *chip; + struct s_i2c_bus *bus; + + pci_set_drvdata(dev, kmalloc(sizeof(struct s_i2c_chip), GFP_KERNEL)); + chip = (struct s_i2c_chip *)pci_get_drvdata(dev); + if (chip == NULL) { + return -ENOMEM; + } + + memset(chip, 0, sizeof(struct s_i2c_chip)); + + base = dev->resource[0].start & PCI_BASE_ADDRESS_MEM_MASK; + len = dev->resource[0].end - base + 1; + chip->mmio = ioremap_nocache(base, len); + + if (chip->mmio == NULL) { + dev_err(&dev->dev, "ioremap failed\n"); + prosavage_remove(dev); + return -ENODEV; + } + + + /* + * Chip initialisation + */ + /* Unlock Extended IO Space ??? */ + + + /* + * i2c bus registration + */ + bus = &chip->i2c_bus[0]; + snprintf(bus->adap.name, sizeof(bus->adap.name), + "ProSavage I2C bus at %02x:%02x.%x", + dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + ret = i2c_register_bus(dev, bus, chip->mmio + 0x8000, CR_SERIAL1); + if (ret) { + goto err_adap; + } + /* + * ddc bus registration + */ + bus = &chip->i2c_bus[1]; + snprintf(bus->adap.name, sizeof(bus->adap.name), + "ProSavage DDC bus at %02x:%02x.%x", + dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + ret = i2c_register_bus(dev, bus, chip->mmio + 0x8000, CR_SERIAL2); + if (ret) { + goto err_adap; + } + return 0; +err_adap: + dev_err(&dev->dev, ": %s failed\n", bus->adap.name); + prosavage_remove(dev); + return ret; +} + + +/* + * Data for PCI driver interface + */ +static struct pci_device_id prosavage_pci_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_SAVAGE4) }, + { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_PROSAVAGE8) }, + { 0, }, +}; + +static struct pci_driver prosavage_driver = { + .name = "prosavage-smbus", + .id_table = prosavage_pci_tbl, + .probe = prosavage_probe, + .remove = __devexit_p(prosavage_remove), +}; + +static int __init i2c_prosavage_init(void) +{ + return pci_module_init(&prosavage_driver); +} + +static void __exit i2c_prosavage_exit(void) +{ + pci_unregister_driver(&prosavage_driver); +} + +MODULE_DEVICE_TABLE(pci, prosavage_pci_tbl); +MODULE_AUTHOR("Henk Vergonet"); +MODULE_DESCRIPTION("ProSavage VIA 8365/8375 smbus driver"); +MODULE_LICENSE("GPL"); + +module_init (i2c_prosavage_init); +module_exit (i2c_prosavage_exit); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-rpx.c i2c-2.5/drivers/i2c/busses/i2c-rpx.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-rpx.c Thu Jan 1 00:00:00 1970 +++ i2c-2.5/drivers/i2c/busses/i2c-rpx.c Tue Sep 23 10:12:59 2003 @@ -0,0 +1,103 @@ +/* + * Embedded Planet RPX Lite MPC8xx CPM I2C interface. + * Copyright (c) 1999 Dan Malek (dmalek@jlc.net). + * + * moved into proper i2c interface; + * Brad Parker (brad@heeltoe.com) + * + * RPX lite specific parts of the i2c interface + * Update: There actually isn't anything RPXLite-specific about this module. + * This should work for most any 8xx board. The console messages have been + * changed to eliminate RPXLite references. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static void +rpx_iic_init(struct i2c_algo_8xx_data *data) +{ + volatile cpm8xx_t *cp; + volatile immap_t *immap; + + cp = cpmp; /* Get pointer to Communication Processor */ + immap = (immap_t *)IMAP_ADDR; /* and to internal registers */ + + data->iip = (iic_t *)&cp->cp_dparam[PROFF_IIC]; + + /* Check for and use a microcode relocation patch. + */ + if ((data->reloc = data->iip->iic_rpbase)) + data->iip = (iic_t *)&cp->cp_dpmem[data->iip->iic_rpbase]; + + data->i2c = (i2c8xx_t *)&(immap->im_i2c); + data->cp = cp; + + /* Initialize Port B IIC pins. + */ + cp->cp_pbpar |= 0x00000030; + cp->cp_pbdir |= 0x00000030; + cp->cp_pbodr |= 0x00000030; + + /* Allocate space for two transmit and two receive buffer + * descriptors in the DP ram. + */ + data->dp_addr = m8xx_cpm_dpalloc(sizeof(cbd_t) * 4); + + /* ptr to i2c area */ + data->i2c = (i2c8xx_t *)&(((immap_t *)IMAP_ADDR)->im_i2c); +} + +static int rpx_install_isr(int irq, void (*func)(void *, void *), void *data) +{ + /* install interrupt handler */ + cpm_install_handler(irq, (void (*)(void *, struct pt_regs *)) func, data); + + return 0; +} + +static struct i2c_algo_8xx_data rpx_data = { + .setisr = rpx_install_isr +}; + +static struct i2c_adapter rpx_ops = { + .owner = THIS_MODULE, + .name = "m8xx", + .id = I2C_HW_MPC8XX_EPON, + .algo_data = &rpx_data, +}; + +int __init i2c_rpx_init(void) +{ + printk(KERN_INFO "i2c-rpx: i2c MPC8xx driver\n"); + + /* reset hardware to sane state */ + rpx_iic_init(&rpx_data); + + if (i2c_8xx_add_bus(&rpx_ops) < 0) { + printk("i2c-rpx: Unable to register with I2C\n"); + return -ENODEV; + } + + return 0; +} + +void __exit i2c_rpx_exit(void) +{ + i2c_8xx_del_bus(&rpx_ops); +} + +MODULE_AUTHOR("Dan Malek "); +MODULE_DESCRIPTION("I2C-Bus adapter routines for MPC8xx boards"); + +module_init(i2c_rpx_init); +module_exit(i2c_rpx_exit); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-savage4.c i2c-2.5/drivers/i2c/busses/i2c-savage4.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-savage4.c Thu Jan 1 00:00:00 1970 +++ i2c-2.5/drivers/i2c/busses/i2c-savage4.c Tue Sep 23 10:12:59 2003 @@ -0,0 +1,205 @@ +/* + i2c-savage4.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 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 + +/* 3DFX defines */ +#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 0x04 + +/* delays */ +#define CYCLE_DELAY 10 +#define TIMEOUT (HZ / 2) + + +static void *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 */ + +static int config_s4(struct pci_dev *dev) +{ + unsigned int cadr; + + /* map memory */ + cadr = dev->resource[0].start; + cadr &= PCI_BASE_ADDRESS_MEM_MASK; + ioaddr = ioremap_nocache(cadr, 0x0080000); + if (ioaddr) { + /* writel(0x8160, ioaddr + REG2); */ + writel(0x00000020, ioaddr + REG); + dev_info(&dev->dev, "Using Savage4 at %p\n", ioaddr); + return 0; + } + return -ENODEV; +} + +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 = { + .owner = THIS_MODULE, + .name = "I2C Savage4 adapter", + .algo_data = &sav_i2c_bit_data, +}; + +static struct pci_device_id savage4_ids[] __devinitdata = { + { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE4) }, + { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE2000) }, + { 0, } +}; + +static int __devinit savage4_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + int retval; + + retval = config_s4(dev); + if (retval) + return retval; + + /* set up the sysfs linkage to our parent device */ + savage4_i2c_adapter.dev.parent = &dev->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); + iounmap(ioaddr); +} + +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) +{ + return pci_module_init(&savage4_driver); +} + +static void __exit i2c_savage4_exit(void) +{ + pci_unregister_driver(&savage4_driver); +} + +MODULE_AUTHOR("Frodo Looijaard , " + "Philip Edelbrock , " + "Ralph Metzler , " + "and Mark D. Studebaker "); +MODULE_DESCRIPTION("Savage4 I2C/SMBus driver"); +MODULE_LICENSE("GPL"); + +module_init(i2c_savage4_init); +module_exit(i2c_savage4_exit); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-sis5595.c i2c-2.5/drivers/i2c/busses/i2c-sis5595.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-sis5595.c Thu Jan 1 00:00:00 1970 +++ i2c-2.5/drivers/i2c/busses/i2c-sis5595.c Tue Sep 23 10:12:59 2003 @@ -0,0 +1,416 @@ +/* + 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 + */ + +/* #define DEBUG 1 */ + +#include +#include +#include +#include +#include +#include + +static int blacklist[] = { + PCI_DEVICE_ID_SI_540, + PCI_DEVICE_ID_SI_550, + PCI_DEVICE_ID_SI_630, + PCI_DEVICE_ID_SI_645, + PCI_DEVICE_ID_SI_646, + PCI_DEVICE_ID_SI_648, + PCI_DEVICE_ID_SI_650, + PCI_DEVICE_ID_SI_651, + PCI_DEVICE_ID_SI_730, + PCI_DEVICE_ID_SI_735, + PCI_DEVICE_ID_SI_745, + PCI_DEVICE_ID_SI_746, + 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, + 0, /* terminates the list */ +}; + +/* 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 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); +} + +static int sis5595_setup(struct pci_dev *SIS5595_dev) +{ + u16 a; + u8 val; + int *i; + int retval = -ENODEV; + + /* Look for imposters */ + for (i = blacklist; *i != 0; i++) { + struct pci_dev *dev; + dev = pci_get_device(PCI_VENDOR_ID_SI, *i, NULL); + if (dev) { + dev_err(&SIS5595_dev->dev, "Looked for SIS5595 but found unsupported device %.4x\n", *i); + pci_dev_put(dev); + 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) { + dev_err(&SIS5595_dev->dev, "ACPI base address uninitialized - upgrade BIOS or use force_addr=0xaddr\n"); + return -ENODEV; + } + + if (force_addr) + sis5595_base = force_addr & ~(SIS5595_EXTENT - 1); + dev_dbg(&SIS5595_dev->dev, "ACPI Base address: %04x\n", sis5595_base); + + /* NB: We grab just the two SMBus registers here, but this may still + * interfere with ACPI :-( */ + if (!request_region(sis5595_base + SMB_INDEX, 2, "sis5595-smbus")) { + dev_err(&SIS5595_dev->dev, "SMBus registers 0x%04x-0x%04x already in use!\n", + sis5595_base + SMB_INDEX, sis5595_base + SMB_INDEX + 1); + return -ENODEV; + } + + if (force_addr) { + dev_info(&SIS5595_dev->dev, "forcing ISA address 0x%04X\n", sis5595_base); + if (!pci_write_config_word(SIS5595_dev, ACPI_BASE, sis5595_base)) + goto error; + if (!pci_read_config_word(SIS5595_dev, ACPI_BASE, &a)) + goto error; + if ((a & ~(SIS5595_EXTENT - 1)) != sis5595_base) { + /* doesn't work for some chips! */ + dev_err(&SIS5595_dev->dev, "force address failed - not supported?\n"); + goto error; + } + } + + if (!pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val)) + goto error; + if ((val & 0x80) == 0) { + dev_info(&SIS5595_dev->dev, "enabling ACPI\n"); + if (!pci_write_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, val | 0x80)) + goto error; + if (!pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val)) + goto error; + if ((val & 0x80) == 0) { + /* doesn't work for some chips? */ + dev_err(&SIS5595_dev->dev, "ACPI enable failed - not supported?\n"); + goto error; + } + } + + /* Everything is happy */ + return 0; + +error: + release_region(sis5595_base + SMB_INDEX, 2); + return retval; +} + +static int sis5595_transaction(struct i2c_adapter *adap) +{ + int temp; + int result = 0; + int timeout = 0; + + /* Make sure the SMBus host is ready to start transmitting */ + temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8); + if (temp != 0x00) { + dev_dbg(&adap->dev, "SMBus busy (%04x). Resetting... \n", temp); + 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) { + dev_dbg(&adap->dev, "Failed! (%02x)\n", temp); + return -1; + } else { + dev_dbg(&adap->dev, "Successfull!\n"); + } + } + + /* 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) { + dev_dbg(&adap->dev, "SMBus Timeout!\n"); + result = -1; + } + + if (temp & 0x10) { + dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); + result = -1; + } + + if (temp & 0x20) { + dev_err(&adap->dev, "Bus collision! SMBus may be locked until " + "next hard reset (or not...)\n"); + /* Clock stops and slave is stuck in mid-transmission */ + result = -1; + } + + temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8); + if (temp != 0x00) { + sis5595_write(SMB_STS_LO, temp & 0xff); + sis5595_write(SMB_STS_HI, temp >> 8); + } + + temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8); + if (temp != 0x00) + dev_dbg(&adap->dev, "Failed reset at end of transaction (%02x)\n", temp); + + return result; +} + +/* Return -1 on error. */ +static 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(adap)) + 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 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 = { + .owner = THIS_MODULE, + .name = "unset", + .algo = &smbus_algorithm, +}; + +static struct pci_device_id sis5595_ids[] __devinitdata = { + { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) }, + { 0, } +}; + +static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + if (sis5595_setup(dev)) { + dev_err(&dev->dev, "SIS5595 not detected, module not inserted.\n"); + return -ENODEV; + } + + /* set up the driverfs linkage to our parent device */ + sis5595_adapter.dev.parent = &dev->dev; + + sprintf(sis5595_adapter.name, "SMBus SIS5595 adapter at %04x", + sis5595_base + SMB_INDEX); + return i2c_add_adapter(&sis5595_adapter); +} + +static void __devexit sis5595_remove(struct pci_dev *dev) +{ + i2c_del_adapter(&sis5595_adapter); +} + +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) +{ + return pci_module_init(&sis5595_driver); +} + +static void __exit i2c_sis5595_exit(void) +{ + pci_unregister_driver(&sis5595_driver); + release_region(sis5595_base + SMB_INDEX, 2); +} + +MODULE_AUTHOR("Frodo Looijaard "); +MODULE_DESCRIPTION("SIS5595 SMBus driver"); +MODULE_LICENSE("GPL"); + +module_init(i2c_sis5595_init); +module_exit(i2c_sis5595_exit); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-sis630.c i2c-2.5/drivers/i2c/busses/i2c-sis630.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-sis630.c Thu Jan 1 00:00:00 1970 +++ i2c-2.5/drivers/i2c/busses/i2c-sis630.c Tue Sep 23 10:12:59 2003 @@ -0,0 +1,493 @@ +/* + 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 are 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. +*/ + +/* #define DEBUG 1 */ + +#include +#include +#include +#include +#include +#include + + +/* 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 + +/* insmod parameters */ +static int high_clock = 0; +MODULE_PARM(high_clock, "i"); +MODULE_PARM_DESC(high_clock, "Set Host Master Clock to 56KHz (default 14KHz)."); + + +static unsigned short acpi_base = 0; + +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(struct i2c_adapter *adap, int size, u8 *oldclock) +{ + int temp; + + /* Make sure the SMBus host is ready to start transmitting. */ + if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) { + dev_dbg(&adap->dev, "SMBus busy (%02x).Resetting...\n",temp); + /* kill smbus transaction */ + sis630_write(SMBHOST_CNT, 0x20); + + if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) { + dev_dbg(&adap->dev, "Failed! (%02x)\n", temp); + return -1; + } else { + dev_dbg(&adap->dev, "Successfull!\n"); + } + } + + /* save old clock, so we can prevent machine for hung */ + *oldclock = sis630_read(SMB_CNT); + + dev_dbg(&adap->dev, "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(struct i2c_adapter *adap, 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) { + dev_dbg(&adap->dev, "SMBus Timeout!\n"); + result = -1; + } + + if (temp & 0x02) { + dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); + result = -1; + } + + if (temp & 0x04) { + dev_err(&adap->dev, "Bus collision!\n"); + result = -1; + /* + 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(struct i2c_adapter *adap, u8 oldclock) +{ + int temp = 0; + + /* clear all status "sticky" bits */ + sis630_write(SMB_STS, temp); + + dev_dbg(&adap->dev, "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)); + + dev_dbg(&adap->dev, "SMB_CNT after clock restore 0x%02x\n", sis630_read(SMB_CNT)); +} + +static int sis630_transaction(struct i2c_adapter *adap, int size) +{ + int result = 0; + u8 oldclock = 0; + + result = sis630_transaction_start(adap, size, &oldclock); + if (!result) { + result = sis630_transaction_wait(adap, size); + sis630_transaction_end(adap, oldclock); + } + + return result; +} + +static int sis630_block_data(struct i2c_adapter *adap, 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++) { + dev_dbg(&adap->dev, "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)) { + dev_dbg(&adap->dev, "start trans len=%d i=%d\n",len ,i); + /* first transaction */ + if (sis630_transaction_start(adap, SIS630_BLOCK_DATA, &oldclock)) + return -1; + } + else if ((i-1)%8 == 7 || i==len) { + dev_dbg(&adap->dev, "trans_wait len=%d i=%d\n",len,i); + if (i>8) { + dev_dbg(&adap->dev, "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(adap, SIS630_BLOCK_DATA)) { + dev_dbg(&adap->dev, "trans_wait failed\n"); + rc = -1; + break; + } + } + } + } + else { + /* read request */ + data->block[0] = len = 0; + if (sis630_transaction_start(adap, SIS630_BLOCK_DATA, &oldclock)) { + return -1; + } + do { + if (sis630_transaction_wait(adap, SIS630_BLOCK_DATA)) { + dev_dbg(&adap->dev, "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); + + dev_dbg(&adap->dev, "block data read len=0x%x\n", data->block[0]); + + for (i=0; i < 8 && len < data->block[0]; i++,len++) { + dev_dbg(&adap->dev, "read i=%d len=%d\n", i, len); + data->block[len+1] = sis630_read(SMB_BYTE+i); + } + + dev_dbg(&adap->dev, "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(adap, 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(adap, data, read_write); + default: + printk("Unsupported I2C size\n"); + return -1; + break; + } + + if (sis630_transaction(adap, 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 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 sis630_setup(struct pci_dev *dummy) +{ + unsigned char b; + struct pci_dev *sis630_dev = NULL; + int retval = -ENODEV; + + /* We need ISA bridge and not pci device passed in. */ + sis630_dev = pci_get_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, sis630_dev); + if (!sis630_dev) { + dev_err(&dummy->dev, "Error: Can't detect 85C503/5513 ISA bridge!\n"); + return -ENODEV; + } + + /* + Enable ACPI first , so we can accsess reg 74-75 + in acpi io space and read acpi base addr + */ + if (!pci_read_config_byte(sis630_dev, SIS630_BIOS_CTL_REG,&b)) { + dev_err(&sis630_dev->dev, "Error: Can't read bios ctl reg\n"); + goto exit; + } + + /* if ACPI already enabled , do nothing */ + if (!(b & 0x80) && + !pci_write_config_byte(sis630_dev, SIS630_BIOS_CTL_REG, b | 0x80)) { + dev_err(&sis630_dev->dev, "Error: Can't enable ACPI\n"); + goto exit; + } + /* Determine the ACPI base address */ + if (!pci_read_config_word(sis630_dev,SIS630_ACPI_BASE_REG,&acpi_base)) { + dev_err(&sis630_dev->dev, "Error: Can't determine ACPI base address\n"); + goto exit; + } + + dev_dbg(&sis630_dev->dev, "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-smbus")) { + dev_err(&sis630_dev->dev, "SMBus registers 0x%04x-0x%04x already " + "in use!\n", acpi_base + SMB_STS, acpi_base + SMB_SAA); + goto exit; + } + + retval = 0; + +exit: + pci_dev_put(sis630_dev); + return retval; +} + + +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 = { + .owner = THIS_MODULE, + .name = "unset", + .algo = &smbus_algorithm, +}; + +static struct pci_device_id sis630_ids[] __devinitdata = { + { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630) }, + { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_730) }, + { 0, } +}; + +static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + + if (sis630_setup(dev)) { + dev_err(&dev->dev, "SIS630 comp. bus not detected, module not inserted.\n"); + return -ENODEV; + } + + /* set up the driverfs linkage to our parent device */ + sis630_adapter.dev.parent = &dev->dev; + + 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) +{ + i2c_del_adapter(&sis630_adapter); +} + + +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) +{ + return pci_module_init(&sis630_driver); +} + + +static void __exit i2c_sis630_exit(void) +{ + pci_unregister_driver(&sis630_driver); + release_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION); +} + + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Alexander Malysh "); +MODULE_DESCRIPTION("SIS630 SMBus driver"); + +module_init(i2c_sis630_init); +module_exit(i2c_sis630_exit); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-sis96x.c i2c-2.5/drivers/i2c/busses/i2c-sis96x.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-sis96x.c Mon Sep 8 19:49:59 2003 +++ i2c-2.5/drivers/i2c/busses/i2c-sis96x.c Tue Sep 23 10:12:59 2003 @@ -261,7 +261,6 @@ static struct i2c_adapter sis96x_adapter = { .owner = THIS_MODULE, - .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_SIS96X, .class = I2C_ADAP_CLASS_SMBUS, .algo = &smbus_algorithm, .name = "unset", @@ -318,7 +317,7 @@ /* set up the driverfs linkage to our parent device */ sis96x_adapter.dev.parent = &dev->dev; - snprintf(sis96x_adapter.name, DEVICE_NAME_SIZE, + snprintf(sis96x_adapter.name, I2C_NAME_SIZE, "SiS96x SMBus adapter at 0x%04x", sis96x_smbus_base); if ((retval = i2c_add_adapter(&sis96x_adapter))) { diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-velleman.c i2c-2.5/drivers/i2c/busses/i2c-velleman.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-velleman.c Thu Jan 1 00:00:00 1970 +++ i2c-2.5/drivers/i2c/busses/i2c-velleman.c Tue Sep 23 10:12:59 2003 @@ -0,0 +1,160 @@ +/* ------------------------------------------------------------------------- */ +/* i2c-velleman.c i2c-hw access for Velleman K9000 adapters */ +/* ------------------------------------------------------------------------- */ +/* Copyright (C) 1995-96, 2000 Simon G. 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. */ +/* ------------------------------------------------------------------------- */ + +/* $Id$ */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* ----- global defines ----------------------------------------------- */ +#define DEB(x) /* should be reasonable open, close &c. */ +#define DEB2(x) /* low level debugging - very slow */ +#define DEBE(x) x /* error messages */ + + /* Pin Port Inverted name */ +#define I2C_SDA 0x02 /* ctrl bit 1 (inv) */ +#define I2C_SCL 0x08 /* ctrl bit 3 (inv) */ + +#define I2C_SDAIN 0x10 /* stat bit 4 */ +#define I2C_SCLIN 0x08 /* ctrl bit 3 (inv)(reads own output)*/ + +#define I2C_DMASK 0xfd +#define I2C_CMASK 0xf7 + + +/* --- Convenience defines for the parallel port: */ +#define BASE (unsigned int)(data) +#define DATA BASE /* Centronics data port */ +#define STAT (BASE+1) /* Centronics status port */ +#define CTRL (BASE+2) /* Centronics control port */ + +#define DEFAULT_BASE 0x378 +static int base=0; + +/* ----- local functions --------------------------------------------------- */ + +static void bit_velle_setscl(void *data, int state) +{ + if (state) { + outb(inb(CTRL) & I2C_CMASK, CTRL); + } else { + outb(inb(CTRL) | I2C_SCL, CTRL); + } + +} + +static void bit_velle_setsda(void *data, int state) +{ + if (state) { + outb(inb(CTRL) & I2C_DMASK , CTRL); + } else { + outb(inb(CTRL) | I2C_SDA, CTRL); + } + +} + +static int bit_velle_getscl(void *data) +{ + return ( 0 == ( (inb(CTRL)) & I2C_SCLIN ) ); +} + +static int bit_velle_getsda(void *data) +{ + return ( 0 != ( (inb(STAT)) & I2C_SDAIN ) ); +} + +static int bit_velle_init(void) +{ + if (!request_region(base, (base == 0x3bc) ? 3 : 8, + "i2c (Vellemann adapter)")) + return -ENODEV; + + bit_velle_setsda((void*)base,1); + bit_velle_setscl((void*)base,1); + return 0; +} + +/* ------------------------------------------------------------------------ + * Encapsulate the above functions in the correct operations structure. + * This is only done when more than one hardware adapter is supported. + */ + +static struct i2c_algo_bit_data bit_velle_data = { + .setsda = bit_velle_setsda, + .setscl = bit_velle_setscl, + .getsda = bit_velle_getsda, + .getscl = bit_velle_getscl, + .udelay = 10, + .mdelay = 10, + .timeout = HZ +}; + +static struct i2c_adapter bit_velle_ops = { + .owner = THIS_MODULE, + .algo_data = &bit_velle_data, + .name = "Velleman K8000", +}; + +static int __init i2c_bitvelle_init(void) +{ + printk(KERN_INFO "i2c-velleman: i2c Velleman K8000 driver\n"); + if (base==0) { + /* probe some values */ + base=DEFAULT_BASE; + bit_velle_data.data=(void*)DEFAULT_BASE; + if (bit_velle_init()==0) { + if(i2c_bit_add_bus(&bit_velle_ops) < 0) + return -ENODEV; + } else { + return -ENODEV; + } + } else { + bit_velle_data.data=(void*)base; + if (bit_velle_init()==0) { + if(i2c_bit_add_bus(&bit_velle_ops) < 0) + return -ENODEV; + } else { + return -ENODEV; + } + } + printk(KERN_DEBUG "i2c-velleman: found device at %#x.\n",base); + return 0; +} + +static void __exit i2c_bitvelle_exit(void) +{ + i2c_bit_del_bus(&bit_velle_ops); + release_region(base, (base == 0x3bc) ? 3 : 8); +} + +MODULE_AUTHOR("Simon G. Vogl "); +MODULE_DESCRIPTION("I2C-Bus adapter routines for Velleman K8000 adapter"); +MODULE_LICENSE("GPL"); + +MODULE_PARM(base, "i"); + +module_init(i2c_bitvelle_init); +module_exit(i2c_bitvelle_exit); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-via.c i2c-2.5/drivers/i2c/busses/i2c-via.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-via.c Thu Jan 1 00:00:00 1970 +++ i2c-2.5/drivers/i2c/busses/i2c-via.c Tue Sep 23 10:12:59 2003 @@ -0,0 +1,182 @@ +/* + 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. +*/ + +#define DEBUG + +#include +#include +#include +#include +#include +#include +#include + +/* 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 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 = { + .owner = THIS_MODULE, + .name = "VIA i2c", + .algo_data = &bit_data, +}; + + +static struct pci_device_id vt586b_ids[] __devinitdata = { + { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3) }, + { 0, } +}; + +static int __devinit vt586b_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + u16 base; + u8 rev; + int res; + + if (pm_io_base) { + dev_err(&dev->dev, "i2c-via: Will only support one host\n"); + return -ENODEV; + } + + 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)) { + dev_err(&dev->dev, "IO 0x%x-0x%x already in use\n", I2C_DIR, I2C_DIR + IOSPACE); + return -ENODEV; + } + + outb(inb(I2C_DIR) & ~(I2C_SDA | I2C_SCL), I2C_DIR); + outb(inb(I2C_OUT) & ~(I2C_SDA | I2C_SCL), I2C_OUT); + + /* set up the driverfs linkage to our parent device */ + vt586b_adapter.dev.parent = &dev->dev; + + res = i2c_bit_add_bus(&vt586b_adapter); + if ( res < 0 ) { + release_region(I2C_DIR, IOSPACE); + pm_io_base = 0; + return res; + } + return 0; +} + +static void __devexit vt586b_remove(struct pci_dev *dev) +{ + i2c_bit_del_bus(&vt586b_adapter); + release_region(I2C_DIR, IOSPACE); + pm_io_base = 0; +} + + +static struct pci_driver vt586b_driver = { + .name = "vt586b smbus", + .id_table = vt586b_ids, + .probe = vt586b_probe, + .remove = __devexit_p(vt586b_remove), +}; + +static int __init i2c_vt586b_init(void) +{ + return pci_module_init(&vt586b_driver); +} + +static void __exit i2c_vt586b_exit(void) +{ + pci_unregister_driver(&vt586b_driver); +} + + +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 -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-viapro.c i2c-2.5/drivers/i2c/busses/i2c-viapro.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-viapro.c Mon Sep 8 19:50:18 2003 +++ i2c-2.5/drivers/i2c/busses/i2c-viapro.c Tue Sep 23 10:12:59 2003 @@ -287,7 +287,6 @@ static struct i2c_adapter vt596_adapter = { .owner = THIS_MODULE, - .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_VIA2, .class = I2C_ADAP_CLASS_SMBUS, .algo = &smbus_algorithm, .name = "unset", @@ -376,7 +375,7 @@ dev_dbg(&pdev->dev, "VT596_smba = 0x%X\n", vt596_smba); vt596_adapter.dev.parent = &pdev->dev; - snprintf(vt596_adapter.name, DEVICE_NAME_SIZE, + snprintf(vt596_adapter.name, I2C_NAME_SIZE, "SMBus Via Pro adapter at %04x", vt596_smba); return i2c_add_adapter(&vt596_adapter); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/i2c-voodoo3.c i2c-2.5/drivers/i2c/busses/i2c-voodoo3.c --- linux-2.6.0-test5/drivers/i2c/busses/i2c-voodoo3.c Thu Jan 1 00:00:00 1970 +++ i2c-2.5/drivers/i2c/busses/i2c-voodoo3.c Tue Sep 23 10:12:59 2003 @@ -0,0 +1,248 @@ +/* + 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 + +/* 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 *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)); +} + +static int config_v3(struct pci_dev *dev) +{ + unsigned int cadr; + + /* map Voodoo3 memory */ + cadr = dev->resource[0].start; + cadr &= PCI_BASE_ADDRESS_MEM_MASK; + ioaddr = ioremap_nocache(cadr, 0x1000); + if (ioaddr) { + writel(0x8160, ioaddr + REG2); + writel(0xcffc0020, ioaddr + REG); + dev_info(&dev->dev, "Using Banshee/Voodoo3 I2C device at %p\n", ioaddr); + return 0; + } + return -ENODEV; +} + +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 = { + .owner = THIS_MODULE, + .name = "I2C Voodoo3/Banshee adapter", + .algo_data = &voo_i2c_bit_data, +}; + +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 = { + .owner = THIS_MODULE, + .name = "DDC Voodoo3/Banshee adapter", + .algo_data = &voo_ddc_bit_data, +}; + +static struct pci_device_id voodoo3_ids[] __devinitdata = { + { PCI_DEVICE(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3) }, + { PCI_DEVICE(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE) }, + { 0, } +}; + +static int __devinit voodoo3_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + int retval; + + retval = config_v3(dev); + if (retval) + return retval; + + /* set up the sysfs linkage to our parent device */ + voodoo3_i2c_adapter.dev.parent = &dev->dev; + voodoo3_ddc_adapter.dev.parent = &dev->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); + iounmap(ioaddr); +} + +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) +{ + return pci_module_init(&voodoo3_driver); +} + +static void __exit i2c_voodoo3_exit(void) +{ + pci_unregister_driver(&voodoo3_driver); +} + + +MODULE_AUTHOR("Frodo Looijaard , " + "Philip Edelbrock , " + "Ralph Metzler , " + "and Mark D. Studebaker "); +MODULE_DESCRIPTION("Voodoo3 I2C/SMBus driver"); +MODULE_LICENSE("GPL"); + +module_init(i2c_voodoo3_init); +module_exit(i2c_voodoo3_exit); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/scx200_acb.c i2c-2.5/drivers/i2c/busses/scx200_acb.c --- linux-2.6.0-test5/drivers/i2c/busses/scx200_acb.c Thu Jan 1 00:00:00 1970 +++ i2c-2.5/drivers/i2c/busses/scx200_acb.c Tue Sep 23 10:12:59 2003 @@ -0,0 +1,553 @@ +/* linux/drivers/i2c/scx200_acb.c + + Copyright (c) 2001,2002 Christer Weinigel + + National Semiconductor SCx200 ACCESS.bus support + + Based on i2c-keywest.c which is: + Copyright (c) 2001 Benjamin Herrenschmidt + 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. + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define NAME "scx200_acb" + +MODULE_AUTHOR("Christer Weinigel "); +MODULE_DESCRIPTION("NatSemi SCx200 ACCESS.bus Driver"); +MODULE_LICENSE("GPL"); + +#define MAX_DEVICES 4 +static int base[MAX_DEVICES] = { 0x840 }; +MODULE_PARM(base, "1-4i"); +MODULE_PARM_DESC(base, "Base addresses for the ACCESS.bus controllers"); + +#define DEBUG 0 + +#if DEBUG +#define DBG(x...) printk(KERN_DEBUG NAME ": " x) +#else +#define DBG(x...) +#endif + +/* The hardware supports interrupt driven mode too, but I haven't + implemented that. */ +#define POLLED_MODE 1 +#define POLL_TIMEOUT (HZ) + +enum scx200_acb_state { + state_idle, + state_address, + state_command, + state_repeat_start, + state_quick, + state_read, + state_write, +}; + +static const char *scx200_acb_state_name[] = { + "idle", + "address", + "command", + "repeat_start", + "quick", + "read", + "write", +}; + +/* Physical interface */ +struct scx200_acb_iface +{ + struct scx200_acb_iface *next; + struct i2c_adapter adapter; + unsigned base; + struct semaphore sem; + + /* State machine data */ + enum scx200_acb_state state; + int result; + u8 address_byte; + u8 command; + u8 *ptr; + char needs_reset; + unsigned len; +}; + +/* Register Definitions */ +#define ACBSDA (iface->base + 0) +#define ACBST (iface->base + 1) +#define ACBST_SDAST 0x40 /* SDA Status */ +#define ACBST_BER 0x20 +#define ACBST_NEGACK 0x10 /* Negative Acknowledge */ +#define ACBST_STASTR 0x08 /* Stall After Start */ +#define ACBST_MASTER 0x02 +#define ACBCST (iface->base + 2) +#define ACBCST_BB 0x02 +#define ACBCTL1 (iface->base + 3) +#define ACBCTL1_STASTRE 0x80 +#define ACBCTL1_NMINTE 0x40 +#define ACBCTL1_ACK 0x10 +#define ACBCTL1_STOP 0x02 +#define ACBCTL1_START 0x01 +#define ACBADDR (iface->base + 4) +#define ACBCTL2 (iface->base + 5) +#define ACBCTL2_ENABLE 0x01 + +/************************************************************************/ + +static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) +{ + const char *errmsg; + + DBG("state %s, status = 0x%02x\n", + scx200_acb_state_name[iface->state], status); + + if (status & ACBST_BER) { + errmsg = "bus error"; + goto error; + } + if (!(status & ACBST_MASTER)) { + errmsg = "not master"; + goto error; + } + if (status & ACBST_NEGACK) + goto negack; + + switch (iface->state) { + case state_idle: + dev_warn(&iface->adapter.dev, "interrupt in idle state\n"); + break; + + case state_address: + /* Do a pointer write first */ + outb(iface->address_byte & ~1, ACBSDA); + + iface->state = state_command; + break; + + case state_command: + outb(iface->command, ACBSDA); + + if (iface->address_byte & 1) + iface->state = state_repeat_start; + else + iface->state = state_write; + break; + + case state_repeat_start: + outb(inb(ACBCTL1) | ACBCTL1_START, ACBCTL1); + /* fallthrough */ + + case state_quick: + if (iface->address_byte & 1) { + if (iface->len == 1) + outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1); + else + outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1); + outb(iface->address_byte, ACBSDA); + + iface->state = state_read; + } else { + outb(iface->address_byte, ACBSDA); + + iface->state = state_write; + } + break; + + case state_read: + /* Set ACK if receiving the last byte */ + if (iface->len == 1) + outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1); + else + outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1); + + *iface->ptr++ = inb(ACBSDA); + --iface->len; + + if (iface->len == 0) { + iface->result = 0; + iface->state = state_idle; + outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); + } + + break; + + case state_write: + if (iface->len == 0) { + iface->result = 0; + iface->state = state_idle; + outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); + break; + } + + outb(*iface->ptr++, ACBSDA); + --iface->len; + + break; + } + + return; + + negack: + DBG("negative acknowledge in state %s\n", + scx200_acb_state_name[iface->state]); + + iface->state = state_idle; + iface->result = -ENXIO; + + outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); + outb(ACBST_STASTR | ACBST_NEGACK, ACBST); + return; + + error: + dev_err(&iface->adapter.dev, "%s in state %s\n", errmsg, + scx200_acb_state_name[iface->state]); + + iface->state = state_idle; + iface->result = -EIO; + iface->needs_reset = 1; +} + +static void scx200_acb_timeout(struct scx200_acb_iface *iface) +{ + dev_err(&iface->adapter.dev, "timeout in state %s\n", + scx200_acb_state_name[iface->state]); + + iface->state = state_idle; + iface->result = -EIO; + iface->needs_reset = 1; +} + +#ifdef POLLED_MODE +static void scx200_acb_poll(struct scx200_acb_iface *iface) +{ + u8 status = 0; + unsigned long timeout; + + timeout = jiffies + POLL_TIMEOUT; + while (time_before(jiffies, timeout)) { + status = inb(ACBST); + if ((status & (ACBST_SDAST|ACBST_BER|ACBST_NEGACK)) != 0) { + scx200_acb_machine(iface, status); + return; + } + schedule_timeout(HZ/100+1); + } + + scx200_acb_timeout(iface); +} +#endif /* POLLED_MODE */ + +static void scx200_acb_reset(struct scx200_acb_iface *iface) +{ + /* Disable the ACCESS.bus device and Configure the SCL + frequency: 16 clock cycles */ + outb(0x70, ACBCTL2); + /* Polling mode */ + outb(0, ACBCTL1); + /* Disable slave address */ + outb(0, ACBADDR); + /* Enable the ACCESS.bus device */ + outb(inb(ACBCTL2) | ACBCTL2_ENABLE, ACBCTL2); + /* Free STALL after START */ + outb(inb(ACBCTL1) & ~(ACBCTL1_STASTRE | ACBCTL1_NMINTE), ACBCTL1); + /* Send a STOP */ + outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); + /* Clear BER, NEGACK and STASTR bits */ + outb(ACBST_BER | ACBST_NEGACK | ACBST_STASTR, ACBST); + /* Clear BB bit */ + outb(inb(ACBCST) | ACBCST_BB, ACBCST); +} + +static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, + u16 address, unsigned short flags, + char rw, u8 command, int size, + union i2c_smbus_data *data) +{ + struct scx200_acb_iface *iface = i2c_get_adapdata(adapter); + int len; + u8 *buffer; + u16 cur_word; + int rc; + + switch (size) { + case I2C_SMBUS_QUICK: + len = 0; + buffer = NULL; + break; + case I2C_SMBUS_BYTE: + if (rw == I2C_SMBUS_READ) { + len = 1; + buffer = &data->byte; + } else { + len = 1; + buffer = &command; + } + break; + case I2C_SMBUS_BYTE_DATA: + len = 1; + buffer = &data->byte; + break; + case I2C_SMBUS_WORD_DATA: + len = 2; + cur_word = cpu_to_le16(data->word); + buffer = (u8 *)&cur_word; + break; + case I2C_SMBUS_BLOCK_DATA: + len = data->block[0]; + buffer = &data->block[1]; + break; + default: + return -EINVAL; + } + + DBG("size=%d, address=0x%x, command=0x%x, len=%d, read=%d\n", + size, address, command, len, rw == I2C_SMBUS_READ); + + if (!len && rw == I2C_SMBUS_READ) { + dev_warn(&adapter->dev, "zero length read\n"); + return -EINVAL; + } + + if (len && !buffer) { + dev_warn(&adapter->dev, "nonzero length but no buffer\n"); + return -EFAULT; + } + + down(&iface->sem); + + iface->address_byte = address<<1; + if (rw == I2C_SMBUS_READ) + iface->address_byte |= 1; + iface->command = command; + iface->ptr = buffer; + iface->len = len; + iface->result = -EINVAL; + iface->needs_reset = 0; + + outb(inb(ACBCTL1) | ACBCTL1_START, ACBCTL1); + + if (size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE) + iface->state = state_quick; + else + iface->state = state_address; + +#ifdef POLLED_MODE + while (iface->state != state_idle) + scx200_acb_poll(iface); +#else /* POLLED_MODE */ +#error Interrupt driven mode not implemented +#endif /* POLLED_MODE */ + + if (iface->needs_reset) + scx200_acb_reset(iface); + + rc = iface->result; + + up(&iface->sem); + + if (rc == 0 && size == I2C_SMBUS_WORD_DATA && rw == I2C_SMBUS_READ) + data->word = le16_to_cpu(cur_word); + +#if DEBUG + printk(KERN_DEBUG NAME ": transfer done, result: %d", rc); + if (buffer) { + int i; + printk(" data:"); + for (i = 0; i < len; ++i) + printk(" %02x", buffer[i]); + } + printk("\n"); +#endif + + return rc; +} + +static u32 scx200_acb_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; +} + +/* For now, we only handle combined mode (smbus) */ +static struct i2c_algorithm scx200_acb_algorithm = { + .name = "NatSemi SCx200 ACCESS.bus", + .id = I2C_ALGO_SMBUS, + .smbus_xfer = scx200_acb_smbus_xfer, + .functionality = scx200_acb_func, +}; + +struct scx200_acb_iface *scx200_acb_list; + +int scx200_acb_probe(struct scx200_acb_iface *iface) +{ + u8 val; + + /* Disable the ACCESS.bus device and Configure the SCL + frequency: 16 clock cycles */ + outb(0x70, ACBCTL2); + + if (inb(ACBCTL2) != 0x70) { + DBG("ACBCTL2 readback failed\n"); + return -ENXIO; + } + + outb(inb(ACBCTL1) | ACBCTL1_NMINTE, ACBCTL1); + + val = inb(ACBCTL1); + if (val) { + DBG("disabled, but ACBCTL1=0x%02x\n", val); + return -ENXIO; + } + + outb(inb(ACBCTL2) | ACBCTL2_ENABLE, ACBCTL2); + + outb(inb(ACBCTL1) | ACBCTL1_NMINTE, ACBCTL1); + + val = inb(ACBCTL1); + if ((val & ACBCTL1_NMINTE) != ACBCTL1_NMINTE) { + DBG("enabled, but NMINTE won't be set, ACBCTL1=0x%02x\n", val); + return -ENXIO; + } + + return 0; +} + +static int __init scx200_acb_create(int base, int index) +{ + struct scx200_acb_iface *iface; + struct i2c_adapter *adapter; + int rc = 0; + char description[64]; + + iface = kmalloc(sizeof(*iface), GFP_KERNEL); + if (!iface) { + printk(KERN_ERR NAME ": can't allocate memory\n"); + rc = -ENOMEM; + goto errout; + } + + memset(iface, 0, sizeof(*iface)); + adapter = &iface->adapter; + i2c_set_adapdata(adapter, iface); + snprintf(adapter->name, I2C_NAME_SIZE, "SCx200 ACB%d", index); + adapter->owner = THIS_MODULE; + adapter->id = I2C_ALGO_SMBUS; + adapter->algo = &scx200_acb_algorithm; + + init_MUTEX(&iface->sem); + + snprintf(description, sizeof(description), "NatSemi SCx200 ACCESS.bus [%s]", adapter->name); + if (request_region(base, 8, description) == 0) { + dev_err(&adapter->dev, "can't allocate io 0x%x-0x%x\n", + base, base + 8-1); + rc = -EBUSY; + goto errout; + } + iface->base = base; + + rc = scx200_acb_probe(iface); + if (rc) { + dev_warn(&adapter->dev, "probe failed\n"); + goto errout; + } + + scx200_acb_reset(iface); + + if (i2c_add_adapter(adapter) < 0) { + dev_err(&adapter->dev, "failed to register\n"); + rc = -ENODEV; + goto errout; + } + + lock_kernel(); + iface->next = scx200_acb_list; + scx200_acb_list = iface; + unlock_kernel(); + + return 0; + + errout: + if (iface) { + if (iface->base) + release_region(iface->base, 8); + kfree(iface); + } + return rc; +} + +static int __init scx200_acb_init(void) +{ + int i; + int rc; + + printk(KERN_DEBUG NAME ": NatSemi SCx200 ACCESS.bus Driver\n"); + + /* Verify that this really is a SCx200 processor */ + if (pci_find_device(PCI_VENDOR_ID_NS, + PCI_DEVICE_ID_NS_SCx200_BRIDGE, + NULL) == NULL) + return -ENODEV; + + rc = -ENXIO; + for (i = 0; i < MAX_DEVICES; ++i) { + if (base[i] > 0) + rc = scx200_acb_create(base[i], i); + } + if (scx200_acb_list) + return 0; + return rc; +} + +static void __exit scx200_acb_cleanup(void) +{ + struct scx200_acb_iface *iface; + lock_kernel(); + while ((iface = scx200_acb_list) != NULL) { + scx200_acb_list = iface->next; + unlock_kernel(); + + i2c_del_adapter(&iface->adapter); + release_region(iface->base, 8); + kfree(iface); + lock_kernel(); + } + unlock_kernel(); +} + +module_init(scx200_acb_init); +module_exit(scx200_acb_cleanup); + +/* + Local variables: + compile-command: "make -k -C ../.. SUBDIRS=drivers/i2c modules" + c-basic-offset: 8 + End: +*/ + diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/busses/scx200_i2c.c i2c-2.5/drivers/i2c/busses/scx200_i2c.c --- linux-2.6.0-test5/drivers/i2c/busses/scx200_i2c.c Thu Jan 1 00:00:00 1970 +++ i2c-2.5/drivers/i2c/busses/scx200_i2c.c Tue Sep 23 10:12:59 2003 @@ -0,0 +1,132 @@ +/* linux/drivers/i2c/scx200_i2c.c + + Copyright (c) 2001,2002 Christer Weinigel + + National Semiconductor SCx200 I2C bus on GPIO pins + + Based on i2c-velleman.c Copyright (C) 1995-96, 2000 Simon G. 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. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define NAME "scx200_i2c" + +MODULE_AUTHOR("Christer Weinigel "); +MODULE_DESCRIPTION("NatSemi SCx200 I2C Driver"); +MODULE_LICENSE("GPL"); + +MODULE_PARM(scl, "i"); +MODULE_PARM_DESC(scl, "GPIO line for SCL"); +MODULE_PARM(sda, "i"); +MODULE_PARM_DESC(sda, "GPIO line for SDA"); + +static int scl = CONFIG_SCx200_I2C_SCL; +static int sda = CONFIG_SCx200_I2C_SDA; + +static void scx200_i2c_setscl(void *data, int state) +{ + scx200_gpio_set(scl, state); +} + +static void scx200_i2c_setsda(void *data, int state) +{ + scx200_gpio_set(sda, state); +} + +static int scx200_i2c_getscl(void *data) +{ + return scx200_gpio_get(scl); +} + +static int scx200_i2c_getsda(void *data) +{ + return scx200_gpio_get(sda); +} + +/* ------------------------------------------------------------------------ + * Encapsulate the above functions in the correct operations structure. + * This is only done when more than one hardware adapter is supported. + */ + +static struct i2c_algo_bit_data scx200_i2c_data = { + NULL, + scx200_i2c_setsda, + scx200_i2c_setscl, + scx200_i2c_getsda, + scx200_i2c_getscl, + 10, 10, 100, /* waits, timeout */ +}; + +static struct i2c_adapter scx200_i2c_ops = { + .owner = THIS_MODULE, + .algo_data = &scx200_i2c_data, + .name = "NatSemi SCx200 I2C", +}; + +int scx200_i2c_init(void) +{ + printk(KERN_DEBUG NAME ": NatSemi SCx200 I2C Driver\n"); + + if (!scx200_gpio_present()) { + printk(KERN_ERR NAME ": no SCx200 gpio pins available\n"); + return -ENODEV; + } + + printk(KERN_DEBUG NAME ": SCL=GPIO%02u, SDA=GPIO%02u\n", + scl, sda); + + if (scl == -1 || sda == -1 || scl == sda) { + printk(KERN_ERR NAME ": scl and sda must be specified\n"); + return -EINVAL; + } + + /* Configure GPIOs as open collector outputs */ + scx200_gpio_configure(scl, ~2, 5); + scx200_gpio_configure(sda, ~2, 5); + + if (i2c_bit_add_bus(&scx200_i2c_ops) < 0) { + printk(KERN_ERR NAME ": adapter %s registration failed\n", + scx200_i2c_ops.name); + return -ENODEV; + } + + return 0; +} + +void scx200_i2c_cleanup(void) +{ + i2c_bit_del_bus(&scx200_i2c_ops); +} + +module_init(scx200_i2c_init); +module_exit(scx200_i2c_cleanup); + +/* + Local variables: + compile-command: "make -k -C ../.. SUBDIRS=drivers/i2c modules" + c-basic-offset: 8 + End: +*/ diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/chips/Kconfig i2c-2.5/drivers/i2c/chips/Kconfig --- linux-2.6.0-test5/drivers/i2c/chips/Kconfig Mon Sep 8 19:50:06 2003 +++ i2c-2.5/drivers/i2c/chips/Kconfig Tue Sep 23 10:12:59 2003 @@ -1,112 +1,93 @@ # -# Sensor device configuration -# All depend on EXPERIMENTAL and I2C +# I2C Sensor device configuration # menu "I2C Hardware Sensors Chip support" +config I2C_SENSOR + tristate + default n + config SENSORS_ADM1021 - tristate " Analog Devices ADM1021 and compatibles" + tristate "Analog Devices ADM1021 and compatibles" depends on I2C && EXPERIMENTAL + select I2C_SENSOR help If you say yes here you get support for Analog Devices ADM1021 and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A, Genesys Logic GL523SM, National Semi LM84, TI THMC10, - and the XEON processor built-in sensor. This can also - be built as a module which can be inserted and removed while the - kernel is running. + and the XEON processor built-in sensor. - The module will be called adm1021. - - You will also need the latest user-space utilties: you can find them - in the lm_sensors package, which you can download at - http://www.lm-sensors.nu + This driver can also be built as a module. If so, the module + will be called adm1021. config SENSORS_IT87 - tristate " National Semiconductors IT87 and compatibles" + tristate "National Semiconductors IT87 and compatibles" depends on I2C && EXPERIMENTAL + select I2C_SENSOR help - The module will be called it87. + If you say yes here you get support for National Semiconductor IT87 + sensor chips and clones: IT8705F, IT8712F and SiS960. - You will also need the latest user-space utilties: you can find them - in the lm_sensors package, which you can download at - http://www.lm-sensors.nu + This driver can also be built as a module. If so, the module + will be called it87. config SENSORS_LM75 - tristate " National Semiconductors LM75 and compatibles" + tristate "National Semiconductors LM75 and compatibles" depends on I2C && EXPERIMENTAL + select I2C_SENSOR help If you say yes here you get support for National Semiconductor LM75 sensor chips and clones: Dallas Semi DS75 and DS1775, TelCon - TCN75, and National Semi LM77. This can also be built as a module - which can be inserted and removed while the kernel is running. - - The module will be called lm75. - - You will also need the latest user-space utilties: you can find them - in the lm_sensors package, which you can download at - http://www.lm-sensors.nu - -config SENSORS_LM85 - tristate " National Semiconductors LM85 and compatibles" - depends on I2C && EXPERIMENTAL - help - If you say yes here you get support for National Semiconductor LM85 - sensor chips and clones: ADT7463 and ADM1027. - This can also be built as a module which can be inserted and - removed while the kernel is running. + TCN75, and National Semi LM77. - The module will be called lm85. + This driver can also be built as a module. If so, the module + will be called lm75. - You will also need the latest user-space utilties: you can find them - in the lm_sensors package, which you can download at - http://www.lm-sensors.nu - config SENSORS_LM78 - tristate " National Semiconductors LM78 and compatibles" + tristate "National Semiconductors LM78 and compatibles" depends on I2C && EXPERIMENTAL + select I2C_SENSOR help If you say yes here you get support for National Semiconductor LM78, LM78-J and LM79. This can also be built as a module which can be inserted and removed while the kernel is running. - The module will be called lm78. + This driver can also be built as a module. If so, the module + will be called lm78. + +config SENSORS_LM85 + tristate "National Semiconductors LM85 and compatibles" + depends on I2C && EXPERIMENTAL + select I2C_SENSOR + help + If you say yes here you get support for National Semiconductor LM85 + sensor chips and clones: ADT7463 and ADM1027. + + This driver can also be built as a module. If so, the module + will be called lm85. - You will also need the latest user-space utilties: you can find them - in the lm_sensors package, which you can download at - http://www.lm-sensors.nu - config SENSORS_VIA686A - tristate " VIA686A" + tristate "VIA686A" depends on I2C && EXPERIMENTAL + select I2C_SENSOR help - support for via686a If you say yes here you get support for the integrated sensors in - Via 686A/B South Bridges. This can also be built as a module - which can be inserted and removed while the kernel is running. + Via 686A/B South Bridges. - You will also need the latest user-space utilties: you can find them - in the lm_sensors package, which you can download at - http://www.lm-sensors.nu + This driver can also be built as a module. If so, the module + will be called via686a. config SENSORS_W83781D - tristate " Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F" + tristate "Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F" depends on I2C && EXPERIMENTAL + select I2C_SENSOR help If you say yes here you get support for the Winbond W8378x series of sensor chips: the W83781D, W83782D, W83783S and W83682HF, - and the similar Asus AS99127F. This - can also be built as a module which can be inserted and removed - while the kernel is running. + and the similar Asus AS99127F. - You will also need the latest user-space utilties: you can find them - in the lm_sensors package, which you can download at - http://www.lm-sensors.nu - -config I2C_SENSOR - tristate - default y if SENSORS_ADM1021=y || SENSORS_IT87=y || SENSORS_LM75=y || SENSORS_VIA686A=y || SENSORS_W83781D=y || SENSORS_LM85=y - default m if SENSORS_ADM1021=m || SENSORS_IT87=m || SENSORS_LM75=m || SENSORS_VIA686A=m || SENSORS_W83781D=m || SENSORS_LM85=m - default n + This driver can also be built as a module. If so, the module + will be called w83781d. endmenu diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/chips/adm1021.c i2c-2.5/drivers/i2c/chips/adm1021.c --- linux-2.6.0-test5/drivers/i2c/chips/adm1021.c Mon Sep 8 19:49:51 2003 +++ i2c-2.5/drivers/i2c/chips/adm1021.c Tue Sep 23 10:12:59 2003 @@ -225,7 +225,6 @@ struct adm1021_data *data; int err = 0; const char *type_name = ""; - const char *client_name = ""; /* Make sure we aren't probing the ISA bus!! This is just a safety check at this moment; i2c_detect really won't call us. */ @@ -291,28 +290,20 @@ if (kind == max1617) { type_name = "max1617"; - client_name = "MAX1617 chip"; } else if (kind == max1617a) { type_name = "max1617a"; - client_name = "MAX1617A chip"; } else if (kind == adm1021) { type_name = "adm1021"; - client_name = "ADM1021 chip"; } else if (kind == adm1023) { type_name = "adm1023"; - client_name = "ADM1023 chip"; } else if (kind == thmc10) { type_name = "thmc10"; - client_name = "THMC10 chip"; } else if (kind == lm84) { type_name = "lm84"; - client_name = "LM84 chip"; } else if (kind == gl523sm) { type_name = "gl523sm"; - client_name = "GL523SM chip"; } else if (kind == mc1066) { type_name = "mc1066"; - client_name = "MC1066 chip"; } else { dev_err(&adapter->dev, "Internal error: unknown kind (%d)?!?", kind); @@ -320,7 +311,7 @@ } /* Fill in the remaining client fields and put it into the global list */ - strlcpy(new_client->name, client_name, DEVICE_NAME_SIZE); + strlcpy(new_client->name, type_name, I2C_NAME_SIZE); data->type = kind; new_client->id = adm1021_id++; diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/chips/it87.c i2c-2.5/drivers/i2c/chips/it87.c --- linux-2.6.0-test5/drivers/i2c/chips/it87.c Mon Sep 8 19:50:21 2003 +++ i2c-2.5/drivers/i2c/chips/it87.c Tue Sep 23 10:12:59 2003 @@ -592,7 +592,6 @@ struct it87_data *data; int err = 0; const char *name = ""; - const char *client_name = ""; int is_isa = i2c_is_isa_adapter(adapter); if (!is_isa && @@ -681,10 +680,8 @@ if (kind == it87) { name = "it87"; - client_name = "IT87 chip"; } /* else if (kind == it8712) { name = "it8712"; - client_name = "IT87-J chip"; } */ else { dev_dbg(&adapter->dev, "Internal error: unknown kind (%d)?!?", kind); @@ -692,7 +689,7 @@ } /* Fill in the remaining client fields and put it into the global list */ - strlcpy(new_client->name, name, DEVICE_NAME_SIZE); + strlcpy(new_client->name, name, I2C_NAME_SIZE); data->type = kind; diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/chips/lm75.c i2c-2.5/drivers/i2c/chips/lm75.c --- linux-2.6.0-test5/drivers/i2c/chips/lm75.c Mon Sep 8 19:49:51 2003 +++ i2c-2.5/drivers/i2c/chips/lm75.c Tue Sep 23 10:12:59 2003 @@ -194,7 +194,7 @@ } /* Fill in the remaining client fields and put it into the global list */ - strlcpy(new_client->name, name, DEVICE_NAME_SIZE); + strlcpy(new_client->name, name, I2C_NAME_SIZE); new_client->id = lm75_id++; data->valid = 0; diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/chips/lm78.c i2c-2.5/drivers/i2c/chips/lm78.c --- linux-2.6.0-test5/drivers/i2c/chips/lm78.c Mon Sep 8 19:50:22 2003 +++ i2c-2.5/drivers/i2c/chips/lm78.c Tue Sep 23 10:12:59 2003 @@ -625,11 +625,11 @@ } if (kind == lm78) { - client_name = "LM78 chip"; + client_name = "lm78"; } else if (kind == lm78j) { - client_name = "LM78-J chip"; + client_name = "lm78-j"; } else if (kind == lm79) { - client_name = "LM79 chip"; + client_name = "lm79"; } else { dev_dbg(&adapter->dev, "Internal error: unknown kind (%d)?!?", kind); @@ -638,7 +638,7 @@ } /* Fill in the remaining client fields and put into the global list */ - strlcpy(new_client->name, client_name, DEVICE_NAME_SIZE); + strlcpy(new_client->name, client_name, I2C_NAME_SIZE); data->type = kind; data->valid = 0; diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/chips/lm85.c i2c-2.5/drivers/i2c/chips/lm85.c --- linux-2.6.0-test5/drivers/i2c/chips/lm85.c Mon Sep 8 19:50:01 2003 +++ i2c-2.5/drivers/i2c/chips/lm85.c Tue Sep 23 10:12:59 2003 @@ -853,24 +853,20 @@ /* Fill in the chip specific driver values */ if ( kind == any_chip ) { type_name = "lm85"; - strlcpy(new_client->name, "Generic LM85", DEVICE_NAME_SIZE); } else if ( kind == lm85b ) { type_name = "lm85b"; - strlcpy(new_client->name, "National LM85-B", DEVICE_NAME_SIZE); } else if ( kind == lm85c ) { type_name = "lm85c"; - strlcpy(new_client->name, "National LM85-C", DEVICE_NAME_SIZE); } else if ( kind == adm1027 ) { type_name = "adm1027"; - strlcpy(new_client->name, "Analog Devices ADM1027", DEVICE_NAME_SIZE); } else if ( kind == adt7463 ) { type_name = "adt7463"; - strlcpy(new_client->name, "Analog Devices ADT7463", DEVICE_NAME_SIZE); } else { dev_dbg(&adapter->dev, "Internal error, invalid kind (%d)!", kind); err = -EFAULT ; goto ERROR1; } + strlcpy(new_client->name, type_name, I2C_NAME_SIZE); /* Fill in the remaining client fields */ new_client->id = lm85_id++; diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/chips/via686a.c i2c-2.5/drivers/i2c/chips/via686a.c --- linux-2.6.0-test5/drivers/i2c/chips/via686a.c Mon Sep 8 19:49:53 2003 +++ i2c-2.5/drivers/i2c/chips/via686a.c Tue Sep 23 10:12:59 2003 @@ -671,7 +671,7 @@ struct i2c_client *new_client; struct via686a_data *data; int err = 0; - const char client_name[] = "via686a chip"; + const char client_name[] = "via686a"; u16 val; /* Make sure we are probing the ISA bus!! */ @@ -727,7 +727,7 @@ new_client->dev.parent = &adapter->dev; /* Fill in the remaining client fields and put into the global list */ - snprintf(new_client->name, DEVICE_NAME_SIZE, client_name); + snprintf(new_client->name, I2C_NAME_SIZE, client_name); data->valid = 0; init_MUTEX(&data->update_lock); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/chips/w83781d.c i2c-2.5/drivers/i2c/chips/w83781d.c --- linux-2.6.0-test5/drivers/i2c/chips/w83781d.c Mon Sep 8 19:49:50 2003 +++ i2c-2.5/drivers/i2c/chips/w83781d.c Tue Sep 23 10:12:59 2003 @@ -378,8 +378,8 @@ struct w83781d_data *data = i2c_get_clientdata(client); \ u32 val; \ \ - val = simple_strtoul(buf, NULL, 10); \ - data->in_##reg[nr] = (IN_TO_REG(val) / 10); \ + val = simple_strtoul(buf, NULL, 10) / 10; \ + data->in_##reg[nr] = IN_TO_REG(val); \ w83781d_write_value(client, W83781D_REG_IN_##REG(nr), data->in_##reg[nr]); \ \ return count; \ @@ -1098,15 +1098,15 @@ } if (kind == w83781d) - client_name = "W83781D subclient"; + client_name = "w83781d subclient"; else if (kind == w83782d) - client_name = "W83782D subclient"; + client_name = "w83782d subclient"; else if (kind == w83783s) - client_name = "W83783S subclient"; + client_name = "w83783s subclient"; else if (kind == w83627hf) - client_name = "W83627HF subclient"; + client_name = "w83627hf subclient"; else if (kind == as99127f) - client_name = "AS99127F subclient"; + client_name = "as99127f subclient"; else client_name = "unknown subclient?"; @@ -1117,7 +1117,7 @@ data->lm75[i]->driver = &w83781d_driver; data->lm75[i]->flags = 0; strlcpy(data->lm75[i]->name, client_name, - DEVICE_NAME_SIZE); + I2C_NAME_SIZE); if ((err = i2c_attach_client(data->lm75[i]))) { dev_err(&new_client->dev, "Subclient %d " "registration at address 0x%x " @@ -1304,20 +1304,20 @@ } if (kind == w83781d) { - client_name = "W83781D chip"; + client_name = "w83781d"; } else if (kind == w83782d) { - client_name = "W83782D chip"; + client_name = "w83782d"; } else if (kind == w83783s) { - client_name = "W83783S chip"; + client_name = "w83783s"; } else if (kind == w83627hf) { if (val1 == 0x90) - client_name = "W83627THF chip"; + client_name = "w83627thf"; else - client_name = "W83627HF chip"; + client_name = "w83627hf"; } else if (kind == as99127f) { - client_name = "AS99127F chip"; + client_name = "as99127f"; } else if (kind == w83697hf) { - client_name = "W83697HF chip"; + client_name = "w83697hf"; } else { dev_err(&new_client->dev, "Internal error: unknown " "kind (%d)?!?", kind); @@ -1326,7 +1326,7 @@ } /* Fill in the remaining client fields and put into the global list */ - strlcpy(new_client->name, client_name, DEVICE_NAME_SIZE); + strlcpy(new_client->name, client_name, I2C_NAME_SIZE); data->type = kind; data->valid = 0; diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/i2c-adap-ite.c i2c-2.5/drivers/i2c/i2c-adap-ite.c --- linux-2.6.0-test5/drivers/i2c/i2c-adap-ite.c Mon Sep 8 19:49:58 2003 +++ i2c-2.5/drivers/i2c/i2c-adap-ite.c Thu Jan 1 00:00:00 1970 @@ -1,279 +0,0 @@ -/* - ------------------------------------------------------------------------- - i2c-adap-ite.c i2c-hw access for the IIC peripheral on the ITE MIPS system - ------------------------------------------------------------------------- - Hai-Pao Fan, MontaVista Software, Inc. - hpfan@mvista.com or source@mvista.com - - Copyright 2001 MontaVista Software Inc. - - ---------------------------------------------------------------------------- - This file was highly leveraged from i2c-elektor.c, which was created - by Simon G. Vogl and Hans Berglund: - - - Copyright (C) 1995-97 Simon G. Vogl - 1998-99 Hans Berglund - - 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. */ -/* ------------------------------------------------------------------------- */ - -/* With some changes from Kyösti Mälkki and even - Frodo Looijaard */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "i2c-ite.h" - -#define DEFAULT_BASE 0x14014030 -#define ITE_IIC_IO_SIZE 0x40 -#define DEFAULT_IRQ 0 -#define DEFAULT_CLOCK 0x1b0e /* default 16MHz/(27+14) = 400KHz */ -#define DEFAULT_OWN 0x55 - -static int base = 0; -static int irq = 0; -static int clock = 0; -static int own = 0; - -static int i2c_debug=0; -static struct iic_ite gpi; -static wait_queue_head_t iic_wait; -static int iic_pending; - -/* ----- global defines ----------------------------------------------- */ -#define DEB(x) if (i2c_debug>=1) x -#define DEB2(x) if (i2c_debug>=2) x -#define DEB3(x) if (i2c_debug>=3) x -#define DEBE(x) x /* error messages */ - - -/* ----- local functions ---------------------------------------------- */ - -static void iic_ite_setiic(void *data, int ctl, short val) -{ - unsigned long j = jiffies + 10; - - DEB3(printk(" Write 0x%02x to 0x%x\n",(unsigned short)val, ctl&0xff)); - DEB3({while (time_before(jiffies, j)) schedule();}) - outw(val,ctl); -} - -static short iic_ite_getiic(void *data, int ctl) -{ - short val; - - val = inw(ctl); - DEB3(printk("Read 0x%02x from 0x%x\n",(unsigned short)val, ctl&0xff)); - return (val); -} - -/* Return our slave address. This is the address - * put on the I2C bus when another master on the bus wants to address us - * as a slave - */ -static int iic_ite_getown(void *data) -{ - return (gpi.iic_own); -} - - -static int iic_ite_getclock(void *data) -{ - return (gpi.iic_clock); -} - - -#if 0 -static void iic_ite_sleep(unsigned long timeout) -{ - schedule_timeout( timeout * HZ); -} -#endif - - -/* Put this process to sleep. We will wake up when the - * IIC controller interrupts. - */ -static void iic_ite_waitforpin(void) { - - int timeout = 2; - - /* If interrupts are enabled (which they are), then put the process to - * sleep. This process will be awakened by two events -- either the - * the IIC peripheral interrupts or the timeout expires. - * If interrupts are not enabled then delay for a reasonable amount - * of time and return. - */ - if (gpi.iic_irq > 0) { - cli(); - if (iic_pending == 0) { - interruptible_sleep_on_timeout(&iic_wait, timeout*HZ ); - } else - iic_pending = 0; - sti(); - } else { - udelay(100); - } -} - - -static void iic_ite_handler(int this_irq, void *dev_id, struct pt_regs *regs) -{ - - iic_pending = 1; - - DEB2(printk("iic_ite_handler: in interrupt handler\n")); - wake_up_interruptible(&iic_wait); -} - - -/* Lock the region of memory where I/O registers exist. Request our - * interrupt line and register its associated handler. - */ -static int iic_hw_resrc_init(void) -{ - if (!request_region(gpi.iic_base, ITE_IIC_IO_SIZE, "i2c")) - return -ENODEV; - - if (gpi.iic_irq <= 0) - return 0; - - if (request_irq(gpi.iic_irq, iic_ite_handler, 0, "ITE IIC", 0) < 0) - gpi.iic_irq = 0; - else - enable_irq(gpi.iic_irq); - - return 0; -} - - -static void iic_ite_release(void) -{ - if (gpi.iic_irq > 0) { - disable_irq(gpi.iic_irq); - free_irq(gpi.iic_irq, 0); - } - release_region(gpi.iic_base , 2); -} - -/* ------------------------------------------------------------------------ - * Encapsulate the above functions in the correct operations structure. - * This is only done when more than one hardware adapter is supported. - */ -static struct i2c_algo_iic_data iic_ite_data = { - NULL, - iic_ite_setiic, - iic_ite_getiic, - iic_ite_getown, - iic_ite_getclock, - iic_ite_waitforpin, - 80, 80, 100, /* waits, timeout */ -}; - -static struct i2c_adapter iic_ite_ops = { - .owner = THIS_MODULE, - .id = I2C_HW_I_IIC, - .algo_data = &iic_ite_data, - .dev = { - .name = "ITE IIC adapter", - }, -}; - -/* Called when the module is loaded. This function starts the - * cascade of calls up through the hierarchy of i2c modules (i.e. up to the - * algorithm layer and into to the core layer) - */ -static int __init iic_ite_init(void) -{ - - struct iic_ite *piic = &gpi; - - printk(KERN_INFO "Initialize ITE IIC adapter module\n"); - if (base == 0) - piic->iic_base = DEFAULT_BASE; - else - piic->iic_base = base; - - if (irq == 0) - piic->iic_irq = DEFAULT_IRQ; - else - piic->iic_irq = irq; - - if (clock == 0) - piic->iic_clock = DEFAULT_CLOCK; - else - piic->iic_clock = clock; - - if (own == 0) - piic->iic_own = DEFAULT_OWN; - else - piic->iic_own = own; - - iic_ite_data.data = (void *)piic; - init_waitqueue_head(&iic_wait); - if (iic_hw_resrc_init() == 0) { - if (i2c_iic_add_bus(&iic_ite_ops) < 0) - return -ENODEV; - } else { - return -ENODEV; - } - printk(KERN_INFO " found device at %#x irq %d.\n", - piic->iic_base, piic->iic_irq); - return 0; -} - - -static void iic_ite_exit(void) -{ - i2c_iic_del_bus(&iic_ite_ops); - iic_ite_release(); -} - -/* If modules is NOT defined when this file is compiled, then the MODULE_* - * macros will resolve to nothing - */ -MODULE_AUTHOR("MontaVista Software "); -MODULE_DESCRIPTION("I2C-Bus adapter routines for ITE IIC bus adapter"); -MODULE_LICENSE("GPL"); - -MODULE_PARM(base, "i"); -MODULE_PARM(irq, "i"); -MODULE_PARM(clock, "i"); -MODULE_PARM(own, "i"); -MODULE_PARM(i2c_debug,"i"); - - -/* Called when module is loaded or when kernel is initialized. - * If MODULES is defined when this file is compiled, then this function will - * resolve to init_module (the function called when insmod is invoked for a - * module). Otherwise, this function is called early in the boot, when the - * kernel is intialized. Check out /include/init.h to see how this works. - */ -module_init(iic_ite_init); - -/* Resolves to module_cleanup when MODULES is defined. */ -module_exit(iic_ite_exit); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/i2c-algo-ibm_ocp.c i2c-2.5/drivers/i2c/i2c-algo-ibm_ocp.c --- linux-2.6.0-test5/drivers/i2c/i2c-algo-ibm_ocp.c Mon Sep 8 19:50:12 2003 +++ i2c-2.5/drivers/i2c/i2c-algo-ibm_ocp.c Thu Jan 1 00:00:00 1970 @@ -1,900 +0,0 @@ -/* - ------------------------------------------------------------------------- - i2c-algo-ibm_ocp.c i2c driver algorithms for IBM PPC 405 adapters - ------------------------------------------------------------------------- - - Ian DaSilva, MontaVista Software, Inc. - idasilva@mvista.com or source@mvista.com - - Copyright 2000 MontaVista Software Inc. - - Changes made to support the IIC peripheral on the IBM PPC 405 - - - --------------------------------------------------------------------------- - This file was highly leveraged from i2c-algo-pcf.c, which was created - by Simon G. Vogl and Hans Berglund: - - - Copyright (C) 1995-1997 Simon G. Vogl - 1998-2000 Hans Berglund - - With some changes from Kyösti Mälkki and - Frodo Looijaard ,and also from Martin Bailey - - - - 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. - --------------------------------------------------------------------------- - - History: 01/20/12 - Armin - akuster@mvista.com - ported up to 2.4.16+ - - Version 02/03/25 - Armin - converted to ocp format - removed commented out or #if 0 code - added Gérard Basler's fix to iic_combined_transaction() such that it - returns the number of successfully completed transfers . -*/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* ----- global defines ----------------------------------------------- */ -#define DEB(x) if (i2c_debug>=1) x -#define DEB2(x) if (i2c_debug>=2) x -#define DEB3(x) if (i2c_debug>=3) x /* print several statistical values*/ -#define DEBPROTO(x) if (i2c_debug>=9) x; - /* debug the protocol by showing transferred bits */ -#define DEF_TIMEOUT 5 - - -/* ----- global variables --------------------------------------------- */ - - -/* module parameters: - */ -static int i2c_debug=0; - -/* --- setting states on the bus with the right timing: --------------- */ - -#define iic_outb(adap, reg, val) adap->setiic(adap->data, (int) &(reg), val) -#define iic_inb(adap, reg) adap->getiic(adap->data, (int) &(reg)) - -#define IICO_I2C_SDAHIGH 0x0780 -#define IICO_I2C_SDALOW 0x0781 -#define IICO_I2C_SCLHIGH 0x0782 -#define IICO_I2C_SCLLOW 0x0783 -#define IICO_I2C_LINEREAD 0x0784 - -#define IIC_SINGLE_XFER 0 -#define IIC_COMBINED_XFER 1 - -#define IIC_ERR_LOST_ARB -2 -#define IIC_ERR_INCOMPLETE_XFR -3 -#define IIC_ERR_NACK -1 - -/* --- other auxiliary functions -------------------------------------- */ - - -// -// Description: Puts this process to sleep for a period equal to timeout -// -static inline void iic_sleep(unsigned long timeout) -{ - schedule_timeout( timeout * HZ); -} - - -// -// Description: This performs the IBM PPC 405 IIC initialization sequence -// as described in the PPC405GP data book. -// -static int iic_init (struct i2c_algo_iic_data *adap) -{ - struct iic_regs *iic; - struct iic_ibm *adap_priv_data = adap->data; - unsigned short retval; - iic = (struct iic_regs *) adap_priv_data->iic_base; - - /* Clear master low master address */ - iic_outb(adap,iic->lmadr, 0); - - /* Clear high master address */ - iic_outb(adap,iic->hmadr, 0); - - /* Clear low slave address */ - iic_outb(adap,iic->lsadr, 0); - - /* Clear high slave address */ - iic_outb(adap,iic->hsadr, 0); - - /* Clear status */ - iic_outb(adap,iic->sts, 0x0a); - - /* Clear extended status */ - iic_outb(adap,iic->extsts, 0x8f); - - /* Set clock division */ - iic_outb(adap,iic->clkdiv, 0x04); - - retval = iic_inb(adap, iic->clkdiv); - DEB(printk("iic_init: CLKDIV register = %x\n", retval)); - - /* Enable interrupts on Requested Master Transfer Complete */ - iic_outb(adap,iic->intmsk, 0x01); - - /* Clear transfer count */ - iic_outb(adap,iic->xfrcnt, 0x0); - - /* Clear extended control and status */ - iic_outb(adap,iic->xtcntlss, 0xf0); - - /* Set mode control (flush master data buf, enable hold SCL, exit */ - /* unknown state. */ - iic_outb(adap,iic->mdcntl, 0x47); - - /* Clear control register */ - iic_outb(adap,iic->cntl, 0x0); - - DEB2(printk(KERN_DEBUG "iic_init: Initialized IIC on PPC 405\n")); - return 0; -} - - -// -// Description: After we issue a transaction on the IIC bus, this function -// is called. It puts this process to sleep until we get an interrupt from -// from the controller telling us that the transaction we requested in complete. -// -static int wait_for_pin(struct i2c_algo_iic_data *adap, int *status) -{ - - int timeout = DEF_TIMEOUT; - int retval; - struct iic_regs *iic; - struct iic_ibm *adap_priv_data = adap->data; - iic = (struct iic_regs *) adap_priv_data->iic_base; - - - *status = iic_inb(adap, iic->sts); -#ifndef STUB_I2C - - while (timeout-- && (*status & 0x01)) { - adap->waitforpin(adap->data); - *status = iic_inb(adap, iic->sts); - } -#endif - if (timeout <= 0) { - /* Issue stop signal on the bus, and force an interrupt */ - retval = iic_inb(adap, iic->cntl); - iic_outb(adap, iic->cntl, retval | 0x80); - /* Clear status register */ - iic_outb(adap, iic->sts, 0x0a); - /* Exit unknown bus state */ - retval = iic_inb(adap, iic->mdcntl); - iic_outb(adap, iic->mdcntl, (retval | 0x02)); - - // Check the status of the controller. Does it still see a - // pending transfer, even though we've tried to stop any - // ongoing transaction? - retval = iic_inb(adap, iic->sts); - retval = retval & 0x01; - if(retval) { - // The iic controller is hosed. It is not responding to any - // of our commands. We have already tried to force it into - // a known state, but it has not worked. Our only choice now - // is a soft reset, which will clear all registers, and force - // us to re-initialize the controller. - /* Soft reset */ - iic_outb(adap, iic->xtcntlss, 0x01); - udelay(500); - iic_init(adap); - /* Is the pending transfer bit in the sts reg finally cleared? */ - retval = iic_inb(adap, iic->sts); - retval = retval & 0x01; - if(retval) { - printk(KERN_CRIT "The IIC Controller is hosed. A processor reset is required\n"); - } - // For some reason, even though the interrupt bit in this - // register was set during iic_init, it didn't take. We - // need to set it again. Don't ask me why....this is just what - // I saw when testing timeouts. - iic_outb(adap, iic->intmsk, 0x01); - } - return(-1); - } - else - return(0); -} - - -//------------------------------------ -// Utility functions -// - - -// -// Description: Look at the status register to see if there was an error -// in the requested transaction. If there is, look at the extended status -// register and determine the exact cause. -// -int analyze_status(struct i2c_algo_iic_data *adap, int *error_code) -{ - int ret; - struct iic_regs *iic; - struct iic_ibm *adap_priv_data = adap->data; - iic = (struct iic_regs *) adap_priv_data->iic_base; - - - ret = iic_inb(adap, iic->sts); - if(ret & 0x04) { - // Error occurred - ret = iic_inb(adap, iic->extsts); - if(ret & 0x04) { - // Lost arbitration - *error_code = IIC_ERR_LOST_ARB; - } - if(ret & 0x02) { - // Incomplete transfer - *error_code = IIC_ERR_INCOMPLETE_XFR; - } - if(ret & 0x01) { - // Master transfer aborted by a NACK during the transfer of the - // address byte - *error_code = IIC_ERR_NACK; - } - return -1; - } - return 0; -} - - -// -// Description: This function is called by the upper layers to do the -// grunt work for a master send transaction -// -static int iic_sendbytes(struct i2c_adapter *i2c_adap,const char *buf, - int count, int xfer_flag) -{ - struct iic_regs *iic; - struct i2c_algo_iic_data *adap = i2c_adap->algo_data; - struct iic_ibm *adap_priv_data = adap->data; - int wrcount, status, timeout; - int loops, remainder, i, j; - int ret, error_code; - iic = (struct iic_regs *) adap_priv_data->iic_base; - - - if( count == 0 ) return 0; - wrcount = 0; - loops = count / 4; - remainder = count % 4; - - if((loops > 1) && (remainder == 0)) { - for(i=0; i<(loops-1); i++) { - // - // Write four bytes to master data buffer - // - for(j=0; j<4; j++) { - iic_outb(adap, iic->mdbuf, - buf[wrcount++]); - } - // - // Issue command to IICO device to begin transmission - // - iic_outb(adap, iic->cntl, 0x35); - // - // Wait for transmission to complete. When it does, - //loop to the top of the for statement and write the - // next four bytes. - // - timeout = wait_for_pin(adap, &status); - if(timeout < 0) { - // - // Error handling - // - //printk(KERN_ERR "Error: write timeout\n"); - return wrcount; - } - ret = analyze_status(adap, &error_code); - if(ret < 0) { - if(error_code == IIC_ERR_INCOMPLETE_XFR) { - // Return the number of bytes transferred - ret = iic_inb(adap, iic->xfrcnt); - ret = ret & 0x07; - return (wrcount-4+ret); - } - else return error_code; - } - } - } - else if((loops >= 1) && (remainder > 0)){ - //printk(KERN_DEBUG "iic_sendbytes: (loops >= 1)\n"); - for(i=0; imdbuf, - buf[wrcount++]); - } - // - // Issue command to IICO device to begin transmission - // - iic_outb(adap, iic->cntl, 0x35); - // - // Wait for transmission to complete. When it does, - //loop to the top of the for statement and write the - // next four bytes. - // - timeout = wait_for_pin(adap, &status); - if(timeout < 0) { - // - // Error handling - // - //printk(KERN_ERR "Error: write timeout\n"); - return wrcount; - } - ret = analyze_status(adap, &error_code); - if(ret < 0) { - if(error_code == IIC_ERR_INCOMPLETE_XFR) { - // Return the number of bytes transferred - ret = iic_inb(adap, iic->xfrcnt); - ret = ret & 0x07; - return (wrcount-4+ret); - } - else return error_code; - } - } - } - - //printk(KERN_DEBUG "iic_sendbytes: expedite write\n"); - if(remainder == 0) remainder = 4; - // remainder = remainder - 1; - // - // Write the remaining bytes (less than or equal to 4) - // - for(i=0; imdbuf, buf[wrcount++]); - //printk(KERN_DEBUG "iic_sendbytes: data transferred = %x, wrcount = %d\n", buf[wrcount-1], (wrcount-1)); - } - //printk(KERN_DEBUG "iic_sendbytes: Issuing write\n"); - - if(xfer_flag == IIC_COMBINED_XFER) { - iic_outb(adap, iic->cntl, (0x09 | ((remainder-1) << 4))); - } - else { - iic_outb(adap, iic->cntl, (0x01 | ((remainder-1) << 4))); - } - DEB2(printk(KERN_DEBUG "iic_sendbytes: Waiting for interrupt\n")); - timeout = wait_for_pin(adap, &status); - if(timeout < 0) { - // - // Error handling - // - //printk(KERN_ERR "Error: write timeout\n"); - return wrcount; - } - ret = analyze_status(adap, &error_code); - if(ret < 0) { - if(error_code == IIC_ERR_INCOMPLETE_XFR) { - // Return the number of bytes transferred - ret = iic_inb(adap, iic->xfrcnt); - ret = ret & 0x07; - return (wrcount-4+ret); - } - else return error_code; - } - DEB2(printk(KERN_DEBUG "iic_sendbytes: Got interrupt\n")); - return wrcount; -} - - -// -// Description: Called by the upper layers to do the grunt work for -// a master read transaction. -// -static int iic_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count, int xfer_type) -{ - struct iic_regs *iic; - int rdcount=0, i, status, timeout; - struct i2c_algo_iic_data *adap = i2c_adap->algo_data; - struct iic_ibm *adap_priv_data = adap->data; - int loops, remainder, j; - int ret, error_code; - iic = (struct iic_regs *) adap_priv_data->iic_base; - - if(count == 0) return 0; - loops = count / 4; - remainder = count % 4; - - //printk(KERN_DEBUG "iic_readbytes: loops = %d, remainder = %d\n", loops, remainder); - - if((loops > 1) && (remainder == 0)) { - //printk(KERN_DEBUG "iic_readbytes: (loops > 1) && (remainder == 0)\n"); - for(i=0; i<(loops-1); i++) { - // - // Issue command to begin master read (4 bytes maximum) - // - //printk(KERN_DEBUG "--->Issued read command\n"); - iic_outb(adap, iic->cntl, 0x37); - // - // Wait for transmission to complete. When it does, - // loop to the top of the for statement and write the - // next four bytes. - // - //printk(KERN_DEBUG "--->Waiting for interrupt\n"); - timeout = wait_for_pin(adap, &status); - if(timeout < 0) { - // Error Handler - //printk(KERN_ERR "Error: read timed out\n"); - return rdcount; - } - //printk(KERN_DEBUG "--->Got interrupt\n"); - - ret = analyze_status(adap, &error_code); - if(ret < 0) { - if(error_code == IIC_ERR_INCOMPLETE_XFR) - return rdcount; - else - return error_code; - } - - for(j=0; j<4; j++) { - // Wait for data to shuffle to top of data buffer - // This value needs to optimized. - udelay(1); - buf[rdcount] = iic_inb(adap, iic->mdbuf); - rdcount++; - //printk(KERN_DEBUG "--->Read one byte\n"); - } - } - } - - else if((loops >= 1) && (remainder > 0)){ - //printk(KERN_DEBUG "iic_readbytes: (loops >=1) && (remainder > 0)\n"); - for(i=0; iIssued read command\n"); - iic_outb(adap, iic->cntl, 0x37); - // - // Wait for transmission to complete. When it does, - // loop to the top of the for statement and write the - // next four bytes. - // - //printk(KERN_DEBUG "--->Waiting for interrupt\n"); - timeout = wait_for_pin(adap, &status); - if(timeout < 0) { - // Error Handler - //printk(KERN_ERR "Error: read timed out\n"); - return rdcount; - } - //printk(KERN_DEBUG "--->Got interrupt\n"); - - ret = analyze_status(adap, &error_code); - if(ret < 0) { - if(error_code == IIC_ERR_INCOMPLETE_XFR) - return rdcount; - else - return error_code; - } - - for(j=0; j<4; j++) { - // Wait for data to shuffle to top of data buffer - // This value needs to optimized. - udelay(1); - buf[rdcount] = iic_inb(adap, iic->mdbuf); - rdcount++; - //printk(KERN_DEBUG "--->Read one byte\n"); - } - } - } - - //printk(KERN_DEBUG "iic_readbytes: expedite read\n"); - if(remainder == 0) remainder = 4; - DEB2(printk(KERN_DEBUG "iic_readbytes: writing %x to IICO_CNTL\n", (0x03 | ((remainder-1) << 4)))); - - if(xfer_type == IIC_COMBINED_XFER) { - iic_outb(adap, iic->cntl, (0x0b | ((remainder-1) << 4))); - } - else { - iic_outb(adap, iic->cntl, (0x03 | ((remainder-1) << 4))); - } - DEB2(printk(KERN_DEBUG "iic_readbytes: Wait for pin\n")); - timeout = wait_for_pin(adap, &status); - DEB2(printk(KERN_DEBUG "iic_readbytes: Got the interrupt\n")); - if(timeout < 0) { - // Error Handler - //printk(KERN_ERR "Error: read timed out\n"); - return rdcount; - } - - ret = analyze_status(adap, &error_code); - if(ret < 0) { - if(error_code == IIC_ERR_INCOMPLETE_XFR) - return rdcount; - else - return error_code; - } - - //printk(KERN_DEBUG "iic_readbyte: Begin reading data buffer\n"); - for(i=0; imdbuf); - // printk(KERN_DEBUG "iic_readbytes: Character read = %x\n", buf[rdcount]); - rdcount++; - } - - return rdcount; -} - - -// -// Description: This function implements combined transactions. Combined -// transactions consist of combinations of reading and writing blocks of data. -// Each transfer (i.e. a read or a write) is separated by a repeated start -// condition. -// -static int iic_combined_transaction(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) -{ - int i; - struct i2c_msg *pmsg; - int ret; - - DEB2(printk(KERN_DEBUG "Beginning combined transaction\n")); - for(i=0; i < num; i++) { - pmsg = &msgs[i]; - if(pmsg->flags & I2C_M_RD) { - - // Last read or write segment needs to be terminated with a stop - if(i < num-1) { - DEB2(printk(KERN_DEBUG "This one is a read\n")); - } - else { - DEB2(printk(KERN_DEBUG "Doing the last read\n")); - } - ret = iic_readbytes(i2c_adap, pmsg->buf, pmsg->len, (i < num-1) ? IIC_COMBINED_XFER : IIC_SINGLE_XFER); - - if (ret != pmsg->len) { - DEB2(printk("i2c-algo-ppc405.o: fail: " - "only read %d bytes.\n",ret)); - return i; - } - else { - DEB2(printk("i2c-algo-ppc405.o: read %d bytes.\n",ret)); - } - } - else if(!(pmsg->flags & I2C_M_RD)) { - - // Last read or write segment needs to be terminated with a stop - if(i < num-1) { - DEB2(printk(KERN_DEBUG "This one is a write\n")); - } - else { - DEB2(printk(KERN_DEBUG "Doing the last write\n")); - } - ret = iic_sendbytes(i2c_adap, pmsg->buf, pmsg->len, (i < num-1) ? IIC_COMBINED_XFER : IIC_SINGLE_XFER); - - if (ret != pmsg->len) { - DEB2(printk("i2c-algo-ppc405.o: fail: " - "only wrote %d bytes.\n",ret)); - return i; - } - else { - DEB2(printk("i2c-algo-ppc405.o: wrote %d bytes.\n",ret)); - } - } - } - - return num; -} - - -// -// Description: Whenever we initiate a transaction, the first byte clocked -// onto the bus after the start condition is the address (7 bit) of the -// device we want to talk to. This function manipulates the address specified -// so that it makes sense to the hardware when written to the IIC peripheral. -// -// Note: 10 bit addresses are not supported in this driver, although they are -// supported by the hardware. This functionality needs to be implemented. -// -static inline int iic_doAddress(struct i2c_algo_iic_data *adap, - struct i2c_msg *msg, int retries) -{ - struct iic_regs *iic; - unsigned short flags = msg->flags; - unsigned char addr; - struct iic_ibm *adap_priv_data = adap->data; - iic = (struct iic_regs *) adap_priv_data->iic_base; - -// -// The following segment for 10 bit addresses needs to be ported -// -/* Ten bit addresses not supported right now - if ( (flags & I2C_M_TEN) ) { - // a ten bit address - addr = 0xf0 | (( msg->addr >> 7) & 0x03); - DEB2(printk(KERN_DEBUG "addr0: %d\n",addr)); - // try extended address code... - ret = try_address(adap, addr, retries); - if (ret!=1) { - printk(KERN_ERR "iic_doAddress: died at extended address code.\n"); - return -EREMOTEIO; - } - // the remaining 8 bit address - iic_outb(adap,msg->addr & 0x7f); - // Status check comes here - if (ret != 1) { - printk(KERN_ERR "iic_doAddress: died at 2nd address code.\n"); - return -EREMOTEIO; - } - if ( flags & I2C_M_RD ) { - i2c_repstart(adap); - // okay, now switch into reading mode - addr |= 0x01; - ret = try_address(adap, addr, retries); - if (ret!=1) { - printk(KERN_ERR "iic_doAddress: died at extended address code.\n"); - return -EREMOTEIO; - } - } - } else ----------> // normal 7 bit address - -Ten bit addresses not supported yet */ - - addr = ( msg->addr << 1 ); - if (flags & I2C_M_RD ) - addr |= 1; - if (flags & I2C_M_REV_DIR_ADDR ) - addr ^= 1; - // - // Write to the low slave address - // - iic_outb(adap, iic->lmadr, addr); - // - // Write zero to the high slave register since we are - // only using 7 bit addresses - // - iic_outb(adap, iic->hmadr, 0); - - return 0; -} - - -// -// Description: Prepares the controller for a transaction (clearing status -// registers, data buffers, etc), and then calls either iic_readbytes or -// iic_sendbytes to do the actual transaction. -// -static int iic_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg msgs[], - int num) -{ - struct iic_regs *iic; - struct i2c_algo_iic_data *adap = i2c_adap->algo_data; - struct iic_ibm *adap_priv_data = adap->data; - struct i2c_msg *pmsg; - int i = 0; - int ret; - iic = (struct iic_regs *) adap_priv_data->iic_base; - - pmsg = &msgs[i]; - - // - // Clear status register - // - DEB2(printk(KERN_DEBUG "iic_xfer: iic_xfer: Clearing status register\n")); - iic_outb(adap, iic->sts, 0x0a); - - // - // Wait for any pending transfers to complete - // - DEB2(printk(KERN_DEBUG "iic_xfer: Waiting for any pending transfers to complete\n")); - while((ret = iic_inb(adap, iic->sts)) == 0x01) { - ; - } - - // - // Flush master data buf - // - DEB2(printk(KERN_DEBUG "iic_xfer: Clearing master data buffer\n")); - ret = iic_inb(adap, iic->mdcntl); - iic_outb(adap, iic->mdcntl, ret | 0x40); - - // - // Load slave address - // - DEB2(printk(KERN_DEBUG "iic_xfer: Loading slave address\n")); - ret = iic_doAddress(adap, pmsg, i2c_adap->retries); - - // - // Check to see if the bus is busy - // - ret = iic_inb(adap, iic->extsts); - // Mask off the irrelevent bits - ret = ret & 0x70; - // When the bus is free, the BCS bits in the EXTSTS register are 0b100 - if(ret != 0x40) return IIC_ERR_LOST_ARB; - - // - // Combined transaction (read and write) - // - if(num > 1) { - DEB2(printk(KERN_DEBUG "iic_xfer: Call combined transaction\n")); - ret = iic_combined_transaction(i2c_adap, msgs, num); - } - // - // Read only - // - else if((num == 1) && (pmsg->flags & I2C_M_RD)) { - // - // Tell device to begin reading data from the master data - // - DEB2(printk(KERN_DEBUG "iic_xfer: Call adapter's read\n")); - ret = iic_readbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_SINGLE_XFER); - } - // - // Write only - // - else if((num == 1 ) && (!(pmsg->flags & I2C_M_RD))) { - // - // Write data to master data buffers and tell our device - // to begin transmitting - // - DEB2(printk(KERN_DEBUG "iic_xfer: Call adapter's write\n")); - ret = iic_sendbytes(i2c_adap, pmsg->buf, pmsg->len, IIC_SINGLE_XFER); - } - - return ret; -} - - -// -// Description: Implements device specific ioctls. Higher level ioctls can -// be found in i2c-core.c and are typical of any i2c controller (specifying -// slave address, timeouts, etc). These ioctls take advantage of any hardware -// features built into the controller for which this algorithm-adapter set -// was written. These ioctls allow you to take control of the data and clock -// lines on the IBM PPC 405 IIC controller and set the either high or low, -// similar to a GPIO pin. -// -static int algo_control(struct i2c_adapter *adapter, - unsigned int cmd, unsigned long arg) -{ - struct iic_regs *iic; - struct i2c_algo_iic_data *adap = adapter->algo_data; - struct iic_ibm *adap_priv_data = adap->data; - int ret=0; - int lines; - iic = (struct iic_regs *) adap_priv_data->iic_base; - - lines = iic_inb(adap, iic->directcntl); - - if (cmd == IICO_I2C_SDAHIGH) { - lines = lines & 0x01; - if( lines ) lines = 0x04; - else lines = 0; - iic_outb(adap, iic->directcntl,(0x08|lines)); - } - else if (cmd == IICO_I2C_SDALOW) { - lines = lines & 0x01; - if( lines ) lines = 0x04; - else lines = 0; - iic_outb(adap, iic->directcntl,(0x00|lines)); - } - else if (cmd == IICO_I2C_SCLHIGH) { - lines = lines & 0x02; - if( lines ) lines = 0x08; - else lines = 0; - iic_outb(adap, iic->directcntl,(0x04|lines)); - } - else if (cmd == IICO_I2C_SCLLOW) { - lines = lines & 0x02; - if( lines ) lines = 0x08; - else lines = 0; - iic_outb(adap, iic->directcntl,(0x00|lines)); - } - else if (cmd == IICO_I2C_LINEREAD) { - ret = lines; - } - return ret; -} - - -static u32 iic_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | - I2C_FUNC_PROTOCOL_MANGLING; -} - - -/* -----exported algorithm data: ------------------------------------- */ - -static struct i2c_algorithm iic_algo = { - .name = "IBM on-chip IIC algorithm", - .id = I2C_ALGO_OCP, - .master_xfer = iic_xfer, - .algo_control = algo_control, - .functionality = iic_func, -}; - -/* - * registering functions to load algorithms at runtime - */ - - -// -// Description: Register bus structure -// -int i2c_ocp_add_bus(struct i2c_adapter *adap) -{ - struct i2c_algo_iic_data *iic_adap = adap->algo_data; - - DEB2(printk(KERN_DEBUG "i2c-algo-iic.o: hw routines for %s registered.\n", - adap->name)); - - /* register new adapter to i2c module... */ - - adap->id |= iic_algo.id; - adap->algo = &iic_algo; - - adap->timeout = 100; /* default values, should */ - adap->retries = 3; /* be replaced by defines */ - - iic_init(iic_adap); - i2c_add_adapter(adap); - return 0; -} - - -// -// Done -// -int i2c_ocp_del_bus(struct i2c_adapter *adap) -{ - return i2c_del_adapter(adap); -} - - -EXPORT_SYMBOL(i2c_ocp_add_bus); -EXPORT_SYMBOL(i2c_ocp_del_bus); - -// -// The MODULE_* macros resolve to nothing if MODULES is not defined -// when this file is compiled. -// -MODULE_AUTHOR("MontaVista Software "); -MODULE_DESCRIPTION("PPC 405 iic algorithm"); -MODULE_LICENSE("GPL"); - -MODULE_PARM(i2c_debug,"i"); - -MODULE_PARM_DESC(i2c_debug, - "debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol"); - diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/i2c-algo-ibm_ocp.h i2c-2.5/drivers/i2c/i2c-algo-ibm_ocp.h --- linux-2.6.0-test5/drivers/i2c/i2c-algo-ibm_ocp.h Mon Sep 8 19:50:06 2003 +++ i2c-2.5/drivers/i2c/i2c-algo-ibm_ocp.h Thu Jan 1 00:00:00 1970 @@ -1,55 +0,0 @@ -/* ------------------------------------------------------------------------- */ -/* i2c-algo-ibm_ocp.h i2c driver algorithms for IBM PPC 405 IIC adapters */ -/* ------------------------------------------------------------------------- */ -/* Copyright (C) 1995-97 Simon G. Vogl - 1998-99 Hans Berglund - - 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. */ -/* ------------------------------------------------------------------------- */ - -/* With some changes from Kyösti Mälkki and even - Frodo Looijaard */ - -/* Modifications by MontaVista Software, August 2000 - Changes made to support the IIC peripheral on the IBM PPC 405 */ - -#ifndef I2C_ALGO_IIC_H -#define I2C_ALGO_IIC_H 1 - -/* --- Defines for pcf-adapters --------------------------------------- */ -#include - -struct i2c_algo_iic_data { - struct iic_regs *data; /* private data for lolevel routines */ - void (*setiic) (void *data, int ctl, int val); - int (*getiic) (void *data, int ctl); - int (*getown) (void *data); - int (*getclock) (void *data); - void (*waitforpin) (void *data); - - /* local settings */ - int udelay; - int mdelay; - int timeout; -}; - - -#define I2C_IIC_ADAP_MAX 16 - - -int i2c_ocp_add_bus(struct i2c_adapter *); -int i2c_ocp_del_bus(struct i2c_adapter *); - -#endif /* I2C_ALGO_IIC_H */ diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/i2c-algo-ite.c i2c-2.5/drivers/i2c/i2c-algo-ite.c --- linux-2.6.0-test5/drivers/i2c/i2c-algo-ite.c Mon Sep 8 19:50:24 2003 +++ i2c-2.5/drivers/i2c/i2c-algo-ite.c Tue Sep 23 10:12:58 2003 @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/i2c-core.c i2c-2.5/drivers/i2c/i2c-core.c --- linux-2.6.0-test5/drivers/i2c/i2c-core.c Mon Sep 8 19:49:53 2003 +++ i2c-2.5/drivers/i2c/i2c-core.c Tue Sep 23 10:12:58 2003 @@ -581,8 +581,7 @@ */ return (ret == 1 )? count : ret; } else { - printk(KERN_ERR "i2c-core.o: I2C adapter %04x: I2C level transfers not supported\n", - client->adapter->id); + dev_err(&client->adapter->dev, "I2C level transfers not supported\n"); return -ENOSYS; } } @@ -614,8 +613,7 @@ */ return (ret == 1 )? count : ret; } else { - printk(KERN_DEBUG "i2c-core.o: I2C adapter %04x: I2C level transfers not supported\n", - client->adapter->id); + dev_err(&client->adapter->dev, "I2C level transfers not supported\n"); return -ENOSYS; } } diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/i2c-dev.c i2c-2.5/drivers/i2c/i2c-dev.c --- linux-2.6.0-test5/drivers/i2c/i2c-dev.c Mon Sep 8 19:50:21 2003 +++ i2c-2.5/drivers/i2c/i2c-dev.c Tue Sep 23 10:12:58 2003 @@ -505,8 +505,7 @@ { int res; - printk(KERN_INFO "i2c /dev entries driver module version %s (%s)\n", - I2C_VERSION, I2C_DATE); + printk(KERN_INFO "i2c /dev entries driver\n"); if (register_chrdev(I2C_MAJOR,"i2c",&i2cdev_fops)) { printk(KERN_ERR "i2c-dev.o: unable to get major %d for i2c bus\n", diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/i2c-elektor.c i2c-2.5/drivers/i2c/i2c-elektor.c --- linux-2.6.0-test5/drivers/i2c/i2c-elektor.c Mon Sep 8 19:49:51 2003 +++ i2c-2.5/drivers/i2c/i2c-elektor.c Thu Jan 1 00:00:00 1970 @@ -1,287 +0,0 @@ -/* ------------------------------------------------------------------------- */ -/* i2c-elektor.c i2c-hw access for PCF8584 style isa bus adaptes */ -/* ------------------------------------------------------------------------- */ -/* Copyright (C) 1995-97 Simon G. Vogl - 1998-99 Hans Berglund - - 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. */ -/* ------------------------------------------------------------------------- */ - -/* With some changes from Kyösti Mälkki and even - Frodo Looijaard */ - -/* Partialy rewriten by Oleg I. Vdovikin for mmapped support of - for Alpha Processor Inc. UP-2000(+) boards */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include "i2c-pcf8584.h" - -#define DEFAULT_BASE 0x330 - -static int base; -static int irq; -static int clock = 0x1c; -static int own = 0x55; -static int mmapped; -static int i2c_debug; - -/* vdovikin: removed static struct i2c_pcf_isa gpi; code - - this module in real supports only one device, due to missing arguments - in some functions, called from the algo-pcf module. Sometimes it's - need to be rewriten - but for now just remove this for simpler reading */ - -static wait_queue_head_t pcf_wait; -static int pcf_pending; - -/* ----- global defines ----------------------------------------------- */ -#define DEB(x) if (i2c_debug>=1) x -#define DEB2(x) if (i2c_debug>=2) x -#define DEB3(x) if (i2c_debug>=3) x -#define DEBE(x) x /* error messages */ - -/* ----- local functions ---------------------------------------------- */ - -static void pcf_isa_setbyte(void *data, int ctl, int val) -{ - int address = ctl ? (base + 1) : base; - - /* enable irq if any specified for serial operation */ - if (ctl && irq && (val & I2C_PCF_ESO)) { - val |= I2C_PCF_ENI; - } - - DEB3(printk(KERN_DEBUG "i2c-elektor.o: Write 0x%X 0x%02X\n", address, val & 255)); - - switch (mmapped) { - case 0: /* regular I/O */ - outb(val, address); - break; - case 2: /* double mapped I/O needed for UP2000 board, - I don't know why this... */ - writeb(val, address); - /* fall */ - case 1: /* memory mapped I/O */ - writeb(val, address); - break; - } -} - -static int pcf_isa_getbyte(void *data, int ctl) -{ - int address = ctl ? (base + 1) : base; - int val = mmapped ? readb(address) : inb(address); - - DEB3(printk(KERN_DEBUG "i2c-elektor.o: Read 0x%X 0x%02X\n", address, val)); - - return (val); -} - -static int pcf_isa_getown(void *data) -{ - return (own); -} - - -static int pcf_isa_getclock(void *data) -{ - return (clock); -} - -static void pcf_isa_waitforpin(void) { - - int timeout = 2; - - if (irq > 0) { - cli(); - if (pcf_pending == 0) { - interruptible_sleep_on_timeout(&pcf_wait, timeout*HZ ); - } else - pcf_pending = 0; - sti(); - } else { - udelay(100); - } -} - - -static irqreturn_t pcf_isa_handler(int this_irq, void *dev_id, struct pt_regs *regs) { - pcf_pending = 1; - wake_up_interruptible(&pcf_wait); - return IRQ_HANDLED; -} - - -static int pcf_isa_init(void) -{ - if (!mmapped) { - if (!request_region(base, 2, "i2c (isa bus adapter)")) { - printk(KERN_ERR - "i2c-elektor.o: requested I/O region (0x%X:2) " - "is in use.\n", base); - return -ENODEV; - } - } - if (irq > 0) { - if (request_irq(irq, pcf_isa_handler, 0, "PCF8584", 0) < 0) { - printk(KERN_ERR "i2c-elektor.o: Request irq%d failed\n", irq); - irq = 0; - } else - enable_irq(irq); - } - return 0; -} - -/* ------------------------------------------------------------------------ - * Encapsulate the above functions in the correct operations structure. - * This is only done when more than one hardware adapter is supported. - */ -static struct i2c_algo_pcf_data pcf_isa_data = { - .setpcf = pcf_isa_setbyte, - .getpcf = pcf_isa_getbyte, - .getown = pcf_isa_getown, - .getclock = pcf_isa_getclock, - .waitforpin = pcf_isa_waitforpin, - .udelay = 10, - .mdelay = 10, - .timeout = 100, -}; - -static struct i2c_adapter pcf_isa_ops = { - .owner = THIS_MODULE, - .id = I2C_HW_P_ELEK, - .algo_data = &pcf_isa_data, - .name = "PCF8584 ISA adapter", -}; - -static int __init i2c_pcfisa_init(void) -{ -#ifdef __alpha__ - /* check to see we have memory mapped PCF8584 connected to the - Cypress cy82c693 PCI-ISA bridge as on UP2000 board */ - if (base == 0) { - - struct pci_dev *cy693_dev = - pci_find_device(PCI_VENDOR_ID_CONTAQ, - PCI_DEVICE_ID_CONTAQ_82C693, NULL); - - if (cy693_dev) { - char config; - /* yeap, we've found cypress, let's check config */ - if (!pci_read_config_byte(cy693_dev, 0x47, &config)) { - - DEB3(printk(KERN_DEBUG "i2c-elektor.o: found cy82c693, config register 0x47 = 0x%02x.\n", config)); - - /* UP2000 board has this register set to 0xe1, - but the most significant bit as seems can be - reset during the proper initialisation - sequence if guys from API decides to do that - (so, we can even enable Tsunami Pchip - window for the upper 1 Gb) */ - - /* so just check for ROMCS at 0xe0000, - ROMCS enabled for writes - and external XD Bus buffer in use. */ - if ((config & 0x7f) == 0x61) { - /* seems to be UP2000 like board */ - base = 0xe0000; - /* I don't know why we need to - write twice */ - mmapped = 2; - /* UP2000 drives ISA with - 8.25 MHz (PCI/4) clock - (this can be read from cypress) */ - clock = I2C_PCF_CLK | I2C_PCF_TRNS90; - printk(KERN_INFO "i2c-elektor.o: found API UP2000 like board, will probe PCF8584 later.\n"); - } - } - } - } -#endif - - /* sanity checks for mmapped I/O */ - if (mmapped && base < 0xc8000) { - printk(KERN_ERR "i2c-elektor.o: incorrect base address (0x%0X) specified for mmapped I/O.\n", base); - return -ENODEV; - } - - printk(KERN_INFO "i2c-elektor.o: i2c pcf8584-isa adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE); - - if (base == 0) { - base = DEFAULT_BASE; - } - - init_waitqueue_head(&pcf_wait); - if (pcf_isa_init()) - return -ENODEV; - if (i2c_pcf_add_bus(&pcf_isa_ops) < 0) - goto fail; - - printk(KERN_ERR "i2c-elektor.o: found device at %#x.\n", base); - - return 0; - - fail: - if (irq > 0) { - disable_irq(irq); - free_irq(irq, 0); - } - - if (!mmapped) - release_region(base , 2); - return -ENODEV; -} - -static void i2c_pcfisa_exit(void) -{ - i2c_pcf_del_bus(&pcf_isa_ops); - - if (irq > 0) { - disable_irq(irq); - free_irq(irq, 0); - } - - if (!mmapped) - release_region(base , 2); -} - -MODULE_AUTHOR("Hans Berglund "); -MODULE_DESCRIPTION("I2C-Bus adapter routines for PCF8584 ISA bus adapter"); -MODULE_LICENSE("GPL"); - -MODULE_PARM(base, "i"); -MODULE_PARM(irq, "i"); -MODULE_PARM(clock, "i"); -MODULE_PARM(own, "i"); -MODULE_PARM(mmapped, "i"); -MODULE_PARM(i2c_debug, "i"); - -module_init(i2c_pcfisa_init); -module_exit(i2c_pcfisa_exit); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/i2c-elv.c i2c-2.5/drivers/i2c/i2c-elv.c --- linux-2.6.0-test5/drivers/i2c/i2c-elv.c Mon Sep 8 19:50:21 2003 +++ i2c-2.5/drivers/i2c/i2c-elv.c Thu Jan 1 00:00:00 1970 @@ -1,176 +0,0 @@ -/* ------------------------------------------------------------------------- */ -/* i2c-elv.c i2c-hw access for philips style parallel port adapters */ -/* ------------------------------------------------------------------------- */ -/* Copyright (C) 1995-2000 Simon G. 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. */ -/* ------------------------------------------------------------------------- */ - -/* With some changes from Kyösti Mälkki and even - Frodo Looijaard */ - -/* $Id$ */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DEFAULT_BASE 0x378 -static int base=0; -static unsigned char PortData = 0; - -/* ----- global defines ----------------------------------------------- */ -#define DEB(x) /* should be reasonable open, close &c. */ -#define DEB2(x) /* low level debugging - very slow */ -#define DEBE(x) x /* error messages */ -#define DEBINIT(x) x /* detection status messages */ - -/* --- Convenience defines for the parallel port: */ -#define BASE (unsigned int)(data) -#define DATA BASE /* Centronics data port */ -#define STAT (BASE+1) /* Centronics status port */ -#define CTRL (BASE+2) /* Centronics control port */ - - -/* ----- local functions ---------------------------------------------- */ - - -static void bit_elv_setscl(void *data, int state) -{ - if (state) { - PortData &= 0xfe; - } else { - PortData |=1; - } - outb(PortData, DATA); -} - -static void bit_elv_setsda(void *data, int state) -{ - if (state) { - PortData &=0xfd; - } else { - PortData |=2; - } - outb(PortData, DATA); -} - -static int bit_elv_getscl(void *data) -{ - return ( 0 == ( (inb_p(STAT)) & 0x08 ) ); -} - -static int bit_elv_getsda(void *data) -{ - return ( 0 == ( (inb_p(STAT)) & 0x40 ) ); -} - -static int bit_elv_init(void) -{ - if (!request_region(base, (base == 0x3bc) ? 3 : 8, - "i2c (ELV adapter)")) - return -ENODEV; - - if (inb(base+1) & 0x80) { /* BUSY should be high */ - DEBINIT(printk(KERN_DEBUG "i2c-elv.o: Busy was low.\n")); - goto fail; - } - - outb(0x0c,base+2); /* SLCT auf low */ - udelay(400); - if (!(inb(base+1) && 0x10)) { - outb(0x04,base+2); - DEBINIT(printk(KERN_DEBUG "i2c-elv.o: Select was high.\n")); - goto fail; - } - - PortData = 0; - bit_elv_setsda((void*)base,1); - bit_elv_setscl((void*)base,1); - return 0; - -fail: - release_region(base , (base == 0x3bc) ? 3 : 8); - return -ENODEV; -} - -/* ------------------------------------------------------------------------ - * Encapsulate the above functions in the correct operations structure. - * This is only done when more than one hardware adapter is supported. - */ -static struct i2c_algo_bit_data bit_elv_data = { - .setsda = bit_elv_setsda, - .setscl = bit_elv_setscl, - .getsda = bit_elv_getsda, - .getscl = bit_elv_getscl, - .udelay = 80, - .mdelay = 80, - .timeout = HZ -}; - -static struct i2c_adapter bit_elv_ops = { - .owner = THIS_MODULE, - .id = I2C_HW_B_ELV, - .algo_data = &bit_elv_data, - .name = "ELV Parallel port adaptor", -}; - -static int __init i2c_bitelv_init(void) -{ - printk(KERN_INFO "i2c-elv.o: i2c ELV parallel port adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE); - if (base==0) { - /* probe some values */ - base=DEFAULT_BASE; - bit_elv_data.data=(void*)DEFAULT_BASE; - if (bit_elv_init()==0) { - if(i2c_bit_add_bus(&bit_elv_ops) < 0) - return -ENODEV; - } else { - return -ENODEV; - } - } else { - i2c_set_adapdata(&bit_elv_ops, (void *)base); - if (bit_elv_init()==0) { - if(i2c_bit_add_bus(&bit_elv_ops) < 0) - return -ENODEV; - } else { - return -ENODEV; - } - } - printk(KERN_DEBUG "i2c-elv.o: found device at %#x.\n",base); - return 0; -} - -static void __exit i2c_bitelv_exit(void) -{ - i2c_bit_del_bus(&bit_elv_ops); - release_region(base , (base == 0x3bc) ? 3 : 8); -} - -MODULE_AUTHOR("Simon G. Vogl "); -MODULE_DESCRIPTION("I2C-Bus adapter routines for ELV parallel port adapter"); -MODULE_LICENSE("GPL"); - -MODULE_PARM(base, "i"); - -module_init(i2c_bitelv_init); -module_exit(i2c_bitelv_exit); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/i2c-frodo.c i2c-2.5/drivers/i2c/i2c-frodo.c --- linux-2.6.0-test5/drivers/i2c/i2c-frodo.c Mon Sep 8 19:49:50 2003 +++ i2c-2.5/drivers/i2c/i2c-frodo.c Thu Jan 1 00:00:00 1970 @@ -1,85 +0,0 @@ - -/* - * linux/drivers/i2c/i2c-frodo.c - * - * Author: Abraham van der Merwe - * - * An I2C adapter driver for the 2d3D, Inc. StrongARM SA-1110 - * Development board (Frodo). - * - * This source code is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include - - -static void frodo_setsda (void *data,int state) -{ - if (state) - FRODO_CPLD_I2C |= FRODO_I2C_SDA_OUT; - else - FRODO_CPLD_I2C &= ~FRODO_I2C_SDA_OUT; -} - -static void frodo_setscl (void *data,int state) -{ - if (state) - FRODO_CPLD_I2C |= FRODO_I2C_SCL_OUT; - else - FRODO_CPLD_I2C &= ~FRODO_I2C_SCL_OUT; -} - -static int frodo_getsda (void *data) -{ - return ((FRODO_CPLD_I2C & FRODO_I2C_SDA_IN) != 0); -} - -static int frodo_getscl (void *data) -{ - return ((FRODO_CPLD_I2C & FRODO_I2C_SCL_IN) != 0); -} - -static struct i2c_algo_bit_data bit_frodo_data = { - .setsda = frodo_setsda, - .setscl = frodo_setscl, - .getsda = frodo_getsda, - .getscl = frodo_getscl, - .udelay = 80, - .mdelay = 80, - .timeout = HZ -}; - -static struct i2c_adapter frodo_ops = { - .owner = THIS_MODULE, - .id = I2C_HW_B_FRODO, - .algo_data = &bit_frodo_data, - .dev = { - .name = "Frodo adapter driver", - }, -}; - -static int __init i2c_frodo_init (void) -{ - return i2c_bit_add_bus(&frodo_ops); -} - -static void __exit i2c_frodo_exit (void) -{ - i2c_bit_del_bus(&frodo_ops); -} - -MODULE_AUTHOR ("Abraham van der Merwe "); -MODULE_DESCRIPTION ("I2C-Bus adapter routines for Frodo"); -MODULE_LICENSE ("GPL"); - -module_init (i2c_frodo_init); -module_exit (i2c_frodo_exit); - diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/i2c-iop3xx.c i2c-2.5/drivers/i2c/i2c-iop3xx.c --- linux-2.6.0-test5/drivers/i2c/i2c-iop3xx.c Mon Sep 8 19:50:06 2003 +++ i2c-2.5/drivers/i2c/i2c-iop3xx.c Thu Jan 1 00:00:00 1970 @@ -1,536 +0,0 @@ -/* ------------------------------------------------------------------------- */ -/* i2c-iop3xx.c i2c driver algorithms for Intel XScale IOP3xx */ -/* ------------------------------------------------------------------------- */ -/* Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd - * - - 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. - - - 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. */ -/* ------------------------------------------------------------------------- */ -/* - With acknowledgements to i2c-algo-ibm_ocp.c by - Ian DaSilva, MontaVista Software, Inc. idasilva@mvista.com - - And i2c-algo-pcf.c, which was created by Simon G. Vogl and Hans Berglund: - - Copyright (C) 1995-1997 Simon G. Vogl, 1998-2000 Hans Berglund - - And which acknowledged Kyösti Mälkki , - Frodo Looijaard , Martin Bailey - - ---------------------------------------------------------------------------*/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include -#include -#include "i2c-iop3xx.h" - - -/* ----- global defines ----------------------------------------------- */ -#define PASSERT(x) do { if (!(x) ) \ - printk(KERN_CRIT "PASSERT %s in %s:%d\n", #x, __FILE__, __LINE__ );\ - } while (0) - - -/* ----- global variables --------------------------------------------- */ - - -static inline unsigned char iic_cook_addr(struct i2c_msg *msg) -{ - unsigned char addr; - - addr = (msg->addr << 1); - - if (msg->flags & I2C_M_RD) - addr |= 1; - - /* PGM: what is M_REV_DIR_ADDR - do we need it ?? */ - if (msg->flags & I2C_M_REV_DIR_ADDR) - addr ^= 1; - - return addr; -} - - -static inline void iop3xx_adap_reset(struct i2c_algo_iop3xx_data *iop3xx_adap) -{ - /* Follows devman 9.3 */ - *iop3xx_adap->biu->CR = IOP321_ICR_UNIT_RESET; - *iop3xx_adap->biu->SR = IOP321_ISR_CLEARBITS; - *iop3xx_adap->biu->CR = 0; -} - -static inline void iop3xx_adap_set_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap) -{ - *iop3xx_adap->biu->SAR = MYSAR; -} - -static inline void iop3xx_adap_enable(struct i2c_algo_iop3xx_data *iop3xx_adap) -{ - u32 cr = IOP321_ICR_GCD|IOP321_ICR_SCLEN|IOP321_ICR_UE; - - /* NB SR bits not same position as CR IE bits :-( */ - iop3xx_adap->biu->SR_enabled = - IOP321_ISR_ALD | IOP321_ISR_BERRD | - IOP321_ISR_RXFULL | IOP321_ISR_TXEMPTY; - - cr |= IOP321_ICR_ALDIE | IOP321_ICR_BERRIE | - IOP321_ICR_RXFULLIE | IOP321_ICR_TXEMPTYIE; - - *iop3xx_adap->biu->CR = cr; -} - -static void iop3xx_adap_transaction_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap) -{ - unsigned cr = *iop3xx_adap->biu->CR; - - cr &= ~(IOP321_ICR_MSTART | IOP321_ICR_TBYTE | - IOP321_ICR_MSTOP | IOP321_ICR_SCLEN); - *iop3xx_adap->biu->CR = cr; -} - -static void iop3xx_adap_final_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap) -{ - unsigned cr = *iop3xx_adap->biu->CR; - - cr &= ~(IOP321_ICR_ALDIE | IOP321_ICR_BERRIE | - IOP321_ICR_RXFULLIE | IOP321_ICR_TXEMPTYIE); - iop3xx_adap->biu->SR_enabled = 0; - *iop3xx_adap->biu->CR = cr; -} - -/* - * NB: the handler has to clear the source of the interrupt! - * Then it passes the SR flags of interest to BH via adap data - */ -static void iop3xx_i2c_handler(int this_irq, - void *dev_id, - struct pt_regs *regs) -{ - struct i2c_algo_iop3xx_data *iop3xx_adap = dev_id; - - u32 sr = *iop3xx_adap->biu->SR; - - if ((sr &= iop3xx_adap->biu->SR_enabled)) { - *iop3xx_adap->biu->SR = sr; - iop3xx_adap->biu->SR_received |= sr; - wake_up_interruptible(&iop3xx_adap->waitq); - } -} - -/* check all error conditions, clear them , report most important */ -static int iop3xx_adap_error(u32 sr) -{ - int rc = 0; - - if ((sr&IOP321_ISR_BERRD)) { - if ( !rc ) rc = -I2C_ERR_BERR; - } - if ((sr&IOP321_ISR_ALD)) { - if ( !rc ) rc = -I2C_ERR_ALD; - } - return rc; -} - -static inline u32 get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap) -{ - unsigned long flags; - u32 sr; - - spin_lock_irqsave(&iop3xx_adap->lock, flags); - sr = iop3xx_adap->biu->SR_received; - iop3xx_adap->biu->SR_received = 0; - spin_unlock_irqrestore(&iop3xx_adap->lock, flags); - - return sr; -} - -/* - * sleep until interrupted, then recover and analyse the SR - * saved by handler - */ -typedef int (* compare_func)(unsigned test, unsigned mask); -/* returns 1 on correct comparison */ - -static int iop3xx_adap_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap, - unsigned flags, unsigned* status, - compare_func compare) -{ - unsigned sr = 0; - int interrupted; - int done; - int rc; - - do { - interrupted = wait_event_interruptible_timeout ( - iop3xx_adap->waitq, - (done = compare( sr = get_srstat(iop3xx_adap),flags )), - iop3xx_adap->timeout - ); - if ((rc = iop3xx_adap_error(sr)) < 0) { - *status = sr; - return rc; - }else if (!interrupted) { - *status = sr; - return rc = -ETIMEDOUT; - } - } while(!done); - - *status = sr; - - return rc = 0; -} - -/* - * Concrete compare_funcs - */ -static int all_bits_clear(unsigned test, unsigned mask) -{ - return (test & mask) == 0; -} -static int any_bits_set(unsigned test, unsigned mask) -{ - return (test & mask) != 0; -} - -static int iop3xx_adap_wait_tx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status) -{ - return iop3xx_adap_wait_event( - iop3xx_adap, - IOP321_ISR_TXEMPTY|IOP321_ISR_ALD|IOP321_ISR_BERRD, - status, any_bits_set); -} - -static int iop3xx_adap_wait_rx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status) -{ - return iop3xx_adap_wait_event( - iop3xx_adap, - IOP321_ISR_RXFULL|IOP321_ISR_ALD|IOP321_ISR_BERRD, - status, any_bits_set); -} - -static int iop3xx_adap_wait_idle(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status) -{ - return iop3xx_adap_wait_event( - iop3xx_adap, IOP321_ISR_UNITBUSY, status, all_bits_clear); -} - -/* - * Description: This performs the IOP3xx initialization sequence - * Valid for IOP321. Maybe valid for IOP310?. - */ -static int iop3xx_adap_init (struct i2c_algo_iop3xx_data *iop3xx_adap) -{ - *IOP321_GPOD &= ~(iop3xx_adap->channel==0 ? - IOP321_GPOD_I2C0: - IOP321_GPOD_I2C1); - - iop3xx_adap_reset(iop3xx_adap); - iop3xx_adap_set_slave_addr(iop3xx_adap); - iop3xx_adap_enable(iop3xx_adap); - - return 0; -} - -static int iop3xx_adap_send_target_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap, - struct i2c_msg* msg) -{ - unsigned cr = *iop3xx_adap->biu->CR; - int status; - int rc; - - *iop3xx_adap->biu->DBR = iic_cook_addr(msg); - - cr &= ~(IOP321_ICR_MSTOP | IOP321_ICR_NACK); - cr |= IOP321_ICR_MSTART | IOP321_ICR_TBYTE; - - *iop3xx_adap->biu->CR = cr; - rc = iop3xx_adap_wait_tx_done(iop3xx_adap, &status); - /* this assert fires every time, contrary to IOP manual - PASSERT((status&IOP321_ISR_UNITBUSY)!=0); - */ - PASSERT((status&IOP321_ISR_RXREAD)==0); - - return rc; -} - -static int iop3xx_adap_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte, int stop) -{ - unsigned cr = *iop3xx_adap->biu->CR; - int status; - int rc; - - *iop3xx_adap->biu->DBR = byte; - cr &= ~IOP321_ICR_MSTART; - if (stop) { - cr |= IOP321_ICR_MSTOP; - } else { - cr &= ~IOP321_ICR_MSTOP; - } - *iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE; - rc = iop3xx_adap_wait_tx_done(iop3xx_adap, &status); - - return rc; -} - -static int iop3xx_adap_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, - char* byte, int stop) -{ - unsigned cr = *iop3xx_adap->biu->CR; - int status; - int rc; - - cr &= ~IOP321_ICR_MSTART; - - if (stop) { - cr |= IOP321_ICR_MSTOP|IOP321_ICR_NACK; - } else { - cr &= ~(IOP321_ICR_MSTOP|IOP321_ICR_NACK); - } - *iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE; - - rc = iop3xx_adap_wait_rx_done(iop3xx_adap, &status); - - *byte = *iop3xx_adap->biu->DBR; - - return rc; -} - -static int iop3xx_i2c_writebytes(struct i2c_adapter *i2c_adap, - const char *buf, int count) -{ - struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; - int ii; - int rc = 0; - - for (ii = 0; rc == 0 && ii != count; ++ii) { - rc = iop3xx_adap_write_byte(iop3xx_adap, buf[ii], ii==count-1); - } - return rc; -} - -static int iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap, - char *buf, int count) -{ - struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; - int ii; - int rc = 0; - - for (ii = 0; rc == 0 && ii != count; ++ii) { - rc = iop3xx_adap_read_byte(iop3xx_adap, &buf[ii], ii==count-1); - } - return rc; -} - -/* - * Description: This function implements combined transactions. Combined - * transactions consist of combinations of reading and writing blocks of data. - * FROM THE SAME ADDRESS - * Each transfer (i.e. a read or a write) is separated by a repeated start - * condition. - */ -static int iop3xx_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg) -{ - struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; - int rc; - - rc = iop3xx_adap_send_target_slave_addr(iop3xx_adap, pmsg); - if (rc < 0) { - return rc; - } - - if ((pmsg->flags&I2C_M_RD)) { - return iop3xx_i2c_readbytes(i2c_adap, pmsg->buf, pmsg->len); - } else { - return iop3xx_i2c_writebytes(i2c_adap, pmsg->buf, pmsg->len); - } -} - -/* - * master_xfer() - main read/write entry - */ -static int iop3xx_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) -{ - struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; - int im = 0; - int ret = 0; - int status; - - iop3xx_adap_wait_idle(iop3xx_adap, &status); - iop3xx_adap_reset(iop3xx_adap); - iop3xx_adap_enable(iop3xx_adap); - - for (im = 0; ret == 0 && im != num; ++im) { - ret = iop3xx_handle_msg(i2c_adap, &msgs[im]); - } - - iop3xx_adap_transaction_cleanup(iop3xx_adap); - - return ret; -} - -static int algo_control(struct i2c_adapter *adapter, unsigned int cmd, - unsigned long arg) -{ - return 0; -} - -static u32 iic_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - - -/* -----exported algorithm data: ------------------------------------- */ - -static struct i2c_algorithm iic_algo = { - .name = "IOP3xx I2C algorithm", - .id = I2C_ALGO_OCP_IOP3XX, - .master_xfer = iop3xx_master_xfer, - .algo_control = algo_control, - .functionality = iic_func, -}; - -/* - * registering functions to load algorithms at runtime - */ -static int i2c_iop3xx_add_bus(struct i2c_adapter *iic_adap) -{ - struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data; - - if (!request_region( REGION_START(iop3xx_adap), - REGION_LENGTH(iop3xx_adap), - iic_adap->name)) { - return -ENODEV; - } - - init_waitqueue_head(&iop3xx_adap->waitq); - spin_lock_init(&iop3xx_adap->lock); - - if (request_irq( - iop3xx_adap->biu->irq, - iop3xx_i2c_handler, - /* SA_SAMPLE_RANDOM */ 0, - iic_adap->name, - iop3xx_adap)) { - return -ENODEV; - } - - /* register new iic_adapter to i2c module... */ - iic_adap->id |= iic_algo.id; - iic_adap->algo = &iic_algo; - - iic_adap->timeout = 100; /* default values, should */ - iic_adap->retries = 3; /* be replaced by defines */ - - iop3xx_adap_init(iic_adap->algo_data); - i2c_add_adapter(iic_adap); - return 0; -} - -static int i2c_iop3xx_del_bus(struct i2c_adapter *iic_adap) -{ - struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data; - - iop3xx_adap_final_cleanup(iop3xx_adap); - free_irq(iop3xx_adap->biu->irq, iop3xx_adap); - - release_region(REGION_START(iop3xx_adap), REGION_LENGTH(iop3xx_adap)); - - return i2c_del_adapter(iic_adap); -} - -#ifdef CONFIG_ARCH_IOP321 - -static struct iop3xx_biu biu0 = { - .CR = IOP321_ICR0, - .SR = IOP321_ISR0, - .SAR = IOP321_ISAR0, - .DBR = IOP321_IDBR0, - .BMR = IOP321_IBMR0, - .irq = IRQ_IOP321_I2C_0, -}; - -static struct iop3xx_biu biu1 = { - .CR = IOP321_ICR1, - .SR = IOP321_ISR1, - .SAR = IOP321_ISAR1, - .DBR = IOP321_IDBR1, - .BMR = IOP321_IBMR1, - .irq = IRQ_IOP321_I2C_1, -}; - -#define ADAPTER_NAME_ROOT "IOP321 i2c biu adapter " -#else -#error Please define the BIU struct iop3xx_biu for your processor arch -#endif - -static struct i2c_algo_iop3xx_data algo_iop3xx_data0 = { - .channel = 0, - .biu = &biu0, - .timeout = 1*HZ, -}; -static struct i2c_algo_iop3xx_data algo_iop3xx_data1 = { - .channel = 1, - .biu = &biu1, - .timeout = 1*HZ, -}; - -static struct i2c_adapter iop3xx_ops0 = { - .owner = THIS_MODULE, - .name = ADAPTER_NAME_ROOT "0", - .id = I2C_HW_IOP321, - .algo_data = &algo_iop3xx_data0, -}; -static struct i2c_adapter iop3xx_ops1 = { - .owner = THIS_MODULE, - .name = ADAPTER_NAME_ROOT "1", - .id = I2C_HW_IOP321, - .algo_data = &algo_iop3xx_data1, -}; - -static int __init i2c_iop3xx_init (void) -{ - return i2c_iop3xx_add_bus(&iop3xx_ops0) || - i2c_iop3xx_add_bus(&iop3xx_ops1); -} - -static void __exit i2c_iop3xx_exit (void) -{ - i2c_iop3xx_del_bus(&iop3xx_ops0); - i2c_iop3xx_del_bus(&iop3xx_ops1); -} - -module_init (i2c_iop3xx_init); -module_exit (i2c_iop3xx_exit); - -MODULE_AUTHOR("D-TACQ Solutions Ltd "); -MODULE_DESCRIPTION("IOP3xx iic algorithm and driver"); -MODULE_LICENSE("GPL"); - -MODULE_PARM(i2c_debug,"i"); - -MODULE_PARM_DESC(i2c_debug, "debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol"); - diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/i2c-iop3xx.h i2c-2.5/drivers/i2c/i2c-iop3xx.h --- linux-2.6.0-test5/drivers/i2c/i2c-iop3xx.h Mon Sep 8 19:49:50 2003 +++ i2c-2.5/drivers/i2c/i2c-iop3xx.h Thu Jan 1 00:00:00 1970 @@ -1,118 +0,0 @@ -/* ------------------------------------------------------------------------- */ -/* i2c-iop3xx.h algorithm driver definitions private to i2c-iop3xx.c */ -/* ------------------------------------------------------------------------- */ -/* Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd - * - - 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. - - 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_IOP3XX_H -#define I2C_IOP3XX_H 1 - -/* - * iop321 hardware bit definitions - */ -#define IOP321_ICR_FAST_MODE 0x8000 /* 1=400kBps, 0=100kBps */ -#define IOP321_ICR_UNIT_RESET 0x4000 /* 1=RESET */ -#define IOP321_ICR_SADIE 0x2000 /* 1=Slave Detect Interrupt Enable */ -#define IOP321_ICR_ALDIE 0x1000 /* 1=Arb Loss Detect Interrupt Enable */ -#define IOP321_ICR_SSDIE 0x0800 /* 1=Slave STOP Detect Interrupt Enable */ -#define IOP321_ICR_BERRIE 0x0400 /* 1=Bus Error Interrupt Enable */ -#define IOP321_ICR_RXFULLIE 0x0200 /* 1=Receive Full Interrupt Enable */ -#define IOP321_ICR_TXEMPTYIE 0x0100 /* 1=Transmit Empty Interrupt Enable */ -#define IOP321_ICR_GCD 0x0080 /* 1=General Call Disable */ -/* - * IOP321_ICR_GCD: 1 disables response as slave. "This bit must be set - * when sending a master mode general call message from the I2C unit" - */ -#define IOP321_ICR_UE 0x0040 /* 1=Unit Enable */ -/* - * "NOTE: To avoid I2C bus integrity problems, - * the user needs to ensure that the GPIO Output Data Register - - * GPOD bits associated with an I2C port are cleared prior to setting - * the enable bit for that I2C serial port. - * The user prepares to enable I2C port 0 and - * I2C port 1 by clearing GPOD bits 7:6 and GPOD bits 5:4, respectively. - */ -#define IOP321_ICR_SCLEN 0x0020 /* 1=SCL enable for master mode */ -#define IOP321_ICR_MABORT 0x0010 /* 1=Send a STOP with no data - * NB TBYTE must be clear */ -#define IOP321_ICR_TBYTE 0x0008 /* 1=Send/Receive a byte. i2c clears */ -#define IOP321_ICR_NACK 0x0004 /* 1=reply with NACK */ -#define IOP321_ICR_MSTOP 0x0002 /* 1=send a STOP after next data byte */ -#define IOP321_ICR_MSTART 0x0001 /* 1=initiate a START */ - - -#define IOP321_ISR_BERRD 0x0400 /* 1=BUS ERROR Detected */ -#define IOP321_ISR_SAD 0x0200 /* 1=Slave ADdress Detected */ -#define IOP321_ISR_GCAD 0x0100 /* 1=General Call Address Detected */ -#define IOP321_ISR_RXFULL 0x0080 /* 1=Receive Full */ -#define IOP321_ISR_TXEMPTY 0x0040 /* 1=Transmit Empty */ -#define IOP321_ISR_ALD 0x0020 /* 1=Arbitration Loss Detected */ -#define IOP321_ISR_SSD 0x0010 /* 1=Slave STOP Detected */ -#define IOP321_ISR_BBUSY 0x0008 /* 1=Bus BUSY */ -#define IOP321_ISR_UNITBUSY 0x0004 /* 1=Unit Busy */ -#define IOP321_ISR_NACK 0x0002 /* 1=Unit Rx or Tx a NACK */ -#define IOP321_ISR_RXREAD 0x0001 /* 1=READ 0=WRITE (R/W bit of slave addr */ - -#define IOP321_ISR_CLEARBITS 0x07f0 - -#define IOP321_ISAR_SAMASK 0x007f - -#define IOP321_IDBR_MASK 0x00ff - -#define IOP321_IBMR_SCL 0x0002 -#define IOP321_IBMR_SDA 0x0001 - -#define IOP321_GPOD_I2C0 0x00c0 /* clear these bits to enable ch0 */ -#define IOP321_GPOD_I2C1 0x0030 /* clear these bits to enable ch1 */ - -#define MYSAR 0x02 /* SWAG a suitable slave address */ - -#define I2C_ERR 321 -#define I2C_ERR_BERR (I2C_ERR+0) -#define I2C_ERR_ALD (I2C_ERR+1) - - -struct iop3xx_biu { /* Bus Interface Unit - the hardware */ -/* physical hardware defs - regs*/ - u32 *CR; - u32 *SR; - u32 *SAR; - u32 *DBR; - u32 *BMR; -/* irq bit vector */ - u32 irq; -/* stored flags */ - u32 SR_enabled, SR_received; -}; - -struct i2c_algo_iop3xx_data { - int channel; - - wait_queue_head_t waitq; - spinlock_t lock; - int timeout; - struct iop3xx_biu* biu; -}; - -#define REGION_START(adap) ((u32)((adap)->biu->CR)) -#define REGION_END(adap) ((u32)((adap)->biu->BMR+1)) -#define REGION_LENGTH(adap) (REGION_END(adap)-REGION_START(adap)) - -#define IRQ_STATUS_MASK(adap) (1<biu->irq) - -#endif /* I2C_IOP3XX_H */ diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/i2c-keywest.c i2c-2.5/drivers/i2c/i2c-keywest.c --- linux-2.6.0-test5/drivers/i2c/i2c-keywest.c Mon Sep 8 19:50:16 2003 +++ i2c-2.5/drivers/i2c/i2c-keywest.c Thu Jan 1 00:00:00 1970 @@ -1,654 +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 -#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(probe, "i"); -MODULE_PARM(debug, "i"); - -int probe = 0; -int debug = 0; - -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 irqreturn_t -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))) - mod_timer(&iface->timeout_timer, jiffies + POLL_TIMEOUT); - spin_unlock(&iface->lock); - return IRQ_HANDLED; -} - -static void -keywest_timeout(unsigned long data) -{ - struct keywest_iface *iface = (struct keywest_iface *)data; - - DBG("timeout !\n"); - spin_lock_irq(&iface->lock); - if (handle_interrupt(iface, read_reg(reg_isr))) - mod_timer(&iface->timeout_timer, jiffies + POLL_TIMEOUT); - 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 = i2c_get_adapdata(adap); - 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; - 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; - break; - case I2C_SMBUS_BLOCK_DATA: - len = data->block[0]; - buffer = &data->block[1]; - iface->cur_mode |= KW_I2C_MODE_STANDARDSUB; - 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 */ - mod_timer(&iface->timeout_timer, jiffies + POLL_TIMEOUT); - - /* 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 interrupt operations completion */ - 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 = i2c_get_adapdata(adap); - 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 */ - mod_timer(&iface->timeout_timer, jiffies + POLL_TIMEOUT); - - /* 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 interrupt operations completion */ - 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; -} - -/* 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 -create_iface(struct device_node *np, struct device *dev) -{ - unsigned long steps, *psteps, *prate; - unsigned bsteps, tsize, i, nchan, addroffset; - struct keywest_iface* iface; - int rc; - - 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 = (struct keywest_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 sub mode */ - iface->cur_mode |= KW_I2C_MODE_STANDARDSUB; - - /* 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 */ - rc = request_irq(iface->irq, keywest_irq, 0, "keywest i2c", iface); - if (rc) { - printk(KERN_ERR "i2c-keywest: can't get IRQ %d !\n", iface->irq); - iounmap((void *)iface->base); - kfree(iface); - return -ENODEV; - } - - dev_set_drvdata(dev, iface); - - for (i=0; ichannels[i]; - u8 addr; - - 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.client_register = NULL; - chan->adapter.client_unregister = NULL; - i2c_set_adapdata(&chan->adapter, chan); - chan->adapter.dev.parent = dev; - - rc = i2c_add_adapter(&chan->adapter); - if (rc) { - printk("i2c-keywest.c: Adapter %s registration failed\n", - chan->adapter.name); - i2c_set_adapdata(&chan->adapter, NULL); - } - if (probe) { - printk("Probe: "); - for (addr = 0x00; addr <= 0x7f; addr++) { - if (i2c_smbus_xfer(&chan->adapter,addr, - 0,0,0,I2C_SMBUS_QUICK,NULL) >= 0) - printk("%02x ", addr); - } - printk("\n"); - } - } - - printk(KERN_INFO "Found KeyWest i2c on \"%s\", %d channel%s, stepping: %d bits\n", - np->parent->name, nchan, nchan > 1 ? "s" : "", bsteps); - - return 0; -} - -static int -dispose_iface(struct device *dev) -{ - struct keywest_iface *iface = dev_get_drvdata(dev); - int i, rc; - - /* 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 (i2c_get_adapdata(&chan->adapter) == NULL) - continue; - rc = i2c_del_adapter(&chan->adapter); - i2c_set_adapdata(&chan->adapter, NULL); - /* We aren't that prepared to deal with this... */ - if (rc) - printk("i2c-keywest.c: i2c_del_adapter failed, that's bad !\n"); - } - iounmap((void *)iface->base); - dev_set_drvdata(dev, NULL); - kfree(iface); - - return 0; -} - -static int -create_iface_macio(struct macio_dev* dev, const struct of_match *match) -{ - return create_iface(dev->ofdev.node, &dev->ofdev.dev); -} - -static int -dispose_iface_macio(struct macio_dev* dev) -{ - return dispose_iface(&dev->ofdev.dev); -} - -static int -create_iface_of_platform(struct of_device* dev, const struct of_match *match) -{ - return create_iface(dev->node, &dev->dev); -} - -static int -dispose_iface_of_platform(struct of_device* dev) -{ - return dispose_iface(&dev->dev); -} - -static struct of_match i2c_keywest_match[] = -{ - { - .name = OF_ANY_MATCH, - .type = "i2c", - .compatible = "keywest" - }, - {}, -}; - -static struct macio_driver i2c_keywest_macio_driver = -{ - .name = "i2c-keywest", - .match_table = i2c_keywest_match, - .probe = create_iface_macio, - .remove = dispose_iface_macio -}; - -static struct of_platform_driver i2c_keywest_of_platform_driver = -{ - .name = "i2c-keywest", - .match_table = i2c_keywest_match, - .probe = create_iface_of_platform, - .remove = dispose_iface_of_platform -}; - -static int __init -i2c_keywest_init(void) -{ - macio_register_driver(&i2c_keywest_macio_driver); - of_register_driver(&i2c_keywest_of_platform_driver); - - return 0; -} - -static void __exit -i2c_keywest_cleanup(void) -{ - macio_unregister_driver(&i2c_keywest_macio_driver); - of_unregister_driver(&i2c_keywest_of_platform_driver); -} - -module_init(i2c_keywest_init); -module_exit(i2c_keywest_cleanup); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/i2c-keywest.h i2c-2.5/drivers/i2c/i2c-keywest.h --- linux-2.6.0-test5/drivers/i2c/i2c-keywest.h Mon Sep 8 19:50:23 2003 +++ i2c-2.5/drivers/i2c/i2c-keywest.h Thu Jan 1 00:00:00 1970 @@ -1,110 +0,0 @@ -#ifndef __I2C_KEYWEST_H__ -#define __I2C_KEYWEST_H__ - -/* 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; -}; - -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 -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/i2c-philips-par.c i2c-2.5/drivers/i2c/i2c-philips-par.c --- linux-2.6.0-test5/drivers/i2c/i2c-philips-par.c Mon Sep 8 19:49:53 2003 +++ i2c-2.5/drivers/i2c/i2c-philips-par.c Thu Jan 1 00:00:00 1970 @@ -1,256 +0,0 @@ -/* ------------------------------------------------------------------------- */ -/* i2c-philips-par.c i2c-hw access for philips style parallel port adapters */ -/* ------------------------------------------------------------------------- */ -/* Copyright (C) 1995-2000 Simon G. 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. */ -/* ------------------------------------------------------------------------- */ - -/* With some changes from Kyösti Mälkki and even - Frodo Looijaard */ - -/* $Id$ */ - -#include -#include -#include -#include -#include -#include -#include -#include - -static int type; - -struct i2c_par -{ - struct pardevice *pdev; - struct i2c_adapter adapter; - struct i2c_algo_bit_data bit_lp_data; - struct i2c_par *next; -}; - -static struct i2c_par *adapter_list; - - -/* ----- global defines ----------------------------------------------- */ -#define DEB(x) /* should be reasonable open, close &c. */ -#define DEB2(x) /* low level debugging - very slow */ -#define DEBE(x) x /* error messages */ - -/* ----- printer port defines ------------------------------------------*/ - /* Pin Port Inverted name */ -#define I2C_ON 0x20 /* 12 status N paper */ - /* ... only for phil. not used */ -#define I2C_SDA 0x80 /* 9 data N data7 */ -#define I2C_SCL 0x08 /* 17 ctrl N dsel */ - -#define I2C_SDAIN 0x80 /* 11 stat Y busy */ -#define I2C_SCLIN 0x08 /* 15 stat Y enable */ - -#define I2C_DMASK 0x7f -#define I2C_CMASK 0xf7 - -/* ----- local functions ---------------------------------------------- */ - -static void bit_lp_setscl(void *data, int state) -{ - /*be cautious about state of the control register - - touch only the one bit needed*/ - if (state) { - parport_write_control((struct parport *) data, - parport_read_control((struct parport *) data)|I2C_SCL); - } else { - parport_write_control((struct parport *) data, - parport_read_control((struct parport *) data)&I2C_CMASK); - } -} - -static void bit_lp_setsda(void *data, int state) -{ - if (state) { - parport_write_data((struct parport *) data, I2C_DMASK); - } else { - parport_write_data((struct parport *) data, I2C_SDA); - } -} - -static int bit_lp_getscl(void *data) -{ - return parport_read_status((struct parport *) data) & I2C_SCLIN; -} - -static int bit_lp_getsda(void *data) -{ - return parport_read_status((struct parport *) data) & I2C_SDAIN; -} - -static void bit_lp_setscl2(void *data, int state) -{ - if (state) { - parport_write_data((struct parport *) data, - parport_read_data((struct parport *) data)|0x1); - } else { - parport_write_data((struct parport *) data, - parport_read_data((struct parport *) data)&0xfe); - } -} - -static void bit_lp_setsda2(void *data, int state) -{ - if (state) { - parport_write_data((struct parport *) data, - parport_read_data((struct parport *) data)|0x2); - } else { - parport_write_data((struct parport *) data, - parport_read_data((struct parport *) data)&0xfd); - } -} - -static int bit_lp_getsda2(void *data) -{ - return (parport_read_status((struct parport *) data) & - PARPORT_STATUS_BUSY) ? 0 : 1; -} - -/* ------------------------------------------------------------------------ - * Encapsulate the above functions in the correct operations structure. - * This is only done when more than one hardware adapter is supported. - */ - -static struct i2c_algo_bit_data bit_lp_data = { - .setsda = bit_lp_setsda, - .setscl = bit_lp_setscl, - .getsda = bit_lp_getsda, - .getscl = bit_lp_getscl, - .udelay = 80, - .mdelay = 80, - .timeout = HZ -}; - -static struct i2c_algo_bit_data bit_lp_data2 = { - .setsda = bit_lp_setsda2, - .setscl = bit_lp_setscl2, - .getsda = bit_lp_getsda2, - .udelay = 80, - .mdelay = 80, - .timeout = HZ -}; - -static struct i2c_adapter bit_lp_ops = { - .owner = THIS_MODULE, - .id = I2C_HW_B_LP, - .name = "Philips Parallel port adapter", -}; - -static void i2c_parport_attach (struct parport *port) -{ - struct i2c_par *adapter = kmalloc(sizeof(struct i2c_par), - GFP_KERNEL); - if (!adapter) { - printk(KERN_ERR "i2c-philips-par: Unable to malloc.\n"); - return; - } - - printk(KERN_DEBUG "i2c-philips-par.o: attaching to %s\n", port->name); - - adapter->pdev = parport_register_device(port, "i2c-philips-par", - NULL, NULL, NULL, - PARPORT_FLAG_EXCL, - NULL); - if (!adapter->pdev) { - printk(KERN_ERR "i2c-philips-par: Unable to register with parport.\n"); - kfree(adapter); - return; - } - - adapter->adapter = bit_lp_ops; - adapter->adapter.algo_data = &adapter->bit_lp_data; - adapter->bit_lp_data = type ? bit_lp_data2 : bit_lp_data; - adapter->bit_lp_data.data = port; - - if (parport_claim_or_block(adapter->pdev) < 0 ) { - printk(KERN_ERR "i2c-philips-par: Could not claim parallel port.\n"); - kfree(adapter); - return; - } - /* reset hardware to sane state */ - bit_lp_setsda(port, 1); - bit_lp_setscl(port, 1); - parport_release(adapter->pdev); - - if (i2c_bit_add_bus(&adapter->adapter) < 0) - { - printk(KERN_ERR "i2c-philips-par: Unable to register with I2C.\n"); - parport_unregister_device(adapter->pdev); - kfree(adapter); - return; /* No good */ - } - - adapter->next = adapter_list; - adapter_list = adapter; -} - -static void i2c_parport_detach (struct parport *port) -{ - struct i2c_par *adapter, *prev = NULL; - - for (adapter = adapter_list; adapter; adapter = adapter->next) - { - if (adapter->pdev->port == port) - { - parport_unregister_device(adapter->pdev); - i2c_bit_del_bus(&adapter->adapter); - if (prev) - prev->next = adapter->next; - else - adapter_list = adapter->next; - kfree(adapter); - return; - } - prev = adapter; - } -} - - -static struct parport_driver i2c_driver = { - "i2c-philips-par", - i2c_parport_attach, - i2c_parport_detach, - NULL -}; - -int __init i2c_bitlp_init(void) -{ - printk(KERN_INFO "i2c-philips-par.o: i2c Philips parallel port adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE); - - parport_register_driver(&i2c_driver); - - return 0; -} - -void __exit i2c_bitlp_exit(void) -{ - parport_unregister_driver(&i2c_driver); -} - -MODULE_AUTHOR("Simon G. Vogl "); -MODULE_DESCRIPTION("I2C-Bus adapter routines for Philips parallel port adapter"); -MODULE_LICENSE("GPL"); - -MODULE_PARM(type, "i"); - -module_init(i2c_bitlp_init); -module_exit(i2c_bitlp_exit); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/i2c-prosavage.c i2c-2.5/drivers/i2c/i2c-prosavage.c --- linux-2.6.0-test5/drivers/i2c/i2c-prosavage.c Mon Sep 8 19:50:01 2003 +++ i2c-2.5/drivers/i2c/i2c-prosavage.c Thu Jan 1 00:00:00 1970 @@ -1,357 +0,0 @@ -/* - * kernel/busses/i2c-prosavage.c - * - * i2c bus driver for S3/VIA 8365/8375 graphics processor. - * Copyright (c) 2003 Henk Vergonet - * Based on code written by: - * Frodo Looijaard , - * Philip Edelbrock , - * Ralph Metzler , and - * Mark D. Studebaker - * Simon Vogl - * and others - * - * Please read the lm_sensors documentation for details on use. - * - * 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. - * - */ -/* 18-05-2003 HVE - created - * 14-06-2003 HVE - adapted for lm_sensors2 - * 17-06-2003 HVE - linux 2.5.xx compatible - * 18-06-2003 HVE - codingstyle - * 21-06-2003 HVE - compatibility lm_sensors2 and linux 2.5.xx - * codingstyle, mmio enabled - * - * This driver interfaces to the I2C bus of the VIA north bridge embedded - * ProSavage4/8 devices. Usefull for gaining access to the TV Encoder chips. - * - * Graphics cores: - * S3/VIA KM266/VT8375 aka ProSavage8 - * S3/VIA KM133/VT8365 aka Savage4 - * - * Two serial busses are implemented: - * SERIAL1 - I2C serial communications interface - * SERIAL2 - DDC2 monitor communications interface - * - * Tested on a FX41 mainboard, see http://www.shuttle.com - * - * - * TODO: - * - integration with prosavage framebuffer device - * (Additional documentation needed :( - */ - -#include -#include -#include -#include -#include -#include - -#include - - -/* - * driver configuration - */ -#define DRIVER_ID "i2c-prosavage" -#define DRIVER_VERSION "20030621" - -#define ADAPTER_NAME(x) (x).name - -#define MAX_BUSSES 2 - -struct s_i2c_bus { - u8 *mmvga; - int i2c_reg; - int adap_ok; - struct i2c_adapter adap; - struct i2c_algo_bit_data algo; -}; - -struct s_i2c_chip { - u8 *mmio; - struct s_i2c_bus i2c_bus[MAX_BUSSES]; -}; - - -/* - * i2c configuration - */ -#ifndef I2C_HW_B_S3VIA -#define I2C_HW_B_S3VIA 0x18 /* S3VIA ProSavage adapter */ -#endif - -/* delays */ -#define CYCLE_DELAY 10 -#define TIMEOUT (HZ / 2) - - -/* - * S3/VIA 8365/8375 registers - */ -#ifndef PCI_VENDOR_ID_S3 -#define PCI_VENDOR_ID_S3 0x5333 -#endif -#ifndef PCI_DEVICE_ID_S3_SAVAGE4 -#define PCI_DEVICE_ID_S3_SAVAGE4 0x8a25 -#endif -#ifndef PCI_DEVICE_ID_S3_PROSAVAGE8 -#define PCI_DEVICE_ID_S3_PROSAVAGE8 0x8d04 -#endif - -#define VGA_CR_IX 0x3d4 -#define VGA_CR_DATA 0x3d5 - -#define CR_SERIAL1 0xa0 /* I2C serial communications interface */ -#define MM_SERIAL1 0xff20 -#define CR_SERIAL2 0xb1 /* DDC2 monitor communications interface */ - -/* based on vt8365 documentation */ -#define I2C_ENAB 0x10 -#define I2C_SCL_OUT 0x01 -#define I2C_SDA_OUT 0x02 -#define I2C_SCL_IN 0x04 -#define I2C_SDA_IN 0x08 - -#define SET_CR_IX(p, val) *((p)->mmvga + VGA_CR_IX) = (u8)(val) -#define SET_CR_DATA(p, val) *((p)->mmvga + VGA_CR_DATA) = (u8)(val) -#define GET_CR_DATA(p) *((p)->mmvga + VGA_CR_DATA) - - -/* - * Serial bus line handling - * - * serial communications register as parameter in private data - * - * TODO: locks with other code sections accessing video registers? - */ -static void bit_s3via_setscl(void *bus, int val) -{ - struct s_i2c_bus *p = (struct s_i2c_bus *)bus; - unsigned int r; - - SET_CR_IX(p, p->i2c_reg); - r = GET_CR_DATA(p); - r |= I2C_ENAB; - if (val) { - r |= I2C_SCL_OUT; - } else { - r &= ~I2C_SCL_OUT; - } - SET_CR_DATA(p, r); -} - -static void bit_s3via_setsda(void *bus, int val) -{ - struct s_i2c_bus *p = (struct s_i2c_bus *)bus; - unsigned int r; - - SET_CR_IX(p, p->i2c_reg); - r = GET_CR_DATA(p); - r |= I2C_ENAB; - if (val) { - r |= I2C_SDA_OUT; - } else { - r &= ~I2C_SDA_OUT; - } - SET_CR_DATA(p, r); -} - -static int bit_s3via_getscl(void *bus) -{ - struct s_i2c_bus *p = (struct s_i2c_bus *)bus; - - SET_CR_IX(p, p->i2c_reg); - return (0 != (GET_CR_DATA(p) & I2C_SCL_IN)); -} - -static int bit_s3via_getsda(void *bus) -{ - struct s_i2c_bus *p = (struct s_i2c_bus *)bus; - - SET_CR_IX(p, p->i2c_reg); - return (0 != (GET_CR_DATA(p) & I2C_SDA_IN)); -} - - -/* - * adapter initialisation - */ -static int i2c_register_bus(struct s_i2c_bus *p, u8 *mmvga, u32 i2c_reg) -{ - int ret; - p->adap.owner = THIS_MODULE; - p->adap.id = I2C_HW_B_S3VIA; - p->adap.algo_data = &p->algo; - p->algo.setsda = bit_s3via_setsda; - p->algo.setscl = bit_s3via_setscl; - p->algo.getsda = bit_s3via_getsda; - p->algo.getscl = bit_s3via_getscl; - p->algo.udelay = CYCLE_DELAY; - p->algo.mdelay = CYCLE_DELAY; - p->algo.timeout = TIMEOUT; - p->algo.data = p; - p->mmvga = mmvga; - p->i2c_reg = i2c_reg; - - ret = i2c_bit_add_bus(&p->adap); - if (ret) { - return ret; - } - - p->adap_ok = 1; - return 0; -} - - -/* - * Cleanup stuff - */ -static void __devexit prosavage_remove(struct pci_dev *dev) -{ - struct s_i2c_chip *chip; - int i, ret; - - chip = (struct s_i2c_chip *)pci_get_drvdata(dev); - - if (!chip) { - return; - } - for (i = MAX_BUSSES - 1; i >= 0; i--) { - if (chip->i2c_bus[i].adap_ok == 0) - continue; - - ret = i2c_bit_del_bus(&chip->i2c_bus[i].adap); - if (ret) { - printk(DRIVER_ID ": %s not removed\n", - ADAPTER_NAME(chip->i2c_bus[i].adap)); - } - } - if (chip->mmio) { - iounmap(chip->mmio); - } - kfree(chip); -} - - -/* - * Detect chip and initialize it - */ -static int __devinit prosavage_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - int ret; - unsigned long base, len; - struct s_i2c_chip *chip; - struct s_i2c_bus *bus; - - pci_set_drvdata(dev, kmalloc(sizeof(struct s_i2c_chip), GFP_KERNEL)); - chip = (struct s_i2c_chip *)pci_get_drvdata(dev); - if (chip == NULL) { - return -ENOMEM; - } - - memset(chip, 0, sizeof(struct s_i2c_chip)); - - base = dev->resource[0].start & PCI_BASE_ADDRESS_MEM_MASK; - len = dev->resource[0].end - base + 1; - chip->mmio = ioremap_nocache(base, len); - - if (chip->mmio == NULL) { - printk (DRIVER_ID ": ioremap failed\n"); - prosavage_remove(dev); - return -ENODEV; - } - - - /* - * Chip initialisation - */ - /* Unlock Extended IO Space ??? */ - - - /* - * i2c bus registration - */ - bus = &chip->i2c_bus[0]; - snprintf(ADAPTER_NAME(bus->adap), sizeof(ADAPTER_NAME(bus->adap)), - "ProSavage I2C bus at %02x:%02x.%x", - dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); - ret = i2c_register_bus(bus, chip->mmio + 0x8000, CR_SERIAL1); - if (ret) { - goto err_adap; - } - /* - * ddc bus registration - */ - bus = &chip->i2c_bus[1]; - snprintf(ADAPTER_NAME(bus->adap), sizeof(ADAPTER_NAME(bus->adap)), - "ProSavage DDC bus at %02x:%02x.%x", - dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); - ret = i2c_register_bus(bus, chip->mmio + 0x8000, CR_SERIAL2); - if (ret) { - goto err_adap; - } - return 0; -err_adap: - printk (DRIVER_ID ": %s failed\n", ADAPTER_NAME(bus->adap)); - prosavage_remove(dev); - return ret; -} - - -/* - * Data for PCI driver interface - */ -static struct pci_device_id prosavage_pci_tbl[] = { - { - .vendor = PCI_VENDOR_ID_S3, - .device = PCI_DEVICE_ID_S3_SAVAGE4, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - },{ - .vendor = PCI_VENDOR_ID_S3, - .device = PCI_DEVICE_ID_S3_PROSAVAGE8, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - },{ 0, } -}; - -static struct pci_driver prosavage_driver = { - .name = "prosavage-smbus", - .id_table = prosavage_pci_tbl, - .probe = prosavage_probe, - .remove = __devexit_p(prosavage_remove), -}; - -static int __init i2c_prosavage_init(void) -{ - printk(DRIVER_ID " version %s (%s)\n", I2C_VERSION, DRIVER_VERSION); - return pci_module_init(&prosavage_driver); -} - -static void __exit i2c_prosavage_exit(void) -{ - pci_unregister_driver(&prosavage_driver); -} - -MODULE_DEVICE_TABLE(pci, prosavage_pci_tbl); -MODULE_AUTHOR("Henk Vergonet"); -MODULE_DESCRIPTION("ProSavage VIA 8365/8375 smbus driver"); -MODULE_LICENSE("GPL"); - -module_init (i2c_prosavage_init); -module_exit (i2c_prosavage_exit); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/i2c-rpx.c i2c-2.5/drivers/i2c/i2c-rpx.c --- linux-2.6.0-test5/drivers/i2c/i2c-rpx.c Mon Sep 8 19:50:33 2003 +++ i2c-2.5/drivers/i2c/i2c-rpx.c Thu Jan 1 00:00:00 1970 @@ -1,103 +0,0 @@ -/* - * Embedded Planet RPX Lite MPC8xx CPM I2C interface. - * Copyright (c) 1999 Dan Malek (dmalek@jlc.net). - * - * moved into proper i2c interface; - * Brad Parker (brad@heeltoe.com) - * - * RPX lite specific parts of the i2c interface - * Update: There actually isn't anything RPXLite-specific about this module. - * This should work for most any 8xx board. The console messages have been - * changed to eliminate RPXLite references. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -static void -rpx_iic_init(struct i2c_algo_8xx_data *data) -{ - volatile cpm8xx_t *cp; - volatile immap_t *immap; - - cp = cpmp; /* Get pointer to Communication Processor */ - immap = (immap_t *)IMAP_ADDR; /* and to internal registers */ - - data->iip = (iic_t *)&cp->cp_dparam[PROFF_IIC]; - - /* Check for and use a microcode relocation patch. - */ - if ((data->reloc = data->iip->iic_rpbase)) - data->iip = (iic_t *)&cp->cp_dpmem[data->iip->iic_rpbase]; - - data->i2c = (i2c8xx_t *)&(immap->im_i2c); - data->cp = cp; - - /* Initialize Port B IIC pins. - */ - cp->cp_pbpar |= 0x00000030; - cp->cp_pbdir |= 0x00000030; - cp->cp_pbodr |= 0x00000030; - - /* Allocate space for two transmit and two receive buffer - * descriptors in the DP ram. - */ - data->dp_addr = m8xx_cpm_dpalloc(sizeof(cbd_t) * 4); - - /* ptr to i2c area */ - data->i2c = (i2c8xx_t *)&(((immap_t *)IMAP_ADDR)->im_i2c); -} - -static int rpx_install_isr(int irq, void (*func)(void *, void *), void *data) -{ - /* install interrupt handler */ - cpm_install_handler(irq, (void (*)(void *, struct pt_regs *)) func, data); - - return 0; -} - -static struct i2c_algo_8xx_data rpx_data = { - .setisr = rpx_install_isr -}; - -static struct i2c_adapter rpx_ops = { - .owner = THIS_MODULE, - .name = "m8xx", - .id = I2C_HW_MPC8XX_EPON, - .algo_data = &rpx_data, -}; - -int __init i2c_rpx_init(void) -{ - printk("i2c-rpx.o: i2c MPC8xx module version %s (%s)\n", I2C_VERSION, I2C_DATE); - - /* reset hardware to sane state */ - rpx_iic_init(&rpx_data); - - if (i2c_8xx_add_bus(&rpx_ops) < 0) { - printk("i2c-rpx: Unable to register with I2C\n"); - return -ENODEV; - } - - return 0; -} - -void __exit i2c_rpx_exit(void) -{ - i2c_8xx_del_bus(&rpx_ops); -} - -MODULE_AUTHOR("Dan Malek "); -MODULE_DESCRIPTION("I2C-Bus adapter routines for MPC8xx boards"); - -module_init(i2c_rpx_init); -module_exit(i2c_rpx_exit); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/i2c-sensor.c i2c-2.5/drivers/i2c/i2c-sensor.c --- linux-2.6.0-test5/drivers/i2c/i2c-sensor.c Mon Sep 8 19:50:06 2003 +++ i2c-2.5/drivers/i2c/i2c-sensor.c Tue Sep 23 10:12:59 2003 @@ -50,8 +50,9 @@ return -1; for (addr = 0x00; addr <= (is_isa ? 0xffff : 0x7f); addr++) { - /* XXX: WTF is going on here??? */ - if ((is_isa && check_region(addr, 1)) || + void *region_used = request_region(addr, 1, "foo"); + release_region(addr, 1); + if ((is_isa && (region_used == NULL)) || (!is_isa && i2c_check_addr(adapter, addr))) continue; diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/i2c-velleman.c i2c-2.5/drivers/i2c/i2c-velleman.c --- linux-2.6.0-test5/drivers/i2c/i2c-velleman.c Mon Sep 8 19:50:21 2003 +++ i2c-2.5/drivers/i2c/i2c-velleman.c Thu Jan 1 00:00:00 1970 @@ -1,161 +0,0 @@ -/* ------------------------------------------------------------------------- */ -/* i2c-velleman.c i2c-hw access for Velleman K9000 adapters */ -/* ------------------------------------------------------------------------- */ -/* Copyright (C) 1995-96, 2000 Simon G. 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. */ -/* ------------------------------------------------------------------------- */ - -/* $Id$ */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* ----- global defines ----------------------------------------------- */ -#define DEB(x) /* should be reasonable open, close &c. */ -#define DEB2(x) /* low level debugging - very slow */ -#define DEBE(x) x /* error messages */ - - /* Pin Port Inverted name */ -#define I2C_SDA 0x02 /* ctrl bit 1 (inv) */ -#define I2C_SCL 0x08 /* ctrl bit 3 (inv) */ - -#define I2C_SDAIN 0x10 /* stat bit 4 */ -#define I2C_SCLIN 0x08 /* ctrl bit 3 (inv)(reads own output)*/ - -#define I2C_DMASK 0xfd -#define I2C_CMASK 0xf7 - - -/* --- Convenience defines for the parallel port: */ -#define BASE (unsigned int)(data) -#define DATA BASE /* Centronics data port */ -#define STAT (BASE+1) /* Centronics status port */ -#define CTRL (BASE+2) /* Centronics control port */ - -#define DEFAULT_BASE 0x378 -static int base=0; - -/* ----- local functions --------------------------------------------------- */ - -static void bit_velle_setscl(void *data, int state) -{ - if (state) { - outb(inb(CTRL) & I2C_CMASK, CTRL); - } else { - outb(inb(CTRL) | I2C_SCL, CTRL); - } - -} - -static void bit_velle_setsda(void *data, int state) -{ - if (state) { - outb(inb(CTRL) & I2C_DMASK , CTRL); - } else { - outb(inb(CTRL) | I2C_SDA, CTRL); - } - -} - -static int bit_velle_getscl(void *data) -{ - return ( 0 == ( (inb(CTRL)) & I2C_SCLIN ) ); -} - -static int bit_velle_getsda(void *data) -{ - return ( 0 != ( (inb(STAT)) & I2C_SDAIN ) ); -} - -static int bit_velle_init(void) -{ - if (!request_region(base, (base == 0x3bc) ? 3 : 8, - "i2c (Vellemann adapter)")) - return -ENODEV; - - bit_velle_setsda((void*)base,1); - bit_velle_setscl((void*)base,1); - return 0; -} - -/* ------------------------------------------------------------------------ - * Encapsulate the above functions in the correct operations structure. - * This is only done when more than one hardware adapter is supported. - */ - -static struct i2c_algo_bit_data bit_velle_data = { - .setsda = bit_velle_setsda, - .setscl = bit_velle_setscl, - .getsda = bit_velle_getsda, - .getscl = bit_velle_getscl, - .udelay = 10, - .mdelay = 10, - .timeout = HZ -}; - -static struct i2c_adapter bit_velle_ops = { - .owner = THIS_MODULE, - .id = I2C_HW_B_VELLE, - .algo_data = &bit_velle_data, - .name = "Velleman K8000", -}; - -static int __init i2c_bitvelle_init(void) -{ - printk(KERN_INFO "i2c-velleman.o: i2c Velleman K8000 adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE); - if (base==0) { - /* probe some values */ - base=DEFAULT_BASE; - bit_velle_data.data=(void*)DEFAULT_BASE; - if (bit_velle_init()==0) { - if(i2c_bit_add_bus(&bit_velle_ops) < 0) - return -ENODEV; - } else { - return -ENODEV; - } - } else { - bit_velle_data.data=(void*)base; - if (bit_velle_init()==0) { - if(i2c_bit_add_bus(&bit_velle_ops) < 0) - return -ENODEV; - } else { - return -ENODEV; - } - } - printk(KERN_DEBUG "i2c-velleman.o: found device at %#x.\n",base); - return 0; -} - -static void __exit i2c_bitvelle_exit(void) -{ - i2c_bit_del_bus(&bit_velle_ops); - release_region(base, (base == 0x3bc) ? 3 : 8); -} - -MODULE_AUTHOR("Simon G. Vogl "); -MODULE_DESCRIPTION("I2C-Bus adapter routines for Velleman K8000 adapter"); -MODULE_LICENSE("GPL"); - -MODULE_PARM(base, "i"); - -module_init(i2c_bitvelle_init); -module_exit(i2c_bitvelle_exit); diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/scx200_acb.c i2c-2.5/drivers/i2c/scx200_acb.c --- linux-2.6.0-test5/drivers/i2c/scx200_acb.c Mon Sep 8 19:50:04 2003 +++ i2c-2.5/drivers/i2c/scx200_acb.c Thu Jan 1 00:00:00 1970 @@ -1,553 +0,0 @@ -/* linux/drivers/i2c/scx200_acb.c - - Copyright (c) 2001,2002 Christer Weinigel - - National Semiconductor SCx200 ACCESS.bus support - - Based on i2c-keywest.c which is: - Copyright (c) 2001 Benjamin Herrenschmidt - 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. - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define NAME "scx200_acb" - -MODULE_AUTHOR("Christer Weinigel "); -MODULE_DESCRIPTION("NatSemi SCx200 ACCESS.bus Driver"); -MODULE_LICENSE("GPL"); - -#define MAX_DEVICES 4 -static int base[MAX_DEVICES] = { 0x840 }; -MODULE_PARM(base, "1-4i"); -MODULE_PARM_DESC(base, "Base addresses for the ACCESS.bus controllers"); - -#define DEBUG 0 - -#if DEBUG -#define DBG(x...) printk(KERN_DEBUG NAME ": " x) -#else -#define DBG(x...) -#endif - -/* The hardware supports interrupt driven mode too, but I haven't - implemented that. */ -#define POLLED_MODE 1 -#define POLL_TIMEOUT (HZ) - -enum scx200_acb_state { - state_idle, - state_address, - state_command, - state_repeat_start, - state_quick, - state_read, - state_write, -}; - -static const char *scx200_acb_state_name[] = { - "idle", - "address", - "command", - "repeat_start", - "quick", - "read", - "write", -}; - -/* Physical interface */ -struct scx200_acb_iface -{ - struct scx200_acb_iface *next; - struct i2c_adapter adapter; - unsigned base; - struct semaphore sem; - - /* State machine data */ - enum scx200_acb_state state; - int result; - u8 address_byte; - u8 command; - u8 *ptr; - char needs_reset; - unsigned len; -}; - -/* Register Definitions */ -#define ACBSDA (iface->base + 0) -#define ACBST (iface->base + 1) -#define ACBST_SDAST 0x40 /* SDA Status */ -#define ACBST_BER 0x20 -#define ACBST_NEGACK 0x10 /* Negative Acknowledge */ -#define ACBST_STASTR 0x08 /* Stall After Start */ -#define ACBST_MASTER 0x02 -#define ACBCST (iface->base + 2) -#define ACBCST_BB 0x02 -#define ACBCTL1 (iface->base + 3) -#define ACBCTL1_STASTRE 0x80 -#define ACBCTL1_NMINTE 0x40 -#define ACBCTL1_ACK 0x10 -#define ACBCTL1_STOP 0x02 -#define ACBCTL1_START 0x01 -#define ACBADDR (iface->base + 4) -#define ACBCTL2 (iface->base + 5) -#define ACBCTL2_ENABLE 0x01 - -/************************************************************************/ - -static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) -{ - const char *errmsg; - - DBG("state %s, status = 0x%02x\n", - scx200_acb_state_name[iface->state], status); - - if (status & ACBST_BER) { - errmsg = "bus error"; - goto error; - } - if (!(status & ACBST_MASTER)) { - errmsg = "not master"; - goto error; - } - if (status & ACBST_NEGACK) - goto negack; - - switch (iface->state) { - case state_idle: - dev_warn(&iface->adapter.dev, "interrupt in idle state\n"); - break; - - case state_address: - /* Do a pointer write first */ - outb(iface->address_byte & ~1, ACBSDA); - - iface->state = state_command; - break; - - case state_command: - outb(iface->command, ACBSDA); - - if (iface->address_byte & 1) - iface->state = state_repeat_start; - else - iface->state = state_write; - break; - - case state_repeat_start: - outb(inb(ACBCTL1) | ACBCTL1_START, ACBCTL1); - /* fallthrough */ - - case state_quick: - if (iface->address_byte & 1) { - if (iface->len == 1) - outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1); - else - outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1); - outb(iface->address_byte, ACBSDA); - - iface->state = state_read; - } else { - outb(iface->address_byte, ACBSDA); - - iface->state = state_write; - } - break; - - case state_read: - /* Set ACK if receiving the last byte */ - if (iface->len == 1) - outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1); - else - outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1); - - *iface->ptr++ = inb(ACBSDA); - --iface->len; - - if (iface->len == 0) { - iface->result = 0; - iface->state = state_idle; - outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); - } - - break; - - case state_write: - if (iface->len == 0) { - iface->result = 0; - iface->state = state_idle; - outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); - break; - } - - outb(*iface->ptr++, ACBSDA); - --iface->len; - - break; - } - - return; - - negack: - DBG("negative acknowledge in state %s\n", - scx200_acb_state_name[iface->state]); - - iface->state = state_idle; - iface->result = -ENXIO; - - outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); - outb(ACBST_STASTR | ACBST_NEGACK, ACBST); - return; - - error: - dev_err(&iface->adapter.dev, "%s in state %s\n", errmsg, - scx200_acb_state_name[iface->state]); - - iface->state = state_idle; - iface->result = -EIO; - iface->needs_reset = 1; -} - -static void scx200_acb_timeout(struct scx200_acb_iface *iface) -{ - dev_err(&iface->adapter.dev, "timeout in state %s\n", - scx200_acb_state_name[iface->state]); - - iface->state = state_idle; - iface->result = -EIO; - iface->needs_reset = 1; -} - -#ifdef POLLED_MODE -static void scx200_acb_poll(struct scx200_acb_iface *iface) -{ - u8 status = 0; - unsigned long timeout; - - timeout = jiffies + POLL_TIMEOUT; - while (time_before(jiffies, timeout)) { - status = inb(ACBST); - if ((status & (ACBST_SDAST|ACBST_BER|ACBST_NEGACK)) != 0) { - scx200_acb_machine(iface, status); - return; - } - schedule_timeout(HZ/100+1); - } - - scx200_acb_timeout(iface); -} -#endif /* POLLED_MODE */ - -static void scx200_acb_reset(struct scx200_acb_iface *iface) -{ - /* Disable the ACCESS.bus device and Configure the SCL - frequency: 16 clock cycles */ - outb(0x70, ACBCTL2); - /* Polling mode */ - outb(0, ACBCTL1); - /* Disable slave address */ - outb(0, ACBADDR); - /* Enable the ACCESS.bus device */ - outb(inb(ACBCTL2) | ACBCTL2_ENABLE, ACBCTL2); - /* Free STALL after START */ - outb(inb(ACBCTL1) & ~(ACBCTL1_STASTRE | ACBCTL1_NMINTE), ACBCTL1); - /* Send a STOP */ - outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); - /* Clear BER, NEGACK and STASTR bits */ - outb(ACBST_BER | ACBST_NEGACK | ACBST_STASTR, ACBST); - /* Clear BB bit */ - outb(inb(ACBCST) | ACBCST_BB, ACBCST); -} - -static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, - u16 address, unsigned short flags, - char rw, u8 command, int size, - union i2c_smbus_data *data) -{ - struct scx200_acb_iface *iface = i2c_get_adapdata(adapter); - int len; - u8 *buffer; - u16 cur_word; - int rc; - - switch (size) { - case I2C_SMBUS_QUICK: - len = 0; - buffer = NULL; - break; - case I2C_SMBUS_BYTE: - if (rw == I2C_SMBUS_READ) { - len = 1; - buffer = &data->byte; - } else { - len = 1; - buffer = &command; - } - break; - case I2C_SMBUS_BYTE_DATA: - len = 1; - buffer = &data->byte; - break; - case I2C_SMBUS_WORD_DATA: - len = 2; - cur_word = cpu_to_le16(data->word); - buffer = (u8 *)&cur_word; - break; - case I2C_SMBUS_BLOCK_DATA: - len = data->block[0]; - buffer = &data->block[1]; - break; - default: - return -EINVAL; - } - - DBG("size=%d, address=0x%x, command=0x%x, len=%d, read=%d\n", - size, address, command, len, rw == I2C_SMBUS_READ); - - if (!len && rw == I2C_SMBUS_READ) { - dev_warn(&adapter->dev, "zero length read\n"); - return -EINVAL; - } - - if (len && !buffer) { - dev_warn(&adapter->dev, "nonzero length but no buffer\n"); - return -EFAULT; - } - - down(&iface->sem); - - iface->address_byte = address<<1; - if (rw == I2C_SMBUS_READ) - iface->address_byte |= 1; - iface->command = command; - iface->ptr = buffer; - iface->len = len; - iface->result = -EINVAL; - iface->needs_reset = 0; - - outb(inb(ACBCTL1) | ACBCTL1_START, ACBCTL1); - - if (size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE) - iface->state = state_quick; - else - iface->state = state_address; - -#ifdef POLLED_MODE - while (iface->state != state_idle) - scx200_acb_poll(iface); -#else /* POLLED_MODE */ -#error Interrupt driven mode not implemented -#endif /* POLLED_MODE */ - - if (iface->needs_reset) - scx200_acb_reset(iface); - - rc = iface->result; - - up(&iface->sem); - - if (rc == 0 && size == I2C_SMBUS_WORD_DATA && rw == I2C_SMBUS_READ) - data->word = le16_to_cpu(cur_word); - -#if DEBUG - printk(KERN_DEBUG NAME ": transfer done, result: %d", rc); - if (buffer) { - int i; - printk(" data:"); - for (i = 0; i < len; ++i) - printk(" %02x", buffer[i]); - } - printk("\n"); -#endif - - return rc; -} - -static u32 scx200_acb_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; -} - -/* For now, we only handle combined mode (smbus) */ -static struct i2c_algorithm scx200_acb_algorithm = { - .name = "NatSemi SCx200 ACCESS.bus", - .id = I2C_ALGO_SMBUS, - .smbus_xfer = scx200_acb_smbus_xfer, - .functionality = scx200_acb_func, -}; - -struct scx200_acb_iface *scx200_acb_list; - -int scx200_acb_probe(struct scx200_acb_iface *iface) -{ - u8 val; - - /* Disable the ACCESS.bus device and Configure the SCL - frequency: 16 clock cycles */ - outb(0x70, ACBCTL2); - - if (inb(ACBCTL2) != 0x70) { - DBG("ACBCTL2 readback failed\n"); - return -ENXIO; - } - - outb(inb(ACBCTL1) | ACBCTL1_NMINTE, ACBCTL1); - - val = inb(ACBCTL1); - if (val) { - DBG("disabled, but ACBCTL1=0x%02x\n", val); - return -ENXIO; - } - - outb(inb(ACBCTL2) | ACBCTL2_ENABLE, ACBCTL2); - - outb(inb(ACBCTL1) | ACBCTL1_NMINTE, ACBCTL1); - - val = inb(ACBCTL1); - if ((val & ACBCTL1_NMINTE) != ACBCTL1_NMINTE) { - DBG("enabled, but NMINTE won't be set, ACBCTL1=0x%02x\n", val); - return -ENXIO; - } - - return 0; -} - -static int __init scx200_acb_create(int base, int index) -{ - struct scx200_acb_iface *iface; - struct i2c_adapter *adapter; - int rc = 0; - char description[64]; - - iface = kmalloc(sizeof(*iface), GFP_KERNEL); - if (!iface) { - printk(KERN_ERR NAME ": can't allocate memory\n"); - rc = -ENOMEM; - goto errout; - } - - memset(iface, 0, sizeof(*iface)); - adapter = &iface->adapter; - i2c_set_adapdata(adapter, iface); - snprintf(adapter->name, DEVICE_NAME_SIZE, "SCx200 ACB%d", index); - adapter->owner = THIS_MODULE; - adapter->id = I2C_ALGO_SMBUS; - adapter->algo = &scx200_acb_algorithm; - - init_MUTEX(&iface->sem); - - snprintf(description, sizeof(description), "NatSemi SCx200 ACCESS.bus [%s]", adapter->name); - if (request_region(base, 8, description) == 0) { - dev_err(&adapter->dev, "can't allocate io 0x%x-0x%x\n", - base, base + 8-1); - rc = -EBUSY; - goto errout; - } - iface->base = base; - - rc = scx200_acb_probe(iface); - if (rc) { - dev_warn(&adapter->dev, "probe failed\n"); - goto errout; - } - - scx200_acb_reset(iface); - - if (i2c_add_adapter(adapter) < 0) { - dev_err(&adapter->dev, "failed to register\n"); - rc = -ENODEV; - goto errout; - } - - lock_kernel(); - iface->next = scx200_acb_list; - scx200_acb_list = iface; - unlock_kernel(); - - return 0; - - errout: - if (iface) { - if (iface->base) - release_region(iface->base, 8); - kfree(iface); - } - return rc; -} - -static int __init scx200_acb_init(void) -{ - int i; - int rc; - - printk(KERN_DEBUG NAME ": NatSemi SCx200 ACCESS.bus Driver\n"); - - /* Verify that this really is a SCx200 processor */ - if (pci_find_device(PCI_VENDOR_ID_NS, - PCI_DEVICE_ID_NS_SCx200_BRIDGE, - NULL) == NULL) - return -ENODEV; - - rc = -ENXIO; - for (i = 0; i < MAX_DEVICES; ++i) { - if (base[i] > 0) - rc = scx200_acb_create(base[i], i); - } - if (scx200_acb_list) - return 0; - return rc; -} - -static void __exit scx200_acb_cleanup(void) -{ - struct scx200_acb_iface *iface; - lock_kernel(); - while ((iface = scx200_acb_list) != NULL) { - scx200_acb_list = iface->next; - unlock_kernel(); - - i2c_del_adapter(&iface->adapter); - release_region(iface->base, 8); - kfree(iface); - lock_kernel(); - } - unlock_kernel(); -} - -module_init(scx200_acb_init); -module_exit(scx200_acb_cleanup); - -/* - Local variables: - compile-command: "make -k -C ../.. SUBDIRS=drivers/i2c modules" - c-basic-offset: 8 - End: -*/ - diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/i2c/scx200_i2c.c i2c-2.5/drivers/i2c/scx200_i2c.c --- linux-2.6.0-test5/drivers/i2c/scx200_i2c.c Mon Sep 8 19:50:03 2003 +++ i2c-2.5/drivers/i2c/scx200_i2c.c Thu Jan 1 00:00:00 1970 @@ -1,133 +0,0 @@ -/* linux/drivers/i2c/scx200_i2c.c - - Copyright (c) 2001,2002 Christer Weinigel - - National Semiconductor SCx200 I2C bus on GPIO pins - - Based on i2c-velleman.c Copyright (C) 1995-96, 2000 Simon G. 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. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define NAME "scx200_i2c" - -MODULE_AUTHOR("Christer Weinigel "); -MODULE_DESCRIPTION("NatSemi SCx200 I2C Driver"); -MODULE_LICENSE("GPL"); - -MODULE_PARM(scl, "i"); -MODULE_PARM_DESC(scl, "GPIO line for SCL"); -MODULE_PARM(sda, "i"); -MODULE_PARM_DESC(sda, "GPIO line for SDA"); - -static int scl = CONFIG_SCx200_I2C_SCL; -static int sda = CONFIG_SCx200_I2C_SDA; - -static void scx200_i2c_setscl(void *data, int state) -{ - scx200_gpio_set(scl, state); -} - -static void scx200_i2c_setsda(void *data, int state) -{ - scx200_gpio_set(sda, state); -} - -static int scx200_i2c_getscl(void *data) -{ - return scx200_gpio_get(scl); -} - -static int scx200_i2c_getsda(void *data) -{ - return scx200_gpio_get(sda); -} - -/* ------------------------------------------------------------------------ - * Encapsulate the above functions in the correct operations structure. - * This is only done when more than one hardware adapter is supported. - */ - -static struct i2c_algo_bit_data scx200_i2c_data = { - NULL, - scx200_i2c_setsda, - scx200_i2c_setscl, - scx200_i2c_getsda, - scx200_i2c_getscl, - 10, 10, 100, /* waits, timeout */ -}; - -static struct i2c_adapter scx200_i2c_ops = { - .owner = THIS_MODULE, - .id = I2C_HW_B_VELLE, - .algo_data = &scx200_i2c_data, - .name = "NatSemi SCx200 I2C", -}; - -int scx200_i2c_init(void) -{ - printk(KERN_DEBUG NAME ": NatSemi SCx200 I2C Driver\n"); - - if (!scx200_gpio_present()) { - printk(KERN_ERR NAME ": no SCx200 gpio pins available\n"); - return -ENODEV; - } - - printk(KERN_DEBUG NAME ": SCL=GPIO%02u, SDA=GPIO%02u\n", - scl, sda); - - if (scl == -1 || sda == -1 || scl == sda) { - printk(KERN_ERR NAME ": scl and sda must be specified\n"); - return -EINVAL; - } - - /* Configure GPIOs as open collector outputs */ - scx200_gpio_configure(scl, ~2, 5); - scx200_gpio_configure(sda, ~2, 5); - - if (i2c_bit_add_bus(&scx200_i2c_ops) < 0) { - printk(KERN_ERR NAME ": adapter %s registration failed\n", - scx200_i2c_ops.name); - return -ENODEV; - } - - return 0; -} - -void scx200_i2c_cleanup(void) -{ - i2c_bit_del_bus(&scx200_i2c_ops); -} - -module_init(scx200_i2c_init); -module_exit(scx200_i2c_cleanup); - -/* - Local variables: - compile-command: "make -k -C ../.. SUBDIRS=drivers/i2c modules" - c-basic-offset: 8 - End: -*/ diff -Nur --exclude SCCS linux-2.6.0-test5/drivers/ide/pci/siimage.c i2c-2.5/drivers/ide/pci/siimage.c --- linux-2.6.0-test5/drivers/ide/pci/siimage.c Tue Sep 23 10:23:56 2003 +++ i2c-2.5/drivers/ide/pci/siimage.c Tue Sep 23 10:13:01 2003 @@ -1065,8 +1065,8 @@ hwif->hwif_data = 0; hwif->rqsize = 128; -// if (is_sata(hwif)) -// hwif->rqsize = 15; + if (is_sata(hwif)) + hwif->rqsize = 15; if (pci_get_drvdata(dev) == NULL) return; diff -Nur --exclude SCCS linux-2.6.0-test5/include/linux/i2c-id.h i2c-2.5/include/linux/i2c-id.h --- linux-2.6.0-test5/include/linux/i2c-id.h Mon Sep 8 19:49:52 2003 +++ i2c-2.5/include/linux/i2c-id.h Tue Sep 23 10:15:09 2003 @@ -100,7 +100,7 @@ #define I2C_DRIVERID_STM41T00 52 /* real time clock */ #define I2C_DRIVERID_UDA1342 53 /* UDA1342 audio codec */ #define I2C_DRIVERID_ADV7170 54 /* video encoder */ - +#define I2C_DRIVERID_RADEON 55 /* I2C bus on Radeon boards */ #define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */ diff -Nur --exclude SCCS linux-2.6.0-test5/include/linux/i2c.h i2c-2.5/include/linux/i2c.h --- linux-2.6.0-test5/include/linux/i2c.h Mon Sep 8 19:49:54 2003 +++ i2c-2.5/include/linux/i2c.h Tue Sep 23 10:15:09 2003 @@ -28,9 +28,6 @@ #ifndef _LINUX_I2C_H #define _LINUX_I2C_H -#define I2C_DATE "20021208" -#define I2C_VERSION "2.7.0" - #include #include #include @@ -146,6 +143,8 @@ extern struct bus_type i2c_bus_type; +#define I2C_NAME_SIZE 50 + /* * i2c_client identifies a single device (i.e. chip) that is connected to an * i2c bus. The behaviour is defined by the routines of the driver. This @@ -166,7 +165,7 @@ /* to the client */ struct device dev; /* the device structure */ struct list_head list; - char name[DEVICE_NAME_SIZE]; + char name[I2C_NAME_SIZE]; struct completion released; }; #define to_i2c_client(d) container_of(d, struct i2c_client, dev) @@ -253,7 +252,7 @@ int nr; struct list_head clients; struct list_head list; - char name[DEVICE_NAME_SIZE]; + char name[I2C_NAME_SIZE]; struct completion dev_released; struct completion class_dev_released; };