svec: temporary commit of multi-mezzanine svec+fd

parent 7272ee4c
# Assign sensible defaults, but allow overriding with environment variables.
CPU ?:= L865
# CPU ?:= L865
# KVER ?= 2.6.24.7-rt27
KVER ?= 3.2.33-rt50
KERN_DIR?= "/acc/sys/$(CPU)/usr/src/kernels/$(KVER)"
LINUX ?= "/acc/sys/$(CPU)/usr/src/kernels/$(KVER)"
VME_DIR ?= "../../repo/vmebridge/driver"
#VME_OBJDIR ?= "../../repo/vmebridge/driver/$(CPU)/$(KVER)"
VME_OBJDIR ?= "../../repo/vmebridge/driver/"
......@@ -27,4 +27,4 @@ all: modules
.PHONY: all modules clean help install modules_install
modules clean help install modules_install:
$(MAKE) -C $(KERN_DIR) M=$(shell pwd) CPU=$(CPU) KVER=$(KVER) $@
$(MAKE) -C $(LINUX) M=$(shell pwd) CPU=$(CPU) KVER=$(KVER) $@
fmc-bus @ 127da26e
Subproject commit f2fe7b09ce05a2c5718e687cebd5ab2aa6b31e2a
Subproject commit 127da26eb200d61c9e2bad48fca05609cb882fbe
......@@ -25,14 +25,14 @@ static uint32_t svec_readl(struct fmc_device *fmc, int offset)
{
uint32_t val = 0;
val = ioread32be(fmc->base + offset);
val = ioread32be(fmc->fpga_base + offset);
return val;
}
static void svec_writel(struct fmc_device *fmc, uint32_t val, int offset)
{
iowrite32be(val, fmc->base + offset);
iowrite32be(val, fmc->fpga_base + offset);
}
static int svec_reprogram(struct fmc_device *fmc, struct fmc_driver *drv,
......@@ -48,7 +48,6 @@ static int svec_reprogram(struct fmc_device *fmc, struct fmc_driver *drv,
return ret;
}
if (!gw)
gw = svec_fw_name;
......@@ -94,7 +93,7 @@ static int svec_reprogram(struct fmc_device *fmc, struct fmc_driver *drv,
out:
release_firmware(fw);
if (ret < 0)
pr_err("svec-fmc: svec reprogram failed while loading %s\n", gw);
dev_err(dev, "svec reprogram failed while loading %s\n", gw);
return ret;
}
......@@ -130,7 +129,7 @@ static int svec_read_ee(struct fmc_device *fmc, int pos, void *data, int len)
if (!(fmc->flags & FMC_DEVICE_HAS_GOLDEN))
return -ENOTSUPP;
return svec_eeprom_read(fmc, SVEC_I2C_EEPROM_ADDR, pos, data, len);
return svec_eeprom_read(fmc, fmc->eeprom_addr, pos, data, len);
return -ENOTSUPP;
}
......@@ -141,7 +140,7 @@ static int svec_write_ee(struct fmc_device *fmc, int pos,
if (!(fmc->flags & FMC_DEVICE_HAS_GOLDEN))
return -ENOTSUPP;
return svec_eeprom_write(fmc, SVEC_I2C_EEPROM_ADDR, pos, data, len);
return svec_eeprom_write(fmc, fmc->eeprom_addr, pos, data, len);
return -ENOTSUPP;
}
......@@ -159,85 +158,39 @@ static struct fmc_operations svec_fmc_operations = {
.validate = svec_validate,
};
/*
* Finally, the real init and exit
*/
static int check_sdb(struct fmc_device *fmc)
{
struct svec_dev *svec = fmc->carrier_data;
int ret;
uint32_t val;
/* poor man's SDB */
val = fmc_readl(fmc, 0x0);
if (val != 0x5344422d) {
dev_err(svec->dev, "Can't find SDB magic\n");
return -ENODEV;
}
else
dev_info(svec->dev, "SDB magic found\n");
if ((ret = fmc_scan_sdb_tree(fmc, 0x0)) < 0)
return -ENODEV;
if (svec_show_sdb)
fmc_show_sdb_tree(fmc);
/* FIXME: For now, hardcoded mezzanine offsets for fd*/
/* It should be read from SBD */
svec->mezzanine_offset[0] = 0x10000;
svec->mezzanine_offset[1] = 0x20000;
return 0;
}
int svec_fmc_create(struct svec_dev *svec, unsigned int n)
{
struct fmc_device *fmc;
int ret;
struct fmc_device *fmc = svec->fmcs + n;
int ret = 0;
printk(KERN_ERR "%s enters\n", __func__);
if (n<0 || n>1)
return -EINVAL;
fmc = kzalloc(sizeof(*fmc), GFP_KERNEL);
if (!fmc)
return -ENOMEM;
fmc->version = FMC_VERSION;
fmc->carrier_name = "SVEC";
fmc->carrier_data = svec;
fmc->owner = THIS_MODULE;
fmc->fpga_base = svec->map[MAP_REG]->kernel_va;
fmc->irq = 0; /*TO-DO*/
fmc->op = &svec_fmc_operations;
fmc->base = svec->map[MAP_REG]->kernel_va;
fmc->hwdev = svec->dev; /* for messages */
svec->fmc[n] = fmc;
/* Check that the golden binary is actually correct */
if (!svec->already_reprogrammed) {
ret = check_sdb(fmc);
if (ret)
goto out_free;
}
fmc->base += svec->mezzanine_offset[n];
fmc->slot_id = n;
fmc->device_id = n + 1;
fmc->eeprom_addr = 0x50 + 2 * n;
fmc->memlen = 0x100000;
ret = fmc_device_register(fmc);
if (ret)
goto out_irq;
ret = svec_i2c_init(fmc, n);
if (ret) {
dev_err(svec->dev, "Error %d on svec i2c init", ret);
return ret;
}
return ret;
printk(KERN_ERR "%s exits\n", __func__);
out_irq:
out_free:
svec->fmc[n] = NULL;
kfree(fmc);
return ret;
}
void svec_fmc_destroy(struct svec_dev *svec, unsigned int n)
{
fmc_device_unregister(svec->fmc[n]);
svec->fmc[n] = NULL;
}
......@@ -194,15 +194,15 @@ int svec_eeprom_write(struct fmc_device *fmc, int i2c_addr, uint32_t offset,
return size;
}
int svec_i2c_init(struct fmc_device *fmc)
int svec_i2c_init(struct fmc_device *fmc, unsigned int slot)
{
struct svec_dev *svec = fmc->carrier_data;
void *buf;
int i, found;
found = mi2c_scan(fmc);
if (!found) {
fmc->flags |= FMC_DEVICE_NO_MEZZANINE;
printk(KERN_ERR "FMC_DEVICE_NO_MEZZANINE\n");
return 0;
}
......@@ -210,13 +210,16 @@ int svec_i2c_init(struct fmc_device *fmc)
if (!buf)
return -ENOMEM;
i = svec_eeprom_read(fmc, SVEC_I2C_EEPROM_ADDR, 0, buf,
i = svec_eeprom_read(fmc, fmc->eeprom_addr, 0, buf,
SVEC_I2C_EEPROM_SIZE);
if (i != SVEC_I2C_EEPROM_SIZE) {
dev_err(svec->dev, "EEPROM read error: retval is %i\n",
dev_err(fmc->hwdev, "EEPROM read error: retval is %i\n",
i);
kfree(buf);
return -EIO;
} else {
dev_info(fmc->hwdev, "Mezzanine %d, i2c 0x%x: EEPROM read ok\n",
slot + 1, fmc->eeprom_addr);
}
fmc->eeprom = buf;
fmc->eeprom_len = SVEC_I2C_EEPROM_SIZE;
......
......@@ -21,7 +21,6 @@
/* The eeprom is at address 0x50 */
/* FIXME ? Copied from spec.h */
#define SVEC_I2C_EEPROM_ADDR 0x50
#define SVEC_I2C_EEPROM_SIZE (8 * 1024)
enum svec_map_win {
......@@ -39,13 +38,12 @@ struct svec_dev {
char *submod_name;
char *fw_name;
struct device *dev;
struct device *dev;
struct cdev cdev;
char driver[16];
char description[80];
struct vme_mapping *map[2];
uint32_t mezzanine_offset[2];
/* FIXME: Workaround to avoid reprogram on second fd */
int already_reprogrammed;
......@@ -54,7 +52,8 @@ struct svec_dev {
struct list_head list;
unsigned long irqcount;
void *sub_priv;
struct fmc_device *fmc[2];
struct fmc_device *fmcs;
int slot_n;
int irq_count; /* for mezzanine use too */
struct completion compl;
struct gpio_chip *gpio;
......@@ -75,10 +74,10 @@ extern int spec_use_msi;
/* Functions in svec-fmc.c, used by svec-vme.c */
extern int svec_fmc_create(struct svec_dev *svec, unsigned int n);
extern void svec_fmc_destroy(struct svec_dev *svec, unsigned int n);
extern void svec_fmc_check(struct svec_dev *svec, unsigned int n);
/* Functions in svec-i2c.c, used by svec-fmc.c */
extern int svec_i2c_init(struct fmc_device *fmc);
extern int svec_i2c_init(struct fmc_device *fmc, unsigned int n);
extern void svec_i2c_exit(struct fmc_device *fmc);
extern int svec_eeprom_read(struct fmc_device *fmc, int i2c_addr,
uint32_t offset, void *buf, size_t size);
......
......@@ -216,6 +216,7 @@ void setup_csr_fa0(void *base, u32 vme, unsigned vector, unsigned level)
csr_write(ENABLE_CORE, base, BIT_SET_REG);
/* DEBUG */
/*
pr_debug("base: %02x%02x%02x%02x\n", csr_read(base, FUN0ADER),
csr_read(base, FUN0ADER+4), csr_read(base, FUN0ADER+8),
csr_read(base, FUN0ADER+12));
......@@ -224,6 +225,7 @@ void setup_csr_fa0(void *base, u32 vme, unsigned vector, unsigned level)
pr_debug("int_enable: %02x\n", csr_read(base, 0x7ff57));
pr_debug("wb32: %02x\n", csr_read(base, WB_32_64));
pr_debug("vme_core: %02x\n", csr_read(base, 0x7c));
*/
}
int svec_load_fpga(struct svec_dev *svec, const void *blob, int size)
......@@ -304,14 +306,16 @@ int svec_load_fpga(struct svec_dev *svec, const void *blob, int size)
static int __devexit svec_remove(struct device *pdev, unsigned int ndev)
{
struct svec_dev *svec = dev_get_drvdata(pdev);
int i;
/*int i;*/
pr_debug("%s\n", __func__);
for (i=0; i<2; i++) {
if (svec->fmc[i] != NULL)
svec_fmc_destroy(svec, i);
if (svec->fmcs) {
fmc_device_unregister_n(svec->fmcs, svec->slot_n);
kfree(svec->fmcs);
dev_info(pdev, "fmc devices unregistered\n");
}
unmap_window(svec, MAP_CR_CSR);
unmap_window(svec, MAP_REG);
......@@ -387,12 +391,17 @@ static int __devinit svec_probe(struct device *pdev, unsigned int ndev)
svec->vector = vector[ndev];
svec->level = level[ndev];
svec->fw_name = fw_name[ndev];
svec->slot_n = 2; /* Two mezzanines */
svec->fmcs = NULL;
svec->dev = pdev;
svec->map[MAP_CR_CSR] = NULL;
svec->map[MAP_REG] = NULL;
svec->fmc[0] = svec->fmc[1] = NULL;
svec->already_reprogrammed = 0;
/* Alloc fmc structs memory */
svec->fmcs = kzalloc(svec->slot_n * sizeof(struct fmc_device), GFP_KERNEL);
if (!svec->fmcs) return -ENOMEM;
/* Map CR/CSR space */
error = map_window(svec, MAP_CR_CSR, VME_CR_CSR,
VME_D32, svec->vmebase1, 0x80000);
......@@ -452,15 +461,21 @@ static int __devinit svec_probe(struct device *pdev, unsigned int ndev)
dev_info(pdev, "A32 mapping successful at 0x%p\n",
svec->map[MAP_REG]->kernel_va);
/* fmc devices creation */
for (i=0; i<2; i++) {
dev_err(pdev, "Creating fmc device for mezzanine #%d...\n", i+1);
/* fmc structures filling */
for (i=0; i<svec->slot_n; i++) {
error = svec_fmc_create(svec, i);
if (error)
goto failed_unmap;
else
dev_info(pdev, "fmc device created for mezzanine #%d\n", i+1);
}
/* fmc device creation */
error = fmc_device_register_n(svec->fmcs, svec->slot_n);
if (error) {
dev_err(pdev, "Error registering fmc devices\n");
goto failed_unmap;
}
dev_info(pdev, "%d fmc devices registered\n", svec->slot_n);
return 0;
failed_unmap:
......@@ -468,6 +483,8 @@ failed_unmap:
unmap_window(svec, MAP_REG);
failed:
kfree(svec->fmcs);
svec->fmcs = NULL;
kfree(svec);
return -EINVAL;
}
......
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