/** @file Copyright (c) 2017, Linaro, Ltd. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ #include #include #include #include #include #define PDR(x) (SYNQUACER_GPIO_BASE + 4 * (GPIO_PIN (x) >> 3)) #define DDR(x) (SYNQUACER_GPIO_BASE + 0x10 + 4 * (GPIO_PIN (x) >> 3)) #define PFR(x) (SYNQUACER_GPIO_BASE + 0x20 + 4 * (GPIO_PIN (x) >> 3)) #define GPIO_BIT(x) (1U << (GPIO_PIN (x) % 8)) STATIC CONST UINTN mGpioPinCount = 32; /** Gets the state of a GPIO pin @param This Pointer to protocol @param Gpio Which pin to read @param Value State of the pin @retval EFI_SUCCESS GPIO state returned in Value @retval EFI_INVALID_PARAMETER Value is NULL @retval EFI_NOT_FOUND Pin does not exit **/ STATIC EFI_STATUS EFIAPI GpioGet ( IN EMBEDDED_GPIO_PPI *This, IN EMBEDDED_GPIO_PIN Gpio, OUT UINTN *Value ) { if (Value == NULL) { return EFI_INVALID_PARAMETER; } if (GPIO_PORT (Gpio) > 0 || GPIO_PIN (Gpio) >= mGpioPinCount) { return EFI_NOT_FOUND; } *Value = ((MmioRead32 (PDR (GPIO_PIN (Gpio))) & GPIO_BIT (Gpio)) != 0); return EFI_SUCCESS; } /** Sets the state of a GPIO pin @param This Pointer to protocol @param Gpio Which pin to modify @param Mode Mode to set @retval EFI_SUCCESS GPIO set as requested @retval EFI_INVALID_PARAMETER Invalid mode @retval EFI_NOT_FOUND Pin does not exit **/ STATIC EFI_STATUS EFIAPI GpioSet ( IN EMBEDDED_GPIO_PPI *This, IN EMBEDDED_GPIO_PIN Gpio, IN EMBEDDED_GPIO_MODE Mode ) { if (GPIO_PORT (Gpio) > 0 || GPIO_PIN (Gpio) >= mGpioPinCount) { return EFI_NOT_FOUND; } switch (Mode) { case GPIO_MODE_INPUT: MmioAnd32 (DDR (GPIO_PIN (Gpio)), ~GPIO_BIT (Gpio)); break; case GPIO_MODE_OUTPUT_0: MmioOr32 (DDR (GPIO_PIN (Gpio)), GPIO_BIT (Gpio)); MmioAnd32 (PDR (GPIO_PIN (Gpio)), ~GPIO_BIT (Gpio)); break; case GPIO_MODE_OUTPUT_1: MmioOr32 (DDR (GPIO_PIN (Gpio)), GPIO_BIT (Gpio)); MmioOr32 (PDR (GPIO_PIN (Gpio)), GPIO_BIT (Gpio)); break; default: return EFI_INVALID_PARAMETER; } return EFI_SUCCESS; } /** Gets the mode (function) of a GPIO pin @param This Pointer to protocol @param Gpio Which pin @param Mode Pointer to output mode value @retval EFI_SUCCESS Mode value retrieved @retval EFI_INVALID_PARAMETER Mode is NULL @retval EFI_NOT_FOUND Pin does not exit **/ STATIC EFI_STATUS EFIAPI GpioGetMode ( IN EMBEDDED_GPIO_PPI *This, IN EMBEDDED_GPIO_PIN Gpio, OUT EMBEDDED_GPIO_MODE *Mode ) { if (Mode == NULL) { return EFI_INVALID_PARAMETER; } if (GPIO_PORT (Gpio) > 0 || GPIO_PIN (Gpio) >= mGpioPinCount) { return EFI_NOT_FOUND; } if (!(MmioRead32 (DDR (GPIO_PIN (Gpio))) & GPIO_BIT (Gpio))) { *Mode = GPIO_MODE_INPUT; } else if (!(MmioRead32 (PDR (GPIO_PIN (Gpio))) & GPIO_BIT (Gpio))) { *Mode = GPIO_MODE_OUTPUT_0; } else { *Mode = GPIO_MODE_OUTPUT_1; } return EFI_SUCCESS; } /** Sets the pull-up / pull-down resistor of a GPIO pin @param This Pointer to PPI @param Gpio Port/pin index @param Pull The pullup/pulldown mode to set @retval EFI_SUCCESS Mode was set @retval EFI_NOT_FOUND Pin does not exist @retval EFI_UNSUPPORTED Action not supported **/ STATIC EFI_STATUS EFIAPI GpioSetPull ( IN EMBEDDED_GPIO_PPI *This, IN EMBEDDED_GPIO_PIN Gpio, IN EMBEDDED_GPIO_PULL Pull ) { if (Pull != GPIO_PULL_NONE) { return EFI_UNSUPPORTED; } if (GPIO_PORT (Gpio) > 0 || GPIO_PIN (Gpio) >= mGpioPinCount) { return EFI_NOT_FOUND; } return EFI_SUCCESS; } STATIC EMBEDDED_GPIO_PPI mGpioPpi = { GpioGet, GpioSet, GpioGetMode, GpioSetPull, }; STATIC CONST EFI_PEI_PPI_DESCRIPTOR mEmbeddedGpioPpiDescriptor = { EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, &gEdkiiEmbeddedGpioPpiGuid, &mGpioPpi }; EFI_STATUS EFIAPI SynQuacerGpioPeiEntryPoint ( IN EFI_PEI_FILE_HANDLE FfsHeader, IN CONST EFI_PEI_SERVICES **PeiServices ) { return PeiServicesInstallPpi (&mEmbeddedGpioPpiDescriptor); }