brintos

brintos / linux-shallow public Read only

0
0
Text · 11.8 KiB · 70dfd6e Raw
514 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * kxsd9.c	simple support for the Kionix KXSD9 3D4 *		accelerometer.5 *6 * Copyright (c) 2008-2009 Jonathan Cameron <jic23@kernel.org>7 *8 * The i2c interface is very similar, so shouldn't be a problem once9 * I have a suitable wire made up.10 *11 * TODO:	Support the motion detector12 */13 14#include <linux/device.h>15#include <linux/kernel.h>16#include <linux/sysfs.h>17#include <linux/slab.h>18#include <linux/module.h>19#include <linux/regmap.h>20#include <linux/bitops.h>21#include <linux/delay.h>22#include <linux/regulator/consumer.h>23#include <linux/pm_runtime.h>24#include <linux/iio/iio.h>25#include <linux/iio/sysfs.h>26#include <linux/iio/buffer.h>27#include <linux/iio/triggered_buffer.h>28#include <linux/iio/trigger_consumer.h>29 30#include "kxsd9.h"31 32#define KXSD9_REG_X		0x0033#define KXSD9_REG_Y		0x0234#define KXSD9_REG_Z		0x0435#define KXSD9_REG_AUX		0x0636#define KXSD9_REG_RESET		0x0a37#define KXSD9_REG_CTRL_C	0x0c38 39#define KXSD9_CTRL_C_FS_MASK	0x0340#define KXSD9_CTRL_C_FS_8G	0x0041#define KXSD9_CTRL_C_FS_6G	0x0142#define KXSD9_CTRL_C_FS_4G	0x0243#define KXSD9_CTRL_C_FS_2G	0x0344#define KXSD9_CTRL_C_MOT_LAT	BIT(3)45#define KXSD9_CTRL_C_MOT_LEV	BIT(4)46#define KXSD9_CTRL_C_LP_MASK	0xe047#define KXSD9_CTRL_C_LP_NONE	0x0048#define KXSD9_CTRL_C_LP_2000HZC	BIT(5)49#define KXSD9_CTRL_C_LP_2000HZB	BIT(6)50#define KXSD9_CTRL_C_LP_2000HZA	(BIT(5)|BIT(6))51#define KXSD9_CTRL_C_LP_1000HZ	BIT(7)52#define KXSD9_CTRL_C_LP_500HZ	(BIT(7)|BIT(5))53#define KXSD9_CTRL_C_LP_100HZ	(BIT(7)|BIT(6))54#define KXSD9_CTRL_C_LP_50HZ	(BIT(7)|BIT(6)|BIT(5))55 56#define KXSD9_REG_CTRL_B	0x0d57 58#define KXSD9_CTRL_B_CLK_HLD	BIT(7)59#define KXSD9_CTRL_B_ENABLE	BIT(6)60#define KXSD9_CTRL_B_ST		BIT(5) /* Self-test */61 62#define KXSD9_REG_CTRL_A	0x0e63 64/**65 * struct kxsd9_state - device related storage66 * @dev: pointer to the parent device67 * @map: regmap to the device68 * @orientation: mounting matrix, flipped axis etc69 * @regs: regulators for this device, VDD and IOVDD70 * @scale: the current scaling setting71 */72struct kxsd9_state {73	struct device *dev;74	struct regmap *map;75	struct iio_mount_matrix orientation;76	struct regulator_bulk_data regs[2];77	u8 scale;78};79 80#define KXSD9_SCALE_2G "0.011978"81#define KXSD9_SCALE_4G "0.023927"82#define KXSD9_SCALE_6G "0.035934"83#define KXSD9_SCALE_8G "0.047853"84 85/* reverse order */86static const int kxsd9_micro_scales[4] = { 47853, 35934, 23927, 11978 };87 88#define KXSD9_ZERO_G_OFFSET -204889 90/*91 * Regulator names92 */93static const char kxsd9_reg_vdd[] = "vdd";94static const char kxsd9_reg_iovdd[] = "iovdd";95 96static int kxsd9_write_scale(struct iio_dev *indio_dev, int micro)97{98	int ret, i;99	struct kxsd9_state *st = iio_priv(indio_dev);100	bool foundit = false;101 102	for (i = 0; i < 4; i++)103		if (micro == kxsd9_micro_scales[i]) {104			foundit = true;105			break;106		}107	if (!foundit)108		return -EINVAL;109 110	ret = regmap_update_bits(st->map,111				 KXSD9_REG_CTRL_C,112				 KXSD9_CTRL_C_FS_MASK,113				 i);114	if (ret < 0)115		goto error_ret;116 117	/* Cached scale when the sensor is powered down */118	st->scale = i;119 120error_ret:121	return ret;122}123 124static IIO_CONST_ATTR(accel_scale_available,125		KXSD9_SCALE_2G " "126		KXSD9_SCALE_4G " "127		KXSD9_SCALE_6G " "128		KXSD9_SCALE_8G);129 130static struct attribute *kxsd9_attributes[] = {131	&iio_const_attr_accel_scale_available.dev_attr.attr,132	NULL,133};134 135static int kxsd9_write_raw(struct iio_dev *indio_dev,136			   struct iio_chan_spec const *chan,137			   int val,138			   int val2,139			   long mask)140{141	int ret = -EINVAL;142	struct kxsd9_state *st = iio_priv(indio_dev);143 144	pm_runtime_get_sync(st->dev);145 146	if (mask == IIO_CHAN_INFO_SCALE) {147		/* Check no integer component */148		if (val)149			return -EINVAL;150		ret = kxsd9_write_scale(indio_dev, val2);151	}152 153	pm_runtime_mark_last_busy(st->dev);154	pm_runtime_put_autosuspend(st->dev);155 156	return ret;157}158 159static int kxsd9_read_raw(struct iio_dev *indio_dev,160			  struct iio_chan_spec const *chan,161			  int *val, int *val2, long mask)162{163	int ret = -EINVAL;164	struct kxsd9_state *st = iio_priv(indio_dev);165	unsigned int regval;166	__be16 raw_val;167	u16 nval;168 169	pm_runtime_get_sync(st->dev);170 171	switch (mask) {172	case IIO_CHAN_INFO_RAW:173		ret = regmap_bulk_read(st->map, chan->address, &raw_val,174				       sizeof(raw_val));175		if (ret)176			goto error_ret;177		nval = be16_to_cpu(raw_val);178		/* Only 12 bits are valid */179		nval >>= 4;180		*val = nval;181		ret = IIO_VAL_INT;182		break;183	case IIO_CHAN_INFO_OFFSET:184		/* This has a bias of -2048 */185		*val = KXSD9_ZERO_G_OFFSET;186		ret = IIO_VAL_INT;187		break;188	case IIO_CHAN_INFO_SCALE:189		ret = regmap_read(st->map,190				  KXSD9_REG_CTRL_C,191				  &regval);192		if (ret < 0)193			goto error_ret;194		*val = 0;195		*val2 = kxsd9_micro_scales[regval & KXSD9_CTRL_C_FS_MASK];196		ret = IIO_VAL_INT_PLUS_MICRO;197		break;198	}199 200error_ret:201	pm_runtime_mark_last_busy(st->dev);202	pm_runtime_put_autosuspend(st->dev);203 204	return ret;205};206 207static irqreturn_t kxsd9_trigger_handler(int irq, void *p)208{209	const struct iio_poll_func *pf = p;210	struct iio_dev *indio_dev = pf->indio_dev;211	struct kxsd9_state *st = iio_priv(indio_dev);212	/*213	 * Ensure correct positioning and alignment of timestamp.214	 * No need to zero initialize as all elements written.215	 */216	struct {217		__be16 chan[4];218		s64 ts __aligned(8);219	} hw_values;220	int ret;221 222	ret = regmap_bulk_read(st->map,223			       KXSD9_REG_X,224			       hw_values.chan,225			       sizeof(hw_values.chan));226	if (ret) {227		dev_err(st->dev, "error reading data: %d\n", ret);228		goto out;229	}230 231	iio_push_to_buffers_with_timestamp(indio_dev,232					   &hw_values,233					   iio_get_time_ns(indio_dev));234out:235	iio_trigger_notify_done(indio_dev->trig);236 237	return IRQ_HANDLED;238}239 240static int kxsd9_buffer_preenable(struct iio_dev *indio_dev)241{242	struct kxsd9_state *st = iio_priv(indio_dev);243 244	pm_runtime_get_sync(st->dev);245 246	return 0;247}248 249static int kxsd9_buffer_postdisable(struct iio_dev *indio_dev)250{251	struct kxsd9_state *st = iio_priv(indio_dev);252 253	pm_runtime_mark_last_busy(st->dev);254	pm_runtime_put_autosuspend(st->dev);255 256	return 0;257}258 259static const struct iio_buffer_setup_ops kxsd9_buffer_setup_ops = {260	.preenable = kxsd9_buffer_preenable,261	.postdisable = kxsd9_buffer_postdisable,262};263 264static const struct iio_mount_matrix *265kxsd9_get_mount_matrix(const struct iio_dev *indio_dev,266		       const struct iio_chan_spec *chan)267{268	struct kxsd9_state *st = iio_priv(indio_dev);269 270	return &st->orientation;271}272 273static const struct iio_chan_spec_ext_info kxsd9_ext_info[] = {274	IIO_MOUNT_MATRIX(IIO_SHARED_BY_TYPE, kxsd9_get_mount_matrix),275	{ },276};277 278#define KXSD9_ACCEL_CHAN(axis, index)						\279	{								\280		.type = IIO_ACCEL,					\281		.modified = 1,						\282		.channel2 = IIO_MOD_##axis,				\283		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\284		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |	\285					BIT(IIO_CHAN_INFO_OFFSET),	\286		.ext_info = kxsd9_ext_info,				\287		.address = KXSD9_REG_##axis,				\288		.scan_index = index,					\289		.scan_type = {                                          \290			.sign = 'u',					\291			.realbits = 12,					\292			.storagebits = 16,				\293			.shift = 4,					\294			.endianness = IIO_BE,				\295		},							\296	}297 298static const struct iio_chan_spec kxsd9_channels[] = {299	KXSD9_ACCEL_CHAN(X, 0),300	KXSD9_ACCEL_CHAN(Y, 1),301	KXSD9_ACCEL_CHAN(Z, 2),302	{303		.type = IIO_VOLTAGE,304		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),305		.indexed = 1,306		.address = KXSD9_REG_AUX,307		.scan_index = 3,308		.scan_type = {309			.sign = 'u',310			.realbits = 12,311			.storagebits = 16,312			.shift = 4,313			.endianness = IIO_BE,314		},315	},316	IIO_CHAN_SOFT_TIMESTAMP(4),317};318 319static const struct attribute_group kxsd9_attribute_group = {320	.attrs = kxsd9_attributes,321};322 323static int kxsd9_power_up(struct kxsd9_state *st)324{325	int ret;326 327	/* Enable the regulators */328	ret = regulator_bulk_enable(ARRAY_SIZE(st->regs), st->regs);329	if (ret) {330		dev_err(st->dev, "Cannot enable regulators\n");331		return ret;332	}333 334	/* Power up */335	ret = regmap_write(st->map,336			   KXSD9_REG_CTRL_B,337			   KXSD9_CTRL_B_ENABLE);338	if (ret)339		return ret;340 341	/*342	 * Set 1000Hz LPF, 2g fullscale, motion wakeup threshold 1g,343	 * latched wakeup344	 */345	ret = regmap_write(st->map,346			   KXSD9_REG_CTRL_C,347			   KXSD9_CTRL_C_LP_1000HZ |348			   KXSD9_CTRL_C_MOT_LEV	|349			   KXSD9_CTRL_C_MOT_LAT |350			   st->scale);351	if (ret)352		return ret;353 354	/*355	 * Power-up time depends on the LPF setting, but typ 15.9 ms, let's356	 * set 20 ms to allow for some slack.357	 */358	msleep(20);359 360	return 0;361};362 363static int kxsd9_power_down(struct kxsd9_state *st)364{365	int ret;366 367	/*368	 * Set into low power mode - since there may be more users of the369	 * regulators this is the first step of the power saving: it will370	 * make sure we conserve power even if there are others users on the371	 * regulators.372	 */373	ret = regmap_clear_bits(st->map, KXSD9_REG_CTRL_B, KXSD9_CTRL_B_ENABLE);374	if (ret)375		return ret;376 377	/* Disable the regulators */378	ret = regulator_bulk_disable(ARRAY_SIZE(st->regs), st->regs);379	if (ret) {380		dev_err(st->dev, "Cannot disable regulators\n");381		return ret;382	}383 384	return 0;385}386 387static const struct iio_info kxsd9_info = {388	.read_raw = &kxsd9_read_raw,389	.write_raw = &kxsd9_write_raw,390	.attrs = &kxsd9_attribute_group,391};392 393/* Four channels apart from timestamp, scan mask = 0x0f */394static const unsigned long kxsd9_scan_masks[] = { 0xf, 0 };395 396int kxsd9_common_probe(struct device *dev,397		       struct regmap *map,398		       const char *name)399{400	struct iio_dev *indio_dev;401	struct kxsd9_state *st;402	int ret;403 404	indio_dev = devm_iio_device_alloc(dev, sizeof(*st));405	if (!indio_dev)406		return -ENOMEM;407 408	st = iio_priv(indio_dev);409	st->dev = dev;410	st->map = map;411 412	indio_dev->channels = kxsd9_channels;413	indio_dev->num_channels = ARRAY_SIZE(kxsd9_channels);414	indio_dev->name = name;415	indio_dev->info = &kxsd9_info;416	indio_dev->modes = INDIO_DIRECT_MODE;417	indio_dev->available_scan_masks = kxsd9_scan_masks;418 419	/* Read the mounting matrix, if present */420	ret = iio_read_mount_matrix(dev, &st->orientation);421	if (ret)422		return ret;423 424	/* Fetch and turn on regulators */425	st->regs[0].supply = kxsd9_reg_vdd;426	st->regs[1].supply = kxsd9_reg_iovdd;427	ret = devm_regulator_bulk_get(dev,428				      ARRAY_SIZE(st->regs),429				      st->regs);430	if (ret) {431		dev_err(dev, "Cannot get regulators\n");432		return ret;433	}434	/* Default scaling */435	st->scale = KXSD9_CTRL_C_FS_2G;436 437	kxsd9_power_up(st);438 439	ret = iio_triggered_buffer_setup(indio_dev,440					 iio_pollfunc_store_time,441					 kxsd9_trigger_handler,442					 &kxsd9_buffer_setup_ops);443	if (ret) {444		dev_err(dev, "triggered buffer setup failed\n");445		goto err_power_down;446	}447 448	ret = iio_device_register(indio_dev);449	if (ret)450		goto err_cleanup_buffer;451 452	dev_set_drvdata(dev, indio_dev);453 454	/* Enable runtime PM */455	pm_runtime_get_noresume(dev);456	pm_runtime_set_active(dev);457	pm_runtime_enable(dev);458	/*459	 * Set autosuspend to two orders of magnitude larger than the460	 * start-up time. 20ms start-up time means 2000ms autosuspend,461	 * i.e. 2 seconds.462	 */463	pm_runtime_set_autosuspend_delay(dev, 2000);464	pm_runtime_use_autosuspend(dev);465	pm_runtime_put(dev);466 467	return 0;468 469err_cleanup_buffer:470	iio_triggered_buffer_cleanup(indio_dev);471err_power_down:472	kxsd9_power_down(st);473 474	return ret;475}476EXPORT_SYMBOL_NS(kxsd9_common_probe, IIO_KXSD9);477 478void kxsd9_common_remove(struct device *dev)479{480	struct iio_dev *indio_dev = dev_get_drvdata(dev);481	struct kxsd9_state *st = iio_priv(indio_dev);482 483	iio_triggered_buffer_cleanup(indio_dev);484	iio_device_unregister(indio_dev);485	pm_runtime_get_sync(dev);486	pm_runtime_put_noidle(dev);487	pm_runtime_disable(dev);488	kxsd9_power_down(st);489}490EXPORT_SYMBOL_NS(kxsd9_common_remove, IIO_KXSD9);491 492static int kxsd9_runtime_suspend(struct device *dev)493{494	struct iio_dev *indio_dev = dev_get_drvdata(dev);495	struct kxsd9_state *st = iio_priv(indio_dev);496 497	return kxsd9_power_down(st);498}499 500static int kxsd9_runtime_resume(struct device *dev)501{502	struct iio_dev *indio_dev = dev_get_drvdata(dev);503	struct kxsd9_state *st = iio_priv(indio_dev);504 505	return kxsd9_power_up(st);506}507 508EXPORT_NS_RUNTIME_DEV_PM_OPS(kxsd9_dev_pm_ops, kxsd9_runtime_suspend,509			     kxsd9_runtime_resume, NULL, IIO_KXSD9);510 511MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");512MODULE_DESCRIPTION("Kionix KXSD9 driver");513MODULE_LICENSE("GPL v2");514