aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-10 07:15:24 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-10 07:15:24 -0400
commit2474542f64432398f503373f53bdf620491bcfa8 (patch)
tree3c9744b138c2158757530814b35c23eed31cf6ce
parentc7a6ced9d8e8411bdafe83998474d185a79badc3 (diff)
parent85f8879ca4f3d26a7f473522101fb74a79bda3f2 (diff)
Merge tag 'for-3.7-rc1' of git://gitorious.org/linux-pwm/linux-pwm
Pull pwm changes from Thierry Reding: "All legacy PWM providers have now been moved to the PWM subsystem. The plan for 3.8 is to adapt all board files to provide a lookup table for PWM devices in order to get rid of the global namespace. Subsequently, users of the legacy pwm_request() and pwm_free() functions can be migrated to the new pwm_get() and pwm_put() functions. Once this has been completed, the legacy API and the compatibility code in the core can be removed. In addition to the above, these changes also add support for configuring the polarity of a PWM signal (currently only supported on ECAP and EHRPWM) and include a much needed rework of the i.MX driver. Managed functions to obtain and release a PWM device (devm_pwm_get() and devm_pwm_put()) have been added and the pwm-backlight driver has been updated to use them. If the PWM subsystem hasn't been enabled, dummy functions are provided that allow the subsystem to safely compile out. Some common checks on input parameters have been moved to the core and removed from the drivers. Finally, a small fix corrects the description of the PWM specifier's second cell in the device tree representation." * tag 'for-3.7-rc1' of git://gitorious.org/linux-pwm/linux-pwm: (23 commits) pwm: dt: Fix description of second PWM cell pwm: Check for negative duty-cycle and period pwm: Add Ingenic JZ4740 support MIPS: JZ4740: Export timer API pwm: Move PUV3 PWM driver to PWM framework unicore32: pwm: Use managed resource allocations unicore32: pwm: Remove unnecessary indirection unicore32: pwm: Use module_platform_driver() unicore32: pwm: Properly remap memory-mapped registers pwm-backlight: Use devm_pwm_get() instead of pwm_get() pwm: Move AB8500 PWM driver to PWM framework pwm: Fix compilation error when CONFIG_PWM is not defined pwm: i.MX: fix clock lookup pwm: i.MX: use per clock unconditionally pwm: i.MX: add devicetree support pwm: i.MX: Use module_platform_driver pwm: i.MX: add functions to enable/disable pwm. pwm: i.MX: remove unnecessary if in pwm_[en|dis]able pwm: i.MX: factor out SoC specific functions pwm: pwm-tiehrpwm: Add support for configuring polarity of PWM ...
-rw-r--r--Documentation/devicetree/bindings/pwm/imx-pwm.txt17
-rw-r--r--Documentation/devicetree/bindings/pwm/mxs-pwm.txt2
-rw-r--r--Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt2
-rw-r--r--Documentation/driver-model/devres.txt4
-rw-r--r--Documentation/pwm.txt3
-rw-r--r--arch/mips/include/asm/mach-jz4740/platform.h1
-rw-r--r--arch/mips/include/asm/mach-jz4740/timer.h113
-rw-r--r--arch/mips/jz4740/Kconfig3
-rw-r--r--arch/mips/jz4740/Makefile2
-rw-r--r--arch/mips/jz4740/board-qi_lb60.c1
-rw-r--r--arch/mips/jz4740/platform.c6
-rw-r--r--arch/mips/jz4740/pwm.c177
-rw-r--r--arch/mips/jz4740/time.c2
-rw-r--r--arch/mips/jz4740/timer.c4
-rw-r--r--arch/mips/jz4740/timer.h136
-rw-r--r--arch/unicore32/Kconfig12
-rw-r--r--arch/unicore32/include/mach/regs-ost.h18
-rw-r--r--arch/unicore32/kernel/Makefile1
-rw-r--r--arch/unicore32/kernel/pwm.c263
-rw-r--r--drivers/misc/Kconfig10
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/pwm/Kconfig29
-rw-r--r--drivers/pwm/Makefile3
-rw-r--r--drivers/pwm/core.c82
-rw-r--r--drivers/pwm/pwm-ab8500.c (renamed from drivers/misc/ab8500-pwm.c)116
-rw-r--r--drivers/pwm/pwm-bfin.c3
-rw-r--r--drivers/pwm/pwm-imx.c278
-rw-r--r--drivers/pwm/pwm-jz4740.c221
-rw-r--r--drivers/pwm/pwm-puv3.c161
-rw-r--r--drivers/pwm/pwm-pxa.c3
-rw-r--r--drivers/pwm/pwm-samsung.c3
-rw-r--r--drivers/pwm/pwm-tiecap.c24
-rw-r--r--drivers/pwm/pwm-tiehrpwm.c75
-rw-r--r--drivers/video/backlight/pwm_bl.c7
-rw-r--r--include/linux/pwm.h108
35 files changed, 1069 insertions, 822 deletions
diff --git a/Documentation/devicetree/bindings/pwm/imx-pwm.txt b/Documentation/devicetree/bindings/pwm/imx-pwm.txt
new file mode 100644
index 000000000000..8522bfbccfd7
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/imx-pwm.txt
@@ -0,0 +1,17 @@
1Freescale i.MX PWM controller
2
3Required properties:
4- compatible: should be "fsl,<soc>-pwm"
5- reg: physical base address and length of the controller's registers
6- #pwm-cells: should be 2. The first cell specifies the per-chip index
7 of the PWM to use and the second cell is the period in nanoseconds.
8- interrupts: The interrupt for the pwm controller
9
10Example:
11
12pwm1: pwm@53fb4000 {
13 #pwm-cells = <2>;
14 compatible = "fsl,imx53-pwm", "fsl,imx27-pwm";
15 reg = <0x53fb4000 0x4000>;
16 interrupts = <61>;
17};
diff --git a/Documentation/devicetree/bindings/pwm/mxs-pwm.txt b/Documentation/devicetree/bindings/pwm/mxs-pwm.txt
index 11963e4d6bc4..9e3f8f1d46a2 100644
--- a/Documentation/devicetree/bindings/pwm/mxs-pwm.txt
+++ b/Documentation/devicetree/bindings/pwm/mxs-pwm.txt
@@ -4,7 +4,7 @@ Required properties:
4- compatible: should be "fsl,imx23-pwm" 4- compatible: should be "fsl,imx23-pwm"
5- reg: physical base address and length of the controller's registers 5- reg: physical base address and length of the controller's registers
6- #pwm-cells: should be 2. The first cell specifies the per-chip index 6- #pwm-cells: should be 2. The first cell specifies the per-chip index
7 of the PWM to use and the second cell is the duty cycle in nanoseconds. 7 of the PWM to use and the second cell is the period in nanoseconds.
8- fsl,pwm-number: the number of PWM devices 8- fsl,pwm-number: the number of PWM devices
9 9
10Example: 10Example:
diff --git a/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt b/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt
index bbbeedb4ec05..01438ecd6628 100644
--- a/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt
+++ b/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt
@@ -7,7 +7,7 @@ Required properties:
7- reg: physical base address and length of the controller's registers 7- reg: physical base address and length of the controller's registers
8- #pwm-cells: On Tegra the number of cells used to specify a PWM is 2. The 8- #pwm-cells: On Tegra the number of cells used to specify a PWM is 2. The
9 first cell specifies the per-chip index of the PWM to use and the second 9 first cell specifies the per-chip index of the PWM to use and the second
10 cell is the duty cycle in nanoseconds. 10 cell is the period in nanoseconds.
11 11
12Example: 12Example:
13 13
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 950856bd2e39..43cff70465ab 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -284,3 +284,7 @@ CLOCK
284PINCTRL 284PINCTRL
285 devm_pinctrl_get() 285 devm_pinctrl_get()
286 devm_pinctrl_put() 286 devm_pinctrl_put()
287
288PWM
289 devm_pwm_get()
290 devm_pwm_put()
diff --git a/Documentation/pwm.txt b/Documentation/pwm.txt
index 554290ebab94..7d2b4c9b544b 100644
--- a/Documentation/pwm.txt
+++ b/Documentation/pwm.txt
@@ -36,7 +36,8 @@ Legacy users can request a PWM device using pwm_request() and free it
36after usage with pwm_free(). 36after usage with pwm_free().
37 37
38New users should use the pwm_get() function and pass to it the consumer 38New users should use the pwm_get() function and pass to it the consumer
39device or a consumer name. pwm_put() is used to free the PWM device. 39device or a consumer name. pwm_put() is used to free the PWM device. Managed
40variants of these functions, devm_pwm_get() and devm_pwm_put(), also exist.
40 41
41After being requested a PWM has to be configured using: 42After being requested a PWM has to be configured using:
42 43
diff --git a/arch/mips/include/asm/mach-jz4740/platform.h b/arch/mips/include/asm/mach-jz4740/platform.h
index 564ab81d6cdc..163e81db880d 100644
--- a/arch/mips/include/asm/mach-jz4740/platform.h
+++ b/arch/mips/include/asm/mach-jz4740/platform.h
@@ -31,6 +31,7 @@ extern struct platform_device jz4740_pcm_device;
31extern struct platform_device jz4740_codec_device; 31extern struct platform_device jz4740_codec_device;
32extern struct platform_device jz4740_adc_device; 32extern struct platform_device jz4740_adc_device;
33extern struct platform_device jz4740_wdt_device; 33extern struct platform_device jz4740_wdt_device;
34extern struct platform_device jz4740_pwm_device;
34 35
35void jz4740_serial_device_register(void); 36void jz4740_serial_device_register(void);
36 37
diff --git a/arch/mips/include/asm/mach-jz4740/timer.h b/arch/mips/include/asm/mach-jz4740/timer.h
index 9baa03ce748c..a7759fb1f73d 100644
--- a/arch/mips/include/asm/mach-jz4740/timer.h
+++ b/arch/mips/include/asm/mach-jz4740/timer.h
@@ -16,7 +16,120 @@
16#ifndef __ASM_MACH_JZ4740_TIMER 16#ifndef __ASM_MACH_JZ4740_TIMER
17#define __ASM_MACH_JZ4740_TIMER 17#define __ASM_MACH_JZ4740_TIMER
18 18
19#define JZ_REG_TIMER_STOP 0x0C
20#define JZ_REG_TIMER_STOP_SET 0x1C
21#define JZ_REG_TIMER_STOP_CLEAR 0x2C
22#define JZ_REG_TIMER_ENABLE 0x00
23#define JZ_REG_TIMER_ENABLE_SET 0x04
24#define JZ_REG_TIMER_ENABLE_CLEAR 0x08
25#define JZ_REG_TIMER_FLAG 0x10
26#define JZ_REG_TIMER_FLAG_SET 0x14
27#define JZ_REG_TIMER_FLAG_CLEAR 0x18
28#define JZ_REG_TIMER_MASK 0x20
29#define JZ_REG_TIMER_MASK_SET 0x24
30#define JZ_REG_TIMER_MASK_CLEAR 0x28
31
32#define JZ_REG_TIMER_DFR(x) (((x) * 0x10) + 0x30)
33#define JZ_REG_TIMER_DHR(x) (((x) * 0x10) + 0x34)
34#define JZ_REG_TIMER_CNT(x) (((x) * 0x10) + 0x38)
35#define JZ_REG_TIMER_CTRL(x) (((x) * 0x10) + 0x3C)
36
37#define JZ_TIMER_IRQ_HALF(x) BIT((x) + 0x10)
38#define JZ_TIMER_IRQ_FULL(x) BIT(x)
39
40#define JZ_TIMER_CTRL_PWM_ABBRUPT_SHUTDOWN BIT(9)
41#define JZ_TIMER_CTRL_PWM_ACTIVE_LOW BIT(8)
42#define JZ_TIMER_CTRL_PWM_ENABLE BIT(7)
43#define JZ_TIMER_CTRL_PRESCALE_MASK 0x1c
44#define JZ_TIMER_CTRL_PRESCALE_OFFSET 0x3
45#define JZ_TIMER_CTRL_PRESCALE_1 (0 << 3)
46#define JZ_TIMER_CTRL_PRESCALE_4 (1 << 3)
47#define JZ_TIMER_CTRL_PRESCALE_16 (2 << 3)
48#define JZ_TIMER_CTRL_PRESCALE_64 (3 << 3)
49#define JZ_TIMER_CTRL_PRESCALE_256 (4 << 3)
50#define JZ_TIMER_CTRL_PRESCALE_1024 (5 << 3)
51
52#define JZ_TIMER_CTRL_PRESCALER(x) ((x) << JZ_TIMER_CTRL_PRESCALE_OFFSET)
53
54#define JZ_TIMER_CTRL_SRC_EXT BIT(2)
55#define JZ_TIMER_CTRL_SRC_RTC BIT(1)
56#define JZ_TIMER_CTRL_SRC_PCLK BIT(0)
57
58extern void __iomem *jz4740_timer_base;
59void __init jz4740_timer_init(void);
60
19void jz4740_timer_enable_watchdog(void); 61void jz4740_timer_enable_watchdog(void);
20void jz4740_timer_disable_watchdog(void); 62void jz4740_timer_disable_watchdog(void);
21 63
64static inline void jz4740_timer_stop(unsigned int timer)
65{
66 writel(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_STOP_SET);
67}
68
69static inline void jz4740_timer_start(unsigned int timer)
70{
71 writel(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_STOP_CLEAR);
72}
73
74static inline bool jz4740_timer_is_enabled(unsigned int timer)
75{
76 return readb(jz4740_timer_base + JZ_REG_TIMER_ENABLE) & BIT(timer);
77}
78
79static inline void jz4740_timer_enable(unsigned int timer)
80{
81 writeb(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_ENABLE_SET);
82}
83
84static inline void jz4740_timer_disable(unsigned int timer)
85{
86 writeb(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_ENABLE_CLEAR);
87}
88
89static inline void jz4740_timer_set_period(unsigned int timer, uint16_t period)
90{
91 writew(period, jz4740_timer_base + JZ_REG_TIMER_DFR(timer));
92}
93
94static inline void jz4740_timer_set_duty(unsigned int timer, uint16_t duty)
95{
96 writew(duty, jz4740_timer_base + JZ_REG_TIMER_DHR(timer));
97}
98
99static inline void jz4740_timer_set_count(unsigned int timer, uint16_t count)
100{
101 writew(count, jz4740_timer_base + JZ_REG_TIMER_CNT(timer));
102}
103
104static inline uint16_t jz4740_timer_get_count(unsigned int timer)
105{
106 return readw(jz4740_timer_base + JZ_REG_TIMER_CNT(timer));
107}
108
109static inline void jz4740_timer_ack_full(unsigned int timer)
110{
111 writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_FLAG_CLEAR);
112}
113
114static inline void jz4740_timer_irq_full_enable(unsigned int timer)
115{
116 writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_FLAG_CLEAR);
117 writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_MASK_CLEAR);
118}
119
120static inline void jz4740_timer_irq_full_disable(unsigned int timer)
121{
122 writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_MASK_SET);
123}
124
125static inline void jz4740_timer_set_ctrl(unsigned int timer, uint16_t ctrl)
126{
127 writew(ctrl, jz4740_timer_base + JZ_REG_TIMER_CTRL(timer));
128}
129
130static inline uint16_t jz4740_timer_get_ctrl(unsigned int timer)
131{
132 return readw(jz4740_timer_base + JZ_REG_TIMER_CTRL(timer));
133}
134
22#endif 135#endif
diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig
index 3e7141f0746c..468903053883 100644
--- a/arch/mips/jz4740/Kconfig
+++ b/arch/mips/jz4740/Kconfig
@@ -7,6 +7,3 @@ config JZ4740_QI_LB60
7 bool "Qi Hardware Ben NanoNote" 7 bool "Qi Hardware Ben NanoNote"
8 8
9endchoice 9endchoice
10
11config HAVE_PWM
12 bool
diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
index e44abea9c209..63bad0e491d0 100644
--- a/arch/mips/jz4740/Makefile
+++ b/arch/mips/jz4740/Makefile
@@ -5,7 +5,7 @@
5# Object file lists. 5# Object file lists.
6 6
7obj-y += prom.o irq.o time.o reset.o setup.o dma.o \ 7obj-y += prom.o irq.o time.o reset.o setup.o dma.o \
8 gpio.o clock.o platform.o timer.o pwm.o serial.o 8 gpio.o clock.o platform.o timer.o serial.o
9 9
10obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o 10obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o
11 11
diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c
index 9a3d9de4d04e..43d964d36288 100644
--- a/arch/mips/jz4740/board-qi_lb60.c
+++ b/arch/mips/jz4740/board-qi_lb60.c
@@ -437,6 +437,7 @@ static struct platform_device *jz_platform_devices[] __initdata = {
437 &jz4740_codec_device, 437 &jz4740_codec_device,
438 &jz4740_rtc_device, 438 &jz4740_rtc_device,
439 &jz4740_adc_device, 439 &jz4740_adc_device,
440 &jz4740_pwm_device,
440 &qi_lb60_gpio_keys, 441 &qi_lb60_gpio_keys,
441 &qi_lb60_pwm_beeper, 442 &qi_lb60_pwm_beeper,
442 &qi_lb60_charger_device, 443 &qi_lb60_charger_device,
diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c
index e342ed4cbd43..6d14dcdbd908 100644
--- a/arch/mips/jz4740/platform.c
+++ b/arch/mips/jz4740/platform.c
@@ -323,3 +323,9 @@ struct platform_device jz4740_wdt_device = {
323 .num_resources = ARRAY_SIZE(jz4740_wdt_resources), 323 .num_resources = ARRAY_SIZE(jz4740_wdt_resources),
324 .resource = jz4740_wdt_resources, 324 .resource = jz4740_wdt_resources,
325}; 325};
326
327/* PWM */
328struct platform_device jz4740_pwm_device = {
329 .name = "jz4740-pwm",
330 .id = -1,
331};
diff --git a/arch/mips/jz4740/pwm.c b/arch/mips/jz4740/pwm.c
deleted file mode 100644
index a26a6faec9a6..000000000000
--- a/arch/mips/jz4740/pwm.c
+++ /dev/null
@@ -1,177 +0,0 @@
1/*
2 * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
3 * JZ4740 platform PWM support
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * You should have received a copy of the GNU General Public License along
11 * with this program; if not, write to the Free Software Foundation, Inc.,
12 * 675 Mass Ave, Cambridge, MA 02139, USA.
13 *
14 */
15
16#include <linux/kernel.h>
17
18#include <linux/clk.h>
19#include <linux/err.h>
20#include <linux/pwm.h>
21#include <linux/gpio.h>
22
23#include <asm/mach-jz4740/gpio.h>
24#include "timer.h"
25
26static struct clk *jz4740_pwm_clk;
27
28DEFINE_MUTEX(jz4740_pwm_mutex);
29
30struct pwm_device {
31 unsigned int id;
32 unsigned int gpio;
33 bool used;
34};
35
36static struct pwm_device jz4740_pwm_list[] = {
37 { 2, JZ_GPIO_PWM2, false },
38 { 3, JZ_GPIO_PWM3, false },
39 { 4, JZ_GPIO_PWM4, false },
40 { 5, JZ_GPIO_PWM5, false },
41 { 6, JZ_GPIO_PWM6, false },
42 { 7, JZ_GPIO_PWM7, false },
43};
44
45struct pwm_device *pwm_request(int id, const char *label)
46{
47 int ret = 0;
48 struct pwm_device *pwm;
49
50 if (id < 2 || id > 7 || !jz4740_pwm_clk)
51 return ERR_PTR(-ENODEV);
52
53 mutex_lock(&jz4740_pwm_mutex);
54
55 pwm = &jz4740_pwm_list[id - 2];
56 if (pwm->used)
57 ret = -EBUSY;
58 else
59 pwm->used = true;
60
61 mutex_unlock(&jz4740_pwm_mutex);
62
63 if (ret)
64 return ERR_PTR(ret);
65
66 ret = gpio_request(pwm->gpio, label);
67
68 if (ret) {
69 printk(KERN_ERR "Failed to request pwm gpio: %d\n", ret);
70 pwm->used = false;
71 return ERR_PTR(ret);
72 }
73
74 jz_gpio_set_function(pwm->gpio, JZ_GPIO_FUNC_PWM);
75
76 jz4740_timer_start(id);
77
78 return pwm;
79}
80
81void pwm_free(struct pwm_device *pwm)
82{
83 pwm_disable(pwm);
84 jz4740_timer_set_ctrl(pwm->id, 0);
85
86 jz_gpio_set_function(pwm->gpio, JZ_GPIO_FUNC_NONE);
87 gpio_free(pwm->gpio);
88
89 jz4740_timer_stop(pwm->id);
90
91 pwm->used = false;
92}
93
94int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
95{
96 unsigned long long tmp;
97 unsigned long period, duty;
98 unsigned int prescaler = 0;
99 unsigned int id = pwm->id;
100 uint16_t ctrl;
101 bool is_enabled;
102
103 if (duty_ns < 0 || duty_ns > period_ns)
104 return -EINVAL;
105
106 tmp = (unsigned long long)clk_get_rate(jz4740_pwm_clk) * period_ns;
107 do_div(tmp, 1000000000);
108 period = tmp;
109
110 while (period > 0xffff && prescaler < 6) {
111 period >>= 2;
112 ++prescaler;
113 }
114
115 if (prescaler == 6)
116 return -EINVAL;
117
118 tmp = (unsigned long long)period * duty_ns;
119 do_div(tmp, period_ns);
120 duty = period - tmp;
121
122 if (duty >= period)
123 duty = period - 1;
124
125 is_enabled = jz4740_timer_is_enabled(id);
126 if (is_enabled)
127 pwm_disable(pwm);
128
129 jz4740_timer_set_count(id, 0);
130 jz4740_timer_set_duty(id, duty);
131 jz4740_timer_set_period(id, period);
132
133 ctrl = JZ_TIMER_CTRL_PRESCALER(prescaler) | JZ_TIMER_CTRL_SRC_EXT |
134 JZ_TIMER_CTRL_PWM_ABBRUPT_SHUTDOWN;
135
136 jz4740_timer_set_ctrl(id, ctrl);
137
138 if (is_enabled)
139 pwm_enable(pwm);
140
141 return 0;
142}
143
144int pwm_enable(struct pwm_device *pwm)
145{
146 uint32_t ctrl = jz4740_timer_get_ctrl(pwm->id);
147
148 ctrl |= JZ_TIMER_CTRL_PWM_ENABLE;
149 jz4740_timer_set_ctrl(pwm->id, ctrl);
150 jz4740_timer_enable(pwm->id);
151
152 return 0;
153}
154
155void pwm_disable(struct pwm_device *pwm)
156{
157 uint32_t ctrl = jz4740_timer_get_ctrl(pwm->id);
158
159 ctrl &= ~JZ_TIMER_CTRL_PWM_ENABLE;
160 jz4740_timer_disable(pwm->id);
161 jz4740_timer_set_ctrl(pwm->id, ctrl);
162}
163
164static int __init jz4740_pwm_init(void)
165{
166 int ret = 0;
167
168 jz4740_pwm_clk = clk_get(NULL, "ext");
169
170 if (IS_ERR(jz4740_pwm_clk)) {
171 ret = PTR_ERR(jz4740_pwm_clk);
172 jz4740_pwm_clk = NULL;
173 }
174
175 return ret;
176}
177subsys_initcall(jz4740_pwm_init);
diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c
index f83c2dd07a27..39bb4bbf43e7 100644
--- a/arch/mips/jz4740/time.c
+++ b/arch/mips/jz4740/time.c
@@ -20,10 +20,10 @@
20#include <linux/clockchips.h> 20#include <linux/clockchips.h>
21 21
22#include <asm/mach-jz4740/irq.h> 22#include <asm/mach-jz4740/irq.h>
23#include <asm/mach-jz4740/timer.h>
23#include <asm/time.h> 24#include <asm/time.h>
24 25
25#include "clock.h" 26#include "clock.h"
26#include "timer.h"
27 27
28#define TIMER_CLOCKEVENT 0 28#define TIMER_CLOCKEVENT 0
29#define TIMER_CLOCKSOURCE 1 29#define TIMER_CLOCKSOURCE 1
diff --git a/arch/mips/jz4740/timer.c b/arch/mips/jz4740/timer.c
index 654d5c3900b6..22f11d73a17d 100644
--- a/arch/mips/jz4740/timer.c
+++ b/arch/mips/jz4740/timer.c
@@ -17,11 +17,11 @@
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/module.h> 18#include <linux/module.h>
19 19
20#include "timer.h"
21
22#include <asm/mach-jz4740/base.h> 20#include <asm/mach-jz4740/base.h>
21#include <asm/mach-jz4740/timer.h>
23 22
24void __iomem *jz4740_timer_base; 23void __iomem *jz4740_timer_base;
24EXPORT_SYMBOL_GPL(jz4740_timer_base);
25 25
26void jz4740_timer_enable_watchdog(void) 26void jz4740_timer_enable_watchdog(void)
27{ 27{
diff --git a/arch/mips/jz4740/timer.h b/arch/mips/jz4740/timer.h
deleted file mode 100644
index fca3994f2e6d..000000000000
--- a/arch/mips/jz4740/timer.h
+++ /dev/null
@@ -1,136 +0,0 @@
1/*
2 * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
3 * JZ4740 platform timer support
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * You should have received a copy of the GNU General Public License along
11 * with this program; if not, write to the Free Software Foundation, Inc.,
12 * 675 Mass Ave, Cambridge, MA 02139, USA.
13 *
14 */
15
16#ifndef __MIPS_JZ4740_TIMER_H__
17#define __MIPS_JZ4740_TIMER_H__
18
19#include <linux/module.h>
20#include <linux/io.h>
21
22#define JZ_REG_TIMER_STOP 0x0C
23#define JZ_REG_TIMER_STOP_SET 0x1C
24#define JZ_REG_TIMER_STOP_CLEAR 0x2C
25#define JZ_REG_TIMER_ENABLE 0x00
26#define JZ_REG_TIMER_ENABLE_SET 0x04
27#define JZ_REG_TIMER_ENABLE_CLEAR 0x08
28#define JZ_REG_TIMER_FLAG 0x10
29#define JZ_REG_TIMER_FLAG_SET 0x14
30#define JZ_REG_TIMER_FLAG_CLEAR 0x18
31#define JZ_REG_TIMER_MASK 0x20
32#define JZ_REG_TIMER_MASK_SET 0x24
33#define JZ_REG_TIMER_MASK_CLEAR 0x28
34
35#define JZ_REG_TIMER_DFR(x) (((x) * 0x10) + 0x30)
36#define JZ_REG_TIMER_DHR(x) (((x) * 0x10) + 0x34)
37#define JZ_REG_TIMER_CNT(x) (((x) * 0x10) + 0x38)
38#define JZ_REG_TIMER_CTRL(x) (((x) * 0x10) + 0x3C)
39
40#define JZ_TIMER_IRQ_HALF(x) BIT((x) + 0x10)
41#define JZ_TIMER_IRQ_FULL(x) BIT(x)
42
43#define JZ_TIMER_CTRL_PWM_ABBRUPT_SHUTDOWN BIT(9)
44#define JZ_TIMER_CTRL_PWM_ACTIVE_LOW BIT(8)
45#define JZ_TIMER_CTRL_PWM_ENABLE BIT(7)
46#define JZ_TIMER_CTRL_PRESCALE_MASK 0x1c
47#define JZ_TIMER_CTRL_PRESCALE_OFFSET 0x3
48#define JZ_TIMER_CTRL_PRESCALE_1 (0 << 3)
49#define JZ_TIMER_CTRL_PRESCALE_4 (1 << 3)
50#define JZ_TIMER_CTRL_PRESCALE_16 (2 << 3)
51#define JZ_TIMER_CTRL_PRESCALE_64 (3 << 3)
52#define JZ_TIMER_CTRL_PRESCALE_256 (4 << 3)
53#define JZ_TIMER_CTRL_PRESCALE_1024 (5 << 3)
54
55#define JZ_TIMER_CTRL_PRESCALER(x) ((x) << JZ_TIMER_CTRL_PRESCALE_OFFSET)
56
57#define JZ_TIMER_CTRL_SRC_EXT BIT(2)
58#define JZ_TIMER_CTRL_SRC_RTC BIT(1)
59#define JZ_TIMER_CTRL_SRC_PCLK BIT(0)
60
61extern void __iomem *jz4740_timer_base;
62void __init jz4740_timer_init(void);
63
64static inline void jz4740_timer_stop(unsigned int timer)
65{
66 writel(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_STOP_SET);
67}
68
69static inline void jz4740_timer_start(unsigned int timer)
70{
71 writel(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_STOP_CLEAR);
72}
73
74static inline bool jz4740_timer_is_enabled(unsigned int timer)
75{
76 return readb(jz4740_timer_base + JZ_REG_TIMER_ENABLE) & BIT(timer);
77}
78
79static inline void jz4740_timer_enable(unsigned int timer)
80{
81 writeb(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_ENABLE_SET);
82}
83
84static inline void jz4740_timer_disable(unsigned int timer)
85{
86 writeb(BIT(timer), jz4740_timer_base + JZ_REG_TIMER_ENABLE_CLEAR);
87}
88
89
90static inline void jz4740_timer_set_period(unsigned int timer, uint16_t period)
91{
92 writew(period, jz4740_timer_base + JZ_REG_TIMER_DFR(timer));
93}
94
95static inline void jz4740_timer_set_duty(unsigned int timer, uint16_t duty)
96{
97 writew(duty, jz4740_timer_base + JZ_REG_TIMER_DHR(timer));
98}
99
100static inline void jz4740_timer_set_count(unsigned int timer, uint16_t count)
101{
102 writew(count, jz4740_timer_base + JZ_REG_TIMER_CNT(timer));
103}
104
105static inline uint16_t jz4740_timer_get_count(unsigned int timer)
106{
107 return readw(jz4740_timer_base + JZ_REG_TIMER_CNT(timer));
108}
109
110static inline void jz4740_timer_ack_full(unsigned int timer)
111{
112 writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_FLAG_CLEAR);
113}
114
115static inline void jz4740_timer_irq_full_enable(unsigned int timer)
116{
117 writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_FLAG_CLEAR);
118 writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_MASK_CLEAR);
119}
120
121static inline void jz4740_timer_irq_full_disable(unsigned int timer)
122{
123 writel(JZ_TIMER_IRQ_FULL(timer), jz4740_timer_base + JZ_REG_TIMER_MASK_SET);
124}
125
126static inline void jz4740_timer_set_ctrl(unsigned int timer, uint16_t ctrl)
127{
128 writew(ctrl, jz4740_timer_base + JZ_REG_TIMER_CTRL(timer));
129}
130
131static inline uint16_t jz4740_timer_get_ctrl(unsigned int timer)
132{
133 return readw(jz4740_timer_base + JZ_REG_TIMER_CTRL(timer));
134}
135
136#endif
diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig
index 1e638e75a6b7..35ee2bf66354 100644
--- a/arch/unicore32/Kconfig
+++ b/arch/unicore32/Kconfig
@@ -21,9 +21,6 @@ config UNICORE32
21 designs licensed by PKUnity Ltd. 21 designs licensed by PKUnity Ltd.
22 Please see web page at <http://www.pkunity.com/>. 22 Please see web page at <http://www.pkunity.com/>.
23 23
24config HAVE_PWM
25 bool
26
27config GENERIC_GPIO 24config GENERIC_GPIO
28 def_bool y 25 def_bool y
29 26
@@ -106,7 +103,8 @@ config PUV3_DB0913
106 103
107config PUV3_NB0916 104config PUV3_NB0916
108 bool "NetBook board (0916)" 105 bool "NetBook board (0916)"
109 select HAVE_PWM 106 select PWM
107 select PWM_PUV3
110 108
111config PUV3_SMW0919 109config PUV3_SMW0919
112 bool "Security Mini-Workstation board (0919)" 110 bool "Security Mini-Workstation board (0919)"
@@ -220,12 +218,6 @@ config PUV3_GPIO
220 select GPIO_SYSFS if EXPERIMENTAL 218 select GPIO_SYSFS if EXPERIMENTAL
221 default y 219 default y
222 220
223config PUV3_PWM
224 tristate
225 default BACKLIGHT_PWM
226 help
227 Enable support for NB0916 PWM controllers
228
229if PUV3_NB0916 221if PUV3_NB0916
230 222
231menu "PKUnity NetBook-0916 Features" 223menu "PKUnity NetBook-0916 Features"
diff --git a/arch/unicore32/include/mach/regs-ost.h b/arch/unicore32/include/mach/regs-ost.h
index 7b91fe698eed..4a85fb463848 100644
--- a/arch/unicore32/include/mach/regs-ost.h
+++ b/arch/unicore32/include/mach/regs-ost.h
@@ -33,18 +33,16 @@
33 * Interrupt Enable Reg OST_OIER 33 * Interrupt Enable Reg OST_OIER
34 */ 34 */
35#define OST_OIER (PKUNITY_OST_BASE + 0x001C) 35#define OST_OIER (PKUNITY_OST_BASE + 0x001C)
36
36/* 37/*
37 * PWM Pulse Width Control Reg OST_PWMPWCR 38 * PWM Registers: IO base address: PKUNITY_OST_BASE + 0x80
38 */ 39 * PWCR: Pulse Width Control Reg
39#define OST_PWMPWCR (PKUNITY_OST_BASE + 0x0080) 40 * DCCR: Duty Cycle Control Reg
40/* 41 * PCR: Period Control Reg
41 * PWM Duty Cycle Control Reg OST_PWMDCCR
42 */
43#define OST_PWMDCCR (PKUNITY_OST_BASE + 0x0084)
44/*
45 * PWM Period Control Reg OST_PWMPCR
46 */ 42 */
47#define OST_PWMPCR (PKUNITY_OST_BASE + 0x0088) 43#define OST_PWM_PWCR (0x00)
44#define OST_PWM_DCCR (0x04)
45#define OST_PWM_PCR (0x08)
48 46
49/* 47/*
50 * Match detected 0 OST_OSSR_M0 48 * Match detected 0 OST_OSSR_M0
diff --git a/arch/unicore32/kernel/Makefile b/arch/unicore32/kernel/Makefile
index 324010156958..fa497e0efe5a 100644
--- a/arch/unicore32/kernel/Makefile
+++ b/arch/unicore32/kernel/Makefile
@@ -16,7 +16,6 @@ obj-$(CONFIG_UNICORE_FPU_F64) += fpu-ucf64.o
16obj-$(CONFIG_ARCH_PUV3) += clock.o irq.o time.o 16obj-$(CONFIG_ARCH_PUV3) += clock.o irq.o time.o
17 17
18obj-$(CONFIG_PUV3_GPIO) += gpio.o 18obj-$(CONFIG_PUV3_GPIO) += gpio.o
19obj-$(CONFIG_PUV3_PWM) += pwm.o
20obj-$(CONFIG_PUV3_PM) += pm.o sleep.o 19obj-$(CONFIG_PUV3_PM) += pm.o sleep.o
21obj-$(CONFIG_HIBERNATION) += hibernate.o hibernate_asm.o 20obj-$(CONFIG_HIBERNATION) += hibernate.o hibernate_asm.o
22 21
diff --git a/arch/unicore32/kernel/pwm.c b/arch/unicore32/kernel/pwm.c
deleted file mode 100644
index 4615d51e3ba6..000000000000
--- a/arch/unicore32/kernel/pwm.c
+++ /dev/null
@@ -1,263 +0,0 @@
1/*
2 * linux/arch/unicore32/kernel/pwm.c
3 *
4 * Code specific to PKUnity SoC and UniCore ISA
5 *
6 * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
7 * Copyright (C) 2001-2010 Guan Xuetao
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/platform_device.h>
17#include <linux/slab.h>
18#include <linux/err.h>
19#include <linux/clk.h>
20#include <linux/io.h>
21#include <linux/pwm.h>
22
23#include <asm/div64.h>
24#include <mach/hardware.h>
25
26struct pwm_device {
27 struct list_head node;
28 struct platform_device *pdev;
29
30 const char *label;
31 struct clk *clk;
32 int clk_enabled;
33
34 unsigned int use_count;
35 unsigned int pwm_id;
36};
37
38/*
39 * period_ns = 10^9 * (PRESCALE + 1) * (PV + 1) / PWM_CLK_RATE
40 * duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE
41 */
42int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
43{
44 unsigned long long c;
45 unsigned long period_cycles, prescale, pv, dc;
46
47 if (pwm == NULL || period_ns == 0 || duty_ns > period_ns)
48 return -EINVAL;
49
50 c = clk_get_rate(pwm->clk);
51 c = c * period_ns;
52 do_div(c, 1000000000);
53 period_cycles = c;
54
55 if (period_cycles < 1)
56 period_cycles = 1;
57 prescale = (period_cycles - 1) / 1024;
58 pv = period_cycles / (prescale + 1) - 1;
59
60 if (prescale > 63)
61 return -EINVAL;
62
63 if (duty_ns == period_ns)
64 dc = OST_PWMDCCR_FDCYCLE;
65 else
66 dc = (pv + 1) * duty_ns / period_ns;
67
68 /* NOTE: the clock to PWM has to be enabled first
69 * before writing to the registers
70 */
71 clk_enable(pwm->clk);
72 OST_PWMPWCR = prescale;
73 OST_PWMDCCR = pv - dc;
74 OST_PWMPCR = pv;
75 clk_disable(pwm->clk);
76
77 return 0;
78}
79EXPORT_SYMBOL(pwm_config);
80
81int pwm_enable(struct pwm_device *pwm)
82{
83 int rc = 0;
84
85 if (!pwm->clk_enabled) {
86 rc = clk_enable(pwm->clk);
87 if (!rc)
88 pwm->clk_enabled = 1;
89 }
90 return rc;
91}
92EXPORT_SYMBOL(pwm_enable);
93
94void pwm_disable(struct pwm_device *pwm)
95{
96 if (pwm->clk_enabled) {
97 clk_disable(pwm->clk);
98 pwm->clk_enabled = 0;
99 }
100}
101EXPORT_SYMBOL(pwm_disable);
102
103static DEFINE_MUTEX(pwm_lock);
104static LIST_HEAD(pwm_list);
105
106struct pwm_device *pwm_request(int pwm_id, const char *label)
107{
108 struct pwm_device *pwm;
109 int found = 0;
110
111 mutex_lock(&pwm_lock);
112
113 list_for_each_entry(pwm, &pwm_list, node) {
114 if (pwm->pwm_id == pwm_id) {
115 found = 1;
116 break;
117 }
118 }
119
120 if (found) {
121 if (pwm->use_count == 0) {
122 pwm->use_count++;
123 pwm->label = label;
124 } else
125 pwm = ERR_PTR(-EBUSY);
126 } else
127 pwm = ERR_PTR(-ENOENT);
128
129 mutex_unlock(&pwm_lock);
130 return pwm;
131}
132EXPORT_SYMBOL(pwm_request);
133
134void pwm_free(struct pwm_device *pwm)
135{
136 mutex_lock(&pwm_lock);
137
138 if (pwm->use_count) {
139 pwm->use_count--;
140 pwm->label = NULL;
141 } else
142 pr_warning("PWM device already freed\n");
143
144 mutex_unlock(&pwm_lock);
145}
146EXPORT_SYMBOL(pwm_free);
147
148static inline void __add_pwm(struct pwm_device *pwm)
149{
150 mutex_lock(&pwm_lock);
151 list_add_tail(&pwm->node, &pwm_list);
152 mutex_unlock(&pwm_lock);
153}
154
155static struct pwm_device *pwm_probe(struct platform_device *pdev,
156 unsigned int pwm_id, struct pwm_device *parent_pwm)
157{
158 struct pwm_device *pwm;
159 struct resource *r;
160 int ret = 0;
161
162 pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
163 if (pwm == NULL) {
164 dev_err(&pdev->dev, "failed to allocate memory\n");
165 return ERR_PTR(-ENOMEM);
166 }
167
168 pwm->clk = clk_get(NULL, "OST_CLK");
169 if (IS_ERR(pwm->clk)) {
170 ret = PTR_ERR(pwm->clk);
171 goto err_free;
172 }
173 pwm->clk_enabled = 0;
174
175 pwm->use_count = 0;
176 pwm->pwm_id = pwm_id;
177 pwm->pdev = pdev;
178
179 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
180 if (r == NULL) {
181 dev_err(&pdev->dev, "no memory resource defined\n");
182 ret = -ENODEV;
183 goto err_free_clk;
184 }
185
186 r = request_mem_region(r->start, resource_size(r), pdev->name);
187 if (r == NULL) {
188 dev_err(&pdev->dev, "failed to request memory resource\n");
189 ret = -EBUSY;
190 goto err_free_clk;
191 }
192
193 __add_pwm(pwm);
194 platform_set_drvdata(pdev, pwm);
195 return pwm;
196
197err_free_clk:
198 clk_put(pwm->clk);
199err_free:
200 kfree(pwm);
201 return ERR_PTR(ret);
202}
203
204static int __devinit puv3_pwm_probe(struct platform_device *pdev)
205{
206 struct pwm_device *pwm = pwm_probe(pdev, pdev->id, NULL);
207
208 if (IS_ERR(pwm))
209 return PTR_ERR(pwm);
210
211 return 0;
212}
213
214static int __devexit pwm_remove(struct platform_device *pdev)
215{
216 struct pwm_device *pwm;
217 struct resource *r;
218
219 pwm = platform_get_drvdata(pdev);
220 if (pwm == NULL)
221 return -ENODEV;
222
223 mutex_lock(&pwm_lock);
224 list_del(&pwm->node);
225 mutex_unlock(&pwm_lock);
226
227 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
228 release_mem_region(r->start, resource_size(r));
229
230 clk_put(pwm->clk);
231 kfree(pwm);
232 return 0;
233}
234
235static struct platform_driver puv3_pwm_driver = {
236 .driver = {
237 .name = "PKUnity-v3-PWM",
238 },
239 .probe = puv3_pwm_probe,
240 .remove = __devexit_p(pwm_remove),
241};
242
243static int __init pwm_init(void)
244{
245 int ret = 0;
246
247 ret = platform_driver_register(&puv3_pwm_driver);
248 if (ret) {
249 printk(KERN_ERR "failed to register puv3_pwm_driver\n");
250 return ret;
251 }
252
253 return ret;
254}
255arch_initcall(pwm_init);
256
257static void __exit pwm_exit(void)
258{
259 platform_driver_unregister(&puv3_pwm_driver);
260}
261module_exit(pwm_exit);
262
263MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 99c73352c430..b151b7c1bd59 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -60,16 +60,6 @@ config ATMEL_PWM
60 purposes including software controlled power-efficient backlights 60 purposes including software controlled power-efficient backlights
61 on LCD displays, motor control, and waveform generation. 61 on LCD displays, motor control, and waveform generation.
62 62
63config AB8500_PWM
64 bool "AB8500 PWM support"
65 depends on AB8500_CORE && ARCH_U8500
66 select HAVE_PWM
67 depends on !PWM
68 help
69 This driver exports functions to enable/disble/config/free Pulse
70 Width Modulation in the Analog Baseband Chip AB8500.
71 It is used by led and backlight driver to control the intensity.
72
73config ATMEL_TCLIB 63config ATMEL_TCLIB
74 bool "Atmel AT32/AT91 Timer/Counter Library" 64 bool "Atmel AT32/AT91 Timer/Counter Library"
75 depends on (AVR32 || ARCH_AT91) 65 depends on (AVR32 || ARCH_AT91)
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index b88df7a350b8..2129377c0de6 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -44,7 +44,6 @@ obj-$(CONFIG_VMWARE_BALLOON) += vmw_balloon.o
44obj-$(CONFIG_ARM_CHARLCD) += arm-charlcd.o 44obj-$(CONFIG_ARM_CHARLCD) += arm-charlcd.o
45obj-$(CONFIG_PCH_PHUB) += pch_phub.o 45obj-$(CONFIG_PCH_PHUB) += pch_phub.o
46obj-y += ti-st/ 46obj-y += ti-st/
47obj-$(CONFIG_AB8500_PWM) += ab8500-pwm.o
48obj-y += lis3lv02d/ 47obj-y += lis3lv02d/
49obj-y += carma/ 48obj-y += carma/
50obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o 49obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index d7c6b83097c1..ed81720e7b2b 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -1,6 +1,5 @@
1menuconfig PWM 1menuconfig PWM
2 bool "Pulse-Width Modulation (PWM) Support" 2 bool "Pulse-Width Modulation (PWM) Support"
3 depends on !MACH_JZ4740 && !PUV3_PWM
4 help 3 help
5 Generic Pulse-Width Modulation (PWM) support. 4 Generic Pulse-Width Modulation (PWM) support.
6 5
@@ -29,6 +28,15 @@ menuconfig PWM
29 28
30if PWM 29if PWM
31 30
31config PWM_AB8500
32 tristate "AB8500 PWM support"
33 depends on AB8500_CORE && ARCH_U8500
34 help
35 Generic PWM framework driver for Analog Baseband AB8500.
36
37 To compile this driver as a module, choose M here: the module
38 will be called pwm-ab8500.
39
32config PWM_BFIN 40config PWM_BFIN
33 tristate "Blackfin PWM support" 41 tristate "Blackfin PWM support"
34 depends on BFIN_GPTIMERS 42 depends on BFIN_GPTIMERS
@@ -47,6 +55,16 @@ config PWM_IMX
47 To compile this driver as a module, choose M here: the module 55 To compile this driver as a module, choose M here: the module
48 will be called pwm-imx. 56 will be called pwm-imx.
49 57
58config PWM_JZ4740
59 tristate "Ingenic JZ4740 PWM support"
60 depends on MACH_JZ4740
61 help
62 Generic PWM framework driver for Ingenic JZ4740 based
63 machines.
64
65 To compile this driver as a module, choose M here: the module
66 will be called pwm-jz4740.
67
50config PWM_LPC32XX 68config PWM_LPC32XX
51 tristate "LPC32XX PWM support" 69 tristate "LPC32XX PWM support"
52 depends on ARCH_LPC32XX 70 depends on ARCH_LPC32XX
@@ -67,6 +85,15 @@ config PWM_MXS
67 To compile this driver as a module, choose M here: the module 85 To compile this driver as a module, choose M here: the module
68 will be called pwm-mxs. 86 will be called pwm-mxs.
69 87
88config PWM_PUV3
89 tristate "PKUnity NetBook-0916 PWM support"
90 depends on ARCH_PUV3
91 help
92 Generic PWM framework driver for PKUnity NetBook-0916.
93
94 To compile this driver as a module, choose M here: the module
95 will be called pwm-puv3.
96
70config PWM_PXA 97config PWM_PXA
71 tristate "PXA PWM support" 98 tristate "PXA PWM support"
72 depends on ARCH_PXA 99 depends on ARCH_PXA
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 78f123dca30d..acfe4821c58b 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -1,8 +1,11 @@
1obj-$(CONFIG_PWM) += core.o 1obj-$(CONFIG_PWM) += core.o
2obj-$(CONFIG_PWM_AB8500) += pwm-ab8500.o
2obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o 3obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o
3obj-$(CONFIG_PWM_IMX) += pwm-imx.o 4obj-$(CONFIG_PWM_IMX) += pwm-imx.o
5obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o
4obj-$(CONFIG_PWM_LPC32XX) += pwm-lpc32xx.o 6obj-$(CONFIG_PWM_LPC32XX) += pwm-lpc32xx.o
5obj-$(CONFIG_PWM_MXS) += pwm-mxs.o 7obj-$(CONFIG_PWM_MXS) += pwm-mxs.o
8obj-$(CONFIG_PWM_PUV3) += pwm-puv3.o
6obj-$(CONFIG_PWM_PXA) += pwm-pxa.o 9obj-$(CONFIG_PWM_PXA) += pwm-pxa.o
7obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o 10obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o
8obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o 11obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index c6e05078d3ad..f5acdaa52707 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -371,7 +371,7 @@ EXPORT_SYMBOL_GPL(pwm_free);
371 */ 371 */
372int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) 372int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
373{ 373{
374 if (!pwm || period_ns == 0 || duty_ns > period_ns) 374 if (!pwm || duty_ns < 0 || period_ns <= 0 || duty_ns > period_ns)
375 return -EINVAL; 375 return -EINVAL;
376 376
377 return pwm->chip->ops->config(pwm->chip, pwm, duty_ns, period_ns); 377 return pwm->chip->ops->config(pwm->chip, pwm, duty_ns, period_ns);
@@ -379,6 +379,28 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
379EXPORT_SYMBOL_GPL(pwm_config); 379EXPORT_SYMBOL_GPL(pwm_config);
380 380
381/** 381/**
382 * pwm_set_polarity() - configure the polarity of a PWM signal
383 * @pwm: PWM device
384 * @polarity: new polarity of the PWM signal
385 *
386 * Note that the polarity cannot be configured while the PWM device is enabled
387 */
388int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity)
389{
390 if (!pwm || !pwm->chip->ops)
391 return -EINVAL;
392
393 if (!pwm->chip->ops->set_polarity)
394 return -ENOSYS;
395
396 if (test_bit(PWMF_ENABLED, &pwm->flags))
397 return -EBUSY;
398
399 return pwm->chip->ops->set_polarity(pwm->chip, pwm, polarity);
400}
401EXPORT_SYMBOL_GPL(pwm_set_polarity);
402
403/**
382 * pwm_enable() - start a PWM output toggling 404 * pwm_enable() - start a PWM output toggling
383 * @pwm: PWM device 405 * @pwm: PWM device
384 */ 406 */
@@ -624,6 +646,64 @@ out:
624} 646}
625EXPORT_SYMBOL_GPL(pwm_put); 647EXPORT_SYMBOL_GPL(pwm_put);
626 648
649static void devm_pwm_release(struct device *dev, void *res)
650{
651 pwm_put(*(struct pwm_device **)res);
652}
653
654/**
655 * devm_pwm_get() - resource managed pwm_get()
656 * @dev: device for PWM consumer
657 * @con_id: consumer name
658 *
659 * This function performs like pwm_get() but the acquired PWM device will
660 * automatically be released on driver detach.
661 */
662struct pwm_device *devm_pwm_get(struct device *dev, const char *con_id)
663{
664 struct pwm_device **ptr, *pwm;
665
666 ptr = devres_alloc(devm_pwm_release, sizeof(**ptr), GFP_KERNEL);
667 if (!ptr)
668 return ERR_PTR(-ENOMEM);
669
670 pwm = pwm_get(dev, con_id);
671 if (!IS_ERR(pwm)) {
672 *ptr = pwm;
673 devres_add(dev, ptr);
674 } else {
675 devres_free(ptr);
676 }
677
678 return pwm;
679}
680EXPORT_SYMBOL_GPL(devm_pwm_get);
681
682static int devm_pwm_match(struct device *dev, void *res, void *data)
683{
684 struct pwm_device **p = res;
685
686 if (WARN_ON(!p || !*p))
687 return 0;
688
689 return *p == data;
690}
691
692/**
693 * devm_pwm_put() - resource managed pwm_put()
694 * @dev: device for PWM consumer
695 * @pwm: PWM device
696 *
697 * Release a PWM previously allocated using devm_pwm_get(). Calling this
698 * function is usually not needed because devm-allocated resources are
699 * automatically released on driver detach.
700 */
701void devm_pwm_put(struct device *dev, struct pwm_device *pwm)
702{
703 WARN_ON(devres_release(dev, devm_pwm_release, devm_pwm_match, pwm));
704}
705EXPORT_SYMBOL_GPL(devm_pwm_put);
706
627#ifdef CONFIG_DEBUG_FS 707#ifdef CONFIG_DEBUG_FS
628static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s) 708static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s)
629{ 709{
diff --git a/drivers/misc/ab8500-pwm.c b/drivers/pwm/pwm-ab8500.c
index d7a9aa14e5d5..cfb72ca873d1 100644
--- a/drivers/misc/ab8500-pwm.c
+++ b/drivers/pwm/pwm-ab8500.c
@@ -24,16 +24,12 @@
24#define ENABLE_PWM 1 24#define ENABLE_PWM 1
25#define DISABLE_PWM 0 25#define DISABLE_PWM 0
26 26
27struct pwm_device { 27struct ab8500_pwm_chip {
28 struct device *dev; 28 struct pwm_chip chip;
29 struct list_head node;
30 const char *label;
31 unsigned int pwm_id;
32}; 29};
33 30
34static LIST_HEAD(pwm_list); 31static int ab8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
35 32 int duty_ns, int period_ns)
36int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
37{ 33{
38 int ret = 0; 34 int ret = 0;
39 unsigned int higher_val, lower_val; 35 unsigned int higher_val, lower_val;
@@ -50,95 +46,94 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
50 */ 46 */
51 higher_val = ((duty_ns & 0x0300) >> 8); 47 higher_val = ((duty_ns & 0x0300) >> 8);
52 48
53 reg = AB8500_PWM_OUT_CTRL1_REG + ((pwm->pwm_id - 1) * 2); 49 reg = AB8500_PWM_OUT_CTRL1_REG + ((chip->base - 1) * 2);
54 50
55 ret = abx500_set_register_interruptible(pwm->dev, AB8500_MISC, 51 ret = abx500_set_register_interruptible(chip->dev, AB8500_MISC,
56 reg, (u8)lower_val); 52 reg, (u8)lower_val);
57 if (ret < 0) 53 if (ret < 0)
58 return ret; 54 return ret;
59 ret = abx500_set_register_interruptible(pwm->dev, AB8500_MISC, 55 ret = abx500_set_register_interruptible(chip->dev, AB8500_MISC,
60 (reg + 1), (u8)higher_val); 56 (reg + 1), (u8)higher_val);
61 57
62 return ret; 58 return ret;
63} 59}
64EXPORT_SYMBOL(pwm_config);
65 60
66int pwm_enable(struct pwm_device *pwm) 61static int ab8500_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
67{ 62{
68 int ret; 63 int ret;
69 64
70 ret = abx500_mask_and_set_register_interruptible(pwm->dev, 65 ret = abx500_mask_and_set_register_interruptible(chip->dev,
71 AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG, 66 AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG,
72 1 << (pwm->pwm_id-1), ENABLE_PWM); 67 1 << (chip->base - 1), ENABLE_PWM);
73 if (ret < 0) 68 if (ret < 0)
74 dev_err(pwm->dev, "%s: Failed to disable PWM, Error %d\n", 69 dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n",
75 pwm->label, ret); 70 pwm->label, ret);
76 return ret; 71 return ret;
77} 72}
78EXPORT_SYMBOL(pwm_enable);
79 73
80void pwm_disable(struct pwm_device *pwm) 74static void ab8500_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
81{ 75{
82 int ret; 76 int ret;
83 77
84 ret = abx500_mask_and_set_register_interruptible(pwm->dev, 78 ret = abx500_mask_and_set_register_interruptible(chip->dev,
85 AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG, 79 AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG,
86 1 << (pwm->pwm_id-1), DISABLE_PWM); 80 1 << (chip->base - 1), DISABLE_PWM);
87 if (ret < 0) 81 if (ret < 0)
88 dev_err(pwm->dev, "%s: Failed to disable PWM, Error %d\n", 82 dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n",
89 pwm->label, ret); 83 pwm->label, ret);
90 return; 84 return;
91} 85}
92EXPORT_SYMBOL(pwm_disable);
93
94struct pwm_device *pwm_request(int pwm_id, const char *label)
95{
96 struct pwm_device *pwm;
97
98 list_for_each_entry(pwm, &pwm_list, node) {
99 if (pwm->pwm_id == pwm_id) {
100 pwm->label = label;
101 pwm->pwm_id = pwm_id;
102 return pwm;
103 }
104 }
105
106 return ERR_PTR(-ENOENT);
107}
108EXPORT_SYMBOL(pwm_request);
109 86
110void pwm_free(struct pwm_device *pwm) 87static const struct pwm_ops ab8500_pwm_ops = {
111{ 88 .config = ab8500_pwm_config,
112 pwm_disable(pwm); 89 .enable = ab8500_pwm_enable,
113} 90 .disable = ab8500_pwm_disable,
114EXPORT_SYMBOL(pwm_free); 91};
115 92
116static int __devinit ab8500_pwm_probe(struct platform_device *pdev) 93static int __devinit ab8500_pwm_probe(struct platform_device *pdev)
117{ 94{
118 struct pwm_device *pwm; 95 struct ab8500_pwm_chip *ab8500;
96 int err;
97
119 /* 98 /*
120 * Nothing to be done in probe, this is required to get the 99 * Nothing to be done in probe, this is required to get the
121 * device which is required for ab8500 read and write 100 * device which is required for ab8500 read and write
122 */ 101 */
123 pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL); 102 ab8500 = kzalloc(sizeof(*ab8500), GFP_KERNEL);
124 if (pwm == NULL) { 103 if (ab8500 == NULL) {
125 dev_err(&pdev->dev, "failed to allocate memory\n"); 104 dev_err(&pdev->dev, "failed to allocate memory\n");
126 return -ENOMEM; 105 return -ENOMEM;
127 } 106 }
128 pwm->dev = &pdev->dev; 107
129 pwm->pwm_id = pdev->id; 108 ab8500->chip.dev = &pdev->dev;
130 list_add_tail(&pwm->node, &pwm_list); 109 ab8500->chip.ops = &ab8500_pwm_ops;
131 platform_set_drvdata(pdev, pwm); 110 ab8500->chip.base = pdev->id;
132 dev_dbg(pwm->dev, "pwm probe successful\n"); 111 ab8500->chip.npwm = 1;
112
113 err = pwmchip_add(&ab8500->chip);
114 if (err < 0) {
115 kfree(ab8500);
116 return err;
117 }
118
119 dev_dbg(&pdev->dev, "pwm probe successful\n");
120 platform_set_drvdata(pdev, ab8500);
121
133 return 0; 122 return 0;
134} 123}
135 124
136static int __devexit ab8500_pwm_remove(struct platform_device *pdev) 125static int __devexit ab8500_pwm_remove(struct platform_device *pdev)
137{ 126{
138 struct pwm_device *pwm = platform_get_drvdata(pdev); 127 struct ab8500_pwm_chip *ab8500 = platform_get_drvdata(pdev);
139 list_del(&pwm->node); 128 int err;
129
130 err = pwmchip_remove(&ab8500->chip);
131 if (err < 0)
132 return err;
133
140 dev_dbg(&pdev->dev, "pwm driver removed\n"); 134 dev_dbg(&pdev->dev, "pwm driver removed\n");
141 kfree(pwm); 135 kfree(ab8500);
136
142 return 0; 137 return 0;
143} 138}
144 139
@@ -150,19 +145,8 @@ static struct platform_driver ab8500_pwm_driver = {
150 .probe = ab8500_pwm_probe, 145 .probe = ab8500_pwm_probe,
151 .remove = __devexit_p(ab8500_pwm_remove), 146 .remove = __devexit_p(ab8500_pwm_remove),
152}; 147};
148module_platform_driver(ab8500_pwm_driver);
153 149
154static int __init ab8500_pwm_init(void)
155{
156 return platform_driver_register(&ab8500_pwm_driver);
157}
158
159static void __exit ab8500_pwm_exit(void)
160{
161 platform_driver_unregister(&ab8500_pwm_driver);
162}
163
164subsys_initcall(ab8500_pwm_init);
165module_exit(ab8500_pwm_exit);
166MODULE_AUTHOR("Arun MURTHY <arun.murthy@stericsson.com>"); 150MODULE_AUTHOR("Arun MURTHY <arun.murthy@stericsson.com>");
167MODULE_DESCRIPTION("AB8500 Pulse Width Modulation Driver"); 151MODULE_DESCRIPTION("AB8500 Pulse Width Modulation Driver");
168MODULE_ALIAS("platform:ab8500-pwm"); 152MODULE_ALIAS("platform:ab8500-pwm");
diff --git a/drivers/pwm/pwm-bfin.c b/drivers/pwm/pwm-bfin.c
index d53c4e7941ef..5da8e185e838 100644
--- a/drivers/pwm/pwm-bfin.c
+++ b/drivers/pwm/pwm-bfin.c
@@ -69,9 +69,6 @@ static int bfin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
69 unsigned long period, duty; 69 unsigned long period, duty;
70 unsigned long long val; 70 unsigned long long val;
71 71
72 if (duty_ns < 0 || duty_ns > period_ns)
73 return -EINVAL;
74
75 val = (unsigned long long)get_sclk() * period_ns; 72 val = (unsigned long long)get_sclk() * period_ns;
76 do_div(val, NSEC_PER_SEC); 73 do_div(val, NSEC_PER_SEC);
77 period = val; 74 period = val;
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
index 2a0b35333972..8a5d3ae2946a 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx.c
@@ -16,8 +16,7 @@
16#include <linux/clk.h> 16#include <linux/clk.h>
17#include <linux/io.h> 17#include <linux/io.h>
18#include <linux/pwm.h> 18#include <linux/pwm.h>
19#include <mach/hardware.h> 19#include <linux/of_device.h>
20
21 20
22/* i.MX1 and i.MX21 share the same PWM function block: */ 21/* i.MX1 and i.MX21 share the same PWM function block: */
23 22
@@ -25,6 +24,7 @@
25#define MX1_PWMS 0x04 /* PWM Sample Register */ 24#define MX1_PWMS 0x04 /* PWM Sample Register */
26#define MX1_PWMP 0x08 /* PWM Period Register */ 25#define MX1_PWMP 0x08 /* PWM Period Register */
27 26
27#define MX1_PWMC_EN (1 << 4)
28 28
29/* i.MX27, i.MX31, i.MX35 share the same PWM function block: */ 29/* i.MX27, i.MX31, i.MX35 share the same PWM function block: */
30 30
@@ -40,110 +40,165 @@
40#define MX3_PWMCR_EN (1 << 0) 40#define MX3_PWMCR_EN (1 << 0)
41 41
42struct imx_chip { 42struct imx_chip {
43 struct clk *clk; 43 struct clk *clk_per;
44 struct clk *clk_ipg;
44 45
45 int clk_enabled; 46 int enabled;
46 void __iomem *mmio_base; 47 void __iomem *mmio_base;
47 48
48 struct pwm_chip chip; 49 struct pwm_chip chip;
50
51 int (*config)(struct pwm_chip *chip,
52 struct pwm_device *pwm, int duty_ns, int period_ns);
53 void (*set_enable)(struct pwm_chip *chip, bool enable);
49}; 54};
50 55
51#define to_imx_chip(chip) container_of(chip, struct imx_chip, chip) 56#define to_imx_chip(chip) container_of(chip, struct imx_chip, chip)
52 57
53static int imx_pwm_config(struct pwm_chip *chip, 58static int imx_pwm_config_v1(struct pwm_chip *chip,
54 struct pwm_device *pwm, int duty_ns, int period_ns) 59 struct pwm_device *pwm, int duty_ns, int period_ns)
55{ 60{
56 struct imx_chip *imx = to_imx_chip(chip); 61 struct imx_chip *imx = to_imx_chip(chip);
57 62
58 if (!(cpu_is_mx1() || cpu_is_mx21())) { 63 /*
59 unsigned long long c; 64 * The PWM subsystem allows for exact frequencies. However,
60 unsigned long period_cycles, duty_cycles, prescale; 65 * I cannot connect a scope on my device to the PWM line and
61 u32 cr; 66 * thus cannot provide the program the PWM controller
62 67 * exactly. Instead, I'm relying on the fact that the
63 c = clk_get_rate(imx->clk); 68 * Bootloader (u-boot or WinCE+haret) has programmed the PWM
64 c = c * period_ns; 69 * function group already. So I'll just modify the PWM sample
65 do_div(c, 1000000000); 70 * register to follow the ratio of duty_ns vs. period_ns
66 period_cycles = c; 71 * accordingly.
67 72 *
68 prescale = period_cycles / 0x10000 + 1; 73 * This is good enough for programming the brightness of
69 74 * the LCD backlight.
70 period_cycles /= prescale; 75 *
71 c = (unsigned long long)period_cycles * duty_ns; 76 * The real implementation would divide PERCLK[0] first by
72 do_div(c, period_ns); 77 * both the prescaler (/1 .. /128) and then by CLKSEL
73 duty_cycles = c; 78 * (/2 .. /16).
74 79 */
75 /* 80 u32 max = readl(imx->mmio_base + MX1_PWMP);
76 * according to imx pwm RM, the real period value should be 81 u32 p = max * duty_ns / period_ns;
77 * PERIOD value in PWMPR plus 2. 82 writel(max - p, imx->mmio_base + MX1_PWMS);
78 */
79 if (period_cycles > 2)
80 period_cycles -= 2;
81 else
82 period_cycles = 0;
83
84 writel(duty_cycles, imx->mmio_base + MX3_PWMSAR);
85 writel(period_cycles, imx->mmio_base + MX3_PWMPR);
86
87 cr = MX3_PWMCR_PRESCALER(prescale) |
88 MX3_PWMCR_DOZEEN | MX3_PWMCR_WAITEN |
89 MX3_PWMCR_DBGEN | MX3_PWMCR_EN;
90
91 if (cpu_is_mx25())
92 cr |= MX3_PWMCR_CLKSRC_IPG;
93 else
94 cr |= MX3_PWMCR_CLKSRC_IPG_HIGH;
95
96 writel(cr, imx->mmio_base + MX3_PWMCR);
97 } else if (cpu_is_mx1() || cpu_is_mx21()) {
98 /* The PWM subsystem allows for exact frequencies. However,
99 * I cannot connect a scope on my device to the PWM line and
100 * thus cannot provide the program the PWM controller
101 * exactly. Instead, I'm relying on the fact that the
102 * Bootloader (u-boot or WinCE+haret) has programmed the PWM
103 * function group already. So I'll just modify the PWM sample
104 * register to follow the ratio of duty_ns vs. period_ns
105 * accordingly.
106 *
107 * This is good enough for programming the brightness of
108 * the LCD backlight.
109 *
110 * The real implementation would divide PERCLK[0] first by
111 * both the prescaler (/1 .. /128) and then by CLKSEL
112 * (/2 .. /16).
113 */
114 u32 max = readl(imx->mmio_base + MX1_PWMP);
115 u32 p = max * duty_ns / period_ns;
116 writel(max - p, imx->mmio_base + MX1_PWMS);
117 } else {
118 BUG();
119 }
120 83
121 return 0; 84 return 0;
122} 85}
123 86
87static void imx_pwm_set_enable_v1(struct pwm_chip *chip, bool enable)
88{
89 struct imx_chip *imx = to_imx_chip(chip);
90 u32 val;
91
92 val = readl(imx->mmio_base + MX1_PWMC);
93
94 if (enable)
95 val |= MX1_PWMC_EN;
96 else
97 val &= ~MX1_PWMC_EN;
98
99 writel(val, imx->mmio_base + MX1_PWMC);
100}
101
102static int imx_pwm_config_v2(struct pwm_chip *chip,
103 struct pwm_device *pwm, int duty_ns, int period_ns)
104{
105 struct imx_chip *imx = to_imx_chip(chip);
106 unsigned long long c;
107 unsigned long period_cycles, duty_cycles, prescale;
108 u32 cr;
109
110 c = clk_get_rate(imx->clk_per);
111 c = c * period_ns;
112 do_div(c, 1000000000);
113 period_cycles = c;
114
115 prescale = period_cycles / 0x10000 + 1;
116
117 period_cycles /= prescale;
118 c = (unsigned long long)period_cycles * duty_ns;
119 do_div(c, period_ns);
120 duty_cycles = c;
121
122 /*
123 * according to imx pwm RM, the real period value should be
124 * PERIOD value in PWMPR plus 2.
125 */
126 if (period_cycles > 2)
127 period_cycles -= 2;
128 else
129 period_cycles = 0;
130
131 writel(duty_cycles, imx->mmio_base + MX3_PWMSAR);
132 writel(period_cycles, imx->mmio_base + MX3_PWMPR);
133
134 cr = MX3_PWMCR_PRESCALER(prescale) |
135 MX3_PWMCR_DOZEEN | MX3_PWMCR_WAITEN |
136 MX3_PWMCR_DBGEN | MX3_PWMCR_CLKSRC_IPG_HIGH;
137
138 if (imx->enabled)
139 cr |= MX3_PWMCR_EN;
140
141 writel(cr, imx->mmio_base + MX3_PWMCR);
142
143 return 0;
144}
145
146static void imx_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
147{
148 struct imx_chip *imx = to_imx_chip(chip);
149 u32 val;
150
151 val = readl(imx->mmio_base + MX3_PWMCR);
152
153 if (enable)
154 val |= MX3_PWMCR_EN;
155 else
156 val &= ~MX3_PWMCR_EN;
157
158 writel(val, imx->mmio_base + MX3_PWMCR);
159}
160
161static int imx_pwm_config(struct pwm_chip *chip,
162 struct pwm_device *pwm, int duty_ns, int period_ns)
163{
164 struct imx_chip *imx = to_imx_chip(chip);
165 int ret;
166
167 ret = clk_prepare_enable(imx->clk_ipg);
168 if (ret)
169 return ret;
170
171 ret = imx->config(chip, pwm, duty_ns, period_ns);
172
173 clk_disable_unprepare(imx->clk_ipg);
174
175 return ret;
176}
177
124static int imx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 178static int imx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
125{ 179{
126 struct imx_chip *imx = to_imx_chip(chip); 180 struct imx_chip *imx = to_imx_chip(chip);
127 int rc = 0; 181 int ret;
128 182
129 if (!imx->clk_enabled) { 183 ret = clk_prepare_enable(imx->clk_per);
130 rc = clk_prepare_enable(imx->clk); 184 if (ret)
131 if (!rc) 185 return ret;
132 imx->clk_enabled = 1; 186
133 } 187 imx->set_enable(chip, true);
134 return rc; 188
189 imx->enabled = 1;
190
191 return 0;
135} 192}
136 193
137static void imx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) 194static void imx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
138{ 195{
139 struct imx_chip *imx = to_imx_chip(chip); 196 struct imx_chip *imx = to_imx_chip(chip);
140 197
141 writel(0, imx->mmio_base + MX3_PWMCR); 198 imx->set_enable(chip, false);
142 199
143 if (imx->clk_enabled) { 200 clk_disable_unprepare(imx->clk_per);
144 clk_disable_unprepare(imx->clk); 201 imx->enabled = 0;
145 imx->clk_enabled = 0;
146 }
147} 202}
148 203
149static struct pwm_ops imx_pwm_ops = { 204static struct pwm_ops imx_pwm_ops = {
@@ -153,30 +208,66 @@ static struct pwm_ops imx_pwm_ops = {
153 .owner = THIS_MODULE, 208 .owner = THIS_MODULE,
154}; 209};
155 210
211struct imx_pwm_data {
212 int (*config)(struct pwm_chip *chip,
213 struct pwm_device *pwm, int duty_ns, int period_ns);
214 void (*set_enable)(struct pwm_chip *chip, bool enable);
215};
216
217static struct imx_pwm_data imx_pwm_data_v1 = {
218 .config = imx_pwm_config_v1,
219 .set_enable = imx_pwm_set_enable_v1,
220};
221
222static struct imx_pwm_data imx_pwm_data_v2 = {
223 .config = imx_pwm_config_v2,
224 .set_enable = imx_pwm_set_enable_v2,
225};
226
227static const struct of_device_id imx_pwm_dt_ids[] = {
228 { .compatible = "fsl,imx1-pwm", .data = &imx_pwm_data_v1, },
229 { .compatible = "fsl,imx27-pwm", .data = &imx_pwm_data_v2, },
230 { /* sentinel */ }
231};
232MODULE_DEVICE_TABLE(of, imx_pwm_dt_ids);
233
156static int __devinit imx_pwm_probe(struct platform_device *pdev) 234static int __devinit imx_pwm_probe(struct platform_device *pdev)
157{ 235{
236 const struct of_device_id *of_id =
237 of_match_device(imx_pwm_dt_ids, &pdev->dev);
238 struct imx_pwm_data *data;
158 struct imx_chip *imx; 239 struct imx_chip *imx;
159 struct resource *r; 240 struct resource *r;
160 int ret = 0; 241 int ret = 0;
161 242
243 if (!of_id)
244 return -ENODEV;
245
162 imx = devm_kzalloc(&pdev->dev, sizeof(*imx), GFP_KERNEL); 246 imx = devm_kzalloc(&pdev->dev, sizeof(*imx), GFP_KERNEL);
163 if (imx == NULL) { 247 if (imx == NULL) {
164 dev_err(&pdev->dev, "failed to allocate memory\n"); 248 dev_err(&pdev->dev, "failed to allocate memory\n");
165 return -ENOMEM; 249 return -ENOMEM;
166 } 250 }
167 251
168 imx->clk = devm_clk_get(&pdev->dev, "pwm"); 252 imx->clk_per = devm_clk_get(&pdev->dev, "per");
253 if (IS_ERR(imx->clk_per)) {
254 dev_err(&pdev->dev, "getting per clock failed with %ld\n",
255 PTR_ERR(imx->clk_per));
256 return PTR_ERR(imx->clk_per);
257 }
169 258
170 if (IS_ERR(imx->clk)) 259 imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
171 return PTR_ERR(imx->clk); 260 if (IS_ERR(imx->clk_ipg)) {
261 dev_err(&pdev->dev, "getting ipg clock failed with %ld\n",
262 PTR_ERR(imx->clk_ipg));
263 return PTR_ERR(imx->clk_ipg);
264 }
172 265
173 imx->chip.ops = &imx_pwm_ops; 266 imx->chip.ops = &imx_pwm_ops;
174 imx->chip.dev = &pdev->dev; 267 imx->chip.dev = &pdev->dev;
175 imx->chip.base = -1; 268 imx->chip.base = -1;
176 imx->chip.npwm = 1; 269 imx->chip.npwm = 1;
177 270
178 imx->clk_enabled = 0;
179
180 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 271 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
181 if (r == NULL) { 272 if (r == NULL) {
182 dev_err(&pdev->dev, "no memory resource defined\n"); 273 dev_err(&pdev->dev, "no memory resource defined\n");
@@ -187,6 +278,10 @@ static int __devinit imx_pwm_probe(struct platform_device *pdev)
187 if (imx->mmio_base == NULL) 278 if (imx->mmio_base == NULL)
188 return -EADDRNOTAVAIL; 279 return -EADDRNOTAVAIL;
189 280
281 data = of_id->data;
282 imx->config = data->config;
283 imx->set_enable = data->set_enable;
284
190 ret = pwmchip_add(&imx->chip); 285 ret = pwmchip_add(&imx->chip);
191 if (ret < 0) 286 if (ret < 0)
192 return ret; 287 return ret;
@@ -208,23 +303,14 @@ static int __devexit imx_pwm_remove(struct platform_device *pdev)
208 303
209static struct platform_driver imx_pwm_driver = { 304static struct platform_driver imx_pwm_driver = {
210 .driver = { 305 .driver = {
211 .name = "mxc_pwm", 306 .name = "imx-pwm",
307 .of_match_table = of_match_ptr(imx_pwm_dt_ids),
212 }, 308 },
213 .probe = imx_pwm_probe, 309 .probe = imx_pwm_probe,
214 .remove = __devexit_p(imx_pwm_remove), 310 .remove = __devexit_p(imx_pwm_remove),
215}; 311};
216 312
217static int __init imx_pwm_init(void) 313module_platform_driver(imx_pwm_driver);
218{
219 return platform_driver_register(&imx_pwm_driver);
220}
221arch_initcall(imx_pwm_init);
222
223static void __exit imx_pwm_exit(void)
224{
225 platform_driver_unregister(&imx_pwm_driver);
226}
227module_exit(imx_pwm_exit);
228 314
229MODULE_LICENSE("GPL v2"); 315MODULE_LICENSE("GPL v2");
230MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); 316MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c
new file mode 100644
index 000000000000..10250fcefb98
--- /dev/null
+++ b/drivers/pwm/pwm-jz4740.c
@@ -0,0 +1,221 @@
1/*
2 * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
3 * JZ4740 platform PWM support
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * You should have received a copy of the GNU General Public License along
11 * with this program; if not, write to the Free Software Foundation, Inc.,
12 * 675 Mass Ave, Cambridge, MA 02139, USA.
13 *
14 */
15
16#include <linux/clk.h>
17#include <linux/err.h>
18#include <linux/gpio.h>
19#include <linux/kernel.h>
20#include <linux/module.h>
21#include <linux/platform_device.h>
22#include <linux/pwm.h>
23
24#include <asm/mach-jz4740/gpio.h>
25#include <asm/mach-jz4740/timer.h>
26
27#define NUM_PWM 8
28
29static const unsigned int jz4740_pwm_gpio_list[NUM_PWM] = {
30 JZ_GPIO_PWM0,
31 JZ_GPIO_PWM1,
32 JZ_GPIO_PWM2,
33 JZ_GPIO_PWM3,
34 JZ_GPIO_PWM4,
35 JZ_GPIO_PWM5,
36 JZ_GPIO_PWM6,
37 JZ_GPIO_PWM7,
38};
39
40struct jz4740_pwm_chip {
41 struct pwm_chip chip;
42 struct clk *clk;
43};
44
45static inline struct jz4740_pwm_chip *to_jz4740(struct pwm_chip *chip)
46{
47 return container_of(chip, struct jz4740_pwm_chip, chip);
48}
49
50static int jz4740_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
51{
52 unsigned int gpio = jz4740_pwm_gpio_list[pwm->hwpwm];
53 int ret;
54
55 /*
56 * Timers 0 and 1 are used for system tasks, so they are unavailable
57 * for use as PWMs.
58 */
59 if (pwm->hwpwm < 2)
60 return -EBUSY;
61
62 ret = gpio_request(gpio, pwm->label);
63 if (ret) {
64 dev_err(chip->dev, "Failed to request GPIO#%u for PWM: %d\n",
65 gpio, ret);
66 return ret;
67 }
68
69 jz_gpio_set_function(gpio, JZ_GPIO_FUNC_PWM);
70
71 jz4740_timer_start(pwm->hwpwm);
72
73 return 0;
74}
75
76static void jz4740_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
77{
78 unsigned int gpio = jz4740_pwm_gpio_list[pwm->hwpwm];
79
80 jz4740_timer_set_ctrl(pwm->hwpwm, 0);
81
82 jz_gpio_set_function(gpio, JZ_GPIO_FUNC_NONE);
83 gpio_free(gpio);
84
85 jz4740_timer_stop(pwm->hwpwm);
86}
87
88static int jz4740_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
89{
90 uint32_t ctrl = jz4740_timer_get_ctrl(pwm->pwm);
91
92 ctrl |= JZ_TIMER_CTRL_PWM_ENABLE;
93 jz4740_timer_set_ctrl(pwm->hwpwm, ctrl);
94 jz4740_timer_enable(pwm->hwpwm);
95
96 return 0;
97}
98
99static void jz4740_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
100{
101 uint32_t ctrl = jz4740_timer_get_ctrl(pwm->hwpwm);
102
103 ctrl &= ~JZ_TIMER_CTRL_PWM_ENABLE;
104 jz4740_timer_disable(pwm->hwpwm);
105 jz4740_timer_set_ctrl(pwm->hwpwm, ctrl);
106}
107
108static int jz4740_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
109 int duty_ns, int period_ns)
110{
111 struct jz4740_pwm_chip *jz4740 = to_jz4740(pwm->chip);
112 unsigned long long tmp;
113 unsigned long period, duty;
114 unsigned int prescaler = 0;
115 uint16_t ctrl;
116 bool is_enabled;
117
118 tmp = (unsigned long long)clk_get_rate(jz4740->clk) * period_ns;
119 do_div(tmp, 1000000000);
120 period = tmp;
121
122 while (period > 0xffff && prescaler < 6) {
123 period >>= 2;
124 ++prescaler;
125 }
126
127 if (prescaler == 6)
128 return -EINVAL;
129
130 tmp = (unsigned long long)period * duty_ns;
131 do_div(tmp, period_ns);
132 duty = period - tmp;
133
134 if (duty >= period)
135 duty = period - 1;
136
137 is_enabled = jz4740_timer_is_enabled(pwm->hwpwm);
138 if (is_enabled)
139 jz4740_pwm_disable(chip, pwm);
140
141 jz4740_timer_set_count(pwm->hwpwm, 0);
142 jz4740_timer_set_duty(pwm->hwpwm, duty);
143 jz4740_timer_set_period(pwm->hwpwm, period);
144
145 ctrl = JZ_TIMER_CTRL_PRESCALER(prescaler) | JZ_TIMER_CTRL_SRC_EXT |
146 JZ_TIMER_CTRL_PWM_ABBRUPT_SHUTDOWN;
147
148 jz4740_timer_set_ctrl(pwm->hwpwm, ctrl);
149
150 if (is_enabled)
151 jz4740_pwm_enable(chip, pwm);
152
153 return 0;
154}
155
156static const struct pwm_ops jz4740_pwm_ops = {
157 .request = jz4740_pwm_request,
158 .free = jz4740_pwm_free,
159 .config = jz4740_pwm_config,
160 .enable = jz4740_pwm_enable,
161 .disable = jz4740_pwm_disable,
162 .owner = THIS_MODULE,
163};
164
165static int __devinit jz4740_pwm_probe(struct platform_device *pdev)
166{
167 struct jz4740_pwm_chip *jz4740;
168 int ret;
169
170 jz4740 = devm_kzalloc(&pdev->dev, sizeof(*jz4740), GFP_KERNEL);
171 if (!jz4740)
172 return -ENOMEM;
173
174 jz4740->clk = clk_get(NULL, "ext");
175 if (IS_ERR(jz4740->clk))
176 return PTR_ERR(jz4740->clk);
177
178 jz4740->chip.dev = &pdev->dev;
179 jz4740->chip.ops = &jz4740_pwm_ops;
180 jz4740->chip.npwm = NUM_PWM;
181 jz4740->chip.base = -1;
182
183 ret = pwmchip_add(&jz4740->chip);
184 if (ret < 0) {
185 clk_put(jz4740->clk);
186 return ret;
187 }
188
189 platform_set_drvdata(pdev, jz4740);
190
191 return 0;
192}
193
194static int __devexit jz4740_pwm_remove(struct platform_device *pdev)
195{
196 struct jz4740_pwm_chip *jz4740 = platform_get_drvdata(pdev);
197 int ret;
198
199 ret = pwmchip_remove(&jz4740->chip);
200 if (ret < 0)
201 return ret;
202
203 clk_put(jz4740->clk);
204
205 return 0;
206}
207
208static struct platform_driver jz4740_pwm_driver = {
209 .driver = {
210 .name = "jz4740-pwm",
211 .owner = THIS_MODULE,
212 },
213 .probe = jz4740_pwm_probe,
214 .remove = __devexit_p(jz4740_pwm_remove),
215};
216module_platform_driver(jz4740_pwm_driver);
217
218MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
219MODULE_DESCRIPTION("Ingenic JZ4740 PWM driver");
220MODULE_ALIAS("platform:jz4740-pwm");
221MODULE_LICENSE("GPL");
diff --git a/drivers/pwm/pwm-puv3.c b/drivers/pwm/pwm-puv3.c
new file mode 100644
index 000000000000..2a93f37c46ad
--- /dev/null
+++ b/drivers/pwm/pwm-puv3.c
@@ -0,0 +1,161 @@
1/*
2 * linux/arch/unicore32/kernel/pwm.c
3 *
4 * Code specific to PKUnity SoC and UniCore ISA
5 *
6 * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
7 * Copyright (C) 2001-2010 Guan Xuetao
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/platform_device.h>
17#include <linux/slab.h>
18#include <linux/err.h>
19#include <linux/clk.h>
20#include <linux/io.h>
21#include <linux/pwm.h>
22
23#include <asm/div64.h>
24#include <mach/hardware.h>
25
26struct puv3_pwm_chip {
27 struct pwm_chip chip;
28 void __iomem *base;
29 struct clk *clk;
30 bool enabled;
31};
32
33static inline struct puv3_pwm_chip *to_puv3(struct pwm_chip *chip)
34{
35 return container_of(chip, struct puv3_pwm_chip, chip);
36}
37
38/*
39 * period_ns = 10^9 * (PRESCALE + 1) * (PV + 1) / PWM_CLK_RATE
40 * duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE
41 */
42static int puv3_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
43 int duty_ns, int period_ns)
44{
45 unsigned long period_cycles, prescale, pv, dc;
46 struct puv3_pwm_chip *puv3 = to_puv3(chip);
47 unsigned long long c;
48
49 c = clk_get_rate(puv3->clk);
50 c = c * period_ns;
51 do_div(c, 1000000000);
52 period_cycles = c;
53
54 if (period_cycles < 1)
55 period_cycles = 1;
56
57 prescale = (period_cycles - 1) / 1024;
58 pv = period_cycles / (prescale + 1) - 1;
59
60 if (prescale > 63)
61 return -EINVAL;
62
63 if (duty_ns == period_ns)
64 dc = OST_PWMDCCR_FDCYCLE;
65 else
66 dc = (pv + 1) * duty_ns / period_ns;
67
68 /*
69 * NOTE: the clock to PWM has to be enabled first
70 * before writing to the registers
71 */
72 clk_prepare_enable(puv3->clk);
73
74 writel(prescale, puv3->base + OST_PWM_PWCR);
75 writel(pv - dc, puv3->base + OST_PWM_DCCR);
76 writel(pv, puv3->base + OST_PWM_PCR);
77
78 clk_disable_unprepare(puv3->clk);
79
80 return 0;
81}
82
83static int puv3_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
84{
85 struct puv3_pwm_chip *puv3 = to_puv3(chip);
86
87 return clk_prepare_enable(puv3->clk);
88}
89
90static void puv3_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
91{
92 struct puv3_pwm_chip *puv3 = to_puv3(chip);
93
94 clk_disable_unprepare(puv3->clk);
95}
96
97static const struct pwm_ops puv3_pwm_ops = {
98 .config = puv3_pwm_config,
99 .enable = puv3_pwm_enable,
100 .disable = puv3_pwm_disable,
101 .owner = THIS_MODULE,
102};
103
104static int __devinit pwm_probe(struct platform_device *pdev)
105{
106 struct puv3_pwm_chip *puv3;
107 struct resource *r;
108 int ret;
109
110 puv3 = devm_kzalloc(&pdev->dev, sizeof(*puv3), GFP_KERNEL);
111 if (puv3 == NULL) {
112 dev_err(&pdev->dev, "failed to allocate memory\n");
113 return -ENOMEM;
114 }
115
116 puv3->clk = devm_clk_get(&pdev->dev, "OST_CLK");
117 if (IS_ERR(puv3->clk))
118 return PTR_ERR(puv3->clk);
119
120 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
121 if (r == NULL) {
122 dev_err(&pdev->dev, "no memory resource defined\n");
123 return -ENODEV;
124 }
125
126 puv3->base = devm_request_and_ioremap(&pdev->dev, r);
127 if (puv3->base == NULL)
128 return -EADDRNOTAVAIL;
129
130 puv3->chip.dev = &pdev->dev;
131 puv3->chip.ops = &puv3_pwm_ops;
132 puv3->chip.base = -1;
133 puv3->chip.npwm = 1;
134
135 ret = pwmchip_add(&puv3->chip);
136 if (ret < 0) {
137 dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
138 return ret;
139 }
140
141 platform_set_drvdata(pdev, puv3);
142 return 0;
143}
144
145static int __devexit pwm_remove(struct platform_device *pdev)
146{
147 struct puv3_pwm_chip *puv3 = platform_get_drvdata(pdev);
148
149 return pwmchip_remove(&puv3->chip);
150}
151
152static struct platform_driver puv3_pwm_driver = {
153 .driver = {
154 .name = "PKUnity-v3-PWM",
155 },
156 .probe = pwm_probe,
157 .remove = __devexit_p(pwm_remove),
158};
159module_platform_driver(puv3_pwm_driver);
160
161MODULE_LICENSE("GPL v2");
diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c
index bd5867a1c700..260c3a88564d 100644
--- a/drivers/pwm/pwm-pxa.c
+++ b/drivers/pwm/pwm-pxa.c
@@ -70,9 +70,6 @@ static int pxa_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
70 unsigned long offset; 70 unsigned long offset;
71 int rc; 71 int rc;
72 72
73 if (period_ns == 0 || duty_ns > period_ns)
74 return -EINVAL;
75
76 offset = pwm->hwpwm ? 0x10 : 0; 73 offset = pwm->hwpwm ? 0x10 : 0;
77 74
78 c = clk_get_rate(pc->clk); 75 c = clk_get_rate(pc->clk);
diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c
index e5187c0ade9f..023a3bee76e7 100644
--- a/drivers/pwm/pwm-samsung.c
+++ b/drivers/pwm/pwm-samsung.c
@@ -126,9 +126,6 @@ static int s3c_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
126 if (period_ns > NS_IN_HZ || duty_ns > NS_IN_HZ) 126 if (period_ns > NS_IN_HZ || duty_ns > NS_IN_HZ)
127 return -ERANGE; 127 return -ERANGE;
128 128
129 if (duty_ns > period_ns)
130 return -EINVAL;
131
132 if (period_ns == s3c->period_ns && 129 if (period_ns == s3c->period_ns &&
133 duty_ns == s3c->duty_ns) 130 duty_ns == s3c->duty_ns)
134 return 0; 131 return 0;
diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c
index 4b6688909fee..d6d4cf05565e 100644
--- a/drivers/pwm/pwm-tiecap.c
+++ b/drivers/pwm/pwm-tiecap.c
@@ -32,6 +32,7 @@
32#define CAP3 0x10 32#define CAP3 0x10
33#define CAP4 0x14 33#define CAP4 0x14
34#define ECCTL2 0x2A 34#define ECCTL2 0x2A
35#define ECCTL2_APWM_POL_LOW BIT(10)
35#define ECCTL2_APWM_MODE BIT(9) 36#define ECCTL2_APWM_MODE BIT(9)
36#define ECCTL2_SYNC_SEL_DISA (BIT(7) | BIT(6)) 37#define ECCTL2_SYNC_SEL_DISA (BIT(7) | BIT(6))
37#define ECCTL2_TSCTR_FREERUN BIT(4) 38#define ECCTL2_TSCTR_FREERUN BIT(4)
@@ -59,7 +60,7 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
59 unsigned long period_cycles, duty_cycles; 60 unsigned long period_cycles, duty_cycles;
60 unsigned int reg_val; 61 unsigned int reg_val;
61 62
62 if (period_ns < 0 || duty_ns < 0 || period_ns > NSEC_PER_SEC) 63 if (period_ns > NSEC_PER_SEC)
63 return -ERANGE; 64 return -ERANGE;
64 65
65 c = pc->clk_rate; 66 c = pc->clk_rate;
@@ -111,6 +112,26 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
111 return 0; 112 return 0;
112} 113}
113 114
115static int ecap_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
116 enum pwm_polarity polarity)
117{
118 struct ecap_pwm_chip *pc = to_ecap_pwm_chip(chip);
119 unsigned short reg_val;
120
121 pm_runtime_get_sync(pc->chip.dev);
122 reg_val = readw(pc->mmio_base + ECCTL2);
123 if (polarity == PWM_POLARITY_INVERSED)
124 /* Duty cycle defines LOW period of PWM */
125 reg_val |= ECCTL2_APWM_POL_LOW;
126 else
127 /* Duty cycle defines HIGH period of PWM */
128 reg_val &= ~ECCTL2_APWM_POL_LOW;
129
130 writew(reg_val, pc->mmio_base + ECCTL2);
131 pm_runtime_put_sync(pc->chip.dev);
132 return 0;
133}
134
114static int ecap_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 135static int ecap_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
115{ 136{
116 struct ecap_pwm_chip *pc = to_ecap_pwm_chip(chip); 137 struct ecap_pwm_chip *pc = to_ecap_pwm_chip(chip);
@@ -157,6 +178,7 @@ static void ecap_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
157static const struct pwm_ops ecap_pwm_ops = { 178static const struct pwm_ops ecap_pwm_ops = {
158 .free = ecap_pwm_free, 179 .free = ecap_pwm_free,
159 .config = ecap_pwm_config, 180 .config = ecap_pwm_config,
181 .set_polarity = ecap_pwm_set_polarity,
160 .enable = ecap_pwm_enable, 182 .enable = ecap_pwm_enable,
161 .disable = ecap_pwm_disable, 183 .disable = ecap_pwm_disable,
162 .owner = THIS_MODULE, 184 .owner = THIS_MODULE,
diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
index b1996bcd5b78..d3c1dff0a0dc 100644
--- a/drivers/pwm/pwm-tiehrpwm.c
+++ b/drivers/pwm/pwm-tiehrpwm.c
@@ -81,6 +81,15 @@
81#define AQCTL_ZRO_FRCHIGH BIT(1) 81#define AQCTL_ZRO_FRCHIGH BIT(1)
82#define AQCTL_ZRO_FRCTOGGLE (BIT(1) | BIT(0)) 82#define AQCTL_ZRO_FRCTOGGLE (BIT(1) | BIT(0))
83 83
84#define AQCTL_CHANA_POLNORMAL (AQCTL_CAU_FRCLOW | AQCTL_PRD_FRCHIGH | \
85 AQCTL_ZRO_FRCHIGH)
86#define AQCTL_CHANA_POLINVERSED (AQCTL_CAU_FRCHIGH | AQCTL_PRD_FRCLOW | \
87 AQCTL_ZRO_FRCLOW)
88#define AQCTL_CHANB_POLNORMAL (AQCTL_CBU_FRCLOW | AQCTL_PRD_FRCHIGH | \
89 AQCTL_ZRO_FRCHIGH)
90#define AQCTL_CHANB_POLINVERSED (AQCTL_CBU_FRCHIGH | AQCTL_PRD_FRCLOW | \
91 AQCTL_ZRO_FRCLOW)
92
84#define AQSFRC_RLDCSF_MASK (BIT(7) | BIT(6)) 93#define AQSFRC_RLDCSF_MASK (BIT(7) | BIT(6))
85#define AQSFRC_RLDCSF_ZRO 0 94#define AQSFRC_RLDCSF_ZRO 0
86#define AQSFRC_RLDCSF_PRD BIT(6) 95#define AQSFRC_RLDCSF_PRD BIT(6)
@@ -105,6 +114,7 @@ struct ehrpwm_pwm_chip {
105 unsigned int clk_rate; 114 unsigned int clk_rate;
106 void __iomem *mmio_base; 115 void __iomem *mmio_base;
107 unsigned long period_cycles[NUM_PWM_CHANNEL]; 116 unsigned long period_cycles[NUM_PWM_CHANNEL];
117 enum pwm_polarity polarity[NUM_PWM_CHANNEL];
108}; 118};
109 119
110static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip) 120static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip)
@@ -165,39 +175,37 @@ static int set_prescale_div(unsigned long rqst_prescaler,
165 return 1; 175 return 1;
166} 176}
167 177
168static void configure_chans(struct ehrpwm_pwm_chip *pc, int chan, 178static void configure_polarity(struct ehrpwm_pwm_chip *pc, int chan)
169 unsigned long duty_cycles)
170{ 179{
171 int cmp_reg, aqctl_reg; 180 int aqctl_reg;
172 unsigned short aqctl_val, aqctl_mask; 181 unsigned short aqctl_val, aqctl_mask;
173 182
174 /* 183 /*
175 * Channels can be configured from action qualifier module. 184 * Configure PWM output to HIGH/LOW level on counter
176 * Channel 0 configured with compare A register and for 185 * reaches compare register value and LOW/HIGH level
177 * up-counter mode. 186 * on counter value reaches period register value and
178 * Channel 1 configured with compare B register and for 187 * zero value on counter
179 * up-counter mode.
180 */ 188 */
181 if (chan == 1) { 189 if (chan == 1) {
182 aqctl_reg = AQCTLB; 190 aqctl_reg = AQCTLB;
183 cmp_reg = CMPB;
184 /* Configure PWM Low from compare B value */
185 aqctl_val = AQCTL_CBU_FRCLOW;
186 aqctl_mask = AQCTL_CBU_MASK; 191 aqctl_mask = AQCTL_CBU_MASK;
192
193 if (pc->polarity[chan] == PWM_POLARITY_INVERSED)
194 aqctl_val = AQCTL_CHANB_POLINVERSED;
195 else
196 aqctl_val = AQCTL_CHANB_POLNORMAL;
187 } else { 197 } else {
188 cmp_reg = CMPA;
189 aqctl_reg = AQCTLA; 198 aqctl_reg = AQCTLA;
190 /* Configure PWM Low from compare A value*/
191 aqctl_val = AQCTL_CAU_FRCLOW;
192 aqctl_mask = AQCTL_CAU_MASK; 199 aqctl_mask = AQCTL_CAU_MASK;
200
201 if (pc->polarity[chan] == PWM_POLARITY_INVERSED)
202 aqctl_val = AQCTL_CHANA_POLINVERSED;
203 else
204 aqctl_val = AQCTL_CHANA_POLNORMAL;
193 } 205 }
194 206
195 /* Configure PWM High from period value and zero value */
196 aqctl_val |= AQCTL_PRD_FRCHIGH | AQCTL_ZRO_FRCHIGH;
197 aqctl_mask |= AQCTL_PRD_MASK | AQCTL_ZRO_MASK; 207 aqctl_mask |= AQCTL_PRD_MASK | AQCTL_ZRO_MASK;
198 ehrpwm_modify(pc->mmio_base, aqctl_reg, aqctl_mask, aqctl_val); 208 ehrpwm_modify(pc->mmio_base, aqctl_reg, aqctl_mask, aqctl_val);
199
200 ehrpwm_write(pc->mmio_base, cmp_reg, duty_cycles);
201} 209}
202 210
203/* 211/*
@@ -211,9 +219,9 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
211 unsigned long long c; 219 unsigned long long c;
212 unsigned long period_cycles, duty_cycles; 220 unsigned long period_cycles, duty_cycles;
213 unsigned short ps_divval, tb_divval; 221 unsigned short ps_divval, tb_divval;
214 int i; 222 int i, cmp_reg;
215 223
216 if (period_ns < 0 || duty_ns < 0 || period_ns > NSEC_PER_SEC) 224 if (period_ns > NSEC_PER_SEC)
217 return -ERANGE; 225 return -ERANGE;
218 226
219 c = pc->clk_rate; 227 c = pc->clk_rate;
@@ -278,12 +286,29 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
278 ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_CTRMODE_MASK, 286 ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_CTRMODE_MASK,
279 TBCTL_CTRMODE_UP); 287 TBCTL_CTRMODE_UP);
280 288
281 /* Configure the channel for duty cycle */ 289 if (pwm->hwpwm == 1)
282 configure_chans(pc, pwm->hwpwm, duty_cycles); 290 /* Channel 1 configured with compare B register */
291 cmp_reg = CMPB;
292 else
293 /* Channel 0 configured with compare A register */
294 cmp_reg = CMPA;
295
296 ehrpwm_write(pc->mmio_base, cmp_reg, duty_cycles);
297
283 pm_runtime_put_sync(chip->dev); 298 pm_runtime_put_sync(chip->dev);
284 return 0; 299 return 0;
285} 300}
286 301
302static int ehrpwm_pwm_set_polarity(struct pwm_chip *chip,
303 struct pwm_device *pwm, enum pwm_polarity polarity)
304{
305 struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
306
307 /* Configuration of polarity in hardware delayed, do at enable */
308 pc->polarity[pwm->hwpwm] = polarity;
309 return 0;
310}
311
287static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 312static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
288{ 313{
289 struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); 314 struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
@@ -307,6 +332,9 @@ static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
307 332
308 ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val); 333 ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val);
309 334
335 /* Channels polarity can be configured from action qualifier module */
336 configure_polarity(pc, pwm->hwpwm);
337
310 /* Enable time counter for free_run */ 338 /* Enable time counter for free_run */
311 ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_FREE_RUN); 339 ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_FREE_RUN);
312 return 0; 340 return 0;
@@ -358,6 +386,7 @@ static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
358static const struct pwm_ops ehrpwm_pwm_ops = { 386static const struct pwm_ops ehrpwm_pwm_ops = {
359 .free = ehrpwm_pwm_free, 387 .free = ehrpwm_pwm_free,
360 .config = ehrpwm_pwm_config, 388 .config = ehrpwm_pwm_config,
389 .set_polarity = ehrpwm_pwm_set_polarity,
361 .enable = ehrpwm_pwm_enable, 390 .enable = ehrpwm_pwm_enable,
362 .disable = ehrpwm_pwm_disable, 391 .disable = ehrpwm_pwm_disable,
363 .owner = THIS_MODULE, 392 .owner = THIS_MODULE,
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index 995f0164c9b0..069983ca49ff 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -213,7 +213,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
213 pb->exit = data->exit; 213 pb->exit = data->exit;
214 pb->dev = &pdev->dev; 214 pb->dev = &pdev->dev;
215 215
216 pb->pwm = pwm_get(&pdev->dev, NULL); 216 pb->pwm = devm_pwm_get(&pdev->dev, NULL);
217 if (IS_ERR(pb->pwm)) { 217 if (IS_ERR(pb->pwm)) {
218 dev_err(&pdev->dev, "unable to request PWM, trying legacy API\n"); 218 dev_err(&pdev->dev, "unable to request PWM, trying legacy API\n");
219 219
@@ -246,7 +246,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
246 if (IS_ERR(bl)) { 246 if (IS_ERR(bl)) {
247 dev_err(&pdev->dev, "failed to register backlight\n"); 247 dev_err(&pdev->dev, "failed to register backlight\n");
248 ret = PTR_ERR(bl); 248 ret = PTR_ERR(bl);
249 goto err_bl; 249 goto err_alloc;
250 } 250 }
251 251
252 bl->props.brightness = data->dft_brightness; 252 bl->props.brightness = data->dft_brightness;
@@ -255,8 +255,6 @@ static int pwm_backlight_probe(struct platform_device *pdev)
255 platform_set_drvdata(pdev, bl); 255 platform_set_drvdata(pdev, bl);
256 return 0; 256 return 0;
257 257
258err_bl:
259 pwm_put(pb->pwm);
260err_alloc: 258err_alloc:
261 if (data->exit) 259 if (data->exit)
262 data->exit(&pdev->dev); 260 data->exit(&pdev->dev);
@@ -271,7 +269,6 @@ static int pwm_backlight_remove(struct platform_device *pdev)
271 backlight_device_unregister(bl); 269 backlight_device_unregister(bl);
272 pwm_config(pb->pwm, 0, pb->period); 270 pwm_config(pb->pwm, 0, pb->period);
273 pwm_disable(pb->pwm); 271 pwm_disable(pb->pwm);
274 pwm_put(pb->pwm);
275 if (pb->exit) 272 if (pb->exit)
276 pb->exit(&pdev->dev); 273 pb->exit(&pdev->dev);
277 return 0; 274 return 0;
diff --git a/include/linux/pwm.h b/include/linux/pwm.h
index 21d076c5089e..112b31436848 100644
--- a/include/linux/pwm.h
+++ b/include/linux/pwm.h
@@ -1,11 +1,13 @@
1#ifndef __LINUX_PWM_H 1#ifndef __LINUX_PWM_H
2#define __LINUX_PWM_H 2#define __LINUX_PWM_H
3 3
4#include <linux/err.h>
4#include <linux/of.h> 5#include <linux/of.h>
5 6
6struct pwm_device; 7struct pwm_device;
7struct seq_file; 8struct seq_file;
8 9
10#if IS_ENABLED(CONFIG_PWM) || IS_ENABLED(CONFIG_HAVE_PWM)
9/* 11/*
10 * pwm_request - request a PWM device 12 * pwm_request - request a PWM device
11 */ 13 */
@@ -30,10 +32,47 @@ int pwm_enable(struct pwm_device *pwm);
30 * pwm_disable - stop a PWM output toggling 32 * pwm_disable - stop a PWM output toggling
31 */ 33 */
32void pwm_disable(struct pwm_device *pwm); 34void pwm_disable(struct pwm_device *pwm);
35#else
36static inline struct pwm_device *pwm_request(int pwm_id, const char *label)
37{
38 return ERR_PTR(-ENODEV);
39}
40
41static inline void pwm_free(struct pwm_device *pwm)
42{
43}
44
45static inline int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
46{
47 return -EINVAL;
48}
49
50static inline int pwm_enable(struct pwm_device *pwm)
51{
52 return -EINVAL;
53}
54
55static inline void pwm_disable(struct pwm_device *pwm)
56{
57}
58#endif
33 59
34#ifdef CONFIG_PWM
35struct pwm_chip; 60struct pwm_chip;
36 61
62/**
63 * enum pwm_polarity - polarity of a PWM signal
64 * @PWM_POLARITY_NORMAL: a high signal for the duration of the duty-
65 * cycle, followed by a low signal for the remainder of the pulse
66 * period
67 * @PWM_POLARITY_INVERSED: a low signal for the duration of the duty-
68 * cycle, followed by a high signal for the remainder of the pulse
69 * period
70 */
71enum pwm_polarity {
72 PWM_POLARITY_NORMAL,
73 PWM_POLARITY_INVERSED,
74};
75
37enum { 76enum {
38 PWMF_REQUESTED = 1 << 0, 77 PWMF_REQUESTED = 1 << 0,
39 PWMF_ENABLED = 1 << 1, 78 PWMF_ENABLED = 1 << 1,
@@ -61,11 +100,17 @@ static inline unsigned int pwm_get_period(struct pwm_device *pwm)
61 return pwm ? pwm->period : 0; 100 return pwm ? pwm->period : 0;
62} 101}
63 102
103/*
104 * pwm_set_polarity - configure the polarity of a PWM signal
105 */
106int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity);
107
64/** 108/**
65 * struct pwm_ops - PWM controller operations 109 * struct pwm_ops - PWM controller operations
66 * @request: optional hook for requesting a PWM 110 * @request: optional hook for requesting a PWM
67 * @free: optional hook for freeing a PWM 111 * @free: optional hook for freeing a PWM
68 * @config: configure duty cycles and period length for this PWM 112 * @config: configure duty cycles and period length for this PWM
113 * @set_polarity: configure the polarity of this PWM
69 * @enable: enable PWM output toggling 114 * @enable: enable PWM output toggling
70 * @disable: disable PWM output toggling 115 * @disable: disable PWM output toggling
71 * @dbg_show: optional routine to show contents in debugfs 116 * @dbg_show: optional routine to show contents in debugfs
@@ -79,6 +124,9 @@ struct pwm_ops {
79 int (*config)(struct pwm_chip *chip, 124 int (*config)(struct pwm_chip *chip,
80 struct pwm_device *pwm, 125 struct pwm_device *pwm,
81 int duty_ns, int period_ns); 126 int duty_ns, int period_ns);
127 int (*set_polarity)(struct pwm_chip *chip,
128 struct pwm_device *pwm,
129 enum pwm_polarity polarity);
82 int (*enable)(struct pwm_chip *chip, 130 int (*enable)(struct pwm_chip *chip,
83 struct pwm_device *pwm); 131 struct pwm_device *pwm);
84 void (*disable)(struct pwm_chip *chip, 132 void (*disable)(struct pwm_chip *chip,
@@ -113,6 +161,7 @@ struct pwm_chip {
113 unsigned int of_pwm_n_cells; 161 unsigned int of_pwm_n_cells;
114}; 162};
115 163
164#if IS_ENABLED(CONFIG_PWM)
116int pwm_set_chip_data(struct pwm_device *pwm, void *data); 165int pwm_set_chip_data(struct pwm_device *pwm, void *data);
117void *pwm_get_chip_data(struct pwm_device *pwm); 166void *pwm_get_chip_data(struct pwm_device *pwm);
118 167
@@ -125,6 +174,57 @@ struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
125struct pwm_device *pwm_get(struct device *dev, const char *consumer); 174struct pwm_device *pwm_get(struct device *dev, const char *consumer);
126void pwm_put(struct pwm_device *pwm); 175void pwm_put(struct pwm_device *pwm);
127 176
177struct pwm_device *devm_pwm_get(struct device *dev, const char *consumer);
178void devm_pwm_put(struct device *dev, struct pwm_device *pwm);
179#else
180static inline int pwm_set_chip_data(struct pwm_device *pwm, void *data)
181{
182 return -EINVAL;
183}
184
185static inline void *pwm_get_chip_data(struct pwm_device *pwm)
186{
187 return NULL;
188}
189
190static inline int pwmchip_add(struct pwm_chip *chip)
191{
192 return -EINVAL;
193}
194
195static inline int pwmchip_remove(struct pwm_chip *chip)
196{
197 return -EINVAL;
198}
199
200static inline struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
201 unsigned int index,
202 const char *label)
203{
204 return ERR_PTR(-ENODEV);
205}
206
207static inline struct pwm_device *pwm_get(struct device *dev,
208 const char *consumer)
209{
210 return ERR_PTR(-ENODEV);
211}
212
213static inline void pwm_put(struct pwm_device *pwm)
214{
215}
216
217static inline struct pwm_device *devm_pwm_get(struct device *dev,
218 const char *consumer)
219{
220 return ERR_PTR(-ENODEV);
221}
222
223static inline void devm_pwm_put(struct device *dev, struct pwm_device *pwm)
224{
225}
226#endif
227
128struct pwm_lookup { 228struct pwm_lookup {
129 struct list_head list; 229 struct list_head list;
130 const char *provider; 230 const char *provider;
@@ -141,8 +241,12 @@ struct pwm_lookup {
141 .con_id = _con_id, \ 241 .con_id = _con_id, \
142 } 242 }
143 243
244#if IS_ENABLED(CONFIG_PWM)
144void pwm_add_table(struct pwm_lookup *table, size_t num); 245void pwm_add_table(struct pwm_lookup *table, size_t num);
145 246#else
247static inline void pwm_add_table(struct pwm_lookup *table, size_t num)
248{
249}
146#endif 250#endif
147 251
148#endif /* __LINUX_PWM_H */ 252#endif /* __LINUX_PWM_H */