Re: register tweaking module

Top Page
Attachments:
Message as email
+ (text/plain)
+ reg.c (text/plain)
+ all_registers (text/plain)
Delete this message
Reply to this message
Author: y.rutschle@indigovision.com
Date:  
To: Abraham vd Merwe
CC: Erik Mouw, ARM Linux Kernel List
Subject: Re: register tweaking module
On Fri, Feb 22, 2002 at 02:28:45PM -0000, Abraham vd Merwe
wrote:
> I still think the registers module is far more useful
> since it actually have names for the registers (otherwise
> you have to remember the damn offsets) - still I guess
> someone should rather write a userland utility...


Last time I talked about that, Nico pointed out that indeed
a userland utility would do just as well, so I wrote one,
then forgot about it... Here it is anyway.

Just put the reg binary in your path, put the register
description file in your home directory ($HOME/.registers)
or in your current directory (./registers, not hidden), then
everything can be accessed easily:

bash# reg MDCNFG
0x72447245

bash# reg MDCNFG 0x72557255

It supports "access methods", SA1110 registers are memory
mapped so it's method "mem", see the file for an example
using smbus (I2C subset). I2C is done through /dev/i2c-0, so
you need i2c-proc.o loaded... and I am not sure that program
is well designed for i2c in general, it just works on my
particular architecture (one bus).

Enjoy,
Y.


/*file header*****************************************************************\
**
** FILE NAME:   reg.c
**
** PROJECT:     Linux Utilities
**
** Provide access to hardware registers
**
** This program is based on devmem2.c (http://www.lart.tudelft.nl/)
**
*********************************************
**
** $Revision: 1.1 $
** $Modtime:: 24/04/01 15:47    $
** $Author: yves $
**
*********************************************
**
** PUBLIC FUNCTIONS DEFINED IN THIS FILE:
**      none
**
*********************************************
**
** CONTRIBUTORS:
**      YR      Yves Rutschle           <>
**
*******************************************************************************
**
** Copyright (c) 2002 IndigoVision Limited
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License version 2 as
** published by the Free Software Foundation.
**
** 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
**
\*****************************************************************************/


/********************************************
** INCLUDE FILES
*/

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <linux/i2c.h>
#include <linux/i2c-dev.h>

/********************************************
** PRIVATE DEFINES
*/

#define MAP_SIZE 4096
#define MAP_MASK ( MAP_SIZE - 1 )

#define LINE_LEN 160
#define PATH_MAX 4096

#define I2C_SUPPORT 0        /* unset to leave out I2C support */


/********************************************
** PRIVATE DATA TYPES
*/

/********************************************
** PRIVATE FUNCTION PROTOTYPES
*/

/********************************************
** PUBLIC DATA
*/

/********************************************
** PRIVATE DATA
*/

/*function header*************************************************************\
**
** FUNCTION NAME:   MemAccess
**
** Does an access through /dev/mem
**
** ARGUMENTS:
**      szArgs          String containing the register address
**      cSize           Size of the register ( b, h, w )
**      pVal            NULL for read, pointer to value for write
**
** RETURNS:
**      (void)
**
\*****************************************************************************/
void MemAccess( char* szArgs, char cSize, unsigned int *pVal )
{
    void *pMap, *pRegAddr;
    int fd, nAddr;


    fd = open( "/dev/mem", O_RDWR | O_SYNC );
    if ( fd < 0 )
    {
        perror( "/dev/mem" );
        exit( 1 );
    }


    nAddr = strtoul( szArgs, NULL, 0 );


    pMap = mmap( 
            0, 
            MAP_SIZE, 
            PROT_READ | PROT_WRITE, 
            MAP_SHARED, 
            fd, 
            nAddr & ~MAP_MASK 
            );
    if ( pMap == (void*)-1 )
    {
        perror( "mmap()" );
        exit( 1 );
    }


    pRegAddr = pMap + ( nAddr & MAP_MASK );


    if ( pVal )
        switch ( cSize )
        {
            case 'b': *( unsigned char* ) pRegAddr = *pVal;
                      break;
            case 'h': *( unsigned short* ) pRegAddr = *pVal;
                      break;
            case 'w': *( unsigned int* ) pRegAddr = *pVal;
                      break;
        }
    else
        switch( cSize )
        {
            case 'b': printf( "0x%02X\n", *( unsigned char* ) pRegAddr );
                      break;
            case 'h': printf( "0x%04X\n", *( unsigned short* ) pRegAddr );
                      break;
            case 'w': printf( "0x%08X\n", *( unsigned int* ) pRegAddr );
                      break;
        }


}

