2006-12-28 20:22:32 +03:00
/*
* A20R specific code
*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
*
* Copyright ( C ) 2006 Thomas Bogendoerfer ( tsbogend @ alpha . franken . de )
*/
# include <linux/init.h>
# include <linux/interrupt.h>
2010-10-07 17:08:54 +04:00
# include <linux/irq.h>
2006-12-28 20:22:32 +03:00
# include <linux/platform_device.h>
# include <linux/serial_8250.h>
# include <asm/sni.h>
# include <asm/time.h>
# define PORT(_base,_irq) \
{ \
. iobase = _base , \
. irq = _irq , \
. uartclk = 1843200 , \
. iotype = UPIO_PORT , \
. flags = UPF_BOOT_AUTOCONF , \
}
static struct plat_serial8250_port a20r_data [ ] = {
PORT ( 0x3f8 , 4 ) ,
PORT ( 0x2f8 , 3 ) ,
{ } ,
} ;
static struct platform_device a20r_serial8250_device = {
. name = " serial8250 " ,
. id = PLAT8250_DEV_PLATFORM ,
. dev = {
. platform_data = a20r_data ,
} ,
} ;
2007-06-21 01:36:47 +04:00
static struct resource a20r_ds1216_rsrc [ ] = {
2013-01-22 15:59:30 +04:00
{
. start = 0x1c081ffc ,
. end = 0x1c081fff ,
. flags = IORESOURCE_MEM
}
2007-06-21 01:36:47 +04:00
} ;
static struct platform_device a20r_ds1216_device = {
2013-01-22 15:59:30 +04:00
. name = " rtc-ds1216 " ,
. num_resources = ARRAY_SIZE ( a20r_ds1216_rsrc ) ,
. resource = a20r_ds1216_rsrc
2007-06-21 01:36:47 +04:00
} ;
2006-12-28 20:22:32 +03:00
static struct resource snirm_82596_rsrc [ ] = {
{
2007-06-21 01:36:47 +04:00
. start = 0x18000000 ,
. end = 0x18000004 ,
2006-12-28 20:22:32 +03:00
. flags = IORESOURCE_MEM
} ,
{
2007-06-21 01:36:47 +04:00
. start = 0x18010000 ,
. end = 0x18010004 ,
2006-12-28 20:22:32 +03:00
. flags = IORESOURCE_MEM
} ,
{
2007-06-21 01:36:47 +04:00
. start = 0x1ff00000 ,
. end = 0x1ff00020 ,
2006-12-28 20:22:32 +03:00
. flags = IORESOURCE_MEM
} ,
{
. start = 22 ,
. end = 22 ,
. flags = IORESOURCE_IRQ
} ,
{
2013-01-22 15:59:30 +04:00
. flags = 0x01 /* 16bit mpu port access */
2006-12-28 20:22:32 +03:00
}
} ;
static struct platform_device snirm_82596_pdev = {
2013-01-22 15:59:30 +04:00
. name = " snirm_82596 " ,
. num_resources = ARRAY_SIZE ( snirm_82596_rsrc ) ,
. resource = snirm_82596_rsrc
2006-12-28 20:22:32 +03:00
} ;
static struct resource snirm_53c710_rsrc [ ] = {
{
2007-07-11 21:10:39 +04:00
. start = 0x19000000 ,
. end = 0x190fffff ,
2006-12-28 20:22:32 +03:00
. flags = IORESOURCE_MEM
} ,
{
. start = 19 ,
. end = 19 ,
. flags = IORESOURCE_IRQ
}
} ;
static struct platform_device snirm_53c710_pdev = {
2013-01-22 15:59:30 +04:00
. name = " snirm_53c710 " ,
. num_resources = ARRAY_SIZE ( snirm_53c710_rsrc ) ,
. resource = snirm_53c710_rsrc
2006-12-28 20:22:32 +03:00
} ;
static struct resource sc26xx_rsrc [ ] = {
{
2007-07-11 21:10:39 +04:00
. start = 0x1c070000 ,
. end = 0x1c0700ff ,
2006-12-28 20:22:32 +03:00
. flags = IORESOURCE_MEM
} ,
{
. start = 20 ,
. end = 20 ,
. flags = IORESOURCE_IRQ
}
} ;
2012-12-03 22:23:32 +04:00
# include <linux/platform_data/serial-sccnxp.h>
2012-08-25 19:24:20 +04:00
static struct sccnxp_pdata sccnxp_data = {
. reg_shift = 2 ,
. frequency = 3686400 ,
. mctrl_cfg [ 0 ] = MCTRL_SIG ( DTR_OP , LINE_OP7 ) |
MCTRL_SIG ( RTS_OP , LINE_OP3 ) |
MCTRL_SIG ( DSR_IP , LINE_IP5 ) |
MCTRL_SIG ( DCD_IP , LINE_IP6 ) ,
. mctrl_cfg [ 1 ] = MCTRL_SIG ( DTR_OP , LINE_OP2 ) |
MCTRL_SIG ( RTS_OP , LINE_OP1 ) |
MCTRL_SIG ( DSR_IP , LINE_IP0 ) |
MCTRL_SIG ( CTS_IP , LINE_IP1 ) |
MCTRL_SIG ( DCD_IP , LINE_IP2 ) |
MCTRL_SIG ( RNG_IP , LINE_IP3 ) ,
} ;
2012-10-11 13:14:13 +04:00
static struct platform_device sc26xx_pdev = {
2012-08-25 19:24:20 +04:00
. name = " sc2681 " ,
2012-10-11 13:14:13 +04:00
. resource = sc26xx_rsrc ,
. num_resources = ARRAY_SIZE ( sc26xx_rsrc ) ,
2012-08-25 19:24:20 +04:00
. dev = {
. platform_data = & sccnxp_data ,
} ,
} ;
2006-12-28 20:22:32 +03:00
static u32 a20r_ack_hwint ( void )
{
u32 status = read_c0_status ( ) ;
2007-10-12 02:46:15 +04:00
write_c0_status ( status | 0x00010000 ) ;
2006-12-28 20:22:32 +03:00
asm volatile (
" .set push \n "
" .set noat \n "
" .set noreorder \n "
" lw $1, 0(%0) \n "
" sb $0, 0(%1) \n "
" sync \n "
" lb %1, 0(%1) \n "
" b 1f \n "
" ori %1, $1, 2 \n "
" .align 8 \n "
" 1: \n "
" nop \n "
" sw %1, 0(%0) \n "
" sync \n "
" li %1, 0x20 \n "
" 2: \n "
" nop \n "
" bnez %1,2b \n "
" addiu %1, -1 \n "
" sw $1, 0(%0) \n "
" sync \n "
2013-01-22 15:59:30 +04:00
" .set pop \n "
2006-12-28 20:22:32 +03:00
:
: " Jr " ( PCIMT_UCONF ) , " Jr " ( 0xbc000000 ) ) ;
write_c0_status ( status ) ;
return status ;
}
2011-03-24 00:09:15 +03:00
static inline void unmask_a20r_irq ( struct irq_data * d )
2006-12-28 20:22:32 +03:00
{
2011-03-24 00:09:15 +03:00
set_c0_status ( 0x100 < < ( d - > irq - SNI_A20R_IRQ_BASE ) ) ;
2006-12-28 20:22:32 +03:00
irq_enable_hazard ( ) ;
}
2011-03-24 00:09:15 +03:00
static inline void mask_a20r_irq ( struct irq_data * d )
2006-12-28 20:22:32 +03:00
{
2011-03-24 00:09:15 +03:00
clear_c0_status ( 0x100 < < ( d - > irq - SNI_A20R_IRQ_BASE ) ) ;
2006-12-28 20:22:32 +03:00
irq_disable_hazard ( ) ;
}
static struct irq_chip a20r_irq_type = {
2009-11-18 01:51:03 +03:00
. name = " A20R " ,
2011-03-24 00:09:15 +03:00
. irq_mask = mask_a20r_irq ,
. irq_unmask = unmask_a20r_irq ,
2006-12-28 20:22:32 +03:00
} ;
/*
* hwint 0 receive all interrupts
*/
static void a20r_hwint ( void )
{
u32 cause , status ;
int irq ;
2007-10-12 02:46:15 +04:00
clear_c0_status ( IE_IRQ0 ) ;
2006-12-28 20:22:32 +03:00
status = a20r_ack_hwint ( ) ;
cause = read_c0_cause ( ) ;
irq = ffs ( ( ( cause & status ) > > 8 ) & 0xf8 ) ;
if ( likely ( irq > 0 ) )
do_IRQ ( SNI_A20R_IRQ_BASE + irq - 1 ) ;
set_c0_status ( IE_IRQ0 ) ;
}
void __init sni_a20r_irq_init ( void )
{
int i ;
for ( i = SNI_A20R_IRQ_BASE + 2 ; i < SNI_A20R_IRQ_BASE + 8 ; i + + )
2011-03-27 17:19:28 +04:00
irq_set_chip_and_handler ( i , & a20r_irq_type , handle_level_irq ) ;
2006-12-28 20:22:32 +03:00
sni_hwint = a20r_hwint ;
change_c0_status ( ST0_IM , IE_IRQ0 ) ;
2007-10-12 02:46:15 +04:00
setup_irq ( SNI_A20R_IRQ_BASE + 3 , & sni_isa_irq ) ;
2006-12-28 20:22:32 +03:00
}
void sni_a20r_init ( void )
{
2007-06-21 01:36:47 +04:00
/* FIXME, remove if not needed */
2006-12-28 20:22:32 +03:00
}
static int __init snirm_a20r_setup_devinit ( void )
{
switch ( sni_brd_type ) {
case SNI_BRD_TOWER_OASIC :
case SNI_BRD_MINITOWER :
2013-01-22 15:59:30 +04:00
platform_device_register ( & snirm_82596_pdev ) ;
platform_device_register ( & snirm_53c710_pdev ) ;
platform_device_register ( & sc26xx_pdev ) ;
platform_device_register ( & a20r_serial8250_device ) ;
platform_device_register ( & a20r_ds1216_device ) ;
2008-01-05 01:31:07 +03:00
sni_eisa_root_init ( ) ;
2013-01-22 15:59:30 +04:00
break ;
2006-12-28 20:22:32 +03:00
}
return 0 ;
}
device_initcall ( snirm_a20r_setup_devinit ) ;