Commit acc8d804 authored by Maciej Lipinski's avatar Maciej Lipinski

[FRAM/VXS] added support for FRAM type of memory (needed on VXS)

parent 463e159b
...@@ -12,7 +12,8 @@ obj-$(CONFIG_EMBEDDED_NODE) += \ ...@@ -12,7 +12,8 @@ obj-$(CONFIG_EMBEDDED_NODE) += \
dev/sfp.o \ dev/sfp.o \
dev/devicelist.o \ dev/devicelist.o \
dev/rxts_calibrator.o \ dev/rxts_calibrator.o \
dev/flash.o dev/flash.o \
dev/fram.o
obj-$(CONFIG_WR_NODE) += \ obj-$(CONFIG_WR_NODE) += \
dev/temperature.o \ dev/temperature.o \
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
/* /*
* Delay function - limit SPI clock speed to 10 MHz * Delay function - limit SPI clock speed to 10 MHz
*/ */
static void delay(void) void delay(void)
{ {
int i; int i;
...@@ -28,7 +28,7 @@ static void delay(void) ...@@ -28,7 +28,7 @@ static void delay(void)
/* /*
* Bit-bang SPI transfer function * Bit-bang SPI transfer function
*/ */
static uint8_t bbspi_transfer(int cspin, uint8_t val) uint8_t bbspi_transfer(int cspin, uint8_t val)
{ {
int i; int i;
......
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2018 CERN (www.cern.ch)
* Author: Maciej Lipinski
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#include <wrc.h>
#include <fram.h>
#include <types.h>
#include <storage.h>
#include <flash.h>
#define SDBFS_BIG_ENDIAN
#include <libsdbfs.h>
/*
* Init function (just set the SPI pins for idle)
*/
void fram_init(void)
{
//flash_init(); //ML: it is the same as flash, so no need to call it
}
/*
* Write data to flash chip
*/
int fram_write(uint32_t addr, uint8_t *buf, int count)
{
int i;
bbspi_transfer(1, 0); // idle (possibly not needed)
bbspi_transfer(0, 0x06); // WREN (set write enable latch)
bbspi_transfer(1, 0); // idle (possibly not needed)
bbspi_transfer(0, 0x02); // optcode for writing
bbspi_transfer(0, (addr & 0xFF00) >> 8);// write address MSB
bbspi_transfer(0, (addr & 0xFF)); // write address LSB
for (i = 0; i < count; i++) {
bbspi_transfer(0, buf[i]);
}
bbspi_transfer(1, 0);
return count;
}
/*
* Read data from flash
*/
int fram_read(uint32_t addr, uint8_t *buf, int count)
{
int i;
bbspi_transfer(1, 0); // idle (possibly not needed)
bbspi_transfer(0, 0x03); // optcode for reading
bbspi_transfer(0, (addr & 0xFF00) >> 8);
bbspi_transfer(0, (addr & 0xFF));
for (i = 0; i < count; i++) {
buf[i] = bbspi_transfer(0, 0);
}
bbspi_transfer(1, 0);
return count;
}
int fram_erase(uint32_t addr, int count)
{
int i;
uint8_t buf[1] = {0xff};
for (i = 0; i < count; i++)
flash_write(addr+i, buf , 1);
return count;
}
/*****************************************************************************/
/* SDB */
/*****************************************************************************/
/* The sdb filesystem itself */
static struct sdbfs wrc_sdb = {
.name = "wrpc-storage",
.blocksize = 0, /* Not currently used */
/* .read and .write according to device type */
};
/*
* SDB read and write functions
*/
static int sdb_fram_read(struct sdbfs *fs, int offset, void *buf, int count)
{
return fram_read(offset, buf, count);
}
static int sdb_fram_write(struct sdbfs *fs, int offset, void *buf, int count)
{
return fram_write(offset, buf, count);
}
/*
* A trivial dumper, just to show what's up in there
*/
static void fram_sdb_list(struct sdbfs *fs)
{
struct sdb_device *d;
int new = 1;
while ((d = sdbfs_scan(fs, new)) != NULL) {
d->sdb_component.product.record_type = '\0';
pp_printf("file 0x%08x @ %4i, name %19s\n",
(int)(d->sdb_component.product.device_id),
(int)(d->sdb_component.addr_first),
(char *)(d->sdb_component.product.name));
new = 0;
}
}
/*
* Check for SDB presence on fram
*/
int fram_sdb_check(void)
{
uint32_t magic = 0;
int i;
uint32_t entry_point[] = {
0x000000, /* fram base */
0x6000 /* for VXS*/
};
for (i = 0; i < ARRAY_SIZE(entry_point); i++) {
fram_read(entry_point[i], (uint8_t *)&magic, 4);
if (magic == SDB_MAGIC)
break;
}
if (i == ARRAY_SIZE(entry_point))
return -1;
pp_printf("Found SDB magic at address 0x%06x\n", entry_point[i]);
wrc_sdb.drvdata = NULL;
wrc_sdb.entrypoint = entry_point[i];
wrc_sdb.read = sdb_fram_read;
wrc_sdb.write = sdb_fram_write;
fram_sdb_list(&wrc_sdb);
return 0;
}
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#define SDBFS_BIG_ENDIAN #define SDBFS_BIG_ENDIAN
#include <libsdbfs.h> #include <libsdbfs.h>
#include <flash.h> #include <flash.h>
#include <fram.h>
/* /*
* This source file is a drop-in replacement of the legacy one: it manages * This source file is a drop-in replacement of the legacy one: it manages
...@@ -55,6 +56,22 @@ static int sdb_flash_erase(struct sdbfs *fs, int offset, int count) ...@@ -55,6 +56,22 @@ static int sdb_flash_erase(struct sdbfs *fs, int offset, int count)
return flash_erase(offset, count); return flash_erase(offset, count);
} }
/* Functions for FRAM access */
static int sdb_fram_read(struct sdbfs *fs, int offset, void *buf, int count)
{
return fram_read(offset, buf, count);
}
static int sdb_fram_write(struct sdbfs *fs, int offset, void *buf, int count)
{
return fram_write(offset, buf, count);
}
static int sdb_fram_erase(struct sdbfs *fs, int offset, int count)
{
return fram_erase(offset, count);
}
/* The methods for W1 access */ /* The methods for W1 access */
static int sdb_w1_read(struct sdbfs *fs, int offset, void *buf, int count) static int sdb_w1_read(struct sdbfs *fs, int offset, void *buf, int count)
{ {
...@@ -211,6 +228,11 @@ void storage_init(int chosen_i2cif, int chosen_i2c_addr) ...@@ -211,6 +228,11 @@ void storage_init(int chosen_i2cif, int chosen_i2c_addr)
0x170000, /* after first FPGA bitstream */ 0x170000, /* after first FPGA bitstream */
0x2e0000, /* after MultiBoot bitstream */ 0x2e0000, /* after MultiBoot bitstream */
0x600000}; /* after SVEC AFPGA bitstream */ 0x600000}; /* after SVEC AFPGA bitstream */
uint32_t entry_points_fram[] = {
0x000000, /* fram base */
0x6000,
0x7000
};
int i, ret; int i, ret;
/* /*
...@@ -233,9 +255,27 @@ void storage_init(int chosen_i2cif, int chosen_i2c_addr) ...@@ -233,9 +255,27 @@ void storage_init(int chosen_i2cif, int chosen_i2c_addr)
goto found_exit; goto found_exit;
} }
/* /*
* 2. Look for w1 first: if there is no eeprom it fails fast * 2. Check if there is SDBFS in the FRAM.
*/
for (i = 0; i < ARRAY_SIZE(entry_points_fram); i++) {
fram_read(entry_points_fram[i], (void *)&magic, sizeof(magic));
if (magic == SDB_MAGIC)
break;
}
if (magic == SDB_MAGIC) {
pp_printf("sdbfs: found at %i in Fram\n",
entry_points_fram[i]);
wrc_sdb.drvdata = NULL;
wrc_sdb.blocksize = 0;
wrc_sdb.entrypoint = entry_points_fram[i];
wrc_sdb.read = sdb_fram_read;
wrc_sdb.write = sdb_fram_write;
wrc_sdb.erase = sdb_fram_erase;
goto found_exit;
}
/*
* 3. Look for w1 first: if there is no eeprom it fails fast
*/ */
for (i = 0; i < ARRAY_SIZE(entry_points_eeprom); i++) { for (i = 0; i < ARRAY_SIZE(entry_points_eeprom); i++) {
ret = w1_read_eeprom_bus(&wrpc_w1_bus, entry_points_eeprom[i], ret = w1_read_eeprom_bus(&wrpc_w1_bus, entry_points_eeprom[i],
...@@ -258,7 +298,7 @@ void storage_init(int chosen_i2cif, int chosen_i2c_addr) ...@@ -258,7 +298,7 @@ void storage_init(int chosen_i2cif, int chosen_i2c_addr)
} }
/* /*
* 3. If w1 failed, look for i2c: start from low offsets. * 4. If w1 failed, look for i2c: start from low offsets.
*/ */
i2c_params.ifnum = chosen_i2cif; i2c_params.ifnum = chosen_i2cif;
i2c_params.addr = EEPROM_START_ADR; i2c_params.addr = EEPROM_START_ADR;
...@@ -790,7 +830,10 @@ int storage_sdbfs_erase(int mem_type, uint32_t base_adr, uint32_t blocksize, ...@@ -790,7 +830,10 @@ int storage_sdbfs_erase(int mem_type, uint32_t base_adr, uint32_t blocksize,
wrc_sdb.drvdata = &wrpc_w1_bus; wrc_sdb.drvdata = &wrpc_w1_bus;
sdb_w1_erase(&wrc_sdb, base_adr, SDBFS_REC * sdb_w1_erase(&wrc_sdb, base_adr, SDBFS_REC *
sizeof(struct sdb_device)); sizeof(struct sdb_device));
} } else if (mem_type == MEM_FRAM) {
pp_printf("Erasing FRAM (0x%x)...\n", base_adr);
sdb_fram_erase(NULL, base_adr, SDBFS_REC * blocksize);
}
return 0; return 0;
} }
...@@ -897,8 +940,14 @@ int storage_gensdbfs(int mem_type, uint32_t base_adr, uint32_t blocksize, ...@@ -897,8 +940,14 @@ int storage_gensdbfs(int mem_type, uint32_t base_adr, uint32_t blocksize,
sdb_w1_write(&wrc_sdb, base_adr + i*size, &sdbfs[i], sdb_w1_write(&wrc_sdb, base_adr + i*size, &sdbfs[i],
size); size);
} }
} } else if (mem_type == MEM_FRAM) {
pp_printf("Formatting SDBFS in FRAM(0x%x)...\n", base_adr);
sdb_fram_erase(NULL, base_adr, SDBFS_REC * size);
for (i = 0; i < SDBFS_REC; ++i) {
sdb_fram_write(NULL, base_adr + i*size, &sdbfs[i],
size);
}
}
/* re-initialize storage after writing sdbfs image */ /* re-initialize storage after writing sdbfs image */
storage_init(WRPC_FMC_I2C, FMC_EEPROM_ADR); storage_init(WRPC_FMC_I2C, FMC_EEPROM_ADR);
......
...@@ -13,6 +13,10 @@ ...@@ -13,6 +13,10 @@
#define FLASH_BLOCKSIZE 65536 #define FLASH_BLOCKSIZE 65536
void delay(void);
uint8_t bbspi_transfer(int cspin, uint8_t val);
void flash_init(void);
/* Flash interface functions */ /* Flash interface functions */
void flash_init(void); void flash_init(void);
int flash_write(uint32_t addr, uint8_t *buf, int count); int flash_write(uint32_t addr, uint8_t *buf, int count);
......
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2018 CERN (www.cern.ch)
* Author: Maciej Lipinski
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#ifndef __FRAM_H_
#define __FRAM_H_
#include "types.h"
/* Fram interface functions */
void fram_init(void);
int fram_write(uint32_t addr, uint8_t *buf, int count);
int fram_read(uint32_t addr, uint8_t *buf, int count);
int fram_erase(uint32_t addr, int count);
/* SDB flash interface functions */
int fram_sdb_check(void);
#endif // __FRAM_H_
...@@ -88,6 +88,7 @@ extern struct storage_config storage_cfg; ...@@ -88,6 +88,7 @@ extern struct storage_config storage_cfg;
#define MEM_FLASH 0 #define MEM_FLASH 0
#define MEM_EEPROM 1 #define MEM_EEPROM 1
#define MEM_1W_EEPROM 2 #define MEM_1W_EEPROM 2
#define MEM_FRAM 3
#define SDBFS_REC 5 #define SDBFS_REC 5
int storage_read_hdl_cfg(void); int storage_read_hdl_cfg(void);
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "syscon.h" #include "syscon.h"
#include "hw/memlayout.h" #include "hw/memlayout.h"
#include "storage.h" #include "storage.h"
#include <flash.h>
/* /*
* args[1] - where to write sdbfs image (0 - Flash, 1 - I2C EEPROM, * args[1] - where to write sdbfs image (0 - Flash, 1 - I2C EEPROM,
...@@ -33,6 +34,8 @@ static int cmd_sdb(const char *args[]) ...@@ -33,6 +34,8 @@ static int cmd_sdb(const char *args[])
/* interpret args[3] as i2c adr or blocksize depending on memory type */ /* interpret args[3] as i2c adr or blocksize depending on memory type */
if (args[3] && atoi(args[1]) == MEM_FLASH) if (args[3] && atoi(args[1]) == MEM_FLASH)
blocksize = atoi(args[3])*1024; blocksize = atoi(args[3])*1024;
else if (args[3] && atoi(args[1]) == MEM_FRAM)
blocksize = atoi(args[3]);
else if (args[3]) else if (args[3])
i2c_adr = atoi(args[3]); i2c_adr = atoi(args[3]);
...@@ -45,10 +48,11 @@ static int cmd_sdb(const char *args[]) ...@@ -45,10 +48,11 @@ static int cmd_sdb(const char *args[])
return 0; return 0;
} }
if (!strcasecmp(args[0], "fs") && storage_cfg.valid && if (!strcasecmp(args[0], "fs") && storage_cfg.valid &&
atoi(args[1]) == MEM_FLASH) { (atoi(args[1]) == MEM_FLASH ||
atoi(args[1]) == MEM_FRAM)) {
/* if available, we can also use Flash parameters specified with /* if available, we can also use Flash parameters specified with
* HDL generics */ * HDL generics */
storage_gensdbfs(MEM_FLASH, storage_cfg.baseadr, storage_gensdbfs(atoi(args[1]), storage_cfg.baseadr,
storage_cfg.blocksize, 0); storage_cfg.blocksize, 0);
return 0; return 0;
} }
...@@ -59,12 +63,12 @@ static int cmd_sdb(const char *args[]) ...@@ -59,12 +63,12 @@ static int cmd_sdb(const char *args[])
return 0; return 0;
} }
if (!strcasecmp(args[0], "fse") && storage_cfg.valid && if (!strcasecmp(args[0], "fse") && storage_cfg.valid &&
atoi(args[1]) == MEM_FLASH) { (atoi(args[1]) == MEM_FLASH ||
storage_sdbfs_erase(MEM_FLASH, storage_cfg.baseadr, atoi(args[1]) == MEM_FRAM)) {
storage_sdbfs_erase(atoi(args[1]), storage_cfg.baseadr,
storage_cfg.blocksize, 0); storage_cfg.blocksize, 0);
return 0; return 0;
} }
return -EINVAL; return -EINVAL;
} }
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "lib/ipv4.h" #include "lib/ipv4.h"
#include "rxts_calibrator.h" #include "rxts_calibrator.h"
#include "flash.h" #include "flash.h"
#include "fram.h"
#include "wrc_ptp.h" #include "wrc_ptp.h"
#include "system_checks.h" #include "system_checks.h"
......
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