spin_unlock_irqrestore(&minfo->xfer_lock, flags);
 }
 
-/**
- * scmi_rx_callback() - callback for receiving messages
- *
- * @cinfo: SCMI channel info
- * @msg_hdr: Message header
- *
- * Processes one received message to appropriate transfer information and
- * signals completion of the transfer.
- *
- * NOTE: This function will be invoked in IRQ context, hence should be
- * as optimal as possible.
- */
-void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr)
+static void scmi_handle_notification(struct scmi_chan_info *cinfo, u32 msg_hdr)
 {
-       struct scmi_info *info = handle_to_scmi_info(cinfo->handle);
-       struct scmi_xfers_info *minfo = &info->tx_minfo;
-       u16 xfer_id = MSG_XTRACT_TOKEN(msg_hdr);
-       u8 msg_type = MSG_XTRACT_TYPE(msg_hdr);
-       struct device *dev = cinfo->dev;
        struct scmi_xfer *xfer;
+       struct device *dev = cinfo->dev;
+       struct scmi_info *info = handle_to_scmi_info(cinfo->handle);
+       struct scmi_xfers_info *minfo = &info->rx_minfo;
+
+       xfer = scmi_xfer_get(cinfo->handle, minfo);
+       if (IS_ERR(xfer)) {
+               dev_err(dev, "failed to get free message slot (%ld)\n",
+                       PTR_ERR(xfer));
+               info->desc->ops->clear_notification(cinfo);
+               return;
+       }
+
+       unpack_scmi_header(msg_hdr, &xfer->hdr);
+       scmi_dump_header_dbg(dev, &xfer->hdr);
+       info->desc->ops->fetch_notification(cinfo, info->desc->max_msg_size,
+                                           xfer);
+
+       trace_scmi_rx_done(xfer->transfer_id, xfer->hdr.id,
+                          xfer->hdr.protocol_id, xfer->hdr.seq,
+                          MSG_TYPE_NOTIFICATION);
 
-       if (msg_type == MSG_TYPE_NOTIFICATION)
-               return; /* Notifications not yet supported */
+       __scmi_xfer_put(minfo, xfer);
+
+       info->desc->ops->clear_notification(cinfo);
+}
+
+static void scmi_handle_response(struct scmi_chan_info *cinfo,
+                                u16 xfer_id, u8 msg_type)
+{
+       struct scmi_xfer *xfer;
+       struct device *dev = cinfo->dev;
+       struct scmi_info *info = handle_to_scmi_info(cinfo->handle);
+       struct scmi_xfers_info *minfo = &info->tx_minfo;
 
        /* Are we even expecting this? */
        if (!test_bit(xfer_id, minfo->xfer_alloc_table)) {
                complete(&xfer->done);
 }
 
+/**
+ * scmi_rx_callback() - callback for receiving messages
+ *
+ * @cinfo: SCMI channel info
+ * @msg_hdr: Message header
+ *
+ * Processes one received message to appropriate transfer information and
+ * signals completion of the transfer.
+ *
+ * NOTE: This function will be invoked in IRQ context, hence should be
+ * as optimal as possible.
+ */
+void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr)
+{
+       u16 xfer_id = MSG_XTRACT_TOKEN(msg_hdr);
+       u8 msg_type = MSG_XTRACT_TYPE(msg_hdr);
+
+       switch (msg_type) {
+       case MSG_TYPE_NOTIFICATION:
+               scmi_handle_notification(cinfo, msg_hdr);
+               break;
+       case MSG_TYPE_COMMAND:
+       case MSG_TYPE_DELAYED_RESP:
+               scmi_handle_response(cinfo, xfer_id, msg_type);
+               break;
+       default:
+               WARN_ONCE(1, "received unknown msg_type:%d\n", msg_type);
+               break;
+       }
+}
+
 /**
  * scmi_xfer_put() - Release a transmit message
  *