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