blob: cd09c788bea1c1ba503445561a66e080320c5144 [file] [log] [blame]
wdenk1cb8e982003-03-06 21:55:29 +00001/*
2 * (C) Copyright 2002
3 * David Mueller, ELSOFT AG, d.mueller@elsoft.ch
4 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
wdenk1cb8e982003-03-06 21:55:29 +00006 */
7
8/* This code should work for both the S3C2400 and the S3C2410
9 * as they seem to have the same I2C controller inside.
10 * The different address mapping is handled by the s3c24xx.h files below.
11 */
12
13#include <common.h>
Rajeshwari Shindea9d2ae72012-12-26 20:03:12 +000014#include <fdtdec.h>
Piotr Wilczekc86d9ed2012-11-20 02:19:05 +000015#if (defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +000016#include <asm/arch/clk.h>
17#include <asm/arch/cpu.h>
Rajeshwari Shindea9d2ae72012-12-26 20:03:12 +000018#include <asm/arch/pinmux.h>
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +000019#else
kevin.morfitt@fearnside-systems.co.ukac678042009-11-17 18:30:34 +090020#include <asm/arch/s3c24x0_cpu.h>
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +000021#endif
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +090022#include <asm/io.h>
wdenk1cb8e982003-03-06 21:55:29 +000023#include <i2c.h>
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +000024#include "s3c24x0_i2c.h"
wdenk1cb8e982003-03-06 21:55:29 +000025
26#ifdef CONFIG_HARD_I2C
27
wdenk48b42612003-06-19 23:01:32 +000028#define I2C_WRITE 0
29#define I2C_READ 1
wdenk1cb8e982003-03-06 21:55:29 +000030
wdenk48b42612003-06-19 23:01:32 +000031#define I2C_OK 0
32#define I2C_NOK 1
33#define I2C_NACK 2
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +090034#define I2C_NOK_LA 3 /* Lost arbitration */
35#define I2C_NOK_TOUT 4 /* time out */
wdenk1cb8e982003-03-06 21:55:29 +000036
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +090037#define I2CSTAT_BSY 0x20 /* Busy bit */
38#define I2CSTAT_NACK 0x01 /* Nack bit */
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +000039#define I2CCON_ACKGEN 0x80 /* Acknowledge generation */
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +090040#define I2CCON_IRPND 0x10 /* Interrupt pending bit */
41#define I2C_MODE_MT 0xC0 /* Master Transmit Mode */
42#define I2C_MODE_MR 0x80 /* Master Receive Mode */
43#define I2C_START_STOP 0x20 /* START / STOP */
44#define I2C_TXRX_ENA 0x10 /* I2C Tx/Rx enable */
wdenk1cb8e982003-03-06 21:55:29 +000045
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +090046#define I2C_TIMEOUT 1 /* 1 second */
wdenk1cb8e982003-03-06 21:55:29 +000047
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +000048
Rajeshwari Shindea9d2ae72012-12-26 20:03:12 +000049/*
50 * For SPL boot some boards need i2c before SDRAM is initialised so force
51 * variables to live in SRAM
52 */
53static unsigned int g_current_bus __attribute__((section(".data")));
Rajeshwari Shinded04df3c2013-01-13 19:49:36 +000054#ifdef CONFIG_OF_CONTROL
55static int i2c_busses __attribute__((section(".data")));
Rajeshwari Shindea9d2ae72012-12-26 20:03:12 +000056static struct s3c24x0_i2c_bus i2c_bus[CONFIG_MAX_I2C_NUM]
57 __attribute__((section(".data")));
Rajeshwari Shinded04df3c2013-01-13 19:49:36 +000058#endif
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +000059
Piotr Wilczekc86d9ed2012-11-20 02:19:05 +000060#if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
wdenk48b42612003-06-19 23:01:32 +000061static int GetI2CSDA(void)
wdenk1cb8e982003-03-06 21:55:29 +000062{
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +090063 struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
wdenk48b42612003-06-19 23:01:32 +000064
wdenk6dff5522003-07-15 07:45:49 +000065#ifdef CONFIG_S3C2410
C Naumand9abba82010-10-26 23:04:31 +090066 return (readl(&gpio->gpedat) & 0x8000) >> 15;
wdenk6dff5522003-07-15 07:45:49 +000067#endif
68#ifdef CONFIG_S3C2400
C Naumand9abba82010-10-26 23:04:31 +090069 return (readl(&gpio->pgdat) & 0x0020) >> 5;
wdenk6dff5522003-07-15 07:45:49 +000070#endif
wdenk1cb8e982003-03-06 21:55:29 +000071}
72
wdenk48b42612003-06-19 23:01:32 +000073static void SetI2CSCL(int x)
wdenk1cb8e982003-03-06 21:55:29 +000074{
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +090075 struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
wdenk48b42612003-06-19 23:01:32 +000076
wdenk6dff5522003-07-15 07:45:49 +000077#ifdef CONFIG_S3C2410
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +000078 writel((readl(&gpio->gpedat) & ~0x4000) |
79 (x & 1) << 14, &gpio->gpedat);
wdenk6dff5522003-07-15 07:45:49 +000080#endif
81#ifdef CONFIG_S3C2400
C Naumand9abba82010-10-26 23:04:31 +090082 writel((readl(&gpio->pgdat) & ~0x0040) | (x & 1) << 6, &gpio->pgdat);
wdenk6dff5522003-07-15 07:45:49 +000083#endif
wdenk1cb8e982003-03-06 21:55:29 +000084}
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +000085#endif
wdenk1cb8e982003-03-06 21:55:29 +000086
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +000087static int WaitForXfer(struct s3c24x0_i2c *i2c)
wdenk1cb8e982003-03-06 21:55:29 +000088{
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +090089 int i;
wdenk1cb8e982003-03-06 21:55:29 +000090
wdenkfc3e2162003-10-08 22:33:00 +000091 i = I2C_TIMEOUT * 10000;
C Naumand9abba82010-10-26 23:04:31 +090092 while (!(readl(&i2c->iiccon) & I2CCON_IRPND) && (i > 0)) {
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +090093 udelay(100);
wdenkfc3e2162003-10-08 22:33:00 +000094 i--;
95 }
wdenk1cb8e982003-03-06 21:55:29 +000096
C Naumand9abba82010-10-26 23:04:31 +090097 return (readl(&i2c->iiccon) & I2CCON_IRPND) ? I2C_OK : I2C_NOK_TOUT;
wdenk1cb8e982003-03-06 21:55:29 +000098}
99
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000100static int IsACK(struct s3c24x0_i2c *i2c)
wdenk1cb8e982003-03-06 21:55:29 +0000101{
C Naumand9abba82010-10-26 23:04:31 +0900102 return !(readl(&i2c->iicstat) & I2CSTAT_NACK);
wdenk1cb8e982003-03-06 21:55:29 +0000103}
104
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000105static void ReadWriteByte(struct s3c24x0_i2c *i2c)
wdenk1cb8e982003-03-06 21:55:29 +0000106{
C Naumand9abba82010-10-26 23:04:31 +0900107 writel(readl(&i2c->iiccon) & ~I2CCON_IRPND, &i2c->iiccon);
wdenk1cb8e982003-03-06 21:55:29 +0000108}
109
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000110static struct s3c24x0_i2c *get_base_i2c(void)
111{
Piotr Wilczekc86d9ed2012-11-20 02:19:05 +0000112#ifdef CONFIG_EXYNOS4
113 struct s3c24x0_i2c *i2c = (struct s3c24x0_i2c *)(samsung_get_base_i2c()
114 + (EXYNOS4_I2C_SPACING
115 * g_current_bus));
116 return i2c;
117#elif defined CONFIG_EXYNOS5
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000118 struct s3c24x0_i2c *i2c = (struct s3c24x0_i2c *)(samsung_get_base_i2c()
119 + (EXYNOS5_I2C_SPACING
120 * g_current_bus));
121 return i2c;
122#else
123 return s3c24x0_get_base_i2c();
124#endif
125}
126
127static void i2c_ch_init(struct s3c24x0_i2c *i2c, int speed, int slaveadd)
128{
129 ulong freq, pres = 16, div;
Piotr Wilczekc86d9ed2012-11-20 02:19:05 +0000130#if (defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000131 freq = get_i2c_clk();
132#else
133 freq = get_PCLK();
134#endif
135 /* calculate prescaler and divisor values */
136 if ((freq / pres / (16 + 1)) > speed)
137 /* set prescaler to 512 */
138 pres = 512;
139
140 div = 0;
141 while ((freq / pres / (div + 1)) > speed)
142 div++;
143
144 /* set prescaler, divisor according to freq, also set ACKGEN, IRQ */
145 writel((div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0), &i2c->iiccon);
146
147 /* init to SLAVE REVEIVE and set slaveaddr */
148 writel(0, &i2c->iicstat);
149 writel(slaveadd, &i2c->iicadd);
150 /* program Master Transmit (and implicit STOP) */
151 writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat);
152}
153
Rajeshwari Shinde178239d2012-07-23 21:23:54 +0000154/*
155 * MULTI BUS I2C support
156 */
157
158#ifdef CONFIG_I2C_MULTI_BUS
159int i2c_set_bus_num(unsigned int bus)
160{
161 struct s3c24x0_i2c *i2c;
162
163 if ((bus < 0) || (bus >= CONFIG_MAX_I2C_NUM)) {
164 debug("Bad bus: %d\n", bus);
165 return -1;
166 }
167
168 g_current_bus = bus;
169 i2c = get_base_i2c();
170 i2c_ch_init(i2c, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
171
172 return 0;
173}
174
175unsigned int i2c_get_bus_num(void)
176{
177 return g_current_bus;
178}
179#endif
180
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900181void i2c_init(int speed, int slaveadd)
wdenk1cb8e982003-03-06 21:55:29 +0000182{
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000183 struct s3c24x0_i2c *i2c;
Piotr Wilczekc86d9ed2012-11-20 02:19:05 +0000184#if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900185 struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000186#endif
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900187 int i;
wdenk1cb8e982003-03-06 21:55:29 +0000188
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000189 /* By default i2c channel 0 is the current bus */
190 g_current_bus = 0;
191 i2c = get_base_i2c();
wdenk1cb8e982003-03-06 21:55:29 +0000192
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000193 /* wait for some time to give previous transfer a chance to finish */
wdenkfc3e2162003-10-08 22:33:00 +0000194 i = I2C_TIMEOUT * 1000;
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000195 while ((readl(&i2c->iicstat) & I2CSTAT_BSY) && (i > 0)) {
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900196 udelay(1000);
wdenk1cb8e982003-03-06 21:55:29 +0000197 i--;
198 }
wdenk1cb8e982003-03-06 21:55:29 +0000199
Piotr Wilczekc86d9ed2012-11-20 02:19:05 +0000200#if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
C Naumand9abba82010-10-26 23:04:31 +0900201 if ((readl(&i2c->iicstat) & I2CSTAT_BSY) || GetI2CSDA() == 0) {
wdenk6dff5522003-07-15 07:45:49 +0000202#ifdef CONFIG_S3C2410
C Naumand9abba82010-10-26 23:04:31 +0900203 ulong old_gpecon = readl(&gpio->gpecon);
wdenk6dff5522003-07-15 07:45:49 +0000204#endif
205#ifdef CONFIG_S3C2400
C Naumand9abba82010-10-26 23:04:31 +0900206 ulong old_gpecon = readl(&gpio->pgcon);
wdenk6dff5522003-07-15 07:45:49 +0000207#endif
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900208 /* bus still busy probably by (most) previously interrupted
209 transfer */
wdenk1cb8e982003-03-06 21:55:29 +0000210
wdenkfc3e2162003-10-08 22:33:00 +0000211#ifdef CONFIG_S3C2410
212 /* set I2CSDA and I2CSCL (GPE15, GPE14) to GPIO */
C Naumand9abba82010-10-26 23:04:31 +0900213 writel((readl(&gpio->gpecon) & ~0xF0000000) | 0x10000000,
214 &gpio->gpecon);
wdenkfc3e2162003-10-08 22:33:00 +0000215#endif
216#ifdef CONFIG_S3C2400
217 /* set I2CSDA and I2CSCL (PG5, PG6) to GPIO */
C Naumand9abba82010-10-26 23:04:31 +0900218 writel((readl(&gpio->pgcon) & ~0x00003c00) | 0x00001000,
219 &gpio->pgcon);
wdenkfc3e2162003-10-08 22:33:00 +0000220#endif
wdenk1cb8e982003-03-06 21:55:29 +0000221
wdenkfc3e2162003-10-08 22:33:00 +0000222 /* toggle I2CSCL until bus idle */
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900223 SetI2CSCL(0);
224 udelay(1000);
wdenkfc3e2162003-10-08 22:33:00 +0000225 i = 10;
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900226 while ((i > 0) && (GetI2CSDA() != 1)) {
227 SetI2CSCL(1);
228 udelay(1000);
229 SetI2CSCL(0);
230 udelay(1000);
wdenkfc3e2162003-10-08 22:33:00 +0000231 i--;
232 }
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900233 SetI2CSCL(1);
234 udelay(1000);
wdenk1cb8e982003-03-06 21:55:29 +0000235
wdenkfc3e2162003-10-08 22:33:00 +0000236 /* restore pin functions */
237#ifdef CONFIG_S3C2410
C Naumand9abba82010-10-26 23:04:31 +0900238 writel(old_gpecon, &gpio->gpecon);
wdenkfc3e2162003-10-08 22:33:00 +0000239#endif
240#ifdef CONFIG_S3C2400
C Naumand9abba82010-10-26 23:04:31 +0900241 writel(old_gpecon, &gpio->pgcon);
wdenkfc3e2162003-10-08 22:33:00 +0000242#endif
243 }
Piotr Wilczekc86d9ed2012-11-20 02:19:05 +0000244#endif /* #if !(defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5) */
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000245 i2c_ch_init(i2c, speed, slaveadd);
wdenk1cb8e982003-03-06 21:55:29 +0000246}
247
248/*
wdenkfc3e2162003-10-08 22:33:00 +0000249 * cmd_type is 0 for write, 1 for read.
250 *
251 * addr_len can take any value from 0-255, it is only limited
252 * by the char, we could make it larger if needed. If it is
253 * 0 we skip the address write cycle.
254 */
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000255static int i2c_transfer(struct s3c24x0_i2c *i2c,
256 unsigned char cmd_type,
257 unsigned char chip,
258 unsigned char addr[],
259 unsigned char addr_len,
260 unsigned char data[],
261 unsigned short data_len)
wdenk1cb8e982003-03-06 21:55:29 +0000262{
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900263 int i, result;
wdenk1cb8e982003-03-06 21:55:29 +0000264
wdenkfc3e2162003-10-08 22:33:00 +0000265 if (data == 0 || data_len == 0) {
266 /*Don't support data transfer of no length or to address 0 */
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000267 debug("i2c_transfer: bad call\n");
wdenkfc3e2162003-10-08 22:33:00 +0000268 return I2C_NOK;
269 }
wdenk1cb8e982003-03-06 21:55:29 +0000270
wdenkfc3e2162003-10-08 22:33:00 +0000271 /* Check I2C bus idle */
272 i = I2C_TIMEOUT * 1000;
C Naumand9abba82010-10-26 23:04:31 +0900273 while ((readl(&i2c->iicstat) & I2CSTAT_BSY) && (i > 0)) {
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900274 udelay(1000);
wdenkfc3e2162003-10-08 22:33:00 +0000275 i--;
276 }
wdenk1cb8e982003-03-06 21:55:29 +0000277
C Naumand9abba82010-10-26 23:04:31 +0900278 if (readl(&i2c->iicstat) & I2CSTAT_BSY)
wdenkfc3e2162003-10-08 22:33:00 +0000279 return I2C_NOK_TOUT;
wdenk1cb8e982003-03-06 21:55:29 +0000280
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000281 writel(readl(&i2c->iiccon) | I2CCON_ACKGEN, &i2c->iiccon);
wdenkfc3e2162003-10-08 22:33:00 +0000282 result = I2C_OK;
wdenk1cb8e982003-03-06 21:55:29 +0000283
wdenkfc3e2162003-10-08 22:33:00 +0000284 switch (cmd_type) {
wdenk48b42612003-06-19 23:01:32 +0000285 case I2C_WRITE:
wdenkfc3e2162003-10-08 22:33:00 +0000286 if (addr && addr_len) {
C Naumand9abba82010-10-26 23:04:31 +0900287 writel(chip, &i2c->iicds);
wdenkfc3e2162003-10-08 22:33:00 +0000288 /* send START */
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900289 writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP,
C Naumand9abba82010-10-26 23:04:31 +0900290 &i2c->iicstat);
wdenkfc3e2162003-10-08 22:33:00 +0000291 i = 0;
292 while ((i < addr_len) && (result == I2C_OK)) {
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000293 result = WaitForXfer(i2c);
C Naumand9abba82010-10-26 23:04:31 +0900294 writel(addr[i], &i2c->iicds);
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000295 ReadWriteByte(i2c);
wdenkfc3e2162003-10-08 22:33:00 +0000296 i++;
297 }
298 i = 0;
299 while ((i < data_len) && (result == I2C_OK)) {
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000300 result = WaitForXfer(i2c);
C Naumand9abba82010-10-26 23:04:31 +0900301 writel(data[i], &i2c->iicds);
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000302 ReadWriteByte(i2c);
wdenkfc3e2162003-10-08 22:33:00 +0000303 i++;
304 }
305 } else {
C Naumand9abba82010-10-26 23:04:31 +0900306 writel(chip, &i2c->iicds);
wdenkfc3e2162003-10-08 22:33:00 +0000307 /* send START */
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900308 writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP,
C Naumand9abba82010-10-26 23:04:31 +0900309 &i2c->iicstat);
wdenkfc3e2162003-10-08 22:33:00 +0000310 i = 0;
Rajeshwari Shindecb466c02013-02-19 02:19:45 +0000311 while ((i < data_len) && (result == I2C_OK)) {
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000312 result = WaitForXfer(i2c);
C Naumand9abba82010-10-26 23:04:31 +0900313 writel(data[i], &i2c->iicds);
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000314 ReadWriteByte(i2c);
wdenkfc3e2162003-10-08 22:33:00 +0000315 i++;
316 }
wdenk1cb8e982003-03-06 21:55:29 +0000317 }
wdenk1cb8e982003-03-06 21:55:29 +0000318
wdenkfc3e2162003-10-08 22:33:00 +0000319 if (result == I2C_OK)
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000320 result = WaitForXfer(i2c);
wdenk1cb8e982003-03-06 21:55:29 +0000321
wdenkfc3e2162003-10-08 22:33:00 +0000322 /* send STOP */
Rajeshwari Shindecb466c02013-02-19 02:19:45 +0000323 writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat);
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000324 ReadWriteByte(i2c);
wdenkfc3e2162003-10-08 22:33:00 +0000325 break;
wdenk1cb8e982003-03-06 21:55:29 +0000326
wdenk48b42612003-06-19 23:01:32 +0000327 case I2C_READ:
wdenkfc3e2162003-10-08 22:33:00 +0000328 if (addr && addr_len) {
C Naumand9abba82010-10-26 23:04:31 +0900329 writel(chip, &i2c->iicds);
wdenkfc3e2162003-10-08 22:33:00 +0000330 /* send START */
Rajeshwari Shindecb466c02013-02-19 02:19:45 +0000331 writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP,
332 &i2c->iicstat);
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000333 result = WaitForXfer(i2c);
334 if (IsACK(i2c)) {
wdenkfc3e2162003-10-08 22:33:00 +0000335 i = 0;
336 while ((i < addr_len) && (result == I2C_OK)) {
C Naumand9abba82010-10-26 23:04:31 +0900337 writel(addr[i], &i2c->iicds);
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000338 ReadWriteByte(i2c);
339 result = WaitForXfer(i2c);
wdenkfc3e2162003-10-08 22:33:00 +0000340 i++;
341 }
wdenk1cb8e982003-03-06 21:55:29 +0000342
C Naumand9abba82010-10-26 23:04:31 +0900343 writel(chip, &i2c->iicds);
wdenkfc3e2162003-10-08 22:33:00 +0000344 /* resend START */
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900345 writel(I2C_MODE_MR | I2C_TXRX_ENA |
C Naumand9abba82010-10-26 23:04:31 +0900346 I2C_START_STOP, &i2c->iicstat);
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000347 ReadWriteByte(i2c);
348 result = WaitForXfer(i2c);
wdenkfc3e2162003-10-08 22:33:00 +0000349 i = 0;
350 while ((i < data_len) && (result == I2C_OK)) {
351 /* disable ACK for final READ */
352 if (i == data_len - 1)
C Naumand9abba82010-10-26 23:04:31 +0900353 writel(readl(&i2c->iiccon)
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000354 & ~I2CCON_ACKGEN,
355 &i2c->iiccon);
356 ReadWriteByte(i2c);
357 result = WaitForXfer(i2c);
C Naumand9abba82010-10-26 23:04:31 +0900358 data[i] = readl(&i2c->iicds);
wdenkfc3e2162003-10-08 22:33:00 +0000359 i++;
360 }
361 } else {
362 result = I2C_NACK;
363 }
364
wdenk1cb8e982003-03-06 21:55:29 +0000365 } else {
C Naumand9abba82010-10-26 23:04:31 +0900366 writel(chip, &i2c->iicds);
wdenkfc3e2162003-10-08 22:33:00 +0000367 /* send START */
Rajeshwari Shindecb466c02013-02-19 02:19:45 +0000368 writel(I2C_MODE_MR | I2C_TXRX_ENA | I2C_START_STOP,
369 &i2c->iicstat);
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000370 result = WaitForXfer(i2c);
wdenkfc3e2162003-10-08 22:33:00 +0000371
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000372 if (IsACK(i2c)) {
wdenkfc3e2162003-10-08 22:33:00 +0000373 i = 0;
374 while ((i < data_len) && (result == I2C_OK)) {
375 /* disable ACK for final READ */
376 if (i == data_len - 1)
C Naumand9abba82010-10-26 23:04:31 +0900377 writel(readl(&i2c->iiccon) &
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000378 ~I2CCON_ACKGEN,
379 &i2c->iiccon);
380 ReadWriteByte(i2c);
381 result = WaitForXfer(i2c);
C Naumand9abba82010-10-26 23:04:31 +0900382 data[i] = readl(&i2c->iicds);
wdenkfc3e2162003-10-08 22:33:00 +0000383 i++;
384 }
385 } else {
386 result = I2C_NACK;
387 }
wdenk1cb8e982003-03-06 21:55:29 +0000388 }
389
wdenkfc3e2162003-10-08 22:33:00 +0000390 /* send STOP */
C Naumand9abba82010-10-26 23:04:31 +0900391 writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat);
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000392 ReadWriteByte(i2c);
wdenkfc3e2162003-10-08 22:33:00 +0000393 break;
wdenk1cb8e982003-03-06 21:55:29 +0000394
395 default:
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000396 debug("i2c_transfer: bad call\n");
wdenkfc3e2162003-10-08 22:33:00 +0000397 result = I2C_NOK;
398 break;
399 }
wdenk1cb8e982003-03-06 21:55:29 +0000400
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000401 return result;
wdenk1cb8e982003-03-06 21:55:29 +0000402}
403
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900404int i2c_probe(uchar chip)
wdenk1cb8e982003-03-06 21:55:29 +0000405{
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000406 struct s3c24x0_i2c *i2c;
wdenkfc3e2162003-10-08 22:33:00 +0000407 uchar buf[1];
wdenk1cb8e982003-03-06 21:55:29 +0000408
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000409 i2c = get_base_i2c();
wdenkfc3e2162003-10-08 22:33:00 +0000410 buf[0] = 0;
wdenk1cb8e982003-03-06 21:55:29 +0000411
wdenkfc3e2162003-10-08 22:33:00 +0000412 /*
413 * What is needed is to send the chip address and verify that the
414 * address was <ACK>ed (i.e. there was a chip at that address which
415 * drove the data line low).
416 */
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000417 return i2c_transfer(i2c, I2C_READ, chip << 1, 0, 0, buf, 1) != I2C_OK;
wdenk1cb8e982003-03-06 21:55:29 +0000418}
419
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900420int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
wdenk1cb8e982003-03-06 21:55:29 +0000421{
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000422 struct s3c24x0_i2c *i2c;
wdenkfc3e2162003-10-08 22:33:00 +0000423 uchar xaddr[4];
424 int ret;
wdenk1cb8e982003-03-06 21:55:29 +0000425
wdenkfc3e2162003-10-08 22:33:00 +0000426 if (alen > 4) {
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000427 debug("I2C read: addr len %d not supported\n", alen);
wdenkfc3e2162003-10-08 22:33:00 +0000428 return 1;
429 }
wdenk1cb8e982003-03-06 21:55:29 +0000430
wdenkfc3e2162003-10-08 22:33:00 +0000431 if (alen > 0) {
432 xaddr[0] = (addr >> 24) & 0xFF;
433 xaddr[1] = (addr >> 16) & 0xFF;
434 xaddr[2] = (addr >> 8) & 0xFF;
435 xaddr[3] = addr & 0xFF;
436 }
wdenk1cb8e982003-03-06 21:55:29 +0000437
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200438#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
wdenkfc3e2162003-10-08 22:33:00 +0000439 /*
440 * EEPROM chips that implement "address overflow" are ones
441 * like Catalyst 24WC04/08/16 which has 9/10/11 bits of
442 * address and the extra bits end up in the "chip address"
443 * bit slots. This makes a 24WC08 (1Kbyte) chip look like
444 * four 256 byte chips.
445 *
446 * Note that we consider the length of the address field to
447 * still be one byte because the extra address bits are
448 * hidden in the chip address.
449 */
450 if (alen > 0)
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900451 chip |= ((addr >> (alen * 8)) &
452 CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
wdenk1cb8e982003-03-06 21:55:29 +0000453#endif
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000454 i2c = get_base_i2c();
455 ret = i2c_transfer(i2c, I2C_READ, chip << 1, &xaddr[4 - alen], alen,
456 buffer, len);
457 if (ret != 0) {
458 debug("I2c read: failed %d\n", ret);
wdenkfc3e2162003-10-08 22:33:00 +0000459 return 1;
460 }
461 return 0;
wdenk1cb8e982003-03-06 21:55:29 +0000462}
463
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900464int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
wdenk1cb8e982003-03-06 21:55:29 +0000465{
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000466 struct s3c24x0_i2c *i2c;
wdenkfc3e2162003-10-08 22:33:00 +0000467 uchar xaddr[4];
wdenk1cb8e982003-03-06 21:55:29 +0000468
wdenkfc3e2162003-10-08 22:33:00 +0000469 if (alen > 4) {
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000470 debug("I2C write: addr len %d not supported\n", alen);
wdenkfc3e2162003-10-08 22:33:00 +0000471 return 1;
472 }
wdenk1cb8e982003-03-06 21:55:29 +0000473
wdenkfc3e2162003-10-08 22:33:00 +0000474 if (alen > 0) {
475 xaddr[0] = (addr >> 24) & 0xFF;
476 xaddr[1] = (addr >> 16) & 0xFF;
477 xaddr[2] = (addr >> 8) & 0xFF;
478 xaddr[3] = addr & 0xFF;
479 }
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200480#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
wdenkfc3e2162003-10-08 22:33:00 +0000481 /*
482 * EEPROM chips that implement "address overflow" are ones
483 * like Catalyst 24WC04/08/16 which has 9/10/11 bits of
484 * address and the extra bits end up in the "chip address"
485 * bit slots. This makes a 24WC08 (1Kbyte) chip look like
486 * four 256 byte chips.
487 *
488 * Note that we consider the length of the address field to
489 * still be one byte because the extra address bits are
490 * hidden in the chip address.
491 */
492 if (alen > 0)
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900493 chip |= ((addr >> (alen * 8)) &
494 CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
wdenk1cb8e982003-03-06 21:55:29 +0000495#endif
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000496 i2c = get_base_i2c();
wdenkfc3e2162003-10-08 22:33:00 +0000497 return (i2c_transfer
Rajeshwari Shindeab7e52b2012-07-23 21:23:53 +0000498 (i2c, I2C_WRITE, chip << 1, &xaddr[4 - alen], alen, buffer,
wdenkfc3e2162003-10-08 22:33:00 +0000499 len) != 0);
wdenk1cb8e982003-03-06 21:55:29 +0000500}
Rajeshwari Shindea9d2ae72012-12-26 20:03:12 +0000501
Amar1ae76d42013-07-10 10:42:29 +0530502#ifdef CONFIG_OF_CONTROL
Rajeshwari Shindea9d2ae72012-12-26 20:03:12 +0000503void board_i2c_init(const void *blob)
504{
Amar2c07bb92013-04-04 02:27:06 -0400505 int i;
Rajeshwari Shindea9d2ae72012-12-26 20:03:12 +0000506 int node_list[CONFIG_MAX_I2C_NUM];
Amar2c07bb92013-04-04 02:27:06 -0400507 int count;
Rajeshwari Shindea9d2ae72012-12-26 20:03:12 +0000508
509 count = fdtdec_find_aliases_for_id(blob, "i2c",
510 COMPAT_SAMSUNG_S3C2440_I2C, node_list,
511 CONFIG_MAX_I2C_NUM);
512
513 for (i = 0; i < count; i++) {
514 struct s3c24x0_i2c_bus *bus;
515 int node = node_list[i];
516
517 if (node <= 0)
518 continue;
519 bus = &i2c_bus[i];
520 bus->regs = (struct s3c24x0_i2c *)
521 fdtdec_get_addr(blob, node, "reg");
522 bus->id = pinmux_decode_periph_id(blob, node);
523 bus->node = node;
524 bus->bus_num = i2c_busses++;
525 exynos_pinmux_config(bus->id, 0);
526 }
527}
528
529static struct s3c24x0_i2c_bus *get_bus(unsigned int bus_idx)
530{
531 if (bus_idx < i2c_busses)
532 return &i2c_bus[bus_idx];
533
534 debug("Undefined bus: %d\n", bus_idx);
535 return NULL;
536}
537
538int i2c_get_bus_num_fdt(int node)
539{
540 int i;
541
542 for (i = 0; i < i2c_busses; i++) {
543 if (node == i2c_bus[i].node)
544 return i;
545 }
546
547 debug("%s: Can't find any matched I2C bus\n", __func__);
548 return -1;
549}
550
551int i2c_reset_port_fdt(const void *blob, int node)
552{
553 struct s3c24x0_i2c_bus *i2c;
554 int bus;
555
556 bus = i2c_get_bus_num_fdt(node);
557 if (bus < 0) {
558 debug("could not get bus for node %d\n", node);
559 return -1;
560 }
561
562 i2c = get_bus(bus);
563 if (!i2c) {
564 debug("get_bus() failed for node node %d\n", node);
565 return -1;
566 }
567
568 i2c_ch_init(i2c->regs, CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
569
570 return 0;
571}
572#endif
573
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900574#endif /* CONFIG_HARD_I2C */