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