in slaves/w1_therm.c [1047:1147]
static int convert_t(struct w1_slave *sl, struct therm_info *info)
{
struct w1_master *dev_master = sl->master;
int max_trying = W1_THERM_MAX_TRY;
int t_conv;
int ret = -ENODEV;
bool strong_pullup;
if (!sl->family_data)
goto error;
strong_pullup = (w1_strong_pullup == 2 ||
(!SLAVE_POWERMODE(sl) &&
w1_strong_pullup));
if (strong_pullup && SLAVE_FEATURES(sl) & W1_THERM_POLL_COMPLETION) {
dev_warn(&sl->dev,
"%s: Disabling W1_THERM_POLL_COMPLETION in parasite power mode.\n",
__func__);
SLAVE_FEATURES(sl) &= ~W1_THERM_POLL_COMPLETION;
}
/* get conversion duration device and id dependent */
t_conv = conversion_time(sl);
memset(info->rom, 0, sizeof(info->rom));
/* prevent the slave from going away in sleep */
atomic_inc(THERM_REFCNT(sl->family_data));
if (!bus_mutex_lock(&dev_master->bus_mutex)) {
ret = -EAGAIN; /* Didn't acquire the mutex */
goto dec_refcnt;
}
while (max_trying-- && ret) { /* ret should be 0 */
info->verdict = 0;
info->crc = 0;
/* safe version to select slave */
if (!reset_select_slave(sl)) {
unsigned long sleep_rem;
/* 750ms strong pullup (or delay) after the convert */
if (strong_pullup)
w1_next_pullup(dev_master, t_conv);
w1_write_8(dev_master, W1_CONVERT_TEMP);
if (strong_pullup) { /*some device need pullup */
sleep_rem = msleep_interruptible(t_conv);
if (sleep_rem != 0) {
ret = -EINTR;
goto mt_unlock;
}
mutex_unlock(&dev_master->bus_mutex);
} else { /*no device need pullup */
if (SLAVE_FEATURES(sl) & W1_THERM_POLL_COMPLETION) {
ret = w1_poll_completion(dev_master, W1_POLL_CONVERT_TEMP);
if (ret) {
dev_dbg(&sl->dev, "%s: Timeout\n", __func__);
goto mt_unlock;
}
mutex_unlock(&dev_master->bus_mutex);
} else {
/* Fixed delay */
mutex_unlock(&dev_master->bus_mutex);
sleep_rem = msleep_interruptible(t_conv);
if (sleep_rem != 0) {
ret = -EINTR;
goto dec_refcnt;
}
}
}
ret = read_scratchpad(sl, info);
/* If enabled, check for conversion success */
if ((SLAVE_FEATURES(sl) & W1_THERM_CHECK_RESULT) &&
(info->rom[6] == 0xC) &&
((info->rom[1] == 0x5 && info->rom[0] == 0x50) ||
(info->rom[1] == 0x7 && info->rom[0] == 0xFF))
) {
/* Invalid reading (scratchpad byte 6 = 0xC)
* due to insufficient conversion time
* or power failure.
*/
ret = -EIO;
}
goto dec_refcnt;
}
}
mt_unlock:
mutex_unlock(&dev_master->bus_mutex);
dec_refcnt:
atomic_dec(THERM_REFCNT(sl->family_data));
error:
return ret;
}