linux/drivers/iio/magnetometer/yamaha-yas530.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Driver for the Yamaha YAS magnetic sensors, often used in Samsung
 * mobile phones. While all are not yet handled because of lacking
 * hardware, expand this driver to handle the different variants:
 *
 * YAS530 MS-3E (2011 Samsung Galaxy S Advance)
 * YAS532 MS-3R (2011 Samsung Galaxy S4)
 * YAS533 MS-3F (Vivo 1633, 1707, V3, Y21L)
 * (YAS534 is a magnetic switch, not handled)
 * YAS535 MS-6C
 * YAS536 MS-3W
 * YAS537 MS-3T (2015 Samsung Galaxy S6, Note 5, Galaxy S7)
 * YAS539 MS-3S (2018 Samsung Galaxy A7 SM-A750FN)
 *
 * Code functions found in the MPU3050 YAS530 and YAS532 drivers
 * named "inv_compass" in the Tegra Android kernel tree.
 * Copyright (C) 2012 InvenSense Corporation
 *
 * Code functions for YAS537 based on Yamaha Android kernel driver.
 * Copyright (c) 2014 Yamaha Corporation
 *
 * Author: Linus Walleij <[email protected]>
 */
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/random.h>
#include <linux/units.h>

#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>

#include <asm/unaligned.h>

/* Commonly used registers */
#define YAS5XX_DEVICE_ID
#define YAS5XX_MEASURE_DATA

/* These registers are used by YAS530, YAS532 and YAS533 */
#define YAS530_ACTUATE_INIT_COIL
#define YAS530_MEASURE
#define YAS530_CONFIG
#define YAS530_MEASURE_INTERVAL
#define YAS530_OFFSET_X
#define YAS530_OFFSET_Y1
#define YAS530_OFFSET_Y2
#define YAS530_TEST1
#define YAS530_TEST2
#define YAS530_CAL

/* Registers used by YAS537 */
#define YAS537_MEASURE
#define YAS537_CONFIG
#define YAS537_MEASURE_INTERVAL
#define YAS537_OFFSET_X
#define YAS537_OFFSET_Y1
#define YAS537_OFFSET_Y2
#define YAS537_AVR
#define YAS537_HCK
#define YAS537_LCK
#define YAS537_SRST
#define YAS537_ADCCAL
#define YAS537_MTC
#define YAS537_OC
#define YAS537_TRM
#define YAS537_CAL

/* Bits in the YAS5xx config register */
#define YAS5XX_CONFIG_INTON
#define YAS5XX_CONFIG_INTHACT
#define YAS5XX_CONFIG_CCK_MASK
#define YAS5XX_CONFIG_CCK_SHIFT

/* Bits in the measure command register */
#define YAS5XX_MEASURE_START
#define YAS5XX_MEASURE_LDTC
#define YAS5XX_MEASURE_FORS
#define YAS5XX_MEASURE_DLYMES
#define YAS5XX_MEASURE_CONT

/* Bits in the measure data register */
#define YAS5XX_MEASURE_DATA_BUSY

#define YAS530_DEVICE_ID
#define YAS530_VERSION_A
#define YAS530_VERSION_B
#define YAS530_VERSION_A_COEF
#define YAS530_VERSION_B_COEF
#define YAS530_DATA_BITS
#define YAS530_DATA_CENTER
#define YAS530_DATA_OVERFLOW

#define YAS532_DEVICE_ID
#define YAS532_VERSION_AB
#define YAS532_VERSION_AC
#define YAS532_VERSION_AB_COEF
#define YAS532_VERSION_AC_COEF_X
#define YAS532_VERSION_AC_COEF_Y1
#define YAS532_VERSION_AC_COEF_Y2
#define YAS532_DATA_BITS
#define YAS532_DATA_CENTER
#define YAS532_DATA_OVERFLOW

