1 /*****************************************************************************
13 * MT6582 CCCI SYSTEM MESSAGE
19 ****************************************************************************/
21 #include <linux/sched.h>
22 #include <linux/kernel.h>
23 #include <linux/module.h>
24 #include <linux/device.h>
25 #include <linux/cdev.h>
26 #include <linux/kfifo.h>
27 #include <linux/spinlock.h>
28 #include <linux/interrupt.h>
29 #include <linux/delay.h>
30 #include <linux/uaccess.h>
31 #include <linux/timer.h>
32 #include <linux/delay.h>
33 #include <linux/semaphore.h>
35 #include "eemcs_kal.h"
36 #include "eemcs_ccci.h"
37 #include "eemcs_debug.h"
38 #include "eemcs_char.h"
39 #include "eemcs_file_ops.h"
40 #include "eemcs_sysmsg.h"
41 #include "mach/mtk_eemcs_helper.h"
42 #include "eemcs_state.h"
44 static spinlock_t sysmsg_fifo_lock
= __SPIN_LOCK_UNLOCKED(sysmsg_fifo_lock
);
45 static struct kfifo sysmsg_fifo
;
46 struct work_struct sysmsg_work
;
49 //#define __EEMCS_SYSMSG_IT__
50 #ifdef __EEMCS_SYSMSG_IT__
51 #define TEST_MSG_ID_MD2AP (0x113)
52 #define TEST_MSG_ID_AP2MD (0x107)
55 //------------For MD get Battery info from AP------------//
56 void send_battery_info(int md_id
)
59 unsigned int para
= 0;
60 unsigned int resv
= 0;
61 unsigned int msg_id
= EXT_MD_GET_BATTERY_INFO
;
63 resv
= eemcs_get_bat_info(para
);
64 ret
= eemcs_notify_md_by_sys_msg(md_id
, msg_id
, resv
);
65 DBGLOG(SMSG
, INF
, "send bat vol(%d) to md: %d", resv
, ret
);
69 int eemcs_md_get_battery_info(int md_id
, int data
)
71 DBGLOG(SMSG
,DBG
,"request to send battery voltage to md");
72 send_battery_info(md_id
);
75 //--------------end-------------------------//
77 //------------For MD send sim type msg to AP------------//
79 int enable_get_sim_type(int md_id
, unsigned int enable
)
82 unsigned int msg_id
= EXT_MD_SIM_TYPE
;
83 unsigned int resv
= enable
;
85 ret
= eemcs_notify_md_by_sys_msg(MD_SYS5
, msg_id
, resv
);
87 DBGLOG(SMSG
,INF
,"enable_get_sim_type(enable=%d): %d", resv
, ret
);
92 int sim_type
= 0xEEEEEEEE; //sim_type(MCC/MNC) send by MD wouldn't be 0xEEEEEEEE
93 int set_sim_type(int md_id
, int data
)
98 DBGLOG(SMSG
,INF
,"set_sim_type(type=0x%x): %d", sim_type
, ret
);
103 int get_sim_type(int md_id
, int *p_sim_type
)
105 *p_sim_type
= sim_type
;
106 if (sim_type
== 0xEEEEEEEE)
108 DBGLOG(SMSG
,ERR
,"get_sim_type fail: md not send sim type yet, type=0x%x", sim_type
);
111 DBGLOG(SMSG
,INF
,"get_sim_type: type=0x%x", sim_type
);
116 //--------------end-------------------------//
118 static void eemcs_sysmsg_work(struct work_struct
*work
)
120 //unsigned char *p_rdata;
122 CCCI_BUFF_T
*p_cccih
= NULL
;
125 DBGLOG(SMSG
, DBG
, "====> %s", FUNC_NAME
);
127 while(kfifo_out(&sysmsg_fifo
, &skb
, sizeof(unsigned int)))
129 p_cccih
= (CCCI_BUFF_T
*)skb
->data
;
130 DBGLOG(SMSG
, DBG
, "eemcs_sysmsg_work, msg: %08X, %08X, %08X, %08X\n", \
131 p_cccih
->data
[0], p_cccih
->data
[1], p_cccih
->channel
, p_cccih
->reserved
);
132 eemcs_exec_ccci_sys_call_back(md_id
, p_cccih
->data
[1], p_cccih
->reserved
);
135 DBGLOG(SMSG
, DBG
, "<==== %s", FUNC_NAME
);
138 static int send_eemcs_system_ch_msg(int md_id
, unsigned int msg_id
, unsigned int data
)
140 CCCI_BUFF_T
* ccci_header
;
141 struct sk_buff
*new_skb
;
142 unsigned int skb_len
= CCCI_SYSMSG_HEADER_ROOM
;
145 DBGLOG(SMSG
, DBG
, "send_eemcs_system_ch_msg");
147 if (check_device_state() != EEMCS_BOOTING_DONE
) {//modem not ready
148 DBGLOG(CHAR
, ERR
, "send sys msg(id=%d) fail when modem not ready", msg_id
);
152 //when alloc skb fail, not use __GFP_WAIT because this API may be used in interrupt context
153 while(NULL
== (new_skb
= dev_alloc_skb(skb_len
)))
155 DBGLOG(SMSG
, ERR
, "dev_alloc_skb fail");
158 /* reserve SDIO_H and CCCI header room */
159 #ifdef CCCI_SDIO_HEAD
160 skb_reserve(new_skb
, sizeof(SDIO_H
));
162 ccci_header
= (CCCI_BUFF_T
*)skb_put(new_skb
, sizeof(CCCI_BUFF_T
)) ;
165 ccci_header
->data
[0] = 0xFFFFFFFF;
166 ccci_header
->data
[1] = msg_id
;
167 ccci_header
->channel
= CH_SYS_TX
;
168 ccci_header
->reserved
= data
;
171 DBGLOG(SMSG
, DBG
, "send_sys_msg: 0x%08X, 0x%08X, 0x%02d, 0x%08X",
172 ccci_header
->data
[0],ccci_header
->data
[1] ,ccci_header
->channel
, ccci_header
->reserved
);
174 ret
= ccci_sysmsg_ch_write_desc_to_q(ccci_header
->channel
, new_skb
);
175 if(ret
!= KAL_SUCCESS
)
177 DBGLOG(SMSG
, ERR
, "send_sys_msg(id=%d, data=0x%x) fail: %d", msg_id
, ccci_header
->reserved
, ret
);
178 dev_kfree_skb(new_skb
);
180 DBGLOG(SMSG
, DBG
, "send_sys_msg(id=%d, data=0x%x) OK: %d", msg_id
, ccci_header
->reserved
, ret
);
185 // eemcs_sysmsg_rx_dispatch_cb: CCCI_SYSTEM_RX message dispatch call back function for MODEM
186 // @skb: pointer to a CCCI buffer
187 // @private_data: pointer to private data of CCCI_SYSTEM_RX
188 KAL_INT32
eemcs_sysmsg_rx_dispatch_cb(struct sk_buff
*skb
, KAL_UINT32 private_data
)
190 CCCI_BUFF_T
*p_cccih
= NULL
;
192 DBGLOG(SMSG
, DBG
, "====> %s", FUNC_NAME
);
195 p_cccih
= (CCCI_BUFF_T
*)skb
->data
;
196 DBGLOG(SMSG
, INF
, "sysmsg RX callback, msg: %08X, %08X, %02d, %08X\n", p_cccih
->data
[0], p_cccih
->data
[1], p_cccih
->channel
, p_cccih
->reserved
);
198 if (p_cccih
->channel
== CH_SYS_TX
){
199 DBGLOG(SMSG
, ERR
, "Wrong CH for recv");
203 if (kfifo_is_full(&sysmsg_fifo
))
205 DBGLOG(SMSG
, ERR
, "kfifo full and packet drop, msg: %08X, %08X, %02d, %08X\n", \
206 p_cccih
->data
[0], p_cccih
->data
[1], p_cccih
->channel
, p_cccih
->reserved
);
211 spin_lock_bh(&sysmsg_fifo_lock
);
212 //DBGLOG(SMSG, TRA, "ready to put skb into FIFO");
213 kfifo_in(&sysmsg_fifo
, &skb
, sizeof(unsigned int));
214 //DBGLOG(SMSG, TRA, "after put skb into FIFO");
215 spin_unlock_bh(&sysmsg_fifo_lock
);
216 DBGLOG(SMSG
, DBG
, "schedule sysmsg_work");
217 schedule_work(&sysmsg_work
);
222 DBGLOG(SMSG
, ERR
, "skb is NULL!");
226 DBGLOG(SMSG
, DBG
, "<==== %s", FUNC_NAME
);
230 #ifdef __EEMCS_SYSMSG_IT__
231 int eemcs_sysmsg_echo_test(int md_id
, int data
)
233 eemcs_notify_md_by_sys_msg(md_id
, TEST_MSG_ID_AP2MD
, data
);
238 int eemcs_sysmsg_mod_init(void)
242 DBGLOG(SMSG
, DBG
, "====> %s", FUNC_NAME
);
244 ret
= kfifo_alloc(&sysmsg_fifo
, sizeof(unsigned)*CCCI_SYSMSG_MAX_REQ_NUM
, GFP_KERNEL
);
247 DBGLOG(SMSG
, ERR
, "kfifo_alloc fail: %d", ret
);
251 //related channel registration.
253 KAL_ASSERT(ccci_ch_register((CCCI_CHANNEL_T
)CH_SYS_RX
, eemcs_sysmsg_rx_dispatch_cb
, 0) == KAL_SUCCESS
);
255 eemcs_register_sys_msg_notify_func(MD_SYS5
, send_eemcs_system_ch_msg
);
257 INIT_WORK(&sysmsg_work
, eemcs_sysmsg_work
);
259 #ifdef __EEMCS_SYSMSG_IT__
260 eemcs_register_ccci_sys_call_back(MD_SYS5
, TEST_MSG_ID_MD2AP
, eemcs_sysmsg_echo_test
);
263 //DBGLOG(SMSG, TRA, "register sys msg callback: md_get_battery_info");
264 eemcs_register_ccci_sys_call_back(MD_SYS5
, EXT_MD_GET_BATTERY_INFO
, eemcs_md_get_battery_info
); //EXT_MD_GET_BATTERY_INFO == MD_GET_BATTERY_INFO == 0x105
266 eemcs_register_ccci_sys_call_back(MD_SYS5
, EXT_MD_SIM_TYPE
, set_sim_type
);
268 DBGLOG(SMSG
, DBG
, "<==== %s", FUNC_NAME
);
273 void eemcs_sysmsg_exit(void)
275 DBGLOG(SMSG
, INF
, "====> %s", FUNC_NAME
);
276 kfifo_free(&sysmsg_fifo
);