]> git.proxmox.com Git - mirror_edk2.git/blobdiff - QuarkPlatformPkg/Platform/Pei/PlatformInit/PlatformEarlyInit.c
QuarkPlatformPkg/PlatformInit: Fix recovery detection issues
[mirror_edk2.git] / QuarkPlatformPkg / Platform / Pei / PlatformInit / PlatformEarlyInit.c
index 32ae3e089189d2537ea14391c6f10bd0f4d96dbe..0f71b1fda21d9e18bfd688d568bf372474170f03 100644 (file)
@@ -6,7 +6,7 @@ This PEIM initialize platform for MRC, following action is performed,
 4. Calls MRC to initialize memory and install a PPI notify to do post memory initialization.\r
 This file contains the main entrypoint of the PEIM.\r
 \r
-Copyright (c) 2013 Intel Corporation.\r
+Copyright (c) 2013 - 2016 Intel Corporation.\r
 \r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
@@ -192,6 +192,271 @@ SetLanControllerMacAddr (
   PciWrite16 (DevPcieAddr + PCI_COMMAND_OFFSET, SaveCmdReg);\r
 }\r
 \r
+/**\r
+  Initialize state of I2C GPIO expanders.\r
+\r
+  @param  PlatformType  Platform type for GPIO expander init.\r
+\r
+**/\r
+EFI_STATUS\r
+EarlyPlatformConfigGpioExpanders (\r
+  IN CONST EFI_PLATFORM_TYPE              PlatformType,\r
+  EFI_BOOT_MODE                           BootMode\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  EFI_I2C_DEVICE_ADDRESS  I2CSlaveAddress;\r
+  UINTN                   Length;\r
+  UINTN                   ReadLength;\r
+  UINT8                   Buffer[2];\r
+\r
+  //\r
+  // Configure GPIO expanders for Galileo Gen 2\r
+  // Route I2C pins to Arduino header\r
+  // Set all GPIO expander pins connected to the Reset Button as inputs\r
+  //\r
+  if (PlatformType == GalileoGen2) {\r
+    //\r
+    // Configure AMUX1_IN (EXP2.P1_4) as an output\r
+    //\r
+    PlatformPcal9555GpioSetDir (\r
+      GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR,  // IO Expander 2.\r
+      12,                                   // P1-4.\r
+      FALSE                                 // Configure as output\r
+      );\r
+\r
+    //\r
+    // Set AMUX1_IN(EXP2.P1_4) low to route I2C to Arduino Shield connector\r
+    //\r
+    PlatformPcal9555GpioSetLevel (\r
+      GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR,  // IO Expander 2.\r
+      12,                                   // P1-4. \r
+      FALSE                                 // Set pin low\r
+      );\r
+\r
+    //\r
+    // Configure Reset Button(EXP1.P1_7) as an input\r
+    //\r
+    PlatformPcal9555GpioSetDir (\r
+      GALILEO_GEN2_IOEXP1_7BIT_SLAVE_ADDR,  // IO Expander 1.\r
+      15,                                   // P1-7.\r
+      TRUE\r
+      );\r
+\r
+    //\r
+    // Disable pullup on Reset Button(EXP1.P1_7)\r
+    //\r
+    PlatformPcal9555GpioDisablePull (\r
+      GALILEO_GEN2_IOEXP1_7BIT_SLAVE_ADDR,  // IO Expander 1.\r
+      15                                    // P1-7.\r
+      );\r
+\r
+    //\r
+    // Configure Reset Button(EXP2.P1_7) as an input\r
+    //\r
+    PlatformPcal9555GpioSetDir (\r
+      GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR,  // IO Expander 2.\r
+      15,                                   // P1-7.\r
+      TRUE\r
+      );\r
+\r
+    //\r
+    // Disable pullup on Reset Button(EXP2.P1_7)\r
+    //\r
+    PlatformPcal9555GpioDisablePull (\r
+      GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR,  // IO Expander 2.\r
+      15                                    // P1-7.\r
+      );\r
+\r
+    if (BootMode != BOOT_IN_RECOVERY_MODE) {\r
+      //\r
+      // Read state of Reset Button - EXP2.P1_7\r
+      // This GPIO is pulled high when the button is not pressed\r
+      // This GPIO reads low when button is pressed\r
+      //\r
+      if (!PlatformPcal9555GpioGetState (\r
+             GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR,  // IO Expander 2\r
+             15                                    // P1-7\r
+             )) {\r
+        DEBUG ((EFI_D_INFO, "  Force Recovery mode and reset\n"));\r
+\r
+        //\r
+        // Set 'B_CFG_STICKY_RW_FORCE_RECOVERY' sticky bit so we know we need to do a recovery following warm reset\r
+        //\r
+        QNCAltPortWrite (\r
+          QUARK_SCSS_SOC_UNIT_SB_PORT_ID,\r
+          QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW,\r
+          QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW) | B_CFG_STICKY_RW_FORCE_RECOVERY\r
+          );\r
+        ResetWarm();\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Configure GPIO expanders for Galileo Gen 2\r
+  // Set all GPIO expander pins connected to the Reset Button as inputs\r
+  // Route I2C pins to Arduino header\r
+  //\r
+  if (PlatformType == Galileo) {\r
+    //\r
+    // Detect the I2C Slave Address of the GPIO Expander\r
+    //\r
+    if (PlatformLegacyGpioGetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL, GALILEO_DETERMINE_IOEXP_SLA_RESUMEWELL_GPIO)) {\r
+      I2CSlaveAddress.I2CDeviceAddress = GALILEO_IOEXP_J2HI_7BIT_SLAVE_ADDR;\r
+    } else {\r
+      I2CSlaveAddress.I2CDeviceAddress = GALILEO_IOEXP_J2LO_7BIT_SLAVE_ADDR;\r
+    }\r
+    DEBUG ((EFI_D_INFO, "Galileo GPIO Expender Slave Address = %02x\n", I2CSlaveAddress.I2CDeviceAddress));\r
+\r
+    //\r
+    // Set I2C_MUX (GPORT1_BIT5) low to route I2C to Arduino Shield connector\r
+    //\r
+\r
+    //\r
+    // Select GPIO Expander GPORT1\r
+    //\r
+    Length = 2;\r
+    Buffer[0] = 0x18; //sub-address\r
+    Buffer[1] = 0x01; //data\r
+    Status = I2cWriteMultipleByte (\r
+      I2CSlaveAddress,\r
+      EfiI2CSevenBitAddrMode,\r
+      &Length,\r
+      &Buffer\r
+      );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    //\r
+    // Read "Pin Direction" of GPIO Expander GPORT1\r
+    //\r
+    Length = 1;\r
+    ReadLength = 1;\r
+    Buffer[1] = 0x1C;\r
+    Status = I2cReadMultipleByte (\r
+      I2CSlaveAddress,\r
+      EfiI2CSevenBitAddrMode,\r
+      &Length,\r
+      &ReadLength,\r
+      &Buffer[1]\r
+      );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    //\r
+    // Configure GPIO Expander GPORT1_BIT5 as an output\r
+    //\r
+    Length = 2;\r
+    Buffer[0] = 0x1C; //sub-address\r
+    Buffer[1] = (UINT8)(Buffer[1] & (~BIT5)); //data\r
+\r
+    Status = I2cWriteMultipleByte (\r
+      I2CSlaveAddress,\r
+      EfiI2CSevenBitAddrMode,\r
+      &Length,\r
+      &Buffer\r
+      );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    //\r
+    // Set GPIO Expander GPORT1_BIT5 low\r
+    //\r
+    Length = 2;\r
+    Buffer[0] = 0x09; //sub-address\r
+    Buffer[1] = (UINT8)(~BIT5); //data\r
+\r
+    Status = I2cWriteMultipleByte (\r
+      I2CSlaveAddress,\r
+      EfiI2CSevenBitAddrMode,\r
+      &Length,\r
+      &Buffer\r
+      );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    //\r
+    // Configure RESET_N_SHLD (GPORT5_BIT0) and SW_RESET_N_SHLD (GPORT5_BIT1) as inputs\r
+    //\r
+\r
+    //\r
+    // Select GPIO Expander GPORT5\r
+    //\r
+    Length = 2;\r
+    Buffer[0] = 0x18;\r
+    Buffer[1] = 0x05;\r
+    Status = I2cWriteMultipleByte (\r
+      I2CSlaveAddress,\r
+      EfiI2CSevenBitAddrMode,\r
+      &Length,\r
+      &Buffer\r
+      );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    //\r
+    // Read "Pin Direction" of GPIO Expander GPORT5\r
+    //\r
+    Length = 1;\r
+    ReadLength = 1;\r
+    Buffer[1] = 0x1C;\r
+    Status = I2cReadMultipleByte (\r
+      I2CSlaveAddress,\r
+      EfiI2CSevenBitAddrMode,\r
+      &Length,\r
+      &ReadLength,\r
+      &Buffer[1]\r
+      );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    //\r
+    // Configure GPIO Expander GPORT5_BIT0 and GPORT5_BIT1 as inputs\r
+    //\r
+    Length = 2;\r
+    Buffer[0] = 0x1C;\r
+    Buffer[1] = Buffer[1] | BIT0 | BIT1;\r
+    Status = I2cWriteMultipleByte (\r
+      I2CSlaveAddress,\r
+      EfiI2CSevenBitAddrMode,\r
+      &Length,\r
+      &Buffer\r
+      );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    if (BootMode != BOOT_IN_RECOVERY_MODE) {\r
+      //\r
+      // Read state of RESET_N_SHLD (GPORT5_BIT0)\r
+      //\r
+      Buffer[1] = 5;\r
+      Length = 1;\r
+      ReadLength = 1;\r
+      Status = I2cReadMultipleByte (\r
+                 I2CSlaveAddress,\r
+                 EfiI2CSevenBitAddrMode,\r
+                 &Length,\r
+                 &ReadLength,\r
+                 &Buffer[1]\r
+                 );\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      //\r
+      // Return the state of GPORT5_BIT0\r
+      //\r
+      if ((Buffer[1] & BIT0) == 0) {\r
+        DEBUG ((EFI_D_INFO, "  Force Recovery mode and reset\n"));\r
+\r
+        //\r
+        // Set 'B_CFG_STICKY_RW_FORCE_RECOVERY' sticky bit so we know we need to do a recovery following warm reset\r
+        //\r
+        QNCAltPortWrite (\r
+          QUARK_SCSS_SOC_UNIT_SB_PORT_ID,\r
+          QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW,\r
+          QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW) | B_CFG_STICKY_RW_FORCE_RECOVERY\r
+          );\r
+        ResetWarm();\r
+      }\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 /**\r
   This is the entrypoint of PEIM\r
 \r
@@ -304,6 +569,12 @@ PeiInitPlatform (
   DEBUG ((EFI_D_INFO, "Platform Erratas After MRC\n"));\r
   PlatformErratasPostMrc ();\r
 \r
+  //\r
+  //\r
+  //\r
+  DEBUG ((EFI_D_INFO, "EarlyPlatformConfigGpioExpanders ()\n"));\r
+  EarlyPlatformConfigGpioExpanders (PlatformType, BootMode);\r
+\r
   //\r
   // Now that all of the pre-permanent memory activities have\r
   // been taken care of, post a call-back for the permanent-memory\r
@@ -579,8 +850,8 @@ EarlyPlatformInit (
   //\r
   if (CheckForResetDueToErrors (TRUE)) {\r
     if(FeaturePcdGet (WaitIfResetDueToError)) {\r
-      DEBUG ((EFI_D_ERROR, "Press any key to continue.\n"));\r
-      PlatformDebugPortGetChar8 ();\r
+      DEBUG ((EFI_D_ERROR, "Wait 10 seconds.\n"));\r
+      MicroSecondDelay(10000000);\r
     }\r
   }\r
 \r