Showing posts with label TWL4030. Show all posts
Showing posts with label TWL4030. Show all posts

Tuesday, September 28, 2010

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