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 static void wait_for_bb (void); 29080c646dSJean-Christophe PLAGNIOL-VILLARD static u16 wait_for_pin (void); 30080c646dSJean-Christophe PLAGNIOL-VILLARD static void flush_fifo(void); 31080c646dSJean-Christophe PLAGNIOL-VILLARD 32080c646dSJean-Christophe PLAGNIOL-VILLARD void i2c_init (int speed, int slaveadd) 33080c646dSJean-Christophe PLAGNIOL-VILLARD { 34*7f79dfb4STom Rix int psc, fsscll, fssclh; 35*7f79dfb4STom Rix int hsscll = 0, hssclh = 0; 36*7f79dfb4STom Rix u32 scll, sclh; 37*7f79dfb4STom Rix 38*7f79dfb4STom Rix /* Only handle standard, fast and high speeds */ 39*7f79dfb4STom Rix if ((speed != OMAP_I2C_STANDARD) && 40*7f79dfb4STom Rix (speed != OMAP_I2C_FAST_MODE) && 41*7f79dfb4STom Rix (speed != OMAP_I2C_HIGH_SPEED)) { 42*7f79dfb4STom Rix printf("Error : I2C unsupported speed %d\n", speed); 43*7f79dfb4STom Rix return; 44*7f79dfb4STom Rix } 45*7f79dfb4STom Rix 46*7f79dfb4STom Rix psc = I2C_IP_CLK / I2C_INTERNAL_SAMPLING_CLK; 47*7f79dfb4STom Rix psc -= 1; 48*7f79dfb4STom Rix if (psc < I2C_PSC_MIN) { 49*7f79dfb4STom Rix printf("Error : I2C unsupported prescalar %d\n", psc); 50*7f79dfb4STom Rix return; 51*7f79dfb4STom Rix } 52*7f79dfb4STom Rix 53*7f79dfb4STom Rix if (speed == OMAP_I2C_HIGH_SPEED) { 54*7f79dfb4STom Rix /* High speed */ 55*7f79dfb4STom Rix 56*7f79dfb4STom Rix /* For first phase of HS mode */ 57*7f79dfb4STom Rix fsscll = fssclh = I2C_INTERNAL_SAMPLING_CLK / 58*7f79dfb4STom Rix (2 * OMAP_I2C_FAST_MODE); 59*7f79dfb4STom Rix 60*7f79dfb4STom Rix fsscll -= I2C_HIGHSPEED_PHASE_ONE_SCLL_TRIM; 61*7f79dfb4STom Rix fssclh -= I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM; 62*7f79dfb4STom Rix if (((fsscll < 0) || (fssclh < 0)) || 63*7f79dfb4STom Rix ((fsscll > 255) || (fssclh > 255))) { 64*7f79dfb4STom Rix printf("Error : I2C initializing first phase clock\n"); 65*7f79dfb4STom Rix return; 66*7f79dfb4STom Rix } 67*7f79dfb4STom Rix 68*7f79dfb4STom Rix /* For second phase of HS mode */ 69*7f79dfb4STom Rix hsscll = hssclh = I2C_INTERNAL_SAMPLING_CLK / (2 * speed); 70*7f79dfb4STom Rix 71*7f79dfb4STom Rix hsscll -= I2C_HIGHSPEED_PHASE_TWO_SCLL_TRIM; 72*7f79dfb4STom Rix hssclh -= I2C_HIGHSPEED_PHASE_TWO_SCLH_TRIM; 73*7f79dfb4STom Rix if (((fsscll < 0) || (fssclh < 0)) || 74*7f79dfb4STom Rix ((fsscll > 255) || (fssclh > 255))) { 75*7f79dfb4STom Rix printf("Error : I2C initializing second phase clock\n"); 76*7f79dfb4STom Rix return; 77*7f79dfb4STom Rix } 78*7f79dfb4STom Rix 79*7f79dfb4STom Rix scll = (unsigned int)hsscll << 8 | (unsigned int)fsscll; 80*7f79dfb4STom Rix sclh = (unsigned int)hssclh << 8 | (unsigned int)fssclh; 81*7f79dfb4STom Rix 82*7f79dfb4STom Rix } else { 83*7f79dfb4STom Rix /* Standard and fast speed */ 84*7f79dfb4STom Rix fsscll = fssclh = I2C_INTERNAL_SAMPLING_CLK / (2 * speed); 85*7f79dfb4STom Rix 86*7f79dfb4STom Rix fsscll -= I2C_FASTSPEED_SCLL_TRIM; 87*7f79dfb4STom Rix fssclh -= I2C_FASTSPEED_SCLH_TRIM; 88*7f79dfb4STom Rix if (((fsscll < 0) || (fssclh < 0)) || 89*7f79dfb4STom Rix ((fsscll > 255) || (fssclh > 255))) { 90*7f79dfb4STom Rix printf("Error : I2C initializing clock\n"); 91*7f79dfb4STom Rix return; 92*7f79dfb4STom Rix } 93*7f79dfb4STom Rix 94*7f79dfb4STom Rix scll = (unsigned int)fsscll; 95*7f79dfb4STom Rix sclh = (unsigned int)fssclh; 96*7f79dfb4STom Rix } 97080c646dSJean-Christophe PLAGNIOL-VILLARD 98e23c7c95SDirk Behme writew(0x2, I2C_SYSC); /* for ES2 after soft reset */ 99080c646dSJean-Christophe PLAGNIOL-VILLARD udelay(1000); 100e23c7c95SDirk Behme writew(0x0, I2C_SYSC); /* will probably self clear but */ 101080c646dSJean-Christophe PLAGNIOL-VILLARD 102e23c7c95SDirk Behme if (readw (I2C_CON) & I2C_CON_EN) { 103e23c7c95SDirk Behme writew (0, I2C_CON); 104080c646dSJean-Christophe PLAGNIOL-VILLARD udelay (50000); 105080c646dSJean-Christophe PLAGNIOL-VILLARD } 106080c646dSJean-Christophe PLAGNIOL-VILLARD 107*7f79dfb4STom Rix writew(psc, I2C_PSC); 108*7f79dfb4STom Rix writew(scll, I2C_SCLL); 109*7f79dfb4STom Rix writew(sclh, I2C_SCLH); 110*7f79dfb4STom Rix 111080c646dSJean-Christophe PLAGNIOL-VILLARD /* own address */ 112e23c7c95SDirk Behme writew (slaveadd, I2C_OA); 113e23c7c95SDirk Behme writew (I2C_CON_EN, I2C_CON); 114080c646dSJean-Christophe PLAGNIOL-VILLARD 115080c646dSJean-Christophe PLAGNIOL-VILLARD /* have to enable intrrupts or OMAP i2c module doesn't work */ 116e23c7c95SDirk Behme writew (I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | 117080c646dSJean-Christophe PLAGNIOL-VILLARD I2C_IE_NACK_IE | I2C_IE_AL_IE, I2C_IE); 118080c646dSJean-Christophe PLAGNIOL-VILLARD udelay (1000); 119080c646dSJean-Christophe PLAGNIOL-VILLARD flush_fifo(); 120e23c7c95SDirk Behme writew (0xFFFF, I2C_STAT); 121e23c7c95SDirk Behme writew (0, I2C_CNT); 122080c646dSJean-Christophe PLAGNIOL-VILLARD } 123080c646dSJean-Christophe PLAGNIOL-VILLARD 124080c646dSJean-Christophe PLAGNIOL-VILLARD static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value) 125080c646dSJean-Christophe PLAGNIOL-VILLARD { 126080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_error = 0; 127080c646dSJean-Christophe PLAGNIOL-VILLARD u16 status; 128080c646dSJean-Christophe PLAGNIOL-VILLARD 129080c646dSJean-Christophe PLAGNIOL-VILLARD /* wait until bus not busy */ 130080c646dSJean-Christophe PLAGNIOL-VILLARD wait_for_bb (); 131080c646dSJean-Christophe PLAGNIOL-VILLARD 132080c646dSJean-Christophe PLAGNIOL-VILLARD /* one byte only */ 133e23c7c95SDirk Behme writew (1, I2C_CNT); 134080c646dSJean-Christophe PLAGNIOL-VILLARD /* set slave address */ 135e23c7c95SDirk Behme writew (devaddr, I2C_SA); 136080c646dSJean-Christophe PLAGNIOL-VILLARD /* no stop bit needed here */ 137e23c7c95SDirk Behme writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX, I2C_CON); 138080c646dSJean-Christophe PLAGNIOL-VILLARD 139080c646dSJean-Christophe PLAGNIOL-VILLARD status = wait_for_pin (); 140080c646dSJean-Christophe PLAGNIOL-VILLARD 141080c646dSJean-Christophe PLAGNIOL-VILLARD if (status & I2C_STAT_XRDY) { 142080c646dSJean-Christophe PLAGNIOL-VILLARD /* Important: have to use byte access */ 143e23c7c95SDirk Behme writeb (regoffset, I2C_DATA); 144080c646dSJean-Christophe PLAGNIOL-VILLARD udelay (20000); 145e23c7c95SDirk Behme if (readw (I2C_STAT) & I2C_STAT_NACK) { 146080c646dSJean-Christophe PLAGNIOL-VILLARD i2c_error = 1; 147080c646dSJean-Christophe PLAGNIOL-VILLARD } 148080c646dSJean-Christophe PLAGNIOL-VILLARD } else { 149080c646dSJean-Christophe PLAGNIOL-VILLARD i2c_error = 1; 150080c646dSJean-Christophe PLAGNIOL-VILLARD } 151080c646dSJean-Christophe PLAGNIOL-VILLARD 152080c646dSJean-Christophe PLAGNIOL-VILLARD if (!i2c_error) { 153080c646dSJean-Christophe PLAGNIOL-VILLARD /* free bus, otherwise we can't use a combined transction */ 154e23c7c95SDirk Behme writew (0, I2C_CON); 155e23c7c95SDirk Behme while (readw (I2C_STAT) || (readw (I2C_CON) & I2C_CON_MST)) { 156080c646dSJean-Christophe PLAGNIOL-VILLARD udelay (10000); 157080c646dSJean-Christophe PLAGNIOL-VILLARD /* Have to clear pending interrupt to clear I2C_STAT */ 158e23c7c95SDirk Behme writew (0xFFFF, I2C_STAT); 159080c646dSJean-Christophe PLAGNIOL-VILLARD } 160080c646dSJean-Christophe PLAGNIOL-VILLARD 161080c646dSJean-Christophe PLAGNIOL-VILLARD wait_for_bb (); 162080c646dSJean-Christophe PLAGNIOL-VILLARD /* set slave address */ 163e23c7c95SDirk Behme writew (devaddr, I2C_SA); 164080c646dSJean-Christophe PLAGNIOL-VILLARD /* read one byte from slave */ 165e23c7c95SDirk Behme writew (1, I2C_CNT); 166080c646dSJean-Christophe PLAGNIOL-VILLARD /* need stop bit here */ 167e23c7c95SDirk Behme writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, 168080c646dSJean-Christophe PLAGNIOL-VILLARD I2C_CON); 169080c646dSJean-Christophe PLAGNIOL-VILLARD 170080c646dSJean-Christophe PLAGNIOL-VILLARD status = wait_for_pin (); 171080c646dSJean-Christophe PLAGNIOL-VILLARD if (status & I2C_STAT_RRDY) { 1727d264c1eSDirk Behme #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) 1737d264c1eSDirk Behme *value = readb (I2C_DATA); 1747d264c1eSDirk Behme #else 175e23c7c95SDirk Behme *value = readw (I2C_DATA); 1767d264c1eSDirk Behme #endif 177080c646dSJean-Christophe PLAGNIOL-VILLARD udelay (20000); 178080c646dSJean-Christophe PLAGNIOL-VILLARD } else { 179080c646dSJean-Christophe PLAGNIOL-VILLARD i2c_error = 1; 180080c646dSJean-Christophe PLAGNIOL-VILLARD } 181080c646dSJean-Christophe PLAGNIOL-VILLARD 182080c646dSJean-Christophe PLAGNIOL-VILLARD if (!i2c_error) { 183e23c7c95SDirk Behme writew (I2C_CON_EN, I2C_CON); 184e23c7c95SDirk Behme while (readw (I2C_STAT) 185e23c7c95SDirk Behme || (readw (I2C_CON) & I2C_CON_MST)) { 186080c646dSJean-Christophe PLAGNIOL-VILLARD udelay (10000); 187e23c7c95SDirk Behme writew (0xFFFF, I2C_STAT); 188080c646dSJean-Christophe PLAGNIOL-VILLARD } 189080c646dSJean-Christophe PLAGNIOL-VILLARD } 190080c646dSJean-Christophe PLAGNIOL-VILLARD } 191080c646dSJean-Christophe PLAGNIOL-VILLARD flush_fifo(); 192e23c7c95SDirk Behme writew (0xFFFF, I2C_STAT); 193e23c7c95SDirk Behme writew (0, I2C_CNT); 194080c646dSJean-Christophe PLAGNIOL-VILLARD return i2c_error; 195080c646dSJean-Christophe PLAGNIOL-VILLARD } 196080c646dSJean-Christophe PLAGNIOL-VILLARD 197080c646dSJean-Christophe PLAGNIOL-VILLARD static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value) 198080c646dSJean-Christophe PLAGNIOL-VILLARD { 199080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_error = 0; 200080c646dSJean-Christophe PLAGNIOL-VILLARD u16 status, stat; 201080c646dSJean-Christophe PLAGNIOL-VILLARD 202080c646dSJean-Christophe PLAGNIOL-VILLARD /* wait until bus not busy */ 203080c646dSJean-Christophe PLAGNIOL-VILLARD wait_for_bb (); 204080c646dSJean-Christophe PLAGNIOL-VILLARD 205080c646dSJean-Christophe PLAGNIOL-VILLARD /* two bytes */ 206e23c7c95SDirk Behme writew (2, I2C_CNT); 207080c646dSJean-Christophe PLAGNIOL-VILLARD /* set slave address */ 208e23c7c95SDirk Behme writew (devaddr, I2C_SA); 209080c646dSJean-Christophe PLAGNIOL-VILLARD /* stop bit needed here */ 210e23c7c95SDirk Behme writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | 211080c646dSJean-Christophe PLAGNIOL-VILLARD I2C_CON_STP, I2C_CON); 212080c646dSJean-Christophe PLAGNIOL-VILLARD 213080c646dSJean-Christophe PLAGNIOL-VILLARD /* wait until state change */ 214080c646dSJean-Christophe PLAGNIOL-VILLARD status = wait_for_pin (); 215080c646dSJean-Christophe PLAGNIOL-VILLARD 216080c646dSJean-Christophe PLAGNIOL-VILLARD if (status & I2C_STAT_XRDY) { 2177d264c1eSDirk Behme #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) 2187d264c1eSDirk Behme /* send out 1 byte */ 2197d264c1eSDirk Behme writeb (regoffset, I2C_DATA); 2207d264c1eSDirk Behme writew (I2C_STAT_XRDY, I2C_STAT); 2217d264c1eSDirk Behme 2227d264c1eSDirk Behme status = wait_for_pin (); 2237d264c1eSDirk Behme if ((status & I2C_STAT_XRDY)) { 2247d264c1eSDirk Behme /* send out next 1 byte */ 2257d264c1eSDirk Behme writeb (value, I2C_DATA); 2267d264c1eSDirk Behme writew (I2C_STAT_XRDY, I2C_STAT); 2277d264c1eSDirk Behme } else { 2287d264c1eSDirk Behme i2c_error = 1; 2297d264c1eSDirk Behme } 2307d264c1eSDirk Behme #else 231080c646dSJean-Christophe PLAGNIOL-VILLARD /* send out two bytes */ 232e23c7c95SDirk Behme writew ((value << 8) + regoffset, I2C_DATA); 2337d264c1eSDirk Behme #endif 234080c646dSJean-Christophe PLAGNIOL-VILLARD /* must have enough delay to allow BB bit to go low */ 235080c646dSJean-Christophe PLAGNIOL-VILLARD udelay (50000); 236e23c7c95SDirk Behme if (readw (I2C_STAT) & I2C_STAT_NACK) { 237080c646dSJean-Christophe PLAGNIOL-VILLARD i2c_error = 1; 238080c646dSJean-Christophe PLAGNIOL-VILLARD } 239080c646dSJean-Christophe PLAGNIOL-VILLARD } else { 240080c646dSJean-Christophe PLAGNIOL-VILLARD i2c_error = 1; 241080c646dSJean-Christophe PLAGNIOL-VILLARD } 242080c646dSJean-Christophe PLAGNIOL-VILLARD 243080c646dSJean-Christophe PLAGNIOL-VILLARD if (!i2c_error) { 244080c646dSJean-Christophe PLAGNIOL-VILLARD int eout = 200; 245080c646dSJean-Christophe PLAGNIOL-VILLARD 246e23c7c95SDirk Behme writew (I2C_CON_EN, I2C_CON); 247e23c7c95SDirk Behme while ((stat = readw (I2C_STAT)) || (readw (I2C_CON) & I2C_CON_MST)) { 248080c646dSJean-Christophe PLAGNIOL-VILLARD udelay (1000); 249080c646dSJean-Christophe PLAGNIOL-VILLARD /* have to read to clear intrrupt */ 250e23c7c95SDirk Behme writew (0xFFFF, I2C_STAT); 251080c646dSJean-Christophe PLAGNIOL-VILLARD if(--eout == 0) /* better leave with error than hang */ 252080c646dSJean-Christophe PLAGNIOL-VILLARD break; 253080c646dSJean-Christophe PLAGNIOL-VILLARD } 254080c646dSJean-Christophe PLAGNIOL-VILLARD } 255080c646dSJean-Christophe PLAGNIOL-VILLARD flush_fifo(); 256e23c7c95SDirk Behme writew (0xFFFF, I2C_STAT); 257e23c7c95SDirk Behme writew (0, I2C_CNT); 258080c646dSJean-Christophe PLAGNIOL-VILLARD return i2c_error; 259080c646dSJean-Christophe PLAGNIOL-VILLARD } 260080c646dSJean-Christophe PLAGNIOL-VILLARD 261080c646dSJean-Christophe PLAGNIOL-VILLARD static void flush_fifo(void) 262080c646dSJean-Christophe PLAGNIOL-VILLARD { u16 stat; 263080c646dSJean-Christophe PLAGNIOL-VILLARD 264080c646dSJean-Christophe PLAGNIOL-VILLARD /* note: if you try and read data when its not there or ready 265080c646dSJean-Christophe PLAGNIOL-VILLARD * you get a bus error 266080c646dSJean-Christophe PLAGNIOL-VILLARD */ 267080c646dSJean-Christophe PLAGNIOL-VILLARD while(1){ 268e23c7c95SDirk Behme stat = readw(I2C_STAT); 269080c646dSJean-Christophe PLAGNIOL-VILLARD if(stat == I2C_STAT_RRDY){ 2707d264c1eSDirk Behme #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) 2717d264c1eSDirk Behme readb(I2C_DATA); 2727d264c1eSDirk Behme #else 273e23c7c95SDirk Behme readw(I2C_DATA); 2747d264c1eSDirk Behme #endif 275e23c7c95SDirk Behme writew(I2C_STAT_RRDY,I2C_STAT); 276080c646dSJean-Christophe PLAGNIOL-VILLARD udelay(1000); 277080c646dSJean-Christophe PLAGNIOL-VILLARD }else 278080c646dSJean-Christophe PLAGNIOL-VILLARD break; 279080c646dSJean-Christophe PLAGNIOL-VILLARD } 280080c646dSJean-Christophe PLAGNIOL-VILLARD } 281080c646dSJean-Christophe PLAGNIOL-VILLARD 282080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_probe (uchar chip) 283080c646dSJean-Christophe PLAGNIOL-VILLARD { 284080c646dSJean-Christophe PLAGNIOL-VILLARD int res = 1; /* default = fail */ 285080c646dSJean-Christophe PLAGNIOL-VILLARD 286e23c7c95SDirk Behme if (chip == readw (I2C_OA)) { 287080c646dSJean-Christophe PLAGNIOL-VILLARD return res; 288080c646dSJean-Christophe PLAGNIOL-VILLARD } 289080c646dSJean-Christophe PLAGNIOL-VILLARD 290080c646dSJean-Christophe PLAGNIOL-VILLARD /* wait until bus not busy */ 291080c646dSJean-Christophe PLAGNIOL-VILLARD wait_for_bb (); 292080c646dSJean-Christophe PLAGNIOL-VILLARD 293080c646dSJean-Christophe PLAGNIOL-VILLARD /* try to read one byte */ 294e23c7c95SDirk Behme writew (1, I2C_CNT); 295080c646dSJean-Christophe PLAGNIOL-VILLARD /* set slave address */ 296e23c7c95SDirk Behme writew (chip, I2C_SA); 297080c646dSJean-Christophe PLAGNIOL-VILLARD /* stop bit needed here */ 298e23c7c95SDirk Behme writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, I2C_CON); 299080c646dSJean-Christophe PLAGNIOL-VILLARD /* enough delay for the NACK bit set */ 300080c646dSJean-Christophe PLAGNIOL-VILLARD udelay (50000); 301080c646dSJean-Christophe PLAGNIOL-VILLARD 302e23c7c95SDirk Behme if (!(readw (I2C_STAT) & I2C_STAT_NACK)) { 303080c646dSJean-Christophe PLAGNIOL-VILLARD res = 0; /* success case */ 304080c646dSJean-Christophe PLAGNIOL-VILLARD flush_fifo(); 305e23c7c95SDirk Behme writew(0xFFFF, I2C_STAT); 306080c646dSJean-Christophe PLAGNIOL-VILLARD } else { 307e23c7c95SDirk Behme writew(0xFFFF, I2C_STAT); /* failue, clear sources*/ 308e23c7c95SDirk Behme writew (readw (I2C_CON) | I2C_CON_STP, I2C_CON); /* finish up xfer */ 309080c646dSJean-Christophe PLAGNIOL-VILLARD udelay(20000); 310080c646dSJean-Christophe PLAGNIOL-VILLARD wait_for_bb (); 311080c646dSJean-Christophe PLAGNIOL-VILLARD } 312080c646dSJean-Christophe PLAGNIOL-VILLARD flush_fifo(); 313e23c7c95SDirk Behme writew (0, I2C_CNT); /* don't allow any more data in...we don't want it.*/ 314e23c7c95SDirk Behme writew(0xFFFF, I2C_STAT); 315080c646dSJean-Christophe PLAGNIOL-VILLARD return res; 316080c646dSJean-Christophe PLAGNIOL-VILLARD } 317080c646dSJean-Christophe PLAGNIOL-VILLARD 318080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len) 319080c646dSJean-Christophe PLAGNIOL-VILLARD { 320080c646dSJean-Christophe PLAGNIOL-VILLARD int i; 321080c646dSJean-Christophe PLAGNIOL-VILLARD 322080c646dSJean-Christophe PLAGNIOL-VILLARD if (alen > 1) { 323080c646dSJean-Christophe PLAGNIOL-VILLARD printf ("I2C read: addr len %d not supported\n", alen); 324080c646dSJean-Christophe PLAGNIOL-VILLARD return 1; 325080c646dSJean-Christophe PLAGNIOL-VILLARD } 326080c646dSJean-Christophe PLAGNIOL-VILLARD 327080c646dSJean-Christophe PLAGNIOL-VILLARD if (addr + len > 256) { 328080c646dSJean-Christophe PLAGNIOL-VILLARD printf ("I2C read: address out of range\n"); 329080c646dSJean-Christophe PLAGNIOL-VILLARD return 1; 330080c646dSJean-Christophe PLAGNIOL-VILLARD } 331080c646dSJean-Christophe PLAGNIOL-VILLARD 332080c646dSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < len; i++) { 333080c646dSJean-Christophe PLAGNIOL-VILLARD if (i2c_read_byte (chip, addr + i, &buffer[i])) { 334080c646dSJean-Christophe PLAGNIOL-VILLARD printf ("I2C read: I/O error\n"); 3356d0f6bcfSJean-Christophe PLAGNIOL-VILLARD i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); 336080c646dSJean-Christophe PLAGNIOL-VILLARD return 1; 337080c646dSJean-Christophe PLAGNIOL-VILLARD } 338080c646dSJean-Christophe PLAGNIOL-VILLARD } 339080c646dSJean-Christophe PLAGNIOL-VILLARD 340080c646dSJean-Christophe PLAGNIOL-VILLARD return 0; 341080c646dSJean-Christophe PLAGNIOL-VILLARD } 342080c646dSJean-Christophe PLAGNIOL-VILLARD 343080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len) 344080c646dSJean-Christophe PLAGNIOL-VILLARD { 345080c646dSJean-Christophe PLAGNIOL-VILLARD int i; 346080c646dSJean-Christophe PLAGNIOL-VILLARD 347080c646dSJean-Christophe PLAGNIOL-VILLARD if (alen > 1) { 348080c646dSJean-Christophe PLAGNIOL-VILLARD printf ("I2C read: addr len %d not supported\n", alen); 349080c646dSJean-Christophe PLAGNIOL-VILLARD return 1; 350080c646dSJean-Christophe PLAGNIOL-VILLARD } 351080c646dSJean-Christophe PLAGNIOL-VILLARD 352080c646dSJean-Christophe PLAGNIOL-VILLARD if (addr + len > 256) { 353080c646dSJean-Christophe PLAGNIOL-VILLARD printf ("I2C read: address out of range\n"); 354080c646dSJean-Christophe PLAGNIOL-VILLARD return 1; 355080c646dSJean-Christophe PLAGNIOL-VILLARD } 356080c646dSJean-Christophe PLAGNIOL-VILLARD 357080c646dSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < len; i++) { 358080c646dSJean-Christophe PLAGNIOL-VILLARD if (i2c_write_byte (chip, addr + i, buffer[i])) { 359080c646dSJean-Christophe PLAGNIOL-VILLARD printf ("I2C read: I/O error\n"); 3606d0f6bcfSJean-Christophe PLAGNIOL-VILLARD i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); 361080c646dSJean-Christophe PLAGNIOL-VILLARD return 1; 362080c646dSJean-Christophe PLAGNIOL-VILLARD } 363080c646dSJean-Christophe PLAGNIOL-VILLARD } 364080c646dSJean-Christophe PLAGNIOL-VILLARD 365080c646dSJean-Christophe PLAGNIOL-VILLARD return 0; 366080c646dSJean-Christophe PLAGNIOL-VILLARD } 367080c646dSJean-Christophe PLAGNIOL-VILLARD 368080c646dSJean-Christophe PLAGNIOL-VILLARD static void wait_for_bb (void) 369080c646dSJean-Christophe PLAGNIOL-VILLARD { 370080c646dSJean-Christophe PLAGNIOL-VILLARD int timeout = 10; 371080c646dSJean-Christophe PLAGNIOL-VILLARD u16 stat; 372080c646dSJean-Christophe PLAGNIOL-VILLARD 373e23c7c95SDirk Behme writew(0xFFFF, I2C_STAT); /* clear current interruts...*/ 374e23c7c95SDirk Behme while ((stat = readw (I2C_STAT) & I2C_STAT_BB) && timeout--) { 375e23c7c95SDirk Behme writew (stat, I2C_STAT); 376080c646dSJean-Christophe PLAGNIOL-VILLARD udelay (50000); 377080c646dSJean-Christophe PLAGNIOL-VILLARD } 378080c646dSJean-Christophe PLAGNIOL-VILLARD 379080c646dSJean-Christophe PLAGNIOL-VILLARD if (timeout <= 0) { 380080c646dSJean-Christophe PLAGNIOL-VILLARD printf ("timed out in wait_for_bb: I2C_STAT=%x\n", 381e23c7c95SDirk Behme readw (I2C_STAT)); 382080c646dSJean-Christophe PLAGNIOL-VILLARD } 383e23c7c95SDirk Behme writew(0xFFFF, I2C_STAT); /* clear delayed stuff*/ 384080c646dSJean-Christophe PLAGNIOL-VILLARD } 385080c646dSJean-Christophe PLAGNIOL-VILLARD 386080c646dSJean-Christophe PLAGNIOL-VILLARD static u16 wait_for_pin (void) 387080c646dSJean-Christophe PLAGNIOL-VILLARD { 388080c646dSJean-Christophe PLAGNIOL-VILLARD u16 status; 389080c646dSJean-Christophe PLAGNIOL-VILLARD int timeout = 10; 390080c646dSJean-Christophe PLAGNIOL-VILLARD 391080c646dSJean-Christophe PLAGNIOL-VILLARD do { 392080c646dSJean-Christophe PLAGNIOL-VILLARD udelay (1000); 393e23c7c95SDirk Behme status = readw (I2C_STAT); 394080c646dSJean-Christophe PLAGNIOL-VILLARD } while ( !(status & 395080c646dSJean-Christophe PLAGNIOL-VILLARD (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY | 396080c646dSJean-Christophe PLAGNIOL-VILLARD I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK | 397080c646dSJean-Christophe PLAGNIOL-VILLARD I2C_STAT_AL)) && timeout--); 398080c646dSJean-Christophe PLAGNIOL-VILLARD 399080c646dSJean-Christophe PLAGNIOL-VILLARD if (timeout <= 0) { 400080c646dSJean-Christophe PLAGNIOL-VILLARD printf ("timed out in wait_for_pin: I2C_STAT=%x\n", 401e23c7c95SDirk Behme readw (I2C_STAT)); 402e23c7c95SDirk Behme writew(0xFFFF, I2C_STAT); 403080c646dSJean-Christophe PLAGNIOL-VILLARD } 404080c646dSJean-Christophe PLAGNIOL-VILLARD return status; 405080c646dSJean-Christophe PLAGNIOL-VILLARD } 406