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