diff options
-rw-r--r-- | drivers/staging/iio/magnetometer/Kconfig | 8 | ||||
-rw-r--r-- | drivers/staging/iio/magnetometer/hmc5843.c | 186 |
2 files changed, 149 insertions, 45 deletions
diff --git a/drivers/staging/iio/magnetometer/Kconfig b/drivers/staging/iio/magnetometer/Kconfig index 722c4e13f713..b9d932595ba9 100644 --- a/drivers/staging/iio/magnetometer/Kconfig +++ b/drivers/staging/iio/magnetometer/Kconfig | |||
@@ -15,13 +15,13 @@ config SENSORS_AK8975 | |||
15 | will be called ak8975. | 15 | will be called ak8975. |
16 | 16 | ||
17 | config SENSORS_HMC5843 | 17 | config SENSORS_HMC5843 |
18 | tristate "Honeywell HMC5843 3-Axis Magnetometer" | 18 | tristate "Honeywell HMC5843/5883/5883L 3-Axis Magnetometer" |
19 | depends on I2C | 19 | depends on I2C |
20 | help | 20 | help |
21 | Say Y here to add support for the Honeywell HMC 5843 3-Axis | 21 | Say Y here to add support for the Honeywell HMC5843, HMC5883 and |
22 | Magnetometer (digital compass). | 22 | HMC5883L 3-Axis Magnetometer (digital compass). |
23 | 23 | ||
24 | To compile this driver as a module, choose M here: the module | 24 | To compile this driver as a module, choose M here: the module |
25 | will be called hmc5843 | 25 | will be called hmc5843. |
26 | 26 | ||
27 | endmenu | 27 | endmenu |
diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c index 32f19b7493d9..c1fa09f07625 100644 --- a/drivers/staging/iio/magnetometer/hmc5843.c +++ b/drivers/staging/iio/magnetometer/hmc5843.c | |||
@@ -2,6 +2,8 @@ | |||
2 | Author: Shubhrajyoti Datta <shubhrajyoti@ti.com> | 2 | Author: Shubhrajyoti Datta <shubhrajyoti@ti.com> |
3 | Acknowledgement: Jonathan Cameron <jic23@cam.ac.uk> for valuable inputs. | 3 | Acknowledgement: Jonathan Cameron <jic23@cam.ac.uk> for valuable inputs. |
4 | 4 | ||
5 | Support for HMC5883 and HMC5883L by Peter Meerwald <pmeerw@pmeerw.net>. | ||
6 | |||
5 | This program is free software; you can redistribute it and/or modify | 7 | This program is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published by | 8 | it under the terms of the GNU General Public License as published by |
7 | the Free Software Foundation; either version 2 of the License, or | 9 | the Free Software Foundation; either version 2 of the License, or |
@@ -44,6 +46,11 @@ | |||
44 | #define HMC5843_ID_REG_B 0x0B | 46 | #define HMC5843_ID_REG_B 0x0B |
45 | #define HMC5843_ID_REG_C 0x0C | 47 | #define HMC5843_ID_REG_C 0x0C |
46 | 48 | ||
49 | enum hmc5843_ids { | ||
50 | HMC5843_ID, | ||
51 | HMC5883_ID, | ||
52 | HMC5883L_ID, | ||
53 | }; | ||
47 | 54 | ||
48 | /* | 55 | /* |
49 | * Beware: identification of the HMC5883 is still "H43"; | 56 | * Beware: identification of the HMC5883 is still "H43"; |
@@ -103,8 +110,16 @@ static const int hmc5843_regval_to_nanoscale[] = { | |||
103 | 6173, 7692, 10309, 12821, 18868, 21739, 25641, 35714 | 110 | 6173, 7692, 10309, 12821, 18868, 21739, 25641, 35714 |
104 | }; | 111 | }; |
105 | 112 | ||
113 | static const int hmc5883_regval_to_nanoscale[] = { | ||
114 | 7812, 9766, 13021, 16287, 24096, 27701, 32573, 45662 | ||
115 | }; | ||
116 | |||
117 | static const int hmc5883l_regval_to_nanoscale[] = { | ||
118 | 7299, 9174, 12195, 15152, 22727, 25641, 30303, 43478 | ||
119 | }; | ||
120 | |||
106 | /* | 121 | /* |
107 | * From the datasheet: | 122 | * From the HMC5843 datasheet: |
108 | * Value | Sensor input field range (Ga) | Gain (counts/milli-Gauss) | 123 | * Value | Sensor input field range (Ga) | Gain (counts/milli-Gauss) |
109 | * 0 | (+-)0.7 | 1620 | 124 | * 0 | (+-)0.7 | 1620 |
110 | * 1 | (+-)1.0 | 1300 | 125 | * 1 | (+-)1.0 | 1300 |
@@ -114,44 +129,75 @@ static const int hmc5843_regval_to_nanoscale[] = { | |||
114 | * 5 | (+-)3.8 | 460 | 129 | * 5 | (+-)3.8 | 460 |
115 | * 6 | (+-)4.5 | 390 | 130 | * 6 | (+-)4.5 | 390 |
116 | * 7 | (+-)6.5 | 280 | 131 | * 7 | (+-)6.5 | 280 |
132 | * | ||
133 | * From the HMC5883 datasheet: | ||
134 | * Value | Recommended sensor field range (Ga) | Gain (counts/Gauss) | ||
135 | * 0 | (+-)0.9 | 1280 | ||
136 | * 1 | (+-)1.2 | 1024 | ||
137 | * 2 | (+-)1.9 | 768 | ||
138 | * 3 | (+-)2.5 | 614 | ||
139 | * 4 | (+-)4.0 | 415 | ||
140 | * 5 | (+-)4.6 | 361 | ||
141 | * 6 | (+-)5.5 | 307 | ||
142 | * 7 | (+-)7.9 | 219 | ||
143 | * | ||
144 | * From the HMC5883L datasheet: | ||
145 | * Value | Recommended sensor field range (Ga) | Gain (LSB/Gauss) | ||
146 | * 0 | (+-)0.88 | 1370 | ||
147 | * 1 | (+-)1.3 | 1090 | ||
148 | * 2 | (+-)1.9 | 820 | ||
149 | * 3 | (+-)2.5 | 660 | ||
150 | * 4 | (+-)4.0 | 440 | ||
151 | * 5 | (+-)4.7 | 390 | ||
152 | * 6 | (+-)5.6 | 330 | ||
153 | * 7 | (+-)8.1 | 230 | ||
117 | */ | 154 | */ |
118 | static const int hmc5843_regval_to_input_field_mga[] = { | 155 | static const int hmc5843_regval_to_input_field_mga[] = { |
119 | 700, | 156 | 700, 1000, 1500, 2000, 3200, 3800, 4500, 6500 |
120 | 1000, | 157 | }; |
121 | 1500, | 158 | |
122 | 2000, | 159 | static const int hmc5883_regval_to_input_field_mga[] = { |
123 | 3200, | 160 | 900, 1200, 1900, 2500, 4000, 4600, 5500, 7900 |
124 | 3800, | 161 | }; |
125 | 4500, | 162 | |
126 | 6500 | 163 | static const int hmc5883l_regval_to_input_field_mga[] = { |
164 | 880, 1300, 1900, 2500, 4000, 4700, 5600, 8100 | ||
127 | }; | 165 | }; |
128 | 166 | ||
129 | /* | 167 | /* |
130 | * From the datasheet: | 168 | * From the datasheet: |
131 | * Value | Data output rate (Hz) | 169 | * Value | HMC5843 | HMC5883/HMC5883L |
132 | * 0 | 0.5 | 170 | * | Data output rate (Hz) | Data output rate (Hz) |
133 | * 1 | 1 | 171 | * 0 | 0.5 | 0.75 |
134 | * 2 | 2 | 172 | * 1 | 1 | 1.5 |
135 | * 3 | 5 | 173 | * 2 | 2 | 3 |
136 | * 4 | 10 (default) | 174 | * 3 | 5 | 7.5 |
137 | * 5 | 20 | 175 | * 4 | 10 (default) | 15 |
138 | * 6 | 50 | 176 | * 5 | 20 | 30 |
139 | * 7 | Not used | 177 | * 6 | 50 | 75 |
178 | * 7 | Not used | Not used | ||
140 | */ | 179 | */ |
141 | static const char * const hmc5843_regval_to_sample_freq[] = { | 180 | static const char * const hmc5843_regval_to_sample_freq[] = { |
142 | "0.5", | 181 | "0.5", "1", "2", "5", "10", "20", "50", |
143 | "1", | 182 | }; |
144 | "2", | 183 | |
145 | "5", | 184 | static const char * const hmc5883_regval_to_sample_freq[] = { |
146 | "10", | 185 | "0.75", "1.5", "3", "7.5", "15", "30", "75", |
147 | "20", | ||
148 | "50", | ||
149 | }; | 186 | }; |
150 | 187 | ||
151 | /* Addresses to scan: 0x1E */ | 188 | /* Addresses to scan: 0x1E */ |
152 | static const unsigned short normal_i2c[] = { HMC5843_I2C_ADDRESS, | 189 | static const unsigned short normal_i2c[] = { HMC5843_I2C_ADDRESS, |
153 | I2C_CLIENT_END }; | 190 | I2C_CLIENT_END }; |
154 | 191 | ||
192 | /* Describe chip variants */ | ||
193 | struct hmc5843_chip_info { | ||
194 | const struct iio_chan_spec *channels; | ||
195 | int num_channels; | ||
196 | const char * const *regval_to_sample_freq; | ||
197 | const int *regval_to_input_field_mga; | ||
198 | const int *regval_to_nanoscale; | ||
199 | }; | ||
200 | |||
155 | /* Each client has this additional data */ | 201 | /* Each client has this additional data */ |
156 | struct hmc5843_data { | 202 | struct hmc5843_data { |
157 | struct mutex lock; | 203 | struct mutex lock; |
@@ -159,6 +205,7 @@ struct hmc5843_data { | |||
159 | u8 meas_conf; | 205 | u8 meas_conf; |
160 | u8 operating_mode; | 206 | u8 operating_mode; |
161 | u8 range; | 207 | u8 range; |
208 | const struct hmc5843_chip_info *variant; | ||
162 | }; | 209 | }; |
163 | 210 | ||
164 | /* The lower two bits contain the current conversion mode */ | 211 | /* The lower two bits contain the current conversion mode */ |
@@ -334,7 +381,27 @@ static IIO_DEVICE_ATTR(meas_conf, | |||
334 | hmc5843_set_measurement_configuration, | 381 | hmc5843_set_measurement_configuration, |
335 | 0); | 382 | 0); |
336 | 383 | ||
337 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("0.5 1 2 5 10 20 50"); | 384 | static ssize_t hmc5843_show_sampling_frequencies_available(struct device *dev, |
385 | struct device_attribute *attr, | ||
386 | char *buf) | ||
387 | { | ||
388 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | ||
389 | struct hmc5843_data *data = iio_priv(indio_dev); | ||
390 | ssize_t total_n = 0; | ||
391 | int i; | ||
392 | |||
393 | for (i = 0; i < HMC5843_RATE_NOT_USED; i++) { | ||
394 | ssize_t n = sprintf(buf, "%s ", data->variant->regval_to_sample_freq[i]); | ||
395 | buf += n; | ||
396 | total_n += n; | ||
397 | } | ||
398 | /* replace trailing space by newline */ | ||
399 | buf[-1] = '\n'; | ||
400 | |||
401 | return total_n; | ||
402 | } | ||
403 | |||
404 | static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(hmc5843_show_sampling_frequencies_available); | ||
338 | 405 | ||
339 | static s32 hmc5843_set_rate(struct i2c_client *client, | 406 | static s32 hmc5843_set_rate(struct i2c_client *client, |
340 | u8 rate) | 407 | u8 rate) |
@@ -356,12 +423,11 @@ static s32 hmc5843_set_rate(struct i2c_client *client, | |||
356 | static int hmc5843_check_sampling_frequency(struct hmc5843_data *data, | 423 | static int hmc5843_check_sampling_frequency(struct hmc5843_data *data, |
357 | const char *buf) | 424 | const char *buf) |
358 | { | 425 | { |
359 | const char * const *samp_freq = hmc5843_regval_to_sample_freq; | 426 | const char * const *samp_freq = data->variant->regval_to_sample_freq; |
360 | int i; | 427 | int i; |
361 | 428 | ||
362 | for (i = 0; i < HMC5843_RATE_NOT_USED; i++) { | 429 | for (i = 0; i < HMC5843_RATE_NOT_USED; i++) { |
363 | if (strncmp(buf, samp_freq[i], | 430 | if (sysfs_streq(buf, samp_freq[i])) |
364 | strlen(samp_freq[i])) == 0) | ||
365 | return i; | 431 | return i; |
366 | } | 432 | } |
367 | 433 | ||
@@ -404,13 +470,14 @@ static ssize_t hmc5843_show_sampling_frequency(struct device *dev, | |||
404 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 470 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
405 | struct i2c_client *client = to_i2c_client(indio_dev->dev.parent); | 471 | struct i2c_client *client = to_i2c_client(indio_dev->dev.parent); |
406 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | 472 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
473 | struct hmc5843_data *data = iio_priv(indio_dev); | ||
407 | s32 rate; | 474 | s32 rate; |
408 | 475 | ||
409 | rate = i2c_smbus_read_byte_data(client, this_attr->address); | 476 | rate = i2c_smbus_read_byte_data(client, this_attr->address); |
410 | if (rate < 0) | 477 | if (rate < 0) |
411 | return rate; | 478 | return rate; |
412 | rate = (rate & HMC5843_RATE_BITMASK) >> HMC5843_RATE_OFFSET; | 479 | rate = (rate & HMC5843_RATE_BITMASK) >> HMC5843_RATE_OFFSET; |
413 | return sprintf(buf, "%s\n", hmc5843_regval_to_sample_freq[rate]); | 480 | return sprintf(buf, "%s\n", data->variant->regval_to_sample_freq[rate]); |
414 | } | 481 | } |
415 | 482 | ||
416 | static IIO_DEVICE_ATTR(sampling_frequency, | 483 | static IIO_DEVICE_ATTR(sampling_frequency, |
@@ -428,7 +495,7 @@ static ssize_t hmc5843_show_range_gain(struct device *dev, | |||
428 | struct hmc5843_data *data = iio_priv(indio_dev); | 495 | struct hmc5843_data *data = iio_priv(indio_dev); |
429 | 496 | ||
430 | range = data->range; | 497 | range = data->range; |
431 | return sprintf(buf, "%d\n", hmc5843_regval_to_input_field_mga[range]); | 498 | return sprintf(buf, "%d\n", data->variant->regval_to_input_field_mga[range]); |
432 | } | 499 | } |
433 | 500 | ||
434 | static ssize_t hmc5843_set_range_gain(struct device *dev, | 501 | static ssize_t hmc5843_set_range_gain(struct device *dev, |
@@ -486,7 +553,7 @@ static int hmc5843_read_raw(struct iio_dev *indio_dev, | |||
486 | val); | 553 | val); |
487 | case IIO_CHAN_INFO_SCALE: | 554 | case IIO_CHAN_INFO_SCALE: |
488 | *val = 0; | 555 | *val = 0; |
489 | *val2 = hmc5843_regval_to_nanoscale[data->range]; | 556 | *val2 = data->variant->regval_to_nanoscale[data->range]; |
490 | return IIO_VAL_INT_PLUS_NANO; | 557 | return IIO_VAL_INT_PLUS_NANO; |
491 | }; | 558 | }; |
492 | return -EINVAL; | 559 | return -EINVAL; |
@@ -508,12 +575,18 @@ static const struct iio_chan_spec hmc5843_channels[] = { | |||
508 | HMC5843_CHANNEL(Z, HMC5843_DATA_OUT_Z_MSB_REG), | 575 | HMC5843_CHANNEL(Z, HMC5843_DATA_OUT_Z_MSB_REG), |
509 | }; | 576 | }; |
510 | 577 | ||
578 | static const struct iio_chan_spec hmc5883_channels[] = { | ||
579 | HMC5843_CHANNEL(X, HMC5843_DATA_OUT_X_MSB_REG), | ||
580 | HMC5843_CHANNEL(Y, HMC5883_DATA_OUT_Y_MSB_REG), | ||
581 | HMC5843_CHANNEL(Z, HMC5883_DATA_OUT_Z_MSB_REG), | ||
582 | }; | ||
583 | |||
511 | static struct attribute *hmc5843_attributes[] = { | 584 | static struct attribute *hmc5843_attributes[] = { |
512 | &iio_dev_attr_meas_conf.dev_attr.attr, | 585 | &iio_dev_attr_meas_conf.dev_attr.attr, |
513 | &iio_dev_attr_operating_mode.dev_attr.attr, | 586 | &iio_dev_attr_operating_mode.dev_attr.attr, |
514 | &iio_dev_attr_sampling_frequency.dev_attr.attr, | 587 | &iio_dev_attr_sampling_frequency.dev_attr.attr, |
515 | &iio_dev_attr_in_magn_range.dev_attr.attr, | 588 | &iio_dev_attr_in_magn_range.dev_attr.attr, |
516 | &iio_const_attr_sampling_frequency_available.dev_attr.attr, | 589 | &iio_dev_attr_sampling_frequency_available.dev_attr.attr, |
517 | NULL | 590 | NULL |
518 | }; | 591 | }; |
519 | 592 | ||
@@ -521,6 +594,33 @@ static const struct attribute_group hmc5843_group = { | |||
521 | .attrs = hmc5843_attributes, | 594 | .attrs = hmc5843_attributes, |
522 | }; | 595 | }; |
523 | 596 | ||
597 | static const struct hmc5843_chip_info hmc5843_chip_info_tbl[] = { | ||
598 | [HMC5843_ID] = { | ||
599 | .channels = hmc5843_channels, | ||
600 | .num_channels = ARRAY_SIZE(hmc5843_channels), | ||
601 | .regval_to_sample_freq = hmc5843_regval_to_sample_freq, | ||
602 | .regval_to_input_field_mga = | ||
603 | hmc5843_regval_to_input_field_mga, | ||
604 | .regval_to_nanoscale = hmc5843_regval_to_nanoscale, | ||
605 | }, | ||
606 | [HMC5883_ID] = { | ||
607 | .channels = hmc5883_channels, | ||
608 | .num_channels = ARRAY_SIZE(hmc5883_channels), | ||
609 | .regval_to_sample_freq = hmc5883_regval_to_sample_freq, | ||
610 | .regval_to_input_field_mga = | ||
611 | hmc5883_regval_to_input_field_mga, | ||
612 | .regval_to_nanoscale = hmc5883_regval_to_nanoscale, | ||
613 | }, | ||
614 | [HMC5883L_ID] = { | ||
615 | .channels = hmc5883_channels, | ||
616 | .num_channels = ARRAY_SIZE(hmc5883_channels), | ||
617 | .regval_to_sample_freq = hmc5883_regval_to_sample_freq, | ||
618 | .regval_to_input_field_mga = | ||
619 | hmc5883l_regval_to_input_field_mga, | ||
620 | .regval_to_nanoscale = hmc5883l_regval_to_nanoscale, | ||
621 | }, | ||
622 | }; | ||
623 | |||
524 | static int hmc5843_detect(struct i2c_client *client, | 624 | static int hmc5843_detect(struct i2c_client *client, |
525 | struct i2c_board_info *info) | 625 | struct i2c_board_info *info) |
526 | { | 626 | { |
@@ -540,19 +640,23 @@ static int hmc5843_detect(struct i2c_client *client, | |||
540 | return 0; | 640 | return 0; |
541 | } | 641 | } |
542 | 642 | ||
543 | /* Called when we have found a new HMC5843 */ | 643 | /* Called when we have found a new HMC58X3 */ |
544 | static void hmc5843_init_client(struct i2c_client *client) | 644 | static void hmc5843_init_client(struct i2c_client *client, |
645 | const struct i2c_device_id *id) | ||
545 | { | 646 | { |
546 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | 647 | struct iio_dev *indio_dev = i2c_get_clientdata(client); |
547 | struct hmc5843_data *data = iio_priv(indio_dev); | 648 | struct hmc5843_data *data = iio_priv(indio_dev); |
548 | 649 | ||
650 | data->variant = &hmc5843_chip_info_tbl[id->driver_data]; | ||
651 | indio_dev->channels = data->variant->channels; | ||
652 | indio_dev->num_channels = data->variant->num_channels; | ||
549 | hmc5843_set_meas_conf(client, data->meas_conf); | 653 | hmc5843_set_meas_conf(client, data->meas_conf); |
550 | hmc5843_set_rate(client, data->rate); | 654 | hmc5843_set_rate(client, data->rate); |
551 | hmc5843_configure(client, data->operating_mode); | 655 | hmc5843_configure(client, data->operating_mode); |
552 | i2c_smbus_write_byte_data(client, HMC5843_CONFIG_REG_B, data->range); | 656 | i2c_smbus_write_byte_data(client, HMC5843_CONFIG_REG_B, data->range); |
553 | mutex_init(&data->lock); | 657 | mutex_init(&data->lock); |
554 | 658 | ||
555 | pr_info("HMC5843 initialized\n"); | 659 | pr_info("%s initialized\n", id->name); |
556 | } | 660 | } |
557 | 661 | ||
558 | static const struct iio_info hmc5843_info = { | 662 | static const struct iio_info hmc5843_info = { |
@@ -581,12 +685,10 @@ static int hmc5843_probe(struct i2c_client *client, | |||
581 | data->operating_mode = HMC5843_MODE_CONVERSION_CONTINUOUS; | 685 | data->operating_mode = HMC5843_MODE_CONVERSION_CONTINUOUS; |
582 | 686 | ||
583 | i2c_set_clientdata(client, indio_dev); | 687 | i2c_set_clientdata(client, indio_dev); |
584 | hmc5843_init_client(client); | 688 | hmc5843_init_client(client, id); |
585 | 689 | ||
586 | indio_dev->info = &hmc5843_info; | 690 | indio_dev->info = &hmc5843_info; |
587 | indio_dev->name = id->name; | 691 | indio_dev->name = id->name; |
588 | indio_dev->channels = hmc5843_channels; | ||
589 | indio_dev->num_channels = ARRAY_SIZE(hmc5843_channels); | ||
590 | indio_dev->dev.parent = &client->dev; | 692 | indio_dev->dev.parent = &client->dev; |
591 | indio_dev->modes = INDIO_DIRECT_MODE; | 693 | indio_dev->modes = INDIO_DIRECT_MODE; |
592 | 694 | ||
@@ -639,7 +741,9 @@ static SIMPLE_DEV_PM_OPS(hmc5843_pm_ops, hmc5843_suspend, hmc5843_resume); | |||
639 | #endif | 741 | #endif |
640 | 742 | ||
641 | static const struct i2c_device_id hmc5843_id[] = { | 743 | static const struct i2c_device_id hmc5843_id[] = { |
642 | { "hmc5843", 0 }, | 744 | { "hmc5843", HMC5843_ID }, |
745 | { "hmc5883", HMC5883_ID }, | ||
746 | { "hmc5883l", HMC5883L_ID }, | ||
643 | { } | 747 | { } |
644 | }; | 748 | }; |
645 | MODULE_DEVICE_TABLE(i2c, hmc5843_id); | 749 | MODULE_DEVICE_TABLE(i2c, hmc5843_id); |
@@ -658,5 +762,5 @@ static struct i2c_driver hmc5843_driver = { | |||
658 | module_i2c_driver(hmc5843_driver); | 762 | module_i2c_driver(hmc5843_driver); |
659 | 763 | ||
660 | MODULE_AUTHOR("Shubhrajyoti Datta <shubhrajyoti@ti.com"); | 764 | MODULE_AUTHOR("Shubhrajyoti Datta <shubhrajyoti@ti.com"); |
661 | MODULE_DESCRIPTION("HMC5843 driver"); | 765 | MODULE_DESCRIPTION("HMC5843/5883/5883L driver"); |
662 | MODULE_LICENSE("GPL"); | 766 | MODULE_LICENSE("GPL"); |