aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-pxa
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-pxa')
-rw-r--r--arch/arm/mach-pxa/Kconfig25
-rw-r--r--arch/arm/mach-pxa/Makefile1
-rw-r--r--arch/arm/mach-pxa/clock.c3
-rw-r--r--arch/arm/mach-pxa/clock.h12
-rw-r--r--arch/arm/mach-pxa/devices.c60
-rw-r--r--arch/arm/mach-pxa/devices.h5
-rw-r--r--arch/arm/mach-pxa/irq.c1
-rw-r--r--arch/arm/mach-pxa/lpd270.c38
-rw-r--r--arch/arm/mach-pxa/magician.c68
-rw-r--r--arch/arm/mach-pxa/mainstone.c63
-rw-r--r--arch/arm/mach-pxa/pcm990-baseboard.c99
-rw-r--r--arch/arm/mach-pxa/pwm.c319
-rw-r--r--arch/arm/mach-pxa/pxa25x.c14
-rw-r--r--arch/arm/mach-pxa/pxa27x.c5
-rw-r--r--arch/arm/mach-pxa/pxa3xx.c4
-rw-r--r--arch/arm/mach-pxa/zylonite.c26
-rw-r--r--arch/arm/mach-pxa/zylonite_pxa300.c4
-rw-r--r--arch/arm/mach-pxa/zylonite_pxa320.c2
18 files changed, 640 insertions, 109 deletions
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index caccbbc41b43..914bb33dab92 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -36,10 +36,12 @@ config ARCH_LUBBOCK
36config MACH_LOGICPD_PXA270 36config MACH_LOGICPD_PXA270
37 bool "LogicPD PXA270 Card Engine Development Platform" 37 bool "LogicPD PXA270 Card Engine Development Platform"
38 select PXA27x 38 select PXA27x
39 select HAVE_PWM
39 40
40config MACH_MAINSTONE 41config MACH_MAINSTONE
41 bool "Intel HCDDBBVA0 Development Platform" 42 bool "Intel HCDDBBVA0 Development Platform"
42 select PXA27x 43 select PXA27x
44 select HAVE_PWM
43 45
44config ARCH_PXA_IDP 46config ARCH_PXA_IDP
45 bool "Accelent Xscale IDP" 47 bool "Accelent Xscale IDP"
@@ -115,6 +117,7 @@ config MACH_COLIBRI
115config MACH_ZYLONITE 117config MACH_ZYLONITE
116 bool "PXA3xx Development Platform" 118 bool "PXA3xx Development Platform"
117 select PXA3xx 119 select PXA3xx
120 select HAVE_PWM
118 121
119config MACH_LITTLETON 122config MACH_LITTLETON
120 bool "PXA3xx Form Factor Platform (aka Littleton)" 123 bool "PXA3xx Form Factor Platform (aka Littleton)"
@@ -145,6 +148,22 @@ choice
145 148
146config MACH_PCM990_BASEBOARD 149config MACH_PCM990_BASEBOARD
147 bool "PHYTEC PCM-990 development board" 150 bool "PHYTEC PCM-990 development board"
151 select HAVE_PWM
152
153endchoice
154
155choice
156 prompt "display on pcm990"
157 depends on MACH_PCM990_BASEBOARD
158
159config PCM990_DISPLAY_SHARP
160 bool "sharp lq084v1dg21 stn display"
161
162config PCM990_DISPLAY_NEC
163 bool "nec nl6448bc20_18d tft display"
164
165config PCM990_DISPLAY_NONE
166 bool "no display"
148 167
149endchoice 168endchoice
150 169
@@ -263,4 +282,10 @@ config PXA_SSP
263 tristate 282 tristate
264 help 283 help
265 Enable support for PXA2xx SSP ports 284 Enable support for PXA2xx SSP ports
285
286config PXA_PWM
287 tristate
288 default BACKLIGHT_PWM
289 help
290 Enable support for PXA2xx/PXA3xx PWM controllers
266endif 291endif
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 0e6d05bb81aa..02cbc3cfbe01 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_CPU_FREQ) += cpu-pxa.o
10 10
11# Generic drivers that other drivers may depend upon 11# Generic drivers that other drivers may depend upon
12obj-$(CONFIG_PXA_SSP) += ssp.o 12obj-$(CONFIG_PXA_SSP) += ssp.o
13obj-$(CONFIG_PXA_PWM) += pwm.o
13 14
14# SoC-specific code 15# SoC-specific code
15obj-$(CONFIG_PXA25x) += mfp-pxa2xx.o pxa25x.o 16obj-$(CONFIG_PXA25x) += mfp-pxa2xx.o pxa25x.o
diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c
index 180c8bb53041..b4d04955dcb0 100644
--- a/arch/arm/mach-pxa/clock.c
+++ b/arch/arm/mach-pxa/clock.c
@@ -47,6 +47,9 @@ struct clk *clk_get(struct device *dev, const char *id)
47 clk = p; 47 clk = p;
48 mutex_unlock(&clocks_mutex); 48 mutex_unlock(&clocks_mutex);
49 49
50 if (!IS_ERR(clk) && clk->ops == NULL)
51 clk = clk->other;
52
50 return clk; 53 return clk;
51} 54}
52EXPORT_SYMBOL(clk_get); 55EXPORT_SYMBOL(clk_get);
diff --git a/arch/arm/mach-pxa/clock.h b/arch/arm/mach-pxa/clock.h
index bc6b77e1592e..83cbfaba485d 100644
--- a/arch/arm/mach-pxa/clock.h
+++ b/arch/arm/mach-pxa/clock.h
@@ -15,6 +15,7 @@ struct clk {
15 unsigned int cken; 15 unsigned int cken;
16 unsigned int delay; 16 unsigned int delay;
17 unsigned int enabled; 17 unsigned int enabled;
18 struct clk *other;
18}; 19};
19 20
20#define INIT_CKEN(_name, _cken, _rate, _delay, _dev) \ 21#define INIT_CKEN(_name, _cken, _rate, _delay, _dev) \
@@ -35,6 +36,17 @@ struct clk {
35 .cken = CKEN_##_cken, \ 36 .cken = CKEN_##_cken, \
36 } 37 }
37 38
39/*
40 * This is a placeholder to alias one clock device+name pair
41 * to another struct clk.
42 */
43#define INIT_CKOTHER(_name, _other, _dev) \
44 { \
45 .name = _name, \
46 .dev = _dev, \
47 .other = _other, \
48 }
49
38extern const struct clkops clk_cken_ops; 50extern const struct clkops clk_cken_ops;
39 51
40void clk_cken_enable(struct clk *clk); 52void clk_cken_enable(struct clk *clk);
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index af6cc3dbb9a3..4a1eebb42e49 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -289,6 +289,36 @@ struct platform_device pxa_device_rtc = {
289 289
290#ifdef CONFIG_PXA25x 290#ifdef CONFIG_PXA25x
291 291
292static struct resource pxa25x_resource_pwm0[] = {
293 [0] = {
294 .start = 0x40b00000,
295 .end = 0x40b0000f,
296 .flags = IORESOURCE_MEM,
297 },
298};
299
300struct platform_device pxa25x_device_pwm0 = {
301 .name = "pxa25x-pwm",
302 .id = 0,
303 .resource = pxa25x_resource_pwm0,
304 .num_resources = ARRAY_SIZE(pxa25x_resource_pwm0),
305};
306
307static struct resource pxa25x_resource_pwm1[] = {
308 [0] = {
309 .start = 0x40c00000,
310 .end = 0x40c0000f,
311 .flags = IORESOURCE_MEM,
312 },
313};
314
315struct platform_device pxa25x_device_pwm1 = {
316 .name = "pxa25x-pwm",
317 .id = 1,
318 .resource = pxa25x_resource_pwm1,
319 .num_resources = ARRAY_SIZE(pxa25x_resource_pwm1),
320};
321
292static u64 pxa25x_ssp_dma_mask = DMA_BIT_MASK(32); 322static u64 pxa25x_ssp_dma_mask = DMA_BIT_MASK(32);
293 323
294static struct resource pxa25x_resource_ssp[] = { 324static struct resource pxa25x_resource_ssp[] = {
@@ -577,6 +607,36 @@ struct platform_device pxa27x_device_ssp3 = {
577 .num_resources = ARRAY_SIZE(pxa27x_resource_ssp3), 607 .num_resources = ARRAY_SIZE(pxa27x_resource_ssp3),
578}; 608};
579 609
610static struct resource pxa27x_resource_pwm0[] = {
611 [0] = {
612 .start = 0x40b00000,
613 .end = 0x40b0001f,
614 .flags = IORESOURCE_MEM,
615 },
616};
617
618struct platform_device pxa27x_device_pwm0 = {
619 .name = "pxa27x-pwm",
620 .id = 0,
621 .resource = pxa27x_resource_pwm0,
622 .num_resources = ARRAY_SIZE(pxa27x_resource_pwm0),
623};
624
625static struct resource pxa27x_resource_pwm1[] = {
626 [0] = {
627 .start = 0x40c00000,
628 .end = 0x40c0001f,
629 .flags = IORESOURCE_MEM,
630 },
631};
632
633struct platform_device pxa27x_device_pwm1 = {
634 .name = "pxa27x-pwm",
635 .id = 1,
636 .resource = pxa27x_resource_pwm1,
637 .num_resources = ARRAY_SIZE(pxa27x_resource_pwm1),
638};
639
580static struct resource pxa27x_resource_camera[] = { 640static struct resource pxa27x_resource_camera[] = {
581 [0] = { 641 [0] = {
582 .start = 0x50000000, 642 .start = 0x50000000,
diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h
index fcab017f27ee..e620a3373d42 100644
--- a/arch/arm/mach-pxa/devices.h
+++ b/arch/arm/mach-pxa/devices.h
@@ -24,4 +24,9 @@ extern struct platform_device pxa27x_device_ssp2;
24extern struct platform_device pxa27x_device_ssp3; 24extern struct platform_device pxa27x_device_ssp3;
25extern struct platform_device pxa3xx_device_ssp4; 25extern struct platform_device pxa3xx_device_ssp4;
26 26
27extern struct platform_device pxa25x_device_pwm0;
28extern struct platform_device pxa25x_device_pwm1;
29extern struct platform_device pxa27x_device_pwm0;
30extern struct platform_device pxa27x_device_pwm1;
31
27void __init pxa_register_device(struct platform_device *dev, void *data); 32void __init pxa_register_device(struct platform_device *dev, void *data);
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index a9a0c3fab159..fbff557bb225 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -21,7 +21,6 @@
21#include <asm/irq.h> 21#include <asm/irq.h>
22#include <asm/mach/irq.h> 22#include <asm/mach/irq.h>
23#include <asm/arch/pxa-regs.h> 23#include <asm/arch/pxa-regs.h>
24#include <asm/arch/pxa2xx-gpio.h>
25 24
26#include "generic.h" 25#include "generic.h"
27 26
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
index 6fd7b8b753fc..183b587672a6 100644
--- a/arch/arm/mach-pxa/lpd270.c
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -23,6 +23,7 @@
23#include <linux/ioport.h> 23#include <linux/ioport.h>
24#include <linux/mtd/mtd.h> 24#include <linux/mtd/mtd.h>
25#include <linux/mtd/partitions.h> 25#include <linux/mtd/partitions.h>
26#include <linux/pwm_backlight.h>
26 27
27#include <asm/types.h> 28#include <asm/types.h>
28#include <asm/setup.h> 29#include <asm/setup.h>
@@ -236,21 +237,20 @@ static struct platform_device lpd270_flash_device[2] = {
236 }, 237 },
237}; 238};
238 239
239static void lpd270_backlight_power(int on) 240static struct platform_pwm_backlight_data lpd270_backlight_data = {
240{ 241 .pwm_id = 0,
241 if (on) { 242 .max_brightness = 1,
242 pxa_gpio_mode(GPIO16_PWM0_MD); 243 .dft_brightness = 1,
243 pxa_set_cken(CKEN_PWM0, 1); 244 .pwm_period_ns = 78770,
244 PWM_CTRL0 = 0; 245};
245 PWM_PWDUTY0 = 0x3ff; 246
246 PWM_PERVAL0 = 0x3ff; 247static struct platform_device lpd270_backlight_device = {
247 } else { 248 .name = "pwm-backlight",
248 PWM_CTRL0 = 0; 249 .dev = {
249 PWM_PWDUTY0 = 0x0; 250 .parent = &pxa27x_device_pwm0.dev,
250 PWM_PERVAL0 = 0x3FF; 251 .platform_data = &lpd270_backlight_data,
251 pxa_set_cken(CKEN_PWM0, 0); 252 },
252 } 253};
253}
254 254
255/* 5.7" TFT QVGA (LoLo display number 1) */ 255/* 5.7" TFT QVGA (LoLo display number 1) */
256static struct pxafb_mode_info sharp_lq057q3dc02_mode = { 256static struct pxafb_mode_info sharp_lq057q3dc02_mode = {
@@ -272,7 +272,6 @@ static struct pxafb_mach_info sharp_lq057q3dc02 = {
272 .num_modes = 1, 272 .num_modes = 1,
273 .lccr0 = 0x07800080, 273 .lccr0 = 0x07800080,
274 .lccr3 = 0x00400000, 274 .lccr3 = 0x00400000,
275 .pxafb_backlight_power = lpd270_backlight_power,
276}; 275};
277 276
278/* 12.1" TFT SVGA (LoLo display number 2) */ 277/* 12.1" TFT SVGA (LoLo display number 2) */
@@ -295,7 +294,6 @@ static struct pxafb_mach_info sharp_lq121s1dg31 = {
295 .num_modes = 1, 294 .num_modes = 1,
296 .lccr0 = 0x07800080, 295 .lccr0 = 0x07800080,
297 .lccr3 = 0x00400000, 296 .lccr3 = 0x00400000,
298 .pxafb_backlight_power = lpd270_backlight_power,
299}; 297};
300 298
301/* 3.6" TFT QVGA (LoLo display number 3) */ 299/* 3.6" TFT QVGA (LoLo display number 3) */
@@ -318,7 +316,6 @@ static struct pxafb_mach_info sharp_lq036q1da01 = {
318 .num_modes = 1, 316 .num_modes = 1,
319 .lccr0 = 0x07800080, 317 .lccr0 = 0x07800080,
320 .lccr3 = 0x00400000, 318 .lccr3 = 0x00400000,
321 .pxafb_backlight_power = lpd270_backlight_power,
322}; 319};
323 320
324/* 6.4" TFT VGA (LoLo display number 5) */ 321/* 6.4" TFT VGA (LoLo display number 5) */
@@ -341,7 +338,6 @@ static struct pxafb_mach_info sharp_lq64d343 = {
341 .num_modes = 1, 338 .num_modes = 1,
342 .lccr0 = 0x07800080, 339 .lccr0 = 0x07800080,
343 .lccr3 = 0x00400000, 340 .lccr3 = 0x00400000,
344 .pxafb_backlight_power = lpd270_backlight_power,
345}; 341};
346 342
347/* 10.4" TFT VGA (LoLo display number 7) */ 343/* 10.4" TFT VGA (LoLo display number 7) */
@@ -364,7 +360,6 @@ static struct pxafb_mach_info sharp_lq10d368 = {
364 .num_modes = 1, 360 .num_modes = 1,
365 .lccr0 = 0x07800080, 361 .lccr0 = 0x07800080,
366 .lccr3 = 0x00400000, 362 .lccr3 = 0x00400000,
367 .pxafb_backlight_power = lpd270_backlight_power,
368}; 363};
369 364
370/* 3.5" TFT QVGA (LoLo display number 8) */ 365/* 3.5" TFT QVGA (LoLo display number 8) */
@@ -387,7 +382,6 @@ static struct pxafb_mach_info sharp_lq035q7db02_20 = {
387 .num_modes = 1, 382 .num_modes = 1,
388 .lccr0 = 0x07800080, 383 .lccr0 = 0x07800080,
389 .lccr3 = 0x00400000, 384 .lccr3 = 0x00400000,
390 .pxafb_backlight_power = lpd270_backlight_power,
391}; 385};
392 386
393static struct pxafb_mach_info *lpd270_lcd_to_use; 387static struct pxafb_mach_info *lpd270_lcd_to_use;
@@ -417,6 +411,7 @@ __setup("lcd=", lpd270_set_lcd);
417 411
418static struct platform_device *platform_devices[] __initdata = { 412static struct platform_device *platform_devices[] __initdata = {
419 &smc91x_device, 413 &smc91x_device,
414 &lpd270_backlight_device,
420 &lpd270_audio_device, 415 &lpd270_audio_device,
421 &lpd270_flash_device[0], 416 &lpd270_flash_device[0],
422 &lpd270_flash_device[1], 417 &lpd270_flash_device[1],
@@ -457,6 +452,7 @@ static void __init lpd270_init(void)
457 * On LogicPD PXA270, we route AC97_SYSCLK via GPIO45. 452 * On LogicPD PXA270, we route AC97_SYSCLK via GPIO45.
458 */ 453 */
459 pxa_gpio_mode(GPIO45_SYSCLK_AC97_MD); 454 pxa_gpio_mode(GPIO45_SYSCLK_AC97_MD);
455 pxa_gpio_mode(GPIO16_PWM0_MD);
460 456
461 platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); 457 platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
462 458
diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
index b94cae483149..01b2fa790217 100644
--- a/arch/arm/mach-pxa/magician.c
+++ b/arch/arm/mach-pxa/magician.c
@@ -25,6 +25,7 @@
25#include <linux/mtd/map.h> 25#include <linux/mtd/map.h>
26#include <linux/mtd/physmap.h> 26#include <linux/mtd/physmap.h>
27#include <linux/pda_power.h> 27#include <linux/pda_power.h>
28#include <linux/pwm_backlight.h>
28 29
29#include <asm/gpio.h> 30#include <asm/gpio.h>
30#include <asm/hardware.h> 31#include <asm/hardware.h>
@@ -40,6 +41,7 @@
40#include <asm/arch/irda.h> 41#include <asm/arch/irda.h>
41#include <asm/arch/ohci.h> 42#include <asm/arch/ohci.h>
42 43
44#include "devices.h"
43#include "generic.h" 45#include "generic.h"
44 46
45static unsigned long magician_pin_config[] = { 47static unsigned long magician_pin_config[] = {
@@ -349,40 +351,58 @@ static struct pxafb_mach_info samsung_info = {
349 * Backlight 351 * Backlight
350 */ 352 */
351 353
352static void magician_set_bl_intensity(int intensity) 354static int magician_backlight_init(struct device *dev)
353{ 355{
354 if (intensity) { 356 int ret;
355 PWM_CTRL0 = 1; 357
356 PWM_PERVAL0 = 0xc8; 358 ret = gpio_request(EGPIO_MAGICIAN_BL_POWER, "BL_POWER");
357 if (intensity > 0xc7) { 359 if (ret)
358 PWM_PWDUTY0 = intensity - 0x48; 360 goto err;
359 gpio_set_value(EGPIO_MAGICIAN_BL_POWER2, 1); 361 ret = gpio_request(EGPIO_MAGICIAN_BL_POWER2, "BL_POWER2");
360 } else { 362 if (ret)
361 PWM_PWDUTY0 = intensity; 363 goto err2;
362 gpio_set_value(EGPIO_MAGICIAN_BL_POWER2, 0); 364 return 0;
363 } 365
364 gpio_set_value(EGPIO_MAGICIAN_BL_POWER, 1); 366err2:
365 pxa_set_cken(CKEN_PWM0, 1); 367 gpio_free(EGPIO_MAGICIAN_BL_POWER);
368err:
369 return ret;
370}
371
372static int magician_backlight_notify(int brightness)
373{
374 gpio_set_value(EGPIO_MAGICIAN_BL_POWER, brightness);
375 if (brightness >= 200) {
376 gpio_set_value(EGPIO_MAGICIAN_BL_POWER2, 1);
377 return brightness - 72;
366 } else { 378 } else {
367 /* PWM_PWDUTY0 = intensity; */ 379 gpio_set_value(EGPIO_MAGICIAN_BL_POWER2, 0);
368 gpio_set_value(EGPIO_MAGICIAN_BL_POWER, 0); 380 return brightness;
369 pxa_set_cken(CKEN_PWM0, 0);
370 } 381 }
371} 382}
372 383
373static struct generic_bl_info backlight_info = { 384static void magician_backlight_exit(struct device *dev)
374 .default_intensity = 0x64, 385{
375 .limit_mask = 0x0b, 386 gpio_free(EGPIO_MAGICIAN_BL_POWER);
376 .max_intensity = 0xc7+0x48, 387 gpio_free(EGPIO_MAGICIAN_BL_POWER2);
377 .set_bl_intensity = magician_set_bl_intensity, 388}
389
390static struct platform_pwm_backlight_data backlight_data = {
391 .pwm_id = 0,
392 .max_brightness = 272,
393 .dft_brightness = 100,
394 .pwm_period_ns = 30923,
395 .init = magician_backlight_init,
396 .notify = magician_backlight_notify,
397 .exit = magician_backlight_exit,
378}; 398};
379 399
380static struct platform_device backlight = { 400static struct platform_device backlight = {
381 .name = "generic-bl", 401 .name = "pwm-backlight",
382 .dev = { 402 .dev = {
383 .platform_data = &backlight_info, 403 .parent = &pxa27x_device_pwm0.dev,
404 .platform_data = &backlight_data,
384 }, 405 },
385 .id = -1,
386}; 406};
387 407
388/* 408/*
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 7399fb34da4e..266594426e8b 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -23,9 +23,9 @@
23#include <linux/ioport.h> 23#include <linux/ioport.h>
24#include <linux/mtd/mtd.h> 24#include <linux/mtd/mtd.h>
25#include <linux/mtd/partitions.h> 25#include <linux/mtd/partitions.h>
26#include <linux/backlight.h>
27#include <linux/input.h> 26#include <linux/input.h>
28#include <linux/gpio_keys.h> 27#include <linux/gpio_keys.h>
28#include <linux/pwm_backlight.h>
29 29
30#include <asm/types.h> 30#include <asm/types.h>
31#include <asm/setup.h> 31#include <asm/setup.h>
@@ -349,56 +349,27 @@ static struct platform_device mst_flash_device[2] = {
349 }, 349 },
350}; 350};
351 351
352#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE 352#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
353static int mainstone_backlight_update_status(struct backlight_device *bl) 353static struct platform_pwm_backlight_data mainstone_backlight_data = {
354{ 354 .pwm_id = 0,
355 int brightness = bl->props.brightness; 355 .max_brightness = 1023,
356 356 .dft_brightness = 1023,
357 if (bl->props.power != FB_BLANK_UNBLANK || 357 .pwm_period_ns = 78770,
358 bl->props.fb_blank != FB_BLANK_UNBLANK) 358};
359 brightness = 0;
360
361 if (brightness != 0)
362 pxa_set_cken(CKEN_PWM0, 1);
363
364 PWM_CTRL0 = 0;
365 PWM_PWDUTY0 = brightness;
366 PWM_PERVAL0 = bl->props.max_brightness;
367
368 if (brightness == 0)
369 pxa_set_cken(CKEN_PWM0, 0);
370 return 0; /* pointless return value */
371}
372
373static int mainstone_backlight_get_brightness(struct backlight_device *bl)
374{
375 return PWM_PWDUTY0;
376}
377 359
378static /*const*/ struct backlight_ops mainstone_backlight_ops = { 360static struct platform_device mainstone_backlight_device = {
379 .update_status = mainstone_backlight_update_status, 361 .name = "pwm-backlight",
380 .get_brightness = mainstone_backlight_get_brightness, 362 .dev = {
363 .parent = &pxa27x_device_pwm0.dev,
364 .platform_data = &mainstone_backlight_data,
365 },
381}; 366};
382 367
383static void __init mainstone_backlight_register(void) 368static void __init mainstone_backlight_register(void)
384{ 369{
385 struct backlight_device *bl; 370 int ret = platform_device_register(&mainstone_backlight_device);
386 371 if (ret)
387 bl = backlight_device_register("mainstone-bl", &pxa_device_fb.dev, 372 printk(KERN_ERR "mainstone: failed to register backlight device: %d\n", ret);
388 NULL, &mainstone_backlight_ops);
389 if (IS_ERR(bl)) {
390 printk(KERN_ERR "mainstone: unable to register backlight: %ld\n",
391 PTR_ERR(bl));
392 return;
393 }
394
395 /*
396 * broken design - register-then-setup interfaces are
397 * utterly broken by definition.
398 */
399 bl->props.max_brightness = 1023;
400 bl->props.brightness = 1023;
401 backlight_update_status(bl);
402} 373}
403#else 374#else
404#define mainstone_backlight_register() do { } while (0) 375#define mainstone_backlight_register() do { } while (0)
diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
index 49d951db0f3d..2564e16e4e2f 100644
--- a/arch/arm/mach-pxa/pcm990-baseboard.c
+++ b/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -24,6 +24,7 @@
24#include <linux/platform_device.h> 24#include <linux/platform_device.h>
25#include <linux/ide.h> 25#include <linux/ide.h>
26#include <linux/i2c.h> 26#include <linux/i2c.h>
27#include <linux/pwm_backlight.h>
27 28
28#include <media/soc_camera.h> 29#include <media/soc_camera.h>
29 30
@@ -36,9 +37,99 @@
36#include <asm/arch/mmc.h> 37#include <asm/arch/mmc.h>
37#include <asm/arch/ohci.h> 38#include <asm/arch/ohci.h>
38#include <asm/arch/pcm990_baseboard.h> 39#include <asm/arch/pcm990_baseboard.h>
40#include <asm/arch/pxafb.h>
41
42#include "devices.h"
43
44/*
45 * pcm990_lcd_power - control power supply to the LCD
46 * @on: 0 = switch off, 1 = switch on
47 *
48 * Called by the pxafb driver
49 */
50#ifndef CONFIG_PCM990_DISPLAY_NONE
51static void pcm990_lcd_power(int on, struct fb_var_screeninfo *var)
52{
53 if (on) {
54 /* enable LCD-Latches
55 * power on LCD
56 */
57 __PCM990_CTRL_REG(PCM990_CTRL_PHYS + PCM990_CTRL_REG3) =
58 PCM990_CTRL_LCDPWR + PCM990_CTRL_LCDON;
59 } else {
60 /* disable LCD-Latches
61 * power off LCD
62 */
63 __PCM990_CTRL_REG(PCM990_CTRL_PHYS + PCM990_CTRL_REG3) = 0x00;
64 }
65}
66#endif
67
68#if defined(CONFIG_PCM990_DISPLAY_SHARP)
69static struct pxafb_mode_info fb_info_sharp_lq084v1dg21 = {
70 .pixclock = 28000,
71 .xres = 640,
72 .yres = 480,
73 .bpp = 16,
74 .hsync_len = 20,
75 .left_margin = 103,
76 .right_margin = 47,
77 .vsync_len = 6,
78 .upper_margin = 28,
79 .lower_margin = 5,
80 .sync = 0,
81 .cmap_greyscale = 0,
82};
83
84static struct pxafb_mach_info pcm990_fbinfo __initdata = {
85 .modes = &fb_info_sharp_lq084v1dg21,
86 .num_modes = 1,
87 .lccr0 = LCCR0_PAS,
88 .lccr3 = LCCR3_PCP,
89 .pxafb_lcd_power = pcm990_lcd_power,
90};
91#elif defined(CONFIG_PCM990_DISPLAY_NEC)
92struct pxafb_mode_info fb_info_nec_nl6448bc20_18d = {
93 .pixclock = 39720,
94 .xres = 640,
95 .yres = 480,
96 .bpp = 16,
97 .hsync_len = 32,
98 .left_margin = 16,
99 .right_margin = 48,
100 .vsync_len = 2,
101 .upper_margin = 12,
102 .lower_margin = 17,
103 .sync = 0,
104 .cmap_greyscale = 0,
105};
106
107static struct pxafb_mach_info pcm990_fbinfo __initdata = {
108 .modes = &fb_info_nec_nl6448bc20_18d,
109 .num_modes = 1,
110 .lccr0 = LCCR0_Act,
111 .lccr3 = LCCR3_PixFlEdg,
112 .pxafb_lcd_power = pcm990_lcd_power,
113};
114#endif
115
116static struct platform_pwm_backlight_data pcm990_backlight_data = {
117 .pwm_id = 0,
118 .max_brightness = 1023,
119 .dft_brightness = 1023,
120 .pwm_period_ns = 78770,
121};
122
123static struct platform_device pcm990_backlight_device = {
124 .name = "pwm-backlight",
125 .dev = {
126 .parent = &pxa27x_device_pwm0.dev,
127 .platform_data = &pcm990_backlight_data,
128 },
129};
39 130
40/* 131/*
41 * The PCM-990 development baseboard uses PCM-027's hardeware in the 132 * The PCM-990 development baseboard uses PCM-027's hardware in the
42 * following way: 133 * following way:
43 * 134 *
44 * - LCD support is in use 135 * - LCD support is in use
@@ -393,6 +484,12 @@ void __init pcm990_baseboard_init(void)
393 /* register CPLD's IRQ controller */ 484 /* register CPLD's IRQ controller */
394 pcm990_init_irq(); 485 pcm990_init_irq();
395 486
487#ifndef CONFIG_PCM990_DISPLAY_NONE
488 set_pxa_fb_info(&pcm990_fbinfo);
489#endif
490 pxa_gpio_mode(GPIO16_PWM0_MD);
491 platform_device_register(&pcm990_backlight_device);
492
396 platform_device_register(&pxa27x_device_ac97); 493 platform_device_register(&pxa27x_device_ac97);
397 494
398 /* MMC */ 495 /* MMC */
diff --git a/arch/arm/mach-pxa/pwm.c b/arch/arm/mach-pxa/pwm.c
new file mode 100644
index 000000000000..ce28cd9fed16
--- /dev/null
+++ b/arch/arm/mach-pxa/pwm.c
@@ -0,0 +1,319 @@
1/*
2 * linux/arch/arm/mach-pxa/pwm.c
3 *
4 * simple driver for PWM (Pulse Width Modulator) controller
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * 2008-02-13 initial version
11 * eric miao <eric.miao@marvell.com>
12 */
13
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/platform_device.h>
17#include <linux/err.h>
18#include <linux/clk.h>
19#include <linux/io.h>
20#include <linux/pwm.h>
21
22#include <asm/div64.h>
23#include <asm/arch/pxa-regs.h>
24
25/* PWM registers and bits definitions */
26#define PWMCR (0x00)
27#define PWMDCR (0x04)
28#define PWMPCR (0x08)
29
30#define PWMCR_SD (1 << 6)
31#define PWMDCR_FD (1 << 10)
32
33struct pwm_device {
34 struct list_head node;
35 struct platform_device *pdev;
36
37 const char *label;
38 struct clk *clk;
39 int clk_enabled;
40 void __iomem *mmio_base;
41
42 unsigned int use_count;
43 unsigned int pwm_id;
44};
45
46/*
47 * period_ns = 10^9 * (PRESCALE + 1) * (PV + 1) / PWM_CLK_RATE
48 * duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE
49 */
50int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
51{
52 unsigned long long c;
53 unsigned long period_cycles, prescale, pv, dc;
54
55 if (pwm == NULL || period_ns == 0 || duty_ns > period_ns)
56 return -EINVAL;
57
58 c = clk_get_rate(pwm->clk);
59 c = c * period_ns;
60 do_div(c, 1000000000);
61 period_cycles = c;
62
63 if (period_cycles < 0)
64 period_cycles = 1;
65 prescale = (period_cycles - 1) / 1024;
66 pv = period_cycles / (prescale + 1) - 1;
67
68 if (prescale > 63)
69 return -EINVAL;
70
71 if (duty_ns == period_ns)
72 dc = PWMDCR_FD;
73 else
74 dc = (pv + 1) * duty_ns / period_ns;
75
76 /* NOTE: the clock to PWM has to be enabled first
77 * before writing to the registers
78 */
79 clk_enable(pwm->clk);
80 __raw_writel(prescale, pwm->mmio_base + PWMCR);
81 __raw_writel(dc, pwm->mmio_base + PWMDCR);
82 __raw_writel(pv, pwm->mmio_base + PWMPCR);
83 clk_disable(pwm->clk);
84
85 return 0;
86}
87EXPORT_SYMBOL(pwm_config);
88
89int pwm_enable(struct pwm_device *pwm)
90{
91 int rc = 0;
92
93 if (!pwm->clk_enabled) {
94 rc = clk_enable(pwm->clk);
95 if (!rc)
96 pwm->clk_enabled = 1;
97 }
98 return rc;
99}
100EXPORT_SYMBOL(pwm_enable);
101
102void pwm_disable(struct pwm_device *pwm)
103{
104 if (pwm->clk_enabled) {
105 clk_disable(pwm->clk);
106 pwm->clk_enabled = 0;
107 }
108}
109EXPORT_SYMBOL(pwm_disable);
110
111static DEFINE_MUTEX(pwm_lock);
112static LIST_HEAD(pwm_list);
113
114struct pwm_device *pwm_request(int pwm_id, const char *label)
115{
116 struct pwm_device *pwm;
117 int found = 0;
118
119 mutex_lock(&pwm_lock);
120
121 list_for_each_entry(pwm, &pwm_list, node) {
122 if (pwm->pwm_id == pwm_id) {
123 found = 1;
124 break;
125 }
126 }
127
128 if (found) {
129 if (pwm->use_count == 0) {
130 pwm->use_count++;
131 pwm->label = label;
132 } else
133 pwm = ERR_PTR(-EBUSY);
134 } else
135 pwm = ERR_PTR(-ENOENT);
136
137 mutex_unlock(&pwm_lock);
138 return pwm;
139}
140EXPORT_SYMBOL(pwm_request);
141
142void pwm_free(struct pwm_device *pwm)
143{
144 mutex_lock(&pwm_lock);
145
146 if (pwm->use_count) {
147 pwm->use_count--;
148 pwm->label = NULL;
149 } else
150 pr_warning("PWM device already freed\n");
151
152 mutex_unlock(&pwm_lock);
153}
154EXPORT_SYMBOL(pwm_free);
155
156static inline void __add_pwm(struct pwm_device *pwm)
157{
158 mutex_lock(&pwm_lock);
159 list_add_tail(&pwm->node, &pwm_list);
160 mutex_unlock(&pwm_lock);
161}
162
163static struct pwm_device *pwm_probe(struct platform_device *pdev,
164 unsigned int pwm_id, struct pwm_device *parent_pwm)
165{
166 struct pwm_device *pwm;
167 struct resource *r;
168 int ret = 0;
169
170 pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
171 if (pwm == NULL) {
172 dev_err(&pdev->dev, "failed to allocate memory\n");
173 return ERR_PTR(-ENOMEM);
174 }
175
176 pwm->clk = clk_get(&pdev->dev, "PWMCLK");
177 if (IS_ERR(pwm->clk)) {
178 ret = PTR_ERR(pwm->clk);
179 goto err_free;
180 }
181 pwm->clk_enabled = 0;
182
183 pwm->use_count = 0;
184 pwm->pwm_id = pwm_id;
185 pwm->pdev = pdev;
186
187 if (parent_pwm != NULL) {
188 /* registers for the second PWM has offset of 0x10 */
189 pwm->mmio_base = parent_pwm->mmio_base + 0x10;
190 __add_pwm(pwm);
191 return pwm;
192 }
193
194 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
195 if (r == NULL) {
196 dev_err(&pdev->dev, "no memory resource defined\n");
197 ret = -ENODEV;
198 goto err_free_clk;
199 }
200
201 r = request_mem_region(r->start, r->end - r->start + 1, pdev->name);
202 if (r == NULL) {
203 dev_err(&pdev->dev, "failed to request memory resource\n");
204 ret = -EBUSY;
205 goto err_free_clk;
206 }
207
208 pwm->mmio_base = ioremap(r->start, r->end - r->start + 1);
209 if (pwm->mmio_base == NULL) {
210 dev_err(&pdev->dev, "failed to ioremap() registers\n");
211 ret = -ENODEV;
212 goto err_free_mem;
213 }
214
215 __add_pwm(pwm);
216 platform_set_drvdata(pdev, pwm);
217 return pwm;
218
219err_free_mem:
220 release_mem_region(r->start, r->end - r->start + 1);
221err_free_clk:
222 clk_put(pwm->clk);
223err_free:
224 kfree(pwm);
225 return ERR_PTR(ret);
226}
227
228static int __devinit pxa25x_pwm_probe(struct platform_device *pdev)
229{
230 struct pwm_device *pwm = pwm_probe(pdev, pdev->id, NULL);
231
232 if (IS_ERR(pwm))
233 return PTR_ERR(pwm);
234
235 return 0;
236}
237
238static int __devinit pxa27x_pwm_probe(struct platform_device *pdev)
239{
240 struct pwm_device *pwm;
241
242 pwm = pwm_probe(pdev, pdev->id, NULL);
243 if (IS_ERR(pwm))
244 return PTR_ERR(pwm);
245
246 pwm = pwm_probe(pdev, pdev->id + 2, pwm);
247 if (IS_ERR(pwm))
248 return PTR_ERR(pwm);
249
250 return 0;
251}
252
253static int __devexit pwm_remove(struct platform_device *pdev)
254{
255 struct pwm_device *pwm;
256 struct resource *r;
257
258 pwm = platform_get_drvdata(pdev);
259 if (pwm == NULL)
260 return -ENODEV;
261
262 mutex_lock(&pwm_lock);
263 list_del(&pwm->node);
264 mutex_unlock(&pwm_lock);
265
266 iounmap(pwm->mmio_base);
267
268 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
269 release_mem_region(r->start, r->end - r->start + 1);
270
271 clk_put(pwm->clk);
272 kfree(pwm);
273 return 0;
274}
275
276static struct platform_driver pxa25x_pwm_driver = {
277 .driver = {
278 .name = "pxa25x-pwm",
279 },
280 .probe = pxa25x_pwm_probe,
281 .remove = __devexit_p(pwm_remove),
282};
283
284static struct platform_driver pxa27x_pwm_driver = {
285 .driver = {
286 .name = "pxa27x-pwm",
287 },
288 .probe = pxa27x_pwm_probe,
289 .remove = __devexit_p(pwm_remove),
290};
291
292static int __init pwm_init(void)
293{
294 int ret = 0;
295
296 ret = platform_driver_register(&pxa25x_pwm_driver);
297 if (ret) {
298 printk(KERN_ERR "failed to register pxa25x_pwm_driver\n");
299 return ret;
300 }
301
302 ret = platform_driver_register(&pxa27x_pwm_driver);
303 if (ret) {
304 printk(KERN_ERR "failed to register pxa27x_pwm_driver\n");
305 return ret;
306 }
307
308 return ret;
309}
310arch_initcall(pwm_init);
311
312static void __exit pwm_exit(void)
313{
314 platform_driver_unregister(&pxa25x_pwm_driver);
315 platform_driver_unregister(&pxa27x_pwm_driver);
316}
317module_exit(pwm_exit);
318
319MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index 3b848dc3ca11..a1a7dd23ce5a 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -118,6 +118,10 @@ static struct clk pxa25x_hwuart_clk =
118 INIT_CKEN("UARTCLK", HWUART, 14745600, 1, &pxa_device_hwuart.dev) 118 INIT_CKEN("UARTCLK", HWUART, 14745600, 1, &pxa_device_hwuart.dev)
119; 119;
120 120
121/*
122 * PXA 2xx clock declarations. Order is important (see aliases below)
123 * Please be careful not to disrupt the ordering.
124 */
121static struct clk pxa25x_clks[] = { 125static struct clk pxa25x_clks[] = {
122 INIT_CK("LCDCLK", LCD, &clk_pxa25x_lcd_ops, &pxa_device_fb.dev), 126 INIT_CK("LCDCLK", LCD, &clk_pxa25x_lcd_ops, &pxa_device_fb.dev),
123 INIT_CKEN("UARTCLK", FFUART, 14745600, 1, &pxa_device_ffuart.dev), 127 INIT_CKEN("UARTCLK", FFUART, 14745600, 1, &pxa_device_ffuart.dev),
@@ -130,17 +134,19 @@ static struct clk pxa25x_clks[] = {
130 INIT_CKEN("SSPCLK", SSP, 3686400, 0, &pxa25x_device_ssp.dev), 134 INIT_CKEN("SSPCLK", SSP, 3686400, 0, &pxa25x_device_ssp.dev),
131 INIT_CKEN("SSPCLK", NSSP, 3686400, 0, &pxa25x_device_nssp.dev), 135 INIT_CKEN("SSPCLK", NSSP, 3686400, 0, &pxa25x_device_nssp.dev),
132 INIT_CKEN("SSPCLK", ASSP, 3686400, 0, &pxa25x_device_assp.dev), 136 INIT_CKEN("SSPCLK", ASSP, 3686400, 0, &pxa25x_device_assp.dev),
137 INIT_CKEN("PWMCLK", PWM0, 3686400, 0, &pxa25x_device_pwm0.dev),
138 INIT_CKEN("PWMCLK", PWM1, 3686400, 0, &pxa25x_device_pwm1.dev),
133 139
134 INIT_CKEN("AC97CLK", AC97, 24576000, 0, NULL), 140 INIT_CKEN("AC97CLK", AC97, 24576000, 0, NULL),
135 141
136 /* 142 /*
137 INIT_CKEN("PWMCLK", PWM0, 3686400, 0, NULL),
138 INIT_CKEN("PWMCLK", PWM0, 3686400, 0, NULL),
139 INIT_CKEN("I2SCLK", I2S, 14745600, 0, NULL), 143 INIT_CKEN("I2SCLK", I2S, 14745600, 0, NULL),
140 */ 144 */
141 INIT_CKEN("FICPCLK", FICP, 47923000, 0, NULL), 145 INIT_CKEN("FICPCLK", FICP, 47923000, 0, NULL),
142}; 146};
143 147
148static struct clk gpio7_clk = INIT_CKOTHER("GPIO7_CK", &pxa25x_clks[4], NULL);
149
144#ifdef CONFIG_PM 150#ifdef CONFIG_PM
145 151
146#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x 152#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
@@ -270,6 +276,8 @@ static struct platform_device *pxa25x_devices[] __initdata = {
270 &pxa25x_device_ssp, 276 &pxa25x_device_ssp,
271 &pxa25x_device_nssp, 277 &pxa25x_device_nssp,
272 &pxa25x_device_assp, 278 &pxa25x_device_assp,
279 &pxa25x_device_pwm0,
280 &pxa25x_device_pwm1,
273}; 281};
274 282
275static struct sys_device pxa25x_sysdev[] = { 283static struct sys_device pxa25x_sysdev[] = {
@@ -312,6 +320,8 @@ static int __init pxa25x_init(void)
312 if (cpu_is_pxa25x()) 320 if (cpu_is_pxa25x())
313 ret = platform_device_register(&pxa_device_hwuart); 321 ret = platform_device_register(&pxa_device_hwuart);
314 322
323 clks_register(&gpio7_clk, 1);
324
315 return ret; 325 return ret;
316} 326}
317 327
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 48cbdc771a80..4d7afae352a1 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -157,12 +157,13 @@ static struct clk pxa27x_clks[] = {
157 INIT_CKEN("SSPCLK", SSP1, 13000000, 0, &pxa27x_device_ssp1.dev), 157 INIT_CKEN("SSPCLK", SSP1, 13000000, 0, &pxa27x_device_ssp1.dev),
158 INIT_CKEN("SSPCLK", SSP2, 13000000, 0, &pxa27x_device_ssp2.dev), 158 INIT_CKEN("SSPCLK", SSP2, 13000000, 0, &pxa27x_device_ssp2.dev),
159 INIT_CKEN("SSPCLK", SSP3, 13000000, 0, &pxa27x_device_ssp3.dev), 159 INIT_CKEN("SSPCLK", SSP3, 13000000, 0, &pxa27x_device_ssp3.dev),
160 INIT_CKEN("PWMCLK", PWM0, 13000000, 0, &pxa27x_device_pwm0.dev),
161 INIT_CKEN("PWMCLK", PWM1, 13000000, 0, &pxa27x_device_pwm1.dev),
160 162
161 INIT_CKEN("AC97CLK", AC97, 24576000, 0, NULL), 163 INIT_CKEN("AC97CLK", AC97, 24576000, 0, NULL),
162 INIT_CKEN("AC97CONFCLK", AC97CONF, 24576000, 0, NULL), 164 INIT_CKEN("AC97CONFCLK", AC97CONF, 24576000, 0, NULL),
163 165
164 /* 166 /*
165 INIT_CKEN("PWMCLK", PWM0, 13000000, 0, NULL),
166 INIT_CKEN("MSLCLK", MSL, 48000000, 0, NULL), 167 INIT_CKEN("MSLCLK", MSL, 48000000, 0, NULL),
167 INIT_CKEN("USIMCLK", USIM, 48000000, 0, NULL), 168 INIT_CKEN("USIMCLK", USIM, 48000000, 0, NULL),
168 INIT_CKEN("MSTKCLK", MEMSTK, 19500000, 0, NULL), 169 INIT_CKEN("MSTKCLK", MEMSTK, 19500000, 0, NULL),
@@ -366,6 +367,8 @@ static struct platform_device *devices[] __initdata = {
366 &pxa27x_device_ssp1, 367 &pxa27x_device_ssp1,
367 &pxa27x_device_ssp2, 368 &pxa27x_device_ssp2,
368 &pxa27x_device_ssp3, 369 &pxa27x_device_ssp3,
370 &pxa27x_device_pwm0,
371 &pxa27x_device_pwm1,
369}; 372};
370 373
371static struct sys_device pxa27x_sysdev[] = { 374static struct sys_device pxa27x_sysdev[] = {
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 7fbe78649dad..d26a9b02a559 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -239,6 +239,8 @@ static struct clk pxa3xx_clks[] = {
239 PXA3xx_CKEN("SSPCLK", SSP2, 13000000, 0, &pxa27x_device_ssp2.dev), 239 PXA3xx_CKEN("SSPCLK", SSP2, 13000000, 0, &pxa27x_device_ssp2.dev),
240 PXA3xx_CKEN("SSPCLK", SSP3, 13000000, 0, &pxa27x_device_ssp3.dev), 240 PXA3xx_CKEN("SSPCLK", SSP3, 13000000, 0, &pxa27x_device_ssp3.dev),
241 PXA3xx_CKEN("SSPCLK", SSP4, 13000000, 0, &pxa3xx_device_ssp4.dev), 241 PXA3xx_CKEN("SSPCLK", SSP4, 13000000, 0, &pxa3xx_device_ssp4.dev),
242 PXA3xx_CKEN("PWMCLK", PWM0, 13000000, 0, &pxa27x_device_pwm0.dev),
243 PXA3xx_CKEN("PWMCLK", PWM1, 13000000, 0, &pxa27x_device_pwm1.dev),
242 244
243 PXA3xx_CKEN("MMCCLK", MMC1, 19500000, 0, &pxa_device_mci.dev), 245 PXA3xx_CKEN("MMCCLK", MMC1, 19500000, 0, &pxa_device_mci.dev),
244 PXA3xx_CKEN("MMCCLK", MMC2, 19500000, 0, &pxa3xx_device_mci2.dev), 246 PXA3xx_CKEN("MMCCLK", MMC2, 19500000, 0, &pxa3xx_device_mci2.dev),
@@ -530,6 +532,8 @@ static struct platform_device *devices[] __initdata = {
530 &pxa27x_device_ssp2, 532 &pxa27x_device_ssp2,
531 &pxa27x_device_ssp3, 533 &pxa27x_device_ssp3,
532 &pxa3xx_device_ssp4, 534 &pxa3xx_device_ssp4,
535 &pxa27x_device_pwm0,
536 &pxa27x_device_pwm1,
533}; 537};
534 538
535static struct sys_device pxa3xx_sysdev[] = { 539static struct sys_device pxa3xx_sysdev[] = {
diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
index 4a0028087ea6..b13bb9385138 100644
--- a/arch/arm/mach-pxa/zylonite.c
+++ b/arch/arm/mach-pxa/zylonite.c
@@ -18,6 +18,7 @@
18#include <linux/interrupt.h> 18#include <linux/interrupt.h>
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/pwm_backlight.h>
21 22
22#include <asm/mach-types.h> 23#include <asm/mach-types.h>
23#include <asm/mach/arch.h> 24#include <asm/mach/arch.h>
@@ -28,12 +29,12 @@
28#include <asm/arch/mmc.h> 29#include <asm/arch/mmc.h>
29#include <asm/arch/pxa27x_keypad.h> 30#include <asm/arch/pxa27x_keypad.h>
30 31
32#include "devices.h"
31#include "generic.h" 33#include "generic.h"
32 34
33#define MAX_SLOTS 3 35#define MAX_SLOTS 3
34struct platform_mmc_slot zylonite_mmc_slot[MAX_SLOTS]; 36struct platform_mmc_slot zylonite_mmc_slot[MAX_SLOTS];
35 37
36int gpio_backlight;
37int gpio_eth_irq; 38int gpio_eth_irq;
38 39
39int wm9713_irq; 40int wm9713_irq;
@@ -62,10 +63,20 @@ static struct platform_device smc91x_device = {
62}; 63};
63 64
64#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE) 65#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
65static void zylonite_backlight_power(int on) 66static struct platform_pwm_backlight_data zylonite_backlight_data = {
66{ 67 .pwm_id = 3,
67 gpio_set_value(gpio_backlight, on); 68 .max_brightness = 100,
68} 69 .dft_brightness = 100,
70 .pwm_period_ns = 10000,
71};
72
73static struct platform_device zylonite_backlight_device = {
74 .name = "pwm-backlight",
75 .dev = {
76 .parent = &pxa27x_device_pwm1.dev,
77 .platform_data = &zylonite_backlight_data,
78 },
79};
69 80
70static struct pxafb_mode_info toshiba_ltm035a776c_mode = { 81static struct pxafb_mode_info toshiba_ltm035a776c_mode = {
71 .pixclock = 110000, 82 .pixclock = 110000,
@@ -98,7 +109,6 @@ static struct pxafb_mode_info toshiba_ltm04c380k_mode = {
98static struct pxafb_mach_info zylonite_toshiba_lcd_info = { 109static struct pxafb_mach_info zylonite_toshiba_lcd_info = {
99 .num_modes = 1, 110 .num_modes = 1,
100 .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL, 111 .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
101 .pxafb_backlight_power = zylonite_backlight_power,
102}; 112};
103 113
104static struct pxafb_mode_info sharp_ls037_modes[] = { 114static struct pxafb_mode_info sharp_ls037_modes[] = {
@@ -134,13 +144,11 @@ static struct pxafb_mach_info zylonite_sharp_lcd_info = {
134 .modes = sharp_ls037_modes, 144 .modes = sharp_ls037_modes,
135 .num_modes = 2, 145 .num_modes = 2,
136 .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL, 146 .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
137 .pxafb_backlight_power = zylonite_backlight_power,
138}; 147};
139 148
140static void __init zylonite_init_lcd(void) 149static void __init zylonite_init_lcd(void)
141{ 150{
142 /* backlight GPIO: output, default on */ 151 platform_device_register(&zylonite_backlight_device);
143 gpio_direction_output(gpio_backlight, 1);
144 152
145 if (lcd_id & 0x20) { 153 if (lcd_id & 0x20) {
146 set_pxa_fb_info(&zylonite_sharp_lcd_info); 154 set_pxa_fb_info(&zylonite_sharp_lcd_info);
diff --git a/arch/arm/mach-pxa/zylonite_pxa300.c b/arch/arm/mach-pxa/zylonite_pxa300.c
index 324fb9daae28..6f7ae972b8db 100644
--- a/arch/arm/mach-pxa/zylonite_pxa300.c
+++ b/arch/arm/mach-pxa/zylonite_pxa300.c
@@ -50,6 +50,7 @@ static mfp_cfg_t common_mfp_cfg[] __initdata = {
50 GPIO75_LCD_BIAS, 50 GPIO75_LCD_BIAS,
51 GPIO76_LCD_VSYNC, 51 GPIO76_LCD_VSYNC,
52 GPIO127_LCD_CS_N, 52 GPIO127_LCD_CS_N,
53 GPIO20_PWM3_OUT, /* backlight */
53 54
54 /* BTUART */ 55 /* BTUART */
55 GPIO111_UART2_RTS, 56 GPIO111_UART2_RTS,
@@ -200,9 +201,6 @@ void __init zylonite_pxa300_init(void)
200 /* detect LCD panel */ 201 /* detect LCD panel */
201 zylonite_detect_lcd_panel(); 202 zylonite_detect_lcd_panel();
202 203
203 /* GPIO pin assignment */
204 gpio_backlight = mfp_to_gpio(MFP_PIN_GPIO20);
205
206 /* MMC card detect & write protect for controller 0 */ 204 /* MMC card detect & write protect for controller 0 */
207 zylonite_mmc_slot[0].gpio_cd = EXT_GPIO(0); 205 zylonite_mmc_slot[0].gpio_cd = EXT_GPIO(0);
208 zylonite_mmc_slot[0].gpio_wp = EXT_GPIO(2); 206 zylonite_mmc_slot[0].gpio_wp = EXT_GPIO(2);
diff --git a/arch/arm/mach-pxa/zylonite_pxa320.c b/arch/arm/mach-pxa/zylonite_pxa320.c
index 193d07903b06..2b4fc34919ac 100644
--- a/arch/arm/mach-pxa/zylonite_pxa320.c
+++ b/arch/arm/mach-pxa/zylonite_pxa320.c
@@ -49,6 +49,7 @@ static mfp_cfg_t mfp_cfg[] __initdata = {
49 GPIO15_2_LCD_LCLK, 49 GPIO15_2_LCD_LCLK,
50 GPIO16_2_LCD_PCLK, 50 GPIO16_2_LCD_PCLK,
51 GPIO17_2_LCD_BIAS, 51 GPIO17_2_LCD_BIAS,
52 GPIO14_PWM3_OUT, /* backlight */
52 53
53 /* FFUART */ 54 /* FFUART */
54 GPIO41_UART1_RXD | MFP_LPM_EDGE_FALL, 55 GPIO41_UART1_RXD | MFP_LPM_EDGE_FALL,
@@ -187,7 +188,6 @@ void __init zylonite_pxa320_init(void)
187 zylonite_detect_lcd_panel(); 188 zylonite_detect_lcd_panel();
188 189
189 /* GPIO pin assignment */ 190 /* GPIO pin assignment */
190 gpio_backlight = mfp_to_gpio(MFP_PIN_GPIO14);
191 gpio_eth_irq = mfp_to_gpio(MFP_PIN_GPIO9); 191 gpio_eth_irq = mfp_to_gpio(MFP_PIN_GPIO9);
192 192
193 /* MMC card detect & write protect for controller 0 */ 193 /* MMC card detect & write protect for controller 0 */