Lines Matching +full:short +full:- +full:circuit
1 // SPDX-License-Identifier: GPL-2.0-only
114 ret = regmap_update_bits(rdev->regmap, in qcom_labibb_ocp_hw_enable()
115 vreg->base + REG_LABIBB_INT_LATCHED_CLR, in qcom_labibb_ocp_hw_enable()
121 return regmap_update_bits(rdev->regmap, in qcom_labibb_ocp_hw_enable()
122 vreg->base + REG_LABIBB_INT_EN_SET, in qcom_labibb_ocp_hw_enable()
130 return regmap_update_bits(rdev->regmap, in qcom_labibb_ocp_hw_disable()
131 vreg->base + REG_LABIBB_INT_EN_CLR, in qcom_labibb_ocp_hw_disable()
136 * qcom_labibb_check_ocp_status - Check the Over-Current Protection status
140 * set, then there is no Over-Current event.
142 * Returns: Zero if there is no over-current, 1 if in over-current or
150 ret = regmap_read(vreg->rdev->regmap, vreg->base + REG_LABIBB_STATUS1, in qcom_labibb_check_ocp_status()
159 * qcom_labibb_ocp_recovery_worker - Handle OCP event
164 * signaling an over-current condition and will eventually stop
187 ops = vreg->rdev->desc->ops; in qcom_labibb_ocp_recovery_worker()
189 if (vreg->ocp_irq_count >= LABIBB_MAX_OCP_COUNT) { in qcom_labibb_ocp_recovery_worker()
199 BUG_ON(vreg->fatal_count > LABIBB_MAX_FATAL_COUNT); in qcom_labibb_ocp_recovery_worker()
200 dev_err(&vreg->rdev->dev, "LABIBB: CRITICAL: Disabling regulator\n"); in qcom_labibb_ocp_recovery_worker()
203 ret = ops->disable(vreg->rdev); in qcom_labibb_ocp_recovery_worker()
205 vreg->fatal_count++; in qcom_labibb_ocp_recovery_worker()
208 enable_irq(vreg->ocp_irq); in qcom_labibb_ocp_recovery_worker()
209 vreg->fatal_count = 0; in qcom_labibb_ocp_recovery_worker()
215 vreg->ocp_irq_count++; in qcom_labibb_ocp_recovery_worker()
219 ret = qcom_labibb_ocp_hw_enable(vreg->rdev); in qcom_labibb_ocp_recovery_worker()
222 dev_err(vreg->dev, "Cannot enable OCP IRQ\n"); in qcom_labibb_ocp_recovery_worker()
223 vreg->ocp_irq_count++; in qcom_labibb_ocp_recovery_worker()
227 enable_irq(vreg->ocp_irq); in qcom_labibb_ocp_recovery_worker()
229 vreg->ocp_irq_count = 0; in qcom_labibb_ocp_recovery_worker()
233 mod_delayed_work(system_wq, &vreg->ocp_recovery_work, in qcom_labibb_ocp_recovery_worker()
238 * qcom_labibb_ocp_isr - Interrupt routine for OverCurrent Protection
243 * that an over-current event has happened and then will schedule
246 * Disabling and eventually re-enabling the regulator is expected
248 * over-current condition only at first initialization or it may
258 const struct regulator_ops *ops = vreg->rdev->desc->ops; in qcom_labibb_ocp_isr()
262 if (!ops->is_enabled(vreg->rdev)) in qcom_labibb_ocp_isr()
266 if (vreg->ocp_irq_count > LABIBB_MAX_OCP_COUNT) in qcom_labibb_ocp_isr()
277 vreg->ocp_irq_count = 0; in qcom_labibb_ocp_isr()
280 vreg->ocp_irq_count++; in qcom_labibb_ocp_isr()
284 * we will re-enable it in the recovery worker function. in qcom_labibb_ocp_isr()
289 dev_warn(vreg->dev, "Over-Current interrupt fired!\n"); in qcom_labibb_ocp_isr()
292 ret = qcom_labibb_ocp_hw_disable(vreg->rdev); in qcom_labibb_ocp_isr()
297 regulator_notifier_call_chain(vreg->rdev, in qcom_labibb_ocp_isr()
302 schedule_delayed_work(&vreg->ocp_recovery_work, in qcom_labibb_ocp_isr()
319 * labibb supports only protection - and does not support setting in qcom_labibb_set_ocp()
323 return -EINVAL; in qcom_labibb_set_ocp()
326 if (vreg->ocp_irq <= 0) in qcom_labibb_set_ocp()
327 return -EINVAL; in qcom_labibb_set_ocp()
329 ocp_irq_name = devm_kasprintf(vreg->dev, GFP_KERNEL, "%s-over-current", in qcom_labibb_set_ocp()
330 vreg->desc.name); in qcom_labibb_set_ocp()
332 return -ENOMEM; in qcom_labibb_set_ocp()
334 /* IRQ polarities - LAB: trigger-low, IBB: trigger-high */ in qcom_labibb_set_ocp()
335 switch (vreg->type) { in qcom_labibb_set_ocp()
345 return -EINVAL; in qcom_labibb_set_ocp()
349 ret = regmap_update_bits(rdev->regmap, in qcom_labibb_set_ocp()
350 vreg->base + REG_LABIBB_INT_SET_TYPE, in qcom_labibb_set_ocp()
357 ret = regmap_update_bits(rdev->regmap, in qcom_labibb_set_ocp()
358 vreg->base + REG_LABIBB_INT_POLARITY_HIGH, in qcom_labibb_set_ocp()
362 ret = regmap_update_bits(rdev->regmap, in qcom_labibb_set_ocp()
363 vreg->base + REG_LABIBB_INT_POLARITY_LOW, in qcom_labibb_set_ocp()
372 return devm_request_threaded_irq(vreg->dev, vreg->ocp_irq, NULL, in qcom_labibb_set_ocp()
378 * qcom_labibb_check_sc_status - Check the Short Circuit Protection status
383 * experienced a short-circuit event.
385 * Returns: Zero if there is no short-circuit, 1 if in short-circuit or
394 lab_reg = ibb_reg = vreg->base + REG_LABIBB_STATUS1; in qcom_labibb_check_sc_status()
395 if (vreg->type == QCOM_LAB_TYPE) in qcom_labibb_check_sc_status()
396 ibb_reg -= PMI8998_IBB_LAB_REG_OFFSET; in qcom_labibb_check_sc_status()
400 ret = regmap_read(vreg->rdev->regmap, lab_reg, &lab_status); in qcom_labibb_check_sc_status()
403 ret = regmap_read(vreg->rdev->regmap, ibb_reg, &ibb_status); in qcom_labibb_check_sc_status()
412 * qcom_labibb_sc_recovery_worker - Handle Short Circuit event
415 * This is the worker function to handle the Short Circuit Protection
417 * signaling a short-circuit condition and will eventually never
418 * re-enable the regulator if such condition is still signaled after
438 ops = vreg->rdev->desc->ops; in qcom_labibb_sc_recovery_worker()
445 if (vreg->fatal_count > LABIBB_MAX_FATAL_COUNT) in qcom_labibb_sc_recovery_worker()
448 /* Too many short-circuit events. Throw in the towel. */ in qcom_labibb_sc_recovery_worker()
449 if (vreg->sc_count > LABIBB_MAX_SC_COUNT) in qcom_labibb_sc_recovery_worker()
454 * and IBB when a short-circuit event is detected, so we have to in qcom_labibb_sc_recovery_worker()
457 lab_reg = ibb_reg = vreg->base + REG_LABIBB_ENABLE_CTL; in qcom_labibb_sc_recovery_worker()
458 if (vreg->type == QCOM_LAB_TYPE) in qcom_labibb_sc_recovery_worker()
459 ibb_reg -= PMI8998_IBB_LAB_REG_OFFSET; in qcom_labibb_sc_recovery_worker()
468 ret = regmap_read(vreg->regmap, lab_reg, &lab_val); in qcom_labibb_sc_recovery_worker()
470 vreg->fatal_count++; in qcom_labibb_sc_recovery_worker()
474 ret = regmap_read(vreg->regmap, ibb_reg, &ibb_val); in qcom_labibb_sc_recovery_worker()
476 vreg->fatal_count++; in qcom_labibb_sc_recovery_worker()
494 * which means that we can re-enable the regulators, if they in qcom_labibb_sc_recovery_worker()
497 ret = ops->enable(vreg->rdev); in qcom_labibb_sc_recovery_worker()
502 vreg->sc_count = 0; in qcom_labibb_sc_recovery_worker()
503 enable_irq(vreg->sc_irq); in qcom_labibb_sc_recovery_worker()
508 * Now that we have done basic handling of the short-circuit, in qcom_labibb_sc_recovery_worker()
512 vreg->sc_count++; in qcom_labibb_sc_recovery_worker()
513 mod_delayed_work(system_wq, &vreg->sc_recovery_work, in qcom_labibb_sc_recovery_worker()
518 * qcom_labibb_sc_isr - Interrupt routine for Short Circuit Protection
522 * Short Circuit Protection (SCP) will signal to the client driver
523 * that a regulation-out event has happened and then will schedule
528 * the worker function if the hardware stops signaling the short
529 * circuit event.
537 if (vreg->sc_count > LABIBB_MAX_SC_COUNT) in qcom_labibb_sc_isr()
540 /* Warn the user for short circuit */ in qcom_labibb_sc_isr()
541 dev_warn(vreg->dev, "Short-Circuit interrupt fired!\n"); in qcom_labibb_sc_isr()
545 * we will re-enable it in the recovery worker function. in qcom_labibb_sc_isr()
550 regulator_notifier_call_chain(vreg->rdev, in qcom_labibb_sc_isr()
553 /* Schedule the short-circuit handling as high-priority work */ in qcom_labibb_sc_isr()
554 mod_delayed_work(system_highpri_wq, &vreg->sc_recovery_work, in qcom_labibb_sc_isr()
564 struct regulator_desc *desc = &vreg->desc; in qcom_labibb_set_current_limit()
565 struct labibb_current_limits *lim = &vreg->uA_limits; in qcom_labibb_set_current_limit()
567 int i, ret, sel = -1; in qcom_labibb_set_current_limit()
569 if (min_uA < lim->uA_min || max_uA < lim->uA_min) in qcom_labibb_set_current_limit()
570 return -EINVAL; in qcom_labibb_set_current_limit()
572 for (i = 0; i < desc->n_current_limits; i++) { in qcom_labibb_set_current_limit()
573 int uA_limit = (lim->uA_step * i) + lim->uA_min; in qcom_labibb_set_current_limit()
579 return -EINVAL; in qcom_labibb_set_current_limit()
582 ret = regmap_write(vreg->regmap, vreg->base + REG_LABIBB_SEC_ACCESS, in qcom_labibb_set_current_limit()
587 mask = desc->csel_mask | lim->ovr_val; in qcom_labibb_set_current_limit()
589 val = (u32)sel | lim->ovr_val; in qcom_labibb_set_current_limit()
592 return regmap_update_bits(vreg->regmap, desc->csel_reg, mask, val); in qcom_labibb_set_current_limit()
598 struct regulator_desc *desc = &vreg->desc; in qcom_labibb_get_current_limit()
599 struct labibb_current_limits *lim = &vreg->uA_limits; in qcom_labibb_get_current_limit()
603 ret = regmap_read(vreg->regmap, desc->csel_reg, &cur_step); in qcom_labibb_get_current_limit()
606 cur_step &= desc->csel_mask; in qcom_labibb_get_current_limit()
608 return (cur_step * lim->uA_step) + lim->uA_min; in qcom_labibb_get_current_limit()
616 if (vreg->type == QCOM_IBB_TYPE) in qcom_labibb_set_soft_start()
617 val = vreg->dischg_sel; in qcom_labibb_set_soft_start()
619 val = vreg->soft_start_sel; in qcom_labibb_set_soft_start()
621 return regmap_write(rdev->regmap, rdev->desc->soft_start_reg, val); in qcom_labibb_set_soft_start()
631 return -EINVAL; in qcom_labibb_get_table_sel()
644 struct labibb_regulator *vreg = config->driver_data; in qcom_labibb_of_parse_cb()
648 ret = of_property_read_u32(np, "qcom,discharge-resistor-kohms", in qcom_labibb_of_parse_cb()
658 vreg->dischg_sel = (u8)ret; in qcom_labibb_of_parse_cb()
660 ret = of_property_read_u32(np, "qcom,soft-start-us", in qcom_labibb_of_parse_cb()
670 vreg->soft_start_sel = (u8)ret; in qcom_labibb_of_parse_cb()
756 { .compatible = "qcom,pmi8998-lab-ibb", .data = &pmi8998_labibb_data},
764 struct device *dev = &pdev->dev; in qcom_labibb_regulator_probe()
772 reg_regmap = dev_get_regmap(pdev->dev.parent, NULL); in qcom_labibb_regulator_probe()
774 dev_err(&pdev->dev, "Couldn't get parent's regmap\n"); in qcom_labibb_regulator_probe()
775 return -ENODEV; in qcom_labibb_regulator_probe()
778 reg_data = device_get_match_data(&pdev->dev); in qcom_labibb_regulator_probe()
780 return -ENODEV; in qcom_labibb_regulator_probe()
782 for (; reg_data->name; reg_data++) { in qcom_labibb_regulator_probe()
789 ret = regmap_read(reg_regmap, reg_data->base + REG_PERPH_TYPE, in qcom_labibb_regulator_probe()
795 return -EINVAL; in qcom_labibb_regulator_probe()
799 WARN_ON(type != reg_data->type)) in qcom_labibb_regulator_probe()
800 return -EINVAL; in qcom_labibb_regulator_probe()
802 vreg = devm_kzalloc(&pdev->dev, sizeof(*vreg), in qcom_labibb_regulator_probe()
805 return -ENOMEM; in qcom_labibb_regulator_probe()
808 "%s-short-circuit", in qcom_labibb_regulator_probe()
809 reg_data->name); in qcom_labibb_regulator_probe()
811 return -ENOMEM; in qcom_labibb_regulator_probe()
813 reg_node = of_get_child_by_name(pdev->dev.of_node, in qcom_labibb_regulator_probe()
814 reg_data->name); in qcom_labibb_regulator_probe()
816 return -EINVAL; in qcom_labibb_regulator_probe()
818 /* The Short Circuit interrupt is critical */ in qcom_labibb_regulator_probe()
819 irq = of_irq_get_byname(reg_node, "sc-err"); in qcom_labibb_regulator_probe()
822 irq = -EINVAL; in qcom_labibb_regulator_probe()
825 return dev_err_probe(vreg->dev, irq, in qcom_labibb_regulator_probe()
826 "Short-circuit irq not found.\n"); in qcom_labibb_regulator_probe()
828 vreg->sc_irq = irq; in qcom_labibb_regulator_probe()
832 vreg->ocp_irq = irq; in qcom_labibb_regulator_probe()
833 vreg->ocp_irq_count = 0; in qcom_labibb_regulator_probe()
836 vreg->regmap = reg_regmap; in qcom_labibb_regulator_probe()
837 vreg->dev = dev; in qcom_labibb_regulator_probe()
838 vreg->base = reg_data->base; in qcom_labibb_regulator_probe()
839 vreg->type = reg_data->type; in qcom_labibb_regulator_probe()
840 INIT_DELAYED_WORK(&vreg->sc_recovery_work, in qcom_labibb_regulator_probe()
843 if (vreg->ocp_irq > 0) in qcom_labibb_regulator_probe()
844 INIT_DELAYED_WORK(&vreg->ocp_recovery_work, in qcom_labibb_regulator_probe()
847 switch (vreg->type) { in qcom_labibb_regulator_probe()
849 /* LAB Limits: 200-1600mA */ in qcom_labibb_regulator_probe()
850 vreg->uA_limits.uA_min = 200000; in qcom_labibb_regulator_probe()
851 vreg->uA_limits.uA_step = 200000; in qcom_labibb_regulator_probe()
852 vreg->uA_limits.ovr_val = LAB_CURRENT_LIMIT_OVERRIDE_EN; in qcom_labibb_regulator_probe()
855 /* IBB Limits: 0-1550mA */ in qcom_labibb_regulator_probe()
856 vreg->uA_limits.uA_min = 0; in qcom_labibb_regulator_probe()
857 vreg->uA_limits.uA_step = 50000; in qcom_labibb_regulator_probe()
858 vreg->uA_limits.ovr_val = 0; /* No override bit */ in qcom_labibb_regulator_probe()
861 return -EINVAL; in qcom_labibb_regulator_probe()
864 memcpy(&vreg->desc, reg_data->desc, sizeof(vreg->desc)); in qcom_labibb_regulator_probe()
865 vreg->desc.of_match = reg_data->name; in qcom_labibb_regulator_probe()
866 vreg->desc.name = reg_data->name; in qcom_labibb_regulator_probe()
868 cfg.dev = vreg->dev; in qcom_labibb_regulator_probe()
870 cfg.regmap = vreg->regmap; in qcom_labibb_regulator_probe()
872 vreg->rdev = devm_regulator_register(vreg->dev, &vreg->desc, in qcom_labibb_regulator_probe()
875 if (IS_ERR(vreg->rdev)) { in qcom_labibb_regulator_probe()
877 reg_data->name, ret); in qcom_labibb_regulator_probe()
878 return PTR_ERR(vreg->rdev); in qcom_labibb_regulator_probe()
881 ret = devm_request_threaded_irq(vreg->dev, vreg->sc_irq, NULL, in qcom_labibb_regulator_probe()
895 .name = "qcom-lab-ibb-regulator",