]> git.sur5r.net Git - u-boot/blob - board/keymile/km_arm/fpga_config.c
arm/km: enable BOCO2 FPGA download support
[u-boot] / 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_DONE       0x20
100
101 int trigger_fpga_config(void)
102 {
103         int ret = 0;
104
105         if (check_boco2()) {
106                 /* we have a BOCO2, this has to be triggered here */
107
108                 /* make sure the FPGA_can access the EEPROM */
109                 ret = boco_clear_bits(SPI_REG, CFG_EEPROM);
110                 if (ret)
111                         return ret;
112
113                 /* trigger the config start */
114                 ret = boco_clear_bits(SPI_REG, FPGA_PROG);
115                 if (ret)
116                         return ret;
117
118                 /* small delay for the pulse */
119                 udelay(10);
120
121                 /* up signal for pulse end */
122                 ret = boco_set_bits(SPI_REG, FPGA_PROG);
123                 if (ret)
124                         return ret;
125
126         } else {
127                 /* we do it the old way, with the gpio pin */
128                 kw_gpio_set_valid(KM_XLX_PROGRAM_B_PIN, 1);
129                 kw_gpio_direction_output(KM_XLX_PROGRAM_B_PIN, 0);
130                 /* small delay for the pulse */
131                 udelay(10);
132                 kw_gpio_direction_input(KM_XLX_PROGRAM_B_PIN);
133         }
134
135         return 0;
136 }
137
138 int wait_for_fpga_config(void)
139 {
140         int ret = 0;
141         u8 spictrl;
142         u32 timeout = 20000;
143
144         if (!check_boco2()) {
145                 /* we do not have BOCO2, this is not really used */
146                 return 0;
147         }
148
149         printf("PCIe FPGA config:");
150         do {
151                 ret = i2c_read(BOCO_ADDR, SPI_REG, 1, &spictrl, 1);
152                 if (ret) {
153                         printf("%s: error reading the BOCO spictrl !!\n",
154                                 __func__);
155                         return ret;
156                 }
157                 if (timeout-- == 0) {
158                         printf(" FPGA_DONE timeout\n");
159                         return -EFAULT;
160                 }
161                 udelay(10);
162         } while (!(spictrl & FPGA_DONE));
163
164         printf(" done\n");
165
166         return 0;
167 }
168
169 #define PRST1           0x4
170 #define BRIDGE_RST      0x4
171
172 int fpga_reset(void)
173 {
174         int ret = 0;
175
176         if (!check_boco2()) {
177                 /* we do not have BOCO2, this is not really used */
178                 return 0;
179         }
180
181         ret = boco_clear_bits(PRST1, BRIDGE_RST);
182         if (ret)
183                 return ret;
184
185         /* small delay for the pulse */
186         udelay(10);
187
188         ret = boco_set_bits(PRST1, BRIDGE_RST);
189         if (ret)
190                 return ret;
191
192         return 0;
193 }
194
195 /* the FPGA was configured, we configure the BOCO2 so that the EEPROM
196  * is available from the Bobcat SPI bus */
197 int toggle_eeprom_spi_bus(void)
198 {
199         int ret = 0;
200
201         if (!check_boco2()) {
202                 /* we do not have BOCO2, this is not really used */
203                 return 0;
204         }
205
206         ret = boco_set_bits(SPI_REG, CFG_EEPROM);
207         if (ret)
208                 return ret;
209
210         return 0;
211 }
212