Loading Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt +15 −3 Original line number Diff line number Diff line Loading @@ -93,7 +93,18 @@ LAB subnode required properties: 1130, 1070, 1010, 960, 910. - qcom,qpnp-lab-limit-maximum-current: The maximum inductor current limit in mA of LAB regulator. Supported values are 200, 400, 600 and 800. are 200, 400, 600, 800, 1000, 1200, 1400 and 1600. - interrupts: Specify the interrupts as per the interrupt encoding. Currently "lab-vreg-ok" is required for LCD mode in pmicobalt. For AMOLED mode, "lab-vreg-ok" is required only when SWIRE control is enabled and skipping 2nd SWIRE pulse is required in pmi8952/8996. - interrupt-names: Interrupt names to match up 1-to-1 with the interrupts specified in 'interrupts' property. LAB subnode optional properties: Loading Loading @@ -229,7 +240,8 @@ Example: reg = <0xde00 0x100>; reg-names = "lab"; interrupts = <0x3 0xde 0x0>; interrupts = <0x3 0xde 0x0 IRQ_TYPE_EDGE_RISING>; interrupt-names = "lab-vreg-ok"; regulator-name = "lab_reg"; Loading @@ -249,7 +261,7 @@ Example: qcom,qpnp-lab-full-pull-down; qcom,qpnp-lab-pull-down-enable; qcom,qpnp-lab-switching-clock-frequency = <1600>; qcom,qpnp-lab-limit-maximum-current = <800>; qcom,qpnp-lab-limit-maximum-current = <1600>; qcom,qpnp-lab-limit-max-current-enable; qcom,qpnp-lab-ps-threshold = <40>; qcom,qpnp-lab-ps-enable; Loading arch/arm/boot/dts/qcom/msm-pmi8994.dtsi +1 −1 Original line number Diff line number Diff line Loading @@ -497,7 +497,7 @@ qcom,qpnp-lab-pull-down-enable; qcom,qpnp-lab-switching-clock-frequency = <1600>; qcom,qpnp-lab-limit-maximum-current = <800>; qcom,qpnp-lab-limit-maximum-current = <1600>; qcom,qpnp-lab-limit-max-current-enable; qcom,qpnp-lab-ps-threshold = <20>; qcom,qpnp-lab-ps-enable; Loading arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi +4 −1 Original line number Diff line number Diff line Loading @@ -555,6 +555,9 @@ regulator-min-microvolt = <4600000>; regulator-max-microvolt = <6000000>; interrupts = <0x3 0xde 0x0 IRQ_TYPE_EDGE_RISING>; interrupt-names = "lab-vreg-ok"; qcom,qpnp-lab-min-voltage = <4600000>; qcom,qpnp-lab-step-size = <100000>; qcom,qpnp-lab-slew-rate = <5000>; Loading @@ -569,7 +572,7 @@ qcom,qpnp-lab-pull-down-enable; qcom,qpnp-lab-switching-clock-frequency = <1600>; qcom,qpnp-lab-limit-maximum-current = <800>; qcom,qpnp-lab-limit-maximum-current = <1600>; qcom,qpnp-lab-limit-max-current-enable; qcom,qpnp-lab-ps-threshold = <20>; qcom,qpnp-lab-ps-enable; Loading drivers/regulator/qpnp-labibb-regulator.c +163 −24 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ #define QPNP_LABIBB_REGULATOR_DRIVER_NAME "qcom,qpnp-labibb-regulator" #define REG_REVISION_2 0x01 #define REG_PERPH_TYPE 0x04 #define QPNP_LAB_TYPE 0x24 Loading Loading @@ -60,6 +61,7 @@ #define REG_LAB_PRECHARGE_CTL 0x5E #define REG_LAB_SOFT_START_CTL 0x5F #define REG_LAB_SPARE_CTL 0x60 #define REG_LAB_PFM_CTL 0x62 /* LAB register bits definitions */ Loading Loading @@ -91,9 +93,9 @@ #define LAB_IBB_EN_RDY_EN BIT(7) /* REG_LAB_CURRENT_LIMIT */ #define LAB_CURRENT_LIMIT_BITS 3 #define LAB_CURRENT_LIMIT_MASK ((1 << LAB_CURRENT_LIMIT_BITS) - 1) #define LAB_CURRENT_LIMIT_EN BIT(7) #define LAB_CURRENT_LIMIT_MASK GENMASK(2, 0) #define LAB_CURRENT_LIMIT_EN_BIT BIT(7) #define LAB_OVERRIDE_CURRENT_MAX_BIT BIT(3) /* REG_LAB_CURRENT_SENSE */ #define LAB_CURRENT_SENSE_GAIN_BITS 2 Loading Loading @@ -129,6 +131,9 @@ #define LAB_SPARE_TOUCH_WAKE_BIT BIT(3) #define LAB_SPARE_DISABLE_SCP_BIT BIT(0) /* REG_LAB_PFM_CTL */ #define LAB_PFM_EN_BIT BIT(7) /* IBB register offset definitions */ #define REG_IBB_REVISION4 0x03 #define REG_IBB_STATUS1 0x08 Loading Loading @@ -344,6 +349,10 @@ static const int lab_current_limit_plan[] = { 400, 600, 800, 1000, 1200, 1400, 1600, }; static const char * const lab_current_sense_plan[] = { Loading Loading @@ -471,6 +480,8 @@ struct qpnp_labibb { struct pmic_revid_data *pmic_rev_id; u16 lab_base; u16 ibb_base; u8 lab_dig_major; u8 ibb_dig_major; struct lab_regulator lab_vreg; struct ibb_regulator ibb_vreg; enum qpnp_labibb_mode mode; Loading @@ -481,6 +492,7 @@ struct qpnp_labibb { bool swire_control; bool ttw_force_lab_on; bool skip_2nd_swire_cmd; bool pfm_enable; u32 swire_2nd_cmd_delay; u32 swire_ibb_ps_enable_delay; }; Loading Loading @@ -783,7 +795,7 @@ static int qpnp_lab_dt_init(struct qpnp_labibb *labibb, if (of_property_read_bool(of_node, "qcom,qpnp-lab-limit-max-current-enable")) val |= LAB_CURRENT_LIMIT_EN; val |= LAB_CURRENT_LIMIT_EN_BIT; rc = qpnp_labibb_write(labibb, labibb->lab_base + REG_LAB_CURRENT_LIMIT, &val, 1); Loading Loading @@ -936,6 +948,88 @@ static int qpnp_lab_dt_init(struct qpnp_labibb *labibb, return rc; } #define LAB_CURRENT_MAX_1600MA 0x7 #define LAB_CURRENT_MAX_400MA 0x1 static int qpnp_lab_pfm_disable(struct qpnp_labibb *labibb) { int rc = 0; u8 val, mask; mutex_lock(&(labibb->lab_vreg.lab_mutex)); if (!labibb->pfm_enable) { pr_debug("PFM already disabled\n"); goto out; } val = 0; mask = LAB_PFM_EN_BIT; rc = qpnp_labibb_masked_write(labibb, labibb->lab_base + REG_LAB_PFM_CTL, mask, val); if (rc < 0) { pr_err("Write register %x failed rc = %d\n", REG_LAB_PFM_CTL, rc); goto out; } val = LAB_CURRENT_MAX_1600MA; mask = LAB_OVERRIDE_CURRENT_MAX_BIT | LAB_CURRENT_LIMIT_MASK; rc = qpnp_labibb_masked_write(labibb, labibb->lab_base + REG_LAB_CURRENT_LIMIT, mask, val); if (rc < 0) { pr_err("Write register %x failed rc = %d\n", REG_LAB_CURRENT_LIMIT, rc); goto out; } labibb->pfm_enable = false; out: mutex_unlock(&(labibb->lab_vreg.lab_mutex)); return rc; } static int qpnp_lab_pfm_enable(struct qpnp_labibb *labibb) { int rc = 0; u8 val, mask; mutex_lock(&(labibb->lab_vreg.lab_mutex)); if (labibb->pfm_enable) { pr_debug("PFM already enabled\n"); goto out; } /* Wait for ~100uS */ usleep_range(100, 105); val = LAB_OVERRIDE_CURRENT_MAX_BIT | LAB_CURRENT_MAX_400MA; mask = LAB_OVERRIDE_CURRENT_MAX_BIT | LAB_CURRENT_LIMIT_MASK; rc = qpnp_labibb_masked_write(labibb, labibb->lab_base + REG_LAB_CURRENT_LIMIT, mask, val); if (rc < 0) { pr_err("Write register %x failed rc = %d\n", REG_LAB_CURRENT_LIMIT, rc); goto out; } /* Wait for ~100uS */ usleep_range(100, 105); val = LAB_PFM_EN_BIT; mask = LAB_PFM_EN_BIT; rc = qpnp_labibb_masked_write(labibb, labibb->lab_base + REG_LAB_PFM_CTL, mask, val); if (rc < 0) { pr_err("Write register %x failed rc = %d\n", REG_LAB_PFM_CTL, rc); goto out; } labibb->pfm_enable = true; out: mutex_unlock(&(labibb->lab_vreg.lab_mutex)); return rc; } static int qpnp_labibb_restore_settings(struct qpnp_labibb *labibb) { int rc, i; Loading Loading @@ -1435,6 +1529,15 @@ static int qpnp_labibb_regulator_disable(struct qpnp_labibb *labibb) return -EINVAL; } if (labibb->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE && labibb->mode == QPNP_LABIBB_LCD_MODE) { rc = qpnp_lab_pfm_disable(labibb); if (rc < 0) { pr_err("Error in disabling PFM, rc=%d\n", rc); return rc; } } labibb->lab_vreg.vreg_enabled = 0; labibb->ibb_vreg.vreg_enabled = 0; Loading Loading @@ -1644,9 +1747,17 @@ static irqreturn_t lab_vreg_ok_handler(int irq, void *_labibb) struct qpnp_labibb *labibb = _labibb; int rc; if (labibb->skip_2nd_swire_cmd && labibb->lab_dig_major < 2) { rc = qpnp_skip_swire_command(labibb); if (rc) pr_err("Failed in 'qpnp_skip_swire_command' rc=%d\n", rc); if (rc < 0) pr_err("Failed in 'qpnp_skip_swire_command' rc=%d\n", rc); } else if (labibb->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE && labibb->mode == QPNP_LABIBB_LCD_MODE) { rc = qpnp_lab_pfm_enable(labibb); if (rc < 0) pr_err("Failed to config PFM, rc=%d\n", rc); } return IRQ_HANDLED; } Loading @@ -1661,6 +1772,23 @@ static int qpnp_lab_regulator_get_voltage(struct regulator_dev *rdev) return labibb->lab_vreg.curr_volt; } static bool is_lab_vreg_ok_irq_available(struct qpnp_labibb *labibb) { /* * LAB VREG_OK interrupt is used only to skip 2nd SWIRE command in * dig_major < 2 targets. For pmicobalt, it is used to enable PFM in * LCD mode. */ if (labibb->skip_2nd_swire_cmd && labibb->lab_dig_major < 2) return true; if (labibb->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE && labibb->mode == QPNP_LABIBB_LCD_MODE) return true; return false; } static struct regulator_ops qpnp_lab_ops = { .enable = qpnp_lab_regulator_enable, .disable = qpnp_lab_regulator_disable, Loading Loading @@ -1809,19 +1937,6 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb, } } if (labibb->skip_2nd_swire_cmd) { rc = devm_request_threaded_irq(labibb->dev, labibb->lab_vreg.lab_vreg_ok_irq, NULL, lab_vreg_ok_handler, IRQF_ONESHOT | IRQF_TRIGGER_RISING, "lab-vreg-ok", labibb); if (rc) { pr_err("Failed to register 'lab-vreg-ok' irq rc=%d\n", rc); return rc; } } val = (labibb->standalone) ? 0 : LAB_IBB_EN_RDY_EN; rc = qpnp_labibb_sec_write(labibb, labibb->lab_base, REG_LAB_IBB_EN_RDY, &val, 1); Loading Loading @@ -1899,6 +2014,19 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb, labibb->lab_vreg.vreg_enabled = 1; } if (is_lab_vreg_ok_irq_available(labibb)) { rc = devm_request_threaded_irq(labibb->dev, labibb->lab_vreg.lab_vreg_ok_irq, NULL, lab_vreg_ok_handler, IRQF_ONESHOT | IRQF_TRIGGER_RISING, "lab-vreg-ok", labibb); if (rc) { pr_err("Failed to register 'lab-vreg-ok' irq rc=%d\n", rc); return rc; } } rc = qpnp_labibb_read(labibb, &val, labibb->lab_base + REG_LAB_MODULE_RDY, 1); if (rc) { Loading Loading @@ -1953,7 +2081,6 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb, return -EINVAL; } mutex_init(&(labibb->lab_vreg.lab_mutex)); return 0; } Loading Loading @@ -2683,14 +2810,13 @@ static int register_qpnp_ibb_regulator(struct qpnp_labibb *labibb, return -EINVAL; } mutex_init(&(labibb->ibb_vreg.ibb_mutex)); return 0; } static int qpnp_lab_register_irq(struct device_node *child, struct qpnp_labibb *labibb) { if (labibb->skip_2nd_swire_cmd) { if (is_lab_vreg_ok_irq_available(labibb)) { labibb->lab_vreg.lab_vreg_ok_irq = of_irq_get_byname(child, "lab-vreg-ok"); if (labibb->lab_vreg.lab_vreg_ok_irq < 0) { Loading Loading @@ -2745,7 +2871,7 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) unsigned int base; struct device_node *child, *revid_dev_node; const char *mode_name; u8 type; u8 type, revision; int rc = 0; labibb = devm_kzalloc(&pdev->dev, Loading @@ -2763,6 +2889,9 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) labibb->dev = &(pdev->dev); labibb->pdev = pdev; mutex_init(&(labibb->lab_vreg.lab_mutex)); mutex_init(&(labibb->ibb_vreg.ibb_mutex)); revid_dev_node = of_parse_phandle(labibb->dev->of_node, "qcom,pmic-revid", 0); if (!revid_dev_node) { Loading Loading @@ -2817,6 +2946,7 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) labibb->skip_2nd_swire_cmd = of_property_read_bool(labibb->dev->of_node, "qcom,skip-2nd-swire-cmd"); rc = of_property_read_u32(labibb->dev->of_node, "qcom,swire-2nd-cmd-delay", &labibb->swire_2nd_cmd_delay); Loading Loading @@ -2846,6 +2976,13 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) return rc; } rc = qpnp_labibb_read(labibb, &revision, base + REG_REVISION_2, 1); if (rc) { pr_err("Reading REVISION_2 failed rc=%d\n", rc); goto fail_registration; } rc = qpnp_labibb_read(labibb, &type, base + REG_PERPH_TYPE, 1); if (rc) { Loading @@ -2856,6 +2993,7 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) switch (type) { case QPNP_LAB_TYPE: labibb->lab_base = base; labibb->lab_dig_major = revision; rc = qpnp_lab_register_irq(child, labibb); if (rc) { pr_err("Failed to register LAB IRQ rc=%d\n", Loading @@ -2869,6 +3007,7 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) case QPNP_IBB_TYPE: labibb->ibb_base = base; labibb->ibb_dig_major = revision; rc = register_qpnp_ibb_regulator(labibb, child); if (rc) goto fail_registration; Loading Loading
Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt +15 −3 Original line number Diff line number Diff line Loading @@ -93,7 +93,18 @@ LAB subnode required properties: 1130, 1070, 1010, 960, 910. - qcom,qpnp-lab-limit-maximum-current: The maximum inductor current limit in mA of LAB regulator. Supported values are 200, 400, 600 and 800. are 200, 400, 600, 800, 1000, 1200, 1400 and 1600. - interrupts: Specify the interrupts as per the interrupt encoding. Currently "lab-vreg-ok" is required for LCD mode in pmicobalt. For AMOLED mode, "lab-vreg-ok" is required only when SWIRE control is enabled and skipping 2nd SWIRE pulse is required in pmi8952/8996. - interrupt-names: Interrupt names to match up 1-to-1 with the interrupts specified in 'interrupts' property. LAB subnode optional properties: Loading Loading @@ -229,7 +240,8 @@ Example: reg = <0xde00 0x100>; reg-names = "lab"; interrupts = <0x3 0xde 0x0>; interrupts = <0x3 0xde 0x0 IRQ_TYPE_EDGE_RISING>; interrupt-names = "lab-vreg-ok"; regulator-name = "lab_reg"; Loading @@ -249,7 +261,7 @@ Example: qcom,qpnp-lab-full-pull-down; qcom,qpnp-lab-pull-down-enable; qcom,qpnp-lab-switching-clock-frequency = <1600>; qcom,qpnp-lab-limit-maximum-current = <800>; qcom,qpnp-lab-limit-maximum-current = <1600>; qcom,qpnp-lab-limit-max-current-enable; qcom,qpnp-lab-ps-threshold = <40>; qcom,qpnp-lab-ps-enable; Loading
arch/arm/boot/dts/qcom/msm-pmi8994.dtsi +1 −1 Original line number Diff line number Diff line Loading @@ -497,7 +497,7 @@ qcom,qpnp-lab-pull-down-enable; qcom,qpnp-lab-switching-clock-frequency = <1600>; qcom,qpnp-lab-limit-maximum-current = <800>; qcom,qpnp-lab-limit-maximum-current = <1600>; qcom,qpnp-lab-limit-max-current-enable; qcom,qpnp-lab-ps-threshold = <20>; qcom,qpnp-lab-ps-enable; Loading
arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi +4 −1 Original line number Diff line number Diff line Loading @@ -555,6 +555,9 @@ regulator-min-microvolt = <4600000>; regulator-max-microvolt = <6000000>; interrupts = <0x3 0xde 0x0 IRQ_TYPE_EDGE_RISING>; interrupt-names = "lab-vreg-ok"; qcom,qpnp-lab-min-voltage = <4600000>; qcom,qpnp-lab-step-size = <100000>; qcom,qpnp-lab-slew-rate = <5000>; Loading @@ -569,7 +572,7 @@ qcom,qpnp-lab-pull-down-enable; qcom,qpnp-lab-switching-clock-frequency = <1600>; qcom,qpnp-lab-limit-maximum-current = <800>; qcom,qpnp-lab-limit-maximum-current = <1600>; qcom,qpnp-lab-limit-max-current-enable; qcom,qpnp-lab-ps-threshold = <20>; qcom,qpnp-lab-ps-enable; Loading
drivers/regulator/qpnp-labibb-regulator.c +163 −24 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ #define QPNP_LABIBB_REGULATOR_DRIVER_NAME "qcom,qpnp-labibb-regulator" #define REG_REVISION_2 0x01 #define REG_PERPH_TYPE 0x04 #define QPNP_LAB_TYPE 0x24 Loading Loading @@ -60,6 +61,7 @@ #define REG_LAB_PRECHARGE_CTL 0x5E #define REG_LAB_SOFT_START_CTL 0x5F #define REG_LAB_SPARE_CTL 0x60 #define REG_LAB_PFM_CTL 0x62 /* LAB register bits definitions */ Loading Loading @@ -91,9 +93,9 @@ #define LAB_IBB_EN_RDY_EN BIT(7) /* REG_LAB_CURRENT_LIMIT */ #define LAB_CURRENT_LIMIT_BITS 3 #define LAB_CURRENT_LIMIT_MASK ((1 << LAB_CURRENT_LIMIT_BITS) - 1) #define LAB_CURRENT_LIMIT_EN BIT(7) #define LAB_CURRENT_LIMIT_MASK GENMASK(2, 0) #define LAB_CURRENT_LIMIT_EN_BIT BIT(7) #define LAB_OVERRIDE_CURRENT_MAX_BIT BIT(3) /* REG_LAB_CURRENT_SENSE */ #define LAB_CURRENT_SENSE_GAIN_BITS 2 Loading Loading @@ -129,6 +131,9 @@ #define LAB_SPARE_TOUCH_WAKE_BIT BIT(3) #define LAB_SPARE_DISABLE_SCP_BIT BIT(0) /* REG_LAB_PFM_CTL */ #define LAB_PFM_EN_BIT BIT(7) /* IBB register offset definitions */ #define REG_IBB_REVISION4 0x03 #define REG_IBB_STATUS1 0x08 Loading Loading @@ -344,6 +349,10 @@ static const int lab_current_limit_plan[] = { 400, 600, 800, 1000, 1200, 1400, 1600, }; static const char * const lab_current_sense_plan[] = { Loading Loading @@ -471,6 +480,8 @@ struct qpnp_labibb { struct pmic_revid_data *pmic_rev_id; u16 lab_base; u16 ibb_base; u8 lab_dig_major; u8 ibb_dig_major; struct lab_regulator lab_vreg; struct ibb_regulator ibb_vreg; enum qpnp_labibb_mode mode; Loading @@ -481,6 +492,7 @@ struct qpnp_labibb { bool swire_control; bool ttw_force_lab_on; bool skip_2nd_swire_cmd; bool pfm_enable; u32 swire_2nd_cmd_delay; u32 swire_ibb_ps_enable_delay; }; Loading Loading @@ -783,7 +795,7 @@ static int qpnp_lab_dt_init(struct qpnp_labibb *labibb, if (of_property_read_bool(of_node, "qcom,qpnp-lab-limit-max-current-enable")) val |= LAB_CURRENT_LIMIT_EN; val |= LAB_CURRENT_LIMIT_EN_BIT; rc = qpnp_labibb_write(labibb, labibb->lab_base + REG_LAB_CURRENT_LIMIT, &val, 1); Loading Loading @@ -936,6 +948,88 @@ static int qpnp_lab_dt_init(struct qpnp_labibb *labibb, return rc; } #define LAB_CURRENT_MAX_1600MA 0x7 #define LAB_CURRENT_MAX_400MA 0x1 static int qpnp_lab_pfm_disable(struct qpnp_labibb *labibb) { int rc = 0; u8 val, mask; mutex_lock(&(labibb->lab_vreg.lab_mutex)); if (!labibb->pfm_enable) { pr_debug("PFM already disabled\n"); goto out; } val = 0; mask = LAB_PFM_EN_BIT; rc = qpnp_labibb_masked_write(labibb, labibb->lab_base + REG_LAB_PFM_CTL, mask, val); if (rc < 0) { pr_err("Write register %x failed rc = %d\n", REG_LAB_PFM_CTL, rc); goto out; } val = LAB_CURRENT_MAX_1600MA; mask = LAB_OVERRIDE_CURRENT_MAX_BIT | LAB_CURRENT_LIMIT_MASK; rc = qpnp_labibb_masked_write(labibb, labibb->lab_base + REG_LAB_CURRENT_LIMIT, mask, val); if (rc < 0) { pr_err("Write register %x failed rc = %d\n", REG_LAB_CURRENT_LIMIT, rc); goto out; } labibb->pfm_enable = false; out: mutex_unlock(&(labibb->lab_vreg.lab_mutex)); return rc; } static int qpnp_lab_pfm_enable(struct qpnp_labibb *labibb) { int rc = 0; u8 val, mask; mutex_lock(&(labibb->lab_vreg.lab_mutex)); if (labibb->pfm_enable) { pr_debug("PFM already enabled\n"); goto out; } /* Wait for ~100uS */ usleep_range(100, 105); val = LAB_OVERRIDE_CURRENT_MAX_BIT | LAB_CURRENT_MAX_400MA; mask = LAB_OVERRIDE_CURRENT_MAX_BIT | LAB_CURRENT_LIMIT_MASK; rc = qpnp_labibb_masked_write(labibb, labibb->lab_base + REG_LAB_CURRENT_LIMIT, mask, val); if (rc < 0) { pr_err("Write register %x failed rc = %d\n", REG_LAB_CURRENT_LIMIT, rc); goto out; } /* Wait for ~100uS */ usleep_range(100, 105); val = LAB_PFM_EN_BIT; mask = LAB_PFM_EN_BIT; rc = qpnp_labibb_masked_write(labibb, labibb->lab_base + REG_LAB_PFM_CTL, mask, val); if (rc < 0) { pr_err("Write register %x failed rc = %d\n", REG_LAB_PFM_CTL, rc); goto out; } labibb->pfm_enable = true; out: mutex_unlock(&(labibb->lab_vreg.lab_mutex)); return rc; } static int qpnp_labibb_restore_settings(struct qpnp_labibb *labibb) { int rc, i; Loading Loading @@ -1435,6 +1529,15 @@ static int qpnp_labibb_regulator_disable(struct qpnp_labibb *labibb) return -EINVAL; } if (labibb->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE && labibb->mode == QPNP_LABIBB_LCD_MODE) { rc = qpnp_lab_pfm_disable(labibb); if (rc < 0) { pr_err("Error in disabling PFM, rc=%d\n", rc); return rc; } } labibb->lab_vreg.vreg_enabled = 0; labibb->ibb_vreg.vreg_enabled = 0; Loading Loading @@ -1644,9 +1747,17 @@ static irqreturn_t lab_vreg_ok_handler(int irq, void *_labibb) struct qpnp_labibb *labibb = _labibb; int rc; if (labibb->skip_2nd_swire_cmd && labibb->lab_dig_major < 2) { rc = qpnp_skip_swire_command(labibb); if (rc) pr_err("Failed in 'qpnp_skip_swire_command' rc=%d\n", rc); if (rc < 0) pr_err("Failed in 'qpnp_skip_swire_command' rc=%d\n", rc); } else if (labibb->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE && labibb->mode == QPNP_LABIBB_LCD_MODE) { rc = qpnp_lab_pfm_enable(labibb); if (rc < 0) pr_err("Failed to config PFM, rc=%d\n", rc); } return IRQ_HANDLED; } Loading @@ -1661,6 +1772,23 @@ static int qpnp_lab_regulator_get_voltage(struct regulator_dev *rdev) return labibb->lab_vreg.curr_volt; } static bool is_lab_vreg_ok_irq_available(struct qpnp_labibb *labibb) { /* * LAB VREG_OK interrupt is used only to skip 2nd SWIRE command in * dig_major < 2 targets. For pmicobalt, it is used to enable PFM in * LCD mode. */ if (labibb->skip_2nd_swire_cmd && labibb->lab_dig_major < 2) return true; if (labibb->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE && labibb->mode == QPNP_LABIBB_LCD_MODE) return true; return false; } static struct regulator_ops qpnp_lab_ops = { .enable = qpnp_lab_regulator_enable, .disable = qpnp_lab_regulator_disable, Loading Loading @@ -1809,19 +1937,6 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb, } } if (labibb->skip_2nd_swire_cmd) { rc = devm_request_threaded_irq(labibb->dev, labibb->lab_vreg.lab_vreg_ok_irq, NULL, lab_vreg_ok_handler, IRQF_ONESHOT | IRQF_TRIGGER_RISING, "lab-vreg-ok", labibb); if (rc) { pr_err("Failed to register 'lab-vreg-ok' irq rc=%d\n", rc); return rc; } } val = (labibb->standalone) ? 0 : LAB_IBB_EN_RDY_EN; rc = qpnp_labibb_sec_write(labibb, labibb->lab_base, REG_LAB_IBB_EN_RDY, &val, 1); Loading Loading @@ -1899,6 +2014,19 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb, labibb->lab_vreg.vreg_enabled = 1; } if (is_lab_vreg_ok_irq_available(labibb)) { rc = devm_request_threaded_irq(labibb->dev, labibb->lab_vreg.lab_vreg_ok_irq, NULL, lab_vreg_ok_handler, IRQF_ONESHOT | IRQF_TRIGGER_RISING, "lab-vreg-ok", labibb); if (rc) { pr_err("Failed to register 'lab-vreg-ok' irq rc=%d\n", rc); return rc; } } rc = qpnp_labibb_read(labibb, &val, labibb->lab_base + REG_LAB_MODULE_RDY, 1); if (rc) { Loading Loading @@ -1953,7 +2081,6 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb, return -EINVAL; } mutex_init(&(labibb->lab_vreg.lab_mutex)); return 0; } Loading Loading @@ -2683,14 +2810,13 @@ static int register_qpnp_ibb_regulator(struct qpnp_labibb *labibb, return -EINVAL; } mutex_init(&(labibb->ibb_vreg.ibb_mutex)); return 0; } static int qpnp_lab_register_irq(struct device_node *child, struct qpnp_labibb *labibb) { if (labibb->skip_2nd_swire_cmd) { if (is_lab_vreg_ok_irq_available(labibb)) { labibb->lab_vreg.lab_vreg_ok_irq = of_irq_get_byname(child, "lab-vreg-ok"); if (labibb->lab_vreg.lab_vreg_ok_irq < 0) { Loading Loading @@ -2745,7 +2871,7 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) unsigned int base; struct device_node *child, *revid_dev_node; const char *mode_name; u8 type; u8 type, revision; int rc = 0; labibb = devm_kzalloc(&pdev->dev, Loading @@ -2763,6 +2889,9 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) labibb->dev = &(pdev->dev); labibb->pdev = pdev; mutex_init(&(labibb->lab_vreg.lab_mutex)); mutex_init(&(labibb->ibb_vreg.ibb_mutex)); revid_dev_node = of_parse_phandle(labibb->dev->of_node, "qcom,pmic-revid", 0); if (!revid_dev_node) { Loading Loading @@ -2817,6 +2946,7 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) labibb->skip_2nd_swire_cmd = of_property_read_bool(labibb->dev->of_node, "qcom,skip-2nd-swire-cmd"); rc = of_property_read_u32(labibb->dev->of_node, "qcom,swire-2nd-cmd-delay", &labibb->swire_2nd_cmd_delay); Loading Loading @@ -2846,6 +2976,13 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) return rc; } rc = qpnp_labibb_read(labibb, &revision, base + REG_REVISION_2, 1); if (rc) { pr_err("Reading REVISION_2 failed rc=%d\n", rc); goto fail_registration; } rc = qpnp_labibb_read(labibb, &type, base + REG_PERPH_TYPE, 1); if (rc) { Loading @@ -2856,6 +2993,7 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) switch (type) { case QPNP_LAB_TYPE: labibb->lab_base = base; labibb->lab_dig_major = revision; rc = qpnp_lab_register_irq(child, labibb); if (rc) { pr_err("Failed to register LAB IRQ rc=%d\n", Loading @@ -2869,6 +3007,7 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) case QPNP_IBB_TYPE: labibb->ibb_base = base; labibb->ibb_dig_major = revision; rc = register_qpnp_ibb_regulator(labibb, child); if (rc) goto fail_registration; Loading