Commit 969ee716 authored by Federico Vaga's avatar Federico Vaga

kernel: always reset FPGA after programming

There should not be any side effect on resetting the FGPA every time
we program it. Confirmed by Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent c1db3e8a
...@@ -161,3 +161,17 @@ void gpiofix_low_level(int fd, void __iomem *bar4) ...@@ -161,3 +161,17 @@ void gpiofix_low_level(int fd, void __iomem *bar4)
gpio_out(fd, bar4, GNGPIO_OUTPUT_ENABLE, GPIO_BOOTSEL0, 0); gpio_out(fd, bar4, GNGPIO_OUTPUT_ENABLE, GPIO_BOOTSEL0, 0);
gpio_out(fd, bar4, GNGPIO_OUTPUT_ENABLE, GPIO_BOOTSEL1, 0); gpio_out(fd, bar4, GNGPIO_OUTPUT_ENABLE, GPIO_BOOTSEL1, 0);
} }
void loader_reset_fpga(int fd, void __iomem *bar4)
{
uint32_t reg;
/* After reprogramming, reset the FPGA using the gennum register */
reg = lll_read(fd, bar4, GNPCI_SYS_CFG_SYSTEM);
/*
* This _fucking_ register must be written with extreme care,
* becase some fields are "protected" and some are not. *hate*
*/
lll_write(fd, bar4, (reg & ~0xffff) | 0x3fff, GNPCI_SYS_CFG_SYSTEM);
lll_write(fd, bar4, (reg & ~0xffff) | 0x7fff, GNPCI_SYS_CFG_SYSTEM);
}
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
extern int loader_low_level(int fd, void __iomem *bar4, const void *, int); extern int loader_low_level(int fd, void __iomem *bar4, const void *, int);
extern void waitdone_low_level(int fd, void __iomem *bar4); extern void waitdone_low_level(int fd, void __iomem *bar4);
extern void gpiofix_low_level(int fd, void __iomem *bar4); extern void gpiofix_low_level(int fd, void __iomem *bar4);
extern void loader_reset_fpga(int fd, void __iomem *bar4);
/* The following part implements a different access rule for user and kernel */ /* The following part implements a different access rule for user and kernel */
......
...@@ -45,7 +45,6 @@ static int spec_reprogram(struct fmc_device *fmc, struct fmc_driver *drv, ...@@ -45,7 +45,6 @@ static int spec_reprogram(struct fmc_device *fmc, struct fmc_driver *drv,
const struct firmware *fw; const struct firmware *fw;
struct spec_dev *spec = fmc->carrier_data; struct spec_dev *spec = fmc->carrier_data;
struct device *dev = fmc->hwdev; struct device *dev = fmc->hwdev;
uint32_t reg;
int ret; int ret;
if (!gw) if (!gw)
...@@ -79,15 +78,6 @@ static int spec_reprogram(struct fmc_device *fmc, struct fmc_driver *drv, ...@@ -79,15 +78,6 @@ static int spec_reprogram(struct fmc_device *fmc, struct fmc_driver *drv,
else else
fmc->flags |= FMC_DEVICE_HAS_CUSTOM; fmc->flags |= FMC_DEVICE_HAS_CUSTOM;
/* After reprogramming, reset the FPGA using the gennum register */
reg = gennum_readl(spec, GNPCI_SYS_CFG_SYSTEM);
/*
* This _fucking_ register must be written with extreme care,
* becase some fields are "protected" and some are not. *hate*
*/
gennum_writel(spec, (reg & ~0xffff) | 0x3fff, GNPCI_SYS_CFG_SYSTEM);
gennum_writel(spec, (reg & ~0xffff) | 0x7fff, GNPCI_SYS_CFG_SYSTEM);
out: out:
release_firmware(fw); release_firmware(fw);
return ret; return ret;
......
...@@ -36,6 +36,7 @@ int spec_load_fpga(struct spec_dev *spec, const void *data, int size) ...@@ -36,6 +36,7 @@ int spec_load_fpga(struct spec_dev *spec, const void *data, int size)
struct device *dev = &spec->pdev->dev; struct device *dev = &spec->pdev->dev;
int i, wrote; int i, wrote;
unsigned long j; unsigned long j;
uint32_t reg;
/* loader_low_level is designed to run from user space too */ /* loader_low_level is designed to run from user space too */
wrote = loader_low_level(0 /* unused fd */, wrote = loader_low_level(0 /* unused fd */,
...@@ -62,6 +63,8 @@ int spec_load_fpga(struct spec_dev *spec, const void *data, int size) ...@@ -62,6 +63,8 @@ int spec_load_fpga(struct spec_dev *spec, const void *data, int size)
} }
} }
gpiofix_low_level(0 /* unused fd */, spec->remap[2]); gpiofix_low_level(0 /* unused fd */, spec->remap[2]);
loader_reset_fpga(0 /* unused fd */, spec->remap[2]);
return 0; return 0;
} }
......
...@@ -12,7 +12,7 @@ extern int loader_low_level( ...@@ -12,7 +12,7 @@ extern int loader_low_level(
void __iomem *bar4, /* This is ignored in user space */ void __iomem *bar4, /* This is ignored in user space */
const void *data, const void *data,
int size8); int size8);
extern void loader_reset_fpga(int fd, void __iomem *bar4);
...@@ -40,7 +40,7 @@ enum { ...@@ -40,7 +40,7 @@ enum {
FCL_TIMER2_1 = FCL_BASE + 0x30, FCL_TIMER2_1 = FCL_BASE + 0x30,
FCL_DBG_STS = FCL_BASE + 0x34, FCL_DBG_STS = FCL_BASE + 0x34,
FCL_FIFO = 0xE00, FCL_FIFO = 0xE00,
PCI_SYS_CFG_SYSTEM = 0x800 GNPCI_SYS_CFG_SYSTEM = 0x800
}; };
......
...@@ -278,6 +278,7 @@ int spec_load_bitstream_buffer(void *card, void *buf, size_t size) ...@@ -278,6 +278,7 @@ int spec_load_bitstream_buffer(void *card, void *buf, size_t size)
rv = loader_low_level(0, p->bar4, buf, size); rv = loader_low_level(0, p->bar4, buf, size);
waitdone_low_level(0, p->bar4); waitdone_low_level(0, p->bar4);
gpiofix_low_level(0, p->bar4); gpiofix_low_level(0, p->bar4);
loader_reset_fpga(0, p->bar4);
return rv; return rv;
} }
......
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