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 * 8942ba996SJean-Christophe PLAGNIOL-VILLARD * See file CREDITS for list of people who contributed to this 9942ba996SJean-Christophe PLAGNIOL-VILLARD * project. 10942ba996SJean-Christophe PLAGNIOL-VILLARD * 11942ba996SJean-Christophe PLAGNIOL-VILLARD * This program is free software; you can redistribute it and/or 12942ba996SJean-Christophe PLAGNIOL-VILLARD * modify it under the terms of the GNU General Public License as 13942ba996SJean-Christophe PLAGNIOL-VILLARD * published by the Free Software Foundation; either version 2 of 14942ba996SJean-Christophe PLAGNIOL-VILLARD * the License, or (at your option) any later version. 15942ba996SJean-Christophe PLAGNIOL-VILLARD * 16942ba996SJean-Christophe PLAGNIOL-VILLARD * This program is distributed in the hope that it will be useful, 17942ba996SJean-Christophe PLAGNIOL-VILLARD * but WITHOUT ANY WARRANTY; without even the implied warranty of 18942ba996SJean-Christophe PLAGNIOL-VILLARD * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19942ba996SJean-Christophe PLAGNIOL-VILLARD * GNU General Public License for more details. 20942ba996SJean-Christophe PLAGNIOL-VILLARD * 21942ba996SJean-Christophe PLAGNIOL-VILLARD * You should have received a copy of the GNU General Public License 22942ba996SJean-Christophe PLAGNIOL-VILLARD * along with this program; if not, write to the Free Software 23942ba996SJean-Christophe PLAGNIOL-VILLARD * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 24942ba996SJean-Christophe PLAGNIOL-VILLARD * MA 02111-1307 USA 25942ba996SJean-Christophe PLAGNIOL-VILLARD */ 26942ba996SJean-Christophe PLAGNIOL-VILLARD 27942ba996SJean-Christophe PLAGNIOL-VILLARD #include <common.h> 28942ba996SJean-Christophe PLAGNIOL-VILLARD #include <i2c.h> 29942ba996SJean-Christophe PLAGNIOL-VILLARD #include <asm/arch/hardware.h> 30942ba996SJean-Christophe PLAGNIOL-VILLARD #include <asm/arch/i2c_defs.h> 31942ba996SJean-Christophe PLAGNIOL-VILLARD 32942ba996SJean-Christophe PLAGNIOL-VILLARD #define CHECK_NACK() \ 33942ba996SJean-Christophe PLAGNIOL-VILLARD do {\ 34942ba996SJean-Christophe PLAGNIOL-VILLARD if (tmp & (I2C_TIMEOUT | I2C_STAT_NACK)) {\ 35942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0;\ 36942ba996SJean-Christophe PLAGNIOL-VILLARD return(1);\ 37942ba996SJean-Christophe PLAGNIOL-VILLARD }\ 38942ba996SJean-Christophe PLAGNIOL-VILLARD } while (0) 39942ba996SJean-Christophe PLAGNIOL-VILLARD 40942ba996SJean-Christophe PLAGNIOL-VILLARD 41942ba996SJean-Christophe PLAGNIOL-VILLARD static int wait_for_bus(void) 42942ba996SJean-Christophe PLAGNIOL-VILLARD { 43942ba996SJean-Christophe PLAGNIOL-VILLARD int stat, timeout; 44942ba996SJean-Christophe PLAGNIOL-VILLARD 45942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_STAT) = 0xffff; 46942ba996SJean-Christophe PLAGNIOL-VILLARD 47942ba996SJean-Christophe PLAGNIOL-VILLARD for (timeout = 0; timeout < 10; timeout++) { 48942ba996SJean-Christophe PLAGNIOL-VILLARD if (!((stat = REG(I2C_STAT)) & I2C_STAT_BB)) { 49942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_STAT) = 0xffff; 50942ba996SJean-Christophe PLAGNIOL-VILLARD return(0); 51942ba996SJean-Christophe PLAGNIOL-VILLARD } 52942ba996SJean-Christophe PLAGNIOL-VILLARD 53942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_STAT) = stat; 54942ba996SJean-Christophe PLAGNIOL-VILLARD udelay(50000); 55942ba996SJean-Christophe PLAGNIOL-VILLARD } 56942ba996SJean-Christophe PLAGNIOL-VILLARD 57942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_STAT) = 0xffff; 58942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 59942ba996SJean-Christophe PLAGNIOL-VILLARD } 60942ba996SJean-Christophe PLAGNIOL-VILLARD 61942ba996SJean-Christophe PLAGNIOL-VILLARD 62942ba996SJean-Christophe PLAGNIOL-VILLARD static int poll_i2c_irq(int mask) 63942ba996SJean-Christophe PLAGNIOL-VILLARD { 64942ba996SJean-Christophe PLAGNIOL-VILLARD int stat, timeout; 65942ba996SJean-Christophe PLAGNIOL-VILLARD 66942ba996SJean-Christophe PLAGNIOL-VILLARD for (timeout = 0; timeout < 10; timeout++) { 67942ba996SJean-Christophe PLAGNIOL-VILLARD udelay(1000); 68942ba996SJean-Christophe PLAGNIOL-VILLARD stat = REG(I2C_STAT); 69942ba996SJean-Christophe PLAGNIOL-VILLARD if (stat & mask) { 70942ba996SJean-Christophe PLAGNIOL-VILLARD return(stat); 71942ba996SJean-Christophe PLAGNIOL-VILLARD } 72942ba996SJean-Christophe PLAGNIOL-VILLARD } 73942ba996SJean-Christophe PLAGNIOL-VILLARD 74942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_STAT) = 0xffff; 75942ba996SJean-Christophe PLAGNIOL-VILLARD return(stat | I2C_TIMEOUT); 76942ba996SJean-Christophe PLAGNIOL-VILLARD } 77942ba996SJean-Christophe PLAGNIOL-VILLARD 78942ba996SJean-Christophe PLAGNIOL-VILLARD 79942ba996SJean-Christophe PLAGNIOL-VILLARD void flush_rx(void) 80942ba996SJean-Christophe PLAGNIOL-VILLARD { 81942ba996SJean-Christophe PLAGNIOL-VILLARD while (1) { 82942ba996SJean-Christophe PLAGNIOL-VILLARD if (!(REG(I2C_STAT) & I2C_STAT_RRDY)) 83942ba996SJean-Christophe PLAGNIOL-VILLARD break; 84942ba996SJean-Christophe PLAGNIOL-VILLARD 85*bd0f5ca8SAnatolij Gustschin REG(I2C_DRR); 86942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_STAT) = I2C_STAT_RRDY; 87942ba996SJean-Christophe PLAGNIOL-VILLARD udelay(1000); 88942ba996SJean-Christophe PLAGNIOL-VILLARD } 89942ba996SJean-Christophe PLAGNIOL-VILLARD } 90942ba996SJean-Christophe PLAGNIOL-VILLARD 91942ba996SJean-Christophe PLAGNIOL-VILLARD 92942ba996SJean-Christophe PLAGNIOL-VILLARD void i2c_init(int speed, int slaveadd) 93942ba996SJean-Christophe PLAGNIOL-VILLARD { 94942ba996SJean-Christophe PLAGNIOL-VILLARD u_int32_t div, psc; 95942ba996SJean-Christophe PLAGNIOL-VILLARD 96942ba996SJean-Christophe PLAGNIOL-VILLARD if (REG(I2C_CON) & I2C_CON_EN) { 97942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0; 98942ba996SJean-Christophe PLAGNIOL-VILLARD udelay (50000); 99942ba996SJean-Christophe PLAGNIOL-VILLARD } 100942ba996SJean-Christophe PLAGNIOL-VILLARD 101942ba996SJean-Christophe PLAGNIOL-VILLARD psc = 2; 102942ba996SJean-Christophe PLAGNIOL-VILLARD div = (CONFIG_SYS_HZ_CLOCK / ((psc + 1) * speed)) - 10; /* SCLL + SCLH */ 103942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_PSC) = psc; /* 27MHz / (2 + 1) = 9MHz */ 104942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_SCLL) = (div * 50) / 100; /* 50% Duty */ 105942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_SCLH) = div - REG(I2C_SCLL); 106942ba996SJean-Christophe PLAGNIOL-VILLARD 107942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_OA) = slaveadd; 108942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CNT) = 0; 109942ba996SJean-Christophe PLAGNIOL-VILLARD 110942ba996SJean-Christophe PLAGNIOL-VILLARD /* Interrupts must be enabled or I2C module won't work */ 111942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_IE) = I2C_IE_SCD_IE | I2C_IE_XRDY_IE | 112942ba996SJean-Christophe PLAGNIOL-VILLARD I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | I2C_IE_NACK_IE; 113942ba996SJean-Christophe PLAGNIOL-VILLARD 114942ba996SJean-Christophe PLAGNIOL-VILLARD /* Now enable I2C controller (get it out of reset) */ 115942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = I2C_CON_EN; 116942ba996SJean-Christophe PLAGNIOL-VILLARD 117942ba996SJean-Christophe PLAGNIOL-VILLARD udelay(1000); 118942ba996SJean-Christophe PLAGNIOL-VILLARD } 119942ba996SJean-Christophe PLAGNIOL-VILLARD 12049d6da60SHeiko Schocher int i2c_set_bus_speed(unsigned int speed) 12149d6da60SHeiko Schocher { 12249d6da60SHeiko Schocher i2c_init(speed, CONFIG_SYS_I2C_SLAVE); 12349d6da60SHeiko Schocher return 0; 12449d6da60SHeiko Schocher } 125942ba996SJean-Christophe PLAGNIOL-VILLARD 126942ba996SJean-Christophe PLAGNIOL-VILLARD int i2c_probe(u_int8_t chip) 127942ba996SJean-Christophe PLAGNIOL-VILLARD { 128942ba996SJean-Christophe PLAGNIOL-VILLARD int rc = 1; 129942ba996SJean-Christophe PLAGNIOL-VILLARD 130942ba996SJean-Christophe PLAGNIOL-VILLARD if (chip == REG(I2C_OA)) { 131942ba996SJean-Christophe PLAGNIOL-VILLARD return(rc); 132942ba996SJean-Christophe PLAGNIOL-VILLARD } 133942ba996SJean-Christophe PLAGNIOL-VILLARD 134942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0; 135942ba996SJean-Christophe PLAGNIOL-VILLARD if (wait_for_bus()) {return(1);} 136942ba996SJean-Christophe PLAGNIOL-VILLARD 137942ba996SJean-Christophe PLAGNIOL-VILLARD /* try to read one byte from current (or only) address */ 138942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CNT) = 1; 139942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_SA) = chip; 140942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP); 141942ba996SJean-Christophe PLAGNIOL-VILLARD udelay (50000); 142942ba996SJean-Christophe PLAGNIOL-VILLARD 143942ba996SJean-Christophe PLAGNIOL-VILLARD if (!(REG(I2C_STAT) & I2C_STAT_NACK)) { 144942ba996SJean-Christophe PLAGNIOL-VILLARD rc = 0; 145942ba996SJean-Christophe PLAGNIOL-VILLARD flush_rx(); 146942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_STAT) = 0xffff; 147942ba996SJean-Christophe PLAGNIOL-VILLARD } else { 148942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_STAT) = 0xffff; 149942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) |= I2C_CON_STP; 150942ba996SJean-Christophe PLAGNIOL-VILLARD udelay(20000); 151942ba996SJean-Christophe PLAGNIOL-VILLARD if (wait_for_bus()) {return(1);} 152942ba996SJean-Christophe PLAGNIOL-VILLARD } 153942ba996SJean-Christophe PLAGNIOL-VILLARD 154942ba996SJean-Christophe PLAGNIOL-VILLARD flush_rx(); 155942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_STAT) = 0xffff; 156942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CNT) = 0; 157942ba996SJean-Christophe PLAGNIOL-VILLARD return(rc); 158942ba996SJean-Christophe PLAGNIOL-VILLARD } 159942ba996SJean-Christophe PLAGNIOL-VILLARD 160942ba996SJean-Christophe PLAGNIOL-VILLARD 161942ba996SJean-Christophe PLAGNIOL-VILLARD int i2c_read(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len) 162942ba996SJean-Christophe PLAGNIOL-VILLARD { 163942ba996SJean-Christophe PLAGNIOL-VILLARD u_int32_t tmp; 164942ba996SJean-Christophe PLAGNIOL-VILLARD int i; 165942ba996SJean-Christophe PLAGNIOL-VILLARD 166942ba996SJean-Christophe PLAGNIOL-VILLARD if ((alen < 0) || (alen > 2)) { 167942ba996SJean-Christophe PLAGNIOL-VILLARD printf("%s(): bogus address length %x\n", __FUNCTION__, alen); 168942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 169942ba996SJean-Christophe PLAGNIOL-VILLARD } 170942ba996SJean-Christophe PLAGNIOL-VILLARD 171942ba996SJean-Christophe PLAGNIOL-VILLARD if (wait_for_bus()) {return(1);} 172942ba996SJean-Christophe PLAGNIOL-VILLARD 173942ba996SJean-Christophe PLAGNIOL-VILLARD if (alen != 0) { 174942ba996SJean-Christophe PLAGNIOL-VILLARD /* Start address phase */ 175942ba996SJean-Christophe PLAGNIOL-VILLARD tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX; 176942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CNT) = alen; 177942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_SA) = chip; 178942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = tmp; 179942ba996SJean-Christophe PLAGNIOL-VILLARD 180942ba996SJean-Christophe PLAGNIOL-VILLARD tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); 181942ba996SJean-Christophe PLAGNIOL-VILLARD 182942ba996SJean-Christophe PLAGNIOL-VILLARD CHECK_NACK(); 183942ba996SJean-Christophe PLAGNIOL-VILLARD 184942ba996SJean-Christophe PLAGNIOL-VILLARD switch (alen) { 185942ba996SJean-Christophe PLAGNIOL-VILLARD case 2: 186942ba996SJean-Christophe PLAGNIOL-VILLARD /* Send address MSByte */ 187942ba996SJean-Christophe PLAGNIOL-VILLARD if (tmp & I2C_STAT_XRDY) { 188942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_DXR) = (addr >> 8) & 0xff; 189942ba996SJean-Christophe PLAGNIOL-VILLARD } else { 190942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0; 191942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 192942ba996SJean-Christophe PLAGNIOL-VILLARD } 193942ba996SJean-Christophe PLAGNIOL-VILLARD 194942ba996SJean-Christophe PLAGNIOL-VILLARD tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); 195942ba996SJean-Christophe PLAGNIOL-VILLARD 196942ba996SJean-Christophe PLAGNIOL-VILLARD CHECK_NACK(); 197942ba996SJean-Christophe PLAGNIOL-VILLARD /* No break, fall through */ 198942ba996SJean-Christophe PLAGNIOL-VILLARD case 1: 199942ba996SJean-Christophe PLAGNIOL-VILLARD /* Send address LSByte */ 200942ba996SJean-Christophe PLAGNIOL-VILLARD if (tmp & I2C_STAT_XRDY) { 201942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_DXR) = addr & 0xff; 202942ba996SJean-Christophe PLAGNIOL-VILLARD } else { 203942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0; 204942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 205942ba996SJean-Christophe PLAGNIOL-VILLARD } 206942ba996SJean-Christophe PLAGNIOL-VILLARD 207942ba996SJean-Christophe PLAGNIOL-VILLARD tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK | I2C_STAT_ARDY); 208942ba996SJean-Christophe PLAGNIOL-VILLARD 209942ba996SJean-Christophe PLAGNIOL-VILLARD CHECK_NACK(); 210942ba996SJean-Christophe PLAGNIOL-VILLARD 211942ba996SJean-Christophe PLAGNIOL-VILLARD if (!(tmp & I2C_STAT_ARDY)) { 212942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0; 213942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 214942ba996SJean-Christophe PLAGNIOL-VILLARD } 215942ba996SJean-Christophe PLAGNIOL-VILLARD } 216942ba996SJean-Christophe PLAGNIOL-VILLARD } 217942ba996SJean-Christophe PLAGNIOL-VILLARD 218942ba996SJean-Christophe PLAGNIOL-VILLARD /* Address phase is over, now read 'len' bytes and stop */ 219942ba996SJean-Christophe PLAGNIOL-VILLARD tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP; 220942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CNT) = len & 0xffff; 221942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_SA) = chip; 222942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = tmp; 223942ba996SJean-Christophe PLAGNIOL-VILLARD 224942ba996SJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < len; i++) { 225942ba996SJean-Christophe PLAGNIOL-VILLARD tmp = poll_i2c_irq(I2C_STAT_RRDY | I2C_STAT_NACK | I2C_STAT_ROVR); 226942ba996SJean-Christophe PLAGNIOL-VILLARD 227942ba996SJean-Christophe PLAGNIOL-VILLARD CHECK_NACK(); 228942ba996SJean-Christophe PLAGNIOL-VILLARD 229942ba996SJean-Christophe PLAGNIOL-VILLARD if (tmp & I2C_STAT_RRDY) { 230942ba996SJean-Christophe PLAGNIOL-VILLARD buf[i] = REG(I2C_DRR); 231942ba996SJean-Christophe PLAGNIOL-VILLARD } else { 232942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0; 233942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 234942ba996SJean-Christophe PLAGNIOL-VILLARD } 235942ba996SJean-Christophe PLAGNIOL-VILLARD } 236942ba996SJean-Christophe PLAGNIOL-VILLARD 237942ba996SJean-Christophe PLAGNIOL-VILLARD tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK); 238942ba996SJean-Christophe PLAGNIOL-VILLARD 239942ba996SJean-Christophe PLAGNIOL-VILLARD CHECK_NACK(); 240942ba996SJean-Christophe PLAGNIOL-VILLARD 241942ba996SJean-Christophe PLAGNIOL-VILLARD if (!(tmp & I2C_STAT_SCD)) { 242942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0; 243942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 244942ba996SJean-Christophe PLAGNIOL-VILLARD } 245942ba996SJean-Christophe PLAGNIOL-VILLARD 246942ba996SJean-Christophe PLAGNIOL-VILLARD flush_rx(); 247942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_STAT) = 0xffff; 248942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CNT) = 0; 249942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0; 250942ba996SJean-Christophe PLAGNIOL-VILLARD 251942ba996SJean-Christophe PLAGNIOL-VILLARD return(0); 252942ba996SJean-Christophe PLAGNIOL-VILLARD } 253942ba996SJean-Christophe PLAGNIOL-VILLARD 254942ba996SJean-Christophe PLAGNIOL-VILLARD 255942ba996SJean-Christophe PLAGNIOL-VILLARD int i2c_write(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len) 256942ba996SJean-Christophe PLAGNIOL-VILLARD { 257942ba996SJean-Christophe PLAGNIOL-VILLARD u_int32_t tmp; 258942ba996SJean-Christophe PLAGNIOL-VILLARD int i; 259942ba996SJean-Christophe PLAGNIOL-VILLARD 260942ba996SJean-Christophe PLAGNIOL-VILLARD if ((alen < 0) || (alen > 2)) { 261942ba996SJean-Christophe PLAGNIOL-VILLARD printf("%s(): bogus address length %x\n", __FUNCTION__, alen); 262942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 263942ba996SJean-Christophe PLAGNIOL-VILLARD } 264942ba996SJean-Christophe PLAGNIOL-VILLARD if (len < 0) { 265942ba996SJean-Christophe PLAGNIOL-VILLARD printf("%s(): bogus length %x\n", __FUNCTION__, len); 266942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 267942ba996SJean-Christophe PLAGNIOL-VILLARD } 268942ba996SJean-Christophe PLAGNIOL-VILLARD 269942ba996SJean-Christophe PLAGNIOL-VILLARD if (wait_for_bus()) {return(1);} 270942ba996SJean-Christophe PLAGNIOL-VILLARD 271942ba996SJean-Christophe PLAGNIOL-VILLARD /* Start address phase */ 272942ba996SJean-Christophe PLAGNIOL-VILLARD tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | I2C_CON_STP; 273942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CNT) = (alen == 0) ? len & 0xffff : (len & 0xffff) + alen; 274942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_SA) = chip; 275942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = tmp; 276942ba996SJean-Christophe PLAGNIOL-VILLARD 277942ba996SJean-Christophe PLAGNIOL-VILLARD switch (alen) { 278942ba996SJean-Christophe PLAGNIOL-VILLARD case 2: 279942ba996SJean-Christophe PLAGNIOL-VILLARD /* Send address MSByte */ 280942ba996SJean-Christophe PLAGNIOL-VILLARD tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); 281942ba996SJean-Christophe PLAGNIOL-VILLARD 282942ba996SJean-Christophe PLAGNIOL-VILLARD CHECK_NACK(); 283942ba996SJean-Christophe PLAGNIOL-VILLARD 284942ba996SJean-Christophe PLAGNIOL-VILLARD if (tmp & I2C_STAT_XRDY) { 285942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_DXR) = (addr >> 8) & 0xff; 286942ba996SJean-Christophe PLAGNIOL-VILLARD } else { 287942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0; 288942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 289942ba996SJean-Christophe PLAGNIOL-VILLARD } 290942ba996SJean-Christophe PLAGNIOL-VILLARD /* No break, fall through */ 291942ba996SJean-Christophe PLAGNIOL-VILLARD case 1: 292942ba996SJean-Christophe PLAGNIOL-VILLARD /* Send address LSByte */ 293942ba996SJean-Christophe PLAGNIOL-VILLARD tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); 294942ba996SJean-Christophe PLAGNIOL-VILLARD 295942ba996SJean-Christophe PLAGNIOL-VILLARD CHECK_NACK(); 296942ba996SJean-Christophe PLAGNIOL-VILLARD 297942ba996SJean-Christophe PLAGNIOL-VILLARD if (tmp & I2C_STAT_XRDY) { 298942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_DXR) = addr & 0xff; 299942ba996SJean-Christophe PLAGNIOL-VILLARD } else { 300942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0; 301942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 302942ba996SJean-Christophe PLAGNIOL-VILLARD } 303942ba996SJean-Christophe PLAGNIOL-VILLARD } 304942ba996SJean-Christophe PLAGNIOL-VILLARD 305942ba996SJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < len; i++) { 306942ba996SJean-Christophe PLAGNIOL-VILLARD tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); 307942ba996SJean-Christophe PLAGNIOL-VILLARD 308942ba996SJean-Christophe PLAGNIOL-VILLARD CHECK_NACK(); 309942ba996SJean-Christophe PLAGNIOL-VILLARD 310942ba996SJean-Christophe PLAGNIOL-VILLARD if (tmp & I2C_STAT_XRDY) { 311942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_DXR) = buf[i]; 312942ba996SJean-Christophe PLAGNIOL-VILLARD } else { 313942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 314942ba996SJean-Christophe PLAGNIOL-VILLARD } 315942ba996SJean-Christophe PLAGNIOL-VILLARD } 316942ba996SJean-Christophe PLAGNIOL-VILLARD 317942ba996SJean-Christophe PLAGNIOL-VILLARD tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK); 318942ba996SJean-Christophe PLAGNIOL-VILLARD 319942ba996SJean-Christophe PLAGNIOL-VILLARD CHECK_NACK(); 320942ba996SJean-Christophe PLAGNIOL-VILLARD 321942ba996SJean-Christophe PLAGNIOL-VILLARD if (!(tmp & I2C_STAT_SCD)) { 322942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0; 323942ba996SJean-Christophe PLAGNIOL-VILLARD return(1); 324942ba996SJean-Christophe PLAGNIOL-VILLARD } 325942ba996SJean-Christophe PLAGNIOL-VILLARD 326942ba996SJean-Christophe PLAGNIOL-VILLARD flush_rx(); 327942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_STAT) = 0xffff; 328942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CNT) = 0; 329942ba996SJean-Christophe PLAGNIOL-VILLARD REG(I2C_CON) = 0; 330942ba996SJean-Christophe PLAGNIOL-VILLARD 331942ba996SJean-Christophe PLAGNIOL-VILLARD return(0); 332942ba996SJean-Christophe PLAGNIOL-VILLARD } 333