1/* linux/arch/arm/mach-s3c2410/mach-bast.c 2 * 3 * Copyright 2003-2008 Simtec Electronics 4 * Ben Dooks <ben@simtec.co.uk> 5 * 6 * http://www.simtec.co.uk/products/EB2410ITX/ 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11*/ 12 13#include <linux/kernel.h> 14#include <linux/types.h> 15#include <linux/interrupt.h> 16#include <linux/list.h> 17#include <linux/timer.h> 18#include <linux/init.h> 19#include <linux/gpio.h> 20#include <linux/syscore_ops.h> 21#include <linux/serial_core.h> 22#include <linux/serial_s3c.h> 23#include <linux/platform_device.h> 24#include <linux/dm9000.h> 25#include <linux/ata_platform.h> 26#include <linux/i2c.h> 27#include <linux/io.h> 28#include <linux/serial_8250.h> 29 30#include <linux/mtd/mtd.h> 31#include <linux/mtd/nand.h> 32#include <linux/mtd/nand_ecc.h> 33#include <linux/mtd/partitions.h> 34 35#include <linux/platform_data/asoc-s3c24xx_simtec.h> 36#include <linux/platform_data/hwmon-s3c.h> 37#include <linux/platform_data/i2c-s3c2410.h> 38#include <linux/platform_data/mtd-nand-s3c2410.h> 39 40#include <net/ax88796.h> 41 42#include <asm/irq.h> 43#include <asm/mach/arch.h> 44#include <asm/mach/map.h> 45#include <asm/mach/irq.h> 46#include <asm/mach-types.h> 47 48#include <mach/fb.h> 49#include <mach/hardware.h> 50#include <mach/regs-gpio.h> 51#include <mach/regs-lcd.h> 52#include <mach/gpio-samsung.h> 53 54#include <plat/cpu.h> 55#include <plat/cpu-freq.h> 56#include <plat/devs.h> 57#include <plat/gpio-cfg.h> 58#include <plat/samsung-time.h> 59 60#include "bast.h" 61#include "common.h" 62#include "simtec.h" 63 64#define COPYRIGHT ", Copyright 2004-2008 Simtec Electronics" 65 66/* macros for virtual address mods for the io space entries */ 67#define VA_C5(item) ((unsigned long)(item) + BAST_VAM_CS5) 68#define VA_C4(item) ((unsigned long)(item) + BAST_VAM_CS4) 69#define VA_C3(item) ((unsigned long)(item) + BAST_VAM_CS3) 70#define VA_C2(item) ((unsigned long)(item) + BAST_VAM_CS2) 71 72/* macros to modify the physical addresses for io space */ 73 74#define PA_CS2(item) (__phys_to_pfn((item) + S3C2410_CS2)) 75#define PA_CS3(item) (__phys_to_pfn((item) + S3C2410_CS3)) 76#define PA_CS4(item) (__phys_to_pfn((item) + S3C2410_CS4)) 77#define PA_CS5(item) (__phys_to_pfn((item) + S3C2410_CS5)) 78 79static struct map_desc bast_iodesc[] __initdata = { 80 /* ISA IO areas */ 81 { 82 .virtual = (u32)S3C24XX_VA_ISA_BYTE, 83 .pfn = PA_CS2(BAST_PA_ISAIO), 84 .length = SZ_16M, 85 .type = MT_DEVICE, 86 }, { 87 .virtual = (u32)S3C24XX_VA_ISA_WORD, 88 .pfn = PA_CS3(BAST_PA_ISAIO), 89 .length = SZ_16M, 90 .type = MT_DEVICE, 91 }, 92 /* bast CPLD control registers, and external interrupt controls */ 93 { 94 .virtual = (u32)BAST_VA_CTRL1, 95 .pfn = __phys_to_pfn(BAST_PA_CTRL1), 96 .length = SZ_1M, 97 .type = MT_DEVICE, 98 }, { 99 .virtual = (u32)BAST_VA_CTRL2, 100 .pfn = __phys_to_pfn(BAST_PA_CTRL2), 101 .length = SZ_1M, 102 .type = MT_DEVICE, 103 }, { 104 .virtual = (u32)BAST_VA_CTRL3, 105 .pfn = __phys_to_pfn(BAST_PA_CTRL3), 106 .length = SZ_1M, 107 .type = MT_DEVICE, 108 }, { 109 .virtual = (u32)BAST_VA_CTRL4, 110 .pfn = __phys_to_pfn(BAST_PA_CTRL4), 111 .length = SZ_1M, 112 .type = MT_DEVICE, 113 }, 114 /* PC104 IRQ mux */ 115 { 116 .virtual = (u32)BAST_VA_PC104_IRQREQ, 117 .pfn = __phys_to_pfn(BAST_PA_PC104_IRQREQ), 118 .length = SZ_1M, 119 .type = MT_DEVICE, 120 }, { 121 .virtual = (u32)BAST_VA_PC104_IRQRAW, 122 .pfn = __phys_to_pfn(BAST_PA_PC104_IRQRAW), 123 .length = SZ_1M, 124 .type = MT_DEVICE, 125 }, { 126 .virtual = (u32)BAST_VA_PC104_IRQMASK, 127 .pfn = __phys_to_pfn(BAST_PA_PC104_IRQMASK), 128 .length = SZ_1M, 129 .type = MT_DEVICE, 130 }, 131 132 /* peripheral space... one for each of fast/slow/byte/16bit */ 133 /* note, ide is only decoded in word space, even though some registers 134 * are only 8bit */ 135 136 /* slow, byte */ 137 { VA_C2(BAST_VA_ISAIO), PA_CS2(BAST_PA_ISAIO), SZ_16M, MT_DEVICE }, 138 { VA_C2(BAST_VA_ISAMEM), PA_CS2(BAST_PA_ISAMEM), SZ_16M, MT_DEVICE }, 139 { VA_C2(BAST_VA_SUPERIO), PA_CS2(BAST_PA_SUPERIO), SZ_1M, MT_DEVICE }, 140 141 /* slow, word */ 142 { VA_C3(BAST_VA_ISAIO), PA_CS3(BAST_PA_ISAIO), SZ_16M, MT_DEVICE }, 143 { VA_C3(BAST_VA_ISAMEM), PA_CS3(BAST_PA_ISAMEM), SZ_16M, MT_DEVICE }, 144 { VA_C3(BAST_VA_SUPERIO), PA_CS3(BAST_PA_SUPERIO), SZ_1M, MT_DEVICE }, 145 146 /* fast, byte */ 147 { VA_C4(BAST_VA_ISAIO), PA_CS4(BAST_PA_ISAIO), SZ_16M, MT_DEVICE }, 148 { VA_C4(BAST_VA_ISAMEM), PA_CS4(BAST_PA_ISAMEM), SZ_16M, MT_DEVICE }, 149 { VA_C4(BAST_VA_SUPERIO), PA_CS4(BAST_PA_SUPERIO), SZ_1M, MT_DEVICE }, 150 151 /* fast, word */ 152 { VA_C5(BAST_VA_ISAIO), PA_CS5(BAST_PA_ISAIO), SZ_16M, MT_DEVICE }, 153 { VA_C5(BAST_VA_ISAMEM), PA_CS5(BAST_PA_ISAMEM), SZ_16M, MT_DEVICE }, 154 { VA_C5(BAST_VA_SUPERIO), PA_CS5(BAST_PA_SUPERIO), SZ_1M, MT_DEVICE }, 155}; 156 157#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK 158#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB 159#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE 160 161static struct s3c2410_uartcfg bast_uartcfgs[] __initdata = { 162 [0] = { 163 .hwport = 0, 164 .flags = 0, 165 .ucon = UCON, 166 .ulcon = ULCON, 167 .ufcon = UFCON, 168 }, 169 [1] = { 170 .hwport = 1, 171 .flags = 0, 172 .ucon = UCON, 173 .ulcon = ULCON, 174 .ufcon = UFCON, 175 }, 176 /* port 2 is not actually used */ 177 [2] = { 178 .hwport = 2, 179 .flags = 0, 180 .ucon = UCON, 181 .ulcon = ULCON, 182 .ufcon = UFCON, 183 } 184}; 185 186/* NAND Flash on BAST board */ 187 188#ifdef CONFIG_PM 189static int bast_pm_suspend(void) 190{ 191 /* ensure that an nRESET is not generated on resume. */ 192 gpio_direction_output(S3C2410_GPA(21), 1); 193 return 0; 194} 195 196static void bast_pm_resume(void) 197{ 198 s3c_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPA21_nRSTOUT); 199} 200 201#else 202#define bast_pm_suspend NULL 203#define bast_pm_resume NULL 204#endif 205 206static struct syscore_ops bast_pm_syscore_ops = { 207 .suspend = bast_pm_suspend, 208 .resume = bast_pm_resume, 209}; 210 211static int smartmedia_map[] = { 0 }; 212static int chip0_map[] = { 1 }; 213static int chip1_map[] = { 2 }; 214static int chip2_map[] = { 3 }; 215 216static struct mtd_partition __initdata bast_default_nand_part[] = { 217 [0] = { 218 .name = "Boot Agent", 219 .size = SZ_16K, 220 .offset = 0, 221 }, 222 [1] = { 223 .name = "/boot", 224 .size = SZ_4M - SZ_16K, 225 .offset = SZ_16K, 226 }, 227 [2] = { 228 .name = "user", 229 .offset = SZ_4M, 230 .size = MTDPART_SIZ_FULL, 231 } 232}; 233 234/* the bast has 4 selectable slots for nand-flash, the three 235 * on-board chip areas, as well as the external SmartMedia 236 * slot. 237 * 238 * Note, there is no current hot-plug support for the SmartMedia 239 * socket. 240*/ 241 242static struct s3c2410_nand_set __initdata bast_nand_sets[] = { 243 [0] = { 244 .name = "SmartMedia", 245 .nr_chips = 1, 246 .nr_map = smartmedia_map, 247 .options = NAND_SCAN_SILENT_NODEV, 248 .nr_partitions = ARRAY_SIZE(bast_default_nand_part), 249 .partitions = bast_default_nand_part, 250 }, 251 [1] = { 252 .name = "chip0", 253 .nr_chips = 1, 254 .nr_map = chip0_map, 255 .nr_partitions = ARRAY_SIZE(bast_default_nand_part), 256 .partitions = bast_default_nand_part, 257 }, 258 [2] = { 259 .name = "chip1", 260 .nr_chips = 1, 261 .nr_map = chip1_map, 262 .options = NAND_SCAN_SILENT_NODEV, 263 .nr_partitions = ARRAY_SIZE(bast_default_nand_part), 264 .partitions = bast_default_nand_part, 265 }, 266 [3] = { 267 .name = "chip2", 268 .nr_chips = 1, 269 .nr_map = chip2_map, 270 .options = NAND_SCAN_SILENT_NODEV, 271 .nr_partitions = ARRAY_SIZE(bast_default_nand_part), 272 .partitions = bast_default_nand_part, 273 } 274}; 275 276static void bast_nand_select(struct s3c2410_nand_set *set, int slot) 277{ 278 unsigned int tmp; 279 280 slot = set->nr_map[slot] & 3; 281 282 pr_debug("bast_nand: selecting slot %d (set %p,%p)\n", 283 slot, set, set->nr_map); 284 285 tmp = __raw_readb(BAST_VA_CTRL2); 286 tmp &= BAST_CPLD_CTLR2_IDERST; 287 tmp |= slot; 288 tmp |= BAST_CPLD_CTRL2_WNAND; 289 290 pr_debug("bast_nand: ctrl2 now %02x\n", tmp); 291 292 __raw_writeb(tmp, BAST_VA_CTRL2); 293} 294 295static struct s3c2410_platform_nand __initdata bast_nand_info = { 296 .tacls = 30, 297 .twrph0 = 60, 298 .twrph1 = 60, 299 .nr_sets = ARRAY_SIZE(bast_nand_sets), 300 .sets = bast_nand_sets, 301 .select_chip = bast_nand_select, 302}; 303 304/* DM9000 */ 305 306static struct resource bast_dm9k_resource[] = { 307 [0] = DEFINE_RES_MEM(S3C2410_CS5 + BAST_PA_DM9000, 4), 308 [1] = DEFINE_RES_MEM(S3C2410_CS5 + BAST_PA_DM9000 + 0x40, 0x40), 309 [2] = DEFINE_RES_NAMED(BAST_IRQ_DM9000 , 1, NULL, IORESOURCE_IRQ \ 310 | IORESOURCE_IRQ_HIGHLEVEL), 311}; 312 313/* for the moment we limit ourselves to 16bit IO until some 314 * better IO routines can be written and tested 315*/ 316 317static struct dm9000_plat_data bast_dm9k_platdata = { 318 .flags = DM9000_PLATF_16BITONLY, 319}; 320 321static struct platform_device bast_device_dm9k = { 322 .name = "dm9000", 323 .id = 0, 324 .num_resources = ARRAY_SIZE(bast_dm9k_resource), 325 .resource = bast_dm9k_resource, 326 .dev = { 327 .platform_data = &bast_dm9k_platdata, 328 } 329}; 330 331/* serial devices */ 332 333#define SERIAL_BASE (S3C2410_CS2 + BAST_PA_SUPERIO) 334#define SERIAL_FLAGS (UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SHARE_IRQ) 335#define SERIAL_CLK (1843200) 336 337static struct plat_serial8250_port bast_sio_data[] = { 338 [0] = { 339 .mapbase = SERIAL_BASE + 0x2f8, 340 .irq = BAST_IRQ_PCSERIAL1, 341 .flags = SERIAL_FLAGS, 342 .iotype = UPIO_MEM, 343 .regshift = 0, 344 .uartclk = SERIAL_CLK, 345 }, 346 [1] = { 347 .mapbase = SERIAL_BASE + 0x3f8, 348 .irq = BAST_IRQ_PCSERIAL2, 349 .flags = SERIAL_FLAGS, 350 .iotype = UPIO_MEM, 351 .regshift = 0, 352 .uartclk = SERIAL_CLK, 353 }, 354 { } 355}; 356 357static struct platform_device bast_sio = { 358 .name = "serial8250", 359 .id = PLAT8250_DEV_PLATFORM, 360 .dev = { 361 .platform_data = &bast_sio_data, 362 }, 363}; 364 365/* we have devices on the bus which cannot work much over the 366 * standard 100KHz i2c bus frequency 367*/ 368 369static struct s3c2410_platform_i2c __initdata bast_i2c_info = { 370 .flags = 0, 371 .slave_addr = 0x10, 372 .frequency = 100*1000, 373}; 374 375/* Asix AX88796 10/100 ethernet controller */ 376 377static struct ax_plat_data bast_asix_platdata = { 378 .flags = AXFLG_MAC_FROMDEV, 379 .wordlength = 2, 380 .dcr_val = 0x48, 381 .rcr_val = 0x40, 382}; 383 384static struct resource bast_asix_resource[] = { 385 [0] = DEFINE_RES_MEM(S3C2410_CS5 + BAST_PA_ASIXNET, 0x18 * 0x20), 386 [1] = DEFINE_RES_MEM(S3C2410_CS5 + BAST_PA_ASIXNET + (0x1f * 0x20), 1), 387 [2] = DEFINE_RES_IRQ(BAST_IRQ_ASIX), 388}; 389 390static struct platform_device bast_device_asix = { 391 .name = "ax88796", 392 .id = 0, 393 .num_resources = ARRAY_SIZE(bast_asix_resource), 394 .resource = bast_asix_resource, 395 .dev = { 396 .platform_data = &bast_asix_platdata 397 } 398}; 399 400/* Asix AX88796 10/100 ethernet controller parallel port */ 401 402static struct resource bast_asixpp_resource[] = { 403 [0] = DEFINE_RES_MEM(S3C2410_CS5 + BAST_PA_ASIXNET + (0x18 * 0x20), \ 404 0x30 * 0x20), 405}; 406 407static struct platform_device bast_device_axpp = { 408 .name = "ax88796-pp", 409 .id = 0, 410 .num_resources = ARRAY_SIZE(bast_asixpp_resource), 411 .resource = bast_asixpp_resource, 412}; 413 414/* LCD/VGA controller */ 415 416static struct s3c2410fb_display __initdata bast_lcd_info[] = { 417 { 418 .type = S3C2410_LCDCON1_TFT, 419 .width = 640, 420 .height = 480, 421 422 .pixclock = 33333, 423 .xres = 640, 424 .yres = 480, 425 .bpp = 4, 426 .left_margin = 40, 427 .right_margin = 20, 428 .hsync_len = 88, 429 .upper_margin = 30, 430 .lower_margin = 32, 431 .vsync_len = 3, 432 433 .lcdcon5 = 0x00014b02, 434 }, 435 { 436 .type = S3C2410_LCDCON1_TFT, 437 .width = 640, 438 .height = 480, 439 440 .pixclock = 33333, 441 .xres = 640, 442 .yres = 480, 443 .bpp = 8, 444 .left_margin = 40, 445 .right_margin = 20, 446 .hsync_len = 88, 447 .upper_margin = 30, 448 .lower_margin = 32, 449 .vsync_len = 3, 450 451 .lcdcon5 = 0x00014b02, 452 }, 453 { 454 .type = S3C2410_LCDCON1_TFT, 455 .width = 640, 456 .height = 480, 457 458 .pixclock = 33333, 459 .xres = 640, 460 .yres = 480, 461 .bpp = 16, 462 .left_margin = 40, 463 .right_margin = 20, 464 .hsync_len = 88, 465 .upper_margin = 30, 466 .lower_margin = 32, 467 .vsync_len = 3, 468 469 .lcdcon5 = 0x00014b02, 470 }, 471}; 472 473/* LCD/VGA controller */ 474 475static struct s3c2410fb_mach_info __initdata bast_fb_info = { 476 477 .displays = bast_lcd_info, 478 .num_displays = ARRAY_SIZE(bast_lcd_info), 479 .default_display = 1, 480}; 481 482/* I2C devices fitted. */ 483 484static struct i2c_board_info bast_i2c_devs[] __initdata = { 485 { 486 I2C_BOARD_INFO("tlv320aic23", 0x1a), 487 }, { 488 I2C_BOARD_INFO("simtec-pmu", 0x6b), 489 }, { 490 I2C_BOARD_INFO("ch7013", 0x75), 491 }, 492}; 493 494static struct s3c_hwmon_pdata bast_hwmon_info = { 495 /* LCD contrast (0-6.6V) */ 496 .in[0] = &(struct s3c_hwmon_chcfg) { 497 .name = "lcd-contrast", 498 .mult = 3300, 499 .div = 512, 500 }, 501 /* LED current feedback */ 502 .in[1] = &(struct s3c_hwmon_chcfg) { 503 .name = "led-feedback", 504 .mult = 3300, 505 .div = 1024, 506 }, 507 /* LCD feedback (0-6.6V) */ 508 .in[2] = &(struct s3c_hwmon_chcfg) { 509 .name = "lcd-feedback", 510 .mult = 3300, 511 .div = 512, 512 }, 513 /* Vcore (1.8-2.0V), Vref 3.3V */ 514 .in[3] = &(struct s3c_hwmon_chcfg) { 515 .name = "vcore", 516 .mult = 3300, 517 .div = 1024, 518 }, 519}; 520 521/* Standard BAST devices */ 522// cat /sys/devices/platform/s3c24xx-adc/s3c-hwmon/in_0 523 524static struct platform_device *bast_devices[] __initdata = { 525 &s3c2410_device_dclk, 526 &s3c_device_ohci, 527 &s3c_device_lcd, 528 &s3c_device_wdt, 529 &s3c_device_i2c0, 530 &s3c_device_rtc, 531 &s3c_device_nand, 532 &s3c_device_adc, 533 &s3c_device_hwmon, 534 &bast_device_dm9k, 535 &bast_device_asix, 536 &bast_device_axpp, 537 &bast_sio, 538}; 539 540static struct s3c_cpufreq_board __initdata bast_cpufreq = { 541 .refresh = 7800, /* 7.8usec */ 542 .auto_io = 1, 543 .need_io = 1, 544}; 545 546static struct s3c24xx_audio_simtec_pdata __initdata bast_audio = { 547 .have_mic = 1, 548 .have_lout = 1, 549}; 550 551static void __init bast_map_io(void) 552{ 553 s3c_hwmon_set_platdata(&bast_hwmon_info); 554 555 s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc)); 556 s3c24xx_init_uarts(bast_uartcfgs, ARRAY_SIZE(bast_uartcfgs)); 557 samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); 558} 559 560static void __init bast_init_time(void) 561{ 562 s3c2410_init_clocks(12000000); 563 samsung_timer_init(); 564} 565 566static void __init bast_init(void) 567{ 568 register_syscore_ops(&bast_pm_syscore_ops); 569 570 s3c_i2c0_set_platdata(&bast_i2c_info); 571 s3c_nand_set_platdata(&bast_nand_info); 572 s3c24xx_fb_set_platdata(&bast_fb_info); 573 platform_add_devices(bast_devices, ARRAY_SIZE(bast_devices)); 574 575 i2c_register_board_info(0, bast_i2c_devs, 576 ARRAY_SIZE(bast_i2c_devs)); 577 578 usb_simtec_init(); 579 nor_simtec_init(); 580 simtec_audio_add(NULL, true, &bast_audio); 581 582 WARN_ON(gpio_request(S3C2410_GPA(21), "bast nreset")); 583 584 s3c_cpufreq_setboard(&bast_cpufreq); 585} 586 587MACHINE_START(BAST, "Simtec-BAST") 588 /* Maintainer: Ben Dooks <ben@simtec.co.uk> */ 589 .atag_offset = 0x100, 590 .map_io = bast_map_io, 591 .init_irq = s3c2410_init_irq, 592 .init_machine = bast_init, 593 .init_time = bast_init_time, 594MACHINE_END 595