]> git.sur5r.net Git - u-boot/blobdiff - board/theadorable/theadorable.c
arm: mvebu: theadorable: Add 'pcie' test command
[u-boot] / board / theadorable / theadorable.c
index ee88a98a24169c0de3a0fef2592d1e89385aaf08..9b56620e658b2bf8ba73916f84fd0864f218d203 100644 (file)
@@ -5,9 +5,13 @@
  */
 
 #include <common.h>
+#include <i2c.h>
+#include <pci.h>
+#include <asm/gpio.h>
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/soc.h>
+#include <linux/crc8.h>
 #include <linux/mbus.h>
 #ifdef CONFIG_NET
 #include <netdev.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#define MV_USB_PHY_BASE                        (MVEBU_AXP_USB_BASE + 0x800)
+#define PHY_CHANNEL_RX_CTRL0_REG(port, chan) \
+       (MV_USB_PHY_BASE + ((port) << 12) + ((chan) << 6) + 0x8)
+
 #define THEADORABLE_GPP_OUT_ENA_LOW    0x00336780
 #define THEADORABLE_GPP_OUT_ENA_MID    0x00003cf0
 #define THEADORABLE_GPP_OUT_ENA_HIGH   (~(0x0))
@@ -27,6 +35,15 @@ DECLARE_GLOBAL_DATA_PTR;
 #define THEADORABLE_GPP_OUT_VAL_MID    0x0007000c
 #define THEADORABLE_GPP_OUT_VAL_HIGH   0x00000000
 
+#define GPIO_USB0_PWR_ON               18
+#define GPIO_USB1_PWR_ON               19
+
+#define PEX_SWITCH_NOT_FOUNT_LIMIT     3
+
+#define STM_I2C_BUS    1
+#define STM_I2C_ADDR   0x27
+#define REBOOT_DELAY   1000            /* reboot-delay in ms */
+
 /* DDR3 static configuration */
 static MV_DRAM_MC_INIT ddr3_theadorable[MV_MAX_DDR3_STATIC_SIZE] = {
        {0x00001400, 0x7301ca28},       /* DDR SDRAM Configuration Register */
@@ -98,6 +115,13 @@ MV_BIN_SERDES_CFG theadorable_serdes_cfg[] = {
        },
 };
 
+/*
+ * Define a board-specific detection pulse-width array for the SerDes PCIe
+ * interfaces. If not defined in the board code, the default of currently 2
+ * is used. Values from 0...3 are possible (2 bits).
+ */
+u8 serdes_pex_pulse_width[4] = { 0, 2, 2, 2 };
+
 MV_DRAM_MODES *ddr3_get_static_ddr_mode(void)
 {
        /* Only one mode supported for this board */
@@ -109,6 +133,12 @@ MV_BIN_SERDES_CFG *board_serdes_cfg_get(u8 pex_mode)
        return &theadorable_serdes_cfg[0];
 }
 
