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;
}
Exemple #3
0
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;
}
Exemple #4
0
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;
}
Exemple #6
0
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;
}
Exemple #8
0
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;
}
Exemple #10
0
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;
}
Exemple #11
0
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);
}
Exemple #12
0
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;
}
Exemple #13
0
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;
}
Exemple #14
0
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;
}
Exemple #15
0
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;
}
Exemple #16
0
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;
}