diff --git a/homeassistant/components/prusalink/__init__.py b/homeassistant/components/prusalink/__init__.py
index 98dc7cb47ae..b6a00bbaf10 100644
--- a/homeassistant/components/prusalink/__init__.py
+++ b/homeassistant/components/prusalink/__init__.py
@@ -20,6 +20,7 @@ from homeassistant.const import (
     Platform,
 )
 from homeassistant.core import HomeAssistant, callback
+from homeassistant.exceptions import ConfigEntryError
 from homeassistant.helpers import issue_registry as ir
 from homeassistant.helpers.aiohttp_client import async_get_clientsession
 from homeassistant.helpers.device_registry import DeviceInfo
@@ -29,73 +30,24 @@ from homeassistant.helpers.update_coordinator import (
     UpdateFailed,
 )
 
+from .config_flow import ConfigFlow
 from .const import DOMAIN
 
 PLATFORMS: list[Platform] = [Platform.BUTTON, Platform.CAMERA, Platform.SENSOR]
 _LOGGER = logging.getLogger(__name__)
 
 
-async def _migrate_to_version_2(
-    hass: HomeAssistant, entry: ConfigEntry
-) -> PrusaLink | None:
-    """Migrate to Version 2."""
-    _LOGGER.debug("Migrating entry to version 2")
-
-    data = dict(entry.data)
-    # "maker" is currently hardcoded in the firmware
-    # https://github.com/prusa3d/Prusa-Firmware-Buddy/blob/bfb0ffc745ee6546e7efdba618d0e7c0f4c909cd/lib/WUI/wui_api.h#L19
-    data = {
-        **entry.data,
-        CONF_USERNAME: "maker",
-        CONF_PASSWORD: entry.data[CONF_API_KEY],
-    }
-    data.pop(CONF_API_KEY)
+async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
+    """Set up PrusaLink from a config entry."""
+    if entry.version == 1 and entry.minor_version < 2:
+        raise ConfigEntryError("Please upgrade your printer's firmware.")
 
     api = PrusaLink(
         async_get_clientsession(hass),
-        data[CONF_HOST],
-        data[CONF_USERNAME],
-        data[CONF_PASSWORD],
+        entry.data[CONF_HOST],
+        entry.data[CONF_USERNAME],
+        entry.data[CONF_PASSWORD],
     )
