1 /* 2 * linux/arch/arm/mach-omap1/board-palmte.c 3 * 4 * Modified from board-generic.c 5 * 6 * Support for the Palm Tungsten E PDA. 7 * 8 * Original version : Laurent Gonzalez 9 * 10 * Maintainers : http://palmtelinux.sf.net 11 * palmtelinux-developpers@lists.sf.net 12 * 13 * Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org> 14 * 15 * This program is free software; you can redistribute it and/or modify 16 * it under the terms of the GNU General Public License version 2 as 17 * published by the Free Software Foundation. 18 */ 19 20 #include <linux/kernel.h> 21 #include <linux/init.h> 22 #include <linux/input.h> 23 #include <linux/platform_device.h> 24 #include <linux/mtd/mtd.h> 25 #include <linux/mtd/partitions.h> 26 #include <linux/spi/spi.h> 27 #include <linux/spi/tsc2102.h> 28 #include <linux/interrupt.h> 29 #include <linux/apm-emulation.h> 30 31 #include <asm/hardware.h> 32 #include <asm/mach-types.h> 33 #include <asm/mach/arch.h> 34 #include <asm/mach/map.h> 35 #include <asm/mach/flash.h> 36 37 #include <asm/arch/gpio.h> 38 #include <asm/arch/mux.h> 39 #include <asm/arch/usb.h> 40 #include <asm/arch/tc.h> 41 #include <asm/arch/dma.h> 42 #include <asm/arch/board.h> 43 #include <asm/arch/irda.h> 44 #include <asm/arch/keypad.h> 45 #include <asm/arch/common.h> 46 #include <asm/arch/mcbsp.h> 47 #include <asm/arch/omap-alsa.h> 48 49 static void __init omap_palmte_init_irq(void) 50 { 51 omap1_init_common_hw(); 52 omap_init_irq(); 53 omap_gpio_init(); 54 } 55 56 static const int palmte_keymap[] = { 57 KEY(0, 0, KEY_F1), /* Calendar */ 58 KEY(0, 1, KEY_F2), /* Contacts */ 59 KEY(0, 2, KEY_F3), /* Tasks List */ 60 KEY(0, 3, KEY_F4), /* Note Pad */ 61 KEY(0, 4, KEY_POWER), 62 KEY(1, 0, KEY_LEFT), 63 KEY(1, 1, KEY_DOWN), 64 KEY(1, 2, KEY_UP), 65 KEY(1, 3, KEY_RIGHT), 66 KEY(1, 4, KEY_CENTER), 67 0, 68 }; 69 70 static struct omap_kp_platform_data palmte_kp_data = { 71 .rows = 8, 72 .cols = 8, 73 .keymap = (int *) palmte_keymap, 74 .rep = 1, 75 .delay = 12, 76 }; 77 78 static struct resource palmte_kp_resources[] = { 79 [0] = { 80 .start = INT_KEYBOARD, 81 .end = INT_KEYBOARD, 82 .flags = IORESOURCE_IRQ, 83 }, 84 }; 85 86 static struct platform_device palmte_kp_device = { 87 .name = "omap-keypad", 88 .id = -1, 89 .dev = { 90 .platform_data = &palmte_kp_data, 91 }, 92 .num_resources = ARRAY_SIZE(palmte_kp_resources), 93 .resource = palmte_kp_resources, 94 }; 95 96 static struct mtd_partition palmte_rom_partitions[] = { 97 /* PalmOS "Small ROM", contains the bootloader and the debugger */ 98 { 99 .name = "smallrom", 100 .offset = 0, 101 .size = 0xa000, 102 .mask_flags = MTD_WRITEABLE, 103 }, 104 /* PalmOS "Big ROM", a filesystem with all the OS code and data */ 105 { 106 .name = "bigrom", 107 .offset = SZ_128K, 108 /* 109 * 0x5f0000 bytes big in the multi-language ("EFIGS") version, 110 * 0x7b0000 bytes in the English-only ("enUS") version. 111 */ 112 .size = 0x7b0000, 113 .mask_flags = MTD_WRITEABLE, 114 }, 115 }; 116 117 static struct flash_platform_data palmte_rom_data = { 118 .map_name = "map_rom", 119 .width = 2, 120 .parts = palmte_rom_partitions, 121 .nr_parts = ARRAY_SIZE(palmte_rom_partitions), 122 }; 123 124 static struct resource palmte_rom_resource = { 125 .start = OMAP_CS0_PHYS, 126 .end = OMAP_CS0_PHYS + SZ_8M - 1, 127 .flags = IORESOURCE_MEM, 128 }; 129 130 static struct platform_device palmte_rom_device = { 131 .name = "omapflash", 132 .id = -1, 133 .dev = { 134 .platform_data = &palmte_rom_data, 135 }, 136 .num_resources = 1, 137 .resource = &palmte_rom_resource, 138 }; 139 140 static struct platform_device palmte_lcd_device = { 141 .name = "lcd_palmte", 142 .id = -1, 143 }; 144 145 static struct omap_backlight_config palmte_backlight_config = { 146 .default_intensity = 0xa0, 147 }; 148 149 static struct platform_device palmte_backlight_device = { 150 .name = "omap-bl", 151 .id = -1, 152 .dev = { 153 .platform_data = &palmte_backlight_config, 154 }, 155 }; 156 157 static struct omap_irda_config palmte_irda_config = { 158 .transceiver_cap = IR_SIRMODE, 159 .rx_channel = OMAP_DMA_UART3_RX, 160 .tx_channel = OMAP_DMA_UART3_TX, 161 .dest_start = UART3_THR, 162 .src_start = UART3_RHR, 163 .tx_trigger = 0, 164 .rx_trigger = 0, 165 }; 166 167 static struct resource palmte_irda_resources[] = { 168 [0] = { 169 .start = INT_UART3, 170 .end = INT_UART3, 171 .flags = IORESOURCE_IRQ, 172 }, 173 }; 174 175 static struct platform_device palmte_irda_device = { 176 .name = "omapirda", 177 .id = -1, 178 .dev = { 179 .platform_data = &palmte_irda_config, 180 }, 181 .num_resources = ARRAY_SIZE(palmte_irda_resources), 182 .resource = palmte_irda_resources, 183 }; 184 185 static struct platform_device *palmte_devices[] __initdata = { 186 &palmte_rom_device, 187 &palmte_kp_device, 188 &palmte_lcd_device, 189 &palmte_backlight_device, 190 &palmte_irda_device, 191 }; 192 193 static struct omap_usb_config palmte_usb_config __initdata = { 194 .register_dev = 1, /* Mini-B only receptacle */ 195 .hmc_mode = 0, 196 .pins[0] = 2, 197 }; 198 199 static struct omap_mmc_config palmte_mmc_config __initdata = { 200 .mmc[0] = { 201 .enabled = 1, 202 .wp_pin = PALMTE_MMC_WP_GPIO, 203 .power_pin = PALMTE_MMC_POWER_GPIO, 204 .switch_pin = PALMTE_MMC_SWITCH_GPIO, 205 }, 206 }; 207 208 static struct omap_lcd_config palmte_lcd_config __initdata = { 209 .ctrl_name = "internal", 210 }; 211 212 static struct omap_uart_config palmte_uart_config __initdata = { 213 .enabled_uarts = (1 << 0) | (1 << 1) | (0 << 2), 214 }; 215 216 static struct omap_mcbsp_reg_cfg palmte_mcbsp1_regs = { 217 .spcr2 = FRST | GRST | XRST | XINTM(3), 218 .xcr2 = XDATDLY(1) | XFIG, 219 .xcr1 = XWDLEN1(OMAP_MCBSP_WORD_32), 220 .pcr0 = SCLKME | FSXP | CLKXP, 221 }; 222 223 static struct omap_alsa_codec_config palmte_alsa_config = { 224 .name = "TSC2102 audio", 225 .mcbsp_regs_alsa = &palmte_mcbsp1_regs, 226 .codec_configure_dev = NULL, /* tsc2102_configure, */ 227 .codec_set_samplerate = NULL, /* tsc2102_set_samplerate, */ 228 .codec_clock_setup = NULL, /* tsc2102_clock_setup, */ 229 .codec_clock_on = NULL, /* tsc2102_clock_on, */ 230 .codec_clock_off = NULL, /* tsc2102_clock_off, */ 231 .get_default_samplerate = NULL, /* tsc2102_get_default_samplerate, */ 232 }; 233 234 #ifdef CONFIG_APM 235 /* 236 * Values measured in 10 minute intervals averaged over 10 samples. 237 * May differ slightly from device to device but should be accurate 238 * enough to give basic idea of battery life left and trigger 239 * potential alerts. 240 */ 241 static const int palmte_battery_sample[] = { 242 2194, 2157, 2138, 2120, 243 2104, 2089, 2075, 2061, 244 2048, 2038, 2026, 2016, 245 2008, 1998, 1989, 1980, 246 1970, 1958, 1945, 1928, 247 1910, 1888, 1860, 1827, 248 1791, 1751, 1709, 1656, 249 }; 250 251 #define INTERVAL 10 252 #define BATTERY_HIGH_TRESHOLD 66 253 #define BATTERY_LOW_TRESHOLD 33 254 255 static void palmte_get_power_status(struct apm_power_info *info, int *battery) 256 { 257 int charging, batt, hi, lo, mid; 258 259 charging = !omap_get_gpio_datain(PALMTE_DC_GPIO); 260 batt = battery[0]; 261 if (charging) 262 batt -= 60; 263 264 hi = ARRAY_SIZE(palmte_battery_sample); 265 lo = 0; 266 267 info->battery_flag = 0; 268 info->units = APM_UNITS_MINS; 269 270 if (batt > palmte_battery_sample[lo]) { 271 info->battery_life = 100; 272 info->time = INTERVAL * ARRAY_SIZE(palmte_battery_sample); 273 } else if (batt <= palmte_battery_sample[hi - 1]) { 274 info->battery_life = 0; 275 info->time = 0; 276 } else { 277 while (hi > lo + 1) { 278 mid = (hi + lo) >> 1; 279 if (batt <= palmte_battery_sample[mid]) 280 lo = mid; 281 else 282 hi = mid; 283 } 284 285 mid = palmte_battery_sample[lo] - palmte_battery_sample[hi]; 286 hi = palmte_battery_sample[lo] - batt; 287 info->battery_life = 100 - (100 * lo + 100 * hi / mid) / 288 ARRAY_SIZE(palmte_battery_sample); 289 info->time = INTERVAL * (ARRAY_SIZE(palmte_battery_sample) - 290 lo) - INTERVAL * hi / mid; 291 } 292 293 if (charging) { 294 info->ac_line_status = APM_AC_ONLINE; 295 info->battery_status = APM_BATTERY_STATUS_CHARGING; 296 info->battery_flag |= APM_BATTERY_FLAG_CHARGING; 297 } else { 298 info->ac_line_status = APM_AC_OFFLINE; 299 if (info->battery_life > BATTERY_HIGH_TRESHOLD) 300 info->battery_status = APM_BATTERY_STATUS_HIGH; 301 else if (info->battery_life > BATTERY_LOW_TRESHOLD) 302 info->battery_status = APM_BATTERY_STATUS_LOW; 303 else 304 info->battery_status = APM_BATTERY_STATUS_CRITICAL; 305 } 306 307 if (info->battery_life > BATTERY_HIGH_TRESHOLD) 308 info->battery_flag |= APM_BATTERY_FLAG_HIGH; 309 else if (info->battery_life > BATTERY_LOW_TRESHOLD) 310 info->battery_flag |= APM_BATTERY_FLAG_LOW; 311 else 312 info->battery_flag |= APM_BATTERY_FLAG_CRITICAL; 313 } 314 #else 315 #define palmte_get_power_status NULL 316 #endif 317 318 static struct tsc2102_config palmte_tsc2102_config = { 319 .use_internal = 0, 320 .monitor = TSC_BAT1 | TSC_AUX | TSC_TEMP, 321 .temp_at25c = { 2200, 2615 }, 322 .apm_report = palmte_get_power_status, 323 .alsa_config = &palmte_alsa_config, 324 }; 325 326 static struct omap_board_config_kernel palmte_config[] __initdata = { 327 { OMAP_TAG_USB, &palmte_usb_config }, 328 { OMAP_TAG_MMC, &palmte_mmc_config }, 329 { OMAP_TAG_LCD, &palmte_lcd_config }, 330 { OMAP_TAG_UART, &palmte_uart_config }, 331 }; 332 333 static struct spi_board_info palmte_spi_info[] __initdata = { 334 { 335 .modalias = "tsc2102", 336 .bus_num = 2, /* uWire (officially) */ 337 .chip_select = 0, /* As opposed to 3 */ 338 .irq = OMAP_GPIO_IRQ(PALMTE_PINTDAV_GPIO), 339 .platform_data = &palmte_tsc2102_config, 340 .max_speed_hz = 8000000, 341 }, 342 }; 343 344 static void palmte_headphones_detect(void *data, int state) 345 { 346 if (state) { 347 /* Headphones connected, disable speaker */ 348 omap_set_gpio_dataout(PALMTE_SPEAKER_GPIO, 0); 349 printk(KERN_INFO "PM: speaker off\n"); 350 } else { 351 /* Headphones unplugged, re-enable speaker */ 352 omap_set_gpio_dataout(PALMTE_SPEAKER_GPIO, 1); 353 printk(KERN_INFO "PM: speaker on\n"); 354 } 355 } 356 357 static void __init palmte_misc_gpio_setup(void) 358 { 359 /* Set TSC2102 PINTDAV pin as input (used by TSC2102 driver) */ 360 if (omap_request_gpio(PALMTE_PINTDAV_GPIO)) { 361 printk(KERN_ERR "Could not reserve PINTDAV GPIO!\n"); 362 return; 363 } 364 omap_set_gpio_direction(PALMTE_PINTDAV_GPIO, 1); 365 366 /* Set USB-or-DC-IN pin as input (unused) */ 367 if (omap_request_gpio(PALMTE_USB_OR_DC_GPIO)) { 368 printk(KERN_ERR "Could not reserve cable signal GPIO!\n"); 369 return; 370 } 371 omap_set_gpio_direction(PALMTE_USB_OR_DC_GPIO, 1); 372 } 373 374 static void __init omap_palmte_init(void) 375 { 376 omap_board_config = palmte_config; 377 omap_board_config_size = ARRAY_SIZE(palmte_config); 378 379 platform_add_devices(palmte_devices, ARRAY_SIZE(palmte_devices)); 380 381 spi_register_board_info(palmte_spi_info, ARRAY_SIZE(palmte_spi_info)); 382 palmte_misc_gpio_setup(); 383 omap_serial_init(); 384 omap_register_i2c_bus(1, 100, NULL, 0); 385 } 386 387 static void __init omap_palmte_map_io(void) 388 { 389 omap1_map_common_io(); 390 } 391 392 MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E") 393 .phys_io = 0xfff00000, 394 .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, 395 .boot_params = 0x10000100, 396 .map_io = omap_palmte_map_io, 397 .init_irq = omap_palmte_init_irq, 398 .init_machine = omap_palmte_init, 399 .timer = &omap_timer, 400 MACHINE_END 401