Example #1
0
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;
}
Example #4
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, &reg);
	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, &reg);
	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;
}
Example #6
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;

	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, &reg);
	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, &reg);
	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;
}
Example #7
0
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(&param);
                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, &param);
		
		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, &param);
                
                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;
}
Example #8
0
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, &reg);
	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, &reg);
	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;
}