linux/arch/arm/mach-s3c24xx/mach-osiris.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2005-2008 Simtec Electronics
   3 *      http://armlinux.simtec.co.uk/
   4 *      Ben Dooks <ben@simtec.co.uk>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9*/
  10
  11#include <linux/kernel.h>
  12#include <linux/types.h>
  13#include <linux/interrupt.h>
  14#include <linux/list.h>
  15#include <linux/timer.h>
  16#include <linux/init.h>
  17#include <linux/gpio.h>
  18#include <linux/device.h>
  19#include <linux/syscore_ops.h>
  20#include <linux/serial_core.h>
  21#include <linux/serial_s3c.h>
  22#include <linux/clk.h>
  23#include <linux/i2c.h>
  24#include <linux/io.h>
  25#include <linux/platform_device.h>
  26
  27#include <linux/i2c/tps65010.h>
  28
  29#include <asm/mach-types.h>
  30#include <asm/mach/arch.h>
  31#include <asm/mach/map.h>
  32#include <asm/mach/irq.h>
  33#include <asm/irq.h>
  34
  35#include <linux/platform_data/mtd-nand-s3c2410.h>
  36#include <linux/platform_data/i2c-s3c2410.h>
  37
  38#include <linux/mtd/mtd.h>
  39#include <linux/mtd/nand.h>
  40#include <linux/mtd/nand_ecc.h>
  41#include <linux/mtd/partitions.h>
  42
  43#include <plat/cpu.h>
  44#include <plat/cpu-freq.h>
  45#include <plat/devs.h>
  46#include <plat/gpio-cfg.h>
  47#include <plat/samsung-time.h>
  48
  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 "common.h"
  55#include "osiris.h"
  56#include "regs-mem.h"
  57
  58/* onboard perihperal map */
  59
  60static struct map_desc osiris_iodesc[] __initdata = {
  61  /* ISA IO areas (may be over-written later) */
  62
  63  {
  64          .virtual      = (u32)S3C24XX_VA_ISA_BYTE,
  65          .pfn          = __phys_to_pfn(S3C2410_CS5),
  66          .length       = SZ_16M,
  67          .type         = MT_DEVICE,
  68  }, {
  69          .virtual      = (u32)S3C24XX_VA_ISA_WORD,
  70          .pfn          = __phys_to_pfn(S3C2410_CS5),
  71          .length       = SZ_16M,
  72          .type         = MT_DEVICE,
  73  },
  74
  75  /* CPLD control registers */
  76
  77  {
  78          .virtual      = (u32)OSIRIS_VA_CTRL0,
  79          .pfn          = __phys_to_pfn(OSIRIS_PA_CTRL0),
  80          .length       = SZ_16K,
  81          .type         = MT_DEVICE,
  82  }, {
  83          .virtual      = (u32)OSIRIS_VA_CTRL1,
  84          .pfn          = __phys_to_pfn(OSIRIS_PA_CTRL1),
  85          .length       = SZ_16K,
  86          .type         = MT_DEVICE,
  87  }, {
  88          .virtual      = (u32)OSIRIS_VA_CTRL2,
  89          .pfn          = __phys_to_pfn(OSIRIS_PA_CTRL2),
  90          .length       = SZ_16K,
  91          .type         = MT_DEVICE,
  92  }, {
  93          .virtual      = (u32)OSIRIS_VA_IDREG,
  94          .pfn          = __phys_to_pfn(OSIRIS_PA_IDREG),
  95          .length       = SZ_16K,
  96          .type         = MT_DEVICE,
  97  },
  98};
  99
 100#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
 101#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
 102#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
 103
 104static struct s3c2410_uartcfg osiris_uartcfgs[] __initdata = {
 105        [0] = {
 106                .hwport      = 0,
 107                .flags       = 0,
 108                .ucon        = UCON,
 109                .ulcon       = ULCON,
 110                .ufcon       = UFCON,
 111                .clk_sel        = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2,
 112        },
 113        [1] = {
 114                .hwport      = 1,
 115                .flags       = 0,
 116                .ucon        = UCON,
 117                .ulcon       = ULCON,
 118                .ufcon       = UFCON,
 119                .clk_sel        = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2,
 120        },
 121        [2] = {
 122                .hwport      = 2,
 123                .flags       = 0,
 124                .ucon        = UCON,
 125                .ulcon       = ULCON,
 126                .ufcon       = UFCON,
 127                .clk_sel        = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2,
 128        }
 129};
 130
 131/* NAND Flash on Osiris board */
 132
 133static int external_map[]   = { 2 };
 134static int chip0_map[]      = { 0 };
 135static int chip1_map[]      = { 1 };
 136
 137static struct mtd_partition __initdata osiris_default_nand_part[] = {
 138        [0] = {
 139                .name   = "Boot Agent",
 140                .size   = SZ_16K,
 141                .offset = 0,
 142        },
 143        [1] = {
 144                .name   = "/boot",
 145                .size   = SZ_4M - SZ_16K,
 146                .offset = SZ_16K,
 147        },
 148        [2] = {
 149                .name   = "user1",
 150                .offset = SZ_4M,
 151                .size   = SZ_32M - SZ_4M,
 152        },
 153        [3] = {
 154                .name   = "user2",
 155                .offset = SZ_32M,
 156                .size   = MTDPART_SIZ_FULL,
 157        }
 158};
 159
 160static struct mtd_partition __initdata osiris_default_nand_part_large[] = {
 161        [0] = {
 162                .name   = "Boot Agent",
 163                .size   = SZ_128K,
 164                .offset = 0,
 165        },
 166        [1] = {
 167                .name   = "/boot",
 168                .size   = SZ_4M - SZ_128K,
 169                .offset = SZ_128K,
 170        },
 171        [2] = {
 172                .name   = "user1",
 173                .offset = SZ_4M,
 174                .size   = SZ_32M - SZ_4M,
 175        },
 176        [3] = {
 177                .name   = "user2",
 178                .offset = SZ_32M,
 179                .size   = MTDPART_SIZ_FULL,
 180        }
 181};
 182
 183/* the Osiris has 3 selectable slots for nand-flash, the two
 184 * on-board chip areas, as well as the external slot.
 185 *
 186 * Note, there is no current hot-plug support for the External
 187 * socket.
 188*/
 189
 190static struct s3c2410_nand_set __initdata osiris_nand_sets[] = {
 191        [1] = {
 192                .name           = "External",
 193                .nr_chips       = 1,
 194                .nr_map         = external_map,
 195                .options        = NAND_SCAN_SILENT_NODEV,
 196                .nr_partitions  = ARRAY_SIZE(osiris_default_nand_part),
 197                .partitions     = osiris_default_nand_part,
 198        },
 199        [0] = {
 200                .name           = "chip0",
 201                .nr_chips       = 1,
 202                .nr_map         = chip0_map,
 203                .nr_partitions  = ARRAY_SIZE(osiris_default_nand_part),
 204                .partitions     = osiris_default_nand_part,
 205        },
 206        [2] = {
 207                .name           = "chip1",
 208                .nr_chips       = 1,
 209                .nr_map         = chip1_map,
 210                .options        = NAND_SCAN_SILENT_NODEV,
 211                .nr_partitions  = ARRAY_SIZE(osiris_default_nand_part),
 212                .partitions     = osiris_default_nand_part,
 213        },
 214};
 215
 216static void osiris_nand_select(struct s3c2410_nand_set *set, int slot)
 217{
 218        unsigned int tmp;
 219
 220        slot = set->nr_map[slot] & 3;
 221
 222        pr_debug("osiris_nand: selecting slot %d (set %p,%p)\n",
 223                 slot, set, set->nr_map);
 224
 225        tmp = __raw_readb(OSIRIS_VA_CTRL0);
 226        tmp &= ~OSIRIS_CTRL0_NANDSEL;
 227        tmp |= slot;
 228
 229        pr_debug("osiris_nand: ctrl0 now %02x\n", tmp);
 230
 231        __raw_writeb(tmp, OSIRIS_VA_CTRL0);
 232}
 233
 234static struct s3c2410_platform_nand __initdata osiris_nand_info = {
 235        .tacls          = 25,
 236        .twrph0         = 60,
 237        .twrph1         = 60,
 238        .nr_sets        = ARRAY_SIZE(osiris_nand_sets),
 239        .sets           = osiris_nand_sets,
 240        .select_chip    = osiris_nand_select,
 241};
 242
 243/* PCMCIA control and configuration */
 244
 245static struct resource osiris_pcmcia_resource[] = {
 246        [0] = DEFINE_RES_MEM(0x0f000000, SZ_1M),
 247        [1] = DEFINE_RES_MEM(0x0c000000, SZ_1M),
 248};
 249
 250static struct platform_device osiris_pcmcia = {
 251        .name           = "osiris-pcmcia",
 252        .id             = -1,
 253        .num_resources  = ARRAY_SIZE(osiris_pcmcia_resource),
 254        .resource       = osiris_pcmcia_resource,
 255};
 256
 257/* Osiris power management device */
 258
 259#ifdef CONFIG_PM
 260static unsigned char pm_osiris_ctrl0;
 261
 262static int osiris_pm_suspend(void)
 263{
 264        unsigned int tmp;
 265
 266        pm_osiris_ctrl0 = __raw_readb(OSIRIS_VA_CTRL0);
 267        tmp = pm_osiris_ctrl0 & ~OSIRIS_CTRL0_NANDSEL;
 268
 269        /* ensure correct NAND slot is selected on resume */
 270        if ((pm_osiris_ctrl0 & OSIRIS_CTRL0_BOOT_INT) == 0)
 271                tmp |= 2;
 272
 273        __raw_writeb(tmp, OSIRIS_VA_CTRL0);
 274
 275        /* ensure that an nRESET is not generated on resume. */
 276        gpio_request_one(S3C2410_GPA(21), GPIOF_OUT_INIT_HIGH, NULL);
 277        gpio_free(S3C2410_GPA(21));
 278
 279        return 0;
 280}
 281
 282static void osiris_pm_resume(void)
 283{
 284        if (pm_osiris_ctrl0 & OSIRIS_CTRL0_FIX8)
 285                __raw_writeb(OSIRIS_CTRL1_FIX8, OSIRIS_VA_CTRL1);
 286
 287        __raw_writeb(pm_osiris_ctrl0, OSIRIS_VA_CTRL0);
 288
 289        s3c_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPA21_nRSTOUT);
 290}
 291
 292#else
 293#define osiris_pm_suspend NULL
 294#define osiris_pm_resume NULL
 295#endif
 296
 297static struct syscore_ops osiris_pm_syscore_ops = {
 298        .suspend        = osiris_pm_suspend,
 299        .resume         = osiris_pm_resume,
 300};
 301
 302/* Link for DVS driver to TPS65011 */
 303
 304static void osiris_tps_release(struct device *dev)
 305{
 306        /* static device, do not need to release anything */
 307}
 308
 309static struct platform_device osiris_tps_device = {
 310        .name   = "osiris-dvs",
 311        .id     = -1,
 312        .dev.release = osiris_tps_release,
 313};
 314
 315static int osiris_tps_setup(struct i2c_client *client, void *context)
 316{
 317        osiris_tps_device.dev.parent = &client->dev;
 318        return platform_device_register(&osiris_tps_device);
 319}
 320
 321static int osiris_tps_remove(struct i2c_client *client, void *context)
 322{
 323        platform_device_unregister(&osiris_tps_device);
 324        return 0;
 325}
 326
 327static struct tps65010_board osiris_tps_board = {
 328        .base           = -1,   /* GPIO can go anywhere at the moment */
 329        .setup          = osiris_tps_setup,
 330        .teardown       = osiris_tps_remove,
 331};
 332
 333/* I2C devices fitted. */
 334
 335static struct i2c_board_info osiris_i2c_devs[] __initdata = {
 336        {
 337                I2C_BOARD_INFO("tps65011", 0x48),
 338                .irq    = IRQ_EINT20,
 339                .platform_data = &osiris_tps_board,
 340        },
 341};
 342
 343/* Standard Osiris devices */
 344
 345static struct platform_device *osiris_devices[] __initdata = {
 346        &s3c2410_device_dclk,
 347        &s3c_device_i2c0,
 348        &s3c_device_wdt,
 349        &s3c_device_nand,
 350        &osiris_pcmcia,
 351};
 352
 353static struct s3c_cpufreq_board __initdata osiris_cpufreq = {
 354        .refresh        = 7800, /* refresh period is 7.8usec */
 355        .auto_io        = 1,
 356        .need_io        = 1,
 357};
 358
 359static void __init osiris_map_io(void)
 360{
 361        unsigned long flags;
 362
 363        s3c24xx_init_io(osiris_iodesc, ARRAY_SIZE(osiris_iodesc));
 364        s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs));
 365        samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 366
 367        /* check for the newer revision boards with large page nand */
 368
 369        if ((__raw_readb(OSIRIS_VA_IDREG) & OSIRIS_ID_REVMASK) >= 4) {
 370                printk(KERN_INFO "OSIRIS-B detected (revision %d)\n",
 371                       __raw_readb(OSIRIS_VA_IDREG) & OSIRIS_ID_REVMASK);
 372                osiris_nand_sets[0].partitions = osiris_default_nand_part_large;
 373                osiris_nand_sets[0].nr_partitions = ARRAY_SIZE(osiris_default_nand_part_large);
 374        } else {
 375                /* write-protect line to the NAND */
 376                gpio_request_one(S3C2410_GPA(0), GPIOF_OUT_INIT_HIGH, NULL);
 377                gpio_free(S3C2410_GPA(0));
 378        }
 379
 380        /* fix bus configuration (nBE settings wrong on ABLE pre v2.20) */
 381
 382        local_irq_save(flags);
 383        __raw_writel(__raw_readl(S3C2410_BWSCON) | S3C2410_BWSCON_ST1 | S3C2410_BWSCON_ST2 | S3C2410_BWSCON_ST3 | S3C2410_BWSCON_ST4 | S3C2410_BWSCON_ST5, S3C2410_BWSCON);
 384        local_irq_restore(flags);
 385}
 386
 387static void __init osiris_init_time(void)
 388{
 389        s3c2440_init_clocks(12000000);
 390        samsung_timer_init();
 391}
 392
 393static void __init osiris_init(void)
 394{
 395        register_syscore_ops(&osiris_pm_syscore_ops);
 396
 397        s3c_i2c0_set_platdata(NULL);
 398        s3c_nand_set_platdata(&osiris_nand_info);
 399
 400        s3c_cpufreq_setboard(&osiris_cpufreq);
 401
 402        i2c_register_board_info(0, osiris_i2c_devs,
 403                                ARRAY_SIZE(osiris_i2c_devs));
 404
 405        platform_add_devices(osiris_devices, ARRAY_SIZE(osiris_devices));
 406};
 407
 408MACHINE_START(OSIRIS, "Simtec-OSIRIS")
 409        /* Maintainer: Ben Dooks <ben@simtec.co.uk> */
 410        .atag_offset    = 0x100,
 411        .map_io         = osiris_map_io,
 412        .init_irq       = s3c2440_init_irq,
 413        .init_machine   = osiris_init,
 414        .init_time      = osiris_init_time,
 415MACHINE_END
 416