|
@@ -59,6 +59,12 @@ static const unsigned short normal_i2c[] = {
|
|
|
#define ADC128_REG_MAN_ID 0x3e
|
|
|
#define ADC128_REG_DEV_ID 0x3f
|
|
|
|
|
|
+/* No. of voltage entries in adc128_attrs */
|
|
|
+#define ADC128_ATTR_NUM_VOLT (8 * 4)
|
|
|
+
|
|
|
+/* Voltage inputs visible per operation mode */
|
|
|
+static const u8 num_inputs[] = { 7, 8, 4, 6 };
|
|
|
+
|
|
|
struct adc128_data {
|
|
|
struct i2c_client *client;
|
|
|
struct regulator *regulator;
|
|
@@ -68,7 +74,7 @@ struct adc128_data {
|
|
|
bool valid; /* true if following fields are valid */
|
|
|
unsigned long last_updated; /* In jiffies */
|
|
|
|
|
|
- u16 in[3][7]; /* Register value, normalized to 12 bit
|
|
|
+ u16 in[3][8]; /* Register value, normalized to 12 bit
|
|
|
* 0: input voltage
|
|
|
* 1: min limit
|
|
|
* 2: max limit
|
|
@@ -89,7 +95,7 @@ static struct adc128_data *adc128_update_device(struct device *dev)
|
|
|
mutex_lock(&data->update_lock);
|
|
|
|
|
|
if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
|
|
|
- for (i = 0; i < 7; i++) {
|
|
|
+ for (i = 0; i < num_inputs[data->mode]; i++) {
|
|
|
rv = i2c_smbus_read_word_swapped(client,
|
|
|
ADC128_REG_IN(i));
|
|
|
if (rv < 0)
|
|
@@ -109,20 +115,25 @@ static struct adc128_data *adc128_update_device(struct device *dev)
|
|
|
data->in[2][i] = rv << 4;
|
|
|
}
|
|
|
|
|
|
- rv = i2c_smbus_read_word_swapped(client, ADC128_REG_TEMP);
|
|
|
- if (rv < 0)
|
|
|
- goto abort;
|
|
|
- data->temp[0] = rv >> 7;
|
|
|
+ if (data->mode != 1) {
|
|
|
+ rv = i2c_smbus_read_word_swapped(client,
|
|
|
+ ADC128_REG_TEMP);
|
|
|
+ if (rv < 0)
|
|
|
+ goto abort;
|
|
|
+ data->temp[0] = rv >> 7;
|
|
|
|
|
|
- rv = i2c_smbus_read_byte_data(client, ADC128_REG_TEMP_MAX);
|
|
|
- if (rv < 0)
|
|
|
- goto abort;
|
|
|
- data->temp[1] = rv << 1;
|
|
|
+ rv = i2c_smbus_read_byte_data(client,
|
|
|
+ ADC128_REG_TEMP_MAX);
|
|
|
+ if (rv < 0)
|
|
|
+ goto abort;
|
|
|
+ data->temp[1] = rv << 1;
|
|
|
|
|
|
- rv = i2c_smbus_read_byte_data(client, ADC128_REG_TEMP_HYST);
|
|
|
- if (rv < 0)
|
|
|
- goto abort;
|
|
|
- data->temp[2] = rv << 1;
|
|
|
+ rv = i2c_smbus_read_byte_data(client,
|
|
|
+ ADC128_REG_TEMP_HYST);
|
|
|
+ if (rv < 0)
|
|
|
+ goto abort;
|
|
|
+ data->temp[2] = rv << 1;
|
|
|
+ }
|
|
|
|
|
|
rv = i2c_smbus_read_byte_data(client, ADC128_REG_ALARM);
|
|
|
if (rv < 0)
|
|
@@ -242,6 +253,25 @@ static ssize_t adc128_show_alarm(struct device *dev,
|
|
|
return sprintf(buf, "%u\n", !!(alarms & mask));
|
|
|
}
|
|
|
|
|
|
+static umode_t adc128_is_visible(struct kobject *kobj,
|
|
|
+ struct attribute *attr, int index)
|
|
|
+{
|
|
|
+ struct device *dev = container_of(kobj, struct device, kobj);
|
|
|
+ struct adc128_data *data = dev_get_drvdata(dev);
|
|
|
+
|
|
|
+ if (index < ADC128_ATTR_NUM_VOLT) {
|
|
|
+ /* Voltage, visible according to num_inputs[] */
|
|
|
+ if (index >= num_inputs[data->mode] * 4)
|
|
|
+ return 0;
|
|
|
+ } else {
|
|
|
+ /* Temperature, visible if not in mode 1 */
|
|
|
+ if (data->mode == 1)
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return attr->mode;
|
|
|
+}
|
|
|
+
|
|
|
static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO,
|
|
|
adc128_show_in, NULL, 0, 0);
|
|
|
static SENSOR_DEVICE_ATTR_2(in0_min, S_IWUSR | S_IRUGO,
|
|
@@ -291,6 +321,13 @@ static SENSOR_DEVICE_ATTR_2(in6_min, S_IWUSR | S_IRUGO,
|
|
|
static SENSOR_DEVICE_ATTR_2(in6_max, S_IWUSR | S_IRUGO,
|
|
|
adc128_show_in, adc128_set_in, 6, 2);
|
|
|
|
|
|
+static SENSOR_DEVICE_ATTR_2(in7_input, S_IRUGO,
|
|
|
+ adc128_show_in, NULL, 7, 0);
|
|
|
+static SENSOR_DEVICE_ATTR_2(in7_min, S_IWUSR | S_IRUGO,
|
|
|
+ adc128_show_in, adc128_set_in, 7, 1);
|
|
|
+static SENSOR_DEVICE_ATTR_2(in7_max, S_IWUSR | S_IRUGO,
|
|
|
+ adc128_show_in, adc128_set_in, 7, 2);
|
|
|
+
|
|
|
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, adc128_show_temp, NULL, 0);
|
|
|
static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
|
|
|
adc128_show_temp, adc128_set_temp, 1);
|
|
@@ -304,44 +341,54 @@ static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, adc128_show_alarm, NULL, 3);
|
|
|
static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, adc128_show_alarm, NULL, 4);
|
|
|
static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, adc128_show_alarm, NULL, 5);
|
|
|
static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, adc128_show_alarm, NULL, 6);
|
|
|
+static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, adc128_show_alarm, NULL, 7);
|
|
|
static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, adc128_show_alarm, NULL, 7);
|
|
|
|
|
|
static struct attribute *adc128_attrs[] = {
|
|
|
- &sensor_dev_attr_in0_min.dev_attr.attr,
|
|
|
- &sensor_dev_attr_in1_min.dev_attr.attr,
|
|
|
- &sensor_dev_attr_in2_min.dev_attr.attr,
|
|
|
- &sensor_dev_attr_in3_min.dev_attr.attr,
|
|
|
- &sensor_dev_attr_in4_min.dev_attr.attr,
|
|
|
- &sensor_dev_attr_in5_min.dev_attr.attr,
|
|
|
- &sensor_dev_attr_in6_min.dev_attr.attr,
|
|
|
- &sensor_dev_attr_in0_max.dev_attr.attr,
|
|
|
- &sensor_dev_attr_in1_max.dev_attr.attr,
|
|
|
- &sensor_dev_attr_in2_max.dev_attr.attr,
|
|
|
- &sensor_dev_attr_in3_max.dev_attr.attr,
|
|
|
- &sensor_dev_attr_in4_max.dev_attr.attr,
|
|
|
- &sensor_dev_attr_in5_max.dev_attr.attr,
|
|
|
- &sensor_dev_attr_in6_max.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in0_alarm.dev_attr.attr,
|
|
|
&sensor_dev_attr_in0_input.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in0_max.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in0_min.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in1_alarm.dev_attr.attr,
|
|
|
&sensor_dev_attr_in1_input.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in1_max.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in1_min.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in2_alarm.dev_attr.attr,
|
|
|
&sensor_dev_attr_in2_input.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in2_max.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in2_min.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in3_alarm.dev_attr.attr,
|
|
|
&sensor_dev_attr_in3_input.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in3_max.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in3_min.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in4_alarm.dev_attr.attr,
|
|
|
&sensor_dev_attr_in4_input.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in4_max.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in4_min.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in5_alarm.dev_attr.attr,
|
|
|
&sensor_dev_attr_in5_input.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in5_max.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in5_min.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in6_alarm.dev_attr.attr,
|
|
|
&sensor_dev_attr_in6_input.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in6_max.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in6_min.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in7_alarm.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in7_input.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in7_max.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_in7_min.dev_attr.attr,
|
|
|
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
|
|
&sensor_dev_attr_temp1_max.dev_attr.attr,
|
|
|
- &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
|
|
|
- &sensor_dev_attr_in0_alarm.dev_attr.attr,
|
|
|
- &sensor_dev_attr_in1_alarm.dev_attr.attr,
|
|
|
- &sensor_dev_attr_in2_alarm.dev_attr.attr,
|
|
|
- &sensor_dev_attr_in3_alarm.dev_attr.attr,
|
|
|
- &sensor_dev_attr_in4_alarm.dev_attr.attr,
|
|
|
- &sensor_dev_attr_in5_alarm.dev_attr.attr,
|
|
|
- &sensor_dev_attr_in6_alarm.dev_attr.attr,
|
|
|
&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
|
|
|
+ &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
|
|
|
NULL
|
|
|
};
|
|
|
-ATTRIBUTE_GROUPS(adc128);
|
|
|
+
|
|
|
+static struct attribute_group adc128_group = {
|
|
|
+ .attrs = adc128_attrs,
|
|
|
+ .is_visible = adc128_is_visible,
|
|
|
+};
|
|
|
+__ATTRIBUTE_GROUPS(adc128);
|
|
|
|
|
|
static int adc128_detect(struct i2c_client *client, struct i2c_board_info *info)
|
|
|
{
|
|
@@ -446,9 +493,8 @@ static int adc128_probe(struct i2c_client *client,
|
|
|
|
|
|
/* Operation mode is optional and defaults to mode 0 */
|
|
|
if (of_property_read_u8(dev->of_node, "ti,mode", &data->mode) == 0) {
|
|
|
- /* Currently only mode 0 supported */
|
|
|
- if (data->mode != 0) {
|
|
|
- dev_err(dev, "unsupported operation mode %d\n",
|
|
|
+ if (data->mode > 3) {
|
|
|
+ dev_err(dev, "invalid operation mode %d\n",
|
|
|
data->mode);
|
|
|
err = -EINVAL;
|
|
|
goto error;
|