/*function header*************************************************************\
**
** FUNCTION NAME:   SMBusAccess
**
** Does a register access through /dev/i2c-0
**
** ARGUMENTS:
**      szArgs          String containing the register address
**      cSize           Size of the register ( b, h, w )
**      pVal            NULL for read, pointer to value for write
**
** RETURNS:
**      (void)
**
\*****************************************************************************/
#if I2C_SUPPORT
void SMBusAccess( void* szArgs, char cSize, unsigned int *pVal )
{
    unsigned int nDevAddr, nRegNum;
    int hI2C, res=0;
    char szDevName[ 20 ];


    sprintf( szDevName, "/dev/i2c-0" );


    if ( ( hI2C = open( szDevName, O_RDWR ) ) < 0 )
    {
        perror( "/dev/i2c-0" );
        fprintf( stderr, "(Did you load i2c-dev.o?)\n" );
        exit( 1 );
    }


    sscanf( szArgs, "%i %i", &nDevAddr, &nRegNum );


    if ( ioctl( hI2C, I2C_SLAVE, nDevAddr ) < 0 )
    {
        perror( "I2C address setting" );
        fprintf( stderr, "(Maybe a driver already uses that address?)\n" );
        exit( 1 );
    }


    if ( pVal )
    {
        switch ( cSize )
        {
            case 'b': res = i2c_smbus_write_byte_data( hI2C, nRegNum,  *pVal );
                      break;
            case 'h':
            case 'w': res = i2c_smbus_write_word_data( hI2C, nRegNum,  *pVal );
                      break;
        }
        if ( res == -1 )
        {
            perror( "smbus write failed" );
            exit( 1 );
        }
    }
    else
    {
        switch ( cSize )
        {
            case 'b': res = i2c_smbus_read_byte_data( hI2C, nRegNum );
                      if ( res == -1 ) break;
                      printf( "0x%02X\n", res );
                      break;
            case 'h':
            case 'w': res = i2c_smbus_read_word_data( hI2C, nRegNum );
                      if ( res == -1 ) break;
                      printf( "0x%04X\n", res );
                      break;
        }
        if ( res == -1 )
            perror( "smbus read failed" );
        exit( 1 );
    }
}
#endif /* I2C_SUPPORT */


/*function header*************************************************************\
**
** FUNCTION NAME:   main
**
**
**
** ARGUMENTS:
**      standard arguments
**
** RETURNS:
**      error level
**
\*****************************************************************************/
int main( int nArg, char * aszArg[] )
{
    FILE *hRegFile;
    char *szRegName, *szReg, *szAccess, cSize, szAddrArg[50];
    char szPath[PATH_MAX];
    char szBuffer[LINE_LEN];
    unsigned int nVal, *pVal;


    if ( nArg < 2 )
    {
        fprintf( stderr, "\nUsage:\t%s <reg_name> [value]\n\n\n", aszArg[ 0 ] );
        exit( 1 );
    }


    szRegName = aszArg[ 1 ];


    /* Look for description file in current directory */
    hRegFile = fopen( "registers", "r" );


    /* If none, try in the home directory */
    if ( ! hRegFile )
    {
        strcpy( szPath, getenv( "HOME" ) );
        strcat( szPath, "/.registers" );
        hRegFile = fopen( szPath, "r" );
    }
    if ( !hRegFile )
    {
        perror( "Unable to open description file" );
        exit( 1 );
    }


    /* Search for the register entry */
    while ( fgets( szBuffer, LINE_LEN, hRegFile ) )
    {
        if ( szBuffer[0] == '#' ) continue;


        sscanf( 
                szBuffer,
                "%as %as %c %50[0-9xa-fA-F ]", 
                &szReg, 
                &szAccess, 
                &cSize,
                szAddrArg
              );
        if ( strcmp( szRegName, szReg ) == 0 )
            goto found;
    }
    fprintf( stderr, "Register %s is unknown\n", szRegName );
    exit( 1 );


found:
    if ( nArg == 3 )
    {
        nVal = strtoul( aszArg[ 2 ], NULL, 0 );
        pVal = &nVal;
    }
    else
        pVal = NULL;


    /* Dispatch to appropriate access method */
    if ( strcmp( szAccess, "mem" ) == 0 )
        MemAccess( szAddrArg, cSize, pVal );
#if I2C_SUPPORT
    else if ( strcmp( szAccess, "smbus" ) == 0 )
        SMBusAccess( szAddrArg, cSize, pVal );
#endif
    else 
        fprintf( stderr, "Access method %s is not supported\n", szAccess );


    return 0;


}

