/** * struct meson_i2c - Meson I2C device private data * * @adap: I2C adapter instance * @dev: Pointer to device structure * @regs: Base address of the device memory mapped registers * @clk: Pointer to clock structure * @msg: Pointer to the current I2C message * @state: Current state in the driver state machine * @last: Flag set for the last message in the transfer * @count: Number of bytes to be sent/received in current transfer * @pos: Current position in the send/receive buffer * @error: Flag set when an error is received * @lock: To avoid race conditions between irq handler and xfer code * @done: Completion used to wait for transfer termination * @tokens: Sequence of tokens to be written to the device * @num_tokens: Number of tokens * @data: Pointer to the controller's platform data
*/ struct meson_i2c { struct i2c_adapter adap; struct device *dev; void __iomem *regs; struct clk *clk;
struct i2c_msg *msg; int state; bool last; int count; int pos; int error;
spinlock_t lock; struct completion done;
u32 tokens[2]; int num_tokens;
/* According to I2C-BUS Spec 2.1, in FAST-MODE, the minimum LOW period is 1.3uS, and * minimum HIGH is least 0.6us. * For 400000 freq, the period is 2.5us. To keep within the specs, give 40% of period to * HIGH and 60% to LOW. This means HIGH at 1.0us and LOW 1.5us. * The same applies for Fast-mode plus, where LOW is 0.5us and HIGH is 0.26us. * Duty = H/(H + L) = 2/5
*/ if (freq <= I2C_MAX_STANDARD_MODE_FREQ) {
div_h = DIV_ROUND_UP(clk_rate, freq);
div_l = DIV_ROUND_UP(div_h, 4);
div_h = DIV_ROUND_UP(div_h, 2) - FILTER_DELAY;
} else {
div_h = DIV_ROUND_UP(clk_rate * 2, freq * 5) - FILTER_DELAY;
div_l = DIV_ROUND_UP(clk_rate * 3, freq * 5 * 2);
}
/* clock divider has 12 bits */ if (div_h > GENMASK(11, 0)) {
dev_err(i2c->dev, "requested bus frequency too low\n");
div_h = GENMASK(11, 0);
} if (div_l > GENMASK(11, 0)) {
dev_err(i2c->dev, "requested bus frequency too low\n");
div_l = GENMASK(11, 0);
}
staticvoid meson_i2c_transfer_complete(struct meson_i2c *i2c, u32 ctrl)
{ if (ctrl & REG_CTRL_ERROR) { /* * The bit is set when the IGNORE_NAK bit is cleared * and the device didn't respond. In this case, the * I2C controller automatically generates a STOP * condition.
*/
dev_dbg(i2c->dev, "error bit set\n");
i2c->error = -ENXIO;
i2c->state = STATE_IDLE;
} else { if (i2c->state == STATE_READ && i2c->count)
meson_i2c_get_data(i2c, i2c->msg->buf + i2c->pos,
i2c->count);
i2c->pos += i2c->count;
if (i2c->pos >= i2c->msg->len)
i2c->state = STATE_IDLE;
}
}
/* * Protect access to i2c struct and registers from interrupt * handlers triggered by a transfer terminated after the * timeout period
*/
spin_lock_irqsave(&i2c->lock, flags);
if (atomic && !ret)
meson_i2c_transfer_complete(i2c, ctrl);
/* Abort any active operation */
meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, 0);
if (ret)
i2c->state = STATE_IDLE;
if (i2c->error)
ret = i2c->error;
spin_unlock_irqrestore(&i2c->lock, flags);
return ret;
}
staticint meson_i2c_xfer_messages(struct i2c_adapter *adap, struct i2c_msg *msgs, int num, bool atomic)
{ struct meson_i2c *i2c = adap->algo_data; int i, ret = 0;
for (i = 0; i < num; i++) {
ret = meson_i2c_xfer_msg(i2c, msgs + i, i == num - 1, atomic); if (ret) break;
}
/* * A transfer is triggered when START bit changes from 0 to 1. * Ensure that the bit is set to 0 after probe
*/
meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, 0);
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.