2009-05-22 11:04:53 +00:00
/*
* For License see notice in hfc_multi . c
*
* special IO and init functions for the embedded XHFC board
* from Speech Design
*
*/
# include <asm/8xx_immap.h>
/* Change this to the value used by your board */
# ifndef IMAP_ADDR
# define IMAP_ADDR 0xFFF00000
# endif
static void
# ifdef HFC_REGISTER_DEBUG
HFC_outb_embsd ( struct hfc_multi * hc , u_char reg , u_char val ,
2012-02-19 19:52:38 -08:00
const char * function , int line )
2009-05-22 11:04:53 +00:00
# else
2012-02-19 19:52:38 -08:00
HFC_outb_embsd ( struct hfc_multi * hc , u_char reg , u_char val )
2009-05-22 11:04:53 +00:00
# endif
{
hc - > immap - > im_ioport . iop_padat | = PA_XHFC_A0 ;
writeb ( reg , hc - > xhfc_memaddr ) ;
hc - > immap - > im_ioport . iop_padat & = ~ ( PA_XHFC_A0 ) ;
writeb ( val , hc - > xhfc_memdata ) ;
}
static u_char
# ifdef HFC_REGISTER_DEBUG
HFC_inb_embsd ( struct hfc_multi * hc , u_char reg , const char * function , int line )
# else
2012-02-19 19:52:38 -08:00
HFC_inb_embsd ( struct hfc_multi * hc , u_char reg )
2009-05-22 11:04:53 +00:00
# endif
{
hc - > immap - > im_ioport . iop_padat | = PA_XHFC_A0 ;
writeb ( reg , hc - > xhfc_memaddr ) ;
hc - > immap - > im_ioport . iop_padat & = ~ ( PA_XHFC_A0 ) ;
return readb ( hc - > xhfc_memdata ) ;
}
static u_short
# ifdef HFC_REGISTER_DEBUG
HFC_inw_embsd ( struct hfc_multi * hc , u_char reg , const char * function , int line )
# else
2012-02-19 19:52:38 -08:00
HFC_inw_embsd ( struct hfc_multi * hc , u_char reg )
2009-05-22 11:04:53 +00:00
# endif
{
hc - > immap - > im_ioport . iop_padat | = PA_XHFC_A0 ;
writeb ( reg , hc - > xhfc_memaddr ) ;
hc - > immap - > im_ioport . iop_padat & = ~ ( PA_XHFC_A0 ) ;
return readb ( hc - > xhfc_memdata ) ;
}
static void
# ifdef HFC_REGISTER_DEBUG
HFC_wait_embsd ( struct hfc_multi * hc , const char * function , int line )
# else
2012-02-19 19:52:38 -08:00
HFC_wait_embsd ( struct hfc_multi * hc )
2009-05-22 11:04:53 +00:00
# endif
{
hc - > immap - > im_ioport . iop_padat | = PA_XHFC_A0 ;
writeb ( R_STATUS , hc - > xhfc_memaddr ) ;
hc - > immap - > im_ioport . iop_padat & = ~ ( PA_XHFC_A0 ) ;
while ( readb ( hc - > xhfc_memdata ) & V_BUSY )
cpu_relax ( ) ;
}
/* write fifo data (EMBSD) */
void
write_fifo_embsd ( struct hfc_multi * hc , u_char * data , int len )
{
hc - > immap - > im_ioport . iop_padat | = PA_XHFC_A0 ;
* hc - > xhfc_memaddr = A_FIFO_DATA0 ;
hc - > immap - > im_ioport . iop_padat & = ~ ( PA_XHFC_A0 ) ;
while ( len ) {
* hc - > xhfc_memdata = * data ;
data + + ;
len - - ;
}
}
/* read fifo data (EMBSD) */
void
read_fifo_embsd ( struct hfc_multi * hc , u_char * data , int len )
{
hc - > immap - > im_ioport . iop_padat | = PA_XHFC_A0 ;
* hc - > xhfc_memaddr = A_FIFO_DATA0 ;
hc - > immap - > im_ioport . iop_padat & = ~ ( PA_XHFC_A0 ) ;
while ( len ) {
* data = ( u_char ) ( * hc - > xhfc_memdata ) ;
data + + ;
len - - ;
}
}
static int
setup_embedded ( struct hfc_multi * hc , struct hm_map * m )
{
printk ( KERN_INFO
2012-02-19 19:52:38 -08:00
" HFC-multi: card manufacturer: '%s' card name: '%s' clock: %s \n " ,
m - > vendor_name , m - > card_name , m - > clock2 ? " double " : " normal " ) ;
2009-05-22 11:04:53 +00:00
hc - > pci_dev = NULL ;
if ( m - > clock2 )
test_and_set_bit ( HFC_CHIP_CLOCK2 , & hc - > chip ) ;
hc - > leds = m - > leds ;
hc - > ledstate = 0xAFFEAFFE ;
hc - > opticalsupport = m - > opticalsupport ;
hc - > pci_iobase = 0 ;
hc - > pci_membase = 0 ;
hc - > xhfc_membase = NULL ;
hc - > xhfc_memaddr = NULL ;
hc - > xhfc_memdata = NULL ;
/* set memory access methods */
if ( m - > io_mode ) /* use mode from card config */
hc - > io_mode = m - > io_mode ;
switch ( hc - > io_mode ) {
case HFC_IO_MODE_EMBSD :
test_and_set_bit ( HFC_CHIP_EMBSD , & hc - > chip ) ;
hc - > slots = 128 ; /* required */
/* fall through */
hc - > HFC_outb = HFC_outb_embsd ;
hc - > HFC_inb = HFC_inb_embsd ;
hc - > HFC_inw = HFC_inw_embsd ;
hc - > HFC_wait = HFC_wait_embsd ;
hc - > read_fifo = read_fifo_embsd ;
hc - > write_fifo = write_fifo_embsd ;
hc - > xhfc_origmembase = XHFC_MEMBASE + XHFC_OFFSET * hc - > id ;
hc - > xhfc_membase = ( u_char * ) ioremap ( hc - > xhfc_origmembase ,
2012-02-19 19:52:38 -08:00
XHFC_MEMSIZE ) ;
2009-05-22 11:04:53 +00:00
if ( ! hc - > xhfc_membase ) {
printk ( KERN_WARNING
2012-02-19 19:52:38 -08:00
" HFC-multi: failed to remap xhfc address space. "
" (internal error) \n " ) ;
2009-05-22 11:04:53 +00:00
return - EIO ;
}
hc - > xhfc_memaddr = ( u_long * ) ( hc - > xhfc_membase + 4 ) ;
hc - > xhfc_memdata = ( u_long * ) ( hc - > xhfc_membase ) ;
printk ( KERN_INFO
2012-02-19 19:52:38 -08:00
" HFC-multi: xhfc_membase:%#lx xhfc_origmembase:%#lx "
" xhfc_memaddr:%#lx xhfc_memdata:%#lx \n " ,
( u_long ) hc - > xhfc_membase , hc - > xhfc_origmembase ,
( u_long ) hc - > xhfc_memaddr , ( u_long ) hc - > xhfc_memdata ) ;
2009-05-22 11:04:53 +00:00
break ;
default :
printk ( KERN_WARNING " HFC-multi: Invalid IO mode. \n " ) ;
return - EIO ;
}
/* Prepare the MPC8XX PortA 10 as output (address/data selector) */
hc - > immap = ( struct immap * ) ( IMAP_ADDR ) ;
hc - > immap - > im_ioport . iop_papar & = ~ ( PA_XHFC_A0 ) ;
hc - > immap - > im_ioport . iop_paodr & = ~ ( PA_XHFC_A0 ) ;
hc - > immap - > im_ioport . iop_padir | = PA_XHFC_A0 ;
/* Prepare the MPC8xx PortB __X__ as input (ISDN__X__IRQ) */
hc - > pb_irqmsk = ( PB_XHFC_IRQ1 < < hc - > id ) ;
hc - > immap - > im_cpm . cp_pbpar & = ~ ( hc - > pb_irqmsk ) ;
hc - > immap - > im_cpm . cp_pbodr & = ~ ( hc - > pb_irqmsk ) ;
hc - > immap - > im_cpm . cp_pbdir & = ~ ( hc - > pb_irqmsk ) ;
/* At this point the needed config is done */
/* fifos are still not enabled */
return 0 ;
}