linux/arch/arm/mach-pxa/palm27x.c
<<
>>
Prefs
   1/*
   2 * Common code for Palm LD, T5, TX, Z72
   3 *
   4 * Copyright (C) 2010-2011 Marek Vasut <marek.vasut@gmail.com>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 *
  10 */
  11
  12#include <linux/platform_device.h>
  13#include <linux/delay.h>
  14#include <linux/irq.h>
  15#include <linux/gpio_keys.h>
  16#include <linux/input.h>
  17#include <linux/pda_power.h>
  18#include <linux/pwm.h>
  19#include <linux/pwm_backlight.h>
  20#include <linux/gpio.h>
  21#include <linux/wm97xx.h>
  22#include <linux/power_supply.h>
  23#include <linux/usb/gpio_vbus.h>
  24#include <linux/regulator/max1586.h>
  25#include <linux/i2c/pxa-i2c.h>
  26
  27#include <asm/mach-types.h>
  28#include <asm/mach/arch.h>
  29#include <asm/mach/map.h>
  30
  31#include "pxa27x.h"
  32#include <mach/audio.h>
  33#include <linux/platform_data/mmc-pxamci.h>
  34#include <linux/platform_data/video-pxafb.h>
  35#include <linux/platform_data/irda-pxaficp.h>
  36#include "udc.h"
  37#include <linux/platform_data/asoc-palm27x.h>
  38#include "palm27x.h"
  39
  40#include "generic.h"
  41#include "devices.h"
  42
  43/******************************************************************************
  44 * SD/MMC card controller
  45 ******************************************************************************/
  46#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
  47static struct pxamci_platform_data palm27x_mci_platform_data = {
  48        .ocr_mask               = MMC_VDD_32_33 | MMC_VDD_33_34,
  49        .detect_delay_ms        = 200,
  50};
  51
  52void __init palm27x_mmc_init(int detect, int ro, int power,
  53                                        int power_inverted)
  54{
  55        palm27x_mci_platform_data.gpio_card_detect      = detect;
  56        palm27x_mci_platform_data.gpio_card_ro          = ro;
  57        palm27x_mci_platform_data.gpio_power            = power;
  58        palm27x_mci_platform_data.gpio_power_invert     = power_inverted;
  59
  60        pxa_set_mci_info(&palm27x_mci_platform_data);
  61}
  62#endif
  63
  64/******************************************************************************
  65 * Power management - standby
  66 ******************************************************************************/
  67#if defined(CONFIG_SUSPEND)
  68void __init palm27x_pm_init(unsigned long str_base)
  69{
  70        static const unsigned long resume[] = {
  71                0xe3a00101,     /* mov  r0,     #0x40000000 */
  72                0xe380060f,     /* orr  r0, r0, #0x00f00000 */
  73                0xe590f008,     /* ldr  pc, [r0, #0x08] */
  74        };
  75
  76        /*
  77         * Copy the bootloader.
  78         * NOTE: PalmZ72 uses a different wakeup method!
  79         */
  80        memcpy(phys_to_virt(str_base), resume, sizeof(resume));
  81}
  82#endif
  83
  84/******************************************************************************
  85 * Framebuffer
  86 ******************************************************************************/
  87#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
  88struct pxafb_mode_info palm_320x480_lcd_mode = {
  89        .pixclock       = 57692,
  90        .xres           = 320,
  91        .yres           = 480,
  92        .bpp            = 16,
  93
  94        .left_margin    = 32,
  95        .right_margin   = 1,
  96        .upper_margin   = 7,
  97        .lower_margin   = 1,
  98
  99        .hsync_len      = 4,
 100        .vsync_len      = 1,
 101};
 102
 103struct pxafb_mode_info palm_320x320_lcd_mode = {
 104        .pixclock       = 115384,
 105        .xres           = 320,
 106        .yres           = 320,
 107        .bpp            = 16,
 108
 109        .left_margin    = 27,
 110        .right_margin   = 7,
 111        .upper_margin   = 7,
 112        .lower_margin   = 8,
 113
 114        .hsync_len      = 6,
 115        .vsync_len      = 1,
 116};
 117
 118struct pxafb_mode_info palm_320x320_new_lcd_mode = {
 119        .pixclock       = 86538,
 120        .xres           = 320,
 121        .yres           = 320,
 122        .bpp            = 16,
 123
 124        .left_margin    = 20,
 125        .right_margin   = 8,
 126        .upper_margin   = 8,
 127        .lower_margin   = 5,
 128
 129        .hsync_len      = 4,
 130        .vsync_len      = 1,
 131};
 132
 133static struct pxafb_mach_info palm27x_lcd_screen = {
 134        .num_modes      = 1,
 135        .lcd_conn       = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
 136};
 137
 138static int palm27x_lcd_power;
 139static void palm27x_lcd_ctl(int on, struct fb_var_screeninfo *info)
 140{
 141        gpio_set_value(palm27x_lcd_power, on);
 142}
 143
 144void __init palm27x_lcd_init(int power, struct pxafb_mode_info *mode)
 145{
 146        palm27x_lcd_screen.modes = mode;
 147
 148        if (gpio_is_valid(power)) {
 149                if (!gpio_request(power, "LCD power")) {
 150                        pr_err("Palm27x: failed to claim lcd power gpio!\n");
 151                        return;
 152                }
 153                if (!gpio_direction_output(power, 1)) {
 154                        pr_err("Palm27x: lcd power configuration failed!\n");
 155                        return;
 156                }
 157                palm27x_lcd_power = power;
 158                palm27x_lcd_screen.pxafb_lcd_power = palm27x_lcd_ctl;
 159        }
 160
 161        pxa_set_fb_info(NULL, &palm27x_lcd_screen);
 162}
 163#endif
 164
 165/******************************************************************************
 166 * USB Gadget
 167 ******************************************************************************/
 168#if     defined(CONFIG_USB_PXA27X) || \
 169        defined(CONFIG_USB_PXA27X_MODULE)
 170static struct gpio_vbus_mach_info palm27x_udc_info = {
 171        .gpio_vbus_inverted     = 1,
 172};
 173
 174static struct platform_device palm27x_gpio_vbus = {
 175        .name   = "gpio-vbus",
 176        .id     = -1,
 177        .dev    = {
 178                .platform_data  = &palm27x_udc_info,
 179        },
 180};
 181
 182void __init palm27x_udc_init(int vbus, int pullup, int vbus_inverted)
 183{
 184        palm27x_udc_info.gpio_vbus      = vbus;
 185        palm27x_udc_info.gpio_pullup    = pullup;
 186
 187        palm27x_udc_info.gpio_vbus_inverted = vbus_inverted;
 188
 189        if (!gpio_request(pullup, "USB Pullup")) {
 190                gpio_direction_output(pullup,
 191                        palm27x_udc_info.gpio_vbus_inverted);
 192                gpio_free(pullup);
 193        } else
 194                return;
 195
 196        platform_device_register(&palm27x_gpio_vbus);
 197}
 198#endif
 199
 200/******************************************************************************
 201 * IrDA
 202 ******************************************************************************/
 203#if defined(CONFIG_IRDA) || defined(CONFIG_IRDA_MODULE)
 204static struct pxaficp_platform_data palm27x_ficp_platform_data = {
 205        .transceiver_cap        = IR_SIRMODE | IR_OFF,
 206};
 207
 208void __init palm27x_irda_init(int pwdn)
 209{
 210        palm27x_ficp_platform_data.gpio_pwdown = pwdn;
 211        pxa_set_ficp_info(&palm27x_ficp_platform_data);
 212}
 213#endif
 214
 215/******************************************************************************
 216 * WM97xx audio, battery
 217 ******************************************************************************/
 218#if     defined(CONFIG_TOUCHSCREEN_WM97XX) || \
 219        defined(CONFIG_TOUCHSCREEN_WM97XX_MODULE)
 220static struct wm97xx_batt_pdata palm27x_batt_pdata = {
 221        .batt_aux       = WM97XX_AUX_ID3,
 222        .temp_aux       = WM97XX_AUX_ID2,
 223        .charge_gpio    = -1,
 224        .batt_mult      = 1000,
 225        .batt_div       = 414,
 226        .temp_mult      = 1,
 227        .temp_div       = 1,
 228        .batt_tech      = POWER_SUPPLY_TECHNOLOGY_LIPO,
 229        .batt_name      = "main-batt",
 230};
 231
 232static struct wm97xx_pdata palm27x_wm97xx_pdata = {
 233        .batt_pdata     = &palm27x_batt_pdata,
 234};
 235
 236static pxa2xx_audio_ops_t palm27x_ac97_pdata = {
 237        .codec_pdata    = { &palm27x_wm97xx_pdata, },
 238};
 239
 240static struct palm27x_asoc_info palm27x_asoc_pdata = {
 241        .jack_gpio      = -1,
 242};
 243
 244static struct platform_device palm27x_asoc = {
 245        .name = "palm27x-asoc",
 246        .id   = -1,
 247        .dev  = {
 248                .platform_data = &palm27x_asoc_pdata,
 249        },
 250};
 251
 252void __init palm27x_ac97_init(int minv, int maxv, int jack, int reset)
 253{
 254        palm27x_ac97_pdata.reset_gpio   = reset;
 255        palm27x_asoc_pdata.jack_gpio    = jack;
 256
 257        if (minv < 0 || maxv < 0) {
 258                palm27x_ac97_pdata.codec_pdata[0] = NULL;
 259                pxa_set_ac97_info(&palm27x_ac97_pdata);
 260        } else {
 261                palm27x_batt_pdata.min_voltage  = minv,
 262                palm27x_batt_pdata.max_voltage  = maxv,
 263
 264                pxa_set_ac97_info(&palm27x_ac97_pdata);
 265                platform_device_register(&palm27x_asoc);
 266        }
 267}
 268#endif
 269
 270/******************************************************************************
 271 * Backlight
 272 ******************************************************************************/
 273#if defined(CONFIG_BACKLIGHT_PWM) || defined(CONFIG_BACKLIGHT_PWM_MODULE)
 274static struct pwm_lookup palm27x_pwm_lookup[] = {
 275        PWM_LOOKUP("pxa27x-pwm.0", 0, "pwm-backlight.0", NULL, 3500 * 1024,
 276                   PWM_POLARITY_NORMAL),
 277};
 278
 279static int palm_bl_power;
 280static int palm_lcd_power;
 281
 282static int palm27x_backlight_init(struct device *dev)
 283{
 284        int ret;
 285
 286        ret = gpio_request(palm_bl_power, "BL POWER");
 287        if (ret)
 288                goto err;
 289        ret = gpio_direction_output(palm_bl_power, 0);
 290        if (ret)
 291                goto err2;
 292
 293        if (gpio_is_valid(palm_lcd_power)) {
 294                ret = gpio_request(palm_lcd_power, "LCD POWER");
 295                if (ret)
 296                        goto err2;
 297                ret = gpio_direction_output(palm_lcd_power, 0);
 298                if (ret)
 299                        goto err3;
 300        }
 301
 302        return 0;
 303err3:
 304        gpio_free(palm_lcd_power);
 305err2:
 306        gpio_free(palm_bl_power);
 307err:
 308        return ret;
 309}
 310
 311static int palm27x_backlight_notify(struct device *dev, int brightness)
 312{
 313        gpio_set_value(palm_bl_power, brightness);
 314        if (gpio_is_valid(palm_lcd_power))
 315                gpio_set_value(palm_lcd_power, brightness);
 316        return brightness;
 317}
 318
 319static void palm27x_backlight_exit(struct device *dev)
 320{
 321        gpio_free(palm_bl_power);
 322        if (gpio_is_valid(palm_lcd_power))
 323                gpio_free(palm_lcd_power);
 324}
 325
 326static struct platform_pwm_backlight_data palm27x_backlight_data = {
 327        .max_brightness = 0xfe,
 328        .dft_brightness = 0x7e,
 329        .enable_gpio    = -1,
 330        .init           = palm27x_backlight_init,
 331        .notify         = palm27x_backlight_notify,
 332        .exit           = palm27x_backlight_exit,
 333};
 334
 335static struct platform_device palm27x_backlight = {
 336        .name   = "pwm-backlight",
 337        .dev    = {
 338                .parent         = &pxa27x_device_pwm0.dev,
 339                .platform_data  = &palm27x_backlight_data,
 340        },
 341};
 342
 343void __init palm27x_pwm_init(int bl, int lcd)
 344{
 345        palm_bl_power   = bl;
 346        palm_lcd_power  = lcd;
 347        pwm_add_table(palm27x_pwm_lookup, ARRAY_SIZE(palm27x_pwm_lookup));
 348        platform_device_register(&palm27x_backlight);
 349}
 350#endif
 351
 352/******************************************************************************
 353 * Power supply
 354 ******************************************************************************/
 355#if defined(CONFIG_PDA_POWER) || defined(CONFIG_PDA_POWER_MODULE)
 356static int palm_ac_state;
 357static int palm_usb_state;
 358
 359static int palm27x_power_supply_init(struct device *dev)
 360{
 361        int ret;
 362
 363        ret = gpio_request(palm_ac_state, "AC state");
 364        if (ret)
 365                goto err1;
 366        ret = gpio_direction_input(palm_ac_state);
 367        if (ret)
 368                goto err2;
 369
 370        if (gpio_is_valid(palm_usb_state)) {
 371                ret = gpio_request(palm_usb_state, "USB state");
 372                if (ret)
 373                        goto err2;
 374                ret = gpio_direction_input(palm_usb_state);
 375                if (ret)
 376                        goto err3;
 377        }
 378
 379        return 0;
 380err3:
 381        gpio_free(palm_usb_state);
 382err2:
 383        gpio_free(palm_ac_state);
 384err1:
 385        return ret;
 386}
 387
 388static void palm27x_power_supply_exit(struct device *dev)
 389{
 390        gpio_free(palm_usb_state);
 391        gpio_free(palm_ac_state);
 392}
 393
 394static int palm27x_is_ac_online(void)
 395{
 396        return gpio_get_value(palm_ac_state);
 397}
 398
 399static int palm27x_is_usb_online(void)
 400{
 401        return !gpio_get_value(palm_usb_state);
 402}
 403static char *palm27x_supplicants[] = {
 404        "main-battery",
 405};
 406
 407static struct pda_power_pdata palm27x_ps_info = {
 408        .init                   = palm27x_power_supply_init,
 409        .exit                   = palm27x_power_supply_exit,
 410        .is_ac_online           = palm27x_is_ac_online,
 411        .is_usb_online          = palm27x_is_usb_online,
 412        .supplied_to            = palm27x_supplicants,
 413        .num_supplicants        = ARRAY_SIZE(palm27x_supplicants),
 414};
 415
 416static struct platform_device palm27x_power_supply = {
 417        .name = "pda-power",
 418        .id   = -1,
 419        .dev  = {
 420                .platform_data = &palm27x_ps_info,
 421        },
 422};
 423
 424void __init palm27x_power_init(int ac, int usb)
 425{
 426        palm_ac_state   = ac;
 427        palm_usb_state  = usb;
 428        platform_device_register(&palm27x_power_supply);
 429}
 430#endif
 431
 432/******************************************************************************
 433 * Core power regulator
 434 ******************************************************************************/
 435#if defined(CONFIG_REGULATOR_MAX1586) || \
 436    defined(CONFIG_REGULATOR_MAX1586_MODULE)
 437static struct regulator_consumer_supply palm27x_max1587a_consumers[] = {
 438        REGULATOR_SUPPLY("vcc_core", NULL),
 439};
 440
 441static struct regulator_init_data palm27x_max1587a_v3_info = {
 442        .constraints = {
 443                .name           = "vcc_core range",
 444                .min_uV         = 900000,
 445                .max_uV         = 1705000,
 446                .always_on      = 1,
 447                .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
 448        },
 449        .consumer_supplies      = palm27x_max1587a_consumers,
 450        .num_consumer_supplies  = ARRAY_SIZE(palm27x_max1587a_consumers),
 451};
 452
 453static struct max1586_subdev_data palm27x_max1587a_subdevs[] = {
 454        {
 455                .name           = "vcc_core",
 456                .id             = MAX1586_V3,
 457                .platform_data  = &palm27x_max1587a_v3_info,
 458        }
 459};
 460
 461static struct max1586_platform_data palm27x_max1587a_info = {
 462        .subdevs     = palm27x_max1587a_subdevs,
 463        .num_subdevs = ARRAY_SIZE(palm27x_max1587a_subdevs),
 464        .v3_gain     = MAX1586_GAIN_R24_3k32, /* 730..1550 mV */
 465};
 466
 467static struct i2c_board_info __initdata palm27x_pi2c_board_info[] = {
 468        {
 469                I2C_BOARD_INFO("max1586", 0x14),
 470                .platform_data  = &palm27x_max1587a_info,
 471        },
 472};
 473
 474static struct i2c_pxa_platform_data palm27x_i2c_power_info = {
 475        .use_pio        = 1,
 476};
 477
 478void __init palm27x_pmic_init(void)
 479{
 480        i2c_register_board_info(1, ARRAY_AND_SIZE(palm27x_pi2c_board_info));
 481        pxa27x_set_i2c_power_info(&palm27x_i2c_power_info);
 482}
 483#endif
 484