2 * linux/arch/arm/mach-s5pv310/charger-u1hd.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 (-5 * 1000)
33 #define SECBATTSPEC_TEMP_LOW_REC (0 * 1000)
35 #ifdef CONFIG_SENSORS_NTC_THERMISTOR
36 static unsigned int read_thermistor_uV(void)
38 struct s3c_adc_request req = {
42 #if defined(CONFIG_CHARGERCTRL_MAX8922)
43 .channel = 7, /* XADCAIN_7 */
44 #elif defined(CONFIG_CHARGERCTRL_MAX8997)
45 .channel = 6, /* XADCAIN_6 */
49 return s3c_adc_convert_uV(s3c_adc_get(&req));
52 static struct ntc_thermistor_platform_data ncp15wb473_pdata = {
53 .read_uV = read_thermistor_uV,
54 .pullup_uV = 3300000, /* VADC_3.3V_C210 */
55 .pullup_ohm = 100000, /* R613 in SLP 7 0105 */
56 .pulldown_ohm = 100000, /* R615 in SLP 7 0105 */
57 .connect = NTC_CONNECTED_GROUND,
60 struct platform_device u1hd_ncp15wb473_thermistor;
61 static const char *thermistor_dirent = "temp1_input";
62 static struct device_attribute *thermistor_attr;
63 static int __read_thermistor_mC(void)
70 if (thermistor_attr == NULL) {
72 struct sysfs_dirent *ntc_d;
74 ntc = &u1hd_ncp15wb473_thermistor.dev.kobj;
75 ntc_d = sysfs_get_dirent(ntc->sd,
76 get_ktype(ntc)->namespace(ntc),
78 if (!ntc_d || sysfs_type(ntc_d) != SYSFS_KOBJ_ATTR) {
80 dev_err(&u1hd_ncp15wb473_thermistor.dev, "Cannot init"
81 "ialize ncp15wb473's dirent info.\n");
86 thermistor_attr = container_of(ntc_d->s_attr.attr,
87 struct device_attribute, attr);
92 if (IS_ERR(thermistor_attr)) {
93 dev_warn(&u1hd_ncp15wb473_thermistor.dev, "Cannot read.\n");
97 count = thermistor_attr->show(&u1hd_ncp15wb473_thermistor.dev,
98 thermistor_attr, buf);
100 sscanf(buf, "%d", &mC);
104 thermistor_attr = ERR_PTR(err);
108 #else /* CONFIG_SENSORS_NTC_THERMISTOR */
109 static int __read_thermistor_mC(void)
111 return 25000; /* 25 mili-Centigrade */
113 #endif /* CONFIG_SENSORS_NTC_THERMISTOR */
115 static bool s3c_wksrc_rtc_alarm(void)
117 u32 reg = s3c_suspend_wakeup_stat & S5P_WAKEUP_STAT_WKSRC_MASK;
119 if ((reg & S5P_WAKEUP_STAT_RTCALARM) &&
120 !(reg & ~S5P_WAKEUP_STAT_RTCALARM))
121 return true; /* yes, it is */
126 enum temp_stat { TEMP_OK = 0, TEMP_HOT = 1, TEMP_COLD = -1 };
128 static int u1hd_thermistor_ck(int *mC)
130 static enum temp_stat state = TEMP_OK;
132 *mC = __read_thermistor_mC();
135 if (*mC >= SECBATTSPEC_TEMP_HIGH)
137 else if (*mC <= SECBATTSPEC_TEMP_LOW)
141 if (*mC <= SECBATTSPEC_TEMP_LOW)
143 else if (*mC < SECBATTSPEC_TEMP_HIGH_REC)
147 if (*mC >= SECBATTSPEC_TEMP_HIGH)
149 else if (*mC > SECBATTSPEC_TEMP_LOW_REC)
152 pr_err("%s has invalid state %d\n", __func__, state);
158 static char *u1hd_charger_stats[] = {
159 #if defined(CONFIG_CHARGERCTRL_MAX8922)
162 #if defined(CONFIG_CHARGERCTRL_MAX8997)
167 static struct regulator_bulk_data u1hd_chargers[] = {
168 { .supply = "vinchg2", },
170 static struct charger_irq u1hd_chg_irqs[] = {
171 { IRQ_PMIC_BASE + MAX8997_PMICIRQ_TOPOFFR, 0, CM_IRQ_BATT_FULL,
173 { IRQ_FUEL_BASE + MAX17042_IRQ_Battery_Removed, 0, CM_IRQ_BATT_OUT,
175 { IRQ_PMIC_BASE + MAX8997_PMICIRQ_CHGRSTF, 0, CM_IRQ_CHG_START_STOP,
177 { IRQ_PMIC_BASE + MAX8997_PMICIRQ_MBCHGTMEXPD, 0, CM_IRQ_OTHERS,
178 true, "CHG TIMEOUT" },
179 { IRQ_PMIC_BASE + MAX8997_PMICIRQ_DCINOVP, 0, CM_IRQ_OTHERS,
180 true, "CHG OVERVOLT" },
181 { IRQ_PMIC_BASE + MAX8997_PMICIRQ_CHGINS, 0, CM_IRQ_EXT_PWR_IN_OUT,
182 true, "CHG PWR Insert" },
183 { IRQ_PMIC_BASE + MAX8997_PMICIRQ_CHGRM, 0, CM_IRQ_EXT_PWR_IN_OUT,
184 true, "CHG PWR Remove" },
185 { 0, 0, 0, false, NULL },
188 static struct charger_desc u1hd_charger_desc = {
189 .psy_name = "battery",
190 .polling_interval_ms = 30000,
191 .polling_mode = CM_POLL_EXTERNAL_POWER_ONLY,
192 .fullbatt_vchkdrop_ms = 30000,
193 .fullbatt_vchkdrop_uV = 50000,
194 .fullbatt_uV = 4200000,
195 .battery_present = CM_CHARGER_STAT,
196 .psy_charger_stat = u1hd_charger_stats,
197 .charger_regulators = u1hd_chargers,
198 .num_charger_regulators = ARRAY_SIZE(u1hd_chargers),
199 .psy_fuel_gauge = "max17042_battery",
200 .irqs = u1hd_chg_irqs,
202 .is_temperature_error = u1hd_thermistor_ck,
203 .measure_ambient_temp = true,
204 .measure_battery_temp = true,
208 struct charger_global_desc u1hd_charger_g_desc = {
210 .is_rtc_only_wakeup_reason = s3c_wksrc_rtc_alarm,
211 .assume_timer_stops_in_suspend = true,
214 #ifdef CONFIG_SENSORS_NTC_THERMISTOR
215 struct platform_device u1hd_ncp15wb473_thermistor = {
216 .name = "ncp15wb473",
218 .platform_data = &ncp15wb473_pdata,
223 struct platform_device u1hd_charger_manager = {
224 .name = "charger-manager",
226 .platform_data = &u1hd_charger_desc,