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