backlight: Convert corgi backlight driver into a more generic driver
[linux-2.6.git] / arch / arm / mach-pxa / corgi.c
1 /*
2  * Support for Sharp SL-C7xx PDAs
3  * Models: SL-C700 (Corgi), SL-C750 (Shepherd), SL-C760 (Husky)
4  *
5  * Copyright (c) 2004-2005 Richard Purdie
6  *
7  * Based on Sharp's 2.4 kernel patches/lubbock.c
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  *
13  */
14
15 #include <linux/kernel.h>
16 #include <linux/init.h>
17 #include <linux/platform_device.h>
18 #include <linux/major.h>
19 #include <linux/fs.h>
20 #include <linux/interrupt.h>
21 #include <linux/mmc/host.h>
22 #include <linux/pm.h>
23 #include <linux/backlight.h>
24
25 #include <asm/setup.h>
26 #include <asm/memory.h>
27 #include <asm/mach-types.h>
28 #include <asm/hardware.h>
29 #include <asm/irq.h>
30 #include <asm/io.h>
31 #include <asm/system.h>
32
33 #include <asm/mach/arch.h>
34 #include <asm/mach/map.h>
35 #include <asm/mach/irq.h>
36
37 #include <asm/arch/pxa-regs.h>
38 #include <asm/arch/irda.h>
39 #include <asm/arch/mmc.h>
40 #include <asm/arch/udc.h>
41 #include <asm/arch/corgi.h>
42 #include <asm/arch/sharpsl.h>
43
44 #include <asm/mach/sharpsl_param.h>
45 #include <asm/hardware/scoop.h>
46
47 #include "generic.h"
48 #include "devices.h"
49 #include "sharpsl.h"
50
51
52 /*
53  * Corgi SCOOP Device
54  */
55 static struct resource corgi_scoop_resources[] = {
56         [0] = {
57                 .start          = 0x10800000,
58                 .end            = 0x10800fff,
59                 .flags          = IORESOURCE_MEM,
60         },
61 };
62
63 static struct scoop_config corgi_scoop_setup = {
64         .io_dir         = CORGI_SCOOP_IO_DIR,
65         .io_out         = CORGI_SCOOP_IO_OUT,
66 };
67
68 struct platform_device corgiscoop_device = {
69         .name           = "sharp-scoop",
70         .id             = -1,
71         .dev            = {
72                 .platform_data  = &corgi_scoop_setup,
73         },
74         .num_resources  = ARRAY_SIZE(corgi_scoop_resources),
75         .resource       = corgi_scoop_resources,
76 };
77
78 static void corgi_pcmcia_init(void)
79 {
80         /* Setup default state of GPIO outputs
81            before we enable them as outputs. */
82         GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) |
83                 GPIO_bit(GPIO49_nPWE) | GPIO_bit(GPIO50_nPIOR) |
84                 GPIO_bit(GPIO51_nPIOW) | GPIO_bit(GPIO52_nPCE_1) |
85                 GPIO_bit(GPIO53_nPCE_2);
86
87         pxa_gpio_mode(GPIO48_nPOE_MD);
88         pxa_gpio_mode(GPIO49_nPWE_MD);
89         pxa_gpio_mode(GPIO50_nPIOR_MD);
90         pxa_gpio_mode(GPIO51_nPIOW_MD);
91         pxa_gpio_mode(GPIO55_nPREG_MD);
92         pxa_gpio_mode(GPIO56_nPWAIT_MD);
93         pxa_gpio_mode(GPIO57_nIOIS16_MD);
94         pxa_gpio_mode(GPIO52_nPCE_1_MD);
95         pxa_gpio_mode(GPIO53_nPCE_2_MD);
96         pxa_gpio_mode(GPIO54_pSKTSEL_MD);
97 }
98
99 static struct scoop_pcmcia_dev corgi_pcmcia_scoop[] = {
100 {
101         .dev        = &corgiscoop_device.dev,
102         .irq        = CORGI_IRQ_GPIO_CF_IRQ,
103         .cd_irq     = CORGI_IRQ_GPIO_CF_CD,
104         .cd_irq_str = "PCMCIA0 CD",
105 },
106 };
107
108 static struct scoop_pcmcia_config corgi_pcmcia_config = {
109         .devs         = &corgi_pcmcia_scoop[0],
110         .num_devs     = 1,
111         .pcmcia_init  = corgi_pcmcia_init,
112 };
113
114 EXPORT_SYMBOL(corgiscoop_device);
115
116
117 /*
118  * Corgi SSP Device
119  *
120  * Set the parent as the scoop device because a lot of SSP devices
121  * also use scoop functions and this makes the power up/down order
122  * work correctly.
123  */
124 struct platform_device corgissp_device = {
125         .name           = "corgi-ssp",
126         .dev            = {
127                 .parent = &corgiscoop_device.dev,
128         },
129         .id             = -1,
130 };
131
132 struct corgissp_machinfo corgi_ssp_machinfo = {
133         .port           = 1,
134         .cs_lcdcon      = CORGI_GPIO_LCDCON_CS,
135         .cs_ads7846     = CORGI_GPIO_ADS7846_CS,
136         .cs_max1111     = CORGI_GPIO_MAX1111_CS,
137         .clk_lcdcon     = 76,
138         .clk_ads7846    = 2,
139         .clk_max1111    = 8,
140 };
141
142
143 /*
144  * Corgi Backlight Device
145  */
146 static void corgi_bl_kick_battery(void)
147 {
148         void (*kick_batt)(void);
149
150         kick_batt = symbol_get(sharpsl_battery_kick);
151         if (kick_batt) {
152                 kick_batt();
153                 symbol_put(sharpsl_battery_kick);
154         }
155 }
156
157 static struct generic_bl_info corgi_bl_machinfo = {
158         .name = "corgi-bl",
159         .max_intensity = 0x2f,
160         .default_intensity = 0x1f,
161         .limit_mask = 0x0b,
162         .set_bl_intensity = corgi_bl_set_intensity,
163         .kick_battery = corgi_bl_kick_battery,
164 };
165
166 static struct platform_device corgibl_device = {
167         .name           = "generic-bl",
168         .dev            = {
169                 .parent = &corgifb_device.dev,
170                 .platform_data  = &corgi_bl_machinfo,
171         },
172         .id             = -1,
173 };
174
175
176 /*
177  * Corgi Keyboard Device
178  */
179 static struct platform_device corgikbd_device = {
180         .name           = "corgi-keyboard",
181         .id             = -1,
182 };
183
184
185 /*
186  * Corgi LEDs
187  */
188 static struct platform_device corgiled_device = {
189         .name           = "corgi-led",
190         .id             = -1,
191 };
192
193 /*
194  * Corgi Touch Screen Device
195  */
196 static struct resource corgits_resources[] = {
197         [0] = {
198                 .start          = CORGI_IRQ_GPIO_TP_INT,
199                 .end            = CORGI_IRQ_GPIO_TP_INT,
200                 .flags          = IORESOURCE_IRQ,
201         },
202 };
203
204 static struct corgits_machinfo  corgi_ts_machinfo = {
205         .get_hsync_len   = corgi_get_hsync_len,
206         .put_hsync       = corgi_put_hsync,
207         .wait_hsync      = corgi_wait_hsync,
208 };
209
210 static struct platform_device corgits_device = {
211         .name           = "corgi-ts",
212         .dev            = {
213                 .parent = &corgissp_device.dev,
214                 .platform_data  = &corgi_ts_machinfo,
215         },
216         .id             = -1,
217         .num_resources  = ARRAY_SIZE(corgits_resources),
218         .resource       = corgits_resources,
219 };
220
221
222 /*
223  * MMC/SD Device
224  *
225  * The card detect interrupt isn't debounced so we delay it by 250ms
226  * to give the card a chance to fully insert/eject.
227  */
228 static struct pxamci_platform_data corgi_mci_platform_data;
229
230 static int corgi_mci_init(struct device *dev, irq_handler_t corgi_detect_int, void *data)
231 {
232         int err;
233
234         /* setup GPIO for PXA25x MMC controller */
235         pxa_gpio_mode(GPIO6_MMCCLK_MD);
236         pxa_gpio_mode(GPIO8_MMCCS0_MD);
237         pxa_gpio_mode(CORGI_GPIO_nSD_DETECT | GPIO_IN);
238         pxa_gpio_mode(CORGI_GPIO_SD_PWR | GPIO_OUT);
239
240         corgi_mci_platform_data.detect_delay = msecs_to_jiffies(250);
241
242         err = request_irq(CORGI_IRQ_GPIO_nSD_DETECT, corgi_detect_int,
243                           IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
244                           "MMC card detect", data);
245         if (err) {
246                 printk(KERN_ERR "corgi_mci_init: MMC/SD: can't request MMC card detect IRQ\n");
247                 return -1;
248         }
249
250         return 0;
251 }
252
253 static void corgi_mci_setpower(struct device *dev, unsigned int vdd)
254 {
255         struct pxamci_platform_data* p_d = dev->platform_data;
256
257         if (( 1 << vdd) & p_d->ocr_mask)
258                 GPSR1 = GPIO_bit(CORGI_GPIO_SD_PWR);
259         else
260                 GPCR1 = GPIO_bit(CORGI_GPIO_SD_PWR);
261 }
262
263 static int corgi_mci_get_ro(struct device *dev)
264 {
265         return GPLR(CORGI_GPIO_nSD_WP) & GPIO_bit(CORGI_GPIO_nSD_WP);
266 }
267
268 static void corgi_mci_exit(struct device *dev, void *data)
269 {
270         free_irq(CORGI_IRQ_GPIO_nSD_DETECT, data);
271 }
272
273 static struct pxamci_platform_data corgi_mci_platform_data = {
274         .ocr_mask       = MMC_VDD_32_33|MMC_VDD_33_34,
275         .init           = corgi_mci_init,
276         .get_ro         = corgi_mci_get_ro,
277         .setpower       = corgi_mci_setpower,
278         .exit           = corgi_mci_exit,
279 };
280
281
282 /*
283  * Irda
284  */
285 static void corgi_irda_transceiver_mode(struct device *dev, int mode)
286 {
287         if (mode & IR_OFF)
288                 GPSR(CORGI_GPIO_IR_ON) = GPIO_bit(CORGI_GPIO_IR_ON);
289         else
290                 GPCR(CORGI_GPIO_IR_ON) = GPIO_bit(CORGI_GPIO_IR_ON);
291 }
292
293 static struct pxaficp_platform_data corgi_ficp_platform_data = {
294         .transceiver_cap  = IR_SIRMODE | IR_OFF,
295         .transceiver_mode = corgi_irda_transceiver_mode,
296 };
297
298
299 /*
300  * USB Device Controller
301  */
302 static struct pxa2xx_udc_mach_info udc_info __initdata = {
303         /* no connect GPIO; corgi can't tell connection status */
304         .gpio_pullup            = CORGI_GPIO_USB_PULLUP,
305 };
306
307
308 static struct platform_device *devices[] __initdata = {
309         &corgiscoop_device,
310         &corgissp_device,
311         &corgifb_device,
312         &corgikbd_device,
313         &corgibl_device,
314         &corgits_device,
315         &corgiled_device,
316 };
317
318 static void corgi_poweroff(void)
319 {
320         RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
321
322         if (!machine_is_corgi())
323                 /* Green LED off tells the bootloader to halt */
324                 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN);
325         arm_machine_restart('h');
326 }
327
328 static void corgi_restart(char mode)
329 {
330         RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
331
332         if (!machine_is_corgi())
333                 /* Green LED on tells the bootloader to reboot */
334                 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN);
335         arm_machine_restart('h');
336 }
337
338 static void __init corgi_init(void)
339 {
340         pm_power_off = corgi_poweroff;
341         arm_pm_restart = corgi_restart;
342
343         /* setup sleep mode values */
344         PWER  = 0x00000002;
345         PFER  = 0x00000000;
346         PRER  = 0x00000002;
347         PGSR0 = 0x0158C000;
348         PGSR1 = 0x00FF0080;
349         PGSR2 = 0x0001C004;
350         /* Stop 3.6MHz and drive HIGH to PCMCIA and CS */
351         PCFR |= PCFR_OPDE;
352
353         corgi_ssp_set_machinfo(&corgi_ssp_machinfo);
354
355         pxa_gpio_mode(CORGI_GPIO_IR_ON | GPIO_OUT);
356         pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN);
357
358         pxa_set_udc_info(&udc_info);
359         pxa_set_mci_info(&corgi_mci_platform_data);
360         pxa_set_ficp_info(&corgi_ficp_platform_data);
361
362         platform_scoop_config = &corgi_pcmcia_config;
363
364         platform_add_devices(devices, ARRAY_SIZE(devices));
365 }
366
367 static void __init fixup_corgi(struct machine_desc *desc,
368                 struct tag *tags, char **cmdline, struct meminfo *mi)
369 {
370         sharpsl_save_param();
371         mi->nr_banks=1;
372         mi->bank[0].start = 0xa0000000;
373         mi->bank[0].node = 0;
374         if (machine_is_corgi())
375                 mi->bank[0].size = (32*1024*1024);
376         else
377                 mi->bank[0].size = (64*1024*1024);
378 }
379
380 #ifdef CONFIG_MACH_CORGI
381 MACHINE_START(CORGI, "SHARP Corgi")
382         .phys_io        = 0x40000000,
383         .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
384         .fixup          = fixup_corgi,
385         .map_io         = pxa_map_io,
386         .init_irq       = pxa25x_init_irq,
387         .init_machine   = corgi_init,
388         .timer          = &pxa_timer,
389 MACHINE_END
390 #endif
391
392 #ifdef CONFIG_MACH_SHEPHERD
393 MACHINE_START(SHEPHERD, "SHARP Shepherd")
394         .phys_io        = 0x40000000,
395         .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
396         .fixup          = fixup_corgi,
397         .map_io         = pxa_map_io,
398         .init_irq       = pxa25x_init_irq,
399         .init_machine   = corgi_init,
400         .timer          = &pxa_timer,
401 MACHINE_END
402 #endif
403
404 #ifdef CONFIG_MACH_HUSKY
405 MACHINE_START(HUSKY, "SHARP Husky")
406         .phys_io        = 0x40000000,
407         .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
408         .fixup          = fixup_corgi,
409         .map_io         = pxa_map_io,
410         .init_irq       = pxa25x_init_irq,
411         .init_machine   = corgi_init,
412         .timer          = &pxa_timer,
413 MACHINE_END
414 #endif
415