Exemplo n.º 1
0
static int batt_read_adc(int channel, int *mv_reading)
{
	int ret;
	void *h;
	struct adc_chan_result adc_chan_result;
	struct completion  conv_complete_evt;
#ifdef CONFIG_LGE_PM
    int wait_ret;
#endif

	pr_debug("%s: called for %d\n", __func__, channel);
	ret = adc_channel_open(channel, &h);
	if (ret) {
		pr_err("%s: couldnt open channel %d ret=%d\n",
					__func__, channel, ret);
		goto out;
	}
	init_completion(&conv_complete_evt);
	ret = adc_channel_request_conv(h, &conv_complete_evt);
	if (ret) {
		pr_err("%s: couldnt request conv channel %d ret=%d\n",
						__func__, channel, ret);
		goto out;
	}
#ifdef CONFIG_LGE_PM
    wait_ret = wait_for_completion_timeout(&conv_complete_evt, 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(&conv_complete_evt);
#endif

	ret = adc_channel_read_result(h, &adc_chan_result);
	if (ret) {
		pr_err("%s: couldnt read result channel %d ret=%d\n",
						__func__, channel, ret);
		goto out;
	}
	ret = adc_channel_close(h);
	if (ret) {
		pr_err("%s: couldnt close channel %d ret=%d\n",
						__func__, channel, ret);
	}
	if (mv_reading)
		*mv_reading = adc_chan_result.measurement;

	pr_debug("%s: done for %d\n", __func__, channel);
	return adc_chan_result.physical;
out:
	pr_debug("%s: done for %d\n", __func__, channel);
	return -EINVAL;

#ifdef CONFIG_LGE_PM
sanity_out:

    pm8058_xoadc_clear_recentQ();

	ret = adc_channel_close(h);
	if (ret) {
		pr_err("%s: couldnt close channel %d ret=%d\n",
						__func__, channel, ret);
	}
    
    if(channel == CHANNEL_ADC_BATT_THERM)
    {
        printk(KERN_ERR "============== batt temp adc read fail so default temp ===============\n");
	    if (mv_reading)
		    *mv_reading = MSM_CHARGER_GAUGE_MISSING_TEMP_ADC;
        return MSM_CHARGER_GAUGE_MISSING_TEMP;
    }
    else if(channel == CHANNEL_ADC_ACC)
    {
        printk(KERN_ERR "============== ACC adc read fail so default usb ===============\n");
        return CHANNEL_ADC_ACC_MISSING;
    }
    else
    {
        printk(KERN_ERR "============== adc read fail  ===============\n");
	    return -EINVAL;
    }
#endif
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
0
u32 lightsensor_get_adc(int channel)
{
	int ret;
	void *h;
	struct adc_chan_result adc_chan_result;
	struct completion  conv_complete_evt;
#ifdef CONFIG_SEC_DEBUG_PM8058_ADC
	static int retry_cnt;
#endif
	pr_debug("%s: called for %d\n", __func__, channel);
	ret = adc_channel_open(channel, &h);
	if (ret) {
		pr_err("%s: couldnt open channel %d ret=%d\n",
					__func__, channel, ret);
		goto out;
	}
	init_completion(&conv_complete_evt);
	ret = adc_channel_request_conv(h, &conv_complete_evt);
	if (ret) {
		pr_err("%s: couldnt request conv channel %d ret=%d\n",
						__func__, channel, ret);
		goto out;
	}
	ret = wait_for_completion_interruptible_timeout(&conv_complete_evt, 5*HZ);
	if (!ret) {
		pr_err("%s: wait interrupted channel %d ret=%d\n",
						__func__, channel, ret);
#ifdef CONFIG_SEC_DEBUG_PM8058_ADC_VERBOSE
		adc_dbg_info_timer(0);
#else
		pm8058_xoadc_clear_recentQ();
#ifdef CONFIG_SEC_DEBUG_PM8058_ADC
		if(retry_cnt++ >= 10)
			adc_dbg_info_timer(0);
#endif
#endif
		goto out;
	}
#ifdef CONFIG_SEC_DEBUG_PM8058_ADC
	retry_cnt = 0;
#endif
	ret = adc_channel_read_result(h, &adc_chan_result);
	if (ret) {
		pr_err("%s: couldnt read result channel %d ret=%d\n",
						__func__, channel, ret);
		goto out;
	}
	ret = adc_channel_close(h);
	if (ret) {
		pr_err("%s: couldnt close channel %d ret=%d\n",
						__func__, channel, ret);
	}

	pr_debug("%s: done for %d\n", __func__, channel);
//	return adc_chan_result.physical;
	return adc_chan_result.measurement;

out:
	pr_debug("%s: done for %d\n", __func__, channel);
	return -EINVAL;

}
Exemplo n.º 4
0
static int pm8058_tz_get_temp(struct thermal_zone_device *thermal,
			      unsigned long *temp)
{
	struct pm8058_tm_device *tm = 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 (!tm || !temp)
		return -EINVAL;

	*temp = tm->temp;

	rc = adc_channel_request_conv(tm->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(tm->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;
	tm->temp = adc_result.physical;

	return 0;

#ifdef CONFIG_LGE_PM
sanity_out:

    pm8058_xoadc_clear_recentQ();

	*temp = MSM_CHARGER_GAUGE_MISSING_TEMP;
	tm->temp = MSM_CHARGER_GAUGE_MISSING_TEMP;
    
    printk(KERN_ERR "============== batt temp adc read fail so default temp ===============\n");
    return 0;
#endif    

}

static int pm8058_tz_get_mode(struct thermal_zone_device *thermal,
			      enum thermal_device_mode *mode)
{
	struct pm8058_tm_device *tm = thermal->devdata;

	if (!tm || !mode)
		return -EINVAL;

	*mode = tm->mode;

	return 0;
}

static int pm8058_tz_set_mode(struct thermal_zone_device *thermal,
			      enum thermal_device_mode mode)
{
	struct pm8058_tm_device *tm = thermal->devdata;

	if (!tm)
		return -EINVAL;

	if (mode != tm->mode) {
		if (mode == THERMAL_DEVICE_ENABLED)
			pm8058_tm_shutdown_override(tm->pm_chip,
						    SOFTWARE_OVERRIDE_ENABLED);
		else
			pm8058_tm_shutdown_override(tm->pm_chip,
						    SOFTWARE_OVERRIDE_DISABLED);
	}
	tm->mode = mode;

	return 0;
}

static int pm8058_tz_get_trip_type(struct thermal_zone_device *thermal,
				   int trip, enum thermal_trip_type *type)
{
	struct pm8058_tm_device *tm = thermal->devdata;

	if (!tm || trip < 0 || !type)
		return -EINVAL;

	switch (trip) {
	case PM8058_TRIP_STAGE3:
		*type = THERMAL_TRIP_CRITICAL;
		break;
	case PM8058_TRIP_STAGE2:
		*type = THERMAL_TRIP_HOT;
		break;
	case PM8058_TRIP_STAGE1:
		*type = THERMAL_TRIP_HOT;
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static int pm8058_tz_get_trip_temp(struct thermal_zone_device *thermal,
				   int trip, unsigned long *temp)
{
	struct pm8058_tm_device *tm = thermal->devdata;
	int thresh_temp;

	if (!tm || trip < 0 || !temp)
		return -EINVAL;

	thresh_temp = tm->thresh * PM8058_TEMP_THRESH_STEP +
		      PM8058_TEMP_THRESH_MIN;

	switch (trip) {
	case PM8058_TRIP_STAGE3:
		thresh_temp += 2 * PM8058_TEMP_STAGE_STEP;
		break;
	case PM8058_TRIP_STAGE2:
		thresh_temp += PM8058_TEMP_STAGE_STEP;
		break;
	case PM8058_TRIP_STAGE1:
		break;
	default:
		return -EINVAL;
	}

	*temp = thresh_temp;

	return 0;
}

static int pm8058_tz_get_crit_temp(struct thermal_zone_device *thermal,
				   unsigned long *temp)
{
	struct pm8058_tm_device *tm = thermal->devdata;

	if (!tm || !temp)
		return -EINVAL;

	*temp = tm->thresh * PM8058_TEMP_THRESH_STEP + PM8058_TEMP_THRESH_MIN +
		2 * PM8058_TEMP_STAGE_STEP;

	return 0;
}

static struct thermal_zone_device_ops pm8058_thermal_zone_ops = {
	.get_temp = pm8058_tz_get_temp,
	.get_mode = pm8058_tz_get_mode,
	.set_mode = pm8058_tz_set_mode,
	.get_trip_type = pm8058_tz_get_trip_type,
	.get_trip_temp = pm8058_tz_get_trip_temp,
	.get_crit_temp = pm8058_tz_get_crit_temp,
};

static irqreturn_t pm8058_tm_isr(int irq, void *data)
{
	struct pm8058_tm_device *tm = data;
	int rc;
	u8 reg;

	rc = pm8058_tm_read_ctrl(tm->pm_chip, &reg);
	if (rc < 0)
		goto isr_handled;

	tm->stage = (reg & PM8058_TEMP_STATUS_MASK) >> PM8058_TEMP_STATUS_SHIFT;
	tm->thresh = (reg & PM8058_TEMP_THRESH_MASK) >>
			PM8058_TEMP_THRESH_SHIFT;

	if (reg & (PM8058_TEMP_ST2_SD | PM8058_TEMP_ST3_SD)) {
		reg &= ~(PM8058_TEMP_ST2_SD | PM8058_TEMP_ST3_SD |
			 PM8058_TEMP_STATUS_MASK);
		pm8058_tm_write_ctrl(tm->pm_chip, reg);
	}

	thermal_zone_device_update(tm->tz_dev);

	/* Notify user space */
	if (tm->mode == THERMAL_DEVICE_ENABLED)
		kobject_uevent(&tm->tz_dev->device.kobj, KOBJ_CHANGE);

isr_handled:
	return IRQ_HANDLED;
}

static int pm8058_tm_init_reg(struct pm8058_tm_device *tm)
{
	int rc;
	u8 reg;

	rc = pm8058_tm_read_ctrl(tm->pm_chip, &reg);
	if (rc < 0)
		return rc;

	tm->stage = (reg & PM8058_TEMP_STATUS_MASK) >> PM8058_TEMP_STATUS_SHIFT;
	tm->temp = 0;

	/* Use temperature threshold set 0: (105, 125, 145) */
	tm->thresh = 0;
	reg = (tm->thresh << PM8058_TEMP_THRESH_SHIFT) &
	      PM8058_TEMP_THRESH_MASK;
	rc = pm8058_tm_write_ctrl(tm->pm_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 << PM8058_TEMP_PWM_EN_SHIFT |
	       3 << PM8058_TEMP_PWM_PER_PRE_SHIFT |
	       3 << PM8058_TEMP_PWM_PER_DIV_SHIFT;

	rc = pm8058_tm_write_pwm(tm->pm_chip, reg);

	return rc;
}