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) += \
dev/sfp.o \
dev/devicelist.o \
dev/rxts_calibrator.o \
dev/flash.o
dev/flash.o \
dev/fram.o
obj-$(CONFIG_WR_NODE) += \
dev/temperature.o \
......
......@@ -17,7 +17,7 @@
/*
* Delay function - limit SPI clock speed to 10 MHz
*/
static void delay(void)
void delay(void)
{
int i;
......@@ -28,7 +28,7 @@ static void delay(void)
/*
* 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;
......
/*
* 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 @@
#define SDBFS_BIG_ENDIAN
#include <libsdbfs.h>
#include <flash.h>
#include <fram.h>
/*
* 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)
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 */
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)
0x170000, /* after first FPGA bitstream */
0x2e0000, /* after MultiBoot bitstream */
0x600000}; /* after SVEC AFPGA bitstream */
uint32_t entry_points_fram[] = {
0x000000, /* fram base */
0x6000,
0x7000
};
int i, ret;
/*
......@@ -233,9 +255,27 @@ void storage_init(int chosen_i2cif, int chosen_i2c_addr)
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++) {
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)
}
/*
* 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.addr = EEPROM_START_ADR;
......@@ -790,7 +830,10 @@ int storage_sdbfs_erase(int mem_type, uint32_t base_adr, uint32_t blocksize,
wrc_sdb.drvdata = &wrpc_w1_bus;
sdb_w1_erase(&wrc_sdb, base_adr, SDBFS_REC *
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;
}
......@@ -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],
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 */
storage_init(WRPC_FMC_I2C, FMC_EEPROM_ADR);
......
......@@ -13,6 +13,10 @@
#define FLASH_BLOCKSIZE 65536
void delay(void);
uint8_t bbspi_transfer(int cspin, uint8_t val);
void flash_init(void);
/* Flash interface functions */
void flash_init(void);
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;
#define MEM_FLASH 0
#define MEM_EEPROM 1
#define MEM_1W_EEPROM 2
#define MEM_FRAM 3
#define SDBFS_REC 5
int storage_read_hdl_cfg(void);
......
......@@ -10,6 +10,7 @@
#include "syscon.h"
#include "hw/memlayout.h"
#include "storage.h"
#include <flash.h>
/*
* args[1] - where to write sdbfs image (0 - Flash, 1 - I2C EEPROM,
......@@ -33,6 +34,8 @@ static int cmd_sdb(const char *args[])
/* interpret args[3] as i2c adr or blocksize depending on memory type */
if (args[3] && atoi(args[1]) == MEM_FLASH)
blocksize = atoi(args[3])*1024;
else if (args[3] && atoi(args[1]) == MEM_FRAM)
blocksize = atoi(args[3]);
else if (args[3])
i2c_adr = atoi(args[3]);
......@@ -45,10 +48,11 @@ static int cmd_sdb(const char *args[])
return 0;
}
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
* HDL generics */
storage_gensdbfs(MEM_FLASH, storage_cfg.baseadr,
storage_gensdbfs(atoi(args[1]), storage_cfg.baseadr,
storage_cfg.blocksize, 0);
return 0;
}
......@@ -59,12 +63,12 @@ static int cmd_sdb(const char *args[])
return 0;
}
if (!strcasecmp(args[0], "fse") && storage_cfg.valid &&
atoi(args[1]) == MEM_FLASH) {
storage_sdbfs_erase(MEM_FLASH, storage_cfg.baseadr,
(atoi(args[1]) == MEM_FLASH ||
atoi(args[1]) == MEM_FRAM)) {
storage_sdbfs_erase(atoi(args[1]), storage_cfg.baseadr,
storage_cfg.blocksize, 0);
return 0;
}
return -EINVAL;
}
......
......@@ -30,6 +30,7 @@
#include "lib/ipv4.h"
#include "rxts_calibrator.h"
#include "flash.h"
#include "fram.h"
#include "wrc_ptp.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