static int bma250_power_down(struct driver_data *dd) { int rc = 0; char bypass = 0; struct bma250_platform_data *pdata = dd->ic_dev->dev.platform_data; mutex_lock(&bma250_power_lock); if (slave_hw) { pdata->vote_sleep_status(BMA250_SLAVE1, BMA250_SLEEP); pdata->bypass_state(READ_BYPASS_STATE, &bypass); if (!bypass) { if (pdata->check_sleep_status() == BMA250_SLEEP) { rc = bma250_ic_write(dd->ic_dev, BMA250_MODE_CTRL_REG, BMA250_MODE_SUSPEND); cancel_delayed_work(&dd->work_data); } } } else { rc = bma250_ic_write(dd->ic_dev, BMA250_MODE_CTRL_REG, BMA250_MODE_SUSPEND); cancel_delayed_work(&dd->work_data); } (void)dd->pdata->hw_config(&dd->ic_dev->dev, 0); dd->power = false; mutex_unlock(&bma250_power_lock); return rc; }
static ssize_t bma250_calib_image_show(struct device *dev, struct device_attribute *attr, char *buf) { struct driver_data *dd = dev_get_drvdata(dev); int rc; /* enable EEPROM */ rc = bma250_ic_write(dd->ic_dev, BMA250_EEPROM_CTRL_REG, BMA250_EEPROM_PROG_MODE); if (rc) goto calib_offset_reg_error; /* get eeprom offset value */ rc = bma250_ic_read(dd->ic_dev, BMA250_OFFSET_X_AXIS_REG, buf, BMA250_CALIB_GET_REG_MAX); if (rc) goto calib_offset_reg_error; /* disable EEPROM */ rc = bma250_ic_write(dd->ic_dev, BMA250_EEPROM_CTRL_REG, BMA250_EEPROM_RDY_MODE); if (rc) goto calib_offset_reg_error; dev_dbg(&dd->ic_dev->dev, "%s:REG:%d:%d:%d\n", __func__, *buf, *(buf+1), *(buf+2)); return BMA250_CALIB_GET_REG_MAX; calib_offset_reg_error: dev_err(&dd->ic_dev->dev, "%s: Offset read/write error from register.\n", __func__); return -EIO; }
static int bma250_power_up(struct driver_data *dd) { int rc; mutex_lock(&bma250_power_lock); rc = bma250_hw_setup(dd); if (rc) goto hw_setup_error; rc = bma250_ic_write(dd->ic_dev, BMA250_RESET_REG, BMA250_RESET); if (rc) goto power_up_error; msleep(4); rc = bma250_ic_write(dd->ic_dev, BMA250_MODE_CTRL_REG, BMA250_MODE_NOSLEEP); if (rc) goto power_up_error; dd->power = true; mutex_unlock(&bma250_power_lock); return rc; power_up_error: bma250_hw_shutdown(dd); hw_setup_error: dd->power = false; mutex_unlock(&bma250_power_lock); return rc; }
static inline int bma250_rate_handler(struct driver_data *dd) { int rc = 0; u8 sleep, filter; if (dd->new_cnf.rate == dd->cur_cnf.rate) return rc; if (dd->new_cnf.rate > 1000) { sleep = BMA250_MODE_SLEEP_1000MS; } else if (dd->new_cnf.rate > 500) { sleep = BMA250_MODE_SLEEP_500MS; } else if (dd->new_cnf.rate > 100) { sleep = BMA250_MODE_SLEEP_100MS; } else if (dd->new_cnf.rate > 50) { sleep = BMA250_MODE_SLEEP_50MS; } else if (dd->new_cnf.rate > 25) { sleep = BMA250_MODE_SLEEP_25MS; } else if (dd->new_cnf.rate > 10) { sleep = BMA250_MODE_SLEEP_10MS; } else if (dd->new_cnf.rate > 6) { sleep = BMA250_MODE_SLEEP_6MS; } else { sleep = BMA250_MODE_NOSLEEP; } if (dd->new_cnf.rate > 100) { filter = BMA250_BW_7_81HZ; } else if (dd->new_cnf.rate > 50) { filter = BMA250_BW_15_63HZ; } else { filter = BMA250_BW_31_25HZ; } /* only possible to use sleep together with interrupt */ if (dd->new_cnf.resolution == TIMER_RESOLUTION) sleep = BMA250_MODE_NOSLEEP; rc = bma250_ic_write(dd->ic_dev, BMA250_MODE_CTRL_REG, sleep); if (rc) goto rate_error; rc = bma250_ic_write(dd->ic_dev, BMA250_BW_SEL_REG, filter); if (rc) goto rate_error; dd->delay_jiffies = msecs_to_jiffies(dd->new_cnf.rate); dd->cur_cnf.rate = dd->new_cnf.rate; return rc; rate_error: dev_err(&dd->ip_dev->dev, "%s: device failed, error %d\n", __func__, rc); return rc; }
static int bma250_power_up(struct driver_data *dd) { int rc = 0; char bypass = 0; struct bma250_platform_data *pdata = dd->ic_dev->dev.platform_data; mutex_lock(&bma250_power_lock); rc = dd->pdata->hw_config(&dd->ic_dev->dev, 1); if (rc) goto hw_setup_error; if (slave_hw) { pdata->bypass_state(READ_BYPASS_STATE, &bypass); if (!bypass) { if (pdata->check_sleep_status() == BMA250_SLEEP) { rc = bma250_ic_write(dd->ic_dev, BMA250_RESET_REG, BMA250_RESET); if (rc) goto power_up_error; msleep(BMA250_STARTUP_TIME); rc = bma250_ic_write(dd->ic_dev, BMA250_MODE_CTRL_REG, BMA250_MODE_NOSLEEP); if (rc) goto power_up_error; } } pdata->vote_sleep_status(BMA250_SLAVE1, BMA250_AWAKE); } else { rc = bma250_ic_write(dd->ic_dev, BMA250_RESET_REG, BMA250_RESET); if (rc) goto power_up_error; msleep(BMA250_STARTUP_TIME); rc = bma250_ic_write(dd->ic_dev, BMA250_MODE_CTRL_REG, BMA250_MODE_NOSLEEP); if (rc) goto power_up_error; } dd->power = true; mutex_unlock(&bma250_power_lock); return rc; power_up_error: printk(KERN_ERR "%s: Force power doen due to not read bypass status.\n", __func__); (void) dd->pdata->hw_config(&dd->ic_dev->dev, 0); hw_setup_error: printk(KERN_ERR "%s: Force power down.(bypass check error)\n", __func__); dd->power = false; mutex_unlock(&bma250_power_lock); return rc; }
static int bma250_config(struct driver_data *dd) { int rc; u8 rx_buf[2]; const struct registers *preg = &use_chip_default; struct bma250_platform_data *pdata = dd->ic_dev->dev.platform_data; /* use platform data register values if they exist */ if (pdata && pdata->reg) preg = pdata->reg; rc = bma250_power_up(dd); if (rc) goto config_exit; rc = bma250_ic_read(dd->ic_dev, BMA250_CHIP_ID_REG, rx_buf, 2); if (rc) goto config_exit; if ((rx_buf[0] == 0x00) || (rx_buf[1] == 0x00)) { printk(KERN_ERR "bma250: device not found.\n"); rc = -ENODEV; goto config_exit; } printk(KERN_INFO "bma250: detected chip id %d, rev 0x%X\n", rx_buf[0] & 0x07, rx_buf[1]); if (preg->int_pin1 >= 0) { rc = bma250_ic_write(dd->ic_dev, BMA250_INT_PIN1_REG, preg->int_pin1); if (rc) goto config_exit; } if (preg->int_pin2 >= 0) { rc = bma250_ic_write(dd->ic_dev, BMA250_INT_PIN2_REG, preg->int_pin2); if (rc) goto config_exit; } rc = bma250_ic_write(dd->ic_dev, BMA250_INT_CTRL_REG, BMA250_INT_MODE_LATCHED); if (rc) goto config_exit; rc = bma250_update_settings(dd); config_exit: return rc; }
static inline int bma250_calibration_init(struct device *dev) { int rc; char bypass = 0; struct driver_data *dd = dev_get_drvdata(dev); struct bma250_platform_data *pdata = dd->ic_dev->dev.platform_data; /* Check whether Gyro had been activated. */ if (slave_hw) pdata->bypass_state(READ_BYPASS_STATE, &bypass); if (slave_hw && bypass) { rc = -EBUSY; goto calib_init_error_end; } /* Save POWER flag for recovery */ dd->recovery_power = dd->power; if (!(dd->recovery_power)) { /* Power ON if accelerometer is suspend state. */ rc = bma250_power_up(dd); if (rc) goto calib_init_error; } else { /* Stop data updating if accelerometer is active state. */ cancel_delayed_work(&dd->work_data); } /* Set +/-2g Range Mode and 15.63 Hz Low Pass Filter Mode */ rc = bma250_ic_write(dd->ic_dev, BMA250_RANGE_REG, BMA250_RANGE_2G); if (rc) goto calib_init_error; rc = bma250_ic_write(dd->ic_dev, BMA250_BW_SEL_REG, BMA250_BW_15_63HZ); if (rc) goto calib_init_error; msleep(BMA250_CALIB_SET_INTERVAL); return rc; calib_init_error: dev_err(&dd->ic_dev->dev, "%s: Calibration start failure.(%d)\n", __func__, rc); rc = -EIO; calib_init_error_end: return rc; }
static int bma250_power_down(struct driver_data *dd) { int rc; mutex_lock(&bma250_power_lock); if (!dd->ip_dev->users) rc = bma250_ic_write(dd->ic_dev, BMA250_MODE_CTRL_REG, BMA250_MODE_SUSPEND); else rc = bma250_ic_write(dd->ic_dev, BMA250_MODE_CTRL_REG, BMA250_MODE_LOWPOWER); dd->power = false; cancel_delayed_work(&dd->work_data); mutex_unlock(&bma250_power_lock); return rc; }
static ssize_t bma250_calib_image_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct driver_data *dd = dev_get_drvdata(dev); int rc; dev_dbg(&dd->ic_dev->dev, "%s : Image DEC : %d:%d:%d\n", __func__, *buf, *(buf + 1), *(buf + 2)); /* enable EEPROM */ rc = bma250_ic_write(dd->ic_dev, BMA250_EEPROM_CTRL_REG, BMA250_EEPROM_PROG_MODE); if (rc) goto calib_set_image_reg_error; /* write X axis calibration data to Image (LSB) */ rc = bma250_ic_write(dd->ic_dev, BMA250_OFFSET_X_AXIS_REG, *buf); if (rc) goto calib_set_image_reg_error; /* write Y axis calibration data to Image (LSB) */ rc = bma250_ic_write(dd->ic_dev, BMA250_OFFSET_Y_AXIS_REG, *(buf + 1)); if (rc) goto calib_set_image_reg_error; /* write Z axis calibration data to Image (LSB) */ rc = bma250_ic_write(dd->ic_dev, BMA250_OFFSET_Z_AXIS_REG, *(buf + 2)); if (rc) goto calib_set_image_reg_error; /* disable EEPROM */ rc = bma250_ic_write(dd->ic_dev, BMA250_EEPROM_CTRL_REG, BMA250_EEPROM_RDY_MODE); if (rc) goto calib_set_image_reg_error; msleep(BMA250_CALIB_SET_EEPROM); return BMA250_CALIB_GET_REG_MAX; calib_set_image_reg_error: dev_err(&dd->ic_dev->dev, "%s: Image write error from register.\n", __func__); return -EIO; }
static inline int bma250_range_handler(struct driver_data *dd) { int rc = 0; u8 range, threshold, duration = 0; if (dd->new_cnf.range == dd->cur_cnf.range) return rc; if (dd->new_cnf.range == 16) { range = BMA250_RANGE_16G; threshold = 2; } else if (dd->new_cnf.range == 8) { range = BMA250_RANGE_8G; threshold = 3; } else if (dd->new_cnf.range == 4) { range = BMA250_RANGE_4G; threshold = 4; } else { range = BMA250_RANGE_2G; threshold = 5; } rc = bma250_ic_write(dd->ic_dev, BMA250_RANGE_REG, range); if (rc) goto range_error; /* threshold definition for the slope int, g-range dependant */ rc = bma250_ic_write(dd->ic_dev, BMA250_SLOPE_THR, threshold); if (rc) goto range_error; /* number of samples (n + 1) to be evaluted for slope int */ rc = bma250_ic_write(dd->ic_dev, BMA250_SLOPE_DUR, duration); if (rc) goto range_error; dd->shift = bma250_range2shift(range); dd->cur_cnf.range = dd->new_cnf.range; return rc; range_error: dev_err(&dd->ip_dev->dev, "%s: device failed, error %d\n", __func__, rc); return rc; }
static inline int bma250_bw_handler(struct driver_data *dd) { if (dd->rate > 100) dd->bw_sel = BMA250_BW_7_81HZ; else if (dd->rate > 50) dd->bw_sel = BMA250_BW_15_63HZ; else dd->bw_sel = BMA250_BW_31_25HZ; return bma250_ic_write(dd->ic_dev, BMA250_BW_SEL_REG, dd->bw_sel); }
static inline int bma250_resolution_handler(struct driver_data *dd) { int rc = 0; u8 interrupt; if (dd->new_cnf.resolution == dd->cur_cnf.resolution) return rc; if (dd->new_cnf.resolution == INTERRUPT_RESOLUTION) { /* slope and orientation interrupt based motion detect */ interrupt = BMA250_INT_SLOPE_Z | BMA250_INT_SLOPE_Y | BMA250_INT_SLOPE_X | BMA250_INT_ORIENT; } else { /* disable all interrupts, use timer based solution */ interrupt = 0; /* only possible to use sleep together with interrupt */ rc = bma250_ic_write(dd->ic_dev,BMA250_MODE_CTRL_REG, BMA250_MODE_NOSLEEP); if (rc) goto resolution_error; } rc = bma250_ic_write(dd->ic_dev, BMA250_INT_ENABLE1_REG, interrupt); if (rc) dev_err(&dd->ip_dev->dev, "%s: device failed, error %d\n", __func__, rc); else dd->cur_cnf.resolution = dd->new_cnf.resolution; return rc; resolution_error: dev_err(&dd->ip_dev->dev, "%s: device failed, error %d\n", __func__, rc); return rc; }
static int bma250_power_down(struct driver_data *dd) { int rc; mutex_lock(&bma250_power_lock); rc = bma250_ic_write(dd->ic_dev, BMA250_MODE_CTRL_REG, BMA250_MODE_SUSPEND); cancel_delayed_work(&dd->work_data); bma250_hw_shutdown(dd); dd->power = false; mutex_unlock(&bma250_power_lock); return rc; }
static int bma250_power_up(struct driver_data *dd) { int rc; mutex_lock(&bma250_power_lock); dd->cur_cnf.rate = INVALID; dd->cur_cnf.range = INVALID; dd->cur_cnf.resolution = INVALID; dd->power = true; rc = bma250_ic_write(dd->ic_dev, BMA250_RESET_REG, BMA250_RESET); msleep(4); mutex_unlock(&bma250_power_lock); return rc; }
static inline int bma250_reset_interrupt(struct driver_data *dd) { int rc = 0; u8 val; if (dd->cur_cnf.resolution == INTERRUPT_RESOLUTION) { rc = bma250_ic_read(dd->ic_dev, BMA250_INT_CTRL_REG, &val, 1); if (rc) goto interrupt_error; rc = bma250_ic_write(dd->ic_dev, BMA250_INT_CTRL_REG, val | BMA250_INT_RESET); if (rc) goto interrupt_error; } return rc; interrupt_error: dev_err(&dd->ip_dev->dev, "%s: device failed, error %d\n", __func__, rc); return rc; }
static ssize_t bma250_dbfs_write(struct file *fp, const char __user *buf, size_t count, loff_t *f_pos) { u8 *p; u8 *np; u8 *mbuf; int rc; unsigned int val; u8 reg; u8 data; struct driver_data *dd; /* format of write data is "A[A] D[D]" eg. "AA DD", "A D" etc where A is address in hex, D is data in hex. Multiple address/data pairs may be separated by spaces. */ if (count < 3) return 0; dd = fp->private_data; mbuf = kzalloc(count, GFP_KERNEL); if (!mbuf) { rc = -ENOMEM; goto dbfs_write_exit; } if (copy_from_user(mbuf, buf, count)) { rc = -EFAULT; goto dbfs_write_exit_copy; } p = mbuf; while (isspace(*p)) p++; do { val = simple_strtoul(p, (char **)&np, 16); if ((val > BMA250_LAST_REG) || (p == np)) { rc = -EINVAL; goto dbfs_write_exit_copy; } while (isspace(*np) && ((np - mbuf) < count)) np++; p = np; reg = (u8)val; val = simple_strtoul(p, (char **)&np, 16); if ((val > 0xFF) || (p == np)) { rc = -EINVAL; goto dbfs_write_exit_copy; } while (isspace(*np) && ((np - mbuf) < count)) np++; p = np; data = (u8)val; rc = bma250_ic_write(dd->ic_dev, reg, data); /* update here to avoid checking g-range at each interrupt */ if ((!rc) && (reg == BMA250_RANGE_REG)) dd->shift = bma250_range2shift(data); } while (!rc && (np - mbuf) < count); if (rc) goto dbfs_write_exit; kfree(mbuf); return count; dbfs_write_exit_copy: kfree(mbuf); dbfs_write_exit: return rc; }
static ssize_t bma250_calib_eeprom_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct driver_data *dd = dev_get_drvdata(dev); int rc; u8 tmp = 0; dev_dbg(&dd->ic_dev->dev, "%s : DEC : %d:%d:%d\n", __func__, *buf, *(buf + 1), *(buf + 2)); /* enable EEPROM */ rc = bma250_ic_write(dd->ic_dev, BMA250_EEPROM_CTRL_REG, BMA250_EEPROM_PROG_MODE); if (rc) goto calib_EEPROM_error; /* write X axis calibration data to Image (LSB) */ rc = bma250_ic_write(dd->ic_dev, BMA250_OFFSET_X_AXIS_REG, *buf); if (rc) goto calib_EEPROM_error; /* write Y axis calibration data to Image (LSB) */ rc = bma250_ic_write(dd->ic_dev, BMA250_OFFSET_Y_AXIS_REG, *(buf + 1)); if (rc) goto calib_EEPROM_error; /* write Z axis calibration data to Image (LSB) */ rc = bma250_ic_write(dd->ic_dev, BMA250_OFFSET_Z_AXIS_REG, *(buf + 2)); if (rc) goto calib_EEPROM_error; /* enable EEPROM write process */ rc = bma250_ic_write(dd->ic_dev, BMA250_EEPROM_CTRL_REG, BMA250_EEPROM_WRITE_MODE); if (rc) goto calib_EEPROM_error; msleep(BMA250_CALIB_SET_EEPROM); /* waiting for nvm_rdy bit is set*/ do { msleep(BMA250_CALIB_GET_INTERVAL); rc = bma250_ic_read(dd->ic_dev, BMA250_EEPROM_CTRL_REG, &tmp, 1); if (rc) goto calib_EEPROM_error; } while (!(tmp & BMA250_EEPROM_NOT_RDY_MODE)); /* disable data access to EEPROM area */ rc = bma250_ic_write(dd->ic_dev, BMA250_EEPROM_CTRL_REG, BMA250_EEPROM_RDY_MODE); if (rc) goto calib_EEPROM_error; msleep(BMA250_CALIB_SET_EEPROM); return BMA250_CALIB_GET_REG_MAX; calib_EEPROM_error: dev_err(&dd->ic_dev->dev, "%s: EEPROM read/write error from register.\n", __func__); return -EIO; }