Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 // Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
0003 // Copyright (c) 2018, Linaro Limited
0004 
0005 #include <linux/irq.h>
0006 #include <linux/kernel.h>
0007 #include <linux/init.h>
0008 #include <linux/slab.h>
0009 #include <linux/interrupt.h>
0010 #include <linux/platform_device.h>
0011 #include <linux/dma-mapping.h>
0012 #include <linux/dmaengine.h>
0013 #include <linux/slimbus.h>
0014 #include <linux/delay.h>
0015 #include <linux/pm_runtime.h>
0016 #include <linux/mutex.h>
0017 #include <linux/notifier.h>
0018 #include <linux/remoteproc/qcom_rproc.h>
0019 #include <linux/of.h>
0020 #include <linux/io.h>
0021 #include <linux/soc/qcom/qmi.h>
0022 #include <linux/soc/qcom/pdr.h>
0023 #include <net/sock.h>
0024 #include "slimbus.h"
0025 
0026 /* NGD (Non-ported Generic Device) registers */
0027 #define NGD_CFG         0x0
0028 #define NGD_CFG_ENABLE      BIT(0)
0029 #define NGD_CFG_RX_MSGQ_EN  BIT(1)
0030 #define NGD_CFG_TX_MSGQ_EN  BIT(2)
0031 #define NGD_STATUS      0x4
0032 #define NGD_LADDR       BIT(1)
0033 #define NGD_RX_MSGQ_CFG     0x8
0034 #define NGD_INT_EN      0x10
0035 #define NGD_INT_RECFG_DONE  BIT(24)
0036 #define NGD_INT_TX_NACKED_2 BIT(25)
0037 #define NGD_INT_MSG_BUF_CONTE   BIT(26)
0038 #define NGD_INT_MSG_TX_INVAL    BIT(27)
0039 #define NGD_INT_IE_VE_CHG   BIT(28)
0040 #define NGD_INT_DEV_ERR     BIT(29)
0041 #define NGD_INT_RX_MSG_RCVD BIT(30)
0042 #define NGD_INT_TX_MSG_SENT BIT(31)
0043 #define NGD_INT_STAT        0x14
0044 #define NGD_INT_CLR     0x18
0045 #define DEF_NGD_INT_MASK (NGD_INT_TX_NACKED_2 | NGD_INT_MSG_BUF_CONTE | \
0046                 NGD_INT_MSG_TX_INVAL | NGD_INT_IE_VE_CHG | \
0047                 NGD_INT_DEV_ERR | NGD_INT_TX_MSG_SENT | \
0048                 NGD_INT_RX_MSG_RCVD)
0049 
0050 /* Slimbus QMI service */
0051 #define SLIMBUS_QMI_SVC_ID  0x0301
0052 #define SLIMBUS_QMI_SVC_V1  1
0053 #define SLIMBUS_QMI_INS_ID  0
0054 #define SLIMBUS_QMI_SELECT_INSTANCE_REQ_V01 0x0020
0055 #define SLIMBUS_QMI_SELECT_INSTANCE_RESP_V01    0x0020
0056 #define SLIMBUS_QMI_POWER_REQ_V01       0x0021
0057 #define SLIMBUS_QMI_POWER_RESP_V01      0x0021
0058 #define SLIMBUS_QMI_CHECK_FRAMER_STATUS_REQ 0x0022
0059 #define SLIMBUS_QMI_CHECK_FRAMER_STATUS_RESP    0x0022
0060 #define SLIMBUS_QMI_POWER_REQ_MAX_MSG_LEN   14
0061 #define SLIMBUS_QMI_POWER_RESP_MAX_MSG_LEN  7
0062 #define SLIMBUS_QMI_SELECT_INSTANCE_REQ_MAX_MSG_LEN 14
0063 #define SLIMBUS_QMI_SELECT_INSTANCE_RESP_MAX_MSG_LEN    7
0064 #define SLIMBUS_QMI_CHECK_FRAMER_STAT_RESP_MAX_MSG_LEN  7
0065 /* QMI response timeout of 500ms */
0066 #define SLIMBUS_QMI_RESP_TOUT   1000
0067 
0068 /* User defined commands */
0069 #define SLIM_USR_MC_GENERIC_ACK 0x25
0070 #define SLIM_USR_MC_MASTER_CAPABILITY   0x0
0071 #define SLIM_USR_MC_REPORT_SATELLITE    0x1
0072 #define SLIM_USR_MC_ADDR_QUERY      0xD
0073 #define SLIM_USR_MC_ADDR_REPLY      0xE
0074 #define SLIM_USR_MC_DEFINE_CHAN     0x20
0075 #define SLIM_USR_MC_DEF_ACT_CHAN    0x21
0076 #define SLIM_USR_MC_CHAN_CTRL       0x23
0077 #define SLIM_USR_MC_RECONFIG_NOW    0x24
0078 #define SLIM_USR_MC_REQ_BW      0x28
0079 #define SLIM_USR_MC_CONNECT_SRC     0x2C
0080 #define SLIM_USR_MC_CONNECT_SINK    0x2D
0081 #define SLIM_USR_MC_DISCONNECT_PORT 0x2E
0082 #define SLIM_USR_MC_REPEAT_CHANGE_VALUE 0x0
0083 
0084 #define QCOM_SLIM_NGD_AUTOSUSPEND   MSEC_PER_SEC
0085 #define SLIM_RX_MSGQ_TIMEOUT_VAL    0x10000
0086 
0087 #define SLIM_LA_MGR 0xFF
0088 #define SLIM_ROOT_FREQ  24576000
0089 #define LADDR_RETRY 5
0090 
0091 /* Per spec.max 40 bytes per received message */
0092 #define SLIM_MSGQ_BUF_LEN   40
0093 #define QCOM_SLIM_NGD_DESC_NUM  32
0094 
0095 #define SLIM_MSG_ASM_FIRST_WORD(l, mt, mc, dt, ad) \
0096         ((l) | ((mt) << 5) | ((mc) << 8) | ((dt) << 15) | ((ad) << 16))
0097 
0098 #define INIT_MX_RETRIES 10
0099 #define DEF_RETRY_MS    10
0100 #define SAT_MAGIC_LSB   0xD9
0101 #define SAT_MAGIC_MSB   0xC5
0102 #define SAT_MSG_VER 0x1
0103 #define SAT_MSG_PROT    0x1
0104 #define to_ngd(d)   container_of(d, struct qcom_slim_ngd, dev)
0105 
0106 struct ngd_reg_offset_data {
0107     u32 offset, size;
0108 };
0109 
0110 static const struct ngd_reg_offset_data ngd_v1_5_offset_info = {
0111     .offset = 0x1000,
0112     .size = 0x1000,
0113 };
0114 
0115 enum qcom_slim_ngd_state {
0116     QCOM_SLIM_NGD_CTRL_AWAKE,
0117     QCOM_SLIM_NGD_CTRL_IDLE,
0118     QCOM_SLIM_NGD_CTRL_ASLEEP,
0119     QCOM_SLIM_NGD_CTRL_DOWN,
0120 };
0121 
0122 struct qcom_slim_ngd_qmi {
0123     struct qmi_handle qmi;
0124     struct sockaddr_qrtr svc_info;
0125     struct qmi_handle svc_event_hdl;
0126     struct qmi_response_type_v01 resp;
0127     struct qmi_handle *handle;
0128     struct completion qmi_comp;
0129 };
0130 
0131 struct qcom_slim_ngd_ctrl;
0132 struct qcom_slim_ngd;
0133 
0134 struct qcom_slim_ngd_dma_desc {
0135     struct dma_async_tx_descriptor *desc;
0136     struct qcom_slim_ngd_ctrl *ctrl;
0137     struct completion *comp;
0138     dma_cookie_t cookie;
0139     dma_addr_t phys;
0140     void *base;
0141 };
0142 
0143 struct qcom_slim_ngd {
0144     struct platform_device *pdev;
0145     void __iomem *base;
0146     int id;
0147 };
0148 
0149 struct qcom_slim_ngd_ctrl {
0150     struct slim_framer framer;
0151     struct slim_controller ctrl;
0152     struct qcom_slim_ngd_qmi qmi;
0153     struct qcom_slim_ngd *ngd;
0154     struct device *dev;
0155     void __iomem *base;
0156     struct dma_chan *dma_rx_channel;
0157     struct dma_chan *dma_tx_channel;
0158     struct qcom_slim_ngd_dma_desc rx_desc[QCOM_SLIM_NGD_DESC_NUM];
0159     struct qcom_slim_ngd_dma_desc txdesc[QCOM_SLIM_NGD_DESC_NUM];
0160     struct completion reconf;
0161     struct work_struct m_work;
0162     struct work_struct ngd_up_work;
0163     struct workqueue_struct *mwq;
0164     struct completion qmi_up;
0165     spinlock_t tx_buf_lock;
0166     struct mutex tx_lock;
0167     struct mutex ssr_lock;
0168     struct notifier_block nb;
0169     void *notifier;
0170     struct pdr_handle *pdr;
0171     enum qcom_slim_ngd_state state;
0172     dma_addr_t rx_phys_base;
0173     dma_addr_t tx_phys_base;
0174     void *rx_base;
0175     void *tx_base;
0176     int tx_tail;
0177     int tx_head;
0178     u32 ver;
0179 };
0180 
0181 enum slimbus_mode_enum_type_v01 {
0182     /* To force a 32 bit signed enum. Do not change or use*/
0183     SLIMBUS_MODE_ENUM_TYPE_MIN_ENUM_VAL_V01 = INT_MIN,
0184     SLIMBUS_MODE_SATELLITE_V01 = 1,
0185     SLIMBUS_MODE_MASTER_V01 = 2,
0186     SLIMBUS_MODE_ENUM_TYPE_MAX_ENUM_VAL_V01 = INT_MAX,
0187 };
0188 
0189 enum slimbus_pm_enum_type_v01 {
0190     /* To force a 32 bit signed enum. Do not change or use*/
0191     SLIMBUS_PM_ENUM_TYPE_MIN_ENUM_VAL_V01 = INT_MIN,
0192     SLIMBUS_PM_INACTIVE_V01 = 1,
0193     SLIMBUS_PM_ACTIVE_V01 = 2,
0194     SLIMBUS_PM_ENUM_TYPE_MAX_ENUM_VAL_V01 = INT_MAX,
0195 };
0196 
0197 enum slimbus_resp_enum_type_v01 {
0198     SLIMBUS_RESP_ENUM_TYPE_MIN_VAL_V01 = INT_MIN,
0199     SLIMBUS_RESP_SYNCHRONOUS_V01 = 1,
0200     SLIMBUS_RESP_ENUM_TYPE_MAX_VAL_V01 = INT_MAX,
0201 };
0202 
0203 struct slimbus_select_inst_req_msg_v01 {
0204     uint32_t instance;
0205     uint8_t mode_valid;
0206     enum slimbus_mode_enum_type_v01 mode;
0207 };
0208 
0209 struct slimbus_select_inst_resp_msg_v01 {
0210     struct qmi_response_type_v01 resp;
0211 };
0212 
0213 struct slimbus_power_req_msg_v01 {
0214     enum slimbus_pm_enum_type_v01 pm_req;
0215     uint8_t resp_type_valid;
0216     enum slimbus_resp_enum_type_v01 resp_type;
0217 };
0218 
0219 struct slimbus_power_resp_msg_v01 {
0220     struct qmi_response_type_v01 resp;
0221 };
0222 
0223 static struct qmi_elem_info slimbus_select_inst_req_msg_v01_ei[] = {
0224     {
0225         .data_type  = QMI_UNSIGNED_4_BYTE,
0226         .elem_len   = 1,
0227         .elem_size  = sizeof(uint32_t),
0228         .array_type = NO_ARRAY,
0229         .tlv_type   = 0x01,
0230         .offset     = offsetof(struct slimbus_select_inst_req_msg_v01,
0231                        instance),
0232         .ei_array   = NULL,
0233     },
0234     {
0235         .data_type  = QMI_OPT_FLAG,
0236         .elem_len   = 1,
0237         .elem_size  = sizeof(uint8_t),
0238         .array_type = NO_ARRAY,
0239         .tlv_type   = 0x10,
0240         .offset     = offsetof(struct slimbus_select_inst_req_msg_v01,
0241                        mode_valid),
0242         .ei_array   = NULL,
0243     },
0244     {
0245         .data_type  = QMI_UNSIGNED_4_BYTE,
0246         .elem_len   = 1,
0247         .elem_size  = sizeof(enum slimbus_mode_enum_type_v01),
0248         .array_type = NO_ARRAY,
0249         .tlv_type   = 0x10,
0250         .offset     = offsetof(struct slimbus_select_inst_req_msg_v01,
0251                        mode),
0252         .ei_array   = NULL,
0253     },
0254     {
0255         .data_type  = QMI_EOTI,
0256         .elem_len   = 0,
0257         .elem_size  = 0,
0258         .array_type = NO_ARRAY,
0259         .tlv_type   = 0x00,
0260         .offset     = 0,
0261         .ei_array   = NULL,
0262     },
0263 };
0264 
0265 static struct qmi_elem_info slimbus_select_inst_resp_msg_v01_ei[] = {
0266     {
0267         .data_type  = QMI_STRUCT,
0268         .elem_len   = 1,
0269         .elem_size  = sizeof(struct qmi_response_type_v01),
0270         .array_type = NO_ARRAY,
0271         .tlv_type   = 0x02,
0272         .offset     = offsetof(struct slimbus_select_inst_resp_msg_v01,
0273                        resp),
0274         .ei_array   = qmi_response_type_v01_ei,
0275     },
0276     {
0277         .data_type  = QMI_EOTI,
0278         .elem_len   = 0,
0279         .elem_size  = 0,
0280         .array_type = NO_ARRAY,
0281         .tlv_type   = 0x00,
0282         .offset     = 0,
0283         .ei_array   = NULL,
0284     },
0285 };
0286 
0287 static struct qmi_elem_info slimbus_power_req_msg_v01_ei[] = {
0288     {
0289         .data_type  = QMI_UNSIGNED_4_BYTE,
0290         .elem_len   = 1,
0291         .elem_size  = sizeof(enum slimbus_pm_enum_type_v01),
0292         .array_type = NO_ARRAY,
0293         .tlv_type   = 0x01,
0294         .offset     = offsetof(struct slimbus_power_req_msg_v01,
0295                        pm_req),
0296         .ei_array   = NULL,
0297     },
0298     {
0299         .data_type  = QMI_OPT_FLAG,
0300         .elem_len   = 1,
0301         .elem_size  = sizeof(uint8_t),
0302         .array_type = NO_ARRAY,
0303         .tlv_type   = 0x10,
0304         .offset     = offsetof(struct slimbus_power_req_msg_v01,
0305                        resp_type_valid),
0306     },
0307     {
0308         .data_type  = QMI_SIGNED_4_BYTE_ENUM,
0309         .elem_len   = 1,
0310         .elem_size  = sizeof(enum slimbus_resp_enum_type_v01),
0311         .array_type = NO_ARRAY,
0312         .tlv_type   = 0x10,
0313         .offset     = offsetof(struct slimbus_power_req_msg_v01,
0314                        resp_type),
0315     },
0316     {
0317         .data_type  = QMI_EOTI,
0318         .elem_len   = 0,
0319         .elem_size  = 0,
0320         .array_type = NO_ARRAY,
0321         .tlv_type   = 0x00,
0322         .offset     = 0,
0323         .ei_array   = NULL,
0324     },
0325 };
0326 
0327 static struct qmi_elem_info slimbus_power_resp_msg_v01_ei[] = {
0328     {
0329         .data_type  = QMI_STRUCT,
0330         .elem_len   = 1,
0331         .elem_size  = sizeof(struct qmi_response_type_v01),
0332         .array_type = NO_ARRAY,
0333         .tlv_type   = 0x02,
0334         .offset     = offsetof(struct slimbus_power_resp_msg_v01, resp),
0335         .ei_array   = qmi_response_type_v01_ei,
0336     },
0337     {
0338         .data_type  = QMI_EOTI,
0339         .elem_len   = 0,
0340         .elem_size  = 0,
0341         .array_type = NO_ARRAY,
0342         .tlv_type   = 0x00,
0343         .offset     = 0,
0344         .ei_array   = NULL,
0345     },
0346 };
0347 
0348 static int qcom_slim_qmi_send_select_inst_req(struct qcom_slim_ngd_ctrl *ctrl,
0349                 struct slimbus_select_inst_req_msg_v01 *req)
0350 {
0351     struct slimbus_select_inst_resp_msg_v01 resp = { { 0, 0 } };
0352     struct qmi_txn txn;
0353     int rc;
0354 
0355     rc = qmi_txn_init(ctrl->qmi.handle, &txn,
0356                 slimbus_select_inst_resp_msg_v01_ei, &resp);
0357     if (rc < 0) {
0358         dev_err(ctrl->dev, "QMI TXN init fail: %d\n", rc);
0359         return rc;
0360     }
0361 
0362     rc = qmi_send_request(ctrl->qmi.handle, NULL, &txn,
0363                 SLIMBUS_QMI_SELECT_INSTANCE_REQ_V01,
0364                 SLIMBUS_QMI_SELECT_INSTANCE_REQ_MAX_MSG_LEN,
0365                 slimbus_select_inst_req_msg_v01_ei, req);
0366     if (rc < 0) {
0367         dev_err(ctrl->dev, "QMI send req fail %d\n", rc);
0368         qmi_txn_cancel(&txn);
0369         return rc;
0370     }
0371 
0372     rc = qmi_txn_wait(&txn, SLIMBUS_QMI_RESP_TOUT);
0373     if (rc < 0) {
0374         dev_err(ctrl->dev, "QMI TXN wait fail: %d\n", rc);
0375         return rc;
0376     }
0377     /* Check the response */
0378     if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
0379         dev_err(ctrl->dev, "QMI request failed 0x%x\n",
0380             resp.resp.result);
0381         return -EREMOTEIO;
0382     }
0383 
0384     return 0;
0385 }
0386 
0387 static void qcom_slim_qmi_power_resp_cb(struct qmi_handle *handle,
0388                     struct sockaddr_qrtr *sq,
0389                     struct qmi_txn *txn, const void *data)
0390 {
0391     struct slimbus_power_resp_msg_v01 *resp;
0392 
0393     resp = (struct slimbus_power_resp_msg_v01 *)data;
0394     if (resp->resp.result != QMI_RESULT_SUCCESS_V01)
0395         pr_err("QMI power request failed 0x%x\n",
0396                 resp->resp.result);
0397 
0398     complete(&txn->completion);
0399 }
0400 
0401 static int qcom_slim_qmi_send_power_request(struct qcom_slim_ngd_ctrl *ctrl,
0402                     struct slimbus_power_req_msg_v01 *req)
0403 {
0404     struct slimbus_power_resp_msg_v01 resp = { { 0, 0 } };
0405     struct qmi_txn txn;
0406     int rc;
0407 
0408     rc = qmi_txn_init(ctrl->qmi.handle, &txn,
0409                 slimbus_power_resp_msg_v01_ei, &resp);
0410 
0411     rc = qmi_send_request(ctrl->qmi.handle, NULL, &txn,
0412                 SLIMBUS_QMI_POWER_REQ_V01,
0413                 SLIMBUS_QMI_POWER_REQ_MAX_MSG_LEN,
0414                 slimbus_power_req_msg_v01_ei, req);
0415     if (rc < 0) {
0416         dev_err(ctrl->dev, "QMI send req fail %d\n", rc);
0417         qmi_txn_cancel(&txn);
0418         return rc;
0419     }
0420 
0421     rc = qmi_txn_wait(&txn, SLIMBUS_QMI_RESP_TOUT);
0422     if (rc < 0) {
0423         dev_err(ctrl->dev, "QMI TXN wait fail: %d\n", rc);
0424         return rc;
0425     }
0426 
0427     /* Check the response */
0428     if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
0429         dev_err(ctrl->dev, "QMI request failed 0x%x\n",
0430             resp.resp.result);
0431         return -EREMOTEIO;
0432     }
0433 
0434     return 0;
0435 }
0436 
0437 static const struct qmi_msg_handler qcom_slim_qmi_msg_handlers[] = {
0438     {
0439         .type = QMI_RESPONSE,
0440         .msg_id = SLIMBUS_QMI_POWER_RESP_V01,
0441         .ei = slimbus_power_resp_msg_v01_ei,
0442         .decoded_size = sizeof(struct slimbus_power_resp_msg_v01),
0443         .fn = qcom_slim_qmi_power_resp_cb,
0444     },
0445     {}
0446 };
0447 
0448 static int qcom_slim_qmi_init(struct qcom_slim_ngd_ctrl *ctrl,
0449                   bool apps_is_master)
0450 {
0451     struct slimbus_select_inst_req_msg_v01 req;
0452     struct qmi_handle *handle;
0453     int rc;
0454 
0455     handle = devm_kzalloc(ctrl->dev, sizeof(*handle), GFP_KERNEL);
0456     if (!handle)
0457         return -ENOMEM;
0458 
0459     rc = qmi_handle_init(handle, SLIMBUS_QMI_POWER_REQ_MAX_MSG_LEN,
0460                 NULL, qcom_slim_qmi_msg_handlers);
0461     if (rc < 0) {
0462         dev_err(ctrl->dev, "QMI client init failed: %d\n", rc);
0463         goto qmi_handle_init_failed;
0464     }
0465 
0466     rc = kernel_connect(handle->sock,
0467                 (struct sockaddr *)&ctrl->qmi.svc_info,
0468                 sizeof(ctrl->qmi.svc_info), 0);
0469     if (rc < 0) {
0470         dev_err(ctrl->dev, "Remote Service connect failed: %d\n", rc);
0471         goto qmi_connect_to_service_failed;
0472     }
0473 
0474     /* Instance is 0 based */
0475     req.instance = (ctrl->ngd->id >> 1);
0476     req.mode_valid = 1;
0477 
0478     /* Mode indicates the role of the ADSP */
0479     if (apps_is_master)
0480         req.mode = SLIMBUS_MODE_SATELLITE_V01;
0481     else
0482         req.mode = SLIMBUS_MODE_MASTER_V01;
0483 
0484     ctrl->qmi.handle = handle;
0485 
0486     rc = qcom_slim_qmi_send_select_inst_req(ctrl, &req);
0487     if (rc) {
0488         dev_err(ctrl->dev, "failed to select h/w instance\n");
0489         goto qmi_select_instance_failed;
0490     }
0491 
0492     return 0;
0493 
0494 qmi_select_instance_failed:
0495     ctrl->qmi.handle = NULL;
0496 qmi_connect_to_service_failed:
0497     qmi_handle_release(handle);
0498 qmi_handle_init_failed:
0499     devm_kfree(ctrl->dev, handle);
0500     return rc;
0501 }
0502 
0503 static void qcom_slim_qmi_exit(struct qcom_slim_ngd_ctrl *ctrl)
0504 {
0505     if (!ctrl->qmi.handle)
0506         return;
0507 
0508     qmi_handle_release(ctrl->qmi.handle);
0509     devm_kfree(ctrl->dev, ctrl->qmi.handle);
0510     ctrl->qmi.handle = NULL;
0511 }
0512 
0513 static int qcom_slim_qmi_power_request(struct qcom_slim_ngd_ctrl *ctrl,
0514                        bool active)
0515 {
0516     struct slimbus_power_req_msg_v01 req;
0517 
0518     if (active)
0519         req.pm_req = SLIMBUS_PM_ACTIVE_V01;
0520     else
0521         req.pm_req = SLIMBUS_PM_INACTIVE_V01;
0522 
0523     req.resp_type_valid = 0;
0524 
0525     return qcom_slim_qmi_send_power_request(ctrl, &req);
0526 }
0527 
0528 static u32 *qcom_slim_ngd_tx_msg_get(struct qcom_slim_ngd_ctrl *ctrl, int len,
0529                      struct completion *comp)
0530 {
0531     struct qcom_slim_ngd_dma_desc *desc;
0532     unsigned long flags;
0533 
0534     spin_lock_irqsave(&ctrl->tx_buf_lock, flags);
0535 
0536     if ((ctrl->tx_tail + 1) % QCOM_SLIM_NGD_DESC_NUM == ctrl->tx_head) {
0537         spin_unlock_irqrestore(&ctrl->tx_buf_lock, flags);
0538         return NULL;
0539     }
0540     desc  = &ctrl->txdesc[ctrl->tx_tail];
0541     desc->base = ctrl->tx_base + ctrl->tx_tail * SLIM_MSGQ_BUF_LEN;
0542     desc->comp = comp;
0543     ctrl->tx_tail = (ctrl->tx_tail + 1) % QCOM_SLIM_NGD_DESC_NUM;
0544 
0545     spin_unlock_irqrestore(&ctrl->tx_buf_lock, flags);
0546 
0547     return desc->base;
0548 }
0549 
0550 static void qcom_slim_ngd_tx_msg_dma_cb(void *args)
0551 {
0552     struct qcom_slim_ngd_dma_desc *desc = args;
0553     struct qcom_slim_ngd_ctrl *ctrl = desc->ctrl;
0554     unsigned long flags;
0555 
0556     spin_lock_irqsave(&ctrl->tx_buf_lock, flags);
0557 
0558     if (desc->comp) {
0559         complete(desc->comp);
0560         desc->comp = NULL;
0561     }
0562 
0563     ctrl->tx_head = (ctrl->tx_head + 1) % QCOM_SLIM_NGD_DESC_NUM;
0564     spin_unlock_irqrestore(&ctrl->tx_buf_lock, flags);
0565 }
0566 
0567 static int qcom_slim_ngd_tx_msg_post(struct qcom_slim_ngd_ctrl *ctrl,
0568                      void *buf, int len)
0569 {
0570     struct qcom_slim_ngd_dma_desc *desc;
0571     unsigned long flags;
0572     int index, offset;
0573 
0574     spin_lock_irqsave(&ctrl->tx_buf_lock, flags);
0575     offset = buf - ctrl->tx_base;
0576     index = offset/SLIM_MSGQ_BUF_LEN;
0577 
0578     desc = &ctrl->txdesc[index];
0579     desc->phys = ctrl->tx_phys_base + offset;
0580     desc->base = ctrl->tx_base + offset;
0581     desc->ctrl = ctrl;
0582     len = (len + 3) & 0xfc;
0583 
0584     desc->desc = dmaengine_prep_slave_single(ctrl->dma_tx_channel,
0585                         desc->phys, len,
0586                         DMA_MEM_TO_DEV,
0587                         DMA_PREP_INTERRUPT);
0588     if (!desc->desc) {
0589         dev_err(ctrl->dev, "unable to prepare channel\n");
0590         spin_unlock_irqrestore(&ctrl->tx_buf_lock, flags);
0591         return -EINVAL;
0592     }
0593 
0594     desc->desc->callback = qcom_slim_ngd_tx_msg_dma_cb;
0595     desc->desc->callback_param = desc;
0596     desc->desc->cookie = dmaengine_submit(desc->desc);
0597     dma_async_issue_pending(ctrl->dma_tx_channel);
0598     spin_unlock_irqrestore(&ctrl->tx_buf_lock, flags);
0599 
0600     return 0;
0601 }
0602 
0603 static void qcom_slim_ngd_rx(struct qcom_slim_ngd_ctrl *ctrl, u8 *buf)
0604 {
0605     u8 mc, mt, len;
0606 
0607     mt = SLIM_HEADER_GET_MT(buf[0]);
0608     len = SLIM_HEADER_GET_RL(buf[0]);
0609     mc = SLIM_HEADER_GET_MC(buf[1]);
0610 
0611     if (mc == SLIM_USR_MC_MASTER_CAPABILITY &&
0612         mt == SLIM_MSG_MT_SRC_REFERRED_USER)
0613         queue_work(ctrl->mwq, &ctrl->m_work);
0614 
0615     if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
0616         mc == SLIM_MSG_MC_REPLY_VALUE || (mc == SLIM_USR_MC_ADDR_REPLY &&
0617         mt == SLIM_MSG_MT_SRC_REFERRED_USER) ||
0618         (mc == SLIM_USR_MC_GENERIC_ACK &&
0619          mt == SLIM_MSG_MT_SRC_REFERRED_USER)) {
0620         slim_msg_response(&ctrl->ctrl, &buf[4], buf[3], len - 4);
0621         pm_runtime_mark_last_busy(ctrl->ctrl.dev);
0622     }
0623 }
0624 
0625 static void qcom_slim_ngd_rx_msgq_cb(void *args)
0626 {
0627     struct qcom_slim_ngd_dma_desc *desc = args;
0628     struct qcom_slim_ngd_ctrl *ctrl = desc->ctrl;
0629 
0630     qcom_slim_ngd_rx(ctrl, (u8 *)desc->base);
0631     /* Add descriptor back to the queue */
0632     desc->desc = dmaengine_prep_slave_single(ctrl->dma_rx_channel,
0633                     desc->phys, SLIM_MSGQ_BUF_LEN,
0634                     DMA_DEV_TO_MEM,
0635                     DMA_PREP_INTERRUPT);
0636     if (!desc->desc) {
0637         dev_err(ctrl->dev, "Unable to prepare rx channel\n");
0638         return;
0639     }
0640 
0641     desc->desc->callback = qcom_slim_ngd_rx_msgq_cb;
0642     desc->desc->callback_param = desc;
0643     desc->desc->cookie = dmaengine_submit(desc->desc);
0644     dma_async_issue_pending(ctrl->dma_rx_channel);
0645 }
0646 
0647 static int qcom_slim_ngd_post_rx_msgq(struct qcom_slim_ngd_ctrl *ctrl)
0648 {
0649     struct qcom_slim_ngd_dma_desc *desc;
0650     int i;
0651 
0652     for (i = 0; i < QCOM_SLIM_NGD_DESC_NUM; i++) {
0653         desc = &ctrl->rx_desc[i];
0654         desc->phys = ctrl->rx_phys_base + i * SLIM_MSGQ_BUF_LEN;
0655         desc->ctrl = ctrl;
0656         desc->base = ctrl->rx_base + i * SLIM_MSGQ_BUF_LEN;
0657         desc->desc = dmaengine_prep_slave_single(ctrl->dma_rx_channel,
0658                         desc->phys, SLIM_MSGQ_BUF_LEN,
0659                         DMA_DEV_TO_MEM,
0660                         DMA_PREP_INTERRUPT);
0661         if (!desc->desc) {
0662             dev_err(ctrl->dev, "Unable to prepare rx channel\n");
0663             return -EINVAL;
0664         }
0665 
0666         desc->desc->callback = qcom_slim_ngd_rx_msgq_cb;
0667         desc->desc->callback_param = desc;
0668         desc->desc->cookie = dmaengine_submit(desc->desc);
0669     }
0670     dma_async_issue_pending(ctrl->dma_rx_channel);
0671 
0672     return 0;
0673 }
0674 
0675 static int qcom_slim_ngd_init_rx_msgq(struct qcom_slim_ngd_ctrl *ctrl)
0676 {
0677     struct device *dev = ctrl->dev;
0678     int ret, size;
0679 
0680     ctrl->dma_rx_channel = dma_request_chan(dev, "rx");
0681     if (IS_ERR(ctrl->dma_rx_channel)) {
0682         dev_err(dev, "Failed to request RX dma channel");
0683         ret = PTR_ERR(ctrl->dma_rx_channel);
0684         ctrl->dma_rx_channel = NULL;
0685         return ret;
0686     }
0687 
0688     size = QCOM_SLIM_NGD_DESC_NUM * SLIM_MSGQ_BUF_LEN;
0689     ctrl->rx_base = dma_alloc_coherent(dev, size, &ctrl->rx_phys_base,
0690                        GFP_KERNEL);
0691     if (!ctrl->rx_base) {
0692         ret = -ENOMEM;
0693         goto rel_rx;
0694     }
0695 
0696     ret = qcom_slim_ngd_post_rx_msgq(ctrl);
0697     if (ret) {
0698         dev_err(dev, "post_rx_msgq() failed 0x%x\n", ret);
0699         goto rx_post_err;
0700     }
0701 
0702     return 0;
0703 
0704 rx_post_err:
0705     dma_free_coherent(dev, size, ctrl->rx_base, ctrl->rx_phys_base);
0706 rel_rx:
0707     dma_release_channel(ctrl->dma_rx_channel);
0708     return ret;
0709 }
0710 
0711 static int qcom_slim_ngd_init_tx_msgq(struct qcom_slim_ngd_ctrl *ctrl)
0712 {
0713     struct device *dev = ctrl->dev;
0714     unsigned long flags;
0715     int ret = 0;
0716     int size;
0717 
0718     ctrl->dma_tx_channel = dma_request_chan(dev, "tx");
0719     if (IS_ERR(ctrl->dma_tx_channel)) {
0720         dev_err(dev, "Failed to request TX dma channel");
0721         ret = PTR_ERR(ctrl->dma_tx_channel);
0722         ctrl->dma_tx_channel = NULL;
0723         return ret;
0724     }
0725 
0726     size = ((QCOM_SLIM_NGD_DESC_NUM + 1) * SLIM_MSGQ_BUF_LEN);
0727     ctrl->tx_base = dma_alloc_coherent(dev, size, &ctrl->tx_phys_base,
0728                        GFP_KERNEL);
0729     if (!ctrl->tx_base) {
0730         ret = -EINVAL;
0731         goto rel_tx;
0732     }
0733 
0734     spin_lock_irqsave(&ctrl->tx_buf_lock, flags);
0735     ctrl->tx_tail = 0;
0736     ctrl->tx_head = 0;
0737     spin_unlock_irqrestore(&ctrl->tx_buf_lock, flags);
0738 
0739     return 0;
0740 rel_tx:
0741     dma_release_channel(ctrl->dma_tx_channel);
0742     return ret;
0743 }
0744 
0745 static int qcom_slim_ngd_init_dma(struct qcom_slim_ngd_ctrl *ctrl)
0746 {
0747     int ret = 0;
0748 
0749     ret = qcom_slim_ngd_init_rx_msgq(ctrl);
0750     if (ret) {
0751         dev_err(ctrl->dev, "rx dma init failed\n");
0752         return ret;
0753     }
0754 
0755     ret = qcom_slim_ngd_init_tx_msgq(ctrl);
0756     if (ret)
0757         dev_err(ctrl->dev, "tx dma init failed\n");
0758 
0759     return ret;
0760 }
0761 
0762 static irqreturn_t qcom_slim_ngd_interrupt(int irq, void *d)
0763 {
0764     struct qcom_slim_ngd_ctrl *ctrl = d;
0765     void __iomem *base = ctrl->ngd->base;
0766     u32 stat = readl(base + NGD_INT_STAT);
0767 
0768     if ((stat & NGD_INT_MSG_BUF_CONTE) ||
0769         (stat & NGD_INT_MSG_TX_INVAL) || (stat & NGD_INT_DEV_ERR) ||
0770         (stat & NGD_INT_TX_NACKED_2)) {
0771         dev_err(ctrl->dev, "Error Interrupt received 0x%x\n", stat);
0772     }
0773 
0774     writel(stat, base + NGD_INT_CLR);
0775 
0776     return IRQ_HANDLED;
0777 }
0778 
0779 static int qcom_slim_ngd_xfer_msg(struct slim_controller *sctrl,
0780                   struct slim_msg_txn *txn)
0781 {
0782     struct qcom_slim_ngd_ctrl *ctrl = dev_get_drvdata(sctrl->dev);
0783     DECLARE_COMPLETION_ONSTACK(tx_sent);
0784     DECLARE_COMPLETION_ONSTACK(done);
0785     int ret, timeout, i;
0786     u8 wbuf[SLIM_MSGQ_BUF_LEN];
0787     u8 rbuf[SLIM_MSGQ_BUF_LEN];
0788     u32 *pbuf;
0789     u8 *puc;
0790     u8 la = txn->la;
0791     bool usr_msg = false;
0792 
0793     if (txn->mt == SLIM_MSG_MT_CORE &&
0794         (txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
0795          txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW))
0796         return 0;
0797 
0798     if (txn->dt == SLIM_MSG_DEST_ENUMADDR)
0799         return -EPROTONOSUPPORT;
0800 
0801     if (txn->msg->num_bytes > SLIM_MSGQ_BUF_LEN ||
0802             txn->rl > SLIM_MSGQ_BUF_LEN) {
0803         dev_err(ctrl->dev, "msg exceeds HW limit\n");
0804         return -EINVAL;
0805     }
0806 
0807     pbuf = qcom_slim_ngd_tx_msg_get(ctrl, txn->rl, &tx_sent);
0808     if (!pbuf) {
0809         dev_err(ctrl->dev, "Message buffer unavailable\n");
0810         return -ENOMEM;
0811     }
0812 
0813     if (txn->mt == SLIM_MSG_MT_CORE &&
0814         (txn->mc == SLIM_MSG_MC_CONNECT_SOURCE ||
0815         txn->mc == SLIM_MSG_MC_CONNECT_SINK ||
0816         txn->mc == SLIM_MSG_MC_DISCONNECT_PORT)) {
0817         txn->mt = SLIM_MSG_MT_DEST_REFERRED_USER;
0818         switch (txn->mc) {
0819         case SLIM_MSG_MC_CONNECT_SOURCE:
0820             txn->mc = SLIM_USR_MC_CONNECT_SRC;
0821             break;
0822         case SLIM_MSG_MC_CONNECT_SINK:
0823             txn->mc = SLIM_USR_MC_CONNECT_SINK;
0824             break;
0825         case SLIM_MSG_MC_DISCONNECT_PORT:
0826             txn->mc = SLIM_USR_MC_DISCONNECT_PORT;
0827             break;
0828         default:
0829             return -EINVAL;
0830         }
0831 
0832         usr_msg = true;
0833         i = 0;
0834         wbuf[i++] = txn->la;
0835         la = SLIM_LA_MGR;
0836         wbuf[i++] = txn->msg->wbuf[0];
0837         if (txn->mc != SLIM_USR_MC_DISCONNECT_PORT)
0838             wbuf[i++] = txn->msg->wbuf[1];
0839 
0840         txn->comp = &done;
0841         ret = slim_alloc_txn_tid(sctrl, txn);
0842         if (ret) {
0843             dev_err(ctrl->dev, "Unable to allocate TID\n");
0844             return ret;
0845         }
0846 
0847         wbuf[i++] = txn->tid;
0848 
0849         txn->msg->num_bytes = i;
0850         txn->msg->wbuf = wbuf;
0851         txn->msg->rbuf = rbuf;
0852         txn->rl = txn->msg->num_bytes + 4;
0853     }
0854 
0855     /* HW expects length field to be excluded */
0856     txn->rl--;
0857     puc = (u8 *)pbuf;
0858     *pbuf = 0;
0859     if (txn->dt == SLIM_MSG_DEST_LOGICALADDR) {
0860         *pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc, 0,
0861                 la);
0862         puc += 3;
0863     } else {
0864         *pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc, 1,
0865                 la);
0866         puc += 2;
0867     }
0868 
0869     if (slim_tid_txn(txn->mt, txn->mc))
0870         *(puc++) = txn->tid;
0871 
0872     if (slim_ec_txn(txn->mt, txn->mc)) {
0873         *(puc++) = (txn->ec & 0xFF);
0874         *(puc++) = (txn->ec >> 8) & 0xFF;
0875     }
0876 
0877     if (txn->msg && txn->msg->wbuf)
0878         memcpy(puc, txn->msg->wbuf, txn->msg->num_bytes);
0879 
0880     mutex_lock(&ctrl->tx_lock);
0881     ret = qcom_slim_ngd_tx_msg_post(ctrl, pbuf, txn->rl);
0882     if (ret) {
0883         mutex_unlock(&ctrl->tx_lock);
0884         return ret;
0885     }
0886 
0887     timeout = wait_for_completion_timeout(&tx_sent, HZ);
0888     if (!timeout) {
0889         dev_err(sctrl->dev, "TX timed out:MC:0x%x,mt:0x%x", txn->mc,
0890                     txn->mt);
0891         mutex_unlock(&ctrl->tx_lock);
0892         return -ETIMEDOUT;
0893     }
0894 
0895     if (usr_msg) {
0896         timeout = wait_for_completion_timeout(&done, HZ);
0897         if (!timeout) {
0898             dev_err(sctrl->dev, "TX timed out:MC:0x%x,mt:0x%x",
0899                 txn->mc, txn->mt);
0900             mutex_unlock(&ctrl->tx_lock);
0901             return -ETIMEDOUT;
0902         }
0903     }
0904 
0905     mutex_unlock(&ctrl->tx_lock);
0906     return 0;
0907 }
0908 
0909 static int qcom_slim_ngd_xfer_msg_sync(struct slim_controller *ctrl,
0910                        struct slim_msg_txn *txn)
0911 {
0912     DECLARE_COMPLETION_ONSTACK(done);
0913     int ret, timeout;
0914 
0915     pm_runtime_get_sync(ctrl->dev);
0916 
0917     txn->comp = &done;
0918 
0919     ret = qcom_slim_ngd_xfer_msg(ctrl, txn);
0920     if (ret)
0921         return ret;
0922 
0923     timeout = wait_for_completion_timeout(&done, HZ);
0924     if (!timeout) {
0925         dev_err(ctrl->dev, "TX timed out:MC:0x%x,mt:0x%x", txn->mc,
0926                 txn->mt);
0927         return -ETIMEDOUT;
0928     }
0929     return 0;
0930 }
0931 
0932 static int qcom_slim_ngd_enable_stream(struct slim_stream_runtime *rt)
0933 {
0934     struct slim_device *sdev = rt->dev;
0935     struct slim_controller *ctrl = sdev->ctrl;
0936     struct slim_val_inf msg =  {0};
0937     u8 wbuf[SLIM_MSGQ_BUF_LEN];
0938     u8 rbuf[SLIM_MSGQ_BUF_LEN];
0939     struct slim_msg_txn txn = {0,};
0940     int i, ret;
0941 
0942     txn.mt = SLIM_MSG_MT_DEST_REFERRED_USER;
0943     txn.dt = SLIM_MSG_DEST_LOGICALADDR;
0944     txn.la = SLIM_LA_MGR;
0945     txn.ec = 0;
0946     txn.msg = &msg;
0947     txn.msg->num_bytes = 0;
0948     txn.msg->wbuf = wbuf;
0949     txn.msg->rbuf = rbuf;
0950 
0951     for (i = 0; i < rt->num_ports; i++) {
0952         struct slim_port *port = &rt->ports[i];
0953 
0954         if (txn.msg->num_bytes == 0) {
0955             int seg_interval = SLIM_SLOTS_PER_SUPERFRAME/rt->ratem;
0956             int exp;
0957 
0958             wbuf[txn.msg->num_bytes++] = sdev->laddr;
0959             wbuf[txn.msg->num_bytes] = rt->bps >> 2 |
0960                            (port->ch.aux_fmt << 6);
0961 
0962             /* Data channel segment interval not multiple of 3 */
0963             exp = seg_interval % 3;
0964             if (exp)
0965                 wbuf[txn.msg->num_bytes] |= BIT(5);
0966 
0967             txn.msg->num_bytes++;
0968             wbuf[txn.msg->num_bytes++] = exp << 4 | rt->prot;
0969 
0970             if (rt->prot == SLIM_PROTO_ISO)
0971                 wbuf[txn.msg->num_bytes++] =
0972                         port->ch.prrate |
0973                         SLIM_CHANNEL_CONTENT_FL;
0974             else
0975                 wbuf[txn.msg->num_bytes++] =  port->ch.prrate;
0976 
0977             ret = slim_alloc_txn_tid(ctrl, &txn);
0978             if (ret) {
0979                 dev_err(&sdev->dev, "Fail to allocate TID\n");
0980                 return -ENXIO;
0981             }
0982             wbuf[txn.msg->num_bytes++] = txn.tid;
0983         }
0984         wbuf[txn.msg->num_bytes++] = port->ch.id;
0985     }
0986 
0987     txn.mc = SLIM_USR_MC_DEF_ACT_CHAN;
0988     txn.rl = txn.msg->num_bytes + 4;
0989     ret = qcom_slim_ngd_xfer_msg_sync(ctrl, &txn);
0990     if (ret) {
0991         slim_free_txn_tid(ctrl, &txn);
0992         dev_err(&sdev->dev, "TX timed out:MC:0x%x,mt:0x%x", txn.mc,
0993                 txn.mt);
0994         return ret;
0995     }
0996 
0997     txn.mc = SLIM_USR_MC_RECONFIG_NOW;
0998     txn.msg->num_bytes = 2;
0999     wbuf[1] = sdev->laddr;
1000     txn.rl = txn.msg->num_bytes + 4;
1001 
1002     ret = slim_alloc_txn_tid(ctrl, &txn);
1003     if (ret) {
1004         dev_err(ctrl->dev, "Fail to allocate TID\n");
1005         return ret;
1006     }
1007 
1008     wbuf[0] = txn.tid;
1009     ret = qcom_slim_ngd_xfer_msg_sync(ctrl, &txn);
1010     if (ret) {
1011         slim_free_txn_tid(ctrl, &txn);
1012         dev_err(&sdev->dev, "TX timed out:MC:0x%x,mt:0x%x", txn.mc,
1013                 txn.mt);
1014     }
1015 
1016     return ret;
1017 }
1018 
1019 static int qcom_slim_ngd_get_laddr(struct slim_controller *ctrl,
1020                    struct slim_eaddr *ea, u8 *laddr)
1021 {
1022     struct slim_val_inf msg =  {0};
1023     u8 failed_ea[6] = {0, 0, 0, 0, 0, 0};
1024     struct slim_msg_txn txn;
1025     u8 wbuf[10] = {0};
1026     u8 rbuf[10] = {0};
1027     int ret;
1028 
1029     txn.mt = SLIM_MSG_MT_DEST_REFERRED_USER;
1030     txn.dt = SLIM_MSG_DEST_LOGICALADDR;
1031     txn.la = SLIM_LA_MGR;
1032     txn.ec = 0;
1033 
1034     txn.mc = SLIM_USR_MC_ADDR_QUERY;
1035     txn.rl = 11;
1036     txn.msg = &msg;
1037     txn.msg->num_bytes = 7;
1038     txn.msg->wbuf = wbuf;
1039     txn.msg->rbuf = rbuf;
1040 
1041     ret = slim_alloc_txn_tid(ctrl, &txn);
1042     if (ret < 0)
1043         return ret;
1044 
1045     wbuf[0] = (u8)txn.tid;
1046     memcpy(&wbuf[1], ea, sizeof(*ea));
1047 
1048     ret = qcom_slim_ngd_xfer_msg_sync(ctrl, &txn);
1049     if (ret) {
1050         slim_free_txn_tid(ctrl, &txn);
1051         return ret;
1052     }
1053 
1054     if (!memcmp(rbuf, failed_ea, 6))
1055         return -ENXIO;
1056 
1057     *laddr = rbuf[6];
1058 
1059     return ret;
1060 }
1061 
1062 static int qcom_slim_ngd_exit_dma(struct qcom_slim_ngd_ctrl *ctrl)
1063 {
1064     if (ctrl->dma_rx_channel) {
1065         dmaengine_terminate_sync(ctrl->dma_rx_channel);
1066         dma_release_channel(ctrl->dma_rx_channel);
1067     }
1068 
1069     if (ctrl->dma_tx_channel) {
1070         dmaengine_terminate_sync(ctrl->dma_tx_channel);
1071         dma_release_channel(ctrl->dma_tx_channel);
1072     }
1073 
1074     ctrl->dma_tx_channel = ctrl->dma_rx_channel = NULL;
1075 
1076     return 0;
1077 }
1078 
1079 static void qcom_slim_ngd_setup(struct qcom_slim_ngd_ctrl *ctrl)
1080 {
1081     u32 cfg = readl_relaxed(ctrl->ngd->base);
1082 
1083     if (ctrl->state == QCOM_SLIM_NGD_CTRL_DOWN ||
1084         ctrl->state == QCOM_SLIM_NGD_CTRL_ASLEEP)
1085         qcom_slim_ngd_init_dma(ctrl);
1086 
1087     /* By default enable message queues */
1088     cfg |= NGD_CFG_RX_MSGQ_EN;
1089     cfg |= NGD_CFG_TX_MSGQ_EN;
1090 
1091     /* Enable NGD if it's not already enabled*/
1092     if (!(cfg & NGD_CFG_ENABLE))
1093         cfg |= NGD_CFG_ENABLE;
1094 
1095     writel_relaxed(cfg, ctrl->ngd->base);
1096 }
1097 
1098 static int qcom_slim_ngd_power_up(struct qcom_slim_ngd_ctrl *ctrl)
1099 {
1100     enum qcom_slim_ngd_state cur_state = ctrl->state;
1101     struct qcom_slim_ngd *ngd = ctrl->ngd;
1102     u32 laddr, rx_msgq;
1103     int timeout, ret = 0;
1104 
1105     if (ctrl->state == QCOM_SLIM_NGD_CTRL_DOWN) {
1106         timeout = wait_for_completion_timeout(&ctrl->qmi.qmi_comp, HZ);
1107         if (!timeout)
1108             return -EREMOTEIO;
1109     }
1110 
1111     if (ctrl->state == QCOM_SLIM_NGD_CTRL_ASLEEP ||
1112         ctrl->state == QCOM_SLIM_NGD_CTRL_DOWN) {
1113         ret = qcom_slim_qmi_power_request(ctrl, true);
1114         if (ret) {
1115             dev_err(ctrl->dev, "SLIM QMI power request failed:%d\n",
1116                     ret);
1117             return ret;
1118         }
1119     }
1120 
1121     ctrl->ver = readl_relaxed(ctrl->base);
1122     /* Version info in 16 MSbits */
1123     ctrl->ver >>= 16;
1124 
1125     laddr = readl_relaxed(ngd->base + NGD_STATUS);
1126     if (laddr & NGD_LADDR) {
1127         /*
1128          * external MDM restart case where ADSP itself was active framer
1129          * For example, modem restarted when playback was active
1130          */
1131         if (cur_state == QCOM_SLIM_NGD_CTRL_AWAKE) {
1132             dev_info(ctrl->dev, "Subsys restart: ADSP active framer\n");
1133             return 0;
1134         }
1135         qcom_slim_ngd_setup(ctrl);
1136         return 0;
1137     }
1138 
1139     writel_relaxed(DEF_NGD_INT_MASK, ngd->base + NGD_INT_EN);
1140     rx_msgq = readl_relaxed(ngd->base + NGD_RX_MSGQ_CFG);
1141 
1142     writel_relaxed(rx_msgq|SLIM_RX_MSGQ_TIMEOUT_VAL,
1143                 ngd->base + NGD_RX_MSGQ_CFG);
1144     qcom_slim_ngd_setup(ctrl);
1145 
1146     timeout = wait_for_completion_timeout(&ctrl->reconf, HZ);
1147     if (!timeout) {
1148         dev_err(ctrl->dev, "capability exchange timed-out\n");
1149         return -ETIMEDOUT;
1150     }
1151 
1152     return 0;
1153 }
1154 
1155 static void qcom_slim_ngd_notify_slaves(struct qcom_slim_ngd_ctrl *ctrl)
1156 {
1157     struct slim_device *sbdev;
1158     struct device_node *node;
1159 
1160     for_each_child_of_node(ctrl->ngd->pdev->dev.of_node, node) {
1161         sbdev = of_slim_get_device(&ctrl->ctrl, node);
1162         if (!sbdev)
1163             continue;
1164 
1165         if (slim_get_logical_addr(sbdev))
1166             dev_err(ctrl->dev, "Failed to get logical address\n");
1167     }
1168 }
1169 
1170 static void qcom_slim_ngd_master_worker(struct work_struct *work)
1171 {
1172     struct qcom_slim_ngd_ctrl *ctrl;
1173     struct slim_msg_txn txn;
1174     struct slim_val_inf msg = {0};
1175     int retries = 0;
1176     u8 wbuf[8];
1177     int ret = 0;
1178 
1179     ctrl = container_of(work, struct qcom_slim_ngd_ctrl, m_work);
1180     txn.dt = SLIM_MSG_DEST_LOGICALADDR;
1181     txn.ec = 0;
1182     txn.mc = SLIM_USR_MC_REPORT_SATELLITE;
1183     txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
1184     txn.la = SLIM_LA_MGR;
1185     wbuf[0] = SAT_MAGIC_LSB;
1186     wbuf[1] = SAT_MAGIC_MSB;
1187     wbuf[2] = SAT_MSG_VER;
1188     wbuf[3] = SAT_MSG_PROT;
1189     txn.msg = &msg;
1190     txn.msg->wbuf = wbuf;
1191     txn.msg->num_bytes = 4;
1192     txn.rl = 8;
1193 
1194     dev_info(ctrl->dev, "SLIM SAT: Rcvd master capability\n");
1195 
1196 capability_retry:
1197     ret = qcom_slim_ngd_xfer_msg(&ctrl->ctrl, &txn);
1198     if (!ret) {
1199         if (ctrl->state >= QCOM_SLIM_NGD_CTRL_ASLEEP)
1200             complete(&ctrl->reconf);
1201         else
1202             dev_err(ctrl->dev, "unexpected state:%d\n",
1203                         ctrl->state);
1204 
1205         if (ctrl->state == QCOM_SLIM_NGD_CTRL_DOWN)
1206             qcom_slim_ngd_notify_slaves(ctrl);
1207 
1208     } else if (ret == -EIO) {
1209         dev_err(ctrl->dev, "capability message NACKed, retrying\n");
1210         if (retries < INIT_MX_RETRIES) {
1211             msleep(DEF_RETRY_MS);
1212             retries++;
1213             goto capability_retry;
1214         }
1215     } else {
1216         dev_err(ctrl->dev, "SLIM: capability TX failed:%d\n", ret);
1217     }
1218 }
1219 
1220 static int qcom_slim_ngd_update_device_status(struct device *dev, void *null)
1221 {
1222     slim_report_absent(to_slim_device(dev));
1223 
1224     return 0;
1225 }
1226 
1227 static int qcom_slim_ngd_runtime_resume(struct device *dev)
1228 {
1229     struct qcom_slim_ngd_ctrl *ctrl = dev_get_drvdata(dev);
1230     int ret = 0;
1231 
1232     if (!ctrl->qmi.handle)
1233         return 0;
1234 
1235     if (ctrl->state >= QCOM_SLIM_NGD_CTRL_ASLEEP)
1236         ret = qcom_slim_ngd_power_up(ctrl);
1237     if (ret) {
1238         /* Did SSR cause this power up failure */
1239         if (ctrl->state != QCOM_SLIM_NGD_CTRL_DOWN)
1240             ctrl->state = QCOM_SLIM_NGD_CTRL_ASLEEP;
1241         else
1242             dev_err(ctrl->dev, "HW wakeup attempt during SSR\n");
1243     } else {
1244         ctrl->state = QCOM_SLIM_NGD_CTRL_AWAKE;
1245     }
1246 
1247     return 0;
1248 }
1249 
1250 static int qcom_slim_ngd_enable(struct qcom_slim_ngd_ctrl *ctrl, bool enable)
1251 {
1252     if (enable) {
1253         int ret = qcom_slim_qmi_init(ctrl, false);
1254 
1255         if (ret) {
1256             dev_err(ctrl->dev, "qmi init fail, ret:%d, state:%d\n",
1257                 ret, ctrl->state);
1258             return ret;
1259         }
1260         /* controller state should be in sync with framework state */
1261         complete(&ctrl->qmi.qmi_comp);
1262         if (!pm_runtime_enabled(ctrl->ctrl.dev) ||
1263              !pm_runtime_suspended(ctrl->ctrl.dev))
1264             qcom_slim_ngd_runtime_resume(ctrl->ctrl.dev);
1265         else
1266             pm_runtime_resume(ctrl->ctrl.dev);
1267 
1268         pm_runtime_mark_last_busy(ctrl->ctrl.dev);
1269         pm_runtime_put(ctrl->ctrl.dev);
1270 
1271         ret = slim_register_controller(&ctrl->ctrl);
1272         if (ret) {
1273             dev_err(ctrl->dev, "error adding slim controller\n");
1274             return ret;
1275         }
1276 
1277         dev_info(ctrl->dev, "SLIM controller Registered\n");
1278     } else {
1279         qcom_slim_qmi_exit(ctrl);
1280         slim_unregister_controller(&ctrl->ctrl);
1281     }
1282 
1283     return 0;
1284 }
1285 
1286 static int qcom_slim_ngd_qmi_new_server(struct qmi_handle *hdl,
1287                     struct qmi_service *service)
1288 {
1289     struct qcom_slim_ngd_qmi *qmi =
1290         container_of(hdl, struct qcom_slim_ngd_qmi, svc_event_hdl);
1291     struct qcom_slim_ngd_ctrl *ctrl =
1292         container_of(qmi, struct qcom_slim_ngd_ctrl, qmi);
1293 
1294     qmi->svc_info.sq_family = AF_QIPCRTR;
1295     qmi->svc_info.sq_node = service->node;
1296     qmi->svc_info.sq_port = service->port;
1297 
1298     complete(&ctrl->qmi_up);
1299 
1300     return 0;
1301 }
1302 
1303 static void qcom_slim_ngd_qmi_del_server(struct qmi_handle *hdl,
1304                      struct qmi_service *service)
1305 {
1306     struct qcom_slim_ngd_qmi *qmi =
1307         container_of(hdl, struct qcom_slim_ngd_qmi, svc_event_hdl);
1308     struct qcom_slim_ngd_ctrl *ctrl =
1309         container_of(qmi, struct qcom_slim_ngd_ctrl, qmi);
1310 
1311     reinit_completion(&ctrl->qmi_up);
1312     qmi->svc_info.sq_node = 0;
1313     qmi->svc_info.sq_port = 0;
1314 }
1315 
1316 static const struct qmi_ops qcom_slim_ngd_qmi_svc_event_ops = {
1317     .new_server = qcom_slim_ngd_qmi_new_server,
1318     .del_server = qcom_slim_ngd_qmi_del_server,
1319 };
1320 
1321 static int qcom_slim_ngd_qmi_svc_event_init(struct qcom_slim_ngd_ctrl *ctrl)
1322 {
1323     struct qcom_slim_ngd_qmi *qmi = &ctrl->qmi;
1324     int ret;
1325 
1326     ret = qmi_handle_init(&qmi->svc_event_hdl, 0,
1327                 &qcom_slim_ngd_qmi_svc_event_ops, NULL);
1328     if (ret < 0) {
1329         dev_err(ctrl->dev, "qmi_handle_init failed: %d\n", ret);
1330         return ret;
1331     }
1332 
1333     ret = qmi_add_lookup(&qmi->svc_event_hdl, SLIMBUS_QMI_SVC_ID,
1334             SLIMBUS_QMI_SVC_V1, SLIMBUS_QMI_INS_ID);
1335     if (ret < 0) {
1336         dev_err(ctrl->dev, "qmi_add_lookup failed: %d\n", ret);
1337         qmi_handle_release(&qmi->svc_event_hdl);
1338     }
1339     return ret;
1340 }
1341 
1342 static void qcom_slim_ngd_qmi_svc_event_deinit(struct qcom_slim_ngd_qmi *qmi)
1343 {
1344     qmi_handle_release(&qmi->svc_event_hdl);
1345 }
1346 
1347 static struct platform_driver qcom_slim_ngd_driver;
1348 #define QCOM_SLIM_NGD_DRV_NAME  "qcom,slim-ngd"
1349 
1350 static const struct of_device_id qcom_slim_ngd_dt_match[] = {
1351     {
1352         .compatible = "qcom,slim-ngd-v1.5.0",
1353         .data = &ngd_v1_5_offset_info,
1354     },{
1355         .compatible = "qcom,slim-ngd-v2.1.0",
1356         .data = &ngd_v1_5_offset_info,
1357     },
1358     {}
1359 };
1360 
1361 MODULE_DEVICE_TABLE(of, qcom_slim_ngd_dt_match);
1362 
1363 static void qcom_slim_ngd_down(struct qcom_slim_ngd_ctrl *ctrl)
1364 {
1365     mutex_lock(&ctrl->ssr_lock);
1366     device_for_each_child(ctrl->ctrl.dev, NULL,
1367                   qcom_slim_ngd_update_device_status);
1368     qcom_slim_ngd_enable(ctrl, false);
1369     mutex_unlock(&ctrl->ssr_lock);
1370 }
1371 
1372 static void qcom_slim_ngd_up_worker(struct work_struct *work)
1373 {
1374     struct qcom_slim_ngd_ctrl *ctrl;
1375 
1376     ctrl = container_of(work, struct qcom_slim_ngd_ctrl, ngd_up_work);
1377 
1378     /* Make sure qmi service is up before continuing */
1379     wait_for_completion_interruptible(&ctrl->qmi_up);
1380 
1381     mutex_lock(&ctrl->ssr_lock);
1382     qcom_slim_ngd_enable(ctrl, true);
1383     mutex_unlock(&ctrl->ssr_lock);
1384 }
1385 
1386 static int qcom_slim_ngd_ssr_pdr_notify(struct qcom_slim_ngd_ctrl *ctrl,
1387                     unsigned long action)
1388 {
1389     switch (action) {
1390     case QCOM_SSR_BEFORE_SHUTDOWN:
1391     case SERVREG_SERVICE_STATE_DOWN:
1392         /* Make sure the last dma xfer is finished */
1393         mutex_lock(&ctrl->tx_lock);
1394         if (ctrl->state != QCOM_SLIM_NGD_CTRL_DOWN) {
1395             pm_runtime_get_noresume(ctrl->ctrl.dev);
1396             ctrl->state = QCOM_SLIM_NGD_CTRL_DOWN;
1397             qcom_slim_ngd_down(ctrl);
1398             qcom_slim_ngd_exit_dma(ctrl);
1399         }
1400         mutex_unlock(&ctrl->tx_lock);
1401         break;
1402     case QCOM_SSR_AFTER_POWERUP:
1403     case SERVREG_SERVICE_STATE_UP:
1404         schedule_work(&ctrl->ngd_up_work);
1405         break;
1406     default:
1407         break;
1408     }
1409 
1410     return NOTIFY_OK;
1411 }
1412 
1413 static int qcom_slim_ngd_ssr_notify(struct notifier_block *nb,
1414                     unsigned long action,
1415                     void *data)
1416 {
1417     struct qcom_slim_ngd_ctrl *ctrl = container_of(nb,
1418                            struct qcom_slim_ngd_ctrl, nb);
1419 
1420     return qcom_slim_ngd_ssr_pdr_notify(ctrl, action);
1421 }
1422 
1423 static void slim_pd_status(int state, char *svc_path, void *priv)
1424 {
1425     struct qcom_slim_ngd_ctrl *ctrl = (struct qcom_slim_ngd_ctrl *)priv;
1426 
1427     qcom_slim_ngd_ssr_pdr_notify(ctrl, state);
1428 }
1429 static int of_qcom_slim_ngd_register(struct device *parent,
1430                      struct qcom_slim_ngd_ctrl *ctrl)
1431 {
1432     const struct ngd_reg_offset_data *data;
1433     struct qcom_slim_ngd *ngd;
1434     const struct of_device_id *match;
1435     struct device_node *node;
1436     u32 id;
1437     int ret;
1438 
1439     match = of_match_node(qcom_slim_ngd_dt_match, parent->of_node);
1440     data = match->data;
1441     for_each_available_child_of_node(parent->of_node, node) {
1442         if (of_property_read_u32(node, "reg", &id))
1443             continue;
1444 
1445         ngd = kzalloc(sizeof(*ngd), GFP_KERNEL);
1446         if (!ngd) {
1447             of_node_put(node);
1448             return -ENOMEM;
1449         }
1450 
1451         ngd->pdev = platform_device_alloc(QCOM_SLIM_NGD_DRV_NAME, id);
1452         if (!ngd->pdev) {
1453             kfree(ngd);
1454             of_node_put(node);
1455             return -ENOMEM;
1456         }
1457         ngd->id = id;
1458         ngd->pdev->dev.parent = parent;
1459 
1460         ret = driver_set_override(&ngd->pdev->dev,
1461                       &ngd->pdev->driver_override,
1462                       QCOM_SLIM_NGD_DRV_NAME,
1463                       strlen(QCOM_SLIM_NGD_DRV_NAME));
1464         if (ret) {
1465             platform_device_put(ngd->pdev);
1466             kfree(ngd);
1467             of_node_put(node);
1468             return ret;
1469         }
1470         ngd->pdev->dev.of_node = node;
1471         ctrl->ngd = ngd;
1472 
1473         platform_device_add(ngd->pdev);
1474         ngd->base = ctrl->base + ngd->id * data->offset +
1475                     (ngd->id - 1) * data->size;
1476 
1477         return 0;
1478     }
1479 
1480     return -ENODEV;
1481 }
1482 
1483 static int qcom_slim_ngd_probe(struct platform_device *pdev)
1484 {
1485     struct device *dev = &pdev->dev;
1486     struct qcom_slim_ngd_ctrl *ctrl = dev_get_drvdata(dev->parent);
1487     int ret;
1488 
1489     ctrl->ctrl.dev = dev;
1490 
1491     platform_set_drvdata(pdev, ctrl);
1492     pm_runtime_use_autosuspend(dev);
1493     pm_runtime_set_autosuspend_delay(dev, QCOM_SLIM_NGD_AUTOSUSPEND);
1494     pm_runtime_set_suspended(dev);
1495     pm_runtime_enable(dev);
1496     pm_runtime_get_noresume(dev);
1497     ret = qcom_slim_ngd_qmi_svc_event_init(ctrl);
1498     if (ret) {
1499         dev_err(&pdev->dev, "QMI service registration failed:%d", ret);
1500         return ret;
1501     }
1502 
1503     INIT_WORK(&ctrl->m_work, qcom_slim_ngd_master_worker);
1504     INIT_WORK(&ctrl->ngd_up_work, qcom_slim_ngd_up_worker);
1505     ctrl->mwq = create_singlethread_workqueue("ngd_master");
1506     if (!ctrl->mwq) {
1507         dev_err(&pdev->dev, "Failed to start master worker\n");
1508         ret = -ENOMEM;
1509         goto wq_err;
1510     }
1511 
1512     return 0;
1513 wq_err:
1514     qcom_slim_ngd_qmi_svc_event_deinit(&ctrl->qmi);
1515     if (ctrl->mwq)
1516         destroy_workqueue(ctrl->mwq);
1517 
1518     return ret;
1519 }
1520 
1521 static int qcom_slim_ngd_ctrl_probe(struct platform_device *pdev)
1522 {
1523     struct device *dev = &pdev->dev;
1524     struct qcom_slim_ngd_ctrl *ctrl;
1525     struct resource *res;
1526     int ret;
1527     struct pdr_service *pds;
1528 
1529     ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
1530     if (!ctrl)
1531         return -ENOMEM;
1532 
1533     dev_set_drvdata(dev, ctrl);
1534 
1535     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1536     ctrl->base = devm_ioremap_resource(dev, res);
1537     if (IS_ERR(ctrl->base))
1538         return PTR_ERR(ctrl->base);
1539 
1540     ret = platform_get_irq(pdev, 0);
1541     if (ret < 0)
1542         return ret;
1543 
1544     ret = devm_request_irq(dev, ret, qcom_slim_ngd_interrupt,
1545                    IRQF_TRIGGER_HIGH, "slim-ngd", ctrl);
1546     if (ret) {
1547         dev_err(&pdev->dev, "request IRQ failed\n");
1548         return ret;
1549     }
1550 
1551     ctrl->nb.notifier_call = qcom_slim_ngd_ssr_notify;
1552     ctrl->notifier = qcom_register_ssr_notifier("lpass", &ctrl->nb);
1553     if (IS_ERR(ctrl->notifier))
1554         return PTR_ERR(ctrl->notifier);
1555 
1556     ctrl->dev = dev;
1557     ctrl->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
1558     ctrl->framer.superfreq =
1559         ctrl->framer.rootfreq / SLIM_CL_PER_SUPERFRAME_DIV8;
1560 
1561     ctrl->ctrl.a_framer = &ctrl->framer;
1562     ctrl->ctrl.clkgear = SLIM_MAX_CLK_GEAR;
1563     ctrl->ctrl.get_laddr = qcom_slim_ngd_get_laddr;
1564     ctrl->ctrl.enable_stream = qcom_slim_ngd_enable_stream;
1565     ctrl->ctrl.xfer_msg = qcom_slim_ngd_xfer_msg;
1566     ctrl->ctrl.wakeup = NULL;
1567     ctrl->state = QCOM_SLIM_NGD_CTRL_DOWN;
1568 
1569     mutex_init(&ctrl->tx_lock);
1570     mutex_init(&ctrl->ssr_lock);
1571     spin_lock_init(&ctrl->tx_buf_lock);
1572     init_completion(&ctrl->reconf);
1573     init_completion(&ctrl->qmi.qmi_comp);
1574     init_completion(&ctrl->qmi_up);
1575 
1576     ctrl->pdr = pdr_handle_alloc(slim_pd_status, ctrl);
1577     if (IS_ERR(ctrl->pdr)) {
1578         dev_err(dev, "Failed to init PDR handle\n");
1579         return PTR_ERR(ctrl->pdr);
1580     }
1581 
1582     pds = pdr_add_lookup(ctrl->pdr, "avs/audio", "msm/adsp/audio_pd");
1583     if (IS_ERR(pds) && PTR_ERR(pds) != -EALREADY) {
1584         dev_err(dev, "pdr add lookup failed: %d\n", ret);
1585         return PTR_ERR(pds);
1586     }
1587 
1588     platform_driver_register(&qcom_slim_ngd_driver);
1589     return of_qcom_slim_ngd_register(dev, ctrl);
1590 }
1591 
1592 static int qcom_slim_ngd_ctrl_remove(struct platform_device *pdev)
1593 {
1594     platform_driver_unregister(&qcom_slim_ngd_driver);
1595 
1596     return 0;
1597 }
1598 
1599 static int qcom_slim_ngd_remove(struct platform_device *pdev)
1600 {
1601     struct qcom_slim_ngd_ctrl *ctrl = platform_get_drvdata(pdev);
1602 
1603     pm_runtime_disable(&pdev->dev);
1604     pdr_handle_release(ctrl->pdr);
1605     qcom_unregister_ssr_notifier(ctrl->notifier, &ctrl->nb);
1606     qcom_slim_ngd_enable(ctrl, false);
1607     qcom_slim_ngd_exit_dma(ctrl);
1608     qcom_slim_ngd_qmi_svc_event_deinit(&ctrl->qmi);
1609     if (ctrl->mwq)
1610         destroy_workqueue(ctrl->mwq);
1611 
1612     kfree(ctrl->ngd);
1613     ctrl->ngd = NULL;
1614     return 0;
1615 }
1616 
1617 static int __maybe_unused qcom_slim_ngd_runtime_idle(struct device *dev)
1618 {
1619     struct qcom_slim_ngd_ctrl *ctrl = dev_get_drvdata(dev);
1620 
1621     if (ctrl->state == QCOM_SLIM_NGD_CTRL_AWAKE)
1622         ctrl->state = QCOM_SLIM_NGD_CTRL_IDLE;
1623     pm_request_autosuspend(dev);
1624     return -EAGAIN;
1625 }
1626 
1627 static int __maybe_unused qcom_slim_ngd_runtime_suspend(struct device *dev)
1628 {
1629     struct qcom_slim_ngd_ctrl *ctrl = dev_get_drvdata(dev);
1630     int ret = 0;
1631 
1632     qcom_slim_ngd_exit_dma(ctrl);
1633     if (!ctrl->qmi.handle)
1634         return 0;
1635 
1636     ret = qcom_slim_qmi_power_request(ctrl, false);
1637     if (ret && ret != -EBUSY)
1638         dev_info(ctrl->dev, "slim resource not idle:%d\n", ret);
1639     if (!ret || ret == -ETIMEDOUT)
1640         ctrl->state = QCOM_SLIM_NGD_CTRL_ASLEEP;
1641 
1642     return ret;
1643 }
1644 
1645 static const struct dev_pm_ops qcom_slim_ngd_dev_pm_ops = {
1646     SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
1647                 pm_runtime_force_resume)
1648     SET_RUNTIME_PM_OPS(
1649         qcom_slim_ngd_runtime_suspend,
1650         qcom_slim_ngd_runtime_resume,
1651         qcom_slim_ngd_runtime_idle
1652     )
1653 };
1654 
1655 static struct platform_driver qcom_slim_ngd_ctrl_driver = {
1656     .probe = qcom_slim_ngd_ctrl_probe,
1657     .remove = qcom_slim_ngd_ctrl_remove,
1658     .driver = {
1659         .name = "qcom,slim-ngd-ctrl",
1660         .of_match_table = qcom_slim_ngd_dt_match,
1661     },
1662 };
1663 
1664 static struct platform_driver qcom_slim_ngd_driver = {
1665     .probe = qcom_slim_ngd_probe,
1666     .remove = qcom_slim_ngd_remove,
1667     .driver = {
1668         .name = QCOM_SLIM_NGD_DRV_NAME,
1669         .pm = &qcom_slim_ngd_dev_pm_ops,
1670     },
1671 };
1672 
1673 module_platform_driver(qcom_slim_ngd_ctrl_driver);
1674 MODULE_LICENSE("GPL v2");
1675 MODULE_DESCRIPTION("Qualcomm SLIMBus NGD controller");