2005-04-17 02:20:36 +04:00
/*
* linux / arch / arm / mach - pxa / pxa27x . c
*
* Author : Nicolas Pitre
* Created : Nov 05 , 2002
* Copyright : MontaVista Software Inc .
*
* Code specific to PXA27x aka Bulverde .
*
* 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 .
*/
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/init.h>
2007-10-18 14:04:39 +04:00
# include <linux/suspend.h>
2005-10-29 22:07:23 +04:00
# include <linux/platform_device.h>
2011-04-23 00:03:11 +04:00
# include <linux/syscore_ops.h>
2010-11-03 18:29:35 +03:00
# include <linux/io.h>
2010-11-29 13:18:26 +03:00
# include <linux/irq.h>
2011-02-23 14:38:16 +03:00
# include <linux/i2c/pxa-i2c.h>
2005-04-17 02:20:36 +04:00
2010-10-11 04:20:19 +04:00
# include <asm/mach/map.h>
2008-08-05 19:14:15 +04:00
# include <mach/hardware.h>
2005-04-17 02:20:36 +04:00
# include <asm/irq.h>
2008-08-05 19:14:15 +04:00
# include <mach/irqs.h>
2009-01-06 12:37:37 +03:00
# include <mach/gpio.h>
2009-01-02 18:17:22 +03:00
# include <mach/pxa27x.h>
2008-08-07 14:05:25 +04:00
# include <mach/reset.h>
2008-08-05 19:14:15 +04:00
# include <mach/ohci.h>
# include <mach/pm.h>
# include <mach/dma.h>
2010-11-03 18:29:35 +03:00
# include <mach/smemc.h>
2005-04-17 02:20:36 +04:00
# include "generic.h"
2007-05-15 18:39:36 +04:00
# include "devices.h"
2007-08-20 13:18:02 +04:00
# include "clock.h"
2005-04-17 02:20:36 +04:00
2008-10-04 08:45:39 +04:00
void pxa27x_clear_otgph ( void )
{
if ( cpu_is_pxa27x ( ) & & ( PSSR & PSSR_OTGPH ) )
PSSR | = PSSR_OTGPH ;
}
EXPORT_SYMBOL ( pxa27x_clear_otgph ) ;
2010-01-04 11:30:58 +03:00
static unsigned long ac97_reset_config [ ] = {
GPIO113_GPIO ,
2010-07-13 05:41:28 +04:00
GPIO113_AC97_nRESET ,
GPIO95_GPIO ,
GPIO95_AC97_nRESET ,
2010-01-04 11:30:58 +03:00
} ;
void pxa27x_assert_ac97reset ( int reset_gpio , int on )
{
if ( reset_gpio = = 113 )
pxa2xx_mfp_config ( on ? & ac97_reset_config [ 0 ] :
& ac97_reset_config [ 1 ] , 1 ) ;
if ( reset_gpio = = 95 )
pxa2xx_mfp_config ( on ? & ac97_reset_config [ 2 ] :
& ac97_reset_config [ 3 ] , 1 ) ;
}
EXPORT_SYMBOL_GPL ( pxa27x_assert_ac97reset ) ;
2005-04-17 02:20:36 +04:00
/* Crystal clock: 13MHz */
# define BASE_CLK 13000000
/*
* Get the clock frequency as reflected by CCSR and the turbo flag .
* We assume these values have been applied via a fcs .
* If info is not 0 we also display the current settings .
*/
2007-08-20 13:07:44 +04:00
unsigned int pxa27x_get_clk_frequency_khz ( int info )
2005-04-17 02:20:36 +04:00
{
unsigned long ccsr , clkcfg ;
unsigned int l , L , m , M , n2 , N , S ;
int cccr_a , t , ht , b ;
ccsr = CCSR ;
cccr_a = CCCR & ( 1 < < 25 ) ;
/* Read clkcfg register: it has turbo, b, half-turbo (and f) */
asm ( " mrc \t p14, 0, %0, c6, c0, 0 " : " =r " ( clkcfg ) ) ;
2006-02-01 22:25:59 +03:00
t = clkcfg & ( 1 < < 0 ) ;
2005-04-17 02:20:36 +04:00
ht = clkcfg & ( 1 < < 2 ) ;
b = clkcfg & ( 1 < < 3 ) ;
l = ccsr & 0x1f ;
n2 = ( ccsr > > 7 ) & 0xf ;
m = ( l < = 10 ) ? 1 : ( l < = 20 ) ? 2 : 4 ;
L = l * BASE_CLK ;
N = ( L * n2 ) / 2 ;
M = ( ! cccr_a ) ? ( L / m ) : ( ( b ) ? L : ( L / 2 ) ) ;
S = ( b ) ? L : ( L / 2 ) ;
if ( info ) {
printk ( KERN_INFO " Run Mode clock: %d.%02dMHz (*%d) \n " ,
L / 1000000 , ( L % 1000000 ) / 10000 , l ) ;
printk ( KERN_INFO " Turbo Mode clock: %d.%02dMHz (*%d.%d, %sactive) \n " ,
N / 1000000 , ( N % 1000000 ) / 10000 , n2 / 2 , ( n2 % 2 ) * 5 ,
( t ) ? " " : " in " ) ;
printk ( KERN_INFO " Memory clock: %d.%02dMHz (/%d) \n " ,
M / 1000000 , ( M % 1000000 ) / 10000 , m ) ;
printk ( KERN_INFO " System bus clock: %d.%02dMHz \n " ,
S / 1000000 , ( S % 1000000 ) / 10000 ) ;
}
return ( t ) ? ( N / 1000 ) : ( L / 1000 ) ;
}
/*
2010-11-22 17:48:49 +03:00
* Return the current mem clock frequency as reflected by CCCR [ A ] , B , and L
2005-04-17 02:20:36 +04:00
*/
2010-11-22 17:48:49 +03:00
static unsigned long clk_pxa27x_mem_getrate ( struct clk * clk )
2005-04-17 02:20:36 +04:00
{
unsigned long ccsr , clkcfg ;
unsigned int l , L , m , M ;
int cccr_a , b ;
ccsr = CCSR ;
cccr_a = CCCR & ( 1 < < 25 ) ;
/* Read clkcfg register: it has turbo, b, half-turbo (and f) */
asm ( " mrc \t p14, 0, %0, c6, c0, 0 " : " =r " ( clkcfg ) ) ;
b = clkcfg & ( 1 < < 3 ) ;
l = ccsr & 0x1f ;
m = ( l < = 10 ) ? 1 : ( l < = 20 ) ? 2 : 4 ;
L = l * BASE_CLK ;
M = ( ! cccr_a ) ? ( L / m ) : ( ( b ) ? L : ( L / 2 ) ) ;
2010-11-22 17:48:49 +03:00
return M ;
2005-04-17 02:20:36 +04:00
}
2010-11-22 17:48:49 +03:00
static const struct clkops clk_pxa27x_mem_ops = {
. enable = clk_dummy_enable ,
. disable = clk_dummy_disable ,
. getrate = clk_pxa27x_mem_getrate ,
} ;
2005-04-17 02:20:36 +04:00
/*
* Return the current LCD clock frequency in units of 10 kHz as
*/
2007-08-20 13:34:37 +04:00
static unsigned int pxa27x_get_lcdclk_frequency_10khz ( void )
2005-04-17 02:20:36 +04:00
{
unsigned long ccsr ;
unsigned int l , L , k , K ;
ccsr = CCSR ;
l = ccsr & 0x1f ;
k = ( l < = 7 ) ? 1 : ( l < = 16 ) ? 2 : 4 ;
L = l * BASE_CLK ;
K = L / k ;
return ( K / 10000 ) ;
}
2007-08-20 13:18:02 +04:00
static unsigned long clk_pxa27x_lcd_getrate ( struct clk * clk )
{
return pxa27x_get_lcdclk_frequency_10khz ( ) * 10000 ;
}
static const struct clkops clk_pxa27x_lcd_ops = {
2010-11-22 05:49:55 +03:00
. enable = clk_pxa2xx_cken_enable ,
. disable = clk_pxa2xx_cken_disable ,
2007-08-20 13:18:02 +04:00
. getrate = clk_pxa27x_lcd_getrate ,
} ;
2010-11-22 05:49:55 +03:00
static DEFINE_PXA2_CKEN ( pxa27x_ffuart , FFUART , 14857000 , 1 ) ;
static DEFINE_PXA2_CKEN ( pxa27x_btuart , BTUART , 14857000 , 1 ) ;
static DEFINE_PXA2_CKEN ( pxa27x_stuart , STUART , 14857000 , 1 ) ;
static DEFINE_PXA2_CKEN ( pxa27x_i2s , I2S , 14682000 , 0 ) ;
static DEFINE_PXA2_CKEN ( pxa27x_i2c , I2C , 32842000 , 0 ) ;
static DEFINE_PXA2_CKEN ( pxa27x_usb , USB , 48000000 , 5 ) ;
static DEFINE_PXA2_CKEN ( pxa27x_mmc , MMC , 19500000 , 0 ) ;
static DEFINE_PXA2_CKEN ( pxa27x_ficp , FICP , 48000000 , 0 ) ;
static DEFINE_PXA2_CKEN ( pxa27x_usbhost , USBHOST , 48000000 , 0 ) ;
static DEFINE_PXA2_CKEN ( pxa27x_pwri2c , PWRI2C , 13000000 , 0 ) ;
static DEFINE_PXA2_CKEN ( pxa27x_keypad , KEYPAD , 32768 , 0 ) ;
static DEFINE_PXA2_CKEN ( pxa27x_ssp1 , SSP1 , 13000000 , 0 ) ;
static DEFINE_PXA2_CKEN ( pxa27x_ssp2 , SSP2 , 13000000 , 0 ) ;
static DEFINE_PXA2_CKEN ( pxa27x_ssp3 , SSP3 , 13000000 , 0 ) ;
static DEFINE_PXA2_CKEN ( pxa27x_pwm0 , PWM0 , 13000000 , 0 ) ;
static DEFINE_PXA2_CKEN ( pxa27x_pwm1 , PWM1 , 13000000 , 0 ) ;
static DEFINE_PXA2_CKEN ( pxa27x_ac97 , AC97 , 24576000 , 0 ) ;
static DEFINE_PXA2_CKEN ( pxa27x_ac97conf , AC97CONF , 24576000 , 0 ) ;
static DEFINE_PXA2_CKEN ( pxa27x_msl , MSL , 48000000 , 0 ) ;
static DEFINE_PXA2_CKEN ( pxa27x_usim , USIM , 48000000 , 0 ) ;
static DEFINE_PXA2_CKEN ( pxa27x_memstk , MEMSTK , 19500000 , 0 ) ;
static DEFINE_PXA2_CKEN ( pxa27x_im , IM , 0 , 0 ) ;
static DEFINE_PXA2_CKEN ( pxa27x_memc , MEMC , 0 , 0 ) ;
2008-11-08 23:25:21 +03:00
static DEFINE_CK ( pxa27x_lcd , LCD , & clk_pxa27x_lcd_ops ) ;
static DEFINE_CK ( pxa27x_camera , CAMERA , & clk_pxa27x_lcd_ops ) ;
2010-11-22 17:48:49 +03:00
static DEFINE_CLK ( pxa27x_mem , & clk_pxa27x_mem_ops , 0 , 0 ) ;
2008-11-08 23:25:21 +03:00
static struct clk_lookup pxa27x_clkregs [ ] = {
INIT_CLKREG ( & clk_pxa27x_lcd , " pxa2xx-fb " , NULL ) ,
INIT_CLKREG ( & clk_pxa27x_camera , " pxa27x-camera.0 " , NULL ) ,
INIT_CLKREG ( & clk_pxa27x_ffuart , " pxa2xx-uart.0 " , NULL ) ,
INIT_CLKREG ( & clk_pxa27x_btuart , " pxa2xx-uart.1 " , NULL ) ,
INIT_CLKREG ( & clk_pxa27x_stuart , " pxa2xx-uart.2 " , NULL ) ,
INIT_CLKREG ( & clk_pxa27x_i2s , " pxa2xx-i2s " , NULL ) ,
INIT_CLKREG ( & clk_pxa27x_i2c , " pxa2xx-i2c.0 " , NULL ) ,
INIT_CLKREG ( & clk_pxa27x_usb , " pxa27x-udc " , NULL ) ,
INIT_CLKREG ( & clk_pxa27x_mmc , " pxa2xx-mci.0 " , NULL ) ,
INIT_CLKREG ( & clk_pxa27x_stuart , " pxa2xx-ir " , " UARTCLK " ) ,
INIT_CLKREG ( & clk_pxa27x_ficp , " pxa2xx-ir " , " FICPCLK " ) ,
INIT_CLKREG ( & clk_pxa27x_usbhost , " pxa27x-ohci " , NULL ) ,
INIT_CLKREG ( & clk_pxa27x_pwri2c , " pxa2xx-i2c.1 " , NULL ) ,
INIT_CLKREG ( & clk_pxa27x_keypad , " pxa27x-keypad " , NULL ) ,
INIT_CLKREG ( & clk_pxa27x_ssp1 , " pxa27x-ssp.0 " , NULL ) ,
INIT_CLKREG ( & clk_pxa27x_ssp2 , " pxa27x-ssp.1 " , NULL ) ,
INIT_CLKREG ( & clk_pxa27x_ssp3 , " pxa27x-ssp.2 " , NULL ) ,
INIT_CLKREG ( & clk_pxa27x_pwm0 , " pxa27x-pwm.0 " , NULL ) ,
INIT_CLKREG ( & clk_pxa27x_pwm1 , " pxa27x-pwm.1 " , NULL ) ,
INIT_CLKREG ( & clk_pxa27x_ac97 , NULL , " AC97CLK " ) ,
INIT_CLKREG ( & clk_pxa27x_ac97conf , NULL , " AC97CONFCLK " ) ,
INIT_CLKREG ( & clk_pxa27x_msl , NULL , " MSLCLK " ) ,
INIT_CLKREG ( & clk_pxa27x_usim , NULL , " USIMCLK " ) ,
INIT_CLKREG ( & clk_pxa27x_memstk , NULL , " MSTKCLK " ) ,
INIT_CLKREG ( & clk_pxa27x_im , NULL , " IMCLK " ) ,
INIT_CLKREG ( & clk_pxa27x_memc , NULL , " MEMCLK " ) ,
2010-11-22 17:48:49 +03:00
INIT_CLKREG ( & clk_pxa27x_mem , " pxa2xx-pcmcia " , NULL ) ,
2007-08-20 13:18:02 +04:00
} ;
2005-06-14 01:35:41 +04:00
# ifdef CONFIG_PM
2007-07-18 14:38:45 +04:00
# define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
# define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
2009-05-26 10:10:18 +04:00
/*
* allow platforms to override default PWRMODE setting used for PM_SUSPEND_MEM
*/
static unsigned int pwrmode = PWRMODE_SLEEP ;
int __init pxa27x_set_pwrmode ( unsigned int mode )
{
switch ( mode ) {
case PWRMODE_SLEEP :
case PWRMODE_DEEPSLEEP :
pwrmode = mode ;
return 0 ;
}
return - EINVAL ;
}
2007-07-18 14:38:45 +04:00
/*
* List of global PXA peripheral registers to preserve .
* More ones like CP and general purpose register values are preserved
* with the stack pointer in sleep . S .
*/
2008-09-03 14:06:34 +04:00
enum {
2007-07-18 14:38:45 +04:00
SLEEP_SAVE_PSTR ,
SLEEP_SAVE_MDREFR ,
2008-09-03 14:06:34 +04:00
SLEEP_SAVE_PCFR ,
2008-05-03 00:17:06 +04:00
SLEEP_SAVE_COUNT
2007-07-18 14:38:45 +04:00
} ;
void pxa27x_cpu_pm_save ( unsigned long * sleep_save )
{
2010-11-03 18:29:35 +03:00
sleep_save [ SLEEP_SAVE_MDREFR ] = __raw_readl ( MDREFR ) ;
2008-09-03 14:06:34 +04:00
SAVE ( PCFR ) ;
2007-07-18 14:38:45 +04:00
SAVE ( PSTR ) ;
}
void pxa27x_cpu_pm_restore ( unsigned long * sleep_save )
{
2010-11-03 18:29:35 +03:00
__raw_writel ( sleep_save [ SLEEP_SAVE_MDREFR ] , MDREFR ) ;
2008-09-03 14:06:34 +04:00
RESTORE ( PCFR ) ;
2007-07-18 14:38:45 +04:00
PSSR = PSSR_RDH | PSSR_PH ;
RESTORE ( PSTR ) ;
}
void pxa27x_cpu_pm_enter ( suspend_state_t state )
2005-06-03 23:52:27 +04:00
{
extern void pxa_cpu_standby ( void ) ;
/* ensure voltage-change sequencer not initiated, which hangs */
PCFR & = ~ PCFR_FVC ;
/* Clear edge-detect status register. */
PEDR = 0xDF12FE1B ;
2008-05-08 19:50:39 +04:00
/* Clear reset status */
RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR ;
2005-06-03 23:52:27 +04:00
switch ( state ) {
2005-07-01 14:27:05 +04:00
case PM_SUSPEND_STANDBY :
pxa_cpu_standby ( ) ;
break ;
2005-06-03 23:52:27 +04:00
case PM_SUSPEND_MEM :
2011-02-06 20:41:26 +03:00
pxa27x_cpu_suspend ( pwrmode , PLAT_PHYS_OFFSET - PAGE_OFFSET ) ;
2005-06-03 23:52:27 +04:00
break ;
}
}
2005-04-17 02:20:36 +04:00
2007-07-18 14:38:45 +04:00
static int pxa27x_cpu_pm_valid ( suspend_state_t state )
2007-05-15 14:22:48 +04:00
{
return state = = PM_SUSPEND_MEM | | state = = PM_SUSPEND_STANDBY ;
}
2008-08-27 15:55:04 +04:00
static int pxa27x_cpu_pm_prepare ( void )
{
/* set resume return address */
2011-02-06 20:41:26 +03:00
PSPR = virt_to_phys ( cpu_resume ) ;
2008-08-27 15:55:04 +04:00
return 0 ;
}
static void pxa27x_cpu_pm_finish ( void )
{
/* ensure not to come back here if it wasn't intended */
PSPR = 0 ;
}
2007-07-18 14:38:45 +04:00
static struct pxa_cpu_pm_fns pxa27x_cpu_pm_fns = {
2008-05-03 00:17:06 +04:00
. save_count = SLEEP_SAVE_COUNT ,
2007-07-18 14:38:45 +04:00
. save = pxa27x_cpu_pm_save ,
. restore = pxa27x_cpu_pm_restore ,
. valid = pxa27x_cpu_pm_valid ,
. enter = pxa27x_cpu_pm_enter ,
2008-08-27 15:55:04 +04:00
. prepare = pxa27x_cpu_pm_prepare ,
. finish = pxa27x_cpu_pm_finish ,
2007-05-15 14:16:10 +04:00
} ;
2007-07-18 14:38:45 +04:00
static void __init pxa27x_init_pm ( void )
{
pxa_cpu_pm_fns = & pxa27x_cpu_pm_fns ;
}
2008-01-02 03:24:49 +03:00
# else
static inline void pxa27x_init_pm ( void ) { }
2005-06-14 01:35:41 +04:00
# endif
2007-08-29 13:22:17 +04:00
/* PXA27x: Various gpios can issue wakeup events. This logic only
* handles the simple cases , not the WEMUX2 and WEMUX3 options
*/
2010-11-29 13:18:26 +03:00
static int pxa27x_set_wake ( struct irq_data * d , unsigned int on )
2007-08-29 13:22:17 +04:00
{
2011-04-12 14:39:39 +04:00
int gpio = irq_to_gpio ( d - > irq ) ;
2007-08-29 13:22:17 +04:00
uint32_t mask ;
2008-03-11 04:46:28 +03:00
if ( gpio > = 0 & & gpio < 128 )
return gpio_set_wake ( gpio , on ) ;
2007-08-29 13:22:17 +04:00
2010-11-29 13:18:26 +03:00
if ( d - > irq = = IRQ_KEYPAD )
2008-03-11 04:46:28 +03:00
return keypad_set_wake ( on ) ;
2007-08-29 13:22:17 +04:00
2010-11-29 13:18:26 +03:00
switch ( d - > irq ) {
2007-08-29 13:22:17 +04:00
case IRQ_RTCAlrm :
mask = PWER_RTC ;
break ;
case IRQ_USB :
mask = 1u < < 26 ;
break ;
default :
return - EINVAL ;
}
if ( on )
PWER | = mask ;
else
PWER & = ~ mask ;
return 0 ;
}
void __init pxa27x_init_irq ( void )
{
2008-03-04 09:19:58 +03:00
pxa_init_irq ( 34 , pxa27x_set_wake ) ;
2009-01-06 12:37:37 +03:00
pxa_init_gpio ( IRQ_GPIO_2_x , 2 , 120 , pxa27x_set_wake ) ;
2007-08-29 13:22:17 +04:00
}
2010-10-11 04:20:19 +04:00
static struct map_desc pxa27x_io_desc [ ] __initdata = {
{ /* Mem Ctl */
2010-11-03 18:29:35 +03:00
. virtual = SMEMC_VIRT ,
. pfn = __phys_to_pfn ( PXA2XX_SMEMC_BASE ) ,
2010-10-11 04:20:19 +04:00
. length = 0x00200000 ,
. type = MT_DEVICE
} , { /* IMem ctl */
. virtual = 0xfe000000 ,
. pfn = __phys_to_pfn ( 0x58000000 ) ,
. length = 0x00100000 ,
. type = MT_DEVICE
} ,
} ;
void __init pxa27x_map_io ( void )
{
pxa_map_io ( ) ;
iotable_init ( ARRAY_AND_SIZE ( pxa27x_io_desc ) ) ;
pxa27x_get_clk_frequency_khz ( 1 ) ;
}
2005-04-17 02:20:36 +04:00
/*
* device registration specific to PXA27x .
*/
2008-08-17 09:23:05 +04:00
void __init pxa27x_set_i2c_power_info ( struct i2c_pxa_platform_data * info )
2008-01-27 20:14:50 +03:00
{
2008-06-02 21:49:27 +04:00
local_irq_disable ( ) ;
PCFR | = PCFR_PI2CEN ;
local_irq_enable ( ) ;
2008-11-28 10:24:12 +03:00
pxa_register_device ( & pxa27x_device_i2c_power , info ) ;
2008-01-27 20:14:50 +03:00
}
2005-04-17 02:20:36 +04:00
static struct platform_device * devices [ ] __initdata = {
2008-06-23 02:36:39 +04:00
& pxa27x_device_udc ,
2010-06-13 20:43:00 +04:00
& pxa_device_pmu ,
2007-07-17 13:45:58 +04:00
& pxa_device_i2s ,
2010-03-17 23:15:21 +03:00
& pxa_device_asoc_ssp1 ,
& pxa_device_asoc_ssp2 ,
& pxa_device_asoc_ssp3 ,
& pxa_device_asoc_platform ,
2008-11-14 01:50:56 +03:00
& sa1100_device_rtc ,
2007-07-17 13:45:58 +04:00
& pxa_device_rtc ,
2007-12-10 12:54:36 +03:00
& pxa27x_device_ssp1 ,
& pxa27x_device_ssp2 ,
& pxa27x_device_ssp3 ,
2008-04-14 00:44:04 +04:00
& pxa27x_device_pwm0 ,
& pxa27x_device_pwm1 ,
2005-04-17 02:20:36 +04:00
} ;
static int __init pxa27x_init ( void )
{
2011-04-23 00:03:11 +04:00
int ret = 0 ;
2008-01-29 02:00:02 +03:00
2007-05-15 14:16:10 +04:00
if ( cpu_is_pxa27x ( ) ) {
2008-07-29 10:26:00 +04:00
reset_status = RCSR ;
2010-01-12 15:28:00 +03:00
clkdev_add_table ( pxa27x_clkregs , ARRAY_SIZE ( pxa27x_clkregs ) ) ;
2007-08-20 13:18:02 +04:00
2009-01-02 11:26:33 +03:00
if ( ( ret = pxa_init_dma ( IRQ_DMA , 32 ) ) )
2007-06-22 08:40:17 +04:00
return ret ;
2008-01-02 03:24:49 +03:00
2007-07-18 14:38:45 +04:00
pxa27x_init_pm ( ) ;
2008-01-02 03:24:49 +03:00
2011-04-23 00:03:11 +04:00
register_syscore_ops ( & pxa_irq_syscore_ops ) ;
register_syscore_ops ( & pxa2xx_mfp_syscore_ops ) ;
register_syscore_ops ( & pxa_gpio_syscore_ops ) ;
register_syscore_ops ( & pxa2xx_clock_syscore_ops ) ;
2008-01-29 02:00:02 +03:00
2007-05-15 14:16:10 +04:00
ret = platform_add_devices ( devices , ARRAY_SIZE ( devices ) ) ;
}
2008-01-29 02:00:02 +03:00
2007-05-15 14:16:10 +04:00
return ret ;
2005-04-17 02:20:36 +04:00
}
2008-04-19 13:59:24 +04:00
postcore_initcall ( pxa27x_init ) ;