// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
// Copyright (c) 2018, Linaro Limited
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/slimbus.h>
#include <linux/delay.h>
#include <linux/pm_runtime.h>
#include <linux/of.h>
#include <linux/io.h>
#include <linux/soc/qcom/qmi.h>
#include <net/sock.h>
#include "slimbus.h"
/* NGD (Non-ported Generic Device) registers */
#define NGD_CFG 0x0
#define NGD_CFG_ENABLE BIT(0)
#define NGD_CFG_RX_MSGQ_EN BIT(1)
#define NGD_CFG_TX_MSGQ_EN BIT(2)
#define NGD_STATUS 0x4
#define NGD_LADDR BIT(1)
#define NGD_RX_MSGQ_CFG 0x8
#define NGD_INT_EN 0x10
#define NGD_INT_RECFG_DONE BIT(24)
#define NGD_INT_TX_NACKED_2 BIT(25)
#define NGD_INT_MSG_BUF_CONTE BIT(26)
#define NGD_INT_MSG_TX_INVAL BIT(27)
#define NGD_INT_IE_VE_CHG BIT(28)
#define NGD_INT_DEV_ERR BIT(29)
#define NGD_INT_RX_MSG_RCVD BIT(30)
#define NGD_INT_TX_MSG_SENT BIT(31)
#define NGD_INT_STAT 0x14
#define NGD_INT_CLR 0x18
#define DEF_NGD_INT_MASK (NGD_INT_TX_NACKED_2 | NGD_INT_MSG_BUF_CONTE | \
NGD_INT_MSG_TX_INVAL | NGD_INT_IE_VE_CHG | \
NGD_INT_DEV_ERR | NGD_INT_TX_MSG_SENT | \
NGD_INT_RX_MSG_RCVD)
/* Slimbus QMI service */
#define SLIMBUS_QMI_SVC_ID 0x0301
#define SLIMBUS_QMI_SVC_V1 1
#define SLIMBUS_QMI_INS_ID 0
#define SLIMBUS_QMI_SELECT_INSTANCE_REQ_V01 0x0020
#define SLIMBUS_QMI_SELECT_INSTANCE_RESP_V01 0x0020
#define SLIMBUS_QMI_POWER_REQ_V01 0x0021
#define SLIMBUS_QMI_POWER_RESP_V01 0x0021
#define SLIMBUS_QMI_CHECK_FRAMER_STATUS_REQ 0x0022
#define SLIMBUS_QMI_CHECK_FRAMER_STATUS_RESP 0x0022
#define SLIMBUS_QMI_POWER_REQ_MAX_MSG_LEN 14
#define SLIMBUS_QMI_POWER_RESP_MAX_MSG_LEN 7
#define SLIMBUS_QMI_SELECT_INSTANCE_REQ_MAX_MSG_LEN 14
#define SLIMBUS_QMI_SELECT_INSTANCE_RESP_MAX_MSG_LEN 7
#define SLIMBUS_QMI_CHECK_FRAMER_STAT_RESP_MAX_MSG_LEN 7
/* QMI response timeout of 500ms */
#define SLIMBUS_QMI_RESP_TOUT 1000
/* User defined commands */
#define SLIM_USR_MC_GENERIC_ACK 0x25
#define SLIM_USR_MC_MASTER_CAPABILITY 0x0
#define SLIM_USR_MC_REPORT_SATELLITE 0x1
#define SLIM_USR_MC_ADDR_QUERY 0xD
#define SLIM_USR_MC_ADDR_REPLY 0xE
#define SLIM_USR_MC_DEFINE_CHAN 0x20
#define SLIM_USR_MC_DEF_ACT_CHAN 0x21
#define SLIM_USR_MC_CHAN_CTRL 0x23
#define SLIM_USR_MC_RECONFIG_NOW 0x24
#define SLIM_USR_MC_REQ_BW 0x28
#define SLIM_USR_MC_CONNECT_SRC 0x2C
#define SLIM_USR_MC_CONNECT_SINK 0x2D
#define SLIM_USR_MC_DISCONNECT_PORT 0x2E
#define SLIM_USR_MC_REPEAT_CHANGE_VALUE 0x0
#define QCOM_SLIM_NGD_AUTOSUSPEND MSEC_PER_SEC
#define SLIM_RX_MSGQ_TIMEOUT_VAL 0x10000
#define SLIM_LA_MGR 0xFF
#define SLIM_ROOT_FREQ 24576000
#define LADDR_RETRY 5
/* Per spec.max 40 bytes per received message */
#define SLIM_MSGQ_BUF_LEN 40
#define QCOM_SLIM_NGD_DESC_NUM 32
#define SLIM_MSG_ASM_FIRST_WORD(l, mt, mc, dt, ad) \
((l) | ((mt) << 5) | ((mc) << 8) | ((dt) << 15) | ((ad) << 16))
#define INIT_MX_RETRIES 10
#define DEF_RETRY_MS 10
#define SAT_MAGIC_LSB 0xD9
#define SAT_MAGIC_MSB 0xC5
#define SAT_MSG_VER 0x1
#define SAT_MSG_PROT 0x1
#define to_ngd(d) container_of(d, struct qcom_slim_ngd, dev)
struct ngd_reg_offset_data {
u32 offset, size;
};
static const struct ngd_reg_offset_data ngd_v1_5_offset_info = {
.offset = 0x1000,
.size = 0x1000,
};
enum qcom_slim_ngd_state {
QCOM_SLIM_NGD_CTRL_AWAKE,
QCOM_SLIM_NGD_CTRL_IDLE,
QCOM_SLIM_NGD_CTRL_ASLEEP,
QCOM_SLIM_NGD_CTRL_DOWN,
};
struct qcom_slim_ngd_qmi {
struct qmi_handle qmi;
struct sockaddr_qrtr svc_info;
struct qmi_handle svc_event_hdl;
struct qmi_response_type_v01 resp;
struct qmi_handle *handle;
struct completion qmi_comp