forked from Miroirs/x49gp
641 lines
19 KiB
C
641 lines
19 KiB
C
/* $Id: s3c2410_io_port.c,v 1.14 2008/12/11 12:18:17 ecd Exp $
|
|
*/
|
|
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
|
|
#include "x49gp.h"
|
|
#include "s3c2410.h"
|
|
#include "s3c2410_intc.h"
|
|
|
|
typedef struct {
|
|
uint32_t gpacon;
|
|
uint32_t gpadat;
|
|
|
|
uint32_t gpbcon;
|
|
uint32_t gpbdat;
|
|
uint32_t gpbup;
|
|
|
|
uint32_t gpccon;
|
|
uint32_t gpcdat;
|
|
uint32_t gpcup;
|
|
|
|
uint32_t gpdcon;
|
|
uint32_t gpddat;
|
|
uint32_t gpdup;
|
|
|
|
uint32_t gpecon;
|
|
uint32_t gpedat;
|
|
uint32_t gpeup;
|
|
|
|
uint32_t gpfcon;
|
|
uint32_t gpfdat;
|
|
uint32_t gpfup;
|
|
|
|
uint32_t gpgcon;
|
|
uint32_t gpgdat;
|
|
uint32_t gpgup;
|
|
|
|
uint32_t gphcon;
|
|
uint32_t gphdat;
|
|
uint32_t gphup;
|
|
|
|
uint32_t misccr;
|
|
uint32_t dclkcon;
|
|
|
|
uint32_t extint0;
|
|
uint32_t extint1;
|
|
uint32_t extint2;
|
|
uint32_t eintflt0;
|
|
uint32_t eintflt1;
|
|
uint32_t eintflt2;
|
|
uint32_t eintflt3;
|
|
uint32_t eintmask;
|
|
uint32_t eintpend;
|
|
|
|
uint32_t gstatus0;
|
|
uint32_t gstatus1;
|
|
uint32_t gstatus2;
|
|
uint32_t gstatus3;
|
|
uint32_t gstatus4;
|
|
|
|
unsigned int nr_regs;
|
|
s3c2410_offset_t* regs;
|
|
|
|
x49gp_t* x49gp;
|
|
} s3c2410_io_port_t;
|
|
|
|
static int s3c2410_io_port_data_init( s3c2410_io_port_t* io )
|
|
{
|
|
s3c2410_offset_t regs[] = {
|
|
S3C2410_OFFSET( IO_PORT, GPACON, 0x007fffff, io->gpacon ), S3C2410_OFFSET( IO_PORT, GPADAT, 0x00000000, io->gpadat ),
|
|
|
|
S3C2410_OFFSET( IO_PORT, GPBCON, 0x00000000, io->gpbcon ), S3C2410_OFFSET( IO_PORT, GPBDAT, 0x00000000, io->gpbdat ),
|
|
S3C2410_OFFSET( IO_PORT, GPBUP, 0x00000000, io->gpbup ),
|
|
|
|
S3C2410_OFFSET( IO_PORT, GPCCON, 0x00000000, io->gpccon ), S3C2410_OFFSET( IO_PORT, GPCDAT, 0x00000000, io->gpcdat ),
|
|
S3C2410_OFFSET( IO_PORT, GPCUP, 0x00000000, io->gpcup ),
|
|
|
|
S3C2410_OFFSET( IO_PORT, GPDCON, 0x00000000, io->gpdcon ), S3C2410_OFFSET( IO_PORT, GPDDAT, 0x0000038c, io->gpddat ),
|
|
S3C2410_OFFSET( IO_PORT, GPDUP, 0x0000f000, io->gpdup ),
|
|
|
|
S3C2410_OFFSET( IO_PORT, GPECON, 0x00000000, io->gpecon ), S3C2410_OFFSET( IO_PORT, GPEDAT, 0x0000c7c0, io->gpedat ),
|
|
S3C2410_OFFSET( IO_PORT, GPEUP, 0x00000000, io->gpeup ),
|
|
|
|
S3C2410_OFFSET( IO_PORT, GPFCON, 0x00000000, io->gpfcon ), S3C2410_OFFSET( IO_PORT, GPFDAT, 0x00000008, io->gpfdat ),
|
|
S3C2410_OFFSET( IO_PORT, GPFUP, 0x00000000, io->gpfup ),
|
|
|
|
S3C2410_OFFSET( IO_PORT, GPGCON, 0x00000000, io->gpgcon ), S3C2410_OFFSET( IO_PORT, GPGDAT, 0x0000fffe, io->gpgdat ),
|
|
S3C2410_OFFSET( IO_PORT, GPGUP, 0x0000f800, io->gpgup ),
|
|
|
|
S3C2410_OFFSET( IO_PORT, GPHCON, 0x00000000, io->gphcon ), S3C2410_OFFSET( IO_PORT, GPHDAT, 0x00000000, io->gphdat ),
|
|
S3C2410_OFFSET( IO_PORT, GPHUP, 0x00000000, io->gphup ),
|
|
|
|
S3C2410_OFFSET( IO_PORT, MISCCR, 0x00010330, io->misccr ), S3C2410_OFFSET( IO_PORT, DCLKCON, 0x00000000, io->dclkcon ),
|
|
|
|
S3C2410_OFFSET( IO_PORT, EXTINT0, 0x00000000, io->extint0 ), S3C2410_OFFSET( IO_PORT, EXTINT1, 0x00000000, io->extint1 ),
|
|
S3C2410_OFFSET( IO_PORT, EXTINT2, 0x00000000, io->extint2 ), S3C2410_OFFSET( IO_PORT, EINTFLT0, 0x00000000, io->eintflt0 ),
|
|
S3C2410_OFFSET( IO_PORT, EINTFLT1, 0x00000000, io->eintflt1 ), S3C2410_OFFSET( IO_PORT, EINTFLT2, 0x00000000, io->eintflt2 ),
|
|
S3C2410_OFFSET( IO_PORT, EINTFLT3, 0x00000000, io->eintflt3 ), S3C2410_OFFSET( IO_PORT, EINTMASK, 0x00fffff0, io->eintmask ),
|
|
S3C2410_OFFSET( IO_PORT, EINTPEND, 0x00000000, io->eintpend ),
|
|
|
|
S3C2410_OFFSET( IO_PORT, GSTATUS0, 0x00000001, io->gstatus0 ), S3C2410_OFFSET( IO_PORT, GSTATUS1, 0x32410002, io->gstatus1 ),
|
|
S3C2410_OFFSET( IO_PORT, GSTATUS2, 0x00000001, io->gstatus2 ), S3C2410_OFFSET( IO_PORT, GSTATUS3, 0x00000000, io->gstatus3 ),
|
|
S3C2410_OFFSET( IO_PORT, GSTATUS4, 0x00000000, io->gstatus4 ) };
|
|
|
|
memset( io, 0, sizeof( s3c2410_io_port_t ) );
|
|
|
|
io->regs = malloc( sizeof( regs ) );
|
|
if ( NULL == io->regs ) {
|
|
fprintf( stderr, "%s:%u: Out of memory\n", __FUNCTION__, __LINE__ );
|
|
return -ENOMEM;
|
|
}
|
|
|
|
memcpy( io->regs, regs, sizeof( regs ) );
|
|
io->nr_regs = sizeof( regs ) / sizeof( regs[ 0 ] );
|
|
|
|
return 0;
|
|
}
|
|
|
|
static uint32_t s3c2410_scan_keys( x49gp_t* x49gp, uint32_t gpgcon, uint32_t gpgdat )
|
|
{
|
|
uint32_t result;
|
|
int col, row;
|
|
|
|
result = 0xfffe | ( gpgdat & 1 );
|
|
|
|
for ( col = 0; col < 8; col++ ) {
|
|
switch ( ( gpgcon >> ( 2 * ( col + 8 ) ) ) & 3 ) {
|
|
case 0: /* Input */
|
|
case 2: /* Interrupt */
|
|
case 3: /* Reserved */
|
|
break;
|
|
case 1: /* Output */
|
|
result &= ~( 1 << ( col + 8 ) );
|
|
result |= gpgdat & ( 1 << ( col + 8 ) );
|
|
|
|
if ( 0 == ( gpgdat & ( 1 << ( col + 8 ) ) ) ) {
|
|
result &= ~( x49gp->keybycol[ col ] );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
for ( row = 1; row < 8; row++ ) {
|
|
switch ( ( gpgcon >> ( 2 * row ) ) & 3 ) {
|
|
case 0: /* Input */
|
|
case 2: /* Interrupt */
|
|
case 3: /* Reserved */
|
|
break;
|
|
case 1: /* Output */
|
|
result &= ~( 1 << row );
|
|
result |= gpgdat & ( 1 << row );
|
|
|
|
if ( 0 == ( gpgdat & ( 1 << row ) ) ) {
|
|
result &= ~( x49gp->keybyrow[ row ] << 8 );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static uint32_t s3c2410_io_port_read( void* opaque, target_phys_addr_t offset )
|
|
{
|
|
s3c2410_io_port_t* io = opaque;
|
|
s3c2410_offset_t* reg;
|
|
|
|
if ( !S3C2410_OFFSET_OK( io, offset ) ) {
|
|
fprintf( stderr, "%s:%u: offset %08lx not OK\n", __FUNCTION__, __LINE__, ( unsigned long )offset );
|
|
abort();
|
|
return ~( 0 );
|
|
}
|
|
|
|
reg = S3C2410_OFFSET_ENTRY( io, offset );
|
|
|
|
switch ( offset ) {
|
|
case S3C2410_IO_PORT_MISCCR:
|
|
// if (io->x49gp->arm->NresetSig != LOW) {
|
|
*( reg->datap ) |= 0x00010000;
|
|
// }
|
|
break;
|
|
|
|
case S3C2410_IO_PORT_GPCDAT:
|
|
if ( 0 == ( ( io->gpccon >> 30 ) & 3 ) ) {
|
|
*( reg->datap ) |= 0x8000;
|
|
}
|
|
if ( 0 == ( ( io->gpccon >> 28 ) & 3 ) ) {
|
|
*( reg->datap ) |= 0x4000;
|
|
}
|
|
if ( 0 == ( ( io->gpccon >> 26 ) & 3 ) ) {
|
|
*( reg->datap ) |= 0x2000;
|
|
}
|
|
if ( 0 == ( ( io->gpccon >> 24 ) & 3 ) ) {
|
|
*( reg->datap ) |= 0x1000;
|
|
}
|
|
break;
|
|
|
|
case S3C2410_IO_PORT_GPDDAT:
|
|
if ( 0 == ( ( io->gpdcon >> 6 ) & 3 ) ) {
|
|
*( reg->datap ) |= 0x0008;
|
|
}
|
|
break;
|
|
|
|
case S3C2410_IO_PORT_GPEDAT:
|
|
if ( 0 == ( ( io->gpecon >> 30 ) & 3 ) ) {
|
|
*( reg->datap ) |= 0x8000;
|
|
}
|
|
if ( 0 == ( ( io->gpecon >> 28 ) & 3 ) ) {
|
|
*( reg->datap ) |= 0x4000;
|
|
}
|
|
break;
|
|
|
|
case S3C2410_IO_PORT_GPFDAT:
|
|
#if 1
|
|
if ( 1 != ( ( io->gpfcon >> 6 ) & 3 ) ) {
|
|
*( reg->datap ) |= 0x0008;
|
|
}
|
|
#endif
|
|
break;
|
|
|
|
case S3C2410_IO_PORT_GPGDAT:
|
|
return s3c2410_scan_keys( io->x49gp, io->gpgcon, io->gpgdat );
|
|
|
|
case S3C2410_IO_PORT_GPHDAT:
|
|
if ( 0 == ( ( io->gphcon >> 14 ) & 3 ) ) {
|
|
*( reg->datap ) |= 0x80;
|
|
}
|
|
if ( 0 == ( ( io->gphcon >> 12 ) & 3 ) ) {
|
|
*( reg->datap ) &= ~( 0x40 );
|
|
}
|
|
break;
|
|
}
|
|
|
|
#ifdef DEBUG_S3C2410_IO_PORT
|
|
printf( "read %s [%08x] %s [%08lx] data %08x\n", "s3c2410-io-port", S3C2410_IO_PORT_BASE, reg->name, ( unsigned long )offset,
|
|
*( reg->datap ) );
|
|
#endif
|
|
|
|
return *( reg->datap );
|
|
}
|
|
|
|
static void s3c2410_io_port_write( void* opaque, target_phys_addr_t offset, uint32_t data )
|
|
{
|
|
s3c2410_io_port_t* io = opaque;
|
|
s3c2410_offset_t* reg;
|
|
uint32_t change;
|
|
static uint32_t lcd_data = 0;
|
|
|
|
if ( !S3C2410_OFFSET_OK( io, offset ) ) {
|
|
return;
|
|
}
|
|
|
|
reg = S3C2410_OFFSET_ENTRY( io, offset );
|
|
|
|
#ifdef DEBUG_S3C2410_IO_PORT
|
|
printf( "write %s [%08x] %s [%08lx] data %08x\n", "s3c2410-io-port", S3C2410_IO_PORT_BASE, reg->name, ( unsigned long )offset, data );
|
|
#endif
|
|
|
|
switch ( offset ) {
|
|
case S3C2410_IO_PORT_GPDDAT:
|
|
change = *( reg->datap ) ^ data;
|
|
*( reg->datap ) = data;
|
|
|
|
if ( !( data & 0x200 ) && ( change & 0x200 ) ) {
|
|
lcd_data = 0;
|
|
}
|
|
|
|
if ( !( data & 0x200 ) && ( data & 0x2000 ) && ( change & 0x2000 ) ) {
|
|
#ifdef DEBUG_S3C2410_IO_PORT
|
|
printf( "IO_PORT GPDDAT: clk0 rise: data %u\n", ( data >> 12 ) & 1 );
|
|
#endif
|
|
lcd_data <<= 1;
|
|
lcd_data |= ( data >> 12 ) & 1;
|
|
}
|
|
|
|
if ( ( data & 0x200 ) && ( change & 0x200 ) ) {
|
|
#ifdef DEBUG_S3C2410_IO_PORT
|
|
printf( "IO_PORT GPDDAT: cs0 rise: data %04x\n", lcd_data );
|
|
#endif
|
|
}
|
|
|
|
break;
|
|
|
|
case S3C2410_IO_PORT_MISCCR:
|
|
*( reg->datap ) = data;
|
|
if ( !( *( reg->datap ) & 0x00010000 ) ) {
|
|
*( reg->datap ) = 0x10330;
|
|
// if (io->x49gp->arm->NresetSig != LOW) {
|
|
// io->x49gp->arm->NresetSig = LOW;
|
|
// io->x49gp->arm->Exception++;
|
|
// }
|
|
}
|
|
break;
|
|
|
|
case S3C2410_IO_PORT_GSTATUS0:
|
|
case S3C2410_IO_PORT_GSTATUS1:
|
|
/* read only */
|
|
break;
|
|
|
|
case S3C2410_IO_PORT_GSTATUS2:
|
|
*( reg->datap ) &= ~( data & 7 );
|
|
break;
|
|
|
|
case S3C2410_IO_PORT_EINTPEND:
|
|
*( reg->datap ) &= ~( data );
|
|
|
|
if ( 0 == ( *( reg->datap ) & 0x000000f0 ) )
|
|
s3c2410_intc_deassert( io->x49gp, EINT4_7 );
|
|
if ( 0 == ( *( reg->datap ) & 0x00ffff00 ) )
|
|
s3c2410_intc_deassert( io->x49gp, EINT8_23 );
|
|
break;
|
|
|
|
default:
|
|
*( reg->datap ) = data;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void s3c2410_io_port_g_update( x49gp_t* x49gp, int column, int row, unsigned char columnbit, unsigned char rowbit, uint32_t new_state )
|
|
{
|
|
s3c2410_io_port_t* io = x49gp->s3c2410_io_port;
|
|
uint32_t oldvalue, newvalue, change;
|
|
int n;
|
|
|
|
oldvalue = s3c2410_scan_keys( x49gp, io->gpgcon, io->gpgdat );
|
|
|
|
if ( new_state ) {
|
|
x49gp->keybycol[ column ] |= rowbit;
|
|
x49gp->keybyrow[ row ] |= columnbit;
|
|
|
|
} else {
|
|
x49gp->keybycol[ column ] &= ~rowbit;
|
|
x49gp->keybyrow[ row ] &= ~columnbit;
|
|
}
|
|
|
|
newvalue = s3c2410_scan_keys( x49gp, io->gpgcon, io->gpgdat );
|
|
change = newvalue ^ oldvalue;
|
|
|
|
for ( n = 0; n < 15; ++n ) {
|
|
|
|
switch ( ( io->gpgcon >> ( 2 * n ) ) & 3 ) {
|
|
|
|
case 2: /* Interrupt */
|
|
{
|
|
switch ( n + 8 <= 15 ? ( io->extint1 >> ( 4 * n ) ) & 7 : // EINT 8-15
|
|
( io->extint2 >> ( 4 * ( n - 8 ) ) ) & 7 // EINT 16-23
|
|
) {
|
|
case 0: /* Low Level */
|
|
if ( !( newvalue & ( 1 << n ) ) ) {
|
|
io->eintpend |= 1 << ( n + 8 );
|
|
if ( io->eintpend & ~( io->eintmask ) )
|
|
s3c2410_intc_assert( x49gp, EINT8_23, 1 );
|
|
}
|
|
break;
|
|
case 1: /* High Level */
|
|
if ( newvalue & ( 1 << n ) ) {
|
|
io->eintpend |= 1 << ( n + 8 );
|
|
if ( io->eintpend & ~( io->eintmask ) )
|
|
s3c2410_intc_assert( x49gp, EINT8_23, 1 );
|
|
}
|
|
break;
|
|
case 2: /* Falling Edge */
|
|
case 3:
|
|
if ( ( change & ( 1 << n ) ) && !( newvalue & ( 1 << n ) ) ) {
|
|
io->eintpend |= 1 << ( n + 8 );
|
|
if ( io->eintpend & ~( io->eintmask ) )
|
|
s3c2410_intc_assert( x49gp, EINT8_23, 1 );
|
|
}
|
|
break;
|
|
case 4: /* Rising Edge */
|
|
case 5:
|
|
if ( ( change & ( 1 << n ) ) && ( newvalue & ( 1 << n ) ) ) {
|
|
io->eintpend |= 1 << ( n + 8 );
|
|
if ( io->eintpend & ~( io->eintmask ) )
|
|
s3c2410_intc_assert( x49gp, EINT8_23, 1 );
|
|
}
|
|
break;
|
|
case 6: /* Any Edge */
|
|
case 7:
|
|
if ( change & ( 1 << n ) ) {
|
|
io->eintpend |= 1 << ( n + 8 );
|
|
if ( io->eintpend & ~( io->eintmask ) )
|
|
s3c2410_intc_assert( x49gp, EINT8_23, 1 );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case 0: /* Input */
|
|
case 1: /* Output */
|
|
case 3: /* Reserved */
|
|
break;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void s3c2410_io_port_f_set_bit( x49gp_t* x49gp, int n, uint32_t value )
|
|
{
|
|
s3c2410_io_port_t* io = x49gp->s3c2410_io_port;
|
|
uint32_t change;
|
|
int pending, level;
|
|
|
|
if ( n > 7 )
|
|
return;
|
|
|
|
// g_mutex_lock(x49gp->memlock);
|
|
|
|
change = 0;
|
|
switch ( ( io->gpfcon >> ( 2 * n ) ) & 3 ) {
|
|
case 0: /* Input */
|
|
io->gpfdat &= ~( 1 << n );
|
|
io->gpfdat |= ( value << n );
|
|
goto out;
|
|
|
|
case 2: /* Interrupt */
|
|
change = io->gpfdat ^ ( value << n );
|
|
io->gpfdat &= ~( 1 << n );
|
|
io->gpfdat |= ( value << n );
|
|
break;
|
|
|
|
case 1: /* Output */
|
|
case 3: /* Reserved */
|
|
goto out;
|
|
}
|
|
|
|
pending = -1;
|
|
level = 0;
|
|
switch ( ( io->extint0 >> ( 4 * n ) ) & 7 ) {
|
|
case 0: /* Low Level */
|
|
if ( !( io->gpfdat & ( 1 << n ) ) )
|
|
pending = n;
|
|
level = 1;
|
|
break;
|
|
|
|
case 1: /* High Level */
|
|
if ( io->gpfdat & ( 1 << n ) )
|
|
pending = n;
|
|
level = 1;
|
|
break;
|
|
|
|
case 2: /* Falling Edge */
|
|
case 3:
|
|
if ( ( change & ( 1 << n ) ) && !( io->gpfdat & ( 1 << n ) ) )
|
|
pending = n;
|
|
break;
|
|
|
|
case 4: /* Rising Edge */
|
|
case 5:
|
|
if ( ( change & ( 1 << n ) ) && ( io->gpfdat & ( 1 << n ) ) )
|
|
pending = n;
|
|
break;
|
|
|
|
case 6: /* Any Edge */
|
|
case 7:
|
|
if ( change & ( 1 << n ) )
|
|
pending = n;
|
|
break;
|
|
}
|
|
|
|
if ( -1 == pending )
|
|
goto out;
|
|
|
|
switch ( n ) {
|
|
case 0:
|
|
s3c2410_intc_assert( x49gp, EINT0, level );
|
|
break;
|
|
case 1:
|
|
s3c2410_intc_assert( x49gp, EINT1, level );
|
|
break;
|
|
case 2:
|
|
s3c2410_intc_assert( x49gp, EINT2, level );
|
|
break;
|
|
case 3:
|
|
s3c2410_intc_assert( x49gp, EINT3, level );
|
|
break;
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
io->eintpend |= ( 1 << n );
|
|
if ( io->eintpend & ~( io->eintmask ) )
|
|
s3c2410_intc_assert( x49gp, EINT4_7, 1 );
|
|
break;
|
|
}
|
|
|
|
out:
|
|
// g_mutex_unlock(x49gp->memlock);
|
|
|
|
return;
|
|
}
|
|
|
|
static int s3c2410_io_port_load( x49gp_module_t* module, GKeyFile* key )
|
|
{
|
|
s3c2410_io_port_t* io = module->user_data;
|
|
s3c2410_offset_t* reg;
|
|
int error = 0;
|
|
int i;
|
|
|
|
#ifdef DEBUG_X49GP_MODULES
|
|
printf( "%s: %s:%u\n", module->name, __FUNCTION__, __LINE__ );
|
|
#endif
|
|
|
|
for ( i = 0; i < io->nr_regs; i++ ) {
|
|
reg = &io->regs[ i ];
|
|
|
|
if ( NULL == reg->name )
|
|
continue;
|
|
|
|
if ( x49gp_module_get_u32( module, key, reg->name, reg->reset, reg->datap ) )
|
|
error = -EAGAIN;
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
static int s3c2410_io_port_save( x49gp_module_t* module, GKeyFile* key )
|
|
{
|
|
s3c2410_io_port_t* io = module->user_data;
|
|
s3c2410_offset_t* reg;
|
|
int i;
|
|
|
|
#ifdef DEBUG_X49GP_MODULES
|
|
printf( "%s: %s:%u\n", module->name, __FUNCTION__, __LINE__ );
|
|
#endif
|
|
|
|
for ( i = 0; i < io->nr_regs; i++ ) {
|
|
reg = &io->regs[ i ];
|
|
|
|
if ( NULL == reg->name )
|
|
continue;
|
|
|
|
x49gp_module_set_u32( module, key, reg->name, *( reg->datap ) );
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int s3c2410_io_port_reset( x49gp_module_t* module, x49gp_reset_t reset )
|
|
{
|
|
s3c2410_io_port_t* io = module->user_data;
|
|
s3c2410_offset_t* reg;
|
|
int i;
|
|
|
|
#ifdef DEBUG_X49GP_MODULES
|
|
printf( "%s: %s:%u\n", module->name, __FUNCTION__, __LINE__ );
|
|
#endif
|
|
|
|
if ( reset == X49GP_RESET_POWER_OFF ) {
|
|
io->gstatus2 = 2;
|
|
return 0;
|
|
}
|
|
|
|
for ( i = 0; i < io->nr_regs; i++ ) {
|
|
reg = &io->regs[ i ];
|
|
|
|
if ( NULL == reg->name )
|
|
continue;
|
|
|
|
*( reg->datap ) = reg->reset;
|
|
}
|
|
|
|
if ( reset == X49GP_RESET_WATCHDOG ) {
|
|
io->gstatus2 = 4;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static CPUReadMemoryFunc* s3c2410_io_port_readfn[] = { s3c2410_io_port_read, s3c2410_io_port_read, s3c2410_io_port_read };
|
|
|
|
static CPUWriteMemoryFunc* s3c2410_io_port_writefn[] = { s3c2410_io_port_write, s3c2410_io_port_write, s3c2410_io_port_write };
|
|
|
|
static int s3c2410_io_port_init( x49gp_module_t* module )
|
|
{
|
|
s3c2410_io_port_t* io;
|
|
int iotype;
|
|
|
|
#ifdef DEBUG_X49GP_MODULES
|
|
printf( "%s: %s:%u\n", module->name, __FUNCTION__, __LINE__ );
|
|
#endif
|
|
|
|
io = malloc( sizeof( s3c2410_io_port_t ) );
|
|
if ( NULL == io ) {
|
|
fprintf( stderr, "%s:%u: Out of memory\n", __FUNCTION__, __LINE__ );
|
|
return -ENOMEM;
|
|
}
|
|
if ( s3c2410_io_port_data_init( io ) ) {
|
|
free( io );
|
|
return -ENOMEM;
|
|
}
|
|
|
|
module->user_data = io;
|
|
module->x49gp->s3c2410_io_port = io;
|
|
io->x49gp = module->x49gp;
|
|
|
|
iotype = cpu_register_io_memory( s3c2410_io_port_readfn, s3c2410_io_port_writefn, io );
|
|
#ifdef DEBUG_S3C2410_IO_PORT
|
|
printf( "%s: iotype %08x\n", __FUNCTION__, iotype );
|
|
#endif
|
|
cpu_register_physical_memory( S3C2410_IO_PORT_BASE, S3C2410_MAP_SIZE, iotype );
|
|
return 0;
|
|
}
|
|
|
|
static int s3c2410_io_port_exit( x49gp_module_t* module )
|
|
{
|
|
s3c2410_io_port_t* io;
|
|
|
|
#ifdef DEBUG_X49GP_MODULES
|
|
printf( "%s: %s:%u\n", module->name, __FUNCTION__, __LINE__ );
|
|
#endif
|
|
|
|
if ( module->user_data ) {
|
|
io = module->user_data;
|
|
if ( io->regs )
|
|
free( io->regs );
|
|
free( io );
|
|
}
|
|
|
|
x49gp_module_unregister( module );
|
|
free( module );
|
|
|
|
return 0;
|
|
}
|
|
|
|
int x49gp_s3c2410_io_port_init( x49gp_t* x49gp )
|
|
{
|
|
x49gp_module_t* module;
|
|
|
|
if ( x49gp_module_init( x49gp, "s3c2410-io-port", s3c2410_io_port_init, s3c2410_io_port_exit, s3c2410_io_port_reset,
|
|
s3c2410_io_port_load, s3c2410_io_port_save, NULL, &module ) ) {
|
|
return -1;
|
|
}
|
|
|
|
return x49gp_module_register( module );
|
|
}
|