diff options
author | Richard Zhu <r65037@freescale.com> | 2008-03-12 10:27:26 +0800 |
---|---|---|
committer | Daniel Schaeffer <daniel.schaeffer@timesys.com> | 2008-08-25 15:20:43 -0400 |
commit | aba6a1b9f031fdf426c03c42c2cd1c55df0680d6 (patch) | |
tree | 825a32bee3030c7a6f3ef8e183497e89f26a939b | |
parent | 12afc0de99f62b780b97d9441fc577cd5fe1582a (diff) |
ENGR00068036 3DS pmic adc arbitration fix
Fix 3DS pmic adc arbitration fix and batt hw event support
Signed-off-by: Mark Zhou <b02241@freescale.com>
-rw-r--r-- | drivers/input/touchscreen/mxc_ts.c | 6 | ||||
-rw-r--r-- | drivers/mxc/pmic/Makefile | 1 | ||||
-rw-r--r-- | drivers/mxc/pmic/mc13783/pmic_adc.c | 58 | ||||
-rw-r--r-- | drivers/mxc/pmic/mc13783/pmic_adc_defs.h | 4 | ||||
-rw-r--r-- | drivers/mxc/pmic/mc13783/pmic_battery.c | 361 | ||||
-rw-r--r-- | drivers/mxc/pmic/mc13783/pmic_power.c | 34 | ||||
-rw-r--r-- | include/asm-arm/arch-mxc/pmic_battery.h | 42 | ||||
-rw-r--r-- | include/asm-arm/arch-mxc/pmic_status.h | 2 |
8 files changed, 446 insertions, 62 deletions
diff --git a/drivers/input/touchscreen/mxc_ts.c b/drivers/input/touchscreen/mxc_ts.c index 514f73082bfe..eefd4b9f5068 100644 --- a/drivers/input/touchscreen/mxc_ts.c +++ b/drivers/input/touchscreen/mxc_ts.c @@ -1,5 +1,5 @@ /* - * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2007-2008 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -49,8 +49,8 @@ static int ts_thread(void *arg) while (input_ts_installed) { try_to_freeze(); memset(&ts_sample, 0, sizeof(t_touch_screen)); - pmic_adc_get_touch_sample(&ts_sample, !wait); - + if (0 != pmic_adc_get_touch_sample(&ts_sample, !wait)) + continue; input_report_abs(mxc_inputdev, ABS_X, ts_sample.x_position); input_report_abs(mxc_inputdev, ABS_Y, ts_sample.y_position); input_report_abs(mxc_inputdev, ABS_PRESSURE, diff --git a/drivers/mxc/pmic/Makefile b/drivers/mxc/pmic/Makefile index d937cf72d69d..b4312cca7080 100644 --- a/drivers/mxc/pmic/Makefile +++ b/drivers/mxc/pmic/Makefile @@ -4,4 +4,3 @@ obj-y += core/ obj-$(CONFIG_MXC_PMIC_MC13783) += mc13783/ -obj-$(CONFIG_MXC_PMIC_SC55112) += sc55112/ diff --git a/drivers/mxc/pmic/mc13783/pmic_adc.c b/drivers/mxc/pmic/mc13783/pmic_adc.c index e29a1d254b3e..05874249b66e 100644 --- a/drivers/mxc/pmic/mc13783/pmic_adc.c +++ b/drivers/mxc/pmic/mc13783/pmic_adc.c @@ -93,6 +93,8 @@ static bool wait_ts; static bool monitor_en; static bool monitor_adc; static t_check_mode wcomp_mode; +static DECLARE_MUTEX(convert_mutex); + void (*monitoring_cb) (void); /*call back to be called when event is detected. */ static DECLARE_WAIT_QUEUE_HEAD(queue_adc_busy); @@ -159,7 +161,15 @@ static int pmic_adc_suspend(struct platform_device *pdev, pm_message_t state) static int pmic_adc_resume(struct platform_device *pdev) { /* nothing for mc13783 adc */ + unsigned int adc_0_reg, adc_1_reg; suspend_flag = 0; + + /* let interrupt of TSI again */ + adc_0_reg = ADC_WAIT_TSI_0; + CHECK_ERROR(pmic_write_reg(REG_ADC_0, adc_0_reg, PMIC_ALL_BITS)); + adc_1_reg = ADC_WAIT_TSI_1 | (ADC_BIS * adc_ts); + CHECK_ERROR(pmic_write_reg(REG_ADC_1, adc_1_reg, PMIC_ALL_BITS)); + while (swait > 0) { swait--; wake_up_interruptible(&suspendq); @@ -450,6 +460,9 @@ int pmic_adc_init(void) CHECK_ERROR(pmic_write_reg(REG_ADC_2, reg_value, PMIC_ALL_BITS)); CHECK_ERROR(pmic_write_reg(REG_ADC_3, DEF_ADC_3, PMIC_ALL_BITS)); CHECK_ERROR(pmic_write_reg(REG_ADC_4, reg_value, PMIC_ALL_BITS)); + reg_value = 0x001000; + CHECK_ERROR(pmic_write_reg(REG_ARBITRATION_PERIPHERAL_AUDIO, reg_value, + 0xFFFFFF)); data_ready_adc_1 = false; data_ready_adc_2 = false; @@ -554,11 +567,13 @@ PMIC_STATUS mc13783_adc_convert(t_adc_param * adc_param) /* configure adc to wait tsi interrupt */ INIT_COMPLETION(adc_tsi); pr_debug("mc13783 ADC - pmic_write_reg ....\n"); - adc_0_reg = 0x001c00 | (ADC_BIS * use_bis); + /*for ts don't use bis */ + adc_0_reg = 0x001c00 | (ADC_BIS * 0); pmic_event_unmask(EVENT_TSI); CHECK_ERROR(pmic_write_reg (REG_ADC_0, adc_0_reg, PMIC_ALL_BITS)); - adc_1_reg = 0x200001 | (ADC_BIS * adc_ts); + /*for ts don't use bis */ + adc_1_reg = 0x200001 | (ADC_BIS * 0); CHECK_ERROR(pmic_write_reg (REG_ADC_1, adc_1_reg, PMIC_ALL_BITS)); pr_debug("wait tsi ....\n"); @@ -566,7 +581,9 @@ PMIC_STATUS mc13783_adc_convert(t_adc_param * adc_param) wait_for_completion_interruptible(&adc_tsi); wait_ts = false; } - use_bis = mc13783_adc_request(); + if (adc_param->read_ts == false) + down(&convert_mutex); + use_bis = mc13783_adc_request(adc_param->read_ts); if (use_bis < 0) { pr_debug("process has received a signal and got interrupted\n"); return -EINTR; @@ -696,6 +713,9 @@ PMIC_STATUS mc13783_adc_convert(t_adc_param * adc_param) adc_param->ts_value.contact_resistance = adc_param->value[6]; } */ mc13783_adc_release(use_bis); + if (adc_param->read_ts == false) + up(&convert_mutex); + return PMIC_SUCCESS; } @@ -935,9 +955,12 @@ PMIC_STATUS pmic_adc_get_touch_mode(t_touch_mode * touch_mode) */ PMIC_STATUS pmic_adc_get_touch_sample(t_touch_screen * touch_sample, int wait) { - mc13783_adc_read_ts(touch_sample, wait); - pmic_adc_filter(touch_sample); - return PMIC_SUCCESS; + if (mc13783_adc_read_ts(touch_sample, wait) != 0) + return PMIC_ERROR; + if (0 == pmic_adc_filter(touch_sample)) + return PMIC_SUCCESS; + else + return PMIC_ERROR; } /*! @@ -962,7 +985,8 @@ PMIC_STATUS mc13783_adc_read_ts(t_touch_screen * ts_value, int wait_tsi) mc13783_adc_init_param(¶m); param.wait_tsi = wait_tsi; param.read_ts = true; - mc13783_adc_convert(¶m); + if (mc13783_adc_convert(¶m) != 0) + return PMIC_ERROR; /* check if x-y is ok */ if ((param.ts_value.x_position1 < TS_X_MAX) && (param.ts_value.x_position1 >= TS_X_MIN) && @@ -1038,16 +1062,22 @@ PMIC_STATUS pmic_adc_get_battery_current(t_conversion_mode mode, * @return This function returns index of ADC to be used (0 or 1) if successful. return -1 if error. */ -int mc13783_adc_request(void) +int mc13783_adc_request(bool read_ts) { int adc_index = -1; - if (((adc_dev[0] == ADC_USED) && (adc_dev[1] == ADC_USED))) { - /* all ADC is used wait... */ - wait_event(queue_adc_busy, 0); - } else if (adc_dev[0] == ADC_FREE) { + if (read_ts != 0) { + /*for ts we use bis=0 */ + if (adc_dev[0] == ADC_USED) + return -1; + /*no wait here */ adc_dev[0] = ADC_USED; adc_index = 0; - } else if (adc_dev[1] == ADC_FREE) { + } else { + /*for other adc use bis = 1 */ + if (adc_dev[1] == ADC_USED) { + return -1; + /*no wait here */ + } adc_dev[1] = ADC_USED; adc_index = 1; } @@ -1143,7 +1173,7 @@ PMIC_STATUS pmic_adc_active_comparator(unsigned char low, monitoring.channel = channel; monitoring.callback = (void *)callback; - use_bis = mc13783_adc_request(); + use_bis = mc13783_adc_request(false); if (use_bis < 0) { pr_debug("mc13783_adc : request error\n"); return PMIC_ERROR; diff --git a/drivers/mxc/pmic/mc13783/pmic_adc_defs.h b/drivers/mxc/pmic/mc13783/pmic_adc_defs.h index c2a282c829ca..db1b08232c77 100644 --- a/drivers/mxc/pmic/mc13783/pmic_adc_defs.h +++ b/drivers/mxc/pmic/mc13783/pmic_adc_defs.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2004-2008 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -283,7 +283,7 @@ static int pmic_adc_filter(t_touch_screen * ts_curr); * @return This function returns index of ADC to be used (0 or 1) if successful. return -1 if error. */ -int mc13783_adc_request(void); +int mc13783_adc_request(bool read_ts); /*! * This function is used to update buffer of touch screen value in read mode. diff --git a/drivers/mxc/pmic/mc13783/pmic_battery.c b/drivers/mxc/pmic/mc13783/pmic_battery.c index c8a6da093012..b3d737e13c48 100644 --- a/drivers/mxc/pmic/mc13783/pmic_battery.c +++ b/drivers/mxc/pmic/mc13783/pmic_battery.c @@ -34,6 +34,11 @@ #include "pmic_battery_defs.h" +#include <asm/arch/pmic_power.h> +#ifdef MXC_HWEVENT +#include <../drivers/mxc/hw_event/mxc_hw_event.h> +#endif + static int pmic_battery_major; /*! @@ -71,6 +76,89 @@ EXPORT_SYMBOL(pmic_batt_set_5k_pull); EXPORT_SYMBOL(pmic_batt_event_subscribe); EXPORT_SYMBOL(pmic_batt_event_unsubscribe); +static DECLARE_MUTEX(count_mutex); /* open count mutex */ +static int open_count; /* open count for device file */ + +/*! + * Callback function for events, we want on MGN board + */ +static void callback_chg_detect(void) +{ +#ifdef MXC_HWEVENT + t_sensor_bits sensor; + struct mxc_hw_event event = { HWE_BAT_CHARGER_PLUG, 0 }; + + pr_debug("In callback_chg_detect\n"); + + /* get sensor values */ + pmic_get_sensors(&sensor); + + pr_debug("Callback, charger detect:%d\n", sensor.sense_chgdets); + + if (sensor.sense_chgdets) + event.args = 1; + else + event.args = 0; + /* send hardware event */ + hw_event_send(HWE_DEF_PRIORITY, event); +#endif +} + +static void callback_low_battery(void) +{ +#ifdef MXC_HWEVENT + struct mxc_hw_event event = { HWE_BAT_BATTERY_LOW, 0 }; + + pr_debug("In callback_low_battery\n"); + /* send hardware event */ + hw_event_send(HWE_DEF_PRIORITY, event); +#endif +} + +static void callback_power_fail(void) +{ +#ifdef MXC_HWEVENT + struct mxc_hw_event event = { HWE_BAT_POWER_FAILED, 0 }; + + pr_debug("In callback_power_fail\n"); + /* send hardware event */ + hw_event_send(HWE_DEF_PRIORITY, event); +#endif +} + +static void callback_chg_overvoltage(void) +{ +#ifdef MXC_HWEVENT + struct mxc_hw_event event = { HWE_BAT_CHARGER_OVERVOLTAGE, 0 }; + + pr_debug("In callback_chg_overvoltage\n"); + /* send hardware event */ + hw_event_send(HWE_DEF_PRIORITY, event); +#endif +} + +static void callback_chg_full(void) +{ +#ifdef MXC_HWEVENT + t_sensor_bits sensor; + struct mxc_hw_event event = { HWE_BAT_CHARGER_FULL, 0 }; + + pr_debug("In callback_chg_full\n"); + + /* disable charge function */ + pmic_batt_disable_charger(BATT_MAIN_CHGR); + + /* get charger sensor */ + pmic_get_sensors(&sensor); + + /* if did not detect the charger */ + if (sensor.sense_chgdets) + return; + /* send hardware event */ + hw_event_send(HWE_DEF_PRIORITY, event); +#endif +} + /*! * This is the suspend of power management for the pmic battery API. * It suports SAVE and POWER_DOWN state. @@ -131,9 +219,8 @@ PMIC_STATUS pmic_batt_enable_charger(t_batt_charger chgr, mask = 0; reg = 0; - if (suspend_flag == 1) { + if (suspend_flag == 1) return PMIC_ERROR; - } switch (chgr) { case BATT_MAIN_CHGR: @@ -183,10 +270,8 @@ PMIC_STATUS pmic_batt_disable_charger(t_batt_charger chgr) mask = 0; reg = 0; - if (suspend_flag == 1) { + if (suspend_flag == 1) return PMIC_ERROR; - } - switch (chgr) { case BATT_MAIN_CHGR: val = BITFVAL(MC13783_BATT_DAC_DAC, 0) | @@ -237,9 +322,8 @@ PMIC_STATUS pmic_batt_set_charger(t_batt_charger chgr, mask = 0; reg = 0; - if (suspend_flag == 1) { + if (suspend_flag == 1) return PMIC_ERROR; - } switch (chgr) { case BATT_MAIN_CHGR: @@ -287,9 +371,8 @@ PMIC_STATUS pmic_batt_get_charger_setting(t_batt_charger chgr, reg = 0; - if (suspend_flag == 1) { + if (suspend_flag == 1) return PMIC_ERROR; - } switch (chgr) { case BATT_MAIN_CHGR: @@ -329,6 +412,93 @@ PMIC_STATUS pmic_batt_get_charger_setting(t_batt_charger chgr, } /*! + * This function is retrives the main battery voltage. + * + * @param b_voltage Output parameter for voltage setting. + * + * @return This function returns PMIC_SUCCESS if successful. + */ +PMIC_STATUS pmic_batt_get_batt_voltage(unsigned short *b_voltage) +{ + t_channel channel; + unsigned short result[8]; + + if (suspend_flag == 1) + return PMIC_ERROR; + channel = BATTERY_VOLTAGE; + CHECK_ERROR(pmic_adc_convert(channel, result)); + *b_voltage = result[0]; + + return PMIC_SUCCESS; +} + +/*! + * This function is retrives the main battery current. + * + * @param b_current Output parameter for current setting. + * + * @return This function returns PMIC_SUCCESS if successful. + */ +PMIC_STATUS pmic_batt_get_batt_current(unsigned short *b_current) +{ + t_channel channel; + unsigned short result[8]; + + if (suspend_flag == 1) + return PMIC_ERROR; + + channel = BATTERY_CURRENT; + CHECK_ERROR(pmic_adc_convert(channel, result)); + *b_current = result[0]; + + return PMIC_SUCCESS; +} + +/*! + * This function is retrives the main battery temperature. + * + * @param b_temper Output parameter for temperature setting. + * + * @return This function returns PMIC_SUCCESS if successful. + */ +PMIC_STATUS pmic_batt_get_batt_temperature(unsigned short *b_temper) +{ + t_channel channel; + unsigned short result[8]; + + if (suspend_flag == 1) + return PMIC_ERROR; + + channel = GEN_PURPOSE_AD5; + CHECK_ERROR(pmic_adc_convert(channel, result)); + *b_temper = result[0]; + + return PMIC_SUCCESS; +} + +/*! + * This function is retrives the main battery charging voltage. + * + * @param c_voltage Output parameter for charging voltage setting. + * + * @return This function returns PMIC_SUCCESS if successful. + */ +PMIC_STATUS pmic_batt_get_charge_voltage(unsigned short *c_voltage) +{ + t_channel channel; + unsigned short result[8]; + + if (suspend_flag == 1) + return PMIC_ERROR; + + channel = CHARGE_VOLTAGE; + CHECK_ERROR(pmic_adc_convert(channel, result)); + *c_voltage = result[0]; + + return PMIC_SUCCESS; +} + +/*! * This function is retrives the main battery charging current. * * @param c_current Output parameter for charging current setting. @@ -340,9 +510,8 @@ PMIC_STATUS pmic_batt_get_charge_current(unsigned short *c_current) t_channel channel; unsigned short result[8]; - if (suspend_flag == 1) { + if (suspend_flag == 1) return PMIC_ERROR; - } channel = CHARGE_CURRENT; CHECK_ERROR(pmic_adc_convert(channel, result)); @@ -382,9 +551,8 @@ PMIC_STATUS pmic_batt_bp_enable_eol(t_bp_threshold typical) { unsigned int val, mask; - if (suspend_flag == 1) { + if (suspend_flag == 1) return PMIC_ERROR; - } val = BITFVAL(MC13783_BATT_DAC_EOL_CMP_EN, MC13783_BATT_DAC_EOL_CMP_EN_ENABLE) | @@ -406,9 +574,8 @@ PMIC_STATUS pmic_batt_disable_eol(void) { unsigned int val, mask; - if (suspend_flag == 1) { + if (suspend_flag == 1) return PMIC_ERROR; - } val = BITFVAL(MC13783_BATT_DAC_EOL_CMP_EN, MC13783_BATT_DAC_EOL_CMP_EN_DISABLE); @@ -430,9 +597,9 @@ PMIC_STATUS pmic_batt_disable_eol(void) PMIC_STATUS pmic_batt_set_out_control(t_control control) { unsigned int val, mask; - if (suspend_flag == 1) { + if (suspend_flag == 1) return PMIC_ERROR; - } + switch (control) { case CONTROL_HARDWARE: val = BITFVAL(MC13783_BATT_DAC_FETOVRD_EN, 0) | @@ -471,12 +638,12 @@ PMIC_STATUS pmic_batt_set_threshold(int threshold) { unsigned int val, mask; - if (suspend_flag == 1) { + if (suspend_flag == 1) return PMIC_ERROR; - } - if (threshold > BAT_THRESHOLD_MAX) { + + if (threshold > BAT_THRESHOLD_MAX) return PMIC_PARAMETER_ERROR; - } + val = BITFVAL(MC13783_BATT_DAC_OVCTRL, threshold); mask = BITFMASK(MC13783_BATT_DAC_OVCTRL); CHECK_ERROR(pmic_write_reg(REG_CHARGER, val, mask)); @@ -495,9 +662,8 @@ PMIC_STATUS pmic_batt_led_control(bool on) { unsigned val, mask; - if (suspend_flag == 1) { + if (suspend_flag == 1) return PMIC_ERROR; - } val = BITFVAL(MC13783_BATT_DAC_LED_EN, on); mask = BITFMASK(MC13783_BATT_DAC_LED_EN); @@ -519,9 +685,8 @@ PMIC_STATUS pmic_batt_set_reverse_supply(bool enable) { unsigned val, mask; - if (suspend_flag == 1) { + if (suspend_flag == 1) return PMIC_ERROR; - } val = BITFVAL(MC13783_BATT_DAC_REVERSE_SUPPLY, enable); mask = BITFMASK(MC13783_BATT_DAC_REVERSE_SUPPLY); @@ -543,9 +708,8 @@ PMIC_STATUS pmic_batt_set_unregulated(bool enable) { unsigned val, mask; - if (suspend_flag == 1) { + if (suspend_flag == 1) return PMIC_ERROR; - } val = BITFVAL(MC13783_BATT_DAC_UNREGULATED, enable); mask = BITFMASK(MC13783_BATT_DAC_UNREGULATED); @@ -568,9 +732,8 @@ PMIC_STATUS pmic_batt_set_5k_pull(bool enable) { unsigned val, mask; - if (suspend_flag == 1) { + if (suspend_flag == 1) return PMIC_ERROR; - } val = BITFVAL(MC13783_BATT_DAC_5K, enable); mask = BITFMASK(MC13783_BATT_DAC_5K); @@ -598,7 +761,7 @@ PMIC_STATUS mc13783_battery_event(t_batt_event event, void *callback, bool sub) bat_callback.param = NULL; switch (event) { case BAT_IT_CHG_DET: - bat_event = EVENT_WLOWI; + bat_event = EVENT_CHGDETI; break; case BAT_IT_CHG_OVERVOLT: bat_event = EVENT_CHGOVI; @@ -619,9 +782,9 @@ PMIC_STATUS mc13783_battery_event(t_batt_event event, void *callback, bool sub) return PMIC_PARAMETER_ERROR; } if (sub == true) { - CHECK_ERROR(pmic_event_subscribe(event, bat_callback)); + CHECK_ERROR(pmic_event_subscribe(bat_event, bat_callback)); } else { - CHECK_ERROR(pmic_event_unsubscribe(event, bat_callback)); + CHECK_ERROR(pmic_event_unsubscribe(bat_event, bat_callback)); } return 0; } @@ -636,9 +799,9 @@ PMIC_STATUS mc13783_battery_event(t_batt_event event, void *callback, bool sub) */ PMIC_STATUS pmic_batt_event_subscribe(t_batt_event event, void *callback) { - if (suspend_flag == 1) { + if (suspend_flag == 1) return PMIC_ERROR; - } + return mc13783_battery_event(event, callback, true); } @@ -652,9 +815,9 @@ PMIC_STATUS pmic_batt_event_subscribe(t_batt_event event, void *callback) */ PMIC_STATUS pmic_batt_event_unsubscribe(t_batt_event event, void *callback) { - if (suspend_flag == 1) { + if (suspend_flag == 1) return PMIC_ERROR; - } + return mc13783_battery_event(event, callback, false); } @@ -672,6 +835,7 @@ static int pmic_battery_ioctl(struct inode *inode, struct file *file, { t_charger_setting *chgr_setting = NULL; unsigned short c_current; + unsigned int bc_info; t_eol_setting *eol_setting; if (_IOC_TYPE(cmd) != 'p') @@ -747,12 +911,58 @@ static int pmic_battery_ioctl(struct inode *inode, struct file *file, kfree(chgr_setting); break; + case PMIC_BATT_GET_CHARGER_SENSOR: + { + t_sensor_bits sensor; + pmic_get_sensors(&sensor); + if (copy_to_user + ((unsigned int *)arg, &sensor.sense_chgdets, + sizeof(unsigned int))) + return -EFAULT; + + break; + } + case PMIC_BATT_GET_BATTERY_VOLTAGE: + CHECK_ERROR(pmic_batt_get_batt_voltage(&c_current)); + bc_info = (unsigned int)c_current * 2300 / 1023 + 2400; + if (copy_to_user((unsigned int *)arg, &bc_info, + sizeof(unsigned int))) + return -EFAULT; + + break; + + case PMIC_BATT_GET_BATTERY_CURRENT: + CHECK_ERROR(pmic_batt_get_batt_current(&c_current)); + bc_info = (unsigned int)c_current * 5750 / 1023; + if (copy_to_user((unsigned int *)arg, &bc_info, + sizeof(unsigned int))) + return -EFAULT; + break; + + case PMIC_BATT_GET_BATTERY_TEMPERATURE: + CHECK_ERROR(pmic_batt_get_batt_temperature(&c_current)); + bc_info = (unsigned int)c_current; + if (copy_to_user((unsigned int *)arg, &bc_info, + sizeof(unsigned int))) + return -EFAULT; + + break; + + case PMIC_BATT_GET_CHARGER_VOLTAGE: + CHECK_ERROR(pmic_batt_get_charge_voltage(&c_current)); + bc_info = (unsigned int)c_current * 23000 / 1023; + if (copy_to_user((unsigned int *)arg, &bc_info, + sizeof(unsigned int))) + return -EFAULT; + + break; + case PMIC_BATT_GET_CHARGER_CURRENT: CHECK_ERROR(pmic_batt_get_charge_current(&c_current)); - if (copy_to_user((unsigned char *)arg, &c_current, - sizeof(unsigned char *))) { + bc_info = (unsigned int)c_current * 5750 / 1023; + if (copy_to_user((unsigned int *)arg, &bc_info, + sizeof(unsigned int))) return -EFAULT; - } break; @@ -821,7 +1031,60 @@ static int pmic_battery_open(struct inode *inode, struct file *file) return -ERESTARTSYS; } } + + /* check open count, if open firstly, register callbacks */ + down(&count_mutex); + if (open_count++ > 0) { + up(&count_mutex); + return 0; + } + + pr_debug("Subscribe the callbacks\n"); + /* register battery event callback */ + if (pmic_batt_event_subscribe(BAT_IT_CHG_DET, callback_chg_detect)) { + pr_debug("Failed to subscribe the charger detect callback\n"); + goto event_err1; + } + if (pmic_power_event_sub(PWR_IT_LOBATLI, callback_power_fail)) { + pr_debug("Failed to subscribe the power failed callback\n"); + goto event_err2; + } + if (pmic_power_event_sub(PWR_IT_LOBATHI, callback_low_battery)) { + pr_debug("Failed to subscribe the low battery callback\n"); + goto event_err3; + } + if (pmic_batt_event_subscribe + (BAT_IT_CHG_OVERVOLT, callback_chg_overvoltage)) { + pr_debug("Failed to subscribe the low battery callback\n"); + goto event_err4; + } + if (pmic_batt_event_subscribe + (BAT_IT_BELOW_THRESHOLD, callback_chg_full)) { + pr_debug("Failed to subscribe the charge full callback\n"); + goto event_err5; + } + + up(&count_mutex); + return 0; + + /* un-subscribe the event callbacks */ +event_err5: + pmic_batt_event_unsubscribe(BAT_IT_CHG_OVERVOLT, + callback_chg_overvoltage); +event_err4: + pmic_power_event_unsub(PWR_IT_LOBATHI, callback_low_battery); +event_err3: + pmic_power_event_unsub(PWR_IT_LOBATLI, callback_power_fail); +event_err2: + pmic_batt_event_unsubscribe(BAT_IT_CHG_DET, callback_chg_detect); +event_err1: + + open_count--; + up(&count_mutex); + + return -EFAULT; + } /*! @@ -840,6 +1103,23 @@ static int pmic_battery_release(struct inode *inode, struct file *file) return -ERESTARTSYS; } } + + /* check open count, if open firstly, register callbacks */ + down(&count_mutex); + if (--open_count == 0) { + /* unregister these event callback */ + pr_debug("Unsubscribe the callbacks\n"); + pmic_batt_event_unsubscribe(BAT_IT_BELOW_THRESHOLD, + callback_chg_full); + pmic_batt_event_unsubscribe(BAT_IT_CHG_OVERVOLT, + callback_chg_overvoltage); + pmic_power_event_unsub(PWR_IT_LOBATHI, callback_low_battery); + pmic_power_event_unsub(PWR_IT_LOBATLI, callback_power_fail); + pmic_batt_event_unsubscribe(BAT_IT_CHG_DET, + callback_chg_detect); + } + up(&count_mutex); + return 0; } @@ -888,6 +1168,9 @@ static int pmic_battery_probe(struct platform_device *pdev) goto err_out2; } + pmic_batt_led_control(true); + pmic_batt_set_5k_pull(true); + printk(KERN_INFO "PMIC Battery successfully probed\n"); return ret; diff --git a/drivers/mxc/pmic/mc13783/pmic_power.c b/drivers/mxc/pmic/mc13783/pmic_power.c index 133e8014fa13..40630332a3ab 100644 --- a/drivers/mxc/pmic/mc13783/pmic_power.c +++ b/drivers/mxc/pmic/mc13783/pmic_power.c @@ -21,7 +21,7 @@ /* * Includes */ - +#define DEBUG #include <linux/platform_device.h> #include <asm/ioctl.h> #include <asm/arch/pmic_power.h> @@ -29,6 +29,14 @@ #include "pmic_power_defs.h" +#ifdef CONFIG_MXC_HWEVENT +#include <../drivers/mxc/hw_event/mxc_hw_event.h> +#endif + +#include <asm/mach-types.h> + +#define MC13783_REGCTRL_GPOx_MASK 0x18000 + static bool VBKUP1_EN = false; static bool VBKUP2_EN = false; @@ -3036,6 +3044,26 @@ PMIC_STATUS pmic_power_event_unsub(t_pwr_int event, void *callback) return pmic_power_event(event, callback, false); } +void pmic_power_key_callback(void) +{ +#ifdef MXC_HWEVENT + /*read the power key is pressed or up */ + t_sensor_bits sense; + struct mxc_hw_event event = { HWE_POWER_KEY, 0 }; + + pmic_get_sensors(&sense); + if (sense.sense_onofd1s) { + pr_debug("PMIC Power key up\n"); + event.args = PWRK_UNPRESS; + } else { + pr_debug("PMIC Power key pressed\n"); + event.args = PWRK_PRESS; + } + /* send hw event */ + hw_event_send(HWE_DEF_PRIORITY, event); +#endif +} + /* * Init and Exit */ @@ -3059,10 +3087,12 @@ static struct platform_driver pmic_power_driver_ldm = { static int __init pmic_power_init(void) { pr_debug("PMIC Power driver loading..\n"); + pmic_power_event_sub(PWR_IT_ONOFD1I, pmic_power_key_callback); return platform_driver_register(&pmic_power_driver_ldm); } static void __exit pmic_power_exit(void) { + pmic_power_event_unsub(PWR_IT_ONOFD1I, pmic_power_key_callback); platform_driver_unregister(&pmic_power_driver_ldm); pr_debug("PMIC Power driver successfully unloaded\n"); } @@ -3071,7 +3101,7 @@ static void __exit pmic_power_exit(void) * Module entry points */ -subsys_initcall(pmic_power_init); +subsys_initcall_sync(pmic_power_init); module_exit(pmic_power_exit); MODULE_DESCRIPTION("pmic_power driver"); diff --git a/include/asm-arm/arch-mxc/pmic_battery.h b/include/asm-arm/arch-mxc/pmic_battery.h index 39805b72e530..61dbdfc023c4 100644 --- a/include/asm-arm/arch-mxc/pmic_battery.h +++ b/include/asm-arm/arch-mxc/pmic_battery.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2004-2008 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -85,6 +85,32 @@ * Argument type: int */ #define PMIC_BATT_SET_THRESHOLD _IOW('p', 0xc9, int) + +/*! + * Get the charger voltage. + * Argument type: int + */ +#define PMIC_BATT_GET_CHARGER_VOLTAGE _IOR('p', 0xca, int) +/*! + * Get the battery voltage. + * Argument type: int + */ +#define PMIC_BATT_GET_BATTERY_VOLTAGE _IOR('p', 0xcb, int) +/*! + * Get the battery current. + * Argument type: int + */ +#define PMIC_BATT_GET_BATTERY_CURRENT _IOR('p', 0xcc, int) +/*! + * Get the charger sensor. + * Argument type: int + */ +#define PMIC_BATT_GET_CHARGER_SENSOR _IOR('p', 0xcd, int) +/*! + * Get the battery temperature. + * Argument type: int + */ +#define PMIC_BATT_GET_BATTERY_TEMPERATURE _IOR('p', 0xce, int) /*! @} */ /*! @@ -154,6 +180,20 @@ typedef enum { BAT_IT_BELOW_THRESHOLD, } t_batt_event; +/*START: for 3ds hw event*/ +/*! + * Battery event type enum + */ +enum { + BAT_EVENT_CHARGER_PLUG = 0x01, + BAT_EVENT_CHARGER_UNPLUG = 0x02, + BAT_EVENT_CHARGER_OVERVOLTAGE = 0x04, + BAT_EVENT_BATTERY_LOW = 0x08, + BAT_EVENT_POWER_FAILED = 0x10, + BAT_EVENT_CHARGER_FULL = 0x20, +} t_bat_event; +/*END: for 3ds hw event*/ + /*! * This structure is used for the following battery changer control * IOCTLs: diff --git a/include/asm-arm/arch-mxc/pmic_status.h b/include/asm-arm/arch-mxc/pmic_status.h index 55dbe155ea56..a9287292e7db 100644 --- a/include/asm-arm/arch-mxc/pmic_status.h +++ b/include/asm-arm/arch-mxc/pmic_status.h @@ -13,7 +13,9 @@ #ifndef __ASM_ARCH_MXC_PMIC_STATUS_H__ #define __ASM_ARCH_MXC_PMIC_STATUS_H__ #include <asm-generic/errno-base.h> +#ifdef __KERNEL__ #include <asm/uaccess.h> /* copy_{from,to}_user() */ +#endif /*! * @file arch-mxc/pmic_status.h * @brief PMIC APIs return code definition. |