Commit 45f20a6f authored by Dimitris Lampridis's avatar Dimitris Lampridis
Browse files

[WR-dev] Added software tool to allow access to I2C EEPROM from the Linux prompt

parent abc2d57e
......@@ -10,7 +10,7 @@ CFLAGS += -I $(VME_INC)
LDFLAGS += -L /acc/local/$(CPU)/lib
LDLIBS += -lvmebus
all: vfchd-vuart.$(CPU) vfchd-wrc_loader.$(CPU)
all: vfchd-vuart.$(CPU) vfchd-wrc_loader.$(CPU) vfchd-eeprom_loader.$(CPU)
%.$(CPU): %.$(CPU).o
......
/* A simple tool to update the I2C EEPROM attached to the WR PTP core from a Linux terminal. */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>
#include <libvmebus.h>
#include "wrc_syscon_regs.h"
#define I2C_EEPROM_SIZE ((size_t)(8 * 1024))
#define I2C_EEPROM_ADDR 0x51
volatile void *vme_base_ptr;
uint32_t wrc_sys_base = 0x60400;
uint32_t vfchd_read(uint32_t offset)
{
volatile uint32_t *addr = vme_base_ptr + offset;
uint32_t datum = ntohl(addr[0]);
return datum;
}
void vfchd_write(uint32_t datum, uint32_t offset)
{
volatile uint32_t *addr = vme_base_ptr + offset;
addr[0] = htonl(datum);
}
void set_sda(int val)
{
if (val)
vfchd_write(SYSC_GPSR_FMC_SDA, wrc_sys_base + SYSC_REG_GPSR);
else
vfchd_write(SYSC_GPCR_FMC_SDA, wrc_sys_base + SYSC_REG_GPCR);
usleep(1.25); /* 400kHz -> 2.5us/loop */
}
void set_scl(int val)
{
if (val)
vfchd_write(SYSC_GPSR_FMC_SCL, wrc_sys_base + SYSC_REG_GPSR);
else
vfchd_write(SYSC_GPCR_FMC_SCL, wrc_sys_base + SYSC_REG_GPCR);
usleep(1.25); /* 400kHz -> 2.5us/loop */
}
int get_sda()
{
return vfchd_read(wrc_sys_base + SYSC_REG_GPSR) & SYSC_GPSR_FMC_SDA ? 1 : 0;
}
static void mi2c_start()
{
set_sda(0);
set_scl(0);
}
static void mi2c_stop()
{
set_sda(0);
set_scl(1);
set_sda(1);
}
static int mi2c_put_byte(int data)
{
int i;
int ack;
for (i = 0; i < 8; i++, data<<=1) {
set_sda(data & 0x80);
set_scl(1);
set_scl(0);
}
set_sda(1);
set_scl(1);
ack = get_sda();
set_scl(0);
set_sda(0);
return ack ? -EIO : 0; /* ack low == success */
}
static int mi2c_get_byte(unsigned char *data, int ack)
{
int i;
int indata = 0;
/* assert: scl is low */
set_scl(0);
set_sda(1);
for (i = 0; i < 8; i++) {
set_scl(1);
indata <<= 1;
if (get_sda())
indata |= 0x01;
set_scl(0);
}
set_sda((ack ? 0 : 1));
set_scl(1);
set_scl(0);
set_sda(0);
*data= indata;
return 0;
}
void mi2c_init()
{
set_scl(1);
set_sda(1);
}
int vfchd_eeprom_read(uint16_t offset, void *buf, size_t size)
{
int ret = size;
uint8_t *buf8 = buf;
unsigned char c;
if (offset > I2C_EEPROM_SIZE)
return -EINVAL;
if (offset + size > I2C_EEPROM_SIZE)
return -EINVAL;
/* Read it all in a single loop: hardware allows it */
mi2c_start();
if(mi2c_put_byte(I2C_EEPROM_ADDR << 1) < 0) {
mi2c_stop();
return -EIO;
}
mi2c_put_byte((offset >> 8) & 0xff);
mi2c_put_byte(offset & 0xff);
mi2c_stop();
mi2c_start();
mi2c_put_byte((I2C_EEPROM_ADDR << 1) | 1);
while (size--) {
mi2c_get_byte(&c, size != 0);
*buf8++ = c;
//printk("read 0x%08x, %4i to go\n", c, size);
}
mi2c_stop();
return ret;
}
int vfchd_eeprom_write(uint16_t offset, const void *buf, size_t size)
{
int i, busy;
const uint8_t *buf8 = buf;
if (offset > I2C_EEPROM_SIZE)
return -EINVAL;
if (offset + size > I2C_EEPROM_SIZE)
return -EINVAL;
for(i = 0; i < size; i++) {
mi2c_start();
if(mi2c_put_byte( I2C_EEPROM_ADDR << 1) < 0) {
mi2c_stop();
return -1;
}
mi2c_put_byte((offset >> 8) & 0xff);
mi2c_put_byte(offset & 0xff);
mi2c_put_byte(buf8[i]);
mi2c_stop();
do { /* wait until the chip becomes ready */
mi2c_start();
busy = mi2c_put_byte(I2C_EEPROM_ADDR << 1);
mi2c_stop();
} while(busy);
}
return size;
}
void vfchd_eeprom_loader (const char *fname) {
FILE *f = fopen(fname, "rb");
if ( f == NULL )
{
fprintf( stderr, "Could not open file\n" );
return;
}
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
uint8_t datum, readback;
int i = 0;
/* Keep th WR PTP core in reset */
vfchd_write(0x1deadbee, wrc_sys_base);
for (i=0; i < fsize; i++) {
fread((void *)&datum, 1, 1, f);
vfchd_eeprom_write (i, &datum, 1);
vfchd_eeprom_read (i, &readback, 1);
if ( readback != datum) {
fprintf(stderr, "\nerror writing value 0x%.2x to address 0x%.8x. Read-back value was 0x%.2x\n",
htonl(datum), i, readback);
break;
}
}
fclose(f);
/* Bring back the WR PTP core */
vfchd_write(0x0deadbee, wrc_sys_base);
}
int main(int argc, char **argv)
{
struct vme_mapping map;
struct vme_mapping *mapp = &map;
memset(mapp, 0, sizeof(*mapp));
mapp->am = VME_A32_USER_DATA_SCT;
mapp->data_width = VME_D32;
mapp->sizel = 0x80000;
mapp->vme_addrl = 0x4000000;
if ((vme_base_ptr = vme_map(mapp, 1)) == NULL) {
printf("could not map at 0x%08x\n", mapp->vme_addrl);
exit(1);
}
fprintf(stderr, "vme 0x%08x kernel %p user %p\n",
mapp->vme_addrl, mapp->kernel_va, mapp->user_va);
vfchd_eeprom_loader(argv[1]);
vme_unmap(mapp, 1);
return 0;
}
/* A simple console for accessing the VFC-HD virtual UART (i.e. for communicating with the WR Core shell
from a Linux terminal. */
/* A simple tool to update the WR PTP core software from a Linux terminal. */
#include <stdio.h>
#include <stdlib.h>
......
/*
Register definitions for slave core: WR Core System Controller
* File : wrc_syscon_regs.h
* Author : auto-generated by wbgen2 from wrc_syscon_wb.wb
* Created : Fri Feb 17 19:23:19 2012
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE wrc_syscon_wb.wb
DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
*/
#ifndef __WBGEN2_REGDEFS_WRC_SYSCON_WB_WB
#define __WBGEN2_REGDEFS_WRC_SYSCON_WB_WB
#if defined( __GNUC__)
#define PACKED __attribute__ ((packed))
#else
#error "Unsupported compiler?"
#endif
#ifndef __WBGEN2_MACROS_DEFINED__
#define __WBGEN2_MACROS_DEFINED__
#define WBGEN2_GEN_MASK(offset, size) (((1<<(size))-1) << (offset))
#define WBGEN2_GEN_WRITE(value, offset, size) (((value) & ((1<<(size))-1)) << (offset))
#define WBGEN2_GEN_READ(reg, offset, size) (((reg) >> (offset)) & ((1<<(size))-1))
#define WBGEN2_SIGN_EXTEND(value, bits) (((value) & (1<<bits) ? ~((1<<(bits))-1): 0 ) | (value))
#endif
/* definitions for register: Syscon reset register */
/* definitions for field: Reset trigger in reg: Syscon reset register */
#define SYSC_RSTR_TRIG_MASK WBGEN2_GEN_MASK(0, 28)
#define SYSC_RSTR_TRIG_SHIFT 0
#define SYSC_RSTR_TRIG_W(value) WBGEN2_GEN_WRITE(value, 0, 28)
#define SYSC_RSTR_TRIG_R(reg) WBGEN2_GEN_READ(reg, 0, 28)
/* definitions for field: Reset line state value in reg: Syscon reset register */
#define SYSC_RSTR_RST WBGEN2_GEN_MASK(28, 1)
/* definitions for register: GPIO Set/Readback Register */
/* definitions for field: Status LED in reg: GPIO Set/Readback Register */
#define SYSC_GPSR_LED_STAT WBGEN2_GEN_MASK(0, 1)
/* definitions for field: Link LED in reg: GPIO Set/Readback Register */
#define SYSC_GPSR_LED_LINK WBGEN2_GEN_MASK(1, 1)
/* definitions for field: FMC I2C bitbanged SCL in reg: GPIO Set/Readback Register */
#define SYSC_GPSR_FMC_SCL WBGEN2_GEN_MASK(2, 1)
/* definitions for field: FMC I2C bitbanged SDA in reg: GPIO Set/Readback Register */
#define SYSC_GPSR_FMC_SDA WBGEN2_GEN_MASK(3, 1)
/* definitions for field: Network AP reset in reg: GPIO Set/Readback Register */
#define SYSC_GPSR_NET_RST WBGEN2_GEN_MASK(4, 1)
/* definitions for field: SPEC Pushbutton 1 state in reg: GPIO Set/Readback Register */
#define SYSC_GPSR_BTN1 WBGEN2_GEN_MASK(5, 1)
/* definitions for field: SPEC Pushbutton 2 state in reg: GPIO Set/Readback Register */
#define SYSC_GPSR_BTN2 WBGEN2_GEN_MASK(6, 1)
/* definitions for field: SFP detect (MOD_DEF0 signal) in reg: GPIO Set/Readback Register */
#define SYSC_GPSR_SFP_DET WBGEN2_GEN_MASK(7, 1)
/* definitions for field: SFP I2C bitbanged SCL in reg: GPIO Set/Readback Register */
#define SYSC_GPSR_SFP_SCL WBGEN2_GEN_MASK(8, 1)
/* definitions for field: SFP I2C bitbanged SDA in reg: GPIO Set/Readback Register */
#define SYSC_GPSR_SFP_SDA WBGEN2_GEN_MASK(9, 1)
/* definitions for register: GPIO Clear Register */
/* definitions for field: Status LED in reg: GPIO Clear Register */
#define SYSC_GPCR_LED_STAT WBGEN2_GEN_MASK(0, 1)
/* definitions for field: Link LED in reg: GPIO Clear Register */
#define SYSC_GPCR_LED_LINK WBGEN2_GEN_MASK(1, 1)
/* definitions for field: FMC I2C bitbanged SCL in reg: GPIO Clear Register */
#define SYSC_GPCR_FMC_SCL WBGEN2_GEN_MASK(2, 1)
/* definitions for field: FMC I2C bitbanged SDA in reg: GPIO Clear Register */
#define SYSC_GPCR_FMC_SDA WBGEN2_GEN_MASK(3, 1)
/* definitions for field: SFP I2C bitbanged SCL in reg: GPIO Clear Register */
#define SYSC_GPCR_SFP_SCL WBGEN2_GEN_MASK(8, 1)
/* definitions for field: FMC I2C bitbanged SDA in reg: GPIO Clear Register */
#define SYSC_GPCR_SFP_SDA WBGEN2_GEN_MASK(9, 1)
/* definitions for register: Hardware Feature Register */
/* definitions for field: Memory size in reg: Hardware Feature Register */
#define SYSC_HWFR_MEMSIZE_MASK WBGEN2_GEN_MASK(0, 4)
#define SYSC_HWFR_MEMSIZE_SHIFT 0
#define SYSC_HWFR_MEMSIZE_W(value) WBGEN2_GEN_WRITE(value, 0, 4)
#define SYSC_HWFR_MEMSIZE_R(reg) WBGEN2_GEN_READ(reg, 0, 4)
/* definitions for register: Timer Control Register */
/* definitions for field: Timer Divider in reg: Timer Control Register */
#define SYSC_TCR_TDIV_MASK WBGEN2_GEN_MASK(0, 12)
#define SYSC_TCR_TDIV_SHIFT 0
#define SYSC_TCR_TDIV_W(value) WBGEN2_GEN_WRITE(value, 0, 12)
#define SYSC_TCR_TDIV_R(reg) WBGEN2_GEN_READ(reg, 0, 12)
/* definitions for field: Timer Enable in reg: Timer Control Register */
#define SYSC_TCR_ENABLE WBGEN2_GEN_MASK(31, 1)
/* definitions for register: Timer Counter Value Register */
/* [0x0]: REG Syscon reset register */
#define SYSC_REG_RSTR 0x00000000
/* [0x4]: REG GPIO Set/Readback Register */
#define SYSC_REG_GPSR 0x00000004
/* [0x8]: REG GPIO Clear Register */
#define SYSC_REG_GPCR 0x00000008
/* [0xc]: REG Hardware Feature Register */
#define SYSC_REG_HWFR 0x0000000c
/* [0x10]: REG Timer Control Register */
#define SYSC_REG_TCR 0x00000010
/* [0x14]: REG Timer Counter Value Register */
#define SYSC_REG_TVR 0x00000014
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment