/* SPDX-License-Identifier: GPL-2.0-only */ /* * Memsic MXC400xXC Gsensor driver for screen orientation * */ #ifndef __GSENSOR_H #define __GSENSOR_H #include #include #include #include #include /* Gsensor orientation values (hex per API spec) */ enum gsensor_orientation_hex { GSENSOR_ORIENT_UNKNOWN_HEX = 0x00, GSENSOR_ORIENT_PORTRAIT_HEX = 0x14, GSENSOR_ORIENT_LANDSCAPE_HEX = 0x15, GSENSOR_ORIENT_PORTRAIT_FLIP_HEX = 0x16, GSENSOR_ORIENT_LANDSCAPE_FLIP_HEX = 0x17, }; /* Gsensor orientation strings */ #define GSENSOR_ORIENT_PORTRAIT_STR "portrait" #define GSENSOR_ORIENT_LANDSCAPE_STR "landscape" #define GSENSOR_ORIENT_PORTRAIT_FLIP_STR "portrait_flip" #define GSENSOR_ORIENT_LANDSCAPE_FLIP_STR "landscape_flip" /* Gsensor mode bits (per API spec) */ #define GSENSOR_MODE_SOFT_RESET BIT(2) /* EC17: soft reset */ #define GSENSOR_MODE_INITIALIZED BIT(1) /* EC16: 0=not init, 1=init */ #define GSENSOR_MODE_INTERRUPT BIT(0) /* 0=poll, 1=interrupt */ /* Memsic MXC400xXC Register Definitions */ #define MXC400X_REG_WHO_AM_I 0x00 #define MXC400X_WHO_AM_I_VALUE 0x20 #define MXC400X_REG_XOUT_U 0x04 #define MXC400X_REG_XOUT_L 0x05 #define MXC400X_REG_YOUT_U 0x06 #define MXC400X_REG_YOUT_L 0x07 #define MXC400X_REG_ZOUT_U 0x08 #define MXC400X_REG_ZOUT_L 0x09 #define MXC400X_REG_CONTROL 0x0A #define MXC400X_CONTROL_MODE_MASK 0x03 #define MXC400X_CONTROL_MODE_STANDBY 0x00 #define MXC400X_CONTROL_MODE_ACTIVE 0x01 #define MXC400X_CONTROL_MODE_RESET 0x02 #define MXC400X_REG_INT_ENABLE 0x0B #define MXC400X_INT_ENABLE_DRDY BIT(0) #define MXC400X_REG_INT_STATUS 0x0C /* ST LIS2DH12 / SC7A20 register */ #define ST_ACCEL_WHO_AM_I_ADDR 0x0F #define ST_ACCEL_WHO_AM_I_VALUE 0x33 /* LIS2DH12 / SC7A20 */ #define ST_ACCEL_CTRL_REG1_ADDR 0x20 #define ST_ACCEL_CTRL_REG4_ADDR 0x23 #define ST_ACCEL_OUT_X_L_ADDR 0x28 #define ST_ACCEL_OUT_X_H_ADDR 0x29 #define ST_ACCEL_OUT_Y_L_ADDR 0x2A #define ST_ACCEL_OUT_Y_H_ADDR 0x2B #define ST_ACCEL_OUT_Z_L_ADDR 0x2C #define ST_ACCEL_OUT_Z_H_ADDR 0x2D #define ST_ACCEL_STATUS_REG_ADDR 0x27 #define ST_ACCEL_STATUS_DRDY 0x07 /* Driver Constants */ #define GSENSOR_NUMBER_DATA_CHANNELS 3 #define GSENSOR_DEBOUNCE_MS 100 #define MXC400X_SCALE_FACTOR 1000 /* mg per count at 2g range */ /* Default I2C address */ #define MXC400X_DEFAULT_I2C_ADDR 0x15 /* Sensor Settings Structure */ struct gsensor_fs_avl { unsigned int num; /* Full scale value in g */ unsigned int value; /* Register value */ unsigned int gain; /* Gain in micro g per LSB */ }; struct gsensor_odr_avl { unsigned int hz; /* Output data rate in Hz */ unsigned int value; /* Register value */ }; struct gsensor_settings { u8 wai; /* WHO_AM_I expected value */ u8 wai_addr; /* WHO_AM_I register address */ const char **sensors_supported; /* Supported device names */ /* Channel configuration */ const struct iio_chan_spec *ch; int num_channels; /* ODR configuration */ struct { u8 addr; u8 mask; const struct gsensor_odr_avl *odr_avl; int num_odr; } odr; /* Power mode configuration */ struct { u8 addr; u8 mask; u8 value_on; u8 value_off; } pw; /* Full scale configuration */ struct { u8 addr; u8 mask; const struct gsensor_fs_avl *fs_avl; int num_fs; } fs; /* Block Data Update */ struct { u8 addr; u8 mask; } bdu; /* Data ready interrupt */ struct { struct { u8 addr; u8 mask; } int1; u8 addr_ihl; u8 mask_ihl; struct { u8 addr; u8 mask; } stat_drdy; } drdy_irq; /* SPI/I2C interface mode */ struct { u8 addr; u8 value; } sim; bool multi_read_bit; unsigned int bootime; }; /* Driver Data Structure */ struct gsensor_data { struct i2c_client *client; struct device *dev; struct mutex lock; /* Protects data access */ /* Sensor settings */ const struct gsensor_settings *sensor_settings; /* Current configuration */ const struct gsensor_fs_avl *current_fullscale; unsigned int odr; /* Orientation data */ enum gsensor_orientation_hex orientation_hex; char orientation_str[32]; struct delayed_work debounce_work; enum gsensor_orientation_hex pending_orientation; unsigned long last_change_jiffies; /* State */ bool enabled; bool initialized; bool interrupt_mode; bool irq_enabled; /* IIO related */ struct iio_dev *indio_dev; /* Verifone sysfs */ struct kobject *verifone_kobj; /* Regulators (optional) */ struct regulator *vdd; struct regulator *vdd_io; }; /* Core functions */ int gsensor_common_probe(struct iio_dev *indio_dev); void gsensor_common_remove(struct iio_dev *indio_dev); const struct gsensor_settings *gsensor_get_settings(const char *name); /* Buffer functions */ int gsensor_allocate_ring(struct iio_dev *indio_dev); int gsensor_trig_set_state(struct iio_trigger *trig, bool state); int gsensor_allocate_trigger(struct iio_dev *indio_dev); extern const struct iio_trigger_ops gsensor_trigger_ops; /* Power management */ int gsensor_power_enable(struct iio_dev *indio_dev); int gsensor_power_disable(struct iio_dev *indio_dev); /* I2C functions */ int gsensor_i2c_read(struct device *dev, u8 reg, u8 *data, size_t len); int gsensor_i2c_write(struct device *dev, u8 reg, u8 value); int gsensor_init_main(void); void gsensor_exit_main(void); int gsensor_read_raw_data(struct gsensor_data *gs, int *x, int *y, int *z); int gsensor_set_enable(struct gsensor_data *gs, bool enable); int gsensor_set_dataready_irq(struct gsensor_data *gs, bool enable); /* Helper macros */ #define GSENSOR_DEV_ATTR_SAMP_FREQ_AVAIL() \ IIO_DEV_ATTR_SAMP_FREQ_AVAIL(gsensor_show_available_odr) #define GSENSOR_DEV_ATTR_SCALE_AVAIL() \ IIO_DEVICE_ATTR(in_accel_scale_available, 0444, \ gsensor_show_available_scale, NULL, 0) #endif /* __GSENSOR_H */