Commit 7b5f5b9b authored by Luis Fernando Ruiz's avatar Luis Fernando Ruiz

FMC related code for svec.

parent 6d6d4117
This diff is collapsed.
......@@ -19,6 +19,10 @@
#define SVEC_MAX_DEVICES 32
#define SVEC_DEFAULT_IDX { [0 ... (SVEC_MAX_DEVICES-1)] = -1 }
enum svec_map_win {
MAP_CR_CSR = 0, /* CR/CSR */
MAP_REG /* A32 space */
};
/* Our device structure */
struct svec_dev {
......@@ -35,7 +39,7 @@ struct svec_dev {
char driver[16];
char description[80];
struct vme_mapping *cr_csr;
struct vme_mapping *map[2];
/* struct work_struct work; */
const struct firmware *fw;
......
......@@ -72,48 +72,52 @@ static inline unsigned int swapbe32(unsigned int val)
((val & 0xff00) << 8) | ((val & 0xff) << 24));
}
int map_cr_csr(struct svec_dev *svec)
int map_window( struct svec_dev *svec,
enum svec_map_win win,
enum vme_address_modifier am,
enum vme_data_width dw,
unsigned long base,
unsigned int size)
{
int rval;
if (svec->cr_csr != NULL) {
printk(KERN_ERR PFX "Error: CS/CSR already mapped?\n");
if (svec->map[win] != NULL) {
printk(KERN_ERR PFX "Error: window %d already mapped\n", (int)win);
return -EPERM;
}
svec->cr_csr = kzalloc(sizeof(struct vme_mapping), GFP_KERNEL);
if (!svec->cr_csr) {
svec->map[win] = kzalloc(sizeof(struct vme_mapping), GFP_KERNEL);
if (!svec->map[win]) {
printk(KERN_ERR PFX "kzalloc failed allocating memory for vme_mapping struct\n");
return -ENOMEM;
}
/* CS/CSR mapping*/
svec->cr_csr->am = VME_CR_CSR; /* 0x2f */
svec->cr_csr->data_width = VME_D32;
svec->cr_csr->vme_addru = 0;
svec->cr_csr->vme_addrl = svec->vmebase1;
svec->cr_csr->sizeu = 0;
svec->cr_csr->sizel = 0x80000;
svec->cr_csr->window_num = 0;
svec->cr_csr->bcast_select = 0;
svec->cr_csr->read_prefetch_enabled = 0;
printk(KERN_ERR PFX "Mapping CR/CSR space\n");
if (( rval = vme_find_mapping(svec->cr_csr, 1)) != 0) {
printk(KERN_ERR PFX "Failed to map CS_CSR (%d)\n", rval);
/* Window mapping*/
svec->map[win]->am = am; /* 0x2f */
svec->map[win]->data_width = dw;
svec->map[win]->vme_addru = 0;
svec->map[win]->vme_addrl = base;
svec->map[win]->sizeu = 0;
svec->map[win]->sizel = size;
if (( rval = vme_find_mapping(svec->map[win], 1)) != 0) {
printk(KERN_ERR PFX "Failed to map window %d: (%d)\n", (int)win, rval);
return -EINVAL;
}
printk(KERN_ERR PFX "CR/CSR mapping successful at 0x%p\n", svec->cr_csr->kernel_va);
return 0;
}
int unmap_cr_csr(struct svec_dev *svec) {
if (vme_release_mapping(svec->cr_csr, 1)) {
printk(KERN_ERR PFX "Unmap CR/CSR window failed\n");
int unmap_window(struct svec_dev *svec, enum svec_map_win win)
{
if (svec->map[win] == NULL) {
printk(KERN_ERR PFX "window %d not mapped. Cannot unmap\n", (int)win);
return -EINVAL;
}
printk(KERN_ERR PFX "CR/CSR window unmaped\n");
if (vme_release_mapping(svec->map[win], 1)) {
printk(KERN_ERR PFX "Unmap for window %d failed\n", (int)win);
return -EINVAL;
}
printk(KERN_ERR PFX "window %d unmaped\n", (int)win);
return 0;
}
......@@ -136,12 +140,12 @@ int svec_bootloader_unlock (struct svec_dev *svec)
int i;
/* Check if CS/CSR window is mapped */
if (svec->cr_csr == NULL) {
if (svec->map[MAP_CR_CSR] == NULL) {
printk(KERN_ERR PFX "CS/CSR window not found\n");
return -EINVAL;
}
addr = svec->cr_csr->kernel_va + BASE_LOADER + XLDR_REG_BTRIGR;
addr = svec->map[MAP_CR_CSR]->kernel_va + BASE_LOADER + XLDR_REG_BTRIGR;
/* Magic sequence: unlock bootloader mode, disable application FPGA */
for (i=0; i<8; i++)
......@@ -159,12 +163,12 @@ int svec_bootloader_is_active(struct svec_dev *svec)
void *addr;
/* Check if CS/CSR window is mapped */
if (svec->cr_csr == NULL) {
if (svec->map[MAP_CR_CSR] == NULL) {
printk(KERN_ERR PFX "CS/CSR window not found\n");
return -EINVAL;
}
addr = svec->cr_csr->kernel_va + BASE_LOADER + XLDR_REG_IDR;
addr = svec->map[MAP_CR_CSR]->kernel_va + BASE_LOADER + XLDR_REG_IDR;
idc = swapbe32(ioread32(addr));
idc = htonl(idc);
......@@ -188,17 +192,15 @@ static u8 csr_read(void *base, u32 offset)
char *p = base;
u8 value;
value = ioread8(p + offset);
pr_debug("read: 0x%08x -> 0x%02x\n", (u32)(p+offset), value);
offset -= offset % 4;
value = ioread32be(p + offset);
return value;
}
static void csr_write(u8 value, void *base, u32 offset)
{
char *p = base;
pr_debug("write: 0x%08x <- 0x%02x\n", (u32)(p+offset), value);
iowrite8(value, p + offset);
offset -= offset % 4;
iowrite32be(value, base + offset);
}
void setup_csr_fa0(void *base, u32 vme, unsigned vector, unsigned level)
......@@ -233,6 +235,17 @@ void setup_csr_fa0(void *base, u32 vme, unsigned vector, unsigned level)
/* enable module, hence make FUN0 available */
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));
pr_debug("vector: %02x\n", csr_read(base, INTVECTOR));
pr_debug("level: %02x\n", csr_read(base, INT_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)
......@@ -254,7 +267,7 @@ int svec_load_fpga(struct svec_dev *svec, const void *blob, int size)
}
/* Check if CS/CSR window is mapped */
if (svec->cr_csr == NULL) {
if (svec->map[MAP_CR_CSR] == NULL) {
printk(KERN_ERR PFX "CS/CSR window not found\n");
return -EINVAL;
}
......@@ -272,7 +285,7 @@ int svec_load_fpga(struct svec_dev *svec, const void *blob, int size)
}
/* FPGA loader virtual address */
loader_addr = svec->cr_csr->kernel_va + BASE_LOADER;
loader_addr = svec->map[MAP_CR_CSR]->kernel_va + BASE_LOADER;
iowrite32(swapbe32(XLDR_CSR_SWRST), loader_addr + XLDR_REG_CSR);
iowrite32(swapbe32(XLDR_CSR_START | XLDR_CSR_MSBF), loader_addr + XLDR_REG_CSR);
......@@ -311,7 +324,7 @@ 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 *card = dev_get_drvdata(pdev);
struct svec_dev *svec = dev_get_drvdata(pdev);
printk(KERN_ERR PFX "%s\n", __func__);
......@@ -325,8 +338,8 @@ static int __devexit svec_remove(struct device *pdev, unsigned int ndev)
*/
/* avoid deleting unregistered devices */
/*
if (card) {
if (card->cdev.owner == THIS_MODULE) {
if (svec) {
if (svec->cdev.owner == THIS_MODULE) {
printk(KERN_ERR PFX "unregister_chrdev_region\n");
unregister_chrdev_region(devno, lun_num);
}
......@@ -335,7 +348,10 @@ static int __devexit svec_remove(struct device *pdev, unsigned int ndev)
printk(KERN_ERR PFX "card is null!\n");
*/
unmap_cr_csr(card);
unmap_window(svec, MAP_CR_CSR);
unmap_window(svec, MAP_REG);
if (svec->fmc != NULL)
svec_fmc_destroy(svec);
return 0;
}
......@@ -416,12 +432,19 @@ static int __devinit svec_probe(struct device *pdev, unsigned int ndev)
svec->level = level[ndev];
svec->fw_name = fw_name[ndev];
svec->dev = pdev;
svec->cr_csr = NULL;
svec->map[MAP_CR_CSR] = NULL;
svec->map[MAP_REG] = NULL;
svec->fmc = NULL;
/* Map CS/CSR space */
error = map_cr_csr(svec);
if (error)
/* Map CR/CSR space */
error = map_window(svec, MAP_CR_CSR, VME_CR_CSR,
VME_D32, svec->vmebase1, 0x80000);
if (error) {
printk(KERN_ERR PFX "error mapping CR/CSR space\n");
goto failed;
}
printk(KERN_ERR PFX "CR/CSR mapping successful at 0x%p\n",
svec->map[MAP_CR_CSR]->kernel_va);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
name = pdev->bus_id;
......@@ -473,21 +496,35 @@ static int __devinit svec_probe(struct device *pdev, unsigned int ndev)
goto failed;
/* configure and activate function 0 */
setup_csr_fa0(svec->cr_csr->kernel_va, vmebase2[ndev],
setup_csr_fa0(svec->map[MAP_CR_CSR]->kernel_va, vmebase2[ndev],
vector[ndev], level[ndev]);
/* Map A32 space */
error = map_window(svec, MAP_REG, VME_A32_USER_DATA_SCT,
VME_D32, svec->vmebase2, 0x100000);
if (error) {
printk(KERN_ERR PFX "error mapping CR/CSR space\n");
goto failed;
}
printk(KERN_ERR PFX "A32 mapping successful at 0x%p\n",
svec->map[MAP_REG]->kernel_va);
/* fmc creation */
error = svec_fmc_create(svec);
if (error)
goto failed_unmap;
return 0;
/*
device_create_failed:
cdev_del(&svec->cdev);
*/
failed_unmap:
unmap_window(svec, MAP_CR_CSR);
unmap_window(svec, MAP_REG);
failed:
kfree(svec);
return -EINVAL;
out:
return error;
}
static struct vme_driver svec_driver = {
......@@ -534,6 +571,7 @@ static void __exit svec_exit(void)
pr_debug("%s\n", __func__);
vme_unregister_driver(&svec_driver);
class_destroy(svec_class);
unregister_chrdev_region(svec_devno, lun_num);
pr_debug(PFX "class_destroy\n");
}
......
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