diff --git a/homeassistant/components/lutron_caseta/__init__.py b/homeassistant/components/lutron_caseta/__init__.py
index d697d6244b55f1b25843b69bb6050d259b8be622..b489fe9dba782b32dd4b746470863c39bf50c877 100644
--- a/homeassistant/components/lutron_caseta/__init__.py
+++ b/homeassistant/components/lutron_caseta/__init__.py
@@ -3,7 +3,6 @@
 from __future__ import annotations
 
 import asyncio
-import contextlib
 from itertools import chain
 import logging
 import ssl
@@ -37,11 +36,12 @@ from .const import (
     ATTR_SERIAL,
     ATTR_TYPE,
     BRIDGE_DEVICE_ID,
-    BRIDGE_TIMEOUT,
     CONF_CA_CERTS,
     CONF_CERTFILE,
     CONF_KEYFILE,
     CONF_SUBTYPE,
+    CONFIGURE_TIMEOUT,
+    CONNECT_TIMEOUT,
     DOMAIN,
     LUTRON_CASETA_BUTTON_EVENT,
     MANUFACTURER,
@@ -161,28 +161,40 @@ async def async_setup_entry(
     keyfile = hass.config.path(entry.data[CONF_KEYFILE])
     certfile = hass.config.path(entry.data[CONF_CERTFILE])
     ca_certs = hass.config.path(entry.data[CONF_CA_CERTS])
-    bridge = None
+    connected_future: asyncio.Future[None] = hass.loop.create_future()
+
+    def _on_connect() -> None:
+        nonlocal connected_future
+        if not connected_future.done():
+            connected_future.set_result(None)
 
     try:
         bridge = Smartbridge.create_tls(
-            hostname=host, keyfile=keyfile, certfile=certfile, ca_certs=ca_certs
+            hostname=host,
+            keyfile=keyfile,
+            certfile=certfile,
+            ca_certs=ca_certs,
+            on_connect_callback=_on_connect,
         )
     except ssl.SSLError:
         _LOGGER.error("Invalid certificate used to connect to bridge at %s", host)
         return False
 
-    timed_out = True
-    with contextlib.suppress(TimeoutError):
-        async with asyncio.timeout(BRIDGE_TIMEOUT):
-            await bridge.connect()
-            timed_out = False
-
-    if timed_out or not bridge.is_connected():
-        await bridge.close()
-        if timed_out:
-            raise ConfigEntryNotReady(f"Timed out while trying to connect to {host}")
-        if not bridge.is_connected():
-            raise ConfigEntryNotReady(f"Cannot connect to {host}")
+    connect_task = hass.async_create_task(bridge.connect())
+    for future, name, timeout in (
+        (connected_future, "connect", CONNECT_TIMEOUT),
+        (connect_task, "configure", CONFIGURE_TIMEOUT),
+    ):
+        try:
+            async with asyncio.timeout(timeout):
+                await future
+        except TimeoutError as ex:
+            connect_task.cancel()
+            await bridge.close()
+            raise ConfigEntryNotReady(f"Timed out on {name} for {host}") from ex
+
+    if not bridge.is_connected():
+        raise ConfigEntryNotReady(f"Connection failed to {host}")
 
     _LOGGER.debug("Connected to Lutron Caseta bridge via LEAP at %s", host)
     await _async_migrate_unique_ids(hass, entry)
diff --git a/homeassistant/components/lutron_caseta/config_flow.py b/homeassistant/components/lutron_caseta/config_flow.py
index 767c3d2f2b78505e8e55051ee6a1edd09f04ef61..45e7a04bdc9e31e187a30d0cc192038dd3d12cf5 100644
--- a/homeassistant/components/lutron_caseta/config_flow.py
+++ b/homeassistant/components/lutron_caseta/config_flow.py
@@ -20,10 +20,11 @@ from homeassistant.helpers.service_info.zeroconf import ZeroconfServiceInfo
 from .const import (
     ABORT_REASON_CANNOT_CONNECT,
     BRIDGE_DEVICE_ID,
-    BRIDGE_TIMEOUT,
     CONF_CA_CERTS,
     CONF_CERTFILE,
     CONF_KEYFILE,
+    CONFIGURE_TIMEOUT,
+    CONNECT_TIMEOUT,
     DOMAIN,
     ERROR_CANNOT_CONNECT,
     STEP_IMPORT_FAILED,
@@ -232,7 +233,7 @@ class LutronCasetaFlowHandler(ConfigFlow, domain=DOMAIN):
             return None
 
         try:
-            async with asyncio.timeout(BRIDGE_TIMEOUT):
+            async with asyncio.timeout(CONNECT_TIMEOUT + CONFIGURE_TIMEOUT):
                 await bridge.connect()
         except TimeoutError:
             _LOGGER.error(
diff --git a/homeassistant/components/lutron_caseta/const.py b/homeassistant/components/lutron_caseta/const.py
index 809b9e8d007eb8466a26de135987bbbb720ba4b5..26a83de6f4b7200a68e0521406299e6121a4b10c 100644
--- a/homeassistant/components/lutron_caseta/const.py
+++ b/homeassistant/components/lutron_caseta/const.py
@@ -34,7 +34,8 @@ ACTION_RELEASE = "release"
 
 CONF_SUBTYPE = "subtype"
 
-BRIDGE_TIMEOUT = 35
+CONNECT_TIMEOUT = 9
+CONFIGURE_TIMEOUT = 50
 
 UNASSIGNED_AREA = "Unassigned"
 
diff --git a/tests/components/lutron_caseta/__init__.py b/tests/components/lutron_caseta/__init__.py
index b27d30ac31f3830eabf1486475fd58e328666130..5f146cd988ac318acf84038c6a5230920dc45efa 100644
--- a/tests/components/lutron_caseta/__init__.py
+++ b/tests/components/lutron_caseta/__init__.py
@@ -1,5 +1,8 @@
 """Tests for the Lutron Caseta integration."""
 
+import asyncio
+from collections.abc import Callable
+from typing import Any
 from unittest.mock import patch
 
 from homeassistant.components.lutron_caseta import DOMAIN
@@ -84,25 +87,12 @@ _LEAP_DEVICE_TYPES = {
 }
 
 
-async def async_setup_integration(hass: HomeAssistant, mock_bridge) -> MockConfigEntry:
-    """Set up a mock bridge."""
-    mock_entry = MockConfigEntry(domain=DOMAIN, data=ENTRY_MOCK_DATA)
-    mock_entry.add_to_hass(hass)
-
-    with patch(
-        "homeassistant.components.lutron_caseta.Smartbridge.create_tls"
-    ) as create_tls:
-        create_tls.return_value = mock_bridge(can_connect=True)
-        await hass.config_entries.async_setup(mock_entry.entry_id)
-        await hass.async_block_till_done()
-    return mock_entry
-
-
 class MockBridge:
     """Mock Lutron bridge that emulates configured connected status."""
 
-    def __init__(self, can_connect=True) -> None:
+    def __init__(self, can_connect=True, timeout_on_connect=False) -> None:
         """Initialize MockBridge instance with configured mock connectivity."""
+        self.timeout_on_connect = timeout_on_connect
         self.can_connect = can_connect
         self.is_currently_connected = False
         self.areas = self.load_areas()
@@ -113,6 +103,8 @@ class MockBridge:
 
     async def connect(self):
         """Connect the mock bridge."""
+        if self.timeout_on_connect:
+            await asyncio.Event().wait()  # wait forever
         if self.can_connect:
             self.is_currently_connected = True
 
@@ -320,3 +312,43 @@ class MockBridge:
     async def close(self):
         """Close the mock bridge connection."""
         self.is_currently_connected = False
+
+
+def make_mock_entry() -> MockConfigEntry:
+    """Create a mock config entry."""
+    return MockConfigEntry(domain=DOMAIN, data=ENTRY_MOCK_DATA)
+
+
+async def async_setup_integration(
+    hass: HomeAssistant,
+    mock_bridge: MockBridge,
+    config_entry_id: str | None = None,
+    can_connect: bool = True,
+    timeout_during_connect: bool = False,
+    timeout_during_configure: bool = False,
+) -> MockConfigEntry:
+    """Set up a mock bridge."""
+    if config_entry_id is None:
+        mock_entry = make_mock_entry()
+        mock_entry.add_to_hass(hass)
+        config_entry_id = mock_entry.entry_id
+    else:
+        mock_entry = hass.config_entries.async_get_entry(config_entry_id)
+
+    def create_tls_factory(
+        *args: Any, on_connect_callback: Callable[[], None], **kwargs: Any
+    ) -> None:
+        """Return a mock bridge."""
+        if not timeout_during_connect:
+            on_connect_callback()
+        return mock_bridge(
+            can_connect=can_connect, timeout_on_connect=timeout_during_configure
+        )
+
+    with patch(
+        "homeassistant.components.lutron_caseta.Smartbridge.create_tls",
+        create_tls_factory,
+    ):
+        await hass.config_entries.async_setup(config_entry_id)
+        await hass.async_block_till_done()
+    return mock_entry
diff --git a/tests/components/lutron_caseta/test_device_trigger.py b/tests/components/lutron_caseta/test_device_trigger.py
index 1ab45bf75824ad360c604567613fa053d13d29be..001bf86ad54b8069b3a6eaece500b65d715153f3 100644
--- a/tests/components/lutron_caseta/test_device_trigger.py
+++ b/tests/components/lutron_caseta/test_device_trigger.py
@@ -1,7 +1,5 @@
 """The tests for Lutron Caséta device triggers."""
 
-from unittest.mock import patch
-
 import pytest
 from pytest_unordered import unordered
 
@@ -37,7 +35,7 @@ from homeassistant.core import HomeAssistant, ServiceCall
 from homeassistant.helpers import device_registry as dr
 from homeassistant.setup import async_setup_component
 
-from . import MockBridge
+from . import MockBridge, async_setup_integration
 
 from tests.common import MockConfigEntry, async_get_device_automations
 
@@ -112,12 +110,7 @@ async def _async_setup_lutron_with_picos(hass: HomeAssistant) -> str:
     )
     config_entry.add_to_hass(hass)
 
-    with patch(
-        "homeassistant.components.lutron_caseta.Smartbridge.create_tls",
-        return_value=MockBridge(can_connect=True),
-    ):
-        await hass.config_entries.async_setup(config_entry.entry_id)
-        await hass.async_block_till_done()
+    await async_setup_integration(hass, MockBridge, config_entry.entry_id)
 
     return config_entry.entry_id
 
@@ -487,9 +480,7 @@ async def test_if_fires_on_button_event_late_setup(
         },
     )
 
-    with patch("homeassistant.components.lutron_caseta.Smartbridge.create_tls"):
-        await hass.config_entries.async_setup(config_entry_id)
-        await hass.async_block_till_done()
+    await async_setup_integration(hass, MockBridge, config_entry_id)
 
     message = {
         ATTR_SERIAL: device.get("serial"),
diff --git a/tests/components/lutron_caseta/test_diagnostics.py b/tests/components/lutron_caseta/test_diagnostics.py
index 5c7d20da2081d318e41dd7a0fc806a07bdf1248c..4522991857858885bdb2483d55d894bccb0315f3 100644
--- a/tests/components/lutron_caseta/test_diagnostics.py
+++ b/tests/components/lutron_caseta/test_diagnostics.py
@@ -1,6 +1,6 @@
 """Test the Lutron Caseta diagnostics."""
 
-from unittest.mock import ANY, patch
+from unittest.mock import ANY
 
 from homeassistant.components.lutron_caseta import DOMAIN
 from homeassistant.components.lutron_caseta.const import (
@@ -11,7 +11,7 @@ from homeassistant.components.lutron_caseta.const import (
 from homeassistant.const import CONF_HOST
 from homeassistant.core import HomeAssistant
 
-from . import MockBridge
+from . import MockBridge, async_setup_integration
 
 from tests.common import MockConfigEntry
 from tests.components.diagnostics import get_diagnostics_for_config_entry
@@ -34,12 +34,7 @@ async def test_diagnostics(
     )
     config_entry.add_to_hass(hass)
 
-    with patch(
-        "homeassistant.components.lutron_caseta.Smartbridge.create_tls",
-        return_value=MockBridge(can_connect=True),
-    ):
-        await hass.config_entries.async_setup(config_entry.entry_id)
-        await hass.async_block_till_done()
+    await async_setup_integration(hass, MockBridge, config_entry.entry_id)
 
     diag = await get_diagnostics_for_config_entry(hass, hass_client, config_entry)
     assert diag == {
diff --git a/tests/components/lutron_caseta/test_init.py b/tests/components/lutron_caseta/test_init.py
new file mode 100644
index 0000000000000000000000000000000000000000..7e509acbf62f4ca4548906716077dbc91a85c1d4
--- /dev/null
+++ b/tests/components/lutron_caseta/test_init.py
@@ -0,0 +1,54 @@
+"""Tests for the Lutron Caseta integration."""
+
+from unittest.mock import patch
+
+import pytest
+
+from homeassistant.components import lutron_caseta
+from homeassistant.config_entries import ConfigEntryState
+from homeassistant.core import HomeAssistant
+
+from . import MockBridge, async_setup_integration, make_mock_entry
+
+
+@pytest.mark.parametrize(
+    ("constant", "message", "timeout_during_connect", "timeout_during_configure"),
+    [
+        ("CONNECT_TIMEOUT", "Timed out on connect", True, False),
+        ("CONFIGURE_TIMEOUT", "Timed out on configure", False, True),
+    ],
+)
+async def test_timeout_during_setup(
+    hass: HomeAssistant,
+    caplog: pytest.LogCaptureFixture,
+    constant: str,
+    message: str,
+    timeout_during_connect: bool,
+    timeout_during_configure: bool,
+) -> None:
+    """Test a timeout during setup."""
+    mock_entry = make_mock_entry()
+    mock_entry.add_to_hass(hass)
+    with patch.object(lutron_caseta, constant, 0.001):
+        await async_setup_integration(
+            hass,
+            MockBridge,
+            config_entry_id=mock_entry.entry_id,
+            timeout_during_connect=timeout_during_connect,
+            timeout_during_configure=timeout_during_configure,
+        )
+    assert mock_entry.state is ConfigEntryState.SETUP_RETRY
+    assert f"{message} for 1.1.1.1" in caplog.text
+
+
+async def test_cannot_connect(
+    hass: HomeAssistant, caplog: pytest.LogCaptureFixture
+) -> None:
+    """Test failing to connect."""
+    mock_entry = make_mock_entry()
+    mock_entry.add_to_hass(hass)
+    await async_setup_integration(
+        hass, MockBridge, config_entry_id=mock_entry.entry_id, can_connect=False
+    )
+    assert mock_entry.state is ConfigEntryState.SETUP_RETRY
+    assert "Connection failed to 1.1.1.1" in caplog.text
diff --git a/tests/components/lutron_caseta/test_logbook.py b/tests/components/lutron_caseta/test_logbook.py
index 9a58838d65c0cce7e97b042435d137fba33290da..8b4a3e00fa9c9835f8b32a222bf924d1cb90a0e4 100644
--- a/tests/components/lutron_caseta/test_logbook.py
+++ b/tests/components/lutron_caseta/test_logbook.py
@@ -1,7 +1,5 @@
 """The tests for lutron caseta logbook."""
 
-from unittest.mock import patch
-
 from homeassistant.components.lutron_caseta.const import (
     ATTR_ACTION,
     ATTR_AREA_NAME,
@@ -43,13 +41,7 @@ async def test_humanify_lutron_caseta_button_event(hass: HomeAssistant) -> None:
         unique_id="abc",
     )
     config_entry.add_to_hass(hass)
-
-    with patch(
-        "homeassistant.components.lutron_caseta.Smartbridge.create_tls",
-        return_value=MockBridge(can_connect=True),
-    ):
-        await hass.config_entries.async_setup(config_entry.entry_id)
-        await hass.async_block_till_done()
+    await async_setup_integration(hass, MockBridge, config_entry.entry_id)
 
     await hass.async_block_till_done()
 
@@ -104,15 +96,10 @@ async def test_humanify_lutron_caseta_button_event_integration_not_loaded(
     )
     config_entry.add_to_hass(hass)
 
-    with patch(
-        "homeassistant.components.lutron_caseta.Smartbridge.create_tls",
-        return_value=MockBridge(can_connect=True),
-    ):
-        await hass.config_entries.async_setup(config_entry.entry_id)
-        await hass.async_block_till_done()
+    await async_setup_integration(hass, MockBridge, config_entry.entry_id)
 
-        await hass.config_entries.async_unload(config_entry.entry_id)
-        await hass.async_block_till_done()
+    await hass.config_entries.async_unload(config_entry.entry_id)
+    await hass.async_block_till_done()
 
     for device in device_registry.devices.values():
         if device.config_entries == {config_entry.entry_id}: