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