2005-04-17 02:20:36 +04:00
/*
* Support for Sharp SL - C7xx PDAs
* Models : SL - C700 ( Corgi ) , SL - C750 ( Shepherd ) , SL - C760 ( Husky )
*
* Copyright ( c ) 2004 - 2005 Richard Purdie
*
* Based on Sharp ' s 2.4 kernel patches / lubbock . c
*
* 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/kernel.h>
# include <linux/init.h>
# include <linux/device.h>
# include <linux/major.h>
# include <linux/fs.h>
# include <linux/interrupt.h>
# include <linux/mmc/host.h>
# include <asm/setup.h>
# include <asm/memory.h>
# include <asm/mach-types.h>
# include <asm/hardware.h>
# include <asm/irq.h>
# include <asm/io.h>
# include <asm/mach/arch.h>
# include <asm/mach/map.h>
# include <asm/mach/irq.h>
# include <asm/arch/pxa-regs.h>
# include <asm/arch/irq.h>
# include <asm/arch/mmc.h>
# include <asm/arch/udc.h>
# include <asm/arch/corgi.h>
# include <asm/mach/sharpsl_param.h>
# include <asm/hardware/scoop.h>
# include "generic.h"
2005-09-13 12:25:30 +04:00
# include "sharpsl.h"
2005-04-17 02:20:36 +04:00
/*
* Corgi SCOOP Device
*/
static struct resource corgi_scoop_resources [ ] = {
[ 0 ] = {
. start = 0x10800000 ,
. end = 0x10800fff ,
. flags = IORESOURCE_MEM ,
} ,
} ;
static struct scoop_config corgi_scoop_setup = {
. io_dir = CORGI_SCOOP_IO_DIR ,
. io_out = CORGI_SCOOP_IO_OUT ,
} ;
2005-09-05 23:49:54 +04:00
static struct scoop_pcmcia_dev corgi_pcmcia_scoop [ ] = {
{
. dev = & corgiscoop_device . dev ,
. irq = CORGI_IRQ_GPIO_CF_IRQ ,
. cd_irq = CORGI_IRQ_GPIO_CF_CD ,
. cd_irq_str = " PCMCIA0 CD " ,
} ,
} ;
2005-04-17 02:20:36 +04:00
struct platform_device corgiscoop_device = {
. name = " sharp-scoop " ,
. id = - 1 ,
. dev = {
. platform_data = & corgi_scoop_setup ,
} ,
. num_resources = ARRAY_SIZE ( corgi_scoop_resources ) ,
. resource = corgi_scoop_resources ,
} ;
/*
* Corgi SSP Device
*
* Set the parent as the scoop device because a lot of SSP devices
* also use scoop functions and this makes the power up / down order
* work correctly .
*/
2005-09-07 02:19:05 +04:00
struct platform_device corgissp_device = {
2005-04-17 02:20:36 +04:00
. name = " corgi-ssp " ,
. dev = {
. parent = & corgiscoop_device . dev ,
} ,
. id = - 1 ,
} ;
2005-09-13 12:25:30 +04:00
struct corgissp_machinfo corgi_ssp_machinfo = {
. port = 1 ,
. cs_lcdcon = CORGI_GPIO_LCDCON_CS ,
. cs_ads7846 = CORGI_GPIO_ADS7846_CS ,
. cs_max1111 = CORGI_GPIO_MAX1111_CS ,
. clk_lcdcon = 76 ,
. clk_ads7846 = 2 ,
. clk_max1111 = 8 ,
} ;
2005-04-17 02:20:36 +04:00
/*
* Corgi Backlight Device
*/
2005-09-13 12:25:33 +04:00
static struct corgibl_machinfo corgi_bl_machinfo = {
. max_intensity = 0x2f ,
. set_bl_intensity = corgi_bl_set_intensity ,
} ;
2005-04-17 02:20:36 +04:00
static struct platform_device corgibl_device = {
. name = " corgi-bl " ,
. dev = {
. parent = & corgifb_device . dev ,
2005-09-13 12:25:33 +04:00
. platform_data = & corgi_bl_machinfo ,
2005-04-17 02:20:36 +04:00
} ,
. id = - 1 ,
} ;
2005-09-07 02:19:07 +04:00
/*
* Corgi Keyboard Device
*/
static struct platform_device corgikbd_device = {
. name = " corgi-keyboard " ,
. id = - 1 ,
} ;
/*
* Corgi Touch Screen Device
*/
2005-09-13 12:25:33 +04:00
static struct resource corgits_resources [ ] = {
[ 0 ] = {
. start = CORGI_IRQ_GPIO_TP_INT ,
. end = CORGI_IRQ_GPIO_TP_INT ,
. flags = IORESOURCE_IRQ ,
} ,
} ;
static struct corgits_machinfo corgi_ts_machinfo = {
. get_hsync_len = corgi_get_hsync_len ,
. put_hsync = corgi_put_hsync ,
. wait_hsync = corgi_wait_hsync ,
} ;
2005-09-07 02:19:07 +04:00
static struct platform_device corgits_device = {
. name = " corgi-ts " ,
. dev = {
. parent = & corgissp_device . dev ,
2005-09-13 12:25:33 +04:00
. platform_data = & corgi_ts_machinfo ,
2005-09-07 02:19:07 +04:00
} ,
. id = - 1 ,
2005-09-13 12:25:33 +04:00
. num_resources = ARRAY_SIZE ( corgits_resources ) ,
. resource = corgits_resources ,
2005-09-07 02:19:07 +04:00
} ;
2005-04-17 02:20:36 +04:00
/*
* MMC / SD Device
*
2005-09-09 21:54:03 +04:00
* The card detect interrupt isn ' t debounced so we delay it by 250 ms
2005-04-17 02:20:36 +04:00
* to give the card a chance to fully insert / eject .
*/
2005-09-09 21:54:03 +04:00
static struct pxamci_platform_data corgi_mci_platform_data ;
2005-04-17 02:20:36 +04:00
2005-09-09 21:54:03 +04:00
static int corgi_mci_init ( struct device * dev , irqreturn_t ( * corgi_detect_int ) ( int , void * , struct pt_regs * ) , void * data )
2005-04-17 02:20:36 +04:00
{
int err ;
/* setup GPIO for PXA25x MMC controller */
pxa_gpio_mode ( GPIO6_MMCCLK_MD ) ;
pxa_gpio_mode ( GPIO8_MMCCS0_MD ) ;
pxa_gpio_mode ( CORGI_GPIO_nSD_DETECT | GPIO_IN ) ;
pxa_gpio_mode ( CORGI_GPIO_SD_PWR | GPIO_OUT ) ;
2005-09-09 21:54:03 +04:00
corgi_mci_platform_data . detect_delay = msecs_to_jiffies ( 250 ) ;
2005-04-17 02:20:36 +04:00
2005-09-09 21:54:03 +04:00
err = request_irq ( CORGI_IRQ_GPIO_nSD_DETECT , corgi_detect_int , SA_INTERRUPT ,
2005-04-17 02:20:36 +04:00
" MMC card detect " , data ) ;
if ( err ) {
printk ( KERN_ERR " corgi_mci_init: MMC/SD: can't request MMC card detect IRQ \n " ) ;
return - 1 ;
}
set_irq_type ( CORGI_IRQ_GPIO_nSD_DETECT , IRQT_BOTHEDGE ) ;
return 0 ;
}
static void corgi_mci_setpower ( struct device * dev , unsigned int vdd )
{
struct pxamci_platform_data * p_d = dev - > platform_data ;
2005-09-15 17:53:21 +04:00
if ( ( 1 < < vdd ) & p_d - > ocr_mask )
2005-04-17 02:20:36 +04:00
GPSR1 = GPIO_bit ( CORGI_GPIO_SD_PWR ) ;
2005-09-15 17:53:21 +04:00
else
2005-04-17 02:20:36 +04:00
GPCR1 = GPIO_bit ( CORGI_GPIO_SD_PWR ) ;
}
2005-09-07 02:19:07 +04:00
static int corgi_mci_get_ro ( struct device * dev )
{
return GPLR ( CORGI_GPIO_nSD_WP ) & GPIO_bit ( CORGI_GPIO_nSD_WP ) ;
}
2005-04-17 02:20:36 +04:00
static void corgi_mci_exit ( struct device * dev , void * data )
{
free_irq ( CORGI_IRQ_GPIO_nSD_DETECT , data ) ;
}
static struct pxamci_platform_data corgi_mci_platform_data = {
. ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34 ,
. init = corgi_mci_init ,
2005-09-07 02:19:07 +04:00
. get_ro = corgi_mci_get_ro ,
2005-04-17 02:20:36 +04:00
. setpower = corgi_mci_setpower ,
. exit = corgi_mci_exit ,
} ;
2005-09-07 02:19:07 +04:00
2005-04-17 02:20:36 +04:00
/*
* USB Device Controller
*/
static void corgi_udc_command ( int cmd )
{
switch ( cmd ) {
case PXA2XX_UDC_CMD_CONNECT :
GPSR ( CORGI_GPIO_USB_PULLUP ) = GPIO_bit ( CORGI_GPIO_USB_PULLUP ) ;
break ;
case PXA2XX_UDC_CMD_DISCONNECT :
GPCR ( CORGI_GPIO_USB_PULLUP ) = GPIO_bit ( CORGI_GPIO_USB_PULLUP ) ;
break ;
}
}
static struct pxa2xx_udc_mach_info udc_info __initdata = {
/* no connect GPIO; corgi can't tell connection status */
. udc_command = corgi_udc_command ,
} ;
static struct platform_device * devices [ ] __initdata = {
& corgiscoop_device ,
& corgissp_device ,
& corgifb_device ,
2005-09-07 02:19:07 +04:00
& corgikbd_device ,
2005-04-17 02:20:36 +04:00
& corgibl_device ,
2005-09-07 02:19:07 +04:00
& corgits_device ,
2005-04-17 02:20:36 +04:00
} ;
static void __init corgi_init ( void )
{
2005-09-15 17:53:21 +04:00
/* setup sleep mode values */
PWER = 0x00000002 ;
PFER = 0x00000000 ;
PRER = 0x00000002 ;
PGSR0 = 0x0158C000 ;
PGSR1 = 0x00FF0080 ;
PGSR2 = 0x0001C004 ;
/* Stop 3.6MHz and drive HIGH to PCMCIA and CS */
PCFR | = PCFR_OPDE ;
2005-09-13 12:25:30 +04:00
corgi_ssp_set_machinfo ( & corgi_ssp_machinfo ) ;
2005-04-17 02:20:36 +04:00
pxa_gpio_mode ( CORGI_GPIO_USB_PULLUP | GPIO_OUT ) ;
2005-09-13 12:25:33 +04:00
pxa_gpio_mode ( CORGI_GPIO_HSYNC | GPIO_IN ) ;
2005-04-17 02:20:36 +04:00
pxa_set_udc_info ( & udc_info ) ;
pxa_set_mci_info ( & corgi_mci_platform_data ) ;
2005-09-05 23:49:54 +04:00
scoop_num = 1 ;
scoop_devs = & corgi_pcmcia_scoop [ 0 ] ;
2005-04-17 02:20:36 +04:00
platform_add_devices ( devices , ARRAY_SIZE ( devices ) ) ;
}
static void __init fixup_corgi ( struct machine_desc * desc ,
struct tag * tags , char * * cmdline , struct meminfo * mi )
{
sharpsl_save_param ( ) ;
mi - > nr_banks = 1 ;
mi - > bank [ 0 ] . start = 0xa0000000 ;
mi - > bank [ 0 ] . node = 0 ;
if ( machine_is_corgi ( ) )
mi - > bank [ 0 ] . size = ( 32 * 1024 * 1024 ) ;
else
mi - > bank [ 0 ] . size = ( 64 * 1024 * 1024 ) ;
}
# ifdef CONFIG_MACH_CORGI
MACHINE_START ( CORGI , " SHARP Corgi " )
2005-07-03 20:38:58 +04:00
. phys_ram = 0xa0000000 ,
. phys_io = 0x40000000 ,
2005-07-04 13:44:34 +04:00
. io_pg_offst = ( io_p2v ( 0x40000000 ) > > 18 ) & 0xfffc ,
2005-07-03 20:38:58 +04:00
. fixup = fixup_corgi ,
2005-09-15 17:53:21 +04:00
. map_io = pxa_map_io ,
. init_irq = pxa_init_irq ,
2005-07-03 20:38:58 +04:00
. init_machine = corgi_init ,
. timer = & pxa_timer ,
2005-04-17 02:20:36 +04:00
MACHINE_END
# endif
# ifdef CONFIG_MACH_SHEPHERD
MACHINE_START ( SHEPHERD , " SHARP Shepherd " )
2005-07-03 20:38:58 +04:00
. phys_ram = 0xa0000000 ,
. phys_io = 0x40000000 ,
2005-07-04 13:44:34 +04:00
. io_pg_offst = ( io_p2v ( 0x40000000 ) > > 18 ) & 0xfffc ,
2005-07-03 20:38:58 +04:00
. fixup = fixup_corgi ,
2005-09-15 17:53:21 +04:00
. map_io = pxa_map_io ,
. init_irq = pxa_init_irq ,
2005-07-03 20:38:58 +04:00
. init_machine = corgi_init ,
. timer = & pxa_timer ,
2005-04-17 02:20:36 +04:00
MACHINE_END
# endif
# ifdef CONFIG_MACH_HUSKY
MACHINE_START ( HUSKY , " SHARP Husky " )
2005-07-03 20:38:58 +04:00
. phys_ram = 0xa0000000 ,
. phys_io = 0x40000000 ,
2005-07-04 13:44:34 +04:00
. io_pg_offst = ( io_p2v ( 0x40000000 ) > > 18 ) & 0xfffc ,
2005-07-03 20:38:58 +04:00
. fixup = fixup_corgi ,
2005-09-15 17:53:21 +04:00
. map_io = pxa_map_io ,
. init_irq = pxa_init_irq ,
2005-07-03 20:38:58 +04:00
. init_machine = corgi_init ,
. timer = & pxa_timer ,
2005-04-17 02:20:36 +04:00
MACHINE_END
# endif