#include "dbc.h"
 
+#define DBC_DEFAULT_TIMEOUT            (10 * MSEC_PER_SEC)
 struct error_map {
        u32 psp;
        int ret;
        {0x0,   0x0},
 };
 
-static int send_dbc_cmd(struct psp_dbc_device *dbc_dev,
-                       enum psp_platform_access_msg msg)
+static inline int send_dbc_cmd_thru_ext(struct psp_dbc_device *dbc_dev, int msg)
+{
+       dbc_dev->mbox->ext_req.header.sub_cmd_id = msg;
+
+       return psp_extended_mailbox_cmd(dbc_dev->psp,
+                                       DBC_DEFAULT_TIMEOUT,
+                                       (struct psp_ext_request *)dbc_dev->mbox);
+}
+
+static inline int send_dbc_cmd_thru_pa(struct psp_dbc_device *dbc_dev, int msg)
+{
+       return psp_send_platform_access_msg(msg,
+                                           (struct psp_request *)dbc_dev->mbox);
+}
+
+static int send_dbc_cmd(struct psp_dbc_device *dbc_dev, int msg)
 {
        int ret;
 
        *dbc_dev->result = 0;
-       ret = psp_send_platform_access_msg(msg, (struct psp_request *)dbc_dev->mbox);
+       ret = dbc_dev->use_ext ? send_dbc_cmd_thru_ext(dbc_dev, msg) :
+                                send_dbc_cmd_thru_pa(dbc_dev, msg);
        if (ret == -EIO) {
                int i;
 
        struct psp_dbc_device *dbc_dev;
        int ret;
 
-       if (!PSP_FEATURE(psp, DBC))
-               return 0;
-
        dbc_dev = devm_kzalloc(dev, sizeof(*dbc_dev), GFP_KERNEL);
        if (!dbc_dev)
                return -ENOMEM;
 
        psp->dbc_data = dbc_dev;
        dbc_dev->dev = dev;
-       dbc_dev->payload_size = &dbc_dev->mbox->pa_req.header.payload_size;
-       dbc_dev->result = &dbc_dev->mbox->pa_req.header.status;
-       dbc_dev->payload = &dbc_dev->mbox->pa_req.buf;
-       dbc_dev->header_size = sizeof(struct psp_req_buffer_hdr);
+       dbc_dev->psp = psp;
+
+       if (PSP_CAPABILITY(psp, DBC_THRU_EXT)) {
+               dbc_dev->use_ext = true;
+               dbc_dev->payload_size = &dbc_dev->mbox->ext_req.header.payload_size;
+               dbc_dev->result = &dbc_dev->mbox->ext_req.header.status;
+               dbc_dev->payload = &dbc_dev->mbox->ext_req.buf;
+               dbc_dev->header_size = sizeof(struct psp_ext_req_buffer_hdr);
+       } else {
+               dbc_dev->payload_size = &dbc_dev->mbox->pa_req.header.payload_size;
+               dbc_dev->result = &dbc_dev->mbox->pa_req.header.status;
+               dbc_dev->payload = &dbc_dev->mbox->pa_req.buf;
+               dbc_dev->header_size = sizeof(struct psp_req_buffer_hdr);
+       }
 
        ret = send_dbc_nonce(dbc_dev);
        if (ret == -EACCES) {
 
 
 struct psp_dbc_device {
        struct device *dev;
+       struct psp_device *psp;
 
        union dbc_buffer *mbox;
 
 
 union dbc_buffer {
        struct psp_request              pa_req;
+       struct psp_ext_request          ext_req;
 };
 
 void dbc_dev_destroy(struct psp_device *psp);
 
        return 0;
 }
 
-static void psp_init_platform_access(struct psp_device *psp)
-{
-       int ret;
-
-       ret = platform_access_dev_init(psp);
-       if (ret) {
-               dev_warn(psp->dev, "platform access init failed: %d\n", ret);
-               return;
-       }
-
-       /* dbc must come after platform access as it tests the feature */
-       ret = dbc_dev_init(psp);
-       if (ret)
-               dev_warn(psp->dev, "failed to init dynamic boost control: %d\n",
-                        ret);
-}
-
 static int psp_init(struct psp_device *psp)
 {
        int ret;
                        return ret;
        }
 
-       if (psp->vdata->platform_access)
-               psp_init_platform_access(psp);
+       if (psp->vdata->platform_access) {
+               ret = platform_access_dev_init(psp);
+               if (ret)
+                       return ret;
+       }
+
+       /* dbc must come after platform access as it tests the feature */
+       if (PSP_FEATURE(psp, DBC) ||
+           PSP_CAPABILITY(psp, DBC_THRU_EXT)) {
+               ret = dbc_dev_init(psp);
+               if (ret)
+                       return ret;
+       }
 
        return 0;
 }
 
 #include <linux/interrupt.h>
 #include <linux/mutex.h>
 #include <linux/psp.h>
+#include <linux/psp-platform-access.h>
 
 #include "sp-dev.h"
 
 
 #define PSP_CAPABILITY_SEV                     BIT(0)
 #define PSP_CAPABILITY_TEE                     BIT(1)
+#define PSP_CAPABILITY_DBC_THRU_EXT            BIT(2)
 #define PSP_CAPABILITY_PSP_SECURITY_REPORTING  BIT(7)
 
 #define PSP_CAPABILITY_PSP_SECURITY_OFFSET     8
        void *buf;
 } __packed;
 
+/**
+ * enum psp_sub_cmd - PSP mailbox sub commands
+ * @PSP_SUB_CMD_DBC_GET_NONCE:         Get nonce from DBC
+ * @PSP_SUB_CMD_DBC_SET_UID:           Set UID for DBC
+ * @PSP_SUB_CMD_DBC_GET_PARAMETER:     Get parameter from DBC
+ * @PSP_SUB_CMD_DBC_SET_PARAMETER:     Set parameter for DBC
+ */
+enum psp_sub_cmd {
+       PSP_SUB_CMD_DBC_GET_NONCE       = PSP_DYNAMIC_BOOST_GET_NONCE,
+       PSP_SUB_CMD_DBC_SET_UID         = PSP_DYNAMIC_BOOST_SET_UID,
+       PSP_SUB_CMD_DBC_GET_PARAMETER   = PSP_DYNAMIC_BOOST_GET_PARAMETER,
+       PSP_SUB_CMD_DBC_SET_PARAMETER   = PSP_DYNAMIC_BOOST_SET_PARAMETER,
+};
+
 int psp_extended_mailbox_cmd(struct psp_device *psp, unsigned int timeout_msecs,
                             struct psp_ext_request *req);
 #endif /* __PSP_DEV_H */