Merge tag 'pwm/for-3.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 16 Nov 2013 20:21:40 +0000 (12:21 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 16 Nov 2013 20:21:40 +0000 (12:21 -0800)
Pull pwm changes from Thierry Reding:
 "Mostly bug fixes and clean up.  There is a new driver, which is
  actually moving a custom PWM driver from drivers/misc.

  The majority of the patches are enhancements to the device tree
  support in the pwm-backlight driver.  Backlights can now additionally
  be powered using a regulator and enabled using a GPIO in addition to
  just the PWM input"

* tag 'pwm/for-3.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm: (30 commits)
  Documentation/pwm: Update supported SoC name for pwm-samsung
  pwm: samsung: Fix kernel warning while unexporting a channel
  MAINTAINERS: Move PWM subsystem tree to kernel.org
  Documentation/pwm: Fix trivial typos
  pwm-backlight: Remove unused variable
  pwm_backlight: avoid short blank screen while doing hibernation
  pwm-backlight: Fix brightness adjustment
  pwm: add ep93xx PWM support
  pwm-backlight: Allow for non-increasing brightness levels
  pwm-backlight: Add power supply support
  pwm-backlight: Use new enable_gpio field
  unicore32: Initialize PWM backlight enable_gpio field
  ARM: shmobile: Initialize PWM backlight enable_gpio field
  ARM: SAMSUNG: Initialize PWM backlight enable_gpio field
  ARM: pxa: Initialize PWM backlight enable_gpio field
  ARM: OMAP: Initialize PWM backlight enable_gpio field
  pwm-backlight: Add optional enable GPIO
  pwm-backlight: Track enable state
  pwm-backlight: Refactor backlight power on/off
  pwm-backlight: Improve readability
  ...

51 files changed:
Documentation/devicetree/bindings/pwm/pwm-samsung.txt
Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt
Documentation/pwm.txt
MAINTAINERS
arch/arm/mach-pxa/cm-x300.c
arch/arm/mach-pxa/colibri-pxa270-income.c
arch/arm/mach-pxa/ezx.c
arch/arm/mach-pxa/hx4700.c
arch/arm/mach-pxa/lpd270.c
arch/arm/mach-pxa/magician.c
arch/arm/mach-pxa/mainstone.c
arch/arm/mach-pxa/mioa701.c
arch/arm/mach-pxa/palm27x.c
arch/arm/mach-pxa/palmtc.c
arch/arm/mach-pxa/palmte2.c
arch/arm/mach-pxa/pcm990-baseboard.c
arch/arm/mach-pxa/raumfeld.c
arch/arm/mach-pxa/tavorevb.c
arch/arm/mach-pxa/viper.c
arch/arm/mach-pxa/z2.c
arch/arm/mach-pxa/zylonite.c
arch/arm/mach-s3c24xx/mach-h1940.c
arch/arm/mach-s3c24xx/mach-rx1950.c
arch/arm/mach-s3c64xx/mach-crag6410.c
arch/arm/mach-s3c64xx/mach-hmt.c
arch/arm/mach-s3c64xx/mach-smartq.c
arch/arm/mach-s3c64xx/mach-smdk6410.c
arch/arm/mach-s5p64x0/mach-smdk6440.c
arch/arm/mach-s5p64x0/mach-smdk6450.c
arch/arm/mach-s5pc100/mach-smdkc100.c
arch/arm/mach-s5pv210/mach-smdkv210.c
arch/arm/mach-shmobile/board-armadillo800eva.c
arch/arm/plat-samsung/dev-backlight.c
arch/unicore32/kernel/puv3-nb0916.c
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/ep93xx_pwm.c [deleted file]
drivers/pwm/Kconfig
drivers/pwm/Makefile
drivers/pwm/pwm-atmel-tcb.c
drivers/pwm/pwm-ep93xx.c [new file with mode: 0644]
drivers/pwm/pwm-imx.c
drivers/pwm/pwm-lpc32xx.c
drivers/pwm/pwm-mxs.c
drivers/pwm/pwm-samsung.c
drivers/pwm/pwm-tiecap.c
drivers/pwm/pwm-tiehrpwm.c
drivers/pwm/pwm-twl-led.c
drivers/pwm/pwm-twl.c
drivers/video/backlight/pwm_bl.c
include/linux/pwm_backlight.h

index d61fccd40bad42a746374c29f8589891bb75621f..5538de9c20077566c4dec8243fcba0f78778f4fc 100644 (file)
@@ -15,7 +15,7 @@ Required properties:
     samsung,s5pc100-pwm - for 32-bit timers present on S5PC100, S5PV210,
                          Exynos4210 rev0 SoCs
     samsung,exynos4210-pwm - for 32-bit timers present on Exynos4210,
-                          Exynos4x12 and Exynos5250 SoCs
+                          Exynos4x12, Exynos5250 and Exynos5420 SoCs
 - reg: base address and size of register area
 - interrupts: list of timer interrupts (one interrupt per timer, starting at
   timer 0)
index 1e4fc727f3b180f84242a3d77b3854ad113b4a60..764db86d441ad131aceca0e15146d5c914d97919 100644 (file)
@@ -10,12 +10,16 @@ Required properties:
       last value in the array represents a 100% duty cycle (brightest).
   - default-brightness-level: the default brightness level (index into the
       array defined by the "brightness-levels" property)
+  - power-supply: regulator for supply voltage
 
 Optional properties:
   - pwm-names: a list of names for the PWM devices specified in the
                "pwms" property (see PWM binding[0])
+  - enable-gpios: contains a single GPIO specifier for the GPIO which enables
+                  and disables the backlight (see GPIO binding[1])
 
 [0]: Documentation/devicetree/bindings/pwm/pwm.txt
+[1]: Documentation/devicetree/bindings/gpio/gpio.txt
 
 Example:
 
@@ -25,4 +29,7 @@ Example:
 
                brightness-levels = <0 4 8 16 32 64 128 255>;
                default-brightness-level = <6>;
+
+               power-supply = <&vdd_bl_reg>;
+               enable-gpios = <&gpio 58 0>;
        };
index 1039b68fe9c62aa773f4e90e68613870c0cd9db3..93cb979749860f323bb797ce2adc2923d629e1ed 100644 (file)
@@ -39,7 +39,7 @@ New users should use the pwm_get() function and pass to it the consumer
 device or a consumer name. pwm_put() is used to free the PWM device. Managed
 variants of these functions, devm_pwm_get() and devm_pwm_put(), also exist.
 
-After being requested a PWM has to be configured using:
+After being requested, a PWM has to be configured using:
 
 int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns);
 
@@ -94,7 +94,7 @@ for new drivers to use the generic PWM framework.
 A new PWM controller/chip can be added using pwmchip_add() and removed
 again with pwmchip_remove(). pwmchip_add() takes a filled in struct
 pwm_chip as argument which provides a description of the PWM chip, the
-number of PWM devices provider by the chip and the chip-specific
+number of PWM devices provided by the chip and the chip-specific
 implementation of the supported PWM operations to the framework.
 
 Locking
index aef332323256bbcb34674d3845d80d73819fc197..88bc6edee2627735a9ac79f89f91266d41223b88 100644 (file)
@@ -6785,8 +6785,7 @@ PWM SUBSYSTEM
 M:     Thierry Reding <thierry.reding@gmail.com>
 L:     linux-pwm@vger.kernel.org
 S:     Maintained
-W:     http://gitorious.org/linux-pwm
-T:     git git://gitorious.org/linux-pwm/linux-pwm.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm.git
 F:     Documentation/pwm.txt
 F:     Documentation/devicetree/bindings/pwm/
 F:     include/linux/pwm.h