#define YAS537_DEVICE_ID
#define YAS537_VERSION_0
#define YAS537_VERSION_1
#define YAS537_MAG_AVERAGE_32_MASK
#define YAS537_MEASURE_TIME_WORST_US
#define YAS537_DEFAULT_SENSOR_DELAY_MS
#define YAS537_MAG_RCOIL_TIME_US
#define YAS537_MTC3_MASK_PREP
#define YAS537_MTC3_MASK_GET
#define YAS537_MTC3_ADD_BIT
#define YAS537_HCK_MASK_PREP
#define YAS537_HCK_MASK_GET
#define YAS537_LCK_MASK_PREP
#define YAS537_LCK_MASK_GET
#define YAS537_OC_MASK_GET

/* Turn off device regulators etc after 5 seconds of inactivity */
#define YAS5XX_AUTOSUSPEND_DELAY_MS

enum chip_ids {};

static const int yas530_volatile_reg[] =;

static const int yas537_volatile_reg[] =;

struct yas5xx_calibration {};

struct yas5xx;

/**
 * struct yas5xx_chip_info - device-specific data and function pointers
 * @devid: device ID number
 * @product_name: product name of the YAS variant
 * @version_names: version letters or namings
 * @volatile_reg: device-specific volatile registers
 * @volatile_reg_qty: quantity of device-specific volatile registers
 * @scaling_val2: scaling value for IIO_CHAN_INFO_SCALE
 * @t_ref: number of counts at reference temperature 20 °C
 * @min_temp_x10: starting point of temperature counting in 1/10:s degrees Celsius
 * @get_measure: function pointer to get a measurement
 * @get_calibration_data: function pointer to get calibration data
 * @dump_calibration: function pointer to dump calibration for debugging
 * @measure_offsets: function pointer to measure the offsets
 * @power_on: function pointer to power-on procedure
 *
 * The "t_ref" value for YAS532/533 is known from the Android driver.
 * For YAS530 and YAS537 it was approximately measured.
 *
 * The temperatures "min_temp_x10" are derived from the temperature resolutions
 * given in the data sheets.
 */
struct yas5xx_chip_info {};

/**
 * struct yas5xx - state container for the YAS5xx driver
 * @dev: parent device pointer
 * @chip_info: device-specific data and function pointers
 * @version: device version
 * @calibration: calibration settings from the OTP storage
 * @hard_offsets: offsets for each axis measured with initcoil actuated
 * @orientation: mounting matrix, flipped axis etc
 * @map: regmap to access the YAX5xx registers over I2C
 * @regs: the vdd and vddio power regulators
 * @reset: optional GPIO line used for handling RESET
 * @lock: locks the magnetometer for exclusive use during a measurement (which
 * involves several register transactions so the regmap lock is not enough)
 * so that measurements get serialized in a first-come-first serve manner
 * @scan: naturally aligned measurements
 */
struct yas5xx {};

/* On YAS530 the x, y1 and y2 values are 12 bits */
static u16 yas530_extract_axis(u8 *data)
{}

/* On YAS532 the x, y1 and y2 values are 13 bits */
static u16 yas532_extract_axis(u8 *data)
{}

/**
 * yas530_measure() - Make a measure from the hardware
 * @yas5xx: The device state
 * @t: the raw temperature measurement
 * @x: the raw x axis measurement
 * @y1: the y1 axis measurement
 * @y2: the y2 axis measurement
 * @return: 0 on success or error code
 *
 * Used by YAS530, YAS532 and YAS533.
 */
static int yas530_measure(struct yas5xx *yas5xx, u16 *t, u16 *x, u16 *y1, u16 *y2)
{}

/**
 * yas537_measure() - Make a measure from the hardware
 * @yas5xx: The device state
 * @t: the raw temperature measurement
 * @x: the raw x axis measurement
 * @y1: the y1 axis measurement
 * @y2: the y2 axis measurement
 * @return: 0 on success or error code
 */
static int yas537_measure(struct yas5xx *yas5xx, u16 *t, u16 *x, u16 *y1, u16 *y2)
{}

/* Used by YAS530, YAS532 and YAS533 */
static s32 yas530_linearize(struct yas5xx *yas5xx, u16 val, int axis)
{}

static s32 yas5xx_calc_temperature(struct yas5xx *yas5xx, u16 t)
{}

