]> git.proxmox.com Git - mirror_edk2.git/blob - Vlv2TbltDevicePkg/Library/MultiPlatformLib/BoardGpios/BoardGpios.c
Upload BSD-licensed Vlv2TbltDevicePkg and Vlv2DeviceRefCodePkg to
[mirror_edk2.git] / Vlv2TbltDevicePkg / Library / MultiPlatformLib / BoardGpios / BoardGpios.c
1 /** @file
2 Gpio setting for multiplatform..
3
4 Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
5
6 This program and the accompanying materials are licensed and made available under
7 the terms and conditions of the BSD License that accompanies this distribution.
8 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
17 #include <BoardGpios.h>
18 #include <Guid/SetupVariable.h>
19
20 //
21 //AlpineValley platform ocde begin
22 //
23 #define AV_SC_REG_GPIOS_MUXES_SEL0 0x48
24 #define AV_SC_REG_GPIOS_MUXES_SEL1 0x4C
25 #define AV_SC_REG_GPIOS_MUXES_SEL2 0x50
26 #define AV_SC_REG_GPIOS_MUXES_EN0 0x54
27 #define AV_SC_REG_GPIOS_MUXES_EN1 0x58
28 #define AV_SC_REG_GPIOS_MUXES_EN2 0x5C
29 //
30 //AlpineValley platform code end
31 //
32
33 EFI_GUID gPeiSmbusPpiGuid = EFI_PEI_SMBUS_PPI_GUID;
34
35 /**
36 @param None
37
38 @retval EFI_SUCCESS The function completed successfully.
39
40 **/
41 EFI_STATUS
42 ConfigurePlatformSysCtrlGpio (
43 IN EFI_PEI_SERVICES **PeiServices,
44 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
45 IN VOID *SmbusPpi
46 )
47 {
48 //
49 //AlpineValley platform code begin
50 //
51 // Initialize GPIO Settings:
52 //
53 UINT32 Status;
54 EFI_PLATFORM_INFO_HOB *PlatformInfoHob;
55
56 DEBUG ((EFI_D_INFO, "ConfigurePlatformSysCtrlGpio()...\n"));
57
58 //
59 // Obtain Platform Info from HOB.
60 //
61 Status = GetPlatformInfoHob ((const EFI_PEI_SERVICES **)PeiServices, &PlatformInfoHob);
62 ASSERT_EFI_ERROR (Status);
63
64 //
65 // The GPIO settings are dependent upon the platform. Obtain the Board ID through
66 // the EC to determine the current platform.
67 //
68 DEBUG ((EFI_D_INFO, "Platform Flavor | Board ID = 0x%X | 0x%X\n", PlatformInfoHob->PlatformFlavor, PlatformInfoHob->BoardId));
69
70
71
72 Status = (**PeiServices).LocatePpi (
73 (const EFI_PEI_SERVICES **)PeiServices,
74 &gPeiSmbusPpiGuid,
75 0,
76 NULL,
77 (void **)&SmbusPpi
78 );
79 ASSERT_EFI_ERROR (Status);
80
81 //
82 // Select/modify the GPIO initialization data based on the Board ID.
83 //
84 switch (PlatformInfoHob->BoardId)
85 {
86 default:
87 Status = EFI_SUCCESS;
88
89 //
90 // Do nothing for other RVP boards.
91 //
92 break;
93 }
94 return Status;
95 }
96
97 static EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = {
98 {
99 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
100 &gEfiPeiSmbusPpiGuid,
101 ConfigurePlatformSysCtrlGpio
102 }
103 };
104
105 EFI_STATUS
106 InstallPlatformSysCtrlGPIONotify (
107 IN CONST EFI_PEI_SERVICES **PeiServices
108 )
109 {
110 EFI_STATUS Status;
111
112 DEBUG ((EFI_D_INFO, "InstallPlatformSysCtrlGPIONotify()...\n"));
113
114 Status = (*PeiServices)->NotifyPpi(PeiServices, &mNotifyList[0]);
115 ASSERT_EFI_ERROR (Status);
116 return EFI_SUCCESS;
117
118 }
119
120 #define V_PCH_ILB_IRQE_UARTIRQEN_IRQ3 BIT3 // UART IRQ3 Enable
121
122 /**
123 Returns the Correct GPIO table for Mobile/Desktop respectively.
124 Before call it, make sure PlatformInfoHob->BoardId&PlatformFlavor is get correctly.
125
126 @param PeiServices General purpose services available to every PEIM.
127 @param PlatformInfoHob PlatformInfoHob pointer with PlatformFlavor specified.
128 @param BoardId BoardId ID as determined through the EC.
129
130 @retval EFI_SUCCESS The function completed successfully.
131 @retval EFI_DEVICE_ERROR KSC fails to respond.
132
133 **/
134 EFI_STATUS
135 MultiPlatformGpioTableInit (
136 IN CONST EFI_PEI_SERVICES **PeiServices,
137 IN EFI_PLATFORM_INFO_HOB *PlatformInfoHob
138 )
139 {
140 EFI_STATUS Status;
141 EFI_PEI_READ_ONLY_VARIABLE2_PPI *PeiReadOnlyVarPpi;
142 UINTN VarSize;
143 SYSTEM_CONFIGURATION SystemConfiguration;
144
145 DEBUG ((EFI_D_INFO, "MultiPlatformGpioTableInit()...\n"));
146
147 //
148 // Select/modify the GPIO initialization data based on the Board ID.
149 //
150 switch (PlatformInfoHob->BoardId) {
151
152 case BOARD_ID_MINNOW2: // Minnow2
153
154 Status = (**PeiServices).LocatePpi (
155 PeiServices,
156 &gEfiPeiReadOnlyVariable2PpiGuid,
157 0,
158 NULL,
159 (void **)&PeiReadOnlyVarPpi
160 );
161 ASSERT_EFI_ERROR (Status);
162
163 VarSize = sizeof (SYSTEM_CONFIGURATION);
164 Status = PeiReadOnlyVarPpi->GetVariable (
165 PeiReadOnlyVarPpi,
166 PLATFORM_SETUP_VARIABLE_NAME,
167 &gEfiSetupVariableGuid,
168 NULL,
169 &VarSize,
170 &SystemConfiguration
171 );
172
173 if (SystemConfiguration.GpioWakeCapability == 1) {
174 PlatformInfoHob->PlatformCfioData = (EFI_PHYSICAL_ADDRESS)(UINTN) &mMinnow2CfioInitData2;
175 }
176 else {
177 PlatformInfoHob->PlatformCfioData = (EFI_PHYSICAL_ADDRESS)(UINTN) &mMinnow2CfioInitData;
178 }
179
180 PlatformInfoHob->PlatformGpioData_NC = (EFI_PHYSICAL_ADDRESS)(UINTN) &mMinnow2_GpioInitData_NC[0];
181 PlatformInfoHob->PlatformGpioData_SC = (EFI_PHYSICAL_ADDRESS)(UINTN) &mMinnow2_GpioInitData_SC[0];
182 PlatformInfoHob->PlatformGpioData_SUS = (EFI_PHYSICAL_ADDRESS)(UINTN) &mMinnow2_GpioInitData_SUS[0];
183 break;
184
185 }
186
187 return EFI_SUCCESS;
188 }
189
190 UINT32
191 GPIORead32 (
192 IN UINT32 mmio_conf
193 )
194 {
195 UINT32 conf_val;
196 UINT32 i;
197 conf_val = MmioRead32(mmio_conf);
198 for(i=0;i<5;i++){
199 if(conf_val == 0xffffffff)
200 conf_val = MmioRead32(mmio_conf);
201 else
202 break;
203 }
204
205 return conf_val;
206 }
207
208 /**
209
210 Set GPIO CONF0 and PAD_VAL registers for NC/SC/SUS GPIO clusters
211
212 @param Gpio_Mmio_Offset GPIO_SCORE_OFFSET or GPIO_NCORE_OFFSET or GPIO_SSUS_OFFSET.
213 @param Gpio_Pin_Num Pin numbers to config for each GPIO clusters.
214 @param Gpio_Conf_Data GPIO_CONF_PAD_INIT data array for each GPIO clusters.
215
216 **/
217 VOID
218 InternalGpioConfig (
219 IN UINT32 Gpio_Mmio_Offset,
220 IN UINT32 Gpio_Pin_Num,
221 GPIO_CONF_PAD_INIT* Gpio_Conf_Data
222 )
223 {
224 UINT32 index;
225 UINT32 mmio_conf0;
226 UINT32 mmio_padval;
227 PAD_CONF0 conf0_val;
228 PAD_VAL pad_val;
229
230 //
231 // GPIO WELL -- Memory base registers
232 //
233
234 // A0 BIOS Spec doesn't mention it although X0 does. comment out now.
235 // GPIO write 0x01001002 to IOBASE + Gpio_Mmio_Offset + 0x0900
236 //
237 for(index=0; index < Gpio_Pin_Num; index++)
238 {
239 //
240 // Calculate the MMIO Address for specific GPIO pin CONF0 register pointed by index.
241 //
242 mmio_conf0 = IO_BASE_ADDRESS + Gpio_Mmio_Offset + R_PCH_CFIO_PAD_CONF0 + Gpio_Conf_Data[index].offset * 16;
243 mmio_padval= IO_BASE_ADDRESS + Gpio_Mmio_Offset + R_PCH_CFIO_PAD_VAL + Gpio_Conf_Data[index].offset * 16;
244
245 #ifdef EFI_DEBUG
246 DEBUG ((EFI_D_INFO, "%s, ", Gpio_Conf_Data[index].pad_name));
247
248 #endif
249 DEBUG ((EFI_D_INFO, "Usage = %d, Func# = %d, IntType = %d, Pull Up/Down = %d, MMIO Base = 0x%08x, ",
250 Gpio_Conf_Data[index].usage,
251 Gpio_Conf_Data[index].func,
252 Gpio_Conf_Data[index].int_type,
253 Gpio_Conf_Data[index].pull,
254 mmio_conf0));
255
256 //
257 // Step 1: PadVal Programming.
258 //
259 pad_val.dw = GPIORead32(mmio_padval);
260
261 //
262 // Config PAD_VAL only for GPIO (Non-Native) Pin
263 //
264 if(Native != Gpio_Conf_Data[index].usage)
265 {
266 pad_val.dw &= ~0x6; // Clear bits 1:2
267 pad_val.dw |= (Gpio_Conf_Data[index].usage & 0x6); // Set bits 1:2 according to PadVal
268
269 //
270 // set GPO default value
271 //
272 if(Gpio_Conf_Data[index].usage == GPO && Gpio_Conf_Data[index].gpod4 != NA)
273 {
274 pad_val.r.pad_val = Gpio_Conf_Data[index].gpod4;
275 }
276 }
277
278
279 DEBUG ((EFI_D_INFO, "Set PAD_VAL = 0x%08x, ", pad_val.dw));
280
281 MmioWrite32(mmio_padval, pad_val.dw);
282
283 //
284 // Step 2: CONF0 Programming
285 // Read GPIO default CONF0 value, which is assumed to be default value after reset.
286 //
287 conf0_val.dw = GPIORead32(mmio_conf0);
288
289 //
290 // Set Function #
291 //
292 conf0_val.r.Func_Pin_Mux = Gpio_Conf_Data[index].func;
293
294 if(GPO == Gpio_Conf_Data[index].usage)
295 {
296 //
297 // If used as GPO, then internal pull need to be disabled.
298 //
299 conf0_val.r.Pull_assign = 0; // Non-pull
300 }
301 else
302 {
303 //
304 // Set PullUp / PullDown
305 //
306 if(P_20K_H == Gpio_Conf_Data[index].pull)
307 {
308 conf0_val.r.Pull_assign = 0x1; // PullUp
309 conf0_val.r.Pull_strength = 0x2;// 20K
310 }
311 else if(P_20K_L == Gpio_Conf_Data[index].pull)
312 {
313 conf0_val.r.Pull_assign = 0x2; // PullDown
314 conf0_val.r.Pull_strength = 0x2;// 20K
315 }
316 else if(P_10K_H == Gpio_Conf_Data[index].pull)
317 {
318 conf0_val.r.Pull_assign = 0x1; // PullUp
319 conf0_val.r.Pull_strength = 0x1;// 10K
320 }
321 else if(P_10K_L == Gpio_Conf_Data[index].pull)
322 {
323 conf0_val.r.Pull_assign = 0x2; // PullDown
324 conf0_val.r.Pull_strength = 0x1;// 10K
325 }
326 else if(P_2K_H == Gpio_Conf_Data[index].pull)
327 {
328 conf0_val.r.Pull_assign = 0x1; // PullUp
329 conf0_val.r.Pull_strength = 0x0;// 2K
330 }
331 else if(P_2K_L == Gpio_Conf_Data[index].pull)
332 {
333 conf0_val.r.Pull_assign = 0x2; // PullDown
334 conf0_val.r.Pull_strength = 0x0;// 2K
335 }
336 else if(P_NONE == Gpio_Conf_Data[index].pull)
337 {
338 conf0_val.r.Pull_assign = 0; // Non-pull
339 }
340 else
341 {
342 ASSERT(FALSE); // Invalid value
343 }
344 }
345
346
347 //
348 // Set INT Trigger Type
349 //
350 conf0_val.dw &= ~0x0f000000; // Clear bits 27:24
351
352 //
353 // Set INT Trigger Type
354 //
355 if(TRIG_ == Gpio_Conf_Data[index].int_type)
356 {
357 //
358 // Interrupt not capable, clear bits 27:24
359 //
360 }
361 else
362 {
363 conf0_val.dw |= (Gpio_Conf_Data[index].int_type & 0x0f)<<24;
364 }
365
366 DEBUG ((EFI_D_INFO, "Set CONF0 = 0x%08x\n", conf0_val.dw));
367
368 //
369 // Write back the targeted GPIO config value according to platform (board) GPIO setting.
370 //
371 MmioWrite32 (mmio_conf0, conf0_val.dw);
372 }
373
374 //
375 // A0 BIOS Spec doesn't mention it although X0 does. comment out now.
376 // GPIO SCORE write 0x01001002 to IOBASE + 0x0900
377 //
378 }
379
380 /**
381 Returns the Correct GPIO table for Mobile/Desktop respectively.
382 Before call it, make sure PlatformInfoHob->BoardId&PlatformFlavor is get correctly.
383
384 @param PeiServices General purpose services available to every PEIM.
385 @param PlatformInfoHob PlatformInfoHob pointer with PlatformFlavor specified.
386 @param BoardId BoardId ID as determined through the EC.
387
388 @retval EFI_SUCCESS The function completed successfully.
389 @retval EFI_DEVICE_ERROR KSC fails to respond.
390
391 **/
392 EFI_STATUS
393 MultiPlatformGpioProgram (
394 IN CONST EFI_PEI_SERVICES **PeiServices,
395 IN EFI_PLATFORM_INFO_HOB *PlatformInfoHob
396 )
397 {
398 #if !_SIMIC_
399 CFIO_INIT_STRUCT* PlatformCfioDataPtr;
400
401 PlatformCfioDataPtr = (CFIO_INIT_STRUCT *) (UINTN) PlatformInfoHob->PlatformCfioData;
402 DEBUG ((EFI_D_INFO, "MultiPlatformGpioProgram()...\n"));
403
404 //
405 // SCORE GPIO WELL -- IO base registers
406 //
407
408 //
409 // GPIO_USE_SEL Register -> 1 = GPIO 0 = Native
410 //
411 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_USE_SEL, PlatformCfioDataPtr->Use_Sel_SC0);
412
413 //
414 // Set GP_LVL Register
415 //
416 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_LVL , PlatformCfioDataPtr->GP_Lvl_SC0);
417
418 //
419 // GP_IO_SEL Register -> 1 = Input 0 = Output. If Native Mode don't care
420 //
421 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_IO_SEL, PlatformCfioDataPtr->Io_Sel_SC0);
422
423 //
424 // GPIO Triger Positive Edge Enable Register
425 //
426 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_TPE, PlatformCfioDataPtr->TPE_SC0);
427
428 //
429 // GPIO Trigger Negative Edge Enable Register
430 //
431 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_TNE, PlatformCfioDataPtr->TNE_SC0);
432
433 //
434 // GPIO Trigger Status
435 //
436 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_TS, PlatformCfioDataPtr->TS_SC0);
437
438 //
439 // GPIO_USE_SEL2 Register -> 1 = GPIO 0 = Native
440 //
441 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_USE_SEL2, PlatformCfioDataPtr->Use_Sel_SC1);
442
443 //
444 // Set GP_LVL2 Register
445 //
446 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_LVL2, PlatformCfioDataPtr->GP_Lvl_SC1);
447
448 //
449 // GP_IO_SEL2 Register -> 1 = Input 0 = Output. If Native Mode don't care
450 //
451 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_IO_SEL2, PlatformCfioDataPtr->Io_Sel_SC1);
452
453 //
454 // GPIO_USE_SEL3 Register -> 1 = GPIO 0 = Native
455 //
456 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_USE_SEL3, PlatformCfioDataPtr->Use_Sel_SC2);
457
458 //
459 // Set GP_LVL3 Register
460 //
461 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_LVL3, PlatformCfioDataPtr->GP_Lvl_SC2);
462
463 //
464 // GP_IO_SEL3 Register -> 1 = Input 0 = Output if Native Mode don't care
465 //
466 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_IO_SEL3, PlatformCfioDataPtr->Io_Sel_SC2);
467
468 //
469 // SUS GPIO WELL -- IO base registers
470 //
471
472 //
473 // GPIO_USE_SEL Register -> 1 = GPIO 0 = Native
474 //
475 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_USE_SEL, PlatformCfioDataPtr->Use_Sel_SS);
476
477 //
478 // Set GP_LVL Register
479 //
480 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_LVL , PlatformCfioDataPtr->GP_Lvl_SS);
481
482 //
483 // GP_IO_SEL Register -> 1 = Input 0 = Output. If Native Mode don't care.
484 //
485 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_IO_SEL, PlatformCfioDataPtr->Io_Sel_SS);
486
487 //
488 // GPIO Triger Positive Edge Enable Register.
489 //
490 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_TPE, PlatformCfioDataPtr->TPE_SS);
491
492 //
493 // GPIO Trigger Negative Edge Enable Register.
494 //
495 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_TNE, PlatformCfioDataPtr->TNE_SS);
496
497 //
498 // GPIO Trigger Status.
499 //
500 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_TS, PlatformCfioDataPtr->TS_SS);
501
502 //
503 // GPIO Wake Enable.
504 //
505 IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SUS_WAKE_EN, PlatformCfioDataPtr->WE_SS);
506
507 //
508 // Config SC/NC/SUS GPIO Pins
509 //
510 switch (PlatformInfoHob->BoardId) {
511 case BOARD_ID_MINNOW2:
512 DEBUG ((EFI_D_INFO, "Start to config Minnow2 GPIO pins\n"));
513 InternalGpioConfig(GPIO_SCORE_OFFSET, sizeof(mMinnow2_GpioInitData_SC)/sizeof(mMinnow2_GpioInitData_SC[0]), (GPIO_CONF_PAD_INIT *) (UINTN) PlatformInfoHob->PlatformGpioData_SC);
514 InternalGpioConfig(GPIO_NCORE_OFFSET, sizeof(mMinnow2_GpioInitData_NC)/sizeof(mMinnow2_GpioInitData_NC[0]), (GPIO_CONF_PAD_INIT *) (UINTN) PlatformInfoHob->PlatformGpioData_NC);
515 InternalGpioConfig(GPIO_SSUS_OFFSET, sizeof(mMinnow2_GpioInitData_SUS)/sizeof(mMinnow2_GpioInitData_SUS[0]), (GPIO_CONF_PAD_INIT *) (UINTN) PlatformInfoHob->PlatformGpioData_SUS);
516 break;
517 default:
518
519 break;
520 }
521
522 //
523 // configure the CFIO Pnp settings
524 //
525 if (PlatformInfoHob->CfioEnabled) {
526 if (PlatformInfoHob->BoardId == BOARD_ID_MINNOW2){
527 InternalGpioConfig(GPIO_SCORE_OFFSET, sizeof(mNB_BB_FAB3_GpioInitData_SC_TRI)/sizeof(mNB_BB_FAB3_GpioInitData_SC_TRI[0]), (GPIO_CONF_PAD_INIT *) (UINTN)PlatformInfoHob->PlatformGpioData_SC_TRI);
528 }
529 }
530 #else
531 DEBUG ((EFI_D_INFO, "Skip MultiPlatformGpioProgram()...for SIMICS or HYB model\n"));
532 #endif
533 return EFI_SUCCESS;
534 }
535