Re: [PATCH v4 2/5] i2c: designware: Master mode as separated driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, 2016-12-07 at 17:55 +0000, Luis Oliveira wrote:
> - The functions related to I2C master mode of operation were moved
>   to a single file: i2c-designware-master.c
> - Common functions were moved into i2c-designware-common.c
> - Common definitions were moved into i2c-designware-core.h (were in
> core.c)
> 

Yeah, there are some places that might be cleaned up but it came from
the original and could be done in the future.

Acked-by: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx>

> Signed-off-by: Luis Oliveira <lolivei@xxxxxxxxxxxx>
> ---
> Changes V3->V4: (Andy Shevchenko)
> - The name of the i2c-designware-src.c was changed to i2c-designware-
> common.c
>   as suggested by Andy.
> 
>  drivers/i2c/busses/Makefile                        |   1 +
>  drivers/i2c/busses/i2c-designware-common.c         | 252
> +++++++++++++++
>  drivers/i2c/busses/i2c-designware-core.h           | 131 ++++++++
>  ...c-designware-core.c => i2c-designware-master.c} | 347 +-----------
> ---------
>  4 files changed, 390 insertions(+), 341 deletions(-)
>  create mode 100644 drivers/i2c/busses/i2c-designware-common.c
>  rename drivers/i2c/busses/{i2c-designware-core.c => i2c-designware-
> master.c} (66%)
> 
> diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
> index 1c1bac87a9db..4f8f6a2b9346 100644
> --- a/drivers/i2c/busses/Makefile
> +++ b/drivers/i2c/busses/Makefile
> @@ -40,6 +40,7 @@ obj-$(CONFIG_I2C_CBUS_GPIO)	+= i2c-cbus-
> gpio.o
>  obj-$(CONFIG_I2C_CPM)		+= i2c-cpm.o
>  obj-$(CONFIG_I2C_DAVINCI)	+= i2c-davinci.o
>  obj-$(CONFIG_I2C_DESIGNWARE_CORE)	+= i2c-designware-core.o
> +i2c-designware-core-objs := i2c-designware-common.o i2c-designware-
> master.o
>  obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM)	+= i2c-designware-
> platform.o
>  i2c-designware-platform-objs := i2c-designware-platdrv.o
>  i2c-designware-platform-$(CONFIG_I2C_DESIGNWARE_BAYTRAIL) += i2c-
> designware-baytrail.o
> diff --git a/drivers/i2c/busses/i2c-designware-common.c
> b/drivers/i2c/busses/i2c-designware-common.c
> new file mode 100644
> index 000000000000..6afd2ff5d73f
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-designware-common.c
> @@ -0,0 +1,252 @@
> +/*
> + * Synopsys DesignWare I2C adapter driver (master only).
> + *
> + * Based on the TI DAVINCI I2C adapter driver.
> + *
> + * Copyright (C) 2006 Texas Instruments.
> + * Copyright (C) 2007 MontaVista Software Inc.
> + * Copyright (C) 2009 Provigent Ltd.
> + *
> + * ------------------------------------------------------------------
> ----------
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + * ------------------------------------------------------------------
> ----------
> + *
> + */
> +#include <linux/export.h>
> +#include <linux/errno.h>
> +#include <linux/err.h>
> +#include <linux/i2c.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/delay.h>
> +#include <linux/module.h>
> +#include "i2c-designware-core.h"
> +
> +static char *abort_sources[] = {
> +	[ABRT_7B_ADDR_NOACK] =
> +		"slave address not acknowledged (7bit mode)",
> +	[ABRT_10ADDR1_NOACK] =
> +		"first address byte not acknowledged (10bit mode)",
> +	[ABRT_10ADDR2_NOACK] =
> +		"second address byte not acknowledged (10bit mode)",
> +	[ABRT_TXDATA_NOACK] =
> +		"data not acknowledged",
> +	[ABRT_GCALL_NOACK] =
> +		"no acknowledgement for a general call",
> +	[ABRT_GCALL_READ] =
> +		"read after general call",
> +	[ABRT_SBYTE_ACKDET] =
> +		"start byte acknowledged",
> +	[ABRT_SBYTE_NORSTRT] =
> +		"trying to send start byte when restart is disabled",
> +	[ABRT_10B_RD_NORSTRT] =
> +		"trying to read when restart is disabled (10bit
> mode)",
> +	[ABRT_MASTER_DIS] =
> +		"trying to use disabled adapter",
> +	[ARB_LOST] =
> +		"lost arbitration",
> +};
> +
> +u32 dw_readl(struct dw_i2c_dev *dev, int offset)
> +{
> +	u32 value;
> +
> +	if (dev->accessor_flags & ACCESS_16BIT)
> +		value = readw_relaxed(dev->base + offset) |
> +			(readw_relaxed(dev->base + offset + 2) <<
> 16);
> +	else
> +		value = readl_relaxed(dev->base + offset);
> +
> +	if (dev->accessor_flags & ACCESS_SWAP)
> +		return swab32(value);
> +	else
> +		return value;
> +}
> +
> +void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
> +{
> +	if (dev->accessor_flags & ACCESS_SWAP)
> +		b = swab32(b);
> +
> +	if (dev->accessor_flags & ACCESS_16BIT) {
> +		writew_relaxed((u16)b, dev->base + offset);
> +		writew_relaxed((u16)(b >> 16), dev->base + offset +
> 2);
> +	} else {
> +		writel_relaxed(b, dev->base + offset);
> +	}
> +}
> +
> +u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int
> offset)
> +{
> +	/*
> +	 * DesignWare I2C core doesn't seem to have solid strategy to
> meet
> +	 * the tHD;STA timing spec.  Configuring _HCNT based on tHIGH
> spec
> +	 * will result in violation of the tHD;STA spec.
> +	 */
> +	if (cond)
> +		/*
> +		 * Conditional expression:
> +		 *
> +		 *   IC_[FS]S_SCL_HCNT + (1+4+3) >= IC_CLK * tHIGH
> +		 *
> +		 * This is based on the DW manuals, and represents an
> ideal
> +		 * configuration.  The resulting I2C bus speed will
> be
> +		 * faster than any of the others.
> +		 *
> +		 * If your hardware is free from tHD;STA issue, try
> this one.
> +		 */
> +		return (ic_clk * tSYMBOL + 500000) / 1000000 - 8 +
> offset;
> +	else
> +		/*
> +		 * Conditional expression:
> +		 *
> +		 *   IC_[FS]S_SCL_HCNT + 3 >= IC_CLK * (tHD;STA + tf)
> +		 *
> +		 * This is just experimental rule; the tHD;STA period
> turned
> +		 * out to be proportinal to (_HCNT + 3).  With this
> setting,
> +		 * we could meet both tHIGH and tHD;STA timing specs.
> +		 *
> +		 * If unsure, you'd better to take this alternative.
> +		 *
> +		 * The reason why we need to take into account "tf"
> here,
> +		 * is the same as described in i2c_dw_scl_lcnt().
> +		 */
> +		return (ic_clk * (tSYMBOL + tf) + 500000) / 1000000
> +			- 3 + offset;
> +}
> +
> +u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
> +{
> +	/*
> +	 * Conditional expression:
> +	 *
> +	 *   IC_[FS]S_SCL_LCNT + 1 >= IC_CLK * (tLOW + tf)
> +	 *
> +	 * DW I2C core starts counting the SCL CNTs for the LOW
> period
> +	 * of the SCL clock (tLOW) as soon as it pulls the SCL line.
> +	 * In order to meet the tLOW timing spec, we need to take
> into
> +	 * account the fall time of SCL signal (tf).  Default tf
> value
> +	 * should be 0.3 us, for safety.
> +	 */
> +	return ((ic_clk * (tLOW + tf) + 500000) / 1000000) - 1 +
> offset;
> +}
> +
> +void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable)
> +{
> +	dw_writel(dev, enable, DW_IC_ENABLE);
> +}
> +
> +void __i2c_dw_enable_and_wait(struct dw_i2c_dev *dev, bool enable)
> +{
> +	int timeout = 100;
> +
> +	do {
> +		__i2c_dw_enable(dev, enable);
> +		if ((dw_readl(dev, DW_IC_ENABLE_STATUS) & 1) ==
> enable)
> +			return;
> +
> +		/*
> +		 * Wait 10 times the signaling period of the highest
> I2C
> +		 * transfer supported by the driver (for 400KHz this
> is
> +		 * 25us) as described in the DesignWare I2C databook.
> +		 */
> +		usleep_range(25, 250);
> +	} while (timeout--);
> +
> +	dev_warn(dev->dev, "timeout in %sabling adapter\n",
> +		 enable ? "en" : "dis");
> +}
> +
> +unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev)
> +{
> +	/*
> +	 * Clock is not necessary if we got LCNT/HCNT values directly
> from
> +	 * the platform code.
> +	 */
> +	if (WARN_ON_ONCE(!dev->get_clk_rate_khz))
> +		return 0;
> +	return dev->get_clk_rate_khz(dev);
> +}
> +
> +int i2c_dw_acquire_lock(struct dw_i2c_dev *dev)
> +{
> +	int ret;
> +
> +	if (!dev->acquire_lock)
> +		return 0;
> +
> +	ret = dev->acquire_lock(dev);
> +	if (!ret)
> +		return 0;
> +
> +	dev_err(dev->dev, "couldn't acquire bus ownership\n");
> +
> +	return ret;
> +}
> +
> +void i2c_dw_release_lock(struct dw_i2c_dev *dev)
> +{
> +	if (dev->release_lock)
> +		dev->release_lock(dev);
> +}
> +
> +/*
> + * Waiting for bus not busy
> + */
> +int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
> +{
> +	int timeout = TIMEOUT;
> +
> +	while (dw_readl(dev, DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) {
> +		if (timeout <= 0) {
> +			dev_warn(dev->dev, "timeout waiting for bus
> ready\n");
> +			return -ETIMEDOUT;
> +		}
> +		timeout--;
> +		usleep_range(1000, 1100);
> +	}
> +
> +	return 0;
> +}
> +
> +int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
> +{
> +	unsigned long abort_source = dev->abort_source;
> +	int i;
> +
> +	if (abort_source & DW_IC_TX_ABRT_NOACK) {
> +		for_each_set_bit(i, &abort_source,
> ARRAY_SIZE(abort_sources))
> +			dev_dbg(dev->dev,
> +				"%s: %s\n", __func__,
> abort_sources[i]);
> +		return -EREMOTEIO;
> +	}
> +
> +	for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
> +		dev_err(dev->dev, "%s: %s\n", __func__,
> abort_sources[i]);
> +
> +	if (abort_source & DW_IC_TX_ARB_LOST)
> +		return -EAGAIN;
> +	else if (abort_source & DW_IC_TX_ABRT_GCALL_READ)
> +		return -EINVAL; /* wrong msgs[] data */
> +	else
> +		return -EIO;
> +}
> +
> +u32 i2c_dw_func(struct i2c_adapter *adap)
> +{
> +	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
> +	return dev->functionality;
> +}
> +
> +MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter core");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/i2c/busses/i2c-designware-core.h
> b/drivers/i2c/busses/i2c-designware-core.h
> index 26250b425e2f..8bba7a37c3ce 100644
> --- a/drivers/i2c/busses/i2c-designware-core.h
> +++ b/drivers/i2c/busses/i2c-designware-core.h
> @@ -40,6 +40,124 @@
>  #define DW_IC_CON_RESTART_EN		0x20
>  #define DW_IC_CON_SLAVE_DISABLE		0x40
>  
> +/*
> + * Registers offset
> + */
> +#define DW_IC_CON		0x0
> +#define DW_IC_TAR		0x4
> +#define DW_IC_DATA_CMD		0x10
> +#define DW_IC_SS_SCL_HCNT	0x14
> +#define DW_IC_SS_SCL_LCNT	0x18
> +#define DW_IC_FS_SCL_HCNT	0x1c
> +#define DW_IC_FS_SCL_LCNT	0x20
> +#define DW_IC_HS_SCL_HCNT	0x24
> +#define DW_IC_HS_SCL_LCNT	0x28
> +#define DW_IC_INTR_STAT		0x2c
> +#define DW_IC_INTR_MASK		0x30
> +#define DW_IC_RAW_INTR_STAT	0x34
> +#define DW_IC_RX_TL		0x38
> +#define DW_IC_TX_TL		0x3c
> +#define DW_IC_CLR_INTR		0x40
> +#define DW_IC_CLR_RX_UNDER	0x44
> +#define DW_IC_CLR_RX_OVER	0x48
> +#define DW_IC_CLR_TX_OVER	0x4c
> +#define DW_IC_CLR_RD_REQ	0x50
> +#define DW_IC_CLR_TX_ABRT	0x54
> +#define DW_IC_CLR_RX_DONE	0x58
> +#define DW_IC_CLR_ACTIVITY	0x5c
> +#define DW_IC_CLR_STOP_DET	0x60
> +#define DW_IC_CLR_START_DET	0x64
> +#define DW_IC_CLR_GEN_CALL	0x68
> +#define DW_IC_ENABLE		0x6c
> +#define DW_IC_STATUS		0x70
> +#define DW_IC_TXFLR		0x74
> +#define DW_IC_RXFLR		0x78
> +#define DW_IC_SDA_HOLD		0x7c
> +#define DW_IC_TX_ABRT_SOURCE	0x80
> +#define DW_IC_ENABLE_STATUS	0x9c
> +#define DW_IC_COMP_PARAM_1	0xf4
> +#define DW_IC_COMP_VERSION	0xf8
> +#define DW_IC_SDA_HOLD_MIN_VERS	0x3131312A
> +#define DW_IC_COMP_TYPE		0xfc
> +#define DW_IC_COMP_TYPE_VALUE	0x44570140
> +
> +#define DW_IC_INTR_RX_UNDER	0x001
> +#define DW_IC_INTR_RX_OVER	0x002
> +#define DW_IC_INTR_RX_FULL	0x004
> +#define DW_IC_INTR_TX_OVER	0x008
> +#define DW_IC_INTR_TX_EMPTY	0x010
> +#define DW_IC_INTR_RD_REQ	0x020
> +#define DW_IC_INTR_TX_ABRT	0x040
> +#define DW_IC_INTR_RX_DONE	0x080
> +#define DW_IC_INTR_ACTIVITY	0x100
> +#define DW_IC_INTR_STOP_DET	0x200
> +#define DW_IC_INTR_START_DET	0x400
> +#define DW_IC_INTR_GEN_CALL	0x800
> +
> +#define DW_IC_INTR_DEFAULT_MASK		(DW_IC_INTR_RX_FULL |
> \
> +					 DW_IC_INTR_TX_ABRT | \
> +					 DW_IC_INTR_STOP_DET)
> +#define DW_IC_INTR_MASTER_MASK		(DW_IC_INTR_DEFAULT_MAS
> K | \
> +					 DW_IC_INTR_TX_EMPTY)
> +#define DW_IC_STATUS_ACTIVITY		0x1
> +#define DW_IC_STATUS_TFE		BIT(2)
> +#define DW_IC_STATUS_MASTER_ACTIVITY	BIT(5)
> +
> +#define DW_IC_SDA_HOLD_RX_SHIFT		16
> +#define DW_IC_SDA_HOLD_RX_MASK		GENMASK(23,
> DW_IC_SDA_HOLD_RX_SHIFT)
> +
> +#define DW_IC_ERR_TX_ABRT	0x1
> +
> +#define DW_IC_TAR_10BITADDR_MASTER BIT(12)
> +
> +#define DW_IC_COMP_PARAM_1_SPEED_MODE_HIGH	(BIT(2) | BIT(3))
> +#define DW_IC_COMP_PARAM_1_SPEED_MODE_MASK	GENMASK(3, 2)
> +
> +/*
> + * status codes
> + */
> +#define STATUS_IDLE			0x0
> +#define STATUS_WRITE_IN_PROGRESS	0x1
> +#define STATUS_READ_IN_PROGRESS		0x2
> +
> +#define TIMEOUT			20 /* ms */
> +
> +/*
> + * hardware abort codes from the DW_IC_TX_ABRT_SOURCE register
> + *
> + * only expected abort codes are listed here
> + * refer to the datasheet for the full list
> + */
> +#define ABRT_7B_ADDR_NOACK	0
> +#define ABRT_10ADDR1_NOACK	1
> +#define ABRT_10ADDR2_NOACK	2
> +#define ABRT_TXDATA_NOACK	3
> +#define ABRT_GCALL_NOACK	4
> +#define ABRT_GCALL_READ		5
> +#define ABRT_SBYTE_ACKDET	7
> +#define ABRT_SBYTE_NORSTRT	9
> +#define ABRT_10B_RD_NORSTRT	10
> +#define ABRT_MASTER_DIS		11
> +#define ARB_LOST		12
> +
> +#define DW_IC_TX_ABRT_7B_ADDR_NOACK	(1UL <<
> ABRT_7B_ADDR_NOACK)
> +#define DW_IC_TX_ABRT_10ADDR1_NOACK	(1UL <<
> ABRT_10ADDR1_NOACK)
> +#define DW_IC_TX_ABRT_10ADDR2_NOACK	(1UL <<
> ABRT_10ADDR2_NOACK)
> +#define DW_IC_TX_ABRT_TXDATA_NOACK	(1UL << ABRT_TXDATA_NOACK)
> +#define DW_IC_TX_ABRT_GCALL_NOACK	(1UL << ABRT_GCALL_NOACK)
> +#define DW_IC_TX_ABRT_GCALL_READ	(1UL << ABRT_GCALL_READ)
> +#define DW_IC_TX_ABRT_SBYTE_ACKDET	(1UL << ABRT_SBYTE_ACKDET)
> +#define DW_IC_TX_ABRT_SBYTE_NORSTRT	(1UL <<
> ABRT_SBYTE_NORSTRT)
> +#define DW_IC_TX_ABRT_10B_RD_NORSTRT	(1UL <<
> ABRT_10B_RD_NORSTRT)
> +#define DW_IC_TX_ABRT_MASTER_DIS	(1UL << ABRT_MASTER_DIS)
> +#define DW_IC_TX_ARB_LOST		(1UL << ARB_LOST)
> +
> +#define DW_IC_TX_ABRT_NOACK		(DW_IC_TX_ABRT_7B_ADDR_NOA
> CK | \
> +					 DW_IC_TX_ABRT_10ADDR1_NOACK
> | \
> +					 DW_IC_TX_ABRT_10ADDR2_NOACK
> | \
> +					 DW_IC_TX_ABRT_TXDATA_NOACK |
> \
> +					 DW_IC_TX_ABRT_GCALL_NOACK)
> +
>  
>  /**
>   * struct dw_i2c_dev - private i2c-designware data
> @@ -132,6 +250,19 @@ struct dw_i2c_dev {
>  #define ACCESS_16BIT		0x00000002
>  #define ACCESS_INTR_MASK	0x00000004
>  
> +u32 dw_readl(struct dw_i2c_dev *dev, int offset);
> +void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset);
> +u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int
> offset);
> +u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset);
> +void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable);
> +void __i2c_dw_enable_and_wait(struct dw_i2c_dev *dev, bool enable);
> +unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev);
> +int i2c_dw_acquire_lock(struct dw_i2c_dev *dev);
> +void i2c_dw_release_lock(struct dw_i2c_dev *dev);
> +int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev);
> +int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev);
> +u32 i2c_dw_func(struct i2c_adapter *adap);
> +
>  extern int i2c_dw_init(struct dw_i2c_dev *dev);
>  extern void i2c_dw_disable(struct dw_i2c_dev *dev);
>  extern void i2c_dw_disable_int(struct dw_i2c_dev *dev);
> diff --git a/drivers/i2c/busses/i2c-designware-core.c
> b/drivers/i2c/busses/i2c-designware-master.c
> similarity index 66%
> rename from drivers/i2c/busses/i2c-designware-core.c
> rename to drivers/i2c/busses/i2c-designware-master.c
> index a51addfde565..9943addac3d7 100644
> --- a/drivers/i2c/busses/i2c-designware-core.c
> +++ b/drivers/i2c/busses/i2c-designware-master.c
> @@ -32,305 +32,18 @@
>  #include <linux/module.h>
>  #include "i2c-designware-core.h"
>  
> -/*
> - * Registers offset
> - */
> -#define DW_IC_CON		0x0
> -#define DW_IC_TAR		0x4
> -#define DW_IC_DATA_CMD		0x10
> -#define DW_IC_SS_SCL_HCNT	0x14
> -#define DW_IC_SS_SCL_LCNT	0x18
> -#define DW_IC_FS_SCL_HCNT	0x1c
> -#define DW_IC_FS_SCL_LCNT	0x20
> -#define DW_IC_HS_SCL_HCNT	0x24
> -#define DW_IC_HS_SCL_LCNT	0x28
> -#define DW_IC_INTR_STAT		0x2c
> -#define DW_IC_INTR_MASK		0x30
> -#define DW_IC_RAW_INTR_STAT	0x34
> -#define DW_IC_RX_TL		0x38
> -#define DW_IC_TX_TL		0x3c
> -#define DW_IC_CLR_INTR		0x40
> -#define DW_IC_CLR_RX_UNDER	0x44
> -#define DW_IC_CLR_RX_OVER	0x48
> -#define DW_IC_CLR_TX_OVER	0x4c
> -#define DW_IC_CLR_RD_REQ	0x50
> -#define DW_IC_CLR_TX_ABRT	0x54
> -#define DW_IC_CLR_RX_DONE	0x58
> -#define DW_IC_CLR_ACTIVITY	0x5c
> -#define DW_IC_CLR_STOP_DET	0x60
> -#define DW_IC_CLR_START_DET	0x64
> -#define DW_IC_CLR_GEN_CALL	0x68
> -#define DW_IC_ENABLE		0x6c
> -#define DW_IC_STATUS		0x70
> -#define DW_IC_TXFLR		0x74
> -#define DW_IC_RXFLR		0x78
> -#define DW_IC_SDA_HOLD		0x7c
> -#define DW_IC_TX_ABRT_SOURCE	0x80
> -#define DW_IC_ENABLE_STATUS	0x9c
> -#define DW_IC_COMP_PARAM_1	0xf4
> -#define DW_IC_COMP_VERSION	0xf8
> -#define DW_IC_SDA_HOLD_MIN_VERS	0x3131312A
> -#define DW_IC_COMP_TYPE		0xfc
> -#define DW_IC_COMP_TYPE_VALUE	0x44570140
> -
> -#define DW_IC_INTR_RX_UNDER	0x001
> -#define DW_IC_INTR_RX_OVER	0x002
> -#define DW_IC_INTR_RX_FULL	0x004
> -#define DW_IC_INTR_TX_OVER	0x008
> -#define DW_IC_INTR_TX_EMPTY	0x010
> -#define DW_IC_INTR_RD_REQ	0x020
> -#define DW_IC_INTR_TX_ABRT	0x040
> -#define DW_IC_INTR_RX_DONE	0x080
> -#define DW_IC_INTR_ACTIVITY	0x100
> -#define DW_IC_INTR_STOP_DET	0x200
> -#define DW_IC_INTR_START_DET	0x400
> -#define DW_IC_INTR_GEN_CALL	0x800
> -
> -#define DW_IC_INTR_DEFAULT_MASK		(DW_IC_INTR_RX_FULL |
> \
> -					 DW_IC_INTR_TX_ABRT | \
> -					 DW_IC_INTR_STOP_DET)
> -
> -#define DW_IC_INTR_MASTER_MASK		(DW_IC_INTR_DEFAULT_MAS
> K | \
> -					 DW_IC_INTR_TX_EMPTY)
> -
> -#define DW_IC_STATUS_ACTIVITY	0x1
> -
> -#define DW_IC_SDA_HOLD_RX_SHIFT		16
> -#define DW_IC_SDA_HOLD_RX_MASK		GENMASK(23,
> DW_IC_SDA_HOLD_RX_SHIFT)
> -
> -#define DW_IC_ERR_TX_ABRT	0x1
> -
> -#define DW_IC_TAR_10BITADDR_MASTER BIT(12)
> -
> -#define DW_IC_COMP_PARAM_1_SPEED_MODE_HIGH	(BIT(2) | BIT(3))
> -#define DW_IC_COMP_PARAM_1_SPEED_MODE_MASK	GENMASK(3, 2)
> -
> -/*
> - * status codes
> - */
> -#define STATUS_IDLE			0x0
> -#define STATUS_WRITE_IN_PROGRESS	0x1
> -#define STATUS_READ_IN_PROGRESS		0x2
> -
> -#define TIMEOUT			20 /* ms */
> -
> -/*
> - * hardware abort codes from the DW_IC_TX_ABRT_SOURCE register
> - *
> - * only expected abort codes are listed here
> - * refer to the datasheet for the full list
> - */
> -#define ABRT_7B_ADDR_NOACK	0
> -#define ABRT_10ADDR1_NOACK	1
> -#define ABRT_10ADDR2_NOACK	2
> -#define ABRT_TXDATA_NOACK	3
> -#define ABRT_GCALL_NOACK	4
> -#define ABRT_GCALL_READ		5
> -#define ABRT_SBYTE_ACKDET	7
> -#define ABRT_SBYTE_NORSTRT	9
> -#define ABRT_10B_RD_NORSTRT	10
> -#define ABRT_MASTER_DIS		11
> -#define ARB_LOST		12
> -
> -#define DW_IC_TX_ABRT_7B_ADDR_NOACK	(1UL <<
> ABRT_7B_ADDR_NOACK)
> -#define DW_IC_TX_ABRT_10ADDR1_NOACK	(1UL <<
> ABRT_10ADDR1_NOACK)
> -#define DW_IC_TX_ABRT_10ADDR2_NOACK	(1UL <<
> ABRT_10ADDR2_NOACK)
> -#define DW_IC_TX_ABRT_TXDATA_NOACK	(1UL << ABRT_TXDATA_NOACK)
> -#define DW_IC_TX_ABRT_GCALL_NOACK	(1UL << ABRT_GCALL_NOACK)
> -#define DW_IC_TX_ABRT_GCALL_READ	(1UL << ABRT_GCALL_READ)
> -#define DW_IC_TX_ABRT_SBYTE_ACKDET	(1UL << ABRT_SBYTE_ACKDET)
> -#define DW_IC_TX_ABRT_SBYTE_NORSTRT	(1UL <<
> ABRT_SBYTE_NORSTRT)
> -#define DW_IC_TX_ABRT_10B_RD_NORSTRT	(1UL <<
> ABRT_10B_RD_NORSTRT)
> -#define DW_IC_TX_ABRT_MASTER_DIS	(1UL << ABRT_MASTER_DIS)
> -#define DW_IC_TX_ARB_LOST		(1UL << ARB_LOST)
> -
> -#define DW_IC_TX_ABRT_NOACK		(DW_IC_TX_ABRT_7B_ADDR_NOA
> CK | \
> -					 DW_IC_TX_ABRT_10ADDR1_NOACK
> | \
> -					 DW_IC_TX_ABRT_10ADDR2_NOACK
> | \
> -					 DW_IC_TX_ABRT_TXDATA_NOACK |
> \
> -					 DW_IC_TX_ABRT_GCALL_NOACK)
> -
> -static char *abort_sources[] = {
> -	[ABRT_7B_ADDR_NOACK] =
> -		"slave address not acknowledged (7bit mode)",
> -	[ABRT_10ADDR1_NOACK] =
> -		"first address byte not acknowledged (10bit mode)",
> -	[ABRT_10ADDR2_NOACK] =
> -		"second address byte not acknowledged (10bit mode)",
> -	[ABRT_TXDATA_NOACK] =
> -		"data not acknowledged",
> -	[ABRT_GCALL_NOACK] =
> -		"no acknowledgement for a general call",
> -	[ABRT_GCALL_READ] =
> -		"read after general call",
> -	[ABRT_SBYTE_ACKDET] =
> -		"start byte acknowledged",
> -	[ABRT_SBYTE_NORSTRT] =
> -		"trying to send start byte when restart is disabled",
> -	[ABRT_10B_RD_NORSTRT] =
> -		"trying to read when restart is disabled (10bit
> mode)",
> -	[ABRT_MASTER_DIS] =
> -		"trying to use disabled adapter",
> -	[ARB_LOST] =
> -		"lost arbitration",
> -};
> -
> -static u32 dw_readl(struct dw_i2c_dev *dev, int offset)
> -{
> -	u32 value;
> -
> -	if (dev->accessor_flags & ACCESS_16BIT)
> -		value = readw_relaxed(dev->base + offset) |
> -			(readw_relaxed(dev->base + offset + 2) <<
> 16);
> -	else
> -		value = readl_relaxed(dev->base + offset);
> -
> -	if (dev->accessor_flags & ACCESS_SWAP)
> -		return swab32(value);
> -	else
> -		return value;
> -}
> -
> -static void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
> -{
> -	if (dev->accessor_flags & ACCESS_SWAP)
> -		b = swab32(b);
> -
> -	if (dev->accessor_flags & ACCESS_16BIT) {
> -		writew_relaxed((u16)b, dev->base + offset);
> -		writew_relaxed((u16)(b >> 16), dev->base + offset +
> 2);
> -	} else {
> -		writel_relaxed(b, dev->base + offset);
> -	}
> -}
> -
>  static void i2c_dw_configure_fifo_master(struct dw_i2c_dev *dev)
>  {
>  	/* Configure Tx/Rx FIFO threshold levels */
>  	dw_writel(dev, dev->tx_fifo_depth / 2, DW_IC_TX_TL);
>  	dw_writel(dev, 0, DW_IC_RX_TL);
>  
> -	/* configure the i2c master */
> +	/* configure the I2C master */
>  	dw_writel(dev, dev->master_cfg, DW_IC_CON);
>  }
>  
> -static u32
> -i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int
> offset)
> -{
> -	/*
> -	 * DesignWare I2C core doesn't seem to have solid strategy to
> meet
> -	 * the tHD;STA timing spec.  Configuring _HCNT based on tHIGH
> spec
> -	 * will result in violation of the tHD;STA spec.
> -	 */
> -	if (cond)
> -		/*
> -		 * Conditional expression:
> -		 *
> -		 *   IC_[FS]S_SCL_HCNT + (1+4+3) >= IC_CLK * tHIGH
> -		 *
> -		 * This is based on the DW manuals, and represents an
> ideal
> -		 * configuration.  The resulting I2C bus speed will
> be
> -		 * faster than any of the others.
> -		 *
> -		 * If your hardware is free from tHD;STA issue, try
> this one.
> -		 */
> -		return (ic_clk * tSYMBOL + 500000) / 1000000 - 8 +
> offset;
> -	else
> -		/*
> -		 * Conditional expression:
> -		 *
> -		 *   IC_[FS]S_SCL_HCNT + 3 >= IC_CLK * (tHD;STA + tf)
> -		 *
> -		 * This is just experimental rule; the tHD;STA period
> turned
> -		 * out to be proportinal to (_HCNT + 3).  With this
> setting,
> -		 * we could meet both tHIGH and tHD;STA timing specs.
> -		 *
> -		 * If unsure, you'd better to take this alternative.
> -		 *
> -		 * The reason why we need to take into account "tf"
> here,
> -		 * is the same as described in i2c_dw_scl_lcnt().
> -		 */
> -		return (ic_clk * (tSYMBOL + tf) + 500000) / 1000000
> -			- 3 + offset;
> -}
> -
> -static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
> -{
> -	/*
> -	 * Conditional expression:
> -	 *
> -	 *   IC_[FS]S_SCL_LCNT + 1 >= IC_CLK * (tLOW + tf)
> -	 *
> -	 * DW I2C core starts counting the SCL CNTs for the LOW
> period
> -	 * of the SCL clock (tLOW) as soon as it pulls the SCL line.
> -	 * In order to meet the tLOW timing spec, we need to take
> into
> -	 * account the fall time of SCL signal (tf).  Default tf
> value
> -	 * should be 0.3 us, for safety.
> -	 */
> -	return ((ic_clk * (tLOW + tf) + 500000) / 1000000) - 1 +
> offset;
> -}
> -
> -static void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable)
> -{
> -	dw_writel(dev, enable, DW_IC_ENABLE);
> -}
> -
> -static void __i2c_dw_enable_and_wait(struct dw_i2c_dev *dev, bool
> enable)
> -{
> -	int timeout = 100;
> -
> -	do {
> -		__i2c_dw_enable(dev, enable);
> -		if ((dw_readl(dev, DW_IC_ENABLE_STATUS) & 1) ==
> enable)
> -			return;
> -
> -		/*
> -		 * Wait 10 times the signaling period of the highest
> I2C
> -		 * transfer supported by the driver (for 400KHz this
> is
> -		 * 25us) as described in the DesignWare I2C databook.
> -		 */
> -		usleep_range(25, 250);
> -	} while (timeout--);
> -
> -	dev_warn(dev->dev, "timeout in %sabling adapter\n",
> -		 enable ? "en" : "dis");
> -}
> -
> -static unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev)
> -{
> -	/*
> -	 * Clock is not necessary if we got LCNT/HCNT values directly
> from
> -	 * the platform code.
> -	 */
> -	if (WARN_ON_ONCE(!dev->get_clk_rate_khz))
> -		return 0;
> -	return dev->get_clk_rate_khz(dev);
> -}
> -
> -static int i2c_dw_acquire_lock(struct dw_i2c_dev *dev)
> -{
> -	int ret;
> -
> -	if (!dev->acquire_lock)
> -		return 0;
> -
> -	ret = dev->acquire_lock(dev);
> -	if (!ret)
> -		return 0;
> -
> -	dev_err(dev->dev, "couldn't acquire bus ownership\n");
> -
> -	return ret;
> -}
> -
> -static void i2c_dw_release_lock(struct dw_i2c_dev *dev)
> -{
> -	if (dev->release_lock)
> -		dev->release_lock(dev);
> -}
> -
>  /**
> - * i2c_dw_init() - initialize the designware i2c hardware
> + * i2c_dw_init() - initialize the designware i2c master hardware
>   * @dev: device private data
>   *
>   * This functions configures and enables the I2C.
> @@ -462,25 +175,6 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
>  }
>  EXPORT_SYMBOL_GPL(i2c_dw_init);
>  
> -/*
> - * Waiting for bus not busy
> - */
> -static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
> -{
> -	int timeout = TIMEOUT;
> -
> -	while (dw_readl(dev, DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) {
> -		if (timeout <= 0) {
> -			dev_warn(dev->dev, "timeout waiting for bus
> ready\n");
> -			return -ETIMEDOUT;
> -		}
> -		timeout--;
> -		usleep_range(1000, 1100);
> -	}
> -
> -	return 0;
> -}
> -
>  static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
>  {
>  	struct i2c_msg *msgs = dev->msgs;
> @@ -715,29 +409,6 @@ i2c_dw_read(struct dw_i2c_dev *dev)
>  	}
>  }
>  
> -static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
> -{
> -	unsigned long abort_source = dev->abort_source;
> -	int i;
> -
> -	if (abort_source & DW_IC_TX_ABRT_NOACK) {
> -		for_each_set_bit(i, &abort_source,
> ARRAY_SIZE(abort_sources))
> -			dev_dbg(dev->dev,
> -				"%s: %s\n", __func__,
> abort_sources[i]);
> -		return -EREMOTEIO;
> -	}
> -
> -	for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
> -		dev_err(dev->dev, "%s: %s\n", __func__,
> abort_sources[i]);
> -
> -	if (abort_source & DW_IC_TX_ARB_LOST)
> -		return -EAGAIN;
> -	else if (abort_source & DW_IC_TX_ABRT_GCALL_READ)
> -		return -EINVAL; /* wrong msgs[] data */
> -	else
> -		return -EIO;
> -}
> -
>  /*
>   * Prepare controller for a transaction and call i2c_dw_xfer_msg
>   */
> @@ -825,12 +496,6 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct
> i2c_msg msgs[], int num)
>  	return ret;
>  }
>  
> -static u32 i2c_dw_func(struct i2c_adapter *adap)
> -{
> -	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
> -	return dev->functionality;
> -}
> -
>  static struct i2c_algorithm i2c_dw_algo = {
>  	.master_xfer	= i2c_dw_xfer,
>  	.functionality	= i2c_dw_func,
> @@ -892,10 +557,10 @@ static u32 i2c_dw_read_clear_intrbits(struct
> dw_i2c_dev *dev)
>  }
>  
>  /*
> - * Interrupt service routine. This gets called whenever an I2C
> interrupt
> + * Interrupt service routine. This gets called whenever an I2C master
> interrupt
>   * occurs.
>   */
> -int i2c_dw_irq_handler_master(struct dw_i2c_dev *dev)
> +static int i2c_dw_irq_handler_master(struct dw_i2c_dev *dev)
>  {
>  	u32 stat;
>  
> @@ -940,7 +605,7 @@ int i2c_dw_irq_handler_master(struct dw_i2c_dev
> *dev)
>  static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
>  {
>  	struct dw_i2c_dev *dev = dev_id;
> -	u32 stat, enabled, mode;
> +	u32 stat, enabled;
>  
>  	enabled = dw_readl(dev, DW_IC_ENABLE);
>  	stat = dw_readl(dev, DW_IC_RAW_INTR_STAT);
> @@ -1041,5 +706,5 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
>  }
>  EXPORT_SYMBOL_GPL(i2c_dw_probe);
>  
> -MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter core");
> +MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter master");
>  MODULE_LICENSE("GPL");

-- 
Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx>
Intel Finland Oy
--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux GPIO]     [Linux SPI]     [Linux Hardward Monitoring]     [LM Sensors]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux