1*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /* 2*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 2001, 2002 3*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * 5*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * See file CREDITS for list of people who contributed to this 6*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * project. 7*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * 8*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * This program is free software; you can redistribute it and/or 9*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * modify it under the terms of the GNU General Public License as 10*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * published by the Free Software Foundation; either version 2 of 11*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * the License, or (at your option) any later version. 12*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * 13*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * This program is distributed in the hope that it will be useful, 14*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * but WITHOUT ANY WARRANTY; without even the implied warranty of 15*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * GNU General Public License for more details. 17*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * 18*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * You should have received a copy of the GNU General Public License 19*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * along with this program; if not, write to the Free Software 20*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * MA 02111-1307 USA 22*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * 23*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * This has been changed substantially by Gerald Van Baren, Custom IDEAS, 24*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * vanbaren@cideas.com. It was heavily influenced by LiMon, written by 25*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * Neil Russell. 26*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD */ 27*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 28*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #include <common.h> 29*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC8260 /* only valid for MPC8260 */ 30*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #include <ioports.h> 31*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #endif 32*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_AT91RM9200 /* need this for the at91rm9200 */ 33*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #include <asm/io.h> 34*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #include <asm/arch/hardware.h> 35*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #endif 36*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_IXP425 /* only valid for IXP425 */ 37*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #include <asm/arch/ixp425.h> 38*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #endif 39*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_LPC2292 40*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #include <asm/arch/hardware.h> 41*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #endif 42*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #include <i2c.h> 43*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 44*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /* #define DEBUG_I2C */ 45*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 46*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG_I2C 47*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD DECLARE_GLOBAL_DATA_PTR; 48*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #endif 49*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 50*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 51*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 52*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * Definitions 53*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD */ 54*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 55*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #define RETRIES 0 56*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 57*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 58*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #define I2C_ACK 0 /* PD_SDA level to ack a byte */ 59*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #define I2C_NOACK 1 /* PD_SDA level to noack a byte */ 60*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 61*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 62*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG_I2C 63*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #define PRINTD(fmt,args...) do { \ 64*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD if (gd->have_console) \ 65*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD printf (fmt ,##args); \ 66*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } while (0) 67*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #else 68*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #define PRINTD(fmt,args...) 69*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #endif 70*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 71*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 72*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * Local functions 73*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD */ 74*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD static void send_reset (void); 75*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD static void send_start (void); 76*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD static void send_stop (void); 77*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD static void send_ack (int); 78*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD static int write_byte (uchar byte); 79*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD static uchar read_byte (int); 80*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 81*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 82*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 83*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * Send a reset sequence consisting of 9 clocks with the data signal high 84*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * to clock any confused device back into an idle state. Also send a 85*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * <stop> at the end of the sequence for belts & suspenders. 86*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD */ 87*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD static void send_reset(void) 88*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD { 89*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC8260 90*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT); 91*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #endif 92*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_8xx 93*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD volatile immap_t *immr = (immap_t *)CFG_IMMR; 94*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #endif 95*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD int j; 96*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 97*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SCL(1); 98*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SDA(1); 99*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #ifdef I2C_INIT 100*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_INIT; 101*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #endif 102*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_TRISTATE; 103*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD for(j = 0; j < 9; j++) { 104*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SCL(0); 105*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 106*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 107*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SCL(1); 108*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 109*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 110*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 111*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD send_stop(); 112*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_TRISTATE; 113*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 114*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 115*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 116*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * START: High -> Low on SDA while SCL is High 117*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD */ 118*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD static void send_start(void) 119*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD { 120*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC8260 121*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT); 122*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #endif 123*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_8xx 124*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD volatile immap_t *immr = (immap_t *)CFG_IMMR; 125*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #endif 126*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 127*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 128*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SDA(1); 129*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_ACTIVE; 130*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 131*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SCL(1); 132*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 133*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SDA(0); 134*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 135*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 136*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 137*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 138*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * STOP: Low -> High on SDA while SCL is High 139*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD */ 140*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD static void send_stop(void) 141*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD { 142*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC8260 143*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT); 144*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #endif 145*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_8xx 146*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD volatile immap_t *immr = (immap_t *)CFG_IMMR; 147*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #endif 148*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 149*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SCL(0); 150*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 151*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SDA(0); 152*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_ACTIVE; 153*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 154*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SCL(1); 155*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 156*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SDA(1); 157*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 158*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_TRISTATE; 159*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 160*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 161*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 162*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 163*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * ack should be I2C_ACK or I2C_NOACK 164*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD */ 165*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD static void send_ack(int ack) 166*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD { 167*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC8260 168*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT); 169*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #endif 170*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_8xx 171*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD volatile immap_t *immr = (immap_t *)CFG_IMMR; 172*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #endif 173*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 174*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SCL(0); 175*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 176*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_ACTIVE; 177*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SDA(ack); 178*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 179*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SCL(1); 180*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 181*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 182*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SCL(0); 183*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 184*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 185*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 186*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 187*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 188*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * Send 8 bits and look for an acknowledgement. 189*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD */ 190*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD static int write_byte(uchar data) 191*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD { 192*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC8260 193*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT); 194*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #endif 195*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_8xx 196*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD volatile immap_t *immr = (immap_t *)CFG_IMMR; 197*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #endif 198*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD int j; 199*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD int nack; 200*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 201*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_ACTIVE; 202*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD for(j = 0; j < 8; j++) { 203*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SCL(0); 204*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 205*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SDA(data & 0x80); 206*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 207*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SCL(1); 208*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 209*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 210*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 211*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD data <<= 1; 212*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 213*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 214*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /* 215*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * Look for an <ACK>(negative logic) and return it. 216*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD */ 217*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SCL(0); 218*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 219*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SDA(1); 220*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_TRISTATE; 221*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 222*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SCL(1); 223*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 224*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 225*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD nack = I2C_READ; 226*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SCL(0); 227*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 228*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_ACTIVE; 229*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 230*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD return(nack); /* not a nack is an ack */ 231*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 232*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 233*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 234*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 235*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * if ack == I2C_ACK, ACK the byte so can continue reading, else 236*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * send I2C_NOACK to end the read. 237*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD */ 238*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD static uchar read_byte(int ack) 239*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD { 240*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_MPC8260 241*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT); 242*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #endif 243*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_8xx 244*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD volatile immap_t *immr = (immap_t *)CFG_IMMR; 245*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #endif 246*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD int data; 247*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD int j; 248*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 249*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /* 250*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * Read 8 bits, MSB first. 251*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD */ 252*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_TRISTATE; 253*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SDA(1); 254*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD data = 0; 255*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD for(j = 0; j < 8; j++) { 256*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SCL(0); 257*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 258*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_SCL(1); 259*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 260*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD data <<= 1; 261*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD data |= I2C_READ; 262*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD I2C_DELAY; 263*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 264*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD send_ack(ack); 265*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 266*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD return(data); 267*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 268*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 269*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /*=====================================================================*/ 270*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /* Public Functions */ 271*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /*=====================================================================*/ 272*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 273*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 274*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * Initialization 275*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD */ 276*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD void i2c_init (int speed, int slaveaddr) 277*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD { 278*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /* 279*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * WARNING: Do NOT save speed in a static variable: if the 280*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * I2C routines are called before RAM is initialized (to read 281*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * the DIMM SPD, for instance), RAM won't be usable and your 282*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * system will crash. 283*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD */ 284*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD send_reset (); 285*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 286*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 287*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 288*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * Probe to see if a chip is present. Also good for checking for the 289*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * completion of EEPROM writes since the chip stops responding until 290*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * the write completes (typically 10mSec). 291*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD */ 292*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD int i2c_probe(uchar addr) 293*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD { 294*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD int rc; 295*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 296*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /* 297*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * perform 1 byte write transaction with just address byte 298*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * (fake write) 299*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD */ 300*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD send_start(); 301*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD rc = write_byte ((addr << 1) | 0); 302*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD send_stop(); 303*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 304*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD return (rc ? 1 : 0); 305*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 306*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 307*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 308*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * Read bytes 309*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD */ 310*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) 311*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD { 312*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD int shift; 313*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD PRINTD("i2c_read: chip %02X addr %02X alen %d buffer %p len %d\n", 314*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD chip, addr, alen, buffer, len); 315*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 316*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW 317*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /* 318*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * EEPROM chips that implement "address overflow" are ones 319*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * like Catalyst 24WC04/08/16 which has 9/10/11 bits of 320*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * address and the extra bits end up in the "chip address" 321*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * bit slots. This makes a 24WC08 (1Kbyte) chip look like 322*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * four 256 byte chips. 323*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * 324*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * Note that we consider the length of the address field to 325*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * still be one byte because the extra address bits are 326*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * hidden in the chip address. 327*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD */ 328*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW); 329*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 330*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD PRINTD("i2c_read: fix addr_overflow: chip %02X addr %02X\n", 331*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD chip, addr); 332*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD #endif 333*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 334*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /* 335*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * Do the addressing portion of a write cycle to set the 336*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * chip's address pointer. If the address length is zero, 337*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * don't do the normal write cycle to set the address pointer, 338*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * there is no address pointer in this chip. 339*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD */ 340*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD send_start(); 341*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD if(alen > 0) { 342*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD if(write_byte(chip << 1)) { /* write cycle */ 343*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD send_stop(); 344*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD PRINTD("i2c_read, no chip responded %02X\n", chip); 345*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD return(1); 346*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 347*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD shift = (alen-1) * 8; 348*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD while(alen-- > 0) { 349*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD if(write_byte(addr >> shift)) { 350*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD PRINTD("i2c_read, address not <ACK>ed\n"); 351*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD return(1); 352*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 353*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD shift -= 8; 354*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 355*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD send_stop(); /* reportedly some chips need a full stop */ 356*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD send_start(); 357*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 358*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /* 359*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * Send the chip address again, this time for a read cycle. 360*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * Then read the data. On the last byte, we do a NACK instead 361*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * of an ACK(len == 0) to terminate the read. 362*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD */ 363*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD write_byte((chip << 1) | 1); /* read cycle */ 364*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD while(len-- > 0) { 365*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD *buffer++ = read_byte(len == 0); 366*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 367*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD send_stop(); 368*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD return(0); 369*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 370*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 371*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 372*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * Write bytes 373*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD */ 374*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) 375*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD { 376*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD int shift, failures = 0; 377*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 378*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD PRINTD("i2c_write: chip %02X addr %02X alen %d buffer %p len %d\n", 379*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD chip, addr, alen, buffer, len); 380*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 381*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD send_start(); 382*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD if(write_byte(chip << 1)) { /* write cycle */ 383*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD send_stop(); 384*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD PRINTD("i2c_write, no chip responded %02X\n", chip); 385*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD return(1); 386*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 387*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD shift = (alen-1) * 8; 388*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD while(alen-- > 0) { 389*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD if(write_byte(addr >> shift)) { 390*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD PRINTD("i2c_write, address not <ACK>ed\n"); 391*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD return(1); 392*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 393*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD shift -= 8; 394*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 395*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 396*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD while(len-- > 0) { 397*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD if(write_byte(*buffer++)) { 398*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD failures++; 399*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 400*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 401*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD send_stop(); 402*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD return(failures); 403*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 404*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 405*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 406*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * Read a register 407*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD */ 408*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD uchar i2c_reg_read(uchar i2c_addr, uchar reg) 409*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD { 410*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD uchar buf; 411*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 412*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD i2c_read(i2c_addr, reg, 1, &buf, 1); 413*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 414*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD return(buf); 415*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 416*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD 417*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 418*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD * Write a register 419*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD */ 420*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD void i2c_reg_write(uchar i2c_addr, uchar reg, uchar val) 421*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD { 422*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD i2c_write(i2c_addr, reg, 1, &val, 1); 423*4d75e0aaSJean-Christophe PLAGNIOL-VILLARD } 424