u-boot/board/nm/hw14/nbhw_fpga_config.c

235 lines
4.7 KiB
C

#undef DEBUG
#include <common.h>
#include <dm.h>
#include <dm/device.h>
#include <dm/ofnode.h>
#include <asm/gpio.h>
#include <asm/io.h>
#include <errno.h>
#include "../common/nbhw_bd.h"
#include "../common/nbhw_sim.h"
#include "nbhw_gpio.h"
DECLARE_GLOBAL_DATA_PTR;
struct gpio_desc leds[16];
struct udevice *driver_dev;
struct config_priv {
u32 led_count;
} priv;
typedef enum {
TYPE_USB,
TYPE_USB3,
TYPE_PCIE,
} slot_type_t;
struct pcie_slot_gpios {
struct gpio_desc reset;
struct gpio_desc power;
struct gpio_desc wdis_out;
struct gpio_desc wdis;
};
#define PCIE_SLOT_COUNT 8
static struct pcie_slot_gpios pcie_slots[PCIE_SLOT_COUNT];
static int pcie_slot_count = 0;
int pcie_lane_by_slot(int slot);
static int request_and_set_gpio_by_name(ofnode fdt,
const char *name, struct gpio_desc *desc)
{
int default_value = 0;
u32 gpio_array[4];
debug("%s\n", __func__);
/* Request the gpio described by the property */
if (gpio_request_by_name_nodev(fdt, name, 0, desc,
GPIOD_IS_OUT))
{
debug("Could not request gpio %s\n", name);
return -1;
}
/* Get the gpio array, to find out its default value (4 index) */
if (ofnode_read_u32_array(fdt, name, gpio_array, 4)) {
printf("Could not request gpio array %s\n", name);
return -1;
}
default_value = gpio_array[3];
debug("Set GPIO %s to %d\n", name, default_value);
dm_gpio_set_value(desc, default_value);
return 0;
}
static int add_pcie_slot(ofnode fdt)
{
debug("%s\n", __func__);
request_and_set_gpio_by_name(fdt, "power",
&pcie_slots[pcie_slot_count].power);
request_and_set_gpio_by_name(fdt, "reset",
&pcie_slots[pcie_slot_count].reset);
request_and_set_gpio_by_name(fdt, "wdis-out",
&pcie_slots[pcie_slot_count].wdis_out);
request_and_set_gpio_by_name(fdt, "wdis",
&pcie_slots[pcie_slot_count].wdis);
pcie_slot_count++;
return 0;
}
static void configure_pcie_muxes(void)
{
/* Disable PCI clock and serdes4 routing unless
explicitly requested later. */
set_gpio(GPIO_SERDES4_MUX_EN, 0);
set_gpio(GPIO_PEX2_CLK_1_4_MUX_EN, 0);
/* Check for PCIe on slot 1 */
if (pcie_lane_by_slot(1) >= 0) {
// PEX2 is on slot 1
// mux serdes4 to slot 1 pci pins
set_gpio(GPIO_SERDES4_MUX_SEL, 1);
set_gpio(GPIO_SERDES4_MUX_EN, 1);
// route PEX2 clock to slot 1
set_gpio(GPIO_PEX2_CLK_1_4_MUX_SEL, 1);
set_gpio(GPIO_PEX2_CLK_1_4_MUX_EN, 1);
} else {
// mux serdes4 to slot 1 usb 3.0 pins
set_gpio(GPIO_SERDES4_MUX_SEL, 0);
set_gpio(GPIO_SERDES4_MUX_EN, 1);
}
/* Check for PCIe on slot 4 */
if (pcie_lane_by_slot(4) >= 0) {
// PEX2 is on slot 4
// route PEX2 clock to slot 4
set_gpio(GPIO_PEX2_CLK_1_4_MUX_SEL, 0);
set_gpio(GPIO_PEX2_CLK_1_4_MUX_EN, 1);
}
}
static int configure_pcie_slots(void)
{
int i;
configure_pcie_muxes();
configure_sim_slots(6);
udelay(1200000); /* 1.2 s */
/* Apply power to all PCIe slots */
for (i = 0; i < pcie_slot_count; i++) {
dm_gpio_set_value(&pcie_slots[i].power, 1);
udelay(200000); /* 200 ms */
}
/* Assert reset after power is enabled */
for (i = 0; i < pcie_slot_count; i++) {
dm_gpio_set_value(&pcie_slots[i].reset, 1);
}
/* Deactivate WDIS */
for (i = 0; i < pcie_slot_count; i++) {
dm_gpio_set_value(&pcie_slots[i].wdis_out, 1);
dm_gpio_set_value(&pcie_slots[i].wdis, 0);
udelay(2000); /* 2 ms needed by Reyax module as regulator is enabled by WDIS~*/
}
udelay(12000); /* 12 ms */
/* Deassert reset */
for (i = 0; i < pcie_slot_count; i++) {
dm_gpio_set_value(&pcie_slots[i].reset, 0);
}
pci_init_board();
return 0;
}
static int configure_leds(void)
{
int i;
int led_count;
led_count = gpio_request_list_by_name(driver_dev, "leds", leds,
ARRAY_SIZE(leds), GPIOD_IS_OUT);
dm_gpio_set_value(&leds[0], 1);
for (i = 1; i < ARRAY_SIZE(leds); i++) {
dm_gpio_set_value(&leds[i], 0);
}
priv.led_count = led_count;
return 0;
}
void set_led(int index, int value)
{
if ((index<0) || (index>=priv.led_count)) return;
dm_gpio_set_value(&leds[index], value);
}
int nbhw_fpga_configure(void)
{
ofnode subnode;
ofnode node = driver_dev->node;
debug("%s\n", __func__);
ofnode_for_each_subnode(subnode, node) {
const char *name;
name = ofnode_get_name(subnode);
debug("Try to configure %s\n", name);
if (!strncmp("pcieslot", name, 8)) {
add_pcie_slot(subnode);
}
}
if (configure_leds())
return -1;
if (configure_pcie_slots()) {
return -1;
}
return 0;
}
static int nbhw_fpga_config_bind(struct udevice *dev)
{
debug("%s\n", __func__);
driver_dev = dev;
return 0;
}
static const struct udevice_id nbhw_fpga_config_ids[] = {
{ .compatible = "nm,hw14-fpga-config" },
{ }
};
U_BOOT_DRIVER(gpio_nbhw_fpga_config) = {
.name = "hw14_fpga_config",
.id = UCLASS_ROOT,
.of_match = nbhw_fpga_config_ids,
.bind = nbhw_fpga_config_bind,
};