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;
}
Beispiel #2
0
static int ftr_ssbi_write(
	struct ftr_dev_node_info *pdev,
	unsigned int addr,
	u8 *buf,
	size_t len)
{
	int ret;
	struct i2c_msg msg = {
		.addr = addr,
		.flags = 0x0,
		.buf = (u8 *) buf,
		.len = len,
	};

	ret = i2c_transfer(pdev->ssbi_adap, &msg, 1);

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

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_FTR_DEVICE_NUM)
		return -EINVAL;

	pdev = ftr_dev_info + pdfi->ftrId;

	switch (cmd) {
	case RFIC_IOCTL_READ_REGISTER:
		{
			int ret;
			unsigned int rficAddr;
			u8 value;

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

			mutex_lock(&pdev->lock);
			mb();
			
			__raw_writel(
				pdev->busSelect[RFIC_FTR_GET_BUS(rficAddr)],
				pdev->grfcCtrlAddr);
			__raw_writel(
				pdev->busSelect[RFIC_FTR_GET_BUS(rficAddr)],
				pdev->grfcCtrlAddr);
			mb();
			ret = ftr_ssbi_read(pdev, 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);
			mb();
			
			__raw_writel(
				pdev->busSelect[RFIC_FTR_GET_BUS(rficAddr)],
				pdev->grfcCtrlAddr);
			__raw_writel(
				pdev->busSelect[RFIC_FTR_GET_BUS(rficAddr)],
				pdev->grfcCtrlAddr);
			mb();
			ret = ftr_ssbi_write(pdev, 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);
			mb();
			
			__raw_writel(
				pdev->busSelect[RFIC_FTR_GET_BUS(rficAddr)],
				pdev->grfcCtrlAddr);
			__raw_writel(
				pdev->busSelect[RFIC_FTR_GET_BUS(rficAddr)],
				pdev->grfcCtrlAddr);
			mb();
			ret = ftr_ssbi_read(pdev, RFIC_FTR_GET_ADDR(rficAddr),
				&value, 1);
			value &= (u8) ~param.mask;
			value |= (u8) (param.value & param.mask);
			ret = ftr_ssbi_write(pdev, RFIC_FTR_GET_ADDR(rficAddr),
				&value, 1);
			mutex_unlock(&pdev->lock);

			if (ret)
				return ret;
		}
		break;

	case RFIC_IOCTL_GET_GRFC:
		{
			struct rfic_grfc_param param;

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

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

			param.maskValue = __raw_readl(
				MSM_GRFC_BASE + 0x18 + param.grfcId * 4);
			param.ctrlValue = __raw_readl(
				MSM_GRFC_BASE + 0x00 + 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 (copy_from_user(&param, argp, sizeof param))
				return -EFAULT;

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

			__raw_writel(param.maskValue,
				MSM_GRFC_BASE + 0x18 + param.grfcId * 4);
			
			__raw_writel(param.ctrlValue,
				MSM_GRFC_BASE + 0x00 + param.grfcId * 4);
			__raw_writel(param.ctrlValue,
				MSM_GRFC_BASE + 0x00 + param.grfcId * 4);
			mb();
		}
		break;

	default:
		return -EINVAL;
	}

	return 0;
}