2008-08-29 18:47:52 +04:00
/*
* Hardware definitions for Palm Zire72
*
* Authors :
* Vladimir " Farcaller " Pouzanov < farcaller @ gmail . com >
* Sergey Lapin < slapin @ ossfans . org >
* Alex Osborne < bobofdoom @ gmail . com >
* Jan Herman < 2 hp @ 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>
2009-01-02 18:17:22 +03:00
# include <mach/pxa27x.h>
2008-08-29 18:47:52 +04:00
# 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 ,
} ;
2008-08-29 18:53:24 +04:00
# 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
2008-08-29 18:47:52 +04:00
/******************************************************************************
* 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