Commit 81b05911 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

kernel: fixed SDB enumeration for gatewares containing different mezzanine cores

parent 440342bc
...@@ -25,7 +25,7 @@ obj-m := fmc-fine-delay.o ...@@ -25,7 +25,7 @@ obj-m := fmc-fine-delay.o
fmc-fine-delay-objs = fd-zio.o fd-irq.o fd-core.o fmc-fine-delay-objs = fd-zio.o fd-irq.o fd-core.o
fmc-fine-delay-objs += onewire.o spi.o i2c.o gpio.o fmc-fine-delay-objs += onewire.o spi.o i2c.o gpio.o
fmc-fine-delay-objs += acam.o calibrate.o pll.o time.o fmc-fine-delay-objs += acam.o calibrate.o pll.o time.o
fmc-fine-delay-objs += calibration.o fmc-fine-delay-objs += calibration.o fmc-util.o
fmc-fine-delay-objs += ../sdb-lib/access.o fmc-fine-delay-objs += ../sdb-lib/access.o
fmc-fine-delay-objs += ../sdb-lib/glue.o fmc-fine-delay-objs += ../sdb-lib/glue.o
......
...@@ -129,7 +129,7 @@ int fd_probe(struct fmc_device *fmc) ...@@ -129,7 +129,7 @@ int fd_probe(struct fmc_device *fmc)
struct fd_dev *fd; struct fd_dev *fd;
struct device *dev = &fmc->dev; struct device *dev = &fmc->dev;
char *fwname; char *fwname;
int i, index, ret, ch; int i, index, ret, ch, ord;
fd = kzalloc(sizeof(*fd), GFP_KERNEL); fd = kzalloc(sizeof(*fd), GFP_KERNEL);
if (!fd) { if (!fd) {
...@@ -169,14 +169,15 @@ int fd_probe(struct fmc_device *fmc) ...@@ -169,14 +169,15 @@ int fd_probe(struct fmc_device *fmc)
fmc_show_sdb_tree(fmc); fmc_show_sdb_tree(fmc);
/* Now use SDB to find the base addresses */ /* Now use SDB to find the base addresses */
fd->fd_regs_base =
fmc_find_sdb_device(fmc->sdb, 0xce42, 0xf19ede1a, NULL); ord = fmc->slot_id;
/* ugly hack for svec testing*/ fd->fd_regs_base = fmc_sdb_find_nth_device ( fmc->sdb, 0xce42, 0xf19ede1a, &ord, NULL );
/* FIXME: this depends on 0x10000/0x20000 being the FD cores if( (signed long)fd->fd_regs_base < 0)
* base addresses */ {
if (!strcmp(fmc->carrier_name, "SVEC") && fmc->slot_id == 1) dev_err(dev, "Can't find the FD core. Wrong gateware?\n");
fd->fd_regs_base += 0x10000; }
dev_info(dev, "fd_regs_base is %x\n", fd->fd_regs_base); dev_info(dev, "fd_regs_base is %x\n", fd->fd_regs_base);
fd->fd_owregs_base = fd->fd_regs_base + 0x500; fd->fd_owregs_base = fd->fd_regs_base + 0x500;
......
...@@ -382,6 +382,7 @@ extern int fd_eeprom_write(struct fd_dev *fd, int i2c_addr, uint32_t offset, ...@@ -382,6 +382,7 @@ extern int fd_eeprom_write(struct fd_dev *fd, int i2c_addr, uint32_t offset,
/* Function exported by calibration.c */ /* Function exported by calibration.c */
int fd_handle_eeprom_calibration(struct fd_dev *fd); int fd_handle_eeprom_calibration(struct fd_dev *fd);
signed long fmc_sdb_find_nth_device (struct sdb_array *tree, uint64_t vid, uint32_t did, int *ordinal, uint32_t *size );
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* __FINE_DELAY_H__ */ #endif /* __FINE_DELAY_H__ */
/*
* Some utility functions not supported in the current version of fmc-bus.
*
* Copyright (C) 2012-2014 CERN (www.cern.ch)
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* Author: Alessandro Rubini <rubini@gnudd.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2 as published by the Free Software Foundation or, at your
* option, any later version.
*/
#include <linux/fmc.h>
#include <linux/fmc-sdb.h>
#include <linux/err.h>
#include <asm/byteorder.h>
#include "fine-delay.h"
typedef int (*sdb_traverse_cb) (uint32_t address, uint32_t size, uint64_t vid, uint32_t did);
static int traverse_sdb_devices(struct sdb_array *tree,
sdb_traverse_cb cb)
{
union sdb_record *r;
struct sdb_product *p;
struct sdb_component *c;
int i, n = tree->len, rv;
uint64_t last, first, vid;
uint32_t did, size;
/* FIXME: what if the first interconnect is not at zero? */
for (i = 0; i < n; i++) {
r = &tree->record[i];
c = &r->dev.sdb_component;
p = &c->product;
if (!IS_ERR(tree->subtree[i]))
{
rv = traverse_sdb_devices ( tree->subtree[i], cb );
if(rv > 0)
return 1;
}
if (r->empty.record_type != sdb_type_device)
continue;
/* record is a device?*/
last = __be64_to_cpu(c->addr_last);
first = __be64_to_cpu(c->addr_first);
vid = __be64_to_cpu(p->vendor_id);
did = __be32_to_cpu(p->device_id);
size = (uint32_t) (last + 1 - first);
if (cb (first + tree->baseaddr, size, vid, did))
return 1;
}
return 0;
}
/* Finds the Nth SDB device that matches (vid/did) pair, where N <= *ordinal.
If N < *ordinal, the value of N is stored at *ordinal.
This magic is used to handle hybrid bistreams (with two or more different
mezzanines). */
signed long fmc_sdb_find_nth_device (struct sdb_array *tree, uint64_t vid, uint32_t did, int *ordinal, uint32_t *size )
{
int n = -1;
uint32_t current_address;
uint32_t current_size;
int callback (uint32_t address, uint32_t size, uint64_t vid_, uint32_t did_)
{
if(vid_ == vid && did_ == did)
{
n++;
current_address = address;
current_size = size;
if(!ordinal || n == *ordinal)
{
return 1;
}
}
return 0; /* continue scanning */
}
traverse_sdb_devices (tree, callback);
if (n >= 0)
{
if(size)
*size = current_size;
if(ordinal)
*ordinal = n;
return current_address;
}
return -ENODEV;
}
\ No newline at end of file
...@@ -72,7 +72,7 @@ static int ow_reset(struct fd_dev *fd, int port) ...@@ -72,7 +72,7 @@ static int ow_reset(struct fd_dev *fd, int port)
| CSR_CYC_MSK | CSR_RST_MSK; | CSR_CYC_MSK | CSR_RST_MSK;
ow_writel(fd, data, R_CSR); ow_writel(fd, data, R_CSR);
while(ow_readl(fd, R_CSR) & CSR_CYC_MSK) while(ow_readl(fd, R_CSR) & CSR_CYC_MSK)
/* FIXME: timeout */; udelay(10);
reg = ow_readl(fd, R_CSR); reg = ow_readl(fd, R_CSR);
return ~reg & CSR_DAT_MSK; return ~reg & CSR_DAT_MSK;
} }
...@@ -85,7 +85,7 @@ static int slot(struct fd_dev *fd, int port, int bit) ...@@ -85,7 +85,7 @@ static int slot(struct fd_dev *fd, int port, int bit)
| CSR_CYC_MSK | (bit & CSR_DAT_MSK); | CSR_CYC_MSK | (bit & CSR_DAT_MSK);
ow_writel(fd, data, R_CSR); ow_writel(fd, data, R_CSR);
while(ow_readl(fd, R_CSR) & CSR_CYC_MSK) while(ow_readl(fd, R_CSR) & CSR_CYC_MSK)
/* FIXME: timeout */; udelay(10);
reg = ow_readl(fd, R_CSR); reg = ow_readl(fd, R_CSR);
return reg & CSR_DAT_MSK; return reg & CSR_DAT_MSK;
} }
......
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