1/* 2 * Copyright (c) 2003-2008 Simtec Electronics 3 * Ben Dooks <ben@simtec.co.uk> 4 * 5 * Machine support for Thorcom VR1000 board. Designed for Thorcom by 6 * Simtec Electronics, http://www.simtec.co.uk/ 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 * 12*/ 13 14#include <linux/kernel.h> 15#include <linux/types.h> 16#include <linux/interrupt.h> 17#include <linux/list.h> 18#include <linux/timer.h> 19#include <linux/init.h> 20#include <linux/gpio.h> 21#include <linux/dm9000.h> 22#include <linux/i2c.h> 23 24#include <linux/serial.h> 25#include <linux/tty.h> 26#include <linux/serial_8250.h> 27#include <linux/serial_reg.h> 28#include <linux/serial_s3c.h> 29#include <linux/io.h> 30 31#include <asm/mach/arch.h> 32#include <asm/mach/map.h> 33#include <asm/mach/irq.h> 34 35#include <asm/irq.h> 36#include <asm/mach-types.h> 37 38#include <linux/platform_data/leds-s3c24xx.h> 39#include <linux/platform_data/i2c-s3c2410.h> 40#include <linux/platform_data/asoc-s3c24xx_simtec.h> 41 42#include <mach/hardware.h> 43#include <mach/regs-gpio.h> 44#include <mach/gpio-samsung.h> 45 46#include <plat/cpu.h> 47#include <plat/devs.h> 48#include <plat/samsung-time.h> 49 50#include "bast.h" 51#include "common.h" 52#include "simtec.h" 53#include "vr1000.h" 54 55/* macros for virtual address mods for the io space entries */ 56#define VA_C5(item) ((unsigned long)(item) + BAST_VAM_CS5) 57#define VA_C4(item) ((unsigned long)(item) + BAST_VAM_CS4) 58#define VA_C3(item) ((unsigned long)(item) + BAST_VAM_CS3) 59#define VA_C2(item) ((unsigned long)(item) + BAST_VAM_CS2) 60 61/* macros to modify the physical addresses for io space */ 62 63#define PA_CS2(item) (__phys_to_pfn((item) + S3C2410_CS2)) 64#define PA_CS3(item) (__phys_to_pfn((item) + S3C2410_CS3)) 65#define PA_CS4(item) (__phys_to_pfn((item) + S3C2410_CS4)) 66#define PA_CS5(item) (__phys_to_pfn((item) + S3C2410_CS5)) 67 68static struct map_desc vr1000_iodesc[] __initdata = { 69 /* ISA IO areas */ 70 { 71 .virtual = (u32)S3C24XX_VA_ISA_BYTE, 72 .pfn = PA_CS2(BAST_PA_ISAIO), 73 .length = SZ_16M, 74 .type = MT_DEVICE, 75 }, { 76 .virtual = (u32)S3C24XX_VA_ISA_WORD, 77 .pfn = PA_CS3(BAST_PA_ISAIO), 78 .length = SZ_16M, 79 .type = MT_DEVICE, 80 }, 81 82 /* CPLD control registers, and external interrupt controls */ 83 { 84 .virtual = (u32)VR1000_VA_CTRL1, 85 .pfn = __phys_to_pfn(VR1000_PA_CTRL1), 86 .length = SZ_1M, 87 .type = MT_DEVICE, 88 }, { 89 .virtual = (u32)VR1000_VA_CTRL2, 90 .pfn = __phys_to_pfn(VR1000_PA_CTRL2), 91 .length = SZ_1M, 92 .type = MT_DEVICE, 93 }, { 94 .virtual = (u32)VR1000_VA_CTRL3, 95 .pfn = __phys_to_pfn(VR1000_PA_CTRL3), 96 .length = SZ_1M, 97 .type = MT_DEVICE, 98 }, { 99 .virtual = (u32)VR1000_VA_CTRL4, 100 .pfn = __phys_to_pfn(VR1000_PA_CTRL4), 101 .length = SZ_1M, 102 .type = MT_DEVICE, 103 }, 104}; 105 106#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK 107#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB 108#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE 109 110static struct s3c2410_uartcfg vr1000_uartcfgs[] __initdata = { 111 [0] = { 112 .hwport = 0, 113 .flags = 0, 114 .ucon = UCON, 115 .ulcon = ULCON, 116 .ufcon = UFCON, 117 }, 118 [1] = { 119 .hwport = 1, 120 .flags = 0, 121 .ucon = UCON, 122 .ulcon = ULCON, 123 .ufcon = UFCON, 124 }, 125 /* port 2 is not actually used */ 126 [2] = { 127 .hwport = 2, 128 .flags = 0, 129 .ucon = UCON, 130 .ulcon = ULCON, 131 .ufcon = UFCON, 132 } 133}; 134 135/* definitions for the vr1000 extra 16550 serial ports */ 136 137#define VR1000_BAUDBASE (3692307) 138 139#define VR1000_SERIAL_MAPBASE(x) (VR1000_PA_SERIAL + 0x80 + ((x) << 5)) 140 141static struct plat_serial8250_port serial_platform_data[] = { 142 [0] = { 143 .mapbase = VR1000_SERIAL_MAPBASE(0), 144 .irq = VR1000_IRQ_SERIAL + 0, 145 .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, 146 .iotype = UPIO_MEM, 147 .regshift = 0, 148 .uartclk = VR1000_BAUDBASE, 149 }, 150 [1] = { 151 .mapbase = VR1000_SERIAL_MAPBASE(1), 152 .irq = VR1000_IRQ_SERIAL + 1, 153 .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, 154 .iotype = UPIO_MEM, 155 .regshift = 0, 156 .uartclk = VR1000_BAUDBASE, 157 }, 158 [2] = { 159 .mapbase = VR1000_SERIAL_MAPBASE(2), 160 .irq = VR1000_IRQ_SERIAL + 2, 161 .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, 162 .iotype = UPIO_MEM, 163 .regshift = 0, 164 .uartclk = VR1000_BAUDBASE, 165 }, 166 [3] = { 167 .mapbase = VR1000_SERIAL_MAPBASE(3), 168 .irq = VR1000_IRQ_SERIAL + 3, 169 .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, 170 .iotype = UPIO_MEM, 171 .regshift = 0, 172 .uartclk = VR1000_BAUDBASE, 173 }, 174 { }, 175}; 176 177static struct platform_device serial_device = { 178 .name = "serial8250", 179 .id = PLAT8250_DEV_PLATFORM, 180 .dev = { 181 .platform_data = serial_platform_data, 182 }, 183}; 184 185/* DM9000 ethernet devices */ 186 187static struct resource vr1000_dm9k0_resource[] = { 188 [0] = DEFINE_RES_MEM(S3C2410_CS5 + VR1000_PA_DM9000, 4), 189 [1] = DEFINE_RES_MEM(S3C2410_CS5 + VR1000_PA_DM9000 + 0x40, 0x40), 190 [2] = DEFINE_RES_NAMED(VR1000_IRQ_DM9000A, 1, NULL, IORESOURCE_IRQ \ 191 | IORESOURCE_IRQ_HIGHLEVEL), 192}; 193 194static struct resource vr1000_dm9k1_resource[] = { 195 [0] = DEFINE_RES_MEM(S3C2410_CS5 + VR1000_PA_DM9000 + 0x80, 4), 196 [1] = DEFINE_RES_MEM(S3C2410_CS5 + VR1000_PA_DM9000 + 0xC0, 0x40), 197 [2] = DEFINE_RES_NAMED(VR1000_IRQ_DM9000N, 1, NULL, IORESOURCE_IRQ \ 198 | IORESOURCE_IRQ_HIGHLEVEL), 199}; 200 201/* for the moment we limit ourselves to 16bit IO until some 202 * better IO routines can be written and tested 203*/ 204 205static struct dm9000_plat_data vr1000_dm9k_platdata = { 206 .flags = DM9000_PLATF_16BITONLY, 207}; 208 209static struct platform_device vr1000_dm9k0 = { 210 .name = "dm9000", 211 .id = 0, 212 .num_resources = ARRAY_SIZE(vr1000_dm9k0_resource), 213 .resource = vr1000_dm9k0_resource, 214 .dev = { 215 .platform_data = &vr1000_dm9k_platdata, 216 } 217}; 218 219static struct platform_device vr1000_dm9k1 = { 220 .name = "dm9000", 221 .id = 1, 222 .num_resources = ARRAY_SIZE(vr1000_dm9k1_resource), 223 .resource = vr1000_dm9k1_resource, 224 .dev = { 225 .platform_data = &vr1000_dm9k_platdata, 226 } 227}; 228 229/* LEDS */ 230 231static struct s3c24xx_led_platdata vr1000_led1_pdata = { 232 .name = "led1", 233 .gpio = S3C2410_GPB(0), 234 .def_trigger = "", 235}; 236 237static struct s3c24xx_led_platdata vr1000_led2_pdata = { 238 .name = "led2", 239 .gpio = S3C2410_GPB(1), 240 .def_trigger = "", 241}; 242 243static struct s3c24xx_led_platdata vr1000_led3_pdata = { 244 .name = "led3", 245 .gpio = S3C2410_GPB(2), 246 .def_trigger = "", 247}; 248 249static struct platform_device vr1000_led1 = { 250 .name = "s3c24xx_led", 251 .id = 1, 252 .dev = { 253 .platform_data = &vr1000_led1_pdata, 254 }, 255}; 256 257static struct platform_device vr1000_led2 = { 258 .name = "s3c24xx_led", 259 .id = 2, 260 .dev = { 261 .platform_data = &vr1000_led2_pdata, 262 }, 263}; 264 265static struct platform_device vr1000_led3 = { 266 .name = "s3c24xx_led", 267 .id = 3, 268 .dev = { 269 .platform_data = &vr1000_led3_pdata, 270 }, 271}; 272 273/* I2C devices. */ 274 275static struct i2c_board_info vr1000_i2c_devs[] __initdata = { 276 { 277 I2C_BOARD_INFO("tlv320aic23", 0x1a), 278 }, { 279 I2C_BOARD_INFO("tmp101", 0x48), 280 }, { 281 I2C_BOARD_INFO("m41st87", 0x68), 282 }, 283}; 284 285/* devices for this board */ 286 287static struct platform_device *vr1000_devices[] __initdata = { 288 &s3c2410_device_dclk, 289 &s3c_device_ohci, 290 &s3c_device_lcd, 291 &s3c_device_wdt, 292 &s3c_device_i2c0, 293 &s3c_device_adc, 294 &serial_device, 295 &vr1000_dm9k0, 296 &vr1000_dm9k1, 297 &vr1000_led1, 298 &vr1000_led2, 299 &vr1000_led3, 300}; 301 302static void vr1000_power_off(void) 303{ 304 gpio_direction_output(S3C2410_GPB(9), 1); 305} 306 307static void __init vr1000_map_io(void) 308{ 309 pm_power_off = vr1000_power_off; 310 311 s3c24xx_init_io(vr1000_iodesc, ARRAY_SIZE(vr1000_iodesc)); 312 s3c24xx_init_uarts(vr1000_uartcfgs, ARRAY_SIZE(vr1000_uartcfgs)); 313 samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4); 314} 315 316static void __init vr1000_init_time(void) 317{ 318 s3c2410_init_clocks(12000000); 319 samsung_timer_init(); 320} 321 322static void __init vr1000_init(void) 323{ 324 s3c_i2c0_set_platdata(NULL); 325 platform_add_devices(vr1000_devices, ARRAY_SIZE(vr1000_devices)); 326 327 i2c_register_board_info(0, vr1000_i2c_devs, 328 ARRAY_SIZE(vr1000_i2c_devs)); 329 330 nor_simtec_init(); 331 simtec_audio_add(NULL, true, NULL); 332 333 WARN_ON(gpio_request(S3C2410_GPB(9), "power off")); 334} 335 336MACHINE_START(VR1000, "Thorcom-VR1000") 337 /* Maintainer: Ben Dooks <ben@simtec.co.uk> */ 338 .atag_offset = 0x100, 339 .map_io = vr1000_map_io, 340 .init_machine = vr1000_init, 341 .init_irq = s3c2410_init_irq, 342 .init_time = vr1000_init_time, 343MACHINE_END 344