| // SPDX-License-Identifier: GPL-2.0+ |
| /* |
| * (C) Copyright 2013 Keymile AG |
| * Valentin Longchamp <valentin.longchamp@keymile.com> |
| * |
| * Copyright 2007-2011 Freescale Semiconductor, Inc. |
| */ |
| |
| #include <common.h> |
| #include <command.h> |
| #include <init.h> |
| #include <pci.h> |
| #include <asm/fsl_pci.h> |
| #include <linux/libfdt.h> |
| #include <fdt_support.h> |
| #include <asm/fsl_serdes.h> |
| #include <linux/errno.h> |
| |
| #include "../common/qrio.h" |
| #include "kmp204x.h" |
| |
| #define PROM_SEL_L 11 |
| /* control the PROM_SEL_L signal*/ |
| static void toggle_fpga_eeprom_bus(bool cpu_own) |
| { |
| qrio_gpio_direction_output(QRIO_GPIO_A, PROM_SEL_L, !cpu_own); |
| } |
| |
| #define CONF_SEL_L 10 |
| #define FPGA_PROG_L 19 |
| #define FPGA_DONE 18 |
| #define FPGA_INIT_L 17 |
| |
| int trigger_fpga_config(void) |
| { |
| int ret = 0, init_l; |
| /* approx 10ms */ |
| u32 timeout = 10000; |
| |
| /* make sure the FPGA_can access the EEPROM */ |
| toggle_fpga_eeprom_bus(false); |
| |
| /* assert CONF_SEL_L to be able to drive FPGA_PROG_L */ |
| qrio_gpio_direction_output(QRIO_GPIO_A, CONF_SEL_L, 0); |
| |
| /* trigger the config start */ |
| qrio_gpio_direction_output(QRIO_GPIO_A, FPGA_PROG_L, 0); |
| |
| /* small delay for INIT_L line */ |
| udelay(10); |
| |
| /* wait for FPGA_INIT to be asserted */ |
| do { |
| init_l = qrio_get_gpio(QRIO_GPIO_A, FPGA_INIT_L); |
| if (timeout-- == 0) { |
| printf("FPGA_INIT timeout\n"); |
| ret = -EFAULT; |
| break; |
| } |
| udelay(10); |
| } while (init_l); |
| |
| /* deassert FPGA_PROG, config should start */ |
| qrio_set_gpio(QRIO_GPIO_A, FPGA_PROG_L, 1); |
| |
| return ret; |
| } |
| |
| /* poll the FPGA_DONE signal and give the EEPROM back to the QorIQ */ |
| static int wait_for_fpga_config(void) |
| { |
| int ret = 0, done; |
| /* approx 5 s */ |
| u32 timeout = 500000; |
| |
| printf("PCIe FPGA config:"); |
| do { |
| done = qrio_get_gpio(QRIO_GPIO_A, FPGA_DONE); |
| if (timeout-- == 0) { |
| printf(" FPGA_DONE timeout\n"); |
| ret = -EFAULT; |
| goto err_out; |
| } |
| udelay(10); |
| } while (!done); |
| |
| printf(" done\n"); |
| |
| err_out: |
| /* deactive CONF_SEL and give the CPU conf EEPROM access */ |
| qrio_set_gpio(QRIO_GPIO_A, CONF_SEL_L, 1); |
| toggle_fpga_eeprom_bus(true); |
| |
| return ret; |
| } |
| |
| #define PCIE_SW_RST 14 |
| #define PEXHC_RST 13 |
| #define HOOPER_RST 12 |
| |
| void pci_init_board(void) |
| { |
| qrio_prstcfg(PCIE_SW_RST, PRSTCFG_POWUP_UNIT_CORE_RST); |
| qrio_prstcfg(PEXHC_RST, PRSTCFG_POWUP_UNIT_CORE_RST); |
| qrio_prstcfg(HOOPER_RST, PRSTCFG_POWUP_UNIT_CORE_RST); |
| |
| /* wait for the PCIe FPGA to be configured |
| * it has been triggered earlier in board_early_init_r */ |
| if (wait_for_fpga_config()) |
| printf("error finishing PCIe FPGA config\n"); |
| |
| qrio_prst(PCIE_SW_RST, false, false); |
| qrio_prst(PEXHC_RST, false, false); |
| qrio_prst(HOOPER_RST, false, false); |
| /* Hooper is not direcly PCIe capable */ |
| mdelay(50); |
| |
| fsl_pcie_init_board(0); |
| } |
| |
| void pci_of_setup(void *blob, bd_t *bd) |
| { |
| FT_FSL_PCI_SETUP; |
| } |