]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.c
ArmPlatformPkg: remove ArmJunoPkg
[mirror_edk2.git] / ArmPlatformPkg / ArmJunoPkg / Drivers / ArmJunoDxe / ArmJunoDxe.c
diff --git a/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.c b/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.c
deleted file mode 100644 (file)
index 18491c7..0000000
+++ /dev/null
@@ -1,550 +0,0 @@
-/** @file\r
-*\r
-*  Copyright (c) 2013-2015, ARM Limited. All rights reserved.\r
-*\r
-*  This program and the accompanying materials\r
-*  are licensed and made available under the terms and conditions of the BSD License\r
-*  which accompanies this distribution.  The full text of the license may be found at\r
-*  http://opensource.org/licenses/bsd-license.php\r
-*\r
-*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-*\r
-**/\r
-\r
-#include "ArmJunoDxeInternal.h"\r
-#include <ArmPlatform.h>\r
-\r
-#include <IndustryStandard/Pci.h>\r
-#include <Protocol/DevicePathFromText.h>\r
-#include <Protocol/PciIo.h>\r
-#include <Protocol/PciRootBridgeIo.h>\r
-\r
-#include <Guid/EventGroup.h>\r
-#include <Guid/GlobalVariable.h>\r
-\r
-#include <Library/ArmShellCmdLib.h>\r
-#include <Library/AcpiLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/DevicePathLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/NonDiscoverableDeviceRegistrationLib.h>\r
-#include <Library/UefiRuntimeServicesTableLib.h>\r
-#include <Library/IoLib.h>\r
-#include <Library/PrintLib.h>\r
-\r
-\r
-// This GUID must match the FILE_GUID in ArmPlatformPkg/ArmJunoPkg/AcpiTables/AcpiTables.inf\r
-STATIC CONST EFI_GUID mJunoAcpiTableFile = { 0xa1dd808e, 0x1e95, 0x4399, { 0xab, 0xc0, 0x65, 0x3c, 0x82, 0xe8, 0x53, 0x0c } };\r
-\r
-typedef struct {\r
-  ACPI_HID_DEVICE_PATH      AcpiDevicePath;\r
-  PCI_DEVICE_PATH           PciDevicePath;\r
-  EFI_DEVICE_PATH_PROTOCOL  EndDevicePath;\r
-} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;\r
-\r
-STATIC CONST EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mPciRootComplexDevicePath = {\r
-    {\r
-      { ACPI_DEVICE_PATH,\r
-        ACPI_DP,\r
-        { (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),\r
-          (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) }\r
-      },\r
-      EISA_PNP_ID (0x0A03),\r
-      0\r
-    },\r
-    {\r
-      { HARDWARE_DEVICE_PATH,\r
-        HW_PCI_DP,\r
-        { (UINT8) (sizeof (PCI_DEVICE_PATH)),\r
-          (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) }\r
-      },\r
-      0,\r
-      0\r
-    },\r
-    {\r
-      END_DEVICE_PATH_TYPE,\r
-      END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
-      { END_DEVICE_PATH_LENGTH, 0 }\r
-    }\r
-};\r
-\r
-EFI_EVENT mAcpiRegistration = NULL;\r
-\r
-/**\r
-  This function reads PCI ID of the controller.\r
-\r
-  @param[in]  PciIo   PCI IO protocol handle\r
-  @param[in]  PciId   Looking for specified PCI ID Vendor/Device\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-ReadMarvellYoukonPciId (\r
-  IN EFI_PCI_IO_PROTOCOL  *PciIo,\r
-  IN UINT32               PciId\r
-  )\r
-{\r
-  UINT32      DevicePciId;\r
-  EFI_STATUS  Status;\r
-\r
-  Status = PciIo->Pci.Read (\r
-                        PciIo,\r
-                        EfiPciIoWidthUint32,\r
-                        PCI_VENDOR_ID_OFFSET,\r
-                        1,\r
-                        &DevicePciId);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  if (DevicePciId != PciId) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  This function searches for Marvell Yukon NIC on the Juno\r
-  platform and returns PCI IO protocol handle for the controller.\r
-\r
-  @param[out]  PciIo   PCI IO protocol handle\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-GetMarvellYukonPciIoProtocol (\r
-  OUT EFI_PCI_IO_PROTOCOL  **PciIo\r
-  )\r
-{\r
-  UINTN       HandleCount;\r
-  EFI_HANDLE  *HandleBuffer;\r
-  UINTN       HIndex;\r
-  EFI_STATUS  Status;\r
-\r
-  Status = gBS->LocateHandleBuffer (\r
-                  ByProtocol,\r
-                  &gEfiPciIoProtocolGuid,\r
-                  NULL,\r
-                  &HandleCount,\r
-                  &HandleBuffer);\r
-  if (EFI_ERROR (Status)) {\r
-    return (Status);\r
-  }\r
-\r
-  for (HIndex = 0; HIndex < HandleCount; ++HIndex) {\r
-    // If PciIo opened with EFI_OPEN_PROTOCOL_GET_PROTOCOL, the CloseProtocol() is not required\r
-    Status = gBS->OpenProtocol (\r
-                    HandleBuffer[HIndex],\r
-                    &gEfiPciIoProtocolGuid,\r
-                    (VOID **) PciIo,\r
-                    NULL,\r
-                    NULL,\r
-                    EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
-    if (EFI_ERROR (Status)) {\r
-      continue;\r
-    }\r
-\r
-    Status = ReadMarvellYoukonPciId (*PciIo, JUNO_MARVELL_YUKON_ID);\r
-    if (EFI_ERROR (Status)) {\r
-      continue;\r
-    } else {\r
-      break;\r
-    }\r
-  }\r
-\r
-  gBS->FreePool (HandleBuffer);\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
- This function restore the original controller attributes\r
-\r
-   @param[in]   PciIo               PCI IO protocol handle\r
-   @param[in]   PciAttr             PCI controller attributes.\r
-   @param[in]   AcpiResDescriptor   ACPI 2.0 resource descriptors for the BAR\r
-**/\r
-STATIC\r
-VOID\r
-RestorePciDev (\r
-  IN EFI_PCI_IO_PROTOCOL                *PciIo,\r
-  IN UINT64                             PciAttr\r
-  )\r
-{\r
-  PciIo->Attributes (\r
-           PciIo,\r
-           EfiPciIoAttributeOperationSet,\r
-           PciAttr,\r
-           NULL\r
-           );\r
-}\r
-\r
-/**\r
- This function returns PCI MMIO base address for a controller\r
-\r
-   @param[in]   PciIo               PCI IO protocol handle\r
-   @param[out]  PciRegBase          PCI base MMIO address\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-BarIsDeviceMemory (\r
-  IN   EFI_PCI_IO_PROTOCOL *PciIo,\r
-  OUT  UINT32              *PciRegBase\r
-  )\r
-{\r
-  EFI_STATUS                         Status;\r
-  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *AcpiResDescriptor;\r
-  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *AcpiCurrentDescriptor;\r
-\r
-  // Marvell Yukon's Bar0 provides base memory address for control registers\r
-  Status = PciIo->GetBarAttributes (PciIo, PCI_BAR_IDX0, NULL, (VOID**)&AcpiResDescriptor);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  AcpiCurrentDescriptor = AcpiResDescriptor;\r
-\r
-  // Search for a memory type descriptor\r
-  while (AcpiCurrentDescriptor->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
-\r
-    // Check if Bar is memory type one and fetch a base address\r
-    if (AcpiCurrentDescriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR &&\r
-        AcpiCurrentDescriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM &&\r
-        !(AcpiCurrentDescriptor->SpecificFlag & ACPI_SPECFLAG_PREFETCHABLE)) {\r
-      *PciRegBase = AcpiCurrentDescriptor->AddrRangeMin;\r
-      break;\r
-    } else {\r
-      Status = EFI_UNSUPPORTED;\r
-    }\r
-\r
-    AcpiCurrentDescriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (AcpiCurrentDescriptor + 1);\r
-  }\r
-\r
-  gBS->FreePool (AcpiResDescriptor);\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
- This function provides PCI MMIO base address, old PCI controller attributes.\r
-\r
-   @param[in]   PciIo               PCI IO protocol handle\r
-   @param[out]  PciRegBase          PCI base MMIO address\r
-   @param[out]  OldPciAttr          Old PCI controller attributes.\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-InitPciDev (\r
-  IN EFI_PCI_IO_PROTOCOL                 *PciIo,\r
-  OUT UINT32                             *PciRegBase,\r
-  OUT UINT64                             *OldPciAttr\r
-  )\r
-{\r
-  UINT64      AttrSupports;\r
-  EFI_STATUS  Status;\r
-\r
-  // Get controller's current attributes\r
-  Status = PciIo->Attributes (\r
-                    PciIo,\r
-                    EfiPciIoAttributeOperationGet,\r
-                    0,\r
-                    OldPciAttr);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  // Fetch supported attributes\r
-  Status = PciIo->Attributes (\r
-                    PciIo,\r
-                    EfiPciIoAttributeOperationSupported,\r
-                    0,\r
-                    &AttrSupports);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  // Enable EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_MEMORY and\r
-  // EFI_PCI_IO_ATTRIBUTE_BUS_MASTER bits in the PCI Config Header\r
-  AttrSupports &= EFI_PCI_DEVICE_ENABLE;\r
-  Status = PciIo->Attributes (\r
-                    PciIo,\r
-                    EfiPciIoAttributeOperationEnable,\r
-                    AttrSupports,\r
-                    NULL);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  Status = BarIsDeviceMemory (PciIo, PciRegBase);\r
-  if (EFI_ERROR (Status)) {\r
-    RestorePciDev (PciIo, *OldPciAttr);\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
- This function reads MAC address from IOFPGA and writes it to Marvell Yukon NIC\r
-\r
-   @param[in]   PciRegBase   PCI base MMIO address\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-WriteMacAddress (\r
-  IN UINT32  PciRegBase\r
-  )\r
-{\r
-  UINT32  MacHigh;\r
-  UINT32  MacLow;\r
-\r
-  // Read MAC address from IOFPGA\r
-  MacHigh= MmioRead32 (ARM_JUNO_SYS_PCIGBE_H);\r
-  MacLow = MmioRead32 (ARM_JUNO_SYS_PCIGBE_L);\r
-\r
-  // Set software reset control register to protect from deactivation\r
-  // the config write state\r
-  MmioWrite16 (PciRegBase + R_CONTROL_STATUS, CS_RESET_CLR);\r
-\r
-  // Convert to Marvell MAC Address register format\r
-  MacHigh = SwapBytes32 ((MacHigh & 0xFFFF) << 16 |\r
-                         (MacLow & 0xFFFF0000) >> 16);\r
-  MacLow = SwapBytes32 (MacLow) >> 16;\r
-\r
-  // Set MAC Address\r
-  MmioWrite8 (PciRegBase + R_TST_CTRL_1, TST_CFG_WRITE_ENABLE);\r
-  MmioWrite32 (PciRegBase + R_MAC, MacHigh);\r
-  MmioWrite32 (PciRegBase + R_MAC_MAINT, MacHigh);\r
-  MmioWrite32 (PciRegBase + R_MAC + R_MAC_LOW, MacLow);\r
-  MmioWrite32 (PciRegBase + R_MAC_MAINT + R_MAC_LOW, MacLow);\r
-  MmioWrite8 (PciRegBase + R_TST_CTRL_1, TST_CFG_WRITE_DISABLE);\r
-\r
-  // Initiate device reset\r
-  MmioWrite16 (PciRegBase + R_CONTROL_STATUS, CS_RESET_SET);\r
-  MmioWrite16 (PciRegBase + R_CONTROL_STATUS, CS_RESET_CLR);\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  The function reads MAC address from Juno IOFPGA registers and writes it\r
-  into Marvell Yukon NIC.\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-ArmJunoSetNicMacAddress ()\r
-{\r
-  UINT64                              OldPciAttr;\r
-  EFI_PCI_IO_PROTOCOL*                PciIo;\r
-  UINT32                              PciRegBase;\r
-  EFI_STATUS                          Status;\r
-\r
-  Status = GetMarvellYukonPciIoProtocol (&PciIo);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  PciRegBase = 0;\r
-  Status = InitPciDev (PciIo, &PciRegBase, &OldPciAttr);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  Status = WriteMacAddress (PciRegBase);\r
-\r
-  RestorePciDev (PciIo, OldPciAttr);\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Notification function of the event defined as belonging to the\r
-  EFI_END_OF_DXE_EVENT_GROUP_GUID event group that was created in\r
-  the entry point of the driver.\r
-\r
-  This function is called when an event belonging to the\r
-  EFI_END_OF_DXE_EVENT_GROUP_GUID event group is signalled. Such an\r
-  event is signalled once at the end of the dispatching of all\r
-  drivers (end of the so called DXE phase).\r
-\r
-  @param[in]  Event    Event declared in the entry point of the driver whose\r
-                       notification function is being invoked.\r
-  @param[in]  Context  NULL\r
-**/\r
-STATIC\r
-VOID\r
-OnEndOfDxe (\r
-  IN EFI_EVENT  Event,\r
-  IN VOID       *Context\r
-  )\r
-{\r
-  EFI_DEVICE_PATH_PROTOCOL* PciRootComplexDevicePath;\r
-  EFI_HANDLE                Handle;\r
-  EFI_STATUS                Status;\r
-\r
-  //\r
-  // PCI Root Complex initialization\r
-  // At the end of the DXE phase, we should get all the driver dispatched.\r
-  // Force the PCI Root Complex to be initialized. It allows the OS to skip\r
-  // this step.\r
-  //\r
-  PciRootComplexDevicePath = (EFI_DEVICE_PATH_PROTOCOL*) &mPciRootComplexDevicePath;\r
-  Status = gBS->LocateDevicePath (&gEfiPciRootBridgeIoProtocolGuid,\r
-                                  &PciRootComplexDevicePath,\r
-                                  &Handle);\r
-\r
-  Status = gBS->ConnectController (Handle, NULL, PciRootComplexDevicePath, FALSE);\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  Status = ArmJunoSetNicMacAddress ();\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR, "ArmJunoDxe: Failed to set Marvell Yukon NIC MAC address\n"));\r
-  }\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-ArmJunoEntryPoint (\r
-  IN EFI_HANDLE         ImageHandle,\r
-  IN EFI_SYSTEM_TABLE   *SystemTable\r
-  )\r
-{\r
-  EFI_STATUS            Status;\r
-  EFI_PHYSICAL_ADDRESS  HypBase;\r
-  CHAR16                *TextDevicePath;\r
-  UINTN                 TextDevicePathSize;\r
-  VOID                  *Buffer;\r
-  UINT32                JunoRevision;\r
-  EFI_EVENT             EndOfDxeEvent;\r
-\r
-  //\r
-  // Register the OHCI and EHCI controllers as non-coherent\r
-  // non-discoverable devices.\r
-  //\r
-  Status = RegisterNonDiscoverableMmioDevice (\r
-             NonDiscoverableDeviceTypeOhci,\r
-             NonDiscoverableDeviceDmaTypeNonCoherent,\r
-             NULL,\r
-             NULL,\r
-             1,\r
-             FixedPcdGet32 (PcdSynopsysUsbOhciBaseAddress),\r
-             SIZE_64KB\r
-             );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  Status = RegisterNonDiscoverableMmioDevice (\r
-             NonDiscoverableDeviceTypeEhci,\r
-             NonDiscoverableDeviceDmaTypeNonCoherent,\r
-             NULL,\r
-             NULL,\r
-             1,\r
-             FixedPcdGet32 (PcdSynopsysUsbEhciBaseAddress),\r
-             SIZE_64KB\r
-             );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // If a hypervisor has been declared then we need to make sure its region is protected at runtime\r
-  //\r
-  // Note: This code is only a workaround for our dummy hypervisor (ArmPkg/Extra/AArch64ToAArch32Shim/)\r
-  //       that does not set up (yet) the stage 2 translation table to hide its own memory to EL1.\r
-  //\r
-  if (FixedPcdGet32 (PcdHypFvSize) != 0) {\r
-    // Ensure the hypervisor region is strictly contained into a EFI_PAGE_SIZE-aligned region.\r
-    // The memory must be a multiple of EFI_PAGE_SIZE to ensure we do not reserve more memory than the hypervisor itself.\r
-    // A UEFI Runtime region size granularity cannot be smaller than EFI_PAGE_SIZE. If the hypervisor size is not rounded\r
-    // to this size then there is a risk some non-runtime memory could be visible to the OS view.\r
-    if (((FixedPcdGet32 (PcdHypFvSize) & EFI_PAGE_MASK) == 0) && ((FixedPcdGet32 (PcdHypFvBaseAddress) & EFI_PAGE_MASK) == 0)) {\r
-      // The memory needs to be declared because the DXE core marked it as reserved and removed it from the memory space\r
-      // as it contains the Firmware.\r
-      Status = gDS->AddMemorySpace (\r
-          EfiGcdMemoryTypeSystemMemory,\r
-          FixedPcdGet32 (PcdHypFvBaseAddress), FixedPcdGet32 (PcdHypFvSize),\r
-          EFI_MEMORY_WB | EFI_MEMORY_RUNTIME\r
-          );\r
-      if (!EFI_ERROR (Status)) {\r
-        // We allocate the memory to ensure it is marked as runtime memory\r
-        HypBase = FixedPcdGet32 (PcdHypFvBaseAddress);\r
-        Status = gBS->AllocatePages (AllocateAddress, EfiRuntimeServicesCode,\r
-                                     EFI_SIZE_TO_PAGES (FixedPcdGet32 (PcdHypFvSize)), &HypBase);\r
-      }\r
-    } else {\r
-      // The hypervisor must be contained into a EFI_PAGE_SIZE-aligned region and its size must also be aligned\r
-      // on a EFI_PAGE_SIZE boundary (ie: 4KB).\r
-      Status = EFI_UNSUPPORTED;\r
-      ASSERT_EFI_ERROR (Status);\r
-    }\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
-  }\r
-\r
-  // Install dynamic Shell command to run baremetal binaries.\r
-  Status = ShellDynCmdRunAxfInstall (ImageHandle);\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "ArmJunoDxe: Failed to install ShellDynCmdRunAxf\n"));\r
-  }\r
-\r
-  GetJunoRevision(JunoRevision);\r
-\r
-  //\r
-  // Try to install the ACPI Tables\r
-  //\r
-  Status = LocateAndInstallAcpiFromFv (&mJunoAcpiTableFile);\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // Setup R1/R2 options if not already done.\r
-  //\r
-  if (JunoRevision != JUNO_REVISION_R0) {\r
-    // Enable PCI enumeration\r
-    PcdSetBool (PcdPciDisableBusEnumeration, FALSE);\r
-\r
-    //\r
-    // Create an event belonging to the "gEfiEndOfDxeEventGroupGuid" group.\r
-    // The "OnEndOfDxe()" function is declared as the call back function.\r
-    // It will be called at the end of the DXE phase when an event of the\r
-    // same group is signalled to inform about the end of the DXE phase.\r
-    // Install the INSTALL_FDT_PROTOCOL protocol.\r
-    //\r
-    Status = gBS->CreateEventEx (\r
-                    EVT_NOTIFY_SIGNAL,\r
-                    TPL_CALLBACK,\r
-                    OnEndOfDxe,\r
-                    NULL,\r
-                    &gEfiEndOfDxeEventGroupGuid,\r
-                    &EndOfDxeEvent\r
-                    );\r
-\r
-    // Declare the related ACPI Tables\r
-    EfiCreateProtocolNotifyEvent (\r
-        &gEfiAcpiTableProtocolGuid,\r
-        TPL_CALLBACK,\r
-        AcpiPciNotificationEvent,\r
-        NULL,\r
-        &mAcpiRegistration\r
-        );\r
-  }\r
-\r
-  //\r
-  // Set up the device path to the FDT.\r
-  //\r
-  TextDevicePath = (CHAR16*)FixedPcdGetPtr (PcdJunoFdtDevicePath);\r
-  if (TextDevicePath != NULL) {\r
-    TextDevicePathSize = StrSize (TextDevicePath);\r
-    Buffer = PcdSetPtr (PcdFdtDevicePaths, &TextDevicePathSize, TextDevicePath);\r
-    Status = (Buffer != NULL) ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL;\r
-  } else {\r
-    Status = EFI_NOT_FOUND;\r
-  }\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG (\r
-      (EFI_D_ERROR,\r
-      "ArmJunoDxe: Setting of FDT device path in PcdFdtDevicePaths failed - %r\n", Status)\r
-      );\r
-    return Status;\r
-  }\r
-\r
-  return Status;\r
-}\r