Commit | Line | Data |
---|---|---|
3696a8a4 MR |
1 | /* |
2 | * linux/arch/arm/mach-pxa/cm-x270.c | |
3 | * | |
2f01a973 | 4 | * Copyright (C) 2007, 2008 CompuLab, Ltd. |
3696a8a4 MR |
5 | * Mike Rapoport <mike@compulab.co.il> |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License version 2 as | |
9 | * published by the Free Software Foundation. | |
10 | */ | |
11 | ||
3696a8a4 | 12 | #include <linux/platform_device.h> |
3696a8a4 | 13 | #include <linux/sysdev.h> |
2f01a973 MR |
14 | #include <linux/irq.h> |
15 | #include <linux/gpio.h> | |
3696a8a4 MR |
16 | |
17 | #include <linux/dm9000.h> | |
18 | #include <linux/rtc-v3020.h> | |
3696a8a4 | 19 | #include <video/mbxfb.h> |
2f01a973 | 20 | #include <linux/leds.h> |
3696a8a4 MR |
21 | |
22 | #include <asm/mach/arch.h> | |
23 | #include <asm/mach-types.h> | |
24 | #include <asm/mach/map.h> | |
25 | ||
bb548dd4 | 26 | #include <asm/arch/pxa2xx-regs.h> |
2f01a973 MR |
27 | #include <asm/arch/mfp-pxa27x.h> |
28 | #include <asm/arch/pxa-regs.h> | |
9f19d638 | 29 | #include <asm/arch/audio.h> |
3696a8a4 MR |
30 | #include <asm/arch/pxafb.h> |
31 | #include <asm/arch/ohci.h> | |
32 | #include <asm/arch/mmc.h> | |
33 | #include <asm/arch/bitfield.h> | |
3696a8a4 MR |
34 | |
35 | #include <asm/hardware/it8152.h> | |
36 | ||
37 | #include "generic.h" | |
38 | #include "cm-x270-pci.h" | |
39 | ||
2f01a973 MR |
40 | /* virtual addresses for statically mapped regions */ |
41 | #define CMX270_VIRT_BASE (0xe8000000) | |
42 | #define CMX270_IT8152_VIRT (CMX270_VIRT_BASE) | |
43 | ||
3696a8a4 MR |
44 | #define RTC_PHYS_BASE (PXA_CS1_PHYS + (5 << 22)) |
45 | #define DM9000_PHYS_BASE (PXA_CS1_PHYS + (6 << 22)) | |
46 | ||
2f01a973 MR |
47 | /* GPIO IRQ usage */ |
48 | #define GPIO10_ETHIRQ (10) | |
49 | #define GPIO22_IT8152_IRQ (22) | |
50 | #define GPIO83_MMC_IRQ (83) | |
51 | #define GPIO95_GFXIRQ (95) | |
52 | ||
53 | #define CMX270_ETHIRQ IRQ_GPIO(GPIO10_ETHIRQ) | |
54 | #define CMX270_IT8152_IRQ IRQ_GPIO(GPIO22_IT8152_IRQ) | |
55 | #define CMX270_MMC_IRQ IRQ_GPIO(GPIO83_MMC_IRQ) | |
56 | #define CMX270_GFXIRQ IRQ_GPIO(GPIO95_GFXIRQ) | |
57 | ||
58 | /* MMC power enable */ | |
59 | #define GPIO105_MMC_POWER (105) | |
60 | ||
61 | static unsigned long cmx270_pin_config[] = { | |
62 | /* AC'97 */ | |
63 | GPIO28_AC97_BITCLK, | |
64 | GPIO29_AC97_SDATA_IN_0, | |
65 | GPIO30_AC97_SDATA_OUT, | |
66 | GPIO31_AC97_SYNC, | |
67 | GPIO98_AC97_SYSCLK, | |
68 | GPIO113_AC97_nRESET, | |
69 | ||
70 | /* BTUART */ | |
71 | GPIO42_BTUART_RXD, | |
72 | GPIO43_BTUART_TXD, | |
73 | GPIO44_BTUART_CTS, | |
74 | GPIO45_BTUART_RTS, | |
75 | ||
76 | /* STUART */ | |
77 | GPIO46_STUART_RXD, | |
78 | GPIO47_STUART_TXD, | |
79 | ||
80 | /* MCI controller */ | |
81 | GPIO32_MMC_CLK, | |
82 | GPIO112_MMC_CMD, | |
83 | GPIO92_MMC_DAT_0, | |
84 | GPIO109_MMC_DAT_1, | |
85 | GPIO110_MMC_DAT_2, | |
86 | GPIO111_MMC_DAT_3, | |
87 | ||
88 | /* LCD */ | |
89 | GPIO58_LCD_LDD_0, | |
90 | GPIO59_LCD_LDD_1, | |
91 | GPIO60_LCD_LDD_2, | |
92 | GPIO61_LCD_LDD_3, | |
93 | GPIO62_LCD_LDD_4, | |
94 | GPIO63_LCD_LDD_5, | |
95 | GPIO64_LCD_LDD_6, | |
96 | GPIO65_LCD_LDD_7, | |
97 | GPIO66_LCD_LDD_8, | |
98 | GPIO67_LCD_LDD_9, | |
99 | GPIO68_LCD_LDD_10, | |
100 | GPIO69_LCD_LDD_11, | |
101 | GPIO70_LCD_LDD_12, | |
102 | GPIO71_LCD_LDD_13, | |
103 | GPIO72_LCD_LDD_14, | |
104 | GPIO73_LCD_LDD_15, | |
105 | GPIO74_LCD_FCLK, | |
106 | GPIO75_LCD_LCLK, | |
107 | GPIO76_LCD_PCLK, | |
108 | GPIO77_LCD_BIAS, | |
109 | ||
110 | /* I2C */ | |
111 | GPIO117_I2C_SCL, | |
112 | GPIO118_I2C_SDA, | |
113 | ||
114 | /* SSP1 */ | |
115 | GPIO23_SSP1_SCLK, | |
116 | GPIO24_SSP1_SFRM, | |
117 | GPIO25_SSP1_TXD, | |
118 | GPIO26_SSP1_RXD, | |
119 | ||
120 | /* SSP2 */ | |
121 | GPIO19_SSP2_SCLK, | |
122 | GPIO14_SSP2_SFRM, | |
123 | GPIO87_SSP2_TXD, | |
124 | GPIO88_SSP2_RXD, | |
125 | ||
126 | /* PC Card */ | |
127 | GPIO48_nPOE, | |
128 | GPIO49_nPWE, | |
129 | GPIO50_nPIOR, | |
130 | GPIO51_nPIOW, | |
131 | GPIO85_nPCE_1, | |
132 | GPIO54_nPCE_2, | |
133 | GPIO55_nPREG, | |
134 | GPIO56_nPWAIT, | |
135 | GPIO57_nIOIS16, | |
136 | ||
137 | /* SDRAM and local bus */ | |
138 | GPIO15_nCS_1, | |
139 | GPIO78_nCS_2, | |
140 | GPIO79_nCS_3, | |
141 | GPIO80_nCS_4, | |
142 | GPIO33_nCS_5, | |
143 | GPIO49_nPWE, | |
144 | GPIO18_RDY, | |
145 | ||
146 | /* GPIO */ | |
147 | GPIO0_GPIO | WAKEUP_ON_EDGE_BOTH, | |
148 | GPIO105_GPIO | MFP_LPM_DRIVE_HIGH, /* MMC/SD power */ | |
149 | GPIO53_GPIO, /* PC card reset */ | |
150 | ||
151 | /* NAND controls */ | |
152 | GPIO11_GPIO | MFP_LPM_DRIVE_HIGH, /* NAND CE# */ | |
153 | GPIO89_GPIO, /* NAND Ready/Busy */ | |
154 | ||
155 | /* interrupts */ | |
156 | GPIO10_GPIO, /* DM9000 interrupt */ | |
157 | GPIO83_GPIO, /* MMC card detect */ | |
158 | }; | |
159 | ||
160 | #if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE) | |
161 | static struct resource cmx270_dm9000_resource[] = { | |
3696a8a4 MR |
162 | [0] = { |
163 | .start = DM9000_PHYS_BASE, | |
164 | .end = DM9000_PHYS_BASE + 4, | |
165 | .flags = IORESOURCE_MEM, | |
166 | }, | |
167 | [1] = { | |
168 | .start = DM9000_PHYS_BASE + 8, | |
169 | .end = DM9000_PHYS_BASE + 8 + 500, | |
170 | .flags = IORESOURCE_MEM, | |
171 | }, | |
172 | [2] = { | |
173 | .start = CMX270_ETHIRQ, | |
174 | .end = CMX270_ETHIRQ, | |
2f01a973 | 175 | .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, |
3696a8a4 MR |
176 | } |
177 | }; | |
178 | ||
2f01a973 | 179 | static struct dm9000_plat_data cmx270_dm9000_platdata = { |
3696a8a4 MR |
180 | .flags = DM9000_PLATF_32BITONLY, |
181 | }; | |
182 | ||
2f01a973 | 183 | static struct platform_device cmx270_dm9000_device = { |
3696a8a4 MR |
184 | .name = "dm9000", |
185 | .id = 0, | |
2f01a973 MR |
186 | .num_resources = ARRAY_SIZE(cmx270_dm9000_resource), |
187 | .resource = cmx270_dm9000_resource, | |
3696a8a4 | 188 | .dev = { |
2f01a973 | 189 | .platform_data = &cmx270_dm9000_platdata, |
3696a8a4 MR |
190 | } |
191 | }; | |
192 | ||
2f01a973 MR |
193 | static void __init cmx270_init_dm9000(void) |
194 | { | |
195 | platform_device_register(&cmx270_dm9000_device); | |
196 | } | |
197 | #else | |
198 | static inline void cmx270_init_dm9000(void) {} | |
199 | #endif | |
200 | ||
201 | /* UCB1400 touchscreen controller */ | |
202 | #if defined(CONFIG_TOUCHSCREEN_UCB1400) || defined(CONFIG_TOUCHSCREEN_UCB1400_MODULE) | |
3696a8a4 MR |
203 | static struct platform_device cmx270_ts_device = { |
204 | .name = "ucb1400_ts", | |
205 | .id = -1, | |
206 | }; | |
207 | ||
2f01a973 MR |
208 | static void __init cmx270_init_touchscreen(void) |
209 | { | |
210 | platform_device_register(&cmx270_ts_device); | |
211 | } | |
212 | #else | |
213 | static inline void cmx270_init_touchscreen(void) {} | |
214 | #endif | |
215 | ||
216 | /* V3020 RTC */ | |
217 | #if defined(CONFIG_RTC_DRV_V3020) || defined(CONFIG_RTC_DRV_V3020_MODULE) | |
3696a8a4 MR |
218 | static struct resource cmx270_v3020_resource[] = { |
219 | [0] = { | |
220 | .start = RTC_PHYS_BASE, | |
221 | .end = RTC_PHYS_BASE + 4, | |
222 | .flags = IORESOURCE_MEM, | |
223 | }, | |
224 | }; | |
225 | ||
226 | struct v3020_platform_data cmx270_v3020_pdata = { | |
227 | .leftshift = 16, | |
228 | }; | |
229 | ||
230 | static struct platform_device cmx270_rtc_device = { | |
231 | .name = "v3020", | |
232 | .num_resources = ARRAY_SIZE(cmx270_v3020_resource), | |
233 | .resource = cmx270_v3020_resource, | |
234 | .id = -1, | |
235 | .dev = { | |
236 | .platform_data = &cmx270_v3020_pdata, | |
237 | } | |
238 | }; | |
239 | ||
2f01a973 MR |
240 | static void __init cmx270_init_rtc(void) |
241 | { | |
242 | platform_device_register(&cmx270_rtc_device); | |
243 | } | |
244 | #else | |
245 | static inline void cmx270_init_rtc(void) {} | |
246 | #endif | |
247 | ||
248 | /* CM-X270 LEDs */ | |
249 | #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) | |
250 | static struct gpio_led cmx270_leds[] = { | |
251 | [0] = { | |
252 | .name = "cm-x270:red", | |
253 | .default_trigger = "nand-disk", | |
254 | .gpio = 93, | |
255 | .active_low = 1, | |
256 | }, | |
257 | [1] = { | |
258 | .name = "cm-x270:green", | |
259 | .default_trigger = "heartbeat", | |
260 | .gpio = 94, | |
261 | .active_low = 1, | |
262 | }, | |
263 | }; | |
264 | ||
265 | static struct gpio_led_platform_data cmx270_gpio_led_pdata = { | |
266 | .num_leds = ARRAY_SIZE(cmx270_leds), | |
267 | .leds = cmx270_leds, | |
268 | }; | |
269 | ||
3696a8a4 | 270 | static struct platform_device cmx270_led_device = { |
2f01a973 | 271 | .name = "leds-gpio", |
3696a8a4 | 272 | .id = -1, |
2f01a973 MR |
273 | .dev = { |
274 | .platform_data = &cmx270_gpio_led_pdata, | |
275 | }, | |
3696a8a4 MR |
276 | }; |
277 | ||
2f01a973 MR |
278 | static void __init cmx270_init_leds(void) |
279 | { | |
280 | platform_device_register(&cmx270_led_device); | |
281 | } | |
282 | #else | |
283 | static inline void cmx270_init_leds(void) {} | |
284 | #endif | |
285 | ||
3696a8a4 | 286 | /* 2700G graphics */ |
2f01a973 | 287 | #if defined(CONFIG_FB_MBX) || defined(CONFIG_FB_MBX_MODULE) |
3696a8a4 MR |
288 | static u64 fb_dma_mask = ~(u64)0; |
289 | ||
290 | static struct resource cmx270_2700G_resource[] = { | |
291 | /* frame buffer memory including ODFB and External SDRAM */ | |
292 | [0] = { | |
2f01a973 MR |
293 | .start = PXA_CS2_PHYS, |
294 | .end = PXA_CS2_PHYS + 0x01ffffff, | |
3696a8a4 MR |
295 | .flags = IORESOURCE_MEM, |
296 | }, | |
297 | /* Marathon registers */ | |
298 | [1] = { | |
2f01a973 MR |
299 | .start = PXA_CS2_PHYS + 0x03fe0000, |
300 | .end = PXA_CS2_PHYS + 0x03ffffff, | |
3696a8a4 MR |
301 | .flags = IORESOURCE_MEM, |
302 | }, | |
303 | }; | |
304 | ||
305 | static unsigned long save_lcd_regs[10]; | |
306 | ||
307 | static int cmx270_marathon_probe(struct fb_info *fb) | |
308 | { | |
309 | /* save PXA-270 pin settings before enabling 2700G */ | |
310 | save_lcd_regs[0] = GPDR1; | |
311 | save_lcd_regs[1] = GPDR2; | |
312 | save_lcd_regs[2] = GAFR1_U; | |
313 | save_lcd_regs[3] = GAFR2_L; | |
314 | save_lcd_regs[4] = GAFR2_U; | |
315 | ||
316 | /* Disable PXA-270 on-chip controller driving pins */ | |
317 | GPDR1 &= ~(0xfc000000); | |
318 | GPDR2 &= ~(0x00c03fff); | |
319 | GAFR1_U &= ~(0xfff00000); | |
320 | GAFR2_L &= ~(0x0fffffff); | |
321 | GAFR2_U &= ~(0x0000f000); | |
322 | return 0; | |
323 | } | |
324 | ||
325 | static int cmx270_marathon_remove(struct fb_info *fb) | |
326 | { | |
327 | GPDR1 = save_lcd_regs[0]; | |
328 | GPDR2 = save_lcd_regs[1]; | |
329 | GAFR1_U = save_lcd_regs[2]; | |
330 | GAFR2_L = save_lcd_regs[3]; | |
331 | GAFR2_U = save_lcd_regs[4]; | |
332 | return 0; | |
333 | } | |
334 | ||
335 | static struct mbxfb_platform_data cmx270_2700G_data = { | |
336 | .xres = { | |
337 | .min = 240, | |
338 | .max = 1200, | |
339 | .defval = 640, | |
340 | }, | |
341 | .yres = { | |
342 | .min = 240, | |
343 | .max = 1200, | |
344 | .defval = 480, | |
345 | }, | |
346 | .bpp = { | |
347 | .min = 16, | |
348 | .max = 32, | |
349 | .defval = 16, | |
350 | }, | |
351 | .memsize = 8*1024*1024, | |
352 | .probe = cmx270_marathon_probe, | |
353 | .remove = cmx270_marathon_remove, | |
354 | }; | |
355 | ||
356 | static struct platform_device cmx270_2700G = { | |
357 | .name = "mbx-fb", | |
358 | .dev = { | |
359 | .platform_data = &cmx270_2700G_data, | |
360 | .dma_mask = &fb_dma_mask, | |
361 | .coherent_dma_mask = 0xffffffff, | |
362 | }, | |
363 | .num_resources = ARRAY_SIZE(cmx270_2700G_resource), | |
364 | .resource = cmx270_2700G_resource, | |
365 | .id = -1, | |
366 | }; | |
367 | ||
2f01a973 MR |
368 | static void __init cmx270_init_2700G(void) |
369 | { | |
370 | platform_device_register(&cmx270_2700G); | |
371 | } | |
372 | #else | |
373 | static inline void cmx270_init_2700G(void) {} | |
374 | #endif | |
3696a8a4 | 375 | |
2f01a973 | 376 | #if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE) |
3696a8a4 MR |
377 | /* |
378 | Display definitions | |
379 | keep these for backwards compatibility, although symbolic names (as | |
380 | e.g. in lpd270.c) looks better | |
381 | */ | |
382 | #define MTYPE_STN320x240 0 | |
383 | #define MTYPE_TFT640x480 1 | |
384 | #define MTYPE_CRT640x480 2 | |
385 | #define MTYPE_CRT800x600 3 | |
386 | #define MTYPE_TFT320x240 6 | |
387 | #define MTYPE_STN640x480 7 | |
388 | ||
389 | static struct pxafb_mode_info generic_stn_320x240_mode = { | |
390 | .pixclock = 76923, | |
391 | .bpp = 8, | |
392 | .xres = 320, | |
393 | .yres = 240, | |
394 | .hsync_len = 3, | |
395 | .vsync_len = 2, | |
396 | .left_margin = 3, | |
397 | .upper_margin = 0, | |
398 | .right_margin = 3, | |
399 | .lower_margin = 0, | |
400 | .sync = (FB_SYNC_HOR_HIGH_ACT | | |
401 | FB_SYNC_VERT_HIGH_ACT), | |
402 | .cmap_greyscale = 0, | |
403 | }; | |
404 | ||
405 | static struct pxafb_mach_info generic_stn_320x240 = { | |
406 | .modes = &generic_stn_320x240_mode, | |
407 | .num_modes = 1, | |
408 | .lccr0 = 0, | |
409 | .lccr3 = (LCCR3_PixClkDiv(0x03) | | |
410 | LCCR3_Acb(0xff) | | |
411 | LCCR3_PCP), | |
412 | .cmap_inverse = 0, | |
413 | .cmap_static = 0, | |
414 | }; | |
415 | ||
416 | static struct pxafb_mode_info generic_tft_640x480_mode = { | |
417 | .pixclock = 38461, | |
418 | .bpp = 8, | |
419 | .xres = 640, | |
420 | .yres = 480, | |
421 | .hsync_len = 60, | |
422 | .vsync_len = 2, | |
423 | .left_margin = 70, | |
424 | .upper_margin = 10, | |
425 | .right_margin = 70, | |
426 | .lower_margin = 5, | |
427 | .sync = 0, | |
428 | .cmap_greyscale = 0, | |
429 | }; | |
430 | ||
431 | static struct pxafb_mach_info generic_tft_640x480 = { | |
432 | .modes = &generic_tft_640x480_mode, | |
433 | .num_modes = 1, | |
434 | .lccr0 = (LCCR0_PAS), | |
435 | .lccr3 = (LCCR3_PixClkDiv(0x01) | | |
436 | LCCR3_Acb(0xff) | | |
437 | LCCR3_PCP), | |
438 | .cmap_inverse = 0, | |
439 | .cmap_static = 0, | |
440 | }; | |
441 | ||
442 | static struct pxafb_mode_info generic_crt_640x480_mode = { | |
443 | .pixclock = 38461, | |
444 | .bpp = 8, | |
445 | .xres = 640, | |
446 | .yres = 480, | |
447 | .hsync_len = 63, | |
448 | .vsync_len = 2, | |
449 | .left_margin = 81, | |
450 | .upper_margin = 33, | |
451 | .right_margin = 16, | |
452 | .lower_margin = 10, | |
453 | .sync = (FB_SYNC_HOR_HIGH_ACT | | |
454 | FB_SYNC_VERT_HIGH_ACT), | |
455 | .cmap_greyscale = 0, | |
456 | }; | |
457 | ||
458 | static struct pxafb_mach_info generic_crt_640x480 = { | |
459 | .modes = &generic_crt_640x480_mode, | |
460 | .num_modes = 1, | |
461 | .lccr0 = (LCCR0_PAS), | |
462 | .lccr3 = (LCCR3_PixClkDiv(0x01) | | |
463 | LCCR3_Acb(0xff)), | |
464 | .cmap_inverse = 0, | |
465 | .cmap_static = 0, | |
466 | }; | |
467 | ||
468 | static struct pxafb_mode_info generic_crt_800x600_mode = { | |
469 | .pixclock = 28846, | |
470 | .bpp = 8, | |
471 | .xres = 800, | |
472 | .yres = 600, | |
473 | .hsync_len = 63, | |
474 | .vsync_len = 2, | |
475 | .left_margin = 26, | |
476 | .upper_margin = 21, | |
477 | .right_margin = 26, | |
478 | .lower_margin = 11, | |
479 | .sync = (FB_SYNC_HOR_HIGH_ACT | | |
480 | FB_SYNC_VERT_HIGH_ACT), | |
481 | .cmap_greyscale = 0, | |
482 | }; | |
483 | ||
484 | static struct pxafb_mach_info generic_crt_800x600 = { | |
485 | .modes = &generic_crt_800x600_mode, | |
486 | .num_modes = 1, | |
487 | .lccr0 = (LCCR0_PAS), | |
488 | .lccr3 = (LCCR3_PixClkDiv(0x02) | | |
489 | LCCR3_Acb(0xff)), | |
490 | .cmap_inverse = 0, | |
491 | .cmap_static = 0, | |
492 | }; | |
493 | ||
494 | static struct pxafb_mode_info generic_tft_320x240_mode = { | |
495 | .pixclock = 134615, | |
496 | .bpp = 16, | |
497 | .xres = 320, | |
498 | .yres = 240, | |
499 | .hsync_len = 63, | |
500 | .vsync_len = 7, | |
501 | .left_margin = 75, | |
502 | .upper_margin = 0, | |
503 | .right_margin = 15, | |
504 | .lower_margin = 15, | |
505 | .sync = 0, | |
506 | .cmap_greyscale = 0, | |
507 | }; | |
508 | ||
509 | static struct pxafb_mach_info generic_tft_320x240 = { | |
510 | .modes = &generic_tft_320x240_mode, | |
511 | .num_modes = 1, | |
512 | .lccr0 = (LCCR0_PAS), | |
513 | .lccr3 = (LCCR3_PixClkDiv(0x06) | | |
514 | LCCR3_Acb(0xff) | | |
515 | LCCR3_PCP), | |
516 | .cmap_inverse = 0, | |
517 | .cmap_static = 0, | |
518 | }; | |
519 | ||
520 | static struct pxafb_mode_info generic_stn_640x480_mode = { | |
521 | .pixclock = 57692, | |
522 | .bpp = 8, | |
523 | .xres = 640, | |
524 | .yres = 480, | |
525 | .hsync_len = 4, | |
526 | .vsync_len = 2, | |
527 | .left_margin = 10, | |
528 | .upper_margin = 5, | |
529 | .right_margin = 10, | |
530 | .lower_margin = 5, | |
531 | .sync = (FB_SYNC_HOR_HIGH_ACT | | |
532 | FB_SYNC_VERT_HIGH_ACT), | |
533 | .cmap_greyscale = 0, | |
534 | }; | |
535 | ||
536 | static struct pxafb_mach_info generic_stn_640x480 = { | |
537 | .modes = &generic_stn_640x480_mode, | |
538 | .num_modes = 1, | |
539 | .lccr0 = 0, | |
540 | .lccr3 = (LCCR3_PixClkDiv(0x02) | | |
541 | LCCR3_Acb(0xff)), | |
542 | .cmap_inverse = 0, | |
543 | .cmap_static = 0, | |
544 | }; | |
545 | ||
546 | static struct pxafb_mach_info *cmx270_display = &generic_crt_640x480; | |
547 | ||
548 | static int __init cmx270_set_display(char *str) | |
549 | { | |
550 | int disp_type = simple_strtol(str, NULL, 0); | |
551 | switch (disp_type) { | |
552 | case MTYPE_STN320x240: | |
553 | cmx270_display = &generic_stn_320x240; | |
554 | break; | |
555 | case MTYPE_TFT640x480: | |
556 | cmx270_display = &generic_tft_640x480; | |
557 | break; | |
558 | case MTYPE_CRT640x480: | |
559 | cmx270_display = &generic_crt_640x480; | |
560 | break; | |
561 | case MTYPE_CRT800x600: | |
562 | cmx270_display = &generic_crt_800x600; | |
563 | break; | |
564 | case MTYPE_TFT320x240: | |
565 | cmx270_display = &generic_tft_320x240; | |
566 | break; | |
567 | case MTYPE_STN640x480: | |
568 | cmx270_display = &generic_stn_640x480; | |
569 | break; | |
570 | default: /* fallback to CRT 640x480 */ | |
571 | cmx270_display = &generic_crt_640x480; | |
572 | break; | |
573 | } | |
574 | return 1; | |
575 | } | |
576 | ||
577 | /* | |
578 | This should be done really early to get proper configuration for | |
579 | frame buffer. | |
580 | Indeed, pxafb parameters can be used istead, but CM-X270 bootloader | |
581 | has limitied line length for kernel command line, and also it will | |
582 | break compatibitlty with proprietary releases already in field. | |
583 | */ | |
584 | __setup("monitor=", cmx270_set_display); | |
585 | ||
2f01a973 MR |
586 | static void __init cmx270_init_display(void) |
587 | { | |
588 | set_pxa_fb_info(cmx270_display); | |
589 | } | |
590 | #else | |
591 | static inline void cmx270_init_display(void) {} | |
592 | #endif | |
593 | ||
3696a8a4 | 594 | /* PXA27x OHCI controller setup */ |
2f01a973 | 595 | #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) |
3696a8a4 MR |
596 | static int cmx270_ohci_init(struct device *dev) |
597 | { | |
598 | /* Set the Power Control Polarity Low */ | |
599 | UHCHR = (UHCHR | UHCHR_PCPL) & | |
600 | ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSE); | |
601 | ||
602 | return 0; | |
603 | } | |
604 | ||
605 | static struct pxaohci_platform_data cmx270_ohci_platform_data = { | |
606 | .port_mode = PMM_PERPORT_MODE, | |
607 | .init = cmx270_ohci_init, | |
608 | }; | |
609 | ||
2f01a973 MR |
610 | static void __init cmx270_init_ohci(void) |
611 | { | |
612 | pxa_set_ohci_info(&cmx270_ohci_platform_data); | |
613 | } | |
614 | #else | |
615 | static inline void cmx270_init_ohci(void) {} | |
616 | #endif | |
3696a8a4 | 617 | |
2f01a973 | 618 | #if defined(CONFIG_MMC) || defined(CONFIG_MMC_MODULE) |
3696a8a4 MR |
619 | static int cmx270_mci_init(struct device *dev, |
620 | irq_handler_t cmx270_detect_int, | |
621 | void *data) | |
622 | { | |
623 | int err; | |
624 | ||
2f01a973 MR |
625 | err = gpio_request(GPIO105_MMC_POWER, "MMC/SD power"); |
626 | if (err) { | |
627 | dev_warn(dev, "power gpio unavailable\n"); | |
628 | return err; | |
629 | } | |
3696a8a4 | 630 | |
2f01a973 | 631 | gpio_direction_output(GPIO105_MMC_POWER, 0); |
3696a8a4 MR |
632 | |
633 | err = request_irq(CMX270_MMC_IRQ, cmx270_detect_int, | |
634 | IRQF_DISABLED | IRQF_TRIGGER_FALLING, | |
635 | "MMC card detect", data); | |
2f01a973 MR |
636 | if (err) { |
637 | gpio_free(GPIO105_MMC_POWER); | |
638 | dev_err(dev, "cmx270_mci_init: MMC/SD: can't" | |
639 | " request MMC card detect IRQ\n"); | |
640 | } | |
3696a8a4 | 641 | |
2687bd38 | 642 | return err; |
3696a8a4 MR |
643 | } |
644 | ||
645 | static void cmx270_mci_setpower(struct device *dev, unsigned int vdd) | |
646 | { | |
647 | struct pxamci_platform_data *p_d = dev->platform_data; | |
648 | ||
649 | if ((1 << vdd) & p_d->ocr_mask) { | |
2f01a973 MR |
650 | dev_dbg(dev, "power on\n"); |
651 | gpio_set_value(GPIO105_MMC_POWER, 0); | |
3696a8a4 | 652 | } else { |
2f01a973 MR |
653 | gpio_set_value(GPIO105_MMC_POWER, 1); |
654 | dev_dbg(dev, "power off\n"); | |
3696a8a4 MR |
655 | } |
656 | } | |
657 | ||
658 | static void cmx270_mci_exit(struct device *dev, void *data) | |
659 | { | |
660 | free_irq(CMX270_MMC_IRQ, data); | |
2f01a973 | 661 | gpio_free(GPIO105_MMC_POWER); |
3696a8a4 MR |
662 | } |
663 | ||
664 | static struct pxamci_platform_data cmx270_mci_platform_data = { | |
665 | .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, | |
666 | .init = cmx270_mci_init, | |
667 | .setpower = cmx270_mci_setpower, | |
668 | .exit = cmx270_mci_exit, | |
669 | }; | |
670 | ||
2f01a973 MR |
671 | static void __init cmx270_init_mmc(void) |
672 | { | |
673 | pxa_set_mci_info(&cmx270_mci_platform_data); | |
674 | } | |
675 | #else | |
676 | static inline void cmx270_init_mmc(void) {} | |
677 | #endif | |
678 | ||
3696a8a4 MR |
679 | #ifdef CONFIG_PM |
680 | static unsigned long sleep_save_msc[10]; | |
681 | ||
682 | static int cmx270_suspend(struct sys_device *dev, pm_message_t state) | |
683 | { | |
684 | cmx270_pci_suspend(); | |
685 | ||
686 | /* save MSC registers */ | |
687 | sleep_save_msc[0] = MSC0; | |
688 | sleep_save_msc[1] = MSC1; | |
689 | sleep_save_msc[2] = MSC2; | |
690 | ||
691 | /* setup power saving mode registers */ | |
692 | PCFR = 0x0; | |
693 | PSLR = 0xff400000; | |
694 | PMCR = 0x00000005; | |
695 | PWER = 0x80000000; | |
696 | PFER = 0x00000000; | |
697 | PRER = 0x00000000; | |
698 | PGSR0 = 0xC0018800; | |
699 | PGSR1 = 0x004F0002; | |
700 | PGSR2 = 0x6021C000; | |
701 | PGSR3 = 0x00020000; | |
702 | ||
703 | return 0; | |
704 | } | |
705 | ||
706 | static int cmx270_resume(struct sys_device *dev) | |
707 | { | |
708 | cmx270_pci_resume(); | |
709 | ||
710 | /* restore MSC registers */ | |
711 | MSC0 = sleep_save_msc[0]; | |
712 | MSC1 = sleep_save_msc[1]; | |
713 | MSC2 = sleep_save_msc[2]; | |
714 | ||
715 | return 0; | |
716 | } | |
717 | ||
718 | static struct sysdev_class cmx270_pm_sysclass = { | |
af5ca3f4 | 719 | .name = "pm", |
3696a8a4 MR |
720 | .resume = cmx270_resume, |
721 | .suspend = cmx270_suspend, | |
722 | }; | |
723 | ||
724 | static struct sys_device cmx270_pm_device = { | |
725 | .cls = &cmx270_pm_sysclass, | |
726 | }; | |
727 | ||
728 | static int __init cmx270_pm_init(void) | |
729 | { | |
730 | int error; | |
731 | error = sysdev_class_register(&cmx270_pm_sysclass); | |
732 | if (error == 0) | |
733 | error = sysdev_register(&cmx270_pm_device); | |
734 | return error; | |
735 | } | |
736 | #else | |
737 | static int __init cmx270_pm_init(void) { return 0; } | |
738 | #endif | |
739 | ||
2f01a973 MR |
740 | #if defined(CONFIG_SND_PXA2XX_AC97) || defined(CONFIG_SND_PXA2XX_AC97_MODULE) |
741 | static void __init cmx270_init_ac97(void) | |
3696a8a4 | 742 | { |
9f19d638 | 743 | pxa_set_ac97_info(NULL); |
2f01a973 MR |
744 | } |
745 | #else | |
746 | static inline void cmx270_init_ac97(void) {} | |
747 | #endif | |
3696a8a4 | 748 | |
2f01a973 MR |
749 | static void __init cmx270_init(void) |
750 | { | |
751 | cmx270_pm_init(); | |
3696a8a4 | 752 | |
2f01a973 MR |
753 | pxa2xx_mfp_config(ARRAY_AND_SIZE(cmx270_pin_config)); |
754 | ||
755 | cmx270_init_dm9000(); | |
756 | cmx270_init_rtc(); | |
757 | cmx270_init_display(); | |
758 | cmx270_init_mmc(); | |
759 | cmx270_init_ohci(); | |
760 | cmx270_init_ac97(); | |
761 | cmx270_init_touchscreen(); | |
762 | cmx270_init_leds(); | |
763 | cmx270_init_2700G(); | |
3696a8a4 MR |
764 | } |
765 | ||
766 | static void __init cmx270_init_irq(void) | |
767 | { | |
768 | pxa27x_init_irq(); | |
769 | ||
2f01a973 MR |
770 | cmx270_pci_init_irq(GPIO22_IT8152_IRQ); |
771 | } | |
3696a8a4 | 772 | |
2f01a973 MR |
773 | #ifdef CONFIG_PCI |
774 | /* Map PCI companion statically */ | |
775 | static struct map_desc cmx270_io_desc[] __initdata = { | |
776 | [0] = { /* PCI bridge */ | |
777 | .virtual = CMX270_IT8152_VIRT, | |
778 | .pfn = __phys_to_pfn(PXA_CS4_PHYS), | |
779 | .length = SZ_64M, | |
780 | .type = MT_DEVICE | |
781 | }, | |
782 | }; | |
3696a8a4 | 783 | |
2f01a973 MR |
784 | static void __init cmx270_map_io(void) |
785 | { | |
786 | pxa_map_io(); | |
787 | iotable_init(cmx270_io_desc, ARRAY_SIZE(cmx270_io_desc)); | |
3696a8a4 | 788 | |
2f01a973 | 789 | it8152_base_address = CMX270_IT8152_VIRT; |
3696a8a4 | 790 | } |
2f01a973 | 791 | #else |
3696a8a4 MR |
792 | static void __init cmx270_map_io(void) |
793 | { | |
794 | pxa_map_io(); | |
3696a8a4 | 795 | } |
2f01a973 | 796 | #endif |
3696a8a4 MR |
797 | |
798 | MACHINE_START(ARMCORE, "Compulab CM-x270") | |
799 | .boot_params = 0xa0000100, | |
800 | .phys_io = 0x40000000, | |
801 | .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, | |
802 | .map_io = cmx270_map_io, | |
803 | .init_irq = cmx270_init_irq, | |
804 | .timer = &pxa_timer, | |
805 | .init_machine = cmx270_init, | |
806 | MACHINE_END |