/******************************* END OF FILE *******************************/
# SA1110 Registers
# Name    method size  addr
UDCCR      mem   w   0x80000000  # UDC control register
UDCAR      mem   w   0x80000004  # UDC address register
UDCOMP     mem   w   0x80000008  # UDC OUT max packet register
UDCIMP     mem   w   0x8000000C  # UDC IN max packet register
UDCCS0     mem   w   0x80000010  # UDC endpoint 0 control/status register
UDCCS1     mem   w   0x80000014  # UDC endpoint 1 (out) control/status register
UDCCS2     mem   w   0x80000018  # UDC endpoint 2 (in) control/status register
UDCD0      mem   w   0x8000001C  # UDC endpoint 0 data register
UDCWC      mem   w   0x80000020  # UDC endpoint 0 write count register
UDCDR      mem   w   0x80000028  # UDC transmit/receive data register (FIFOs)
UDCSR      mem   w   0x80000030  # UDC status/interrupt register
Ser1UTCR0  mem   w   0x80010000  # UART control register 0
Ser1UTCR1  mem   w   0x80010004  # UART control register 1
Ser1UTCR2  mem   w   0x80010008  # UART control register 2
Ser1UTCR3  mem   w   0x8001000C  # UART control register 3
Ser1UTDR   mem   w   0x80010014  # UART data register
Ser1UTSR0  mem   w   0x8001001C  # UART status register 0
Ser1UTSR1  mem   w   0x80010020  # UART status register 1
GPCLKR0    mem   w   0x80020060  # GPCLK Control Register 0
GPCLKR1    mem   w   0x80020064  # GPCLK Control Register 1
GPCLKR2    mem   w   0x8002006C  # GPCLK Control Register 2
GPCLKR3    mem   w   0x80020070  # GPCLK Control Register 3
Ser2UTCR0  mem   w   0x80030000  # UART control register 0
Ser2UTCR1  mem   w   0x80030004  # UART control register 1
Ser2UTCR2  mem   w   0x80030008  # UART control register 2
Ser2UTCR3  mem   w   0x8003000C  # UART control register 3
Ser2UTCR4  mem   w   0x80030010  # UART control register 4
Ser2UTDR   mem   w   0x80030014  # UART data register
Ser2UTSR0  mem   w   0x8003001C  # UART status register 0
Ser2UTSR1  mem   w   0x80030020  # UART status register 1
HSCR0      mem   w   0x80040060  # HSSP control register 0
HSCR1      mem   w   0x80040064  # HSSP control register 1
HSDR       mem   w   0x8004006C  # HSSP data register
HSSR0      mem   w   0x80040074  # HSSP status register 0
HSSR1      mem   w   0x80040078  # HSSP status register 1
Ser3UTCR0  mem   w   0x80050000  # UART control register 0
Ser3UTCR1  mem   w   0x80050004  # UART control register 1
Ser3UTCR2  mem   w   0x80050008  # UART control register 2
Ser3UTCR3  mem   w   0x8005000C  # UART control register 3
Ser3UTDR   mem   w   0x80050014  # UART data register
Ser3UTSR0  mem   w   0x8005001C  # UART status register 0
Ser3UTSR1  mem   w   0x80050020  # UART status register 1
MCCR0      mem   w   0x80060000  # MCP control register 0
MCDR0      mem   w   0x80060008  # MCP data register 0
MCDR1      mem   w   0x8006000C  # MCP data register 1
MCDR2      mem   w   0x80060010  # MCP data register 2
MCSR       mem   w   0x80060018  # MCP status register
SSCR0      mem   w   0x80070060  # SSP control register 0
SSCR1      mem   w   0x80070064  # SSP control register 1
SSDR       mem   w   0x8007006C  # SSP data register
SSSR       mem   w   0x80070074  # SSP status register
OSMR0      mem   w   0x90000000  # OS timer match registers 0
OSMR1      mem   w   0x90000004  # OS timer match registers 1
OSMR2      mem   w   0x90000008  # OS timer match registers 2
OSMR3      mem   w   0x9000000C  # OS timer match registers 3
OSCR       mem   w   0x90000010  # OS timer counter register
OSSR       mem   w   0x90000014  # OS timer status register
OWER       mem   w   0x90000018  # OS timer watchdog enable register
OIER       mem   w   0x9000001C  # OS timer interrupt enable register
RTAR       mem   w   0x90010000  # Real-time clock alarm register
RCNR       mem   w   0x90010004  # Real-time clock count register
RTTR       mem   w   0x90010008  # Real-time clock trim register
RTSR       mem   w   0x90010010  # Real-time clock status register
PMCR       mem   w   0x90020000  # Power manager control register
PSSR       mem   w   0x90020004  # Power manager sleep status register
PSPR       mem   w   0x90020008  # Power manager scratchpad register
PWER       mem   w   0x9002000C  # Power manager wakeup enable register
PCFR       mem   w   0x90020010  # Power manager configuration register
PPCR       mem   w   0x90020014  # Power manager PLL configuration register
PGSR       mem   w   0x90020018  # Power manager GPIO sleep state register
POSR       mem   w   0x9002001C  # Power manager oscillator status register
RSRR       mem   w   0x90030000  # Reset controller software reset register
RCSR       mem   w   0x90030004  # Reset controller status register
TUCR       mem   w   0x90030008  # Reserved for test
GPLR       mem   w   0x90040000  # GPIO pin level register
GPDR       mem   w   0x90040004  # GPIO pin direction register
GPSR       mem   w   0x90040008  # GPIO pin output set register
GPCR       mem   w   0x9004000C  # GPIO pin output clear register
GRER       mem   w   0x90040010  # GPIO rising-edge register
GFER       mem   w   0x90040014  # GPIO falling-edge register
GEDR       mem   w   0x90040018  # GPIO edge detect status register
GAFR       mem   w   0x9004001C  # GPIO alternate function register
ICIP       mem   w   0x90050000  # Interrupt controller irq pending register
ICMR       mem   w   0x90050004  # Interrupt controller mask register
ICLR       mem   w   0x90050008  # Interrupt controller FIQ level register
ICCR       mem   w   0x9005000C  # Interrupt controller control register
ICFP       mem   w   0x90050010  # Interrupt controller FIQ pending register
ICPR       mem   w   0x90050020  # Interrupt controller pending register
PPDR       mem   w   0x90060000  # PPC pin direction register
PPSR       mem   w   0x90060004  # PPC pin state register
PPAR       mem   w   0x90060008  # PPC pin assignment register
PSDR       mem   w   0x9006000C  # PPC sleep mode direction register
PPFR       mem   w   0x90060010  # PPC pin flag register
HSCR2      mem   w   0x90060028  # HSSP control register 2
MCCR1      mem   w   0x90060030  # MCP control register 1
MDCNFG     mem   w   0xA0000000  # DRAM configuration register
MDCAS00    mem   w   0xA0000004  # DRAM CAS waveform rotate register 0 for DRAM bank pair 0/1
MDCAS01    mem   w   0xA0000008  # DRAM CAS waveform rotate register 1 for DRAM bank pair 0/1
MDCAS02    mem   w   0xA000000C  # DRAM CAS waveform rotate register 2 for DRAM bank pair 0/1
MSC0       mem   w   0xA0000010  # Static memory control register 0
MSC1       mem   w   0xA0000014  # Static memory control register 1
MECR       mem   w   0xA0000018  # Expansion bus configuration register
MDREFR     mem   w   0xA000001C  # DRAM refresh control register
MDCAS20    mem   w   0xA0000020  # DRAM CAS waveform rotate register 0 for DRAM bank pair 2/3
MDCAS21    mem   w   0xA0000024  # DRAM CAS waveform rotate register 1 for DRAM bank pair 2/3
MDCAS22    mem   w   0xA0000028  # DRAM CAS waveform rotate register 2 for DRAM bank pair 2/3
MSC2       mem   w   0xA000002C  # Static memory control register 2
SMCNFG     mem   w   0xA0000030  # SMROM configuration register
DDAR0      mem   w   0xB0000000  # DMA device address register
SetDCSR0           mem   w   0xB0000004  # DMA control/status register 0 - write ones to set
ClrDCSR0           mem   w   0xB0000008  # DMA control/status register 0 - write ones to clear
RdDCSR0    mem   w   0xB000000C  # DMA control/status register 0 - read only
DBSA0      mem   w   0xB0000010  # DMA buffer A start address 0
DBTA0      mem   w   0xB0000014  # DMA buffer A transfer count 0
DBSB0      mem   w   0xB0000018  # DMA buffer B start address 0
DBTB0      mem   w   0xB000001C  # DMA buffer B transfer count 0
DDAR1      mem   w   0xB0000020  # DMA device address register 1
SetDCSR1   mem   w   0xB0000024  # DMA control/status register 1 - write ones to set
ClrDCSR1   mem   w   0xB0000028  # DMA control/status register 1 - write ones to clear
RdDCSR1    mem   w   0xB000002C  # DMA control/status register 1 - read only
DBSA1      mem   w   0xB0000030  # DMA buffer A start address 1
DBTA1      mem   w   0xB0000034  # DMA buffer A transfer count 1
DBSB1      mem   w   0xB0000038  # DMA buffer B start address 1
DBTB1      mem   w   0xB000003C  # DMA buffer B transfer count 1
DDAR2      mem   w   0xB0000040  # DMA device address register 2
SetDCSR2   mem   w   0xB0000044  # DMA control/status register 2 - write ones to set
ClrDCSR2   mem   w   0xB0000048  # DMA control/status register 2 - write ones to clear
RdDCSR2    mem   w   0xB000004C  # DMA control/status register 2 - read only
DBSA2      mem   w   0xB0000050  # DMA buffer A start address 2
DBTA2      mem   w   0xB0000054  # DMA buffer A transfer count 2
DBSB2      mem   w   0xB0000058  # DMA buffer B start address 2
DBTB2      mem   w   0xB000005C  # DMA buffer B transfer count 2
DDAR3      mem   w   0xB0000060  # DMA device address register 3
SetDCSR3   mem   w   0xB0000064  # DMA control/status register 3 - write ones to set
ClrDCSR3   mem   w   0xB0000068  # DMA control/status register 3 - Write ones to clear
RdDCSR3    mem   w   0xB000006C  # DMA control/status register 3 - Read only
DBSA3      mem   w   0xB0000070  # DMA buffer A start address 3
DBTA3      mem   w   0xB0000074  # DMA buffer A transfer count 3
DBSB3      mem   w   0xB0000078  # DMA buffer B start address 3
DBTB3      mem   w   0xB000007C  # DMA buffer B transfer count 3
DDAR4      mem   w   0xB0000080  # DMA device address register 4
SetDCSR4   mem   w   0xB0000084  # DMA control/status register 4 - write ones to set
ClrDCSR4   mem   w   0xB0000088  # DMA control/status register 4 - write ones to clear
RdDCSR4    mem   w   0xB000008C  # DMA control/status register 4 - read only
DBSA4      mem   w   0xB0000090  # DMA buffer A start address 4
DBTA4      mem   w   0xB0000094  # DMA buffer A transfer count 4
DBSB4      mem   w   0xB0000098  # DMA buffer B start address 4
DBTB4      mem   w   0xB000009C  # DMA buffer B transfer count 4
DDAR5      mem   w   0xB00000A0  # DMA device address register 5
SetDCSR5   mem   w   0xB00000A4  # DMA control/status register 5 - write ones to set
ClrDCSR5   mem   w   0xB00000A8  # DMA control/status register 5 - write ones to clear
RdDCSR5    mem   w   0xB00000AC  # DMA control/status register 5 - read only
DBSA5      mem   w   0xB00000B0  # DMA buffer A start address 5
DBTA5      mem   w   0xB00000B4  # DMA buffer A transfer count 5
DBSB5      mem   w   0xB00000B8  # DMA buffer B start address 5
DBTB5      mem   w   0xB00000BC  # DMA buffer B transfer count 5
LCCR0      mem   w   0xB0100000  # LCD controller control register 0
LCSR       mem   w   0xB0100004  # LCD controller status register
DBAR1      mem   w   0xB0100010  # DMA channel 1 base address register
DCAR1      mem   w   0xB0100014  # DMA channel 1 current address register
DBAR2      mem   w   0xB0100018  # DMA channel 2 base address register
DCAR2      mem   w   0xB010001C  # DMA channel 2 current address register
LCCR1      mem   w   0xB0100020  # LCD controller control register 1
LCCR2      mem   w   0xB0100024  # LCD controller control register 2
LCCR3      mem   w   0xB0100028  # LCD controller control register 



# BT835 registers

STATUS     smbus   b   0x45 0x00
INPUT      smbus   b   0x45 0x01


VDELAY     smbus   h   0x45 0x02
VDELAY_LO  smbus   b   0x45 0x02
VDELAY_HI  smbus   b   0x45 0x03


VACTIVE    smbus   h   0x45 0x04
VACTIVE_LO smbus   b   0x45 0x04
VACTIVE_HI smbus   b   0x45 0x05


HDELAY     smbus   h   0x45 0x06
HDELAY_LO  smbus   b   0x45 0x06
HDELAY_HI  smbus   b   0x45 0x07


HACTIVE    smbus   h   0x45 0x08
HACTIVE_LO smbus   b   0x45 0x08
HACTIVE_HI smbus   b   0x45 0x09


HSCALE     smbus   h   0x45 0x0A
HSCALE_LO  smbus   b   0x45 0x0A
HSCALE_HI  smbus   b   0x45 0x0B


VSCALE     smbus   h   0x45 0x0C
VSCALE_LO  smbus   b   0x45 0x0C
VSCALE_HI  smbus   b   0x45 0x0D


VSCALE_CTL smbus   b   0x45 0x0E
TDEC       smbus   b   0x45 0x0F
BRIGHT     smbus   b   0x45 0x10
CONTRAST   smbus   b   0x45 0x11
SAT_U      smbus   b   0x45 0x12
SAT_V      smbus   b   0x45 0x13
HUE        smbus   b   0x45 0x14
CONTROL_0  smbus   b   0x45 0x15
CONTROL_1  smbus   b   0x45 0x16
CONTROL_2  smbus   b   0x45 0x17
CONTROL_3  smbus   b   0x45 0x18
VPOLE      smbus   b   0x45 0x19
AGC_DELAY  smbus   b   0x45 0x1A
BG_DELAY   smbus   b   0x45 0x1B
ADC        smbus   b   0x45 0x1C
WC_UP      smbus   b   0x45 0x1D
WC_DN      smbus   b   0x45 0x1E
CC_STATUS  smbus   b   0x45 0x1F
CC_DATA    smbus   b   0x45 0x20
GPIO       smbus   b   0x45 0x21
GPIO_NOE   smbus   b   0x45 0x22
VSIF       smbus   b   0x45 0x23
TG_CTL     smbus   b   0x45 0x24


PLL_F      smbus   h   0x45 0x25
PLL_F_LO   smbus   b   0x45 0x25
PLL_F_HI   smbus   b   0x45 0x26


PLL_XCI_28 smbus b 0x45 0x27

PLL_F      smbus   h   0x45 0x28
PLL_F_LO   smbus   b   0x45 0x28
PLL_F_HI   smbus   b   0x45 0x29


PLL_XCI_35 smbus   b   0x45 0x2A
DVLCNT     smbus   b   0x45 0x2B
IDCODE     smbus   b   0x45 0xfe
SW_RESET   smbus   b   0x45 0xff