aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2014-07-13 00:27:47 -0400
committerOlof Johansson <olof@lixom.net>2014-07-13 00:27:47 -0400
commitbde19a7e7492f97701f011e4297bec6b992b22f8 (patch)
tree9843c948af134783d871ffe7819167f0c28b6250
parent4c834452aad01531db949414f94f817a86348d59 (diff)
parentf2a70e1fc1ccc0fcdf4ad12db7382134228fb552 (diff)
Merge tag 'at91-drivers' of git://github.com/at91linux/linux-at91 into next/drivers
Merge "at91: drivers for 3.17 #1" from Nicolas Ferre: "This update delayed to 3.17, is about replacing the existing calls to the older, non-standard drivers by the use of the newer "pwm-atmel" which takes advantage of the PWM framework. All concerned maintainer gave their acknowledgement to the relevant patches. At the end, it removes three obsolete drivers and the diffstat looks pretty nice as well." Atmel PWM driver update for 3.17 - move to the new PWM driver which uses PWM framework - remove 3 obsolete drivers (atmel-pwm-bl.c, leds-atmel-pwm.c and atmel_pwm.c) * tag 'at91-drivers' of git://github.com/at91linux/linux-at91: misc: atmel_pwm: remove obsolete driver leds: atmel-pwm: remove obsolete driver backlight: atmel-pwm-bl: remove obsolete driver avr32: update defconfig to use the generic PWM framework avr32: favr-32: use generic pwm_bl driver avr32: merisc: use generic leds_pwm driver avr32: MRMT: use generic leds_pwm driver avr32/at32ap: switch to the generic PWM framework PWM: atmel: allow building for AVR32 ARM: at91: remove useless at91_pwm_leds() ARM: at91: at91sam9rl: switch to generic PWM framework ARM: at91: sam9263ek: use generic leds_pwm driver ARM: at91: at91sam9263: switch to generic PWM framework ARM: at91: sam9m10g45ek: use generic leds_pwm driver ARM: at91: at91sam9g45: switch to generic PWM framework Signed-off-by: Olof Johansson <olof@lixom.net>
-rw-r--r--arch/arm/mach-at91/at91sam9263.c1
-rw-r--r--arch/arm/mach-at91/at91sam9263_devices.c11
-rw-r--r--arch/arm/mach-at91/at91sam9g45.c1
-rw-r--r--arch/arm/mach-at91/at91sam9g45_devices.c11
-rw-r--r--arch/arm/mach-at91/at91sam9rl.c1
-rw-r--r--arch/arm/mach-at91/at91sam9rl_devices.c11
-rw-r--r--arch/arm/mach-at91/board-sam9263ek.c55
-rw-r--r--arch/arm/mach-at91/board-sam9m10g45ek.c42
-rw-r--r--arch/arm/mach-at91/board.h1
-rw-r--r--arch/arm/mach-at91/leds.c37
-rw-r--r--arch/avr32/boards/atngw100/mrmt.c34
-rw-r--r--arch/avr32/boards/favr-32/setup.c48
-rw-r--r--arch/avr32/boards/merisc/setup.c34
-rw-r--r--arch/avr32/configs/atngw100_mrmt_defconfig5
-rw-r--r--arch/avr32/configs/atstk1002_defconfig5
-rw-r--r--arch/avr32/configs/atstk1003_defconfig5
-rw-r--r--arch/avr32/configs/atstk1004_defconfig5
-rw-r--r--arch/avr32/configs/atstk1006_defconfig5
-rw-r--r--arch/avr32/configs/favr-32_defconfig6
-rw-r--r--arch/avr32/configs/merisc_defconfig5
-rw-r--r--arch/avr32/mach-at32ap/at32ap700x.c7
-rw-r--r--drivers/leds/Kconfig8
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/leds-atmel-pwm.c149
-rw-r--r--drivers/misc/Kconfig10
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/atmel_pwm.c402
-rw-r--r--drivers/pwm/Kconfig2
-rw-r--r--drivers/video/backlight/Kconfig11
-rw-r--r--drivers/video/backlight/Makefile1
-rw-r--r--drivers/video/backlight/atmel-pwm-bl.c223
-rw-r--r--include/linux/atmel-pwm-bl.h43
-rw-r--r--include/linux/atmel_pwm.h70
33 files changed, 186 insertions, 1065 deletions
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index f30290572293..f6663d6c01ec 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -199,6 +199,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
199 CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk), 199 CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
200 CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk), 200 CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
201 CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk), 201 CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk),
202 CLKDEV_CON_DEV_ID(NULL, "at91sam9rl-pwm", &pwm_clk),
202 /* fake hclk clock */ 203 /* fake hclk clock */
203 CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk), 204 CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
204 CLKDEV_CON_ID("pioA", &pioA_clk), 205 CLKDEV_CON_ID("pioA", &pioA_clk),
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 309390d8e2f8..cef0e2f57068 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -1131,9 +1131,7 @@ static void __init at91_add_device_watchdog(void) {}
1131 * PWM 1131 * PWM
1132 * --------------------------------------------------------------------*/ 1132 * --------------------------------------------------------------------*/
1133 1133
1134#if defined(CONFIG_ATMEL_PWM) 1134#if IS_ENABLED(CONFIG_PWM_ATMEL)
1135static u32 pwm_mask;
1136
1137static struct resource pwm_resources[] = { 1135static struct resource pwm_resources[] = {
1138 [0] = { 1136 [0] = {
1139 .start = AT91SAM9263_BASE_PWMC, 1137 .start = AT91SAM9263_BASE_PWMC,
@@ -1148,11 +1146,8 @@ static struct resource pwm_resources[] = {
1148}; 1146};
1149 1147
1150static struct platform_device at91sam9263_pwm0_device = { 1148static struct platform_device at91sam9263_pwm0_device = {
1151 .name = "atmel_pwm", 1149 .name = "at91sam9rl-pwm",
1152 .id = -1, 1150 .id = -1,
1153 .dev = {
1154 .platform_data = &pwm_mask,
1155 },
1156 .resource = pwm_resources, 1151 .resource = pwm_resources,
1157 .num_resources = ARRAY_SIZE(pwm_resources), 1152 .num_resources = ARRAY_SIZE(pwm_resources),
1158}; 1153};
@@ -1171,8 +1166,6 @@ void __init at91_add_device_pwm(u32 mask)
1171 if (mask & (1 << AT91_PWM3)) 1166 if (mask & (1 << AT91_PWM3))
1172 at91_set_B_periph(AT91_PIN_PB29, 1); /* enable PWM3 */ 1167 at91_set_B_periph(AT91_PIN_PB29, 1); /* enable PWM3 */
1173 1168
1174 pwm_mask = mask;
1175
1176 platform_device_register(&at91sam9263_pwm0_device); 1169 platform_device_register(&at91sam9263_pwm0_device);
1177} 1170}
1178#else 1171#else
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index 9d3d544ac19c..7300523da6ea 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -251,6 +251,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
251 CLKDEV_CON_DEV_ID(NULL, "atmel_sha", &aestdessha_clk), 251 CLKDEV_CON_DEV_ID(NULL, "atmel_sha", &aestdessha_clk),
252 CLKDEV_CON_DEV_ID(NULL, "atmel_tdes", &aestdessha_clk), 252 CLKDEV_CON_DEV_ID(NULL, "atmel_tdes", &aestdessha_clk),
253 CLKDEV_CON_DEV_ID(NULL, "atmel_aes", &aestdessha_clk), 253 CLKDEV_CON_DEV_ID(NULL, "atmel_aes", &aestdessha_clk),
254 CLKDEV_CON_DEV_ID(NULL, "at91sam9rl-pwm", &pwm_clk),
254 /* more usart lookup table for DT entries */ 255 /* more usart lookup table for DT entries */
255 CLKDEV_CON_DEV_ID("usart", "ffffee00.serial", &mck), 256 CLKDEV_CON_DEV_ID("usart", "ffffee00.serial", &mck),
256 CLKDEV_CON_DEV_ID("usart", "fff8c000.serial", &usart0_clk), 257 CLKDEV_CON_DEV_ID("usart", "fff8c000.serial", &usart0_clk),
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 391ab6bb536a..21ab782cc8e9 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -1334,9 +1334,7 @@ static void __init at91_add_device_watchdog(void) {}
1334 * PWM 1334 * PWM
1335 * --------------------------------------------------------------------*/ 1335 * --------------------------------------------------------------------*/
1336 1336
1337#if defined(CONFIG_ATMEL_PWM) || defined(CONFIG_ATMEL_PWM_MODULE) 1337#if IS_ENABLED(CONFIG_PWM_ATMEL)
1338static u32 pwm_mask;
1339
1340static struct resource pwm_resources[] = { 1338static struct resource pwm_resources[] = {
1341 [0] = { 1339 [0] = {
1342 .start = AT91SAM9G45_BASE_PWMC, 1340 .start = AT91SAM9G45_BASE_PWMC,
@@ -1351,11 +1349,8 @@ static struct resource pwm_resources[] = {
1351}; 1349};
1352 1350
1353static struct platform_device at91sam9g45_pwm0_device = { 1351static struct platform_device at91sam9g45_pwm0_device = {
1354 .name = "atmel_pwm", 1352 .name = "at91sam9rl-pwm",
1355 .id = -1, 1353 .id = -1,
1356 .dev = {
1357 .platform_data = &pwm_mask,
1358 },
1359 .resource = pwm_resources, 1354 .resource = pwm_resources,
1360 .num_resources = ARRAY_SIZE(pwm_resources), 1355 .num_resources = ARRAY_SIZE(pwm_resources),
1361}; 1356};
@@ -1374,8 +1369,6 @@ void __init at91_add_device_pwm(u32 mask)
1374 if (mask & (1 << AT91_PWM3)) 1369 if (mask & (1 << AT91_PWM3))
1375 at91_set_B_periph(AT91_PIN_PD0, 1); /* enable PWM3 */ 1370 at91_set_B_periph(AT91_PIN_PD0, 1); /* enable PWM3 */
1376 1371
1377 pwm_mask = mask;
1378
1379 platform_device_register(&at91sam9g45_pwm0_device); 1372 platform_device_register(&at91sam9g45_pwm0_device);
1380} 1373}
1381#else 1374#else
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index a79960f57e6a..878d5015daab 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -200,6 +200,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
200 CLKDEV_CON_DEV_ID("pclk", "fffc4000.ssc", &ssc1_clk), 200 CLKDEV_CON_DEV_ID("pclk", "fffc4000.ssc", &ssc1_clk),
201 CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi0_clk), 201 CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi0_clk),
202 CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.1", &twi1_clk), 202 CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.1", &twi1_clk),
203 CLKDEV_CON_DEV_ID(NULL, "at91sam9rl-pwm", &pwm_clk),
203 CLKDEV_CON_ID("pioA", &pioA_clk), 204 CLKDEV_CON_ID("pioA", &pioA_clk),
204 CLKDEV_CON_ID("pioB", &pioB_clk), 205 CLKDEV_CON_ID("pioB", &pioB_clk),
205 CLKDEV_CON_ID("pioC", &pioC_clk), 206 CLKDEV_CON_ID("pioC", &pioC_clk),
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 0b1d71a7d9bf..37d1c9ed4562 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -799,9 +799,7 @@ static void __init at91_add_device_watchdog(void) {}
799 * PWM 799 * PWM
800 * --------------------------------------------------------------------*/ 800 * --------------------------------------------------------------------*/
801 801
802#if defined(CONFIG_ATMEL_PWM) 802#if IS_ENABLED(CONFIG_PWM_ATMEL)
803static u32 pwm_mask;
804
805static struct resource pwm_resources[] = { 803static struct resource pwm_resources[] = {
806 [0] = { 804 [0] = {
807 .start = AT91SAM9RL_BASE_PWMC, 805 .start = AT91SAM9RL_BASE_PWMC,
@@ -816,11 +814,8 @@ static struct resource pwm_resources[] = {
816}; 814};
817 815
818static struct platform_device at91sam9rl_pwm0_device = { 816static struct platform_device at91sam9rl_pwm0_device = {
819 .name = "atmel_pwm", 817 .name = "at91sam9rl-pwm",
820 .id = -1, 818 .id = -1,
821 .dev = {
822 .platform_data = &pwm_mask,
823 },
824 .resource = pwm_resources, 819 .resource = pwm_resources,
825 .num_resources = ARRAY_SIZE(pwm_resources), 820 .num_resources = ARRAY_SIZE(pwm_resources),
826}; 821};
@@ -839,8 +834,6 @@ void __init at91_add_device_pwm(u32 mask)
839 if (mask & (1 << AT91_PWM3)) 834 if (mask & (1 << AT91_PWM3))
840 at91_set_B_periph(AT91_PIN_PD8, 1); /* enable PWM3 */ 835 at91_set_B_periph(AT91_PIN_PD8, 1); /* enable PWM3 */
841 836
842 pwm_mask = mask;
843
844 platform_device_register(&at91sam9rl_pwm0_device); 837 platform_device_register(&at91sam9rl_pwm0_device);
845} 838}
846#else 839#else
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index cd2726ee5add..fc446097f410 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -32,6 +32,8 @@
32#include <linux/gpio_keys.h> 32#include <linux/gpio_keys.h>
33#include <linux/input.h> 33#include <linux/input.h>
34#include <linux/leds.h> 34#include <linux/leds.h>
35#include <linux/pwm.h>
36#include <linux/leds_pwm.h>
35 37
36#include <video/atmel_lcdc.h> 38#include <video/atmel_lcdc.h>
37 39
@@ -369,21 +371,47 @@ static struct gpio_led ek_leds[] = {
369 .name = "ds3", 371 .name = "ds3",
370 .gpio = AT91_PIN_PB7, 372 .gpio = AT91_PIN_PB7,
371 .default_trigger = "heartbeat", 373 .default_trigger = "heartbeat",
374 },
375#if !IS_ENABLED(CONFIG_LEDS_PWM)
376 {
377 .name = "ds1",
378 .gpio = AT91_PIN_PB8,
379 .active_low = 1,
380 .default_trigger = "none",
372 } 381 }
382#endif
373}; 383};
374 384
375/* 385/*
376 * PWM Leds 386 * PWM Leds
377 */ 387 */
378static struct gpio_led ek_pwm_led[] = { 388static struct pwm_lookup pwm_lookup[] = {
379 /* For now only DS1 is PWM-driven (by pwm1) */ 389 PWM_LOOKUP("at91sam9rl-pwm", 1, "leds_pwm", "ds1",
390 5000, PWM_POLARITY_INVERSED),
391};
392
393#if IS_ENABLED(CONFIG_LEDS_PWM)
394static struct led_pwm pwm_leds[] = {
380 { 395 {
381 .name = "ds1", 396 .name = "ds1",
382 .gpio = 1, /* is PWM channel number */ 397 .max_brightness = 255,
383 .active_low = 1, 398 },
384 .default_trigger = "none", 399};
385 } 400
401static struct led_pwm_platform_data pwm_data = {
402 .num_leds = ARRAY_SIZE(pwm_leds),
403 .leds = pwm_leds,
404};
405
406static struct platform_device leds_pwm = {
407 .name = "leds_pwm",
408 .id = -1,
409 .dev = {
410 .platform_data = &pwm_data,
411 },
386}; 412};
413#endif
414
387 415
388/* 416/*
389 * CAN 417 * CAN
@@ -403,6 +431,12 @@ static struct at91_can_data ek_can_data = {
403 .transceiver_switch = sam9263ek_transceiver_switch, 431 .transceiver_switch = sam9263ek_transceiver_switch,
404}; 432};
405 433
434static struct platform_device *devices[] __initdata = {
435#if IS_ENABLED(CONFIG_LEDS_PWM)
436 &leds_pwm,
437#endif
438};
439
406static void __init ek_board_init(void) 440static void __init ek_board_init(void)
407{ 441{
408 /* Serial */ 442 /* Serial */
@@ -437,9 +471,14 @@ static void __init ek_board_init(void)
437 at91_add_device_ac97(&ek_ac97_data); 471 at91_add_device_ac97(&ek_ac97_data);
438 /* LEDs */ 472 /* LEDs */
439 at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds)); 473 at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
440 at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led)); 474 pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
475#if IS_ENABLED(CONFIG_LEDS_PWM)
476 at91_add_device_pwm(1 << AT91_PWM1);
477#endif
441 /* CAN */ 478 /* CAN */
442 at91_add_device_can(&ek_can_data); 479 at91_add_device_can(&ek_can_data);
480 /* Other platform devices */
481 platform_add_devices(devices, ARRAY_SIZE(devices));
443} 482}
444 483
445MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK") 484MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
index 1ea61328f30d..b227732b0c83 100644
--- a/arch/arm/mach-at91/board-sam9m10g45ek.c
+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
@@ -26,6 +26,8 @@
26#include <linux/leds.h> 26#include <linux/leds.h>
27#include <linux/atmel-mci.h> 27#include <linux/atmel-mci.h>
28#include <linux/delay.h> 28#include <linux/delay.h>
29#include <linux/pwm.h>
30#include <linux/leds_pwm.h>
29 31
30#include <linux/platform_data/at91_adc.h> 32#include <linux/platform_data/at91_adc.h>
31 33
@@ -416,7 +418,7 @@ static struct gpio_led ek_leds[] = {
416 .active_low = 1, 418 .active_low = 1,
417 .default_trigger = "nand-disk", 419 .default_trigger = "nand-disk",
418 }, 420 },
419#if !(defined(CONFIG_LEDS_ATMEL_PWM) || defined(CONFIG_LEDS_ATMEL_PWM_MODULE)) 421#if !IS_ENABLED(CONFIG_LEDS_PWM)
420 { /* "right" led, green, userled1, pwm1 */ 422 { /* "right" led, green, userled1, pwm1 */
421 .name = "d7", 423 .name = "d7",
422 .gpio = AT91_PIN_PD31, 424 .gpio = AT91_PIN_PD31,
@@ -430,22 +432,41 @@ static struct gpio_led ek_leds[] = {
430/* 432/*
431 * PWM Leds 433 * PWM Leds
432 */ 434 */
433static struct gpio_led ek_pwm_led[] = { 435static struct pwm_lookup pwm_lookup[] = {
434#if defined(CONFIG_LEDS_ATMEL_PWM) || defined(CONFIG_LEDS_ATMEL_PWM_MODULE) 436 PWM_LOOKUP("at91sam9rl-pwm", 1, "leds_pwm", "d7",
437 5000, PWM_POLARITY_INVERSED),
438};
439
440#if IS_ENABLED(CONFIG_LEDS_PWM)
441static struct led_pwm pwm_leds[] = {
435 { /* "right" led, green, userled1, pwm1 */ 442 { /* "right" led, green, userled1, pwm1 */
436 .name = "d7", 443 .name = "d7",
437 .gpio = 1, /* is PWM channel number */ 444 .max_brightness = 255,
438 .active_low = 1,
439 .default_trigger = "none",
440 }, 445 },
441#endif
442}; 446};
443 447
448static struct led_pwm_platform_data pwm_data = {
449 .num_leds = ARRAY_SIZE(pwm_leds),
450 .leds = pwm_leds,
451};
452
453static struct platform_device leds_pwm = {
454 .name = "leds_pwm",
455 .id = -1,
456 .dev = {
457 .platform_data = &pwm_data,
458 },
459};
460#endif
461
444static struct platform_device *devices[] __initdata = { 462static struct platform_device *devices[] __initdata = {
445#if defined(CONFIG_SOC_CAMERA_OV2640) || \ 463#if defined(CONFIG_SOC_CAMERA_OV2640) || \
446 defined(CONFIG_SOC_CAMERA_OV2640_MODULE) 464 defined(CONFIG_SOC_CAMERA_OV2640_MODULE)
447 &isi_ov2640, 465 &isi_ov2640,
448#endif 466#endif
467#if IS_ENABLED(CONFIG_LEDS_PWM)
468 &leds_pwm,
469#endif
449}; 470};
450 471
451static void __init ek_board_init(void) 472static void __init ek_board_init(void)
@@ -486,7 +507,10 @@ static void __init ek_board_init(void)
486 at91_add_device_ac97(&ek_ac97_data); 507 at91_add_device_ac97(&ek_ac97_data);
487 /* LEDs */ 508 /* LEDs */
488 at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds)); 509 at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
489 at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led)); 510 pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
511#if IS_ENABLED(CONFIG_LEDS_PWM)
512 at91_add_device_pwm(1 << AT91_PWM1);
513#endif
490 /* Other platform devices */ 514 /* Other platform devices */
491 platform_add_devices(devices, ARRAY_SIZE(devices)); 515 platform_add_devices(devices, ARRAY_SIZE(devices));
492} 516}
diff --git a/arch/arm/mach-at91/board.h b/arch/arm/mach-at91/board.h
index 4e773b55bc2d..836e9a537e0c 100644
--- a/arch/arm/mach-at91/board.h
+++ b/arch/arm/mach-at91/board.h
@@ -123,6 +123,5 @@ extern void __init at91_add_device_can(struct at91_can_data *data);
123 123
124 /* LEDs */ 124 /* LEDs */
125extern void __init at91_gpio_leds(struct gpio_led *leds, int nr); 125extern void __init at91_gpio_leds(struct gpio_led *leds, int nr);
126extern void __init at91_pwm_leds(struct gpio_led *leds, int nr);
127 126
128#endif 127#endif
diff --git a/arch/arm/mach-at91/leds.c b/arch/arm/mach-at91/leds.c
index 77c4d8fd03fd..eb22e3357e87 100644
--- a/arch/arm/mach-at91/leds.c
+++ b/arch/arm/mach-at91/leds.c
@@ -54,40 +54,3 @@ void __init at91_gpio_leds(struct gpio_led *leds, int nr)
54void __init at91_gpio_leds(struct gpio_led *leds, int nr) {} 54void __init at91_gpio_leds(struct gpio_led *leds, int nr) {}
55#endif 55#endif
56 56
57
58/* ------------------------------------------------------------------------- */
59
60#if defined (CONFIG_LEDS_ATMEL_PWM)
61
62/*
63 * PWM Leds
64 */
65
66static struct gpio_led_platform_data pwm_led_data;
67
68static struct platform_device at91_pwm_leds_device = {
69 .name = "leds-atmel-pwm",
70 .id = -1,
71 .dev.platform_data = &pwm_led_data,
72};
73
74void __init at91_pwm_leds(struct gpio_led *leds, int nr)
75{
76 int i;
77 u32 pwm_mask = 0;
78
79 if (!nr)
80 return;
81
82 for (i = 0; i < nr; i++)
83 pwm_mask |= (1 << leds[i].gpio);
84
85 pwm_led_data.leds = leds;
86 pwm_led_data.num_leds = nr;
87
88 at91_add_device_pwm(pwm_mask);
89 platform_device_register(&at91_pwm_leds_device);
90}
91#else
92void __init at91_pwm_leds(struct gpio_led *leds, int nr){}
93#endif
diff --git a/arch/avr32/boards/atngw100/mrmt.c b/arch/avr32/boards/atngw100/mrmt.c
index 1ba09e4c02b1..91146b416cdb 100644
--- a/arch/avr32/boards/atngw100/mrmt.c
+++ b/arch/avr32/boards/atngw100/mrmt.c
@@ -17,6 +17,8 @@
17#include <linux/types.h> 17#include <linux/types.h>
18#include <linux/fb.h> 18#include <linux/fb.h>
19#include <linux/leds.h> 19#include <linux/leds.h>
20#include <linux/pwm.h>
21#include <linux/leds_pwm.h>
20#include <linux/input.h> 22#include <linux/input.h>
21#include <linux/gpio_keys.h> 23#include <linux/gpio_keys.h>
22#include <linux/atmel_serial.h> 24#include <linux/atmel_serial.h>
@@ -155,21 +157,28 @@ static struct platform_device rmt_ts_device = {
155 157
156#ifdef CONFIG_BOARD_MRMT_BL_PWM 158#ifdef CONFIG_BOARD_MRMT_BL_PWM
157/* PWM LEDs: LCD Backlight, etc */ 159/* PWM LEDs: LCD Backlight, etc */
158static struct gpio_led rmt_pwm_led[] = { 160static struct pwm_lookup pwm_lookup[] = {
159 /* here the "gpio" is actually a PWM channel */ 161 PWM_LOOKUP("at91sam9rl-pwm", PWM_CH_BL, "leds_pwm", "ds1",
160 { .name = "backlight", .gpio = PWM_CH_BL, }, 162 5000, PWM_POLARITY_INVERSED),
161}; 163};
162 164
163static struct gpio_led_platform_data rmt_pwm_led_data = { 165static struct led_pwm pwm_leds[] = {
164 .num_leds = ARRAY_SIZE(rmt_pwm_led), 166 {
165 .leds = rmt_pwm_led, 167 .name = "backlight",
168 .max_brightness = 255,
169 },
170};
171
172static struct led_pwm_platform_data pwm_data = {
173 .num_leds = ARRAY_SIZE(pwm_leds),
174 .leds = pwm_leds,
166}; 175};
167 176
168static struct platform_device rmt_pwm_led_dev = { 177static struct platform_device leds_pwm = {
169 .name = "leds-atmel-pwm", 178 .name = "leds_pwm",
170 .id = -1, 179 .id = -1,
171 .dev = { 180 .dev = {
172 .platform_data = &rmt_pwm_led_data, 181 .platform_data = &pwm_data,
173 }, 182 },
174}; 183};
175#endif 184#endif
@@ -325,7 +334,8 @@ static int __init mrmt1_init(void)
325#ifdef CONFIG_BOARD_MRMT_BL_PWM 334#ifdef CONFIG_BOARD_MRMT_BL_PWM
326 /* Use PWM for Backlight controls */ 335 /* Use PWM for Backlight controls */
327 at32_add_device_pwm(1 << PWM_CH_BL); 336 at32_add_device_pwm(1 << PWM_CH_BL);
328 platform_device_register(&rmt_pwm_led_dev); 337 pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
338 platform_device_register(&leds_pwm);
329#else 339#else
330 /* Backlight always on */ 340 /* Backlight always on */
331 udelay( 1 ); 341 udelay( 1 );
diff --git a/arch/avr32/boards/favr-32/setup.c b/arch/avr32/boards/favr-32/setup.c
index 1f121497b517..234cb071c601 100644
--- a/arch/avr32/boards/favr-32/setup.c
+++ b/arch/avr32/boards/favr-32/setup.c
@@ -18,7 +18,10 @@
18#include <linux/gpio.h> 18#include <linux/gpio.h>
19#include <linux/leds.h> 19#include <linux/leds.h>
20#include <linux/atmel-mci.h> 20#include <linux/atmel-mci.h>
21#include <linux/atmel-pwm-bl.h> 21#include <linux/pwm.h>
22#include <linux/pwm_backlight.h>
23#include <linux/regulator/fixed.h>
24#include <linux/regulator/machine.h>
22#include <linux/spi/spi.h> 25#include <linux/spi/spi.h>
23#include <linux/spi/ads7846.h> 26#include <linux/spi/ads7846.h>
24 27
@@ -33,6 +36,8 @@
33#include <mach/board.h> 36#include <mach/board.h>
34#include <mach/portmux.h> 37#include <mach/portmux.h>
35 38
39#define PWM_BL_CH 2
40
36/* Oscillator frequencies. These are board-specific */ 41/* Oscillator frequencies. These are board-specific */
37unsigned long at32_board_osc_rates[3] = { 42unsigned long at32_board_osc_rates[3] = {
38 [0] = 32768, /* 32.768 kHz on RTC osc */ 43 [0] = 32768, /* 32.768 kHz on RTC osc */
@@ -227,29 +232,36 @@ void __init favr32_setup_leds(void)
227 platform_device_register(&favr32_led_dev); 232 platform_device_register(&favr32_led_dev);
228} 233}
229 234
230static struct atmel_pwm_bl_platform_data atmel_pwm_bl_pdata = { 235static struct pwm_lookup pwm_lookup[] = {
231 .pwm_channel = 2, 236 PWM_LOOKUP("at91sam9rl-pwm", PWM_BL_CH, "pwm-backlight.0", NULL,
232 .pwm_frequency = 200000, 237 5000, PWM_POLARITY_INVERSED),
233 .pwm_compare_max = 345,
234 .pwm_duty_max = 345,
235 .pwm_duty_min = 90,
236 .pwm_active_low = 1,
237 .gpio_on = GPIO_PIN_PA(28),
238 .on_active_low = 0,
239}; 238};
240 239
241static struct platform_device atmel_pwm_bl_dev = { 240static struct regulator_consumer_supply fixed_power_consumers[] = {
242 .name = "atmel-pwm-bl", 241 REGULATOR_SUPPLY("power", "pwm-backlight.0"),
243 .id = 0, 242};
244 .dev = { 243
245 .platform_data = &atmel_pwm_bl_pdata, 244static struct platform_pwm_backlight_data pwm_bl_data = {
245 .enable_gpio = GPIO_PIN_PA(28),
246 .max_brightness = 255,
247 .dft_brightness = 255,
248 .lth_brightness = 50,
249};
250
251static struct platform_device pwm_bl_device = {
252 .name = "pwm-backlight",
253 .dev = {
254 .platform_data = &pwm_bl_data,
246 }, 255 },
247}; 256};
248 257
249static void __init favr32_setup_atmel_pwm_bl(void) 258static void __init favr32_setup_atmel_pwm_bl(void)
250{ 259{
251 platform_device_register(&atmel_pwm_bl_dev); 260 pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
252 at32_select_gpio(atmel_pwm_bl_pdata.gpio_on, 0); 261 regulator_register_always_on(0, "fixed", fixed_power_consumers,
262 ARRAY_SIZE(fixed_power_consumers), 3300000);
263 platform_device_register(&pwm_bl_device);
264 at32_select_gpio(pwm_bl_data.enable_gpio, 0);
253} 265}
254 266
255void __init setup_board(void) 267void __init setup_board(void)
@@ -339,7 +351,7 @@ static int __init favr32_init(void)
339 351
340 set_abdac_rate(at32_add_device_abdac(0, &abdac0_data)); 352 set_abdac_rate(at32_add_device_abdac(0, &abdac0_data));
341 353
342 at32_add_device_pwm(1 << atmel_pwm_bl_pdata.pwm_channel); 354 at32_add_device_pwm(1 << PWM_BL_CH);
343 at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); 355 at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
344 at32_add_device_mci(0, &mci0_data); 356 at32_add_device_mci(0, &mci0_data);
345 at32_add_device_usba(0, NULL); 357 at32_add_device_usba(0, NULL);
diff --git a/arch/avr32/boards/merisc/setup.c b/arch/avr32/boards/merisc/setup.c
index ed137e335796..83d896cc2aed 100644
--- a/arch/avr32/boards/merisc/setup.c
+++ b/arch/avr32/boards/merisc/setup.c
@@ -22,6 +22,8 @@
22#include <linux/irq.h> 22#include <linux/irq.h>
23#include <linux/fb.h> 23#include <linux/fb.h>
24#include <linux/atmel-mci.h> 24#include <linux/atmel-mci.h>
25#include <linux/pwm.h>
26#include <linux/leds_pwm.h>
25 27
26#include <asm/io.h> 28#include <asm/io.h>
27#include <asm/setup.h> 29#include <asm/setup.h>
@@ -167,24 +169,29 @@ static struct i2c_board_info __initdata i2c_info[] = {
167 }, 169 },
168}; 170};
169 171
170#ifdef CONFIG_LEDS_ATMEL_PWM 172#if IS_ENABLED(CONFIG_LEDS_PWM)
171static struct gpio_led stk_pwm_led[] = { 173static struct pwm_lookup pwm_lookup[] = {
174 PWM_LOOKUP("at91sam9rl-pwm", 0, "leds_pwm", "backlight",
175 5000, PWM_POLARITY_NORMAL),
176};
177
178static struct led_pwm pwm_leds[] = {
172 { 179 {
173 .name = "backlight", 180 .name = "backlight",
174 .gpio = 0, /* PWM channel 0 (LCD backlight) */ 181 .max_brightness = 255,
175 }, 182 },
176}; 183};
177 184
178static struct gpio_led_platform_data stk_pwm_led_data = { 185static struct led_pwm_platform_data pwm_data = {
179 .num_leds = ARRAY_SIZE(stk_pwm_led), 186 .num_leds = ARRAY_SIZE(pwm_leds),
180 .leds = stk_pwm_led, 187 .leds = pwm_leds,
181}; 188};
182 189
183static struct platform_device stk_pwm_led_dev = { 190static struct platform_device leds_pwm = {
184 .name = "leds-atmel-pwm", 191 .name = "leds_pwm",
185 .id = -1, 192 .id = -1,
186 .dev = { 193 .dev = {
187 .platform_data = &stk_pwm_led_data, 194 .platform_data = &pwm_data,
188 }, 195 },
189}; 196};
190#endif 197#endif
@@ -278,9 +285,10 @@ static int __init merisc_init(void)
278 285
279 at32_add_device_mci(0, &mci0_data); 286 at32_add_device_mci(0, &mci0_data);
280 287
281#ifdef CONFIG_LEDS_ATMEL_PWM 288#if IS_ENABLED(CONFIG_LEDS_PWM)
289 pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
282 at32_add_device_pwm((1 << 0) | (1 << 2)); 290 at32_add_device_pwm((1 << 0) | (1 << 2));
283 platform_device_register(&stk_pwm_led_dev); 291 platform_device_register(&leds_pwm);
284#else 292#else
285 at32_add_device_pwm((1 << 2)); 293 at32_add_device_pwm((1 << 2));
286#endif 294#endif
diff --git a/arch/avr32/configs/atngw100_mrmt_defconfig b/arch/avr32/configs/atngw100_mrmt_defconfig
index 9a57da44eb6f..6838781e966f 100644
--- a/arch/avr32/configs/atngw100_mrmt_defconfig
+++ b/arch/avr32/configs/atngw100_mrmt_defconfig
@@ -56,7 +56,6 @@ CONFIG_MTD_CFI_AMDSTD=y
56CONFIG_MTD_PHYSMAP=y 56CONFIG_MTD_PHYSMAP=y
57CONFIG_MTD_DATAFLASH=y 57CONFIG_MTD_DATAFLASH=y
58CONFIG_BLK_DEV_LOOP=y 58CONFIG_BLK_DEV_LOOP=y
59CONFIG_ATMEL_PWM=y
60CONFIG_NETDEVICES=y 59CONFIG_NETDEVICES=y
61CONFIG_NET_ETHERNET=y 60CONFIG_NET_ETHERNET=y
62CONFIG_MACB=y 61CONFIG_MACB=y
@@ -104,8 +103,8 @@ CONFIG_MMC=y
104CONFIG_MMC_ATMELMCI=y 103CONFIG_MMC_ATMELMCI=y
105CONFIG_NEW_LEDS=y 104CONFIG_NEW_LEDS=y
106CONFIG_LEDS_CLASS=y 105CONFIG_LEDS_CLASS=y
107CONFIG_LEDS_ATMEL_PWM=y
108CONFIG_LEDS_GPIO=y 106CONFIG_LEDS_GPIO=y
107CONFIG_LEDS_PWM=y
109CONFIG_LEDS_TRIGGERS=y 108CONFIG_LEDS_TRIGGERS=y
110CONFIG_LEDS_TRIGGER_TIMER=y 109CONFIG_LEDS_TRIGGER_TIMER=y
111CONFIG_LEDS_TRIGGER_HEARTBEAT=y 110CONFIG_LEDS_TRIGGER_HEARTBEAT=y
@@ -114,6 +113,8 @@ CONFIG_RTC_DRV_S35390A=m
114CONFIG_RTC_DRV_AT32AP700X=m 113CONFIG_RTC_DRV_AT32AP700X=m
115CONFIG_DMADEVICES=y 114CONFIG_DMADEVICES=y
116CONFIG_UIO=y 115CONFIG_UIO=y
116CONFIG_PWM=y
117CONFIG_PWM_ATMEL=y
117CONFIG_EXT2_FS=y 118CONFIG_EXT2_FS=y
118CONFIG_EXT2_FS_XATTR=y 119CONFIG_EXT2_FS_XATTR=y
119CONFIG_EXT3_FS=y 120CONFIG_EXT3_FS=y
diff --git a/arch/avr32/configs/atstk1002_defconfig b/arch/avr32/configs/atstk1002_defconfig
index 2813dd2b9138..b056820eef33 100644
--- a/arch/avr32/configs/atstk1002_defconfig
+++ b/arch/avr32/configs/atstk1002_defconfig
@@ -64,7 +64,6 @@ CONFIG_BLK_DEV_LOOP=m
64CONFIG_BLK_DEV_NBD=m 64CONFIG_BLK_DEV_NBD=m
65CONFIG_BLK_DEV_RAM=m 65CONFIG_BLK_DEV_RAM=m
66CONFIG_MISC_DEVICES=y 66CONFIG_MISC_DEVICES=y
67CONFIG_ATMEL_PWM=m
68CONFIG_ATMEL_TCLIB=y 67CONFIG_ATMEL_TCLIB=y
69CONFIG_ATMEL_SSC=m 68CONFIG_ATMEL_SSC=m
70# CONFIG_SCSI_PROC_FS is not set 69# CONFIG_SCSI_PROC_FS is not set
@@ -133,14 +132,16 @@ CONFIG_MMC_TEST=m
133CONFIG_MMC_ATMELMCI=y 132CONFIG_MMC_ATMELMCI=y
134CONFIG_NEW_LEDS=y 133CONFIG_NEW_LEDS=y
135CONFIG_LEDS_CLASS=y 134CONFIG_LEDS_CLASS=y
136CONFIG_LEDS_ATMEL_PWM=m
137CONFIG_LEDS_GPIO=m 135CONFIG_LEDS_GPIO=m
136CONFIG_LEDS_PWM=m
138CONFIG_LEDS_TRIGGERS=y 137CONFIG_LEDS_TRIGGERS=y
139CONFIG_LEDS_TRIGGER_TIMER=m 138CONFIG_LEDS_TRIGGER_TIMER=m
140CONFIG_LEDS_TRIGGER_HEARTBEAT=m 139CONFIG_LEDS_TRIGGER_HEARTBEAT=m
141CONFIG_RTC_CLASS=y 140CONFIG_RTC_CLASS=y
142CONFIG_RTC_DRV_AT32AP700X=y 141CONFIG_RTC_DRV_AT32AP700X=y
143CONFIG_DMADEVICES=y 142CONFIG_DMADEVICES=y
143CONFIG_PWM=y
144CONFIG_PWM_ATMEL=m
144CONFIG_EXT2_FS=y 145CONFIG_EXT2_FS=y
145CONFIG_EXT3_FS=y 146CONFIG_EXT3_FS=y
146# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set 147# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
diff --git a/arch/avr32/configs/atstk1003_defconfig b/arch/avr32/configs/atstk1003_defconfig
index f8ff3a3baad4..0cd23a303da1 100644
--- a/arch/avr32/configs/atstk1003_defconfig
+++ b/arch/avr32/configs/atstk1003_defconfig
@@ -53,7 +53,6 @@ CONFIG_BLK_DEV_LOOP=m
53CONFIG_BLK_DEV_NBD=m 53CONFIG_BLK_DEV_NBD=m
54CONFIG_BLK_DEV_RAM=m 54CONFIG_BLK_DEV_RAM=m
55CONFIG_MISC_DEVICES=y 55CONFIG_MISC_DEVICES=y
56CONFIG_ATMEL_PWM=m
57CONFIG_ATMEL_TCLIB=y 56CONFIG_ATMEL_TCLIB=y
58CONFIG_ATMEL_SSC=m 57CONFIG_ATMEL_SSC=m
59# CONFIG_SCSI_PROC_FS is not set 58# CONFIG_SCSI_PROC_FS is not set
@@ -112,14 +111,16 @@ CONFIG_MMC_TEST=m
112CONFIG_MMC_ATMELMCI=y 111CONFIG_MMC_ATMELMCI=y
113CONFIG_NEW_LEDS=y 112CONFIG_NEW_LEDS=y
114CONFIG_LEDS_CLASS=y 113CONFIG_LEDS_CLASS=y
115CONFIG_LEDS_ATMEL_PWM=m
116CONFIG_LEDS_GPIO=m 114CONFIG_LEDS_GPIO=m
115CONFIG_LEDS_PWM=m
117CONFIG_LEDS_TRIGGERS=y 116CONFIG_LEDS_TRIGGERS=y
118CONFIG_LEDS_TRIGGER_TIMER=m 117CONFIG_LEDS_TRIGGER_TIMER=m
119CONFIG_LEDS_TRIGGER_HEARTBEAT=m 118CONFIG_LEDS_TRIGGER_HEARTBEAT=m
120CONFIG_RTC_CLASS=y 119CONFIG_RTC_CLASS=y
121CONFIG_RTC_DRV_AT32AP700X=y 120CONFIG_RTC_DRV_AT32AP700X=y
122CONFIG_DMADEVICES=y 121CONFIG_DMADEVICES=y
122CONFIG_PWM=y
123CONFIG_PWM_ATMEL=m
123CONFIG_EXT2_FS=y 124CONFIG_EXT2_FS=y
124CONFIG_EXT3_FS=y 125CONFIG_EXT3_FS=y
125# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set 126# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
diff --git a/arch/avr32/configs/atstk1004_defconfig b/arch/avr32/configs/atstk1004_defconfig
index 992228e54e38..ac1041f5f85a 100644
--- a/arch/avr32/configs/atstk1004_defconfig
+++ b/arch/avr32/configs/atstk1004_defconfig
@@ -53,7 +53,6 @@ CONFIG_BLK_DEV_LOOP=m
53CONFIG_BLK_DEV_NBD=m 53CONFIG_BLK_DEV_NBD=m
54CONFIG_BLK_DEV_RAM=m 54CONFIG_BLK_DEV_RAM=m
55CONFIG_MISC_DEVICES=y 55CONFIG_MISC_DEVICES=y
56CONFIG_ATMEL_PWM=m
57CONFIG_ATMEL_TCLIB=y 56CONFIG_ATMEL_TCLIB=y
58CONFIG_ATMEL_SSC=m 57CONFIG_ATMEL_SSC=m
59# CONFIG_SCSI_PROC_FS is not set 58# CONFIG_SCSI_PROC_FS is not set
@@ -111,14 +110,16 @@ CONFIG_MMC_TEST=m
111CONFIG_MMC_ATMELMCI=y 110CONFIG_MMC_ATMELMCI=y
112CONFIG_NEW_LEDS=y 111CONFIG_NEW_LEDS=y
113CONFIG_LEDS_CLASS=y 112CONFIG_LEDS_CLASS=y
114CONFIG_LEDS_ATMEL_PWM=m
115CONFIG_LEDS_GPIO=m 113CONFIG_LEDS_GPIO=m
114CONFIG_LEDS_PWM=m
116CONFIG_LEDS_TRIGGERS=y 115CONFIG_LEDS_TRIGGERS=y
117CONFIG_LEDS_TRIGGER_TIMER=m 116CONFIG_LEDS_TRIGGER_TIMER=m
118CONFIG_LEDS_TRIGGER_HEARTBEAT=m 117CONFIG_LEDS_TRIGGER_HEARTBEAT=m
119CONFIG_RTC_CLASS=y 118CONFIG_RTC_CLASS=y
120CONFIG_RTC_DRV_AT32AP700X=y 119CONFIG_RTC_DRV_AT32AP700X=y
121CONFIG_DMADEVICES=y 120CONFIG_DMADEVICES=y
121CONFIG_PWM=y
122CONFIG_PWM_ATMEL=m
122CONFIG_EXT2_FS=y 123CONFIG_EXT2_FS=y
123CONFIG_EXT3_FS=y 124CONFIG_EXT3_FS=y
124# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set 125# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
diff --git a/arch/avr32/configs/atstk1006_defconfig b/arch/avr32/configs/atstk1006_defconfig
index b8e698b0d1fa..ea4f670cb995 100644
--- a/arch/avr32/configs/atstk1006_defconfig
+++ b/arch/avr32/configs/atstk1006_defconfig
@@ -67,7 +67,6 @@ CONFIG_BLK_DEV_LOOP=m
67CONFIG_BLK_DEV_NBD=m 67CONFIG_BLK_DEV_NBD=m
68CONFIG_BLK_DEV_RAM=m 68CONFIG_BLK_DEV_RAM=m
69CONFIG_MISC_DEVICES=y 69CONFIG_MISC_DEVICES=y
70CONFIG_ATMEL_PWM=m
71CONFIG_ATMEL_TCLIB=y 70CONFIG_ATMEL_TCLIB=y
72CONFIG_ATMEL_SSC=m 71CONFIG_ATMEL_SSC=m
73# CONFIG_SCSI_PROC_FS is not set 72# CONFIG_SCSI_PROC_FS is not set
@@ -136,14 +135,16 @@ CONFIG_MMC_TEST=m
136CONFIG_MMC_ATMELMCI=y 135CONFIG_MMC_ATMELMCI=y
137CONFIG_NEW_LEDS=y 136CONFIG_NEW_LEDS=y
138CONFIG_LEDS_CLASS=y 137CONFIG_LEDS_CLASS=y
139CONFIG_LEDS_ATMEL_PWM=m
140CONFIG_LEDS_GPIO=m 138CONFIG_LEDS_GPIO=m
139CONFIG_LEDS_PWM=m
141CONFIG_LEDS_TRIGGERS=y 140CONFIG_LEDS_TRIGGERS=y
142CONFIG_LEDS_TRIGGER_TIMER=m 141CONFIG_LEDS_TRIGGER_TIMER=m
143CONFIG_LEDS_TRIGGER_HEARTBEAT=m 142CONFIG_LEDS_TRIGGER_HEARTBEAT=m
144CONFIG_RTC_CLASS=y 143CONFIG_RTC_CLASS=y
145CONFIG_RTC_DRV_AT32AP700X=y 144CONFIG_RTC_DRV_AT32AP700X=y
146CONFIG_DMADEVICES=y 145CONFIG_DMADEVICES=y
146CONFIG_PWM=y
147CONFIG_PWM_ATMEL=m
147CONFIG_EXT2_FS=y 148CONFIG_EXT2_FS=y
148CONFIG_EXT3_FS=y 149CONFIG_EXT3_FS=y
149# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set 150# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
diff --git a/arch/avr32/configs/favr-32_defconfig b/arch/avr32/configs/favr-32_defconfig
index 07bed3f7eb5e..b3eb67dc05ac 100644
--- a/arch/avr32/configs/favr-32_defconfig
+++ b/arch/avr32/configs/favr-32_defconfig
@@ -67,7 +67,6 @@ CONFIG_MTD_PHYSMAP=y
67CONFIG_BLK_DEV_LOOP=m 67CONFIG_BLK_DEV_LOOP=m
68CONFIG_BLK_DEV_NBD=m 68CONFIG_BLK_DEV_NBD=m
69CONFIG_BLK_DEV_RAM=m 69CONFIG_BLK_DEV_RAM=m
70CONFIG_ATMEL_PWM=m
71CONFIG_ATMEL_TCLIB=y 70CONFIG_ATMEL_TCLIB=y
72CONFIG_ATMEL_SSC=m 71CONFIG_ATMEL_SSC=m
73CONFIG_NETDEVICES=y 72CONFIG_NETDEVICES=y
@@ -108,7 +107,7 @@ CONFIG_FB=y
108CONFIG_FB_ATMEL=y 107CONFIG_FB_ATMEL=y
109CONFIG_BACKLIGHT_LCD_SUPPORT=y 108CONFIG_BACKLIGHT_LCD_SUPPORT=y
110# CONFIG_LCD_CLASS_DEVICE is not set 109# CONFIG_LCD_CLASS_DEVICE is not set
111CONFIG_BACKLIGHT_ATMEL_PWM=m 110CONFIG_BACKLIGHT_PWM=m
112CONFIG_SOUND=m 111CONFIG_SOUND=m
113CONFIG_SOUND_PRIME=m 112CONFIG_SOUND_PRIME=m
114# CONFIG_HID_SUPPORT is not set 113# CONFIG_HID_SUPPORT is not set
@@ -123,7 +122,6 @@ CONFIG_MMC=y
123CONFIG_MMC_ATMELMCI=y 122CONFIG_MMC_ATMELMCI=y
124CONFIG_NEW_LEDS=y 123CONFIG_NEW_LEDS=y
125CONFIG_LEDS_CLASS=y 124CONFIG_LEDS_CLASS=y
126CONFIG_LEDS_ATMEL_PWM=m
127CONFIG_LEDS_GPIO=y 125CONFIG_LEDS_GPIO=y
128CONFIG_LEDS_TRIGGERS=y 126CONFIG_LEDS_TRIGGERS=y
129CONFIG_LEDS_TRIGGER_TIMER=y 127CONFIG_LEDS_TRIGGER_TIMER=y
@@ -132,6 +130,8 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
132CONFIG_RTC_CLASS=y 130CONFIG_RTC_CLASS=y
133CONFIG_RTC_DRV_AT32AP700X=y 131CONFIG_RTC_DRV_AT32AP700X=y
134CONFIG_DMADEVICES=y 132CONFIG_DMADEVICES=y
133CONFIG_PWM=y
134CONFIG_PWM_ATMEL=y
135CONFIG_EXT2_FS=y 135CONFIG_EXT2_FS=y
136CONFIG_EXT3_FS=y 136CONFIG_EXT3_FS=y
137# CONFIG_EXT3_FS_XATTR is not set 137# CONFIG_EXT3_FS_XATTR is not set
diff --git a/arch/avr32/configs/merisc_defconfig b/arch/avr32/configs/merisc_defconfig
index 91df6b2986be..b9ef4cc85d08 100644
--- a/arch/avr32/configs/merisc_defconfig
+++ b/arch/avr32/configs/merisc_defconfig
@@ -55,7 +55,6 @@ CONFIG_MTD_ABSENT=y
55CONFIG_MTD_PHYSMAP=y 55CONFIG_MTD_PHYSMAP=y
56CONFIG_MTD_BLOCK2MTD=y 56CONFIG_MTD_BLOCK2MTD=y
57CONFIG_BLK_DEV_LOOP=y 57CONFIG_BLK_DEV_LOOP=y
58CONFIG_ATMEL_PWM=y
59CONFIG_ATMEL_SSC=y 58CONFIG_ATMEL_SSC=y
60CONFIG_SCSI=y 59CONFIG_SCSI=y
61CONFIG_BLK_DEV_SD=y 60CONFIG_BLK_DEV_SD=y
@@ -103,12 +102,14 @@ CONFIG_MMC=y
103CONFIG_MMC_ATMELMCI=y 102CONFIG_MMC_ATMELMCI=y
104CONFIG_NEW_LEDS=y 103CONFIG_NEW_LEDS=y
105CONFIG_LEDS_CLASS=y 104CONFIG_LEDS_CLASS=y
106CONFIG_LEDS_ATMEL_PWM=y 105CONFIG_LEDS_PWM=y
107CONFIG_RTC_CLASS=y 106CONFIG_RTC_CLASS=y
108# CONFIG_RTC_HCTOSYS is not set 107# CONFIG_RTC_HCTOSYS is not set
109CONFIG_RTC_DRV_PCF8563=y 108CONFIG_RTC_DRV_PCF8563=y
110CONFIG_DMADEVICES=y 109CONFIG_DMADEVICES=y
111CONFIG_UIO=y 110CONFIG_UIO=y
111CONFIG_PWM=y
112CONFIG_PWM_ATMEL=m
112CONFIG_EXT2_FS=y 113CONFIG_EXT2_FS=y
113# CONFIG_DNOTIFY is not set 114# CONFIG_DNOTIFY is not set
114CONFIG_FUSE_FS=y 115CONFIG_FUSE_FS=y
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c
index a1f4d1e91b52..db85b5ec3351 100644
--- a/arch/avr32/mach-at32ap/at32ap700x.c
+++ b/arch/avr32/mach-at32ap/at32ap700x.c
@@ -1553,7 +1553,7 @@ static struct resource atmel_pwm0_resource[] __initdata = {
1553 IRQ(24), 1553 IRQ(24),
1554}; 1554};
1555static struct clk atmel_pwm0_mck = { 1555static struct clk atmel_pwm0_mck = {
1556 .name = "pwm_clk", 1556 .name = "at91sam9rl-pwm",
1557 .parent = &pbb_clk, 1557 .parent = &pbb_clk,
1558 .mode = pbb_clk_mode, 1558 .mode = pbb_clk_mode,
1559 .get_rate = pbb_clk_get_rate, 1559 .get_rate = pbb_clk_get_rate,
@@ -1568,7 +1568,7 @@ struct platform_device *__init at32_add_device_pwm(u32 mask)
1568 if (!mask) 1568 if (!mask)
1569 return NULL; 1569 return NULL;
1570 1570
1571 pdev = platform_device_alloc("atmel_pwm", 0); 1571 pdev = platform_device_alloc("at91sam9rl-pwm", 0);
1572 if (!pdev) 1572 if (!pdev)
1573 return NULL; 1573 return NULL;
1574 1574
@@ -1576,9 +1576,6 @@ struct platform_device *__init at32_add_device_pwm(u32 mask)
1576 ARRAY_SIZE(atmel_pwm0_resource))) 1576 ARRAY_SIZE(atmel_pwm0_resource)))
1577 goto out_free_pdev; 1577 goto out_free_pdev;
1578 1578
1579 if (platform_device_add_data(pdev, &mask, sizeof(mask)))
1580 goto out_free_pdev;
1581
1582 pin_mask = 0; 1579 pin_mask = 0;
1583 if (mask & (1 << 0)) 1580 if (mask & (1 << 0))
1584 pin_mask |= (1 << 28); 1581 pin_mask |= (1 << 28);
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index a1b044e7eaad..8736f69262f9 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -32,14 +32,6 @@ config LEDS_88PM860X
32 This option enables support for on-chip LED drivers found on Marvell 32 This option enables support for on-chip LED drivers found on Marvell
33 Semiconductor 88PM8606 PMIC. 33 Semiconductor 88PM8606 PMIC.
34 34
35config LEDS_ATMEL_PWM
36 tristate "LED Support using Atmel PWM outputs"
37 depends on LEDS_CLASS
38 depends on ATMEL_PWM
39 help
40 This option enables support for LEDs driven using outputs
41 of the dedicated PWM controller found on newer Atmel SOCs.
42
43config LEDS_LM3530 35config LEDS_LM3530
44 tristate "LCD Backlight driver for LM3530" 36 tristate "LCD Backlight driver for LM3530"
45 depends on LEDS_CLASS 37 depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 79c5155199a7..3c036663f17b 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -6,7 +6,6 @@ obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o
6 6
7# LED Platform Drivers 7# LED Platform Drivers
8obj-$(CONFIG_LEDS_88PM860X) += leds-88pm860x.o 8obj-$(CONFIG_LEDS_88PM860X) += leds-88pm860x.o
9obj-$(CONFIG_LEDS_ATMEL_PWM) += leds-atmel-pwm.o
10obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o 9obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o
11obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o 10obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o
12obj-$(CONFIG_LEDS_LM3530) += leds-lm3530.o 11obj-$(CONFIG_LEDS_LM3530) += leds-lm3530.o
diff --git a/drivers/leds/leds-atmel-pwm.c b/drivers/leds/leds-atmel-pwm.c
deleted file mode 100644
index 56cec8d6a2ac..000000000000
--- a/drivers/leds/leds-atmel-pwm.c
+++ /dev/null
@@ -1,149 +0,0 @@
1#include <linux/kernel.h>
2#include <linux/platform_device.h>
3#include <linux/leds.h>
4#include <linux/io.h>
5#include <linux/atmel_pwm.h>
6#include <linux/slab.h>
7#include <linux/module.h>
8
9
10struct pwmled {
11 struct led_classdev cdev;
12 struct pwm_channel pwmc;
13 struct gpio_led *desc;
14 u32 mult;
15 u8 active_low;
16};
17
18
19/*
20 * For simplicity, we use "brightness" as if it were a linear function
21 * of PWM duty cycle. However, a logarithmic function of duty cycle is
22 * probably a better match for perceived brightness: two is half as bright
23 * as four, four is half as bright as eight, etc
24 */
25static void pwmled_brightness(struct led_classdev *cdev, enum led_brightness b)
26{
27 struct pwmled *led;
28
29 /* update the duty cycle for the *next* period */
30 led = container_of(cdev, struct pwmled, cdev);
31 pwm_channel_writel(&led->pwmc, PWM_CUPD, led->mult * (unsigned) b);
32}
33
34/*
35 * NOTE: we reuse the platform_data structure of GPIO leds,
36 * but repurpose its "gpio" number as a PWM channel number.
37 */
38static int pwmled_probe(struct platform_device *pdev)
39{
40 const struct gpio_led_platform_data *pdata;
41 struct pwmled *leds;
42 int i;
43 int status;
44
45 pdata = dev_get_platdata(&pdev->dev);
46 if (!pdata || pdata->num_leds < 1)
47 return -ENODEV;
48
49 leds = devm_kzalloc(&pdev->dev, pdata->num_leds * sizeof(*leds),
50 GFP_KERNEL);
51 if (!leds)
52 return -ENOMEM;
53
54 for (i = 0; i < pdata->num_leds; i++) {
55 struct pwmled *led = leds + i;
56 const struct gpio_led *dat = pdata->leds + i;
57 u32 tmp;
58
59 led->cdev.name = dat->name;
60 led->cdev.brightness = LED_OFF;
61 led->cdev.brightness_set = pwmled_brightness;
62 led->cdev.default_trigger = dat->default_trigger;
63
64 led->active_low = dat->active_low;
65
66 status = pwm_channel_alloc(dat->gpio, &led->pwmc);
67 if (status < 0)
68 goto err;
69
70 /*
71 * Prescale clock by 2^x, so PWM counts in low MHz.
72 * Start each cycle with the LED active, so increasing
73 * the duty cycle gives us more time on (== brighter).
74 */
75 tmp = 5;
76 if (!led->active_low)
77 tmp |= PWM_CPR_CPOL;
78 pwm_channel_writel(&led->pwmc, PWM_CMR, tmp);
79
80 /*
81 * Pick a period so PWM cycles at 100+ Hz; and a multiplier
82 * for scaling duty cycle: brightness * mult.
83 */
84 tmp = (led->pwmc.mck / (1 << 5)) / 100;
85 tmp /= 255;
86 led->mult = tmp;
87 pwm_channel_writel(&led->pwmc, PWM_CDTY,
88 led->cdev.brightness * 255);
89 pwm_channel_writel(&led->pwmc, PWM_CPRD,
90 LED_FULL * tmp);
91
92 pwm_channel_enable(&led->pwmc);
93
94 /* Hand it over to the LED framework */
95 status = led_classdev_register(&pdev->dev, &led->cdev);
96 if (status < 0) {
97 pwm_channel_free(&led->pwmc);
98 goto err;
99 }
100 }
101
102 platform_set_drvdata(pdev, leds);
103 return 0;
104
105err:
106 if (i > 0) {
107 for (i = i - 1; i >= 0; i--) {
108 led_classdev_unregister(&leds[i].cdev);
109 pwm_channel_free(&leds[i].pwmc);
110 }
111 }
112
113 return status;
114}
115
116static int pwmled_remove(struct platform_device *pdev)
117{
118 const struct gpio_led_platform_data *pdata;
119 struct pwmled *leds;
120 unsigned i;
121
122 pdata = dev_get_platdata(&pdev->dev);
123 leds = platform_get_drvdata(pdev);
124
125 for (i = 0; i < pdata->num_leds; i++) {
126 struct pwmled *led = leds + i;
127
128 led_classdev_unregister(&led->cdev);
129 pwm_channel_free(&led->pwmc);
130 }
131
132 return 0;
133}
134
135static struct platform_driver pwmled_driver = {
136 .driver = {
137 .name = "leds-atmel-pwm",
138 .owner = THIS_MODULE,
139 },
140 /* REVISIT add suspend() and resume() methods */
141 .probe = pwmled_probe,
142 .remove = pwmled_remove,
143};
144
145module_platform_driver(pwmled_driver);
146
147MODULE_DESCRIPTION("Driver for LEDs with PWM-controlled brightness");
148MODULE_LICENSE("GPL");
149MODULE_ALIAS("platform:leds-atmel-pwm");
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index ee9402324a23..b841180c7c74 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -51,16 +51,6 @@ config AD525X_DPOT_SPI
51 To compile this driver as a module, choose M here: the 51 To compile this driver as a module, choose M here: the
52 module will be called ad525x_dpot-spi. 52 module will be called ad525x_dpot-spi.
53 53
54config ATMEL_PWM
55 tristate "Atmel AT32/AT91 PWM support"
56 depends on HAVE_CLK
57 depends on AVR32 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91SAM9G45
58 help
59 This option enables device driver support for the PWM channels
60 on certain Atmel processors. Pulse Width Modulation is used for
61 purposes including software controlled power-efficient backlights
62 on LCD displays, motor control, and waveform generation.
63
64config ATMEL_TCLIB 54config ATMEL_TCLIB
65 bool "Atmel AT32/AT91 Timer/Counter Library" 55 bool "Atmel AT32/AT91 Timer/Counter Library"
66 depends on (AVR32 || ARCH_AT91) 56 depends on (AVR32 || ARCH_AT91)
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index d59ce1261b38..5497d026e651 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -7,7 +7,6 @@ obj-$(CONFIG_AD525X_DPOT) += ad525x_dpot.o
7obj-$(CONFIG_AD525X_DPOT_I2C) += ad525x_dpot-i2c.o 7obj-$(CONFIG_AD525X_DPOT_I2C) += ad525x_dpot-i2c.o
8obj-$(CONFIG_AD525X_DPOT_SPI) += ad525x_dpot-spi.o 8obj-$(CONFIG_AD525X_DPOT_SPI) += ad525x_dpot-spi.o
9obj-$(CONFIG_INTEL_MID_PTI) += pti.o 9obj-$(CONFIG_INTEL_MID_PTI) += pti.o
10obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o
11obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o 10obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o
12obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o 11obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o
13obj-$(CONFIG_BMP085) += bmp085.o 12obj-$(CONFIG_BMP085) += bmp085.o
diff --git a/drivers/misc/atmel_pwm.c b/drivers/misc/atmel_pwm.c
deleted file mode 100644
index a6dc56e1bc58..000000000000
--- a/drivers/misc/atmel_pwm.c
+++ /dev/null
@@ -1,402 +0,0 @@
1#include <linux/module.h>
2#include <linux/clk.h>
3#include <linux/err.h>
4#include <linux/slab.h>
5#include <linux/io.h>
6#include <linux/interrupt.h>
7#include <linux/platform_device.h>
8#include <linux/atmel_pwm.h>
9
10
11/*
12 * This is a simple driver for the PWM controller found in various newer
13 * Atmel SOCs, including the AVR32 series and the AT91sam9263.
14 *
15 * Chips with current Linux ports have only 4 PWM channels, out of max 32.
16 * AT32UC3A and AT32UC3B chips have 7 channels (but currently no Linux).
17 * Docs are inconsistent about the width of the channel counter registers;
18 * it's at least 16 bits, but several places say 20 bits.
19 */
20#define PWM_NCHAN 4 /* max 32 */
21
22struct pwm {
23 spinlock_t lock;
24 struct platform_device *pdev;
25 u32 mask;
26 int irq;
27 void __iomem *base;
28 struct clk *clk;
29 struct pwm_channel *channel[PWM_NCHAN];
30 void (*handler[PWM_NCHAN])(struct pwm_channel *);
31};
32
33
34/* global PWM controller registers */
35#define PWM_MR 0x00
36#define PWM_ENA 0x04
37#define PWM_DIS 0x08
38#define PWM_SR 0x0c
39#define PWM_IER 0x10
40#define PWM_IDR 0x14
41#define PWM_IMR 0x18
42#define PWM_ISR 0x1c
43
44static inline void pwm_writel(const struct pwm *p, unsigned offset, u32 val)
45{
46 __raw_writel(val, p->base + offset);
47}
48
49static inline u32 pwm_readl(const struct pwm *p, unsigned offset)
50{
51 return __raw_readl(p->base + offset);
52}
53
54static inline void __iomem *pwmc_regs(const struct pwm *p, int index)
55{
56 return p->base + 0x200 + index * 0x20;
57}
58
59static struct pwm *pwm;
60
61static void pwm_dumpregs(struct pwm_channel *ch, char *tag)
62{
63 struct device *dev = &pwm->pdev->dev;
64
65 dev_dbg(dev, "%s: mr %08x, sr %08x, imr %08x\n",
66 tag,
67 pwm_readl(pwm, PWM_MR),
68 pwm_readl(pwm, PWM_SR),
69 pwm_readl(pwm, PWM_IMR));
70 dev_dbg(dev,
71 "pwm ch%d - mr %08x, dty %u, prd %u, cnt %u\n",
72 ch->index,
73 pwm_channel_readl(ch, PWM_CMR),
74 pwm_channel_readl(ch, PWM_CDTY),
75 pwm_channel_readl(ch, PWM_CPRD),
76 pwm_channel_readl(ch, PWM_CCNT));
77}
78
79
80/**
81 * pwm_channel_alloc - allocate an unused PWM channel
82 * @index: identifies the channel
83 * @ch: structure to be initialized
84 *
85 * Drivers allocate PWM channels according to the board's wiring, and
86 * matching board-specific setup code. Returns zero or negative errno.
87 */
88int pwm_channel_alloc(int index, struct pwm_channel *ch)
89{
90 unsigned long flags;
91 int status = 0;
92
93 if (!pwm)
94 return -EPROBE_DEFER;
95
96 if (!(pwm->mask & 1 << index))
97 return -ENODEV;
98
99 if (index < 0 || index >= PWM_NCHAN || !ch)
100 return -EINVAL;
101 memset(ch, 0, sizeof *ch);
102
103 spin_lock_irqsave(&pwm->lock, flags);
104 if (pwm->channel[index])
105 status = -EBUSY;
106 else {
107 clk_enable(pwm->clk);
108
109 ch->regs = pwmc_regs(pwm, index);
110 ch->index = index;
111
112 /* REVISIT: ap7000 seems to go 2x as fast as we expect!! */
113 ch->mck = clk_get_rate(pwm->clk);
114
115 pwm->channel[index] = ch;
116 pwm->handler[index] = NULL;
117
118 /* channel and irq are always disabled when we return */
119 pwm_writel(pwm, PWM_DIS, 1 << index);
120 pwm_writel(pwm, PWM_IDR, 1 << index);
121 }
122 spin_unlock_irqrestore(&pwm->lock, flags);
123 return status;
124}
125EXPORT_SYMBOL(pwm_channel_alloc);
126
127static int pwmcheck(struct pwm_channel *ch)
128{
129 int index;
130
131 if (!pwm)
132 return -ENODEV;
133 if (!ch)
134 return -EINVAL;
135 index = ch->index;
136 if (index < 0 || index >= PWM_NCHAN || pwm->channel[index] != ch)
137 return -EINVAL;
138
139 return index;
140}
141
142/**
143 * pwm_channel_free - release a previously allocated channel
144 * @ch: the channel being released
145 *
146 * The channel is completely shut down (counter and IRQ disabled),
147 * and made available for re-use. Returns zero, or negative errno.
148 */
149int pwm_channel_free(struct pwm_channel *ch)
150{
151 unsigned long flags;
152 int t;
153
154 spin_lock_irqsave(&pwm->lock, flags);
155 t = pwmcheck(ch);
156 if (t >= 0) {
157 pwm->channel[t] = NULL;
158 pwm->handler[t] = NULL;
159
160 /* channel and irq are always disabled when we return */
161 pwm_writel(pwm, PWM_DIS, 1 << t);
162 pwm_writel(pwm, PWM_IDR, 1 << t);
163
164 clk_disable(pwm->clk);
165 t = 0;
166 }
167 spin_unlock_irqrestore(&pwm->lock, flags);
168 return t;
169}
170EXPORT_SYMBOL(pwm_channel_free);
171
172int __pwm_channel_onoff(struct pwm_channel *ch, int enabled)
173{
174 unsigned long flags;
175 int t;
176
177 /* OMITTED FUNCTIONALITY: starting several channels in synch */
178
179 spin_lock_irqsave(&pwm->lock, flags);
180 t = pwmcheck(ch);
181 if (t >= 0) {
182 pwm_writel(pwm, enabled ? PWM_ENA : PWM_DIS, 1 << t);
183 t = 0;
184 pwm_dumpregs(ch, enabled ? "enable" : "disable");
185 }
186 spin_unlock_irqrestore(&pwm->lock, flags);
187
188 return t;
189}
190EXPORT_SYMBOL(__pwm_channel_onoff);
191
192/**
193 * pwm_clk_alloc - allocate and configure CLKA or CLKB
194 * @prescale: from 0..10, the power of two used to divide MCK
195 * @div: from 1..255, the linear divisor to use
196 *
197 * Returns PWM_CPR_CLKA, PWM_CPR_CLKB, or negative errno. The allocated
198 * clock will run with a period of (2^prescale * div) / MCK, or twice as
199 * long if center aligned PWM output is used. The clock must later be
200 * deconfigured using pwm_clk_free().
201 */
202int pwm_clk_alloc(unsigned prescale, unsigned div)
203{
204 unsigned long flags;
205 u32 mr;
206 u32 val = (prescale << 8) | div;
207 int ret = -EBUSY;
208
209 if (prescale >= 10 || div == 0 || div > 255)
210 return -EINVAL;
211
212 spin_lock_irqsave(&pwm->lock, flags);
213 mr = pwm_readl(pwm, PWM_MR);
214 if ((mr & 0xffff) == 0) {
215 mr |= val;
216 ret = PWM_CPR_CLKA;
217 } else if ((mr & (0xffff << 16)) == 0) {
218 mr |= val << 16;
219 ret = PWM_CPR_CLKB;
220 }
221 if (ret > 0)
222 pwm_writel(pwm, PWM_MR, mr);
223 spin_unlock_irqrestore(&pwm->lock, flags);
224 return ret;
225}
226EXPORT_SYMBOL(pwm_clk_alloc);
227
228/**
229 * pwm_clk_free - deconfigure and release CLKA or CLKB
230 *
231 * Reverses the effect of pwm_clk_alloc().
232 */
233void pwm_clk_free(unsigned clk)
234{
235 unsigned long flags;
236 u32 mr;
237
238 spin_lock_irqsave(&pwm->lock, flags);
239 mr = pwm_readl(pwm, PWM_MR);
240 if (clk == PWM_CPR_CLKA)
241 pwm_writel(pwm, PWM_MR, mr & ~(0xffff << 0));
242 if (clk == PWM_CPR_CLKB)
243 pwm_writel(pwm, PWM_MR, mr & ~(0xffff << 16));
244 spin_unlock_irqrestore(&pwm->lock, flags);
245}
246EXPORT_SYMBOL(pwm_clk_free);
247
248/**
249 * pwm_channel_handler - manage channel's IRQ handler
250 * @ch: the channel
251 * @handler: the handler to use, possibly NULL
252 *
253 * If the handler is non-null, the handler will be called after every
254 * period of this PWM channel. If the handler is null, this channel
255 * won't generate an IRQ.
256 */
257int pwm_channel_handler(struct pwm_channel *ch,
258 void (*handler)(struct pwm_channel *ch))
259{
260 unsigned long flags;
261 int t;
262
263 spin_lock_irqsave(&pwm->lock, flags);
264 t = pwmcheck(ch);
265 if (t >= 0) {
266 pwm->handler[t] = handler;
267 pwm_writel(pwm, handler ? PWM_IER : PWM_IDR, 1 << t);
268 t = 0;
269 }
270 spin_unlock_irqrestore(&pwm->lock, flags);
271
272 return t;
273}
274EXPORT_SYMBOL(pwm_channel_handler);
275
276static irqreturn_t pwm_irq(int id, void *_pwm)
277{
278 struct pwm *p = _pwm;
279 irqreturn_t handled = IRQ_NONE;
280 u32 irqstat;
281 int index;
282
283 spin_lock(&p->lock);
284
285 /* ack irqs, then handle them */
286 irqstat = pwm_readl(pwm, PWM_ISR);
287
288 while (irqstat) {
289 struct pwm_channel *ch;
290 void (*handler)(struct pwm_channel *ch);
291
292 index = ffs(irqstat) - 1;
293 irqstat &= ~(1 << index);
294 ch = pwm->channel[index];
295 handler = pwm->handler[index];
296 if (handler && ch) {
297 spin_unlock(&p->lock);
298 handler(ch);
299 spin_lock(&p->lock);
300 handled = IRQ_HANDLED;
301 }
302 }
303
304 spin_unlock(&p->lock);
305 return handled;
306}
307
308static int __init pwm_probe(struct platform_device *pdev)
309{
310 struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
311 int irq = platform_get_irq(pdev, 0);
312 u32 *mp = pdev->dev.platform_data;
313 struct pwm *p;
314 int status = -EIO;
315
316 if (pwm)
317 return -EBUSY;
318 if (!r || irq < 0 || !mp || !*mp)
319 return -ENODEV;
320 if (*mp & ~((1<<PWM_NCHAN)-1)) {
321 dev_warn(&pdev->dev, "mask 0x%x ... more than %d channels\n",
322 *mp, PWM_NCHAN);
323 return -EINVAL;
324 }
325
326 p = kzalloc(sizeof(*p), GFP_KERNEL);
327 if (!p)
328 return -ENOMEM;
329
330 spin_lock_init(&p->lock);
331 p->pdev = pdev;
332 p->mask = *mp;
333 p->irq = irq;
334 p->base = ioremap(r->start, resource_size(r));
335 if (!p->base)
336 goto fail;
337 p->clk = clk_get(&pdev->dev, "pwm_clk");
338 if (IS_ERR(p->clk)) {
339 status = PTR_ERR(p->clk);
340 p->clk = NULL;
341 goto fail;
342 }
343
344 status = request_irq(irq, pwm_irq, 0, pdev->name, p);
345 if (status < 0)
346 goto fail;
347
348 pwm = p;
349 platform_set_drvdata(pdev, p);
350
351 return 0;
352
353fail:
354 if (p->clk)
355 clk_put(p->clk);
356 if (p->base)
357 iounmap(p->base);
358
359 kfree(p);
360 return status;
361}
362
363static int __exit pwm_remove(struct platform_device *pdev)
364{
365 struct pwm *p = platform_get_drvdata(pdev);
366
367 if (p != pwm)
368 return -EINVAL;
369
370 clk_enable(pwm->clk);
371 pwm_writel(pwm, PWM_DIS, (1 << PWM_NCHAN) - 1);
372 pwm_writel(pwm, PWM_IDR, (1 << PWM_NCHAN) - 1);
373 clk_disable(pwm->clk);
374
375 pwm = NULL;
376
377 free_irq(p->irq, p);
378 clk_put(p->clk);
379 iounmap(p->base);
380 kfree(p);
381
382 return 0;
383}
384
385static struct platform_driver atmel_pwm_driver = {
386 .driver = {
387 .name = "atmel_pwm",
388 .owner = THIS_MODULE,
389 },
390 .remove = __exit_p(pwm_remove),
391
392 /* NOTE: PWM can keep running in AVR32 "idle" and "frozen" states;
393 * and all AT91sam9263 states, albeit at reduced clock rate if
394 * MCK becomes the slow clock (i.e. what Linux labels STR).
395 */
396};
397
398module_platform_driver_probe(atmel_pwm_driver, pwm_probe);
399
400MODULE_DESCRIPTION("Driver for AT32/AT91 PWM module");
401MODULE_LICENSE("GPL");
402MODULE_ALIAS("platform:atmel_pwm");
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 4ad7b89a4cb4..331dfca415c7 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -43,7 +43,7 @@ config PWM_AB8500
43 43
44config PWM_ATMEL 44config PWM_ATMEL
45 tristate "Atmel PWM support" 45 tristate "Atmel PWM support"
46 depends on ARCH_AT91 46 depends on ARCH_AT91 || AVR32
47 help 47 help
48 Generic PWM framework driver for Atmel SoC. 48 Generic PWM framework driver for Atmel SoC.
49 49
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 5d449059a556..c3c18339b8cb 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -178,17 +178,6 @@ config BACKLIGHT_ATMEL_LCDC
178 If in doubt, it's safe to enable this option; it doesn't kick 178 If in doubt, it's safe to enable this option; it doesn't kick
179 in unless the board's description says it's wired that way. 179 in unless the board's description says it's wired that way.
180 180
181config BACKLIGHT_ATMEL_PWM
182 tristate "Atmel PWM backlight control"
183 depends on ATMEL_PWM
184 help
185 Say Y here if you want to use the PWM peripheral in Atmel AT91 and
186 AVR32 devices. This driver will need additional platform data to know
187 which PWM instance to use and how to configure it.
188
189 To compile this driver as a module, choose M here: the module will be
190 called atmel-pwm-bl.
191
192config BACKLIGHT_EP93XX 181config BACKLIGHT_EP93XX
193 tristate "Cirrus EP93xx Backlight Driver" 182 tristate "Cirrus EP93xx Backlight Driver"
194 depends on FB_EP93XX 183 depends on FB_EP93XX
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index bb820024f346..351451dbb607 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -25,7 +25,6 @@ obj-$(CONFIG_BACKLIGHT_ADP8860) += adp8860_bl.o
25obj-$(CONFIG_BACKLIGHT_ADP8870) += adp8870_bl.o 25obj-$(CONFIG_BACKLIGHT_ADP8870) += adp8870_bl.o
26obj-$(CONFIG_BACKLIGHT_APPLE) += apple_bl.o 26obj-$(CONFIG_BACKLIGHT_APPLE) += apple_bl.o
27obj-$(CONFIG_BACKLIGHT_AS3711) += as3711_bl.o 27obj-$(CONFIG_BACKLIGHT_AS3711) += as3711_bl.o
28obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o
29obj-$(CONFIG_BACKLIGHT_BD6107) += bd6107.o 28obj-$(CONFIG_BACKLIGHT_BD6107) += bd6107.o
30obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o 29obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
31obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o 30obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c
deleted file mode 100644
index 261b1a4ec3d8..000000000000
--- a/drivers/video/backlight/atmel-pwm-bl.c
+++ /dev/null
@@ -1,223 +0,0 @@
1/*
2 * Copyright (C) 2008 Atmel Corporation
3 *
4 * Backlight driver using Atmel PWM peripheral.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
9 */
10#include <linux/init.h>
11#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/platform_device.h>
14#include <linux/fb.h>
15#include <linux/gpio.h>
16#include <linux/backlight.h>
17#include <linux/atmel_pwm.h>
18#include <linux/atmel-pwm-bl.h>
19#include <linux/slab.h>
20
21struct atmel_pwm_bl {
22 const struct atmel_pwm_bl_platform_data *pdata;
23 struct backlight_device *bldev;
24 struct platform_device *pdev;
25 struct pwm_channel pwmc;
26 int gpio_on;
27};
28
29static void atmel_pwm_bl_set_gpio_on(struct atmel_pwm_bl *pwmbl, int on)
30{
31 if (!gpio_is_valid(pwmbl->gpio_on))
32 return;
33
34 gpio_set_value(pwmbl->gpio_on, on ^ pwmbl->pdata->on_active_low);
35}
36
37static int atmel_pwm_bl_set_intensity(struct backlight_device *bd)
38{
39 struct atmel_pwm_bl *pwmbl = bl_get_data(bd);
40 int intensity = bd->props.brightness;
41 int pwm_duty;
42
43 if (bd->props.power != FB_BLANK_UNBLANK)
44 intensity = 0;
45 if (bd->props.fb_blank != FB_BLANK_UNBLANK)
46 intensity = 0;
47
48 if (pwmbl->pdata->pwm_active_low)
49 pwm_duty = pwmbl->pdata->pwm_duty_min + intensity;
50 else
51 pwm_duty = pwmbl->pdata->pwm_duty_max - intensity;
52
53 if (pwm_duty > pwmbl->pdata->pwm_duty_max)
54 pwm_duty = pwmbl->pdata->pwm_duty_max;
55 if (pwm_duty < pwmbl->pdata->pwm_duty_min)
56 pwm_duty = pwmbl->pdata->pwm_duty_min;
57
58 if (!intensity) {
59 atmel_pwm_bl_set_gpio_on(pwmbl, 0);
60 pwm_channel_writel(&pwmbl->pwmc, PWM_CUPD, pwm_duty);
61 pwm_channel_disable(&pwmbl->pwmc);
62 } else {
63 pwm_channel_enable(&pwmbl->pwmc);
64 pwm_channel_writel(&pwmbl->pwmc, PWM_CUPD, pwm_duty);
65 atmel_pwm_bl_set_gpio_on(pwmbl, 1);
66 }
67
68 return 0;
69}
70
71static int atmel_pwm_bl_get_intensity(struct backlight_device *bd)
72{
73 struct atmel_pwm_bl *pwmbl = bl_get_data(bd);
74 u32 cdty;
75 u32 intensity;
76
77 cdty = pwm_channel_readl(&pwmbl->pwmc, PWM_CDTY);
78 if (pwmbl->pdata->pwm_active_low)
79 intensity = cdty - pwmbl->pdata->pwm_duty_min;
80 else
81 intensity = pwmbl->pdata->pwm_duty_max - cdty;
82
83 return intensity & 0xffff;
84}
85
86static int atmel_pwm_bl_init_pwm(struct atmel_pwm_bl *pwmbl)
87{
88 unsigned long pwm_rate = pwmbl->pwmc.mck;
89 unsigned long prescale = DIV_ROUND_UP(pwm_rate,
90 (pwmbl->pdata->pwm_frequency *
91 pwmbl->pdata->pwm_compare_max)) - 1;
92
93 /*
94 * Prescale must be power of two and maximum 0xf in size because of
95 * hardware limit. PWM speed will be:
96 * PWM module clock speed / (2 ^ prescale).
97 */
98 prescale = fls(prescale);
99 if (prescale > 0xf)
100 prescale = 0xf;
101
102 pwm_channel_writel(&pwmbl->pwmc, PWM_CMR, prescale);
103 pwm_channel_writel(&pwmbl->pwmc, PWM_CDTY,
104 pwmbl->pdata->pwm_duty_min +
105 pwmbl->bldev->props.brightness);
106 pwm_channel_writel(&pwmbl->pwmc, PWM_CPRD,
107 pwmbl->pdata->pwm_compare_max);
108
109 dev_info(&pwmbl->pdev->dev, "Atmel PWM backlight driver (%lu Hz)\n",
110 pwmbl->pwmc.mck / pwmbl->pdata->pwm_compare_max /
111 (1 << prescale));
112
113 return pwm_channel_enable(&pwmbl->pwmc);
114}
115
116static const struct backlight_ops atmel_pwm_bl_ops = {
117 .get_brightness = atmel_pwm_bl_get_intensity,
118 .update_status = atmel_pwm_bl_set_intensity,
119};
120
121static int atmel_pwm_bl_probe(struct platform_device *pdev)
122{
123 struct backlight_properties props;
124 const struct atmel_pwm_bl_platform_data *pdata;
125 struct backlight_device *bldev;
126 struct atmel_pwm_bl *pwmbl;
127 unsigned long flags;
128 int retval;
129
130 pdata = dev_get_platdata(&pdev->dev);
131 if (!pdata)
132 return -ENODEV;
133
134 if (pdata->pwm_compare_max < pdata->pwm_duty_max ||
135 pdata->pwm_duty_min > pdata->pwm_duty_max ||
136 pdata->pwm_frequency == 0)
137 return -EINVAL;
138
139 pwmbl = devm_kzalloc(&pdev->dev, sizeof(struct atmel_pwm_bl),
140 GFP_KERNEL);
141 if (!pwmbl)
142 return -ENOMEM;
143
144 pwmbl->pdev = pdev;
145 pwmbl->pdata = pdata;
146 pwmbl->gpio_on = pdata->gpio_on;
147
148 retval = pwm_channel_alloc(pdata->pwm_channel, &pwmbl->pwmc);
149 if (retval)
150 return retval;
151
152 if (gpio_is_valid(pwmbl->gpio_on)) {
153 /* Turn display off by default. */
154 if (pdata->on_active_low)
155 flags = GPIOF_OUT_INIT_HIGH;
156 else
157 flags = GPIOF_OUT_INIT_LOW;
158
159 retval = devm_gpio_request_one(&pdev->dev, pwmbl->gpio_on,
160 flags, "gpio_atmel_pwm_bl");
161 if (retval)
162 goto err_free_pwm;
163 }
164
165 memset(&props, 0, sizeof(struct backlight_properties));
166 props.type = BACKLIGHT_RAW;
167 props.max_brightness = pdata->pwm_duty_max - pdata->pwm_duty_min;
168 bldev = devm_backlight_device_register(&pdev->dev, "atmel-pwm-bl",
169 &pdev->dev, pwmbl, &atmel_pwm_bl_ops,
170 &props);
171 if (IS_ERR(bldev)) {
172 retval = PTR_ERR(bldev);
173 goto err_free_pwm;
174 }
175
176 pwmbl->bldev = bldev;
177
178 platform_set_drvdata(pdev, pwmbl);
179
180 /* Power up the backlight by default at middle intesity. */
181 bldev->props.power = FB_BLANK_UNBLANK;
182 bldev->props.brightness = bldev->props.max_brightness / 2;
183
184 retval = atmel_pwm_bl_init_pwm(pwmbl);
185 if (retval)
186 goto err_free_pwm;
187
188 atmel_pwm_bl_set_intensity(bldev);
189
190 return 0;
191
192err_free_pwm:
193 pwm_channel_free(&pwmbl->pwmc);
194
195 return retval;
196}
197
198static int atmel_pwm_bl_remove(struct platform_device *pdev)
199{
200 struct atmel_pwm_bl *pwmbl = platform_get_drvdata(pdev);
201
202 atmel_pwm_bl_set_gpio_on(pwmbl, 0);
203 pwm_channel_disable(&pwmbl->pwmc);
204 pwm_channel_free(&pwmbl->pwmc);
205
206 return 0;
207}
208
209static struct platform_driver atmel_pwm_bl_driver = {
210 .driver = {
211 .name = "atmel-pwm-bl",
212 },
213 /* REVISIT add suspend() and resume() */
214 .probe = atmel_pwm_bl_probe,
215 .remove = atmel_pwm_bl_remove,
216};
217
218module_platform_driver(atmel_pwm_bl_driver);
219
220MODULE_AUTHOR("Hans-Christian egtvedt <hans-christian.egtvedt@atmel.com>");
221MODULE_DESCRIPTION("Atmel PWM backlight driver");
222MODULE_LICENSE("GPL");
223MODULE_ALIAS("platform:atmel-pwm-bl");
diff --git a/include/linux/atmel-pwm-bl.h b/include/linux/atmel-pwm-bl.h
deleted file mode 100644
index 0153a47806c2..000000000000
--- a/include/linux/atmel-pwm-bl.h
+++ /dev/null
@@ -1,43 +0,0 @@
1/*
2 * Copyright (C) 2007 Atmel Corporation
3 *
4 * Driver for the AT32AP700X PS/2 controller (PSIF).
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation.
9 */
10
11#ifndef __INCLUDE_ATMEL_PWM_BL_H
12#define __INCLUDE_ATMEL_PWM_BL_H
13
14/**
15 * struct atmel_pwm_bl_platform_data
16 * @pwm_channel: which PWM channel in the PWM module to use.
17 * @pwm_frequency: PWM frequency to generate, the driver will try to be as
18 * close as the prescaler allows.
19 * @pwm_compare_max: value to use in the PWM channel compare register.
20 * @pwm_duty_max: maximum duty cycle value, must be less than or equal to
21 * pwm_compare_max.
22 * @pwm_duty_min: minimum duty cycle value, must be less than pwm_duty_max.
23 * @pwm_active_low: set to one if the low part of the PWM signal increases the
24 * brightness of the backlight.
25 * @gpio_on: GPIO line to control the backlight on/off, set to -1 if not used.
26 * @on_active_low: set to one if the on/off signal is on when GPIO is low.
27 *
28 * This struct must be added to the platform device in the board code. It is
29 * used by the atmel-pwm-bl driver to setup the GPIO to control on/off and the
30 * PWM device.
31 */
32struct atmel_pwm_bl_platform_data {
33 unsigned int pwm_channel;
34 unsigned int pwm_frequency;
35 unsigned int pwm_compare_max;
36 unsigned int pwm_duty_max;
37 unsigned int pwm_duty_min;
38 unsigned int pwm_active_low;
39 int gpio_on;
40 unsigned int on_active_low;
41};
42
43#endif /* __INCLUDE_ATMEL_PWM_BL_H */
diff --git a/include/linux/atmel_pwm.h b/include/linux/atmel_pwm.h
deleted file mode 100644
index ea04abb3db8e..000000000000
--- a/include/linux/atmel_pwm.h
+++ /dev/null
@@ -1,70 +0,0 @@
1#ifndef __LINUX_ATMEL_PWM_H
2#define __LINUX_ATMEL_PWM_H
3
4/**
5 * struct pwm_channel - driver handle to a PWM channel
6 * @regs: base of this channel's registers
7 * @index: number of this channel (0..31)
8 * @mck: base clock rate, which can be prescaled and maybe subdivided
9 *
10 * Drivers initialize a pwm_channel structure using pwm_channel_alloc().
11 * Then they configure its clock rate (derived from MCK), alignment,
12 * polarity, and duty cycle by writing directly to the channel registers,
13 * before enabling the channel by calling pwm_channel_enable().
14 *
15 * After emitting a PWM signal for the desired length of time, drivers
16 * may then pwm_channel_disable() or pwm_channel_free(). Both of these
17 * disable the channel, but when it's freed the IRQ is deconfigured and
18 * the channel must later be re-allocated and reconfigured.
19 *
20 * Note that if the period or duty cycle need to be changed while the
21 * PWM channel is operating, drivers must use the PWM_CUPD double buffer
22 * mechanism, either polling until they change or getting implicitly
23 * notified through a once-per-period interrupt handler.
24 */
25struct pwm_channel {
26 void __iomem *regs;
27 unsigned index;
28 unsigned long mck;
29};
30
31extern int pwm_channel_alloc(int index, struct pwm_channel *ch);
32extern int pwm_channel_free(struct pwm_channel *ch);
33
34extern int pwm_clk_alloc(unsigned prescale, unsigned div);
35extern void pwm_clk_free(unsigned clk);
36
37extern int __pwm_channel_onoff(struct pwm_channel *ch, int enabled);
38
39#define pwm_channel_enable(ch) __pwm_channel_onoff((ch), 1)
40#define pwm_channel_disable(ch) __pwm_channel_onoff((ch), 0)
41
42/* periodic interrupts, mostly for CUPD changes to period or cycle */
43extern int pwm_channel_handler(struct pwm_channel *ch,
44 void (*handler)(struct pwm_channel *ch));
45
46/* per-channel registers (banked at pwm_channel->regs) */
47#define PWM_CMR 0x00 /* mode register */
48#define PWM_CPR_CPD (1 << 10) /* set: CUPD modifies period */
49#define PWM_CPR_CPOL (1 << 9) /* set: idle high */
50#define PWM_CPR_CALG (1 << 8) /* set: center align */
51#define PWM_CPR_CPRE (0xf << 0) /* mask: rate is mck/(2^pre) */
52#define PWM_CPR_CLKA (0xb << 0) /* rate CLKA */
53#define PWM_CPR_CLKB (0xc << 0) /* rate CLKB */
54#define PWM_CDTY 0x04 /* duty cycle (max of CPRD) */
55#define PWM_CPRD 0x08 /* period (count up from zero) */
56#define PWM_CCNT 0x0c /* counter (20 bits?) */
57#define PWM_CUPD 0x10 /* update CPRD (or CDTY) next period */
58
59static inline void
60pwm_channel_writel(struct pwm_channel *pwmc, unsigned offset, u32 val)
61{
62 __raw_writel(val, pwmc->regs + offset);
63}
64
65static inline u32 pwm_channel_readl(struct pwm_channel *pwmc, unsigned offset)
66{
67 return __raw_readl(pwmc->regs + offset);
68}
69
70#endif /* __LINUX_ATMEL_PWM_H */