brintos

brintos / linux-shallow public Read only

0
0
Text · 15.2 KiB · 6cc0dfd Raw
657 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * STMicroelectronics magnetometers driver4 *5 * Copyright 2012-2013 STMicroelectronics Inc.6 *7 * Denis Ciocca <denis.ciocca@st.com>8 */9 10#include <linux/kernel.h>11#include <linux/module.h>12#include <linux/mutex.h>13#include <linux/sysfs.h>14#include <linux/iio/iio.h>15#include <linux/iio/sysfs.h>16#include <linux/iio/trigger.h>17 18#include <linux/iio/common/st_sensors.h>19#include "st_magn.h"20 21#define ST_MAGN_NUMBER_DATA_CHANNELS		322 23/* DEFAULT VALUE FOR SENSORS */24#define ST_MAGN_DEFAULT_OUT_X_H_ADDR		0x0325#define ST_MAGN_DEFAULT_OUT_Y_H_ADDR		0x0726#define ST_MAGN_DEFAULT_OUT_Z_H_ADDR		0x0527 28/* FULLSCALE */29#define ST_MAGN_FS_AVL_1300MG			130030#define ST_MAGN_FS_AVL_1900MG			190031#define ST_MAGN_FS_AVL_2000MG			200032#define ST_MAGN_FS_AVL_2500MG			250033#define ST_MAGN_FS_AVL_4000MG			400034#define ST_MAGN_FS_AVL_4700MG			470035#define ST_MAGN_FS_AVL_5600MG			560036#define ST_MAGN_FS_AVL_8000MG			800037#define ST_MAGN_FS_AVL_8100MG			810038#define ST_MAGN_FS_AVL_12000MG			1200039#define ST_MAGN_FS_AVL_15000MG			1500040#define ST_MAGN_FS_AVL_16000MG			1600041 42/* Special L addresses for Sensor 2 */43#define ST_MAGN_2_OUT_X_L_ADDR			0x2844#define ST_MAGN_2_OUT_Y_L_ADDR			0x2a45#define ST_MAGN_2_OUT_Z_L_ADDR			0x2c46 47/* Special L addresses for sensor 3 */48#define ST_MAGN_3_OUT_X_L_ADDR			0x6849#define ST_MAGN_3_OUT_Y_L_ADDR			0x6a50#define ST_MAGN_3_OUT_Z_L_ADDR			0x6c51 52/* Special L addresses for sensor 4 */53#define ST_MAGN_4_OUT_X_L_ADDR			0x0854#define ST_MAGN_4_OUT_Y_L_ADDR			0x0a55#define ST_MAGN_4_OUT_Z_L_ADDR			0x0c56 57static const struct iio_mount_matrix *58st_magn_get_mount_matrix(const struct iio_dev *indio_dev,59			 const struct iio_chan_spec *chan)60{61	struct st_sensor_data *mdata = iio_priv(indio_dev);62 63	return &mdata->mount_matrix;64}65 66static const struct iio_chan_spec_ext_info st_magn_mount_matrix_ext_info[] = {67	IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, st_magn_get_mount_matrix),68	{ }69};70 71static const struct iio_chan_spec st_magn_16bit_channels[] = {72	ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN,73			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),74			ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_BE, 16, 16,75			ST_MAGN_DEFAULT_OUT_X_H_ADDR,76			st_magn_mount_matrix_ext_info),77	ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN,78			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),79			ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_BE, 16, 16,80			ST_MAGN_DEFAULT_OUT_Y_H_ADDR,81			st_magn_mount_matrix_ext_info),82	ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN,83			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),84			ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_BE, 16, 16,85			ST_MAGN_DEFAULT_OUT_Z_H_ADDR,86			st_magn_mount_matrix_ext_info),87	IIO_CHAN_SOFT_TIMESTAMP(3)88};89 90static const struct iio_chan_spec st_magn_2_16bit_channels[] = {91	ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN,92			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),93			ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,94			ST_MAGN_2_OUT_X_L_ADDR,95			st_magn_mount_matrix_ext_info),96	ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN,97			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),98			ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,99			ST_MAGN_2_OUT_Y_L_ADDR,100			st_magn_mount_matrix_ext_info),101	ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN,102			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),103			ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,104			ST_MAGN_2_OUT_Z_L_ADDR,105			st_magn_mount_matrix_ext_info),106	IIO_CHAN_SOFT_TIMESTAMP(3)107};108 109static const struct iio_chan_spec st_magn_3_16bit_channels[] = {110	ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN,111			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),112			ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,113			ST_MAGN_3_OUT_X_L_ADDR,114			st_magn_mount_matrix_ext_info),115	ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN,116			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),117			ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,118			ST_MAGN_3_OUT_Y_L_ADDR,119			st_magn_mount_matrix_ext_info),120	ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN,121			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),122			ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,123			ST_MAGN_3_OUT_Z_L_ADDR,124			st_magn_mount_matrix_ext_info),125	IIO_CHAN_SOFT_TIMESTAMP(3)126};127 128static const struct iio_chan_spec st_magn_4_16bit_channels[] = {129	ST_SENSORS_LSM_CHANNELS(IIO_MAGN,130			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),131			ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,132			ST_MAGN_4_OUT_X_L_ADDR),133	ST_SENSORS_LSM_CHANNELS(IIO_MAGN,134			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),135			ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,136			ST_MAGN_4_OUT_Y_L_ADDR),137	ST_SENSORS_LSM_CHANNELS(IIO_MAGN,138			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),139			ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,140			ST_MAGN_4_OUT_Z_L_ADDR),141	IIO_CHAN_SOFT_TIMESTAMP(3)142};143 144static const struct st_sensor_settings st_magn_sensors_settings[] = {145	{146		.wai = 0, /* This sensor has no valid WhoAmI report 0 */147		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,148		.sensors_supported = {149			[0] = LSM303DLH_MAGN_DEV_NAME,150		},151		.ch = (struct iio_chan_spec *)st_magn_16bit_channels,152		.odr = {153			.addr = 0x00,154			.mask = 0x1c,155			.odr_avl = {156				{ .hz = 1, .value = 0x00 },157				{ .hz = 2, .value = 0x01 },158				{ .hz = 3, .value = 0x02 },159				{ .hz = 8, .value = 0x03 },160				{ .hz = 15, .value = 0x04 },161				{ .hz = 30, .value = 0x05 },162				{ .hz = 75, .value = 0x06 },163				/* 220 Hz, 0x07 reportedly exist */164			},165		},166		.pw = {167			.addr = 0x02,168			.mask = 0x03,169			.value_on = 0x00,170			.value_off = 0x03,171		},172		.fs = {173			.addr = 0x01,174			.mask = 0xe0,175			.fs_avl = {176				[0] = {177					.num = ST_MAGN_FS_AVL_1300MG,178					.value = 0x01,179					.gain = 1100,180					.gain2 = 980,181				},182				[1] = {183					.num = ST_MAGN_FS_AVL_1900MG,184					.value = 0x02,185					.gain = 855,186					.gain2 = 760,187				},188				[2] = {189					.num = ST_MAGN_FS_AVL_2500MG,190					.value = 0x03,191					.gain = 670,192					.gain2 = 600,193				},194				[3] = {195					.num = ST_MAGN_FS_AVL_4000MG,196					.value = 0x04,197					.gain = 450,198					.gain2 = 400,199				},200				[4] = {201					.num = ST_MAGN_FS_AVL_4700MG,202					.value = 0x05,203					.gain = 400,204					.gain2 = 355,205				},206				[5] = {207					.num = ST_MAGN_FS_AVL_5600MG,208					.value = 0x06,209					.gain = 330,210					.gain2 = 295,211				},212				[6] = {213					.num = ST_MAGN_FS_AVL_8100MG,214					.value = 0x07,215					.gain = 230,216					.gain2 = 205,217				},218			},219		},220		.multi_read_bit = false,221		.bootime = 2,222	},223	{224		.wai = 0x3c,225		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,226		.sensors_supported = {227			[0] = LSM303DLHC_MAGN_DEV_NAME,228			[1] = LSM303DLM_MAGN_DEV_NAME,229		},230		.ch = (struct iio_chan_spec *)st_magn_16bit_channels,231		.odr = {232			.addr = 0x00,233			.mask = 0x1c,234			.odr_avl = {235				{ .hz = 1, .value = 0x00 },236				{ .hz = 2, .value = 0x01 },237				{ .hz = 3, .value = 0x02 },238				{ .hz = 8, .value = 0x03 },239				{ .hz = 15, .value = 0x04 },240				{ .hz = 30, .value = 0x05 },241				{ .hz = 75, .value = 0x06 },242				{ .hz = 220, .value = 0x07 },243			},244		},245		.pw = {246			.addr = 0x02,247			.mask = 0x03,248			.value_on = 0x00,249			.value_off = 0x03,250		},251		.fs = {252			.addr = 0x01,253			.mask = 0xe0,254			.fs_avl = {255				[0] = {256					.num = ST_MAGN_FS_AVL_1300MG,257					.value = 0x01,258					.gain = 909,259					.gain2 = 1020,260				},261				[1] = {262					.num = ST_MAGN_FS_AVL_1900MG,263					.value = 0x02,264					.gain = 1169,265					.gain2 = 1315,266				},267				[2] = {268					.num = ST_MAGN_FS_AVL_2500MG,269					.value = 0x03,270					.gain = 1492,271					.gain2 = 1666,272				},273				[3] = {274					.num = ST_MAGN_FS_AVL_4000MG,275					.value = 0x04,276					.gain = 2222,277					.gain2 = 2500,278				},279				[4] = {280					.num = ST_MAGN_FS_AVL_4700MG,281					.value = 0x05,282					.gain = 2500,283					.gain2 = 2816,284				},285				[5] = {286					.num = ST_MAGN_FS_AVL_5600MG,287					.value = 0x06,288					.gain = 3030,289					.gain2 = 3389,290				},291				[6] = {292					.num = ST_MAGN_FS_AVL_8100MG,293					.value = 0x07,294					.gain = 4347,295					.gain2 = 4878,296				},297			},298		},299		.multi_read_bit = false,300		.bootime = 2,301	},302	{303		.wai = 0x3d,304		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,305		.sensors_supported = {306			[0] = LIS3MDL_MAGN_DEV_NAME,307			[1] = LSM9DS1_MAGN_DEV_NAME,308			[2] = LSM303C_MAGN_DEV_NAME,309		},310		.ch = (struct iio_chan_spec *)st_magn_2_16bit_channels,311		.odr = {312			.addr = 0x20,313			.mask = 0x1c,314			.odr_avl = {315				{ .hz = 1, .value = 0x00 },316				{ .hz = 2, .value = 0x01 },317				{ .hz = 3, .value = 0x02 },318				{ .hz = 5, .value = 0x03 },319				{ .hz = 10, .value = 0x04 },320				{ .hz = 20, .value = 0x05 },321				{ .hz = 40, .value = 0x06 },322				{ .hz = 80, .value = 0x07 },323			},324		},325		.pw = {326			.addr = 0x22,327			.mask = 0x03,328			.value_on = 0x00,329			.value_off = 0x03,330		},331		.fs = {332			.addr = 0x21,333			.mask = 0x60,334			.fs_avl = {335				[0] = {336					.num = ST_MAGN_FS_AVL_4000MG,337					.value = 0x00,338					.gain = 146,339				},340				[1] = {341					.num = ST_MAGN_FS_AVL_8000MG,342					.value = 0x01,343					.gain = 292,344				},345				[2] = {346					.num = ST_MAGN_FS_AVL_12000MG,347					.value = 0x02,348					.gain = 438,349				},350				[3] = {351					.num = ST_MAGN_FS_AVL_16000MG,352					.value = 0x03,353					.gain = 584,354				},355			},356		},357		.bdu = {358			.addr = 0x24,359			.mask = 0x40,360		},361		.drdy_irq = {362			/* drdy line is routed drdy pin */363			.stat_drdy = {364				.addr = ST_SENSORS_DEFAULT_STAT_ADDR,365				.mask = 0x07,366			},367		},368		.sim = {369			.addr = 0x22,370			.value = BIT(2),371		},372		.multi_read_bit = true,373		.bootime = 2,374	},375	{376		.wai = 0x40,377		.wai_addr = 0x4f,378		.sensors_supported = {379			[0] = LSM303AGR_MAGN_DEV_NAME,380			[1] = LIS2MDL_MAGN_DEV_NAME,381			[2] = IIS2MDC_MAGN_DEV_NAME,382		},383		.ch = (struct iio_chan_spec *)st_magn_3_16bit_channels,384		.odr = {385			.addr = 0x60,386			.mask = 0x0c,387			.odr_avl = {388				{ .hz = 10, .value = 0x00 },389				{ .hz = 20, .value = 0x01 },390				{ .hz = 50, .value = 0x02 },391				{ .hz = 100, .value = 0x03 },392			},393		},394		.pw = {395			.addr = 0x60,396			.mask = 0x03,397			.value_on = 0x00,398			.value_off = 0x03,399		},400		.fs = {401			.fs_avl = {402				[0] = {403					.num = ST_MAGN_FS_AVL_15000MG,404					.gain = 1500,405				},406			},407		},408		.bdu = {409			.addr = 0x62,410			.mask = 0x10,411		},412		.drdy_irq = {413			.int1 = {414				.addr = 0x62,415				.mask = 0x01,416			},417			.stat_drdy = {418				.addr = 0x67,419				.mask = 0x07,420			},421		},422		.multi_read_bit = false,423		.bootime = 2,424	},425	{426		.wai = 0x49,427		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,428		.sensors_supported = {429			[0] = LSM9DS0_IMU_DEV_NAME,430			[1] = LSM303D_IMU_DEV_NAME,431		},432		.ch = (struct iio_chan_spec *)st_magn_4_16bit_channels,433		.odr = {434			.addr = 0x24,435			.mask = GENMASK(4, 2),436			.odr_avl = {437				{ 3, 0x00, },438				{ 6, 0x01, },439				{ 12, 0x02, },440				{ 25, 0x03, },441				{ 50, 0x04, },442				{ 100, 0x05, },443			},444		},445		.pw = {446			.addr = 0x26,447			.mask = GENMASK(1, 0),448			.value_on = 0x00,449			.value_off = 0x03,450		},451		.fs = {452			.addr = 0x25,453			.mask = GENMASK(6, 5),454			.fs_avl = {455				[0] = {456					.num = ST_MAGN_FS_AVL_2000MG,457					.value = 0x00,458					.gain = 73,459				},460				[1] = {461					.num = ST_MAGN_FS_AVL_4000MG,462					.value = 0x01,463					.gain = 146,464				},465				[2] = {466					.num = ST_MAGN_FS_AVL_8000MG,467					.value = 0x02,468					.gain = 292,469				},470				[3] = {471					.num = ST_MAGN_FS_AVL_12000MG,472					.value = 0x03,473					.gain = 438,474				},475			},476		},477		.bdu = {478			.addr = 0x20,479			.mask = BIT(3),480		},481		.drdy_irq = {482			.int1 = {483				.addr = 0x22,484				.mask = BIT(1),485			},486			.int2 = {487				.addr = 0x23,488				.mask = BIT(2),489			},490			.stat_drdy = {491				.addr = 0x07,492				.mask = GENMASK(2, 0),493			},494		},495		.sim = {496			.addr = 0x21,497			.value = BIT(0),498		},499		.multi_read_bit = true,500		.bootime = 2,501	},502};503 504/* Default magn DRDY is available on INT2 pin */505static const struct st_sensors_platform_data default_magn_pdata = {506	.drdy_int_pin = 2,507};508 509static int st_magn_read_raw(struct iio_dev *indio_dev,510			struct iio_chan_spec const *ch, int *val,511							int *val2, long mask)512{513	int err;514	struct st_sensor_data *mdata = iio_priv(indio_dev);515 516	switch (mask) {517	case IIO_CHAN_INFO_RAW:518		err = st_sensors_read_info_raw(indio_dev, ch, val);519		if (err < 0)520			goto read_error;521 522		return IIO_VAL_INT;523	case IIO_CHAN_INFO_SCALE:524		*val = 0;525		if ((ch->scan_index == ST_SENSORS_SCAN_Z) &&526					(mdata->current_fullscale->gain2 != 0))527			*val2 = mdata->current_fullscale->gain2;528		else529			*val2 = mdata->current_fullscale->gain;530		return IIO_VAL_INT_PLUS_MICRO;531	case IIO_CHAN_INFO_SAMP_FREQ:532		*val = mdata->odr;533		return IIO_VAL_INT;534	default:535		return -EINVAL;536	}537 538read_error:539	return err;540}541 542static int st_magn_write_raw(struct iio_dev *indio_dev,543		struct iio_chan_spec const *chan, int val, int val2, long mask)544{545	switch (mask) {546	case IIO_CHAN_INFO_SCALE:547		return st_sensors_set_fullscale_by_gain(indio_dev, val2);548	case IIO_CHAN_INFO_SAMP_FREQ:549		if (val2)550			return -EINVAL;551 552		return st_sensors_set_odr(indio_dev, val);553	default:554		return -EINVAL;555	}556}557 558static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();559static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_magn_scale_available);560 561static struct attribute *st_magn_attributes[] = {562	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,563	&iio_dev_attr_in_magn_scale_available.dev_attr.attr,564	NULL,565};566 567static const struct attribute_group st_magn_attribute_group = {568	.attrs = st_magn_attributes,569};570 571static const struct iio_info magn_info = {572	.attrs = &st_magn_attribute_group,573	.read_raw = &st_magn_read_raw,574	.write_raw = &st_magn_write_raw,575	.debugfs_reg_access = &st_sensors_debugfs_reg_access,576};577 578#ifdef CONFIG_IIO_TRIGGER579static const struct iio_trigger_ops st_magn_trigger_ops = {580	.set_trigger_state = ST_MAGN_TRIGGER_SET_STATE,581	.validate_device = st_sensors_validate_device,582};583#define ST_MAGN_TRIGGER_OPS (&st_magn_trigger_ops)584#else585#define ST_MAGN_TRIGGER_OPS NULL586#endif587 588/*589 * st_magn_get_settings() - get sensor settings from device name590 * @name: device name buffer reference.591 *592 * Return: valid reference on success, NULL otherwise.593 */594const struct st_sensor_settings *st_magn_get_settings(const char *name)595{596	int index = st_sensors_get_settings_index(name,597					st_magn_sensors_settings,598					ARRAY_SIZE(st_magn_sensors_settings));599	if (index < 0)600		return NULL;601 602	return &st_magn_sensors_settings[index];603}604EXPORT_SYMBOL_NS(st_magn_get_settings, IIO_ST_SENSORS);605 606int st_magn_common_probe(struct iio_dev *indio_dev)607{608	struct st_sensor_data *mdata = iio_priv(indio_dev);609	struct device *parent = indio_dev->dev.parent;610	struct st_sensors_platform_data *pdata = dev_get_platdata(parent);611	int err;612 613	indio_dev->modes = INDIO_DIRECT_MODE;614	indio_dev->info = &magn_info;615 616	err = st_sensors_verify_id(indio_dev);617	if (err < 0)618		return err;619 620	mdata->num_data_channels = ST_MAGN_NUMBER_DATA_CHANNELS;621	indio_dev->channels = mdata->sensor_settings->ch;622	indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;623 624	err = iio_read_mount_matrix(parent, &mdata->mount_matrix);625	if (err)626		return err;627 628	mdata->current_fullscale = &mdata->sensor_settings->fs.fs_avl[0];629	mdata->odr = mdata->sensor_settings->odr.odr_avl[0].hz;630 631	if (!pdata)632		pdata = (struct st_sensors_platform_data *)&default_magn_pdata;633 634	err = st_sensors_init_sensor(indio_dev, pdata);635	if (err < 0)636		return err;637 638	err = st_magn_allocate_ring(indio_dev);639	if (err < 0)640		return err;641 642	if (mdata->irq > 0) {643		err = st_sensors_allocate_trigger(indio_dev,644						ST_MAGN_TRIGGER_OPS);645		if (err < 0)646			return err;647	}648 649	return devm_iio_device_register(parent, indio_dev);650}651EXPORT_SYMBOL_NS(st_magn_common_probe, IIO_ST_SENSORS);652 653MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");654MODULE_DESCRIPTION("STMicroelectronics magnetometers driver");655MODULE_LICENSE("GPL v2");656MODULE_IMPORT_NS(IIO_ST_SENSORS);657