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, ®, 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, ®, 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 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; }
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; }
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; }
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); }
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 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; }
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; }
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; }