Loading Documentation/devicetree/bindings/regulator/cpr3-regulator.txt +13 −0 Original line number Diff line number Diff line Loading @@ -183,6 +183,19 @@ Platform independent properties: This is the voltage that vdd-supply must be set to when performing an aging measurement. - qcom,cpr-panic-reg-addr-list Usage: optional Value type: <prop-encoded-array> Definition: Array of register addresses to be dumped when device resets. - qcom,cpr-panic-reg-name-list Usage: optional, though only meaningful if qcom,cpr-panic-reg-addr-list is specified Value type: <prop-encoded-array> Definition: Address names. Must be specified in the same order as the corresponding addresses are specified in the qcom,cpr-panic-reg-addr-list property. ================================================= Second Level Nodes - CPR Threads for a Controller ================================================= Loading Documentation/devicetree/bindings/regulator/cpr4-apss-regulator.txt +7 −0 Original line number Diff line number Diff line Loading @@ -407,6 +407,13 @@ apc_cpr: cpr4-ctrl@b018000 { qcom,cpr-step-quot-fixed = <16>; qcom,cpr-voltage-settling-time = <1600>; qcom,cpr-panic-reg-addr-list = <0xb1d2c18 0xb1d2900 0x0b1112b0 0xb018798>; qcom,cpr-panic-reg-name-list = "CCI_SAW4_PMIC_STS", "CCI_SAW4_VCTL", "APCS_ALIAS0_APM_CTLER_STATUS", "APCS0_CPR_CORE_ADJ_MODE_REG"; thread@0 { qcom,cpr-thread-id = <0>; qcom,cpr-consecutive-up = <1>; Loading drivers/regulator/cpr3-regulator.c +47 −0 Original line number Diff line number Diff line Loading @@ -5817,6 +5817,42 @@ static int cpr3_regulator_validate_controller(struct cpr3_controller *ctrl) return 0; } /** * cpr3_panic_callback() - panic notification callback function. This function * is invoked when a kernel panic occurs. * @nfb: Notifier block pointer of CPR3 controller * @event: Value passed unmodified to notifier function * @data: Pointer passed unmodified to notifier function * * Return: NOTIFY_OK */ static int cpr3_panic_callback(struct notifier_block *nfb, unsigned long event, void *data) { struct cpr3_controller *ctrl = container_of(nfb, struct cpr3_controller, panic_notifier); struct cpr3_panic_regs_info *regs_info = ctrl->panic_regs_info; struct cpr3_reg_info *reg; void __iomem *virt_addr; int i = 0; for (i = 0; i < regs_info->reg_count; i++) { reg = &(regs_info->regs[i]); virt_addr = ioremap(reg->addr, 0x4); reg->value = readl_relaxed(virt_addr); iounmap(virt_addr); pr_err("%s[0x%08x] = 0x%08x\n", reg->name, reg->addr, reg->value); } /* * Barrier to ensure that the information has been updated in the * structure. */ mb(); return NOTIFY_OK; } /** * cpr3_regulator_register() - register the regulators for a CPR3 controller and * perform CPR hardware initialization Loading Loading @@ -5968,6 +6004,13 @@ int cpr3_regulator_register(struct platform_device *pdev, list_add(&ctrl->list, &cpr3_controller_list); mutex_unlock(&cpr3_controller_list_mutex); if (ctrl->panic_regs_info) { /* Register panic notification call back */ ctrl->panic_notifier.notifier_call = cpr3_panic_callback; atomic_notifier_chain_register(&panic_notifier_list, &ctrl->panic_notifier); } return 0; free_regulators: Loading Loading @@ -6021,5 +6064,9 @@ int cpr3_regulator_unregister(struct cpr3_controller *ctrl) for (j = 0; j < ctrl->thread[i].vreg_count; j++) regulator_unregister(ctrl->thread[i].vreg[j].rdev); if (ctrl->panic_notifier.notifier_call) atomic_notifier_chain_unregister(&panic_notifier_list, &ctrl->panic_notifier); return 0; } drivers/regulator/cpr3-regulator.h +34 −0 Original line number Diff line number Diff line Loading @@ -493,6 +493,35 @@ struct cpr3_aging_sensor_info { u32 bypass_mask[CPR3_MAX_SENSOR_COUNT / 32]; }; /** * struct cpr3_reg_info - Register information data structure * @name: Register name * @addr: Register physical address * @value: Register content * * This data structure is used to dump some critical register contents * when the device crashes due to a kernel panic. */ struct cpr3_reg_info { const char *name; u32 addr; u32 value; }; /** * struct cpr3_panic_regs_info - Data structure to dump critical register * contents. * @reg_count: Number of elements in the regs array * @regs: Array of critical registers information * * This data structure is used to dump critical register contents when * the device crashes due to a kernel panic. */ struct cpr3_panic_regs_info { int reg_count; struct cpr3_reg_info *regs; }; /** * struct cpr3_controller - CPR3 controller data structure * @dev: Device pointer for the CPR3 controller device Loading Loading @@ -662,6 +691,9 @@ struct cpr3_aging_sensor_info { * VDD supply voltage to settle after being increased or * decreased by step_volt microvolts which is used when * SDELTA voltage margin adjustments are applied. * @panic_regs_info: Array of panic registers information which provides the * list of registers to dump when the device crashes. * @panic_notifier: Notifier block registered to global panic notifier list. * * This structure contains both configuration and runtime state data. The * elements cpr_allowed_sw, use_hw_closed_loop, aggr_corner, cpr_enabled, Loading Loading @@ -755,6 +787,8 @@ struct cpr3_controller { u32 temp_sensor_id_start; u32 temp_sensor_id_end; u32 voltage_settling_time; struct cpr3_panic_regs_info *panic_regs_info; struct notifier_block panic_notifier; }; /* Used for rounding voltages to the closest physically available set point. */ Loading drivers/regulator/cpr3-util.c +70 −0 Original line number Diff line number Diff line Loading @@ -1020,6 +1020,74 @@ static int cpr3_parse_irq_affinity(struct cpr3_controller *ctrl) return 0; } static int cpr3_panic_notifier_init(struct cpr3_controller *ctrl) { struct device_node *node = ctrl->dev->of_node; struct cpr3_panic_regs_info *panic_regs_info; struct cpr3_reg_info *regs; int i, reg_count, len, rc = 0; if (!of_find_property(node, "qcom,cpr-panic-reg-addr-list", &len)) { /* panic register address list not specified */ return rc; } reg_count = len / sizeof(u32); if (!reg_count) { cpr3_err(ctrl, "qcom,cpr-panic-reg-addr-list has invalid len = %d\n", len); return -EINVAL; } if (!of_find_property(node, "qcom,cpr-panic-reg-name-list", NULL)) { cpr3_err(ctrl, "property qcom,cpr-panic-reg-name-list not specified\n"); return -EINVAL; } len = of_property_count_strings(node, "qcom,cpr-panic-reg-name-list"); if (reg_count != len) { cpr3_err(ctrl, "qcom,cpr-panic-reg-name-list should have %d strings\n", reg_count); return -EINVAL; } panic_regs_info = devm_kzalloc(ctrl->dev, sizeof(*panic_regs_info), GFP_KERNEL); if (!panic_regs_info) return -ENOMEM; regs = devm_kcalloc(ctrl->dev, reg_count, sizeof(*regs), GFP_KERNEL); if (!regs) return -ENOMEM; for (i = 0; i < reg_count; i++) { rc = of_property_read_string_index(node, "qcom,cpr-panic-reg-name-list", i, &(regs[i].name)); if (rc) { cpr3_err(ctrl, "error reading property qcom,cpr-panic-reg-name-list, rc=%d\n", rc); return rc; } rc = of_property_read_u32_index(node, "qcom,cpr-panic-reg-addr-list", i, &(regs[i].addr)); if (rc) { cpr3_err(ctrl, "error reading property qcom,cpr-panic-reg-addr-list, rc=%d\n", rc); return rc; } regs[i].value = 0xFFFFFFFF; } panic_regs_info->reg_count = reg_count; panic_regs_info->regs = regs; ctrl->panic_regs_info = panic_regs_info; return rc; } /** * cpr3_parse_common_ctrl_data() - parse common CPR3 controller properties from * device tree Loading Loading @@ -1147,6 +1215,8 @@ int cpr3_parse_common_ctrl_data(struct cpr3_controller *ctrl) } } rc = cpr3_panic_notifier_init(ctrl); return rc; } Loading Loading
Documentation/devicetree/bindings/regulator/cpr3-regulator.txt +13 −0 Original line number Diff line number Diff line Loading @@ -183,6 +183,19 @@ Platform independent properties: This is the voltage that vdd-supply must be set to when performing an aging measurement. - qcom,cpr-panic-reg-addr-list Usage: optional Value type: <prop-encoded-array> Definition: Array of register addresses to be dumped when device resets. - qcom,cpr-panic-reg-name-list Usage: optional, though only meaningful if qcom,cpr-panic-reg-addr-list is specified Value type: <prop-encoded-array> Definition: Address names. Must be specified in the same order as the corresponding addresses are specified in the qcom,cpr-panic-reg-addr-list property. ================================================= Second Level Nodes - CPR Threads for a Controller ================================================= Loading
Documentation/devicetree/bindings/regulator/cpr4-apss-regulator.txt +7 −0 Original line number Diff line number Diff line Loading @@ -407,6 +407,13 @@ apc_cpr: cpr4-ctrl@b018000 { qcom,cpr-step-quot-fixed = <16>; qcom,cpr-voltage-settling-time = <1600>; qcom,cpr-panic-reg-addr-list = <0xb1d2c18 0xb1d2900 0x0b1112b0 0xb018798>; qcom,cpr-panic-reg-name-list = "CCI_SAW4_PMIC_STS", "CCI_SAW4_VCTL", "APCS_ALIAS0_APM_CTLER_STATUS", "APCS0_CPR_CORE_ADJ_MODE_REG"; thread@0 { qcom,cpr-thread-id = <0>; qcom,cpr-consecutive-up = <1>; Loading
drivers/regulator/cpr3-regulator.c +47 −0 Original line number Diff line number Diff line Loading @@ -5817,6 +5817,42 @@ static int cpr3_regulator_validate_controller(struct cpr3_controller *ctrl) return 0; } /** * cpr3_panic_callback() - panic notification callback function. This function * is invoked when a kernel panic occurs. * @nfb: Notifier block pointer of CPR3 controller * @event: Value passed unmodified to notifier function * @data: Pointer passed unmodified to notifier function * * Return: NOTIFY_OK */ static int cpr3_panic_callback(struct notifier_block *nfb, unsigned long event, void *data) { struct cpr3_controller *ctrl = container_of(nfb, struct cpr3_controller, panic_notifier); struct cpr3_panic_regs_info *regs_info = ctrl->panic_regs_info; struct cpr3_reg_info *reg; void __iomem *virt_addr; int i = 0; for (i = 0; i < regs_info->reg_count; i++) { reg = &(regs_info->regs[i]); virt_addr = ioremap(reg->addr, 0x4); reg->value = readl_relaxed(virt_addr); iounmap(virt_addr); pr_err("%s[0x%08x] = 0x%08x\n", reg->name, reg->addr, reg->value); } /* * Barrier to ensure that the information has been updated in the * structure. */ mb(); return NOTIFY_OK; } /** * cpr3_regulator_register() - register the regulators for a CPR3 controller and * perform CPR hardware initialization Loading Loading @@ -5968,6 +6004,13 @@ int cpr3_regulator_register(struct platform_device *pdev, list_add(&ctrl->list, &cpr3_controller_list); mutex_unlock(&cpr3_controller_list_mutex); if (ctrl->panic_regs_info) { /* Register panic notification call back */ ctrl->panic_notifier.notifier_call = cpr3_panic_callback; atomic_notifier_chain_register(&panic_notifier_list, &ctrl->panic_notifier); } return 0; free_regulators: Loading Loading @@ -6021,5 +6064,9 @@ int cpr3_regulator_unregister(struct cpr3_controller *ctrl) for (j = 0; j < ctrl->thread[i].vreg_count; j++) regulator_unregister(ctrl->thread[i].vreg[j].rdev); if (ctrl->panic_notifier.notifier_call) atomic_notifier_chain_unregister(&panic_notifier_list, &ctrl->panic_notifier); return 0; }
drivers/regulator/cpr3-regulator.h +34 −0 Original line number Diff line number Diff line Loading @@ -493,6 +493,35 @@ struct cpr3_aging_sensor_info { u32 bypass_mask[CPR3_MAX_SENSOR_COUNT / 32]; }; /** * struct cpr3_reg_info - Register information data structure * @name: Register name * @addr: Register physical address * @value: Register content * * This data structure is used to dump some critical register contents * when the device crashes due to a kernel panic. */ struct cpr3_reg_info { const char *name; u32 addr; u32 value; }; /** * struct cpr3_panic_regs_info - Data structure to dump critical register * contents. * @reg_count: Number of elements in the regs array * @regs: Array of critical registers information * * This data structure is used to dump critical register contents when * the device crashes due to a kernel panic. */ struct cpr3_panic_regs_info { int reg_count; struct cpr3_reg_info *regs; }; /** * struct cpr3_controller - CPR3 controller data structure * @dev: Device pointer for the CPR3 controller device Loading Loading @@ -662,6 +691,9 @@ struct cpr3_aging_sensor_info { * VDD supply voltage to settle after being increased or * decreased by step_volt microvolts which is used when * SDELTA voltage margin adjustments are applied. * @panic_regs_info: Array of panic registers information which provides the * list of registers to dump when the device crashes. * @panic_notifier: Notifier block registered to global panic notifier list. * * This structure contains both configuration and runtime state data. The * elements cpr_allowed_sw, use_hw_closed_loop, aggr_corner, cpr_enabled, Loading Loading @@ -755,6 +787,8 @@ struct cpr3_controller { u32 temp_sensor_id_start; u32 temp_sensor_id_end; u32 voltage_settling_time; struct cpr3_panic_regs_info *panic_regs_info; struct notifier_block panic_notifier; }; /* Used for rounding voltages to the closest physically available set point. */ Loading
drivers/regulator/cpr3-util.c +70 −0 Original line number Diff line number Diff line Loading @@ -1020,6 +1020,74 @@ static int cpr3_parse_irq_affinity(struct cpr3_controller *ctrl) return 0; } static int cpr3_panic_notifier_init(struct cpr3_controller *ctrl) { struct device_node *node = ctrl->dev->of_node; struct cpr3_panic_regs_info *panic_regs_info; struct cpr3_reg_info *regs; int i, reg_count, len, rc = 0; if (!of_find_property(node, "qcom,cpr-panic-reg-addr-list", &len)) { /* panic register address list not specified */ return rc; } reg_count = len / sizeof(u32); if (!reg_count) { cpr3_err(ctrl, "qcom,cpr-panic-reg-addr-list has invalid len = %d\n", len); return -EINVAL; } if (!of_find_property(node, "qcom,cpr-panic-reg-name-list", NULL)) { cpr3_err(ctrl, "property qcom,cpr-panic-reg-name-list not specified\n"); return -EINVAL; } len = of_property_count_strings(node, "qcom,cpr-panic-reg-name-list"); if (reg_count != len) { cpr3_err(ctrl, "qcom,cpr-panic-reg-name-list should have %d strings\n", reg_count); return -EINVAL; } panic_regs_info = devm_kzalloc(ctrl->dev, sizeof(*panic_regs_info), GFP_KERNEL); if (!panic_regs_info) return -ENOMEM; regs = devm_kcalloc(ctrl->dev, reg_count, sizeof(*regs), GFP_KERNEL); if (!regs) return -ENOMEM; for (i = 0; i < reg_count; i++) { rc = of_property_read_string_index(node, "qcom,cpr-panic-reg-name-list", i, &(regs[i].name)); if (rc) { cpr3_err(ctrl, "error reading property qcom,cpr-panic-reg-name-list, rc=%d\n", rc); return rc; } rc = of_property_read_u32_index(node, "qcom,cpr-panic-reg-addr-list", i, &(regs[i].addr)); if (rc) { cpr3_err(ctrl, "error reading property qcom,cpr-panic-reg-addr-list, rc=%d\n", rc); return rc; } regs[i].value = 0xFFFFFFFF; } panic_regs_info->reg_count = reg_count; panic_regs_info->regs = regs; ctrl->panic_regs_info = panic_regs_info; return rc; } /** * cpr3_parse_common_ctrl_data() - parse common CPR3 controller properties from * device tree Loading Loading @@ -1147,6 +1215,8 @@ int cpr3_parse_common_ctrl_data(struct cpr3_controller *ctrl) } } rc = cpr3_panic_notifier_init(ctrl); return rc; } Loading