| // SPDX-License-Identifier: GPL-2.0+ | 
 | /* | 
 |  * FSI-attached I2C master algorithm | 
 |  * | 
 |  * Copyright 2018 IBM Corporation | 
 |  * | 
 |  * This program is free software; you can redistribute it and/or | 
 |  * modify it under the terms of the GNU General Public License | 
 |  * as published by the Free Software Foundation; either version | 
 |  * 2 of the License, or (at your option) any later version. | 
 |  */ | 
 |  | 
 | #include <linux/bitfield.h> | 
 | #include <linux/bitops.h> | 
 | #include <linux/delay.h> | 
 | #include <linux/device.h> | 
 | #include <linux/errno.h> | 
 | #include <linux/fsi.h> | 
 | #include <linux/i2c.h> | 
 | #include <linux/jiffies.h> | 
 | #include <linux/kernel.h> | 
 | #include <linux/list.h> | 
 | #include <linux/module.h> | 
 | #include <linux/mutex.h> | 
 | #include <linux/of.h> | 
 | #include <linux/slab.h> | 
 |  | 
 | #define FSI_ENGID_I2C		0x7 | 
 |  | 
 | #define I2C_DEFAULT_CLK_DIV	6 | 
 |  | 
 | /* i2c registers */ | 
 | #define I2C_FSI_FIFO		0x00 | 
 | #define I2C_FSI_CMD		0x04 | 
 | #define I2C_FSI_MODE		0x08 | 
 | #define I2C_FSI_WATER_MARK	0x0C | 
 | #define I2C_FSI_INT_MASK	0x10 | 
 | #define I2C_FSI_INT_COND	0x14 | 
 | #define I2C_FSI_OR_INT_MASK	0x14 | 
 | #define I2C_FSI_INTS		0x18 | 
 | #define I2C_FSI_AND_INT_MASK	0x18 | 
 | #define I2C_FSI_STAT		0x1C | 
 | #define I2C_FSI_RESET_I2C	0x1C | 
 | #define I2C_FSI_ESTAT		0x20 | 
 | #define I2C_FSI_RESET_ERR	0x20 | 
 | #define I2C_FSI_RESID_LEN	0x24 | 
 | #define I2C_FSI_SET_SCL		0x24 | 
 | #define I2C_FSI_PORT_BUSY	0x28 | 
 | #define I2C_FSI_RESET_SCL	0x2C | 
 | #define I2C_FSI_SET_SDA		0x30 | 
 | #define I2C_FSI_RESET_SDA	0x34 | 
 |  | 
 | /* cmd register */ | 
 | #define I2C_CMD_WITH_START	BIT(31) | 
 | #define I2C_CMD_WITH_ADDR	BIT(30) | 
 | #define I2C_CMD_RD_CONT		BIT(29) | 
 | #define I2C_CMD_WITH_STOP	BIT(28) | 
 | #define I2C_CMD_FORCELAUNCH	BIT(27) | 
 | #define I2C_CMD_ADDR		GENMASK(23, 17) | 
 | #define I2C_CMD_READ		BIT(16) | 
 | #define I2C_CMD_LEN		GENMASK(15, 0) | 
 |  | 
 | /* mode register */ | 
 | #define I2C_MODE_CLKDIV		GENMASK(31, 16) | 
 | #define I2C_MODE_PORT		GENMASK(15, 10) | 
 | #define I2C_MODE_ENHANCED	BIT(3) | 
 | #define I2C_MODE_DIAG		BIT(2) | 
 | #define I2C_MODE_PACE_ALLOW	BIT(1) | 
 | #define I2C_MODE_WRAP		BIT(0) | 
 |  | 
 | /* watermark register */ | 
 | #define I2C_WATERMARK_HI	GENMASK(15, 12) | 
 | #define I2C_WATERMARK_LO	GENMASK(7, 4) | 
 |  | 
 | #define I2C_FIFO_HI_LVL		4 | 
 | #define I2C_FIFO_LO_LVL		4 | 
 |  | 
 | /* interrupt register */ | 
 | #define I2C_INT_INV_CMD		BIT(15) | 
 | #define I2C_INT_PARITY		BIT(14) | 
 | #define I2C_INT_BE_OVERRUN	BIT(13) | 
 | #define I2C_INT_BE_ACCESS	BIT(12) | 
 | #define I2C_INT_LOST_ARB	BIT(11) | 
 | #define I2C_INT_NACK		BIT(10) | 
 | #define I2C_INT_DAT_REQ		BIT(9) | 
 | #define I2C_INT_CMD_COMP	BIT(8) | 
 | #define I2C_INT_STOP_ERR	BIT(7) | 
 | #define I2C_INT_BUSY		BIT(6) | 
 | #define I2C_INT_IDLE		BIT(5) | 
 |  | 
 | /* status register */ | 
 | #define I2C_STAT_INV_CMD	BIT(31) | 
 | #define I2C_STAT_PARITY		BIT(30) | 
 | #define I2C_STAT_BE_OVERRUN	BIT(29) | 
 | #define I2C_STAT_BE_ACCESS	BIT(28) | 
 | #define I2C_STAT_LOST_ARB	BIT(27) | 
 | #define I2C_STAT_NACK		BIT(26) | 
 | #define I2C_STAT_DAT_REQ	BIT(25) | 
 | #define I2C_STAT_CMD_COMP	BIT(24) | 
 | #define I2C_STAT_STOP_ERR	BIT(23) | 
 | #define I2C_STAT_MAX_PORT	GENMASK(19, 16) | 
 | #define I2C_STAT_ANY_INT	BIT(15) | 
 | #define I2C_STAT_SCL_IN		BIT(11) | 
 | #define I2C_STAT_SDA_IN		BIT(10) | 
 | #define I2C_STAT_PORT_BUSY	BIT(9) | 
 | #define I2C_STAT_SELF_BUSY	BIT(8) | 
 | #define I2C_STAT_FIFO_COUNT	GENMASK(7, 0) | 
 |  | 
 | #define I2C_STAT_ERR		(I2C_STAT_INV_CMD |			\ | 
 | 				 I2C_STAT_PARITY |			\ | 
 | 				 I2C_STAT_BE_OVERRUN |			\ | 
 | 				 I2C_STAT_BE_ACCESS |			\ | 
 | 				 I2C_STAT_LOST_ARB |			\ | 
 | 				 I2C_STAT_NACK |			\ | 
 | 				 I2C_STAT_STOP_ERR) | 
 | #define I2C_STAT_ANY_RESP	(I2C_STAT_ERR |				\ | 
 | 				 I2C_STAT_DAT_REQ |			\ | 
 | 				 I2C_STAT_CMD_COMP) | 
 |  | 
 | /* extended status register */ | 
 | #define I2C_ESTAT_FIFO_SZ	GENMASK(31, 24) | 
 | #define I2C_ESTAT_SCL_IN_SY	BIT(15) | 
 | #define I2C_ESTAT_SDA_IN_SY	BIT(14) | 
 | #define I2C_ESTAT_S_SCL		BIT(13) | 
 | #define I2C_ESTAT_S_SDA		BIT(12) | 
 | #define I2C_ESTAT_M_SCL		BIT(11) | 
 | #define I2C_ESTAT_M_SDA		BIT(10) | 
 | #define I2C_ESTAT_HI_WATER	BIT(9) | 
 | #define I2C_ESTAT_LO_WATER	BIT(8) | 
 | #define I2C_ESTAT_PORT_BUSY	BIT(7) | 
 | #define I2C_ESTAT_SELF_BUSY	BIT(6) | 
 | #define I2C_ESTAT_VERSION	GENMASK(4, 0) | 
 |  | 
 | /* port busy register */ | 
 | #define I2C_PORT_BUSY_RESET	BIT(31) | 
 |  | 
 | /* wait for command complete or data request */ | 
 | #define I2C_CMD_SLEEP_MAX_US	500 | 
 | #define I2C_CMD_SLEEP_MIN_US	50 | 
 |  | 
 | /* wait after reset; choose time from legacy driver */ | 
 | #define I2C_RESET_SLEEP_MAX_US	2000 | 
 | #define I2C_RESET_SLEEP_MIN_US	1000 | 
 |  | 
 | /* choose timeout length from legacy driver; it's well tested */ | 
 | #define I2C_ABORT_TIMEOUT	msecs_to_jiffies(100) | 
 |  | 
 | struct fsi_i2c_master { | 
 | 	struct fsi_device	*fsi; | 
 | 	u8			fifo_size; | 
 | 	struct list_head	ports; | 
 | 	struct mutex		lock; | 
 | }; | 
 |  | 
 | struct fsi_i2c_port { | 
 | 	struct list_head	list; | 
 | 	struct i2c_adapter	adapter; | 
 | 	struct fsi_i2c_master	*master; | 
 | 	u16			port; | 
 | 	u16			xfrd; | 
 | }; | 
 |  | 
 | static int fsi_i2c_read_reg(struct fsi_device *fsi, unsigned int reg, | 
 | 			    u32 *data) | 
 | { | 
 | 	int rc; | 
 | 	__be32 data_be; | 
 |  | 
 | 	rc = fsi_device_read(fsi, reg, &data_be, sizeof(data_be)); | 
 | 	if (rc) | 
 | 		return rc; | 
 |  | 
 | 	*data = be32_to_cpu(data_be); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int fsi_i2c_write_reg(struct fsi_device *fsi, unsigned int reg, | 
 | 			     u32 *data) | 
 | { | 
 | 	__be32 data_be = cpu_to_be32p(data); | 
 |  | 
 | 	return fsi_device_write(fsi, reg, &data_be, sizeof(data_be)); | 
 | } | 
 |  | 
 | static int fsi_i2c_dev_init(struct fsi_i2c_master *i2c) | 
 | { | 
 | 	int rc; | 
 | 	u32 mode = I2C_MODE_ENHANCED, extended_status, watermark; | 
 | 	u32 interrupt = 0; | 
 |  | 
 | 	/* since we use polling, disable interrupts */ | 
 | 	rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_INT_MASK, &interrupt); | 
 | 	if (rc) | 
 | 		return rc; | 
 |  | 
 | 	mode |= FIELD_PREP(I2C_MODE_CLKDIV, I2C_DEFAULT_CLK_DIV); | 
 | 	rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_MODE, &mode); | 
 | 	if (rc) | 
 | 		return rc; | 
 |  | 
 | 	rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_ESTAT, &extended_status); | 
 | 	if (rc) | 
 | 		return rc; | 
 |  | 
 | 	i2c->fifo_size = FIELD_GET(I2C_ESTAT_FIFO_SZ, extended_status); | 
 | 	watermark = FIELD_PREP(I2C_WATERMARK_HI, | 
 | 			       i2c->fifo_size - I2C_FIFO_HI_LVL); | 
 | 	watermark |= FIELD_PREP(I2C_WATERMARK_LO, I2C_FIFO_LO_LVL); | 
 |  | 
 | 	return fsi_i2c_write_reg(i2c->fsi, I2C_FSI_WATER_MARK, &watermark); | 
 | } | 
 |  | 
 | static int fsi_i2c_set_port(struct fsi_i2c_port *port) | 
 | { | 
 | 	int rc; | 
 | 	struct fsi_device *fsi = port->master->fsi; | 
 | 	u32 mode, dummy = 0; | 
 |  | 
 | 	rc = fsi_i2c_read_reg(fsi, I2C_FSI_MODE, &mode); | 
 | 	if (rc) | 
 | 		return rc; | 
 |  | 
 | 	if (FIELD_GET(I2C_MODE_PORT, mode) == port->port) | 
 | 		return 0; | 
 |  | 
 | 	mode = (mode & ~I2C_MODE_PORT) | FIELD_PREP(I2C_MODE_PORT, port->port); | 
 | 	rc = fsi_i2c_write_reg(fsi, I2C_FSI_MODE, &mode); | 
 | 	if (rc) | 
 | 		return rc; | 
 |  | 
 | 	/* reset engine when port is changed */ | 
 | 	return fsi_i2c_write_reg(fsi, I2C_FSI_RESET_ERR, &dummy); | 
 | } | 
 |  | 
 | static int fsi_i2c_start(struct fsi_i2c_port *port, struct i2c_msg *msg, | 
 | 			 bool stop) | 
 | { | 
 | 	struct fsi_i2c_master *i2c = port->master; | 
 | 	u32 cmd = I2C_CMD_WITH_START | I2C_CMD_WITH_ADDR; | 
 |  | 
 | 	port->xfrd = 0; | 
 |  | 
 | 	if (msg->flags & I2C_M_RD) | 
 | 		cmd |= I2C_CMD_READ; | 
 |  | 
 | 	if (stop || msg->flags & I2C_M_STOP) | 
 | 		cmd |= I2C_CMD_WITH_STOP; | 
 |  | 
 | 	cmd |= FIELD_PREP(I2C_CMD_ADDR, msg->addr); | 
 | 	cmd |= FIELD_PREP(I2C_CMD_LEN, msg->len); | 
 |  | 
 | 	return fsi_i2c_write_reg(i2c->fsi, I2C_FSI_CMD, &cmd); | 
 | } | 
 |  | 
 | static int fsi_i2c_get_op_bytes(int op_bytes) | 
 | { | 
 | 	/* fsi is limited to max 4 byte aligned ops */ | 
 | 	if (op_bytes > 4) | 
 | 		return 4; | 
 | 	else if (op_bytes == 3) | 
 | 		return 2; | 
 | 	return op_bytes; | 
 | } | 
 |  | 
 | static int fsi_i2c_write_fifo(struct fsi_i2c_port *port, struct i2c_msg *msg, | 
 | 			      u8 fifo_count) | 
 | { | 
 | 	int write; | 
 | 	int rc; | 
 | 	struct fsi_i2c_master *i2c = port->master; | 
 | 	int bytes_to_write = i2c->fifo_size - fifo_count; | 
 | 	int bytes_remaining = msg->len - port->xfrd; | 
 |  | 
 | 	bytes_to_write = min(bytes_to_write, bytes_remaining); | 
 |  | 
 | 	while (bytes_to_write) { | 
 | 		write = fsi_i2c_get_op_bytes(bytes_to_write); | 
 |  | 
 | 		rc = fsi_device_write(i2c->fsi, I2C_FSI_FIFO, | 
 | 				      &msg->buf[port->xfrd], write); | 
 | 		if (rc) | 
 | 			return rc; | 
 |  | 
 | 		port->xfrd += write; | 
 | 		bytes_to_write -= write; | 
 | 	} | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int fsi_i2c_read_fifo(struct fsi_i2c_port *port, struct i2c_msg *msg, | 
 | 			     u8 fifo_count) | 
 | { | 
 | 	int read; | 
 | 	int rc; | 
 | 	struct fsi_i2c_master *i2c = port->master; | 
 | 	int bytes_to_read; | 
 | 	int xfr_remaining = msg->len - port->xfrd; | 
 | 	u32 dummy; | 
 |  | 
 | 	bytes_to_read = min_t(int, fifo_count, xfr_remaining); | 
 |  | 
 | 	while (bytes_to_read) { | 
 | 		read = fsi_i2c_get_op_bytes(bytes_to_read); | 
 |  | 
 | 		if (xfr_remaining) { | 
 | 			rc = fsi_device_read(i2c->fsi, I2C_FSI_FIFO, | 
 | 					     &msg->buf[port->xfrd], read); | 
 | 			if (rc) | 
 | 				return rc; | 
 |  | 
 | 			port->xfrd += read; | 
 | 			xfr_remaining -= read; | 
 | 		} else { | 
 | 			/* no more buffer but data in fifo, need to clear it */ | 
 | 			rc = fsi_device_read(i2c->fsi, I2C_FSI_FIFO, &dummy, | 
 | 					     read); | 
 | 			if (rc) | 
 | 				return rc; | 
 | 		} | 
 |  | 
 | 		bytes_to_read -= read; | 
 | 	} | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int fsi_i2c_get_scl(struct i2c_adapter *adap) | 
 | { | 
 | 	u32 stat = 0; | 
 | 	struct fsi_i2c_port *port = adap->algo_data; | 
 | 	struct fsi_i2c_master *i2c = port->master; | 
 |  | 
 | 	fsi_i2c_read_reg(i2c->fsi, I2C_FSI_STAT, &stat); | 
 |  | 
 | 	return !!(stat & I2C_STAT_SCL_IN); | 
 | } | 
 |  | 
 | static void fsi_i2c_set_scl(struct i2c_adapter *adap, int val) | 
 | { | 
 | 	u32 dummy = 0; | 
 | 	struct fsi_i2c_port *port = adap->algo_data; | 
 | 	struct fsi_i2c_master *i2c = port->master; | 
 |  | 
 | 	if (val) | 
 | 		fsi_i2c_write_reg(i2c->fsi, I2C_FSI_SET_SCL, &dummy); | 
 | 	else | 
 | 		fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_SCL, &dummy); | 
 | } | 
 |  | 
 | static int fsi_i2c_get_sda(struct i2c_adapter *adap) | 
 | { | 
 | 	u32 stat = 0; | 
 | 	struct fsi_i2c_port *port = adap->algo_data; | 
 | 	struct fsi_i2c_master *i2c = port->master; | 
 |  | 
 | 	fsi_i2c_read_reg(i2c->fsi, I2C_FSI_STAT, &stat); | 
 |  | 
 | 	return !!(stat & I2C_STAT_SDA_IN); | 
 | } | 
 |  | 
 | static void fsi_i2c_set_sda(struct i2c_adapter *adap, int val) | 
 | { | 
 | 	u32 dummy = 0; | 
 | 	struct fsi_i2c_port *port = adap->algo_data; | 
 | 	struct fsi_i2c_master *i2c = port->master; | 
 |  | 
 | 	if (val) | 
 | 		fsi_i2c_write_reg(i2c->fsi, I2C_FSI_SET_SDA, &dummy); | 
 | 	else | 
 | 		fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_SDA, &dummy); | 
 | } | 
 |  | 
 | static void fsi_i2c_prepare_recovery(struct i2c_adapter *adap) | 
 | { | 
 | 	int rc; | 
 | 	u32 mode; | 
 | 	struct fsi_i2c_port *port = adap->algo_data; | 
 | 	struct fsi_i2c_master *i2c = port->master; | 
 |  | 
 | 	rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_MODE, &mode); | 
 | 	if (rc) | 
 | 		return; | 
 |  | 
 | 	mode |= I2C_MODE_DIAG; | 
 | 	fsi_i2c_write_reg(i2c->fsi, I2C_FSI_MODE, &mode); | 
 | } | 
 |  | 
 | static void fsi_i2c_unprepare_recovery(struct i2c_adapter *adap) | 
 | { | 
 | 	int rc; | 
 | 	u32 mode; | 
 | 	struct fsi_i2c_port *port = adap->algo_data; | 
 | 	struct fsi_i2c_master *i2c = port->master; | 
 |  | 
 | 	rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_MODE, &mode); | 
 | 	if (rc) | 
 | 		return; | 
 |  | 
 | 	mode &= ~I2C_MODE_DIAG; | 
 | 	fsi_i2c_write_reg(i2c->fsi, I2C_FSI_MODE, &mode); | 
 | } | 
 |  | 
 | static int fsi_i2c_reset_bus(struct fsi_i2c_master *i2c, | 
 | 			     struct fsi_i2c_port *port) | 
 | { | 
 | 	int rc; | 
 | 	u32 stat, dummy = 0; | 
 |  | 
 | 	/* force bus reset, ignore errors */ | 
 | 	i2c_recover_bus(&port->adapter); | 
 |  | 
 | 	/* reset errors */ | 
 | 	rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_ERR, &dummy); | 
 | 	if (rc) | 
 | 		return rc; | 
 |  | 
 | 	/* wait for command complete */ | 
 | 	usleep_range(I2C_RESET_SLEEP_MIN_US, I2C_RESET_SLEEP_MAX_US); | 
 |  | 
 | 	rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_STAT, &stat); | 
 | 	if (rc) | 
 | 		return rc; | 
 |  | 
 | 	if (stat & I2C_STAT_CMD_COMP) | 
 | 		return 0; | 
 |  | 
 | 	/* failed to get command complete; reset engine again */ | 
 | 	rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_I2C, &dummy); | 
 | 	if (rc) | 
 | 		return rc; | 
 |  | 
 | 	/* re-init engine again */ | 
 | 	return fsi_i2c_dev_init(i2c); | 
 | } | 
 |  | 
 | static int fsi_i2c_reset_engine(struct fsi_i2c_master *i2c, u16 port) | 
 | { | 
 | 	int rc; | 
 | 	u32 mode, dummy = 0; | 
 |  | 
 | 	/* reset engine */ | 
 | 	rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_I2C, &dummy); | 
 | 	if (rc) | 
 | 		return rc; | 
 |  | 
 | 	/* re-init engine */ | 
 | 	rc = fsi_i2c_dev_init(i2c); | 
 | 	if (rc) | 
 | 		return rc; | 
 |  | 
 | 	rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_MODE, &mode); | 
 | 	if (rc) | 
 | 		return rc; | 
 |  | 
 | 	/* set port; default after reset is 0 */ | 
 | 	if (port) { | 
 | 		mode &= ~I2C_MODE_PORT; | 
 | 		mode |= FIELD_PREP(I2C_MODE_PORT, port); | 
 | 		rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_MODE, &mode); | 
 | 		if (rc) | 
 | 			return rc; | 
 | 	} | 
 |  | 
 | 	/* reset busy register; hw workaround */ | 
 | 	dummy = I2C_PORT_BUSY_RESET; | 
 | 	rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_PORT_BUSY, &dummy); | 
 | 	if (rc) | 
 | 		return rc; | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int fsi_i2c_abort(struct fsi_i2c_port *port, u32 status) | 
 | { | 
 | 	int rc; | 
 | 	unsigned long start; | 
 | 	u32 cmd = I2C_CMD_WITH_STOP; | 
 | 	u32 stat; | 
 | 	struct fsi_i2c_master *i2c = port->master; | 
 | 	struct fsi_device *fsi = i2c->fsi; | 
 |  | 
 | 	rc = fsi_i2c_reset_engine(i2c, port->port); | 
 | 	if (rc) | 
 | 		return rc; | 
 |  | 
 | 	rc = fsi_i2c_read_reg(fsi, I2C_FSI_STAT, &stat); | 
 | 	if (rc) | 
 | 		return rc; | 
 |  | 
 | 	/* if sda is low, peform full bus reset */ | 
 | 	if (!(stat & I2C_STAT_SDA_IN)) { | 
 | 		rc = fsi_i2c_reset_bus(i2c, port); | 
 | 		if (rc) | 
 | 			return rc; | 
 | 	} | 
 |  | 
 | 	/* skip final stop command for these errors */ | 
 | 	if (status & (I2C_STAT_PARITY | I2C_STAT_LOST_ARB | I2C_STAT_STOP_ERR)) | 
 | 		return 0; | 
 |  | 
 | 	/* write stop command */ | 
 | 	rc = fsi_i2c_write_reg(fsi, I2C_FSI_CMD, &cmd); | 
 | 	if (rc) | 
 | 		return rc; | 
 |  | 
 | 	/* wait until we see command complete in the master */ | 
 | 	start = jiffies; | 
 |  | 
 | 	do { | 
 | 		rc = fsi_i2c_read_reg(fsi, I2C_FSI_STAT, &status); | 
 | 		if (rc) | 
 | 			return rc; | 
 |  | 
 | 		if (status & I2C_STAT_CMD_COMP) | 
 | 			return 0; | 
 |  | 
 | 		usleep_range(I2C_CMD_SLEEP_MIN_US, I2C_CMD_SLEEP_MAX_US); | 
 | 	} while (time_after(start + I2C_ABORT_TIMEOUT, jiffies)); | 
 |  | 
 | 	return -ETIMEDOUT; | 
 | } | 
 |  | 
 | static int fsi_i2c_handle_status(struct fsi_i2c_port *port, | 
 | 				 struct i2c_msg *msg, u32 status) | 
 | { | 
 | 	int rc; | 
 | 	u8 fifo_count; | 
 |  | 
 | 	if (status & I2C_STAT_ERR) { | 
 | 		rc = fsi_i2c_abort(port, status); | 
 | 		if (rc) | 
 | 			return rc; | 
 |  | 
 | 		if (status & I2C_STAT_INV_CMD) | 
 | 			return -EINVAL; | 
 |  | 
 | 		if (status & (I2C_STAT_PARITY | I2C_STAT_BE_OVERRUN | | 
 | 		    I2C_STAT_BE_ACCESS)) | 
 | 			return -EPROTO; | 
 |  | 
 | 		if (status & I2C_STAT_NACK) | 
 | 			return -ENXIO; | 
 |  | 
 | 		if (status & I2C_STAT_LOST_ARB) | 
 | 			return -EAGAIN; | 
 |  | 
 | 		if (status & I2C_STAT_STOP_ERR) | 
 | 			return -EBADMSG; | 
 |  | 
 | 		return -EIO; | 
 | 	} | 
 |  | 
 | 	if (status & I2C_STAT_DAT_REQ) { | 
 | 		fifo_count = FIELD_GET(I2C_STAT_FIFO_COUNT, status); | 
 |  | 
 | 		if (msg->flags & I2C_M_RD) | 
 | 			return fsi_i2c_read_fifo(port, msg, fifo_count); | 
 |  | 
 | 		return fsi_i2c_write_fifo(port, msg, fifo_count); | 
 | 	} | 
 |  | 
 | 	if (status & I2C_STAT_CMD_COMP) { | 
 | 		if (port->xfrd < msg->len) | 
 | 			return -ENODATA; | 
 |  | 
 | 		return msg->len; | 
 | 	} | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int fsi_i2c_wait(struct fsi_i2c_port *port, struct i2c_msg *msg, | 
 | 			unsigned long timeout) | 
 | { | 
 | 	u32 status = 0; | 
 | 	int rc; | 
 | 	unsigned long start = jiffies; | 
 |  | 
 | 	do { | 
 | 		rc = fsi_i2c_read_reg(port->master->fsi, I2C_FSI_STAT, | 
 | 				      &status); | 
 | 		if (rc) | 
 | 			return rc; | 
 |  | 
 | 		if (status & I2C_STAT_ANY_RESP) { | 
 | 			rc = fsi_i2c_handle_status(port, msg, status); | 
 | 			if (rc < 0) | 
 | 				return rc; | 
 |  | 
 | 			/* cmd complete and all data xfrd */ | 
 | 			if (rc == msg->len) | 
 | 				return 0; | 
 |  | 
 | 			/* need to xfr more data, but maybe don't need wait */ | 
 | 			continue; | 
 | 		} | 
 |  | 
 | 		usleep_range(I2C_CMD_SLEEP_MIN_US, I2C_CMD_SLEEP_MAX_US); | 
 | 	} while (time_after(start + timeout, jiffies)); | 
 |  | 
 | 	return -ETIMEDOUT; | 
 | } | 
 |  | 
 | static int fsi_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, | 
 | 			int num) | 
 | { | 
 | 	int i, rc; | 
 | 	unsigned long start_time; | 
 | 	struct fsi_i2c_port *port = adap->algo_data; | 
 | 	struct fsi_i2c_master *master = port->master; | 
 | 	struct i2c_msg *msg; | 
 |  | 
 | 	mutex_lock(&master->lock); | 
 |  | 
 | 	rc = fsi_i2c_set_port(port); | 
 | 	if (rc) | 
 | 		goto unlock; | 
 |  | 
 | 	for (i = 0; i < num; i++) { | 
 | 		msg = msgs + i; | 
 | 		start_time = jiffies; | 
 |  | 
 | 		rc = fsi_i2c_start(port, msg, i == num - 1); | 
 | 		if (rc) | 
 | 			goto unlock; | 
 |  | 
 | 		rc = fsi_i2c_wait(port, msg, | 
 | 				  adap->timeout - (jiffies - start_time)); | 
 | 		if (rc) | 
 | 			goto unlock; | 
 | 	} | 
 |  | 
 | unlock: | 
 | 	mutex_unlock(&master->lock); | 
 | 	return rc ? : num; | 
 | } | 
 |  | 
 | static u32 fsi_i2c_functionality(struct i2c_adapter *adap) | 
 | { | 
 | 	return I2C_FUNC_I2C | I2C_FUNC_PROTOCOL_MANGLING | | 
 | 		I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_BLOCK_DATA; | 
 | } | 
 |  | 
 | static struct i2c_bus_recovery_info fsi_i2c_bus_recovery_info = { | 
 | 	.recover_bus = i2c_generic_scl_recovery, | 
 | 	.get_scl = fsi_i2c_get_scl, | 
 | 	.set_scl = fsi_i2c_set_scl, | 
 | 	.get_sda = fsi_i2c_get_sda, | 
 | 	.set_sda = fsi_i2c_set_sda, | 
 | 	.prepare_recovery = fsi_i2c_prepare_recovery, | 
 | 	.unprepare_recovery = fsi_i2c_unprepare_recovery, | 
 | }; | 
 |  | 
 | static const struct i2c_algorithm fsi_i2c_algorithm = { | 
 | 	.master_xfer = fsi_i2c_xfer, | 
 | 	.functionality = fsi_i2c_functionality, | 
 | }; | 
 |  | 
 | static int fsi_i2c_probe(struct device *dev) | 
 | { | 
 | 	struct fsi_i2c_master *i2c; | 
 | 	struct fsi_i2c_port *port; | 
 | 	struct device_node *np; | 
 | 	int rc; | 
 | 	u32 port_no; | 
 |  | 
 | 	i2c = devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL); | 
 | 	if (!i2c) | 
 | 		return -ENOMEM; | 
 |  | 
 | 	mutex_init(&i2c->lock); | 
 | 	i2c->fsi = to_fsi_dev(dev); | 
 | 	INIT_LIST_HEAD(&i2c->ports); | 
 |  | 
 | 	rc = fsi_i2c_dev_init(i2c); | 
 | 	if (rc) | 
 | 		return rc; | 
 |  | 
 | 	/* Add adapter for each i2c port of the master. */ | 
 | 	for_each_available_child_of_node(dev->of_node, np) { | 
 | 		rc = of_property_read_u32(np, "reg", &port_no); | 
 | 		if (rc || port_no > USHRT_MAX) | 
 | 			continue; | 
 |  | 
 | 		port = kzalloc(sizeof(*port), GFP_KERNEL); | 
 | 		if (!port) | 
 | 			break; | 
 |  | 
 | 		port->master = i2c; | 
 | 		port->port = port_no; | 
 |  | 
 | 		port->adapter.owner = THIS_MODULE; | 
 | 		port->adapter.dev.of_node = np; | 
 | 		port->adapter.dev.parent = dev; | 
 | 		port->adapter.algo = &fsi_i2c_algorithm; | 
 | 		port->adapter.bus_recovery_info = &fsi_i2c_bus_recovery_info; | 
 | 		port->adapter.algo_data = port; | 
 |  | 
 | 		snprintf(port->adapter.name, sizeof(port->adapter.name), | 
 | 			 "i2c_bus-%u", port_no); | 
 |  | 
 | 		rc = i2c_add_adapter(&port->adapter); | 
 | 		if (rc < 0) { | 
 | 			dev_err(dev, "Failed to register adapter: %d\n", rc); | 
 | 			kfree(port); | 
 | 			continue; | 
 | 		} | 
 |  | 
 | 		list_add(&port->list, &i2c->ports); | 
 | 	} | 
 |  | 
 | 	dev_set_drvdata(dev, i2c); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int fsi_i2c_remove(struct device *dev) | 
 | { | 
 | 	struct fsi_i2c_master *i2c = dev_get_drvdata(dev); | 
 | 	struct fsi_i2c_port *port, *tmp; | 
 |  | 
 | 	list_for_each_entry_safe(port, tmp, &i2c->ports, list) { | 
 | 		list_del(&port->list); | 
 | 		i2c_del_adapter(&port->adapter); | 
 | 		kfree(port); | 
 | 	} | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static const struct fsi_device_id fsi_i2c_ids[] = { | 
 | 	{ FSI_ENGID_I2C, FSI_VERSION_ANY }, | 
 | 	{ } | 
 | }; | 
 |  | 
 | static struct fsi_driver fsi_i2c_driver = { | 
 | 	.id_table = fsi_i2c_ids, | 
 | 	.drv = { | 
 | 		.name = "i2c-fsi", | 
 | 		.bus = &fsi_bus_type, | 
 | 		.probe = fsi_i2c_probe, | 
 | 		.remove = fsi_i2c_remove, | 
 | 	}, | 
 | }; | 
 |  | 
 | module_fsi_driver(fsi_i2c_driver); | 
 |  | 
 | MODULE_AUTHOR("Eddie James <eajames@us.ibm.com>"); | 
 | MODULE_DESCRIPTION("FSI attached I2C master"); | 
 | MODULE_LICENSE("GPL"); |