Commit 4858704d authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging

* 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging:
  therm_windtunnel: Convert to a new-style i2c driver
  therm_adt746x: Convert to a new-style i2c driver
  windfarm: Convert to new-style i2c drivers
  therm_pm72: Convert to a new-style i2c driver
  i2c-viapro: Add new PCI device ID for VX855
  i2c/chips: Move max6875 to drivers/misc/eeprom
  i2c: Do not give adapters a default parent
  i2c: Do not probe for TV chips on Voodoo3 adapters
  i2c: Retry automatically on arbitration loss
  i2c: Remove void casts
parents 86ade88e 036533e2
...@@ -19,6 +19,9 @@ Supported adapters: ...@@ -19,6 +19,9 @@ Supported adapters:
* VIA Technologies, Inc. VX800/VX820 * VIA Technologies, Inc. VX800/VX820
Datasheet: available on http://linux.via.com.tw Datasheet: available on http://linux.via.com.tw
* VIA Technologies, Inc. VX855/VX875
Datasheet: Availability unknown
Authors: Authors:
Kyösti Mälkki <kmalkki@cc.hut.fi>, Kyösti Mälkki <kmalkki@cc.hut.fi>,
Mark D. Studebaker <mdsxyz123@yahoo.com>, Mark D. Studebaker <mdsxyz123@yahoo.com>,
...@@ -53,6 +56,7 @@ Your lspci -n listing must show one of these : ...@@ -53,6 +56,7 @@ Your lspci -n listing must show one of these :
device 1106:3287 (VT8251) device 1106:3287 (VT8251)
device 1106:8324 (CX700) device 1106:8324 (CX700)
device 1106:8353 (VX800/VX820) device 1106:8353 (VX800/VX820)
device 1106:8409 (VX855/VX875)
If none of these show up, you should look in the BIOS for settings like If none of these show up, you should look in the BIOS for settings like
enable ACPI / SMBus or even USB. enable ACPI / SMBus or even USB.
......
...@@ -963,7 +963,7 @@ CONFIG_EEPROM_LEGACY=y ...@@ -963,7 +963,7 @@ CONFIG_EEPROM_LEGACY=y
CONFIG_SENSORS_PCF8574=y CONFIG_SENSORS_PCF8574=y
# CONFIG_PCF8575 is not set # CONFIG_PCF8575 is not set
CONFIG_SENSORS_PCF8591=y CONFIG_SENSORS_PCF8591=y
CONFIG_SENSORS_MAX6875=y CONFIG_EEPROM_MAX6875=y
# CONFIG_SENSORS_TSL2550 is not set # CONFIG_SENSORS_TSL2550 is not set
CONFIG_I2C_DEBUG_CORE=y CONFIG_I2C_DEBUG_CORE=y
CONFIG_I2C_DEBUG_ALGO=y CONFIG_I2C_DEBUG_ALGO=y
......
...@@ -1849,7 +1849,7 @@ CONFIG_EEPROM_LEGACY=m ...@@ -1849,7 +1849,7 @@ CONFIG_EEPROM_LEGACY=m
CONFIG_SENSORS_PCF8574=m CONFIG_SENSORS_PCF8574=m
CONFIG_SENSORS_PCA9539=m CONFIG_SENSORS_PCA9539=m
CONFIG_SENSORS_PCF8591=m CONFIG_SENSORS_PCF8591=m
CONFIG_SENSORS_MAX6875=m CONFIG_EEPROM_MAX6875=m
# CONFIG_SENSORS_TSL2550 is not set # CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_ALGO is not set
......
...@@ -1808,7 +1808,7 @@ CONFIG_PCF8575=m ...@@ -1808,7 +1808,7 @@ CONFIG_PCF8575=m
CONFIG_SENSORS_PCA9539=m CONFIG_SENSORS_PCA9539=m
CONFIG_SENSORS_PCF8591=m CONFIG_SENSORS_PCF8591=m
# CONFIG_TPS65010 is not set # CONFIG_TPS65010 is not set
CONFIG_SENSORS_MAX6875=m CONFIG_EEPROM_MAX6875=m
CONFIG_SENSORS_TSL2550=m CONFIG_SENSORS_TSL2550=m
CONFIG_MCU_MPC8349EMITX=m CONFIG_MCU_MPC8349EMITX=m
# CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_CORE is not set
......
...@@ -211,7 +211,7 @@ config I2C_VIA ...@@ -211,7 +211,7 @@ config I2C_VIA
will be called i2c-via. will be called i2c-via.
config I2C_VIAPRO config I2C_VIAPRO
tristate "VIA VT82C596/82C686/82xx and CX700/VX800/VX820" tristate "VIA VT82C596/82C686/82xx and CX700/VX8xx"
depends on PCI depends on PCI
help help
If you say yes to this option, support will be included for the VIA If you say yes to this option, support will be included for the VIA
...@@ -225,8 +225,8 @@ config I2C_VIAPRO ...@@ -225,8 +225,8 @@ config I2C_VIAPRO
VT8237R/A/S VT8237R/A/S
VT8251 VT8251
CX700 CX700
VX800 VX800/VX820
VX820 VX855/VX875
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called i2c-viapro. will be called i2c-viapro.
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
VT8251 0x3287 yes VT8251 0x3287 yes
CX700 0x8324 yes CX700 0x8324 yes
VX800/VX820 0x8353 yes VX800/VX820 0x8353 yes
VX855/VX875 0x8409 yes
Note: we assume there can only be one device, with one SMBus interface. Note: we assume there can only be one device, with one SMBus interface.
*/ */
...@@ -404,6 +405,7 @@ static int __devinit vt596_probe(struct pci_dev *pdev, ...@@ -404,6 +405,7 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
switch (pdev->device) { switch (pdev->device) {
case PCI_DEVICE_ID_VIA_CX700: case PCI_DEVICE_ID_VIA_CX700:
case PCI_DEVICE_ID_VIA_VX800: case PCI_DEVICE_ID_VIA_VX800:
case PCI_DEVICE_ID_VIA_VX855:
case PCI_DEVICE_ID_VIA_8251: case PCI_DEVICE_ID_VIA_8251:
case PCI_DEVICE_ID_VIA_8237: case PCI_DEVICE_ID_VIA_8237:
case PCI_DEVICE_ID_VIA_8237A: case PCI_DEVICE_ID_VIA_8237A:
...@@ -469,6 +471,8 @@ static struct pci_device_id vt596_ids[] = { ...@@ -469,6 +471,8 @@ static struct pci_device_id vt596_ids[] = {
.driver_data = SMBBA3 }, .driver_data = SMBBA3 },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX800), { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX800),
.driver_data = SMBBA3 }, .driver_data = SMBBA3 },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855),
.driver_data = SMBBA3 },
{ 0, } { 0, }
}; };
......
...@@ -163,7 +163,6 @@ static struct i2c_algo_bit_data voo_i2c_bit_data = { ...@@ -163,7 +163,6 @@ static struct i2c_algo_bit_data voo_i2c_bit_data = {
static struct i2c_adapter voodoo3_i2c_adapter = { static struct i2c_adapter voodoo3_i2c_adapter = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.class = I2C_CLASS_TV_ANALOG,
.name = "I2C Voodoo3/Banshee adapter", .name = "I2C Voodoo3/Banshee adapter",
.algo_data = &voo_i2c_bit_data, .algo_data = &voo_i2c_bit_data,
}; };
......
...@@ -64,21 +64,6 @@ config SENSORS_PCA9539 ...@@ -64,21 +64,6 @@ config SENSORS_PCA9539
This driver is deprecated and will be dropped soon. Use This driver is deprecated and will be dropped soon. Use
drivers/gpio/pca953x.c instead. drivers/gpio/pca953x.c instead.
config SENSORS_MAX6875
tristate "Maxim MAX6875 Power supply supervisor"
depends on EXPERIMENTAL
help
If you say yes here you get support for the Maxim MAX6875
EEPROM-programmable, quad power-supply sequencer/supervisor.
This provides an interface to program the EEPROM and reset the chip.
This driver also supports the Maxim MAX6874 hex power-supply
sequencer/supervisor if found at a compatible address.
This driver can also be built as a module. If so, the module
will be called max6875.
config SENSORS_TSL2550 config SENSORS_TSL2550
tristate "Taos TSL2550 ambient light sensor" tristate "Taos TSL2550 ambient light sensor"
depends on EXPERIMENTAL depends on EXPERIMENTAL
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
# #
obj-$(CONFIG_DS1682) += ds1682.o obj-$(CONFIG_DS1682) += ds1682.o
obj-$(CONFIG_SENSORS_MAX6875) += max6875.o
obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o
obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o
obj-$(CONFIG_PCF8575) += pcf8575.o obj-$(CONFIG_PCF8575) += pcf8575.o
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/idr.h> #include <linux/idr.h>
#include <linux/platform_device.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/hardirq.h> #include <linux/hardirq.h>
...@@ -451,16 +450,6 @@ static int i2c_register_adapter(struct i2c_adapter *adap) ...@@ -451,16 +450,6 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
mutex_lock(&core_lock); mutex_lock(&core_lock);
/* Add the adapter to the driver core.
* If the parent pointer is not set up,
* we add this adapter to the host bus.
*/
if (adap->dev.parent == NULL) {
adap->dev.parent = &platform_bus;
pr_debug("I2C adapter driver [%s] forgot to specify "
"physical device\n", adap->name);
}
/* Set default timeout to 1 second if not already set */ /* Set default timeout to 1 second if not already set */
if (adap->timeout == 0) if (adap->timeout == 0)
adap->timeout = HZ; adap->timeout = HZ;
...@@ -1022,7 +1011,8 @@ module_exit(i2c_exit); ...@@ -1022,7 +1011,8 @@ module_exit(i2c_exit);
*/ */
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{ {
int ret; unsigned long orig_jiffies;
int ret, try;
/* REVISIT the fault reporting model here is weak: /* REVISIT the fault reporting model here is weak:
* *
...@@ -1060,7 +1050,15 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) ...@@ -1060,7 +1050,15 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
mutex_lock_nested(&adap->bus_lock, adap->level); mutex_lock_nested(&adap->bus_lock, adap->level);
} }
ret = adap->algo->master_xfer(adap,msgs,num); /* Retry automatically on arbitration loss */
orig_jiffies = jiffies;
for (ret = 0, try = 0; try <= adap->retries; try++) {
ret = adap->algo->master_xfer(adap, msgs, num);
if (ret != -EAGAIN)
break;
if (time_after(jiffies, orig_jiffies + adap->timeout))
break;
}
mutex_unlock(&adap->bus_lock); mutex_unlock(&adap->bus_lock);
return ret; return ret;
...@@ -1509,7 +1507,7 @@ struct i2c_adapter* i2c_get_adapter(int id) ...@@ -1509,7 +1507,7 @@ struct i2c_adapter* i2c_get_adapter(int id)
struct i2c_adapter *adapter; struct i2c_adapter *adapter;
mutex_lock(&core_lock); mutex_lock(&core_lock);
adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id); adapter = idr_find(&i2c_adapter_idr, id);
if (adapter && !try_module_get(adapter->owner)) if (adapter && !try_module_get(adapter->owner))
adapter = NULL; adapter = NULL;
...@@ -1995,14 +1993,27 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, ...@@ -1995,14 +1993,27 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
char read_write, u8 command, int protocol, char read_write, u8 command, int protocol,
union i2c_smbus_data *data) union i2c_smbus_data *data)
{ {
unsigned long orig_jiffies;
int try;
s32 res; s32 res;
flags &= I2C_M_TEN | I2C_CLIENT_PEC; flags &= I2C_M_TEN | I2C_CLIENT_PEC;
if (adapter->algo->smbus_xfer) { if (adapter->algo->smbus_xfer) {
mutex_lock(&adapter->bus_lock); mutex_lock(&adapter->bus_lock);
res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write,
command, protocol, data); /* Retry automatically on arbitration loss */
orig_jiffies = jiffies;
for (res = 0, try = 0; try <= adapter->retries; try++) {
res = adapter->algo->smbus_xfer(adapter, addr, flags,
read_write, command,
protocol, data);
if (res != -EAGAIN)
break;
if (time_after(jiffies,
orig_jiffies + adapter->timeout))
break;
}
mutex_unlock(&adapter->bus_lock); mutex_unlock(&adapter->bus_lock);
} else } else
res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,
......
...@@ -72,7 +72,7 @@ MODULE_PARM_DESC(verbose,"Verbose log operations " ...@@ -72,7 +72,7 @@ MODULE_PARM_DESC(verbose,"Verbose log operations "
"(default 0)"); "(default 0)");
struct thermostat { struct thermostat {
struct i2c_client clt; struct i2c_client *clt;
u8 temps[3]; u8 temps[3];
u8 cached_temp[3]; u8 cached_temp[3];
u8 initial_limits[3]; u8 initial_limits[3];
...@@ -87,9 +87,6 @@ static struct of_device * of_dev; ...@@ -87,9 +87,6 @@ static struct of_device * of_dev;
static struct thermostat* thermostat; static struct thermostat* thermostat;
static struct task_struct *thread_therm = NULL; static struct task_struct *thread_therm = NULL;
static int attach_one_thermostat(struct i2c_adapter *adapter, int addr,
int busno);
static void write_both_fan_speed(struct thermostat *th, int speed); static void write_both_fan_speed(struct thermostat *th, int speed);
static void write_fan_speed(struct thermostat *th, int speed, int fan); static void write_fan_speed(struct thermostat *th, int speed, int fan);
...@@ -101,7 +98,7 @@ write_reg(struct thermostat* th, int reg, u8 data) ...@@ -101,7 +98,7 @@ write_reg(struct thermostat* th, int reg, u8 data)
tmp[0] = reg; tmp[0] = reg;
tmp[1] = data; tmp[1] = data;
rc = i2c_master_send(&th->clt, (const char *)tmp, 2); rc = i2c_master_send(th->clt, (const char *)tmp, 2);
if (rc < 0) if (rc < 0)
return rc; return rc;
if (rc != 2) if (rc != 2)
...@@ -116,12 +113,12 @@ read_reg(struct thermostat* th, int reg) ...@@ -116,12 +113,12 @@ read_reg(struct thermostat* th, int reg)
int rc; int rc;
reg_addr = (u8)reg; reg_addr = (u8)reg;
rc = i2c_master_send(&th->clt, &reg_addr, 1); rc = i2c_master_send(th->clt, &reg_addr, 1);
if (rc < 0) if (rc < 0)
return rc; return rc;
if (rc != 1) if (rc != 1)
return -ENODEV; return -ENODEV;
rc = i2c_master_recv(&th->clt, (char *)&data, 1); rc = i2c_master_recv(th->clt, (char *)&data, 1);
if (rc < 0) if (rc < 0)
return rc; return rc;
return data; return data;
...@@ -131,26 +128,36 @@ static int ...@@ -131,26 +128,36 @@ static int
attach_thermostat(struct i2c_adapter *adapter) attach_thermostat(struct i2c_adapter *adapter)
{ {
unsigned long bus_no; unsigned long bus_no;
struct i2c_board_info info;
struct i2c_client *client;
if (strncmp(adapter->name, "uni-n", 5)) if (strncmp(adapter->name, "uni-n", 5))
return -ENODEV; return -ENODEV;
bus_no = simple_strtoul(adapter->name + 6, NULL, 10); bus_no = simple_strtoul(adapter->name + 6, NULL, 10);
if (bus_no != therm_bus) if (bus_no != therm_bus)
return -ENODEV; return -ENODEV;
return attach_one_thermostat(adapter, therm_address, bus_no);
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "therm_adt746x", I2C_NAME_SIZE);
info.addr = therm_address;
client = i2c_new_device(adapter, &info);
if (!client)
return -ENODEV;
/*
* Let i2c-core delete that device on driver removal.
* This is safe because i2c-core holds the core_lock mutex for us.
*/
list_add_tail(&client->detected, &client->driver->clients);
return 0;
} }
static int static int
detach_thermostat(struct i2c_adapter *adapter) remove_thermostat(struct i2c_client *client)
{ {
struct thermostat* th; struct thermostat *th = i2c_get_clientdata(client);
int i; int i;
if (thermostat == NULL)
return 0;
th = thermostat;
if (thread_therm != NULL) { if (thread_therm != NULL) {
kthread_stop(thread_therm); kthread_stop(thread_therm);
} }
...@@ -166,8 +173,6 @@ detach_thermostat(struct i2c_adapter *adapter) ...@@ -166,8 +173,6 @@ detach_thermostat(struct i2c_adapter *adapter)
write_both_fan_speed(th, -1); write_both_fan_speed(th, -1);
i2c_detach_client(&th->clt);
thermostat = NULL; thermostat = NULL;
kfree(th); kfree(th);
...@@ -175,14 +180,6 @@ detach_thermostat(struct i2c_adapter *adapter) ...@@ -175,14 +180,6 @@ detach_thermostat(struct i2c_adapter *adapter)
return 0; return 0;
} }
static struct i2c_driver thermostat_driver = {
.driver = {
.name = "therm_adt746x",
},
.attach_adapter = attach_thermostat,
.detach_adapter = detach_thermostat,
};
static int read_fan_speed(struct thermostat *th, u8 addr) static int read_fan_speed(struct thermostat *th, u8 addr)
{ {
u8 tmp[2]; u8 tmp[2];
...@@ -371,8 +368,8 @@ static void set_limit(struct thermostat *th, int i) ...@@ -371,8 +368,8 @@ static void set_limit(struct thermostat *th, int i)
th->limits[i] = default_limits_local[i] + limit_adjust; th->limits[i] = default_limits_local[i] + limit_adjust;
} }
static int attach_one_thermostat(struct i2c_adapter *adapter, int addr, static int probe_thermostat(struct i2c_client *client,
int busno) const struct i2c_device_id *id)
{ {
struct thermostat* th; struct thermostat* th;
int rc; int rc;
...@@ -385,16 +382,12 @@ static int attach_one_thermostat(struct i2c_adapter *adapter, int addr, ...@@ -385,16 +382,12 @@ static int attach_one_thermostat(struct i2c_adapter *adapter, int addr,
if (!th) if (!th)
return -ENOMEM; return -ENOMEM;
th->clt.addr = addr; i2c_set_clientdata(client, th);
th->clt.adapter = adapter; th->clt = client;
th->clt.driver = &thermostat_driver;
strcpy(th->clt.name, "thermostat");
rc = read_reg(th, 0); rc = read_reg(th, 0);
if (rc < 0) { if (rc < 0) {
printk(KERN_ERR "adt746x: Thermostat failed to read config " dev_err(&client->dev, "Thermostat failed to read config!\n");
"from bus %d !\n",
busno);
kfree(th); kfree(th);
return -ENODEV; return -ENODEV;
} }
...@@ -423,14 +416,6 @@ static int attach_one_thermostat(struct i2c_adapter *adapter, int addr, ...@@ -423,14 +416,6 @@ static int attach_one_thermostat(struct i2c_adapter *adapter, int addr,
thermostat = th; thermostat = th;
if (i2c_attach_client(&th->clt)) {
printk(KERN_INFO "adt746x: Thermostat failed to attach "
"client !\n");
thermostat = NULL;
kfree(th);
return -ENODEV;
}
/* be sure to really write fan speed the first time */ /* be sure to really write fan speed the first time */
th->last_speed[0] = -2; th->last_speed[0] = -2;
th->last_speed[1] = -2; th->last_speed[1] = -2;
...@@ -456,6 +441,21 @@ static int attach_one_thermostat(struct i2c_adapter *adapter, int addr, ...@@ -456,6 +441,21 @@ static int attach_one_thermostat(struct i2c_adapter *adapter, int addr,
return 0; return 0;
} }
static const struct i2c_device_id therm_adt746x_id[] = {
{ "therm_adt746x", 0 },
{ }
};
static struct i2c_driver thermostat_driver = {
.driver = {
.name = "therm_adt746x",
},
.attach_adapter = attach_thermostat,
.probe = probe_thermostat,
.remove = remove_thermostat,
.id_table = therm_adt746x_id,
};
/* /*
* Now, unfortunately, sysfs doesn't give us a nice void * we could * Now, unfortunately, sysfs doesn't give us a nice void * we could
* pass around to the attribute functions, so we don't really have * pass around to the attribute functions, so we don't really have
......
...@@ -286,22 +286,6 @@ struct fcu_fan_table fcu_fans[] = { ...@@ -286,22 +286,6 @@ struct fcu_fan_table fcu_fans[] = {
}, },
}; };
/*
* i2c_driver structure to attach to the host i2c controller
*/
static int therm_pm72_attach(struct i2c_adapter *adapter);
static int therm_pm72_detach(struct i2c_adapter *adapter);
static struct i2c_driver therm_pm72_driver =
{
.driver = {
.name = "therm_pm72",
},
.attach_adapter = therm_pm72_attach,
.detach_adapter = therm_pm72_detach,
};
/* /*
* Utility function to create an i2c_client structure and * Utility function to create an i2c_client structure and
* attach it to one of u3 adapters * attach it to one of u3 adapters
...@@ -310,6 +294,7 @@ static struct i2c_client *attach_i2c_chip(int id, const char *name) ...@@ -310,6 +294,7 @@ static struct i2c_client *attach_i2c_chip(int id, const char *name)
{ {
struct i2c_client *clt; struct i2c_client *clt;
struct i2c_adapter *adap; struct i2c_adapter *adap;
struct i2c_board_info info;
if (id & 0x200) if (id & 0x200)
adap = k2; adap = k2;
...@@ -320,31 +305,21 @@ static struct i2c_client *attach_i2c_chip(int id, const char *name) ...@@ -320,31 +305,21 @@ static struct i2c_client *attach_i2c_chip(int id, const char *name)
if (adap == NULL) if (adap == NULL)
return NULL; return NULL;
clt = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); memset(&info, 0, sizeof(struct i2c_board_info));
if (clt == NULL) info.addr = (id >> 1) & 0x7f;
return NULL; strlcpy(info.type, "therm_pm72", I2C_NAME_SIZE);
clt = i2c_new_device(adap, &info);
clt->addr = (id >> 1) & 0x7f; if (!clt) {
clt->adapter = adap;
clt->driver = &therm_pm72_driver;
strncpy(clt->name, name, I2C_NAME_SIZE-1);
if (i2c_attach_client(clt)) {
printk(KERN_ERR "therm_pm72: Failed to attach to i2c ID 0x%x\n", id); printk(KERN_ERR "therm_pm72: Failed to attach to i2c ID 0x%x\n", id);
kfree(clt);
return NULL; return NULL;
} }
return clt;
}
/* /*
* Utility function to get rid of the i2c_client structure * Let i2c-core delete that device on driver removal.
* (will also detach from the adapter hopepfully) * This is safe because i2c-core holds the core_lock mutex for us.
*/ */
static void detach_i2c_chip(struct i2c_client *clt) list_add_tail(&clt->detected, &clt->driver->clients);
{ return clt;
i2c_detach_client(clt);
kfree(clt);
} }
/* /*
...@@ -1203,8 +1178,6 @@ static int init_cpu_state(struct cpu_pid_state *state, int index) ...@@ -1203,8 +1178,6 @@ static int init_cpu_state(struct cpu_pid_state *state, int index)
return 0; return 0;
fail: fail:
if (state->monitor)
detach_i2c_chip(state->monitor);
state->monitor = NULL; state->monitor = NULL;
return -ENODEV; return -ENODEV;
...@@ -1232,7 +1205,6 @@ static void dispose_cpu_state(struct cpu_pid_state *state) ...@@ -1232,7 +1205,6 @@ static void dispose_cpu_state(struct cpu_pid_state *state)
device_remove_file(&of_dev->dev, &dev_attr_cpu1_intake_fan_rpm); device_remove_file(&of_dev->dev, &dev_attr_cpu1_intake_fan_rpm);
} }
detach_i2c_chip(state->monitor);
state->monitor = NULL; state->monitor = NULL;
} }
...@@ -1407,7 +1379,6 @@ static void dispose_backside_state(struct backside_pid_state *state) ...@@ -1407,7 +1379,6 @@ static void dispose_backside_state(struct backside_pid_state *state)
device_remove_file(&of_dev->dev, &dev_attr_backside_temperature); device_remove_file(&of_dev->dev, &dev_attr_backside_temperature);
device_remove_file(&of_dev->dev, &dev_attr_backside_fan_pwm); device_remove_file(&of_dev->dev, &dev_attr_backside_fan_pwm);
detach_i2c_chip(state->monitor);
state->monitor = NULL; state->monitor = NULL;
} }
...@@ -1532,7 +1503,6 @@ static void dispose_drives_state(struct drives_pid_state *state) ...@@ -1532,7 +1503,6 @@ static void dispose_drives_state(struct drives_pid_state *state)
device_remove_file(&of_dev->dev, &dev_attr_drives_temperature); device_remove_file(&of_dev->dev, &dev_attr_drives_temperature);
device_remove_file(&of_dev->dev, &dev_attr_drives_fan_rpm); device_remove_file(&of_dev->dev, &dev_attr_drives_fan_rpm);
detach_i2c_chip(state->monitor);
state->monitor = NULL; state->monitor = NULL;
} }
...@@ -1654,7 +1624,6 @@ static void dispose_dimms_state(struct dimm_pid_state *state) ...@@ -1654,7 +1624,6 @@ static void dispose_dimms_state(struct dimm_pid_state *state)
device_remove_file(&of_dev->dev, &dev_attr_dimms_temperature); device_remove_file(&of_dev->dev, &dev_attr_dimms_temperature);
detach_i2c_chip(state->monitor);
state->monitor = NULL; state->monitor = NULL;
} }
...@@ -1779,7 +1748,6 @@ static void dispose_slots_state(struct slots_pid_state *state) ...@@ -1779,7 +1748,6 @@ static void dispose_slots_state(struct slots_pid_state *state)
device_remove_file(&of_dev->dev, &dev_attr_slots_temperature); device_remove_file(&of_dev->dev, &dev_attr_slots_temperature);
device_remove_file(&of_dev->dev, &dev_attr_slots_fan_pwm); device_remove_file(&of_dev->dev, &dev_attr_slots_fan_pwm);
detach_i2c_chip(state->monitor);
state->monitor = NULL; state->monitor = NULL;
} }
...@@ -2008,8 +1976,6 @@ static int attach_fcu(void) ...@@ -2008,8 +1976,6 @@ static int attach_fcu(void)
*/ */
static void detach_fcu(void) static void detach_fcu(void)
{ {
if (fcu)
detach_i2c_chip(fcu);
fcu = NULL; fcu = NULL;
} }
...@@ -2060,12 +2026,21 @@ static int therm_pm72_attach(struct i2c_adapter *adapter) ...@@ -2060,12 +2026,21 @@ static int therm_pm72_attach(struct i2c_adapter *adapter)
return 0; return 0;
} }
static int therm_pm72_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
/* Always succeed, the real work was done in therm_pm72_attach() */
return 0;
}
/* /*
* Called on every adapter when the driver or the i2c controller * Called when any of the devices which participates into thermal management
* is going away. * is going away.
*/ */
static int therm_pm72_detach(struct i2c_adapter *adapter) static int therm_pm72_remove(struct i2c_client *client)
{ {
struct i2c_adapter *adapter = client->adapter;
mutex_lock(&driver_lock); mutex_lock(&driver_lock);
if (state != state_detached) if (state != state_detached)
...@@ -2096,6 +2071,30 @@ static int therm_pm72_detach(struct i2c_adapter *adapter) ...@@ -2096,6 +2071,30 @@ static int therm_pm72_detach(struct i2c_adapter *adapter)
return 0; return 0;
} }
/*
* i2c_driver structure to attach to the host i2c controller
*/
static const struct i2c_device_id therm_pm72_id[] = {
/*
* Fake device name, thermal management is done by several
* chips but we don't need to differentiate between them at
* this point.
*/
{ "therm_pm72", 0 },
{ }
};
static struct i2c_driver therm_pm72_driver = {
.driver = {
.name = "therm_pm72",
},
.attach_adapter = therm_pm72_attach,
.probe = therm_pm72_probe,
.remove = therm_pm72_remove,
.id_table = therm_pm72_id,
};
static int fan_check_loc_match(const char *loc, int fan) static int fan_check_loc_match(const char *loc, int fan)
{ {
char tmp[64]; char tmp[64];
......
...@@ -48,16 +48,6 @@ ...@@ -48,16 +48,6 @@
#define LOG_TEMP 0 /* continously log temperature */ #define LOG_TEMP 0 /* continously log temperature */
static int do_probe( struct i2c_adapter *adapter, int addr, int kind);
/* scan 0x48-0x4f (DS1775) and 0x2c-2x2f (ADM1030) */
static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
0x4c, 0x4d, 0x4e, 0x4f,
0x2c, 0x2d, 0x2e, 0x2f,
I2C_CLIENT_END };
I2C_CLIENT_INSMOD;
static struct { static struct {
volatile int running; volatile int running;
struct task_struct *poll_task; struct task_struct *poll_task;
...@@ -315,53 +305,54 @@ static int control_loop(void *dummy) ...@@ -315,53 +305,54 @@ static int control_loop(void *dummy)
static int static int
do_attach( struct i2c_adapter *adapter ) do_attach( struct i2c_adapter *adapter )
{ {
int ret = 0; /* scan 0x48-0x4f (DS1775) and 0x2c-2x2f (ADM1030) */
static const unsigned short scan_ds1775[] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
I2C_CLIENT_END
};
static const unsigned short scan_adm1030[] = {
0x2c, 0x2d, 0x2e, 0x2f,
I2C_CLIENT_END
};
if( strncmp(adapter->name, "uni-n", 5) ) if( strncmp(adapter->name, "uni-n", 5) )
return 0; return 0;
if( !x.running ) { if( !x.running ) {
ret = i2c_probe( adapter, &addr_data, &do_probe ); struct i2c_board_info info;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "therm_ds1775", I2C_NAME_SIZE);
i2c_new_probed_device(adapter, &info, scan_ds1775);
strlcpy(info.type, "therm_adm1030", I2C_NAME_SIZE);
i2c_new_probed_device(adapter, &info, scan_adm1030);
if( x.thermostat && x.fan ) { if( x.thermostat && x.fan ) {
x.running = 1; x.running = 1;
x.poll_task = kthread_run(control_loop, NULL, "g4fand"); x.poll_task = kthread_run(control_loop, NULL, "g4fand");
} }
} }
return ret; return 0;
} }
static int static int
do_detach( struct i2c_client *client ) do_remove(struct i2c_client *client)
{ {
int err; if (x.running) {
x.running = 0;
if( (err=i2c_detach_client(client)) ) kthread_stop(x.poll_task);
printk(KERN_ERR "failed to detach thermostat client\n"); x.poll_task = NULL;
else {
if( x.running ) {
x.running = 0;
kthread_stop(x.poll_task);
x.poll_task = NULL;
}
if( client == x.thermostat )
x.thermostat = NULL;
else if( client == x.fan )
x.fan = NULL;
else {
printk(KERN_ERR "g4fan: bad client\n");
}
kfree( client );
} }
return err; if (client == x.thermostat)
} x.thermostat = NULL;
else if (client == x.fan)
x.fan = NULL;
else
printk(KERN_ERR "g4fan: bad client\n");
static struct i2c_driver g4fan_driver = { return 0;
.driver = { }
.name = "therm_windtunnel",
},
.attach_adapter = do_attach,
.detach_client = do_detach,
};
static int static int
attach_fan( struct i2c_client *cl ) attach_fan( struct i2c_client *cl )
...@@ -374,13 +365,8 @@ attach_fan( struct i2c_client *cl ) ...@@ -374,13 +365,8 @@ attach_fan( struct i2c_client *cl )
goto out; goto out;
printk("ADM1030 fan controller [@%02x]\n", cl->addr ); printk("ADM1030 fan controller [@%02x]\n", cl->addr );
strlcpy( cl->name, "ADM1030 fan controller", sizeof(cl->name) ); x.fan = cl;
if( !i2c_attach_client(cl) )
x.fan = cl;
out: out:
if( cl != x.fan )
kfree( cl );
return 0; return 0;
} }
...@@ -412,39 +398,47 @@ attach_thermostat( struct i2c_client *cl ) ...@@ -412,39 +398,47 @@ attach_thermostat( struct i2c_client *cl )
x.temp = temp; x.temp = temp;
x.overheat_temp = os_temp; x.overheat_temp = os_temp;
x.overheat_hyst = hyst_temp; x.overheat_hyst = hyst_temp;
x.thermostat = cl;
strlcpy( cl->name, "DS1775 thermostat", sizeof(cl->name) );
if( !i2c_attach_client(cl) )
x.thermostat = cl;
out: out:
if( cl != x.thermostat )
kfree( cl );
return 0; return 0;
} }
enum chip { ds1775, adm1030 };
static const struct i2c_device_id therm_windtunnel_id[] = {
{ "therm_ds1775", ds1775 },
{ "therm_adm1030", adm1030 },
{ }
};
static int static int
do_probe( struct i2c_adapter *adapter, int addr, int kind ) do_probe(struct i2c_client *cl, const struct i2c_device_id *id)
{ {
struct i2c_client *cl; struct i2c_adapter *adapter = cl->adapter;
if( !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA if( !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA
| I2C_FUNC_SMBUS_WRITE_BYTE) ) | I2C_FUNC_SMBUS_WRITE_BYTE) )
return 0; return 0;
if( !(cl=kzalloc(sizeof(*cl), GFP_KERNEL)) ) switch (id->driver_data) {
return -ENOMEM; case adm1030:
cl->addr = addr;
cl->adapter = adapter;
cl->driver = &g4fan_driver;
cl->flags = 0;
if( addr < 0x48 )
return attach_fan( cl ); return attach_fan( cl );
return attach_thermostat( cl ); case ds1775:
return attach_thermostat(cl);
}
return 0;
} }
static struct i2c_driver g4fan_driver = {
.driver = {
.name = "therm_windtunnel",
},
.attach_adapter = do_attach,
.probe = do_probe,
.remove = do_remove,
.id_table = therm_windtunnel_id,
};
/************************************************************************/ /************************************************************************/
/* initialization / cleanup */ /* initialization / cleanup */
......
...@@ -37,34 +37,22 @@ ...@@ -37,34 +37,22 @@
struct wf_lm75_sensor { struct wf_lm75_sensor {
int ds1775 : 1; int ds1775 : 1;
int inited : 1; int inited : 1;
struct i2c_client i2c; struct i2c_client *i2c;
struct wf_sensor sens; struct wf_sensor sens;
}; };
#define wf_to_lm75(c) container_of(c, struct wf_lm75_sensor, sens) #define wf_to_lm75(c) container_of(c, struct wf_lm75_sensor, sens)
#define i2c_to_lm75(c) container_of(c, struct wf_lm75_sensor, i2c)
static int wf_lm75_attach(struct i2c_adapter *adapter);
static int wf_lm75_detach(struct i2c_client *client);
static struct i2c_driver wf_lm75_driver = {
.driver = {
.name = "wf_lm75",
},
.attach_adapter = wf_lm75_attach,
.detach_client = wf_lm75_detach,
};
static int wf_lm75_get(struct wf_sensor *sr, s32 *value) static int wf_lm75_get(struct wf_sensor *sr, s32 *value)
{ {
struct wf_lm75_sensor *lm = wf_to_lm75(sr); struct wf_lm75_sensor *lm = wf_to_lm75(sr);
s32 data; s32 data;
if (lm->i2c.adapter == NULL) if (lm->i2c == NULL)
return -ENODEV; return -ENODEV;
/* Init chip if necessary */ /* Init chip if necessary */
if (!lm->inited) { if (!lm->inited) {
u8 cfg_new, cfg = (u8)i2c_smbus_read_byte_data(&lm->i2c, 1); u8 cfg_new, cfg = (u8)i2c_smbus_read_byte_data(lm->i2c, 1);
DBG("wf_lm75: Initializing %s, cfg was: %02x\n", DBG("wf_lm75: Initializing %s, cfg was: %02x\n",
sr->name, cfg); sr->name, cfg);
...@@ -73,7 +61,7 @@ static int wf_lm75_get(struct wf_sensor *sr, s32 *value) ...@@ -73,7 +61,7 @@ static int wf_lm75_get(struct wf_sensor *sr, s32 *value)
* the firmware for now * the firmware for now
*/ */
cfg_new = cfg & ~0x01; cfg_new = cfg & ~0x01;
i2c_smbus_write_byte_data(&lm->i2c, 1, cfg_new); i2c_smbus_write_byte_data(lm->i2c, 1, cfg_new);
lm->inited = 1; lm->inited = 1;
/* If we just powered it up, let's wait 200 ms */ /* If we just powered it up, let's wait 200 ms */
...@@ -81,7 +69,7 @@ static int wf_lm75_get(struct wf_sensor *sr, s32 *value) ...@@ -81,7 +69,7 @@ static int wf_lm75_get(struct wf_sensor *sr, s32 *value)
} }
/* Read temperature register */ /* Read temperature register */
data = (s32)le16_to_cpu(i2c_smbus_read_word_data(&lm->i2c, 0)); data = (s32)le16_to_cpu(i2c_smbus_read_word_data(lm->i2c, 0));
data <<= 8; data <<= 8;
*value = data; *value = data;
...@@ -92,12 +80,6 @@ static void wf_lm75_release(struct wf_sensor *sr) ...@@ -92,12 +80,6 @@ static void wf_lm75_release(struct wf_sensor *sr)
{ {
struct wf_lm75_sensor *lm = wf_to_lm75(sr); struct wf_lm75_sensor *lm = wf_to_lm75(sr);
/* check if client is registered and detach from i2c */
if (lm->i2c.adapter) {
i2c_detach_client(&lm->i2c);
lm->i2c.adapter = NULL;
}
kfree(lm); kfree(lm);
} }
...@@ -107,59 +89,77 @@ static struct wf_sensor_ops wf_lm75_ops = { ...@@ -107,59 +89,77 @@ static struct wf_sensor_ops wf_lm75_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
static struct wf_lm75_sensor *wf_lm75_create(struct i2c_adapter *adapter, static int wf_lm75_probe(struct i2c_client *client,
u8 addr, int ds1775, const struct i2c_device_id *id)
const char *loc)
{ {
struct wf_lm75_sensor *lm; struct wf_lm75_sensor *lm;
int rc; int rc;
DBG("wf_lm75: creating %s device at address 0x%02x\n",
ds1775 ? "ds1775" : "lm75", addr);
lm = kzalloc(sizeof(struct wf_lm75_sensor), GFP_KERNEL); lm = kzalloc(sizeof(struct wf_lm75_sensor), GFP_KERNEL);
if (lm == NULL) if (lm == NULL)
return NULL; return -ENODEV;
lm->inited = 0;
lm->ds1775 = id->driver_data;
lm->i2c = client;
lm->sens.name = client->dev.platform_data;
lm->sens.ops = &wf_lm75_ops;
i2c_set_clientdata(client, lm);
rc = wf_register_sensor(&lm->sens);
if (rc) {
i2c_set_clientdata(client, NULL);
kfree(lm);
}
return rc;
}
static struct i2c_client *wf_lm75_create(struct i2c_adapter *adapter,
u8 addr, int ds1775,
const char *loc)
{
struct i2c_board_info info;
struct i2c_client *client;
char *name;
DBG("wf_lm75: creating %s device at address 0x%02x\n",
ds1775 ? "ds1775" : "lm75", addr);
/* Usual rant about sensor names not beeing very consistent in /* Usual rant about sensor names not beeing very consistent in
* the device-tree, oh well ... * the device-tree, oh well ...
* Add more entries below as you deal with more setups * Add more entries below as you deal with more setups
*/ */
if (!strcmp(loc, "Hard drive") || !strcmp(loc, "DRIVE BAY")) if (!strcmp(loc, "Hard drive") || !strcmp(loc, "DRIVE BAY"))
lm->sens.name = "hd-temp"; name = "hd-temp";
else if (!strcmp(loc, "Incoming Air Temp")) else if (!strcmp(loc, "Incoming Air Temp"))
lm->sens.name = "incoming-air-temp"; name = "incoming-air-temp";
else if (!strcmp(loc, "ODD Temp")) else if (!strcmp(loc, "ODD Temp"))
lm->sens.name = "optical-drive-temp"; name = "optical-drive-temp";
else if (!strcmp(loc, "HD Temp")) else if (!strcmp(loc, "HD Temp"))
lm->sens.name = "hard-drive-temp"; name = "hard-drive-temp";
else else
goto fail; goto fail;
lm->inited = 0; memset(&info, 0, sizeof(struct i2c_board_info));
lm->sens.ops = &wf_lm75_ops; info.addr = (addr >> 1) & 0x7f;
lm->ds1775 = ds1775; info.platform_data = name;
lm->i2c.addr = (addr >> 1) & 0x7f; strlcpy(info.type, ds1775 ? "wf_ds1775" : "wf_lm75", I2C_NAME_SIZE);
lm->i2c.adapter = adapter;
lm->i2c.driver = &wf_lm75_driver;
strncpy(lm->i2c.name, lm->sens.name, I2C_NAME_SIZE-1);
rc = i2c_attach_client(&lm->i2c);
if (rc) {
printk(KERN_ERR "windfarm: failed to attach %s %s to i2c,"
" err %d\n", ds1775 ? "ds1775" : "lm75",
lm->i2c.name, rc);
goto fail;
}
if (wf_register_sensor(&lm->sens)) { client = i2c_new_device(adapter, &info);
i2c_detach_client(&lm->i2c); if (client == NULL) {
printk(KERN_ERR "windfarm: failed to attach %s %s to i2c\n",
ds1775 ? "ds1775" : "lm75", name);
goto fail; goto fail;
} }
return lm; /*
* Let i2c-core delete that device on driver removal.
* This is safe because i2c-core holds the core_lock mutex for us.
*/
list_add_tail(&client->detected, &client->driver->clients);
return client;
fail: fail:
kfree(lm);
return NULL; return NULL;
} }
...@@ -202,21 +202,38 @@ static int wf_lm75_attach(struct i2c_adapter *adapter) ...@@ -202,21 +202,38 @@ static int wf_lm75_attach(struct i2c_adapter *adapter)
return 0; return 0;
} }
static int wf_lm75_detach(struct i2c_client *client) static int wf_lm75_remove(struct i2c_client *client)
{ {
struct wf_lm75_sensor *lm = i2c_to_lm75(client); struct wf_lm75_sensor *lm = i2c_get_clientdata(client);
DBG("wf_lm75: i2c detatch called for %s\n", lm->sens.name); DBG("wf_lm75: i2c detatch called for %s\n", lm->sens.name);
/* Mark client detached */ /* Mark client detached */
lm->i2c.adapter = NULL; lm->i2c = NULL;
/* release sensor */ /* release sensor */
wf_unregister_sensor(&lm->sens); wf_unregister_sensor(&lm->sens);
i2c_set_clientdata(client, NULL);
return 0; return 0;
} }
static const struct i2c_device_id wf_lm75_id[] = {
{ "wf_lm75", 0 },
{ "wf_ds1775", 1 },
{ }
};
static struct i2c_driver wf_lm75_driver = {
.driver = {
.name = "wf_lm75",
},
.attach_adapter = wf_lm75_attach,
.probe = wf_lm75_probe,
.remove = wf_lm75_remove,
.id_table = wf_lm75_id,
};
static int __init wf_lm75_sensor_init(void) static int __init wf_lm75_sensor_init(void)
{ {
/* Don't register on old machines that use therm_pm72 for now */ /* Don't register on old machines that use therm_pm72 for now */
......
...@@ -26,34 +26,22 @@ ...@@ -26,34 +26,22 @@
#define MAX6690_EXTERNAL_TEMP 1 #define MAX6690_EXTERNAL_TEMP 1
struct wf_6690_sensor { struct wf_6690_sensor {
struct i2c_client i2c; struct i2c_client *i2c;
struct wf_sensor sens; struct wf_sensor sens;
}; };
#define wf_to_6690(x) container_of((x), struct wf_6690_sensor, sens) #define wf_to_6690(x) container_of((x), struct wf_6690_sensor, sens)
#define i2c_to_6690(x) container_of((x), struct wf_6690_sensor, i2c)
static int wf_max6690_attach(struct i2c_adapter *adapter);
static int wf_max6690_detach(struct i2c_client *client);
static struct i2c_driver wf_max6690_driver = {
.driver = {
.name = "wf_max6690",
},
.attach_adapter = wf_max6690_attach,
.detach_client = wf_max6690_detach,
};
static int wf_max6690_get(struct wf_sensor *sr, s32 *value) static int wf_max6690_get(struct wf_sensor *sr, s32 *value)
{ {
struct wf_6690_sensor *max = wf_to_6690(sr); struct wf_6690_sensor *max = wf_to_6690(sr);
s32 data; s32 data;
if (max->i2c.adapter == NULL) if (max->i2c == NULL)
return -ENODEV; return -ENODEV;
/* chip gets initialized by firmware */ /* chip gets initialized by firmware */
data = i2c_smbus_read_byte_data(&max->i2c, MAX6690_EXTERNAL_TEMP); data = i2c_smbus_read_byte_data(max->i2c, MAX6690_EXTERNAL_TEMP);
if (data < 0) if (data < 0)
return data; return data;
*value = data << 16; *value = data << 16;
...@@ -64,10 +52,6 @@ static void wf_max6690_release(struct wf_sensor *sr) ...@@ -64,10 +52,6 @@ static void wf_max6690_release(struct wf_sensor *sr)
{ {
struct wf_6690_sensor *max = wf_to_6690(sr); struct wf_6690_sensor *max = wf_to_6690(sr);
if (max->i2c.adapter) {
i2c_detach_client(&max->i2c);
max->i2c.adapter = NULL;
}
kfree(max); kfree(max);
} }
...@@ -77,19 +61,40 @@ static struct wf_sensor_ops wf_max6690_ops = { ...@@ -77,19 +61,40 @@ static struct wf_sensor_ops wf_max6690_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr, static int wf_max6690_probe(struct i2c_client *client,
const char *loc) const struct i2c_device_id *id)
{ {
struct wf_6690_sensor *max; struct wf_6690_sensor *max;
char *name; int rc;
max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL); max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL);
if (max == NULL) { if (max == NULL) {
printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor %s: " printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor: "
"no memory\n", loc); "no memory\n");
return; return -ENOMEM;
}
max->i2c = client;
max->sens.name = client->dev.platform_data;
max->sens.ops = &wf_max6690_ops;
i2c_set_clientdata(client, max);
rc = wf_register_sensor(&max->sens);
if (rc) {
i2c_set_clientdata(client, NULL);
kfree(max);
} }
return rc;
}
static struct i2c_client *wf_max6690_create(struct i2c_adapter *adapter,
u8 addr, const char *loc)
{
struct i2c_board_info info;
struct i2c_client *client;
char *name;
if (!strcmp(loc, "BACKSIDE")) if (!strcmp(loc, "BACKSIDE"))
name = "backside-temp"; name = "backside-temp";
else if (!strcmp(loc, "NB Ambient")) else if (!strcmp(loc, "NB Ambient"))
...@@ -99,27 +104,26 @@ static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr, ...@@ -99,27 +104,26 @@ static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr,
else else
goto fail; goto fail;
max->sens.ops = &wf_max6690_ops; memset(&info, 0, sizeof(struct i2c_board_info));
max->sens.name = name; info.addr = addr >> 1;
max->i2c.addr = addr >> 1; info.platform_data = name;
max->i2c.adapter = adapter; strlcpy(info.type, "wf_max6690", I2C_NAME_SIZE);
max->i2c.driver = &wf_max6690_driver;
strncpy(max->i2c.name, name, I2C_NAME_SIZE-1);
if (i2c_attach_client(&max->i2c)) { client = i2c_new_device(adapter, &info);
if (client == NULL) {
printk(KERN_ERR "windfarm: failed to attach MAX6690 sensor\n"); printk(KERN_ERR "windfarm: failed to attach MAX6690 sensor\n");
goto fail; goto fail;
} }
if (wf_register_sensor(&max->sens)) { /*
i2c_detach_client(&max->i2c); * Let i2c-core delete that device on driver removal.
goto fail; * This is safe because i2c-core holds the core_lock mutex for us.
} */
list_add_tail(&client->detected, &client->driver->clients);
return; return client;
fail: fail:
kfree(max); return NULL;
} }
static int wf_max6690_attach(struct i2c_adapter *adapter) static int wf_max6690_attach(struct i2c_adapter *adapter)
...@@ -154,16 +158,31 @@ static int wf_max6690_attach(struct i2c_adapter *adapter) ...@@ -154,16 +158,31 @@ static int wf_max6690_attach(struct i2c_adapter *adapter)
return 0; return 0;
} }
static int wf_max6690_detach(struct i2c_client *client) static int wf_max6690_remove(struct i2c_client *client)
{ {
struct wf_6690_sensor *max = i2c_to_6690(client); struct wf_6690_sensor *max = i2c_get_clientdata(client);
max->i2c.adapter = NULL; max->i2c = NULL;
wf_unregister_sensor(&max->sens); wf_unregister_sensor(&max->sens);
return 0; return 0;
} }
static const struct i2c_device_id wf_max6690_id[] = {
{ "wf_max6690", 0 },
{ }
};
static struct i2c_driver wf_max6690_driver = {
.driver = {
.name = "wf_max6690",
},
.attach_adapter = wf_max6690_attach,
.probe = wf_max6690_probe,
.remove = wf_max6690_remove,
.id_table = wf_max6690_id,
};
static int __init wf_max6690_sensor_init(void) static int __init wf_max6690_sensor_init(void)
{ {
/* Don't register on old machines that use therm_pm72 for now */ /* Don't register on old machines that use therm_pm72 for now */
......
...@@ -39,7 +39,7 @@ struct wf_sat { ...@@ -39,7 +39,7 @@ struct wf_sat {
struct mutex mutex; struct mutex mutex;
unsigned long last_read; /* jiffies when cache last updated */ unsigned long last_read; /* jiffies when cache last updated */
u8 cache[16]; u8 cache[16];
struct i2c_client i2c; struct i2c_client *i2c;
struct device_node *node; struct device_node *node;
}; };
...@@ -54,18 +54,6 @@ struct wf_sat_sensor { ...@@ -54,18 +54,6 @@ struct wf_sat_sensor {
}; };
#define wf_to_sat(c) container_of(c, struct wf_sat_sensor, sens) #define wf_to_sat(c) container_of(c, struct wf_sat_sensor, sens)
#define i2c_to_sat(c) container_of(c, struct wf_sat, i2c)
static int wf_sat_attach(struct i2c_adapter *adapter);
static int wf_sat_detach(struct i2c_client *client);
static struct i2c_driver wf_sat_driver = {
.driver = {
.name = "wf_smu_sat",
},
.attach_adapter = wf_sat_attach,
.detach_client = wf_sat_detach,
};
struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id, struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id,
unsigned int *size) unsigned int *size)
...@@ -81,13 +69,13 @@ struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id, ...@@ -81,13 +69,13 @@ struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id,
if (sat_id > 1 || (sat = sats[sat_id]) == NULL) if (sat_id > 1 || (sat = sats[sat_id]) == NULL)
return NULL; return NULL;
err = i2c_smbus_write_word_data(&sat->i2c, 8, id << 8); err = i2c_smbus_write_word_data(sat->i2c, 8, id << 8);
if (err) { if (err) {
printk(KERN_ERR "smu_sat_get_sdb_part wr error %d\n", err); printk(KERN_ERR "smu_sat_get_sdb_part wr error %d\n", err);
return NULL; return NULL;
} }
err = i2c_smbus_read_word_data(&sat->i2c, 9); err = i2c_smbus_read_word_data(sat->i2c, 9);
if (err < 0) { if (err < 0) {
printk(KERN_ERR "smu_sat_get_sdb_part rd len error\n"); printk(KERN_ERR "smu_sat_get_sdb_part rd len error\n");
return NULL; return NULL;
...@@ -105,7 +93,7 @@ struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id, ...@@ -105,7 +93,7 @@ struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id,
return NULL; return NULL;
for (i = 0; i < len; i += 4) { for (i = 0; i < len; i += 4) {
err = i2c_smbus_read_i2c_block_data(&sat->i2c, 0xa, 4, data); err = i2c_smbus_read_i2c_block_data(sat->i2c, 0xa, 4, data);
if (err < 0) { if (err < 0) {
printk(KERN_ERR "smu_sat_get_sdb_part rd err %d\n", printk(KERN_ERR "smu_sat_get_sdb_part rd err %d\n",
err); err);
...@@ -138,7 +126,7 @@ static int wf_sat_read_cache(struct wf_sat *sat) ...@@ -138,7 +126,7 @@ static int wf_sat_read_cache(struct wf_sat *sat)
{ {
int err; int err;
err = i2c_smbus_read_i2c_block_data(&sat->i2c, 0x3f, 16, sat->cache); err = i2c_smbus_read_i2c_block_data(sat->i2c, 0x3f, 16, sat->cache);
if (err < 0) if (err < 0)
return err; return err;
sat->last_read = jiffies; sat->last_read = jiffies;
...@@ -161,7 +149,7 @@ static int wf_sat_get(struct wf_sensor *sr, s32 *value) ...@@ -161,7 +149,7 @@ static int wf_sat_get(struct wf_sensor *sr, s32 *value)
int i, err; int i, err;
s32 val; s32 val;
if (sat->i2c.adapter == NULL) if (sat->i2c == NULL)
return -ENODEV; return -ENODEV;
mutex_lock(&sat->mutex); mutex_lock(&sat->mutex);
...@@ -193,10 +181,6 @@ static void wf_sat_release(struct wf_sensor *sr) ...@@ -193,10 +181,6 @@ static void wf_sat_release(struct wf_sensor *sr)
struct wf_sat *sat = sens->sat; struct wf_sat *sat = sens->sat;
if (atomic_dec_and_test(&sat->refcnt)) { if (atomic_dec_and_test(&sat->refcnt)) {
if (sat->i2c.adapter) {
i2c_detach_client(&sat->i2c);
sat->i2c.adapter = NULL;
}
if (sat->nr >= 0) if (sat->nr >= 0)
sats[sat->nr] = NULL; sats[sat->nr] = NULL;
kfree(sat); kfree(sat);
...@@ -212,38 +196,58 @@ static struct wf_sensor_ops wf_sat_ops = { ...@@ -212,38 +196,58 @@ static struct wf_sensor_ops wf_sat_ops = {
static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev) static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev)
{ {
struct i2c_board_info info;
struct i2c_client *client;
const u32 *reg;
u8 addr;
reg = of_get_property(dev, "reg", NULL);
if (reg == NULL)
return;
addr = *reg;
DBG(KERN_DEBUG "wf_sat: creating sat at address %x\n", addr);
memset(&info, 0, sizeof(struct i2c_board_info));
info.addr = (addr >> 1) & 0x7f;
info.platform_data = dev;
strlcpy(info.type, "wf_sat", I2C_NAME_SIZE);
client = i2c_new_device(adapter, &info);
if (client == NULL) {
printk(KERN_ERR "windfarm: failed to attach smu-sat to i2c\n");
return;
}
/*
* Let i2c-core delete that device on driver removal.
* This is safe because i2c-core holds the core_lock mutex for us.
*/
list_add_tail(&client->detected, &client->driver->clients);
}
static int wf_sat_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device_node *dev = client->dev.platform_data;
struct wf_sat *sat; struct wf_sat *sat;
struct wf_sat_sensor *sens; struct wf_sat_sensor *sens;
const u32 *reg; const u32 *reg;
const char *loc, *type; const char *loc, *type;
u8 addr, chip, core; u8 chip, core;
struct device_node *child; struct device_node *child;
int shift, cpu, index; int shift, cpu, index;
char *name; char *name;
int vsens[2], isens[2]; int vsens[2], isens[2];
reg = of_get_property(dev, "reg", NULL);
if (reg == NULL)
return;
addr = *reg;
DBG(KERN_DEBUG "wf_sat: creating sat at address %x\n", addr);
sat = kzalloc(sizeof(struct wf_sat), GFP_KERNEL); sat = kzalloc(sizeof(struct wf_sat), GFP_KERNEL);
if (sat == NULL) if (sat == NULL)
return; return -ENOMEM;
sat->nr = -1; sat->nr = -1;
sat->node = of_node_get(dev); sat->node = of_node_get(dev);
atomic_set(&sat->refcnt, 0); atomic_set(&sat->refcnt, 0);
mutex_init(&sat->mutex); mutex_init(&sat->mutex);
sat->i2c.addr = (addr >> 1) & 0x7f; sat->i2c = client;
sat->i2c.adapter = adapter; i2c_set_clientdata(client, sat);
sat->i2c.driver = &wf_sat_driver;
strncpy(sat->i2c.name, "smu-sat", I2C_NAME_SIZE-1);
if (i2c_attach_client(&sat->i2c)) {
printk(KERN_ERR "windfarm: failed to attach smu-sat to i2c\n");
goto fail;
}
vsens[0] = vsens[1] = -1; vsens[0] = vsens[1] = -1;
isens[0] = isens[1] = -1; isens[0] = isens[1] = -1;
...@@ -344,10 +348,7 @@ static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev) ...@@ -344,10 +348,7 @@ static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev)
if (sat->nr >= 0) if (sat->nr >= 0)
sats[sat->nr] = sat; sats[sat->nr] = sat;
return; return 0;
fail:
kfree(sat);
} }
static int wf_sat_attach(struct i2c_adapter *adapter) static int wf_sat_attach(struct i2c_adapter *adapter)
...@@ -366,16 +367,32 @@ static int wf_sat_attach(struct i2c_adapter *adapter) ...@@ -366,16 +367,32 @@ static int wf_sat_attach(struct i2c_adapter *adapter)
return 0; return 0;
} }
static int wf_sat_detach(struct i2c_client *client) static int wf_sat_remove(struct i2c_client *client)
{ {
struct wf_sat *sat = i2c_to_sat(client); struct wf_sat *sat = i2c_get_clientdata(client);
/* XXX TODO */ /* XXX TODO */
sat->i2c.adapter = NULL; sat->i2c = NULL;
i2c_set_clientdata(client, NULL);
return 0; return 0;
} }
static const struct i2c_device_id wf_sat_id[] = {
{ "wf_sat", 0 },
{ }
};
static struct i2c_driver wf_sat_driver = {
.driver = {
.name = "wf_smu_sat",
},
.attach_adapter = wf_sat_attach,
.probe = wf_sat_probe,
.remove = wf_sat_remove,
.id_table = wf_sat_id,
};
static int __init sat_sensors_init(void) static int __init sat_sensors_init(void)
{ {
return i2c_add_driver(&wf_sat_driver); return i2c_add_driver(&wf_sat_driver);
......
...@@ -48,6 +48,20 @@ config EEPROM_LEGACY ...@@ -48,6 +48,20 @@ config EEPROM_LEGACY
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called eeprom. will be called eeprom.
config EEPROM_MAX6875
tristate "Maxim MAX6874/5 power supply supervisor"
depends on I2C && EXPERIMENTAL
help
If you say yes here you get read-only support for the user EEPROM of
the Maxim MAX6874/5 EEPROM-programmable, quad power-supply
sequencer/supervisor.
All other features of this chip should be accessed via i2c-dev.
This driver can also be built as a module. If so, the module
will be called max6875.
config EEPROM_93CX6 config EEPROM_93CX6
tristate "EEPROM 93CX6 support" tristate "EEPROM 93CX6 support"
help help
......
obj-$(CONFIG_EEPROM_AT24) += at24.o obj-$(CONFIG_EEPROM_AT24) += at24.o
obj-$(CONFIG_EEPROM_AT25) += at25.o obj-$(CONFIG_EEPROM_AT25) += at25.o
obj-$(CONFIG_EEPROM_LEGACY) += eeprom.o obj-$(CONFIG_EEPROM_LEGACY) += eeprom.o
obj-$(CONFIG_EEPROM_MAX6875) += max6875.o
obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com> Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com>
Based on i2c/chips/eeprom.c Based on eeprom.c
The MAX6875 has a bank of registers and two banks of EEPROM. The MAX6875 has a bank of registers and two banks of EEPROM.
Address ranges are defined as follows: Address ranges are defined as follows:
......
...@@ -1315,7 +1315,6 @@ static int __devinit tdfxfb_setup_i2c_bus(struct tdfxfb_i2c_chan *chan, ...@@ -1315,7 +1315,6 @@ static int __devinit tdfxfb_setup_i2c_bus(struct tdfxfb_i2c_chan *chan,
strlcpy(chan->adapter.name, name, sizeof(chan->adapter.name)); strlcpy(chan->adapter.name, name, sizeof(chan->adapter.name));
chan->adapter.owner = THIS_MODULE; chan->adapter.owner = THIS_MODULE;
chan->adapter.class = I2C_CLASS_TV_ANALOG;
chan->adapter.algo_data = &chan->algo; chan->adapter.algo_data = &chan->algo;
chan->adapter.dev.parent = dev; chan->adapter.dev.parent = dev;
chan->algo.setsda = tdfxfb_i2c_setsda; chan->algo.setsda = tdfxfb_i2c_setsda;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment