2011-11-11 06:45:52 +04:00
/*
* R8A7740 processor 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
*/
2011-11-11 06:46:23 +04:00
# include <linux/delay.h>
2011-11-11 06:45:52 +04:00
# include <linux/kernel.h>
# include <linux/init.h>
2011-11-11 06:46:23 +04:00
# include <linux/io.h>
2011-11-11 06:45:52 +04:00
# include <linux/platform_device.h>
# include <linux/serial_sci.h>
# include <linux/sh_timer.h>
# include <mach/r8a7740.h>
# include <asm/mach-types.h>
# include <asm/mach/arch.h>
/* SCIFA0 */
static struct plat_sci_port scif0_platform_data = {
. mapbase = 0xe6c40000 ,
. flags = UPF_BOOT_AUTOCONF ,
. scscr = SCSCR_RE | SCSCR_TE ,
. scbrr_algo_id = SCBRR_ALGO_4 ,
. type = PORT_SCIFA ,
2011-11-11 06:46:35 +04:00
. irqs = SCIx_IRQ_MUXED ( evt2irq ( 0x0c00 ) ) ,
2011-11-11 06:45:52 +04:00
} ;
static struct platform_device scif0_device = {
. name = " sh-sci " ,
. id = 0 ,
. dev = {
. platform_data = & scif0_platform_data ,
} ,
} ;
/* SCIFA1 */
static struct plat_sci_port scif1_platform_data = {
. mapbase = 0xe6c50000 ,
. flags = UPF_BOOT_AUTOCONF ,
. scscr = SCSCR_RE | SCSCR_TE ,
. scbrr_algo_id = SCBRR_ALGO_4 ,
. type = PORT_SCIFA ,
2011-11-11 06:46:35 +04:00
. irqs = SCIx_IRQ_MUXED ( evt2irq ( 0x0c20 ) ) ,
2011-11-11 06:45:52 +04:00
} ;
static struct platform_device scif1_device = {
. name = " sh-sci " ,
. id = 1 ,
. dev = {
. platform_data = & scif1_platform_data ,
} ,
} ;
/* SCIFA2 */
static struct plat_sci_port scif2_platform_data = {
. mapbase = 0xe6c60000 ,
. flags = UPF_BOOT_AUTOCONF ,
. scscr = SCSCR_RE | SCSCR_TE ,
. scbrr_algo_id = SCBRR_ALGO_4 ,
. type = PORT_SCIFA ,
2011-11-11 06:46:35 +04:00
. irqs = SCIx_IRQ_MUXED ( evt2irq ( 0x0c40 ) ) ,
2011-11-11 06:45:52 +04:00
} ;
static struct platform_device scif2_device = {
. name = " sh-sci " ,
. id = 2 ,
. dev = {
. platform_data = & scif2_platform_data ,
} ,
} ;
/* SCIFA3 */
static struct plat_sci_port scif3_platform_data = {
. mapbase = 0xe6c70000 ,
. flags = UPF_BOOT_AUTOCONF ,
. scscr = SCSCR_RE | SCSCR_TE ,
. scbrr_algo_id = SCBRR_ALGO_4 ,
. type = PORT_SCIFA ,
2011-11-11 06:46:35 +04:00
. irqs = SCIx_IRQ_MUXED ( evt2irq ( 0x0c60 ) ) ,
2011-11-11 06:45:52 +04:00
} ;
static struct platform_device scif3_device = {
. name = " sh-sci " ,
. id = 3 ,
. dev = {
. platform_data = & scif3_platform_data ,
} ,
} ;
/* SCIFA4 */
static struct plat_sci_port scif4_platform_data = {
. mapbase = 0xe6c80000 ,
. flags = UPF_BOOT_AUTOCONF ,
. scscr = SCSCR_RE | SCSCR_TE ,
. scbrr_algo_id = SCBRR_ALGO_4 ,
. type = PORT_SCIFA ,
2011-11-11 06:46:35 +04:00
. irqs = SCIx_IRQ_MUXED ( evt2irq ( 0x0d20 ) ) ,
2011-11-11 06:45:52 +04:00
} ;
static struct platform_device scif4_device = {
. name = " sh-sci " ,
. id = 4 ,
. dev = {
. platform_data = & scif4_platform_data ,
} ,
} ;
/* SCIFA5 */
static struct plat_sci_port scif5_platform_data = {
. mapbase = 0xe6cb0000 ,
. flags = UPF_BOOT_AUTOCONF ,
. scscr = SCSCR_RE | SCSCR_TE ,
. scbrr_algo_id = SCBRR_ALGO_4 ,
. type = PORT_SCIFA ,
2011-11-11 06:46:35 +04:00
. irqs = SCIx_IRQ_MUXED ( evt2irq ( 0x0d40 ) ) ,
2011-11-11 06:45:52 +04:00
} ;
static struct platform_device scif5_device = {
. name = " sh-sci " ,
. id = 5 ,
. dev = {
. platform_data = & scif5_platform_data ,
} ,
} ;
/* SCIFA6 */
static struct plat_sci_port scif6_platform_data = {
. mapbase = 0xe6cc0000 ,
. flags = UPF_BOOT_AUTOCONF ,
. scscr = SCSCR_RE | SCSCR_TE ,
. scbrr_algo_id = SCBRR_ALGO_4 ,
. type = PORT_SCIFA ,
2011-11-11 06:46:35 +04:00
. irqs = SCIx_IRQ_MUXED ( evt2irq ( 0x04c0 ) ) ,
2011-11-11 06:45:52 +04:00
} ;
static struct platform_device scif6_device = {
. name = " sh-sci " ,
. id = 6 ,
. dev = {
. platform_data = & scif6_platform_data ,
} ,
} ;
/* SCIFA7 */
static struct plat_sci_port scif7_platform_data = {
. mapbase = 0xe6cd0000 ,
. flags = UPF_BOOT_AUTOCONF ,
. scscr = SCSCR_RE | SCSCR_TE ,
. scbrr_algo_id = SCBRR_ALGO_4 ,
. type = PORT_SCIFA ,
2011-11-11 06:46:35 +04:00
. irqs = SCIx_IRQ_MUXED ( evt2irq ( 0x04e0 ) ) ,
2011-11-11 06:45:52 +04:00
} ;
static struct platform_device scif7_device = {
. name = " sh-sci " ,
. id = 7 ,
. dev = {
. platform_data = & scif7_platform_data ,
} ,
} ;
/* SCIFB */
static struct plat_sci_port scifb_platform_data = {
. mapbase = 0xe6c30000 ,
. flags = UPF_BOOT_AUTOCONF ,
. scscr = SCSCR_RE | SCSCR_TE ,
. scbrr_algo_id = SCBRR_ALGO_4 ,
. type = PORT_SCIFB ,
2011-11-11 06:46:35 +04:00
. irqs = SCIx_IRQ_MUXED ( evt2irq ( 0x0d60 ) ) ,
2011-11-11 06:45:52 +04:00
} ;
static struct platform_device scifb_device = {
. name = " sh-sci " ,
. id = 8 ,
. dev = {
. platform_data = & scifb_platform_data ,
} ,
} ;
/* CMT */
static struct sh_timer_config cmt10_platform_data = {
. name = " CMT10 " ,
. channel_offset = 0x10 ,
. timer_bit = 0 ,
. clockevent_rating = 125 ,
. clocksource_rating = 125 ,
} ;
static struct resource cmt10_resources [ ] = {
[ 0 ] = {
. name = " CMT10 " ,
. start = 0xe6138010 ,
. end = 0xe613801b ,
. flags = IORESOURCE_MEM ,
} ,
[ 1 ] = {
2011-11-11 06:46:35 +04:00
. start = evt2irq ( 0x0b00 ) ,
2011-11-11 06:45:52 +04:00
. flags = IORESOURCE_IRQ ,
} ,
} ;
static struct platform_device cmt10_device = {
. name = " sh_cmt " ,
. id = 10 ,
. dev = {
. platform_data = & cmt10_platform_data ,
} ,
. resource = cmt10_resources ,
. num_resources = ARRAY_SIZE ( cmt10_resources ) ,
} ;
static struct platform_device * r8a7740_early_devices [ ] __initdata = {
& scif0_device ,
& scif1_device ,
& scif2_device ,
& scif3_device ,
& scif4_device ,
& scif5_device ,
& scif6_device ,
& scif7_device ,
& scifb_device ,
& cmt10_device ,
} ;
2011-11-11 06:46:23 +04:00
/* I2C */
static struct resource i2c0_resources [ ] = {
[ 0 ] = {
. name = " IIC0 " ,
. start = 0xfff20000 ,
. end = 0xfff20425 - 1 ,
. flags = IORESOURCE_MEM ,
} ,
[ 1 ] = {
2011-11-11 06:46:35 +04:00
. start = intcs_evt2irq ( 0xe00 ) ,
. end = intcs_evt2irq ( 0xe60 ) ,
2011-11-11 06:46:23 +04:00
. flags = IORESOURCE_IRQ ,
} ,
} ;
static struct resource i2c1_resources [ ] = {
[ 0 ] = {
. name = " IIC1 " ,
. start = 0xe6c20000 ,
. end = 0xe6c20425 - 1 ,
. flags = IORESOURCE_MEM ,
} ,
[ 1 ] = {
2011-11-11 06:46:35 +04:00
. start = evt2irq ( 0x780 ) , /* IIC1_ALI1 */
. end = evt2irq ( 0x7e0 ) , /* IIC1_DTEI1 */
2011-11-11 06:46:23 +04:00
. flags = IORESOURCE_IRQ ,
} ,
} ;
static struct platform_device i2c0_device = {
. name = " i2c-sh_mobile " ,
. id = 0 ,
. resource = i2c0_resources ,
. num_resources = ARRAY_SIZE ( i2c0_resources ) ,
} ;
static struct platform_device i2c1_device = {
. name = " i2c-sh_mobile " ,
. id = 1 ,
. resource = i2c1_resources ,
. num_resources = ARRAY_SIZE ( i2c1_resources ) ,
} ;
static struct platform_device * r8a7740_late_devices [ ] __initdata = {
& i2c0_device ,
& i2c1_device ,
} ;
# define ICCR 0x0004
# define ICSTART 0x0070
# define i2c_read(reg, offset) ioread8(reg + offset)
# define i2c_write(reg, offset, data) iowrite8(data, reg + offset)
/*
* r8a7740 chip has lasting errata on I2C I / O pad reset .
* this is work - around for it .
*/
static void r8a7740_i2c_workaround ( struct platform_device * pdev )
{
struct resource * res ;
void __iomem * reg ;
res = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
if ( unlikely ( ! res ) ) {
pr_err ( " r8a7740 i2c workaround fail (cannot find resource) \n " ) ;
return ;
}
reg = ioremap ( res - > start , resource_size ( res ) ) ;
if ( unlikely ( ! reg ) ) {
pr_err ( " r8a7740 i2c workaround fail (cannot map IO) \n " ) ;
return ;
}
i2c_write ( reg , ICCR , i2c_read ( reg , ICCR ) | 0x80 ) ;
i2c_read ( reg , ICCR ) ; /* dummy read */
i2c_write ( reg , ICSTART , i2c_read ( reg , ICSTART ) | 0x10 ) ;
i2c_read ( reg , ICSTART ) ; /* dummy read */
mdelay ( 100 ) ;
i2c_write ( reg , ICCR , 0x01 ) ;
i2c_read ( reg , ICCR ) ;
i2c_write ( reg , ICSTART , 0x00 ) ;
i2c_read ( reg , ICSTART ) ;
i2c_write ( reg , ICCR , 0x10 ) ;
mdelay ( 100 ) ;
i2c_write ( reg , ICCR , 0x00 ) ;
mdelay ( 100 ) ;
i2c_write ( reg , ICCR , 0x10 ) ;
mdelay ( 100 ) ;
iounmap ( reg ) ;
}
2011-11-11 06:45:52 +04:00
void __init r8a7740_add_standard_devices ( void )
{
2011-11-11 06:46:23 +04:00
/* I2C work-around */
r8a7740_i2c_workaround ( & i2c0_device ) ;
r8a7740_i2c_workaround ( & i2c1_device ) ;
2011-11-11 06:45:52 +04:00
platform_add_devices ( r8a7740_early_devices ,
ARRAY_SIZE ( r8a7740_early_devices ) ) ;
2011-11-11 06:46:23 +04:00
platform_add_devices ( r8a7740_late_devices ,
ARRAY_SIZE ( r8a7740_late_devices ) ) ;
2011-11-11 06:45:52 +04:00
}
void __init r8a7740_add_early_devices ( void )
{
early_platform_add_devices ( r8a7740_early_devices ,
ARRAY_SIZE ( r8a7740_early_devices ) ) ;
}