diff options
Diffstat (limited to 'driver/accel_kxcj9.c')
-rw-r--r-- | driver/accel_kxcj9.c | 219 |
1 files changed, 106 insertions, 113 deletions
diff --git a/driver/accel_kxcj9.c b/driver/accel_kxcj9.c index 1dc491151b..de05f85559 100644 --- a/driver/accel_kxcj9.c +++ b/driver/accel_kxcj9.c @@ -5,7 +5,7 @@ /* KXCJ9 gsensor module for Chrome EC */ -#include "accelerometer.h" +#include "accelgyro.h" #include "common.h" #include "console.h" #include "driver/accel_kxcj9.h" @@ -31,20 +31,20 @@ struct accel_param_pair { }; /* List of range values in +/-G's and their associated register values. */ -const struct accel_param_pair ranges[] = { +static const struct accel_param_pair ranges[] = { {2, KXCJ9_GSEL_2G}, {4, KXCJ9_GSEL_4G}, {8, KXCJ9_GSEL_8G_14BIT} }; /* List of resolution values in bits and their associated register values. */ -const struct accel_param_pair resolutions[] = { +static const struct accel_param_pair resolutions[] = { {8, KXCJ9_RES_8BIT}, {12, KXCJ9_RES_12BIT} }; /* List of ODR values in mHz and their associated register values. */ -const struct accel_param_pair datarates[] = { +static const struct accel_param_pair datarates[] = { {781, KXCJ9_OSA_0_781HZ}, {1563, KXCJ9_OSA_1_563HZ}, {3125, KXCJ9_OSA_3_125HZ}, @@ -59,24 +59,6 @@ const struct accel_param_pair datarates[] = { {1600000, KXCJ9_OSA_1600_HZ} }; -/* Current range of each accelerometer. The value is an index into ranges[]. */ -static int sensor_range[ACCEL_COUNT] = {0, 0}; - -/* - * Current resolution of each accelerometer. The value is an index into - * resolutions[]. - */ -static int sensor_resolution[ACCEL_COUNT] = {1, 1}; - -/* - * Current output data rate of each accelerometer. The value is an index into - * datarates[]. - */ -static int sensor_datarate[ACCEL_COUNT] = {6, 6}; - - -static struct mutex accel_mutex[ACCEL_COUNT]; - /** * Find index into a accel_param_pair that matches the given engineering value * passed in. The round_up flag is used to specify whether to round up or down. @@ -126,12 +108,12 @@ static int raw_write8(const int addr, const int reg, int data) * * Note: This is intended to be called in a pair with enable_sensor(). * - * @id Sensor index + * @data Pointer to motion sensor data * @ctrl1 Pointer to location to store KXCJ9_CTRL1 register after disabling * * @return EC_SUCCESS if successful, EC_ERROR_* otherwise */ -static int disable_sensor(const enum accel_id id, int *ctrl1) +static int disable_sensor(struct kxcj9_data *data, int *ctrl1) { int ret; @@ -139,7 +121,7 @@ static int disable_sensor(const enum accel_id id, int *ctrl1) * Read the current state of the ctrl1 register so that we can restore * it later. */ - ret = raw_read8(accel_addr[id], KXCJ9_CTRL1, ctrl1); + ret = raw_read8(data->accel_addr, KXCJ9_CTRL1, ctrl1); if (ret != EC_SUCCESS) return ret; @@ -147,13 +129,13 @@ static int disable_sensor(const enum accel_id id, int *ctrl1) * Before disabling the sensor, acquire mutex to prevent another task * from attempting to access accel parameters until we enable sensor. */ - mutex_lock(&accel_mutex[id]); + mutex_lock(&data->accel_mutex); /* Disable sensor. */ *ctrl1 &= ~KXCJ9_CTRL1_PC1; - ret = raw_write8(accel_addr[id], KXCJ9_CTRL1, *ctrl1); + ret = raw_write8(data->accel_addr, KXCJ9_CTRL1, *ctrl1); if (ret != EC_SUCCESS) { - mutex_unlock(&accel_mutex[id]); + mutex_unlock(&data->accel_mutex); return ret; } @@ -165,178 +147,166 @@ static int disable_sensor(const enum accel_id id, int *ctrl1) * * Note: This is intended to be called in a pair with disable_sensor(). * - * @id Sensor index + * @data Pointer to motion sensor data * @ctrl1 Value of KXCJ9_CTRL1 register to write to sensor * * @return EC_SUCCESS if successful, EC_ERROR_* otherwise */ -static int enable_sensor(const enum accel_id id, const int ctrl1) +static int enable_sensor(struct kxcj9_data *data, const int ctrl1) { int i, ret; for (i = 0; i < SENSOR_ENABLE_ATTEMPTS; i++) { /* Enable accelerometer based on ctrl1 value. */ - ret = raw_write8(accel_addr[id], KXCJ9_CTRL1, + ret = raw_write8(data->accel_addr, KXCJ9_CTRL1, ctrl1 | KXCJ9_CTRL1_PC1); /* On first success, we are done. */ if (ret == EC_SUCCESS) { - mutex_unlock(&accel_mutex[id]); + mutex_unlock(&data->accel_mutex); return EC_SUCCESS; } - } /* Release mutex. */ - mutex_unlock(&accel_mutex[id]); + mutex_unlock(&data->accel_mutex); /* Cannot enable accel, print warning and return an error. */ - CPRINTF("Error trying to enable accelerometer %d\n", id); + CPRINTF("Error trying to enable accelerometer\n"); return ret; } -int accel_set_range(const enum accel_id id, const int range, const int rnd) +static int accel_set_range(void *drv_data, + const int range, + const int rnd) { int ret, ctrl1, ctrl1_new, index; - - /* Check for valid id. */ - if (id < 0 || id >= ACCEL_COUNT) - return EC_ERROR_INVAL; + struct kxcj9_data *data = (struct kxcj9_data *)drv_data; /* Find index for interface pair matching the specified range. */ index = find_param_index(range, rnd, ranges, ARRAY_SIZE(ranges)); /* Disable the sensor to allow for changing of critical parameters. */ - ret = disable_sensor(id, &ctrl1); + ret = disable_sensor(data, &ctrl1); if (ret != EC_SUCCESS) return ret; /* Determine new value of CTRL1 reg and attempt to write it. */ ctrl1_new = (ctrl1 & ~KXCJ9_GSEL_ALL) | ranges[index].reg; - ret = raw_write8(accel_addr[id], KXCJ9_CTRL1, ctrl1_new); + ret = raw_write8(data->accel_addr, KXCJ9_CTRL1, ctrl1_new); /* If successfully written, then save the range. */ if (ret == EC_SUCCESS) { - sensor_range[id] = index; + data->sensor_range = index; ctrl1 = ctrl1_new; } /* Re-enable the sensor. */ - if (enable_sensor(id, ctrl1) != EC_SUCCESS) + if (enable_sensor(data, ctrl1) != EC_SUCCESS) return EC_ERROR_UNKNOWN; return ret; } -int accel_get_range(const enum accel_id id, int * const range) +static int accel_get_range(void *drv_data, int * const range) { - /* Check for valid id. */ - if (id < 0 || id >= ACCEL_COUNT) - return EC_ERROR_INVAL; - - *range = ranges[sensor_range[id]].val; + struct kxcj9_data *data = (struct kxcj9_data *)drv_data; + *range = ranges[data->sensor_range].val; return EC_SUCCESS; } -int accel_set_resolution(const enum accel_id id, const int res, const int rnd) +static int accel_set_resolution(void *drv_data, + const int res, + const int rnd) { int ret, ctrl1, ctrl1_new, index; - - /* Check for valid id. */ - if (id < 0 || id >= ACCEL_COUNT) - return EC_ERROR_INVAL; + struct kxcj9_data *data = (struct kxcj9_data *)drv_data; /* Find index for interface pair matching the specified resolution. */ index = find_param_index(res, rnd, resolutions, ARRAY_SIZE(resolutions)); /* Disable the sensor to allow for changing of critical parameters. */ - ret = disable_sensor(id, &ctrl1); + ret = disable_sensor(data, &ctrl1); if (ret != EC_SUCCESS) return ret; /* Determine new value of CTRL1 reg and attempt to write it. */ ctrl1_new = (ctrl1 & ~KXCJ9_RES_12BIT) | resolutions[index].reg; - ret = raw_write8(accel_addr[id], KXCJ9_CTRL1, ctrl1_new); + ret = raw_write8(data->accel_addr, KXCJ9_CTRL1, ctrl1_new); /* If successfully written, then save the range. */ if (ret == EC_SUCCESS) { - sensor_resolution[id] = index; + data->sensor_resolution = index; ctrl1 = ctrl1_new; } /* Re-enable the sensor. */ - if (enable_sensor(id, ctrl1) != EC_SUCCESS) + if (enable_sensor(data, ctrl1) != EC_SUCCESS) return EC_ERROR_UNKNOWN; return ret; } -int accel_get_resolution(const enum accel_id id, int * const res) +static int accel_get_resolution(void *drv_data, int * const res) { - /* Check for valid id. */ - if (id < 0 || id >= ACCEL_COUNT) - return EC_ERROR_INVAL; - - *res = resolutions[sensor_resolution[id]].val; + struct kxcj9_data *data = (struct kxcj9_data *)drv_data; + *res = resolutions[data->sensor_resolution].val; return EC_SUCCESS; } -int accel_set_datarate(const enum accel_id id, const int rate, const int rnd) +static int accel_set_datarate(void *drv_data, + const int rate, + const int rnd) { int ret, ctrl1, index; - - /* Check for valid id. */ - if (id < 0 || id >= ACCEL_COUNT) - return EC_ERROR_INVAL; + struct kxcj9_data *data = (struct kxcj9_data *)drv_data; /* Find index for interface pair matching the specified rate. */ index = find_param_index(rate, rnd, datarates, ARRAY_SIZE(datarates)); /* Disable the sensor to allow for changing of critical parameters. */ - ret = disable_sensor(id, &ctrl1); + ret = disable_sensor(data, &ctrl1); if (ret != EC_SUCCESS) return ret; /* Set output data rate. */ - ret = raw_write8(accel_addr[id], KXCJ9_DATA_CTRL, + ret = raw_write8(data->accel_addr, KXCJ9_DATA_CTRL, datarates[index].reg); /* If successfully written, then save the range. */ if (ret == EC_SUCCESS) - sensor_datarate[id] = index; + data->sensor_datarate = index; /* Re-enable the sensor. */ - if (enable_sensor(id, ctrl1) != EC_SUCCESS) + if (enable_sensor(data, ctrl1) != EC_SUCCESS) return EC_ERROR_UNKNOWN; return ret; } -int accel_get_datarate(const enum accel_id id, int * const rate) +static int accel_get_datarate(void *drv_data, int * const rate) { - /* Check for valid id. */ - if (id < 0 || id >= ACCEL_COUNT) - return EC_ERROR_INVAL; - - *rate = datarates[sensor_datarate[id]].val; + struct kxcj9_data *data = (struct kxcj9_data *)drv_data; + *rate = datarates[data->sensor_datarate].val; return EC_SUCCESS; } #ifdef CONFIG_ACCEL_INTERRUPTS -int accel_set_interrupt(const enum accel_id id, unsigned int threshold) +static int accel_set_interrupt(void *drv_data, unsigned int threshold) { int ctrl1, tmp, ret; + struct kxcj9_data *data = (struct kxcj9_data *)drv_data; /* Disable the sensor to allow for changing of critical parameters. */ - ret = disable_sensor(id, &ctrl1); + ret = disable_sensor(data, &ctrl1); if (ret != EC_SUCCESS) return ret; /* Set interrupt timer to 1 so it wakes up immediately. */ - ret = raw_write8(accel_addr[id], KXCJ9_WAKEUP_TIMER, 1); + ret = raw_write8(data->accel_addr, KXCJ9_WAKEUP_TIMER, 1); if (ret != EC_SUCCESS) goto error_enable_sensor; @@ -345,7 +315,7 @@ int accel_set_interrupt(const enum accel_id id, unsigned int threshold) * first we need to divide by 16 to get the value to send. */ threshold >>= 4; - ret = raw_write8(accel_addr[id], KXCJ9_WAKEUP_THRESHOLD, threshold); + ret = raw_write8(data->accel_addr, KXCJ9_WAKEUP_THRESHOLD, threshold); if (ret != EC_SUCCESS) goto error_enable_sensor; @@ -354,11 +324,11 @@ int accel_set_interrupt(const enum accel_id id, unsigned int threshold) * function is called once, the interrupt stays enabled and it is * only necessary to clear KXCJ9_INT_REL to allow the next interrupt. */ - ret = raw_read8(accel_addr[id], KXCJ9_INT_CTRL1, &tmp); + ret = raw_read8(data->accel_addr, KXCJ9_INT_CTRL1, &tmp); if (ret != EC_SUCCESS) goto error_enable_sensor; if (!(tmp & KXCJ9_INT_CTRL1_IEN)) { - ret = raw_write8(accel_addr[id], KXCJ9_INT_CTRL1, + ret = raw_write8(data->accel_addr, KXCJ9_INT_CTRL1, tmp | KXCJ9_INT_CTRL1_IEN); if (ret != EC_SUCCESS) goto error_enable_sensor; @@ -369,41 +339,40 @@ int accel_set_interrupt(const enum accel_id id, unsigned int threshold) * Note: this register latches motion detected above threshold. Once * latched, no interrupt can occur until this register is cleared. */ - ret = raw_read8(accel_addr[id], KXCJ9_INT_REL, &tmp); + ret = raw_read8(data->accel_addr, KXCJ9_INT_REL, &tmp); error_enable_sensor: /* Re-enable the sensor. */ - if (enable_sensor(id, ctrl1) != EC_SUCCESS) + if (enable_sensor(data, ctrl1) != EC_SUCCESS) return EC_ERROR_UNKNOWN; return ret; } #endif -int accel_read(const enum accel_id id, int * const x_acc, int * const y_acc, - int * const z_acc) +static int accel_read(void *drv_data, + int * const x_acc, + int * const y_acc, + int * const z_acc) { uint8_t acc[6]; uint8_t reg = KXCJ9_XOUT_L; int ret, multiplier; - - /* Check for valid id. */ - if (id < 0 || id >= ACCEL_COUNT) - return EC_ERROR_INVAL; + struct kxcj9_data *data = (struct kxcj9_data *)drv_data; /* Read 6 bytes starting at KXCJ9_XOUT_L. */ - mutex_lock(&accel_mutex[id]); + mutex_lock(&data->accel_mutex); i2c_lock(I2C_PORT_ACCEL, 1); - ret = i2c_xfer(I2C_PORT_ACCEL, accel_addr[id], ®, 1, acc, 6, + ret = i2c_xfer(I2C_PORT_ACCEL, data->accel_addr, ®, 1, acc, 6, I2C_XFER_SINGLE); i2c_lock(I2C_PORT_ACCEL, 0); - mutex_unlock(&accel_mutex[id]); + mutex_unlock(&data->accel_mutex); if (ret != EC_SUCCESS) return ret; /* Determine multiplier based on stored range. */ - switch (ranges[sensor_range[id]].reg) { + switch (ranges[data->sensor_range].reg) { case KXCJ9_GSEL_2G: multiplier = 1; break; @@ -436,17 +405,23 @@ int accel_read(const enum accel_id id, int * const x_acc, int * const y_acc, return EC_SUCCESS; } -int accel_init(const enum accel_id id) +static int accel_init(void *drv_data, int i2c_addr) { int ret = EC_SUCCESS; int cnt = 0, ctrl1, ctrl2; + struct kxcj9_data *data = (struct kxcj9_data *)drv_data; - /* Check for valid id. */ - if (id < 0 || id >= ACCEL_COUNT) + if (data == NULL) return EC_ERROR_INVAL; + memset(&data->accel_mutex, sizeof(struct mutex), 0); + data->sensor_range = 0; + data->sensor_datarate = 6; + data->sensor_resolution = 1; + data->accel_addr = i2c_addr; + /* Disable the sensor to allow for changing of critical parameters. */ - ret = disable_sensor(id, &ctrl1); + ret = disable_sensor(data, &ctrl1); if (ret != EC_SUCCESS) return ret; @@ -455,13 +430,13 @@ int accel_init(const enum accel_id id) * the sensor is unknown here. Initiate software reset to restore * sensor to default. */ - ret = raw_write8(accel_addr[id], KXCJ9_CTRL2, KXCJ9_CTRL2_SRST); + ret = raw_write8(data->accel_addr, KXCJ9_CTRL2, KXCJ9_CTRL2_SRST); if (ret != EC_SUCCESS) return ret; /* Wait until software reset is complete or timeout. */ while (1) { - ret = raw_read8(accel_addr[id], KXCJ9_CTRL2, &ctrl2); + ret = raw_read8(data->accel_addr, KXCJ9_CTRL2, &ctrl2); /* Reset complete. */ if (ret == EC_SUCCESS && !(ctrl2 & KXCJ9_CTRL2_SRST)) @@ -476,23 +451,25 @@ int accel_init(const enum accel_id id) } /* Set resolution and range. */ - ctrl1 = resolutions[sensor_resolution[id]].reg | - ranges[sensor_range[id]].reg; + ctrl1 = resolutions[data->sensor_resolution].reg | + ranges[data->sensor_range].reg; #ifdef CONFIG_ACCEL_INTERRUPTS /* Enable wake up (motion detect) functionality. */ ctrl1 |= KXCJ9_CTRL1_WUFE; #endif - ret = raw_write8(accel_addr[id], KXCJ9_CTRL1, ctrl1); + ret = raw_write8(data->accel_addr, KXCJ9_CTRL1, ctrl1); #ifdef CONFIG_ACCEL_INTERRUPTS /* Set interrupt polarity to rising edge and keep interrupt disabled. */ - ret |= raw_write8(accel_addr[id], KXCJ9_INT_CTRL1, KXCJ9_INT_CTRL1_IEA); + ret |= raw_write8(data->accel_addr, + KXCJ9_INT_CTRL1, + KXCJ9_INT_CTRL1_IEA); /* Set output data rate for wake-up interrupt function. */ - ret |= raw_write8(accel_addr[id], KXCJ9_CTRL2, KXCJ9_OWUF_100_0HZ); + ret |= raw_write8(data->accel_addr, KXCJ9_CTRL2, KXCJ9_OWUF_100_0HZ); /* Set interrupt to trigger on motion on any axis. */ - ret |= raw_write8(accel_addr[id], KXCJ9_INT_CTRL2, + ret |= raw_write8(data->accel_addr, KXCJ9_INT_CTRL2, KXCJ9_INT_SRC2_XNWU | KXCJ9_INT_SRC2_XPWU | KXCJ9_INT_SRC2_YNWU | KXCJ9_INT_SRC2_YPWU | KXCJ9_INT_SRC2_ZNWU | KXCJ9_INT_SRC2_ZPWU); @@ -506,11 +483,27 @@ int accel_init(const enum accel_id id) #endif /* Set output data rate. */ - ret |= raw_write8(accel_addr[id], KXCJ9_DATA_CTRL, - datarates[sensor_datarate[id]].reg); + ret |= raw_write8(data->accel_addr, KXCJ9_DATA_CTRL, + datarates[data->sensor_datarate].reg); /* Enable the sensor. */ - ret |= enable_sensor(id, ctrl1); + ret |= enable_sensor(data, ctrl1); return ret; } + +const struct accelgyro_info accel_kxcj9 = { + .chip_type = CHIP_KXCJ9, + .sensor_type = SENSOR_ACCELEROMETER, + .init = accel_init, + .read = accel_read, + .set_range = accel_set_range, + .get_range = accel_get_range, + .set_resolution = accel_set_resolution, + .get_resolution = accel_get_resolution, + .set_datarate = accel_set_datarate, + .get_datarate = accel_get_datarate, +#ifdef CONFIG_ACCEL_INTERRUPTS + .set_interrupt = accel_set_interrupt, +#endif +}; |