From a5f08a327abc45eb6cb3cc1f5fabf38607ae2acc Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 14 Oct 2008 17:30:02 +0200 Subject: i2c/isp1301_omap: Convert to a new-style i2c driver, part 1 Based on David Brownell's patch for tps65010, this patch starts converting isp1301_omap.c to new-style i2c driver. Signed-off-by: Felipe Balbi Signed-off-by: Jean Delvare Acked-by: Tony Lindgren --- drivers/i2c/chips/isp1301_omap.c | 59 ++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c index 4655b794ebe..8444fc6fbf6 100644 --- a/drivers/i2c/chips/isp1301_omap.c +++ b/drivers/i2c/chips/isp1301_omap.c @@ -49,7 +49,8 @@ MODULE_LICENSE("GPL"); struct isp1301 { struct otg_transceiver otg; - struct i2c_client client; + struct i2c_client *client; + struct i2c_client c; void (*i2c_release)(struct device *dev); int irq; @@ -153,25 +154,25 @@ static struct i2c_driver isp1301_driver; static inline u8 isp1301_get_u8(struct isp1301 *isp, u8 reg) { - return i2c_smbus_read_byte_data(&isp->client, reg + 0); + return i2c_smbus_read_byte_data(isp->client, reg + 0); } static inline int isp1301_get_u16(struct isp1301 *isp, u8 reg) { - return i2c_smbus_read_word_data(&isp->client, reg); + return i2c_smbus_read_word_data(isp->client, reg); } static inline int isp1301_set_bits(struct isp1301 *isp, u8 reg, u8 bits) { - return i2c_smbus_write_byte_data(&isp->client, reg + 0, bits); + return i2c_smbus_write_byte_data(isp->client, reg + 0, bits); } static inline int isp1301_clear_bits(struct isp1301 *isp, u8 reg, u8 bits) { - return i2c_smbus_write_byte_data(&isp->client, reg + 1, bits); + return i2c_smbus_write_byte_data(isp->client, reg + 1, bits); } /*-------------------------------------------------------------------------*/ @@ -349,10 +350,10 @@ isp1301_defer_work(struct isp1301 *isp, int work) int status; if (isp && !test_and_set_bit(work, &isp->todo)) { - (void) get_device(&isp->client.dev); + (void) get_device(&isp->client->dev); status = schedule_work(&isp->work); if (!status && !isp->working) - dev_vdbg(&isp->client.dev, + dev_vdbg(&isp->client->dev, "work item %d may be lost\n", work); } } @@ -1135,7 +1136,7 @@ isp1301_work(struct work_struct *work) /* transfer state from otg engine to isp1301 */ if (test_and_clear_bit(WORK_UPDATE_ISP, &isp->todo)) { otg_update_isp(isp); - put_device(&isp->client.dev); + put_device(&isp->client->dev); } #endif /* transfer state from isp1301 to otg engine */ @@ -1143,7 +1144,7 @@ isp1301_work(struct work_struct *work) u8 stat = isp1301_clear_latch(isp); isp_update_otg(isp, stat); - put_device(&isp->client.dev); + put_device(&isp->client->dev); } if (test_and_clear_bit(WORK_HOST_RESUME, &isp->todo)) { @@ -1178,7 +1179,7 @@ isp1301_work(struct work_struct *work) } host_resume(isp); // mdelay(10); - put_device(&isp->client.dev); + put_device(&isp->client->dev); } if (test_and_clear_bit(WORK_TIMER, &isp->todo)) { @@ -1187,15 +1188,15 @@ isp1301_work(struct work_struct *work) if (!stop) mod_timer(&isp->timer, jiffies + TIMER_JIFFIES); #endif - put_device(&isp->client.dev); + put_device(&isp->client->dev); } if (isp->todo) - dev_vdbg(&isp->client.dev, + dev_vdbg(&isp->client->dev, "work done, todo = 0x%lx\n", isp->todo); if (stop) { - dev_dbg(&isp->client.dev, "stop\n"); + dev_dbg(&isp->client->dev, "stop\n"); break; } } while (isp->todo); @@ -1219,7 +1220,7 @@ static void isp1301_release(struct device *dev) { struct isp1301 *isp; - isp = container_of(dev, struct isp1301, client.dev); + isp = dev_get_drvdata(dev); /* ugly -- i2c hijacks our memory hook to wait_for_completion() */ if (isp->i2c_release) @@ -1233,7 +1234,7 @@ static int isp1301_detach_client(struct i2c_client *i2c) { struct isp1301 *isp; - isp = container_of(i2c, struct isp1301, client); + isp = i2c_get_clientdata(i2c); isp1301_clear_bits(isp, ISP1301_INTERRUPT_FALLING, ~0); isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0); @@ -1285,7 +1286,7 @@ static int isp1301_otg_enable(struct isp1301 *isp) isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING, INTR_VBUS_VLD | INTR_SESS_VLD | INTR_ID_GND); - dev_info(&isp->client.dev, "ready for dual-role USB ...\n"); + dev_info(&isp->client->dev, "ready for dual-role USB ...\n"); return 0; } @@ -1310,7 +1311,7 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host) #ifdef CONFIG_USB_OTG isp->otg.host = host; - dev_dbg(&isp->client.dev, "registered host\n"); + dev_dbg(&isp->client->dev, "registered host\n"); host_suspend(isp); if (isp->otg.gadget) return isp1301_otg_enable(isp); @@ -1325,7 +1326,7 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host) if (machine_is_omap_h2()) isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0); - dev_info(&isp->client.dev, "A-Host sessions ok\n"); + dev_info(&isp->client->dev, "A-Host sessions ok\n"); isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING, INTR_ID_GND); isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING, @@ -1343,7 +1344,7 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host) return 0; #else - dev_dbg(&isp->client.dev, "host sessions not allowed\n"); + dev_dbg(&isp->client->dev, "host sessions not allowed\n"); return -EINVAL; #endif @@ -1370,7 +1371,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget) #ifdef CONFIG_USB_OTG isp->otg.gadget = gadget; - dev_dbg(&isp->client.dev, "registered gadget\n"); + dev_dbg(&isp->client->dev, "registered gadget\n"); /* gadget driver may be suspended until vbus_connect () */ if (isp->otg.host) return isp1301_otg_enable(isp); @@ -1395,7 +1396,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget) INTR_SESS_VLD); isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING, INTR_VBUS_VLD); - dev_info(&isp->client.dev, "B-Peripheral sessions ok\n"); + dev_info(&isp->client->dev, "B-Peripheral sessions ok\n"); dump_regs(isp, __func__); /* If this has a Mini-AB connector, this mode is highly @@ -1408,7 +1409,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget) return 0; #else - dev_dbg(&isp->client.dev, "peripheral sessions not allowed\n"); + dev_dbg(&isp->client->dev, "peripheral sessions not allowed\n"); return -EINVAL; #endif } @@ -1528,12 +1529,12 @@ static int isp1301_probe(struct i2c_adapter *bus, int address, int kind) isp->timer.data = (unsigned long) isp; isp->irq = -1; - isp->client.addr = address; - i2c_set_clientdata(&isp->client, isp); - isp->client.adapter = bus; - isp->client.driver = &isp1301_driver; - strlcpy(isp->client.name, DRIVER_NAME, I2C_NAME_SIZE); - i2c = &isp->client; + isp->c.addr = address; + i2c_set_clientdata(&isp->c, isp); + isp->c.adapter = bus; + isp->c.driver = &isp1301_driver; + strlcpy(isp->c.name, DRIVER_NAME, I2C_NAME_SIZE); + isp->client = i2c = &isp->c; /* if this is a true probe, verify the chip ... */ if (kind < 0) { @@ -1618,7 +1619,7 @@ fail2: goto fail1; } - isp->otg.dev = &isp->client.dev; + isp->otg.dev = &isp->client->dev; isp->otg.label = DRIVER_NAME; isp->otg.set_host = isp1301_set_host, -- cgit v1.2.3 From 9df013b3e46c67dd3745df91eaccdc719118e0cc Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 14 Oct 2008 17:30:02 +0200 Subject: i2c/isp1301_omap: Convert to a new-style i2c driver, part 2 Based on David Brownell's patch for tps65010 and previous work by Felipe Balbi, this patch finishes converting isp1301_omap to a new-style i2c driver. There's definitely room for further drivers cleanups, but these are out of the scope of this patch. Signed-off-by: Jean Delvare Acked-by: Tony Lindgren --- arch/arm/mach-omap1/board-h3.c | 4 ++ arch/arm/mach-omap2/board-h4.c | 11 +++++ drivers/i2c/chips/isp1301_omap.c | 98 ++++++++++++++-------------------------- 3 files changed, 48 insertions(+), 65 deletions(-) diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index 2ced6d9984d..adfcd7b5139 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c @@ -476,6 +476,10 @@ static struct i2c_board_info __initdata h3_i2c_board_info[] = { I2C_BOARD_INFO("tps65013", 0x48), /* .irq = OMAP_GPIO_IRQ(??), */ }, + { + I2C_BOARD_INFO("isp1301_omap", 0x2d), + .irq = OMAP_GPIO_IRQ(14), + }, }; static struct omap_gpio_switch h3_gpio_switches[] __initdata = { diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c index d4e3b6fc470..2fef2c84508 100644 --- a/arch/arm/mach-omap2/board-h4.c +++ b/arch/arm/mach-omap2/board-h4.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -391,6 +392,13 @@ static struct omap_board_config_kernel h4_config[] = { { OMAP_TAG_LCD, &h4_lcd_config }, }; +static struct i2c_board_info __initdata h4_i2c_board_info[] = { + { + I2C_BOARD_INFO("isp1301_omap", 0x2d), + .irq = OMAP_GPIO_IRQ(125), + }, +}; + static void __init omap_h4_init(void) { /* @@ -411,6 +419,9 @@ static void __init omap_h4_init(void) } #endif + i2c_register_board_info(1, h4_i2c_board_info, + ARRAY_SIZE(h4_i2c_board_info)); + platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices)); omap_board_config = h4_config; omap_board_config_size = ARRAY_SIZE(h4_config); diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c index 8444fc6fbf6..28902ebd553 100644 --- a/drivers/i2c/chips/isp1301_omap.c +++ b/drivers/i2c/chips/isp1301_omap.c @@ -50,10 +50,8 @@ MODULE_LICENSE("GPL"); struct isp1301 { struct otg_transceiver otg; struct i2c_client *client; - struct i2c_client c; void (*i2c_release)(struct device *dev); - int irq; int irq_type; u32 last_otg_ctrl; @@ -139,14 +137,6 @@ static inline void notresponding(struct isp1301 *isp) /*-------------------------------------------------------------------------*/ -/* only two addresses possible */ -#define ISP_BASE 0x2c -static unsigned short normal_i2c[] = { - ISP_BASE, ISP_BASE + 1, - I2C_CLIENT_END }; - -I2C_CLIENT_INSMOD; - static struct i2c_driver isp1301_driver; /* smbus apis are used for portability */ @@ -1230,7 +1220,7 @@ static void isp1301_release(struct device *dev) static struct isp1301 *the_transceiver; -static int isp1301_detach_client(struct i2c_client *i2c) +static int __exit isp1301_remove(struct i2c_client *i2c) { struct isp1301 *isp; @@ -1238,7 +1228,7 @@ static int isp1301_detach_client(struct i2c_client *i2c) isp1301_clear_bits(isp, ISP1301_INTERRUPT_FALLING, ~0); isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0); - free_irq(isp->irq, isp); + free_irq(i2c->irq, isp); #ifdef CONFIG_USB_OTG otg_unbind(isp); #endif @@ -1253,7 +1243,7 @@ static int isp1301_detach_client(struct i2c_client *i2c) put_device(&i2c->dev); the_transceiver = 0; - return i2c_detach_client(i2c); + return 0; } /*-------------------------------------------------------------------------*/ @@ -1509,12 +1499,10 @@ isp1301_start_hnp(struct otg_transceiver *dev) /*-------------------------------------------------------------------------*/ -/* no error returns, they'd just make bus scanning stop */ -static int isp1301_probe(struct i2c_adapter *bus, int address, int kind) +static int __init isp1301_probe(struct i2c_client *i2c) { int status; struct isp1301 *isp; - struct i2c_client *i2c; if (the_transceiver) return 0; @@ -1528,37 +1516,19 @@ static int isp1301_probe(struct i2c_adapter *bus, int address, int kind) isp->timer.function = isp1301_timer; isp->timer.data = (unsigned long) isp; - isp->irq = -1; - isp->c.addr = address; - i2c_set_clientdata(&isp->c, isp); - isp->c.adapter = bus; - isp->c.driver = &isp1301_driver; - strlcpy(isp->c.name, DRIVER_NAME, I2C_NAME_SIZE); - isp->client = i2c = &isp->c; - - /* if this is a true probe, verify the chip ... */ - if (kind < 0) { - status = isp1301_get_u16(isp, ISP1301_VENDOR_ID); - if (status != I2C_VENDOR_ID_PHILIPS) { - dev_dbg(&bus->dev, "addr %d not philips id: %d\n", - address, status); - goto fail1; - } - status = isp1301_get_u16(isp, ISP1301_PRODUCT_ID); - if (status != I2C_PRODUCT_ID_PHILIPS_1301) { - dev_dbg(&bus->dev, "%d not isp1301, %d\n", - address, status); - goto fail1; - } - } + i2c_set_clientdata(i2c, isp); + isp->client = i2c; - status = i2c_attach_client(i2c); - if (status < 0) { - dev_dbg(&bus->dev, "can't attach %s to device %d, err %d\n", - DRIVER_NAME, address, status); -fail1: - kfree(isp); - return 0; + /* verify the chip (shouldn't be necesary) */ + status = isp1301_get_u16(isp, ISP1301_VENDOR_ID); + if (status != I2C_VENDOR_ID_PHILIPS) { + dev_dbg(&i2c->dev, "not philips id: %d\n", status); + goto fail; + } + status = isp1301_get_u16(isp, ISP1301_PRODUCT_ID); + if (status != I2C_PRODUCT_ID_PHILIPS_1301) { + dev_dbg(&i2c->dev, "not isp1301, %d\n", status); + goto fail; } isp->i2c_release = i2c->dev.release; i2c->dev.release = isp1301_release; @@ -1587,7 +1557,7 @@ fail1: status = otg_bind(isp); if (status < 0) { dev_dbg(&i2c->dev, "can't bind OTG\n"); - goto fail2; + goto fail; } #endif @@ -1600,26 +1570,21 @@ fail1: /* IRQ wired at M14 */ omap_cfg_reg(M14_1510_GPIO2); - isp->irq = OMAP_GPIO_IRQ(2); if (gpio_request(2, "isp1301") == 0) gpio_direction_input(2); isp->irq_type = IRQF_TRIGGER_FALLING; } isp->irq_type |= IRQF_SAMPLE_RANDOM; - status = request_irq(isp->irq, isp1301_irq, + status = request_irq(i2c->irq, isp1301_irq, isp->irq_type, DRIVER_NAME, isp); if (status < 0) { dev_dbg(&i2c->dev, "can't get IRQ %d, err %d\n", - isp->irq, status); -#ifdef CONFIG_USB_OTG -fail2: -#endif - i2c_detach_client(i2c); - goto fail1; + i2c->irq, status); + goto fail; } - isp->otg.dev = &isp->client->dev; + isp->otg.dev = &i2c->dev; isp->otg.label = DRIVER_NAME; isp->otg.set_host = isp1301_set_host, @@ -1650,22 +1615,25 @@ fail2: status); return 0; -} -static int isp1301_scan_bus(struct i2c_adapter *bus) -{ - if (!i2c_check_functionality(bus, I2C_FUNC_SMBUS_BYTE_DATA - | I2C_FUNC_SMBUS_READ_WORD_DATA)) - return -EINVAL; - return i2c_probe(bus, &addr_data, isp1301_probe); +fail: + kfree(isp); + return -ENODEV; } +static const struct i2c_device_id isp1301_id[] = { + { "isp1301_omap", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, isp1301_id); + static struct i2c_driver isp1301_driver = { .driver = { .name = "isp1301_omap", }, - .attach_adapter = isp1301_scan_bus, - .detach_client = isp1301_detach_client, + .probe = isp1301_probe, + .remove = __exit_p(isp1301_remove), + .id_table = isp1301_id, }; /*-------------------------------------------------------------------------*/ -- cgit v1.2.3 From ce5640330b10c6cecfbda50569b9f53c081d10c6 Mon Sep 17 00:00:00 2001 From: Rene Herman Date: Tue, 14 Oct 2008 17:30:03 +0200 Subject: i2c-pca-isa: Don't grab arbitrary resources Grabbing ISA bus resources without anything or anyone telling us we should can break boot on randconfig/allyesconfig builds by keeping resources that are in fact owned by different hardware busy and does as reported by Ingo Molnar. Generally it's also dangerous to just poke at random I/O ports and especially those in the range where other old easily confused ISA hardware might live. For this specialized I2C bus driver, insist that the user specifies the resources before grabbing them. The^WA user of this driver is a one time echo "options i2c-pca-isa base=0x330 irq=10" >> /etc/modprobe.conf away from the old behaviour. Signed-off-by: Rene Herman Signed-off-by: Jean Delvare --- drivers/i2c/busses/i2c-pca-isa.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c index a119784bae1..f80df9ae505 100644 --- a/drivers/i2c/busses/i2c-pca-isa.c +++ b/drivers/i2c/busses/i2c-pca-isa.c @@ -36,8 +36,8 @@ #define DRIVER "i2c-pca-isa" #define IO_SIZE 4 -static unsigned long base = 0x330; -static int irq = 10; +static unsigned long base; +static int irq = -1; /* Data sheet recommends 59kHz for 100kHz operation due to variation * in the actual clock rate */ @@ -107,6 +107,19 @@ static struct i2c_adapter pca_isa_ops = { .timeout = 100, }; +static int __devinit pca_isa_match(struct device *dev, unsigned int id) +{ + int match = base != 0; + + if (match) { + if (irq <= -1) + dev_warn(dev, "Using polling mode (specify irq)\n"); + } else + dev_err(dev, "Please specify I/O base\n"); + + return match; +} + static int __devinit pca_isa_probe(struct device *dev, unsigned int id) { init_waitqueue_head(&pca_wait); @@ -153,7 +166,7 @@ static int __devexit pca_isa_remove(struct device *dev, unsigned int id) { i2c_del_adapter(&pca_isa_ops); - if (irq > 0) { + if (irq > -1) { disable_irq(irq); free_irq(irq, &pca_isa_ops); } @@ -163,6 +176,7 @@ static int __devexit pca_isa_remove(struct device *dev, unsigned int id) } static struct isa_driver pca_isa_driver = { + .match = pca_isa_match, .probe = pca_isa_probe, .remove = __devexit_p(pca_isa_remove), .driver = { -- cgit v1.2.3 From 4ad48e6ab18c86255f534a2cdcba5a4ead57a15f Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 14 Oct 2008 17:30:03 +0200 Subject: i2c: Renesas Highlander FPGA SMBus support This adds support for the SMBus adapter found in the various FPGAs on the Renesas Highlander platforms. Particularly the R0P7780LC0011RL and R0P7785LC0011RL FPGAs. Functionality is fairly restricted, in that only byte and block data transfers are supported. Normal/fast mode and IRQ/polling are also supported. Primarily used for various RTCs and thermal sensors. Signed-off-by: Paul Mundt Signed-off-by: Jean Delvare --- drivers/i2c/busses/Kconfig | 12 + drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-highlander.c | 498 ++++++++++++++++++++++++++++++++++++ 3 files changed, 511 insertions(+) create mode 100644 drivers/i2c/busses/i2c-highlander.c diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 6ee997b2817..e54b9fe4680 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -330,6 +330,18 @@ config I2C_GPIO This is a very simple bitbanging I2C driver utilizing the arch-neutral GPIO API to control the SCL and SDA lines. +config I2C_HIGHLANDER + tristate "Highlander FPGA SMBus interface" + depends on SH_HIGHLANDER + help + If you say yes to this option, support will be included for + the SMBus interface located in the FPGA on various Highlander + boards, particularly the R0P7780LC0011RL and R0P7785LC0011RL + FPGAs. This is wholly unrelated to the SoC I2C. + + This driver can also be built as a module. If so, the module + will be called i2c-highlander. + config I2C_IBM_IIC tristate "IBM PPC 4xx on-chip I2C interface" depends on 4xx diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 97dbfa2107f..0c2c4b26cdf 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o obj-$(CONFIG_I2C_CPM) += i2c-cpm.o obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o +obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o diff --git a/drivers/i2c/busses/i2c-highlander.c b/drivers/i2c/busses/i2c-highlander.c new file mode 100644 index 00000000000..f4d22ae9d29 --- /dev/null +++ b/drivers/i2c/busses/i2c-highlander.c @@ -0,0 +1,498 @@ +/* + * Renesas Solutions Highlander FPGA I2C/SMBus support. + * + * Supported devices: R0P7780LC0011RL, R0P7785LC0011RL + * + * Copyright (C) 2008 Paul Mundt + * Copyright (C) 2008 Renesas Solutions Corp. + * Copyright (C) 2008 Atom Create Engineering Co., Ltd. + * + * This file is subject to the terms and conditions of the GNU General + * Public License version 2. See the file "COPYING" in the main directory + * of this archive for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define SMCR 0x00 +#define SMCR_START (1 << 0) +#define SMCR_IRIC (1 << 1) +#define SMCR_BBSY (1 << 2) +#define SMCR_ACKE (1 << 3) +#define SMCR_RST (1 << 4) +#define SMCR_IEIC (1 << 6) + +#define SMSMADR 0x02 + +#define SMMR 0x04 +#define SMMR_MODE0 (1 << 0) +#define SMMR_MODE1 (1 << 1) +#define SMMR_CAP (1 << 3) +#define SMMR_TMMD (1 << 4) +#define SMMR_SP (1 << 7) + +#define SMSADR 0x06 +#define SMTRDR 0x46 + +struct highlander_i2c_dev { + struct device *dev; + void __iomem *base; + struct i2c_adapter adapter; + struct completion cmd_complete; + unsigned long last_read_time; + int irq; + u8 *buf; + size_t buf_len; +}; + +static int iic_force_poll, iic_force_normal; +static int iic_timeout = 1000, iic_read_delay; + +static inline void highlander_i2c_irq_enable(struct highlander_i2c_dev *dev) +{ + iowrite16(ioread16(dev->base + SMCR) | SMCR_IEIC, dev->base + SMCR); +} + +static inline void highlander_i2c_irq_disable(struct highlander_i2c_dev *dev) +{ + iowrite16(ioread16(dev->base + SMCR) & ~SMCR_IEIC, dev->base + SMCR); +} + +static inline void highlander_i2c_start(struct highlander_i2c_dev *dev) +{ + iowrite16(ioread16(dev->base + SMCR) | SMCR_START, dev->base + SMCR); +} + +static inline void highlander_i2c_done(struct highlander_i2c_dev *dev) +{ + iowrite16(ioread16(dev->base + SMCR) | SMCR_IRIC, dev->base + SMCR); +} + +static void highlander_i2c_setup(struct highlander_i2c_dev *dev) +{ + u16 smmr; + + smmr = ioread16(dev->base + SMMR); + smmr |= SMMR_TMMD; + + if (iic_force_normal) + smmr &= ~SMMR_SP; + else + smmr |= SMMR_SP; + + iowrite16(smmr, dev->base + SMMR); +} + +static void smbus_write_data(u8 *src, u16 *dst, int len) +{ + for (; len > 1; len -= 2) { + *dst++ = be16_to_cpup((u16 *)src); + src += 2; + } + + if (len) + *dst = *src << 8; +} + +static void smbus_read_data(u16 *src, u8 *dst, int len) +{ + for (; len > 1; len -= 2) { + *(u16 *)dst = cpu_to_be16p(src++); + dst += 2; + } + + if (len) + *dst = *src >> 8; +} + +static void highlander_i2c_command(struct highlander_i2c_dev *dev, + u8 command, int len) +{ + unsigned int i; + u16 cmd = (command << 8) | command; + + for (i = 0; i < len; i += 2) { + if (len - i == 1) + cmd = command << 8; + iowrite16(cmd, dev->base + SMSADR + i); + dev_dbg(dev->dev, "command data[%x] 0x%04x\n", i/2, cmd); + } +} + +static int highlander_i2c_wait_for_bbsy(struct highlander_i2c_dev *dev) +{ + unsigned long timeout; + + timeout = jiffies + msecs_to_jiffies(iic_timeout); + while (ioread16(dev->base + SMCR) & SMCR_BBSY) { + if (time_after(jiffies, timeout)) { + dev_warn(dev->dev, "timeout waiting for bus ready\n"); + return -ETIMEDOUT; + } + + msleep(1); + } + + return 0; +} + +static int highlander_i2c_reset(struct highlander_i2c_dev *dev) +{ + iowrite16(ioread16(dev->base + SMCR) | SMCR_RST, dev->base + SMCR); + return highlander_i2c_wait_for_bbsy(dev); +} + +static int highlander_i2c_wait_for_ack(struct highlander_i2c_dev *dev) +{ + u16 tmp = ioread16(dev->base + SMCR); + + if ((tmp & (SMCR_IRIC | SMCR_ACKE)) == SMCR_ACKE) { + dev_warn(dev->dev, "ack abnormality\n"); + return highlander_i2c_reset(dev); + } + + return 0; +} + +static irqreturn_t highlander_i2c_irq(int irq, void *dev_id) +{ + struct highlander_i2c_dev *dev = dev_id; + + highlander_i2c_done(dev); + complete(&dev->cmd_complete); + + return IRQ_HANDLED; +} + +static void highlander_i2c_poll(struct highlander_i2c_dev *dev) +{ + unsigned long timeout; + u16 smcr; + + timeout = jiffies + msecs_to_jiffies(iic_timeout); + for (;;) { + smcr = ioread16(dev->base + SMCR); + + /* + * Don't bother checking ACKE here, this and the reset + * are handled in highlander_i2c_wait_xfer_done() when + * waiting for the ACK. + */ + + if (smcr & SMCR_IRIC) + return; + if (time_after(jiffies, timeout)) + break; + + cpu_relax(); + cond_resched(); + } + + dev_err(dev->dev, "polling timed out\n"); +} + +static inline int highlander_i2c_wait_xfer_done(struct highlander_i2c_dev *dev) +{ + if (dev->irq) + wait_for_completion_timeout(&dev->cmd_complete, + msecs_to_jiffies(iic_timeout)); + else + /* busy looping, the IRQ of champions */ + highlander_i2c_poll(dev); + + return highlander_i2c_wait_for_ack(dev); +} + +static int highlander_i2c_read(struct highlander_i2c_dev *dev) +{ + int i, cnt; + u16 data[16]; + + if (highlander_i2c_wait_for_bbsy(dev)) + return -EAGAIN; + + highlander_i2c_start(dev); + + if (highlander_i2c_wait_xfer_done(dev)) { + dev_err(dev->dev, "Arbitration loss\n"); + return -EAGAIN; + } + + /* + * The R0P7780LC0011RL FPGA needs a significant delay between + * data read cycles, otherwise the transciever gets confused and + * garbage is returned when the read is subsequently aborted. + * + * It is not sufficient to wait for BBSY. + * + * While this generally only applies to the older SH7780-based + * Highlanders, the same issue can be observed on SH7785 ones, + * albeit less frequently. SH7780-based Highlanders may need + * this to be as high as 1000 ms. + */ + if (iic_read_delay && time_before(jiffies, dev->last_read_time + + msecs_to_jiffies(iic_read_delay))) + msleep(jiffies_to_msecs((dev->last_read_time + + msecs_to_jiffies(iic_read_delay)) - jiffies)); + + cnt = (dev->buf_len + 1) >> 1; + for (i = 0; i < cnt; i++) { + data[i] = ioread16(dev->base + SMTRDR + (i * sizeof(u16))); + dev_dbg(dev->dev, "read data[%x] 0x%04x\n", i, data[i]); + } + + smbus_read_data(data, dev->buf, dev->buf_len); + + dev->last_read_time = jiffies; + + return 0; +} + +static int highlander_i2c_write(struct highlander_i2c_dev *dev) +{ + int i, cnt; + u16 data[16]; + + smbus_write_data(dev->buf, data, dev->buf_len); + + cnt = (dev->buf_len + 1) >> 1; + for (i = 0; i < cnt; i++) { + iowrite16(data[i], dev->base + SMTRDR + (i * sizeof(u16))); + dev_dbg(dev->dev, "write data[%x] 0x%04x\n", i, data[i]); + } + + if (highlander_i2c_wait_for_bbsy(dev)) + return -EAGAIN; + + highlander_i2c_start(dev); + + return highlander_i2c_wait_xfer_done(dev); +} + +static int highlander_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, + union i2c_smbus_data *data) +{ + struct highlander_i2c_dev *dev = i2c_get_adapdata(adap); + int read = read_write & I2C_SMBUS_READ; + u16 tmp; + + init_completion(&dev->cmd_complete); + + dev_dbg(dev->dev, "addr %04x, command %02x, read_write %d, size %d\n", + addr, command, read_write, size); + + /* + * Set up the buffer and transfer size + */ + switch (size) { + case I2C_SMBUS_BYTE_DATA: + dev->buf = &data->byte; + dev->buf_len = 1; + break; + case I2C_SMBUS_I2C_BLOCK_DATA: + dev->buf = &data->block[1]; + dev->buf_len = data->block[0]; + break; + default: + dev_err(dev->dev, "unsupported command %d\n", size); + return -EINVAL; + } + + /* + * Encode the mode setting + */ + tmp = ioread16(dev->base + SMMR); + tmp &= ~(SMMR_MODE0 | SMMR_MODE1); + + switch (dev->buf_len) { + case 1: + /* default */ + break; + case 8: + tmp |= SMMR_MODE0; + break; + case 16: + tmp |= SMMR_MODE1; + break; + case 32: + tmp |= (SMMR_MODE0 | SMMR_MODE1); + break; + default: + dev_err(dev->dev, "unsupported xfer size %d\n", dev->buf_len); + return -EINVAL; + } + + iowrite16(tmp, dev->base + SMMR); + + /* Ensure we're in a sane state */ + highlander_i2c_done(dev); + + /* Set slave address */ + iowrite16((addr << 1) | read, dev->base + SMSMADR); + + highlander_i2c_command(dev, command, dev->buf_len); + + if (read) + return highlander_i2c_read(dev); + else + return highlander_i2c_write(dev); +} + +static u32 highlander_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK; +} + +static const struct i2c_algorithm highlander_i2c_algo = { + .smbus_xfer = highlander_i2c_smbus_xfer, + .functionality = highlander_i2c_func, +}; + +static int __devinit highlander_i2c_probe(struct platform_device *pdev) +{ + struct highlander_i2c_dev *dev; + struct i2c_adapter *adap; + struct resource *res; + int ret; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (unlikely(!res)) { + dev_err(&pdev->dev, "no mem resource\n"); + return -ENODEV; + } + + dev = kzalloc(sizeof(struct highlander_i2c_dev), GFP_KERNEL); + if (unlikely(!dev)) + return -ENOMEM; + + dev->base = ioremap_nocache(res->start, res->end - res->start + 1); + if (unlikely(!dev->base)) { + ret = -ENXIO; + goto err; + } + + dev->dev = &pdev->dev; + platform_set_drvdata(pdev, dev); + + dev->irq = platform_get_irq(pdev, 0); + if (iic_force_poll) + dev->irq = 0; + + if (dev->irq) { + ret = request_irq(dev->irq, highlander_i2c_irq, IRQF_DISABLED, + pdev->name, dev); + if (unlikely(ret)) + goto err_unmap; + + highlander_i2c_irq_enable(dev); + } else { + dev_notice(&pdev->dev, "no IRQ, using polling mode\n"); + highlander_i2c_irq_disable(dev); + } + + dev->last_read_time = jiffies; /* initial read jiffies */ + + highlander_i2c_setup(dev); + + adap = &dev->adapter; + i2c_set_adapdata(adap, dev); + adap->owner = THIS_MODULE; + adap->class = I2C_CLASS_HWMON; + strlcpy(adap->name, "HL FPGA I2C adapter", sizeof(adap->name)); + adap->algo = &highlander_i2c_algo; + adap->dev.parent = &pdev->dev; + adap->nr = pdev->id; + + /* + * Reset the adapter + */ + ret = highlander_i2c_reset(dev); + if (unlikely(ret)) { + dev_err(&pdev->dev, "controller didn't come up\n"); + goto err_free_irq; + } + + ret = i2c_add_numbered_adapter(adap); + if (unlikely(ret)) { + dev_err(&pdev->dev, "failure adding adapter\n"); + goto err_free_irq; + } + + return 0; + +err_free_irq: + if (dev->irq) + free_irq(dev->irq, dev); +err_unmap: + iounmap(dev->base); +err: + kfree(dev); + + platform_set_drvdata(pdev, NULL); + + return ret; +} + +static int __devexit highlander_i2c_remove(struct platform_device *pdev) +{ + struct highlander_i2c_dev *dev = platform_get_drvdata(pdev); + + i2c_del_adapter(&dev->adapter); + + if (dev->irq) + free_irq(dev->irq, dev); + + iounmap(dev->base); + kfree(dev); + + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver highlander_i2c_driver = { + .driver = { + .name = "i2c-highlander", + .owner = THIS_MODULE, + }, + + .probe = highlander_i2c_probe, + .remove = __devexit_p(highlander_i2c_remove), +}; + +static int __init highlander_i2c_init(void) +{ + return platform_driver_register(&highlander_i2c_driver); +} + +static void __exit highlander_i2c_exit(void) +{ + platform_driver_unregister(&highlander_i2c_driver); +} + +module_init(highlander_i2c_init); +module_exit(highlander_i2c_exit); + +MODULE_AUTHOR("Paul Mundt"); +MODULE_DESCRIPTION("Renesas Highlander FPGA I2C/SMBus adapter"); +MODULE_LICENSE("GPL v2"); + +module_param(iic_force_poll, bool, 0); +module_param(iic_force_normal, bool, 0); +module_param(iic_timeout, int, 0); +module_param(iic_read_delay, int, 0); + +MODULE_PARM_DESC(iic_force_poll, "Force polling mode"); +MODULE_PARM_DESC(iic_force_normal, + "Force normal mode (100 kHz), default is fast mode (400 kHz)"); +MODULE_PARM_DESC(iic_timeout, "Set timeout value in msecs (default 1000 ms)"); +MODULE_PARM_DESC(iic_read_delay, + "Delay between data read cycles (default 0 ms)"); -- cgit v1.2.3 From b806a71a0e9dacb6763371561caa693c78b93d40 Mon Sep 17 00:00:00 2001 From: Rudolf Marek Date: Tue, 14 Oct 2008 17:30:03 +0200 Subject: i2c-viapro: Add VX800/VX820 support Thanks to new datasheets published on http://linux.via.com.tw we can now add support for VX800/VX820 chipsets. Signed-off-by: Rudolf Marek Signed-off-by: Jean Delvare --- Documentation/i2c/busses/i2c-viapro | 8 ++++++-- drivers/i2c/busses/Kconfig | 4 +++- drivers/i2c/busses/i2c-viapro.c | 4 ++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Documentation/i2c/busses/i2c-viapro b/Documentation/i2c/busses/i2c-viapro index 1405fb69984..22efedf60c8 100644 --- a/Documentation/i2c/busses/i2c-viapro +++ b/Documentation/i2c/busses/i2c-viapro @@ -16,6 +16,9 @@ Supported adapters: * VIA Technologies, Inc. CX700 Datasheet: available on request and under NDA from VIA + * VIA Technologies, Inc. VX800/VX820 + Datasheet: available on http://linux.via.com.tw + Authors: Kyösti Mälkki , Mark D. Studebaker , @@ -49,6 +52,7 @@ Your lspci -n listing must show one of these : device 1106:3372 (VT8237S) device 1106:3287 (VT8251) device 1106:8324 (CX700) + device 1106:8353 (VX800/VX820) If none of these show up, you should look in the BIOS for settings like enable ACPI / SMBus or even USB. @@ -57,5 +61,5 @@ Except for the oldest chips (VT82C596A/B, VT82C686A and most probably VT8231), this driver supports I2C block transactions. Such transactions are mainly useful to read from and write to EEPROMs. -The CX700 additionally appears to support SMBus PEC, although this driver -doesn't implement it yet. +The CX700/VX800/VX820 additionally appears to support SMBus PEC, although +this driver doesn't implement it yet. diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index e54b9fe4680..b32164cfbc4 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -209,7 +209,7 @@ config I2C_VIA will be called i2c-via. config I2C_VIAPRO - tristate "VIA VT82C596/82C686/82xx and CX700" + tristate "VIA VT82C596/82C686/82xx and CX700/VX800/VX820" depends on PCI help If you say yes to this option, support will be included for the VIA @@ -223,6 +223,8 @@ config I2C_VIAPRO VT8237R/A/S VT8251 CX700 + VX800 + VX820 This driver can also be built as a module. If so, the module will be called i2c-viapro. diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c index 862eb352a2d..1345da97b23 100644 --- a/drivers/i2c/busses/i2c-viapro.c +++ b/drivers/i2c/busses/i2c-viapro.c @@ -36,6 +36,7 @@ VT8237S 0x3372 yes VT8251 0x3287 yes CX700 0x8324 yes + VX800/VX820 0x8353 yes Note: we assume there can only be one device, with one SMBus interface. */ @@ -396,6 +397,7 @@ found: switch (pdev->device) { case PCI_DEVICE_ID_VIA_CX700: + case PCI_DEVICE_ID_VIA_VX800: case PCI_DEVICE_ID_VIA_8251: case PCI_DEVICE_ID_VIA_8237: case PCI_DEVICE_ID_VIA_8237A: @@ -459,6 +461,8 @@ static struct pci_device_id vt596_ids[] = { .driver_data = SMBBA3 }, { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_CX700), .driver_data = SMBBA3 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX800), + .driver_data = SMBBA3 }, { 0, } }; -- cgit v1.2.3 From b84ee0b0c7dc91b729672e6a971fe3b0629ef0ad Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 14 Oct 2008 17:30:04 +0200 Subject: i2c/tps65010: Vibrator hookup to gpiolib All the tps6501{0,1,2,3,4} chips have a signal for hooking up with a vibrator (for non-auditory cell phone "ring") ... expose that as one more (output-only) GPIO. [ dbrownell@users.sourceforge.net: comments; list tps65014 too ] Signed-off-by: Marek Vasut Signed-off-by: David Brownell Signed-off-by: Jean Delvare --- drivers/i2c/chips/tps65010.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c index cf02e8fceb4..acf8b9d5f57 100644 --- a/drivers/i2c/chips/tps65010.c +++ b/drivers/i2c/chips/tps65010.c @@ -456,14 +456,17 @@ static irqreturn_t tps65010_irq(int irq, void *_tps) /* offsets 0..3 == GPIO1..GPIO4 * offsets 4..5 == LED1/nPG, LED2 (we set one of the non-BLINK modes) + * offset 6 == vibrator motor driver */ static void tps65010_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { if (offset < 4) tps65010_set_gpio_out_value(offset + 1, value); - else + else if (offset < 6) tps65010_set_led(offset - 3, value ? ON : OFF); + else + tps65010_set_vib(value); } static int @@ -477,8 +480,10 @@ tps65010_output(struct gpio_chip *chip, unsigned offset, int value) if (!(tps->outmask & (1 << offset))) return -EINVAL; tps65010_set_gpio_out_value(offset + 1, value); - } else + } else if (offset < 6) tps65010_set_led(offset - 3, value ? ON : OFF); + else + tps65010_set_vib(value); return 0; } @@ -646,7 +651,7 @@ static int tps65010_probe(struct i2c_client *client, tps->chip.get = tps65010_gpio_get; tps->chip.base = board->base; - tps->chip.ngpio = 6; + tps->chip.ngpio = 7; tps->chip.can_sleep = 1; status = gpiochip_add(&tps->chip); @@ -675,6 +680,7 @@ static const struct i2c_device_id tps65010_id[] = { { "tps65011", TPS65011 }, { "tps65012", TPS65012 }, { "tps65013", TPS65013 }, + { "tps65014", TPS65011 }, /* tps65011 charging at 6.5V max */ { } }; MODULE_DEVICE_TABLE(i2c, tps65010_id); -- cgit v1.2.3 From dbc2bc251e06c83efcc8d39f1e7de12c2b1ff591 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 14 Oct 2008 17:30:04 +0200 Subject: hwmon: (dme1737) Be less i2c-centric The dme1737 driver support both LPC (ISA) and SMBus devices. At the moment it's rather i2c-centric, and LPC variants use a fake i2c_client for some operations. In a near future, i2c_client will be allocated by i2c-core rather than by the device drivers, so non-i2c drivers will not have one. As a preparation step, change the driver code to no longer assume that an i2c_client structure is always available. No functional change. Signed-off-by: Jean Delvare Cc: Juerg Haefliger --- drivers/hwmon/dme1737.c | 226 ++++++++++++++++++++++++------------------------ 1 file changed, 111 insertions(+), 115 deletions(-) diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c index cdb8311e4ef..2bf97e1470c 100644 --- a/drivers/hwmon/dme1737.c +++ b/drivers/hwmon/dme1737.c @@ -175,11 +175,12 @@ static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23}; * Data structures and manipulation thereof * --------------------------------------------------------------------- */ -/* For ISA chips, we abuse the i2c_client addr and name fields. We also use - the driver field to differentiate between I2C and ISA chips. */ struct dme1737_data { - struct i2c_client client; + struct i2c_client _client; /* will go away soon */ + struct i2c_client *client; /* for I2C devices only */ struct device *hwmon_dev; + const char *name; + unsigned int addr; /* for ISA devices only */ struct mutex update_lock; int valid; /* !=0 if following fields are valid */ @@ -512,11 +513,12 @@ static inline int PWM_OFF_TO_REG(int val, int ix, int reg) * before calling dme1737_read or dme1737_write. * --------------------------------------------------------------------- */ -static u8 dme1737_read(struct i2c_client *client, u8 reg) +static u8 dme1737_read(const struct dme1737_data *data, u8 reg) { + struct i2c_client *client = data->client; s32 val; - if (client->driver) { /* I2C device */ + if (client) { /* I2C device */ val = i2c_smbus_read_byte_data(client, reg); if (val < 0) { @@ -525,18 +527,19 @@ static u8 dme1737_read(struct i2c_client *client, u8 reg) "maintainer.\n", reg); } } else { /* ISA device */ - outb(reg, client->addr); - val = inb(client->addr + 1); + outb(reg, data->addr); + val = inb(data->addr + 1); } return val; } -static s32 dme1737_write(struct i2c_client *client, u8 reg, u8 val) +static s32 dme1737_write(const struct dme1737_data *data, u8 reg, u8 val) { + struct i2c_client *client = data->client; s32 res = 0; - if (client->driver) { /* I2C device */ + if (client) { /* I2C device */ res = i2c_smbus_write_byte_data(client, reg, val); if (res < 0) { @@ -545,8 +548,8 @@ static s32 dme1737_write(struct i2c_client *client, u8 reg, u8 val) "maintainer.\n", reg); } } else { /* ISA device */ - outb(reg, client->addr); - outb(val, client->addr + 1); + outb(reg, data->addr); + outb(val, data->addr + 1); } return res; @@ -555,7 +558,6 @@ static s32 dme1737_write(struct i2c_client *client, u8 reg, u8 val) static struct dme1737_data *dme1737_update_device(struct device *dev) { struct dme1737_data *data = dev_get_drvdata(dev); - struct i2c_client *client = &data->client; int ix; u8 lsb[5]; @@ -563,7 +565,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) /* Enable a Vbat monitoring cycle every 10 mins */ if (time_after(jiffies, data->last_vbat + 600 * HZ) || !data->valid) { - dme1737_write(client, DME1737_REG_CONFIG, dme1737_read(client, + dme1737_write(data, DME1737_REG_CONFIG, dme1737_read(data, DME1737_REG_CONFIG) | 0x10); data->last_vbat = jiffies; } @@ -571,7 +573,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) /* Sample register contents every 1 sec */ if (time_after(jiffies, data->last_update + HZ) || !data->valid) { if (data->type != sch5027) { - data->vid = dme1737_read(client, DME1737_REG_VID) & + data->vid = dme1737_read(data, DME1737_REG_VID) & 0x3f; } @@ -580,11 +582,11 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) /* Voltage inputs are stored as 16 bit values even * though they have only 12 bits resolution. This is * to make it consistent with the temp inputs. */ - data->in[ix] = dme1737_read(client, + data->in[ix] = dme1737_read(data, DME1737_REG_IN(ix)) << 8; - data->in_min[ix] = dme1737_read(client, + data->in_min[ix] = dme1737_read(data, DME1737_REG_IN_MIN(ix)); - data->in_max[ix] = dme1737_read(client, + data->in_max[ix] = dme1737_read(data, DME1737_REG_IN_MAX(ix)); } @@ -595,14 +597,14 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) * to take advantage of implicit conversions between * register values (2's complement) and temp values * (signed decimal). */ - data->temp[ix] = dme1737_read(client, + data->temp[ix] = dme1737_read(data, DME1737_REG_TEMP(ix)) << 8; - data->temp_min[ix] = dme1737_read(client, + data->temp_min[ix] = dme1737_read(data, DME1737_REG_TEMP_MIN(ix)); - data->temp_max[ix] = dme1737_read(client, + data->temp_max[ix] = dme1737_read(data, DME1737_REG_TEMP_MAX(ix)); if (data->type != sch5027) { - data->temp_offset[ix] = dme1737_read(client, + data->temp_offset[ix] = dme1737_read(data, DME1737_REG_TEMP_OFFSET(ix)); } } @@ -612,7 +614,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) * which the registers are read (MSB first, then LSB) is * important! */ for (ix = 0; ix < ARRAY_SIZE(lsb); ix++) { - lsb[ix] = dme1737_read(client, + lsb[ix] = dme1737_read(data, DME1737_REG_IN_TEMP_LSB(ix)); } for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) { @@ -631,19 +633,19 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) if (!(data->has_fan & (1 << ix))) { continue; } - data->fan[ix] = dme1737_read(client, + data->fan[ix] = dme1737_read(data, DME1737_REG_FAN(ix)); - data->fan[ix] |= dme1737_read(client, + data->fan[ix] |= dme1737_read(data, DME1737_REG_FAN(ix) + 1) << 8; - data->fan_min[ix] = dme1737_read(client, + data->fan_min[ix] = dme1737_read(data, DME1737_REG_FAN_MIN(ix)); - data->fan_min[ix] |= dme1737_read(client, + data->fan_min[ix] |= dme1737_read(data, DME1737_REG_FAN_MIN(ix) + 1) << 8; - data->fan_opt[ix] = dme1737_read(client, + data->fan_opt[ix] = dme1737_read(data, DME1737_REG_FAN_OPT(ix)); /* fan_max exists only for fan[5-6] */ if (ix > 3) { - data->fan_max[ix - 4] = dme1737_read(client, + data->fan_max[ix - 4] = dme1737_read(data, DME1737_REG_FAN_MAX(ix)); } } @@ -655,63 +657,63 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) if (!(data->has_pwm & (1 << ix))) { continue; } - data->pwm[ix] = dme1737_read(client, + data->pwm[ix] = dme1737_read(data, DME1737_REG_PWM(ix)); - data->pwm_freq[ix] = dme1737_read(client, + data->pwm_freq[ix] = dme1737_read(data, DME1737_REG_PWM_FREQ(ix)); /* pwm_config and pwm_min exist only for pwm[1-3] */ if (ix < 3) { - data->pwm_config[ix] = dme1737_read(client, + data->pwm_config[ix] = dme1737_read(data, DME1737_REG_PWM_CONFIG(ix)); - data->pwm_min[ix] = dme1737_read(client, + data->pwm_min[ix] = dme1737_read(data, DME1737_REG_PWM_MIN(ix)); } } for (ix = 0; ix < ARRAY_SIZE(data->pwm_rr); ix++) { - data->pwm_rr[ix] = dme1737_read(client, + data->pwm_rr[ix] = dme1737_read(data, DME1737_REG_PWM_RR(ix)); } /* Thermal zone registers */ for (ix = 0; ix < ARRAY_SIZE(data->zone_low); ix++) { - data->zone_low[ix] = dme1737_read(client, + data->zone_low[ix] = dme1737_read(data, DME1737_REG_ZONE_LOW(ix)); - data->zone_abs[ix] = dme1737_read(client, + data->zone_abs[ix] = dme1737_read(data, DME1737_REG_ZONE_ABS(ix)); } if (data->type != sch5027) { for (ix = 0; ix < ARRAY_SIZE(data->zone_hyst); ix++) { - data->zone_hyst[ix] = dme1737_read(client, + data->zone_hyst[ix] = dme1737_read(data, DME1737_REG_ZONE_HYST(ix)); } } /* Alarm registers */ - data->alarms = dme1737_read(client, + data->alarms = dme1737_read(data, DME1737_REG_ALARM1); /* Bit 7 tells us if the other alarm registers are non-zero and * therefore also need to be read */ if (data->alarms & 0x80) { - data->alarms |= dme1737_read(client, + data->alarms |= dme1737_read(data, DME1737_REG_ALARM2) << 8; - data->alarms |= dme1737_read(client, + data->alarms |= dme1737_read(data, DME1737_REG_ALARM3) << 16; } /* The ISA chips require explicit clearing of alarm bits. * Don't worry, an alarm will come back if the condition * that causes it still exists */ - if (!client->driver) { + if (!data->client) { if (data->alarms & 0xff0000) { - dme1737_write(client, DME1737_REG_ALARM3, + dme1737_write(data, DME1737_REG_ALARM3, 0xff); } if (data->alarms & 0xff00) { - dme1737_write(client, DME1737_REG_ALARM2, + dme1737_write(data, DME1737_REG_ALARM2, 0xff); } if (data->alarms & 0xff) { - dme1737_write(client, DME1737_REG_ALARM1, + dme1737_write(data, DME1737_REG_ALARM1, 0xff); } } @@ -770,7 +772,6 @@ static ssize_t set_in(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct dme1737_data *data = dev_get_drvdata(dev); - struct i2c_client *client = &data->client; struct sensor_device_attribute_2 *sensor_attr_2 = to_sensor_dev_attr_2(attr); int ix = sensor_attr_2->index; @@ -781,12 +782,12 @@ static ssize_t set_in(struct device *dev, struct device_attribute *attr, switch (fn) { case SYS_IN_MIN: data->in_min[ix] = IN_TO_REG(val, data->in_nominal[ix]); - dme1737_write(client, DME1737_REG_IN_MIN(ix), + dme1737_write(data, DME1737_REG_IN_MIN(ix), data->in_min[ix]); break; case SYS_IN_MAX: data->in_max[ix] = IN_TO_REG(val, data->in_nominal[ix]); - dme1737_write(client, DME1737_REG_IN_MAX(ix), + dme1737_write(data, DME1737_REG_IN_MAX(ix), data->in_max[ix]); break; default: @@ -850,7 +851,6 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct dme1737_data *data = dev_get_drvdata(dev); - struct i2c_client *client = &data->client; struct sensor_device_attribute_2 *sensor_attr_2 = to_sensor_dev_attr_2(attr); int ix = sensor_attr_2->index; @@ -861,17 +861,17 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *attr, switch (fn) { case SYS_TEMP_MIN: data->temp_min[ix] = TEMP_TO_REG(val); - dme1737_write(client, DME1737_REG_TEMP_MIN(ix), + dme1737_write(data, DME1737_REG_TEMP_MIN(ix), data->temp_min[ix]); break; case SYS_TEMP_MAX: data->temp_max[ix] = TEMP_TO_REG(val); - dme1737_write(client, DME1737_REG_TEMP_MAX(ix), + dme1737_write(data, DME1737_REG_TEMP_MAX(ix), data->temp_max[ix]); break; case SYS_TEMP_OFFSET: data->temp_offset[ix] = TEMP_TO_REG(val); - dme1737_write(client, DME1737_REG_TEMP_OFFSET(ix), + dme1737_write(data, DME1737_REG_TEMP_OFFSET(ix), data->temp_offset[ix]); break; default: @@ -939,7 +939,6 @@ static ssize_t set_zone(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct dme1737_data *data = dev_get_drvdata(dev); - struct i2c_client *client = &data->client; struct sensor_device_attribute_2 *sensor_attr_2 = to_sensor_dev_attr_2(attr); int ix = sensor_attr_2->index; @@ -950,37 +949,37 @@ static ssize_t set_zone(struct device *dev, struct device_attribute *attr, switch (fn) { case SYS_ZONE_AUTO_POINT1_TEMP_HYST: /* Refresh the cache */ - data->zone_low[ix] = dme1737_read(client, + data->zone_low[ix] = dme1737_read(data, DME1737_REG_ZONE_LOW(ix)); /* Modify the temp hyst value */ data->zone_hyst[ix == 2] = TEMP_HYST_TO_REG( TEMP_FROM_REG(data->zone_low[ix], 8) - - val, ix, dme1737_read(client, + val, ix, dme1737_read(data, DME1737_REG_ZONE_HYST(ix == 2))); - dme1737_write(client, DME1737_REG_ZONE_HYST(ix == 2), + dme1737_write(data, DME1737_REG_ZONE_HYST(ix == 2), data->zone_hyst[ix == 2]); break; case SYS_ZONE_AUTO_POINT1_TEMP: data->zone_low[ix] = TEMP_TO_REG(val); - dme1737_write(client, DME1737_REG_ZONE_LOW(ix), + dme1737_write(data, DME1737_REG_ZONE_LOW(ix), data->zone_low[ix]); break; case SYS_ZONE_AUTO_POINT2_TEMP: /* Refresh the cache */ - data->zone_low[ix] = dme1737_read(client, + data->zone_low[ix] = dme1737_read(data, DME1737_REG_ZONE_LOW(ix)); /* Modify the temp range value (which is stored in the upper * nibble of the pwm_freq register) */ data->pwm_freq[ix] = TEMP_RANGE_TO_REG(val - TEMP_FROM_REG(data->zone_low[ix], 8), - dme1737_read(client, + dme1737_read(data, DME1737_REG_PWM_FREQ(ix))); - dme1737_write(client, DME1737_REG_PWM_FREQ(ix), + dme1737_write(data, DME1737_REG_PWM_FREQ(ix), data->pwm_freq[ix]); break; case SYS_ZONE_AUTO_POINT3_TEMP: data->zone_abs[ix] = TEMP_TO_REG(val); - dme1737_write(client, DME1737_REG_ZONE_ABS(ix), + dme1737_write(data, DME1737_REG_ZONE_ABS(ix), data->zone_abs[ix]); break; default: @@ -1046,7 +1045,6 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct dme1737_data *data = dev_get_drvdata(dev); - struct i2c_client *client = &data->client; struct sensor_device_attribute_2 *sensor_attr_2 = to_sensor_dev_attr_2(attr); int ix = sensor_attr_2->index; @@ -1060,21 +1058,21 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr, data->fan_min[ix] = FAN_TO_REG(val, 0); } else { /* Refresh the cache */ - data->fan_opt[ix] = dme1737_read(client, + data->fan_opt[ix] = dme1737_read(data, DME1737_REG_FAN_OPT(ix)); /* Modify the fan min value */ data->fan_min[ix] = FAN_TO_REG(val, FAN_TPC_FROM_REG(data->fan_opt[ix])); } - dme1737_write(client, DME1737_REG_FAN_MIN(ix), + dme1737_write(data, DME1737_REG_FAN_MIN(ix), data->fan_min[ix] & 0xff); - dme1737_write(client, DME1737_REG_FAN_MIN(ix) + 1, + dme1737_write(data, DME1737_REG_FAN_MIN(ix) + 1, data->fan_min[ix] >> 8); break; case SYS_FAN_MAX: /* Only valid for fan[5-6] */ data->fan_max[ix - 4] = FAN_MAX_TO_REG(val); - dme1737_write(client, DME1737_REG_FAN_MAX(ix), + dme1737_write(data, DME1737_REG_FAN_MAX(ix), data->fan_max[ix - 4]); break; case SYS_FAN_TYPE: @@ -1086,9 +1084,9 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr, val); goto exit; } - data->fan_opt[ix] = FAN_TYPE_TO_REG(val, dme1737_read(client, + data->fan_opt[ix] = FAN_TYPE_TO_REG(val, dme1737_read(data, DME1737_REG_FAN_OPT(ix))); - dme1737_write(client, DME1737_REG_FAN_OPT(ix), + dme1737_write(data, DME1737_REG_FAN_OPT(ix), data->fan_opt[ix]); break; default: @@ -1185,7 +1183,6 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct dme1737_data *data = dev_get_drvdata(dev); - struct i2c_client *client = &data->client; struct sensor_device_attribute_2 *sensor_attr_2 = to_sensor_dev_attr_2(attr); int ix = sensor_attr_2->index; @@ -1196,12 +1193,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, switch (fn) { case SYS_PWM: data->pwm[ix] = SENSORS_LIMIT(val, 0, 255); - dme1737_write(client, DME1737_REG_PWM(ix), data->pwm[ix]); + dme1737_write(data, DME1737_REG_PWM(ix), data->pwm[ix]); break; case SYS_PWM_FREQ: - data->pwm_freq[ix] = PWM_FREQ_TO_REG(val, dme1737_read(client, + data->pwm_freq[ix] = PWM_FREQ_TO_REG(val, dme1737_read(data, DME1737_REG_PWM_FREQ(ix))); - dme1737_write(client, DME1737_REG_PWM_FREQ(ix), + dme1737_write(data, DME1737_REG_PWM_FREQ(ix), data->pwm_freq[ix]); break; case SYS_PWM_ENABLE: @@ -1214,7 +1211,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, goto exit; } /* Refresh the cache */ - data->pwm_config[ix] = dme1737_read(client, + data->pwm_config[ix] = dme1737_read(data, DME1737_REG_PWM_CONFIG(ix)); if (val == PWM_EN_FROM_REG(data->pwm_config[ix])) { /* Bail out if no change */ @@ -1226,14 +1223,14 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, data->pwm_acz[ix] = PWM_ACZ_FROM_REG( data->pwm_config[ix]); /* Save the current ramp rate state and disable it */ - data->pwm_rr[ix > 0] = dme1737_read(client, + data->pwm_rr[ix > 0] = dme1737_read(data, DME1737_REG_PWM_RR(ix > 0)); data->pwm_rr_en &= ~(1 << ix); if (PWM_RR_EN_FROM_REG(data->pwm_rr[ix > 0], ix)) { data->pwm_rr_en |= (1 << ix); data->pwm_rr[ix > 0] = PWM_RR_EN_TO_REG(0, ix, data->pwm_rr[ix > 0]); - dme1737_write(client, + dme1737_write(data, DME1737_REG_PWM_RR(ix > 0), data->pwm_rr[ix > 0]); } @@ -1247,14 +1244,14 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, /* Turn fan fully on */ data->pwm_config[ix] = PWM_EN_TO_REG(0, data->pwm_config[ix]); - dme1737_write(client, DME1737_REG_PWM_CONFIG(ix), + dme1737_write(data, DME1737_REG_PWM_CONFIG(ix), data->pwm_config[ix]); break; case 1: /* Turn on manual mode */ data->pwm_config[ix] = PWM_EN_TO_REG(1, data->pwm_config[ix]); - dme1737_write(client, DME1737_REG_PWM_CONFIG(ix), + dme1737_write(data, DME1737_REG_PWM_CONFIG(ix), data->pwm_config[ix]); /* Change permissions of pwm[ix] to read-writeable */ dme1737_chmod_file(dev, dme1737_pwm_chmod_attr[ix], @@ -1269,14 +1266,14 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, data->pwm_config[ix] = PWM_ACZ_TO_REG( data->pwm_acz[ix], data->pwm_config[ix]); - dme1737_write(client, DME1737_REG_PWM_CONFIG(ix), + dme1737_write(data, DME1737_REG_PWM_CONFIG(ix), data->pwm_config[ix]); /* Enable PWM ramp rate if previously enabled */ if (data->pwm_rr_en & (1 << ix)) { data->pwm_rr[ix > 0] = PWM_RR_EN_TO_REG(1, ix, - dme1737_read(client, + dme1737_read(data, DME1737_REG_PWM_RR(ix > 0))); - dme1737_write(client, + dme1737_write(data, DME1737_REG_PWM_RR(ix > 0), data->pwm_rr[ix > 0]); } @@ -1286,9 +1283,9 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, case SYS_PWM_RAMP_RATE: /* Only valid for pwm[1-3] */ /* Refresh the cache */ - data->pwm_config[ix] = dme1737_read(client, + data->pwm_config[ix] = dme1737_read(data, DME1737_REG_PWM_CONFIG(ix)); - data->pwm_rr[ix > 0] = dme1737_read(client, + data->pwm_rr[ix > 0] = dme1737_read(data, DME1737_REG_PWM_RR(ix > 0)); /* Set the ramp rate value */ if (val > 0) { @@ -1301,7 +1298,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, data->pwm_rr[ix > 0] = PWM_RR_EN_TO_REG(val > 0, ix, data->pwm_rr[ix > 0]); } - dme1737_write(client, DME1737_REG_PWM_RR(ix > 0), + dme1737_write(data, DME1737_REG_PWM_RR(ix > 0), data->pwm_rr[ix > 0]); break; case SYS_PWM_AUTO_CHANNELS_ZONE: @@ -1315,14 +1312,14 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, goto exit; } /* Refresh the cache */ - data->pwm_config[ix] = dme1737_read(client, + data->pwm_config[ix] = dme1737_read(data, DME1737_REG_PWM_CONFIG(ix)); if (PWM_EN_FROM_REG(data->pwm_config[ix]) == 2) { /* PWM is already in auto mode so update the temp * channel assignment */ data->pwm_config[ix] = PWM_ACZ_TO_REG(val, data->pwm_config[ix]); - dme1737_write(client, DME1737_REG_PWM_CONFIG(ix), + dme1737_write(data, DME1737_REG_PWM_CONFIG(ix), data->pwm_config[ix]); } else { /* PWM is not in auto mode so we save the temp @@ -1333,7 +1330,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, case SYS_PWM_AUTO_PWM_MIN: /* Only valid for pwm[1-3] */ /* Refresh the cache */ - data->pwm_min[ix] = dme1737_read(client, + data->pwm_min[ix] = dme1737_read(data, DME1737_REG_PWM_MIN(ix)); /* There are only 2 values supported for the auto_pwm_min * value: 0 or auto_point1_pwm. So if the temperature drops @@ -1341,20 +1338,20 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, * off or runs at auto_point1_pwm duty-cycle. */ if (val > ((data->pwm_min[ix] + 1) / 2)) { data->pwm_rr[0] = PWM_OFF_TO_REG(1, ix, - dme1737_read(client, + dme1737_read(data, DME1737_REG_PWM_RR(0))); } else { data->pwm_rr[0] = PWM_OFF_TO_REG(0, ix, - dme1737_read(client, + dme1737_read(data, DME1737_REG_PWM_RR(0))); } - dme1737_write(client, DME1737_REG_PWM_RR(0), + dme1737_write(data, DME1737_REG_PWM_RR(0), data->pwm_rr[0]); break; case SYS_PWM_AUTO_POINT1_PWM: /* Only valid for pwm[1-3] */ data->pwm_min[ix] = SENSORS_LIMIT(val, 0, 255); - dme1737_write(client, DME1737_REG_PWM_MIN(ix), + dme1737_write(data, DME1737_REG_PWM_MIN(ix), data->pwm_min[ix]); break; default: @@ -1402,7 +1399,7 @@ static ssize_t show_name(struct device *dev, struct device_attribute *attr, { struct dme1737_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", data->client.name); + return sprintf(buf, "%s\n", data->name); } /* --------------------------------------------------------------------- @@ -1908,7 +1905,7 @@ static void dme1737_remove_files(struct device *dev) sysfs_remove_group(&dev->kobj, &dme1737_group); - if (!data->client.driver) { + if (!data->client) { sysfs_remove_file(&dev->kobj, &dev_attr_name.attr); } } @@ -1919,7 +1916,7 @@ static int dme1737_create_files(struct device *dev) int err, ix; /* Create a name attribute for ISA devices */ - if (!data->client.driver && + if (!data->client && (err = sysfs_create_file(&dev->kobj, &dev_attr_name.attr))) { goto exit; } @@ -2013,14 +2010,14 @@ exit: static int dme1737_init_device(struct device *dev) { struct dme1737_data *data = dev_get_drvdata(dev); - struct i2c_client *client = &data->client; + struct i2c_client *client = data->client; int ix; u8 reg; /* Point to the right nominal voltages array */ data->in_nominal = IN_NOMINAL(data->type); - data->config = dme1737_read(client, DME1737_REG_CONFIG); + data->config = dme1737_read(data, DME1737_REG_CONFIG); /* Inform if part is not monitoring/started */ if (!(data->config & 0x01)) { if (!force_start) { @@ -2032,7 +2029,7 @@ static int dme1737_init_device(struct device *dev) /* Force monitoring */ data->config |= 0x01; - dme1737_write(client, DME1737_REG_CONFIG, data->config); + dme1737_write(data, DME1737_REG_CONFIG, data->config); } /* Inform if part is not ready */ if (!(data->config & 0x04)) { @@ -2041,8 +2038,8 @@ static int dme1737_init_device(struct device *dev) } /* Determine which optional fan and pwm features are enabled/present */ - if (client->driver) { /* I2C chip */ - data->config2 = dme1737_read(client, DME1737_REG_CONFIG2); + if (client) { /* I2C chip */ + data->config2 = dme1737_read(data, DME1737_REG_CONFIG2); /* Check if optional fan3 input is enabled */ if (data->config2 & 0x04) { data->has_fan |= (1 << 2); @@ -2051,7 +2048,7 @@ static int dme1737_init_device(struct device *dev) /* Fan4 and pwm3 are only available if the client's I2C address * is the default 0x2e. Otherwise the I/Os associated with * these functions are used for addr enable/select. */ - if (data->client.addr == 0x2e) { + if (client->addr == 0x2e) { data->has_fan |= (1 << 3); data->has_pwm |= (1 << 2); } @@ -2086,16 +2083,16 @@ static int dme1737_init_device(struct device *dev) (data->has_fan & (1 << 4)) ? "yes" : "no", (data->has_fan & (1 << 5)) ? "yes" : "no"); - reg = dme1737_read(client, DME1737_REG_TACH_PWM); + reg = dme1737_read(data, DME1737_REG_TACH_PWM); /* Inform if fan-to-pwm mapping differs from the default */ - if (client->driver && reg != 0xa4) { /* I2C chip */ + if (client && reg != 0xa4) { /* I2C chip */ dev_warn(dev, "Non-standard fan to pwm mapping: " "fan1->pwm%d, fan2->pwm%d, fan3->pwm%d, " "fan4->pwm%d. Please report to the driver " "maintainer.\n", (reg & 0x03) + 1, ((reg >> 2) & 0x03) + 1, ((reg >> 4) & 0x03) + 1, ((reg >> 6) & 0x03) + 1); - } else if (!client->driver && reg != 0x24) { /* ISA chip */ + } else if (!client && reg != 0x24) { /* ISA chip */ dev_warn(dev, "Non-standard fan to pwm mapping: " "fan1->pwm%d, fan2->pwm%d, fan3->pwm%d. " "Please report to the driver maintainer.\n", @@ -2108,7 +2105,7 @@ static int dme1737_init_device(struct device *dev) * disabled). */ if (!(data->config & 0x02)) { for (ix = 0; ix < 3; ix++) { - data->pwm_config[ix] = dme1737_read(client, + data->pwm_config[ix] = dme1737_read(data, DME1737_REG_PWM_CONFIG(ix)); if ((data->has_pwm & (1 << ix)) && (PWM_EN_FROM_REG(data->pwm_config[ix]) == -1)) { @@ -2116,8 +2113,8 @@ static int dme1737_init_device(struct device *dev) "manual mode.\n", ix + 1); data->pwm_config[ix] = PWM_EN_TO_REG(1, data->pwm_config[ix]); - dme1737_write(client, DME1737_REG_PWM(ix), 0); - dme1737_write(client, + dme1737_write(data, DME1737_REG_PWM(ix), 0); + dme1737_write(data, DME1737_REG_PWM_CONFIG(ix), data->pwm_config[ix]); } @@ -2210,7 +2207,8 @@ static int dme1737_i2c_detect(struct i2c_adapter *adapter, int address, goto exit; } - client = &data->client; + client = &data->_client; + data->client = client; i2c_set_clientdata(client, data); client->addr = address; client->adapter = adapter; @@ -2220,8 +2218,8 @@ static int dme1737_i2c_detect(struct i2c_adapter *adapter, int address, /* A negative kind means that the driver was loaded with no force * parameter (default), so we must identify the chip. */ if (kind < 0) { - company = dme1737_read(client, DME1737_REG_COMPANY); - verstep = dme1737_read(client, DME1737_REG_VERSTEP); + company = dme1737_read(data, DME1737_REG_COMPANY); + verstep = dme1737_read(data, DME1737_REG_VERSTEP); if (company == DME1737_COMPANY_SMSC && (verstep & DME1737_VERSTEP_MASK) == DME1737_VERSTEP) { @@ -2246,6 +2244,7 @@ static int dme1737_i2c_detect(struct i2c_adapter *adapter, int address, /* Fill in the remaining client fields and put it into the global * list */ strlcpy(client->name, name, I2C_NAME_SIZE); + data->name = client->name; mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ @@ -2403,7 +2402,6 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev) { u8 company, device; struct resource *res; - struct i2c_client *client; struct dme1737_data *data; struct device *dev = &pdev->dev; int err; @@ -2422,15 +2420,13 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev) goto exit_release_region; } - client = &data->client; - i2c_set_clientdata(client, data); - client->addr = res->start; + data->addr = res->start; platform_set_drvdata(pdev, data); /* Skip chip detection if module is loaded with force_id parameter */ if (!force_id) { - company = dme1737_read(client, DME1737_REG_COMPANY); - device = dme1737_read(client, DME1737_REG_DEVICE); + company = dme1737_read(data, DME1737_REG_COMPANY); + device = dme1737_read(data, DME1737_REG_DEVICE); if (!((company == DME1737_COMPANY_SMSC) && (device == SCH311X_DEVICE))) { @@ -2441,10 +2437,10 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev) data->type = sch311x; /* Fill in the remaining client fields and initialize the mutex */ - strlcpy(client->name, "sch311x", I2C_NAME_SIZE); + data->name = "sch311x"; mutex_init(&data->update_lock); - dev_info(dev, "Found a SCH311x chip at 0x%04x\n", client->addr); + dev_info(dev, "Found a SCH311x chip at 0x%04x\n", data->addr); /* Initialize the chip */ if ((err = dme1737_init_device(dev))) { @@ -2485,7 +2481,7 @@ static int __devexit dme1737_isa_remove(struct platform_device *pdev) hwmon_device_unregister(data->hwmon_dev); dme1737_remove_files(&pdev->dev); - release_region(data->client.addr, DME1737_EXTENT); + release_region(data->addr, DME1737_EXTENT); platform_set_drvdata(pdev, NULL); kfree(data); -- cgit v1.2.3 From 67a37308ae37f8948d3c26f75a18f0ddb77ac198 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 14 Oct 2008 17:30:04 +0200 Subject: hwmon: (dme1737) Convert to a new-style i2c driver The new-style dme1737 driver implements the optional detect() callback to cover the use cases of the legacy driver. I don't actually expect any new-style device for that driver, but as the old i2c API is going away soon, we have to switch to the new one. Signed-off-by: Jean Delvare Cc: Juerg Haefliger --- drivers/hwmon/dme1737.c | 106 ++++++++++++++++++++++-------------------------- 1 file changed, 48 insertions(+), 58 deletions(-) diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c index 2bf97e1470c..27a5d397f9a 100644 --- a/drivers/hwmon/dme1737.c +++ b/drivers/hwmon/dme1737.c @@ -176,7 +176,6 @@ static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23}; * --------------------------------------------------------------------- */ struct dme1737_data { - struct i2c_client _client; /* will go away soon */ struct i2c_client *client; /* for I2C devices only */ struct device *hwmon_dev; const char *name; @@ -2188,38 +2187,24 @@ exit: return err; } -static int dme1737_i2c_detect(struct i2c_adapter *adapter, int address, - int kind) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int dme1737_i2c_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) { + struct i2c_adapter *adapter = client->adapter; + struct device *dev = &adapter->dev; u8 company, verstep = 0; - struct i2c_client *client; - struct dme1737_data *data; - struct device *dev; - int err = 0; const char *name; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { - goto exit; - } - - if (!(data = kzalloc(sizeof(struct dme1737_data), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; + return -ENODEV; } - client = &data->_client; - data->client = client; - i2c_set_clientdata(client, data); - client->addr = address; - client->adapter = adapter; - client->driver = &dme1737_i2c_driver; - dev = &client->dev; - /* A negative kind means that the driver was loaded with no force * parameter (default), so we must identify the chip. */ if (kind < 0) { - company = dme1737_read(data, DME1737_REG_COMPANY); - verstep = dme1737_read(data, DME1737_REG_VERSTEP); + company = i2c_smbus_read_byte_data(client, DME1737_REG_COMPANY); + verstep = i2c_smbus_read_byte_data(client, DME1737_REG_VERSTEP); if (company == DME1737_COMPANY_SMSC && (verstep & DME1737_VERSTEP_MASK) == DME1737_VERSTEP) { @@ -2228,8 +2213,7 @@ static int dme1737_i2c_detect(struct i2c_adapter *adapter, int address, verstep == SCH5027_VERSTEP) { kind = sch5027; } else { - err = -ENODEV; - goto exit_kfree; + return -ENODEV; } } @@ -2239,33 +2223,44 @@ static int dme1737_i2c_detect(struct i2c_adapter *adapter, int address, kind = dme1737; name = "dme1737"; } - data->type = kind; - - /* Fill in the remaining client fields and put it into the global - * list */ - strlcpy(client->name, name, I2C_NAME_SIZE); - data->name = client->name; - mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(client))) { - goto exit_kfree; - } dev_info(dev, "Found a %s chip at 0x%02x (rev 0x%02x).\n", kind == sch5027 ? "SCH5027" : "DME1737", client->addr, verstep); + strlcpy(info->type, name, I2C_NAME_SIZE); + + return 0; +} + +static int dme1737_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct dme1737_data *data; + struct device *dev = &client->dev; + int err; + + data = kzalloc(sizeof(struct dme1737_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->type = id->driver_data; + data->client = client; + data->name = client->name; + mutex_init(&data->update_lock); /* Initialize the DME1737 chip */ if ((err = dme1737_init_device(dev))) { dev_err(dev, "Failed to initialize device.\n"); - goto exit_detach; + goto exit_kfree; } /* Create sysfs files */ if ((err = dme1737_create_files(dev))) { dev_err(dev, "Failed to create sysfs files.\n"); - goto exit_detach; + goto exit_kfree; } /* Register device */ @@ -2280,45 +2275,40 @@ static int dme1737_i2c_detect(struct i2c_adapter *adapter, int address, exit_remove: dme1737_remove_files(dev); -exit_detach: - i2c_detach_client(client); exit_kfree: kfree(data); exit: return err; } -static int dme1737_i2c_attach_adapter(struct i2c_adapter *adapter) -{ - if (!(adapter->class & I2C_CLASS_HWMON)) { - return 0; - } - - return i2c_probe(adapter, &addr_data, dme1737_i2c_detect); -} - -static int dme1737_i2c_detach_client(struct i2c_client *client) +static int dme1737_i2c_remove(struct i2c_client *client) { struct dme1737_data *data = i2c_get_clientdata(client); - int err; hwmon_device_unregister(data->hwmon_dev); dme1737_remove_files(&client->dev); - if ((err = i2c_detach_client(client))) { - return err; - } - kfree(data); return 0; } +static const struct i2c_device_id dme1737_id[] = { + { "dme1737", dme1737 }, + { "sch5027", sch5027 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, dme1737_id); + static struct i2c_driver dme1737_i2c_driver = { + .class = I2C_CLASS_HWMON, .driver = { .name = "dme1737", }, - .attach_adapter = dme1737_i2c_attach_adapter, - .detach_client = dme1737_i2c_detach_client, + .probe = dme1737_i2c_probe, + .remove = dme1737_i2c_remove, + .id_table = dme1737_id, + .detect = dme1737_i2c_detect, + .address_data = &addr_data, }; /* --------------------------------------------------------------------- -- cgit v1.2.3 From 9def255631bb742264d334d77819e1ae5278a515 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 14 Oct 2008 17:30:04 +0200 Subject: i2c-parport-light: Don't register a platform device resource The i2c-parport-light driver isn't a real platform driver, so it should not instantiate platform devices with resources. The resource management system can't cope with colliding resources, and we are likely to create such a colliding resource. So, better just try to grab the I/O ports we need right at module initialization time, and bail out if we can't. It has the added benefit that the module will no longer load if it isn't going to work, which is definitely more user-friendly. Signed-off-by: Jean Delvare --- drivers/i2c/busses/i2c-parport-light.c | 39 +++++++--------------------------- 1 file changed, 8 insertions(+), 31 deletions(-) diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c index c6faf9bdad1..b2b8380f660 100644 --- a/drivers/i2c/busses/i2c-parport-light.c +++ b/drivers/i2c/busses/i2c-parport-light.c @@ -123,11 +123,6 @@ static struct i2c_adapter parport_adapter = { static int __devinit i2c_parport_probe(struct platform_device *pdev) { int err; - struct resource *res; - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!request_region(res->start, res->end - res->start + 1, DRVNAME)) - return -EBUSY; /* Reset hardware to a sane state (SCL and SDA high) */ parport_setsda(NULL, 1); @@ -138,29 +133,19 @@ static int __devinit i2c_parport_probe(struct platform_device *pdev) parport_adapter.dev.parent = &pdev->dev; err = i2c_bit_add_bus(&parport_adapter); - if (err) { + if (err) dev_err(&pdev->dev, "Unable to register with I2C\n"); - goto exit_region; - } - return 0; - -exit_region: - release_region(res->start, res->end - res->start + 1); return err; } static int __devexit i2c_parport_remove(struct platform_device *pdev) { - struct resource *res; - i2c_del_adapter(&parport_adapter); /* Un-init if needed (power off...) */ if (adapter_parm[type].init.val) line_set(0, &adapter_parm[type].init); - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - release_region(res->start, res->end - res->start + 1); return 0; } @@ -175,12 +160,6 @@ static struct platform_driver i2c_parport_driver = { static int __init i2c_parport_device_add(u16 address) { - struct resource res = { - .start = address, - .end = address + 2, - .name = DRVNAME, - .flags = IORESOURCE_IO, - }; int err; pdev = platform_device_alloc(DRVNAME, -1); @@ -190,13 +169,6 @@ static int __init i2c_parport_device_add(u16 address) goto exit; } - err = platform_device_add_resources(pdev, &res, 1); - if (err) { - printk(KERN_ERR DRVNAME ": Device resource addition failed " - "(%d)\n", err); - goto exit_device_put; - } - err = platform_device_add(pdev); if (err) { printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", @@ -231,13 +203,16 @@ static int __init i2c_parport_init(void) base = DEFAULT_BASE; } + if (!request_region(base, 3, DRVNAME)) + return -EBUSY; + if (!adapter_parm[type].getscl.val) parport_algo_data.getscl = NULL; /* Sets global pdev as a side effect */ err = i2c_parport_device_add(base); if (err) - goto exit; + goto exit_release; err = platform_driver_register(&i2c_parport_driver); if (err) @@ -247,7 +222,8 @@ static int __init i2c_parport_init(void) exit_device: platform_device_unregister(pdev); -exit: +exit_release: + release_region(base, 3); return err; } @@ -255,6 +231,7 @@ static void __exit i2c_parport_exit(void) { platform_driver_unregister(&i2c_parport_driver); platform_device_unregister(pdev); + release_region(base, 3); } MODULE_AUTHOR("Jean Delvare "); -- cgit v1.2.3 From fceb2d06800ddae53095f63843d85fcff4f701ac Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 14 Oct 2008 17:30:05 +0200 Subject: i2c: Improve dev-interface documentation * Clarify some points. * Point developers to i2c-tools instead of lm_sensors. * Fix coding style in code examples. Signed-off-by: Jean Delvare --- Documentation/i2c/dev-interface | 65 +++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/Documentation/i2c/dev-interface b/Documentation/i2c/dev-interface index 9dd79123ddd..689a79ea5ce 100644 --- a/Documentation/i2c/dev-interface +++ b/Documentation/i2c/dev-interface @@ -4,6 +4,10 @@ the /dev interface. You need to load module i2c-dev for this. Each registered i2c adapter gets a number, counting from 0. You can examine /sys/class/i2c-dev/ to see what number corresponds to which adapter. +Alternatively, you can run "i2cdetect -l" to obtain a formated list of all +i2c adapters present on your system at a given time. i2cdetect is part of +the i2c-tools package. + I2C device files are character device files with major device number 89 and a minor device number corresponding to the number assigned as explained above. They should be called "i2c-%d" (i2c-0, i2c-1, ..., @@ -17,30 +21,34 @@ So let's say you want to access an i2c adapter from a C program. The first thing to do is "#include ". Please note that there are two files named "i2c-dev.h" out there, one is distributed with the Linux kernel and is meant to be included from kernel -driver code, the other one is distributed with lm_sensors and is +driver code, the other one is distributed with i2c-tools and is meant to be included from user-space programs. You obviously want the second one here. Now, you have to decide which adapter you want to access. You should -inspect /sys/class/i2c-dev/ to decide this. Adapter numbers are assigned -somewhat dynamically, so you can not even assume /dev/i2c-0 is the -first adapter. +inspect /sys/class/i2c-dev/ or run "i2cdetect -l" to decide this. +Adapter numbers are assigned somewhat dynamically, so you can not +assume much about them. They can even change from one boot to the next. Next thing, open the device file, as follows: + int file; int adapter_nr = 2; /* probably dynamically determined */ char filename[20]; - sprintf(filename,"/dev/i2c-%d",adapter_nr); - if ((file = open(filename,O_RDWR)) < 0) { + snprintf(filename, 19, "/dev/i2c-%d", adapter_nr); + file = open(filename, O_RDWR); + if (file < 0) { /* ERROR HANDLING; you can check errno to see what went wrong */ exit(1); } When you have opened the device, you must specify with what device address you want to communicate: + int addr = 0x40; /* The I2C address */ - if (ioctl(file,I2C_SLAVE,addr) < 0) { + + if (ioctl(file, I2C_SLAVE, addr) < 0) { /* ERROR HANDLING; you can check errno to see what went wrong */ exit(1); } @@ -48,31 +56,41 @@ address you want to communicate: Well, you are all set up now. You can now use SMBus commands or plain I2C to communicate with your device. SMBus commands are preferred if the device supports them. Both are illustrated below. + __u8 register = 0x10; /* Device register to access */ __s32 res; char buf[10]; + /* Using SMBus commands */ - res = i2c_smbus_read_word_data(file,register); + res = i2c_smbus_read_word_data(file, register); if (res < 0) { /* ERROR HANDLING: i2c transaction failed */ } else { /* res contains the read word */ } + /* Using I2C Write, equivalent of - i2c_smbus_write_word_data(file,register,0x6543) */ + i2c_smbus_write_word_data(file, register, 0x6543) */ buf[0] = register; buf[1] = 0x43; buf[2] = 0x65; - if ( write(file,buf,3) != 3) { + if (write(file, buf, 3) ! =3) { /* ERROR HANDLING: i2c transaction failed */ } + /* Using I2C Read, equivalent of i2c_smbus_read_byte(file) */ - if (read(file,buf,1) != 1) { + if (read(file, buf, 1) != 1) { /* ERROR HANDLING: i2c transaction failed */ } else { /* buf[0] contains the read byte */ } +Note that only a subset of the I2C and SMBus protocols can be achieved by +the means of read() and write() calls. In particular, so-called combined +transactions (mixing read and write messages in the same transaction) +aren't supported. For this reason, this interface is almost never used by +user-space programs. + IMPORTANT: because of the use of inline functions, you *have* to use '-O' or some variation when you compile your program! @@ -80,31 +98,29 @@ IMPORTANT: because of the use of inline functions, you *have* to use Full interface description ========================== -The following IOCTLs are defined and fully supported -(see also i2c-dev.h): +The following IOCTLs are defined: -ioctl(file,I2C_SLAVE,long addr) +ioctl(file, I2C_SLAVE, long addr) Change slave address. The address is passed in the 7 lower bits of the argument (except for 10 bit addresses, passed in the 10 lower bits in this case). -ioctl(file,I2C_TENBIT,long select) +ioctl(file, I2C_TENBIT, long select) Selects ten bit addresses if select not equals 0, selects normal 7 bit addresses if select equals 0. Default 0. This request is only valid if the adapter has I2C_FUNC_10BIT_ADDR. -ioctl(file,I2C_PEC,long select) +ioctl(file, I2C_PEC, long select) Selects SMBus PEC (packet error checking) generation and verification if select not equals 0, disables if select equals 0. Default 0. Used only for SMBus transactions. This request only has an effect if the the adapter has I2C_FUNC_SMBUS_PEC; it is still safe if not, it just doesn't have any effect. -ioctl(file,I2C_FUNCS,unsigned long *funcs) +ioctl(file, I2C_FUNCS, unsigned long *funcs) Gets the adapter functionality and puts it in *funcs. -ioctl(file,I2C_RDWR,struct i2c_rdwr_ioctl_data *msgset) - +ioctl(file, I2C_RDWR, struct i2c_rdwr_ioctl_data *msgset) Do combined read/write transaction without stop in between. Only valid if the adapter has I2C_FUNC_I2C. The argument is a pointer to a @@ -120,10 +136,9 @@ ioctl(file,I2C_RDWR,struct i2c_rdwr_ioctl_data *msgset) The slave address and whether to use ten bit address mode has to be set in each message, overriding the values set with the above ioctl's. - -Other values are NOT supported at this moment, except for I2C_SMBUS, -which you should never directly call; instead, use the access functions -below. +ioctl(file, I2C_SMBUS, struct i2c_smbus_ioctl_data *args) + Not meant to be called directly; instead, use the access functions + below. You can do plain i2c transactions by using read(2) and write(2) calls. You do not need to pass the address byte; instead, set it through @@ -148,7 +163,7 @@ what happened. The 'write' transactions return 0 on success; the returns the number of values read. The block buffers need not be longer than 32 bytes. -The above functions are all macros, that resolve to calls to the -i2c_smbus_access function, that on its turn calls a specific ioctl +The above functions are all inline functions, that resolve to calls to +the i2c_smbus_access function, that on its turn calls a specific ioctl with the data in a specific format. Read the source code if you want to know what happens behind the screens. -- cgit v1.2.3 From 7c15fd1249658e203b2ac8661e48da6c2102e563 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 14 Oct 2008 17:30:05 +0200 Subject: i2c: Document the implementation details of the /dev interface I wrote this explanation to answer a question on the i2c mailing list, and thought it would be good to have in the kernel documentation. Signed-off-by: Jean Delvare --- Documentation/i2c/dev-interface | 45 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/Documentation/i2c/dev-interface b/Documentation/i2c/dev-interface index 689a79ea5ce..3e742ba2553 100644 --- a/Documentation/i2c/dev-interface +++ b/Documentation/i2c/dev-interface @@ -167,3 +167,48 @@ The above functions are all inline functions, that resolve to calls to the i2c_smbus_access function, that on its turn calls a specific ioctl with the data in a specific format. Read the source code if you want to know what happens behind the screens. + + +Implementation details +====================== + +For the interested, here's the code flow which happens inside the kernel +when you use the /dev interface to I2C: + +1* Your program opens /dev/i2c-N and calls ioctl() on it, as described in +section "C example" above. + +2* These open() and ioctl() calls are handled by the i2c-dev kernel +driver: see i2c-dev.c:i2cdev_open() and i2c-dev.c:i2cdev_ioctl(), +respectively. You can think of i2c-dev as a generic I2C chip driver +that can be programmed from user-space. + +3* Some ioctl() calls are for administrative tasks and are handled by +i2c-dev directly. Examples include I2C_SLAVE (set the address of the +device you want to access) and I2C_PEC (enable or disable SMBus error +checking on future transactions.) + +4* Other ioctl() calls are converted to in-kernel function calls by +i2c-dev. Examples include I2C_FUNCS, which queries the I2C adapter +functionality using i2c.h:i2c_get_functionality(), and I2C_SMBUS, which +performs an SMBus transaction using i2c-core.c:i2c_smbus_xfer(). + +The i2c-dev driver is responsible for checking all the parameters that +come from user-space for validity. After this point, there is no +difference between these calls that came from user-space through i2c-dev +and calls that would have been performed by kernel I2C chip drivers +directly. This means that I2C bus drivers don't need to implement +anything special to support access from user-space. + +5* These i2c-core.c/i2c.h functions are wrappers to the actual +implementation of your I2C bus driver. Each adapter must declare +callback functions implementing these standard calls. +i2c.h:i2c_get_functionality() calls i2c_adapter.algo->functionality(), +while i2c-core.c:i2c_smbus_xfer() calls either +adapter.algo->smbus_xfer() if it is implemented, or if not, +i2c-core.c:i2c_smbus_xfer_emulated() which in turn calls +i2c_adapter.algo->master_xfer(). + +After your I2C bus driver has processed these requests, execution runs +up the call chain, with almost no processing done, except by i2c-dev to +package the returned data, if any, in suitable format for the ioctl. -- cgit v1.2.3 From 1d0b19c9a0612c653d1a0df267ba159089f6d139 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 14 Oct 2008 17:30:05 +0200 Subject: i2c: Guard against oopses from bad init sequences Guard I2C against oopsing because of init sequence problems, by verifying that i2c_init() has been called before calling any routines that rely on that initialization. This specific test just requires that bus_register(&i2c_bus_type) was called. Examples of this kind of oopsing come from subystems and drivers which register I2C drivers in their subsys_initcall code but which are statically linked before I2C by drivers/Makefile. Signed-off-by: David Brownell Signed-off-by: Jean Delvare --- drivers/i2c/i2c-core.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index b346a687ab5..a96e1bf2764 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -437,6 +437,10 @@ static int i2c_register_adapter(struct i2c_adapter *adap) { int res = 0, dummy; + /* Can't register until after driver model init */ + if (unlikely(WARN_ON(!i2c_bus_type.p))) + return -EAGAIN; + mutex_init(&adap->bus_lock); mutex_init(&adap->clist_lock); INIT_LIST_HEAD(&adap->clients); @@ -696,6 +700,10 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) { int res; + /* Can't register until after driver model init */ + if (unlikely(WARN_ON(!i2c_bus_type.p))) + return -EAGAIN; + /* new style driver methods can't mix with legacy ones */ if (is_newstyle_driver(driver)) { if (driver->attach_adapter || driver->detach_adapter -- cgit v1.2.3 From f1453ee3a4da94250849606882948c590a4ad8dd Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 14 Oct 2008 17:30:06 +0200 Subject: i2c: Only build Tyan SMBus mux drivers on x86 The two Tyan SMBus mux drivers (i2c-amd756-s4882 and i2c-nforce2-s4985) are only useful on specific x86 motherboards, so there is no point in letting them be built on other architectures. Signed-off-by: Jean Delvare --- drivers/i2c/busses/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index b32164cfbc4..acadbc51fc0 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -55,7 +55,7 @@ config I2C_AMD756 config I2C_AMD756_S4882 tristate "SMBus multiplexing on the Tyan S4882" - depends on I2C_AMD756 && EXPERIMENTAL + depends on I2C_AMD756 && X86 && EXPERIMENTAL help Enabling this option will add specific SMBus support for the Tyan S4882 motherboard. On this 4-CPU board, the SMBus is multiplexed @@ -148,7 +148,7 @@ config I2C_NFORCE2 config I2C_NFORCE2_S4985 tristate "SMBus multiplexing on the Tyan S4985" - depends on I2C_NFORCE2 && EXPERIMENTAL + depends on I2C_NFORCE2 && X86 && EXPERIMENTAL help Enabling this option will add specific SMBus support for the Tyan S4985 motherboard. On this 4-CPU board, the SMBus is multiplexed -- cgit v1.2.3 From a10f9e7caf8d3028d8fb1d4c3d590492cde3df3e Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 14 Oct 2008 17:30:06 +0200 Subject: i2c: Do earlier driver model init Move I2C driver model init earlier in the boot sequence. This avoids oopsing in statically linked systems when some subsystems register I2C drivers in subsys_initcall() code, but those subsystems are linked (and initialized) before I2C. Signed-off-by: David Brownell Signed-off-by: Jean Delvare --- drivers/i2c/i2c-core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index a96e1bf2764..80ae12048e8 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -986,7 +986,10 @@ static void __exit i2c_exit(void) bus_unregister(&i2c_bus_type); } -subsys_initcall(i2c_init); +/* We must initialize early, because some subsystems register i2c drivers + * in subsys_initcall() code, but are linked (and initialized) before i2c. + */ +postcore_initcall(i2c_init); module_exit(i2c_exit); /* ---------------------------------------------------- -- cgit v1.2.3 From 596c88f4601e6245a15ea7619527674abbfdcf92 Mon Sep 17 00:00:00 2001 From: Prakash Mortha Date: Tue, 14 Oct 2008 17:30:06 +0200 Subject: i2c: Restore i2c_smbus_process_call function Restore the i2c_smbus_process_call() as one driver (for the Micronas MAP5401) will need it soon. [JD: Update documentation accordingly.] Signed-off-by: Prakash Mortha Signed-off-by: Jean Delvare --- Documentation/i2c/smbus-protocol | 4 ++-- Documentation/i2c/writing-clients | 4 ++-- drivers/i2c/i2c-core.c | 22 ++++++++++++++++++++++ 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/Documentation/i2c/smbus-protocol b/Documentation/i2c/smbus-protocol index 24bfb65da17..9df47441f0e 100644 --- a/Documentation/i2c/smbus-protocol +++ b/Documentation/i2c/smbus-protocol @@ -109,8 +109,8 @@ specified through the Comm byte. S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P -SMBus Process Call -================== +SMBus Process Call: i2c_smbus_process_call() +============================================= This command selects a device register (through the Comm byte), sends 16 bits of data to it, and reads 16 bits of data in return. diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients index 6b61b3a2e90..d73ee117a8c 100644 --- a/Documentation/i2c/writing-clients +++ b/Documentation/i2c/writing-clients @@ -606,6 +606,8 @@ SMBus communication extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command); extern s32 i2c_smbus_write_word_data(struct i2c_client * client, u8 command, u16 value); + extern s32 i2c_smbus_process_call(struct i2c_client *client, + u8 command, u16 value); extern s32 i2c_smbus_read_block_data(struct i2c_client * client, u8 command, u8 *values); extern s32 i2c_smbus_write_block_data(struct i2c_client * client, @@ -621,8 +623,6 @@ These ones were removed from i2c-core because they had no users, but could be added back later if needed: extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value); - extern s32 i2c_smbus_process_call(struct i2c_client * client, - u8 command, u16 value); extern s32 i2c_smbus_block_process_call(struct i2c_client *client, u8 command, u8 length, u8 *values) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 80ae12048e8..42e852d79ff 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1687,6 +1687,28 @@ s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value) } EXPORT_SYMBOL(i2c_smbus_write_word_data); +/** + * i2c_smbus_process_call - SMBus "process call" protocol + * @client: Handle to slave device + * @command: Byte interpreted by slave + * @value: 16-bit "word" being written + * + * This executes the SMBus "process call" protocol, returning negative errno + * else a 16-bit unsigned "word" received from the device. + */ +s32 i2c_smbus_process_call(struct i2c_client *client, u8 command, u16 value) +{ + union i2c_smbus_data data; + int status; + data.word = value; + + status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, + I2C_SMBUS_WRITE, command, + I2C_SMBUS_PROC_CALL, &data); + return (status < 0) ? status : data.word; +} +EXPORT_SYMBOL(i2c_smbus_process_call); + /** * i2c_smbus_read_block_data - SMBus "block read" protocol * @client: Handle to slave device -- cgit v1.2.3 From a05f2c5a2735ee1d68770137fbbfc334d3b9cda9 Mon Sep 17 00:00:00 2001 From: Prakash Mortha Date: Tue, 14 Oct 2008 17:30:06 +0200 Subject: i2c-viapro: Add support for SMBus Process Call transactions Add support for SMBus Process Call transactions. These are combined word write, word read transactions. Signed-off-by: Prakash Mortha Signed-off-by: Jean Delvare --- drivers/i2c/busses/i2c-viapro.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c index 1345da97b23..73dc52e114e 100644 --- a/drivers/i2c/busses/i2c-viapro.c +++ b/drivers/i2c/busses/i2c-viapro.c @@ -83,6 +83,7 @@ static unsigned short SMBHSTCFG = 0xD2; #define VT596_BYTE 0x04 #define VT596_BYTE_DATA 0x08 #define VT596_WORD_DATA 0x0C +#define VT596_PROC_CALL 0x10 #define VT596_BLOCK_DATA 0x14 #define VT596_I2C_BLOCK_DATA 0x34 @@ -233,6 +234,12 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr, } size = VT596_WORD_DATA; break; + case I2C_SMBUS_PROC_CALL: + outb_p(command, SMBHSTCMD); + outb_p(data->word & 0xff, SMBHSTDAT0); + outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); + size = VT596_PROC_CALL; + break; case I2C_SMBUS_I2C_BLOCK_DATA: if (!(vt596_features & FEATURE_I2CBLOCK)) goto exit_unsupported; @@ -263,6 +270,9 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr, if (status) return status; + if (size == VT596_PROC_CALL) + read_write = I2C_SMBUS_READ; + if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK)) return 0; @@ -272,6 +282,7 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr, data->byte = inb_p(SMBHSTDAT0); break; case VT596_WORD_DATA: + case VT596_PROC_CALL: data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); break; case VT596_I2C_BLOCK_DATA: @@ -296,7 +307,7 @@ static u32 vt596_func(struct i2c_adapter *adapter) { u32 func = I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA; + I2C_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_DATA; if (vt596_features & FEATURE_I2CBLOCK) func |= I2C_FUNC_SMBUS_I2C_BLOCK; -- cgit v1.2.3