• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/staging/iio/magnetometer/
1/*  Copyright (C) 2010 Texas Instruments
2    Author: Shubhrajyoti Datta <shubhrajyoti@ti.com>
3    Acknowledgement: Jonathan Cameron <jic23@cam.ac.uk> for valuable inputs.
4
5    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
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18*/
19
20#include <linux/module.h>
21#include <linux/init.h>
22#include <linux/i2c.h>
23#include <linux/slab.h>
24#include <linux/types.h>
25#include "../iio.h"
26#include "../sysfs.h"
27#include "magnet.h"
28
29#define HMC5843_I2C_ADDRESS			0x1E
30
31#define HMC5843_CONFIG_REG_A			0x00
32#define HMC5843_CONFIG_REG_B			0x01
33#define HMC5843_MODE_REG			0x02
34#define HMC5843_DATA_OUT_X_MSB_REG		0x03
35#define HMC5843_DATA_OUT_X_LSB_REG		0x04
36#define HMC5843_DATA_OUT_Y_MSB_REG		0x05
37#define HMC5843_DATA_OUT_Y_LSB_REG		0x06
38#define HMC5843_DATA_OUT_Z_MSB_REG		0x07
39#define HMC5843_DATA_OUT_Z_LSB_REG		0x08
40#define HMC5843_STATUS_REG			0x09
41#define HMC5843_ID_REG_A			0x0A
42#define HMC5843_ID_REG_B			0x0B
43#define HMC5843_ID_REG_C			0x0C
44
45#define HMC5843_ID_REG_LENGTH			0x03
46#define HMC5843_ID_STRING			"H43"
47
48/*
49 * Range settings in  (+-)Ga
50 * */
51#define RANGE_GAIN_OFFSET			0x05
52
53#define	RANGE_0_7				0x00
54#define	RANGE_1_0				0x01 /* default */
55#define	RANGE_1_5				0x02
56#define	RANGE_2_0				0x03
57#define	RANGE_3_2				0x04
58#define	RANGE_3_8				0x05
59#define	RANGE_4_5				0x06
60#define	RANGE_6_5				0x07 /* Not recommended */
61
62/*
63 * Device status
64 */
65#define	DATA_READY  				0x01
66#define	DATA_OUTPUT_LOCK  			0x02
67#define	VOLTAGE_REGULATOR_ENABLED  		0x04
68
69/*
70 * Mode register configuration
71 */
72#define	MODE_CONVERSION_CONTINUOUS		0x00
73#define	MODE_CONVERSION_SINGLE			0x01
74#define	MODE_IDLE				0x02
75#define	MODE_SLEEP				0x03
76
77/* Minimum Data Output Rate in 1/10 Hz  */
78#define RATE_OFFSET				0x02
79#define RATE_BITMASK				0x1C
80#define	RATE_5					0x00
81#define	RATE_10					0x01
82#define	RATE_20					0x02
83#define	RATE_50					0x03
84#define	RATE_100				0x04
85#define	RATE_200				0x05
86#define	RATE_500				0x06
87#define	RATE_NOT_USED				0x07
88
89/*
90 * Device Configutration
91 */
92#define	CONF_NORMAL  				0x00
93#define	CONF_POSITIVE_BIAS			0x01
94#define	CONF_NEGATIVE_BIAS			0x02
95#define	CONF_NOT_USED				0x03
96#define	MEAS_CONF_MASK				0x03
97
98static const int regval_to_counts_per_mg[] = {
99	1620,
100	1300,
101	970,
102	780,
103	530,
104	460,
105	390,
106	280
107};
108static const int regval_to_input_field_mg[] = {
109	700,
110	1000,
111	1500,
112	2000,
113	3200,
114	3800,
115	4500,
116	6500
117};
118static const char *regval_to_samp_freq[] = {
119	"0.5",
120	"1",
121	"2",
122	"5",
123	"10",
124	"20",
125	"50",
126};
127
128/* Addresses to scan: 0x1E */
129static const unsigned short normal_i2c[] = { HMC5843_I2C_ADDRESS,
130							I2C_CLIENT_END };
131
132/* Each client has this additional data */
133struct hmc5843_data {
134	struct iio_dev	*indio_dev;
135	struct mutex lock;
136	u8		rate;
137	u8		meas_conf;
138	u8		operating_mode;
139	u8		range;
140};
141
142static void hmc5843_init_client(struct i2c_client *client);
143
144static s32 hmc5843_configure(struct i2c_client *client,
145				       u8 operating_mode)
146{
147	/* The lower two bits contain the current conversion mode */
148	return i2c_smbus_write_byte_data(client,
149					HMC5843_MODE_REG,
150					(operating_mode & 0x03));
151}
152
153/* Return the measurement value from the  specified channel */
154static ssize_t hmc5843_read_measurement(struct device *dev,
155		struct device_attribute *attr,
156		char *buf)
157{
158	struct iio_dev *indio_dev = dev_get_drvdata(dev);
159	struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
160	s16 coordinate_val;
161	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
162	struct hmc5843_data *data = indio_dev->dev_data;
163	s32 result;
164
165	mutex_lock(&data->lock);
166
167	result = i2c_smbus_read_byte_data(client, HMC5843_STATUS_REG);
168	while (!(result & DATA_READY))
169		result = i2c_smbus_read_byte_data(client, HMC5843_STATUS_REG);
170
171	result = i2c_smbus_read_word_data(client, this_attr->address);
172	mutex_unlock(&data->lock);
173	if (result < 0)
174		return -EINVAL;
175
176	coordinate_val	= (s16)swab16((u16)result);
177	return sprintf(buf, "%d\n", coordinate_val);
178}
179static IIO_DEV_ATTR_MAGN_X(hmc5843_read_measurement,
180		HMC5843_DATA_OUT_X_MSB_REG);
181static IIO_DEV_ATTR_MAGN_Y(hmc5843_read_measurement,
182		HMC5843_DATA_OUT_Y_MSB_REG);
183static IIO_DEV_ATTR_MAGN_Z(hmc5843_read_measurement,
184		HMC5843_DATA_OUT_Z_MSB_REG);
185
186/*
187 * From the datasheet
188 * 0 - Continuous-Conversion Mode: In continuous-conversion mode, the
189 * device continuously performs conversions an places the result in the
190 * data register.
191 *
192 * 1 - Single-Conversion Mode : device performs a single measurement,
193 *  sets RDY high and returned to sleep mode
194 *
195 * 2 - Idle Mode :  Device is placed in idle mode.
196 *
197 * 3 - Sleep Mode. Device is placed in sleep mode.
198 *
199 */
200static ssize_t hmc5843_show_operating_mode(struct device *dev,
201					struct device_attribute *attr,
202					char *buf)
203{
204	struct iio_dev *indio_dev = dev_get_drvdata(dev);
205	struct hmc5843_data *data = indio_dev->dev_data;
206	return sprintf(buf, "%d\n", data->operating_mode);
207}
208
209static ssize_t hmc5843_set_operating_mode(struct device *dev,
210				struct device_attribute *attr,
211				const char *buf,
212				size_t count)
213{
214	struct iio_dev *indio_dev = dev_get_drvdata(dev);
215	struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
216	struct hmc5843_data *data = indio_dev->dev_data;
217	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
218	unsigned long operating_mode = 0;
219	s32 status;
220	int error;
221	mutex_lock(&data->lock);
222	error = strict_strtoul(buf, 10, &operating_mode);
223	if (error)
224		return error;
225	dev_dbg(dev, "set Conversion mode to %lu\n", operating_mode);
226	if (operating_mode > MODE_SLEEP)
227			return -EINVAL;
228
229	status = i2c_smbus_write_byte_data(client, this_attr->address,
230					operating_mode);
231	if (status) {
232		count = -EINVAL;
233		goto exit;
234	}
235	data->operating_mode = operating_mode;
236
237exit:
238	mutex_unlock(&data->lock);
239	return count;
240}
241static IIO_DEVICE_ATTR(operating_mode,
242			S_IWUSR | S_IRUGO,
243			hmc5843_show_operating_mode,
244			hmc5843_set_operating_mode,
245			HMC5843_MODE_REG);
246
247/*
248 * API for setting the measurement configuration to
249 * Normal, Positive bias and Negative bias
250 * From the datasheet
251 *
252 * Normal measurement configuration (default): In normal measurement
253 * configuration the device follows normal measurement flow. Pins BP and BN
254 * are left floating and high impedance.
255 *
256 * Positive bias configuration: In positive bias configuration, a positive
257 * current is forced across the resistive load on pins BP and BN.
258 *
259 * Negative bias configuration. In negative bias configuration, a negative
260 * current is forced across the resistive load on pins BP and BN.
261 *
262 */
263static s32 hmc5843_set_meas_conf(struct i2c_client *client,
264				      u8 meas_conf)
265{
266	struct hmc5843_data *data = i2c_get_clientdata(client);
267	u8 reg_val;
268	reg_val = (meas_conf & MEAS_CONF_MASK) |  (data->rate << RATE_OFFSET);
269	return i2c_smbus_write_byte_data(client, HMC5843_CONFIG_REG_A, reg_val);
270}
271
272static ssize_t hmc5843_show_measurement_configuration(struct device *dev,
273						struct device_attribute *attr,
274						char *buf)
275{
276	struct iio_dev *indio_dev = dev_get_drvdata(dev);
277	struct hmc5843_data *data = indio_dev->dev_data;
278	return sprintf(buf, "%d\n", data->meas_conf);
279}
280
281static ssize_t hmc5843_set_measurement_configuration(struct device *dev,
282						struct device_attribute *attr,
283						const char *buf,
284						size_t count)
285{
286	struct iio_dev *indio_dev = dev_get_drvdata(dev);
287	struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
288	struct hmc5843_data *data = i2c_get_clientdata(client);
289	unsigned long meas_conf = 0;
290	int error = strict_strtoul(buf, 10, &meas_conf);
291	if (error)
292		return error;
293	mutex_lock(&data->lock);
294
295	dev_dbg(dev, "set mode to %lu\n", meas_conf);
296	if (hmc5843_set_meas_conf(client, meas_conf)) {
297		count = -EINVAL;
298		goto exit;
299	}
300	data->meas_conf = meas_conf;
301
302exit:
303	mutex_unlock(&data->lock);
304	return count;
305}
306static IIO_DEVICE_ATTR(meas_conf,
307			S_IWUSR | S_IRUGO,
308			hmc5843_show_measurement_configuration,
309			hmc5843_set_measurement_configuration,
310			0);
311
312/*
313 * From Datasheet
314 * The table shows the minimum data output
315 * Value	| Minimum data output rate(Hz)
316 * 0		| 0.5
317 * 1		| 1
318 * 2		| 2
319 * 3		| 5
320 * 4		| 10 (default)
321 * 5		| 20
322 * 6		| 50
323 * 7		| Not used
324 */
325static IIO_CONST_ATTR_AVAIL_SAMP_FREQ("0.5 1 2 5 10 20 50");
326
327static s32 hmc5843_set_rate(struct i2c_client *client,
328				u8 rate)
329{
330	struct hmc5843_data *data = i2c_get_clientdata(client);
331	u8 reg_val;
332
333	reg_val = (data->meas_conf) |  (rate << RATE_OFFSET);
334	if (rate >= RATE_NOT_USED) {
335		dev_err(&client->dev,
336			"This data output rate is not supported \n");
337		return -EINVAL;
338	}
339	return i2c_smbus_write_byte_data(client, HMC5843_CONFIG_REG_A, reg_val);
340}
341
342static ssize_t set_sampling_frequency(struct device *dev,
343					struct device_attribute *attr,
344					const char *buf, size_t count)
345{
346
347	struct iio_dev *indio_dev = dev_get_drvdata(dev);
348	struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
349	struct hmc5843_data *data = indio_dev->dev_data;
350	unsigned long rate = 0;
351
352	if (strncmp(buf, "0.5" , 3) == 0)
353		rate = RATE_5;
354	else if (strncmp(buf, "1" , 1) == 0)
355		rate = RATE_10;
356	else if (strncmp(buf, "2", 1) == 0)
357		rate = RATE_20;
358	else if (strncmp(buf, "5", 1) == 0)
359		rate = RATE_50;
360	else if (strncmp(buf, "10", 2) == 0)
361		rate = RATE_100;
362	else if (strncmp(buf, "20" , 2) == 0)
363		rate = RATE_200;
364	else if (strncmp(buf, "50" , 2) == 0)
365		rate = RATE_500;
366	else
367		return -EINVAL;
368
369	mutex_lock(&data->lock);
370	dev_dbg(dev, "set rate to %lu\n", rate);
371	if (hmc5843_set_rate(client, rate)) {
372		count = -EINVAL;
373		goto exit;
374	}
375	data->rate = rate;
376
377exit:
378	mutex_unlock(&data->lock);
379	return count;
380}
381
382static ssize_t show_sampling_frequency(struct device *dev,
383			struct device_attribute *attr, char *buf)
384{
385	struct iio_dev *indio_dev = dev_get_drvdata(dev);
386	struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
387	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
388	u32 rate;
389
390	rate = i2c_smbus_read_byte_data(client,  this_attr->address);
391	if (rate < 0)
392		return -EINVAL;
393	rate = (rate & RATE_BITMASK) >> RATE_OFFSET;
394	return sprintf(buf, "%s\n", regval_to_samp_freq[rate]);
395}
396static IIO_DEVICE_ATTR(sampling_frequency,
397			S_IWUSR | S_IRUGO,
398			show_sampling_frequency,
399			set_sampling_frequency,
400			HMC5843_CONFIG_REG_A);
401
402/*
403 * From Datasheet
404 *	Nominal gain settings
405 * Value	| Sensor Input Field Range(Ga)	| Gain(counts/ milli-gauss)
406 *0		|(+-)0.7			|1620
407 *1		|(+-)1.0			|1300
408 *2		|(+-)1.5			|970
409 *3		|(+-)2.0			|780
410 *4		|(+-)3.2			|530
411 *5		|(+-)3.8			|460
412 *6		|(+-)4.5			|390
413 *7		|(+-)6.5			|280
414 */
415static ssize_t show_range(struct device *dev,
416				struct device_attribute *attr,
417				char *buf)
418{
419	u8 range;
420	struct iio_dev *indio_dev = dev_get_drvdata(dev);
421	struct hmc5843_data *data = indio_dev->dev_data;
422
423	range = data->range;
424	return sprintf(buf, "%d\n", regval_to_input_field_mg[range]);
425}
426
427static ssize_t set_range(struct device *dev,
428			struct device_attribute *attr,
429			const char *buf,
430			size_t count)
431{
432	struct iio_dev *indio_dev = dev_get_drvdata(dev);
433	struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
434	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
435	struct hmc5843_data *data = indio_dev->dev_data;
436	unsigned long range = 0;
437	int error;
438	mutex_lock(&data->lock);
439	error = strict_strtoul(buf, 10, &range);
440	if (error)
441		return error;
442	dev_dbg(dev, "set range to %lu\n", range);
443
444	if (range > RANGE_6_5)
445		return -EINVAL;
446
447	data->range = range;
448	range = range << RANGE_GAIN_OFFSET;
449	if (i2c_smbus_write_byte_data(client, this_attr->address, range))
450		count = -EINVAL;
451
452	mutex_unlock(&data->lock);
453	return count;
454
455}
456static IIO_DEVICE_ATTR(magn_range,
457			S_IWUSR | S_IRUGO,
458			show_range,
459			set_range,
460			HMC5843_CONFIG_REG_B);
461
462static ssize_t show_gain(struct device *dev,
463			struct device_attribute *attr,
464			char *buf)
465{
466	struct iio_dev *indio_dev = dev_get_drvdata(dev);
467	struct hmc5843_data *data = indio_dev->dev_data;
468	return sprintf(buf, "%d\n", regval_to_counts_per_mg[data->range]);
469}
470static IIO_DEVICE_ATTR(magn_gain,
471			S_IRUGO,
472			show_gain,
473			NULL , 0);
474
475static struct attribute *hmc5843_attributes[] = {
476	&iio_dev_attr_meas_conf.dev_attr.attr,
477	&iio_dev_attr_operating_mode.dev_attr.attr,
478	&iio_dev_attr_sampling_frequency.dev_attr.attr,
479	&iio_dev_attr_magn_range.dev_attr.attr,
480	&iio_dev_attr_magn_gain.dev_attr.attr,
481	&iio_dev_attr_magn_x_raw.dev_attr.attr,
482	&iio_dev_attr_magn_y_raw.dev_attr.attr,
483	&iio_dev_attr_magn_z_raw.dev_attr.attr,
484	&iio_const_attr_available_sampling_frequency.dev_attr.attr,
485	NULL
486};
487
488static const struct attribute_group hmc5843_group = {
489	.attrs = hmc5843_attributes,
490};
491
492static int hmc5843_detect(struct i2c_client *client,
493			  struct i2c_board_info *info)
494{
495	unsigned char id_str[HMC5843_ID_REG_LENGTH];
496
497	if (client->addr != HMC5843_I2C_ADDRESS)
498		return -ENODEV;
499
500	if (i2c_smbus_read_i2c_block_data(client, HMC5843_ID_REG_A,
501				HMC5843_ID_REG_LENGTH, id_str)
502			!= HMC5843_ID_REG_LENGTH)
503		return -ENODEV;
504
505	if (0 != strncmp(id_str, HMC5843_ID_STRING, HMC5843_ID_REG_LENGTH))
506		return -ENODEV;
507
508	return 0;
509}
510
511/* Called when we have found a new HMC5843. */
512static void hmc5843_init_client(struct i2c_client *client)
513{
514	struct hmc5843_data *data = i2c_get_clientdata(client);
515	hmc5843_set_meas_conf(client, data->meas_conf);
516	hmc5843_set_rate(client, data->rate);
517	hmc5843_configure(client, data->operating_mode);
518	i2c_smbus_write_byte_data(client, HMC5843_CONFIG_REG_B, data->range);
519	mutex_init(&data->lock);
520	pr_info("HMC5843 initialized\n");
521}
522
523static int hmc5843_probe(struct i2c_client *client,
524			 const struct i2c_device_id *id)
525{
526	struct hmc5843_data *data;
527	int err = 0;
528
529	data = kzalloc(sizeof(struct hmc5843_data), GFP_KERNEL);
530	if (!data) {
531		err = -ENOMEM;
532		goto exit;
533	}
534
535	/* default settings at probe */
536
537	data->meas_conf = CONF_NORMAL;
538	data->range = RANGE_1_0;
539	data->operating_mode = MODE_CONVERSION_CONTINUOUS;
540
541	i2c_set_clientdata(client, data);
542
543	/* Initialize the HMC5843 chip */
544	hmc5843_init_client(client);
545
546	data->indio_dev = iio_allocate_device();
547	if (!data->indio_dev) {
548		err = -ENOMEM;
549		goto exit_free1;
550	}
551	data->indio_dev->attrs = &hmc5843_group;
552	data->indio_dev->dev.parent = &client->dev;
553	data->indio_dev->dev_data = (void *)(data);
554	data->indio_dev->driver_module = THIS_MODULE;
555	data->indio_dev->modes = INDIO_DIRECT_MODE;
556	err = iio_device_register(data->indio_dev);
557	if (err)
558		goto exit_free2;
559	return 0;
560exit_free2:
561	iio_free_device(data->indio_dev);
562exit_free1:
563	kfree(data);
564exit:
565	return err;
566}
567
568static int hmc5843_remove(struct i2c_client *client)
569{
570	struct hmc5843_data *data = i2c_get_clientdata(client);
571	 /*  sleep mode to save power */
572	hmc5843_configure(client, MODE_SLEEP);
573	iio_device_unregister(data->indio_dev);
574	kfree(i2c_get_clientdata(client));
575	return 0;
576}
577
578static int hmc5843_suspend(struct i2c_client *client, pm_message_t mesg)
579{
580	hmc5843_configure(client, MODE_SLEEP);
581	return 0;
582}
583
584static int hmc5843_resume(struct i2c_client *client)
585{
586	struct hmc5843_data *data = i2c_get_clientdata(client);
587	hmc5843_configure(client, data->operating_mode);
588	return 0;
589}
590
591static const struct i2c_device_id hmc5843_id[] = {
592	{ "hmc5843", 0 },
593	{ }
594};
595
596static struct i2c_driver hmc5843_driver = {
597	.driver = {
598		.name	= "hmc5843",
599	},
600	.id_table	= hmc5843_id,
601	.probe		= hmc5843_probe,
602	.remove		= hmc5843_remove,
603	.detect		= hmc5843_detect,
604	.address_list	= normal_i2c,
605	.suspend	= hmc5843_suspend,
606	.resume		= hmc5843_resume,
607};
608
609static int __init hmc5843_init(void)
610{
611	return i2c_add_driver(&hmc5843_driver);
612}
613
614static void __exit hmc5843_exit(void)
615{
616	i2c_del_driver(&hmc5843_driver);
617}
618
619MODULE_AUTHOR("Shubhrajyoti Datta <shubhrajyoti@ti.com");
620MODULE_DESCRIPTION("HMC5843 driver");
621MODULE_LICENSE("GPL");
622
623module_init(hmc5843_init);
624module_exit(hmc5843_exit);
625