Commit 7ec28c04 authored by Lucas Russo's avatar Lucas Russo

emb-sw/*: various modifications to the spi, i2c, onewire interfaces

parent f2cb30f4
......@@ -52,6 +52,26 @@
#define OETH_RX_BUFF_SIZE BUFF_SIZE
#define OETH_TX_BUFF_SIZE BUFF_SIZE
/****************************/
/* IDs */
/****************************/
/*
* IDs of general components
*/
#define GEN_LED_GPIO_ID 0
#define GEN_BUTTON_GPIO_ID 1
/*
* IDs of some FMC516 components
*/
#define FMC516_SYS_I2C_ID 0
#define FMC516_VCXO_I2C_ID 1
#define FMC516_ISLA216P25_SPI_ID 0
#define FMC516_LMK02000_SPI_ID 1
#define FMC516_DS2431_OWR_ID 0
#define FMC516_DS2432_OWR_ID 1
int board_init();
int board_update();
......
This diff is collapsed.
This diff is collapsed.
#include "board.h"
#include "inttypes.h"
#include "fmc150.h"
// Delay in number of processor clock cycles
#define SPI_DELAY 300
#define SPI_BUSY_MAX_TRIES 10
/* Register values for cdce72010 */
uint32_t cdce72010_regs[CDCE72010_NUMREGS] = {
//internal reference clock. Default config.
/*0x683C0310,
0x68000021,
0x83040002,
0x68000003,
0xE9800004,
0x68000005,
0x68000006,
0x83800017,
0x68000098,
0x68050CC9,
0x05FC270A,
0x0280044B,
0x0000180C*/
//3.84MHz ext clock. Does not lock.
/*0x682C0290,
0x68840041,
0x83840002,
0x68400003,
0xE9800004,
0x68000005,
0x68000006,
0x83800017,
0x68000098,
0x68000C49,
0x0BFC02FA,
0x8000050B,
0x0000180C*/
//61.44MHz ext clock. LOCK.
/*0x682C0290,
0x68840041,
0x83040002,
0x68400003,
0xE9800004,
0x68000005,
0x68000006,
0x83800017,
0x68000098,
0x68000049,
0x0024009A,
0x8000050B,
0x0000180C*/
//7.68MHz ext clock. Lock.
// Use with Libera RF & clock generator. RF = 291.840MHz, MCf = 7.680MHz, H = 38
// DDS = 3.072MHz -> Phase increment = 2048d
0x682C0290,
0x68840041,
0x83860002, //divide by 5
//0x83840002, //divide by 4
0x68400003,
0xE9800004,
0x68000005,
0x68000006,
0x83800017,
0x68000098,
0x68000049,
0x007C003A, // PFD_freq = 1.92MHz
0x8000050B,
//0x0000180C
//15.36MHz ext clock.
/*0x682C0290,
0x68840041,
0x83840002,
/*;83020002,;divide by 6
;83860002, ;divide by 5
;83800002, ;divide by 2
;83840002, ;divide by 4
;83060002, ;divide by 8
0x68400003,
0xE9800004,
0x68000005,
0x68000006,
0x83800017,
0x68000098,
0x68000049,
0x003C003A,
0x8000050B,
0x0000180C*/
//9.6MHz ext clock.
/*0x682C0290,
0x68840041,
0x83860002,//;divide by 5
0x68400003,
0xE9800004,
0x68000005,
0x68000006,
0x83800017,
0x68000098,
0x68000049,
0x007C004A,
0x8000050B,
0x0000180C*/
//9.250MHz ext clock. No lock
/*0x682C0290,
0x68840041,
0x83860002,
0x68400003,
0xE9800004,
0x68000005,
0x68000006,
0x83800017,
0x68000098,
0x68000049,
0x5FFC39CA,
//0x8000390B, // DIvide by 32
0x8000050B, //Divide by 8
0x0000180C*/
//10.803 (originally 10.803 actually) ext clock.
//Could it be something related to the lock window? see cdce72010 datasheet
/*0x682C0290,
0x68840041,
0x83840002,
0x68400003,
0xE9800004,
0x68000005,
0x68000006,
0x83800017,
0x68000098,
0x68000049,
0x03FC02CA,
0x8000050B,
0x0000180C*/
};
// Global FMC150 handler.
fmc150_t *fmc150;
int fmc150_init(void)
{
if (fmc150_devl->devices){
// get first gpio device found
fmc150 = (fmc150_t *)fmc150_devl->devices->base;//BASE_FMC150;
return 0;
}
return -1;
}
void update_fmc150_adc_delay(uint8_t adc_strobe_delay, uint8_t adc_cha_delay, uint8_t adc_chb_delay)
{
fmc150->ADC_DLY = (uint32_t) FMC150_ADC_DLY_STR_W(adc_strobe_delay) +
(uint32_t) FMC150_ADC_DLY_CHA_W(adc_cha_delay) +
(uint32_t) FMC150_ADC_DLY_CHB_W(adc_chb_delay);
fmc150->FLGS_PULSE = 0x1;
}
/* Check if 150 is busy */
int fmc150_spi_busy(void)
{
return fmc150->FLGS_OUT & FMC150_FLGS_OUT_SPI_BUSY;
}
int read_fmc150_register(uint32_t cs, uint32_t addr, uint32_t* data)
{
// Test if SPI interface is busy
if (fmc150_spi_busy())
return -1;
// Set bit to read from SPI
fmc150->FLGS_IN |= FMC150_FLGS_IN_SPI_RW;
// Set address to read from
fmc150->ADDR = addr;
// Toggle chipselect
fmc150->CS ^= cs;
// Sleeps SPI_DELAY*4 processor cycles. Is that enough? */
delay(SPI_DELAY);
// Get data from register
*data = fmc150->DATA_OUT;
return 0;
}
int write_fmc150_register(uint32_t cs, uint32_t addr, uint32_t data)
{
// Test if SPI interface is busy
if (fmc150_spi_busy())
return -1;
// Set bit to write from SPI
fmc150->FLGS_IN &= ~FMC150_FLGS_IN_SPI_RW;
// Set address to write to
fmc150->ADDR = addr;
// Set value to write to
fmc150->DATA_IN = data;
// Toggle chipselect
fmc150->CS ^= cs;
return 0;
}
static int fmc150_spi_busy_loop()
{
int i = 0;
for(i = 0; i < SPI_BUSY_MAX_TRIES; ++i){
if(!fmc150_spi_busy())
break;
delay(SPI_DELAY);
}
// return error (-1) if max tries reached
if (i == SPI_BUSY_MAX_TRIES)
return -1;
else
return 0;
}
// TODO: implement a register structure and associate permissions
// (RO, RW, WO)
int init_cdce72010()
{
int i;
uint32_t reg;
/* Write regs to cdce72010 statically */
// Do not write the last register, as it is Read-only
for(i = 0; i < CDCE72010_NUMREGS; ++i){
if(fmc150_spi_busy_loop() < 0){
pp_printf("init_cdce72010: max SPI tries excceded!\n");
return -1;
}
pp_printf("init_cdce72010: writing data: 0x%x at register addr: 0x%x\n", cdce72010_regs[i], i);
// The CDCE72010 chip word addressed , hence the "i" addressing index
write_fmc150_register(FMC150_CS_CDCE72010, i, cdce72010_regs[i]);
// Do a write-read cycle in order to ensure that we wrote the correct value
delay(SPI_DELAY);
if(fmc150_spi_busy_loop() < 0){
pp_printf("init_cdce72010: max SPI tries excceded!\n");
return -1;
}
// The CDCE72010 chip word addressed , hence the "i" addressing index
read_fmc150_register(FMC150_CS_CDCE72010, i, &reg);
pp_printf("init_cdce72010: reading data: 0x%x at register addr: 0x%x\n", reg, i);
// Check if value written is the same of the value just read
if(cdce72010_regs[i] != reg){
pp_printf("init_cdce72010: error: data written (0x%x) != data read (0x%x)!\n",
cdce72010_regs[i], reg);
return -1;
}
delay(SPI_DELAY);
}
return 0;
}
......@@ -6,88 +6,161 @@
#include "board.h" // Board definitions: SPI device structure
#include "i2c.h" // SPI device functions
#include "memmgr.h" // malloc and free clones
#include "debug_print.h"
// Global SPI handler.
i2c_t **i2c;
int i2c_init(void)
{
int i;
struct dev_node *dev_p = 0;
if (!i2c_devl->devices)
return -1;
// get all base addresses
i2c = (i2c_t **) memmgr_alloc(sizeof(i2c)*i2c_devl->size);
//dbg_print("> i2c size: %d\n", i2c_devl->size);
for (i = 0, dev_p = i2c_devl->devices; i < i2c_devl->size;
++i, dev_p = dev_p->next) {
i2c[i] = (i2c_t *) dev_p->base;
// Default configuration
int i;
struct dev_node *dev_p = 0;
if (!i2c_devl->devices)
return -1;
// get all base addresses
i2c = (i2c_t **) memmgr_alloc(sizeof(i2c)*i2c_devl->size);
//dbg_print("> i2c size: %d\n", i2c_devl->size);
for (i = 0, dev_p = i2c_devl->devices; i < i2c_devl->size;
++i, dev_p = dev_p->next) {
i2c[i] = (i2c_t *) dev_p->base;
// Default configuration
i2c[i]->CTR = 0;
i2c[i]->PREL = DEFAULT_I2C_PRESCALER & 0xFF;
i2c[i]->PREH = (DEFAULT_I2C_PRESCALER >> 8) & 0xFF;
// Enbale core
i2c[i]->CTR = I2C_CTR_EN;
// Check if the core is indeed enabled
if (!(i2c[i]->CTR & I2C_CTR_EN))
return -1;
//dbg_print("> i2c addr[%d]: %08X\n", i, i2c[i]);
}
//i2c = (i2c_t *)i2c_devl->devices->base;;
return 0;
}
//dbg_print("> i2c addr[%d]: %08X\n", i, i2c[i]);
}
//i2c = (i2c_t *)i2c_devl->devices->base;;
return 0;
void i2c_exit(void)
{
memmgr_free(i2c);
}
void spi_exit(void)
int oc_i2c_poll(unsigned int id)
{
memmgr_free(spi);
memmgr_free(spi_config);
return (i2c[id]->SR & I2C_SR_TIP) ? 1 : 0;
}
int oc_spi_poll(unsigned int id)
int oc_i2c_start(unsigned int id, int addr, int read)
{
return spi[id]->CTRL & SPI_CTRL_BSY;
uint32_t i2c_addr;
// shift addr bits as the last one represents rw bit (read = 1, write = 0)
i2c_addr = I2C_ADDR(addr);
if (read == 1)
i2c_addr |= I2C_TXR_READ;
i2c[id]->TXR = i2c_addr;
// Start transaction. Generates repeated start condition and write to slave
i2c[id]->CR = I2C_CR_STA | I2C_CR_WR;
// Wait for completion
while(oc_i2c_poll(id));
// Check if we received an ACK from slave
if (i2c[id]->SR & I2C_SR_RXACK) {
dbg_print("> no ack received from slave at addr 0X%2X\n", addr);
return -1;
}
return 0;
}
void oc_spi_config(unsigned int id, int ass, int rx_neg, int tx_neg,
int lsb, int ie)
int oc_i2c_rx(unsigned int id, uint32_t *out, int last)
{
spi_config[id] = 0;
uint32_t i2c_cmd;
i2c_cmd = I2C_CR_RD;
// Generates STOP condition and send NACK on completion
if(last)
i2c_cmd |= I2C_CR_STO | I2C_CR_ACK;
if(ass)
spi_config[id] |= SPI_CTRL_ASS;
i2c[id]->CR = i2c_cmd;
if(tx_neg)
spi_config[id] |= SPI_CTRL_TXNEG;
// Wait for completion
while(oc_i2c_poll(id));
if(rx_neg)
spi_config[id] |= SPI_CTRL_RXNEG;
// Check if we received an ACK from slave
if (i2c[id]->SR & I2C_SR_RXACK) {
dbg_print("> no ack received from slave at rx transaction\n");
return -1;
}
if(lsb)
spi_config[id] |= SPI_CTRL_LSB;
*out = i2c[id]->RXR & 0xFF;
if(ie)
spi_config[id] |= SPI_CTRL_IE;
return 0;
}
int oc_spi_txrx(unsigned int id, int ss, int nbits, uint32_t in, uint32_t *out)
int oc_i2c_tx(unsigned int id, uint32_t in, int last)
{
uint32_t rval;
uint32_t i2c_cmd;
// Avoid breaking the code when just issuing a read command (out can be null)
if (!out)
out = &rval;
// We don't really care about sizes here as only the 8 LSB
// are effectivelly written to the I2C core and no harm is inflicted
// by doing this.
i2c[id]->TXR = in;
// Write configuration to SPI core
spi[id]->CTRL = spi_config[id] | SPI_CTRL_CHAR_LEN(nbits);
// Write command
i2c_cmd = I2C_CR_WR;
// Transmit to core
spi[id]->TX0 = in;
// Generates STOP condition
if(last)
i2c_cmd |= I2C_CR_STO;
// Receive from core
spi[id]->SS = (1 << ss);
spi[id]->CTRL |= SPI_CTRL_GO_BSY;
i2c[id]->CR = i2c_cmd;
while(oc_spi_poll(id));
// Wait for completion
while(oc_i2c_poll(id));
*out = spi[id]->RX0;
// Check if we received an ACK from slave
if (i2c[id]->SR & I2C_SR_RXACK) {
dbg_print("> no ack received from slave at tx transaction\n");
return -1;
}
return 0;
return 0;
}
// This just prints if devices have been found at specified addresses
int oc_i2c_scan(unsigned int id)
{
int i;
uint32_t i2c_addr;
for (i = 0; i < 128; ++i) {
i2c_addr = I2C_ADDR(i) | I2C_TXR_READ;
i2c[id]->TXR = i2c_addr;
i2c[id]->CR = I2C_CR_STA | I2C_CR_WR;
// Wait for completion
while(oc_i2c_poll(id));
// Check if we received an ACK from slave
if (!(i2c[id]->SR & I2C_SR_RXACK)) {
dbg_print("> device found at addr 0X%02X\n", i);
i2c[id]->TXR = 0;
i2c[id]->CR = I2C_CR_STO | I2C_CR_WR;
while(oc_i2c_poll(id));
}
}
return 0;
}
......@@ -8,88 +8,117 @@
#include "memmgr.h" // malloc and free clones
// Global SPI handler.
onewire_t **onewire;
owr_t **owr;
int onewire_init(void)
int owr_init(void)
{
int i;
struct dev_node *dev_p = 0;
if (!spi_devl->devices)
return -1;
// get all base addresses
spi = (spi_t **) memmgr_alloc(sizeof(spi)*spi_devl->size);
spi_config = (uint32_t *) memmgr_alloc(sizeof(spi_config)*spi_devl->size);
//dbg_print("> spi size: %d\n", spi_devl->size);
for (i = 0, dev_p = spi_devl->devices; i < spi_devl->size;
++i, dev_p = dev_p->next) {
spi[i] = (spi_t *) dev_p->base;
// Default configuration
spi[i]->DIVIDER = DEFAULT_SPI_DIVIDER & SPI_DIV_MASK;
spi[i]->CTRL = SPI_CTRL_ASS | SPI_CTRL_TXNEG;
//dbg_print("> spi addr[%d]: %08X\n", i, spi[i]);
}
//spi = (spi_t *)spi_devl->devices->base;;
return 0;
int i;
struct dev_node *dev_p = 0;
if (!owr_devl->devices)
return -1;
// get all base addresses
owr = (owr_t **) memmgr_alloc(sizeof(owr)*owr_devl->size);
//dbg_print("> owr size: %d\n", owr_devl->size);
for (i = 0, dev_p = owr_devl->devices; i < owr_devl->size;
++i, dev_p = dev_p->next) {
owr[i] = (owr_t *) dev_p->base;
// Default configuration
owr[i]->CDR = (OWR_CDR_NOR(DEFAULT_OWR_DIVIDER_NOR)) |
(OWR_CDR_OVD(DEFAULT_OWR_DIVIDER_OVD));
//dbg_print("> owr addr[%d]: %08X\n", i, owr[i]);
}
//owr = (owr_t *)owr_devl->devices->base;
return 0;
}
void spi_exit(void)
void owr_exit(void)
{
memmgr_free(spi);
memmgr_free(spi_config);
memmgr_free(owr);
}
int oc_spi_poll(unsigned int id)
int oc_owr_poll(unsigned int id)
{
return spi[id]->CTRL & SPI_CTRL_BSY;
return (owr[id]->CSR & OWR_CSR_CYC) ? 1 : 0;
}
void oc_spi_config(unsigned int id, int ass, int rx_neg, int tx_neg,
int lsb, int ie)
int oc_owr_reset(unsigned int id, int port)
{
spi_config[id] = 0;
// Request reset
owr[id]->CSR = OWR_CSR_SEL(port) | OWR_CSR_CYC | OWR_CSR_RST;
if(ass)
spi_config[id] |= SPI_CTRL_ASS;
// Wait for completion
while(oc_owr_poll(id));
if(tx_neg)
spi_config[id] |= SPI_CTRL_TXNEG;
// Read presence status. 0 -> presence detected, 1 -> presence NOT detected
//return (owr[id]->CSR & OWR_CSR_DAT) ? 0 : 1;
return (~(owr[id]->CSR) & OWR_CSR_DAT);
}
if(rx_neg)
spi_config[id] |= SPI_CTRL_RXNEG;
int oc_owr_slot(unsigned int id, int port, uint32_t in_bit, uint32_t *out_bit)
{
uint32_t rval;
if(lsb)
spi_config[id] |= SPI_CTRL_LSB;
// Avoid breaking the code when just issuing a read command (out_bit can be null).
// This is the case when in_bit = 0 (write 0 slot), but not for in_bit = 1
// (write 1 and/or read slot)
if (!out_bit)
out_bit = &rval;
if(ie)
spi_config[id] |= SPI_CTRL_IE;
}
owr[id]->CSR = OWR_CSR_SEL(port) | OWR_CSR_CYC | (in_bit & OWR_CSR_DAT);
int oc_spi_txrx(unsigned int id, int ss, int nbits, uint32_t in, uint32_t *out)
{
uint32_t rval;
// Wait for completion
while(oc_owr_poll(id));
// Avoid breaking the code when just issuing a read command (out can be null)
if (!out)
out = &rval;
*out_bit = owr[id]->CSR & OWR_CSR_DAT;
// Write configuration to SPI core
spi[id]->CTRL = spi_config[id] | SPI_CTRL_CHAR_LEN(nbits);
return 0;
}
// Transmit to core
spi[id]->TX0 = in;
int oc_owr_read_bit(unsigned int id, int port, uint32_t *out_bit)
{
return oc_owr_slot(id, port, 0x1, out_bit);
}
// Receive from core
spi[id]->SS = (1 << ss);
spi[id]->CTRL |= SPI_CTRL_GO_BSY;
int oc_owr_write_bit(unsigned int id, int port, uint32_t in_bit, uint32_t *out_bit)
{
return oc_owr_slot(id, port, in_bit, out_bit);
}
int read_byte(unsigned int id, int port, uint32_t *out_byte)
{
int i;
uint32_t owr_data = 0;
uint32_t owr_bit = 0;
while(oc_spi_poll(id));
for (i = 0; i < 8; ++i) {
oc_owr_read_bit(id, port, &owr_bit);
owr_data |= owr_bit << i;
}
*out = spi[id]->RX0;
*out_byte = owr_data;
return 0;
return 0;
}
int write_byte(unsigned int id, int port, uint32_t in_byte)
{
int i;
uint32_t owr_data = 0;
uint32_t owr_byte = in_byte;
uint32_t owr_bit;
for (i = 0; i < 8; ++i) {
oc_owr_write_bit(id, port, owr_byte & 0x1, &owr_bit);
owr_data |= owr_bit << i;
owr_byte >> 1;
}
if(owr_data == in_byte)
return 0;
else
return -1;
}
......@@ -9,197 +9,197 @@
#define SDB_EMPTY 0xFF
typedef struct pair64 {
uint32_t high;
uint32_t low;
uint32_t high;
uint32_t low;
} pair64_t;
struct sdb_empty {
int8_t reserved[63];
uint8_t record_type;
int8_t reserved[63];
uint8_t record_type;
};
struct sdb_product {
pair64_t vendor_id;
uint32_t device_id;
uint32_t version;
uint32_t date;
int8_t name[19];
uint8_t record_type;
pair64_t vendor_id;
uint32_t device_id;
uint32_t version;
uint32_t date;
int8_t name[19];
uint8_t record_type;
};
struct sdb_component {
pair64_t addr_first;
pair64_t addr_last;
struct sdb_product product;
pair64_t addr_first;
pair64_t addr_last;
struct sdb_product product;
};
struct sdb_device {
uint16_t abi_class;
uint8_t abi_ver_major;
uint8_t abi_ver_minor;
uint32_t bus_specific;
struct sdb_component sdb_component;
uint16_t abi_class;
uint8_t abi_ver_major;
uint8_t abi_ver_minor;
uint32_t bus_specific;
struct sdb_component sdb_component;
};
struct sdb_bridge {
pair64_t sdb_child;
struct sdb_component sdb_component;
pair64_t sdb_child;
struct sdb_component sdb_component;
};
struct sdb_interconnect {
uint32_t sdb_magic;
uint16_t sdb_records;
uint8_t sdb_version;
uint8_t sdb_bus_type;
struct sdb_component sdb_component;
uint32_t sdb_magic;
uint16_t sdb_records;
uint8_t sdb_version;
uint8_t sdb_bus_type;
struct sdb_component sdb_component;
};
typedef union sdb_record {
struct sdb_empty empty;
struct sdb_device device;
struct sdb_bridge bridge;
struct sdb_interconnect interconnect;
struct sdb_empty empty;
struct sdb_device device;
struct sdb_bridge bridge;
struct sdb_interconnect interconnect;
} sdb_record_t;
static unsigned char *find_device_deep(unsigned int base, unsigned int sdb,
unsigned int devid)
unsigned int devid)
{
sdb_record_t *record = (sdb_record_t *) sdb;
int records = record->interconnect.sdb_records;
int i;
for (i = 0; i < records; ++i, ++record) {
if (record->empty.record_type == SDB_BRIDGE) {
unsigned char *out =
find_device_deep(base +
record->bridge.sdb_component.
addr_first.low,
record->bridge.sdb_child.low,
devid);
if (out)
return out;
}
if (record->empty.record_type == SDB_DEVICE &&
record->device.sdb_component.product.device_id == devid) {
break;
}
}
if (i == records)
return 0;
return (unsigned char *)(base +
record->device.sdb_component.addr_first.low);
sdb_record_t *record = (sdb_record_t *) sdb;
int records = record->interconnect.sdb_records;
int i;
for (i = 0; i < records; ++i, ++record) {
if (record->empty.record_type == SDB_BRIDGE) {
unsigned char *out =
find_device_deep(base +
record->bridge.sdb_component.
addr_first.low,
record->bridge.sdb_child.low,
devid);
if (out)
return out;
}
if (record->empty.record_type == SDB_DEVICE &&
record->device.sdb_component.product.device_id == devid) {
break;
}
}
if (i == records)
return 0;
return (unsigned char *)(base +
record->device.sdb_component.addr_first.low);
}
static void find_device_deep_all_rec(struct dev_node **dev, unsigned int *size,
unsigned int base, unsigned int sdb, unsigned int devid)
unsigned int base, unsigned int sdb, unsigned int devid)
{
sdb_record_t *record = (sdb_record_t *) sdb;
int records = record->interconnect.sdb_records;
int i;
for (i = 0; i < records; ++i, ++record) {
if (record->empty.record_type == SDB_BRIDGE) {
find_device_deep_all_rec(dev, size, base +
record->bridge.sdb_component.addr_first.low,
record->bridge.sdb_child.low,
devid);
}
if (record->empty.record_type == SDB_DEVICE &&
record->device.sdb_component.product.device_id == devid) {
// Alloc new node device
*dev = (struct dev_node *)memmgr_alloc(sizeof(struct dev_node));
(*dev)->base = (unsigned char *)(base +
record->device.sdb_component.addr_first.low);
// Ensure a null pointer on end of list
(*dev)->next = 0;
// Pass new node address
dev = &(*dev)->next;
(*size)++;
}
}
sdb_record_t *record = (sdb_record_t *) sdb;
int records = record->interconnect.sdb_records;
int i;
for (i = 0; i < records; ++i, ++record) {
if (record->empty.record_type == SDB_BRIDGE) {
find_device_deep_all_rec(dev, size, base +
record->bridge.sdb_component.addr_first.low,
record->bridge.sdb_child.low,
devid);
}
if (record->empty.record_type == SDB_DEVICE &&
record->device.sdb_component.product.device_id == devid) {
// Alloc new node device
*dev = (struct dev_node *)memmgr_alloc(sizeof(struct dev_node));
(*dev)->base = (unsigned char *)(base +
record->device.sdb_component.addr_first.low);
// Ensure a null pointer on end of list
(*dev)->next = 0;
// Pass new node address
dev = &(*dev)->next;
(*size)++;
}
}
}
static struct dev_list *find_device_deep_all(unsigned int base, unsigned int sdb,
unsigned int devid)
unsigned int devid)
{
// Device structure list
struct dev_list *dev = (struct dev_list *)memmgr_alloc(sizeof(struct dev_list));
// Device structure list
struct dev_list *dev = (struct dev_list *)memmgr_alloc(sizeof(struct dev_list));
// Initialize structure
dev->devid = devid;
dev->size = 0;
dev->devices = 0;
// Initialize structure
dev->devid = devid;
dev->size = 0;
dev->devices = 0;
// Fill device list with the appropriate nodes
find_device_deep_all_rec(&(dev->devices), &(dev->size), base, sdb, devid);
// Fill device list with the appropriate nodes
find_device_deep_all_rec(&(dev->devices), &(dev->size), base, sdb, devid);
return dev;
return dev;
}
static void print_devices_deep(unsigned int base, unsigned int sdb)
{
sdb_record_t *record = (sdb_record_t *) sdb;
int records = record->interconnect.sdb_records;
int i;
char buf[20];
for (i = 0; i < records; ++i, ++record) {
if (record->empty.record_type == SDB_BRIDGE)
print_devices_deep(base +
record->bridge.sdb_component.
addr_first.low,
record->bridge.sdb_child.low);
if (record->empty.record_type != SDB_DEVICE)
continue;
memcpy(buf, record->device.sdb_component.product.name, 19);
buf[19] = 0;
pp_printf("%8x:%8x 0x%8x %s\n",
record->device.sdb_component.product.vendor_id.low,
record->device.sdb_component.product.device_id,
base + record->device.sdb_component.addr_first.low,
buf);
}
sdb_record_t *record = (sdb_record_t *) sdb;
int records = record->interconnect.sdb_records;
int i;
char buf[20];
for (i = 0; i < records; ++i, ++record) {
if (record->empty.record_type == SDB_BRIDGE)
print_devices_deep(base +
record->bridge.sdb_component.
addr_first.low,
record->bridge.sdb_child.low);
if (record->empty.record_type != SDB_DEVICE)
continue;
memcpy(buf, record->device.sdb_component.product.name, 19);
buf[19] = 0;
pp_printf("%8x:%8x 0x%8x %s\n",
record->device.sdb_component.product.vendor_id.low,
record->device.sdb_component.product.device_id,
base + record->device.sdb_component.addr_first.low,
buf);
}
}
static unsigned char *find_device(unsigned int devid)
{
return find_device_deep(0, SDB_ADDRESS, devid);
return find_device_deep(0, SDB_ADDRESS, devid);
}
static struct dev_list *find_device_all(unsigned int devid)
{
return find_device_deep_all(0, SDB_ADDRESS, devid);
return find_device_deep_all(0, SDB_ADDRESS, devid);
}
void sdb_print_devices(void)
{
pp_printf("-------------------------------------------\n");
pp_printf("| SDB memory map |\n");
pp_printf("-------------------------------------------\n\n");
print_devices_deep(0, SDB_ADDRESS);
pp_printf("-------------------------------------------\n");
pp_printf("| SDB memory map |\n");
pp_printf("-------------------------------------------\n\n");
print_devices_deep(0, SDB_ADDRESS);
}
void sdb_find_devices(void)
{
// Enumerate devices
// get the second device form this list. Just for testing! with the etherbone
// core
mem_devl = find_device_all(0x66cfeb52);
dma_devl = find_device_all(0xcababa56);
ethmac_devl = find_device_all(0xf8cfeb16);
ethmac_adapt_devl = find_device_all(0x2ff9a28e);
ebone_cfg_devl = find_device_all(0x68202b22);
fmc516_devl = find_device_all(0x27b95341);
spi_devl = find_device_all(0x40286417);
i2c_devl = find_device_all(0x97b6323d);
one_wire_devl = find_device_all(0x525fbb09);
uart_devl = find_device_all(0x8a5719ae);
gpio_devl = find_device_all(0x35aa6b95);
tics_devl = find_device_all(0xfdafb9dd);
// Enumerate devices
// get the second device form this list. Just for testing! with the etherbone
// core
mem_devl = find_device_all(0x66cfeb52);
dma_devl = find_device_all(0xcababa56);
ethmac_devl = find_device_all(0xf8cfeb16);
ethmac_adapt_devl = find_device_all(0x2ff9a28e);
ebone_cfg_devl = find_device_all(0x68202b22);
fmc516_devl = find_device_all(0x27b95341);
spi_devl = find_device_all(0x40286417);
i2c_devl = find_device_all(0x97b6323d);
owr_devl = find_device_all(0x525fbb09);
uart_devl = find_device_all(0x8a5719ae);
gpio_devl = find_device_all(0x35aa6b95);
tics_devl = find_device_all(0xfdafb9dd);
}
......@@ -48,6 +48,11 @@ int oc_spi_poll(unsigned int id)
return spi[id]->CTRL & SPI_CTRL_BSY;
}
int oc_spi_three_mode(unsigned int id)
{
return spi[id]->CTRL & SPI_CTRL_THREE_WIRE;
}
void oc_spi_config(unsigned int id, int ass, int rx_neg, int tx_neg,
int lsb, int ie)
{
......@@ -69,7 +74,45 @@ void oc_spi_config(unsigned int id, int ass, int rx_neg, int tx_neg,
spi_config[id] |= SPI_CTRL_IE;
}
int oc_spi_txrx(unsigned int id, int ss, int nbits, uint32_t in, uint32_t *out)
// For use only with spi three-wire mode
int oc_spi_three_mode_tx(unsigned int id, int ss, int nbits, uint32_t in)
{
// Write configuration to SPI core. SPI_CTRL_DIR = 1
spi[id]->CTRL = spi_config[id] | SPI_CTRL_DIR | SPI_CTRL_CHAR_LEN(nbits);
// Transmit to core
spi[id]->TX0 = in;
spi[id]->SS = (1 << ss);
// Initiate transaction
spi[id]->CTRL |= SPI_CTRL_GO_BSY;
// Wait for completion
while(oc_spi_poll(id));
return 0;
}
// For use only with spi three-wire mode
int oc_spi_three_mode_rx(unsigned int id, int ss, int nbits, uint32_t *out)
{
// Write configuration to SPI core. SPI_CTRL_DIR = 0
spi[id]->CTRL = spi_config[id] | SPI_CTRL_CHAR_LEN(nbits);
spi[id]->SS = (1 << ss);
// Initiate transaction
spi[id]->CTRL |= SPI_CTRL_GO_BSY;
// Wait for reception
while(oc_spi_poll(id));
*out = spi[id]->RX0;
return 0;
}
int oc_spi_txrx(unsigned int id, int ss, int nbits, int write, uint32_t in, uint32_t *out)
{
uint32_t rval;
......@@ -93,4 +136,3 @@ int oc_spi_txrx(unsigned int id, int ss, int nbits, uint32_t in, uint32_t *out)
return 0;
}
../boards/ml605/board.h
\ No newline at end of file
/*
* Copyright (C) 2012 LNLS (www.lnls.br)
* Author: Lucas Russo <lucas.russo@lnls.br>
*
* Released according to the GNU GPL, version 2 or any later version.
*/
#ifndef _DEBUG_PRINT_
#define _DEBUG_PRINT_
#include <stdarg.h>
#include "pp-printf.h"
void debug_print(const char *fmt, ...);
//__attribute__((format(printf,1,2)));
void debug_print2(const char *fmt, const char *data, int len);
#ifdef DEBUG_PRINT
#define dbg_print(fmt, ...) \
pp_printf("%s (%d): "fmt, __FILE__, __LINE__, ##__VA_ARGS__)
#define dbg_print2(fmt, data, len) \
debug_print2(fmt, data, len)
#else
#define dbg_print(...)
#define dbg_print2(fmt, data, len)
#endif
#endif
......@@ -8,20 +8,20 @@
//#define NUM_GPIO_DEVS 2
/* Simple device nodes for supporting various instances
of the same component */
of the same component */
struct dev_node{
//int i;
unsigned char *base;
//unsigned char *end;
//struct dev_node *parent;
struct dev_node *next;
//int i;
unsigned char *base;
//unsigned char *end;
//struct dev_node *parent;
struct dev_node *next;
};
/* List of devices of the same kind (same devid).*/
struct dev_list{
unsigned int devid;
unsigned int size;
struct dev_node *devices;
unsigned int devid;
unsigned int size;
struct dev_node *devices;
};
/* Automate the address peripheral discover. use SDB */
......@@ -39,7 +39,7 @@ struct dev_list *ebone_cfg_devl;
struct dev_list *fmc516_devl;
struct dev_list *spi_devl;
struct dev_list *i2c_devl;
struct dev_list *one_wire_devl;
struct dev_list *owr_devl;
// Peripheral components
struct dev_list *uart_devl;
......
......@@ -20,6 +20,7 @@
#define I2C_SR 0x00000010
#define I2C_CTR_EN (1<<7)
#define I2C_TXR_READ (1<<0)
#define I2C_CR_STA (1<<7)
#define I2C_CR_STO (1<<6)
#define I2C_CR_RD (1<<5)
......@@ -28,14 +29,16 @@
#define I2C_SR_RXACK (1<<7)
#define I2C_SR_TIP (1<<1)
#define I2C_ADDR(x) (((x) << 1) & 0xff)
PACKED struct I2C_WB {
uint32_t PREL;
uint32_t PREH;
uint32_t CTR;
uint32_t TXR;
uint32_t RXR;
uint32_t CR;
uint32_t SR;
uint32_t PREL;
uint32_t PREH;
uint32_t CTR;
uint32_t TXR;
uint32_t RXR;
uint32_t CR;
uint32_t SR;
};
#endif
#ifndef __ONEWIRE_REGDEFS_WB
#define __ONEWIRE_REGDEFS_WB
#ifndef __OWR_REGDEFS_WB
#define __OWR_REGDEFS_WB
#include <inttypes.h>
......@@ -11,31 +11,36 @@
// OpenCores 1-wire registers description
#define ONEWIRE_CSR 0x00000000
#define ONEWIRE_CDR 0x00000004
#define OWR_CSR 0x00000000
#define OWR_CDR 0x00000004
#define ONEWIRE_CSR_DAT (1<<0)
#define ONEWIRE_CSR_RST (1<<1)
#define ONEWIRE_CSR_OVD (1<<2)
#define ONEWIRE_CSR_CYC (1<<3)
#define ONEWIRE_CSR_PWR (1<<4)
#define ONEWIRE_CSR_IRQ (1<<6)
#define ONEWIRE_CSR_IEN (1<<7)
#define OWR_CSR_DAT (1<<0)
#define OWR_CSR_RST (1<<1)
#define OWR_CSR_OVD (1<<2)
#define OWR_CSR_CYC (1<<3)
#define OWR_CSR_PWR (1<<4)
#define OWR_CSR_IRQ (1<<6)
#define OWR_CSR_IEN (1<<7)
#define ONEWIRE_CSR_SEL_OFS 8
#define ONEWIRE_CSR_SEL (0xF<<8)
#define OWR_CSR_SEL_OFS 8
#define OWR_CSR_SEL_MASK (0xF << OWR_CSR_SEL_OFS)
#define OWR_CSR_SEL(x) (((x) << OWR_CSR_SEL_OFS) & OWR_CSR_SEL_MASK)
#define ONEWIRE_CSR_POWER_OFS 16
#define ONEWIRE_CSR_POWER (0xFFFF<<16)
#define OWR_CSR_POWER_OFS 16
#define OWR_CSR_POWER_MASK (0xFFFF << OWR_CSR_POWER_OFS)
#define OWR_CSR_POWER(x) (((x) << OWR_CSR_POWER_OFS) & OWR_CSR_POWER_MASK)
#define ONEWIRE_CDR_NOR (0xFFFF<<0)
#define OWR_CDR_NOR_OFS 0
#define OWR_CDR_NOR_MASK (0xFFFF << OWR_CDR_NOR_OFS)
#define OWR_CDR_NOR(x) (((x) << OWR_CDR_NOR_OFS) & OWR_CDR_NOR_MASK)
#define ONEWIRE_CDR_OVD_OFS 16
#define ONEWIRE_CDR_OVD (0XFFFF<<16)
#define OWR_CDR_OVD_OFS 16
#define OWR_CDR_OVD_MASK (0XFFFF << OWR_CDR_OVD_OFS)
#define OWR_CDR_OVD(x) (((x) << OWR_CDR_OVD_OFS) & OWR_CDR_OVD_MASK)
PACKED struct ONEWIRE_WB {
uint32_t CSR;
uint32_t CDR;
PACKED struct OWR_WB {
uint32_t CSR;
uint32_t CDR;
};
#endif
......@@ -37,26 +37,26 @@
#define SPI_DIV_MASK 0xFFFF
PACKED struct SPI_WB {
union {
uint32_t RX0;
uint32_t TX0;
};
union {
uint32_t RX1;
uint32_t TX1;
};
union {
uint32_t RX2;
uint32_t TX2;
};
union {
uint32_t RX3;
uint32_t TX3;
};
uint32_t CTRL;
uint32_t DIVIDER;
uint32_t SS;
union {
uint32_t RX0;
uint32_t TX0;
};
union {
uint32_t RX1;
uint32_t TX1;
};
union {
uint32_t RX2;
uint32_t TX2;
};
union {
uint32_t RX3;
uint32_t TX3;
};
uint32_t CTRL;
uint32_t DIVIDER;
uint32_t SS;
};
#endif
......@@ -10,15 +10,22 @@
* 5*scl
*
* For wb_clk_i = 100MHz and desired scl = 100 KHz:
* prescaler = 0.2*10^3 - 1
* prescaler = 0.2*10^3 - 1 = 199
*/
#define DEFAULT_I2C_PRESCALER 100
#define DEFAULT_I2C_PRESCALER 199
/* Type definitions */
typedef volatile struct I2C_WB i2c_t;
/* I2C API */
int i2c_init(void);
void i2c_exit(void);
int oc_i2c_poll(unsigned int id);
int oc_i2c_start(unsigned int id, int addr, int read);
int oc_i2c_rx(unsigned int id, uint32_t *out, int last);
int oc_i2c_tx(unsigned int id, uint32_t in, int last);
int oc_i2c_scan(unsigned int id);
#endif
......@@ -4,10 +4,25 @@
/* Hardware definitions */
#include <hw/wb_onewire.h>
//clk_div_nor = clock divider normal operation, clk_div_nor = Fclk * 5E-6 - 1
//clk_div_ovd = clock divider overdrive operation, clk_div_ovd = Fclk * 1E-6 - 1
// Clock divider for 100MHz bus clock
#define DEFAULT_OWR_DIVIDER_NOR 499
#define DEFAULT_OWR_DIVIDER_OVD 99
/* Type definitions */
typedef volatile struct ONEWIRE_WB onewire_t;
typedef volatile struct OWR_WB owr_t;
/* Onewire API */
int owr_init(void);
void owr_exit(void);
int oc_owr_poll(unsigned int id);
int oc_owr_reset(unsigned int id, int port);
int oc_owr_slot(unsigned int id, int port, uint32_t in_bit, uint32_t *out_bit);
int oc_owr_read_bit(unsigned int id, int port, uint32_t *out_bit);
int oc_owr_write_bit(unsigned int id, int port, uint32_t in_bit, uint32_t *out_bit);
int read_byte(unsigned int id, int port, uint32_t *out_byte);
int write_byte(unsigned int id, int port, uint32_t in_byte);
#endif
......@@ -8,8 +8,26 @@
#ifndef _REGS_H_
#define _REGS_H_
#define READ_ONLY 0x1
#define WRITE_ONLY 0x2
#define READ_WRITE (READ_ONLY | WRITE_ONLY)
#include <inttypes.h>
#define REGS_DEFAULT_NO_INIT 0
#define REGS_DEFAULT_INIT 1
#define REGS_DEFAULT_END 2
#define REGS_TYPE_READ_ONLY (1 << 0)
#define REGS_TYPE_WRITE_ONLY (1 << 1)
#define REGS_TYPE_READ_WRITE (1 << 2)
#define REGS_TYPE_RESERVED (1 << 3)
#define REGS_DEFAULT_SIZE 4
#define REGS_DEFAULT_TYPE REGS_READ_WRITE
struct default_dev_regs_t
{
uint8_t type;
uint8_t size; // in bytes
uint32_t addr;
uint32_t val;
};
#endif
......@@ -4,6 +4,9 @@
/* Hardware definitions */
#include <hw/wb_spi.h>
/*
* fsclk = fs_wbclk / (divider+1)*2
*/
#define DEFAULT_SPI_DIVIDER 100
/* Type definitions */
......@@ -14,7 +17,18 @@ int spi_init(void);
void spi_exit(void);
int oc_spi_poll(unsigned int id);
void oc_spi_config(unsigned int id, int ass, int rx_neg, int tx_neg,
<<<<<<< HEAD
int lsb, int ie);
=======
int lsb, int ie);
// For use only with spi three-wire mode
int oc_spi_three_mode_tx(unsigned int id, int ss, int nbits, uint32_t in)
// For use only with spi three-wire mode
int oc_spi_three_mode_rx(unsigned int id, int ss, int nbits, uint32_t *out)
<<<<<<< HEAD
>>>>>>> e8e9b7f... various: temp-mess 4
=======
>>>>>>> e8e9b7f... various: temp-mess 4
int oc_spi_txrx(unsigned int id, int ss, int nbits, uint32_t in, uint32_t *out);
......
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