* [BK PATCH] I2C update for 2.6.7-rc1 @ 2004-05-28 21:59 Greg KH 2004-05-28 22:00 ` [PATCH] " Greg KH 0 siblings, 1 reply; 9+ messages in thread From: Greg KH @ 2004-05-28 21:59 UTC (permalink / raw) To: torvalds, akpm; +Cc: linux-kernel, sensors Hi, Here are some i2c driver fixes for 2.6.7-rc1. There is also a new i2c chip driver in here. The majority of these patches have been in the past few -mm releases. Please pull from: bk://kernel.bkbits.net/gregkh/linux/i2c-2.6 Individual patches will follow, sent to the sensors and linux-kernel lists. thanks, greg k-h drivers/i2c/busses/Kconfig | 8 drivers/i2c/busses/i2c-ibm_iic.c | 48 +++- drivers/i2c/busses/i2c-parport.h | 14 + drivers/i2c/chips/Kconfig | 10 + drivers/i2c/chips/Makefile | 1 drivers/i2c/chips/eeprom.c | 5 drivers/i2c/chips/max1619.c | 378 +++++++++++++++++++++++++++++++++++++++ drivers/i2c/i2c-core.c | 21 +- 8 files changed, 457 insertions(+), 28 deletions(-) ----- <faikuygur:tnn.net>: o I2C: use idr_get_new to allocate a bus id in drivers/i2c/i2c-core.c <fishor:gmx.net>: o I2C: add max1619 driver Eugene Surovegin: o I2C PPC4xx IIC driver: 0-length transaction temporary fix o I2C PPC4xx IIC driver: fix debug build with gcc3 o I2C PPC4xx IIC driver: Kconfig cleanup o I2C PPC4xx IIC driver: upgrade to new OCP infrastructre Jean Delvare: o I2C: i2c-parport: support the ADM1031 evaluation board o I2C: Incomplete AT24RF08 corruption prevention in i2c eeprom ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH] I2C update for 2.6.7-rc1 2004-05-28 21:59 [BK PATCH] I2C update for 2.6.7-rc1 Greg KH @ 2004-05-28 22:00 ` Greg KH 2004-05-28 22:00 ` Greg KH 0 siblings, 1 reply; 9+ messages in thread From: Greg KH @ 2004-05-28 22:00 UTC (permalink / raw) To: linux-kernel, sensors ChangeSet 1.1717.6.23, 2004/05/19 00:24:54-07:00, faikuygur@tnn.net [PATCH] I2C: use idr_get_new to allocate a bus id in drivers/i2c/i2c-core.c drivers/i2c/i2c-core.c | 21 +++++++++++++++++---- 1 files changed, 17 insertions(+), 4 deletions(-) diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c --- a/drivers/i2c/i2c-core.c Fri May 28 14:52:36 2004 +++ b/drivers/i2c/i2c-core.c Fri May 28 14:52:36 2004 @@ -28,6 +28,7 @@ #include <linux/slab.h> #include <linux/i2c.h> #include <linux/init.h> +#include <linux/idr.h> #include <linux/seq_file.h> #include <asm/uaccess.h> @@ -35,6 +36,7 @@ static LIST_HEAD(adapters); static LIST_HEAD(drivers); static DECLARE_MUTEX(core_lists); +static DEFINE_IDR(i2c_adapter_idr); int i2c_device_probe(struct device *dev) { @@ -113,13 +115,19 @@ */ int i2c_add_adapter(struct i2c_adapter *adap) { - static int nr = 0; + int id, res = 0; struct list_head *item; struct i2c_driver *driver; down(&core_lists); - adap->nr = nr++; + if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) { + res = -ENOMEM; + goto out_unlock; + } + + id = idr_get_new(&i2c_adapter_idr, NULL); + adap->nr = id & MAX_ID_MASK; init_MUTEX(&adap->bus_lock); init_MUTEX(&adap->clist_lock); list_add_tail(&adap->list,&adapters); @@ -151,10 +159,12 @@ /* We ignore the return code; if it fails, too bad */ driver->attach_adapter(adap); } - up(&core_lists); dev_dbg(&adap->dev, "registered as adapter #%d\n", adap->nr); - return 0; + + out_unlock: + up(&core_lists); + return res; } @@ -207,6 +217,9 @@ /* wait for sysfs to drop all references */ wait_for_completion(&adap->dev_released); wait_for_completion(&adap->class_dev_released); + + /* free dynamically allocated bus id */ + idr_remove(&i2c_adapter_idr, adap->nr); dev_dbg(&adap->dev, "adapter unregistered\n"); ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] I2C update for 2.6.7-rc1 2004-05-28 22:00 ` [PATCH] " Greg KH @ 2004-05-28 22:00 ` Greg KH 2004-05-28 22:00 ` Greg KH 0 siblings, 1 reply; 9+ messages in thread From: Greg KH @ 2004-05-28 22:00 UTC (permalink / raw) To: linux-kernel, sensors ChangeSet 1.1717.6.24, 2004/05/19 00:25:14-07:00, khali@linux-fr.org [PATCH] I2C: Incomplete AT24RF08 corruption prevention in i2c eeprom The AT24RF08 corruption prevention trick that is found in the i2c eeprom driver is not correct. The prevention is activated only conditionally, while it should be done all the time. drivers/i2c/chips/eeprom.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff -Nru a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c --- a/drivers/i2c/chips/eeprom.c Fri May 28 14:52:32 2004 +++ b/drivers/i2c/chips/eeprom.c Fri May 28 14:52:32 2004 @@ -203,11 +203,12 @@ new_client->driver = &eeprom_driver; new_client->flags = 0; + /* prevent 24RF08 corruption */ + i2c_smbus_write_quick(new_client, 0); + /* Now, we do the remaining detection. It is not there, unless you force the checksum to work out. */ if (checksum) { - /* prevent 24RF08 corruption */ - i2c_smbus_write_quick(new_client, 0); cs = 0; for (i = 0; i <= 0x3e; i++) cs += i2c_smbus_read_byte_data(new_client, i); ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] I2C update for 2.6.7-rc1 2004-05-28 22:00 ` Greg KH @ 2004-05-28 22:00 ` Greg KH 2004-05-28 22:00 ` Greg KH 0 siblings, 1 reply; 9+ messages in thread From: Greg KH @ 2004-05-28 22:00 UTC (permalink / raw) To: linux-kernel, sensors ChangeSet 1.1717.6.25, 2004/05/19 00:25:35-07:00, ebs@ebshome.net [PATCH] I2C PPC4xx IIC driver: upgrade to new OCP infrastructre this patch changes IBM PPC4xx IIC driver to support new PPC OCP infrastructure recently added to 2.6 kernel. drivers/i2c/busses/i2c-ibm_iic.c | 30 +++++++++++++++++------------- 1 files changed, 17 insertions(+), 13 deletions(-) diff -Nru a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c --- a/drivers/i2c/busses/i2c-ibm_iic.c Fri May 28 14:52:27 2004 +++ b/drivers/i2c/busses/i2c-ibm_iic.c Fri May 28 14:52:27 2004 @@ -3,7 +3,7 @@ * * Support for the IIC peripheral on IBM PPC 4xx * - * Copyright (c) 2003 Zultys Technologies. + * Copyright (c) 2003, 2004 Zultys Technologies. * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> * * Based on original work by @@ -45,7 +45,7 @@ #include "i2c-ibm_iic.h" -#define DRIVER_VERSION "2.0" +#define DRIVER_VERSION "2.01" MODULE_DESCRIPTION("IBM IIC driver v" DRIVER_VERSION); MODULE_LICENSE("GPL"); @@ -549,19 +549,24 @@ struct ibm_iic_private* dev; struct i2c_adapter* adap; + struct ocp_func_iic_data* iic_data = ocp->def->additions; int ret; - bd_t* bd = (bd_t*)&__res; + if (!iic_data) + printk(KERN_WARNING"ibm-iic%d: missing additional data!\n", + ocp->def->index); + if (!(dev = kmalloc(sizeof(*dev), GFP_KERNEL))){ - printk(KERN_CRIT "ibm-iic: failed to allocate device data\n"); + printk(KERN_CRIT "ibm-iic%d: failed to allocate device data\n", + ocp->def->index); return -ENOMEM; } memset(dev, 0, sizeof(*dev)); - dev->idx = ocp->num; + dev->idx = ocp->def->index; ocp_set_drvdata(ocp, dev); - if (!(dev->vaddr = ioremap(ocp->paddr, sizeof(struct iic_regs)))){ + if (!(dev->vaddr = ioremap(ocp->def->paddr, sizeof(struct iic_regs)))){ printk(KERN_CRIT "ibm-iic%d: failed to ioremap device registers\n", dev->idx); ret = -ENXIO; @@ -570,7 +575,7 @@ init_waitqueue_head(&dev->wq); - dev->irq = iic_force_poll ? -1 : ocp->irq; + dev->irq = iic_force_poll ? -1 : ocp->def->irq; if (dev->irq >= 0){ /* Disable interrupts until we finish intialization, assumes level-sensitive IRQ setup... @@ -589,13 +594,12 @@ dev->idx); /* Board specific settings */ - BUG_ON(dev->idx >= sizeof(bd->bi_iic_fast) / sizeof(bd->bi_iic_fast[0])); - dev->fast_mode = iic_force_fast ? 1 : bd->bi_iic_fast[dev->idx]; + dev->fast_mode = iic_force_fast ? 1 : (iic_data ? iic_data->fast_mode : 0); /* clckdiv is the same for *all* IIC interfaces, * but I'd rather make a copy than introduce another global. --ebs */ - dev->clckdiv = iic_clckdiv(bd->bi_opb_busfreq); + dev->clckdiv = iic_clckdiv(ocp_sys_info.opb_bus_freq); DBG("%d: clckdiv = %d\n", dev->idx, dev->clckdiv); /* Initialize IIC interface */ @@ -664,7 +668,7 @@ static struct ocp_device_id ibm_iic_ids[] __devinitdata = { - { .vendor = OCP_VENDOR_IBM, .device = OCP_FUNC_IIC }, + { .vendor = OCP_VENDOR_IBM, .function = OCP_FUNC_IIC }, { .vendor = OCP_VENDOR_INVALID } }; @@ -672,7 +676,7 @@ static struct ocp_driver ibm_iic_driver = { - .name = "ocp_iic", + .name = "iic", .id_table = ibm_iic_ids, .probe = iic_probe, .remove = __devexit_p(iic_remove), @@ -685,7 +689,7 @@ static int __init iic_init(void) { printk(KERN_INFO "IBM IIC driver v" DRIVER_VERSION "\n"); - return ocp_module_init(&ibm_iic_driver); + return ocp_register_driver(&ibm_iic_driver); } static void __exit iic_exit(void) ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] I2C update for 2.6.7-rc1 2004-05-28 22:00 ` Greg KH @ 2004-05-28 22:00 ` Greg KH 2004-05-28 22:00 ` Greg KH 0 siblings, 1 reply; 9+ messages in thread From: Greg KH @ 2004-05-28 22:00 UTC (permalink / raw) To: linux-kernel, sensors ChangeSet 1.1717.6.26, 2004/05/19 00:25:54-07:00, ebs@ebshome.net [PATCH] I2C PPC4xx IIC driver: Kconfig cleanup this patch renames Kconfig entry for PPC4xx IIC driver making it more clear and also adds a help text. drivers/i2c/busses/Kconfig | 8 +++++++- 1 files changed, 7 insertions(+), 1 deletion(-) diff -Nru a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig --- a/drivers/i2c/busses/Kconfig Fri May 28 14:52:22 2004 +++ b/drivers/i2c/busses/Kconfig Fri May 28 14:52:22 2004 @@ -118,8 +118,14 @@ will be called i2c-i810. config I2C_IBM_IIC - tristate "IBM IIC I2C" + tristate "IBM PPC 4xx on-chip I2C interface" depends on IBM_OCP && I2C + help + Say Y here if you want to use IIC peripheral found on + embedded IBM PPC 4xx based systems. + + This driver can also be built as a module. If so, the module + will be called i2c-ibm_iic. config I2C_IOP3XX tristate "Intel XScale IOP3xx on-chip I2C interface" ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] I2C update for 2.6.7-rc1 2004-05-28 22:00 ` Greg KH @ 2004-05-28 22:00 ` Greg KH 2004-05-28 22:00 ` Greg KH 0 siblings, 1 reply; 9+ messages in thread From: Greg KH @ 2004-05-28 22:00 UTC (permalink / raw) To: linux-kernel, sensors ChangeSet 1.1717.6.27, 2004/05/19 00:26:13-07:00, ebs@ebshome.net [PATCH] I2C PPC4xx IIC driver: fix debug build with gcc3 this patch fixes PPC4xx IIC driver debug mode build with gcc 3.x compiler. Noticed by Evgenij Polyakov. drivers/i2c/busses/i2c-ibm_iic.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff -Nru a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c --- a/drivers/i2c/busses/i2c-ibm_iic.c Fri May 28 14:52:17 2004 +++ b/drivers/i2c/busses/i2c-ibm_iic.c Fri May 28 14:52:17 2004 @@ -69,14 +69,14 @@ #endif #if DBG_LEVEL > 0 -# define DBG(x...) printk(KERN_DEBUG "ibm-iic" ##x) +# define DBG(f,x...) printk(KERN_DEBUG "ibm-iic" f, ##x) #else -# define DBG(x...) ((void)0) +# define DBG(f,x...) ((void)0) #endif #if DBG_LEVEL > 1 -# define DBG2(x...) DBG( ##x ) +# define DBG2(f,x...) DBG(f, ##x) #else -# define DBG2(x...) ((void)0) +# define DBG2(f,x...) ((void)0) #endif #if DBG_LEVEL > 2 static void dump_iic_regs(const char* header, struct ibm_iic_private* dev) ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] I2C update for 2.6.7-rc1 2004-05-28 22:00 ` Greg KH @ 2004-05-28 22:00 ` Greg KH 2004-05-28 22:00 ` Greg KH 0 siblings, 1 reply; 9+ messages in thread From: Greg KH @ 2004-05-28 22:00 UTC (permalink / raw) To: linux-kernel, sensors ChangeSet 1.1717.6.28, 2004/05/19 00:26:34-07:00, ebs@ebshome.net [PATCH] I2C PPC4xx IIC driver: 0-length transaction temporary fix this patch adds temporary fix for 0-length requests (e.g. SMBUS_QUICK) to PPC4xx IIC driver. This i2c controller doesn't support such transactions and this patch just restores previous driver version behavior making SMBUS_QUICK-based bus scan at least partially usable. This is temporary kludge until correct bit-banging emulation is implemented. drivers/i2c/busses/i2c-ibm_iic.c | 10 ++++++++++ 1 files changed, 10 insertions(+) diff -Nru a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c --- a/drivers/i2c/busses/i2c-ibm_iic.c Fri May 28 14:52:12 2004 +++ b/drivers/i2c/busses/i2c-ibm_iic.c Fri May 28 14:52:12 2004 @@ -455,6 +455,16 @@ } for (i = 0; i < num; ++i){ if (unlikely(msgs[i].len <= 0)){ + if (num == 1 && !msgs[0].len){ + /* Special case for I2C_SMBUS_QUICK emulation. + * Although this logic is FAR FROM PERFECT, this + * is what previous driver version did. + * IBM IIC doesn't support 0-length transactions + * (except bit-banging through IICx_DIRECTCNTL). + */ + DBG("%d: zero-length msg kludge\n", dev->idx); + return 0; + } DBG("%d: invalid len %d in msg[%d]\n", dev->idx, msgs[i].len, i); return -EINVAL; ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] I2C update for 2.6.7-rc1 2004-05-28 22:00 ` Greg KH @ 2004-05-28 22:00 ` Greg KH 2004-05-28 22:00 ` Greg KH 0 siblings, 1 reply; 9+ messages in thread From: Greg KH @ 2004-05-28 22:00 UTC (permalink / raw) To: linux-kernel, sensors ChangeSet 1.1717.6.29, 2004/05/28 13:47:51-07:00, khali@linux-fr.org [PATCH] I2C: i2c-parport: support the ADM1031 evaluation board The following patch adds support for the ADM1030 and ADM1031 evaluation boards to the i2c-parport and i2c-parport-light drivers. They are almost compatible with the already supported ADM1025 and ADM1032 boards, except that the ADM1032 board needs some pins to be set high to draw its power, while the same pins power up heating resistors on the ADM1031 board. I considered it was a bit dangerous to do that by default, so I ended up with two different device definitions, one with powering pins set, and one with these pins cleared. Signed-off-by: Greg Kroah-Hartman <greg@kroah.com> drivers/i2c/busses/i2c-parport.h | 14 ++++++++++---- 1 files changed, 10 insertions(+), 4 deletions(-) diff -Nru a/drivers/i2c/busses/i2c-parport.h b/drivers/i2c/busses/i2c-parport.h --- a/drivers/i2c/busses/i2c-parport.h Fri May 28 14:52:07 2004 +++ b/drivers/i2c/busses/i2c-parport.h Fri May 28 14:52:07 2004 @@ -67,13 +67,18 @@ .getsda = { 0x40, STAT, 1 }, .getscl = { 0x08, STAT, 1 }, }, - /* type 4: ADM1025 and ADM1032 evaluation boards */ + /* type 4: ADM1032 evaluation board */ + { + .setsda = { 0x02, DATA, 1 }, + .setscl = { 0x01, DATA, 1 }, + .getsda = { 0x10, STAT, 1 }, + .init = { 0xf0, DATA, 0 }, + }, + /* type 5: ADM1025, ADM1030 and ADM1031 evaluation boards */ { .setsda = { 0x02, DATA, 1 }, .setscl = { 0x01, DATA, 1 }, .getsda = { 0x10, STAT, 1 }, - .init = { 0xf0, DATA, 0 }, /* ADM1025 doesn't need this, - but it doesn't hurt */ }, }; @@ -85,4 +90,5 @@ " 1 = home brew teletext adapter\n" " 2 = Velleman K8000 adapter\n" " 3 = ELV adapter\n" - " 4 = ADM1025 and ADM1032 evaluation boards\n"); + " 4 = ADM1032 evaluation board\n" + " 5 = ADM1025, ADM1030 and ADM1031 evaluation boards\n"); ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] I2C update for 2.6.7-rc1 2004-05-28 22:00 ` Greg KH @ 2004-05-28 22:00 ` Greg KH 0 siblings, 0 replies; 9+ messages in thread From: Greg KH @ 2004-05-28 22:00 UTC (permalink / raw) To: linux-kernel, sensors ChangeSet 1.1717.6.30, 2004/05/28 13:48:49-07:00, fishor@gmx.net [PATCH] I2C: add max1619 driver This is a driver for "Remote/Local Temperature Sensor with Dual-Alarm Outputs and SMBus Serial Interface" MAX1619. I found this chip an my Laptop SAMSUNG NV5000. Daryng I use Linux cooling didn't worked at all, naw with this driwer it's working. I hope this will be usefool for ather too. I didn't hade any expiriens with programming, but i didn't wont to wait wann some body make it vor me. Jean halped me correrct any mysteiks wich i made. Thanks Jaen :) Signed-off-by: Greg Kroah-Hartman <greg@kroah.com> drivers/i2c/chips/Kconfig | 10 + drivers/i2c/chips/Makefile | 1 drivers/i2c/chips/max1619.c | 378 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 389 insertions(+) diff -Nru a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig --- a/drivers/i2c/chips/Kconfig Fri May 28 14:52:02 2004 +++ b/drivers/i2c/chips/Kconfig Fri May 28 14:52:02 2004 @@ -145,6 +145,16 @@ This driver can also be built as a module. If so, the module will be called lm90. +config SENSORS_MAX1619 + tristate "Maxim MAX1619 sensor chip" + depends on I2C && EXPERIMENTAL + select I2C_SENSOR + help + If you say yes here you get support for MAX1619 sensor chip. + + This driver can also be built as a module. If so, the module + will be called max1619. + config SENSORS_VIA686A tristate "VIA686A" depends on I2C && EXPERIMENTAL diff -Nru a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile --- a/drivers/i2c/chips/Makefile Fri May 28 14:52:02 2004 +++ b/drivers/i2c/chips/Makefile Fri May 28 14:52:02 2004 @@ -19,6 +19,7 @@ obj-$(CONFIG_SENSORS_LM83) += lm83.o obj-$(CONFIG_SENSORS_LM85) += lm85.o obj-$(CONFIG_SENSORS_LM90) += lm90.o +obj-$(CONFIG_SENSORS_MAX1619) += max1619.o obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o obj-$(CONFIG_SENSORS_RTC8564) += rtc8564.o diff -Nru a/drivers/i2c/chips/max1619.c b/drivers/i2c/chips/max1619.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/i2c/chips/max1619.c Fri May 28 14:52:02 2004 @@ -0,0 +1,378 @@ +/* + * max1619.c - Part of lm_sensors, Linux kernel modules for hardware + * monitoring + * Copyright (C) 2003-2004 Alexey Fisher <fishor@mail.ru> + * Jean Delvare <khali@linux-fr.org> + * + * Based on the lm90 driver. The MAX1619 is a sensor chip made by Maxim. + * It reports up to two temperatures (its own plus up to + * one external one). Complete datasheet can be + * obtained from Maxim's website at: + * http://pdfserv.maxim-ic.com/en/ds/MAX1619.pdf + * + * 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 <linux/config.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/i2c-sensor.h> + + +static unsigned short normal_i2c[] = { I2C_CLIENT_END }; +static unsigned short normal_i2c_range[] = { 0x18, 0x1a, 0x29, 0x2b, + 0x4c, 0x4e, I2C_CLIENT_END }; +static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END }; +static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END }; + +/* + * Insmod parameters + */ + +SENSORS_INSMOD_1(max1619); + +/* + * The MAX1619 registers + */ + +#define MAX1619_REG_R_MAN_ID 0xFE +#define MAX1619_REG_R_CHIP_ID 0xFF +#define MAX1619_REG_R_CONFIG 0x03 +#define MAX1619_REG_W_CONFIG 0x09 +#define MAX1619_REG_R_CONVRATE 0x04 +#define MAX1619_REG_W_CONVRATE 0x0A +#define MAX1619_REG_R_STATUS 0x02 +#define MAX1619_REG_R_LOCAL_TEMP 0x00 +#define MAX1619_REG_R_REMOTE_TEMP 0x01 +#define MAX1619_REG_R_REMOTE_HIGH 0x07 +#define MAX1619_REG_W_REMOTE_HIGH 0x0D +#define MAX1619_REG_R_REMOTE_LOW 0x08 +#define MAX1619_REG_W_REMOTE_LOW 0x0E +#define MAX1619_REG_R_REMOTE_CRIT 0x10 +#define MAX1619_REG_W_REMOTE_CRIT 0x12 +#define MAX1619_REG_R_TCRIT_HYST 0x11 +#define MAX1619_REG_W_TCRIT_HYST 0x13 + +/* + * Conversions and various macros + */ + +#define TEMP_FROM_REG(val) ((val & 0x80 ? val-0x100 : val) * 1000) +#define TEMP_TO_REG(val) ((val < 0 ? val+0x100*1000 : val) / 1000) + +/* + * Functions declaration + */ + +static int max1619_attach_adapter(struct i2c_adapter *adapter); +static int max1619_detect(struct i2c_adapter *adapter, int address, + int kind); +static void max1619_init_client(struct i2c_client *client); +static int max1619_detach_client(struct i2c_client *client); +static struct max1619_data *max1619_update_device(struct device *dev); + +/* + * Driver data (common to all clients) + */ + +static struct i2c_driver max1619_driver = { + .owner = THIS_MODULE, + .name = "max1619", + .flags = I2C_DF_NOTIFY, + .attach_adapter = max1619_attach_adapter, + .detach_client = max1619_detach_client, +}; + +/* + * Client data (each client gets its own) + */ + +struct max1619_data { + struct i2c_client client; + struct semaphore update_lock; + char valid; /* zero until following fields are valid */ + unsigned long last_updated; /* in jiffies */ + + /* registers values */ + u8 temp_input1; /* local */ + u8 temp_input2, temp_low2, temp_high2; /* remote */ + u8 temp_crit2; + u8 temp_hyst2; + u8 alarms; +}; + +/* + * Internal variables + */ + +static int max1619_id = 0; + +/* + * Sysfs stuff + */ + +#define show_temp(value) \ +static ssize_t show_##value(struct device *dev, char *buf) \ +{ \ + struct max1619_data *data = max1619_update_device(dev); \ + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value)); \ +} +show_temp(temp_input1); +show_temp(temp_input2); +show_temp(temp_low2); +show_temp(temp_high2); +show_temp(temp_crit2); +show_temp(temp_hyst2); + +#define set_temp2(value, reg) \ +static ssize_t set_##value(struct device *dev, const char *buf, \ + size_t count) \ +{ \ + struct i2c_client *client = to_i2c_client(dev); \ + struct max1619_data *data = i2c_get_clientdata(client); \ + data->value = TEMP_TO_REG(simple_strtol(buf, NULL, 10)); \ + i2c_smbus_write_byte_data(client, reg, data->value); \ + return count; \ +} + +set_temp2(temp_low2, MAX1619_REG_W_REMOTE_LOW); +set_temp2(temp_high2, MAX1619_REG_W_REMOTE_HIGH); +set_temp2(temp_crit2, MAX1619_REG_W_REMOTE_CRIT); +set_temp2(temp_hyst2, MAX1619_REG_W_TCRIT_HYST); + +static ssize_t show_alarms(struct device *dev, char *buf) +{ + struct max1619_data *data = max1619_update_device(dev); + return sprintf(buf, "%d\n", data->alarms); +} + +static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input1, NULL); +static DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input2, NULL); +static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_low2, + set_temp_low2); +static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_high2, + set_temp_high2); +static DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp_crit2, + set_temp_crit2); +static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp_hyst2, + set_temp_hyst2); +static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); + +/* + * Real code + */ + +static int max1619_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_detect(adapter, &addr_data, max1619_detect); +} + +/* + * The following function does more than just detection. If detection + * succeeds, it also registers the new chip. + */ +static int max1619_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *new_client; + struct max1619_data *data; + int err = 0; + const char *name = ""; + u8 reg_config=0, reg_convrate=0, reg_status=0; + u8 man_id, chip_id; + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + goto exit; + + if (!(data = kmalloc(sizeof(struct max1619_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + memset(data, 0, sizeof(struct max1619_data)); + + /* The common I2C client data is placed right before the + MAX1619-specific data. */ + new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = address; + new_client->adapter = adapter; + new_client->driver = &max1619_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. + */ + if (kind < 0) { /* detection */ + reg_config = i2c_smbus_read_byte_data(new_client, + MAX1619_REG_R_CONFIG); + reg_convrate = i2c_smbus_read_byte_data(new_client, + MAX1619_REG_R_CONVRATE); + reg_status = i2c_smbus_read_byte_data(new_client, + MAX1619_REG_R_STATUS); + if ((reg_config & 0x03) != 0x00 + || reg_convrate > 0x07 || (reg_status & 0x61 ) !=0x00) { + dev_dbg(&adapter->dev, + "MAX1619 detection failed at 0x%02x.\n", + address); + goto exit_free; + } + } + + if (kind <= 0) { /* identification */ + + man_id = i2c_smbus_read_byte_data(new_client, + MAX1619_REG_R_MAN_ID); + chip_id = i2c_smbus_read_byte_data(new_client, + MAX1619_REG_R_CHIP_ID); + + if ((man_id == 0x4D) && (chip_id == 0x04)){ + kind = max1619; + } + } + + if (kind <= 0) { /* identification failed */ + dev_info(&adapter->dev, + "Unsupported chip (man_id=0x%02X, " + "chip_id=0x%02X).\n", man_id, chip_id); + goto exit_free; + } + + + if (kind == max1619){ + name = "max1619"; + } + + /* We can fill in the remaining client fields */ + strlcpy(new_client->name, name, I2C_NAME_SIZE); + new_client->id = max1619_id++; + data->valid = 0; + init_MUTEX(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) + goto exit_free; + + /* Initialize the MAX1619 chip */ + max1619_init_client(new_client); + + /* Register sysfs hooks */ + device_create_file(&new_client->dev, &dev_attr_temp1_input); + device_create_file(&new_client->dev, &dev_attr_temp2_input); + device_create_file(&new_client->dev, &dev_attr_temp2_min); + device_create_file(&new_client->dev, &dev_attr_temp2_max); + device_create_file(&new_client->dev, &dev_attr_temp2_crit); + device_create_file(&new_client->dev, &dev_attr_temp2_crit_hyst); + device_create_file(&new_client->dev, &dev_attr_alarms); + + return 0; + +exit_free: + kfree(data); +exit: + return err; +} + +static void max1619_init_client(struct i2c_client *client) +{ + u8 config; + + /* + * Start the conversions. + */ + i2c_smbus_write_byte_data(client, MAX1619_REG_W_CONVRATE, + 5); /* 2 Hz */ + config = i2c_smbus_read_byte_data(client, MAX1619_REG_R_CONFIG); + if (config & 0x40) + i2c_smbus_write_byte_data(client, MAX1619_REG_W_CONFIG, + config & 0xBF); /* run */ +} + +static int max1619_detach_client(struct i2c_client *client) +{ + int err; + + if ((err = i2c_detach_client(client))) { + dev_err(&client->dev, "Client deregistration failed, " + "client not detached.\n"); + return err; + } + + kfree(i2c_get_clientdata(client)); + return 0; +} + +static struct max1619_data *max1619_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct max1619_data *data = i2c_get_clientdata(client); + + down(&data->update_lock); + + if ((jiffies - data->last_updated > HZ * 2) || + (jiffies < data->last_updated) || + !data->valid) { + + dev_dbg(&client->dev, "Updating max1619 data.\n"); + data->temp_input1 = i2c_smbus_read_byte_data(client, + MAX1619_REG_R_LOCAL_TEMP); + data->temp_input2 = i2c_smbus_read_byte_data(client, + MAX1619_REG_R_REMOTE_TEMP); + data->temp_high2 = i2c_smbus_read_byte_data(client, + MAX1619_REG_R_REMOTE_HIGH); + data->temp_low2 = i2c_smbus_read_byte_data(client, + MAX1619_REG_R_REMOTE_LOW); + data->temp_crit2 = i2c_smbus_read_byte_data(client, + MAX1619_REG_R_REMOTE_CRIT); + data->temp_hyst2 = i2c_smbus_read_byte_data(client, + MAX1619_REG_R_TCRIT_HYST); + data->alarms = i2c_smbus_read_byte_data(client, + MAX1619_REG_R_STATUS); + + data->last_updated = jiffies; + data->valid = 1; + } + + up(&data->update_lock); + + return data; +} + +static int __init sensors_max1619_init(void) +{ + return i2c_add_driver(&max1619_driver); +} + +static void __exit sensors_max1619_exit(void) +{ + i2c_del_driver(&max1619_driver); +} + +MODULE_AUTHOR("Alexey Fisher <fishor@mail.ru> and" + "Jean Delvare <khali@linux-fr.org>"); +MODULE_DESCRIPTION("MAX1619 sensor driver"); +MODULE_LICENSE("GPL"); + +module_init(sensors_max1619_init); +module_exit(sensors_max1619_exit); ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2004-05-28 22:30 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2004-05-28 21:59 [BK PATCH] I2C update for 2.6.7-rc1 Greg KH 2004-05-28 22:00 ` [PATCH] " Greg KH 2004-05-28 22:00 ` Greg KH 2004-05-28 22:00 ` Greg KH 2004-05-28 22:00 ` Greg KH 2004-05-28 22:00 ` Greg KH 2004-05-28 22:00 ` Greg KH 2004-05-28 22:00 ` Greg KH 2004-05-28 22:00 ` Greg KH
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox