xref: /rk3399_rockchip-uboot/drivers/i2c/s3c24x0_i2c.c (revision e4e2402071e8052eab7fb10ecfbdec01310ac06f)
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 
13d3b63577SJean-Christophe PLAGNIOL-VILLARD #include <common.h>
14a9d2ae70SRajeshwari Shinde #include <fdtdec.h>
15c86d9ed3SPiotr Wilczek #if (defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
16ab7e52bbSRajeshwari Shinde #include <asm/arch/clk.h>
17ab7e52bbSRajeshwari Shinde #include <asm/arch/cpu.h>
18a9d2ae70SRajeshwari Shinde #include <asm/arch/pinmux.h>
19ab7e52bbSRajeshwari Shinde #else
20ac67804fSkevin.morfitt@fearnside-systems.co.uk #include <asm/arch/s3c24x0_cpu.h>
21ab7e52bbSRajeshwari Shinde #endif
22eb0ae7f5Skevin.morfitt@fearnside-systems.co.uk #include <asm/io.h>
23d3b63577SJean-Christophe PLAGNIOL-VILLARD #include <i2c.h>
24ab7e52bbSRajeshwari Shinde #include "s3c24x0_i2c.h"
25d3b63577SJean-Christophe PLAGNIOL-VILLARD 
26d3b63577SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_HARD_I2C
27d3b63577SJean-Christophe PLAGNIOL-VILLARD 
28d3b63577SJean-Christophe PLAGNIOL-VILLARD #define	I2C_WRITE	0
29d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2C_READ	1
30d3b63577SJean-Christophe PLAGNIOL-VILLARD 
31d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2C_OK		0
32d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2C_NOK		1
33d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2C_NACK	2
34d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2C_NOK_LA	3	/* Lost arbitration */
35d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2C_NOK_TOUT	4	/* time out */
36d3b63577SJean-Christophe PLAGNIOL-VILLARD 
37d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2CSTAT_BSY	0x20	/* Busy bit */
38d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2CSTAT_NACK	0x01	/* Nack bit */
39ab7e52bbSRajeshwari Shinde #define I2CCON_ACKGEN	0x80	/* Acknowledge generation */
40d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2CCON_IRPND	0x10	/* Interrupt pending bit */
41d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2C_MODE_MT	0xC0	/* Master Transmit Mode */
42d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2C_MODE_MR	0x80	/* Master Receive Mode */
43d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2C_START_STOP	0x20	/* START / STOP */
44d3b63577SJean-Christophe PLAGNIOL-VILLARD #define I2C_TXRX_ENA	0x10	/* I2C Tx/Rx enable */
45d3b63577SJean-Christophe PLAGNIOL-VILLARD 
46*e4e24020SNaveen Krishna Ch #define I2C_TIMEOUT_MS 1000		/* 1 second */
47d3b63577SJean-Christophe PLAGNIOL-VILLARD 
48ab7e52bbSRajeshwari Shinde 
49a9d2ae70SRajeshwari Shinde /*
50a9d2ae70SRajeshwari Shinde  * For SPL boot some boards need i2c before SDRAM is initialised so force
51a9d2ae70SRajeshwari Shinde  * variables to live in SRAM
52a9d2ae70SRajeshwari Shinde  */
53a9d2ae70SRajeshwari Shinde static unsigned int g_current_bus __attribute__((section(".data")));
54d04df3c6SRajeshwari Shinde #ifdef CONFIG_OF_CONTROL
55d04df3c6SRajeshwari Shinde static int i2c_busses __attribute__((section(".data")));
56a9d2ae70SRajeshwari Shinde static struct s3c24x0_i2c_bus i2c_bus[CONFIG_MAX_I2C_NUM]
57a9d2ae70SRajeshwari Shinde 			__attribute__((section(".data")));
58d04df3c6SRajeshwari Shinde #endif
59ab7e52bbSRajeshwari Shinde 
60c86d9ed3SPiotr Wilczek #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
61d3b63577SJean-Christophe PLAGNIOL-VILLARD static int GetI2CSDA(void)
62d3b63577SJean-Christophe PLAGNIOL-VILLARD {
63eb0ae7f5Skevin.morfitt@fearnside-systems.co.uk 	struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
64d3b63577SJean-Christophe PLAGNIOL-VILLARD 
65d3b63577SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_S3C2410
66d9abba82SC Nauman 	return (readl(&gpio->gpedat) & 0x8000) >> 15;
67d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif
68d3b63577SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_S3C2400
69d9abba82SC Nauman 	return (readl(&gpio->pgdat) & 0x0020) >> 5;
70d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif
71d3b63577SJean-Christophe PLAGNIOL-VILLARD }
72d3b63577SJean-Christophe PLAGNIOL-VILLARD 
73d3b63577SJean-Christophe PLAGNIOL-VILLARD static void SetI2CSCL(int x)
74d3b63577SJean-Christophe PLAGNIOL-VILLARD {
75eb0ae7f5Skevin.morfitt@fearnside-systems.co.uk 	struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
76d3b63577SJean-Christophe PLAGNIOL-VILLARD 
77d3b63577SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_S3C2410
78ab7e52bbSRajeshwari Shinde 	writel((readl(&gpio->gpedat) & ~0x4000) |
79ab7e52bbSRajeshwari Shinde 					(x & 1) << 14, &gpio->gpedat);
80d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif
81d3b63577SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_S3C2400
82d9abba82SC Nauman 	writel((readl(&gpio->pgdat) & ~0x0040) | (x & 1) << 6, &gpio->pgdat);
83d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif
84d3b63577SJean-Christophe PLAGNIOL-VILLARD }
85ab7e52bbSRajeshwari Shinde #endif
86d3b63577SJean-Christophe PLAGNIOL-VILLARD 
87*e4e24020SNaveen Krishna Ch /*
88*e4e24020SNaveen Krishna Ch  * Wait til the byte transfer is completed.
89*e4e24020SNaveen Krishna Ch  *
90*e4e24020SNaveen Krishna Ch  * @param i2c- pointer to the appropriate i2c register bank.
91*e4e24020SNaveen Krishna Ch  * @return I2C_OK, if transmission was ACKED
92*e4e24020SNaveen Krishna Ch  *         I2C_NACK, if transmission was NACKED
93*e4e24020SNaveen Krishna Ch  *         I2C_NOK_TIMEOUT, if transaction did not complete in I2C_TIMEOUT_MS
94*e4e24020SNaveen Krishna Ch  */
95*e4e24020SNaveen Krishna Ch 
96ab7e52bbSRajeshwari Shinde static int WaitForXfer(struct s3c24x0_i2c *i2c)
97d3b63577SJean-Christophe PLAGNIOL-VILLARD {
98*e4e24020SNaveen Krishna Ch 	ulong start_time = get_timer(0);
99d3b63577SJean-Christophe PLAGNIOL-VILLARD 
100*e4e24020SNaveen Krishna Ch 	do {
101*e4e24020SNaveen Krishna Ch 		if (readl(&i2c->iiccon) & I2CCON_IRPND)
102*e4e24020SNaveen Krishna Ch 			return (readl(&i2c->iicstat) & I2CSTAT_NACK) ?
103*e4e24020SNaveen Krishna Ch 				I2C_NACK : I2C_OK;
104*e4e24020SNaveen Krishna Ch 	} while (get_timer(start_time) < I2C_TIMEOUT_MS);
105d3b63577SJean-Christophe PLAGNIOL-VILLARD 
106*e4e24020SNaveen Krishna Ch 	return I2C_NOK_TOUT;
107d3b63577SJean-Christophe PLAGNIOL-VILLARD }
108d3b63577SJean-Christophe PLAGNIOL-VILLARD 
109ab7e52bbSRajeshwari Shinde static void ReadWriteByte(struct s3c24x0_i2c *i2c)
110d3b63577SJean-Christophe PLAGNIOL-VILLARD {
111d9abba82SC Nauman 	writel(readl(&i2c->iiccon) & ~I2CCON_IRPND, &i2c->iiccon);
112d3b63577SJean-Christophe PLAGNIOL-VILLARD }
113d3b63577SJean-Christophe PLAGNIOL-VILLARD 
114ab7e52bbSRajeshwari Shinde static struct s3c24x0_i2c *get_base_i2c(void)
115ab7e52bbSRajeshwari Shinde {
116c86d9ed3SPiotr Wilczek #ifdef CONFIG_EXYNOS4
117c86d9ed3SPiotr Wilczek 	struct s3c24x0_i2c *i2c = (struct s3c24x0_i2c *)(samsung_get_base_i2c()
118c86d9ed3SPiotr Wilczek 							+ (EXYNOS4_I2C_SPACING
119c86d9ed3SPiotr Wilczek 							* g_current_bus));
120c86d9ed3SPiotr Wilczek 	return i2c;
121c86d9ed3SPiotr Wilczek #elif defined CONFIG_EXYNOS5
122ab7e52bbSRajeshwari Shinde 	struct s3c24x0_i2c *i2c = (struct s3c24x0_i2c *)(samsung_get_base_i2c()
123ab7e52bbSRajeshwari Shinde 							+ (EXYNOS5_I2C_SPACING
124ab7e52bbSRajeshwari Shinde 							* g_current_bus));
125ab7e52bbSRajeshwari Shinde 	return i2c;
126ab7e52bbSRajeshwari Shinde #else
127ab7e52bbSRajeshwari Shinde 	return s3c24x0_get_base_i2c();
128ab7e52bbSRajeshwari Shinde #endif
129ab7e52bbSRajeshwari Shinde }
130ab7e52bbSRajeshwari Shinde 
131ab7e52bbSRajeshwari Shinde static void i2c_ch_init(struct s3c24x0_i2c *i2c, int speed, int slaveadd)
132ab7e52bbSRajeshwari Shinde {
133ab7e52bbSRajeshwari Shinde 	ulong freq, pres = 16, div;
134c86d9ed3SPiotr Wilczek #if (defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
135ab7e52bbSRajeshwari Shinde 	freq = get_i2c_clk();
136ab7e52bbSRajeshwari Shinde #else
137ab7e52bbSRajeshwari Shinde 	freq = get_PCLK();
138ab7e52bbSRajeshwari Shinde #endif
139ab7e52bbSRajeshwari Shinde 	/* calculate prescaler and divisor values */
140ab7e52bbSRajeshwari Shinde 	if ((freq / pres / (16 + 1)) > speed)
141ab7e52bbSRajeshwari Shinde 		/* set prescaler to 512 */
142ab7e52bbSRajeshwari Shinde 		pres = 512;
143ab7e52bbSRajeshwari Shinde 
144ab7e52bbSRajeshwari Shinde 	div = 0;
145ab7e52bbSRajeshwari Shinde 	while ((freq / pres / (div + 1)) > speed)
146ab7e52bbSRajeshwari Shinde 		div++;
147ab7e52bbSRajeshwari Shinde 
148ab7e52bbSRajeshwari Shinde 	/* set prescaler, divisor according to freq, also set ACKGEN, IRQ */
149ab7e52bbSRajeshwari Shinde 	writel((div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0), &i2c->iiccon);
150ab7e52bbSRajeshwari Shinde 
151ab7e52bbSRajeshwari Shinde 	/* init to SLAVE REVEIVE and set slaveaddr */
152ab7e52bbSRajeshwari Shinde 	writel(0, &i2c->iicstat);
153ab7e52bbSRajeshwari Shinde 	writel(slaveadd, &i2c->iicadd);
154ab7e52bbSRajeshwari Shinde 	/* program Master Transmit (and implicit STOP) */
155ab7e52bbSRajeshwari Shinde 	writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat);
156ab7e52bbSRajeshwari Shinde }
157ab7e52bbSRajeshwari Shinde 
158178239deSRajeshwari Shinde /*
159178239deSRajeshwari Shinde  * MULTI BUS I2C support
160178239deSRajeshwari Shinde  */
161178239deSRajeshwari Shinde 
162178239deSRajeshwari Shinde #ifdef CONFIG_I2C_MULTI_BUS
163178239deSRajeshwari Shinde int i2c_set_bus_num(unsigned int bus)
164178239deSRajeshwari Shinde {
165178239deSRajeshwari Shinde 	struct s3c24x0_i2c *i2c;
166178239deSRajeshwari Shinde 
167178239deSRajeshwari Shinde 	if ((bus < 0) || (bus >= CONFIG_MAX_I2C_NUM)) {
168178239deSRajeshwari Shinde 		debug("Bad bus: %d\n", bus);
169178239deSRajeshwari Shinde 		return -1;
170178239deSRajeshwari Shinde 	}
171178239deSRajeshwari Shinde 
172178239deSRajeshwari Shinde 	g_current_bus = bus;
173178239deSRajeshwari Shinde 	i2c = get_base_i2c();
174178239deSRajeshwari Shinde 	i2c_ch_init(i2c, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
175178239deSRajeshwari Shinde 
176178239deSRajeshwari Shinde 	return 0;
177178239deSRajeshwari Shinde }
178178239deSRajeshwari Shinde 
179178239deSRajeshwari Shinde unsigned int i2c_get_bus_num(void)
180178239deSRajeshwari Shinde {
181178239deSRajeshwari Shinde 	return g_current_bus;
182178239deSRajeshwari Shinde }
183178239deSRajeshwari Shinde #endif
184178239deSRajeshwari Shinde 
185d3b63577SJean-Christophe PLAGNIOL-VILLARD void i2c_init(int speed, int slaveadd)
186d3b63577SJean-Christophe PLAGNIOL-VILLARD {
187*e4e24020SNaveen Krishna Ch 	int i;
188ab7e52bbSRajeshwari Shinde 	struct s3c24x0_i2c *i2c;
189c86d9ed3SPiotr Wilczek #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
190eb0ae7f5Skevin.morfitt@fearnside-systems.co.uk 	struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
191ab7e52bbSRajeshwari Shinde #endif
192*e4e24020SNaveen Krishna Ch 	ulong start_time = get_timer(0);
193d3b63577SJean-Christophe PLAGNIOL-VILLARD 
194ab7e52bbSRajeshwari Shinde 	/* By default i2c channel 0 is the current bus */
195ab7e52bbSRajeshwari Shinde 	g_current_bus = 0;
196ab7e52bbSRajeshwari Shinde 	i2c = get_base_i2c();
197d3b63577SJean-Christophe PLAGNIOL-VILLARD 
198*e4e24020SNaveen Krishna Ch 	/*
199*e4e24020SNaveen Krishna Ch 	 * In case the previous transfer is still going, wait to give it a
200*e4e24020SNaveen Krishna Ch 	 * chance to finish.
201*e4e24020SNaveen Krishna Ch 	 */
202*e4e24020SNaveen Krishna Ch 	while (readl(&i2c->iicstat) & I2CSTAT_BSY) {
203*e4e24020SNaveen Krishna Ch 		if (get_timer(start_time) > I2C_TIMEOUT_MS) {
204*e4e24020SNaveen Krishna Ch 			printf("%s: I2C bus busy for %p\n", __func__,
205*e4e24020SNaveen Krishna Ch 			       &i2c->iicstat);
206*e4e24020SNaveen Krishna Ch 			return;
207*e4e24020SNaveen Krishna Ch 		}
208d3b63577SJean-Christophe PLAGNIOL-VILLARD 	}
209d3b63577SJean-Christophe PLAGNIOL-VILLARD 
210c86d9ed3SPiotr Wilczek #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
211d9abba82SC Nauman 	if ((readl(&i2c->iicstat) & I2CSTAT_BSY) || GetI2CSDA() == 0) {
212d3b63577SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_S3C2410
213d9abba82SC Nauman 		ulong old_gpecon = readl(&gpio->gpecon);
214d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif
215d3b63577SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_S3C2400
216d9abba82SC Nauman 		ulong old_gpecon = readl(&gpio->pgcon);
217d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif
218eb0ae7f5Skevin.morfitt@fearnside-systems.co.uk 		/* bus still busy probably by (most) previously interrupted
219eb0ae7f5Skevin.morfitt@fearnside-systems.co.uk 		   transfer */
220d3b63577SJean-Christophe PLAGNIOL-VILLARD 
221d3b63577SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_S3C2410
222d3b63577SJean-Christophe PLAGNIOL-VILLARD 		/* set I2CSDA and I2CSCL (GPE15, GPE14) to GPIO */
223d9abba82SC Nauman 		writel((readl(&gpio->gpecon) & ~0xF0000000) | 0x10000000,
224d9abba82SC Nauman 		       &gpio->gpecon);
225d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif
226d3b63577SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_S3C2400
227d3b63577SJean-Christophe PLAGNIOL-VILLARD 		/* set I2CSDA and I2CSCL (PG5, PG6) to GPIO */
228d9abba82SC Nauman 		writel((readl(&gpio->pgcon) & ~0x00003c00) | 0x00001000,
229d9abba82SC Nauman 		       &gpio->pgcon);
230d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif
231d3b63577SJean-Christophe PLAGNIOL-VILLARD 
232d3b63577SJean-Christophe PLAGNIOL-VILLARD 		/* toggle I2CSCL until bus idle */
233d3b63577SJean-Christophe PLAGNIOL-VILLARD 		SetI2CSCL(0);
234d3b63577SJean-Christophe PLAGNIOL-VILLARD 		udelay(1000);
235d3b63577SJean-Christophe PLAGNIOL-VILLARD 		i = 10;
236d3b63577SJean-Christophe PLAGNIOL-VILLARD 		while ((i > 0) && (GetI2CSDA() != 1)) {
237d3b63577SJean-Christophe PLAGNIOL-VILLARD 			SetI2CSCL(1);
238d3b63577SJean-Christophe PLAGNIOL-VILLARD 			udelay(1000);
239d3b63577SJean-Christophe PLAGNIOL-VILLARD 			SetI2CSCL(0);
240d3b63577SJean-Christophe PLAGNIOL-VILLARD 			udelay(1000);
241d3b63577SJean-Christophe PLAGNIOL-VILLARD 			i--;
242d3b63577SJean-Christophe PLAGNIOL-VILLARD 		}
243d3b63577SJean-Christophe PLAGNIOL-VILLARD 		SetI2CSCL(1);
244d3b63577SJean-Christophe PLAGNIOL-VILLARD 		udelay(1000);
245d3b63577SJean-Christophe PLAGNIOL-VILLARD 
246d3b63577SJean-Christophe PLAGNIOL-VILLARD 		/* restore pin functions */
247d3b63577SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_S3C2410
248d9abba82SC Nauman 		writel(old_gpecon, &gpio->gpecon);
249d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif
250d3b63577SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_S3C2400
251d9abba82SC Nauman 		writel(old_gpecon, &gpio->pgcon);
252d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif
253d3b63577SJean-Christophe PLAGNIOL-VILLARD 	}
254c86d9ed3SPiotr Wilczek #endif /* #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5) */
255ab7e52bbSRajeshwari Shinde 	i2c_ch_init(i2c, speed, slaveadd);
256d3b63577SJean-Christophe PLAGNIOL-VILLARD }
257d3b63577SJean-Christophe PLAGNIOL-VILLARD 
258d3b63577SJean-Christophe PLAGNIOL-VILLARD /*
259d3b63577SJean-Christophe PLAGNIOL-VILLARD  * cmd_type is 0 for write, 1 for read.
260d3b63577SJean-Christophe PLAGNIOL-VILLARD  *
261d3b63577SJean-Christophe PLAGNIOL-VILLARD  * addr_len can take any value from 0-255, it is only limited
262d3b63577SJean-Christophe PLAGNIOL-VILLARD  * by the char, we could make it larger if needed. If it is
263d3b63577SJean-Christophe PLAGNIOL-VILLARD  * 0 we skip the address write cycle.
264d3b63577SJean-Christophe PLAGNIOL-VILLARD  */
265ab7e52bbSRajeshwari Shinde static int i2c_transfer(struct s3c24x0_i2c *i2c,
266ab7e52bbSRajeshwari Shinde 			unsigned char cmd_type,
267d3b63577SJean-Christophe PLAGNIOL-VILLARD 			unsigned char chip,
268d3b63577SJean-Christophe PLAGNIOL-VILLARD 			unsigned char addr[],
269d3b63577SJean-Christophe PLAGNIOL-VILLARD 			unsigned char addr_len,
270ab7e52bbSRajeshwari Shinde 			unsigned char data[],
271ab7e52bbSRajeshwari Shinde 			unsigned short data_len)
272d3b63577SJean-Christophe PLAGNIOL-VILLARD {
273*e4e24020SNaveen Krishna Ch 	int i = 0, result;
274*e4e24020SNaveen Krishna Ch 	ulong start_time = get_timer(0);
275d3b63577SJean-Christophe PLAGNIOL-VILLARD 
276d3b63577SJean-Christophe PLAGNIOL-VILLARD 	if (data == 0 || data_len == 0) {
277d3b63577SJean-Christophe PLAGNIOL-VILLARD 		/*Don't support data transfer of no length or to address 0 */
278ab7e52bbSRajeshwari Shinde 		debug("i2c_transfer: bad call\n");
279d3b63577SJean-Christophe PLAGNIOL-VILLARD 		return I2C_NOK;
280d3b63577SJean-Christophe PLAGNIOL-VILLARD 	}
281d3b63577SJean-Christophe PLAGNIOL-VILLARD 
282*e4e24020SNaveen Krishna Ch 	while (readl(&i2c->iicstat) & I2CSTAT_BSY) {
283*e4e24020SNaveen Krishna Ch 		if (get_timer(start_time) > I2C_TIMEOUT_MS)
284*e4e24020SNaveen Krishna Ch 			return I2C_NOK_TOUT;
285d3b63577SJean-Christophe PLAGNIOL-VILLARD 	}
286d3b63577SJean-Christophe PLAGNIOL-VILLARD 
287ab7e52bbSRajeshwari Shinde 	writel(readl(&i2c->iiccon) | I2CCON_ACKGEN, &i2c->iiccon);
288*e4e24020SNaveen Krishna Ch 
289*e4e24020SNaveen Krishna Ch 	/* Get the slave chip address going */
290*e4e24020SNaveen Krishna Ch 	writel(chip, &i2c->iicds);
291*e4e24020SNaveen Krishna Ch 	if ((cmd_type == I2C_WRITE) || (addr && addr_len))
292*e4e24020SNaveen Krishna Ch 		writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP,
293*e4e24020SNaveen Krishna Ch 		       &i2c->iicstat);
294*e4e24020SNaveen Krishna Ch 	else
295*e4e24020SNaveen Krishna Ch 		writel(I2C_MODE_MR | I2C_TXRX_ENA | I2C_START_STOP,
296*e4e24020SNaveen Krishna Ch 		       &i2c->iicstat);
297*e4e24020SNaveen Krishna Ch 
298*e4e24020SNaveen Krishna Ch 	/* Wait for chip address to transmit. */
299*e4e24020SNaveen Krishna Ch 	result = WaitForXfer(i2c);
300*e4e24020SNaveen Krishna Ch 	if (result != I2C_OK)
301*e4e24020SNaveen Krishna Ch 		goto bailout;
302*e4e24020SNaveen Krishna Ch 
303*e4e24020SNaveen Krishna Ch 	/* If register address needs to be transmitted - do it now. */
304*e4e24020SNaveen Krishna Ch 	if (addr && addr_len) {
305*e4e24020SNaveen Krishna Ch 		while ((i < addr_len) && (result == I2C_OK)) {
306*e4e24020SNaveen Krishna Ch 			writel(addr[i++], &i2c->iicds);
307*e4e24020SNaveen Krishna Ch 			ReadWriteByte(i2c);
308*e4e24020SNaveen Krishna Ch 			result = WaitForXfer(i2c);
309*e4e24020SNaveen Krishna Ch 		}
310*e4e24020SNaveen Krishna Ch 		i = 0;
311*e4e24020SNaveen Krishna Ch 		if (result != I2C_OK)
312*e4e24020SNaveen Krishna Ch 			goto bailout;
313*e4e24020SNaveen Krishna Ch 	}
314d3b63577SJean-Christophe PLAGNIOL-VILLARD 
315d3b63577SJean-Christophe PLAGNIOL-VILLARD 	switch (cmd_type) {
316d3b63577SJean-Christophe PLAGNIOL-VILLARD 	case I2C_WRITE:
317d3b63577SJean-Christophe PLAGNIOL-VILLARD 		while ((i < data_len) && (result == I2C_OK)) {
318*e4e24020SNaveen Krishna Ch 			writel(data[i++], &i2c->iicds);
319ab7e52bbSRajeshwari Shinde 			ReadWriteByte(i2c);
320ab7e52bbSRajeshwari Shinde 			result = WaitForXfer(i2c);
321d3b63577SJean-Christophe PLAGNIOL-VILLARD 		}
322d3b63577SJean-Christophe PLAGNIOL-VILLARD 		break;
323d3b63577SJean-Christophe PLAGNIOL-VILLARD 
324d3b63577SJean-Christophe PLAGNIOL-VILLARD 	case I2C_READ:
325d3b63577SJean-Christophe PLAGNIOL-VILLARD 		if (addr && addr_len) {
326*e4e24020SNaveen Krishna Ch 			/*
327*e4e24020SNaveen Krishna Ch 			 * Register address has been sent, now send slave chip
328*e4e24020SNaveen Krishna Ch 			 * address again to start the actual read transaction.
329*e4e24020SNaveen Krishna Ch 			 */
330d9abba82SC Nauman 			writel(chip, &i2c->iicds);
331*e4e24020SNaveen Krishna Ch 
332*e4e24020SNaveen Krishna Ch 			/* Generate a re-START. */
333*e4e24020SNaveen Krishna Ch 			writel(I2C_MODE_MR | I2C_TXRX_ENA | I2C_START_STOP,
334d9abba82SC Nauman 				&i2c->iicstat);
335ab7e52bbSRajeshwari Shinde 			ReadWriteByte(i2c);
336ab7e52bbSRajeshwari Shinde 			result = WaitForXfer(i2c);
337*e4e24020SNaveen Krishna Ch 
338*e4e24020SNaveen Krishna Ch 			if (result != I2C_OK)
339*e4e24020SNaveen Krishna Ch 				goto bailout;
340d3b63577SJean-Christophe PLAGNIOL-VILLARD 		}
341d3b63577SJean-Christophe PLAGNIOL-VILLARD 
342d3b63577SJean-Christophe PLAGNIOL-VILLARD 		while ((i < data_len) && (result == I2C_OK)) {
343d3b63577SJean-Christophe PLAGNIOL-VILLARD 			/* disable ACK for final READ */
344d3b63577SJean-Christophe PLAGNIOL-VILLARD 			if (i == data_len - 1)
345d9abba82SC Nauman 				writel(readl(&i2c->iiccon)
346ab7e52bbSRajeshwari Shinde 				       & ~I2CCON_ACKGEN,
347ab7e52bbSRajeshwari Shinde 				       &i2c->iiccon);
348ab7e52bbSRajeshwari Shinde 			ReadWriteByte(i2c);
349ab7e52bbSRajeshwari Shinde 			result = WaitForXfer(i2c);
350*e4e24020SNaveen Krishna Ch 			data[i++] = readl(&i2c->iicds);
351d3b63577SJean-Christophe PLAGNIOL-VILLARD 		}
352*e4e24020SNaveen Krishna Ch 		if (result == I2C_NACK)
353*e4e24020SNaveen Krishna Ch 			result = I2C_OK; /* Normal terminated read. */
354d3b63577SJean-Christophe PLAGNIOL-VILLARD 		break;
355d3b63577SJean-Christophe PLAGNIOL-VILLARD 
356d3b63577SJean-Christophe PLAGNIOL-VILLARD 	default:
357ab7e52bbSRajeshwari Shinde 		debug("i2c_transfer: bad call\n");
358d3b63577SJean-Christophe PLAGNIOL-VILLARD 		result = I2C_NOK;
359d3b63577SJean-Christophe PLAGNIOL-VILLARD 		break;
360d3b63577SJean-Christophe PLAGNIOL-VILLARD 	}
361d3b63577SJean-Christophe PLAGNIOL-VILLARD 
362*e4e24020SNaveen Krishna Ch bailout:
363*e4e24020SNaveen Krishna Ch 	/* Send STOP. */
364*e4e24020SNaveen Krishna Ch 	writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat);
365*e4e24020SNaveen Krishna Ch 	ReadWriteByte(i2c);
366*e4e24020SNaveen Krishna Ch 
367ab7e52bbSRajeshwari Shinde 	return result;
368d3b63577SJean-Christophe PLAGNIOL-VILLARD }
369d3b63577SJean-Christophe PLAGNIOL-VILLARD 
370d3b63577SJean-Christophe PLAGNIOL-VILLARD int i2c_probe(uchar chip)
371d3b63577SJean-Christophe PLAGNIOL-VILLARD {
372ab7e52bbSRajeshwari Shinde 	struct s3c24x0_i2c *i2c;
373d3b63577SJean-Christophe PLAGNIOL-VILLARD 	uchar buf[1];
374d3b63577SJean-Christophe PLAGNIOL-VILLARD 
375ab7e52bbSRajeshwari Shinde 	i2c = get_base_i2c();
376d3b63577SJean-Christophe PLAGNIOL-VILLARD 	buf[0] = 0;
377d3b63577SJean-Christophe PLAGNIOL-VILLARD 
378d3b63577SJean-Christophe PLAGNIOL-VILLARD 	/*
379d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * What is needed is to send the chip address and verify that the
380d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * address was <ACK>ed (i.e. there was a chip at that address which
381d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * drove the data line low).
382d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 */
383ab7e52bbSRajeshwari Shinde 	return i2c_transfer(i2c, I2C_READ, chip << 1, 0, 0, buf, 1) != I2C_OK;
384d3b63577SJean-Christophe PLAGNIOL-VILLARD }
385d3b63577SJean-Christophe PLAGNIOL-VILLARD 
386d3b63577SJean-Christophe PLAGNIOL-VILLARD int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
387d3b63577SJean-Christophe PLAGNIOL-VILLARD {
388ab7e52bbSRajeshwari Shinde 	struct s3c24x0_i2c *i2c;
389d3b63577SJean-Christophe PLAGNIOL-VILLARD 	uchar xaddr[4];
390d3b63577SJean-Christophe PLAGNIOL-VILLARD 	int ret;
391d3b63577SJean-Christophe PLAGNIOL-VILLARD 
392d3b63577SJean-Christophe PLAGNIOL-VILLARD 	if (alen > 4) {
393ab7e52bbSRajeshwari Shinde 		debug("I2C read: addr len %d not supported\n", alen);
394d3b63577SJean-Christophe PLAGNIOL-VILLARD 		return 1;
395d3b63577SJean-Christophe PLAGNIOL-VILLARD 	}
396d3b63577SJean-Christophe PLAGNIOL-VILLARD 
397d3b63577SJean-Christophe PLAGNIOL-VILLARD 	if (alen > 0) {
398d3b63577SJean-Christophe PLAGNIOL-VILLARD 		xaddr[0] = (addr >> 24) & 0xFF;
399d3b63577SJean-Christophe PLAGNIOL-VILLARD 		xaddr[1] = (addr >> 16) & 0xFF;
400d3b63577SJean-Christophe PLAGNIOL-VILLARD 		xaddr[2] = (addr >> 8) & 0xFF;
401d3b63577SJean-Christophe PLAGNIOL-VILLARD 		xaddr[3] = addr & 0xFF;
402d3b63577SJean-Christophe PLAGNIOL-VILLARD 	}
403d3b63577SJean-Christophe PLAGNIOL-VILLARD 
404d3b63577SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
405d3b63577SJean-Christophe PLAGNIOL-VILLARD 	/*
406d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * EEPROM chips that implement "address overflow" are ones
407d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * like Catalyst 24WC04/08/16 which has 9/10/11 bits of
408d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * address and the extra bits end up in the "chip address"
409d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * bit slots. This makes a 24WC08 (1Kbyte) chip look like
410d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * four 256 byte chips.
411d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 *
412d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * Note that we consider the length of the address field to
413d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * still be one byte because the extra address bits are
414d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * hidden in the chip address.
415d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 */
416d3b63577SJean-Christophe PLAGNIOL-VILLARD 	if (alen > 0)
417eb0ae7f5Skevin.morfitt@fearnside-systems.co.uk 		chip |= ((addr >> (alen * 8)) &
418eb0ae7f5Skevin.morfitt@fearnside-systems.co.uk 			 CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
419d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif
420ab7e52bbSRajeshwari Shinde 	i2c = get_base_i2c();
421ab7e52bbSRajeshwari Shinde 	ret = i2c_transfer(i2c, I2C_READ, chip << 1, &xaddr[4 - alen], alen,
422ab7e52bbSRajeshwari Shinde 			buffer, len);
423ab7e52bbSRajeshwari Shinde 	if (ret != 0) {
424ab7e52bbSRajeshwari Shinde 		debug("I2c read: failed %d\n", ret);
425d3b63577SJean-Christophe PLAGNIOL-VILLARD 		return 1;
426d3b63577SJean-Christophe PLAGNIOL-VILLARD 	}
427d3b63577SJean-Christophe PLAGNIOL-VILLARD 	return 0;
428d3b63577SJean-Christophe PLAGNIOL-VILLARD }
429d3b63577SJean-Christophe PLAGNIOL-VILLARD 
430d3b63577SJean-Christophe PLAGNIOL-VILLARD int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
431d3b63577SJean-Christophe PLAGNIOL-VILLARD {
432ab7e52bbSRajeshwari Shinde 	struct s3c24x0_i2c *i2c;
433d3b63577SJean-Christophe PLAGNIOL-VILLARD 	uchar xaddr[4];
434d3b63577SJean-Christophe PLAGNIOL-VILLARD 
435d3b63577SJean-Christophe PLAGNIOL-VILLARD 	if (alen > 4) {
436ab7e52bbSRajeshwari Shinde 		debug("I2C write: addr len %d not supported\n", alen);
437d3b63577SJean-Christophe PLAGNIOL-VILLARD 		return 1;
438d3b63577SJean-Christophe PLAGNIOL-VILLARD 	}
439d3b63577SJean-Christophe PLAGNIOL-VILLARD 
440d3b63577SJean-Christophe PLAGNIOL-VILLARD 	if (alen > 0) {
441d3b63577SJean-Christophe PLAGNIOL-VILLARD 		xaddr[0] = (addr >> 24) & 0xFF;
442d3b63577SJean-Christophe PLAGNIOL-VILLARD 		xaddr[1] = (addr >> 16) & 0xFF;
443d3b63577SJean-Christophe PLAGNIOL-VILLARD 		xaddr[2] = (addr >> 8) & 0xFF;
444d3b63577SJean-Christophe PLAGNIOL-VILLARD 		xaddr[3] = addr & 0xFF;
445d3b63577SJean-Christophe PLAGNIOL-VILLARD 	}
446d3b63577SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
447d3b63577SJean-Christophe PLAGNIOL-VILLARD 	/*
448d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * EEPROM chips that implement "address overflow" are ones
449d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * like Catalyst 24WC04/08/16 which has 9/10/11 bits of
450d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * address and the extra bits end up in the "chip address"
451d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * bit slots. This makes a 24WC08 (1Kbyte) chip look like
452d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * four 256 byte chips.
453d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 *
454d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * Note that we consider the length of the address field to
455d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * still be one byte because the extra address bits are
456d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 * hidden in the chip address.
457d3b63577SJean-Christophe PLAGNIOL-VILLARD 	 */
458d3b63577SJean-Christophe PLAGNIOL-VILLARD 	if (alen > 0)
459eb0ae7f5Skevin.morfitt@fearnside-systems.co.uk 		chip |= ((addr >> (alen * 8)) &
460eb0ae7f5Skevin.morfitt@fearnside-systems.co.uk 			 CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
461d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif
462ab7e52bbSRajeshwari Shinde 	i2c = get_base_i2c();
463d3b63577SJean-Christophe PLAGNIOL-VILLARD 	return (i2c_transfer
464ab7e52bbSRajeshwari Shinde 		(i2c, I2C_WRITE, chip << 1, &xaddr[4 - alen], alen, buffer,
465d3b63577SJean-Christophe PLAGNIOL-VILLARD 		 len) != 0);
466d3b63577SJean-Christophe PLAGNIOL-VILLARD }
467a9d2ae70SRajeshwari Shinde 
4681ae76d43SAmar #ifdef CONFIG_OF_CONTROL
469a9d2ae70SRajeshwari Shinde void board_i2c_init(const void *blob)
470a9d2ae70SRajeshwari Shinde {
4712c07bb9bSAmar 	int i;
472a9d2ae70SRajeshwari Shinde 	int node_list[CONFIG_MAX_I2C_NUM];
4732c07bb9bSAmar 	int count;
474a9d2ae70SRajeshwari Shinde 
475a9d2ae70SRajeshwari Shinde 	count = fdtdec_find_aliases_for_id(blob, "i2c",
476a9d2ae70SRajeshwari Shinde 		COMPAT_SAMSUNG_S3C2440_I2C, node_list,
477a9d2ae70SRajeshwari Shinde 		CONFIG_MAX_I2C_NUM);
478a9d2ae70SRajeshwari Shinde 
479a9d2ae70SRajeshwari Shinde 	for (i = 0; i < count; i++) {
480a9d2ae70SRajeshwari Shinde 		struct s3c24x0_i2c_bus *bus;
481a9d2ae70SRajeshwari Shinde 		int node = node_list[i];
482a9d2ae70SRajeshwari Shinde 
483a9d2ae70SRajeshwari Shinde 		if (node <= 0)
484a9d2ae70SRajeshwari Shinde 			continue;
485a9d2ae70SRajeshwari Shinde 		bus = &i2c_bus[i];
486a9d2ae70SRajeshwari Shinde 		bus->regs = (struct s3c24x0_i2c *)
487a9d2ae70SRajeshwari Shinde 			fdtdec_get_addr(blob, node, "reg");
488a9d2ae70SRajeshwari Shinde 		bus->id = pinmux_decode_periph_id(blob, node);
489a9d2ae70SRajeshwari Shinde 		bus->node = node;
490a9d2ae70SRajeshwari Shinde 		bus->bus_num = i2c_busses++;
491a9d2ae70SRajeshwari Shinde 		exynos_pinmux_config(bus->id, 0);
492a9d2ae70SRajeshwari Shinde 	}
493a9d2ae70SRajeshwari Shinde }
494a9d2ae70SRajeshwari Shinde 
495a9d2ae70SRajeshwari Shinde static struct s3c24x0_i2c_bus *get_bus(unsigned int bus_idx)
496a9d2ae70SRajeshwari Shinde {
497a9d2ae70SRajeshwari Shinde 	if (bus_idx < i2c_busses)
498a9d2ae70SRajeshwari Shinde 		return &i2c_bus[bus_idx];
499a9d2ae70SRajeshwari Shinde 
500a9d2ae70SRajeshwari Shinde 	debug("Undefined bus: %d\n", bus_idx);
501a9d2ae70SRajeshwari Shinde 	return NULL;
502a9d2ae70SRajeshwari Shinde }
503a9d2ae70SRajeshwari Shinde 
504a9d2ae70SRajeshwari Shinde int i2c_get_bus_num_fdt(int node)
505a9d2ae70SRajeshwari Shinde {
506a9d2ae70SRajeshwari Shinde 	int i;
507a9d2ae70SRajeshwari Shinde 
508a9d2ae70SRajeshwari Shinde 	for (i = 0; i < i2c_busses; i++) {
509a9d2ae70SRajeshwari Shinde 		if (node == i2c_bus[i].node)
510a9d2ae70SRajeshwari Shinde 			return i;
511a9d2ae70SRajeshwari Shinde 	}
512a9d2ae70SRajeshwari Shinde 
513a9d2ae70SRajeshwari Shinde 	debug("%s: Can't find any matched I2C bus\n", __func__);
514a9d2ae70SRajeshwari Shinde 	return -1;
515a9d2ae70SRajeshwari Shinde }
516a9d2ae70SRajeshwari Shinde 
517a9d2ae70SRajeshwari Shinde int i2c_reset_port_fdt(const void *blob, int node)
518a9d2ae70SRajeshwari Shinde {
519a9d2ae70SRajeshwari Shinde 	struct s3c24x0_i2c_bus *i2c;
520a9d2ae70SRajeshwari Shinde 	int bus;
521a9d2ae70SRajeshwari Shinde 
522a9d2ae70SRajeshwari Shinde 	bus = i2c_get_bus_num_fdt(node);
523a9d2ae70SRajeshwari Shinde 	if (bus < 0) {
524a9d2ae70SRajeshwari Shinde 		debug("could not get bus for node %d\n", node);
525a9d2ae70SRajeshwari Shinde 		return -1;
526a9d2ae70SRajeshwari Shinde 	}
527a9d2ae70SRajeshwari Shinde 
528a9d2ae70SRajeshwari Shinde 	i2c = get_bus(bus);
529a9d2ae70SRajeshwari Shinde 	if (!i2c) {
530a9d2ae70SRajeshwari Shinde 		debug("get_bus() failed for node node %d\n", node);
531a9d2ae70SRajeshwari Shinde 		return -1;
532a9d2ae70SRajeshwari Shinde 	}
533a9d2ae70SRajeshwari Shinde 
534a9d2ae70SRajeshwari Shinde 	i2c_ch_init(i2c->regs, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
535a9d2ae70SRajeshwari Shinde 
536a9d2ae70SRajeshwari Shinde 	return 0;
537a9d2ae70SRajeshwari Shinde }
538a9d2ae70SRajeshwari Shinde #endif
539a9d2ae70SRajeshwari Shinde 
540d3b63577SJean-Christophe PLAGNIOL-VILLARD #endif /* CONFIG_HARD_I2C */
541