2005-11-07 01:00:19 -08:00
/*
2008-04-18 13:33:38 -07:00
* Freescale MPC85xx / MPC86xx RapidIO support
2005-11-07 01:00:19 -08:00
*
2008-04-18 13:33:41 -07:00
* Copyright ( C ) 2007 , 2008 Freescale Semiconductor , Inc .
* Zhang Wei < wei . zhang @ freescale . com >
*
2005-11-07 01:00:19 -08:00
* Copyright 2005 MontaVista Software , Inc .
* Matt Porter < mporter @ kernel . crashing . org >
*
* 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 ; either version 2 of the License , or ( at your
* option ) any later version .
*/
# include <linux/init.h>
# include <linux/module.h>
# include <linux/types.h>
# include <linux/dma-mapping.h>
# include <linux/interrupt.h>
# include <linux/rio.h>
# include <linux/rio_drv.h>
# include <asm/io.h>
2008-04-18 13:33:41 -07:00
/* RapidIO definition irq, which read from OF-tree */
# define IRQ_RIO_BELL(m) (((struct rio_priv *)(m->priv))->bellirq)
# define IRQ_RIO_TX(m) (((struct rio_priv *)(m->priv))->txirq)
# define IRQ_RIO_RX(m) (((struct rio_priv *)(m->priv))->rxirq)
2005-11-07 01:00:19 -08:00
# define RIO_REGS_BASE (CCSRBAR + 0xc0000)
# define RIO_ATMU_REGS_OFFSET 0x10c00
# define RIO_MSG_REGS_OFFSET 0x11000
# define RIO_MAINT_WIN_SIZE 0x400000
# define RIO_DBELL_WIN_SIZE 0x1000
# define RIO_MSG_OMR_MUI 0x00000002
# define RIO_MSG_OSR_TE 0x00000080
# define RIO_MSG_OSR_QOI 0x00000020
# define RIO_MSG_OSR_QFI 0x00000010
# define RIO_MSG_OSR_MUB 0x00000004
# define RIO_MSG_OSR_EOMI 0x00000002
# define RIO_MSG_OSR_QEI 0x00000001
# define RIO_MSG_IMR_MI 0x00000002
# define RIO_MSG_ISR_TE 0x00000080
# define RIO_MSG_ISR_QFI 0x00000010
# define RIO_MSG_ISR_DIQI 0x00000001
# define RIO_MSG_DESC_SIZE 32
# define RIO_MSG_BUFFER_SIZE 4096
# define RIO_MIN_TX_RING_SIZE 2
# define RIO_MAX_TX_RING_SIZE 2048
# define RIO_MIN_RX_RING_SIZE 2
# define RIO_MAX_RX_RING_SIZE 2048
# define DOORBELL_DMR_DI 0x00000002
# define DOORBELL_DSR_TE 0x00000080
# define DOORBELL_DSR_QFI 0x00000010
# define DOORBELL_DSR_DIQI 0x00000001
# define DOORBELL_TID_OFFSET 0x03
# define DOORBELL_SID_OFFSET 0x05
# define DOORBELL_INFO_OFFSET 0x06
# define DOORBELL_MESSAGE_SIZE 0x08
# define DBELL_SID(x) (*(u8 *)(x + DOORBELL_SID_OFFSET))
# define DBELL_TID(x) (*(u8 *)(x + DOORBELL_TID_OFFSET))
# define DBELL_INF(x) (*(u16 *)(x + DOORBELL_INFO_OFFSET))
struct rio_atmu_regs {
u32 rowtar ;
u32 pad1 ;
u32 rowbar ;
u32 pad2 ;
u32 rowar ;
u32 pad3 [ 3 ] ;
} ;
struct rio_msg_regs {
u32 omr ;
u32 osr ;
u32 pad1 ;
u32 odqdpar ;
u32 pad2 ;
u32 osar ;
u32 odpr ;
u32 odatr ;
u32 odcr ;
u32 pad3 ;
u32 odqepar ;
u32 pad4 [ 13 ] ;
u32 imr ;
u32 isr ;
u32 pad5 ;
u32 ifqdpar ;
u32 pad6 ;
u32 ifqepar ;
u32 pad7 [ 250 ] ;
u32 dmr ;
u32 dsr ;
u32 pad8 ;
u32 dqdpar ;
u32 pad9 ;
u32 dqepar ;
u32 pad10 [ 26 ] ;
u32 pwmr ;
u32 pwsr ;
u32 pad11 ;
u32 pwqbar ;
} ;
struct rio_tx_desc {
u32 res1 ;
u32 saddr ;
u32 dport ;
u32 dattr ;
u32 res2 ;
u32 res3 ;
u32 dwcnt ;
u32 res4 ;
} ;
2008-04-18 13:33:41 -07:00
struct rio_dbell_ring {
2005-11-07 01:00:19 -08:00
void * virt ;
dma_addr_t phys ;
2008-04-18 13:33:41 -07:00
} ;
2005-11-07 01:00:19 -08:00
2008-04-18 13:33:41 -07:00
struct rio_msg_tx_ring {
2005-11-07 01:00:19 -08:00
void * virt ;
dma_addr_t phys ;
void * virt_buffer [ RIO_MAX_TX_RING_SIZE ] ;
dma_addr_t phys_buffer [ RIO_MAX_TX_RING_SIZE ] ;
int tx_slot ;
int size ;
2005-11-07 01:00:20 -08:00
void * dev_id ;
2008-04-18 13:33:41 -07:00
} ;
2005-11-07 01:00:19 -08:00
2008-04-18 13:33:41 -07:00
struct rio_msg_rx_ring {
2005-11-07 01:00:19 -08:00
void * virt ;
dma_addr_t phys ;
void * virt_buffer [ RIO_MAX_RX_RING_SIZE ] ;
int rx_slot ;
int size ;
2005-11-07 01:00:20 -08:00
void * dev_id ;
2008-04-18 13:33:41 -07:00
} ;
struct rio_priv {
void __iomem * regs_win ;
struct rio_atmu_regs __iomem * atmu_regs ;
struct rio_atmu_regs __iomem * maint_atmu_regs ;
struct rio_atmu_regs __iomem * dbell_atmu_regs ;
void __iomem * dbell_win ;
void __iomem * maint_win ;
struct rio_msg_regs __iomem * msg_regs ;
struct rio_dbell_ring dbell_ring ;
struct rio_msg_tx_ring msg_tx_ring ;
struct rio_msg_rx_ring msg_rx_ring ;
int bellirq ;
int txirq ;
int rxirq ;
} ;
2005-11-07 01:00:19 -08:00
/**
2008-04-18 13:33:38 -07:00
* fsl_rio_doorbell_send - Send a MPC85xx doorbell message
2005-11-07 01:00:19 -08:00
* @ index : ID of RapidIO interface
* @ destid : Destination ID of target device
* @ data : 16 - bit info field of RapidIO doorbell message
*
* Sends a MPC85xx doorbell message . Returns % 0 on success or
* % - EINVAL on failure .
*/
2008-04-18 13:33:41 -07:00
static int fsl_rio_doorbell_send ( struct rio_mport * mport ,
int index , u16 destid , u16 data )
2005-11-07 01:00:19 -08:00
{
2008-04-18 13:33:41 -07:00
struct rio_priv * priv = mport - > priv ;
2008-04-18 13:33:38 -07:00
pr_debug ( " fsl_doorbell_send: index %d destid %4.4x data %4.4x \n " ,
2005-11-07 01:00:19 -08:00
index , destid , data ) ;
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > dbell_atmu_regs - > rowtar , destid < < 22 ) ;
out_be16 ( priv - > dbell_win , data ) ;
2005-11-07 01:00:19 -08:00
return 0 ;
}
/**
2008-04-18 13:33:38 -07:00
* fsl_local_config_read - Generate a MPC85xx local config space read
2005-11-07 01:00:19 -08:00
* @ index : ID of RapdiIO interface
* @ offset : Offset into configuration space
* @ len : Length ( in bytes ) of the maintenance transaction
* @ data : Value to be read into
*
* Generates a MPC85xx local configuration space read . Returns % 0 on
* success or % - EINVAL on failure .
*/
2008-04-18 13:33:41 -07:00
static int fsl_local_config_read ( struct rio_mport * mport ,
int index , u32 offset , int len , u32 * data )
2005-11-07 01:00:19 -08:00
{
2008-04-18 13:33:41 -07:00
struct rio_priv * priv = mport - > priv ;
2008-04-18 13:33:38 -07:00
pr_debug ( " fsl_local_config_read: index %d offset %8.8x \n " , index ,
2005-11-07 01:00:19 -08:00
offset ) ;
2008-04-18 13:33:41 -07:00
* data = in_be32 ( priv - > regs_win + offset ) ;
2005-11-07 01:00:19 -08:00
return 0 ;
}
/**
2008-04-18 13:33:38 -07:00
* fsl_local_config_write - Generate a MPC85xx local config space write
2005-11-07 01:00:19 -08:00
* @ index : ID of RapdiIO interface
* @ offset : Offset into configuration space
* @ len : Length ( in bytes ) of the maintenance transaction
* @ data : Value to be written
*
* Generates a MPC85xx local configuration space write . Returns % 0 on
* success or % - EINVAL on failure .
*/
2008-04-18 13:33:41 -07:00
static int fsl_local_config_write ( struct rio_mport * mport ,
int index , u32 offset , int len , u32 data )
2005-11-07 01:00:19 -08:00
{
2008-04-18 13:33:41 -07:00
struct rio_priv * priv = mport - > priv ;
2005-11-07 01:00:19 -08:00
pr_debug
2008-04-18 13:33:38 -07:00
( " fsl_local_config_write: index %d offset %8.8x data %8.8x \n " ,
2005-11-07 01:00:19 -08:00
index , offset , data ) ;
2008-04-18 13:33:41 -07:00
out_be32 ( priv - > regs_win + offset , data ) ;
2005-11-07 01:00:19 -08:00
return 0 ;
}
/**
2008-04-18 13:33:38 -07:00
* fsl_rio_config_read - Generate a MPC85xx read maintenance transaction
2005-11-07 01:00:19 -08:00
* @ index : ID of RapdiIO interface
* @ destid : Destination ID of transaction
* @ hopcount : Number of hops to target device
* @ offset : Offset into configuration space
* @ len : Length ( in bytes ) of the maintenance transaction
* @ val : Location to be read into
*
* Generates a MPC85xx read maintenance transaction . Returns % 0 on
* success or % - EINVAL on failure .
*/
static int
2008-04-18 13:33:41 -07:00
fsl_rio_config_read ( struct rio_mport * mport , int index , u16 destid ,
u8 hopcount , u32 offset , int len , u32 * val )
2005-11-07 01:00:19 -08:00
{
2008-04-18 13:33:41 -07:00
struct rio_priv * priv = mport - > priv ;
2005-11-07 01:00:19 -08:00
u8 * data ;
pr_debug
2008-04-18 13:33:38 -07:00
( " fsl_rio_config_read: index %d destid %d hopcount %d offset %8.8x len %d \n " ,
2005-11-07 01:00:19 -08:00
index , destid , hopcount , offset , len ) ;
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > maint_atmu_regs - > rowtar ,
2005-11-07 01:00:19 -08:00
( destid < < 22 ) | ( hopcount < < 12 ) | ( ( offset & ~ 0x3 ) > > 9 ) ) ;
2008-04-18 13:33:41 -07:00
data = ( u8 * ) priv - > maint_win + offset ;
2005-11-07 01:00:19 -08:00
switch ( len ) {
case 1 :
* val = in_8 ( ( u8 * ) data ) ;
break ;
case 2 :
* val = in_be16 ( ( u16 * ) data ) ;
break ;
default :
* val = in_be32 ( ( u32 * ) data ) ;
break ;
}
return 0 ;
}
/**
2008-04-18 13:33:38 -07:00
* fsl_rio_config_write - Generate a MPC85xx write maintenance transaction
2005-11-07 01:00:19 -08:00
* @ index : ID of RapdiIO interface
* @ destid : Destination ID of transaction
* @ hopcount : Number of hops to target device
* @ offset : Offset into configuration space
* @ len : Length ( in bytes ) of the maintenance transaction
* @ val : Value to be written
*
* Generates an MPC85xx write maintenance transaction . Returns % 0 on
* success or % - EINVAL on failure .
*/
static int
2008-04-18 13:33:41 -07:00
fsl_rio_config_write ( struct rio_mport * mport , int index , u16 destid ,
u8 hopcount , u32 offset , int len , u32 val )
2005-11-07 01:00:19 -08:00
{
2008-04-18 13:33:41 -07:00
struct rio_priv * priv = mport - > priv ;
2005-11-07 01:00:19 -08:00
u8 * data ;
pr_debug
2008-04-18 13:33:38 -07:00
( " fsl_rio_config_write: index %d destid %d hopcount %d offset %8.8x len %d val %8.8x \n " ,
2005-11-07 01:00:19 -08:00
index , destid , hopcount , offset , len , val ) ;
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > maint_atmu_regs - > rowtar ,
2005-11-07 01:00:19 -08:00
( destid < < 22 ) | ( hopcount < < 12 ) | ( ( offset & ~ 0x3 ) > > 9 ) ) ;
2008-04-18 13:33:41 -07:00
data = ( u8 * ) priv - > maint_win + offset ;
2005-11-07 01:00:19 -08:00
switch ( len ) {
case 1 :
out_8 ( ( u8 * ) data , val ) ;
break ;
case 2 :
out_be16 ( ( u16 * ) data , val ) ;
break ;
default :
out_be32 ( ( u32 * ) data , val ) ;
break ;
}
return 0 ;
}
/**
* rio_hw_add_outb_message - Add message to the MPC85xx outbound message queue
* @ mport : Master port with outbound message queue
* @ rdev : Target of outbound message
* @ mbox : Outbound mailbox
* @ buffer : Message to add to outbound queue
* @ len : Length of message
*
* Adds the @ buffer message to the MPC85xx outbound message queue . Returns
* % 0 on success or % - EINVAL on failure .
*/
int
rio_hw_add_outb_message ( struct rio_mport * mport , struct rio_dev * rdev , int mbox ,
void * buffer , size_t len )
{
2008-04-18 13:33:41 -07:00
struct rio_priv * priv = mport - > priv ;
2005-11-07 01:00:19 -08:00
u32 omr ;
2008-04-18 13:33:41 -07:00
struct rio_tx_desc * desc = ( struct rio_tx_desc * ) priv - > msg_tx_ring . virt
+ priv - > msg_tx_ring . tx_slot ;
2005-11-07 01:00:19 -08:00
int ret = 0 ;
pr_debug
( " RIO: rio_hw_add_outb_message(): destid %4.4x mbox %d buffer %8.8x len %8.8x \n " ,
rdev - > destid , mbox , ( int ) buffer , len ) ;
if ( ( len < 8 ) | | ( len > RIO_MAX_MSG_SIZE ) ) {
ret = - EINVAL ;
goto out ;
}
/* Copy and clear rest of buffer */
2008-04-18 13:33:41 -07:00
memcpy ( priv - > msg_tx_ring . virt_buffer [ priv - > msg_tx_ring . tx_slot ] , buffer ,
len ) ;
2005-11-07 01:00:19 -08:00
if ( len < ( RIO_MAX_MSG_SIZE - 4 ) )
2008-04-18 13:33:41 -07:00
memset ( priv - > msg_tx_ring . virt_buffer [ priv - > msg_tx_ring . tx_slot ]
+ len , 0 , RIO_MAX_MSG_SIZE - len ) ;
2005-11-07 01:00:19 -08:00
/* Set mbox field for message */
desc - > dport = mbox & 0x3 ;
/* Enable EOMI interrupt, set priority, and set destid */
desc - > dattr = 0x28000000 | ( rdev - > destid < < 2 ) ;
/* Set transfer size aligned to next power of 2 (in double words) */
desc - > dwcnt = is_power_of_2 ( len ) ? len : 1 < < get_bitmask_order ( len ) ;
/* Set snooping and source buffer address */
2008-04-18 13:33:41 -07:00
desc - > saddr = 0x00000004
| priv - > msg_tx_ring . phys_buffer [ priv - > msg_tx_ring . tx_slot ] ;
2005-11-07 01:00:19 -08:00
/* Increment enqueue pointer */
2008-04-18 13:33:41 -07:00
omr = in_be32 ( & priv - > msg_regs - > omr ) ;
out_be32 ( & priv - > msg_regs - > omr , omr | RIO_MSG_OMR_MUI ) ;
2005-11-07 01:00:19 -08:00
/* Go to next descriptor */
2008-04-18 13:33:41 -07:00
if ( + + priv - > msg_tx_ring . tx_slot = = priv - > msg_tx_ring . size )
priv - > msg_tx_ring . tx_slot = 0 ;
2005-11-07 01:00:19 -08:00
out :
return ret ;
}
EXPORT_SYMBOL_GPL ( rio_hw_add_outb_message ) ;
/**
2008-04-18 13:33:38 -07:00
* fsl_rio_tx_handler - MPC85xx outbound message interrupt handler
2005-11-07 01:00:19 -08:00
* @ irq : Linux interrupt number
* @ dev_instance : Pointer to interrupt - specific data
*
* Handles outbound message interrupts . Executes a register outbound
2007-05-12 05:42:54 +10:00
* mailbox event handler and acks the interrupt occurrence .
2005-11-07 01:00:19 -08:00
*/
static irqreturn_t
2008-04-18 13:33:38 -07:00
fsl_rio_tx_handler ( int irq , void * dev_instance )
2005-11-07 01:00:19 -08:00
{
int osr ;
struct rio_mport * port = ( struct rio_mport * ) dev_instance ;
2008-04-18 13:33:41 -07:00
struct rio_priv * priv = port - > priv ;
2005-11-07 01:00:19 -08:00
2008-04-18 13:33:41 -07:00
osr = in_be32 ( & priv - > msg_regs - > osr ) ;
2005-11-07 01:00:19 -08:00
if ( osr & RIO_MSG_OSR_TE ) {
pr_info ( " RIO: outbound message transmission error \n " ) ;
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > msg_regs - > osr , RIO_MSG_OSR_TE ) ;
2005-11-07 01:00:19 -08:00
goto out ;
}
if ( osr & RIO_MSG_OSR_QOI ) {
pr_info ( " RIO: outbound message queue overflow \n " ) ;
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > msg_regs - > osr , RIO_MSG_OSR_QOI ) ;
2005-11-07 01:00:19 -08:00
goto out ;
}
if ( osr & RIO_MSG_OSR_EOMI ) {
2008-04-18 13:33:41 -07:00
u32 dqp = in_be32 ( & priv - > msg_regs - > odqdpar ) ;
int slot = ( dqp - priv - > msg_tx_ring . phys ) > > 5 ;
port - > outb_msg [ 0 ] . mcback ( port , priv - > msg_tx_ring . dev_id , - 1 ,
slot ) ;
2005-11-07 01:00:19 -08:00
/* Ack the end-of-message interrupt */
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > msg_regs - > osr , RIO_MSG_OSR_EOMI ) ;
2005-11-07 01:00:19 -08:00
}
out :
return IRQ_HANDLED ;
}
/**
* rio_open_outb_mbox - Initialize MPC85xx outbound mailbox
* @ mport : Master port implementing the outbound message unit
2005-11-07 01:00:20 -08:00
* @ dev_id : Device specific pointer to pass on event
2005-11-07 01:00:19 -08:00
* @ mbox : Mailbox to open
* @ entries : Number of entries in the outbound mailbox ring
*
* Initializes buffer ring , request the outbound message interrupt ,
* and enables the outbound message unit . Returns % 0 on success and
* % - EINVAL or % - ENOMEM on failure .
*/
2005-11-07 01:00:20 -08:00
int rio_open_outb_mbox ( struct rio_mport * mport , void * dev_id , int mbox , int entries )
2005-11-07 01:00:19 -08:00
{
int i , j , rc = 0 ;
2008-04-18 13:33:41 -07:00
struct rio_priv * priv = mport - > priv ;
2005-11-07 01:00:19 -08:00
if ( ( entries < RIO_MIN_TX_RING_SIZE ) | |
( entries > RIO_MAX_TX_RING_SIZE ) | | ( ! is_power_of_2 ( entries ) ) ) {
rc = - EINVAL ;
goto out ;
}
/* Initialize shadow copy ring */
2008-04-18 13:33:41 -07:00
priv - > msg_tx_ring . dev_id = dev_id ;
priv - > msg_tx_ring . size = entries ;
for ( i = 0 ; i < priv - > msg_tx_ring . size ; i + + ) {
priv - > msg_tx_ring . virt_buffer [ i ] =
dma_alloc_coherent ( NULL , RIO_MSG_BUFFER_SIZE ,
& priv - > msg_tx_ring . phys_buffer [ i ] , GFP_KERNEL ) ;
if ( ! priv - > msg_tx_ring . virt_buffer [ i ] ) {
2005-11-07 01:00:19 -08:00
rc = - ENOMEM ;
2008-04-18 13:33:41 -07:00
for ( j = 0 ; j < priv - > msg_tx_ring . size ; j + + )
if ( priv - > msg_tx_ring . virt_buffer [ j ] )
2005-11-07 01:00:19 -08:00
dma_free_coherent ( NULL ,
2008-04-18 13:33:41 -07:00
RIO_MSG_BUFFER_SIZE ,
priv - > msg_tx_ring .
virt_buffer [ j ] ,
priv - > msg_tx_ring .
phys_buffer [ j ] ) ;
2005-11-07 01:00:19 -08:00
goto out ;
}
}
/* Initialize outbound message descriptor ring */
2008-04-18 13:33:41 -07:00
priv - > msg_tx_ring . virt = dma_alloc_coherent ( NULL ,
priv - > msg_tx_ring . size * RIO_MSG_DESC_SIZE ,
& priv - > msg_tx_ring . phys , GFP_KERNEL ) ;
if ( ! priv - > msg_tx_ring . virt ) {
2005-11-07 01:00:19 -08:00
rc = - ENOMEM ;
goto out_dma ;
}
2008-04-18 13:33:41 -07:00
memset ( priv - > msg_tx_ring . virt , 0 ,
priv - > msg_tx_ring . size * RIO_MSG_DESC_SIZE ) ;
priv - > msg_tx_ring . tx_slot = 0 ;
2005-11-07 01:00:19 -08:00
/* Point dequeue/enqueue pointers at first entry in ring */
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > msg_regs - > odqdpar , priv - > msg_tx_ring . phys ) ;
out_be32 ( & priv - > msg_regs - > odqepar , priv - > msg_tx_ring . phys ) ;
2005-11-07 01:00:19 -08:00
/* Configure for snooping */
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > msg_regs - > osar , 0x00000004 ) ;
2005-11-07 01:00:19 -08:00
/* Clear interrupt status */
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > msg_regs - > osr , 0x000000b3 ) ;
2005-11-07 01:00:19 -08:00
/* Hook up outbound message handler */
2008-04-18 13:33:41 -07:00
rc = request_irq ( IRQ_RIO_TX ( mport ) , fsl_rio_tx_handler , 0 ,
" msg_tx " , ( void * ) mport ) ;
if ( rc < 0 )
2005-11-07 01:00:19 -08:00
goto out_irq ;
/*
* Configure outbound message unit
* Snooping
* Interrupts ( all enabled , except QEIE )
* Chaining mode
* Disable
*/
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > msg_regs - > omr , 0x00100220 ) ;
2005-11-07 01:00:19 -08:00
/* Set number of entries */
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > msg_regs - > omr ,
in_be32 ( & priv - > msg_regs - > omr ) |
2005-11-07 01:00:19 -08:00
( ( get_bitmask_order ( entries ) - 2 ) < < 12 ) ) ;
/* Now enable the unit */
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > msg_regs - > omr , in_be32 ( & priv - > msg_regs - > omr ) | 0x1 ) ;
2005-11-07 01:00:19 -08:00
out :
return rc ;
out_irq :
2008-04-18 13:33:41 -07:00
dma_free_coherent ( NULL , priv - > msg_tx_ring . size * RIO_MSG_DESC_SIZE ,
priv - > msg_tx_ring . virt , priv - > msg_tx_ring . phys ) ;
2005-11-07 01:00:19 -08:00
out_dma :
2008-04-18 13:33:41 -07:00
for ( i = 0 ; i < priv - > msg_tx_ring . size ; i + + )
2005-11-07 01:00:19 -08:00
dma_free_coherent ( NULL , RIO_MSG_BUFFER_SIZE ,
2008-04-18 13:33:41 -07:00
priv - > msg_tx_ring . virt_buffer [ i ] ,
priv - > msg_tx_ring . phys_buffer [ i ] ) ;
2005-11-07 01:00:19 -08:00
return rc ;
}
/**
* rio_close_outb_mbox - Shut down MPC85xx outbound mailbox
* @ mport : Master port implementing the outbound message unit
* @ mbox : Mailbox to close
*
* Disables the outbound message unit , free all buffers , and
* frees the outbound message interrupt .
*/
void rio_close_outb_mbox ( struct rio_mport * mport , int mbox )
{
2008-04-18 13:33:41 -07:00
struct rio_priv * priv = mport - > priv ;
2005-11-07 01:00:19 -08:00
/* Disable inbound message unit */
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > msg_regs - > omr , 0 ) ;
2005-11-07 01:00:19 -08:00
/* Free ring */
2008-04-18 13:33:41 -07:00
dma_free_coherent ( NULL , priv - > msg_tx_ring . size * RIO_MSG_DESC_SIZE ,
priv - > msg_tx_ring . virt , priv - > msg_tx_ring . phys ) ;
2005-11-07 01:00:19 -08:00
/* Free interrupt */
2008-04-18 13:33:41 -07:00
free_irq ( IRQ_RIO_TX ( mport ) , ( void * ) mport ) ;
2005-11-07 01:00:19 -08:00
}
/**
2008-04-18 13:33:38 -07:00
* fsl_rio_rx_handler - MPC85xx inbound message interrupt handler
2005-11-07 01:00:19 -08:00
* @ irq : Linux interrupt number
* @ dev_instance : Pointer to interrupt - specific data
*
* Handles inbound message interrupts . Executes a registered inbound
2007-05-12 05:42:54 +10:00
* mailbox event handler and acks the interrupt occurrence .
2005-11-07 01:00:19 -08:00
*/
static irqreturn_t
2008-04-18 13:33:38 -07:00
fsl_rio_rx_handler ( int irq , void * dev_instance )
2005-11-07 01:00:19 -08:00
{
int isr ;
struct rio_mport * port = ( struct rio_mport * ) dev_instance ;
2008-04-18 13:33:41 -07:00
struct rio_priv * priv = port - > priv ;
2005-11-07 01:00:19 -08:00
2008-04-18 13:33:41 -07:00
isr = in_be32 ( & priv - > msg_regs - > isr ) ;
2005-11-07 01:00:19 -08:00
if ( isr & RIO_MSG_ISR_TE ) {
pr_info ( " RIO: inbound message reception error \n " ) ;
2008-04-18 13:33:41 -07:00
out_be32 ( ( void * ) & priv - > msg_regs - > isr , RIO_MSG_ISR_TE ) ;
2005-11-07 01:00:19 -08:00
goto out ;
}
/* XXX Need to check/dispatch until queue empty */
if ( isr & RIO_MSG_ISR_DIQI ) {
/*
* We implement * only * mailbox 0 , but can receive messages
* for any mailbox / letter to that mailbox destination . So ,
* make the callback with an unknown / invalid mailbox number
* argument .
*/
2008-04-18 13:33:41 -07:00
port - > inb_msg [ 0 ] . mcback ( port , priv - > msg_rx_ring . dev_id , - 1 , - 1 ) ;
2005-11-07 01:00:19 -08:00
/* Ack the queueing interrupt */
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > msg_regs - > isr , RIO_MSG_ISR_DIQI ) ;
2005-11-07 01:00:19 -08:00
}
out :
return IRQ_HANDLED ;
}
/**
* rio_open_inb_mbox - Initialize MPC85xx inbound mailbox
* @ mport : Master port implementing the inbound message unit
2005-11-07 01:00:20 -08:00
* @ dev_id : Device specific pointer to pass on event
2005-11-07 01:00:19 -08:00
* @ mbox : Mailbox to open
* @ entries : Number of entries in the inbound mailbox ring
*
* Initializes buffer ring , request the inbound message interrupt ,
* and enables the inbound message unit . Returns % 0 on success
* and % - EINVAL or % - ENOMEM on failure .
*/
2005-11-07 01:00:20 -08:00
int rio_open_inb_mbox ( struct rio_mport * mport , void * dev_id , int mbox , int entries )
2005-11-07 01:00:19 -08:00
{
int i , rc = 0 ;
2008-04-18 13:33:41 -07:00
struct rio_priv * priv = mport - > priv ;
2005-11-07 01:00:19 -08:00
if ( ( entries < RIO_MIN_RX_RING_SIZE ) | |
( entries > RIO_MAX_RX_RING_SIZE ) | | ( ! is_power_of_2 ( entries ) ) ) {
rc = - EINVAL ;
goto out ;
}
/* Initialize client buffer ring */
2008-04-18 13:33:41 -07:00
priv - > msg_rx_ring . dev_id = dev_id ;
priv - > msg_rx_ring . size = entries ;
priv - > msg_rx_ring . rx_slot = 0 ;
for ( i = 0 ; i < priv - > msg_rx_ring . size ; i + + )
priv - > msg_rx_ring . virt_buffer [ i ] = NULL ;
2005-11-07 01:00:19 -08:00
/* Initialize inbound message ring */
2008-04-18 13:33:41 -07:00
priv - > msg_rx_ring . virt = dma_alloc_coherent ( NULL ,
priv - > msg_rx_ring . size * RIO_MAX_MSG_SIZE ,
& priv - > msg_rx_ring . phys , GFP_KERNEL ) ;
if ( ! priv - > msg_rx_ring . virt ) {
2005-11-07 01:00:19 -08:00
rc = - ENOMEM ;
goto out ;
}
/* Point dequeue/enqueue pointers at first entry in ring */
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > msg_regs - > ifqdpar , ( u32 ) priv - > msg_rx_ring . phys ) ;
out_be32 ( & priv - > msg_regs - > ifqepar , ( u32 ) priv - > msg_rx_ring . phys ) ;
2005-11-07 01:00:19 -08:00
/* Clear interrupt status */
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > msg_regs - > isr , 0x00000091 ) ;
2005-11-07 01:00:19 -08:00
/* Hook up inbound message handler */
2008-04-18 13:33:41 -07:00
rc = request_irq ( IRQ_RIO_RX ( mport ) , fsl_rio_rx_handler , 0 ,
" msg_rx " , ( void * ) mport ) ;
if ( rc < 0 ) {
2005-11-07 01:00:19 -08:00
dma_free_coherent ( NULL , RIO_MSG_BUFFER_SIZE ,
2008-04-18 13:33:41 -07:00
priv - > msg_tx_ring . virt_buffer [ i ] ,
priv - > msg_tx_ring . phys_buffer [ i ] ) ;
2005-11-07 01:00:19 -08:00
goto out ;
}
/*
* Configure inbound message unit :
* Snooping
* 4 KB max message size
* Unmask all interrupt sources
* Disable
*/
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > msg_regs - > imr , 0x001b0060 ) ;
2005-11-07 01:00:19 -08:00
/* Set number of queue entries */
2008-04-18 13:33:41 -07:00
setbits32 ( & priv - > msg_regs - > imr , ( get_bitmask_order ( entries ) - 2 ) < < 12 ) ;
2005-11-07 01:00:19 -08:00
/* Now enable the unit */
2008-04-18 13:33:41 -07:00
setbits32 ( & priv - > msg_regs - > imr , 0x1 ) ;
2005-11-07 01:00:19 -08:00
out :
return rc ;
}
/**
* rio_close_inb_mbox - Shut down MPC85xx inbound mailbox
* @ mport : Master port implementing the inbound message unit
* @ mbox : Mailbox to close
*
* Disables the inbound message unit , free all buffers , and
* frees the inbound message interrupt .
*/
void rio_close_inb_mbox ( struct rio_mport * mport , int mbox )
{
2008-04-18 13:33:41 -07:00
struct rio_priv * priv = mport - > priv ;
2005-11-07 01:00:19 -08:00
/* Disable inbound message unit */
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > msg_regs - > imr , 0 ) ;
2005-11-07 01:00:19 -08:00
/* Free ring */
2008-04-18 13:33:41 -07:00
dma_free_coherent ( NULL , priv - > msg_rx_ring . size * RIO_MAX_MSG_SIZE ,
priv - > msg_rx_ring . virt , priv - > msg_rx_ring . phys ) ;
2005-11-07 01:00:19 -08:00
/* Free interrupt */
2008-04-18 13:33:41 -07:00
free_irq ( IRQ_RIO_RX ( mport ) , ( void * ) mport ) ;
2005-11-07 01:00:19 -08:00
}
/**
* rio_hw_add_inb_buffer - Add buffer to the MPC85xx inbound message queue
* @ mport : Master port implementing the inbound message unit
* @ mbox : Inbound mailbox number
* @ buf : Buffer to add to inbound queue
*
* Adds the @ buf buffer to the MPC85xx inbound message queue . Returns
* % 0 on success or % - EINVAL on failure .
*/
int rio_hw_add_inb_buffer ( struct rio_mport * mport , int mbox , void * buf )
{
int rc = 0 ;
2008-04-18 13:33:41 -07:00
struct rio_priv * priv = mport - > priv ;
2005-11-07 01:00:19 -08:00
pr_debug ( " RIO: rio_hw_add_inb_buffer(), msg_rx_ring.rx_slot %d \n " ,
2008-04-18 13:33:41 -07:00
priv - > msg_rx_ring . rx_slot ) ;
2005-11-07 01:00:19 -08:00
2008-04-18 13:33:41 -07:00
if ( priv - > msg_rx_ring . virt_buffer [ priv - > msg_rx_ring . rx_slot ] ) {
2005-11-07 01:00:19 -08:00
printk ( KERN_ERR
" RIO: error adding inbound buffer %d, buffer exists \n " ,
2008-04-18 13:33:41 -07:00
priv - > msg_rx_ring . rx_slot ) ;
2005-11-07 01:00:19 -08:00
rc = - EINVAL ;
goto out ;
}
2008-04-18 13:33:41 -07:00
priv - > msg_rx_ring . virt_buffer [ priv - > msg_rx_ring . rx_slot ] = buf ;
if ( + + priv - > msg_rx_ring . rx_slot = = priv - > msg_rx_ring . size )
priv - > msg_rx_ring . rx_slot = 0 ;
2005-11-07 01:00:19 -08:00
out :
return rc ;
}
EXPORT_SYMBOL_GPL ( rio_hw_add_inb_buffer ) ;
/**
* rio_hw_get_inb_message - Fetch inbound message from the MPC85xx message unit
* @ mport : Master port implementing the inbound message unit
* @ mbox : Inbound mailbox number
*
* Gets the next available inbound message from the inbound message queue .
* A pointer to the message is returned on success or NULL on failure .
*/
void * rio_hw_get_inb_message ( struct rio_mport * mport , int mbox )
{
2008-04-18 13:33:41 -07:00
struct rio_priv * priv = mport - > priv ;
2005-11-07 01:00:19 -08:00
u32 phys_buf , virt_buf ;
void * buf = NULL ;
int buf_idx ;
2008-04-18 13:33:41 -07:00
phys_buf = in_be32 ( & priv - > msg_regs - > ifqdpar ) ;
2005-11-07 01:00:19 -08:00
/* If no more messages, then bail out */
2008-04-18 13:33:41 -07:00
if ( phys_buf = = in_be32 ( & priv - > msg_regs - > ifqepar ) )
2005-11-07 01:00:19 -08:00
goto out2 ;
2008-04-18 13:33:41 -07:00
virt_buf = ( u32 ) priv - > msg_rx_ring . virt + ( phys_buf
- priv - > msg_rx_ring . phys ) ;
buf_idx = ( phys_buf - priv - > msg_rx_ring . phys ) / RIO_MAX_MSG_SIZE ;
buf = priv - > msg_rx_ring . virt_buffer [ buf_idx ] ;
2005-11-07 01:00:19 -08:00
if ( ! buf ) {
printk ( KERN_ERR
" RIO: inbound message copy failed, no buffers \n " ) ;
goto out1 ;
}
/* Copy max message size, caller is expected to allocate that big */
memcpy ( buf , ( void * ) virt_buf , RIO_MAX_MSG_SIZE ) ;
/* Clear the available buffer */
2008-04-18 13:33:41 -07:00
priv - > msg_rx_ring . virt_buffer [ buf_idx ] = NULL ;
2005-11-07 01:00:19 -08:00
out1 :
2008-04-18 13:33:41 -07:00
setbits32 ( & priv - > msg_regs - > imr , RIO_MSG_IMR_MI ) ;
2005-11-07 01:00:19 -08:00
out2 :
return buf ;
}
EXPORT_SYMBOL_GPL ( rio_hw_get_inb_message ) ;
/**
2008-04-18 13:33:38 -07:00
* fsl_rio_dbell_handler - MPC85xx doorbell interrupt handler
2005-11-07 01:00:19 -08:00
* @ irq : Linux interrupt number
* @ dev_instance : Pointer to interrupt - specific data
*
* Handles doorbell interrupts . Parses a list of registered
* doorbell event handlers and executes a matching event handler .
*/
static irqreturn_t
2008-04-18 13:33:38 -07:00
fsl_rio_dbell_handler ( int irq , void * dev_instance )
2005-11-07 01:00:19 -08:00
{
int dsr ;
struct rio_mport * port = ( struct rio_mport * ) dev_instance ;
2008-04-18 13:33:41 -07:00
struct rio_priv * priv = port - > priv ;
2005-11-07 01:00:19 -08:00
2008-04-18 13:33:41 -07:00
dsr = in_be32 ( & priv - > msg_regs - > dsr ) ;
2005-11-07 01:00:19 -08:00
if ( dsr & DOORBELL_DSR_TE ) {
pr_info ( " RIO: doorbell reception error \n " ) ;
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > msg_regs - > dsr , DOORBELL_DSR_TE ) ;
2005-11-07 01:00:19 -08:00
goto out ;
}
if ( dsr & DOORBELL_DSR_QFI ) {
pr_info ( " RIO: doorbell queue full \n " ) ;
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > msg_regs - > dsr , DOORBELL_DSR_QFI ) ;
2005-11-07 01:00:19 -08:00
goto out ;
}
/* XXX Need to check/dispatch until queue empty */
if ( dsr & DOORBELL_DSR_DIQI ) {
u32 dmsg =
2008-04-18 13:33:41 -07:00
( u32 ) priv - > dbell_ring . virt +
( in_be32 ( & priv - > msg_regs - > dqdpar ) & 0xfff ) ;
2005-11-07 01:00:19 -08:00
struct rio_dbell * dbell ;
int found = 0 ;
pr_debug
( " RIO: processing doorbell, sid %2.2x tid %2.2x info %4.4x \n " ,
DBELL_SID ( dmsg ) , DBELL_TID ( dmsg ) , DBELL_INF ( dmsg ) ) ;
list_for_each_entry ( dbell , & port - > dbells , node ) {
if ( ( dbell - > res - > start < = DBELL_INF ( dmsg ) ) & &
( dbell - > res - > end > = DBELL_INF ( dmsg ) ) ) {
found = 1 ;
break ;
}
}
if ( found ) {
2005-11-07 01:00:20 -08:00
dbell - > dinb ( port , dbell - > dev_id , DBELL_SID ( dmsg ) , DBELL_TID ( dmsg ) ,
2005-11-07 01:00:19 -08:00
DBELL_INF ( dmsg ) ) ;
} else {
pr_debug
( " RIO: spurious doorbell, sid %2.2x tid %2.2x info %4.4x \n " ,
DBELL_SID ( dmsg ) , DBELL_TID ( dmsg ) , DBELL_INF ( dmsg ) ) ;
}
2008-04-18 13:33:41 -07:00
setbits32 ( & priv - > msg_regs - > dmr , DOORBELL_DMR_DI ) ;
out_be32 ( & priv - > msg_regs - > dsr , DOORBELL_DSR_DIQI ) ;
2005-11-07 01:00:19 -08:00
}
out :
return IRQ_HANDLED ;
}
/**
2008-04-18 13:33:38 -07:00
* fsl_rio_doorbell_init - MPC85xx doorbell interface init
2005-11-07 01:00:19 -08:00
* @ mport : Master port implementing the inbound doorbell unit
*
* Initializes doorbell unit hardware and inbound DMA buffer
2008-04-18 13:33:38 -07:00
* ring . Called from fsl_rio_setup ( ) . Returns % 0 on success
2005-11-07 01:00:19 -08:00
* or % - ENOMEM on failure .
*/
2008-04-18 13:33:38 -07:00
static int fsl_rio_doorbell_init ( struct rio_mport * mport )
2005-11-07 01:00:19 -08:00
{
2008-04-18 13:33:41 -07:00
struct rio_priv * priv = mport - > priv ;
2005-11-07 01:00:19 -08:00
int rc = 0 ;
/* Map outbound doorbell window immediately after maintenance window */
2008-04-18 13:33:41 -07:00
priv - > dbell_win = ioremap ( mport - > iores . start + RIO_MAINT_WIN_SIZE ,
RIO_DBELL_WIN_SIZE ) ;
if ( ! priv - > dbell_win ) {
2005-11-07 01:00:19 -08:00
printk ( KERN_ERR
" RIO: unable to map outbound doorbell window \n " ) ;
rc = - ENOMEM ;
goto out ;
}
/* Initialize inbound doorbells */
2008-04-18 13:33:41 -07:00
priv - > dbell_ring . virt = dma_alloc_coherent ( NULL , 512 *
DOORBELL_MESSAGE_SIZE , & priv - > dbell_ring . phys , GFP_KERNEL ) ;
if ( ! priv - > dbell_ring . virt ) {
2005-11-07 01:00:19 -08:00
printk ( KERN_ERR " RIO: unable allocate inbound doorbell ring \n " ) ;
rc = - ENOMEM ;
2008-04-18 13:33:41 -07:00
iounmap ( priv - > dbell_win ) ;
2005-11-07 01:00:19 -08:00
goto out ;
}
/* Point dequeue/enqueue pointers at first entry in ring */
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > msg_regs - > dqdpar , ( u32 ) priv - > dbell_ring . phys ) ;
out_be32 ( & priv - > msg_regs - > dqepar , ( u32 ) priv - > dbell_ring . phys ) ;
2005-11-07 01:00:19 -08:00
/* Clear interrupt status */
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > msg_regs - > dsr , 0x00000091 ) ;
2005-11-07 01:00:19 -08:00
/* Hook up doorbell handler */
2008-04-18 13:33:41 -07:00
rc = request_irq ( IRQ_RIO_BELL ( mport ) , fsl_rio_dbell_handler , 0 ,
" dbell_rx " , ( void * ) mport ) ;
if ( rc < 0 ) {
iounmap ( priv - > dbell_win ) ;
2005-11-07 01:00:19 -08:00
dma_free_coherent ( NULL , 512 * DOORBELL_MESSAGE_SIZE ,
2008-04-18 13:33:41 -07:00
priv - > dbell_ring . virt , priv - > dbell_ring . phys ) ;
2005-11-07 01:00:19 -08:00
printk ( KERN_ERR
" MPC85xx RIO: unable to request inbound doorbell irq " ) ;
goto out ;
}
/* Configure doorbells for snooping, 512 entries, and enable */
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > msg_regs - > dmr , 0x00108161 ) ;
2005-11-07 01:00:19 -08:00
out :
return rc ;
}
static char * cmdline = NULL ;
2008-04-18 13:33:38 -07:00
static int fsl_rio_get_hdid ( int index )
2005-11-07 01:00:19 -08:00
{
/* XXX Need to parse multiple entries in some format */
if ( ! cmdline )
return - 1 ;
return simple_strtol ( cmdline , NULL , 0 ) ;
}
2008-04-18 13:33:38 -07:00
static int fsl_rio_get_cmdline ( char * s )
2005-11-07 01:00:19 -08:00
{
if ( ! s )
return 0 ;
cmdline = s ;
return 1 ;
}
2008-04-18 13:33:38 -07:00
__setup ( " riohdid= " , fsl_rio_get_cmdline ) ;
2005-11-07 01:00:19 -08:00
/**
2008-04-18 13:33:38 -07:00
* fsl_rio_setup - Setup MPC85xx RapidIO interface
2005-11-07 01:00:19 -08:00
* @ law_start : Starting physical address of RapidIO LAW
* @ law_size : Size of RapidIO LAW
*
* Initializes MPC85xx RapidIO hardware interface , configures
* master port with system - specific info , and registers the
* master port with the RapidIO subsystem .
*/
2008-04-18 13:33:38 -07:00
void fsl_rio_setup ( int law_start , int law_size )
2005-11-07 01:00:19 -08:00
{
struct rio_ops * ops ;
struct rio_mport * port ;
2008-04-18 13:33:41 -07:00
struct rio_priv * priv = NULL ;
int rc ;
2005-11-07 01:00:19 -08:00
ops = kmalloc ( sizeof ( struct rio_ops ) , GFP_KERNEL ) ;
2008-04-18 13:33:38 -07:00
ops - > lcread = fsl_local_config_read ;
ops - > lcwrite = fsl_local_config_write ;
ops - > cread = fsl_rio_config_read ;
ops - > cwrite = fsl_rio_config_write ;
ops - > dsend = fsl_rio_doorbell_send ;
2005-11-07 01:00:19 -08:00
2008-04-18 13:33:41 -07:00
port = kzalloc ( sizeof ( struct rio_mport ) , GFP_KERNEL ) ;
2005-11-07 01:00:19 -08:00
port - > id = 0 ;
port - > index = 0 ;
2008-04-18 13:33:41 -07:00
priv = kzalloc ( sizeof ( struct rio_priv ) , GFP_KERNEL ) ;
if ( ! priv ) {
printk ( KERN_ERR " Can't alloc memory for 'priv' \n " ) ;
rc = - ENOMEM ;
goto err ;
}
2005-11-07 01:00:19 -08:00
INIT_LIST_HEAD ( & port - > dbells ) ;
port - > iores . start = law_start ;
port - > iores . end = law_start + law_size ;
port - > iores . flags = IORESOURCE_MEM ;
rio_init_dbell_res ( & port - > riores [ RIO_DOORBELL_RESOURCE ] , 0 , 0xffff ) ;
rio_init_mbox_res ( & port - > riores [ RIO_INB_MBOX_RESOURCE ] , 0 , 0 ) ;
rio_init_mbox_res ( & port - > riores [ RIO_OUTB_MBOX_RESOURCE ] , 0 , 0 ) ;
strcpy ( port - > name , " RIO0 mport " ) ;
port - > ops = ops ;
2008-04-18 13:33:38 -07:00
port - > host_deviceid = fsl_rio_get_hdid ( port - > id ) ;
2005-11-07 01:00:19 -08:00
2008-04-18 13:33:41 -07:00
port - > priv = priv ;
2005-11-07 01:00:19 -08:00
rio_register_mport ( port ) ;
2008-04-18 13:33:41 -07:00
priv - > regs_win = ioremap ( RIO_REGS_BASE , 0x20000 ) ;
priv - > atmu_regs = ( struct rio_atmu_regs * ) ( priv - > regs_win
+ RIO_ATMU_REGS_OFFSET ) ;
priv - > maint_atmu_regs = priv - > atmu_regs + 1 ;
priv - > dbell_atmu_regs = priv - > atmu_regs + 2 ;
priv - > msg_regs = ( struct rio_msg_regs * ) ( priv - > regs_win
+ RIO_MSG_REGS_OFFSET ) ;
2005-11-07 01:00:19 -08:00
/* Configure maintenance transaction window */
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > maint_atmu_regs - > rowbar , 0x000c0000 ) ;
out_be32 ( & priv - > maint_atmu_regs - > rowar , 0x80077015 ) ;
2005-11-07 01:00:19 -08:00
2008-04-18 13:33:41 -07:00
priv - > maint_win = ioremap ( law_start , RIO_MAINT_WIN_SIZE ) ;
2005-11-07 01:00:19 -08:00
/* Configure outbound doorbell window */
2008-04-18 13:33:41 -07:00
out_be32 ( & priv - > dbell_atmu_regs - > rowbar , 0x000c0400 ) ;
out_be32 ( & priv - > dbell_atmu_regs - > rowar , 0x8004200b ) ;
2008-04-18 13:33:38 -07:00
fsl_rio_doorbell_init ( port ) ;
2008-04-18 13:33:41 -07:00
return ;
err :
if ( priv )
iounmap ( priv - > regs_win ) ;
kfree ( priv ) ;
kfree ( port ) ;
2005-11-07 01:00:19 -08:00
}