Browse Source

Make requests from configured power

Now the DPM tests if the configuration holds a current or a power, and
if it's a power, it calculates current at the necessary voltage(s) based
on that power.  This is used when making requests, when advertising our
Sink_Capabilities, and when checking Type-C Current advertisements.
Clara Hobbs 4 years ago
parent
commit
974bd90424
2 changed files with 47 additions and 20 deletions
  1. 3
    3
      lib/include/pd.h
  2. 44
    17
      src/device_policy_manager.c

+ 3
- 3
lib/include/pd.h View File

@@ -328,9 +328,9 @@
328 328
 #define PD_PDV2MV(pdv) ((pdv) * 50)
329 329
 #define PD_PAV2MV(pav) ((pav) * 100)
330 330
 
331
-#define PD_MA2PDI(ma) ((ma) / 10)
332
-#define PD_MA2PAI(ma) ((ma) / 50)
333
-#define PD_CA2PAI(ca) ((ca) / 5)
331
+#define PD_MA2PDI(ma) (((ma) + 10 - 1) / 10)
332
+#define PD_MA2PAI(ma) (((ma) + 50 - 1) / 50)
333
+#define PD_CA2PAI(ca) (((ca) + 5 - 1) / 5)
334 334
 #define PD_PDI2MA(pdi) ((pdi) * 10)
335 335
 #define PD_PAI2MA(pai) ((pai) * 50)
336 336
 #define PD_PAI2CA(pai) ((pai) * 5)

+ 44
- 17
src/device_policy_manager.c View File

@@ -32,6 +32,21 @@
32 32
 #define DPM_MIN_CURRENT PD_MA2PDI(100)
33 33
 
34 34
 
35
+/*
36
+ * Return the current specified by the given PDBS configuration object at the
37
+ * given voltage (in millivolts), in centiamperes.
38
+ */
39
+static uint16_t dpm_get_current(struct pdbs_config *scfg, uint16_t mv)
40
+{
41
+    switch (scfg->flags & PDBS_CONFIG_FLAGS_CURRENT_DEFN) {
42
+        case PDBS_CONFIG_FLAGS_CURRENT_DEFN_I:
43
+            return scfg->i;
44
+        case PDBS_CONFIG_FLAGS_CURRENT_DEFN_P:
45
+            return (scfg->p * 1000 + mv - 1) / mv;
46
+    }
47
+}
48
+
49
+
35 50
 /*
36 51
  * Find the index of the first PDO from capabilities in the voltage range,
37 52
  * using the desired order.
@@ -59,10 +74,11 @@ static int8_t dpm_get_range_fixed_pdo_index(const union pd_msg *caps,
59 74
     while (0 <= i && i < numobj) {
60 75
         /* If we have a fixed PDO, its V is within our range, and its I is at
61 76
          * least our desired I */
