diff --git a/src/input_common/drivers/joycon.cpp b/src/input_common/drivers/joycon.cpp
index 8b57ebe07e..653862a727 100644
--- a/src/input_common/drivers/joycon.cpp
+++ b/src/input_common/drivers/joycon.cpp
@@ -195,8 +195,8 @@ void Joycons::RegisterNewDevice(SDL_hid_device_info* device_info) {
                 OnMotionUpdate(port, type, id, value);
             }},
             .on_ring_data = {[this](f32 ring_data) { OnRingConUpdate(ring_data); }},
-            .on_amiibo_data = {[this, port](const std::vector<u8>& amiibo_data) {
-                OnAmiiboUpdate(port, amiibo_data);
+            .on_amiibo_data = {[this, port, type](const std::vector<u8>& amiibo_data) {
+                OnAmiiboUpdate(port, type, amiibo_data);
             }},
             .on_camera_data = {[this, port](const std::vector<u8>& camera_data,
                                             Joycon::IrsResolution format) {
@@ -398,8 +398,9 @@ void Joycons::OnRingConUpdate(f32 ring_data) {
     SetAxis(identifier, 100, ring_data);
 }
 
-void Joycons::OnAmiiboUpdate(std::size_t port, const std::vector<u8>& amiibo_data) {
-    const auto identifier = GetIdentifier(port, Joycon::ControllerType::Right);
+void Joycons::OnAmiiboUpdate(std::size_t port, Joycon::ControllerType type,
+                             const std::vector<u8>& amiibo_data) {
+    const auto identifier = GetIdentifier(port, type);
     const auto nfc_state = amiibo_data.empty() ? Common::Input::NfcState::AmiiboRemoved
                                                : Common::Input::NfcState::NewAmiibo;
     SetNfc(identifier, {nfc_state, amiibo_data});
diff --git a/src/input_common/drivers/joycon.h b/src/input_common/drivers/joycon.h
index 5b40817e28..e3f0ad78f9 100644
--- a/src/input_common/drivers/joycon.h
+++ b/src/input_common/drivers/joycon.h
@@ -81,7 +81,8 @@ private:
     void OnMotionUpdate(std::size_t port, Joycon::ControllerType type, int id,
                         const Joycon::MotionData& value);
     void OnRingConUpdate(f32 ring_data);
-    void OnAmiiboUpdate(std::size_t port, const std::vector<u8>& amiibo_data);
+    void OnAmiiboUpdate(std::size_t port, Joycon::ControllerType type,
+                        const std::vector<u8>& amiibo_data);
     void OnCameraUpdate(std::size_t port, const std::vector<u8>& camera_data,
                         Joycon::IrsResolution format);
 
diff --git a/src/input_common/helpers/joycon_protocol/common_protocol.cpp b/src/input_common/helpers/joycon_protocol/common_protocol.cpp
index 077d72cd03..51669261a7 100644
--- a/src/input_common/helpers/joycon_protocol/common_protocol.cpp
+++ b/src/input_common/helpers/joycon_protocol/common_protocol.cpp
@@ -265,7 +265,7 @@ DriverResult JoyconCommonProtocol::SendMCUData(ReportMode report_mode, MCUSubCom
 
 DriverResult JoyconCommonProtocol::WaitSetMCUMode(ReportMode report_mode, MCUMode mode) {
     MCUCommandResponse output{};
-    constexpr std::size_t MaxTries{8};
+    constexpr std::size_t MaxTries{16};
     std::size_t tries{};
 
     do {
diff --git a/src/input_common/helpers/joycon_protocol/joycon_types.h b/src/input_common/helpers/joycon_protocol/joycon_types.h
index 1c8d294b0e..353dc744d5 100644
--- a/src/input_common/helpers/joycon_protocol/joycon_types.h
+++ b/src/input_common/helpers/joycon_protocol/joycon_types.h
@@ -577,8 +577,8 @@ static_assert(sizeof(NFCPollingCommandData) == 0x05, "NFCPollingCommandData is a
 
 struct NFCRequestState {
     NFCReadCommand command_argument;
-    u8 packet_id;
     INSERT_PADDING_BYTES(0x1);
+    u8 packet_id;
     MCUPacketFlag packet_flag;
     u8 data_length;
     union {
diff --git a/src/input_common/helpers/joycon_protocol/nfc.cpp b/src/input_common/helpers/joycon_protocol/nfc.cpp
index 14818ae332..46c9e9489f 100644
--- a/src/input_common/helpers/joycon_protocol/nfc.cpp
+++ b/src/input_common/helpers/joycon_protocol/nfc.cpp
@@ -64,6 +64,20 @@ DriverResult NfcProtocol::StartNFCPollingMode() {
     if (result == DriverResult::Success) {
         result = WaitUntilNfcIsReady();
     }
+    if (result == DriverResult::Success) {
+        MCUCommandResponse output{};
+        result = SendStopPollingRequest(output);
+    }
+    if (result == DriverResult::Success) {
+        result = WaitUntilNfcIsReady();
+    }
+    if (result == DriverResult::Success) {
+        MCUCommandResponse output{};
+        result = SendStartPollingRequest(output);
+    }
+    if (result == DriverResult::Success) {
+        result = WaitUntilNfcIsPolling();
+    }
     if (result == DriverResult::Success) {
         is_enabled = true;
     }
@@ -77,24 +91,21 @@ DriverResult NfcProtocol::ScanAmiibo(std::vector<u8>& data) {
     }
     update_counter = 0;
 
-    LOG_DEBUG(Input, "Start NFC pooling Mode");
+    LOG_DEBUG(Input, "Scan for amiibos");
     ScopedSetBlocking sb(this);
     DriverResult result{DriverResult::Success};
     TagFoundData tag_data{};
 
     if (result == DriverResult::Success) {
-        result = StartPolling(tag_data);
-    }
-    if (result == DriverResult::Success) {
-        result = ReadTag(tag_data);
-    }
-    if (result == DriverResult::Success) {
-        result = WaitUntilNfcIsReady();
-    }
-    if (result == DriverResult::Success) {
-        result = StartPolling(tag_data, 7);
+        result = IsTagInRange(tag_data);
     }
+
     if (result == DriverResult::Success) {
+        std::string uuid_string;
+        for (auto& content : tag_data.uuid) {
+            uuid_string += fmt::format(" {:02x}", content);
+        }
+        LOG_INFO(Input, "Tag detected, type={}, uuid={}", tag_data.type, uuid_string);
         result = GetAmiiboData(data);
     }
 
@@ -102,12 +113,17 @@ DriverResult NfcProtocol::ScanAmiibo(std::vector<u8>& data) {
 }
 
 bool NfcProtocol::HasAmiibo() {
+    if (update_counter++ < AMIIBO_UPDATE_DELAY) {
+        return true;
+    }
+    update_counter = 0;
+
     ScopedSetBlocking sb(this);
     DriverResult result{DriverResult::Success};
     TagFoundData tag_data{};
 
     if (result == DriverResult::Success) {
-        result = StartPolling(tag_data);
+        result = IsTagInRange(tag_data, 7);
     }
 
     return result == DriverResult::Success;
@@ -119,7 +135,7 @@ DriverResult NfcProtocol::WaitUntilNfcIsReady() {
     std::size_t tries = 0;
 
     do {
-        auto result = SendStartWaitingRecieveRequest(output);
+        auto result = SendNextPackageRequest(output, {});
 
         if (result != DriverResult::Success) {
             return result;
@@ -134,13 +150,14 @@ DriverResult NfcProtocol::WaitUntilNfcIsReady() {
     return DriverResult::Success;
 }
 
-DriverResult NfcProtocol::StartPolling(TagFoundData& data, std::size_t timeout_limit) {
-    LOG_DEBUG(Input, "Start Polling for tag");
+DriverResult NfcProtocol::WaitUntilNfcIsPolling() {
+    constexpr std::size_t timeout_limit = 10;
     MCUCommandResponse output{};
     std::size_t tries = 0;
 
     do {
-        const auto result = SendStartPollingRequest(output);
+        auto result = SendNextPackageRequest(output, {});
+
         if (result != DriverResult::Success) {
             return result;
         }
@@ -149,7 +166,26 @@ DriverResult NfcProtocol::StartPolling(TagFoundData& data, std::size_t timeout_l
         }
     } while (output.mcu_report != MCUReport::NFCState ||
              (output.mcu_data[1] << 8) + output.mcu_data[0] != 0x0500 ||
-             output.mcu_data[6] != 0x09);
+             output.mcu_data[5] != 0x31 || output.mcu_data[6] != 0x01);
+
+    return DriverResult::Success;
+}
+
+DriverResult NfcProtocol::IsTagInRange(TagFoundData& data, std::size_t timeout_limit) {
+    MCUCommandResponse output{};
+    std::size_t tries = 0;
+
+    do {
+        const auto result = SendNextPackageRequest(output, {});
+        if (result != DriverResult::Success) {
+            return result;
+        }
+        if (tries++ > timeout_limit) {
+            return DriverResult::Timeout;
+        }
+    } while (output.mcu_report != MCUReport::NFCState ||
+             (output.mcu_data[1] << 8) + output.mcu_data[0] != 0x0500 ||
+             (output.mcu_data[6] != 0x09 && output.mcu_data[6] != 0x04));
 
     data.type = output.mcu_data[12];
     data.uuid.resize(output.mcu_data[14]);
@@ -158,85 +194,22 @@ DriverResult NfcProtocol::StartPolling(TagFoundData& data, std::size_t timeout_l
     return DriverResult::Success;
 }
 
-DriverResult NfcProtocol::ReadTag(const TagFoundData& data) {
-    constexpr std::size_t timeout_limit = 10;
-    MCUCommandResponse output{};
-    std::size_t tries = 0;
-
-    std::string uuid_string;
-    for (auto& content : data.uuid) {
-        uuid_string += fmt::format(" {:02x}", content);
-    }
-
-    LOG_INFO(Input, "Tag detected, type={}, uuid={}", data.type, uuid_string);
-
-    tries = 0;
-    NFCPages ntag_pages = NFCPages::Block0;
-    // Read Tag data
-    while (true) {
-        auto result = SendReadAmiiboRequest(output, ntag_pages);
-        const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]);
-
-        if (result != DriverResult::Success) {
-            return result;
-        }
-
-        if ((output.mcu_report == MCUReport::NFCReadData ||
-             output.mcu_report == MCUReport::NFCState) &&
-            nfc_status == NFCStatus::TagLost) {
-            return DriverResult::ErrorReadingData;
-        }
-
-        if (output.mcu_report == MCUReport::NFCReadData && output.mcu_data[1] == 0x07 &&
-            output.mcu_data[2] == 0x01) {
-            if (data.type != 2) {
-                continue;
-            }
-            switch (output.mcu_data[24]) {
-            case 0:
-                ntag_pages = NFCPages::Block135;
-                break;
-            case 3:
-                ntag_pages = NFCPages::Block45;
-                break;
-            case 4:
-                ntag_pages = NFCPages::Block231;
-                break;
-            default:
-                return DriverResult::ErrorReadingData;
-            }
-            continue;
-        }
-
-        if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::LastPackage) {
-            // finished
-            SendStopPollingRequest(output);
-            return DriverResult::Success;
-        }
-
-        // Ignore other state reports
-        if (output.mcu_report == MCUReport::NFCState) {
-            continue;
-        }
-
-        if (tries++ > timeout_limit) {
-            return DriverResult::Timeout;
-        }
-    }
-
-    return DriverResult::Success;
-}
-
 DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) {
-    constexpr std::size_t timeout_limit = 10;
+    constexpr std::size_t timeout_limit = 60;
     MCUCommandResponse output{};
     std::size_t tries = 0;
 
-    NFCPages ntag_pages = NFCPages::Block135;
+    u8 package_index = 0;
     std::size_t ntag_buffer_pos = 0;
+    auto result = SendReadAmiiboRequest(output, NFCPages::Block135);
+
+    if (result != DriverResult::Success) {
+        return result;
+    }
+
     // Read Tag data
-    while (true) {
-        auto result = SendReadAmiiboRequest(output, ntag_pages);
+    while (tries++ < timeout_limit) {
+        result = SendNextPackageRequest(output, package_index);
         const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]);
 
         if (result != DriverResult::Success) {
@@ -259,6 +232,7 @@ DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) {
                 memcpy(ntag_data.data() + ntag_buffer_pos, output.mcu_data.data() + 6,
                        payload_size);
             }
+            package_index++;
             continue;
         }
 
@@ -266,18 +240,9 @@ DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) {
             LOG_INFO(Input, "Finished reading amiibo");
             return DriverResult::Success;
         }
-
-        // Ignore other state reports
-        if (output.mcu_report == MCUReport::NFCState) {
-            continue;
-        }
-
-        if (tries++ > timeout_limit) {
-            return DriverResult::Timeout;
-        }
     }
 
-    return DriverResult::Success;
+    return DriverResult::Timeout;
 }
 
 DriverResult NfcProtocol::SendStartPollingRequest(MCUCommandResponse& output) {
@@ -321,10 +286,10 @@ DriverResult NfcProtocol::SendStopPollingRequest(MCUCommandResponse& output) {
                        output);
 }
 
-DriverResult NfcProtocol::SendStartWaitingRecieveRequest(MCUCommandResponse& output) {
+DriverResult NfcProtocol::SendNextPackageRequest(MCUCommandResponse& output, u8 packet_id) {
     NFCRequestState request{
         .command_argument = NFCReadCommand::StartWaitingRecieve,
-        .packet_id = 0x0,
+        .packet_id = packet_id,
         .packet_flag = MCUPacketFlag::LastCommandPacket,
         .data_length = 0,
         .raw_data = {},
diff --git a/src/input_common/helpers/joycon_protocol/nfc.h b/src/input_common/helpers/joycon_protocol/nfc.h
index 4cb992d1d3..c9e9af03fa 100644
--- a/src/input_common/helpers/joycon_protocol/nfc.h
+++ b/src/input_common/helpers/joycon_protocol/nfc.h
@@ -42,9 +42,9 @@ private:
 
     DriverResult WaitUntilNfcIsReady();
 
-    DriverResult StartPolling(TagFoundData& data, std::size_t timeout_limit = 1);
+    DriverResult WaitUntilNfcIsPolling();
 
-    DriverResult ReadTag(const TagFoundData& data);
+    DriverResult IsTagInRange(TagFoundData& data, std::size_t timeout_limit = 1);
 
     DriverResult GetAmiiboData(std::vector<u8>& data);
 
@@ -52,7 +52,7 @@ private:
 
     DriverResult SendStopPollingRequest(MCUCommandResponse& output);
 
-    DriverResult SendStartWaitingRecieveRequest(MCUCommandResponse& output);
+    DriverResult SendNextPackageRequest(MCUCommandResponse& output, u8 packet_id);
 
     DriverResult SendReadAmiiboRequest(MCUCommandResponse& output, NFCPages ntag_pages);