Loading Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt +21 −2 Original line number Original line Diff line number Diff line Loading @@ -66,12 +66,25 @@ Optional properties: All the below properties are in the sub-node section (properties of the child All the below properties are in the sub-node section (properties of the child node). node). Sub-node required properties: Sub-nodes (if defined) should belong to either a PON configuration or a regulator configuration. Regulator sub-node required properties: - regulator-name Regulator name for the PON regulator that is being configured. - qcom,pon-spare-reg-addr Register offset from the base address of the PON peripheral that needs to be configured for the regulator being controlled. - qcom,pon-spare-reg-bit Bit position in the specified register that needs to be configured for the regulator being controlled. PON sub-node required properties: - qcom,pon-type The type of PON/RESET source. The driver - qcom,pon-type The type of PON/RESET source. The driver currently supports KPDPWR(0), RESIN(1) and currently supports KPDPWR(0), RESIN(1) and CBLPWR(2) pon/reset sources. CBLPWR(2) pon/reset sources. Sub-node optional properties: PON sub-node optional properties: - qcom,pull-up The initial state of the reset pin under - qcom,pull-up The initial state of the reset pin under consideration. consideration. 0 = No pull-up 0 = No pull-up Loading Loading @@ -152,4 +165,10 @@ Example: compatible = "qcom,qpnp-power-on"; compatible = "qcom,qpnp-power-on"; reg = <0x800 0x100>; reg = <0x800 0x100>; qcom,secondary-pon-reset; qcom,secondary-pon-reset; pon_perph_reg: qcom,pon_perph_reg { regulator-name = "pon_spare_reg"; qcom,pon-spare-reg-addr = <0x8c>; qcom,pon-spare-reg-bit = <1>; }; }; }; arch/arm/boot/dts/qcom/msm-pmi8994.dtsi +5 −0 Original line number Original line Diff line number Diff line Loading @@ -33,6 +33,11 @@ qcom,secondary-pon-reset; qcom,secondary-pon-reset; qcom,s3-debounce = <32>; qcom,s3-debounce = <32>; qcom,s3-src = "kpdpwr-and-resin"; qcom,s3-src = "kpdpwr-and-resin"; pon_perph_reg: qcom,pon_perph_reg { regulator-name = "pon_spare_reg"; qcom,pon-spare-reg-addr = <0x8c>; qcom,pon-spare-reg-bit = <1>; }; }; }; pmi8994_gpios: gpios { pmi8994_gpios: gpios { Loading arch/arm/boot/dts/qcom/msm8996-regulator.dtsi +2 −0 Original line number Original line Diff line number Diff line Loading @@ -456,6 +456,7 @@ * control boost regulator request. * control boost regulator request. */ */ regulator-name = "pmi8994_boost_5v"; regulator-name = "pmi8994_boost_5v"; parent-supply = <&pon_perph_reg>; status = "okay"; status = "okay"; }; }; pmi8994_boost_pin_ctrl: regulator-bst-pin-ctrl { pmi8994_boost_pin_ctrl: regulator-bst-pin-ctrl { Loading @@ -468,6 +469,7 @@ */ */ compatible = "qcom,rpm-smd-regulator"; compatible = "qcom,rpm-smd-regulator"; regulator-name = "pmi8994_boost_pin_ctrl"; regulator-name = "pmi8994_boost_pin_ctrl"; parent-supply = <&pon_perph_reg>; qcom,set = <3>; qcom,set = <3>; qcom,enable-with-pin-ctrl = <0 1>; qcom,enable-with-pin-ctrl = <0 1>; }; }; Loading drivers/platform/msm/qpnp-power-on.c +186 −20 Original line number Original line Diff line number Diff line Loading @@ -25,6 +25,9 @@ #include <linux/mutex.h> #include <linux/mutex.h> #include <linux/input.h> #include <linux/input.h> #include <linux/log2.h> #include <linux/log2.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/regulator/of_regulator.h> #include <linux/qpnp/power-on.h> #include <linux/qpnp/power-on.h> #define CREATE_MASK(NUM_BITS, POS) \ #define CREATE_MASK(NUM_BITS, POS) \ Loading Loading @@ -151,19 +154,31 @@ struct qpnp_pon_config { bool config_reset; bool config_reset; }; }; struct pon_regulator { struct qpnp_pon *pon; struct regulator_dev *rdev; struct regulator_desc rdesc; u32 addr; u32 bit; bool enabled; }; struct qpnp_pon { struct qpnp_pon { struct spmi_device *spmi; struct spmi_device *spmi; struct input_dev *pon_input; struct input_dev *pon_input; struct qpnp_pon_config *pon_cfg; struct qpnp_pon_config *pon_cfg; struct pon_regulator *pon_reg_cfg; struct list_head list; struct list_head list; int num_pon_config; u16 base; struct delayed_work bark_work; struct delayed_work bark_work; u32 dbc; struct dentry *debugfs; int pon_trigger_reason; int pon_trigger_reason; int pon_power_off_reason; int pon_power_off_reason; int num_pon_reg; int num_pon_config; int reg_count; u32 dbc; u32 uvlo; u32 uvlo; struct dentry *debugfs; u16 base; u8 warm_reset_reason1; u8 warm_reset_reason1; u8 warm_reset_reason2; u8 warm_reset_reason2; bool is_spon; bool is_spon; Loading Loading @@ -1093,7 +1108,9 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon) } } /* iterate through the list of pon configs */ /* iterate through the list of pon configs */ while ((pp = of_get_next_child(pon->spmi->dev.of_node, pp))) { for_each_available_child_of_node(pon->spmi->dev.of_node, pp) { if (!of_find_property(pp, "qcom,pon-type", NULL)) continue; cfg = &pon->pon_cfg[i++]; cfg = &pon->pon_cfg[i++]; Loading Loading @@ -1436,6 +1453,137 @@ free_input_dev: return rc; return rc; } } static int pon_spare_regulator_enable(struct regulator_dev *rdev) { int rc = 0; u8 value; struct pon_regulator *pon_reg = rdev_get_drvdata(rdev); pr_debug("reg %s enable addr: %x bit: %d\n", rdev->desc->name, pon_reg->addr, pon_reg->bit); value = BIT(pon_reg->bit) & 0xFF; rc = qpnp_pon_masked_write(pon_reg->pon, pon_reg->pon->base + pon_reg->addr, value, value); if (rc) dev_err(&pon_reg->pon->spmi->dev, "Unable to write to %x\n", pon_reg->pon->base + pon_reg->addr); else pon_reg->enabled = true; return rc; } static int pon_spare_regulator_disable(struct regulator_dev *rdev) { int rc = 0; u8 mask; struct pon_regulator *pon_reg = rdev_get_drvdata(rdev); pr_debug("reg %s disable addr: %x bit: %d\n", rdev->desc->name, pon_reg->addr, pon_reg->bit); mask = BIT(pon_reg->bit) & 0xFF; rc = qpnp_pon_masked_write(pon_reg->pon, pon_reg->pon->base + pon_reg->addr, mask, 0); if (rc) dev_err(&pon_reg->pon->spmi->dev, "Unable to write to %x\n", pon_reg->pon->base + pon_reg->addr); else pon_reg->enabled = false; return rc; } static int pon_spare_regulator_is_enable(struct regulator_dev *rdev) { struct pon_regulator *pon_reg = rdev_get_drvdata(rdev); return pon_reg->enabled; } struct regulator_ops pon_spare_reg_ops = { .enable = pon_spare_regulator_enable, .disable = pon_spare_regulator_disable, .is_enabled = pon_spare_regulator_is_enable, }; static int pon_regulator_init(struct qpnp_pon *pon) { int rc = 0, i = 0; struct regulator_init_data *init_data; struct regulator_config reg_cfg = {}; struct device_node *node = NULL; struct device *dev = &pon->spmi->dev; struct pon_regulator *pon_reg; if (!pon->num_pon_reg) return 0; pon->pon_reg_cfg = devm_kcalloc(dev, pon->num_pon_reg, sizeof(*(pon->pon_reg_cfg)), GFP_KERNEL); if (!pon->pon_reg_cfg) return -ENOMEM; for_each_available_child_of_node(dev->of_node, node) { if (!of_find_property(node, "regulator-name", NULL)) continue; pon_reg = &pon->pon_reg_cfg[i++]; pon_reg->pon = pon; rc = of_property_read_u32(node, "qcom,pon-spare-reg-addr", &pon_reg->addr); if (rc) { dev_err(dev, "Unable to read address for regulator, rc=%d\n", rc); return rc; } rc = of_property_read_u32(node, "qcom,pon-spare-reg-bit", &pon_reg->bit); if (rc) { dev_err(dev, "Unable to read bit for regulator, rc=%d\n", rc); return rc; } init_data = of_get_regulator_init_data(dev, node); if (!init_data) { dev_err(dev, "regulator init data is missing\n"); return -EINVAL; } init_data->constraints.valid_ops_mask |= REGULATOR_CHANGE_STATUS; if (!init_data->constraints.name) { dev_err(dev, "regulator-name is missing\n"); return -EINVAL; } pon_reg->rdesc.owner = THIS_MODULE; pon_reg->rdesc.type = REGULATOR_VOLTAGE; pon_reg->rdesc.ops = &pon_spare_reg_ops; pon_reg->rdesc.name = init_data->constraints.name; reg_cfg.dev = dev; reg_cfg.init_data = init_data; reg_cfg.driver_data = pon_reg; reg_cfg.of_node = node; pon_reg->rdev = regulator_register(&pon_reg->rdesc, ®_cfg); if (IS_ERR(pon_reg->rdev)) { rc = PTR_ERR(pon_reg->rdev); pon_reg->rdev = NULL; if (rc != -EPROBE_DEFER) dev_err(dev, "regulator_register failed, rc=%d\n", rc); return rc; } } return rc; } static bool dload_on_uvlo; static bool dload_on_uvlo; static int qpnp_pon_debugfs_uvlo_dload_get(char *buf, static int qpnp_pon_debugfs_uvlo_dload_get(char *buf, Loading Loading @@ -1572,7 +1720,7 @@ static int qpnp_pon_probe(struct spmi_device *spmi) { { struct qpnp_pon *pon; struct qpnp_pon *pon; struct resource *pon_resource; struct resource *pon_resource; struct device_node *itr = NULL; struct device_node *node = NULL; u32 delay = 0, s3_debounce = 0; u32 delay = 0, s3_debounce = 0; int rc, sys_reset, index; int rc, sys_reset, index; u8 pon_sts = 0, buf[2]; u8 pon_sts = 0, buf[2]; Loading Loading @@ -1607,8 +1755,26 @@ static int qpnp_pon_probe(struct spmi_device *spmi) pon->base = pon_resource->start; pon->base = pon_resource->start; /* get the total number of pon configurations */ /* get the total number of pon configurations */ while ((itr = of_get_next_child(spmi->dev.of_node, itr))) for_each_available_child_of_node(spmi->dev.of_node, node) { if (of_find_property(node, "regulator-name", NULL)) { pon->num_pon_reg++; } else if (of_find_property(node, "qcom,pon-type", NULL)) { pon->num_pon_config++; pon->num_pon_config++; } else { pr_err("Unknown sub-node\n"); return -EINVAL; } } pr_debug("PON@SID %d: num_pon_config: %d num_pon_reg: %d\n", pon->spmi->sid, pon->num_pon_config, pon->num_pon_reg); rc = pon_regulator_init(pon); if (rc) { dev_err(&pon->spmi->dev, "Error in pon_regulator_init rc: %d\n", rc); return rc; } if (!pon->num_pon_config) if (!pon->num_pon_config) /* No PON config., do not register the driver */ /* No PON config., do not register the driver */ Loading Loading
Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt +21 −2 Original line number Original line Diff line number Diff line Loading @@ -66,12 +66,25 @@ Optional properties: All the below properties are in the sub-node section (properties of the child All the below properties are in the sub-node section (properties of the child node). node). Sub-node required properties: Sub-nodes (if defined) should belong to either a PON configuration or a regulator configuration. Regulator sub-node required properties: - regulator-name Regulator name for the PON regulator that is being configured. - qcom,pon-spare-reg-addr Register offset from the base address of the PON peripheral that needs to be configured for the regulator being controlled. - qcom,pon-spare-reg-bit Bit position in the specified register that needs to be configured for the regulator being controlled. PON sub-node required properties: - qcom,pon-type The type of PON/RESET source. The driver - qcom,pon-type The type of PON/RESET source. The driver currently supports KPDPWR(0), RESIN(1) and currently supports KPDPWR(0), RESIN(1) and CBLPWR(2) pon/reset sources. CBLPWR(2) pon/reset sources. Sub-node optional properties: PON sub-node optional properties: - qcom,pull-up The initial state of the reset pin under - qcom,pull-up The initial state of the reset pin under consideration. consideration. 0 = No pull-up 0 = No pull-up Loading Loading @@ -152,4 +165,10 @@ Example: compatible = "qcom,qpnp-power-on"; compatible = "qcom,qpnp-power-on"; reg = <0x800 0x100>; reg = <0x800 0x100>; qcom,secondary-pon-reset; qcom,secondary-pon-reset; pon_perph_reg: qcom,pon_perph_reg { regulator-name = "pon_spare_reg"; qcom,pon-spare-reg-addr = <0x8c>; qcom,pon-spare-reg-bit = <1>; }; }; };
arch/arm/boot/dts/qcom/msm-pmi8994.dtsi +5 −0 Original line number Original line Diff line number Diff line Loading @@ -33,6 +33,11 @@ qcom,secondary-pon-reset; qcom,secondary-pon-reset; qcom,s3-debounce = <32>; qcom,s3-debounce = <32>; qcom,s3-src = "kpdpwr-and-resin"; qcom,s3-src = "kpdpwr-and-resin"; pon_perph_reg: qcom,pon_perph_reg { regulator-name = "pon_spare_reg"; qcom,pon-spare-reg-addr = <0x8c>; qcom,pon-spare-reg-bit = <1>; }; }; }; pmi8994_gpios: gpios { pmi8994_gpios: gpios { Loading
arch/arm/boot/dts/qcom/msm8996-regulator.dtsi +2 −0 Original line number Original line Diff line number Diff line Loading @@ -456,6 +456,7 @@ * control boost regulator request. * control boost regulator request. */ */ regulator-name = "pmi8994_boost_5v"; regulator-name = "pmi8994_boost_5v"; parent-supply = <&pon_perph_reg>; status = "okay"; status = "okay"; }; }; pmi8994_boost_pin_ctrl: regulator-bst-pin-ctrl { pmi8994_boost_pin_ctrl: regulator-bst-pin-ctrl { Loading @@ -468,6 +469,7 @@ */ */ compatible = "qcom,rpm-smd-regulator"; compatible = "qcom,rpm-smd-regulator"; regulator-name = "pmi8994_boost_pin_ctrl"; regulator-name = "pmi8994_boost_pin_ctrl"; parent-supply = <&pon_perph_reg>; qcom,set = <3>; qcom,set = <3>; qcom,enable-with-pin-ctrl = <0 1>; qcom,enable-with-pin-ctrl = <0 1>; }; }; Loading
drivers/platform/msm/qpnp-power-on.c +186 −20 Original line number Original line Diff line number Diff line Loading @@ -25,6 +25,9 @@ #include <linux/mutex.h> #include <linux/mutex.h> #include <linux/input.h> #include <linux/input.h> #include <linux/log2.h> #include <linux/log2.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/regulator/of_regulator.h> #include <linux/qpnp/power-on.h> #include <linux/qpnp/power-on.h> #define CREATE_MASK(NUM_BITS, POS) \ #define CREATE_MASK(NUM_BITS, POS) \ Loading Loading @@ -151,19 +154,31 @@ struct qpnp_pon_config { bool config_reset; bool config_reset; }; }; struct pon_regulator { struct qpnp_pon *pon; struct regulator_dev *rdev; struct regulator_desc rdesc; u32 addr; u32 bit; bool enabled; }; struct qpnp_pon { struct qpnp_pon { struct spmi_device *spmi; struct spmi_device *spmi; struct input_dev *pon_input; struct input_dev *pon_input; struct qpnp_pon_config *pon_cfg; struct qpnp_pon_config *pon_cfg; struct pon_regulator *pon_reg_cfg; struct list_head list; struct list_head list; int num_pon_config; u16 base; struct delayed_work bark_work; struct delayed_work bark_work; u32 dbc; struct dentry *debugfs; int pon_trigger_reason; int pon_trigger_reason; int pon_power_off_reason; int pon_power_off_reason; int num_pon_reg; int num_pon_config; int reg_count; u32 dbc; u32 uvlo; u32 uvlo; struct dentry *debugfs; u16 base; u8 warm_reset_reason1; u8 warm_reset_reason1; u8 warm_reset_reason2; u8 warm_reset_reason2; bool is_spon; bool is_spon; Loading Loading @@ -1093,7 +1108,9 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon) } } /* iterate through the list of pon configs */ /* iterate through the list of pon configs */ while ((pp = of_get_next_child(pon->spmi->dev.of_node, pp))) { for_each_available_child_of_node(pon->spmi->dev.of_node, pp) { if (!of_find_property(pp, "qcom,pon-type", NULL)) continue; cfg = &pon->pon_cfg[i++]; cfg = &pon->pon_cfg[i++]; Loading Loading @@ -1436,6 +1453,137 @@ free_input_dev: return rc; return rc; } } static int pon_spare_regulator_enable(struct regulator_dev *rdev) { int rc = 0; u8 value; struct pon_regulator *pon_reg = rdev_get_drvdata(rdev); pr_debug("reg %s enable addr: %x bit: %d\n", rdev->desc->name, pon_reg->addr, pon_reg->bit); value = BIT(pon_reg->bit) & 0xFF; rc = qpnp_pon_masked_write(pon_reg->pon, pon_reg->pon->base + pon_reg->addr, value, value); if (rc) dev_err(&pon_reg->pon->spmi->dev, "Unable to write to %x\n", pon_reg->pon->base + pon_reg->addr); else pon_reg->enabled = true; return rc; } static int pon_spare_regulator_disable(struct regulator_dev *rdev) { int rc = 0; u8 mask; struct pon_regulator *pon_reg = rdev_get_drvdata(rdev); pr_debug("reg %s disable addr: %x bit: %d\n", rdev->desc->name, pon_reg->addr, pon_reg->bit); mask = BIT(pon_reg->bit) & 0xFF; rc = qpnp_pon_masked_write(pon_reg->pon, pon_reg->pon->base + pon_reg->addr, mask, 0); if (rc) dev_err(&pon_reg->pon->spmi->dev, "Unable to write to %x\n", pon_reg->pon->base + pon_reg->addr); else pon_reg->enabled = false; return rc; } static int pon_spare_regulator_is_enable(struct regulator_dev *rdev) { struct pon_regulator *pon_reg = rdev_get_drvdata(rdev); return pon_reg->enabled; } struct regulator_ops pon_spare_reg_ops = { .enable = pon_spare_regulator_enable, .disable = pon_spare_regulator_disable, .is_enabled = pon_spare_regulator_is_enable, }; static int pon_regulator_init(struct qpnp_pon *pon) { int rc = 0, i = 0; struct regulator_init_data *init_data; struct regulator_config reg_cfg = {}; struct device_node *node = NULL; struct device *dev = &pon->spmi->dev; struct pon_regulator *pon_reg; if (!pon->num_pon_reg) return 0; pon->pon_reg_cfg = devm_kcalloc(dev, pon->num_pon_reg, sizeof(*(pon->pon_reg_cfg)), GFP_KERNEL); if (!pon->pon_reg_cfg) return -ENOMEM; for_each_available_child_of_node(dev->of_node, node) { if (!of_find_property(node, "regulator-name", NULL)) continue; pon_reg = &pon->pon_reg_cfg[i++]; pon_reg->pon = pon; rc = of_property_read_u32(node, "qcom,pon-spare-reg-addr", &pon_reg->addr); if (rc) { dev_err(dev, "Unable to read address for regulator, rc=%d\n", rc); return rc; } rc = of_property_read_u32(node, "qcom,pon-spare-reg-bit", &pon_reg->bit); if (rc) { dev_err(dev, "Unable to read bit for regulator, rc=%d\n", rc); return rc; } init_data = of_get_regulator_init_data(dev, node); if (!init_data) { dev_err(dev, "regulator init data is missing\n"); return -EINVAL; } init_data->constraints.valid_ops_mask |= REGULATOR_CHANGE_STATUS; if (!init_data->constraints.name) { dev_err(dev, "regulator-name is missing\n"); return -EINVAL; } pon_reg->rdesc.owner = THIS_MODULE; pon_reg->rdesc.type = REGULATOR_VOLTAGE; pon_reg->rdesc.ops = &pon_spare_reg_ops; pon_reg->rdesc.name = init_data->constraints.name; reg_cfg.dev = dev; reg_cfg.init_data = init_data; reg_cfg.driver_data = pon_reg; reg_cfg.of_node = node; pon_reg->rdev = regulator_register(&pon_reg->rdesc, ®_cfg); if (IS_ERR(pon_reg->rdev)) { rc = PTR_ERR(pon_reg->rdev); pon_reg->rdev = NULL; if (rc != -EPROBE_DEFER) dev_err(dev, "regulator_register failed, rc=%d\n", rc); return rc; } } return rc; } static bool dload_on_uvlo; static bool dload_on_uvlo; static int qpnp_pon_debugfs_uvlo_dload_get(char *buf, static int qpnp_pon_debugfs_uvlo_dload_get(char *buf, Loading Loading @@ -1572,7 +1720,7 @@ static int qpnp_pon_probe(struct spmi_device *spmi) { { struct qpnp_pon *pon; struct qpnp_pon *pon; struct resource *pon_resource; struct resource *pon_resource; struct device_node *itr = NULL; struct device_node *node = NULL; u32 delay = 0, s3_debounce = 0; u32 delay = 0, s3_debounce = 0; int rc, sys_reset, index; int rc, sys_reset, index; u8 pon_sts = 0, buf[2]; u8 pon_sts = 0, buf[2]; Loading Loading @@ -1607,8 +1755,26 @@ static int qpnp_pon_probe(struct spmi_device *spmi) pon->base = pon_resource->start; pon->base = pon_resource->start; /* get the total number of pon configurations */ /* get the total number of pon configurations */ while ((itr = of_get_next_child(spmi->dev.of_node, itr))) for_each_available_child_of_node(spmi->dev.of_node, node) { if (of_find_property(node, "regulator-name", NULL)) { pon->num_pon_reg++; } else if (of_find_property(node, "qcom,pon-type", NULL)) { pon->num_pon_config++; pon->num_pon_config++; } else { pr_err("Unknown sub-node\n"); return -EINVAL; } } pr_debug("PON@SID %d: num_pon_config: %d num_pon_reg: %d\n", pon->spmi->sid, pon->num_pon_config, pon->num_pon_reg); rc = pon_regulator_init(pon); if (rc) { dev_err(&pon->spmi->dev, "Error in pon_regulator_init rc: %d\n", rc); return rc; } if (!pon->num_pon_config) if (!pon->num_pon_config) /* No PON config., do not register the driver */ /* No PON config., do not register the driver */ Loading