aboutsummaryrefslogtreecommitdiff
path: root/drivers/misc/mediatek/eccci/mt6735/cldma_platform.c
blob: 44f595fe259c5fdbfaf2e0e5bddcf519dabb9c4e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <mach/mt_spm_sleep.h>
#include <mach/mt_gpio.h>
#include <mach/mt_clkbuf_ctl.h>

#if defined(CONFIG_MTK_LEGACY)
#include <mach/mt_clkmgr.h>
#else
#include <linux/clk.h>
#endif /*CONFIG_MTK_LEGACY*/

#include <mach/upmu_common.h>
#include <mach/upmu_sw.h>
#include <mach/upmu_hw.h>
#include <mach/mt_pbm.h>

#include "ccci_core.h"
#include "ccci_platform.h"
#include "modem_cldma.h"
#include "cldma_platform.h"
#include "cldma_reg.h"
#include "modem_reg_base.h"

#ifdef CONFIG_OF
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#endif
#include "ccci_core.h"

#if !defined(CONFIG_MTK_LEGACY)
static struct clk *clk_scp_sys_md1_main;
#endif

extern unsigned long infra_ao_base;
extern void ccci_mem_dump(int md_id, void *start_addr, int len);

#define TAG "mcd"
void md_cldma_hw_reset(struct ccci_modem *md)
{
    unsigned int reg_value;
    struct md_cd_ctrl *md_ctrl = (struct md_cd_ctrl *)md->private_data;
    CCCI_INF_MSG(md->index, TAG, "md_cldma_hw_reset:rst cldma\n");
    //reset cldma hw
    reg_value = ccci_read32(infra_ao_base,INFRA_RST0_REG);
    reg_value &=~(CLDMA_AO_RST_MASK|CLDMA_PD_RST_MASK);
    reg_value |=(CLDMA_AO_RST_MASK|CLDMA_PD_RST_MASK);
    ccci_write32(infra_ao_base,INFRA_RST0_REG,reg_value);
    CCCI_INF_MSG(md->index, TAG, "md_cldma_hw_reset:clear reset\n");
    //reset cldma clr
    reg_value = ccci_read32(infra_ao_base,INFRA_RST1_REG);
    reg_value &=~(CLDMA_AO_RST_MASK|CLDMA_PD_RST_MASK);
    reg_value |=(CLDMA_AO_RST_MASK|CLDMA_PD_RST_MASK);
    ccci_write32(infra_ao_base,INFRA_RST1_REG,reg_value);
    CCCI_INF_MSG(md->index, TAG, "md_cldma_hw_reset:done\n");
}

int md_cd_get_modem_hw_info(struct platform_device *dev_ptr, struct ccci_dev_cfg *dev_cfg, struct md_hw_info *hw_info)
{
    struct device_node *node=NULL;
    memset(dev_cfg, 0, sizeof(struct ccci_dev_cfg));
    memset(hw_info, 0, sizeof(struct md_hw_info));

    if(dev_ptr->dev.of_node == NULL) {
        CCCI_ERR_MSG(dev_cfg->index, TAG, "modem OF node NULL\n");
        return -1;
    }

    of_property_read_u32(dev_ptr->dev.of_node, "cell-index", &dev_cfg->index);
    CCCI_INF_MSG(dev_cfg->index, TAG, "modem hw info get idx:%d\n", dev_cfg->index);
    if(!get_modem_is_enabled(dev_cfg->index)) {
        CCCI_ERR_MSG(dev_cfg->index, TAG, "modem %d not enable, exit\n", dev_cfg->index + 1);
        return -1;
    }

    switch(dev_cfg->index) {
    case 0: //MD_SYS1
        of_property_read_u32(dev_ptr->dev.of_node, "cldma,major", &dev_cfg->major);
        of_property_read_u32(dev_ptr->dev.of_node, "cldma,minor_base", &dev_cfg->minor_base);
        of_property_read_u32(dev_ptr->dev.of_node, "cldma,capability", &dev_cfg->capability);

        hw_info->cldma_ap_ao_base = of_iomap(dev_ptr->dev.of_node, 0);
        hw_info->cldma_md_ao_base = of_iomap(dev_ptr->dev.of_node, 1);
        hw_info->cldma_ap_pdn_base = of_iomap(dev_ptr->dev.of_node, 2);
        hw_info->cldma_md_pdn_base = of_iomap(dev_ptr->dev.of_node, 3);
        hw_info->ap_ccif_base = of_iomap(dev_ptr->dev.of_node, 4);        
        hw_info->md_ccif_base = of_iomap(dev_ptr->dev.of_node, 5);
        hw_info->cldma_irq_id = irq_of_parse_and_map(dev_ptr->dev.of_node, 0);
        hw_info->ap_ccif_irq_id = irq_of_parse_and_map(dev_ptr->dev.of_node, 1);
        hw_info->md_wdt_irq_id = irq_of_parse_and_map(dev_ptr->dev.of_node, 2);

        // Device tree using none flag to register irq, sensitivity has set at "irq_of_parse_and_map"
        hw_info->cldma_irq_flags = IRQF_TRIGGER_NONE;
        hw_info->ap_ccif_irq_flags = IRQF_TRIGGER_NONE;
        hw_info->md_wdt_irq_flags = IRQF_TRIGGER_NONE;
        hw_info->ap2md_bus_timeout_irq_flags = IRQF_TRIGGER_NONE;

        hw_info->sram_size = CCIF_SRAM_SIZE;
        hw_info->md_rgu_base = MD_RGU_BASE;
        hw_info->md_boot_slave_Vector = MD_BOOT_VECTOR;
        hw_info->md_boot_slave_Key = MD_BOOT_VECTOR_KEY;
        hw_info->md_boot_slave_En = MD_BOOT_VECTOR_EN;
#if !defined(CONFIG_MTK_LEGACY)
        clk_scp_sys_md1_main = devm_clk_get(&dev_ptr->dev,"scp-sys-md1-main");
        if(IS_ERR(clk_scp_sys_md1_main)){
            CCCI_ERR_MSG(dev_cfg->index, TAG, "modem %d get scp-sys-md1-main failed\n", dev_cfg->index + 1);
            return -1;
        }
#endif
        break;
    default:
        return -1;
    }

    CCCI_INF_MSG(dev_cfg->index, TAG, "modem cldma of node get dev_major:%d\n", dev_cfg->major);
    CCCI_INF_MSG(dev_cfg->index, TAG, "modem cldma of node get minor_base:%d\n", dev_cfg->minor_base);
    CCCI_INF_MSG(dev_cfg->index, TAG, "modem cldma of node get capability:%d\n", dev_cfg->capability);
    CCCI_INF_MSG(dev_cfg->index, TAG, "ap_cldma: ao_base=0x%p, pdn_base=0x%p\n", (void*)hw_info->cldma_ap_ao_base,(void*)hw_info->cldma_ap_pdn_base);
    CCCI_INF_MSG(dev_cfg->index, TAG, "md_cldma: ao_base=0x%p, pdn_base=0x%p\n",(void*) hw_info->cldma_md_ao_base,(void*) hw_info->cldma_md_pdn_base);

    CCCI_INF_MSG(dev_cfg->index, TAG, "ap_ccif_base:0x%p, md_ccif_base:0x%p\n",(void*) hw_info->ap_ccif_base,(void*) hw_info->md_ccif_base);
    CCCI_INF_MSG(dev_cfg->index, TAG, "cldma_irq_id:%d\n", hw_info->cldma_irq_id);
    CCCI_INF_MSG(dev_cfg->index, TAG, "ccif_irq_id:%d\n", hw_info->ap_ccif_irq_id);
    CCCI_INF_MSG(dev_cfg->index, TAG, "md_wdt_irq_id:%d\n", hw_info->md_wdt_irq_id);

    return 0;
}

int md_cd_io_remap_md_side_register(struct ccci_modem *md)
{
	struct md_cd_ctrl *md_ctrl = (struct md_cd_ctrl *)md->private_data;
	md_ctrl->cldma_ap_pdn_base = (void __iomem *)(md_ctrl->hw_info->cldma_ap_pdn_base);
    md_ctrl->cldma_ap_ao_base =  (void __iomem *)(md_ctrl->hw_info->cldma_ap_ao_base);
	md_ctrl->cldma_md_pdn_base = (void __iomem *)(md_ctrl->hw_info->cldma_md_pdn_base);
    md_ctrl->cldma_md_ao_base = (void __iomem *)(md_ctrl->hw_info->cldma_md_ao_base);
	md_ctrl->md_boot_slave_Vector = ioremap_nocache(md_ctrl->hw_info->md_boot_slave_Vector, 0x4);
	md_ctrl->md_boot_slave_Key = ioremap_nocache(md_ctrl->hw_info->md_boot_slave_Key, 0x4);
	md_ctrl->md_boot_slave_En = ioremap_nocache(md_ctrl->hw_info->md_boot_slave_En, 0x4);
	md_ctrl->md_rgu_base = ioremap_nocache(md_ctrl->hw_info->md_rgu_base, 0x40);
	md_ctrl->md_global_con0 = ioremap_nocache(MD_GLOBAL_CON0, 0x4);

	md_ctrl->md_bus_status = ioremap_nocache(MD_BUS_STATUS_BASE, MD_BUS_STATUS_LENGTH);
	md_ctrl->md_pc_monitor = ioremap_nocache(MD_PC_MONITOR_BASE, MD_PC_MONITOR_LENGTH);
	md_ctrl->md_topsm_status = ioremap_nocache(MD_TOPSM_STATUS_BASE, MD_TOPSM_STATUS_LENGTH);
	md_ctrl->md_ost_status = ioremap_nocache(MD_OST_STATUS_BASE, MD_OST_STATUS_LENGTH);
	md_ctrl->md_pll = ioremap_nocache(MD_PLL_BASE, MD_PLL_LENGTH);
#ifdef MD_PEER_WAKEUP
	md_ctrl->md_peer_wakeup = ioremap_nocache(MD_PEER_WAKEUP, 0x4);
#endif
	return 0;
}
void md_cd_lock_cldma_clock_src(int locked)
{
	//spm_ap_mdsrc_req(locked);
}
void md_cd_lock_modem_clock_src(int locked)
{
	spm_ap_mdsrc_req(locked);
}

void md_cd_dump_debug_register(struct ccci_modem *md)
{
	struct md_cd_ctrl *md_ctrl = (struct md_cd_ctrl *)md->private_data;
	unsigned int reg_value;
    md_cd_lock_modem_clock_src(1);
	CCCI_INF_MSG(md->index, TAG, "Dump MD Bus status %x\n", MD_BUS_STATUS_BASE);
	ccci_mem_dump(md->index,md_ctrl->md_bus_status, MD_BUS_STATUS_LENGTH);
	CCCI_INF_MSG(md->index, TAG, "Dump MD PC monitor %x\n", MD_PC_MONITOR_BASE);
	// stop MD PCMon
	reg_value = ccci_read32(md_ctrl->md_pc_monitor,0); 
	reg_value &= ~(0x1<<21);
	ccci_write32(md_ctrl->md_pc_monitor, 0, reg_value); // clear bit[21]
	ccci_write32((md_ctrl->md_pc_monitor+4), 0, 0x80000000); // stop MD PCMon
	ccci_mem_dump(md->index, md_ctrl->md_pc_monitor, MD_PC_MONITOR_LENGTH);
	ccci_write32(md_ctrl->md_pc_monitor+4, 0, 0x1); // restart MD PCMon
	CCCI_INF_MSG(md->index, TAG, "Dump MD TOPSM status %x\n", MD_TOPSM_STATUS_BASE);
	ccci_mem_dump(md->index, md_ctrl->md_topsm_status, MD_TOPSM_STATUS_LENGTH);
	CCCI_INF_MSG(md->index, TAG, "Dump MD OST status %x\n", MD_OST_STATUS_BASE);
	ccci_mem_dump(md->index, md_ctrl->md_ost_status, MD_OST_STATUS_LENGTH);
	CCCI_INF_MSG(md->index, TAG, "Dump MD PLL %x\n", MD_PLL_BASE);
	ccci_mem_dump(md->index, md_ctrl->md_pll, MD_PLL_LENGTH);
    md_cd_lock_modem_clock_src(0);
}

