| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896 |
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/interrupt.h>
- #include <linux/slab.h>
- #include <mach/irqs.h>
- #include <linux/kallsyms.h>
- #include <linux/delay.h>
- #include <linux/wakelock.h>
- #include <ccci.h>
- #define FIRST_PENDING (1<<0)
- #define PENDING_50MS (1<<1)
- /* #define PENDING_100MS (1<<2) */
- #define PENDING_1500MS (1<<2)
- const struct logic_channel_static_info_t logic_ch_static_info_tab[] = {
- {CCCI_CONTROL_RX, 8, "ctl_rx", L_CH_MUST_RDY_FOR_BOOT},
- {CCCI_CONTROL_TX, 0, "ctl_tx",
- L_CH_ATTR_TX | L_CH_ATTR_PRVLG1 | L_CH_ATTR_PRVLG0 | L_CH_ATTR_PRVLG2},
- {CCCI_SYSTEM_RX, 16, "sys_rx", 0},
- {CCCI_SYSTEM_TX, 0, "sys_tx", L_CH_ATTR_TX},
- {CCCI_PCM_RX, 128, "audio_rx", 0},
- {CCCI_PCM_TX, 0, "audio_tx", L_CH_ATTR_TX},
- {CCCI_UART1_RX, 8, "meta_rx", L_CH_DROP_TOLERATED},
- {CCCI_UART1_RX_ACK, 0, "meta_rx_ack",
- L_CH_ATTR_TX | L_CH_ATTR_DUMMY_WRITE},
- {CCCI_UART1_TX, 0, "meta_tx", L_CH_ATTR_TX | L_CH_ATTR_DUMMY_WRITE},
- {CCCI_UART1_TX_ACK, 8, "meta_tx_ack", L_CH_DROP_TOLERATED},
- {CCCI_UART2_RX, 8, "muxd_rx", L_CH_DROP_TOLERATED},
- {CCCI_UART2_RX_ACK, 0, "muxd_rx_ack", L_CH_ATTR_TX},
- {CCCI_UART2_TX, 0, "muxd_tx", L_CH_ATTR_TX},
- {CCCI_UART2_TX_ACK, 8, "muxd_tx_ack", L_CH_DROP_TOLERATED},
- {CCCI_FS_RX, 16, "md_nvram_rx", 0},
- {CCCI_FS_TX, 0, "md_nvram_tx",
- L_CH_ATTR_TX | L_CH_ATTR_PRVLG1 | L_CH_ATTR_OPEN_CLEAR |
- L_CH_ATTR_PRVLG0 | L_CH_ATTR_PRVLG2},
- {CCCI_PMIC_RX, 0, "pmic_rx", 0},
- {CCCI_PMIC_TX, 0, "pmic_tx", L_CH_ATTR_TX},
- {CCCI_UEM_RX, 8, "uem_rx", 0},
- {CCCI_UEM_TX, 0, "uem_tx", L_CH_ATTR_TX},
- {CCCI_CCMNI1_RX, 8, "ccmni1_rx", L_CH_DROP_TOLERATED},
- {CCCI_CCMNI1_RX_ACK, 0, "ccmni1_rx_ack", L_CH_ATTR_TX},
- {CCCI_CCMNI1_TX, 0, "ccmni1_tx", L_CH_ATTR_TX},
- {CCCI_CCMNI1_TX_ACK, 8, "ccmni1_tx_ack", L_CH_DROP_TOLERATED},
- {CCCI_CCMNI2_RX, 8, "ccmni2_rx", L_CH_DROP_TOLERATED},
- {CCCI_CCMNI2_RX_ACK, 0, "ccmni2_rx_ack", L_CH_ATTR_TX},
- {CCCI_CCMNI2_TX, 0, "ccmni2_tx", L_CH_ATTR_TX},
- {CCCI_CCMNI2_TX_ACK, 8, "ccmni2_tx_ack", L_CH_DROP_TOLERATED},
- {CCCI_CCMNI3_RX, 8, "ccmni3_rx", L_CH_DROP_TOLERATED},
- {CCCI_CCMNI3_RX_ACK, 0, "ccmni3_rx_ack", L_CH_ATTR_TX},
- {CCCI_CCMNI3_TX, 0, "ccmni3_tx", L_CH_ATTR_TX},
- {CCCI_CCMNI3_TX_ACK, 8, "ccmni3_tx_ack", L_CH_DROP_TOLERATED},
- {CCCI_RPC_RX, 8, "rpc_rx", 0},
- {CCCI_RPC_TX, 0, "rpc_tx", L_CH_ATTR_TX | L_CH_ATTR_PRVLG1},
- {CCCI_IPC_RX, 8, "ipc_rx", 0},
- {CCCI_IPC_RX_ACK, 0, "ipc_rx_ack", L_CH_ATTR_TX},
- {CCCI_IPC_TX, 0, "ipc_tx", L_CH_ATTR_TX},
- {CCCI_IPC_TX_ACK, 8, "ipc_tx_ack", 0},
- {CCCI_IPC_UART_RX, 8, "ipc_uart_rx", L_CH_DROP_TOLERATED},
- {CCCI_IPC_UART_RX_ACK, 0, "ipc_uart_rx_ack", L_CH_ATTR_TX},
- {CCCI_IPC_UART_TX, 0, "ipc_uart_tx", L_CH_ATTR_TX},
- {CCCI_IPC_UART_TX_ACK, 8, "ipc_uart_tx_ack", L_CH_DROP_TOLERATED},
- {CCCI_MD_LOG_RX, 256, "md_log_rx", 0},
- {CCCI_MD_LOG_TX, 0, "md_log_tx",
- L_CH_ATTR_TX | L_CH_ATTR_PRVLG1 | L_CH_ATTR_PRVLG2},
- #ifdef CONFIG_MTK_ICUSB_SUPPORT
- {CCCI_ICUSB_RX, 8, "icusb_rx", L_CH_DROP_TOLERATED},
- {CCCI_ICUSB_RX_ACK, 0, "icusb_rx_ack", L_CH_ATTR_TX},
- {CCCI_ICUSB_TX, 0, "icusb_tx", L_CH_ATTR_TX},
- {CCCI_ICUSB_TX_ACK, 8, "icusb_tx_ack", L_CH_DROP_TOLERATED},
- #endif
- };
- #define MAX_LOGIC_CH_ID (sizeof(logic_ch_static_info_tab)/sizeof(struct logic_channel_static_info_t))
- static struct logic_dispatch_ctl_block_t *logic_dispatch_ctlb[MAX_MD_NUM];
- static unsigned char md_enabled[MAX_MD_NUM]; /* Boot up time will determine this */
- static unsigned char active_md[MAX_MD_NUM];
- static unsigned int max_md_sys;
- /****************************************************************************/
- /* update&get md sys info */
- /* */
- /****************************************************************************/
- void set_md_sys_max_num(unsigned int max_num)
- {
- max_md_sys = max_num;
- }
- void set_md_enable(int md_id, int en)
- {
- md_enabled[md_id] = en;
- }
- void update_active_md_sys_state(int md_id, int active)
- {
- if (md_enabled[md_id]) {
- active_md[md_id] = active;
- if (active) {
- /* CCCI_DBG_MSG(md_id, "cci", "enable modem intr\n"); */
- ccci_enable_md_intr(md_id);
- }
- } else {
- CCCI_MSG("md_sys%d is not enable\n", md_id);
- }
- }
- int get_md_wakeup_src(int md_id, char *buf, unsigned int len)
- {
- unsigned int i, rx, ch;
- struct ccif_msg_t data;
- unsigned int rx_ch[CCIF_STD_V1_MAX_CH_NUM][2] = {
- {-1, 0}, {-1, 0}, {-1, 0}, {-1, 0}, {-1, 0},
- {-1, 0}, {-1, 0}, {-1, 0}
- };
- char str[64];
- char log_buf[256] = "";
- int ret = 0;
- char *channel_name;
- struct ccif_t *ccif;
- int curr_str_len = 0;
- struct logic_dispatch_ctl_block_t *ctlb;
- ctlb = logic_dispatch_ctlb[md_id];
- ccif = ctlb->m_ccif;
- rx = ccif->ccif_get_rx_ch(ccif);
- if (rx == 0)
- return ret;
- for (i = 0; i < CCIF_STD_V1_MAX_CH_NUM; i++) {
- if (rx & (1 << i)) {
- ccif->ccif_read_phy_ch_data(ccif, i,
- (unsigned int *)&data);
- for (ch = 0; ch < i; ch++)
- if (data.channel == rx_ch[ch][0])
- break;
- rx_ch[ch][0] = data.channel;
- rx_ch[ch][1]++;
- }
- }
- for (i = 0; i < CCIF_STD_V1_MAX_CH_NUM; i++) {
- if (rx_ch[i][1]) {
- if ((rx_ch[i][0] >= 0)
- && (rx_ch[i][0] < MAX_LOGIC_CH_ID)) {
- channel_name =
- logic_ch_static_info_tab[rx_ch[i]
- [0]].m_ch_name;
- sprintf(str, "%s(%d,%d) ", channel_name,
- rx_ch[i][0], rx_ch[i][1]);
- } else
- sprintf(str, "%s(%d,%d) ", "unknown",
- rx_ch[i][0], rx_ch[i][1]);
- curr_str_len += strlen(str);
- if (curr_str_len < 255)
- strcat(log_buf, str);
- }
- }
- if (curr_str_len > 255) {
- CCCI_MSG
- ("[ccci/ctl] wakeup source buffer not enough(req:%d>255) for MD%d\n",
- curr_str_len, md_id + 1);
- }
- CCCI_MSG("[ccci/ctl] (%d)CCIF_MD%d wakeup source: %s\n", md_id + 1,
- md_id + 1, log_buf);
- return ret;
- }
- /****************************************************************************/
- /* logical channel handle function */
- /* */
- /****************************************************************************/
- int register_to_logic_ch(int md_id, int ch, void (*func) (void *), void *owner)
- {
- struct logic_channel_info_t *ch_info;
- int ret = 0;
- unsigned long flags;
- struct logic_dispatch_ctl_block_t *ctl_b;
- ctl_b = logic_dispatch_ctlb[md_id];
- ch_info = &(ctl_b->m_logic_ch_table[ch]);
- if ((ch_info->m_attrs & L_CH_ATTR_TX) && (func != NULL))
- return 0;
- spin_lock_irqsave(&ch_info->m_lock, flags);
- /* Check whether call back function has been registered */
- if (!ch_info->m_register) {
- ch_info->m_register = 1;
- ch_info->m_call_back = func;
- ch_info->m_owner = owner;
- } else {
- CCCI_MSG_INF(md_id, "cci",
- "%s fail: %s(ch%d) cb func has registered\n",
- __func__, ch_info->m_ch_name,
- ch_info->m_ch_id);
- ret = -CCCI_ERR_LOGIC_CH_HAS_REGISTERED;
- }
- spin_unlock_irqrestore(&ch_info->m_lock, flags);
- return ret;
- }
- int un_register_to_logic_ch(int md_id, int ch)
- {
- struct logic_channel_info_t *ch_info;
- unsigned long flags;
- struct logic_dispatch_ctl_block_t *ctl_b;
- if (unlikely(ch >= CCCI_MAX_CH_NUM)) {
- CCCI_MSG_INF(md_id, "cci", "%s fail: invalid logic ch%d\n",
- __func__, ch);
- return -CCCI_ERR_INVALID_LOGIC_CHANNEL_ID;
- }
- ctl_b = logic_dispatch_ctlb[md_id];
- ch_info = &(ctl_b->m_logic_ch_table[ch]);
- spin_lock_irqsave(&ch_info->m_lock, flags);
- if (ch_info->m_register == 0)
- CCCI_MSG_INF(md_id, "cci", "ch%d not registered yet\n", ch);
- ch_info->m_call_back = NULL;
- ch_info->m_owner = NULL;
- ch_info->m_register = 0;
- spin_unlock_irqrestore(&ch_info->m_lock, flags);
- return 0;
- }
- int get_logic_ch_data(struct logic_channel_info_t *ch_info, struct ccci_msg_t *msg)
- {
- if (unlikely(ch_info == NULL)) {
- CCCI_MSG("%s fail: get invalid ch info\n", __func__);
- return -CCCI_ERR_GET_NULL_POINTER;
- }
- if (unlikely(ch_info->m_attrs & L_CH_ATTR_TX)) {
- CCCI_MSG_INF(ch_info->m_md_id, "cci",
- "%s fail: %s(ch%d) is tx\n", __func__,
- ch_info->m_ch_name, msg->channel);
- return -CCCI_ERR_GET_RX_DATA_FROM_TX_CHANNEL;
- }
- /* check whether fifo is ready */
- if (unlikely(!ch_info->m_kfifo_ready)) {
- CCCI_MSG_INF(ch_info->m_md_id, "cci",
- "%s fail: %s(ch%d) kfifo not ready\n",
- __func__, ch_info->m_ch_name, msg->channel);
- return -CCCI_ERR_KFIFO_IS_NOT_READY;
- }
- /* Check fifo if has data */
- if (kfifo_is_empty(&ch_info->m_kfifo))
- return 0;
- /* Pop data */
- return kfifo_out(&ch_info->m_kfifo, msg, sizeof(struct ccif_msg_t));
- }
- int get_logic_ch_data_len(struct logic_channel_info_t *ch_info)
- {
- if (unlikely(ch_info == NULL)) {
- CCCI_MSG("%s get invalid ch info\n", __func__);
- return 0;
- }
- if (unlikely(ch_info->m_attrs & L_CH_ATTR_TX)) {
- CCCI_MSG_INF(ch_info->m_md_id, "cci",
- "%s fail: %s(ch%d) is tx\n", __func__,
- ch_info->m_ch_name, ch_info->m_ch_id);
- return 0;
- }
- /* check whether fifo is ready */
- if (unlikely(!ch_info->m_kfifo_ready)) {
- CCCI_MSG_INF(ch_info->m_md_id, "cci",
- "%s fail: %s(ch%d) kfifo not ready\n",
- __func__, ch_info->m_ch_name,
- ch_info->m_ch_id);
- return 0;
- }
- /* Check fifo data length */
- return kfifo_len(&ch_info->m_kfifo);
- }
- struct logic_channel_info_t *get_logic_ch_info(int md_id, int ch_id)
- {
- struct logic_channel_info_t *ch_info;
- struct logic_dispatch_ctl_block_t *ctl_block;
- if (unlikely(ch_id >= CCCI_MAX_CH_NUM)) {
- CCCI_MSG_INF(md_id, "cci", "%s fail: invalid logic ch%d\n",
- __func__, ch_id);
- return NULL;
- }
- ctl_block = logic_dispatch_ctlb[md_id];
- ch_info = &(ctl_block->m_logic_ch_table[ch_id]);
- return ch_info;
- }
- static int __logic_dispatch_push(struct ccif_msg_t *msg, void *ctl_b)
- {
- struct logic_channel_info_t *ch_info;
- int ret = 0;
- struct logic_dispatch_ctl_block_t *ctl_block =
- (struct logic_dispatch_ctl_block_t *) ctl_b;
- int md_id = ctl_block->m_md_id;
- int drop = 1;
- if (unlikely(msg->channel >= CCCI_MAX_CH_NUM)) {
- CCCI_MSG_INF(md_id, "cci", "%s get invalid logic ch id:%d\n",
- __func__, msg->channel);
- ret = -CCCI_ERR_INVALID_LOGIC_CHANNEL_ID;
- goto _out;
- }
- ch_info = &(ctl_block->m_logic_ch_table[msg->channel]);
- if (unlikely(ch_info->m_attrs & L_CH_ATTR_TX)) {
- CCCI_MSG_INF(md_id, "cci", "%s CH:%d %s is tx channel\n",
- __func__, msg->channel, ch_info->m_ch_name);
- ret = -CCCI_ERR_PUSH_RX_DATA_TO_TX_CHANNEL;
- goto _out;
- }
- /* check whether fifo is ready */
- if (!ch_info->m_kfifo_ready) {
- CCCI_MSG_INF(md_id, "cci", "%s CH:%d %s's kfifo is not ready\n",
- __func__, msg->channel, ch_info->m_ch_name);
- ret = -CCCI_ERR_KFIFO_IS_NOT_READY;
- goto _out;
- }
- /* Check fifo free space */
- if (kfifo_is_full(&ch_info->m_kfifo)) {
- if (ch_info->m_attrs & L_CH_DROP_TOLERATED) {
- CCCI_CTL_MSG(md_id,
- "Drop (%08X %08X %02d %08X) is tolerated\n",
- msg->data[0], msg->data[1], msg->channel,
- msg->reserved);
- ret = sizeof(struct ccif_msg_t);
- } else {
- /* message should NOT be droped */
- CCCI_DBG_MSG(md_id, "cci",
- "kfifo full: ch:%s size:%d (%08X %08X %02d %08X)\n",
- ch_info->m_ch_name,
- kfifo_size(&ch_info->m_kfifo),
- msg->data[0], msg->data[1], msg->channel,
- msg->reserved);
- /* disalbe CCIF interrupt here???? */
- ret = 0; /* Fix this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
- }
- goto _out;
- }
- /* Push data */
- ret = kfifo_in(&ch_info->m_kfifo, msg, sizeof(struct ccif_msg_t));
- WARN_ON(ret != sizeof(struct ccif_msg_t));
- ctl_block->m_has_pending_data = 1;
- drop = 0;
- _out:
- add_logic_layer_record(md_id, (struct ccci_msg_t *) msg, drop);
- return ret;
- }
- static void __logic_layer_tasklet(unsigned long data)
- {
- struct logic_dispatch_ctl_block_t *logic_ctlb =
- (struct logic_dispatch_ctl_block_t *) data;
- struct logic_channel_info_t *ch_info;
- int i = 0;
- logic_ctlb->m_running = 1;
- while (logic_ctlb->m_has_pending_data) {
- logic_ctlb->m_has_pending_data = 0;
- for (i = 0; i < CCCI_MAX_CH_NUM; i++) {
- ch_info = &logic_ctlb->m_logic_ch_table[i];
- if (!ch_info->m_kfifo_ready)
- continue;
- if (!kfifo_is_empty(&ch_info->m_kfifo)) {
- /* Note here, register call back should using spinlock_irqsave */
- spin_lock(&ch_info->m_lock);
- /* Has data to process */
- if (ch_info->m_call_back != NULL) {
- /* 1.Check if this channel is active
- has call back means this channel is active */
- ch_info->m_call_back(ch_info);
- } else if (ch_info->m_attrs &
- L_CH_MUST_RDY_FOR_BOOT) {
- /* 2.Important channel not ready, show waring message */
- CCCI_DBG_MSG(ch_info->m_md_id, "cci",
- "Has pending msg for ch:%d\n",
- ch_info->m_ch_id);
- }
- spin_unlock(&ch_info->m_lock);
- }
- }
- }
- logic_ctlb->m_running = 0;
- /* wake_lock_timeout(&logic_ctlb->m_wakeup_wake_lock, 3*HZ/2); */
- }
- static void __let_logic_dispatch_tasklet_run(void *ctl_b)
- {
- struct logic_dispatch_ctl_block_t *ctl_block =
- (struct logic_dispatch_ctl_block_t *) ctl_b;
- tasklet_schedule(&ctl_block->m_dispatch_tasklet);
- }
- void freeze_logic_layer_tx(int md_id)
- {
- struct logic_dispatch_ctl_block_t *ctl_b;
- ctl_b = logic_dispatch_ctlb[md_id];
- ctl_b->m_freezed = 1;
- }
- void freeze_all_logic_layer(int md_id)
- {
- struct logic_dispatch_ctl_block_t *ctl_b;
- struct ccif_t *ccif;
- ctl_b = logic_dispatch_ctlb[md_id];
- ccif = ctl_b->m_ccif;
- ccif->ccif_dis_intr(ccif);
- ctl_b->m_freezed = 1;
- }
- int logic_layer_reset(int md_id)
- {
- struct logic_dispatch_ctl_block_t *ctl_b;
- struct ccif_t *ccif;
- u64 ref_jiffies = get_jiffies_64();
- int i;
- ctl_b = logic_dispatch_ctlb[md_id];
- ccif = ctl_b->m_ccif;
- /* Check whether there is on-going isr/tasklet */
- while ((CCIF_TOP_HALF_RUNNING & ccif->m_status) || ctl_b->m_running
- || ctl_b->m_has_pending_data) {
- if ((get_jiffies_64() - ref_jiffies) > 2 * HZ) {
- CCCI_MSG_INF(ctl_b->m_md_id, "cci",
- "%s wait isr/tasklet more than 2 seconds\n",
- __func__);
- break;
- }
- }
- /* isr/tasklet done, then reset ccif and logic channel */
- ccif->ccif_reset(ccif);
- for (i = 0; i < CCCI_MAX_CH_NUM; i++) {
- if (ctl_b->m_logic_ch_table[i].m_kfifo_ready)
- kfifo_reset(&(ctl_b->m_logic_ch_table[i].m_kfifo));
- }
- ctl_b->m_has_pending_data = 0;
- ctl_b->m_freezed = 0;
- ctl_b->m_running = 0;
- /* ctl_b->m_privilege = MD_BOOT_STAGE_0; */
- ctl_b->m_status_flag = 0;
- return 0;
- }
- /****************************************************************************/
- /* logical channel handle function */
- /* */
- /****************************************************************************/
- int bind_to_low_layer_notify(int md_id, void (*isr_func)(int),
- void (*send_func)(int, unsigned int))
- {
- struct logic_dispatch_ctl_block_t *ctl_b;
- struct ccif_t *ccif;
- int ret = 0;
- ctl_b = logic_dispatch_ctlb[md_id];
- /* Check whether call back function has been registered */
- if (NULL != ctl_b->m_send_notify_cb) {
- ret = -CCCI_ERR_MD_CB_HAS_REGISTER;
- return ret;
- }
- ctl_b->m_send_notify_cb = send_func;
- if (isr_func) {
- ccif = ctl_b->m_ccif;
- ret = ccif->register_isr_notify_func(ccif, isr_func);
- }
- return ret;
- }
- /* Support function for ccci char/tty/ccmni/fs/rpc/ipc/... */
- int ccci_message_send(int md_id, struct ccci_msg_t *msg, int retry_en)
- {
- struct logic_dispatch_ctl_block_t *ctl_b;
- struct ccif_t *ccif;
- int ret = 0;
- int args = 0;
- int drop = 0;
- unsigned long flags;
- int need_notify = 0;
- int md_stage = 0;
- ctl_b = logic_dispatch_ctlb[md_id];
- ccif = ctl_b->m_ccif;
- if (unlikely(ctl_b->m_freezed)) {
- CCCI_MSG_INF(md_id, "cci", "%s fail: ccci is freezed\n",
- __func__);
- ret = -CCCI_ERR_MD_NOT_READY;
- goto out;
- }
- if (unlikely(msg->channel >= CCCI_MAX_CH_NUM)) {
- if (msg->channel == CCCI_FORCE_ASSERT_CH) {
- ret =
- ccif->ccif_write_phy_ch_data(ccif,
- (unsigned int *)msg,
- retry_en);
- goto out;
- } else {
- CCCI_MSG_INF(md_id, "cci",
- "%s fail: invalid logic ch(%d)\n",
- __func__, msg->channel);
- ret = -CCCI_ERR_INVALID_LOGIC_CHANNEL_ID;
- goto out;
- }
- }
- md_stage = get_curr_md_state(md_id);
- if (unlikely(md_stage == MD_BOOT_STAGE_0)) { /* PRIVILEGE 0 <-- */
- /* At ccci privilege mode, only privilege channel can send data to modem */
- if (ctl_b->
- m_logic_ch_table[msg->channel].m_attrs & L_CH_ATTR_PRVLG0) {
- ret =
- ccif->ccif_write_phy_ch_data(ccif,
- (unsigned int *)msg,
- retry_en);
- } else {
- ret = -ENODEV;
- }
- } else if (unlikely(md_stage == MD_BOOT_STAGE_1)) { /* PRIVILEGE 1 <-- */
- if (ctl_b->
- m_logic_ch_table[msg->channel].m_attrs & L_CH_ATTR_PRVLG1) {
- ret =
- ccif->ccif_write_phy_ch_data(ccif,
- (unsigned int *)msg,
- retry_en);
- } else {
- ret = -ENODEV;
- }
- } else if (unlikely(md_stage == MD_BOOT_STAGE_EXCEPTION)) { /* PRIVILEGE 2 <-- */
- if (ctl_b->
- m_logic_ch_table[msg->channel].m_attrs & L_CH_ATTR_PRVLG2) {
- ret =
- ccif->ccif_write_phy_ch_data(ccif,
- (unsigned int *)msg,
- retry_en);
- } else if (ctl_b->
- m_logic_ch_table[msg->
- channel].m_attrs &
- L_CH_ATTR_DUMMY_WRITE) {
- ret = sizeof(struct ccci_msg_t); /* Dummy write here, MD using polling */
- } else {
- ret = -ETXTBSY;
- }
- } else {
- ret =
- ccif->ccif_write_phy_ch_data(ccif, (unsigned int *)msg,
- retry_en);
- }
- out:
- spin_lock_irqsave(&ctl_b->m_lock, flags);
- if (ret == -CCCI_ERR_CCIF_NO_PHYSICAL_CHANNEL) {
- drop = 1;
- if ((get_debug_mode_flag() & (DBG_FLAG_JTAG | DBG_FLAG_DEBUG))
- == 0) {
- need_notify = 1;
- if ((ctl_b->m_status_flag & FIRST_PENDING) == 0) {
- ctl_b->m_status_flag |= FIRST_PENDING;
- ctl_b->m_last_send_ref_jiffies = get_jiffies_64(); /* Update jiffies; */
- } else {
- if (((get_jiffies_64() -
- ctl_b->m_last_send_ref_jiffies) > 5)
- && ((ctl_b->m_status_flag & PENDING_50MS) == 0)) { /* 50ms */
- /* Dump EE memory */
- args = 1;
- ctl_b->m_status_flag |= PENDING_50MS;
- } else if ((get_jiffies_64() - ctl_b->m_last_send_ref_jiffies) > 150) { /* 1500ms */
- /* Trigger EE */
- args = 2;
- /* ctl_b->m_status_flag |= PENDING_100MS; */
- ctl_b->m_status_flag |= PENDING_1500MS;
- }
- }
- }
- } else {
- ctl_b->m_status_flag = 0;
- }
- spin_unlock_irqrestore(&ctl_b->m_lock, flags);
- if ((NULL != ctl_b->m_send_notify_cb) && need_notify)
- ctl_b->m_send_notify_cb(md_id, args);
- add_logic_layer_record(md_id, msg, drop);
- return ret;
- }
- void ccci_disable_md_intr(int md_id)
- {
- struct ccif_t *ccif_obj;
- ccif_obj = logic_dispatch_ctlb[md_id]->m_ccif;
- ccif_obj->ccif_dis_intr(ccif_obj);
- }
- void ccci_enable_md_intr(int md_id)
- {
- struct ccif_t *ccif_obj;
- ccif_obj = logic_dispatch_ctlb[md_id]->m_ccif;
- ccif_obj->ccif_en_intr(ccif_obj);
- }
- void ccci_hal_reset(int md_id)
- {
- struct ccif_t *ccif_obj;
- ccif_obj = logic_dispatch_ctlb[md_id]->m_ccif;
- ccif_obj->ccif_reset(ccif_obj);
- }
- void ccci_hal_irq_register(int md_id)
- {
- struct ccif_t *ccif_obj;
- ccif_obj = logic_dispatch_ctlb[md_id]->m_ccif;
- ccif_obj->ccif_register_intr(ccif_obj);
- }
- int ccci_write_runtime_data(int md_id, unsigned char buf[], int len)
- {
- struct ccif_t *ccif_obj;
- int tmp;
- tmp = (int)buf;
- if ((tmp & (~0x3)) != tmp)
- return -CCCI_ERR_START_ADDR_NOT_4BYTES_ALIGN;
- if ((len & (~0x3)) != len)
- return -CCCI_ERR_NOT_DIVISIBLE_BY_4;
- ccif_obj = logic_dispatch_ctlb[md_id]->m_ccif;
- return ccif_obj->ccif_write_runtime_data(ccif_obj, (unsigned int *)buf,
- len >> 2);
- }
- void ccci_dump_logic_layer_info(int md_id, unsigned int buf[], int len)
- {
- struct ccif_t *ccif;
- struct logic_dispatch_ctl_block_t *ctl_b;
- ctl_b = logic_dispatch_ctlb[md_id];
- if (ctl_b != NULL) {
- /* 1. Dump CCIF Info */
- ccif = ctl_b->m_ccif;
- ccif->ccif_dump_reg(ccif, buf, len);
- /* 2. Dump logic layer info */
- dump_logical_layer_tx_rx_histroy(md_id);
- }
- }
- void ccci_dump_hw_reg_val(int md_id, unsigned int buf[], int len)
- {
- struct ccif_t *ccif;
- struct logic_dispatch_ctl_block_t *ctl_b;
- ctl_b = logic_dispatch_ctlb[md_id];
- if (ctl_b != NULL) {
- /* 1. Dump CCIF Info */
- ccif = ctl_b->m_ccif;
- ccif->ccif_dump_reg(ccif, buf, len);
- }
- }
- /****************************************************************************/
- /* ccci logical layer initial */
- /* */
- /****************************************************************************/
- int ccci_logic_ctlb_init(int md_id)
- {
- int ret = 0;
- struct ccif_t *ccif;
- struct logic_channel_info_t *ch_info;
- int ch_id, ch_attr, i;
- struct logic_dispatch_ctl_block_t *ctl_b;
- struct ccif_hw_info_t ccif_hw_inf;
- CCCI_FUNC_ENTRY(md_id);
- /* Channel number check */
- if ((sizeof(logic_ch_static_info_tab) /
- sizeof(struct logic_channel_static_info_t)) != CCCI_MAX_CH_NUM) {
- CCCI_MSG_INF(md_id, "cci",
- "%s: channel max number mis-match fail\n",
- __func__);
- return -CCCI_ERR_CHANNEL_NUM_MIS_MATCH;
- }
- /* Allocate ctl block memory */
- ctl_b = (struct logic_dispatch_ctl_block_t *)
- kzalloc(sizeof(struct logic_dispatch_ctl_block_t), GFP_KERNEL);
- if (ctl_b == NULL) {
- CCCI_MSG_INF(md_id, "cci",
- "%s: alloc memory fail for logic_dispatch_ctlb\n",
- __func__);
- return -CCCI_ERR_ALLOCATE_MEMORY_FAIL;
- }
- logic_dispatch_ctlb[md_id] = ctl_b;
- /* Get CCIF HW info */
- if (get_ccif_hw_info(md_id, &ccif_hw_inf) < 0) {
- CCCI_MSG_INF(md_id, "cci", "%s: get ccif%d hw info fail\n",
- __func__, md_id + 1);
- ret = -CCCI_ERR_CCIF_GET_HW_INFO_FAIL;
- goto _ccif_instance_create_fail;
- }
- /* Create ccif instance */
- ccif = ccif_create_instance(&ccif_hw_inf, ctl_b, md_id);
- if (ccif == NULL) {
- CCCI_MSG_INF(md_id, "cci", "%s: create ccif instance fail\n",
- __func__);
- ret = -CCCI_ERR_CREATE_CCIF_INSTANCE_FAIL;
- goto _ccif_instance_create_fail;
- }
- ccif->ccif_init(ccif);
- ctl_b->m_ccif = ccif;
- /* Initialize logic channel and its kfifo */
- /* Step1, set all runtime channel id to CCCI_INVALID_CH_ID means default state */
- /* So, even if static channel table is out of order, we can make sure logic_dispatch_ctlb's channel */
- /* table is in order */
- for (i = 0; i < CCCI_MAX_CH_NUM; i++) {
- ch_info = &ctl_b->m_logic_ch_table[i];
- ch_info->m_ch_id = CCCI_INVALID_CH_ID;
- }
- /* Step2, set all runtime channel info according to static channel info, make it in order */
- for (i = 0; i < CCCI_MAX_CH_NUM; i++) {
- ch_id = logic_ch_static_info_tab[i].m_ch_id;
- ch_info = &ctl_b->m_logic_ch_table[ch_id];
- if (ch_info->m_ch_id != CCCI_INVALID_CH_ID) {
- CCCI_MSG_INF(md_id, "cci",
- "[Error]%s: ch%d has registered\n",
- __func__, ch_id);
- ret = -CCCI_ERR_REPEAT_CHANNEL_ID;
- goto _ccif_logic_channel_init_fail;
- } else {
- ch_info->m_ch_id = ch_id;
- ch_info->m_attrs = logic_ch_static_info_tab[i].m_attrs;
- ch_info->m_ch_name =
- logic_ch_static_info_tab[i].m_ch_name;
- ch_info->m_call_back = NULL;
- if (logic_ch_static_info_tab[i].m_kfifo_size) {
- if (0 !=
- kfifo_alloc(&ch_info->m_kfifo,
- sizeof(struct ccif_msg_t) *
- logic_ch_static_info_tab
- [i].m_kfifo_size, GFP_KERNEL)) {
- CCCI_MSG_INF(md_id, "cci",
- "%s: alloc kfifo fail for %s(ch%d)\n",
- __func__,
- ch_info->m_ch_name, ch_id);
- ch_info->m_kfifo_ready = 0;
- ret = CCCI_ERR_ALLOCATE_MEMORY_FAIL;
- goto _ccif_logic_channel_init_fail;
- } else {
- ch_info->m_kfifo_ready = 1;
- ch_info->m_md_id = md_id;
- }
- } else {
- ch_info->m_kfifo_ready = 0;
- }
- spin_lock_init(&ch_info->m_lock);
- }
- /* initial channel recording info */
- if (logic_ch_static_info_tab[i].m_attrs & L_CH_ATTR_TX)
- ch_attr = CCCI_LOG_TX;
- else
- ch_attr = CCCI_LOG_RX;
- statistics_init_ch_dir(md_id, ch_id, ch_attr,
- ch_info->m_ch_name);
- }
- /* Init logic_dispatch_ctlb */
- tasklet_init(&ctl_b->m_dispatch_tasklet, __logic_layer_tasklet,
- (unsigned long)ctl_b);
- ctl_b->m_has_pending_data = 0;
- ctl_b->m_freezed = 0;
- ctl_b->m_running = 0;
- /* ctl_b->m_privilege = MD_BOOT_STAGE_0; */
- ctl_b->m_md_id = md_id;
- snprintf(ctl_b->m_wakelock_name, sizeof(ctl_b->m_wakelock_name),
- "ccci%d_logic", (md_id + 1));
- wake_lock_init(&ctl_b->m_wakeup_wake_lock, WAKE_LOCK_SUSPEND,
- ctl_b->m_wakelock_name);
- ctl_b->m_send_notify_cb = NULL;
- spin_lock_init(&ctl_b->m_lock);
- /* Init CCIF now */
- ccif->register_call_back_func(ccif, __logic_dispatch_push,
- __let_logic_dispatch_tasklet_run);
- /* ccif->ccif_register_intr(ccif); */
- /* Init done */
- /* CCCI_DBG_MSG(md_id, "cci", "ccci_logic_ctlb_init success!\n"); */
- return ret;
- _ccif_logic_channel_init_fail:
- for (i = 0; i < CCCI_MAX_CH_NUM; i++) {
- ch_info = &ctl_b->m_logic_ch_table[i];
- if (ch_info->m_kfifo_ready) {
- kfifo_free(&ch_info->m_kfifo);
- ch_info->m_kfifo_ready = 0;
- }
- }
- _ccif_instance_create_fail:
- kfree(ctl_b);
- logic_dispatch_ctlb[md_id] = NULL;
- return ret;
- }
- void ccci_logic_ctlb_deinit(int md_id)
- {
- struct ccif_t *ccif;
- struct logic_channel_info_t *ch_info;
- int i;
- struct logic_dispatch_ctl_block_t *ctl_b;
- ctl_b = logic_dispatch_ctlb[md_id];
- if (ctl_b != NULL) {
- /* Step 1, freeze ccci */
- ctl_b->m_freezed = 1;
- /* Step 2, de-init ccif */
- ccif = logic_dispatch_ctlb[md_id]->m_ccif;
- ccif->ccif_de_init(ccif);
- /* Step 3, kill ccci dispatch tasklet */
- tasklet_kill(&ctl_b->m_dispatch_tasklet);
- /* Step 4, free kfifo memory */
- for (i = 0; i < CCCI_MAX_CH_NUM; i++) {
- ch_info = &ctl_b->m_logic_ch_table[i];
- if (ch_info->m_kfifo_ready) {
- kfifo_free(&ch_info->m_kfifo);
- ch_info->m_kfifo_ready = 0;
- }
- }
- /* Step 5, destroy wake lock */
- wake_lock_destroy(&ctl_b->m_wakeup_wake_lock);
- /* Step 6, free logic_dispatch_ctlb memory */
- kfree(ctl_b);
- logic_dispatch_ctlb[md_id] = NULL;
- }
- }
- int ccci_logic_layer_init(int md_id)
- {
- int ret = 0;
- ret = ccci_logic_ctlb_init(md_id);
- return ret;
- }
- void ccci_logic_layer_exit(int md_id)
- {
- ccci_logic_ctlb_deinit(md_id);
- }
|