2009-08-18 17:06:22 +00:00
|
|
|
/*
|
|
|
|
* LISL02DQ.h -- support STMicroelectronics LISD02DQ
|
|
|
|
* 3d 2g Linear Accelerometers via SPI
|
|
|
|
*
|
|
|
|
* Copyright (c) 2007 Jonathan Cameron <jic23@cam.ac.uk>
|
|
|
|
*
|
|
|
|
* Loosely based upon tle62x0.c
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
|
|
* published by the Free Software Foundation.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef SPI_LIS3L02DQ_H_
|
|
|
|
#define SPI_LIS3L02DQ_H_
|
|
|
|
#define LIS3L02DQ_READ_REG(a) ((a) | 0x80)
|
|
|
|
#define LIS3L02DQ_WRITE_REG(a) a
|
|
|
|
|
|
|
|
/* Calibration parameters */
|
|
|
|
#define LIS3L02DQ_REG_OFFSET_X_ADDR 0x16
|
|
|
|
#define LIS3L02DQ_REG_OFFSET_Y_ADDR 0x17
|
|
|
|
#define LIS3L02DQ_REG_OFFSET_Z_ADDR 0x18
|
|
|
|
|
|
|
|
#define LIS3L02DQ_REG_GAIN_X_ADDR 0x19
|
|
|
|
#define LIS3L02DQ_REG_GAIN_Y_ADDR 0x1A
|
|
|
|
#define LIS3L02DQ_REG_GAIN_Z_ADDR 0x1B
|
|
|
|
|
|
|
|
/* Control Register (1 of 2) */
|
|
|
|
#define LIS3L02DQ_REG_CTRL_1_ADDR 0x20
|
|
|
|
/* Power ctrl - either bit set corresponds to on*/
|
|
|
|
#define LIS3L02DQ_REG_CTRL_1_PD_ON 0xC0
|
|
|
|
|
|
|
|
/* Decimation Factor */
|
|
|
|
#define LIS3L02DQ_DEC_MASK 0x30
|
|
|
|
#define LIS3L02DQ_REG_CTRL_1_DF_128 0x00
|
|
|
|
#define LIS3L02DQ_REG_CTRL_1_DF_64 0x10
|
|
|
|
#define LIS3L02DQ_REG_CTRL_1_DF_32 0x20
|
|
|
|
#define LIS3L02DQ_REG_CTRL_1_DF_8 (0x10 | 0x20)
|
|
|
|
|
|
|
|
/* Self Test Enable */
|
|
|
|
#define LIS3L02DQ_REG_CTRL_1_SELF_TEST_ON 0x08
|
|
|
|
|
|
|
|
/* Axes enable ctrls */
|
|
|
|
#define LIS3L02DQ_REG_CTRL_1_AXES_Z_ENABLE 0x04
|
|
|
|
#define LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE 0x02
|
|
|
|
#define LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE 0x01
|
|
|
|
|
|
|
|
/* Control Register (2 of 2) */
|
|
|
|
#define LIS3L02DQ_REG_CTRL_2_ADDR 0x21
|
|
|
|
|
|
|
|
/* Block Data Update only after MSB and LSB read */
|
|
|
|
#define LIS3L02DQ_REG_CTRL_2_BLOCK_UPDATE 0x40
|
|
|
|
|
|
|
|
/* Set to big endian output */
|
|
|
|
#define LIS3L02DQ_REG_CTRL_2_BIG_ENDIAN 0x20
|
|
|
|
|
|
|
|
/* Reboot memory content */
|
|
|
|
#define LIS3L02DQ_REG_CTRL_2_REBOOT_MEMORY 0x10
|
|
|
|
|
|
|
|
/* Interupt Enable - applies data ready to the RDY pad */
|
|
|
|
#define LIS3L02DQ_REG_CTRL_2_ENABLE_INTERRUPT 0x08
|
|
|
|
|
|
|
|
/* Enable Data Ready Generation - relationship with previous unclear in docs */
|
|
|
|
#define LIS3L02DQ_REG_CTRL_2_ENABLE_DATA_READY_GENERATION 0x04
|
|
|
|
|
|
|
|
/* SPI 3 wire mode */
|
|
|
|
#define LIS3L02DQ_REG_CTRL_2_THREE_WIRE_SPI_MODE 0x02
|
|
|
|
|
|
|
|
/* Data alignment, default is 12 bit right justified
|
|
|
|
* - option for 16 bit left justified */
|
|
|
|
#define LIS3L02DQ_REG_CTRL_2_DATA_ALIGNMENT_16_BIT_LEFT_JUSTIFIED 0x01
|
|
|
|
|
|
|
|
/* Interupt related stuff */
|
|
|
|
#define LIS3L02DQ_REG_WAKE_UP_CFG_ADDR 0x23
|
|
|
|
|
|
|
|
/* Switch from or combination fo conditions to and */
|
|
|
|
#define LIS3L02DQ_REG_WAKE_UP_CFG_BOOLEAN_AND 0x80
|
|
|
|
|
|
|
|
/* Latch interupt request,
|
|
|
|
* if on ack must be given by reading the ack register */
|
|
|
|
#define LIS3L02DQ_REG_WAKE_UP_CFG_LATCH_SRC 0x40
|
|
|
|
|
|
|
|
/* Z Interupt on High (above threshold)*/
|
|
|
|
#define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Z_HIGH 0x20
|
|
|
|
/* Z Interupt on Low */
|
|
|
|
#define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Z_LOW 0x10
|
|
|
|
/* Y Interupt on High */
|
|
|
|
#define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Y_HIGH 0x08
|
|
|
|
/* Y Interupt on Low */
|
|
|
|
#define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Y_LOW 0x04
|
|
|
|
/* X Interupt on High */
|
|
|
|
#define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_X_HIGH 0x02
|
|
|
|
/* X Interupt on Low */
|
|
|
|
#define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_X_LOW 0x01
|
|
|
|
|
|
|
|
/* Register that gives description of what caused interupt
|
|
|
|
* - latched if set in CFG_ADDRES */
|
|
|
|
#define LIS3L02DQ_REG_WAKE_UP_SRC_ADDR 0x24
|
|
|
|
/* top bit ignored */
|
|
|
|
/* Interupt Active */
|
|
|
|
#define LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_ACTIVATED 0x40
|
|
|
|
/* Interupts that have been triggered */
|
|
|
|
#define LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_HIGH 0x20
|
|
|
|
#define LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_LOW 0x10
|
|
|
|
#define LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_HIGH 0x08
|
|
|
|
#define LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_LOW 0x04
|
|
|
|
#define LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_HIGH 0x02
|
|
|
|
#define LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_LOW 0x01
|
|
|
|
|
|
|
|
#define LIS3L02DQ_REG_WAKE_UP_ACK_ADDR 0x25
|
|
|
|
|
|
|
|
/* Status register */
|
|
|
|
#define LIS3L02DQ_REG_STATUS_ADDR 0x27
|
|
|
|
/* XYZ axis data overrun - first is all overrun? */
|
|
|
|
#define LIS3L02DQ_REG_STATUS_XYZ_OVERRUN 0x80
|
|
|
|
#define LIS3L02DQ_REG_STATUS_Z_OVERRUN 0x40
|
|
|
|
#define LIS3L02DQ_REG_STATUS_Y_OVERRUN 0x20
|
|
|
|
#define LIS3L02DQ_REG_STATUS_X_OVERRUN 0x10
|
|
|
|
/* XYZ new data available - first is all 3 available? */
|
|
|
|
#define LIS3L02DQ_REG_STATUS_XYZ_NEW_DATA 0x08
|
|
|
|
#define LIS3L02DQ_REG_STATUS_Z_NEW_DATA 0x04
|
|
|
|
#define LIS3L02DQ_REG_STATUS_Y_NEW_DATA 0x02
|
|
|
|
#define LIS3L02DQ_REG_STATUS_X_NEW_DATA 0x01
|
|
|
|
|
|
|
|
/* The accelerometer readings - low and high bytes.
|
|
|
|
Form of high byte dependant on justification set in ctrl reg */
|
|
|
|
#define LIS3L02DQ_REG_OUT_X_L_ADDR 0x28
|
|
|
|
#define LIS3L02DQ_REG_OUT_X_H_ADDR 0x29
|
|
|
|
#define LIS3L02DQ_REG_OUT_Y_L_ADDR 0x2A
|
|
|
|
#define LIS3L02DQ_REG_OUT_Y_H_ADDR 0x2B
|
|
|
|
#define LIS3L02DQ_REG_OUT_Z_L_ADDR 0x2C
|
|
|
|
#define LIS3L02DQ_REG_OUT_Z_H_ADDR 0x2D
|
|
|
|
|
|
|
|
/* Threshold values for all axes and both above and below thresholds
|
|
|
|
* - i.e. there is only one value */
|
|
|
|
#define LIS3L02DQ_REG_THS_L_ADDR 0x2E
|
|
|
|
#define LIS3L02DQ_REG_THS_H_ADDR 0x2F
|
|
|
|
|
|
|
|
#define LIS3L02DQ_DEFAULT_CTRL1 (LIS3L02DQ_REG_CTRL_1_PD_ON \
|
|
|
|
| LIS3L02DQ_REG_CTRL_1_AXES_Z_ENABLE \
|
|
|
|
| LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE \
|
|
|
|
| LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE \
|
|
|
|
| LIS3L02DQ_REG_CTRL_1_DF_128)
|
|
|
|
|
|
|
|
#define LIS3L02DQ_DEFAULT_CTRL2 0
|
|
|
|
|
|
|
|
#define LIS3L02DQ_MAX_TX 12
|
|
|
|
#define LIS3L02DQ_MAX_RX 12
|
|
|
|
/**
|
|
|
|
* struct lis3l02dq_state - device instance specific data
|
|
|
|
* @us: actual spi_device
|
|
|
|
* @work_trigger_to_ring: bh for triggered event handling
|
|
|
|
* @work_cont_thresh: CLEAN
|
|
|
|
* @inter: used to check if new interrupt has been triggered
|
|
|
|
* @last_timestamp: passing timestamp from th to bh of interrupt handler
|
|
|
|
* @indio_dev: industrial I/O device structure
|
|
|
|
* @trig: data ready trigger registered with iio
|
|
|
|
* @tx: transmit buffer
|
|
|
|
* @rx: recieve buffer
|
|
|
|
* @buf_lock: mutex to protect tx and rx
|
|
|
|
**/
|
|
|
|
struct lis3l02dq_state {
|
|
|
|
struct spi_device *us;
|
|
|
|
struct work_struct work_trigger_to_ring;
|
|
|
|
struct iio_work_cont work_cont_thresh;
|
|
|
|
bool inter;
|
|
|
|
s64 last_timestamp;
|
|
|
|
struct iio_dev *indio_dev;
|
|
|
|
struct iio_trigger *trig;
|
|
|
|
u8 *tx;
|
|
|
|
u8 *rx;
|
|
|
|
struct mutex buf_lock;
|
|
|
|
};
|
|
|
|
|
|
|
|
int lis3l02dq_spi_read_reg_8(struct device *dev,
|
|
|
|
u8 reg_address,
|
|
|
|
u8 *val);
|
|
|
|
|
|
|
|
int lis3l02dq_spi_write_reg_8(struct device *dev,
|
|
|
|
u8 reg_address,
|
|
|
|
u8 *val);
|
|
|
|
#define LIS3L02DQ_SCAN_ACC_X 0
|
|
|
|
#define LIS3L02DQ_SCAN_ACC_Y 1
|
|
|
|
#define LIS3L02DQ_SCAN_ACC_Z 2
|
|
|
|
|
2009-08-18 17:06:28 +00:00
|
|
|
|
|
|
|
#ifdef CONFIG_IIO_RING_BUFFER
|
|
|
|
/* At the moment triggers are only used for ring buffer
|
|
|
|
* filling. This may change!
|
|
|
|
*/
|
|
|
|
void lis3l02dq_remove_trigger(struct iio_dev *indio_dev);
|
|
|
|
int lis3l02dq_probe_trigger(struct iio_dev *indio_dev);
|
|
|
|
|
|
|
|
ssize_t lis3l02dq_read_accel_from_ring(struct device *dev,
|
|
|
|
struct device_attribute *attr,
|
|
|
|
char *buf);
|
|
|
|
|
|
|
|
|
|
|
|
int lis3l02dq_configure_ring(struct iio_dev *indio_dev);
|
|
|
|
void lis3l02dq_unconfigure_ring(struct iio_dev *indio_dev);
|
|
|
|
|
|
|
|
int lis3l02dq_initialize_ring(struct iio_ring_buffer *ring);
|
|
|
|
void lis3l02dq_uninitialize_ring(struct iio_ring_buffer *ring);
|
|
|
|
#else /* CONFIG_IIO_RING_BUFFER */
|
|
|
|
|
2009-08-18 17:06:22 +00:00
|
|
|
static inline void lis3l02dq_remove_trigger(struct iio_dev *indio_dev) {};
|
|
|
|
static inline int lis3l02dq_probe_trigger(struct iio_dev *indio_dev)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
static inline ssize_t
|
|
|
|
lis3l02dq_read_accel_from_ring(struct device *dev,
|
|
|
|
struct device_attribute *attr,
|
|
|
|
char *buf)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int lis3l02dq_configure_ring(struct iio_dev *indio_dev)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
static inline void lis3l02dq_unconfigure_ring(struct iio_dev *indio_dev)
|
|
|
|
{};
|
|
|
|
static inline int lis3l02dq_initialize_ring(struct iio_ring_buffer *ring)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
static inline void lis3l02dq_uninitialize_ring(struct iio_ring_buffer *ring) {};
|
2009-08-18 17:06:28 +00:00
|
|
|
#endif /* CONFIG_IIO_RING_BUFFER */
|
2009-08-18 17:06:22 +00:00
|
|
|
#endif /* SPI_LIS3L02DQ_H_ */
|