[PATCH linux dev-4.10] i2c: aspeed: Reset to upstream version

Andrew Jeffery andrew at aj.id.au
Wed Jul 26 18:05:52 AEST 2017


On Tue, 2017-07-25 at 16:24 +0930, Joel Stanley wrote:
> This sets the i2c device driver to the same state as the one that was
> included in the 4.13 merge window.
> 
> By doing this we get fixes that happened in the latter stages of upstream
> review.
> 
> Signed-off-by: Joel Stanley <joel at jms.id.au>

Tested-by: Andrew Jeffery <andrew at aj.id.au>

> ---
> Instead of doing the revert and then cherry pick, this sets the tree to the
> same state as the upstream driver.
> 
>  drivers/i2c/busses/i2c-aspeed.c     | 233 ++++++++++++++++++------------------
>  drivers/irqchip/irq-aspeed-i2c-ic.c |  31 +++--
>  2 files changed, 139 insertions(+), 125 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
> index ee1f546fec05..f19348328a71 100644
> --- a/drivers/i2c/busses/i2c-aspeed.c
> +++ b/drivers/i2c/busses/i2c-aspeed.c
> @@ -78,11 +78,6 @@
> >  #define ASPEED_I2CD_INTR_RX_DONE			BIT(2)
> >  #define ASPEED_I2CD_INTR_TX_NAK				BIT(1)
> >  #define ASPEED_I2CD_INTR_TX_ACK				BIT(0)
> > -#define ASPEED_I2CD_INTR_ERROR						       \
> > > -		(ASPEED_I2CD_INTR_ARBIT_LOSS |				       \
> > > -		 ASPEED_I2CD_INTR_ABNORMAL |				       \
> > > -		 ASPEED_I2CD_INTR_SCL_TIMEOUT |				       \
> > -		 ASPEED_I2CD_INTR_SDA_DL_TIMEOUT)
> >  #define ASPEED_I2CD_INTR_ALL						       \
> > >  		(ASPEED_I2CD_INTR_SDA_DL_TIMEOUT |			       \
> > >  		 ASPEED_I2CD_INTR_BUS_RECOVER_DONE |			       \
> @@ -137,7 +132,8 @@ struct aspeed_i2c_bus {
> >  	/* Synchronizes I/O mem access to base. */
> > >  	spinlock_t			lock;
> > >  	struct completion		cmd_complete;
> > > -	int				irq;
> > > +	unsigned long			parent_clk_frequency;
> > > +	u32				bus_frequency;
> >  	/* Transaction state. */
> > >  	enum aspeed_i2c_master_state	master_state;
> > >  	struct i2c_msg			*msgs;
> @@ -146,6 +142,8 @@ struct aspeed_i2c_bus {
> > >  	size_t				msgs_count;
> > >  	bool				send_stop;
> > >  	int				cmd_err;
> > +	/* Protected only by i2c_lock_bus */
> > > +	int				master_xfer_result;
>  #if IS_ENABLED(CONFIG_I2C_SLAVE)
> > >  	struct i2c_client		*slave;
> > >  	enum aspeed_i2c_slave_state	slave_state;
> @@ -167,7 +165,7 @@ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
> >  		/* Bus is idle: no recovery needed. */
> >  		if (command & ASPEED_I2CD_SCL_LINE_STS)
> >  			goto out;
> > -		dev_dbg(bus->dev, "bus hung (state %x), attempting recovery\n",
> > +		dev_dbg(bus->dev, "SCL hung (state %x), attempting recovery\n",
> >  			command);
>  
> >  		reinit_completion(&bus->cmd_complete);
> @@ -185,13 +183,14 @@ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
> >  		/* Recovery failed. */
> >  		else if (!(readl(bus->base + ASPEED_I2C_CMD_REG) &
> >  			   ASPEED_I2CD_SCL_LINE_STS))
> > -			ret = -EIO;
> > +			goto reset_out;
> >  	/* Bus error. */
> >  	} else {
> > -		dev_dbg(bus->dev, "bus hung (state %x), attempting recovery\n",
> > +		dev_dbg(bus->dev, "SDA hung (state %x), attempting recovery\n",
> >  			command);
>  
> >  		reinit_completion(&bus->cmd_complete);
> > +		/* Writes 1 to 8 SCL clock cycles until SDA is released. */
> >  		writel(ASPEED_I2CD_BUS_RECOVER_CMD,
> >  		       bus->base + ASPEED_I2C_CMD_REG);
> >  		spin_unlock_irqrestore(&bus->lock, flags);
> @@ -207,7 +206,7 @@ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
> >  		/* Recovery failed. */
> >  		else if (!(readl(bus->base + ASPEED_I2C_CMD_REG) &
> >  			   ASPEED_I2CD_SDA_LINE_STS))
> > -			ret = -EIO;
> > +			goto reset_out;
> >  	}
>  
>  out:
> @@ -325,7 +324,8 @@ static bool aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus)
>  }
>  #endif /* CONFIG_I2C_SLAVE */
>  
> -static void __aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)
> +/* precondition: bus.lock has been acquired. */
> +static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)
>  {
> >  	u32 command = ASPEED_I2CD_M_START_CMD | ASPEED_I2CD_M_TX_CMD;
> >  	struct i2c_msg *msg = &bus->msgs[bus->msgs_index];
> @@ -346,30 +346,47 @@ static void __aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)
> >  	writel(command, bus->base + ASPEED_I2C_CMD_REG);
>  }
>  
> -static void __aspeed_i2c_do_stop(struct aspeed_i2c_bus *bus)
> +/* precondition: bus.lock has been acquired. */
> +static void aspeed_i2c_do_stop(struct aspeed_i2c_bus *bus)
>  {
> >  	bus->master_state = ASPEED_I2C_MASTER_STOP;
> >  	writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG);
>  }
>  
> -static void __aspeed_i2c_next_msg_or_stop(struct aspeed_i2c_bus *bus)
> +/* precondition: bus.lock has been acquired. */
> +static void aspeed_i2c_next_msg_or_stop(struct aspeed_i2c_bus *bus)
>  {
> >  	if (bus->msgs_index + 1 < bus->msgs_count) {
> >  		bus->msgs_index++;
> > -		__aspeed_i2c_do_start(bus);
> > +		aspeed_i2c_do_start(bus);
> >  	} else {
> > -		__aspeed_i2c_do_stop(bus);
> > +		aspeed_i2c_do_stop(bus);
> >  	}
>  }
>  
> +static int aspeed_i2c_is_irq_error(u32 irq_status)
> +{
> > +	if (irq_status & ASPEED_I2CD_INTR_ARBIT_LOSS)
> > +		return -EAGAIN;
> > +	if (irq_status & (ASPEED_I2CD_INTR_SDA_DL_TIMEOUT |
> > +			  ASPEED_I2CD_INTR_SCL_TIMEOUT))
> > +		return -EBUSY;
> > +	if (irq_status & (ASPEED_I2CD_INTR_ABNORMAL))
> > +		return -EPROTO;
> +
> > +	return 0;
> +}
> +
>  static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
>  {
> >  	u32 irq_status, status_ack = 0, command = 0;
> >  	struct i2c_msg *msg;
> >  	u8 recv_byte;
> > +	int ret;
>  
> >  	spin_lock(&bus->lock);
> >  	irq_status = readl(bus->base + ASPEED_I2C_INTR_STS_REG);
> > +	/* Ack all interrupt bits. */
> >  	writel(irq_status, bus->base + ASPEED_I2C_INTR_STS_REG);
>  
> >  	if (irq_status & ASPEED_I2CD_INTR_BUS_RECOVER_DONE) {
> @@ -379,15 +396,24 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
> >  	}
>  
> >  	/*
> > -	 * Either we encountered an interrupt that reports an error, or we are
> > -	 * in an invalid state.
> > +	 * We encountered an interrupt that reports an error: the hardware
> > +	 * should clear the command queue effectively taking us back to the
> > +	 * INACTIVE state.
> >  	 */
> > -	if (irq_status & ASPEED_I2CD_INTR_ERROR ||
> > -	    (!bus->msgs && bus->master_state != ASPEED_I2C_MASTER_STOP)) {
> > +	ret = aspeed_i2c_is_irq_error(irq_status);
> > +	if (ret < 0) {
> >  		dev_dbg(bus->dev, "received error interrupt: 0x%08x",
> >  			irq_status);
> > +		bus->cmd_err = ret;
> > +		bus->master_state = ASPEED_I2C_MASTER_INACTIVE;
> > +		goto out_complete;
> > +	}
> +
> > +	/* We are in an invalid state; reset bus to a known state. */
> > +	if (!bus->msgs && bus->master_state != ASPEED_I2C_MASTER_STOP) {
> > +		dev_err(bus->dev, "bus in unknown state");
> >  		bus->cmd_err = -EIO;
> > -		__aspeed_i2c_do_stop(bus);
> > +		aspeed_i2c_do_stop(bus);
> >  		goto out_no_complete;
> >  	}
> >  	msg = &bus->msgs[bus->msgs_index];
> @@ -399,12 +425,17 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
> >  	 */
> >  	if (bus->master_state == ASPEED_I2C_MASTER_START) {
> >  		if (unlikely(!(irq_status & ASPEED_I2CD_INTR_TX_ACK))) {
> > -			dev_dbg(bus->dev,
> > -				"no slave present at %02x", msg->addr);
> > +			pr_devel("no slave present at %02x", msg->addr);
> >  			status_ack |= ASPEED_I2CD_INTR_TX_NAK;
> > -			goto error_and_stop;
> > +			bus->cmd_err = -ENXIO;
> > +			aspeed_i2c_do_stop(bus);
> > +			goto out_no_complete;
> >  		}
> >  		status_ack |= ASPEED_I2CD_INTR_TX_ACK;
> > +		if (msg->len == 0) { /* SMBUS_QUICK */
> > +			aspeed_i2c_do_stop(bus);
> > +			goto out_no_complete;
> > +		}
> >  		if (msg->flags & I2C_M_RD)
> >  			bus->master_state = ASPEED_I2C_MASTER_RX_FIRST;
> >  		else
> @@ -431,7 +462,7 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
> >  			writel(ASPEED_I2CD_M_TX_CMD,
> >  			       bus->base + ASPEED_I2C_CMD_REG);
> >  		} else {
> > -			__aspeed_i2c_next_msg_or_stop(bus);
> > +			aspeed_i2c_next_msg_or_stop(bus);
> >  		}
> >  		goto out_no_complete;
> >  	case ASPEED_I2C_MASTER_RX_FIRST:
> @@ -452,7 +483,7 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
> >  		if (msg->flags & I2C_M_RECV_LEN) {
> >  			if (unlikely(recv_byte > I2C_SMBUS_BLOCK_MAX)) {
> >  				bus->cmd_err = -EPROTO;
> > -				__aspeed_i2c_do_stop(bus);
> > +				aspeed_i2c_do_stop(bus);
> >  				goto out_no_complete;
> >  			}
> >  			msg->len = recv_byte +
> @@ -467,7 +498,7 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
> >  				command |= ASPEED_I2CD_M_S_RX_CMD_LAST;
> >  			writel(command, bus->base + ASPEED_I2C_CMD_REG);
> >  		} else {
> > -			__aspeed_i2c_next_msg_or_stop(bus);
> > +			aspeed_i2c_next_msg_or_stop(bus);
> >  		}
> >  		goto out_no_complete;
> >  	case ASPEED_I2C_MASTER_STOP:
> @@ -491,14 +522,19 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
> >  	default:
> >  		WARN(1, "unknown master state\n");
> >  		bus->master_state = ASPEED_I2C_MASTER_INACTIVE;
> > -		bus->cmd_err = -EIO;
> > +		bus->cmd_err = -EINVAL;
> >  		goto out_complete;
> >  	}
>  error_and_stop:
> >  	bus->cmd_err = -EIO;
> > -	__aspeed_i2c_do_stop(bus);
> > +	aspeed_i2c_do_stop(bus);
> >  	goto out_no_complete;
>  out_complete:
> > +	bus->msgs = NULL;
> > +	if (bus->cmd_err)
> > +		bus->master_xfer_result = bus->cmd_err;
> > +	else
> > +		bus->master_xfer_result = bus->msgs_index + 1;
> >  	complete(&bus->cmd_complete);
>  out_no_complete:
> >  	if (irq_status != status_ack)
> @@ -520,16 +556,13 @@ static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id)
> >  	}
>  #endif /* CONFIG_I2C_SLAVE */
>  
> > -	if (aspeed_i2c_master_irq(bus))
> > -		return IRQ_HANDLED;
> > -	else
> > -		return IRQ_NONE;
> > +	return aspeed_i2c_master_irq(bus) ? IRQ_HANDLED : IRQ_NONE;
>  }
>  
>  static int aspeed_i2c_master_xfer(struct i2c_adapter *adap,
> >  				  struct i2c_msg *msgs, int num)
>  {
> > -	struct aspeed_i2c_bus *bus = adap->algo_data;
> > +	struct aspeed_i2c_bus *bus = i2c_get_adapdata(adap);
> >  	unsigned long time_left, flags;
> >  	int ret = 0;
>  
> @@ -547,30 +580,22 @@ static int aspeed_i2c_master_xfer(struct i2c_adapter *adap,
> >  		spin_lock_irqsave(&bus->lock, flags);
> >  	}
>  
> > +	bus->cmd_err = 0;
> >  	bus->msgs = msgs;
> >  	bus->msgs_index = 0;
> >  	bus->msgs_count = num;
>  
> >  	reinit_completion(&bus->cmd_complete);
> > -	__aspeed_i2c_do_start(bus);
> > +	aspeed_i2c_do_start(bus);
> >  	spin_unlock_irqrestore(&bus->lock, flags);
>  
> >  	time_left = wait_for_completion_timeout(&bus->cmd_complete,
> >  						bus->adap.timeout);
>  
> > -	spin_lock_irqsave(&bus->lock, flags);
> > -	bus->msgs = NULL;
> >  	if (time_left == 0)
> > -		ret = -ETIMEDOUT;
> > -	else
> > -		ret = bus->cmd_err;
> > -	spin_unlock_irqrestore(&bus->lock, flags);
> -
> > -	/* If nothing went wrong, return number of messages transferred. */
> > -	if (ret >= 0)
> > -		return bus->msgs_index + 1;
> > +		return -ETIMEDOUT;
> >  	else
> > -		return ret;
> > +		return bus->master_xfer_result;
>  }
>  
>  static u32 aspeed_i2c_functionality(struct i2c_adapter *adap)
> @@ -579,6 +604,7 @@ static u32 aspeed_i2c_functionality(struct i2c_adapter *adap)
>  }
>  
>  #if IS_ENABLED(CONFIG_I2C_SLAVE)
> +/* precondition: bus.lock has been acquired. */
>  static void __aspeed_i2c_reg_slave(struct aspeed_i2c_bus *bus, u16 slave_addr)
>  {
> >  	u32 addr_reg_val, func_ctrl_reg_val;
> @@ -597,10 +623,9 @@ static void __aspeed_i2c_reg_slave(struct aspeed_i2c_bus *bus, u16 slave_addr)
>  
>  static int aspeed_i2c_reg_slave(struct i2c_client *client)
>  {
> > -	struct aspeed_i2c_bus *bus;
> > +	struct aspeed_i2c_bus *bus = i2c_get_adapdata(client->adapter);
> >  	unsigned long flags;
>  
> > -	bus = client->adapter->algo_data;
> >  	spin_lock_irqsave(&bus->lock, flags);
> >  	if (bus->slave) {
> >  		spin_unlock_irqrestore(&bus->lock, flags);
> @@ -618,7 +643,7 @@ static int aspeed_i2c_reg_slave(struct i2c_client *client)
>  
>  static int aspeed_i2c_unreg_slave(struct i2c_client *client)
>  {
> > -	struct aspeed_i2c_bus *bus = client->adapter->algo_data;
> > +	struct aspeed_i2c_bus *bus = i2c_get_adapdata(client->adapter);
> >  	u32 func_ctrl_reg_val;
> >  	unsigned long flags;
>  
> @@ -687,71 +712,38 @@ static u32 aspeed_i2c_get_clk_reg_val(u32 divisor)
> >  			| (base_clk & ASPEED_I2CD_TIME_BASE_DIVISOR_MASK);
>  }
>  
> -static int __aspeed_i2c_init_clk(struct aspeed_i2c_bus *bus,
> > -				 struct platform_device *pdev)
> +/* precondition: bus.lock has been acquired. */
> +static int aspeed_i2c_init_clk(struct aspeed_i2c_bus *bus)
>  {
> > -	u32 clk_freq, divisor, clk_reg_val;
> > -	struct clk *pclk;
> > -	int ret;
> -
> > -	pclk = devm_clk_get(&pdev->dev, NULL);
> > -	if (IS_ERR(pclk)) {
> > -		dev_err(&pdev->dev, "clk_get failed\n");
> > -		return PTR_ERR(pclk);
> > -	}
> > -	ret = of_property_read_u32(pdev->dev.of_node,
> > -				   "bus-frequency", &clk_freq);
> > -	if (ret < 0) {
> > -		dev_err(&pdev->dev,
> > -			"Could not read bus-frequency property\n");
> > -		clk_freq = 100000;
> > -	}
> > -	divisor = clk_get_rate(pclk) / clk_freq;
> > -	/* We just need the clock rate, we don't actually use the clk object. */
> > -	devm_clk_put(&pdev->dev, pclk);
> > +	u32 divisor, clk_reg_val;
>  
> > +	divisor = bus->parent_clk_frequency / bus->bus_frequency;
> >  	clk_reg_val = aspeed_i2c_get_clk_reg_val(divisor);
> >  	writel(clk_reg_val, bus->base + ASPEED_I2C_AC_TIMING_REG1);
> -
> > -	/*
> > -	 * If the base divisor is non-zero then we do not want to enable high
> > -	 * speed mode, otherwise we might as well enable it.
> > -	 * For reference, setting high speed mode will make the base divisor
> > -	 * zero and corresponds to a minimum SCL frequency of about 1.5MHz.
> > -	 */
> > -	if (clk_reg_val & ASPEED_I2CD_TIME_BASE_DIVISOR_MASK) {
> > -		writel(ASPEED_NO_TIMEOUT_CTRL,
> > -		       bus->base + ASPEED_I2C_AC_TIMING_REG2);
> > -	} else {
> > -		writel(readl(bus->base + ASPEED_I2C_FUN_CTRL_REG) |
> > -		       ASPEED_I2CD_M_HIGH_SPEED_EN |
> > -		       ASPEED_I2CD_M_SDA_DRIVE_1T_EN |
> > -		       ASPEED_I2CD_SDA_DRIVE_1T_EN,
> > -		       bus->base + ASPEED_I2C_FUN_CTRL_REG);
> -
> > -		writel(0x3, bus->base + ASPEED_I2C_AC_TIMING_REG2);
> > -	}
> > +	writel(ASPEED_NO_TIMEOUT_CTRL, bus->base + ASPEED_I2C_AC_TIMING_REG2);
>  
> >  	return 0;
>  }
>  
> -static int __aspeed_i2c_init(struct aspeed_i2c_bus *bus,
> +/* precondition: bus.lock has been acquired. */
> +static int aspeed_i2c_init(struct aspeed_i2c_bus *bus,
> >  			     struct platform_device *pdev)
>  {
> > +	u32 fun_ctrl_reg = ASPEED_I2CD_MASTER_EN;
> >  	int ret;
>  
> >  	/* Disable everything. */
> >  	writel(0, bus->base + ASPEED_I2C_FUN_CTRL_REG);
>  
> > -	ret = __aspeed_i2c_init_clk(bus, pdev);
> > +	ret = aspeed_i2c_init_clk(bus);
> >  	if (ret < 0)
> >  		return ret;
>  
> > +	if (!of_property_read_bool(pdev->dev.of_node, "multi-master"))
> > +		fun_ctrl_reg |= ASPEED_I2CD_MULTI_MASTER_DIS;
> +
> >  	/* Enable Master Mode */
> > -	writel(readl(bus->base + ASPEED_I2C_FUN_CTRL_REG) |
> > -	       ASPEED_I2CD_MASTER_EN |
> > -	       /* TODO: provide device tree option for multi-master mode. */
> > -	       ASPEED_I2CD_MULTI_MASTER_DIS,
> > +	writel(readl(bus->base + ASPEED_I2C_FUN_CTRL_REG) | fun_ctrl_reg,
> >  	       bus->base + ASPEED_I2C_FUN_CTRL_REG);
>  
>  #if IS_ENABLED(CONFIG_I2C_SLAVE)
> @@ -774,20 +766,11 @@ static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus)
>  
> >  	spin_lock_irqsave(&bus->lock, flags);
>  
> > -	/* Disable and quiesce interrupts. */
> > -	reinit_completion(&bus->cmd_complete);
> > +	/* Disable and ack all interrupts. */
> >  	writel(0, bus->base + ASPEED_I2C_INTR_CTRL_REG);
> > +	writel(0xffffffff, bus->base + ASPEED_I2C_INTR_STS_REG);
>  
> > -	spin_unlock_irqrestore(&bus->lock, flags);
> > -	/*
> > -	 * We need to make sure that there are no interrupts that fired just
> > -	 * before we grabbed the lock; if that did not happen, then we are going
> > -	 * to timeout and that is okay.
> > -	 */
> > -	wait_for_completion_timeout(&bus->cmd_complete, bus->adap.timeout);
> > -	spin_lock_irqsave(&bus->lock, flags);
> -
> > -	ret = __aspeed_i2c_init(bus, pdev);
> > +	ret = aspeed_i2c_init(bus, pdev);
>  
> >  	spin_unlock_irqrestore(&bus->lock, flags);
>  
> @@ -797,8 +780,9 @@ static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus)
>  static int aspeed_i2c_probe_bus(struct platform_device *pdev)
>  {
> >  	struct aspeed_i2c_bus *bus;
> > +	struct clk *parent_clk;
> >  	struct resource *res;
> > -	int ret;
> > +	int irq, ret;
>  
> >  	bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
> >  	if (!bus)
> @@ -809,6 +793,21 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
> >  	if (IS_ERR(bus->base))
> >  		return PTR_ERR(bus->base);
>  
> > +	parent_clk = devm_clk_get(&pdev->dev, NULL);
> > +	if (IS_ERR(parent_clk))
> > +		return PTR_ERR(parent_clk);
> > +	bus->parent_clk_frequency = clk_get_rate(parent_clk);
> > +	/* We just need the clock rate, we don't actually use the clk object. */
> > +	devm_clk_put(&pdev->dev, parent_clk);
> +
> > +	ret = of_property_read_u32(pdev->dev.of_node,
> > +				   "bus-frequency", &bus->bus_frequency);
> > +	if (ret < 0) {
> > +		dev_err(&pdev->dev,
> > +			"Could not read bus-frequency property\n");
> > +		bus->bus_frequency = 100000;
> > +	}
> +
> >  	/* Initialize the I2C adapter */
> >  	spin_lock_init(&bus->lock);
> >  	init_completion(&bus->cmd_complete);
> @@ -816,24 +815,26 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
> >  	bus->adap.retries = 0;
> >  	bus->adap.timeout = 5 * HZ;
> >  	bus->adap.algo = &aspeed_i2c_algo;
> > -	bus->adap.algo_data = bus;
> >  	bus->adap.dev.parent = &pdev->dev;
> >  	bus->adap.dev.of_node = pdev->dev.of_node;
> > -	snprintf(bus->adap.name, sizeof(bus->adap.name), "Aspeed i2c");
> > +	strlcpy(bus->adap.name, pdev->name, sizeof(bus->adap.name));
> > +	i2c_set_adapdata(&bus->adap, bus);
>  
> >  	bus->dev = &pdev->dev;
>  
> > +	/* Clean up any left over interrupt state. */
> > +	writel(0, bus->base + ASPEED_I2C_INTR_CTRL_REG);
> > +	writel(0xffffffff, bus->base + ASPEED_I2C_INTR_STS_REG);
> >  	/*
> > -	 * No need to quiesce interrupts because there is no interrupt handler
> > -	 * installed.
> > +	 * bus.lock does not need to be held because the interrupt handler has
> > +	 * not been enabled yet.
> >  	 */
> > -	writel(0, bus->base + ASPEED_I2C_INTR_CTRL_REG);
> > -	ret = __aspeed_i2c_init(bus, pdev);
> > +	ret = aspeed_i2c_init(bus, pdev);
> >  	if (ret < 0)
> >  		return ret;
>  
> > -	bus->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
> > -	ret = devm_request_irq(&pdev->dev, bus->irq, aspeed_i2c_bus_irq,
> > +	irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
> > +	ret = devm_request_irq(&pdev->dev, irq, aspeed_i2c_bus_irq,
> >  			       0, dev_name(&pdev->dev), bus);
> >  	if (ret < 0)
> >  		return ret;
> @@ -845,7 +846,7 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
> >  	platform_set_drvdata(pdev, bus);
>  
> >  	dev_info(bus->dev, "i2c bus %d registered, irq %d\n",
> > -		 bus->adap.nr, bus->irq);
> > +		 bus->adap.nr, irq);
>  
> >  	return 0;
>  }
> diff --git a/drivers/irqchip/irq-aspeed-i2c-ic.c b/drivers/irqchip/irq-aspeed-i2c-ic.c
> index a36fb09c10c2..815b88dd18f2 100644
> --- a/drivers/irqchip/irq-aspeed-i2c-ic.c
> +++ b/drivers/irqchip/irq-aspeed-i2c-ic.c
> @@ -69,24 +69,31 @@ static int __init aspeed_i2c_ic_of_init(struct device_node *node,
> >  					struct device_node *parent)
>  {
> >  	struct aspeed_i2c_ic *i2c_ic;
> > +	int ret = 0;
>  
> >  	i2c_ic = kzalloc(sizeof(*i2c_ic), GFP_KERNEL);
> >  	if (!i2c_ic)
> >  		return -ENOMEM;
>  
> >  	i2c_ic->base = of_iomap(node, 0);
> > -	if (IS_ERR(i2c_ic->base))
> > -		return PTR_ERR(i2c_ic->base);
> > +	if (IS_ERR(i2c_ic->base)) {
> > +		ret = PTR_ERR(i2c_ic->base);
> > +		goto err_free_ic;
> > +	}
>  
> >  	i2c_ic->parent_irq = irq_of_parse_and_map(node, 0);
> > -	if (i2c_ic->parent_irq < 0)
> > -		return i2c_ic->parent_irq;
> > +	if (i2c_ic->parent_irq < 0) {
> > +		ret = i2c_ic->parent_irq;
> > +		goto err_iounmap;
> > +	}
>  
> > -	i2c_ic->irq_domain = irq_domain_add_linear(
> > -			node, ASPEED_I2C_IC_NUM_BUS,
> > -			&aspeed_i2c_ic_irq_domain_ops, NULL);
> > -	if (!i2c_ic->irq_domain)
> > -		return -ENOMEM;
> > +	i2c_ic->irq_domain = irq_domain_add_linear(node, ASPEED_I2C_IC_NUM_BUS,
> > +						   &aspeed_i2c_ic_irq_domain_ops,
> > +						   NULL);
> > +	if (!i2c_ic->irq_domain) {
> > +		ret = -ENOMEM;
> > +		goto err_iounmap;
> > +	}
>  
> >  	i2c_ic->irq_domain->name = "aspeed-i2c-domain";
>  
> @@ -96,6 +103,12 @@ static int __init aspeed_i2c_ic_of_init(struct device_node *node,
> >  	pr_info("i2c controller registered, irq %d\n", i2c_ic->parent_irq);
>  
> >  	return 0;
> +
> +err_iounmap:
> > +	iounmap(i2c_ic->base);
> +err_free_ic:
> > +	kfree(i2c_ic);
> > +	return ret;
>  }
>  
>  IRQCHIP_DECLARE(ast2400_i2c_ic, "aspeed,ast2400-i2c-ic", aspeed_i2c_ic_of_init);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: This is a digitally signed message part
URL: <http://lists.ozlabs.org/pipermail/openbmc/attachments/20170726/a5976ca5/attachment.sig>


More information about the openbmc mailing list