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
|
/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* USB Power delivery module */
#ifndef __USB_PD_H
#define __USB_PD_H
#include "common.h"
enum pd_errors {
PD_ERR_INVAL = -1, /* Invalid packet */
PD_ERR_HARD_RESET = -2, /* Got a Hard-Reset packet */
PD_ERR_CRC = -3, /* CRC mismatch */
PD_ERR_ID = -4, /* Invalid ID number */
};
/* incoming packet event (for the USB PD task) */
#define PD_EVENT_RX (1<<2)
/* --- PD data message helpers --- */
#define PDO_MAX_OBJECTS 7
#define PDO_MODES (PDO_MAX_OBJECTS - 1)
/* PDO : Power Data Object */
/*
* 1. The vSafe5V Fixed Supply Object shall always be the first object.
* 2. The remaining Fixed Supply Objects,
* if present, shall be sent in voltage order; lowest to highest.
* 3. The Battery Supply Objects,
* if present shall be sent in Minimum Voltage order; lowest to highest.
* 4. The Variable Supply (non battery) Objects,
* if present, shall be sent in Minimum Voltage order; lowest to highest.
*/
#define PDO_TYPE_FIXED (0 << 30)
#define PDO_TYPE_BATTERY (1 << 30)
#define PDO_TYPE_VARIABLE (2 << 30)
#define PDO_TYPE_MASK (3 << 30)
#define PDO_FIXED_DUAL_ROLE (1 << 29) /* Dual role device */
#define PDO_FIXED_SUSPEND (1 << 28) /* USB Suspend supported */
#define PDO_FIXED_EXTERNAL (1 << 27) /* Externally powered */
#define PDO_FIXED_COMM_CAP (1 << 26) /* USB Communications Capable */
#define PDO_FIXED_PEAK_CURR () /* [21..20] Peak current */
#define PDO_FIXED_VOLT(mv) (((mv)/50) << 10) /* Voltage in 50mV units */
#define PDO_FIXED_CURR(ma) (((ma)/10) << 0) /* Max current in 10mA units */
#define PDO_FIXED(mv, ma, flags) (PDO_FIXED_VOLT(mv) |\
PDO_FIXED_CURR(ma) | (flags))
#define PDO_VAR_MAX_VOLT(mv) ((((mv) / 50) & 0x3FF) << 20)
#define PDO_VAR_MIN_VOLT(mv) ((((mv) / 50) & 0x3FF) << 10)
#define PDO_VAR_OP_CURR(ma) ((((ma) / 10) & 0x3FF) << 0)
#define PDO_VAR(min_mv, max_mv, op_ma) \
(PDO_VAR_MIN_VOLT(min_mv) | \
PDO_VAR_MAX_VOLT(max_mv) | \
PDO_VAR_OP_CURR(op_ma))
#define PDO_BATT_MAX_VOLT(mv) ((((mv) / 50) & 0x3FF) << 20)
#define PDO_BATT_MIN_VOLT(mv) ((((mv) / 50) & 0x3FF) << 10)
#define PDO_BATT_OP_POWER(mw) ((((mw) / 10) & 0x3FF) << 0)
#define PDO_BATT(min_mv, max_mv, op_mw) \
(PDO_BATT_MIN_VOLT(min_mv) | \
PDO_BATT_MAX_VOLT(max_mv) | \
PDO_BATT_OP_POWER(op_mw))
/* RDO : Request Data Object */
#define RDO_OBJ_POS(n) (((n) & 0x7) << 28)
#define RDO_GIVE_BACK (1 << 27)
#define RDO_CAP_MISMATCH (1 << 26)
#define RDO_COMM_CAP (1 << 25)
#define RDO_NO_SUSPEND (1 << 24)
#define RDO_FIXED_VAR_OP_CURR(ma) ((((ma) / 10) & 0x3FF) << 10)
#define RDO_FIXED_VAR_MAX_CURR(ma) ((((ma) / 10) & 0x3FF) << 0)
#define RDO_BATT_OP_POWER(mw) ((((mw) / 250) & 0x3FF) << 10)
#define RDO_BATT_MAX_POWER(mw) ((((mw) / 250) & 0x3FF) << 10)
#define RDO_FIXED(n, op_ma, max_ma, flags) \
(RDO_OBJ_POS(n) | (flags) | \
RDO_FIXED_VAR_OP_CURR(op_ma) | \
RDO_FIXED_VAR_MAX_CURR(max_ma))
#define RDO_BATT(n, op_mw, max_mw, flags) \
(RDO_OBJ_POS(n) | (flags) | \
RDO_BATT_OP_POWER(op_mw) | \
RDO_BATT_MAX_POWER(max_mw))
/* BDO : BIST Data Object */
#define BDO_MODE_RECV (0 << 28)
#define BDO_MODE_TRANSMIT (1 << 28)
#define BDO_MODE_COUNTERS (2 << 28)
#define BDO_MODE_CARRIER0 (3 << 28)
#define BDO_MODE_CARRIER1 (4 << 28)
#define BDO_MODE_CARRIER2 (5 << 28)
#define BDO_MODE_CARRIER3 (6 << 28)
#define BDO_MODE_EYE (7 << 28)
#define BDO(mode, cnt) ((mode) | ((cnt) & 0xFFFF))
/* TODO(tbroch) is there a finite number for these in the spec */
#define SVID_DISCOVERY_MAX 16
/* function table for entered mode */
struct amode_fx {
int (*status)(int port, uint32_t *payload);
int (*config)(int port, uint32_t *payload);
};
/* function table for alternate mode capable responders */
struct svdm_response {
int (*identity)(int port, uint32_t *payload);
int (*svids)(int port, uint32_t *payload);
int (*modes)(int port, uint32_t *payload);
int (*enter_mode)(int port, uint32_t *payload);
int (*exit_mode)(int port, uint32_t *payload);
struct amode_fx *amode;
};
struct svdm_svid_data {
uint16_t svid;
int mode_cnt;
uint32_t mode_vdo[PDO_MODES];
};
struct svdm_amode_fx {
uint16_t svid;
void (*enter)(int port, uint32_t mode_caps);
int (*status)(int port, uint32_t *payload);
int (*config)(int port, uint32_t *payload);
void (*exit)(int port);
};
/* defined in <board>/usb_pd_policy.c */
/* All UFP_U should have */
extern const struct svdm_response svdm_rsp;
/* All DFP_U should have */
extern const struct svdm_amode_fx supported_modes[];
extern const int supported_modes_cnt;
struct svdm_amode_data {
const struct svdm_amode_fx *fx;
int index;
uint32_t mode_caps;
};
enum hpd_level {
hpd_unknown = -1,
hpd_low = 0,
hpd_high,
};
/* Policy structure for driving alternate mode */
struct pd_policy {
/* index of svid currently being operated on */
int svid_idx;
/* count of svids discovered */
int svid_cnt;
/* supported svids & corresponding vdo mode data */
struct svdm_svid_data svids[SVID_DISCOVERY_MAX];
/* active mode */
struct svdm_amode_data amode;
};
/*
* VDO : Vendor Defined Message Object
* VDM object is minimum of VDM header + 6 additional data objects.
*/
/*
* VDM header
* ----------
* <31:16> :: SVID
* <15> :: VDM type ( 1b == structured, 0b == unstructured )
* <14:13> :: Structured VDM version (can only be 00 == 1.0 currently)
* <12:11> :: reserved
* <10:8> :: object position (1-7 valid ... used for enter/exit mode only)
* <7:6> :: command type (SVDM only?)
* <5> :: reserved (SVDM), command type (UVDM)
* <4:0> :: command
*/
#define VDO_MAX_SIZE 7
#define VDO(vid, type, custom) \
(((vid) << 16) | \
((type) << 15) | \
((custom) & 0x7FFF))
#define VDO_SVDM_TYPE (1 << 15)
#define VDO_SVDM_VERS(x) (x << 13)
#define VDO_OPOS(x) (x << 8)
#define VDO_CMDT(x) (x << 6)
#define VDO_CMDT_MASK VDO_CMDT(0x3)
#define CMDT_INIT 0
#define CMDT_RSP_ACK 1
#define CMDT_RSP_NAK 2
#define CMDT_RSP_BUSY 3
/* reserved for SVDM ... for Google UVDM */
#define VDO_SRC_INITIATOR (0 << 5)
#define VDO_SRC_RESPONDER (1 << 5)
#define CMD_DISCOVER_IDENT 1
#define CMD_DISCOVER_SVID 2
#define CMD_DISCOVER_MODES 3
#define CMD_ENTER_MODE 4
#define CMD_EXIT_MODE 5
#define CMD_ATTENTION 6
#define CMD_DP_STATUS 16
#define CMD_DP_CONFIG 17
#define VDO_CMD_VENDOR(x) (((10 + (x)) & 0x1f))
/* ChromeOS specific commands */
#define VDO_CMD_VERSION VDO_CMD_VENDOR(0)
#define VDO_CMD_SEND_INFO VDO_CMD_VENDOR(1)
#define VDO_CMD_READ_INFO VDO_CMD_VENDOR(2)
#define VDO_CMD_REBOOT VDO_CMD_VENDOR(5)
#define VDO_CMD_FLASH_ERASE VDO_CMD_VENDOR(6)
#define VDO_CMD_FLASH_WRITE VDO_CMD_VENDOR(7)
#define VDO_CMD_ERASE_SIG VDO_CMD_VENDOR(8)
#define VDO_CMD_PING_ENABLE VDO_CMD_VENDOR(10)
#define VDO_CMD_CURRENT VDO_CMD_VENDOR(11)
#define VDO_CMD_FLIP VDO_CMD_VENDOR(12)
#define PD_VDO_VID(vdo) ((vdo) >> 16)
#define PD_VDO_SVDM(vdo) (((vdo) >> 15) & 1)
#define PD_VDO_OPOS(vdo) (((vdo) >> 8) & 0x7)
#define PD_VDO_CMD(vdo) ((vdo) & 0x1f)
#define PD_VDO_CMDT(vdo) (((vdo) >> 6) & 0x3)
/*
* SVDM Identity request -> response
*
* Request is simply properly formatted SVDM header
*
* Response is 4 data objects:
* [0] :: SVDM header
* [1] :: Identitiy header
* [2] :: Cert Stat VDO
* [3] :: (Product | Cable | AMA) VDO
*
*/
#define VDO_INDEX_HDR 0
#define VDO_INDEX_IDH 1
#define VDO_INDEX_CSTAT 2
#define VDO_INDEX_CABLE 3
#define VDO_INDEX_AMA 3
#define VDO_I(name) VDO_INDEX_##name
/*
* SVDM Identity Header
* --------------------
* <31> :: data capable as a USB host
* <30> :: data capable as a USB device
* <29:27> :: product type
* <26> :: modal operation supported (1b == yes)
* <25:16> :: SBZ
* <15:0> :: USB-IF assigned VID for this cable vendor
*/
#define IDH_PTYPE_UNDEF 0
#define IDH_PTYPE_HUB 1
#define IDH_PTYPE_PERIPH 2
#define IDH_PTYPE_ACABLE 4
#define IDH_PTYPE_PCABLE 5
#define IDH_PTYPE_AMA 6
#define VDO_IDH(usbh, usbd, ptype, is_modal, vid) \
((usbh) << 31 | (usbd) << 30 | ((ptype) & 0x7) << 27 \
| (is_modal) << 26 | ((vid) & 0xffff))
#define PD_IDH_PTYPE(vdo) (((vdo) >> 27) & 0x7)
#define PD_IDH_VID(vdo) ((vdo) & 0xffff)
/*
* Cert Stat VDO
* -------------
* <31:20> : SBZ
* <19:0> : USB-IF assigned TID for this cable
*/
#define VDO_CSTAT(tid) ((tid) & 0xfffff)
#define PD_CSTAT_TID(vdo) ((vdo) & 0xfffff)
/*
* Cable VDO
* ---------
* <31:28> :: Cable HW version
* <27:24> :: Cable FW version
* <23:20> :: SBZ
* <19:18> :: type-C to Type-A/B/C (00b == A, 01 == B, 10 == C)
* <17> :: Type-C to Plug/Receptacle (0b == plug, 1b == receptacle)
* <16:13> :: cable latency (0001 == <10ns(~1m length))
* <12:11> :: cable termination type (11b == both ends active VCONN req)
* <10> :: SSTX1 Directionality support (0b == fixed, 1b == cfgable)
* <9> :: SSTX2 Directionality support
* <8> :: SSRX1 Directionality support
* <7> :: SSRX2 Directionality support
* <6:5> :: Vbus current handling capability
* <4> :: Vbus through cable (0b == no, 1b == yes)
* <3> :: SOP" controller present? (0b == no, 1b == yes)
* <2:0> :: USB SS Signaling support
*/
#define CABLE_ATYPE 0
#define CABLE_BTYPE 1
#define CABLE_CTYPE 2
#define CABLE_PLUG 0
#define CABLE_RECEPTACLE 1
#define VDO_CABLE(hw, fw, cbl, gdr, lat, term, tx1d, tx2d, rx1d, rx2d, cur, vps, sopp, usbss) \
(((hw) & 0x7) << 28 | ((fw) & 0x7) << 24 | ((cbl) & 0x3) << 18 \
| (gdr) << 17 | ((lat) & 0x7) << 13 | ((term) & 0x3) << 11 \
| (tx1d) << 10 | (tx2d) << 9 | (rx1d) << 8 | (rx2d) << 7 \
| ((cur) & 0x3) << 5 | (vps) << 4 | (sopp) << 3 \
| ((usbss) & 0x7))
/*
* AMA VDO
* ---------
* <31:28> :: Cable HW version
* <27:24> :: Cable FW version
* <23:12> :: SBZ
* <11> :: SSTX1 Directionality support (0b == fixed, 1b == cfgable)
* <10> :: SSTX2 Directionality support
* <9> :: SSRX1 Directionality support
* <8> :: SSRX2 Directionality support
* <7:5> :: Vconn power
* <4> :: Vconn power required
* <3> :: Vbus power required
* <2:0> :: USB SS Signaling support
*/
#define VDO_AMA(hw, fw, tx1d, tx2d, rx1d, rx2d, vcpwr, vcr, vbr, usbss) \
(((hw) & 0x7) << 28 | ((fw) & 0x7) << 24 \
| (tx1d) << 11 | (tx2d) << 10 | (rx1d) << 9 | (rx2d) << 8 \
| ((vcpwr) & 0x3) << 5 | (vcr) << 4 | (vbr) << 3 \
| ((usbss) & 0x7))
#define PD_VDO_AMA_VCONN_REQ(vdo) (((vdo) >> 4) & 1)
#define PD_VDO_AMA_VBUS_REQ(vdo) (((vdo) >> 3) & 1)
/*
* SVDM Discover SVIDs request -> response
*
* Request is properly formatted VDM Header with discover SVIDs command.
* Response is a set of SVIDs of all all supported SVIDs with all zero's to
* mark the end of SVIDs. If more than 12 SVIDs are supported command SHOULD be
* repeated.
*/
#define VDO_SVID(svid0, svid1) (((svid0) & 0xffff) << 16 | ((svid1) & 0xffff))
#define PD_VDO_SVID_SVID0(vdo) ((vdo) >> 16)
#define PD_VDO_SVID_SVID1(vdo) ((vdo) & 0xffff)
/*
* Mode Capabilities
*
* Number of VDOs supplied is SID dependent (but <= 6 VDOS?)
*/
#define VDO_MODE_CNT_DISPLAYPORT 1
/*
* DisplayPort modes capabilities
* -------------------------------
* <31:24> : SBZ
* <23:16> : sink pin assignment supported
* <15:8> : source pin assignment supported
* <7> : USB 2.0 signaling (0b=yes, 1b=no)
* <6> : Plug | Receptacle (0b == plug, 1b == receptacle)
* <5:3> : USB Gen 2 signaling for DP (000b=no, 001b=yes, rest=rsv)
* <2> : supports dp1.3
* <1:0> : signal direction ( 00b=rsv, 01b=sink, 10b=src 11b=both )
*/
#define VDO_MODE_DP(snkp, srcp, usb, gdr, usbdp, dp3, sdir) \
(((snkp) & 0xff) << 16 | ((srcp) & 0xff) << 8 \
| ((usb) & 1) << 7 | ((gdr) & 1) << 6 | ((usbdp) & 0x7) << 3 \
| ((dp3) & 1) << 2 | ((sdir) & 0x3))
#define MODE_DP_PIN_A 0x01
#define MODE_DP_PIN_B 0x02
#define MODE_DP_PIN_C 0x04
#define MODE_DP_PIN_D 0x08
#define MODE_DP_PIN_E 0x10
#define MODE_DP_SNK 0x1
#define MODE_DP_SRC 0x2
#define MODE_DP_BOTH 0x3
/*
* DisplayPort Status VDO
* ----------------------
* <31:9> : SBZ
* <8> : IRQ_HPD : 1 == irq arrived since last message otherwise 0.
* <7> : HPD state : 0 = HPD_LOW, 1 == HPD_HIGH
* <6> : Exit DP Alt mode: 0 == maintain, 1 == exit
* <5> : USB config : 0 == maintain current, 1 == switch to USB from DP
* <4> : Multi-function preference : 0 == no pref, 1 == MF preferred.
* <3> : enabled : is DPout on/off.
* <2> : power low : 0 == normal or LPM disabled, 1 == DP disabled for LPM
* <1:0> : connect status : 00b == no (DFP|UFP)_D is connected or disabled.
* 01b == DFP_D connected, 10b == UFP_D connected, 11b == both.
*/
#define VDO_DP_STATUS(irq, lvl, amode, usbc, mf, en, lp, conn) \
(((irq) & 1) << 8 | ((lvl) & 1) << 7 | ((amode) & 1) << 6 \
| ((usbc) & 1) << 5 | ((mf) & 1) << 4 | ((en) & 1) << 3 \
| ((lp) & 1) << 2 | ((conn & 0x3) << 0))
/*
* DisplayPort Configure VDO
* -------------------------
* <31:24> : SBZ
* <23:16> : sink pin assignment supported (same as mode caps)
* <15:8> : source pin assignment supported (same as mode caps)
* <7:6> : SBZ
* <5:2> : signalling : 0h == unspec'd, 1h == dp v1.3,
* 2h == USB gen2, remaining rsv
* <1:0> : cfg : 00 == USB, 01|10 == DP, 11 == reserved
*/
#define VDO_DP_CFG(snkp, srcp, sig, cfg) \
(((snkp) & 0xff) << 16 | ((srcp) & 0xff) << 8 \
| ((sig) & 0x7) << 2 | ((cfg) & 0x3))
#define PD_DP_CFG_DPON(x) (((x & 0x3) == 1) || ((x & 0x3) == 2))
/*
* ChromeOS specific PD device Hardware IDs. Used to identify unique
* products and used in VDO_INFO. Note this field is 10 bits.
*/
#define USB_PD_HW_DEV_ID_RESERVED 0
#define USB_PD_HW_DEV_ID_ZINGER 1
#define USB_PD_HW_DEV_ID_MINIMUFFIN 2
/*
* ChromeOS specific VDO_CMD_READ_INFO responds with device info including:
* RW Hash: First 20 bytes of SHA-256 of RW (20 bytes)
* HW Device ID: unique descriptor for each ChromeOS model (2 bytes)
* top 6 bits are minor revision, bottom 10 bits are major
* SW Debug Version: Software version useful for debugging (15 bits)
* IS RW: True if currently in RW, False otherwise (1 bit)
*/
#define VDO_INFO(id, id_minor, ver, is_rw) ((id_minor) << 26 \
| ((id) & 0x3ff) << 16 \
| ((ver) & 0x7fff) << 1 \
| ((is_rw) & 1))
#define VDO_INFO_HW_DEV_ID(x) ((x) >> 16)
#define VDO_INFO_SW_DBG_VER(x) (((x) >> 1) & 0x7fff)
#define VDO_INFO_IS_RW(x) ((x) & 1)
/* USB-IF SIDs */
#define USB_SID_PD 0xff00 /* power delivery */
#define USB_SID_DISPLAYPORT 0xff01
#define USB_GOOGLE_TYPEC_URL "http://www.google.com/chrome/devices/typec"
/* USB Vendor ID assigned to Google Inc. */
#define USB_VID_GOOGLE 0x18d1
/* Timeout for message receive in microseconds */
#define USB_PD_RX_TMOUT_US 2700
/* --- Protocol layer functions --- */
enum pd_states {
PD_STATE_DISABLED,
#ifdef CONFIG_USB_PD_DUAL_ROLE
PD_STATE_SUSPENDED,
PD_STATE_SNK_DISCONNECTED,
PD_STATE_SNK_DISCOVERY,
PD_STATE_SNK_REQUESTED,
PD_STATE_SNK_TRANSITION,
PD_STATE_SNK_READY,
#endif /* CONFIG_USB_PD_DUAL_ROLE */
PD_STATE_SRC_DISCONNECTED,
PD_STATE_SRC_DISCOVERY,
PD_STATE_SRC_NEGOCIATE,
PD_STATE_SRC_ACCEPTED,
PD_STATE_SRC_TRANSITION,
PD_STATE_SRC_READY,
PD_STATE_SOFT_RESET,
PD_STATE_HARD_RESET,
PD_STATE_BIST,
/* Number of states. Not an actual state. */
PD_STATE_COUNT,
};
#ifdef CONFIG_USB_PD_DUAL_ROLE
enum pd_dual_role_states {
PD_DRP_TOGGLE_ON,
PD_DRP_TOGGLE_OFF,
PD_DRP_FORCE_SINK,
PD_DRP_FORCE_SOURCE
};
/**
* Set dual role state, from among enum pd_dual_role_states
*
* @param state New state of dual-role port, selected from
* enum pd_dual_role_states
*/
void pd_set_dual_role(enum pd_dual_role_states state);
#endif
/* Control Message type */
enum pd_ctrl_msg_type {
/* 0 Reserved */
PD_CTRL_GOOD_CRC = 1,
PD_CTRL_GOTO_MIN = 2,
PD_CTRL_ACCEPT = 3,
PD_CTRL_REJECT = 4,
PD_CTRL_PING = 5,
PD_CTRL_PS_RDY = 6,
PD_CTRL_GET_SOURCE_CAP = 7,
PD_CTRL_GET_SINK_CAP = 8,
PD_CTRL_PROTOCOL_ERR = 9,
PD_CTRL_SWAP = 10,
/* 11 Reserved */
PD_CTRL_WAIT = 12,
PD_CTRL_SOFT_RESET = 13,
/* 14-15 Reserved */
};
/* Data message type */
enum pd_data_msg_type {
/* 0 Reserved */
PD_DATA_SOURCE_CAP = 1,
PD_DATA_REQUEST = 2,
PD_DATA_BIST = 3,
PD_DATA_SINK_CAP = 4,
/* 5-14 Reserved */
PD_DATA_VENDOR_DEF = 15,
};
/* Protocol revision */
#define PD_REV10 0
#define PD_REV20 1
/* BMC-supported bit : we are using the baseband variant of the protocol */
#define PD_BMC_SUPPORTED (1 << 15)
/* Port role */
#define PD_ROLE_SINK 0
#define PD_ROLE_SOURCE 1
/* build message header */
/* TODO(crosbug.com/p/28343): need to seperate data role from power role */
#define PD_HEADER(type, role, id, cnt) \
((type) | (PD_REV20 << 6) | \
((role) << 5) | ((role) << 8) | \
((id) << 9) | ((cnt) << 12) | \
PD_BMC_SUPPORTED)
#define PD_HEADER_CNT(header) (((header) >> 12) & 7)
#define PD_HEADER_TYPE(header) ((header) & 0xF)
#define PD_HEADER_ID(header) (((header) >> 9) & 7)
/* K-codes for special symbols */
#define PD_SYNC1 0x18
#define PD_SYNC2 0x11
#define PD_RST1 0x07
#define PD_RST2 0x19
#define PD_EOP 0x0D
/* --- Policy layer functions --- */
/**
* Decide which voltage to use from the source capabilities.
*
* @param cnt the number of Power Data Objects.
* @param src_caps Power Data Objects representing the source capabilities.
* @param rdo requested Request Data Object.
* @return <0 if invalid, else value is the current limit of the RDO data
*/
int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo);
/**
* Put a cap on the max voltage requested as a sink.
* @param mv maximum voltage in millivolts.
*/
void pd_set_max_voltage(unsigned mv);
/**
* Request a new operating voltage.
*
* @param rdo Request Data Object with the selected operating point.
* @return EC_SUCCESS if we can get the requested voltage/OP, <0 else.
*/
int pd_request_voltage(uint32_t rdo);
/**
* Go back to the default/safe state of the power supply
*
* @param port USB-C port number
*/
void pd_power_supply_reset(int port);
/**
* Enable the power supply output after the ready delay.
*
* @param port USB-C port number
* @return EC_SUCCESS if the power supply is ready, <0 else.
*/
int pd_set_power_supply_ready(int port);
/**
* Ask the specified voltage from the PD source.
*
* It triggers a new negotiation sequence with the source.
* @param port USB-C port number
* @param mv request voltage in millivolts.
*/
void pd_request_source_voltage(int port, int mv);
/**
* Set the input current limit.
*
* @port USB-C port number
* @max_ma Maximum current limit
*/
void pd_set_input_current_limit(int port, uint32_t max_ma);
/**
* Verify board specific health status : current, voltages...
*
* @return EC_SUCCESS if the board is good, <0 else.
*/
int pd_board_checks(void);
/**
* Get PD device info used for VDO_CMD_SEND_INFO / VDO_CMD_READ_INFO
*
* @return Pointer to data payload for VDO_CMD_*_INFO
*/
uint32_t *pd_get_info(void);
/**
* Handle Vendor Defined Messages
*
* @param port USB-C port number
* @param cnt number of data objects in the payload.
* @param payload payload data.
* @param rpayload pointer to the data to send back.
* @return if >0, number of VDOs to send back.
*/
int pd_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload);
/**
* Handle Structured Vendor Defined Messages
*
* @param port USB-C port number
* @param cnt number of data objects in the payload.
* @param payload payload data.
* @param rpayload pointer to the data to send back.
* @return if >0, number of VDOs to send back.
*/
int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload);
/**
* Exit alternate mode
*
* @param port USB-C port number
* @param payload payload data.
* @return if >0, number of VDOs to send back.
*/
int pd_exit_mode(int port, uint32_t *payload);
/**
* Store Device ID & RW hash of device
*
* @param port USB-C port number
* @param dev_id device identifier
* @param rw_hash pointer to rw_hash
*/
void pd_dev_store_rw_hash(int port, uint16_t dev_id, uint32_t *rw_hash);
/**
* Send Vendor Defined Message
*
* @param port USB-C port number
* @param vid Vendor ID
* @param cmd VDO command number
* @param data Pointer to payload to send
* @param data number of data objects in payload
*/
void pd_send_vdm(int port, uint32_t vid, int cmd, const uint32_t *data,
int count);
/* Power Data Objects for the source and the sink */
extern const uint32_t pd_src_pdo[];
extern const int pd_src_pdo_cnt;
extern const uint32_t pd_snk_pdo[];
extern const int pd_snk_pdo_cnt;
/**
* Get PD source power data objects.
*
* @param src_pdo pointer to the data to return.
* @return number of PDOs returned.
*/
int pd_get_source_pdo(const uint32_t **src_pdo);
/* Muxing for the USB type C */
enum typec_mux {
TYPEC_MUX_NONE,
TYPEC_MUX_USB,
TYPEC_MUX_DP,
TYPEC_MUX_DOCK,
};
/**
* Configure superspeed muxes on type-C port.
*
* @param port port number.
* @param mux selected function.
* @param polarity plug polarity (0=CC1, 1=CC2).
*/
void board_set_usb_mux(int port, enum typec_mux mux, int polarity);
/**
* Query superspeed mux status on type-C port.
*
* @param port port number.
* @param dp_str pointer to the DP string to return.
* @param usb_str pointer to the USB string to return.
* @return Non-zero if superspeed connection is enabled; otherwise, zero.
*/
int board_get_usb_mux(int port, const char **dp_str, const char **usb_str);
/**
* Flip the superspeed muxes on type-C port.
*
* This is used for factory test automation. Note that this function should
* only flip the superspeed muxes and leave CC lines alone. Without further
* changes, this function MUST ONLY be used for testing purpose, because
* the protocol layer loses track of the superspeed polarity and DP/USB3.0
* connection may break.
*
* @param port port number.
*/
void board_flip_usb_mux(int port);
/* --- Physical layer functions : chip specific --- */
/* Packet preparation/retrieval */
/**
* Prepare packet reading state machine.
*
* @param port USB-C port number
*/
void pd_init_dequeue(int port);
/**
* Prepare packet reading state machine.
*
* @param port USB-C port number
* @param off current position in the packet buffer.
* @param len minimum size to read in bits.
* @param val the read bits.
* @return new position in the packet buffer.
*/
int pd_dequeue_bits(int port, int off, int len, uint32_t *val);
/**
* Advance until the end of the preamble.
*
* @param port USB-C port number
* @return new position in the packet buffer.
*/
int pd_find_preamble(int port);
/**
* Write the preamble in the TX buffer.
*
* @param port USB-C port number
* @return new position in the packet buffer.
*/
int pd_write_preamble(int port);
/**
* Write one 10-period symbol in the TX packet.
* corresponding to a quartet with 4b5b encoding
* and Biphase Mark Coding.
*
* @param port USB-C port number
* @param bit_off current position in the packet buffer.
* @param val10 the 10-bit integer.
* @return new position in the packet buffer.
*/
int pd_write_sym(int port, int bit_off, uint32_t val10);
/**
* Ensure that we have an edge after EOP and we end up at level 0,
* also fill the last byte.
*
* @param port USB-C port number
* @param bit_off current position in the packet buffer.
* @return new position in the packet buffer.
*/
int pd_write_last_edge(int port, int bit_off);
/**
* Dump the current PD packet on the console for debug.
*
* @param port USB-C port number
* @param msg context string.
*/
void pd_dump_packet(int port, const char *msg);
/**
* Change the TX data clock frequency.
*
* @param port USB-C port number
* @param freq frequency in hertz.
*/
void pd_set_clock(int port, int freq);
/* TX/RX callbacks */
/**
* Start sending over the wire the prepared packet.
*
* @param port USB-C port number
* @param polarity plug polarity (0=CC1, 1=CC2).
* @param bit_len size of the packet in bits.
*/
void pd_start_tx(int port, int polarity, int bit_len);
/**
* Set PD TX DMA to use circular mode. Call this before pd_start_tx() to
* continually loop over the transmit buffer given in pd_start_tx().
*
* @param port USB-C port number
*/
void pd_tx_set_circular_mode(int port);
/**
* Call when we are done sending a packet.
*
* @param port USB-C port number
* @param polarity plug polarity (0=CC1, 1=CC2).
*/
void pd_tx_done(int port, int polarity);
/**
* Check whether the PD reception is started.
*
* @param port USB-C port number
* @return true if the reception is on-going.
*/
int pd_rx_started(int port);
/**
* Suspend the PD task.
* @param port USB-C port number
* @param enable pass 0 to resume, anything else to suspend
*/
void pd_set_suspend(int port, int enable);
/* Callback when the hardware has detected an incoming packet */
void pd_rx_event(int port);
/* Start sampling the CC line for reception */
void pd_rx_start(int port);
/* Call when we are done reading a packet */
void pd_rx_complete(int port);
/* restart listening to the CC wire */
void pd_rx_enable_monitoring(int port);
/* stop listening to the CC wire during transmissions */
void pd_rx_disable_monitoring(int port);
/**
* Deinitialize the hardware used for PD.
*
* @param port USB-C port number
*/
void pd_hw_release(int port);
/**
* Initialize the hardware used for PD RX/TX.
*
* @param port USB-C port number
*/
void pd_hw_init(int port);
/* --- Protocol layer functions --- */
/**
* Get connected state
*
* @param port USB-C port number
* @return True if port is in connected state
*/
int pd_is_connected(int port);
/**
* Get port polarity.
*
* @param port USB-C port number
*/
int pd_get_polarity(int port);
/**
* Set the PD communication enabled flag. When communication is disabled,
* the port can still detect connection and source power but will not
* send or respond to any PD communication.
*
* @param enable Enable flag to set
*/
void pd_comm_enable(int enable);
/**
* Set the PD pings enabled flag. When source has negotiated power over
* PD successfully, it can optionally send pings periodically based on
* this enable flag.
*
* @param port USB-C port number
* @param enable Enable flag to set
*/
void pd_ping_enable(int port, int enable);
/* Issue PD soft reset */
void pd_soft_reset(void);
#endif /* __USB_PD_H */
|