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