12373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie/*
22373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * Synopsys DesignWare I2C adapter driver (master only).
32373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie *
42373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * Based on the TI DAVINCI I2C adapter driver.
52373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie *
62373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * Copyright (C) 2006 Texas Instruments.
72373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * Copyright (C) 2007 MontaVista Software Inc.
82373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * Copyright (C) 2009 Provigent Ltd.
92373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie *
102373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * ----------------------------------------------------------------------------
112373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie *
122373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * This program is free software; you can redistribute it and/or modify
132373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * it under the terms of the GNU General Public License as published by
142373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * the Free Software Foundation; either version 2 of the License, or
152373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * (at your option) any later version.
162373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie *
172373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * This program is distributed in the hope that it will be useful,
182373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * but WITHOUT ANY WARRANTY; without even the implied warranty of
192373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
202373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * GNU General Public License for more details.
212373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie *
222373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * You should have received a copy of the GNU General Public License
232373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * along with this program; if not, write to the Free Software
242373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
252373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * ----------------------------------------------------------------------------
262373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie *
272373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie */
282373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie#include <linux/clk.h>
292373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie#include <linux/errno.h>
302373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie#include <linux/err.h>
312373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie#include <linux/i2c.h>
322373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie#include <linux/interrupt.h>
332373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie#include <linux/io.h>
3418dbdda89f5cf0540e577280395f16079308e87dDirk Brandewie#include <linux/pm_runtime.h>
352373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie#include <linux/delay.h>
362373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie#include "i2c-designware-core.h"
372373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
38f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie/*
39f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie * Registers offset
40f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie */
41f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_CON		0x0
42f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_TAR		0x4
43f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_DATA_CMD		0x10
44f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_SS_SCL_HCNT	0x14
45f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_SS_SCL_LCNT	0x18
46f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_FS_SCL_HCNT	0x1c
47f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_FS_SCL_LCNT	0x20
48f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_INTR_STAT		0x2c
49f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_INTR_MASK		0x30
50f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_RAW_INTR_STAT	0x34
51f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_RX_TL		0x38
52f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_TX_TL		0x3c
53f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_CLR_INTR		0x40
54f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_CLR_RX_UNDER	0x44
55f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_CLR_RX_OVER	0x48
56f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_CLR_TX_OVER	0x4c
57f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_CLR_RD_REQ	0x50
58f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_CLR_TX_ABRT	0x54
59f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_CLR_RX_DONE	0x58
60f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_CLR_ACTIVITY	0x5c
61f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_CLR_STOP_DET	0x60
62f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_CLR_START_DET	0x64
63f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_CLR_GEN_CALL	0x68
64f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_ENABLE		0x6c
65f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_STATUS		0x70
66f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_TXFLR		0x74
67f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_RXFLR		0x78
68f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_TX_ABRT_SOURCE	0x80
69f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_COMP_PARAM_1	0xf4
70f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_COMP_TYPE		0xfc
71f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_COMP_TYPE_VALUE	0x44570140
72f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie
73f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_INTR_RX_UNDER	0x001
74f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_INTR_RX_OVER	0x002
75f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_INTR_RX_FULL	0x004
76f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_INTR_TX_OVER	0x008
77f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_INTR_TX_EMPTY	0x010
78f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_INTR_RD_REQ	0x020
79f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_INTR_TX_ABRT	0x040
80f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_INTR_RX_DONE	0x080
81f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_INTR_ACTIVITY	0x100
82f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_INTR_STOP_DET	0x200
83f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_INTR_START_DET	0x400
84f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_INTR_GEN_CALL	0x800
85f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie
86f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_INTR_DEFAULT_MASK		(DW_IC_INTR_RX_FULL | \
87f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie					 DW_IC_INTR_TX_EMPTY | \
88f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie					 DW_IC_INTR_TX_ABRT | \
89f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie					 DW_IC_INTR_STOP_DET)
90f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie
91f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_STATUS_ACTIVITY	0x1
92f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie
93f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_ERR_TX_ABRT	0x1
94f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie
95f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie/*
96f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie * status codes
97f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie */
98f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define STATUS_IDLE			0x0
99f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define STATUS_WRITE_IN_PROGRESS	0x1
100f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define STATUS_READ_IN_PROGRESS		0x2
101f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie
102f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define TIMEOUT			20 /* ms */
103f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie
104f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie/*
105f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie * hardware abort codes from the DW_IC_TX_ABRT_SOURCE register
106f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie *
107f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie * only expected abort codes are listed here
108f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie * refer to the datasheet for the full list
109f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie */
110f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define ABRT_7B_ADDR_NOACK	0
111f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define ABRT_10ADDR1_NOACK	1
112f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define ABRT_10ADDR2_NOACK	2
113f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define ABRT_TXDATA_NOACK	3
114f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define ABRT_GCALL_NOACK	4
115f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define ABRT_GCALL_READ		5
116f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define ABRT_SBYTE_ACKDET	7
117f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define ABRT_SBYTE_NORSTRT	9
118f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define ABRT_10B_RD_NORSTRT	10
119f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define ABRT_MASTER_DIS		11
120f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define ARB_LOST		12
121f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie
122f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_TX_ABRT_7B_ADDR_NOACK	(1UL << ABRT_7B_ADDR_NOACK)
123f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_TX_ABRT_10ADDR1_NOACK	(1UL << ABRT_10ADDR1_NOACK)
124f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_TX_ABRT_10ADDR2_NOACK	(1UL << ABRT_10ADDR2_NOACK)
125f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_TX_ABRT_TXDATA_NOACK	(1UL << ABRT_TXDATA_NOACK)
126f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_TX_ABRT_GCALL_NOACK	(1UL << ABRT_GCALL_NOACK)
127f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_TX_ABRT_GCALL_READ	(1UL << ABRT_GCALL_READ)
128f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_TX_ABRT_SBYTE_ACKDET	(1UL << ABRT_SBYTE_ACKDET)
129f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_TX_ABRT_SBYTE_NORSTRT	(1UL << ABRT_SBYTE_NORSTRT)
130f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_TX_ABRT_10B_RD_NORSTRT	(1UL << ABRT_10B_RD_NORSTRT)
131f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_TX_ABRT_MASTER_DIS	(1UL << ABRT_MASTER_DIS)
132f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_TX_ARB_LOST		(1UL << ARB_LOST)
133f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie
134f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie#define DW_IC_TX_ABRT_NOACK		(DW_IC_TX_ABRT_7B_ADDR_NOACK | \
135f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie					 DW_IC_TX_ABRT_10ADDR1_NOACK | \
136f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie					 DW_IC_TX_ABRT_10ADDR2_NOACK | \
137f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie					 DW_IC_TX_ABRT_TXDATA_NOACK | \
138f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie					 DW_IC_TX_ABRT_GCALL_NOACK)
139f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie
1402373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewiestatic char *abort_sources[] = {
1412373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	[ABRT_7B_ADDR_NOACK] =
1422373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		"slave address not acknowledged (7bit mode)",
1432373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	[ABRT_10ADDR1_NOACK] =
1442373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		"first address byte not acknowledged (10bit mode)",
1452373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	[ABRT_10ADDR2_NOACK] =
1462373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		"second address byte not acknowledged (10bit mode)",
1472373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	[ABRT_TXDATA_NOACK] =
1482373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		"data not acknowledged",
1492373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	[ABRT_GCALL_NOACK] =
1502373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		"no acknowledgement for a general call",
1512373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	[ABRT_GCALL_READ] =
1522373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		"read after general call",
1532373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	[ABRT_SBYTE_ACKDET] =
1542373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		"start byte acknowledged",
1552373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	[ABRT_SBYTE_NORSTRT] =
1562373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		"trying to send start byte when restart is disabled",
1572373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	[ABRT_10B_RD_NORSTRT] =
1582373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		"trying to read when restart is disabled (10bit mode)",
1592373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	[ABRT_MASTER_DIS] =
1602373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		"trying to use disabled adapter",
1612373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	[ARB_LOST] =
1622373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		"lost arbitration",
1632373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie};
1642373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
1652373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewieu32 dw_readl(struct dw_i2c_dev *dev, int offset)
1662373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie{
1672373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	u32 value = readl(dev->base + offset);
1682373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
1692373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (dev->swab)
1702373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		return swab32(value);
1712373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	else
1722373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		return value;
1732373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie}
1742373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
1752373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewievoid dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
1762373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie{
1772373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (dev->swab)
1782373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		b = swab32(b);
1792373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
1802373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	writel(b, dev->base + offset);
1812373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie}
1822373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
1832373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewiestatic u32
1842373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewiei2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
1852373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie{
1862373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	/*
1872373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 * DesignWare I2C core doesn't seem to have solid strategy to meet
1882373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 * the tHD;STA timing spec.  Configuring _HCNT based on tHIGH spec
1892373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 * will result in violation of the tHD;STA spec.
1902373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 */
1912373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (cond)
1922373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		/*
1932373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 * Conditional expression:
1942373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 *
1952373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 *   IC_[FS]S_SCL_HCNT + (1+4+3) >= IC_CLK * tHIGH
1962373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 *
1972373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 * This is based on the DW manuals, and represents an ideal
1982373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 * configuration.  The resulting I2C bus speed will be
1992373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 * faster than any of the others.
2002373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 *
2012373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 * If your hardware is free from tHD;STA issue, try this one.
2022373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 */
2032373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		return (ic_clk * tSYMBOL + 5000) / 10000 - 8 + offset;
2042373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	else
2052373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		/*
2062373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 * Conditional expression:
2072373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 *
2082373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 *   IC_[FS]S_SCL_HCNT + 3 >= IC_CLK * (tHD;STA + tf)
2092373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 *
2102373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 * This is just experimental rule; the tHD;STA period turned
2112373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 * out to be proportinal to (_HCNT + 3).  With this setting,
2122373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 * we could meet both tHIGH and tHD;STA timing specs.
2132373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 *
2142373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 * If unsure, you'd better to take this alternative.
2152373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 *
2162373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 * The reason why we need to take into account "tf" here,
2172373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 * is the same as described in i2c_dw_scl_lcnt().
2182373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 */
2192373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		return (ic_clk * (tSYMBOL + tf) + 5000) / 10000 - 3 + offset;
2202373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie}
2212373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
2222373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewiestatic u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
2232373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie{
2242373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	/*
2252373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 * Conditional expression:
2262373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 *
2272373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 *   IC_[FS]S_SCL_LCNT + 1 >= IC_CLK * (tLOW + tf)
2282373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 *
2292373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 * DW I2C core starts counting the SCL CNTs for the LOW period
2302373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 * of the SCL clock (tLOW) as soon as it pulls the SCL line.
2312373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 * In order to meet the tLOW timing spec, we need to take into
2322373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 * account the fall time of SCL signal (tf).  Default tf value
2332373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 * should be 0.3 us, for safety.
2342373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 */
2352373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	return ((ic_clk * (tLOW + tf) + 5000) / 10000) - 1 + offset;
2362373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie}
2372373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
2382373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie/**
2392373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * i2c_dw_init() - initialize the designware i2c master hardware
2402373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * @dev: device private data
2412373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie *
2422373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * This functions configures and enables the I2C master.
2432373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * This function is called during I2C init function, and in case of timeout at
2442373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * run time.
2452373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie */
2462373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewieint i2c_dw_init(struct dw_i2c_dev *dev)
2472373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie{
2481d31b58f648c4f754b23fed4d57acc941080e5eeDirk Brandewie	u32 input_clock_khz;
249e18563fc560aba0d95a5a73145812a081fb38facDirk Brandewie	u32 hcnt, lcnt;
2502373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	u32 reg;
2512373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
2521d31b58f648c4f754b23fed4d57acc941080e5eeDirk Brandewie	input_clock_khz = dev->get_clk_rate_khz(dev);
2531d31b58f648c4f754b23fed4d57acc941080e5eeDirk Brandewie
2542373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	/* Configure register endianess access */
2552373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	reg = dw_readl(dev, DW_IC_COMP_TYPE);
2562373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) {
2572373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		dev->swab = 1;
2582373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		reg = DW_IC_COMP_TYPE_VALUE;
2592373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	}
2602373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
2612373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (reg != DW_IC_COMP_TYPE_VALUE) {
2622373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		dev_err(dev->dev, "Unknown Synopsys component type: "
2632373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			"0x%08x\n", reg);
2642373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		return -ENODEV;
2652373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	}
2662373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
2672373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	/* Disable the adapter */
2682373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	dw_writel(dev, 0, DW_IC_ENABLE);
2692373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
2702373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	/* set standard and fast speed deviders for high/low periods */
2712373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
2722373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	/* Standard-mode */
2732373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	hcnt = i2c_dw_scl_hcnt(input_clock_khz,
2742373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie				40,	/* tHD;STA = tHIGH = 4.0 us */
2752373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie				3,	/* tf = 0.3 us */
2762373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie				0,	/* 0: DW default, 1: Ideal */
2772373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie				0);	/* No offset */
2782373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	lcnt = i2c_dw_scl_lcnt(input_clock_khz,
2792373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie				47,	/* tLOW = 4.7 us */
2802373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie				3,	/* tf = 0.3 us */
2812373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie				0);	/* No offset */
2822373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	dw_writel(dev, hcnt, DW_IC_SS_SCL_HCNT);
2832373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT);
2842373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
2852373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
2862373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	/* Fast-mode */
2872373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	hcnt = i2c_dw_scl_hcnt(input_clock_khz,
2882373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie				6,	/* tHD;STA = tHIGH = 0.6 us */
2892373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie				3,	/* tf = 0.3 us */
2902373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie				0,	/* 0: DW default, 1: Ideal */
2912373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie				0);	/* No offset */
2922373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	lcnt = i2c_dw_scl_lcnt(input_clock_khz,
2932373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie				13,	/* tLOW = 1.3 us */
2942373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie				3,	/* tf = 0.3 us */
2952373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie				0);	/* No offset */
2962373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	dw_writel(dev, hcnt, DW_IC_FS_SCL_HCNT);
2972373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT);
2982373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
2992373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
3002373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	/* Configure Tx/Rx FIFO threshold levels */
3012373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	dw_writel(dev, dev->tx_fifo_depth - 1, DW_IC_TX_TL);
3022373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	dw_writel(dev, 0, DW_IC_RX_TL);
3032373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
3042373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	/* configure the i2c master */
305e18563fc560aba0d95a5a73145812a081fb38facDirk Brandewie	dw_writel(dev, dev->master_cfg , DW_IC_CON);
3062373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	return 0;
3072373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie}
3082373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
3092373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie/*
3102373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * Waiting for bus not busy
3112373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie */
3122373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewiestatic int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
3132373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie{
3142373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	int timeout = TIMEOUT;
3152373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
3162373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	while (dw_readl(dev, DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) {
3172373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		if (timeout <= 0) {
3182373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			dev_warn(dev->dev, "timeout waiting for bus ready\n");
3192373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			return -ETIMEDOUT;
3202373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		}
3212373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		timeout--;
3222373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		mdelay(1);
3232373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	}
3242373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
3252373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	return 0;
3262373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie}
3272373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
3282373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewiestatic void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
3292373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie{
3302373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	struct i2c_msg *msgs = dev->msgs;
3312373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	u32 ic_con;
3322373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
3332373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	/* Disable the adapter */
3342373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	dw_writel(dev, 0, DW_IC_ENABLE);
3352373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
3362373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	/* set the slave (target) address */
3372373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	dw_writel(dev, msgs[dev->msg_write_idx].addr, DW_IC_TAR);
3382373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
3392373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	/* if the slave address is ten bit address, enable 10BITADDR */
3402373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	ic_con = dw_readl(dev, DW_IC_CON);
3412373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (msgs[dev->msg_write_idx].flags & I2C_M_TEN)
3422373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		ic_con |= DW_IC_CON_10BITADDR_MASTER;
3432373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	else
3442373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
3452373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	dw_writel(dev, ic_con, DW_IC_CON);
3462373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
3472373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	/* Enable the adapter */
3482373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	dw_writel(dev, 1, DW_IC_ENABLE);
3492373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
3502373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	/* Enable interrupts */
3512373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK);
3522373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie}
3532373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
3542373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie/*
3552373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * Initiate (and continue) low level master read/write transaction.
3562373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * This function is only called from i2c_dw_isr, and pumping i2c_msg
3572373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * messages into the tx buffer.  Even if the size of i2c_msg data is
3582373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * longer than the size of the tx buffer, it handles everything.
3592373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie */
3602373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewievoid
3612373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewiei2c_dw_xfer_msg(struct dw_i2c_dev *dev)
3622373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie{
3632373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	struct i2c_msg *msgs = dev->msgs;
3642373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	u32 intr_mask;
3652373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	int tx_limit, rx_limit;
3662373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	u32 addr = msgs[dev->msg_write_idx].addr;
3672373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	u32 buf_len = dev->tx_buf_len;
3682373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	u8 *buf = dev->tx_buf;
3692373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
3702373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	intr_mask = DW_IC_INTR_DEFAULT_MASK;
3712373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
3722373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) {
3732373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		/*
3742373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 * if target address has changed, we need to
3752373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 * reprogram the target address in the i2c
3762373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 * adapter when we are done with this transfer
3772373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 */
3782373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		if (msgs[dev->msg_write_idx].addr != addr) {
3792373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			dev_err(dev->dev,
3802373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie				"%s: invalid target address\n", __func__);
3812373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			dev->msg_err = -EINVAL;
3822373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			break;
3832373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		}
3842373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
3852373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		if (msgs[dev->msg_write_idx].len == 0) {
3862373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			dev_err(dev->dev,
3872373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie				"%s: invalid message length\n", __func__);
3882373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			dev->msg_err = -EINVAL;
3892373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			break;
3902373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		}
3912373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
3922373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) {
3932373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			/* new i2c_msg */
3942373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			buf = msgs[dev->msg_write_idx].buf;
3952373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			buf_len = msgs[dev->msg_write_idx].len;
3962373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		}
3972373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
3982373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		tx_limit = dev->tx_fifo_depth - dw_readl(dev, DW_IC_TXFLR);
3992373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		rx_limit = dev->rx_fifo_depth - dw_readl(dev, DW_IC_RXFLR);
4002373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
4012373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) {
4022373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			if (msgs[dev->msg_write_idx].flags & I2C_M_RD) {
4032373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie				dw_writel(dev, 0x100, DW_IC_DATA_CMD);
4042373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie				rx_limit--;
4052373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			} else
4062373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie				dw_writel(dev, *buf++, DW_IC_DATA_CMD);
4072373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			tx_limit--; buf_len--;
4082373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		}
4092373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
4102373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		dev->tx_buf = buf;
4112373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		dev->tx_buf_len = buf_len;
4122373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
4132373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		if (buf_len > 0) {
4142373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			/* more bytes to be written */
4152373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			dev->status |= STATUS_WRITE_IN_PROGRESS;
4162373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			break;
4172373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		} else
4182373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			dev->status &= ~STATUS_WRITE_IN_PROGRESS;
4192373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	}
4202373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
4212373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	/*
4222373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 * If i2c_msg index search is completed, we don't need TX_EMPTY
4232373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 * interrupt any more.
4242373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 */
4252373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (dev->msg_write_idx == dev->msgs_num)
4262373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		intr_mask &= ~DW_IC_INTR_TX_EMPTY;
4272373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
4282373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (dev->msg_err)
4292373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		intr_mask = 0;
4302373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
4312373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	dw_writel(dev, intr_mask,  DW_IC_INTR_MASK);
4322373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie}
4332373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
4342373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewiestatic void
4352373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewiei2c_dw_read(struct dw_i2c_dev *dev)
4362373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie{
4372373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	struct i2c_msg *msgs = dev->msgs;
4382373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	int rx_valid;
4392373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
4402373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	for (; dev->msg_read_idx < dev->msgs_num; dev->msg_read_idx++) {
4412373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		u32 len;
4422373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		u8 *buf;
4432373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
4442373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		if (!(msgs[dev->msg_read_idx].flags & I2C_M_RD))
4452373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			continue;
4462373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
4472373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		if (!(dev->status & STATUS_READ_IN_PROGRESS)) {
4482373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			len = msgs[dev->msg_read_idx].len;
4492373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			buf = msgs[dev->msg_read_idx].buf;
4502373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		} else {
4512373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			len = dev->rx_buf_len;
4522373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			buf = dev->rx_buf;
4532373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		}
4542373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
4552373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		rx_valid = dw_readl(dev, DW_IC_RXFLR);
4562373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
4572373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		for (; len > 0 && rx_valid > 0; len--, rx_valid--)
4582373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			*buf++ = dw_readl(dev, DW_IC_DATA_CMD);
4592373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
4602373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		if (len > 0) {
4612373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			dev->status |= STATUS_READ_IN_PROGRESS;
4622373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			dev->rx_buf_len = len;
4632373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			dev->rx_buf = buf;
4642373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			return;
4652373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		} else
4662373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			dev->status &= ~STATUS_READ_IN_PROGRESS;
4672373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	}
4682373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie}
4692373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
4702373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewiestatic int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
4712373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie{
4722373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	unsigned long abort_source = dev->abort_source;
4732373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	int i;
4742373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
4752373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (abort_source & DW_IC_TX_ABRT_NOACK) {
4762373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
4772373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie			dev_dbg(dev->dev,
4782373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie				"%s: %s\n", __func__, abort_sources[i]);
4792373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		return -EREMOTEIO;
4802373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	}
4812373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
4822373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
4832373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]);
4842373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
4852373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (abort_source & DW_IC_TX_ARB_LOST)
4862373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		return -EAGAIN;
4872373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	else if (abort_source & DW_IC_TX_ABRT_GCALL_READ)
4882373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		return -EINVAL; /* wrong msgs[] data */
4892373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	else
4902373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		return -EIO;
4912373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie}
4922373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
4932373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie/*
4942373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * Prepare controller for a transaction and call i2c_dw_xfer_msg
4952373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie */
4962373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewieint
4972373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewiei2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
4982373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie{
4992373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
5002373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	int ret;
5012373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
5022373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);
5032373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
5042373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	mutex_lock(&dev->lock);
50518dbdda89f5cf0540e577280395f16079308e87dDirk Brandewie	pm_runtime_get_sync(dev->dev);
5062373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
5072373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	INIT_COMPLETION(dev->cmd_complete);
5082373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	dev->msgs = msgs;
5092373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	dev->msgs_num = num;
5102373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	dev->cmd_err = 0;
5112373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	dev->msg_write_idx = 0;
5122373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	dev->msg_read_idx = 0;
5132373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	dev->msg_err = 0;
5142373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	dev->status = STATUS_IDLE;
5152373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	dev->abort_source = 0;
5162373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
5172373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	ret = i2c_dw_wait_bus_not_busy(dev);
5182373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (ret < 0)
5192373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		goto done;
5202373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
5212373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	/* start the transfers */
5222373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	i2c_dw_xfer_init(dev);
5232373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
5242373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	/* wait for tx to complete */
5252373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, HZ);
5262373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (ret == 0) {
5272373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		dev_err(dev->dev, "controller timed out\n");
5282373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		i2c_dw_init(dev);
5292373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		ret = -ETIMEDOUT;
5302373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		goto done;
5312373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	} else if (ret < 0)
5322373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		goto done;
5332373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
5342373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (dev->msg_err) {
5352373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		ret = dev->msg_err;
5362373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		goto done;
5372373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	}
5382373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
5392373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	/* no error */
5402373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (likely(!dev->cmd_err)) {
5412373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		/* Disable the adapter */
5422373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		dw_writel(dev, 0, DW_IC_ENABLE);
5432373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		ret = num;
5442373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		goto done;
5452373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	}
5462373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
5472373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	/* We have an error */
5482373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (dev->cmd_err == DW_IC_ERR_TX_ABRT) {
5492373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		ret = i2c_dw_handle_tx_abort(dev);
5502373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		goto done;
5512373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	}
5522373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	ret = -EIO;
5532373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
5542373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewiedone:
55518dbdda89f5cf0540e577280395f16079308e87dDirk Brandewie	pm_runtime_put(dev->dev);
5562373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	mutex_unlock(&dev->lock);
5572373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
5582373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	return ret;
5592373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie}
5602373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
5612373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewieu32 i2c_dw_func(struct i2c_adapter *adap)
5622373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie{
5632fa8326b4b1e5fdc889b57b03b1313f3229cb438Dirk Brandewie	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
5642fa8326b4b1e5fdc889b57b03b1313f3229cb438Dirk Brandewie	return dev->functionality;
5652373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie}
5662373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
5672373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewiestatic u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
5682373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie{
5692373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	u32 stat;
5702373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
5712373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	/*
5722373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 * The IC_INTR_STAT register just indicates "enabled" interrupts.
5732373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 * Ths unmasked raw version of interrupt status bits are available
5742373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 * in the IC_RAW_INTR_STAT register.
5752373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 *
5762373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 * That is,
5772373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 *   stat = dw_readl(IC_INTR_STAT);
5782373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 * equals to,
5792373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 *   stat = dw_readl(IC_RAW_INTR_STAT) & dw_readl(IC_INTR_MASK);
5802373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 *
5812373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 * The raw version might be useful for debugging purposes.
5822373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 */
5832373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	stat = dw_readl(dev, DW_IC_INTR_STAT);
5842373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
5852373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	/*
5862373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 * Do not use the IC_CLR_INTR register to clear interrupts, or
5872373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 * you'll miss some interrupts, triggered during the period from
5882373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 * dw_readl(IC_INTR_STAT) to dw_readl(IC_CLR_INTR).
5892373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 *
5902373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 * Instead, use the separately-prepared IC_CLR_* registers.
5912373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 */
5922373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (stat & DW_IC_INTR_RX_UNDER)
5932373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		dw_readl(dev, DW_IC_CLR_RX_UNDER);
5942373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (stat & DW_IC_INTR_RX_OVER)
5952373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		dw_readl(dev, DW_IC_CLR_RX_OVER);
5962373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (stat & DW_IC_INTR_TX_OVER)
5972373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		dw_readl(dev, DW_IC_CLR_TX_OVER);
5982373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (stat & DW_IC_INTR_RD_REQ)
5992373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		dw_readl(dev, DW_IC_CLR_RD_REQ);
6002373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (stat & DW_IC_INTR_TX_ABRT) {
6012373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		/*
6022373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 * The IC_TX_ABRT_SOURCE register is cleared whenever
6032373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 * the IC_CLR_TX_ABRT is read.  Preserve it beforehand.
6042373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 */
6052373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		dev->abort_source = dw_readl(dev, DW_IC_TX_ABRT_SOURCE);
6062373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		dw_readl(dev, DW_IC_CLR_TX_ABRT);
6072373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	}
6082373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (stat & DW_IC_INTR_RX_DONE)
6092373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		dw_readl(dev, DW_IC_CLR_RX_DONE);
6102373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (stat & DW_IC_INTR_ACTIVITY)
6112373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		dw_readl(dev, DW_IC_CLR_ACTIVITY);
6122373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (stat & DW_IC_INTR_STOP_DET)
6132373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		dw_readl(dev, DW_IC_CLR_STOP_DET);
6142373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (stat & DW_IC_INTR_START_DET)
6152373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		dw_readl(dev, DW_IC_CLR_START_DET);
6162373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (stat & DW_IC_INTR_GEN_CALL)
6172373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		dw_readl(dev, DW_IC_CLR_GEN_CALL);
6182373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
6192373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	return stat;
6202373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie}
6212373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
6222373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie/*
6232373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * Interrupt service routine. This gets called whenever an I2C interrupt
6242373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie * occurs.
6252373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie */
6262373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewieirqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
6272373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie{
6282373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	struct dw_i2c_dev *dev = dev_id;
629af06cf6c8cb600803951ddabe6fb034126752488Dirk Brandewie	u32 stat, enabled;
630af06cf6c8cb600803951ddabe6fb034126752488Dirk Brandewie
631af06cf6c8cb600803951ddabe6fb034126752488Dirk Brandewie	enabled = dw_readl(dev, DW_IC_ENABLE);
632af06cf6c8cb600803951ddabe6fb034126752488Dirk Brandewie	stat = dw_readl(dev, DW_IC_RAW_INTR_STAT);
633af06cf6c8cb600803951ddabe6fb034126752488Dirk Brandewie	dev_dbg(dev->dev, "%s:  %s enabled= 0x%x stat=0x%x\n", __func__,
634af06cf6c8cb600803951ddabe6fb034126752488Dirk Brandewie		dev->adapter.name, enabled, stat);
635af06cf6c8cb600803951ddabe6fb034126752488Dirk Brandewie	if (!enabled || !(stat & ~DW_IC_INTR_ACTIVITY))
636af06cf6c8cb600803951ddabe6fb034126752488Dirk Brandewie		return IRQ_NONE;
6372373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
6382373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	stat = i2c_dw_read_clear_intrbits(dev);
6392373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
6402373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (stat & DW_IC_INTR_TX_ABRT) {
6412373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		dev->cmd_err |= DW_IC_ERR_TX_ABRT;
6422373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		dev->status = STATUS_IDLE;
6432373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
6442373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		/*
6452373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 * Anytime TX_ABRT is set, the contents of the tx/rx
6462373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 * buffers are flushed.  Make sure to skip them.
6472373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		 */
6482373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		dw_writel(dev, 0, DW_IC_INTR_MASK);
6492373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		goto tx_aborted;
6502373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	}
6512373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
6522373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (stat & DW_IC_INTR_RX_FULL)
6532373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		i2c_dw_read(dev);
6542373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
6552373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if (stat & DW_IC_INTR_TX_EMPTY)
6562373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		i2c_dw_xfer_msg(dev);
6572373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
6582373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	/*
6592373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 * No need to modify or disable the interrupt mask here.
6602373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 * i2c_dw_xfer_msg() will take care of it according to
6612373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 * the current transmit status.
6622373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	 */
6632373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
6642373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewietx_aborted:
6652373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err)
6662373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie		complete(&dev->cmd_complete);
6672373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie
6682373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie	return IRQ_HANDLED;
6692373f6b9744d5373b886f3ce1a985193cca0a356Dirk Brandewie}
670f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie
671f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewievoid i2c_dw_enable(struct dw_i2c_dev *dev)
672f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie{
673f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie       /* Enable the adapter */
674f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie	dw_writel(dev, 1, DW_IC_ENABLE);
675f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie}
676f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie
67718dbdda89f5cf0540e577280395f16079308e87dDirk Brandewieu32 i2c_dw_is_enabled(struct dw_i2c_dev *dev)
678f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie{
67918dbdda89f5cf0540e577280395f16079308e87dDirk Brandewie	return dw_readl(dev, DW_IC_ENABLE);
68018dbdda89f5cf0540e577280395f16079308e87dDirk Brandewie}
681f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie
68218dbdda89f5cf0540e577280395f16079308e87dDirk Brandewievoid i2c_dw_disable(struct dw_i2c_dev *dev)
68318dbdda89f5cf0540e577280395f16079308e87dDirk Brandewie{
684f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie	/* Disable controller */
685f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie	dw_writel(dev, 0, DW_IC_ENABLE);
686f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie
687f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie	/* Disable all interupts */
688f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie	dw_writel(dev, 0, DW_IC_INTR_MASK);
689f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie	dw_readl(dev, DW_IC_CLR_INTR);
690f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie}
691f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie
692f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewievoid i2c_dw_clear_int(struct dw_i2c_dev *dev)
693f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie{
694f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie	dw_readl(dev, DW_IC_CLR_INTR);
695f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie}
696f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie
697f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewievoid i2c_dw_disable_int(struct dw_i2c_dev *dev)
698f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie{
699f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie	dw_writel(dev, 0, DW_IC_INTR_MASK);
700f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie}
701f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie
702f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewieu32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev)
703f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie{
704f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie	return dw_readl(dev, DW_IC_COMP_PARAM_1);
705f3fa9f3da5621154323775ff0efdba99dcebcee4Dirk Brandewie}
706