xref: /rk3399_rockchip-uboot/board/keymile/common/common.c (revision c24853644ddd2dd2e4246b5854a93e6254a14092)
1 /*
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 
37 extern 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
46 static 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 
58 static 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 
66 static void set_sda (int state)
67 {
68 	set_pin (state, SDA_MASK);
69 }
70 
71 static void set_scl (int state)
72 {
73 	set_pin (state, SCL_MASK);
74 }
75 
76 static int get_sda (void)
77 {
78 	return get_pin (SDA_MASK);
79 }
80 
81 static int get_scl (void)
82 {
83 	return get_pin (SCL_MASK);
84 }
85 
86 #if defined(CONFIG_HARD_I2C)
87 static 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)
104 static void set_sda (int state)
105 {
106 	I2C_SDA(state);
107 }
108 
109 static void set_scl (int state)
110 {
111 	I2C_SCL(state);
112 }
113 
114 static int get_sda (void)
115 {
116 	return i2c_soft_read_pin ();
117 }
118 
119 static 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 
132 static 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  */
151 static 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  */
187 void 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
210