Beispiel #1
0
// kmj_el15.pm8901_patch
int pm8901_preload_dVdd(void)
{
	int rc;
	u8 reg;

	if (pmic_chip == NULL) {
		pr_err("%s: Error: PMIC 8901 driver has not probed\n",
			__func__);
		return -ENODEV;
	}

	reg = 0x0F;
	rc = ssbi_write(pmic_chip->dev, 0x0BD, &reg, 1);
	if (rc)
		pr_err("%s: ssbi_write failed for 0x0BD, rc=%d\n", __func__,
			rc);

	reg = 0xB4;
	rc = ssbi_write(pmic_chip->dev, 0x001, &reg, 1);
	if (rc)
		pr_err("%s: ssbi_write failed for 0x001, rc=%d\n", __func__,
			rc);

	pr_info("%s: dVdd preloaded\n", __func__);

	return rc;
}
Beispiel #2
0
int pm8058_misc_control(struct pm8058_chip *chip, int mask, int flag)
{
	int		rc;
	u8		misc;
	unsigned long	irqsave;

	if (chip == NULL)
		chip = pmic_chip;	
	if (chip == NULL)
		return -ENODEV;

	spin_lock_irqsave(&chip->pm_lock, irqsave);

	rc = ssbi_read(chip->dev, SSBI_REG_ADDR_MISC, &misc, 1);
	if (rc) {
		pr_err("%s: FAIL ssbi_read(0x%x): rc=%d\n",
		       __func__, SSBI_REG_ADDR_MISC, rc);
		goto get_out;
	}

	misc &= ~mask;
	misc |= flag;

	rc = ssbi_write(chip->dev, SSBI_REG_ADDR_MISC, &misc, 1);
	if (rc) {
		pr_err("%s: FAIL ssbi_write(0x%x)=0x%x: rc=%d\n",
		       __func__, SSBI_REG_ADDR_MISC, misc, rc);
		goto get_out;
	}

get_out:
	spin_unlock_irqrestore(&chip->pm_lock, irqsave);

	return rc;
}
Beispiel #3
0
static int pm8921_writeb(const struct device *dev, u16 addr, u8 val)
{
	const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
	const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data;

	return ssbi_write(pmic->dev->parent, addr, &val, 1);
}
static int pm8058_masked_write(u16 addr, u8 val, u8 mask)
{
	int rc;
	u8 reg;

	if (pmic_chip == NULL)
		return -ENODEV;

	rc = ssbi_read(pmic_chip->dev, addr, &reg, 1);
	if (rc) {
		pr_err("%s: ssbi_read(0x%03X) failed: rc=%d\n", __func__, addr,
			rc);
		goto done;
	}

	reg &= ~mask;
	reg |= val & mask;

	rc = ssbi_write(pmic_chip->dev, addr, &reg, 1);
	if (rc)
		pr_err("%s: ssbi_write(0x%03X)=0x%02X failed: rc=%d\n",
			__func__, addr, reg, rc);
done:
	return rc;
}
Beispiel #5
0
int pm8058_reset_pwr_off(int reset)
{
	int		rc;
	u8		pon;
	unsigned long	irqsave;

	if (pmic_chip == NULL)
		return -ENODEV;

	spin_lock_irqsave(&pmic_chip->pm_lock, irqsave);

	rc = ssbi_read(pmic_chip->dev, SSBI_REG_ADDR_PON_CNTL_1, &pon, 1);
	if (rc) {
		pr_err("%s: FAIL ssbi_read(0x%x): rc=%d\n",
		       __func__, SSBI_REG_ADDR_PON_CNTL_1, rc);
		goto get_out;
	}

	pon &= ~PM8058_PON_WD_EN_MASK;
	pon |= reset ? PM8058_PON_WD_EN_RESET : PM8058_PON_WD_EN_PWR_OFF;

	rc = ssbi_write(pmic_chip->dev, SSBI_REG_ADDR_PON_CNTL_1, &pon, 1);
	if (rc) {
		pr_err("%s: FAIL ssbi_write(0x%x)=0x%x: rc=%d\n",
		       __func__, SSBI_REG_ADDR_PON_CNTL_1, pon, rc);
		goto get_out;
	}

get_out:
	spin_unlock_irqrestore(&pmic_chip->pm_lock, irqsave);

	return rc;
}
Beispiel #6
0
int pm8058_misc_control(struct pm8058_chip *chip, int mask, int flag)
{
	int		rc;
	u8		misc;

	if (chip == NULL)
		chip = pmic_chip;	/* for calls from non child */
	if (chip == NULL)
		return -ENODEV;

	mutex_lock(&chip->pm_lock);

	rc = ssbi_read(chip->dev, SSBI_REG_ADDR_MISC, &misc, 1);
	if (rc) {
		pr_err("%s: FAIL ssbi_read(0x%x): rc=%d\n",
		       __func__, SSBI_REG_ADDR_MISC, rc);
		goto get_out;
	}

	misc &= ~mask;
	misc |= flag;

	rc = ssbi_write(chip->dev, SSBI_REG_ADDR_MISC, &misc, 1);
	if (rc) {
		pr_err("%s: FAIL ssbi_write(0x%x)=0x%x: rc=%d\n",
		       __func__, SSBI_REG_ADDR_MISC, misc, rc);
		goto get_out;
	}

get_out:
	mutex_unlock(&chip->pm_lock);

	return rc;
}
int pm8058_write(struct pm8058_chip *chip, u16 addr, u8 *values,
		 unsigned int len)
{
	if (chip == NULL)
		return -EINVAL;

	return ssbi_write(chip->dev, addr, values, len);
}
Beispiel #8
0
static int pm8921_write_buf(const struct device *dev, u16 addr, u8 *buf,
									int cnt)
{
	const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
	const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data;

	return ssbi_write(pmic->dev->parent, addr, buf, cnt);
}
Beispiel #9
0
/* Internal functions */
static inline int
pm8901_config_irq(struct pm8901_chip *chip, u8 *bp, u8 *cp)
{
	int	rc;

	rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp, 1);
	if (rc) {
		pr_err("%s: ssbi_write: rc=%d (Select block)\n",
			__func__, rc);
		goto bail_out;
	}

	rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_CONFIG, cp, 1);
	if (rc)
		pr_err("%s: ssbi_write: rc=%d (Configure IRQ)\n",
			__func__, rc);

