diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-02-10 16:52:55 +0100 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-02-10 17:14:49 +0100 |
commit | 9edd576d89a5b6d3e136d7dcab654d887c0d25b7 (patch) | |
tree | d19670de2256f8187321de3a41fa4a10d3c8e402 /drivers/hwmon/pmbus | |
parent | e21af88d39796c907c38648c824be3d646ffbe35 (diff) | |
parent | 28a4d5675857f6386930a324317281cb8ed1e5d0 (diff) |
Merge remote-tracking branch 'airlied/drm-fixes' into drm-intel-next-queued
Back-merge from drm-fixes into drm-intel-next to sort out two things:
- interlaced support: -fixes contains a bugfix to correctly clear
interlaced configuration bits in case the bios sets up an interlaced
mode and we want to set up the progressive mode (current kernels
don't support interlaced). The actual feature work to support
interlaced depends upon (and conflicts with) this bugfix.
- forcewake voodoo to workaround missed IRQ issues: -fixes only enabled
this for ivybridge, but some recent bug reports indicate that we
need this on Sandybridge, too. But in a slightly different flavour
and with other fixes and reworks on top. Additionally there are some
forcewake cleanup patches heading to -next that would conflict with
currrent -fixes.
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/hwmon/pmbus')
-rw-r--r-- | drivers/hwmon/pmbus/Kconfig | 9 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/adm1275.c | 71 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/pmbus.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/zl6100.c | 43 |
4 files changed, 91 insertions, 34 deletions
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig index 4b26f51920b..cfec923f42b 100644 --- a/drivers/hwmon/pmbus/Kconfig +++ b/drivers/hwmon/pmbus/Kconfig @@ -19,8 +19,8 @@ config SENSORS_PMBUS default y help If you say yes here you get hardware monitoring support for generic - PMBus devices, including but not limited to ADP4000, BMR450, BMR451, - BMR453, BMR454, NCP4200, and NCP4208. + PMBus devices, including but not limited to ADP4000, BMR453, BMR454, + NCP4200, and NCP4208. This driver can also be built as a module. If so, the module will be called pmbus. @@ -113,8 +113,9 @@ config SENSORS_ZL6100 default n help If you say yes here you get hardware monitoring support for Intersil - ZL2004, ZL2006, ZL2008, ZL2105, ZL2106, ZL6100, and ZL6105 Digital - DC/DC Controllers. + ZL2004, ZL2005, ZL2006, ZL2008, ZL2105, ZL2106, ZL6100, and ZL6105 + Digital DC/DC Controllers, as well as for Ericsson BMR450, BMR451, + BMR462, BMR463, and BMR464. This driver can also be built as a module. If so, the module will be called zl6100. diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c index 980a4d9d502..81c7c2ead6f 100644 --- a/drivers/hwmon/pmbus/adm1275.c +++ b/drivers/hwmon/pmbus/adm1275.c @@ -170,35 +170,71 @@ static int adm1275_read_byte_data(struct i2c_client *client, int page, int reg) return ret; } +static const struct i2c_device_id adm1275_id[] = { + { "adm1275", adm1275 }, + { "adm1276", adm1276 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adm1275_id); + static int adm1275_probe(struct i2c_client *client, const struct i2c_device_id *id) { + u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1]; int config, device_config; int ret; struct pmbus_driver_info *info; struct adm1275_data *data; + const struct i2c_device_id *mid; if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_BYTE_DATA)) + I2C_FUNC_SMBUS_READ_BYTE_DATA + | I2C_FUNC_SMBUS_BLOCK_DATA)) return -ENODEV; - data = kzalloc(sizeof(struct adm1275_data), GFP_KERNEL); - if (!data) - return -ENOMEM; + ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, block_buffer); + if (ret < 0) { + dev_err(&client->dev, "Failed to read Manufacturer ID\n"); + return ret; + } + if (ret != 3 || strncmp(block_buffer, "ADI", 3)) { + dev_err(&client->dev, "Unsupported Manufacturer ID\n"); + return -ENODEV; + } - config = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG); - if (config < 0) { - ret = config; - goto err_mem; + ret = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, block_buffer); + if (ret < 0) { + dev_err(&client->dev, "Failed to read Manufacturer Model\n"); + return ret; + } + for (mid = adm1275_id; mid->name[0]; mid++) { + if (!strncasecmp(mid->name, block_buffer, strlen(mid->name))) + break; + } + if (!mid->name[0]) { + dev_err(&client->dev, "Unsupported device\n"); + return -ENODEV; } + if (id->driver_data != mid->driver_data) + dev_notice(&client->dev, + "Device mismatch: Configured %s, detected %s\n", + id->name, mid->name); + + config = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG); + if (config < 0) + return config; + device_config = i2c_smbus_read_byte_data(client, ADM1275_DEVICE_CONFIG); - if (device_config < 0) { - ret = device_config; - goto err_mem; - } + if (device_config < 0) + return device_config; + + data = kzalloc(sizeof(struct adm1275_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->id = mid->driver_data; - data->id = id->driver_data; info = &data->info; info->pages = 1; @@ -233,7 +269,7 @@ static int adm1275_probe(struct i2c_client *client, if (device_config & ADM1275_IOUT_WARN2_SELECT) data->have_oc_fault = true; - switch (id->driver_data) { + switch (data->id) { case adm1275: if (config & ADM1275_VIN_VOUT_SELECT) info->func[0] |= @@ -281,13 +317,6 @@ static int adm1275_remove(struct i2c_client *client) return 0; } -static const struct i2c_device_id adm1275_id[] = { - { "adm1275", adm1275 }, - { "adm1276", adm1276 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adm1275_id); - static struct i2c_driver adm1275_driver = { .driver = { .name = "adm1275", diff --git a/drivers/hwmon/pmbus/pmbus.c b/drivers/hwmon/pmbus/pmbus.c index 995e873197e..18a385e753d 100644 --- a/drivers/hwmon/pmbus/pmbus.c +++ b/drivers/hwmon/pmbus/pmbus.c @@ -200,8 +200,6 @@ static int pmbus_remove(struct i2c_client *client) */ static const struct i2c_device_id pmbus_id[] = { {"adp4000", 1}, - {"bmr450", 1}, - {"bmr451", 1}, {"bmr453", 1}, {"bmr454", 1}, {"ncp4200", 1}, diff --git a/drivers/hwmon/pmbus/zl6100.c b/drivers/hwmon/pmbus/zl6100.c index 2bc980006f8..48c7b4a716a 100644 --- a/drivers/hwmon/pmbus/zl6100.c +++ b/drivers/hwmon/pmbus/zl6100.c @@ -28,7 +28,7 @@ #include <linux/delay.h> #include "pmbus.h" -enum chips { zl2004, zl2006, zl2008, zl2105, zl2106, zl6100, zl6105 }; +enum chips { zl2004, zl2005, zl2006, zl2008, zl2105, zl2106, zl6100, zl6105 }; struct zl6100_data { int id; @@ -38,8 +38,11 @@ struct zl6100_data { #define to_zl6100_data(x) container_of(x, struct zl6100_data, info) +#define ZL6100_MFR_CONFIG 0xd0 #define ZL6100_DEVICE_ID 0xe4 +#define ZL6100_MFR_XTEMP_ENABLE (1 << 7) + #define ZL6100_WAIT_TIME 1000 /* uS */ static ushort delay = ZL6100_WAIT_TIME; @@ -65,6 +68,19 @@ static int zl6100_read_word_data(struct i2c_client *client, int page, int reg) if (page || reg >= PMBUS_VIRT_BASE) return -ENXIO; + if (data->id == zl2005) { + /* + * Limit register detection is not reliable on ZL2005. + * Make sure registers are not erroneously detected. + */ + switch (reg) { + case PMBUS_VOUT_OV_WARN_LIMIT: + case PMBUS_VOUT_UV_WARN_LIMIT: + case PMBUS_IOUT_OC_WARN_LIMIT: + return -ENXIO; + } + } + zl6100_wait(data); ret = pmbus_read_word_data(client, page, reg); data->access = ktime_get(); @@ -122,7 +138,13 @@ static int zl6100_write_byte(struct i2c_client *client, int page, u8 value) } static const struct i2c_device_id zl6100_id[] = { + {"bmr450", zl2005}, + {"bmr451", zl2005}, + {"bmr462", zl2008}, + {"bmr463", zl2008}, + {"bmr464", zl2008}, {"zl2004", zl2004}, + {"zl2005", zl2005}, {"zl2006", zl2006}, {"zl2008", zl2008}, {"zl2105", zl2105}, @@ -143,7 +165,7 @@ static int zl6100_probe(struct i2c_client *client, const struct i2c_device_id *mid; if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_BYTE_DATA + I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_READ_BLOCK_DATA)) return -ENODEV; @@ -177,8 +199,9 @@ static int zl6100_probe(struct i2c_client *client, data->id = mid->driver_data; /* - * ZL2008, ZL2105, and ZL6100 are known to require a wait time + * ZL2005, ZL2008, ZL2105, and ZL6100 are known to require a wait time * between I2C accesses. ZL2004 and ZL6105 are known to be safe. + * Other chips have not yet been tested. * * Only clear the wait time for chips known to be safe. The wait time * can be cleared later for additional chips if tests show that it @@ -190,12 +213,9 @@ static int zl6100_probe(struct i2c_client *client, /* * Since there was a direct I2C device access above, wait before * accessing the chip again. - * Set the timestamp, wait, then set it again. This should provide - * enough buffer time to be safe. */ data->access = ktime_get(); zl6100_wait(data); - data->access = ktime_get(); info = &data->info; @@ -203,7 +223,16 @@ static int zl6100_probe(struct i2c_client *client, info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT - | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP; + | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; + + ret = i2c_smbus_read_word_data(client, ZL6100_MFR_CONFIG); + if (ret < 0) + goto err_mem; + if (ret & ZL6100_MFR_XTEMP_ENABLE) + info->func[0] |= PMBUS_HAVE_TEMP2; + + data->access = ktime_get(); + zl6100_wait(data); info->read_word_data = zl6100_read_word_data; info->read_byte_data = zl6100_read_byte_data; |