Required properties:
- compatible: should be "atmel,tcb-pwm"
-- #pwm-cells: Should be 3. The first cell specifies the per-chip index
- of the PWM to use, the second cell is the period in nanoseconds and
- bit 0 in the third cell is used to encode the polarity of PWM output.
- Set bit 0 of the third cell in PWM specifier to 1 for inverse polarity &
- set to 0 for normal polarity.
+- #pwm-cells: should be 3. See pwm.txt in this directory for a description of
+ the cells format. The only third cell flag supported by this binding is
+ PWM_POLARITY_INVERTED.
- tc-block: The Timer Counter block to use as a PWM chip.
Example:
Required properties:
- compatible: should be "fsl,<soc>-pwm"
- reg: physical base address and length of the controller's registers
-- #pwm-cells: should be 2. The first cell specifies the per-chip index
- of the PWM to use and the second cell is the period in nanoseconds.
+- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
+ the cells format.
- interrupts: The interrupt for the pwm controller
Example:
Required properties:
- compatible: should be "fsl,imx23-pwm"
- reg: physical base address and length of the controller's registers
-- #pwm-cells: should be 2. The first cell specifies the per-chip index
- of the PWM to use and the second cell is the period in nanoseconds.
+- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
+ the cells format.
- fsl,pwm-number: the number of PWM devices
Example:
- "nvidia,tegra20-pwm"
- "nvidia,tegra30-pwm"
- reg: physical base address and length of the controller's registers
-- #pwm-cells: On Tegra the number of cells used to specify a PWM is 2. The
- first cell specifies the per-chip index of the PWM to use and the second
- cell is the period in nanoseconds.
+- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
+ the cells format.
Example:
Required properties:
- compatible: "nxp,pca9685-pwm"
- - #pwm-cells: should be 2. The first cell specifies the per-chip index
- of the PWM to use and the second cell is the period in nanoseconds.
+ - #pwm-cells: Should be 2. See pwm.txt in this directory for a description of
+ the cells format.
The index 16 is the ALLCALL channel, that sets all PWM channels at the same
time.
- reg: base address and size of register area
- interrupts: list of timer interrupts (one interrupt per timer, starting at
timer 0)
-- #pwm-cells: number of cells used for PWM specifier - must be 3
- the specifier format is as follows:
- - phandle to PWM controller node
- - index of PWM channel (from 0 to 4)
- - PWM signal period in nanoseconds
- - bitmask of optional PWM flags:
- 0x1 - invert PWM signal
+- #pwm-cells: should be 3. See pwm.txt in this directory for a description of
+ the cells format. The only third cell flag supported by this binding is
+ PWM_POLARITY_INVERTED.
Optional properties:
- samsung,pwm-outputs: list of PWM channels used as PWM outputs on particular
- compatible: Must be "ti,<soc>-ecap".
for am33xx - compatible = "ti,am33xx-ecap";
for da850 - compatible = "ti,da850-ecap", "ti,am33xx-ecap";
-- #pwm-cells: Should be 3. Number of cells being used to specify PWM property.
- First cell specifies the per-chip index of the PWM to use, the second
- cell is the period in nanoseconds and bit 0 in the third cell is used to
- encode the polarity of PWM output. Set bit 0 of the third in PWM specifier
- to 1 for inverse polarity & set to 0 for normal polarity.
+- #pwm-cells: should be 3. See pwm.txt in this directory for a description of
+ the cells format. The PWM channel index ranges from 0 to 4. The only third
+ cell flag supported by this binding is PWM_POLARITY_INVERTED.
- reg: physical base address and size of the registers map.
Optional properties:
- compatible: Must be "ti,<soc>-ehrpwm".
for am33xx - compatible = "ti,am33xx-ehrpwm";
for da850 - compatible = "ti,da850-ehrpwm", "ti,am33xx-ehrpwm";
-- #pwm-cells: Should be 3. Number of cells being used to specify PWM property.
- First cell specifies the per-chip index of the PWM to use, the second
- cell is the period in nanoseconds and bit 0 in the third cell is used to
- encode the polarity of PWM output. Set bit 0 of the third in PWM specifier
- to 1 for inverse polarity & set to 0 for normal polarity.
+- #pwm-cells: should be 3. See pwm.txt in this directory for a description of
+ the cells format. The only third cell flag supported by this binding is
+ PWM_POLARITY_INVERTED.
- reg: physical base address and size of the registers map.
Optional properties:
pwm-specifier typically encodes the chip-relative PWM number and the PWM
period in nanoseconds.
-Optionally, the pwm-specifier can encode a number of flags in a third cell:
-- bit 0: PWM signal polarity (0: normal polarity, 1: inverse polarity)
+Optionally, the pwm-specifier can encode a number of flags (defined in
+<dt-bindings/pwm/pwm.h>) in a third cell:
+- PWM_POLARITY_INVERTED: invert the PWM signal polarity
Example with optional PWM specifier for inverse polarity
bl: backlight {
- pwms = <&pwm 0 5000000 1>;
+ pwms = <&pwm 0 5000000 PWM_POLARITY_INVERTED>;
pwm-names = "backlight";
};
--- /dev/null
+* Renesas R-Car Timer Pulse Unit PWM Controller
+
+Required Properties:
+
+ - compatible: should be one of the following.
+ - "renesas,tpu-r8a73a4": for R8A77A4 (R-Mobile APE6) compatible PWM controller.
+ - "renesas,tpu-r8a7740": for R8A7740 (R-Mobile A1) compatible PWM controller.
+ - "renesas,tpu-r8a7790": for R8A7790 (R-Car H2) compatible PWM controller.
+ - "renesas,tpu-sh7372": for SH7372 (SH-Mobile AP4) compatible PWM controller.
+ - "renesas,tpu": for generic R-Car TPU PWM controller.
+
+ - reg: Base address and length of each memory resource used by the PWM
+ controller hardware module.
+
+ - #pwm-cells: should be 3. See pwm.txt in this directory for a description of
+ the cells format. The only third cell flag supported by this binding is
+ PWM_POLARITY_INVERTED.
+
+Please refer to pwm.txt in this directory for details of the common PWM bindings
+used by client devices.
+
+Example: R8A7740 (R-Car A1) TPU controller node
+
+ tpu: pwm@e6600000 {
+ compatible = "renesas,tpu-r8a7740", "renesas,tpu";
+ reg = <0xe6600000 0x100>;
+ #pwm-cells = <3>;
+ };
- "st,spear320-pwm"
- "st,spear1340-pwm"
- reg: physical base address and length of the controller's registers
-- #pwm-cells: number of cells used to specify PWM which is fixed to 2 on
- SPEAr. The first cell specifies the per-chip index of the PWM to use and
- the second cell is the period in nanoseconds.
+- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
+ the cells format.
Example:
Required properties:
- compatible: "ti,twl4030-pwm" or "ti,twl6030-pwm"
-- #pwm-cells: should be 2. The first cell specifies the per-chip index
- of the PWM to use and the second cell is the period in nanoseconds.
+- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
+ the cells format.
Example:
Required properties:
- compatible: "ti,twl4030-pwmled" or "ti,twl6030-pwmled"
-- #pwm-cells: should be 2. The first cell specifies the per-chip index
- of the PWM to use and the second cell is the period in nanoseconds.
+- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
+ the cells format.
Example:
Required properties:
- compatible: should be "via,vt8500-pwm"
- reg: physical base address and length of the controller's registers
-- #pwm-cells: Should be 3. Number of cells being used to specify PWM property.
- First cell specifies the per-chip index of the PWM to use, the second
- cell is the period in nanoseconds and bit 0 in the third cell is used to
- encode the polarity of PWM output. Set bit 0 of the third in PWM specifier
- to 1 for inverse polarity & set to 0 for normal polarity.
+- #pwm-cells: should be 3. See pwm.txt in this directory for a description of
+ the cells format. The only third cell flag supported by this binding is
+ PWM_POLARITY_INVERTED.
- clocks: phandle to the PWM source clock
Example:
/dts-v1/;
#include "am33xx.dtsi"
+#include <dt-bindings/pwm/pwm.h>
/ {
model = "TI AM335x EVM-SK";
backlight {
compatible = "pwm-backlight";
- pwms = <&ecap2 0 50000 1>;
+ pwms = <&ecap2 0 50000 PWM_POLARITY_INVERTED>;
brightness-levels = <0 58 61 66 75 90 125 170 255>;
default-brightness-level = <8>;
};
/dts-v1/;
/include/ "wm8850.dtsi"
+#include <dt-bindings/pwm/pwm.h>
/ {
model = "Wondermedia WM8850-W70v2 Tablet";
backlight {
compatible = "pwm-backlight";
- pwms = <&pwm 0 50000 1>; /* duty inverted */
+ pwms = <&pwm 0 50000 PWM_POLARITY_INVERTED>;
brightness-levels = <0 40 60 80 100 130 190 255>;
default-brightness-level = <5>;
#include <linux/debugfs.h>
#include <linux/seq_file.h>
-#define MAX_PWMS 1024
+#include <dt-bindings/pwm/pwm.h>
-/* flags in the third cell of the DT PWM specifier */
-#define PWM_SPEC_POLARITY (1 << 0)
+#define MAX_PWMS 1024
static DEFINE_MUTEX(pwm_lookup_lock);
static LIST_HEAD(pwm_lookup_list);
pwm_set_period(pwm, args->args[1]);
- if (args->args[2] & PWM_SPEC_POLARITY)
+ if (args->args[2] & PWM_POLARITY_INVERTED)
pwm_set_polarity(pwm, PWM_POLARITY_INVERSED);
else
pwm_set_polarity(pwm, PWM_POLARITY_NORMAL);
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -EINVAL;
-
lpc32xx->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(lpc32xx->base))
return PTR_ERR(lpc32xx->base);
platform_set_drvdata(pdev, mxs);
- stmp_reset_block(mxs->base);
+ ret = stmp_reset_block(mxs->base);
+ if (ret)
+ goto pwm_remove;
return 0;
+
+pwm_remove:
+ pwmchip_remove(&mxs->chip);
+ return ret;
}
static int mxs_pwm_remove(struct platform_device *pdev)
.id_table = pwm_id_table,
};
-static int __init pwm_init(void)
-{
- return platform_driver_register(&pwm_driver);
-}
-arch_initcall(pwm_init);
-
-static void __exit pwm_exit(void)
-{
- platform_driver_unregister(&pwm_driver);
-}
-module_exit(pwm_exit);
+module_platform_driver(pwm_driver);
MODULE_LICENSE("GPL v2");
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/of.h>
#include <linux/platform_data/pwm-renesas-tpu.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
struct tpu_device {
struct platform_device *pdev;
- struct tpu_pwm_platform_data *pdata;
+ enum pwm_polarity polarities[TPU_CHANNEL_MAX];
struct pwm_chip chip;
spinlock_t lock;
pwm->tpu = tpu;
pwm->channel = _pwm->hwpwm;
- pwm->polarity = tpu->pdata ? tpu->pdata->channels[pwm->channel].polarity
- : PWM_POLARITY_NORMAL;
+ pwm->polarity = tpu->polarities[pwm->channel];
pwm->prescaler = 0;
pwm->period = 0;
pwm->duty = 0;
* Probe and remove
*/
+static void tpu_parse_pdata(struct tpu_device *tpu)
+{
+ struct tpu_pwm_platform_data *pdata = tpu->pdev->dev.platform_data;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(tpu->polarities); ++i)
+ tpu->polarities[i] = pdata ? pdata->channels[i].polarity
+ : PWM_POLARITY_NORMAL;
+}
+
static int tpu_probe(struct platform_device *pdev)
{
struct tpu_device *tpu;
return -ENOMEM;
}
- tpu->pdata = pdev->dev.platform_data;
+ spin_lock_init(&tpu->lock);
+ tpu->pdev = pdev;
+
+ /* Initialize device configuration from platform data. */
+ tpu_parse_pdata(tpu);
/* Map memory, get clock and pin control. */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "failed to get I/O memory\n");
- return -ENXIO;
- }
-
tpu->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(tpu->base))
return PTR_ERR(tpu->base);
/* Initialize and register the device. */
platform_set_drvdata(pdev, tpu);
- spin_lock_init(&tpu->lock);
- tpu->pdev = pdev;
-
tpu->chip.dev = &pdev->dev;
tpu->chip.ops = &tpu_pwm_ops;
+ tpu->chip.of_xlate = of_pwm_xlate_with_flags;
+ tpu->chip.of_pwm_n_cells = 3;
tpu->chip.base = -1;
tpu->chip.npwm = TPU_CHANNEL_MAX;
return 0;
}
+#ifdef CONFIG_OF
+static const struct of_device_id tpu_of_table[] = {
+ { .compatible = "renesas,tpu-r8a73a4", },
+ { .compatible = "renesas,tpu-r8a7740", },
+ { .compatible = "renesas,tpu-r8a7790", },
+ { .compatible = "renesas,tpu-sh7372", },
+ { .compatible = "renesas,tpu", },
+ { },
+};
+
+MODULE_DEVICE_TABLE(of, tpu_of_table);
+#endif
+
static struct platform_driver tpu_driver = {
.probe = tpu_probe,
.remove = tpu_remove,
.driver = {
.name = "renesas-tpu-pwm",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(tpu_of_table),
}
};
int ret;
u32 val;
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!r) {
- dev_err(&pdev->dev, "no memory resources defined\n");
- return -ENODEV;
- }
-
pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
if (!pc) {
dev_err(&pdev->dev, "failed to allocate memory\n");
return -ENOMEM;
}
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pc->mmio_base = devm_ioremap_resource(&pdev->dev, r);
if (IS_ERR(pc->mmio_base))
return PTR_ERR(pc->mmio_base);
return pwmchip_remove(&pc->chip);
}
+#ifdef CONFIG_PM_SLEEP
static void ecap_pwm_save_context(struct ecap_pwm_chip *pc)
{
pm_runtime_get_sync(pc->chip.dev);
writew(pc->ctx.ecctl2, pc->mmio_base + ECCTL2);
}
-#ifdef CONFIG_PM_SLEEP
static int ecap_pwm_suspend(struct device *dev)
{
struct ecap_pwm_chip *pc = dev_get_drvdata(dev);
return container_of(chip, struct ehrpwm_pwm_chip, chip);
}
-static u16 ehrpwm_read(void *base, int offset)
+static u16 ehrpwm_read(void __iomem *base, int offset)
{
return readw(base + offset);
}
-static void ehrpwm_write(void *base, int offset, unsigned int val)
+static void ehrpwm_write(void __iomem *base, int offset, unsigned int val)
{
writew(val & 0xFFFF, base + offset);
}
-static void ehrpwm_modify(void *base, int offset,
+static void ehrpwm_modify(void __iomem *base, int offset,
unsigned short mask, unsigned short val)
{
unsigned short regval;
return ret ? : len;
}
+static DEVICE_ATTR(export, 0200, NULL, pwm_export_store);
static ssize_t pwm_unexport_store(struct device *parent,
struct device_attribute *attr,
return ret ? : len;
}
+static DEVICE_ATTR(unexport, 0200, NULL, pwm_unexport_store);
-static ssize_t pwm_npwm_show(struct device *parent,
- struct device_attribute *attr,
- char *buf)
+static ssize_t npwm_show(struct device *parent, struct device_attribute *attr,
+ char *buf)
{
const struct pwm_chip *chip = dev_get_drvdata(parent);
return sprintf(buf, "%u\n", chip->npwm);
}
+static DEVICE_ATTR_RO(npwm);
-static struct device_attribute pwm_chip_attrs[] = {
- __ATTR(export, 0200, NULL, pwm_export_store),
- __ATTR(unexport, 0200, NULL, pwm_unexport_store),
- __ATTR(npwm, 0444, pwm_npwm_show, NULL),
- __ATTR_NULL,
+static struct attribute *pwm_chip_attrs[] = {
+ &dev_attr_export.attr,
+ &dev_attr_unexport.attr,
+ &dev_attr_npwm.attr,
+ NULL,
};
+ATTRIBUTE_GROUPS(pwm_chip);
static struct class pwm_class = {
.name = "pwm",
.owner = THIS_MODULE,
- .dev_attrs = pwm_chip_attrs,
+ .dev_groups = pwm_chip_groups,
};
static int pwmchip_sysfs_match(struct device *parent, const void *data)
--- /dev/null
+/*
+ * This header provides constants for most PWM bindings.
+ *
+ * Most PWM bindings can include a flags cell as part of the PWM specifier.
+ * In most cases, the format of the flags cell uses the standard values
+ * defined in this header.
+ */
+
+#ifndef _DT_BINDINGS_PWM_PWM_H
+#define _DT_BINDINGS_PWM_PWM_H
+
+#define PWM_POLARITY_INVERTED (1 << 0)
+
+#endif