From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753625AbcLGTFI (ORCPT ); Wed, 7 Dec 2016 14:05:08 -0500 Received: from mga01.intel.com ([192.55.52.88]:15080 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932559AbcLGTFF (ORCPT ); Wed, 7 Dec 2016 14:05:05 -0500 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.33,315,1477983600"; d="scan'208";a="15035878" Message-ID: <1481137408.30772.10.camel@linux.intel.com> Subject: Re: [PATCH v4 2/5] i2c: designware: Master mode as separated driver From: Andy Shevchenko To: Luis Oliveira , wsa@the-dreams.de, robh+dt@kernel.org, mark.rutland@arm.com, jarkko.nikula@linux.intel.com, mika.westerberg@linux.intel.com, linux-i2c@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Ramiro.Oliveira@synopsys.com, Joao.Pinto@synopsys.com, CARLOS.PALMINHA@synopsys.com Date: Wed, 07 Dec 2016 21:03:28 +0200 In-Reply-To: <44c434e5d4c3b12e891c424e264647101f3629a4.1481131072.git.lolivei@synopsys.com> References: <44c434e5d4c3b12e891c424e264647101f3629a4.1481131072.git.lolivei@synopsys.com> Organization: Intel Finland Oy Content-Type: text/plain; charset="UTF-8" X-Mailer: Evolution 3.22.2-1 Mime-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 > Signed-off-by: Luis Oliveira > --- > 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 > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#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 >  #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 Intel Finland Oy