]> git.ipfire.org Git - people/ms/u-boot.git/blob - board/keymile/km_arm/fpga_config.c
arm/km: skip FPGA config when already configured
[people/ms/u-boot.git] / board / keymile / km_arm / fpga_config.c
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()
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 BRIDGE_RST 0x4
210
211 int fpga_reset(void)
212 {
213 int ret = 0;
214
215 if (!check_boco2()) {
216 /* we do not have BOCO2, this is not really used */
217 return 0;
218 }
219
220 ret = boco_clear_bits(PRST1, BRIDGE_RST);
221 if (ret)
222 return ret;
223
224 /* small delay for the pulse */
225 udelay(10);
226
227 ret = boco_set_bits(PRST1, BRIDGE_RST);
228 if (ret)
229 return ret;
230
231 return 0;
232 }
233
234 /* the FPGA was configured, we configure the BOCO2 so that the EEPROM
235 * is available from the Bobcat SPI bus */
236 int toggle_eeprom_spi_bus(void)
237 {
238 int ret = 0;
239
240 if (!check_boco2()) {
241 /* we do not have BOCO2, this is not really used */
242 return 0;
243 }
244
245 ret = boco_set_bits(SPI_REG, CFG_EEPROM);
246 if (ret)
247 return ret;
248
249 return 0;
250 }
251