-    try:
-        await api.get_info()
-    except InvalidAuth:
-        # We are unable to reach the new API which usually means
-        # that the user is running an outdated firmware version
-        ir.async_create_issue(
-            hass,
-            DOMAIN,
-            "firmware_5_1_required",
-            is_fixable=False,
-            severity=ir.IssueSeverity.ERROR,
-            translation_key="firmware_5_1_required",
-            translation_placeholders={
-                "entry_title": entry.title,
-                "prusa_mini_firmware_update": "https://help.prusa3d.com/article/firmware-updating-mini-mini_124784",
-                "prusa_mk4_xl_firmware_update": "https://help.prusa3d.com/article/how-to-update-firmware-mk4-xl_453086",
-            },
-        )
-        return None
-
-    entry.version = 2
-    hass.config_entries.async_update_entry(entry, data=data)
-    _LOGGER.info("Migrated config entry to version %d", entry.version)
-    return api
-
-
-async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
-    """Set up PrusaLink from a config entry."""
-    if entry.version == 1:
-        if (api := await _migrate_to_version_2(hass, entry)) is None:
-            return False
-        ir.async_delete_issue(hass, DOMAIN, "firmware_5_1_required")
-    else:
-        api = PrusaLink(
-            async_get_clientsession(hass),
-            entry.data[CONF_HOST],
-            entry.data[CONF_USERNAME],
-            entry.data[CONF_PASSWORD],
-        )
 
     coordinators = {
         "legacy_status": LegacyStatusCoordinator(hass, api),
@@ -112,9 +64,59 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
     return True
 
 
-async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
+async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
     """Migrate old entry."""
-    # Version 1->2 migration are handled in async_setup_entry.
+    if config_entry.version > ConfigFlow.VERSION:
+        # This means the user has downgraded from a future version
+        return False
+
+    new_data = dict(config_entry.data)
+    if config_entry.version == 1:
+        if config_entry.minor_version < 2:
+            # Add username and password
+            # "maker" is currently hardcoded in the firmware
+            # https://github.com/prusa3d/Prusa-Firmware-Buddy/blob/bfb0ffc745ee6546e7efdba618d0e7c0f4c909cd/lib/WUI/wui_api.h#L19
+            username = "maker"
+            password = config_entry.data[CONF_API_KEY]
+
+            api = PrusaLink(
+                async_get_clientsession(hass),
+                config_entry.data[CONF_HOST],
+                username,
+                password,
+            )
+            try:
+                await api.get_info()
+            except InvalidAuth:
+                # We are unable to reach the new API which usually means
+                # that the user is running an outdated firmware version
+                ir.async_create_issue(
+                    hass,
+                    DOMAIN,
+                    "firmware_5_1_required",
+                    is_fixable=False,
+                    severity=ir.IssueSeverity.ERROR,
+                    translation_key="firmware_5_1_required",
+                    translation_placeholders={
+                        "entry_title": config_entry.title,
+                        "prusa_mini_firmware_update": "https://help.prusa3d.com/article/firmware-updating-mini-mini_124784",
+                        "prusa_mk4_xl_firmware_update": "https://help.prusa3d.com/article/how-to-update-firmware-mk4-xl_453086",
+                    },
+                )
+                # There is a check in the async_setup_entry to prevent the setup if minor_version < 2
+                # Currently we can't reload the config entry
+                # if the migration returns False.
+                # Return True here to workaround that.
+                return True
+
+            new_data[CONF_USERNAME] = username
+            new_data[CONF_PASSWORD] = password
+
+        ir.async_delete_issue(hass, DOMAIN, "firmware_5_1_required")
+        config_entry.minor_version = 2
+
+        hass.config_entries.async_update_entry(config_entry, data=new_data)
+
     return True
 
 
diff --git a/homeassistant/components/prusalink/config_flow.py b/homeassistant/components/prusalink/config_flow.py
index e967cefaffd..378c5e7395a 100644
--- a/homeassistant/components/prusalink/config_flow.py
+++ b/homeassistant/components/prusalink/config_flow.py
@@ -66,7 +66,8 @@ async def validate_input(hass: HomeAssistant, data: dict[str, str]) -> dict[str,
 class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
     """Handle a config flow for PrusaLink."""
 
-    VERSION = 2
+    VERSION = 1
+    MINOR_VERSION = 2
 
     async def async_step_user(
         self, user_input: dict[str, Any] | None = None
diff --git a/tests/components/prusalink/conftest.py b/tests/components/prusalink/conftest.py
index 97f4bd92d7d..1e514342068 100644
--- a/tests/components/prusalink/conftest.py
+++ b/tests/components/prusalink/conftest.py
@@ -14,7 +14,8 @@ def mock_config_entry(hass):
     entry = MockConfigEntry(
         domain=DOMAIN,
         data={"host": "http://example.com", "username": "dummy", "password": "dummypw"},
-        version=2,
+        version=1,
+        minor_version=2,
     )
     entry.add_to_hass(hass)
     return entry
diff --git a/tests/components/prusalink/test_init.py b/tests/components/prusalink/test_init.py
index 963750ef8be..5b261207e93 100644
--- a/tests/components/prusalink/test_init.py
+++ b/tests/components/prusalink/test_init.py
@@ -6,6 +6,7 @@ from pyprusalink.types import InvalidAuth, PrusaLinkError
 import pytest
 
 from homeassistant.components.prusalink import DOMAIN
+from homeassistant.components.prusalink.config_flow import ConfigFlow
 from homeassistant.config_entries import ConfigEntry, ConfigEntryState
 from homeassistant.const import CONF_API_KEY, CONF_HOST, CONF_PASSWORD, CONF_USERNAME
 from homeassistant.core import HomeAssistant
@@ -14,11 +15,12 @@ from homeassistant.util.dt import utcnow
 
 from tests.common import MockConfigEntry, async_fire_time_changed
 
+pytestmark = pytest.mark.usefixtures("mock_api")
+
 
 async def test_unloading(
     hass: HomeAssistant,
     mock_config_entry: ConfigEntry,
-    mock_api,
 ) -> None:
     """Test unloading prusalink."""
     assert await hass.config_entries.async_setup(mock_config_entry.entry_id)
@@ -35,7 +37,7 @@ async def test_unloading(
 
 @pytest.mark.parametrize("exception", [InvalidAuth, PrusaLinkError])
 async def test_failed_update(
-    hass: HomeAssistant, mock_config_entry: ConfigEntry, mock_api, exception
+    hass: HomeAssistant, mock_config_entry: ConfigEntry, exception
 ) -> None:
     """Test failed update marks prusalink unavailable."""
     assert await hass.config_entries.async_setup(mock_config_entry.entry_id)
@@ -61,16 +63,17 @@ async def test_failed_update(
         assert state.state == "unavailable"
 
 
-async def test_migration_1_2(
-    hass: HomeAssistant, issue_registry: ir.IssueRegistry, mock_api
+async def test_migration_from_1_1_to_1_2(
+    hass: HomeAssistant, issue_registry: ir.IssueRegistry
 ) -> None:
     """Test migrating from version 1 to 2."""
+    data = {
+        CONF_HOST: "http://prusaxl.local",
+        CONF_API_KEY: "api-key",
+    }
     entry = MockConfigEntry(
         domain=DOMAIN,
-        data={
-            CONF_HOST: "http://prusaxl.local",
-            CONF_API_KEY: "api-key",
-        },
+        data=data,
         version=1,
     )
     entry.add_to_hass(hass)
@@ -83,7 +86,7 @@ async def test_migration_1_2(
     # Ensure that we have username, password after migration
     assert len(config_entries) == 1
     assert config_entries[0].data == {
-        CONF_HOST: "http://prusaxl.local",
+        **data,
         CONF_USERNAME: "maker",
         CONF_PASSWORD: "api-key",
     }
@@ -91,10 +94,10 @@ async def test_migration_1_2(
     assert len(issue_registry.issues) == 0
 
 
-async def test_outdated_firmware_migration_1_2(
-    hass: HomeAssistant, issue_registry: ir.IssueRegistry, mock_api
+async def test_migration_from_1_1_to_1_2_outdated_firmware(
+    hass: HomeAssistant, issue_registry: ir.IssueRegistry
 ) -> None:
-    """Test migrating from version 1 to 2."""
+    """Test migrating from version 1.1 to 1.2."""
     entry = MockConfigEntry(
         domain=DOMAIN,
         data={
@@ -107,14 +110,14 @@ async def test_outdated_firmware_migration_1_2(
 
     with patch(
         "pyprusalink.PrusaLink.get_info",
-        side_effect=InvalidAuth,
+        side_effect=InvalidAuth,  # Simulate firmware update required
     ):
         await hass.config_entries.async_setup(entry.entry_id)
         await hass.async_block_till_done()
 
     assert entry.state == ConfigEntryState.SETUP_ERROR
-    # Make sure that we don't have thrown the issues
-    assert len(issue_registry.issues) == 1
+    assert entry.minor_version == 1
+    assert (DOMAIN, "firmware_5_1_required") in issue_registry.issues
 
     # Reloading the integration with a working API (e.g. User updated firmware)
     await hass.config_entries.async_reload(entry.entry_id)
@@ -122,4 +125,22 @@ async def test_outdated_firmware_migration_1_2(
 
     # Integration should be running now, the issue should be gone
     assert entry.state == ConfigEntryState.LOADED
-    assert len(issue_registry.issues) == 0
+    assert entry.minor_version == 2
+    assert (DOMAIN, "firmware_5_1_required") not in issue_registry.issues
+
+
+async def test_migration_fails_on_future_version(
+    hass: HomeAssistant, issue_registry: ir.IssueRegistry
+) -> None:
+    """Test migrating fails on a version higher than the current one."""
+    entry = MockConfigEntry(
+        domain=DOMAIN,
+        data={},
+        version=ConfigFlow.VERSION + 1,
+    )
+    entry.add_to_hass(hass)
+
+    await hass.config_entries.async_setup(entry.entry_id)
+    await hass.async_block_till_done()
+
+    assert entry.state == ConfigEntryState.MIGRATION_ERROR