static void pmic_fg_init_hw_regs(struct pmic_fg_info *info)
{
	/* program temperature thresholds */
	intel_mid_pmic_writeb(DC_FG_VLTFW_REG, FG_VLTFW_N5C);
	intel_mid_pmic_writeb(DC_FG_VHTFW_REG, FG_VHTFW_60C);

	/* enable interrupts */
	intel_mid_pmic_setb(DC_TEMP_IRQ_CFG_REG, TEMP_IRQ_CFG_MASK);
	intel_mid_pmic_setb(DC_FG_IRQ_CFG_REG, FG_IRQ_CFG_LOWBATT_MASK);
}
static void __crystalcove_irq_type(int gpio, int type)
{
	int offset = gpio < 8 ? gpio : gpio - 8;
	u8 ctli = gpio < 8 ? GPIO0P0CTLI + gpio : GPIO1P0CTLI + (gpio - 8);

	type &= IRQ_TYPE_EDGE_BOTH;
	intel_mid_pmic_clearb(ctli, CTLI_INTCNT_BE);
	if (type == IRQ_TYPE_EDGE_BOTH)
		intel_mid_pmic_setb(ctli, CTLI_INTCNT_BE);
	else if (type == IRQ_TYPE_EDGE_RISING)
		intel_mid_pmic_setb(ctli, CTLI_INTCNT_PE);
	else if (type & IRQ_TYPE_EDGE_FALLING)
		intel_mid_pmic_setb(ctli, CTLI_INTCNT_NE);
}
static int pmic_fg_reg_setb(struct pmic_fg_info *info, int reg, u8 mask)
{
       int ret;

       ret = intel_mid_pmic_setb(reg, mask);
       if (ret < 0)
               dev_err(&info->pdev->dev, "pmic reg set mask err:%d\n", ret);
       return ret;
}
static void crystalcove_gpio_set(struct gpio_chip *chip,
		unsigned gpio, int value)
{
	u8 ctlo = gpio < 8 ? GPIO0P0CTLO + gpio : GPIO1P0CTLO + (gpio - 8);

	if (value)
		intel_mid_pmic_setb(ctlo, 1);
	else
		intel_mid_pmic_clearb(ctlo, 1);
}
static void __crystalcove_irq_mask(int gpio, int mask)
{
	u8 mirqs0 = gpio < 8 ? MGPIO0IRQS0 : MGPIO1IRQS0;
	int offset = gpio < 8 ? gpio : gpio - 8;

	if (mask)
		intel_mid_pmic_setb(mirqs0, 1 << offset);
	else
		intel_mid_pmic_clearb(mirqs0, 1 << offset);
}
static int pmic_chrg_reg_setb(struct pmic_chrg_info *info, int reg, u8 mask)
{
    int ret, i;

    for (i = 0; i < RETRY_RW; i++) {
        ret = intel_mid_pmic_setb(reg, mask);
        if (ret < 0) {
            dev_warn(&info->pdev->dev,
                     "failed to set reg 0x%x: %d\n", reg, ret);
            usleep_range(1000, 2000);
        } else
            break;
    }

    return ret;
}
/**
 * iio_crystalcove_gpadc_sample - do gpadc sample.
 * @indio_dev: industrial IO GPADC device handle
 * @ch: gpadc bit set of channels to sample, for example, set ch = (1<<0)|(1<<2)
 *	means you are going to sample both channel 0 and 2 at the same time.
 * @res:gpadc sampling result
 *
 * Returns 0 on success or an error code.
 *
 * This function may sleep.
 */
int iio_crystalcove_gpadc_sample(struct iio_dev *indio_dev,
				int ch, struct gpadc_result *res)
{
	struct gpadc_info *info = iio_priv(indio_dev);
	int i;
	int ret;
	int mask = 0;
	u8 th, tl;

	for (i = 0; i < GPADC_CH_NUM; i++) {
		if (ch & (1 << i))
			mask |= (1 << i);
	}
	mutex_lock(&info->lock);
	info->irq_pending = 0;
	intel_mid_pmic_setb(MANCONV0, (u8)mask);
	intel_mid_pmic_setb(MANCONV1, (u8)(mask >> 8));
	ret = wait_event_timeout(info->wait,
			((info->irq_pending & mask) == mask), HZ);
	if (ret == 0) {
		ret = -ETIMEDOUT;
		dev_err(info->dev, "sample timeout, return %d\n", ret);
		goto done;
	} else
		ret = 0;
	for (i = 0; i < GPADC_CH_NUM; i++) {
		if (ch & (1 << i)) {
			th = intel_mid_pmic_readb(gpadc_regmaps[i].rslth);
			tl = intel_mid_pmic_readb(gpadc_regmaps[i].rsltl);
			res->data[i] = ((th & 0x3) << 8) + tl;
		}
	}
done:
	mutex_unlock(&info->lock);
	return ret;
}