Tuesday, September 28, 2010

Bare Metal: PuppyBoot entry code (XLDR) - ARM assembly initialization sequences

In the wake of my relocation, I feel its time to pause a bit on the linux kernel BSP development and start backing up my bare metal code base for my Beagle Board.

I called this code base as PuppyBeagle, as its more of a miniature version of a OS kernel, in terms of what it prepares the board with. Here are some of the files that I did write to bootup the board, setup Interrupt Vector Table (IVT), iniitialize RAM, initialize serial port for early debugging, initialize and blink LED connected to the TWL4030 PM IC, due to which, I need to program the I2C to communicate between OMAP and the PMIC.
I have also initialize the MMC module, though reading/writing is still not 100% reliably working and I had paused for sometime working more on this but rather continued development more on the linux side. But hopefully, once I move to my new place, I can take this up again!


/******************************************************************************
*             Entry Point to PuppyBeagle Boot code
*
* This part of the code does some basic IVT setup until an application code
* overrides this table with a well defined IVT.
*
*       Copyrights (c) 2010 Amarnath B Revanna, amarnath.revanna@gmail.com
******************************************************************************/
.text
.code 32
.global _start
.func _start
_start:
wait4debugger: b wait4debugger

b reset
ldr pc, [pc, #0x14]
ldr pc, [pc, #0x14]
ldr pc, [pc, #0x14]
ldr pc, [pc, #0x14]
ldr pc, [pc, #0x14]
ldr pc, [pc, #0x14]
ldr pc, [pc, #0x14]
/*
ldr pc, =swi
ldr pc, =pabort
ldr pc, =dabort
rsvd: b rsvd
ldr pc, =irq
ldr pc, =fiq
*/
reset:
/*
 * We will branch to a C program to do low level initialization. Note that we
 * cannot use any initialized variables or depend on bss stack as they are not
 * yet setup. So we will do low level init. to prepare for a C environment.
 * Also note that this C function must reside within the 1k memory area to
 * branch to and return.
 * Before branching, we need to set a default stack where args. will be saved
 * and R14 needs to be updated with the return address.
 */
/*
 * Setup stacks for different modes. We need to do this as we
 * may encounter exceptions anytime and should setup secondary
          * IVT to handle exceptions properly.
 */
//We are in SVC mode currently, so start from there
ldr sp, = __svc_stack__start;
//Next, switch to IRQ mode
mrs r0, cpsr
bic r0, r0, #MODE_MASK
orr r0, r0, #MODE_IRQ
msr  cpsr_c, r0
ldr sp, = __irq_stack__start;

//Next, switch to IRQ mode
mrs r0, cpsr
bic r0, r0, #MODE_MASK
orr r0, r0, #MODE_FIQ
msr  cpsr_c, r0
ldr sp, = __fiq_stack__start;

//Next, switch to IRQ mode
mrs r0, cpsr
bic r0, r0, #MODE_MASK
orr r0, r0, #MODE_ABT
msr  cpsr_c, r0
ldr sp, = __abt_stack__start;

//Next, switch to IRQ mode
mrs r0, cpsr
bic r0, r0, #MODE_MASK
orr r0, r0, #MODE_UND
msr  cpsr_c, r0
ldr sp, = __und_stack__start;
//Next, switch to SYS/USR mode
mrs r0, cpsr
bic r0, r0, #MODE_MASK
orr r0, r0, #MODE_SYS
msr  cpsr_c, r0
ldr sp, = __sys_stack__start;

// Now, switch back to SVC mode
mrs r0, cpsr
bic r0, r0, #MODE_MASK
orr r0, r0, #MODE_SVC
msr  cpsr_c, r0

/* Prepare for C runtime environment */
//Clear bss section for unitialized var. as reqd. by C standards
ldr r0, =__bss_start
ldr r1, =__bss_end
bss_clear: cmp r0, r1
beq clear_done
mov r2, #0
str r2, [r0], #4
b bss_clear

// All basic initialization done, can jump to C code from here
clear_done:
bl low_level_init
ldr r12, =main
mov lr, pc
bx r12
//We never expect to return here, if we do, we throw exception
swi 0xFFFFFF
.size _start, . - _start
.endfunc
.equ MODE_MASK, 0x1F
.equ MODE_ABT, 0b10111
.equ MODE_FIQ, 0b10001
.equ MODE_IRQ, 0b10010
.equ MODE_SVC, 0b10011
.equ MODE_SYS, 0b11111
.equ MODE_UND, 0b11011
.equ MODE_USR, 0b10000

.equ IVT_VECTOR_ADDR, 0x4020FFC8
.equ IVT_END_ADDR, IVT_VECTOR_ADDR + (7 * 4)
.end


Bare Metal: PuppyBeagle linker script [PB.ld]

Its important to take a look at the linker script developed to build the PuppyBeagle code base, that describes the memory allocations for different areas of the image that is eventually built.


/*******************************************************************************
*        Linker Script for mapping PuppyBeagle code to SRAM and DDRAM
*
*      Copyright (c) 2010 Amarnath B Revanna, amarnath.revanna@gmail.com
*
 ******************************************************************************/

OUTPUT_FORMAT ("elf32-littlearm")
OUTPUT_ARCH (arm)
ENTRY (_start)

MEMORY {

SRAM (rwx) : ORIGIN = 0X40200000, LENGTH = 64K
}

SVC_STACK_SIZE = 536;
IRQ_STACK_SIZE = 536;
FIQ_STACK_SIZE = 536;
ABT_STACK_SIZE = 536;
UND_STACK_SIZE = 536;
SYS_STACK_SIZE = 536;

SECTIONS {

.stack : {
__stack_start__ = . + 0xF000;
__stack_end__ = __stack_start__ + 0xCB0;

__svc_stack__start = __stack_end__;
__svc_stack__end = __svc_stack__start - SVC_STACK_SIZE;

__irq_stack__start = __svc_stack__end - 4;
__irq_stack__end = __irq_stack__start - IRQ_STACK_SIZE;

__fiq_stack__start = __irq_stack__end - 4;
__fiq_stack__end = __fiq_stack__start - FIQ_STACK_SIZE;

__abt_stack__start = __fiq_stack__end - 4;
__abt_stack__end = __abt_stack__start - ABT_STACK_SIZE;

__und_stack__start = __abt_stack__end - 4;
__und_stack__end = __und_stack__start - UND_STACK_SIZE;

__sys_stack__start = __und_stack__end - 4;
__sys_stack__end = __sys_stack__start - SYS_STACK_SIZE;


} > SRAM

.reset : {
*startup.o (.text)
/*
* Startup code containing IVT should be
* placed as the first section of image
*/
*low_init.o (.text)
  . = ALIGN (0x4);
} > SRAM

.text : {
CREATE_OBJECT_SYMBOLS
* (.text .text.* .gnu.linkonce.t.*)
* (.plt)
* (.gnu.warning)
* (.glue_7t) * (.glue_7)
. = ALIGN (0x4);

KEEP ( *crtbegin.o (.ctors))
KEEP ( * (EXCLUDE_FILE (*crtend.o) .ctors))
KEEP ( * (SORT (.ctors)))
KEEP ( *crtend.o (.ctors))
KEEP ( *crtbegin.o (.dtors))
KEEP ( * (EXCLUDE_FILE(*crtend.o) .dtors))
KEEP ( *(SORT (.dtors.*)))
KEEP ( *crtend.o (.dtors))

*(.init)
*(.fini)
*(.rodata .rodata.* .gnu.linkonce.r.*)
} > SRAM

.data : {
__data_start = .;
KEEP (* (.jcr))
* (.got.plt) * (.got)
* (.shdata)
*. (.data .data.* .gnu.linkonce.d.*)
. = ALIGN (0x4);
_edata = .;
} > SRAM

.bss : {
__bss_start = .;
* (.shbss)
* (.bss .bss.* .gnu.linkonce.b.*)
* (COMMON)
. = ALIGN (0x4);
__bss_end = .;
} > SRAM
/*Used by linker for internal purposes only*/
.stab 0 (NOLOAD) : {
*.(.stab)
}

.stabstr 0 (NOLOAD) : {
*.(.stabstr)
}

/*
* DWARF Debug Sections.
* Symbols in DWARF debugging sections are relative to the beginning of
* the section so we begin them at 0.
*/

/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }

}

Each of the section will be explained in detail soon, for now, just take it as it is with a grain of salt ;)

Bare Metal: PuppyBeagle low level initialization code header file [low_init.h]

#ifndef __BEAGLE_H__
#define __BEAGLE_H__

#define MMC_REG_BASE 0x4809C010
#define SDRC_REG_BASE 0x6D000010

#define RAMSZ_TYP_CLR 0xFFFC00FE
#define RAMSZ_TYP 0x00007801


typedef struct {
unsigned int SDRC_SYSCONFIG; //0x10
unsigned int SDRC_SYSSTATUS;//0x14
unsigned int rsvd1[10];//0x18,1c,20,24,28,2c,30,34,38,3c
unsigned int SDRC_CS_CFG;//40
unsigned int SDRC_SHARING;//44
unsigned int SDRC_ERR_ADDR;//48
unsigned int SDRC_ERR_TYPE;//4c
unsigned int rsvd2[4];//50,54,58,5c
unsigned int SDRC_DLLA_CTRL;//60
unsigned int SDRC_DLLA_STATUS;//64
unsigned int rsvd5[2];//68,6c
unsigned int SDRC_POWER_REG; //70
unsigned int rsvd3[3];//74,78,7c
unsigned int SDRC_MCFG_0;//80
unsigned int SDRC_MR_0;//84
unsigned int SDRC_EMR2_0;//8c
unsigned int rsvd4[3];//90,94,98
unsigned int SDRC_ACTIM_CTRLA_0;//9c
unsigned int SDRC_ACTIM_CTRLB_0;//a0
unsigned int SDRC_RFR_CTRL_0;//a4
unsigned int SDRC_MANUAL_0;//a8
} sdrc_reg;

#endif

Bare Metal: PuppyBeagle low level initialization code in C [low_init.c]

/******************************************************************************
*            PuppyBeagle low level init code
*
* This part of the code does some basic hardware initialization including
* UART init, SDRAM init, 2nd level IVT setup
*
*       Copyrights (c) 2010 Amarnath B Revanna, amarnath.revanna@gmail.com
******************************************************************************/
#include
#include "low_init.h"
#include "sprint.h"

void und_ex_handler (void)
{
sprint ("*** UNDEF EXCEPTION RAISED ***\n");
}
void swi_ex_handler (void)
{
sprint ("*** SWI EXCEPTION RAISED ***\n");
}
void pabt_ex_handler (void)
{
sprint ("*** PREFETCH ABORT ***\n");
}
void dabt_ex_handler (void)
{
sprint ("*** DATA ABORT ***\n");
}
void irq_ex_handler (void)
{
sprint ("*** RECEIVED IRQ INTERRUPT ***\n");
}
void fiq_ex_handler (void)
{
sprint ("*** RECEIVED FIQ INTERRUPT ***\n");
}

void low_level_init ()
{
uart_reg *puart;
sdrc_reg *psdrc;

uint32_t *pIvt2_und = (uint32_t *)0x4020FFE4;
uint32_t *pIvt2_swi = (uint32_t *)0x4020FFE8;
uint32_t *pIvt2_pabt = (uint32_t *)0x4020FFEC;
uint32_t *pIvt2_dabt = (uint32_t *)0x4020FFF0;
uint32_t *pIvt2_irq = (uint32_t *)0x4020FFF8;
uint32_t *pIvt2_fiq = (uint32_t *)0x4020FFFC;

puart = (uart_reg *) UART3_REG_BASE;
psdrc = (sdrc_reg *) SDRC_REG_BASE;

//Do soft-reset and wait for reset complete
puart->UART_SYSC |= UART_RST_MASK;
while (!puart->UART_SYSS)
;

/* Put UART3 in Config. Mode B to access UART_DLL_REG which is same as
* UART_THR_REG
*/
puart->UART_LCR &= UART3_B_MODE;
puart->UART_THR = BAUD_115200;

//Put UART3 in Operational Mode
puart->UART_LCR = UART3_OP_MODE;

// Put UART3 in 16x mode
puart->UART_MDR1 = UART_16X_MODE;

//Finally, touch UART_RESUME register to start Tx/Rx
puart->UART_RESUME = puart->UART_RESUME;

sprint ("UART CONFIGURED...\n");

//Next, start SDRAM configuration
psdrc->SDRC_MCFG_0 &= RAMSZ_TYP_CLR;
psdrc->SDRC_MCFG_0 |= RAMSZ_TYP;

sprint ("SDRC CONFIGURED...\n");

//Setup secondary IVT
*pIvt2_und = (uint32_t) &und_ex_handler;
*pIvt2_swi = (uint32_t) &swi_ex_handler;
*pIvt2_pabt = (uint32_t) &pabt_ex_handler;
*pIvt2_dabt = (uint32_t) &dabt_ex_handler;
*pIvt2_irq = (uint32_t) &irq_ex_handler;
*pIvt2_fiq = (uint32_t) &fiq_ex_handler;

sprint ("IVT SETUP...\n");

}

Bare Metal: PuppyBeagle platform definition header file [beagle.h]

#ifndef __BEAGLE_H__
#define __BEAGLE_H__

#define MMC_REG_BASE 0x4809C010
#define UART3_REG_BASE 0x49020000
#define SDRC_REG_BASE 0x6D000010

#define UART3_OP_MODE 0x3
#define UART3_B_MODE 0xBF
#define UART_RST_MASK 0x2
#define BAUD_115200 0x1A
#define UART_16X_MODE 0xFFFFFFF0
#define UART_TXFIFO_EMPTY 0x00000020

#define RAMSZ_TYP_CLR 0xFFFC00FE
#define RAMSZ_TYP 0x00007801


#define MMC_CLOCK_EN 0x01000000
#define MMC_SW_RESET 0x2
#define MMC_RESET_DONE 0x2
#define MMC_1_8_N_3_V 0x06000000

typedef struct {
unsigned int MMC_SYSCONFIG;
unsigned int MMC_SYSSTATUS;
unsigned int MMC_CSRE;
unsigned int MMC_SYSTEST;
unsigned int MMC_CON;
unsigned int MMC_PWCNT;
unsigned int MMC_BLK;
unsigned int MMC_ARG;
unsigned int MMC_CMD;
unsigned int MMC_RSP10;
unsigned int MMC_RSP32;
unsigned int MMC_RSP54;
unsigned int MMC_RSP76;
unsigned int MMC_DATA;
unsigned int MMC_PSTATE;
unsigned int MMC_HCTL;
unsigned int MMC_SYSCTL;
unsigned int MMC_STAT;
unsigned int MMC_IE;
unsigned int MMC_ISE;
unsigned int MMC_AC12;
unsigned int MMC_CAPA;
unsigned int MMC_CUR_CAPA;
unsigned int MMC_REV;
} mmc_reg;

typedef struct {
unsigned int UART_THR;
unsigned int UART_IER;
unsigned int UART_FCR;
unsigned int UART_LCR;
unsigned int UART_MCR;
unsigned int UART_LSR;
unsigned int UART_MSR_TCR;
unsigned int UART_SPR_TLR;
unsigned int UART_MDR1;
unsigned int UART_MDR2;
unsigned int UART_SFLSR;
unsigned int UART_TXFLL;
unsigned int UART_RESUME;
unsigned int UART_TXFLH;
unsigned int UART_RXFLL;
unsigned int UART_SFREGL;
unsigned int UART_RXFLH;
unsigned int UART_SFREGH;
unsigned int UART_BLR;
unsigned int UART_ACREG;
unsigned int UART_SCR;
unsigned int UART_SSR;
unsigned int UART_EBLR;
unsigned int UART_SYSC;
unsigned int UART_SYSS;
unsigned int UART_WER;
unsigned int UART_CFPS;
} uart_reg;

typedef struct {
unsigned int SDRC_SYSCONFIG; //0x10
unsigned int SDRC_SYSSTATUS;//0x14
unsigned int rsvd1[10];//0x18,1c,20,24,28,2c,30,34,38,3c
unsigned int SDRC_CS_CFG;//40
unsigned int SDRC_SHARING;//44
unsigned int SDRC_ERR_ADDR;//48
unsigned int SDRC_ERR_TYPE;//4c
unsigned int rsvd2[4];//50,54,58,5c
unsigned int SDRC_DLLA_CTRL;//60
unsigned int SDRC_DLLA_STATUS;//64
unsigned int rsvd5[2];//68,6c
unsigned int SDRC_POWER_REG; //70
unsigned int rsvd3[3];//74,78,7c
unsigned int SDRC_MCFG_0;//80
unsigned int SDRC_MR_0;//84
unsigned int SDRC_EMR2_0;//8c
unsigned int rsvd4[3];//90,94,98
unsigned int SDRC_ACTIM_CTRLA_0;//9c
unsigned int SDRC_ACTIM_CTRLB_0;//a0
unsigned int SDRC_RFR_CTRL_0;//a4
unsigned int SDRC_MANUAL_0;//a8
} sdrc_reg;

//volatile unsigned int *PRCM_CM_ICLKEN1_CORE = (unsigned int *) 0x48004A10;
//volatile unsigned int *PRCM_CM_FCLKEN1_CORE = (unsigned int *) 0x48004A00;

#endif

Bare Metal: PuppyBeagle C init file [main.c]

int main (void)
{
i2c_init();
mmc_init();
}

Bare Metal: PuppyBeagle i2c driver file to talk to TWL 4030 [i2c.c/i2c.h]

#include "prcm.h"
#include "i2c.h"

void i2c_write (char slaveaddr, char *data, int ploadsz, char stop)
{
i2c_reg *pi2c = (i2c_reg *) I2C1_REG_BASE;

//Config. I2C slave addr. and address count
restart:pi2c->I2C_SA = slaveaddr;
pi2c->I2C_CNT = ploadsz;

pi2c->I2C_DATA = *data;

//Poll for I2C bus free
while (pi2c->I2C_STAT & I2C1_STAT_BB)
;

//Config. I2C to be master and set it to tx mode
pi2c->I2C_CON = I2C1_EN| I2C1_MASTER | I2C1_TX;

  //Initiate transfer (set Start bit only)
pi2c->I2C_CON |= I2C1_CON_STT;
if (stop)
  pi2c->I2C_CON |= I2C1_CON_STP;

//Wait for I2C to be ready again for next request
while (ploadsz)
{
if (pi2c->I2C_STAT & I2C1_STAT_NACK)
{
pi2c->I2C_STAT |= I2C1_STAT_NACK;
goto restart;
}
if (pi2c->I2C_STAT & I2C1_STAT_AL)
{
pi2c->I2C_STAT |= I2C1_STAT_AL;
goto restart;
}
if (pi2c->I2C_STAT & I2C1_STAT_ARDY)
{
pi2c->I2C_STAT |= I2C1_STAT_ARDY;
continue;
}
if (pi2c->I2C_STAT & I2C1_STAT_XRDY)
{
pi2c->I2C_STAT |= I2C1_STAT_XRDY;
data++;
ploadsz--;
  pi2c->I2C_DATA = *data;
}
}

if (!stop)
return;

//Clear status
pi2c->I2C_STAT |= 0xFFFF;
pi2c->I2C_CNT = 0;
}

void i2c_read (char slaveaddr, char *data, int ploadsz, char stop)
{
int resp = 0;
i2c_reg *pi2c = (i2c_reg *) I2C1_REG_BASE;

//Now config. I2C to be master and set it to rx mode to read register
pi2c->I2C_CON = I2C1_EN | I2C1_MASTER | I2C1_RX;

//Initiate receive (set Start and Stop bits set)
pi2c->I2C_CON |= I2C1_CON_STT;

if (stop)
pi2c->I2C_CON |= I2C1_CON_STP;

restart:pi2c->I2C_SA = slaveaddr;
pi2c->I2C_CNT = ploadsz;

pi2c->I2C_DATA = *data;

//Poll for I2C bus free
while (pi2c->I2C_STAT & I2C1_STAT_BB)
;

//Config. I2C to be master and set it to tx mode
pi2c->I2C_CON = I2C1_EN| I2C1_MASTER | I2C1_TX;

  //Initiate transfer (set Start bit only)
pi2c->I2C_CON |= I2C1_CON_STT;
if (stop)
  pi2c->I2C_CON |= I2C1_CON_STP;

//Wait for I2C to be ready again for next request
while (ploadsz)
{
if (pi2c->I2C_STAT & I2C1_STAT_NACK)
{
pi2c->I2C_STAT |= I2C1_STAT_NACK;
goto restart;
}
if (pi2c->I2C_STAT & I2C1_STAT_AL)
{
pi2c->I2C_STAT |= I2C1_STAT_AL;
goto restart;
}
if (pi2c->I2C_STAT & I2C1_STAT_ARDY)
{
pi2c->I2C_STAT |= I2C1_STAT_ARDY;
continue;
}
if (pi2c->I2C_STAT & I2C1_STAT_RRDY)
{
pi2c->I2C_STAT |= I2C1_STAT_RRDY;
data++;
ploadsz--;
  *data = pi2c->I2C_DATA;
}
}

if (!stop)
return;

//Clear status
pi2c->I2C_STAT |= 0xFFFF;
pi2c->I2C_CNT = 0;
 
}

void i2c_reg_read (char slaveaddr, char reg, char value)
{
i2c_reg *pi2c = (i2c_reg *) I2C1_REG_BASE;

i2c_write (slaveaddr, &reg, 1, NO_STOP);
i2c_read (slaveaddr, &value, 1, STOP);

}

void i2c_reg_write (char slaveaddr, char reg, char value)
{
char buf[2];

buf[0] = reg;
buf[1] = value;
i2c_write (slaveaddr, buf, 2, STOP);
}

void i2c_init(void)
{
i2c_reg *pi2c = (i2c_reg *) I2C1_REG_BASE;
corecm_reg *pcorecm = (corecm_reg *) CORECM_REG_BASE;

/*Enable I & F Clocks for I2C1 module */
pcorecm->CORECM_FCLKEN1 |= I2C1_CLOCK_EN;
pcorecm->CORECM_ICLKEN1 |= I2C1_CLOCK_EN;

//Adjust prescalar to obtain 12MHz internal sampling clock
pi2c->I2C_PSC = I2C1_PRESCALAR;

//Config. i2c for a bit rate of 100Kbps

/*
* (TL + TH) * Int_clk = 100 Kbps
* (TL + TH) * 12MHz = 100 Kbps
* 1/(TL + TH) = 120
* Since TL = SCLL + 7 and TH = SCLH + 5, if we choose to have
* TL == TH i.e. both high and low half-cycles to be equal, we
* see that (SCLH + 5) + (SCLL + 7) = 120
* Since TL=TH, the values that satisfy above equation would be
* SCLH = 55 and SCLL = 53
*/

pi2c->I2C_SCLL = I2C1_SCLL_TL;
pi2c->I2C_SCLH = I2C1_SCLL_TH;

//Config. own address (master: 0x1)
pi2c->I2C_OA0 = I2C1_OWN_ADDR;

//Keep TX/RX Threshold at its default values

//We will start with a device reset
if (pi2c->I2C_CON & I2C1_EN)
pi2c->I2C_CON = 0x0;

pi2c->I2C_CON |= I2C1_EN;

//wait for reset complete
while (!(pi2c->I2C_SYSS & I2C_RST_DONE))
;

  i2c_reg_write(I2C1_TWLED_SLAVE_ADDR, LED_REG, LEDB_EN | PWMB_EN);
// i2c_reg_write(I2C1_TWLED_SLAVE_ADDR, LED_REG, LED_EN);

}


And its correspoding header file


#ifndef __I2C_H__
#define __I2C_H__

#define I2C1_REG_BASE 0x48070004

#define I2C1_CLOCK_EN 0x00008000
#define I2C1_PRESCALAR 0x7
#define I2C1_SCLL_TL 0x35
#define I2C1_SCLL_TH 0x37
#define I2C1_OWN_ADDR 0x1
#define I2C1_EN 0x8000
#define I2C1_MASTER 0x400
#define I2C1_TX 0x200
#define I2C1_RX 0x00
#define I2C1_TWLED_SLAVE_ADDR 0x4a
#define I2C1_DCOUNT 0x8
#define I2C1_STAT_BB 0x1000
#define I2C1_CON_STT 0x1
#define I2C1_CON_STP 0x2
#define I2C1_STAT_BB 0x1000
#define I2C1_STAT_XRDY 0x10
#define I2C1_STAT_RRDY 0x8
#define I2C1_STAT_ARDY 0x4
#define I2C1_STAT_NACK 0x2
#define I2C1_STAT_AL 0x0
#define I2C_RESET 0x2
#define I2C_RST_DONE 0x1

#define STOP 1
#define NO_STOP 0

typedef struct {
unsigned short I2C_IE;
unsigned short rsvd1;
unsigned short I2C_STAT;
unsigned short rsvd2;
unsigned short I2C_WE;
unsigned short rsvd3;
unsigned short I2C_SYSS;
unsigned short rsvd4;
unsigned short I2C_BUF;
unsigned short rsvd5;
unsigned short I2C_CNT;
unsigned short rsvd6;
unsigned short I2C_DATA;
unsigned short rsvd7;
unsigned short I2C_SYSC;
unsigned short rsvd8;
unsigned short I2C_CON;
unsigned short rsvd9;
unsigned short I2C_OA0;
unsigned short rsvd10;
unsigned short I2C_SA;
unsigned short rsvd11;
unsigned short I2C_PSC;
unsigned short rsvd12;
unsigned short I2C_SCLL;
unsigned short rsvd13;
unsigned short I2C_SCLH;
unsigned short rsvd14;
unsigned short I2C_SYSTEST;
unsigned short rsvd15;
unsigned short I2C_BUFSTAT;
unsigned short rsvd16;
unsigned short I2C_OA1;
unsigned short rsvd17;
unsigned short I2C_OA2;
unsigned short rsvd18;
unsigned short I2C_OA3;
unsigned short rsvd19;
unsigned short I2C_ACTOA;
unsigned short rsvd20;
unsigned short I2C_SBLOCK;
unsigned short rsvd21;
} i2c_reg;

void i2c_write (char slaveaddr, char *data, int ploadsz, char stop);
void i2c_read (char slaveaddr, char *data, int ploadsz, char stop);

void i2c_reg_write (char slaveaddr, char reg, char value);
void i2c_reg_read (char slaveaddr, char reg, char value);

#define LED_REG 0xEE
#define PWMA_REG 0xEF

#define LEDB_EN 1 << 1
#define PWMB_EN 1 << 5
#define PWMA_ON 63
#define PWMA_OFF 127
#define PWMA_LEN 0x80

#endif

Bare Metal: PuppyBeagle interrupt controller (INTC) init file [intc.c/intc.h]

#include "sprint.h"
#include "intc.h"

void intc_init (void)
{
intc_reg *pintc = (intc_reg *) INTC_REG_BASE;

pintc->INTCPS_SYSCONFIG = INTC_SWRESET;

//Wait for reset complete
while (!pintc->INTCPS_SYSCONFIG)
;

sprint ("Inside intc_init\n");
}

and its header file

#ifndef __INTC_H
#define __INTC_H

#define INTC_REG_BASE 0x48200010

#define INTC_SWRESET 0x2

typedef struct {
unsigned int INTCPS_SYSCONFIG;//10
unsigned int INTCPS_SYSSTATUS;//0x14
unsigned int RSVD0[10];//3c
unsigned int INTCPS_SIR_IRQ;//40
unsigned int INTCPS_SIR_FIQ;//44
unsigned int INTCPS_CONTROL;//48
unsigned int INTCPS_PROTECTION;//4c
unsigned int INTCPS_IDLE;//50
unsigned int RSVD1[3];//5c
unsigned int INTCPS_IRQ_PRIORITY;//60
unsigned int INTCPS_FIQ_PRIORITY;//64
unsigned int INTCPS_THRESHOLD;//68
unsigned int RSVD2[5];//7c
unsigned int INTCPS_INTR0;//80
unsigned int INTCPS_MIR0;//84
unsigned int INTCPS_MIR_CLEAR0;//88
unsigned int INTCPS_MIR_SET0;//8c
unsigned int INTCPS_ISR_SET0;//90
unsigned int INTCPS_ISR_CLEAR0;//94
unsigned int INTCPS_PENDING_IRQ0;//98
unsigned int INTCPS_PENDING_FIQ0;//9c
unsigned int INTCPS_INTR1;//a0
unsigned int INTCPS_MIR1;//a4
unsigned int INTCPS_MIR_CLEAR1;//a8
unsigned int INTCPS_MIR_SET1;//ac
unsigned int INTCPS_ISR_SET1;//b0
unsigned int INTCPS_ISR_CLEAR1;//b4
unsigned int INTCPS_PENDING_IRQ1;//b8
unsigned int INTCPS_PENDING_FIQ1;//bc
unsigned int INTCPS_INTR2;//c0
unsigned int INTCPS_MIR2;//c4
unsigned int INTCPS_MIR_CLEAR2;//c8
unsigned int INTCPS_MIR_SET2;//cc
unsigned int INTCPS_ISR_SET2;//d0
unsigned int INTCPS_ISR_CLEAR2;//d4
unsigned int INTCPS_PENDING_IRQ2;//d8
unsigned int INTCPS_PENDING_FIQ2;//dc
unsigned int RSVD3[8];//fc
unsigned int INTCPS_ILR0;//100
unsigned int INTCPS_ILR1;
unsigned int INTCPS_ILR2;
unsigned int INTCPS_ILR3;
unsigned int INTCPS_ILR4;
unsigned int INTCPS_ILR5;
unsigned int INTCPS_ILR6;
unsigned int INTCPS_ILR7;
unsigned int INTCPS_ILR8;
unsigned int INTCPS_ILR9;
unsigned int INTCPS_ILR10;
unsigned int INTCPS_ILR11;
unsigned int INTCPS_ILR12;
unsigned int INTCPS_ILR13;
unsigned int INTCPS_ILR14;
unsigned int INTCPS_ILR15;
unsigned int INTCPS_ILR16;
unsigned int INTCPS_ILR17;
unsigned int INTCPS_ILR18;
unsigned int INTCPS_ILR19;
unsigned int INTCPS_ILR20;
unsigned int INTCPS_ILR21;
unsigned int INTCPS_ILR22;
unsigned int INTCPS_ILR23;
unsigned int INTCPS_ILR24;
unsigned int INTCPS_ILR25;
unsigned int INTCPS_ILR26;
unsigned int INTCPS_ILR27;
unsigned int INTCPS_ILR28;
unsigned int INTCPS_ILR29;
unsigned int INTCPS_ILR30;
unsigned int INTCPS_ILR31;
unsigned int INTCPS_ILR32;
unsigned int INTCPS_ILR33;
unsigned int INTCPS_ILR34;
unsigned int INTCPS_ILR35;
unsigned int INTCPS_ILR36;
unsigned int INTCPS_ILR37;
unsigned int INTCPS_ILR38;
unsigned int INTCPS_ILR39;
unsigned int INTCPS_ILR40;
unsigned int INTCPS_ILR41;
unsigned int INTCPS_ILR42;
unsigned int INTCPS_ILR43;
unsigned int INTCPS_ILR44;
unsigned int INTCPS_ILR45;
unsigned int INTCPS_ILR46;
unsigned int INTCPS_ILR47;
unsigned int INTCPS_ILR48;
unsigned int INTCPS_ILR49;
unsigned int INTCPS_ILR50;
unsigned int INTCPS_ILR51;
unsigned int INTCPS_ILR52;
unsigned int INTCPS_ILR53;
unsigned int INTCPS_ILR54;
unsigned int INTCPS_ILR55;
unsigned int INTCPS_ILR56;
unsigned int INTCPS_ILR57;
unsigned int INTCPS_ILR58;
unsigned int INTCPS_ILR59;
unsigned int INTCPS_ILR60;
unsigned int INTCPS_ILR61;
unsigned int INTCPS_ILR62;
unsigned int INTCPS_ILR63;
unsigned int INTCPS_ILR64;
unsigned int INTCPS_ILR65;
unsigned int INTCPS_ILR66;
unsigned int INTCPS_ILR67;
unsigned int INTCPS_ILR68;
unsigned int INTCPS_ILR69;
unsigned int INTCPS_ILR70;
unsigned int INTCPS_ILR71;
unsigned int INTCPS_ILR72;
unsigned int INTCPS_ILR73;
unsigned int INTCPS_ILR74;
unsigned int INTCPS_ILR75;
unsigned int INTCPS_ILR76;
unsigned int INTCPS_ILR77;
unsigned int INTCPS_ILR78;
unsigned int INTCPS_ILR79;
unsigned int INTCPS_ILR80;
unsigned int INTCPS_ILR81;
unsigned int INTCPS_ILR82;
unsigned int INTCPS_ILR83;
unsigned int INTCPS_ILR84;
unsigned int INTCPS_ILR85;
unsigned int INTCPS_ILR86;
unsigned int INTCPS_ILR87;
unsigned int INTCPS_ILR88;
unsigned int INTCPS_ILR89;
unsigned int INTCPS_ILR90;
unsigned int INTCPS_ILR91;
unsigned int INTCPS_ILR92;
unsigned int INTCPS_ILR93;
unsigned int INTCPS_ILR94;
unsigned int INTCPS_ILR95;
} intc_reg;

#endif

Bare Metal: PuppyBeagle interrupt controller (INTC) init file [mmc.c/mmc.h]

#include "sprint.h"
#include "prcm.h"
#include "mmc.h"
#include "i2c.h"
#include

//TWL MMC VOLT. ENABLE REG PHY. ADDRESS
#define VMMC1_DEDICATED 0x85

//PBIAS CONTROL REG PHY. ADDRESS
#define CM_CNTL_PBIAS_LITE 0x48002520

#define TWL_MMC3V 0x2
#define PBIASLITE_PWRDNZ0 1 << 1

void mmc_init (void)
{
int wait;
mmc_reg *pmmc = (mmc_reg *) MMC_REG_BASE;
corecm_reg *pcorecm = (corecm_reg *) CORECM_REG_BASE;
unsigned int *pcm = (unsigned int*) CM_CNTL_PBIAS_LITE;

//Config. PBIAS Voltage and internal clock
  i2c_reg_write(I2C1_TWLED_SLAVE_ADDR, VMMC1_DEDICATED, TWL_MMC3V);

/*Enable I & F Clocks for MMC module */
pcorecm->CORECM_FCLKEN1 |= MMC_CLOCK_EN;
pcorecm->CORECM_ICLKEN1 |= MMC_CLOCK_EN;

//VDDS MMC1 Stable
*pcm |= PBIASLITE_PWRDNZ0;

/*Do a soft reset of MMC module and wait for status done*/
pmmc->MMC_SYSCONFIG |= MMC_SW_RESET;
while (!(pmmc->MMC_SYSSTATUS |= MMC_RESET_DONE))
;

sprint ("Done with MMC RESET, WILL INIT. APPROPRIATE VOLTAGE...\n");

/*Initialize appropriate voltage sources to MMC*/
pmmc->MMC_CAPA |= MMC_1_8_N_3_V;

//Do MMC Bus Configuration
pmmc->MMC_CON |= MMC_OD_SET;
pmmc->MMC_HCTL |= MMC_SDVS_3V | MMC_SDBP_ON;

while (!(pmmc->MMC_HCTL & MMC_SDBP_CHKMSK))
;
//Enable internal clock [Ref: 22.5.1.5 in TRM]
pmmc->MMC_SYSCTL |= MMC_SYSCTL_ICEN;

//Wait for clock to stabilize
while (!(pmmc->MMC_SYSCTL & MMC_SYSCTL_ICS))
;

//TODO: IDLE MODE behavior skipped for now

/* Start MMC Card reset and initialization */
pmmc->MMC_CON |= MMC_INIT_SET;
pmmc->MMC_CMD = 0x0;

//We need to wait for 1 msec
wait = 0x100000;
while (wait)
wait--;
pmmc->MMC_STAT |= MMC_STAT_CLR;
pmmc->MMC_CON |= MMC_INIT_CLR;

//Clear MMC_STAT register
pmmc->MMC_STAT = 0xFFFFFFFF;

//Send CMD0
pmmc->MMC_CMD = MMC_CMD0;
pmmc->MMC_CMD = MMC_CMD5;

do {
if (pmmc->MMC_STAT & MMC_STAT_CC_TST)
{
sprint ("Found an SDIO CARD\n");
return;
}
} while (!pmmc->MMC_STAT & MMC_STAT_CTO_TST);

pmmc->MMC_SYSCTL |= MMC_SYSCTL_SRC_SET;
while (pmmc->MMC_SYSCTL & MMC_SYSCTL_SRC_SET)
;

pmmc->MMC_CMD = MMC_CMD8;


do {
if (pmmc->MMC_STAT & MMC_STAT_CC_TST)
{
sprint ("Found an SDCard\n");
return;
}
} while (!pmmc->MMC_STAT & MMC_STAT_CTO_TST);

pmmc->MMC_SYSCTL |= MMC_SYSCTL_SRC_SET;
while (pmmc->MMC_SYSCTL & MMC_SYSCTL_SRC_SET)
;

pmmc->MMC_CMD = MMC_CMD55;
pmmc->MMC_CMD = MMC_ACMD41;

do {
if (pmmc->MMC_STAT & MMC_STAT_CC_TST)
{
sprint ("Found an SD v1.1 Card\n");
return;
}
} while (!pmmc->MMC_STAT & MMC_STAT_CTO_TST);

pmmc->MMC_SYSCTL |= MMC_SYSCTL_SRC_SET;
while (pmmc->MMC_SYSCTL & MMC_SYSCTL_SRC_SET)
;

pmmc->MMC_CMD = MMC_CMD1;

do {
if (pmmc->MMC_STAT & MMC_STAT_CTO_TST)
{
sprint ("Unknown Card!!\n");
return;
}
} while (!pmmc->MMC_STAT & MMC_STAT_CC_TST);

sprint ("Found an MMC Card\n");

}


and its header file


#ifndef __MMC_H__
#define __MMC_H__

#define MMC_REG_BASE 0x4809C010

#define MMC_CLOCK_EN 0x01000000
#define MMC_SW_RESET 0x2
#define MMC_RESET_DONE 0x2
#define MMC_1_8_N_3_V 0x06000000
#define MMC_OD_SET 0x1
#define MMC_SDVS_3V 0xC00
#define MMC_SDBP_ON 0x100
#define MMC_SDBP_CHKMSK 0x100
#define MMC_SYSCTL_ICEN 0x1
#define MMC_SYSCTL_ICS 0x2
#define MMC_INIT_SET 0x1
#define MMC_INIT_CLR 0x0
#define MMC_STAT_CLR 0xFFFFFFFF
#define MMC_STAT_CC_TST 0x1
#define MMC_STAT_CTO_TST 0x00010000
#define MMC_SYSCTL_SRC_SET 0x02000000

//MMC CMDS
#define MMC_CMD0 0x00000000
#define MMC_CMD1 0x01020000
#define MMC_CMD5 0x05020000
#define MMC_CMD8 0x081A0000
#define MMC_CMD55 0x371A0000
#define MMC_ACMD41 0x291A0000

typedef struct {
unsigned int MMC_SYSCONFIG;//10
unsigned int MMC_SYSSTATUS;//14
unsigned int rsvd1[3];//18,1c,20
unsigned int MMC_CSRE;//24
unsigned int MMC_SYSTEST;//28
unsigned int MMC_CON;//2c
unsigned int MMC_PWCNT;//30
unsigned int rsvd2[52];//832d
unsigned int MMC_BLK;
unsigned int MMC_ARG;
unsigned int MMC_CMD;
unsigned int MMC_RSP10;
unsigned int MMC_RSP32;
unsigned int MMC_RSP54;
unsigned int MMC_RSP76;
unsigned int MMC_DATA;
unsigned int MMC_PSTATE;
unsigned int MMC_HCTL;
unsigned int MMC_SYSCTL;
unsigned int MMC_STAT;
unsigned int MMC_IE;
unsigned int MMC_ISE;
unsigned int MMC_AC12;
unsigned int MMC_CAPA;
unsigned int MMC_CUR_CAPA;
unsigned int rsvd3[44];
unsigned int MMC_REV;
} mmc_reg;

#endif