Loading Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt +4 −0 Original line number Diff line number Diff line Loading @@ -151,6 +151,10 @@ LAB subnode optional properties: any value in the allowed limit. - qcom,notify-lab-vreg-ok-sts: A boolean property which upon set will poll and notify the lab_vreg_ok status. - qcom,qpnp-lab-sc-wait-time-ms: This property is used to specify the time (in ms) to poll for the short circuit detection. If not specified the default time is 5 sec. Following properties are available only for PM660A: Loading drivers/regulator/qpnp-labibb-regulator.c +47 −4 Original line number Diff line number Diff line Loading @@ -559,6 +559,7 @@ struct lab_regulator { int step_size; int slew_rate; int soft_start; int sc_wait_time_ms; int vreg_enabled; }; Loading Loading @@ -608,6 +609,8 @@ struct qpnp_labibb { bool skip_2nd_swire_cmd; bool pfm_enable; bool notify_lab_vreg_ok_sts; bool detect_lab_sc; bool sc_detected; u32 swire_2nd_cmd_delay; u32 swire_ibb_ps_enable_delay; }; Loading Loading @@ -2138,8 +2141,10 @@ static void qpnp_lab_vreg_notifier_work(struct work_struct *work) u8 val; struct qpnp_labibb *labibb = container_of(work, struct qpnp_labibb, lab_vreg_ok_work); if (labibb->lab_vreg.sc_wait_time_ms != -EINVAL) retries = labibb->lab_vreg.sc_wait_time_ms / 5; while (retries--) { while (retries) { rc = qpnp_labibb_read(labibb, labibb->lab_base + REG_LAB_STATUS1, &val, 1); if (rc < 0) { Loading @@ -2155,11 +2160,31 @@ static void qpnp_lab_vreg_notifier_work(struct work_struct *work) } usleep_range(dly, dly + 100); retries--; } if (!retries) if (!retries) { if (labibb->detect_lab_sc) { pr_crit("short circuit detected on LAB rail.. disabling the LAB/IBB/OLEDB modules\n"); /* Disable LAB module */ val = 0; rc = qpnp_labibb_write(labibb, labibb->lab_base + REG_LAB_MODULE_RDY, &val, 1); if (rc < 0) { pr_err("write register %x failed rc = %d\n", REG_LAB_MODULE_RDY, rc); return; } raw_notifier_call_chain(&labibb_notifier, LAB_VREG_NOT_OK, NULL); labibb->sc_detected = true; labibb->lab_vreg.vreg_enabled = 0; labibb->ibb_vreg.vreg_enabled = 0; } else { pr_err("LAB_VREG_OK not set, failed to notify\n"); } } } static int qpnp_labibb_regulator_enable(struct qpnp_labibb *labibb) { Loading Loading @@ -2323,6 +2348,11 @@ static int qpnp_lab_regulator_enable(struct regulator_dev *rdev) struct qpnp_labibb *labibb = rdev_get_drvdata(rdev); if (labibb->sc_detected) { pr_info("Short circuit detected: disabled LAB/IBB rails\n"); return 0; } if (labibb->skip_2nd_swire_cmd) { rc = qpnp_ibb_ps_config(labibb, false); if (rc < 0) { Loading Loading @@ -2363,7 +2393,7 @@ static int qpnp_lab_regulator_enable(struct regulator_dev *rdev) labibb->lab_vreg.vreg_enabled = 1; } if (labibb->notify_lab_vreg_ok_sts) if (labibb->notify_lab_vreg_ok_sts || labibb->detect_lab_sc) schedule_work(&labibb->lab_vreg_ok_work); return 0; Loading Loading @@ -2621,6 +2651,12 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb, labibb->notify_lab_vreg_ok_sts = of_property_read_bool(of_node, "qcom,notify-lab-vreg-ok-sts"); labibb->lab_vreg.sc_wait_time_ms = -EINVAL; if (labibb->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE && labibb->detect_lab_sc) of_property_read_u32(of_node, "qcom,qpnp-lab-sc-wait-time-ms", &labibb->lab_vreg.sc_wait_time_ms); rc = of_property_read_u32(of_node, "qcom,qpnp-lab-soft-start", &(labibb->lab_vreg.soft_start)); if (!rc) { Loading Loading @@ -3255,6 +3291,11 @@ static int qpnp_ibb_regulator_enable(struct regulator_dev *rdev) u8 val; struct qpnp_labibb *labibb = rdev_get_drvdata(rdev); if (labibb->sc_detected) { pr_info("Short circuit detected: disabled LAB/IBB rails\n"); return 0; } if (!labibb->ibb_vreg.vreg_enabled && !labibb->swire_control) { if (!labibb->standalone) Loading Loading @@ -3731,6 +3772,8 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) if (labibb->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE) { labibb->mode = QPNP_LABIBB_AMOLED_MODE; /* Enable polling for LAB short circuit detection for PM660A */ labibb->detect_lab_sc = true; } else { rc = of_property_read_string(labibb->dev->of_node, "qcom,qpnp-labibb-mode", &mode_name); Loading include/linux/regulator/qpnp-labibb-regulator.h +1 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ enum labibb_notify_event { LAB_VREG_OK = 1, LAB_VREG_NOT_OK, }; int qpnp_labibb_notifier_register(struct notifier_block *nb); Loading Loading
Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt +4 −0 Original line number Diff line number Diff line Loading @@ -151,6 +151,10 @@ LAB subnode optional properties: any value in the allowed limit. - qcom,notify-lab-vreg-ok-sts: A boolean property which upon set will poll and notify the lab_vreg_ok status. - qcom,qpnp-lab-sc-wait-time-ms: This property is used to specify the time (in ms) to poll for the short circuit detection. If not specified the default time is 5 sec. Following properties are available only for PM660A: Loading
drivers/regulator/qpnp-labibb-regulator.c +47 −4 Original line number Diff line number Diff line Loading @@ -559,6 +559,7 @@ struct lab_regulator { int step_size; int slew_rate; int soft_start; int sc_wait_time_ms; int vreg_enabled; }; Loading Loading @@ -608,6 +609,8 @@ struct qpnp_labibb { bool skip_2nd_swire_cmd; bool pfm_enable; bool notify_lab_vreg_ok_sts; bool detect_lab_sc; bool sc_detected; u32 swire_2nd_cmd_delay; u32 swire_ibb_ps_enable_delay; }; Loading Loading @@ -2138,8 +2141,10 @@ static void qpnp_lab_vreg_notifier_work(struct work_struct *work) u8 val; struct qpnp_labibb *labibb = container_of(work, struct qpnp_labibb, lab_vreg_ok_work); if (labibb->lab_vreg.sc_wait_time_ms != -EINVAL) retries = labibb->lab_vreg.sc_wait_time_ms / 5; while (retries--) { while (retries) { rc = qpnp_labibb_read(labibb, labibb->lab_base + REG_LAB_STATUS1, &val, 1); if (rc < 0) { Loading @@ -2155,11 +2160,31 @@ static void qpnp_lab_vreg_notifier_work(struct work_struct *work) } usleep_range(dly, dly + 100); retries--; } if (!retries) if (!retries) { if (labibb->detect_lab_sc) { pr_crit("short circuit detected on LAB rail.. disabling the LAB/IBB/OLEDB modules\n"); /* Disable LAB module */ val = 0; rc = qpnp_labibb_write(labibb, labibb->lab_base + REG_LAB_MODULE_RDY, &val, 1); if (rc < 0) { pr_err("write register %x failed rc = %d\n", REG_LAB_MODULE_RDY, rc); return; } raw_notifier_call_chain(&labibb_notifier, LAB_VREG_NOT_OK, NULL); labibb->sc_detected = true; labibb->lab_vreg.vreg_enabled = 0; labibb->ibb_vreg.vreg_enabled = 0; } else { pr_err("LAB_VREG_OK not set, failed to notify\n"); } } } static int qpnp_labibb_regulator_enable(struct qpnp_labibb *labibb) { Loading Loading @@ -2323,6 +2348,11 @@ static int qpnp_lab_regulator_enable(struct regulator_dev *rdev) struct qpnp_labibb *labibb = rdev_get_drvdata(rdev); if (labibb->sc_detected) { pr_info("Short circuit detected: disabled LAB/IBB rails\n"); return 0; } if (labibb->skip_2nd_swire_cmd) { rc = qpnp_ibb_ps_config(labibb, false); if (rc < 0) { Loading Loading @@ -2363,7 +2393,7 @@ static int qpnp_lab_regulator_enable(struct regulator_dev *rdev) labibb->lab_vreg.vreg_enabled = 1; } if (labibb->notify_lab_vreg_ok_sts) if (labibb->notify_lab_vreg_ok_sts || labibb->detect_lab_sc) schedule_work(&labibb->lab_vreg_ok_work); return 0; Loading Loading @@ -2621,6 +2651,12 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb, labibb->notify_lab_vreg_ok_sts = of_property_read_bool(of_node, "qcom,notify-lab-vreg-ok-sts"); labibb->lab_vreg.sc_wait_time_ms = -EINVAL; if (labibb->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE && labibb->detect_lab_sc) of_property_read_u32(of_node, "qcom,qpnp-lab-sc-wait-time-ms", &labibb->lab_vreg.sc_wait_time_ms); rc = of_property_read_u32(of_node, "qcom,qpnp-lab-soft-start", &(labibb->lab_vreg.soft_start)); if (!rc) { Loading Loading @@ -3255,6 +3291,11 @@ static int qpnp_ibb_regulator_enable(struct regulator_dev *rdev) u8 val; struct qpnp_labibb *labibb = rdev_get_drvdata(rdev); if (labibb->sc_detected) { pr_info("Short circuit detected: disabled LAB/IBB rails\n"); return 0; } if (!labibb->ibb_vreg.vreg_enabled && !labibb->swire_control) { if (!labibb->standalone) Loading Loading @@ -3731,6 +3772,8 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) if (labibb->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE) { labibb->mode = QPNP_LABIBB_AMOLED_MODE; /* Enable polling for LAB short circuit detection for PM660A */ labibb->detect_lab_sc = true; } else { rc = of_property_read_string(labibb->dev->of_node, "qcom,qpnp-labibb-mode", &mode_name); Loading
include/linux/regulator/qpnp-labibb-regulator.h +1 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ enum labibb_notify_event { LAB_VREG_OK = 1, LAB_VREG_NOT_OK, }; int qpnp_labibb_notifier_register(struct notifier_block *nb); Loading