77
+        uint16_t v = PD_PDO_SRC_FIXED_VOLTAGE_GET(caps->obj[i]);
62 78
         if ((caps->obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_FIXED
63
-                && PD_PDO_SRC_FIXED_CURRENT_GET(caps->obj[i]) >= scfg->i
64
-                && PD_PDO_SRC_FIXED_VOLTAGE_GET(caps->obj[i]) >= PD_MV2PDV(scfg->vmin)
65
-                && PD_PDO_SRC_FIXED_VOLTAGE_GET(caps->obj[i]) <= PD_MV2PDV(scfg->vmax)) {
79
+                && PD_PDO_SRC_FIXED_CURRENT_GET(caps->obj[i]) >= dpm_get_current(scfg, PD_PDV2MV(v))
80
+                && v >= PD_MV2PDV(scfg->vmin)
81
+                && v <= PD_MV2PDV(scfg->vmax)) {
66 82
             return i;
67 83
         }
68 84
         i += step;
@@ -100,6 +116,9 @@ bool pdbs_dpm_evaluate_capability(struct pdb_config *cfg,
100 116
     /* Get whether or not the power supply is constrained */
101 117
     dpm_data->_unconstrained_power = caps->obj[0] & PD_PDO_SRC_FIXED_UNCONSTRAINED;
102 118
 
119
+    /* Get the current we want */
120
+    uint16_t current = dpm_get_current(scfg, scfg->v);
121
+
103 122
     /* Make sure we have configuration */
104 123
     if (scfg != NULL && dpm_data->output_enabled) {
105 124
         /* Look at the PDOs to see if one matches our desires */
@@ -108,20 +127,20 @@ bool pdbs_dpm_evaluate_capability(struct pdb_config *cfg,
108 127
              * at least our desired I */
109 128
             if ((caps->obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_FIXED
110 129
                     && PD_PDO_SRC_FIXED_VOLTAGE_GET(caps->obj[i]) == PD_MV2PDV(scfg->v)
111
-                    && PD_PDO_SRC_FIXED_CURRENT_GET(caps->obj[i]) >= scfg->i) {
130
+                    && PD_PDO_SRC_FIXED_CURRENT_GET(caps->obj[i]) >= current) {
112 131
                 /* We got what we wanted, so build a request for that */
113 132
                 request->hdr = cfg->pe.hdr_template | PD_MSGTYPE_REQUEST
114 133
                     | PD_NUMOBJ(1);
115 134
                 if (scfg->flags & PDBS_CONFIG_FLAGS_GIVEBACK) {
116 135
                     /* GiveBack enabled */
117 136
                     request->obj[0] = PD_RDO_FV_MIN_CURRENT_SET(DPM_MIN_CURRENT)
118
-                        | PD_RDO_FV_CURRENT_SET(scfg->i)
137
+                        | PD_RDO_FV_CURRENT_SET(current)
119 138
                         | PD_RDO_NO_USB_SUSPEND | PD_RDO_GIVEBACK
120 139
                         | PD_RDO_OBJPOS_SET(i + 1);
121 140
                 } else {
122 141
                     /* GiveBack disabled */
123
-                    request->obj[0] = PD_RDO_FV_MAX_CURRENT_SET(scfg->i)
124
-                        | PD_RDO_FV_CURRENT_SET(scfg->i)
142
+                    request->obj[0] = PD_RDO_FV_MAX_CURRENT_SET(current)
143
+                        | PD_RDO_FV_CURRENT_SET(current)
125 144
                         | PD_RDO_NO_USB_SUSPEND | PD_RDO_OBJPOS_SET(i + 1);
126 145
                 }
127 146
                 if (dpm_data->usb_comms) {
@@ -140,13 +159,13 @@ bool pdbs_dpm_evaluate_capability(struct pdb_config *cfg,
140 159
                     && (caps->obj[i] & PD_APDO_TYPE) == PD_APDO_TYPE_PPS
141 160
                     && PD_APDO_PPS_MAX_VOLTAGE_GET(caps->obj[i]) >= PD_MV2PAV(scfg->v)
142 161
                     && PD_APDO_PPS_MIN_VOLTAGE_GET(caps->obj[i]) <= PD_MV2PAV(scfg->v)
143
-                    && PD_APDO_PPS_CURRENT_GET(caps->obj[i]) >= PD_CA2PAI(scfg->i)) {
162
+                    && PD_APDO_PPS_CURRENT_GET(caps->obj[i]) >= PD_CA2PAI(current)) {
144 163
                 /* We got what we wanted, so build a request for that */
145 164
                 request->hdr = cfg->pe.hdr_template | PD_MSGTYPE_REQUEST
146 165
                     | PD_NUMOBJ(1);
147 166
 
148 167
                 /* Build a request */
149
-                request->obj[0] = PD_RDO_PROG_CURRENT_SET(PD_CA2PAI(scfg->i))
168
+                request->obj[0] = PD_RDO_PROG_CURRENT_SET(PD_CA2PAI(current))
150 169
                     | PD_RDO_PROG_VOLTAGE_SET(PD_MV2PRV(scfg->v))
151 170
                     | PD_RDO_NO_USB_SUSPEND | PD_RDO_OBJPOS_SET(i + 1);
152 171
                 if (dpm_data->usb_comms) {
@@ -166,16 +185,18 @@ bool pdbs_dpm_evaluate_capability(struct pdb_config *cfg,
166 185
             /* We got what we wanted, so build a request for that */
167 186
             request->hdr = cfg->pe.hdr_template | PD_MSGTYPE_REQUEST
168 187
                 | PD_NUMOBJ(1);
188
+            /* Get the current we need at this voltage */
189
+            current = dpm_get_current(scfg, PD_PDV2MV(PD_PDO_SRC_FIXED_VOLTAGE_GET(caps->obj[i])));
169 190
             if (scfg->flags & PDBS_CONFIG_FLAGS_GIVEBACK) {
170 191
                 /* GiveBack enabled */
171 192
                 request->obj[0] = PD_RDO_FV_MIN_CURRENT_SET(DPM_MIN_CURRENT)
172
-                    | PD_RDO_FV_CURRENT_SET(scfg->i)
193
+                    | PD_RDO_FV_CURRENT_SET(current)
173 194
                     | PD_RDO_NO_USB_SUSPEND | PD_RDO_GIVEBACK
174 195
                     | PD_RDO_OBJPOS_SET(i + 1);
175 196
             } else {
176 197
                 /* GiveBack disabled */
177
-                request->obj[0] = PD_RDO_FV_MAX_CURRENT_SET(scfg->i)
178
-                    | PD_RDO_FV_CURRENT_SET(scfg->i)
198
+                request->obj[0] = PD_RDO_FV_MAX_CURRENT_SET(current)
199
+                    | PD_RDO_FV_CURRENT_SET(current)
179 200
                     | PD_RDO_NO_USB_SUSPEND | PD_RDO_OBJPOS_SET(i + 1);
180 201
             }
181 202
             if (dpm_data->usb_comms) {
@@ -232,10 +253,12 @@ void pdbs_dpm_get_sink_capability(struct pdb_config *cfg, union pd_msg *cap)
232 253
     }
233 254
 
234 255
     if (scfg != NULL) {
256
+        /* Get the current we want */
257
+        uint16_t current = dpm_get_current(scfg, scfg->v);
235 258
         /* Add a PDO for the desired power. */
236 259
         cap->obj[numobj++] = PD_PDO_TYPE_FIXED
237 260
             | PD_PDO_SNK_FIXED_VOLTAGE_SET(PD_MV2PDV(scfg->v))
238
-            | PD_PDO_SNK_FIXED_CURRENT_SET(scfg->i);
261
+            | PD_PDO_SNK_FIXED_CURRENT_SET(current);
239 262
 
240 263
         /* Get the PDO from the voltage range */
241 264
         int8_t i = dpm_get_range_fixed_pdo_index(dpm_data->capabilities, scfg);
@@ -243,7 +266,7 @@ void pdbs_dpm_get_sink_capability(struct pdb_config *cfg, union pd_msg *cap)
243 266
         /* If it's vSafe5V, set our vSafe5V's current to what we want */
244 267
         if (i == 0) {
245 268
             cap->obj[0] &= ~PD_PDO_SNK_FIXED_CURRENT;
246
-            cap->obj[0] |= PD_PDO_SNK_FIXED_CURRENT_SET(scfg->i);
269
+            cap->obj[0] |= PD_PDO_SNK_FIXED_CURRENT_SET(current);
247 270
         } else {
248 271
             /* If we want more than 5 V, set the Higher Capability flag */
249 272
             if (PD_MV2PDV(scfg->v) != PD_MV2PDV(5000)) {
@@ -274,7 +297,7 @@ void pdbs_dpm_get_sink_capability(struct pdb_config *cfg, union pd_msg *cap)
274 297
             cap->obj[numobj++] = PD_PDO_TYPE_AUGMENTED | PD_APDO_TYPE_PPS
275 298
                 | PD_APDO_PPS_MAX_VOLTAGE_SET(PD_MV2PAV(scfg->v))
276 299
                 | PD_APDO_PPS_MIN_VOLTAGE_SET(PD_MV2PAV(scfg->v))
277
-                | PD_APDO_PPS_CURRENT_SET(PD_CA2PAI(scfg->i));
300
+                | PD_APDO_PPS_CURRENT_SET(PD_CA2PAI(current));
278 301
         }
279 302
     }
280 303
 
@@ -317,18 +340,22 @@ bool pdbs_dpm_evaluate_typec_current(struct pdb_config *cfg,
317 340
 
318 341
     /* If we have no configuration or don't want 5 V, Type-C Current can't
319 342
      * possibly satisfy our needs */
343
+    /* TODO Check if 5 V is inside the voltage range */
320 344
     if (scfg == NULL || PD_MV2PDV(scfg->v) != PD_MV2PDV(5000)) {
321 345
         dpm_data->_capability_match = false;
322 346
         return false;
323 347
     }
324 348
 
349
+    /* Get the current we want */
350
+    uint16_t current = dpm_get_current(scfg, scfg->v);
351
+
325 352
     /* If 1.5 A is available and we want no more than that, great. */
326
-    if (tcc == fusb_tcc_1_5 && scfg->i <= 150) {
353
+    if (tcc == fusb_tcc_1_5 && current <= 150) {
327 354
         dpm_data->_capability_match = true;
328 355
         return true;
329 356
     }
330 357
     /* If 3 A is available and we want no more than that, that's great too. */
331
-    if (tcc == fusb_tcc_3_0 && scfg->i <= 300) {
358
+    if (tcc == fusb_tcc_3_0 && current <= 300) {
332 359
         dpm_data->_capability_match = true;
333 360
         return true;
334 361
     }

Loading…
Cancel
Save