aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/power/charger-manager.h
blob: 95bca908ce31a325eb1ca3b056c2386632a7f5e1 (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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
/* linux/include/linux/power/charger-manager.h
 *
 * Copyright (C) 2011 Samsung Electronics Co., Ltd.
 * MyungJoo.Ham <myungjoo.ham@samsung.com>
 *
 * Charger Manager.
 * This framework enables to control and multiple chargers and to
 * monitor charging even in the context of suspend-to-RAM with
 * an interface combining the chargers.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
**/

#ifndef __SAMSUNG_DEV_CHARGER_H
#define __SAMSUNG_DEV_CHARGER_H

#include <linux/power_supply.h>
#include <linux/extcon.h>

enum data_source {
	CM_ASSUME_ALWAYS_TRUE,
	CM_ASSUME_ALWAYS_FALSE,
	CM_FUEL_GAUGE,
	CM_CHARGER_STAT,
};

enum cm_event_types {
	CM_EVENT_UNDESCRIBED = 0,
	CM_EVENT_BATT_FULL,
	CM_EVENT_BATT_IN,
	CM_EVENT_BATT_OUT,
	CM_EVENT_EXT_PWR_IN_OUT,
	CM_EVENT_CHG_START_STOP,
	CM_EVENT_OTHERS,
};

enum polling_modes {
	CM_POLL_DISABLE = 0,
	CM_POLL_ALWAYS,
	/* To use PWR-ONLY option, EXT_PWR_IN_OUT type irqs should exist */
	CM_POLL_EXTERNAL_POWER_ONLY,
	/* To use CHG-ONLY option, CHG_START_STOP type irqs should exist */
	CM_POLL_CHARGING_ONLY,
};

struct charger_global_desc {
	/*
	 * For in-suspend monitoring, suspend-again related data is
	 * required. These are used as global for Charger-Manager.
	 * They should work with no_irq with dpm_suspend()'ed environment.
	 *
	 * rtc is the name of RTC used to wakeup the system from
	 * suspend. Previously appointed alarm is saved and restored if
	 * enabled and the alarm time is later than now.
	 */
	char *rtc;

	/*
	 * If the system is waked up by waekup-sources other than the RTC or
	 * callbacks.setup provided with charger_global_desc, Charger Manager
	 * should recognize with is_rtc_only_wakeup_reason() returning false.
	 * If the RTC given to CM is the only wakeup reason,
	 * is_rtc_only_wakeup_reason should return true.
	 */
	bool (*is_rtc_only_wakeup_reason)(void);

	/*
	 * Assume that the jiffy timer stops in suspend-to-RAM.
	 * When enabled, CM does not rely on jiffies value in
	 * suspend_again and assumes that jiffies value does not
	 * change during suspend.
	 */
	bool assume_timer_stops_in_suspend;
};

#ifdef CONFIG_EXTCON
struct charger_cable {
	const char *extcon_name;
	const char *name;

	/*
	 * Set min/max current of regulator to protect over-current issue
	 * according to a kind of charger cable when cable is attached.
	 */
	int min_uA;
	int max_uA;

	/* The charger-manager use Exton framework*/
	struct extcon_specific_cable_nb extcon_dev;
	struct work_struct wq;
	struct notifier_block nb;

	/* The state of charger cable */
	bool attached;

	struct charger_regulator *charger;
	struct charger_manager *cm;
};

struct charger_regulator {
	/* The name of regulator for charging */
	const char *regulator_name;
	struct regulator *consumer;

	/*
	 * Store constraint information related to current limit,
	 * each cable have different condition for charging.
	 */
	struct charger_cable *cables;
	int num_cables;
};
#endif

struct charger_desc {
	/*
	 * The name of psy (power-supply-class) entry.
	 * If psy_name is NULL, "battery" is used.
	 */
	char *psy_name;

	/* The manager may poll with shorter interval, but not longer. */
	enum polling_modes polling_mode;
	unsigned int polling_interval_ms;

	/*
	 * Check voltage drop after the battery is fully charged.
	 * If it has dropped more than fullbatt_vchkdrop_uV after
	 * fullbatt_vchkdrop_ms, CM will restart charging.
	 */
	unsigned int fullbatt_vchkdrop_ms;
	unsigned int fullbatt_vchkdrop_uV;

	/*
	 * If it is not being charged and VBATT >= fullbatt_uV,
	 * it is assumed to be full. In order not to use this, set
	 * fullbatt_uV 0.
	 */
	unsigned int fullbatt_uV;

	/*
	 * How the data is picked up for "PRESENT"?
	 * Are we reading the value from chargers or fuel gauges?
	 */
	enum data_source battery_present;

	/*
	 * The power-supply entries of psy_charger_stat[i] shows "PRESENT",
	 * "ONLINE", "STATUS (Should notify at least FULL or NOT)" of the
	 * charger-i. "Charging/Discharging/NotCharging" of "STATUS" are
	 * optional and recommended.
	 */
	char **psy_charger_stat;

	/*
	 * The power-supply entries with VOLTAGE_NOW, CAPACITY,
	 * and "PRESENT".
	 */
	char *psy_fuel_gauge;

	int (*is_temperature_error)(int *mC);
	bool measure_ambient_temp;
	bool measure_battery_temp;

	int soc_margin;

	struct charger_regulator *charger_regulators;
	int num_charger_regulators;
};

#define PSY_NAME_MAX	30
struct charger_manager {
	struct list_head entry;
	struct device *dev;
	struct charger_desc *desc;

	struct power_supply *fuel_gauge;
	struct power_supply **charger_stat;

	bool cancel_suspend; /* if there is a pending charger event. */
	bool charger_enabled;

	unsigned long fullbatt_vchk_jiffies_at; /* 0 for N/A */
	unsigned int fullbatt_vchk_uV;
	struct delayed_work fullbatt_vchk_work;

	bool user_prohibit;
	int emergency_stop; /* Do not charge */
	int last_temp_mC;

	char psy_name_buf[PSY_NAME_MAX + 1]; /* Output to user */
	struct power_supply charger_psy;

	/*
	 * status saved entering a suspend and if the saved status is
	 * changed at suspend_again, suspend_again STOPs
	 */
	bool status_save_ext_pwr_inserted;
	bool status_save_batt;

	int batt_tmu_status;
};

/* In case IRQs cannot be given and notifications will be given. */
#ifdef CONFIG_CHARGER_MANAGER
extern void cm_notify_event(struct power_supply *psy, enum cm_event_types type,
			    char *msg); /* msg: optional */
extern struct charger_manager *get_charger_manager(char *psy_name);
extern int setup_charger_manager(struct charger_global_desc *gd);
extern bool is_charger_manager_active(void);
extern bool cm_suspend_again(void);
extern void cm_prohibit_charging(struct charger_manager *cm);
extern void cm_allow_charging(struct charger_manager *cm);
#else
static void __maybe_unused cm_notify_event(struct power_supply *psy,
					   enum cm_event_types type, char *msg)
{ }

static struct charger_manager __maybe_unused *get_charger_manager(
						char *psy_name)
{
	return NULL;
}

static void __maybe_unused setup_charger_manager(struct charger_global_desc *gd)
{ }

static bool __maybe_unused is_charger_manager_active(void)
{
	return false;
}

static bool __maybe_unused cm_suspend_again(void)
{
	return false;
}
static void __maybe_unused cm_prohibit_charging(struct charger_manager *cm) { }
static void __maybe_unused cm_allow_charging(struct charger_manager *cm) { }
#endif

#endif /* __SAMSUNG_DEV_CHARGER_H */