1942ba996SJean-Christophe PLAGNIOL-VILLARD /* 2942ba996SJean-Christophe PLAGNIOL-VILLARD * TI DaVinci (TMS320DM644x) I2C driver. 3942ba996SJean-Christophe PLAGNIOL-VILLARD * 4942ba996SJean-Christophe PLAGNIOL-VILLARD * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> 5942ba996SJean-Christophe PLAGNIOL-VILLARD * 6942ba996SJean-Christophe PLAGNIOL-VILLARD * -------------------------------------------------------- 7942ba996SJean-Christophe PLAGNIOL-VILLARD * 81a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 9942ba996SJean-Christophe PLAGNIOL-VILLARD */ 10942ba996SJean-Christophe PLAGNIOL-VILLARD 11942ba996SJean-Christophe PLAGNIOL-VILLARD #include <common.h> 12942ba996SJean-Christophe PLAGNIOL-VILLARD #include <i2c.h> 13942ba996SJean-Christophe PLAGNIOL-VILLARD #include <asm/arch/hardware.h> 14942ba996SJean-Christophe PLAGNIOL-VILLARD #include <asm/arch/i2c_defs.h> 15*356d15ebSKaricheri, Muralidharan #include "davinci_i2c.h" 16942ba996SJean-Christophe PLAGNIOL-VILLARD 17942ba996SJean-Christophe PLAGNIOL-VILLARD #define CHECK_NACK() \ 18942ba996SJean-Christophe PLAGNIOL-VILLARD do {\ 19942ba996SJean-Christophe PLAGNIOL-VILLARD if (tmp & (I2C_TIMEOUT | I2C_STAT_NACK)) {\ 20942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0;\ 21942ba996SJean-Christophe PLAGNIOL-VILLARD return(1);\ 22942ba996SJean-Christophe PLAGNIOL-VILLARD }\ 23942ba996SJean-Christophe PLAGNIOL-VILLARD } while (0) 24942ba996SJean-Christophe PLAGNIOL-VILLARD 25942ba996SJean-Christophe PLAGNIOL-VILLARD 26942ba996SJean-Christophe PLAGNIOL-VILLARD static int wait_for_bus(void) 27942ba996SJean-Christophe PLAGNIOL-VILLARD { 28942ba996SJean-Christophe PLAGNIOL-VILLARD int stat, timeout; 29942ba996SJean-Christophe PLAGNIOL-VILLARD 30942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_STAT) = 0xffff; 31942ba996SJean-Christophe PLAGNIOL-VILLARD 32942ba996SJean-Christophe PLAGNIOL-VILLARD for (timeout = 0; timeout < 10; timeout++) { 33942ba996SJean-Christophe PLAGNIOL-VILLARD if (!((stat = REG(I2C_STAT)) & I2C_STAT_BB)) { 34942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_STAT) = 0xffff; 35942ba996SJean-Christophe PLAGNIOL-VILLARD return(0); 36942ba996SJean-Christophe PLAGNIOL-VILLARD } 37942ba996SJean-Christophe PLAGNIOL-VILLARD 38942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_STAT) = stat; 39942ba996SJean-Christophe PLAGNIOL-VILLARD udelay(50000); 40942ba996SJean-Christophe PLAGNIOL-VILLARD } 41942ba996SJean-Christophe PLAGNIOL-VILLARD 42942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_STAT) = 0xffff; 43942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 44942ba996SJean-Christophe PLAGNIOL-VILLARD } 45942ba996SJean-Christophe PLAGNIOL-VILLARD 46942ba996SJean-Christophe PLAGNIOL-VILLARD 47942ba996SJean-Christophe PLAGNIOL-VILLARD static int poll_i2c_irq(int mask) 48942ba996SJean-Christophe PLAGNIOL-VILLARD { 49942ba996SJean-Christophe PLAGNIOL-VILLARD int stat, timeout; 50942ba996SJean-Christophe PLAGNIOL-VILLARD 51942ba996SJean-Christophe PLAGNIOL-VILLARD for (timeout = 0; timeout < 10; timeout++) { 52942ba996SJean-Christophe PLAGNIOL-VILLARD udelay(1000); 53942ba996SJean-Christophe PLAGNIOL-VILLARD stat = REG(I2C_STAT); 54942ba996SJean-Christophe PLAGNIOL-VILLARD if (stat & mask) { 55942ba996SJean-Christophe PLAGNIOL-VILLARD return(stat); 56942ba996SJean-Christophe PLAGNIOL-VILLARD } 57942ba996SJean-Christophe PLAGNIOL-VILLARD } 58942ba996SJean-Christophe PLAGNIOL-VILLARD 59942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_STAT) = 0xffff; 60942ba996SJean-Christophe PLAGNIOL-VILLARD return(stat | I2C_TIMEOUT); 61942ba996SJean-Christophe PLAGNIOL-VILLARD } 62942ba996SJean-Christophe PLAGNIOL-VILLARD 63942ba996SJean-Christophe PLAGNIOL-VILLARD 64942ba996SJean-Christophe PLAGNIOL-VILLARD void flush_rx(void) 65942ba996SJean-Christophe PLAGNIOL-VILLARD { 66942ba996SJean-Christophe PLAGNIOL-VILLARD while (1) { 67942ba996SJean-Christophe PLAGNIOL-VILLARD if (!(REG(I2C_STAT) & I2C_STAT_RRDY)) 68942ba996SJean-Christophe PLAGNIOL-VILLARD break; 69942ba996SJean-Christophe PLAGNIOL-VILLARD 70bd0f5ca8SAnatolij Gustschin REG(I2C_DRR); 71942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_STAT) = I2C_STAT_RRDY; 72942ba996SJean-Christophe PLAGNIOL-VILLARD udelay(1000); 73942ba996SJean-Christophe PLAGNIOL-VILLARD } 74942ba996SJean-Christophe PLAGNIOL-VILLARD } 75942ba996SJean-Christophe PLAGNIOL-VILLARD 76942ba996SJean-Christophe PLAGNIOL-VILLARD 77942ba996SJean-Christophe PLAGNIOL-VILLARD void i2c_init(int speed, int slaveadd) 78942ba996SJean-Christophe PLAGNIOL-VILLARD { 79942ba996SJean-Christophe PLAGNIOL-VILLARD u_int32_t div, psc; 80942ba996SJean-Christophe PLAGNIOL-VILLARD 81942ba996SJean-Christophe PLAGNIOL-VILLARD if (REG(I2C_CON) & I2C_CON_EN) { 82942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0; 83942ba996SJean-Christophe PLAGNIOL-VILLARD udelay (50000); 84942ba996SJean-Christophe PLAGNIOL-VILLARD } 85942ba996SJean-Christophe PLAGNIOL-VILLARD 86942ba996SJean-Christophe PLAGNIOL-VILLARD psc = 2; 87942ba996SJean-Christophe PLAGNIOL-VILLARD div = (CONFIG_SYS_HZ_CLOCK / ((psc + 1) * speed)) - 10; /* SCLL + SCLH */ 88942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_PSC) = psc; /* 27MHz / (2 + 1) = 9MHz */ 89942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_SCLL) = (div * 50) / 100; /* 50% Duty */ 90942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_SCLH) = div - REG(I2C_SCLL); 91942ba996SJean-Christophe PLAGNIOL-VILLARD 92942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_OA) = slaveadd; 93942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CNT) = 0; 94942ba996SJean-Christophe PLAGNIOL-VILLARD 95942ba996SJean-Christophe PLAGNIOL-VILLARD /* Interrupts must be enabled or I2C module won't work */ 96942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_IE) = I2C_IE_SCD_IE | I2C_IE_XRDY_IE | 97942ba996SJean-Christophe PLAGNIOL-VILLARD I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | I2C_IE_NACK_IE; 98942ba996SJean-Christophe PLAGNIOL-VILLARD 99942ba996SJean-Christophe PLAGNIOL-VILLARD /* Now enable I2C controller (get it out of reset) */ 100942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = I2C_CON_EN; 101942ba996SJean-Christophe PLAGNIOL-VILLARD 102942ba996SJean-Christophe PLAGNIOL-VILLARD udelay(1000); 103942ba996SJean-Christophe PLAGNIOL-VILLARD } 104942ba996SJean-Christophe PLAGNIOL-VILLARD 10549d6da60SHeiko Schocher int i2c_set_bus_speed(unsigned int speed) 10649d6da60SHeiko Schocher { 10749d6da60SHeiko Schocher i2c_init(speed, CONFIG_SYS_I2C_SLAVE); 10849d6da60SHeiko Schocher return 0; 10949d6da60SHeiko Schocher } 110942ba996SJean-Christophe PLAGNIOL-VILLARD 111942ba996SJean-Christophe PLAGNIOL-VILLARD int i2c_probe(u_int8_t chip) 112942ba996SJean-Christophe PLAGNIOL-VILLARD { 113942ba996SJean-Christophe PLAGNIOL-VILLARD int rc = 1; 114942ba996SJean-Christophe PLAGNIOL-VILLARD 115942ba996SJean-Christophe PLAGNIOL-VILLARD if (chip == REG(I2C_OA)) { 116942ba996SJean-Christophe PLAGNIOL-VILLARD return(rc); 117942ba996SJean-Christophe PLAGNIOL-VILLARD } 118942ba996SJean-Christophe PLAGNIOL-VILLARD 119942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0; 120942ba996SJean-Christophe PLAGNIOL-VILLARD if (wait_for_bus()) {return(1);} 121942ba996SJean-Christophe PLAGNIOL-VILLARD 122942ba996SJean-Christophe PLAGNIOL-VILLARD /* try to read one byte from current (or only) address */ 123942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CNT) = 1; 124942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_SA) = chip; 125942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP); 126942ba996SJean-Christophe PLAGNIOL-VILLARD udelay (50000); 127942ba996SJean-Christophe PLAGNIOL-VILLARD 128942ba996SJean-Christophe PLAGNIOL-VILLARD if (!(REG(I2C_STAT) & I2C_STAT_NACK)) { 129942ba996SJean-Christophe PLAGNIOL-VILLARD rc = 0; 130942ba996SJean-Christophe PLAGNIOL-VILLARD flush_rx(); 131942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_STAT) = 0xffff; 132942ba996SJean-Christophe PLAGNIOL-VILLARD } else { 133942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_STAT) = 0xffff; 134942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) |= I2C_CON_STP; 135942ba996SJean-Christophe PLAGNIOL-VILLARD udelay(20000); 136942ba996SJean-Christophe PLAGNIOL-VILLARD if (wait_for_bus()) {return(1);} 137942ba996SJean-Christophe PLAGNIOL-VILLARD } 138942ba996SJean-Christophe PLAGNIOL-VILLARD 139942ba996SJean-Christophe PLAGNIOL-VILLARD flush_rx(); 140942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_STAT) = 0xffff; 141942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CNT) = 0; 142942ba996SJean-Christophe PLAGNIOL-VILLARD return(rc); 143942ba996SJean-Christophe PLAGNIOL-VILLARD } 144942ba996SJean-Christophe PLAGNIOL-VILLARD 145942ba996SJean-Christophe PLAGNIOL-VILLARD 146942ba996SJean-Christophe PLAGNIOL-VILLARD int i2c_read(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len) 147942ba996SJean-Christophe PLAGNIOL-VILLARD { 148942ba996SJean-Christophe PLAGNIOL-VILLARD u_int32_t tmp; 149942ba996SJean-Christophe PLAGNIOL-VILLARD int i; 150942ba996SJean-Christophe PLAGNIOL-VILLARD 151942ba996SJean-Christophe PLAGNIOL-VILLARD if ((alen < 0) || (alen > 2)) { 152942ba996SJean-Christophe PLAGNIOL-VILLARD printf("%s(): bogus address length %x\n", __FUNCTION__, alen); 153942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 154942ba996SJean-Christophe PLAGNIOL-VILLARD } 155942ba996SJean-Christophe PLAGNIOL-VILLARD 156942ba996SJean-Christophe PLAGNIOL-VILLARD if (wait_for_bus()) {return(1);} 157942ba996SJean-Christophe PLAGNIOL-VILLARD 158942ba996SJean-Christophe PLAGNIOL-VILLARD if (alen != 0) { 159942ba996SJean-Christophe PLAGNIOL-VILLARD /* Start address phase */ 160942ba996SJean-Christophe PLAGNIOL-VILLARD tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX; 161942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CNT) = alen; 162942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_SA) = chip; 163942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = tmp; 164942ba996SJean-Christophe PLAGNIOL-VILLARD 165942ba996SJean-Christophe PLAGNIOL-VILLARD tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); 166942ba996SJean-Christophe PLAGNIOL-VILLARD 167942ba996SJean-Christophe PLAGNIOL-VILLARD CHECK_NACK(); 168942ba996SJean-Christophe PLAGNIOL-VILLARD 169942ba996SJean-Christophe PLAGNIOL-VILLARD switch (alen) { 170942ba996SJean-Christophe PLAGNIOL-VILLARD case 2: 171942ba996SJean-Christophe PLAGNIOL-VILLARD /* Send address MSByte */ 172942ba996SJean-Christophe PLAGNIOL-VILLARD if (tmp & I2C_STAT_XRDY) { 173942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_DXR) = (addr >> 8) & 0xff; 174942ba996SJean-Christophe PLAGNIOL-VILLARD } else { 175942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0; 176942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 177942ba996SJean-Christophe PLAGNIOL-VILLARD } 178942ba996SJean-Christophe PLAGNIOL-VILLARD 179942ba996SJean-Christophe PLAGNIOL-VILLARD tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); 180942ba996SJean-Christophe PLAGNIOL-VILLARD 181942ba996SJean-Christophe PLAGNIOL-VILLARD CHECK_NACK(); 182942ba996SJean-Christophe PLAGNIOL-VILLARD /* No break, fall through */ 183942ba996SJean-Christophe PLAGNIOL-VILLARD case 1: 184942ba996SJean-Christophe PLAGNIOL-VILLARD /* Send address LSByte */ 185942ba996SJean-Christophe PLAGNIOL-VILLARD if (tmp & I2C_STAT_XRDY) { 186942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_DXR) = addr & 0xff; 187942ba996SJean-Christophe PLAGNIOL-VILLARD } else { 188942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0; 189942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 190942ba996SJean-Christophe PLAGNIOL-VILLARD } 191942ba996SJean-Christophe PLAGNIOL-VILLARD 192942ba996SJean-Christophe PLAGNIOL-VILLARD tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK | I2C_STAT_ARDY); 193942ba996SJean-Christophe PLAGNIOL-VILLARD 194942ba996SJean-Christophe PLAGNIOL-VILLARD CHECK_NACK(); 195942ba996SJean-Christophe PLAGNIOL-VILLARD 196942ba996SJean-Christophe PLAGNIOL-VILLARD if (!(tmp & I2C_STAT_ARDY)) { 197942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0; 198942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 199942ba996SJean-Christophe PLAGNIOL-VILLARD } 200942ba996SJean-Christophe PLAGNIOL-VILLARD } 201942ba996SJean-Christophe PLAGNIOL-VILLARD } 202942ba996SJean-Christophe PLAGNIOL-VILLARD 203942ba996SJean-Christophe PLAGNIOL-VILLARD /* Address phase is over, now read 'len' bytes and stop */ 204942ba996SJean-Christophe PLAGNIOL-VILLARD tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP; 205942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CNT) = len & 0xffff; 206942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_SA) = chip; 207942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = tmp; 208942ba996SJean-Christophe PLAGNIOL-VILLARD 209942ba996SJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < len; i++) { 210942ba996SJean-Christophe PLAGNIOL-VILLARD tmp = poll_i2c_irq(I2C_STAT_RRDY | I2C_STAT_NACK | I2C_STAT_ROVR); 211942ba996SJean-Christophe PLAGNIOL-VILLARD 212942ba996SJean-Christophe PLAGNIOL-VILLARD CHECK_NACK(); 213942ba996SJean-Christophe PLAGNIOL-VILLARD 214942ba996SJean-Christophe PLAGNIOL-VILLARD if (tmp & I2C_STAT_RRDY) { 215942ba996SJean-Christophe PLAGNIOL-VILLARD buf[i] = REG(I2C_DRR); 216942ba996SJean-Christophe PLAGNIOL-VILLARD } else { 217942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0; 218942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 219942ba996SJean-Christophe PLAGNIOL-VILLARD } 220942ba996SJean-Christophe PLAGNIOL-VILLARD } 221942ba996SJean-Christophe PLAGNIOL-VILLARD 222942ba996SJean-Christophe PLAGNIOL-VILLARD tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK); 223942ba996SJean-Christophe PLAGNIOL-VILLARD 224942ba996SJean-Christophe PLAGNIOL-VILLARD CHECK_NACK(); 225942ba996SJean-Christophe PLAGNIOL-VILLARD 226942ba996SJean-Christophe PLAGNIOL-VILLARD if (!(tmp & I2C_STAT_SCD)) { 227942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0; 228942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 229942ba996SJean-Christophe PLAGNIOL-VILLARD } 230942ba996SJean-Christophe PLAGNIOL-VILLARD 231942ba996SJean-Christophe PLAGNIOL-VILLARD flush_rx(); 232942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_STAT) = 0xffff; 233942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CNT) = 0; 234942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0; 235942ba996SJean-Christophe PLAGNIOL-VILLARD 236942ba996SJean-Christophe PLAGNIOL-VILLARD return(0); 237942ba996SJean-Christophe PLAGNIOL-VILLARD } 238942ba996SJean-Christophe PLAGNIOL-VILLARD 239942ba996SJean-Christophe PLAGNIOL-VILLARD 240942ba996SJean-Christophe PLAGNIOL-VILLARD int i2c_write(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len) 241942ba996SJean-Christophe PLAGNIOL-VILLARD { 242942ba996SJean-Christophe PLAGNIOL-VILLARD u_int32_t tmp; 243942ba996SJean-Christophe PLAGNIOL-VILLARD int i; 244942ba996SJean-Christophe PLAGNIOL-VILLARD 245942ba996SJean-Christophe PLAGNIOL-VILLARD if ((alen < 0) || (alen > 2)) { 246942ba996SJean-Christophe PLAGNIOL-VILLARD printf("%s(): bogus address length %x\n", __FUNCTION__, alen); 247942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 248942ba996SJean-Christophe PLAGNIOL-VILLARD } 249942ba996SJean-Christophe PLAGNIOL-VILLARD if (len < 0) { 250942ba996SJean-Christophe PLAGNIOL-VILLARD printf("%s(): bogus length %x\n", __FUNCTION__, len); 251942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 252942ba996SJean-Christophe PLAGNIOL-VILLARD } 253942ba996SJean-Christophe PLAGNIOL-VILLARD 254942ba996SJean-Christophe PLAGNIOL-VILLARD if (wait_for_bus()) {return(1);} 255942ba996SJean-Christophe PLAGNIOL-VILLARD 256942ba996SJean-Christophe PLAGNIOL-VILLARD /* Start address phase */ 257942ba996SJean-Christophe PLAGNIOL-VILLARD tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | I2C_CON_STP; 258942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CNT) = (alen == 0) ? len & 0xffff : (len & 0xffff) + alen; 259942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_SA) = chip; 260942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = tmp; 261942ba996SJean-Christophe PLAGNIOL-VILLARD 262942ba996SJean-Christophe PLAGNIOL-VILLARD switch (alen) { 263942ba996SJean-Christophe PLAGNIOL-VILLARD case 2: 264942ba996SJean-Christophe PLAGNIOL-VILLARD /* Send address MSByte */ 265942ba996SJean-Christophe PLAGNIOL-VILLARD tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); 266942ba996SJean-Christophe PLAGNIOL-VILLARD 267942ba996SJean-Christophe PLAGNIOL-VILLARD CHECK_NACK(); 268942ba996SJean-Christophe PLAGNIOL-VILLARD 269942ba996SJean-Christophe PLAGNIOL-VILLARD if (tmp & I2C_STAT_XRDY) { 270942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_DXR) = (addr >> 8) & 0xff; 271942ba996SJean-Christophe PLAGNIOL-VILLARD } else { 272942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0; 273942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 274942ba996SJean-Christophe PLAGNIOL-VILLARD } 275942ba996SJean-Christophe PLAGNIOL-VILLARD /* No break, fall through */ 276942ba996SJean-Christophe PLAGNIOL-VILLARD case 1: 277942ba996SJean-Christophe PLAGNIOL-VILLARD /* Send address LSByte */ 278942ba996SJean-Christophe PLAGNIOL-VILLARD tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); 279942ba996SJean-Christophe PLAGNIOL-VILLARD 280942ba996SJean-Christophe PLAGNIOL-VILLARD CHECK_NACK(); 281942ba996SJean-Christophe PLAGNIOL-VILLARD 282942ba996SJean-Christophe PLAGNIOL-VILLARD if (tmp & I2C_STAT_XRDY) { 283942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_DXR) = addr & 0xff; 284942ba996SJean-Christophe PLAGNIOL-VILLARD } else { 285942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0; 286942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 287942ba996SJean-Christophe PLAGNIOL-VILLARD } 288942ba996SJean-Christophe PLAGNIOL-VILLARD } 289942ba996SJean-Christophe PLAGNIOL-VILLARD 290942ba996SJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < len; i++) { 291942ba996SJean-Christophe PLAGNIOL-VILLARD tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); 292942ba996SJean-Christophe PLAGNIOL-VILLARD 293942ba996SJean-Christophe PLAGNIOL-VILLARD CHECK_NACK(); 294942ba996SJean-Christophe PLAGNIOL-VILLARD 295942ba996SJean-Christophe PLAGNIOL-VILLARD if (tmp & I2C_STAT_XRDY) { 296942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_DXR) = buf[i]; 297942ba996SJean-Christophe PLAGNIOL-VILLARD } else { 298942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 299942ba996SJean-Christophe PLAGNIOL-VILLARD } 300942ba996SJean-Christophe PLAGNIOL-VILLARD } 301942ba996SJean-Christophe PLAGNIOL-VILLARD 302942ba996SJean-Christophe PLAGNIOL-VILLARD tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK); 303942ba996SJean-Christophe PLAGNIOL-VILLARD 304942ba996SJean-Christophe PLAGNIOL-VILLARD CHECK_NACK(); 305942ba996SJean-Christophe PLAGNIOL-VILLARD 306942ba996SJean-Christophe PLAGNIOL-VILLARD if (!(tmp & I2C_STAT_SCD)) { 307942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0; 308942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 309942ba996SJean-Christophe PLAGNIOL-VILLARD } 310942ba996SJean-Christophe PLAGNIOL-VILLARD 311942ba996SJean-Christophe PLAGNIOL-VILLARD flush_rx(); 312942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_STAT) = 0xffff; 313942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CNT) = 0; 314942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0; 315942ba996SJean-Christophe PLAGNIOL-VILLARD 316942ba996SJean-Christophe PLAGNIOL-VILLARD return(0); 317942ba996SJean-Christophe PLAGNIOL-VILLARD } 318