• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * linux/arch/arm/mach-pxa/cm-x2xx.c
3  *
4  * Copyright (C) 2008 CompuLab, Ltd.
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 
12 #include <linux/platform_device.h>
13 #include <linux/syscore_ops.h>
14 #include <linux/irq.h>
15 #include <linux/gpio.h>
16 
17 #include <linux/dm9000.h>
18 #include <linux/leds.h>
19 
20 #include <asm/mach/arch.h>
21 #include <asm/mach-types.h>
22 #include <asm/mach/map.h>
23 
24 #include <mach/pxa25x.h>
25 #undef GPIO24_SSP1_SFRM
26 #include <mach/pxa27x.h>
27 #include <mach/audio.h>
28 #include <linux/platform_data/video-pxafb.h>
29 #include <mach/smemc.h>
30 
31 #include <asm/hardware/it8152.h>
32 
33 #include "generic.h"
34 #include "cm-x2xx-pci.h"
35 
36 extern void cmx255_init(void);
37 extern void cmx270_init(void);
38 
39 /* reserve IRQs for IT8152 */
40 #define CMX2XX_NR_IRQS		(IRQ_BOARD_START + 40)
41 
42 /* virtual addresses for statically mapped regions */
43 #define CMX2XX_VIRT_BASE	(void __iomem *)(0xe8000000)
44 #define CMX2XX_IT8152_VIRT	(CMX2XX_VIRT_BASE)
45 
46 /* physical address if local-bus attached devices */
47 #define CMX255_DM9000_PHYS_BASE (PXA_CS1_PHYS + (8 << 22))
48 #define CMX270_DM9000_PHYS_BASE	(PXA_CS1_PHYS + (6 << 22))
49 
50 /* leds */
51 #define CMX255_GPIO_RED		(27)
52 #define CMX255_GPIO_GREEN	(32)
53 #define CMX270_GPIO_RED		(93)
54 #define CMX270_GPIO_GREEN	(94)
55 
56 /* GPIO IRQ usage */
57 #define GPIO22_ETHIRQ		(22)
58 #define GPIO10_ETHIRQ		(10)
59 #define CMX255_GPIO_IT8152_IRQ	(0)
60 #define CMX270_GPIO_IT8152_IRQ	(22)
61 
62 #define CMX255_ETHIRQ		PXA_GPIO_TO_IRQ(GPIO22_ETHIRQ)
63 #define CMX270_ETHIRQ		PXA_GPIO_TO_IRQ(GPIO10_ETHIRQ)
64 
65 #if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
66 static struct resource cmx255_dm9000_resource[] = {
67 	[0] = {
68 		.start = CMX255_DM9000_PHYS_BASE,
69 		.end   = CMX255_DM9000_PHYS_BASE + 3,
70 		.flags = IORESOURCE_MEM,
71 	},
72 	[1] = {
73 		.start = CMX255_DM9000_PHYS_BASE + 4,
74 		.end   = CMX255_DM9000_PHYS_BASE + 4 + 500,
75 		.flags = IORESOURCE_MEM,
76 	},
77 	[2] = {
78 		.start = CMX255_ETHIRQ,
79 		.end   = CMX255_ETHIRQ,
80 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
81 	}
82 };
83 
84 static struct resource cmx270_dm9000_resource[] = {
85 	[0] = {
86 		.start = CMX270_DM9000_PHYS_BASE,
87 		.end   = CMX270_DM9000_PHYS_BASE + 3,
88 		.flags = IORESOURCE_MEM,
89 	},
90 	[1] = {
91 		.start = CMX270_DM9000_PHYS_BASE + 8,
92 		.end   = CMX270_DM9000_PHYS_BASE + 8 + 500,
93 		.flags = IORESOURCE_MEM,
94 	},
95 	[2] = {
96 		.start = CMX270_ETHIRQ,
97 		.end   = CMX270_ETHIRQ,
98 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
99 	}
100 };
101 
102 static struct dm9000_plat_data cmx270_dm9000_platdata = {
103 	.flags		= DM9000_PLATF_32BITONLY | DM9000_PLATF_NO_EEPROM,
104 };
105 
106 static struct platform_device cmx2xx_dm9000_device = {
107 	.name		= "dm9000",
108 	.id		= 0,
109 	.num_resources	= ARRAY_SIZE(cmx270_dm9000_resource),
110 	.dev		= {
111 		.platform_data = &cmx270_dm9000_platdata,
112 	}
113 };
114 
cmx2xx_init_dm9000(void)115 static void __init cmx2xx_init_dm9000(void)
116 {
117 	if (cpu_is_pxa25x())
118 		cmx2xx_dm9000_device.resource = cmx255_dm9000_resource;
119 	else
120 		cmx2xx_dm9000_device.resource = cmx270_dm9000_resource;
121 	platform_device_register(&cmx2xx_dm9000_device);
122 }
123 #else
cmx2xx_init_dm9000(void)124 static inline void cmx2xx_init_dm9000(void) {}
125 #endif
126 
127 /* UCB1400 touchscreen controller */
128 #if defined(CONFIG_TOUCHSCREEN_UCB1400) || defined(CONFIG_TOUCHSCREEN_UCB1400_MODULE)
129 static struct platform_device cmx2xx_ts_device = {
130 	.name		= "ucb1400_core",
131 	.id		= -1,
132 };
133 
cmx2xx_init_touchscreen(void)134 static void __init cmx2xx_init_touchscreen(void)
135 {
136 	platform_device_register(&cmx2xx_ts_device);
137 }
138 #else
cmx2xx_init_touchscreen(void)139 static inline void cmx2xx_init_touchscreen(void) {}
140 #endif
141 
142 /* CM-X270 LEDs */
143 #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
144 static struct gpio_led cmx2xx_leds[] = {
145 	[0] = {
146 		.name = "cm-x2xx:red",
147 		.default_trigger = "nand-disk",
148 		.active_low = 1,
149 	},
150 	[1] = {
151 		.name = "cm-x2xx:green",
152 		.default_trigger = "heartbeat",
153 		.active_low = 1,
154 	},
155 };
156 
157 static struct gpio_led_platform_data cmx2xx_gpio_led_pdata = {
158 	.num_leds = ARRAY_SIZE(cmx2xx_leds),
159 	.leds = cmx2xx_leds,
160 };
161 
162 static struct platform_device cmx2xx_led_device = {
163 	.name		= "leds-gpio",
164 	.id		= -1,
165 	.dev		= {
166 		.platform_data = &cmx2xx_gpio_led_pdata,
167 	},
168 };
169 
cmx2xx_init_leds(void)170 static void __init cmx2xx_init_leds(void)
171 {
172 	if (cpu_is_pxa25x()) {
173 		cmx2xx_leds[0].gpio = CMX255_GPIO_RED;
174 		cmx2xx_leds[1].gpio = CMX255_GPIO_GREEN;
175 	} else {
176 		cmx2xx_leds[0].gpio = CMX270_GPIO_RED;
177 		cmx2xx_leds[1].gpio = CMX270_GPIO_GREEN;
178 	}
179 	platform_device_register(&cmx2xx_led_device);
180 }
181 #else
cmx2xx_init_leds(void)182 static inline void cmx2xx_init_leds(void) {}
183 #endif
184 
185 #if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
186 /*
187   Display definitions
188   keep these for backwards compatibility, although symbolic names (as
189   e.g. in lpd270.c) looks better
190 */
191 #define MTYPE_STN320x240	0
192 #define MTYPE_TFT640x480	1
193 #define MTYPE_CRT640x480	2
194 #define MTYPE_CRT800x600	3
195 #define MTYPE_TFT320x240	6
196 #define MTYPE_STN640x480	7
197 
198 static struct pxafb_mode_info generic_stn_320x240_mode = {
199 	.pixclock	= 76923,
200 	.bpp		= 8,
201 	.xres		= 320,
202 	.yres		= 240,
203 	.hsync_len	= 3,
204 	.vsync_len	= 2,
205 	.left_margin	= 3,
206 	.upper_margin	= 0,
207 	.right_margin	= 3,
208 	.lower_margin	= 0,
209 	.sync		= (FB_SYNC_HOR_HIGH_ACT |
210 			   FB_SYNC_VERT_HIGH_ACT),
211 	.cmap_greyscale = 0,
212 };
213 
214 static struct pxafb_mach_info generic_stn_320x240 = {
215 	.modes		= &generic_stn_320x240_mode,
216 	.num_modes	= 1,
217 	.lcd_conn	= LCD_COLOR_STN_8BPP | LCD_PCLK_EDGE_FALL |\
218 			  LCD_AC_BIAS_FREQ(0xff),
219 	.cmap_inverse	= 0,
220 	.cmap_static	= 0,
221 };
222 
223 static struct pxafb_mode_info generic_tft_640x480_mode = {
224 	.pixclock	= 38461,
225 	.bpp		= 8,
226 	.xres		= 640,
227 	.yres		= 480,
228 	.hsync_len	= 60,
229 	.vsync_len	= 2,
230 	.left_margin	= 70,
231 	.upper_margin	= 10,
232 	.right_margin	= 70,
233 	.lower_margin	= 5,
234 	.sync		= 0,
235 	.cmap_greyscale = 0,
236 };
237 
238 static struct pxafb_mach_info generic_tft_640x480 = {
239 	.modes		= &generic_tft_640x480_mode,
240 	.num_modes	= 1,
241 	.lcd_conn	= LCD_COLOR_TFT_8BPP | LCD_PCLK_EDGE_FALL |\
242 			  LCD_AC_BIAS_FREQ(0xff),
243 	.cmap_inverse	= 0,
244 	.cmap_static	= 0,
245 };
246 
247 static struct pxafb_mode_info generic_crt_640x480_mode = {
248 	.pixclock	= 38461,
249 	.bpp		= 8,
250 	.xres		= 640,
251 	.yres		= 480,
252 	.hsync_len	= 63,
253 	.vsync_len	= 2,
254 	.left_margin	= 81,
255 	.upper_margin	= 33,
256 	.right_margin	= 16,
257 	.lower_margin	= 10,
258 	.sync		= (FB_SYNC_HOR_HIGH_ACT |
259 			   FB_SYNC_VERT_HIGH_ACT),
260 	.cmap_greyscale = 0,
261 };
262 
263 static struct pxafb_mach_info generic_crt_640x480 = {
264 	.modes		= &generic_crt_640x480_mode,
265 	.num_modes	= 1,
266 	.lcd_conn	= LCD_COLOR_TFT_8BPP | LCD_AC_BIAS_FREQ(0xff),
267 	.cmap_inverse	= 0,
268 	.cmap_static	= 0,
269 };
270 
271 static struct pxafb_mode_info generic_crt_800x600_mode = {
272 	.pixclock	= 28846,
273 	.bpp		= 8,
274 	.xres		= 800,
275 	.yres	  	= 600,
276 	.hsync_len	= 63,
277 	.vsync_len	= 2,
278 	.left_margin	= 26,
279 	.upper_margin	= 21,
280 	.right_margin	= 26,
281 	.lower_margin	= 11,
282 	.sync		= (FB_SYNC_HOR_HIGH_ACT |
283 			   FB_SYNC_VERT_HIGH_ACT),
284 	.cmap_greyscale = 0,
285 };
286 
287 static struct pxafb_mach_info generic_crt_800x600 = {
288 	.modes		= &generic_crt_800x600_mode,
289 	.num_modes	= 1,
290 	.lcd_conn	= LCD_COLOR_TFT_8BPP | LCD_AC_BIAS_FREQ(0xff),
291 	.cmap_inverse	= 0,
292 	.cmap_static	= 0,
293 };
294 
295 static struct pxafb_mode_info generic_tft_320x240_mode = {
296 	.pixclock	= 134615,
297 	.bpp		= 16,
298 	.xres		= 320,
299 	.yres		= 240,
300 	.hsync_len	= 63,
301 	.vsync_len	= 7,
302 	.left_margin	= 75,
303 	.upper_margin	= 0,
304 	.right_margin	= 15,
305 	.lower_margin	= 15,
306 	.sync		= 0,
307 	.cmap_greyscale = 0,
308 };
309 
310 static struct pxafb_mach_info generic_tft_320x240 = {
311 	.modes		= &generic_tft_320x240_mode,
312 	.num_modes	= 1,
313 	.lcd_conn	= LCD_COLOR_TFT_16BPP | LCD_AC_BIAS_FREQ(0xff),
314 	.cmap_inverse	= 0,
315 	.cmap_static	= 0,
316 };
317 
318 static struct pxafb_mode_info generic_stn_640x480_mode = {
319 	.pixclock	= 57692,
320 	.bpp		= 8,
321 	.xres		= 640,
322 	.yres		= 480,
323 	.hsync_len	= 4,
324 	.vsync_len	= 2,
325 	.left_margin	= 10,
326 	.upper_margin	= 5,
327 	.right_margin	= 10,
328 	.lower_margin	= 5,
329 	.sync		= (FB_SYNC_HOR_HIGH_ACT |
330 			   FB_SYNC_VERT_HIGH_ACT),
331 	.cmap_greyscale = 0,
332 };
333 
334 static struct pxafb_mach_info generic_stn_640x480 = {
335 	.modes		= &generic_stn_640x480_mode,
336 	.num_modes	= 1,
337 	.lcd_conn	= LCD_COLOR_STN_8BPP | LCD_AC_BIAS_FREQ(0xff),
338 	.cmap_inverse	= 0,
339 	.cmap_static	= 0,
340 };
341 
342 static struct pxafb_mach_info *cmx2xx_display = &generic_crt_640x480;
343 
cmx2xx_set_display(char * str)344 static int __init cmx2xx_set_display(char *str)
345 {
346 	int disp_type = simple_strtol(str, NULL, 0);
347 	switch (disp_type) {
348 	case MTYPE_STN320x240:
349 		cmx2xx_display = &generic_stn_320x240;
350 		break;
351 	case MTYPE_TFT640x480:
352 		cmx2xx_display = &generic_tft_640x480;
353 		break;
354 	case MTYPE_CRT640x480:
355 		cmx2xx_display = &generic_crt_640x480;
356 		break;
357 	case MTYPE_CRT800x600:
358 		cmx2xx_display = &generic_crt_800x600;
359 		break;
360 	case MTYPE_TFT320x240:
361 		cmx2xx_display = &generic_tft_320x240;
362 		break;
363 	case MTYPE_STN640x480:
364 		cmx2xx_display = &generic_stn_640x480;
365 		break;
366 	default: /* fallback to CRT 640x480 */
367 		cmx2xx_display = &generic_crt_640x480;
368 		break;
369 	}
370 	return 1;
371 }
372 
373 /*
374    This should be done really early to get proper configuration for
375    frame buffer.
376    Indeed, pxafb parameters can be used istead, but CM-X2XX bootloader
377    has limitied line length for kernel command line, and also it will
378    break compatibitlty with proprietary releases already in field.
379 */
380 __setup("monitor=", cmx2xx_set_display);
381 
cmx2xx_init_display(void)382 static void __init cmx2xx_init_display(void)
383 {
384 	pxa_set_fb_info(NULL, cmx2xx_display);
385 }
386 #else
cmx2xx_init_display(void)387 static inline void cmx2xx_init_display(void) {}
388 #endif
389 
390 #ifdef CONFIG_PM
391 static unsigned long sleep_save_msc[10];
392 
cmx2xx_suspend(void)393 static int cmx2xx_suspend(void)
394 {
395 	cmx2xx_pci_suspend();
396 
397 	/* save MSC registers */
398 	sleep_save_msc[0] = __raw_readl(MSC0);
399 	sleep_save_msc[1] = __raw_readl(MSC1);
400 	sleep_save_msc[2] = __raw_readl(MSC2);
401 
402 	/* setup power saving mode registers */
403 	PCFR = 0x0;
404 	PSLR = 0xff400000;
405 	PMCR  = 0x00000005;
406 	PWER  = 0x80000000;
407 	PFER  = 0x00000000;
408 	PRER  = 0x00000000;
409 	PGSR0 = 0xC0018800;
410 	PGSR1 = 0x004F0002;
411 	PGSR2 = 0x6021C000;
412 	PGSR3 = 0x00020000;
413 
414 	return 0;
415 }
416 
cmx2xx_resume(void)417 static void cmx2xx_resume(void)
418 {
419 	cmx2xx_pci_resume();
420 
421 	/* restore MSC registers */
422 	__raw_writel(sleep_save_msc[0], MSC0);
423 	__raw_writel(sleep_save_msc[1], MSC1);
424 	__raw_writel(sleep_save_msc[2], MSC2);
425 }
426 
427 static struct syscore_ops cmx2xx_pm_syscore_ops = {
428 	.resume = cmx2xx_resume,
429 	.suspend = cmx2xx_suspend,
430 };
431 
cmx2xx_pm_init(void)432 static int __init cmx2xx_pm_init(void)
433 {
434 	register_syscore_ops(&cmx2xx_pm_syscore_ops);
435 
436 	return 0;
437 }
438 #else
cmx2xx_pm_init(void)439 static int __init cmx2xx_pm_init(void) { return 0; }
440 #endif
441 
442 #if defined(CONFIG_SND_PXA2XX_AC97) || defined(CONFIG_SND_PXA2XX_AC97_MODULE)
cmx2xx_init_ac97(void)443 static void __init cmx2xx_init_ac97(void)
444 {
445 	pxa_set_ac97_info(NULL);
446 }
447 #else
cmx2xx_init_ac97(void)448 static inline void cmx2xx_init_ac97(void) {}
449 #endif
450 
cmx2xx_init(void)451 static void __init cmx2xx_init(void)
452 {
453 	pxa_set_ffuart_info(NULL);
454 	pxa_set_btuart_info(NULL);
455 	pxa_set_stuart_info(NULL);
456 
457 	cmx2xx_pm_init();
458 
459 	if (cpu_is_pxa25x())
460 		cmx255_init();
461 	else
462 		cmx270_init();
463 
464 	cmx2xx_init_dm9000();
465 	cmx2xx_init_display();
466 	cmx2xx_init_ac97();
467 	cmx2xx_init_touchscreen();
468 	cmx2xx_init_leds();
469 }
470 
cmx2xx_init_irq(void)471 static void __init cmx2xx_init_irq(void)
472 {
473 	if (cpu_is_pxa25x()) {
474 		pxa25x_init_irq();
475 		cmx2xx_pci_init_irq(CMX255_GPIO_IT8152_IRQ);
476 	} else {
477 		pxa27x_init_irq();
478 		cmx2xx_pci_init_irq(CMX270_GPIO_IT8152_IRQ);
479 	}
480 }
481 
482 #ifdef CONFIG_PCI
483 /* Map PCI companion statically */
484 static struct map_desc cmx2xx_io_desc[] __initdata = {
485 	[0] = { /* PCI bridge */
486 		.virtual	= (unsigned long)CMX2XX_IT8152_VIRT,
487 		.pfn		= __phys_to_pfn(PXA_CS4_PHYS),
488 		.length		= SZ_64M,
489 		.type		= MT_DEVICE
490 	},
491 };
492 
cmx2xx_map_io(void)493 static void __init cmx2xx_map_io(void)
494 {
495 	if (cpu_is_pxa25x())
496 		pxa25x_map_io();
497 
498 	if (cpu_is_pxa27x())
499 		pxa27x_map_io();
500 
501 	iotable_init(cmx2xx_io_desc, ARRAY_SIZE(cmx2xx_io_desc));
502 
503 	it8152_base_address = CMX2XX_IT8152_VIRT;
504 }
505 #else
cmx2xx_map_io(void)506 static void __init cmx2xx_map_io(void)
507 {
508 	if (cpu_is_pxa25x())
509 		pxa25x_map_io();
510 
511 	if (cpu_is_pxa27x())
512 		pxa27x_map_io();
513 }
514 #endif
515 
516 MACHINE_START(ARMCORE, "Compulab CM-X2XX")
517 	.atag_offset	= 0x100,
518 	.map_io		= cmx2xx_map_io,
519 	.nr_irqs	= CMX2XX_NR_IRQS,
520 	.init_irq	= cmx2xx_init_irq,
521 	/* NOTE: pxa25x_handle_irq() works on PXA27x w/o camera support */
522 	.handle_irq	= pxa25x_handle_irq,
523 	.init_time	= pxa_timer_init,
524 	.init_machine	= cmx2xx_init,
525 #ifdef CONFIG_PCI
526 	.dma_zone_size	= SZ_64M,
527 #endif
528 	.restart	= pxa_restart,
529 MACHINE_END
530