void md_cd_check_emi_state(struct ccci_modem *md, int polling)
{
}

int md_cd_power_on(struct ccci_modem *md)
{
    int ret = 0;
    unsigned int reg_value;
    struct md_cd_ctrl *md_ctrl = (struct md_cd_ctrl *)md->private_data;
    // turn on VLTE
#ifdef FEATURE_VLTE_SUPPORT
    mt_set_gpio_out(GPIO_LTE_VSRAM_EXT_POWER_EN_PIN,1);
    CCCI_INF_MSG(md->index, CORE, "md_cd_power_on:mt_set_gpio_out(GPIO_LTE_VSRAM_EXT_POWER_EN_PIN,1)\n");

    //if(!(mt6325_upmu_get_swcid()==PMIC6325_E1_CID_CODE ||
    //     mt6325_upmu_get_swcid()==PMIC6325_E2_CID_CODE))
    {
    CCCI_INF_MSG(md->index, CORE, "md_cd_power_on:set VLTE on,bit0,1\n");
    pmic_config_interface(0x04D6, 0x1, 0x1, 0); //bit[0] =>1'b1 
    udelay(200);
    /*
        *[Notes] move into md cmos flow, for hardwareissue, so disable on denlai.
        * bring up need confirm with MD DE & SPM 
        */
    //reg_value = ccci_read32(infra_ao_base,0x338); 
    //reg_value &= ~(0x40); //bit[6] =>1'b0
    //ccci_write32(infra_ao_base,0x338,reg_value);
    //CCCI_INF_MSG(md->index, CORE, "md_cd_power_on: set infra_misc VLTE bit(0x1000_0338)=0x%x, bit[6]=0x%x\n",ccci_read32(infra_ao_base,0x338),(ccci_read32(infra_ao_base,0x338)&0x40));
    }
#endif
#ifdef FEATURE_RF_CLK_BUF
    //config RFICx as BSI
    mutex_lock(&clk_buf_ctrl_lock); // fixme,clkbuf, ->down(&clk_buf_ctrl_lock_2);
    CCCI_INF_MSG(md->index, TAG, "clock buffer, BSI ignore mode\n"); 

    mt_set_gpio_mode(GPIO_RFIC0_BSI_CK,  GPIO_MODE_01); 
    mt_set_gpio_mode(GPIO_RFIC0_BSI_D0,  GPIO_MODE_01);
    mt_set_gpio_mode(GPIO_RFIC0_BSI_D1,  GPIO_MODE_01);
    mt_set_gpio_mode(GPIO_RFIC0_BSI_D2,  GPIO_MODE_01);
    mt_set_gpio_mode(GPIO_RFIC0_BSI_CS,  GPIO_MODE_01);
#endif
	// power on MD_INFRA and MODEM_TOP
    switch(md->index)
    {
        case MD_SYS1:

#if defined(CONFIG_MTK_LEGACY)
       	CCCI_INF_MSG(md->index, TAG, "Call start md_power_on()\n"); 
        ret = md_power_on(SYS_MD1);
        CCCI_INF_MSG(md->index, TAG, "Call end md_power_on() ret=%d\n",ret);
#else
        CCCI_INF_MSG(md->index, TAG, "Call start clk_prepare_enable()\n"); 
        clk_prepare_enable(clk_scp_sys_md1_main);
        CCCI_INF_MSG(md->index, TAG, "Call end clk_prepare_enable()\n");
#endif

        kicker_pbm_by_md(MD1,true);
        CCCI_INF_MSG(md->index, TAG, "Call end kicker_pbm_by_md(0,true)\n"); 
        break;
    }
#ifdef FEATURE_RF_CLK_BUF 
	mutex_unlock(&clk_buf_ctrl_lock); // fixme,clkbuf, ->delete
#endif
	if(ret)
		return ret;
	// disable MD WDT
	cldma_write32(md_ctrl->md_rgu_base, WDT_MD_MODE, WDT_MD_MODE_KEY);
	return 0;
}

