1 /*
2  * (C) Copyright 2012
3  * Valentin Lontgchamp, Keymile AG, valentin.longchamp@keymile.com
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., 51 Franklin Street, Fifth Floor, Boston,
21  * MA 02110-1301 USA
22  */
23 
24 #include <common.h>
25 #include <i2c.h>
26 #include <asm/errno.h>
27 
28 /* GPIO Pin from kirkwood connected to PROGRAM_B pin of the xilinx FPGA */
29 #define KM_XLX_PROGRAM_B_PIN    39
30 
31 #define BOCO_ADDR	0x10
32 
33 #define ID_REG		0x00
34 #define BOCO2_ID	0x5b
35 
36 static int check_boco2(void)
37 {
38 	int ret;
39 	u8 id;
40 
41 	ret = i2c_read(BOCO_ADDR, ID_REG, 1, &id, 1);
42 	if (ret) {
43 		printf("%s: error reading the BOCO id !!\n", __func__);
44 		return ret;
45 	}
46 
47 	return (id == BOCO2_ID);
48 }
49 
50 static int boco_clear_bits(u8 reg, u8 flags)
51 {
52 	int ret;
53 	u8 regval;
54 
55 	/* give access to the EEPROM from FPGA */
56 	ret = i2c_read(BOCO_ADDR, reg, 1, &regval, 1);
57 	if (ret) {
58 		printf("%s: error reading the BOCO @%#x !!\n",
59 			__func__, reg);
60 		return ret;
61 	}
62 	regval &= ~flags;
63 	ret = i2c_write(BOCO_ADDR, reg, 1, &regval, 1);
64 	if (ret) {
65 		printf("%s: error writing the BOCO @%#x !!\n",
66 			__func__, reg);
67 		return ret;
68 	}
69 
70 	return 0;
71 }
72 
73 static int boco_set_bits(u8 reg, u8 flags)
74 {
75 	int ret;
76 	u8 regval;
77 
78 	/* give access to the EEPROM from FPGA */
79 	ret = i2c_read(BOCO_ADDR, reg, 1, &regval, 1);
80 	if (ret) {
81 		printf("%s: error reading the BOCO @%#x !!\n",
82 			__func__, reg);
83 		return ret;
84 	}
85 	regval |= flags;
86 	ret = i2c_write(BOCO_ADDR, reg, 1, &regval, 1);
87 	if (ret) {
88 		printf("%s: error writing the BOCO @%#x !!\n",
89 			__func__, reg);
90 		return ret;
91 	}
92 
93 	return 0;
94 }
95 
96 #define SPI_REG		0x06
97 #define CFG_EEPROM	0x02
98 #define FPGA_PROG	0x04
99 #define FPGA_INIT_B	0x10
100 #define FPGA_DONE	0x20
101 
102 static int fpga_done(void)
103 {
104 	int ret = 0;
105 	u8 regval;
106 
107 	/* this is only supported with the boco2 design */
108 	if (!check_boco2())
109 		return 0;
110 
111 	ret = i2c_read(BOCO_ADDR, SPI_REG, 1, &regval, 1);
112 	if (ret) {
113 		printf("%s: error reading the BOCO @%#x !!\n",
114 			__func__, SPI_REG);
115 		return 0;
116 	}
117 
118 	return regval & FPGA_DONE ? 1 : 0;
119 }
120 
121 int skip;
122 
123 int trigger_fpga_config(void)
124 {
125 	int ret = 0;
126 
127 	/* if the FPGA is already configured, we do not want to
128 	 * reconfigure it */
129 	skip = 0;
130 	if (fpga_done()) {
131 		printf("PCIe FPGA config: skipped\n");
132 		skip = 1;
133 		return 0;
134 	}
135 
136 	if (check_boco2()) {
137 		/* we have a BOCO2, this has to be triggered here */
138 
139 		/* make sure the FPGA_can access the EEPROM */
140 		ret = boco_clear_bits(SPI_REG, CFG_EEPROM);
141 		if (ret)
142 			return ret;
143 
144 		/* trigger the config start */
145 		ret = boco_clear_bits(SPI_REG, FPGA_PROG | FPGA_INIT_B);
146 		if (ret)
147 			return ret;
148 
149 		/* small delay for the pulse */
150 		udelay(10);
151 
152 		/* up signal for pulse end */
153 		ret = boco_set_bits(SPI_REG, FPGA_PROG);
154 		if (ret)
155 			return ret;
156 
157 		/* finally, raise INIT_B to remove the config delay */
158 		ret = boco_set_bits(SPI_REG, FPGA_INIT_B);
159 		if (ret)
160 			return ret;
161 
162 	} else {
163 		/* we do it the old way, with the gpio pin */
164 		kw_gpio_set_valid(KM_XLX_PROGRAM_B_PIN, 1);
165 		kw_gpio_direction_output(KM_XLX_PROGRAM_B_PIN, 0);
166 		/* small delay for the pulse */
167 		udelay(10);
168 		kw_gpio_direction_input(KM_XLX_PROGRAM_B_PIN);
169 	}
170 
171 	return 0;
172 }
173 
174 int wait_for_fpga_config(void)
175 {
176 	int ret = 0;
177 	u8 spictrl;
178 	u32 timeout = 20000;
179 
180 	if (skip)
181 		return 0;
182 
183 	if (!check_boco2()) {
184 		/* we do not have BOCO2, this is not really used */
185 		return 0;
186 	}
187 
188 	printf("PCIe FPGA config:");
189 	do {
190 		ret = i2c_read(BOCO_ADDR, SPI_REG, 1, &spictrl, 1);
191 		if (ret) {
192 			printf("%s: error reading the BOCO spictrl !!\n",
193 				__func__);
194 			return ret;
195 		}
196 		if (timeout-- == 0) {
197 			printf(" FPGA_DONE timeout\n");
198 			return -EFAULT;
199 		}
200 		udelay(10);
201 	} while (!(spictrl & FPGA_DONE));
202 
203 	printf(" done\n");
204 
205 	return 0;
206 }
207 
208 #define PRST1		0x4
209 #define PCIE_RST	0x10
210 #define TRAFFIC_RST	0x04
211 
212 int fpga_reset(void)
213 {
214 	int ret = 0;
215 	u8 resets;
216 
217 	if (!check_boco2()) {
218 		/* we do not have BOCO2, this is not really used */
219 		return 0;
220 	}
221 
222 	/* if we have skipped, we only want to reset the PCIe part */
223 	resets = skip ? PCIE_RST : PCIE_RST | TRAFFIC_RST;
224 
225 	ret = boco_clear_bits(PRST1, resets);
226 	if (ret)
227 		return ret;
228 
229 	/* small delay for the pulse */
230 	udelay(10);
231 
232 	ret = boco_set_bits(PRST1, resets);
233 	if (ret)
234 		return ret;
235 
236 	return 0;
237 }
238 
239 /* the FPGA was configured, we configure the BOCO2 so that the EEPROM
240  * is available from the Bobcat SPI bus */
241 int toggle_eeprom_spi_bus(void)
242 {
243 	int ret = 0;
244 
245 	if (!check_boco2()) {
246 		/* we do not have BOCO2, this is not really used */
247 		return 0;
248 	}
249 
250 	ret = boco_set_bits(SPI_REG, CFG_EEPROM);
251 	if (ret)
252 		return ret;
253 
254 	return 0;
255 }
256