diff options
| author | Mark Brown <broonie@kernel.org> | 2014-09-28 07:14:26 -0400 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2014-09-28 07:14:26 -0400 |
| commit | d1c3f7ca158e78fa78c9789d836d2a98d5fd25f3 (patch) | |
| tree | 30f11b3581cdab9f344bd6718a73988e7fc6a59c | |
| parent | 6a642509801116037720892efe72f0e84f02f317 (diff) | |
| parent | fbf7974427910a3f13fcb76a3493f9da0b141120 (diff) | |
Merge remote-tracking branch 'regulator/topic/pwm' into regulator-drivers
Conflicts:
drivers/regulator/Kconfig
| -rw-r--r-- | Documentation/devicetree/bindings/regulator/pwm-regulator.txt | 27 | ||||
| -rw-r--r-- | drivers/regulator/Kconfig | 13 | ||||
| -rw-r--r-- | drivers/regulator/Makefile | 2 | ||||
| -rw-r--r-- | drivers/regulator/pwm-regulator.c | 197 | ||||
| -rw-r--r-- | drivers/regulator/st-pwm.c | 190 |
5 files changed, 232 insertions, 197 deletions
diff --git a/Documentation/devicetree/bindings/regulator/pwm-regulator.txt b/Documentation/devicetree/bindings/regulator/pwm-regulator.txt new file mode 100644 index 000000000000..ce91f61feb12 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/pwm-regulator.txt | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | pwm regulator bindings | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible: Should be "pwm-regulator" | ||
| 5 | - pwms: OF device-tree PWM specification (see PWM binding pwm.txt) | ||
| 6 | - voltage-table: voltage and duty table, include 2 members in each set of | ||
| 7 | brackets, first one is voltage(unit: uv), the next is duty(unit: percent) | ||
| 8 | |||
| 9 | Any property defined as part of the core regulator binding defined in | ||
| 10 | regulator.txt can also be used. | ||
| 11 | |||
| 12 | Example: | ||
| 13 | pwm_regulator { | ||
| 14 | compatible = "pwm-regulator; | ||
| 15 | pwms = <&pwm1 0 8448 0>; | ||
| 16 | |||
| 17 | voltage-table = <1114000 0>, | ||
| 18 | <1095000 10>, | ||
| 19 | <1076000 20>, | ||
| 20 | <1056000 30>, | ||
| 21 | <1036000 40>, | ||
| 22 | <1016000 50>; | ||
| 23 | |||
| 24 | regulator-min-microvolt = <1016000>; | ||
| 25 | regulator-max-microvolt = <1114000>; | ||
| 26 | regulator-name = "vdd_logic"; | ||
| 27 | }; | ||
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 0e59754d8df2..c3ca05cb5c87 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
| @@ -449,6 +449,13 @@ config REGULATOR_PFUZE100 | |||
| 449 | Say y here to support the regulators found on the Freescale | 449 | Say y here to support the regulators found on the Freescale |
| 450 | PFUZE100/PFUZE200 PMIC. | 450 | PFUZE100/PFUZE200 PMIC. |
| 451 | 451 | ||
| 452 | config REGULATOR_PWM | ||
| 453 | tristate "PWM voltage regulator" | ||
| 454 | depends on PWM | ||
| 455 | help | ||
| 456 | This driver supports PWM controlled voltage regulators. PWM | ||
| 457 | duty cycle can increase or decrease the voltage. | ||
| 458 | |||
| 452 | config REGULATOR_QCOM_RPM | 459 | config REGULATOR_QCOM_RPM |
| 453 | tristate "Qualcomm RPM regulator driver" | 460 | tristate "Qualcomm RPM regulator driver" |
| 454 | depends on MFD_QCOM_RPM | 461 | depends on MFD_QCOM_RPM |
| @@ -495,12 +502,6 @@ config REGULATOR_S5M8767 | |||
| 495 | via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and | 502 | via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and |
| 496 | supports DVS mode with 8bits of output voltage control. | 503 | supports DVS mode with 8bits of output voltage control. |
| 497 | 504 | ||
| 498 | config REGULATOR_ST_PWM | ||
| 499 | tristate "STMicroelectronics PWM voltage regulator" | ||
| 500 | depends on ARCH_STI | ||
| 501 | help | ||
| 502 | This driver supports ST's PWM controlled voltage regulators. | ||
| 503 | |||
| 504 | config REGULATOR_TI_ABB | 505 | config REGULATOR_TI_ABB |
| 505 | tristate "TI Adaptive Body Bias on-chip LDO" | 506 | tristate "TI Adaptive Body Bias on-chip LDO" |
| 506 | depends on ARCH_OMAP | 507 | depends on ARCH_OMAP |
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 9c50dc61d927..2f49356e03a7 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile | |||
| @@ -58,6 +58,7 @@ obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o | |||
| 58 | obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o | 58 | obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o |
| 59 | obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o | 59 | obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o |
| 60 | obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o | 60 | obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o |
| 61 | obj-$(CONFIG_REGULATOR_PWM) += pwm-regulator.o | ||
| 61 | obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o | 62 | obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o |
| 62 | obj-$(CONFIG_REGULATOR_PBIAS) += pbias-regulator.o | 63 | obj-$(CONFIG_REGULATOR_PBIAS) += pbias-regulator.o |
| 63 | obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o | 64 | obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o |
| @@ -66,7 +67,6 @@ obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o | |||
| 66 | obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o | 67 | obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o |
| 67 | obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o | 68 | obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o |
| 68 | obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o | 69 | obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o |
| 69 | obj-$(CONFIG_REGULATOR_ST_PWM) += st-pwm.o | ||
| 70 | obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o | 70 | obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o |
| 71 | obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o | 71 | obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o |
| 72 | obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o | 72 | obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o |
diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c new file mode 100644 index 000000000000..d3f55eaea058 --- /dev/null +++ b/drivers/regulator/pwm-regulator.c | |||
| @@ -0,0 +1,197 @@ | |||
| 1 | /* | ||
| 2 | * Regulator driver for PWM Regulators | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 - STMicroelectronics Inc. | ||
| 5 | * | ||
| 6 | * Author: Lee Jones <lee.jones@linaro.org> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/init.h> | ||
| 15 | #include <linux/err.h> | ||
| 16 | #include <linux/regulator/driver.h> | ||
| 17 | #include <linux/regulator/machine.h> | ||
| 18 | #include <linux/regulator/of_regulator.h> | ||
| 19 | #include <linux/of.h> | ||
| 20 | #include <linux/of_device.h> | ||
| 21 | #include <linux/pwm.h> | ||
| 22 | |||
| 23 | struct pwm_regulator_data { | ||
| 24 | struct regulator_desc desc; | ||
| 25 | struct pwm_voltages *duty_cycle_table; | ||
| 26 | struct pwm_device *pwm; | ||
| 27 | bool enabled; | ||
| 28 | int state; | ||
| 29 | }; | ||
| 30 | |||
| 31 | struct pwm_voltages { | ||
| 32 | unsigned int uV; | ||
| 33 | unsigned int dutycycle; | ||
| 34 | }; | ||
| 35 | |||
| 36 | static int pwm_regulator_get_voltage_sel(struct regulator_dev *dev) | ||
| 37 | { | ||
| 38 | struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); | ||
| 39 | |||
| 40 | return drvdata->state; | ||
| 41 | } | ||
| 42 | |||
| 43 | static int pwm_regulator_set_voltage_sel(struct regulator_dev *dev, | ||
| 44 | unsigned selector) | ||
| 45 | { | ||
| 46 | struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); | ||
| 47 | unsigned int pwm_reg_period; | ||
| 48 | int dutycycle; | ||
| 49 | int ret; | ||
| 50 | |||
| 51 | pwm_reg_period = pwm_get_period(drvdata->pwm); | ||
| 52 | |||
| 53 | dutycycle = (pwm_reg_period * | ||
| 54 | drvdata->duty_cycle_table[selector].dutycycle) / 100; | ||
| 55 | |||
| 56 | ret = pwm_config(drvdata->pwm, dutycycle, pwm_reg_period); | ||
| 57 | if (ret) { | ||
| 58 | dev_err(&dev->dev, "Failed to configure PWM\n"); | ||
| 59 | return ret; | ||
| 60 | } | ||
| 61 | |||
| 62 | drvdata->state = selector; | ||
| 63 | |||
| 64 | if (!drvdata->enabled) { | ||
| 65 | ret = pwm_enable(drvdata->pwm); | ||
| 66 | if (ret) { | ||
| 67 | dev_err(&dev->dev, "Failed to enable PWM\n"); | ||
| 68 | return ret; | ||
| 69 | } | ||
| 70 | drvdata->enabled = true; | ||
| 71 | } | ||
| 72 | |||
| 73 | return 0; | ||
| 74 | } | ||
| 75 | |||
| 76 | static int pwm_regulator_list_voltage(struct regulator_dev *dev, | ||
| 77 | unsigned selector) | ||
| 78 | { | ||
| 79 | struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); | ||
| 80 | |||
| 81 | if (selector >= drvdata->desc.n_voltages) | ||
| 82 | return -EINVAL; | ||
| 83 | |||
| 84 | return drvdata->duty_cycle_table[selector].uV; | ||
| 85 | } | ||
| 86 | |||
| 87 | static struct regulator_ops pwm_regulator_voltage_ops = { | ||
| 88 | .set_voltage_sel = pwm_regulator_set_voltage_sel, | ||
| 89 | .get_voltage_sel = pwm_regulator_get_voltage_sel, | ||
| 90 | .list_voltage = pwm_regulator_list_voltage, | ||
| 91 | .map_voltage = regulator_map_voltage_iterate, | ||
| 92 | }; | ||
| 93 | |||
| 94 | static const struct regulator_desc pwm_regulator_desc = { | ||
| 95 | .name = "pwm-regulator", | ||
| 96 | .ops = &pwm_regulator_voltage_ops, | ||
| 97 | .type = REGULATOR_VOLTAGE, | ||
| 98 | .owner = THIS_MODULE, | ||
| 99 | .supply_name = "pwm", | ||
| 100 | }; | ||
| 101 | |||
| 102 | static int pwm_regulator_probe(struct platform_device *pdev) | ||
| 103 | { | ||
| 104 | struct pwm_regulator_data *drvdata; | ||
| 105 | struct property *prop; | ||
| 106 | struct regulator_dev *regulator; | ||
| 107 | struct regulator_config config = { }; | ||
| 108 | struct device_node *np = pdev->dev.of_node; | ||
| 109 | int length, ret; | ||
| 110 | |||
| 111 | if (!np) { | ||
| 112 | dev_err(&pdev->dev, "Device Tree node missing\n"); | ||
| 113 | return -EINVAL; | ||
| 114 | } | ||
| 115 | |||
| 116 | drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); | ||
| 117 | if (!drvdata) | ||
| 118 | return -ENOMEM; | ||
| 119 | |||
| 120 | memcpy(&drvdata->desc, &pwm_regulator_desc, sizeof(pwm_regulator_desc)); | ||
| 121 | |||
| 122 | /* determine the number of voltage-table */ | ||
| 123 | prop = of_find_property(np, "voltage-table", &length); | ||
| 124 | if (!prop) { | ||
| 125 | dev_err(&pdev->dev, "No voltage-table\n"); | ||
| 126 | return -EINVAL; | ||
| 127 | } | ||
| 128 | |||
| 129 | if ((length < sizeof(*drvdata->duty_cycle_table)) || | ||
| 130 | (length % sizeof(*drvdata->duty_cycle_table))) { | ||
| 131 | dev_err(&pdev->dev, "voltage-table length(%d) is invalid\n", | ||
| 132 | length); | ||
| 133 | return -EINVAL; | ||
| 134 | } | ||
| 135 | |||
| 136 | drvdata->desc.n_voltages = length / sizeof(*drvdata->duty_cycle_table); | ||
| 137 | |||
| 138 | drvdata->duty_cycle_table = devm_kzalloc(&pdev->dev, | ||
| 139 | length, GFP_KERNEL); | ||
| 140 | if (!drvdata->duty_cycle_table) | ||
| 141 | return -ENOMEM; | ||
| 142 | |||
| 143 | /* read voltage table from DT property */ | ||
| 144 | ret = of_property_read_u32_array(np, "voltage-table", | ||
| 145 | (u32 *)drvdata->duty_cycle_table, | ||
| 146 | length / sizeof(u32)); | ||
| 147 | if (ret < 0) { | ||
| 148 | dev_err(&pdev->dev, "read voltage-table failed\n"); | ||
| 149 | return ret; | ||
| 150 | } | ||
| 151 | |||
| 152 | config.init_data = of_get_regulator_init_data(&pdev->dev, np); | ||
| 153 | if (!config.init_data) | ||
| 154 | return -ENOMEM; | ||
| 155 | |||
| 156 | config.of_node = np; | ||
| 157 | config.dev = &pdev->dev; | ||
| 158 | config.driver_data = drvdata; | ||
| 159 | |||
| 160 | drvdata->pwm = devm_pwm_get(&pdev->dev, NULL); | ||
| 161 | if (IS_ERR(drvdata->pwm)) { | ||
| 162 | dev_err(&pdev->dev, "Failed to get PWM\n"); | ||
| 163 | return PTR_ERR(drvdata->pwm); | ||
| 164 | } | ||
| 165 | |||
| 166 | regulator = devm_regulator_register(&pdev->dev, | ||
| 167 | &drvdata->desc, &config); | ||
| 168 | if (IS_ERR(regulator)) { | ||
| 169 | dev_err(&pdev->dev, "Failed to register regulator %s\n", | ||
| 170 | drvdata->desc.name); | ||
| 171 | return PTR_ERR(regulator); | ||
| 172 | } | ||
| 173 | |||
| 174 | return 0; | ||
| 175 | } | ||
| 176 | |||
| 177 | static const struct of_device_id pwm_of_match[] = { | ||
| 178 | { .compatible = "pwm-regulator" }, | ||
| 179 | { }, | ||
| 180 | }; | ||
| 181 | MODULE_DEVICE_TABLE(of, pwm_of_match); | ||
| 182 | |||
| 183 | static struct platform_driver pwm_regulator_driver = { | ||
| 184 | .driver = { | ||
| 185 | .name = "pwm-regulator", | ||
| 186 | .owner = THIS_MODULE, | ||
| 187 | .of_match_table = of_match_ptr(pwm_of_match), | ||
| 188 | }, | ||
| 189 | .probe = pwm_regulator_probe, | ||
| 190 | }; | ||
| 191 | |||
| 192 | module_platform_driver(pwm_regulator_driver); | ||
| 193 | |||
| 194 | MODULE_LICENSE("GPL"); | ||
| 195 | MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org>"); | ||
| 196 | MODULE_DESCRIPTION("PWM Regulator Driver"); | ||
| 197 | MODULE_ALIAS("platform:pwm-regulator"); | ||
diff --git a/drivers/regulator/st-pwm.c b/drivers/regulator/st-pwm.c deleted file mode 100644 index 5ea78df449f8..000000000000 --- a/drivers/regulator/st-pwm.c +++ /dev/null | |||
| @@ -1,190 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Regulator driver for ST's PWM Regulators | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 - STMicroelectronics Inc. | ||
| 5 | * | ||
| 6 | * Author: Lee Jones <lee.jones@linaro.org> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/init.h> | ||
| 15 | #include <linux/err.h> | ||
| 16 | #include <linux/regulator/driver.h> | ||
| 17 | #include <linux/regulator/machine.h> | ||
| 18 | #include <linux/regulator/of_regulator.h> | ||
| 19 | #include <linux/of.h> | ||
| 20 | #include <linux/of_device.h> | ||
| 21 | #include <linux/pwm.h> | ||
| 22 | |||
| 23 | #define ST_PWM_REG_PERIOD 8448 | ||
| 24 | |||
| 25 | struct st_pwm_regulator_pdata { | ||
| 26 | const struct regulator_desc *desc; | ||
| 27 | struct st_pwm_voltages *duty_cycle_table; | ||
| 28 | }; | ||
| 29 | |||
| 30 | struct st_pwm_regulator_data { | ||
| 31 | const struct st_pwm_regulator_pdata *pdata; | ||
| 32 | struct pwm_device *pwm; | ||
| 33 | bool enabled; | ||
| 34 | int state; | ||
| 35 | }; | ||
| 36 | |||
| 37 | struct st_pwm_voltages { | ||
| 38 | unsigned int uV; | ||
| 39 | unsigned int dutycycle; | ||
| 40 | }; | ||
| 41 | |||
| 42 | static int st_pwm_regulator_get_voltage_sel(struct regulator_dev *dev) | ||
| 43 | { | ||
| 44 | struct st_pwm_regulator_data *drvdata = rdev_get_drvdata(dev); | ||
| 45 | |||
| 46 | return drvdata->state; | ||
| 47 | } | ||
| 48 | |||
| 49 | static int st_pwm_regulator_set_voltage_sel(struct regulator_dev *dev, | ||
| 50 | unsigned selector) | ||
| 51 | { | ||
| 52 | struct st_pwm_regulator_data *drvdata = rdev_get_drvdata(dev); | ||
| 53 | int dutycycle; | ||
| 54 | int ret; | ||
| 55 | |||
| 56 | dutycycle = (ST_PWM_REG_PERIOD / 100) * | ||
| 57 | drvdata->pdata->duty_cycle_table[selector].dutycycle; | ||
| 58 | |||
| 59 | ret = pwm_config(drvdata->pwm, dutycycle, ST_PWM_REG_PERIOD); | ||
| 60 | if (ret) { | ||
| 61 | dev_err(&dev->dev, "Failed to configure PWM\n"); | ||
| 62 | return ret; | ||
| 63 | } | ||
| 64 | |||
| 65 | drvdata->state = selector; | ||
| 66 | |||
| 67 | if (!drvdata->enabled) { | ||
| 68 | ret = pwm_enable(drvdata->pwm); | ||
| 69 | if (ret) { | ||
| 70 | dev_err(&dev->dev, "Failed to enable PWM\n"); | ||
| 71 | return ret; | ||
| 72 | } | ||
| 73 | drvdata->enabled = true; | ||
| 74 | } | ||
| 75 | |||
| 76 | return 0; | ||
| 77 | } | ||
| 78 | |||
| 79 | static int st_pwm_regulator_list_voltage(struct regulator_dev *dev, | ||
| 80 | unsigned selector) | ||
| 81 | { | ||
| 82 | struct st_pwm_regulator_data *drvdata = rdev_get_drvdata(dev); | ||
| 83 | |||
| 84 | if (selector >= dev->desc->n_voltages) | ||
| 85 | return -EINVAL; | ||
| 86 | |||
| 87 | return drvdata->pdata->duty_cycle_table[selector].uV; | ||
| 88 | } | ||
| 89 | |||
| 90 | static struct regulator_ops st_pwm_regulator_voltage_ops = { | ||
| 91 | .set_voltage_sel = st_pwm_regulator_set_voltage_sel, | ||
| 92 | .get_voltage_sel = st_pwm_regulator_get_voltage_sel, | ||
| 93 | .list_voltage = st_pwm_regulator_list_voltage, | ||
| 94 | .map_voltage = regulator_map_voltage_iterate, | ||
| 95 | }; | ||
| 96 | |||
| 97 | static struct st_pwm_voltages b2105_duty_cycle_table[] = { | ||
| 98 | { .uV = 1114000, .dutycycle = 0, }, | ||
| 99 | { .uV = 1095000, .dutycycle = 10, }, | ||
| 100 | { .uV = 1076000, .dutycycle = 20, }, | ||
| 101 | { .uV = 1056000, .dutycycle = 30, }, | ||
| 102 | { .uV = 1036000, .dutycycle = 40, }, | ||
| 103 | { .uV = 1016000, .dutycycle = 50, }, | ||
| 104 | /* WARNING: Values above 50% duty-cycle cause boot failures. */ | ||
| 105 | }; | ||
| 106 | |||
| 107 | static const struct regulator_desc b2105_desc = { | ||
| 108 | .name = "b2105-pwm-regulator", | ||
| 109 | .ops = &st_pwm_regulator_voltage_ops, | ||
| 110 | .type = REGULATOR_VOLTAGE, | ||
| 111 | .owner = THIS_MODULE, | ||
| 112 | .n_voltages = ARRAY_SIZE(b2105_duty_cycle_table), | ||
| 113 | .supply_name = "pwm", | ||
| 114 | }; | ||
| 115 | |||
| 116 | static const struct st_pwm_regulator_pdata b2105_info = { | ||
| 117 | .desc = &b2105_desc, | ||
| 118 | .duty_cycle_table = b2105_duty_cycle_table, | ||
| 119 | }; | ||
| 120 | |||
| 121 | static const struct of_device_id st_pwm_of_match[] = { | ||
| 122 | { .compatible = "st,b2105-pwm-regulator", .data = &b2105_info, }, | ||
| 123 | { }, | ||
| 124 | }; | ||
| 125 | MODULE_DEVICE_TABLE(of, st_pwm_of_match); | ||
| 126 | |||
| 127 | static int st_pwm_regulator_probe(struct platform_device *pdev) | ||
| 128 | { | ||
| 129 | struct st_pwm_regulator_data *drvdata; | ||
| 130 | struct regulator_dev *regulator; | ||
| 131 | struct regulator_config config = { }; | ||
| 132 | struct device_node *np = pdev->dev.of_node; | ||
| 133 | const struct of_device_id *of_match; | ||
| 134 | |||
| 135 | if (!np) { | ||
| 136 | dev_err(&pdev->dev, "Device Tree node missing\n"); | ||
| 137 | return -EINVAL; | ||
| 138 | } | ||
| 139 | |||
| 140 | drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); | ||
| 141 | if (!drvdata) | ||
| 142 | return -ENOMEM; | ||
| 143 | |||
| 144 | of_match = of_match_device(st_pwm_of_match, &pdev->dev); | ||
| 145 | if (!of_match) { | ||
| 146 | dev_err(&pdev->dev, "failed to match of device\n"); | ||
| 147 | return -ENODEV; | ||
| 148 | } | ||
| 149 | drvdata->pdata = of_match->data; | ||
| 150 | |||
| 151 | config.init_data = of_get_regulator_init_data(&pdev->dev, np); | ||
| 152 | if (!config.init_data) | ||
| 153 | return -ENOMEM; | ||
| 154 | |||
| 155 | config.of_node = np; | ||
| 156 | config.dev = &pdev->dev; | ||
| 157 | config.driver_data = drvdata; | ||
| 158 | |||
| 159 | drvdata->pwm = devm_pwm_get(&pdev->dev, NULL); | ||
| 160 | if (IS_ERR(drvdata->pwm)) { | ||
| 161 | dev_err(&pdev->dev, "Failed to get PWM\n"); | ||
| 162 | return PTR_ERR(drvdata->pwm); | ||
| 163 | } | ||
| 164 | |||
| 165 | regulator = devm_regulator_register(&pdev->dev, | ||
| 166 | drvdata->pdata->desc, &config); | ||
| 167 | if (IS_ERR(regulator)) { | ||
| 168 | dev_err(&pdev->dev, "Failed to register regulator %s\n", | ||
| 169 | drvdata->pdata->desc->name); | ||
| 170 | return PTR_ERR(regulator); | ||
| 171 | } | ||
| 172 | |||
| 173 | return 0; | ||
| 174 | } | ||
| 175 | |||
| 176 | static struct platform_driver st_pwm_regulator_driver = { | ||
| 177 | .driver = { | ||
| 178 | .name = "st-pwm-regulator", | ||
| 179 | .owner = THIS_MODULE, | ||
| 180 | .of_match_table = of_match_ptr(st_pwm_of_match), | ||
| 181 | }, | ||
| 182 | .probe = st_pwm_regulator_probe, | ||
| 183 | }; | ||
| 184 | |||
| 185 | module_platform_driver(st_pwm_regulator_driver); | ||
| 186 | |||
| 187 | MODULE_LICENSE("GPL"); | ||
| 188 | MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org>"); | ||
| 189 | MODULE_DESCRIPTION("ST PWM Regulator Driver"); | ||
| 190 | MODULE_ALIAS("platform:st_pwm-regulator"); | ||