int md_cd_bootup_cleanup(struct ccci_modem *md, int success)
{
	return 0;
}

int md_cd_let_md_go(struct ccci_modem *md)
{
	struct md_cd_ctrl *md_ctrl = (struct md_cd_ctrl *)md->private_data;
	if(MD_IN_DEBUG(md))
		return -1;
	CCCI_INF_MSG(md->index, TAG, "set MD boot slave\n"); 
	// set the start address to let modem to run
	cldma_write32(md_ctrl->md_boot_slave_Key, 0, 0x3567C766); // make boot vector programmable
	cldma_write32(md_ctrl->md_boot_slave_Vector, 0, 0x00000000); // after remap, MD ROM address is 0 from MD's view
	cldma_write32(md_ctrl->md_boot_slave_En, 0, 0xA3B66175); // make boot vector take effect
	return 0;
}

int md_cd_power_off(struct ccci_modem *md, unsigned int timeout)
{
    int ret = 0;
    unsigned int reg_value;
#ifdef FEATURE_RF_CLK_BUF    
    mutex_lock(&clk_buf_ctrl_lock); 
#endif
    // power off MD_INFRA and MODEM_TOP
    switch(md->index)
    {
        case MD_SYS1:
#if defined(CONFIG_MTK_LEGACY)
        ret = md_power_off(SYS_MD1, timeout);
#else
        clk_disable(clk_scp_sys_md1_main);
        #ifdef FEATURE_RF_CLK_BUF
        mutex_unlock(&clk_buf_ctrl_lock);
        #endif
        clk_unprepare(clk_scp_sys_md1_main); // cannot be called in mutex context
        #ifdef FEATURE_RF_CLK_BUF
        mutex_lock(&clk_buf_ctrl_lock);
        #endif
#endif
        kicker_pbm_by_md(MD1,false);
        CCCI_INF_MSG(md->index, TAG, "Call end kicker_pbm_by_md(0,false)\n"); 
        break;
    }
#ifdef FEATURE_RF_CLK_BUF
    // config RFICx as AP SPM control
    CCCI_INF_MSG(md->index, TAG, "clock buffer, AP SPM control mode\n"); 
    mt_set_gpio_mode(GPIO_RFIC0_BSI_CK,  GPIO_MODE_04); 
    mt_set_gpio_mode(GPIO_RFIC0_BSI_D0,  GPIO_MODE_04);
    mt_set_gpio_mode(GPIO_RFIC0_BSI_D1,  GPIO_MODE_04);
    mt_set_gpio_mode(GPIO_RFIC0_BSI_D2,  GPIO_MODE_04);
    mt_set_gpio_mode(GPIO_RFIC0_BSI_CS,  GPIO_MODE_04);
	mutex_unlock(&clk_buf_ctrl_lock);
#endif

#ifdef FEATURE_VLTE_SUPPORT
    // Turn off VLTE
    //if(!(mt6325_upmu_get_swcid()==PMIC6325_E1_CID_CODE ||
    //     mt6325_upmu_get_swcid()==PMIC6325_E2_CID_CODE))
    {    
    /*
        *[Notes] move into md cmos flow, for hardwareissue, so disable on denlai.
        * bring up need confirm with MD DE & SPM 
        */
    //reg_value = ccci_read32(infra_ao_base,0x338); 
    //reg_value &= ~(0x40); //bit[6] =>1'b0
    //reg_value |= 0x40;//bit[6] =>1'b1
    //ccci_write32(infra_ao_base,0x338,reg_value);
    //CCCI_INF_MSG(md->index, CORE, "md_cd_power_off: set SRCLKEN infra_misc(0x1000_0338)=0x%x, bit[6]=0x%x\n",ccci_read32(infra_ao_base,0x338),(ccci_read32(infra_ao_base,0x338)&0x40));
    
    CCCI_INF_MSG(md->index, CORE, "md_cd_power_off:set VLTE on,bit0=0\n");
    pmic_config_interface(0x04D6, 0x0, 0x1, 0); //bit[0] =>1'b0
    }
    mt_set_gpio_out(GPIO_LTE_VSRAM_EXT_POWER_EN_PIN,0);
    CCCI_INF_MSG(md->index, CORE, "md_cd_power_off:mt_set_gpio_out(GPIO_LTE_VSRAM_EXT_POWER_EN_PIN,0)\n");
#endif
    return ret;
}


void cldma_dump_register(struct ccci_modem *md)
{
    struct md_cd_ctrl *md_ctrl = (struct md_cd_ctrl *)md->private_data;
    printk("[CCCI%d-DUMP]dump AP CLDMA Tx pdn register, active=%x\n",md->index+1, md_ctrl->txq_active);
    ccci_mem_dump(md->index, md_ctrl->cldma_ap_pdn_base+CLDMA_AP_UL_START_ADDR_0, CLDMA_AP_UL_CHECKSUM_CHANNEL_ENABLE-CLDMA_AP_UL_START_ADDR_0+4);
    printk("[CCCI%d-DUMP]dump AP CLDMA Tx ao register, active=%x\n",md->index+1, md_ctrl->txq_active);
    ccci_mem_dump(md->index, md_ctrl->cldma_ap_ao_base+CLDMA_AP_UL_START_ADDR_BK_0, CLDMA_AP_UL_CURRENT_ADDR_BK_7-CLDMA_AP_UL_START_ADDR_BK_0+4);

    printk("[CCCI%d-DUMP]dump AP CLDMA Rx pdn register, active=%x\n",md->index+1, md_ctrl->rxq_active);
    ccci_mem_dump(md->index, md_ctrl->cldma_ap_pdn_base+CLDMA_AP_SO_ERROR, CLDMA_AP_SO_STOP_CMD-CLDMA_AP_SO_ERROR+4);

    printk("[CCCI%d-DUMP]dump AP CLDMA Rx ao register, active=%x\n",md->index+1, md_ctrl->rxq_active);
    ccci_mem_dump(md->index, md_ctrl->cldma_ap_ao_base+CLDMA_AP_SO_CFG, CLDMA_AP_DEBUG_ID_EN-CLDMA_AP_SO_CFG+4);

    printk("[CCCI%d-DUMP]dump AP CLDMA MISC pdn register\n",md->index+1);
    ccci_mem_dump(md->index, md_ctrl->cldma_ap_pdn_base+CLDMA_AP_L2TISAR0, CLDMA_AP_CLDMA_IP_BUSY-CLDMA_AP_L2TISAR0+4);

    printk("[CCCI%d-DUMP]dump AP CLDMA MISC ao register\n",md->index+1);
    ccci_mem_dump(md->index, md_ctrl->cldma_ap_ao_base+CLDMA_AP_L2RIMR0, CLDMA_AP_DUMMY-CLDMA_AP_L2RIMR0+4);
    
    printk("[CCCI%d-DUMP]dump MD CLDMA Tx pdn register, active=%x\n",md->index+1, md_ctrl->txq_active);
    ccci_mem_dump(md->index, md_ctrl->cldma_md_pdn_base+CLDMA_AP_UL_START_ADDR_0, CLDMA_AP_UL_CHECKSUM_CHANNEL_ENABLE-CLDMA_AP_UL_START_ADDR_0+4);
    printk("[CCCI%d-DUMP]dump MD CLDMA Tx ao register, active=%x\n",md->index+1, md_ctrl->txq_active);
    ccci_mem_dump(md->index, md_ctrl->cldma_md_ao_base+CLDMA_AP_UL_START_ADDR_BK_0, CLDMA_AP_UL_CURRENT_ADDR_BK_7-CLDMA_AP_UL_START_ADDR_BK_0+4);

    printk("[CCCI%d-DUMP]dump MD CLDMA Rx pdn register, active=%x\n",md->index+1, md_ctrl->rxq_active);
    ccci_mem_dump(md->index, md_ctrl->cldma_md_pdn_base+CLDMA_AP_SO_ERROR, CLDMA_AP_SO_STOP_CMD-CLDMA_AP_SO_ERROR+4);
    printk("[CCCI%d-DUMP]dump MD CLDMA Rx ao register, active=%x\n",md->index+1, md_ctrl->rxq_active);
    ccci_mem_dump(md->index, md_ctrl->cldma_md_ao_base+CLDMA_AP_SO_CFG, CLDMA_AP_DEBUG_ID_EN-CLDMA_AP_SO_CFG+4);

    printk("[CCCI%d-DUMP]dump MD CLDMA MISC pdn register\n",md->index+1);
    ccci_mem_dump(md->index, md_ctrl->cldma_md_pdn_base+CLDMA_AP_L2TISAR0, CLDMA_AP_CLDMA_IP_BUSY-CLDMA_AP_L2TISAR0+4);
    printk("[CCCI%d-DUMP]dump MD CLDMA MISC ao register\n",md->index+1);
    ccci_mem_dump(md->index, md_ctrl->cldma_md_ao_base+CLDMA_AP_L2RIMR0, CLDMA_AP_DUMMY-CLDMA_AP_L2RIMR0+4);

}

