113ca70a1ac81929364cd3de658241a960fbc0e1
[oweals/u-boot.git] / board / keymile / km83xx / km83xx_i2c.c
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 }