1/* linux/arch/arm/mach-s3c2440/mach-mini2440.c 2 * 3 * Copyright (c) 2008 Ramax Lo <ramaxlo@gmail.com> 4 * Based on mach-anubis.c by Ben Dooks <ben@simtec.co.uk> 5 * and modifications by SBZ <sbz@spgui.org> and 6 * Weibing <http://weibing.blogbus.com> and 7 * Michel Pollet <buserror@gmail.com> 8 * 9 * For product information, visit http://code.google.com/p/mini2440/ 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 16#include <linux/kernel.h> 17#include <linux/types.h> 18#include <linux/interrupt.h> 19#include <linux/list.h> 20#include <linux/timer.h> 21#include <linux/init.h> 22#include <linux/gpio.h> 23#include <linux/input.h> 24#include <linux/io.h> 25#include <linux/serial_core.h> 26#include <linux/dm9000.h> 27#include <linux/i2c/at24.h> 28#include <linux/platform_device.h> 29#include <linux/gpio_keys.h> 30#include <linux/i2c.h> 31#include <linux/mmc/host.h> 32 33#include <asm/mach/arch.h> 34#include <asm/mach/map.h> 35 36#include <mach/hardware.h> 37#include <mach/fb.h> 38#include <asm/mach-types.h> 39 40#include <plat/regs-serial.h> 41#include <mach/regs-gpio.h> 42#include <mach/leds-gpio.h> 43#include <mach/regs-mem.h> 44#include <mach/regs-lcd.h> 45#include <mach/irqs.h> 46#include <plat/nand.h> 47#include <plat/iic.h> 48#include <plat/mci.h> 49#include <plat/udc.h> 50 51#include <linux/mtd/mtd.h> 52#include <linux/mtd/nand.h> 53#include <linux/mtd/nand_ecc.h> 54#include <linux/mtd/partitions.h> 55 56#include <plat/gpio-cfg.h> 57#include <plat/clock.h> 58#include <plat/devs.h> 59#include <plat/cpu.h> 60 61#include <sound/s3c24xx_uda134x.h> 62 63#define MACH_MINI2440_DM9K_BASE (S3C2410_CS4 + 0x300) 64 65static struct map_desc mini2440_iodesc[] __initdata = { 66 /* nothing to declare, move along */ 67}; 68 69#define UCON S3C2410_UCON_DEFAULT 70#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB 71#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE 72 73 74static struct s3c2410_uartcfg mini2440_uartcfgs[] __initdata = { 75 [0] = { 76 .hwport = 0, 77 .flags = 0, 78 .ucon = UCON, 79 .ulcon = ULCON, 80 .ufcon = UFCON, 81 }, 82 [1] = { 83 .hwport = 1, 84 .flags = 0, 85 .ucon = UCON, 86 .ulcon = ULCON, 87 .ufcon = UFCON, 88 }, 89 [2] = { 90 .hwport = 2, 91 .flags = 0, 92 .ucon = UCON, 93 .ulcon = ULCON, 94 .ufcon = UFCON, 95 }, 96}; 97 98/* USB device UDC support */ 99 100static void mini2440_udc_pullup(enum s3c2410_udc_cmd_e cmd) 101{ 102 pr_debug("udc: pullup(%d)\n", cmd); 103 104 switch (cmd) { 105 case S3C2410_UDC_P_ENABLE : 106 gpio_set_value(S3C2410_GPC(5), 1); 107 break; 108 case S3C2410_UDC_P_DISABLE : 109 gpio_set_value(S3C2410_GPC(5), 0); 110 break; 111 case S3C2410_UDC_P_RESET : 112 break; 113 default: 114 break; 115 } 116} 117 118static struct s3c2410_udc_mach_info mini2440_udc_cfg __initdata = { 119 .udc_command = mini2440_udc_pullup, 120}; 121 122 123/* LCD timing and setup */ 124 125/* 126 * This macro simplifies the table bellow 127 */ 128#define _LCD_DECLARE(_clock,_xres,margin_left,margin_right,hsync, \ 129 _yres,margin_top,margin_bottom,vsync, refresh) \ 130 .width = _xres, \ 131 .xres = _xres, \ 132 .height = _yres, \ 133 .yres = _yres, \ 134 .left_margin = margin_left, \ 135 .right_margin = margin_right, \ 136 .upper_margin = margin_top, \ 137 .lower_margin = margin_bottom, \ 138 .hsync_len = hsync, \ 139 .vsync_len = vsync, \ 140 .pixclock = ((_clock*100000000000LL) / \ 141 ((refresh) * \ 142 (hsync + margin_left + _xres + margin_right) * \ 143 (vsync + margin_top + _yres + margin_bottom))), \ 144 .bpp = 16,\ 145 .type = (S3C2410_LCDCON1_TFT16BPP |\ 146 S3C2410_LCDCON1_TFT) 147 148static struct s3c2410fb_display mini2440_lcd_cfg[] __initdata = { 149 [0] = { /* mini2440 + 3.5" TFT + touchscreen */ 150 _LCD_DECLARE( 151 7, /* The 3.5 is quite fast */ 152 240, 21, 38, 6, /* x timing */ 153 320, 4, 4, 2, /* y timing */ 154 60), /* refresh rate */ 155 .lcdcon5 = (S3C2410_LCDCON5_FRM565 | 156 S3C2410_LCDCON5_INVVLINE | 157 S3C2410_LCDCON5_INVVFRAME | 158 S3C2410_LCDCON5_INVVDEN | 159 S3C2410_LCDCON5_PWREN), 160 }, 161 [1] = { /* mini2440 + 7" TFT + touchscreen */ 162 _LCD_DECLARE( 163 10, /* the 7" runs slower */ 164 800, 40, 40, 48, /* x timing */ 165 480, 29, 3, 3, /* y timing */ 166 50), /* refresh rate */ 167 .lcdcon5 = (S3C2410_LCDCON5_FRM565 | 168 S3C2410_LCDCON5_INVVLINE | 169 S3C2410_LCDCON5_INVVFRAME | 170 S3C2410_LCDCON5_PWREN), 171 }, 172 /* The VGA shield can outout at several resolutions. All share 173 * the same timings, however, anything smaller than 1024x768 174 * will only be displayed in the top left corner of a 1024x768 175 * XGA output unless you add optional dip switches to the shield. 176 * Therefore timings for other resolutions have been ommited here. 177 */ 178 [2] = { 179 _LCD_DECLARE( 180 10, 181 1024, 1, 2, 2, /* y timing */ 182 768, 200, 16, 16, /* x timing */ 183 24), /* refresh rate, maximum stable, 184 tested with the FPGA shield */ 185 .lcdcon5 = (S3C2410_LCDCON5_FRM565 | 186 S3C2410_LCDCON5_HWSWP), 187 }, 188}; 189 190/* todo - put into gpio header */ 191 192#define S3C2410_GPCCON_MASK(x) (3 << ((x) * 2)) 193#define S3C2410_GPDCON_MASK(x) (3 << ((x) * 2)) 194 195static struct s3c2410fb_mach_info mini2440_fb_info __initdata = { 196 .displays = &mini2440_lcd_cfg[0], /* not constant! see init */ 197 .num_displays = 1, 198 .default_display = 0, 199 200 /* Enable VD[2..7], VD[10..15], VD[18..23] and VCLK, syncs, VDEN 201 * and disable the pull down resistors on pins we are using for LCD 202 * data. */ 203 204 .gpcup = (0xf << 1) | (0x3f << 10), 205 206 .gpccon = (S3C2410_GPC1_VCLK | S3C2410_GPC2_VLINE | 207 S3C2410_GPC3_VFRAME | S3C2410_GPC4_VM | 208 S3C2410_GPC10_VD2 | S3C2410_GPC11_VD3 | 209 S3C2410_GPC12_VD4 | S3C2410_GPC13_VD5 | 210 S3C2410_GPC14_VD6 | S3C2410_GPC15_VD7), 211 212 .gpccon_mask = (S3C2410_GPCCON_MASK(1) | S3C2410_GPCCON_MASK(2) | 213 S3C2410_GPCCON_MASK(3) | S3C2410_GPCCON_MASK(4) | 214 S3C2410_GPCCON_MASK(10) | S3C2410_GPCCON_MASK(11) | 215 S3C2410_GPCCON_MASK(12) | S3C2410_GPCCON_MASK(13) | 216 S3C2410_GPCCON_MASK(14) | S3C2410_GPCCON_MASK(15)), 217 218 .gpdup = (0x3f << 2) | (0x3f << 10), 219 220 .gpdcon = (S3C2410_GPD2_VD10 | S3C2410_GPD3_VD11 | 221 S3C2410_GPD4_VD12 | S3C2410_GPD5_VD13 | 222 S3C2410_GPD6_VD14 | S3C2410_GPD7_VD15 | 223 S3C2410_GPD10_VD18 | S3C2410_GPD11_VD19 | 224 S3C2410_GPD12_VD20 | S3C2410_GPD13_VD21 | 225 S3C2410_GPD14_VD22 | S3C2410_GPD15_VD23), 226 227 .gpdcon_mask = (S3C2410_GPDCON_MASK(2) | S3C2410_GPDCON_MASK(3) | 228 S3C2410_GPDCON_MASK(4) | S3C2410_GPDCON_MASK(5) | 229 S3C2410_GPDCON_MASK(6) | S3C2410_GPDCON_MASK(7) | 230 S3C2410_GPDCON_MASK(10) | S3C2410_GPDCON_MASK(11)| 231 S3C2410_GPDCON_MASK(12) | S3C2410_GPDCON_MASK(13)| 232 S3C2410_GPDCON_MASK(14) | S3C2410_GPDCON_MASK(15)), 233}; 234 235/* MMC/SD */ 236 237static struct s3c24xx_mci_pdata mini2440_mmc_cfg __initdata = { 238 .gpio_detect = S3C2410_GPG(8), 239 .gpio_wprotect = S3C2410_GPH(8), 240 .set_power = NULL, 241 .ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34, 242}; 243 244/* NAND Flash on MINI2440 board */ 245 246static struct mtd_partition mini2440_default_nand_part[] __initdata = { 247 [0] = { 248 .name = "u-boot", 249 .size = SZ_256K, 250 .offset = 0, 251 }, 252 [1] = { 253 .name = "u-boot-env", 254 .size = SZ_128K, 255 .offset = SZ_256K, 256 }, 257 [2] = { 258 .name = "kernel", 259 /* 5 megabytes, for a kernel with no modules 260 * or a uImage with a ramdisk attached */ 261 .size = 0x00500000, 262 .offset = SZ_256K + SZ_128K, 263 }, 264 [3] = { 265 .name = "root", 266 .offset = SZ_256K + SZ_128K + 0x00500000, 267 .size = MTDPART_SIZ_FULL, 268 }, 269}; 270 271static struct s3c2410_nand_set mini2440_nand_sets[] __initdata = { 272 [0] = { 273 .name = "nand", 274 .nr_chips = 1, 275 .nr_partitions = ARRAY_SIZE(mini2440_default_nand_part), 276 .partitions = mini2440_default_nand_part, 277 .flash_bbt = 1, /* we use u-boot to create a BBT */ 278 }, 279}; 280 281static struct s3c2410_platform_nand mini2440_nand_info __initdata = { 282 .tacls = 0, 283 .twrph0 = 25, 284 .twrph1 = 15, 285 .nr_sets = ARRAY_SIZE(mini2440_nand_sets), 286 .sets = mini2440_nand_sets, 287 .ignore_unset_ecc = 1, 288}; 289 290/* DM9000AEP 10/100 ethernet controller */ 291 292static struct resource mini2440_dm9k_resource[] = { 293 [0] = { 294 .start = MACH_MINI2440_DM9K_BASE, 295 .end = MACH_MINI2440_DM9K_BASE + 3, 296 .flags = IORESOURCE_MEM 297 }, 298 [1] = { 299 .start = MACH_MINI2440_DM9K_BASE + 4, 300 .end = MACH_MINI2440_DM9K_BASE + 7, 301 .flags = IORESOURCE_MEM 302 }, 303 [2] = { 304 .start = IRQ_EINT7, 305 .end = IRQ_EINT7, 306 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, 307 } 308}; 309 310/* 311 * The DM9000 has no eeprom, and it's MAC address is set by 312 * the bootloader before starting the kernel. 313 */ 314static struct dm9000_plat_data mini2440_dm9k_pdata = { 315 .flags = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM), 316}; 317 318static struct platform_device mini2440_device_eth = { 319 .name = "dm9000", 320 .id = -1, 321 .num_resources = ARRAY_SIZE(mini2440_dm9k_resource), 322 .resource = mini2440_dm9k_resource, 323 .dev = { 324 .platform_data = &mini2440_dm9k_pdata, 325 }, 326}; 327 328/* CON5 329 * +--+ /-----\ 330 * | | | | 331 * | | | BAT | 332 * | | \_____/ 333 * | | 334 * | | +----+ +----+ 335 * | | | K5 | | K1 | 336 * | | +----+ +----+ 337 * | | +----+ +----+ 338 * | | | K4 | | K2 | 339 * | | +----+ +----+ 340 * | | +----+ +----+ 341 * | | | K6 | | K3 | 342 * | | +----+ +----+ 343 * ..... 344 */ 345static struct gpio_keys_button mini2440_buttons[] = { 346 { 347 .gpio = S3C2410_GPG(0), /* K1 */ 348 .code = KEY_F1, 349 .desc = "Button 1", 350 .active_low = 1, 351 }, 352 { 353 .gpio = S3C2410_GPG(3), /* K2 */ 354 .code = KEY_F2, 355 .desc = "Button 2", 356 .active_low = 1, 357 }, 358 { 359 .gpio = S3C2410_GPG(5), /* K3 */ 360 .code = KEY_F3, 361 .desc = "Button 3", 362 .active_low = 1, 363 }, 364 { 365 .gpio = S3C2410_GPG(6), /* K4 */ 366 .code = KEY_POWER, 367 .desc = "Power", 368 .active_low = 1, 369 }, 370 { 371 .gpio = S3C2410_GPG(7), /* K5 */ 372 .code = KEY_F5, 373 .desc = "Button 5", 374 .active_low = 1, 375 }, 376}; 377 378static struct gpio_keys_platform_data mini2440_button_data = { 379 .buttons = mini2440_buttons, 380 .nbuttons = ARRAY_SIZE(mini2440_buttons), 381}; 382 383static struct platform_device mini2440_button_device = { 384 .name = "gpio-keys", 385 .id = -1, 386 .dev = { 387 .platform_data = &mini2440_button_data, 388 } 389}; 390 391/* LEDS */ 392 393static struct s3c24xx_led_platdata mini2440_led1_pdata = { 394 .name = "led1", 395 .gpio = S3C2410_GPB(5), 396 .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE, 397 .def_trigger = "heartbeat", 398}; 399 400static struct s3c24xx_led_platdata mini2440_led2_pdata = { 401 .name = "led2", 402 .gpio = S3C2410_GPB(6), 403 .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE, 404 .def_trigger = "nand-disk", 405}; 406 407static struct s3c24xx_led_platdata mini2440_led3_pdata = { 408 .name = "led3", 409 .gpio = S3C2410_GPB(7), 410 .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE, 411 .def_trigger = "mmc0", 412}; 413 414static struct s3c24xx_led_platdata mini2440_led4_pdata = { 415 .name = "led4", 416 .gpio = S3C2410_GPB(8), 417 .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE, 418 .def_trigger = "", 419}; 420 421static struct s3c24xx_led_platdata mini2440_led_backlight_pdata = { 422 .name = "backlight", 423 .gpio = S3C2410_GPG(4), 424 .def_trigger = "backlight", 425}; 426 427static struct platform_device mini2440_led1 = { 428 .name = "s3c24xx_led", 429 .id = 1, 430 .dev = { 431 .platform_data = &mini2440_led1_pdata, 432 }, 433}; 434 435static struct platform_device mini2440_led2 = { 436 .name = "s3c24xx_led", 437 .id = 2, 438 .dev = { 439 .platform_data = &mini2440_led2_pdata, 440 }, 441}; 442 443static struct platform_device mini2440_led3 = { 444 .name = "s3c24xx_led", 445 .id = 3, 446 .dev = { 447 .platform_data = &mini2440_led3_pdata, 448 }, 449}; 450 451static struct platform_device mini2440_led4 = { 452 .name = "s3c24xx_led", 453 .id = 4, 454 .dev = { 455 .platform_data = &mini2440_led4_pdata, 456 }, 457}; 458 459static struct platform_device mini2440_led_backlight = { 460 .name = "s3c24xx_led", 461 .id = 5, 462 .dev = { 463 .platform_data = &mini2440_led_backlight_pdata, 464 }, 465}; 466 467/* AUDIO */ 468 469static struct s3c24xx_uda134x_platform_data mini2440_audio_pins = { 470 .l3_clk = S3C2410_GPB(4), 471 .l3_mode = S3C2410_GPB(2), 472 .l3_data = S3C2410_GPB(3), 473 .model = UDA134X_UDA1341 474}; 475 476static struct platform_device mini2440_audio = { 477 .name = "s3c24xx_uda134x", 478 .id = 0, 479 .dev = { 480 .platform_data = &mini2440_audio_pins, 481 }, 482}; 483 484/* 485 * I2C devices 486 */ 487static struct at24_platform_data at24c08 = { 488 .byte_len = SZ_8K / 8, 489 .page_size = 16, 490}; 491 492static struct i2c_board_info mini2440_i2c_devs[] __initdata = { 493 { 494 I2C_BOARD_INFO("24c08", 0x50), 495 .platform_data = &at24c08, 496 }, 497}; 498 499static struct platform_device *mini2440_devices[] __initdata = { 500 &s3c_device_ohci, 501 &s3c_device_wdt, 502 &s3c_device_i2c0, 503 &s3c_device_rtc, 504 &s3c_device_usbgadget, 505 &mini2440_device_eth, 506 &mini2440_led1, 507 &mini2440_led2, 508 &mini2440_led3, 509 &mini2440_led4, 510 &mini2440_button_device, 511 &s3c_device_nand, 512 &s3c_device_sdi, 513 &s3c_device_iis, 514 &mini2440_audio, 515}; 516 517static void __init mini2440_map_io(void) 518{ 519 s3c24xx_init_io(mini2440_iodesc, ARRAY_SIZE(mini2440_iodesc)); 520 s3c24xx_init_clocks(12000000); 521 s3c24xx_init_uarts(mini2440_uartcfgs, ARRAY_SIZE(mini2440_uartcfgs)); 522} 523 524/* 525 * mini2440_features string 526 * 527 * t = Touchscreen present 528 * b = backlight control 529 * c = camera [TODO] 530 * 0-9 LCD configuration 531 * 532 */ 533static char mini2440_features_str[12] __initdata = "0tb"; 534 535static int __init mini2440_features_setup(char *str) 536{ 537 if (str) 538 strlcpy(mini2440_features_str, str, sizeof(mini2440_features_str)); 539 return 1; 540} 541 542__setup("mini2440=", mini2440_features_setup); 543 544#define FEATURE_SCREEN (1 << 0) 545#define FEATURE_BACKLIGHT (1 << 1) 546#define FEATURE_TOUCH (1 << 2) 547#define FEATURE_CAMERA (1 << 3) 548 549struct mini2440_features_t { 550 int count; 551 int done; 552 int lcd_index; 553 struct platform_device *optional[8]; 554}; 555 556static void mini2440_parse_features( 557 struct mini2440_features_t * features, 558 const char * features_str ) 559{ 560 const char * fp = features_str; 561 562 features->count = 0; 563 features->done = 0; 564 features->lcd_index = -1; 565 566 while (*fp) { 567 char f = *fp++; 568 569 switch (f) { 570 case '0'...'9': /* tft screen */ 571 if (features->done & FEATURE_SCREEN) { 572 printk(KERN_INFO "MINI2440: '%c' ignored, " 573 "screen type already set\n", f); 574 } else { 575 int li = f - '0'; 576 if (li >= ARRAY_SIZE(mini2440_lcd_cfg)) 577 printk(KERN_INFO "MINI2440: " 578 "'%c' out of range LCD mode\n", f); 579 else { 580 features->optional[features->count++] = 581 &s3c_device_lcd; 582 features->lcd_index = li; 583 } 584 } 585 features->done |= FEATURE_SCREEN; 586 break; 587 case 'b': 588 if (features->done & FEATURE_BACKLIGHT) 589 printk(KERN_INFO "MINI2440: '%c' ignored, " 590 "backlight already set\n", f); 591 else { 592 features->optional[features->count++] = 593 &mini2440_led_backlight; 594 } 595 features->done |= FEATURE_BACKLIGHT; 596 break; 597 case 't': 598 printk(KERN_INFO "MINI2440: '%c' ignored, " 599 "touchscreen not compiled in\n", f); 600 break; 601 case 'c': 602 if (features->done & FEATURE_CAMERA) 603 printk(KERN_INFO "MINI2440: '%c' ignored, " 604 "camera already registered\n", f); 605 else 606 features->optional[features->count++] = 607 &s3c_device_camif; 608 features->done |= FEATURE_CAMERA; 609 break; 610 } 611 } 612} 613 614static void __init mini2440_init(void) 615{ 616 struct mini2440_features_t features = { 0 }; 617 int i; 618 619 printk(KERN_INFO "MINI2440: Option string mini2440=%s\n", 620 mini2440_features_str); 621 622 /* Parse the feature string */ 623 mini2440_parse_features(&features, mini2440_features_str); 624 625 /* turn LCD on */ 626 s3c_gpio_cfgpin(S3C2410_GPC(0), S3C2410_GPC0_LEND); 627 628 /* Turn the backlight early on */ 629 WARN_ON(gpio_request(S3C2410_GPG(4), "backlight")); 630 gpio_direction_output(S3C2410_GPG(4), 1); 631 632 /* remove pullup on optional PWM backlight -- unused on 3.5 and 7"s */ 633 s3c_gpio_setpull(S3C2410_GPB(1), S3C_GPIO_PULL_UP); 634 s3c2410_gpio_setpin(S3C2410_GPB(1), 0); 635 s3c_gpio_cfgpin(S3C2410_GPB(1), S3C2410_GPIO_INPUT); 636 637 /* Make sure the D+ pullup pin is output */ 638 WARN_ON(gpio_request(S3C2410_GPC(5), "udc pup")); 639 gpio_direction_output(S3C2410_GPC(5), 0); 640 641 /* mark the key as input, without pullups (there is one on the board) */ 642 for (i = 0; i < ARRAY_SIZE(mini2440_buttons); i++) { 643 s3c_gpio_setpull(mini2440_buttons[i].gpio, S3C_GPIO_PULL_UP); 644 s3c_gpio_cfgpin(mini2440_buttons[i].gpio, S3C2410_GPIO_INPUT); 645 } 646 if (features.lcd_index != -1) { 647 int li; 648 649 mini2440_fb_info.displays = 650 &mini2440_lcd_cfg[features.lcd_index]; 651 652 printk(KERN_INFO "MINI2440: LCD"); 653 for (li = 0; li < ARRAY_SIZE(mini2440_lcd_cfg); li++) 654 if (li == features.lcd_index) 655 printk(" [%d:%dx%d]", li, 656 mini2440_lcd_cfg[li].width, 657 mini2440_lcd_cfg[li].height); 658 else 659 printk(" %d:%dx%d", li, 660 mini2440_lcd_cfg[li].width, 661 mini2440_lcd_cfg[li].height); 662 printk("\n"); 663 s3c24xx_fb_set_platdata(&mini2440_fb_info); 664 } 665 666 s3c24xx_udc_set_platdata(&mini2440_udc_cfg); 667 s3c24xx_mci_set_platdata(&mini2440_mmc_cfg); 668 s3c_nand_set_platdata(&mini2440_nand_info); 669 s3c_i2c0_set_platdata(NULL); 670 671 i2c_register_board_info(0, mini2440_i2c_devs, 672 ARRAY_SIZE(mini2440_i2c_devs)); 673 674 platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices)); 675 676 if (features.count) /* the optional features */ 677 platform_add_devices(features.optional, features.count); 678 679} 680 681 682MACHINE_START(MINI2440, "MINI2440") 683 /* Maintainer: Michel Pollet <buserror@gmail.com> */ 684 .phys_io = S3C2410_PA_UART, 685 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, 686 .boot_params = S3C2410_SDRAM_PA + 0x100, 687 .map_io = mini2440_map_io, 688 .init_machine = mini2440_init, 689 .init_irq = s3c24xx_init_irq, 690 .timer = &s3c24xx_timer, 691MACHINE_END 692