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