bail_out:
	return rc;
}
int pm8058_write(struct pm8058_chip *chip, u16 addr, u8 *values,
		 unsigned int len)
{
	int rc;
	unsigned long irqsave;
	if (chip == NULL)
		return -EINVAL;
	spin_lock_irqsave(&chip->pm_lock, irqsave);

	rc = ssbi_write(chip->dev, addr, values, len);

	spin_unlock_irqrestore(&chip->pm_lock, irqsave);

	return rc;
}
int pm8058_irq_get_rt_status(struct pm8058_chip *chip, int irq)
{
	int     rc;
	u8      block, bits, bit;
#ifdef CONFIG_MSM8X60_SSBI
	unsigned long irqsave;
#endif

	if (chip == NULL || irq < chip->pdata.irq_base ||
			irq >= chip->pdata.irq_base + MAX_PM_IRQ)
		return -EINVAL;

	irq -= chip->pdata.irq_base;

	block = irq / 8;
	bit = irq % 8;

#ifdef CONFIG_MSM8X60_SSBI
	spin_lock_irqsave(&chip->pm_lock, irqsave);
#else
	mutex_lock(&chip->pm_lock);
#endif

	rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, &block, 1);
	if (rc) {
		pr_err("%s: FAIL ssbi_write(): rc=%d (Select Block)\n",
				__func__, rc);
		goto bail_out;
	}

	rc = ssbi_read(chip->dev, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits, 1);
	if (rc) {
		pr_err("%s: FAIL ssbi_read(): rc=%d (Read RT Status)\n",
				__func__, rc);
		goto bail_out;
	}

	rc = (bits & (1 << bit)) ? 1 : 0;

bail_out:
#ifdef CONFIG_MSM8X60_SSBI
	spin_unlock_irqrestore(&chip->pm_lock, irqsave);
#else
	mutex_unlock(&chip->pm_lock);
#endif

	return rc;
}
/* Helper Functions */
DEFINE_RATELIMIT_STATE(pm8058_msg_ratelimit, 60 * HZ, 10);

static inline int pm8058_can_print(void)
{
	return __ratelimit(&pm8058_msg_ratelimit);
}

#ifdef CONFIG_MSM8X60_SSBI
#define ssbi_write(client, addr, buf, len) \
	msm_ssbi_write(pmic_chip->id, addr, buf, len)
#define ssbi_read(client, addr, buf, len) \
	msm_ssbi_read(pmic_chip->id, addr, buf, len)
#else /*CONFIG_MSM8X60_SSBI*/
static inline int
ssbi_write(struct i2c_client *client, u16 addr, const u8 *buf, size_t len)
{
	int	rc;
	struct	i2c_msg msg = {
		.addr           = addr,
		.flags          = 0x0,
		.buf            = (u8 *)buf,
		.len            = len,
	};

	rc = i2c_transfer(client->adapter, &msg, 1);

	return (rc == 1) ? 0 : rc;
}

static inline int
ssbi_read(struct i2c_client *client, u16 addr, u8 *buf, size_t len)
{
	int	rc;
	struct	i2c_msg msg = {
		.addr           = addr,
		.flags          = I2C_M_RD,
		.buf            = buf,
		.len            = len,
	};

	rc = i2c_transfer(client->adapter, &msg, 1);
	return (rc == 1) ? 0 : rc;
}
#endif/*CONFIG_MSM8X60_SSBI*/
static int pm8058_masked_write(u16 addr, u8 val, u8 mask)
{
	int rc;
	u8 reg;

#ifndef CONFIG_MACH_VERDI_LTE //[Puccini] QCT patch: SMPS actvie pull-down
#ifdef CONFIG_MSM8X60_SSBI
	unsigned long irqsave;
#endif
#endif // !CONFIG_MACH_VERDI_LTE

	if (pmic_chip == NULL)
		return -ENODEV;

#ifndef CONFIG_MACH_VERDI_LTE //[Puccini] QCT patch: SMPS actvie pull-down
#ifdef CONFIG_MSM8X60_SSBI
	spin_lock_irqsave(&pmic_chip->pm_lock, irqsave);
#else
	mutex_lock(&pmic_chip->pm_lock);
#endif
#endif // !CONFIG_MACH_VERDI_LTE

	rc = ssbi_read(pmic_chip->dev, addr, &reg, 1);
	if (rc) {
		pr_err("%s: ssbi_read(0x%03X) failed: rc=%d\n", __func__, addr,
			rc);
		goto done;
	}

	reg &= ~mask;
	reg |= val & mask;

	rc = ssbi_write(pmic_chip->dev, addr, &reg, 1);
	if (rc)
		pr_err("%s: ssbi_write(0x%03X)=0x%02X failed: rc=%d\n",
			__func__, addr, reg, rc);
done:
#ifndef CONFIG_MACH_VERDI_LTE //[Puccini] QCT patch: SMPS actvie pull-down
#ifdef CONFIG_MSM8X60_SSBI
	spin_unlock_irqrestore(&pmic_chip->pm_lock, irqsave);
#else
	mutex_unlock(&pmic_chip->pm_lock);
#endif
#endif // !CONFIG_MACH_VERDI_LTE

	return rc;
}
/* External APIs */
int pm8058_rev(struct pm8058_chip *chip)
{
	if (chip == NULL)
		return -EINVAL;

	return chip->revision;
}
EXPORT_SYMBOL(pm8058_rev);

