Пример #1
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;
	}
Пример #3
0
static int pm8901_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	int	i, rc;
	struct	pm8901_platform_data *pdata = client->dev.platform_data;
	struct	pm8901_chip *chip;

	if (pdata == NULL || !client->irq) {
		pr_err("%s: No platform_data or IRQ.\n", __func__);
		return -ENODEV;
	}

	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {
		pr_err("%s: i2c_check_functionality failed.\n", __func__);
		return -ENODEV;
	}

	chip = kzalloc(sizeof *chip, GFP_KERNEL);
	if (chip == NULL) {
		pr_err("%s: kzalloc() failed.\n", __func__);
		return -ENOMEM;
	}

	chip->dev = client;

	/* Read PMIC chip revision */
	rc = ssbi_read(chip->dev, SSBI_REG_REV, &chip->revision, 1);
	if (rc)
		pr_err("%s: Failed on ssbi_read for revision: rc=%d.\n",
			__func__, rc);
	pr_info("%s: PMIC revision: %X\n", __func__, chip->revision);

	(void) memcpy((void *)&chip->pdata, (const void *)pdata,
		      sizeof(chip->pdata));

	set_irq_data(chip->dev->irq, (void *)chip);
	set_irq_wake(chip->dev->irq, 1);

	chip->pm_max_irq = 0;
	chip->pm_max_blocks = 0;
	chip->pm_max_masters = 0;

	i2c_set_clientdata(client, chip);

	pmic_chip = chip;
	spin_lock_init(&chip->pm_lock);

        // kmj_el15.pm8901_patch
        // This api is s/w workaround for PM8901's abnormal spike which could
        // cause DDR problem on PCB. Because of the spike SS made new PCB for
        // h/w workaround. This s/w workaround is for old PCBs. And If a target
        // is new PCB,  you should call a api to drop bypass voltage
        // to 1.725 originally. But you don't need that here, bacause you've done
        // that already at SBL3. So instead of calling api to drop bypass voltage 
        // here you just need to check if SBL3 bootloader includes the api.
        // In other words this api has dependency with SBL3 change
        if( pm8901_is_old_PCB_with_PM8901()==1 )
                pm8901_preload_dVdd();
	

	/* Register for all reserved IRQs */
	for (i = pdata->irq_base; i < (pdata->irq_base + MAX_PM_IRQ); i++) {
		set_irq_chip(i, &pm8901_irq_chip);
		set_irq_handler(i, handle_edge_irq);
		set_irq_flags(i, IRQF_VALID);
		set_irq_data(i, (void *)chip);
	}

	/* Add sub devices with the chip parameter as driver data */
	for (i = 0; i < pdata->num_subdevs; i++)
		pdata->sub_devices[i].driver_data = chip;
	rc = mfd_add_devices(&chip->dev->dev, 0, pdata->sub_devices,
			     pdata->num_subdevs, NULL, 0);
	if (rc) {
		pr_err("%s: could not add devices %d\n", __func__, rc);
		return rc;
	}

	rc = request_threaded_irq(chip->dev->irq, NULL, pm8901_isr_thread,
			IRQF_ONESHOT | IRQF_DISABLED | pdata->irq_trigger_flags,
			"pm8901-irq", chip);
	if (rc)
		pr_err("%s: could not request irq %d: %d\n", __func__,
				chip->dev->irq, rc);

	rc = pmic8901_dbg_probe(chip);
	if (rc < 0)
		pr_err("%s: could not set up debugfs: %d\n", __func__, rc);

	return rc;
}
Пример #4
0
static int pm8058_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	int	i, rc;
	struct	pm8058_platform_data *pdata = client->dev.platform_data;
	struct	pm8058_chip *chip;

	if (pdata == NULL || !client->irq) {
		pr_err("%s: No platform_data or IRQ.\n", __func__);
		return -ENODEV;
	}

	if (pdata->num_subdevs == 0) {
		pr_err("%s: No sub devices to support.\n", __func__);
		return -ENODEV;
	}

	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {
		pr_err("%s: i2c_check_functionality failed.\n", __func__);
		return -ENODEV;
	}

	chip = kzalloc(sizeof *chip, GFP_KERNEL);
	if (chip == NULL) {
		pr_err("%s: kzalloc() failed.\n", __func__);
		return -ENOMEM;
	}

	chip->dev = client;

	/* Read PMIC chip revision */
	rc = ssbi_read(chip->dev, SSBI_REG_REV, &chip->revision, 1);
	if (rc)
		pr_err("%s: Failed on ssbi_read for revision: rc=%d.\n",
			__func__, rc);
	pr_info("%s: PMIC revision: %X\n", __func__, chip->revision);

	(void) memcpy((void *)&chip->pdata, (const void *)pdata,
		      sizeof(chip->pdata));

	mutex_init(&chip->pm_lock);
	set_irq_data(chip->dev->irq, (void *)chip);
	set_irq_wake(chip->dev->irq, 1);

	chip->pm_max_irq = 0;
	chip->pm_max_blocks = 0;
	chip->pm_max_masters = 0;

	i2c_set_clientdata(client, chip);

	pmic_chip = chip;

	/* Register for all reserved IRQs */
	for (i = pdata->irq_base; i < (pdata->irq_base + MAX_PM_IRQ); i++) {
		set_irq_chip(i, &pm8058_irq_chip);
		set_irq_data(i, (void *)chip);
		set_irq_handler(i, handle_edge_irq);
		set_irq_flags(i, IRQF_VALID);
		set_irq_nested_thread(i, 1);
	}

	/* Add sub devices with the chip parameter as driver data */
	for (i = 0; i < pdata->num_subdevs; i++)
		pdata->sub_devices[i].driver_data = chip;
	rc = mfd_add_devices(&chip->dev->dev, 0, pdata->sub_devices,
			     pdata->num_subdevs, NULL, 0);

	if (pdata->init) {
		rc = pdata->init(chip);
		if (rc != 0) {
			pr_err("%s: board init failed\n", __func__);
			chip->dev = NULL;
			kfree(chip);
			return -ENODEV;
		}
	}

	rc = request_threaded_irq(chip->dev->irq, NULL, pm8058_isr_thread,
			IRQF_ONESHOT | IRQF_DISABLED | pdata->irq_trigger_flags,
			"pm8058-irq", chip);
	if (rc < 0)
		pr_err("%s: could not request irq %d: %d\n", __func__,
				chip->dev->irq, rc);

	rc = pmic8058_dbg_probe(chip);
	if (rc < 0)
		pr_err("%s: could not set up debugfs: %d\n", __func__, rc);

	return 0;
}
Пример #5
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;
}
Пример #6
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);
}
Пример #7
0
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;
}
Пример #8
0
static int pm8921_probe(struct platform_device *pdev)
{
	const struct pm8921_platform_data *pdata = pdev->dev.platform_data;
	const char *revision_name = "unknown";
	struct pm8921 *pmic;
	enum pm8xxx_version version;
	int revision;
	int rc;
	u8 val;

	if (!pdata) {
		pr_err("missing platform data\n");
		return -EINVAL;
	}

	pmic = kzalloc(sizeof(struct pm8921), GFP_KERNEL);
	if (!pmic) {
		pr_err("Cannot alloc pm8921 struct\n");
		return -ENOMEM;
	}

	/* Read PMIC chip revision */
	rc = ssbi_read(pdev->dev.parent, REG_HWREV, &val, sizeof(val));
	if (rc) {
		pr_err("Failed to read hw rev reg %d:rc=%d\n", REG_HWREV, rc);
		goto err_read_rev;
	}
	pr_info("PMIC revision 1: %02X\n", val);
	pmic->rev_registers = val;

	/* Read PMIC chip revision 2 */
	rc = ssbi_read(pdev->dev.parent, REG_HWREV_2, &val, sizeof(val));
	if (rc) {
		pr_err("Failed to read hw rev 2 reg %d:rc=%d\n",
			REG_HWREV_2, rc);
		goto err_read_rev;
	}
	pr_info("PMIC revision 2: %02X\n", val);
	pmic->rev_registers |= val << BITS_PER_BYTE;

	pmic->dev = &pdev->dev;
	pm8921_drvdata.pm_chip_data = pmic;
	platform_set_drvdata(pdev, &pm8921_drvdata);

	/* Print out human readable version and revision names. */
	version = pm8xxx_get_version(pmic->dev);
	revision = pm8xxx_get_revision(pmic->dev);
	if (version == PM8XXX_VERSION_8921) {
		if (revision >= 0 && revision < ARRAY_SIZE(pm8921_rev_names))
			revision_name = pm8921_rev_names[revision];
		pr_info("PMIC version: PM8921 rev %s\n", revision_name);
	} else if (version == PM8XXX_VERSION_8922) {
		if (revision >= 0 && revision < ARRAY_SIZE(pm8922_rev_names))
			revision_name = pm8922_rev_names[revision];
		pr_info("PMIC version: PM8922 rev %s\n", revision_name);
	} else if (version == PM8XXX_VERSION_8917) {
		if (revision >= 0 && revision < ARRAY_SIZE(pm8917_rev_names))
			revision_name = pm8917_rev_names[revision];
		pr_info("PMIC version: PM8917 rev %s\n", revision_name);
	} else {
		WARN_ON(version != PM8XXX_VERSION_8921
			&& version != PM8XXX_VERSION_8922
			&& version != PM8XXX_VERSION_8917);
	}

	/* Log human readable restart reason */
	rc = msm_ssbi_read(pdev->dev.parent, REG_PM8921_PON_CNTRL_3, &val, 1);
	if (rc) {
		pr_err("Cannot read restart reason rc=%d\n", rc);
		goto err_read_rev;
	}
	val &= PM8XXX_RESTART_REASON_MASK;
	pr_info("PMIC Restart Reason: %s\n", pm8xxx_restart_reason_str[val]);
	pmic->restart_reason = val;

	rc = pm8921_add_subdevices(pdata, pmic);
	if (rc) {
		pr_err("Cannot add subdevices rc=%d\n", rc);
		goto err;
	}

	/* gpio might not work if no irq device is found */
	WARN_ON(pmic->irq_chip == NULL);

	return 0;

err:
	mfd_remove_devices(pmic->dev);
	platform_set_drvdata(pdev, NULL);
	kfree(pmic->mfd_regulators);
	kfree(pmic->regulator_cdata);
err_read_rev:
	kfree(pmic);
	return rc;
}
Пример #9
0
static int pm8901_probe(struct platform_device *pdev)
{
	int i, rc;
	struct pm8901_platform_data *pdata = pdev->dev.platform_data;
	struct pm8901_chip *chip;

	if (pdata == NULL || pdata->irq <= 0) {
		pr_err("%s: No platform_data or IRQ.\n", __func__);
		return -ENODEV;
	}

	chip = kzalloc(sizeof *chip, GFP_KERNEL);
	if (chip == NULL) {
		pr_err("%s: kzalloc() failed.\n", __func__);
		return -ENOMEM;
	}

	chip->dev = &pdev->dev;

	/* Read PMIC chip revision */
	rc = ssbi_read(chip->dev, SSBI_REG_REV, &chip->revision, 1);
	if (rc)
		pr_err("%s: Failed on ssbi_read for revision: rc=%d.\n",
			__func__, rc);
	pr_info("%s: PMIC revision: %X\n", __func__, chip->revision);

	(void) memcpy((void *)&chip->pdata, (const void *)pdata,
		      sizeof(chip->pdata));

	irq_set_handler_data(pdata->irq, (void *)chip);
	irq_set_irq_wake(pdata->irq, 1);

	chip->pm_max_irq = 0;
	chip->pm_max_blocks = 0;
	chip->pm_max_masters = 0;

	platform_set_drvdata(pdev, chip);

	pmic_chip = chip;
	spin_lock_init(&chip->pm_lock);

	/* Register for all reserved IRQs */
	for (i = pdata->irq_base; i < (pdata->irq_base + MAX_PM_IRQ); i++) {
		irq_set_chip(i, &pm8901_irq_chip);
		irq_set_handler(i, handle_edge_irq);
		set_irq_flags(i, IRQF_VALID);
		irq_set_handler_data(i, (void *)chip);
	}

	rc = mfd_add_devices(chip->dev, 0, pdata->sub_devices,
			     pdata->num_subdevs, NULL, 0);
	if (rc) {
		pr_err("%s: could not add devices %d\n", __func__, rc);
		return rc;
	}

	rc = request_threaded_irq(pdata->irq, NULL, pm8901_isr_thread,
			IRQF_ONESHOT | IRQF_DISABLED | pdata->irq_trigger_flags,
			"pm8901-irq", chip);
	if (rc)
		pr_err("%s: could not request irq %d: %d\n", __func__,
				pdata->irq, rc);

	rc = pmic8901_dbg_probe(chip);
	if (rc < 0)
		pr_err("%s: could not set up debugfs: %d\n", __func__, rc);

	return rc;
}
Пример #10
0
static int pm8901_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	int	i, rc;
	struct	pm8901_platform_data *pdata = client->dev.platform_data;
	struct	pm8901_chip *chip;

	if (pdata == NULL || !client->irq) {
		pr_err("%s: No platform_data or IRQ.\n", __func__);
		return -ENODEV;
	}

	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {
		pr_err("%s: i2c_check_functionality failed.\n", __func__);
		return -ENODEV;
	}

	chip = kzalloc(sizeof *chip, GFP_KERNEL);
	if (chip == NULL) {
		pr_err("%s: kzalloc() failed.\n", __func__);
		return -ENOMEM;
	}

	chip->dev = client;

	
	rc = ssbi_read(chip->dev, SSBI_REG_REV, &chip->revision, 1);
	if (rc)
		pr_err("%s: Failed on ssbi_read for revision: rc=%d.\n",
			__func__, rc);
	pr_info("%s: PMIC revision: %X\n", __func__, chip->revision);

	(void) memcpy((void *)&chip->pdata, (const void *)pdata,
		      sizeof(chip->pdata));

	set_irq_data(chip->dev->irq, (void *)chip);
	set_irq_wake(chip->dev->irq, 1);

	chip->pm_max_irq = 0;
	chip->pm_max_blocks = 0;
	chip->pm_max_masters = 0;

	i2c_set_clientdata(client, chip);

	pmic_chip = chip;
	spin_lock_init(&chip->pm_lock);

	
	for (i = pdata->irq_base; i < (pdata->irq_base + MAX_PM_IRQ); i++) {
		set_irq_chip(i, &pm8901_irq_chip);
		set_irq_handler(i, handle_edge_irq);
		set_irq_flags(i, IRQF_VALID);
		set_irq_data(i, (void *)chip);
	}

	
	for (i = 0; i < pdata->num_subdevs; i++)
		pdata->sub_devices[i].driver_data = chip;
	rc = mfd_add_devices(&chip->dev->dev, 0, pdata->sub_devices,
			     pdata->num_subdevs, NULL, 0);
	if (rc) {
		pr_err("%s: could not add devices %d\n", __func__, rc);
		return rc;
	}

	rc = request_threaded_irq(chip->dev->irq, NULL, pm8901_isr_thread,
			IRQF_ONESHOT | IRQF_DISABLED | IRQF_TRIGGER_LOW,
			"pm8901-irq", chip);
	if (rc)
		pr_err("%s: could not request irq %d: %d\n", __func__,
				chip->dev->irq, rc);

	return rc;
}