^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) // Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // Copyright (c) 2018, Linaro Limited
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/dmaengine.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/slimbus.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/soc/qcom/qmi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "slimbus.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /* NGD (Non-ported Generic Device) registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define NGD_CFG 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define NGD_CFG_ENABLE BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define NGD_CFG_RX_MSGQ_EN BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define NGD_CFG_TX_MSGQ_EN BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define NGD_STATUS 0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define NGD_LADDR BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define NGD_RX_MSGQ_CFG 0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define NGD_INT_EN 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define NGD_INT_RECFG_DONE BIT(24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define NGD_INT_TX_NACKED_2 BIT(25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define NGD_INT_MSG_BUF_CONTE BIT(26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define NGD_INT_MSG_TX_INVAL BIT(27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define NGD_INT_IE_VE_CHG BIT(28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define NGD_INT_DEV_ERR BIT(29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define NGD_INT_RX_MSG_RCVD BIT(30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define NGD_INT_TX_MSG_SENT BIT(31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define NGD_INT_STAT 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define NGD_INT_CLR 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define DEF_NGD_INT_MASK (NGD_INT_TX_NACKED_2 | NGD_INT_MSG_BUF_CONTE | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) NGD_INT_MSG_TX_INVAL | NGD_INT_IE_VE_CHG | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) NGD_INT_DEV_ERR | NGD_INT_TX_MSG_SENT | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) NGD_INT_RX_MSG_RCVD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* Slimbus QMI service */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define SLIMBUS_QMI_SVC_ID 0x0301
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define SLIMBUS_QMI_SVC_V1 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define SLIMBUS_QMI_INS_ID 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define SLIMBUS_QMI_SELECT_INSTANCE_REQ_V01 0x0020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define SLIMBUS_QMI_SELECT_INSTANCE_RESP_V01 0x0020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define SLIMBUS_QMI_POWER_REQ_V01 0x0021
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define SLIMBUS_QMI_POWER_RESP_V01 0x0021
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define SLIMBUS_QMI_CHECK_FRAMER_STATUS_REQ 0x0022
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define SLIMBUS_QMI_CHECK_FRAMER_STATUS_RESP 0x0022
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define SLIMBUS_QMI_POWER_REQ_MAX_MSG_LEN 14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define SLIMBUS_QMI_POWER_RESP_MAX_MSG_LEN 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define SLIMBUS_QMI_SELECT_INSTANCE_REQ_MAX_MSG_LEN 14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define SLIMBUS_QMI_SELECT_INSTANCE_RESP_MAX_MSG_LEN 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define SLIMBUS_QMI_CHECK_FRAMER_STAT_RESP_MAX_MSG_LEN 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* QMI response timeout of 500ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define SLIMBUS_QMI_RESP_TOUT 1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* User defined commands */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define SLIM_USR_MC_GENERIC_ACK 0x25
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define SLIM_USR_MC_MASTER_CAPABILITY 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define SLIM_USR_MC_REPORT_SATELLITE 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define SLIM_USR_MC_ADDR_QUERY 0xD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define SLIM_USR_MC_ADDR_REPLY 0xE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define SLIM_USR_MC_DEFINE_CHAN 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define SLIM_USR_MC_DEF_ACT_CHAN 0x21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define SLIM_USR_MC_CHAN_CTRL 0x23
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define SLIM_USR_MC_RECONFIG_NOW 0x24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define SLIM_USR_MC_REQ_BW 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define SLIM_USR_MC_CONNECT_SRC 0x2C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define SLIM_USR_MC_CONNECT_SINK 0x2D
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define SLIM_USR_MC_DISCONNECT_PORT 0x2E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define SLIM_USR_MC_REPEAT_CHANGE_VALUE 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define QCOM_SLIM_NGD_AUTOSUSPEND MSEC_PER_SEC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define SLIM_RX_MSGQ_TIMEOUT_VAL 0x10000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define SLIM_LA_MGR 0xFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define SLIM_ROOT_FREQ 24576000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define LADDR_RETRY 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /* Per spec.max 40 bytes per received message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define SLIM_MSGQ_BUF_LEN 40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define QCOM_SLIM_NGD_DESC_NUM 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define SLIM_MSG_ASM_FIRST_WORD(l, mt, mc, dt, ad) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) ((l) | ((mt) << 5) | ((mc) << 8) | ((dt) << 15) | ((ad) << 16))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define INIT_MX_RETRIES 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define DEF_RETRY_MS 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define SAT_MAGIC_LSB 0xD9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define SAT_MAGIC_MSB 0xC5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define SAT_MSG_VER 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define SAT_MSG_PROT 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define to_ngd(d) container_of(d, struct qcom_slim_ngd, dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct ngd_reg_offset_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) u32 offset, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static const struct ngd_reg_offset_data ngd_v1_5_offset_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .offset = 0x1000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) .size = 0x1000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) enum qcom_slim_ngd_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) QCOM_SLIM_NGD_CTRL_AWAKE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) QCOM_SLIM_NGD_CTRL_IDLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) QCOM_SLIM_NGD_CTRL_ASLEEP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) QCOM_SLIM_NGD_CTRL_DOWN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct qcom_slim_ngd_qmi {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct qmi_handle qmi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct sockaddr_qrtr svc_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct qmi_handle svc_event_hdl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct qmi_response_type_v01 resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct qmi_handle *handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct completion qmi_comp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct qcom_slim_ngd_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct qcom_slim_ngd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) struct qcom_slim_ngd_dma_desc {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct dma_async_tx_descriptor *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct qcom_slim_ngd_ctrl *ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) struct completion *comp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) dma_cookie_t cookie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) dma_addr_t phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) void *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct qcom_slim_ngd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct platform_device *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct qcom_slim_ngd_ctrl {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct slim_framer framer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct slim_controller ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct qcom_slim_ngd_qmi qmi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct qcom_slim_ngd *ngd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) struct dma_chan *dma_rx_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct dma_chan *dma_tx_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct qcom_slim_ngd_dma_desc rx_desc[QCOM_SLIM_NGD_DESC_NUM];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct qcom_slim_ngd_dma_desc txdesc[QCOM_SLIM_NGD_DESC_NUM];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct completion reconf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct work_struct m_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct workqueue_struct *mwq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) spinlock_t tx_buf_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) enum qcom_slim_ngd_state state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) dma_addr_t rx_phys_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) dma_addr_t tx_phys_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) void *rx_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) void *tx_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) int tx_tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) int tx_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) u32 ver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) enum slimbus_mode_enum_type_v01 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) /* To force a 32 bit signed enum. Do not change or use*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) SLIMBUS_MODE_ENUM_TYPE_MIN_ENUM_VAL_V01 = INT_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) SLIMBUS_MODE_SATELLITE_V01 = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) SLIMBUS_MODE_MASTER_V01 = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) SLIMBUS_MODE_ENUM_TYPE_MAX_ENUM_VAL_V01 = INT_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) enum slimbus_pm_enum_type_v01 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) /* To force a 32 bit signed enum. Do not change or use*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) SLIMBUS_PM_ENUM_TYPE_MIN_ENUM_VAL_V01 = INT_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) SLIMBUS_PM_INACTIVE_V01 = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) SLIMBUS_PM_ACTIVE_V01 = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) SLIMBUS_PM_ENUM_TYPE_MAX_ENUM_VAL_V01 = INT_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) enum slimbus_resp_enum_type_v01 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) SLIMBUS_RESP_ENUM_TYPE_MIN_VAL_V01 = INT_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) SLIMBUS_RESP_SYNCHRONOUS_V01 = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) SLIMBUS_RESP_ENUM_TYPE_MAX_VAL_V01 = INT_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct slimbus_select_inst_req_msg_v01 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) uint32_t instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) uint8_t mode_valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) enum slimbus_mode_enum_type_v01 mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct slimbus_select_inst_resp_msg_v01 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct qmi_response_type_v01 resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct slimbus_power_req_msg_v01 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) enum slimbus_pm_enum_type_v01 pm_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) uint8_t resp_type_valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) enum slimbus_resp_enum_type_v01 resp_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) struct slimbus_power_resp_msg_v01 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct qmi_response_type_v01 resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static struct qmi_elem_info slimbus_select_inst_req_msg_v01_ei[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) .data_type = QMI_UNSIGNED_4_BYTE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) .elem_len = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) .elem_size = sizeof(uint32_t),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) .array_type = NO_ARRAY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) .tlv_type = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) .offset = offsetof(struct slimbus_select_inst_req_msg_v01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) instance),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) .ei_array = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) .data_type = QMI_OPT_FLAG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) .elem_len = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) .elem_size = sizeof(uint8_t),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) .array_type = NO_ARRAY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) .tlv_type = 0x10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) .offset = offsetof(struct slimbus_select_inst_req_msg_v01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) mode_valid),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) .ei_array = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) .data_type = QMI_UNSIGNED_4_BYTE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) .elem_len = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) .elem_size = sizeof(enum slimbus_mode_enum_type_v01),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) .array_type = NO_ARRAY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) .tlv_type = 0x10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) .offset = offsetof(struct slimbus_select_inst_req_msg_v01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) mode),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) .ei_array = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) .data_type = QMI_EOTI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) .elem_len = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) .elem_size = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) .array_type = NO_ARRAY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) .tlv_type = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) .offset = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) .ei_array = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static struct qmi_elem_info slimbus_select_inst_resp_msg_v01_ei[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) .data_type = QMI_STRUCT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) .elem_len = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) .elem_size = sizeof(struct qmi_response_type_v01),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) .array_type = NO_ARRAY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) .tlv_type = 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) .offset = offsetof(struct slimbus_select_inst_resp_msg_v01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) .ei_array = qmi_response_type_v01_ei,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) .data_type = QMI_EOTI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) .elem_len = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) .elem_size = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) .array_type = NO_ARRAY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) .tlv_type = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) .offset = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) .ei_array = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) static struct qmi_elem_info slimbus_power_req_msg_v01_ei[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) .data_type = QMI_UNSIGNED_4_BYTE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) .elem_len = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) .elem_size = sizeof(enum slimbus_pm_enum_type_v01),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) .array_type = NO_ARRAY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) .tlv_type = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) .offset = offsetof(struct slimbus_power_req_msg_v01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) pm_req),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) .ei_array = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) .data_type = QMI_OPT_FLAG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) .elem_len = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) .elem_size = sizeof(uint8_t),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) .array_type = NO_ARRAY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) .tlv_type = 0x10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) .offset = offsetof(struct slimbus_power_req_msg_v01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) resp_type_valid),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) .data_type = QMI_SIGNED_4_BYTE_ENUM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) .elem_len = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) .elem_size = sizeof(enum slimbus_resp_enum_type_v01),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) .array_type = NO_ARRAY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) .tlv_type = 0x10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) .offset = offsetof(struct slimbus_power_req_msg_v01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) resp_type),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) .data_type = QMI_EOTI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) .elem_len = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) .elem_size = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) .array_type = NO_ARRAY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) .tlv_type = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) .offset = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) .ei_array = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static struct qmi_elem_info slimbus_power_resp_msg_v01_ei[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) .data_type = QMI_STRUCT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) .elem_len = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) .elem_size = sizeof(struct qmi_response_type_v01),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) .array_type = NO_ARRAY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) .tlv_type = 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) .offset = offsetof(struct slimbus_power_resp_msg_v01, resp),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) .ei_array = qmi_response_type_v01_ei,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) .data_type = QMI_EOTI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) .elem_len = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) .elem_size = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) .array_type = NO_ARRAY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) .tlv_type = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) .offset = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) .ei_array = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) static int qcom_slim_qmi_send_select_inst_req(struct qcom_slim_ngd_ctrl *ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) struct slimbus_select_inst_req_msg_v01 *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) struct slimbus_select_inst_resp_msg_v01 resp = { { 0, 0 } };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) struct qmi_txn txn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) rc = qmi_txn_init(ctrl->qmi.handle, &txn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) slimbus_select_inst_resp_msg_v01_ei, &resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) dev_err(ctrl->dev, "QMI TXN init fail: %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) rc = qmi_send_request(ctrl->qmi.handle, NULL, &txn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) SLIMBUS_QMI_SELECT_INSTANCE_REQ_V01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) SLIMBUS_QMI_SELECT_INSTANCE_REQ_MAX_MSG_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) slimbus_select_inst_req_msg_v01_ei, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) dev_err(ctrl->dev, "QMI send req fail %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) qmi_txn_cancel(&txn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) rc = qmi_txn_wait(&txn, SLIMBUS_QMI_RESP_TOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) dev_err(ctrl->dev, "QMI TXN wait fail: %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /* Check the response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) dev_err(ctrl->dev, "QMI request failed 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) resp.resp.result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) static void qcom_slim_qmi_power_resp_cb(struct qmi_handle *handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) struct sockaddr_qrtr *sq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) struct qmi_txn *txn, const void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) struct slimbus_power_resp_msg_v01 *resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) resp = (struct slimbus_power_resp_msg_v01 *)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (resp->resp.result != QMI_RESULT_SUCCESS_V01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) pr_err("QMI power request failed 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) resp->resp.result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) complete(&txn->completion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) static int qcom_slim_qmi_send_power_request(struct qcom_slim_ngd_ctrl *ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) struct slimbus_power_req_msg_v01 *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) struct slimbus_power_resp_msg_v01 resp = { { 0, 0 } };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) struct qmi_txn txn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) rc = qmi_txn_init(ctrl->qmi.handle, &txn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) slimbus_power_resp_msg_v01_ei, &resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) rc = qmi_send_request(ctrl->qmi.handle, NULL, &txn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) SLIMBUS_QMI_POWER_REQ_V01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) SLIMBUS_QMI_POWER_REQ_MAX_MSG_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) slimbus_power_req_msg_v01_ei, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) dev_err(ctrl->dev, "QMI send req fail %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) qmi_txn_cancel(&txn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) rc = qmi_txn_wait(&txn, SLIMBUS_QMI_RESP_TOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) dev_err(ctrl->dev, "QMI TXN wait fail: %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) /* Check the response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) dev_err(ctrl->dev, "QMI request failed 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) resp.resp.result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) static struct qmi_msg_handler qcom_slim_qmi_msg_handlers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) .type = QMI_RESPONSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) .msg_id = SLIMBUS_QMI_POWER_RESP_V01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) .ei = slimbus_power_resp_msg_v01_ei,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) .decoded_size = sizeof(struct slimbus_power_resp_msg_v01),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) .fn = qcom_slim_qmi_power_resp_cb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) static int qcom_slim_qmi_init(struct qcom_slim_ngd_ctrl *ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) bool apps_is_master)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) struct slimbus_select_inst_req_msg_v01 req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) struct qmi_handle *handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) handle = devm_kzalloc(ctrl->dev, sizeof(*handle), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (!handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) rc = qmi_handle_init(handle, SLIMBUS_QMI_POWER_REQ_MAX_MSG_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) NULL, qcom_slim_qmi_msg_handlers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) dev_err(ctrl->dev, "QMI client init failed: %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) goto qmi_handle_init_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) rc = kernel_connect(handle->sock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) (struct sockaddr *)&ctrl->qmi.svc_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) sizeof(ctrl->qmi.svc_info), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) dev_err(ctrl->dev, "Remote Service connect failed: %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) goto qmi_connect_to_service_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) /* Instance is 0 based */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) req.instance = (ctrl->ngd->id >> 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) req.mode_valid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) /* Mode indicates the role of the ADSP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (apps_is_master)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) req.mode = SLIMBUS_MODE_SATELLITE_V01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) req.mode = SLIMBUS_MODE_MASTER_V01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) ctrl->qmi.handle = handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) rc = qcom_slim_qmi_send_select_inst_req(ctrl, &req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) dev_err(ctrl->dev, "failed to select h/w instance\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) goto qmi_select_instance_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) qmi_select_instance_failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) ctrl->qmi.handle = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) qmi_connect_to_service_failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) qmi_handle_release(handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) qmi_handle_init_failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) devm_kfree(ctrl->dev, handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) static void qcom_slim_qmi_exit(struct qcom_slim_ngd_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (!ctrl->qmi.handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) qmi_handle_release(ctrl->qmi.handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) devm_kfree(ctrl->dev, ctrl->qmi.handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) ctrl->qmi.handle = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) static int qcom_slim_qmi_power_request(struct qcom_slim_ngd_ctrl *ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) bool active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) struct slimbus_power_req_msg_v01 req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) req.pm_req = SLIMBUS_PM_ACTIVE_V01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) req.pm_req = SLIMBUS_PM_INACTIVE_V01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) req.resp_type_valid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) return qcom_slim_qmi_send_power_request(ctrl, &req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) static u32 *qcom_slim_ngd_tx_msg_get(struct qcom_slim_ngd_ctrl *ctrl, int len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) struct completion *comp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) struct qcom_slim_ngd_dma_desc *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) spin_lock_irqsave(&ctrl->tx_buf_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if ((ctrl->tx_tail + 1) % QCOM_SLIM_NGD_DESC_NUM == ctrl->tx_head) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) spin_unlock_irqrestore(&ctrl->tx_buf_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) desc = &ctrl->txdesc[ctrl->tx_tail];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) desc->base = ctrl->tx_base + ctrl->tx_tail * SLIM_MSGQ_BUF_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) desc->comp = comp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) ctrl->tx_tail = (ctrl->tx_tail + 1) % QCOM_SLIM_NGD_DESC_NUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) spin_unlock_irqrestore(&ctrl->tx_buf_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) return desc->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) static void qcom_slim_ngd_tx_msg_dma_cb(void *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) struct qcom_slim_ngd_dma_desc *desc = args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) struct qcom_slim_ngd_ctrl *ctrl = desc->ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) spin_lock_irqsave(&ctrl->tx_buf_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (desc->comp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) complete(desc->comp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) desc->comp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) ctrl->tx_head = (ctrl->tx_head + 1) % QCOM_SLIM_NGD_DESC_NUM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) spin_unlock_irqrestore(&ctrl->tx_buf_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) static int qcom_slim_ngd_tx_msg_post(struct qcom_slim_ngd_ctrl *ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) void *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) struct qcom_slim_ngd_dma_desc *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) int index, offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) spin_lock_irqsave(&ctrl->tx_buf_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) offset = buf - ctrl->tx_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) index = offset/SLIM_MSGQ_BUF_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) desc = &ctrl->txdesc[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) desc->phys = ctrl->tx_phys_base + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) desc->base = ctrl->tx_base + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) desc->ctrl = ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) len = (len + 3) & 0xfc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) desc->desc = dmaengine_prep_slave_single(ctrl->dma_tx_channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) desc->phys, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) DMA_MEM_TO_DEV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) DMA_PREP_INTERRUPT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) if (!desc->desc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) dev_err(ctrl->dev, "unable to prepare channel\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) spin_unlock_irqrestore(&ctrl->tx_buf_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) desc->desc->callback = qcom_slim_ngd_tx_msg_dma_cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) desc->desc->callback_param = desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) desc->desc->cookie = dmaengine_submit(desc->desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) dma_async_issue_pending(ctrl->dma_tx_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) spin_unlock_irqrestore(&ctrl->tx_buf_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) static void qcom_slim_ngd_rx(struct qcom_slim_ngd_ctrl *ctrl, u8 *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) u8 mc, mt, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) mt = SLIM_HEADER_GET_MT(buf[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) len = SLIM_HEADER_GET_RL(buf[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) mc = SLIM_HEADER_GET_MC(buf[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (mc == SLIM_USR_MC_MASTER_CAPABILITY &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) mt == SLIM_MSG_MT_SRC_REFERRED_USER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) queue_work(ctrl->mwq, &ctrl->m_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) mc == SLIM_MSG_MC_REPLY_VALUE || (mc == SLIM_USR_MC_ADDR_REPLY &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) mt == SLIM_MSG_MT_SRC_REFERRED_USER) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) (mc == SLIM_USR_MC_GENERIC_ACK &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) mt == SLIM_MSG_MT_SRC_REFERRED_USER)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) slim_msg_response(&ctrl->ctrl, &buf[4], buf[3], len - 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) pm_runtime_mark_last_busy(ctrl->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) static void qcom_slim_ngd_rx_msgq_cb(void *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) struct qcom_slim_ngd_dma_desc *desc = args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) struct qcom_slim_ngd_ctrl *ctrl = desc->ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) qcom_slim_ngd_rx(ctrl, (u8 *)desc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) /* Add descriptor back to the queue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) desc->desc = dmaengine_prep_slave_single(ctrl->dma_rx_channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) desc->phys, SLIM_MSGQ_BUF_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) DMA_DEV_TO_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) DMA_PREP_INTERRUPT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (!desc->desc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) dev_err(ctrl->dev, "Unable to prepare rx channel\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) desc->desc->callback = qcom_slim_ngd_rx_msgq_cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) desc->desc->callback_param = desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) desc->desc->cookie = dmaengine_submit(desc->desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) dma_async_issue_pending(ctrl->dma_rx_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) static int qcom_slim_ngd_post_rx_msgq(struct qcom_slim_ngd_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) struct qcom_slim_ngd_dma_desc *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) for (i = 0; i < QCOM_SLIM_NGD_DESC_NUM; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) desc = &ctrl->rx_desc[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) desc->phys = ctrl->rx_phys_base + i * SLIM_MSGQ_BUF_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) desc->ctrl = ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) desc->base = ctrl->rx_base + i * SLIM_MSGQ_BUF_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) desc->desc = dmaengine_prep_slave_single(ctrl->dma_rx_channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) desc->phys, SLIM_MSGQ_BUF_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) DMA_DEV_TO_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) DMA_PREP_INTERRUPT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (!desc->desc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) dev_err(ctrl->dev, "Unable to prepare rx channel\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) desc->desc->callback = qcom_slim_ngd_rx_msgq_cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) desc->desc->callback_param = desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) desc->desc->cookie = dmaengine_submit(desc->desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) dma_async_issue_pending(ctrl->dma_rx_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) static int qcom_slim_ngd_init_rx_msgq(struct qcom_slim_ngd_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) struct device *dev = ctrl->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) int ret, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) ctrl->dma_rx_channel = dma_request_chan(dev, "rx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) if (IS_ERR(ctrl->dma_rx_channel)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) dev_err(dev, "Failed to request RX dma channel");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) ret = PTR_ERR(ctrl->dma_rx_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) ctrl->dma_rx_channel = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) size = QCOM_SLIM_NGD_DESC_NUM * SLIM_MSGQ_BUF_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) ctrl->rx_base = dma_alloc_coherent(dev, size, &ctrl->rx_phys_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) if (!ctrl->rx_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) dev_err(dev, "dma_alloc_coherent failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) goto rel_rx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) ret = qcom_slim_ngd_post_rx_msgq(ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) dev_err(dev, "post_rx_msgq() failed 0x%x\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) goto rx_post_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) rx_post_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) dma_free_coherent(dev, size, ctrl->rx_base, ctrl->rx_phys_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) rel_rx:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) dma_release_channel(ctrl->dma_rx_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) static int qcom_slim_ngd_init_tx_msgq(struct qcom_slim_ngd_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) struct device *dev = ctrl->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) ctrl->dma_tx_channel = dma_request_chan(dev, "tx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (IS_ERR(ctrl->dma_tx_channel)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) dev_err(dev, "Failed to request TX dma channel");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) ret = PTR_ERR(ctrl->dma_tx_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) ctrl->dma_tx_channel = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) size = ((QCOM_SLIM_NGD_DESC_NUM + 1) * SLIM_MSGQ_BUF_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) ctrl->tx_base = dma_alloc_coherent(dev, size, &ctrl->tx_phys_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) if (!ctrl->tx_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) dev_err(dev, "dma_alloc_coherent failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) goto rel_tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) spin_lock_irqsave(&ctrl->tx_buf_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) ctrl->tx_tail = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) ctrl->tx_head = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) spin_unlock_irqrestore(&ctrl->tx_buf_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) rel_tx:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) dma_release_channel(ctrl->dma_tx_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) static int qcom_slim_ngd_init_dma(struct qcom_slim_ngd_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) ret = qcom_slim_ngd_init_rx_msgq(ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) dev_err(ctrl->dev, "rx dma init failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) ret = qcom_slim_ngd_init_tx_msgq(ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) dev_err(ctrl->dev, "tx dma init failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) static irqreturn_t qcom_slim_ngd_interrupt(int irq, void *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) struct qcom_slim_ngd_ctrl *ctrl = d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) void __iomem *base = ctrl->ngd->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) u32 stat = readl(base + NGD_INT_STAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if ((stat & NGD_INT_MSG_BUF_CONTE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) (stat & NGD_INT_MSG_TX_INVAL) || (stat & NGD_INT_DEV_ERR) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) (stat & NGD_INT_TX_NACKED_2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) dev_err(ctrl->dev, "Error Interrupt received 0x%x\n", stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) writel(stat, base + NGD_INT_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) static int qcom_slim_ngd_xfer_msg(struct slim_controller *sctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) struct slim_msg_txn *txn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) struct qcom_slim_ngd_ctrl *ctrl = dev_get_drvdata(sctrl->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) DECLARE_COMPLETION_ONSTACK(tx_sent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) DECLARE_COMPLETION_ONSTACK(done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) int ret, timeout, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) u8 wbuf[SLIM_MSGQ_BUF_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) u8 rbuf[SLIM_MSGQ_BUF_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) u32 *pbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) u8 *puc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) u8 la = txn->la;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) bool usr_msg = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) if (txn->mt == SLIM_MSG_MT_CORE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) (txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) if (txn->dt == SLIM_MSG_DEST_ENUMADDR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) return -EPROTONOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (txn->msg->num_bytes > SLIM_MSGQ_BUF_LEN ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) txn->rl > SLIM_MSGQ_BUF_LEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) dev_err(ctrl->dev, "msg exceeds HW limit\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) pbuf = qcom_slim_ngd_tx_msg_get(ctrl, txn->rl, &tx_sent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) if (!pbuf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) dev_err(ctrl->dev, "Message buffer unavailable\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if (txn->mt == SLIM_MSG_MT_CORE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) (txn->mc == SLIM_MSG_MC_CONNECT_SOURCE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) txn->mc == SLIM_MSG_MC_CONNECT_SINK ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) txn->mc == SLIM_MSG_MC_DISCONNECT_PORT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) txn->mt = SLIM_MSG_MT_DEST_REFERRED_USER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) switch (txn->mc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) case SLIM_MSG_MC_CONNECT_SOURCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) txn->mc = SLIM_USR_MC_CONNECT_SRC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) case SLIM_MSG_MC_CONNECT_SINK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) txn->mc = SLIM_USR_MC_CONNECT_SINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) case SLIM_MSG_MC_DISCONNECT_PORT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) txn->mc = SLIM_USR_MC_DISCONNECT_PORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) usr_msg = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) wbuf[i++] = txn->la;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) la = SLIM_LA_MGR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) wbuf[i++] = txn->msg->wbuf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if (txn->mc != SLIM_USR_MC_DISCONNECT_PORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) wbuf[i++] = txn->msg->wbuf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) txn->comp = &done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) ret = slim_alloc_txn_tid(sctrl, txn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) dev_err(ctrl->dev, "Unable to allocate TID\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) wbuf[i++] = txn->tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) txn->msg->num_bytes = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) txn->msg->wbuf = wbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) txn->msg->rbuf = rbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) txn->rl = txn->msg->num_bytes + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) /* HW expects length field to be excluded */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) txn->rl--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) puc = (u8 *)pbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) *pbuf = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) if (txn->dt == SLIM_MSG_DEST_LOGICALADDR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) *pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) la);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) puc += 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) *pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) la);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) puc += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) if (slim_tid_txn(txn->mt, txn->mc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) *(puc++) = txn->tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (slim_ec_txn(txn->mt, txn->mc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) *(puc++) = (txn->ec & 0xFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) *(puc++) = (txn->ec >> 8) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if (txn->msg && txn->msg->wbuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) memcpy(puc, txn->msg->wbuf, txn->msg->num_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) ret = qcom_slim_ngd_tx_msg_post(ctrl, pbuf, txn->rl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) timeout = wait_for_completion_timeout(&tx_sent, HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) if (!timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) dev_err(sctrl->dev, "TX timed out:MC:0x%x,mt:0x%x", txn->mc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) txn->mt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) if (usr_msg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) timeout = wait_for_completion_timeout(&done, HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) if (!timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) dev_err(sctrl->dev, "TX timed out:MC:0x%x,mt:0x%x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) txn->mc, txn->mt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) static int qcom_slim_ngd_xfer_msg_sync(struct slim_controller *ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) struct slim_msg_txn *txn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) DECLARE_COMPLETION_ONSTACK(done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) int ret, timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) pm_runtime_get_sync(ctrl->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) txn->comp = &done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) ret = qcom_slim_ngd_xfer_msg(ctrl, txn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) timeout = wait_for_completion_timeout(&done, HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) if (!timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) dev_err(ctrl->dev, "TX timed out:MC:0x%x,mt:0x%x", txn->mc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) txn->mt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) static int qcom_slim_ngd_enable_stream(struct slim_stream_runtime *rt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) struct slim_device *sdev = rt->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) struct slim_controller *ctrl = sdev->ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) struct slim_val_inf msg = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) u8 wbuf[SLIM_MSGQ_BUF_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) u8 rbuf[SLIM_MSGQ_BUF_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) struct slim_msg_txn txn = {0,};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) txn.mt = SLIM_MSG_MT_DEST_REFERRED_USER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) txn.dt = SLIM_MSG_DEST_LOGICALADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) txn.la = SLIM_LA_MGR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) txn.ec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) txn.msg = &msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) txn.msg->num_bytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) txn.msg->wbuf = wbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) txn.msg->rbuf = rbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) for (i = 0; i < rt->num_ports; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) struct slim_port *port = &rt->ports[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) if (txn.msg->num_bytes == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) int seg_interval = SLIM_SLOTS_PER_SUPERFRAME/rt->ratem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) int exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) wbuf[txn.msg->num_bytes++] = sdev->laddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) wbuf[txn.msg->num_bytes] = rt->bps >> 2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) (port->ch.aux_fmt << 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) /* Data channel segment interval not multiple of 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) exp = seg_interval % 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) if (exp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) wbuf[txn.msg->num_bytes] |= BIT(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) txn.msg->num_bytes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) wbuf[txn.msg->num_bytes++] = exp << 4 | rt->prot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) if (rt->prot == SLIM_PROTO_ISO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) wbuf[txn.msg->num_bytes++] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) port->ch.prrate |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) SLIM_CHANNEL_CONTENT_FL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) wbuf[txn.msg->num_bytes++] = port->ch.prrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) ret = slim_alloc_txn_tid(ctrl, &txn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) dev_err(&sdev->dev, "Fail to allocate TID\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) wbuf[txn.msg->num_bytes++] = txn.tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) wbuf[txn.msg->num_bytes++] = port->ch.id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) txn.mc = SLIM_USR_MC_DEF_ACT_CHAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) txn.rl = txn.msg->num_bytes + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) ret = qcom_slim_ngd_xfer_msg_sync(ctrl, &txn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) slim_free_txn_tid(ctrl, &txn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) dev_err(&sdev->dev, "TX timed out:MC:0x%x,mt:0x%x", txn.mc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) txn.mt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) txn.mc = SLIM_USR_MC_RECONFIG_NOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) txn.msg->num_bytes = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) wbuf[1] = sdev->laddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) txn.rl = txn.msg->num_bytes + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) ret = slim_alloc_txn_tid(ctrl, &txn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) dev_err(ctrl->dev, "Fail to allocate TID\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) wbuf[0] = txn.tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) ret = qcom_slim_ngd_xfer_msg_sync(ctrl, &txn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) slim_free_txn_tid(ctrl, &txn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) dev_err(&sdev->dev, "TX timed out:MC:0x%x,mt:0x%x", txn.mc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) txn.mt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) static int qcom_slim_ngd_get_laddr(struct slim_controller *ctrl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) struct slim_eaddr *ea, u8 *laddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) struct slim_val_inf msg = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) u8 failed_ea[6] = {0, 0, 0, 0, 0, 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) struct slim_msg_txn txn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) u8 wbuf[10] = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) u8 rbuf[10] = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) txn.mt = SLIM_MSG_MT_DEST_REFERRED_USER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) txn.dt = SLIM_MSG_DEST_LOGICALADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) txn.la = SLIM_LA_MGR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) txn.ec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) txn.mc = SLIM_USR_MC_ADDR_QUERY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) txn.rl = 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) txn.msg = &msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) txn.msg->num_bytes = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) txn.msg->wbuf = wbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) txn.msg->rbuf = rbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) ret = slim_alloc_txn_tid(ctrl, &txn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) wbuf[0] = (u8)txn.tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) memcpy(&wbuf[1], ea, sizeof(*ea));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) ret = qcom_slim_ngd_xfer_msg_sync(ctrl, &txn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) slim_free_txn_tid(ctrl, &txn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) if (!memcmp(rbuf, failed_ea, 6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) *laddr = rbuf[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) static int qcom_slim_ngd_exit_dma(struct qcom_slim_ngd_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) if (ctrl->dma_rx_channel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) dmaengine_terminate_sync(ctrl->dma_rx_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) dma_release_channel(ctrl->dma_rx_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) if (ctrl->dma_tx_channel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) dmaengine_terminate_sync(ctrl->dma_tx_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) dma_release_channel(ctrl->dma_tx_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) ctrl->dma_tx_channel = ctrl->dma_rx_channel = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) static void qcom_slim_ngd_setup(struct qcom_slim_ngd_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) u32 cfg = readl_relaxed(ctrl->ngd->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) if (ctrl->state == QCOM_SLIM_NGD_CTRL_DOWN ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) ctrl->state == QCOM_SLIM_NGD_CTRL_ASLEEP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) qcom_slim_ngd_init_dma(ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) /* By default enable message queues */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) cfg |= NGD_CFG_RX_MSGQ_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) cfg |= NGD_CFG_TX_MSGQ_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) /* Enable NGD if it's not already enabled*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) if (!(cfg & NGD_CFG_ENABLE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) cfg |= NGD_CFG_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) writel_relaxed(cfg, ctrl->ngd->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) static int qcom_slim_ngd_power_up(struct qcom_slim_ngd_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) enum qcom_slim_ngd_state cur_state = ctrl->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) struct qcom_slim_ngd *ngd = ctrl->ngd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) u32 laddr, rx_msgq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) int timeout, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) if (ctrl->state == QCOM_SLIM_NGD_CTRL_DOWN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) timeout = wait_for_completion_timeout(&ctrl->qmi.qmi_comp, HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) if (!timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) return -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) if (ctrl->state == QCOM_SLIM_NGD_CTRL_ASLEEP ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) ctrl->state == QCOM_SLIM_NGD_CTRL_DOWN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) ret = qcom_slim_qmi_power_request(ctrl, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) dev_err(ctrl->dev, "SLIM QMI power request failed:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) ctrl->ver = readl_relaxed(ctrl->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) /* Version info in 16 MSbits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) ctrl->ver >>= 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) laddr = readl_relaxed(ngd->base + NGD_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) if (laddr & NGD_LADDR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) * external MDM restart case where ADSP itself was active framer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) * For example, modem restarted when playback was active
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) if (cur_state == QCOM_SLIM_NGD_CTRL_AWAKE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) dev_info(ctrl->dev, "Subsys restart: ADSP active framer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) qcom_slim_ngd_setup(ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) writel_relaxed(DEF_NGD_INT_MASK, ngd->base + NGD_INT_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) rx_msgq = readl_relaxed(ngd->base + NGD_RX_MSGQ_CFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) writel_relaxed(rx_msgq|SLIM_RX_MSGQ_TIMEOUT_VAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) ngd->base + NGD_RX_MSGQ_CFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) qcom_slim_ngd_setup(ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) timeout = wait_for_completion_timeout(&ctrl->reconf, HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) if (!timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) dev_err(ctrl->dev, "capability exchange timed-out\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) static void qcom_slim_ngd_notify_slaves(struct qcom_slim_ngd_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) struct slim_device *sbdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) struct device_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) for_each_child_of_node(ctrl->ngd->pdev->dev.of_node, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) sbdev = of_slim_get_device(&ctrl->ctrl, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) if (!sbdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) if (slim_get_logical_addr(sbdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) dev_err(ctrl->dev, "Failed to get logical address\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) static void qcom_slim_ngd_master_worker(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) struct qcom_slim_ngd_ctrl *ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) struct slim_msg_txn txn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) struct slim_val_inf msg = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) int retries = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) u8 wbuf[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) ctrl = container_of(work, struct qcom_slim_ngd_ctrl, m_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) txn.dt = SLIM_MSG_DEST_LOGICALADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) txn.ec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) txn.mc = SLIM_USR_MC_REPORT_SATELLITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) txn.la = SLIM_LA_MGR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) wbuf[0] = SAT_MAGIC_LSB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) wbuf[1] = SAT_MAGIC_MSB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) wbuf[2] = SAT_MSG_VER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) wbuf[3] = SAT_MSG_PROT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) txn.msg = &msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) txn.msg->wbuf = wbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) txn.msg->num_bytes = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) txn.rl = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) dev_info(ctrl->dev, "SLIM SAT: Rcvd master capability\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) capability_retry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) ret = qcom_slim_ngd_xfer_msg(&ctrl->ctrl, &txn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) if (ctrl->state >= QCOM_SLIM_NGD_CTRL_ASLEEP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) complete(&ctrl->reconf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) dev_err(ctrl->dev, "unexpected state:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) ctrl->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) if (ctrl->state == QCOM_SLIM_NGD_CTRL_DOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) qcom_slim_ngd_notify_slaves(ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) } else if (ret == -EIO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) dev_err(ctrl->dev, "capability message NACKed, retrying\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) if (retries < INIT_MX_RETRIES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) msleep(DEF_RETRY_MS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) retries++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) goto capability_retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) dev_err(ctrl->dev, "SLIM: capability TX failed:%d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) static int qcom_slim_ngd_runtime_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) struct qcom_slim_ngd_ctrl *ctrl = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) if (!ctrl->qmi.handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) if (ctrl->state >= QCOM_SLIM_NGD_CTRL_ASLEEP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) ret = qcom_slim_ngd_power_up(ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) /* Did SSR cause this power up failure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) if (ctrl->state != QCOM_SLIM_NGD_CTRL_DOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) ctrl->state = QCOM_SLIM_NGD_CTRL_ASLEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) dev_err(ctrl->dev, "HW wakeup attempt during SSR\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) ctrl->state = QCOM_SLIM_NGD_CTRL_AWAKE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) static int qcom_slim_ngd_enable(struct qcom_slim_ngd_ctrl *ctrl, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) int ret = qcom_slim_qmi_init(ctrl, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) dev_err(ctrl->dev, "qmi init fail, ret:%d, state:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) ret, ctrl->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) /* controller state should be in sync with framework state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) complete(&ctrl->qmi.qmi_comp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) if (!pm_runtime_enabled(ctrl->dev) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) !pm_runtime_suspended(ctrl->dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) qcom_slim_ngd_runtime_resume(ctrl->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) pm_runtime_resume(ctrl->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) pm_runtime_mark_last_busy(ctrl->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) pm_runtime_put(ctrl->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) ret = slim_register_controller(&ctrl->ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) dev_err(ctrl->dev, "error adding slim controller\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) dev_info(ctrl->dev, "SLIM controller Registered\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) qcom_slim_qmi_exit(ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) slim_unregister_controller(&ctrl->ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) static int qcom_slim_ngd_qmi_new_server(struct qmi_handle *hdl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) struct qmi_service *service)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) struct qcom_slim_ngd_qmi *qmi =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) container_of(hdl, struct qcom_slim_ngd_qmi, svc_event_hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) struct qcom_slim_ngd_ctrl *ctrl =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) container_of(qmi, struct qcom_slim_ngd_ctrl, qmi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) qmi->svc_info.sq_family = AF_QIPCRTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) qmi->svc_info.sq_node = service->node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) qmi->svc_info.sq_port = service->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) qcom_slim_ngd_enable(ctrl, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) static void qcom_slim_ngd_qmi_del_server(struct qmi_handle *hdl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) struct qmi_service *service)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) struct qcom_slim_ngd_qmi *qmi =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) container_of(hdl, struct qcom_slim_ngd_qmi, svc_event_hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) struct qcom_slim_ngd_ctrl *ctrl =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) container_of(qmi, struct qcom_slim_ngd_ctrl, qmi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) qmi->svc_info.sq_node = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) qmi->svc_info.sq_port = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) qcom_slim_ngd_enable(ctrl, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) static struct qmi_ops qcom_slim_ngd_qmi_svc_event_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) .new_server = qcom_slim_ngd_qmi_new_server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) .del_server = qcom_slim_ngd_qmi_del_server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) static int qcom_slim_ngd_qmi_svc_event_init(struct qcom_slim_ngd_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) struct qcom_slim_ngd_qmi *qmi = &ctrl->qmi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) ret = qmi_handle_init(&qmi->svc_event_hdl, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) &qcom_slim_ngd_qmi_svc_event_ops, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) dev_err(ctrl->dev, "qmi_handle_init failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) ret = qmi_add_lookup(&qmi->svc_event_hdl, SLIMBUS_QMI_SVC_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) SLIMBUS_QMI_SVC_V1, SLIMBUS_QMI_INS_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) dev_err(ctrl->dev, "qmi_add_lookup failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) qmi_handle_release(&qmi->svc_event_hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) static void qcom_slim_ngd_qmi_svc_event_deinit(struct qcom_slim_ngd_qmi *qmi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) qmi_handle_release(&qmi->svc_event_hdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) static struct platform_driver qcom_slim_ngd_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) #define QCOM_SLIM_NGD_DRV_NAME "qcom,slim-ngd"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) static const struct of_device_id qcom_slim_ngd_dt_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) .compatible = "qcom,slim-ngd-v1.5.0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) .data = &ngd_v1_5_offset_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) },{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) .compatible = "qcom,slim-ngd-v2.1.0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) .data = &ngd_v1_5_offset_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) MODULE_DEVICE_TABLE(of, qcom_slim_ngd_dt_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) static int of_qcom_slim_ngd_register(struct device *parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) struct qcom_slim_ngd_ctrl *ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) const struct ngd_reg_offset_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) struct qcom_slim_ngd *ngd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) const struct of_device_id *match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) struct device_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) u32 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) match = of_match_node(qcom_slim_ngd_dt_match, parent->of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) data = match->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) for_each_available_child_of_node(parent->of_node, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) if (of_property_read_u32(node, "reg", &id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) ngd = kzalloc(sizeof(*ngd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) if (!ngd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) of_node_put(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) ngd->pdev = platform_device_alloc(QCOM_SLIM_NGD_DRV_NAME, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) if (!ngd->pdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) kfree(ngd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) of_node_put(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) ngd->id = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) ngd->pdev->dev.parent = parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) ngd->pdev->driver_override = QCOM_SLIM_NGD_DRV_NAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) ngd->pdev->dev.of_node = node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) ctrl->ngd = ngd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) platform_device_add(ngd->pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) ngd->base = ctrl->base + ngd->id * data->offset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) (ngd->id - 1) * data->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) static int qcom_slim_ngd_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) struct qcom_slim_ngd_ctrl *ctrl = dev_get_drvdata(dev->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) ctrl->ctrl.dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) platform_set_drvdata(pdev, ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) pm_runtime_use_autosuspend(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) pm_runtime_set_autosuspend_delay(dev, QCOM_SLIM_NGD_AUTOSUSPEND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) pm_runtime_set_suspended(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) pm_runtime_enable(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) pm_runtime_get_noresume(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) ret = qcom_slim_ngd_qmi_svc_event_init(ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) dev_err(&pdev->dev, "QMI service registration failed:%d", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) INIT_WORK(&ctrl->m_work, qcom_slim_ngd_master_worker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) ctrl->mwq = create_singlethread_workqueue("ngd_master");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) if (!ctrl->mwq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) dev_err(&pdev->dev, "Failed to start master worker\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) goto wq_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) wq_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) qcom_slim_ngd_qmi_svc_event_deinit(&ctrl->qmi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) if (ctrl->mwq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) destroy_workqueue(ctrl->mwq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) static int qcom_slim_ngd_ctrl_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) struct qcom_slim_ngd_ctrl *ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) if (!ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) dev_set_drvdata(dev, ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) ctrl->base = devm_ioremap_resource(dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) if (IS_ERR(ctrl->base))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) return PTR_ERR(ctrl->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) dev_err(&pdev->dev, "no slimbus IRQ resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) ret = devm_request_irq(dev, res->start, qcom_slim_ngd_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) IRQF_TRIGGER_HIGH, "slim-ngd", ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) dev_err(&pdev->dev, "request IRQ failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) ctrl->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) ctrl->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) ctrl->framer.superfreq =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) ctrl->framer.rootfreq / SLIM_CL_PER_SUPERFRAME_DIV8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) ctrl->ctrl.a_framer = &ctrl->framer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) ctrl->ctrl.clkgear = SLIM_MAX_CLK_GEAR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) ctrl->ctrl.get_laddr = qcom_slim_ngd_get_laddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) ctrl->ctrl.enable_stream = qcom_slim_ngd_enable_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) ctrl->ctrl.xfer_msg = qcom_slim_ngd_xfer_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) ctrl->ctrl.wakeup = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) ctrl->state = QCOM_SLIM_NGD_CTRL_DOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) spin_lock_init(&ctrl->tx_buf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) init_completion(&ctrl->reconf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) init_completion(&ctrl->qmi.qmi_comp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) platform_driver_register(&qcom_slim_ngd_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) return of_qcom_slim_ngd_register(dev, ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) static int qcom_slim_ngd_ctrl_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) platform_driver_unregister(&qcom_slim_ngd_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) static int qcom_slim_ngd_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) struct qcom_slim_ngd_ctrl *ctrl = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) pm_runtime_disable(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) qcom_slim_ngd_enable(ctrl, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) qcom_slim_ngd_exit_dma(ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) qcom_slim_ngd_qmi_svc_event_deinit(&ctrl->qmi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) if (ctrl->mwq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) destroy_workqueue(ctrl->mwq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) kfree(ctrl->ngd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) ctrl->ngd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) static int __maybe_unused qcom_slim_ngd_runtime_idle(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) struct qcom_slim_ngd_ctrl *ctrl = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) if (ctrl->state == QCOM_SLIM_NGD_CTRL_AWAKE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) ctrl->state = QCOM_SLIM_NGD_CTRL_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) pm_request_autosuspend(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) static int __maybe_unused qcom_slim_ngd_runtime_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) struct qcom_slim_ngd_ctrl *ctrl = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) qcom_slim_ngd_exit_dma(ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) if (!ctrl->qmi.handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) ret = qcom_slim_qmi_power_request(ctrl, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) if (ret && ret != -EBUSY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) dev_info(ctrl->dev, "slim resource not idle:%d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) if (!ret || ret == -ETIMEDOUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) ctrl->state = QCOM_SLIM_NGD_CTRL_ASLEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) static const struct dev_pm_ops qcom_slim_ngd_dev_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) pm_runtime_force_resume)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) SET_RUNTIME_PM_OPS(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) qcom_slim_ngd_runtime_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) qcom_slim_ngd_runtime_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) qcom_slim_ngd_runtime_idle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) static struct platform_driver qcom_slim_ngd_ctrl_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) .probe = qcom_slim_ngd_ctrl_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) .remove = qcom_slim_ngd_ctrl_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) .name = "qcom,slim-ngd-ctrl",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) .of_match_table = qcom_slim_ngd_dt_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) static struct platform_driver qcom_slim_ngd_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) .probe = qcom_slim_ngd_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) .remove = qcom_slim_ngd_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) .name = QCOM_SLIM_NGD_DRV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) .pm = &qcom_slim_ngd_dev_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) module_platform_driver(qcom_slim_ngd_ctrl_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) MODULE_DESCRIPTION("Qualcomm SLIMBus NGD controller");