Release 4.7 drivers/regulator/pwm-regulator.c
/*
* Regulator driver for PWM Regulators
*
* Copyright (C) 2014 - STMicroelectronics Inc.
*
* Author: Lee Jones <lee.jones@linaro.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pwm.h>
struct pwm_regulator_data {
/* Shared */
struct pwm_device *pwm;
/* Voltage table */
struct pwm_voltages *duty_cycle_table;
/* regulator descriptor */
struct regulator_desc desc;
/* Regulator ops */
struct regulator_ops ops;
int state;
/* Continuous voltage */
int volt_uV;
};
struct pwm_voltages {
unsigned int uV;
unsigned int dutycycle;
};
/**
* Voltage table call-backs
*/
static int pwm_regulator_get_voltage_sel(struct regulator_dev *rdev)
{
struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
return drvdata->state;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
lee jones | lee jones | 24 | 92.31% | 2 | 66.67% |
chris zhong | chris zhong | 2 | 7.69% | 1 | 33.33% |
| Total | 26 | 100.00% | 3 | 100.00% |
static int pwm_regulator_set_voltage_sel(struct regulator_dev *rdev,
unsigned selector)
{
struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
struct pwm_args pargs;
int dutycycle;
int ret;
pwm_get_args(drvdata->pwm, &pargs);
dutycycle = (pargs.period *
drvdata->duty_cycle_table[selector].dutycycle) / 100;
ret = pwm_config(drvdata->pwm, dutycycle, pargs.period);
if (ret) {
dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret);
return ret;
}
drvdata->state = selector;
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
lee jones | lee jones | 80 | 74.07% | 2 | 40.00% |
boris brezillon | boris brezillon | 13 | 12.04% | 1 | 20.00% |
chris zhong | chris zhong | 12 | 11.11% | 1 | 20.00% |
laxman dewangan | laxman dewangan | 3 | 2.78% | 1 | 20.00% |
| Total | 108 | 100.00% | 5 | 100.00% |
static int pwm_regulator_list_voltage(struct regulator_dev *rdev,
unsigned selector)
{
struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
if (selector >= rdev->desc->n_voltages)
return -EINVAL;
return drvdata->duty_cycle_table[selector].uV;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
lee jones | lee jones | 46 | 95.83% | 3 | 75.00% |
chris zhong | chris zhong | 2 | 4.17% | 1 | 25.00% |
| Total | 48 | 100.00% | 4 | 100.00% |
static int pwm_regulator_enable(struct regulator_dev *dev)
{
struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev);
return pwm_enable(drvdata->pwm);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
boris brezillon | boris brezillon | 29 | 100.00% | 1 | 100.00% |
| Total | 29 | 100.00% | 1 | 100.00% |
static int pwm_regulator_disable(struct regulator_dev *dev)
{
struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev);
pwm_disable(drvdata->pwm);
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
boris brezillon | boris brezillon | 31 | 100.00% | 1 | 100.00% |
| Total | 31 | 100.00% | 1 | 100.00% |
static int pwm_regulator_is_enabled(struct regulator_dev *dev)
{
struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev);
return pwm_is_enabled(drvdata->pwm);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
boris brezillon | boris brezillon | 29 | 100.00% | 1 | 100.00% |
| Total | 29 | 100.00% | 1 | 100.00% |
static int pwm_regulator_get_voltage(struct regulator_dev *rdev)
{
struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
return drvdata->volt_uV;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
lee jones | lee jones | 26 | 100.00% | 1 | 100.00% |
| Total | 26 | 100.00% | 1 | 100.00% |
static int pwm_regulator_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV,
unsigned *selector)
{
struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
unsigned int ramp_delay = rdev->constraints->ramp_delay;
struct pwm_args pargs;
unsigned int req_diff = min_uV - rdev->constraints->min_uV;
unsigned int diff;
unsigned int duty_pulse;
u64 req_period;
u32 rem;
int ret;
pwm_get_args(drvdata->pwm, &pargs);
diff = rdev->constraints->max_uV - rdev->constraints->min_uV;
/* First try to find out if we get the iduty cycle time which is
* factor of PWM period time. If (request_diff_to_min * pwm_period)
* is perfect divided by voltage_range_diff then it is possible to
* get duty cycle time which is factor of PWM period. This will help
* to get output voltage nearer to requested value as there is no
* calculation loss.
*/
req_period = req_diff * pargs.period;
div_u64_rem(req_period, diff, &rem);
if (!rem) {
do_div(req_period, diff);
duty_pulse = (unsigned int)req_period;
} else {
duty_pulse = (pargs.period / 100) * ((req_diff * 100) / diff);
}
ret = pwm_config(drvdata->pwm, duty_pulse, pargs.period);
if (ret) {
dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret);
return ret;
}
ret = pwm_enable(drvdata->pwm);
if (ret) {
dev_err(&rdev->dev, "Failed to enable PWM: %d\n", ret);
return ret;
}
drvdata->volt_uV = min_uV;
/* Delay required by PWM regulator to settle to the new voltage */
usleep_range(ramp_delay, ramp_delay + 1000);
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
lee jones | lee jones | 128 | 51.82% | 2 | 33.33% |
laxman dewangan | laxman dewangan | 100 | 40.49% | 2 | 33.33% |
boris brezillon | boris brezillon | 17 | 6.88% | 1 | 16.67% |
mark brown | mark brown | 2 | 0.81% | 1 | 16.67% |
| Total | 247 | 100.00% | 6 | 100.00% |
static struct regulator_ops pwm_regulator_voltage_table_ops = {
.set_voltage_sel = pwm_regulator_set_voltage_sel,
.get_voltage_sel = pwm_regulator_get_voltage_sel,
.list_voltage = pwm_regulator_list_voltage,
.map_voltage = regulator_map_voltage_iterate,
.enable = pwm_regulator_enable,
.disable = pwm_regulator_disable,
.is_enabled = pwm_regulator_is_enabled,
};
static struct regulator_ops pwm_regulator_voltage_continuous_ops = {
.get_voltage = pwm_regulator_get_voltage,
.set_voltage = pwm_regulator_set_voltage,
.enable = pwm_regulator_enable,
.disable = pwm_regulator_disable,
.is_enabled = pwm_regulator_is_enabled,
};
static struct regulator_desc pwm_regulator_desc = {
.name = "pwm-regulator",
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.supply_name = "pwm",
};
static int pwm_regulator_init_table(struct platform_device *pdev,
struct pwm_regulator_data *drvdata)
{
struct device_node *np = pdev->dev.of_node;
struct pwm_voltages *duty_cycle_table;
unsigned int length = 0;
int ret;
of_find_property(np, "voltage-table", &length);
if ((length < sizeof(*duty_cycle_table)) ||
(length % sizeof(*duty_cycle_table))) {
dev_err(&pdev->dev, "voltage-table length(%d) is invalid\n",
length);
return -EINVAL;
}
duty_cycle_table = devm_kzalloc(&pdev->dev, length, GFP_KERNEL);
if (!duty_cycle_table)
return -ENOMEM;
ret = of_property_read_u32_array(np, "voltage-table",
(u32 *)duty_cycle_table,
length / sizeof(u32));
if (ret) {
dev_err(&pdev->dev, "Failed to read voltage-table: %d\n", ret);
return ret;
}
drvdata->duty_cycle_table = duty_cycle_table;
memcpy(&drvdata->ops, &pwm_regulator_voltage_table_ops,
sizeof(drvdata->ops));
drvdata->desc.ops = &drvdata->ops;
drvdata->desc.n_voltages = length / sizeof(*duty_cycle_table);
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
lee jones | lee jones | 149 | 71.29% | 4 | 57.14% |
laxman dewangan | laxman dewangan | 30 | 14.35% | 2 | 28.57% |
chris zhong | chris zhong | 30 | 14.35% | 1 | 14.29% |
| Total | 209 | 100.00% | 7 | 100.00% |
static int pwm_regulator_init_continuous(struct platform_device *pdev,
struct pwm_regulator_data *drvdata)
{
memcpy(&drvdata->ops, &pwm_regulator_voltage_continuous_ops,
sizeof(drvdata->ops));
drvdata->desc.ops = &drvdata->ops;
drvdata->desc.continuous_voltage_range = true;
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
lee jones | lee jones | 29 | 51.79% | 1 | 50.00% |
laxman dewangan | laxman dewangan | 27 | 48.21% | 1 | 50.00% |
| Total | 56 | 100.00% | 2 | 100.00% |
static int pwm_regulator_probe(struct platform_device *pdev)
{
const struct regulator_init_data *init_data;
struct pwm_regulator_data *drvdata;
struct regulator_dev *regulator;
struct regulator_config config = { };
struct device_node *np = pdev->dev.of_node;
int ret;
if (!np) {
dev_err(&pdev->dev, "Device Tree node missing\n");
return -EINVAL;
}
drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
memcpy(&drvdata->desc, &pwm_regulator_desc, sizeof(drvdata->desc));
if (of_find_property(np, "voltage-table", NULL))
ret = pwm_regulator_init_table(pdev, drvdata);
else
ret = pwm_regulator_init_continuous(pdev, drvdata);
if (ret)
return ret;
init_data = of_get_regulator_init_data(&pdev->dev, np,
&drvdata->desc);
if (!init_data)
return -ENOMEM;
config.of_node = np;
config.dev = &pdev->dev;
config.driver_data = drvdata;
config.init_data = init_data;
drvdata->pwm = devm_pwm_get(&pdev->dev, NULL);
if (IS_ERR(drvdata->pwm)) {
ret = PTR_ERR(drvdata->pwm);
dev_err(&pdev->dev, "Failed to get PWM: %d\n", ret);
return ret;
}
/*
* FIXME: pwm_apply_args() should be removed when switching to the
* atomic PWM API.
*/
pwm_apply_args(drvdata->pwm);
regulator = devm_regulator_register(&pdev->dev,
&drvdata->desc, &config);
if (IS_ERR(regulator)) {
ret = PTR_ERR(regulator);
dev_err(&pdev->dev, "Failed to register regulator %s: %d\n",
drvdata->desc.name, ret);
return ret;
}
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
lee jones | lee jones | 220 | 69.18% | 4 | 44.44% |
laxman dewangan | laxman dewangan | 51 | 16.04% | 2 | 22.22% |
chris zhong | chris zhong | 37 | 11.64% | 1 | 11.11% |
boris brezillon | boris brezillon | 8 | 2.52% | 1 | 11.11% |
javier martinez canillas | javier martinez canillas | 2 | 0.63% | 1 | 11.11% |
| Total | 318 | 100.00% | 9 | 100.00% |
static const struct of_device_id pwm_of_match[] = {
{ .compatible = "pwm-regulator" },
{ },
};
MODULE_DEVICE_TABLE(of, pwm_of_match);
static struct platform_driver pwm_regulator_driver = {
.driver = {
.name = "pwm-regulator",
.of_match_table = of_match_ptr(pwm_of_match),
},
.probe = pwm_regulator_probe,
};
module_platform_driver(pwm_regulator_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org>");
MODULE_DESCRIPTION("PWM Regulator Driver");
MODULE_ALIAS("platform:pwm-regulator");
Overall Contributors
| Person | Tokens | Prop | Commits | CommitProp |
lee jones | lee jones | 881 | 63.52% | 9 | 50.00% |
laxman dewangan | laxman dewangan | 221 | 15.93% | 3 | 16.67% |
boris brezillon | boris brezillon | 157 | 11.32% | 2 | 11.11% |
chris zhong | chris zhong | 123 | 8.87% | 1 | 5.56% |
mark brown | mark brown | 2 | 0.14% | 1 | 5.56% |
javier martinez canillas | javier martinez canillas | 2 | 0.14% | 1 | 5.56% |
axel lin | axel lin | 1 | 0.07% | 1 | 5.56% |
| Total | 1387 | 100.00% | 18 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.