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