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