/* Module setup. */
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Jan Kandziora ");
MODULE_DESCRIPTION("w1 family 19 driver for DS28E17, 1-wire to I2C master bridge");
MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS28E17));
/* Default I2C speed to be set when a DS28E17 is detected. */ staticint i2c_speed = 100;
module_param_named(speed, i2c_speed, int, 0600);
MODULE_PARM_DESC(speed, "Default I2C speed to be set when a DS28E17 is detected");
/* Default I2C stretch value to be set when a DS28E17 is detected. */ staticchar i2c_stretch = 1;
module_param_named(stretch, i2c_stretch, byte, 0600);
MODULE_PARM_DESC(stretch, "Default I2C stretch value to be set when a DS28E17 is detected");
/* Wait a while until the busy flag clears. */ staticint w1_f19_i2c_busy_wait(struct w1_slave *sl, size_t count)
{ constunsignedlong timebases[3] = W1_F19_BUSY_TIMEBASES; struct w1_f19_data *data = sl->family_data; unsignedint checks;
/* Check the busy flag first in any case.*/ if (w1_touch_bit(sl->master, 1) == 0) return 0;
/* * Do a generously long sleep in the beginning, * as we have to wait at least this time for all * the I2C bytes at the given speed to be transferred.
*/
usleep_range(timebases[data->speed] * (data->stretch) * count,
timebases[data->speed] * (data->stretch) * count
+ W1_F19_BUSY_GRATUITY);
/* Now continusly check the busy flag sent by the DS28E17. */
checks = W1_F19_BUSY_CHECKS; while ((checks--) > 0) { /* Return success if the busy flag is cleared. */ if (w1_touch_bit(sl->master, 1) == 0) return 0;
/* Wait one non-streched byte timeslot. */
udelay(timebases[data->speed]);
}
/* Return number of bytes written. */ return count;
}
/* Write data to I2C slave. */ staticint w1_f19_i2c_write(struct w1_slave *sl, u16 i2c_address, const u8 *buffer, size_t count, bool stop)
{ int result; int remaining = count; const u8 *p;
u8 command[2];
/* Check input. */ if (count == 0) return -EOPNOTSUPP;
/* Check whether we need multiple commands. */ if (count <= W1_F19_WRITE_DATA_LIMIT) { /* * Small data amount. Data can be sent with * a single onewire command.
*/
/* Send all data to DS28E17. */
command[0] = (stop ? W1_F19_WRITE_DATA_WITH_STOP
: W1_F19_WRITE_DATA_NO_STOP);
command[1] = i2c_address << 1;
result = __w1_f19_i2c_write(sl, command, 2, buffer, count);
} else { /* Large data amount. Data has to be sent in multiple chunks. */
/* Send first chunk to DS28E17. */
p = buffer;
command[0] = W1_F19_WRITE_DATA_NO_STOP;
command[1] = i2c_address << 1;
result = __w1_f19_i2c_write(sl, command, 2, p,
W1_F19_WRITE_DATA_LIMIT); if (result < 0) return result;
/* Resume to same DS28E17. */ if (w1_reset_resume_command(sl->master)) return -EIO;
/* Next data chunk. */
p += W1_F19_WRITE_DATA_LIMIT;
remaining -= W1_F19_WRITE_DATA_LIMIT;
while (remaining > W1_F19_WRITE_DATA_LIMIT) { /* Send intermediate chunk to DS28E17. */
command[0] = W1_F19_WRITE_DATA_ONLY;
result = __w1_f19_i2c_write(sl, command, 1, p,
W1_F19_WRITE_DATA_LIMIT); if (result < 0) return result;
/* Resume to same DS28E17. */ if (w1_reset_resume_command(sl->master)) return -EIO;
/* Next data chunk. */
p += W1_F19_WRITE_DATA_LIMIT;
remaining -= W1_F19_WRITE_DATA_LIMIT;
}
/* Send final chunk to DS28E17. */
command[0] = (stop ? W1_F19_WRITE_DATA_ONLY_WITH_STOP
: W1_F19_WRITE_DATA_ONLY);
result = __w1_f19_i2c_write(sl, command, 1, p, remaining);
}
return result;
}
/* Read data from I2C slave. */ staticint w1_f19_i2c_read(struct w1_slave *sl, u16 i2c_address,
u8 *buffer, size_t count)
{
u16 crc; int error;
u8 w1_buf[5];
/* Check input. */ if (count == 0) return -EOPNOTSUPP;
/* Read received I2C data from DS28E17. */ return w1_read_block(sl->master, rbuffer, rcount);
}
/* Do an I2C master transfer. */ staticint w1_f19_i2c_master_transfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
{ struct w1_slave *sl = (struct w1_slave *) adapter->algo_data; int i = 0; int result = 0;
/* Select DS28E17. */ if (w1_reset_select_slave(sl)) {
i = -EIO; goto error;
}
/* Loop while there are still messages to transfer. */ while (i < num) { /* * Check for special case: Small write followed * by read to same I2C device.
*/ if (i < (num-1)
&& msgs[i].addr == msgs[i+1].addr
&& !(msgs[i].flags & I2C_M_RD)
&& (msgs[i+1].flags & I2C_M_RD)
&& (msgs[i].len <= W1_F19_WRITE_DATA_LIMIT)) { /* * The DS28E17 has a combined transfer * for small write+read.
*/
result = w1_f19_i2c_write_read(sl, msgs[i].addr,
msgs[i].buf, msgs[i].len,
msgs[i+1].buf, msgs[i+1].len); if (result < 0) {
i = result; goto error;
}
/* * Check if we should interpret the read data * as a length byte. The DS28E17 unfortunately * has no read without stop, so we can just do * another simple read in that case.
*/ if (msgs[i+1].flags & I2C_M_RECV_LEN) {
result = w1_f19_i2c_read(sl, msgs[i+1].addr,
&(msgs[i+1].buf[1]), msgs[i+1].buf[0]); if (result < 0) {
i = result; goto error;
}
}
/* Eat up read message, too. */
i++;
} elseif (msgs[i].flags & I2C_M_RD) { /* Read transfer. */
result = w1_f19_i2c_read(sl, msgs[i].addr,
msgs[i].buf, msgs[i].len); if (result < 0) {
i = result; goto error;
}
/* * Check if we should interpret the read data * as a length byte. The DS28E17 unfortunately * has no read without stop, so we can just do * another simple read in that case.
*/ if (msgs[i].flags & I2C_M_RECV_LEN) {
result = w1_f19_i2c_read(sl,
msgs[i].addr,
&(msgs[i].buf[1]),
msgs[i].buf[0]); if (result < 0) {
i = result; goto error;
}
}
} else { /* * Write transfer. * Stop condition only for last * transfer.
*/
result = w1_f19_i2c_write(sl,
msgs[i].addr,
msgs[i].buf,
msgs[i].len,
i == (num-1)); if (result < 0) {
i = result; goto error;
}
}
/* Next message. */
i++;
/* Are there still messages to send/receive? */ if (i < num) { /* Yes. Resume to same DS28E17. */ if (w1_reset_resume_command(sl->master)) {
i = -EIO; goto error;
}
}
}
error: /* End onewire transaction. */
mutex_unlock(&sl->master->bus_mutex);
/* Return number of messages processed or error. */ return i;
}
/* Get I2C adapter functionality. */ static u32 w1_f19_i2c_functionality(struct i2c_adapter *adapter)
{ /* * Plain I2C functions only. * SMBus is emulated by the kernel's I2C layer. * No "I2C_FUNC_SMBUS_QUICK" * No "I2C_FUNC_SMBUS_READ_BLOCK_DATA" * No "I2C_FUNC_SMBUS_BLOCK_PROC_CALL"
*/ return I2C_FUNC_I2C |
I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA |
I2C_FUNC_SMBUS_PROC_CALL |
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA |
I2C_FUNC_SMBUS_I2C_BLOCK |
I2C_FUNC_SMBUS_PEC;
}
/* Allocate memory for slave specific data. */
data = devm_kzalloc(&sl->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM;
sl->family_data = data;
/* Setup default I2C speed on slave. */ switch (i2c_speed) { case 100:
__w1_f19_set_i2c_speed(sl, 0); break; case 400:
__w1_f19_set_i2c_speed(sl, 1); break; case 900:
__w1_f19_set_i2c_speed(sl, 2); break; default: /* * A i2c_speed module parameter of anything else * than 100, 400, 900 means not to touch the * speed of the DS28E17. * We assume 400kBaud, the power-on value.
*/
data->speed = 1;
}
/* * Setup default busy stretch * configuration for the DS28E17.
*/
data->stretch = i2c_stretch;
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.