forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
hwmon: (max1111) Add support for MAX1110, MAX1112, and MAX1113
MAX1110 is similar to MAX1111, with 8 instead of 4 channels. MAX1112 and MAX1113 are similar to MAX1110 and MAX1111, with 4.096V reference voltage instead of 2.048V. Signed-off-by: Guenter Roeck <[email protected]> Acked-by: Jean Delvare <[email protected]>
- Loading branch information
Showing
2 changed files
with
70 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,8 @@ | |
#include <linux/spi/spi.h> | ||
#include <linux/slab.h> | ||
|
||
enum chips { max1110, max1111, max1112, max1113 }; | ||
|
||
#define MAX1111_TX_BUF_SIZE 1 | ||
#define MAX1111_RX_BUF_SIZE 2 | ||
|
||
|
@@ -30,6 +32,7 @@ | |
#define MAX1111_CTRL_PD1 (1u << 1) | ||
#define MAX1111_CTRL_SGL (1u << 2) | ||
#define MAX1111_CTRL_UNI (1u << 3) | ||
#define MAX1110_CTRL_SEL_SH (4) | ||
#define MAX1111_CTRL_SEL_SH (5) /* NOTE: bit 4 is ignored */ | ||
#define MAX1111_CTRL_STR (1u << 7) | ||
|
||
|
@@ -42,6 +45,8 @@ struct max1111_data { | |
uint8_t rx_buf[MAX1111_RX_BUF_SIZE]; | ||
struct mutex drvdata_lock; | ||
/* protect msg, xfer and buffers from multiple access */ | ||
int sel_sh; | ||
int lsb; | ||
}; | ||
|
||
static int max1111_read(struct device *dev, int channel) | ||
|
@@ -53,7 +58,7 @@ static int max1111_read(struct device *dev, int channel) | |
/* writing to drvdata struct is not thread safe, wait on mutex */ | ||
mutex_lock(&data->drvdata_lock); | ||
|
||
data->tx_buf[0] = (channel << MAX1111_CTRL_SEL_SH) | | ||
data->tx_buf[0] = (channel << data->sel_sh) | | ||
MAX1111_CTRL_PD0 | MAX1111_CTRL_PD1 | | ||
MAX1111_CTRL_SGL | MAX1111_CTRL_UNI | MAX1111_CTRL_STR; | ||
|
||
|
@@ -93,12 +98,13 @@ EXPORT_SYMBOL(max1111_read_channel); | |
static ssize_t show_name(struct device *dev, | ||
struct device_attribute *attr, char *buf) | ||
{ | ||
return sprintf(buf, "max1111\n"); | ||
return sprintf(buf, "%s\n", to_spi_device(dev)->modalias); | ||
} | ||
|
||
static ssize_t show_adc(struct device *dev, | ||
struct device_attribute *attr, char *buf) | ||
{ | ||
struct max1111_data *data = dev_get_drvdata(dev); | ||
int channel = to_sensor_dev_attr(attr)->index; | ||
int ret; | ||
|
||
|
@@ -107,10 +113,10 @@ static ssize_t show_adc(struct device *dev, | |
return ret; | ||
|
||
/* | ||
* assume the reference voltage to be 2.048V, with an 8-bit sample, | ||
* the LSB weight is 8mV | ||
* Assume the reference voltage to be 2.048V or 4.096V, with an 8-bit | ||
* sample. The LSB weight is 8mV or 16mV depending on the chip type. | ||
*/ | ||
return sprintf(buf, "%d\n", ret * 8); | ||
return sprintf(buf, "%d\n", ret * data->lsb); | ||
} | ||
|
||
#define MAX1111_ADC_ATTR(_id) \ | ||
|
@@ -121,6 +127,10 @@ static MAX1111_ADC_ATTR(0); | |
static MAX1111_ADC_ATTR(1); | ||
static MAX1111_ADC_ATTR(2); | ||
static MAX1111_ADC_ATTR(3); | ||
static MAX1111_ADC_ATTR(4); | ||
static MAX1111_ADC_ATTR(5); | ||
static MAX1111_ADC_ATTR(6); | ||
static MAX1111_ADC_ATTR(7); | ||
|
||
static struct attribute *max1111_attributes[] = { | ||
&dev_attr_name.attr, | ||
|
@@ -135,6 +145,18 @@ static const struct attribute_group max1111_attr_group = { | |
.attrs = max1111_attributes, | ||
}; | ||
|
||
static struct attribute *max1110_attributes[] = { | ||
&sensor_dev_attr_in4_input.dev_attr.attr, | ||
&sensor_dev_attr_in5_input.dev_attr.attr, | ||
&sensor_dev_attr_in6_input.dev_attr.attr, | ||
&sensor_dev_attr_in7_input.dev_attr.attr, | ||
NULL, | ||
}; | ||
|
||
static const struct attribute_group max1110_attr_group = { | ||
.attrs = max1110_attributes, | ||
}; | ||
|
||
static int __devinit setup_transfer(struct max1111_data *data) | ||
{ | ||
struct spi_message *m; | ||
|
@@ -159,6 +181,7 @@ static int __devinit setup_transfer(struct max1111_data *data) | |
|
||
static int __devinit max1111_probe(struct spi_device *spi) | ||
{ | ||
enum chips chip = spi_get_device_id(spi)->driver_data; | ||
struct max1111_data *data; | ||
int err; | ||
|
||
|
@@ -174,6 +197,24 @@ static int __devinit max1111_probe(struct spi_device *spi) | |
return -ENOMEM; | ||
} | ||
|
||
switch (chip) { | ||
case max1110: | ||
data->lsb = 8; | ||
data->sel_sh = MAX1110_CTRL_SEL_SH; | ||
break; | ||
case max1111: | ||
data->lsb = 8; | ||
data->sel_sh = MAX1111_CTRL_SEL_SH; | ||
break; | ||
case max1112: | ||
data->lsb = 16; | ||
data->sel_sh = MAX1110_CTRL_SEL_SH; | ||
break; | ||
case max1113: | ||
data->lsb = 16; | ||
data->sel_sh = MAX1111_CTRL_SEL_SH; | ||
break; | ||
} | ||
err = setup_transfer(data); | ||
if (err) | ||
return err; | ||
|
@@ -188,6 +229,14 @@ static int __devinit max1111_probe(struct spi_device *spi) | |
dev_err(&spi->dev, "failed to create attribute group\n"); | ||
return err; | ||
} | ||
if (chip == max1110 || chip == max1112) { | ||
err = sysfs_create_group(&spi->dev.kobj, &max1110_attr_group); | ||
if (err) { | ||
dev_err(&spi->dev, | ||
"failed to create extended attribute group\n"); | ||
goto err_remove; | ||
} | ||
} | ||
|
||
data->hwmon_dev = hwmon_device_register(&spi->dev); | ||
if (IS_ERR(data->hwmon_dev)) { | ||
|
@@ -202,6 +251,7 @@ static int __devinit max1111_probe(struct spi_device *spi) | |
return 0; | ||
|
||
err_remove: | ||
sysfs_remove_group(&spi->dev.kobj, &max1110_attr_group); | ||
sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group); | ||
return err; | ||
} | ||
|
@@ -211,23 +261,33 @@ static int __devexit max1111_remove(struct spi_device *spi) | |
struct max1111_data *data = spi_get_drvdata(spi); | ||
|
||
hwmon_device_unregister(data->hwmon_dev); | ||
sysfs_remove_group(&spi->dev.kobj, &max1110_attr_group); | ||
sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group); | ||
mutex_destroy(&data->drvdata_lock); | ||
return 0; | ||
} | ||
|
||
static const struct spi_device_id max1111_ids[] = { | ||
{ "max1110", max1110 }, | ||
{ "max1111", max1111 }, | ||
{ "max1112", max1112 }, | ||
{ "max1113", max1113 }, | ||
{ }, | ||
}; | ||
MODULE_DEVICE_TABLE(spi, max1111_ids); | ||
|
||
static struct spi_driver max1111_driver = { | ||
.driver = { | ||
.name = "max1111", | ||
.owner = THIS_MODULE, | ||
}, | ||
.id_table = max1111_ids, | ||
.probe = max1111_probe, | ||
.remove = __devexit_p(max1111_remove), | ||
}; | ||
|
||
module_spi_driver(max1111_driver); | ||
|
||
MODULE_AUTHOR("Eric Miao <[email protected]>"); | ||
MODULE_DESCRIPTION("MAX1111 ADC Driver"); | ||
MODULE_DESCRIPTION("MAX1110/MAX1111/MAX1112/MAX1113 ADC Driver"); | ||
MODULE_LICENSE("GPL"); | ||
MODULE_ALIAS("spi:max1111"); |