15bbc810a1b650cc64ea1576d8652863469033c6
[oweals/u-boot.git] / board / keymile / kmp204x / pci.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2013 Keymile AG
4  * Valentin Longchamp <valentin.longchamp@keymile.com>
5  *
6  * Copyright 2007-2011 Freescale Semiconductor, Inc.
7  */
8
9 #include <common.h>
10 #include <command.h>
11 #include <init.h>
12 #include <pci.h>
13 #include <asm/fsl_pci.h>
14 #include <linux/libfdt.h>
15 #include <fdt_support.h>
16 #include <asm/fsl_serdes.h>
17 #include <linux/errno.h>
18
19 #include "../common/qrio.h"
20 #include "kmp204x.h"
21
22 #define PROM_SEL_L      11
23 /* control the PROM_SEL_L signal*/
24 static void toggle_fpga_eeprom_bus(bool cpu_own)
25 {
26         qrio_gpio_direction_output(QRIO_GPIO_A, PROM_SEL_L, !cpu_own);
27 }
28
29 #define CONF_SEL_L      10
30 #define FPGA_PROG_L     19
31 #define FPGA_DONE       18
32 #define FPGA_INIT_L     17
33
34 int trigger_fpga_config(void)
35 {
36         int ret = 0, init_l;
37         /* approx 10ms */
38         u32 timeout = 10000;
39
40         /* make sure the FPGA_can access the EEPROM */
41         toggle_fpga_eeprom_bus(false);
42
43         /* assert CONF_SEL_L to be able to drive FPGA_PROG_L */
44         qrio_gpio_direction_output(QRIO_GPIO_A, CONF_SEL_L, 0);
45
46         /* trigger the config start */
47         qrio_gpio_direction_output(QRIO_GPIO_A, FPGA_PROG_L, 0);
48
49         /* small delay for INIT_L line */
50         udelay(10);
51
52         /* wait for FPGA_INIT to be asserted */
53         do {
54                 init_l = qrio_get_gpio(QRIO_GPIO_A, FPGA_INIT_L);
55                 if (timeout-- == 0) {
56                         printf("FPGA_INIT timeout\n");
57                         ret = -EFAULT;
58                         break;
59                 }
60                 udelay(10);
61         } while (init_l);
62
63         /* deassert FPGA_PROG, config should start */
64         qrio_set_gpio(QRIO_GPIO_A, FPGA_PROG_L, 1);
65
66         return ret;
67 }
68
69 /* poll the FPGA_DONE signal and give the EEPROM back to the QorIQ */
70 static int wait_for_fpga_config(void)
71 {
72         int ret = 0, done;
73         /* approx 5 s */
74         u32 timeout = 500000;
75
76         printf("PCIe FPGA config:");
77         do {
78                 done = qrio_get_gpio(QRIO_GPIO_A, FPGA_DONE);
79                 if (timeout-- == 0) {
80                         printf(" FPGA_DONE timeout\n");
81                         ret = -EFAULT;
82                         goto err_out;
83                 }
84                 udelay(10);
85         } while (!done);
86
87         printf(" done\n");
88
89 err_out:
90         /* deactive CONF_SEL and give the CPU conf EEPROM access */
91         qrio_set_gpio(QRIO_GPIO_A, CONF_SEL_L, 1);
92         toggle_fpga_eeprom_bus(true);
93
94         return ret;
95 }
96
97 #define PCIE_SW_RST     14
98 #define PEXHC_RST       13
99 #define HOOPER_RST      12
100
101 void pci_init_board(void)
102 {
103         qrio_prstcfg(PCIE_SW_RST, PRSTCFG_POWUP_UNIT_CORE_RST);
104         qrio_prstcfg(PEXHC_RST, PRSTCFG_POWUP_UNIT_CORE_RST);
105         qrio_prstcfg(HOOPER_RST, PRSTCFG_POWUP_UNIT_CORE_RST);
106
107         /* wait for the PCIe FPGA to be configured
108          * it has been triggered earlier in board_early_init_r */
109         if (wait_for_fpga_config())
110                 printf("error finishing PCIe FPGA config\n");
111
112         qrio_prst(PCIE_SW_RST, false, false);
113         qrio_prst(PEXHC_RST, false, false);
114         qrio_prst(HOOPER_RST, false, false);
115         /* Hooper is not direcly PCIe capable */
116         mdelay(50);
117
118         fsl_pcie_init_board(0);
119 }
120
121 void pci_of_setup(void *blob, bd_t *bd)
122 {
123         FT_FSL_PCI_SETUP;
124 }