Commit 15f9aa0a authored by Federico Vaga's avatar Federico Vaga

sw:drv: wait for DDR calibration with timeout

In the following commit we have added a 1ms delay before checking the
DDR calibration status. We thought it to be enough, but it is not. On
some designs the calibration takes more time.

commit 2647a65e ("sw:drv: add delay before checking DDR status")

This patch polls for the DDR calibration status and waits until it is
complete or the timeout expires. The timeout is set to 1s, if it happens
it is really a bad sign, and it should not be considered acceptable.
Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent e4987acf
......@@ -544,6 +544,37 @@ static struct resource spec_fpga_dma_res[] = {
},
};
static int spec_fpga_ddr_wait_calibration(struct spec_fpga *spec_fpga,
unsigned int timeout_us)
{
unsigned long timeout;
uint32_t ddr_status;
timeout = jiffies + usecs_to_jiffies(timeout_us);
do {
cpu_relax();
if (time_after(jiffies, timeout))
return -ETIMEDOUT;
ddr_status = ioread32(spec_fpga->fpga + SPEC_FPGA_CSR_DDR_STATUS);
} while (!(ddr_status & SPEC_FPGA_CSR_DDR_STATUS_DONE));
return 0;
}
static int spec_fpga_ddr_init(struct spec_fpga *spec_fpga)
{
int err;
err = spec_fpga_ddr_wait_calibration(spec_fpga, 1000000);
if (err) {
dev_err(&spec_fpga->dev,
"DDR controller calibration timeout\n");
return err;
}
return 0;
}
static int spec_fpga_dma_init(struct spec_fpga *spec_fpga)
{
struct pci_dev *pcidev = to_pci_dev(spec_fpga->dev.parent);
......@@ -552,19 +583,15 @@ static int spec_fpga_dma_init(struct spec_fpga *spec_fpga)
struct resource res[ARRAY_SIZE(spec_fpga_dma_res)];
struct platform_device *pdev;
struct irq_domain *vic_domain;
uint32_t ddr_status;
int err;
if (!(spec_fpga->meta->cap & SPEC_META_CAP_DMA))
return 0;
mdelay(1);
ddr_status = ioread32(spec_fpga->fpga + SPEC_FPGA_CSR_DDR_STATUS);
if (!(ddr_status & SPEC_FPGA_CSR_DDR_STATUS_DONE)) {
dev_err(&spec_fpga->dev,
"Failed to load DMA engine: DDR controller not calibrated - 0x%x.\n",
ddr_status);
return -ENODEV;
}
err = spec_fpga_ddr_init(spec_fpga);
if (err)
return err;
vic_domain = spec_fpga_irq_find_host(&spec_fpga->vic_pdev->dev);
if (!vic_domain) {
dev_err(&spec_fpga->dev,
......
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