int pm8058_irq_get_rt_status(struct pm8058_chip *chip, int irq)
{
	int     rc;
	u8      block, bits, bit;
#ifdef CONFIG_MSM8X60_SSBI
	unsigned long irqsave;
#endif

	if (chip == NULL || irq < chip->pdata.irq_base ||
			irq >= chip->pdata.irq_base + MAX_PM_IRQ)
		return -EINVAL;

	irq -= chip->pdata.irq_base;

	block = irq / 8;
	bit = irq % 8;

#ifdef CONFIG_MSM8X60_SSBI
	spin_lock_irqsave(&chip->pm_lock, irqsave);
#else
	mutex_lock(&chip->pm_lock);
#endif

	rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, &block, 1);
	if (rc) {
		pr_err("%s: FAIL ssbi_write(): rc=%d (Select Block)\n",
				__func__, rc);
		goto bail_out;
	}

	rc = ssbi_read(chip->dev, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits, 1);
	if (rc) {
		pr_err("%s: FAIL ssbi_read(): rc=%d (Read RT Status)\n",
				__func__, rc);
		goto bail_out;
	}

	rc = (bits & (1 << bit)) ? 1 : 0;

bail_out:
#ifdef CONFIG_MSM8X60_SSBI
	spin_unlock_irqrestore(&chip->pm_lock, irqsave);
#else
	mutex_unlock(&chip->pm_lock);
#endif

	return rc;
}
EXPORT_SYMBOL(pm8058_irq_get_rt_status);

#ifdef CONFIG_MSM8X60_SSBI
int pm8058_read(struct pm8058_chip *chip, u16 addr, u8 *values,
		unsigned int len)
{
	int rc;
	unsigned long irqsave;
	if (chip == NULL)
		return -EINVAL;
	spin_lock_irqsave(&chip->pm_lock, irqsave);

	rc = ssbi_read(chip->dev, addr, values, len);

	spin_unlock_irqrestore(&chip->pm_lock, irqsave);

	return rc;
}
EXPORT_SYMBOL(pm8058_read);

int pm8058_write(struct pm8058_chip *chip, u16 addr, u8 *values,
		 unsigned int len)
{
	int rc;
	unsigned long irqsave;
	if (chip == NULL)
		return -EINVAL;
	spin_lock_irqsave(&chip->pm_lock, irqsave);

	rc = ssbi_write(chip->dev, addr, values, len);

	spin_unlock_irqrestore(&chip->pm_lock, irqsave);

	return rc;
}
EXPORT_SYMBOL(pm8058_write);
#else
int pm8058_read(struct pm8058_chip *chip, u16 addr, u8 *values,
		unsigned int len)
{
	if (chip == NULL)
		return -EINVAL;

	return ssbi_read(chip->dev, addr, values, len);
}
EXPORT_SYMBOL(pm8058_read);

int pm8058_write(struct pm8058_chip *chip, u16 addr, u8 *values,
		 unsigned int len)
{
	if (chip == NULL)
		return -EINVAL;

	return ssbi_write(chip->dev, addr, values, len);
}
EXPORT_SYMBOL(pm8058_write);
#endif /*CONFIG_MSM8X60_SSBI */
int pm8058_misc_control(struct pm8058_chip *chip, int mask, int flag)
{
	int		rc;
	u8		misc;
#ifdef CONFIG_MSM8X60_SSBI
	unsigned long irqsave;
#endif

	if (chip == NULL)
		chip = pmic_chip;	/* for calls from non child */
	if (chip == NULL)
		return -ENODEV;

#ifdef CONFIG_MSM8X60_SSBI
	spin_lock_irqsave(&chip->pm_lock, irqsave);
#else
	mutex_lock(&chip->pm_lock);
#endif

	rc = ssbi_read(chip->dev, SSBI_REG_ADDR_MISC, &misc, 1);
	if (rc) {
		pr_err("%s: FAIL ssbi_read(0x%x): rc=%d\n",
		       __func__, SSBI_REG_ADDR_MISC, rc);
		goto get_out;
	}

	misc &= ~mask;
	misc |= flag;

	rc = ssbi_write(chip->dev, SSBI_REG_ADDR_MISC, &misc, 1);
	if (rc) {
		pr_err("%s: FAIL ssbi_write(0x%x)=0x%x: rc=%d\n",
		       __func__, SSBI_REG_ADDR_MISC, misc, rc);
		goto get_out;
	}

get_out:
#ifdef CONFIG_MSM8X60_SSBI
	spin_unlock_irqrestore(&chip->pm_lock, irqsave);
#else
	mutex_unlock(&chip->pm_lock);
#endif

	return rc;
}
Beispiel #14
0
int pm8901_reset_pwr_off(int reset)
{
    int rc = 0, i;
    u8 pmr;
    u8 pmr_addr[4] = {
        SSBI_REG_ADDR_S2_PMR,
        SSBI_REG_ADDR_S3_PMR,
        SSBI_REG_ADDR_S4_PMR,
        SSBI_REG_ADDR_S1_PMR,
    };

    if (pmic_chip == NULL)
        return -ENODEV;

    /* Turn off regulators S1, S2, S3, S4 when shutting down. */
    if (!reset) {
        for (i = 0; i < 4; i++) {
            rc = ssbi_read(pmic_chip->dev, pmr_addr[i], &pmr, 1);
            if (rc) {
                pr_err("%s: FAIL ssbi_read(0x%x): rc=%d\n",
                       __func__, pmr_addr[i], rc);
                goto get_out;
            }

            pmr &= ~REGULATOR_PMR_STATE_MASK;
            pmr |= REGULATOR_PMR_STATE_OFF;

            rc = ssbi_write(pmic_chip->dev, pmr_addr[i], &pmr, 1);
            if (rc) {
                pr_err("%s: FAIL ssbi_write(0x%x)=0x%x: rc=%d"
                       "\n", __func__, pmr_addr[i], pmr, rc);
                goto get_out;
            }
            mdelay(DELAY_AFTER_REG_DISABLE_MS);
        }
    }

get_out:
    mdelay(DELAY_BEFORE_SHUTDOWN_MS);
    return rc;
}
Beispiel #15
0
int pm8901_reset_pwr_off(int reset)
{
	int rc = 0, i;
	u8 pmr;
	u8 pmr_addr[4] = {
		SSBI_REG_ADDR_S2_PMR,
		SSBI_REG_ADDR_S3_PMR,
		SSBI_REG_ADDR_S4_PMR,
		SSBI_REG_ADDR_S1_PMR,
	};

	if (pmic_chip == NULL)
		return -ENODEV;

	/* Turn off regulators S1, S2, S3, S4 when shutting down. */
	if (!reset) {
		for (i = 0; i < 4; i++) {
			rc = ssbi_read(pmic_chip->dev, pmr_addr[i], &pmr, 1);
			if (rc) {
				pr_err("%s: FAIL ssbi_read(0x%x): rc=%d\n",
				       __func__, pmr_addr[i], rc);
				goto get_out;
			}

			pmr &= ~REGULATOR_PMR_STATE_MASK;
			pmr |= REGULATOR_PMR_STATE_OFF;

			rc = ssbi_write(pmic_chip->dev, pmr_addr[i], &pmr, 1);
			/* changed from 4 to 10 because S3B voltage fail in Q1LTE*/
			mdelay(10); /* 10ms delay between regulator turn Off */
			if (rc) {
				pr_err("%s: FAIL ssbi_write(0x%x)=0x%x: rc=%d"
				       "\n", __func__, pmr_addr[i], pmr, rc);
				goto get_out;
			}
		}
	}

get_out:
	return rc;
}
Beispiel #16
0
static inline int
pm8901_read_block(struct pm8901_chip *chip, u8 *bp, u8 *ip)
{
	int	rc;

	rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp, 1);
	if (rc) {
		pr_err("%s: FAIL ssbi_write(): rc=%d (Select Block)\n",
		       __func__, rc);
		*bp = 0;
		goto bail_out;
	}

	rc = ssbi_read(chip->dev, SSBI_REG_ADDR_IRQ_IT_STATUS, ip, 1);
	if (rc)
		pr_err("%s: FAIL ssbi_read(): rc=%d (Read Status)\n",
		       __func__, rc);

