for (i = 0; i < size; ++i) {
buf[i] = (val >> (i * DA9150_QIF_BYTE_SIZE)) &
DA9150_QIF_BYTE_MASK;
}
da9150_write_qif(fg->da9150, write_addr, size, buf);
}
/* Trigger QIF Sync to update QIF readable data */ staticvoid da9150_fg_read_sync_start(struct da9150_fg *fg)
{ int i = 0;
u32 res = 0;
mutex_lock(&fg->io_lock);
/* Check if QIF sync already requested, and write to sync if not */
res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
DA9150_QIF_SYNC_SIZE); if (res > 0)
da9150_fg_write_attr(fg, DA9150_QIF_SYNC,
DA9150_QIF_SYNC_SIZE, 0);
/* Wait for sync to complete */
res = 0; while ((res == 0) && (i++ < DA9150_QIF_SYNC_RETRIES)) {
usleep_range(DA9150_QIF_SYNC_TIMEOUT,
DA9150_QIF_SYNC_TIMEOUT * 2);
res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
DA9150_QIF_SYNC_SIZE);
}
/* Check if sync completed */ if (res == 0)
dev_err(fg->dev, "Failed to perform QIF read sync!\n");
}
/* * Should always be called after QIF sync read has been performed, and all * attributes required have been accessed.
*/ staticinlinevoid da9150_fg_read_sync_end(struct da9150_fg *fg)
{
mutex_unlock(&fg->io_lock);
}
/* Sync read of single QIF attribute */ static u32 da9150_fg_read_attr_sync(struct da9150_fg *fg, u8 code, u8 size)
{
u32 val;
da9150_fg_read_sync_start(fg);
val = da9150_fg_read_attr(fg, code, size);
da9150_fg_read_sync_end(fg);
return val;
}
/* Wait for QIF Sync, write QIF data and wait for ack */ staticvoid da9150_fg_write_attr_sync(struct da9150_fg *fg, u8 code, u8 size,
u32 val)
{ int i = 0;
u32 res = 0, sync_val;
mutex_lock(&fg->io_lock);
/* Check if QIF sync already requested */
res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
DA9150_QIF_SYNC_SIZE);
/* Wait for an existing sync to complete */ while ((res == 0) && (i++ < DA9150_QIF_SYNC_RETRIES)) {
usleep_range(DA9150_QIF_SYNC_TIMEOUT,
DA9150_QIF_SYNC_TIMEOUT * 2);
res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
DA9150_QIF_SYNC_SIZE);
}
if (res == 0) {
dev_err(fg->dev, "Timeout waiting for existing QIF sync!\n");
mutex_unlock(&fg->io_lock); return;
}
/* Write value for QIF code */
da9150_fg_write_attr(fg, code, size, val);
/* Wait for write acknowledgment */
i = 0;
sync_val = res; while ((res == sync_val) && (i++ < DA9150_QIF_SYNC_RETRIES)) {
usleep_range(DA9150_QIF_SYNC_TIMEOUT,
DA9150_QIF_SYNC_TIMEOUT * 2);
res = da9150_fg_read_attr(fg, DA9150_QIF_SYNC,
DA9150_QIF_SYNC_SIZE);
}
mutex_unlock(&fg->io_lock);
/* Check write was actually successful */ if (res != (sync_val + 1))
dev_err(fg->dev, "Error performing QIF sync write for code %d\n",
code);
}
/* Power Supply attributes */ staticint da9150_fg_capacity(struct da9150_fg *fg, union power_supply_propval *val)
{
val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_SOC_PCT,
DA9150_QIF_SOC_PCT_SIZE);
/* * Temperature reading from device is only valid if battery/system provides * valid NTC to associated pin of DA9150 chip.
*/ staticint da9150_fg_temp(struct da9150_fg *fg, union power_supply_propval *val)
{
val->intval = da9150_fg_read_attr_sync(fg, DA9150_QIF_NTCAVG,
DA9150_QIF_NTCAVG_SIZE);
staticint da9150_fg_get_prop(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val)
{ struct da9150_fg *fg = dev_get_drvdata(psy->dev.parent); int ret;
switch (psp) { case POWER_SUPPLY_PROP_CAPACITY:
ret = da9150_fg_capacity(fg, val); break; case POWER_SUPPLY_PROP_CURRENT_AVG:
ret = da9150_fg_current_avg(fg, val); break; case POWER_SUPPLY_PROP_VOLTAGE_AVG:
ret = da9150_fg_voltage_avg(fg, val); break; case POWER_SUPPLY_PROP_CHARGE_FULL:
ret = da9150_fg_charge_full(fg, val); break; case POWER_SUPPLY_PROP_TEMP:
ret = da9150_fg_temp(fg, val); break; default:
ret = -EINVAL; break;
}
/* * If an interval period has been provided then setup repeating * work for reporting data updates.
*/ if (fg->interval) {
ret = devm_delayed_work_autocancel(dev, &fg->work,
da9150_fg_work); if (ret) {
dev_err(dev, "Failed to init work\n"); return ret;
}
/* * Trigger SOC check to happen now so as to indicate any value change * since last check before suspend.
*/ if (fg->interval)
flush_delayed_work(&fg->work);
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.