1e792affeSHolger Brunck /* 2e792affeSHolger Brunck * (C) Copyright 2011 3e792affeSHolger Brunck * Holger Brunck, Keymile GmbH Hannover, holger.brunck@keymile.com 4e792affeSHolger Brunck * 51a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 6e792affeSHolger Brunck */ 7e792affeSHolger Brunck 8e792affeSHolger Brunck #include <common.h> 9e792affeSHolger Brunck #include <i2c.h> 10e792affeSHolger Brunck #include <asm/io.h> 11e792affeSHolger Brunck #include <linux/ctype.h> 12e792affeSHolger Brunck #include "../common/common.h" 13e792affeSHolger Brunck 14e792affeSHolger Brunck static void i2c_write_start_seq(void) 15e792affeSHolger Brunck { 16*ec2c81c5Smario.six@gdsys.cc struct fsl_i2c_base *base; 17*ec2c81c5Smario.six@gdsys.cc base = (struct fsl_i2c_base *)(CONFIG_SYS_IMMR + 18*ec2c81c5Smario.six@gdsys.cc CONFIG_SYS_I2C_OFFSET); 19e792affeSHolger Brunck udelay(DELAY_ABORT_SEQ); 20*ec2c81c5Smario.six@gdsys.cc out_8(&base->cr, (I2C_CR_MEN | I2C_CR_MSTA)); 21e792affeSHolger Brunck udelay(DELAY_ABORT_SEQ); 22*ec2c81c5Smario.six@gdsys.cc out_8(&base->cr, (I2C_CR_MEN)); 23e792affeSHolger Brunck } 24e792affeSHolger Brunck 25e792affeSHolger Brunck int i2c_make_abort(void) 26e792affeSHolger Brunck { 27*ec2c81c5Smario.six@gdsys.cc struct fsl_i2c_base *base; 28*ec2c81c5Smario.six@gdsys.cc base = (struct fsl_i2c_base *)(CONFIG_SYS_IMMR + 29*ec2c81c5Smario.six@gdsys.cc CONFIG_SYS_I2C_OFFSET); 30e792affeSHolger Brunck uchar last; 31e792affeSHolger Brunck int nbr_read = 0; 32e792affeSHolger Brunck int i = 0; 33e792affeSHolger Brunck int ret = 0; 34e792affeSHolger Brunck 35e792affeSHolger Brunck /* wait after each operation to finsh with a delay */ 36*ec2c81c5Smario.six@gdsys.cc out_8(&base->cr, (I2C_CR_MSTA)); 37e792affeSHolger Brunck udelay(DELAY_ABORT_SEQ); 38*ec2c81c5Smario.six@gdsys.cc out_8(&base->cr, (I2C_CR_MEN | I2C_CR_MSTA)); 39e792affeSHolger Brunck udelay(DELAY_ABORT_SEQ); 40*ec2c81c5Smario.six@gdsys.cc in_8(&base->dr); 41e792affeSHolger Brunck udelay(DELAY_ABORT_SEQ); 42*ec2c81c5Smario.six@gdsys.cc last = in_8(&base->dr); 43e792affeSHolger Brunck nbr_read++; 44e792affeSHolger Brunck 45e792affeSHolger Brunck /* 46e792affeSHolger Brunck * do read until the last bit is 1, but stop if the full eeprom is 47e792affeSHolger Brunck * read. 48e792affeSHolger Brunck */ 49e792affeSHolger Brunck while (((last & 0x01) != 0x01) && 50e792affeSHolger Brunck (nbr_read < CONFIG_SYS_IVM_EEPROM_MAX_LEN)) { 51e792affeSHolger Brunck udelay(DELAY_ABORT_SEQ); 52*ec2c81c5Smario.six@gdsys.cc last = in_8(&base->dr); 53e792affeSHolger Brunck nbr_read++; 54e792affeSHolger Brunck } 55e792affeSHolger Brunck if ((last & 0x01) != 0x01) 56e792affeSHolger Brunck ret = -2; 57e792affeSHolger Brunck if ((last != 0xff) || (nbr_read > 1)) 58e792affeSHolger Brunck printf("[INFO] i2c abort after %d bytes (0x%02x)\n", 59e792affeSHolger Brunck nbr_read, last); 60e792affeSHolger Brunck udelay(DELAY_ABORT_SEQ); 61*ec2c81c5Smario.six@gdsys.cc out_8(&base->cr, (I2C_CR_MEN)); 62e792affeSHolger Brunck udelay(DELAY_ABORT_SEQ); 63e792affeSHolger Brunck /* clear status reg */ 64*ec2c81c5Smario.six@gdsys.cc out_8(&base->sr, 0); 65e792affeSHolger Brunck 66e792affeSHolger Brunck for (i = 0; i < 5; i++) 67e792affeSHolger Brunck i2c_write_start_seq(); 68e792affeSHolger Brunck if (ret != 0) 69e792affeSHolger Brunck printf("[ERROR] i2c abort failed after %d bytes (0x%02x)\n", 70e792affeSHolger Brunck nbr_read, last); 71e792affeSHolger Brunck 72e792affeSHolger Brunck return ret; 73e792affeSHolger Brunck } 74