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/serial_s3c.h> 21#include <linux/platform_device.h> 22#include <linux/ata_platform.h> 23#include <linux/i2c.h> 24#include <linux/io.h> 25#include <linux/sm501.h> 26#include <linux/sm501-regs.h> 27 28#include <asm/mach/arch.h> 29#include <asm/mach/map.h> 30#include <asm/mach/irq.h> 31 32#include <mach/hardware.h> 33#include <asm/irq.h> 34#include <asm/mach-types.h> 35 36#include <mach/regs-gpio.h> 37#include <mach/regs-lcd.h> 38#include <mach/gpio-samsung.h> 39#include <linux/platform_data/mtd-nand-s3c2410.h> 40#include <linux/platform_data/i2c-s3c2410.h> 41 42#include <linux/mtd/mtd.h> 43#include <linux/mtd/nand.h> 44#include <linux/mtd/nand_ecc.h> 45#include <linux/mtd/partitions.h> 46 47#include <net/ax88796.h> 48 49#include <plat/devs.h> 50#include <plat/cpu.h> 51#include <linux/platform_data/asoc-s3c24xx_simtec.h> 52#include <plat/samsung-time.h> 53 54#include "anubis.h" 55#include "common.h" 56#include "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 s3c2410_uartcfg anubis_uartcfgs[] __initdata = { 100 [0] = { 101 .hwport = 0, 102 .flags = 0, 103 .ucon = UCON, 104 .ulcon = ULCON, 105 .ufcon = UFCON, 106 .clk_sel = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2, 107 }, 108 [1] = { 109 .hwport = 2, 110 .flags = 0, 111 .ucon = UCON, 112 .ulcon = ULCON, 113 .ufcon = UFCON, 114 .clk_sel = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2, 115 }, 116}; 117 118/* NAND Flash on Anubis board */ 119 120static int external_map[] = { 2 }; 121static int chip0_map[] = { 0 }; 122static int chip1_map[] = { 1 }; 123 124static struct mtd_partition __initdata anubis_default_nand_part[] = { 125 [0] = { 126 .name = "Boot Agent", 127 .size = SZ_16K, 128 .offset = 0, 129 }, 130 [1] = { 131 .name = "/boot", 132 .size = SZ_4M - SZ_16K, 133 .offset = SZ_16K, 134 }, 135 [2] = { 136 .name = "user1", 137 .offset = SZ_4M, 138 .size = SZ_32M - SZ_4M, 139 }, 140 [3] = { 141 .name = "user2", 142 .offset = SZ_32M, 143 .size = MTDPART_SIZ_FULL, 144 } 145}; 146 147static struct mtd_partition __initdata anubis_default_nand_part_large[] = { 148 [0] = { 149 .name = "Boot Agent", 150 .size = SZ_128K, 151 .offset = 0, 152 }, 153 [1] = { 154 .name = "/boot", 155 .size = SZ_4M - SZ_128K, 156 .offset = SZ_128K, 157 }, 158 [2] = { 159 .name = "user1", 160 .offset = SZ_4M, 161 .size = SZ_32M - SZ_4M, 162 }, 163 [3] = { 164 .name = "user2", 165 .offset = SZ_32M, 166 .size = MTDPART_SIZ_FULL, 167 } 168}; 169 170/* the Anubis has 3 selectable slots for nand-flash, the two 171 * on-board chip areas, as well as the external slot. 172 * 173 * Note, there is no current hot-plug support for the External 174 * socket. 175*/ 176 177static struct s3c2410_nand_set __initdata anubis_nand_sets[] = { 178 [1] = { 179 .name = "External", 180 .nr_chips = 1, 181 .nr_map = external_map, 182 .nr_partitions = ARRAY_SIZE(anubis_default_nand_part), 183 .partitions = anubis_default_nand_part, 184 }, 185 [0] = { 186 .name = "chip0", 187 .nr_chips = 1, 188 .nr_map = chip0_map, 189 .nr_partitions = ARRAY_SIZE(anubis_default_nand_part), 190 .partitions = anubis_default_nand_part, 191 }, 192 [2] = { 193 .name = "chip1", 194 .nr_chips = 1, 195 .nr_map = chip1_map, 196 .nr_partitions = ARRAY_SIZE(anubis_default_nand_part), 197 .partitions = anubis_default_nand_part, 198 }, 199}; 200 201static void anubis_nand_select(struct s3c2410_nand_set *set, int slot) 202{ 203 unsigned int tmp; 204 205 slot = set->nr_map[slot] & 3; 206 207 pr_debug("anubis_nand: selecting slot %d (set %p,%p)\n", 208 slot, set, set->nr_map); 209 210 tmp = __raw_readb(ANUBIS_VA_CTRL1); 211 tmp &= ~ANUBIS_CTRL1_NANDSEL; 212 tmp |= slot; 213 214 pr_debug("anubis_nand: ctrl1 now %02x\n", tmp); 215 216 __raw_writeb(tmp, ANUBIS_VA_CTRL1); 217} 218 219static struct s3c2410_platform_nand __initdata anubis_nand_info = { 220 .tacls = 25, 221 .twrph0 = 55, 222 .twrph1 = 40, 223 .nr_sets = ARRAY_SIZE(anubis_nand_sets), 224 .sets = anubis_nand_sets, 225 .select_chip = anubis_nand_select, 226}; 227 228/* IDE channels */ 229 230static struct pata_platform_info anubis_ide_platdata = { 231 .ioport_shift = 5, 232}; 233 234static struct resource anubis_ide0_resource[] = { 235 [0] = DEFINE_RES_MEM(S3C2410_CS3, 8 * 32), 236 [2] = DEFINE_RES_MEM(S3C2410_CS3 + (1 << 26) + (6 * 32), 32), 237 [3] = DEFINE_RES_IRQ(ANUBIS_IRQ_IDE0), 238}; 239 240static struct platform_device anubis_device_ide0 = { 241 .name = "pata_platform", 242 .id = 0, 243 .num_resources = ARRAY_SIZE(anubis_ide0_resource), 244 .resource = anubis_ide0_resource, 245 .dev = { 246 .platform_data = &anubis_ide_platdata, 247 .coherent_dma_mask = ~0, 248 }, 249}; 250 251static struct resource anubis_ide1_resource[] = { 252 [0] = DEFINE_RES_MEM(S3C2410_CS4, 8 * 32), 253 [1] = DEFINE_RES_MEM(S3C2410_CS4 + (1 << 26) + (6 * 32), 32), 254 [2] = DEFINE_RES_IRQ(ANUBIS_IRQ_IDE0), 255}; 256 257static struct platform_device anubis_device_ide1 = { 258 .name = "pata_platform", 259 .id = 1, 260 .num_resources = ARRAY_SIZE(anubis_ide1_resource), 261 .resource = anubis_ide1_resource, 262 .dev = { 263 .platform_data = &anubis_ide_platdata, 264 .coherent_dma_mask = ~0, 265 }, 266}; 267 268/* Asix AX88796 10/100 ethernet controller */ 269 270static struct ax_plat_data anubis_asix_platdata = { 271 .flags = AXFLG_MAC_FROMDEV, 272 .wordlength = 2, 273 .dcr_val = 0x48, 274 .rcr_val = 0x40, 275}; 276 277static struct resource anubis_asix_resource[] = { 278 [0] = DEFINE_RES_MEM(S3C2410_CS5, 0x20 * 0x20), 279 [1] = DEFINE_RES_IRQ(ANUBIS_IRQ_ASIX), 280}; 281 282static struct platform_device anubis_device_asix = { 283 .name = "ax88796", 284 .id = 0, 285 .num_resources = ARRAY_SIZE(anubis_asix_resource), 286 .resource = anubis_asix_resource, 287 .dev = { 288 .platform_data = &anubis_asix_platdata, 289 } 290}; 291 292/* SM501 */ 293 294static struct resource anubis_sm501_resource[] = { 295 [0] = DEFINE_RES_MEM(S3C2410_CS2, SZ_8M), 296 [1] = DEFINE_RES_MEM(S3C2410_CS2 + SZ_64M - SZ_2M, SZ_2M), 297 [2] = DEFINE_RES_IRQ(IRQ_EINT0), 298}; 299 300static struct sm501_initdata anubis_sm501_initdata = { 301 .gpio_high = { 302 .set = 0x3F000000, /* 24bit panel */ 303 .mask = 0x0, 304 }, 305 .misc_timing = { 306 .set = 0x010100, /* SDRAM timing */ 307 .mask = 0x1F1F00, 308 }, 309 .misc_control = { 310 .set = SM501_MISC_PNL_24BIT, 311 .mask = 0, 312 }, 313 314 .devices = SM501_USE_GPIO, 315 316 /* set the SDRAM and bus clocks */ 317 .mclk = 72 * MHZ, 318 .m1xclk = 144 * MHZ, 319}; 320 321static struct sm501_platdata_gpio_i2c anubis_sm501_gpio_i2c[] = { 322 [0] = { 323 .bus_num = 1, 324 .pin_scl = 44, 325 .pin_sda = 45, 326 }, 327 [1] = { 328 .bus_num = 2, 329 .pin_scl = 40, 330 .pin_sda = 41, 331 }, 332}; 333 334static struct sm501_platdata anubis_sm501_platdata = { 335 .init = &anubis_sm501_initdata, 336 .gpio_base = -1, 337 .gpio_i2c = anubis_sm501_gpio_i2c, 338 .gpio_i2c_nr = ARRAY_SIZE(anubis_sm501_gpio_i2c), 339}; 340 341static struct platform_device anubis_device_sm501 = { 342 .name = "sm501", 343 .id = 0, 344 .num_resources = ARRAY_SIZE(anubis_sm501_resource), 345 .resource = anubis_sm501_resource, 346 .dev = { 347 .platform_data = &anubis_sm501_platdata, 348 }, 349}; 350 351/* Standard Anubis devices */ 352 353static struct platform_device *anubis_devices[] __initdata = { 354 &s3c2410_device_dclk, 355 &s3c_device_ohci, 356 &s3c_device_wdt, 357 &s3c_device_adc, 358 &s3c_device_i2c0, 359 &s3c_device_rtc, 360 &s3c_device_nand, 361 &anubis_device_ide0, 362 &anubis_device_ide1, 363 &anubis_device_asix, 364 &anubis_device_sm501, 365}; 366 367/* I2C devices. */ 368 369static struct i2c_board_info anubis_i2c_devs[] __initdata = { 370 { 371 I2C_BOARD_INFO("tps65011", 0x48), 372 .irq = IRQ_EINT20, 373 } 374}; 375 376/* Audio setup */ 377static struct s3c24xx_audio_simtec_pdata __initdata anubis_audio = { 378 .have_mic = 1, 379 .have_lout = 1, 380 .output_cdclk = 1, 381 .use_mpllin = 1, 382 .amp_gpio = S3C2410_GPB(2), 383 .amp_gain[0] = S3C2410_GPD(10), 384 .amp_gain[1] = S3C2410_GPD(11), 385}; 386 387static void __init anubis_map_io(void) 388{ 389 s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc)); 390 s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs)); 391 samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); 392 393 /* check for the newer revision boards with large page nand */ 394 395 if ((__raw_readb(ANUBIS_VA_IDREG) & ANUBIS_IDREG_REVMASK) >= 4) { 396 printk(KERN_INFO "ANUBIS-B detected (revision %d)\n", 397 __raw_readb(ANUBIS_VA_IDREG) & ANUBIS_IDREG_REVMASK); 398 anubis_nand_sets[0].partitions = anubis_default_nand_part_large; 399 anubis_nand_sets[0].nr_partitions = ARRAY_SIZE(anubis_default_nand_part_large); 400 } else { 401 /* ensure that the GPIO is setup */ 402 gpio_request_one(S3C2410_GPA(0), GPIOF_OUT_INIT_HIGH, NULL); 403 gpio_free(S3C2410_GPA(0)); 404 } 405} 406 407static void __init anubis_init_time(void) 408{ 409 s3c2440_init_clocks(12000000); 410 samsung_timer_init(); 411} 412 413static void __init anubis_init(void) 414{ 415 s3c_i2c0_set_platdata(NULL); 416 s3c_nand_set_platdata(&anubis_nand_info); 417 simtec_audio_add(NULL, false, &anubis_audio); 418 419 platform_add_devices(anubis_devices, ARRAY_SIZE(anubis_devices)); 420 421 i2c_register_board_info(0, anubis_i2c_devs, 422 ARRAY_SIZE(anubis_i2c_devs)); 423} 424 425 426MACHINE_START(ANUBIS, "Simtec-Anubis") 427 /* Maintainer: Ben Dooks <ben@simtec.co.uk> */ 428 .atag_offset = 0x100, 429 .map_io = anubis_map_io, 430 .init_machine = anubis_init, 431 .init_irq = s3c2440_init_irq, 432 .init_time = anubis_init_time, 433MACHINE_END 434