int ccci_modem_remove(struct platform_device *dev)
{
	return 0;
}

void ccci_modem_shutdown(struct platform_device *dev)
{
}

int ccci_modem_suspend(struct platform_device *dev, pm_message_t state)
{
    struct ccci_modem *md = (struct ccci_modem *)dev->dev.platform_data;
    struct md_cd_ctrl *md_ctrl = (struct md_cd_ctrl *)md->private_data;
    CCCI_INF_MSG(md->index, TAG, "ccci_modem_suspend\n");
    return 0;
}

int ccci_modem_resume(struct platform_device *dev)
{
    struct ccci_modem *md = (struct ccci_modem *)dev->dev.platform_data;
    struct md_cd_ctrl *md_ctrl = (struct md_cd_ctrl *)md->private_data;
    CCCI_INF_MSG(md->index, TAG, "ccci_modem_resume\n");
	  return 0;
}

int ccci_modem_pm_suspend(struct device *device)
{
    struct platform_device *pdev = to_platform_device(device);
    BUG_ON(pdev == NULL);

    return ccci_modem_suspend(pdev, PMSG_SUSPEND);
}

int ccci_modem_pm_resume(struct device *device)
{
    struct platform_device *pdev = to_platform_device(device);
    BUG_ON(pdev == NULL);

    return ccci_modem_resume(pdev);
}

int ccci_modem_pm_restore_noirq(struct device *device)
{
	struct ccci_modem *md = (struct ccci_modem *)device->platform_data;
    struct md_cd_ctrl *md_ctrl = (struct md_cd_ctrl *)md->private_data;

	// set flag for next md_start
	md->config.setting |= MD_SETTING_RELOAD;
	md->config.setting |= MD_SETTING_FIRST_BOOT;	
    // restore IRQ
#ifdef FEATURE_PM_IPO_H
    irq_set_irq_type(md_ctrl->cldma_irq_id, IRQF_TRIGGER_HIGH); 
    irq_set_irq_type(md_ctrl->md_wdt_irq_id, IRQF_TRIGGER_FALLING); 
#endif
    return 0;
}


