common: Drop linux/delay.h from common header
[oweals/u-boot.git] / board / toradex / apalis-tk1 / apalis-tk1.c
index c7e519c19b5b28ca78d4c8b70458e9864db43eaa..d77b4c4ab9c88780a5963abfd76061c09328caed 100644 (file)
@@ -1,21 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
- * Copyright (c) 2016 Toradex, Inc.
- *
- * SPDX-License-Identifier:    GPL-2.0+
+ * Copyright (c) 2016-2018 Toradex, Inc.
  */
 
 #include <common.h>
+#include <dm.h>
+#include <env.h>
+#include <init.h>
+#include <log.h>
 #include <asm/arch-tegra/ap.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/pinmux.h>
+#include <env_internal.h>
+#include <pci_tegra.h>
+#include <linux/delay.h>
 #include <power/as3722.h>
+#include <power/pmic.h>
 
 #include "../common/tdx-common.h"
 #include "pinmux-config-apalis-tk1.h"
 
-#define LAN_RESET_N TEGRA_GPIO(S, 2)
+#define LAN_DEV_OFF_N  TEGRA_GPIO(O, 6)
+#define LAN_RESET_N    TEGRA_GPIO(S, 2)
+#define FAN_EN         TEGRA_GPIO(DD, 2)
+#define LAN_WAKE_N     TEGRA_GPIO(O, 5)
+#ifdef CONFIG_APALIS_TK1_PCIE_EVALBOARD_INIT
+#define PEX_PERST_N    TEGRA_GPIO(DD, 1) /* Apalis GPIO7 */
+#define RESET_MOCI_CTRL        TEGRA_GPIO(U, 4)
+#endif /* CONFIG_APALIS_TK1_PCIE_EVALBOARD_INIT */
+#define VCC_USBH       TEGRA_GPIO(T, 6)
+#define VCC_USBH_V1_0  TEGRA_GPIO(N, 5)
+#define VCC_USBO1      TEGRA_GPIO(T, 5)
+#define VCC_USBO1_V1_0 TEGRA_GPIO(N, 4)
 
 int arch_misc_init(void)
 {
@@ -23,6 +41,38 @@ int arch_misc_init(void)
            NVBOOTTYPE_RECOVERY)
                printf("USB recovery mode\n");
 
+       /* PCB Version Indication: V1.2 and later have GPIO_PV0 wired to GND */
+       gpio_request(TEGRA_GPIO(V, 0), "PCB Version Indication");
+       gpio_direction_input(TEGRA_GPIO(V, 0));
+       if (gpio_get_value(TEGRA_GPIO(V, 0))) {
+               /*
+                * if using the default device tree for new V1.2 and later HW,
+                * use version for older V1.0 and V1.1 HW
+                */
+               char *fdt_env = env_get("fdt_module");
+
+               if (fdt_env && !strcmp(FDT_MODULE, fdt_env)) {
+                       env_set("fdt_module", FDT_MODULE_V1_0);
+                       printf("patching fdt_module to " FDT_MODULE_V1_0
+                              " for older V1.0 and V1.1 HW\n");
+#ifndef CONFIG_ENV_IS_NOWHERE
+                       env_save();
+#endif
+               }
+
+               /* activate USB power enable GPIOs */
+               gpio_request(VCC_USBH_V1_0, "VCC_USBH");
+               gpio_direction_output(VCC_USBH_V1_0, 1);
+               gpio_request(VCC_USBO1_V1_0, "VCC_USBO1");
+               gpio_direction_output(VCC_USBO1_V1_0, 1);
+       } else {
+               /* activate USB power enable GPIOs */
+               gpio_request(VCC_USBH, "VCC_USBH");
+               gpio_direction_output(VCC_USBH, 1);
+               gpio_request(VCC_USBO1, "VCC_USBO1");
+               gpio_direction_output(VCC_USBO1, 1);
+       }
+
        return 0;
 }
 
@@ -59,117 +109,194 @@ void pinmux_init(void)
 }
 
 #ifdef CONFIG_PCI_TEGRA
-int tegra_pcie_board_init(void)
+/* TODO: Convert to driver model */
+static int as3722_sd_enable(struct udevice *pmic, unsigned int sd)
 {
-       struct udevice *pmic;
        int err;
 
-       err = as3722_init(&pmic);
+       if (sd > 6)
+               return -EINVAL;
+
+       err = pmic_clrsetbits(pmic, AS3722_SD_CONTROL, 0, 1 << sd);
        if (err) {
-               error("failed to initialize AS3722 PMIC: %d\n", err);
+               pr_err("failed to update SD control register: %d", err);
                return err;
        }
 
-       err = as3722_sd_enable(pmic, 4);
-       if (err < 0) {
-               error("failed to enable SD4: %d\n", err);
-               return err;
-       }
+       return 0;
+}
 
