LC15: add board revision detection and control of (new) eMMC/uSD switch
authorH. Nikolaus Schaller <hns@goldelico.com>
Sun, 13 Mar 2016 09:05:17 +0000 (10:05 +0100)
committernotaz <notasas@gmail.com>
Sun, 14 Aug 2016 13:43:31 +0000 (16:43 +0300)
Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
board/goldelico/letux-cortex15/lc15.c

index 764979c..faa1a09 100644 (file)
@@ -57,6 +57,79 @@ int board_mmc_init(bd_t *bis)
 
 #endif
 
+/*
+ * Board Revision Detection
+ *
+ * gpio2_32 and gpio2_33 can optionally be pulled up or down
+ * by 10k resistors. These are stronger than the internal
+ * pull-up or pull-down resistors of the omap5 pads.
+ * by trying to pull them up/down and check who wins, we
+ * can find out which resistors are installed.
+ * If no resistor is installed, the gpio value follows the
+ * omap5 pull-up or -down.
+ * Which resistors are installed changes from board revision
+ * to board revision (see schematics).
+ */
+
+const struct pad_conf_entry padconf_version_pd_lc15[] = {
+       {LLIB_WAKEREQOUT, (IEN | PTD | M6)}, /* gpio 2_32 */
+       {C2C_CLKOUT0, (IEN | PTD | M6)}, /* gpio 2_33 */
+};
+
+const struct pad_conf_entry padconf_version_pu_lc15[] = {
+       {LLIB_WAKEREQOUT, (IEN | PTU | M6)}, /* gpio 2_32 */
+       {C2C_CLKOUT0, (IEN | PTU | M6)}, /* gpio 2_33 */
+};
+
+/* operational mode */
+const struct pad_conf_entry padconf_version_operation_lc15[] = {
+       {LLIB_WAKEREQOUT, (IEN | M6)}, /* gpio 2_32 */
+       {C2C_CLKOUT0, (IEN | M6)}, /* gpio 2_33 */
+};
+
+const int versions[]={
+       [0xc] = 49,     /* no resistors */
+       [0xd] = 50,     /* gpio2_32 pu, gpio2_33 floating */
+       [0x8] = 51,     /* gpio2_32 pd, gpio2_33 floating */
+       [0xe] = 0,      /* gpio2_32 floating, gpio2_33 pu */
+       [0x4] = 0,      /* gpio2_32 floating, gpio2_33 pd */
+       [0x0] = 0,      /* gpio2_32 pd, gpio2_33 pd */
+       [0x5] = 0,      /* gpio2_32 pu, gpio2_33 pd */
+       [0xa] = 0,      /* gpio2_32 pd, gpio2_33 pu */
+       [0xf] = 0,      /* gpio2_32 pu, gpio2_33 pu */
+};
+
+int get_board_version(void)
+{ /* read get board version from resistors */
+       static int vers;
+       if (!vers) {
+               gpio_request(32, "version-0");  /* version resistors */
+               gpio_request(33, "version-1");
+               do_set_mux((*ctrl)->control_padconf_core_base,
+                          padconf_version_pd_lc15,
+                          sizeof(padconf_version_pd_lc15) /
+                          sizeof(struct pad_conf_entry));
+               vers = gpio_get_value(32) | (gpio_get_value(33) << 1);
+               do_set_mux((*ctrl)->control_padconf_core_base,
+                          padconf_version_pu_lc15,
+                          sizeof(padconf_version_pu_lc15) /
+                          sizeof(struct pad_conf_entry));
+               vers |= (gpio_get_value(32) << 2) | (gpio_get_value(33) << 3);
+               gpio_free(32);
+               gpio_free(33);
+               do_set_mux((*ctrl)->control_padconf_core_base,
+                          padconf_version_operation_lc15,
+                          sizeof(padconf_version_operation_lc15) /
+                          sizeof(struct pad_conf_entry));
+#if 1
+               printf("version code 0x%01x\n", vers);
+#endif
+               vers = versions[vers&0xf];
+               printf("LC15 V%d.%d\n", vers/10, vers%10);
+       }
+       return vers;
+}
+
 /* SPL only code */
 #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_OS_BOOT)
 
@@ -67,39 +140,76 @@ int board_mmc_init(bd_t *bis)
  * throwing the eMMC/uSD switch.
  */
 