void ccci_modem_restore_reg(struct ccci_modem *md)
{
	struct md_cd_ctrl *md_ctrl = (struct md_cd_ctrl *)md->private_data;
	int i;
	unsigned long flags;

  if(md->md_state == GATED||md->md_state == RESET||md->md_state == INVALID){
    CCCI_INF_MSG(md->index, TAG, "Resume no need reset cldma for md_state=%d\n",md->md_state);
    return;
  }    
	cldma_write32(md_ctrl->ap_ccif_base, APCCIF_CON, 0x01); // arbitration

	if(cldma_read32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_TQSAR(0)))
	{
		CCCI_INF_MSG(md->index, TAG, "Resume cldma pdn register: No need  ...\n");
	}
	else
	{
		CCCI_INF_MSG(md->index, TAG, "Resume cldma pdn register ...11\n");
    	spin_lock_irqsave(&md_ctrl->cldma_timeout_lock, flags);
    	cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_HPQR, 0x00);
        // set checksum
        switch (CHECKSUM_SIZE) {
        case 0:
            cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_UL_CHECKSUM_CHANNEL_ENABLE, 0);
            break;
        case 12:
            cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_UL_CHECKSUM_CHANNEL_ENABLE, CLDMA_BM_ALL_QUEUE);
            cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_UL_CFG, cldma_read32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_UL_CFG)&~0x10);
             break;
        case 16:
            cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_UL_CHECKSUM_CHANNEL_ENABLE, CLDMA_BM_ALL_QUEUE);
            cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_UL_CFG, cldma_read32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_UL_CFG)|0x10);
            break;
        }
        // set start address
        for(i=0; i<QUEUE_LEN(md_ctrl->txq); i++) {
    		if(cldma_read32(md_ctrl->cldma_ap_ao_base, CLDMA_AP_TQCPBAK(md_ctrl->txq[i].index)) == 0){
    			CCCI_INF_MSG(md->index, TAG, "Resume CH(%d) current bak:== 0\n", i);
    			cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_TQSAR(md_ctrl->txq[i].index), md_ctrl->txq[i].tr_done->gpd_addr);
    			cldma_write32(md_ctrl->cldma_ap_ao_base, CLDMA_AP_TQSABAK(md_ctrl->txq[i].index), md_ctrl->txq[i].tr_done->gpd_addr);
    		}
    		else{
    			cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_TQSAR(md_ctrl->txq[i].index), cldma_read32(md_ctrl->cldma_ap_ao_base, CLDMA_AP_TQCPBAK(md_ctrl->txq[i].index)));
    			cldma_write32(md_ctrl->cldma_ap_ao_base, CLDMA_AP_TQSABAK(md_ctrl->txq[i].index), cldma_read32(md_ctrl->cldma_ap_ao_base, CLDMA_AP_TQCPBAK(md_ctrl->txq[i].index)));
    		}
        }
        wmb();
        // start all Tx and Rx queues
        cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_UL_START_CMD, CLDMA_BM_ALL_QUEUE);
        cldma_read32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_UL_START_CMD); // dummy read
        md_ctrl->txq_active |= CLDMA_BM_ALL_QUEUE;
        //cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_SO_START_CMD, CLDMA_BM_ALL_QUEUE);
        //cldma_read32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_SO_START_CMD); // dummy read
        //md_ctrl->rxq_active |= CLDMA_BM_ALL_QUEUE;
        // enable L2 DONE and ERROR interrupts
        cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_L2TIMCR0, CLDMA_BM_INT_DONE|CLDMA_BM_INT_ERROR);
        // enable all L3 interrupts
        cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_L3TIMCR0, CLDMA_BM_INT_ALL);
        cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_L3TIMCR1, CLDMA_BM_INT_ALL);
        cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_L3RIMCR0, CLDMA_BM_INT_ALL);
        cldma_write32(md_ctrl->cldma_ap_pdn_base, CLDMA_AP_L3RIMCR1, CLDMA_BM_INT_ALL);
        spin_unlock_irqrestore(&md_ctrl->cldma_timeout_lock, flags);
        CCCI_INF_MSG(md->index, TAG, "Resume cldma pdn register done\n");
    }
}


int ccci_modem_syssuspend(void)
{
CCCI_INF_MSG(0, TAG, "ccci_modem_syssuspend\n");
    return 0;
}

int ccci_modem_sysresume(void)
{
    CCCI_INF_MSG(0, TAG, "ccci_modem_sysresume\n");
    struct ccci_modem *md;
    md = ccci_get_modem_by_id(0);
    if(md!=NULL){
        ccci_modem_restore_reg(md);
    }
    return 0;
}