summaryrefslogtreecommitdiff
path: root/board/lucid/board.c
blob: fc83e71c7afa11888da9f7a5a891b9a55e0ea77f (plain)
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
/* 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.
 */
/* lucid board configuration */

#include "adc.h"
#include "adc_chip.h"
#include "charge_manager.h"
#include "charge_state.h"
#include "common.h"
#include "console.h"
#include "extpower.h"
#include "gpio.h"
#include "hooks.h"
#include "i2c.h"
#include "registers.h"
#include "task.h"
#include "usb_charge.h"
#include "util.h"

#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args)

void board_config_pre_init(void)
{
	/* enable SYSCFG clock */
	STM32_RCC_APB2ENR |= 1 << 0;
	/*
	 * the DMA mapping is :
	 *  Chan 2 : TIM1_CH1  (C0 RX)
	 *  Chan 3 : SPI1_TX   (C0 TX)
	 *  Chan 4 : USART1_TX
	 *  Chan 5 : USART1_RX
	 */

	/*
	 * Remap USART1 RX/TX DMA to match uart driver.
	 */
	STM32_SYSCFG_CFGR1 |= (1 << 9) | (1 << 10);
}

static void update_vbus_supplier(int vbus_level)
{
	struct charge_port_info charge;

	charge.voltage = USB_CHARGER_VOLTAGE_MV;
	charge.current = vbus_level ? USB_CHARGER_MIN_CURR_MA : 0;
	charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 0, &charge);
}

void vbus_evt(enum gpio_signal signal)
{
	/*
	 * We are using AC_PRESENT signal to detect VBUS presence since
	 * lucid only has one port and charging is always enabled.
	 */

	update_vbus_supplier(gpio_get_level(signal));

	if (task_start_called())
		task_wake(TASK_ID_PD);

	/* trigger AC present interrupt */
	extpower_interrupt(signal);
}

#include "gpio_list.h"

/* ADC channels */
const struct adc_t adc_channels[] = {
	/* USB PD CC lines sensing. Converted to mV (3300mV/4096). */
	[ADC_C0_CC1_PD] = {"C0_CC1_PD", 3300, 4096, 0, STM32_AIN(1)},
	[ADC_C0_CC2_PD] = {"C0_CC2_PD", 3300, 4096, 0, STM32_AIN(3)},

	/* Vbus sensing. Converted to mV, full ADC is equivalent to 30.25V. */
	[ADC_VBUS] = {"VBUS",  30250, 4096, 0, STM32_AIN(7)},
};
BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT);

/* I2C ports */
const struct i2c_port_t i2c_ports[] = {
	{"master", I2C_PORT_MASTER, 100,
		GPIO_MASTER_I2C_SCL, GPIO_MASTER_I2C_SDA},
	{"slave",  I2C_PORT_SLAVE, 100,
		GPIO_SLAVE_I2C_SCL, GPIO_SLAVE_I2C_SDA},
};
const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);

/* Initialize board. */
static void board_init(void)
{
	int i;
	struct charge_port_info charge_none;

	/* Initialize all BC1.2 charge suppliers to 0 */
	/*
	 * TODO: use built-in USB peripheral to detect BC1.2 suppliers an
	 * update charge manager.
	 */
	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);
	}

	/* Initialize VBUS supplier based on whether or not VBUS is present */
	update_vbus_supplier(gpio_get_level(GPIO_AC_PRESENT));
}
DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT);

int board_set_active_charge_port(int charge_port)
{
	/* Only one port and it's always enabled */
	return EC_SUCCESS;
}

void board_set_charge_limit(int charge_ma)
{
	int rv;

	charge_ma = MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT);
	rv = charge_set_input_current_limit(charge_ma);
	if (rv < 0)
		CPRINTS("Failed to set input current limit for PD");
}

/**
 * Custom physical check of battery presence.
 */
enum battery_present battery_is_present(void)
{
	return gpio_get_level(GPIO_BAT_PRESENT) ? BP_YES : BP_NO;
}

static int discharging_on_ac;

/**
 * Discharge battery when on AC power for factory test.
 */
int board_discharge_on_ac(int enable)
{
	int rv = charger_discharge_on_ac(enable);

	if (rv == EC_SUCCESS)
		discharging_on_ac = enable;

	return rv;
}

/**
 * Check if we are discharging while connected to AC
 */
int board_is_discharging_on_ac(void)
{
	return discharging_on_ac;
}