bail_out:
	return rc;
}
Beispiel #17
0
int pm8058_irq_get_rt_status(struct pm8058_chip *chip, int irq)
{
	int     rc;
	u8      block, bits, bit;

	if (chip == NULL || irq < chip->pdata.irq_base ||
			irq >= chip->pdata.irq_base + MAX_PM_IRQ)
		return -EINVAL;

	irq -= chip->pdata.irq_base;

	block = irq / 8;
	bit = irq % 8;

	mutex_lock(&chip->pm_lock);

	rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, &block, 1);
	if (rc) {
		pr_err("%s: FAIL ssbi_write(): rc=%d (Select Block)\n",
				__func__, rc);
		goto bail_out;
	}

	rc = ssbi_read(chip->dev, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits, 1);
	if (rc) {
		pr_err("%s: FAIL ssbi_read(): rc=%d (Read RT Status)\n",
				__func__, rc);
		goto bail_out;
	}

	rc = (bits & (1 << bit)) ? 1 : 0;

bail_out:
	mutex_unlock(&chip->pm_lock);

	return rc;
}
/*
 * Set an SMPS regulator to be disabled in its CTRL register, but enabled
 * in the master enable register.  Also set it's pull down enable bit.
 * Take care to make sure that the output voltage doesn't change if switching
 * from advanced mode to legacy mode.
 */
