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
HiKeyDetectUsbModeInit(IN 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
HiKeyGetUsbMode(IN VOID)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
HiKeyUsbPhyInit(IN UINT8 Mode)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
UartInit(IN 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
MtcmosInit(IN 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
HiKeyInitPeripherals(IN VOID)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