Lines Matching +full:i2c +full:- +full:fsi
1 // SPDX-License-Identifier: GPL-2.0+
3 * FSI-attached I2C controller algorithm
18 #include <linux/fsi.h>
19 #include <linux/i2c.h>
32 /* i2c registers */
149 struct fsi_device *fsi; member
163 static int fsi_i2c_read_reg(struct fsi_device *fsi, unsigned int reg, in fsi_i2c_read_reg() argument
169 rc = fsi_device_read(fsi, reg, &data_be, sizeof(data_be)); in fsi_i2c_read_reg()
178 static int fsi_i2c_write_reg(struct fsi_device *fsi, unsigned int reg, in fsi_i2c_write_reg() argument
183 return fsi_device_write(fsi, reg, &data_be, sizeof(data_be)); in fsi_i2c_write_reg()
186 static int fsi_i2c_dev_init(struct fsi_i2c_ctrl *i2c) in fsi_i2c_dev_init() argument
193 rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_INT_MASK, &interrupt); in fsi_i2c_dev_init()
198 rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_MODE, &mode); in fsi_i2c_dev_init()
202 rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_ESTAT, &extended_status); in fsi_i2c_dev_init()
206 i2c->fifo_size = FIELD_GET(I2C_ESTAT_FIFO_SZ, extended_status); in fsi_i2c_dev_init()
208 i2c->fifo_size - I2C_FIFO_HI_LVL); in fsi_i2c_dev_init()
211 return fsi_i2c_write_reg(i2c->fsi, I2C_FSI_WATER_MARK, &watermark); in fsi_i2c_dev_init()
217 struct fsi_device *fsi = port->ctrl->fsi; in fsi_i2c_set_port() local
220 rc = fsi_i2c_read_reg(fsi, I2C_FSI_MODE, &mode); in fsi_i2c_set_port()
224 if (FIELD_GET(I2C_MODE_PORT, mode) == port->port) in fsi_i2c_set_port()
227 mode = (mode & ~I2C_MODE_PORT) | FIELD_PREP(I2C_MODE_PORT, port->port); in fsi_i2c_set_port()
228 rc = fsi_i2c_write_reg(fsi, I2C_FSI_MODE, &mode); in fsi_i2c_set_port()
233 return fsi_i2c_write_reg(fsi, I2C_FSI_RESET_ERR, &dummy); in fsi_i2c_set_port()
239 struct fsi_i2c_ctrl *i2c = port->ctrl; in fsi_i2c_start() local
242 port->xfrd = 0; in fsi_i2c_start()
244 if (msg->flags & I2C_M_RD) in fsi_i2c_start()
247 if (stop || msg->flags & I2C_M_STOP) in fsi_i2c_start()
250 cmd |= FIELD_PREP(I2C_CMD_ADDR, msg->addr); in fsi_i2c_start()
251 cmd |= FIELD_PREP(I2C_CMD_LEN, msg->len); in fsi_i2c_start()
253 return fsi_i2c_write_reg(i2c->fsi, I2C_FSI_CMD, &cmd); in fsi_i2c_start()
258 /* fsi is limited to max 4 byte aligned ops */ in fsi_i2c_get_op_bytes()
271 struct fsi_i2c_ctrl *i2c = port->ctrl; in fsi_i2c_write_fifo() local
272 int bytes_to_write = i2c->fifo_size - fifo_count; in fsi_i2c_write_fifo()
273 int bytes_remaining = msg->len - port->xfrd; in fsi_i2c_write_fifo()
280 rc = fsi_device_write(i2c->fsi, I2C_FSI_FIFO, in fsi_i2c_write_fifo()
281 &msg->buf[port->xfrd], write); in fsi_i2c_write_fifo()
285 port->xfrd += write; in fsi_i2c_write_fifo()
286 bytes_to_write -= write; in fsi_i2c_write_fifo()
297 struct fsi_i2c_ctrl *i2c = port->ctrl; in fsi_i2c_read_fifo() local
299 int xfr_remaining = msg->len - port->xfrd; in fsi_i2c_read_fifo()
308 rc = fsi_device_read(i2c->fsi, I2C_FSI_FIFO, in fsi_i2c_read_fifo()
309 &msg->buf[port->xfrd], read); in fsi_i2c_read_fifo()
313 port->xfrd += read; in fsi_i2c_read_fifo()
314 xfr_remaining -= read; in fsi_i2c_read_fifo()
317 rc = fsi_device_read(i2c->fsi, I2C_FSI_FIFO, &dummy, in fsi_i2c_read_fifo()
323 bytes_to_read -= read; in fsi_i2c_read_fifo()
332 struct fsi_i2c_port *port = adap->algo_data; in fsi_i2c_get_scl()
333 struct fsi_i2c_ctrl *i2c = port->ctrl; in fsi_i2c_get_scl() local
335 fsi_i2c_read_reg(i2c->fsi, I2C_FSI_STAT, &stat); in fsi_i2c_get_scl()
343 struct fsi_i2c_port *port = adap->algo_data; in fsi_i2c_set_scl()
344 struct fsi_i2c_ctrl *i2c = port->ctrl; in fsi_i2c_set_scl() local
347 fsi_i2c_write_reg(i2c->fsi, I2C_FSI_SET_SCL, &dummy); in fsi_i2c_set_scl()
349 fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_SCL, &dummy); in fsi_i2c_set_scl()
355 struct fsi_i2c_port *port = adap->algo_data; in fsi_i2c_get_sda()
356 struct fsi_i2c_ctrl *i2c = port->ctrl; in fsi_i2c_get_sda() local
358 fsi_i2c_read_reg(i2c->fsi, I2C_FSI_STAT, &stat); in fsi_i2c_get_sda()
366 struct fsi_i2c_port *port = adap->algo_data; in fsi_i2c_set_sda()
367 struct fsi_i2c_ctrl *i2c = port->ctrl; in fsi_i2c_set_sda() local
370 fsi_i2c_write_reg(i2c->fsi, I2C_FSI_SET_SDA, &dummy); in fsi_i2c_set_sda()
372 fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_SDA, &dummy); in fsi_i2c_set_sda()
379 struct fsi_i2c_port *port = adap->algo_data; in fsi_i2c_prepare_recovery()
380 struct fsi_i2c_ctrl *i2c = port->ctrl; in fsi_i2c_prepare_recovery() local
382 rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_MODE, &mode); in fsi_i2c_prepare_recovery()
387 fsi_i2c_write_reg(i2c->fsi, I2C_FSI_MODE, &mode); in fsi_i2c_prepare_recovery()
394 struct fsi_i2c_port *port = adap->algo_data; in fsi_i2c_unprepare_recovery()
395 struct fsi_i2c_ctrl *i2c = port->ctrl; in fsi_i2c_unprepare_recovery() local
397 rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_MODE, &mode); in fsi_i2c_unprepare_recovery()
402 fsi_i2c_write_reg(i2c->fsi, I2C_FSI_MODE, &mode); in fsi_i2c_unprepare_recovery()
405 static int fsi_i2c_reset_bus(struct fsi_i2c_ctrl *i2c, in fsi_i2c_reset_bus() argument
412 i2c_recover_bus(&port->adapter); in fsi_i2c_reset_bus()
415 rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_ERR, &dummy); in fsi_i2c_reset_bus()
422 rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_STAT, &stat); in fsi_i2c_reset_bus()
430 rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_I2C, &dummy); in fsi_i2c_reset_bus()
434 /* re-init engine again */ in fsi_i2c_reset_bus()
435 return fsi_i2c_dev_init(i2c); in fsi_i2c_reset_bus()
438 static int fsi_i2c_reset_engine(struct fsi_i2c_ctrl *i2c, u16 port) in fsi_i2c_reset_engine() argument
444 rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_I2C, &dummy); in fsi_i2c_reset_engine()
448 /* re-init engine */ in fsi_i2c_reset_engine()
449 rc = fsi_i2c_dev_init(i2c); in fsi_i2c_reset_engine()
453 rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_MODE, &mode); in fsi_i2c_reset_engine()
461 rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_MODE, &mode); in fsi_i2c_reset_engine()
468 rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_PORT_BUSY, &dummy); in fsi_i2c_reset_engine()
481 struct fsi_i2c_ctrl *i2c = port->ctrl; in fsi_i2c_abort() local
482 struct fsi_device *fsi = i2c->fsi; in fsi_i2c_abort() local
484 rc = fsi_i2c_reset_engine(i2c, port->port); in fsi_i2c_abort()
488 rc = fsi_i2c_read_reg(fsi, I2C_FSI_STAT, &stat); in fsi_i2c_abort()
494 rc = fsi_i2c_reset_bus(i2c, port); in fsi_i2c_abort()
504 rc = fsi_i2c_write_reg(fsi, I2C_FSI_CMD, &cmd); in fsi_i2c_abort()
512 rc = fsi_i2c_read_reg(fsi, I2C_FSI_STAT, &status); in fsi_i2c_abort()
522 return -ETIMEDOUT; in fsi_i2c_abort()
537 return -EINVAL; in fsi_i2c_handle_status()
541 return -EPROTO; in fsi_i2c_handle_status()
544 return -ENXIO; in fsi_i2c_handle_status()
547 return -EAGAIN; in fsi_i2c_handle_status()
550 return -EBADMSG; in fsi_i2c_handle_status()
552 return -EIO; in fsi_i2c_handle_status()
558 if (msg->flags & I2C_M_RD) in fsi_i2c_handle_status()
565 if (port->xfrd < msg->len) in fsi_i2c_handle_status()
566 return -ENODATA; in fsi_i2c_handle_status()
568 return msg->len; in fsi_i2c_handle_status()
582 rc = fsi_i2c_read_reg(port->ctrl->fsi, I2C_FSI_STAT, in fsi_i2c_wait()
593 if (rc == msg->len) in fsi_i2c_wait()
603 return -ETIMEDOUT; in fsi_i2c_wait()
611 struct fsi_i2c_port *port = adap->algo_data; in fsi_i2c_xfer()
612 struct fsi_i2c_ctrl *ctrl = port->ctrl; in fsi_i2c_xfer()
615 mutex_lock(&ctrl->lock); in fsi_i2c_xfer()
625 rc = fsi_i2c_start(port, msg, i == num - 1); in fsi_i2c_xfer()
630 adap->timeout - (jiffies - start_time)); in fsi_i2c_xfer()
636 mutex_unlock(&ctrl->lock); in fsi_i2c_xfer()
661 static struct device_node *fsi_i2c_find_port_of_node(struct device_node *fsi, in fsi_i2c_find_port_of_node() argument
668 for_each_child_of_node(fsi, np) { in fsi_i2c_find_port_of_node()
679 struct fsi_i2c_ctrl *i2c; in fsi_i2c_probe() local
685 i2c = devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL); in fsi_i2c_probe()
686 if (!i2c) in fsi_i2c_probe()
687 return -ENOMEM; in fsi_i2c_probe()
689 mutex_init(&i2c->lock); in fsi_i2c_probe()
690 i2c->fsi = to_fsi_dev(dev); in fsi_i2c_probe()
691 INIT_LIST_HEAD(&i2c->ports); in fsi_i2c_probe()
693 rc = fsi_i2c_dev_init(i2c); in fsi_i2c_probe()
697 rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_STAT, &stat); in fsi_i2c_probe()
702 dev_dbg(dev, "I2C controller has %d ports\n", ports); in fsi_i2c_probe()
705 np = fsi_i2c_find_port_of_node(dev->of_node, port_no); in fsi_i2c_probe()
715 port->ctrl = i2c; in fsi_i2c_probe()
716 port->port = port_no; in fsi_i2c_probe()
718 port->adapter.owner = THIS_MODULE; in fsi_i2c_probe()
719 port->adapter.dev.of_node = np; in fsi_i2c_probe()
720 port->adapter.dev.parent = dev; in fsi_i2c_probe()
721 port->adapter.algo = &fsi_i2c_algorithm; in fsi_i2c_probe()
722 port->adapter.bus_recovery_info = &fsi_i2c_bus_recovery_info; in fsi_i2c_probe()
723 port->adapter.algo_data = port; in fsi_i2c_probe()
725 snprintf(port->adapter.name, sizeof(port->adapter.name), in fsi_i2c_probe()
726 "i2c_bus-%u", port_no); in fsi_i2c_probe()
728 rc = i2c_add_adapter(&port->adapter); in fsi_i2c_probe()
735 list_add(&port->list, &i2c->ports); in fsi_i2c_probe()
738 dev_set_drvdata(dev, i2c); in fsi_i2c_probe()
745 struct fsi_i2c_ctrl *i2c = dev_get_drvdata(dev); in fsi_i2c_remove() local
748 list_for_each_entry_safe(port, tmp, &i2c->ports, list) { in fsi_i2c_remove()
749 list_del(&port->list); in fsi_i2c_remove()
750 i2c_del_adapter(&port->adapter); in fsi_i2c_remove()
765 .name = "i2c-fsi",
775 MODULE_DESCRIPTION("FSI attached I2C controller");