2 * linux/arch/arm/mach-s5pv310/charger-u1.c
4 * MyungJoo Ham <myungjoo.ham@samsung.com>
6 * U1 Board Charger Support with Charger-Manager Framework
12 #include <linux/err.h>
13 #include <linux/platform_device.h>
14 #include <linux/ntc.h>
15 #include <linux/rtc/rtc-s3c.h>
16 #include <linux/regulator/consumer.h>
17 #include <linux/power/charger-manager.h>
18 #include <linux/power/max17042_battery.h>
19 #include <linux/mfd/max8997.h>
24 #include <mach/regs-pmu.h>
25 #include <mach/irqs.h>
27 #include "../../../fs/sysfs/sysfs.h"
29 /* Temperatures in milli-centigrade */
30 #define SECBATTSPEC_TEMP_HIGH (65 * 1000)
31 #define SECBATTSPEC_TEMP_HIGH_REC (43 * 1000)
32 #define SECBATTSPEC_TEMP_LOW (-3 * 1000)
33 #define SECBATTSPEC_TEMP_LOW_REC (0 * 1000)
35 #define SECBATT_CHANGE_MODE_TEMP (38 * 1000)
36 #define SECBATT_CHANGE_MODE_TEMP_REC (35 * 1000)
38 #ifdef CONFIG_SENSORS_NTC_THERMISTOR
39 static unsigned int read_thermistor_uV(void)
41 struct s3c_adc_request req = {
45 .channel = 7, /* XADCAIN_7 for LCD in u1 */
48 return s3c_adc_convert_uV(s3c_adc_get(&req));
51 static unsigned int read_thermistor_uV_pmic(void)
53 struct s3c_adc_request req = {
57 .channel = 6, /* XADCAIN_6 for PMIC in u1 */
60 return s3c_adc_convert_uV(s3c_adc_get(&req));
63 static struct ntc_thermistor_platform_data ncp15wb473_pdata = {
64 .read_uV = read_thermistor_uV,
65 .pullup_uV = 3300000, /* VADC_3.3V_C210 */
66 .pullup_ohm = 100000, /* R613 in SLP 7 0105 */
67 .pulldown_ohm = 100000, /* R615 in SLP 7 0105 */
68 .connect = NTC_CONNECTED_GROUND,
71 static struct ntc_thermistor_platform_data ncp15wb473_pdata_pmic = {
72 .read_uV = read_thermistor_uV_pmic,
73 .pullup_uV = 3300000, /* VADC_3.3V_C210 */
74 .pullup_ohm = 100000, /* R613 in SLP 7 0105 */
75 .pulldown_ohm = 100000, /* R615 in SLP 7 0105 */
76 .connect = NTC_CONNECTED_GROUND,
79 struct platform_device u1_ncp15wb473_thermistor;
80 static const char *thermistor_dirent = "temp1_input";
81 static struct device_attribute *thermistor_attr;
82 static int __read_thermistor_mC(void)
89 if (thermistor_attr == NULL) {
91 struct sysfs_dirent *ntc_d;
93 ntc = &u1_ncp15wb473_thermistor.dev.kobj;
94 ntc_d = sysfs_get_dirent(ntc->sd,
95 get_ktype(ntc)->namespace(ntc),
97 if (!ntc_d || sysfs_type(ntc_d) != SYSFS_KOBJ_ATTR) {
99 dev_err(&u1_ncp15wb473_thermistor.dev, "Cannot init"
100 "ialize ncp15wb473's dirent info.\n");
105 thermistor_attr = container_of(ntc_d->s_attr.attr,
106 struct device_attribute, attr);
111 if (IS_ERR(thermistor_attr)) {
112 dev_warn(&u1_ncp15wb473_thermistor.dev, "Cannot read.\n");
116 count = thermistor_attr->show(&u1_ncp15wb473_thermistor.dev,
117 thermistor_attr, buf);
118 WARN_ON(count >= 31);
119 sscanf(buf, "%d", &mC);
123 thermistor_attr = ERR_PTR(err);
127 #else /* CONFIG_SENSORS_NTC_THERMISTOR */
128 static int __read_thermistor_mC(void)
130 return 25000; /* 25 mili-Centigrade */
132 #endif /* CONFIG_SENSORS_NTC_THERMISTOR */
134 static bool s3c_wksrc_rtc_alarm(void)
136 u32 reg = s3c_suspend_wakeup_stat & S5P_WAKEUP_STAT_WKSRC_MASK;
138 if ((reg & S5P_WAKEUP_STAT_RTCALARM) &&
139 !(reg & ~S5P_WAKEUP_STAT_RTCALARM))
140 return true; /* yes, it is */
145 enum temp_stat { TEMP_OK = 0, TEMP_HOT = 1, TEMP_COLD = -1 };
147 static int u1_change_charge_mode(enum temp_stat state, int mC)
149 static struct regulator *regulator;
152 if (regulator == NULL) {
153 regulator = regulator_get(NULL, "vinchg2_mach");
154 if (IS_ERR_OR_NULL(regulator)) {
155 pr_err("%s : failed to get regulator\n", __func__);
162 if (state == TEMP_OK) {
164 if (mC >= SECBATT_CHANGE_MODE_TEMP)
165 regulator_set_current_limit(regulator, 395000, 450000);
168 if (mC <= SECBATT_CHANGE_MODE_TEMP_REC)
169 regulator_set_current_limit(regulator, 600000, 650000);
177 static int u1_thermistor_ck(int *mC)
179 static enum temp_stat state = TEMP_OK;
181 *mC = __read_thermistor_mC();
184 if (*mC >= SECBATTSPEC_TEMP_HIGH)
186 else if (*mC <= SECBATTSPEC_TEMP_LOW)
190 if (*mC <= SECBATTSPEC_TEMP_LOW)
192 else if (*mC < SECBATTSPEC_TEMP_HIGH_REC)
196 if (*mC >= SECBATTSPEC_TEMP_HIGH)
198 else if (*mC > SECBATTSPEC_TEMP_LOW_REC)
201 pr_err("%s has invalid state %d\n", __func__, state);
204 u1_change_charge_mode(state, *mC);
209 static char *u1_charger_stats[] = {
210 #if defined(CONFIG_CHARGERCTRL_MAX8922)
213 #if defined(CONFIG_CHARGERCTRL_MAX8997)
218 static struct regulator_bulk_data u1_chargers[] = {
219 { .supply = "vinchg2", },
221 static struct charger_irq u1_chg_irqs[] = {
222 { IRQ_PMIC_BASE + MAX8997_PMICIRQ_TOPOFFR, 0, CM_IRQ_BATT_FULL,
224 { IRQ_FUEL_BASE + MAX17042_IRQ_Battery_Removed, 0, CM_IRQ_BATT_OUT,
226 { IRQ_PMIC_BASE + MAX8997_PMICIRQ_CHGRSTF, 0, CM_IRQ_CHG_START_STOP,
228 { IRQ_PMIC_BASE + MAX8997_PMICIRQ_MBCHGTMEXPD, 0, CM_IRQ_OTHERS,
229 true, "CHG TIMEOUT" },
230 { IRQ_PMIC_BASE + MAX8997_PMICIRQ_DCINOVP, 0, CM_IRQ_OTHERS,
231 true, "CHG OVERVOLT" },
232 { IRQ_PMIC_BASE + MAX8997_PMICIRQ_CHGINS, 0, CM_IRQ_EXT_PWR_IN_OUT,
233 true, "CHG PWR Insert" },
234 { IRQ_PMIC_BASE + MAX8997_PMICIRQ_CHGRM, 0, CM_IRQ_EXT_PWR_IN_OUT,
235 true, "CHG PWR Remove" },
236 { 0, 0, 0, false, NULL },
239 static struct charger_desc u1_charger_desc = {
240 .psy_name = "battery",
241 .polling_interval_ms = 30000,
242 .polling_mode = CM_POLL_EXTERNAL_POWER_ONLY,
243 .fullbatt_vchkdrop_ms = 30000,
244 .fullbatt_vchkdrop_uV = 50000,
245 .fullbatt_uV = 4200000,
246 .battery_present = CM_CHARGER_STAT,
247 .psy_charger_stat = u1_charger_stats,
248 .charger_regulators = u1_chargers,
249 .num_charger_regulators = ARRAY_SIZE(u1_chargers),
250 .psy_fuel_gauge = "max17042_battery",
253 .is_temperature_error = u1_thermistor_ck,
254 .measure_ambient_temp = true,
255 .measure_battery_temp = true,
259 struct charger_global_desc u1_charger_g_desc = {
261 .is_rtc_only_wakeup_reason = s3c_wksrc_rtc_alarm,
262 .assume_timer_stops_in_suspend = true,
265 #ifdef CONFIG_SENSORS_NTC_THERMISTOR
266 struct platform_device u1_ncp15wb473_thermistor = {
267 .name = "ncp15wb473",
270 .platform_data = &ncp15wb473_pdata,
274 struct platform_device u1_ncp15wb473_thermistor_pmic = {
275 .name = "ncp15wb473",
278 .platform_data = &ncp15wb473_pdata_pmic,
284 struct platform_device u1_charger_manager = {
285 .name = "charger-manager",
287 .platform_data = &u1_charger_desc,