index f9423493ed36407627f2bf1e7bdab115d58ad2c1..584439bfa59f4ea0631deecac94920eb4eb97280 100644 (file)
@@ -310,6 +310,7 @@ static struct platform_pwm_backlight_data cm_x300_backlight_data = {
        .max_brightness = 100,
        .dft_brightness = 100,
        .pwm_period_ns  = 10000,
+       .enable_gpio    = -1,
 };
 
 static struct platform_device cm_x300_backlight_device = {
index 2d4a7b4d5d78b8c5d69dd985f6fbef683f8699e3..3aa264640c9dd5a0457b99e5a34897bd684ad3ba 100644 (file)
@@ -189,6 +189,7 @@ static struct platform_pwm_backlight_data income_backlight_data = {
        .max_brightness = 0x3ff,
        .dft_brightness = 0x1ff,
        .pwm_period_ns  = 1000000,
+       .enable_gpio    = -1,
 };
 
 static struct platform_device income_backlight = {
index fe2eb8394dffe9c289a0a3a2214efc4af24bdb0b..ab93441e596ed7eb6d3e0f4552d029626e81e42c 100644 (file)
@@ -54,6 +54,7 @@ static struct platform_pwm_backlight_data ezx_backlight_data = {
        .max_brightness = 1023,
        .dft_brightness = 1023,
        .pwm_period_ns  = 78770,
+       .enable_gpio    = -1,
 };
 
 static struct platform_device ezx_backlight_device = {
index 133109ec7332b23d1c412509f66a31f52aaaa412..a7c30eb0c8db18aaffd429ec7e637a14a892ad81 100644 (file)
@@ -561,6 +561,7 @@ static struct platform_pwm_backlight_data backlight_data = {
        .max_brightness = 200,
        .dft_brightness = 100,
        .pwm_period_ns  = 30923,
+       .enable_gpio    = -1,
 };
 
 static struct platform_device backlight = {
index 1255ee00f3d1d7c1f80f9cd0b2a28936c47353ad..9f6ec167902a6bc1c2db823d257e006550a3c3b0 100644 (file)
@@ -269,6 +269,7 @@ static struct platform_pwm_backlight_data lpd270_backlight_data = {
        .max_brightness = 1,
        .dft_brightness = 1,
        .pwm_period_ns  = 78770,
+       .enable_gpio    = -1,
 };
 
 static struct platform_device lpd270_backlight_device = {
index f44532fc648b1982ded0d249a18005b84647767d..fab30d666cc72534493839521324a577a40e5a54 100644 (file)
@@ -378,6 +378,7 @@ static struct platform_pwm_backlight_data backlight_data = {
        .max_brightness = 272,
        .dft_brightness = 100,
        .pwm_period_ns  = 30923,
+       .enable_gpio    = -1,
        .init           = magician_backlight_init,
        .notify         = magician_backlight_notify,
        .exit           = magician_backlight_exit,
index dd70343c87085edf4da384fedd434a339802756c..08ccc0718f319e4f7209e8592e50d0f26b92862d 100644 (file)
@@ -338,6 +338,7 @@ static struct platform_pwm_backlight_data mainstone_backlight_data = {
        .max_brightness = 1023,
        .dft_brightness = 1023,
        .pwm_period_ns  = 78770,
+       .enable_gpio    = -1,
 };
 
 static struct platform_device mainstone_backlight_device = {
index acc9d3cc0762174f071a22a93cf8ae34f49b9cbb..f70583fee59f8b61e59a1022f07b36c26fd3210c 100644 (file)
@@ -186,6 +186,7 @@ static struct platform_pwm_backlight_data mioa701_backlight_data = {
        .max_brightness = 100,
        .dft_brightness = 50,
        .pwm_period_ns  = 4000 * 1024,  /* Fl = 250kHz */
+       .enable_gpio    = -1,
 };
 
 /*
index 17d4c53017cade633c95315782128c0e0620c776..e54a296fb81f8b045f814860c0dc729edb71d2c4 100644 (file)
@@ -322,6 +322,7 @@ static struct platform_pwm_backlight_data palm27x_backlight_data = {
        .max_brightness = 0xfe,
        .dft_brightness = 0x7e,
        .pwm_period_ns  = 3500 * 1024,
+       .enable_gpio    = -1,
        .init           = palm27x_backlight_init,
        .notify         = palm27x_backlight_notify,
        .exit           = palm27x_backlight_exit,
index 100b176f7e882aaa2ba5047fefc19eb44d514394..7691c974ca4bd0b6ade4c467e3ea6a26c611d9ce 100644 (file)
@@ -166,45 +166,12 @@ static inline void palmtc_keys_init(void) {}
  * Backlight
  ******************************************************************************/
 #if defined(CONFIG_BACKLIGHT_PWM) || defined(CONFIG_BACKLIGHT_PWM_MODULE)
-static int palmtc_backlight_init(struct device *dev)
-{
-       int ret;
-
-       ret = gpio_request(GPIO_NR_PALMTC_BL_POWER, "BL POWER");
-       if (ret)
-               goto err;
-       ret = gpio_direction_output(GPIO_NR_PALMTC_BL_POWER, 1);
-       if (ret)
-               goto err2;
-
-       return 0;
-
-err2:
-       gpio_free(GPIO_NR_PALMTC_BL_POWER);
-err:
-       return ret;
-}
-
-static int palmtc_backlight_notify(struct device *dev, int brightness)
-{
-       /* backlight is on when GPIO16 AF0 is high */
-       gpio_set_value(GPIO_NR_PALMTC_BL_POWER, brightness);
-       return brightness;
-}
-
-static void palmtc_backlight_exit(struct device *dev)
-{
-       gpio_free(GPIO_NR_PALMTC_BL_POWER);
-}
-
 static struct platform_pwm_backlight_data palmtc_backlight_data = {
        .pwm_id         = 1,
        .max_brightness = PALMTC_MAX_INTENSITY,
        .dft_brightness = PALMTC_MAX_INTENSITY,
        .pwm_period_ns  = PALMTC_PERIOD_NS,
-       .init           = palmtc_backlight_init,
-       .notify         = palmtc_backlight_notify,
-       .exit           = palmtc_backlight_exit,
+       .enable_gpio    = GPIO_NR_PALMTC_BL_POWER,
 };
 
 static struct platform_device palmtc_backlight = {
index 0742721ced2da7eebf983026f288265e039e139f..956fd24ee6fdca69b63bed29ebe4b9ebe567fd83 100644 (file)
@@ -165,6 +165,7 @@ static struct platform_pwm_backlight_data palmte2_backlight_data = {
        .max_brightness = PALMTE2_MAX_INTENSITY,
        .dft_brightness = PALMTE2_MAX_INTENSITY,
        .pwm_period_ns  = PALMTE2_PERIOD_NS,
+       .enable_gpio    = -1,
        .init           = palmte2_backlight_init,
        .notify         = palmte2_backlight_notify,
        .exit           = palmte2_backlight_exit,
index 3133ba82c50807ec105a57f1dfe4b7d06a887c31..9a4e470f162bc0fc2403a1985e25d0cfd5bd2018 100644 (file)
@@ -153,6 +153,7 @@ static struct platform_pwm_backlight_data pcm990_backlight_data = {
        .max_brightness = 1023,
        .dft_brightness = 1023,
        .pwm_period_ns  = 78770,
+       .enable_gpio    = -1,
 };
 
 static struct platform_device pcm990_backlight_device = {
index 969b0ba7fa703a688a7078250c2118a3e19fe4b3..8386dc30b3e40d7c8eefac202411159932553327 100644 (file)
@@ -539,6 +539,7 @@ static struct platform_pwm_backlight_data raumfeld_pwm_backlight_data = {
        .dft_brightness = 100,
        /* 10000 ns = 10 ms ^= 100 kHz */
        .pwm_period_ns  = 10000,
+       .enable_gpio    = -1,
 };
 
 static struct platform_device raumfeld_pwm_backlight_device = {
index 4680efe553459bd6c98e3d4c771d7633c3a840a1..a71da84e784b75fcf9f740758ee0cb0604d3f741 100644 (file)
@@ -175,6 +175,7 @@ static struct platform_pwm_backlight_data tavorevb_backlight_data[] = {
                .max_brightness = 100,
                .dft_brightness = 100,
                .pwm_period_ns  = 100000,
+               .enable_gpio    = -1,
        },
        [1] = {
                /* secondary backlight */
@@ -182,6 +183,7 @@ static struct platform_pwm_backlight_data tavorevb_backlight_data[] = {
                .max_brightness = 100,
                .dft_brightness = 100,
                .pwm_period_ns  = 100000,
+               .enable_gpio    = -1,
        },
 };
 
index 9c363c081d3facb3be9ebe8693b32c2db9702bbc..29905b127ad988b68ec02a09b441cb48e9c59704 100644 (file)
@@ -401,6 +401,7 @@ static struct platform_pwm_backlight_data viper_backlight_data = {
        .max_brightness = 100,
        .dft_brightness = 100,
        .pwm_period_ns  = 1000000,
+       .enable_gpio    = -1,
        .init           = viper_backlight_init,
        .notify         = viper_backlight_notify,
        .exit           = viper_backlight_exit,
index 2513d8f4931f49675dfd8322edd03c2ffbd3ca0f..e1a121b36cfa6eef0e9dec7155da7f929e1075ed 100644 (file)
@@ -206,6 +206,7 @@ static struct platform_pwm_backlight_data z2_backlight_data[] = {
                .max_brightness = 1023,
                .dft_brightness = 0,
                .pwm_period_ns  = 1260320,
+               .enable_gpio    = -1,
        },
        [1] = {
                /* LCD Backlight */
@@ -213,6 +214,7 @@ static struct platform_pwm_backlight_data z2_backlight_data[] = {
                .max_brightness = 1023,
                .dft_brightness = 512,
                .pwm_period_ns  = 1260320,
+               .enable_gpio    = -1,
        },
 };
 
index 36cf7cf95ec1d5d4fe2fd764067b7d640247aa2e..77daea478e88709aa20568d30073ae3c625efa73 100644 (file)
@@ -125,6 +125,7 @@ static struct platform_pwm_backlight_data zylonite_backlight_data = {
        .max_brightness = 100,
        .dft_brightness = 100,
        .pwm_period_ns  = 10000,
+       .enable_gpio    = -1,
 };
 
 static struct platform_device zylonite_backlight_device = {
index 74dd47988b415b217dbcd931794e4fd40d5dcdd4..952b6a040d1fcaa5694d21459acec9880ba626f0 100644 (file)
@@ -504,6 +504,7 @@ static struct platform_pwm_backlight_data backlight_data = {
        .dft_brightness = 50,
        /* tcnt = 0x31 */
        .pwm_period_ns  = 36296,
+       .enable_gpio    = -1,
        .init           = h1940_backlight_init,
        .notify         = h1940_backlight_notify,
        .exit           = h1940_backlight_exit,
index 206b1f7546d16e973aaa60030ce777684cdbfe57..034b7fe45c49294908bfc5b3716d52f6d9bec3e6 100644 (file)
@@ -522,6 +522,7 @@ static struct platform_pwm_backlight_data rx1950_backlight_data = {
        .max_brightness = 24,
        .dft_brightness = 4,
        .pwm_period_ns = 48000,
+       .enable_gpio = -1,
        .init = rx1950_backlight_init,
        .notify = rx1950_backlight_notify,
        .exit = rx1950_backlight_exit,
index aca7d16e195dec0fda2989680cc58e73abb50315..758e31b265501de472aa6eba453038385e102536 100644 (file)
@@ -114,6 +114,7 @@ static struct platform_pwm_backlight_data crag6410_backlight_data = {
        .max_brightness = 1000,
        .dft_brightness = 600,
        .pwm_period_ns  = 100000,       /* about 1kHz */
+       .enable_gpio    = -1,
 };
 
 static struct platform_device crag6410_backlight_device = {
index e8064044ef796d35a12bfcc0e06c86dea065dca1..614a03a92cf70545be3fd60bb66a29dc46b1fb6e 100644 (file)
@@ -114,6 +114,7 @@ static struct platform_pwm_backlight_data hmt_backlight_data = {
        .max_brightness = 100 * 256,
        .dft_brightness = 40 * 256,
        .pwm_period_ns  = 1000000000 / (100 * 256 * 20),
+       .enable_gpio    = -1,
        .init           = hmt_bl_init,
        .notify         = hmt_bl_notify,
        .exit           = hmt_bl_exit,
index 0f47237be3b2dd2286fe0582791548d16df3a786..a6b338fd0470d6b55f0601058f4dc5446cfc480c 100644 (file)
@@ -151,6 +151,7 @@ static struct platform_pwm_backlight_data smartq_backlight_data = {
        .max_brightness = 1000,
        .dft_brightness = 600,
        .pwm_period_ns  = 1000000000 / (1000 * 20),
+       .enable_gpio    = -1,
        .init           = smartq_bl_init,
 };
 
index 2a7b32ca5c96a3037c007eeb032092cf2127bfec..d5ea938cc9a1a03f7b6f884155de620a3fc0c3b3 100644 (file)
@@ -625,6 +625,7 @@ static struct samsung_bl_gpio_info smdk6410_bl_gpio_info = {
 
 static struct platform_pwm_backlight_data smdk6410_bl_data = {
        .pwm_id = 1,
+       .enable_gpio = -1,
 };
 
 static struct s3c_hsotg_plat smdk6410_hsotg_pdata;
index 0b00304c1e91840f1760c4cae2c80b4d9441ea79..9efdcc03df3b5477bc51ccb8196f0f7fcccabd97 100644 (file)
@@ -223,6 +223,7 @@ static struct samsung_bl_gpio_info smdk6440_bl_gpio_info = {
 
 static struct platform_pwm_backlight_data smdk6440_bl_data = {
        .pwm_id = 1,
+       .enable_gpio = -1,
 };
 
 static void __init smdk6440_map_io(void)
index 5949296e88fdc07af89538478f88e0a142e5f3b7..c3cacc067efed25aff9740a2d65b795c4dd59266 100644 (file)
@@ -242,6 +242,7 @@ static struct samsung_bl_gpio_info smdk6450_bl_gpio_info = {
 
 static struct platform_pwm_backlight_data smdk6450_bl_data = {
        .pwm_id = 1,
+       .enable_gpio = -1,
 };
 
 static void __init smdk6450_map_io(void)
index 7c57a221785e65d3aeb55e9c637397b91a857daa..9e256b9fc9303a9bf3b5411e0b8d70287254e036 100644 (file)
@@ -216,6 +216,7 @@ static struct samsung_bl_gpio_info smdkc100_bl_gpio_info = {
 
 static struct platform_pwm_backlight_data smdkc100_bl_data = {
        .pwm_id = 0,
+       .enable_gpio = -1,
 };
 
 static void __init smdkc100_map_io(void)
index 6d72bb992e389b59872b3fead4742d4d3669e3bb..f52cc15c2d85a221a161f5c5d18fbf30c815dd72 100644 (file)
@@ -279,6 +279,7 @@ static struct samsung_bl_gpio_info smdkv210_bl_gpio_info = {
 static struct platform_pwm_backlight_data smdkv210_bl_data = {
        .pwm_id = 3,
        .pwm_period_ns = 1000,
+       .enable_gpio = -1,
 };
 
 static void __init smdkv210_map_io(void)
index 8bc8e4c5884767f381c09da79ffcf2b52e2ffdc9..958e3cbf0ac2f2110e7f4fc9ca41dc19e66e4ca8 100644 (file)
@@ -423,6 +423,7 @@ static struct platform_pwm_backlight_data pwm_backlight_data = {
        .max_brightness = 255,
        .dft_brightness = 255,
        .pwm_period_ns = 33333, /* 30kHz */
+       .enable_gpio = -1,
 };
 
 static struct platform_device pwm_backlight_device = {
index d51f9565567cd1d27a197ab83a7ab35618072147..be4ad0b21c082abf990d00bec2f14d665672e78d 100644 (file)
@@ -70,6 +70,7 @@ static struct samsung_bl_drvdata samsung_dfl_bl_data __initdata = {
                .max_brightness = 255,
                .dft_brightness = 255,
                .pwm_period_ns  = 78770,
+               .enable_gpio    = -1,
                .init           = samsung_bl_init,
                .exit           = samsung_bl_exit,
        },
@@ -121,6 +122,10 @@ void __init samsung_bl_set(struct samsung_bl_gpio_info *gpio_info,
                samsung_bl_data->lth_brightness = bl_data->lth_brightness;
        if (bl_data->pwm_period_ns)
                samsung_bl_data->pwm_period_ns = bl_data->pwm_period_ns;
+       if (bl_data->enable_gpio >= 0)
+               samsung_bl_data->enable_gpio = bl_data->enable_gpio;
+       if (bl_data->enable_gpio_flags)
+               samsung_bl_data->enable_gpio_flags = bl_data->enable_gpio_flags;
        if (bl_data->init)
                samsung_bl_data->init = bl_data->init;
        if (bl_data->notify)
index 181108b8ecce766d0102b9e12ac070e6510337b0..0c6618e7189782674af77f9130ede7b3c71d39e6 100644 (file)
@@ -54,6 +54,7 @@ static struct platform_pwm_backlight_data nb0916_backlight_data = {
        .max_brightness = 100,
        .dft_brightness = 100,
        .pwm_period_ns  = 70 * 1024,
+       .enable_gpio    = -1,
 };
 
 static struct gpio_keys_button nb0916_gpio_keys[] = {
index e760715bd9cbd30c01c6c16da430c06931fb04c1..a3e291d0df9a19211c7b3d855fc31ad3463524ff 100644 (file)
@@ -381,19 +381,6 @@ config HMC6352
          This driver provides support for the Honeywell HMC6352 compass,
          providing configuration and heading data via sysfs.
 
-config EP93XX_PWM
-       tristate "EP93xx PWM support"
-       depends on ARCH_EP93XX
-       help
-         This option enables device driver support for the PWM channels
-         on the Cirrus EP93xx processors.  The EP9307 chip only has one
-         PWM channel all the others have two, the second channel is an
-         alternate function of the EGPIO14 pin.  A sysfs interface is
-         provided to control the PWM channels.
-
-         To compile this driver as a module, choose M here: the module will
-         be called ep93xx_pwm.
-
 config DS1682
        tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm"
        depends on I2C
index 0b7ea3ea8bb86cc3971c7af15258c285100bd8e1..f45473e68bf71d7ab65e40e06c9bf0a0484242e6 100644 (file)
@@ -33,7 +33,6 @@ obj-$(CONFIG_APDS9802ALS)     += apds9802als.o
 obj-$(CONFIG_ISL29003)         += isl29003.o
 obj-$(CONFIG_ISL29020)         += isl29020.o
 obj-$(CONFIG_SENSORS_TSL2550)  += tsl2550.o
-obj-$(CONFIG_EP93XX_PWM)       += ep93xx_pwm.o
 obj-$(CONFIG_DS1682)           += ds1682.o
 obj-$(CONFIG_TI_DAC7512)       += ti_dac7512.o
 obj-$(CONFIG_C2PORT)           += c2port/
diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c
deleted file mode 100644 (file)
index cdb67a9..0000000
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- *  Simple PWM driver for EP93XX
- *
- *     (c) Copyright 2009  Matthieu Crapet <mcrapet@gmail.com>
- *     (c) Copyright 2009  H Hartley Sweeten <hsweeten@visionengravers.com>
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- *  EP9307 has only one channel:
- *    - PWMOUT
- *
- *  EP9301/02/12/15 have two channels:
- *    - PWMOUT
- *    - PWMOUT1 (alternate function for EGPIO14)
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-
-#include <mach/platform.h>
-
-#define EP93XX_PWMx_TERM_COUNT 0x00
-#define EP93XX_PWMx_DUTY_CYCLE 0x04
-#define EP93XX_PWMx_ENABLE     0x08
-#define EP93XX_PWMx_INVERT     0x0C
-
-#define EP93XX_PWM_MAX_COUNT   0xFFFF
-
-struct ep93xx_pwm {
-       void __iomem    *mmio_base;
-       struct clk      *clk;
-       u32             duty_percent;
-};
-
-/*
- * /sys/devices/platform/ep93xx-pwm.N
- *   /min_freq      read-only   minimum pwm output frequency
- *   /max_req       read-only   maximum pwm output frequency
- *   /freq          read-write  pwm output frequency (0 = disable output)
- *   /duty_percent  read-write  pwm duty cycle percent (1..99)
- *   /invert        read-write  invert pwm output
- */
-
-static ssize_t ep93xx_pwm_get_min_freq(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct ep93xx_pwm *pwm = platform_get_drvdata(pdev);
-       unsigned long rate = clk_get_rate(pwm->clk);
-
-       return sprintf(buf, "%ld\n", rate / (EP93XX_PWM_MAX_COUNT + 1));
-}
-
-static ssize_t ep93xx_pwm_get_max_freq(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct ep93xx_pwm *pwm = platform_get_drvdata(pdev);
-       unsigned long rate = clk_get_rate(pwm->clk);
-
-       return sprintf(buf, "%ld\n", rate / 2);
-}
-
-static ssize_t ep93xx_pwm_get_freq(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct ep93xx_pwm *pwm = platform_get_drvdata(pdev);
-
-       if (readl(pwm->mmio_base + EP93XX_PWMx_ENABLE) & 0x1) {
-               unsigned long rate = clk_get_rate(pwm->clk);
-               u16 term = readl(pwm->mmio_base + EP93XX_PWMx_TERM_COUNT);
-
-               return sprintf(buf, "%ld\n", rate / (term + 1));
-       } else {
-               return sprintf(buf, "disabled\n");
-       }
-}
-
-static ssize_t ep93xx_pwm_set_freq(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t count)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct ep93xx_pwm *pwm = platform_get_drvdata(pdev);
-       long val;
-       int err;
-
-       err = kstrtol(buf, 10, &val);
-       if (err)
-               return -EINVAL;
-
-       if (val == 0) {
-               writel(0x0, pwm->mmio_base + EP93XX_PWMx_ENABLE);
-       } else if (val <= (clk_get_rate(pwm->clk) / 2)) {
-               u32 term, duty;
-
-               val = (clk_get_rate(pwm->clk) / val) - 1;
-               if (val > EP93XX_PWM_MAX_COUNT)
-                       val = EP93XX_PWM_MAX_COUNT;
-               if (val < 1)
-                       val = 1;
-
-               term = readl(pwm->mmio_base + EP93XX_PWMx_TERM_COUNT);
-               duty = ((val + 1) * pwm->duty_percent / 100) - 1;
-
-               /* If pwm is running, order is important */
-               if (val > term) {
-                       writel(val, pwm->mmio_base + EP93XX_PWMx_TERM_COUNT);
-                       writel(duty, pwm->mmio_base + EP93XX_PWMx_DUTY_CYCLE);
-               } else {
-                       writel(duty, pwm->mmio_base + EP93XX_PWMx_DUTY_CYCLE);
-                       writel(val, pwm->mmio_base + EP93XX_PWMx_TERM_COUNT);
-               }
-
-               if (!readl(pwm->mmio_base + EP93XX_PWMx_ENABLE) & 0x1)
-                       writel(0x1, pwm->mmio_base + EP93XX_PWMx_ENABLE);
-       } else {
-               return -EINVAL;
-       }
-
-       return count;
-}
-
-static ssize_t ep93xx_pwm_get_duty_percent(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct ep93xx_pwm *pwm = platform_get_drvdata(pdev);
-
-       return sprintf(buf, "%d\n", pwm->duty_percent);
-}
-
-static ssize_t ep93xx_pwm_set_duty_percent(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t count)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct ep93xx_pwm *pwm = platform_get_drvdata(pdev);
-       long val;
-       int err;
-
-       err = kstrtol(buf, 10, &val);
-       if (err)
-               return -EINVAL;
-
-       if (val > 0 && val < 100) {
-               u32 term = readl(pwm->mmio_base + EP93XX_PWMx_TERM_COUNT);
-               u32 duty = ((term + 1) * val / 100) - 1;
-
-               writel(duty, pwm->mmio_base + EP93XX_PWMx_DUTY_CYCLE);
-               pwm->duty_percent = val;
-               return count;
-       }
-
-       return -EINVAL;
-}
-
-static ssize_t ep93xx_pwm_get_invert(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct ep93xx_pwm *pwm = platform_get_drvdata(pdev);
-       int inverted = readl(pwm->mmio_base + EP93XX_PWMx_INVERT) & 0x1;
-
-       return sprintf(buf, "%d\n", inverted);
-}
-
-static ssize_t ep93xx_pwm_set_invert(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t count)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct ep93xx_pwm *pwm = platform_get_drvdata(pdev);
-       long val;
-       int err;
-
-       err = kstrtol(buf, 10, &val);
-       if (err)
-               return -EINVAL;
-
-       if (val == 0)
-               writel(0x0, pwm->mmio_base + EP93XX_PWMx_INVERT);
-       else if (val == 1)
-               writel(0x1, pwm->mmio_base + EP93XX_PWMx_INVERT);
-       else
-               return -EINVAL;
-
-       return count;
-}
-
-static DEVICE_ATTR(min_freq, S_IRUGO, ep93xx_pwm_get_min_freq, NULL);
-static DEVICE_ATTR(max_freq, S_IRUGO, ep93xx_pwm_get_max_freq, NULL);
-static DEVICE_ATTR(freq, S_IWUSR | S_IRUGO,
-                  ep93xx_pwm_get_freq, ep93xx_pwm_set_freq);
-static DEVICE_ATTR(duty_percent, S_IWUSR | S_IRUGO,
-                  ep93xx_pwm_get_duty_percent, ep93xx_pwm_set_duty_percent);
-static DEVICE_ATTR(invert, S_IWUSR | S_IRUGO,
-                  ep93xx_pwm_get_invert, ep93xx_pwm_set_invert);
-
-static struct attribute *ep93xx_pwm_attrs[] = {
-       &dev_attr_min_freq.attr,
-       &dev_attr_max_freq.attr,
-       &dev_attr_freq.attr,
-       &dev_attr_duty_percent.attr,
-       &dev_attr_invert.attr,
-       NULL
-};
-
-static const struct attribute_group ep93xx_pwm_sysfs_files = {
-       .attrs  = ep93xx_pwm_attrs,
-};
-
-static int ep93xx_pwm_probe(struct platform_device *pdev)
-{
-       struct ep93xx_pwm *pwm;
-       struct resource *res;
-       int ret;
-
-       pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL);
-       if (!pwm)
-               return -ENOMEM;
-
-       pwm->clk = devm_clk_get(&pdev->dev, "pwm_clk");
-       if (IS_ERR(pwm->clk))
-               return PTR_ERR(pwm->clk);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       pwm->mmio_base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(pwm->mmio_base))
-               return PTR_ERR(pwm->mmio_base);
-
-       ret = ep93xx_pwm_acquire_gpio(pdev);
-       if (ret)
-               return ret;
-
-       ret = sysfs_create_group(&pdev->dev.kobj, &ep93xx_pwm_sysfs_files);
-       if (ret) {
-               ep93xx_pwm_release_gpio(pdev);
-               return ret;
-       }
-
-       pwm->duty_percent = 50;
-
-       /* disable pwm at startup. Avoids zero value. */
-       writel(0x0, pwm->mmio_base + EP93XX_PWMx_ENABLE);
-       writel(EP93XX_PWM_MAX_COUNT, pwm->mmio_base + EP93XX_PWMx_TERM_COUNT);
-       writel(EP93XX_PWM_MAX_COUNT/2, pwm->mmio_base + EP93XX_PWMx_DUTY_CYCLE);
-
-       clk_enable(pwm->clk);
-
-       platform_set_drvdata(pdev, pwm);
-       return 0;
-}
-
-static int ep93xx_pwm_remove(struct platform_device *pdev)
-{
-       struct ep93xx_pwm *pwm = platform_get_drvdata(pdev);
-
-       writel(0x0, pwm->mmio_base + EP93XX_PWMx_ENABLE);
-       clk_disable(pwm->clk);
-       sysfs_remove_group(&pdev->dev.kobj, &ep93xx_pwm_sysfs_files);
-       ep93xx_pwm_release_gpio(pdev);
-
-       return 0;
-}
-
-static struct platform_driver ep93xx_pwm_driver = {
-       .driver         = {
-               .name   = "ep93xx-pwm",
-               .owner  = THIS_MODULE,
-       },
-       .probe          = ep93xx_pwm_probe,
-       .remove         = ep93xx_pwm_remove,
-};
-module_platform_driver(ep93xx_pwm_driver);
-
-MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>, "
-             "H Hartley Sweeten <hsweeten@visionengravers.com>");
-MODULE_DESCRIPTION("EP93xx PWM driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:ep93xx-pwm");
index 75840b5cea6dfd978d83c5b4c741af0b5af99122..eece329d78729049c4dd7b2e49668217309a5668 100644 (file)
@@ -62,6 +62,15 @@ config PWM_BFIN
          To compile this driver as a module, choose M here: the module
          will be called pwm-bfin.
 
+config PWM_EP93XX
+       tristate "Cirrus Logic EP93xx PWM support"
+       depends on ARCH_EP93XX
+       help
+         Generic PWM framework driver for Cirrus Logic EP93xx.
+
+         To compile this driver as a module, choose M here: the module
+         will be called pwm-ep93xx.
+
 config PWM_IMX
        tristate "i.MX PWM support"
        depends on ARCH_MXC
index 77a8c185c5b2b46c6a4afe0e0a45bc8d5dd772d0..8b754e4dba4aae03cc36562d5e0c079e6327c4d2 100644 (file)
@@ -3,6 +3,7 @@ obj-$(CONFIG_PWM_SYSFS)         += sysfs.o
 obj-$(CONFIG_PWM_AB8500)       += pwm-ab8500.o
 obj-$(CONFIG_PWM_ATMEL_TCB)    += pwm-atmel-tcb.o
 obj-$(CONFIG_PWM_BFIN)         += pwm-bfin.o
+obj-$(CONFIG_PWM_EP93XX)       += pwm-ep93xx.o
 obj-$(CONFIG_PWM_IMX)          += pwm-imx.o
 obj-$(CONFIG_PWM_JZ4740)       += pwm-jz4740.o
 obj-$(CONFIG_PWM_LPC32XX)      += pwm-lpc32xx.o
index ba6ce01035e4feae2c1f40dcf8b24e0ad4923ffa..f3dcd02390f1b5da7d9cf43d3b053d3e6840bc0f 100644 (file)
@@ -249,6 +249,8 @@ static int atmel_tcb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
                }
        }
 
+       cmr |= (tcbpwm->div & ATMEL_TC_TCCLKS);
+
        __raw_writel(cmr, regs + ATMEL_TC_REG(group, CMR));
 
        if (index == 0)
@@ -305,7 +307,7 @@ static int atmel_tcb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
                i = slowclk;
                rate = 32768;
                min = div_u64(NSEC_PER_SEC, rate);
-               max = min << 16;
+               max = min << tc->tcb_config->counter_width;
 
                /* If period is too big return ERANGE error */
                if (max < period_ns)
diff --git a/drivers/pwm/pwm-ep93xx.c b/drivers/pwm/pwm-ep93xx.c
new file mode 100644 (file)
index 0000000..33aa446
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * PWM framework driver for Cirrus Logic EP93xx
+ *
+ * Copyright (c) 2009        Matthieu Crapet <mcrapet@gmail.com>
+ * Copyright (c) 2009, 2013  H Hartley Sweeten <hsweeten@visionengravers.com>
+ *
+ * EP9301/02 have only one channel:
+ *   platform device ep93xx-pwm.1 - PWMOUT1 (EGPIO14)
+ *
+ * EP9307 has only one channel:
+ *   platform device ep93xx-pwm.0 - PWMOUT
+ *
+ * EP9312/15 have two channels:
+ *   platform device ep93xx-pwm.0 - PWMOUT
+ *   platform device ep93xx-pwm.1 - PWMOUT1 (EGPIO14)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/pwm.h>
+
+#include <asm/div64.h>
+
+#include <mach/platform.h>     /* for ep93xx_pwm_{acquire,release}_gpio() */
+
+#define EP93XX_PWMx_TERM_COUNT 0x00
+#define EP93XX_PWMx_DUTY_CYCLE 0x04
+#define EP93XX_PWMx_ENABLE     0x08
+#define EP93XX_PWMx_INVERT     0x0c
+
+struct ep93xx_pwm {
+       void __iomem *base;
+       struct clk *clk;
+       struct pwm_chip chip;
+};
+
+static inline struct ep93xx_pwm *to_ep93xx_pwm(struct pwm_chip *chip)
+{
+       return container_of(chip, struct ep93xx_pwm, chip);
+}
+
+static int ep93xx_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+       struct platform_device *pdev = to_platform_device(chip->dev);
+
+       return ep93xx_pwm_acquire_gpio(pdev);
+}
+
+static void ep93xx_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+       struct platform_device *pdev = to_platform_device(chip->dev);
+
+       ep93xx_pwm_release_gpio(pdev);
+}
+
+static int ep93xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+                            int duty_ns, int period_ns)
+{
+       struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip);
+       void __iomem *base = ep93xx_pwm->base;
+       unsigned long long c;
+       unsigned long period_cycles;
+       unsigned long duty_cycles;
+       unsigned long term;
+       int ret = 0;
+
+       /*
+        * The clock needs to be enabled to access the PWM registers.
+        * Configuration can be changed at any time.
+        */
+       if (!test_bit(PWMF_ENABLED, &pwm->flags)) {
+               ret = clk_enable(ep93xx_pwm->clk);
+               if (ret)
+                       return ret;
+       }
+
+       c = clk_get_rate(ep93xx_pwm->clk);
+       c *= period_ns;
+       do_div(c, 1000000000);
+       period_cycles = c;
+
+       c = period_cycles;
+       c *= duty_ns;
+       do_div(c, period_ns);
+       duty_cycles = c;
+
+       if (period_cycles < 0x10000 && duty_cycles < 0x10000) {
+               term = readw(base + EP93XX_PWMx_TERM_COUNT);
+
+               /* Order is important if PWM is running */
+               if (period_cycles > term) {
+                       writew(period_cycles, base + EP93XX_PWMx_TERM_COUNT);
+                       writew(duty_cycles, base + EP93XX_PWMx_DUTY_CYCLE);
+               } else {
+                       writew(duty_cycles, base + EP93XX_PWMx_DUTY_CYCLE);
+                       writew(period_cycles, base + EP93XX_PWMx_TERM_COUNT);
+               }
+       } else {
+               ret = -EINVAL;
+       }
+
+       if (!test_bit(PWMF_ENABLED, &pwm->flags))
+               clk_disable(ep93xx_pwm->clk);
+
+       return ret;
+}
+
+static int ep93xx_pwm_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
+                              enum pwm_polarity polarity)
+{
+       struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip);
+       int ret;
+
+       /*
+        * The clock needs to be enabled to access the PWM registers.
+        * Polarity can only be changed when the PWM is disabled.
+        */
+       ret = clk_enable(ep93xx_pwm->clk);
+       if (ret)
+               return ret;
+
+       if (polarity == PWM_POLARITY_INVERSED)
+               writew(0x1, ep93xx_pwm->base + EP93XX_PWMx_INVERT);
+       else
+               writew(0x0, ep93xx_pwm->base + EP93XX_PWMx_INVERT);
+
+       clk_disable(ep93xx_pwm->clk);
+
+       return 0;
+}
+
+static int ep93xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+       struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip);
+       int ret;
+
+       ret = clk_enable(ep93xx_pwm->clk);
+       if (ret)
+               return ret;
+
+       writew(0x1, ep93xx_pwm->base + EP93XX_PWMx_ENABLE);
+
+       return 0;
+}
+
+static void ep93xx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+       struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip);
+
+       writew(0x0, ep93xx_pwm->base + EP93XX_PWMx_ENABLE);
+       clk_disable(ep93xx_pwm->clk);
+}
+
+static const struct pwm_ops ep93xx_pwm_ops = {
+       .request = ep93xx_pwm_request,
+       .free = ep93xx_pwm_free,
+       .config = ep93xx_pwm_config,
+       .set_polarity = ep93xx_pwm_polarity,
+       .enable = ep93xx_pwm_enable,
+       .disable = ep93xx_pwm_disable,
+       .owner = THIS_MODULE,
+};
+
+static int ep93xx_pwm_probe(struct platform_device *pdev)
+{
+       struct ep93xx_pwm *ep93xx_pwm;
+       struct resource *res;
+       int ret;
+
+       ep93xx_pwm = devm_kzalloc(&pdev->dev, sizeof(*ep93xx_pwm), GFP_KERNEL);
+       if (!ep93xx_pwm)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       ep93xx_pwm->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(ep93xx_pwm->base))
+               return PTR_ERR(ep93xx_pwm->base);
+
+       ep93xx_pwm->clk = devm_clk_get(&pdev->dev, "pwm_clk");
+       if (IS_ERR(ep93xx_pwm->clk))
+               return PTR_ERR(ep93xx_pwm->clk);
+
+       ep93xx_pwm->chip.dev = &pdev->dev;
+       ep93xx_pwm->chip.ops = &ep93xx_pwm_ops;
+       ep93xx_pwm->chip.base = -1;
+       ep93xx_pwm->chip.npwm = 1;
+
+       ret = pwmchip_add(&ep93xx_pwm->chip);
+       if (ret < 0)
+               return ret;
+
+       platform_set_drvdata(pdev, ep93xx_pwm);
+       return 0;
+}
+
+static int ep93xx_pwm_remove(struct platform_device *pdev)
+{
+       struct ep93xx_pwm *ep93xx_pwm = platform_get_drvdata(pdev);
+
+       return pwmchip_remove(&ep93xx_pwm->chip);
+}
+
+static struct platform_driver ep93xx_pwm_driver = {
+       .driver = {
+               .name = "ep93xx-pwm",
+       },
+       .probe = ep93xx_pwm_probe,
+       .remove = ep93xx_pwm_remove,
+};
+module_platform_driver(ep93xx_pwm_driver);
+
+MODULE_DESCRIPTION("Cirrus Logic EP93xx PWM driver");
+MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>, "
+             "H Hartley Sweeten <hsweeten@visionengravers.com>");
+MODULE_ALIAS("platform:ep93xx-pwm");
+MODULE_LICENSE("GPL");
index 2b7c4f88b461b788c1d683a141d6a402d958af12..cc477334487494fe014ba8993feb8c674fadad3f 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/pwm.h>
+#include <linux/of.h>
 #include <linux/of_device.h>
 
 /* i.MX1 and i.MX21 share the same PWM function block: */
@@ -296,7 +297,7 @@ static struct platform_driver imx_pwm_driver = {
        .driver         = {
                .name   = "imx-pwm",
                .owner = THIS_MODULE,
-               .of_match_table = of_match_ptr(imx_pwm_dt_ids),
+               .of_match_table = imx_pwm_dt_ids,
        },
        .probe          = imx_pwm_probe,
        .remove         = imx_pwm_remove,
index efac99e03d57191c2d8667264cff0a5e8a603dbe..9dc0f9d42bfa3a44807c8f2b3917ad27c3f8f437 100644 (file)
@@ -169,7 +169,7 @@ static struct platform_driver lpc32xx_pwm_driver = {
        .driver = {
                .name = "lpc32xx-pwm",
                .owner = THIS_MODULE,
-               .of_match_table = of_match_ptr(lpc32xx_pwm_dt_ids),
+               .of_match_table = lpc32xx_pwm_dt_ids,
        },
        .probe = lpc32xx_pwm_probe,
        .remove = lpc32xx_pwm_remove,
index c2c5a4fd1b96bb4eede5bdd553911e3da66dee5e..9475bc7a6f97ded7ec293881151747073c198ff3 100644 (file)
@@ -189,7 +189,7 @@ static struct platform_driver mxs_pwm_driver = {
        .driver = {
                .name = "mxs-pwm",
                .owner = THIS_MODULE,
-               .of_match_table = of_match_ptr(mxs_pwm_dt_ids),
+               .of_match_table = mxs_pwm_dt_ids,
        },
        .probe = mxs_pwm_probe,
        .remove = mxs_pwm_remove,
index fcc8b9adde9fe89b2e35ae3ae01312aaff90605c..b59639e0c02978388126a1d7d56d8f3b62c32b6c 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pwm.h>
 #include <linux/slab.h>
@@ -224,8 +225,8 @@ static int pwm_samsung_request(struct pwm_chip *chip, struct pwm_device *pwm)
 
 static void pwm_samsung_free(struct pwm_chip *chip, struct pwm_device *pwm)
 {
-       pwm_set_chip_data(pwm, NULL);
        devm_kfree(chip->dev, pwm_get_chip_data(pwm));
+       pwm_set_chip_data(pwm, NULL);
 }
 
 static int pwm_samsung_enable(struct pwm_chip *chip, struct pwm_device *pwm)
index c2e2e5852362afbd62a8c097fb195ea92433cf15..4e5c3d13d4f8d31a0faa65ccd7146c0a28436e3c 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/pm_runtime.h>
 #include <linux/pwm.h>
 #include <linux/of_device.h>
-#include <linux/pinctrl/consumer.h>
 
 #include "pwm-tipwmss.h"
 
@@ -208,11 +207,6 @@ static int ecap_pwm_probe(struct platform_device *pdev)
        struct clk *clk;
        struct ecap_pwm_chip *pc;
        u16 status;
-       struct pinctrl *pinctrl;
-
-       pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
-       if (IS_ERR(pinctrl))
-               dev_warn(&pdev->dev, "unable to select pin group\n");
 
        pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
        if (!pc) {
index 084f552465322654f9f3b7e0a765926ff8bd49fd..a4d8f519d965660d1a33e0cdfc7bda02224fbd7d 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/clk.h>
 #include <linux/pm_runtime.h>
 #include <linux/of_device.h>
-#include <linux/pinctrl/consumer.h>
 
 #include "pwm-tipwmss.h"
 
@@ -439,11 +438,6 @@ static int ehrpwm_pwm_probe(struct platform_device *pdev)
        struct clk *clk;
        struct ehrpwm_pwm_chip *pc;
        u16 status;
-       struct pinctrl *pinctrl;
-
-       pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
-       if (IS_ERR(pinctrl))
-               dev_warn(&pdev->dev, "unable to select pin group\n");
 
        pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
        if (!pc) {
index 29d1bba4804ec95fa7c249ebbe6ad3ea057fe08a..b964470025c5e288a6009817ddb683c679868eb6 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pwm.h>
 #include <linux/i2c/twl.h>
index eef910580eaef3c355bb0384759b16155924e9d8..b99a50e626a64f82ca98783cc373bd2bc4c82e01 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pwm.h>
 #include <linux/i2c/twl.h>
index 36db5d98dd2f5e900d9dafe3bd6e0e10b30e082e..fb80d68f4d3366e5672498da5bd05f3140e7a753 100644 (file)
@@ -10,6 +10,8 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -19,6 +21,7 @@
 #include <linux/err.h>
 #include <linux/pwm.h>
 #include <linux/pwm_backlight.h>
+#include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 
 struct pwm_bl_data {
@@ -27,6 +30,11 @@ struct pwm_bl_data {
        unsigned int            period;
        unsigned int            lth_brightness;
        unsigned int            *levels;
+       bool                    enabled;
+       struct regulator        *power_supply;
+       int                     enable_gpio;
+       unsigned long           enable_gpio_flags;
+       unsigned int            scale;
        int                     (*notify)(struct device *,
                                          int brightness);
        void                    (*notify_after)(struct device *,
@@ -35,11 +43,65 @@ struct pwm_bl_data {
        void                    (*exit)(struct device *);
 };
 
+static void pwm_backlight_power_on(struct pwm_bl_data *pb, int brightness)
+{
+       int err;
+
+       if (pb->enabled)
+               return;
+
+       err = regulator_enable(pb->power_supply);
+       if (err < 0)
+               dev_err(pb->dev, "failed to enable power supply\n");
+
+       if (gpio_is_valid(pb->enable_gpio)) {
+               if (pb->enable_gpio_flags & PWM_BACKLIGHT_GPIO_ACTIVE_LOW)
+                       gpio_set_value(pb->enable_gpio, 0);
+               else
+                       gpio_set_value(pb->enable_gpio, 1);
+       }
+
+       pwm_enable(pb->pwm);
+       pb->enabled = true;
+}
+
+static void pwm_backlight_power_off(struct pwm_bl_data *pb)
+{
+       if (!pb->enabled)
+               return;
+
+       pwm_config(pb->pwm, 0, pb->period);
+       pwm_disable(pb->pwm);
+
+       if (gpio_is_valid(pb->enable_gpio)) {
+               if (pb->enable_gpio_flags & PWM_BACKLIGHT_GPIO_ACTIVE_LOW)
+                       gpio_set_value(pb->enable_gpio, 1);
+               else
+                       gpio_set_value(pb->enable_gpio, 0);
+       }
+
+       regulator_disable(pb->power_supply);
+       pb->enabled = false;
+}
+
+static int compute_duty_cycle(struct pwm_bl_data *pb, int brightness)
+{
+       unsigned int lth = pb->lth_brightness;
+       int duty_cycle;
+
+       if (pb->levels)
+               duty_cycle = pb->levels[brightness];
+       else
+               duty_cycle = brightness;
+
+       return (duty_cycle * (pb->period - lth) / pb->scale) + lth;
+}
+
 static int pwm_backlight_update_status(struct backlight_device *bl)
 {
        struct pwm_bl_data *pb = bl_get_data(bl);
        int brightness = bl->props.brightness;
-       int max = bl->props.max_brightness;
+       int duty_cycle;
 
        if (bl->props.power != FB_BLANK_UNBLANK ||
            bl->props.fb_blank != FB_BLANK_UNBLANK ||
@@ -49,24 +111,12 @@ static int pwm_backlight_update_status(struct backlight_device *bl)
        if (pb->notify)
                brightness = pb->notify(pb->dev, brightness);
 
-       if (brightness == 0) {
-               pwm_config(pb->pwm, 0, pb->period);
-               pwm_disable(pb->pwm);
-       } else {
-               int duty_cycle;
-
-               if (pb->levels) {
-                       duty_cycle = pb->levels[brightness];
-                       max = pb->levels[max];
-               } else {
-                       duty_cycle = brightness;
-               }
-
-               duty_cycle = pb->lth_brightness +
-                    (duty_cycle * (pb->period - pb->lth_brightness) / max);
+       if (brightness > 0) {
+               duty_cycle = compute_duty_cycle(pb, brightness);
                pwm_config(pb->pwm, duty_cycle, pb->period);
-               pwm_enable(pb->pwm);
-       }
+               pwm_backlight_power_on(pb, brightness);
+       } else
+               pwm_backlight_power_off(pb);
 
        if (pb->notify_after)
                pb->notify_after(pb->dev, brightness);
@@ -98,6 +148,7 @@ static int pwm_backlight_parse_dt(struct device *dev,
                                  struct platform_pwm_backlight_data *data)
 {
        struct device_node *node = dev->of_node;
+       enum of_gpio_flags flags;
        struct property *prop;
        int length;
        u32 value;
@@ -138,11 +189,13 @@ static int pwm_backlight_parse_dt(struct device *dev,
                data->max_brightness--;
        }
 
-       /*
-        * TODO: Most users of this driver use a number of GPIOs to control
-        *       backlight power. Support for specifying these needs to be
-        *       added.
-        */
+       data->enable_gpio = of_get_named_gpio_flags(node, "enable-gpios", 0,
+                                                   &flags);
+       if (data->enable_gpio == -EPROBE_DEFER)
+               return -EPROBE_DEFER;
+
+       if (gpio_is_valid(data->enable_gpio) && (flags & OF_GPIO_ACTIVE_LOW))
+               data->enable_gpio_flags |= PWM_BACKLIGHT_GPIO_ACTIVE_LOW;
 
        return 0;
 }
@@ -168,7 +221,6 @@ static int pwm_backlight_probe(struct platform_device *pdev)
        struct backlight_properties props;
        struct backlight_device *bl;
        struct pwm_bl_data *pb;
-       unsigned int max;
        int ret;
 
        if (!data) {
@@ -195,16 +247,46 @@ static int pwm_backlight_probe(struct platform_device *pdev)
        }
 
        if (data->levels) {
-               max = data->levels[data->max_brightness];
+               unsigned int i;
+
+               for (i = 0; i <= data->max_brightness; i++)
+                       if (data->levels[i] > pb->scale)
+                               pb->scale = data->levels[i];
+
                pb->levels = data->levels;
        } else
-               max = data->max_brightness;
+               pb->scale = data->max_brightness;
 
+       pb->enable_gpio = data->enable_gpio;
+       pb->enable_gpio_flags = data->enable_gpio_flags;
        pb->notify = data->notify;
        pb->notify_after = data->notify_after;
        pb->check_fb = data->check_fb;
        pb->exit = data->exit;
        pb->dev = &pdev->dev;
+       pb->enabled = false;
+
+       if (gpio_is_valid(pb->enable_gpio)) {
+               unsigned long flags;
+
+               if (pb->enable_gpio_flags & PWM_BACKLIGHT_GPIO_ACTIVE_LOW)
+                       flags = GPIOF_OUT_INIT_HIGH;
+               else
+                       flags = GPIOF_OUT_INIT_LOW;
+
+               ret = gpio_request_one(pb->enable_gpio, flags, "enable");
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "failed to request GPIO#%d: %d\n",
+                               pb->enable_gpio, ret);
+                       goto err_alloc;
+               }
+       }
+
+       pb->power_supply = devm_regulator_get(&pdev->dev, "power");
+       if (IS_ERR(pb->power_supply)) {
+               ret = PTR_ERR(pb->power_supply);
+               goto err_gpio;
+       }
 
        pb->pwm = devm_pwm_get(&pdev->dev, NULL);
        if (IS_ERR(pb->pwm)) {
@@ -214,7 +296,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
                if (IS_ERR(pb->pwm)) {
                        dev_err(&pdev->dev, "unable to request legacy PWM\n");
                        ret = PTR_ERR(pb->pwm);
-                       goto err_alloc;
+                       goto err_gpio;
                }
        }
 
@@ -229,7 +311,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
                pwm_set_period(pb->pwm, data->pwm_period_ns);
 
        pb->period = pwm_get_period(pb->pwm);
-       pb->lth_brightness = data->lth_brightness * (pb->period / max);
+       pb->lth_brightness = data->lth_brightness * (pb->period / pb->scale);
 
        memset(&props, 0, sizeof(struct backlight_properties));
        props.type = BACKLIGHT_RAW;
@@ -239,7 +321,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
        if (IS_ERR(bl)) {
                dev_err(&pdev->dev, "failed to register backlight\n");
                ret = PTR_ERR(bl);
-               goto err_alloc;
+               goto err_gpio;
        }
 
        if (data->dft_brightness > data->max_brightness) {
@@ -255,6 +337,9 @@ static int pwm_backlight_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, bl);
        return 0;
 
+err_gpio:
+       if (gpio_is_valid(pb->enable_gpio))
+               gpio_free(pb->enable_gpio);
 err_alloc:
        if (data->exit)
                data->exit(&pdev->dev);
@@ -267,10 +352,11 @@ static int pwm_backlight_remove(struct platform_device *pdev)
        struct pwm_bl_data *pb = bl_get_data(bl);
 
        backlight_device_unregister(bl);
-       pwm_config(pb->pwm, 0, pb->period);
-       pwm_disable(pb->pwm);
+       pwm_backlight_power_off(pb);
+
        if (pb->exit)
                pb->exit(&pdev->dev);
+
        return 0;
 }
 
@@ -282,10 +368,12 @@ static int pwm_backlight_suspend(struct device *dev)
 
        if (pb->notify)
                pb->notify(pb->dev, 0);
-       pwm_config(pb->pwm, 0, pb->period);
-       pwm_disable(pb->pwm);
+
+       pwm_backlight_power_off(pb);
+
        if (pb->notify_after)
                pb->notify_after(pb->dev, 0);
+
        return 0;
 }
 
@@ -294,12 +382,19 @@ static int pwm_backlight_resume(struct device *dev)
        struct backlight_device *bl = dev_get_drvdata(dev);
 
        backlight_update_status(bl);
+
        return 0;
 }
 #endif
 
-static SIMPLE_DEV_PM_OPS(pwm_backlight_pm_ops, pwm_backlight_suspend,
-                        pwm_backlight_resume);
+static const struct dev_pm_ops pwm_backlight_pm_ops = {
+#ifdef CONFIG_PM_SLEEP
+       .suspend = pwm_backlight_suspend,
+       .resume = pwm_backlight_resume,
+       .poweroff = pwm_backlight_suspend,
+       .restore = pwm_backlight_resume,
+#endif
+};
 
 static struct platform_driver pwm_backlight_driver = {
        .driver         = {
@@ -317,4 +412,3 @@ module_platform_driver(pwm_backlight_driver);
 MODULE_DESCRIPTION("PWM based Backlight Driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:pwm-backlight");
-
index 56f4a866539ad7b66476fc3d1c09d15ab8ad2be1..2de2e275b2cbd1390ec6693d8f436b05352da16a 100644 (file)
@@ -6,6 +6,9 @@
 
 #include <linux/backlight.h>
 
+/* TODO: convert to gpiod_*() API once it has been merged */
+#define PWM_BACKLIGHT_GPIO_ACTIVE_LOW  (1 << 0)
+
 struct platform_pwm_backlight_data {
        int pwm_id;
        unsigned int max_brightness;
@@ -13,6 +16,8 @@ struct platform_pwm_backlight_data {
        unsigned int lth_brightness;
        unsigned int pwm_period_ns;
        unsigned int *levels;
+       int enable_gpio;
+       unsigned long enable_gpio_flags;
        int (*init)(struct device *dev);
        int (*notify)(struct device *dev, int brightness);
        void (*notify_after)(struct device *dev, int brightness);