-const struct pad_conf_entry wkupconf_mmcmux_pyra[] = {
-       {DRM_EMU1, (IEN | M6)}, /* gpio 1_wk7 */
+const struct pad_conf_entry wkupconf_mmcmux_lc15[] = {
+       {DRM_EMU1, (IEN | PTU | M6)}, /* gpio 1_wk7 */
 };
 
-const struct pad_conf_entry padconf_mmcmux_pyra[] = {
-       {HSI2_ACFLAG, (IDIS | M6)}, /* gpio 3_82 */
+const struct pad_conf_entry padconf_mmcmux_lc15[] = {
+       {HSI2_ACFLAG, (IEN | M6)}, /* gpio 3_82 */
+       {HSI2_CAREADY, (IEN | M6)}, /* gpio 3_76 */
+};
+
+/* board revision 5.0 uses different gpios */
+
+const struct pad_conf_entry padconf_mmcmux_lc15_50[] = {
 };
 
 int set_mmc_switch(void)
 {
        int val;
+       int vers = get_board_version();
+       int hard_select = 7;    /* gpio to select uSD or eMMC by external hw signal */
+       int soft_select = 86;   /* gpio to select uSD or eMMC */
+       int control = 76;       /* control between SW and HW select */
+#if 0
        printf("set_mmc_switch for LC15 called\n");
-       /* make gpio1_wk7 an input */
+#endif
+       if (vers <= 49)
+               return 1;
+       if (vers <= 50) {
+               /* board revision 5.0 shares the revision gpios with mmc_switch control */
+               soft_select = 32;
+               control = 33;
+       }
+
+       gpio_request(hard_select, "bootsel");           /* BOOTSEL button */
+       gpio_request(soft_select, "soft-select");       /* choose uSD and not eMMC */
+       gpio_request(control, "mmc-control");   /* MMC switch control */
+
+       /* make gpio1_wk7 an input so that we can read the state of the BOOTSEL button */
        do_set_mux((*ctrl)->control_padconf_wkup_base,
-                  wkupconf_mmcmux_pyra,
-                  sizeof(wkupconf_mmcmux_pyra) /
-                  sizeof(struct pad_conf_entry));
-       gpio_request(7, "gpio1_wk7");   /* BOOTSEL button */
-       gpio_request(82, "gpio3_82");   /* MMC switch control */
-       val = gpio_get_value(7);        /* BOOTSEL pressed? */
-       printk("  gpio7 = %d\n", val);
-       gpio_direction_output(82, !val);        /* pass button setting to output */
-       /* go from High-Z to low L to make it really an output
-        * overriding the hardware defined state from the BOOTSEL button
-        */
-       do_set_mux((*ctrl)->control_padconf_core_base,
-                  padconf_mmcmux_pyra,
-                  sizeof(padconf_mmcmux_pyra) /
+                  wkupconf_mmcmux_lc15,
+                  sizeof(wkupconf_mmcmux_lc15) /
                   sizeof(struct pad_conf_entry));
+
+       /* is BOOTSEL active? Then we did boot SPL from µSD */
+       val = gpio_get_value(hard_select);
+
+#if 1
+       printk("  gpio%d = %s\n", hard_select, val?"eMMC":"uSD");
+#endif
+
+       /* pass hard-select to soft-select so that the user can release/press the button */
+       gpio_direction_output(soft_select, !val);
+       /* switch to soft control */
+       gpio_direction_output(control, 1);
+
+       /* make the control gpios active outputs */
+       /* note: never make gpio3_82 an output on V5.0 boards */
+       if (vers > 50)
+               do_set_mux((*ctrl)->control_padconf_core_base,
+                          padconf_mmcmux_lc15,
+                          sizeof(padconf_mmcmux_lc15) /
+                          sizeof(struct pad_conf_entry));
+
+#if 1
        /* read back */
-       printk("  gpio82 = %d\n", gpio_get_value(82));
-       gpio_free(7);
-       gpio_free(82);
+       printk("  gpio%d = %d (mmc1=%s)\n", soft_select, gpio_get_value(soft_select), gpio_get_value(soft_select)?"uSD":"eMMC");
+       printk("  gpio%d = %d (ctrl=%s)\n", control, gpio_get_value(control), gpio_get_value(control)?"soft":"hard");
+#endif
+       gpio_free(hard_select);
+       gpio_free(soft_select);
+       gpio_free(control);
        return 0;
 }
 
@@ -108,7 +218,7 @@ int set_mmc_switch(void)
 int spl_start_uboot(void)
 {
        set_mmc_switch();
-       return 1;       /* no direct Linux boot */
+       return 1;       /* no boot to Linux */
 }
 
 #endif