async def METHOD_NAME(
    prompt: str = "Enter PIN",
    allow_cancel: bool = True,
    retry: bool = True,
    cache_time_ms: int = 0,
) -> None:
    # _get_last_unlock_time
    last_unlock = int.from_bytes(
        storage_cache.get(storage_cache.APP_COMMON_REQUEST_PIN_LAST_UNLOCK, b""), "big"
    )
    if (
        cache_time_ms
        and last_unlock
        and utime.ticks_ms() - last_unlock <= cache_time_ms
        and config.is_unlocked()
    ):
        return
    if config.has_pin():
        from trezor.ui.layouts import request_pin_on_device
        pin = await request_pin_on_device(prompt, config.get_pin_rem(), allow_cancel)
        config.ensure_not_wipe_code(pin)
    else:
        pin = ""
    salt = await _request_sd_salt(raise_cancelled_on_unavailable=True)
    if config.unlock(pin, salt):
        _set_last_unlock_time()
        return
    elif not config.has_pin():
        raise RuntimeError
    while retry:
        pin = await request_pin_on_device(  # type: ignore ["request_pin_on_device" is possibly unbound]
            "Enter PIN", config.get_pin_rem(), allow_cancel, wrong_pin=True
        )
        if config.unlock(pin, salt):
            _set_last_unlock_time()
            return
    raise wire.PinInvalid