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