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