#define MMC35240_WAIT_CHARGE_PUMP 50000 /* us */ #define MMC35240_WAIT_SET_RESET 1000 /* us */
/* * Memsic OTP process code piece is put here for reference: * * #define OTP_CONVERT(REG) ((float)((REG) >=32 ? (32 - (REG)) : (REG)) * 0.006 * 1) For X axis, the COEFFICIENT is always 1. * 2) For Y axis, the COEFFICIENT is as below: * f_OTP_matrix[4] = OTP_CONVERT(((reg_data[1] & 0x03) << 4) | * (reg_data[2] >> 4)) + 1.0; * 3) For Z axis, the COEFFICIENT is as below: * f_OTP_matrix[8] = (OTP_CONVERT(reg_data[3] & 0x3f) + 1) * 1.35; * We implemented the OTP logic into driver.
*/
/* scale = 1000 here for Y otp */ #define MMC35240_OTP_CONVERT_Y(REG) (((REG) >= 32 ? (32 - (REG)) : (REG)) * 6)
staticint mmc35240_get_samp_freq_index(struct mmc35240_data *data, int val, int val2)
{ int i;
for (i = 0; i < ARRAY_SIZE(mmc35240_samp_freq); i++) if (mmc35240_samp_freq[i].val == val &&
mmc35240_samp_freq[i].val2 == val2) return i; return -EINVAL;
}
/* * Recharge the capacitor at VCAP pin, requested to be issued * before a SET/RESET command.
*/
ret = regmap_set_bits(data->regmap, MMC35240_REG_CTRL0,
MMC35240_CTRL0_REFILL_BIT); if (ret < 0) return ret;
usleep_range(MMC35240_WAIT_CHARGE_PUMP, MMC35240_WAIT_CHARGE_PUMP + 1);
if (set)
coil_bit = MMC35240_CTRL0_SET_BIT; else
coil_bit = MMC35240_CTRL0_RESET_BIT;
ret = regmap_read(data->regmap, MMC35240_REG_ID, ®_id); if (ret < 0) {
dev_err(&data->client->dev, "Error reading product id\n"); return ret;
}
dev_dbg(&data->client->dev, "MMC35240 chip id %x\n", reg_id);
/* * make sure we restore sensor characteristics, by doing * a SET/RESET sequence, the axis polarity being naturally * aligned after RESET
*/
ret = mmc35240_hw_set(data, true); if (ret < 0) return ret;
usleep_range(MMC35240_WAIT_SET_RESET, MMC35240_WAIT_SET_RESET + 1);
ret = mmc35240_hw_set(data, false); if (ret < 0) return ret;
/* set default sampling frequency */
ret = regmap_update_bits(data->regmap, MMC35240_REG_CTRL1,
MMC35240_CTRL1_BW_MASK,
data->res << MMC35240_CTRL1_BW_SHIFT); if (ret < 0) return ret;
ret = regmap_bulk_read(data->regmap, MMC35240_OTP_START_ADDR,
otp_data, sizeof(otp_data)); if (ret < 0) return ret;
ret = regmap_write(data->regmap, MMC35240_REG_CTRL0,
MMC35240_CTRL0_TM_BIT); if (ret < 0) return ret;
while (tries-- > 0) {
ret = regmap_read(data->regmap, MMC35240_REG_STATUS,
®_status); if (ret < 0) return ret; if (reg_status & MMC35240_STATUS_MEAS_DONE_BIT) break; /* minimum wait time to complete measurement is 10 ms */
usleep_range(10000, 11000);
}
if (tries < 0) {
dev_err(&data->client->dev, "data not ready\n"); return -EIO;
}
return 0;
}
staticint mmc35240_read_measurement(struct mmc35240_data *data, __le16 buf[3])
{ int ret;
ret = mmc35240_take_measurement(data); if (ret < 0) return ret;
/** * mmc35240_raw_to_mgauss - convert raw readings to milli gauss. Also apply * compensation for output value. * * @data: device private data * @index: axis index for which we want the conversion * @buf: raw data to be converted, 2 bytes in little endian format * @val: compensated output reading (unit is milli gauss) * * Returns: 0 in case of success, -EINVAL when @index is not valid
*/ staticint mmc35240_raw_to_mgauss(struct mmc35240_data *data, int index,
__le16 buf[], int *val)
{ int raw[3]; int sens[3]; int nfo;
staticint mmc35240_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask)
{ struct mmc35240_data *data = iio_priv(indio_dev); int i, ret;
switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ:
i = mmc35240_get_samp_freq_index(data, val, val2); if (i < 0) return -EINVAL;
mutex_lock(&data->mutex);
ret = regmap_update_bits(data->regmap, MMC35240_REG_CTRL1,
MMC35240_CTRL1_BW_MASK,
i << MMC35240_CTRL1_BW_SHIFT);
mutex_unlock(&data->mutex); return ret; default: return -EINVAL;
}
}
staticbool mmc35240_is_writeable_reg(struct device *dev, unsignedint reg)
{ switch (reg) { case MMC35240_REG_CTRL0: case MMC35240_REG_CTRL1: returntrue; default: returnfalse;
}
}
staticbool mmc35240_is_readable_reg(struct device *dev, unsignedint reg)
{ switch (reg) { case MMC35240_REG_XOUT_L: case MMC35240_REG_XOUT_H: case MMC35240_REG_YOUT_L: case MMC35240_REG_YOUT_H: case MMC35240_REG_ZOUT_L: case MMC35240_REG_ZOUT_H: case MMC35240_REG_STATUS: case MMC35240_REG_ID: returntrue; default: returnfalse;
}
}
staticbool mmc35240_is_volatile_reg(struct device *dev, unsignedint reg)
{ switch (reg) { case MMC35240_REG_CTRL0: case MMC35240_REG_CTRL1: returnfalse; default: returntrue;
}
}
regcache_mark_dirty(data->regmap);
ret = regcache_sync_region(data->regmap, MMC35240_REG_CTRL0,
MMC35240_REG_CTRL1); if (ret < 0)
dev_err(dev, "Failed to restore control registers\n");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.