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