Commit 94674ffb authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

kernel: added sysfs-based VME configuration

parent 73372076
......@@ -25,6 +25,7 @@ svec-objs := svec-drv.o
svec-objs += svec-sysfs.o
svec-objs += svec-fmc.o
svec-objs += svec-i2c.o
svec-objs += svec-irq.o
all: modules
......
This diff is collapsed.
......@@ -12,7 +12,6 @@
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/fmc-sdb.h>
#include <linux/jhash.h>
#include "svec.h"
static int svec_show_sdb;
......@@ -40,14 +39,13 @@ static int svec_reprogram(struct fmc_device *fmc, struct fmc_driver *drv,
const struct firmware *fw;
struct svec_dev *svec = fmc->carrier_data;
struct device *dev = fmc->hwdev;
uint32_t fw_hash;
int ret = 0;
/* If no firmware filename is provided, load default */
if (!gw)
gw = svec_fw_name;
if (!strlen(gw)) { /* use module parameters from the driver */
if (!strlen(gw)) { /* use module parameters from the driver */
int index;
/*
......@@ -59,7 +57,7 @@ static int svec_reprogram(struct fmc_device *fmc, struct fmc_driver *drv,
gw = drv->gw_val[index];
if (!gw)
return -ESRCH; /* the caller may accept this */
return -ESRCH; /* the caller may accept this */
}
dev_info(fmc->hwdev, "reprogramming with %s\n", gw);
......@@ -69,29 +67,18 @@ static int svec_reprogram(struct fmc_device *fmc, struct fmc_driver *drv,
return ret;
}
fmc_free_sdb_tree(fmc);
/* Hash firmware bitstream */
fw_hash = jhash(fw->data, fw->size,0);
if (fw_hash == svec->fw_hash) {
dev_info(dev, "card already programmed with \"%s\" [%x]\n", gw, fw_hash);
goto out;
}
/* load the firmware */
ret = svec_load_fpga(svec, fw->data, fw->size);
if (ret <0) {
if (ret < 0) {
dev_err(dev, "error %i programming firmware \"%s\"\n", ret, gw);
goto out;
}
/* configure and activate function 0 */
dev_info(fmc->hwdev, "svec-fmc: setup fa0\n");
svec_setup_csr_fa0(svec->map[MAP_CR_CSR]->kernel_va, svec->vmebase,
svec->vector, svec->level);
/* Configure & activate CSR functions depending on chosen AM */
svec_setup_csr(svec);
/* Store firmware hash to avoid reprogram */
svec->fw_hash = fw_hash;
out:
out:
release_firmware(fw);
if (ret < 0)
dev_err(dev, "svec reprogram failed while loading %s\n", gw);
......@@ -100,22 +87,7 @@ out:
static int svec_validate(struct fmc_device *fmc, struct fmc_driver *drv)
{
return 0; /* everyhing is valid */
}
static int svec_irq_request(struct fmc_device *fmc, irq_handler_t handler,
char *name, int flags)
{
return 0;
}
static void svec_irq_ack(struct fmc_device *fmc)
{
}
static int svec_irq_free(struct fmc_device *fmc)
{
return 0;
return 0; /* everyhing is valid */
}
static int svec_gpio_config(struct fmc_device *fmc, struct fmc_gpio *gpio,
......@@ -124,7 +96,6 @@ static int svec_gpio_config(struct fmc_device *fmc, struct fmc_gpio *gpio,
return 0;
}
static int svec_read_ee(struct fmc_device *fmc, int pos, void *data, int len)
{
if (!(fmc->flags & FMC_DEVICE_HAS_GOLDEN))
......@@ -142,16 +113,16 @@ static int svec_write_ee(struct fmc_device *fmc, int pos,
}
static struct fmc_operations svec_fmc_operations = {
.readl = svec_readl,
.writel = svec_writel,
.reprogram = svec_reprogram,
.irq_request = svec_irq_request,
.irq_ack = svec_irq_ack,
.irq_free = svec_irq_free,
.gpio_config = svec_gpio_config,
.read_ee = svec_read_ee,
.write_ee = svec_write_ee,
.validate = svec_validate,
.readl = svec_readl,
.writel = svec_writel,
.reprogram = svec_reprogram,
.irq_request = svec_irq_request,
.irq_ack = svec_irq_ack,
.irq_free = svec_irq_free,
.gpio_config = svec_gpio_config,
.read_ee = svec_read_ee,
.write_ee = svec_write_ee,
.validate = svec_validate,
};
static int check_golden(struct fmc_device *fmc)
......@@ -166,7 +137,7 @@ static int check_golden(struct fmc_device *fmc)
dev_err(svec->dev, "Bad SDB magic: 0x%08x\n", magic);
return -ENODEV;
}
if ( (ret = fmc_scan_sdb_tree(fmc, 0x0)) < 0)
if ((ret = fmc_scan_sdb_tree(fmc, 0x0)) < 0)
return -ENODEV;
vendor = fmc_readl(fmc, 0x5c);
......@@ -194,8 +165,7 @@ int svec_fmc_prepare(struct svec_dev *svec, unsigned int fmc_slot)
fmc = kzalloc(sizeof(*fmc), GFP_KERNEL);
if (!fmc) {
dev_err(svec->dev, "cannot allocate fmc slot %d\n",
fmc_slot);
dev_err(svec->dev, "cannot allocate fmc slot %d\n", fmc_slot);
return -ENOMEM;
}
......@@ -206,19 +176,27 @@ int svec_fmc_prepare(struct svec_dev *svec, unsigned int fmc_slot)
fmc->fpga_base = svec->map[MAP_REG]->kernel_va;
fmc->irq = 0; /*TO-DO*/
fmc->irq = 0; /*TO-DO */
fmc->op = &svec_fmc_operations;
fmc->hwdev = svec->dev; /* for messages */
fmc->hwdev = svec->dev; /* for messages */
fmc->slot_id = fmc_slot;
fmc->device_id = (svec->slot << 6) | fmc_slot;
fmc->eeprom_addr = 0x50 + 2 * fmc_slot;
fmc->memlen = 0x100000;
fmc->memlen = svec->cfg_cur.vme_size;
/* check golden integrity */
/* FIXME: this uses fmc_scan_sdb_tree and de-allocation
* could be wrong at second reprogramming, as it is called
* n times, one per slot */
ret = svec_load_golden(svec);
if (ret) {
dev_err(svec->dev, "Cannot load golden bitstream: %d\n", ret);
kfree(fmc);
return ret;
}
ret = check_golden(fmc);
if (ret) {
dev_err(svec->dev, "Bad golden, error %d\n", ret);
......@@ -235,7 +213,7 @@ int svec_fmc_prepare(struct svec_dev *svec, unsigned int fmc_slot)
svec->fmcs[fmc_slot] = fmc;
dev_info(svec->dev, "ready to create fmc device_id 0x%x\n",
fmc->device_id);
fmc->device_id);
return ret;
}
......@@ -246,8 +224,9 @@ int svec_fmc_create(struct svec_dev *svec)
int error = 0;
/* fmc structures filling */
for (i=0; i < svec->fmcs_n; i++) {
for (i = 0; i < svec->fmcs_n; i++) {
error = svec_fmc_prepare(svec, i);
if (error)
goto failed;
}
......@@ -263,7 +242,14 @@ int svec_fmc_create(struct svec_dev *svec)
*/
dev_info(svec->dev, "fmc devices registered\n");
failed:
return 0;
failed:
for (i = 0; i < svec->fmcs_n; i++)
if (svec->fmcs[i])
kfree(svec->fmcs[i]);
/* FIXME: free fmc allocations. */
return error;
......@@ -271,7 +257,10 @@ failed:
void svec_fmc_destroy(struct svec_dev *svec)
{
if (!svec->fmcs[0])
return;
fmc_device_unregister_n(svec->fmcs, svec->fmcs_n);
dev_info(svec->dev, "%d fmc devices unregistered\n",
svec->fmcs_n);
dev_info(svec->dev, "%d fmc devices unregistered\n", svec->fmcs_n);
}
......@@ -22,10 +22,10 @@
/* re-definitions for fields in golden core */
#define GLD_I2C_CORE_BASE 0x10000
#define GLD_I2CR_SCL_OUT GLD_I2CR0_SCL_OUT
#define GLD_I2CR_SDA_OUT GLD_I2CR0_SDA_OUT
#define GLD_I2CR_SCL_IN GLD_I2CR0_SCL_IN
#define GLD_I2CR_SDA_IN GLD_I2CR0_SDA_IN
#define GLD_I2CR_SCL_OUT GLD_I2CR0_SCL_OUT
#define GLD_I2CR_SDA_OUT GLD_I2CR0_SDA_OUT
#define GLD_I2CR_SCL_IN GLD_I2CR0_SCL_IN
#define GLD_I2CR_SDA_IN GLD_I2CR0_SDA_IN
static int svec_i2c_dump;
module_param_named(i2c_dump, svec_i2c_dump, int, 0444);
......@@ -51,7 +51,7 @@ static inline int mezzanine_present(struct fmc_device *fmc)
uint32_t presence;
presence = fmc_readl(fmc, GLD_I2C_CORE_BASE + GLD_REG_CSR);
presence = GLD_CSR_FMC_PRESENT_R(presence) & (1<<fmc->slot_id);
presence = GLD_CSR_FMC_PRESENT_R(presence) & (1 << fmc->slot_id);
return presence;
}
......@@ -62,7 +62,7 @@ static void dumpstruct(char *name, void *ptr, int size)
unsigned char *p = ptr;
printk("%s: (size 0x%x)\n", name, size);
for (i = 0; i < size; ) {
for (i = 0; i < size;) {
printk("%02x", p[i]);
i++;
printk(i & 3 ? " " : i & 0xf ? " " : "\n");
......@@ -79,7 +79,7 @@ static void set_sda(struct fmc_device *fmc, int val)
if (val)
reg |= GLD_I2CR_SDA_OUT;
golden_writel(fmc, reg, 0);
udelay(3); /* FIXME: is this enough? */
udelay(3); /* FIXME: is this enough? */
}
static void set_scl(struct fmc_device *fmc, int val)
......@@ -90,7 +90,7 @@ static void set_scl(struct fmc_device *fmc, int val)
if (val)
reg |= GLD_I2CR_SCL_OUT;
golden_writel(fmc, reg, 0);
udelay(3); /* FIXME: is this enough? */
udelay(3); /* FIXME: is this enough? */
}
static int get_sda(struct fmc_device *fmc)
......@@ -116,7 +116,7 @@ int mi2c_put_byte(struct fmc_device *fmc, int data)
int i;
int ack;
for (i = 0; i < 8; i++, data<<=1) {
for (i = 0; i < 8; i++, data <<= 1) {
set_sda(fmc, data & 0x80);
set_scl(fmc, 1);
set_scl(fmc, 0);
......@@ -130,7 +130,7 @@ int mi2c_put_byte(struct fmc_device *fmc, int data)
set_scl(fmc, 0);
set_sda(fmc, 0);
return ack ? -EIO : 0; /* ack low == success */
return ack ? -EIO : 0; /* ack low == success */
}
int mi2c_get_byte(struct fmc_device *fmc, unsigned char *data, int sendack)
......@@ -154,7 +154,7 @@ int mi2c_get_byte(struct fmc_device *fmc, unsigned char *data, int sendack)
set_scl(fmc, 0);
set_sda(fmc, 0);
*data= indata;
*data = indata;
return 0;
}
......@@ -167,17 +167,17 @@ void mi2c_init(struct fmc_device *fmc)
void mi2c_scan(struct fmc_device *fmc)
{
int i;
for(i = 0; i < 256; i += 2) {
for (i = 0; i < 256; i += 2) {
mi2c_start(fmc);
if(!mi2c_put_byte(fmc, i))
if (!mi2c_put_byte(fmc, i))
pr_info("%s: Found i2c device at 0x%x\n",
KBUILD_MODNAME, i >> 1);
KBUILD_MODNAME, i >> 1);
mi2c_stop(fmc);
}
}
int svec_eeprom_read(struct fmc_device *fmc, uint32_t offset,
void *buf, size_t size)
void *buf, size_t size)
{
unsigned char c;
int ret = size;
......@@ -185,7 +185,7 @@ int svec_eeprom_read(struct fmc_device *fmc, uint32_t offset,
int i2c_addr = fmc->eeprom_addr;
mi2c_start(fmc);
if(mi2c_put_byte(fmc, i2c_addr << 1) < 0) {
if (mi2c_put_byte(fmc, i2c_addr << 1) < 0) {
mi2c_stop(fmc);
return -EIO;
}
......@@ -204,13 +204,13 @@ int svec_eeprom_read(struct fmc_device *fmc, uint32_t offset,
}
int svec_eeprom_write(struct fmc_device *fmc, uint32_t offset,
const void *buf, size_t size)
const void *buf, size_t size)
{
int i, busy;
const uint8_t *buf8 = buf;
int i2c_addr = fmc->eeprom_addr;
for(i = 0; i < size; i++) {
for (i = 0; i < size; i++) {
mi2c_start(fmc);
if (mi2c_put_byte(fmc, i2c_addr << 1) < 0) {
......@@ -223,11 +223,11 @@ int svec_eeprom_write(struct fmc_device *fmc, uint32_t offset,
offset++;
mi2c_stop(fmc);
do { /* wait until the chip becomes ready */
do { /* wait until the chip becomes ready */
mi2c_start(fmc);
busy = mi2c_put_byte(fmc, i2c_addr << 1);
mi2c_stop(fmc);
} while(busy);
} while (busy);
}
return size;
}
......@@ -256,7 +256,7 @@ int svec_i2c_init(struct fmc_device *fmc)
return -EIO;
} else {
dev_info(fmc->hwdev, "Mezzanine %d, i2c 0x%x: EEPROM read ok\n",
fmc->slot_id + 1, fmc->eeprom_addr);
fmc->slot_id + 1, fmc->eeprom_addr);
}
fmc->eeprom = buf;
fmc->eeprom_len = SVEC_I2C_EEPROM_SIZE;
......@@ -273,4 +273,3 @@ void svec_i2c_exit(struct fmc_device *fmc)
fmc->eeprom = NULL;
fmc->eeprom_len = 0;
}
This diff is collapsed.
......@@ -15,7 +15,16 @@
#include "vmebus.h"
#define SVEC_MAX_DEVICES 32
#define SVEC_MAX_FIRMWARE_SIZE 0x400000
#define SVEC_DEFAULT_IDX { [0 ... (SVEC_MAX_DEVICES-1)] = -1 }
#define SVEC_DEFAULT_VME_AM { [0 ... (SVEC_MAX_DEVICES-1)] = 0x39 }
#define SVEC_DEFAULT_VME_SIZE { [0 ... (SVEC_MAX_DEVICES-1)] = 0x100000 }
#define SVEC_DEFAULT_IRQ_LEVEL { [0 ... (SVEC_MAX_DEVICES-1)] = 0x2 }
#define SVEC_UNINITIALIZED_VME_BASE { [0 ... (SVEC_MAX_DEVICES-1)] = 0xffffffff }
#define SVEC_UNINITIALIZED_IRQ_VECTOR { [0 ... (SVEC_MAX_DEVICES-1)] = -1 }
#define SVEC_IRQ_LEVEL 2
#define SVEC_N_SLOTS 2
#define SVEC_BASE_LOADER 0x70000
......@@ -28,45 +37,63 @@
#define SVEC_I2C_EEPROM_SIZE (8 * 1024)
enum svec_map_win {
MAP_CR_CSR = 0, /* CR/CSR */
MAP_REG /* A32 space */
MAP_CR_CSR = 0, /* CR/CSR */
MAP_REG /* A32/A24/A16 space */
};
struct svec_config {
int configured;
uint32_t vme_base;
int vme_am;
uint32_t vme_size;
uint32_t vic_base;
int interrupt_vector;
int interrupt_level;
int use_vic;
int use_fmc;
};
#define SVEC_FLAG_FMCS_REGISTERED 0
#define SVEC_FLAG_IRQS_REQUESTED 1
#define SVEC_FLAG_BOOTLOADER_ACTIVE 2
/* Our device structure */
struct svec_dev {
int lun;
int slot;
uint32_t vmebase;
int vector;
int level;
char *fw_name;
struct device *dev;
char driver[16];
char description[80];
uint32_t fw_hash;
struct vme_mapping *map[2];
/* struct work_struct work; */
unsigned long irqcount;
struct fmc_device *fmcs[SVEC_N_SLOTS];
/* FMC devices */
int fmcs_n; /* Number of FMC devices */
int irq_count; /* for mezzanine use too */
int lun;
int slot;
unsigned long flags;
char *fw_name;
struct device *dev;
char driver[16];
char description[80];
uint32_t fw_hash;
struct vme_mapping *map[2];
struct svec_config cfg_cur, cfg_new;
/* struct work_struct work; */
unsigned long irqcount;
struct fmc_device *fmcs[SVEC_N_SLOTS];
/* FMC devices */
int fmcs_n; /* Number of FMC devices */
int irq_count; /* for mezzanine use too */
uint32_t vme_raw_addr; /* VME address for raw VME I/O through vme_addr/vme_data attributes */
};
/* Functions and data in svec-vme.c */
extern int svec_is_bootloader_active(struct svec_dev *svec);
extern int svec_bootloader_unlock (struct svec_dev *svec);
extern int svec_bootloader_unlock(struct svec_dev *svec);
extern int svec_load_fpga(struct svec_dev *svec, const void *data, int size);
extern int svec_load_fpga_file(struct svec_dev *svec, const char *name);
extern void svec_setup_csr_fa0(void *base, u32 vme, unsigned vector,
unsigned level);
extern void svec_setup_csr_fa0(struct svec_dev *svec);
extern int svec_unmap_window(struct svec_dev *svec, enum svec_map_win map_type);
extern int svec_map_window( struct svec_dev *svec, enum svec_map_win map_type);
extern int svec_map_window(struct svec_dev *svec, enum svec_map_win map_type);
extern char *svec_fw_name;
extern int spec_use_msi;
/* Functions in svec-fmc.c, used by svec-vme.c */
extern int svec_fmc_create(struct svec_dev *svec);
......@@ -82,6 +109,7 @@ extern int svec_eeprom_write(struct fmc_device *fmc, uint32_t offset,
/* SVEC CSR offsets */
#define FUN0ADER 0x7FF63
#define FUN1ADER 0x7FF73
#define INT_LEVEL 0x7ff5b
#define INTVECTOR 0x7ff5f
#define WB_32_64 0x7ff33
......@@ -96,4 +124,20 @@ extern int svec_eeprom_write(struct fmc_device *fmc, uint32_t offset,
extern int svec_create_sysfs_files(struct svec_dev *card);
extern void svec_remove_sysfs_files(struct svec_dev *card);
int svec_dma_write(struct svec_dev *svec, uint32_t addr, int am, size_t size,
void *buf, int is_fifo);
int svec_dma_read(struct svec_dev *svec, uint32_t addr, int am, size_t size,
void *buf, int is_fifo);
int svec_irq_request(struct fmc_device *fmc, irq_handler_t handler, char *name,
int flags);
void svec_irq_ack(struct fmc_device *fmc);
int svec_irq_free(struct fmc_device *fmc);
int svec_reconfigure(struct svec_dev *svec);
int svec_setup_csr(struct svec_dev *svec);
int svec_validate_configuration(struct device *pdev, struct svec_config *cfg);
int svec_load_golden(struct svec_dev *svec);
#endif /* __SVEC_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