int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo) { int i; int sel_mv; int max_uw = 0; int max_i = -1; /* Get max power */ for (i = 0; i < cnt; i++) { int uw; int mv = ((src_caps[i] >> 10) & 0x3FF) * 50; if ((src_caps[i] & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) { uw = 250000 * (src_caps[i] & 0x3FF); } else { int ma = (src_caps[i] & 0x3FF) * 10; uw = ma * mv; } if ((uw > max_uw) && (mv <= max_mv)) { max_i = i; max_uw = uw; sel_mv = mv; } } if (max_i < 0) return -EC_ERROR_UNKNOWN; /* request all the power ... */ if ((src_caps[max_i] & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) { int uw = 250000 * (src_caps[i] & 0x3FF); *rdo = RDO_BATT(max_i + 1, uw/2, uw, 0); ccprintf("Request [%d] %dV %d/%d mW\n", max_i, sel_mv/1000, uw/1000, uw/1000); } else { int ma = 10 * (src_caps[max_i] & 0x3FF); *rdo = RDO_FIXED(max_i + 1, ma / 2, ma, 0); ccprintf("Request [%d] %dV %d/%d mA\n", max_i, sel_mv/1000, max_i, ma/2, ma); } return EC_SUCCESS; }
int pd_choose_voltage_common(int cnt, uint32_t *src_caps, uint32_t *rdo, uint32_t *curr_limit, uint32_t *supply_voltage, int choose_min) { int i; int sel_mv; int max_uw = 0; int max_ma; int max_i = -1; int max; uint32_t flags; /* Get max power */ for (i = 0; i < cnt; i++) { int uw; int mv = ((src_caps[i] >> 10) & 0x3FF) * 50; if ((src_caps[i] & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) { uw = 250000 * (src_caps[i] & 0x3FF); } else { int ma = (src_caps[i] & 0x3FF) * 10; uw = ma * mv; } if ((uw > max_uw) && (mv <= max_mv)) { max_i = i; max_uw = uw; sel_mv = mv; } /* * Choose the first entry if seaching for minimum, which will * always be vSafe5V. */ if (choose_min) break; } if (max_i < 0) return -EC_ERROR_UNKNOWN; /* build rdo for desired power */ if ((src_caps[max_i] & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) { int uw = 250000 * (src_caps[max_i] & 0x3FF); max = MIN(1000 * uw, MAX_POWER_MW); flags = (max < OPERATING_POWER_MW) ? RDO_CAP_MISMATCH : 0; max_ma = 1000 * max / sel_mv; *rdo = RDO_BATT(max_i + 1, max, max, flags); CPRINTF("Request [%d] %dV %dmW", max_i, sel_mv/1000, max); } else { int ma = 10 * (src_caps[max_i] & 0x3FF); /* * If we're choosing the minimum charge mode, limit our current * to what we can set with ilim PWM (500mA) */ max = MIN(ma, choose_min ? CONFIG_CHARGER_INPUT_CURRENT : MAX_CURRENT_MA); flags = (max * sel_mv) < (1000 * OPERATING_POWER_MW) ? RDO_CAP_MISMATCH : 0; max_ma = max; *rdo = RDO_FIXED(max_i + 1, max, max, flags); CPRINTF("Request [%d] %dV %dmA", max_i, sel_mv/1000, max); } /* Mismatch bit set if less power offered than the operating power */ if (flags & RDO_CAP_MISMATCH) CPRINTF(" Mismatch"); CPRINTF("\n"); *curr_limit = max_ma; *supply_voltage = sel_mv; return EC_SUCCESS; }