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