Lines Matching full:ak8974
3 * Driver for the Asahi Kasei EMD Corporation AK8974
42 /* These registers are common for AK8974 and AMI30x */
68 /* AK8974-specific offsets */
173 * struct ak8974 - state container for the AK8974 driver
176 * @map: regmap to access the AK8974 registers over I2C
186 struct ak8974 { struct
207 static int ak8974_get_u16_val(struct ak8974 *ak8974, u8 reg, u16 *val) in ak8974_get_u16_val() argument
212 ret = regmap_bulk_read(ak8974->map, reg, &bulk, 2); in ak8974_get_u16_val()
220 static int ak8974_set_u16_val(struct ak8974 *ak8974, u8 reg, u16 val) in ak8974_set_u16_val() argument
224 return regmap_bulk_write(ak8974->map, reg, &bulk, 2); in ak8974_set_u16_val()
227 static int ak8974_set_power(struct ak8974 *ak8974, bool mode) in ak8974_set_power() argument
234 ret = regmap_write(ak8974->map, AK8974_CTRL1, val); in ak8974_set_power()
244 static int ak8974_reset(struct ak8974 *ak8974) in ak8974_reset() argument
249 ret = ak8974_set_power(ak8974, AK8974_PWR_ON); in ak8974_reset()
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()
271 return ak8974_set_power(ak8974, AK8974_PWR_OFF); in ak8974_reset()
274 static int ak8974_configure(struct ak8974 *ak8974) in ak8974_configure() argument
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()
287 ret = ak8974_set_u16_val(ak8974, AMI306_CTRL4, 0xA07E); 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()
300 static int ak8974_trigmeas(struct ak8974 *ak8974) in ak8974_trigmeas() argument
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()
333 static int ak8974_await_drdy(struct ak8974 *ak8974) in ak8974_await_drdy() argument
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()
353 ret = regmap_read(ak8974->map, AK8974_STATUS, &val); in ak8974_await_drdy()
360 dev_err(&ak8974->i2c->dev, "timeout waiting for DRDY\n"); in ak8974_await_drdy()
364 static int ak8974_getresult(struct ak8974 *ak8974, __le16 *result) in ak8974_getresult() argument
369 ret = ak8974_await_drdy(ak8974); in ak8974_getresult()
372 ret = regmap_read(ak8974->map, AK8974_INT_SRC, &src); in ak8974_getresult()
378 dev_err(&ak8974->i2c->dev, in ak8974_getresult()
383 ret = regmap_bulk_read(ak8974->map, AK8974_DATA_X, result, 6); in ak8974_getresult()
392 struct ak8974 *ak8974 = d; in ak8974_drdy_irq() local
394 if (!ak8974->drdy_irq) in ak8974_drdy_irq()
403 struct ak8974 *ak8974 = d; in ak8974_drdy_irq_thread() local
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()
423 static int ak8974_selftest(struct ak8974 *ak8974) in ak8974_selftest() argument
425 struct device *dev = &ak8974->i2c->dev; in ak8974_selftest()
429 ret = regmap_read(ak8974->map, AK8974_SELFTEST, &val); 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()
454 ret = regmap_read(ak8974->map, AK8974_SELFTEST, &val); in ak8974_selftest()
466 static void ak8974_read_calib_data(struct ak8974 *ak8974, unsigned int reg, in ak8974_read_calib_data() argument
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()
480 static int ak8974_detect(struct ak8974 *ak8974) in ak8974_detect() argument
488 ret = regmap_read(ak8974->map, AK8974_WHOAMI, &whoami); in ak8974_detect()
499 ret = regmap_read(ak8974->map, AMI305_VER, &fw); in ak8974_detect()
503 ret = ak8974_get_u16_val(ak8974, AMI305_SN, &sn); in ak8974_detect()
507 dev_info(&ak8974->i2c->dev, in ak8974_detect()
512 name = "ak8974"; 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()
525 ak8974->name = name; in ak8974_detect()
526 ak8974->variant = whoami; in ak8974_detect()
532 ak8974_read_calib_data(ak8974, AMI306_FINEOUTPUT_X, in ak8974_detect()
534 ak8974_read_calib_data(ak8974, AMI306_OFFZERO_X, in ak8974_detect()
548 dev_info(&ak8974->i2c->dev, in ak8974_detect()
558 static int ak8974_measure_channel(struct ak8974 *ak8974, unsigned long address, in ak8974_measure_channel() argument
564 pm_runtime_get_sync(&ak8974->i2c->dev); in ak8974_measure_channel()
565 mutex_lock(&ak8974->lock); in ak8974_measure_channel()
571 ret = ak8974_trigmeas(ak8974); in ak8974_measure_channel()
574 ret = ak8974_getresult(ak8974, hw_values); 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()
597 struct ak8974 *ak8974 = iio_priv(indio_dev); in ak8974_read_raw() local
603 dev_err(&ak8974->i2c->dev, "faulty channel address\n"); 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()
659 struct ak8974 *ak8974 = iio_priv(indio_dev); in ak8974_fill_buffer() local
662 pm_runtime_get_sync(&ak8974->i2c->dev); in ak8974_fill_buffer()
663 mutex_lock(&ak8974->lock); in ak8974_fill_buffer()
665 ret = ak8974_trigmeas(ak8974); 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()
700 struct ak8974 *ak8974 = iio_priv(indio_dev); in ak8974_get_mount_matrix() local
702 return &ak8974->orientation; in ak8974_get_mount_matrix()
729 * We have no datasheet for the AK8974 but we guess that its
761 struct ak8974 *ak8974 = iio_priv(indio_dev); in ak8974_writeable_reg() local
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()
814 struct ak8974 *ak8974; in ak8974_probe() local
820 indio_dev = devm_iio_device_alloc(&i2c->dev, sizeof(*ak8974)); in ak8974_probe()
824 ak8974 = iio_priv(indio_dev); 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()
837 ARRAY_SIZE(ak8974->regs), in ak8974_probe()
838 ak8974->regs); in ak8974_probe()
842 ret = regulator_bulk_enable(ARRAY_SIZE(ak8974->regs), ak8974->regs); 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()
858 return PTR_ERR(ak8974->map); in ak8974_probe()
861 ret = ak8974_set_power(ak8974, AK8974_PWR_ON); in ak8974_probe()
867 ret = ak8974_detect(ak8974); in ak8974_probe()
869 dev_err(&i2c->dev, "neither AK8974 nor AMI30x found\n"); in ak8974_probe()
873 ret = ak8974_selftest(ak8974); in ak8974_probe()
877 ret = ak8974_reset(ak8974); in ak8974_probe()
879 dev_err(&i2c->dev, "AK8974 reset failed\n"); in ak8974_probe()
883 switch (ak8974->variant) { in ak8974_probe()
901 indio_dev->name = ak8974->name; in ak8974_probe()
917 ak8974->drdy_active_low = true; in ak8974_probe()
930 ak8974->name, in ak8974_probe()
931 ak8974); in ak8974_probe()
937 ak8974->drdy_irq = true; in ak8974_probe()
959 ak8974_set_power(ak8974, AK8974_PWR_OFF); in ak8974_probe()
960 regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs); in ak8974_probe()
968 struct ak8974 *ak8974 = iio_priv(indio_dev); in ak8974_remove() local
975 ak8974_set_power(ak8974, AK8974_PWR_OFF); in ak8974_remove()
976 regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs); in ak8974_remove()
981 struct ak8974 *ak8974 = in ak8974_runtime_suspend() local
984 ak8974_set_power(ak8974, AK8974_PWR_OFF); in ak8974_runtime_suspend()
985 regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs); in ak8974_runtime_suspend()
992 struct ak8974 *ak8974 = in ak8974_runtime_resume() local
996 ret = regulator_bulk_enable(ARRAY_SIZE(ak8974->regs), ak8974->regs); in ak8974_runtime_resume()
1000 ret = ak8974_set_power(ak8974, AK8974_PWR_ON); in ak8974_runtime_resume()
1004 ret = ak8974_configure(ak8974); in ak8974_runtime_resume()
1011 ak8974_set_power(ak8974, AK8974_PWR_OFF); in ak8974_runtime_resume()
1013 regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs); in ak8974_runtime_resume()
1024 { "ak8974" },
1031 { .compatible = "asahi-kasei,ak8974", },
1039 .name = "ak8974",
1049 MODULE_DESCRIPTION("AK8974 and AMI30x 3-axis magnetometer driver");