Commit 7299ab70 authored by Thierry Reding's avatar Thierry Reding

pwm: Add device tree support

This patch adds helpers to support device tree bindings for the generic
PWM API. Device tree binding documentation for PWM controllers is also
provided.
Acked-by: default avatarArnd Bergmann <arnd@arndb.de>
Reviewed-by: default avatarShawn Guo <shawn.guo@linaro.org>
Signed-off-by: default avatarThierry Reding <thierry.reding@avionic-design.de>
parent e05e5070
Specifying PWM information for devices
======================================
1) PWM user nodes
-----------------
PWM users should specify a list of PWM devices that they want to use
with a property containing a 'pwm-list':
pwm-list ::= <single-pwm> [pwm-list]
single-pwm ::= <pwm-phandle> <pwm-specifier>
pwm-phandle : phandle to PWM controller node
pwm-specifier : array of #pwm-cells specifying the given PWM
(controller specific)
PWM properties should be named "pwms". The exact meaning of each pwms
property must be documented in the device tree binding for each device.
An optional property "pwm-names" may contain a list of strings to label
each of the PWM devices listed in the "pwms" property. If no "pwm-names"
property is given, the name of the user node will be used as fallback.
Drivers for devices that use more than a single PWM device can use the
"pwm-names" property to map the name of the PWM device requested by the
pwm_get() call to an index into the list given by the "pwms" property.
The following example could be used to describe a PWM-based backlight
device:
pwm: pwm {
#pwm-cells = <2>;
};
[...]
bl: backlight {
pwms = <&pwm 0 5000000>;
pwm-names = "backlight";
};
pwm-specifier typically encodes the chip-relative PWM number and the PWM
period in nanoseconds. Note that in the example above, specifying the
"pwm-names" is redundant because the name "backlight" would be used as
fallback anyway.
2) PWM controller nodes
-----------------------
PWM controller nodes must specify the number of cells used for the
specifier using the '#pwm-cells' property.
An example PWM controller might look like this:
pwm: pwm@7000a000 {
compatible = "nvidia,tegra20-pwm";
reg = <0x7000a000 0x100>;
#pwm-cells = <2>;
};
......@@ -129,6 +129,45 @@ static int pwm_device_request(struct pwm_device *pwm, const char *label)
return 0;
}
static struct pwm_device *of_pwm_simple_xlate(struct pwm_chip *pc,
const struct of_phandle_args *args)
{
struct pwm_device *pwm;
if (pc->of_pwm_n_cells < 2)
return ERR_PTR(-EINVAL);
if (args->args[0] >= pc->npwm)
return ERR_PTR(-EINVAL);
pwm = pwm_request_from_chip(pc, args->args[0], NULL);
if (IS_ERR(pwm))
return pwm;
pwm_set_period(pwm, args->args[1]);
return pwm;
}
void of_pwmchip_add(struct pwm_chip *chip)
{
if (!chip->dev || !chip->dev->of_node)
return;
if (!chip->of_xlate) {
chip->of_xlate = of_pwm_simple_xlate;
chip->of_pwm_n_cells = 2;
}
of_node_get(chip->dev->of_node);
}
void of_pwmchip_remove(struct pwm_chip *chip)
{
if (chip->dev && chip->dev->of_node)
of_node_put(chip->dev->of_node);
}
/**
* pwm_set_chip_data() - set private chip data for a PWM
* @pwm: PWM device
......@@ -201,6 +240,9 @@ int pwmchip_add(struct pwm_chip *chip)
ret = 0;
if (IS_ENABLED(CONFIG_OF))
of_pwmchip_add(chip);
out:
mutex_unlock(&pwm_lock);
return ret;
......@@ -231,6 +273,10 @@ int pwmchip_remove(struct pwm_chip *chip)
}
list_del_init(&chip->list);
if (IS_ENABLED(CONFIG_OF))
of_pwmchip_remove(chip);
free_pwms(chip);
out:
......@@ -356,6 +402,99 @@ void pwm_disable(struct pwm_device *pwm)
}
EXPORT_SYMBOL_GPL(pwm_disable);
static struct pwm_chip *of_node_to_pwmchip(struct device_node *np)
{
struct pwm_chip *chip;
mutex_lock(&pwm_lock);
list_for_each_entry(chip, &pwm_chips, list)
if (chip->dev && chip->dev->of_node == np) {
mutex_unlock(&pwm_lock);
return chip;
}
mutex_unlock(&pwm_lock);
return ERR_PTR(-EPROBE_DEFER);
}
/**
* of_pwm_request() - request a PWM via the PWM framework
* @np: device node to get the PWM from
* @con_id: consumer name
*
* Returns the PWM device parsed from the phandle and index specified in the
* "pwms" property of a device tree node or a negative error-code on failure.
* Values parsed from the device tree are stored in the returned PWM device
* object.
*
* If con_id is NULL, the first PWM device listed in the "pwms" property will
* be requested. Otherwise the "pwm-names" property is used to do a reverse
* lookup of the PWM index. This also means that the "pwm-names" property
* becomes mandatory for devices that look up the PWM device via the con_id
* parameter.
*/
static struct pwm_device *of_pwm_request(struct device_node *np,
const char *con_id)
{
struct pwm_device *pwm = NULL;
struct of_phandle_args args;
struct pwm_chip *pc;
int index = 0;
int err;
if (con_id) {
index = of_property_match_string(np, "pwm-names", con_id);
if (index < 0)
return ERR_PTR(index);
}
err = of_parse_phandle_with_args(np, "pwms", "#pwm-cells", index,
&args);
if (err) {
pr_debug("%s(): can't parse \"pwms\" property\n", __func__);
return ERR_PTR(err);
}
pc = of_node_to_pwmchip(args.np);
if (IS_ERR(pc)) {
pr_debug("%s(): PWM chip not found\n", __func__);
pwm = ERR_CAST(pc);
goto put;
}
if (args.args_count != pc->of_pwm_n_cells) {
pr_debug("%s: wrong #pwm-cells for %s\n", np->full_name,
args.np->full_name);
pwm = ERR_PTR(-EINVAL);
goto put;
}
pwm = pc->of_xlate(pc, &args);
if (IS_ERR(pwm))
goto put;
/*
* If a consumer name was not given, try to look it up from the
* "pwm-names" property if it exists. Otherwise use the name of
* the user device node.
*/
if (!con_id) {
err = of_property_read_string_index(np, "pwm-names", index,
&con_id);
if (err < 0)
con_id = np->name;
}
pwm->label = con_id;
put:
of_node_put(args.np);
return pwm;
}
/**
* pwm_add_table() - register PWM device consumers
* @table: array of consumers to register
......@@ -378,8 +517,9 @@ void __init pwm_add_table(struct pwm_lookup *table, size_t num)
* @dev: device for PWM consumer
* @con_id: consumer name
*
* Look up a PWM chip and a relative index via a table supplied by board setup
* code (see pwm_add_table()).
* Lookup is first attempted using DT. If the device was not instantiated from
* a device tree, a PWM chip and a relative index is looked up via a table
* supplied by board setup code (see pwm_add_table()).
*
* Once a PWM chip has been found the specified PWM device will be requested
* and is ready to be used.
......@@ -394,6 +534,10 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id)
unsigned int index;
unsigned int match;
/* look up via DT first */
if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node)
return of_pwm_request(dev->of_node, con_id);
/*
* We look up the provider in the static table typically provided by
* board setup code. We first try to lookup the consumer device by
......
#ifndef __LINUX_PWM_H
#define __LINUX_PWM_H
#include <linux/of.h>
struct pwm_device;
struct seq_file;
......@@ -105,6 +107,10 @@ struct pwm_chip {
unsigned int npwm;
struct pwm_device *pwms;
struct pwm_device * (*of_xlate)(struct pwm_chip *pc,
const struct of_phandle_args *args);
unsigned int of_pwm_n_cells;
};
int pwm_set_chip_data(struct pwm_device *pwm, void *data);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment