![Eric Miao](/assets/img/avatar_default.png)
Considering the header mess ATM, it is not always possible to include the correct header files within board code. Let's keep this simple: <mach/pxa25x.h> - for pxa25x based platforms <mach/pxa27x.h> - for pxa27x based platforms <mach/pxa300.h> - for pxa300 based platforms <mach/pxa320.h> - for pxa320 based platforms <mach/pxa930.h> - for pxa930 based platforms NOTE: 1. one header one board file, they are not compatible (i.e. they have conflicting definitions which won't compile if included together). 2. Unless strictly necessary, the following header files are considered to be SoC files use _only_, and is not recommended to be included in board code: <mach/hardware.h> <mach/pxa-regs.h> <mach/pxa2xx-regs.h> <mach/pxa3xx-regs.h> <mach/mfp.h> <mach/mfp-pxa2xx.h> <mach/mfp-pxa25x.h> <mach/mfp-pxa27x.h> <mach/mfp-pxa3xx.h> <mach/mfp-pxa300.h> <mach/mfp-pxa320.h> <mach/mfp-pxa930.h> Signed-off-by: Eric Miao <eric.miao@marvell.com>
553 lines
14 KiB
C
553 lines
14 KiB
C
/*
|
|
* Hardware definitions for Palm Zire72
|
|
*
|
|
* Authors:
|
|
* Vladimir "Farcaller" Pouzanov <farcaller@gmail.com>
|
|
* Sergey Lapin <slapin@ossfans.org>
|
|
* Alex Osborne <bobofdoom@gmail.com>
|
|
* Jan Herman <2hp@seznam.cz>
|
|
*
|
|
* Rewrite for mainline:
|
|
* Marek Vasut <marek.vasut@gmail.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* (find more info at www.hackndev.com)
|
|
*
|
|
*/
|
|
|
|
#include <linux/platform_device.h>
|
|
#include <linux/sysdev.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/irq.h>
|
|
#include <linux/gpio_keys.h>
|
|
#include <linux/input.h>
|
|
#include <linux/pda_power.h>
|
|
#include <linux/pwm_backlight.h>
|
|
#include <linux/gpio.h>
|
|
#include <linux/power_supply.h>
|
|
|
|
#include <asm/mach-types.h>
|
|
#include <asm/mach/arch.h>
|
|
#include <asm/mach/map.h>
|
|
|
|
#include <mach/pxa27x.h>
|
|
#include <mach/audio.h>
|
|
#include <mach/palmz72.h>
|
|
#include <mach/mmc.h>
|
|
#include <mach/pxafb.h>
|
|
#include <mach/irda.h>
|
|
#include <mach/pxa27x_keypad.h>
|
|
#include <mach/udc.h>
|
|
#include <mach/pm.h>
|
|
|
|
#include "generic.h"
|
|
#include "devices.h"
|
|
|
|
/******************************************************************************
|
|
* Pin configuration
|
|
******************************************************************************/
|
|
static unsigned long palmz72_pin_config[] __initdata = {
|
|
/* MMC */
|
|
GPIO32_MMC_CLK,
|
|
GPIO92_MMC_DAT_0,
|
|
GPIO109_MMC_DAT_1,
|
|
GPIO110_MMC_DAT_2,
|
|
GPIO111_MMC_DAT_3,
|
|
GPIO112_MMC_CMD,
|
|
GPIO14_GPIO, /* SD detect */
|
|
GPIO115_GPIO, /* SD RO */
|
|
GPIO98_GPIO, /* SD power */
|
|
|
|
/* AC97 */
|
|
GPIO28_AC97_BITCLK,
|
|
GPIO29_AC97_SDATA_IN_0,
|
|
GPIO30_AC97_SDATA_OUT,
|
|
GPIO31_AC97_SYNC,
|
|
|
|
/* IrDA */
|
|
GPIO49_GPIO, /* ir disable */
|
|
GPIO46_FICP_RXD,
|
|
GPIO47_FICP_TXD,
|
|
|
|
/* PWM */
|
|
GPIO16_PWM0_OUT,
|
|
|
|
/* USB */
|
|
GPIO15_GPIO, /* usb detect */
|
|
GPIO12_GPIO, /* usb pullup */
|
|
GPIO95_GPIO, /* usb power */
|
|
|
|
/* Matrix keypad */
|
|
GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH,
|
|
GPIO101_KP_MKIN_1 | WAKEUP_ON_LEVEL_HIGH,
|
|
GPIO102_KP_MKIN_2 | WAKEUP_ON_LEVEL_HIGH,
|
|
GPIO97_KP_MKIN_3 | WAKEUP_ON_LEVEL_HIGH,
|
|
GPIO103_KP_MKOUT_0,
|
|
GPIO104_KP_MKOUT_1,
|
|
GPIO105_KP_MKOUT_2,
|
|
|
|
/* LCD */
|
|
GPIO58_LCD_LDD_0,
|
|
GPIO59_LCD_LDD_1,
|
|
GPIO60_LCD_LDD_2,
|
|
GPIO61_LCD_LDD_3,
|
|
GPIO62_LCD_LDD_4,
|
|
GPIO63_LCD_LDD_5,
|
|
GPIO64_LCD_LDD_6,
|
|
GPIO65_LCD_LDD_7,
|
|
GPIO66_LCD_LDD_8,
|
|
GPIO67_LCD_LDD_9,
|
|
GPIO68_LCD_LDD_10,
|
|
GPIO69_LCD_LDD_11,
|
|
GPIO70_LCD_LDD_12,
|
|
GPIO71_LCD_LDD_13,
|
|
GPIO72_LCD_LDD_14,
|
|
GPIO73_LCD_LDD_15,
|
|
GPIO74_LCD_FCLK,
|
|
GPIO75_LCD_LCLK,
|
|
GPIO76_LCD_PCLK,
|
|
GPIO77_LCD_BIAS,
|
|
GPIO20_GPIO, /* bl power */
|
|
GPIO21_GPIO, /* LCD border switch */
|
|
GPIO22_GPIO, /* LCD border color */
|
|
GPIO96_GPIO, /* lcd power */
|
|
|
|
/* Misc. */
|
|
GPIO0_GPIO | WAKEUP_ON_LEVEL_HIGH, /* power detect */
|
|
GPIO88_GPIO, /* green led */
|
|
GPIO27_GPIO, /* WM9712 IRQ */
|
|
};
|
|
|
|
/******************************************************************************
|
|
* SD/MMC card controller
|
|
******************************************************************************/
|
|
static int palmz72_mci_init(struct device *dev,
|
|
irq_handler_t palmz72_detect_int, void *data)
|
|
{
|
|
int err = 0;
|
|
|
|
/* Setup an interrupt for detecting card insert/remove events */
|
|
err = gpio_request(GPIO_NR_PALMZ72_SD_DETECT_N, "SD IRQ");
|
|
if (err)
|
|
goto err;
|
|
err = gpio_direction_input(GPIO_NR_PALMZ72_SD_DETECT_N);
|
|
if (err)
|
|
goto err2;
|
|
err = request_irq(gpio_to_irq(GPIO_NR_PALMZ72_SD_DETECT_N),
|
|
palmz72_detect_int, IRQF_DISABLED | IRQF_SAMPLE_RANDOM |
|
|
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
|
|
"SD/MMC card detect", data);
|
|
if (err) {
|
|
printk(KERN_ERR "%s: cannot request SD/MMC card detect IRQ\n",
|
|
__func__);
|
|
goto err2;
|
|
}
|
|
|
|
/* SD_POWER is not actually power, but it is more like chip
|
|
* select, i.e. it is inverted */
|
|
|
|
err = gpio_request(GPIO_NR_PALMZ72_SD_POWER_N, "SD_POWER");
|
|
if (err)
|
|
goto err3;
|
|
err = gpio_direction_output(GPIO_NR_PALMZ72_SD_POWER_N, 0);
|
|
if (err)
|
|
goto err4;
|
|
err = gpio_request(GPIO_NR_PALMZ72_SD_RO, "SD_RO");
|
|
if (err)
|
|
goto err4;
|
|
err = gpio_direction_input(GPIO_NR_PALMZ72_SD_RO);
|
|
if (err)
|
|
goto err5;
|
|
|
|
printk(KERN_DEBUG "%s: irq registered\n", __func__);
|
|
|
|
return 0;
|
|
|
|
err5:
|
|
gpio_free(GPIO_NR_PALMZ72_SD_RO);
|
|
err4:
|
|
gpio_free(GPIO_NR_PALMZ72_SD_POWER_N);
|
|
err3:
|
|
free_irq(gpio_to_irq(GPIO_NR_PALMZ72_SD_DETECT_N), data);
|
|
err2:
|
|
gpio_free(GPIO_NR_PALMZ72_SD_DETECT_N);
|
|
err:
|
|
return err;
|
|
}
|
|
|
|
static void palmz72_mci_exit(struct device *dev, void *data)
|
|
{
|
|
gpio_free(GPIO_NR_PALMZ72_SD_POWER_N);
|
|
free_irq(gpio_to_irq(GPIO_NR_PALMZ72_SD_DETECT_N), data);
|
|
gpio_free(GPIO_NR_PALMZ72_SD_DETECT_N);
|
|
gpio_free(GPIO_NR_PALMZ72_SD_RO);
|
|
}
|
|
|
|
static void palmz72_mci_power(struct device *dev, unsigned int vdd)
|
|
{
|
|
struct pxamci_platform_data *p_d = dev->platform_data;
|
|
if (p_d->ocr_mask & (1 << vdd))
|
|
gpio_set_value(GPIO_NR_PALMZ72_SD_POWER_N, 0);
|
|
else
|
|
gpio_set_value(GPIO_NR_PALMZ72_SD_POWER_N, 1);
|
|
}
|
|
|
|
static int palmz72_mci_ro(struct device *dev)
|
|
{
|
|
return gpio_get_value(GPIO_NR_PALMZ72_SD_RO);
|
|
}
|
|
|
|
static struct pxamci_platform_data palmz72_mci_platform_data = {
|
|
.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
|
|
.setpower = palmz72_mci_power,
|
|
.get_ro = palmz72_mci_ro,
|
|
.init = palmz72_mci_init,
|
|
.exit = palmz72_mci_exit,
|
|
};
|
|
|
|
/******************************************************************************
|
|
* GPIO keyboard
|
|
******************************************************************************/
|
|
static unsigned int palmz72_matrix_keys[] = {
|
|
KEY(0, 0, KEY_POWER),
|
|
KEY(0, 1, KEY_F1),
|
|
KEY(0, 2, KEY_ENTER),
|
|
|
|
KEY(1, 0, KEY_F2),
|
|
KEY(1, 1, KEY_F3),
|
|
KEY(1, 2, KEY_F4),
|
|
|
|
KEY(2, 0, KEY_UP),
|
|
KEY(2, 2, KEY_DOWN),
|
|
|
|
KEY(3, 0, KEY_RIGHT),
|
|
KEY(3, 2, KEY_LEFT),
|
|
};
|
|
|
|
static struct pxa27x_keypad_platform_data palmz72_keypad_platform_data = {
|
|
.matrix_key_rows = 4,
|
|
.matrix_key_cols = 3,
|
|
.matrix_key_map = palmz72_matrix_keys,
|
|
.matrix_key_map_size = ARRAY_SIZE(palmz72_matrix_keys),
|
|
|
|
.debounce_interval = 30,
|
|
};
|
|
|
|
/******************************************************************************
|
|
* Backlight
|
|
******************************************************************************/
|
|
static int palmz72_backlight_init(struct device *dev)
|
|
{
|
|
int ret;
|
|
|
|
ret = gpio_request(GPIO_NR_PALMZ72_BL_POWER, "BL POWER");
|
|
if (ret)
|
|
goto err;
|
|
ret = gpio_direction_output(GPIO_NR_PALMZ72_BL_POWER, 0);
|
|
if (ret)
|
|
goto err2;
|
|
ret = gpio_request(GPIO_NR_PALMZ72_LCD_POWER, "LCD POWER");
|
|
if (ret)
|
|
goto err2;
|
|
ret = gpio_direction_output(GPIO_NR_PALMZ72_LCD_POWER, 0);
|
|
if (ret)
|
|
goto err3;
|
|
|
|
return 0;
|
|
err3:
|
|
gpio_free(GPIO_NR_PALMZ72_LCD_POWER);
|
|
err2:
|
|
gpio_free(GPIO_NR_PALMZ72_BL_POWER);
|
|
err:
|
|
return ret;
|
|
}
|
|
|
|
static int palmz72_backlight_notify(int brightness)
|
|
{
|
|
gpio_set_value(GPIO_NR_PALMZ72_BL_POWER, brightness);
|
|
gpio_set_value(GPIO_NR_PALMZ72_LCD_POWER, brightness);
|
|
return brightness;
|
|
}
|
|
|
|
static void palmz72_backlight_exit(struct device *dev)
|
|
{
|
|
gpio_free(GPIO_NR_PALMZ72_BL_POWER);
|
|
gpio_free(GPIO_NR_PALMZ72_LCD_POWER);
|
|
}
|
|
|
|
static struct platform_pwm_backlight_data palmz72_backlight_data = {
|
|
.pwm_id = 0,
|
|
.max_brightness = PALMZ72_MAX_INTENSITY,
|
|
.dft_brightness = PALMZ72_MAX_INTENSITY,
|
|
.pwm_period_ns = PALMZ72_PERIOD_NS,
|
|
.init = palmz72_backlight_init,
|
|
.notify = palmz72_backlight_notify,
|
|
.exit = palmz72_backlight_exit,
|
|
};
|
|
|
|
static struct platform_device palmz72_backlight = {
|
|
.name = "pwm-backlight",
|
|
.dev = {
|
|
.parent = &pxa27x_device_pwm0.dev,
|
|
.platform_data = &palmz72_backlight_data,
|
|
},
|
|
};
|
|
|
|
/******************************************************************************
|
|
* IrDA
|
|
******************************************************************************/
|
|
static int palmz72_irda_startup(struct device *dev)
|
|
{
|
|
int err;
|
|
err = gpio_request(GPIO_NR_PALMZ72_IR_DISABLE, "IR DISABLE");
|
|
if (err)
|
|
goto err;
|
|
err = gpio_direction_output(GPIO_NR_PALMZ72_IR_DISABLE, 1);
|
|
if (err)
|
|
gpio_free(GPIO_NR_PALMZ72_IR_DISABLE);
|
|
err:
|
|
return err;
|
|
}
|
|
|
|
static void palmz72_irda_shutdown(struct device *dev)
|
|
{
|
|
gpio_free(GPIO_NR_PALMZ72_IR_DISABLE);
|
|
}
|
|
|
|
static void palmz72_irda_transceiver_mode(struct device *dev, int mode)
|
|
{
|
|
gpio_set_value(GPIO_NR_PALMZ72_IR_DISABLE, mode & IR_OFF);
|
|
pxa2xx_transceiver_mode(dev, mode);
|
|
}
|
|
|
|
static struct pxaficp_platform_data palmz72_ficp_platform_data = {
|
|
.startup = palmz72_irda_startup,
|
|
.shutdown = palmz72_irda_shutdown,
|
|
.transceiver_cap = IR_SIRMODE | IR_OFF,
|
|
.transceiver_mode = palmz72_irda_transceiver_mode,
|
|
};
|
|
|
|
/******************************************************************************
|
|
* LEDs
|
|
******************************************************************************/
|
|
static struct gpio_led gpio_leds[] = {
|
|
{
|
|
.name = "palmz72:green:led",
|
|
.default_trigger = "none",
|
|
.gpio = GPIO_NR_PALMZ72_LED_GREEN,
|
|
},
|
|
};
|
|
|
|
static struct gpio_led_platform_data gpio_led_info = {
|
|
.leds = gpio_leds,
|
|
.num_leds = ARRAY_SIZE(gpio_leds),
|
|
};
|
|
|
|
static struct platform_device palmz72_leds = {
|
|
.name = "leds-gpio",
|
|
.id = -1,
|
|
.dev = {
|
|
.platform_data = &gpio_led_info,
|
|
}
|
|
};
|
|
|
|
/******************************************************************************
|
|
* Power supply
|
|
******************************************************************************/
|
|
static int power_supply_init(struct device *dev)
|
|
{
|
|
int ret;
|
|
|
|
ret = gpio_request(GPIO_NR_PALMZ72_POWER_DETECT, "CABLE_STATE_AC");
|
|
if (ret)
|
|
goto err1;
|
|
ret = gpio_direction_input(GPIO_NR_PALMZ72_POWER_DETECT);
|
|
if (ret)
|
|
goto err2;
|
|
|
|
ret = gpio_request(GPIO_NR_PALMZ72_USB_DETECT_N, "CABLE_STATE_USB");
|
|
if (ret)
|
|
goto err2;
|
|
ret = gpio_direction_input(GPIO_NR_PALMZ72_USB_DETECT_N);
|
|
if (ret)
|
|
goto err3;
|
|
|
|
return 0;
|
|
err3:
|
|
gpio_free(GPIO_NR_PALMZ72_USB_DETECT_N);
|
|
err2:
|
|
gpio_free(GPIO_NR_PALMZ72_POWER_DETECT);
|
|
err1:
|
|
return ret;
|
|
}
|
|
|
|
static int palmz72_is_ac_online(void)
|
|
{
|
|
return gpio_get_value(GPIO_NR_PALMZ72_POWER_DETECT);
|
|
}
|
|
|
|
static int palmz72_is_usb_online(void)
|
|
{
|
|
return !gpio_get_value(GPIO_NR_PALMZ72_USB_DETECT_N);
|
|
}
|
|
|
|
static void power_supply_exit(struct device *dev)
|
|
{
|
|
gpio_free(GPIO_NR_PALMZ72_USB_DETECT_N);
|
|
gpio_free(GPIO_NR_PALMZ72_POWER_DETECT);
|
|
}
|
|
|
|
static char *palmz72_supplicants[] = {
|
|
"main-battery",
|
|
};
|
|
|
|
static struct pda_power_pdata power_supply_info = {
|
|
.init = power_supply_init,
|
|
.is_ac_online = palmz72_is_ac_online,
|
|
.is_usb_online = palmz72_is_usb_online,
|
|
.exit = power_supply_exit,
|
|
.supplied_to = palmz72_supplicants,
|
|
.num_supplicants = ARRAY_SIZE(palmz72_supplicants),
|
|
};
|
|
|
|
static struct platform_device power_supply = {
|
|
.name = "pda-power",
|
|
.id = -1,
|
|
.dev = {
|
|
.platform_data = &power_supply_info,
|
|
},
|
|
};
|
|
|
|
/******************************************************************************
|
|
* Framebuffer
|
|
******************************************************************************/
|
|
static struct pxafb_mode_info palmz72_lcd_modes[] = {
|
|
{
|
|
.pixclock = 115384,
|
|
.xres = 320,
|
|
.yres = 320,
|
|
.bpp = 16,
|
|
|
|
.left_margin = 27,
|
|
.right_margin = 7,
|
|
.upper_margin = 7,
|
|
.lower_margin = 8,
|
|
|
|
.hsync_len = 6,
|
|
.vsync_len = 1,
|
|
},
|
|
};
|
|
|
|
static struct pxafb_mach_info palmz72_lcd_screen = {
|
|
.modes = palmz72_lcd_modes,
|
|
.num_modes = ARRAY_SIZE(palmz72_lcd_modes),
|
|
.lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
|
|
};
|
|
|
|
#ifdef CONFIG_PM
|
|
|
|
/* We have some black magic here
|
|
* PalmOS ROM on recover expects special struct physical address
|
|
* to be transferred via PSPR. Using this struct PalmOS restores
|
|
* its state after sleep. As for Linux, we need to setup it the
|
|
* same way. More than that, PalmOS ROM changes some values in memory.
|
|
* For now only one location is found, which needs special treatment.
|
|
* Thanks to Alex Osborne, Andrzej Zaborowski, and lots of other people
|
|
* for reading backtraces for me :)
|
|
*/
|
|
|
|
#define PALMZ72_SAVE_DWORD ((unsigned long *)0xc0000050)
|
|
|
|
static struct palmz72_resume_info palmz72_resume_info = {
|
|
.magic0 = 0xb4e6,
|
|
.magic1 = 1,
|
|
|
|
/* reset state, MMU off etc */
|
|
.arm_control = 0,
|
|
.aux_control = 0,
|
|
.ttb = 0,
|
|
.domain_access = 0,
|
|
.process_id = 0,
|
|
};
|
|
|
|
static unsigned long store_ptr;
|
|
|
|
/* sys_device for Palm Zire 72 PM */
|
|
|
|
static int palmz72_pm_suspend(struct sys_device *dev, pm_message_t msg)
|
|
{
|
|
/* setup the resume_info struct for the original bootloader */
|
|
palmz72_resume_info.resume_addr = (u32) pxa_cpu_resume;
|
|
|
|
/* Storing memory touched by ROM */
|
|
store_ptr = *PALMZ72_SAVE_DWORD;
|
|
|
|
/* Setting PSPR to a proper value */
|
|
PSPR = virt_to_phys(&palmz72_resume_info);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int palmz72_pm_resume(struct sys_device *dev)
|
|
{
|
|
*PALMZ72_SAVE_DWORD = store_ptr;
|
|
return 0;
|
|
}
|
|
|
|
static struct sysdev_class palmz72_pm_sysclass = {
|
|
.name = "palmz72_pm",
|
|
.suspend = palmz72_pm_suspend,
|
|
.resume = palmz72_pm_resume,
|
|
};
|
|
|
|
static struct sys_device palmz72_pm_device = {
|
|
.cls = &palmz72_pm_sysclass,
|
|
};
|
|
|
|
static int __init palmz72_pm_init(void)
|
|
{
|
|
int ret = -ENODEV;
|
|
if (machine_is_palmz72()) {
|
|
ret = sysdev_class_register(&palmz72_pm_sysclass);
|
|
if (ret == 0)
|
|
ret = sysdev_register(&palmz72_pm_device);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
device_initcall(palmz72_pm_init);
|
|
#endif
|
|
|
|
/******************************************************************************
|
|
* Machine init
|
|
******************************************************************************/
|
|
static struct platform_device *devices[] __initdata = {
|
|
&palmz72_backlight,
|
|
&palmz72_leds,
|
|
&power_supply,
|
|
};
|
|
|
|
static void __init palmz72_init(void)
|
|
{
|
|
pxa2xx_mfp_config(ARRAY_AND_SIZE(palmz72_pin_config));
|
|
set_pxa_fb_info(&palmz72_lcd_screen);
|
|
pxa_set_mci_info(&palmz72_mci_platform_data);
|
|
pxa_set_ac97_info(NULL);
|
|
pxa_set_ficp_info(&palmz72_ficp_platform_data);
|
|
pxa_set_keypad_info(&palmz72_keypad_platform_data);
|
|
platform_add_devices(devices, ARRAY_SIZE(devices));
|
|
}
|
|
|
|
MACHINE_START(PALMZ72, "Palm Zire72")
|
|
.phys_io = 0x40000000,
|
|
.io_pg_offst = io_p2v(0x40000000),
|
|
.boot_params = 0xa0000100,
|
|
.map_io = pxa_map_io,
|
|
.init_irq = pxa27x_init_irq,
|
|
.timer = &pxa_timer,
|
|
.init_machine = palmz72_init
|
|
MACHINE_END
|