blob: 0f57015a5e52079a40a245607aca818a134f9681 [file] [log] [blame]
Heiko Schocher5e51b482008-10-15 09:39:08 +02001/*
2 * (C) Copyright 2008
3 * Heiko Schocher, DENX Software Engineering, hs@denx.de.
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 */
23
24#include <common.h>
25#include <mpc8260.h>
26#include <ioports.h>
27#include <malloc.h>
28
29#if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT)
30#include <libfdt.h>
31#endif
32
33#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
34#include <i2c.h>
35#endif
36
37extern int i2c_soft_read_pin (void);
38
39#if defined(CFG_I2C_INIT_BOARD)
40#define DELAY_ABORT_SEQ 62
41#define DELAY_HALF_PERIOD (500 / (CFG_I2C_SPEED / 1000))
42
43#if defined(CONFIG_MGCOGE)
44#define SDA_MASK 0x00010000
45#define SCL_MASK 0x00020000
46static void set_pin (int state, unsigned long mask)
47{
48 volatile ioport_t *iop = ioport_addr ((immap_t *)CFG_IMMR, 3);
49
50 if (state)
51 iop->pdat |= (mask);
52 else
53 iop->pdat &= ~(mask);
54
55 iop->pdir |= (mask);
56}
57
58static int get_pin (unsigned long mask)
59{
60 volatile ioport_t *iop = ioport_addr ((immap_t *)CFG_IMMR, 3);
61
62 iop->pdir &= ~(mask);
63 return (0 != (iop->pdat & (mask)));
64}
65
66static void set_sda (int state)
67{
68 set_pin (state, SDA_MASK);
69}
70
71static void set_scl (int state)
72{
73 set_pin (state, SCL_MASK);
74}
75
76static int get_sda (void)
77{
78 return get_pin (SDA_MASK);
79}
80
81static int get_scl (void)
82{
83 return get_pin (SCL_MASK);
84}
85
86#if defined(CONFIG_HARD_I2C)
87static void setports (int gpio)
88{
89 volatile ioport_t *iop = ioport_addr ((immap_t *)CFG_IMMR, 3);
90
91 if (gpio) {
92 iop->ppar &= ~(SDA_MASK | SCL_MASK);
93 iop->podr &= ~(SDA_MASK | SCL_MASK);
94 } else {
95 iop->ppar |= (SDA_MASK | SCL_MASK);
96 iop->pdir &= ~(SDA_MASK | SCL_MASK);
97 iop->podr |= (SDA_MASK | SCL_MASK);
98 }
99}
100#endif
101#endif
102
103#if defined(CONFIG_MGSUVD)
104static void set_sda (int state)
105{
106 I2C_SDA(state);
107}
108
109static void set_scl (int state)
110{
111 I2C_SCL(state);
112}
113
114static int get_sda (void)
115{
116 return i2c_soft_read_pin ();
117}
118
119static int get_scl (void)
120{
121 int val;
122
123 *(unsigned short *)(I2C_BASE_DIR) &= ~SCL_CONF;
124 udelay (1);
125 val = *(unsigned char *)(I2C_BASE_PORT);
126
127 return ((val & SCL_BIT) == SCL_BIT);
128}
129
130#endif
131
132static void writeStartSeq (void)
133{
134 set_sda (1);
135 udelay (DELAY_HALF_PERIOD);
136 set_scl (1);
137 udelay (DELAY_HALF_PERIOD);
138 set_sda (0);
139 udelay (DELAY_HALF_PERIOD);
140 set_scl (0);
141 udelay (DELAY_HALF_PERIOD);
142}
143
144/* I2C is a synchronous protocol and resets of the processor in the middle
145 of an access can block the I2C Bus until a powerdown of the full unit is
146 done. This function toggles the SCL until the SCL and SCA line are
147 released, but max. 16 times, after this a I2C start-sequence is sent.
148 This I2C Deblocking mechanism was developed by Keymile in association
149 with Anatech and Atmel in 1998.
150 */
151static int i2c_make_abort (void)
152{
153 int scl_state = 0;
154 int sda_state = 0;
155 int i = 0;
156 int ret = 0;
157
158 if (!get_sda ()) {
159 ret = -1;
160 while (i < 16) {
161 i++;
162 set_scl (0);
163 udelay (DELAY_ABORT_SEQ);
164 set_scl (1);
165 udelay (DELAY_ABORT_SEQ);
166 scl_state = get_scl ();
167 sda_state = get_sda ();
168 if (scl_state && sda_state) {
169 ret = 0;
170 break;
171 }
172 }
173 }
174 if (ret == 0) {
175 for (i =0; i < 5; i++) {
176 writeStartSeq ();
177 }
178 }
179 get_sda ();
180 return ret;
181}
182
183/**
184 * i2c_init_board - reset i2c bus. When the board is powercycled during a
185 * bus transfer it might hang; for details see doc/I2C_Edge_Conditions.
186 */
187void i2c_init_board(void)
188{
189#if defined(CONFIG_HARD_I2C)
190 volatile immap_t *immap = (immap_t *)CFG_IMMR ;
191 volatile i2c8260_t *i2c = (i2c8260_t *)&immap->im_i2c;
192
193 /* disable I2C controller first, otherwhise it thinks we want to */
194 /* talk to the slave port... */
195 i2c->i2c_i2mod &= ~0x01;
196
197 /* Set the PortPins to GPIO */
198 setports (1);
199#endif
200
201 /* Now run the AbortSequence() */
202 i2c_make_abort ();
203
204#if defined(CONFIG_HARD_I2C)
205 /* Set the PortPins back to use for I2C */
206 setports (0);
207#endif
208}
209#endif