Home | History | Annotate | Download | only in HiKeyDxe
      1 /** @file
      2 *
      3 *  Copyright (c) 2015, Linaro Ltd. All rights reserved.
      4 *  Copyright (c) 2015, Hisilicon Ltd. All rights reserved.
      5 *
      6 *  This program and the accompanying materials
      7 *  are licensed and made available under the terms and conditions of the BSD License
      8 *  which accompanies this distribution.  The full text of the license may be found at
      9 *  http://opensource.org/licenses/bsd-license.php
     10 *
     11 *  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 *  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 *
     14 **/
     15 
     16 #include <Library/IoLib.h>
     17 #include <Library/TimerLib.h>
     18 #include <Library/UefiLib.h>
     19 #include <Library/UefiRuntimeServicesTableLib.h>
     20 
     21 #include <Protocol/EmbeddedGpio.h>
     22 #include <Protocol/DwUsb.h>
     23 
     24 #include <Hi6220.h>
     25 
     26 #include "Hi6220RegsPeri.h"
     27 #include "HiKeyDxeInternal.h"
     28 
     29 #define USB_SEL_GPIO0_3          3     // GPIO 0_3
     30 #define USB_5V_HUB_EN            7     // GPIO 0_7
     31 #define USB_ID_DET_GPIO2_5       21    // GPIO 2_5
     32 #define USB_VBUS_DET_GPIO2_6     22    // GPIO 2_6
     33 
     34 // Jumper on pin5-6 of J15 determines whether boot to fastboot
     35 #define DETECT_J15_FASTBOOT      24    // GPIO 3_0
     36 
     37 STATIC EMBEDDED_GPIO *mGpio;
     38 
     39 STATIC
     40 VOID
     41 HiKeyDetectUsbModeInit (
     42   IN VOID
     43   )
     44 {
     45   EFI_STATUS     Status;
     46 
     47   /* set pullup on both GPIO2_5 & GPIO2_6. It's required for inupt. */
     48   MmioWrite32 (0xf8001864, 1);
     49   MmioWrite32 (0xf8001868, 1);
     50 
     51   Status = gBS->LocateProtocol (&gEmbeddedGpioProtocolGuid, NULL, (VOID **)&mGpio);
     52   ASSERT_EFI_ERROR (Status);
     53   Status = mGpio->Set (mGpio, USB_SEL_GPIO0_3, GPIO_MODE_OUTPUT_0);
     54   ASSERT_EFI_ERROR (Status);
     55   Status = mGpio->Set (mGpio, USB_5V_HUB_EN, GPIO_MODE_OUTPUT_0);
     56   ASSERT_EFI_ERROR (Status);
     57   MicroSecondDelay (1000);
     58 
     59   Status = mGpio->Set (mGpio, USB_ID_DET_GPIO2_5, GPIO_MODE_INPUT);
     60   ASSERT_EFI_ERROR (Status);
     61   Status = mGpio->Set (mGpio, USB_VBUS_DET_GPIO2_6, GPIO_MODE_INPUT);
     62   ASSERT_EFI_ERROR (Status);
     63 }
     64 
     65 UINTN
     66 HiKeyGetUsbMode (
     67   IN VOID
     68   )
     69 {
     70   EFI_STATUS     Status;
     71   UINTN          GpioId, GpioVbus;
     72   UINTN          Value;
     73 
     74   Status = mGpio->Get (mGpio, USB_ID_DET_GPIO2_5, &Value);
     75   ASSERT_EFI_ERROR (Status);
     76   GpioId = Value;
     77   Status = mGpio->Get (mGpio, USB_VBUS_DET_GPIO2_6, &Value);
     78   ASSERT_EFI_ERROR (Status);
     79   GpioVbus = Value;
     80 
     81   if ((GpioId == 1) && (GpioVbus == 0))
     82     return USB_DEVICE_MODE;
     83   else if ((GpioId == 0) && (GpioVbus == 1))
     84     return USB_CABLE_NOT_ATTACHED;
     85   return USB_HOST_MODE;
     86 }
     87 
     88 EFI_STATUS
     89 HiKeyUsbPhyInit (
     90   IN UINT8        Mode
     91   )
     92 {
     93   UINTN         Value;
     94   UINT32        Data;
     95 
     96   HiKeyDetectUsbModeInit ();
     97 
     98   //setup clock
     99   MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CLKEN0, BIT4);
    100   do {
    101        Value = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_CLKSTAT0);
    102   } while ((Value & BIT4) == 0);
    103 
    104   //setup phy
    105   Data = RST0_USBOTG_BUS | RST0_POR_PICOPHY |
    106            RST0_USBOTG | RST0_USBOTG_32K;
    107   MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_RSTDIS0, Data);
    108   do {
    109     Value = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_RSTSTAT0);
    110     Value &= Data;
    111   } while (Value);
    112 
    113   Value = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_CTRL4);
    114   Value &= ~(CTRL4_PICO_SIDDQ | CTRL4_FPGA_EXT_PHY_SEL |
    115              CTRL4_OTG_PHY_SEL);
    116   Value |=  CTRL4_PICO_VBUSVLDEXT | CTRL4_PICO_VBUSVLDEXTSEL;
    117   MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CTRL4, Value);
    118   MicroSecondDelay (1000);
    119 
    120   //If Mode = 1, USB in Device Mode
    121   //If Mode = 0, USB in Host Mode
    122   if (Mode == USB_DEVICE_MODE) {
    123     if (HiKeyGetUsbMode () == USB_DEVICE_MODE) {
    124       DEBUG ((EFI_D_ERROR, "usb work as device mode.\n"));
    125     } else {
    126       return EFI_INVALID_PARAMETER;
    127     }
    128 
    129      Value = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_CTRL5);
    130      Value &= ~CTRL5_PICOPHY_BC_MODE;
    131      MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CTRL5, Value);
    132      MicroSecondDelay (20000);
    133   } else {
    134     if (HiKeyGetUsbMode () == USB_HOST_MODE) {
    135       DEBUG ((EFI_D_ERROR, "usb work as host mode.\n"));
    136     } else {
    137       return EFI_INVALID_PARAMETER;
    138     }
    139 
    140     /*CTRL5*/
    141     Data = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_CTRL5);
    142     Data &= ~CTRL5_PICOPHY_BC_MODE;
    143     Data |= CTRL5_USBOTG_RES_SEL | CTRL5_PICOPHY_ACAENB |
    144             CTRL5_PICOPHY_VDATDETENB | CTRL5_PICOPHY_DCDENB;
    145     MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CTRL5, Data);
    146     MicroSecondDelay (20000);
    147     MmioWrite32 (PERI_CTRL_BASE + 0x018, 0x70533483); //EYE_PATTERN
    148 
    149     MicroSecondDelay (5000);
    150   }
    151 
    152   return EFI_SUCCESS;
    153 }
    154 
    155 STATIC
    156 VOID
    157 UartInit (
    158   IN VOID
    159   )
    160 {
    161   UINT32     Val;
    162 
    163   /* make UART1 out of reset */
    164   MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_RSTDIS3, PERIPH_RST3_UART1);
    165   MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CLKEN3, PERIPH_RST3_UART1);
    166   /* make UART2 out of reset */
    167   MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_RSTDIS3, PERIPH_RST3_UART2);
    168   MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CLKEN3, PERIPH_RST3_UART2);
    169   /* make UART3 out of reset */
    170   MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_RSTDIS3, PERIPH_RST3_UART3);
    171   MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CLKEN3, PERIPH_RST3_UART3);
    172   /* make UART4 out of reset */
    173   MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_RSTDIS3, PERIPH_RST3_UART4);
    174   MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CLKEN3, PERIPH_RST3_UART4);
    175 
    176   /* make DW_MMC2 out of reset */
    177   MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_RSTDIS0, PERIPH_RST0_MMC2);
    178 
    179   /* enable clock for BT/WIFI */
    180   Val = MmioRead32 (PMUSSI_REG(0x1c)) | 0x40;
    181   MmioWrite32 (PMUSSI_REG(0x1c), Val);
    182 }
    183 
    184 STATIC
    185 VOID
    186 MtcmosInit (
    187   IN VOID
    188   )
    189 {
    190   UINT32     Data;
    191 
    192   /* enable MTCMOS for GPU */
    193   MmioWrite32 (AO_CTRL_BASE + SC_PW_MTCMOS_EN0, PW_EN0_G3D);
    194   do {
    195     Data = MmioRead32 (AO_CTRL_BASE + SC_PW_MTCMOS_ACK_STAT0);
    196   } while ((Data & PW_EN0_G3D) == 0);
    197 }
    198 
    199 EFI_STATUS
    200 HiKeyInitPeripherals (
    201   IN VOID
    202   )
    203 {
    204   UINT32     Data, Bits;
    205 
    206   /* make I2C0/I2C1/I2C2/SPI0 out of reset */
    207   Bits = PERIPH_RST3_I2C0 | PERIPH_RST3_I2C1 | PERIPH_RST3_I2C2 | \
    208 	 PERIPH_RST3_SSP;
    209   MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_RSTDIS3, Bits);
    210 
    211   do {
    212     Data = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_RSTSTAT3);
    213   } while (Data & Bits);
    214 
    215   UartInit ();
    216   MtcmosInit ();
    217 
    218   return EFI_SUCCESS;
    219 }
    220