aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMario Six2018-10-04 02:00:55 -0500
committerSimon Glass2018-11-14 11:16:27 -0600
commitab88bd2b6a160310953a230d4a4c334ea6a65d3b (patch)
treeb13f6123ab17c212ce3713c01eb863cfd8541495 /drivers
parentc0a2b086b22b4af3253e4e22d5a9d1e809fd1352 (diff)
downloadu-boot-ab88bd2b6a160310953a230d4a4c334ea6a65d3b.tar.gz
u-boot-ab88bd2b6a160310953a230d4a4c334ea6a65d3b.tar.xz
u-boot-ab88bd2b6a160310953a230d4a4c334ea6a65d3b.zip
misc: Add IHS FPGA driver
Add a driver for gdsys IHS (Integrated Hardware Systems) FPGAs, which supports initialization of the FPGA, as well as information gathering. Reviewed-by: Simon Glass <sjg@chromium.org> Signed-off-by: Mario Six <mario.six@gdsys.cc>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/misc/Kconfig9
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/ihs_fpga.c867
-rw-r--r--drivers/misc/ihs_fpga.h49
4 files changed, 926 insertions, 0 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index d589f32a55..48febc47d2 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -320,4 +320,13 @@ config GDSYS_SOC
320 IHS (Integrated Hardware Systems) FPGA, which holds all devices whose 320 IHS (Integrated Hardware Systems) FPGA, which holds all devices whose
321 register maps are contained within the FPGA's register map. 321 register maps are contained within the FPGA's register map.
322 322
323config IHS_FPGA
324 bool "Enable IHS FPGA driver"
325 depends on MISC
326 help
327 Support IHS (Integrated Hardware Systems) FPGA, the main FPGAs on
328 gdsys devices, which supply the majority of the functionality offered
329 by the devices. This driver supports both CON and CPU variants of the
330 devices, depending on the device tree entry.
331
323endmenu 332endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 4a5a18675a..302d441592 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_GDSYS_IOEP) += gdsys_ioep.o
37obj-$(CONFIG_GDSYS_RXAUI_CTRL) += gdsys_rxaui_ctrl.o 37obj-$(CONFIG_GDSYS_RXAUI_CTRL) += gdsys_rxaui_ctrl.o
38obj-$(CONFIG_GDSYS_SOC) += gdsys_soc.o 38obj-$(CONFIG_GDSYS_SOC) += gdsys_soc.o
39obj-$(CONFIG_$(SPL_)I2C_EEPROM) += i2c_eeprom.o 39obj-$(CONFIG_$(SPL_)I2C_EEPROM) += i2c_eeprom.o
40obj-$(CONFIG_IHS_FPGA) += ihs_fpga.o
40obj-$(CONFIG_IMX8) += imx8/ 41obj-$(CONFIG_IMX8) += imx8/
41obj-$(CONFIG_LED_STATUS) += status_led.o 42obj-$(CONFIG_LED_STATUS) += status_led.o
42obj-$(CONFIG_LED_STATUS_GPIO) += gpio_led.o 43obj-$(CONFIG_LED_STATUS_GPIO) += gpio_led.o
diff --git a/drivers/misc/ihs_fpga.c b/drivers/misc/ihs_fpga.c
new file mode 100644
index 0000000000..f9e4b27a27
--- /dev/null
+++ b/drivers/misc/ihs_fpga.c
@@ -0,0 +1,867 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * (C) Copyright 2017
4 * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
5 *
6 * based on the ioep-fpga driver, which is
7 *
8 * (C) Copyright 2014
9 * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de
10 */
11
12#include <common.h>
13#include <dm.h>
14#include <regmap.h>
15#include <asm/gpio.h>
16
17#include "ihs_fpga.h"
18
19/**
20 * struct ihs_fpga_priv - Private data structure for IHS FPGA driver
21 * @map: Register map for the FPGA's own register space
22 * @reset_gpio: GPIO to start FPGA reconfiguration
23 * @done_gpio: GPOI to read the 'ready' status of the FPGA
24 */
25struct ihs_fpga_priv {
26 struct regmap *map;
27 struct gpio_desc reset_gpio;
28 struct gpio_desc done_gpio;
29};
30
31/* Test pattern for reflection test */
32const u16 REFLECTION_TESTPATTERN = 0xdead;
33/* Delay (in ms) for each round in the reflection test */
34const uint REFLECTION_TEST_DELAY = 100;
35/* Maximum number of rounds in the reflection test */
36const uint REFLECTION_TEST_ROUNDS = 5;
37/* Delay (in ms) for each round waiting for the FPGA's done GPIO */
38const uint FPGA_DONE_WAIT_DELAY = 100;
39/* Maximum number of rounds for waiting for the FPGA's done GPIO */
40const uint FPGA_DONE_WAIT_ROUND = 5;
41
42/**
43 * enum pcb_video_type - Video type of the PCB
44 * @PCB_DVI_SL: Video type is DVI single-link
45 * @PCB_DP_165MPIX: Video type is DisplayPort (165Mpix)
46 * @PCB_DP_300MPIX: Video type is DisplayPort (300Mpix)
47 * @PCB_HDMI: Video type is HDMI
48 * @PCB_DP_1_2: Video type is DisplayPort 1.2
49 * @PCB_HDMI_2_0: Video type is HDMI 2.0
50 */
51enum pcb_video_type {
52 PCB_DVI_SL,
53 PCB_DP_165MPIX,
54 PCB_DP_300MPIX,
55 PCB_HDMI,
56 PCB_DP_1_2,
57 PCB_HDMI_2_0,
58};
59
60/**
61 * enum pcb_transmission_type - Transmission type of the PCB
62 * @PCB_CAT_1G: Transmission type is 1G Ethernet
63 * @PCB_FIBER_3G: Transmission type is 3G Fiber
64 * @PCB_CAT_10G: Transmission type is 10G Ethernet
65 * @PCB_FIBER_10G: Transmission type is 10G Fiber
66 */
67enum pcb_transmission_type {
68 PCB_CAT_1G,
69 PCB_FIBER_3G,
70 PCB_CAT_10G,
71 PCB_FIBER_10G,
72};
73
74/**
75 * enum carrier_speed - Speed of the FPGA's carrier
76 * @CARRIER_SPEED_1G: The carrier speed is 1G
77 * @CARRIER_SPEED_2_5G: The carrier speed is 2.5G
78 * @CARRIER_SPEED_3G: The carrier speed is 3G
79 * @CARRIER_SPEED_10G: The carrier speed is 10G
80 */
81enum carrier_speed {
82 CARRIER_SPEED_1G,
83 CARRIER_SPEED_3G,
84 CARRIER_SPEED_2_5G = CARRIER_SPEED_3G,
85 CARRIER_SPEED_10G,
86};
87
88/**
89 * enum ram_config - FPGA's RAM configuration
90 * @RAM_DDR2_32BIT_295MBPS: DDR2 32 bit at 295Mb/s
91 * @RAM_DDR3_32BIT_590MBPS: DDR3 32 bit at 590Mb/s
92 * @RAM_DDR3_48BIT_590MBPS: DDR3 48 bit at 590Mb/s
93 * @RAM_DDR3_64BIT_1800MBPS: DDR3 64 bit at 1800Mb/s
94 * @RAM_DDR3_48BIT_1800MBPS: DDR3 48 bit at 1800Mb/s
95 */
96enum ram_config {
97 RAM_DDR2_32BIT_295MBPS,
98 RAM_DDR3_32BIT_590MBPS,
99 RAM_DDR3_48BIT_590MBPS,
100 RAM_DDR3_64BIT_1800MBPS,
101 RAM_DDR3_48BIT_1800MBPS,
102};
103
104/**
105 * enum sysclock - Speed of the FPGA's system clock
106 * @SYSCLK_147456: System clock is 147.456 MHz
107 */
108enum sysclock {
109 SYSCLK_147456,
110};
111
112/**
113 * struct fpga_versions - Data read from the versions register
114 * @video_channel: Is the FPGA for a video channel (true) or main
115 * channel (false) device?
116 * @con_side: Is the FPGA for a CON (true) or a CPU (false) device?
117 * @pcb_video_type: Defines for whch video type the FPGA is configured
118 * @pcb_transmission_type: Defines for which transmission type the FPGA is
119 * configured
120 * @hw_version: Hardware version of the FPGA
121 */
122struct fpga_versions {
123 bool video_channel;
124 bool con_side;
125 enum pcb_video_type pcb_video_type;
126 enum pcb_transmission_type pcb_transmission_type;
127 unsigned int hw_version;
128};
129
130/**
131 * struct fpga_features - Data read from the features register
132 * @video_channels: Number of video channels supported
133 * @carriers: Number of carrier channels supported
134 * @carrier_speed: Speed of carriers
135 * @ram_config: RAM configuration of FPGA
136 * @sysclock: System clock speed of FPGA
137 * @pcm_tx: Support for PCM transmission
138 * @pcm_rx: Support for PCM reception
139 * @spdif_tx: Support for SPDIF audio transmission
140 * @spdif_rx: Support for SPDIF audio reception
141 * @usb2: Support for transparent USB2.0
142 * @rs232: Support for bidirectional RS232
143 * @compression_type1: Support for compression type 1
144 * @compression_type2: Support for compression type 2
145 * @compression_type3: Support for compression type 3
146 * @interlace: Support for interlace image formats
147 * @osd: Support for a OSD
148 * @compression_pipes: Number of compression pipes supported
149 */
150struct fpga_features {
151 u8 video_channels;
152 u8 carriers;
153 enum carrier_speed carrier_speed;
154 enum ram_config ram_config;
155 enum sysclock sysclock;
156 bool pcm_tx;
157 bool pcm_rx;
158 bool spdif_tx;
159 bool spdif_rx;
160 bool usb2;
161 bool rs232;
162 bool compression_type1;
163 bool compression_type2;
164 bool compression_type3;
165 bool interlace;
166 bool osd;
167 bool compression_pipes;
168};
169
170#ifdef CONFIG_SYS_FPGA_FLAVOR_GAZERBEAM
171
172/**
173 * get_versions() - Fill structure with info from version register.
174 * @dev: FPGA device to be queried for information
175 * @versions: Pointer to the structure to fill with information from the
176 * versions register
177 * Return: 0
178 */
179static int get_versions(struct udevice *dev, struct fpga_versions *versions)
180{
181 struct ihs_fpga_priv *priv = dev_get_priv(dev);
182 enum {
183 VERSIONS_FPGA_VIDEO_CHANNEL = BIT(12),
184 VERSIONS_FPGA_CON_SIDE = BIT(13),
185 VERSIONS_FPGA_SC = BIT(14),
186 VERSIONS_PCB_CON = BIT(9),
187 VERSIONS_PCB_SC = BIT(8),
188 VERSIONS_PCB_VIDEO_MASK = 0x3 << 6,
189 VERSIONS_PCB_VIDEO_DP_1_2 = 0x0 << 6,
190 VERSIONS_PCB_VIDEO_HDMI_2_0 = 0x1 << 6,
191 VERSIONS_PCB_TRANSMISSION_MASK = 0x3 << 4,
192 VERSIONS_PCB_TRANSMISSION_FIBER_10G = 0x0 << 4,
193 VERSIONS_PCB_TRANSMISSION_CAT_10G = 0x1 << 4,
194 VERSIONS_PCB_TRANSMISSION_FIBER_3G = 0x2 << 4,
195 VERSIONS_PCB_TRANSMISSION_CAT_1G = 0x3 << 4,
196 VERSIONS_HW_VER_MASK = 0xf << 0,
197 };
198 u16 raw_versions;
199
200 memset(versions, 0, sizeof(struct fpga_versions));
201
202 ihs_fpga_get(priv->map, versions, &raw_versions);
203
204 versions->video_channel = raw_versions & VERSIONS_FPGA_VIDEO_CHANNEL;
205 versions->con_side = raw_versions & VERSIONS_FPGA_CON_SIDE;
206
207 switch (raw_versions & VERSIONS_PCB_VIDEO_MASK) {
208 case VERSIONS_PCB_VIDEO_DP_1_2:
209 versions->pcb_video_type = PCB_DP_1_2;
210 break;
211
212 case VERSIONS_PCB_VIDEO_HDMI_2_0:
213 versions->pcb_video_type = PCB_HDMI_2_0;
214 break;
215 }
216
217 switch (raw_versions & VERSIONS_PCB_TRANSMISSION_MASK) {
218 case VERSIONS_PCB_TRANSMISSION_FIBER_10G:
219 versions->pcb_transmission_type = PCB_FIBER_10G;
220 break;
221
222 case VERSIONS_PCB_TRANSMISSION_CAT_10G:
223 versions->pcb_transmission_type = PCB_CAT_10G;
224 break;
225
226 case VERSIONS_PCB_TRANSMISSION_FIBER_3G:
227 versions->pcb_transmission_type = PCB_FIBER_3G;
228 break;
229
230 case VERSIONS_PCB_TRANSMISSION_CAT_1G:
231 versions->pcb_transmission_type = PCB_CAT_1G;
232 break;
233 }
234
235 versions->hw_version = raw_versions & VERSIONS_HW_VER_MASK;
236
237 return 0;
238}
239
240/**
241 * get_features() - Fill structure with info from features register.
242 * @dev: FPGA device to be queried for information
243 * @features: Pointer to the structure to fill with information from the
244 * features register
245 * Return: 0
246 */
247static int get_features(struct udevice *dev, struct fpga_features *features)
248{
249 struct ihs_fpga_priv *priv = dev_get_priv(dev);
250 enum {
251 FEATURE_SPDIF_RX = BIT(15),
252 FEATURE_SPDIF_TX = BIT(14),
253 FEATURE_PCM_RX = BIT(13),
254 FEATURE_PCM_TX = BIT(12),
255 FEATURE_RAM_MASK = GENMASK(11, 8),
256 FEATURE_RAM_DDR2_32BIT_295MBPS = 0x0 << 8,
257 FEATURE_RAM_DDR3_32BIT_590MBPS = 0x1 << 8,
258 FEATURE_RAM_DDR3_48BIT_590MBPS = 0x2 << 8,
259 FEATURE_RAM_DDR3_64BIT_1800MBPS = 0x3 << 8,
260 FEATURE_RAM_DDR3_48BIT_1800MBPS = 0x4 << 8,
261 FEATURE_CARRIER_SPEED_MASK = GENMASK(7, 6),
262 FEATURE_CARRIER_SPEED_1G = 0x0 << 6,
263 FEATURE_CARRIER_SPEED_2_5G = 0x1 << 6,
264 FEATURE_CARRIER_SPEED_10G = 0x2 << 6,
265 FEATURE_CARRIERS_MASK = GENMASK(5, 4),
266 FEATURE_CARRIERS_0 = 0x0 << 4,
267 FEATURE_CARRIERS_1 = 0x1 << 4,
268 FEATURE_CARRIERS_2 = 0x2 << 4,
269 FEATURE_CARRIERS_4 = 0x3 << 4,
270 FEATURE_USB2 = BIT(3),
271 FEATURE_VIDEOCHANNELS_MASK = GENMASK(2, 0),
272 FEATURE_VIDEOCHANNELS_0 = 0x0 << 0,
273 FEATURE_VIDEOCHANNELS_1 = 0x1 << 0,
274 FEATURE_VIDEOCHANNELS_1_1 = 0x2 << 0,
275 FEATURE_VIDEOCHANNELS_2 = 0x3 << 0,
276 };
277
278 enum {
279 EXT_FEATURE_OSD = BIT(15),
280 EXT_FEATURE_ETHERNET = BIT(9),
281 EXT_FEATURE_INTERLACE = BIT(8),
282 EXT_FEATURE_RS232 = BIT(7),
283 EXT_FEATURE_COMPRESSION_PERF_MASK = GENMASK(6, 4),
284 EXT_FEATURE_COMPRESSION_PERF_1X = 0x0 << 4,
285 EXT_FEATURE_COMPRESSION_PERF_2X = 0x1 << 4,
286 EXT_FEATURE_COMPRESSION_PERF_4X = 0x2 << 4,
287 EXT_FEATURE_COMPRESSION_TYPE1 = BIT(0),
288 EXT_FEATURE_COMPRESSION_TYPE2 = BIT(1),
289 EXT_FEATURE_COMPRESSION_TYPE3 = BIT(2),
290 };
291
292 u16 raw_features;
293 u16 raw_extended_features;
294
295 memset(features, 0, sizeof(struct fpga_features));
296
297 ihs_fpga_get(priv->map, features, &raw_features);
298 ihs_fpga_get(priv->map, extended_features, &raw_extended_features);
299
300 switch (raw_features & FEATURE_VIDEOCHANNELS_MASK) {
301 case FEATURE_VIDEOCHANNELS_0:
302 features->video_channels = 0;
303 break;
304
305 case FEATURE_VIDEOCHANNELS_1:
306 features->video_channels = 1;
307 break;
308
309 case FEATURE_VIDEOCHANNELS_1_1:
310 case FEATURE_VIDEOCHANNELS_2:
311 features->video_channels = 2;
312 break;
313 };
314
315 switch (raw_features & FEATURE_CARRIERS_MASK) {
316 case FEATURE_CARRIERS_0:
317 features->carriers = 0;
318 break;
319
320 case FEATURE_CARRIERS_1:
321 features->carriers = 1;
322 break;
323
324 case FEATURE_CARRIERS_2:
325 features->carriers = 2;
326 break;
327
328 case FEATURE_CARRIERS_4:
329 features->carriers = 4;
330 break;
331 }
332
333 switch (raw_features & FEATURE_CARRIER_SPEED_MASK) {
334 case FEATURE_CARRIER_SPEED_1G:
335 features->carrier_speed = CARRIER_SPEED_1G;
336 break;
337 case FEATURE_CARRIER_SPEED_2_5G:
338 features->carrier_speed = CARRIER_SPEED_2_5G;
339 break;
340 case FEATURE_CARRIER_SPEED_10G:
341 features->carrier_speed = CARRIER_SPEED_10G;
342 break;
343 }
344
345 switch (raw_features & FEATURE_RAM_MASK) {
346 case FEATURE_RAM_DDR2_32BIT_295MBPS:
347 features->ram_config = RAM_DDR2_32BIT_295MBPS;
348 break;
349
350 case FEATURE_RAM_DDR3_32BIT_590MBPS:
351 features->ram_config = RAM_DDR3_32BIT_590MBPS;
352 break;
353
354 case FEATURE_RAM_DDR3_48BIT_590MBPS:
355 features->ram_config = RAM_DDR3_48BIT_590MBPS;
356 break;
357
358 case FEATURE_RAM_DDR3_64BIT_1800MBPS:
359 features->ram_config = RAM_DDR3_64BIT_1800MBPS;
360 break;
361
362 case FEATURE_RAM_DDR3_48BIT_1800MBPS:
363 features->ram_config = RAM_DDR3_48BIT_1800MBPS;
364 break;
365 }
366
367 features->pcm_tx = raw_features & FEATURE_PCM_TX;
368 features->pcm_rx = raw_features & FEATURE_PCM_RX;
369 features->spdif_tx = raw_features & FEATURE_SPDIF_TX;
370 features->spdif_rx = raw_features & FEATURE_SPDIF_RX;
371 features->usb2 = raw_features & FEATURE_USB2;
372 features->rs232 = raw_extended_features & EXT_FEATURE_RS232;
373 features->compression_type1 = raw_extended_features &
374 EXT_FEATURE_COMPRESSION_TYPE1;
375 features->compression_type2 = raw_extended_features &
376 EXT_FEATURE_COMPRESSION_TYPE2;
377 features->compression_type3 = raw_extended_features &
378 EXT_FEATURE_COMPRESSION_TYPE3;
379 features->interlace = raw_extended_features & EXT_FEATURE_INTERLACE;
380 features->osd = raw_extended_features & EXT_FEATURE_OSD;
381 features->compression_pipes = raw_extended_features &
382 EXT_FEATURE_COMPRESSION_PERF_MASK;
383
384 return 0;
385}
386
387#else
388
389/**
390 * get_versions() - Fill structure with info from version register.
391 * @fpga: Identifier of the FPGA device to be queried for information
392 * @versions: Pointer to the structure to fill with information from the
393 * versions register
394 *
395 * This is the legacy version and should be considered deprecated for new
396 * devices.
397 *
398 * Return: 0
399 */
400static int get_versions(unsigned int fpga, struct fpga_versions *versions)
401{
402 enum {
403 /* HW version encoding is a mess, leave it for the moment */
404 VERSIONS_HW_VER_MASK = 0xf << 0,
405 VERSIONS_PIX_CLOCK_GEN_IDT8N3QV01 = BIT(4),
406 VERSIONS_SFP = BIT(5),
407 VERSIONS_VIDEO_MASK = 0x7 << 6,
408 VERSIONS_VIDEO_DVI = 0x0 << 6,
409 VERSIONS_VIDEO_DP_165 = 0x1 << 6,
410 VERSIONS_VIDEO_DP_300 = 0x2 << 6,
411 VERSIONS_VIDEO_HDMI = 0x3 << 6,
412 VERSIONS_UT_MASK = 0xf << 12,
413 VERSIONS_UT_MAIN_SERVER = 0x0 << 12,
414 VERSIONS_UT_MAIN_USER = 0x1 << 12,
415 VERSIONS_UT_VIDEO_SERVER = 0x2 << 12,
416 VERSIONS_UT_VIDEO_USER = 0x3 << 12,
417 };
418 u16 raw_versions;
419
420 memset(versions, 0, sizeof(struct fpga_versions));
421
422 FPGA_GET_REG(fpga, versions, &raw_versions);
423
424 switch (raw_versions & VERSIONS_UT_MASK) {
425 case VERSIONS_UT_MAIN_SERVER:
426 versions->video_channel = false;
427 versions->con_side = false;
428 break;
429
430 case VERSIONS_UT_MAIN_USER:
431 versions->video_channel = false;
432 versions->con_side = true;
433 break;
434
435 case VERSIONS_UT_VIDEO_SERVER:
436 versions->video_channel = true;
437 versions->con_side = false;
438 break;
439
440 case VERSIONS_UT_VIDEO_USER:
441 versions->video_channel = true;
442 versions->con_side = true;
443 break;
444 }
445
446 switch (raw_versions & VERSIONS_VIDEO_MASK) {
447 case VERSIONS_VIDEO_DVI:
448 versions->pcb_video_type = PCB_DVI_SL;
449 break;
450
451 case VERSIONS_VIDEO_DP_165:
452 versions->pcb_video_type = PCB_DP_165MPIX;
453 break;
454
455 case VERSIONS_VIDEO_DP_300:
456 versions->pcb_video_type = PCB_DP_300MPIX;
457 break;
458
459 case VERSIONS_VIDEO_HDMI:
460 versions->pcb_video_type = PCB_HDMI;
461 break;
462 }
463
464 versions->hw_version = raw_versions & VERSIONS_HW_VER_MASK;
465
466 if (raw_versions & VERSIONS_SFP)
467 versions->pcb_transmission_type = PCB_FIBER_3G;
468 else
469 versions->pcb_transmission_type = PCB_CAT_1G;
470
471 return 0;
472}
473
474/**
475 * get_features() - Fill structure with info from features register.
476 * @fpga: Identifier of the FPGA device to be queried for information
477 * @features: Pointer to the structure to fill with information from the
478 * features register
479 *
480 * This is the legacy version and should be considered deprecated for new
481 * devices.
482 *
483 * Return: 0
484 */
485static int get_features(unsigned int fpga, struct fpga_features *features)
486{
487 enum {
488 FEATURE_CARRIER_SPEED_2_5 = BIT(4),
489 FEATURE_RAM_MASK = 0x7 << 5,
490 FEATURE_RAM_DDR2_32BIT = 0x0 << 5,
491 FEATURE_RAM_DDR3_32BIT = 0x1 << 5,
492 FEATURE_RAM_DDR3_48BIT = 0x2 << 5,
493 FEATURE_PCM_AUDIO_TX = BIT(9),
494 FEATURE_PCM_AUDIO_RX = BIT(10),
495 FEATURE_OSD = BIT(11),
496 FEATURE_USB20 = BIT(12),
497 FEATURE_COMPRESSION_MASK = 7 << 13,
498 FEATURE_COMPRESSION_TYPE1 = 0x1 << 13,
499 FEATURE_COMPRESSION_TYPE1_TYPE2 = 0x3 << 13,
500 FEATURE_COMPRESSION_TYPE1_TYPE2_TYPE3 = 0x7 << 13,
501 };
502
503 enum {
504 EXTENDED_FEATURE_SPDIF_AUDIO_TX = BIT(0),
505 EXTENDED_FEATURE_SPDIF_AUDIO_RX = BIT(1),
506 EXTENDED_FEATURE_RS232 = BIT(2),
507 EXTENDED_FEATURE_COMPRESSION_PIPES = BIT(3),
508 EXTENDED_FEATURE_INTERLACE = BIT(4),
509 };
510
511 u16 raw_features;
512 u16 raw_extended_features;
513
514 memset(features, 0, sizeof(struct fpga_features));
515
516 FPGA_GET_REG(fpga, fpga_features, &raw_features);
517 FPGA_GET_REG(fpga, fpga_ext_features, &raw_extended_features);
518
519 features->video_channels = raw_features & 0x3;
520 features->carriers = (raw_features >> 2) & 0x3;
521
522 features->carrier_speed = (raw_features & FEATURE_CARRIER_SPEED_2_5)
523 ? CARRIER_SPEED_2_5G : CARRIER_SPEED_1G;
524
525 switch (raw_features & FEATURE_RAM_MASK) {
526 case FEATURE_RAM_DDR2_32BIT:
527 features->ram_config = RAM_DDR2_32BIT_295MBPS;
528 break;
529
530 case FEATURE_RAM_DDR3_32BIT:
531 features->ram_config = RAM_DDR3_32BIT_590MBPS;
532 break;
533
534 case FEATURE_RAM_DDR3_48BIT:
535 features->ram_config = RAM_DDR3_48BIT_590MBPS;
536 break;
537 }
538
539 features->pcm_tx = raw_features & FEATURE_PCM_AUDIO_TX;
540 features->pcm_rx = raw_features & FEATURE_PCM_AUDIO_RX;
541 features->spdif_tx = raw_extended_features &
542 EXTENDED_FEATURE_SPDIF_AUDIO_TX;
543 features->spdif_rx = raw_extended_features &
544 EXTENDED_FEATURE_SPDIF_AUDIO_RX;
545
546 features->usb2 = raw_features & FEATURE_USB20;
547 features->rs232 = raw_extended_features & EXTENDED_FEATURE_RS232;
548
549 features->compression_type1 = false;
550 features->compression_type2 = false;
551 features->compression_type3 = false;
552 switch (raw_features & FEATURE_COMPRESSION_MASK) {
553 case FEATURE_COMPRESSION_TYPE1_TYPE2_TYPE3:
554 features->compression_type3 = true;
555 /* fall-through */
556 case FEATURE_COMPRESSION_TYPE1_TYPE2:
557 features->compression_type2 = true;
558 /* fall-through */
559 case FEATURE_COMPRESSION_TYPE1:
560 features->compression_type1 = true;
561 break;
562 }
563
564 features->interlace = raw_extended_features &
565 EXTENDED_FEATURE_INTERLACE;
566 features->osd = raw_features & FEATURE_OSD;
567 features->compression_pipes = raw_extended_features &
568 EXTENDED_FEATURE_COMPRESSION_PIPES;
569
570 return 0;
571}
572
573#endif
574
575/**
576 * fpga_print_info() - Print information about FPGA device
577 * @dev: FPGA device to print information about
578 */
579static void fpga_print_info(struct udevice *dev)
580{
581 struct ihs_fpga_priv *priv = dev_get_priv(dev);
582 u16 fpga_version;
583 struct fpga_versions versions;
584 struct fpga_features features;
585
586 ihs_fpga_get(priv->map, fpga_version, &fpga_version);
587 get_versions(dev, &versions);
588 get_features(dev, &features);
589
590 if (versions.video_channel)
591 printf("Videochannel");
592 else
593 printf("Mainchannel");
594
595 if (versions.con_side)
596 printf(" User");
597 else
598 printf(" Server");
599
600 switch (versions.pcb_transmission_type) {
601 case PCB_CAT_1G:
602 case PCB_CAT_10G:
603 printf(" CAT");
604 break;
605 case PCB_FIBER_3G:
606 case PCB_FIBER_10G:
607 printf(" Fiber");
608 break;
609 };
610
611 switch (versions.pcb_video_type) {
612 case PCB_DVI_SL:
613 printf(" DVI,");
614 break;
615 case PCB_DP_165MPIX:
616 printf(" DP 165MPix/s,");
617 break;
618 case PCB_DP_300MPIX:
619 printf(" DP 300MPix/s,");
620 break;
621 case PCB_HDMI:
622 printf(" HDMI,");
623 break;
624 case PCB_DP_1_2:
625 printf(" DP 1.2,");
626 break;
627 case PCB_HDMI_2_0:
628 printf(" HDMI 2.0,");
629 break;
630 }
631
632 printf(" FPGA V %d.%02d\n features: ",
633 fpga_version / 100, fpga_version % 100);
634
635 if (!features.compression_type1 &&
636 !features.compression_type2 &&
637 !features.compression_type3)
638 printf("no compression, ");
639
640 if (features.compression_type1)
641 printf("type1, ");
642
643 if (features.compression_type2)
644 printf("type2, ");
645
646 if (features.compression_type3)
647 printf("type3, ");
648
649 printf("%sosd", features.osd ? "" : "no ");
650
651 if (features.pcm_rx && features.pcm_tx)
652 printf(", pcm rx+tx");
653 else if (features.pcm_rx)
654 printf(", pcm rx");
655 else if (features.pcm_tx)
656 printf(", pcm tx");
657
658 if (features.spdif_rx && features.spdif_tx)
659 printf(", spdif rx+tx");
660 else if (features.spdif_rx)
661 printf(", spdif rx");
662 else if (features.spdif_tx)
663 printf(", spdif tx");
664
665 puts(",\n ");
666
667 switch (features.sysclock) {
668 case SYSCLK_147456:
669 printf("clock 147.456 MHz");
670 break;
671 }
672
673 switch (features.ram_config) {
674 case RAM_DDR2_32BIT_295MBPS:
675 printf(", RAM 32 bit DDR2");
676 break;
677 case RAM_DDR3_32BIT_590MBPS:
678 printf(", RAM 32 bit DDR3");
679 break;
680 case RAM_DDR3_48BIT_590MBPS:
681 case RAM_DDR3_48BIT_1800MBPS:
682 printf(", RAM 48 bit DDR3");
683 break;
684 case RAM_DDR3_64BIT_1800MBPS:
685 printf(", RAM 64 bit DDR3");
686 break;
687 }
688
689 printf(", %d carrier(s)", features.carriers);
690
691 switch (features.carrier_speed) {
692 case CARRIER_SPEED_1G:
693 printf(", 1Gbit/s");
694 break;
695 case CARRIER_SPEED_3G:
696 printf(", 3Gbit/s");
697 break;
698 case CARRIER_SPEED_10G:
699 printf(", 10Gbit/s");
700 break;
701 }
702
703 printf(", %d video channel(s)\n", features.video_channels);
704}
705
706/**
707 * do_reflection_test() - Run reflection test on a FPGA device
708 * @dev: FPGA device to run reflection test on
709 *
710 * Return: 0 if reflection test succeeded, -ve on error
711 */
712static int do_reflection_test(struct udevice *dev)
713{
714 struct ihs_fpga_priv *priv = dev_get_priv(dev);
715 int ctr = 0;
716
717 while (1) {
718 u16 val;
719
720 ihs_fpga_set(priv->map, reflection_low, REFLECTION_TESTPATTERN);
721
722 ihs_fpga_get(priv->map, reflection_low, &val);
723 if (val == (~REFLECTION_TESTPATTERN & 0xffff))
724 return -EIO;
725
726 mdelay(REFLECTION_TEST_DELAY);
727 if (ctr++ > REFLECTION_TEST_ROUNDS)
728 return 0;
729 }
730}
731
732/**
733 * wait_for_fpga_done() - Wait until 'done'-flag is set for FPGA device
734 * @dev: FPGA device whose done flag to wait for
735 *
736 * This function waits until it detects that the done-GPIO's value was changed
737 * to 1 by the FPGA, which indicates that the device is configured and ready to
738 * use.
739 *
740 * Return: 0 if done flag was detected, -ve on error
741 */
742static int wait_for_fpga_done(struct udevice *dev)
743{
744 struct ihs_fpga_priv *priv = dev_get_priv(dev);
745 int ctr = 0;
746 int done_val;
747
748 while (1) {
749 done_val = dm_gpio_get_value(&priv->done_gpio);
750 if (done_val < 0) {
751 debug("%s: Error while reading done-GPIO (err = %d)\n",
752 dev->name, done_val);
753 return done_val;
754 }
755
756 if (done_val)
757 return 0;
758
759 mdelay(FPGA_DONE_WAIT_DELAY);
760 if (ctr++ > FPGA_DONE_WAIT_ROUND) {
761 debug("%s: FPGA init failed (done not detected)\n",
762 dev->name);
763 return -EIO;
764 }
765 }
766}
767
768static int ihs_fpga_probe(struct udevice *dev)
769{
770 struct ihs_fpga_priv *priv = dev_get_priv(dev);
771 int ret;
772
773 /* TODO(mario.six@gdsys.cc): Case of FPGA attached to MCLink bus */
774
775 ret = regmap_init_mem(dev_ofnode(dev), &priv->map);
776 if (ret) {
777 debug("%s: Could not initialize regmap (err = %d)",
778 dev->name, ret);
779 return ret;
780 }
781
782 ret = gpio_request_by_name(dev, "reset-gpios", 0, &priv->reset_gpio,
783 GPIOD_IS_OUT);
784 if (ret) {
785 debug("%s: Could not get reset-GPIO (err = %d)\n",
786 dev->name, ret);
787 return ret;
788 }
789
790 if (!priv->reset_gpio.dev) {
791 debug("%s: Could not get reset-GPIO\n", dev->name);
792 return -ENOENT;
793 }
794
795 ret = gpio_request_by_name(dev, "done-gpios", 0, &priv->done_gpio,
796 GPIOD_IS_IN);
797 if (ret) {
798 debug("%s: Could not get done-GPIO (err = %d)\n",
799 dev->name, ret);
800 return ret;
801 }
802
803 if (!priv->done_gpio.dev) {
804 debug("%s: Could not get done-GPIO\n", dev->name);
805 return -ENOENT;
806 }
807
808 ret = dm_gpio_set_value(&priv->reset_gpio, 1);
809 if (ret) {
810 debug("%s: Error while setting reset-GPIO (err = %d)\n",
811 dev->name, ret);
812 return ret;
813 }
814
815 /* If FPGA already runs, don't initialize again */
816 if (do_reflection_test(dev))
817 goto reflection_ok;
818
819 ret = dm_gpio_set_value(&priv->reset_gpio, 0);
820 if (ret) {
821 debug("%s: Error while setting reset-GPIO (err = %d)\n",
822 dev->name, ret);
823 return ret;
824 }
825
826 ret = wait_for_fpga_done(dev);
827 if (ret) {
828 debug("%s: Error while waiting for FPGA done (err = %d)\n",
829 dev->name, ret);
830 return ret;
831 }
832
833 udelay(10);
834
835 ret = dm_gpio_set_value(&priv->reset_gpio, 1);
836 if (ret) {
837 debug("%s: Error while setting reset-GPIO (err = %d)\n",
838 dev->name, ret);
839 return ret;
840 }
841
842 if (!do_reflection_test(dev)) {
843 debug("%s: Reflection test FAILED\n", dev->name);
844 return -EIO;
845 }
846
847reflection_ok:
848 printf("%s: Reflection test passed.\n", dev->name);
849
850 fpga_print_info(dev);
851
852 return 0;
853}
854
855static const struct udevice_id ihs_fpga_ids[] = {
856 { .compatible = "gdsys,iocon_fpga" },
857 { .compatible = "gdsys,iocpu_fpga" },
858 { }
859};
860
861U_BOOT_DRIVER(ihs_fpga_bus) = {
862 .name = "ihs_fpga_bus",
863 .id = UCLASS_MISC,
864 .of_match = ihs_fpga_ids,
865 .probe = ihs_fpga_probe,
866 .priv_auto_alloc_size = sizeof(struct ihs_fpga_priv),
867};
diff --git a/drivers/misc/ihs_fpga.h b/drivers/misc/ihs_fpga.h
new file mode 100644
index 0000000000..efb5dabb9c
--- /dev/null
+++ b/drivers/misc/ihs_fpga.h
@@ -0,0 +1,49 @@
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * (C) Copyright 2018
4 * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
5 */
6
7/**
8 * struct ihs_fpga_regs - IHS FPGA register map structure
9 * @reflection_low: Lower reflection register
10 * @versions: PCB versions register
11 * @fpga_version: FPGA versions register
12 * @features: FPGA features register
13 * @extended_features: FPGA extended features register
14 * @top_interrupt: Top interrupt register
15 * @top_interrupt_enable: Top interrupt enable register
16 * @status: FPGA status register
17 * @control: FPGA control register
18 * @extended_control: FPGA extended control register
19 */
20struct ihs_fpga_regs {
21 u16 reflection_low;
22 u16 versions;
23 u16 fpga_version;
24 u16 features;
25 u16 extended_features;
26 u16 top_interrupt;
27 u16 top_interrupt_enable;
28 u16 status;
29 u16 control;
30 u16 extended_control;
31};
32
33/**
34 * ihs_fpga_set() - Convenience macro to set values in FPGA register map
35 * @map: Register map to set a value in
36 * @member: Name of member (described by ihs_fpga_regs) to set
37 * @val: Value to set the member to
38 */
39#define ihs_fpga_set(map, member, val) \
40 regmap_set(map, struct ihs_fpga_regs, member, val)
41
42/**
43 * ihs_fpga_get() - Convenience macro to get values from FPGA register map
44 * @map: Register map to read value from
45 * @member: Name of member (described by ihs_fpga_regs) to get
46 * @valp: Pointe to variable to receive the value read
47 */
48#define ihs_fpga_get(map, member, valp) \
49 regmap_get(map, struct ihs_fpga_regs, member, valp)