+u8 board_sat_r_get(u8 dev_num, u8 reg)
+{
+       /* Bit 0 enables PCI 2.0 link capabilities instead of PCI 1.x */
+       return 0x01;
+}
+
 int board_early_init_f(void)
 {
        /* Configure MPP */
@@ -135,6 +165,8 @@ int board_early_init_f(void)
 
 int board_init(void)
 {
+       int ret;
+
        /* adress of boot parameters */
        gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
 
@@ -147,13 +179,33 @@ int board_init(void)
        mbus_dt_setup_win(&mbus_state, SPI_BUS1_DEV2_BASE, SPI_BUS0_DEV1_SIZE,
                          CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_SPI1_CS2);
 
+       /*
+        * Set RX Channel Control 0 Register:
+        * Tests have shown, that setting the LPF_COEF from 0 (1/8)
+        * to 3 (1/1) results in a more stable USB connection.
+        */
+       setbits_le32(PHY_CHANNEL_RX_CTRL0_REG(0, 1), 0xc);
+       setbits_le32(PHY_CHANNEL_RX_CTRL0_REG(0, 2), 0xc);
+       setbits_le32(PHY_CHANNEL_RX_CTRL0_REG(0, 3), 0xc);
+
+       /* Toggle USB power */
+       ret = gpio_request(GPIO_USB0_PWR_ON, "USB0_PWR_ON");
+       if (ret < 0)
+               return ret;
+       gpio_direction_output(GPIO_USB0_PWR_ON, 0);
+       ret = gpio_request(GPIO_USB1_PWR_ON, "USB1_PWR_ON");
+       if (ret < 0)
+               return ret;
+       gpio_direction_output(GPIO_USB1_PWR_ON, 0);
+       mdelay(1);
+       gpio_set_value(GPIO_USB0_PWR_ON, 1);
+       gpio_set_value(GPIO_USB1_PWR_ON, 1);
+
        return 0;
 }
 
 int checkboard(void)
 {
-       puts("Board: theadorable\n");
-
        board_fpga_add();
 
        return 0;
@@ -182,3 +234,104 @@ int board_video_init(void)
 
        return mvebu_lcd_register_init(&lcd_info);
 }
+
+#ifdef CONFIG_BOARD_LATE_INIT
+int board_late_init(void)
+{
+       pci_dev_t bdf;
+       ulong bootcount;
+
+       /*
+        * Check if the PEX switch is detected (somtimes its not available
+        * on the PCIe bus). In this case, try to recover by issuing a
+        * soft-reset or even a power-cycle, depending on the bootcounter
+        * value.
+        */
+       bdf = pci_find_device(PCI_VENDOR_ID_PLX, 0x8619, 0);
+       if (bdf == -1) {
+               u8 i2c_buf[8];
+               int ret;
+
+               /* PEX switch not found! */
+               bootcount = bootcount_load();
+               printf("Failed to find PLX PEX-switch (bootcount=%ld)\n",
+                      bootcount);
+               if (bootcount > PEX_SWITCH_NOT_FOUNT_LIMIT) {
+                       printf("Issuing power-switch via uC!\n");
+
+                       printf("Issuing power-switch via uC!\n");
+                       i2c_set_bus_num(STM_I2C_BUS);
+                       i2c_buf[0] = STM_I2C_ADDR << 1;
+                       i2c_buf[1] = 0xc5;      /* cmd */
+                       i2c_buf[2] = 0x01;      /* enable */
+                       /* Delay before reboot */
+                       i2c_buf[3] = REBOOT_DELAY & 0x00ff;
+                       i2c_buf[4] = (REBOOT_DELAY & 0xff00) >> 8;
+                       /* Delay before shutdown */
+                       i2c_buf[5] = 0x00;
+                       i2c_buf[6] = 0x00;
+                       i2c_buf[7] = crc8(0x72, &i2c_buf[0], 7);
+
+                       ret = i2c_write(STM_I2C_ADDR, 0, 0, &i2c_buf[1], 7);
+                       if (ret) {
+                               printf("I2C write error (ret=%d)\n", ret);
+                               printf("Issuing soft-reset...\n");
+                               /* default handling: SOFT reset */
+                               do_reset(NULL, 0, 0, NULL);
+                       }
+
+                       /* Wait for power-cycle to occur... */
+                       printf("Waiting for power-cycle via uC...\n");
+                       while (1)
+                               ;
+               } else {
+                       printf("Issuing soft-reset...\n");
+                       /* default handling: SOFT reset */
+                       do_reset(NULL, 0, 0, NULL);
+               }
+       }
+
+       return 0;
+}
+#endif
+
+#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_PCI)
+int do_pcie_test(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       pci_dev_t bdf;
+       u16 ven_id, dev_id;
+
+       if (argc != 3)
+               return cmd_usage(cmdtp);
+
+       ven_id = simple_strtoul(argv[1], NULL, 16);
+       dev_id = simple_strtoul(argv[2], NULL, 16);
+
+       printf("Checking for PCIe device: VendorID 0x%04x, DeviceId 0x%04x\n",
+              ven_id, dev_id);
+
+       /*
+        * Check if the PCIe device is detected (somtimes its not available
+        * on the PCIe bus)
+        */
+       bdf = pci_find_device(ven_id, dev_id, 0);
+       if (bdf == -1) {
+               /* PCIe device not found! */
+               printf("Failed to find PCIe device\n");
+       } else {
+               /* PCIe device found! */
+               printf("PCIe device found, resetting board...\n");
+
+               /* default handling: SOFT reset */
+               do_reset(NULL, 0, 0, NULL);
+       }
+
+       return 0;
+}
+
+U_BOOT_CMD(
+       pcie,   3,   0,     do_pcie_test,
+       "Test for presence of a PCIe device",
+       "<VendorID> <DeviceID>"
+);
+#endif