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
|
/* Copyright 2015 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 charger interface routines. This code assumes that CONFIG_CHARGE_MANAGER
* is defined and implemented.
* usb_charger_set_switches() must be implemented by a companion
* usb_switch driver.
* In addition, USB switch-specific usb_charger task or interrupt routine
* is necessary to update charge_manager with detected charger attributes.
*/
#include "charge_manager.h"
#include "common.h"
#include "console.h"
#include "gpio.h"
#include "hooks.h"
#include "task.h"
#include "usb_charge.h"
#include "usb_pd.h"
static void update_vbus_supplier(int port, int vbus_level)
{
struct charge_port_info charge;
/*
* If VBUS is low, or VBUS is high and we are not outputting VBUS
* ourselves, then update the VBUS supplier.
*/
if (!vbus_level || !usb_charger_port_is_sourcing_vbus(port)) {
charge.voltage = USB_CHARGER_VOLTAGE_MV;
charge.current = vbus_level ? USB_CHARGER_MIN_CURR_MA : 0;
charge_manager_update_charge(CHARGE_SUPPLIER_VBUS,
port,
&charge);
}
}
int usb_charger_port_is_sourcing_vbus(int port)
{
if (port == 0)
return gpio_get_level(GPIO_USB_C0_5V_EN);
#if CONFIG_USB_PD_PORT_COUNT >= 2
else if (port == 1)
return gpio_get_level(GPIO_USB_C1_5V_EN);
#endif
/* Not a valid port */
return 0;
}
void usb_charger_vbus_change(int port, int vbus_level)
{
/* If VBUS has transitioned low, notify PD module directly */
pd_vbus_low(port);
/* Update VBUS supplier and signal VBUS change to USB_CHG task */
update_vbus_supplier(port, vbus_level);
#if CONFIG_USB_PD_PORT_COUNT == 2
task_set_event(port ? TASK_ID_USB_CHG_P1 : TASK_ID_USB_CHG_P0,
USB_CHG_EVENT_VBUS, 0);
#else
task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_VBUS, 0);
#endif
}
static void usb_charger_init(void)
{
int i;
struct charge_port_info charge_none;
/* Initialize all charge suppliers to 0 */
charge_none.voltage = USB_CHARGER_VOLTAGE_MV;
charge_none.current = 0;
for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) {
charge_manager_update_charge(CHARGE_SUPPLIER_PROPRIETARY,
i,
&charge_none);
charge_manager_update_charge(CHARGE_SUPPLIER_BC12_CDP,
i,
&charge_none);
charge_manager_update_charge(CHARGE_SUPPLIER_BC12_DCP,
i,
&charge_none);
charge_manager_update_charge(CHARGE_SUPPLIER_BC12_SDP,
i,
&charge_none);
charge_manager_update_charge(CHARGE_SUPPLIER_OTHER,
i,
&charge_none);
#ifndef CONFIG_USB_PD_VBUS_DETECT_TCPC
/*
* Initialize VBUS supplier based on whether VBUS is present.
* For CONFIG_USB_PD_VBUS_DETECT_TCPC, usb_charger_vbus_change()
* will be called directly from TCPC alert.
*/
update_vbus_supplier(i, pd_snk_is_vbus_provided(i));
#endif
}
}
DECLARE_HOOK(HOOK_INIT, usb_charger_init, HOOK_PRIO_CHARGE_MANAGER_INIT + 1);
|