Squashed backup commit (no shallow-clone history issues) of xiaomi-mt6833-dev/kernel_xiaomi_mt6833 (lineage-23.2 branch, upstream commit 9eece662e) plus all fixes applied to get everpal_defconfig building clean against a modern (GCC 15.2.0) toolchain -- see the previous commit message on the lineage-23.2 branch (also in this repo history is not available here since this is a squashed snapshot; full incremental history lives in the local DL380 checkout and the upstream GitHub remote). Upstream: https://github.com/xiaomi-mt6833-dev/kernel_xiaomi_mt6833 (lineage-23.2)
283 lines
7.3 KiB
C
283 lines
7.3 KiB
C
/*
|
|
* Copyright (C) 2016 MediaTek Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
* See http://www.gnu.org/licenses/gpl-2.0.html for more details.
|
|
*/
|
|
|
|
#ifndef __MODEM_CCIF_H__
|
|
#define __MODEM_CCIF_H__
|
|
|
|
#include <linux/pm_wakeup.h>
|
|
#include <linux/dmapool.h>
|
|
#include <linux/atomic.h>
|
|
#include <mt-plat/mtk_ccci_common.h>
|
|
#include "ccci_config.h"
|
|
#include "ccci_ringbuf.h"
|
|
#include "ccci_core.h"
|
|
#include "ccci_modem.h"
|
|
#include "ccci_hif_internal.h"
|
|
|
|
#if (MD_GENERATION >= 6295)
|
|
#define QUEUE_NUM 16
|
|
#else
|
|
#define QUEUE_NUM 8
|
|
#endif
|
|
|
|
/* speciall for user: ccci_fsd data[0] */
|
|
#define CCCI_FS_AP_CCCI_WAKEUP (0x40000000)
|
|
#define CCCI_FS_REQ_SEND_AGAIN 0x80000000
|
|
|
|
/*#define FLOW_CTRL_ENABLE*/
|
|
#define FLOW_CTRL_HEAD 0x464C4F57 /*FLOW*/
|
|
#define FLOW_CTRL_TAIL 0x4354524C /*CTRL*/
|
|
#define FLOW_CTRL_THRESHOLD 3
|
|
|
|
#define CCIF_TRAFFIC_MONITOR_INTERVAL 10
|
|
|
|
#define RX_BUGDET 16
|
|
#define NET_RX_QUEUE_MASK 0x4
|
|
|
|
struct ccif_flow_control {
|
|
unsigned int head_magic;
|
|
unsigned int ap_busy_queue;
|
|
unsigned int md_busy_queue;
|
|
unsigned int tail_magic;
|
|
};
|
|
|
|
struct ccif_sram_layout {
|
|
struct ccci_header dl_header;
|
|
struct md_query_ap_feature md_rt_data;
|
|
struct ccci_header up_header;
|
|
struct ap_query_md_feature ap_rt_data;
|
|
};
|
|
|
|
enum ringbuf_id {
|
|
RB_NORMAL,
|
|
RB_EXP,
|
|
RB_MAX,
|
|
};
|
|
|
|
struct md_ccif_queue {
|
|
enum DIRECTION dir;
|
|
unsigned char index;
|
|
unsigned char hif_id;
|
|
unsigned char resume_cnt;
|
|
unsigned char debug_id;
|
|
unsigned char wakeup;
|
|
atomic_t rx_on_going;
|
|
int budget;
|
|
unsigned int ccif_ch;
|
|
struct ccci_modem *modem;
|
|
struct ccci_port *napi_port;
|
|
struct ccci_ringbuf *ringbuf; /*ringbuf in use*/
|
|
struct ccci_ringbuf *ringbuf_bak[RB_MAX];
|
|
spinlock_t rx_lock; /* lock for the counter, only for rx */
|
|
spinlock_t tx_lock; /* lock for the counter, only for Tx */
|
|
wait_queue_head_t req_wq; /* only for Tx */
|
|
struct work_struct qwork;
|
|
struct workqueue_struct *worker;
|
|
};
|
|
|
|
struct md_ccif_ctrl {
|
|
struct md_ccif_queue txq[QUEUE_NUM];
|
|
struct md_ccif_queue rxq[QUEUE_NUM];
|
|
unsigned int total_smem_size;
|
|
atomic_t reset_on_going;
|
|
|
|
unsigned long channel_id; /* CCIF channel */
|
|
unsigned int ccif_irq_id;
|
|
atomic_t ccif_ap_data_enabled;
|
|
unsigned int sram_size;
|
|
struct ccif_sram_layout *ccif_sram_layout;
|
|
struct work_struct ccif_sram_work;
|
|
struct timer_list bus_timeout_timer;
|
|
void __iomem *ccif_ap_base;
|
|
void __iomem *ccif_md_base;
|
|
atomic_t wakeup_src;
|
|
unsigned int wakeup_count;
|
|
|
|
struct work_struct wdt_work;
|
|
struct ccif_flow_control *flow_ctrl;
|
|
|
|
unsigned char md_id;
|
|
unsigned char hif_id;
|
|
struct ccci_hif_traffic traffic_info;
|
|
struct timer_list traffic_monitor;
|
|
|
|
unsigned short heart_beat_counter;
|
|
struct ccci_hif_ops *ops;
|
|
};
|
|
|
|
static inline void ccif_set_busy_queue(struct md_ccif_ctrl *md_ctrl,
|
|
unsigned int qno)
|
|
{
|
|
if (!md_ctrl->flow_ctrl)
|
|
return;
|
|
/* set busy bit */
|
|
md_ctrl->flow_ctrl->ap_busy_queue |= (0x1 << qno);
|
|
}
|
|
|
|
static inline void ccif_clear_busy_queue(struct md_ccif_ctrl *md_ctrl,
|
|
unsigned int qno)
|
|
{
|
|
if (!md_ctrl->flow_ctrl)
|
|
return;
|
|
/* clear busy bit */
|
|
md_ctrl->flow_ctrl->ap_busy_queue &= ~(0x1 << qno);
|
|
}
|
|
|
|
static inline void ccif_reset_busy_queue(struct md_ccif_ctrl *md_ctrl)
|
|
{
|
|
#ifdef FLOW_CTRL_ENABLE
|
|
if (!md_ctrl->flow_ctrl)
|
|
return;
|
|
/* reset busy bit */
|
|
md_ctrl->flow_ctrl->head_magic = FLOW_CTRL_HEAD;
|
|
md_ctrl->flow_ctrl->ap_busy_queue = 0x0;
|
|
md_ctrl->flow_ctrl->md_busy_queue = 0x0;
|
|
/* Notice: tail will be set by modem
|
|
* if it supports flow control
|
|
*/
|
|
#endif
|
|
}
|
|
|
|
static inline int ccif_is_md_queue_busy(struct md_ccif_ctrl *md_ctrl,
|
|
unsigned int qno)
|
|
{
|
|
/*caller should handle error*/
|
|
if (!md_ctrl->flow_ctrl)
|
|
return -1;
|
|
if (unlikely(md_ctrl->flow_ctrl->head_magic != FLOW_CTRL_HEAD ||
|
|
md_ctrl->flow_ctrl->tail_magic != FLOW_CTRL_TAIL))
|
|
return -1;
|
|
|
|
return (md_ctrl->flow_ctrl->md_busy_queue & (0x1 << qno));
|
|
}
|
|
|
|
static inline int ccif_is_md_flow_ctrl_supported(struct md_ccif_ctrl *md_ctrl)
|
|
{
|
|
if (!md_ctrl->flow_ctrl)
|
|
return -1;
|
|
/*both head and tail are right. make sure MD support flow control too*/
|
|
if (likely(md_ctrl->flow_ctrl->head_magic == FLOW_CTRL_HEAD &&
|
|
md_ctrl->flow_ctrl->tail_magic == FLOW_CTRL_TAIL))
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
static inline void ccif_wake_up_tx_queue(struct md_ccif_ctrl *md_ctrl,
|
|
unsigned int qno)
|
|
{
|
|
struct md_ccif_queue *queue = &md_ctrl->txq[qno];
|
|
|
|
ccif_clear_busy_queue(md_ctrl, qno);
|
|
queue->wakeup = 1;
|
|
wake_up(&queue->req_wq);
|
|
}
|
|
|
|
int ccci_ccif_hif_init(unsigned char hif_id, unsigned char md_id);
|
|
|
|
static inline int ccci_ccif_hif_send_skb(unsigned char hif_id, int tx_qno,
|
|
struct sk_buff *skb, int from_pool, int blocking)
|
|
{
|
|
struct md_ccif_ctrl *md_ctrl =
|
|
(struct md_ccif_ctrl *)ccci_hif_get_by_id(hif_id);
|
|
|
|
if (md_ctrl)
|
|
return md_ctrl->ops->send_skb(hif_id, tx_qno,
|
|
skb, from_pool, blocking);
|
|
else
|
|
return -1;
|
|
}
|
|
static inline int ccci_ccif_hif_write_room(unsigned char hif_id,
|
|
unsigned char qno)
|
|
{
|
|
struct md_ccif_ctrl *md_ctrl =
|
|
(struct md_ccif_ctrl *)ccci_hif_get_by_id(hif_id);
|
|
|
|
if (md_ctrl)
|
|
return md_ctrl->ops->write_room(hif_id, qno);
|
|
else
|
|
return -1;
|
|
|
|
}
|
|
static inline int ccci_ccif_hif_give_more(unsigned char hif_id, int rx_qno)
|
|
{
|
|
struct md_ccif_ctrl *md_ctrl =
|
|
(struct md_ccif_ctrl *)ccci_hif_get_by_id(hif_id);
|
|
|
|
if (md_ctrl)
|
|
return md_ctrl->ops->give_more(hif_id, rx_qno);
|
|
else
|
|
return -1;
|
|
}
|
|
static inline int ccci_ccif_hif_dump_status(unsigned int hif_id,
|
|
enum MODEM_DUMP_FLAG dump_flag, int length)
|
|
{
|
|
struct md_ccif_ctrl *md_ctrl =
|
|
(struct md_ccif_ctrl *)ccci_hif_get_by_id(hif_id);
|
|
|
|
if (md_ctrl)
|
|
return md_ctrl->ops->dump_status(hif_id,
|
|
dump_flag, length);
|
|
else
|
|
return -1;
|
|
|
|
}
|
|
|
|
static inline int ccci_ccif_hif_set_wakeup_src(unsigned char hif_id, int value)
|
|
{
|
|
struct md_ccif_ctrl *md_ctrl =
|
|
(struct md_ccif_ctrl *)ccci_hif_get_by_id(hif_id);
|
|
unsigned int ccif_rx_ch = 0;
|
|
|
|
if (md_ctrl) {
|
|
|
|
if (md_ctrl->ccif_ap_base)
|
|
ccif_rx_ch = ccif_read32(md_ctrl->ccif_ap_base,
|
|
APCCIF_RCHNUM);
|
|
CCCI_NORMAL_LOG(0, "WK", "CCIF RX bitmap:0x%x\r\n",
|
|
ccif_rx_ch);
|
|
#if (MD_GENERATION >= 6297)
|
|
if (ccif_rx_ch & AP_MD_CCB_WAKEUP)
|
|
mtk_ccci_ccb_info_peek();
|
|
#endif
|
|
return atomic_set(&md_ctrl->wakeup_src, value);
|
|
} else
|
|
return -1;
|
|
}
|
|
|
|
void *ccif_hif_fill_rt_header(unsigned char hif_id, int packet_size,
|
|
unsigned int tx_ch, unsigned int txqno);
|
|
void md_ccif_reset_queue(unsigned char hif_id, unsigned char for_start);
|
|
|
|
void ccif_polling_ready(unsigned char hif_id, int step);
|
|
|
|
void md_ccif_sram_reset(unsigned char hif_id);
|
|
int md_ccif_ring_buf_init(unsigned char hif_id);
|
|
void md_ccif_switch_ringbuf(unsigned char hif_id, enum ringbuf_id rb_id);
|
|
|
|
int md_ccif_send(unsigned char hif_id, int channel_id);
|
|
void ccif_set_irq_on_poweron(unsigned char hif_id);
|
|
void ccif_set_irq_on_poweroff(unsigned char hif_id);
|
|
/* always keep this in mind:
|
|
* what if there are more than 1 modems using CLDMA...
|
|
*/
|
|
#ifdef CONFIG_MTK_GIC_V3_EXT
|
|
extern void mt_irq_dump_status(int irq);
|
|
#endif
|
|
extern void mt_irq_set_sens(unsigned int irq, unsigned int sens);
|
|
extern void mt_irq_set_polarity(unsigned int irq, unsigned int polarity);
|
|
/* used for throttling feature - start */
|
|
extern unsigned long ccci_modem_boot_count[];
|
|
/* used for throttling feature - end */
|
|
#endif /* __MODEM_CCIF_H__ */
|