Lines Matching +full:3 +full:- +full:axis

1 // SPDX-License-Identifier: GPL-2.0-only
7 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
38 * 16-bit registers are little-endian. LSB is at the address defined below
65 #define AK8974_INT_THRES 0x26 /* Absolute any axis value threshold */
68 /* AK8974-specific offsets */
72 /* AMI305-specific offsets */
81 /* AMI306-specific control register */
86 /* fine axis sensitivity */
91 /* axis sensitivity */
96 /* axis cross-interference */
110 #define AK8974_INT_X_HIGH BIT(7) /* Axis over +threshold */
113 #define AK8974_INT_X_LOW BIT(4) /* Axis below -threshold */
114 #define AK8974_INT_Y_LOW BIT(3)
116 #define AK8974_INT_RANGE BIT(1) /* Range overflow (any axis) */
128 #define AK8974_CTRL2_DRDY_EN BIT(3) /* 1 = enable data ready signal */
137 #define AK8974_INT_CTRL_XEN BIT(7) /* Enable interrupt for this axis */
141 #define AK8974_INT_CTRL_POL BIT(3) /* 0 = active low; 1 = active high */
145 /* HSCDTD008A-specific control register */
148 #define HSCDTD008A_CTRL4_RANGE BIT(4) /* 0 = 14-bit output; 1 = 15-bit output */
167 #define AK8974_MEASTIME 3
173 * struct ak8974 - state container for the AK8974 driver
175 * @orientation: mounting matrix, flipped axis etc
199 __le16 channels[3];
212 ret = regmap_bulk_read(ak8974->map, reg, &bulk, 2); in ak8974_get_u16_val()
224 return regmap_bulk_write(ak8974->map, reg, &bulk, 2); in ak8974_set_u16_val()
234 ret = regmap_write(ak8974->map, AK8974_CTRL1, val); in ak8974_set_power()
252 ret = regmap_write(ak8974->map, AK8974_CTRL2, AK8974_CTRL2_RESDEF); in ak8974_reset()
255 ret = regmap_write(ak8974->map, AK8974_CTRL3, AK8974_CTRL3_RESDEF); in ak8974_reset()
258 if (ak8974->variant != AK8974_WHOAMI_VALUE_HSCDTD008A) { in ak8974_reset()
259 ret = regmap_write(ak8974->map, AK8974_INT_CTRL, in ak8974_reset()
264 ret = regmap_write(ak8974->map, HSCDTD008A_CTRL4, in ak8974_reset()
278 ret = regmap_write(ak8974->map, AK8974_CTRL2, AK8974_CTRL2_DRDY_EN | in ak8974_configure()
282 ret = regmap_write(ak8974->map, AK8974_CTRL3, 0); in ak8974_configure()
285 if (ak8974->variant == AK8974_WHOAMI_VALUE_AMI306) { in ak8974_configure()
286 /* magic from datasheet: set high-speed measurement mode */ in ak8974_configure()
291 if (ak8974->variant == AK8974_WHOAMI_VALUE_HSCDTD008A) in ak8974_configure()
293 ret = regmap_write(ak8974->map, AK8974_INT_CTRL, AK8974_INT_CTRL_POL); in ak8974_configure()
297 return regmap_write(ak8974->map, AK8974_PRESET, 0); in ak8974_configure()
308 ret = regmap_read(ak8974->map, AK8974_INT_CLEAR, &clear); in ak8974_trigmeas()
313 if (ak8974->drdy_irq) { in ak8974_trigmeas()
319 if (!ak8974->drdy_active_low) in ak8974_trigmeas()
322 init_completion(&ak8974->drdy_complete); in ak8974_trigmeas()
323 ret = regmap_update_bits(ak8974->map, AK8974_CTRL2, in ak8974_trigmeas()
330 return regmap_set_bits(ak8974->map, AK8974_CTRL3, AK8974_CTRL3_FORCE); in ak8974_trigmeas()
339 if (ak8974->drdy_irq) { in ak8974_await_drdy()
340 ret = wait_for_completion_timeout(&ak8974->drdy_complete, in ak8974_await_drdy()
343 dev_err(&ak8974->i2c->dev, in ak8974_await_drdy()
345 return -ETIMEDOUT; in ak8974_await_drdy()
350 /* Default delay-based poll loop */ in ak8974_await_drdy()
353 ret = regmap_read(ak8974->map, AK8974_STATUS, &val); in ak8974_await_drdy()
358 } while (--timeout); in ak8974_await_drdy()
360 dev_err(&ak8974->i2c->dev, "timeout waiting for DRDY\n"); in ak8974_await_drdy()
361 return -ETIMEDOUT; in ak8974_await_drdy()
372 ret = regmap_read(ak8974->map, AK8974_INT_SRC, &src); in ak8974_getresult()
378 dev_err(&ak8974->i2c->dev, in ak8974_getresult()
380 return -ERANGE; in ak8974_getresult()
383 ret = regmap_bulk_read(ak8974->map, AK8974_DATA_X, result, 6); in ak8974_getresult()
394 if (!ak8974->drdy_irq) in ak8974_drdy_irq()
408 ret = regmap_read(ak8974->map, AK8974_STATUS, &val); in ak8974_drdy_irq_thread()
410 dev_err(&ak8974->i2c->dev, "error reading DRDY status\n"); in ak8974_drdy_irq_thread()
415 complete(&ak8974->drdy_complete); in ak8974_drdy_irq_thread()
425 struct device *dev = &ak8974->i2c->dev; in ak8974_selftest()
429 ret = regmap_read(ak8974->map, AK8974_SELFTEST, &val); in ak8974_selftest()
434 return -EIO; in ak8974_selftest()
437 /* Trigger self-test */ in ak8974_selftest()
438 ret = regmap_set_bits(ak8974->map, AK8974_CTRL3, AK8974_CTRL3_SELFTEST); in ak8974_selftest()
446 ret = regmap_read(ak8974->map, AK8974_SELFTEST, &val); in ak8974_selftest()
451 return -EIO; in ak8974_selftest()
454 ret = regmap_read(ak8974->map, AK8974_SELFTEST, &val); in ak8974_selftest()
459 return -EIO; in ak8974_selftest()
461 dev_dbg(dev, "passed self-test\n"); in ak8974_selftest()
469 int ret = regmap_bulk_read(ak8974->map, reg, tab, tab_size); in ak8974_read_calib_data()
472 dev_warn(&ak8974->i2c->dev, in ak8974_read_calib_data()
474 reg, reg + tab_size - 1, ret); in ak8974_read_calib_data()
488 ret = regmap_read(ak8974->map, AK8974_WHOAMI, &whoami); in ak8974_detect()
499 ret = regmap_read(ak8974->map, AMI305_VER, &fw); in ak8974_detect()
507 dev_info(&ak8974->i2c->dev, in ak8974_detect()
513 dev_info(&ak8974->i2c->dev, "detected AK8974\n"); in ak8974_detect()
517 dev_info(&ak8974->i2c->dev, "detected hscdtd008a\n"); in ak8974_detect()
520 dev_err(&ak8974->i2c->dev, "unsupported device (%02x) ", in ak8974_detect()
522 return -ENODEV; in ak8974_detect()
525 ak8974->name = name; in ak8974_detect()
526 ak8974->variant = whoami; in ak8974_detect()
529 __le16 fab_data1[9], fab_data2[3]; in ak8974_detect()
537 for (i = 0; i < 3; ++i) { in ak8974_detect()
538 static const char axis[3] = "XYZ"; in ak8974_detect() local
542 unsigned sens = le16_to_cpu(fab_data1[i + 3]); in ak8974_detect()
548 dev_info(&ak8974->i2c->dev, in ak8974_detect()
549 "factory calibration for axis %c: offz=%u sens=%u fine=%u pga%c=%u pga%c=%u\n", in ak8974_detect()
550 axis[i], offz, sens, fine, pgaxis[i * 2], in ak8974_detect()
561 __le16 hw_values[3]; in ak8974_measure_channel()
564 pm_runtime_get_sync(&ak8974->i2c->dev); in ak8974_measure_channel()
565 mutex_lock(&ak8974->lock); in ak8974_measure_channel()
585 mutex_unlock(&ak8974->lock); in ak8974_measure_channel()
586 pm_runtime_mark_last_busy(&ak8974->i2c->dev); in ak8974_measure_channel()
587 pm_runtime_put_autosuspend(&ak8974->i2c->dev); in ak8974_measure_channel()
602 if (chan->address > 2) { in ak8974_read_raw()
603 dev_err(&ak8974->i2c->dev, "faulty channel address\n"); in ak8974_read_raw()
604 return -EIO; in ak8974_read_raw()
606 ret = ak8974_measure_channel(ak8974, chan->address, val); in ak8974_read_raw()
611 switch (ak8974->variant) { in ak8974_read_raw()
617 * +/- 12 Gauss. in ak8974_read_raw()
621 * 12 bits are used, +/- 2^11 in ak8974_read_raw()
622 * [ -2048 .. 2047 ] (manual page 20) in ak8974_read_raw()
629 * The datasheet for HSCDTF008A, page 3 specifies the in ak8974_read_raw()
630 * range of the sensor as +/- 2.4 mT per axis, which in ak8974_read_raw()
631 * corresponds to +/- 2400 uT = +/- 24 Gauss. in ak8974_read_raw()
635 * 15 bits are used (set up in CTRL4), +/- 2^14 in ak8974_read_raw()
636 * [ -16384 .. 16383 ] (manual page 24) in ak8974_read_raw()
642 /* GUESSING +/- 12 Gauss */ in ak8974_read_raw()
644 /* GUESSING 12 bits ADC +/- 2^11 */ in ak8974_read_raw()
654 return -EINVAL; in ak8974_read_raw()
662 pm_runtime_get_sync(&ak8974->i2c->dev); in ak8974_fill_buffer()
663 mutex_lock(&ak8974->lock); in ak8974_fill_buffer()
667 dev_err(&ak8974->i2c->dev, "error triggering measure\n"); in ak8974_fill_buffer()
670 ret = ak8974_getresult(ak8974, ak8974->scan.channels); in ak8974_fill_buffer()
672 dev_err(&ak8974->i2c->dev, "error getting measures\n"); in ak8974_fill_buffer()
676 iio_push_to_buffers_with_timestamp(indio_dev, &ak8974->scan, in ak8974_fill_buffer()
680 mutex_unlock(&ak8974->lock); in ak8974_fill_buffer()
681 pm_runtime_mark_last_busy(&ak8974->i2c->dev); in ak8974_fill_buffer()
682 pm_runtime_put_autosuspend(&ak8974->i2c->dev); in ak8974_fill_buffer()
688 struct iio_dev *indio_dev = pf->indio_dev; in ak8974_handle_trigger()
691 iio_trigger_notify_done(indio_dev->trig); in ak8974_handle_trigger()
702 return &ak8974->orientation; in ak8974_get_mount_matrix()
710 #define AK8974_AXIS_CHANNEL(axis, index, bits) \ argument
714 .channel2 = IIO_MOD_##axis, \
737 IIO_CHAN_SOFT_TIMESTAMP(3),
748 IIO_CHAN_SOFT_TIMESTAMP(3),
773 return ak8974->variant != AK8974_WHOAMI_VALUE_HSCDTD008A; in ak8974_writeable_reg()
780 return ak8974->variant == AK8974_WHOAMI_VALUE_AK8974 || in ak8974_writeable_reg()
781 ak8974->variant == AK8974_WHOAMI_VALUE_HSCDTD008A; in ak8974_writeable_reg()
788 return ak8974->variant == AK8974_WHOAMI_VALUE_AMI305 || in ak8974_writeable_reg()
789 ak8974->variant == AK8974_WHOAMI_VALUE_AMI306; in ak8974_writeable_reg()
792 return ak8974->variant == AK8974_WHOAMI_VALUE_AMI306; in ak8974_writeable_reg()
816 int irq = i2c->irq; in ak8974_probe()
820 indio_dev = devm_iio_device_alloc(&i2c->dev, sizeof(*ak8974)); in ak8974_probe()
822 return -ENOMEM; in ak8974_probe()
826 ak8974->i2c = i2c; in ak8974_probe()
827 mutex_init(&ak8974->lock); in ak8974_probe()
829 ret = iio_read_mount_matrix(&i2c->dev, &ak8974->orientation); in ak8974_probe()
833 ak8974->regs[0].supply = ak8974_reg_avdd; in ak8974_probe()
834 ak8974->regs[1].supply = ak8974_reg_dvdd; in ak8974_probe()
836 ret = devm_regulator_bulk_get(&i2c->dev, in ak8974_probe()
837 ARRAY_SIZE(ak8974->regs), in ak8974_probe()
838 ak8974->regs); in ak8974_probe()
840 return dev_err_probe(&i2c->dev, ret, "cannot get regulators\n"); in ak8974_probe()
842 ret = regulator_bulk_enable(ARRAY_SIZE(ak8974->regs), ak8974->regs); in ak8974_probe()
844 dev_err(&i2c->dev, "cannot enable regulators\n"); in ak8974_probe()
849 pm_runtime_get_noresume(&i2c->dev); in ak8974_probe()
850 pm_runtime_set_active(&i2c->dev); in ak8974_probe()
851 pm_runtime_enable(&i2c->dev); in ak8974_probe()
853 ak8974->map = devm_regmap_init_i2c(i2c, &ak8974_regmap_config); in ak8974_probe()
854 if (IS_ERR(ak8974->map)) { in ak8974_probe()
855 dev_err(&i2c->dev, "failed to allocate register map\n"); in ak8974_probe()
856 pm_runtime_put_noidle(&i2c->dev); in ak8974_probe()
857 pm_runtime_disable(&i2c->dev); in ak8974_probe()
858 return PTR_ERR(ak8974->map); in ak8974_probe()
863 dev_err(&i2c->dev, "could not power on\n"); in ak8974_probe()
869 dev_err(&i2c->dev, "neither AK8974 nor AMI30x found\n"); in ak8974_probe()
875 dev_err(&i2c->dev, "selftest failed (continuing anyway)\n"); in ak8974_probe()
879 dev_err(&i2c->dev, "AK8974 reset failed\n"); in ak8974_probe()
883 switch (ak8974->variant) { in ak8974_probe()
886 indio_dev->channels = ak8974_12_bits_channels; in ak8974_probe()
887 indio_dev->num_channels = ARRAY_SIZE(ak8974_12_bits_channels); in ak8974_probe()
890 indio_dev->channels = ak8974_15_bits_channels; in ak8974_probe()
891 indio_dev->num_channels = ARRAY_SIZE(ak8974_15_bits_channels); in ak8974_probe()
894 indio_dev->channels = ak8974_12_bits_channels; in ak8974_probe()
895 indio_dev->num_channels = ARRAY_SIZE(ak8974_12_bits_channels); in ak8974_probe()
898 indio_dev->info = &ak8974_info; in ak8974_probe()
899 indio_dev->available_scan_masks = ak8974_scan_masks; in ak8974_probe()
900 indio_dev->modes = INDIO_DIRECT_MODE; in ak8974_probe()
901 indio_dev->name = ak8974->name; in ak8974_probe()
907 dev_err(&i2c->dev, "triggered buffer setup failed\n"); in ak8974_probe()
915 dev_info(&i2c->dev, "enable rising edge DRDY IRQ\n"); in ak8974_probe()
917 ak8974->drdy_active_low = true; in ak8974_probe()
918 dev_info(&i2c->dev, "enable falling edge DRDY IRQ\n"); in ak8974_probe()
925 ret = devm_request_threaded_irq(&i2c->dev, in ak8974_probe()
930 ak8974->name, in ak8974_probe()
933 dev_err(&i2c->dev, "unable to request DRDY IRQ " in ak8974_probe()
934 "- proceeding without IRQ\n"); in ak8974_probe()
937 ak8974->drdy_irq = true; in ak8974_probe()
943 dev_err(&i2c->dev, "device register failed\n"); in ak8974_probe()
947 pm_runtime_set_autosuspend_delay(&i2c->dev, in ak8974_probe()
949 pm_runtime_use_autosuspend(&i2c->dev); in ak8974_probe()
950 pm_runtime_put(&i2c->dev); in ak8974_probe()
957 pm_runtime_put_noidle(&i2c->dev); in ak8974_probe()
958 pm_runtime_disable(&i2c->dev); in ak8974_probe()
960 regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs); in ak8974_probe()
972 pm_runtime_get_sync(&i2c->dev); in ak8974_remove()
973 pm_runtime_put_noidle(&i2c->dev); in ak8974_remove()
974 pm_runtime_disable(&i2c->dev); in ak8974_remove()
976 regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs); in ak8974_remove()
985 regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs); in ak8974_runtime_suspend()
996 ret = regulator_bulk_enable(ARRAY_SIZE(ak8974->regs), ak8974->regs); in ak8974_runtime_resume()
1013 regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs); in ak8974_runtime_resume()
1031 { .compatible = "asahi-kasei,ak8974", },
1049 MODULE_DESCRIPTION("AK8974 and AMI30x 3-axis magnetometer driver");