static int sec_bat_adc_ap_read(unsigned int channel) { int rc = -1, data = -1; struct pm8xxx_adc_chan_result result; switch (channel) { case SEC_BAT_ADC_CHANNEL_TEMP: case SEC_BAT_ADC_CHANNEL_TEMP_AMBIENT: rc = pm8xxx_adc_mpp_config_read( PM8XXX_AMUX_MPP_3, ADC_MPP_1_AMUX6, &result); if (rc) { pr_err("error reading mpp %d, rc = %d\n", PM8XXX_AMUX_MPP_3, rc); return rc; } /* use measurement, no need to scale */ data = (int)result.measurement; break; case SEC_BAT_ADC_CHANNEL_VOLTAGE_NOW: pm8xxx_adc_read(CHANNEL_VBAT, &result); data = (int)result.physical; break; default: pr_err("Invalid adc channel: %d\n", channel); break; } return data; }
static int sec_bat_adc_ap_read(unsigned int channel) { int rc = -1, data = -1; struct pm8xxx_adc_chan_result result; switch (channel) { case SEC_BAT_ADC_CHANNEL_TEMP: case SEC_BAT_ADC_CHANNEL_TEMP_AMBIENT: rc = pm8xxx_adc_mpp_config_read( PM8XXX_AMUX_MPP_3, ADC_MPP_1_AMUX6, &result); if (rc) { pr_err("error reading mpp %d, rc = %d\n", PM8XXX_AMUX_MPP_3, rc); return rc; } /* use measurement, no need to scale */ data = (int)result.measurement; break; case SEC_BAT_ADC_CHANNEL_VOLTAGE_NOW: pm8xxx_adc_read(CHANNEL_VBAT, &result); data = (int)result.physical; break; case SEC_BAT_ADC_CHANNEL_CURRENT_NOW: rc = pm8xxx_adc_mpp_config_read( PM8XXX_AMUX_MPP_7, ADC_MPP_1_AMUX6, &result); if (rc) { pr_err("error reading mpp %d, rc = %d\n", PM8XXX_AMUX_MPP_7, rc); return rc; } /* use measurement, no need to scale */ data = (int)result.measurement; /* MPP7 error in discharging */ if (data > biscotto_battery_data[0].adc2current_table[ biscotto_battery_data[0].adc2current_table_size-1].adc) { pr_err("Invalid adc value: %d, %d\n", data, biscotto_battery_data[0].adc2current_table_size); data = 0; } break; default: pr_err("Invalid adc channel: %d\n", channel); break; } return data; }
int get_mpp_hs_mic_adc(u64 *val) { uint32_t rc; struct pm8xxx_adc_chan_result result; rc = pm8xxx_adc_read(ADC_MPP_1_AMUX6, &result); if (!rc) printk("ADC MPP value chan:%d raw:%x measurement:%lld physical:%lld\n", result.chan, result.adc_code, result.measurement, result.physical); *val = result.adc_code; return 0; }
static int msm_mctl_get_DVE073_temperature_val(int* temperature) { int rc = 0; struct pm8xxx_adc_chan_result result; rc = pm8xxx_adc_read(CHANNEL_MUXOFF, &result); if (rc < 0){ pr_err("pm8xxx adc read error with %d\n", rc); *temperature = 100000; return 0; } *temperature = (int)result.physical; CDBG("%s: temperature:%d\n", __func__, *temperature); return rc; }
static int pm8xxx_tz_get_temp_pm8058_adc(struct thermal_zone_device *thermal, unsigned long *temp) { struct pm8xxx_tm_chip *chip = thermal->devdata; DECLARE_COMPLETION_ONSTACK(wait); struct adc_chan_result adc_result = { .physical = 0lu, }; int rc; if (!chip || !temp) return -EINVAL; *temp = chip->temp; rc = adc_channel_request_conv(chip->adc_handle, &wait); if (rc < 0) { pr_err("%s: adc_channel_request_conv() failed, rc = %d\n", __func__, rc); return rc; } wait_for_completion(&wait); rc = adc_channel_read_result(chip->adc_handle, &adc_result); if (rc < 0) { pr_err("%s: adc_channel_read_result() failed, rc = %d\n", __func__, rc); return rc; } *temp = adc_result.physical; chip->temp = adc_result.physical; return 0; } static int pm8xxx_tz_get_temp_pm8xxx_adc(struct thermal_zone_device *thermal, unsigned long *temp) { struct pm8xxx_tm_chip *chip = thermal->devdata; struct pm8xxx_adc_chan_result result = { .physical = 0lu, }; int rc; if (!chip || !temp) return -EINVAL; *temp = chip->temp; rc = pm8xxx_adc_read(chip->cdata.adc_channel, &result); if (rc < 0) { pr_err("%s: adc_channel_read_result() failed, rc = %d\n", chip->cdata.tm_name, rc); return rc; } *temp = result.physical; chip->temp = result.physical; return 0; } static int pm8xxx_tz_get_mode(struct thermal_zone_device *thermal, enum thermal_device_mode *mode) { struct pm8xxx_tm_chip *chip = thermal->devdata; if (!chip || !mode) return -EINVAL; *mode = chip->mode; return 0; } static int pm8xxx_tz_set_mode(struct thermal_zone_device *thermal, enum thermal_device_mode mode) { struct pm8xxx_tm_chip *chip = thermal->devdata; if (!chip) return -EINVAL; /* Mask software override requests if they are not allowed. */ if (!chip->cdata.allow_software_override) mode = THERMAL_DEVICE_DISABLED; if (mode != chip->mode) { if (mode == THERMAL_DEVICE_ENABLED) pm8xxx_tm_shutdown_override(chip, SOFTWARE_OVERRIDE_ENABLED); else pm8xxx_tm_shutdown_override(chip, SOFTWARE_OVERRIDE_DISABLED); } chip->mode = mode; return 0; } static int pm8xxx_tz_get_trip_type(struct thermal_zone_device *thermal, int trip, enum thermal_trip_type *type) { if (trip < 0 || !type) return -EINVAL; switch (trip) { case TRIP_STAGE3: *type = THERMAL_TRIP_CRITICAL; break; case TRIP_STAGE2: *type = THERMAL_TRIP_HOT; break; case TRIP_STAGE1: *type = THERMAL_TRIP_HOT; break; default: return -EINVAL; } return 0; } static int pm8xxx_tz_get_trip_temp(struct thermal_zone_device *thermal, int trip, unsigned long *temp) { struct pm8xxx_tm_chip *chip = thermal->devdata; int thresh_temp; if (!chip || trip < 0 || !temp) return -EINVAL; thresh_temp = chip->thresh * TEMP_THRESH_STEP + TEMP_THRESH_MIN; switch (trip) { case TRIP_STAGE3: thresh_temp += 2 * TEMP_STAGE_STEP; break; case TRIP_STAGE2: thresh_temp += TEMP_STAGE_STEP; break; case TRIP_STAGE1: break; default: return -EINVAL; } *temp = thresh_temp; return 0; } static int pm8xxx_tz_get_crit_temp(struct thermal_zone_device *thermal, unsigned long *temp) { struct pm8xxx_tm_chip *chip = thermal->devdata; if (!chip || !temp) return -EINVAL; *temp = chip->thresh * TEMP_THRESH_STEP + TEMP_THRESH_MIN + 2 * TEMP_STAGE_STEP; return 0; } static struct thermal_zone_device_ops pm8xxx_thermal_zone_ops_no_adc = { .get_temp = pm8xxx_tz_get_temp_no_adc, .get_mode = pm8xxx_tz_get_mode, .set_mode = pm8xxx_tz_set_mode, .get_trip_type = pm8xxx_tz_get_trip_type, .get_trip_temp = pm8xxx_tz_get_trip_temp, .get_crit_temp = pm8xxx_tz_get_crit_temp, }; static struct thermal_zone_device_ops pm8xxx_thermal_zone_ops_pm8xxx_adc = { .get_temp = pm8xxx_tz_get_temp_pm8xxx_adc, .get_mode = pm8xxx_tz_get_mode, .set_mode = pm8xxx_tz_set_mode, .get_trip_type = pm8xxx_tz_get_trip_type, .get_trip_temp = pm8xxx_tz_get_trip_temp, .get_crit_temp = pm8xxx_tz_get_crit_temp, }; static struct thermal_zone_device_ops pm8xxx_thermal_zone_ops_pm8058_adc = { .get_temp = pm8xxx_tz_get_temp_pm8058_adc, .get_mode = pm8xxx_tz_get_mode, .set_mode = pm8xxx_tz_set_mode, .get_trip_type = pm8xxx_tz_get_trip_type, .get_trip_temp = pm8xxx_tz_get_trip_temp, .get_crit_temp = pm8xxx_tz_get_crit_temp, }; static void pm8xxx_tm_work(struct work_struct *work) { struct delayed_work *dwork = container_of(work, struct delayed_work, work); struct pm8xxx_tm_chip *chip = container_of(dwork, struct pm8xxx_tm_chip, irq_work); unsigned long temp = 0; int rc, stage, thresh; u8 reg; rc = pm8xxx_tm_read_ctrl(chip, ®); if (rc < 0) goto bail; /* Clear status bits. */ if (reg & (TEMP_ALARM_CTRL_ST2_SD | TEMP_ALARM_CTRL_ST3_SD)) { reg &= ~(TEMP_ALARM_CTRL_ST2_SD | TEMP_ALARM_CTRL_ST3_SD | TEMP_ALARM_CTRL_STATUS_MASK); pm8xxx_tm_write_ctrl(chip, reg); } stage = (reg & TEMP_ALARM_CTRL_STATUS_MASK) >> TEMP_ALARM_CTRL_STATUS_SHIFT; thresh = (reg & TEMP_ALARM_CTRL_THRESH_MASK) >> TEMP_ALARM_CTRL_THRESH_SHIFT; thermal_zone_device_update(chip->tz_dev); if (stage != chip->prev_stage) { chip->prev_stage = stage; switch (chip->cdata.adc_type) { case PM8XXX_TM_ADC_NONE: rc = pm8xxx_tz_get_temp_no_adc(chip->tz_dev, &temp); break; case PM8XXX_TM_ADC_PM8058_ADC: rc = pm8xxx_tz_get_temp_pm8058_adc(chip->tz_dev, &temp); break; case PM8XXX_TM_ADC_PM8XXX_ADC: rc = pm8xxx_tz_get_temp_pm8xxx_adc(chip->tz_dev, &temp); break; } if (rc < 0) goto bail; pr_crit("%s: PMIC Temp Alarm - stage=%u, threshold=%u, temp=%lu mC\n", chip->cdata.tm_name, stage, thresh, temp); /* Notify user space */ sysfs_notify(&chip->tz_dev->device.kobj, NULL, "type"); } bail: return; } static irqreturn_t pm8xxx_tm_isr(int irq, void *data) { struct pm8xxx_tm_chip *chip = data; schedule_delayed_work(&chip->irq_work, msecs_to_jiffies(STATUS_REGISTER_DELAY_MS) + 1); return IRQ_HANDLED; } static int pm8xxx_tm_init_reg(struct pm8xxx_tm_chip *chip) { int rc; u8 reg; rc = pm8xxx_tm_read_ctrl(chip, ®); if (rc < 0) return rc; chip->stage = (reg & TEMP_ALARM_CTRL_STATUS_MASK) >> TEMP_ALARM_CTRL_STATUS_SHIFT; chip->temp = 0; /* Use temperature threshold set 0: (105, 125, 145) */ chip->thresh = 0; reg = (chip->thresh << TEMP_ALARM_CTRL_THRESH_SHIFT) & TEMP_ALARM_CTRL_THRESH_MASK; rc = pm8xxx_tm_write_ctrl(chip, reg); if (rc < 0) return rc; /* * Set the PMIC temperature alarm module to be always on. This ensures * that die temperature monitoring is active even if CXO is disabled * (i.e. when sleep_b is low). This is necessary since CXO can be * disabled while the system is still heavily loaded. Also, using * the alway-on instead of PWM-enabled configurations ensures that the * die temperature can be measured by the PMIC ADC without reconfiguring * the temperature alarm module first. */ rc = pm8xxx_tm_write_pwm(chip, TEMP_ALARM_PWM_EN_ALWAYS); return rc; } static int pm8xxx_init_adc(struct pm8xxx_tm_chip *chip, bool enable) { int rc = 0; if (chip->cdata.adc_type == PM8XXX_TM_ADC_PM8058_ADC) { if (enable) { rc = adc_channel_open(chip->cdata.adc_channel, &(chip->adc_handle)); if (rc < 0) pr_err("adc_channel_open() failed.\n"); } else { adc_channel_close(chip->adc_handle); } } return rc; }
static int pm8xxx_tz_get_temp_pm8xxx_adc(struct thermal_zone_device *thermal, unsigned long *temp) { struct pm8xxx_tm_chip *chip = thermal->devdata; struct pm8xxx_adc_chan_result result = { .physical = 0lu, }; int rc; if (!chip || !temp) return -EINVAL; *temp = chip->temp; rc = pm8xxx_adc_read(chip->cdata.adc_channel, &result); if (rc < 0) { pr_err("%s: adc_channel_read_result() failed, rc = %d\n", chip->cdata.tm_name, rc); return rc; } *temp = result.physical; chip->temp = result.physical; return 0; } static int pm8xxx_tz_get_mode(struct thermal_zone_device *thermal, enum thermal_device_mode *mode) { struct pm8xxx_tm_chip *chip = thermal->devdata; if (!chip || !mode) return -EINVAL; *mode = chip->mode; return 0; } static int pm8xxx_tz_set_mode(struct thermal_zone_device *thermal, enum thermal_device_mode mode) { struct pm8xxx_tm_chip *chip = thermal->devdata; if (!chip) return -EINVAL; if (mode != chip->mode) { if (mode == THERMAL_DEVICE_ENABLED) pm8xxx_tm_shutdown_override(chip, SOFTWARE_OVERRIDE_ENABLED); else pm8xxx_tm_shutdown_override(chip, SOFTWARE_OVERRIDE_DISABLED); } chip->mode = mode; return 0; } static int pm8xxx_tz_get_trip_type(struct thermal_zone_device *thermal, int trip, enum thermal_trip_type *type) { if (trip < 0 || !type) return -EINVAL; switch (trip) { case TRIP_STAGE3: *type = THERMAL_TRIP_CRITICAL; break; case TRIP_STAGE2: *type = THERMAL_TRIP_HOT; break; case TRIP_STAGE1: *type = THERMAL_TRIP_HOT; break; default: return -EINVAL; } return 0; } static int pm8xxx_tz_get_trip_temp(struct thermal_zone_device *thermal, int trip, unsigned long *temp) { struct pm8xxx_tm_chip *chip = thermal->devdata; int thresh_temp; if (!chip || trip < 0 || !temp) return -EINVAL; thresh_temp = chip->thresh * TEMP_THRESH_STEP + TEMP_THRESH_MIN; switch (trip) { case TRIP_STAGE3: thresh_temp += 2 * TEMP_STAGE_STEP; break; case TRIP_STAGE2: thresh_temp += TEMP_STAGE_STEP; break; case TRIP_STAGE1: break; default: return -EINVAL; } *temp = thresh_temp; return 0; } static int pm8xxx_tz_get_crit_temp(struct thermal_zone_device *thermal, unsigned long *temp) { struct pm8xxx_tm_chip *chip = thermal->devdata; if (!chip || !temp) return -EINVAL; *temp = chip->thresh * TEMP_THRESH_STEP + TEMP_THRESH_MIN + 2 * TEMP_STAGE_STEP; return 0; } static struct thermal_zone_device_ops pm8xxx_thermal_zone_ops_no_adc = { .get_temp = pm8xxx_tz_get_temp_no_adc, .get_mode = pm8xxx_tz_get_mode, .set_mode = pm8xxx_tz_set_mode, .get_trip_type = pm8xxx_tz_get_trip_type, .get_trip_temp = pm8xxx_tz_get_trip_temp, .get_crit_temp = pm8xxx_tz_get_crit_temp, }; static struct thermal_zone_device_ops pm8xxx_thermal_zone_ops_pm8xxx_adc = { .get_temp = pm8xxx_tz_get_temp_pm8xxx_adc, .get_mode = pm8xxx_tz_get_mode, .set_mode = pm8xxx_tz_set_mode, .get_trip_type = pm8xxx_tz_get_trip_type, .get_trip_temp = pm8xxx_tz_get_trip_temp, .get_crit_temp = pm8xxx_tz_get_crit_temp, }; static void pm8xxx_tm_work(struct work_struct *work) { struct pm8xxx_tm_chip *chip = container_of(work, struct pm8xxx_tm_chip, irq_work); int rc; u8 reg; rc = pm8xxx_tm_read_ctrl(chip, ®); if (rc < 0) goto bail; if (chip->cdata.adc_type == PM8XXX_TM_ADC_NONE) { rc = pm8xxx_tm_update_temp_no_adc(chip); if (rc < 0) goto bail; pr_info("%s: Temp Alarm - stage=%u, threshold=%u, " "temp=%lu mC\n", chip->cdata.tm_name, chip->stage, chip->thresh, chip->temp); } else { chip->stage = (reg & TEMP_ALARM_CTRL_STATUS_MASK) >> TEMP_ALARM_CTRL_STATUS_SHIFT; chip->thresh = (reg & TEMP_ALARM_CTRL_THRESH_MASK) >> TEMP_ALARM_CTRL_THRESH_SHIFT; pr_info("%s: Temp Alarm - stage=%u, threshold=%u\n", chip->cdata.tm_name, chip->stage, chip->thresh); } /* Clear status bits. */ if (reg & (TEMP_ALARM_CTRL_ST2_SD | TEMP_ALARM_CTRL_ST3_SD)) { reg &= ~(TEMP_ALARM_CTRL_ST2_SD | TEMP_ALARM_CTRL_ST3_SD | TEMP_ALARM_CTRL_STATUS_MASK); pm8xxx_tm_write_ctrl(chip, reg); } thermal_zone_device_update(chip->tz_dev); /* Notify user space */ if (chip->mode == THERMAL_DEVICE_ENABLED) kobject_uevent(&chip->tz_dev->device.kobj, KOBJ_CHANGE); bail: enable_irq(chip->tempstat_irq); enable_irq(chip->overtemp_irq); } static irqreturn_t pm8xxx_tm_isr(int irq, void *data) { struct pm8xxx_tm_chip *chip = data; disable_irq_nosync(chip->tempstat_irq); disable_irq_nosync(chip->overtemp_irq); schedule_work(&chip->irq_work); return IRQ_HANDLED; } static int pm8xxx_tm_init_reg(struct pm8xxx_tm_chip *chip) { int rc; u8 reg; rc = pm8xxx_tm_read_ctrl(chip, ®); if (rc < 0) return rc; chip->stage = (reg & TEMP_ALARM_CTRL_STATUS_MASK) >> TEMP_ALARM_CTRL_STATUS_SHIFT; chip->temp = 0; /* Use temperature threshold set 0: (105, 125, 145) */ chip->thresh = 0; reg = (chip->thresh << TEMP_ALARM_CTRL_THRESH_SHIFT) & TEMP_ALARM_CTRL_THRESH_MASK; rc = pm8xxx_tm_write_ctrl(chip, reg); if (rc < 0) return rc; /* * Set the PMIC alarm module PWM to have a frequency of 8 Hz. This * helps cut down on the number of unnecessary interrupts fired when * changing between thermal stages. Also, Enable the over temperature * PWM whenever the PMIC is enabled. */ reg = (1 << TEMP_ALARM_PWM_EN_SHIFT) | (3 << TEMP_ALARM_PWM_PER_PRE_SHIFT) | (3 << TEMP_ALARM_PWM_PER_DIV_SHIFT); rc = pm8xxx_tm_write_pwm(chip, reg); return rc; }
static long ncdiagd_power_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int ret = 0; void __user *pArg = (void __user *)arg; printk(KERN_INFO "[%s] cmd:%d",__func__, cmd); switch(cmd) { case IOCTL_PW_RG_LP_CTL: { unsigned char enable; unsigned char vreg_id; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } enable = buf.req_buf[0]; vreg_id = buf.req_buf[1]; printk(KERN_INFO "DIAG_PW_RG_LP_CTL enable:%x vreg_id:%x", enable, vreg_id); ret = nc_pm8xxx_lp_mode_control(PM8XXX_VERSION_8921, vreg_id, enable); } break; case IOCTL_PW_RG_CTL: { unsigned char enable; unsigned char vreg_id; unsigned int min_volt, max_volt; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } enable = buf.req_buf[0]; vreg_id = buf.req_buf[1]; min_volt = cvt_val(buf.req_buf[3]); min_volt += cvt_val(buf.req_buf[2]) * 100; min_volt *= 1000; max_volt = cvt_val(buf.req_buf[5]); max_volt += cvt_val(buf.req_buf[4]) * 100; max_volt *= 1000; printk(KERN_INFO "DIAG_PW_RG_CTL enable :%x vreg_id :%x", enable, vreg_id); printk(KERN_INFO " min_volt:%x max_volt:%x", min_volt, max_volt); ret = nc_pm8xxx_vreg_control(PM8XXX_VERSION_8921, enable, vreg_id, min_volt, max_volt); } break; case IOCTL_PW_RG_SET_LVL: { unsigned char vreg_id; unsigned int min_volt, max_volt; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } vreg_id = buf.req_buf[0]; min_volt = cvt_val(buf.req_buf[2]); min_volt += cvt_val(buf.req_buf[1]) * 100; min_volt *= 1000; max_volt = cvt_val(buf.req_buf[4]); max_volt += cvt_val(buf.req_buf[3]) * 100; max_volt *= 1000; printk(KERN_INFO "DIAG_PW_RG_SET_LVL vreg_id:%x min_volt:%d max_volt:%d", vreg_id, min_volt, max_volt); ret = nc_pm8xxx_vreg_set_level(PM8XXX_VERSION_8921, vreg_id, min_volt, max_volt); } break; case IOCTL_PW_VT_PLDWN_SW: { unsigned char enable; unsigned char vreg_id; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } enable = buf.req_buf[0]; vreg_id = buf.req_buf[1]; printk(KERN_INFO "DIAG_PW_RG_SMPS_PSK enable:%x vreg_id:%x", enable, vreg_id); ret = nc_pm8xxx_vreg_pull_down_switch(PM8XXX_VERSION_8921, vreg_id, enable); } break; case IOCTL_PW_CHG_COIN_SW: { struct pm8xxx_coincell_chg param; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } param.state = buf.req_buf[0]; param.voltage = PM8XXX_COINCELL_VOLTAGE_3p2V; param.resistor = PM8XXX_COINCELL_RESISTOR_800_OHMS; ret = pm8xxx_coincell_chg_config(¶m); printk(KERN_INFO "DIAG_PW_CHG_COIN_SW enable:%x", param.state); } break; case IOCTL_PW_CHG_BAT_EBL: { bool enable; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } enable = (buf.req_buf[0]&0x01); ret = nc_pm8921_charger_enable(enable); printk(KERN_INFO "DIAG_PW_CHG_BAT_EBL enable:%x", enable); } break; case IOCTL_PW_CHG_DSBL: { unsigned char enable; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } enable = buf.req_buf[0]; enable = enable ? 0x00 : 0x01; ret = pm8921_disable_source_current(enable); printk(KERN_INFO "DIAG_PW_CHG_DSBL enable:%x", enable); } break; case IOCTL_PW_CHG_WCG_GET_STATE: { unsigned int rt_id = 0x00; unsigned int rt_status = 0x00; ioctl_pw_value_type buf; rt_id = PM8921_IRQ_BASE + PM8921_CABLE_IRQ; ret = nc_pm8921_get_rt_status(rt_id, &rt_status); if (ret != 0) { printk(KERN_ERR "nc_pm8921_get_rt_status failed \n"); return PM_ERR_FLAG__SBI_OPT_ERR; } buf.rsp_buf[0] = (u8)rt_status; if(copy_to_user((void *)pArg, &buf, sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_to_user failed"); return PM_ERR_FLAG__SBI_OPT_ERR; } printk(KERN_INFO "IOCTL_PW_CHG_WCG_GET_STATE rt_id:%x rt_status:%x", rt_id, rt_status); } break; case IOCTL_PW_CHG_WCG_SW: { ioctl_pw_value_type buf; struct pm_gpio param; int gpio_port; unsigned char enable = 0x00; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__SBI_OPT_ERR; } gpio_port = PM8921_GPIO_PM_TO_SYS(PM_DIAG_GPIO_32); param.direction = PM_GPIO_DIR_OUT; param.output_buffer = PM_GPIO_OUT_BUF_CMOS; param.output_value = 0; param.pull = PM_GPIO_PULL_NO; param.vin_sel = PM_GPIO_VIN_S4; param.out_strength = PM_GPIO_STRENGTH_LOW; param.function = PM_GPIO_FUNC_NORMAL; param.inv_int_pol = 0; param.disable_pin = 0; enable = buf.req_buf[0]; param.output_value = enable ? 0 : 1; ret = pm8xxx_gpio_config(gpio_port, ¶m); if (ret != 0) { printk(KERN_ERR "pm8xxx_gpio_config failed"); return PM_ERR_FLAG__SBI_OPT_ERR; } printk(KERN_INFO "IOCTL_PW_CHG_WCG_SW enable:%x param.output_value:%x ", enable, param.output_value); } break; case IOCTL_PW_CHG_VMAX_SET: { unsigned short voltage; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } voltage = buf.req_buf[1]; voltage += buf.req_buf[0] * 0x100; ret = nc_pm8921_chg_vmaxsel_set(voltage); printk(KERN_INFO "DIAG_PW_CHG_VMAX_SET voltage:%x", voltage); } break; case IOCTL_PW_CHG_IMAX_SET: { unsigned short cur_val; ioctl_pw_value_type buf; int ibat = 0; unsigned int iusb = 0; const int ibat_min = 325; const int ibat_max = 2000; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } cur_val = buf.req_buf[1]; cur_val += buf.req_buf[0] * 0x100; if (cur_val < ibat_min) { ibat = ibat_min; } else if (cur_val > ibat_max) { ibat = ibat_max; } else { ibat = (int)cur_val; } iusb = (unsigned int)(cur_val | PM8921_DIAG_IUSB_SET); pm8921_set_max_battery_charge_current(ibat); pm8921_charger_vbus_draw(iusb); printk(KERN_INFO "DIAG_PW_CHG_IMAX_SET cur_val:0x%04x", cur_val); } break; case IOCTL_PW_CHG_STATE_GET: { unsigned char chg_state = 0x00; ioctl_pw_value_type buf; ret = nc_pm8921_get_fsm_status((u64 *)&chg_state); buf.rsp_buf[0] = chg_state; if(copy_to_user((void *)pArg, &buf, sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_to_user failed"); return PM_ERR_FLAG__INVALID; } printk(KERN_INFO "DIAG_PW_CHG_STATE_GET chg_state:%x", chg_state); } break; case IOCTL_PW_CHG_USB_DSBL: { unsigned char enable; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } enable = buf.req_buf[0]; enable = enable ? 0x00 : 0x01; ret = nc_pm8921_chg_usb_suspend_enable(enable); printk(KERN_INFO "DIAG_PW_CHG_USB_DSBL enable:%x", enable); } break; case IOCTL_PW_ADC_RD_CHANNEL: { unsigned char analog_chnl, mpp_chnl; struct pm8xxx_adc_chan_result result; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } analog_chnl = buf.req_buf[0]; if (analog_chnl == CHANNEL_BATT_THERM) { analog_chnl = CHANNEL_BATT_THERM_UV; ret = pm8xxx_adc_read(analog_chnl, &result); } else if ((analog_chnl < PM8XXX_CHANNEL_MPP_SCALE1_IDX) || (analog_chnl == ADC_MPP_1_AMUX8 ) || (analog_chnl == ADC_MPP_1_AMUX3 ) || (analog_chnl == ADC_MPP_1_AMUX3_UV)) { ret = pm8xxx_adc_read(analog_chnl, &result); } else if ((analog_chnl >= PM8XXX_CHANNEL_MPP_SCALE1_IDX) && (analog_chnl <= ADC_MPP_1_ATEST_7 ) ) { mpp_chnl = analog_chnl - PM8XXX_CHANNEL_MPP_SCALE1_IDX; ret = pm8xxx_adc_mpp_config_read(mpp_chnl, CHANNEL_MPP_1, &result); } else if ((analog_chnl >= PM8XXX_CHANNEL_MPP_SCALE3_IDX) && (analog_chnl <= ADC_MPP_2_ATEST_7 ) ) { mpp_chnl = analog_chnl - PM8XXX_CHANNEL_MPP_SCALE3_IDX; ret = pm8xxx_adc_mpp_config_read(mpp_chnl, CHANNEL_MPP_2, &result); } else { printk(KERN_ERR "ADC_channel failed"); return PM_ERR_FLAG__FEATURE_NOT_SUPPORTED; } if(ret == PM_ERR_FLAG__SUCCESS) { if ((analog_chnl != CHANNEL_BATT_THERM) && (analog_chnl != ADC_MPP_1_AMUX8 ) && (analog_chnl != CHANNEL_MUXOFF ) && (analog_chnl != ADC_MPP_1_AMUX3 )) { if (result.physical != 0) { result.physical = div_u64(result.physical, 1000); } if (result.physical >= 0xFFFF) { result.physical = 0xFFFF; } } buf.rsp_buf[0] = (result.physical >> 8) & 0xff; buf.rsp_buf[1] = result.physical & 0xff; } if(copy_to_user((void *)pArg, &buf, sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_to_user failed"); return PM_ERR_FLAG__INVALID; } printk(KERN_INFO "DIAG_PW_ADC_RD_CHANNEL analog_chnl :%x", analog_chnl); printk(KERN_INFO " adc_read_val[0]:%x", (int)((result.physical >> 8) & 0xff)); printk(KERN_INFO " adc_read_val[1]:%x", (int)(result.physical & 0xff)); } break; case IOCTL_PW_SP_SMPLD_SW: { unsigned char enable; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } enable = buf.req_buf[0]; ret = pm8xxx_smpl_control(enable); printk(KERN_INFO "DIAG_PW_SP_SMPLD_SW enable:%x", enable); } break; case IOCTL_PW_SP_SMPLD_TM_SET: { unsigned char timer_set; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } timer_set = buf.req_buf[0]; ret = pm8xxx_smpl_set_delay(timer_set); printk(KERN_INFO "DIAG_PW_SP_SMPLD_TM_SET timer_set:%x", timer_set); } break; case IOCTL_PW_MPP_CNFDG_IPUT: { unsigned char mpp_port; unsigned char logi_level; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } mpp_port = buf.req_buf[0]; logi_level = buf.req_buf[1]; ret = nc_pm8xxx_mpp_config_digital_in(PM8921_MPP_PM_TO_SYS(mpp_port), logi_level, PM8XXX_MPP_DIN_TO_INT); printk(KERN_INFO "DIAG_PW_MPP_CNFDG_IPUT mpp_port:%x logi_level:%x", mpp_port +1, logi_level); } break; case IOCTL_PW_MPP_CNFDG_OPUT: { unsigned char mpp_port; unsigned char logi_level; unsigned char out_ctl; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } mpp_port = buf.req_buf[0]; logi_level = buf.req_buf[1]; out_ctl = buf.req_buf[2]; ret = nc_pm8xxx_mpp_config_digital_out(PM8921_MPP_PM_TO_SYS(mpp_port), logi_level, out_ctl); printk(KERN_INFO "DIAG_PW_MPP_CNFDG_OPUT mpp_port:%x logi_level:%x out_ctl:%x", mpp_port +1, logi_level, out_ctl); } break; case IOCTL_PW_MPP_CNFDG_IOPUT: { unsigned char mpp_port; unsigned char logi_level; unsigned char pull_set; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } mpp_port = buf.req_buf[0]; logi_level = buf.req_buf[1]; pull_set = buf.req_buf[2]; ret = nc_pm8xxx_mpp_config_bi_dir(PM8921_MPP_PM_TO_SYS(mpp_port), logi_level, pull_set); printk(KERN_INFO "DIAG_PW_MPP_CNFDG_IOPUT mpp_port:%x logi_level:%x pull_set:%x", mpp_port +1, logi_level, pull_set); } break; case IOCTL_PW_MPP_CNFAN_IPUT: { unsigned char mpp_port; unsigned char ain_chn; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } mpp_port = buf.req_buf[0]; ain_chn = buf.req_buf[1]; ret = nc_pm8xxx_mpp_config_analog_input(PM8921_MPP_PM_TO_SYS(mpp_port), ain_chn, PM8XXX_MPP_AOUT_CTRL_DISABLE); printk(KERN_INFO "DIAG_PW_MPP_CNFAN_IPUT mpp_port:%x ain_chn:%x", mpp_port + 1, ain_chn); } break; case IOCTL_PW_MPP_CNFAN_OPUT: { unsigned char mpp_port; unsigned char aout_level; unsigned char pm_onoff; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } mpp_port = buf.req_buf[0]; aout_level = buf.req_buf[1]; pm_onoff = buf.req_buf[2]; ret = nc_pm8xxx_mpp_config_analog_output(PM8921_MPP_PM_TO_SYS(mpp_port), aout_level, pm_onoff); printk(KERN_INFO "DIAG_PW_MPP_CNFAN_OPUT mpp_port:%x aout_level:%x pm_onoff:%x", mpp_port +1 , aout_level, pm_onoff); } break; case IOCTL_PW_MPP_CNF_I_SINK: { unsigned char mpp_port; unsigned char sink_level; unsigned char pm_onoff; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } mpp_port = buf.req_buf[0]; sink_level = buf.req_buf[1]; pm_onoff = buf.req_buf[2]; ret = nc_pm8xxx_mpp_config_current_sink(PM8921_MPP_PM_TO_SYS(mpp_port), sink_level, pm_onoff); printk(KERN_INFO "DIAG_PW_MPP_CNF_I_SINK mpp_port:%x sink_level:%x pm_onoff:%x", mpp_port + 1, sink_level, pm_onoff); } break; case IOCTL_PW_GPIO_CONFIG_SET: { ioctl_pw_value_type buf; struct pm_gpio param ; int gpio_port; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } gpio_port = PM8921_GPIO_PM_TO_SYS(buf.req_buf[0]); param.direction = buf.req_buf[1]; param.output_buffer = buf.req_buf[2]; param.output_value = buf.req_buf[3]; param.pull = buf.req_buf[4]; param.vin_sel = buf.req_buf[5]; param.out_strength = buf.req_buf[6]; param.function = buf.req_buf[7]; param.inv_int_pol = buf.req_buf[8]; param.disable_pin = buf.req_buf[9]; ret = pm8xxx_gpio_config(gpio_port, ¶m); printk(KERN_INFO "IOCTL_PW_GPIO_CONFIG_SET gpio_port :%x direction:%x output_buffer:%x", gpio_port, param.direction, param.output_buffer); printk(KERN_INFO " output_value:%x pull :%x vin_sel :%x", param.output_value, param.pull, param.vin_sel); printk(KERN_INFO " out_strength:%x function :%x inv_int_pol :%x", param.out_strength, param.function, param.inv_int_pol); printk(KERN_INFO " pin_disable :%x ", param.disable_pin); } break; case IOCTL_PW_GPIO_GET_STATE: { unsigned int gpio_id = 0x00; unsigned int gpio_state = 0x00; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } gpio_id = (unsigned int)buf.req_buf[0]; ret = nc_pm8921_gpio_get_state(gpio_id, &gpio_state); buf.rsp_buf[0] = (u8)gpio_state; if(copy_to_user((void *)pArg, &buf, sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_to_user failed"); return PM_ERR_FLAG__INVALID; } printk(KERN_INFO "DIAG_PW_GPIO_GET_STATE GPIO :%d value :%d", gpio_id+1, gpio_state); } break; case IOCTL_PW_PCT_OTP_STAGE_GET: { unsigned char itemp_stage = 0x00; ioctl_pw_value_type buf; ret = nc_pm8921_itemp_get_stage(&itemp_stage); buf.rsp_buf[0] = itemp_stage; if(copy_to_user((void *)pArg, &buf, sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_to_user failed"); return PM_ERR_FLAG__INVALID; } printk(KERN_INFO "DIAG_PW_PCT_OTP_STAGE_GET itemp_stage:%x", itemp_stage); } break; case IOCTL_PW_PCT_OTP_STG_OVD: { unsigned char enable; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } enable = buf.req_buf[0]; ret = nc_pm8921_itemp_stage_override(enable); printk(KERN_INFO "DIAG_PW_PCT_OTP_STG_OVD enable:%x", enable); } break; case IOCTL_PW_IR_RT_STATUS_GET: { unsigned int rt_id = 0x00; unsigned int rt_status = 0x00; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } rt_id = (unsigned int)buf.req_buf[0]; rt_id += PM8921_IRQ_BASE; nc_pm8921_get_rt_status(rt_id, &rt_status); buf.rsp_buf[0] = (u8)rt_status; if(copy_to_user((void *)pArg, &buf, sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_to_user failed"); return PM_ERR_FLAG__INVALID; } printk(KERN_INFO "DIAG_PW_IR_RT_STATUS_GET rt_id:%x rt_status:%x", rt_id, rt_status); } break; case IOCTL_PW8821_RG_LP_CTL: { unsigned char enable; unsigned char vreg_id; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } enable = buf.req_buf[0]; vreg_id = buf.req_buf[1]; printk(KERN_INFO "DIAG_PW8821_RG_LP_CTL enable:%x vreg_id:%x", enable, vreg_id); ret = nc_pm8xxx_lp_mode_control(PM8XXX_VERSION_8821, vreg_id, enable); } break; case IOCTL_PW8821_RG_CTL: { unsigned char enable; unsigned char vreg_id; unsigned int min_volt, max_volt; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } enable = buf.req_buf[0]; vreg_id = buf.req_buf[1]; min_volt = cvt_val(buf.req_buf[3]); min_volt += cvt_val(buf.req_buf[2]) * 100; min_volt *= 1000; max_volt = cvt_val(buf.req_buf[5]); max_volt += cvt_val(buf.req_buf[4]) * 100; max_volt *= 1000; printk(KERN_INFO "DIAG_PW8821_RG_CTL enable :%x vreg_id :%x", enable, vreg_id); printk(KERN_INFO " min_volt:%x max_volt:%x", min_volt, max_volt); ret = nc_pm8xxx_vreg_control(PM8XXX_VERSION_8821, enable, vreg_id, min_volt, max_volt); } break; case IOCTL_PW8821_RG_SET_LVL: { unsigned char vreg_id; unsigned int min_volt, max_volt; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } vreg_id = buf.req_buf[0]; min_volt = cvt_val(buf.req_buf[2]); min_volt += cvt_val(buf.req_buf[1]) * 100; min_volt *= 1000; max_volt = cvt_val(buf.req_buf[4]); max_volt += cvt_val(buf.req_buf[3]) * 100; max_volt *= 1000; printk(KERN_INFO "DIAG_PW8821_RG_SET_LVL vreg_id:%x min_volt:%x max_volt:%x", vreg_id, min_volt, max_volt); ret = nc_pm8xxx_vreg_set_level(PM8XXX_VERSION_8821, vreg_id, min_volt, max_volt); } break; case IOCTL_PW8821_VT_PLDWN_SW: { unsigned char enable; unsigned char vreg_id; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } enable = buf.req_buf[0]; vreg_id = buf.req_buf[1]; printk(KERN_INFO "DIAG_PW8821_RG_SMPS_PSK enable:%x vreg_id:%x", enable, vreg_id); ret = nc_pm8xxx_vreg_pull_down_switch(PM8XXX_VERSION_8821, vreg_id, enable); } break; case IOCTL_PW8821_MPP_CNFDG_IPUT: { unsigned char mpp_port; unsigned char logi_level; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } mpp_port = buf.req_buf[0]; logi_level = buf.req_buf[1]; ret = nc_pm8xxx_mpp_config_digital_in(PM8821_MPP_PM_TO_SYS(mpp_port), logi_level, PM8XXX_MPP_DIN_TO_INT); printk(KERN_INFO "DIAG_PW8821_MPP_CNFDG_IPUT mpp_port:%x logi_level:%x", mpp_port, logi_level); } break; case IOCTL_PW8821_MPP_CNFDG_OPUT: { unsigned char mpp_port; unsigned char logi_level; unsigned char out_ctl; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } mpp_port = buf.req_buf[0]; logi_level = buf.req_buf[1]; out_ctl = buf.req_buf[2]; ret = nc_pm8xxx_mpp_config_digital_out(PM8821_MPP_PM_TO_SYS(mpp_port), logi_level, out_ctl); printk(KERN_INFO "DIAG_PW8821_MPP_CNFDG_OPUT mpp_port:%x logi_level:%x out_ctl:%x", mpp_port, logi_level, out_ctl); } break; case IOCTL_PW8821_MPP_CNFDG_IOPUT: { unsigned char mpp_port; unsigned char logi_level; unsigned char pull_set; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } mpp_port = buf.req_buf[0]; logi_level = buf.req_buf[1]; pull_set = buf.req_buf[2]; ret = nc_pm8xxx_mpp_config_bi_dir(PM8821_MPP_PM_TO_SYS(mpp_port), logi_level, pull_set); printk(KERN_INFO "DIAG_PW8821_MPP_CNFDG_IOPUT mpp_port:%x logi_level:%x pull_set:%x", mpp_port, logi_level, pull_set); } break; case IOCTL_PW8821_MPP_CNFAN_IPUT: { unsigned char mpp_port; unsigned char ain_chn; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } mpp_port = buf.req_buf[0]; ain_chn = buf.req_buf[1]; ret = nc_pm8xxx_mpp_config_analog_input(PM8821_MPP_PM_TO_SYS(mpp_port), ain_chn, PM8XXX_MPP_AOUT_CTRL_DISABLE); printk(KERN_INFO "DIAG_PW8821_MPP_CNFAN_IPUT mpp_port:%x ain_chn:%x", mpp_port, ain_chn); } break; case IOCTL_PW8821_MPP_CNFAN_OPUT: { unsigned char mpp_port; unsigned char aout_level; unsigned char pm_onoff; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } mpp_port = buf.req_buf[0]; aout_level = buf.req_buf[1]; pm_onoff = buf.req_buf[2]; ret = nc_pm8xxx_mpp_config_analog_output(PM8821_MPP_PM_TO_SYS(mpp_port), aout_level, pm_onoff); printk(KERN_INFO "DIAG_PW8821_MPP_CNFAN_OPUT mpp_port:%x aout_level:%x pm_onoff:%x", mpp_port, aout_level, pm_onoff); } break; case IOCTL_PW8821_MPP_CNF_I_SINK: { unsigned char mpp_port; unsigned char sink_level; unsigned char pm_onoff; ioctl_pw_value_type buf; if(copy_from_user(&buf,pArg,sizeof(ioctl_pw_value_type))) { printk(KERN_ERR "copy_from_user failed"); return PM_ERR_FLAG__INVALID; } mpp_port = buf.req_buf[0]; sink_level = buf.req_buf[1]; pm_onoff = buf.req_buf[2]; ret = nc_pm8xxx_mpp_config_current_sink(PM8821_MPP_PM_TO_SYS(mpp_port), sink_level, pm_onoff); printk(KERN_INFO "DIAG_PW8821_MPP_CNF_I_SINK mpp_port:%x sink_level:%x pm_onoff:%x", mpp_port, sink_level, pm_onoff); } break; case IOCTL_PW_HW_RESET: printk(KERN_INFO "DVE005_FACTORY_DIAG_FTM_ONLINE_RESET_MODE"); printk(KERN_DEBUG "[ncdiagd_power.c]%s: Goto arm_pm_restart() in \n", __func__ ); arm_pm_restart(0, NULL); break; default: printk(KERN_ERR "Invalid Parameter"); return PM_ERR_FLAG__INVALID; } return ret; }
static int pm8xxx_tz_get_temp_pm8058_adc(struct thermal_zone_device *thermal, unsigned long *temp) { struct pm8xxx_tm_chip *chip = thermal->devdata; DECLARE_COMPLETION_ONSTACK(wait); struct adc_chan_result adc_result = { .physical = 0lu, }; int rc; #ifdef CONFIG_LGE_PM /* */ int wait_ret; #endif if (!chip || !temp) return -EINVAL; *temp = chip->temp; rc = adc_channel_request_conv(chip->adc_handle, &wait); if (rc < 0) { pr_err("%s: adc_channel_request_conv() failed, rc = %d\n", __func__, rc); return rc; } #ifdef CONFIG_LGE_PM /* */ wait_ret = wait_for_completion_timeout(&wait, msecs_to_jiffies(MSM_PMIC_ADC_READ_TIMEOUT)); if(wait_ret <= 0) { printk(KERN_ERR "===%s: failed to adc wait for completion!===\n",__func__); goto sanity_out; } #else wait_for_completion(&wait); #endif rc = adc_channel_read_result(chip->adc_handle, &adc_result); if (rc < 0) { pr_err("%s: adc_channel_read_result() failed, rc = %d\n", __func__, rc); return rc; } *temp = adc_result.physical; chip->temp = adc_result.physical; #if defined(CONFIG_MACH_LGE_325_BOARD_SKT) || defined(CONFIG_MACH_LGE_325_BOARD_LGU) /* */ if (chip->temp > 46000) { printk("%s: pmic_die_temp = %ld temp_range = %d \n", __func__, *temp, pmic_die_temp_range); pmic_die_temp_range = 3; } else if (chip->temp > 44000) pmic_die_temp_range = 2; else if (chip->temp > 39000) pmic_die_temp_range = 1; else pmic_die_temp_range = 0; #endif return 0; #ifdef CONFIG_LGE_PM /* */ sanity_out: pm8058_xoadc_clear_recentQ(); *temp = MSM_CHARGER_GAUGE_MISSING_TEMP; chip->temp = MSM_CHARGER_GAUGE_MISSING_TEMP; printk(KERN_ERR "============== batt temp adc read fail so default temp ===============\n"); return 0; #endif } static int pm8xxx_tz_get_temp_pm8xxx_adc(struct thermal_zone_device *thermal, unsigned long *temp) { struct pm8xxx_tm_chip *chip = thermal->devdata; struct pm8xxx_adc_chan_result result = { .physical = 0lu, }; int rc; if (!chip || !temp) return -EINVAL; *temp = chip->temp; rc = pm8xxx_adc_read(chip->cdata.adc_channel, &result); if (rc < 0) { pr_err("%s: adc_channel_read_result() failed, rc = %d\n", chip->cdata.tm_name, rc); return rc; } *temp = result.physical; chip->temp = result.physical; return 0; } static int pm8xxx_tz_get_mode(struct thermal_zone_device *thermal, enum thermal_device_mode *mode) { struct pm8xxx_tm_chip *chip = thermal->devdata; if (!chip || !mode) return -EINVAL; *mode = chip->mode; return 0; } static int pm8xxx_tz_set_mode(struct thermal_zone_device *thermal, enum thermal_device_mode mode) { struct pm8xxx_tm_chip *chip = thermal->devdata; if (!chip) return -EINVAL; if (mode != chip->mode) { if (mode == THERMAL_DEVICE_ENABLED) pm8xxx_tm_shutdown_override(chip, SOFTWARE_OVERRIDE_ENABLED); else pm8xxx_tm_shutdown_override(chip, SOFTWARE_OVERRIDE_DISABLED); } chip->mode = mode; return 0; } static int pm8xxx_tz_get_trip_type(struct thermal_zone_device *thermal, int trip, enum thermal_trip_type *type) { if (trip < 0 || !type) return -EINVAL; switch (trip) { case TRIP_STAGE3: *type = THERMAL_TRIP_CRITICAL; break; case TRIP_STAGE2: *type = THERMAL_TRIP_HOT; break; case TRIP_STAGE1: *type = THERMAL_TRIP_HOT; break; default: return -EINVAL; } return 0; } static int pm8xxx_tz_get_trip_temp(struct thermal_zone_device *thermal, int trip, unsigned long *temp) { struct pm8xxx_tm_chip *chip = thermal->devdata; int thresh_temp; if (!chip || trip < 0 || !temp) return -EINVAL; thresh_temp = chip->thresh * TEMP_THRESH_STEP + TEMP_THRESH_MIN; switch (trip) { case TRIP_STAGE3: thresh_temp += 2 * TEMP_STAGE_STEP; break; case TRIP_STAGE2: thresh_temp += TEMP_STAGE_STEP; break; case TRIP_STAGE1: break; default: return -EINVAL; } *temp = thresh_temp; return 0; } static int pm8xxx_tz_get_crit_temp(struct thermal_zone_device *thermal, unsigned long *temp) { struct pm8xxx_tm_chip *chip = thermal->devdata; if (!chip || !temp) return -EINVAL; *temp = chip->thresh * TEMP_THRESH_STEP + TEMP_THRESH_MIN + 2 * TEMP_STAGE_STEP; return 0; } static struct thermal_zone_device_ops pm8xxx_thermal_zone_ops_no_adc = { .get_temp = pm8xxx_tz_get_temp_no_adc, .get_mode = pm8xxx_tz_get_mode, .set_mode = pm8xxx_tz_set_mode, .get_trip_type = pm8xxx_tz_get_trip_type, .get_trip_temp = pm8xxx_tz_get_trip_temp, .get_crit_temp = pm8xxx_tz_get_crit_temp, }; static struct thermal_zone_device_ops pm8xxx_thermal_zone_ops_pm8xxx_adc = { .get_temp = pm8xxx_tz_get_temp_pm8xxx_adc, .get_mode = pm8xxx_tz_get_mode, .set_mode = pm8xxx_tz_set_mode, .get_trip_type = pm8xxx_tz_get_trip_type, .get_trip_temp = pm8xxx_tz_get_trip_temp, .get_crit_temp = pm8xxx_tz_get_crit_temp, }; static struct thermal_zone_device_ops pm8xxx_thermal_zone_ops_pm8058_adc = { .get_temp = pm8xxx_tz_get_temp_pm8058_adc, .get_mode = pm8xxx_tz_get_mode, .set_mode = pm8xxx_tz_set_mode, .get_trip_type = pm8xxx_tz_get_trip_type, .get_trip_temp = pm8xxx_tz_get_trip_temp, .get_crit_temp = pm8xxx_tz_get_crit_temp, }; static void pm8xxx_tm_work(struct work_struct *work) { struct pm8xxx_tm_chip *chip = container_of(work, struct pm8xxx_tm_chip, irq_work); int rc; u8 reg; rc = pm8xxx_tm_read_ctrl(chip, ®); if (rc < 0) goto bail; if (chip->cdata.adc_type == PM8XXX_TM_ADC_NONE) { rc = pm8xxx_tm_update_temp_no_adc(chip); if (rc < 0) goto bail; pr_info("%s: Temp Alarm - stage=%u, threshold=%u, " "temp=%lu mC\n", chip->cdata.tm_name, chip->stage, chip->thresh, chip->temp); } else { chip->stage = (reg & TEMP_ALARM_CTRL_STATUS_MASK) >> TEMP_ALARM_CTRL_STATUS_SHIFT; chip->thresh = (reg & TEMP_ALARM_CTRL_THRESH_MASK) >> TEMP_ALARM_CTRL_THRESH_SHIFT; pr_info("%s: Temp Alarm - stage=%u, threshold=%u\n", chip->cdata.tm_name, chip->stage, chip->thresh); } /* Clear status bits. */ if (reg & (TEMP_ALARM_CTRL_ST2_SD | TEMP_ALARM_CTRL_ST3_SD)) { reg &= ~(TEMP_ALARM_CTRL_ST2_SD | TEMP_ALARM_CTRL_ST3_SD | TEMP_ALARM_CTRL_STATUS_MASK); pm8xxx_tm_write_ctrl(chip, reg); } thermal_zone_device_update(chip->tz_dev); /* Notify user space */ if (chip->mode == THERMAL_DEVICE_ENABLED) kobject_uevent(&chip->tz_dev->device.kobj, KOBJ_CHANGE); bail: enable_irq(chip->tempstat_irq); enable_irq(chip->overtemp_irq); } static irqreturn_t pm8xxx_tm_isr(int irq, void *data) { struct pm8xxx_tm_chip *chip = data; disable_irq_nosync(chip->tempstat_irq); disable_irq_nosync(chip->overtemp_irq); schedule_work(&chip->irq_work); return IRQ_HANDLED; } static int pm8xxx_tm_init_reg(struct pm8xxx_tm_chip *chip) { int rc; u8 reg; rc = pm8xxx_tm_read_ctrl(chip, ®); if (rc < 0) return rc; chip->stage = (reg & TEMP_ALARM_CTRL_STATUS_MASK) >> TEMP_ALARM_CTRL_STATUS_SHIFT; chip->temp = 0; /* Use temperature threshold set 0: (105, 125, 145) */ chip->thresh = 0; reg = (chip->thresh << TEMP_ALARM_CTRL_THRESH_SHIFT) & TEMP_ALARM_CTRL_THRESH_MASK; rc = pm8xxx_tm_write_ctrl(chip, reg); if (rc < 0) return rc; /* * Set the PMIC alarm module PWM to have a frequency of 8 Hz. This * helps cut down on the number of unnecessary interrupts fired when * changing between thermal stages. Also, Enable the over temperature * PWM whenever the PMIC is enabled. */ reg = (1 << TEMP_ALARM_PWM_EN_SHIFT) | (3 << TEMP_ALARM_PWM_PER_PRE_SHIFT) | (3 << TEMP_ALARM_PWM_PER_DIV_SHIFT); rc = pm8xxx_tm_write_pwm(chip, reg); return rc; } static int pm8xxx_init_adc(struct pm8xxx_tm_chip *chip, bool enable) { int rc = 0; if (chip->cdata.adc_type == PM8XXX_TM_ADC_PM8058_ADC) { if (enable) { rc = adc_channel_open(chip->cdata.adc_channel, &(chip->adc_handle)); if (rc < 0) pr_err("adc_channel_open() failed.\n"); } else { adc_channel_close(chip->adc_handle); } } return rc; }