blob: 113ca70a1ac81929364cd3de658241a960fbc0e1 [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>
11#include "../common/common.h"
12
13static void i2c_write_start_seq(void)
14{
mario.six@gdsys.ccec2c81c2016-04-25 08:31:01 +020015 struct fsl_i2c_base *base;
16 base = (struct fsl_i2c_base *)(CONFIG_SYS_IMMR +
17 CONFIG_SYS_I2C_OFFSET);
Holger Bruncke792aff2011-09-14 10:54:12 +020018 udelay(DELAY_ABORT_SEQ);
mario.six@gdsys.ccec2c81c2016-04-25 08:31:01 +020019 out_8(&base->cr, (I2C_CR_MEN | I2C_CR_MSTA));
Holger Bruncke792aff2011-09-14 10:54:12 +020020 udelay(DELAY_ABORT_SEQ);
mario.six@gdsys.ccec2c81c2016-04-25 08:31:01 +020021 out_8(&base->cr, (I2C_CR_MEN));
Holger Bruncke792aff2011-09-14 10:54:12 +020022}
23
24int i2c_make_abort(void)
25{
mario.six@gdsys.ccec2c81c2016-04-25 08:31:01 +020026 struct fsl_i2c_base *base;
27 base = (struct fsl_i2c_base *)(CONFIG_SYS_IMMR +
28 CONFIG_SYS_I2C_OFFSET);
Holger Bruncke792aff2011-09-14 10:54:12 +020029 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 */
mario.six@gdsys.ccec2c81c2016-04-25 08:31:01 +020035 out_8(&base->cr, (I2C_CR_MSTA));
Holger Bruncke792aff2011-09-14 10:54:12 +020036 udelay(DELAY_ABORT_SEQ);
mario.six@gdsys.ccec2c81c2016-04-25 08:31:01 +020037 out_8(&base->cr, (I2C_CR_MEN | I2C_CR_MSTA));
Holger Bruncke792aff2011-09-14 10:54:12 +020038 udelay(DELAY_ABORT_SEQ);
mario.six@gdsys.ccec2c81c2016-04-25 08:31:01 +020039 in_8(&base->dr);
Holger Bruncke792aff2011-09-14 10:54:12 +020040 udelay(DELAY_ABORT_SEQ);
mario.six@gdsys.ccec2c81c2016-04-25 08:31:01 +020041 last = in_8(&base->dr);
Holger Bruncke792aff2011-09-14 10:54:12 +020042 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);
mario.six@gdsys.ccec2c81c2016-04-25 08:31:01 +020051 last = in_8(&base->dr);
Holger Bruncke792aff2011-09-14 10:54:12 +020052 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);
mario.six@gdsys.ccec2c81c2016-04-25 08:31:01 +020060 out_8(&base->cr, (I2C_CR_MEN));
Holger Bruncke792aff2011-09-14 10:54:12 +020061 udelay(DELAY_ABORT_SEQ);
62 /* clear status reg */
mario.six@gdsys.ccec2c81c2016-04-25 08:31:01 +020063 out_8(&base->sr, 0);
Holger Bruncke792aff2011-09-14 10:54:12 +020064
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}