Browse Source

Advertise Sink_Capabilities correctly

Now the Sink_Capabilities message contains a PDO from inside the range
if applicable, and a PPS APDO if we're using PD 3.0.
Clara Hobbs 4 years ago
parent
commit
a6e2475d0a
3 changed files with 65 additions and 24 deletions
  1. 19
    14
      lib/include/pd.h
  2. 43
    7
      src/device_policy_manager.c
  3. 3
    3
      src/shell.c

+ 19
- 14
lib/include/pd.h View File

@@ -177,20 +177,25 @@
177 177
 /* PD Source Fixed PDO voltage */
178 178
 #define PD_PDO_SRC_FIXED_VOLTAGE_GET(msg, i) (((msg)->obj[(i)] & PD_PDO_SRC_FIXED_VOLTAGE) >> PD_PDO_SRC_FIXED_VOLTAGE_SHIFT)
179 179
 
180
-/* PD Source Programmable Power Supply APDO */
181
-#define PD_APDO_SRC_PPS_MAX_VOLTAGE_SHIFT 17
182
-#define PD_APDO_SRC_PPS_MAX_VOLTAGE (0xFF << PD_APDO_SRC_PPS_MAX_VOLTAGE_SHIFT)
183
-#define PD_APDO_SRC_PPS_MIN_VOLTAGE_SHIFT 8
184
-#define PD_APDO_SRC_PPS_MIN_VOLTAGE (0xFF << PD_APDO_SRC_PPS_MIN_VOLTAGE_SHIFT)
185
-#define PD_APDO_SRC_PPS_CURRENT_SHIFT 0
186
-#define PD_APDO_SRC_PPS_CURRENT (0x7F << PD_APDO_SRC_PPS_CURRENT_SHIFT)
187
-
188
-/* PD Source Programmable Power Supply APDO voltages */
189
-#define PD_APDO_SRC_PPS_MAX_VOLTAGE_GET(msg, i) (((msg)->obj[(i)] & PD_APDO_SRC_PPS_MAX_VOLTAGE) >> PD_APDO_SRC_PPS_MAX_VOLTAGE_SHIFT)
190
-#define PD_APDO_SRC_PPS_MIN_VOLTAGE_GET(msg, i) (((msg)->obj[(i)] & PD_APDO_SRC_PPS_MIN_VOLTAGE) >> PD_APDO_SRC_PPS_MIN_VOLTAGE_SHIFT)
191
-
192
-/* PD Source Programmable Power Supply APDO current */
193
-#define PD_APDO_SRC_PPS_CURRENT_GET(msg, i) (((msg)->obj[(i)] & PD_APDO_SRC_PPS_CURRENT) >> PD_APDO_SRC_PPS_CURRENT_SHIFT)
180
+/* PD Programmable Power Supply APDO */
181
+#define PD_APDO_PPS_MAX_VOLTAGE_SHIFT 17
182
+#define PD_APDO_PPS_MAX_VOLTAGE (0xFF << PD_APDO_PPS_MAX_VOLTAGE_SHIFT)
183
+#define PD_APDO_PPS_MIN_VOLTAGE_SHIFT 8
184
+#define PD_APDO_PPS_MIN_VOLTAGE (0xFF << PD_APDO_PPS_MIN_VOLTAGE_SHIFT)
185
+#define PD_APDO_PPS_CURRENT_SHIFT 0
186
+#define PD_APDO_PPS_CURRENT (0x7F << PD_APDO_PPS_CURRENT_SHIFT)
187
+
188
+/* PD Programmable Power Supply APDO voltages */
189
+#define PD_APDO_PPS_MAX_VOLTAGE_GET(msg, i) (((msg)->obj[(i)] & PD_APDO_PPS_MAX_VOLTAGE) >> PD_APDO_PPS_MAX_VOLTAGE_SHIFT)
190
+#define PD_APDO_PPS_MIN_VOLTAGE_GET(msg, i) (((msg)->obj[(i)] & PD_APDO_PPS_MIN_VOLTAGE) >> PD_APDO_PPS_MIN_VOLTAGE_SHIFT)
191
+
192
+#define PD_APDO_PPS_MAX_VOLTAGE_SET(v) (((v) << PD_APDO_PPS_MAX_VOLTAGE_SHIFT) & PD_APDO_PPS_MAX_VOLTAGE)
193
+#define PD_APDO_PPS_MIN_VOLTAGE_SET(v) (((v) << PD_APDO_PPS_MIN_VOLTAGE_SHIFT) & PD_APDO_PPS_MIN_VOLTAGE)
194
+
195
+/* PD Programmable Power Supply APDO current */
196
+#define PD_APDO_PPS_CURRENT_GET(msg, i) (((msg)->obj[(i)] & PD_APDO_PPS_CURRENT) >> PD_APDO_PPS_CURRENT_SHIFT)
197
+
198
+#define PD_APDO_PPS_CURRENT_SET(i) (((i) << PD_APDO_PPS_CURRENT_SHIFT) & PD_APDO_PPS_CURRENT)
194 199
 
