1/* 2 * linux/arch/arm/mach-omap1/board-h3.c 3 * 4 * This file contains OMAP1710 H3 specific code. 5 * 6 * Copyright (C) 2004 Texas Instruments, Inc. 7 * Copyright (C) 2002 MontaVista Software, Inc. 8 * Copyright (C) 2001 RidgeRun, Inc. 9 * Author: RidgeRun, Inc. 10 * Greg Lonnon (glonnon@ridgerun.com) or info@ridgerun.com 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License version 2 as 14 * published by the Free Software Foundation. 15 */ 16 17#include <linux/types.h> 18#include <linux/init.h> 19#include <linux/major.h> 20#include <linux/kernel.h> 21#include <linux/platform_device.h> 22#include <linux/errno.h> 23#include <linux/workqueue.h> 24#include <linux/mtd/mtd.h> 25#include <linux/mtd/nand.h> 26#include <linux/mtd/partitions.h> 27#include <linux/input.h> 28 29#include <asm/setup.h> 30#include <asm/page.h> 31#include <asm/hardware.h> 32#include <asm/mach-types.h> 33#include <asm/mach/arch.h> 34#include <asm/mach/flash.h> 35#include <asm/mach/map.h> 36 37#include <asm/arch/gpio.h> 38#include <asm/arch/gpioexpander.h> 39#include <asm/arch/irqs.h> 40#include <asm/arch/mux.h> 41#include <asm/arch/tc.h> 42#include <asm/arch/irda.h> 43#include <asm/arch/usb.h> 44#include <asm/arch/keypad.h> 45#include <asm/arch/dma.h> 46#include <asm/arch/common.h> 47 48extern int omap_gpio_init(void); 49 50static int h3_keymap[] = { 51 KEY(0, 0, KEY_LEFT), 52 KEY(0, 1, KEY_RIGHT), 53 KEY(0, 2, KEY_3), 54 KEY(0, 3, KEY_F10), 55 KEY(0, 4, KEY_F5), 56 KEY(0, 5, KEY_9), 57 KEY(1, 0, KEY_DOWN), 58 KEY(1, 1, KEY_UP), 59 KEY(1, 2, KEY_2), 60 KEY(1, 3, KEY_F9), 61 KEY(1, 4, KEY_F7), 62 KEY(1, 5, KEY_0), 63 KEY(2, 0, KEY_ENTER), 64 KEY(2, 1, KEY_6), 65 KEY(2, 2, KEY_1), 66 KEY(2, 3, KEY_F2), 67 KEY(2, 4, KEY_F6), 68 KEY(2, 5, KEY_HOME), 69 KEY(3, 0, KEY_8), 70 KEY(3, 1, KEY_5), 71 KEY(3, 2, KEY_F12), 72 KEY(3, 3, KEY_F3), 73 KEY(3, 4, KEY_F8), 74 KEY(3, 5, KEY_END), 75 KEY(4, 0, KEY_7), 76 KEY(4, 1, KEY_4), 77 KEY(4, 2, KEY_F11), 78 KEY(4, 3, KEY_F1), 79 KEY(4, 4, KEY_F4), 80 KEY(4, 5, KEY_ESC), 81 KEY(5, 0, KEY_F13), 82 KEY(5, 1, KEY_F14), 83 KEY(5, 2, KEY_F15), 84 KEY(5, 3, KEY_F16), 85 KEY(5, 4, KEY_SLEEP), 86 0 87}; 88 89 90static struct mtd_partition nor_partitions[] = { 91 /* bootloader (U-Boot, etc) in first sector */ 92 { 93 .name = "bootloader", 94 .offset = 0, 95 .size = SZ_128K, 96 .mask_flags = MTD_WRITEABLE, /* force read-only */ 97 }, 98 /* bootloader params in the next sector */ 99 { 100 .name = "params", 101 .offset = MTDPART_OFS_APPEND, 102 .size = SZ_128K, 103 .mask_flags = 0, 104 }, 105 /* kernel */ 106 { 107 .name = "kernel", 108 .offset = MTDPART_OFS_APPEND, 109 .size = SZ_2M, 110 .mask_flags = 0 111 }, 112 /* file system */ 113 { 114 .name = "filesystem", 115 .offset = MTDPART_OFS_APPEND, 116 .size = MTDPART_SIZ_FULL, 117 .mask_flags = 0 118 } 119}; 120 121static struct flash_platform_data nor_data = { 122 .map_name = "cfi_probe", 123 .width = 2, 124 .parts = nor_partitions, 125 .nr_parts = ARRAY_SIZE(nor_partitions), 126}; 127 128static struct resource nor_resource = { 129 /* This is on CS3, wherever it's mapped */ 130 .flags = IORESOURCE_MEM, 131}; 132 133static struct platform_device nor_device = { 134 .name = "omapflash", 135 .id = 0, 136 .dev = { 137 .platform_data = &nor_data, 138 }, 139 .num_resources = 1, 140 .resource = &nor_resource, 141}; 142 143static struct mtd_partition nand_partitions[] = { 144 { 145 .name = "filesystem", 146 .size = MTDPART_SIZ_FULL, 147 .offset = MTDPART_OFS_APPEND, 148 }, 149}; 150 151/* dip switches control NAND chip access: 8 bit, 16 bit, or neither */ 152static struct nand_platform_data nand_data = { 153 .options = NAND_SAMSUNG_LP_OPTIONS, 154 .parts = nand_partitions, 155 .nr_parts = ARRAY_SIZE(nand_partitions), 156}; 157 158static struct resource nand_resource = { 159 .flags = IORESOURCE_MEM, 160}; 161 162static struct platform_device nand_device = { 163 .name = "omapnand", 164 .id = 0, 165 .dev = { 166 .platform_data = &nand_data, 167 }, 168 .num_resources = 1, 169 .resource = &nand_resource, 170}; 171 172static struct resource smc91x_resources[] = { 173 [0] = { 174 .start = OMAP1710_ETHR_START, /* Physical */ 175 .end = OMAP1710_ETHR_START + 0xf, 176 .flags = IORESOURCE_MEM, 177 }, 178 [1] = { 179 .start = OMAP_GPIO_IRQ(40), 180 .end = OMAP_GPIO_IRQ(40), 181 .flags = IORESOURCE_IRQ, 182 }, 183}; 184 185static struct platform_device smc91x_device = { 186 .name = "smc91x", 187 .id = 0, 188 .num_resources = ARRAY_SIZE(smc91x_resources), 189 .resource = smc91x_resources, 190}; 191 192#define GPTIMER_BASE 0xFFFB1400 193#define GPTIMER_REGS(x) (0xFFFB1400 + (x * 0x800)) 194#define GPTIMER_REGS_SIZE 0x46 195 196static struct resource intlat_resources[] = { 197 [0] = { 198 .start = GPTIMER_REGS(0), /* Physical */ 199 .end = GPTIMER_REGS(0) + GPTIMER_REGS_SIZE, 200 .flags = IORESOURCE_MEM, 201 }, 202 [1] = { 203 .start = INT_1610_GPTIMER1, 204 .end = INT_1610_GPTIMER1, 205 .flags = IORESOURCE_IRQ, 206 }, 207}; 208 209static struct platform_device intlat_device = { 210 .name = "omap_intlat", 211 .id = 0, 212 .num_resources = ARRAY_SIZE(intlat_resources), 213 .resource = intlat_resources, 214}; 215 216static struct resource h3_kp_resources[] = { 217 [0] = { 218 .start = INT_KEYBOARD, 219 .end = INT_KEYBOARD, 220 .flags = IORESOURCE_IRQ, 221 }, 222}; 223 224static struct omap_kp_platform_data h3_kp_data = { 225 .rows = 8, 226 .cols = 8, 227 .keymap = h3_keymap, 228 .keymapsize = ARRAY_SIZE(h3_keymap), 229 .rep = 1, 230 .delay = 9, 231 .dbounce = 1, 232}; 233 234static struct platform_device h3_kp_device = { 235 .name = "omap-keypad", 236 .id = -1, 237 .dev = { 238 .platform_data = &h3_kp_data, 239 }, 240 .num_resources = ARRAY_SIZE(h3_kp_resources), 241 .resource = h3_kp_resources, 242}; 243 244 245/* Select between the IrDA and aGPS module 246 */ 247static int h3_select_irda(struct device *dev, int state) 248{ 249 unsigned char expa; 250 int err = 0; 251 252 if ((err = read_gpio_expa(&expa, 0x26))) { 253 printk(KERN_ERR "Error reading from I/O EXPANDER \n"); 254 return err; 255 } 256 257 /* 'P6' enable/disable IRDA_TX and IRDA_RX */ 258 if (state & IR_SEL) { /* IrDA */ 259 if ((err = write_gpio_expa(expa | 0x40, 0x26))) { 260 printk(KERN_ERR "Error writing to I/O EXPANDER \n"); 261 return err; 262 } 263 } else { 264 if ((err = write_gpio_expa(expa & ~0x40, 0x26))) { 265 printk(KERN_ERR "Error writing to I/O EXPANDER \n"); 266 return err; 267 } 268 } 269 return err; 270} 271 272static void set_trans_mode(void *data) 273{ 274 int *mode = data; 275 unsigned char expa; 276 int err = 0; 277 278 if ((err = read_gpio_expa(&expa, 0x27)) != 0) { 279 printk(KERN_ERR "Error reading from I/O expander\n"); 280 } 281 282 expa &= ~0x03; 283 284 if (*mode & IR_SIRMODE) { 285 expa |= 0x01; 286 } else { /* MIR/FIR */ 287 expa |= 0x03; 288 } 289 290 if ((err = write_gpio_expa(expa, 0x27)) != 0) { 291 printk(KERN_ERR "Error writing to I/O expander\n"); 292 } 293} 294 295static int h3_transceiver_mode(struct device *dev, int mode) 296{ 297 struct omap_irda_config *irda_config = dev->platform_data; 298 299 cancel_delayed_work(&irda_config->gpio_expa); 300 PREPARE_WORK(&irda_config->gpio_expa, set_trans_mode, &mode); 301#error this is not permitted - mode is an argument variable 302 schedule_delayed_work(&irda_config->gpio_expa, 0); 303 304 return 0; 305} 306 307static struct omap_irda_config h3_irda_data = { 308 .transceiver_cap = IR_SIRMODE | IR_MIRMODE | IR_FIRMODE, 309 .transceiver_mode = h3_transceiver_mode, 310 .select_irda = h3_select_irda, 311 .rx_channel = OMAP_DMA_UART3_RX, 312 .tx_channel = OMAP_DMA_UART3_TX, 313 .dest_start = UART3_THR, 314 .src_start = UART3_RHR, 315 .tx_trigger = 0, 316 .rx_trigger = 0, 317}; 318 319static struct resource h3_irda_resources[] = { 320 [0] = { 321 .start = INT_UART3, 322 .end = INT_UART3, 323 .flags = IORESOURCE_IRQ, 324 }, 325}; 326 327static struct platform_device h3_irda_device = { 328 .name = "omapirda", 329 .id = 0, 330 .dev = { 331 .platform_data = &h3_irda_data, 332 }, 333 .num_resources = ARRAY_SIZE(h3_irda_resources), 334 .resource = h3_irda_resources, 335}; 336 337static struct platform_device h3_lcd_device = { 338 .name = "lcd_h3", 339 .id = -1, 340}; 341 342static struct platform_device *devices[] __initdata = { 343 &nor_device, 344 &nand_device, 345 &smc91x_device, 346 &intlat_device, 347 &h3_irda_device, 348 &h3_kp_device, 349 &h3_lcd_device, 350}; 351 352static struct omap_usb_config h3_usb_config __initdata = { 353 /* usb1 has a Mini-AB port and external isp1301 transceiver */ 354 .otg = 2, 355 356#ifdef CONFIG_USB_GADGET_OMAP 357 .hmc_mode = 19, /* 0:host(off) 1:dev|otg 2:disabled */ 358#elif defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) 359 /* NONSTANDARD CABLE NEEDED (B-to-Mini-B) */ 360 .hmc_mode = 20, /* 1:dev|otg(off) 1:host 2:disabled */ 361#endif 362 363 .pins[1] = 3, 364}; 365 366static struct omap_mmc_config h3_mmc_config __initdata = { 367 .mmc[0] = { 368 .enabled = 1, 369 .power_pin = -1, /* tps65010 GPIO4 */ 370 .switch_pin = OMAP_MPUIO(1), 371 }, 372}; 373 374static struct omap_uart_config h3_uart_config __initdata = { 375 .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), 376}; 377 378static struct omap_lcd_config h3_lcd_config __initdata = { 379 .ctrl_name = "internal", 380}; 381 382static struct omap_board_config_kernel h3_config[] = { 383 { OMAP_TAG_USB, &h3_usb_config }, 384 { OMAP_TAG_MMC, &h3_mmc_config }, 385 { OMAP_TAG_UART, &h3_uart_config }, 386 { OMAP_TAG_LCD, &h3_lcd_config }, 387}; 388 389#define H3_NAND_RB_GPIO_PIN 10 390 391static int nand_dev_ready(struct nand_platform_data *data) 392{ 393 return omap_get_gpio_datain(H3_NAND_RB_GPIO_PIN); 394} 395 396static void __init h3_init(void) 397{ 398 /* Here we assume the NOR boot config: NOR on CS3 (possibly swapped 399 * to address 0 by a dip switch), NAND on CS2B. The NAND driver will 400 * notice whether a NAND chip is enabled at probe time. 401 * 402 * H3 support NAND-boot, with a dip switch to put NOR on CS2B and NAND 403 * (which on H2 may be 16bit) on CS3. Try detecting that in code here, 404 * to avoid probing every possible flash configuration... 405 */ 406 nor_resource.end = nor_resource.start = omap_cs3_phys(); 407 nor_resource.end += SZ_32M - 1; 408 409 nand_resource.end = nand_resource.start = OMAP_CS2B_PHYS; 410 nand_resource.end += SZ_4K - 1; 411 if (!(omap_request_gpio(H3_NAND_RB_GPIO_PIN))) 412 nand_data.dev_ready = nand_dev_ready; 413 414 /* GPIO10 Func_MUX_CTRL reg bit 29:27, Configure V2 to mode1 as GPIO */ 415 /* GPIO10 pullup/down register, Enable pullup on GPIO10 */ 416 omap_cfg_reg(V2_1710_GPIO10); 417 418 platform_add_devices(devices, ARRAY_SIZE(devices)); 419 omap_board_config = h3_config; 420 omap_board_config_size = ARRAY_SIZE(h3_config); 421 omap_serial_init(); 422} 423 424static void __init h3_init_smc91x(void) 425{ 426 omap_cfg_reg(W15_1710_GPIO40); 427 if (omap_request_gpio(40) < 0) { 428 printk("Error requesting gpio 40 for smc91x irq\n"); 429 return; 430 } 431} 432 433static void __init h3_init_irq(void) 434{ 435 omap1_init_common_hw(); 436 omap_init_irq(); 437 omap_gpio_init(); 438 h3_init_smc91x(); 439} 440 441static void __init h3_map_io(void) 442{ 443 omap1_map_common_io(); 444} 445 446MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board") 447 /* Maintainer: Texas Instruments, Inc. */ 448 .phys_io = 0xfff00000, 449 .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, 450 .boot_params = 0x10000100, 451 .map_io = h3_map_io, 452 .init_irq = h3_init_irq, 453 .init_machine = h3_init, 454 .timer = &omap_timer, 455MACHINE_END 456