blob: 62100b19492d017940920aee4c670d7e6886e3d3 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Holger Bruncke792aff2011-09-14 10:54:12 +02002/*
3 * (C) Copyright 2011
4 * Holger Brunck, Keymile GmbH Hannover, holger.brunck@keymile.com
Holger Bruncke792aff2011-09-14 10:54:12 +02005 */
6
7#include <common.h>
8#include <i2c.h>
9#include <asm/io.h>
10#include <linux/ctype.h>
Simon Glassc05ed002020-05-10 11:40:11 -060011#include <linux/delay.h>
Holger Bruncke792aff2011-09-14 10:54:12 +020012#include "../common/common.h"
13
14static void i2c_write_start_seq(void)
15{
mario.six@gdsys.ccec2c81c2016-04-25 08:31:01 +020016 struct fsl_i2c_base *base;
17 base = (struct fsl_i2c_base *)(CONFIG_SYS_IMMR +
18 CONFIG_SYS_I2C_OFFSET);
Holger Bruncke792aff2011-09-14 10:54:12 +020019 udelay(DELAY_ABORT_SEQ);
mario.six@gdsys.ccec2c81c2016-04-25 08:31:01 +020020 out_8(&base->cr, (I2C_CR_MEN | I2C_CR_MSTA));
Holger Bruncke792aff2011-09-14 10:54:12 +020021 udelay(DELAY_ABORT_SEQ);
mario.six@gdsys.ccec2c81c2016-04-25 08:31:01 +020022 out_8(&base->cr, (I2C_CR_MEN));
Holger Bruncke792aff2011-09-14 10:54:12 +020023}
24
25int i2c_make_abort(void)
26{
mario.six@gdsys.ccec2c81c2016-04-25 08:31:01 +020027 struct fsl_i2c_base *base;
28 base = (struct fsl_i2c_base *)(CONFIG_SYS_IMMR +
29 CONFIG_SYS_I2C_OFFSET);
Holger Bruncke792aff2011-09-14 10:54:12 +020030 uchar last;
31 int nbr_read = 0;
32 int i = 0;
33 int ret = 0;
34
35 /* wait after each operation to finsh with a delay */
mario.six@gdsys.ccec2c81c2016-04-25 08:31:01 +020036 out_8(&base->cr, (I2C_CR_MSTA));
Holger Bruncke792aff2011-09-14 10:54:12 +020037 udelay(DELAY_ABORT_SEQ);
mario.six@gdsys.ccec2c81c2016-04-25 08:31:01 +020038 out_8(&base->cr, (I2C_CR_MEN | I2C_CR_MSTA));
Holger Bruncke792aff2011-09-14 10:54:12 +020039 udelay(DELAY_ABORT_SEQ);
mario.six@gdsys.ccec2c81c2016-04-25 08:31:01 +020040 in_8(&base->dr);
Holger Bruncke792aff2011-09-14 10:54:12 +020041 udelay(DELAY_ABORT_SEQ);
mario.six@gdsys.ccec2c81c2016-04-25 08:31:01 +020042 last = in_8(&base->dr);
Holger Bruncke792aff2011-09-14 10:54:12 +020043 nbr_read++;
44
45 /*
46 * do read until the last bit is 1, but stop if the full eeprom is
47 * read.
48 */
49 while (((last & 0x01) != 0x01) &&
50 (nbr_read < CONFIG_SYS_IVM_EEPROM_MAX_LEN)) {
51 udelay(DELAY_ABORT_SEQ);
mario.six@gdsys.ccec2c81c2016-04-25 08:31:01 +020052 last = in_8(&base->dr);
Holger Bruncke792aff2011-09-14 10:54:12 +020053 nbr_read++;
54 }
55 if ((last & 0x01) != 0x01)
56 ret = -2;
57 if ((last != 0xff) || (nbr_read > 1))
58 printf("[INFO] i2c abort after %d bytes (0x%02x)\n",
59 nbr_read, last);
60 udelay(DELAY_ABORT_SEQ);
mario.six@gdsys.ccec2c81c2016-04-25 08:31:01 +020061 out_8(&base->cr, (I2C_CR_MEN));
Holger Bruncke792aff2011-09-14 10:54:12 +020062 udelay(DELAY_ABORT_SEQ);
63 /* clear status reg */
mario.six@gdsys.ccec2c81c2016-04-25 08:31:01 +020064 out_8(&base->sr, 0);
Holger Bruncke792aff2011-09-14 10:54:12 +020065
66 for (i = 0; i < 5; i++)
67 i2c_write_start_seq();
68 if (ret != 0)
69 printf("[ERROR] i2c abort failed after %d bytes (0x%02x)\n",
70 nbr_read, last);
71
72 return ret;
73}