static int disable_smps_locally_set_pull_down(u16 ctrl_addr, u16 test2_addr,
		u16 master_enable_addr, u8 master_enable_bit)
{
	int rc = 0;
	u8 vref_sel, vlow_sel, band, vprog, bank, reg;

	if (pmic_chip == NULL)
		return -ENODEV;

	bank = REGULATOR_BANK_SEL(7);
	rc = ssbi_write(pmic_chip->dev, test2_addr, &bank, 1);
	if (rc) {
		pr_err("%s: FAIL ssbi_write(0x%03X): rc=%d\n", __func__,
			test2_addr, rc);
		goto done;
	}

	rc = ssbi_read(pmic_chip->dev, test2_addr, &reg, 1);
	if (rc) {
		pr_err("%s: FAIL pm8058_read(0x%03X): rc=%d\n",
		       __func__, test2_addr, rc);
		goto done;
	}

	/* Check if in advanced mode. */
	if ((reg & SMPS_ADVANCED_MODE_MASK) == SMPS_ADVANCED_MODE) {
		/* Determine current output voltage. */
		rc = ssbi_read(pmic_chip->dev, ctrl_addr, &reg, 1);
		if (rc) {
			pr_err("%s: FAIL pm8058_read(0x%03X): rc=%d\n",
			       __func__, ctrl_addr, rc);
			goto done;
		}

		band = (reg & SMPS_ADVANCED_BAND_MASK)
			>> SMPS_ADVANCED_BAND_SHIFT;
		switch (band) {
		case 3:
			vref_sel = 0;
			vlow_sel = 0;
			break;
		case 2:
			vref_sel = SMPS_LEGACY_VREF_SEL;
			vlow_sel = 0;
			break;
		case 1:
			vref_sel = SMPS_LEGACY_VREF_SEL;
			vlow_sel = SMPS_LEGACY_VLOW_SEL;
			break;
		default:
			pr_err("%s: regulator already disabled\n", __func__);
			return -EPERM;
		}
		vprog = (reg & SMPS_ADVANCED_VPROG_MASK);
		/* Round up if fine step is in use. */
		vprog = (vprog + 1) >> 1;
		if (vprog > SMPS_LEGACY_VPROG_MASK)
			vprog = SMPS_LEGACY_VPROG_MASK;

		/* Set VLOW_SEL bit. */
		bank = REGULATOR_BANK_SEL(1);
		rc = ssbi_write(pmic_chip->dev, test2_addr, &bank, 1);
		if (rc) {
			pr_err("%s: FAIL ssbi_write(0x%03X): rc=%d\n",
			       __func__, test2_addr, rc);
			goto done;
		}
		rc = pm8058_masked_write(test2_addr,
			REGULATOR_BANK_WRITE | REGULATOR_BANK_SEL(1)
				| vlow_sel,
			REGULATOR_BANK_WRITE | REGULATOR_BANK_MASK
				| SMPS_LEGACY_VLOW_SEL);
		if (rc)
			goto done;

		/* Switch to legacy mode */
		bank = REGULATOR_BANK_SEL(7);
		rc = ssbi_write(pmic_chip->dev, test2_addr, &bank, 1);
		if (rc) {
			pr_err("%s: FAIL ssbi_write(0x%03X): rc=%d\n", __func__,
				test2_addr, rc);
			goto done;
		}
		rc = pm8058_masked_write(test2_addr,
				REGULATOR_BANK_WRITE | REGULATOR_BANK_SEL(7)
					| SMPS_LEGACY_MODE,
				REGULATOR_BANK_WRITE | REGULATOR_BANK_MASK
					| SMPS_ADVANCED_MODE_MASK);
		if (rc)
			goto done;

		/* Enable locally, enable pull down, keep voltage the same. */
		rc = pm8058_masked_write(ctrl_addr,
			REGULATOR_ENABLE | REGULATOR_PULL_DOWN_EN
				| vref_sel | vprog,
			REGULATOR_ENABLE_MASK | REGULATOR_PULL_DOWN_MASK
			       | SMPS_LEGACY_VREF_SEL | SMPS_LEGACY_VPROG_MASK);
		if (rc)
			goto done;
	}
static long ftr_ioctl(struct file *file,
	unsigned int cmd, unsigned long arg)
{
	unsigned int __user *argp = (unsigned int __user *) arg;
	struct ftr_dev_file_info *pdfi =
		(struct ftr_dev_file_info *) file->private_data;
	struct ftr_dev_node_info *pdev;

	if (pdfi->ftrid < 0 || pdfi->ftrid >= RFIC_DEVICE_NUM)
		return -EINVAL;

	pdev = ftr_dev_info + pdfi->ftrid;

	switch (cmd) {
	case RFIC_IOCTL_READ_REGISTER:
		{
		    int ret = 0;
		    unsigned int rficaddr;
		    u8 value = 0;

		    if (get_user(rficaddr, argp))
			return -EFAULT;

		    mutex_lock(&pdev->lock);

		    if (((pdfi->ftrid == 1) || (pdfi->ftrid == 2))
				&& (rfbid < RF_TYPE_48)) {
			__raw_writel(
				pdev->busselect[RFIC_FTR_GET_BUS(rficaddr)],
				pdev->grfcctrladdr);
			mb();
		    }

		    ret = ssbi_read(pdev->dev->parent,
			RFIC_FTR_GET_ADDR(rficaddr), &value, 1);

		    mutex_unlock(&pdev->lock);

		    if (ret)
			return ret;

		    if (put_user(value, argp))
			return -EFAULT;
}

	break;

	case RFIC_IOCTL_WRITE_REGISTER:
		{
		    int ret;
		    struct rfic_write_register_param param;
		    unsigned int rficaddr;
		    u8 value;

		    if (copy_from_user(&param, argp, sizeof(param)))
			return -EFAULT;
		    rficaddr = param.rficaddr;
		    value = (u8) param.value;

		    mutex_lock(&pdev->lock);

		    if (((pdfi->ftrid == 1) || (pdfi->ftrid == 2))
				&& (rfbid < RF_TYPE_48)) {
			__raw_writel(
				pdev->busselect[RFIC_FTR_GET_BUS(rficaddr)],
				pdev->grfcctrladdr);
			mb();
		    }

		    ret = ssbi_write(pdev->dev->parent,
			RFIC_FTR_GET_ADDR(rficaddr), &value, 1);

		    mutex_unlock(&pdev->lock);

		    if (ret)
			return ret;
		}
		break;

	case RFIC_IOCTL_WRITE_REGISTER_WITH_MASK:
		{
			int ret;
			struct rfic_write_register_mask_param param;
			unsigned int rficaddr;
			u8 value;

			if (copy_from_user(&param, argp, sizeof(param)))
				return -EFAULT;

			rficaddr = param.rficaddr;

			mutex_lock(&pdev->lock);

			if (((pdfi->ftrid == 1) || (pdfi->ftrid == 2))
				&& (rfbid < RF_TYPE_48)) {
				__raw_writel(
				pdev->busselect[RFIC_FTR_GET_BUS(rficaddr)],
				pdev->grfcctrladdr);
				mb();
			}

			ret = ssbi_read(pdev->dev->parent,
				RFIC_FTR_GET_ADDR(rficaddr), &value, 1);

			value &= (u8) ~param.mask;
			value |= (u8) (param.value & param.mask);
			ret = ssbi_write(pdev->dev->parent,
				RFIC_FTR_GET_ADDR(rficaddr), &value, 1);

			mutex_unlock(&pdev->lock);

			if (ret)
				return ret;
		}
		break;

	case RFIC_IOCTL_GPIO_SETTING:
		{
			struct rfic_gpio_param param;
			struct msm_gpiomux_config rf_config[MSM_MAX_GPIO];
			struct gpiomux_setting rf_setting[MSM_MAX_GPIO];
			struct gpio_alt_config *alt_config;
			int gp_size, i;
			void *pGP;

			if (pdfi->ftrid != 0)
				return -EINVAL;

			if (copy_from_user(&param, argp, sizeof(param))) {
				pr_err("%s: cfu fail for param\n", __func__);
				return -EFAULT;
			}

			if ((param.num < 1) || (param.num > MSM_MAX_GPIO)) {
				pr_err("Invalid GPIO count %d\n", param.num);
				return -EINVAL;
			}

			gp_size = sizeof(struct gpio_alt_config) * param.num;

			pGP = kmalloc(gp_size, GFP_KERNEL);
			if (pGP == NULL)
				return -ENOMEM;

			if (copy_from_user(pGP, param.pArray, gp_size)) {
				pr_err("%s: cfu fail for pGP\n", __func__);
				kfree(pGP);
				return -EFAULT;
			}

			alt_config = (struct gpio_alt_config *)pGP;
			for (i = 0; i < param.num; i++) {
				rf_config[i].gpio = (unsigned)alt_config->gpio;
				rf_setting[i].func = alt_config->func;
				rf_setting[i].drv = alt_config->drv;
				rf_setting[i].pull = alt_config->pull;
				rf_setting[i].dir = alt_config->dir;
				rf_config[i].settings[GPIOMUX_ACTIVE] =
					&rf_setting[i];
				rf_config[i].settings[GPIOMUX_SUSPENDED] =
					&rf_setting[i];
				alt_config++;
			}
			msm_gpiomux_install(rf_config, param.num);
			kfree(pGP);
		}
		break;

	case RFIC_IOCTL_GET_GRFC:
		{
			struct rfic_grfc_param param;

			if (pdfi->ftrid != 0)
				return -EINVAL;

			if (copy_from_user(&param, argp, sizeof(param)))
				return -EFAULT;

			if (param.grfcid >= RFIC_GRFC_REG_NUM)
				return -EINVAL;

			param.maskvalue = __raw_readl(
				grfc_base + 0x20 + param.grfcid * 4);
			param.ctrlvalue = __raw_readl(
				grfc_base + param.grfcid * 4);

			if (copy_to_user(argp, &param, sizeof(param)))
				return -EFAULT;
		}
		break;

	case RFIC_IOCTL_SET_GRFC:
		{
			struct rfic_grfc_param param;

			if (pdfi->ftrid != 0)
				return -EINVAL;

			if (copy_from_user(&param, argp, sizeof(param)))
				return -EFAULT;

			if (param.grfcid >= RFIC_GRFC_REG_NUM)
				return -EINVAL;

			__raw_writel(0, grfc_base + 0x20 + param.grfcid * 4);
			__raw_writel(param.ctrlvalue,
				grfc_base + param.grfcid * 4);
			__raw_writel(param.maskvalue,
				grfc_base + 0x20 + param.grfcid * 4);
			mb();
		}
		break;

	case RFIC_IOCTL_SET_WFM:
		{
			struct rfic_wfm_param param;
			unsigned int p_sum;

			if (pdfi->ftrid != 0)
				return -EINVAL;

			if (copy_from_user(&param, argp, sizeof(param)))
				return -EFAULT;

			/* Check for integer overflow */
			if (param.offset > UINT_MAX - param.num)
				return -EINVAL;

			p_sum = param.offset + param.num;

			if (p_sum < param.offset || p_sum < param.num)
				return -EINVAL;

			if (p_sum  >  RF_MAX_WF_SIZE)
				return -EINVAL;

			if (copy_from_user(wf_base + param.offset,
					param.pArray, param.num))
				return -EFAULT;
		}
		break;

	case RFIC_IOCTL_SET_LDO:
		{
			unsigned int ldo;

			if (pdfi->ftrid != 0) {
				pr_err("%s: Invalid id %d\n", __func__,
					pdfi->ftrid);
				return -EINVAL;
			}

			if (get_user(ldo, argp)) {
				pr_err("%s: Invalid ldo %d\n", __func__, ldo);
				return -EFAULT;
			}

			switch (ldo) {
			case LDO11:
				if (rf_regulator_init(to_platform_device
					(pdev->dev), "vdd-1v3", 0) != 0)
					pr_err("%s: LDO11 fail\n", __func__);
					break;
			case LDO18:
				if (rf_regulator_init(to_platform_device
					(pdev->dev), "vdd-switch", 0) != 0)
					pr_err("%s: LDO18 fail\n", __func__);
					break;
			case LDO19:
				if (rf_regulator_init(to_platform_device
					(pdev->dev), "vdd-wtr", 0) != 0)
					pr_err("%s: LDO19 fail\n", __func__);
					break;
			case LDO23:
				if (rf_regulator_init(to_platform_device
					(pdev->dev), "vdd-ftr1", 1) != 0)
					pr_err("%s: LDO23 fail\n", __func__);
					break;
			case LDO25:
				if (rf_regulator_init(to_platform_device
					(pdev->dev), "vdd-ftr2", 1) != 0)
					pr_err("%s: LDO25 fail\n", __func__);
					break;
			case LDO26:
				if (rf_regulator_init(to_platform_device
					(pdev->dev), "vdd-1v8", 1) != 0)
					pr_err("%s: LDO26 fail\n", __func__);
					break;
			default:
					pr_err("%s: Unknown LDO\n", __func__);
					break;
			}
		}
		break;

	case RFIC_IOCTL_SET_BOARDID:
		{
			if (pdfi->ftrid != 0)
				return -EINVAL;

			if (get_user(rfbid, argp))
				return -EFAULT;
		}
		break;

	case RFIC_IOCTL_GET_BOARDID:
		{
			if (pdfi->ftrid != 0)
				return -EINVAL;

			if (put_user(rfbid, argp))
				return -EFAULT;
		}
		break;

	case RFIC_IOCTL_GET_PDM:
		{
			struct pdm_param param;
			void __iomem *pdmaddr;
			int num;

			if (copy_from_user(&param, argp, sizeof(param))) {
				pr_err("%s: CFU\n", __func__);
				return -EFAULT;
			}

			if ((pdfi->ftrid != 0)  || (param.num > 5)) {
				pr_err("%s: ftrid %d num =%d\n", __func__,
					pdfi->ftrid, param.num);
				return -EINVAL;
			}

			mutex_lock(&pdev->lock);

			if (param.num > 2)
				num = param.num + 1;
			else
				num = param.num;

			pdmaddr = pdm_base + PDM_1_1_CTL * num;
			param.enable = __raw_readl(pdmaddr);
			param.value = __raw_readl(pdmaddr + 4);

			mutex_unlock(&pdev->lock);

			if (copy_to_user(argp, &param, sizeof(param))) {
				pr_err("%s: CTU\n", __func__);
				return -EFAULT;
			}
			return 0;
		}
		break;

	case RFIC_IOCTL_SET_PDM:
		{
			struct pdm_param param;
			void __iomem *pdmaddr;
			u16 value;
			int num;

			if (copy_from_user(&param, argp, sizeof(param))) {
				pr_err("%s: CFU\n", __func__);
				return -EFAULT;
			}

			if ((pdfi->ftrid != 0)  || (param.num > 5)) {
				pr_err("%s: Invalid id or num\n", __func__);
				return -EINVAL;
			}

			mutex_lock(&pdev->lock);

			if (param.num > 2)
				num = param.num + 1;
			else
				num = param.num;

			value = (u16) param.value;
			pdmaddr = pdm_base + PDM_1_1_CTL * num;
			__raw_writel(param.enable, pdmaddr);
			if (param.enable)
				__raw_writel(value, pdmaddr + 4);
			mutex_unlock(&pdev->lock);
			return 0;
		}
		break;

	default:
		return -EINVAL;
	}

	return 0;
}
static int ftr_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	struct ftr_dev_node_info *ptr;
	struct resource *mem_res;
	struct clk *pdm_clk;
	int ret;
	u8 version = 0;

	pr_debug("%s: me = %p, parent = %p\n",
		__func__, pdev, pdev->dev.parent);

	mutex_lock(&rficlock);

	if (n_dev >= RFIC_DEVICE_NUM) {
		pr_warn("%s: Invalid devices %d\n", __func__, n_dev);
		mutex_unlock(&rficlock);
		return -EINVAL;
	}

	if (!n_dev) {
		rfbid = rf_interface_id();
		if ((rfbid != 0xff) && (rfbid != 0))
			rfbid = rfbid & RF_TYPE_48;

		switch (rfbid) {
		case RF_TYPE_16:
			ftr_regulator_init(pdev);
			break;
		case RF_TYPE_32:
			glu_regulator_init(pdev);
			break;
		case RF_TYPE_48:
			mtr_regulator_init(pdev);
			break;
		default:
			pr_warn("%s:Regulators not turned ON %d\n",
					__func__, rfbid);
		}

		rfbid = rf_interface_id();
		pr_info("%s: RF Board Id 0x%x\n", __func__, rfbid);

		mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
		grfc_base = devm_ioremap_resource(&pdev->dev, mem_res);
		if (IS_ERR(grfc_base)) {
			mutex_unlock(&rficlock);
			return PTR_ERR(grfc_base);
		}

		mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
		wf_base = devm_ioremap_resource(&pdev->dev, mem_res);
		if (IS_ERR(wf_base)) {
			mutex_unlock(&rficlock);
			return PTR_ERR(wf_base);
		}

		mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
		pdm_base = devm_ioremap_resource(&pdev->dev, mem_res);
		if (IS_ERR(pdm_base)) {
			mutex_unlock(&rficlock);
			return PTR_ERR(pdm_base);
		}

		ret = device_create_file(&pdev->dev, &dev_attr_rfboard_id);
		WARN_ON(ret);

		pdm_clk = clk_get(&pdev->dev, "ahb_clk");
		if (IS_ERR(pdm_clk)) {
			pdm_clk = NULL;
			pr_err("%s: AHB CLK is  NULL\n", __func__);
		} else {
			pr_debug("%s: AHB CLK is  0x%x\n", __func__,
				(unsigned int)pdm_clk);
			clk_prepare(pdm_clk);
			clk_enable(pdm_clk);
		}

		pdm_clk = clk_get(&pdev->dev, "pdm2_clk");
		if (IS_ERR(pdm_clk)) {
			pdm_clk = NULL;
			pr_err("%s: PDM2 CLK is  NULL\n", __func__);
		} else {
			pr_debug("%s: PDM2 CLK is  0x%x\n", __func__,
				(unsigned int)pdm_clk);
			clk_prepare(pdm_clk);
			clk_enable(pdm_clk);
		}

		if ((rfbid > RF_TYPE_48) && (rfbid != 0xff)) {
			fsm9900_mtr_init();
			pdm_mtr_enable();
			pr_info("%s: MTR PDM Enabled\n", __func__);
		} else if ((rfbid > RF_TYPE_16) && (rfbid < RF_TYPE_32)) {
			fsm9900_rfic_init();
			pdm_enable();
			pr_info("%s: PDM Enabled\n", __func__);
		} else if ((rfbid > RF_TYPE_32) && (rfbid < RF_TYPE_48)) {
			fsm9900_gluon_init();
			pr_info("%s: Gluon Enabled\n", __func__);
		} else {
			pr_warn("%s:PDMs not configured %d\n",
					__func__, rfbid);
		}

	}

	ptr = ftr_dev_info + n_dev;
	ptr->dev = &pdev->dev;

	if ((n_dev >= 1)  && (n_dev <= 7)) {
		struct ssbi *ssbi =
		platform_get_drvdata(to_platform_device(pdev->dev.parent));
		if ((rfbid > RF_TYPE_48) && (n_dev <= 4)) {
			ssbi->controller_type =
				FSM_SBI_CTRL_GENI_SSBI2_ARBITER;
			set_ssbi_mode_2(ssbi->base);
			pr_debug("%s: SSBI2 = 0x%x\n", __func__,
				ssbi->controller_type);
			rfic_pvc_enable(ssbi->base, 3);
		} else {
			ssbi->controller_type =
				FSM_SBI_CTRL_GENI_SSBI_ARBITER;
			set_ssbi_mode_1(ssbi->base);
			pr_debug("%s: SSBI1 = 0x%x\n", __func__,
				ssbi->controller_type);
			if ((n_dev == 1) || (n_dev == 2))
				rfic_pvc_enable(ssbi->base, 1);
			if ((n_dev == 3) && (rfbid > RF_TYPE_16)
					&& (rfbid < RF_TYPE_32))
				rfic_pvc_enable(ssbi->base, 2);
		}
		platform_set_drvdata(to_platform_device(pdev->dev.parent),
				ssbi);
	}

	if ((rfbid > RF_TYPE_16) && (rfbid < RF_TYPE_48) && (n_dev == 1)) {
		ssbi_write(pdev->dev.parent, 0xff, &version, 1);
		ssbi_read(pdev->dev.parent, 0x2, &version, 1);
		pr_info("%s: FTR1 Version = %02x\n", __func__, version);

		ptr->grfcctrladdr = grfc_base + 0x10; /* grp 4 */
		ptr->grfcmaskaddr = grfc_base + 0x30;
		__raw_writel(0x00001800, ptr->grfcmaskaddr);
		ptr->maskvalue = 0x00001800;
		ptr->busselect[TX1_BUS] = 0x00000000;
		ptr->busselect[TX2_BUS] = 0x00001000;
		ptr->busselect[MISC_BUS] = 0x00000800;
		ptr->busselect[RX_BUS] = 0x00001800;
	} else if ((rfbid > RF_TYPE_16) && (rfbid < RF_TYPE_48) &&
		(n_dev == 2)) {
		ssbi_write(pdev->dev.parent, 0xff, &version, 1);
		ssbi_read(pdev->dev.parent, 0x2, &version, 1);
		pr_info("%s: FTR2 Version = %02x\n", __func__, version);

		ptr->grfcctrladdr = grfc_base + 0x14; /* grp 5*/
		ptr->grfcmaskaddr = grfc_base + 0x34;
		__raw_writel(0x00000600, ptr->grfcmaskaddr);
		ptr->maskvalue = 0x00000600;
		ptr->busselect[TX1_BUS] = 0x000000;
		ptr->busselect[TX2_BUS] = 0x00000400;
		ptr->busselect[MISC_BUS] = 0x00000200;
		ptr->busselect[RX_BUS] = 0x00000600;
	}

	mutex_init(&ptr->lock);

	if (rfbid < RF_TYPE_48) {
		ret = misc_register(ftr_misc_dev + n_dev);

		if (ret < 0) {
			misc_deregister(ftr_misc_dev + n_dev);
			mutex_unlock(&rficlock);
			return ret;
		}
	} else {
		ret = misc_register(mtr_misc_dev + n_dev);

		if (ret < 0) {
			misc_deregister(mtr_misc_dev + n_dev);
			mutex_unlock(&rficlock);
			return ret;
		}
	}

	n_dev++;
	pr_debug("%s: num_of_ssbi_devices = %d\n", __func__, n_dev);
	mutex_unlock(&rficlock);

	return of_platform_populate(np, NULL, NULL, &pdev->dev);
}
Beispiel #21
0
int pm8058_reset_pwr_off(int reset)
{
	int		rc;
	u8		pon;
	u8		ctrl;
	u8		smpl;

	if (pmic_chip == NULL)
		return -ENODEV;

	mutex_lock(&pmic_chip->pm_lock);

	/* Set regulator L22 to 1.225V in high power mode. */
	rc = ssbi_read(pmic_chip->dev, SSBI_REG_ADDR_L22_CTRL, &ctrl, 1);
	if (rc) {
		pr_err("%s: FAIL ssbi_read(0x%x): rc=%d\n", __func__,
			SSBI_REG_ADDR_L22_CTRL, rc);
		goto get_out3;
	}
	/* Leave pull-down state intact. */
	ctrl &= 0x40;
	ctrl |= 0x93;
	rc = ssbi_write(pmic_chip->dev, SSBI_REG_ADDR_L22_CTRL, &ctrl, 1);
	if (rc)
		pr_err("%s: FAIL ssbi_write(0x%x)=0x%x: rc=%d\n", __func__,
			SSBI_REG_ADDR_L22_CTRL, ctrl, rc);

get_out3:
	if (!reset) {
		/* Only modify the SLEEP_CNTL reg if shutdown is desired. */
		rc = ssbi_read(pmic_chip->dev, SSBI_REG_ADDR_SLEEP_CNTL,
			       &smpl, 1);
		if (rc) {
			pr_err("%s: FAIL ssbi_read(0x%x): rc=%d\n",
			       __func__, SSBI_REG_ADDR_SLEEP_CNTL, rc);
			goto get_out2;
		}

		smpl &= ~PM8058_SLEEP_SMPL_EN_MASK;
		smpl |= PM8058_SLEEP_SMPL_EN_PWR_OFF;

		rc = ssbi_write(pmic_chip->dev, SSBI_REG_ADDR_SLEEP_CNTL,
				&smpl, 1);
		if (rc)
			pr_err("%s: FAIL ssbi_write(0x%x)=0x%x: rc=%d\n",
			       __func__, SSBI_REG_ADDR_SLEEP_CNTL, smpl, rc);
	}

get_out2:
	rc = ssbi_read(pmic_chip->dev, SSBI_REG_ADDR_PON_CNTL_1, &pon, 1);
	if (rc) {
		pr_err("%s: FAIL ssbi_read(0x%x): rc=%d\n",
		       __func__, SSBI_REG_ADDR_PON_CNTL_1, rc);
		goto get_out;
	}

	pon &= ~PM8058_PON_WD_EN_MASK;
	pon |= reset ? PM8058_PON_WD_EN_RESET : PM8058_PON_WD_EN_PWR_OFF;

	rc = ssbi_write(pmic_chip->dev, SSBI_REG_ADDR_PON_CNTL_1, &pon, 1);
	if (rc) {
		pr_err("%s: FAIL ssbi_write(0x%x)=0x%x: rc=%d\n",
		       __func__, SSBI_REG_ADDR_PON_CNTL_1, pon, rc);
		goto get_out;
	}

get_out:
	mutex_unlock(&pmic_chip->pm_lock);

	return rc;
}