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