From 115f2db300200fcb95cd733569a5f27b91b2065c Mon Sep 17 00:00:00 2001 From: "Mark D. Studebaker" Date: Sat, 9 Feb 2002 16:36:54 +0000 Subject: [PATCH] add force_subclients parameter which allows moving subclients to different addresses; this allows initialization of two clients on the same i2c bus by preventing subclient address conflicts at 0x48 and 0x49. git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@1312 7894878c-1315-0410-8ee3-d5d059ff63e0 --- doc/chips/MODPARMS | 27 ++++++++++++++++++--------- doc/chips/w83781d | 8 ++++++++ kernel/chips/w83781d.c | 39 +++++++++++++++++++++++++++++++-------- 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/doc/chips/MODPARMS b/doc/chips/MODPARMS index 610d27f3..2747d761 100644 --- a/doc/chips/MODPARMS +++ b/doc/chips/MODPARMS @@ -3,15 +3,16 @@ Parameters for modprobe and insmod ================================== SUMMARY - [modprobe,insmod] module [parameter...] + [modprobe,insmod] module {parameter...} Parameters: - force=bus,address - force_addr=address - force_[chipname]=bus,address - ignore=bus,address - ignore_range=bus,startaddress,endaddress - probe=bus,address - probe_range=bus,startaddress,endaddress + force=bus,address{,bus,address} + force_addr=address{,address} + force_[chipname]=bus,address{,bus,address} + force_subclients=bus,caddr,saddr,saddr + ignore=bus,address{,bus,address} + ignore_range=bus,start,end{,bus,start,end} + probe=bus,address{,bus,address} + probe_range=bus,start,end{,bus,start,end} init=[0,1] (default 1) All arguments are in decimal unless prefixed by "0x". @@ -89,11 +90,19 @@ very strange results... It is used to program the base address of the sensor registers. This is required if the BIOS does not initialize the base address. +`force_subclients' is used to force the i2c addresses for subclients of +a certain chip. Typical usage is `force_subclients=0,0x2d,0x4a,0x4b' +to force the subclients of chip 0x2d on bus 0 to i2c addresses +0x4a and 0x4b. +This parameter is currently supported only by the w83781d driver +and is useful for certain Tyan boards. + `init' is used to tell a driver to bypass initializing a chip. This may be necessary if the BIOS has initialized the chip a certain way and the driver should not overwrite that initialization. +It is also useful if normal initialization crashes the system. The default is 1, so the only useful value is `init=0'. -This parameter is not supported by most drivers. +This parameter is currently supported only by the w83781d driver. ================================== EXAMPLE diff --git a/doc/chips/w83781d b/doc/chips/w83781d index 8e0b911a..4dd8bb02 100644 --- a/doc/chips/w83781d +++ b/doc/chips/w83781d @@ -54,8 +54,16 @@ Module Parameters Ditto * force_w83627hf: Ditto +* force_w83697hf: + Ditto * force_as99127f: Ditto +* force_subclients=bus,caddr,saddr,saddr + This is used to force the i2c addresses for subclients of + a certain chip. Typical usage is `force_subclients=0,0x2d,0x4a,0x4b' + to force the subclients of chip 0x2d on bus 0 to i2c addresses + 0x4a and 0x4b. + This parameter is useful for certain Tyan boards. * ignore: short array (min = 1, max = 48) List of adapter,address pairs not to scan * ignore_range: short array (min = 1, max = 48) diff --git a/kernel/chips/w83781d.c b/kernel/chips/w83781d.c index 429b24ec..4a42534c 100644 --- a/kernel/chips/w83781d.c +++ b/kernel/chips/w83781d.c @@ -67,6 +67,8 @@ static unsigned int normal_isa_range[] = { SENSORS_ISA_END }; /* Insmod parameters */ SENSORS_INSMOD_6(w83781d, w83782d, w83783s, w83627hf, as99127f, w83697hf); +SENSORS_MODULE_PARM(force_subclients, "List of subclient addresses: " \ + "{bus, clientaddr, subclientaddr1, subclientaddr2}"); static int init = 1; MODULE_PARM(init, "i"); @@ -747,7 +749,7 @@ int w83781d_attach_adapter(struct i2c_adapter *adapter) int w83781d_detect(struct i2c_adapter *adapter, int address, unsigned short flags, int kind) { - int i, val1, val2; + int i, val1, val2, id; struct i2c_client *new_client; struct w83781d_data *data; int err = 0; @@ -929,11 +931,33 @@ int w83781d_detect(struct i2c_adapter *adapter, int address, err = -ENOMEM; goto ERROR4; } - val1 = w83781d_read_value(new_client, - W83781D_REG_I2C_SUBADDR); - data->lm75[0].addr = 0x48 + (val1 & 0x07); + id = i2c_adapter_id(adapter); + if(force_subclients[0] == id && force_subclients[1] == address) { + for(i = 2; i <= 3; i++) { + if(force_subclients[i] < 0x48 || + force_subclients[i] > 0x4f) { + printk(KERN_ERR "w83781d.o: Invalid subclient address %d; must be 0x48-0x4f\n", + force_subclients[i]); + goto ERROR5; + } + } + w83781d_write_value(new_client, + W83781D_REG_I2C_SUBADDR, + (force_subclients[2] & 0x07) | + ((force_subclients[3] & 0x07) <<4)); + data->lm75[0].addr = force_subclients[2]; + } else { + val1 = w83781d_read_value(new_client, + W83781D_REG_I2C_SUBADDR); + data->lm75[0].addr = 0x48 + (val1 & 0x07); + } if (kind != w83783s) { - data->lm75[1].addr = 0x48 + ((val1 >> 4) & 0x07); + if(force_subclients[0] == id && + force_subclients[1] == address) { + data->lm75[1].addr = force_subclients[3]; + } else { + data->lm75[1].addr = 0x48 + ((val1 >> 4) & 0x07); + } if(data->lm75[0].addr == data->lm75[1].addr) { printk(KERN_ERR "w83781d.o: Duplicate addresses 0x%x for subclients.\n", data->lm75[0].addr); @@ -963,8 +987,7 @@ int w83781d_detect(struct i2c_adapter *adapter, int address, i, data->lm75[i].addr); if (i == 1) goto ERROR6; - else - goto ERROR5; + goto ERROR5; } if (kind == w83783s) break; @@ -993,7 +1016,7 @@ int w83781d_detect(struct i2c_adapter *adapter, int address, } data->sysctl_id = i; - /* Initialize the Winbond chip */ + /* Initialize the chip */ w83781d_init_client(new_client); return 0;