aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm
diff options
context:
space:
mode:
authorPhilip, Avinash <avinashphilip@ti.com>2012-11-27 03:48:06 -0500
committerThierry Reding <thierry.reding@avionic-design.de>2012-11-28 09:14:41 -0500
commitaf0ba001d208e117b5f4e4f504672b42a664a7f7 (patch)
tree448f579454bea86b34d3e980c75668e13a43a8fd /drivers/pwm
parent83af24027b3df1af5c5a9aa9adcdcfeb3429d3be (diff)
pwm: Add TI PWM subsystem driver
In some platforms (like am33xx), PWM sub modules (ECAP, EHRPWM, EQEP) are integrated to PWM subsystem. These PWM submodules has resources shared and only one register bit-field is provided to control module/clock enable/disable, makes it difficult to handle common resources from independent PWMSS submodule drivers. So the solution here implemented in this patch is, to create driver for PWMSS and take the role of parent driver for PWM submodules. PWMSS parent driver enumerates all the child nodes under PWMSS module. Also symbol "pwmss_submodule_state_change" exported to enable clock gating for individual PWMSS submodules, and submodule drivers has to enable clock gating from their drivers. As this is only supported during DT boot, the parent/child relationship is created and populated in DT execution flow. The only required change is inside DTS file, making EHRPWM & ECAP as a child to PWMSS node. Signed-off-by: Philip, Avinash <avinashphilip@ti.com> Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
Diffstat (limited to 'drivers/pwm')
-rw-r--r--drivers/pwm/Kconfig11
-rw-r--r--drivers/pwm/Makefile1
-rw-r--r--drivers/pwm/pwm-tipwmss.c139
-rw-r--r--drivers/pwm/pwm-tipwmss.h39
4 files changed, 190 insertions, 0 deletions
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 6e556c7da81e..3dcb76d86a97 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -136,6 +136,7 @@ config PWM_TEGRA
136config PWM_TIECAP 136config PWM_TIECAP
137 tristate "ECAP PWM support" 137 tristate "ECAP PWM support"
138 depends on SOC_AM33XX 138 depends on SOC_AM33XX
139 select PWM_TIPWMSS
139 help 140 help
140 PWM driver support for the ECAP APWM controller found on AM33XX 141 PWM driver support for the ECAP APWM controller found on AM33XX
141 TI SOC 142 TI SOC
@@ -146,6 +147,7 @@ config PWM_TIECAP
146config PWM_TIEHRPWM 147config PWM_TIEHRPWM
147 tristate "EHRPWM PWM support" 148 tristate "EHRPWM PWM support"
148 depends on SOC_AM33XX 149 depends on SOC_AM33XX
150 select PWM_TIPWMSS
149 help 151 help
150 PWM driver support for the EHRPWM controller found on AM33XX 152 PWM driver support for the EHRPWM controller found on AM33XX
151 TI SOC 153 TI SOC
@@ -153,6 +155,15 @@ config PWM_TIEHRPWM
153 To compile this driver as a module, choose M here: the module 155 To compile this driver as a module, choose M here: the module
154 will be called pwm-tiehrpwm. 156 will be called pwm-tiehrpwm.
155 157
158config PWM_TIPWMSS
159 bool
160 depends on SOC_AM33XX && (PWM_TIEHRPWM || PWM_TIECAP)
161 help
162 PWM Subsystem driver support for AM33xx SOC.
163
164 PWM submodules require PWM config space access from submodule
165 drivers and require common parent driver support.
166
156config PWM_TWL6030 167config PWM_TWL6030
157 tristate "TWL6030 PWM support" 168 tristate "TWL6030 PWM support"
158 depends on TWL4030_CORE 169 depends on TWL4030_CORE
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 3b3f4c9aa4ef..4fb39f8b6ba9 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -12,5 +12,6 @@ obj-$(CONFIG_PWM_SPEAR) += pwm-spear.o
12obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o 12obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o
13obj-$(CONFIG_PWM_TIECAP) += pwm-tiecap.o 13obj-$(CONFIG_PWM_TIECAP) += pwm-tiecap.o
14obj-$(CONFIG_PWM_TIEHRPWM) += pwm-tiehrpwm.o 14obj-$(CONFIG_PWM_TIEHRPWM) += pwm-tiehrpwm.o
15obj-$(CONFIG_PWM_TIPWMSS) += pwm-tipwmss.o
15obj-$(CONFIG_PWM_TWL6030) += pwm-twl6030.o 16obj-$(CONFIG_PWM_TWL6030) += pwm-twl6030.o
16obj-$(CONFIG_PWM_VT8500) += pwm-vt8500.o 17obj-$(CONFIG_PWM_VT8500) += pwm-vt8500.o
diff --git a/drivers/pwm/pwm-tipwmss.c b/drivers/pwm/pwm-tipwmss.c
new file mode 100644
index 000000000000..3448a1c88590
--- /dev/null
+++ b/drivers/pwm/pwm-tipwmss.c
@@ -0,0 +1,139 @@
1/*
2 * TI PWM Subsystem driver
3 *
4 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <linux/module.h>
19#include <linux/platform_device.h>
20#include <linux/io.h>
21#include <linux/err.h>
22#include <linux/pm_runtime.h>
23#include <linux/of_device.h>
24
25#include "pwm-tipwmss.h"
26
27#define PWMSS_CLKCONFIG 0x8 /* Clock gating reg */
28#define PWMSS_CLKSTATUS 0xc /* Clock gating status reg */
29
30struct pwmss_info {
31 void __iomem *mmio_base;
32 struct mutex pwmss_lock;
33 u16 pwmss_clkconfig;
34};
35
36u16 pwmss_submodule_state_change(struct device *dev, int set)
37{
38 struct pwmss_info *info = dev_get_drvdata(dev);
39 u16 val;
40
41 mutex_lock(&info->pwmss_lock);
42 val = readw(info->mmio_base + PWMSS_CLKCONFIG);
43 val |= set;
44 writew(val , info->mmio_base + PWMSS_CLKCONFIG);
45 mutex_unlock(&info->pwmss_lock);
46
47 return readw(info->mmio_base + PWMSS_CLKSTATUS);
48}
49EXPORT_SYMBOL(pwmss_submodule_state_change);
50
51static const struct of_device_id pwmss_of_match[] = {
52 { .compatible = "ti,am33xx-pwmss" },
53 {},
54};
55MODULE_DEVICE_TABLE(of, pwmss_of_match);
56
57static int pwmss_probe(struct platform_device *pdev)
58{
59 int ret;
60 struct resource *r;
61 struct pwmss_info *info;
62 struct device_node *node = pdev->dev.of_node;
63
64 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
65 if (!info) {
66 dev_err(&pdev->dev, "failed to allocate memory\n");
67 return -ENOMEM;
68 }
69
70 mutex_init(&info->pwmss_lock);
71
72 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
73 if (!r) {
74 dev_err(&pdev->dev, "no memory resource defined\n");
75 return -ENODEV;
76 }
77
78 info->mmio_base = devm_request_and_ioremap(&pdev->dev, r);
79 if (!info->mmio_base)
80 return -EADDRNOTAVAIL;
81
82 pm_runtime_enable(&pdev->dev);
83 pm_runtime_get_sync(&pdev->dev);
84 platform_set_drvdata(pdev, info);
85
86 /* Populate all the child nodes here... */
87 ret = of_platform_populate(node, NULL, NULL, &pdev->dev);
88 if (ret)
89 dev_err(&pdev->dev, "no child node found\n");
90
91 return ret;
92}
93
94static int pwmss_remove(struct platform_device *pdev)
95{
96 struct pwmss_info *info = platform_get_drvdata(pdev);
97
98 pm_runtime_put_sync(&pdev->dev);
99 pm_runtime_disable(&pdev->dev);
100 mutex_destroy(&info->pwmss_lock);
101 return 0;
102}
103
104static int pwmss_suspend(struct device *dev)
105{
106 struct pwmss_info *info = dev_get_drvdata(dev);
107
108 info->pwmss_clkconfig = readw(info->mmio_base + PWMSS_CLKCONFIG);
109 pm_runtime_put_sync(dev);
110 return 0;
111}
112
113static int pwmss_resume(struct device *dev)
114{
115 struct pwmss_info *info = dev_get_drvdata(dev);
116
117 pm_runtime_get_sync(dev);
118 writew(info->pwmss_clkconfig, info->mmio_base + PWMSS_CLKCONFIG);
119 return 0;
120}
121
122static SIMPLE_DEV_PM_OPS(pwmss_pm_ops, pwmss_suspend, pwmss_resume);
123
124static struct platform_driver pwmss_driver = {
125 .driver = {
126 .name = "pwmss",
127 .owner = THIS_MODULE,
128 .pm = &pwmss_pm_ops,
129 .of_match_table = pwmss_of_match,
130 },
131 .probe = pwmss_probe,
132 .remove = pwmss_remove,
133};
134
135module_platform_driver(pwmss_driver);
136
137MODULE_DESCRIPTION("PWM Subsystem driver");
138MODULE_AUTHOR("Texas Instruments");
139MODULE_LICENSE("GPL");
diff --git a/drivers/pwm/pwm-tipwmss.h b/drivers/pwm/pwm-tipwmss.h
new file mode 100644
index 000000000000..11f76a1e266b
--- /dev/null
+++ b/drivers/pwm/pwm-tipwmss.h
@@ -0,0 +1,39 @@
1/*
2 * TI PWM Subsystem driver
3 *
4 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#ifndef __TIPWMSS_H
19#define __TIPWMSS_H
20
21#ifdef CONFIG_PWM_TIPWMSS
22/* PWM substem clock gating */
23#define PWMSS_ECAPCLK_EN BIT(0)
24#define PWMSS_ECAPCLK_STOP_REQ BIT(1)
25#define PWMSS_EPWMCLK_EN BIT(8)
26#define PWMSS_EPWMCLK_STOP_REQ BIT(9)
27
28#define PWMSS_ECAPCLK_EN_ACK BIT(0)
29#define PWMSS_EPWMCLK_EN_ACK BIT(8)
30
31extern u16 pwmss_submodule_state_change(struct device *dev, int set);
32#else
33static inline u16 pwmss_submodule_state_change(struct device *dev, int set)
34{
35 /* return success status value */
36 return 0xFFFF;
37}
38#endif
39#endif /* __TIPWMSS_H */