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