1080c646dSJean-Christophe PLAGNIOL-VILLARD /* 2080c646dSJean-Christophe PLAGNIOL-VILLARD * Basic I2C functions 3080c646dSJean-Christophe PLAGNIOL-VILLARD * 4080c646dSJean-Christophe PLAGNIOL-VILLARD * Copyright (c) 2004 Texas Instruments 5080c646dSJean-Christophe PLAGNIOL-VILLARD * 6080c646dSJean-Christophe PLAGNIOL-VILLARD * This package is free software; you can redistribute it and/or 7080c646dSJean-Christophe PLAGNIOL-VILLARD * modify it under the terms of the license found in the file 8080c646dSJean-Christophe PLAGNIOL-VILLARD * named COPYING that should have accompanied this file. 9080c646dSJean-Christophe PLAGNIOL-VILLARD * 10080c646dSJean-Christophe PLAGNIOL-VILLARD * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 11080c646dSJean-Christophe PLAGNIOL-VILLARD * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 12080c646dSJean-Christophe PLAGNIOL-VILLARD * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 13080c646dSJean-Christophe PLAGNIOL-VILLARD * 14080c646dSJean-Christophe PLAGNIOL-VILLARD * Author: Jian Zhang jzhang@ti.com, Texas Instruments 15080c646dSJean-Christophe PLAGNIOL-VILLARD * 16080c646dSJean-Christophe PLAGNIOL-VILLARD * Copyright (c) 2003 Wolfgang Denk, wd@denx.de 17080c646dSJean-Christophe PLAGNIOL-VILLARD * Rewritten to fit into the current U-Boot framework 18080c646dSJean-Christophe PLAGNIOL-VILLARD * 19080c646dSJean-Christophe PLAGNIOL-VILLARD * Adapted for OMAP2420 I2C, r-woodruff2@ti.com 20080c646dSJean-Christophe PLAGNIOL-VILLARD * 21080c646dSJean-Christophe PLAGNIOL-VILLARD */ 22080c646dSJean-Christophe PLAGNIOL-VILLARD 23080c646dSJean-Christophe PLAGNIOL-VILLARD #include <common.h> 24080c646dSJean-Christophe PLAGNIOL-VILLARD 25080c646dSJean-Christophe PLAGNIOL-VILLARD #include <asm/arch/i2c.h> 26080c646dSJean-Christophe PLAGNIOL-VILLARD #include <asm/io.h> 27080c646dSJean-Christophe PLAGNIOL-VILLARD 28080c646dSJean-Christophe PLAGNIOL-VILLARD #define inw(a) __raw_readw(a) 29080c646dSJean-Christophe PLAGNIOL-VILLARD #define outw(a,v) __raw_writew(a,v) 30080c646dSJean-Christophe PLAGNIOL-VILLARD 31080c646dSJean-Christophe PLAGNIOL-VILLARD static void wait_for_bb (void); 32080c646dSJean-Christophe PLAGNIOL-VILLARD static u16 wait_for_pin (void); 33080c646dSJean-Christophe PLAGNIOL-VILLARD static void flush_fifo(void); 34080c646dSJean-Christophe PLAGNIOL-VILLARD 35080c646dSJean-Christophe PLAGNIOL-VILLARD void i2c_init (int speed, int slaveadd) 36080c646dSJean-Christophe PLAGNIOL-VILLARD { 37080c646dSJean-Christophe PLAGNIOL-VILLARD u16 scl; 38080c646dSJean-Christophe PLAGNIOL-VILLARD 39080c646dSJean-Christophe PLAGNIOL-VILLARD outw(0x2, I2C_SYSC); /* for ES2 after soft reset */ 40080c646dSJean-Christophe PLAGNIOL-VILLARD udelay(1000); 41080c646dSJean-Christophe PLAGNIOL-VILLARD outw(0x0, I2C_SYSC); /* will probably self clear but */ 42080c646dSJean-Christophe PLAGNIOL-VILLARD 43080c646dSJean-Christophe PLAGNIOL-VILLARD if (inw (I2C_CON) & I2C_CON_EN) { 44080c646dSJean-Christophe PLAGNIOL-VILLARD outw (0, I2C_CON); 45080c646dSJean-Christophe PLAGNIOL-VILLARD udelay (50000); 46080c646dSJean-Christophe PLAGNIOL-VILLARD } 47080c646dSJean-Christophe PLAGNIOL-VILLARD 48*8ed44d91SWolfgang Denk /* 12MHz I2C module clock */ 49080c646dSJean-Christophe PLAGNIOL-VILLARD outw (0, I2C_PSC); 50080c646dSJean-Christophe PLAGNIOL-VILLARD speed = speed/1000; /* 100 or 400 */ 51080c646dSJean-Christophe PLAGNIOL-VILLARD scl = ((12000/(speed*2)) - 7); /* use 7 when PSC = 0 */ 52080c646dSJean-Christophe PLAGNIOL-VILLARD outw (scl, I2C_SCLL); 53080c646dSJean-Christophe PLAGNIOL-VILLARD outw (scl, I2C_SCLH); 54080c646dSJean-Christophe PLAGNIOL-VILLARD /* own address */ 55080c646dSJean-Christophe PLAGNIOL-VILLARD outw (slaveadd, I2C_OA); 56080c646dSJean-Christophe PLAGNIOL-VILLARD outw (I2C_CON_EN, I2C_CON); 57080c646dSJean-Christophe PLAGNIOL-VILLARD 58080c646dSJean-Christophe PLAGNIOL-VILLARD /* have to enable intrrupts or OMAP i2c module doesn't work */ 59080c646dSJean-Christophe PLAGNIOL-VILLARD outw (I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | 60080c646dSJean-Christophe PLAGNIOL-VILLARD I2C_IE_NACK_IE | I2C_IE_AL_IE, I2C_IE); 61080c646dSJean-Christophe PLAGNIOL-VILLARD udelay (1000); 62080c646dSJean-Christophe PLAGNIOL-VILLARD flush_fifo(); 63080c646dSJean-Christophe PLAGNIOL-VILLARD outw (0xFFFF, I2C_STAT); 64080c646dSJean-Christophe PLAGNIOL-VILLARD outw (0, I2C_CNT); 65080c646dSJean-Christophe PLAGNIOL-VILLARD } 66080c646dSJean-Christophe PLAGNIOL-VILLARD 67080c646dSJean-Christophe PLAGNIOL-VILLARD static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value) 68080c646dSJean-Christophe PLAGNIOL-VILLARD { 69080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_error = 0; 70080c646dSJean-Christophe PLAGNIOL-VILLARD u16 status; 71080c646dSJean-Christophe PLAGNIOL-VILLARD 72080c646dSJean-Christophe PLAGNIOL-VILLARD /* wait until bus not busy */ 73080c646dSJean-Christophe PLAGNIOL-VILLARD wait_for_bb (); 74080c646dSJean-Christophe PLAGNIOL-VILLARD 75080c646dSJean-Christophe PLAGNIOL-VILLARD /* one byte only */ 76080c646dSJean-Christophe PLAGNIOL-VILLARD outw (1, I2C_CNT); 77080c646dSJean-Christophe PLAGNIOL-VILLARD /* set slave address */ 78080c646dSJean-Christophe PLAGNIOL-VILLARD outw (devaddr, I2C_SA); 79080c646dSJean-Christophe PLAGNIOL-VILLARD /* no stop bit needed here */ 80080c646dSJean-Christophe PLAGNIOL-VILLARD outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX, I2C_CON); 81080c646dSJean-Christophe PLAGNIOL-VILLARD 82080c646dSJean-Christophe PLAGNIOL-VILLARD status = wait_for_pin (); 83080c646dSJean-Christophe PLAGNIOL-VILLARD 84080c646dSJean-Christophe PLAGNIOL-VILLARD if (status & I2C_STAT_XRDY) { 85080c646dSJean-Christophe PLAGNIOL-VILLARD /* Important: have to use byte access */ 86080c646dSJean-Christophe PLAGNIOL-VILLARD *(volatile u8 *) (I2C_DATA) = regoffset; 87080c646dSJean-Christophe PLAGNIOL-VILLARD udelay (20000); 88080c646dSJean-Christophe PLAGNIOL-VILLARD if (inw (I2C_STAT) & I2C_STAT_NACK) { 89080c646dSJean-Christophe PLAGNIOL-VILLARD i2c_error = 1; 90080c646dSJean-Christophe PLAGNIOL-VILLARD } 91080c646dSJean-Christophe PLAGNIOL-VILLARD } else { 92080c646dSJean-Christophe PLAGNIOL-VILLARD i2c_error = 1; 93080c646dSJean-Christophe PLAGNIOL-VILLARD } 94080c646dSJean-Christophe PLAGNIOL-VILLARD 95080c646dSJean-Christophe PLAGNIOL-VILLARD if (!i2c_error) { 96080c646dSJean-Christophe PLAGNIOL-VILLARD /* free bus, otherwise we can't use a combined transction */ 97080c646dSJean-Christophe PLAGNIOL-VILLARD outw (0, I2C_CON); 98080c646dSJean-Christophe PLAGNIOL-VILLARD while (inw (I2C_STAT) || (inw (I2C_CON) & I2C_CON_MST)) { 99080c646dSJean-Christophe PLAGNIOL-VILLARD udelay (10000); 100080c646dSJean-Christophe PLAGNIOL-VILLARD /* Have to clear pending interrupt to clear I2C_STAT */ 101080c646dSJean-Christophe PLAGNIOL-VILLARD outw (0xFFFF, I2C_STAT); 102080c646dSJean-Christophe PLAGNIOL-VILLARD } 103080c646dSJean-Christophe PLAGNIOL-VILLARD 104080c646dSJean-Christophe PLAGNIOL-VILLARD wait_for_bb (); 105080c646dSJean-Christophe PLAGNIOL-VILLARD /* set slave address */ 106080c646dSJean-Christophe PLAGNIOL-VILLARD outw (devaddr, I2C_SA); 107080c646dSJean-Christophe PLAGNIOL-VILLARD /* read one byte from slave */ 108080c646dSJean-Christophe PLAGNIOL-VILLARD outw (1, I2C_CNT); 109080c646dSJean-Christophe PLAGNIOL-VILLARD /* need stop bit here */ 110080c646dSJean-Christophe PLAGNIOL-VILLARD outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, 111080c646dSJean-Christophe PLAGNIOL-VILLARD I2C_CON); 112080c646dSJean-Christophe PLAGNIOL-VILLARD 113080c646dSJean-Christophe PLAGNIOL-VILLARD status = wait_for_pin (); 114080c646dSJean-Christophe PLAGNIOL-VILLARD if (status & I2C_STAT_RRDY) { 115080c646dSJean-Christophe PLAGNIOL-VILLARD *value = inw (I2C_DATA); 116080c646dSJean-Christophe PLAGNIOL-VILLARD udelay (20000); 117080c646dSJean-Christophe PLAGNIOL-VILLARD } else { 118080c646dSJean-Christophe PLAGNIOL-VILLARD i2c_error = 1; 119080c646dSJean-Christophe PLAGNIOL-VILLARD } 120080c646dSJean-Christophe PLAGNIOL-VILLARD 121080c646dSJean-Christophe PLAGNIOL-VILLARD if (!i2c_error) { 122080c646dSJean-Christophe PLAGNIOL-VILLARD outw (I2C_CON_EN, I2C_CON); 123080c646dSJean-Christophe PLAGNIOL-VILLARD while (inw (I2C_STAT) 124080c646dSJean-Christophe PLAGNIOL-VILLARD || (inw (I2C_CON) & I2C_CON_MST)) { 125080c646dSJean-Christophe PLAGNIOL-VILLARD udelay (10000); 126080c646dSJean-Christophe PLAGNIOL-VILLARD outw (0xFFFF, I2C_STAT); 127080c646dSJean-Christophe PLAGNIOL-VILLARD } 128080c646dSJean-Christophe PLAGNIOL-VILLARD } 129080c646dSJean-Christophe PLAGNIOL-VILLARD } 130080c646dSJean-Christophe PLAGNIOL-VILLARD flush_fifo(); 131080c646dSJean-Christophe PLAGNIOL-VILLARD outw (0xFFFF, I2C_STAT); 132080c646dSJean-Christophe PLAGNIOL-VILLARD outw (0, I2C_CNT); 133080c646dSJean-Christophe PLAGNIOL-VILLARD return i2c_error; 134080c646dSJean-Christophe PLAGNIOL-VILLARD } 135080c646dSJean-Christophe PLAGNIOL-VILLARD 136080c646dSJean-Christophe PLAGNIOL-VILLARD static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value) 137080c646dSJean-Christophe PLAGNIOL-VILLARD { 138080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_error = 0; 139080c646dSJean-Christophe PLAGNIOL-VILLARD u16 status, stat; 140080c646dSJean-Christophe PLAGNIOL-VILLARD 141080c646dSJean-Christophe PLAGNIOL-VILLARD /* wait until bus not busy */ 142080c646dSJean-Christophe PLAGNIOL-VILLARD wait_for_bb (); 143080c646dSJean-Christophe PLAGNIOL-VILLARD 144080c646dSJean-Christophe PLAGNIOL-VILLARD /* two bytes */ 145080c646dSJean-Christophe PLAGNIOL-VILLARD outw (2, I2C_CNT); 146080c646dSJean-Christophe PLAGNIOL-VILLARD /* set slave address */ 147080c646dSJean-Christophe PLAGNIOL-VILLARD outw (devaddr, I2C_SA); 148080c646dSJean-Christophe PLAGNIOL-VILLARD /* stop bit needed here */ 149080c646dSJean-Christophe PLAGNIOL-VILLARD outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | 150080c646dSJean-Christophe PLAGNIOL-VILLARD I2C_CON_STP, I2C_CON); 151080c646dSJean-Christophe PLAGNIOL-VILLARD 152080c646dSJean-Christophe PLAGNIOL-VILLARD /* wait until state change */ 153080c646dSJean-Christophe PLAGNIOL-VILLARD status = wait_for_pin (); 154080c646dSJean-Christophe PLAGNIOL-VILLARD 155080c646dSJean-Christophe PLAGNIOL-VILLARD if (status & I2C_STAT_XRDY) { 156080c646dSJean-Christophe PLAGNIOL-VILLARD /* send out two bytes */ 157080c646dSJean-Christophe PLAGNIOL-VILLARD outw ((value << 8) + regoffset, I2C_DATA); 158080c646dSJean-Christophe PLAGNIOL-VILLARD /* must have enough delay to allow BB bit to go low */ 159080c646dSJean-Christophe PLAGNIOL-VILLARD udelay (50000); 160080c646dSJean-Christophe PLAGNIOL-VILLARD if (inw (I2C_STAT) & I2C_STAT_NACK) { 161080c646dSJean-Christophe PLAGNIOL-VILLARD i2c_error = 1; 162080c646dSJean-Christophe PLAGNIOL-VILLARD } 163080c646dSJean-Christophe PLAGNIOL-VILLARD } else { 164080c646dSJean-Christophe PLAGNIOL-VILLARD i2c_error = 1; 165080c646dSJean-Christophe PLAGNIOL-VILLARD } 166080c646dSJean-Christophe PLAGNIOL-VILLARD 167080c646dSJean-Christophe PLAGNIOL-VILLARD if (!i2c_error) { 168080c646dSJean-Christophe PLAGNIOL-VILLARD int eout = 200; 169080c646dSJean-Christophe PLAGNIOL-VILLARD 170080c646dSJean-Christophe PLAGNIOL-VILLARD outw (I2C_CON_EN, I2C_CON); 171080c646dSJean-Christophe PLAGNIOL-VILLARD while ((stat = inw (I2C_STAT)) || (inw (I2C_CON) & I2C_CON_MST)) { 172080c646dSJean-Christophe PLAGNIOL-VILLARD udelay (1000); 173080c646dSJean-Christophe PLAGNIOL-VILLARD /* have to read to clear intrrupt */ 174080c646dSJean-Christophe PLAGNIOL-VILLARD outw (0xFFFF, I2C_STAT); 175080c646dSJean-Christophe PLAGNIOL-VILLARD if(--eout == 0) /* better leave with error than hang */ 176080c646dSJean-Christophe PLAGNIOL-VILLARD break; 177080c646dSJean-Christophe PLAGNIOL-VILLARD } 178080c646dSJean-Christophe PLAGNIOL-VILLARD } 179080c646dSJean-Christophe PLAGNIOL-VILLARD flush_fifo(); 180080c646dSJean-Christophe PLAGNIOL-VILLARD outw (0xFFFF, I2C_STAT); 181080c646dSJean-Christophe PLAGNIOL-VILLARD outw (0, I2C_CNT); 182080c646dSJean-Christophe PLAGNIOL-VILLARD return i2c_error; 183080c646dSJean-Christophe PLAGNIOL-VILLARD } 184080c646dSJean-Christophe PLAGNIOL-VILLARD 185080c646dSJean-Christophe PLAGNIOL-VILLARD static void flush_fifo(void) 186080c646dSJean-Christophe PLAGNIOL-VILLARD { u16 stat; 187080c646dSJean-Christophe PLAGNIOL-VILLARD 188080c646dSJean-Christophe PLAGNIOL-VILLARD /* note: if you try and read data when its not there or ready 189080c646dSJean-Christophe PLAGNIOL-VILLARD * you get a bus error 190080c646dSJean-Christophe PLAGNIOL-VILLARD */ 191080c646dSJean-Christophe PLAGNIOL-VILLARD while(1){ 192080c646dSJean-Christophe PLAGNIOL-VILLARD stat = inw(I2C_STAT); 193080c646dSJean-Christophe PLAGNIOL-VILLARD if(stat == I2C_STAT_RRDY){ 194080c646dSJean-Christophe PLAGNIOL-VILLARD inw(I2C_DATA); 195080c646dSJean-Christophe PLAGNIOL-VILLARD outw(I2C_STAT_RRDY,I2C_STAT); 196080c646dSJean-Christophe PLAGNIOL-VILLARD udelay(1000); 197080c646dSJean-Christophe PLAGNIOL-VILLARD }else 198080c646dSJean-Christophe PLAGNIOL-VILLARD break; 199080c646dSJean-Christophe PLAGNIOL-VILLARD } 200080c646dSJean-Christophe PLAGNIOL-VILLARD } 201080c646dSJean-Christophe PLAGNIOL-VILLARD 202080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_probe (uchar chip) 203080c646dSJean-Christophe PLAGNIOL-VILLARD { 204080c646dSJean-Christophe PLAGNIOL-VILLARD int res = 1; /* default = fail */ 205080c646dSJean-Christophe PLAGNIOL-VILLARD 206080c646dSJean-Christophe PLAGNIOL-VILLARD if (chip == inw (I2C_OA)) { 207080c646dSJean-Christophe PLAGNIOL-VILLARD return res; 208080c646dSJean-Christophe PLAGNIOL-VILLARD } 209080c646dSJean-Christophe PLAGNIOL-VILLARD 210080c646dSJean-Christophe PLAGNIOL-VILLARD /* wait until bus not busy */ 211080c646dSJean-Christophe PLAGNIOL-VILLARD wait_for_bb (); 212080c646dSJean-Christophe PLAGNIOL-VILLARD 213080c646dSJean-Christophe PLAGNIOL-VILLARD /* try to read one byte */ 214080c646dSJean-Christophe PLAGNIOL-VILLARD outw (1, I2C_CNT); 215080c646dSJean-Christophe PLAGNIOL-VILLARD /* set slave address */ 216080c646dSJean-Christophe PLAGNIOL-VILLARD outw (chip, I2C_SA); 217080c646dSJean-Christophe PLAGNIOL-VILLARD /* stop bit needed here */ 218080c646dSJean-Christophe PLAGNIOL-VILLARD outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, I2C_CON); 219080c646dSJean-Christophe PLAGNIOL-VILLARD /* enough delay for the NACK bit set */ 220080c646dSJean-Christophe PLAGNIOL-VILLARD udelay (50000); 221080c646dSJean-Christophe PLAGNIOL-VILLARD 222080c646dSJean-Christophe PLAGNIOL-VILLARD if (!(inw (I2C_STAT) & I2C_STAT_NACK)) { 223080c646dSJean-Christophe PLAGNIOL-VILLARD res = 0; /* success case */ 224080c646dSJean-Christophe PLAGNIOL-VILLARD flush_fifo(); 225080c646dSJean-Christophe PLAGNIOL-VILLARD outw(0xFFFF, I2C_STAT); 226080c646dSJean-Christophe PLAGNIOL-VILLARD } else { 227080c646dSJean-Christophe PLAGNIOL-VILLARD outw(0xFFFF, I2C_STAT); /* failue, clear sources*/ 228080c646dSJean-Christophe PLAGNIOL-VILLARD outw (inw (I2C_CON) | I2C_CON_STP, I2C_CON); /* finish up xfer */ 229080c646dSJean-Christophe PLAGNIOL-VILLARD udelay(20000); 230080c646dSJean-Christophe PLAGNIOL-VILLARD wait_for_bb (); 231080c646dSJean-Christophe PLAGNIOL-VILLARD } 232080c646dSJean-Christophe PLAGNIOL-VILLARD flush_fifo(); 233080c646dSJean-Christophe PLAGNIOL-VILLARD outw (0, I2C_CNT); /* don't allow any more data in...we don't want it.*/ 234080c646dSJean-Christophe PLAGNIOL-VILLARD outw(0xFFFF, I2C_STAT); 235080c646dSJean-Christophe PLAGNIOL-VILLARD return res; 236080c646dSJean-Christophe PLAGNIOL-VILLARD } 237080c646dSJean-Christophe PLAGNIOL-VILLARD 238080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len) 239080c646dSJean-Christophe PLAGNIOL-VILLARD { 240080c646dSJean-Christophe PLAGNIOL-VILLARD int i; 241080c646dSJean-Christophe PLAGNIOL-VILLARD 242080c646dSJean-Christophe PLAGNIOL-VILLARD if (alen > 1) { 243080c646dSJean-Christophe PLAGNIOL-VILLARD printf ("I2C read: addr len %d not supported\n", alen); 244080c646dSJean-Christophe PLAGNIOL-VILLARD return 1; 245080c646dSJean-Christophe PLAGNIOL-VILLARD } 246080c646dSJean-Christophe PLAGNIOL-VILLARD 247080c646dSJean-Christophe PLAGNIOL-VILLARD if (addr + len > 256) { 248080c646dSJean-Christophe PLAGNIOL-VILLARD printf ("I2C read: address out of range\n"); 249080c646dSJean-Christophe PLAGNIOL-VILLARD return 1; 250080c646dSJean-Christophe PLAGNIOL-VILLARD } 251080c646dSJean-Christophe PLAGNIOL-VILLARD 252080c646dSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < len; i++) { 253080c646dSJean-Christophe PLAGNIOL-VILLARD if (i2c_read_byte (chip, addr + i, &buffer[i])) { 254080c646dSJean-Christophe PLAGNIOL-VILLARD printf ("I2C read: I/O error\n"); 2556d0f6bcfSJean-Christophe PLAGNIOL-VILLARD i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); 256080c646dSJean-Christophe PLAGNIOL-VILLARD return 1; 257080c646dSJean-Christophe PLAGNIOL-VILLARD } 258080c646dSJean-Christophe PLAGNIOL-VILLARD } 259080c646dSJean-Christophe PLAGNIOL-VILLARD 260080c646dSJean-Christophe PLAGNIOL-VILLARD return 0; 261080c646dSJean-Christophe PLAGNIOL-VILLARD } 262080c646dSJean-Christophe PLAGNIOL-VILLARD 263080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len) 264080c646dSJean-Christophe PLAGNIOL-VILLARD { 265080c646dSJean-Christophe PLAGNIOL-VILLARD int i; 266080c646dSJean-Christophe PLAGNIOL-VILLARD 267080c646dSJean-Christophe PLAGNIOL-VILLARD if (alen > 1) { 268080c646dSJean-Christophe PLAGNIOL-VILLARD printf ("I2C read: addr len %d not supported\n", alen); 269080c646dSJean-Christophe PLAGNIOL-VILLARD return 1; 270080c646dSJean-Christophe PLAGNIOL-VILLARD } 271080c646dSJean-Christophe PLAGNIOL-VILLARD 272080c646dSJean-Christophe PLAGNIOL-VILLARD if (addr + len > 256) { 273080c646dSJean-Christophe PLAGNIOL-VILLARD printf ("I2C read: address out of range\n"); 274080c646dSJean-Christophe PLAGNIOL-VILLARD return 1; 275080c646dSJean-Christophe PLAGNIOL-VILLARD } 276080c646dSJean-Christophe PLAGNIOL-VILLARD 277080c646dSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < len; i++) { 278080c646dSJean-Christophe PLAGNIOL-VILLARD if (i2c_write_byte (chip, addr + i, buffer[i])) { 279080c646dSJean-Christophe PLAGNIOL-VILLARD printf ("I2C read: I/O error\n"); 2806d0f6bcfSJean-Christophe PLAGNIOL-VILLARD i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); 281080c646dSJean-Christophe PLAGNIOL-VILLARD return 1; 282080c646dSJean-Christophe PLAGNIOL-VILLARD } 283080c646dSJean-Christophe PLAGNIOL-VILLARD } 284080c646dSJean-Christophe PLAGNIOL-VILLARD 285080c646dSJean-Christophe PLAGNIOL-VILLARD return 0; 286080c646dSJean-Christophe PLAGNIOL-VILLARD } 287080c646dSJean-Christophe PLAGNIOL-VILLARD 288080c646dSJean-Christophe PLAGNIOL-VILLARD static void wait_for_bb (void) 289080c646dSJean-Christophe PLAGNIOL-VILLARD { 290080c646dSJean-Christophe PLAGNIOL-VILLARD int timeout = 10; 291080c646dSJean-Christophe PLAGNIOL-VILLARD u16 stat; 292080c646dSJean-Christophe PLAGNIOL-VILLARD 293080c646dSJean-Christophe PLAGNIOL-VILLARD outw(0xFFFF, I2C_STAT); /* clear current interruts...*/ 294080c646dSJean-Christophe PLAGNIOL-VILLARD while ((stat = inw (I2C_STAT) & I2C_STAT_BB) && timeout--) { 295080c646dSJean-Christophe PLAGNIOL-VILLARD outw (stat, I2C_STAT); 296080c646dSJean-Christophe PLAGNIOL-VILLARD udelay (50000); 297080c646dSJean-Christophe PLAGNIOL-VILLARD } 298080c646dSJean-Christophe PLAGNIOL-VILLARD 299080c646dSJean-Christophe PLAGNIOL-VILLARD if (timeout <= 0) { 300080c646dSJean-Christophe PLAGNIOL-VILLARD printf ("timed out in wait_for_bb: I2C_STAT=%x\n", 301080c646dSJean-Christophe PLAGNIOL-VILLARD inw (I2C_STAT)); 302080c646dSJean-Christophe PLAGNIOL-VILLARD } 303080c646dSJean-Christophe PLAGNIOL-VILLARD outw(0xFFFF, I2C_STAT); /* clear delayed stuff*/ 304080c646dSJean-Christophe PLAGNIOL-VILLARD } 305080c646dSJean-Christophe PLAGNIOL-VILLARD 306080c646dSJean-Christophe PLAGNIOL-VILLARD static u16 wait_for_pin (void) 307080c646dSJean-Christophe PLAGNIOL-VILLARD { 308080c646dSJean-Christophe PLAGNIOL-VILLARD u16 status; 309080c646dSJean-Christophe PLAGNIOL-VILLARD int timeout = 10; 310080c646dSJean-Christophe PLAGNIOL-VILLARD 311080c646dSJean-Christophe PLAGNIOL-VILLARD do { 312080c646dSJean-Christophe PLAGNIOL-VILLARD udelay (1000); 313080c646dSJean-Christophe PLAGNIOL-VILLARD status = inw (I2C_STAT); 314080c646dSJean-Christophe PLAGNIOL-VILLARD } while ( !(status & 315080c646dSJean-Christophe PLAGNIOL-VILLARD (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY | 316080c646dSJean-Christophe PLAGNIOL-VILLARD I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK | 317080c646dSJean-Christophe PLAGNIOL-VILLARD I2C_STAT_AL)) && timeout--); 318080c646dSJean-Christophe PLAGNIOL-VILLARD 319080c646dSJean-Christophe PLAGNIOL-VILLARD if (timeout <= 0) { 320080c646dSJean-Christophe PLAGNIOL-VILLARD printf ("timed out in wait_for_pin: I2C_STAT=%x\n", 321080c646dSJean-Christophe PLAGNIOL-VILLARD inw (I2C_STAT)); 322080c646dSJean-Christophe PLAGNIOL-VILLARD outw(0xFFFF, I2C_STAT); 323080c646dSJean-Christophe PLAGNIOL-VILLARD } 324080c646dSJean-Christophe PLAGNIOL-VILLARD return status; 325080c646dSJean-Christophe PLAGNIOL-VILLARD } 326