staticvoid cc2_disable(struct cc2_data *data)
{ int err;
/* ignore alarms triggered by voltage toggling when powering up */
data->process_irqs = false;
/* exclusive regulator, check in case an enable failed */ if (regulator_is_enabled(data->regulator)) {
err = regulator_disable(data->regulator); if (err)
dev_dbg(&data->client->dev, "Failed to disable device");
}
}
staticint cc2_cmd_response_diagnostic(struct device *dev, u8 status)
{ int resp;
if (FIELD_GET(CC2_STATUS_FIELD, status) != CC2_STATUS_CMD_MODE) {
dev_dbg(dev, "Command sent out of command window\n"); return -ETIMEDOUT;
}
resp = FIELD_GET(CC2_RESPONSE_FIELD, status); switch (resp) { case CC2_RESPONSE_ACK: return0; case CC2_RESPONSE_BUSY: return -EBUSY; case CC2_RESPONSE_NACK: if (resp & CC2_ERR_CORR_EEPROM)
dev_dbg(dev, "Command failed: corrected EEPROM\n"); if (resp & CC2_ERR_UNCORR_EEPROM)
dev_dbg(dev, "Command failed: uncorrected EEPROM\n"); if (resp & CC2_ERR_RAM_PARITY)
dev_dbg(dev, "Command failed: RAM parity\n"); if (resp & CC2_ERR_RAM_PARITY)
dev_dbg(dev, "Command failed: configuration error\n"); return -ENODATA; default:
dev_dbg(dev, "Unknown command reply\n"); return -EINVAL;
}
}
staticint cc2_read_command_status(struct i2c_client *client)
{
u8 status; int ret;
ret = i2c_master_recv(client, &status, 1); if (ret != 1) {
ret = ret < 0 ? ret : -EIO; return ret;
}
/* *ThecommandmodeisonlyaccessibleaftersendingtheSTART_CMcommandinthe *first10msafterpower-up.Onlyincasethecommandwindowismissed, *CC2_CM_RETRIESretriesareattemptedbeforegivingupandreturninganerror.
*/ staticint cc2_command_mode_start(struct cc2_data *data)
{ unsignedlong timeout; int i, ret;
for (i = 0; i < CC2_CM_RETRIES; i++) {
ret = cc2_enable(data); if (ret < 0) return ret;
ret = i2c_smbus_write_word_data(data->client, CC2_START_CM, 0); if (ret < 0) return ret;
if (data->irq_ready > 0) {
timeout = usecs_to_jiffies(2 * CC2_RESP_START_CM_US);
ret = wait_for_completion_timeout(&data->complete,
timeout); if (!ret) return -ETIMEDOUT;
} else {
usleep_range(CC2_RESP_START_CM_US, 2 * CC2_RESP_START_CM_US);
}
ret = cc2_read_command_status(data->client); if (ret != -ETIMEDOUT || i == CC2_CM_RETRIES) break;
/* command window missed, prepare for a retry */
cc2_disable(data);
msleep(CC2_POWER_CYCLE_MS);
}
return ret;
}
/* Sending a Start_NOM command finishes the command mode immediately with no *replyandthedeviceentersnormaloperationmode
*/ staticint cc2_command_mode_finish(struct cc2_data *data)
{ int ret;
ret = i2c_smbus_write_word_data(data->client, CC2_START_NOM, 0); if (ret < 0) return ret;
ret = cc2_command_mode_start(data); if (ret < 0) return ret;
ret = i2c_smbus_write_word_data(data->client, reg, 0); if (ret < 0) return ret;
if (data->irq_ready > 0) {
timeout = usecs_to_jiffies(2 * CC2_RESP_EEPROM_R_US);
ret = wait_for_completion_timeout(&data->complete, timeout); if (!ret) return -ETIMEDOUT;
} else {
usleep_range(CC2_RESP_EEPROM_R_US, CC2_RESP_EEPROM_R_US + 10);
}
ret = i2c_master_recv(data->client, buf, CC2_EEPROM_DATA_LEN); if (ret != CC2_EEPROM_DATA_LEN) return ret < 0 ? ret : -EIO;
*val = be16_to_cpup((__be16 *)&buf[1]);
return cc2_read_command_status(data->client);
}
staticint cc2_get_reg_val(struct cc2_data *data, u8 reg, long *val)
{
u16 reg_val; int ret;
ret = cc2_read_reg(data, reg, ®_val); if (!ret)
*val = cc2_rh_convert(reg_val);
cc2_disable(data);
return ret;
}
staticint cc2_data_fetch(struct i2c_client *client, enum hwmon_sensor_types type, long *val)
{
u8 data[CC2_MEASUREMENT_DATA_LEN];
u8 status; int ret;
ret = i2c_master_recv(client, data, CC2_MEASUREMENT_DATA_LEN); if (ret != CC2_MEASUREMENT_DATA_LEN) {
ret = ret < 0 ? ret : -EIO; return ret;
}
status = FIELD_GET(CC2_STATUS_FIELD, data[0]); if (status == CC2_STATUS_STALE_DATA) return -EBUSY;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) return -EOPNOTSUPP;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM;
i2c_set_clientdata(client, data);
mutex_init(&data->dev_access_lock);
data->client = client;
data->regulator = devm_regulator_get_exclusive(dev, "vdd"); if (IS_ERR(data->regulator)) return dev_err_probe(dev, PTR_ERR(data->regulator), "Failed to get regulator\n");
ret = cc2_request_ready_irq(data, dev); if (ret) return dev_err_probe(dev, ret, "Failed to request ready irq\n");
ret = cc2_request_alarm_irqs(data, dev); if (ret) return dev_err_probe(dev, ret, "Failed to request alarm irqs\n");
data->hwmon = devm_hwmon_device_register_with_info(dev, client->name,
data, &cc2_chip_info,
NULL); if (IS_ERR(data->hwmon)) return dev_err_probe(dev, PTR_ERR(data->hwmon), "Failed to register hwmon device\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.