195 200
 /* TODO: other types of source PDO */
196 201
 

+ 43
- 7
src/device_policy_manager.c View File

@@ -138,9 +138,9 @@ bool pdbs_dpm_evaluate_capability(struct pdb_config *cfg,
138 138
              * its I is at least our desired I */
139 139
             if ((capabilities->obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_AUGMENTED
140 140
                     && (capabilities->obj[i] & PD_APDO_TYPE) == PD_APDO_TYPE_PPS
141
-                    && PD_APDO_SRC_PPS_MAX_VOLTAGE_GET(capabilities, i) >= PD_MV2PAV(scfg->v)
142
-                    && PD_APDO_SRC_PPS_MIN_VOLTAGE_GET(capabilities, i) <= PD_MV2PAV(scfg->v)
143
-                    && PD_APDO_SRC_PPS_CURRENT_GET(capabilities, i) >= PD_CA2PAI(scfg->i)) {
141
+                    && PD_APDO_PPS_MAX_VOLTAGE_GET(capabilities, i) >= PD_MV2PAV(scfg->v)
142
+                    && PD_APDO_PPS_MIN_VOLTAGE_GET(capabilities, i) <= PD_MV2PAV(scfg->v)
143
+                    && PD_APDO_PPS_CURRENT_GET(capabilities, i) >= PD_CA2PAI(scfg->i)) {
144 144
                 /* We got what we wanted, so build a request for that */
145 145
                 request->hdr = cfg->pe.hdr_template | PD_MSGTYPE_REQUEST
146 146
                     | PD_NUMOBJ(1);
@@ -231,14 +231,50 @@ void pdbs_dpm_get_sink_capability(struct pdb_config *cfg, union pd_msg *cap)
231 231
             | PD_PDO_SNK_FIXED_CURRENT_SET(DPM_MIN_CURRENT);
232 232
     }
233 233
 
234
-    /* Add a PDO for the desired power. */
235 234
     if (scfg != NULL) {
235
+        /* Add a PDO for the desired power. */
236 236
         cap->obj[numobj++] = PD_PDO_TYPE_FIXED
237 237
             | PD_PDO_SNK_FIXED_VOLTAGE_SET(PD_MV2PDV(scfg->v))
238 238
             | PD_PDO_SNK_FIXED_CURRENT_SET(scfg->i);
239
-        /* If we want more than 5 V, set the Higher Capability flag */
240
-        if (PD_MV2PDV(scfg->v) != PD_MV2PDV(5000)) {
241
-            cap->obj[0] |= PD_PDO_SNK_FIXED_HIGHER_CAP;
239
+
240
+        /* Get the PDO from the voltage range */
241
+        int8_t i = dpm_get_range_fixed_pdo_index(dpm_data->capabilities, scfg);
242
+
243
+        /* If it's vSafe5V, set our vSafe5V's current to what we want */
244
+        if (i == 0) {
245
+            cap->obj[0] &= ~PD_PDO_SNK_FIXED_CURRENT;
246
+            cap->obj[0] |= PD_PDO_SNK_FIXED_CURRENT_SET(scfg->i);
247
+        } else {
248
+            /* If we want more than 5 V, set the Higher Capability flag */
249
+            if (PD_MV2PDV(scfg->v) != PD_MV2PDV(5000)) {
250
+                cap->obj[0] |= PD_PDO_SNK_FIXED_HIGHER_CAP;
251
+            }
252
+
253
+            /* If the range PDO is a different voltage than the preferred
254
+             * voltage, add it to the array. */
255
+            if (i > 0 && PD_PDO_SRC_FIXED_VOLTAGE_GET(dpm_data->capabilities, i) != PD_MV2PDV(scfg->v)) {
256
+                cap->obj[numobj++] = PD_PDO_TYPE_FIXED
257
+                    | PD_PDO_SNK_FIXED_VOLTAGE_SET(PD_PDO_SRC_FIXED_VOLTAGE_GET(dpm_data->capabilities, i))
258
+                    | PD_PDO_SNK_FIXED_CURRENT_SET(PD_PDO_SRC_FIXED_CURRENT_GET(dpm_data->capabilities, i));
259
+            }
260
+
261
+            /* If we have three PDOs at this point, make sure the last two are
262
+             * sorted by voltage. */
263
+            if (numobj == 3
264
+                    && (cap->obj[1] & PD_PDO_SNK_FIXED_VOLTAGE)
265
+                    > (cap->obj[2] & PD_PDO_SNK_FIXED_VOLTAGE)) {
266
+                cap->obj[1] ^= cap->obj[2];
267
+                cap->obj[2] ^= cap->obj[1];
268
+                cap->obj[1] ^= cap->obj[2];
269
+            }
270
+        }
271
+
272
+        /* If we're using PD 3.0, add a PPS APDO for our desired voltage */
273
+        if ((cfg->pe._message->hdr & PD_HDR_SPECREV) >= PD_SPECREV_3_0) {
274
+            cap->obj[numobj++] = PD_PDO_TYPE_AUGMENTED | PD_APDO_TYPE_PPS
275
+                | PD_APDO_PPS_MAX_VOLTAGE_SET(PD_MV2PAV(scfg->v))
276
+                | PD_APDO_PPS_MIN_VOLTAGE_SET(PD_MV2PAV(scfg->v))
277
+                | PD_APDO_PPS_CURRENT_SET(PD_CA2PAI(scfg->i));
242 278
         }
243 279
     }
244 280
 

+ 3
- 3
src/shell.c View File

@@ -117,15 +117,15 @@ static void print_src_pps_apdo(BaseSequentialStream *chp, uint32_t pdo)
117 117
     chprintf(chp, "pps\r\n");
118 118
 
119 119
     /* Minimum voltage */
120
-    tmp = (pdo & PD_APDO_SRC_PPS_MIN_VOLTAGE) >> PD_APDO_SRC_PPS_MIN_VOLTAGE_SHIFT;
120
+    tmp = (pdo & PD_APDO_PPS_MIN_VOLTAGE) >> PD_APDO_PPS_MIN_VOLTAGE_SHIFT;
121 121
     chprintf(chp, "\tvmin: %d.%02d V\r\n", PD_PAV_V(tmp), PD_PAV_CV(tmp));
122 122
 
123 123
     /* Maximum voltage */
124
-    tmp = (pdo & PD_APDO_SRC_PPS_MAX_VOLTAGE) >> PD_APDO_SRC_PPS_MAX_VOLTAGE_SHIFT;
124
+    tmp = (pdo & PD_APDO_PPS_MAX_VOLTAGE) >> PD_APDO_PPS_MAX_VOLTAGE_SHIFT;
125 125
     chprintf(chp, "\tvmax: %d.%02d V\r\n", PD_PAV_V(tmp), PD_PAV_CV(tmp));
126 126
 
127 127
     /* Maximum current */
128
-    tmp = (pdo & PD_APDO_SRC_PPS_CURRENT) >> PD_APDO_SRC_PPS_CURRENT_SHIFT;
128
+    tmp = (pdo & PD_APDO_PPS_CURRENT) >> PD_APDO_PPS_CURRENT_SHIFT;
129 129
     chprintf(chp, "\ti: %d.%02d A\r\n", PD_PAI_A(tmp), PD_PAI_CA(tmp));
130 130
 }
131 131
 

Loading…
Cancel
Save