1/* linux/arch/arm/mach-s3c2410/mach-h1940.c 2 * 3 * Copyright (c) 2003-2005 Simtec Electronics 4 * Ben Dooks <ben@simtec.co.uk> 5 * 6 * http://www.handhelds.org/projects/h1940.html 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/memblock.h> 19#include <linux/timer.h> 20#include <linux/init.h> 21#include <linux/sysdev.h> 22#include <linux/serial_core.h> 23#include <linux/platform_device.h> 24#include <linux/io.h> 25#include <linux/gpio.h> 26#include <linux/pwm_backlight.h> 27#include <video/platform_lcd.h> 28 29#include <linux/mmc/host.h> 30 31#include <asm/mach/arch.h> 32#include <asm/mach/map.h> 33#include <asm/mach/irq.h> 34 35#include <mach/hardware.h> 36#include <asm/irq.h> 37#include <asm/mach-types.h> 38 39#include <plat/regs-serial.h> 40#include <mach/regs-lcd.h> 41#include <mach/regs-clock.h> 42 43#include <mach/regs-gpio.h> 44#include <mach/gpio-fns.h> 45#include <mach/gpio-nrs.h> 46 47#include <mach/h1940.h> 48#include <mach/h1940-latch.h> 49#include <mach/fb.h> 50#include <plat/udc.h> 51#include <plat/iic.h> 52 53#include <plat/gpio-cfg.h> 54#include <plat/clock.h> 55#include <plat/devs.h> 56#include <plat/cpu.h> 57#include <plat/pll.h> 58#include <plat/pm.h> 59#include <plat/mci.h> 60#include <plat/ts.h> 61 62static struct map_desc h1940_iodesc[] __initdata = { 63 [0] = { 64 .virtual = (unsigned long)H1940_LATCH, 65 .pfn = __phys_to_pfn(H1940_PA_LATCH), 66 .length = SZ_16K, 67 .type = MT_DEVICE 68 }, 69}; 70 71#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK 72#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB 73#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE 74 75static struct s3c2410_uartcfg h1940_uartcfgs[] __initdata = { 76 [0] = { 77 .hwport = 0, 78 .flags = 0, 79 .ucon = 0x3c5, 80 .ulcon = 0x03, 81 .ufcon = 0x51, 82 }, 83 [1] = { 84 .hwport = 1, 85 .flags = 0, 86 .ucon = 0x245, 87 .ulcon = 0x03, 88 .ufcon = 0x00, 89 }, 90 /* IR port */ 91 [2] = { 92 .hwport = 2, 93 .flags = 0, 94 .uart_flags = UPF_CONS_FLOW, 95 .ucon = 0x3c5, 96 .ulcon = 0x43, 97 .ufcon = 0x51, 98 } 99}; 100 101/* Board control latch control */ 102 103static unsigned int latch_state = H1940_LATCH_DEFAULT; 104 105void h1940_latch_control(unsigned int clear, unsigned int set) 106{ 107 unsigned long flags; 108 109 local_irq_save(flags); 110 111 latch_state &= ~clear; 112 latch_state |= set; 113 114 __raw_writel(latch_state, H1940_LATCH); 115 116 local_irq_restore(flags); 117} 118 119EXPORT_SYMBOL_GPL(h1940_latch_control); 120 121static void h1940_udc_pullup(enum s3c2410_udc_cmd_e cmd) 122{ 123 printk(KERN_DEBUG "udc: pullup(%d)\n",cmd); 124 125 switch (cmd) 126 { 127 case S3C2410_UDC_P_ENABLE : 128 h1940_latch_control(0, H1940_LATCH_USB_DP); 129 break; 130 case S3C2410_UDC_P_DISABLE : 131 h1940_latch_control(H1940_LATCH_USB_DP, 0); 132 break; 133 case S3C2410_UDC_P_RESET : 134 break; 135 default: 136 break; 137 } 138} 139 140static struct s3c2410_udc_mach_info h1940_udc_cfg __initdata = { 141 .udc_command = h1940_udc_pullup, 142 .vbus_pin = S3C2410_GPG(5), 143 .vbus_pin_inverted = 1, 144}; 145 146static struct s3c2410_ts_mach_info h1940_ts_cfg __initdata = { 147 .delay = 10000, 148 .presc = 49, 149 .oversampling_shift = 2, 150 .cfg_gpio = s3c24xx_ts_cfg_gpio, 151}; 152 153/** 154 * Set lcd on or off 155 **/ 156static struct s3c2410fb_display h1940_lcd __initdata = { 157 .lcdcon5= S3C2410_LCDCON5_FRM565 | \ 158 S3C2410_LCDCON5_INVVLINE | \ 159 S3C2410_LCDCON5_HWSWP, 160 161 .type = S3C2410_LCDCON1_TFT, 162 .width = 240, 163 .height = 320, 164 .pixclock = 260000, 165 .xres = 240, 166 .yres = 320, 167 .bpp = 16, 168 .left_margin = 8, 169 .right_margin = 20, 170 .hsync_len = 4, 171 .upper_margin = 8, 172 .lower_margin = 7, 173 .vsync_len = 1, 174}; 175 176static struct s3c2410fb_mach_info h1940_fb_info __initdata = { 177 .displays = &h1940_lcd, 178 .num_displays = 1, 179 .default_display = 0, 180 181 .lpcsel= 0x02, 182 .gpccon= 0xaa940659, 183 .gpccon_mask= 0xffffffff, 184 .gpcup= 0x0000ffff, 185 .gpcup_mask= 0xffffffff, 186 .gpdcon= 0xaa84aaa0, 187 .gpdcon_mask= 0xffffffff, 188 .gpdup= 0x0000faff, 189 .gpdup_mask= 0xffffffff, 190}; 191 192static struct platform_device h1940_device_leds = { 193 .name = "h1940-leds", 194 .id = -1, 195}; 196 197static struct platform_device h1940_device_bluetooth = { 198 .name = "h1940-bt", 199 .id = -1, 200}; 201 202static struct s3c24xx_mci_pdata h1940_mmc_cfg __initdata = { 203 .gpio_detect = S3C2410_GPF(5), 204 .gpio_wprotect = S3C2410_GPH(8), 205 .set_power = NULL, 206 .ocr_avail = MMC_VDD_32_33, 207}; 208 209static int h1940_backlight_init(struct device *dev) 210{ 211 gpio_request(S3C2410_GPB(0), "Backlight"); 212 213 gpio_direction_output(S3C2410_GPB(0), 0); 214 s3c_gpio_setpull(S3C2410_GPB(0), S3C_GPIO_PULL_NONE); 215 s3c_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0); 216 217 return 0; 218} 219 220static void h1940_backlight_exit(struct device *dev) 221{ 222 gpio_direction_output(S3C2410_GPB(0), 1); 223} 224 225static struct platform_pwm_backlight_data backlight_data = { 226 .pwm_id = 0, 227 .max_brightness = 100, 228 .dft_brightness = 50, 229 /* tcnt = 0x31 */ 230 .pwm_period_ns = 36296, 231 .init = h1940_backlight_init, 232 .exit = h1940_backlight_exit, 233}; 234 235static struct platform_device h1940_backlight = { 236 .name = "pwm-backlight", 237 .dev = { 238 .parent = &s3c_device_timer[0].dev, 239 .platform_data = &backlight_data, 240 }, 241 .id = -1, 242}; 243 244static void h1940_lcd_power_set(struct plat_lcd_data *pd, 245 unsigned int power) 246{ 247 int value; 248 249 if (!power) { 250 /* set to 3ec */ 251 gpio_direction_output(S3C2410_GPC(0), 0); 252 /* wait for 3ac */ 253 do { 254 value = gpio_get_value(S3C2410_GPC(6)); 255 } while (value); 256 /* set to 38c */ 257 gpio_direction_output(S3C2410_GPC(5), 0); 258 } else { 259 /* Set to 3ac */ 260 gpio_direction_output(S3C2410_GPC(5), 1); 261 /* Set to 3ad */ 262 gpio_direction_output(S3C2410_GPC(0), 1); 263 } 264} 265 266static struct plat_lcd_data h1940_lcd_power_data = { 267 .set_power = h1940_lcd_power_set, 268}; 269 270static struct platform_device h1940_lcd_powerdev = { 271 .name = "platform-lcd", 272 .dev.parent = &s3c_device_lcd.dev, 273 .dev.platform_data = &h1940_lcd_power_data, 274}; 275 276static struct platform_device *h1940_devices[] __initdata = { 277 &s3c_device_ohci, 278 &s3c_device_lcd, 279 &s3c_device_wdt, 280 &s3c_device_i2c0, 281 &s3c_device_iis, 282 &s3c_device_usbgadget, 283 &h1940_device_leds, 284 &h1940_device_bluetooth, 285 &s3c_device_sdi, 286 &s3c_device_rtc, 287 &s3c_device_timer[0], 288 &h1940_backlight, 289 &h1940_lcd_powerdev, 290 &s3c_device_adc, 291 &s3c_device_ts, 292}; 293 294static void __init h1940_map_io(void) 295{ 296 s3c24xx_init_io(h1940_iodesc, ARRAY_SIZE(h1940_iodesc)); 297 s3c24xx_init_clocks(0); 298 s3c24xx_init_uarts(h1940_uartcfgs, ARRAY_SIZE(h1940_uartcfgs)); 299 300 /* setup PM */ 301 302#ifdef CONFIG_PM_H1940 303 memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 1024); 304#endif 305 s3c_pm_init(); 306} 307 308/* H1940 and RX3715 need to reserve this for suspend */ 309static void __init h1940_reserve(void) 310{ 311 memblock_reserve(0x30003000, 0x1000); 312 memblock_reserve(0x30081000, 0x1000); 313} 314 315static void __init h1940_init_irq(void) 316{ 317 s3c24xx_init_irq(); 318} 319 320static void __init h1940_init(void) 321{ 322 u32 tmp; 323 324 s3c24xx_fb_set_platdata(&h1940_fb_info); 325 s3c24xx_mci_set_platdata(&h1940_mmc_cfg); 326 s3c24xx_udc_set_platdata(&h1940_udc_cfg); 327 s3c24xx_ts_set_platdata(&h1940_ts_cfg); 328 s3c_i2c0_set_platdata(NULL); 329 330 /* Turn off suspend on both USB ports, and switch the 331 * selectable USB port to USB device mode. */ 332 333 s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST | 334 S3C2410_MISCCR_USBSUSPND0 | 335 S3C2410_MISCCR_USBSUSPND1, 0x0); 336 337 tmp = (0x78 << S3C24XX_PLLCON_MDIVSHIFT) 338 | (0x02 << S3C24XX_PLLCON_PDIVSHIFT) 339 | (0x03 << S3C24XX_PLLCON_SDIVSHIFT); 340 writel(tmp, S3C2410_UPLLCON); 341 342 gpio_request(S3C2410_GPC(0), "LCD power"); 343 gpio_request(S3C2410_GPC(5), "LCD power"); 344 gpio_request(S3C2410_GPC(6), "LCD power"); 345 346 gpio_direction_input(S3C2410_GPC(6)); 347 348 platform_add_devices(h1940_devices, ARRAY_SIZE(h1940_devices)); 349} 350 351MACHINE_START(H1940, "IPAQ-H1940") 352 /* Maintainer: Ben Dooks <ben-linux@fluff.org> */ 353 .phys_io = S3C2410_PA_UART, 354 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, 355 .boot_params = S3C2410_SDRAM_PA + 0x100, 356 .map_io = h1940_map_io, 357 .reserve = h1940_reserve, 358 .init_irq = h1940_init_irq, 359 .init_machine = h1940_init, 360 .timer = &s3c24xx_timer, 361MACHINE_END 362