blob: 3d679dbc3cc6717b43dfe6b3fd59d1d1c0e1dc35 [file] [log] [blame]
yuezonghe824eb0c2024-06-27 02:32:26 -07001/*
2 * linux/arch/arm/mach-pxa/mainstone.c
3 *
4 * Support for the Intel HCDDBBVA0 Development Platform.
5 * (go figure how they came up with such name...)
6 *
7 * Author: Nicolas Pitre
8 * Created: Nov 05, 2002
9 * Copyright: MontaVista Software Inc.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15#include <linux/gpio.h>
16#include <linux/gpio/machine.h>
17#include <linux/init.h>
18#include <linux/platform_device.h>
19#include <linux/syscore_ops.h>
20#include <linux/interrupt.h>
21#include <linux/sched.h>
22#include <linux/bitops.h>
23#include <linux/fb.h>
24#include <linux/ioport.h>
25#include <linux/mtd/mtd.h>
26#include <linux/mtd/partitions.h>
27#include <linux/input.h>
28#include <linux/gpio_keys.h>
29#include <linux/pwm_backlight.h>
30#include <linux/smc91x.h>
31#include <linux/i2c/pxa-i2c.h>
32
33#include <asm/types.h>
34#include <asm/setup.h>
35#include <asm/memory.h>
36#include <asm/mach-types.h>
37#include <mach/hardware.h>
38#include <asm/irq.h>
39#include <asm/sizes.h>
40
41#include <asm/mach/arch.h>
42#include <asm/mach/map.h>
43#include <asm/mach/irq.h>
44#include <asm/mach/flash.h>
45
46#include <mach/pxa27x.h>
47#include <mach/mainstone.h>
48#include <mach/audio.h>
49#include <mach/pxafb.h>
50#include <mach/mmc.h>
51#include <mach/irda.h>
52#include <mach/ohci.h>
53#include <plat/pxa27x_keypad.h>
54#include <mach/smemc.h>
55
56#include "generic.h"
57#include "devices.h"
58
59static unsigned long mainstone_pin_config[] = {
60 /* Chip Select */
61 GPIO15_nCS_1,
62
63 /* LCD - 16bpp Active TFT */
64 GPIOxx_LCD_TFT_16BPP,
65 GPIO16_PWM0_OUT, /* Backlight */
66
67 /* MMC */
68 GPIO32_MMC_CLK,
69 GPIO112_MMC_CMD,
70 GPIO92_MMC_DAT_0,
71 GPIO109_MMC_DAT_1,
72 GPIO110_MMC_DAT_2,
73 GPIO111_MMC_DAT_3,
74
75 /* USB Host Port 1 */
76 GPIO88_USBH1_PWR,
77 GPIO89_USBH1_PEN,
78
79 /* PC Card */
80 GPIO48_nPOE,
81 GPIO49_nPWE,
82 GPIO50_nPIOR,
83 GPIO51_nPIOW,
84 GPIO85_nPCE_1,
85 GPIO54_nPCE_2,
86 GPIO79_PSKTSEL,
87 GPIO55_nPREG,
88 GPIO56_nPWAIT,
89 GPIO57_nIOIS16,
90
91 /* AC97 */
92 GPIO28_AC97_BITCLK,
93 GPIO29_AC97_SDATA_IN_0,
94 GPIO30_AC97_SDATA_OUT,
95 GPIO31_AC97_SYNC,
96 GPIO45_AC97_SYSCLK,
97
98 /* Keypad */
99 GPIO93_KP_DKIN_0,
100 GPIO94_KP_DKIN_1,
101 GPIO95_KP_DKIN_2,
102 GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH,
103 GPIO101_KP_MKIN_1 | WAKEUP_ON_LEVEL_HIGH,
104 GPIO102_KP_MKIN_2 | WAKEUP_ON_LEVEL_HIGH,
105 GPIO97_KP_MKIN_3 | WAKEUP_ON_LEVEL_HIGH,
106 GPIO98_KP_MKIN_4 | WAKEUP_ON_LEVEL_HIGH,
107 GPIO99_KP_MKIN_5 | WAKEUP_ON_LEVEL_HIGH,
108 GPIO103_KP_MKOUT_0,
109 GPIO104_KP_MKOUT_1,
110 GPIO105_KP_MKOUT_2,
111 GPIO106_KP_MKOUT_3,
112 GPIO107_KP_MKOUT_4,
113 GPIO108_KP_MKOUT_5,
114 GPIO96_KP_MKOUT_6,
115
116 /* I2C */
117 GPIO117_I2C_SCL,
118 GPIO118_I2C_SDA,
119
120 /* GPIO */
121 GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH,
122};
123
124static struct resource smc91x_resources[] = {
125 [0] = {
126 .start = (MST_ETH_PHYS + 0x300),
127 .end = (MST_ETH_PHYS + 0xfffff),
128 .flags = IORESOURCE_MEM,
129 },
130 [1] = {
131 .start = MAINSTONE_IRQ(3),
132 .end = MAINSTONE_IRQ(3),
133 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
134 }
135};
136
137static struct smc91x_platdata mainstone_smc91x_info = {
138 .flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT |
139 SMC91X_NOWAIT | SMC91X_USE_DMA,
140};
141
142static struct platform_device smc91x_device = {
143 .name = "smc91x",
144 .id = 0,
145 .num_resources = ARRAY_SIZE(smc91x_resources),
146 .resource = smc91x_resources,
147 .dev = {
148 .platform_data = &mainstone_smc91x_info,
149 },
150};
151
152static int mst_audio_startup(struct snd_pcm_substream *substream, void *priv)
153{
154 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
155 MST_MSCWR2 &= ~MST_MSCWR2_AC97_SPKROFF;
156 return 0;
157}
158
159static void mst_audio_shutdown(struct snd_pcm_substream *substream, void *priv)
160{
161 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
162 MST_MSCWR2 |= MST_MSCWR2_AC97_SPKROFF;
163}
164
165static long mst_audio_suspend_mask;
166
167static void mst_audio_suspend(void *priv)
168{
169 mst_audio_suspend_mask = MST_MSCWR2;
170 MST_MSCWR2 |= MST_MSCWR2_AC97_SPKROFF;
171}
172
173static void mst_audio_resume(void *priv)
174{
175 MST_MSCWR2 &= mst_audio_suspend_mask | ~MST_MSCWR2_AC97_SPKROFF;
176}
177
178static pxa2xx_audio_ops_t mst_audio_ops = {
179 .startup = mst_audio_startup,
180 .shutdown = mst_audio_shutdown,
181 .suspend = mst_audio_suspend,
182 .resume = mst_audio_resume,
183};
184
185static struct resource flash_resources[] = {
186 [0] = {
187 .start = PXA_CS0_PHYS,
188 .end = PXA_CS0_PHYS + SZ_64M - 1,
189 .flags = IORESOURCE_MEM,
190 },
191 [1] = {
192 .start = PXA_CS1_PHYS,
193 .end = PXA_CS1_PHYS + SZ_64M - 1,
194 .flags = IORESOURCE_MEM,
195 },
196};
197
198static struct mtd_partition mainstoneflash0_partitions[] = {
199 {
200 .name = "Bootloader",
201 .size = 0x00040000,
202 .offset = 0,
203 .mask_flags = MTD_WRITEABLE /* force read-only */
204 },{
205 .name = "Kernel",
206 .size = 0x00400000,
207 .offset = 0x00040000,
208 },{
209 .name = "Filesystem",
210 .size = MTDPART_SIZ_FULL,
211 .offset = 0x00440000
212 }
213};
214
215static struct flash_platform_data mst_flash_data[2] = {
216 {
217 .map_name = "cfi_probe",
218 .parts = mainstoneflash0_partitions,
219 .nr_parts = ARRAY_SIZE(mainstoneflash0_partitions),
220 }, {
221 .map_name = "cfi_probe",
222 .parts = NULL,
223 .nr_parts = 0,
224 }
225};
226
227static struct platform_device mst_flash_device[2] = {
228 {
229 .name = "pxa2xx-flash",
230 .id = 0,
231 .dev = {
232 .platform_data = &mst_flash_data[0],
233 },
234 .resource = &flash_resources[0],
235 .num_resources = 1,
236 },
237 {
238 .name = "pxa2xx-flash",
239 .id = 1,
240 .dev = {
241 .platform_data = &mst_flash_data[1],
242 },
243 .resource = &flash_resources[1],
244 .num_resources = 1,
245 },
246};
247
248#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
249static struct platform_pwm_backlight_data mainstone_backlight_data = {
250 .pwm_id = 0,
251 .max_brightness = 1023,
252 .dft_brightness = 1023,
253 .pwm_period_ns = 78770,
254};
255
256static struct platform_device mainstone_backlight_device = {
257 .name = "pwm-backlight",
258 .dev = {
259 .parent = &pxa27x_device_pwm0.dev,
260 .platform_data = &mainstone_backlight_data,
261 },
262};
263
264static void __init mainstone_backlight_register(void)
265{
266 int ret = platform_device_register(&mainstone_backlight_device);
267 if (ret)
268 printk(KERN_ERR "mainstone: failed to register backlight device: %d\n", ret);
269}
270#else
271#define mainstone_backlight_register() do { } while (0)
272#endif
273
274static struct pxafb_mode_info toshiba_ltm04c380k_mode = {
275 .pixclock = 50000,
276 .xres = 640,
277 .yres = 480,
278 .bpp = 16,
279 .hsync_len = 1,
280 .left_margin = 0x9f,
281 .right_margin = 1,
282 .vsync_len = 44,
283 .upper_margin = 0,
284 .lower_margin = 0,
285 .sync = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
286};
287
288static struct pxafb_mode_info toshiba_ltm035a776c_mode = {
289 .pixclock = 110000,
290 .xres = 240,
291 .yres = 320,
292 .bpp = 16,
293 .hsync_len = 4,
294 .left_margin = 8,
295 .right_margin = 20,
296 .vsync_len = 3,
297 .upper_margin = 1,
298 .lower_margin = 10,
299 .sync = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
300};
301
302static struct pxafb_mach_info mainstone_pxafb_info = {
303 .num_modes = 1,
304 .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
305};
306
307static int mainstone_mci_init(struct device *dev, irq_handler_t mstone_detect_int, void *data)
308{
309 int err;
310
311 /* make sure SD/Memory Stick multiplexer's signals
312 * are routed to MMC controller
313 */
314 MST_MSCWR1 &= ~MST_MSCWR1_MS_SEL;
315
316 err = request_irq(MAINSTONE_MMC_IRQ, mstone_detect_int, IRQF_DISABLED,
317 "MMC card detect", data);
318 if (err)
319 printk(KERN_ERR "mainstone_mci_init: MMC/SD: can't request MMC card detect IRQ\n");
320
321 return err;
322}
323
324static void mainstone_mci_setpower(struct device *dev, unsigned int vdd)
325{
326 struct pxamci_platform_data* p_d = dev->platform_data;
327
328 if (( 1 << vdd) & p_d->ocr_mask) {
329 printk(KERN_DEBUG "%s: on\n", __func__);
330 MST_MSCWR1 |= MST_MSCWR1_MMC_ON;
331 MST_MSCWR1 &= ~MST_MSCWR1_MS_SEL;
332 } else {
333 printk(KERN_DEBUG "%s: off\n", __func__);
334 MST_MSCWR1 &= ~MST_MSCWR1_MMC_ON;
335 }
336}
337
338static void mainstone_mci_exit(struct device *dev, void *data)
339{
340 free_irq(MAINSTONE_MMC_IRQ, data);
341}
342
343static struct pxamci_platform_data mainstone_mci_platform_data = {
344 .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
345 .init = mainstone_mci_init,
346 .setpower = mainstone_mci_setpower,
347 .exit = mainstone_mci_exit,
348 .gpio_card_detect = -1,
349 .gpio_card_ro = -1,
350 .gpio_power = -1,
351};
352
353static void mainstone_irda_transceiver_mode(struct device *dev, int mode)
354{
355 unsigned long flags;
356
357 local_irq_save(flags);
358 if (mode & IR_SIRMODE) {
359 MST_MSCWR1 &= ~MST_MSCWR1_IRDA_FIR;
360 } else if (mode & IR_FIRMODE) {
361 MST_MSCWR1 |= MST_MSCWR1_IRDA_FIR;
362 }
363 pxa2xx_transceiver_mode(dev, mode);
364 if (mode & IR_OFF) {
365 MST_MSCWR1 = (MST_MSCWR1 & ~MST_MSCWR1_IRDA_MASK) | MST_MSCWR1_IRDA_OFF;
366 } else {
367 MST_MSCWR1 = (MST_MSCWR1 & ~MST_MSCWR1_IRDA_MASK) | MST_MSCWR1_IRDA_FULL;
368 }
369 local_irq_restore(flags);
370}
371
372static struct pxaficp_platform_data mainstone_ficp_platform_data = {
373 .gpio_pwdown = -1,
374 .transceiver_cap = IR_SIRMODE | IR_FIRMODE | IR_OFF,
375 .transceiver_mode = mainstone_irda_transceiver_mode,
376};
377
378static struct gpio_keys_button gpio_keys_button[] = {
379 [0] = {
380 .desc = "wakeup",
381 .code = KEY_SUSPEND,
382 .type = EV_KEY,
383 .gpio = 1,
384 .wakeup = 1,
385 },
386};
387
388static struct gpio_keys_platform_data mainstone_gpio_keys = {
389 .buttons = gpio_keys_button,
390 .nbuttons = 1,
391};
392
393static struct platform_device mst_gpio_keys_device = {
394 .name = "gpio-keys",
395 .id = -1,
396 .dev = {
397 .platform_data = &mainstone_gpio_keys,
398 },
399};
400
401static struct resource mst_cplds_resources[] = {
402 [0] = {
403 .start = MST_FPGA_PHYS + 0xc0,
404 .end = MST_FPGA_PHYS + 0xe0 - 1,
405 .flags = IORESOURCE_MEM,
406 },
407 [1] = {
408 .start = PXA_GPIO_TO_IRQ(0),
409 .end = PXA_GPIO_TO_IRQ(0),
410 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
411 },
412 [2] = {
413 .start = MAINSTONE_IRQ(0),
414 .end = MAINSTONE_IRQ(15),
415 .flags = IORESOURCE_IRQ,
416 },
417};
418
419static struct platform_device mst_cplds_device = {
420 .name = "pxa_cplds_irqs",
421 .id = -1,
422 .resource = &mst_cplds_resources[0],
423 .num_resources = 3,
424};
425
426static struct platform_device *platform_devices[] __initdata = {
427 &smc91x_device,
428 &mst_flash_device[0],
429 &mst_flash_device[1],
430 &mst_gpio_keys_device,
431 &mst_cplds_device,
432};
433
434static struct pxaohci_platform_data mainstone_ohci_platform_data = {
435 .port_mode = PMM_PERPORT_MODE,
436 .flags = ENABLE_PORT_ALL | POWER_CONTROL_LOW | POWER_SENSE_LOW,
437};
438
439#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE)
440static unsigned int mainstone_matrix_keys[] = {
441 KEY(0, 0, KEY_A), KEY(1, 0, KEY_B), KEY(2, 0, KEY_C),
442 KEY(3, 0, KEY_D), KEY(4, 0, KEY_E), KEY(5, 0, KEY_F),
443 KEY(0, 1, KEY_G), KEY(1, 1, KEY_H), KEY(2, 1, KEY_I),
444 KEY(3, 1, KEY_J), KEY(4, 1, KEY_K), KEY(5, 1, KEY_L),
445 KEY(0, 2, KEY_M), KEY(1, 2, KEY_N), KEY(2, 2, KEY_O),
446 KEY(3, 2, KEY_P), KEY(4, 2, KEY_Q), KEY(5, 2, KEY_R),
447 KEY(0, 3, KEY_S), KEY(1, 3, KEY_T), KEY(2, 3, KEY_U),
448 KEY(3, 3, KEY_V), KEY(4, 3, KEY_W), KEY(5, 3, KEY_X),
449 KEY(2, 4, KEY_Y), KEY(3, 4, KEY_Z),
450
451 KEY(0, 4, KEY_DOT), /* . */
452 KEY(1, 4, KEY_CLOSE), /* @ */
453 KEY(4, 4, KEY_SLASH),
454 KEY(5, 4, KEY_BACKSLASH),
455 KEY(0, 5, KEY_HOME),
456 KEY(1, 5, KEY_LEFTSHIFT),
457 KEY(2, 5, KEY_SPACE),
458 KEY(3, 5, KEY_SPACE),
459 KEY(4, 5, KEY_ENTER),
460 KEY(5, 5, KEY_BACKSPACE),
461
462 KEY(0, 6, KEY_UP),
463 KEY(1, 6, KEY_DOWN),
464 KEY(2, 6, KEY_LEFT),
465 KEY(3, 6, KEY_RIGHT),
466 KEY(4, 6, KEY_SELECT),
467};
468
469struct pxa27x_keypad_platform_data mainstone_keypad_info = {
470 .matrix_key_rows = 6,
471 .matrix_key_cols = 7,
472 .matrix_key_map = mainstone_matrix_keys,
473 .matrix_key_map_size = ARRAY_SIZE(mainstone_matrix_keys),
474
475 .enable_rotary0 = 1,
476 .rotary0_up_key = KEY_UP,
477 .rotary0_down_key = KEY_DOWN,
478
479 .debounce_interval = 30,
480};
481
482static void __init mainstone_init_keypad(void)
483{
484 pxa_set_keypad_info(&mainstone_keypad_info);
485}
486#else
487static inline void mainstone_init_keypad(void) {}
488#endif
489
490static void __init mainstone_init(void)
491{
492 int SW7 = 0; /* FIXME: get from SCR (Mst doc section 3.2.1.1) */
493
494 pxa2xx_mfp_config(ARRAY_AND_SIZE(mainstone_pin_config));
495
496 pxa_set_ffuart_info(NULL);
497 pxa_set_btuart_info(NULL);
498 pxa_set_stuart_info(NULL);
499
500 mst_flash_data[0].width = (__raw_readl(BOOT_DEF) & 1) ? 2 : 4;
501 mst_flash_data[1].width = 4;
502
503 /* Compensate for SW7 which swaps the flash banks */
504 mst_flash_data[SW7].name = "processor-flash";
505 mst_flash_data[SW7 ^ 1].name = "mainboard-flash";
506
507 printk(KERN_NOTICE "Mainstone configured to boot from %s\n",
508 mst_flash_data[0].name);
509
510 /* system bus arbiter setting
511 * - Core_Park
512 * - LCD_wt:DMA_wt:CORE_Wt = 2:3:4
513 */
514 ARB_CNTRL = ARB_CORE_PARK | 0x234;
515
516 platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
517
518 /* reading Mainstone's "Virtual Configuration Register"
519 might be handy to select LCD type here */
520 if (0)
521 mainstone_pxafb_info.modes = &toshiba_ltm04c380k_mode;
522 else
523 mainstone_pxafb_info.modes = &toshiba_ltm035a776c_mode;
524
525 pxa_set_fb_info(NULL, &mainstone_pxafb_info);
526 mainstone_backlight_register();
527
528 pxa_set_mci_info(&mainstone_mci_platform_data);
529 pxa_set_ficp_info(&mainstone_ficp_platform_data);
530 pxa_set_ohci_info(&mainstone_ohci_platform_data);
531 pxa_set_i2c_info(NULL);
532 pxa_set_ac97_info(&mst_audio_ops);
533
534 mainstone_init_keypad();
535}
536
537
538static struct map_desc mainstone_io_desc[] __initdata = {
539 { /* CPLD */
540 .virtual = MST_FPGA_VIRT,
541 .pfn = __phys_to_pfn(MST_FPGA_PHYS),
542 .length = 0x00100000,
543 .type = MT_DEVICE
544 }
545};
546
547static void __init mainstone_map_io(void)
548{
549 pxa27x_map_io();
550 iotable_init(mainstone_io_desc, ARRAY_SIZE(mainstone_io_desc));
551
552 /* for use I SRAM as framebuffer. */
553 PSLR |= 0xF04;
554 PCFR = 0x66;
555}
556
557MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
558 /* Maintainer: MontaVista Software Inc. */
559 .atag_offset = 0x100, /* BLOB boot parameter setting */
560 .map_io = mainstone_map_io,
561 .nr_irqs = MAINSTONE_NR_IRQS,
562 .init_irq = pxa27x_init_irq,
563 .handle_irq = pxa27x_handle_irq,
564 .timer = &pxa_timer,
565 .init_machine = mainstone_init,
566 .restart = pxa_restart,
567MACHINE_END