/**
 * yas530_get_measure() - Measure a sample of all axis and process
 * @yas5xx: The device state
 * @to: Temperature out
 * @xo: X axis out
 * @yo: Y axis out
 * @zo: Z axis out
 * @return: 0 on success or error code
 *
 * Used by YAS530, YAS532 and YAS533.
 */
static int yas530_get_measure(struct yas5xx *yas5xx, s32 *to, s32 *xo, s32 *yo, s32 *zo)
{}

/**
 * yas537_get_measure() - Measure a sample of all axis and process
 * @yas5xx: The device state
 * @to: Temperature out
 * @xo: X axis out
 * @yo: Y axis out
 * @zo: Z axis out
 * @return: 0 on success or error code
 */
static int yas537_get_measure(struct yas5xx *yas5xx, s32 *to, s32 *xo, s32 *yo, s32 *zo)
{}

static int yas5xx_read_raw(struct iio_dev *indio_dev,
			   struct iio_chan_spec const *chan,
			   int *val, int *val2,
			   long mask)
{}

static void yas5xx_fill_buffer(struct iio_dev *indio_dev)
{}

static irqreturn_t yas5xx_handle_trigger(int irq, void *p)
{}


static const struct iio_mount_matrix *
yas5xx_get_mount_matrix(const struct iio_dev *indio_dev,
			const struct iio_chan_spec *chan)
{}

static const struct iio_chan_spec_ext_info yas5xx_ext_info[] =;

#define YAS5XX_AXIS_CHANNEL(axis, index)

static const struct iio_chan_spec yas5xx_channels[] =;

static const unsigned long yas5xx_scan_masks[] =;

static const struct iio_info yas5xx_info =;

static bool yas5xx_volatile_reg(struct device *dev, unsigned int reg)
{}

/* TODO: enable regmap cache, using mark dirty and sync at runtime resume */
static const struct regmap_config yas5xx_regmap_config =;

/**
 * yas530_extract_calibration() - extracts the a2-a9 and k calibration
 * @data: the bitfield to use
 * @c: the calibration to populate
 *
 * Used by YAS530, YAS532 and YAS533.
 */
static void yas530_extract_calibration(u8 *data, struct yas5xx_calibration *c)
{}

static int yas530_get_calibration_data(struct yas5xx *yas5xx)
{}

static int yas532_get_calibration_data(struct yas5xx *yas5xx)
{}

static int yas537_get_calibration_data(struct yas5xx *yas5xx)
{}

/* Used by YAS530, YAS532 and YAS533 */
static void yas530_dump_calibration(struct yas5xx *yas5xx)
{}

static void yas537_dump_calibration(struct yas5xx *yas5xx)
{}

/* Used by YAS530, YAS532 and YAS533 */
static int yas530_set_offsets(struct yas5xx *yas5xx, s8 ox, s8 oy1, s8 oy2)
{}

/* Used by YAS530, YAS532 and YAS533 */
static s8 yas530_adjust_offset(s8 old, int bit, u16 center, u16 measure)
{}

/* Used by YAS530, YAS532 and YAS533 */
static int yas530_measure_offsets(struct yas5xx *yas5xx)
{}

/* Used by YAS530, YAS532 and YAS533 */
static int yas530_power_on(struct yas5xx *yas5xx)
{}

static int yas537_power_on(struct yas5xx *yas5xx)
{}

static const struct yas5xx_chip_info yas5xx_chip_info_tbl[] =;

static int yas5xx_probe(struct i2c_client *i2c)
{}

static void yas5xx_remove(struct i2c_client *i2c)
{}

static int yas5xx_runtime_suspend(struct device *dev)
{}

static int yas5xx_runtime_resume(struct device *dev)
{}

static DEFINE_RUNTIME_DEV_PM_OPS(yas5xx_dev_pm_ops, yas5xx_runtime_suspend,
				 yas5xx_runtime_resume, NULL);

static const struct i2c_device_id yas5xx_id[] =;
MODULE_DEVICE_TABLE(i2c, yas5xx_id);

static const struct of_device_id yas5xx_of_match[] =;
MODULE_DEVICE_TABLE(of, yas5xx_of_match);

static struct i2c_driver yas5xx_driver =;
module_i2c_driver();

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_LICENSE();