mach-qt2410.c (8531B)
1// SPDX-License-Identifier: GPL-2.0+ 2// 3// Copyright (C) 2006 by OpenMoko, Inc. 4// Author: Harald Welte <laforge@openmoko.org> 5// All rights reserved. 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/gpio/machine.h> 15#include <linux/device.h> 16#include <linux/platform_device.h> 17#include <linux/serial_core.h> 18#include <linux/serial_s3c.h> 19#include <linux/spi/spi.h> 20#include <linux/spi/spi_gpio.h> 21#include <linux/io.h> 22#include <linux/mtd/mtd.h> 23#include <linux/mtd/rawnand.h> 24#include <linux/mtd/nand-ecc-sw-hamming.h> 25#include <linux/mtd/partitions.h> 26 27#include <asm/mach/arch.h> 28#include <asm/mach/map.h> 29#include <asm/mach/irq.h> 30 31#include <asm/irq.h> 32#include <asm/mach-types.h> 33 34#include <linux/platform_data/leds-s3c24xx.h> 35#include <linux/platform_data/fb-s3c2410.h> 36#include <linux/platform_data/mtd-nand-s3c2410.h> 37#include <linux/platform_data/usb-s3c2410_udc.h> 38#include <linux/platform_data/i2c-s3c2410.h> 39#include "gpio-samsung.h" 40 41#include "gpio-cfg.h" 42#include "devs.h" 43#include "cpu.h" 44#include "pm.h" 45 46#include "s3c24xx.h" 47#include "common-smdk-s3c24xx.h" 48 49static struct map_desc qt2410_iodesc[] __initdata = { 50 { 0xe0000000, __phys_to_pfn(S3C2410_CS3+0x01000000), SZ_1M, MT_DEVICE } 51}; 52 53#define UCON S3C2410_UCON_DEFAULT 54#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB 55#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE 56 57static struct s3c2410_uartcfg smdk2410_uartcfgs[] = { 58 [0] = { 59 .hwport = 0, 60 .flags = 0, 61 .ucon = UCON, 62 .ulcon = ULCON, 63 .ufcon = UFCON, 64 }, 65 [1] = { 66 .hwport = 1, 67 .flags = 0, 68 .ucon = UCON, 69 .ulcon = ULCON, 70 .ufcon = UFCON, 71 }, 72 [2] = { 73 .hwport = 2, 74 .flags = 0, 75 .ucon = UCON, 76 .ulcon = ULCON, 77 .ufcon = UFCON, 78 } 79}; 80 81/* LCD driver info */ 82 83static struct s3c2410fb_display qt2410_lcd_cfg[] __initdata = { 84 { 85 /* Configuration for 640x480 SHARP LQ080V3DG01 */ 86 .lcdcon5 = S3C2410_LCDCON5_FRM565 | 87 S3C2410_LCDCON5_INVVLINE | 88 S3C2410_LCDCON5_INVVFRAME | 89 S3C2410_LCDCON5_PWREN | 90 S3C2410_LCDCON5_HWSWP, 91 92 .type = S3C2410_LCDCON1_TFT, 93 .width = 640, 94 .height = 480, 95 96 .pixclock = 40000, /* HCLK/4 */ 97 .xres = 640, 98 .yres = 480, 99 .bpp = 16, 100 .left_margin = 44, 101 .right_margin = 116, 102 .hsync_len = 96, 103 .upper_margin = 19, 104 .lower_margin = 11, 105 .vsync_len = 15, 106 }, 107 { 108 /* Configuration for 480x640 toppoly TD028TTEC1 */ 109 .lcdcon5 = S3C2410_LCDCON5_FRM565 | 110 S3C2410_LCDCON5_INVVLINE | 111 S3C2410_LCDCON5_INVVFRAME | 112 S3C2410_LCDCON5_PWREN | 113 S3C2410_LCDCON5_HWSWP, 114 115 .type = S3C2410_LCDCON1_TFT, 116 .width = 480, 117 .height = 640, 118 .pixclock = 40000, /* HCLK/4 */ 119 .xres = 480, 120 .yres = 640, 121 .bpp = 16, 122 .left_margin = 8, 123 .right_margin = 24, 124 .hsync_len = 8, 125 .upper_margin = 2, 126 .lower_margin = 4, 127 .vsync_len = 2, 128 }, 129 { 130 /* Config for 240x320 LCD */ 131 .lcdcon5 = S3C2410_LCDCON5_FRM565 | 132 S3C2410_LCDCON5_INVVLINE | 133 S3C2410_LCDCON5_INVVFRAME | 134 S3C2410_LCDCON5_PWREN | 135 S3C2410_LCDCON5_HWSWP, 136 137 .type = S3C2410_LCDCON1_TFT, 138 .width = 240, 139 .height = 320, 140 .pixclock = 100000, /* HCLK/10 */ 141 .xres = 240, 142 .yres = 320, 143 .bpp = 16, 144 .left_margin = 13, 145 .right_margin = 8, 146 .hsync_len = 4, 147 .upper_margin = 2, 148 .lower_margin = 7, 149 .vsync_len = 4, 150 }, 151}; 152 153 154static struct s3c2410fb_mach_info qt2410_fb_info __initdata = { 155 .displays = qt2410_lcd_cfg, 156 .num_displays = ARRAY_SIZE(qt2410_lcd_cfg), 157 .default_display = 0, 158 159 .lpcsel = ((0xCE6) & ~7) | 1<<4, 160}; 161 162/* CS8900 */ 163 164static struct resource qt2410_cs89x0_resources[] = { 165 [0] = DEFINE_RES_MEM(0x19000000, 17), 166 [1] = DEFINE_RES_IRQ(IRQ_EINT9), 167}; 168 169static struct platform_device qt2410_cs89x0 = { 170 .name = "cirrus-cs89x0", 171 .num_resources = ARRAY_SIZE(qt2410_cs89x0_resources), 172 .resource = qt2410_cs89x0_resources, 173}; 174 175/* LED */ 176 177static struct gpiod_lookup_table qt2410_led_gpio_table = { 178 .dev_id = "s3c24xx_led.0", 179 .table = { 180 GPIO_LOOKUP("GPB", 0, NULL, GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN), 181 { }, 182 }, 183}; 184 185static struct s3c24xx_led_platdata qt2410_pdata_led = { 186 .name = "led", 187 .def_trigger = "timer", 188}; 189 190static struct platform_device qt2410_led = { 191 .name = "s3c24xx_led", 192 .id = 0, 193 .dev = { 194 .platform_data = &qt2410_pdata_led, 195 }, 196}; 197 198/* SPI */ 199 200static struct spi_gpio_platform_data spi_gpio_cfg = { 201 .num_chipselect = 1, 202}; 203 204static struct platform_device qt2410_spi = { 205 .name = "spi_gpio", 206 .id = 1, 207 .dev.platform_data = &spi_gpio_cfg, 208}; 209 210static struct gpiod_lookup_table qt2410_spi_gpiod_table = { 211 .dev_id = "spi_gpio", 212 .table = { 213 GPIO_LOOKUP("GPIOG", 7, 214 "sck", GPIO_ACTIVE_HIGH), 215 GPIO_LOOKUP("GPIOG", 6, 216 "mosi", GPIO_ACTIVE_HIGH), 217 GPIO_LOOKUP("GPIOG", 5, 218 "miso", GPIO_ACTIVE_HIGH), 219 GPIO_LOOKUP("GPIOB", 5, 220 "cs", GPIO_ACTIVE_HIGH), 221 { }, 222 }, 223}; 224 225static struct gpiod_lookup_table qt2410_mmc_gpiod_table = { 226 .dev_id = "s3c2410-sdi", 227 .table = { 228 /* bus pins */ 229 GPIO_LOOKUP_IDX("GPIOE", 5, "bus", 0, GPIO_ACTIVE_HIGH), 230 GPIO_LOOKUP_IDX("GPIOE", 6, "bus", 1, GPIO_ACTIVE_HIGH), 231 GPIO_LOOKUP_IDX("GPIOE", 7, "bus", 2, GPIO_ACTIVE_HIGH), 232 GPIO_LOOKUP_IDX("GPIOE", 8, "bus", 3, GPIO_ACTIVE_HIGH), 233 GPIO_LOOKUP_IDX("GPIOE", 9, "bus", 4, GPIO_ACTIVE_HIGH), 234 GPIO_LOOKUP_IDX("GPIOE", 10, "bus", 5, GPIO_ACTIVE_HIGH), 235 { }, 236 }, 237}; 238 239/* Board devices */ 240 241static struct platform_device *qt2410_devices[] __initdata = { 242 &s3c_device_ohci, 243 &s3c_device_lcd, 244 &s3c_device_wdt, 245 &s3c_device_i2c0, 246 &s3c_device_iis, 247 &s3c_device_sdi, 248 &s3c_device_usbgadget, 249 &qt2410_spi, 250 &qt2410_cs89x0, 251 &qt2410_led, 252}; 253 254static struct mtd_partition __initdata qt2410_nand_part[] = { 255 [0] = { 256 .name = "U-Boot", 257 .size = 0x30000, 258 .offset = 0, 259 }, 260 [1] = { 261 .name = "U-Boot environment", 262 .offset = 0x30000, 263 .size = 0x4000, 264 }, 265 [2] = { 266 .name = "kernel", 267 .offset = 0x34000, 268 .size = SZ_2M, 269 }, 270 [3] = { 271 .name = "initrd", 272 .offset = 0x234000, 273 .size = SZ_4M, 274 }, 275 [4] = { 276 .name = "jffs2", 277 .offset = 0x634000, 278 .size = 0x39cc000, 279 }, 280}; 281 282static struct s3c2410_nand_set __initdata qt2410_nand_sets[] = { 283 [0] = { 284 .name = "NAND", 285 .nr_chips = 1, 286 .nr_partitions = ARRAY_SIZE(qt2410_nand_part), 287 .partitions = qt2410_nand_part, 288 }, 289}; 290 291/* choose a set of timings which should suit most 512Mbit 292 * chips and beyond. 293 */ 294 295static struct s3c2410_platform_nand __initdata qt2410_nand_info = { 296 .tacls = 20, 297 .twrph0 = 60, 298 .twrph1 = 20, 299 .nr_sets = ARRAY_SIZE(qt2410_nand_sets), 300 .sets = qt2410_nand_sets, 301 .engine_type = NAND_ECC_ENGINE_TYPE_SOFT, 302}; 303 304/* UDC */ 305 306static struct s3c2410_udc_mach_info qt2410_udc_cfg = { 307}; 308 309static char tft_type = 's'; 310 311static int __init qt2410_tft_setup(char *str) 312{ 313 tft_type = str[0]; 314 return 1; 315} 316 317__setup("tft=", qt2410_tft_setup); 318 319static void __init qt2410_map_io(void) 320{ 321 s3c24xx_init_io(qt2410_iodesc, ARRAY_SIZE(qt2410_iodesc)); 322 s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs)); 323 s3c24xx_set_timer_source(S3C24XX_PWM3, S3C24XX_PWM4); 324} 325 326static void __init qt2410_init_time(void) 327{ 328 s3c2410_init_clocks(12000000); 329 s3c24xx_timer_init(); 330} 331 332static void __init qt2410_machine_init(void) 333{ 334 s3c_nand_set_platdata(&qt2410_nand_info); 335 336 switch (tft_type) { 337 case 'p': /* production */ 338 qt2410_fb_info.default_display = 1; 339 break; 340 case 'b': /* big */ 341 qt2410_fb_info.default_display = 0; 342 break; 343 case 's': /* small */ 344 default: 345 qt2410_fb_info.default_display = 2; 346 break; 347 } 348 s3c24xx_fb_set_platdata(&qt2410_fb_info); 349 350 /* set initial state of the LED GPIO */ 351 WARN_ON(gpio_request_one(S3C2410_GPB(0), GPIOF_OUT_INIT_HIGH, NULL)); 352 gpio_free(S3C2410_GPB(0)); 353 354 s3c24xx_udc_set_platdata(&qt2410_udc_cfg); 355 s3c_i2c0_set_platdata(NULL); 356 357 /* Configure the I2S pins (GPE0...GPE4) in correct mode */ 358 s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2), 359 S3C_GPIO_PULL_NONE); 360 gpiod_add_lookup_table(&qt2410_spi_gpiod_table); 361 s3c_gpio_setpull(S3C2410_GPB(0), S3C_GPIO_PULL_NONE); 362 gpiod_add_lookup_table(&qt2410_led_gpio_table); 363 gpiod_add_lookup_table(&qt2410_mmc_gpiod_table); 364 platform_add_devices(qt2410_devices, ARRAY_SIZE(qt2410_devices)); 365 s3c_pm_init(); 366} 367 368MACHINE_START(QT2410, "QT2410") 369 .atag_offset = 0x100, 370 .nr_irqs = NR_IRQS_S3C2410, 371 .map_io = qt2410_map_io, 372 .init_irq = s3c2410_init_irq, 373 .init_machine = qt2410_machine_init, 374 .init_time = qt2410_init_time, 375MACHINE_END