SPDX: Convert all of our single license tags to Linux Kernel style
[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 static int fpga_done(void)
86 {
87         int ret = 0;
88         u8 regval;
89
90         /* this is only supported with the boco2 design */
91         if (!check_boco2())
92                 return 0;
93
94         ret = i2c_read(BOCO_ADDR, SPI_REG, 1, &regval, 1);
95         if (ret) {
96                 printf("%s: error reading the BOCO @%#x !!\n",
97                         __func__, SPI_REG);
98                 return 0;
99         }
100
101         return regval & FPGA_DONE ? 1 : 0;
102 }
103
104 int skip;
105
106 int trigger_fpga_config(void)
107 {
108         int ret = 0;
109
110         /* if the FPGA is already configured, we do not want to
111          * reconfigure it */
112         skip = 0;
113         if (fpga_done()) {
114                 printf("PCIe FPGA config: skipped\n");
115                 skip = 1;
116                 return 0;
117         }
118
119         if (check_boco2()) {
120                 /* we have a BOCO2, this has to be triggered here */
121
122                 /* make sure the FPGA_can access the EEPROM */
123                 ret = boco_clear_bits(SPI_REG, CFG_EEPROM);
124                 if (ret)
125                         return ret;
126
127                 /* trigger the config start */
128                 ret = boco_clear_bits(SPI_REG, FPGA_PROG | FPGA_INIT_B);
129                 if (ret)
130                         return ret;
131
132                 /* small delay for the pulse */
133                 udelay(10);
134
135                 /* up signal for pulse end */
136                 ret = boco_set_bits(SPI_REG, FPGA_PROG);
137                 if (ret)
138                         return ret;
139
140                 /* finally, raise INIT_B to remove the config delay */
141                 ret = boco_set_bits(SPI_REG, FPGA_INIT_B);
142                 if (ret)
143                         return ret;
144
145         } else {
146                 /* we do it the old way, with the gpio pin */
147                 kw_gpio_set_valid(KM_XLX_PROGRAM_B_PIN, 1);
148                 kw_gpio_direction_output(KM_XLX_PROGRAM_B_PIN, 0);
149                 /* small delay for the pulse */
150                 udelay(10);
151                 kw_gpio_direction_input(KM_XLX_PROGRAM_B_PIN);
152         }
153
154         return 0;
155 }
156
157 int wait_for_fpga_config(void)
158 {
159         int ret = 0;
160         u8 spictrl;
161         u32 timeout = 20000;
162
163         if (skip)
164                 return 0;
165
166         if (!check_boco2()) {
167                 /* we do not have BOCO2, this is not really used */
168                 return 0;
169         }
170
171         printf("PCIe FPGA config:");
172         do {
173                 ret = i2c_read(BOCO_ADDR, SPI_REG, 1, &spictrl, 1);
174                 if (ret) {
175                         printf("%s: error reading the BOCO spictrl !!\n",
176                                 __func__);
177                         return ret;
178                 }
179                 if (timeout-- == 0) {
180                         printf(" FPGA_DONE timeout\n");
181                         return -EFAULT;
182                 }
183                 udelay(10);
184         } while (!(spictrl & FPGA_DONE));
185
186         printf(" done\n");
187
188         return 0;
189 }
190
191 #if defined(KM_PCIE_RESET_MPP7)
192
193 #define KM_PEX_RST_GPIO_PIN     7
194 int fpga_reset(void)
195 {
196         if (!check_boco2()) {
197                 /* we do not have BOCO2, this is not really used */
198                 return 0;
199         }
200
201         printf("PCIe reset through GPIO7: ");
202         /* apply PCIe reset via GPIO */
203         kw_gpio_set_valid(KM_PEX_RST_GPIO_PIN, 1);
204         kw_gpio_direction_output(KM_PEX_RST_GPIO_PIN, 1);
205         kw_gpio_set_value(KM_PEX_RST_GPIO_PIN, 0);
206         udelay(1000*10);
207         kw_gpio_set_value(KM_PEX_RST_GPIO_PIN, 1);
208
209         printf(" done\n");
210
211         return 0;
212 }
213
214 #else
215
216 #define PRST1           0x4
217 #define PCIE_RST        0x10
218 #define TRAFFIC_RST     0x04
219
220 int fpga_reset(void)
221 {
222         int ret = 0;
223         u8 resets;
224
225         if (!check_boco2()) {
226                 /* we do not have BOCO2, this is not really used */
227                 return 0;
228         }
229
230         /* if we have skipped, we only want to reset the PCIe part */
231         resets = skip ? PCIE_RST : PCIE_RST | TRAFFIC_RST;
232
233         ret = boco_clear_bits(PRST1, resets);
234         if (ret)
235                 return ret;
236
237         /* small delay for the pulse */
238         udelay(10);
239
240         ret = boco_set_bits(PRST1, resets);
241         if (ret)
242                 return ret;
243
244         return 0;
245 }
246 #endif
247
248 /* the FPGA was configured, we configure the BOCO2 so that the EEPROM
249  * is available from the Bobcat SPI bus */
250 int toggle_eeprom_spi_bus(void)
251 {
252         int ret = 0;
253
254         if (!check_boco2()) {
255                 /* we do not have BOCO2, this is not really used */
256                 return 0;
257         }
258
259         ret = boco_set_bits(SPI_REG, CFG_EEPROM);
260         if (ret)
261                 return ret;
262
263         return 0;
264 }