1/* linux/arch/arm/mach-s3c2440/mach-anubis.c 2 * 3 * Copyright 2003-2009 Simtec Electronics 4 * http://armlinux.simtec.co.uk/ 5 * Ben Dooks <ben@simtec.co.uk> 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/kernel.h> 13#include <linux/types.h> 14#include <linux/interrupt.h> 15#include <linux/list.h> 16#include <linux/timer.h> 17#include <linux/init.h> 18#include <linux/gpio.h> 19#include <linux/serial_core.h> 20#include <linux/platform_device.h> 21#include <linux/ata_platform.h> 22#include <linux/i2c.h> 23#include <linux/io.h> 24#include <linux/sm501.h> 25#include <linux/sm501-regs.h> 26 27#include <asm/mach/arch.h> 28#include <asm/mach/map.h> 29#include <asm/mach/irq.h> 30 31#include <mach/anubis-map.h> 32#include <mach/anubis-irq.h> 33#include <mach/anubis-cpld.h> 34 35#include <mach/hardware.h> 36#include <asm/irq.h> 37#include <asm/mach-types.h> 38 39#include <plat/regs-serial.h> 40#include <mach/regs-gpio.h> 41#include <mach/regs-mem.h> 42#include <mach/regs-lcd.h> 43#include <plat/nand.h> 44#include <plat/iic.h> 45 46#include <linux/mtd/mtd.h> 47#include <linux/mtd/nand.h> 48#include <linux/mtd/nand_ecc.h> 49#include <linux/mtd/partitions.h> 50 51#include <net/ax88796.h> 52 53#include <plat/clock.h> 54#include <plat/devs.h> 55#include <plat/cpu.h> 56#include <plat/audio-simtec.h> 57 58#define COPYRIGHT ", Copyright 2005-2009 Simtec Electronics" 59 60static struct map_desc anubis_iodesc[] __initdata = { 61 /* ISA IO areas */ 62 63 { 64 .virtual = (u32)S3C24XX_VA_ISA_BYTE, 65 .pfn = __phys_to_pfn(0x0), 66 .length = SZ_4M, 67 .type = MT_DEVICE, 68 }, { 69 .virtual = (u32)S3C24XX_VA_ISA_WORD, 70 .pfn = __phys_to_pfn(0x0), 71 .length = SZ_4M, 72 .type = MT_DEVICE, 73 }, 74 75 /* we could possibly compress the next set down into a set of smaller tables 76 * pagetables, but that would mean using an L2 section, and it still means 77 * we cannot actually feed the same register to an LDR due to 16K spacing 78 */ 79 80 /* CPLD control registers */ 81 82 { 83 .virtual = (u32)ANUBIS_VA_CTRL1, 84 .pfn = __phys_to_pfn(ANUBIS_PA_CTRL1), 85 .length = SZ_4K, 86 .type = MT_DEVICE, 87 }, { 88 .virtual = (u32)ANUBIS_VA_IDREG, 89 .pfn = __phys_to_pfn(ANUBIS_PA_IDREG), 90 .length = SZ_4K, 91 .type = MT_DEVICE, 92 }, 93}; 94 95#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK 96#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB 97#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE 98 99static struct s3c24xx_uart_clksrc anubis_serial_clocks[] = { 100 [0] = { 101 .name = "uclk", 102 .divisor = 1, 103 .min_baud = 0, 104 .max_baud = 0, 105 }, 106 [1] = { 107 .name = "pclk", 108 .divisor = 1, 109 .min_baud = 0, 110 .max_baud = 0, 111 } 112}; 113 114 115static struct s3c2410_uartcfg anubis_uartcfgs[] __initdata = { 116 [0] = { 117 .hwport = 0, 118 .flags = 0, 119 .ucon = UCON, 120 .ulcon = ULCON, 121 .ufcon = UFCON, 122 .clocks = anubis_serial_clocks, 123 .clocks_size = ARRAY_SIZE(anubis_serial_clocks), 124 }, 125 [1] = { 126 .hwport = 2, 127 .flags = 0, 128 .ucon = UCON, 129 .ulcon = ULCON, 130 .ufcon = UFCON, 131 .clocks = anubis_serial_clocks, 132 .clocks_size = ARRAY_SIZE(anubis_serial_clocks), 133 }, 134}; 135 136/* NAND Flash on Anubis board */ 137 138static int external_map[] = { 2 }; 139static int chip0_map[] = { 0 }; 140static int chip1_map[] = { 1 }; 141 142static struct mtd_partition __initdata anubis_default_nand_part[] = { 143 [0] = { 144 .name = "Boot Agent", 145 .size = SZ_16K, 146 .offset = 0, 147 }, 148 [1] = { 149 .name = "/boot", 150 .size = SZ_4M - SZ_16K, 151 .offset = SZ_16K, 152 }, 153 [2] = { 154 .name = "user1", 155 .offset = SZ_4M, 156 .size = SZ_32M - SZ_4M, 157 }, 158 [3] = { 159 .name = "user2", 160 .offset = SZ_32M, 161 .size = MTDPART_SIZ_FULL, 162 } 163}; 164 165static struct mtd_partition __initdata anubis_default_nand_part_large[] = { 166 [0] = { 167 .name = "Boot Agent", 168 .size = SZ_128K, 169 .offset = 0, 170 }, 171 [1] = { 172 .name = "/boot", 173 .size = SZ_4M - SZ_128K, 174 .offset = SZ_128K, 175 }, 176 [2] = { 177 .name = "user1", 178 .offset = SZ_4M, 179 .size = SZ_32M - SZ_4M, 180 }, 181 [3] = { 182 .name = "user2", 183 .offset = SZ_32M, 184 .size = MTDPART_SIZ_FULL, 185 } 186}; 187 188/* the Anubis has 3 selectable slots for nand-flash, the two 189 * on-board chip areas, as well as the external slot. 190 * 191 * Note, there is no current hot-plug support for the External 192 * socket. 193*/ 194 195static struct s3c2410_nand_set __initdata anubis_nand_sets[] = { 196 [1] = { 197 .name = "External", 198 .nr_chips = 1, 199 .nr_map = external_map, 200 .nr_partitions = ARRAY_SIZE(anubis_default_nand_part), 201 .partitions = anubis_default_nand_part, 202 }, 203 [0] = { 204 .name = "chip0", 205 .nr_chips = 1, 206 .nr_map = chip0_map, 207 .nr_partitions = ARRAY_SIZE(anubis_default_nand_part), 208 .partitions = anubis_default_nand_part, 209 }, 210 [2] = { 211 .name = "chip1", 212 .nr_chips = 1, 213 .nr_map = chip1_map, 214 .nr_partitions = ARRAY_SIZE(anubis_default_nand_part), 215 .partitions = anubis_default_nand_part, 216 }, 217}; 218 219static void anubis_nand_select(struct s3c2410_nand_set *set, int slot) 220{ 221 unsigned int tmp; 222 223 slot = set->nr_map[slot] & 3; 224 225 pr_debug("anubis_nand: selecting slot %d (set %p,%p)\n", 226 slot, set, set->nr_map); 227 228 tmp = __raw_readb(ANUBIS_VA_CTRL1); 229 tmp &= ~ANUBIS_CTRL1_NANDSEL; 230 tmp |= slot; 231 232 pr_debug("anubis_nand: ctrl1 now %02x\n", tmp); 233 234 __raw_writeb(tmp, ANUBIS_VA_CTRL1); 235} 236 237static struct s3c2410_platform_nand __initdata anubis_nand_info = { 238 .tacls = 25, 239 .twrph0 = 55, 240 .twrph1 = 40, 241 .nr_sets = ARRAY_SIZE(anubis_nand_sets), 242 .sets = anubis_nand_sets, 243 .select_chip = anubis_nand_select, 244}; 245 246/* IDE channels */ 247 248static struct pata_platform_info anubis_ide_platdata = { 249 .ioport_shift = 5, 250}; 251 252static struct resource anubis_ide0_resource[] = { 253 { 254 .start = S3C2410_CS3, 255 .end = S3C2410_CS3 + (8*32) - 1, 256 .flags = IORESOURCE_MEM, 257 }, { 258 .start = S3C2410_CS3 + (1<<26) + (6*32), 259 .end = S3C2410_CS3 + (1<<26) + (7*32) - 1, 260 .flags = IORESOURCE_MEM, 261 }, { 262 .start = IRQ_IDE0, 263 .end = IRQ_IDE0, 264 .flags = IORESOURCE_IRQ, 265 }, 266}; 267 268static struct platform_device anubis_device_ide0 = { 269 .name = "pata_platform", 270 .id = 0, 271 .num_resources = ARRAY_SIZE(anubis_ide0_resource), 272 .resource = anubis_ide0_resource, 273 .dev = { 274 .platform_data = &anubis_ide_platdata, 275 .coherent_dma_mask = ~0, 276 }, 277}; 278 279static struct resource anubis_ide1_resource[] = { 280 { 281 .start = S3C2410_CS4, 282 .end = S3C2410_CS4 + (8*32) - 1, 283 .flags = IORESOURCE_MEM, 284 }, { 285 .start = S3C2410_CS4 + (1<<26) + (6*32), 286 .end = S3C2410_CS4 + (1<<26) + (7*32) - 1, 287 .flags = IORESOURCE_MEM, 288 }, { 289 .start = IRQ_IDE0, 290 .end = IRQ_IDE0, 291 .flags = IORESOURCE_IRQ, 292 }, 293}; 294 295static struct platform_device anubis_device_ide1 = { 296 .name = "pata_platform", 297 .id = 1, 298 .num_resources = ARRAY_SIZE(anubis_ide1_resource), 299 .resource = anubis_ide1_resource, 300 .dev = { 301 .platform_data = &anubis_ide_platdata, 302 .coherent_dma_mask = ~0, 303 }, 304}; 305 306/* Asix AX88796 10/100 ethernet controller */ 307 308static struct ax_plat_data anubis_asix_platdata = { 309 .flags = AXFLG_MAC_FROMDEV, 310 .wordlength = 2, 311 .dcr_val = 0x48, 312 .rcr_val = 0x40, 313}; 314 315static struct resource anubis_asix_resource[] = { 316 [0] = { 317 .start = S3C2410_CS5, 318 .end = S3C2410_CS5 + (0x20 * 0x20) -1, 319 .flags = IORESOURCE_MEM 320 }, 321 [1] = { 322 .start = IRQ_ASIX, 323 .end = IRQ_ASIX, 324 .flags = IORESOURCE_IRQ 325 } 326}; 327 328static struct platform_device anubis_device_asix = { 329 .name = "ax88796", 330 .id = 0, 331 .num_resources = ARRAY_SIZE(anubis_asix_resource), 332 .resource = anubis_asix_resource, 333 .dev = { 334 .platform_data = &anubis_asix_platdata, 335 } 336}; 337 338/* SM501 */ 339 340static struct resource anubis_sm501_resource[] = { 341 [0] = { 342 .start = S3C2410_CS2, 343 .end = S3C2410_CS2 + SZ_8M, 344 .flags = IORESOURCE_MEM, 345 }, 346 [1] = { 347 .start = S3C2410_CS2 + SZ_64M - SZ_2M, 348 .end = S3C2410_CS2 + SZ_64M - 1, 349 .flags = IORESOURCE_MEM, 350 }, 351 [2] = { 352 .start = IRQ_EINT0, 353 .end = IRQ_EINT0, 354 .flags = IORESOURCE_IRQ, 355 }, 356}; 357 358static struct sm501_initdata anubis_sm501_initdata = { 359 .gpio_high = { 360 .set = 0x3F000000, /* 24bit panel */ 361 .mask = 0x0, 362 }, 363 .misc_timing = { 364 .set = 0x010100, /* SDRAM timing */ 365 .mask = 0x1F1F00, 366 }, 367 .misc_control = { 368 .set = SM501_MISC_PNL_24BIT, 369 .mask = 0, 370 }, 371 372 .devices = SM501_USE_GPIO, 373 374 /* set the SDRAM and bus clocks */ 375 .mclk = 72 * MHZ, 376 .m1xclk = 144 * MHZ, 377}; 378 379static struct sm501_platdata_gpio_i2c anubis_sm501_gpio_i2c[] = { 380 [0] = { 381 .bus_num = 1, 382 .pin_scl = 44, 383 .pin_sda = 45, 384 }, 385 [1] = { 386 .bus_num = 2, 387 .pin_scl = 40, 388 .pin_sda = 41, 389 }, 390}; 391 392static struct sm501_platdata anubis_sm501_platdata = { 393 .init = &anubis_sm501_initdata, 394 .gpio_base = -1, 395 .gpio_i2c = anubis_sm501_gpio_i2c, 396 .gpio_i2c_nr = ARRAY_SIZE(anubis_sm501_gpio_i2c), 397}; 398 399static struct platform_device anubis_device_sm501 = { 400 .name = "sm501", 401 .id = 0, 402 .num_resources = ARRAY_SIZE(anubis_sm501_resource), 403 .resource = anubis_sm501_resource, 404 .dev = { 405 .platform_data = &anubis_sm501_platdata, 406 }, 407}; 408 409/* Standard Anubis devices */ 410 411static struct platform_device *anubis_devices[] __initdata = { 412 &s3c_device_ohci, 413 &s3c_device_wdt, 414 &s3c_device_adc, 415 &s3c_device_i2c0, 416 &s3c_device_rtc, 417 &s3c_device_nand, 418 &anubis_device_ide0, 419 &anubis_device_ide1, 420 &anubis_device_asix, 421 &anubis_device_sm501, 422}; 423 424static struct clk *anubis_clocks[] __initdata = { 425 &s3c24xx_dclk0, 426 &s3c24xx_dclk1, 427 &s3c24xx_clkout0, 428 &s3c24xx_clkout1, 429 &s3c24xx_uclk, 430}; 431 432/* I2C devices. */ 433 434static struct i2c_board_info anubis_i2c_devs[] __initdata = { 435 { 436 I2C_BOARD_INFO("tps65011", 0x48), 437 .irq = IRQ_EINT20, 438 } 439}; 440 441/* Audio setup */ 442static struct s3c24xx_audio_simtec_pdata __initdata anubis_audio = { 443 .have_mic = 1, 444 .have_lout = 1, 445 .output_cdclk = 1, 446 .use_mpllin = 1, 447 .amp_gpio = S3C2410_GPB(2), 448 .amp_gain[0] = S3C2410_GPD(10), 449 .amp_gain[1] = S3C2410_GPD(11), 450}; 451 452static void __init anubis_map_io(void) 453{ 454 /* initialise the clocks */ 455 456 s3c24xx_dclk0.parent = &clk_upll; 457 s3c24xx_dclk0.rate = 12*1000*1000; 458 459 s3c24xx_dclk1.parent = &clk_upll; 460 s3c24xx_dclk1.rate = 24*1000*1000; 461 462 s3c24xx_clkout0.parent = &s3c24xx_dclk0; 463 s3c24xx_clkout1.parent = &s3c24xx_dclk1; 464 465 s3c24xx_uclk.parent = &s3c24xx_clkout1; 466 467 s3c24xx_register_clocks(anubis_clocks, ARRAY_SIZE(anubis_clocks)); 468 469 s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc)); 470 s3c24xx_init_clocks(0); 471 s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs)); 472 473 /* check for the newer revision boards with large page nand */ 474 475 if ((__raw_readb(ANUBIS_VA_IDREG) & ANUBIS_IDREG_REVMASK) >= 4) { 476 printk(KERN_INFO "ANUBIS-B detected (revision %d)\n", 477 __raw_readb(ANUBIS_VA_IDREG) & ANUBIS_IDREG_REVMASK); 478 anubis_nand_sets[0].partitions = anubis_default_nand_part_large; 479 anubis_nand_sets[0].nr_partitions = ARRAY_SIZE(anubis_default_nand_part_large); 480 } else { 481 /* ensure that the GPIO is setup */ 482 s3c2410_gpio_setpin(S3C2410_GPA(0), 1); 483 } 484} 485 486static void __init anubis_init(void) 487{ 488 s3c_i2c0_set_platdata(NULL); 489 s3c_nand_set_platdata(&anubis_nand_info); 490 simtec_audio_add(NULL, false, &anubis_audio); 491 492 platform_add_devices(anubis_devices, ARRAY_SIZE(anubis_devices)); 493 494 i2c_register_board_info(0, anubis_i2c_devs, 495 ARRAY_SIZE(anubis_i2c_devs)); 496} 497 498 499MACHINE_START(ANUBIS, "Simtec-Anubis") 500 /* Maintainer: Ben Dooks <ben@simtec.co.uk> */ 501 .phys_io = S3C2410_PA_UART, 502 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, 503 .boot_params = S3C2410_SDRAM_PA + 0x100, 504 .map_io = anubis_map_io, 505 .init_machine = anubis_init, 506 .init_irq = s3c24xx_init_irq, 507 .timer = &s3c24xx_timer, 508MACHINE_END 509