xref: /rk3399_rockchip-uboot/drivers/i2c/s3c24x0_i2c.c (revision 45d9ae87cbe9b2e76a856647c35da83535af2984)
1d3b63577SJean-Christophe PLAGNIOL-VILLARD /*
2d3b63577SJean-Christophe PLAGNIOL-VILLARD  * (C) Copyright 2002
3d3b63577SJean-Christophe PLAGNIOL-VILLARD  * David Mueller, ELSOFT AG, d.mueller@elsoft.ch
4d3b63577SJean-Christophe PLAGNIOL-VILLARD  *
51a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
6d3b63577SJean-Christophe PLAGNIOL-VILLARD  */
7d3b63577SJean-Christophe PLAGNIOL-VILLARD 
8d3b63577SJean-Christophe PLAGNIOL-VILLARD /* This code should work for both the S3C2400 and the S3C2410
9d3b63577SJean-Christophe PLAGNIOL-VILLARD  * as they seem to have the same I2C controller inside.
10d3b63577SJean-Christophe PLAGNIOL-VILLARD  * The different address mapping is handled by the s3c24xx.h files below.
11d3b63577SJean-Christophe PLAGNIOL-VILLARD  */
12d3b63577SJean-Christophe PLAGNIOL-VILLARD #include <common.h>
138dfcbaa6SPrzemyslaw Marczak #include <errno.h>
148dfcbaa6SPrzemyslaw Marczak #include <dm.h>
15a9d2ae70SRajeshwari Shinde #include <fdtdec.h>
16c86d9ed3SPiotr Wilczek #if (defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
17ab7e52bbSRajeshwari Shinde #include <asm/arch/clk.h>
18ab7e52bbSRajeshwari Shinde #include <asm/arch/cpu.h>
19a9d2ae70SRajeshwari Shinde #include <asm/arch/pinmux.h>
20ab7e52bbSRajeshwari Shinde #else
21ac67804fSkevin.morfitt@fearnside-systems.co.uk #include <asm/arch/s3c24x0_cpu.h>
22ab7e52bbSRajeshwari Shinde #endif
23eb0ae7f5Skevin.morfitt@fearnside-systems.co.uk #include <asm/io.h>
24d3b63577SJean-Christophe PLAGNIOL-VILLARD #include <i2c.h>
25ab7e52bbSRajeshwari Shinde #include "s3c24x0_i2c.h"
26d3b63577SJean-Christophe PLAGNIOL-VILLARD 
27d3b63577SJean-Christophe PLAGNIOL-VILLARD #define	I2C_WRITE	0
28d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2C_READ	1
29d3b63577SJean-Christophe PLAGNIOL-VILLARD 
30d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2C_OK		0
31d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2C_NOK		1
32d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2C_NACK	2
33d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2C_NOK_LA	3	/* Lost arbitration */
34d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2C_NOK_TOUT	4	/* time out */
35d3b63577SJean-Christophe PLAGNIOL-VILLARD 
36296a461dSNaveen Krishna Ch /* HSI2C specific register description */
37296a461dSNaveen Krishna Ch 
38296a461dSNaveen Krishna Ch /* I2C_CTL Register bits */
39296a461dSNaveen Krishna Ch #define HSI2C_FUNC_MODE_I2C		(1u << 0)
40296a461dSNaveen Krishna Ch #define HSI2C_MASTER			(1u << 3)
41296a461dSNaveen Krishna Ch #define HSI2C_RXCHON			(1u << 6)	/* Write/Send */
42296a461dSNaveen Krishna Ch #define HSI2C_TXCHON			(1u << 7)	/* Read/Receive */
43296a461dSNaveen Krishna Ch #define HSI2C_SW_RST			(1u << 31)
44296a461dSNaveen Krishna Ch 
45296a461dSNaveen Krishna Ch /* I2C_FIFO_CTL Register bits */
46296a461dSNaveen Krishna Ch #define HSI2C_RXFIFO_EN			(1u << 0)
47296a461dSNaveen Krishna Ch #define HSI2C_TXFIFO_EN			(1u << 1)
48296a461dSNaveen Krishna Ch #define HSI2C_TXFIFO_TRIGGER_LEVEL	(0x20 << 16)
49296a461dSNaveen Krishna Ch #define HSI2C_RXFIFO_TRIGGER_LEVEL	(0x20 << 4)
50296a461dSNaveen Krishna Ch 
51296a461dSNaveen Krishna Ch /* I2C_TRAILING_CTL Register bits */
52296a461dSNaveen Krishna Ch #define HSI2C_TRAILING_COUNT		(0xff)
53296a461dSNaveen Krishna Ch 
54296a461dSNaveen Krishna Ch /* I2C_INT_EN Register bits */
55296a461dSNaveen Krishna Ch #define HSI2C_TX_UNDERRUN_EN		(1u << 2)
56296a461dSNaveen Krishna Ch #define HSI2C_TX_OVERRUN_EN		(1u << 3)
57296a461dSNaveen Krishna Ch #define HSI2C_RX_UNDERRUN_EN		(1u << 4)
58296a461dSNaveen Krishna Ch #define HSI2C_RX_OVERRUN_EN		(1u << 5)
59296a461dSNaveen Krishna Ch #define HSI2C_INT_TRAILING_EN		(1u << 6)
60296a461dSNaveen Krishna Ch #define HSI2C_INT_I2C_EN		(1u << 9)
61296a461dSNaveen Krishna Ch 
62296a461dSNaveen Krishna Ch #define HSI2C_INT_ERROR_MASK	(HSI2C_TX_UNDERRUN_EN |\
63296a461dSNaveen Krishna Ch 				 HSI2C_TX_OVERRUN_EN  |\
64296a461dSNaveen Krishna Ch 				 HSI2C_RX_UNDERRUN_EN |\
65296a461dSNaveen Krishna Ch 				 HSI2C_RX_OVERRUN_EN  |\
66296a461dSNaveen Krishna Ch 				 HSI2C_INT_TRAILING_EN)
67296a461dSNaveen Krishna Ch 
68296a461dSNaveen Krishna Ch /* I2C_CONF Register bits */
69296a461dSNaveen Krishna Ch #define HSI2C_AUTO_MODE			(1u << 31)
70296a461dSNaveen Krishna Ch #define HSI2C_10BIT_ADDR_MODE		(1u << 30)
71296a461dSNaveen Krishna Ch #define HSI2C_HS_MODE			(1u << 29)
72296a461dSNaveen Krishna Ch 
73296a461dSNaveen Krishna Ch /* I2C_AUTO_CONF Register bits */
74296a461dSNaveen Krishna Ch #define HSI2C_READ_WRITE		(1u << 16)
75296a461dSNaveen Krishna Ch #define HSI2C_STOP_AFTER_TRANS		(1u << 17)
76296a461dSNaveen Krishna Ch #define HSI2C_MASTER_RUN		(1u << 31)
77296a461dSNaveen Krishna Ch 
78296a461dSNaveen Krishna Ch /* I2C_TIMEOUT Register bits */
79296a461dSNaveen Krishna Ch #define HSI2C_TIMEOUT_EN		(1u << 31)
80296a461dSNaveen Krishna Ch 
81296a461dSNaveen Krishna Ch /* I2C_TRANS_STATUS register bits */
82296a461dSNaveen Krishna Ch #define HSI2C_MASTER_BUSY		(1u << 17)
83296a461dSNaveen Krishna Ch #define HSI2C_SLAVE_BUSY		(1u << 16)
84296a461dSNaveen Krishna Ch #define HSI2C_TIMEOUT_AUTO		(1u << 4)
85296a461dSNaveen Krishna Ch #define HSI2C_NO_DEV			(1u << 3)
86296a461dSNaveen Krishna Ch #define HSI2C_NO_DEV_ACK		(1u << 2)
87296a461dSNaveen Krishna Ch #define HSI2C_TRANS_ABORT		(1u << 1)
88296a461dSNaveen Krishna Ch #define HSI2C_TRANS_SUCCESS		(1u << 0)
89296a461dSNaveen Krishna Ch #define HSI2C_TRANS_ERROR_MASK	(HSI2C_TIMEOUT_AUTO |\
90296a461dSNaveen Krishna Ch 				 HSI2C_NO_DEV | HSI2C_NO_DEV_ACK |\
91296a461dSNaveen Krishna Ch 				 HSI2C_TRANS_ABORT)
92296a461dSNaveen Krishna Ch #define HSI2C_TRANS_FINISHED_MASK (HSI2C_TRANS_ERROR_MASK | HSI2C_TRANS_SUCCESS)
93296a461dSNaveen Krishna Ch 
94296a461dSNaveen Krishna Ch 
95296a461dSNaveen Krishna Ch /* I2C_FIFO_STAT Register bits */
96296a461dSNaveen Krishna Ch #define HSI2C_RX_FIFO_EMPTY		(1u << 24)
97296a461dSNaveen Krishna Ch #define HSI2C_RX_FIFO_FULL		(1u << 23)
98296a461dSNaveen Krishna Ch #define HSI2C_TX_FIFO_EMPTY		(1u << 8)
99296a461dSNaveen Krishna Ch #define HSI2C_TX_FIFO_FULL		(1u << 7)
100296a461dSNaveen Krishna Ch #define HSI2C_RX_FIFO_LEVEL(x)		(((x) >> 16) & 0x7f)
101296a461dSNaveen Krishna Ch #define HSI2C_TX_FIFO_LEVEL(x)		((x) & 0x7f)
102296a461dSNaveen Krishna Ch 
103296a461dSNaveen Krishna Ch #define HSI2C_SLV_ADDR_MAS(x)		((x & 0x3ff) << 10)
104296a461dSNaveen Krishna Ch 
105296a461dSNaveen Krishna Ch /* S3C I2C Controller bits */
106d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2CSTAT_BSY	0x20	/* Busy bit */
107d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2CSTAT_NACK	0x01	/* Nack bit */
108ab7e52bbSRajeshwari Shinde #define I2CCON_ACKGEN	0x80	/* Acknowledge generation */
109d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2CCON_IRPND	0x10	/* Interrupt pending bit */
110d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2C_MODE_MT	0xC0	/* Master Transmit Mode */
111d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2C_MODE_MR	0x80	/* Master Receive Mode */
112d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2C_START_STOP	0x20	/* START / STOP */
113d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2C_TXRX_ENA	0x10	/* I2C Tx/Rx enable */
114d3b63577SJean-Christophe PLAGNIOL-VILLARD 
115a3e757a5SPrzemyslaw Marczak #define I2C_TIMEOUT_MS 10		/* 10 ms */
116d3b63577SJean-Christophe PLAGNIOL-VILLARD 
117a3e757a5SPrzemyslaw Marczak #define	HSI2C_TIMEOUT_US 10000 /* 10 ms, finer granularity */
118296a461dSNaveen Krishna Ch 
119296a461dSNaveen Krishna Ch 
120296a461dSNaveen Krishna Ch /* To support VCMA9 boards and other who dont define max_i2c_num */
121296a461dSNaveen Krishna Ch #ifndef CONFIG_MAX_I2C_NUM
122296a461dSNaveen Krishna Ch #define CONFIG_MAX_I2C_NUM 1
123296a461dSNaveen Krishna Ch #endif
124ab7e52bbSRajeshwari Shinde 
1258dfcbaa6SPrzemyslaw Marczak DECLARE_GLOBAL_DATA_PTR;
1268dfcbaa6SPrzemyslaw Marczak 
127a9d2ae70SRajeshwari Shinde /*
128a9d2ae70SRajeshwari Shinde  * For SPL boot some boards need i2c before SDRAM is initialised so force
129a9d2ae70SRajeshwari Shinde  * variables to live in SRAM
130a9d2ae70SRajeshwari Shinde  */
1318dfcbaa6SPrzemyslaw Marczak #ifdef CONFIG_SYS_I2C
132a9d2ae70SRajeshwari Shinde static struct s3c24x0_i2c_bus i2c_bus[CONFIG_MAX_I2C_NUM]
133a9d2ae70SRajeshwari Shinde 			__attribute__((section(".data")));
1348dfcbaa6SPrzemyslaw Marczak #endif
135296a461dSNaveen Krishna Ch 
1368dfcbaa6SPrzemyslaw Marczak enum exynos_i2c_type {
1378dfcbaa6SPrzemyslaw Marczak 	EXYNOS_I2C_STD,
1388dfcbaa6SPrzemyslaw Marczak 	EXYNOS_I2C_HS,
1398dfcbaa6SPrzemyslaw Marczak };
1408dfcbaa6SPrzemyslaw Marczak 
1418dfcbaa6SPrzemyslaw Marczak #ifdef CONFIG_SYS_I2C
142296a461dSNaveen Krishna Ch /**
143296a461dSNaveen Krishna Ch  * Get a pointer to the given bus index
144296a461dSNaveen Krishna Ch  *
145296a461dSNaveen Krishna Ch  * @bus_idx: Bus index to look up
146296a461dSNaveen Krishna Ch  * @return pointer to bus, or NULL if invalid or not available
147296a461dSNaveen Krishna Ch  */
148296a461dSNaveen Krishna Ch static struct s3c24x0_i2c_bus *get_bus(unsigned int bus_idx)
149296a461dSNaveen Krishna Ch {
150296a461dSNaveen Krishna Ch 	if (bus_idx < ARRAY_SIZE(i2c_bus)) {
151296a461dSNaveen Krishna Ch 		struct s3c24x0_i2c_bus *bus;
152296a461dSNaveen Krishna Ch 
153296a461dSNaveen Krishna Ch 		bus = &i2c_bus[bus_idx];
154296a461dSNaveen Krishna Ch 		if (bus->active)
155296a461dSNaveen Krishna Ch 			return bus;
156296a461dSNaveen Krishna Ch 	}
157296a461dSNaveen Krishna Ch 
158296a461dSNaveen Krishna Ch 	debug("Undefined bus: %d\n", bus_idx);
159296a461dSNaveen Krishna Ch 	return NULL;
160296a461dSNaveen Krishna Ch }
1618dfcbaa6SPrzemyslaw Marczak #endif
162ab7e52bbSRajeshwari Shinde 
163c86d9ed3SPiotr Wilczek #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
164d3b63577SJean-Christophe PLAGNIOL-VILLARD static int GetI2CSDA(void)
165d3b63577SJean-Christophe PLAGNIOL-VILLARD {
166eb0ae7f5Skevin.morfitt@fearnside-systems.co.uk 	struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
167d3b63577SJean-Christophe PLAGNIOL-VILLARD 
1687b0c0f69SMarek Vasut #if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
169d9abba82SC Nauman 	return (readl(&gpio->gpedat) & 0x8000) >> 15;
170d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif
171d3b63577SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_S3C2400
172d9abba82SC Nauman 	return (readl(&gpio->pgdat) & 0x0020) >> 5;
173d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif
174d3b63577SJean-Christophe PLAGNIOL-VILLARD }
175d3b63577SJean-Christophe PLAGNIOL-VILLARD 
176d3b63577SJean-Christophe PLAGNIOL-VILLARD static void SetI2CSCL(int x)
177d3b63577SJean-Christophe PLAGNIOL-VILLARD {
178eb0ae7f5Skevin.morfitt@fearnside-systems.co.uk 	struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
179d3b63577SJean-Christophe PLAGNIOL-VILLARD 
1807b0c0f69SMarek Vasut #if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
181ab7e52bbSRajeshwari Shinde 	writel((readl(&gpio->gpedat) & ~0x4000) |
182ab7e52bbSRajeshwari Shinde 					(x & 1) << 14, &gpio->gpedat);
183d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif
184d3b63577SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_S3C2400
185d9abba82SC Nauman 	writel((readl(&gpio->pgdat) & ~0x0040) | (x & 1) << 6, &gpio->pgdat);
186d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif
187d3b63577SJean-Christophe PLAGNIOL-VILLARD }
188ab7e52bbSRajeshwari Shinde #endif
189d3b63577SJean-Christophe PLAGNIOL-VILLARD 
190e4e24020SNaveen Krishna Ch /*
191e4e24020SNaveen Krishna Ch  * Wait til the byte transfer is completed.
192e4e24020SNaveen Krishna Ch  *
193e4e24020SNaveen Krishna Ch  * @param i2c- pointer to the appropriate i2c register bank.
194e4e24020SNaveen Krishna Ch  * @return I2C_OK, if transmission was ACKED
195e4e24020SNaveen Krishna Ch  *         I2C_NACK, if transmission was NACKED
196e4e24020SNaveen Krishna Ch  *         I2C_NOK_TIMEOUT, if transaction did not complete in I2C_TIMEOUT_MS
197e4e24020SNaveen Krishna Ch  */
198e4e24020SNaveen Krishna Ch 
199ab7e52bbSRajeshwari Shinde static int WaitForXfer(struct s3c24x0_i2c *i2c)
200d3b63577SJean-Christophe PLAGNIOL-VILLARD {
201e4e24020SNaveen Krishna Ch 	ulong start_time = get_timer(0);
202d3b63577SJean-Christophe PLAGNIOL-VILLARD 
203e4e24020SNaveen Krishna Ch 	do {
204e4e24020SNaveen Krishna Ch 		if (readl(&i2c->iiccon) & I2CCON_IRPND)
205e4e24020SNaveen Krishna Ch 			return (readl(&i2c->iicstat) & I2CSTAT_NACK) ?
206e4e24020SNaveen Krishna Ch 				I2C_NACK : I2C_OK;
207e4e24020SNaveen Krishna Ch 	} while (get_timer(start_time) < I2C_TIMEOUT_MS);
208d3b63577SJean-Christophe PLAGNIOL-VILLARD 
209e4e24020SNaveen Krishna Ch 	return I2C_NOK_TOUT;
210d3b63577SJean-Christophe PLAGNIOL-VILLARD }
211d3b63577SJean-Christophe PLAGNIOL-VILLARD 
212296a461dSNaveen Krishna Ch /*
213296a461dSNaveen Krishna Ch  * Wait for transfer completion.
214296a461dSNaveen Krishna Ch  *
215296a461dSNaveen Krishna Ch  * This function reads the interrupt status register waiting for the INT_I2C
216296a461dSNaveen Krishna Ch  * bit to be set, which indicates copletion of a transaction.
217296a461dSNaveen Krishna Ch  *
218296a461dSNaveen Krishna Ch  * @param i2c: pointer to the appropriate register bank
219296a461dSNaveen Krishna Ch  *
220296a461dSNaveen Krishna Ch  * @return: I2C_OK in case of successful completion, I2C_NOK_TIMEOUT in case
221296a461dSNaveen Krishna Ch  *          the status bits do not get set in time, or an approrpiate error
222296a461dSNaveen Krishna Ch  *          value in case of transfer errors.
223296a461dSNaveen Krishna Ch  */
224296a461dSNaveen Krishna Ch static int hsi2c_wait_for_trx(struct exynos5_hsi2c *i2c)
225296a461dSNaveen Krishna Ch {
226296a461dSNaveen Krishna Ch 	int i = HSI2C_TIMEOUT_US;
227296a461dSNaveen Krishna Ch 
228296a461dSNaveen Krishna Ch 	while (i-- > 0) {
229296a461dSNaveen Krishna Ch 		u32 int_status = readl(&i2c->usi_int_stat);
230296a461dSNaveen Krishna Ch 
231296a461dSNaveen Krishna Ch 		if (int_status & HSI2C_INT_I2C_EN) {
232296a461dSNaveen Krishna Ch 			u32 trans_status = readl(&i2c->usi_trans_status);
233296a461dSNaveen Krishna Ch 
234296a461dSNaveen Krishna Ch 			/* Deassert pending interrupt. */
235296a461dSNaveen Krishna Ch 			writel(int_status, &i2c->usi_int_stat);
236296a461dSNaveen Krishna Ch 
237296a461dSNaveen Krishna Ch 			if (trans_status & HSI2C_NO_DEV_ACK) {
238296a461dSNaveen Krishna Ch 				debug("%s: no ACK from device\n", __func__);
239296a461dSNaveen Krishna Ch 				return I2C_NACK;
240296a461dSNaveen Krishna Ch 			}
241296a461dSNaveen Krishna Ch 			if (trans_status & HSI2C_NO_DEV) {
242296a461dSNaveen Krishna Ch 				debug("%s: no device\n", __func__);
243296a461dSNaveen Krishna Ch 				return I2C_NOK;
244296a461dSNaveen Krishna Ch 			}
245296a461dSNaveen Krishna Ch 			if (trans_status & HSI2C_TRANS_ABORT) {
246296a461dSNaveen Krishna Ch 				debug("%s: arbitration lost\n", __func__);
247296a461dSNaveen Krishna Ch 				return I2C_NOK_LA;
248296a461dSNaveen Krishna Ch 			}
249296a461dSNaveen Krishna Ch 			if (trans_status & HSI2C_TIMEOUT_AUTO) {
250296a461dSNaveen Krishna Ch 				debug("%s: device timed out\n", __func__);
251296a461dSNaveen Krishna Ch 				return I2C_NOK_TOUT;
252296a461dSNaveen Krishna Ch 			}
253296a461dSNaveen Krishna Ch 			return I2C_OK;
254296a461dSNaveen Krishna Ch 		}
255296a461dSNaveen Krishna Ch 		udelay(1);
256296a461dSNaveen Krishna Ch 	}
257296a461dSNaveen Krishna Ch 	debug("%s: transaction timeout!\n", __func__);
258296a461dSNaveen Krishna Ch 	return I2C_NOK_TOUT;
259296a461dSNaveen Krishna Ch }
260296a461dSNaveen Krishna Ch 
26126ea7685SSimon Glass static void read_write_byte(struct s3c24x0_i2c *i2c)
262d3b63577SJean-Christophe PLAGNIOL-VILLARD {
26326ea7685SSimon Glass 	clrbits_le32(&i2c->iiccon, I2CCON_IRPND);
264d3b63577SJean-Christophe PLAGNIOL-VILLARD }
265d3b63577SJean-Christophe PLAGNIOL-VILLARD 
2668dfcbaa6SPrzemyslaw Marczak #ifdef CONFIG_SYS_I2C
2672d8f1e27SPiotr Wilczek static struct s3c24x0_i2c *get_base_i2c(int bus)
268ab7e52bbSRajeshwari Shinde {
269c86d9ed3SPiotr Wilczek #ifdef CONFIG_EXYNOS4
270c86d9ed3SPiotr Wilczek 	struct s3c24x0_i2c *i2c = (struct s3c24x0_i2c *)(samsung_get_base_i2c()
271c86d9ed3SPiotr Wilczek 							+ (EXYNOS4_I2C_SPACING
2722d8f1e27SPiotr Wilczek 							* bus));
273c86d9ed3SPiotr Wilczek 	return i2c;
274c86d9ed3SPiotr Wilczek #elif defined CONFIG_EXYNOS5
275ab7e52bbSRajeshwari Shinde 	struct s3c24x0_i2c *i2c = (struct s3c24x0_i2c *)(samsung_get_base_i2c()
276ab7e52bbSRajeshwari Shinde 							+ (EXYNOS5_I2C_SPACING
2772d8f1e27SPiotr Wilczek 							* bus));
278ab7e52bbSRajeshwari Shinde 	return i2c;
279ab7e52bbSRajeshwari Shinde #else
280ab7e52bbSRajeshwari Shinde 	return s3c24x0_get_base_i2c();
281ab7e52bbSRajeshwari Shinde #endif
282ab7e52bbSRajeshwari Shinde }
2838dfcbaa6SPrzemyslaw Marczak #endif
284ab7e52bbSRajeshwari Shinde 
285ab7e52bbSRajeshwari Shinde static void i2c_ch_init(struct s3c24x0_i2c *i2c, int speed, int slaveadd)
286ab7e52bbSRajeshwari Shinde {
287ab7e52bbSRajeshwari Shinde 	ulong freq, pres = 16, div;
288c86d9ed3SPiotr Wilczek #if (defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
289ab7e52bbSRajeshwari Shinde 	freq = get_i2c_clk();
290ab7e52bbSRajeshwari Shinde #else
291ab7e52bbSRajeshwari Shinde 	freq = get_PCLK();
292ab7e52bbSRajeshwari Shinde #endif
293ab7e52bbSRajeshwari Shinde 	/* calculate prescaler and divisor values */
294ab7e52bbSRajeshwari Shinde 	if ((freq / pres / (16 + 1)) > speed)
295ab7e52bbSRajeshwari Shinde 		/* set prescaler to 512 */
296ab7e52bbSRajeshwari Shinde 		pres = 512;
297ab7e52bbSRajeshwari Shinde 
298ab7e52bbSRajeshwari Shinde 	div = 0;
299ab7e52bbSRajeshwari Shinde 	while ((freq / pres / (div + 1)) > speed)
300ab7e52bbSRajeshwari Shinde 		div++;
301ab7e52bbSRajeshwari Shinde 
302ab7e52bbSRajeshwari Shinde 	/* set prescaler, divisor according to freq, also set ACKGEN, IRQ */
303ab7e52bbSRajeshwari Shinde 	writel((div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0), &i2c->iiccon);
304ab7e52bbSRajeshwari Shinde 
305ab7e52bbSRajeshwari Shinde 	/* init to SLAVE REVEIVE and set slaveaddr */
306ab7e52bbSRajeshwari Shinde 	writel(0, &i2c->iicstat);
307ab7e52bbSRajeshwari Shinde 	writel(slaveadd, &i2c->iicadd);
308ab7e52bbSRajeshwari Shinde 	/* program Master Transmit (and implicit STOP) */
309ab7e52bbSRajeshwari Shinde 	writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat);
310ab7e52bbSRajeshwari Shinde }
311ab7e52bbSRajeshwari Shinde 
312296a461dSNaveen Krishna Ch static int hsi2c_get_clk_details(struct s3c24x0_i2c_bus *i2c_bus)
313296a461dSNaveen Krishna Ch {
314296a461dSNaveen Krishna Ch 	struct exynos5_hsi2c *hsregs = i2c_bus->hsregs;
315296a461dSNaveen Krishna Ch 	ulong clkin;
316296a461dSNaveen Krishna Ch 	unsigned int op_clk = i2c_bus->clock_frequency;
317296a461dSNaveen Krishna Ch 	unsigned int i = 0, utemp0 = 0, utemp1 = 0;
318296a461dSNaveen Krishna Ch 	unsigned int t_ftl_cycle;
319296a461dSNaveen Krishna Ch 
320a6756bbdSPiotr Wilczek #if (defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
321296a461dSNaveen Krishna Ch 	clkin = get_i2c_clk();
322a6756bbdSPiotr Wilczek #else
323a6756bbdSPiotr Wilczek 	clkin = get_PCLK();
324296a461dSNaveen Krishna Ch #endif
325296a461dSNaveen Krishna Ch 	/* FPCLK / FI2C =
326296a461dSNaveen Krishna Ch 	 * (CLK_DIV + 1) * (TSCLK_L + TSCLK_H + 2) + 8 + 2 * FLT_CYCLE
327296a461dSNaveen Krishna Ch 	 * uTemp0 = (CLK_DIV + 1) * (TSCLK_L + TSCLK_H + 2)
328296a461dSNaveen Krishna Ch 	 * uTemp1 = (TSCLK_L + TSCLK_H + 2)
329296a461dSNaveen Krishna Ch 	 * uTemp2 = TSCLK_L + TSCLK_H
330296a461dSNaveen Krishna Ch 	 */
331296a461dSNaveen Krishna Ch 	t_ftl_cycle = (readl(&hsregs->usi_conf) >> 16) & 0x7;
332296a461dSNaveen Krishna Ch 	utemp0 = (clkin / op_clk) - 8 - 2 * t_ftl_cycle;
333296a461dSNaveen Krishna Ch 
334296a461dSNaveen Krishna Ch 	/* CLK_DIV max is 256 */
335296a461dSNaveen Krishna Ch 	for (i = 0; i < 256; i++) {
336296a461dSNaveen Krishna Ch 		utemp1 = utemp0 / (i + 1);
337296a461dSNaveen Krishna Ch 		if ((utemp1 < 512) && (utemp1 > 4)) {
338296a461dSNaveen Krishna Ch 			i2c_bus->clk_cycle = utemp1 - 2;
339296a461dSNaveen Krishna Ch 			i2c_bus->clk_div = i;
340296a461dSNaveen Krishna Ch 			return 0;
341296a461dSNaveen Krishna Ch 		}
342296a461dSNaveen Krishna Ch 	}
3438dfcbaa6SPrzemyslaw Marczak 	return -EINVAL;
344296a461dSNaveen Krishna Ch }
345296a461dSNaveen Krishna Ch 
346296a461dSNaveen Krishna Ch static void hsi2c_ch_init(struct s3c24x0_i2c_bus *i2c_bus)
347296a461dSNaveen Krishna Ch {
348296a461dSNaveen Krishna Ch 	struct exynos5_hsi2c *hsregs = i2c_bus->hsregs;
349296a461dSNaveen Krishna Ch 	unsigned int t_sr_release;
350296a461dSNaveen Krishna Ch 	unsigned int n_clkdiv;
351296a461dSNaveen Krishna Ch 	unsigned int t_start_su, t_start_hd;
352296a461dSNaveen Krishna Ch 	unsigned int t_stop_su;
353296a461dSNaveen Krishna Ch 	unsigned int t_data_su, t_data_hd;
354296a461dSNaveen Krishna Ch 	unsigned int t_scl_l, t_scl_h;
355296a461dSNaveen Krishna Ch 	u32 i2c_timing_s1;
356296a461dSNaveen Krishna Ch 	u32 i2c_timing_s2;
357296a461dSNaveen Krishna Ch 	u32 i2c_timing_s3;
358296a461dSNaveen Krishna Ch 	u32 i2c_timing_sla;
359296a461dSNaveen Krishna Ch 
360296a461dSNaveen Krishna Ch 	n_clkdiv = i2c_bus->clk_div;
361296a461dSNaveen Krishna Ch 	t_scl_l = i2c_bus->clk_cycle / 2;
362296a461dSNaveen Krishna Ch 	t_scl_h = i2c_bus->clk_cycle / 2;
363296a461dSNaveen Krishna Ch 	t_start_su = t_scl_l;
364296a461dSNaveen Krishna Ch 	t_start_hd = t_scl_l;
365296a461dSNaveen Krishna Ch 	t_stop_su = t_scl_l;
366296a461dSNaveen Krishna Ch 	t_data_su = t_scl_l / 2;
367296a461dSNaveen Krishna Ch 	t_data_hd = t_scl_l / 2;
368296a461dSNaveen Krishna Ch 	t_sr_release = i2c_bus->clk_cycle;
369296a461dSNaveen Krishna Ch 
370296a461dSNaveen Krishna Ch 	i2c_timing_s1 = t_start_su << 24 | t_start_hd << 16 | t_stop_su << 8;
371296a461dSNaveen Krishna Ch 	i2c_timing_s2 = t_data_su << 24 | t_scl_l << 8 | t_scl_h << 0;
372296a461dSNaveen Krishna Ch 	i2c_timing_s3 = n_clkdiv << 16 | t_sr_release << 0;
373296a461dSNaveen Krishna Ch 	i2c_timing_sla = t_data_hd << 0;
374296a461dSNaveen Krishna Ch 
375296a461dSNaveen Krishna Ch 	writel(HSI2C_TRAILING_COUNT, &hsregs->usi_trailing_ctl);
376296a461dSNaveen Krishna Ch 
377296a461dSNaveen Krishna Ch 	/* Clear to enable Timeout */
378296a461dSNaveen Krishna Ch 	clrsetbits_le32(&hsregs->usi_timeout, HSI2C_TIMEOUT_EN, 0);
379296a461dSNaveen Krishna Ch 
380296a461dSNaveen Krishna Ch 	/* set AUTO mode */
381296a461dSNaveen Krishna Ch 	writel(readl(&hsregs->usi_conf) | HSI2C_AUTO_MODE, &hsregs->usi_conf);
382296a461dSNaveen Krishna Ch 
383296a461dSNaveen Krishna Ch 	/* Enable completion conditions' reporting. */
384296a461dSNaveen Krishna Ch 	writel(HSI2C_INT_I2C_EN, &hsregs->usi_int_en);
385296a461dSNaveen Krishna Ch 
386296a461dSNaveen Krishna Ch 	/* Enable FIFOs */
387296a461dSNaveen Krishna Ch 	writel(HSI2C_RXFIFO_EN | HSI2C_TXFIFO_EN, &hsregs->usi_fifo_ctl);
388296a461dSNaveen Krishna Ch 
389296a461dSNaveen Krishna Ch 	/* Currently operating in Fast speed mode. */
390296a461dSNaveen Krishna Ch 	writel(i2c_timing_s1, &hsregs->usi_timing_fs1);
391296a461dSNaveen Krishna Ch 	writel(i2c_timing_s2, &hsregs->usi_timing_fs2);
392296a461dSNaveen Krishna Ch 	writel(i2c_timing_s3, &hsregs->usi_timing_fs3);
393296a461dSNaveen Krishna Ch 	writel(i2c_timing_sla, &hsregs->usi_timing_sla);
394296a461dSNaveen Krishna Ch }
395296a461dSNaveen Krishna Ch 
396296a461dSNaveen Krishna Ch /* SW reset for the high speed bus */
397296a461dSNaveen Krishna Ch static void exynos5_i2c_reset(struct s3c24x0_i2c_bus *i2c_bus)
398296a461dSNaveen Krishna Ch {
399296a461dSNaveen Krishna Ch 	struct exynos5_hsi2c *i2c = i2c_bus->hsregs;
400296a461dSNaveen Krishna Ch 	u32 i2c_ctl;
401296a461dSNaveen Krishna Ch 
402296a461dSNaveen Krishna Ch 	/* Set and clear the bit for reset */
403296a461dSNaveen Krishna Ch 	i2c_ctl = readl(&i2c->usi_ctl);
404296a461dSNaveen Krishna Ch 	i2c_ctl |= HSI2C_SW_RST;
405296a461dSNaveen Krishna Ch 	writel(i2c_ctl, &i2c->usi_ctl);
406296a461dSNaveen Krishna Ch 
407296a461dSNaveen Krishna Ch 	i2c_ctl = readl(&i2c->usi_ctl);
408296a461dSNaveen Krishna Ch 	i2c_ctl &= ~HSI2C_SW_RST;
409296a461dSNaveen Krishna Ch 	writel(i2c_ctl, &i2c->usi_ctl);
410296a461dSNaveen Krishna Ch 
411296a461dSNaveen Krishna Ch 	/* Initialize the configure registers */
412296a461dSNaveen Krishna Ch 	hsi2c_ch_init(i2c_bus);
413296a461dSNaveen Krishna Ch }
414296a461dSNaveen Krishna Ch 
4158dfcbaa6SPrzemyslaw Marczak #ifdef CONFIG_SYS_I2C
4162d8f1e27SPiotr Wilczek static void s3c24x0_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd)
417d3b63577SJean-Christophe PLAGNIOL-VILLARD {
418ab7e52bbSRajeshwari Shinde 	struct s3c24x0_i2c *i2c;
4192d8f1e27SPiotr Wilczek 	struct s3c24x0_i2c_bus *bus;
420c86d9ed3SPiotr Wilczek #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
421eb0ae7f5Skevin.morfitt@fearnside-systems.co.uk 	struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
422ab7e52bbSRajeshwari Shinde #endif
423e4e24020SNaveen Krishna Ch 	ulong start_time = get_timer(0);
424d3b63577SJean-Christophe PLAGNIOL-VILLARD 
4252d8f1e27SPiotr Wilczek 	i2c = get_base_i2c(adap->hwadapnr);
4268dfcbaa6SPrzemyslaw Marczak 	bus = &i2c_bus[adap->hwadapnr];
4278dfcbaa6SPrzemyslaw Marczak 	if (!bus)
4288dfcbaa6SPrzemyslaw Marczak 		return;
429d3b63577SJean-Christophe PLAGNIOL-VILLARD 
430e4e24020SNaveen Krishna Ch 	/*
431e4e24020SNaveen Krishna Ch 	 * In case the previous transfer is still going, wait to give it a
432e4e24020SNaveen Krishna Ch 	 * chance to finish.
433e4e24020SNaveen Krishna Ch 	 */
434e4e24020SNaveen Krishna Ch 	while (readl(&i2c->iicstat) & I2CSTAT_BSY) {
435e4e24020SNaveen Krishna Ch 		if (get_timer(start_time) > I2C_TIMEOUT_MS) {
436e4e24020SNaveen Krishna Ch 			printf("%s: I2C bus busy for %p\n", __func__,
437e4e24020SNaveen Krishna Ch 			       &i2c->iicstat);
438e4e24020SNaveen Krishna Ch 			return;
439e4e24020SNaveen Krishna Ch 		}
440d3b63577SJean-Christophe PLAGNIOL-VILLARD 	}
441d3b63577SJean-Christophe PLAGNIOL-VILLARD 
442c86d9ed3SPiotr Wilczek #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
443296a461dSNaveen Krishna Ch 	int i;
444296a461dSNaveen Krishna Ch 
445d9abba82SC Nauman 	if ((readl(&i2c->iicstat) & I2CSTAT_BSY) || GetI2CSDA() == 0) {
4467b0c0f69SMarek Vasut #if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
447d9abba82SC Nauman 		ulong old_gpecon = readl(&gpio->gpecon);
448d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif
449d3b63577SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_S3C2400
450d9abba82SC Nauman 		ulong old_gpecon = readl(&gpio->pgcon);
451d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif
452eb0ae7f5Skevin.morfitt@fearnside-systems.co.uk 		/* bus still busy probably by (most) previously interrupted
453eb0ae7f5Skevin.morfitt@fearnside-systems.co.uk 		   transfer */
454d3b63577SJean-Christophe PLAGNIOL-VILLARD 
4557b0c0f69SMarek Vasut #if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
456d3b63577SJean-Christophe PLAGNIOL-VILLARD 		/* set I2CSDA and I2CSCL (GPE15, GPE14) to GPIO */
457d9abba82SC Nauman 		writel((readl(&gpio->gpecon) & ~0xF0000000) | 0x10000000,
458d9abba82SC Nauman 		       &gpio->gpecon);
459d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif
460d3b63577SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_S3C2400
461d3b63577SJean-Christophe PLAGNIOL-VILLARD 		/* set I2CSDA and I2CSCL (PG5, PG6) to GPIO */
462d9abba82SC Nauman 		writel((readl(&gpio->pgcon) & ~0x00003c00) | 0x00001000,
463d9abba82SC Nauman 		       &gpio->pgcon);
464d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif
465d3b63577SJean-Christophe PLAGNIOL-VILLARD 
466d3b63577SJean-Christophe PLAGNIOL-VILLARD 		/* toggle I2CSCL until bus idle */
467d3b63577SJean-Christophe PLAGNIOL-VILLARD 		SetI2CSCL(0);
468d3b63577SJean-Christophe PLAGNIOL-VILLARD 		udelay(1000);
469d3b63577SJean-Christophe PLAGNIOL-VILLARD 		i = 10;
470d3b63577SJean-Christophe PLAGNIOL-VILLARD 		while ((i > 0) && (GetI2CSDA() != 1)) {
471d3b63577SJean-Christophe PLAGNIOL-VILLARD 			SetI2CSCL(1);
472d3b63577SJean-Christophe PLAGNIOL-VILLARD 			udelay(1000);
473d3b63577SJean-Christophe PLAGNIOL-VILLARD 			SetI2CSCL(0);
474d3b63577SJean-Christophe PLAGNIOL-VILLARD 			udelay(1000);
475d3b63577SJean-Christophe PLAGNIOL-VILLARD 			i--;
476d3b63577SJean-Christophe PLAGNIOL-VILLARD 		}
477d3b63577SJean-Christophe PLAGNIOL-VILLARD 		SetI2CSCL(1);
478d3b63577SJean-Christophe PLAGNIOL-VILLARD 		udelay(1000);
479d3b63577SJean-Christophe PLAGNIOL-VILLARD 
480d3b63577SJean-Christophe PLAGNIOL-VILLARD 		/* restore pin functions */
4817b0c0f69SMarek Vasut #if defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
482d9abba82SC Nauman 		writel(old_gpecon, &gpio->gpecon);
483d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif
484d3b63577SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_S3C2400
485d9abba82SC Nauman 		writel(old_gpecon, &gpio->pgcon);
486d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif
487d3b63577SJean-Christophe PLAGNIOL-VILLARD 	}
488c86d9ed3SPiotr Wilczek #endif /* #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5) */
4898dfcbaa6SPrzemyslaw Marczak 
490ab7e52bbSRajeshwari Shinde 	i2c_ch_init(i2c, speed, slaveadd);
4912d8f1e27SPiotr Wilczek 
4922d8f1e27SPiotr Wilczek 	bus->active = true;
4932d8f1e27SPiotr Wilczek 	bus->regs = i2c;
494d3b63577SJean-Christophe PLAGNIOL-VILLARD }
4958dfcbaa6SPrzemyslaw Marczak #endif /* CONFIG_SYS_I2C */
496d3b63577SJean-Christophe PLAGNIOL-VILLARD 
497d3b63577SJean-Christophe PLAGNIOL-VILLARD /*
498296a461dSNaveen Krishna Ch  * Poll the appropriate bit of the fifo status register until the interface is
499296a461dSNaveen Krishna Ch  * ready to process the next byte or timeout expires.
500296a461dSNaveen Krishna Ch  *
501296a461dSNaveen Krishna Ch  * In addition to the FIFO status register this function also polls the
502296a461dSNaveen Krishna Ch  * interrupt status register to be able to detect unexpected transaction
503296a461dSNaveen Krishna Ch  * completion.
504296a461dSNaveen Krishna Ch  *
505296a461dSNaveen Krishna Ch  * When FIFO is ready to process the next byte, this function returns I2C_OK.
506296a461dSNaveen Krishna Ch  * If in course of polling the INT_I2C assertion is detected, the function
507296a461dSNaveen Krishna Ch  * returns I2C_NOK. If timeout happens before any of the above conditions is
508296a461dSNaveen Krishna Ch  * met - the function returns I2C_NOK_TOUT;
509296a461dSNaveen Krishna Ch 
510296a461dSNaveen Krishna Ch  * @param i2c: pointer to the appropriate i2c register bank.
511296a461dSNaveen Krishna Ch  * @param rx_transfer: set to True if the receive transaction is in progress.
512296a461dSNaveen Krishna Ch  * @return: as described above.
513296a461dSNaveen Krishna Ch  */
514296a461dSNaveen Krishna Ch static unsigned hsi2c_poll_fifo(struct exynos5_hsi2c *i2c, bool rx_transfer)
515296a461dSNaveen Krishna Ch {
516296a461dSNaveen Krishna Ch 	u32 fifo_bit = rx_transfer ? HSI2C_RX_FIFO_EMPTY : HSI2C_TX_FIFO_FULL;
517296a461dSNaveen Krishna Ch 	int i = HSI2C_TIMEOUT_US;
518296a461dSNaveen Krishna Ch 
519296a461dSNaveen Krishna Ch 	while (readl(&i2c->usi_fifo_stat) & fifo_bit) {
520296a461dSNaveen Krishna Ch 		if (readl(&i2c->usi_int_stat) & HSI2C_INT_I2C_EN) {
521296a461dSNaveen Krishna Ch 			/*
522296a461dSNaveen Krishna Ch 			 * There is a chance that assertion of
523296a461dSNaveen Krishna Ch 			 * HSI2C_INT_I2C_EN and deassertion of
524296a461dSNaveen Krishna Ch 			 * HSI2C_RX_FIFO_EMPTY happen simultaneously. Let's
525296a461dSNaveen Krishna Ch 			 * give FIFO status priority and check it one more
526296a461dSNaveen Krishna Ch 			 * time before reporting interrupt. The interrupt will
527296a461dSNaveen Krishna Ch 			 * be reported next time this function is called.
528296a461dSNaveen Krishna Ch 			 */
529296a461dSNaveen Krishna Ch 			if (rx_transfer &&
530296a461dSNaveen Krishna Ch 			    !(readl(&i2c->usi_fifo_stat) & fifo_bit))
531296a461dSNaveen Krishna Ch 				break;
532296a461dSNaveen Krishna Ch 			return I2C_NOK;
533296a461dSNaveen Krishna Ch 		}
534296a461dSNaveen Krishna Ch 		if (!i--) {
535296a461dSNaveen Krishna Ch 			debug("%s: FIFO polling timeout!\n", __func__);
536296a461dSNaveen Krishna Ch 			return I2C_NOK_TOUT;
537296a461dSNaveen Krishna Ch 		}
538296a461dSNaveen Krishna Ch 		udelay(1);
539296a461dSNaveen Krishna Ch 	}
540296a461dSNaveen Krishna Ch 	return I2C_OK;
541296a461dSNaveen Krishna Ch }
542296a461dSNaveen Krishna Ch 
543296a461dSNaveen Krishna Ch /*
544296a461dSNaveen Krishna Ch  * Preapre hsi2c transaction, either read or write.
545296a461dSNaveen Krishna Ch  *
546296a461dSNaveen Krishna Ch  * Set up transfer as described in section 27.5.1.2 'I2C Channel Auto Mode' of
547296a461dSNaveen Krishna Ch  * the 5420 UM.
548296a461dSNaveen Krishna Ch  *
549296a461dSNaveen Krishna Ch  * @param i2c: pointer to the appropriate i2c register bank.
550296a461dSNaveen Krishna Ch  * @param chip: slave address on the i2c bus (with read/write bit exlcuded)
551296a461dSNaveen Krishna Ch  * @param len: number of bytes expected to be sent or received
552296a461dSNaveen Krishna Ch  * @param rx_transfer: set to true for receive transactions
553296a461dSNaveen Krishna Ch  * @param: issue_stop: set to true if i2c stop condition should be generated
554296a461dSNaveen Krishna Ch  *         after this transaction.
555296a461dSNaveen Krishna Ch  * @return: I2C_NOK_TOUT in case the bus remained busy for HSI2C_TIMEOUT_US,
556296a461dSNaveen Krishna Ch  *          I2C_OK otherwise.
557296a461dSNaveen Krishna Ch  */
558296a461dSNaveen Krishna Ch static int hsi2c_prepare_transaction(struct exynos5_hsi2c *i2c,
559296a461dSNaveen Krishna Ch 				     u8 chip,
560296a461dSNaveen Krishna Ch 				     u16 len,
561296a461dSNaveen Krishna Ch 				     bool rx_transfer,
562296a461dSNaveen Krishna Ch 				     bool issue_stop)
563296a461dSNaveen Krishna Ch {
564296a461dSNaveen Krishna Ch 	u32 conf;
565296a461dSNaveen Krishna Ch 
566296a461dSNaveen Krishna Ch 	conf = len | HSI2C_MASTER_RUN;
567296a461dSNaveen Krishna Ch 
568296a461dSNaveen Krishna Ch 	if (issue_stop)
569296a461dSNaveen Krishna Ch 		conf |= HSI2C_STOP_AFTER_TRANS;
570296a461dSNaveen Krishna Ch 
571296a461dSNaveen Krishna Ch 	/* Clear to enable Timeout */
572296a461dSNaveen Krishna Ch 	writel(readl(&i2c->usi_timeout) & ~HSI2C_TIMEOUT_EN, &i2c->usi_timeout);
573296a461dSNaveen Krishna Ch 
574296a461dSNaveen Krishna Ch 	/* Set slave address */
575296a461dSNaveen Krishna Ch 	writel(HSI2C_SLV_ADDR_MAS(chip), &i2c->i2c_addr);
576296a461dSNaveen Krishna Ch 
577296a461dSNaveen Krishna Ch 	if (rx_transfer) {
578296a461dSNaveen Krishna Ch 		/* i2c master, read transaction */
579296a461dSNaveen Krishna Ch 		writel((HSI2C_RXCHON | HSI2C_FUNC_MODE_I2C | HSI2C_MASTER),
580296a461dSNaveen Krishna Ch 		       &i2c->usi_ctl);
581296a461dSNaveen Krishna Ch 
582296a461dSNaveen Krishna Ch 		/* read up to len bytes, stop after transaction is finished */
583296a461dSNaveen Krishna Ch 		writel(conf | HSI2C_READ_WRITE, &i2c->usi_auto_conf);
584296a461dSNaveen Krishna Ch 	} else {
585296a461dSNaveen Krishna Ch 		/* i2c master, write transaction */
586296a461dSNaveen Krishna Ch 		writel((HSI2C_TXCHON | HSI2C_FUNC_MODE_I2C | HSI2C_MASTER),
587296a461dSNaveen Krishna Ch 		       &i2c->usi_ctl);
588296a461dSNaveen Krishna Ch 
589296a461dSNaveen Krishna Ch 		/* write up to len bytes, stop after transaction is finished */
590296a461dSNaveen Krishna Ch 		writel(conf, &i2c->usi_auto_conf);
591296a461dSNaveen Krishna Ch 	}
592296a461dSNaveen Krishna Ch 
593296a461dSNaveen Krishna Ch 	/* Reset all pending interrupt status bits we care about, if any */
594296a461dSNaveen Krishna Ch 	writel(HSI2C_INT_I2C_EN, &i2c->usi_int_stat);
595296a461dSNaveen Krishna Ch 
596296a461dSNaveen Krishna Ch 	return I2C_OK;
597296a461dSNaveen Krishna Ch }
598296a461dSNaveen Krishna Ch 
599296a461dSNaveen Krishna Ch /*
600296a461dSNaveen Krishna Ch  * Wait while i2c bus is settling down (mostly stop gets completed).
601296a461dSNaveen Krishna Ch  */
602296a461dSNaveen Krishna Ch static int hsi2c_wait_while_busy(struct exynos5_hsi2c *i2c)
603296a461dSNaveen Krishna Ch {
604296a461dSNaveen Krishna Ch 	int i = HSI2C_TIMEOUT_US;
605296a461dSNaveen Krishna Ch 
606296a461dSNaveen Krishna Ch 	while (readl(&i2c->usi_trans_status) & HSI2C_MASTER_BUSY) {
607296a461dSNaveen Krishna Ch 		if (!i--) {
608296a461dSNaveen Krishna Ch 			debug("%s: bus busy\n", __func__);
609296a461dSNaveen Krishna Ch 			return I2C_NOK_TOUT;
610296a461dSNaveen Krishna Ch 		}
611296a461dSNaveen Krishna Ch 		udelay(1);
612296a461dSNaveen Krishna Ch 	}
613296a461dSNaveen Krishna Ch 	return I2C_OK;
614296a461dSNaveen Krishna Ch }
615296a461dSNaveen Krishna Ch 
616296a461dSNaveen Krishna Ch static int hsi2c_write(struct exynos5_hsi2c *i2c,
617296a461dSNaveen Krishna Ch 		       unsigned char chip,
618296a461dSNaveen Krishna Ch 		       unsigned char addr[],
619296a461dSNaveen Krishna Ch 		       unsigned char alen,
620296a461dSNaveen Krishna Ch 		       unsigned char data[],
621296a461dSNaveen Krishna Ch 		       unsigned short len,
622296a461dSNaveen Krishna Ch 		       bool issue_stop)
623296a461dSNaveen Krishna Ch {
624296a461dSNaveen Krishna Ch 	int i, rv = 0;
625296a461dSNaveen Krishna Ch 
626296a461dSNaveen Krishna Ch 	if (!(len + alen)) {
627296a461dSNaveen Krishna Ch 		/* Writes of zero length not supported in auto mode. */
628296a461dSNaveen Krishna Ch 		debug("%s: zero length writes not supported\n", __func__);
629296a461dSNaveen Krishna Ch 		return I2C_NOK;
630296a461dSNaveen Krishna Ch 	}
631296a461dSNaveen Krishna Ch 
632296a461dSNaveen Krishna Ch 	rv = hsi2c_prepare_transaction
633296a461dSNaveen Krishna Ch 		(i2c, chip, len + alen, false, issue_stop);
634296a461dSNaveen Krishna Ch 	if (rv != I2C_OK)
635296a461dSNaveen Krishna Ch 		return rv;
636296a461dSNaveen Krishna Ch 
637296a461dSNaveen Krishna Ch 	/* Move address, if any, and the data, if any, into the FIFO. */
638296a461dSNaveen Krishna Ch 	for (i = 0; i < alen; i++) {
639296a461dSNaveen Krishna Ch 		rv = hsi2c_poll_fifo(i2c, false);
640296a461dSNaveen Krishna Ch 		if (rv != I2C_OK) {
641296a461dSNaveen Krishna Ch 			debug("%s: address write failed\n", __func__);
642296a461dSNaveen Krishna Ch 			goto write_error;
643296a461dSNaveen Krishna Ch 		}
644296a461dSNaveen Krishna Ch 		writel(addr[i], &i2c->usi_txdata);
645296a461dSNaveen Krishna Ch 	}
646296a461dSNaveen Krishna Ch 
647296a461dSNaveen Krishna Ch 	for (i = 0; i < len; i++) {
648296a461dSNaveen Krishna Ch 		rv = hsi2c_poll_fifo(i2c, false);
649296a461dSNaveen Krishna Ch 		if (rv != I2C_OK) {
650296a461dSNaveen Krishna Ch 			debug("%s: data write failed\n", __func__);
651296a461dSNaveen Krishna Ch 			goto write_error;
652296a461dSNaveen Krishna Ch 		}
653296a461dSNaveen Krishna Ch 		writel(data[i], &i2c->usi_txdata);
654296a461dSNaveen Krishna Ch 	}
655296a461dSNaveen Krishna Ch 
656296a461dSNaveen Krishna Ch 	rv = hsi2c_wait_for_trx(i2c);
657296a461dSNaveen Krishna Ch 
658296a461dSNaveen Krishna Ch  write_error:
659296a461dSNaveen Krishna Ch 	if (issue_stop) {
660296a461dSNaveen Krishna Ch 		int tmp_ret = hsi2c_wait_while_busy(i2c);
661296a461dSNaveen Krishna Ch 		if (rv == I2C_OK)
662296a461dSNaveen Krishna Ch 			rv = tmp_ret;
663296a461dSNaveen Krishna Ch 	}
664296a461dSNaveen Krishna Ch 
665296a461dSNaveen Krishna Ch 	writel(HSI2C_FUNC_MODE_I2C, &i2c->usi_ctl); /* done */
666296a461dSNaveen Krishna Ch 	return rv;
667296a461dSNaveen Krishna Ch }
668296a461dSNaveen Krishna Ch 
669296a461dSNaveen Krishna Ch static int hsi2c_read(struct exynos5_hsi2c *i2c,
670296a461dSNaveen Krishna Ch 		      unsigned char chip,
671296a461dSNaveen Krishna Ch 		      unsigned char addr[],
672296a461dSNaveen Krishna Ch 		      unsigned char alen,
673296a461dSNaveen Krishna Ch 		      unsigned char data[],
674296a461dSNaveen Krishna Ch 		      unsigned short len)
675296a461dSNaveen Krishna Ch {
676296a461dSNaveen Krishna Ch 	int i, rv, tmp_ret;
677296a461dSNaveen Krishna Ch 	bool drop_data = false;
678296a461dSNaveen Krishna Ch 
679296a461dSNaveen Krishna Ch 	if (!len) {
680296a461dSNaveen Krishna Ch 		/* Reads of zero length not supported in auto mode. */
681296a461dSNaveen Krishna Ch 		debug("%s: zero length read adjusted\n", __func__);
682296a461dSNaveen Krishna Ch 		drop_data = true;
683296a461dSNaveen Krishna Ch 		len = 1;
684296a461dSNaveen Krishna Ch 	}
685296a461dSNaveen Krishna Ch 
686296a461dSNaveen Krishna Ch 	if (alen) {
687296a461dSNaveen Krishna Ch 		/* Internal register adress needs to be written first. */
688296a461dSNaveen Krishna Ch 		rv = hsi2c_write(i2c, chip, addr, alen, NULL, 0, false);
689296a461dSNaveen Krishna Ch 		if (rv != I2C_OK)
690296a461dSNaveen Krishna Ch 			return rv;
691296a461dSNaveen Krishna Ch 	}
692296a461dSNaveen Krishna Ch 
693296a461dSNaveen Krishna Ch 	rv = hsi2c_prepare_transaction(i2c, chip, len, true, true);
694296a461dSNaveen Krishna Ch 
695296a461dSNaveen Krishna Ch 	if (rv != I2C_OK)
696296a461dSNaveen Krishna Ch 		return rv;
697296a461dSNaveen Krishna Ch 
698296a461dSNaveen Krishna Ch 	for (i = 0; i < len; i++) {
699296a461dSNaveen Krishna Ch 		rv = hsi2c_poll_fifo(i2c, true);
700296a461dSNaveen Krishna Ch 		if (rv != I2C_OK)
701296a461dSNaveen Krishna Ch 			goto read_err;
702296a461dSNaveen Krishna Ch 		if (drop_data)
703296a461dSNaveen Krishna Ch 			continue;
704296a461dSNaveen Krishna Ch 		data[i] = readl(&i2c->usi_rxdata);
705296a461dSNaveen Krishna Ch 	}
706296a461dSNaveen Krishna Ch 
707296a461dSNaveen Krishna Ch 	rv = hsi2c_wait_for_trx(i2c);
708296a461dSNaveen Krishna Ch 
709296a461dSNaveen Krishna Ch  read_err:
710296a461dSNaveen Krishna Ch 	tmp_ret = hsi2c_wait_while_busy(i2c);
711296a461dSNaveen Krishna Ch 	if (rv == I2C_OK)
712296a461dSNaveen Krishna Ch 		rv = tmp_ret;
713296a461dSNaveen Krishna Ch 
714296a461dSNaveen Krishna Ch 	writel(HSI2C_FUNC_MODE_I2C, &i2c->usi_ctl); /* done */
715296a461dSNaveen Krishna Ch 	return rv;
716296a461dSNaveen Krishna Ch }
717296a461dSNaveen Krishna Ch 
7188dfcbaa6SPrzemyslaw Marczak #ifdef CONFIG_SYS_I2C
7192d8f1e27SPiotr Wilczek static unsigned int s3c24x0_i2c_set_bus_speed(struct i2c_adapter *adap,
7202d8f1e27SPiotr Wilczek 					      unsigned int speed)
7218dfcbaa6SPrzemyslaw Marczak #else
7228dfcbaa6SPrzemyslaw Marczak static int s3c24x0_i2c_set_bus_speed(struct udevice *dev, unsigned int speed)
7238dfcbaa6SPrzemyslaw Marczak #endif
7242d8f1e27SPiotr Wilczek {
7252d8f1e27SPiotr Wilczek 	struct s3c24x0_i2c_bus *i2c_bus;
7262d8f1e27SPiotr Wilczek 
7278dfcbaa6SPrzemyslaw Marczak #ifdef CONFIG_SYS_I2C
7282d8f1e27SPiotr Wilczek 	i2c_bus = get_bus(adap->hwadapnr);
7292d8f1e27SPiotr Wilczek 	if (!i2c_bus)
7308dfcbaa6SPrzemyslaw Marczak 		return -EFAULT;
7318dfcbaa6SPrzemyslaw Marczak #else
7328dfcbaa6SPrzemyslaw Marczak 	i2c_bus = dev_get_priv(dev);
7338dfcbaa6SPrzemyslaw Marczak #endif
7342d8f1e27SPiotr Wilczek 	i2c_bus->clock_frequency = speed;
7352d8f1e27SPiotr Wilczek 
7362d8f1e27SPiotr Wilczek 	if (i2c_bus->is_highspeed) {
7372d8f1e27SPiotr Wilczek 		if (hsi2c_get_clk_details(i2c_bus))
7388dfcbaa6SPrzemyslaw Marczak 			return -EFAULT;
7392d8f1e27SPiotr Wilczek 		hsi2c_ch_init(i2c_bus);
7402d8f1e27SPiotr Wilczek 	} else {
7412d8f1e27SPiotr Wilczek 		i2c_ch_init(i2c_bus->regs, i2c_bus->clock_frequency,
7422d8f1e27SPiotr Wilczek 			    CONFIG_SYS_I2C_S3C24X0_SLAVE);
7432d8f1e27SPiotr Wilczek 	}
7442d8f1e27SPiotr Wilczek 
7452d8f1e27SPiotr Wilczek 	return 0;
7462d8f1e27SPiotr Wilczek }
7472d8f1e27SPiotr Wilczek 
748296a461dSNaveen Krishna Ch /*
749d3b63577SJean-Christophe PLAGNIOL-VILLARD  * cmd_type is 0 for write, 1 for read.
750d3b63577SJean-Christophe PLAGNIOL-VILLARD  *
751d3b63577SJean-Christophe PLAGNIOL-VILLARD  * addr_len can take any value from 0-255, it is only limited
752d3b63577SJean-Christophe PLAGNIOL-VILLARD  * by the char, we could make it larger if needed. If it is
753d3b63577SJean-Christophe PLAGNIOL-VILLARD  * 0 we skip the address write cycle.
754d3b63577SJean-Christophe PLAGNIOL-VILLARD  */
755ab7e52bbSRajeshwari Shinde static int i2c_transfer(struct s3c24x0_i2c *i2c,
756ab7e52bbSRajeshwari Shinde 			unsigned char cmd_type,
757d3b63577SJean-Christophe PLAGNIOL-VILLARD 			unsigned char chip,
758d3b63577SJean-Christophe PLAGNIOL-VILLARD 			unsigned char addr[],
759d3b63577SJean-Christophe PLAGNIOL-VILLARD 			unsigned char addr_len,
760ab7e52bbSRajeshwari Shinde 			unsigned char data[],
761ab7e52bbSRajeshwari Shinde 			unsigned short data_len)
762d3b63577SJean-Christophe PLAGNIOL-VILLARD {
763e4e24020SNaveen Krishna Ch 	int i = 0, result;
764e4e24020SNaveen Krishna Ch 	ulong start_time = get_timer(0);
765d3b63577SJean-Christophe PLAGNIOL-VILLARD 
766d3b63577SJean-Christophe PLAGNIOL-VILLARD 	if (data == 0 || data_len == 0) {
767d3b63577SJean-Christophe PLAGNIOL-VILLARD 		/*Don't support data transfer of no length or to address 0 */
768ab7e52bbSRajeshwari Shinde 		debug("i2c_transfer: bad call\n");
769d3b63577SJean-Christophe PLAGNIOL-VILLARD 		return I2C_NOK;
770d3b63577SJean-Christophe PLAGNIOL-VILLARD 	}
771d3b63577SJean-Christophe PLAGNIOL-VILLARD 
772e4e24020SNaveen Krishna Ch 	while (readl(&i2c->iicstat) & I2CSTAT_BSY) {
773e4e24020SNaveen Krishna Ch 		if (get_timer(start_time) > I2C_TIMEOUT_MS)
774e4e24020SNaveen Krishna Ch 			return I2C_NOK_TOUT;
775d3b63577SJean-Christophe PLAGNIOL-VILLARD 	}
776d3b63577SJean-Christophe PLAGNIOL-VILLARD 
777ab7e52bbSRajeshwari Shinde 	writel(readl(&i2c->iiccon) | I2CCON_ACKGEN, &i2c->iiccon);
778e4e24020SNaveen Krishna Ch 
779e4e24020SNaveen Krishna Ch 	/* Get the slave chip address going */
780e4e24020SNaveen Krishna Ch 	writel(chip, &i2c->iicds);
781e4e24020SNaveen Krishna Ch 	if ((cmd_type == I2C_WRITE) || (addr && addr_len))
782e4e24020SNaveen Krishna Ch 		writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP,
783e4e24020SNaveen Krishna Ch 		       &i2c->iicstat);
784e4e24020SNaveen Krishna Ch 	else
785e4e24020SNaveen Krishna Ch 		writel(I2C_MODE_MR | I2C_TXRX_ENA | I2C_START_STOP,
786e4e24020SNaveen Krishna Ch 		       &i2c->iicstat);
787e4e24020SNaveen Krishna Ch 
788e4e24020SNaveen Krishna Ch 	/* Wait for chip address to transmit. */
789e4e24020SNaveen Krishna Ch 	result = WaitForXfer(i2c);
790e4e24020SNaveen Krishna Ch 	if (result != I2C_OK)
791e4e24020SNaveen Krishna Ch 		goto bailout;
792e4e24020SNaveen Krishna Ch 
793e4e24020SNaveen Krishna Ch 	/* If register address needs to be transmitted - do it now. */
794e4e24020SNaveen Krishna Ch 	if (addr && addr_len) {
795e4e24020SNaveen Krishna Ch 		while ((i < addr_len) && (result == I2C_OK)) {
796e4e24020SNaveen Krishna Ch 			writel(addr[i++], &i2c->iicds);
79726ea7685SSimon Glass 			read_write_byte(i2c);
798e4e24020SNaveen Krishna Ch 			result = WaitForXfer(i2c);
799e4e24020SNaveen Krishna Ch 		}
800e4e24020SNaveen Krishna Ch 		i = 0;
801e4e24020SNaveen Krishna Ch 		if (result != I2C_OK)
802e4e24020SNaveen Krishna Ch 			goto bailout;
803e4e24020SNaveen Krishna Ch 	}
804d3b63577SJean-Christophe PLAGNIOL-VILLARD 
805d3b63577SJean-Christophe PLAGNIOL-VILLARD 	switch (cmd_type) {
806d3b63577SJean-Christophe PLAGNIOL-VILLARD 	case I2C_WRITE:
807d3b63577SJean-Christophe PLAGNIOL-VILLARD 		while ((i < data_len) && (result == I2C_OK)) {
808e4e24020SNaveen Krishna Ch 			writel(data[i++], &i2c->iicds);
80926ea7685SSimon Glass 			read_write_byte(i2c);
810ab7e52bbSRajeshwari Shinde 			result = WaitForXfer(i2c);
811d3b63577SJean-Christophe PLAGNIOL-VILLARD 		}
812d3b63577SJean-Christophe PLAGNIOL-VILLARD 		break;
813d3b63577SJean-Christophe PLAGNIOL-VILLARD 
814d3b63577SJean-Christophe PLAGNIOL-VILLARD 	case I2C_READ:
815d3b63577SJean-Christophe PLAGNIOL-VILLARD 		if (addr && addr_len) {
816e4e24020SNaveen Krishna Ch 			/*
817e4e24020SNaveen Krishna Ch 			 * Register address has been sent, now send slave chip
818e4e24020SNaveen Krishna Ch 			 * address again to start the actual read transaction.
819e4e24020SNaveen Krishna Ch 			 */
820d9abba82SC Nauman 			writel(chip, &i2c->iicds);
821e4e24020SNaveen Krishna Ch 
822e4e24020SNaveen Krishna Ch 			/* Generate a re-START. */
823e4e24020SNaveen Krishna Ch 			writel(I2C_MODE_MR | I2C_TXRX_ENA | I2C_START_STOP,
824d9abba82SC Nauman 				&i2c->iicstat);
82526ea7685SSimon Glass 			read_write_byte(i2c);
826ab7e52bbSRajeshwari Shinde 			result = WaitForXfer(i2c);
827e4e24020SNaveen Krishna Ch 
828e4e24020SNaveen Krishna Ch 			if (result != I2C_OK)
829e4e24020SNaveen Krishna Ch 				goto bailout;
830d3b63577SJean-Christophe PLAGNIOL-VILLARD 		}
831d3b63577SJean-Christophe PLAGNIOL-VILLARD 
832d3b63577SJean-Christophe PLAGNIOL-VILLARD 		while ((i < data_len) && (result == I2C_OK)) {
833d3b63577SJean-Christophe PLAGNIOL-VILLARD 			/* disable ACK for final READ */
834d3b63577SJean-Christophe PLAGNIOL-VILLARD 			if (i == data_len - 1)
835d9abba82SC Nauman 				writel(readl(&i2c->iiccon)
836ab7e52bbSRajeshwari Shinde 				       & ~I2CCON_ACKGEN,
837ab7e52bbSRajeshwari Shinde 				       &i2c->iiccon);
83826ea7685SSimon Glass 			read_write_byte(i2c);
839ab7e52bbSRajeshwari Shinde 			result = WaitForXfer(i2c);
840e4e24020SNaveen Krishna Ch 			data[i++] = readl(&i2c->iicds);
841d3b63577SJean-Christophe PLAGNIOL-VILLARD 		}
842e4e24020SNaveen Krishna Ch 		if (result == I2C_NACK)
843e4e24020SNaveen Krishna Ch 			result = I2C_OK; /* Normal terminated read. */
844d3b63577SJean-Christophe PLAGNIOL-VILLARD 		break;
845d3b63577SJean-Christophe PLAGNIOL-VILLARD 
846d3b63577SJean-Christophe PLAGNIOL-VILLARD 	default:
847ab7e52bbSRajeshwari Shinde 		debug("i2c_transfer: bad call\n");
848d3b63577SJean-Christophe PLAGNIOL-VILLARD 		result = I2C_NOK;
849d3b63577SJean-Christophe PLAGNIOL-VILLARD 		break;
850d3b63577SJean-Christophe PLAGNIOL-VILLARD 	}
851d3b63577SJean-Christophe PLAGNIOL-VILLARD 
852e4e24020SNaveen Krishna Ch bailout:
853e4e24020SNaveen Krishna Ch 	/* Send STOP. */
854e4e24020SNaveen Krishna Ch 	writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat);
85526ea7685SSimon Glass 	read_write_byte(i2c);
856e4e24020SNaveen Krishna Ch 
857ab7e52bbSRajeshwari Shinde 	return result;
858d3b63577SJean-Christophe PLAGNIOL-VILLARD }
859d3b63577SJean-Christophe PLAGNIOL-VILLARD 
8608dfcbaa6SPrzemyslaw Marczak #ifdef CONFIG_SYS_I2C
8612d8f1e27SPiotr Wilczek static int s3c24x0_i2c_probe(struct i2c_adapter *adap, uchar chip)
8628dfcbaa6SPrzemyslaw Marczak #else
8638dfcbaa6SPrzemyslaw Marczak static int s3c24x0_i2c_probe(struct udevice *dev, uint chip, uint chip_flags)
8648dfcbaa6SPrzemyslaw Marczak #endif
865d3b63577SJean-Christophe PLAGNIOL-VILLARD {
866296a461dSNaveen Krishna Ch 	struct s3c24x0_i2c_bus *i2c_bus;
867d3b63577SJean-Christophe PLAGNIOL-VILLARD 	uchar buf[1];
868296a461dSNaveen Krishna Ch 	int ret;
869d3b63577SJean-Christophe PLAGNIOL-VILLARD 
8708dfcbaa6SPrzemyslaw Marczak #ifdef CONFIG_SYS_I2C
8712d8f1e27SPiotr Wilczek 	i2c_bus = get_bus(adap->hwadapnr);
872296a461dSNaveen Krishna Ch 	if (!i2c_bus)
8738dfcbaa6SPrzemyslaw Marczak 		return -EFAULT;
8748dfcbaa6SPrzemyslaw Marczak #else
8758dfcbaa6SPrzemyslaw Marczak 	i2c_bus = dev_get_priv(dev);
8768dfcbaa6SPrzemyslaw Marczak #endif
877d3b63577SJean-Christophe PLAGNIOL-VILLARD 	buf[0] = 0;
878d3b63577SJean-Christophe PLAGNIOL-VILLARD 
879d3b63577SJean-Christophe PLAGNIOL-VILLARD 	/*
880d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * What is needed is to send the chip address and verify that the
881d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * address was <ACK>ed (i.e. there was a chip at that address which
882d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * drove the data line low).
883d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 */
884296a461dSNaveen Krishna Ch 	if (i2c_bus->is_highspeed) {
885296a461dSNaveen Krishna Ch 		ret = hsi2c_read(i2c_bus->hsregs,
886296a461dSNaveen Krishna Ch 				chip, 0, 0, buf, 1);
887296a461dSNaveen Krishna Ch 	} else {
888296a461dSNaveen Krishna Ch 		ret = i2c_transfer(i2c_bus->regs,
889296a461dSNaveen Krishna Ch 				I2C_READ, chip << 1, 0, 0, buf, 1);
890296a461dSNaveen Krishna Ch 	}
891296a461dSNaveen Krishna Ch 
892296a461dSNaveen Krishna Ch 	return ret != I2C_OK;
893d3b63577SJean-Christophe PLAGNIOL-VILLARD }
894d3b63577SJean-Christophe PLAGNIOL-VILLARD 
8958dfcbaa6SPrzemyslaw Marczak #ifdef CONFIG_SYS_I2C
8962d8f1e27SPiotr Wilczek static int s3c24x0_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
8972d8f1e27SPiotr Wilczek 			    int alen, uchar *buffer, int len)
898d3b63577SJean-Christophe PLAGNIOL-VILLARD {
899296a461dSNaveen Krishna Ch 	struct s3c24x0_i2c_bus *i2c_bus;
900d3b63577SJean-Christophe PLAGNIOL-VILLARD 	uchar xaddr[4];
901d3b63577SJean-Christophe PLAGNIOL-VILLARD 	int ret;
902d3b63577SJean-Christophe PLAGNIOL-VILLARD 
9038dfcbaa6SPrzemyslaw Marczak 	i2c_bus = get_bus(adap->hwadapnr);
9048dfcbaa6SPrzemyslaw Marczak 	if (!i2c_bus)
9058dfcbaa6SPrzemyslaw Marczak 		return -EFAULT;
9068dfcbaa6SPrzemyslaw Marczak 
907d3b63577SJean-Christophe PLAGNIOL-VILLARD 	if (alen > 4) {
908ab7e52bbSRajeshwari Shinde 		debug("I2C read: addr len %d not supported\n", alen);
9098dfcbaa6SPrzemyslaw Marczak 		return -EADDRNOTAVAIL;
910d3b63577SJean-Christophe PLAGNIOL-VILLARD 	}
911d3b63577SJean-Christophe PLAGNIOL-VILLARD 
912d3b63577SJean-Christophe PLAGNIOL-VILLARD 	if (alen > 0) {
913d3b63577SJean-Christophe PLAGNIOL-VILLARD 		xaddr[0] = (addr >> 24) & 0xFF;
914d3b63577SJean-Christophe PLAGNIOL-VILLARD 		xaddr[1] = (addr >> 16) & 0xFF;
915d3b63577SJean-Christophe PLAGNIOL-VILLARD 		xaddr[2] = (addr >> 8) & 0xFF;
916d3b63577SJean-Christophe PLAGNIOL-VILLARD 		xaddr[3] = addr & 0xFF;
917d3b63577SJean-Christophe PLAGNIOL-VILLARD 	}
918d3b63577SJean-Christophe PLAGNIOL-VILLARD 
919d3b63577SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
920d3b63577SJean-Christophe PLAGNIOL-VILLARD 	/*
921d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * EEPROM chips that implement "address overflow" are ones
922d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * like Catalyst 24WC04/08/16 which has 9/10/11 bits of
923d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * address and the extra bits end up in the "chip address"
924d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * bit slots. This makes a 24WC08 (1Kbyte) chip look like
925d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * four 256 byte chips.
926d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 *
927d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * Note that we consider the length of the address field to
928d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * still be one byte because the extra address bits are
929d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * hidden in the chip address.
930d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 */
931d3b63577SJean-Christophe PLAGNIOL-VILLARD 	if (alen > 0)
932eb0ae7f5Skevin.morfitt@fearnside-systems.co.uk 		chip |= ((addr >> (alen * 8)) &
933eb0ae7f5Skevin.morfitt@fearnside-systems.co.uk 			 CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
934d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif
935296a461dSNaveen Krishna Ch 	if (i2c_bus->is_highspeed)
936296a461dSNaveen Krishna Ch 		ret = hsi2c_read(i2c_bus->hsregs, chip, &xaddr[4 - alen],
937296a461dSNaveen Krishna Ch 				 alen, buffer, len);
938296a461dSNaveen Krishna Ch 	else
939296a461dSNaveen Krishna Ch 		ret = i2c_transfer(i2c_bus->regs, I2C_READ, chip << 1,
940296a461dSNaveen Krishna Ch 				&xaddr[4 - alen], alen, buffer, len);
941296a461dSNaveen Krishna Ch 
942296a461dSNaveen Krishna Ch 	if (ret) {
943296a461dSNaveen Krishna Ch 		if (i2c_bus->is_highspeed)
944296a461dSNaveen Krishna Ch 			exynos5_i2c_reset(i2c_bus);
945296a461dSNaveen Krishna Ch 		debug("I2c read failed %d\n", ret);
9468dfcbaa6SPrzemyslaw Marczak 		return -EIO;
947d3b63577SJean-Christophe PLAGNIOL-VILLARD 	}
948d3b63577SJean-Christophe PLAGNIOL-VILLARD 	return 0;
949d3b63577SJean-Christophe PLAGNIOL-VILLARD }
950d3b63577SJean-Christophe PLAGNIOL-VILLARD 
9512d8f1e27SPiotr Wilczek static int s3c24x0_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
9522d8f1e27SPiotr Wilczek 			 int alen, uchar *buffer, int len)
953d3b63577SJean-Christophe PLAGNIOL-VILLARD {
954296a461dSNaveen Krishna Ch 	struct s3c24x0_i2c_bus *i2c_bus;
955d3b63577SJean-Christophe PLAGNIOL-VILLARD 	uchar xaddr[4];
956296a461dSNaveen Krishna Ch 	int ret;
957d3b63577SJean-Christophe PLAGNIOL-VILLARD 
9588dfcbaa6SPrzemyslaw Marczak 	i2c_bus = get_bus(adap->hwadapnr);
9598dfcbaa6SPrzemyslaw Marczak 	if (!i2c_bus)
9608dfcbaa6SPrzemyslaw Marczak 		return -EFAULT;
9618dfcbaa6SPrzemyslaw Marczak 
962d3b63577SJean-Christophe PLAGNIOL-VILLARD 	if (alen > 4) {
963ab7e52bbSRajeshwari Shinde 		debug("I2C write: addr len %d not supported\n", alen);
9648dfcbaa6SPrzemyslaw Marczak 		return -EINVAL;
965d3b63577SJean-Christophe PLAGNIOL-VILLARD 	}
966d3b63577SJean-Christophe PLAGNIOL-VILLARD 
967d3b63577SJean-Christophe PLAGNIOL-VILLARD 	if (alen > 0) {
968d3b63577SJean-Christophe PLAGNIOL-VILLARD 		xaddr[0] = (addr >> 24) & 0xFF;
969d3b63577SJean-Christophe PLAGNIOL-VILLARD 		xaddr[1] = (addr >> 16) & 0xFF;
970d3b63577SJean-Christophe PLAGNIOL-VILLARD 		xaddr[2] = (addr >> 8) & 0xFF;
971d3b63577SJean-Christophe PLAGNIOL-VILLARD 		xaddr[3] = addr & 0xFF;
972d3b63577SJean-Christophe PLAGNIOL-VILLARD 	}
973d3b63577SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
974d3b63577SJean-Christophe PLAGNIOL-VILLARD 	/*
975d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * EEPROM chips that implement "address overflow" are ones
976d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * like Catalyst 24WC04/08/16 which has 9/10/11 bits of
977d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * address and the extra bits end up in the "chip address"
978d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * bit slots. This makes a 24WC08 (1Kbyte) chip look like
979d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * four 256 byte chips.
980d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 *
981d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * Note that we consider the length of the address field to
982d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * still be one byte because the extra address bits are
983d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * hidden in the chip address.
984d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 */
985d3b63577SJean-Christophe PLAGNIOL-VILLARD 	if (alen > 0)
986eb0ae7f5Skevin.morfitt@fearnside-systems.co.uk 		chip |= ((addr >> (alen * 8)) &
987eb0ae7f5Skevin.morfitt@fearnside-systems.co.uk 			 CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
988d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif
989296a461dSNaveen Krishna Ch 	if (i2c_bus->is_highspeed)
990296a461dSNaveen Krishna Ch 		ret = hsi2c_write(i2c_bus->hsregs, chip, &xaddr[4 - alen],
991296a461dSNaveen Krishna Ch 				  alen, buffer, len, true);
992296a461dSNaveen Krishna Ch 	else
993296a461dSNaveen Krishna Ch 		ret = i2c_transfer(i2c_bus->regs, I2C_WRITE, chip << 1,
994296a461dSNaveen Krishna Ch 				&xaddr[4 - alen], alen, buffer, len);
995296a461dSNaveen Krishna Ch 
996296a461dSNaveen Krishna Ch 	if (ret != 0) {
997296a461dSNaveen Krishna Ch 		if (i2c_bus->is_highspeed)
998296a461dSNaveen Krishna Ch 			exynos5_i2c_reset(i2c_bus);
999296a461dSNaveen Krishna Ch 		return 1;
1000296a461dSNaveen Krishna Ch 	} else {
1001296a461dSNaveen Krishna Ch 		return 0;
1002296a461dSNaveen Krishna Ch 	}
1003d3b63577SJean-Christophe PLAGNIOL-VILLARD }
1004a9d2ae70SRajeshwari Shinde 
10051ae76d43SAmar #ifdef CONFIG_OF_CONTROL
1006296a461dSNaveen Krishna Ch static void process_nodes(const void *blob, int node_list[], int count,
1007296a461dSNaveen Krishna Ch 			 int is_highspeed)
1008a9d2ae70SRajeshwari Shinde {
1009296a461dSNaveen Krishna Ch 	struct s3c24x0_i2c_bus *bus;
10108dfcbaa6SPrzemyslaw Marczak 	int i, flags;
1011a9d2ae70SRajeshwari Shinde 
1012a9d2ae70SRajeshwari Shinde 	for (i = 0; i < count; i++) {
1013a9d2ae70SRajeshwari Shinde 		int node = node_list[i];
1014a9d2ae70SRajeshwari Shinde 
1015a9d2ae70SRajeshwari Shinde 		if (node <= 0)
1016a9d2ae70SRajeshwari Shinde 			continue;
1017296a461dSNaveen Krishna Ch 
1018a9d2ae70SRajeshwari Shinde 		bus = &i2c_bus[i];
1019940dd162SSimon Glass 		bus->active = true;
1020296a461dSNaveen Krishna Ch 		bus->is_highspeed = is_highspeed;
1021296a461dSNaveen Krishna Ch 
10228dfcbaa6SPrzemyslaw Marczak 		if (is_highspeed) {
10238dfcbaa6SPrzemyslaw Marczak 			flags = PINMUX_FLAG_HS_MODE;
1024296a461dSNaveen Krishna Ch 			bus->hsregs = (struct exynos5_hsi2c *)
1025296a461dSNaveen Krishna Ch 					fdtdec_get_addr(blob, node, "reg");
10268dfcbaa6SPrzemyslaw Marczak 		} else {
10278dfcbaa6SPrzemyslaw Marczak 			flags = 0;
1028a9d2ae70SRajeshwari Shinde 			bus->regs = (struct s3c24x0_i2c *)
1029a9d2ae70SRajeshwari Shinde 					fdtdec_get_addr(blob, node, "reg");
10308dfcbaa6SPrzemyslaw Marczak 		}
1031296a461dSNaveen Krishna Ch 
1032a9d2ae70SRajeshwari Shinde 		bus->id = pinmux_decode_periph_id(blob, node);
1033296a461dSNaveen Krishna Ch 		bus->clock_frequency = fdtdec_get_int(blob, node,
1034296a461dSNaveen Krishna Ch 						"clock-frequency",
10352d8f1e27SPiotr Wilczek 						CONFIG_SYS_I2C_S3C24X0_SPEED);
1036a9d2ae70SRajeshwari Shinde 		bus->node = node;
1037940dd162SSimon Glass 		bus->bus_num = i;
10388fd3ec77SSimon Glass 		exynos_pinmux_config(bus->id, flags);
1039296a461dSNaveen Krishna Ch 
1040296a461dSNaveen Krishna Ch 		/* Mark position as used */
1041296a461dSNaveen Krishna Ch 		node_list[i] = -1;
1042a9d2ae70SRajeshwari Shinde 	}
1043a9d2ae70SRajeshwari Shinde }
1044a9d2ae70SRajeshwari Shinde 
1045296a461dSNaveen Krishna Ch void board_i2c_init(const void *blob)
1046a9d2ae70SRajeshwari Shinde {
1047296a461dSNaveen Krishna Ch 	int node_list[CONFIG_MAX_I2C_NUM];
1048296a461dSNaveen Krishna Ch 	int count;
1049940dd162SSimon Glass 
1050296a461dSNaveen Krishna Ch 	/* First get the normal i2c ports */
1051296a461dSNaveen Krishna Ch 	count = fdtdec_find_aliases_for_id(blob, "i2c",
1052296a461dSNaveen Krishna Ch 		COMPAT_SAMSUNG_S3C2440_I2C, node_list,
1053296a461dSNaveen Krishna Ch 		CONFIG_MAX_I2C_NUM);
1054296a461dSNaveen Krishna Ch 	process_nodes(blob, node_list, count, 0);
1055a9d2ae70SRajeshwari Shinde 
1056296a461dSNaveen Krishna Ch 	/* Now look for high speed i2c ports */
1057296a461dSNaveen Krishna Ch 	count = fdtdec_find_aliases_for_id(blob, "i2c",
1058296a461dSNaveen Krishna Ch 		COMPAT_SAMSUNG_EXYNOS5_I2C, node_list,
1059296a461dSNaveen Krishna Ch 		CONFIG_MAX_I2C_NUM);
1060296a461dSNaveen Krishna Ch 	process_nodes(blob, node_list, count, 1);
1061a9d2ae70SRajeshwari Shinde }
1062a9d2ae70SRajeshwari Shinde 
1063a9d2ae70SRajeshwari Shinde int i2c_get_bus_num_fdt(int node)
1064a9d2ae70SRajeshwari Shinde {
1065a9d2ae70SRajeshwari Shinde 	int i;
1066a9d2ae70SRajeshwari Shinde 
1067940dd162SSimon Glass 	for (i = 0; i < ARRAY_SIZE(i2c_bus); i++) {
1068a9d2ae70SRajeshwari Shinde 		if (node == i2c_bus[i].node)
1069a9d2ae70SRajeshwari Shinde 			return i;
1070a9d2ae70SRajeshwari Shinde 	}
1071a9d2ae70SRajeshwari Shinde 
1072a9d2ae70SRajeshwari Shinde 	debug("%s: Can't find any matched I2C bus\n", __func__);
10738dfcbaa6SPrzemyslaw Marczak 	return -EINVAL;
1074a9d2ae70SRajeshwari Shinde }
1075a9d2ae70SRajeshwari Shinde 
1076a9d2ae70SRajeshwari Shinde int i2c_reset_port_fdt(const void *blob, int node)
1077a9d2ae70SRajeshwari Shinde {
1078296a461dSNaveen Krishna Ch 	struct s3c24x0_i2c_bus *i2c_bus;
1079a9d2ae70SRajeshwari Shinde 	int bus;
1080a9d2ae70SRajeshwari Shinde 
1081a9d2ae70SRajeshwari Shinde 	bus = i2c_get_bus_num_fdt(node);
1082a9d2ae70SRajeshwari Shinde 	if (bus < 0) {
1083a9d2ae70SRajeshwari Shinde 		debug("could not get bus for node %d\n", node);
10848dfcbaa6SPrzemyslaw Marczak 		return bus;
1085a9d2ae70SRajeshwari Shinde 	}
1086a9d2ae70SRajeshwari Shinde 
1087296a461dSNaveen Krishna Ch 	i2c_bus = get_bus(bus);
1088296a461dSNaveen Krishna Ch 	if (!i2c_bus) {
10898dfcbaa6SPrzemyslaw Marczak 		debug("get_bus() failed for node %d\n", node);
10908dfcbaa6SPrzemyslaw Marczak 		return -EFAULT;
1091a9d2ae70SRajeshwari Shinde 	}
1092a9d2ae70SRajeshwari Shinde 
1093296a461dSNaveen Krishna Ch 	if (i2c_bus->is_highspeed) {
1094296a461dSNaveen Krishna Ch 		if (hsi2c_get_clk_details(i2c_bus))
10958dfcbaa6SPrzemyslaw Marczak 			return -EINVAL;
1096296a461dSNaveen Krishna Ch 		hsi2c_ch_init(i2c_bus);
1097296a461dSNaveen Krishna Ch 	} else {
1098296a461dSNaveen Krishna Ch 		i2c_ch_init(i2c_bus->regs, i2c_bus->clock_frequency,
10992d8f1e27SPiotr Wilczek 			    CONFIG_SYS_I2C_S3C24X0_SLAVE);
1100296a461dSNaveen Krishna Ch 	}
1101a9d2ae70SRajeshwari Shinde 
1102a9d2ae70SRajeshwari Shinde 	return 0;
1103a9d2ae70SRajeshwari Shinde }
11048dfcbaa6SPrzemyslaw Marczak #endif /* CONFIG_OF_CONTROL */
11058dfcbaa6SPrzemyslaw Marczak 
11068dfcbaa6SPrzemyslaw Marczak #ifdef CONFIG_EXYNOS5
11078dfcbaa6SPrzemyslaw Marczak static void exynos_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
11088dfcbaa6SPrzemyslaw Marczak {
11098dfcbaa6SPrzemyslaw Marczak 	/* This will override the speed selected in the fdt for that port */
11108dfcbaa6SPrzemyslaw Marczak 	debug("i2c_init(speed=%u, slaveaddr=0x%x)\n", speed, slaveaddr);
11118dfcbaa6SPrzemyslaw Marczak 	if (i2c_set_bus_speed(speed))
11128dfcbaa6SPrzemyslaw Marczak 		error("i2c_init: failed to init bus for speed = %d", speed);
11138dfcbaa6SPrzemyslaw Marczak }
11148dfcbaa6SPrzemyslaw Marczak #endif /* CONFIG_EXYNOS5 */
1115a9d2ae70SRajeshwari Shinde 
11162d8f1e27SPiotr Wilczek /*
11172d8f1e27SPiotr Wilczek  * Register s3c24x0 i2c adapters
11182d8f1e27SPiotr Wilczek  */
1119e717fc6dSNaveen Krishna Ch #if defined(CONFIG_EXYNOS5420)
1120e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c00, s3c24x0_i2c_init, s3c24x0_i2c_probe,
11212d8f1e27SPiotr Wilczek 			s3c24x0_i2c_read, s3c24x0_i2c_write,
11222d8f1e27SPiotr Wilczek 			s3c24x0_i2c_set_bus_speed,
11232d8f1e27SPiotr Wilczek 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1124e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 0)
1125e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c01, s3c24x0_i2c_init, s3c24x0_i2c_probe,
11262d8f1e27SPiotr Wilczek 			s3c24x0_i2c_read, s3c24x0_i2c_write,
11272d8f1e27SPiotr Wilczek 			s3c24x0_i2c_set_bus_speed,
11282d8f1e27SPiotr Wilczek 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1129e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 1)
1130e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c02, s3c24x0_i2c_init, s3c24x0_i2c_probe,
11312d8f1e27SPiotr Wilczek 			s3c24x0_i2c_read, s3c24x0_i2c_write,
11322d8f1e27SPiotr Wilczek 			s3c24x0_i2c_set_bus_speed,
11332d8f1e27SPiotr Wilczek 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1134e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 2)
1135e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c03, exynos_i2c_init, s3c24x0_i2c_probe,
11362d8f1e27SPiotr Wilczek 			s3c24x0_i2c_read, s3c24x0_i2c_write,
11372d8f1e27SPiotr Wilczek 			s3c24x0_i2c_set_bus_speed,
11382d8f1e27SPiotr Wilczek 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1139e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 3)
1140e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c04, exynos_i2c_init, s3c24x0_i2c_probe,
11412d8f1e27SPiotr Wilczek 			s3c24x0_i2c_read, s3c24x0_i2c_write,
11422d8f1e27SPiotr Wilczek 			s3c24x0_i2c_set_bus_speed,
11432d8f1e27SPiotr Wilczek 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1144e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 4)
1145e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c05, exynos_i2c_init, s3c24x0_i2c_probe,
11462d8f1e27SPiotr Wilczek 			s3c24x0_i2c_read, s3c24x0_i2c_write,
11472d8f1e27SPiotr Wilczek 			s3c24x0_i2c_set_bus_speed,
11482d8f1e27SPiotr Wilczek 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1149e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 5)
1150e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c06, exynos_i2c_init, s3c24x0_i2c_probe,
11512d8f1e27SPiotr Wilczek 			s3c24x0_i2c_read, s3c24x0_i2c_write,
11522d8f1e27SPiotr Wilczek 			s3c24x0_i2c_set_bus_speed,
11532d8f1e27SPiotr Wilczek 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1154e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 6)
1155e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c07, exynos_i2c_init, s3c24x0_i2c_probe,
11562d8f1e27SPiotr Wilczek 			s3c24x0_i2c_read, s3c24x0_i2c_write,
11572d8f1e27SPiotr Wilczek 			s3c24x0_i2c_set_bus_speed,
11582d8f1e27SPiotr Wilczek 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1159e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 7)
1160e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c08, exynos_i2c_init, s3c24x0_i2c_probe,
1161e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_read, s3c24x0_i2c_write,
1162e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_set_bus_speed,
1163e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1164e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 8)
1165e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c09, exynos_i2c_init, s3c24x0_i2c_probe,
1166e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_read, s3c24x0_i2c_write,
1167e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_set_bus_speed,
1168e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1169e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 9)
1170e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c10, exynos_i2c_init, s3c24x0_i2c_probe,
1171e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_read, s3c24x0_i2c_write,
1172e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_set_bus_speed,
1173e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1174e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 10)
1175e717fc6dSNaveen Krishna Ch #elif defined(CONFIG_EXYNOS5250)
1176e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c00, exynos_i2c_init, s3c24x0_i2c_probe,
1177e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_read, s3c24x0_i2c_write,
1178e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_set_bus_speed,
1179e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1180e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 0)
1181e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c01, exynos_i2c_init, s3c24x0_i2c_probe,
1182e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_read, s3c24x0_i2c_write,
1183e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_set_bus_speed,
1184e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1185e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 1)
1186e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c02, exynos_i2c_init, s3c24x0_i2c_probe,
1187e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_read, s3c24x0_i2c_write,
1188e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_set_bus_speed,
1189e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1190e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 2)
1191e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c03, exynos_i2c_init, s3c24x0_i2c_probe,
1192e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_read, s3c24x0_i2c_write,
1193e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_set_bus_speed,
1194e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1195e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 3)
1196e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c04, s3c24x0_i2c_init, s3c24x0_i2c_probe,
1197e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_read, s3c24x0_i2c_write,
1198e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_set_bus_speed,
1199e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1200e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 4)
1201e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c05, s3c24x0_i2c_init, s3c24x0_i2c_probe,
1202e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_read, s3c24x0_i2c_write,
1203e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_set_bus_speed,
1204e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1205e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 5)
1206e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c06, s3c24x0_i2c_init, s3c24x0_i2c_probe,
1207e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_read, s3c24x0_i2c_write,
1208e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_set_bus_speed,
1209e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1210e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 6)
1211e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c07, s3c24x0_i2c_init, s3c24x0_i2c_probe,
1212e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_read, s3c24x0_i2c_write,
1213e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_set_bus_speed,
1214e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1215e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 7)
1216e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c08, s3c24x0_i2c_init, s3c24x0_i2c_probe,
1217e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_read, s3c24x0_i2c_write,
1218e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_set_bus_speed,
1219e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1220e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 8)
1221e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c09, s3c24x0_i2c_init, s3c24x0_i2c_probe,
1222e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_read, s3c24x0_i2c_write,
1223e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_set_bus_speed,
1224e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1225e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 9)
1226e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(s3c10, s3c24x0_i2c_init, s3c24x0_i2c_probe,
1227e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_read, s3c24x0_i2c_write,
1228e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_set_bus_speed,
1229e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1230e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 10)
1231e717fc6dSNaveen Krishna Ch #elif defined(CONFIG_EXYNOS4)
1232e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c00, s3c24x0_i2c_init, s3c24x0_i2c_probe,
1233e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_read, s3c24x0_i2c_write,
1234e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_set_bus_speed,
1235e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1236e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 0)
1237e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c01, s3c24x0_i2c_init, s3c24x0_i2c_probe,
1238e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_read, s3c24x0_i2c_write,
1239e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_set_bus_speed,
1240e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1241e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 1)
1242e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c02, s3c24x0_i2c_init, s3c24x0_i2c_probe,
1243e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_read, s3c24x0_i2c_write,
1244e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_set_bus_speed,
1245e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1246e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 2)
1247e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c03, s3c24x0_i2c_init, s3c24x0_i2c_probe,
1248e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_read, s3c24x0_i2c_write,
1249e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_set_bus_speed,
1250e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1251e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 3)
1252e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c04, s3c24x0_i2c_init, s3c24x0_i2c_probe,
1253e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_read, s3c24x0_i2c_write,
1254e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_set_bus_speed,
1255e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1256e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 4)
1257e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c05, s3c24x0_i2c_init, s3c24x0_i2c_probe,
1258e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_read, s3c24x0_i2c_write,
1259e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_set_bus_speed,
1260e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1261e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 5)
1262e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c06, s3c24x0_i2c_init, s3c24x0_i2c_probe,
1263e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_read, s3c24x0_i2c_write,
1264e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_set_bus_speed,
1265e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1266e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 6)
1267e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c07, s3c24x0_i2c_init, s3c24x0_i2c_probe,
1268e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_read, s3c24x0_i2c_write,
1269e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_set_bus_speed,
1270e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1271e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 7)
1272e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(i2c08, s3c24x0_i2c_init, s3c24x0_i2c_probe,
1273e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_read, s3c24x0_i2c_write,
1274e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_set_bus_speed,
1275e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1276e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 8)
1277e717fc6dSNaveen Krishna Ch #else
1278e717fc6dSNaveen Krishna Ch U_BOOT_I2C_ADAP_COMPLETE(s3c0, s3c24x0_i2c_init, s3c24x0_i2c_probe,
1279e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_read, s3c24x0_i2c_write,
1280e717fc6dSNaveen Krishna Ch 			s3c24x0_i2c_set_bus_speed,
1281e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SPEED,
1282e717fc6dSNaveen Krishna Ch 			CONFIG_SYS_I2C_S3C24X0_SLAVE, 0)
1283e717fc6dSNaveen Krishna Ch #endif
12848dfcbaa6SPrzemyslaw Marczak #endif /* CONFIG_SYS_I2C */
12858dfcbaa6SPrzemyslaw Marczak 
12868dfcbaa6SPrzemyslaw Marczak #ifdef CONFIG_DM_I2C
1287*45d9ae87SSimon Glass static int exynos_hs_i2c_xfer(struct udevice *dev, struct i2c_msg *msg,
1288*45d9ae87SSimon Glass 			      int nmsgs)
12898dfcbaa6SPrzemyslaw Marczak {
1290*45d9ae87SSimon Glass 	struct s3c24x0_i2c_bus *i2c_bus = dev_get_priv(dev);
1291*45d9ae87SSimon Glass 	struct exynos5_hsi2c *hsregs = i2c_bus->hsregs;
12928dfcbaa6SPrzemyslaw Marczak 	int ret;
12938dfcbaa6SPrzemyslaw Marczak 
1294*45d9ae87SSimon Glass 	for (; nmsgs > 0; nmsgs--, msg++) {
1295*45d9ae87SSimon Glass 		if (msg->flags & I2C_M_RD) {
1296*45d9ae87SSimon Glass 			ret = hsi2c_read(hsregs, msg->addr, 0, 0, msg->buf,
1297*45d9ae87SSimon Glass 					 msg->len);
12988dfcbaa6SPrzemyslaw Marczak 		} else {
1299*45d9ae87SSimon Glass 			ret = hsi2c_write(hsregs, msg->addr, 0, 0, msg->buf,
1300*45d9ae87SSimon Glass 					  msg->len, true);
1301*45d9ae87SSimon Glass 		}
1302*45d9ae87SSimon Glass 		if (ret) {
1303*45d9ae87SSimon Glass 			exynos5_i2c_reset(i2c_bus);
1304*45d9ae87SSimon Glass 			return -EREMOTEIO;
1305*45d9ae87SSimon Glass 		}
13068dfcbaa6SPrzemyslaw Marczak 	}
13078dfcbaa6SPrzemyslaw Marczak 
1308*45d9ae87SSimon Glass 	return 0;
13098dfcbaa6SPrzemyslaw Marczak }
13108dfcbaa6SPrzemyslaw Marczak 
1311*45d9ae87SSimon Glass static int s3c24x0_do_msg(struct s3c24x0_i2c_bus *i2c_bus, struct i2c_msg *msg,
1312*45d9ae87SSimon Glass 			  int seq)
13138dfcbaa6SPrzemyslaw Marczak {
1314*45d9ae87SSimon Glass 	struct s3c24x0_i2c *i2c = i2c_bus->regs;
1315*45d9ae87SSimon Glass 	bool is_read = msg->flags & I2C_M_RD;
1316*45d9ae87SSimon Glass 	uint status;
1317*45d9ae87SSimon Glass 	uint addr;
1318*45d9ae87SSimon Glass 	int ret, i;
13198dfcbaa6SPrzemyslaw Marczak 
1320*45d9ae87SSimon Glass 	if (!seq)
1321*45d9ae87SSimon Glass 		setbits_le32(&i2c->iiccon, I2CCON_ACKGEN);
1322*45d9ae87SSimon Glass 
1323*45d9ae87SSimon Glass 	/* Get the slave chip address going */
1324*45d9ae87SSimon Glass 	addr = msg->addr << 1;
1325*45d9ae87SSimon Glass 	writel(addr, &i2c->iicds);
1326*45d9ae87SSimon Glass 	status = I2C_TXRX_ENA | I2C_START_STOP;
1327*45d9ae87SSimon Glass 	if (is_read)
1328*45d9ae87SSimon Glass 		status |= I2C_MODE_MR;
1329*45d9ae87SSimon Glass 	else
1330*45d9ae87SSimon Glass 		status |= I2C_MODE_MT;
1331*45d9ae87SSimon Glass 	writel(status, &i2c->iicstat);
1332*45d9ae87SSimon Glass 	if (seq)
1333*45d9ae87SSimon Glass 		read_write_byte(i2c);
1334*45d9ae87SSimon Glass 
1335*45d9ae87SSimon Glass 	/* Wait for chip address to transmit */
1336*45d9ae87SSimon Glass 	ret = WaitForXfer(i2c);
13378dfcbaa6SPrzemyslaw Marczak 	if (ret)
1338*45d9ae87SSimon Glass 		goto err;
1339*45d9ae87SSimon Glass 
1340*45d9ae87SSimon Glass 	if (is_read) {
1341*45d9ae87SSimon Glass 		for (i = 0; !ret && i < msg->len; i++) {
1342*45d9ae87SSimon Glass 			/* disable ACK for final READ */
1343*45d9ae87SSimon Glass 			if (i == msg->len - 1)
1344*45d9ae87SSimon Glass 				clrbits_le32(&i2c->iiccon, I2CCON_ACKGEN);
1345*45d9ae87SSimon Glass 			read_write_byte(i2c);
1346*45d9ae87SSimon Glass 			ret = WaitForXfer(i2c);
1347*45d9ae87SSimon Glass 			msg->buf[i] = readl(&i2c->iicds);
1348*45d9ae87SSimon Glass 		}
1349*45d9ae87SSimon Glass 		if (ret == I2C_NACK)
1350*45d9ae87SSimon Glass 			ret = I2C_OK; /* Normal terminated read */
13518dfcbaa6SPrzemyslaw Marczak 	} else {
1352*45d9ae87SSimon Glass 		for (i = 0; !ret && i < msg->len; i++) {
1353*45d9ae87SSimon Glass 			writel(msg->buf[i], &i2c->iicds);
1354*45d9ae87SSimon Glass 			read_write_byte(i2c);
1355*45d9ae87SSimon Glass 			ret = WaitForXfer(i2c);
1356*45d9ae87SSimon Glass 		}
13578dfcbaa6SPrzemyslaw Marczak 	}
13588dfcbaa6SPrzemyslaw Marczak 
1359*45d9ae87SSimon Glass err:
1360*45d9ae87SSimon Glass 	return ret;
13618dfcbaa6SPrzemyslaw Marczak }
13628dfcbaa6SPrzemyslaw Marczak 
13638dfcbaa6SPrzemyslaw Marczak static int s3c24x0_i2c_xfer(struct udevice *dev, struct i2c_msg *msg,
13648dfcbaa6SPrzemyslaw Marczak 			    int nmsgs)
13658dfcbaa6SPrzemyslaw Marczak {
13668dfcbaa6SPrzemyslaw Marczak 	struct s3c24x0_i2c_bus *i2c_bus = dev_get_priv(dev);
1367*45d9ae87SSimon Glass 	struct s3c24x0_i2c *i2c = i2c_bus->regs;
1368*45d9ae87SSimon Glass 	ulong start_time;
1369*45d9ae87SSimon Glass 	int ret, i;
13708dfcbaa6SPrzemyslaw Marczak 
1371*45d9ae87SSimon Glass 	start_time = get_timer(0);
1372*45d9ae87SSimon Glass 	while (readl(&i2c->iicstat) & I2CSTAT_BSY) {
1373*45d9ae87SSimon Glass 		if (get_timer(start_time) > I2C_TIMEOUT_MS) {
1374*45d9ae87SSimon Glass 			debug("Timeout\n");
1375*45d9ae87SSimon Glass 			return -ETIMEDOUT;
13768dfcbaa6SPrzemyslaw Marczak 		}
13778dfcbaa6SPrzemyslaw Marczak 	}
13788dfcbaa6SPrzemyslaw Marczak 
1379*45d9ae87SSimon Glass 	for (ret = 0, i = 0; !ret && i < nmsgs; i++)
1380*45d9ae87SSimon Glass 		ret = s3c24x0_do_msg(i2c_bus, &msg[i], i);
1381*45d9ae87SSimon Glass 
1382*45d9ae87SSimon Glass 	/* Send STOP */
1383*45d9ae87SSimon Glass 	writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat);
1384*45d9ae87SSimon Glass 	read_write_byte(i2c);
1385*45d9ae87SSimon Glass 
1386*45d9ae87SSimon Glass 	return ret ? -EREMOTEIO : 0;
13878dfcbaa6SPrzemyslaw Marczak }
13888dfcbaa6SPrzemyslaw Marczak 
13898dfcbaa6SPrzemyslaw Marczak static int s3c_i2c_ofdata_to_platdata(struct udevice *dev)
13908dfcbaa6SPrzemyslaw Marczak {
13918dfcbaa6SPrzemyslaw Marczak 	const void *blob = gd->fdt_blob;
13928dfcbaa6SPrzemyslaw Marczak 	struct s3c24x0_i2c_bus *i2c_bus = dev_get_priv(dev);
13938dfcbaa6SPrzemyslaw Marczak 	int node, flags;
13948dfcbaa6SPrzemyslaw Marczak 
139539de8433SSimon Glass 	i2c_bus->is_highspeed = dev_get_driver_data(dev);
13968dfcbaa6SPrzemyslaw Marczak 	node = dev->of_offset;
13978dfcbaa6SPrzemyslaw Marczak 
13988dfcbaa6SPrzemyslaw Marczak 	if (i2c_bus->is_highspeed) {
13998dfcbaa6SPrzemyslaw Marczak 		flags = PINMUX_FLAG_HS_MODE;
14008dfcbaa6SPrzemyslaw Marczak 		i2c_bus->hsregs = (struct exynos5_hsi2c *)
14018dfcbaa6SPrzemyslaw Marczak 				fdtdec_get_addr(blob, node, "reg");
14028dfcbaa6SPrzemyslaw Marczak 	} else {
14038dfcbaa6SPrzemyslaw Marczak 		flags = 0;
14048dfcbaa6SPrzemyslaw Marczak 		i2c_bus->regs = (struct s3c24x0_i2c *)
14058dfcbaa6SPrzemyslaw Marczak 				fdtdec_get_addr(blob, node, "reg");
14068dfcbaa6SPrzemyslaw Marczak 	}
14078dfcbaa6SPrzemyslaw Marczak 
14088dfcbaa6SPrzemyslaw Marczak 	i2c_bus->id = pinmux_decode_periph_id(blob, node);
14098dfcbaa6SPrzemyslaw Marczak 
14108dfcbaa6SPrzemyslaw Marczak 	i2c_bus->clock_frequency = fdtdec_get_int(blob, node,
1411*45d9ae87SSimon Glass 						  "clock-frequency", 100000);
14128dfcbaa6SPrzemyslaw Marczak 	i2c_bus->node = node;
14138dfcbaa6SPrzemyslaw Marczak 	i2c_bus->bus_num = dev->seq;
14148dfcbaa6SPrzemyslaw Marczak 
14158dfcbaa6SPrzemyslaw Marczak 	exynos_pinmux_config(i2c_bus->id, flags);
14168dfcbaa6SPrzemyslaw Marczak 
14178dfcbaa6SPrzemyslaw Marczak 	i2c_bus->active = true;
14188dfcbaa6SPrzemyslaw Marczak 
14198dfcbaa6SPrzemyslaw Marczak 	return 0;
14208dfcbaa6SPrzemyslaw Marczak }
14218dfcbaa6SPrzemyslaw Marczak 
14228dfcbaa6SPrzemyslaw Marczak static const struct dm_i2c_ops s3c_i2c_ops = {
14238dfcbaa6SPrzemyslaw Marczak 	.xfer		= s3c24x0_i2c_xfer,
14248dfcbaa6SPrzemyslaw Marczak 	.probe_chip	= s3c24x0_i2c_probe,
14258dfcbaa6SPrzemyslaw Marczak 	.set_bus_speed	= s3c24x0_i2c_set_bus_speed,
14268dfcbaa6SPrzemyslaw Marczak };
14278dfcbaa6SPrzemyslaw Marczak 
14288dfcbaa6SPrzemyslaw Marczak static const struct udevice_id s3c_i2c_ids[] = {
14298dfcbaa6SPrzemyslaw Marczak 	{ .compatible = "samsung,s3c2440-i2c", .data = EXYNOS_I2C_STD },
14308dfcbaa6SPrzemyslaw Marczak 	{ }
14318dfcbaa6SPrzemyslaw Marczak };
14328dfcbaa6SPrzemyslaw Marczak 
14338dfcbaa6SPrzemyslaw Marczak U_BOOT_DRIVER(i2c_s3c) = {
14348dfcbaa6SPrzemyslaw Marczak 	.name	= "i2c_s3c",
14358dfcbaa6SPrzemyslaw Marczak 	.id	= UCLASS_I2C,
14368dfcbaa6SPrzemyslaw Marczak 	.of_match = s3c_i2c_ids,
14378dfcbaa6SPrzemyslaw Marczak 	.ofdata_to_platdata = s3c_i2c_ofdata_to_platdata,
14388dfcbaa6SPrzemyslaw Marczak 	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
14398dfcbaa6SPrzemyslaw Marczak 	.priv_auto_alloc_size = sizeof(struct s3c24x0_i2c_bus),
14408dfcbaa6SPrzemyslaw Marczak 	.ops	= &s3c_i2c_ops,
14418dfcbaa6SPrzemyslaw Marczak };
1442*45d9ae87SSimon Glass 
1443*45d9ae87SSimon Glass /*
1444*45d9ae87SSimon Glass  * TODO(sjg@chromium.org): Move this to a separate file when everything uses
1445*45d9ae87SSimon Glass  * driver model
1446*45d9ae87SSimon Glass  */
1447*45d9ae87SSimon Glass static const struct dm_i2c_ops exynos_hs_i2c_ops = {
1448*45d9ae87SSimon Glass 	.xfer		= exynos_hs_i2c_xfer,
1449*45d9ae87SSimon Glass 	.probe_chip	= s3c24x0_i2c_probe,
1450*45d9ae87SSimon Glass 	.set_bus_speed	= s3c24x0_i2c_set_bus_speed,
1451*45d9ae87SSimon Glass };
1452*45d9ae87SSimon Glass 
1453*45d9ae87SSimon Glass static const struct udevice_id exynos_hs_i2c_ids[] = {
1454*45d9ae87SSimon Glass 	{ .compatible = "samsung,exynos5-hsi2c", .data = EXYNOS_I2C_HS },
1455*45d9ae87SSimon Glass 	{ }
1456*45d9ae87SSimon Glass };
1457*45d9ae87SSimon Glass 
1458*45d9ae87SSimon Glass U_BOOT_DRIVER(hs_i2c) = {
1459*45d9ae87SSimon Glass 	.name	= "i2c_s3c_hs",
1460*45d9ae87SSimon Glass 	.id	= UCLASS_I2C,
1461*45d9ae87SSimon Glass 	.of_match = exynos_hs_i2c_ids,
1462*45d9ae87SSimon Glass 	.ofdata_to_platdata = s3c_i2c_ofdata_to_platdata,
1463*45d9ae87SSimon Glass 	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
1464*45d9ae87SSimon Glass 	.priv_auto_alloc_size = sizeof(struct s3c24x0_i2c_bus),
1465*45d9ae87SSimon Glass 	.ops	= &exynos_hs_i2c_ops,
1466*45d9ae87SSimon Glass };
14678dfcbaa6SPrzemyslaw Marczak #endif /* CONFIG_DM_I2C */
1468