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/machine.h>
  17#include <linux/gpio.h>
  18#include <linux/wm97xx.h>
  19#include <linux/power_supply.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)
 162
 163/* The actual GPIO offsets get filled in in the palm27x_udc_init() call */
 164static struct gpiod_lookup_table palm27x_udc_gpiod_table = {
 165        .dev_id = "gpio-vbus",
 166        .table = {
 167                GPIO_LOOKUP("gpio-pxa", 0,
 168                            "vbus", GPIO_ACTIVE_HIGH),
 169                GPIO_LOOKUP("gpio-pxa", 0,
 170                            "pullup", GPIO_ACTIVE_HIGH),
 171                { },
 172        },
 173};
 174
 175static struct platform_device palm27x_gpio_vbus = {
 176        .name   = "gpio-vbus",
 177        .id     = -1,
 178};
 179
 180void __init palm27x_udc_init(int vbus, int pullup, int vbus_inverted)
 181{
 182        palm27x_udc_gpiod_table.table[0].chip_hwnum = vbus;
 183        palm27x_udc_gpiod_table.table[1].chip_hwnum = pullup;
 184        if (vbus_inverted)
 185                palm27x_udc_gpiod_table.table[0].flags = GPIO_ACTIVE_LOW;
 186
 187        gpiod_add_lookup_table(&palm27x_udc_gpiod_table);
 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        .batt_mult      = 1000,
 216        .batt_div       = 414,
 217        .temp_mult      = 1,
 218        .temp_div       = 1,
 219        .batt_tech      = POWER_SUPPLY_TECHNOLOGY_LIPO,
 220        .batt_name      = "main-batt",
 221};
 222
 223static struct wm97xx_pdata palm27x_wm97xx_pdata = {
 224        .batt_pdata     = &palm27x_batt_pdata,
 225};
 226
 227static pxa2xx_audio_ops_t palm27x_ac97_pdata = {
 228        .codec_pdata    = { &palm27x_wm97xx_pdata, },
 229};
 230
 231static struct palm27x_asoc_info palm27x_asoc_pdata = {
 232        .jack_gpio      = -1,
 233};
 234
 235static struct platform_device palm27x_asoc = {
 236        .name = "palm27x-asoc",
 237        .id   = -1,
 238        .dev  = {
 239                .platform_data = &palm27x_asoc_pdata,
 240        },
 241};
 242
 243void __init palm27x_ac97_init(int minv, int maxv, int jack, int reset)
 244{
 245        palm27x_ac97_pdata.reset_gpio   = reset;
 246        palm27x_asoc_pdata.jack_gpio    = jack;
 247
 248        if (minv < 0 || maxv < 0) {
 249                palm27x_ac97_pdata.codec_pdata[0] = NULL;
 250                pxa_set_ac97_info(&palm27x_ac97_pdata);
 251        } else {
 252                palm27x_batt_pdata.min_voltage  = minv,
 253                palm27x_batt_pdata.max_voltage  = maxv,
 254
 255                pxa_set_ac97_info(&palm27x_ac97_pdata);
 256                platform_device_register(&palm27x_asoc);
 257        }
 258}
 259#endif
 260
 261/******************************************************************************
 262 * Backlight
 263 ******************************************************************************/
 264#if defined(CONFIG_BACKLIGHT_PWM) || defined(CONFIG_BACKLIGHT_PWM_MODULE)
 265static struct pwm_lookup palm27x_pwm_lookup[] = {
 266        PWM_LOOKUP("pxa27x-pwm.0", 0, "pwm-backlight.0", NULL, 3500 * 1024,
 267                   PWM_POLARITY_NORMAL),
 268};
 269
 270static int palm_bl_power;
 271static int palm_lcd_power;
 272
 273static int palm27x_backlight_init(struct device *dev)
 274{
 275        int ret;
 276
 277        ret = gpio_request(palm_bl_power, "BL POWER");
 278        if (ret)
 279                goto err;
 280        ret = gpio_direction_output(palm_bl_power, 0);
 281        if (ret)
 282                goto err2;
 283
 284        if (gpio_is_valid(palm_lcd_power)) {
 285                ret = gpio_request(palm_lcd_power, "LCD POWER");
 286                if (ret)
 287                        goto err2;
 288                ret = gpio_direction_output(palm_lcd_power, 0);
 289                if (ret)
 290                        goto err3;
 291        }
 292
 293        return 0;
 294err3:
 295        gpio_free(palm_lcd_power);
 296err2:
 297        gpio_free(palm_bl_power);
 298err:
 299        return ret;
 300}
 301
 302static int palm27x_backlight_notify(struct device *dev, int brightness)
 303{
 304        gpio_set_value(palm_bl_power, brightness);
 305        if (gpio_is_valid(palm_lcd_power))
 306                gpio_set_value(palm_lcd_power, brightness);
 307        return brightness;
 308}
 309
 310static void palm27x_backlight_exit(struct device *dev)
 311{
 312        gpio_free(palm_bl_power);
 313        if (gpio_is_valid(palm_lcd_power))
 314                gpio_free(palm_lcd_power);
 315}
 316
 317static struct platform_pwm_backlight_data palm27x_backlight_data = {
 318        .max_brightness = 0xfe,
 319        .dft_brightness = 0x7e,
 320        .init           = palm27x_backlight_init,
 321        .notify         = palm27x_backlight_notify,
 322        .exit           = palm27x_backlight_exit,
 323};
 324
 325static struct platform_device palm27x_backlight = {
 326        .name   = "pwm-backlight",
 327        .dev    = {
 328                .parent         = &pxa27x_device_pwm0.dev,
 329                .platform_data  = &palm27x_backlight_data,
 330        },
 331};
 332
 333void __init palm27x_pwm_init(int bl, int lcd)
 334{
 335        palm_bl_power   = bl;
 336        palm_lcd_power  = lcd;
 337        pwm_add_table(palm27x_pwm_lookup, ARRAY_SIZE(palm27x_pwm_lookup));
 338        platform_device_register(&palm27x_backlight);
 339}
 340#endif
 341
 342/******************************************************************************
 343 * Power supply
 344 ******************************************************************************/
 345#if defined(CONFIG_PDA_POWER) || defined(CONFIG_PDA_POWER_MODULE)
 346static int palm_ac_state;
 347static int palm_usb_state;
 348
 349static int palm27x_power_supply_init(struct device *dev)
 350{
 351        int ret;
 352
 353        ret = gpio_request(palm_ac_state, "AC state");
 354        if (ret)
 355                goto err1;
 356        ret = gpio_direction_input(palm_ac_state);
 357        if (ret)
 358                goto err2;
 359
 360        if (gpio_is_valid(palm_usb_state)) {
 361                ret = gpio_request(palm_usb_state, "USB state");
 362                if (ret)
 363                        goto err2;
 364                ret = gpio_direction_input(palm_usb_state);
 365                if (ret)
 366                        goto err3;
 367        }
 368
 369        return 0;
 370err3:
 371        gpio_free(palm_usb_state);
 372err2:
 373        gpio_free(palm_ac_state);
 374err1:
 375        return ret;
 376}
 377
 378static void palm27x_power_supply_exit(struct device *dev)
 379{
 380        gpio_free(palm_usb_state);
 381        gpio_free(palm_ac_state);
 382}
 383
 384static int palm27x_is_ac_online(void)
 385{
 386        return gpio_get_value(palm_ac_state);
 387}
 388
 389static int palm27x_is_usb_online(void)
 390{
 391        return !gpio_get_value(palm_usb_state);
 392}
 393static char *palm27x_supplicants[] = {
 394        "main-battery",
 395};
 396
 397static struct pda_power_pdata palm27x_ps_info = {
 398        .init                   = palm27x_power_supply_init,
 399        .exit                   = palm27x_power_supply_exit,
 400        .is_ac_online           = palm27x_is_ac_online,
 401        .is_usb_online          = palm27x_is_usb_online,
 402        .supplied_to            = palm27x_supplicants,
 403        .num_supplicants        = ARRAY_SIZE(palm27x_supplicants),
 404};
 405
 406static struct platform_device palm27x_power_supply = {
 407        .name = "pda-power",
 408        .id   = -1,
 409        .dev  = {
 410                .platform_data = &palm27x_ps_info,
 411        },
 412};
 413
 414void __init palm27x_power_init(int ac, int usb)
 415{
 416        palm_ac_state   = ac;
 417        palm_usb_state  = usb;
 418        platform_device_register(&palm27x_power_supply);
 419}
 420#endif
 421
 422/******************************************************************************
 423 * Core power regulator
 424 ******************************************************************************/
 425#if defined(CONFIG_REGULATOR_MAX1586) || \
 426    defined(CONFIG_REGULATOR_MAX1586_MODULE)
 427static struct regulator_consumer_supply palm27x_max1587a_consumers[] = {
 428        REGULATOR_SUPPLY("vcc_core", NULL),
 429};
 430
 431static struct regulator_init_data palm27x_max1587a_v3_info = {
 432        .constraints = {
 433                .name           = "vcc_core range",
 434                .min_uV         = 900000,
 435                .max_uV         = 1705000,
 436                .always_on      = 1,
 437                .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
 438        },
 439        .consumer_supplies      = palm27x_max1587a_consumers,
 440        .num_consumer_supplies  = ARRAY_SIZE(palm27x_max1587a_consumers),
 441};
 442
 443static struct max1586_subdev_data palm27x_max1587a_subdevs[] = {
 444        {
 445                .name           = "vcc_core",
 446                .id             = MAX1586_V3,
 447                .platform_data  = &palm27x_max1587a_v3_info,
 448        }
 449};
 450
 451static struct max1586_platform_data palm27x_max1587a_info = {
 452        .subdevs     = palm27x_max1587a_subdevs,
 453        .num_subdevs = ARRAY_SIZE(palm27x_max1587a_subdevs),
 454        .v3_gain     = MAX1586_GAIN_R24_3k32, /* 730..1550 mV */
 455};
 456
 457static struct i2c_board_info __initdata palm27x_pi2c_board_info[] = {
 458        {
 459                I2C_BOARD_INFO("max1586", 0x14),
 460                .platform_data  = &palm27x_max1587a_info,
 461        },
 462};
 463
 464static struct i2c_pxa_platform_data palm27x_i2c_power_info = {
 465        .use_pio        = 1,
 466};
 467
 468void __init palm27x_pmic_init(void)
 469{
 470        i2c_register_board_info(1, ARRAY_AND_SIZE(palm27x_pi2c_board_info));
 471        pxa27x_set_i2c_power_info(&palm27x_i2c_power_info);
 472}
 473#endif
 474