2011-11-10 18:46:45 -08:00
/*
* bonito board support
*
* Copyright ( C ) 2011 Renesas Solutions Corp .
* Copyright ( C ) 2011 Kuninori Morimoto < kuninori . morimoto . gx @ renesas . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; version 2 of the License .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA
*
*/
# include <linux/kernel.h>
2011-11-10 18:47:07 -08:00
# include <linux/i2c.h>
2011-11-10 18:46:45 -08:00
# include <linux/init.h>
# include <linux/interrupt.h>
# include <linux/irq.h>
# include <linux/platform_device.h>
# include <linux/gpio.h>
2011-11-10 18:47:26 -08:00
# include <linux/smsc911x.h>
2012-02-29 13:46:24 +00:00
# include <linux/videodev2.h>
2011-11-10 18:46:45 -08:00
# include <mach/common.h>
# include <asm/mach-types.h>
# include <asm/mach/arch.h>
# include <asm/mach/map.h>
# include <asm/mach/time.h>
# include <asm/hardware/cache-l2x0.h>
# include <mach/r8a7740.h>
2012-01-03 16:57:33 -06:00
# include <mach/irqs.h>
2011-11-10 18:47:16 -08:00
# include <video/sh_mobile_lcdc.h>
2011-11-10 18:46:45 -08:00
/*
* CS Address device note
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* 0 0x0000 _0000 NOR Flash ( 64 MB ) SW12 : bit3 = OFF
* 2 0x0800 _0000 ExtNOR ( 64 MB ) SW12 : bit3 = OFF
* 4 -
* 5 A -
* 5 B 0x1600 _0000 SRAM ( 8 MB )
* 6 0x1800 _0000 FPGA ( 64 K )
* 0x1801 _0000 Ether ( 4 KB )
* 0x1801 _1000 USB ( 4 KB )
*/
/*
* SW12
*
* bit1 bit2 bit3
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* ON NOR WriteProtect NAND WriteProtect CS0 ExtNOR / CS2 NOR
* OFF NOR Not WriteProtect NAND Not WriteProtect CS0 NOR / CS2 ExtNOR
*/
2011-11-10 18:46:56 -08:00
/*
* SCIFA5 ( CN42 )
*
* S38 .3 = ON
* S39 .6 = ON
* S43 .1 = ON
*/
2011-11-10 18:47:16 -08:00
/*
* LCDC0 ( CN3 / CN4 / CN7 )
*
* S38 .1 = OFF
* S38 .2 = OFF
*/
2011-11-10 18:46:45 -08:00
/*
* FPGA
*/
2011-11-10 18:47:26 -08:00
# define IRQSR0 0x0020
# define IRQSR1 0x0022
# define IRQMR0 0x0030
# define IRQMR1 0x0032
2011-11-10 18:46:56 -08:00
# define BUSSWMR1 0x0070
# define BUSSWMR2 0x0072
# define BUSSWMR3 0x0074
# define BUSSWMR4 0x0076
2011-11-10 18:47:16 -08:00
# define LCDCR 0x10B4
2011-11-10 18:47:26 -08:00
# define DEVRSTCR1 0x10D0
# define DEVRSTCR2 0x10D2
2011-11-10 18:46:45 -08:00
# define A1MDSR 0x10E0
# define BVERR 0x1100
2011-11-10 18:47:26 -08:00
/* FPGA IRQ */
# define FPGA_IRQ_BASE (512)
# define FPGA_IRQ0 (FPGA_IRQ_BASE)
# define FPGA_IRQ1 (FPGA_IRQ_BASE + 16)
2011-11-10 18:47:36 -08:00
# define FPGA_ETH_IRQ (FPGA_IRQ0 + 15)
2011-11-10 18:46:45 -08:00
static u16 bonito_fpga_read ( u32 offset )
{
return __raw_readw ( 0xf0003000 + offset ) ;
}
static void bonito_fpga_write ( u32 offset , u16 val )
{
__raw_writew ( val , 0xf0003000 + offset ) ;
}
2011-11-10 18:47:26 -08:00
static void bonito_fpga_irq_disable ( struct irq_data * data )
{
unsigned int irq = data - > irq ;
u32 addr = ( irq < 1016 ) ? IRQMR0 : IRQMR1 ;
int shift = irq % 16 ;
bonito_fpga_write ( addr , bonito_fpga_read ( addr ) | ( 1 < < shift ) ) ;
}
static void bonito_fpga_irq_enable ( struct irq_data * data )
{
unsigned int irq = data - > irq ;
u32 addr = ( irq < 1016 ) ? IRQMR0 : IRQMR1 ;
int shift = irq % 16 ;
bonito_fpga_write ( addr , bonito_fpga_read ( addr ) & ~ ( 1 < < shift ) ) ;
}
static struct irq_chip bonito_fpga_irq_chip __read_mostly = {
. name = " bonito FPGA " ,
. irq_mask = bonito_fpga_irq_disable ,
. irq_unmask = bonito_fpga_irq_enable ,
} ;
static void bonito_fpga_irq_demux ( unsigned int irq , struct irq_desc * desc )
{
u32 val = bonito_fpga_read ( IRQSR1 ) < < 16 |
bonito_fpga_read ( IRQSR0 ) ;
u32 mask = bonito_fpga_read ( IRQMR1 ) < < 16 |
bonito_fpga_read ( IRQMR0 ) ;
int i ;
val & = ~ mask ;
for ( i = 0 ; i < 32 ; i + + ) {
if ( ! ( val & ( 1 < < i ) ) )
continue ;
generic_handle_irq ( FPGA_IRQ_BASE + i ) ;
}
}
static void bonito_fpga_init ( void )
{
int i ;
bonito_fpga_write ( IRQMR0 , 0xffff ) ; /* mask all */
bonito_fpga_write ( IRQMR1 , 0xffff ) ; /* mask all */
/* Device reset */
bonito_fpga_write ( DEVRSTCR1 ,
( 1 < < 2 ) ) ; /* Eth */
/* FPGA irq require special handling */
for ( i = FPGA_IRQ_BASE ; i < FPGA_IRQ_BASE + 32 ; i + + ) {
irq_set_chip_and_handler_name ( i , & bonito_fpga_irq_chip ,
handle_level_irq , " level " ) ;
set_irq_flags ( i , IRQF_VALID ) ; /* yuck */
}
irq_set_chained_handler ( evt2irq ( 0x0340 ) , bonito_fpga_irq_demux ) ;
irq_set_irq_type ( evt2irq ( 0x0340 ) , IRQ_TYPE_LEVEL_LOW ) ;
}
2011-11-10 18:47:07 -08:00
/*
* PMIC settings
*
* FIXME
*
* bonito board needs some settings by pmic which use i2c access .
* pmic settings use device_initcall ( ) here for use it .
*/
static __u8 * pmic_settings = NULL ;
static __u8 pmic_do_2A [ ] = {
0x1C , 0x09 ,
0x1A , 0x80 ,
0xff , 0xff ,
} ;
static int __init pmic_init ( void )
{
struct i2c_adapter * a = i2c_get_adapter ( 0 ) ;
struct i2c_msg msg ;
__u8 buf [ 2 ] ;
int i , ret ;
if ( ! pmic_settings )
return 0 ;
if ( ! a )
return 0 ;
msg . addr = 0x46 ;
msg . buf = buf ;
msg . len = 2 ;
msg . flags = 0 ;
for ( i = 0 ; ; i + = 2 ) {
buf [ 0 ] = pmic_settings [ i + 0 ] ;
buf [ 1 ] = pmic_settings [ i + 1 ] ;
if ( ( 0xff = = buf [ 0 ] ) & & ( 0xff = = buf [ 1 ] ) )
break ;
ret = i2c_transfer ( a , & msg , 1 ) ;
if ( ret < 0 ) {
pr_err ( " i2c transfer fail \n " ) ;
break ;
}
}
return 0 ;
}
device_initcall ( pmic_init ) ;
2011-11-10 18:47:16 -08:00
/*
* LCDC0
*/
static const struct fb_videomode lcdc0_mode = {
. name = " WVGA Panel " ,
. xres = 800 ,
. yres = 480 ,
. left_margin = 88 ,
. right_margin = 40 ,
. hsync_len = 128 ,
. upper_margin = 20 ,
. lower_margin = 5 ,
. vsync_len = 5 ,
. sync = 0 ,
} ;
static struct sh_mobile_lcdc_info lcdc0_info = {
. clock_source = LCDC_CLK_BUS ,
. ch [ 0 ] = {
. chan = LCDC_CHAN_MAINLCD ,
2012-02-29 13:46:24 +00:00
. fourcc = V4L2_PIX_FMT_RGB565 ,
2011-11-10 18:47:16 -08:00
. interface_type = RGB24 ,
. clock_divider = 5 ,
. flags = 0 ,
2011-11-29 14:33:41 +01:00
. lcd_modes = & lcdc0_mode ,
. num_modes = 1 ,
2011-09-11 22:59:04 +02:00
. panel_cfg = {
2011-11-10 18:47:16 -08:00
. width = 152 ,
. height = 91 ,
} ,
} ,
} ;
static struct resource lcdc0_resources [ ] = {
[ 0 ] = {
. name = " LCDC0 " ,
. start = 0xfe940000 ,
. end = 0xfe943fff ,
. flags = IORESOURCE_MEM ,
} ,
[ 1 ] = {
. start = intcs_evt2irq ( 0x0580 ) ,
. flags = IORESOURCE_IRQ ,
} ,
} ;
static struct platform_device lcdc0_device = {
. name = " sh_mobile_lcdc_fb " ,
. id = 0 ,
. resource = lcdc0_resources ,
. num_resources = ARRAY_SIZE ( lcdc0_resources ) ,
. dev = {
. platform_data = & lcdc0_info ,
. coherent_dma_mask = ~ 0 ,
} ,
} ;
2011-11-10 18:47:36 -08:00
/*
* SMSC 9221
*/
static struct resource smsc_resources [ ] = {
[ 0 ] = {
. start = 0x18010000 ,
. end = 0x18011000 - 1 ,
. flags = IORESOURCE_MEM ,
} ,
[ 1 ] = {
. start = FPGA_ETH_IRQ ,
. flags = IORESOURCE_IRQ ,
} ,
} ;
static struct smsc911x_platform_config smsc_platdata = {
. flags = SMSC911X_USE_16BIT ,
. phy_interface = PHY_INTERFACE_MODE_MII ,
. irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW ,
. irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL ,
} ;
static struct platform_device smsc_device = {
. name = " smsc911x " ,
. dev = {
. platform_data = & smsc_platdata ,
} ,
. resource = smsc_resources ,
. num_resources = ARRAY_SIZE ( smsc_resources ) ,
} ;
2011-11-10 18:46:45 -08:00
/*
2011-11-10 18:46:56 -08:00
* core board devices
2011-11-10 18:46:45 -08:00
*/
2011-11-10 18:46:56 -08:00
static struct platform_device * bonito_core_devices [ ] __initdata = {
} ;
/*
* base board devices
*/
static struct platform_device * bonito_base_devices [ ] __initdata = {
2011-11-10 18:47:16 -08:00
& lcdc0_device ,
2011-11-10 18:47:36 -08:00
& smsc_device ,
2011-11-10 18:46:45 -08:00
} ;
/*
* map I / O
*/
static struct map_desc bonito_io_desc [ ] __initdata = {
/*
* for FPGA ( 0x1800000 - 0x19ffffff )
* 0x18000000 - 0x18002000 - > 0xf0003000 - 0xf0005000
*/
{
. virtual = 0xf0003000 ,
. pfn = __phys_to_pfn ( 0x18000000 ) ,
. length = PAGE_SIZE * 2 ,
. type = MT_DEVICE_NONSHARED
}
} ;
static void __init bonito_map_io ( void )
{
2012-02-29 21:37:35 +09:00
r8a7740_map_io ( ) ;
2011-11-10 18:46:45 -08:00
iotable_init ( bonito_io_desc , ARRAY_SIZE ( bonito_io_desc ) ) ;
}
/*
* board init
*/
2011-11-10 18:46:56 -08:00
# define BIT_ON(sw, bit) (sw & (1 << bit))
# define BIT_OFF(sw, bit) (!(sw & (1 << bit)))
2011-11-10 18:47:16 -08:00
# define VCCQ1CR 0xE6058140
# define VCCQ1LCDCR 0xE6058186
2011-11-10 18:46:45 -08:00
static void __init bonito_init ( void )
{
u16 val ;
r8a7740_pinmux_init ( ) ;
2011-11-10 18:47:26 -08:00
bonito_fpga_init ( ) ;
2011-11-10 18:46:45 -08:00
2011-11-10 18:47:07 -08:00
pmic_settings = pmic_do_2A ;
2011-11-10 18:46:56 -08:00
/*
* core board settings
*/
2011-11-10 18:46:45 -08:00
# ifdef CONFIG_CACHE_L2X0
/* Early BRESP enable, Shared attribute override enable, 32K*8way */
2012-03-09 17:16:40 -06:00
l2x0_init ( IOMEM ( 0xf0002000 ) , 0x40440000 , 0x82000fff ) ;
2011-11-10 18:46:45 -08:00
# endif
r8a7740_add_standard_devices ( ) ;
2011-11-10 18:46:56 -08:00
platform_add_devices ( bonito_core_devices ,
ARRAY_SIZE ( bonito_core_devices ) ) ;
/*
* base board settings
*/
gpio_request ( GPIO_PORT176 , NULL ) ;
gpio_direction_input ( GPIO_PORT176 ) ;
if ( ! gpio_get_value ( GPIO_PORT176 ) ) {
u16 bsw2 ;
u16 bsw3 ;
u16 bsw4 ;
/*
* FPGA
*/
gpio_request ( GPIO_FN_CS5B , NULL ) ;
gpio_request ( GPIO_FN_CS6A , NULL ) ;
gpio_request ( GPIO_FN_CS5A_PORT105 , NULL ) ;
gpio_request ( GPIO_FN_IRQ10 , NULL ) ;
val = bonito_fpga_read ( BVERR ) ;
pr_info ( " bonito version: cpu %02x, base %02x \n " ,
( ( val > > 8 ) & 0xFF ) ,
( ( val > > 0 ) & 0xFF ) ) ;
bsw2 = bonito_fpga_read ( BUSSWMR2 ) ;
bsw3 = bonito_fpga_read ( BUSSWMR3 ) ;
bsw4 = bonito_fpga_read ( BUSSWMR4 ) ;
/*
* SCIFA5 ( CN42 )
*/
if ( BIT_OFF ( bsw2 , 1 ) & & /* S38.3 = ON */
BIT_OFF ( bsw3 , 9 ) & & /* S39.6 = ON */
BIT_OFF ( bsw4 , 4 ) ) { /* S43.1 = ON */
gpio_request ( GPIO_FN_SCIFA5_TXD_PORT91 , NULL ) ;
gpio_request ( GPIO_FN_SCIFA5_RXD_PORT92 , NULL ) ;
}
2011-11-10 18:47:16 -08:00
/*
* LCDC0 ( CN3 )
*/
if ( BIT_ON ( bsw2 , 3 ) & & /* S38.1 = OFF */
BIT_ON ( bsw2 , 2 ) ) { /* S38.2 = OFF */
gpio_request ( GPIO_FN_LCDC0_SELECT , NULL ) ;
gpio_request ( GPIO_FN_LCD0_D0 , NULL ) ;
gpio_request ( GPIO_FN_LCD0_D1 , NULL ) ;
gpio_request ( GPIO_FN_LCD0_D2 , NULL ) ;
gpio_request ( GPIO_FN_LCD0_D3 , NULL ) ;
gpio_request ( GPIO_FN_LCD0_D4 , NULL ) ;
gpio_request ( GPIO_FN_LCD0_D5 , NULL ) ;
gpio_request ( GPIO_FN_LCD0_D6 , NULL ) ;
gpio_request ( GPIO_FN_LCD0_D7 , NULL ) ;
gpio_request ( GPIO_FN_LCD0_D8 , NULL ) ;
gpio_request ( GPIO_FN_LCD0_D9 , NULL ) ;
gpio_request ( GPIO_FN_LCD0_D10 , NULL ) ;
gpio_request ( GPIO_FN_LCD0_D11 , NULL ) ;
gpio_request ( GPIO_FN_LCD0_D12 , NULL ) ;
gpio_request ( GPIO_FN_LCD0_D13 , NULL ) ;
gpio_request ( GPIO_FN_LCD0_D14 , NULL ) ;
gpio_request ( GPIO_FN_LCD0_D15 , NULL ) ;
gpio_request ( GPIO_FN_LCD0_D16 , NULL ) ;
gpio_request ( GPIO_FN_LCD0_D17 , NULL ) ;
gpio_request ( GPIO_FN_LCD0_D18_PORT163 , NULL ) ;
gpio_request ( GPIO_FN_LCD0_D19_PORT162 , NULL ) ;
gpio_request ( GPIO_FN_LCD0_D20_PORT161 , NULL ) ;
gpio_request ( GPIO_FN_LCD0_D21_PORT158 , NULL ) ;
gpio_request ( GPIO_FN_LCD0_D22_PORT160 , NULL ) ;
gpio_request ( GPIO_FN_LCD0_D23_PORT159 , NULL ) ;
gpio_request ( GPIO_FN_LCD0_DCK , NULL ) ;
gpio_request ( GPIO_FN_LCD0_VSYN , NULL ) ;
gpio_request ( GPIO_FN_LCD0_HSYN , NULL ) ;
gpio_request ( GPIO_FN_LCD0_DISP , NULL ) ;
gpio_request ( GPIO_FN_LCD0_LCLK_PORT165 , NULL ) ;
gpio_request ( GPIO_PORT61 , NULL ) ; /* LCDDON */
gpio_direction_output ( GPIO_PORT61 , 1 ) ;
/* backlight on */
bonito_fpga_write ( LCDCR , 1 ) ;
/* drivability Max */
__raw_writew ( 0x00FF , VCCQ1LCDCR ) ;
__raw_writew ( 0xFFFF , VCCQ1CR ) ;
}
2011-11-10 18:46:56 -08:00
platform_add_devices ( bonito_base_devices ,
ARRAY_SIZE ( bonito_base_devices ) ) ;
}
2011-11-10 18:46:45 -08:00
}
2012-03-06 17:36:53 +09:00
static void __init bonito_earlytimer_init ( void )
2011-11-10 18:46:45 -08:00
{
u16 val ;
u8 md_ck = 0 ;
/* read MD_CK value */
val = bonito_fpga_read ( A1MDSR ) ;
if ( val & ( 1 < < 10 ) )
md_ck | = MD_CK2 ;
if ( val & ( 1 < < 9 ) )
md_ck | = MD_CK1 ;
if ( val & ( 1 < < 8 ) )
md_ck | = MD_CK0 ;
r8a7740_clock_init ( md_ck ) ;
2012-03-06 17:36:53 +09:00
shmobile_earlytimer_init ( ) ;
2011-11-10 18:46:45 -08:00
}
2012-03-06 17:36:53 +09:00
void __init bonito_add_early_devices ( void )
{
r8a7740_add_early_devices ( ) ;
/* override timer setup with board-specific code */
shmobile_timer . init = bonito_earlytimer_init ;
}
2011-11-10 18:46:45 -08:00
MACHINE_START ( BONITO , " bonito " )
. map_io = bonito_map_io ,
2012-03-06 17:36:53 +09:00
. init_early = bonito_add_early_devices ,
2011-11-10 18:46:45 -08:00
. init_irq = r8a7740_init_irq ,
. handle_irq = shmobile_handle_irq_intc ,
. init_machine = bonito_init ,
2012-03-06 17:36:53 +09:00
. timer = & shmobile_timer ,
2011-11-10 18:46:45 -08:00
MACHINE_END