/
exrom_tcpm_comm.c
2801 lines (2382 loc) · 82 KB
/
exrom_tcpm_comm.c
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
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
//--------------------------------------------------------------------------
// Refer Specification:
//
// TypeC1.1 : USB Type-C Specification Release 1.1.pdf
// TypeC1.2 : USB Type-C Specification Release 1.2.pdf
// TypeC_FT0.73: USB_Type_C_Functional_Test_Specification_2016_06_24.pdf
//
// TCPC1.0 : USB-Port Controller Specification R1.0 [21051020].pdf
//
// PD2 V1.1 : USB_PD_R2_0 V1.1 - 20150507.pdf
// PD2 V1.2 : USB_PD_R2_0 V1.2 -20160325.pdf
// PD2 V1.2 ECN: USB_PD_R2_0 V1.2 -20160325 - ECN clean markup 20160802.pdf
//
//--------------------------------------------------------------------------
#include "utility.h"
#include "exrom_jm.h"
//--------------------------------------------------------------------------
#if (JM_USB_PD_ENABLE)
//--------------------------------------------------------------------------
#pragma SAVE // save current optimization level
#pragma OPTIMIZE(9) // prevent common subroutine optimization
//--------------------------------------------------------------------------
#include "dp80390.h"
#include "global.h"
#include "constant.h"
#include "rs232.h"
#include "exrom_main.h"
#include "exrom_i2c.h"
#include "exrom_tcpm_comm.h"
#include "exrom_tcpm_bank.h"
#include "main.h"
#include "utility.h"
#include "register.h"
void usb_enter_lowest_power(void);
#define aUSB3_LTSSM_CTRL1 (*(UBYTE volatile xdata*)0x5082) // Link FSM Control1
// Sink Only ---------------------------------------------------------------
//TASKP xdata _PE_task;
TASKP xdata _PE_state;
TASKP xdata _msg_state;
unsigned char ErrorRecovery_Timer_Flag;
unsigned char xdata U8_temp;
unsigned short xdata U16_temp;
unsigned char xdata msg_Received;
unsigned char xdata msg_Transmit;
unsigned char xdata msg_trans_NG;
unsigned char xdata msg_Disc;
unsigned char xdata msg_trans_OK;
unsigned char xdata VBUS_Alarm_Hi;
unsigned char xdata VBUS_Alarm_Lo;
// Sink Only ---------------------------------------------------------------
// Protocol Layer TX
void tx_wait_for_message_request(void);
void tx_construct_vdm_message(void);
void tx_construct_message(void);
void tx_vdm_check_alert_or_receiving(void);
void tx_check_alert_or_receiving(void);
void tx_wait_for_phy_response(void);
void tx_hr_request_hard_reset(void);
void tx_hr_disable_tcpc_receiver(void);
void tx_hr_wait_for_phy_hard_reset_complete(void);
void tx_hr_wait_for_pe_hard_reset_complete(void);
// AC Adapter
void ac_unattached(void);
void ac_wait_adapter_coming(void);
void ac_wait_debounce_timeout(void);
void ac_ready(void);
void ac_wait_detached(void);
void ac_detached(void);
// Hard Disk Drive
void hd_clr_busy_wait_turn_on(void);
void hd_wait_turn_on(void);
void hd_wait_timeout(void);
void hd_turn_on_disk(void);
void hd_wait_usb_turn_on_hdd(void);
void hd_wait_hdd_start_finished(void);
void hd_wait_partner_accepted_hdd_starting_pdo(void);
void hd_wait_hdd_start_finished(void);
void hd_wait_partner_accepted_hdd_idle_pdo(void);
void hd_wait_partner_accepted_hdd_stop_pdo(void);
void hd_ready(void);
void hd_req_usb_turn_off_hdd(void);
void hd_wait_usb_turn_off_hdd(void);
void hd_usb_turn_off_hdd(void);
//
void init_tcpc(void);
void request_turn_on_disk(unsigned char dwcnt_100ms);
void request_turn_off_disk(void);
// AC adapter detached timer
#define read_ac_detached_timer_100ms() read_mcu_dwcnt_100ms_ac()
#define write_ac_detached_timer_100ms(value) write_mcu_dwcnt_100ms_ac(value)
// AC adapter debounce timer
#define read_ac_debounce_timer_100ms() read_mcu_dwcnt_100ms_ac()
#define write_ac_debounce_timer_100ms(value) write_mcu_dwcnt_100ms_ac(value)
// turn on/off hdd timer
#define read_turn_on_disk_timer_100ms() read_mcu_dwcnt_100ms_hd()
#define write_turn_on_disk_timer_100ms(value) write_mcu_dwcnt_100ms_hd(value)
//--------------------------------------------------------------------------
// table for initial tcpc
unsigned char xdata reg_tab_size;
const unsigned char code init_reg_tab[][2] =
{
{0x9B, 0X20}, // sleep mode to active mode
{RT1711P_REG_UNLOCK_PW1, 0X62},
{RT1711P_REG_UNLOCK_PW2, 0X86},
{RT1711P_REG_BMCIO_RXDZSEL0, 0X80}, //
{0X87, 0XDE},
{0X88, 0X5C},
{TCPC_REG_ROLE_CONTROL, 0X0A},
{TCPC_REG_FAULT_CONTROL, 0X84}, // disable OCP, enable OVP
{RT1711P_REG_TTCPC_FILTER, 0X05},
{RT1711P_REG_DRP_TOGGLE_CYCLE, 0X04},
{RT1711P_REG_DRP_DUTY_CTRL, 0X34}, // dcSRC.DRP[9:0]/1024, 30%=0x134, 70%=0x2CC
{RT1711P_REG_DRP_DUTY_CTRL+1, 0X01},
{RT1711P_REG_PHY_CTRL1, 0X31}, // bit7(ENRETRY_DISCARD)=0, assert discard during reply goodcrc
{RT1711P_REG_PHY_CTRL3, 0X70},
{TCPC_REG_RECEIVE_BYTE_COUNT, 0X00},
{TCPC_REG_ALERT_MASK, 0XFF},
{TCPC_REG_ALERT_MASK+1, 0X07}, // disable sink disconnect detect
{TCPC_REG_POWER_STATUS_MASK, 0X06},
{TCPC_REG_FAULT_STATUS_MASK, 0XFF},
{TCPC_REG_COMMAND, 0x33}, // enable vbus detect
{TCPC_REG_RECEIVE_DETECT, 0x00}, // disable receive detect
{TCPC_REG_POWER_CONTROL, 0x00}, // RT1711P Ver.D default is 0x18(Enable bleed discharge), disable AutoDischargeDisconnect
{TCPC_REG_VBUS_VOLTAGE_ALARM_HI_CFG, 0XFF},
{TCPC_REG_VBUS_VOLTAGE_ALARM_HI_CFG+1, 0X03},
{RT1711P_REG_PHY_CTRL4, 0XC0}, // tReceive_L, 0x0A50=2640, 2640/2.4MHz=1.1ms; 0x0960=2400, 2400/2.4MHz=1.0ms
{RT1711P_REG_PHY_CTRL4+1, 0X08}, // tReceive_H, 0x08C0 for Ver.E, 0x08C0=2240, 2240/2400=0.933ms
{0x9C, 0X80}, // enable chip reset if Alert pin 200ms timeout
{RT1711P_REG_DIS_SNK_VBUS_GP_EN, 0xAA}, // sink role gate control for AutoDischargeDisconnect
{RT1711P_REG_DIS_SRC_VBUS_GP_EN, 0xAA}, // source role gate control for AutoDischargeDisconnect
{RT1711P_REG_OCP_OVP_VBUS_GP_EN, 0x0A}, // gate control for OVP, OCP
{0XA5, 0X00}, // Set GPx as control NMOS
{0XAA, 0XC0}, // Enable charge pump for GPx
{RT1711P_REG_VBUS_OVPR_DISCHG, 0XAF}, // OVP = 20V (Max)
{RT1711P_REG_VBUS_OCPR, 0X29}, // 0CP = 5A (Max)
{0XAE, 0X06},
{RT1711P_REG_VDCLEVEL, 0XC5}, // VDC threshlod = 15v
};
// source fixed pdo, PD2 V1.1 p155
const unsigned char code src_fix_pdo_shift[]={ 0, 10, 20, 22, 25, 26, 27, 28, 29, 30};
const unsigned short code src_fix_pdo_mask[] ={0x3FF,0x3FF,0x03,0x07,0x01,0x01,0x01,0x01,0x01,0x03};
// request pdo, PD2 V1.1 p160
const unsigned char code req_pdo_shift[]={ 0, 10, 20, 24, 25, 26, 27, 28, 31};
const unsigned short code req_pdo_mask[] ={0x03FF,0x03FF,0x0F,0x01,0x01,0x01,0x01,0x07,0x01};
// sink fixed pdo, PD2 V1.1 p158
const unsigned char code snk_fix_pdo_shift[]={ 0, 10, 20, 25, 26, 27, 28, 29, 30};
const unsigned short code snk_fix_pdo_mask[] ={0x03FF,0x03FF,0x1F,0x01,0x01,0x01,0x01,0x01,0x03};
// source/sink variable or battery pdo, PD2 V1.1 p157
const unsigned char code var_bat_pdo_shift[]={ 0, 10, 20, 30};
const unsigned short code var_bat_pdo_mask[] ={0x3FF,0x3FF,0x3FF,0x03};
#if BIST_SUPPORT
// BIST header, PD2 V1.1 p165
const unsigned char code bist_header_shift[]={ 0, 16, 28};
const unsigned short code bist_header_mask[] ={0xFFFF,0x0FFF,0x0F};
#endif
const char* code msg_id2string[32] = {
// 0~15 is Control Message
"0000" , // 0
"Good" , // 1
"Goto" , // 2
"Acc" , // 3
"Rej" , // 4
"Pi" , // 5
"PS" , // 6
"G_Src_C" , // 7
"G_Snk_C" , // 8
"DR" , // 9
"PR" , // 10
"VCON" , // 11
"Wait" , // 12
"SRST" , // 13
"1110" , // 14
"1111" , // 15
// 16~31 stores Data Message
"0000" , // 16
"Src_C" , // 17
"Req" , // 18
"BIST" , // 19
"Snk_C" , // 20
"0101" , // 21
"0110" , // 22
"0111" , // 23
"1000" , // 24
"1001" , // 25
"1010" , // 26
"1011" , // 27
"1100" , // 28
"1101" , // 29
"1110" , // 30
"VDM" , // 31
};
//--------------------------------------------------------------------------
// local use
bit timeout;
bit GiveBackFlag;
// RT1711P Device ID
#define RT1711P_DEV_ID_B 0x2091
#define RT1711P_DEV_ID_D 0x2093
#define RT1711P_DEV_ID_E 0x2094
// XDATA Port Memory Map
#define MEM_ADDR_SIZE 0x0120
#define MEM_ADDR_PORTX 0x4500
#define MEM_ADDR_PORT0 (MEM_ADDR_PORTX + MEM_ADDR_SIZE)
#define MEM_ADDR_PORT1 (MEM_ADDR_PORT0 + MEM_ADDR_SIZE)
// port memory
unsigned char xdata port0_mem[MEM_ADDR_SIZE] _at_ MEM_ADDR_PORT0;
unsigned char xdata port1_mem[MEM_ADDR_SIZE] _at_ MEM_ADDR_PORT1;
// flag, allocate in 0~287
// Caution: every bytes shall be allocated by using _at_
unsigned char xdata msg_sent _at_ MEM_ADDR_PORTX + 0;
unsigned char xdata msg_failed _at_ MEM_ADDR_PORTX + 1;
unsigned char xdata msg_discarded _at_ MEM_ADDR_PORTX + 2;
unsigned char xdata reserved003 _at_ MEM_ADDR_PORTX + 3; // reserved
unsigned char xdata reserved004 _at_ MEM_ADDR_PORTX + 4; // reserved
unsigned char xdata hrst_sent _at_ MEM_ADDR_PORTX + 5;
unsigned char xdata vdm_pending _at_ MEM_ADDR_PORTX + 6;
unsigned char xdata pd_connected _at_ MEM_ADDR_PORTX + 7;
unsigned char xdata vbus_present _at_ MEM_ADDR_PORTX + 8;
unsigned char xdata vconn_present _at_ MEM_ADDR_PORTX + 9;
unsigned char xdata vsafe_5v _at_ MEM_ADDR_PORTX + 10;
unsigned char xdata vsafe_0v _at_ MEM_ADDR_PORTX + 11;
unsigned short xdata vbus_target_25mv _at_ MEM_ADDR_PORTX + 12; // 2 bytes
unsigned short xdata vbus_present_25mv _at_ MEM_ADDR_PORTX + 14; // 2 bytes
unsigned char xdata pe_hrst_completed _at_ MEM_ADDR_PORTX + 16;
unsigned char xdata explicit_contract _at_ MEM_ADDR_PORTX + 17;
unsigned char xdata PortPowerRole _at_ MEM_ADDR_PORTX + 18;
unsigned char xdata InitPowerRole _at_ MEM_ADDR_PORTX + 19;
unsigned char xdata PortDataRole _at_ MEM_ADDR_PORTX + 20;
unsigned char xdata InitDataRole _at_ MEM_ADDR_PORTX + 21;
unsigned char xdata cc1_state _at_ MEM_ADDR_PORTX + 22;
unsigned char xdata cc2_state _at_ MEM_ADDR_PORTX + 23;
unsigned char xdata cc_attached _at_ MEM_ADDR_PORTX + 24;
unsigned char xdata monitored_rd_cc _at_ MEM_ADDR_PORTX + 25;
unsigned char xdata monitored_ra_cc _at_ MEM_ADDR_PORTX + 26;
unsigned char xdata cable_connected _at_ MEM_ADDR_PORTX + 27;
unsigned char xdata cable_speed _at_ MEM_ADDR_PORTX + 28;
unsigned char xdata cable_current _at_ MEM_ADDR_PORTX + 29;
unsigned char xdata cable_ack _at_ MEM_ADDR_PORTX + 30;
unsigned char xdata supplied_vconn _at_ MEM_ADDR_PORTX + 31;
unsigned char xdata requested_obj_pos _at_ MEM_ADDR_PORTX + 32;
unsigned char xdata pwr_role_swapped _at_ MEM_ADDR_PORTX + 33;
unsigned char xdata valid_request _at_ MEM_ADDR_PORTX + 34;
unsigned char xdata src_pdo_count _at_ MEM_ADDR_PORTX + 35;
unsigned char xdata usb_comm_capable _at_ MEM_ADDR_PORTX + 36;
unsigned char xdata external_power _at_ MEM_ADDR_PORTX + 37;
unsigned char xdata enable_port _at_ MEM_ADDR_PORTX + 38;
unsigned char xdata vbus_tolerance_25mv _at_ MEM_ADDR_PORTX + 39;
// dpm flag
unsigned char xdata dpm_hard_reset_request _at_ MEM_ADDR_PORTX + 40;
unsigned char xdata dpm_new_power_request _at_ MEM_ADDR_PORTX + 41;
unsigned char xdata dpm_get_src_cap_request _at_ MEM_ADDR_PORTX + 42;
unsigned char xdata dpm_get_snk_cap_request _at_ MEM_ADDR_PORTX + 43;
unsigned char xdata msg_abort _at_ MEM_ADDR_PORTX + 44;
unsigned char xdata vbus_to_20v _at_ MEM_ADDR_PORTX + 45;
unsigned char xdata vbus_from_20v _at_ MEM_ADDR_PORTX + 46;
//
unsigned short xdata req_max_opr_cur_10ma _at_ MEM_ADDR_PORTX + 47; // 2 bytes
unsigned short xdata req_opr_cur_10ma _at_ MEM_ADDR_PORTX + 49; // 2 bytes
unsigned short xdata req_opr_vol_50mv _at_ MEM_ADDR_PORTX + 51; // 2 bytes
// bist
unsigned char xdata bist_mode _at_ MEM_ADDR_PORTX + 53;
// vdm
unsigned short xdata vdm_svid _at_ MEM_ADDR_PORTX + 54; // 2 bytes
unsigned char xdata vdm_type _at_ MEM_ADDR_PORTX + 56;
unsigned char xdata vdm_cmd_type _at_ MEM_ADDR_PORTX + 57;
unsigned char xdata vdm_command _at_ MEM_ADDR_PORTX + 58;
unsigned char xdata vdm_obj_pos _at_ MEM_ADDR_PORTX + 59;
// timer enable flag
unsigned char xdata EnableSinkWaitCapTimer _at_ MEM_ADDR_PORTX + 60;
unsigned char xdata EnablePSTransitionTimer _at_ MEM_ADDR_PORTX + 61;
unsigned char xdata EnableWaitSendTimer _at_ MEM_ADDR_PORTX + 62;
unsigned char xdata EnableNoResponseTimer _at_ MEM_ADDR_PORTX + 63;
unsigned char xdata EnableSenderResponseTimer _at_ MEM_ADDR_PORTX + 64;
// counter
unsigned char xdata HardResetCounter _at_ MEM_ADDR_PORTX + 65;
unsigned char xdata modify_sink_wait_cap _at_ MEM_ADDR_PORTX + 66;
unsigned char xdata CapsCounter _at_ MEM_ADDR_PORTX + 67;
unsigned char xdata DiscoverIdentityCounter _at_ MEM_ADDR_PORTX + 68;
unsigned char xdata reserved069 _at_ MEM_ADDR_PORTX + 69; // reserved
// Message ID variable
unsigned char xdata rx_stored_flag _at_ MEM_ADDR_PORTX + 70;
unsigned char xdata MessageIDCounter _at_ MEM_ADDR_PORTX + 71; // same name with spec
unsigned char xdata StoredMessageID _at_ MEM_ADDR_PORTX + 72; // same name with spec
unsigned char xdata cc_result _at_ MEM_ADDR_PORTX + 73;
unsigned char xdata cc_looking _at_ MEM_ADDR_PORTX + 74;
unsigned char xdata cc_state _at_ MEM_ADDR_PORTX + 75; // bit0~4 of CC_STATUS Register
unsigned char xdata dual_role_port _at_ MEM_ADDR_PORTX + 76;
unsigned char xdata wait_src_recover _at_ MEM_ADDR_PORTX + 77;
// Message Type, for quickly identify and reduce code size
unsigned char xdata tx_msg_type _at_ MEM_ADDR_PORTX + 78;
unsigned char xdata rx_msg_type _at_ MEM_ADDR_PORTX + 79;
//
unsigned char xdata partner_external_power _at_ MEM_ADDR_PORTX + 80;
unsigned char xdata partner_supp_pr_swap _at_ MEM_ADDR_PORTX + 81;
unsigned char xdata partner_supp_dr_swap _at_ MEM_ADDR_PORTX + 82;
unsigned char xdata partner_usb_commun _at_ MEM_ADDR_PORTX + 83;
unsigned char xdata partner_reject_pr_swap _at_ MEM_ADDR_PORTX + 84;
unsigned char xdata partner_reject_dr_swap _at_ MEM_ADDR_PORTX + 85;
unsigned char xdata partner_reject_vc_swap _at_ MEM_ADDR_PORTX + 86;
unsigned char xdata partner_type _at_ MEM_ADDR_PORTX + 87;
unsigned char xdata support_power_swap _at_ MEM_ADDR_PORTX + 88;
unsigned char xdata support_data_swap _at_ MEM_ADDR_PORTX + 89;
unsigned char xdata reserved90 _at_ MEM_ADDR_PORTX + 90;
unsigned char xdata snk_hardresting _at_ MEM_ADDR_PORTX + 91;
TASKP xdata ms_state _at_ MEM_ADDR_PORTX + 92; // 2 bytes, ms: message sent
TASKP xdata md_state _at_ MEM_ADDR_PORTX + 94; // 2 bytes, md: message dropped
TASKP xdata bk_state _at_ MEM_ADDR_PORTX + 96; // 2 bytes, bk: backup
unsigned short xdata device_id _at_ MEM_ADDR_PORTX + 98; // 2 bytes
// Tx Message Payload
struct tx_buf_frame_type xdata tx_frame_type _at_ MEM_ADDR_PORTX + 100; // 2 bytes
struct message_header xdata tx_header _at_ MEM_ADDR_PORTX + 102; // 6 bytes
unsigned long xdata tx_object[7] _at_ MEM_ADDR_PORTX + 108; // 28 bytes
// Rx Message Payload
struct rx_buf_frame_type xdata rx_frame_type _at_ MEM_ADDR_PORTX + 136; // 1 bytes
struct message_header xdata rx_header _at_ MEM_ADDR_PORTX + 137; // 6 bytes
unsigned long xdata rx_object[7] _at_ MEM_ADDR_PORTX + 143; // 28 bytes
// Request Message, re-send if port partner send Wait
struct tx_buf_frame_type xdata req_frame_type _at_ MEM_ADDR_PORTX + 171; // 2 bytes
struct message_header xdata req_header _at_ MEM_ADDR_PORTX + 173; // 6 bytes
unsigned long xdata req_object _at_ MEM_ADDR_PORTX + 179; // 4 bytes
// VDM message, backup if interrupted by pd msg, PD2 V1.1 p183
struct tx_buf_frame_type xdata vdm_frame_type _at_ MEM_ADDR_PORTX + 183; // 2 bytes
struct message_header xdata vdm_header _at_ MEM_ADDR_PORTX + 185; // 6 bytes
unsigned long xdata vdm_object[7] _at_ MEM_ADDR_PORTX + 191; // 28 bytes
//
unsigned short xdata src_cap_vol_25mv[7] _at_ MEM_ADDR_PORTX + 219; // 14 bytes
unsigned short xdata src_cap_cur_10ma[7] _at_ MEM_ADDR_PORTX + 233; // 14 bytes
//
unsigned char xdata partner_non_responsive _at_ MEM_ADDR_PORTX + 247;
unsigned char xdata reserved248 _at_ MEM_ADDR_PORTX + 248;
unsigned char xdata alarm_lo_occurred_0v8 _at_ MEM_ADDR_PORTX + 249; //
unsigned char xdata alarm_lo_occurred_0v1 _at_ MEM_ADDR_PORTX + 250; //
unsigned short xdata alarm_lo_threshold_25mv _at_ MEM_ADDR_PORTX + 251; // 2 bytes
unsigned short xdata backup_vol_25mv _at_ MEM_ADDR_PORTX + 253; // 2 bytes
unsigned short xdata vbus_target_10ma _at_ MEM_ADDR_PORTX + 255; // 2 bytes
unsigned char xdata snk_pdo_count _at_ MEM_ADDR_PORTX + 257; //
unsigned char xdata reserved258 _at_ MEM_ADDR_PORTX + 258; //
unsigned char xdata CapabilityMismatch _at_ MEM_ADDR_PORTX + 259; //
unsigned char xdata enable_cc_detach_timer _at_ MEM_ADDR_PORTX + 260; //
unsigned short xdata alarm_hi_threshold_25mv _at_ MEM_ADDR_PORTX + 261; // 2 bytes
unsigned short xdata req_opr_vol_25mv _at_ MEM_ADDR_PORTX + 263; // 2 bytes
unsigned char xdata pe_one_busy _at_ MEM_ADDR_PORTX + 265; // one port
unsigned char xdata tx_one_busy _at_ MEM_ADDR_PORTX + 266; // one port
unsigned char xdata enable_discharge_timer _at_ MEM_ADDR_PORTX + 267; //
unsigned short xdata stop_discharge_th_25mv _at_ MEM_ADDR_PORTX + 268; // 2 bytes
unsigned char xdata wait_send_request _at_ MEM_ADDR_PORTX + 270; //
unsigned char xdata enable_cc_handle _at_ MEM_ADDR_PORTX + 271; //
unsigned char xdata hard_reset_received _at_ MEM_ADDR_PORTX + 272; //
unsigned char xdata soft_reset_received _at_ MEM_ADDR_PORTX + 273; //
unsigned char xdata vol_alarm_hi_occurred _at_ MEM_ADDR_PORTX + 274; //
unsigned char xdata vol_alarm_lo_occurred _at_ MEM_ADDR_PORTX + 275; //
unsigned char xdata ov_oc_fault_latched _at_ MEM_ADDR_PORTX + 276; //
unsigned char xdata src_detached _at_ MEM_ADDR_PORTX + 277; //
unsigned char xdata reserved278 _at_ MEM_ADDR_PORTX + 278; // reserved
unsigned char xdata reserved279 _at_ MEM_ADDR_PORTX + 279; // reserved
unsigned char xdata reserved280 _at_ MEM_ADDR_PORTX + 280; // reserved
unsigned char xdata reserved281 _at_ MEM_ADDR_PORTX + 281; // reserved
unsigned char xdata reserved282 _at_ MEM_ADDR_PORTX + 282; // reserved
unsigned char xdata reserved283 _at_ MEM_ADDR_PORTX + 283; // reserved
unsigned char xdata reserved284 _at_ MEM_ADDR_PORTX + 284; // reserved
unsigned char xdata reserved285 _at_ MEM_ADDR_PORTX + 285; // reserved
unsigned char xdata reserved286 _at_ MEM_ADDR_PORTX + 286; // reserved
unsigned char xdata reserved287 _at_ MEM_ADDR_PORTX + 287; // reserved
// common variable
unsigned short xdata vbus_vol;
unsigned short data supply_pwr_100mw; // the power suppied to computer port
unsigned short data adapter_pwr_100mw; // the power suppied from adapter port
unsigned short xdata adapter_cur_10ma;
unsigned short xdata adapter_vol_25mv;
unsigned short xdata barrel_adapter_25mv;
unsigned short xdata type_c_adapter_25mv;
#if SEND_GET_SNK_CAP_REQUEST_ONCE_OPT
unsigned char xdata dpm_get_snk_cap_request_sent;
#endif
// local use
static unsigned char xdata local8;
static unsigned short xdata local16;
// alert status
unsigned char data alert0; // DATA memory for code size
unsigned char data alert1; // DATA memory for code size
unsigned char xdata cc_status; // bit0~7 of CC_STATUS Register
unsigned char xdata pwr_status;
unsigned char xdata fault_status;
unsigned char xdata pwr_ctrl;
unsigned char xdata fault_ctrl;
// task
unsigned char data port; // must in DATA memory
TASKP data pe_state; // must in DATA memory
TASKP data tx_state; // must in DATA memory
TASKP data ac_state; // must in DATA memory, ac: analog current
TASKP data hd_state; // must in DATA memory, hd: hard disk drive
// backup
TASKP xdata bak_pe_state[PORT_COUNT];
TASKP xdata bak_tx_state[PORT_COUNT];
// for sata power @PD or non-PD issue
unsigned char xdata i2c_nak;
unsigned char xdata i2c_timeout;
// info from DC Jack
unsigned char xdata ac_inserted;
unsigned char xdata ac_attached;
// info from adapter partner side
unsigned char xdata adapter_contract;
// info from computer partner side
unsigned char xdata computer_contract;
unsigned short xdata sink_from_computer_25mv;
unsigned char xdata is_data_role_ufp;
unsigned char xdata vbus_detected;
// variables for hard disk drive state
unsigned char xdata tcpm_reject_turn_on_disk;
unsigned char xdata usb_req_turn_on_disk;
// (local)
unsigned short xdata max_cur_10ma;
unsigned short xdata cur_10ma;
unsigned short xdata max_vol_50mv;
unsigned short xdata vol_50mv;
unsigned short xdata max_pwr_100mw;
unsigned short xdata pdo0_10ma;
// (local)
unsigned char xdata src_supply_type[7];
// busy flag
unsigned char data combined_busy; // combine all busy flag
unsigned char data pe_all_busy; // all port flag combines one port flag
unsigned char data tx_all_busy; // all port flag combines one port flag
unsigned char data ac_busy;
unsigned char data hd_busy;
#ifdef UART
#define DBG_MAX_BUF_INDEX 895
unsigned short xdata dbg_buf_index;
unsigned short xdata dbg_print_index;
unsigned char xdata dbg_buf[DBG_MAX_BUF_INDEX+1];
unsigned char xdata dbg_busy;
#endif
//--------------------------------------------------------------------------
void write_mcu_dwcnt_1ms(unsigned char value)
{
if(port)
{
aMCU_DWCNT14_1MS = value;
}
else
{
aMCU_DWCNT2_1MS = value;
}
}
unsigned char read_mcu_dwcnt_1ms(void)
{
if(port)
{
return aMCU_DWCNT14_1MS;
}
else
{
return aMCU_DWCNT2_1MS;
}
}
void write_mcu_dwcnt_1ms_detach(unsigned char value)
{
if(port)
{
aMCU_DWCNT12_1MS = value;
}
else
{
aMCU_DWCNT11_1MS = value;
}
}
unsigned char read_mcu_dwcnt_1ms_detach(void)
{
if(port)
{
return aMCU_DWCNT12_1MS;
}
else
{
return aMCU_DWCNT11_1MS;
}
}
void write_mcu_dwcnt_10ms(unsigned char value)
{
if(port)
{
aMCU_DWCNT18_10MS = value;
}
else
{
aMCU_DWCNT17_10MS = value;
}
}
unsigned char read_mcu_dwcnt_10ms(void)
{
if(port)
{
return aMCU_DWCNT18_10MS;
}
else
{
return aMCU_DWCNT17_10MS;
}
}
void write_mcu_dwcnt_100ms(unsigned char value)
{
if(port)
{
aMCU_DWCNT21_100MS = value;
}
else
{
aMCU_DWCNT20_100MS = value;
}
}
unsigned char read_mcu_dwcnt_100ms(void)
{
if(port)
{
return aMCU_DWCNT21_100MS;
}
else
{
return aMCU_DWCNT20_100MS;
}
}
void write_mcu_dwcnt_100ms_ac(unsigned char value)
{
aMCU_DWCNT22_100MS = value;
}
unsigned char read_mcu_dwcnt_100ms_ac(void)
{
return aMCU_DWCNT22_100MS;
}
void write_mcu_dwcnt_100ms_hd(unsigned char value)
{
aMCU_DWCNT23_100MS = value;
}
unsigned char read_mcu_dwcnt_100ms_hd(void)
{
return aMCU_DWCNT23_100MS;
}
//--------------------------------------------------------------------------
void clear_xdata16(void xdata *ptr, unsigned short size)
{
if(size <= 256)
{
xdata_clear(ptr, size);
}
else
{
xdata_clear(ptr, 256);
xdata_clear(ptr+256, size-256);
}
}
void copy_xdata16(const void xdata *src, void xdata *dest, unsigned short size)
{
if(size <= 256)
{
xdata_copy(src, dest, size);
}
else
{
xdata_copy(src, dest, 256);
xdata_copy(src+256, dest+256, size-256);
}
}
void restore_port_variables(void)
{
unsigned char iii=3;
if(port)
{
copy_xdata16(MEM_ADDR_PORT1, MEM_ADDR_PORTX, MEM_ADDR_SIZE);
}
else
{
copy_xdata16(MEM_ADDR_PORT0, MEM_ADDR_PORTX, MEM_ADDR_SIZE);
}
// task, pe_state and tx_state must in DATA memory
pe_state = bak_pe_state[port];
tx_state = bak_tx_state[port];
}
void backup_port_variables(void)
{
if(port)
{
copy_xdata16(MEM_ADDR_PORTX, MEM_ADDR_PORT1, MEM_ADDR_SIZE);
}
else
{
copy_xdata16(MEM_ADDR_PORTX, MEM_ADDR_PORT0, MEM_ADDR_SIZE);
}
// task, pe_state and tx_state must in DATA memory
bak_pe_state[port] = pe_state;
bak_tx_state[port] = tx_state;
}
//--------------------------------------------------------------------------
void dpm_build_sop_ctrl_msg(unsigned char msg)
{
tx_frame_type.SOP = TX_SOP_0P;
set_tx_ctrl_header(msg);
}
void dpm_build_req_msg(void)
{
// decide Request Message's SOP
tx_frame_type.SOP = TX_SOP_0P;
// decide Request Message's Header
set_tx_data_header(MSG_REQUEST, 1);
//
shift_tab = req_pdo_shift;
list_count = sizeof(req_pdo_shift);
dpm_combine_cmm_list_to_tx_obj(0);
// backup, re-send if port partner send Wait
xdata_copy(&tx_frame_type, &req_frame_type, sizeof(req_frame_type));
xdata_copy(&tx_header, &req_header, sizeof(req_header));
xdata_copy(&tx_object[0], &req_object, sizeof(req_object)); // Request Message only have 1 data object
}
void dpm_build_snk_cap_msg(void)
{
// decide SOP
tx_frame_type.SOP = TX_SOP_0P;
#if 0 // code size = 40 bytes
// decide Power Data Object
cmm_pdo_list[0] = req_opr_cur_10ma; // OperationalCurrent10mA
cmm_pdo_list[1] = req_opr_vol_50mv; // Voltage50mV
cmm_pdo_list[2] = 0; // Reserved – shall be set to zero.
cmm_pdo_list[3] = 0; // DataRoleSwap
cmm_pdo_list[4] = usb_comm_capable; // USBCommunicationsCapable
cmm_pdo_list[5] = external_power; // ExternallyPowered
cmm_pdo_list[6] = 0; // HigherCapability
cmm_pdo_list[7] = 0; // DualRolePower
cmm_pdo_list[8] = FIXED_SUPPLY; // SupplyType
// build 32-bit data object, for reduce code size
shift_tab = snk_fix_pdo_shift;
list_count = sizeof(snk_fix_pdo_shift);
dpm_combine_cmm_list_to_tx_obj(0);
#else
// code size = 11 bytes
// 1.5A for 2.5" HDD
if(PARTNER_COMPUTER == partner_type)
{
if(dual_role_port)
{
// requiring no power from the Source, the Voltage (B19..10) shall be set to 5V
// and the Operational Current shall be set to 0mA. PD2 V1.2 ECN p161
// Actually our PCBA still draw small current, so we choise 0.5ma
snk_pdo_count = 1;
tx_object[0] = SNK_CAP_PDO_5V0_0A5_COMPUTER_DRP;
}
else
{
#if (HDD_5V_ONLY == DRIVE_HDD_PWR_TYPE)
{
snk_pdo_count = 1;
tx_object[0] = SNK_CAP_PDO_5V0_0A9_COMPUTER_SNK;
}
#elif (HDD_5V_12V == DRIVE_HDD_PWR_TYPE)
{
snk_pdo_count = 3;
tx_object[0] = SNK_CAP_PDO_5V0_3A0_COMPUTER_SNK;
tx_object[1] = SNK_CAP_PDO_12V_3A0_COMPUTER_SNK;
tx_object[2] = SNK_CAP_VAR_PDO_15V_20V_3A0_COMPUTER_SNK;
}
#endif
}
}
else if(PARTNER_ADAPTER == partner_type)
{
snk_pdo_count = 2;
tx_object[0] = SNK_CAP_PDO_5V0_3A0_ADAPTER_SNK;
tx_object[1] = SNK_CAP_PDO_14V8_20V0_3A0_ADAPTER_SNK;
}
// decide Header
set_tx_data_header(MSG_SINK_CAPABILITIES, snk_pdo_count);
#endif
//ds(""); dw(tx_object[0] >> 16); dw(tx_object[0]);
}
void dpm_parser_snk_pdo(void)
{
//
// Since all USB Consumers support vSafe5V, the required vSafe5V Fixed Supply Power Data Object is also used
// to convey additional information that is returned in bits 29 through 20. PD2 V1.1 p158
//
// shift table
shift_tab = snk_fix_pdo_shift;
list_count = sizeof(snk_fix_pdo_shift);
mask_tab = snk_fix_pdo_mask;
// extract common list from data object
dpm_extract_cmm_list_from_rx_obj(0);
//
partner_supp_dr_swap = cmm_pdo_list[3];
partner_usb_commun = cmm_pdo_list[4];
partner_external_power = cmm_pdo_list[5];
partner_supp_pr_swap = cmm_pdo_list[7];
//U ds("dr"); db(partner_supp_dr_swap);
//U ds("pr"); db(partner_supp_pr_swap);
//U ds("ex"); db(partner_external_power);
//U ds("cm"); db(partner_usb_commun);
}
void dpm_parser_src_pdo(unsigned char index)
{
if(index >= 7)
{
U ds("!e");
return;
}
// extract bit30~31: SupplyType
src_supply_type[index] = (rx_object[index] >> 30) & 0x03;
// decide shift table
if(FIXED_SUPPLY == src_supply_type[index]) //
{
shift_tab = src_fix_pdo_shift;
list_count = sizeof(src_fix_pdo_shift);
mask_tab = src_fix_pdo_mask;
}
else // variable or battery
{
shift_tab = var_bat_pdo_shift;
list_count = sizeof(var_bat_pdo_shift);
mask_tab = var_bat_pdo_mask;
}
// extract common list from data object
dpm_extract_cmm_list_from_rx_obj(index);
//ds(""); dw(rx_object[0] >> 16); dw(rx_object[0]);
// code size: 318 bytes
// assign each item
// if(FIXED_SUPPLY == src_supply_type[index])
// {
// src_fix_pdo[index].MaximumCurrent10mA = cmm_pdo_list[0];
// src_fix_pdo[index].Voltage50mV = cmm_pdo_list[1];
// src_fix_pdo[index].PeakCurrent = cmm_pdo_list[2];
// src_fix_pdo[index].DataRoleSwap = cmm_pdo_list[3];
// src_fix_pdo[index].USBCommunicationsCapable = cmm_pdo_list[4];
// src_fix_pdo[index].ExternallyPowered = cmm_pdo_list[5];
// src_fix_pdo[index].USBSuspendSupported = cmm_pdo_list[6];
// src_fix_pdo[index].DualRolePower = cmm_pdo_list[7];
// }
// else if(BATTERY_SUPPLY == src_supply_type[index])
// {
// src_bat_pdo[index].MaximumAllowablePower250mW = cmm_pdo_list[0];
// src_bat_pdo[index].MinimumVoltage50mV = cmm_pdo_list[1];
// src_bat_pdo[index].MaximumVoltage50mV = cmm_pdo_list[2];
// }
// else if(VARIABLE_SUPPLY == src_supply_type[index])
// {
// src_var_pdo[index].MaximumCurrent10mA = cmm_pdo_list[0];
// src_var_pdo[index].MinimumVoltage50mV = cmm_pdo_list[1];
// src_var_pdo[index].MaximumVoltage50mV = cmm_pdo_list[2];
// }
}
#if BIST_SUPPORT
void dpm_paser_bist_header(void)
{
shift_tab = bist_header_shift;
list_count = sizeof(bist_header_shift);
mask_tab = bist_header_mask;
// extract common list from data object
dpm_extract_cmm_list_from_rx_obj(0);
bist_mode = cmm_pdo_list[2];
//ds(""); dw(rx_object[0] >> 16); dw(rx_object[0]);
}
void dpm_build_transmit_bist_carrier_mode2(void)
{
clr_tx_payload();
// decide SOP
tx_frame_type.SOP = TX_BIST_MODE_2;
}
#endif
void dpm_evaluate_src_cap(void)
{
unsigned char i;
// parser 5V Fixed Power Data Object
// The vSafe5V Fixed Supply Object shall always be the first object, PD2 V1.1 p152
dpm_parser_src_pdo(0);
// vSafe5V Fixed Supply Power Data Object is also used to convey additional information that is returned in bits 29 through 25.
// other Fixed Supply Power Data Objects shall set bits 29...22 to zero, PD2 V1.1 p154
partner_supp_dr_swap = cmm_pdo_list[4];
partner_usb_commun = cmm_pdo_list[5];
partner_external_power = cmm_pdo_list[6];
partner_supp_pr_swap = cmm_pdo_list[8];
//U ds("dr"); db(partner_supp_dr_swap);
//U ds("pr"); db(partner_supp_pr_swap);
//U ds("ext"); db(partner_external_power);
//U ds("com"); db(partner_usb_commun);
// default request 5v
max_cur_10ma = cmm_pdo_list[0];
max_vol_50mv = cmm_pdo_list[1];
pdo0_10ma = max_cur_10ma;
requested_obj_pos = 0;
// request max power if adapter port
if(PARTNER_ADAPTER == partner_type)
{
// parser others power data object
for(i=1; i<rx_header.NumOfDataObj; i++)
{
// parser Power Data Object, from low to high
dpm_parser_src_pdo(i);
// decide current of request pdo
if(FIXED_SUPPLY == src_supply_type[i])
{
cur_10ma = cmm_pdo_list[0]; // Maximum Current in 10mA units
vol_50mv = cmm_pdo_list[1]; // Voltage in 50mV units
}
else if(VARIABLE_SUPPLY == src_supply_type[i])
{
cur_10ma = cmm_pdo_list[0]; // Maximum Current in 10mA units
vol_50mv = cmm_pdo_list[2]; // Maximum Voltage in 50mV units
}
else // battery
{
vol_50mv = cmm_pdo_list[2]; // Maximum Voltage in 50mV units
// calculate max current, I = P / V, 500 = 100mA * 250mW / 50mV
cur_10ma = 0;
if(vol_50mv)
{
cur_10ma = 500 * cmm_pdo_list[0] / vol_50mv; // [0]: Maximum Allowable Power in 250mW units
}
}
// select max voltage
if(vol_50mv > max_vol_50mv)
{
max_vol_50mv = vol_50mv;
max_cur_10ma = cur_10ma;
requested_obj_pos = i;
}
}//for
CapabilityMismatch = 0;
// revise max_vol_50mv
if(0 == max_cur_10ma)
{
// if partner supplied 0mA, just request 5V PDO
max_vol_50mv = VOL05V_50MV;
requested_obj_pos = 0;
}
else if(TYPEC_ACCEPTABLE_V_25MV > max_vol_50mv || TYPEC_ACCEPTABLE_PWR_100MW > calc_power_100mw(max_vol_50mv*2, max_cur_10ma) )
{
// only select over 14.8V/29W or 5V PDO
max_vol_50mv = VOL05V_50MV;
requested_obj_pos = 0;
CapabilityMismatch = 1;
}
// request maximum voltage
req_opr_vol_50mv = max_vol_50mv;
req_max_opr_cur_10ma = max_cur_10ma;
req_opr_cur_10ma = max_cur_10ma;
}
else if(PARTNER_COMPUTER == partner_type)
{
// decide:
// 1. req_max_opr_cur_10ma
// 2. req_opr_cur_10ma
// 3. CapabilityMismatch
// 4. req_opr_vol_50mv
// 5. requested_obj_pos
if(external_power)
{
// request 5v and don't care current
requested_obj_pos = 0;
req_opr_vol_50mv = VOL05V_50MV;
req_max_opr_cur_10ma = pdo0_10ma;
req_opr_cur_10ma = pdo0_10ma;
CapabilityMismatch = 0;
}
else
{
#if (HDD_5V_ONLY == DRIVE_HDD_PWR_TYPE)
{
// only request 5v
req_opr_vol_50mv = VOL05V_50MV;
requested_obj_pos = 0;
if(pdo0_10ma < CUR0A9_10MA) // 1.5A for 2.5" HDD
{