aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm-samsung.txt2
-rw-r--r--Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt7
-rw-r--r--Documentation/pwm.txt4
-rw-r--r--MAINTAINERS3
-rw-r--r--arch/arm/mach-pxa/cm-x300.c1
-rw-r--r--arch/arm/mach-pxa/colibri-pxa270-income.c1
-rw-r--r--arch/arm/mach-pxa/ezx.c1
-rw-r--r--arch/arm/mach-pxa/hx4700.c1
-rw-r--r--arch/arm/mach-pxa/lpd270.c1
-rw-r--r--arch/arm/mach-pxa/magician.c1
-rw-r--r--arch/arm/mach-pxa/mainstone.c1
-rw-r--r--arch/arm/mach-pxa/mioa701.c1
-rw-r--r--arch/arm/mach-pxa/palm27x.c1
-rw-r--r--arch/arm/mach-pxa/palmtc.c35
-rw-r--r--arch/arm/mach-pxa/palmte2.c1
-rw-r--r--arch/arm/mach-pxa/pcm990-baseboard.c1
-rw-r--r--arch/arm/mach-pxa/raumfeld.c1
-rw-r--r--arch/arm/mach-pxa/tavorevb.c2
-rw-r--r--arch/arm/mach-pxa/viper.c1
-rw-r--r--arch/arm/mach-pxa/z2.c2
-rw-r--r--arch/arm/mach-pxa/zylonite.c1
-rw-r--r--arch/arm/mach-s3c24xx/mach-h1940.c1
-rw-r--r--arch/arm/mach-s3c24xx/mach-rx1950.c1
-rw-r--r--arch/arm/mach-s3c64xx/mach-crag6410.c1
-rw-r--r--arch/arm/mach-s3c64xx/mach-hmt.c1
-rw-r--r--arch/arm/mach-s3c64xx/mach-smartq.c1
-rw-r--r--arch/arm/mach-s3c64xx/mach-smdk6410.c1
-rw-r--r--arch/arm/mach-s5p64x0/mach-smdk6440.c1
-rw-r--r--arch/arm/mach-s5p64x0/mach-smdk6450.c1
-rw-r--r--arch/arm/mach-s5pc100/mach-smdkc100.c1
-rw-r--r--arch/arm/mach-s5pv210/mach-smdkv210.c1
-rw-r--r--arch/arm/mach-shmobile/board-armadillo800eva.c1
-rw-r--r--arch/arm/plat-samsung/dev-backlight.c5
-rw-r--r--arch/unicore32/kernel/puv3-nb0916.c1
-rw-r--r--drivers/misc/Kconfig13
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/ep93xx_pwm.c286
-rw-r--r--drivers/pwm/Kconfig9
-rw-r--r--drivers/pwm/Makefile1
-rw-r--r--drivers/pwm/pwm-atmel-tcb.c4
-rw-r--r--drivers/pwm/pwm-ep93xx.c230
-rw-r--r--drivers/pwm/pwm-imx.c3
-rw-r--r--drivers/pwm/pwm-lpc32xx.c2
-rw-r--r--drivers/pwm/pwm-mxs.c2
-rw-r--r--drivers/pwm/pwm-samsung.c3
-rw-r--r--drivers/pwm/pwm-tiecap.c6
-rw-r--r--drivers/pwm/pwm-tiehrpwm.c6
-rw-r--r--drivers/pwm/pwm-twl-led.c1
-rw-r--r--drivers/pwm/pwm-twl.c1
-rw-r--r--drivers/video/backlight/pwm_bl.c166
-rw-r--r--include/linux/pwm_backlight.h5
51 files changed, 433 insertions, 392 deletions
diff --git a/Documentation/devicetree/bindings/pwm/pwm-samsung.txt b/Documentation/devicetree/bindings/pwm/pwm-samsung.txt
index d61fccd40bad..5538de9c2007 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-samsung.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-samsung.txt
@@ -15,7 +15,7 @@ Required properties:
15 samsung,s5pc100-pwm - for 32-bit timers present on S5PC100, S5PV210, 15 samsung,s5pc100-pwm - for 32-bit timers present on S5PC100, S5PV210,
16 Exynos4210 rev0 SoCs 16 Exynos4210 rev0 SoCs
17 samsung,exynos4210-pwm - for 32-bit timers present on Exynos4210, 17 samsung,exynos4210-pwm - for 32-bit timers present on Exynos4210,
18 Exynos4x12 and Exynos5250 SoCs 18 Exynos4x12, Exynos5250 and Exynos5420 SoCs
19- reg: base address and size of register area 19- reg: base address and size of register area
20- interrupts: list of timer interrupts (one interrupt per timer, starting at 20- interrupts: list of timer interrupts (one interrupt per timer, starting at
21 timer 0) 21 timer 0)
diff --git a/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt b/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt
index 1e4fc727f3b1..764db86d441a 100644
--- a/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt
+++ b/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt
@@ -10,12 +10,16 @@ Required properties:
10 last value in the array represents a 100% duty cycle (brightest). 10 last value in the array represents a 100% duty cycle (brightest).
11 - default-brightness-level: the default brightness level (index into the 11 - default-brightness-level: the default brightness level (index into the
12 array defined by the "brightness-levels" property) 12 array defined by the "brightness-levels" property)
13 - power-supply: regulator for supply voltage
13 14
14Optional properties: 15Optional properties:
15 - pwm-names: a list of names for the PWM devices specified in the 16 - pwm-names: a list of names for the PWM devices specified in the
16 "pwms" property (see PWM binding[0]) 17 "pwms" property (see PWM binding[0])
18 - enable-gpios: contains a single GPIO specifier for the GPIO which enables
19 and disables the backlight (see GPIO binding[1])
17 20
18[0]: Documentation/devicetree/bindings/pwm/pwm.txt 21[0]: Documentation/devicetree/bindings/pwm/pwm.txt
22[1]: Documentation/devicetree/bindings/gpio/gpio.txt
19 23
20Example: 24Example:
21 25
@@ -25,4 +29,7 @@ Example:
25 29
26 brightness-levels = <0 4 8 16 32 64 128 255>; 30 brightness-levels = <0 4 8 16 32 64 128 255>;
27 default-brightness-level = <6>; 31 default-brightness-level = <6>;
32
33 power-supply = <&vdd_bl_reg>;
34 enable-gpios = <&gpio 58 0>;
28 }; 35 };
diff --git a/Documentation/pwm.txt b/Documentation/pwm.txt
index 1039b68fe9c6..93cb97974986 100644
--- a/Documentation/pwm.txt
+++ b/Documentation/pwm.txt
@@ -39,7 +39,7 @@ New 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. Managed 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. 40variants of these functions, devm_pwm_get() and devm_pwm_put(), also exist.
41 41
42After being requested a PWM has to be configured using: 42After being requested, a PWM has to be configured using:
43 43
44int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns); 44int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns);
45 45
@@ -94,7 +94,7 @@ for new drivers to use the generic PWM framework.
94A new PWM controller/chip can be added using pwmchip_add() and removed 94A new PWM controller/chip can be added using pwmchip_add() and removed
95again with pwmchip_remove(). pwmchip_add() takes a filled in struct 95again with pwmchip_remove(). pwmchip_add() takes a filled in struct
96pwm_chip as argument which provides a description of the PWM chip, the 96pwm_chip as argument which provides a description of the PWM chip, the
97number of PWM devices provider by the chip and the chip-specific 97number of PWM devices provided by the chip and the chip-specific
98implementation of the supported PWM operations to the framework. 98implementation of the supported PWM operations to the framework.
99 99
100Locking 100Locking
diff --git a/MAINTAINERS b/MAINTAINERS
index aef332323256..88bc6edee262 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6785,8 +6785,7 @@ PWM SUBSYSTEM
6785M: Thierry Reding <thierry.reding@gmail.com> 6785M: Thierry Reding <thierry.reding@gmail.com>
6786L: linux-pwm@vger.kernel.org 6786L: linux-pwm@vger.kernel.org
6787S: Maintained 6787S: Maintained
6788W: http://gitorious.org/linux-pwm 6788T: git git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm.git
6789T: git git://gitorious.org/linux-pwm/linux-pwm.git
6790F: Documentation/pwm.txt 6789F: Documentation/pwm.txt
6791F: Documentation/devicetree/bindings/pwm/ 6790F: Documentation/devicetree/bindings/pwm/
6792F: include/linux/pwm.h 6791F: include/linux/pwm.h
diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index f9423493ed36..584439bfa59f 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -310,6 +310,7 @@ static struct platform_pwm_backlight_data cm_x300_backlight_data = {
310 .max_brightness = 100, 310 .max_brightness = 100,
311 .dft_brightness = 100, 311 .dft_brightness = 100,
312 .pwm_period_ns = 10000, 312 .pwm_period_ns = 10000,
313 .enable_gpio = -1,
313}; 314};
314 315
315static struct platform_device cm_x300_backlight_device = { 316static struct platform_device cm_x300_backlight_device = {
diff --git a/arch/arm/mach-pxa/colibri-pxa270-income.c b/arch/arm/mach-pxa/colibri-pxa270-income.c
index 2d4a7b4d5d78..3aa264640c9d 100644
--- a/arch/arm/mach-pxa/colibri-pxa270-income.c
+++ b/arch/arm/mach-pxa/colibri-pxa270-income.c
@@ -189,6 +189,7 @@ static struct platform_pwm_backlight_data income_backlight_data = {
189 .max_brightness = 0x3ff, 189 .max_brightness = 0x3ff,
190 .dft_brightness = 0x1ff, 190 .dft_brightness = 0x1ff,
191 .pwm_period_ns = 1000000, 191 .pwm_period_ns = 1000000,
192 .enable_gpio = -1,
192}; 193};
193 194
194static struct platform_device income_backlight = { 195static struct platform_device income_backlight = {
diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c
index fe2eb8394dff..ab93441e596e 100644
--- a/arch/arm/mach-pxa/ezx.c
+++ b/arch/arm/mach-pxa/ezx.c
@@ -54,6 +54,7 @@ static struct platform_pwm_backlight_data ezx_backlight_data = {
54 .max_brightness = 1023, 54 .max_brightness = 1023,
55 .dft_brightness = 1023, 55 .dft_brightness = 1023,
56 .pwm_period_ns = 78770, 56 .pwm_period_ns = 78770,
57 .enable_gpio = -1,
57}; 58};
58 59
59static struct platform_device ezx_backlight_device = { 60static struct platform_device ezx_backlight_device = {
diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c
index 133109ec7332..a7c30eb0c8db 100644
--- a/arch/arm/mach-pxa/hx4700.c
+++ b/arch/arm/mach-pxa/hx4700.c
@@ -561,6 +561,7 @@ static struct platform_pwm_backlight_data backlight_data = {
561 .max_brightness = 200, 561 .max_brightness = 200,
562 .dft_brightness = 100, 562 .dft_brightness = 100,
563 .pwm_period_ns = 30923, 563 .pwm_period_ns = 30923,
564 .enable_gpio = -1,
564}; 565};
565 566
566static struct platform_device backlight = { 567static struct platform_device backlight = {
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
index 1255ee00f3d1..9f6ec167902a 100644
--- a/arch/arm/mach-pxa/lpd270.c
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -269,6 +269,7 @@ static struct platform_pwm_backlight_data lpd270_backlight_data = {
269 .max_brightness = 1, 269 .max_brightness = 1,
270 .dft_brightness = 1, 270 .dft_brightness = 1,
271 .pwm_period_ns = 78770, 271 .pwm_period_ns = 78770,
272 .enable_gpio = -1,
272}; 273};
273 274
274static struct platform_device lpd270_backlight_device = { 275static struct platform_device lpd270_backlight_device = {
diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
index f44532fc648b..fab30d666cc7 100644
--- a/arch/arm/mach-pxa/magician.c
+++ b/arch/arm/mach-pxa/magician.c
@@ -378,6 +378,7 @@ static struct platform_pwm_backlight_data backlight_data = {
378 .max_brightness = 272, 378 .max_brightness = 272,
379 .dft_brightness = 100, 379 .dft_brightness = 100,
380 .pwm_period_ns = 30923, 380 .pwm_period_ns = 30923,
381 .enable_gpio = -1,
381 .init = magician_backlight_init, 382 .init = magician_backlight_init,
382 .notify = magician_backlight_notify, 383 .notify = magician_backlight_notify,
383 .exit = magician_backlight_exit, 384 .exit = magician_backlight_exit,
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index dd70343c8708..08ccc0718f31 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -338,6 +338,7 @@ static struct platform_pwm_backlight_data mainstone_backlight_data = {
338 .max_brightness = 1023, 338 .max_brightness = 1023,
339 .dft_brightness = 1023, 339 .dft_brightness = 1023,
340 .pwm_period_ns = 78770, 340 .pwm_period_ns = 78770,
341 .enable_gpio = -1,
341}; 342};
342 343
343static struct platform_device mainstone_backlight_device = { 344static struct platform_device mainstone_backlight_device = {
diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
index acc9d3cc0762..f70583fee59f 100644
--- a/arch/arm/mach-pxa/mioa701.c
+++ b/arch/arm/mach-pxa/mioa701.c
@@ -186,6 +186,7 @@ static struct platform_pwm_backlight_data mioa701_backlight_data = {
186 .max_brightness = 100, 186 .max_brightness = 100,
187 .dft_brightness = 50, 187 .dft_brightness = 50,
188 .pwm_period_ns = 4000 * 1024, /* Fl = 250kHz */ 188 .pwm_period_ns = 4000 * 1024, /* Fl = 250kHz */
189 .enable_gpio = -1,
189}; 190};
190 191
191/* 192/*
diff --git a/arch/arm/mach-pxa/palm27x.c b/arch/arm/mach-pxa/palm27x.c
index 17d4c53017ca..e54a296fb81f 100644
--- a/arch/arm/mach-pxa/palm27x.c
+++ b/arch/arm/mach-pxa/palm27x.c
@@ -322,6 +322,7 @@ static struct platform_pwm_backlight_data palm27x_backlight_data = {
322 .max_brightness = 0xfe, 322 .max_brightness = 0xfe,
323 .dft_brightness = 0x7e, 323 .dft_brightness = 0x7e,
324 .pwm_period_ns = 3500 * 1024, 324 .pwm_period_ns = 3500 * 1024,
325 .enable_gpio = -1,
325 .init = palm27x_backlight_init, 326 .init = palm27x_backlight_init,
326 .notify = palm27x_backlight_notify, 327 .notify = palm27x_backlight_notify,
327 .exit = palm27x_backlight_exit, 328 .exit = palm27x_backlight_exit,
diff --git a/arch/arm/mach-pxa/palmtc.c b/arch/arm/mach-pxa/palmtc.c
index 100b176f7e88..7691c974ca4b 100644
--- a/arch/arm/mach-pxa/palmtc.c
+++ b/arch/arm/mach-pxa/palmtc.c
@@ -166,45 +166,12 @@ static inline void palmtc_keys_init(void) {}
166 * Backlight 166 * Backlight
167 ******************************************************************************/ 167 ******************************************************************************/
168#if defined(CONFIG_BACKLIGHT_PWM) || defined(CONFIG_BACKLIGHT_PWM_MODULE) 168#if defined(CONFIG_BACKLIGHT_PWM) || defined(CONFIG_BACKLIGHT_PWM_MODULE)
169static int palmtc_backlight_init(struct device *dev)
170{
171 int ret;
172
173 ret = gpio_request(GPIO_NR_PALMTC_BL_POWER, "BL POWER");
174 if (ret)
175 goto err;
176 ret = gpio_direction_output(GPIO_NR_PALMTC_BL_POWER, 1);
177 if (ret)
178 goto err2;
179
180 return 0;
181
182err2:
183 gpio_free(GPIO_NR_PALMTC_BL_POWER);
184err:
185 return ret;
186}
187
188static int palmtc_backlight_notify(struct device *dev, int brightness)
189{
190 /* backlight is on when GPIO16 AF0 is high */
191 gpio_set_value(GPIO_NR_PALMTC_BL_POWER, brightness);
192 return brightness;
193}
194
195static void palmtc_backlight_exit(struct device *dev)
196{
197 gpio_free(GPIO_NR_PALMTC_BL_POWER);
198}
199
200static struct platform_pwm_backlight_data palmtc_backlight_data = { 169static struct platform_pwm_backlight_data palmtc_backlight_data = {
201 .pwm_id = 1, 170 .pwm_id = 1,
202 .max_brightness = PALMTC_MAX_INTENSITY, 171 .max_brightness = PALMTC_MAX_INTENSITY,
203 .dft_brightness = PALMTC_MAX_INTENSITY, 172 .dft_brightness = PALMTC_MAX_INTENSITY,
204 .pwm_period_ns = PALMTC_PERIOD_NS, 173 .pwm_period_ns = PALMTC_PERIOD_NS,
205 .init = palmtc_backlight_init, 174 .enable_gpio = GPIO_NR_PALMTC_BL_POWER,
206 .notify = palmtc_backlight_notify,
207 .exit = palmtc_backlight_exit,
208}; 175};
209 176
210static struct platform_device palmtc_backlight = { 177static struct platform_device palmtc_backlight = {
diff --git a/arch/arm/mach-pxa/palmte2.c b/arch/arm/mach-pxa/palmte2.c
index 0742721ced2d..956fd24ee6fd 100644
--- a/arch/arm/mach-pxa/palmte2.c
+++ b/arch/arm/mach-pxa/palmte2.c
@@ -165,6 +165,7 @@ static struct platform_pwm_backlight_data palmte2_backlight_data = {
165 .max_brightness = PALMTE2_MAX_INTENSITY, 165 .max_brightness = PALMTE2_MAX_INTENSITY,
166 .dft_brightness = PALMTE2_MAX_INTENSITY, 166 .dft_brightness = PALMTE2_MAX_INTENSITY,
167 .pwm_period_ns = PALMTE2_PERIOD_NS, 167 .pwm_period_ns = PALMTE2_PERIOD_NS,
168 .enable_gpio = -1,
168 .init = palmte2_backlight_init, 169 .init = palmte2_backlight_init,
169 .notify = palmte2_backlight_notify, 170 .notify = palmte2_backlight_notify,
170 .exit = palmte2_backlight_exit, 171 .exit = palmte2_backlight_exit,
diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
index 3133ba82c508..9a4e470f162b 100644
--- a/arch/arm/mach-pxa/pcm990-baseboard.c
+++ b/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -153,6 +153,7 @@ static struct platform_pwm_backlight_data pcm990_backlight_data = {
153 .max_brightness = 1023, 153 .max_brightness = 1023,
154 .dft_brightness = 1023, 154 .dft_brightness = 1023,
155 .pwm_period_ns = 78770, 155 .pwm_period_ns = 78770,
156 .enable_gpio = -1,
156}; 157};
157 158
158static struct platform_device pcm990_backlight_device = { 159static struct platform_device pcm990_backlight_device = {
diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c
index 969b0ba7fa70..8386dc30b3e4 100644
--- a/arch/arm/mach-pxa/raumfeld.c
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -539,6 +539,7 @@ static struct platform_pwm_backlight_data raumfeld_pwm_backlight_data = {
539 .dft_brightness = 100, 539 .dft_brightness = 100,
540 /* 10000 ns = 10 ms ^= 100 kHz */ 540 /* 10000 ns = 10 ms ^= 100 kHz */
541 .pwm_period_ns = 10000, 541 .pwm_period_ns = 10000,
542 .enable_gpio = -1,
542}; 543};
543 544
544static struct platform_device raumfeld_pwm_backlight_device = { 545static struct platform_device raumfeld_pwm_backlight_device = {
diff --git a/arch/arm/mach-pxa/tavorevb.c b/arch/arm/mach-pxa/tavorevb.c
index 4680efe55345..a71da84e784b 100644
--- a/arch/arm/mach-pxa/tavorevb.c
+++ b/arch/arm/mach-pxa/tavorevb.c
@@ -175,6 +175,7 @@ static struct platform_pwm_backlight_data tavorevb_backlight_data[] = {
175 .max_brightness = 100, 175 .max_brightness = 100,
176 .dft_brightness = 100, 176 .dft_brightness = 100,
177 .pwm_period_ns = 100000, 177 .pwm_period_ns = 100000,
178 .enable_gpio = -1,
178 }, 179 },
179 [1] = { 180 [1] = {
180 /* secondary backlight */ 181 /* secondary backlight */
@@ -182,6 +183,7 @@ static struct platform_pwm_backlight_data tavorevb_backlight_data[] = {
182 .max_brightness = 100, 183 .max_brightness = 100,
183 .dft_brightness = 100, 184 .dft_brightness = 100,
184 .pwm_period_ns = 100000, 185 .pwm_period_ns = 100000,
186 .enable_gpio = -1,
185 }, 187 },
186}; 188};
187 189
diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c
index 9c363c081d3f..29905b127ad9 100644
--- a/arch/arm/mach-pxa/viper.c
+++ b/arch/arm/mach-pxa/viper.c
@@ -401,6 +401,7 @@ static struct platform_pwm_backlight_data viper_backlight_data = {
401 .max_brightness = 100, 401 .max_brightness = 100,
402 .dft_brightness = 100, 402 .dft_brightness = 100,
403 .pwm_period_ns = 1000000, 403 .pwm_period_ns = 1000000,
404 .enable_gpio = -1,
404 .init = viper_backlight_init, 405 .init = viper_backlight_init,
405 .notify = viper_backlight_notify, 406 .notify = viper_backlight_notify,
406 .exit = viper_backlight_exit, 407 .exit = viper_backlight_exit,
diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c
index 2513d8f4931f..e1a121b36cfa 100644
--- a/arch/arm/mach-pxa/z2.c
+++ b/arch/arm/mach-pxa/z2.c
@@ -206,6 +206,7 @@ static struct platform_pwm_backlight_data z2_backlight_data[] = {
206 .max_brightness = 1023, 206 .max_brightness = 1023,
207 .dft_brightness = 0, 207 .dft_brightness = 0,
208 .pwm_period_ns = 1260320, 208 .pwm_period_ns = 1260320,
209 .enable_gpio = -1,
209 }, 210 },
210 [1] = { 211 [1] = {
211 /* LCD Backlight */ 212 /* LCD Backlight */
@@ -213,6 +214,7 @@ static struct platform_pwm_backlight_data z2_backlight_data[] = {
213 .max_brightness = 1023, 214 .max_brightness = 1023,
214 .dft_brightness = 512, 215 .dft_brightness = 512,
215 .pwm_period_ns = 1260320, 216 .pwm_period_ns = 1260320,
217 .enable_gpio = -1,
216 }, 218 },
217}; 219};
218 220
diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
index 36cf7cf95ec1..77daea478e88 100644
--- a/arch/arm/mach-pxa/zylonite.c
+++ b/arch/arm/mach-pxa/zylonite.c
@@ -125,6 +125,7 @@ static struct platform_pwm_backlight_data zylonite_backlight_data = {
125 .max_brightness = 100, 125 .max_brightness = 100,
126 .dft_brightness = 100, 126 .dft_brightness = 100,
127 .pwm_period_ns = 10000, 127 .pwm_period_ns = 10000,
128 .enable_gpio = -1,
128}; 129};
129 130
130static struct platform_device zylonite_backlight_device = { 131static struct platform_device zylonite_backlight_device = {
diff --git a/arch/arm/mach-s3c24xx/mach-h1940.c b/arch/arm/mach-s3c24xx/mach-h1940.c
index 74dd47988b41..952b6a040d1f 100644
--- a/arch/arm/mach-s3c24xx/mach-h1940.c
+++ b/arch/arm/mach-s3c24xx/mach-h1940.c
@@ -504,6 +504,7 @@ static struct platform_pwm_backlight_data backlight_data = {
504 .dft_brightness = 50, 504 .dft_brightness = 50,
505 /* tcnt = 0x31 */ 505 /* tcnt = 0x31 */
506 .pwm_period_ns = 36296, 506 .pwm_period_ns = 36296,
507 .enable_gpio = -1,
507 .init = h1940_backlight_init, 508 .init = h1940_backlight_init,
508 .notify = h1940_backlight_notify, 509 .notify = h1940_backlight_notify,
509 .exit = h1940_backlight_exit, 510 .exit = h1940_backlight_exit,
diff --git a/arch/arm/mach-s3c24xx/mach-rx1950.c b/arch/arm/mach-s3c24xx/mach-rx1950.c
index 206b1f7546d1..034b7fe45c49 100644
--- a/arch/arm/mach-s3c24xx/mach-rx1950.c
+++ b/arch/arm/mach-s3c24xx/mach-rx1950.c
@@ -522,6 +522,7 @@ static struct platform_pwm_backlight_data rx1950_backlight_data = {
522 .max_brightness = 24, 522 .max_brightness = 24,
523 .dft_brightness = 4, 523 .dft_brightness = 4,
524 .pwm_period_ns = 48000, 524 .pwm_period_ns = 48000,
525 .enable_gpio = -1,
525 .init = rx1950_backlight_init, 526 .init = rx1950_backlight_init,
526 .notify = rx1950_backlight_notify, 527 .notify = rx1950_backlight_notify,
527 .exit = rx1950_backlight_exit, 528 .exit = rx1950_backlight_exit,
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c
index aca7d16e195d..758e31b26550 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410.c
@@ -114,6 +114,7 @@ static struct platform_pwm_backlight_data crag6410_backlight_data = {
114 .max_brightness = 1000, 114 .max_brightness = 1000,
115 .dft_brightness = 600, 115 .dft_brightness = 600,
116 .pwm_period_ns = 100000, /* about 1kHz */ 116 .pwm_period_ns = 100000, /* about 1kHz */
117 .enable_gpio = -1,
117}; 118};
118 119
119static struct platform_device crag6410_backlight_device = { 120static struct platform_device crag6410_backlight_device = {
diff --git a/arch/arm/mach-s3c64xx/mach-hmt.c b/arch/arm/mach-s3c64xx/mach-hmt.c
index e8064044ef79..614a03a92cf7 100644
--- a/arch/arm/mach-s3c64xx/mach-hmt.c
+++ b/arch/arm/mach-s3c64xx/mach-hmt.c
@@ -114,6 +114,7 @@ static struct platform_pwm_backlight_data hmt_backlight_data = {
114 .max_brightness = 100 * 256, 114 .max_brightness = 100 * 256,
115 .dft_brightness = 40 * 256, 115 .dft_brightness = 40 * 256,
116 .pwm_period_ns = 1000000000 / (100 * 256 * 20), 116 .pwm_period_ns = 1000000000 / (100 * 256 * 20),
117 .enable_gpio = -1,
117 .init = hmt_bl_init, 118 .init = hmt_bl_init,
118 .notify = hmt_bl_notify, 119 .notify = hmt_bl_notify,
119 .exit = hmt_bl_exit, 120 .exit = hmt_bl_exit,
diff --git a/arch/arm/mach-s3c64xx/mach-smartq.c b/arch/arm/mach-s3c64xx/mach-smartq.c
index 0f47237be3b2..a6b338fd0470 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq.c
@@ -151,6 +151,7 @@ static struct platform_pwm_backlight_data smartq_backlight_data = {
151 .max_brightness = 1000, 151 .max_brightness = 1000,
152 .dft_brightness = 600, 152 .dft_brightness = 600,
153 .pwm_period_ns = 1000000000 / (1000 * 20), 153 .pwm_period_ns = 1000000000 / (1000 * 20),
154 .enable_gpio = -1,
154 .init = smartq_bl_init, 155 .init = smartq_bl_init,
155}; 156};
156 157
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
index 2a7b32ca5c96..d5ea938cc9a1 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -625,6 +625,7 @@ static struct samsung_bl_gpio_info smdk6410_bl_gpio_info = {
625 625
626static struct platform_pwm_backlight_data smdk6410_bl_data = { 626static struct platform_pwm_backlight_data smdk6410_bl_data = {
627 .pwm_id = 1, 627 .pwm_id = 1,
628 .enable_gpio = -1,
628}; 629};
629 630
630static struct s3c_hsotg_plat smdk6410_hsotg_pdata; 631static struct s3c_hsotg_plat smdk6410_hsotg_pdata;
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c
index 0b00304c1e91..9efdcc03df3b 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6440.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c
@@ -223,6 +223,7 @@ static struct samsung_bl_gpio_info smdk6440_bl_gpio_info = {
223 223
224static struct platform_pwm_backlight_data smdk6440_bl_data = { 224static struct platform_pwm_backlight_data smdk6440_bl_data = {
225 .pwm_id = 1, 225 .pwm_id = 1,
226 .enable_gpio = -1,
226}; 227};
227 228
228static void __init smdk6440_map_io(void) 229static void __init smdk6440_map_io(void)
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c
index 5949296e88fd..c3cacc067efe 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6450.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c
@@ -242,6 +242,7 @@ static struct samsung_bl_gpio_info smdk6450_bl_gpio_info = {
242 242
243static struct platform_pwm_backlight_data smdk6450_bl_data = { 243static struct platform_pwm_backlight_data smdk6450_bl_data = {
244 .pwm_id = 1, 244 .pwm_id = 1,
245 .enable_gpio = -1,
245}; 246};
246 247
247static void __init smdk6450_map_io(void) 248static void __init smdk6450_map_io(void)
diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c
index 7c57a221785e..9e256b9fc930 100644
--- a/arch/arm/mach-s5pc100/mach-smdkc100.c
+++ b/arch/arm/mach-s5pc100/mach-smdkc100.c
@@ -216,6 +216,7 @@ static struct samsung_bl_gpio_info smdkc100_bl_gpio_info = {
216 216
217static struct platform_pwm_backlight_data smdkc100_bl_data = { 217static struct platform_pwm_backlight_data smdkc100_bl_data = {
218 .pwm_id = 0, 218 .pwm_id = 0,
219 .enable_gpio = -1,
219}; 220};
220 221
221static void __init smdkc100_map_io(void) 222static void __init smdkc100_map_io(void)
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c
index 6d72bb992e38..f52cc15c2d85 100644
--- a/arch/arm/mach-s5pv210/mach-smdkv210.c
+++ b/arch/arm/mach-s5pv210/mach-smdkv210.c
@@ -279,6 +279,7 @@ static struct samsung_bl_gpio_info smdkv210_bl_gpio_info = {
279static struct platform_pwm_backlight_data smdkv210_bl_data = { 279static struct platform_pwm_backlight_data smdkv210_bl_data = {
280 .pwm_id = 3, 280 .pwm_id = 3,
281 .pwm_period_ns = 1000, 281 .pwm_period_ns = 1000,
282 .enable_gpio = -1,
282}; 283};
283 284
284static void __init smdkv210_map_io(void) 285static void __init smdkv210_map_io(void)
diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
index 8bc8e4c58847..958e3cbf0ac2 100644
--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
@@ -423,6 +423,7 @@ static struct platform_pwm_backlight_data pwm_backlight_data = {
423 .max_brightness = 255, 423 .max_brightness = 255,
424 .dft_brightness = 255, 424 .dft_brightness = 255,
425 .pwm_period_ns = 33333, /* 30kHz */ 425 .pwm_period_ns = 33333, /* 30kHz */
426 .enable_gpio = -1,
426}; 427};
427 428
428static struct platform_device pwm_backlight_device = { 429static struct platform_device pwm_backlight_device = {
diff --git a/arch/arm/plat-samsung/dev-backlight.c b/arch/arm/plat-samsung/dev-backlight.c
index d51f9565567c..be4ad0b21c08 100644
--- a/arch/arm/plat-samsung/dev-backlight.c
+++ b/arch/arm/plat-samsung/dev-backlight.c
@@ -70,6 +70,7 @@ static struct samsung_bl_drvdata samsung_dfl_bl_data __initdata = {
70 .max_brightness = 255, 70 .max_brightness = 255,
71 .dft_brightness = 255, 71 .dft_brightness = 255,
72 .pwm_period_ns = 78770, 72 .pwm_period_ns = 78770,
73 .enable_gpio = -1,
73 .init = samsung_bl_init, 74 .init = samsung_bl_init,
74 .exit = samsung_bl_exit, 75 .exit = samsung_bl_exit,
75 }, 76 },
@@ -121,6 +122,10 @@ void __init samsung_bl_set(struct samsung_bl_gpio_info *gpio_info,
121 samsung_bl_data->lth_brightness = bl_data->lth_brightness; 122 samsung_bl_data->lth_brightness = bl_data->lth_brightness;
122 if (bl_data->pwm_period_ns) 123 if (bl_data->pwm_period_ns)
123 samsung_bl_data->pwm_period_ns = bl_data->pwm_period_ns; 124 samsung_bl_data->pwm_period_ns = bl_data->pwm_period_ns;
125 if (bl_data->enable_gpio >= 0)
126 samsung_bl_data->enable_gpio = bl_data->enable_gpio;
127 if (bl_data->enable_gpio_flags)
128 samsung_bl_data->enable_gpio_flags = bl_data->enable_gpio_flags;
124 if (bl_data->init) 129 if (bl_data->init)
125 samsung_bl_data->init = bl_data->init; 130 samsung_bl_data->init = bl_data->init;
126 if (bl_data->notify) 131 if (bl_data->notify)
diff --git a/arch/unicore32/kernel/puv3-nb0916.c b/arch/unicore32/kernel/puv3-nb0916.c
index 181108b8ecce..0c6618e71897 100644
--- a/arch/unicore32/kernel/puv3-nb0916.c
+++ b/arch/unicore32/kernel/puv3-nb0916.c
@@ -54,6 +54,7 @@ static struct platform_pwm_backlight_data nb0916_backlight_data = {
54 .max_brightness = 100, 54 .max_brightness = 100,
55 .dft_brightness = 100, 55 .dft_brightness = 100,
56 .pwm_period_ns = 70 * 1024, 56 .pwm_period_ns = 70 * 1024,
57 .enable_gpio = -1,
57}; 58};
58 59
59static struct gpio_keys_button nb0916_gpio_keys[] = { 60static struct gpio_keys_button nb0916_gpio_keys[] = {
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index e760715bd9cb..a3e291d0df9a 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -381,19 +381,6 @@ config HMC6352
381 This driver provides support for the Honeywell HMC6352 compass, 381 This driver provides support for the Honeywell HMC6352 compass,
382 providing configuration and heading data via sysfs. 382 providing configuration and heading data via sysfs.
383 383
384config EP93XX_PWM
385 tristate "EP93xx PWM support"
386 depends on ARCH_EP93XX
387 help
388 This option enables device driver support for the PWM channels
389 on the Cirrus EP93xx processors. The EP9307 chip only has one
390 PWM channel all the others have two, the second channel is an
391 alternate function of the EGPIO14 pin. A sysfs interface is
392 provided to control the PWM channels.
393
394 To compile this driver as a module, choose M here: the module will
395 be called ep93xx_pwm.
396
397config DS1682 384config DS1682
398 tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm" 385 tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm"
399 depends on I2C 386 depends on I2C
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 0b7ea3ea8bb8..f45473e68bf7 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -33,7 +33,6 @@ obj-$(CONFIG_APDS9802ALS) += apds9802als.o
33obj-$(CONFIG_ISL29003) += isl29003.o 33obj-$(CONFIG_ISL29003) += isl29003.o
34obj-$(CONFIG_ISL29020) += isl29020.o 34obj-$(CONFIG_ISL29020) += isl29020.o
35obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o 35obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o
36obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o
37obj-$(CONFIG_DS1682) += ds1682.o 36obj-$(CONFIG_DS1682) += ds1682.o
38obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o 37obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o
39obj-$(CONFIG_C2PORT) += c2port/ 38obj-$(CONFIG_C2PORT) += c2port/
diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c
deleted file mode 100644
index cdb67a9c1959..000000000000
--- a/drivers/misc/ep93xx_pwm.c
+++ /dev/null
@@ -1,286 +0,0 @@
1/*
2 * Simple PWM driver for EP93XX
3 *
4 * (c) Copyright 2009 Matthieu Crapet <mcrapet@gmail.com>
5 * (c) Copyright 2009 H Hartley Sweeten <hsweeten@visionengravers.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
12 * EP9307 has only one channel:
13 * - PWMOUT
14 *
15 * EP9301/02/12/15 have two channels:
16 * - PWMOUT
17 * - PWMOUT1 (alternate function for EGPIO14)
18 */
19
20#include <linux/module.h>
21#include <linux/platform_device.h>
22#include <linux/slab.h>
23#include <linux/clk.h>
24#include <linux/err.h>
25#include <linux/io.h>
26
27#include <mach/platform.h>
28
29#define EP93XX_PWMx_TERM_COUNT 0x00
30#define EP93XX_PWMx_DUTY_CYCLE 0x04
31#define EP93XX_PWMx_ENABLE 0x08
32#define EP93XX_PWMx_INVERT 0x0C
33
34#define EP93XX_PWM_MAX_COUNT 0xFFFF
35
36struct ep93xx_pwm {
37 void __iomem *mmio_base;
38 struct clk *clk;
39 u32 duty_percent;
40};
41
42/*
43 * /sys/devices/platform/ep93xx-pwm.N
44 * /min_freq read-only minimum pwm output frequency
45 * /max_req read-only maximum pwm output frequency
46 * /freq read-write pwm output frequency (0 = disable output)
47 * /duty_percent read-write pwm duty cycle percent (1..99)
48 * /invert read-write invert pwm output
49 */
50
51static ssize_t ep93xx_pwm_get_min_freq(struct device *dev,
52 struct device_attribute *attr, char *buf)
53{
54 struct platform_device *pdev = to_platform_device(dev);
55 struct ep93xx_pwm *pwm = platform_get_drvdata(pdev);
56 unsigned long rate = clk_get_rate(pwm->clk);
57
58 return sprintf(buf, "%ld\n", rate / (EP93XX_PWM_MAX_COUNT + 1));
59}
60
61static ssize_t ep93xx_pwm_get_max_freq(struct device *dev,
62 struct device_attribute *attr, char *buf)
63{
64 struct platform_device *pdev = to_platform_device(dev);
65 struct ep93xx_pwm *pwm = platform_get_drvdata(pdev);
66 unsigned long rate = clk_get_rate(pwm->clk);
67
68 return sprintf(buf, "%ld\n", rate / 2);
69}
70
71static ssize_t ep93xx_pwm_get_freq(struct device *dev,
72 struct device_attribute *attr, char *buf)
73{
74 struct platform_device *pdev = to_platform_device(dev);
75 struct ep93xx_pwm *pwm = platform_get_drvdata(pdev);
76
77 if (readl(pwm->mmio_base + EP93XX_PWMx_ENABLE) & 0x1) {
78 unsigned long rate = clk_get_rate(pwm->clk);
79 u16 term = readl(pwm->mmio_base + EP93XX_PWMx_TERM_COUNT);
80
81 return sprintf(buf, "%ld\n", rate / (term + 1));
82 } else {
83 return sprintf(buf, "disabled\n");
84 }
85}
86
87static ssize_t ep93xx_pwm_set_freq(struct device *dev,
88 struct device_attribute *attr, const char *buf, size_t count)
89{
90 struct platform_device *pdev = to_platform_device(dev);
91 struct ep93xx_pwm *pwm = platform_get_drvdata(pdev);
92 long val;
93 int err;
94
95 err = kstrtol(buf, 10, &val);
96 if (err)
97 return -EINVAL;
98
99 if (val == 0) {
100 writel(0x0, pwm->mmio_base + EP93XX_PWMx_ENABLE);
101 } else if (val <= (clk_get_rate(pwm->clk) / 2)) {
102 u32 term, duty;
103
104 val = (clk_get_rate(pwm->clk) / val) - 1;
105 if (val > EP93XX_PWM_MAX_COUNT)
106 val = EP93XX_PWM_MAX_COUNT;
107 if (val < 1)
108 val = 1;
109
110 term = readl(pwm->mmio_base + EP93XX_PWMx_TERM_COUNT);
111 duty = ((val + 1) * pwm->duty_percent / 100) - 1;
112
113 /* If pwm is running, order is important */
114 if (val > term) {
115 writel(val, pwm->mmio_base + EP93XX_PWMx_TERM_COUNT);
116 writel(duty, pwm->mmio_base + EP93XX_PWMx_DUTY_CYCLE);
117 } else {
118 writel(duty, pwm->mmio_base + EP93XX_PWMx_DUTY_CYCLE);
119 writel(val, pwm->mmio_base + EP93XX_PWMx_TERM_COUNT);
120 }
121
122 if (!readl(pwm->mmio_base + EP93XX_PWMx_ENABLE) & 0x1)
123 writel(0x1, pwm->mmio_base + EP93XX_PWMx_ENABLE);
124 } else {
125 return -EINVAL;
126 }
127
128 return count;
129}
130
131static ssize_t ep93xx_pwm_get_duty_percent(struct device *dev,
132 struct device_attribute *attr, char *buf)
133{
134 struct platform_device *pdev = to_platform_device(dev);
135 struct ep93xx_pwm *pwm = platform_get_drvdata(pdev);
136
137 return sprintf(buf, "%d\n", pwm->duty_percent);
138}
139
140static ssize_t ep93xx_pwm_set_duty_percent(struct device *dev,
141 struct device_attribute *attr, const char *buf, size_t count)
142{
143 struct platform_device *pdev = to_platform_device(dev);
144 struct ep93xx_pwm *pwm = platform_get_drvdata(pdev);
145 long val;
146 int err;
147
148 err = kstrtol(buf, 10, &val);
149 if (err)
150 return -EINVAL;
151
152 if (val > 0 && val < 100) {
153 u32 term = readl(pwm->mmio_base + EP93XX_PWMx_TERM_COUNT);
154 u32 duty = ((term + 1) * val / 100) - 1;
155
156 writel(duty, pwm->mmio_base + EP93XX_PWMx_DUTY_CYCLE);
157 pwm->duty_percent = val;
158 return count;
159 }
160
161 return -EINVAL;
162}
163
164static ssize_t ep93xx_pwm_get_invert(struct device *dev,
165 struct device_attribute *attr, char *buf)
166{
167 struct platform_device *pdev = to_platform_device(dev);
168 struct ep93xx_pwm *pwm = platform_get_drvdata(pdev);
169 int inverted = readl(pwm->mmio_base + EP93XX_PWMx_INVERT) & 0x1;
170
171 return sprintf(buf, "%d\n", inverted);
172}
173
174static ssize_t ep93xx_pwm_set_invert(struct device *dev,
175 struct device_attribute *attr, const char *buf, size_t count)
176{
177 struct platform_device *pdev = to_platform_device(dev);
178 struct ep93xx_pwm *pwm = platform_get_drvdata(pdev);
179 long val;
180 int err;
181
182 err = kstrtol(buf, 10, &val);
183 if (err)
184 return -EINVAL;
185
186 if (val == 0)
187 writel(0x0, pwm->mmio_base + EP93XX_PWMx_INVERT);
188 else if (val == 1)
189 writel(0x1, pwm->mmio_base + EP93XX_PWMx_INVERT);
190 else
191 return -EINVAL;
192
193 return count;
194}
195
196static DEVICE_ATTR(min_freq, S_IRUGO, ep93xx_pwm_get_min_freq, NULL);
197static DEVICE_ATTR(max_freq, S_IRUGO, ep93xx_pwm_get_max_freq, NULL);
198static DEVICE_ATTR(freq, S_IWUSR | S_IRUGO,
199 ep93xx_pwm_get_freq, ep93xx_pwm_set_freq);
200static DEVICE_ATTR(duty_percent, S_IWUSR | S_IRUGO,
201 ep93xx_pwm_get_duty_percent, ep93xx_pwm_set_duty_percent);
202static DEVICE_ATTR(invert, S_IWUSR | S_IRUGO,
203 ep93xx_pwm_get_invert, ep93xx_pwm_set_invert);
204
205static struct attribute *ep93xx_pwm_attrs[] = {
206 &dev_attr_min_freq.attr,
207 &dev_attr_max_freq.attr,
208 &dev_attr_freq.attr,
209 &dev_attr_duty_percent.attr,
210 &dev_attr_invert.attr,
211 NULL
212};
213
214static const struct attribute_group ep93xx_pwm_sysfs_files = {
215 .attrs = ep93xx_pwm_attrs,
216};
217
218static int ep93xx_pwm_probe(struct platform_device *pdev)
219{
220 struct ep93xx_pwm *pwm;
221 struct resource *res;
222 int ret;
223
224 pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL);
225 if (!pwm)
226 return -ENOMEM;
227
228 pwm->clk = devm_clk_get(&pdev->dev, "pwm_clk");
229 if (IS_ERR(pwm->clk))
230 return PTR_ERR(pwm->clk);
231
232 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
233 pwm->mmio_base = devm_ioremap_resource(&pdev->dev, res);
234 if (IS_ERR(pwm->mmio_base))
235 return PTR_ERR(pwm->mmio_base);
236
237 ret = ep93xx_pwm_acquire_gpio(pdev);
238 if (ret)
239 return ret;
240
241 ret = sysfs_create_group(&pdev->dev.kobj, &ep93xx_pwm_sysfs_files);
242 if (ret) {
243 ep93xx_pwm_release_gpio(pdev);
244 return ret;
245 }
246
247 pwm->duty_percent = 50;
248
249 /* disable pwm at startup. Avoids zero value. */
250 writel(0x0, pwm->mmio_base + EP93XX_PWMx_ENABLE);
251 writel(EP93XX_PWM_MAX_COUNT, pwm->mmio_base + EP93XX_PWMx_TERM_COUNT);
252 writel(EP93XX_PWM_MAX_COUNT/2, pwm->mmio_base + EP93XX_PWMx_DUTY_CYCLE);
253
254 clk_enable(pwm->clk);
255
256 platform_set_drvdata(pdev, pwm);
257 return 0;
258}
259
260static int ep93xx_pwm_remove(struct platform_device *pdev)
261{
262 struct ep93xx_pwm *pwm = platform_get_drvdata(pdev);
263
264 writel(0x0, pwm->mmio_base + EP93XX_PWMx_ENABLE);
265 clk_disable(pwm->clk);
266 sysfs_remove_group(&pdev->dev.kobj, &ep93xx_pwm_sysfs_files);
267 ep93xx_pwm_release_gpio(pdev);
268
269 return 0;
270}
271
272static struct platform_driver ep93xx_pwm_driver = {
273 .driver = {
274 .name = "ep93xx-pwm",
275 .owner = THIS_MODULE,
276 },
277 .probe = ep93xx_pwm_probe,
278 .remove = ep93xx_pwm_remove,
279};
280module_platform_driver(ep93xx_pwm_driver);
281
282MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>, "
283 "H Hartley Sweeten <hsweeten@visionengravers.com>");
284MODULE_DESCRIPTION("EP93xx PWM driver");
285MODULE_LICENSE("GPL");
286MODULE_ALIAS("platform:ep93xx-pwm");
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 75840b5cea6d..eece329d7872 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -62,6 +62,15 @@ config PWM_BFIN
62 To compile this driver as a module, choose M here: the module 62 To compile this driver as a module, choose M here: the module
63 will be called pwm-bfin. 63 will be called pwm-bfin.
64 64
65config PWM_EP93XX
66 tristate "Cirrus Logic EP93xx PWM support"
67 depends on ARCH_EP93XX
68 help
69 Generic PWM framework driver for Cirrus Logic EP93xx.
70
71 To compile this driver as a module, choose M here: the module
72 will be called pwm-ep93xx.
73
65config PWM_IMX 74config PWM_IMX
66 tristate "i.MX PWM support" 75 tristate "i.MX PWM support"
67 depends on ARCH_MXC 76 depends on ARCH_MXC
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 77a8c185c5b2..8b754e4dba4a 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_PWM_SYSFS) += sysfs.o
3obj-$(CONFIG_PWM_AB8500) += pwm-ab8500.o 3obj-$(CONFIG_PWM_AB8500) += pwm-ab8500.o
4obj-$(CONFIG_PWM_ATMEL_TCB) += pwm-atmel-tcb.o 4obj-$(CONFIG_PWM_ATMEL_TCB) += pwm-atmel-tcb.o
5obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o 5obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o
6obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o
6obj-$(CONFIG_PWM_IMX) += pwm-imx.o 7obj-$(CONFIG_PWM_IMX) += pwm-imx.o
7obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o 8obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o
8obj-$(CONFIG_PWM_LPC32XX) += pwm-lpc32xx.o 9obj-$(CONFIG_PWM_LPC32XX) += pwm-lpc32xx.o
diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c
index ba6ce01035e4..f3dcd02390f1 100644
--- a/drivers/pwm/pwm-atmel-tcb.c
+++ b/drivers/pwm/pwm-atmel-tcb.c
@@ -249,6 +249,8 @@ static int atmel_tcb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
249 } 249 }
250 } 250 }
251 251
252 cmr |= (tcbpwm->div & ATMEL_TC_TCCLKS);
253
252 __raw_writel(cmr, regs + ATMEL_TC_REG(group, CMR)); 254 __raw_writel(cmr, regs + ATMEL_TC_REG(group, CMR));
253 255
254 if (index == 0) 256 if (index == 0)
@@ -305,7 +307,7 @@ static int atmel_tcb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
305 i = slowclk; 307 i = slowclk;
306 rate = 32768; 308 rate = 32768;
307 min = div_u64(NSEC_PER_SEC, rate); 309 min = div_u64(NSEC_PER_SEC, rate);
308 max = min << 16; 310 max = min << tc->tcb_config->counter_width;
309 311
310 /* If period is too big return ERANGE error */ 312 /* If period is too big return ERANGE error */
311 if (max < period_ns) 313 if (max < period_ns)
diff --git a/drivers/pwm/pwm-ep93xx.c b/drivers/pwm/pwm-ep93xx.c
new file mode 100644
index 000000000000..33aa4461e1ce
--- /dev/null
+++ b/drivers/pwm/pwm-ep93xx.c
@@ -0,0 +1,230 @@
1/*
2 * PWM framework driver for Cirrus Logic EP93xx
3 *
4 * Copyright (c) 2009 Matthieu Crapet <mcrapet@gmail.com>
5 * Copyright (c) 2009, 2013 H Hartley Sweeten <hsweeten@visionengravers.com>
6 *
7 * EP9301/02 have only one channel:
8 * platform device ep93xx-pwm.1 - PWMOUT1 (EGPIO14)
9 *
10 * EP9307 has only one channel:
11 * platform device ep93xx-pwm.0 - PWMOUT
12 *
13 * EP9312/15 have two channels:
14 * platform device ep93xx-pwm.0 - PWMOUT
15 * platform device ep93xx-pwm.1 - PWMOUT1 (EGPIO14)
16 *
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version
20 * 2 of the License, or (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 */
27
28#include <linux/module.h>
29#include <linux/platform_device.h>
30#include <linux/slab.h>
31#include <linux/clk.h>
32#include <linux/err.h>
33#include <linux/io.h>
34#include <linux/pwm.h>
35
36#include <asm/div64.h>
37
38#include <mach/platform.h> /* for ep93xx_pwm_{acquire,release}_gpio() */
39
40#define EP93XX_PWMx_TERM_COUNT 0x00
41#define EP93XX_PWMx_DUTY_CYCLE 0x04
42#define EP93XX_PWMx_ENABLE 0x08
43#define EP93XX_PWMx_INVERT 0x0c
44
45struct ep93xx_pwm {
46 void __iomem *base;
47 struct clk *clk;
48 struct pwm_chip chip;
49};
50
51static inline struct ep93xx_pwm *to_ep93xx_pwm(struct pwm_chip *chip)
52{
53 return container_of(chip, struct ep93xx_pwm, chip);
54}
55
56static int ep93xx_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
57{
58 struct platform_device *pdev = to_platform_device(chip->dev);
59
60 return ep93xx_pwm_acquire_gpio(pdev);
61}
62
63static void ep93xx_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
64{
65 struct platform_device *pdev = to_platform_device(chip->dev);
66
67 ep93xx_pwm_release_gpio(pdev);
68}
69
70static int ep93xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
71 int duty_ns, int period_ns)
72{
73 struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip);
74 void __iomem *base = ep93xx_pwm->base;
75 unsigned long long c;
76 unsigned long period_cycles;
77 unsigned long duty_cycles;
78 unsigned long term;
79 int ret = 0;
80
81 /*
82 * The clock needs to be enabled to access the PWM registers.
83 * Configuration can be changed at any time.
84 */
85 if (!test_bit(PWMF_ENABLED, &pwm->flags)) {
86 ret = clk_enable(ep93xx_pwm->clk);
87 if (ret)
88 return ret;
89 }
90
91 c = clk_get_rate(ep93xx_pwm->clk);
92 c *= period_ns;
93 do_div(c, 1000000000);
94 period_cycles = c;
95
96 c = period_cycles;
97 c *= duty_ns;
98 do_div(c, period_ns);
99 duty_cycles = c;
100
101 if (period_cycles < 0x10000 && duty_cycles < 0x10000) {
102 term = readw(base + EP93XX_PWMx_TERM_COUNT);
103
104 /* Order is important if PWM is running */
105 if (period_cycles > term) {
106 writew(period_cycles, base + EP93XX_PWMx_TERM_COUNT);
107 writew(duty_cycles, base + EP93XX_PWMx_DUTY_CYCLE);
108 } else {
109 writew(duty_cycles, base + EP93XX_PWMx_DUTY_CYCLE);
110 writew(period_cycles, base + EP93XX_PWMx_TERM_COUNT);
111 }
112 } else {
113 ret = -EINVAL;
114 }
115
116 if (!test_bit(PWMF_ENABLED, &pwm->flags))
117 clk_disable(ep93xx_pwm->clk);
118
119 return ret;
120}
121
122static int ep93xx_pwm_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
123 enum pwm_polarity polarity)
124{
125 struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip);
126 int ret;
127
128 /*
129 * The clock needs to be enabled to access the PWM registers.
130 * Polarity can only be changed when the PWM is disabled.
131 */
132 ret = clk_enable(ep93xx_pwm->clk);
133 if (ret)
134 return ret;
135
136 if (polarity == PWM_POLARITY_INVERSED)
137 writew(0x1, ep93xx_pwm->base + EP93XX_PWMx_INVERT);
138 else
139 writew(0x0, ep93xx_pwm->base + EP93XX_PWMx_INVERT);
140
141 clk_disable(ep93xx_pwm->clk);
142
143 return 0;
144}
145
146static int ep93xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
147{
148 struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip);
149 int ret;
150
151 ret = clk_enable(ep93xx_pwm->clk);
152 if (ret)
153 return ret;
154
155 writew(0x1, ep93xx_pwm->base + EP93XX_PWMx_ENABLE);
156
157 return 0;
158}
159
160static void ep93xx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
161{
162 struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip);
163
164 writew(0x0, ep93xx_pwm->base + EP93XX_PWMx_ENABLE);
165 clk_disable(ep93xx_pwm->clk);
166}
167
168static const struct pwm_ops ep93xx_pwm_ops = {
169 .request = ep93xx_pwm_request,
170 .free = ep93xx_pwm_free,
171 .config = ep93xx_pwm_config,
172 .set_polarity = ep93xx_pwm_polarity,
173 .enable = ep93xx_pwm_enable,
174 .disable = ep93xx_pwm_disable,
175 .owner = THIS_MODULE,
176};
177
178static int ep93xx_pwm_probe(struct platform_device *pdev)
179{
180 struct ep93xx_pwm *ep93xx_pwm;
181 struct resource *res;
182 int ret;
183
184 ep93xx_pwm = devm_kzalloc(&pdev->dev, sizeof(*ep93xx_pwm), GFP_KERNEL);
185 if (!ep93xx_pwm)
186 return -ENOMEM;
187
188 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
189 ep93xx_pwm->base = devm_ioremap_resource(&pdev->dev, res);
190 if (IS_ERR(ep93xx_pwm->base))
191 return PTR_ERR(ep93xx_pwm->base);
192
193 ep93xx_pwm->clk = devm_clk_get(&pdev->dev, "pwm_clk");
194 if (IS_ERR(ep93xx_pwm->clk))
195 return PTR_ERR(ep93xx_pwm->clk);
196
197 ep93xx_pwm->chip.dev = &pdev->dev;
198 ep93xx_pwm->chip.ops = &ep93xx_pwm_ops;
199 ep93xx_pwm->chip.base = -1;
200 ep93xx_pwm->chip.npwm = 1;
201
202 ret = pwmchip_add(&ep93xx_pwm->chip);
203 if (ret < 0)
204 return ret;
205
206 platform_set_drvdata(pdev, ep93xx_pwm);
207 return 0;
208}
209
210static int ep93xx_pwm_remove(struct platform_device *pdev)
211{
212 struct ep93xx_pwm *ep93xx_pwm = platform_get_drvdata(pdev);
213
214 return pwmchip_remove(&ep93xx_pwm->chip);
215}
216
217static struct platform_driver ep93xx_pwm_driver = {
218 .driver = {
219 .name = "ep93xx-pwm",
220 },
221 .probe = ep93xx_pwm_probe,
222 .remove = ep93xx_pwm_remove,
223};
224module_platform_driver(ep93xx_pwm_driver);
225
226MODULE_DESCRIPTION("Cirrus Logic EP93xx PWM driver");
227MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>, "
228 "H Hartley Sweeten <hsweeten@visionengravers.com>");
229MODULE_ALIAS("platform:ep93xx-pwm");
230MODULE_LICENSE("GPL");
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
index 2b7c4f88b461..cc4773344874 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx.c
@@ -16,6 +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 <linux/of.h>
19#include <linux/of_device.h> 20#include <linux/of_device.h>
20 21
21/* i.MX1 and i.MX21 share the same PWM function block: */ 22/* i.MX1 and i.MX21 share the same PWM function block: */
@@ -296,7 +297,7 @@ static struct platform_driver imx_pwm_driver = {
296 .driver = { 297 .driver = {
297 .name = "imx-pwm", 298 .name = "imx-pwm",
298 .owner = THIS_MODULE, 299 .owner = THIS_MODULE,
299 .of_match_table = of_match_ptr(imx_pwm_dt_ids), 300 .of_match_table = imx_pwm_dt_ids,
300 }, 301 },
301 .probe = imx_pwm_probe, 302 .probe = imx_pwm_probe,
302 .remove = imx_pwm_remove, 303 .remove = imx_pwm_remove,
diff --git a/drivers/pwm/pwm-lpc32xx.c b/drivers/pwm/pwm-lpc32xx.c
index efac99e03d57..9dc0f9d42bfa 100644
--- a/drivers/pwm/pwm-lpc32xx.c
+++ b/drivers/pwm/pwm-lpc32xx.c
@@ -169,7 +169,7 @@ static struct platform_driver lpc32xx_pwm_driver = {
169 .driver = { 169 .driver = {
170 .name = "lpc32xx-pwm", 170 .name = "lpc32xx-pwm",
171 .owner = THIS_MODULE, 171 .owner = THIS_MODULE,
172 .of_match_table = of_match_ptr(lpc32xx_pwm_dt_ids), 172 .of_match_table = lpc32xx_pwm_dt_ids,
173 }, 173 },
174 .probe = lpc32xx_pwm_probe, 174 .probe = lpc32xx_pwm_probe,
175 .remove = lpc32xx_pwm_remove, 175 .remove = lpc32xx_pwm_remove,
diff --git a/drivers/pwm/pwm-mxs.c b/drivers/pwm/pwm-mxs.c
index c2c5a4fd1b96..9475bc7a6f97 100644
--- a/drivers/pwm/pwm-mxs.c
+++ b/drivers/pwm/pwm-mxs.c
@@ -189,7 +189,7 @@ static struct platform_driver mxs_pwm_driver = {
189 .driver = { 189 .driver = {
190 .name = "mxs-pwm", 190 .name = "mxs-pwm",
191 .owner = THIS_MODULE, 191 .owner = THIS_MODULE,
192 .of_match_table = of_match_ptr(mxs_pwm_dt_ids), 192 .of_match_table = mxs_pwm_dt_ids,
193 }, 193 },
194 .probe = mxs_pwm_probe, 194 .probe = mxs_pwm_probe,
195 .remove = mxs_pwm_remove, 195 .remove = mxs_pwm_remove,
diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c
index fcc8b9adde9f..b59639e0c029 100644
--- a/drivers/pwm/pwm-samsung.c
+++ b/drivers/pwm/pwm-samsung.c
@@ -18,6 +18,7 @@
18#include <linux/io.h> 18#include <linux/io.h>
19#include <linux/kernel.h> 19#include <linux/kernel.h>
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/of.h>
21#include <linux/platform_device.h> 22#include <linux/platform_device.h>
22#include <linux/pwm.h> 23#include <linux/pwm.h>
23#include <linux/slab.h> 24#include <linux/slab.h>
@@ -224,8 +225,8 @@ static int pwm_samsung_request(struct pwm_chip *chip, struct pwm_device *pwm)
224 225
225static void pwm_samsung_free(struct pwm_chip *chip, struct pwm_device *pwm) 226static void pwm_samsung_free(struct pwm_chip *chip, struct pwm_device *pwm)
226{ 227{
227 pwm_set_chip_data(pwm, NULL);
228 devm_kfree(chip->dev, pwm_get_chip_data(pwm)); 228 devm_kfree(chip->dev, pwm_get_chip_data(pwm));
229 pwm_set_chip_data(pwm, NULL);
229} 230}
230 231
231static int pwm_samsung_enable(struct pwm_chip *chip, struct pwm_device *pwm) 232static int pwm_samsung_enable(struct pwm_chip *chip, struct pwm_device *pwm)
diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c
index c2e2e5852362..4e5c3d13d4f8 100644
--- a/drivers/pwm/pwm-tiecap.c
+++ b/drivers/pwm/pwm-tiecap.c
@@ -26,7 +26,6 @@
26#include <linux/pm_runtime.h> 26#include <linux/pm_runtime.h>
27#include <linux/pwm.h> 27#include <linux/pwm.h>
28#include <linux/of_device.h> 28#include <linux/of_device.h>
29#include <linux/pinctrl/consumer.h>
30 29
31#include "pwm-tipwmss.h" 30#include "pwm-tipwmss.h"
32 31
@@ -208,11 +207,6 @@ static int ecap_pwm_probe(struct platform_device *pdev)
208 struct clk *clk; 207 struct clk *clk;
209 struct ecap_pwm_chip *pc; 208 struct ecap_pwm_chip *pc;
210 u16 status; 209 u16 status;
211 struct pinctrl *pinctrl;
212
213 pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
214 if (IS_ERR(pinctrl))
215 dev_warn(&pdev->dev, "unable to select pin group\n");
216 210
217 pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); 211 pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
218 if (!pc) { 212 if (!pc) {
diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
index 084f55246532..a4d8f519d965 100644
--- a/drivers/pwm/pwm-tiehrpwm.c
+++ b/drivers/pwm/pwm-tiehrpwm.c
@@ -26,7 +26,6 @@
26#include <linux/clk.h> 26#include <linux/clk.h>
27#include <linux/pm_runtime.h> 27#include <linux/pm_runtime.h>
28#include <linux/of_device.h> 28#include <linux/of_device.h>
29#include <linux/pinctrl/consumer.h>
30 29
31#include "pwm-tipwmss.h" 30#include "pwm-tipwmss.h"
32 31
@@ -439,11 +438,6 @@ static int ehrpwm_pwm_probe(struct platform_device *pdev)
439 struct clk *clk; 438 struct clk *clk;
440 struct ehrpwm_pwm_chip *pc; 439 struct ehrpwm_pwm_chip *pc;
441 u16 status; 440 u16 status;
442 struct pinctrl *pinctrl;
443
444 pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
445 if (IS_ERR(pinctrl))
446 dev_warn(&pdev->dev, "unable to select pin group\n");
447 441
448 pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); 442 pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
449 if (!pc) { 443 if (!pc) {
diff --git a/drivers/pwm/pwm-twl-led.c b/drivers/pwm/pwm-twl-led.c
index 29d1bba4804e..b964470025c5 100644
--- a/drivers/pwm/pwm-twl-led.c
+++ b/drivers/pwm/pwm-twl-led.c
@@ -21,6 +21,7 @@
21 */ 21 */
22 22
23#include <linux/module.h> 23#include <linux/module.h>
24#include <linux/of.h>
24#include <linux/platform_device.h> 25#include <linux/platform_device.h>
25#include <linux/pwm.h> 26#include <linux/pwm.h>
26#include <linux/i2c/twl.h> 27#include <linux/i2c/twl.h>
diff --git a/drivers/pwm/pwm-twl.c b/drivers/pwm/pwm-twl.c
index eef910580eae..b99a50e626a6 100644
--- a/drivers/pwm/pwm-twl.c
+++ b/drivers/pwm/pwm-twl.c
@@ -18,6 +18,7 @@
18 */ 18 */
19 19
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/of.h>
21#include <linux/platform_device.h> 22#include <linux/platform_device.h>
22#include <linux/pwm.h> 23#include <linux/pwm.h>
23#include <linux/i2c/twl.h> 24#include <linux/i2c/twl.h>
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index 36db5d98dd2f..fb80d68f4d33 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -10,6 +10,8 @@
10 * published by the Free Software Foundation. 10 * published by the Free Software Foundation.
11 */ 11 */
12 12
13#include <linux/gpio.h>
14#include <linux/of_gpio.h>
13#include <linux/module.h> 15#include <linux/module.h>
14#include <linux/kernel.h> 16#include <linux/kernel.h>
15#include <linux/init.h> 17#include <linux/init.h>
@@ -19,6 +21,7 @@
19#include <linux/err.h> 21#include <linux/err.h>
20#include <linux/pwm.h> 22#include <linux/pwm.h>
21#include <linux/pwm_backlight.h> 23#include <linux/pwm_backlight.h>
24#include <linux/regulator/consumer.h>
22#include <linux/slab.h> 25#include <linux/slab.h>
23 26
24struct pwm_bl_data { 27struct pwm_bl_data {
@@ -27,6 +30,11 @@ struct pwm_bl_data {
27 unsigned int period; 30 unsigned int period;
28 unsigned int lth_brightness; 31 unsigned int lth_brightness;
29 unsigned int *levels; 32 unsigned int *levels;
33 bool enabled;
34 struct regulator *power_supply;
35 int enable_gpio;
36 unsigned long enable_gpio_flags;
37 unsigned int scale;
30 int (*notify)(struct device *, 38 int (*notify)(struct device *,
31 int brightness); 39 int brightness);
32 void (*notify_after)(struct device *, 40 void (*notify_after)(struct device *,
@@ -35,11 +43,65 @@ struct pwm_bl_data {
35 void (*exit)(struct device *); 43 void (*exit)(struct device *);
36}; 44};
37 45
46static void pwm_backlight_power_on(struct pwm_bl_data *pb, int brightness)
47{
48 int err;
49
50 if (pb->enabled)
51 return;
52
53 err = regulator_enable(pb->power_supply);
54 if (err < 0)
55 dev_err(pb->dev, "failed to enable power supply\n");
56
57 if (gpio_is_valid(pb->enable_gpio)) {
58 if (pb->enable_gpio_flags & PWM_BACKLIGHT_GPIO_ACTIVE_LOW)
59 gpio_set_value(pb->enable_gpio, 0);
60 else
61 gpio_set_value(pb->enable_gpio, 1);
62 }
63
64 pwm_enable(pb->pwm);
65 pb->enabled = true;
66}
67
68static void pwm_backlight_power_off(struct pwm_bl_data *pb)
69{
70 if (!pb->enabled)
71 return;
72
73 pwm_config(pb->pwm, 0, pb->period);
74 pwm_disable(pb->pwm);
75
76 if (gpio_is_valid(pb->enable_gpio)) {
77 if (pb->enable_gpio_flags & PWM_BACKLIGHT_GPIO_ACTIVE_LOW)
78 gpio_set_value(pb->enable_gpio, 1);
79 else
80 gpio_set_value(pb->enable_gpio, 0);
81 }
82
83 regulator_disable(pb->power_supply);
84 pb->enabled = false;
85}
86
87static int compute_duty_cycle(struct pwm_bl_data *pb, int brightness)
88{
89 unsigned int lth = pb->lth_brightness;
90 int duty_cycle;
91
92 if (pb->levels)
93 duty_cycle = pb->levels[brightness];
94 else
95 duty_cycle = brightness;
96
97 return (duty_cycle * (pb->period - lth) / pb->scale) + lth;
98}
99
38static int pwm_backlight_update_status(struct backlight_device *bl) 100static int pwm_backlight_update_status(struct backlight_device *bl)
39{ 101{
40 struct pwm_bl_data *pb = bl_get_data(bl); 102 struct pwm_bl_data *pb = bl_get_data(bl);
41 int brightness = bl->props.brightness; 103 int brightness = bl->props.brightness;
42 int max = bl->props.max_brightness; 104 int duty_cycle;
43 105
44 if (bl->props.power != FB_BLANK_UNBLANK || 106 if (bl->props.power != FB_BLANK_UNBLANK ||
45 bl->props.fb_blank != FB_BLANK_UNBLANK || 107 bl->props.fb_blank != FB_BLANK_UNBLANK ||
@@ -49,24 +111,12 @@ static int pwm_backlight_update_status(struct backlight_device *bl)
49 if (pb->notify) 111 if (pb->notify)
50 brightness = pb->notify(pb->dev, brightness); 112 brightness = pb->notify(pb->dev, brightness);
51 113
52 if (brightness == 0) { 114 if (brightness > 0) {
53 pwm_config(pb->pwm, 0, pb->period); 115 duty_cycle = compute_duty_cycle(pb, brightness);
54 pwm_disable(pb->pwm);
55 } else {
56 int duty_cycle;
57
58 if (pb->levels) {
59 duty_cycle = pb->levels[brightness];
60 max = pb->levels[max];
61 } else {
62 duty_cycle = brightness;
63 }
64
65 duty_cycle = pb->lth_brightness +
66 (duty_cycle * (pb->period - pb->lth_brightness) / max);
67 pwm_config(pb->pwm, duty_cycle, pb->period); 116 pwm_config(pb->pwm, duty_cycle, pb->period);
68 pwm_enable(pb->pwm); 117 pwm_backlight_power_on(pb, brightness);
69 } 118 } else
119 pwm_backlight_power_off(pb);
70 120
71 if (pb->notify_after) 121 if (pb->notify_after)
72 pb->notify_after(pb->dev, brightness); 122 pb->notify_after(pb->dev, brightness);
@@ -98,6 +148,7 @@ static int pwm_backlight_parse_dt(struct device *dev,
98 struct platform_pwm_backlight_data *data) 148 struct platform_pwm_backlight_data *data)
99{ 149{
100 struct device_node *node = dev->of_node; 150 struct device_node *node = dev->of_node;
151 enum of_gpio_flags flags;
101 struct property *prop; 152 struct property *prop;
102 int length; 153 int length;
103 u32 value; 154 u32 value;
@@ -138,11 +189,13 @@ static int pwm_backlight_parse_dt(struct device *dev,
138 data->max_brightness--; 189 data->max_brightness--;
139 } 190 }
140 191
141 /* 192 data->enable_gpio = of_get_named_gpio_flags(node, "enable-gpios", 0,
142 * TODO: Most users of this driver use a number of GPIOs to control 193 &flags);
143 * backlight power. Support for specifying these needs to be 194 if (data->enable_gpio == -EPROBE_DEFER)
144 * added. 195 return -EPROBE_DEFER;
145 */ 196
197 if (gpio_is_valid(data->enable_gpio) && (flags & OF_GPIO_ACTIVE_LOW))
198 data->enable_gpio_flags |= PWM_BACKLIGHT_GPIO_ACTIVE_LOW;
146 199
147 return 0; 200 return 0;
148} 201}
@@ -168,7 +221,6 @@ static int pwm_backlight_probe(struct platform_device *pdev)
168 struct backlight_properties props; 221 struct backlight_properties props;
169 struct backlight_device *bl; 222 struct backlight_device *bl;
170 struct pwm_bl_data *pb; 223 struct pwm_bl_data *pb;
171 unsigned int max;
172 int ret; 224 int ret;
173 225
174 if (!data) { 226 if (!data) {
@@ -195,16 +247,46 @@ static int pwm_backlight_probe(struct platform_device *pdev)
195 } 247 }
196 248
197 if (data->levels) { 249 if (data->levels) {
198 max = data->levels[data->max_brightness]; 250 unsigned int i;
251
252 for (i = 0; i <= data->max_brightness; i++)
253 if (data->levels[i] > pb->scale)
254 pb->scale = data->levels[i];
255
199 pb->levels = data->levels; 256 pb->levels = data->levels;
200 } else 257 } else
201 max = data->max_brightness; 258 pb->scale = data->max_brightness;
202 259
260 pb->enable_gpio = data->enable_gpio;
261 pb->enable_gpio_flags = data->enable_gpio_flags;
203 pb->notify = data->notify; 262 pb->notify = data->notify;
204 pb->notify_after = data->notify_after; 263 pb->notify_after = data->notify_after;
205 pb->check_fb = data->check_fb; 264 pb->check_fb = data->check_fb;
206 pb->exit = data->exit; 265 pb->exit = data->exit;
207 pb->dev = &pdev->dev; 266 pb->dev = &pdev->dev;
267 pb->enabled = false;
268
269 if (gpio_is_valid(pb->enable_gpio)) {
270 unsigned long flags;
271
272 if (pb->enable_gpio_flags & PWM_BACKLIGHT_GPIO_ACTIVE_LOW)
273 flags = GPIOF_OUT_INIT_HIGH;
274 else
275 flags = GPIOF_OUT_INIT_LOW;
276
277 ret = gpio_request_one(pb->enable_gpio, flags, "enable");
278 if (ret < 0) {
279 dev_err(&pdev->dev, "failed to request GPIO#%d: %d\n",
280 pb->enable_gpio, ret);
281 goto err_alloc;
282 }
283 }
284
285 pb->power_supply = devm_regulator_get(&pdev->dev, "power");
286 if (IS_ERR(pb->power_supply)) {
287 ret = PTR_ERR(pb->power_supply);
288 goto err_gpio;
289 }
208 290
209 pb->pwm = devm_pwm_get(&pdev->dev, NULL); 291 pb->pwm = devm_pwm_get(&pdev->dev, NULL);
210 if (IS_ERR(pb->pwm)) { 292 if (IS_ERR(pb->pwm)) {
@@ -214,7 +296,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
214 if (IS_ERR(pb->pwm)) { 296 if (IS_ERR(pb->pwm)) {
215 dev_err(&pdev->dev, "unable to request legacy PWM\n"); 297 dev_err(&pdev->dev, "unable to request legacy PWM\n");
216 ret = PTR_ERR(pb->pwm); 298 ret = PTR_ERR(pb->pwm);
217 goto err_alloc; 299 goto err_gpio;
218 } 300 }
219 } 301 }
220 302
@@ -229,7 +311,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
229 pwm_set_period(pb->pwm, data->pwm_period_ns); 311 pwm_set_period(pb->pwm, data->pwm_period_ns);
230 312
231 pb->period = pwm_get_period(pb->pwm); 313 pb->period = pwm_get_period(pb->pwm);
232 pb->lth_brightness = data->lth_brightness * (pb->period / max); 314 pb->lth_brightness = data->lth_brightness * (pb->period / pb->scale);
233 315
234 memset(&props, 0, sizeof(struct backlight_properties)); 316 memset(&props, 0, sizeof(struct backlight_properties));
235 props.type = BACKLIGHT_RAW; 317 props.type = BACKLIGHT_RAW;
@@ -239,7 +321,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
239 if (IS_ERR(bl)) { 321 if (IS_ERR(bl)) {
240 dev_err(&pdev->dev, "failed to register backlight\n"); 322 dev_err(&pdev->dev, "failed to register backlight\n");
241 ret = PTR_ERR(bl); 323 ret = PTR_ERR(bl);
242 goto err_alloc; 324 goto err_gpio;
243 } 325 }
244 326
245 if (data->dft_brightness > data->max_brightness) { 327 if (data->dft_brightness > data->max_brightness) {
@@ -255,6 +337,9 @@ static int pwm_backlight_probe(struct platform_device *pdev)
255 platform_set_drvdata(pdev, bl); 337 platform_set_drvdata(pdev, bl);
256 return 0; 338 return 0;
257 339
340err_gpio:
341 if (gpio_is_valid(pb->enable_gpio))
342 gpio_free(pb->enable_gpio);
258err_alloc: 343err_alloc:
259 if (data->exit) 344 if (data->exit)
260 data->exit(&pdev->dev); 345 data->exit(&pdev->dev);
@@ -267,10 +352,11 @@ static int pwm_backlight_remove(struct platform_device *pdev)
267 struct pwm_bl_data *pb = bl_get_data(bl); 352 struct pwm_bl_data *pb = bl_get_data(bl);
268 353
269 backlight_device_unregister(bl); 354 backlight_device_unregister(bl);
270 pwm_config(pb->pwm, 0, pb->period); 355 pwm_backlight_power_off(pb);
271 pwm_disable(pb->pwm); 356
272 if (pb->exit) 357 if (pb->exit)
273 pb->exit(&pdev->dev); 358 pb->exit(&pdev->dev);
359
274 return 0; 360 return 0;
275} 361}
276 362
@@ -282,10 +368,12 @@ static int pwm_backlight_suspend(struct device *dev)
282 368
283 if (pb->notify) 369 if (pb->notify)
284 pb->notify(pb->dev, 0); 370 pb->notify(pb->dev, 0);
285 pwm_config(pb->pwm, 0, pb->period); 371
286 pwm_disable(pb->pwm); 372 pwm_backlight_power_off(pb);
373
287 if (pb->notify_after) 374 if (pb->notify_after)
288 pb->notify_after(pb->dev, 0); 375 pb->notify_after(pb->dev, 0);
376
289 return 0; 377 return 0;
290} 378}
291 379
@@ -294,12 +382,19 @@ static int pwm_backlight_resume(struct device *dev)
294 struct backlight_device *bl = dev_get_drvdata(dev); 382 struct backlight_device *bl = dev_get_drvdata(dev);
295 383
296 backlight_update_status(bl); 384 backlight_update_status(bl);
385
297 return 0; 386 return 0;
298} 387}
299#endif 388#endif
300 389
301static SIMPLE_DEV_PM_OPS(pwm_backlight_pm_ops, pwm_backlight_suspend, 390static const struct dev_pm_ops pwm_backlight_pm_ops = {
302 pwm_backlight_resume); 391#ifdef CONFIG_PM_SLEEP
392 .suspend = pwm_backlight_suspend,
393 .resume = pwm_backlight_resume,
394 .poweroff = pwm_backlight_suspend,
395 .restore = pwm_backlight_resume,
396#endif
397};
303 398
304static struct platform_driver pwm_backlight_driver = { 399static struct platform_driver pwm_backlight_driver = {
305 .driver = { 400 .driver = {
@@ -317,4 +412,3 @@ module_platform_driver(pwm_backlight_driver);
317MODULE_DESCRIPTION("PWM based Backlight Driver"); 412MODULE_DESCRIPTION("PWM based Backlight Driver");
318MODULE_LICENSE("GPL"); 413MODULE_LICENSE("GPL");
319MODULE_ALIAS("platform:pwm-backlight"); 414MODULE_ALIAS("platform:pwm-backlight");
320
diff --git a/include/linux/pwm_backlight.h b/include/linux/pwm_backlight.h
index 56f4a866539a..2de2e275b2cb 100644
--- a/include/linux/pwm_backlight.h
+++ b/include/linux/pwm_backlight.h
@@ -6,6 +6,9 @@
6 6
7#include <linux/backlight.h> 7#include <linux/backlight.h>
8 8
9/* TODO: convert to gpiod_*() API once it has been merged */
10#define PWM_BACKLIGHT_GPIO_ACTIVE_LOW (1 << 0)
11
9struct platform_pwm_backlight_data { 12struct platform_pwm_backlight_data {
10 int pwm_id; 13 int pwm_id;
11 unsigned int max_brightness; 14 unsigned int max_brightness;
@@ -13,6 +16,8 @@ struct platform_pwm_backlight_data {
13 unsigned int lth_brightness; 16 unsigned int lth_brightness;
14 unsigned int pwm_period_ns; 17 unsigned int pwm_period_ns;
15 unsigned int *levels; 18 unsigned int *levels;
19 int enable_gpio;
20 unsigned long enable_gpio_flags;
16 int (*init)(struct device *dev); 21 int (*init)(struct device *dev);
17 int (*notify)(struct device *dev, int brightness); 22 int (*notify)(struct device *dev, int brightness);
18 void (*notify_after)(struct device *dev, int brightness); 23 void (*notify_after)(struct device *dev, int brightness);