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