-       err = as3722_sd_set_voltage(pmic, 4, 0x24);
-       if (err < 0) {
-               error("failed to set SD4 voltage: %d\n", err);
-               return err;
-       }
+/* TODO: Convert to driver model */
+static int as3722_ldo_enable(struct udevice *pmic, unsigned int ldo)
+{
+       int err;
+       u8 ctrl_reg = AS3722_LDO_CONTROL0;
 
-       err = as3722_gpio_configure(pmic, 1, AS3722_GPIO_OUTPUT_VDDH |
-                                            AS3722_GPIO_INVERT);
-       if (err < 0) {
-               error("failed to configure GPIO#1 as output: %d\n", err);
-               return err;
-       }
+       if (ldo > 11)
+               return -EINVAL;
 
-       err = as3722_gpio_direction_output(pmic, 2, 1);
-       if (err < 0) {
-               error("failed to set GPIO#2 high: %d\n", err);
-               return err;
+       if (ldo > 7) {
+               ctrl_reg = AS3722_LDO_CONTROL1;
+               ldo -= 8;
        }
 
-       /* Reset I210 Gigabit Ethernet Controller */
-       gpio_request(LAN_RESET_N, "LAN_RESET_N");
-       gpio_direction_output(LAN_RESET_N, 0);
-
-       /*
-        * Make sure we don't get any back feeding from LAN_WAKE_N resp.
-        * DEV_OFF_N
-        */
-       gpio_request(TEGRA_GPIO(O, 5), "LAN_WAKE_N");
-       gpio_direction_output(TEGRA_GPIO(O, 5), 0);
-
-       gpio_request(TEGRA_GPIO(O, 6), "LAN_DEV_OFF_N");
-       gpio_direction_output(TEGRA_GPIO(O, 6), 0);
-
-       /* Make sure LDO9 and LDO10 are initially enabled @ 0V */
-       err = as3722_ldo_enable(pmic, 9);
-       if (err < 0) {
-               error("failed to enable LDO9: %d\n", err);
-               return err;
-       }
-       err = as3722_ldo_enable(pmic, 10);
-       if (err < 0) {
-               error("failed to enable LDO10: %d\n", err);
-               return err;
-       }
-       err = as3722_ldo_set_voltage(pmic, 9, 0x80);
-       if (err < 0) {
-               error("failed to set LDO9 voltage: %d\n", err);
-               return err;
-       }
-       err = as3722_ldo_set_voltage(pmic, 10, 0x80);
-       if (err < 0) {
-               error("failed to set LDO10 voltage: %d\n", err);
+       err = pmic_clrsetbits(pmic, ctrl_reg, 0, 1 << ldo);
+       if (err) {
+               pr_err("failed to update LDO control register: %d", err);
                return err;
        }
 
-       mdelay(100);
+       return 0;
+}
 
-       /* Make sure controller gets enabled by disabling DEV_OFF_N */
-       gpio_set_value(TEGRA_GPIO(O, 6), 1);
+int tegra_pcie_board_init(void)
+{
+       struct udevice *dev;
+       int ret;
 
-       /* Enable LDO9 and LDO10 for +V3.3_ETH on patched prototypes */
-       err = as3722_ldo_set_voltage(pmic, 9, 0xff);
-       if (err < 0) {
-               error("failed to set LDO9 voltage: %d\n", err);
-               return err;
+       ret = uclass_get_device_by_driver(UCLASS_PMIC,
+                                         DM_GET_DRIVER(pmic_as3722), &dev);
+       if (ret) {
+               pr_err("failed to find AS3722 PMIC: %d\n", ret);
+               return ret;
        }
-       err = as3722_ldo_set_voltage(pmic, 10, 0xff);
-       if (err < 0) {
-               error("failed to set LDO10 voltage: %d\n", err);
-               return err;
+
+       ret = as3722_sd_enable(dev, 4);
+       if (ret < 0) {
+               pr_err("failed to enable SD4: %d\n", ret);
+               return ret;
        }
 
-       mdelay(100);
-       gpio_set_value(LAN_RESET_N, 1);
+       ret = as3722_sd_set_voltage(dev, 4, 0x24);
+       if (ret < 0) {
+               pr_err("failed to set SD4 voltage: %d\n", ret);
+               return ret;
+       }
 
-#ifdef APALIS_TK1_PCIE_EVALBOARD_INIT
-#define PEX_PERST_N    TEGRA_GPIO(DD, 1) /* Apalis GPIO7 */
-#define RESET_MOCI_CTRL        TEGRA_GPIO(U, 4)
+       gpio_request(LAN_DEV_OFF_N, "LAN_DEV_OFF_N");
+       gpio_request(LAN_RESET_N, "LAN_RESET_N");
+       gpio_request(LAN_WAKE_N, "LAN_WAKE_N");
 
-       /* Reset PLX PEX 8605 PCIe Switch plus PCIe devices on Apalis Evaluation
-          Board */
+#ifdef CONFIG_APALIS_TK1_PCIE_EVALBOARD_INIT
        gpio_request(PEX_PERST_N, "PEX_PERST_N");
        gpio_request(RESET_MOCI_CTRL, "RESET_MOCI_CTRL");
-       gpio_direction_output(PEX_PERST_N, 0);
-       gpio_direction_output(RESET_MOCI_CTRL, 0);
-       /* Must be asserted for 100 ms after power and clocks are stable */
-       mdelay(100);
-       gpio_set_value(PEX_PERST_N, 1);
-       /* Err_5: PEX_REFCLK_OUTpx/nx Clock Outputs is not Guaranteed Until
-          900 us After PEX_PERST# De-assertion */
-       mdelay(1);
-       gpio_set_value(RESET_MOCI_CTRL, 1);
-#endif /* APALIS_T30_PCIE_EVALBOARD_INIT */
+#endif /* CONFIG_APALIS_TK1_PCIE_EVALBOARD_INIT */
 
        return 0;
 }
+
+void tegra_pcie_board_port_reset(struct tegra_pcie_port *port)
+{
+       int index = tegra_pcie_port_index_of_port(port);
+
+       if (index == 1) { /* I210 Gigabit Ethernet Controller (On-module) */
+               struct udevice *dev;
+               int ret;
+
+               ret = uclass_get_device_by_driver(UCLASS_PMIC,
+                                                 DM_GET_DRIVER(pmic_as3722),
+                                                 &dev);
+               if (ret) {
+                       debug("%s: Failed to find PMIC\n", __func__);
+                       return;
+               }
+
+               /* Reset I210 Gigabit Ethernet Controller */
+               gpio_direction_output(LAN_RESET_N, 0);
+
+               /*
+                * Make sure we don't get any back feeding from DEV_OFF_N resp.
+                * LAN_WAKE_N
+                */
+               gpio_direction_output(LAN_DEV_OFF_N, 0);
+               gpio_direction_output(LAN_WAKE_N, 0);
+
+               /* Make sure LDO9 and LDO10 are initially enabled @ 0V */
+               ret = as3722_ldo_enable(dev, 9);
+               if (ret < 0) {
+                       pr_err("failed to enable LDO9: %d\n", ret);
+                       return;
+               }
+               ret = as3722_ldo_enable(dev, 10);
+               if (ret < 0) {
+                       pr_err("failed to enable LDO10: %d\n", ret);
+                       return;
+               }
+               ret = as3722_ldo_set_voltage(dev, 9, 0x80);
+               if (ret < 0) {
+                       pr_err("failed to set LDO9 voltage: %d\n", ret);
+                       return;
+               }
+               ret = as3722_ldo_set_voltage(dev, 10, 0x80);
+               if (ret < 0) {
+                       pr_err("failed to set LDO10 voltage: %d\n", ret);
+                       return;
+               }
+
+               /* Make sure controller gets enabled by disabling DEV_OFF_N */
+               gpio_set_value(LAN_DEV_OFF_N, 1);
+
+               /*
+                * Enable LDO9 and LDO10 for +V3.3_ETH on patched prototype
+                * V1.0A and sample V1.0B and newer modules
+                */
+               ret = as3722_ldo_set_voltage(dev, 9, 0xff);
+               if (ret < 0) {
+                       pr_err("failed to set LDO9 voltage: %d\n", ret);
+                       return;
+               }
+               ret = as3722_ldo_set_voltage(dev, 10, 0xff);
+               if (ret < 0) {
+                       pr_err("failed to set LDO10 voltage: %d\n", ret);
+                       return;
+               }
+
+               /*
+                * Must be asserted for 100 ms after power and clocks are stable
+                */
+               mdelay(100);
+
+               gpio_set_value(LAN_RESET_N, 1);
+       } else if (index == 0) { /* Apalis PCIe */
+#ifdef CONFIG_APALIS_TK1_PCIE_EVALBOARD_INIT
+               /*
+                * Reset PLX PEX 8605 PCIe Switch plus PCIe devices on Apalis
+                * Evaluation Board
+                */
+               gpio_direction_output(PEX_PERST_N, 0);
+               gpio_direction_output(RESET_MOCI_CTRL, 0);
+
+               /*
+                * Must be asserted for 100 ms after power and clocks are stable
+                */
+               mdelay(100);
+
+               gpio_set_value(PEX_PERST_N, 1);
+               /*
+                * Err_5: PEX_REFCLK_OUTpx/nx Clock Outputs is not Guaranteed
+                * Until 900 us After PEX_PERST# De-assertion
+                */
+               mdelay(1);
+               gpio_set_value(RESET_MOCI_CTRL, 1);
+#endif /* CONFIG_APALIS_TK1_PCIE_EVALBOARD_INIT */
+       }
+}
 #endif /* CONFIG_PCI_TEGRA */
+
+/*
+ * Enable/start PWM CPU fan
+ */
+void start_cpu_fan(void)
+{
+       gpio_request(FAN_EN, "FAN_EN");
+       gpio_direction_output(FAN_EN, 1);
+}
+
+/*
+ * Backlight off before OS handover
+ */
+void board_preboot_os(void)
+{
+       gpio_request(TEGRA_GPIO(BB, 5), "BL_ON");
+       gpio_direction_output(TEGRA_GPIO(BB, 5), 0);
+}