From 9880bfe240aa6ea81cfb1588cd064a0560e6d3c4 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sun, 27 Jan 2008 15:38:44 +0800 Subject: [PATCH] --- yaml --- r: 77356 b: refs/heads/master c: f53e86760e10abbe7ee98a5b3cb270fa6426fcdb h: refs/heads/master v: v3 --- [refs] | 2 +- .../feature-removal-schedule.txt | 31 +- trunk/Documentation/i2c/busses/i2c-i801 | 5 +- trunk/Documentation/i2c/busses/i2c-viapro | 3 +- trunk/Documentation/i2c/chips/pcf8575 | 72 --- trunk/Documentation/i2c/i2c-stub | 6 +- trunk/Documentation/i2c/writing-clients | 6 +- trunk/arch/arm/mach-ixp4xx/avila-setup.c | 14 +- trunk/arch/arm/mach-ixp4xx/dsmg600-setup.c | 13 +- trunk/arch/arm/mach-ixp4xx/ixdp425-setup.c | 14 +- trunk/arch/arm/mach-ixp4xx/nas100d-setup.c | 14 +- trunk/arch/arm/mach-ixp4xx/nslu2-setup.c | 14 +- trunk/arch/arm/mach-omap1/board-h2.c | 2 +- trunk/arch/arm/mach-omap1/board-h3.c | 2 +- trunk/arch/arm/mach-omap1/board-osk.c | 3 +- trunk/arch/arm/mach-omap1/leds-osk.c | 2 +- trunk/arch/arm/mach-pxa/akita-ioexp.c | 2 +- trunk/arch/arm/mach-pxa/pxa27x.c | 6 - trunk/arch/blackfin/mach-common/cplbmgr.S | 15 +- trunk/arch/mips/au1000/common/platform.c | 21 - trunk/arch/ppc/platforms/83xx/mpc834x_sys.c | 20 + trunk/arch/ppc/platforms/85xx/tqm85xx.c | 21 + trunk/arch/ppc/platforms/katana.c | 21 + trunk/drivers/i2c/algos/i2c-algo-bit.c | 226 +++++----- trunk/drivers/i2c/algos/i2c-algo-pcf.c | 85 +++- trunk/drivers/i2c/busses/Kconfig | 33 +- trunk/drivers/i2c/busses/Makefile | 1 + trunk/drivers/i2c/busses/i2c-amd756.c | 5 - trunk/drivers/i2c/busses/i2c-au1550.c | 177 +++----- trunk/drivers/i2c/busses/i2c-au1550.h | 32 ++ trunk/drivers/i2c/busses/i2c-bfin-twi.c | 3 +- trunk/drivers/i2c/busses/i2c-davinci.c | 1 + trunk/drivers/i2c/busses/i2c-i801.c | 163 +++---- trunk/drivers/i2c/busses/i2c-ibm_iic.c | 191 ++++---- trunk/drivers/i2c/busses/i2c-ibm_iic.h | 8 +- trunk/drivers/i2c/busses/i2c-iop3xx.c | 1 + trunk/drivers/i2c/busses/i2c-ixp4xx.c | 178 ++++++++ trunk/drivers/i2c/busses/i2c-mpc.c | 29 +- trunk/drivers/i2c/busses/i2c-nforce2.c | 1 - trunk/drivers/i2c/busses/i2c-omap.c | 2 + trunk/drivers/i2c/busses/i2c-pasemi.c | 3 +- trunk/drivers/i2c/busses/i2c-piix4.c | 41 +- trunk/drivers/i2c/busses/i2c-pxa.c | 189 ++------ trunk/drivers/i2c/busses/i2c-sibyte.c | 29 +- trunk/drivers/i2c/busses/i2c-stub.c | 15 +- trunk/drivers/i2c/busses/i2c-viapro.c | 11 +- trunk/drivers/i2c/chips/Kconfig | 58 ++- trunk/drivers/i2c/chips/Makefile | 4 +- trunk/drivers/i2c/chips/ds1337.c | 410 +++++++++++++++++ trunk/drivers/i2c/chips/ds1374.c | 267 +++++++++++ trunk/drivers/i2c/chips/eeprom.c | 2 +- trunk/drivers/i2c/chips/isp1301_omap.c | 2 +- trunk/drivers/i2c/chips/m41t00.c | 413 ++++++++++++++++++ trunk/drivers/i2c/chips/max6875.c | 2 +- trunk/drivers/i2c/chips/pcf8574.c | 8 +- trunk/drivers/i2c/chips/pcf8575.c | 214 --------- trunk/drivers/i2c/chips/pcf8591.c | 2 +- trunk/drivers/i2c/chips/tps65010.c | 2 +- trunk/drivers/i2c/chips/tsl2550.c | 21 - trunk/drivers/i2c/i2c-core.c | 352 +++++++-------- trunk/drivers/i2c/i2c-dev.c | 29 +- trunk/drivers/macintosh/therm_windtunnel.c | 5 +- trunk/drivers/media/video/dpc7146.c | 19 +- trunk/drivers/media/video/ks0127.c | 1 + trunk/drivers/media/video/mxb.c | 40 +- trunk/drivers/media/video/vino.c | 22 +- trunk/drivers/mmc/host/omap.c | 2 +- trunk/drivers/rtc/rtc-ds1672.c | 2 +- trunk/drivers/rtc/rtc-isl1208.c | 2 +- trunk/drivers/rtc/rtc-max6900.c | 2 +- trunk/drivers/rtc/rtc-pcf8563.c | 2 +- trunk/drivers/rtc/rtc-pcf8583.c | 2 +- trunk/drivers/rtc/rtc-x1205.c | 2 +- trunk/drivers/usb/host/ohci-omap.c | 2 +- trunk/drivers/usb/host/ohci-pnx4008.c | 5 +- trunk/drivers/video/matrox/matroxfb_maven.c | 2 +- trunk/drivers/video/omap/lcd_h3.c | 2 +- trunk/drivers/w1/masters/ds2482.c | 2 +- trunk/include/asm-arm/arch-ixp4xx/platform.h | 11 + .../i2c => asm-arm/arch-omap}/tps65010.h | 8 +- trunk/include/asm-arm/arch-pxa/i2c.h | 6 - trunk/include/linux/i2c-id.h | 63 +++ trunk/include/linux/i2c.h | 126 +++--- trunk/include/linux/m41t00.h | 50 +++ trunk/include/media/v4l2-i2c-drv-legacy.h | 2 +- trunk/sound/ppc/keywest.c | 3 + trunk/sound/soc/codecs/cs4270.c | 2 +- trunk/sound/soc/s3c24xx/neo1973_wm8753.c | 2 +- 88 files changed, 2463 insertions(+), 1443 deletions(-) delete mode 100644 trunk/Documentation/i2c/chips/pcf8575 create mode 100644 trunk/drivers/i2c/busses/i2c-au1550.h create mode 100644 trunk/drivers/i2c/busses/i2c-ixp4xx.c create mode 100644 trunk/drivers/i2c/chips/ds1337.c create mode 100644 trunk/drivers/i2c/chips/ds1374.c create mode 100644 trunk/drivers/i2c/chips/m41t00.c delete mode 100644 trunk/drivers/i2c/chips/pcf8575.c rename trunk/include/{linux/i2c => asm-arm/arch-omap}/tps65010.h (97%) create mode 100644 trunk/include/linux/m41t00.h diff --git a/[refs] b/[refs] index c7193570cb79..de00fd06b074 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 991dee591a99d035796a8c194eb1796cc020e142 +refs/heads/master: f53e86760e10abbe7ee98a5b3cb270fa6426fcdb diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt index 25370662cc5d..9b8291f4c211 100644 --- a/trunk/Documentation/feature-removal-schedule.txt +++ b/trunk/Documentation/feature-removal-schedule.txt @@ -191,6 +191,15 @@ Who: Kay Sievers --------------------------- +What: i2c_adapter.list +When: July 2007 +Why: Superfluous, this list duplicates the one maintained by the driver + core. +Who: Jean Delvare , + David Brownell + +--------------------------- + What: ACPI procfs interface When: July 2008 Why: ACPI sysfs conversion should be finished by January 2008. @@ -216,6 +225,14 @@ Who: Len Brown --------------------------- +What: i2c-ixp2000, i2c-ixp4xx and scx200_i2c drivers +When: September 2007 +Why: Obsolete. The new i2c-gpio driver replaces all hardware-specific + I2C-over-GPIO drivers. +Who: Jean Delvare + +--------------------------- + What: 'time' kernel boot parameter When: January 2008 Why: replaced by 'printk.time=' so that printk timestamps can be @@ -249,6 +266,13 @@ Who: Tejun Heo --------------------------- +What: Legacy RTC drivers (under drivers/i2c/chips) +When: November 2007 +Why: Obsolete. We have a RTC subsystem with better drivers. +Who: Jean Delvare + +--------------------------- + What: iptables SAME target When: 1.1. 2008 Files: net/ipv4/netfilter/ipt_SAME.c, include/linux/netfilter_ipv4/ipt_SAME.h @@ -299,10 +323,3 @@ Why: This driver has been marked obsolete for many years. Who: Stephen Hemminger --------------------------- - -What: i2c-i810, i2c-prosavage and i2c-savage4 -When: May 2008 -Why: These drivers are superseded by i810fb, intelfb and savagefb. -Who: Jean Delvare - ---------------------------- diff --git a/trunk/Documentation/i2c/busses/i2c-i801 b/trunk/Documentation/i2c/busses/i2c-i801 index 3bd958360159..fde4420e3f75 100644 --- a/trunk/Documentation/i2c/busses/i2c-i801 +++ b/trunk/Documentation/i2c/busses/i2c-i801 @@ -17,8 +17,9 @@ Supported adapters: Datasheets: Publicly available at the Intel website Authors: + Frodo Looijaard , + Philip Edelbrock , Mark Studebaker - Jean Delvare Module Parameters @@ -61,7 +62,7 @@ Not supported. I2C Block Read Support ---------------------- -I2C block read is supported on the 82801EB (ICH5) and later chips. +Not supported at the moment. SMBus 2.0 Support diff --git a/trunk/Documentation/i2c/busses/i2c-viapro b/trunk/Documentation/i2c/busses/i2c-viapro index 1405fb69984c..06b4be3ef6d8 100644 --- a/trunk/Documentation/i2c/busses/i2c-viapro +++ b/trunk/Documentation/i2c/busses/i2c-viapro @@ -10,7 +10,7 @@ Supported adapters: * VIA Technologies, Inc. VT8231, VT8233, VT8233A Datasheet: available on request from VIA - * VIA Technologies, Inc. VT8235, VT8237R, VT8237A, VT8237S, VT8251 + * VIA Technologies, Inc. VT8235, VT8237R, VT8237A, VT8251 Datasheet: available on request and under NDA from VIA * VIA Technologies, Inc. CX700 @@ -46,7 +46,6 @@ Your lspci -n listing must show one of these : device 1106:3177 (VT8235) device 1106:3227 (VT8237R) device 1106:3337 (VT8237A) - device 1106:3372 (VT8237S) device 1106:3287 (VT8251) device 1106:8324 (CX700) diff --git a/trunk/Documentation/i2c/chips/pcf8575 b/trunk/Documentation/i2c/chips/pcf8575 deleted file mode 100644 index 25f5698a61cf..000000000000 --- a/trunk/Documentation/i2c/chips/pcf8575 +++ /dev/null @@ -1,72 +0,0 @@ -About the PCF8575 chip and the pcf8575 kernel driver -==================================================== - -The PCF8575 chip is produced by the following manufacturers: - - * Philips NXP - http://www.nxp.com/#/pip/cb=[type=product,path=50807/41735/41850,final=PCF8575_3]|pip=[pip=PCF8575_3][0] - - * Texas Instruments - http://focus.ti.com/docs/prod/folders/print/pcf8575.html - - -Some vendors sell small PCB's with the PCF8575 mounted on it. You can connect -such a board to a Linux host via e.g. an USB to I2C interface. Examples of -PCB boards with a PCF8575: - - * SFE Breakout Board for PCF8575 I2C Expander by RobotShop - http://www.robotshop.ca/home/products/robot-parts/electronics/adapters-converters/sfe-pcf8575-i2c-expander-board.html - - * Breakout Board for PCF8575 I2C Expander by Spark Fun Electronics - http://www.sparkfun.com/commerce/product_info.php?products_id=8130 - - -Description ------------ -The PCF8575 chip is a 16-bit I/O expander for the I2C bus. Up to eight of -these chips can be connected to the same I2C bus. You can find this -chip on some custom designed hardware, but you won't find it on PC -motherboards. - -The PCF8575 chip consists of a 16-bit quasi-bidirectional port and an I2C-bus -interface. Each of the sixteen I/O's can be independently used as an input or -an output. To set up an I/O pin as an input, you have to write a 1 to the -corresponding output. - -For more information please see the datasheet. - - -Detection ---------- - -There is no method known to detect whether a chip on a given I2C address is -a PCF8575 or whether it is any other I2C device. So there are two alternatives -to let the driver find the installed PCF8575 devices: -- Load this driver after any other I2C driver for I2C devices with addresses - in the range 0x20 .. 0x27. -- Pass the I2C bus and address of the installed PCF8575 devices explicitly to - the driver at load time via the probe=... or force=... parameters. - -/sys interface --------------- - -For each address on which a PCF8575 chip was found or forced the following -files will be created under /sys: -* /sys/bus/i2c/devices/-
/read -* /sys/bus/i2c/devices/-
/write -where bus is the I2C bus number (0, 1, ...) and address is the four-digit -hexadecimal representation of the 7-bit I2C address of the PCF8575 -(0020 .. 0027). - -The read file is read-only. Reading it will trigger an I2C read and will hence -report the current input state for the pins configured as inputs, and the -current output value for the pins configured as outputs. - -The write file is read-write. Writing a value to it will configure all pins -as output for which the corresponding bit is zero. Reading the write file will -return the value last written, or -EAGAIN if no value has yet been written to -the write file. - -On module initialization the configuration of the chip is not changed -- the -chip is left in the state it was already configured in through either power-up -or through previous I2C write actions. diff --git a/trunk/Documentation/i2c/i2c-stub b/trunk/Documentation/i2c/i2c-stub index 0d8be1c20c16..89e69ad3436c 100644 --- a/trunk/Documentation/i2c/i2c-stub +++ b/trunk/Documentation/i2c/i2c-stub @@ -25,9 +25,6 @@ The typical use-case is like this: 3. load the target sensors chip driver module 4. observe its behavior in the kernel log -There's a script named i2c-stub-from-dump in the i2c-tools package which -can load register values automatically from a chip dump. - PARAMETERS: int chip_addr[10]: @@ -35,6 +32,9 @@ int chip_addr[10]: CAVEATS: +There are independent arrays for byte/data and word/data commands. Depending +on if/how a target driver mixes them, you'll need to be careful. + If your target driver polls some byte or word waiting for it to change, the stub could lock it up. Use i2cset to unlock it. diff --git a/trunk/Documentation/i2c/writing-clients b/trunk/Documentation/i2c/writing-clients index bfb0a5520817..2c170032bf37 100644 --- a/trunk/Documentation/i2c/writing-clients +++ b/trunk/Documentation/i2c/writing-clients @@ -267,9 +267,9 @@ insmod parameter of the form force_. Fortunately, as a module writer, you just have to define the `normal_i2c' parameter. The complete declaration could look like this: - /* Scan 0x4c to 0x4f */ - static const unsigned short normal_i2c[] = { 0x4c, 0x4d, 0x4e, 0x4f, - I2C_CLIENT_END }; + /* Scan 0x37, and 0x48 to 0x4f */ + static unsigned short normal_i2c[] = { 0x37, 0x48, 0x49, 0x4a, 0x4b, 0x4c, + 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; /* Magic definition of all other variables and things */ I2C_CLIENT_INSMOD; diff --git a/trunk/arch/arm/mach-ixp4xx/avila-setup.c b/trunk/arch/arm/mach-ixp4xx/avila-setup.c index e38f45fa58ae..d59b8dc7dc7a 100644 --- a/trunk/arch/arm/mach-ixp4xx/avila-setup.c +++ b/trunk/arch/arm/mach-ixp4xx/avila-setup.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -48,17 +47,18 @@ static struct platform_device avila_flash = { .resource = &avila_flash_resource, }; -static struct i2c_gpio_platform_data avila_i2c_gpio_data = { +static struct ixp4xx_i2c_pins avila_i2c_gpio_pins = { .sda_pin = AVILA_SDA_PIN, .scl_pin = AVILA_SCL_PIN, }; -static struct platform_device avila_i2c_gpio = { - .name = "i2c-gpio", +static struct platform_device avila_i2c_controller = { + .name = "IXP4XX-I2C", .id = 0, - .dev = { - .platform_data = &avila_i2c_gpio_data, + .dev = { + .platform_data = &avila_i2c_gpio_pins, }, + .num_resources = 0 }; static struct resource avila_uart_resources[] = { @@ -133,7 +133,7 @@ static struct platform_device avila_pata = { }; static struct platform_device *avila_devices[] __initdata = { - &avila_i2c_gpio, + &avila_i2c_controller, &avila_flash, &avila_uart }; diff --git a/trunk/arch/arm/mach-ixp4xx/dsmg600-setup.c b/trunk/arch/arm/mach-ixp4xx/dsmg600-setup.c index c473d408aa7c..1e75e105c4f7 100644 --- a/trunk/arch/arm/mach-ixp4xx/dsmg600-setup.c +++ b/trunk/arch/arm/mach-ixp4xx/dsmg600-setup.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include @@ -38,17 +37,15 @@ static struct platform_device dsmg600_flash = { .resource = &dsmg600_flash_resource, }; -static struct i2c_gpio_platform_data dsmg600_i2c_gpio_data = { +static struct ixp4xx_i2c_pins dsmg600_i2c_gpio_pins = { .sda_pin = DSMG600_SDA_PIN, .scl_pin = DSMG600_SCL_PIN, }; -static struct platform_device dsmg600_i2c_gpio = { - .name = "i2c-gpio", +static struct platform_device dsmg600_i2c_controller = { + .name = "IXP4XX-I2C", .id = 0, - .dev = { - .platform_data = &dsmg600_i2c_gpio_data, - }, + .dev.platform_data = &dsmg600_i2c_gpio_pins, }; #ifdef CONFIG_LEDS_CLASS @@ -119,7 +116,7 @@ static struct platform_device dsmg600_uart = { }; static struct platform_device *dsmg600_devices[] __initdata = { - &dsmg600_i2c_gpio, + &dsmg600_i2c_controller, &dsmg600_flash, }; diff --git a/trunk/arch/arm/mach-ixp4xx/ixdp425-setup.c b/trunk/arch/arm/mach-ixp4xx/ixdp425-setup.c index e89070da28bf..d5008d8fc9a5 100644 --- a/trunk/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/trunk/arch/arm/mach-ixp4xx/ixdp425-setup.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -121,17 +120,18 @@ static struct platform_device ixdp425_flash_nand = { }; #endif /* CONFIG_MTD_NAND_PLATFORM */ -static struct i2c_gpio_platform_data ixdp425_i2c_gpio_data = { +static struct ixp4xx_i2c_pins ixdp425_i2c_gpio_pins = { .sda_pin = IXDP425_SDA_PIN, .scl_pin = IXDP425_SCL_PIN, }; -static struct platform_device ixdp425_i2c_gpio = { - .name = "i2c-gpio", +static struct platform_device ixdp425_i2c_controller = { + .name = "IXP4XX-I2C", .id = 0, - .dev = { - .platform_data = &ixdp425_i2c_gpio_data, + .dev = { + .platform_data = &ixdp425_i2c_gpio_pins, }, + .num_resources = 0 }; static struct resource ixdp425_uart_resources[] = { @@ -178,7 +178,7 @@ static struct platform_device ixdp425_uart = { }; static struct platform_device *ixdp425_devices[] __initdata = { - &ixdp425_i2c_gpio, + &ixdp425_i2c_controller, &ixdp425_flash, #if defined(CONFIG_MTD_NAND_PLATFORM) || \ defined(CONFIG_MTD_NAND_PLATFORM_MODULE) diff --git a/trunk/arch/arm/mach-ixp4xx/nas100d-setup.c b/trunk/arch/arm/mach-ixp4xx/nas100d-setup.c index 54d884fb2517..78a17413ceca 100644 --- a/trunk/arch/arm/mach-ixp4xx/nas100d-setup.c +++ b/trunk/arch/arm/mach-ixp4xx/nas100d-setup.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -69,17 +68,16 @@ static struct platform_device nas100d_leds = { }; #endif -static struct i2c_gpio_platform_data nas100d_i2c_gpio_data = { +static struct ixp4xx_i2c_pins nas100d_i2c_gpio_pins = { .sda_pin = NAS100D_SDA_PIN, .scl_pin = NAS100D_SCL_PIN, }; -static struct platform_device nas100d_i2c_gpio = { - .name = "i2c-gpio", +static struct platform_device nas100d_i2c_controller = { + .name = "IXP4XX-I2C", .id = 0, - .dev = { - .platform_data = &nas100d_i2c_gpio_data, - }, + .dev.platform_data = &nas100d_i2c_gpio_pins, + .num_resources = 0, }; static struct resource nas100d_uart_resources[] = { @@ -126,7 +124,7 @@ static struct platform_device nas100d_uart = { }; static struct platform_device *nas100d_devices[] __initdata = { - &nas100d_i2c_gpio, + &nas100d_i2c_controller, &nas100d_flash, #ifdef CONFIG_LEDS_IXP4XX &nas100d_leds, diff --git a/trunk/arch/arm/mach-ixp4xx/nslu2-setup.c b/trunk/arch/arm/mach-ixp4xx/nslu2-setup.c index 77277d27fcc5..9bf8ccbcaccf 100644 --- a/trunk/arch/arm/mach-ixp4xx/nslu2-setup.c +++ b/trunk/arch/arm/mach-ixp4xx/nslu2-setup.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -42,7 +41,7 @@ static struct platform_device nslu2_flash = { .resource = &nslu2_flash_resource, }; -static struct i2c_gpio_platform_data nslu2_i2c_gpio_data = { +static struct ixp4xx_i2c_pins nslu2_i2c_gpio_pins = { .sda_pin = NSLU2_SDA_PIN, .scl_pin = NSLU2_SCL_PIN, }; @@ -83,12 +82,11 @@ static struct platform_device nslu2_leds = { }; #endif -static struct platform_device nslu2_i2c_gpio = { - .name = "i2c-gpio", +static struct platform_device nslu2_i2c_controller = { + .name = "IXP4XX-I2C", .id = 0, - .dev = { - .platform_data = &nslu2_i2c_gpio_data, - }, + .dev.platform_data = &nslu2_i2c_gpio_pins, + .num_resources = 0, }; static struct platform_device nslu2_beeper = { @@ -141,7 +139,7 @@ static struct platform_device nslu2_uart = { }; static struct platform_device *nslu2_devices[] __initdata = { - &nslu2_i2c_gpio, + &nslu2_i2c_controller, &nslu2_flash, &nslu2_beeper, #ifdef CONFIG_LEDS_IXP4XX diff --git a/trunk/arch/arm/mach-omap1/board-h2.c b/trunk/arch/arm/mach-omap1/board-h2.c index 9393824cc150..130681201c19 100644 --- a/trunk/arch/arm/mach-omap1/board-h2.c +++ b/trunk/arch/arm/mach-omap1/board-h2.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -37,6 +36,7 @@ #include #include +#include #include #include #include diff --git a/trunk/arch/arm/mach-omap1/board-h3.c b/trunk/arch/arm/mach-omap1/board-h3.c index 978cdab16535..4f84ae273a1f 100644 --- a/trunk/arch/arm/mach-omap1/board-h3.c +++ b/trunk/arch/arm/mach-omap1/board-h3.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -38,6 +37,7 @@ #include #include +#include #include #include #include diff --git a/trunk/arch/arm/mach-omap1/board-osk.c b/trunk/arch/arm/mach-omap1/board-osk.c index 5b575e687a2a..5db182da322b 100644 --- a/trunk/arch/arm/mach-omap1/board-osk.c +++ b/trunk/arch/arm/mach-omap1/board-osk.c @@ -37,8 +37,6 @@ #include #include -#include - #include #include @@ -48,6 +46,7 @@ #include #include +#include #include #include #include diff --git a/trunk/arch/arm/mach-omap1/leds-osk.c b/trunk/arch/arm/mach-omap1/leds-osk.c index 6939d5e7569a..86de303ecab2 100644 --- a/trunk/arch/arm/mach-omap1/leds-osk.c +++ b/trunk/arch/arm/mach-omap1/leds-osk.c @@ -5,13 +5,13 @@ */ #include #include -#include #include #include #include #include +#include #include "leds.h" diff --git a/trunk/arch/arm/mach-pxa/akita-ioexp.c b/trunk/arch/arm/mach-pxa/akita-ioexp.c index 254892ac30cd..12d2fe0ceff6 100644 --- a/trunk/arch/arm/mach-pxa/akita-ioexp.c +++ b/trunk/arch/arm/mach-pxa/akita-ioexp.c @@ -29,7 +29,7 @@ #define MAX7310_TIMEOUT 0x04 /* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x18, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x18, I2C_CLIENT_END }; /* I2C Magic */ I2C_CLIENT_INSMOD; diff --git a/trunk/arch/arm/mach-pxa/pxa27x.c b/trunk/arch/arm/mach-pxa/pxa27x.c index 57efebdc4324..8e126e6b74c3 100644 --- a/trunk/arch/arm/mach-pxa/pxa27x.c +++ b/trunk/arch/arm/mach-pxa/pxa27x.c @@ -24,7 +24,6 @@ #include #include #include -#include #include "generic.h" #include "devices.h" @@ -424,11 +423,6 @@ struct platform_device pxa27x_device_i2c_power = { .num_resources = ARRAY_SIZE(i2c_power_resources), }; -void __init pxa_set_i2c_power_info(struct i2c_pxa_platform_data *info) -{ - pxa27x_device_i2c_power.dev.platform_data = info; -} - static struct platform_device *devices[] __initdata = { &pxa_device_mci, &pxa_device_udc, diff --git a/trunk/arch/blackfin/mach-common/cplbmgr.S b/trunk/arch/blackfin/mach-common/cplbmgr.S index 6f909cbfac7b..faca1ab344d2 100644 --- a/trunk/arch/blackfin/mach-common/cplbmgr.S +++ b/trunk/arch/blackfin/mach-common/cplbmgr.S @@ -75,6 +75,15 @@ ENTRY(_cplb_mgr) * from the configuration table. */ + /* A multi-word instruction can cross a page boundary. This means the + * first part of the instruction can be in a valid page, but the + * second part is not, and hence generates the instruction miss. + * However, the fault address is for the start of the instruction, + * not the part that's in the bad page. Therefore, we have to check + * whether the fault address applies to a page that is already present + * in the table. + */ + P4.L = LO(ICPLB_FAULT_ADDR); P4.H = HI(ICPLB_FAULT_ADDR); @@ -87,7 +96,7 @@ ENTRY(_cplb_mgr) R4 = [P4]; /* Get faulting address*/ R6 = 64; /* Advance past the fault address, which*/ R6 = R6 + R4; /* we'll use if we find a match*/ - R3 = ((16 << 8) | 2); /* Extract mask, bits 16 and 17.*/ + R3 = ((16 << 8) | 2); /* Extract mask, two bits at posn 16 */ R5 = 0; .Lisearch: @@ -125,7 +134,9 @@ ENTRY(_cplb_mgr) P4.L = LO(IMEM_CONTROL); P4.H = HI(IMEM_CONTROL); - /* disable cplbs */ + /* Turn off CPLBs while we work, necessary according to HRM before + * modifying CPLB descriptors + */ R5 = [P4]; /* Control Register*/ BITCLR(R5,ENICPLB_P); CLI R1; diff --git a/trunk/arch/mips/au1000/common/platform.c b/trunk/arch/mips/au1000/common/platform.c index 841904cdef4d..d51e18fb789b 100644 --- a/trunk/arch/mips/au1000/common/platform.c +++ b/trunk/arch/mips/au1000/common/platform.c @@ -270,24 +270,6 @@ static struct platform_device smc91x_device = { #endif -/* All Alchemy demoboards with I2C have this #define in their headers */ -#ifdef SMBUS_PSC_BASE -static struct resource pbdb_smbus_resources[] = { - { - .start = SMBUS_PSC_BASE, - .end = SMBUS_PSC_BASE + 0x24 - 1, - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device pbdb_smbus_device = { - .name = "au1xpsc_smbus", - .id = 0, /* bus number */ - .num_resources = ARRAY_SIZE(pbdb_smbus_resources), - .resource = pbdb_smbus_resources, -}; -#endif - static struct platform_device *au1xxx_platform_devices[] __initdata = { &au1xxx_usb_ohci_device, &au1x00_pcmcia_device, @@ -305,9 +287,6 @@ static struct platform_device *au1xxx_platform_devices[] __initdata = { #ifdef CONFIG_MIPS_DB1200 &smc91x_device, #endif -#ifdef SMBUS_PSC_BASE - &pbdb_smbus_device, -#endif }; int __init au1xxx_platform_init(void) diff --git a/trunk/arch/ppc/platforms/83xx/mpc834x_sys.c b/trunk/arch/ppc/platforms/83xx/mpc834x_sys.c index cb0a7493ff64..b84f8df325c4 100644 --- a/trunk/arch/ppc/platforms/83xx/mpc834x_sys.c +++ b/trunk/arch/ppc/platforms/83xx/mpc834x_sys.c @@ -224,6 +224,26 @@ mpc834x_sys_init_IRQ(void) ipic_set_default_priority(); } +#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374) +extern ulong ds1374_get_rtc_time(void); +extern int ds1374_set_rtc_time(ulong); + +static int __init +mpc834x_rtc_hookup(void) +{ + struct timespec tv; + + ppc_md.get_rtc_time = ds1374_get_rtc_time; + ppc_md.set_rtc_time = ds1374_set_rtc_time; + + tv.tv_nsec = 0; + tv.tv_sec = (ppc_md.get_rtc_time)(); + do_settimeofday(&tv); + + return 0; +} +late_initcall(mpc834x_rtc_hookup); +#endif static __inline__ void mpc834x_sys_set_bat(void) { diff --git a/trunk/arch/ppc/platforms/85xx/tqm85xx.c b/trunk/arch/ppc/platforms/85xx/tqm85xx.c index 27ce389c1224..4ee2bd156dc5 100644 --- a/trunk/arch/ppc/platforms/85xx/tqm85xx.c +++ b/trunk/arch/ppc/platforms/85xx/tqm85xx.c @@ -258,6 +258,27 @@ int tqm85xx_show_cpuinfo(struct seq_file *m) return 0; } +#if defined(CONFIG_I2C) && defined(CONFIG_SENSORS_DS1337) +extern ulong ds1337_get_rtc_time(void); +extern int ds1337_set_rtc_time(unsigned long nowtime); + +static int __init +tqm85xx_rtc_hookup(void) +{ + struct timespec tv; + + ppc_md.set_rtc_time = ds1337_set_rtc_time; + ppc_md.get_rtc_time = ds1337_get_rtc_time; + + tv.tv_nsec = 0; + tv.tv_sec = (ppc_md.get_rtc_time)(); + do_settimeofday(&tv); + + return 0; +} +late_initcall(tqm85xx_rtc_hookup); +#endif + #ifdef CONFIG_PCI /* * interrupt routing diff --git a/trunk/arch/ppc/platforms/katana.c b/trunk/arch/ppc/platforms/katana.c index fe6e88cdb1cd..52f63e6f0856 100644 --- a/trunk/arch/ppc/platforms/katana.c +++ b/trunk/arch/ppc/platforms/katana.c @@ -838,6 +838,27 @@ katana_find_end_of_memory(void) return bdp->bi_memsize; } +#if defined(CONFIG_I2C_MV64XXX) && defined(CONFIG_SENSORS_M41T00) +extern ulong m41t00_get_rtc_time(void); +extern int m41t00_set_rtc_time(ulong); + +static int __init +katana_rtc_hookup(void) +{ + struct timespec tv; + + ppc_md.get_rtc_time = m41t00_get_rtc_time; + ppc_md.set_rtc_time = m41t00_set_rtc_time; + + tv.tv_nsec = 0; + tv.tv_sec = (ppc_md.get_rtc_time)(); + do_settimeofday(&tv); + + return 0; +} +late_initcall(katana_rtc_hookup); +#endif + #if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE) static void __init katana_map_io(void) diff --git a/trunk/drivers/i2c/algos/i2c-algo-bit.c b/trunk/drivers/i2c/algos/i2c-algo-bit.c index 35812823787b..a37cb6b8593c 100644 --- a/trunk/drivers/i2c/algos/i2c-algo-bit.c +++ b/trunk/drivers/i2c/algos/i2c-algo-bit.c @@ -1,7 +1,7 @@ -/* ------------------------------------------------------------------------- - * i2c-algo-bit.c i2c driver algorithms for bit-shift adapters - * ------------------------------------------------------------------------- - * Copyright (C) 1995-2000 Simon G. Vogl +/* ------------------------------------------------------------------------- */ +/* i2c-algo-bit.c i2c driver algorithms for bit-shift 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 @@ -15,8 +15,8 @@ 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. - * ------------------------------------------------------------------------- */ + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* ------------------------------------------------------------------------- */ /* With some changes from Frodo Looijaard , Kyösti Mälkki and Jean Delvare */ @@ -60,26 +60,26 @@ MODULE_PARM_DESC(i2c_debug, /* --- setting states on the bus with the right timing: --------------- */ -#define setsda(adap, val) adap->setsda(adap->data, val) -#define setscl(adap, val) adap->setscl(adap->data, val) -#define getsda(adap) adap->getsda(adap->data) -#define getscl(adap) adap->getscl(adap->data) +#define setsda(adap,val) adap->setsda(adap->data, val) +#define setscl(adap,val) adap->setscl(adap->data, val) +#define getsda(adap) adap->getsda(adap->data) +#define getscl(adap) adap->getscl(adap->data) static inline void sdalo(struct i2c_algo_bit_data *adap) { - setsda(adap, 0); + setsda(adap,0); udelay((adap->udelay + 1) / 2); } static inline void sdahi(struct i2c_algo_bit_data *adap) { - setsda(adap, 1); + setsda(adap,1); udelay((adap->udelay + 1) / 2); } static inline void scllo(struct i2c_algo_bit_data *adap) { - setscl(adap, 0); + setscl(adap,0); udelay(adap->udelay / 2); } @@ -91,21 +91,22 @@ static int sclhi(struct i2c_algo_bit_data *adap) { unsigned long start; - setscl(adap, 1); + setscl(adap,1); /* Not all adapters have scl sense line... */ if (!adap->getscl) goto done; - start = jiffies; - while (!getscl(adap)) { - /* This hw knows how to read the clock line, so we wait - * until it actually gets high. This is safer as some - * chips may hold it low ("clock stretching") while they - * are processing data internally. - */ - if (time_after_eq(jiffies, start + adap->timeout)) + start=jiffies; + while (! getscl(adap) ) { + /* the hw knows how to read the clock line, + * so we wait until it actually gets high. + * This is safer as some chips may hold it low + * while they are processing data internally. + */ + if (time_after_eq(jiffies, start+adap->timeout)) { return -ETIMEDOUT; + } cond_resched(); } #ifdef DEBUG @@ -117,11 +118,11 @@ static int sclhi(struct i2c_algo_bit_data *adap) done: udelay(adap->udelay); return 0; -} +} /* --- other auxiliary functions -------------------------------------- */ -static void i2c_start(struct i2c_algo_bit_data *adap) +static void i2c_start(struct i2c_algo_bit_data *adap) { /* assert: scl, sda are high */ setsda(adap, 0); @@ -129,7 +130,7 @@ static void i2c_start(struct i2c_algo_bit_data *adap) scllo(adap); } -static void i2c_repstart(struct i2c_algo_bit_data *adap) +static void i2c_repstart(struct i2c_algo_bit_data *adap) { /* assert: scl is low */ sdahi(adap); @@ -140,18 +141,18 @@ static void i2c_repstart(struct i2c_algo_bit_data *adap) } -static void i2c_stop(struct i2c_algo_bit_data *adap) +static void i2c_stop(struct i2c_algo_bit_data *adap) { /* assert: scl is low */ sdalo(adap); - sclhi(adap); + sclhi(adap); setsda(adap, 1); udelay(adap->udelay); } -/* send a byte without start cond., look for arbitration, +/* send a byte without start cond., look for arbitration, check ackn. from slave */ /* returns: * 1 if the device acknowledged @@ -166,33 +167,27 @@ static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c) struct i2c_algo_bit_data *adap = i2c_adap->algo_data; /* assert: scl is low */ - for (i = 7; i >= 0; i--) { + for ( i=7 ; i>=0 ; i-- ) { sb = (c >> i) & 1; - setsda(adap, sb); + setsda(adap,sb); udelay((adap->udelay + 1) / 2); - if (sclhi(adap) < 0) { /* timed out */ + if (sclhi(adap)<0) { /* timed out */ bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, " "timeout at bit #%d\n", (int)c, i); return -ETIMEDOUT; - } - /* FIXME do arbitration here: - * if (sb && !getsda(adap)) -> ouch! Get out of here. - * - * Report a unique code, so higher level code can retry - * the whole (combined) message and *NOT* issue STOP. + }; + /* do arbitration here: + * if ( sb && ! getsda(adap) ) -> ouch! Get out of here. */ scllo(adap); } sdahi(adap); - if (sclhi(adap) < 0) { /* timeout */ + if (sclhi(adap)<0){ /* timeout */ bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, " "timeout at ack\n", (int)c); return -ETIMEDOUT; - } - - /* read ack: SDA should be pulled down by slave, or it may - * NAK (usually to report problems with the data we wrote). - */ + }; + /* read ack: SDA should be pulled down by slave */ ack = !getsda(adap); /* ack: sda is pulled low -> success */ bit_dbg(2, &i2c_adap->dev, "i2c_outb: 0x%02x %s\n", (int)c, ack ? "A" : "NA"); @@ -203,24 +198,24 @@ static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c) } -static int i2c_inb(struct i2c_adapter *i2c_adap) +static int i2c_inb(struct i2c_adapter *i2c_adap) { /* read byte via i2c port, without start/stop sequence */ /* acknowledge is sent in i2c_read. */ int i; - unsigned char indata = 0; + unsigned char indata=0; struct i2c_algo_bit_data *adap = i2c_adap->algo_data; /* assert: scl is low */ sdahi(adap); - for (i = 0; i < 8; i++) { - if (sclhi(adap) < 0) { /* timeout */ + for (i=0;i<8;i++) { + if (sclhi(adap)<0) { /* timeout */ bit_dbg(1, &i2c_adap->dev, "i2c_inb: timeout at bit " "#%d\n", 7 - i); return -ETIMEDOUT; - } + }; indata *= 2; - if (getsda(adap)) + if ( getsda(adap) ) indata |= 0x01; setscl(adap, 0); udelay(i == 7 ? adap->udelay / 2 : adap->udelay); @@ -233,67 +228,66 @@ static int i2c_inb(struct i2c_adapter *i2c_adap) * Sanity check for the adapter hardware - check the reaction of * the bus lines only if it seems to be idle. */ -static int test_bus(struct i2c_algo_bit_data *adap, char *name) -{ - int scl, sda; +static int test_bus(struct i2c_algo_bit_data *adap, char* name) { + int scl,sda; - if (adap->getscl == NULL) + if (adap->getscl==NULL) pr_info("%s: Testing SDA only, SCL is not readable\n", name); - sda = getsda(adap); - scl = (adap->getscl == NULL) ? 1 : getscl(adap); - if (!scl || !sda) { + sda=getsda(adap); + scl=(adap->getscl==NULL?1:getscl(adap)); + if (!scl || !sda ) { printk(KERN_WARNING "%s: bus seems to be busy\n", name); goto bailout; } sdalo(adap); - sda = getsda(adap); - scl = (adap->getscl == NULL) ? 1 : getscl(adap); - if (sda) { + sda=getsda(adap); + scl=(adap->getscl==NULL?1:getscl(adap)); + if ( 0 != sda ) { printk(KERN_WARNING "%s: SDA stuck high!\n", name); goto bailout; } - if (!scl) { + if ( 0 == scl ) { printk(KERN_WARNING "%s: SCL unexpected low " "while pulling SDA low!\n", name); goto bailout; - } + } sdahi(adap); - sda = getsda(adap); - scl = (adap->getscl == NULL) ? 1 : getscl(adap); - if (!sda) { + sda=getsda(adap); + scl=(adap->getscl==NULL?1:getscl(adap)); + if ( 0 == sda ) { printk(KERN_WARNING "%s: SDA stuck low!\n", name); goto bailout; } - if (!scl) { + if ( 0 == scl ) { printk(KERN_WARNING "%s: SCL unexpected low " "while pulling SDA high!\n", name); goto bailout; } scllo(adap); - sda = getsda(adap); - scl = (adap->getscl == NULL) ? 0 : getscl(adap); - if (scl) { + sda=getsda(adap); + scl=(adap->getscl==NULL?0:getscl(adap)); + if ( 0 != scl ) { printk(KERN_WARNING "%s: SCL stuck high!\n", name); goto bailout; } - if (!sda) { + if ( 0 == sda ) { printk(KERN_WARNING "%s: SDA unexpected low " "while pulling SCL low!\n", name); goto bailout; } - + sclhi(adap); - sda = getsda(adap); - scl = (adap->getscl == NULL) ? 1 : getscl(adap); - if (!scl) { + sda=getsda(adap); + scl=(adap->getscl==NULL?1:getscl(adap)); + if ( 0 == scl ) { printk(KERN_WARNING "%s: SCL stuck low!\n", name); goto bailout; } - if (!sda) { + if ( 0 == sda ) { printk(KERN_WARNING "%s: SDA unexpected low " "while pulling SCL high!\n", name); goto bailout; @@ -320,10 +314,9 @@ static int try_address(struct i2c_adapter *i2c_adap, unsigned char addr, int retries) { struct i2c_algo_bit_data *adap = i2c_adap->algo_data; - int i, ret = -1; - - for (i = 0; i <= retries; i++) { - ret = i2c_outb(i2c_adap, addr); + int i,ret = -1; + for (i=0;i<=retries;i++) { + ret = i2c_outb(i2c_adap,addr); if (ret == 1 || i == retries) break; bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n"); @@ -345,38 +338,20 @@ static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) { const unsigned char *temp = msg->buf; int count = msg->len; - unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK; + unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK; int retval; - int wrcount = 0; + int wrcount=0; while (count > 0) { retval = i2c_outb(i2c_adap, *temp); - - /* OK/ACK; or ignored NAK */ - if ((retval > 0) || (nak_ok && (retval == 0))) { - count--; + if ((retval>0) || (nak_ok && (retval==0))) { /* ok or ignored NAK */ + count--; temp++; wrcount++; - - /* A slave NAKing the master means the slave didn't like - * something about the data it saw. For example, maybe - * the SMBus PEC was wrong. - */ - } else if (retval == 0) { - dev_err(&i2c_adap->dev, "sendbytes: NAK bailout.\n"); - return -EIO; - - /* Timeout; or (someday) lost arbitration - * - * FIXME Lost ARB implies retrying the transaction from - * the first message, after the "winning" master issues - * its STOP. As a rule, upper layer code has no reason - * to know or care about this ... it is *NOT* an error. - */ - } else { - dev_err(&i2c_adap->dev, "sendbytes: error %d\n", - retval); - return retval; + } else { /* arbitration or no acknowledge */ + dev_err(&i2c_adap->dev, "sendbytes: error - bailout.\n"); + return (retval<0)? retval : -EFAULT; + /* got a better one ?? */ } } return wrcount; @@ -401,14 +376,14 @@ static int acknak(struct i2c_adapter *i2c_adap, int is_ack) static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) { int inval; - int rdcount = 0; /* counts bytes read */ + int rdcount=0; /* counts bytes read */ unsigned char *temp = msg->buf; int count = msg->len; const unsigned flags = msg->flags; while (count > 0) { inval = i2c_inb(i2c_adap); - if (inval >= 0) { + if (inval>=0) { *temp = inval; rdcount++; } else { /* read timed out */ @@ -456,7 +431,7 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) * returns: * 0 everything went okay, the chip ack'ed, or IGNORE_NAK flag was set * -x an error occurred (like: -EREMOTEIO if the device did not answer, or - * -ETIMEDOUT, for example if the lines are stuck...) + * -ETIMEDOUT, for example if the lines are stuck...) */ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) { @@ -468,10 +443,10 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) int ret, retries; retries = nak_ok ? 0 : i2c_adap->retries; - - if (flags & I2C_M_TEN) { + + if ( (flags & I2C_M_TEN) ) { /* a ten bit address */ - addr = 0xf0 | ((msg->addr >> 7) & 0x03); + addr = 0xf0 | (( msg->addr >> 7) & 0x03); bit_dbg(2, &i2c_adap->dev, "addr0: %d\n", addr); /* try extended address code...*/ ret = try_address(i2c_adap, addr, retries); @@ -481,33 +456,33 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) return -EREMOTEIO; } /* the remaining 8 bit address */ - ret = i2c_outb(i2c_adap, msg->addr & 0x7f); + ret = i2c_outb(i2c_adap,msg->addr & 0x7f); if ((ret != 1) && !nak_ok) { /* the chip did not ack / xmission error occurred */ dev_err(&i2c_adap->dev, "died at 2nd address code\n"); return -EREMOTEIO; } - if (flags & I2C_M_RD) { + if ( flags & I2C_M_RD ) { bit_dbg(3, &i2c_adap->dev, "emitting repeated " "start condition\n"); i2c_repstart(adap); /* okay, now switch into reading mode */ addr |= 0x01; ret = try_address(i2c_adap, addr, retries); - if ((ret != 1) && !nak_ok) { + if ((ret!=1) && !nak_ok) { dev_err(&i2c_adap->dev, "died at repeated address code\n"); return -EREMOTEIO; } } } else { /* normal 7bit address */ - addr = msg->addr << 1; - if (flags & I2C_M_RD) + addr = ( msg->addr << 1 ); + if (flags & I2C_M_RD ) addr |= 1; - if (flags & I2C_M_REV_DIR_ADDR) + if (flags & I2C_M_REV_DIR_ADDR ) addr ^= 1; ret = try_address(i2c_adap, addr, retries); - if ((ret != 1) && !nak_ok) + if ((ret!=1) && !nak_ok) return -EREMOTEIO; } @@ -519,14 +494,15 @@ static int bit_xfer(struct i2c_adapter *i2c_adap, { struct i2c_msg *pmsg; struct i2c_algo_bit_data *adap = i2c_adap->algo_data; - int i, ret; + + int i,ret; unsigned short nak_ok; bit_dbg(3, &i2c_adap->dev, "emitting start condition\n"); i2c_start(adap); - for (i = 0; i < num; i++) { + for (i=0;iflags & I2C_M_IGNORE_NAK; + nak_ok = pmsg->flags & I2C_M_IGNORE_NAK; if (!(pmsg->flags & I2C_M_NOSTART)) { if (i) { bit_dbg(3, &i2c_adap->dev, "emitting " @@ -541,7 +517,7 @@ static int bit_xfer(struct i2c_adapter *i2c_adap, goto bailout; } } - if (pmsg->flags & I2C_M_RD) { + if (pmsg->flags & I2C_M_RD ) { /* read bytes into buffer*/ ret = readbytes(i2c_adap, pmsg); if (ret >= 1) @@ -575,7 +551,7 @@ static int bit_xfer(struct i2c_adapter *i2c_adap, static u32 bit_func(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL | I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING; @@ -589,8 +565,8 @@ static const struct i2c_algorithm i2c_bit_algo = { .functionality = bit_func, }; -/* - * registering functions to load algorithms at runtime +/* + * registering functions to load algorithms at runtime */ static int i2c_bit_prepare_bus(struct i2c_adapter *adap) { @@ -598,7 +574,7 @@ static int i2c_bit_prepare_bus(struct i2c_adapter *adap) if (bit_test) { int ret = test_bus(bit_adap, adap->name); - if (ret < 0) + if (ret<0) return -ENODEV; } diff --git a/trunk/drivers/i2c/algos/i2c-algo-pcf.c b/trunk/drivers/i2c/algos/i2c-algo-pcf.c index 8907b0191677..ab2e6f3498b4 100644 --- a/trunk/drivers/i2c/algos/i2c-algo-pcf.c +++ b/trunk/drivers/i2c/algos/i2c-algo-pcf.c @@ -203,6 +203,35 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap) /* ----- Utility functions */ +static inline int try_address(struct i2c_algo_pcf_data *adap, + unsigned char addr, int retries) +{ + int i, status, ret = -1; + int wfp; + for (i=0;i= 0) { + if ((status & I2C_PCF_LRB) == 0) { + i2c_stop(adap); + break; /* success! */ + } + } + if (wfp == -EINTR) { + /* arbitration lost */ + udelay(adap->udelay); + return -EINTR; + } + i2c_stop(adap); + udelay(adap->udelay); + } + DEB2(if (i) printk(KERN_DEBUG "i2c-algo-pcf.o: needed %d retries for %d\n",i, + addr)); + return ret; +} + + static int pcf_sendbytes(struct i2c_adapter *i2c_adap, const char *buf, int count, int last) { @@ -292,19 +321,47 @@ static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf, } -static int pcf_doAddress(struct i2c_algo_pcf_data *adap, - struct i2c_msg *msg) +static inline int pcf_doAddress(struct i2c_algo_pcf_data *adap, + struct i2c_msg *msg, int retries) { unsigned short flags = msg->flags; unsigned char addr; - - addr = msg->addr << 1; - if (flags & I2C_M_RD) - addr |= 1; - if (flags & I2C_M_REV_DIR_ADDR) - addr ^= 1; - i2c_outb(adap, addr); - + int ret; + 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 "died at extended address code.\n"); + return -EREMOTEIO; + } + /* the remaining 8 bit address */ + i2c_outb(adap,msg->addr & 0x7f); +/* Status check comes here */ + if (ret != 1) { + printk(KERN_ERR "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 "died at extended address code.\n"); + return -EREMOTEIO; + } + } + } else { /* normal 7bit address */ + addr = ( msg->addr << 1 ); + if (flags & I2C_M_RD ) + addr |= 1; + if (flags & I2C_M_REV_DIR_ADDR ) + addr ^= 1; + i2c_outb(adap, addr); + } return 0; } @@ -333,7 +390,7 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap, pmsg->flags & I2C_M_RD ? "read" : "write", pmsg->len, pmsg->addr, i + 1, num);) - ret = pcf_doAddress(adap, pmsg); + ret = pcf_doAddress(adap, pmsg, i2c_adap->retries); /* Send START */ if (i == 0) { @@ -396,7 +453,7 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap, static u32 pcf_func(struct i2c_adapter *adap) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | - I2C_FUNC_PROTOCOL_MANGLING; + I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING; } /* -----exported algorithm data: ------------------------------------- */ @@ -418,7 +475,9 @@ int i2c_pcf_add_bus(struct i2c_adapter *adap) /* register new adapter to i2c module... */ adap->algo = &pcf_algo; - adap->timeout = 100; + + adap->timeout = 100; /* default values, should */ + adap->retries = 3; /* be replaced by defines */ if ((rval = pcf_init_8584(pcf_adap))) return rval; diff --git a/trunk/drivers/i2c/busses/Kconfig b/trunk/drivers/i2c/busses/Kconfig index 8d12b26bb6c6..c466c6cfc2e5 100644 --- a/trunk/drivers/i2c/busses/Kconfig +++ b/trunk/drivers/i2c/busses/Kconfig @@ -182,8 +182,7 @@ config I2C_I801 will be called i2c-i801. config I2C_I810 - tristate "Intel 810/815 (DEPRECATED)" - default n + tristate "Intel 810/815" depends on PCI select I2C_ALGOBIT help @@ -196,8 +195,6 @@ config I2C_I810 i815 i845G - This driver is deprecated in favor of the i810fb and intelfb drivers. - This driver can also be built as a module. If so, the module will be called i2c-i810. @@ -262,6 +259,20 @@ config I2C_IOP3XX This driver can also be built as a module. If so, the module will be called i2c-iop3xx. +config I2C_IXP4XX + tristate "IXP4xx GPIO-Based I2C Interface (DEPRECATED)" + depends on ARCH_IXP4XX + select I2C_ALGOBIT + help + Say Y here if you have an Intel IXP4xx(420,421,422,425) based + system and are using GPIO lines for an I2C bus. + + This support is also available as a module. If so, the module + will be called i2c-ixp4xx. + + This driver is deprecated and will be dropped soon. Use i2c-gpio + instead. + config I2C_IXP2000 tristate "IXP2000 GPIO-Based I2C Interface (DEPRECATED)" depends on ARCH_IXP2000 @@ -385,8 +396,7 @@ config I2C_PASEMI Supports the PA Semi PWRficient on-chip SMBus interfaces. config I2C_PROSAVAGE - tristate "S3/VIA (Pro)Savage (DEPRECATED)" - default n + tristate "S3/VIA (Pro)Savage" depends on PCI select I2C_ALGOBIT help @@ -397,8 +407,6 @@ config I2C_PROSAVAGE S3/VIA KM266/VT8375 aka ProSavage8 S3/VIA KM133/VT8365 aka Savage4 - This driver is deprecated in favor of the savagefb driver. - This support is also available as a module. If so, the module will be called i2c-prosavage. @@ -410,16 +418,13 @@ config I2C_S3C2410 Samsung S3C2410 based System-on-Chip devices. config I2C_SAVAGE4 - tristate "S3 Savage 4 (DEPRECATED)" - default n - depends on PCI + tristate "S3 Savage 4" + depends on PCI && EXPERIMENTAL select I2C_ALGOBIT help If you say yes to this option, support will be included for the S3 Savage 4 I2C interface. - This driver is deprecated in favor of the savagefb driver. - This driver can also be built as a module. If so, the module will be called i2c-savage4. @@ -606,7 +611,7 @@ config I2C_VIAPRO VT8231 VT8233/A VT8235 - VT8237R/A/S + VT8237R/A VT8251 CX700 diff --git a/trunk/drivers/i2c/busses/Makefile b/trunk/drivers/i2c/busses/Makefile index ea7068f1eb6b..81d43c27cf93 100644 --- a/trunk/drivers/i2c/busses/Makefile +++ b/trunk/drivers/i2c/busses/Makefile @@ -20,6 +20,7 @@ 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_IXP2000) += i2c-ixp2000.o +obj-$(CONFIG_I2C_IXP4XX) += i2c-ixp4xx.o obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o obj-$(CONFIG_I2C_MPC) += i2c-mpc.o obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o diff --git a/trunk/drivers/i2c/busses/i2c-amd756.c b/trunk/drivers/i2c/busses/i2c-amd756.c index 573abe440842..7490dc1771ae 100644 --- a/trunk/drivers/i2c/busses/i2c-amd756.c +++ b/trunk/drivers/i2c/busses/i2c-amd756.c @@ -334,10 +334,6 @@ static int __devinit amd756_probe(struct pci_dev *pdev, int error; u8 temp; - /* driver_data might come from user-space, so check it */ - if (id->driver_data > ARRAY_SIZE(chipname)) - return -EINVAL; - if (amd756_ioport) { dev_err(&pdev->dev, "Only one device supported " "(you have a strange motherboard, btw)\n"); @@ -409,7 +405,6 @@ static struct pci_driver amd756_driver = { .id_table = amd756_ids, .probe = amd756_probe, .remove = __devexit_p(amd756_remove), - .dynids.use_driver_data = 1, }; static int __init amd756_init(void) diff --git a/trunk/drivers/i2c/busses/i2c-au1550.c b/trunk/drivers/i2c/busses/i2c-au1550.c index 1953b26da56a..2f684166c43d 100644 --- a/trunk/drivers/i2c/busses/i2c-au1550.c +++ b/trunk/drivers/i2c/busses/i2c-au1550.c @@ -30,22 +30,14 @@ #include #include #include -#include #include #include #include -#include #include #include -struct i2c_au1550_data { - u32 psc_base; - int xfer_timeout; - int ack_timeout; - struct i2c_adapter adap; - struct resource *ioarea; -}; +#include "i2c-au1550.h" static int wait_xfer_done(struct i2c_au1550_data *adap) @@ -113,7 +105,7 @@ wait_master_done(struct i2c_au1550_data *adap) } static int -do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd, int q) +do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd) { volatile psc_smb_t *sp; u32 stat; @@ -142,10 +134,6 @@ do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd, int q) if (rd) addr |= 1; - /* zero-byte xfers stop immediately */ - if (q) - addr |= PSC_SMBTXRX_STP; - /* Put byte into fifo, start up master. */ sp->psc_smbtxrx = addr; @@ -154,7 +142,7 @@ do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd, int q) au_sync(); if (wait_ack(adap)) return -EIO; - return (q) ? wait_master_done(adap) : 0; + return 0; } static u32 @@ -274,8 +262,7 @@ au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) for (i = 0; !err && i < num; i++) { p = &msgs[i]; - err = do_address(adap, p->addr, p->flags & I2C_M_RD, - (p->len == 0)); + err = do_address(adap, p->addr, p->flags & I2C_M_RD); if (err || !p->len) continue; if (p->flags & I2C_M_RD) @@ -307,48 +294,18 @@ static const struct i2c_algorithm au1550_algo = { * Prior to calling us, the 50MHz clock frequency and routing * must have been set up for the PSC indicated by the adapter. */ -static int __devinit -i2c_au1550_probe(struct platform_device *pdev) +int +i2c_au1550_add_bus(struct i2c_adapter *i2c_adap) { - struct i2c_au1550_data *priv; - volatile psc_smb_t *sp; - struct resource *r; - u32 stat; - int ret; - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r) { - ret = -ENODEV; - goto out; - } - - priv = kzalloc(sizeof(struct i2c_au1550_data), GFP_KERNEL); - if (!priv) { - ret = -ENOMEM; - goto out; - } - - priv->ioarea = request_mem_region(r->start, r->end - r->start + 1, - pdev->name); - if (!priv->ioarea) { - ret = -EBUSY; - goto out_mem; - } - - priv->psc_base = r->start; - priv->xfer_timeout = 200; - priv->ack_timeout = 200; + struct i2c_au1550_data *adap = i2c_adap->algo_data; + volatile psc_smb_t *sp; + u32 stat; - priv->adap.id = I2C_HW_AU1550_PSC; - priv->adap.nr = pdev->id; - priv->adap.algo = &au1550_algo; - priv->adap.algo_data = priv; - priv->adap.dev.parent = &pdev->dev; - strlcpy(priv->adap.name, "Au1xxx PSC I2C", sizeof(priv->adap.name)); + i2c_adap->algo = &au1550_algo; /* Now, set up the PSC for SMBus PIO mode. */ - sp = (volatile psc_smb_t *)priv->psc_base; + sp = (volatile psc_smb_t *)(adap->psc_base); sp->psc_ctrl = PSC_CTRL_DISABLE; au_sync(); sp->psc_sel = PSC_SEL_PS_SMBUSMODE; @@ -386,87 +343,87 @@ i2c_au1550_probe(struct platform_device *pdev) au_sync(); } while ((stat & PSC_SMBSTAT_DR) == 0); - ret = i2c_add_numbered_adapter(&priv->adap); - if (ret == 0) { - platform_set_drvdata(pdev, priv); - return 0; - } - - /* disable the PSC */ - sp->psc_smbcfg = 0; - sp->psc_ctrl = PSC_CTRL_DISABLE; - au_sync(); - - release_resource(priv->ioarea); - kfree(priv->ioarea); -out_mem: - kfree(priv); -out: - return ret; + return i2c_add_adapter(i2c_adap); } -static int __devexit -i2c_au1550_remove(struct platform_device *pdev) -{ - struct i2c_au1550_data *priv = platform_get_drvdata(pdev); - volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base; - platform_set_drvdata(pdev, NULL); - i2c_del_adapter(&priv->adap); - sp->psc_smbcfg = 0; - sp->psc_ctrl = PSC_CTRL_DISABLE; - au_sync(); - release_resource(priv->ioarea); - kfree(priv->ioarea); - kfree(priv); - return 0; +int +i2c_au1550_del_bus(struct i2c_adapter *adap) +{ + return i2c_del_adapter(adap); } static int -i2c_au1550_suspend(struct platform_device *pdev, pm_message_t state) +pb1550_reg(struct i2c_client *client) { - struct i2c_au1550_data *priv = platform_get_drvdata(pdev); - volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base; - - sp->psc_ctrl = PSC_CTRL_SUSPEND; - au_sync(); return 0; } static int -i2c_au1550_resume(struct platform_device *pdev) +pb1550_unreg(struct i2c_client *client) { - struct i2c_au1550_data *priv = platform_get_drvdata(pdev); - volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base; - - sp->psc_ctrl = PSC_CTRL_ENABLE; - au_sync(); - while (!(sp->psc_smbstat & PSC_SMBSTAT_SR)) - au_sync(); return 0; } -static struct platform_driver au1xpsc_smbus_driver = { - .driver = { - .name = "au1xpsc_smbus", - .owner = THIS_MODULE, - }, - .probe = i2c_au1550_probe, - .remove = __devexit_p(i2c_au1550_remove), - .suspend = i2c_au1550_suspend, - .resume = i2c_au1550_resume, +static struct i2c_au1550_data pb1550_i2c_info = { + SMBUS_PSC_BASE, 200, 200 +}; + +static struct i2c_adapter pb1550_board_adapter = { + name: "pb1550 adapter", + id: I2C_HW_AU1550_PSC, + algo: NULL, + algo_data: &pb1550_i2c_info, + client_register: pb1550_reg, + client_unregister: pb1550_unreg, }; +/* BIG hack to support the control interface on the Wolfson WM8731 + * audio codec on the Pb1550 board. We get an address and two data + * bytes to write, create an i2c message, and send it across the + * i2c transfer function. We do this here because we have access to + * the i2c adapter structure. + */ +static struct i2c_msg wm_i2c_msg; /* We don't want this stuff on the stack */ +static u8 i2cbuf[2]; + +int +pb1550_wm_codec_write(u8 addr, u8 reg, u8 val) +{ + wm_i2c_msg.addr = addr; + wm_i2c_msg.flags = 0; + wm_i2c_msg.buf = i2cbuf; + wm_i2c_msg.len = 2; + i2cbuf[0] = reg; + i2cbuf[1] = val; + + return pb1550_board_adapter.algo->master_xfer(&pb1550_board_adapter, &wm_i2c_msg, 1); +} + static int __init i2c_au1550_init(void) { - return platform_driver_register(&au1xpsc_smbus_driver); + printk(KERN_INFO "Au1550 I2C: "); + + /* This is where we would set up a 50MHz clock source + * and routing. On the Pb1550, the SMBus is PSC2, which + * uses a shared clock with USB. This has been already + * configured by Yamon as a 48MHz clock, close enough + * for our work. + */ + if (i2c_au1550_add_bus(&pb1550_board_adapter) < 0) { + printk("failed to initialize.\n"); + return -ENODEV; + } + + printk("initialized.\n"); + return 0; } static void __exit i2c_au1550_exit(void) { - platform_driver_unregister(&au1xpsc_smbus_driver); + i2c_au1550_del_bus(&pb1550_board_adapter); } MODULE_AUTHOR("Dan Malek, Embedded Edge, LLC."); diff --git a/trunk/drivers/i2c/busses/i2c-au1550.h b/trunk/drivers/i2c/busses/i2c-au1550.h new file mode 100644 index 000000000000..fce15d161ae7 --- /dev/null +++ b/trunk/drivers/i2c/busses/i2c-au1550.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2004 Embedded Edge, LLC + * 2.6 port by Matt Porter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef I2C_AU1550_H +#define I2C_AU1550_H + +struct i2c_au1550_data { + u32 psc_base; + int xfer_timeout; + int ack_timeout; +}; + +int i2c_au1550_add_bus(struct i2c_adapter *); +int i2c_au1550_del_bus(struct i2c_adapter *); + +#endif /* I2C_AU1550_H */ diff --git a/trunk/drivers/i2c/busses/i2c-bfin-twi.c b/trunk/drivers/i2c/busses/i2c-bfin-twi.c index 7dbdaeb707a9..67224a424aba 100644 --- a/trunk/drivers/i2c/busses/i2c-bfin-twi.c +++ b/trunk/drivers/i2c/busses/i2c-bfin-twi.c @@ -550,7 +550,6 @@ static int i2c_bfin_twi_probe(struct platform_device *dev) p_adap = &iface->adap; p_adap->id = I2C_HW_BLACKFIN; - p_adap->nr = dev->id; strlcpy(p_adap->name, dev->name, sizeof(p_adap->name)); p_adap->algo = &bfin_twi_algorithm; p_adap->algo_data = iface; @@ -577,7 +576,7 @@ static int i2c_bfin_twi_probe(struct platform_device *dev) bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() | TWI_ENA); SSYNC(); - rc = i2c_add_numbered_adapter(p_adap); + rc = i2c_add_adapter(p_adap); if (rc < 0) free_irq(iface->irq, iface); else diff --git a/trunk/drivers/i2c/busses/i2c-davinci.c b/trunk/drivers/i2c/busses/i2c-davinci.c index cce5a614758d..67679882ebef 100644 --- a/trunk/drivers/i2c/busses/i2c-davinci.c +++ b/trunk/drivers/i2c/busses/i2c-davinci.c @@ -510,6 +510,7 @@ static int davinci_i2c_probe(struct platform_device *pdev) /* FIXME */ adap->timeout = 1; + adap->retries = 1; adap->nr = pdev->id; r = i2c_add_numbered_adapter(adap); diff --git a/trunk/drivers/i2c/busses/i2c-i801.c b/trunk/drivers/i2c/busses/i2c-i801.c index aa9157913b9a..ac27e5f84ebe 100644 --- a/trunk/drivers/i2c/busses/i2c-i801.c +++ b/trunk/drivers/i2c/busses/i2c-i801.c @@ -4,7 +4,6 @@ Copyright (c) 1998 - 2002 Frodo Looijaard , Philip Edelbrock , and Mark D. Studebaker - Copyright (C) 2007 Jean Delvare This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,34 +21,25 @@ */ /* - Supports the following Intel I/O Controller Hubs (ICH): - - I/O Block I2C - region SMBus Block proc. block - Chip name PCI ID size PEC buffer call read - ---------------------------------------------------------------------- - 82801AA (ICH) 0x2413 16 no no no no - 82801AB (ICH0) 0x2423 16 no no no no - 82801BA (ICH2) 0x2443 16 no no no no - 82801CA (ICH3) 0x2483 32 soft no no no - 82801DB (ICH4) 0x24c3 32 hard yes no no - 82801E (ICH5) 0x24d3 32 hard yes yes yes - 6300ESB 0x25a4 32 hard yes yes yes - 82801F (ICH6) 0x266a 32 hard yes yes yes - 6310ESB/6320ESB 0x269b 32 hard yes yes yes - 82801G (ICH7) 0x27da 32 hard yes yes yes - 82801H (ICH8) 0x283e 32 hard yes yes yes - 82801I (ICH9) 0x2930 32 hard yes yes yes - Tolapai 0x5032 32 hard yes ? ? - - Features supported by this driver: - Software PEC no - Hardware PEC yes - Block buffer yes - Block process call transaction no - I2C block read transaction yes (doesn't use the block buffer) - - See the file Documentation/i2c/busses/i2c-i801 for details. + SUPPORTED DEVICES PCI ID + 82801AA 2413 + 82801AB 2423 + 82801BA 2443 + 82801CA/CAM 2483 + 82801DB 24C3 (HW PEC supported) + 82801EB 24D3 (HW PEC supported) + 6300ESB 25A4 + ICH6 266A + ICH7 27DA + ESB2 269B + ICH8 283E + ICH9 2930 + Tolapai 5032 + This driver supports several versions of Intel's I/O Controller Hubs (ICH). + For SMBus support, they are similar to the PIIX4 and are part + of Intel's '810' and other chipsets. + See the file Documentation/i2c/busses/i2c-i801 for details. + I2C Block Read and Process Call are not supported. */ /* Note: we assume there can only be one I801, with one SMBus interface */ @@ -72,9 +62,9 @@ #define SMBHSTDAT0 (5 + i801_smba) #define SMBHSTDAT1 (6 + i801_smba) #define SMBBLKDAT (7 + i801_smba) -#define SMBPEC (8 + i801_smba) /* ICH3 and later */ -#define SMBAUXSTS (12 + i801_smba) /* ICH4 and later */ -#define SMBAUXCTL (13 + i801_smba) /* ICH4 and later */ +#define SMBPEC (8 + i801_smba) /* ICH4 only */ +#define SMBAUXSTS (12 + i801_smba) /* ICH4 only */ +#define SMBAUXCTL (13 + i801_smba) /* ICH4 only */ /* PCI Address Constants */ #define SMBBAR 4 @@ -101,13 +91,13 @@ #define I801_BYTE 0x04 #define I801_BYTE_DATA 0x08 #define I801_WORD_DATA 0x0C -#define I801_PROC_CALL 0x10 /* unimplemented */ +#define I801_PROC_CALL 0x10 /* later chips only, unimplemented */ #define I801_BLOCK_DATA 0x14 -#define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */ +#define I801_I2C_BLOCK_DATA 0x18 /* unimplemented */ #define I801_BLOCK_LAST 0x34 -#define I801_I2C_BLOCK_LAST 0x38 /* ICH5 and later */ +#define I801_I2C_BLOCK_LAST 0x38 /* unimplemented */ #define I801_START 0x40 -#define I801_PEC_EN 0x80 /* ICH3 and later */ +#define I801_PEC_EN 0x80 /* ICH4 only */ /* I801 Hosts Status register bits */ #define SMBHSTSTS_BYTE_DONE 0x80 @@ -123,12 +113,7 @@ static unsigned long i801_smba; static unsigned char i801_original_hstcfg; static struct pci_driver i801_driver; static struct pci_dev *I801_dev; - -#define FEATURE_SMBUS_PEC (1 << 0) -#define FEATURE_BLOCK_BUFFER (1 << 1) -#define FEATURE_BLOCK_PROC (1 << 2) -#define FEATURE_I2C_BLOCK_READ (1 << 3) -static unsigned int i801_features; +static int isich4; static int i801_transaction(int xact) { @@ -257,8 +242,7 @@ static int i801_block_transaction_by_block(union i2c_smbus_data *data, } static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data, - char read_write, int command, - int hwpec) + char read_write, int hwpec) { int i, len; int smbcmd; @@ -275,24 +259,16 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data, } for (i = 1; i <= len; i++) { - if (i == len && read_write == I2C_SMBUS_READ) { - if (command == I2C_SMBUS_I2C_BLOCK_DATA) - smbcmd = I801_I2C_BLOCK_LAST; - else - smbcmd = I801_BLOCK_LAST; - } else { - if (command == I2C_SMBUS_I2C_BLOCK_DATA - && read_write == I2C_SMBUS_READ) - smbcmd = I801_I2C_BLOCK_DATA; - else - smbcmd = I801_BLOCK_DATA; - } + if (i == len && read_write == I2C_SMBUS_READ) + smbcmd = I801_BLOCK_LAST; + else + smbcmd = I801_BLOCK_DATA; outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT); dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, " - "ADD=%02x, DAT0=%02x, DAT1=%02x, BLKDAT=%02x\n", i, + "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i, inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), - inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1), inb_p(SMBBLKDAT)); + inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT)); /* Make sure the SMBus host is ready to start transmitting */ temp = inb_p(SMBHSTSTS); @@ -356,8 +332,7 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data, dev_dbg(&I801_dev->dev, "Error: no response!\n"); } - if (i == 1 && read_write == I2C_SMBUS_READ - && command != I2C_SMBUS_I2C_BLOCK_DATA) { + if (i == 1 && read_write == I2C_SMBUS_READ) { len = inb_p(SMBHSTDAT0); if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) return -1; @@ -378,9 +353,9 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data, temp); } dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, " - "ADD=%02x, DAT0=%02x, DAT1=%02x, BLKDAT=%02x\n", i, + "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i, inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), - inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1), inb_p(SMBBLKDAT)); + inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT)); if (result < 0) return result; @@ -409,38 +384,33 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc); pci_write_config_byte(I801_dev, SMBHSTCFG, hostc | SMBHSTCFG_I2C_EN); - } else if (!(i801_features & FEATURE_I2C_BLOCK_READ)) { + } else { dev_err(&I801_dev->dev, - "I2C block read is unsupported!\n"); + "I2C_SMBUS_I2C_BLOCK_READ not DB!\n"); return -1; } } - if (read_write == I2C_SMBUS_WRITE - || command == I2C_SMBUS_I2C_BLOCK_DATA) { + if (read_write == I2C_SMBUS_WRITE) { if (data->block[0] < 1) data->block[0] = 1; if (data->block[0] > I2C_SMBUS_BLOCK_MAX) data->block[0] = I2C_SMBUS_BLOCK_MAX; } else { - data->block[0] = 32; /* max for SMBus block reads */ + data->block[0] = 32; /* max for reads */ } - if ((i801_features & FEATURE_BLOCK_BUFFER) - && !(command == I2C_SMBUS_I2C_BLOCK_DATA - && read_write == I2C_SMBUS_READ) - && i801_set_block_buffer_mode() == 0) + if (isich4 && i801_set_block_buffer_mode() == 0 ) result = i801_block_transaction_by_block(data, read_write, hwpec); else result = i801_block_transaction_byte_by_byte(data, read_write, - command, hwpec); + hwpec); if (result == 0 && hwpec) i801_wait_hwpec(); - if (command == I2C_SMBUS_I2C_BLOCK_DATA - && read_write == I2C_SMBUS_WRITE) { + if (command == I2C_SMBUS_I2C_BLOCK_DATA) { /* restore saved configuration register value */ pci_write_config_byte(I801_dev, SMBHSTCFG, hostc); } @@ -456,7 +426,7 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr, int block = 0; int ret, xact = 0; - hwpec = (i801_features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC) + hwpec = isich4 && (flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK && size != I2C_SMBUS_I2C_BLOCK_DATA; @@ -492,23 +462,12 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr, xact = I801_WORD_DATA; break; case I2C_SMBUS_BLOCK_DATA: + case I2C_SMBUS_I2C_BLOCK_DATA: outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD); outb_p(command, SMBHSTCMD); block = 1; break; - case I2C_SMBUS_I2C_BLOCK_DATA: - /* NB: page 240 of ICH5 datasheet shows that the R/#W - * bit should be cleared here, even when reading */ - outb_p((addr & 0x7f) << 1, SMBHSTADD); - if (read_write == I2C_SMBUS_READ) { - /* NB: page 240 of ICH5 datasheet also shows - * that DATA1 is the cmd field when reading */ - outb_p(command, SMBHSTDAT1); - } else - outb_p(command, SMBHSTCMD); - block = 1; - break; case I2C_SMBUS_PROC_CALL: default: dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size); @@ -528,7 +487,7 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr, /* Some BIOSes don't like it when PEC is enabled at reboot or resume time, so we forcibly disable it after every transaction. Turn off E32B for the same reason. */ - if (hwpec || block) + if (hwpec) outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL); @@ -555,11 +514,9 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr, static u32 i801_func(struct i2c_adapter *adapter) { return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK | - ((i801_features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) | - ((i801_features & FEATURE_I2C_BLOCK_READ) ? - I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0); + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK + | (isich4 ? I2C_FUNC_SMBUS_PEC : 0); } static const struct i2c_algorithm smbus_algorithm = { @@ -599,8 +556,8 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id int err; I801_dev = dev; - i801_features = 0; switch (dev->device) { + case PCI_DEVICE_ID_INTEL_82801DB_3: case PCI_DEVICE_ID_INTEL_82801EB_3: case PCI_DEVICE_ID_INTEL_ESB_4: case PCI_DEVICE_ID_INTEL_ICH6_16: @@ -608,13 +565,11 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id case PCI_DEVICE_ID_INTEL_ESB2_17: case PCI_DEVICE_ID_INTEL_ICH8_5: case PCI_DEVICE_ID_INTEL_ICH9_6: - i801_features |= FEATURE_I2C_BLOCK_READ; - /* fall through */ - case PCI_DEVICE_ID_INTEL_82801DB_3: case PCI_DEVICE_ID_INTEL_TOLAPAI_1: - i801_features |= FEATURE_SMBUS_PEC; - i801_features |= FEATURE_BLOCK_BUFFER; + isich4 = 1; break; + default: + isich4 = 0; } err = pci_enable_device(dev); @@ -655,11 +610,6 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id else dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n"); - /* Clear special mode bits */ - if (i801_features & (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER)) - outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), - SMBAUXCTL); - /* set up the sysfs linkage to our parent device */ i801_adapter.dev.parent = &dev->dev; @@ -728,8 +678,9 @@ static void __exit i2c_i801_exit(void) pci_unregister_driver(&i801_driver); } -MODULE_AUTHOR("Mark D. Studebaker , " - "Jean Delvare "); +MODULE_AUTHOR ("Frodo Looijaard , " + "Philip Edelbrock , " + "and Mark D. Studebaker "); MODULE_DESCRIPTION("I801 SMBus driver"); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/i2c/busses/i2c-ibm_iic.c b/trunk/drivers/i2c/busses/i2c-ibm_iic.c index 7c7eb0cfeceb..9b43ff7270d0 100644 --- a/trunk/drivers/i2c/busses/i2c-ibm_iic.c +++ b/trunk/drivers/i2c/busses/i2c-ibm_iic.c @@ -6,7 +6,7 @@ * Copyright (c) 2003, 2004 Zultys Technologies. * Eugene Surovegin or * - * Based on original work by + * Based on original work by * Ian DaSilva * Armin Kuster * Matt Porter @@ -86,8 +86,8 @@ static void dump_iic_regs(const char* header, struct ibm_iic_private* dev) 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->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)) @@ -125,7 +125,7 @@ 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. */ @@ -134,7 +134,7 @@ static void iic_dev_init(struct ibm_iic_private* dev) volatile struct iic_regs __iomem *iic = dev->vaddr; DBG("%d: init\n", dev->idx); - + /* Clear master address */ out_8(&iic->lmadr, 0); out_8(&iic->hmadr, 0); @@ -160,7 +160,7 @@ static void iic_dev_init(struct ibm_iic_private* dev) /* Clear control register */ out_8(&iic->cntl, 0); - + /* Enable interrupts if possible */ iic_interrupt_mode(dev, dev->irq >= 0); @@ -171,7 +171,7 @@ static void iic_dev_init(struct ibm_iic_private* dev) DUMP_REGS("iic_init", dev); } -/* +/* * Reset IIC interface */ static void iic_dev_reset(struct ibm_iic_private* dev) @@ -179,42 +179,42 @@ static void iic_dev_reset(struct ibm_iic_private* dev) volatile struct iic_regs __iomem *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); + 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); - + 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); } @@ -324,14 +324,14 @@ static irqreturn_t iic_handler(int irq, void *dev_id) { struct ibm_iic_private* dev = (struct ibm_iic_private*)dev_id; volatile struct iic_regs __iomem *iic = dev->vaddr; - - DBG2("%d: irq handler, STS = 0x%02x, EXTSTS = 0x%02x\n", + + 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; } @@ -341,19 +341,19 @@ static irqreturn_t iic_handler(int irq, void *dev_id) */ static int iic_xfer_result(struct ibm_iic_private* dev) { - volatile struct iic_regs __iomem *iic = dev->vaddr; - + volatile struct iic_regs __iomem *iic = dev->vaddr; + if (unlikely(in_8(&iic->sts) & STS_ERR)){ - DBG("%d: xfer error, EXTSTS = 0x%02x\n", dev->idx, + 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 | + 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 @@ -376,11 +376,11 @@ static void iic_abort_xfer(struct ibm_iic_private* dev) { volatile struct iic_regs __iomem *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) @@ -405,13 +405,13 @@ static void iic_abort_xfer(struct ibm_iic_private* dev) * Returns the number of transferred bytes or error (<0) */ static int iic_wait_for_tc(struct ibm_iic_private* dev){ - + volatile struct iic_regs __iomem *iic = dev->vaddr; int ret = 0; - + if (dev->irq >= 0){ /* Interrupt mode */ - ret = wait_event_interruptible_timeout(dev->wq, + ret = wait_event_interruptible_timeout(dev->wq, !(in_8(&iic->sts) & STS_PT), dev->adap.timeout * HZ); if (unlikely(ret < 0)) @@ -424,37 +424,37 @@ static int iic_wait_for_tc(struct ibm_iic_private* dev){ 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, +static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm, int combined_xfer) { volatile struct iic_regs __iomem *iic = dev->vaddr; @@ -465,48 +465,48 @@ static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm, 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((void __iomem *)&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", + 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; + break; } - + if (cntl & CNTL_RW) for (j = 0; j < count; ++j) *buf++ = in_8((void __iomem *)&iic->mdbuf); } - + return ret > 0 ? 0 : ret; } @@ -517,10 +517,10 @@ static inline void iic_address(struct ibm_iic_private* dev, struct i2c_msg* msg) { volatile struct iic_regs __iomem *iic = dev->vaddr; u16 addr = msg->addr; - - DBG2("%d: iic_address, 0x%03x (%d-bit)\n", dev->idx, + + 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); @@ -537,15 +537,15 @@ 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, +static inline int iic_address_neq(const struct i2c_msg* p1, const struct i2c_msg* p2) { - return (p1->addr != p2->addr) + return (p1->addr != p2->addr) || ((p1->flags & I2C_M_TEN) != (p2->flags & I2C_M_TEN)); -} +} /* - * Generic master transfer entrypoint. + * 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) @@ -553,20 +553,20 @@ 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 __iomem *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, + 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)){ if (num == 1 && !msgs[0].len){ @@ -576,7 +576,7 @@ static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) */ return iic_smbus_quick(dev, &msgs[0]); } - DBG("%d: invalid len %d in msg[%d]\n", dev->idx, + DBG("%d: invalid len %d in msg[%d]\n", dev->idx, msgs[i].len, i); return -EINVAL; } @@ -585,34 +585,34 @@ static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) 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 + * 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); @@ -648,7 +648,7 @@ static inline u8 iic_clckdiv(unsigned int opb) /* Convert to MHz */ opb /= 1000000; - + if (opb < 20 || opb > 150){ printk(KERN_CRIT "ibm-iic: invalid OPB clock frequency %u MHz\n", opb); @@ -666,7 +666,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){ struct i2c_adapter* adap; struct ocp_func_iic_data* iic_data = ocp->def->additions; int ret; - + if (!iic_data) printk(KERN_WARNING"ibm-iic%d: missing additional data!\n", ocp->def->index); @@ -679,7 +679,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){ dev->idx = ocp->def->index; ocp_set_drvdata(ocp, dev); - + if (!request_mem_region(ocp->def->paddr, sizeof(struct iic_regs), "ibm_iic")) { ret = -EBUSY; @@ -692,7 +692,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){ ret = -ENXIO; goto fail2; } - + init_waitqueue_head(&dev->wq); dev->irq = iic_force_poll ? -1 : ocp->def->irq; @@ -702,29 +702,29 @@ static int __devinit iic_probe(struct ocp_device *ocp){ */ 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", + printk(KERN_ERR "ibm-iic%d: request_irq %d failed\n", dev->idx, dev->irq); - /* Fallback to the polling mode */ + /* Fallback to the polling mode */ dev->irq = -1; } } - + if (dev->irq < 0) - printk(KERN_WARNING "ibm-iic%d: using polling mode\n", + printk(KERN_WARNING "ibm-iic%d: using polling mode\n", dev->idx); - + /* Board specific settings */ dev->fast_mode = iic_force_fast ? 1 : (iic_data ? iic_data->fast_mode : 0); - - /* clckdiv is the same for *all* IIC interfaces, + + /* clckdiv is the same for *all* IIC interfaces, * but I'd rather make a copy than introduce another global. --ebs */ dev->clckdiv = iic_clckdiv(ocp_sys_info.opb_bus_freq); DBG("%d: clckdiv = %d\n", dev->idx, dev->clckdiv); - + /* Initialize IIC interface */ iic_dev_init(dev); - + /* Register it with i2c layer */ adap = &dev->adap; adap->dev.parent = &ocp->dev; @@ -736,6 +736,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){ adap->client_register = NULL; adap->client_unregister = NULL; adap->timeout = 1; + adap->retries = 1; /* * If "dev->idx" is negative we consider it as zero. @@ -749,24 +750,24 @@ static int __devinit iic_probe(struct ocp_device *ocp){ 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)"); return 0; -fail: +fail: if (dev->irq >= 0){ iic_interrupt_mode(dev, 0); free_irq(dev->irq, dev); - } + } iounmap(dev->vaddr); -fail2: +fail2: release_mem_region(ocp->def->paddr, sizeof(struct iic_regs)); fail1: ocp_set_drvdata(ocp, NULL); - kfree(dev); + kfree(dev); return ret; } @@ -782,13 +783,13 @@ static void __devexit iic_remove(struct ocp_device *ocp) dev->idx); /* That's *very* bad, just shutdown IRQ ... */ if (dev->irq >= 0){ - iic_interrupt_mode(dev, 0); + iic_interrupt_mode(dev, 0); free_irq(dev->irq, dev); dev->irq = -1; } } else { if (dev->irq >= 0){ - iic_interrupt_mode(dev, 0); + iic_interrupt_mode(dev, 0); free_irq(dev->irq, dev); } iounmap(dev->vaddr); @@ -797,7 +798,7 @@ static void __devexit iic_remove(struct ocp_device *ocp) } } -static struct ocp_device_id ibm_iic_ids[] __devinitdata = +static struct ocp_device_id ibm_iic_ids[] __devinitdata = { { .vendor = OCP_VENDOR_IBM, .function = OCP_FUNC_IIC }, { .vendor = OCP_VENDOR_INVALID } diff --git a/trunk/drivers/i2c/busses/i2c-ibm_iic.h b/trunk/drivers/i2c/busses/i2c-ibm_iic.h index fdaa48292cb6..59d7b437f7ff 100644 --- a/trunk/drivers/i2c/busses/i2c-ibm_iic.h +++ b/trunk/drivers/i2c/busses/i2c-ibm_iic.h @@ -2,11 +2,11 @@ * drivers/i2c/busses/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 + * Based on original work by * Ian DaSilva * Armin Kuster * Matt Porter @@ -22,7 +22,7 @@ #ifndef __I2C_IBM_IIC_H_ #define __I2C_IBM_IIC_H_ -#include +#include struct iic_regs { u16 mdbuf; @@ -58,7 +58,7 @@ struct ibm_iic_private { #define CNTL_TCT_MASK 0x30 #define CNTL_TCT_SHIFT 4 #define CNTL_RPST 0x08 -#define CNTL_CHT 0x04 +#define CNTL_CHT 0x04 #define CNTL_RW 0x02 #define CNTL_PT 0x01 diff --git a/trunk/drivers/i2c/busses/i2c-iop3xx.c b/trunk/drivers/i2c/busses/i2c-iop3xx.c index ab41400c883e..c70146e4c2c0 100644 --- a/trunk/drivers/i2c/busses/i2c-iop3xx.c +++ b/trunk/drivers/i2c/busses/i2c-iop3xx.c @@ -490,6 +490,7 @@ iop3xx_i2c_probe(struct platform_device *pdev) * Default values...should these come in from board code? */ new_adapter->timeout = 100; + new_adapter->retries = 3; new_adapter->algo = &iop3xx_i2c_algo; init_waitqueue_head(&adapter_data->waitq); diff --git a/trunk/drivers/i2c/busses/i2c-ixp4xx.c b/trunk/drivers/i2c/busses/i2c-ixp4xx.c new file mode 100644 index 000000000000..069ed7f3b395 --- /dev/null +++ b/trunk/drivers/i2c/busses/i2c-ixp4xx.c @@ -0,0 +1,178 @@ +/* + * drivers/i2c/busses/i2c-ixp4xx.c + * + * Intel's IXP4xx XScale NPU chipsets (IXP420, 421, 422, 425) do not have + * an on board I2C controller but provide 16 GPIO pins that are often + * used to create an I2C bus. This driver provides an i2c_adapter + * interface that plugs in under algo_bit and drives the GPIO pins + * as instructed by the alogorithm driver. + * + * Author: Deepak Saxena + * + * Copyright (c) 2003-2004 MontaVista Software Inc. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + * + * NOTE: Since different platforms will use different GPIO pins for + * I2C, this driver uses an IXP4xx-specific platform_data + * pointer to pass the GPIO numbers to the driver. This + * allows us to support all the different IXP4xx platforms + * w/o having to put #ifdefs in this driver. + * + * See arch/arm/mach-ixp4xx/ixdp425.c for an example of building a + * device list and filling in the ixp4xx_i2c_pins data structure + * that is passed as the platform_data to this driver. + */ + +#include +#include +#include +#include +#include +#include + +#include /* Pick up IXP4xx-specific bits */ + +static inline int ixp4xx_scl_pin(void *data) +{ + return ((struct ixp4xx_i2c_pins*)data)->scl_pin; +} + +static inline int ixp4xx_sda_pin(void *data) +{ + return ((struct ixp4xx_i2c_pins*)data)->sda_pin; +} + +static void ixp4xx_bit_setscl(void *data, int val) +{ + gpio_line_set(ixp4xx_scl_pin(data), 0); + gpio_line_config(ixp4xx_scl_pin(data), + val ? IXP4XX_GPIO_IN : IXP4XX_GPIO_OUT ); +} + +static void ixp4xx_bit_setsda(void *data, int val) +{ + gpio_line_set(ixp4xx_sda_pin(data), 0); + gpio_line_config(ixp4xx_sda_pin(data), + val ? IXP4XX_GPIO_IN : IXP4XX_GPIO_OUT ); +} + +static int ixp4xx_bit_getscl(void *data) +{ + int scl; + + gpio_line_config(ixp4xx_scl_pin(data), IXP4XX_GPIO_IN ); + gpio_line_get(ixp4xx_scl_pin(data), &scl); + + return scl; +} + +static int ixp4xx_bit_getsda(void *data) +{ + int sda; + + gpio_line_config(ixp4xx_sda_pin(data), IXP4XX_GPIO_IN ); + gpio_line_get(ixp4xx_sda_pin(data), &sda); + + return sda; +} + +struct ixp4xx_i2c_data { + struct ixp4xx_i2c_pins *gpio_pins; + struct i2c_adapter adapter; + struct i2c_algo_bit_data algo_data; +}; + +static int ixp4xx_i2c_remove(struct platform_device *plat_dev) +{ + struct ixp4xx_i2c_data *drv_data = platform_get_drvdata(plat_dev); + + platform_set_drvdata(plat_dev, NULL); + + i2c_del_adapter(&drv_data->adapter); + + kfree(drv_data); + + return 0; +} + +static int ixp4xx_i2c_probe(struct platform_device *plat_dev) +{ + int err; + struct ixp4xx_i2c_pins *gpio = plat_dev->dev.platform_data; + struct ixp4xx_i2c_data *drv_data = + kzalloc(sizeof(struct ixp4xx_i2c_data), GFP_KERNEL); + + if(!drv_data) + return -ENOMEM; + + drv_data->gpio_pins = gpio; + + /* + * We could make a lot of these structures static, but + * certain platforms may have multiple GPIO-based I2C + * buses for various device domains, so we need per-device + * algo_data->data. + */ + drv_data->algo_data.data = gpio; + drv_data->algo_data.setsda = ixp4xx_bit_setsda; + drv_data->algo_data.setscl = ixp4xx_bit_setscl; + drv_data->algo_data.getsda = ixp4xx_bit_getsda; + drv_data->algo_data.getscl = ixp4xx_bit_getscl; + drv_data->algo_data.udelay = 10; + drv_data->algo_data.timeout = 100; + + drv_data->adapter.id = I2C_HW_B_IXP4XX; + drv_data->adapter.class = I2C_CLASS_HWMON; + strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name, + sizeof(drv_data->adapter.name)); + drv_data->adapter.algo_data = &drv_data->algo_data; + + drv_data->adapter.dev.parent = &plat_dev->dev; + + gpio_line_config(gpio->scl_pin, IXP4XX_GPIO_IN); + gpio_line_config(gpio->sda_pin, IXP4XX_GPIO_IN); + gpio_line_set(gpio->scl_pin, 0); + gpio_line_set(gpio->sda_pin, 0); + + err = i2c_bit_add_bus(&drv_data->adapter); + if (err) { + printk(KERN_ERR "ERROR: Could not install %s\n", plat_dev->dev.bus_id); + + kfree(drv_data); + return err; + } + + platform_set_drvdata(plat_dev, drv_data); + + return 0; +} + +static struct platform_driver ixp4xx_i2c_driver = { + .probe = ixp4xx_i2c_probe, + .remove = ixp4xx_i2c_remove, + .driver = { + .name = "IXP4XX-I2C", + .owner = THIS_MODULE, + }, +}; + +static int __init ixp4xx_i2c_init(void) +{ + return platform_driver_register(&ixp4xx_i2c_driver); +} + +static void __exit ixp4xx_i2c_exit(void) +{ + platform_driver_unregister(&ixp4xx_i2c_driver); +} + +module_init(ixp4xx_i2c_init); +module_exit(ixp4xx_i2c_exit); + +MODULE_DESCRIPTION("GPIO-based I2C adapter for IXP4xx systems"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Deepak Saxena "); + diff --git a/trunk/drivers/i2c/busses/i2c-mpc.c b/trunk/drivers/i2c/busses/i2c-mpc.c index bbe787b243b7..d8de4ac88b7d 100644 --- a/trunk/drivers/i2c/busses/i2c-mpc.c +++ b/trunk/drivers/i2c/busses/i2c-mpc.c @@ -180,7 +180,7 @@ static void mpc_i2c_stop(struct mpc_i2c *i2c) static int mpc_write(struct mpc_i2c *i2c, int target, const u8 * data, int length, int restart) { - int i, result; + int i; unsigned timeout = i2c->adap.timeout; u32 flags = restart ? CCR_RSTA : 0; @@ -192,17 +192,15 @@ static int mpc_write(struct mpc_i2c *i2c, int target, /* Write target byte */ writeb((target << 1), i2c->base + MPC_I2C_DR); - result = i2c_wait(i2c, timeout, 1); - if (result < 0) - return result; + if (i2c_wait(i2c, timeout, 1) < 0) + return -1; for (i = 0; i < length; i++) { /* Write data byte */ writeb(data[i], i2c->base + MPC_I2C_DR); - result = i2c_wait(i2c, timeout, 1); - if (result < 0) - return result; + if (i2c_wait(i2c, timeout, 1) < 0) + return -1; } return 0; @@ -212,7 +210,7 @@ static int mpc_read(struct mpc_i2c *i2c, int target, u8 * data, int length, int restart) { unsigned timeout = i2c->adap.timeout; - int i, result; + int i; u32 flags = restart ? CCR_RSTA : 0; /* Start with MEN */ @@ -223,9 +221,8 @@ static int mpc_read(struct mpc_i2c *i2c, int target, /* Write target address byte - this time with the read flag set */ writeb((target << 1) | 1, i2c->base + MPC_I2C_DR); - result = i2c_wait(i2c, timeout, 1); - if (result < 0) - return result; + if (i2c_wait(i2c, timeout, 1) < 0) + return -1; if (length) { if (length == 1) @@ -237,9 +234,8 @@ static int mpc_read(struct mpc_i2c *i2c, int target, } for (i = 0; i < length; i++) { - result = i2c_wait(i2c, timeout, 0); - if (result < 0) - return result; + if (i2c_wait(i2c, timeout, 0) < 0) + return -1; /* Generate txack on next to last byte */ if (i == length - 2) @@ -313,6 +309,7 @@ static struct i2c_adapter mpc_ops = { .algo = &mpc_algo, .class = I2C_CLASS_HWMON, .timeout = 1, + .retries = 1 }; static int fsl_i2c_probe(struct platform_device *pdev) @@ -324,9 +321,9 @@ static int fsl_i2c_probe(struct platform_device *pdev) pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data; - i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); - if (!i2c) + if (!(i2c = kzalloc(sizeof(*i2c), GFP_KERNEL))) { return -ENOMEM; + } i2c->irq = platform_get_irq(pdev, 0); if (i2c->irq < 0) { diff --git a/trunk/drivers/i2c/busses/i2c-nforce2.c b/trunk/drivers/i2c/busses/i2c-nforce2.c index 3dac920e53ea..1bf590c74166 100644 --- a/trunk/drivers/i2c/busses/i2c-nforce2.c +++ b/trunk/drivers/i2c/busses/i2c-nforce2.c @@ -351,7 +351,6 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_ pci_set_drvdata(dev, smbuses); switch(dev->device) { - case PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS: case PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS: case PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS: smbuses[0].blockops = 1; diff --git a/trunk/drivers/i2c/busses/i2c-omap.c b/trunk/drivers/i2c/busses/i2c-omap.c index da6639707ea3..f2552b19ea60 100644 --- a/trunk/drivers/i2c/busses/i2c-omap.c +++ b/trunk/drivers/i2c/busses/i2c-omap.c @@ -362,6 +362,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) omap_i2c_enable_clocks(dev); + /* REVISIT: initialize and use adap->retries. This is an optional + * feature */ if ((r = omap_i2c_wait_for_bb(dev)) < 0) goto out; diff --git a/trunk/drivers/i2c/busses/i2c-pasemi.c b/trunk/drivers/i2c/busses/i2c-pasemi.c index 1603c81e39d4..ca18e0be4901 100644 --- a/trunk/drivers/i2c/busses/i2c-pasemi.c +++ b/trunk/drivers/i2c/busses/i2c-pasemi.c @@ -368,7 +368,6 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev, smbus->adapter.class = I2C_CLASS_HWMON; smbus->adapter.algo = &smbus_algorithm; smbus->adapter.algo_data = smbus; - smbus->adapter.nr = PCI_FUNC(dev->devfn); /* set up the sysfs linkage to our parent device */ smbus->adapter.dev.parent = &dev->dev; @@ -376,7 +375,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev, reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR | (CLK_100K_DIV & CTL_CLK_M))); - error = i2c_add_numbered_adapter(&smbus->adapter); + error = i2c_add_adapter(&smbus->adapter); if (error) goto out_release_region; diff --git a/trunk/drivers/i2c/busses/i2c-piix4.c b/trunk/drivers/i2c/busses/i2c-piix4.c index 9bbe96cef719..167e4137ee21 100644 --- a/trunk/drivers/i2c/busses/i2c-piix4.c +++ b/trunk/drivers/i2c/busses/i2c-piix4.c @@ -121,6 +121,10 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev, { unsigned char temp; + /* match up the function */ + if (PCI_FUNC(PIIX4_dev->devfn) != id->driver_data) + return -ENODEV; + dev_info(&PIIX4_dev->dev, "Found %s device\n", pci_name(PIIX4_dev)); /* Don't access SMBus on IBM systems which get corrupted eeproms */ @@ -385,21 +389,28 @@ static struct i2c_adapter piix4_adapter = { }; static struct pci_device_id piix4_ids[] = { - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3) }, - { PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3) }, - { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, - PCI_DEVICE_ID_SERVERWORKS_OSB4) }, - { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, - PCI_DEVICE_ID_SERVERWORKS_CSB5) }, - { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, - PCI_DEVICE_ID_SERVERWORKS_CSB6) }, - { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, - PCI_DEVICE_ID_SERVERWORKS_HT1000SB) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3), + .driver_data = 3 }, + { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_SMBUS), + .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_SMBUS), + .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS), + .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS), + .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4), + .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5), + .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6), + .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000SB), + .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3), + .driver_data = 3 }, + { PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3), + .driver_data = 0 }, { 0, } }; diff --git a/trunk/drivers/i2c/busses/i2c-pxa.c b/trunk/drivers/i2c/busses/i2c-pxa.c index 2598d29fd7a4..6426a61f8d4d 100644 --- a/trunk/drivers/i2c/busses/i2c-pxa.c +++ b/trunk/drivers/i2c/busses/i2c-pxa.c @@ -65,7 +65,6 @@ struct pxa_i2c { unsigned long iosize; int irq; - int use_pio; }; #define _IBMR(i2c) ((i2c)->reg_base + 0) @@ -164,7 +163,6 @@ static void i2c_pxa_show_state(struct pxa_i2c *i2c, int lno, const char *fname) #define eedbg(lvl, x...) do { if ((lvl) < 1) { printk(KERN_DEBUG "" x); } } while(0) static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret); -static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id); static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why) { @@ -556,71 +554,6 @@ static inline void i2c_pxa_stop_message(struct pxa_i2c *i2c) writel(icr, _ICR(i2c)); } -static int i2c_pxa_pio_set_master(struct pxa_i2c *i2c) -{ - /* make timeout the same as for interrupt based functions */ - long timeout = 2 * DEF_TIMEOUT; - - /* - * Wait for the bus to become free. - */ - while (timeout-- && readl(_ISR(i2c)) & (ISR_IBB | ISR_UB)) { - udelay(1000); - show_state(i2c); - } - - if (timeout <= 0) { - show_state(i2c); - dev_err(&i2c->adap.dev, - "i2c_pxa: timeout waiting for bus free\n"); - return I2C_RETRY; - } - - /* - * Set master mode. - */ - writel(readl(_ICR(i2c)) | ICR_SCLE, _ICR(i2c)); - - return 0; -} - -static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c, - struct i2c_msg *msg, int num) -{ - unsigned long timeout = 500000; /* 5 seconds */ - int ret = 0; - - ret = i2c_pxa_pio_set_master(i2c); - if (ret) - goto out; - - i2c->msg = msg; - i2c->msg_num = num; - i2c->msg_idx = 0; - i2c->msg_ptr = 0; - i2c->irqlogidx = 0; - - i2c_pxa_start_message(i2c); - - while (timeout-- && i2c->msg_num > 0) { - i2c_pxa_handler(0, i2c); - udelay(10); - } - - i2c_pxa_stop_message(i2c); - - /* - * We place the return code in i2c->msg_idx. - */ - ret = i2c->msg_idx; - -out: - if (timeout == 0) - i2c_pxa_scream_blue_murder(i2c, "timeout"); - - return ret; -} - /* * We are protected by the adapter bus mutex. */ @@ -677,35 +610,6 @@ static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num) return ret; } -static int i2c_pxa_pio_xfer(struct i2c_adapter *adap, - struct i2c_msg msgs[], int num) -{ - struct pxa_i2c *i2c = adap->algo_data; - int ret, i; - - /* If the I2C controller is disabled we need to reset it - (probably due to a suspend/resume destroying state). We do - this here as we can then avoid worrying about resuming the - controller before its users. */ - if (!(readl(_ICR(i2c)) & ICR_IUE)) - i2c_pxa_reset(i2c); - - for (i = adap->retries; i >= 0; i--) { - ret = i2c_pxa_do_pio_xfer(i2c, msgs, num); - if (ret != I2C_RETRY) - goto out; - - if (i2c_debug) - dev_dbg(&adap->dev, "Retrying transmission\n"); - udelay(100); - } - i2c_pxa_scream_blue_murder(i2c, "exhausted retries"); - ret = -EREMOTEIO; - out: - i2c_pxa_set_slave(i2c, ret); - return ret; -} - /* * i2c_pxa_master_complete - complete the message and wake up. */ @@ -717,8 +621,7 @@ static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret) i2c->msg_num = 0; if (ret) i2c->msg_idx = ret; - if (!i2c->use_pio) - wake_up(&i2c->wait); + wake_up(&i2c->wait); } static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr) @@ -937,37 +840,6 @@ static const struct i2c_algorithm i2c_pxa_algorithm = { .functionality = i2c_pxa_functionality, }; -static const struct i2c_algorithm i2c_pxa_pio_algorithm = { - .master_xfer = i2c_pxa_pio_xfer, - .functionality = i2c_pxa_functionality, -}; - -static void i2c_pxa_enable(struct platform_device *dev) -{ - if (cpu_is_pxa27x()) { - switch (dev->id) { - case 0: - pxa_gpio_mode(GPIO117_I2CSCL_MD); - pxa_gpio_mode(GPIO118_I2CSDA_MD); - break; - case 1: - local_irq_disable(); - PCFR |= PCFR_PI2CEN; - local_irq_enable(); - break; - } - } -} - -static void i2c_pxa_disable(struct platform_device *dev) -{ - if (cpu_is_pxa27x() && dev->id == 1) { - local_irq_disable(); - PCFR &= ~PCFR_PI2CEN; - local_irq_enable(); - } -} - #define res_len(r) ((r)->end - (r)->start + 1) static int i2c_pxa_probe(struct platform_device *dev) { @@ -992,6 +864,7 @@ static int i2c_pxa_probe(struct platform_device *dev) } i2c->adap.owner = THIS_MODULE; + i2c->adap.algo = &i2c_pxa_algorithm; i2c->adap.retries = 5; spin_lock_init(&i2c->lock); @@ -1026,28 +899,34 @@ static int i2c_pxa_probe(struct platform_device *dev) #endif clk_enable(i2c->clk); - i2c_pxa_enable(dev); - - if (plat) { - i2c->adap.class = plat->class; - i2c->use_pio = plat->use_pio; +#ifdef CONFIG_PXA27x + switch (dev->id) { + case 0: + pxa_gpio_mode(GPIO117_I2CSCL_MD); + pxa_gpio_mode(GPIO118_I2CSDA_MD); + break; + case 1: + local_irq_disable(); + PCFR |= PCFR_PI2CEN; + local_irq_enable(); } +#endif + + ret = request_irq(irq, i2c_pxa_handler, IRQF_DISABLED, + i2c->adap.name, i2c); + if (ret) + goto ereqirq; - if (i2c->use_pio) { - i2c->adap.algo = &i2c_pxa_pio_algorithm; - } else { - i2c->adap.algo = &i2c_pxa_algorithm; - ret = request_irq(irq, i2c_pxa_handler, IRQF_DISABLED, - i2c->adap.name, i2c); - if (ret) - goto ereqirq; - } i2c_pxa_reset(i2c); i2c->adap.algo_data = i2c; i2c->adap.dev.parent = &dev->dev; + if (plat) { + i2c->adap.class = plat->class; + } + /* * If "dev->id" is negative we consider it as zero. * The reason to do so is to avoid sysfs names that only make @@ -1073,11 +952,17 @@ static int i2c_pxa_probe(struct platform_device *dev) return 0; eadapt: - if (!i2c->use_pio) - free_irq(irq, i2c); + free_irq(irq, i2c); ereqirq: clk_disable(i2c->clk); - i2c_pxa_disable(dev); + +#ifdef CONFIG_PXA27x + if (dev->id == 1) { + local_irq_disable(); + PCFR &= ~PCFR_PI2CEN; + local_irq_enable(); + } +#endif eremap: clk_put(i2c->clk); eclk: @@ -1094,12 +979,18 @@ static int i2c_pxa_remove(struct platform_device *dev) platform_set_drvdata(dev, NULL); i2c_del_adapter(&i2c->adap); - if (!i2c->use_pio) - free_irq(i2c->irq, i2c); + free_irq(i2c->irq, i2c); clk_disable(i2c->clk); clk_put(i2c->clk); - i2c_pxa_disable(dev); + +#ifdef CONFIG_PXA27x + if (dev->id == 1) { + local_irq_disable(); + PCFR &= ~PCFR_PI2CEN; + local_irq_enable(); + } +#endif release_mem_region(i2c->iobase, i2c->iosize); kfree(i2c); diff --git a/trunk/drivers/i2c/busses/i2c-sibyte.c b/trunk/drivers/i2c/busses/i2c-sibyte.c index 8fbbdb4c2f35..503a134ec803 100644 --- a/trunk/drivers/i2c/busses/i2c-sibyte.c +++ b/trunk/drivers/i2c/busses/i2c-sibyte.c @@ -36,6 +36,14 @@ struct i2c_algo_sibyte_data { /* ----- global defines ----------------------------------------------- */ #define SMB_CSR(a,r) ((long)(a->reg_base + r)) +/* ----- global variables --------------------------------------------- */ + +/* module parameters: + */ +static int bit_scan; /* have a look at what's hanging 'round */ +module_param(bit_scan, int, 0); +MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus"); + static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr, unsigned short flags, char read_write, @@ -132,8 +140,9 @@ static const struct i2c_algorithm i2c_sibyte_algo = { /* * registering functions to load algorithms at runtime */ -int __init i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed) +int i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed) { + int i; struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data; /* register new adapter to i2c module... */ @@ -143,6 +152,24 @@ int __init i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed) csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ)); csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL)); + /* scan bus */ + if (bit_scan) { + union i2c_smbus_data data; + int rc; + printk(KERN_INFO " i2c-algo-sibyte.o: scanning bus %s.\n", + i2c_adap->name); + for (i = 0x00; i < 0x7f; i++) { + /* XXXKW is this a realistic probe? */ + rc = smbus_xfer(i2c_adap, i, 0, I2C_SMBUS_READ, 0, + I2C_SMBUS_BYTE_DATA, &data); + if (!rc) { + printk("(%02x)",i); + } else + printk("."); + } + printk("\n"); + } + return i2c_add_adapter(i2c_adap); } diff --git a/trunk/drivers/i2c/busses/i2c-stub.c b/trunk/drivers/i2c/busses/i2c-stub.c index c2a9f8c94f5e..84df29da1ddc 100644 --- a/trunk/drivers/i2c/busses/i2c-stub.c +++ b/trunk/drivers/i2c/busses/i2c-stub.c @@ -1,8 +1,8 @@ /* - i2c-stub.c - I2C/SMBus chip emulator + i2c-stub.c - Part of lm_sensors, Linux kernel modules for hardware + monitoring Copyright (c) 2004 Mark M. Hoffman - Copyright (C) 2007 Jean Delvare This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -37,8 +37,8 @@ MODULE_PARM_DESC(chip_addr, struct stub_chip { u8 pointer; - u16 words[256]; /* Byte operations use the LSB as per SMBus - specification */ + u8 bytes[256]; + u16 words[256]; }; static struct stub_chip *stub_chips; @@ -75,7 +75,7 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, "wrote 0x%02x.\n", addr, command); } else { - data->byte = chip->words[chip->pointer++] & 0xff; + data->byte = chip->bytes[chip->pointer++]; dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, " "read 0x%02x.\n", addr, data->byte); @@ -86,13 +86,12 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, case I2C_SMBUS_BYTE_DATA: if (read_write == I2C_SMBUS_WRITE) { - chip->words[command] &= 0xff00; - chip->words[command] |= data->byte; + chip->bytes[command] = data->byte; dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, " "wrote 0x%02x at 0x%02x.\n", addr, data->byte, command); } else { - data->byte = chip->words[command] & 0xff; + data->byte = chip->bytes[command]; dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, " "read 0x%02x at 0x%02x.\n", addr, data->byte, command); diff --git a/trunk/drivers/i2c/busses/i2c-viapro.c b/trunk/drivers/i2c/busses/i2c-viapro.c index 77b13d027f86..c9ce77f13c0e 100644 --- a/trunk/drivers/i2c/busses/i2c-viapro.c +++ b/trunk/drivers/i2c/busses/i2c-viapro.c @@ -4,7 +4,7 @@ Copyright (c) 1998 - 2002 Frodo Looijaard , Philip Edelbrock , Kyösti Mälkki , Mark D. Studebaker - Copyright (C) 2005 - 2008 Jean Delvare + Copyright (C) 2005 - 2007 Jean Delvare This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -35,7 +35,6 @@ VT8235 0x3177 yes VT8237R 0x3227 yes VT8237A 0x3337 yes - VT8237S 0x3372 yes VT8251 0x3287 yes CX700 0x8324 yes @@ -319,10 +318,6 @@ static int __devinit vt596_probe(struct pci_dev *pdev, unsigned char temp; int error = -ENODEV; - /* driver_data might come from user-space, so check it */ - if (id->driver_data & 1 || id->driver_data > 0xff) - return -EINVAL; - /* Determine the address of the SMBus areas */ if (force_addr) { vt596_smba = force_addr & 0xfff0; @@ -394,7 +389,6 @@ static int __devinit vt596_probe(struct pci_dev *pdev, case PCI_DEVICE_ID_VIA_8251: case PCI_DEVICE_ID_VIA_8237: case PCI_DEVICE_ID_VIA_8237A: - case PCI_DEVICE_ID_VIA_8237S: case PCI_DEVICE_ID_VIA_8235: case PCI_DEVICE_ID_VIA_8233A: case PCI_DEVICE_ID_VIA_8233_0: @@ -446,8 +440,6 @@ static struct pci_device_id vt596_ids[] = { .driver_data = SMBBA3 }, { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237A), .driver_data = SMBBA3 }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237S), - .driver_data = SMBBA3 }, { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4), .driver_data = SMBBA1 }, { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8251), @@ -463,7 +455,6 @@ static struct pci_driver vt596_driver = { .name = "vt596_smbus", .id_table = vt596_ids, .probe = vt596_probe, - .dynids.use_driver_data = 1, }; static int __init i2c_vt596_init(void) diff --git a/trunk/drivers/i2c/chips/Kconfig b/trunk/drivers/i2c/chips/Kconfig index bd7082c2443d..2e1c24f671cf 100644 --- a/trunk/drivers/i2c/chips/Kconfig +++ b/trunk/drivers/i2c/chips/Kconfig @@ -4,6 +4,32 @@ menu "Miscellaneous I2C Chip support" +config SENSORS_DS1337 + tristate "Dallas DS1337 and DS1339 Real Time Clock (DEPRECATED)" + depends on EXPERIMENTAL + help + If you say yes here you get support for Dallas Semiconductor + DS1337 and DS1339 real-time clock chips. + + This driver can also be built as a module. If so, the module + will be called ds1337. + + This driver is deprecated and will be dropped soon. Use + rtc-ds1307 instead. + +config SENSORS_DS1374 + tristate "Dallas DS1374 Real Time Clock (DEPRECATED)" + depends on EXPERIMENTAL + help + If you say yes here you get support for Dallas Semiconductor + DS1374 real-time clock chips. + + This driver can also be built as a module. If so, the module + will be called ds1374. + + This driver is deprecated and will be dropped soon. Use + rtc-ds1374 instead. + config DS1682 tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm" depends on EXPERIMENTAL @@ -31,7 +57,7 @@ config SENSORS_PCF8574 default n help If you say yes here you get support for Philips PCF8574 and - PCF8574A chips. These chips are 8-bit I/O expanders for the I2C bus. + PCF8574A chips. This driver can also be built as a module. If so, the module will be called pcf8574. @@ -39,20 +65,6 @@ config SENSORS_PCF8574 These devices are hard to detect and rarely found on mainstream hardware. If unsure, say N. -config PCF8575 - tristate "Philips PCF8575" - default n - help - If you say yes here you get support for Philips PCF8575 chip. - This chip is a 16-bit I/O expander for the I2C bus. Several other - chip manufacturers sell equivalent chips, e.g. Texas Instruments. - - This driver can also be built as a module. If so, the module - will be called pcf8575. - - This device is hard to detect and is rarely found on mainstream - hardware. If unsure, say N. - config SENSORS_PCA9539 tristate "Philips PCA9539 16-bit I/O port" depends on EXPERIMENTAL @@ -88,8 +100,12 @@ config ISP1301_OMAP This driver can also be built as a module. If so, the module will be called isp1301_omap. +# NOTE: This isn't really OMAP-specific, except for the current +# interface location in +# and having mostly OMAP-specific board support config TPS65010 tristate "TPS6501x Power Management chips" + depends on ARCH_OMAP default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK help If you say yes here you get support for the TPS6501x series of @@ -100,6 +116,18 @@ config TPS65010 This driver can also be built as a module. If so, the module will be called tps65010. +config SENSORS_M41T00 + tristate "ST M41T00 RTC chip (DEPRECATED)" + depends on PPC32 + help + If you say yes here you get support for the ST M41T00 RTC chip. + + This driver can also be built as a module. If so, the module + will be called m41t00. + + This driver is deprecated and will be dropped soon. Use + rtc-ds1307 or rtc-m41t80 instead. + config SENSORS_MAX6875 tristate "Maxim MAX6875 Power supply supervisor" depends on EXPERIMENTAL diff --git a/trunk/drivers/i2c/chips/Makefile b/trunk/drivers/i2c/chips/Makefile index 501f00cea782..ca924e105959 100644 --- a/trunk/drivers/i2c/chips/Makefile +++ b/trunk/drivers/i2c/chips/Makefile @@ -2,12 +2,14 @@ # Makefile for miscellaneous I2C chip drivers. # +obj-$(CONFIG_SENSORS_DS1337) += ds1337.o +obj-$(CONFIG_SENSORS_DS1374) += ds1374.o obj-$(CONFIG_DS1682) += ds1682.o obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o obj-$(CONFIG_SENSORS_MAX6875) += max6875.o +obj-$(CONFIG_SENSORS_M41T00) += m41t00.o obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o -obj-$(CONFIG_PCF8575) += pcf8575.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o obj-$(CONFIG_TPS65010) += tps65010.o diff --git a/trunk/drivers/i2c/chips/ds1337.c b/trunk/drivers/i2c/chips/ds1337.c new file mode 100644 index 000000000000..ec17d6b684a2 --- /dev/null +++ b/trunk/drivers/i2c/chips/ds1337.c @@ -0,0 +1,410 @@ +/* + * linux/drivers/i2c/chips/ds1337.c + * + * Copyright (C) 2005 James Chapman + * + * based on linux/drivers/acorn/char/pcf8583.c + * Copyright (C) 2000 Russell King + * + * This program 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. + * + * Driver for Dallas Semiconductor DS1337 and DS1339 real time clock chip + */ + +#include +#include +#include +#include +#include +#include /* get the user-level API */ +#include +#include + +/* Device registers */ +#define DS1337_REG_HOUR 2 +#define DS1337_REG_DAY 3 +#define DS1337_REG_DATE 4 +#define DS1337_REG_MONTH 5 +#define DS1337_REG_CONTROL 14 +#define DS1337_REG_STATUS 15 + +/* FIXME - how do we export these interface constants? */ +#define DS1337_GET_DATE 0 +#define DS1337_SET_DATE 1 + +/* + * Functions declaration + */ +static unsigned short normal_i2c[] = { 0x68, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD_1(ds1337); + +static int ds1337_attach_adapter(struct i2c_adapter *adapter); +static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind); +static void ds1337_init_client(struct i2c_client *client); +static int ds1337_detach_client(struct i2c_client *client); +static int ds1337_command(struct i2c_client *client, unsigned int cmd, + void *arg); + +/* + * Driver data (common to all clients) + */ +static struct i2c_driver ds1337_driver = { + .driver = { + .name = "ds1337", + }, + .attach_adapter = ds1337_attach_adapter, + .detach_client = ds1337_detach_client, + .command = ds1337_command, +}; + +/* + * Client data (each client gets its own) + */ +struct ds1337_data { + struct i2c_client client; + struct list_head list; +}; + +/* + * Internal variables + */ +static LIST_HEAD(ds1337_clients); + +static inline int ds1337_read(struct i2c_client *client, u8 reg, u8 *value) +{ + s32 tmp = i2c_smbus_read_byte_data(client, reg); + + if (tmp < 0) + return -EIO; + + *value = tmp; + + return 0; +} + +/* + * Chip access functions + */ +static int ds1337_get_datetime(struct i2c_client *client, struct rtc_time *dt) +{ + int result; + u8 buf[7]; + u8 val; + struct i2c_msg msg[2]; + u8 offs = 0; + + if (!dt) { + dev_dbg(&client->dev, "%s: EINVAL: dt=NULL\n", __FUNCTION__); + return -EINVAL; + } + + msg[0].addr = client->addr; + msg[0].flags = 0; + msg[0].len = 1; + msg[0].buf = &offs; + + msg[1].addr = client->addr; + msg[1].flags = I2C_M_RD; + msg[1].len = sizeof(buf); + msg[1].buf = &buf[0]; + + result = i2c_transfer(client->adapter, msg, 2); + + dev_dbg(&client->dev, "%s: [%d] %02x %02x %02x %02x %02x %02x %02x\n", + __FUNCTION__, result, buf[0], buf[1], buf[2], buf[3], + buf[4], buf[5], buf[6]); + + if (result == 2) { + dt->tm_sec = BCD2BIN(buf[0]); + dt->tm_min = BCD2BIN(buf[1]); + val = buf[2] & 0x3f; + dt->tm_hour = BCD2BIN(val); + dt->tm_wday = BCD2BIN(buf[3]) - 1; + dt->tm_mday = BCD2BIN(buf[4]); + val = buf[5] & 0x7f; + dt->tm_mon = BCD2BIN(val) - 1; + dt->tm_year = BCD2BIN(buf[6]); + if (buf[5] & 0x80) + dt->tm_year += 100; + + dev_dbg(&client->dev, "%s: secs=%d, mins=%d, " + "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", + __FUNCTION__, dt->tm_sec, dt->tm_min, + dt->tm_hour, dt->tm_mday, + dt->tm_mon, dt->tm_year, dt->tm_wday); + + return 0; + } + + dev_err(&client->dev, "error reading data! %d\n", result); + return -EIO; +} + +static int ds1337_set_datetime(struct i2c_client *client, struct rtc_time *dt) +{ + int result; + u8 buf[8]; + u8 val; + struct i2c_msg msg[1]; + + if (!dt) { + dev_dbg(&client->dev, "%s: EINVAL: dt=NULL\n", __FUNCTION__); + return -EINVAL; + } + + dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " + "mday=%d, mon=%d, year=%d, wday=%d\n", __FUNCTION__, + dt->tm_sec, dt->tm_min, dt->tm_hour, + dt->tm_mday, dt->tm_mon, dt->tm_year, dt->tm_wday); + + buf[0] = 0; /* reg offset */ + buf[1] = BIN2BCD(dt->tm_sec); + buf[2] = BIN2BCD(dt->tm_min); + buf[3] = BIN2BCD(dt->tm_hour); + buf[4] = BIN2BCD(dt->tm_wday + 1); + buf[5] = BIN2BCD(dt->tm_mday); + buf[6] = BIN2BCD(dt->tm_mon + 1); + val = dt->tm_year; + if (val >= 100) { + val -= 100; + buf[6] |= (1 << 7); + } + buf[7] = BIN2BCD(val); + + msg[0].addr = client->addr; + msg[0].flags = 0; + msg[0].len = sizeof(buf); + msg[0].buf = &buf[0]; + + result = i2c_transfer(client->adapter, msg, 1); + if (result == 1) + return 0; + + dev_err(&client->dev, "error writing data! %d\n", result); + return -EIO; +} + +static int ds1337_command(struct i2c_client *client, unsigned int cmd, + void *arg) +{ + dev_dbg(&client->dev, "%s: cmd=%d\n", __FUNCTION__, cmd); + + switch (cmd) { + case DS1337_GET_DATE: + return ds1337_get_datetime(client, arg); + + case DS1337_SET_DATE: + return ds1337_set_datetime(client, arg); + + default: + return -EINVAL; + } +} + +/* + * Public API for access to specific device. Useful for low-level + * RTC access from kernel code. + */ +int ds1337_do_command(int bus, int cmd, void *arg) +{ + struct list_head *walk; + struct list_head *tmp; + struct ds1337_data *data; + + list_for_each_safe(walk, tmp, &ds1337_clients) { + data = list_entry(walk, struct ds1337_data, list); + if (data->client.adapter->nr == bus) + return ds1337_command(&data->client, cmd, arg); + } + + return -ENODEV; +} + +static int ds1337_attach_adapter(struct i2c_adapter *adapter) +{ + return i2c_probe(adapter, &addr_data, ds1337_detect); +} + +/* + * The following function does more than just detection. If detection + * succeeds, it also registers the new chip. + */ +static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *new_client; + struct ds1337_data *data; + int err = 0; + const char *name = ""; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_I2C)) + goto exit; + + if (!(data = kzalloc(sizeof(struct ds1337_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + INIT_LIST_HEAD(&data->list); + + /* The common I2C client data is placed right before the + * DS1337-specific data. + */ + new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = address; + new_client->adapter = adapter; + new_client->driver = &ds1337_driver; + new_client->flags = 0; + + /* + * Now we do the remaining detection. A negative kind means that + * the driver was loaded with no force parameter (default), so we + * must both detect and identify the chip. A zero kind means that + * the driver was loaded with the force parameter, the detection + * step shall be skipped. A positive kind means that the driver + * was loaded with the force parameter and a given kind of chip is + * requested, so both the detection and the identification steps + * are skipped. + * + * For detection, we read registers that are most likely to cause + * detection failure, i.e. those that have more bits with fixed + * or reserved values. + */ + + /* Default to an DS1337 if forced */ + if (kind == 0) + kind = ds1337; + + if (kind < 0) { /* detection and identification */ + u8 data; + + /* Check that status register bits 6-2 are zero */ + if ((ds1337_read(new_client, DS1337_REG_STATUS, &data) < 0) || + (data & 0x7c)) + goto exit_free; + + /* Check for a valid day register value */ + if ((ds1337_read(new_client, DS1337_REG_DAY, &data) < 0) || + (data == 0) || (data & 0xf8)) + goto exit_free; + + /* Check for a valid date register value */ + if ((ds1337_read(new_client, DS1337_REG_DATE, &data) < 0) || + (data == 0) || (data & 0xc0) || ((data & 0x0f) > 9) || + (data >= 0x32)) + goto exit_free; + + /* Check for a valid month register value */ + if ((ds1337_read(new_client, DS1337_REG_MONTH, &data) < 0) || + (data == 0) || (data & 0x60) || ((data & 0x0f) > 9) || + ((data >= 0x13) && (data <= 0x19))) + goto exit_free; + + /* Check that control register bits 6-5 are zero */ + if ((ds1337_read(new_client, DS1337_REG_CONTROL, &data) < 0) || + (data & 0x60)) + goto exit_free; + + kind = ds1337; + } + + if (kind == ds1337) + name = "ds1337"; + + /* We can fill in the remaining client fields */ + strlcpy(new_client->name, name, I2C_NAME_SIZE); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) + goto exit_free; + + /* Initialize the DS1337 chip */ + ds1337_init_client(new_client); + + /* Add client to local list */ + list_add(&data->list, &ds1337_clients); + + return 0; + +exit_free: + kfree(data); +exit: + return err; +} + +static void ds1337_init_client(struct i2c_client *client) +{ + u8 status, control; + + /* On some boards, the RTC isn't configured by boot firmware. + * Handle that case by starting/configuring the RTC now. + */ + status = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS); + control = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL); + + if ((status & 0x80) || (control & 0x80)) { + /* RTC not running */ + u8 buf[1+16]; /* First byte is interpreted as address */ + struct i2c_msg msg[1]; + + dev_dbg(&client->dev, "%s: RTC not running!\n", __FUNCTION__); + + /* Initialize all, including STATUS and CONTROL to zero */ + memset(buf, 0, sizeof(buf)); + + /* Write valid values in the date/time registers */ + buf[1+DS1337_REG_DAY] = 1; + buf[1+DS1337_REG_DATE] = 1; + buf[1+DS1337_REG_MONTH] = 1; + + msg[0].addr = client->addr; + msg[0].flags = 0; + msg[0].len = sizeof(buf); + msg[0].buf = &buf[0]; + + i2c_transfer(client->adapter, msg, 1); + } else { + /* Running: ensure that device is set in 24-hour mode */ + s32 val; + + val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR); + if ((val >= 0) && (val & (1 << 6))) + i2c_smbus_write_byte_data(client, DS1337_REG_HOUR, + val & 0x3f); + } +} + +static int ds1337_detach_client(struct i2c_client *client) +{ + int err; + struct ds1337_data *data = i2c_get_clientdata(client); + + if ((err = i2c_detach_client(client))) + return err; + + list_del(&data->list); + kfree(data); + return 0; +} + +static int __init ds1337_init(void) +{ + return i2c_add_driver(&ds1337_driver); +} + +static void __exit ds1337_exit(void) +{ + i2c_del_driver(&ds1337_driver); +} + +MODULE_AUTHOR("James Chapman "); +MODULE_DESCRIPTION("DS1337 RTC driver"); +MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL_GPL(ds1337_do_command); + +module_init(ds1337_init); +module_exit(ds1337_exit); diff --git a/trunk/drivers/i2c/chips/ds1374.c b/trunk/drivers/i2c/chips/ds1374.c new file mode 100644 index 000000000000..8a2ff0c114d9 --- /dev/null +++ b/trunk/drivers/i2c/chips/ds1374.c @@ -0,0 +1,267 @@ +/* + * drivers/i2c/chips/ds1374.c + * + * I2C client/driver for the Maxim/Dallas DS1374 Real-Time Clock + * + * Author: Randy Vinson + * + * Based on the m41t00.c by Mark Greer + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +/* + * This i2c client/driver wedges between the drivers/char/genrtc.c RTC + * interface and the SMBus interface of the i2c subsystem. + * It would be more efficient to use i2c msgs/i2c_transfer directly but, as + * recommened in .../Documentation/i2c/writing-clients section + * "Sending and receiving", using SMBus level communication is preferred. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DS1374_REG_TOD0 0x00 +#define DS1374_REG_TOD1 0x01 +#define DS1374_REG_TOD2 0x02 +#define DS1374_REG_TOD3 0x03 +#define DS1374_REG_WDALM0 0x04 +#define DS1374_REG_WDALM1 0x05 +#define DS1374_REG_WDALM2 0x06 +#define DS1374_REG_CR 0x07 +#define DS1374_REG_SR 0x08 +#define DS1374_REG_SR_OSF 0x80 +#define DS1374_REG_TCR 0x09 + +#define DS1374_DRV_NAME "ds1374" + +static DEFINE_MUTEX(ds1374_mutex); + +static struct i2c_driver ds1374_driver; +static struct i2c_client *save_client; + +static unsigned short ignore[] = { I2C_CLIENT_END }; +static unsigned short normal_addr[] = { 0x68, I2C_CLIENT_END }; + +static struct i2c_client_address_data addr_data = { + .normal_i2c = normal_addr, + .probe = ignore, + .ignore = ignore, +}; + +static ulong ds1374_read_rtc(void) +{ + ulong time = 0; + int reg = DS1374_REG_WDALM0; + + while (reg--) { + s32 tmp; + if ((tmp = i2c_smbus_read_byte_data(save_client, reg)) < 0) { + dev_warn(&save_client->dev, + "can't read from rtc chip\n"); + return 0; + } + time = (time << 8) | (tmp & 0xff); + } + return time; +} + +static void ds1374_write_rtc(ulong time) +{ + int reg; + + for (reg = DS1374_REG_TOD0; reg < DS1374_REG_WDALM0; reg++) { + if (i2c_smbus_write_byte_data(save_client, reg, time & 0xff) + < 0) { + dev_warn(&save_client->dev, + "can't write to rtc chip\n"); + break; + } + time = time >> 8; + } +} + +static void ds1374_check_rtc_status(void) +{ + s32 tmp; + + tmp = i2c_smbus_read_byte_data(save_client, DS1374_REG_SR); + if (tmp < 0) { + dev_warn(&save_client->dev, + "can't read status from rtc chip\n"); + return; + } + if (tmp & DS1374_REG_SR_OSF) { + dev_warn(&save_client->dev, + "oscillator discontinuity flagged, time unreliable\n"); + tmp &= ~DS1374_REG_SR_OSF; + tmp = i2c_smbus_write_byte_data(save_client, DS1374_REG_SR, + tmp & 0xff); + if (tmp < 0) + dev_warn(&save_client->dev, + "can't clear discontinuity notification\n"); + } +} + +ulong ds1374_get_rtc_time(void) +{ + ulong t1, t2; + int limit = 10; /* arbitrary retry limit */ + + mutex_lock(&ds1374_mutex); + + /* + * Since the reads are being performed one byte at a time using + * the SMBus vs a 4-byte i2c transfer, there is a chance that a + * carry will occur during the read. To detect this, 2 reads are + * performed and compared. + */ + do { + t1 = ds1374_read_rtc(); + t2 = ds1374_read_rtc(); + } while (t1 != t2 && limit--); + + mutex_unlock(&ds1374_mutex); + + if (t1 != t2) { + dev_warn(&save_client->dev, + "can't get consistent time from rtc chip\n"); + t1 = 0; + } + + return t1; +} + +static ulong new_time; + +static void ds1374_set_work(struct work_struct *work) +{ + ulong t1, t2; + int limit = 10; /* arbitrary retry limit */ + + t1 = new_time; + + mutex_lock(&ds1374_mutex); + + /* + * Since the writes are being performed one byte at a time using + * the SMBus vs a 4-byte i2c transfer, there is a chance that a + * carry will occur during the write. To detect this, the write + * value is read back and compared. + */ + do { + ds1374_write_rtc(t1); + t2 = ds1374_read_rtc(); + } while (t1 != t2 && limit--); + + mutex_unlock(&ds1374_mutex); + + if (t1 != t2) + dev_warn(&save_client->dev, + "can't confirm time set from rtc chip\n"); +} + +static struct workqueue_struct *ds1374_workqueue; + +static DECLARE_WORK(ds1374_work, ds1374_set_work); + +int ds1374_set_rtc_time(ulong nowtime) +{ + new_time = nowtime; + + if (in_interrupt()) + queue_work(ds1374_workqueue, &ds1374_work); + else + ds1374_set_work(NULL); + + return 0; +} + +/* + ***************************************************************************** + * + * Driver Interface + * + ***************************************************************************** + */ +static int ds1374_probe(struct i2c_adapter *adap, int addr, int kind) +{ + struct i2c_client *client; + int rc; + + client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (!client) + return -ENOMEM; + + strncpy(client->name, DS1374_DRV_NAME, I2C_NAME_SIZE); + client->addr = addr; + client->adapter = adap; + client->driver = &ds1374_driver; + + ds1374_workqueue = create_singlethread_workqueue("ds1374"); + if (!ds1374_workqueue) { + kfree(client); + return -ENOMEM; /* most expected reason */ + } + + if ((rc = i2c_attach_client(client)) != 0) { + kfree(client); + return rc; + } + + save_client = client; + + ds1374_check_rtc_status(); + + return 0; +} + +static int ds1374_attach(struct i2c_adapter *adap) +{ + return i2c_probe(adap, &addr_data, ds1374_probe); +} + +static int ds1374_detach(struct i2c_client *client) +{ + int rc; + + if ((rc = i2c_detach_client(client)) == 0) { + kfree(i2c_get_clientdata(client)); + destroy_workqueue(ds1374_workqueue); + } + return rc; +} + +static struct i2c_driver ds1374_driver = { + .driver = { + .name = DS1374_DRV_NAME, + }, + .id = I2C_DRIVERID_DS1374, + .attach_adapter = ds1374_attach, + .detach_client = ds1374_detach, +}; + +static int __init ds1374_init(void) +{ + return i2c_add_driver(&ds1374_driver); +} + +static void __exit ds1374_exit(void) +{ + i2c_del_driver(&ds1374_driver); +} + +module_init(ds1374_init); +module_exit(ds1374_exit); + +MODULE_AUTHOR("Randy Vinson "); +MODULE_DESCRIPTION("Maxim/Dallas DS1374 RTC I2C Client Driver"); +MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/i2c/chips/eeprom.c b/trunk/drivers/i2c/chips/eeprom.c index fde297b21ad7..1a7eeebac506 100644 --- a/trunk/drivers/i2c/chips/eeprom.c +++ b/trunk/drivers/i2c/chips/eeprom.c @@ -35,7 +35,7 @@ #include /* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, +static unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, I2C_CLIENT_END }; /* Insmod parameters */ diff --git a/trunk/drivers/i2c/chips/isp1301_omap.c b/trunk/drivers/i2c/chips/isp1301_omap.c index 2a3160153f54..ebfbb2947ae6 100644 --- a/trunk/drivers/i2c/chips/isp1301_omap.c +++ b/trunk/drivers/i2c/chips/isp1301_omap.c @@ -100,7 +100,7 @@ struct isp1301 { #if defined(CONFIG_TPS65010) || defined(CONFIG_TPS65010_MODULE) -#include +#include #else diff --git a/trunk/drivers/i2c/chips/m41t00.c b/trunk/drivers/i2c/chips/m41t00.c new file mode 100644 index 000000000000..3fcb646e2073 --- /dev/null +++ b/trunk/drivers/i2c/chips/m41t00.c @@ -0,0 +1,413 @@ +/* + * I2C client/driver for the ST M41T00 family of i2c rtc chips. + * + * Author: Mark A. Greer + * + * 2005, 2006 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +/* + * This i2c client/driver wedges between the drivers/char/genrtc.c RTC + * interface and the SMBus interface of the i2c subsystem. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct i2c_driver m41t00_driver; +static struct i2c_client *save_client; + +static unsigned short ignore[] = { I2C_CLIENT_END }; +static unsigned short normal_addr[] = { I2C_CLIENT_END, I2C_CLIENT_END }; + +static struct i2c_client_address_data addr_data = { + .normal_i2c = normal_addr, + .probe = ignore, + .ignore = ignore, +}; + +struct m41t00_chip_info { + u8 type; + char *name; + u8 read_limit; + u8 sec; /* Offsets for chip regs */ + u8 min; + u8 hour; + u8 day; + u8 mon; + u8 year; + u8 alarm_mon; + u8 alarm_hour; + u8 sqw; + u8 sqw_freq; +}; + +static struct m41t00_chip_info m41t00_chip_info_tbl[] = { + { + .type = M41T00_TYPE_M41T00, + .name = "m41t00", + .read_limit = 5, + .sec = 0, + .min = 1, + .hour = 2, + .day = 4, + .mon = 5, + .year = 6, + }, + { + .type = M41T00_TYPE_M41T81, + .name = "m41t81", + .read_limit = 1, + .sec = 1, + .min = 2, + .hour = 3, + .day = 5, + .mon = 6, + .year = 7, + .alarm_mon = 0xa, + .alarm_hour = 0xc, + .sqw = 0x13, + }, + { + .type = M41T00_TYPE_M41T85, + .name = "m41t85", + .read_limit = 1, + .sec = 1, + .min = 2, + .hour = 3, + .day = 5, + .mon = 6, + .year = 7, + .alarm_mon = 0xa, + .alarm_hour = 0xc, + .sqw = 0x13, + }, +}; +static struct m41t00_chip_info *m41t00_chip; + +ulong +m41t00_get_rtc_time(void) +{ + s32 sec, min, hour, day, mon, year; + s32 sec1, min1, hour1, day1, mon1, year1; + u8 reads = 0; + u8 buf[8], msgbuf[1] = { 0 }; /* offset into rtc's regs */ + struct i2c_msg msgs[] = { + { + .addr = save_client->addr, + .flags = 0, + .len = 1, + .buf = msgbuf, + }, + { + .addr = save_client->addr, + .flags = I2C_M_RD, + .len = 8, + .buf = buf, + }, + }; + + sec = min = hour = day = mon = year = 0; + + do { + if (i2c_transfer(save_client->adapter, msgs, 2) < 0) + goto read_err; + + sec1 = sec; + min1 = min; + hour1 = hour; + day1 = day; + mon1 = mon; + year1 = year; + + sec = buf[m41t00_chip->sec] & 0x7f; + min = buf[m41t00_chip->min] & 0x7f; + hour = buf[m41t00_chip->hour] & 0x3f; + day = buf[m41t00_chip->day] & 0x3f; + mon = buf[m41t00_chip->mon] & 0x1f; + year = buf[m41t00_chip->year]; + } while ((++reads < m41t00_chip->read_limit) && ((sec != sec1) + || (min != min1) || (hour != hour1) || (day != day1) + || (mon != mon1) || (year != year1))); + + if ((m41t00_chip->read_limit > 1) && ((sec != sec1) || (min != min1) + || (hour != hour1) || (day != day1) || (mon != mon1) + || (year != year1))) + goto read_err; + + sec = BCD2BIN(sec); + min = BCD2BIN(min); + hour = BCD2BIN(hour); + day = BCD2BIN(day); + mon = BCD2BIN(mon); + year = BCD2BIN(year); + + year += 1900; + if (year < 1970) + year += 100; + + return mktime(year, mon, day, hour, min, sec); + +read_err: + dev_err(&save_client->dev, "m41t00_get_rtc_time: Read error\n"); + return 0; +} +EXPORT_SYMBOL_GPL(m41t00_get_rtc_time); + +static void +m41t00_set(void *arg) +{ + struct rtc_time tm; + int nowtime = *(int *)arg; + s32 sec, min, hour, day, mon, year; + u8 wbuf[9], *buf = &wbuf[1], msgbuf[1] = { 0 }; + struct i2c_msg msgs[] = { + { + .addr = save_client->addr, + .flags = 0, + .len = 1, + .buf = msgbuf, + }, + { + .addr = save_client->addr, + .flags = I2C_M_RD, + .len = 8, + .buf = buf, + }, + }; + + to_tm(nowtime, &tm); + tm.tm_year = (tm.tm_year - 1900) % 100; + + sec = BIN2BCD(tm.tm_sec); + min = BIN2BCD(tm.tm_min); + hour = BIN2BCD(tm.tm_hour); + day = BIN2BCD(tm.tm_mday); + mon = BIN2BCD(tm.tm_mon); + year = BIN2BCD(tm.tm_year); + + /* Read reg values into buf[0..7]/wbuf[1..8] */ + if (i2c_transfer(save_client->adapter, msgs, 2) < 0) { + dev_err(&save_client->dev, "m41t00_set: Read error\n"); + return; + } + + wbuf[0] = 0; /* offset into rtc's regs */ + buf[m41t00_chip->sec] = (buf[m41t00_chip->sec] & ~0x7f) | (sec & 0x7f); + buf[m41t00_chip->min] = (buf[m41t00_chip->min] & ~0x7f) | (min & 0x7f); + buf[m41t00_chip->hour] = (buf[m41t00_chip->hour] & ~0x3f) | (hour& 0x3f); + buf[m41t00_chip->day] = (buf[m41t00_chip->day] & ~0x3f) | (day & 0x3f); + buf[m41t00_chip->mon] = (buf[m41t00_chip->mon] & ~0x1f) | (mon & 0x1f); + buf[m41t00_chip->year] = year; + + if (i2c_master_send(save_client, wbuf, 9) < 0) + dev_err(&save_client->dev, "m41t00_set: Write error\n"); +} + +static ulong new_time; +/* well, isn't this API just _lovely_? */ +static void +m41t00_barf(struct work_struct *unusable) +{ + m41t00_set(&new_time); +} + +static struct workqueue_struct *m41t00_wq; +static DECLARE_WORK(m41t00_work, m41t00_barf); + +int +m41t00_set_rtc_time(ulong nowtime) +{ + new_time = nowtime; + + if (in_interrupt()) + queue_work(m41t00_wq, &m41t00_work); + else + m41t00_set(&new_time); + + return 0; +} +EXPORT_SYMBOL_GPL(m41t00_set_rtc_time); + +/* + ***************************************************************************** + * + * platform_data Driver Interface + * + ***************************************************************************** + */ +static int __init +m41t00_platform_probe(struct platform_device *pdev) +{ + struct m41t00_platform_data *pdata; + int i; + + if (pdev && (pdata = pdev->dev.platform_data)) { + normal_addr[0] = pdata->i2c_addr; + + for (i=0; itype) { + m41t00_chip = &m41t00_chip_info_tbl[i]; + m41t00_chip->sqw_freq = pdata->sqw_freq; + return 0; + } + } + return -ENODEV; +} + +static int __exit +m41t00_platform_remove(struct platform_device *pdev) +{ + return 0; +} + +static struct platform_driver m41t00_platform_driver = { + .probe = m41t00_platform_probe, + .remove = m41t00_platform_remove, + .driver = { + .owner = THIS_MODULE, + .name = M41T00_DRV_NAME, + }, +}; + +/* + ***************************************************************************** + * + * Driver Interface + * + ***************************************************************************** + */ +static int +m41t00_probe(struct i2c_adapter *adap, int addr, int kind) +{ + struct i2c_client *client; + int rc; + + if (!i2c_check_functionality(adap, I2C_FUNC_I2C + | I2C_FUNC_SMBUS_BYTE_DATA)) + return 0; + + client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (!client) + return -ENOMEM; + + strlcpy(client->name, m41t00_chip->name, I2C_NAME_SIZE); + client->addr = addr; + client->adapter = adap; + client->driver = &m41t00_driver; + + if ((rc = i2c_attach_client(client))) + goto attach_err; + + if (m41t00_chip->type != M41T00_TYPE_M41T00) { + /* If asked, disable SQW, set SQW frequency & re-enable */ + if (m41t00_chip->sqw_freq) + if (((rc = i2c_smbus_read_byte_data(client, + m41t00_chip->alarm_mon)) < 0) + || ((rc = i2c_smbus_write_byte_data(client, + m41t00_chip->alarm_mon, rc & ~0x40)) <0) + || ((rc = i2c_smbus_write_byte_data(client, + m41t00_chip->sqw, + m41t00_chip->sqw_freq)) < 0) + || ((rc = i2c_smbus_write_byte_data(client, + m41t00_chip->alarm_mon, rc | 0x40)) <0)) + goto sqw_err; + + /* Make sure HT (Halt Update) bit is cleared */ + if ((rc = i2c_smbus_read_byte_data(client, + m41t00_chip->alarm_hour)) < 0) + goto ht_err; + + if (rc & 0x40) + if ((rc = i2c_smbus_write_byte_data(client, + m41t00_chip->alarm_hour, rc & ~0x40))<0) + goto ht_err; + } + + /* Make sure ST (stop) bit is cleared */ + if ((rc = i2c_smbus_read_byte_data(client, m41t00_chip->sec)) < 0) + goto st_err; + + if (rc & 0x80) + if ((rc = i2c_smbus_write_byte_data(client, m41t00_chip->sec, + rc & ~0x80)) < 0) + goto st_err; + + m41t00_wq = create_singlethread_workqueue(m41t00_chip->name); + save_client = client; + return 0; + +st_err: + dev_err(&client->dev, "m41t00_probe: Can't clear ST bit\n"); + goto attach_err; +ht_err: + dev_err(&client->dev, "m41t00_probe: Can't clear HT bit\n"); + goto attach_err; +sqw_err: + dev_err(&client->dev, "m41t00_probe: Can't set SQW Frequency\n"); +attach_err: + kfree(client); + return rc; +} + +static int +m41t00_attach(struct i2c_adapter *adap) +{ + return i2c_probe(adap, &addr_data, m41t00_probe); +} + +static int +m41t00_detach(struct i2c_client *client) +{ + int rc; + + if ((rc = i2c_detach_client(client)) == 0) { + kfree(client); + destroy_workqueue(m41t00_wq); + } + return rc; +} + +static struct i2c_driver m41t00_driver = { + .driver = { + .name = M41T00_DRV_NAME, + }, + .id = I2C_DRIVERID_STM41T00, + .attach_adapter = m41t00_attach, + .detach_client = m41t00_detach, +}; + +static int __init +m41t00_init(void) +{ + int rc; + + if (!(rc = platform_driver_register(&m41t00_platform_driver))) + rc = i2c_add_driver(&m41t00_driver); + return rc; +} + +static void __exit +m41t00_exit(void) +{ + i2c_del_driver(&m41t00_driver); + platform_driver_unregister(&m41t00_platform_driver); +} + +module_init(m41t00_init); +module_exit(m41t00_exit); + +MODULE_AUTHOR("Mark A. Greer "); +MODULE_DESCRIPTION("ST Microelectronics M41T00 RTC I2C Client Driver"); +MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/i2c/chips/max6875.c b/trunk/drivers/i2c/chips/max6875.c index fb7ea5637eca..64692f666372 100644 --- a/trunk/drivers/i2c/chips/max6875.c +++ b/trunk/drivers/i2c/chips/max6875.c @@ -34,7 +34,7 @@ #include /* Do not scan - the MAX6875 access method will write to some EEPROM chips */ -static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; +static unsigned short normal_i2c[] = {I2C_CLIENT_END}; /* Insmod parameters */ I2C_CLIENT_INSMOD_1(max6875); diff --git a/trunk/drivers/i2c/chips/pcf8574.c b/trunk/drivers/i2c/chips/pcf8574.c index b3b830ccf209..21c6dd69193c 100644 --- a/trunk/drivers/i2c/chips/pcf8574.c +++ b/trunk/drivers/i2c/chips/pcf8574.c @@ -41,11 +41,9 @@ #include /* Addresses to scan */ -static const unsigned short normal_i2c[] = { - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - I2C_CLIENT_END -}; +static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + I2C_CLIENT_END }; /* Insmod parameters */ I2C_CLIENT_INSMOD_2(pcf8574, pcf8574a); diff --git a/trunk/drivers/i2c/chips/pcf8575.c b/trunk/drivers/i2c/chips/pcf8575.c deleted file mode 100644 index 3ea08ac0bfa3..000000000000 --- a/trunk/drivers/i2c/chips/pcf8575.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - pcf8575.c - - About the PCF8575 chip: the PCF8575 is a 16-bit I/O expander for the I2C bus - produced by a.o. Philips Semiconductors. - - Copyright (C) 2006 Michael Hennerich, Analog Devices Inc. - - Based on pcf8574.c. - - Copyright (c) 2007 Bart Van Assche . - Ported this driver from ucLinux to the mainstream Linux kernel. - - 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 /* kzalloc() */ -#include /* sysfs_create_group() */ - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - I2C_CLIENT_END -}; - -/* Insmod parameters */ -I2C_CLIENT_INSMOD; - - -/* Each client has this additional data */ -struct pcf8575_data { - struct i2c_client client; - int write; /* last written value, or error code */ -}; - -static int pcf8575_attach_adapter(struct i2c_adapter *adapter); -static int pcf8575_detect(struct i2c_adapter *adapter, int address, int kind); -static int pcf8575_detach_client(struct i2c_client *client); - -/* This is the driver that will be inserted */ -static struct i2c_driver pcf8575_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "pcf8575", - }, - .attach_adapter = pcf8575_attach_adapter, - .detach_client = pcf8575_detach_client, -}; - -/* following are the sysfs callback functions */ -static ssize_t show_read(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - u16 val; - u8 iopin_state[2]; - - i2c_master_recv(client, iopin_state, 2); - - val = iopin_state[0]; - val |= iopin_state[1] << 8; - - return sprintf(buf, "%u\n", val); -} - -static DEVICE_ATTR(read, S_IRUGO, show_read, NULL); - -static ssize_t show_write(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct pcf8575_data *data = dev_get_drvdata(dev); - if (data->write < 0) - return data->write; - return sprintf(buf, "%d\n", data->write); -} - -static ssize_t set_write(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct pcf8575_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - u8 iopin_state[2]; - - if (val > 0xffff) - return -EINVAL; - - data->write = val; - - iopin_state[0] = val & 0xFF; - iopin_state[1] = val >> 8; - - i2c_master_send(client, iopin_state, 2); - - return count; -} - -static DEVICE_ATTR(write, S_IWUSR | S_IRUGO, show_write, set_write); - -static struct attribute *pcf8575_attributes[] = { - &dev_attr_read.attr, - &dev_attr_write.attr, - NULL -}; - -static const struct attribute_group pcf8575_attr_group = { - .attrs = pcf8575_attributes, -}; - -/* - * Real code - */ - -static int pcf8575_attach_adapter(struct i2c_adapter *adapter) -{ - return i2c_probe(adapter, &addr_data, pcf8575_detect); -} - -/* This function is called by i2c_probe */ -static int pcf8575_detect(struct i2c_adapter *adapter, int address, int kind) -{ - struct i2c_client *client; - struct pcf8575_data *data; - int err = 0; - - if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) - goto exit; - - /* OK. For now, we presume we have a valid client. We now create the - client structure, even though we cannot fill it completely yet. */ - data = kzalloc(sizeof(struct pcf8575_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - client = &data->client; - i2c_set_clientdata(client, data); - client->addr = address; - client->adapter = adapter; - client->driver = &pcf8575_driver; - strlcpy(client->name, "pcf8575", I2C_NAME_SIZE); - data->write = -EAGAIN; - - /* This is the place to detect whether the chip at the specified - address really is a PCF8575 chip. However, there is no method known - to detect whether an I2C chip is a PCF8575 or any other I2C chip. */ - - /* Tell the I2C layer a new client has arrived */ - err = i2c_attach_client(client); - if (err) - goto exit_free; - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &pcf8575_attr_group); - if (err) - goto exit_detach; - - return 0; - -exit_detach: - i2c_detach_client(client); -exit_free: - kfree(data); -exit: - return err; -} - -static int pcf8575_detach_client(struct i2c_client *client) -{ - int err; - - sysfs_remove_group(&client->dev.kobj, &pcf8575_attr_group); - - err = i2c_detach_client(client); - if (err) - return err; - - kfree(i2c_get_clientdata(client)); - return 0; -} - -static int __init pcf8575_init(void) -{ - return i2c_add_driver(&pcf8575_driver); -} - -static void __exit pcf8575_exit(void) -{ - i2c_del_driver(&pcf8575_driver); -} - -MODULE_AUTHOR("Michael Hennerich , " - "Bart Van Assche "); -MODULE_DESCRIPTION("pcf8575 driver"); -MODULE_LICENSE("GPL"); - -module_init(pcf8575_init); -module_exit(pcf8575_exit); diff --git a/trunk/drivers/i2c/chips/pcf8591.c b/trunk/drivers/i2c/chips/pcf8591.c index 865f4409c06b..4dc36376eb32 100644 --- a/trunk/drivers/i2c/chips/pcf8591.c +++ b/trunk/drivers/i2c/chips/pcf8591.c @@ -27,7 +27,7 @@ #include /* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, +static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; /* Insmod parameters */ diff --git a/trunk/drivers/i2c/chips/tps65010.c b/trunk/drivers/i2c/chips/tps65010.c index 4154a9108859..e320994b981c 100644 --- a/trunk/drivers/i2c/chips/tps65010.c +++ b/trunk/drivers/i2c/chips/tps65010.c @@ -31,7 +31,7 @@ #include #include -#include +#include /*-------------------------------------------------------------------------*/ diff --git a/trunk/drivers/i2c/chips/tsl2550.c b/trunk/drivers/i2c/chips/tsl2550.c index a10fd2791a69..3de4b19ba08f 100644 --- a/trunk/drivers/i2c/chips/tsl2550.c +++ b/trunk/drivers/i2c/chips/tsl2550.c @@ -432,32 +432,11 @@ static int __devexit tsl2550_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM - -static int tsl2550_suspend(struct i2c_client *client, pm_message_t mesg) -{ - return tsl2550_set_power_state(client, 0); -} - -static int tsl2550_resume(struct i2c_client *client) -{ - return tsl2550_set_power_state(client, 1); -} - -#else - -#define tsl2550_suspend NULL -#define tsl2550_resume NULL - -#endif /* CONFIG_PM */ - static struct i2c_driver tsl2550_driver = { .driver = { .name = TSL2550_DRV_NAME, .owner = THIS_MODULE, }, - .suspend = tsl2550_suspend, - .resume = tsl2550_resume, .probe = tsl2550_probe, .remove = __devexit_p(tsl2550_remove), }; diff --git a/trunk/drivers/i2c/i2c-core.c b/trunk/drivers/i2c/i2c-core.c index 96da22e9a5a4..b5e13e405e72 100644 --- a/trunk/drivers/i2c/i2c-core.c +++ b/trunk/drivers/i2c/i2c-core.c @@ -33,15 +33,14 @@ #include #include #include -#include -#include #include -#include #include "i2c-core.h" -static DEFINE_MUTEX(core_lock); +static LIST_HEAD(adapters); +static LIST_HEAD(drivers); +static DEFINE_MUTEX(core_lists); static DEFINE_IDR(i2c_adapter_idr); #define is_newstyle_driver(d) ((d)->probe || (d)->remove) @@ -199,25 +198,6 @@ static struct bus_type i2c_bus_type = { .resume = i2c_device_resume, }; - -/** - * i2c_verify_client - return parameter as i2c_client, or NULL - * @dev: device, probably from some driver model iterator - * - * When traversing the driver model tree, perhaps using driver model - * iterators like @device_for_each_child(), you can't assume very much - * about the nodes you find. Use this function to avoid oopses caused - * by wrongly treating some non-I2C device as an i2c_client. - */ -struct i2c_client *i2c_verify_client(struct device *dev) -{ - return (dev->bus == &i2c_bus_type) - ? to_i2c_client(dev) - : NULL; -} -EXPORT_SYMBOL(i2c_verify_client); - - /** * i2c_new_device - instantiate an i2c device for use with a new style driver * @adap: the adapter managing the device @@ -296,50 +276,6 @@ void i2c_unregister_device(struct i2c_client *client) EXPORT_SYMBOL_GPL(i2c_unregister_device); -static int dummy_nop(struct i2c_client *client) -{ - return 0; -} - -static struct i2c_driver dummy_driver = { - .driver.name = "dummy", - .probe = dummy_nop, - .remove = dummy_nop, -}; - -/** - * i2c_new_dummy - return a new i2c device bound to a dummy driver - * @adapter: the adapter managing the device - * @address: seven bit address to be used - * @type: optional label used for i2c_client.name - * Context: can sleep - * - * This returns an I2C client bound to the "dummy" driver, intended for use - * with devices that consume multiple addresses. Examples of such chips - * include various EEPROMS (like 24c04 and 24c08 models). - * - * These dummy devices have two main uses. First, most I2C and SMBus calls - * except i2c_transfer() need a client handle; the dummy will be that handle. - * And second, this prevents the specified address from being bound to a - * different driver. - * - * This returns the new i2c client, which should be saved for later use with - * i2c_unregister_device(); or NULL to indicate an error. - */ -struct i2c_client * -i2c_new_dummy(struct i2c_adapter *adapter, u16 address, const char *type) -{ - struct i2c_board_info info = { - .driver_name = "dummy", - .addr = address, - }; - - if (type) - strlcpy(info.type, type, sizeof info.type); - return i2c_new_device(adapter, &info); -} -EXPORT_SYMBOL_GPL(i2c_new_dummy); - /* ------------------------------------------------------------------------- */ /* I2C bus adapters -- one roots each I2C or SMBUS segment */ @@ -384,27 +320,18 @@ static void i2c_scan_static_board_info(struct i2c_adapter *adapter) mutex_unlock(&__i2c_board_lock); } -static int i2c_do_add_adapter(struct device_driver *d, void *data) -{ - struct i2c_driver *driver = to_i2c_driver(d); - struct i2c_adapter *adap = data; - - if (driver->attach_adapter) { - /* We ignore the return code; if it fails, too bad */ - driver->attach_adapter(adap); - } - return 0; -} - static int i2c_register_adapter(struct i2c_adapter *adap) { - int res = 0, dummy; + int res = 0; + struct list_head *item; + struct i2c_driver *driver; mutex_init(&adap->bus_lock); mutex_init(&adap->clist_lock); INIT_LIST_HEAD(&adap->clients); - mutex_lock(&core_lock); + mutex_lock(&core_lists); + list_add_tail(&adap->list, &adapters); /* Add the adapter to the driver core. * If the parent pointer is not set up, @@ -429,14 +356,19 @@ static int i2c_register_adapter(struct i2c_adapter *adap) i2c_scan_static_board_info(adap); /* let legacy drivers scan this bus for matching devices */ - dummy = bus_for_each_drv(&i2c_bus_type, NULL, adap, - i2c_do_add_adapter); + list_for_each(item,&drivers) { + driver = list_entry(item, struct i2c_driver, list); + if (driver->attach_adapter) + /* We ignore the return code; if it fails, too bad */ + driver->attach_adapter(adap); + } out_unlock: - mutex_unlock(&core_lock); + mutex_unlock(&core_lists); return res; out_list: + list_del(&adap->list); idr_remove(&i2c_adapter_idr, adap->nr); goto out_unlock; } @@ -462,11 +394,11 @@ int i2c_add_adapter(struct i2c_adapter *adapter) if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) return -ENOMEM; - mutex_lock(&core_lock); + mutex_lock(&core_lists); /* "above" here means "above or equal to", sigh */ res = idr_get_new_above(&i2c_adapter_idr, adapter, __i2c_first_dynamic_bus_num, &id); - mutex_unlock(&core_lock); + mutex_unlock(&core_lists); if (res < 0) { if (res == -EAGAIN) @@ -511,7 +443,7 @@ int i2c_add_numbered_adapter(struct i2c_adapter *adap) if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) return -ENOMEM; - mutex_lock(&core_lock); + mutex_lock(&core_lists); /* "above" here means "above or equal to", sigh; * we need the "equal to" result to force the result */ @@ -520,7 +452,7 @@ int i2c_add_numbered_adapter(struct i2c_adapter *adap) status = -EBUSY; idr_remove(&i2c_adapter_idr, id); } - mutex_unlock(&core_lock); + mutex_unlock(&core_lists); if (status == -EAGAIN) goto retry; @@ -530,21 +462,6 @@ int i2c_add_numbered_adapter(struct i2c_adapter *adap) } EXPORT_SYMBOL_GPL(i2c_add_numbered_adapter); -static int i2c_do_del_adapter(struct device_driver *d, void *data) -{ - struct i2c_driver *driver = to_i2c_driver(d); - struct i2c_adapter *adapter = data; - int res; - - if (!driver->detach_adapter) - return 0; - res = driver->detach_adapter(adapter); - if (res) - dev_err(&adapter->dev, "detach_adapter failed (%d) " - "for driver [%s]\n", res, driver->driver.name); - return res; -} - /** * i2c_del_adapter - unregister I2C adapter * @adap: the adapter being unregistered @@ -556,24 +473,35 @@ static int i2c_do_del_adapter(struct device_driver *d, void *data) int i2c_del_adapter(struct i2c_adapter *adap) { struct list_head *item, *_n; + struct i2c_adapter *adap_from_list; + struct i2c_driver *driver; struct i2c_client *client; int res = 0; - mutex_lock(&core_lock); + mutex_lock(&core_lists); /* First make sure that this adapter was ever added */ - if (idr_find(&i2c_adapter_idr, adap->nr) != adap) { + list_for_each_entry(adap_from_list, &adapters, list) { + if (adap_from_list == adap) + break; + } + if (adap_from_list != adap) { pr_debug("i2c-core: attempting to delete unregistered " "adapter [%s]\n", adap->name); res = -EINVAL; goto out_unlock; } - /* Tell drivers about this removal */ - res = bus_for_each_drv(&i2c_bus_type, NULL, adap, - i2c_do_del_adapter); - if (res) - goto out_unlock; + list_for_each(item,&drivers) { + driver = list_entry(item, struct i2c_driver, list); + if (driver->detach_adapter) + if ((res = driver->detach_adapter(adap))) { + dev_err(&adap->dev, "detach_adapter failed " + "for driver [%s]\n", + driver->driver.name); + goto out_unlock; + } + } /* detach any active clients. This must be done first, because * it can fail; in which case we give up. */ @@ -601,6 +529,7 @@ int i2c_del_adapter(struct i2c_adapter *adap) /* clean up the sysfs representation */ init_completion(&adap->dev_released); device_unregister(&adap->dev); + list_del(&adap->list); /* wait for sysfs to drop all references */ wait_for_completion(&adap->dev_released); @@ -611,7 +540,7 @@ int i2c_del_adapter(struct i2c_adapter *adap) dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); out_unlock: - mutex_unlock(&core_lock); + mutex_unlock(&core_lists); return res; } EXPORT_SYMBOL(i2c_del_adapter); @@ -654,23 +583,21 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) if (res) return res; - mutex_lock(&core_lock); + mutex_lock(&core_lists); + list_add_tail(&driver->list,&drivers); pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); /* legacy drivers scan i2c busses directly */ if (driver->attach_adapter) { struct i2c_adapter *adapter; - down(&i2c_adapter_class.sem); - list_for_each_entry(adapter, &i2c_adapter_class.devices, - dev.node) { + list_for_each_entry(adapter, &adapters, list) { driver->attach_adapter(adapter); } - up(&i2c_adapter_class.sem); } - mutex_unlock(&core_lock); + mutex_unlock(&core_lists); return 0; } EXPORT_SYMBOL(i2c_register_driver); @@ -682,11 +609,11 @@ EXPORT_SYMBOL(i2c_register_driver); */ void i2c_del_driver(struct i2c_driver *driver) { - struct list_head *item2, *_n; + struct list_head *item1, *item2, *_n; struct i2c_client *client; struct i2c_adapter *adap; - mutex_lock(&core_lock); + mutex_lock(&core_lists); /* new-style driver? */ if (is_newstyle_driver(driver)) @@ -696,8 +623,8 @@ void i2c_del_driver(struct i2c_driver *driver) * attached. If so, detach them to be able to kill the driver * afterwards. */ - down(&i2c_adapter_class.sem); - list_for_each_entry(adap, &i2c_adapter_class.devices, dev.node) { + list_for_each(item1,&adapters) { + adap = list_entry(item1, struct i2c_adapter, list); if (driver->detach_adapter) { if (driver->detach_adapter(adap)) { dev_err(&adap->dev, "detach_adapter failed " @@ -721,31 +648,40 @@ void i2c_del_driver(struct i2c_driver *driver) } } } - up(&i2c_adapter_class.sem); unregister: driver_unregister(&driver->driver); + list_del(&driver->list); pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name); - mutex_unlock(&core_lock); + mutex_unlock(&core_lists); } EXPORT_SYMBOL(i2c_del_driver); /* ------------------------------------------------------------------------- */ -static int __i2c_check_addr(struct device *dev, void *addrp) +static int __i2c_check_addr(struct i2c_adapter *adapter, unsigned int addr) { - struct i2c_client *client = i2c_verify_client(dev); - int addr = *(int *)addrp; + struct list_head *item; + struct i2c_client *client; - if (client && client->addr == addr) - return -EBUSY; + list_for_each(item,&adapter->clients) { + client = list_entry(item, struct i2c_client, list); + if (client->addr == addr) + return -EBUSY; + } return 0; } static int i2c_check_addr(struct i2c_adapter *adapter, int addr) { - return device_for_each_child(&adapter->dev, &addr, __i2c_check_addr); + int rval; + + mutex_lock(&adapter->clist_lock); + rval = __i2c_check_addr(adapter, addr); + mutex_unlock(&adapter->clist_lock); + + return rval; } int i2c_attach_client(struct i2c_client *client) @@ -753,6 +689,15 @@ int i2c_attach_client(struct i2c_client *client) struct i2c_adapter *adapter = client->adapter; int res = 0; + mutex_lock(&adapter->clist_lock); + if (__i2c_check_addr(client->adapter, client->addr)) { + res = -EBUSY; + goto out_unlock; + } + list_add_tail(&client->list,&adapter->clients); + + client->usage_count = 0; + client->dev.parent = &client->adapter->dev; client->dev.bus = &i2c_bus_type; @@ -767,17 +712,13 @@ int i2c_attach_client(struct i2c_client *client) snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id), "%d-%04x", i2c_adapter_id(adapter), client->addr); + dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n", + client->name, client->dev.bus_id); res = device_register(&client->dev); if (res) - goto out_err; - - mutex_lock(&adapter->clist_lock); - list_add_tail(&client->list, &adapter->clients); + goto out_list; mutex_unlock(&adapter->clist_lock); - dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n", - client->name, client->dev.bus_id); - if (adapter->client_register) { if (adapter->client_register(client)) { dev_dbg(&adapter->dev, "client_register " @@ -788,9 +729,12 @@ int i2c_attach_client(struct i2c_client *client) return 0; -out_err: +out_list: + list_del(&client->list); dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x " "(%d)\n", client->name, client->addr, res); +out_unlock: + mutex_unlock(&adapter->clist_lock); return res; } EXPORT_SYMBOL(i2c_attach_client); @@ -800,6 +744,12 @@ int i2c_detach_client(struct i2c_client *client) struct i2c_adapter *adapter = client->adapter; int res = 0; + if (client->usage_count > 0) { + dev_warn(&client->dev, "Client [%s] still busy, " + "can't detach\n", client->name); + return -EBUSY; + } + if (adapter->client_unregister) { res = adapter->client_unregister(client); if (res) { @@ -812,10 +762,9 @@ int i2c_detach_client(struct i2c_client *client) mutex_lock(&adapter->clist_lock); list_del(&client->list); - mutex_unlock(&adapter->clist_lock); - init_completion(&client->released); device_unregister(&client->dev); + mutex_unlock(&adapter->clist_lock); wait_for_completion(&client->released); out: @@ -823,58 +772,72 @@ int i2c_detach_client(struct i2c_client *client) } EXPORT_SYMBOL(i2c_detach_client); -/** - * i2c_use_client - increments the reference count of the i2c client structure - * @client: the client being referenced - * - * Each live reference to a client should be refcounted. The driver model does - * that automatically as part of driver binding, so that most drivers don't - * need to do this explicitly: they hold a reference until they're unbound - * from the device. - * - * A pointer to the client with the incremented reference counter is returned. - */ -struct i2c_client *i2c_use_client(struct i2c_client *client) +static int i2c_inc_use_client(struct i2c_client *client) { - get_device(&client->dev); - return client; + + if (!try_module_get(client->driver->driver.owner)) + return -ENODEV; + if (!try_module_get(client->adapter->owner)) { + module_put(client->driver->driver.owner); + return -ENODEV; + } + + return 0; } -EXPORT_SYMBOL(i2c_use_client); -/** - * i2c_release_client - release a use of the i2c client structure - * @client: the client being no longer referenced - * - * Must be called when a user of a client is finished with it. - */ -void i2c_release_client(struct i2c_client *client) +static void i2c_dec_use_client(struct i2c_client *client) { - put_device(&client->dev); + module_put(client->driver->driver.owner); + module_put(client->adapter->owner); } -EXPORT_SYMBOL(i2c_release_client); -struct i2c_cmd_arg { - unsigned cmd; - void *arg; -}; +int i2c_use_client(struct i2c_client *client) +{ + int ret; -static int i2c_cmd(struct device *dev, void *_arg) + ret = i2c_inc_use_client(client); + if (ret) + return ret; + + client->usage_count++; + + return 0; +} +EXPORT_SYMBOL(i2c_use_client); + +int i2c_release_client(struct i2c_client *client) { - struct i2c_client *client = i2c_verify_client(dev); - struct i2c_cmd_arg *arg = _arg; + if (!client->usage_count) { + pr_debug("i2c-core: %s used one too many times\n", + __FUNCTION__); + return -EPERM; + } + + client->usage_count--; + i2c_dec_use_client(client); - if (client && client->driver && client->driver->command) - client->driver->command(client, arg->cmd, arg->arg); return 0; } +EXPORT_SYMBOL(i2c_release_client); void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg) { - struct i2c_cmd_arg cmd_arg; + struct list_head *item; + struct i2c_client *client; - cmd_arg.cmd = cmd; - cmd_arg.arg = arg; - device_for_each_child(&adap->dev, &cmd_arg, i2c_cmd); + mutex_lock(&adap->clist_lock); + list_for_each(item,&adap->clients) { + client = list_entry(item, struct i2c_client, list); + if (!try_module_get(client->driver->driver.owner)) + continue; + if (NULL != client->driver->command) { + mutex_unlock(&adap->clist_lock); + client->driver->command(client,cmd,arg); + mutex_lock(&adap->clist_lock); + } + module_put(client->driver->driver.owner); + } + mutex_unlock(&adap->clist_lock); } EXPORT_SYMBOL(i2c_clients_command); @@ -885,24 +848,11 @@ static int __init i2c_init(void) retval = bus_register(&i2c_bus_type); if (retval) return retval; - retval = class_register(&i2c_adapter_class); - if (retval) - goto bus_err; - retval = i2c_add_driver(&dummy_driver); - if (retval) - goto class_err; - return 0; - -class_err: - class_unregister(&i2c_adapter_class); -bus_err: - bus_unregister(&i2c_bus_type); - return retval; + return class_register(&i2c_adapter_class); } static void __exit i2c_exit(void) { - i2c_del_driver(&dummy_driver); class_unregister(&i2c_adapter_class); bus_unregister(&i2c_bus_type); } @@ -929,15 +879,7 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num) } #endif - if (in_atomic() || irqs_disabled()) { - ret = mutex_trylock(&adap->bus_lock); - if (!ret) - /* I2C activity is ongoing. */ - return -EAGAIN; - } else { - mutex_lock_nested(&adap->bus_lock, adap->level); - } - + mutex_lock_nested(&adap->bus_lock, adap->level); ret = adap->algo->master_xfer(adap,msgs,num); mutex_unlock(&adap->bus_lock); @@ -1036,7 +978,7 @@ static int i2c_probe_address(struct i2c_adapter *adapter, int addr, int kind, } int i2c_probe(struct i2c_adapter *adapter, - const struct i2c_client_address_data *address_data, + struct i2c_client_address_data *address_data, int (*found_proc) (struct i2c_adapter *, int, int)) { int i, err; @@ -1045,7 +987,7 @@ int i2c_probe(struct i2c_adapter *adapter, /* Force entries are done first, and are not affected by ignore entries */ if (address_data->forces) { - const unsigned short * const *forces = address_data->forces; + unsigned short **forces = address_data->forces; int kind; for (kind = 0; forces[kind]; kind++) { @@ -1143,6 +1085,7 @@ i2c_new_probed_device(struct i2c_adapter *adap, return NULL; } + mutex_lock(&adap->clist_lock); for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) { /* Check address validity */ if (addr_list[i] < 0x03 || addr_list[i] > 0x77) { @@ -1152,7 +1095,7 @@ i2c_new_probed_device(struct i2c_adapter *adap, } /* Check address availability */ - if (i2c_check_addr(adap, addr_list[i])) { + if (__i2c_check_addr(adap, addr_list[i])) { dev_dbg(&adap->dev, "Address 0x%02x already in " "use, not probing\n", addr_list[i]); continue; @@ -1180,6 +1123,7 @@ i2c_new_probed_device(struct i2c_adapter *adap, break; } } + mutex_unlock(&adap->clist_lock); if (addr_list[i] == I2C_CLIENT_END) { dev_dbg(&adap->dev, "Probing failed, no device found\n"); @@ -1195,12 +1139,12 @@ struct i2c_adapter* i2c_get_adapter(int id) { struct i2c_adapter *adapter; - mutex_lock(&core_lock); + mutex_lock(&core_lists); adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id); if (adapter && !try_module_get(adapter->owner)) adapter = NULL; - mutex_unlock(&core_lock); + mutex_unlock(&core_lists); return adapter; } EXPORT_SYMBOL(i2c_get_adapter); diff --git a/trunk/drivers/i2c/i2c-dev.c b/trunk/drivers/i2c/i2c-dev.c index 393e679d9faa..df540d5dfaf4 100644 --- a/trunk/drivers/i2c/i2c-dev.c +++ b/trunk/drivers/i2c/i2c-dev.c @@ -182,22 +182,27 @@ static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t c return ret; } -static int i2cdev_check(struct device *dev, void *addrp) -{ - struct i2c_client *client = i2c_verify_client(dev); - - if (!client || client->addr != *(unsigned int *)addrp) - return 0; - - return dev->driver ? -EBUSY : 0; -} - /* This address checking function differs from the one in i2c-core in that it considers an address with a registered device, but no - driver bound to it, as NOT busy. */ + bound driver, as NOT busy. */ static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr) { - return device_for_each_child(&adapter->dev, &addr, i2cdev_check); + struct list_head *item; + struct i2c_client *client; + int res = 0; + + mutex_lock(&adapter->clist_lock); + list_for_each(item, &adapter->clients) { + client = list_entry(item, struct i2c_client, list); + if (client->addr == addr) { + if (client->driver) + res = -EBUSY; + break; + } + } + mutex_unlock(&adapter->clist_lock); + + return res; } static int i2cdev_ioctl(struct inode *inode, struct file *file, diff --git a/trunk/drivers/macintosh/therm_windtunnel.c b/trunk/drivers/macintosh/therm_windtunnel.c index b66da74caa55..5452da1bb1a5 100644 --- a/trunk/drivers/macintosh/therm_windtunnel.c +++ b/trunk/drivers/macintosh/therm_windtunnel.c @@ -47,10 +47,12 @@ #define LOG_TEMP 0 /* continously log temperature */ +#define I2C_DRIVERID_G4FAN 0x9001 /* fixme */ + static int do_probe( struct i2c_adapter *adapter, int addr, int kind); /* scan 0x48-0x4f (DS1775) and 0x2c-2x2f (ADM1030) */ -static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, +static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END }; @@ -355,6 +357,7 @@ static struct i2c_driver g4fan_driver = { .driver = { .name = "therm_windtunnel", }, + .id = I2C_DRIVERID_G4FAN, .attach_adapter = do_attach, .detach_client = do_detach, }; diff --git a/trunk/drivers/media/video/dpc7146.c b/trunk/drivers/media/video/dpc7146.c index 566e479e2629..255dae303708 100644 --- a/trunk/drivers/media/video/dpc7146.c +++ b/trunk/drivers/media/video/dpc7146.c @@ -87,24 +87,11 @@ struct dpc int cur_input; /* current input */ }; -static int dpc_check_clients(struct device *dev, void *data) -{ - struct dpc* dpc = data; - struct i2c_client *client = i2c_verify_client(dev); - - if( !client ) - return 0; - - if( I2C_SAA7111A == client->addr ) - dpc->saa7111a = client; - - return 0; -} - /* fixme: add vbi stuff here */ static int dpc_probe(struct saa7146_dev* dev) { struct dpc* dpc = NULL; + struct i2c_client *client; dpc = kzalloc(sizeof(struct dpc), GFP_KERNEL); if( NULL == dpc ) { @@ -128,7 +115,9 @@ static int dpc_probe(struct saa7146_dev* dev) } /* loop through all i2c-devices on the bus and look who is there */ - device_for_each_child(&dpc->i2c_adapter.dev, dpc, dpc_check_clients); + list_for_each_entry(client, &dpc->i2c_adapter.clients, list) + if( I2C_SAA7111A == client->addr ) + dpc->saa7111a = client; /* check if all devices are present */ if( 0 == dpc->saa7111a ) { diff --git a/trunk/drivers/media/video/ks0127.c b/trunk/drivers/media/video/ks0127.c index 4895540be195..b6cd21e6dab9 100644 --- a/trunk/drivers/media/video/ks0127.c +++ b/trunk/drivers/media/video/ks0127.c @@ -764,6 +764,7 @@ static struct i2c_client ks0127_client_tmpl = .addr = 0, .adapter = NULL, .driver = &i2c_driver_ks0127, + .usage_count = 0 }; static int ks0127_found_proc(struct i2c_adapter *adapter, int addr, int kind) diff --git a/trunk/drivers/media/video/mxb.c b/trunk/drivers/media/video/mxb.c index add6d0d680be..98ad3092a079 100644 --- a/trunk/drivers/media/video/mxb.c +++ b/trunk/drivers/media/video/mxb.c @@ -149,33 +149,10 @@ struct mxb static struct saa7146_extension extension; -static int mxb_check_clients(struct device *dev, void *data) -{ - struct mxb* mxb = data; - struct i2c_client *client = i2c_verify_client(dev); - - if( !client ) - return 0; - - if( I2C_ADDR_TEA6420_1 == client->addr ) - mxb->tea6420_1 = client; - if( I2C_ADDR_TEA6420_2 == client->addr ) - mxb->tea6420_2 = client; - if( I2C_TEA6415C_2 == client->addr ) - mxb->tea6415c = client; - if( I2C_ADDR_TDA9840 == client->addr ) - mxb->tda9840 = client; - if( I2C_SAA7111 == client->addr ) - mxb->saa7111a = client; - if( 0x60 == client->addr ) - mxb->tuner = client; - - return 0; -} - static int mxb_probe(struct saa7146_dev* dev) { struct mxb* mxb = NULL; + struct i2c_client *client; int result; if ((result = request_module("saa7111")) < 0) { @@ -218,7 +195,20 @@ static int mxb_probe(struct saa7146_dev* dev) } /* loop through all i2c-devices on the bus and look who is there */ - device_for_each_child(&mxb->i2c_adapter.dev, mxb, mxb_check_clients); + list_for_each_entry(client, &mxb->i2c_adapter.clients, list) { + if( I2C_ADDR_TEA6420_1 == client->addr ) + mxb->tea6420_1 = client; + if( I2C_ADDR_TEA6420_2 == client->addr ) + mxb->tea6420_2 = client; + if( I2C_TEA6415C_2 == client->addr ) + mxb->tea6415c = client; + if( I2C_ADDR_TDA9840 == client->addr ) + mxb->tda9840 = client; + if( I2C_SAA7111 == client->addr ) + mxb->saa7111a = client; + if( 0x60 == client->addr ) + mxb->tuner = client; + } /* check if all devices are present */ if( 0 == mxb->tea6420_1 || 0 == mxb->tea6420_2 || 0 == mxb->tea6415c diff --git a/trunk/drivers/media/video/vino.c b/trunk/drivers/media/video/vino.c index 5bb75294b5aa..9a03dc82c6ca 100644 --- a/trunk/drivers/media/video/vino.c +++ b/trunk/drivers/media/video/vino.c @@ -2589,7 +2589,11 @@ static int vino_acquire_input(struct vino_channel_settings *vcs) /* First try D1 and then SAA7191 */ if (vino_drvdata->camera.driver && (vino_drvdata->camera.owner == VINO_NO_CHANNEL)) { - i2c_use_client(vino_drvdata->camera.driver); + if (i2c_use_client(vino_drvdata->camera.driver)) { + ret = -ENODEV; + goto out; + } + vino_drvdata->camera.owner = vcs->channel; vcs->input = VINO_INPUT_D1; vcs->data_norm = VINO_DATA_NORM_D1; @@ -2598,7 +2602,11 @@ static int vino_acquire_input(struct vino_channel_settings *vcs) int input, data_norm; int saa7191_input; - i2c_use_client(vino_drvdata->decoder.driver); + if (i2c_use_client(vino_drvdata->decoder.driver)) { + ret = -ENODEV; + goto out; + } + input = VINO_INPUT_COMPOSITE; saa7191_input = vino_get_saa7191_input(input); @@ -2680,7 +2688,10 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) } if (vino_drvdata->decoder.owner == VINO_NO_CHANNEL) { - i2c_use_client(vino_drvdata->decoder.driver); + if (i2c_use_client(vino_drvdata->decoder.driver)) { + ret = -ENODEV; + goto out; + } vino_drvdata->decoder.owner = vcs->channel; } @@ -2748,7 +2759,10 @@ static int vino_set_input(struct vino_channel_settings *vcs, int input) } if (vino_drvdata->camera.owner == VINO_NO_CHANNEL) { - i2c_use_client(vino_drvdata->camera.driver); + if (i2c_use_client(vino_drvdata->camera.driver)) { + ret = -ENODEV; + goto out; + } vino_drvdata->camera.owner = vcs->channel; } diff --git a/trunk/drivers/mmc/host/omap.c b/trunk/drivers/mmc/host/omap.c index c9dfeb15b487..971e18b91f4a 100644 --- a/trunk/drivers/mmc/host/omap.c +++ b/trunk/drivers/mmc/host/omap.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -36,6 +35,7 @@ #include #include #include +#include #define OMAP_MMC_REG_CMD 0x00 #define OMAP_MMC_REG_ARGL 0x04 diff --git a/trunk/drivers/rtc/rtc-ds1672.c b/trunk/drivers/rtc/rtc-ds1672.c index e0900ca678ec..dfef1637bfb8 100644 --- a/trunk/drivers/rtc/rtc-ds1672.c +++ b/trunk/drivers/rtc/rtc-ds1672.c @@ -16,7 +16,7 @@ #define DRV_VERSION "0.3" /* Addresses to scan: none. This chip cannot be detected. */ -static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { I2C_CLIENT_END }; /* Insmod parameters */ I2C_CLIENT_INSMOD; diff --git a/trunk/drivers/rtc/rtc-isl1208.c b/trunk/drivers/rtc/rtc-isl1208.c index 725b0c73c333..1c743641b73b 100644 --- a/trunk/drivers/rtc/rtc-isl1208.c +++ b/trunk/drivers/rtc/rtc-isl1208.c @@ -61,7 +61,7 @@ /* i2c configuration */ #define ISL1208_I2C_ADDR 0xde -static const unsigned short normal_i2c[] = { +static unsigned short normal_i2c[] = { ISL1208_I2C_ADDR>>1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; /* defines addr_data */ diff --git a/trunk/drivers/rtc/rtc-max6900.c b/trunk/drivers/rtc/rtc-max6900.c index 7683412970c4..a1cd448639c9 100644 --- a/trunk/drivers/rtc/rtc-max6900.c +++ b/trunk/drivers/rtc/rtc-max6900.c @@ -54,7 +54,7 @@ #define MAX6900_I2C_ADDR 0xa0 -static const unsigned short normal_i2c[] = { +static unsigned short normal_i2c[] = { MAX6900_I2C_ADDR >> 1, I2C_CLIENT_END }; diff --git a/trunk/drivers/rtc/rtc-pcf8563.c b/trunk/drivers/rtc/rtc-pcf8563.c index b3317fcc16c3..0242d803ebe5 100644 --- a/trunk/drivers/rtc/rtc-pcf8563.c +++ b/trunk/drivers/rtc/rtc-pcf8563.c @@ -25,7 +25,7 @@ * located at 0x51 will pass the validation routine due to * the way the registers are implemented. */ -static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { I2C_CLIENT_END }; /* Module parameters */ I2C_CLIENT_INSMOD; diff --git a/trunk/drivers/rtc/rtc-pcf8583.c b/trunk/drivers/rtc/rtc-pcf8583.c index c973ba94c422..556d0e7da35b 100644 --- a/trunk/drivers/rtc/rtc-pcf8583.c +++ b/trunk/drivers/rtc/rtc-pcf8583.c @@ -40,7 +40,7 @@ struct pcf8583 { #define CTRL_ALARM 0x02 #define CTRL_TIMER 0x01 -static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; /* Module parameters */ I2C_CLIENT_INSMOD; diff --git a/trunk/drivers/rtc/rtc-x1205.c b/trunk/drivers/rtc/rtc-x1205.c index b90fb1866ce9..b3fae357ca49 100644 --- a/trunk/drivers/rtc/rtc-x1205.c +++ b/trunk/drivers/rtc/rtc-x1205.c @@ -32,7 +32,7 @@ * unknown chips, the user must explicitly set the probe parameter. */ -static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { I2C_CLIENT_END }; /* Insmod parameters */ I2C_CLIENT_INSMOD; diff --git a/trunk/drivers/usb/host/ohci-omap.c b/trunk/drivers/usb/host/ohci-omap.c index 74e1f4be10bb..5cfa3d1c4413 100644 --- a/trunk/drivers/usb/host/ohci-omap.c +++ b/trunk/drivers/usb/host/ohci-omap.c @@ -47,7 +47,7 @@ #endif #ifdef CONFIG_TPS65010 -#include +#include #else #define LOW 0 diff --git a/trunk/drivers/usb/host/ohci-pnx4008.c b/trunk/drivers/usb/host/ohci-pnx4008.c index 6c52c66b659f..ca2a6abbc117 100644 --- a/trunk/drivers/usb/host/ohci-pnx4008.c +++ b/trunk/drivers/usb/host/ohci-pnx4008.c @@ -112,9 +112,9 @@ static int isp1301_detach(struct i2c_client *client); static int isp1301_command(struct i2c_client *client, unsigned int cmd, void *arg); -static const unsigned short normal_i2c[] = +static unsigned short normal_i2c[] = { ISP1301_I2C_ADDR, ISP1301_I2C_ADDR + 1, I2C_CLIENT_END }; -static const unsigned short dummy_i2c_addrlist[] = { I2C_CLIENT_END }; +static unsigned short dummy_i2c_addrlist[] = { I2C_CLIENT_END }; static struct i2c_client_address_data addr_data = { .normal_i2c = normal_i2c, @@ -123,6 +123,7 @@ static struct i2c_client_address_data addr_data = { }; struct i2c_driver isp1301_driver = { + .id = I2C_DRIVERID_I2CDEV, /* Fake Id */ .class = I2C_CLASS_HWMON, .attach_adapter = isp1301_probe, .detach_client = isp1301_detach, diff --git a/trunk/drivers/video/matrox/matroxfb_maven.c b/trunk/drivers/video/matrox/matroxfb_maven.c index 0cd58f84fb46..49cd53e46c0a 100644 --- a/trunk/drivers/video/matrox/matroxfb_maven.c +++ b/trunk/drivers/video/matrox/matroxfb_maven.c @@ -1232,7 +1232,7 @@ static int maven_shutdown_client(struct i2c_client* clnt) { return 0; } -static const unsigned short normal_i2c[] = { MAVEN_I2CID, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { MAVEN_I2CID, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; static struct i2c_driver maven_driver; diff --git a/trunk/drivers/video/omap/lcd_h3.c b/trunk/drivers/video/omap/lcd_h3.c index 31e978349a80..c604d935c188 100644 --- a/trunk/drivers/video/omap/lcd_h3.c +++ b/trunk/drivers/video/omap/lcd_h3.c @@ -21,9 +21,9 @@ #include #include -#include #include +#include #include #define MODULE_NAME "omapfb-lcd_h3" diff --git a/trunk/drivers/w1/masters/ds2482.c b/trunk/drivers/w1/masters/ds2482.c index 0fd5820d5c61..d93eb626b2f0 100644 --- a/trunk/drivers/w1/masters/ds2482.c +++ b/trunk/drivers/w1/masters/ds2482.c @@ -29,7 +29,7 @@ * However, the chip cannot be detected without doing an i2c write, * so use the force module parameter. */ -static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; +static unsigned short normal_i2c[] = {I2C_CLIENT_END}; /** * Insmod parameters diff --git a/trunk/include/asm-arm/arch-ixp4xx/platform.h b/trunk/include/asm-arm/arch-ixp4xx/platform.h index 2ce28e3fd325..2a44d3d67980 100644 --- a/trunk/include/asm-arm/arch-ixp4xx/platform.h +++ b/trunk/include/asm-arm/arch-ixp4xx/platform.h @@ -75,6 +75,17 @@ extern unsigned long ixp4xx_exp_bus_size; #define IXP4XX_PERIPHERAL_BUS_CLOCK (66) /* 66Mhzi APB BUS */ #define IXP4XX_UART_XTAL 14745600 +/* + * The IXP4xx chips do not have an I2C unit, so GPIO lines are just + * used to + * Used as platform_data to provide GPIO pin information to the ixp42x + * I2C driver. + */ +struct ixp4xx_i2c_pins { + unsigned long sda_pin; + unsigned long scl_pin; +}; + /* * This structure provide a means for the board setup code * to give information to th pata_ixp4xx driver. It is diff --git a/trunk/include/linux/i2c/tps65010.h b/trunk/include/asm-arm/arch-omap/tps65010.h similarity index 97% rename from trunk/include/linux/i2c/tps65010.h rename to trunk/include/asm-arm/arch-omap/tps65010.h index 7021635ed6a0..b9aa2b3a3909 100644 --- a/trunk/include/linux/i2c/tps65010.h +++ b/trunk/include/asm-arm/arch-omap/tps65010.h @@ -1,4 +1,4 @@ -/* linux/i2c/tps65010.h +/* linux/include/asm-arm/arch-omap/tps65010.h * * Functions to access TPS65010 power management device. * @@ -25,8 +25,8 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef __LINUX_I2C_TPS65010_H -#define __LINUX_I2C_TPS65010_H +#ifndef __ASM_ARCH_TPS65010_H +#define __ASM_ARCH_TPS65010_H /* * ---------------------------------------------------------------------------- @@ -152,5 +152,5 @@ extern int tps65010_config_vregs1(unsigned value); */ extern int tps65013_set_low_pwr(unsigned mode); -#endif /* __LINUX_I2C_TPS65010_H */ +#endif /* __ASM_ARCH_TPS65010_H */ diff --git a/trunk/include/asm-arm/arch-pxa/i2c.h b/trunk/include/asm-arm/arch-pxa/i2c.h index 80596b013443..e404b233d8a8 100644 --- a/trunk/include/asm-arm/arch-pxa/i2c.h +++ b/trunk/include/asm-arm/arch-pxa/i2c.h @@ -65,13 +65,7 @@ struct i2c_pxa_platform_data { unsigned int slave_addr; struct i2c_slave_client *slave; unsigned int class; - int use_pio; }; extern void pxa_set_i2c_info(struct i2c_pxa_platform_data *info); - -#ifdef CONFIG_PXA27x -extern void pxa_set_i2c_power_info(struct i2c_pxa_platform_data *info); -#endif - #endif diff --git a/trunk/include/linux/i2c-id.h b/trunk/include/linux/i2c-id.h index f922b060158b..c7a51a196f51 100644 --- a/trunk/include/linux/i2c-id.h +++ b/trunk/include/linux/i2c-id.h @@ -33,13 +33,23 @@ #define I2C_DRIVERID_MSP3400 1 #define I2C_DRIVERID_TUNER 2 +#define I2C_DRIVERID_VIDEOTEX 3 /* please rename */ #define I2C_DRIVERID_TDA8425 4 /* stereo sound processor */ #define I2C_DRIVERID_TEA6420 5 /* audio matrix switch */ #define I2C_DRIVERID_TEA6415C 6 /* video matrix switch */ #define I2C_DRIVERID_TDA9840 7 /* stereo sound processor */ #define I2C_DRIVERID_SAA7111A 8 /* video input processor */ +#define I2C_DRIVERID_SAA5281 9 /* videotext decoder */ +#define I2C_DRIVERID_SAA7112 10 /* video decoder, image scaler */ +#define I2C_DRIVERID_SAA7120 11 /* video encoder */ +#define I2C_DRIVERID_SAA7121 12 /* video encoder */ #define I2C_DRIVERID_SAA7185B 13 /* video encoder */ +#define I2C_DRIVERID_CH7003 14 /* digital pc to tv encoder */ +#define I2C_DRIVERID_PCF8574A 15 /* i2c expander - 8 bit in/out */ +#define I2C_DRIVERID_PCF8582C 16 /* eeprom */ +#define I2C_DRIVERID_AT24Cxx 17 /* eeprom 1/2/4/8/16 K */ #define I2C_DRIVERID_TEA6300 18 /* audio mixer */ +#define I2C_DRIVERID_BT829 19 /* pc to tv encoder */ #define I2C_DRIVERID_TDA9850 20 /* audio mixer */ #define I2C_DRIVERID_TDA9855 21 /* audio mixer */ #define I2C_DRIVERID_SAA7110 22 /* video decoder */ @@ -50,19 +60,42 @@ #define I2C_DRIVERID_TDA7432 27 /* Stereo sound processor */ #define I2C_DRIVERID_TVMIXER 28 /* Mixer driver for tv cards */ #define I2C_DRIVERID_TVAUDIO 29 /* Generic TV sound driver */ +#define I2C_DRIVERID_DPL3518 30 /* Dolby decoder chip */ #define I2C_DRIVERID_TDA9873 31 /* TV sound decoder chip */ #define I2C_DRIVERID_TDA9875 32 /* TV sound decoder chip */ #define I2C_DRIVERID_PIC16C54_PV9 33 /* Audio mux/ir receiver */ + +#define I2C_DRIVERID_SBATT 34 /* Smart Battery Device */ +#define I2C_DRIVERID_SBS 35 /* SB System Manager */ +#define I2C_DRIVERID_VES1893 36 /* VLSI DVB-S decoder */ +#define I2C_DRIVERID_VES1820 37 /* VLSI DVB-C decoder */ +#define I2C_DRIVERID_SAA7113 38 /* video decoder */ +#define I2C_DRIVERID_TDA8444 39 /* octuple 6-bit DAC */ #define I2C_DRIVERID_BT819 40 /* video decoder */ #define I2C_DRIVERID_BT856 41 /* video encoder */ #define I2C_DRIVERID_VPX3220 42 /* video decoder+vbi/vtxt */ +#define I2C_DRIVERID_DRP3510 43 /* ADR decoder (Astra Radio) */ +#define I2C_DRIVERID_SP5055 44 /* Satellite tuner */ +#define I2C_DRIVERID_STV0030 45 /* Multipurpose switch */ +#define I2C_DRIVERID_SAA7108 46 /* video decoder, image scaler */ +#define I2C_DRIVERID_DS1307 47 /* DS1307 real time clock */ #define I2C_DRIVERID_ADV7175 48 /* ADV 7175/7176 video encoder */ #define I2C_DRIVERID_SAA7114 49 /* video decoder */ +#define I2C_DRIVERID_ZR36120 50 /* Zoran 36120 video encoder */ +#define I2C_DRIVERID_24LC32A 51 /* Microchip 24LC32A 32k EEPROM */ +#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_MAX1617 56 /* temp sensor */ #define I2C_DRIVERID_SAA7191 57 /* video decoder */ #define I2C_DRIVERID_INDYCAM 58 /* SGI IndyCam */ +#define I2C_DRIVERID_BT832 59 /* CMOS camera video processor */ +#define I2C_DRIVERID_TDA9887 60 /* TDA988x IF-PLL demodulator */ #define I2C_DRIVERID_OVCAMCHIP 61 /* OmniVision CMOS image sens. */ +#define I2C_DRIVERID_TDA7313 62 /* TDA7313 audio processor */ #define I2C_DRIVERID_MAX6900 63 /* MAX6900 real-time clock */ +#define I2C_DRIVERID_SAA7114H 64 /* video decoder */ +#define I2C_DRIVERID_DS1374 65 /* DS1374 real time clock */ #define I2C_DRIVERID_TDA9874 66 /* TV sound decoder */ #define I2C_DRIVERID_SAA6752HS 67 /* MPEG2 encoder */ #define I2C_DRIVERID_TVEEPROM 68 /* TV EEPROM */ @@ -81,6 +114,7 @@ #define I2C_DRIVERID_DS1672 81 /* Dallas/Maxim DS1672 RTC */ #define I2C_DRIVERID_X1205 82 /* Xicor/Intersil X1205 RTC */ #define I2C_DRIVERID_PCF8563 83 /* Philips PCF8563 RTC */ +#define I2C_DRIVERID_RS5C372 84 /* Ricoh RS5C372 RTC */ #define I2C_DRIVERID_BT866 85 /* Conexant bt866 video encoder */ #define I2C_DRIVERID_KS0127 86 /* Samsung ks0127 video decoder */ #define I2C_DRIVERID_TLV320AIC23B 87 /* TI TLV320AIC23B audio codec */ @@ -95,6 +129,8 @@ #define I2C_DRIVERID_CS5345 96 /* cs5345 audio processor */ #define I2C_DRIVERID_I2CDEV 900 +#define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */ +#define I2C_DRIVERID_ALERT 903 /* SMBus Alert Responder Client */ /* IDs -- Use DRIVERIDs 1000-1999 for sensors. These were originally in sensors.h in the lm_sensors package */ @@ -140,16 +176,24 @@ /* --- Bit algorithm adapters */ #define I2C_HW_B_LP 0x010000 /* Parallel port Philips style */ +#define I2C_HW_B_SER 0x010002 /* Serial line interface */ #define I2C_HW_B_BT848 0x010005 /* BT848 video boards */ +#define I2C_HW_B_WNV 0x010006 /* Winnov Videums */ #define I2C_HW_B_VIA 0x010007 /* Via vt82c586b */ #define I2C_HW_B_HYDRA 0x010008 /* Apple Hydra Mac I/O */ #define I2C_HW_B_G400 0x010009 /* Matrox G400 */ #define I2C_HW_B_I810 0x01000a /* Intel I810 */ #define I2C_HW_B_VOO 0x01000b /* 3dfx Voodoo 3 / Banshee */ +#define I2C_HW_B_PPORT 0x01000c /* Primitive parallel port adapter */ +#define I2C_HW_B_SAVG 0x01000d /* Savage 4 */ #define I2C_HW_B_SCX200 0x01000e /* Nat'l Semi SCx200 I2C */ #define I2C_HW_B_RIVA 0x010010 /* Riva based graphics cards */ #define I2C_HW_B_IOC 0x010011 /* IOC bit-wiggling */ +#define I2C_HW_B_TSUNA 0x010012 /* DEC Tsunami chipset */ +#define I2C_HW_B_OMAHA 0x010014 /* Omaha I2C interface (ARM) */ +#define I2C_HW_B_GUIDE 0x010015 /* Guide bit-basher */ #define I2C_HW_B_IXP2000 0x010016 /* GPIO on IXP2000 systems */ +#define I2C_HW_B_IXP4XX 0x010017 /* GPIO on IXP4XX systems */ #define I2C_HW_B_S3VIA 0x010018 /* S3Via ProSavage adapter */ #define I2C_HW_B_ZR36067 0x010019 /* Zoran-36057/36067 based boards */ #define I2C_HW_B_PCILYNX 0x01001a /* TI PCILynx I2C adapter */ @@ -163,11 +207,22 @@ #define I2C_HW_B_CX23885 0x010022 /* conexant 23885 based tv cards (bus1) */ /* --- PCF 8584 based algorithms */ +#define I2C_HW_P_LP 0x020000 /* Parallel port interface */ +#define I2C_HW_P_ISA 0x020001 /* generic ISA Bus inteface card */ #define I2C_HW_P_ELEK 0x020002 /* Elektor ISA Bus inteface card */ /* --- PCA 9564 based algorithms */ #define I2C_HW_A_ISA 0x1a0000 /* generic ISA Bus interface card */ +/* --- ACPI Embedded controller algorithms */ +#define I2C_HW_ACPI_EC 0x1f0000 + +/* --- MPC824x PowerPC adapters */ +#define I2C_HW_MPC824X 0x100001 /* Motorola 8240 / 8245 */ + +/* --- MPC8xx PowerPC adapters */ +#define I2C_HW_MPC8XX_EPON 0x110000 /* Eponymous MPC8xx I2C adapter */ + /* --- PowerPC on-chip adapters */ #define I2C_HW_OCP 0x120000 /* IBM on-chip I2C adapter */ @@ -176,6 +231,7 @@ /* --- SGI adapters */ #define I2C_HW_SGI_VINO 0x160000 +#define I2C_HW_SGI_MACE 0x160001 /* --- XSCALE on-chip adapters */ #define I2C_HW_IOP3XX 0x140000 @@ -199,10 +255,17 @@ #define I2C_HW_SMBUS_W9968CF 0x04000d #define I2C_HW_SMBUS_OV511 0x04000e /* OV511(+) USB 1.1 webcam ICs */ #define I2C_HW_SMBUS_OV518 0x04000f /* OV518(+) USB 1.1 webcam ICs */ +#define I2C_HW_SMBUS_OV519 0x040010 /* OV519 USB 1.1 webcam IC */ #define I2C_HW_SMBUS_OVFX2 0x040011 /* Cypress/OmniVision FX2 webcam */ #define I2C_HW_SMBUS_CAFE 0x040012 /* Marvell 88ALP01 "CAFE" cam */ #define I2C_HW_SMBUS_ALI1563 0x040013 +/* --- ISA pseudo-adapter */ +#define I2C_HW_ISA 0x050000 + +/* --- IPMB adapter */ +#define I2C_HW_IPMB 0x0c0000 + /* --- MCP107 adapter */ #define I2C_HW_MPC107 0x0d0000 diff --git a/trunk/include/linux/i2c.h b/trunk/include/linux/i2c.h index 76014f8f3c60..a100c9f8eb7c 100644 --- a/trunk/include/linux/i2c.h +++ b/trunk/include/linux/i2c.h @@ -140,6 +140,7 @@ struct i2c_driver { int (*command)(struct i2c_client *client,unsigned int cmd, void *arg); struct device_driver driver; + struct list_head list; }; #define to_i2c_driver(d) container_of(d, struct i2c_driver, driver) @@ -154,11 +155,12 @@ struct i2c_driver { * generic enough to hide second-sourcing and compatible revisions. * @adapter: manages the bus segment hosting this I2C device * @driver: device's driver, hence pointer to access routines + * @usage_count: counts current number of users of this client * @dev: Driver model device node for the slave. * @irq: indicates the IRQ generated by this device (if any) * @driver_name: Identifies new-style driver used with this device; also * used as the module name for hotplug/coldplug modprobe support. - * @list: list of active/busy clients (DEPRECATED) + * @list: list of active/busy clients * @released: used to synchronize client releases & detaches and references * * An i2c_client identifies a single device (i.e. chip) connected to an @@ -173,16 +175,16 @@ struct i2c_client { char name[I2C_NAME_SIZE]; struct i2c_adapter *adapter; /* the adapter we sit on */ struct i2c_driver *driver; /* and our access routines */ + int usage_count; /* How many accesses currently */ + /* to the client */ struct device dev; /* the device structure */ int irq; /* irq issued by device (or -1) */ char driver_name[KOBJ_NAME_LEN]; - struct list_head list; /* DEPRECATED */ + struct list_head list; struct completion released; }; #define to_i2c_client(d) container_of(d, struct i2c_client, dev) -extern struct i2c_client *i2c_verify_client(struct device *dev); - static inline struct i2c_client *kobj_to_i2c_client(struct kobject *kobj) { struct device * const dev = container_of(kobj, struct device, kobj); @@ -259,12 +261,6 @@ i2c_new_probed_device(struct i2c_adapter *adap, struct i2c_board_info *info, unsigned short const *addr_list); -/* For devices that use several addresses, use i2c_new_dummy() to make - * client handles for the extra addresses. - */ -extern struct i2c_client * -i2c_new_dummy(struct i2c_adapter *adap, u16 address, const char *type); - extern void i2c_unregister_device(struct i2c_client *); /* Mainboard arch_initcall() code should register all its I2C devices. @@ -323,7 +319,8 @@ struct i2c_adapter { struct device dev; /* the adapter device */ int nr; - struct list_head clients; /* DEPRECATED */ + struct list_head clients; + struct list_head list; char name[48]; struct completion dev_released; }; @@ -360,10 +357,10 @@ static inline void i2c_set_adapdata (struct i2c_adapter *dev, void *data) * command line */ struct i2c_client_address_data { - const unsigned short *normal_i2c; - const unsigned short *probe; - const unsigned short *ignore; - const unsigned short * const *forces; + unsigned short *normal_i2c; + unsigned short *probe; + unsigned short *ignore; + unsigned short **forces; }; /* Internal numbers to terminate lists */ @@ -392,8 +389,11 @@ static inline int i2c_add_driver(struct i2c_driver *driver) extern int i2c_attach_client(struct i2c_client *); extern int i2c_detach_client(struct i2c_client *); -extern struct i2c_client *i2c_use_client(struct i2c_client *client); -extern void i2c_release_client(struct i2c_client *client); +/* Should be used to make sure that client-struct is valid and that it + is okay to access the i2c-client. + returns -ENODEV if client has gone in the meantime */ +extern int i2c_use_client(struct i2c_client *); +extern int i2c_release_client(struct i2c_client *); /* call the i2c_client->command() of all attached clients with * the given arguments */ @@ -405,7 +405,7 @@ extern void i2c_clients_command(struct i2c_adapter *adap, * specific address (unless a 'force' matched); */ extern int i2c_probe(struct i2c_adapter *adapter, - const struct i2c_client_address_data *address_data, + struct i2c_client_address_data *address_data, int (*found_proc) (struct i2c_adapter *, int, int)); extern struct i2c_adapter* i2c_get_adapter(int id); @@ -598,93 +598,104 @@ I2C_CLIENT_MODULE_PARM(probe, "List of adapter,address pairs to scan " \ "additionally"); \ I2C_CLIENT_MODULE_PARM(ignore, "List of adapter,address pairs not to " \ "scan"); \ -const static struct i2c_client_address_data addr_data = { \ +static struct i2c_client_address_data addr_data = { \ .normal_i2c = normal_i2c, \ .probe = probe, \ .ignore = ignore, \ .forces = forces, \ } -#define I2C_CLIENT_FORCE_TEXT \ - "List of adapter,address pairs to boldly assume to be present" - /* These are the ones you want to use in your own drivers. Pick the one which matches the number of devices the driver differenciates between. */ -#define I2C_CLIENT_INSMOD \ -I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \ -static const unsigned short * const forces[] = { force, NULL }; \ +#define I2C_CLIENT_INSMOD \ + I2C_CLIENT_MODULE_PARM(force, \ + "List of adapter,address pairs to boldly assume " \ + "to be present"); \ + static unsigned short *forces[] = { \ + force, \ + NULL \ + }; \ I2C_CLIENT_INSMOD_COMMON #define I2C_CLIENT_INSMOD_1(chip1) \ enum chips { any_chip, chip1 }; \ -I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \ +I2C_CLIENT_MODULE_PARM(force, "List of adapter,address pairs to " \ + "boldly assume to be present"); \ I2C_CLIENT_MODULE_PARM_FORCE(chip1); \ -static const unsigned short * const forces[] = { force, \ - force_##chip1, NULL }; \ +static unsigned short *forces[] = { force, force_##chip1, NULL }; \ I2C_CLIENT_INSMOD_COMMON #define I2C_CLIENT_INSMOD_2(chip1, chip2) \ enum chips { any_chip, chip1, chip2 }; \ -I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \ +I2C_CLIENT_MODULE_PARM(force, "List of adapter,address pairs to " \ + "boldly assume to be present"); \ I2C_CLIENT_MODULE_PARM_FORCE(chip1); \ I2C_CLIENT_MODULE_PARM_FORCE(chip2); \ -static const unsigned short * const forces[] = { force, \ - force_##chip1, force_##chip2, NULL }; \ +static unsigned short *forces[] = { force, force_##chip1, \ + force_##chip2, NULL }; \ I2C_CLIENT_INSMOD_COMMON #define I2C_CLIENT_INSMOD_3(chip1, chip2, chip3) \ enum chips { any_chip, chip1, chip2, chip3 }; \ -I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \ +I2C_CLIENT_MODULE_PARM(force, "List of adapter,address pairs to " \ + "boldly assume to be present"); \ I2C_CLIENT_MODULE_PARM_FORCE(chip1); \ I2C_CLIENT_MODULE_PARM_FORCE(chip2); \ I2C_CLIENT_MODULE_PARM_FORCE(chip3); \ -static const unsigned short * const forces[] = { force, \ - force_##chip1, force_##chip2, force_##chip3, NULL }; \ +static unsigned short *forces[] = { force, force_##chip1, \ + force_##chip2, force_##chip3, \ + NULL }; \ I2C_CLIENT_INSMOD_COMMON #define I2C_CLIENT_INSMOD_4(chip1, chip2, chip3, chip4) \ enum chips { any_chip, chip1, chip2, chip3, chip4 }; \ -I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \ +I2C_CLIENT_MODULE_PARM(force, "List of adapter,address pairs to " \ + "boldly assume to be present"); \ I2C_CLIENT_MODULE_PARM_FORCE(chip1); \ I2C_CLIENT_MODULE_PARM_FORCE(chip2); \ I2C_CLIENT_MODULE_PARM_FORCE(chip3); \ I2C_CLIENT_MODULE_PARM_FORCE(chip4); \ -static const unsigned short * const forces[] = { force, \ - force_##chip1, force_##chip2, force_##chip3, \ - force_##chip4, NULL}; \ +static unsigned short *forces[] = { force, force_##chip1, \ + force_##chip2, force_##chip3, \ + force_##chip4, NULL}; \ I2C_CLIENT_INSMOD_COMMON #define I2C_CLIENT_INSMOD_5(chip1, chip2, chip3, chip4, chip5) \ enum chips { any_chip, chip1, chip2, chip3, chip4, chip5 }; \ -I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \ +I2C_CLIENT_MODULE_PARM(force, "List of adapter,address pairs to " \ + "boldly assume to be present"); \ I2C_CLIENT_MODULE_PARM_FORCE(chip1); \ I2C_CLIENT_MODULE_PARM_FORCE(chip2); \ I2C_CLIENT_MODULE_PARM_FORCE(chip3); \ I2C_CLIENT_MODULE_PARM_FORCE(chip4); \ I2C_CLIENT_MODULE_PARM_FORCE(chip5); \ -static const unsigned short * const forces[] = { force, \ - force_##chip1, force_##chip2, force_##chip3, \ - force_##chip4, force_##chip5, NULL }; \ +static unsigned short *forces[] = { force, force_##chip1, \ + force_##chip2, force_##chip3, \ + force_##chip4, force_##chip5, \ + NULL }; \ I2C_CLIENT_INSMOD_COMMON #define I2C_CLIENT_INSMOD_6(chip1, chip2, chip3, chip4, chip5, chip6) \ enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6 }; \ -I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \ +I2C_CLIENT_MODULE_PARM(force, "List of adapter,address pairs to " \ + "boldly assume to be present"); \ I2C_CLIENT_MODULE_PARM_FORCE(chip1); \ I2C_CLIENT_MODULE_PARM_FORCE(chip2); \ I2C_CLIENT_MODULE_PARM_FORCE(chip3); \ I2C_CLIENT_MODULE_PARM_FORCE(chip4); \ I2C_CLIENT_MODULE_PARM_FORCE(chip5); \ I2C_CLIENT_MODULE_PARM_FORCE(chip6); \ -static const unsigned short * const forces[] = { force, \ - force_##chip1, force_##chip2, force_##chip3, \ - force_##chip4, force_##chip5, force_##chip6, NULL }; \ +static unsigned short *forces[] = { force, force_##chip1, \ + force_##chip2, force_##chip3, \ + force_##chip4, force_##chip5, \ + force_##chip6, NULL }; \ I2C_CLIENT_INSMOD_COMMON #define I2C_CLIENT_INSMOD_7(chip1, chip2, chip3, chip4, chip5, chip6, chip7) \ enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, \ chip7 }; \ -I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \ +I2C_CLIENT_MODULE_PARM(force, "List of adapter,address pairs to " \ + "boldly assume to be present"); \ I2C_CLIENT_MODULE_PARM_FORCE(chip1); \ I2C_CLIENT_MODULE_PARM_FORCE(chip2); \ I2C_CLIENT_MODULE_PARM_FORCE(chip3); \ @@ -692,16 +703,18 @@ I2C_CLIENT_MODULE_PARM_FORCE(chip4); \ I2C_CLIENT_MODULE_PARM_FORCE(chip5); \ I2C_CLIENT_MODULE_PARM_FORCE(chip6); \ I2C_CLIENT_MODULE_PARM_FORCE(chip7); \ -static const unsigned short * const forces[] = { force, \ - force_##chip1, force_##chip2, force_##chip3, \ - force_##chip4, force_##chip5, force_##chip6, \ - force_##chip7, NULL }; \ +static unsigned short *forces[] = { force, force_##chip1, \ + force_##chip2, force_##chip3, \ + force_##chip4, force_##chip5, \ + force_##chip6, force_##chip7, \ + NULL }; \ I2C_CLIENT_INSMOD_COMMON #define I2C_CLIENT_INSMOD_8(chip1, chip2, chip3, chip4, chip5, chip6, chip7, chip8) \ enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, \ chip7, chip8 }; \ -I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \ +I2C_CLIENT_MODULE_PARM(force, "List of adapter,address pairs to " \ + "boldly assume to be present"); \ I2C_CLIENT_MODULE_PARM_FORCE(chip1); \ I2C_CLIENT_MODULE_PARM_FORCE(chip2); \ I2C_CLIENT_MODULE_PARM_FORCE(chip3); \ @@ -710,10 +723,11 @@ I2C_CLIENT_MODULE_PARM_FORCE(chip5); \ I2C_CLIENT_MODULE_PARM_FORCE(chip6); \ I2C_CLIENT_MODULE_PARM_FORCE(chip7); \ I2C_CLIENT_MODULE_PARM_FORCE(chip8); \ -static const unsigned short * const forces[] = { force, \ - force_##chip1, force_##chip2, force_##chip3, \ - force_##chip4, force_##chip5, force_##chip6, \ - force_##chip7, force_##chip8, NULL }; \ +static unsigned short *forces[] = { force, force_##chip1, \ + force_##chip2, force_##chip3, \ + force_##chip4, force_##chip5, \ + force_##chip6, force_##chip7, \ + force_##chip8, NULL }; \ I2C_CLIENT_INSMOD_COMMON #endif /* __KERNEL__ */ #endif /* _LINUX_I2C_H */ diff --git a/trunk/include/linux/m41t00.h b/trunk/include/linux/m41t00.h new file mode 100644 index 000000000000..b423360ca38e --- /dev/null +++ b/trunk/include/linux/m41t00.h @@ -0,0 +1,50 @@ +/* + * Definitions for the ST M41T00 family of i2c rtc chips. + * + * Author: Mark A. Greer + * + * 2005, 2006 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#ifndef _M41T00_H +#define _M41T00_H + +#define M41T00_DRV_NAME "m41t00" +#define M41T00_I2C_ADDR 0x68 + +#define M41T00_TYPE_M41T00 0 +#define M41T00_TYPE_M41T81 81 +#define M41T00_TYPE_M41T85 85 + +struct m41t00_platform_data { + u8 type; + u8 i2c_addr; + u8 sqw_freq; +}; + +/* SQW output disabled, this is default value by power on */ +#define M41T00_SQW_DISABLE (0) + +#define M41T00_SQW_32KHZ (1<<4) /* 32.768 KHz */ +#define M41T00_SQW_8KHZ (2<<4) /* 8.192 KHz */ +#define M41T00_SQW_4KHZ (3<<4) /* 4.096 KHz */ +#define M41T00_SQW_2KHZ (4<<4) /* 2.048 KHz */ +#define M41T00_SQW_1KHZ (5<<4) /* 1.024 KHz */ +#define M41T00_SQW_512HZ (6<<4) /* 512 Hz */ +#define M41T00_SQW_256HZ (7<<4) /* 256 Hz */ +#define M41T00_SQW_128HZ (8<<4) /* 128 Hz */ +#define M41T00_SQW_64HZ (9<<4) /* 64 Hz */ +#define M41T00_SQW_32HZ (10<<4) /* 32 Hz */ +#define M41T00_SQW_16HZ (11<<4) /* 16 Hz */ +#define M41T00_SQW_8HZ (12<<4) /* 8 Hz */ +#define M41T00_SQW_4HZ (13<<4) /* 4 Hz */ +#define M41T00_SQW_2HZ (14<<4) /* 2 Hz */ +#define M41T00_SQW_1HZ (15<<4) /* 1 Hz */ + +extern ulong m41t00_get_rtc_time(void); +extern int m41t00_set_rtc_time(ulong nowtime); + +#endif /* _M41T00_H */ diff --git a/trunk/include/media/v4l2-i2c-drv-legacy.h b/trunk/include/media/v4l2-i2c-drv-legacy.h index e7645578fc22..241854229d6f 100644 --- a/trunk/include/media/v4l2-i2c-drv-legacy.h +++ b/trunk/include/media/v4l2-i2c-drv-legacy.h @@ -34,7 +34,7 @@ struct v4l2_i2c_driver_data { }; static struct v4l2_i2c_driver_data v4l2_i2c_data; -static const struct i2c_client_address_data addr_data; +static struct i2c_client_address_data addr_data; static struct i2c_driver v4l2_i2c_driver_legacy; static char v4l2_i2c_drv_name_legacy[32]; diff --git a/trunk/sound/ppc/keywest.c b/trunk/sound/ppc/keywest.c index bb7d744faff5..272ae38e9b18 100644 --- a/trunk/sound/ppc/keywest.c +++ b/trunk/sound/ppc/keywest.c @@ -34,6 +34,8 @@ static struct pmac_keywest *keywest_ctx; +#define I2C_DRIVERID_KEYWEST 0xFEBA + static int keywest_attach_adapter(struct i2c_adapter *adapter); static int keywest_detach_client(struct i2c_client *client); @@ -41,6 +43,7 @@ struct i2c_driver keywest_driver = { .driver = { .name = "PMac Keywest Audio", }, + .id = I2C_DRIVERID_KEYWEST, .attach_adapter = &keywest_attach_adapter, .detach_client = &keywest_detach_client, }; diff --git a/trunk/sound/soc/codecs/cs4270.c b/trunk/sound/soc/codecs/cs4270.c index dab22cc97ead..abac62866da8 100644 --- a/trunk/sound/soc/codecs/cs4270.c +++ b/trunk/sound/soc/codecs/cs4270.c @@ -234,7 +234,7 @@ static int cs4270_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, * lower three bits are determined via the AD2, AD1, and AD0 pins * (respectively). */ -static const unsigned short normal_i2c[] = { +static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/trunk/sound/soc/s3c24xx/neo1973_wm8753.c b/trunk/sound/soc/s3c24xx/neo1973_wm8753.c index f1f6b9478af9..d5a8fc2cf8d6 100644 --- a/trunk/sound/soc/s3c24xx/neo1973_wm8753.c +++ b/trunk/sound/soc/s3c24xx/neo1973_wm8753.c @@ -573,7 +573,7 @@ static struct snd_soc_device neo1973_snd_devdata = { static struct i2c_client client_template; -static const unsigned short normal_i2c[] = { 0x7C, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x7C, I2C_CLIENT_END }; /* Magic definition of all other variables and things */ I2C_CLIENT_INSMOD;