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