diff options
Diffstat (limited to 'arch/arm/mach-pxa')
-rw-r--r-- | arch/arm/mach-pxa/Kconfig | 25 | ||||
-rw-r--r-- | arch/arm/mach-pxa/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-pxa/clock.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-pxa/clock.h | 12 | ||||
-rw-r--r-- | arch/arm/mach-pxa/devices.c | 60 | ||||
-rw-r--r-- | arch/arm/mach-pxa/devices.h | 5 | ||||
-rw-r--r-- | arch/arm/mach-pxa/irq.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-pxa/lpd270.c | 38 | ||||
-rw-r--r-- | arch/arm/mach-pxa/magician.c | 68 | ||||
-rw-r--r-- | arch/arm/mach-pxa/mainstone.c | 63 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pcm990-baseboard.c | 99 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pwm.c | 319 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa25x.c | 14 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa27x.c | 5 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa3xx.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-pxa/zylonite.c | 26 | ||||
-rw-r--r-- | arch/arm/mach-pxa/zylonite_pxa300.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-pxa/zylonite_pxa320.c | 2 |
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 | |||
36 | config MACH_LOGICPD_PXA270 | 36 | config 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 | ||
40 | config MACH_MAINSTONE | 41 | config 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 | ||
44 | config ARCH_PXA_IDP | 46 | config ARCH_PXA_IDP |
45 | bool "Accelent Xscale IDP" | 47 | bool "Accelent Xscale IDP" |
@@ -115,6 +117,7 @@ config MACH_COLIBRI | |||
115 | config MACH_ZYLONITE | 117 | config MACH_ZYLONITE |
116 | bool "PXA3xx Development Platform" | 118 | bool "PXA3xx Development Platform" |
117 | select PXA3xx | 119 | select PXA3xx |
120 | select HAVE_PWM | ||
118 | 121 | ||
119 | config MACH_LITTLETON | 122 | config 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 | ||
146 | config MACH_PCM990_BASEBOARD | 149 | config MACH_PCM990_BASEBOARD |
147 | bool "PHYTEC PCM-990 development board" | 150 | bool "PHYTEC PCM-990 development board" |
151 | select HAVE_PWM | ||
152 | |||
153 | endchoice | ||
154 | |||
155 | choice | ||
156 | prompt "display on pcm990" | ||
157 | depends on MACH_PCM990_BASEBOARD | ||
158 | |||
159 | config PCM990_DISPLAY_SHARP | ||
160 | bool "sharp lq084v1dg21 stn display" | ||
161 | |||
162 | config PCM990_DISPLAY_NEC | ||
163 | bool "nec nl6448bc20_18d tft display" | ||
164 | |||
165 | config PCM990_DISPLAY_NONE | ||
166 | bool "no display" | ||
148 | 167 | ||
149 | endchoice | 168 | endchoice |
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 | |||
286 | config PXA_PWM | ||
287 | tristate | ||
288 | default BACKLIGHT_PWM | ||
289 | help | ||
290 | Enable support for PXA2xx/PXA3xx PWM controllers | ||
266 | endif | 291 | endif |
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 |
12 | obj-$(CONFIG_PXA_SSP) += ssp.o | 12 | obj-$(CONFIG_PXA_SSP) += ssp.o |
13 | obj-$(CONFIG_PXA_PWM) += pwm.o | ||
13 | 14 | ||
14 | # SoC-specific code | 15 | # SoC-specific code |
15 | obj-$(CONFIG_PXA25x) += mfp-pxa2xx.o pxa25x.o | 16 | obj-$(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 | } |
52 | EXPORT_SYMBOL(clk_get); | 55 | EXPORT_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 | |||
38 | extern const struct clkops clk_cken_ops; | 50 | extern const struct clkops clk_cken_ops; |
39 | 51 | ||
40 | void clk_cken_enable(struct clk *clk); | 52 | void 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 | ||
292 | static struct resource pxa25x_resource_pwm0[] = { | ||
293 | [0] = { | ||
294 | .start = 0x40b00000, | ||
295 | .end = 0x40b0000f, | ||
296 | .flags = IORESOURCE_MEM, | ||
297 | }, | ||
298 | }; | ||
299 | |||
300 | struct 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 | |||
307 | static struct resource pxa25x_resource_pwm1[] = { | ||
308 | [0] = { | ||
309 | .start = 0x40c00000, | ||
310 | .end = 0x40c0000f, | ||
311 | .flags = IORESOURCE_MEM, | ||
312 | }, | ||
313 | }; | ||
314 | |||
315 | struct 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 | |||
292 | static u64 pxa25x_ssp_dma_mask = DMA_BIT_MASK(32); | 322 | static u64 pxa25x_ssp_dma_mask = DMA_BIT_MASK(32); |
293 | 323 | ||
294 | static struct resource pxa25x_resource_ssp[] = { | 324 | static 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 | ||
610 | static struct resource pxa27x_resource_pwm0[] = { | ||
611 | [0] = { | ||
612 | .start = 0x40b00000, | ||
613 | .end = 0x40b0001f, | ||
614 | .flags = IORESOURCE_MEM, | ||
615 | }, | ||
616 | }; | ||
617 | |||
618 | struct 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 | |||
625 | static struct resource pxa27x_resource_pwm1[] = { | ||
626 | [0] = { | ||
627 | .start = 0x40c00000, | ||
628 | .end = 0x40c0001f, | ||
629 | .flags = IORESOURCE_MEM, | ||
630 | }, | ||
631 | }; | ||
632 | |||
633 | struct 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 | |||
580 | static struct resource pxa27x_resource_camera[] = { | 640 | static 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; | |||
24 | extern struct platform_device pxa27x_device_ssp3; | 24 | extern struct platform_device pxa27x_device_ssp3; |
25 | extern struct platform_device pxa3xx_device_ssp4; | 25 | extern struct platform_device pxa3xx_device_ssp4; |
26 | 26 | ||
27 | extern struct platform_device pxa25x_device_pwm0; | ||
28 | extern struct platform_device pxa25x_device_pwm1; | ||
29 | extern struct platform_device pxa27x_device_pwm0; | ||
30 | extern struct platform_device pxa27x_device_pwm1; | ||
31 | |||
27 | void __init pxa_register_device(struct platform_device *dev, void *data); | 32 | void __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 | ||
239 | static void lpd270_backlight_power(int on) | 240 | static 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; | 247 | static 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) */ |
256 | static struct pxafb_mode_info sharp_lq057q3dc02_mode = { | 256 | static 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 | ||
393 | static struct pxafb_mach_info *lpd270_lcd_to_use; | 387 | static struct pxafb_mach_info *lpd270_lcd_to_use; |
@@ -417,6 +411,7 @@ __setup("lcd=", lpd270_set_lcd); | |||
417 | 411 | ||
418 | static struct platform_device *platform_devices[] __initdata = { | 412 | static 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 | ||
45 | static unsigned long magician_pin_config[] = { | 47 | static unsigned long magician_pin_config[] = { |
@@ -349,40 +351,58 @@ static struct pxafb_mach_info samsung_info = { | |||
349 | * Backlight | 351 | * Backlight |
350 | */ | 352 | */ |
351 | 353 | ||
352 | static void magician_set_bl_intensity(int intensity) | 354 | static 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); | 366 | err2: |
365 | pxa_set_cken(CKEN_PWM0, 1); | 367 | gpio_free(EGPIO_MAGICIAN_BL_POWER); |
368 | err: | ||
369 | return ret; | ||
370 | } | ||
371 | |||
372 | static 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 | ||
373 | static struct generic_bl_info backlight_info = { | 384 | static 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 | |||
390 | static 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 | ||
380 | static struct platform_device backlight = { | 400 | static 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) |
353 | static int mainstone_backlight_update_status(struct backlight_device *bl) | 353 | static 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 | |||
373 | static int mainstone_backlight_get_brightness(struct backlight_device *bl) | ||
374 | { | ||
375 | return PWM_PWDUTY0; | ||
376 | } | ||
377 | 359 | ||
378 | static /*const*/ struct backlight_ops mainstone_backlight_ops = { | 360 | static 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 | ||
383 | static void __init mainstone_backlight_register(void) | 368 | static 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 | ||
51 | static 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) | ||
69 | static 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 | |||
84 | static 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) | ||
92 | struct 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 | |||
107 | static 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 | |||
116 | static 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 | |||
123 | static 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 | |||
33 | struct 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 | */ | ||
50 | int 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 | } | ||
87 | EXPORT_SYMBOL(pwm_config); | ||
88 | |||
89 | int 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 | } | ||
100 | EXPORT_SYMBOL(pwm_enable); | ||
101 | |||
102 | void pwm_disable(struct pwm_device *pwm) | ||
103 | { | ||
104 | if (pwm->clk_enabled) { | ||
105 | clk_disable(pwm->clk); | ||
106 | pwm->clk_enabled = 0; | ||
107 | } | ||
108 | } | ||
109 | EXPORT_SYMBOL(pwm_disable); | ||
110 | |||
111 | static DEFINE_MUTEX(pwm_lock); | ||
112 | static LIST_HEAD(pwm_list); | ||
113 | |||
114 | struct 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 | } | ||
140 | EXPORT_SYMBOL(pwm_request); | ||
141 | |||
142 | void 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 | } | ||
154 | EXPORT_SYMBOL(pwm_free); | ||
155 | |||
156 | static 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 | |||
163 | static 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 | |||
219 | err_free_mem: | ||
220 | release_mem_region(r->start, r->end - r->start + 1); | ||
221 | err_free_clk: | ||
222 | clk_put(pwm->clk); | ||
223 | err_free: | ||
224 | kfree(pwm); | ||
225 | return ERR_PTR(ret); | ||
226 | } | ||
227 | |||
228 | static 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 | |||
238 | static 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 | |||
253 | static 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 | |||
276 | static 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 | |||
284 | static 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 | |||
292 | static 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 | } | ||
310 | arch_initcall(pwm_init); | ||
311 | |||
312 | static void __exit pwm_exit(void) | ||
313 | { | ||
314 | platform_driver_unregister(&pxa25x_pwm_driver); | ||
315 | platform_driver_unregister(&pxa27x_pwm_driver); | ||
316 | } | ||
317 | module_exit(pwm_exit); | ||
318 | |||
319 | MODULE_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 | */ | ||
121 | static struct clk pxa25x_clks[] = { | 125 | static 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 | ||
148 | static 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 | ||
275 | static struct sys_device pxa25x_sysdev[] = { | 283 | static 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 | ||
371 | static struct sys_device pxa27x_sysdev[] = { | 374 | static 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 | ||
535 | static struct sys_device pxa3xx_sysdev[] = { | 539 | static 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 |
34 | struct platform_mmc_slot zylonite_mmc_slot[MAX_SLOTS]; | 36 | struct platform_mmc_slot zylonite_mmc_slot[MAX_SLOTS]; |
35 | 37 | ||
36 | int gpio_backlight; | ||
37 | int gpio_eth_irq; | 38 | int gpio_eth_irq; |
38 | 39 | ||
39 | int wm9713_irq; | 40 | int 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) |
65 | static void zylonite_backlight_power(int on) | 66 | static 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 | |||
73 | static 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 | ||
70 | static struct pxafb_mode_info toshiba_ltm035a776c_mode = { | 81 | static 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 = { | |||
98 | static struct pxafb_mach_info zylonite_toshiba_lcd_info = { | 109 | static 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 | ||
104 | static struct pxafb_mode_info sharp_ls037_modes[] = { | 114 | static 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 | ||
140 | static void __init zylonite_init_lcd(void) | 149 | static 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 */ |