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