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(¶m, 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(¶m, 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(¶m, 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(¶m, 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, ¶m, 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(¶m, 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(¶m, 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(¶m, 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, ¶m, 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(¶m, 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_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(¶m, 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(¶m, 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(¶m, 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, ¶m, sizeof param)) return -EFAULT; } break; case RFIC_IOCTL_SET_GRFC: { struct rfic_grfc_param param; if (copy_from_user(¶m, 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; }