};
 
 
+/* -- SSAM KIP-subsystem hub driver. ---------------------------------------- */
+
+/*
+ * Some devices may need a bit of time to be fully usable after being
+ * (re-)connected. This delay has been determined via experimentation.
+ */
+#define SSAM_KIP_UPDATE_CONNECT_DELAY          msecs_to_jiffies(250)
+
+#define SSAM_EVENT_KIP_CID_CONNECTION          0x2c
+
+SSAM_DEFINE_SYNC_REQUEST_R(__ssam_kip_get_connection_state, u8, {
+       .target_category = SSAM_SSH_TC_KIP,
+       .target_id       = 0x01,
+       .command_id      = 0x2c,
+       .instance_id     = 0x00,
+});
+
+static int ssam_kip_get_connection_state(struct ssam_hub *hub, enum ssam_hub_state *state)
+{
+       int status;
+       u8 connected;
+
+       status = ssam_retry(__ssam_kip_get_connection_state, hub->sdev->ctrl, &connected);
+       if (status < 0) {
+               dev_err(&hub->sdev->dev, "failed to query KIP connection state: %d\n", status);
+               return status;
+       }
+
+       *state = connected ? SSAM_HUB_CONNECTED : SSAM_HUB_DISCONNECTED;
+       return 0;
+}
+
+static u32 ssam_kip_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
+{
+       struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
+
+       if (event->command_id != SSAM_EVENT_KIP_CID_CONNECTION)
+               return 0;       /* Return "unhandled". */
+
+       if (event->length < 1) {
+               dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length);
+               return 0;
+       }
+
+       ssam_hub_update(hub, event->data[0]);
+       return SSAM_NOTIF_HANDLED;
+}
+
+static int ssam_kip_hub_probe(struct ssam_device *sdev)
+{
+       struct ssam_hub *hub;
+
+       hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL);
+       if (!hub)
+               return -ENOMEM;
+
+       hub->notif.base.priority = INT_MAX;  /* This notifier should run first. */
+       hub->notif.base.fn = ssam_kip_hub_notif;
+       hub->notif.event.reg = SSAM_EVENT_REGISTRY_SAM;
+       hub->notif.event.id.target_category = SSAM_SSH_TC_KIP,
+       hub->notif.event.id.instance = 0,
+       hub->notif.event.mask = SSAM_EVENT_MASK_TARGET;
+       hub->notif.event.flags = SSAM_EVENT_SEQUENCED;
+
+       hub->connect_delay = SSAM_KIP_UPDATE_CONNECT_DELAY;
+       hub->get_state = ssam_kip_get_connection_state;
+
+       return ssam_hub_setup(sdev, hub);
+}
+
+static const struct ssam_device_id ssam_kip_hub_match[] = {
+       { SSAM_VDEV(HUB, 0x01, SSAM_SSH_TC_KIP, 0x00) },
+       { },
+};
+
+static struct ssam_device_driver ssam_kip_hub_driver = {
+       .probe = ssam_kip_hub_probe,
+       .remove = ssam_hub_remove,
+       .match_table = ssam_kip_hub_match,
+       .driver = {
+               .name = "surface_kip_hub",
+               .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+               .pm = &ssam_hub_pm_ops,
+       },
+};
+
+
 /* -- SSAM platform/meta-hub driver. ---------------------------------------- */
 
 static const struct acpi_device_id ssam_platform_hub_match[] = {
 
        status = platform_driver_register(&ssam_platform_hub_driver);
        if (status)
-               return status;
+               goto err_platform;
 
        status = ssam_device_driver_register(&ssam_base_hub_driver);
        if (status)
-               platform_driver_unregister(&ssam_platform_hub_driver);
+               goto err_base;
+
+       status = ssam_device_driver_register(&ssam_kip_hub_driver);
+       if (status)
+               goto err_kip;
 
+       return 0;
+
+err_kip:
+       ssam_device_driver_unregister(&ssam_base_hub_driver);
+err_base:
+       platform_driver_unregister(&ssam_platform_hub_driver);
+err_platform:
        return status;
 }
 module_init(ssam_device_hub_init);
 
 static void __exit ssam_device_hub_exit(void)
 {
+       ssam_device_driver_unregister(&ssam_kip_hub_driver);
        ssam_device_driver_unregister(&ssam_base_hub_driver);
        platform_driver_unregister(&ssam_platform_hub_driver);
 }