Commit c98922fa authored by Federico Vaga's avatar Federico Vaga

drv: first draft of 'The Convention'

Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent a42c3f2a
......@@ -30,6 +30,7 @@ KBUILD_EXTRA_SYMBOLS += $(FMC_ABS)/drivers/fmc/Module.symvers
obj-m := spec-fmc-carrier.o
spec-fmc-carrier-objs := spec-core.o
spec-fmc-carrier-objs += spec-core-fpga.o
spec-fmc-carrier-objs += spec-fpga.o
spec-fmc-carrier-objs += spec-dbg.o
spec-fmc-carrier-objs += spec-fmc.o
......
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2019 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
*/
#include <linux/types.h>
#include <linux/platform_data/i2c-ocores.h>
#include <linux/ioport.h>
#include <linux/gpio/consumer.h>
#include <linux/irqdomain.h>
#include "spec.h"
#include "spec-compat.h"
/* FIXME find better ID */
static int vic_id;
static int i2c_id;
static int app_id;
enum spec_core_fpga_res_enum {
SPEC_CORE_FPGA_FMC_I2C_MEM = 0,
SPEC_CORE_FPGA_FMC_I2C_IRQ,
SPEC_CORE_FPGA_VIC_MEM,
SPEC_CORE_FPGA_VIC_IRQ,
};
static const struct resource spec_core_fpga_res[] = {
[SPEC_CORE_FPGA_FMC_I2C_MEM] = {
.name = "i2c-ocores-mem",
.flags = IORESOURCE_MEM,
.start = SPEC_CORE_FPGA + 0x0080,
.end = SPEC_CORE_FPGA + 0x009F,
},
[SPEC_CORE_FPGA_FMC_I2C_IRQ] = {
.name = "i2c_ocores-irq",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 2,
.end = 2,
},
[SPEC_CORE_FPGA_VIC_MEM] = {
.name = "htvic-mem",
.flags = IORESOURCE_MEM,
.start = SPEC_CORE_FPGA + 0x0100,
.end = SPEC_CORE_FPGA + 0x01FF,
},
[SPEC_CORE_FPGA_VIC_IRQ] = {
.name = "htvic-irq",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 0,
.end = 0,
},
};
static const struct ocores_i2c_platform_data i2c_pdata = {
.reg_shift = 2, /* 32bit aligned */
.reg_io_width = 4,
.clock_khz = 62500,
.big_endian = 0,
.num_devices = 0,
.devices = NULL,
};
static int spec_core_fpga_vic_init(struct spec_dev *spec)
{
struct pci_dev *pcidev = to_pci_dev(spec->dev.parent);
unsigned long pci_start = pci_resource_start(pcidev, 0);
const unsigned int res_n = 2;
struct resource res[res_n];
struct platform_device *pdev;
if (!(spec->meta->cap & SPEC_META_CAP_VIC))
return 0;
memcpy(&res, &spec_core_fpga_res[SPEC_CORE_FPGA_VIC_MEM],
sizeof(struct resource) * res_n);
res[0].start += pci_start;
res[0].end += pci_start;
res[1].start = gpiod_to_irq(spec->gpiod[GN4124_GPIO_IRQ1]);
res[1].end = res[1].start;
pdev = platform_device_register_resndata(&spec->dev,
"htvic-spec", vic_id++,
res, res_n,
NULL, 0);
if (IS_ERR(pdev))
return PTR_ERR(pdev);
spec->vic_pdev = pdev;
return 0;
}
static void spec_core_fpga_vic_exit(struct spec_dev *spec)
{
if (spec->vic_pdev) {
platform_device_unregister(spec->vic_pdev);
spec->vic_pdev = NULL;
}
}
static int spec_core_fpga_i2c_init(struct spec_dev *spec)
{
struct pci_dev *pcidev = to_pci_dev(spec->dev.parent);
unsigned long pci_start = pci_resource_start(pcidev, 0);
unsigned int res_n = 2;
struct resource res[res_n];
struct platform_device *pdev;
struct irq_domain *vic_domain;
memcpy(&res, &spec_core_fpga_res[SPEC_CORE_FPGA_FMC_I2C_MEM],
sizeof(struct resource) * res_n);
res[0].start += pci_start;
res[0].end += pci_start;
if (spec->vic_pdev)
vic_domain = irq_find_host((void *)&spec->vic_pdev->dev);
else
vic_domain = NULL;
if (vic_domain) {
res[1].start = irq_find_mapping(vic_domain,
res[1].start);
res[1].end = res[1].start;
} else {
res_n = 1;
}
pdev = platform_device_register_resndata(&spec->dev,
"i2c-ohwr", i2c_id++,
res, res_n,
&i2c_pdata,
sizeof(i2c_pdata));
if (IS_ERR(pdev))
return PTR_ERR(pdev);
spec->i2c_pdev = pdev;
return 0;
}
static void spec_core_fpga_i2c_exit(struct spec_dev *spec)
{
if (spec->i2c_pdev) {
platform_device_unregister(spec->i2c_pdev);
spec->i2c_pdev = NULL;
}
}
#define SPEC_CORE_FPGA_THERM_BASE (SPEC_CORE_FPGA + 0x50)
#define SPEC_CORE_FPGA_THERM_SERID_MSB (SPEC_CORE_FPGA_THERM_BASE + 0x0)
#define SPEC_CORE_FPGA_THERM_SERID_LSB (SPEC_CORE_FPGA_THERM_BASE + 0x4)
#define SPEC_CORE_FPGA_THERM_TEMP (SPEC_CORE_FPGA_THERM_BASE + 0x8)
static ssize_t temperature_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct spec_dev *spec = to_spec_dev(dev);
uint32_t temp = ioread32(spec->fpga + SPEC_CORE_FPGA_THERM_TEMP);
return snprintf(buf, PAGE_SIZE, "%d.%d C\n",
temp / 16, (temp & 0xF) * 1000 / 16);
}
static DEVICE_ATTR_RO(temperature);
static ssize_t serial_number_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct spec_dev *spec = to_spec_dev(dev);
return snprintf(buf, PAGE_SIZE, "0x%08x%08x\n",
ioread32(spec->fpga + SPEC_CORE_FPGA_THERM_SERID_MSB),
ioread32(spec->fpga + SPEC_CORE_FPGA_THERM_SERID_LSB));
}
static DEVICE_ATTR_RO(serial_number);
static struct attribute *spec_core_fpga_therm_attrs[] = {
&dev_attr_serial_number.attr,
&dev_attr_temperature.attr,
NULL,
};
static const struct attribute_group spec_core_fpga_therm_group = {
.name = "thermometer",
.attrs = spec_core_fpga_therm_attrs,
};
static int spec_core_fpga_therm_init(struct spec_dev *spec)
{
int err;
clear_bit(SPEC_FLAG_THERM_BIT, spec->flags);
if (!(spec->meta->cap & SPEC_META_CAP_THERM))
return 0;
err = sysfs_create_group(&spec->dev.kobj,
&spec_core_fpga_therm_group);
if (err)
return err;
set_bit(SPEC_FLAG_THERM_BIT, spec->flags);
return 0;
}
static void spec_core_fpga_therm_exit(struct spec_dev *spec)
{
if (!(test_bit(SPEC_FLAG_THERM_BIT, spec->flags)))
return;
sysfs_remove_group(&spec->dev.kobj, &spec_core_fpga_therm_group);
}
#define SPEC_CORE_FPGA_APP_OFF (SPEC_CORE_FPGA + 0x40)
static void spec_core_fpga_app_id_build(struct spec_dev *spec,
unsigned long app_off,
char *id, unsigned int size)
{
uint32_t vendor = ioread32(spec->fpga + app_off);
uint32_t device = ioread32(spec->fpga + app_off);
memset(id, 0, size);
if (vendor == 0xFF000000) {
uint32_t vendor_uuid[4];
vendor_uuid[0] = ioread32(spec->fpga + app_off + 0x30);
vendor_uuid[1] = ioread32(spec->fpga + app_off + 0x34);
vendor_uuid[2] = ioread32(spec->fpga + app_off + 0x38);
vendor_uuid[3] = ioread32(spec->fpga + app_off + 0x3C);
snprintf(id, size, "cern:%16phN:%4phN", &vendor_uuid, &device);
} else {
snprintf(id, size, "cern:%4phN:%4phN", &vendor, &device);
}
}
static int spec_core_fpga_app_init(struct spec_dev *spec)
{
#define SPEC_CORE_FPGA_APP_NAME_MAX 47
#define SPEC_CORE_FPGA_APP_IRQ_BASE 5
#define SPEC_CORE_FPGA_APP_RES_N 28
struct pci_dev *pcidev = to_pci_dev(spec->dev.parent);
unsigned int res_n = SPEC_CORE_FPGA_APP_RES_N;
struct resource res[SPEC_CORE_FPGA_APP_RES_N] = {
[0] = {
.name = "app-mem",
.flags = IORESOURCE_MEM,
},
};
struct platform_device *pdev;
struct irq_domain *vic_domain;
char app_name[SPEC_CORE_FPGA_APP_NAME_MAX];
unsigned long app_offset;
app_offset = ioread32(spec->fpga + SPEC_CORE_FPGA_APP_OFF);
if (!app_offset) {
dev_warn(spec->dev.parent, "Application not found\n");
return 0;
}
res[0].start = pci_resource_start(pcidev, 0) + app_offset;
res[0].end = pci_resource_end(pcidev, 0);
if (spec->vic_pdev)
vic_domain = irq_find_host((void *)&spec->vic_pdev->dev);
else
vic_domain = NULL;
if (vic_domain) {
int i, hwirq;
for (i = 1, hwirq = SPEC_CORE_FPGA_APP_IRQ_BASE;
i < SPEC_CORE_FPGA_APP_RES_N;
++i, ++hwirq) {
res[i].name = "app-irq",
res[i].flags = IORESOURCE_IRQ,
res[i].start = irq_find_mapping(vic_domain, hwirq);
res[i].end = res[1].start;
}
} else {
res_n = 1;
}
spec_core_fpga_app_id_build(spec, SPEC_CORE_FPGA_APP_OFF,
app_name, SPEC_CORE_FPGA_APP_NAME_MAX);
pdev = platform_device_register_resndata(&spec->dev,
app_name, app_id++,
res, res_n,
NULL, 0);
if (IS_ERR(pdev))
return PTR_ERR(pdev);
spec->app_pdev = pdev;
return 0;
}
static void spec_core_fpga_app_exit(struct spec_dev *spec)
{
if (spec->app_pdev) {
platform_device_unregister(spec->app_pdev);
spec->app_pdev = NULL;
}
}
static bool spec_core_fpga_is_valid(struct spec_dev *spec)
{
if ((spec->meta->bom & SPEC_META_BOM_END_MASK) != SPEC_META_BOM_LE) {
dev_err(spec->dev.parent,
"Expected Little Endian devices BOM: 0x%x\n",
spec->meta->bom);
return false;
}
if ((spec->meta->bom & SPEC_META_BOM_VER_MASK) != 0) {
dev_err(spec->dev.parent,
"Unknow Metadata specification version BOM: 0x%x\n",
spec->meta->bom);
return false;
}
if (spec->meta->vendor != SPEC_META_VENDOR_ID ||
spec->meta->device != SPEC_META_DEVICE_ID) {
dev_err(spec->dev.parent,
"Unknow vendor/device ID: %08x:%08x\n",
spec->meta->vendor, spec->meta->device);
return false;
}
if (spec->meta->version != SPEC_META_VERSION_1_4) {
dev_err(spec->dev.parent,
"Unknow version: %08x\n", spec->meta->version);
return false;
}
return true;
}
/**
* Initialize carrier devices on FPGA
*/
int spec_core_fpga_init(struct spec_dev *spec)
{
int err;
spec->fpga = spec->remap[0];
spec->meta = spec->fpga + SPEC_META_BASE;
if (!spec_core_fpga_is_valid(spec))
return -EINVAL;
err = spec_core_fpga_vic_init(spec);
if (err)
goto err_vic;
err = spec_core_fpga_i2c_init(spec);
if (err)
goto err_i2c;
err = spec_core_fpga_therm_init(spec);
if (err)
goto err_therm;
err = spec_core_fpga_app_init(spec);
if (err)
goto err_app;
return 0;
err_app:
spec_core_fpga_therm_exit(spec);
err_therm:
spec_core_fpga_i2c_exit(spec);
err_i2c:
spec_core_fpga_vic_exit(spec);
err_vic:
return err;
}
void spec_core_fpga_exit(struct spec_dev *spec)
{
spec_core_fpga_app_exit(spec);
spec_core_fpga_therm_exit(spec);
spec_core_fpga_i2c_exit(spec);
spec_core_fpga_vic_exit(spec);
}
......@@ -163,6 +163,10 @@ static int spec_probe(struct pci_dev *pdev,
if (err)
goto err_fw;
err = spec_core_fpga_init(spec);
if (err)
goto err_core_fpga;
err = spec_fmc_init(spec);
if (err)
goto err_fmc;
......@@ -174,6 +178,8 @@ static int spec_probe(struct pci_dev *pdev,
return 0;
err_fmc:
spec_core_fpga_exit(spec);
err_core_fpga:
err_fw:
spec_fpga_exit(spec);
err_fpga:
......@@ -203,6 +209,7 @@ static void spec_remove(struct pci_dev *pdev)
spec_dbg_exit(spec);
spec_fmc_exit(spec);
spec_core_fpga_exit(spec);
spec_fpga_exit(spec);
spec_gpio_exit(spec);
gn412x_gpio_exit(&spec->gn412x);
......
......@@ -70,6 +70,47 @@ static const struct file_operations spec_dbg_fw_ops = {
.write = spec_dbg_fw_write,
};
static int spec_dbg_meta(struct seq_file *s, void *offset)
{
struct spec_dev *spec = s->private;
seq_printf(s, "'%s':\n", dev_name(spec->dev.parent));
seq_printf(s, "Metadata:\n");
seq_printf(s, " - Vendor: 0x%08x\n", spec->meta->vendor);
seq_printf(s, " - Device: 0x%08x\n", spec->meta->device);
seq_printf(s, " - Version: 0x%08x\n", spec->meta->version);
seq_printf(s, " - BOM: 0x%08x\n", spec->meta->bom);
seq_printf(s, " - SourceID: 0x%08x%08x%08x%08x\n",
spec->meta->src[0],
spec->meta->src[1],
spec->meta->src[2],
spec->meta->src[3]);
seq_printf(s, " - CapabilityMask: 0x%08x\n", spec->meta->cap);
seq_printf(s, " - VendorUUID: 0x%08x%08x%08x%08x\n",
spec->meta->uuid[0],
spec->meta->uuid[1],
spec->meta->uuid[2],
spec->meta->uuid[3]);
return 0;
}
static int spec_dbg_meta_open(struct inode *inode, struct file *file)
{
struct spec_dev *spec = inode->i_private;
return single_open(file, spec_dbg_meta, spec);
}
static const struct file_operations spec_dbg_meta_ops = {
.owner = THIS_MODULE,
.open = spec_dbg_meta_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
/**
* It initializes the debugfs interface
* @spec: SPEC device instance
......@@ -106,6 +147,16 @@ int spec_dbg_init(struct spec_dev *spec)
return PTR_ERR(spec->dbg_fw);
}
spec->dbg_meta = debugfs_create_file(SPEC_DBG_META_NAME, 0200,
spec->dbg_dir, spec,
&spec_dbg_meta_ops);
if (IS_ERR_OR_NULL(spec->dbg_meta)) {
dev_err(&spec->dev,
"Cannot create debugfs file \"%s\" (%ld)\n",
SPEC_DBG_META_NAME, PTR_ERR(spec->dbg_meta));
return PTR_ERR(spec->dbg_meta);
}
return 0;
}
......
......@@ -12,19 +12,11 @@
#include "spec-compat.h"
#define SPEC_FMC_SLOTS 1
#define SPEC_I2C_SIZE 32
#define SPEC_I2C_ADDR_START 0x14000
#define SPEC_I2C_ADDR_END ((SPEC_I2C_ADDR_START + SPEC_I2C_SIZE) - 1)
static inline u8 spec_fmc_slot_nr(struct spec_dev *spec)
{
return (ioread32be(spec->remap[0] + 0x0) & 0x1);
}
#define SPEC_FMC_PRESENCE (SPEC_CORE_FPGA + 0x64)
static inline u8 spec_fmc_presence(struct spec_dev *spec)
{
return (ioread32(spec->remap[0] + 0x0) & 0x1);
return (ioread32(spec->fpga + SPEC_FMC_PRESENCE) & 0x1);
}
static int spec_fmc_is_present(struct fmc_carrier *carrier,
......@@ -32,7 +24,7 @@ static int spec_fmc_is_present(struct fmc_carrier *carrier,
{
struct spec_dev *spec = carrier->priv;
return (spec_fmc_presence(spec) & BIT(slot->ga));
return spec_fmc_presence(spec);
}
static const struct fmc_carrier_operations spec_fmc_ops = {
......@@ -40,52 +32,6 @@ static const struct fmc_carrier_operations spec_fmc_ops = {
.is_present = spec_fmc_is_present,
};
static const struct ocores_i2c_platform_data pdata = {
.reg_shift = 2, /* 32bit aligned */
.reg_io_width = 4,
.clock_khz = 62500,
.big_endian = 1,
.num_devices = 0,
.devices = NULL,
};
static int id;
/**
* It builds the platform_device_info necessary to register the
* I2C master device.
* @spec the SPEC instance
*
* Return: an array of I2C master devices
*/
static int spec_i2c_add(struct spec_dev *spec)
{
struct resource res = {
.name = "i2c-ocores-mem",
.flags = IORESOURCE_MEM,
.start = pci_resource_start(to_pci_dev(spec->dev.parent), 0) + SPEC_I2C_ADDR_START,
.end = pci_resource_start(to_pci_dev(spec->dev.parent), 0) + SPEC_I2C_ADDR_END,
};
/* FIXME find better ID */
spec->i2c_pdev = platform_device_register_resndata(spec->dev.parent,
"i2c-ohwr", id++,
&res, 1,
&pdata,
sizeof(pdata));
if (!spec->i2c_pdev)
return -ENODEV;
return 0;
}
static void spec_i2c_del(struct spec_dev *spec)
{
if (spec->i2c_pdev)
platform_device_unregister(spec->i2c_pdev);
}
static int spec_i2c_find_adapter(struct device *dev, void *data)
{
struct spec_dev *spec = data;
......@@ -126,27 +72,14 @@ int spec_fmc_init(struct spec_dev *spec)
{
int err;
pr_info("%s:%d\n", __func__, __LINE__);
if (spec_fmc_slot_nr(spec) != SPEC_FMC_SLOTS) {
dev_err(spec->dev.parent,
"Invalid SPEC FPGA (slot count: %d)\n",
spec_fmc_slot_nr(spec));
return -EINVAL;
}
pr_info("%s:%d\n", __func__, __LINE__);
err = spec_i2c_add(spec);
if (err)
goto err_i2c;
pr_info("%s:%d\n", __func__, __LINE__);
spec->slot_info.i2c_bus_nr = spec_i2c_get_bus(spec);
if (spec->slot_info.i2c_bus_nr <= 0)
goto err_i2c_bus;
return -ENODEV;
spec->slot_info.ga = 0;
spec->slot_info.lun = 1;
pr_info("%s:%d\n", __func__, __LINE__);
err = fmc_carrier_register(&spec->dev, &spec_fmc_ops,
spec_fmc_slot_nr(spec), &spec->slot_info,
SPEC_FMC_SLOTS, &spec->slot_info,
spec);
if (err) {
dev_err(spec->dev.parent,
......@@ -158,20 +91,10 @@ int spec_fmc_init(struct spec_dev *spec)
return 0;
err_fmc:
err_i2c_bus:
spec_i2c_del(spec);
err_i2c:
return -1;
return err;
}
int spec_fmc_exit(struct spec_dev *spec)
{
int err;
err = fmc_carrier_unregister(&spec->dev);
if (err)
dev_err(spec->dev.parent,
"Failed to unregister from FMC\n");
spec_i2c_del(spec);
return err;
return fmc_carrier_unregister(&spec->dev);
}
......@@ -86,14 +86,14 @@ int spec_gpio_init(struct spec_dev *spec)
goto err_lookup;
spec->gpiod[GN4124_GPIO_BOOTSEL0] = gpiod_get_index(&spec->dev,
"bootsel", 0,
GPIOD_OUT_HIGH);
"bootsel", 0,
GPIOD_OUT_HIGH);
if (IS_ERR(spec->gpiod[GN4124_GPIO_BOOTSEL0]))
goto err_sel0;
spec->gpiod[GN4124_GPIO_BOOTSEL1] = gpiod_get_index(&spec->dev,
"bootsel", 1,
GPIOD_OUT_HIGH);
"bootsel", 1,
GPIOD_OUT_HIGH);
if (IS_ERR(spec->gpiod[GN4124_GPIO_BOOTSEL1]))
goto err_sel1;
......@@ -107,15 +107,15 @@ int spec_gpio_init(struct spec_dev *spec)
spec->gpiod[GN4124_GPIO_IRQ0] = gpiod_get_index(&spec->dev,
"irq", 0,
GPIOD_IN);
"irq", 0,
GPIOD_IN);
if (IS_ERR(spec->gpiod[GN4124_GPIO_IRQ0])) {
err = PTR_ERR(spec->gpiod[GN4124_GPIO_IRQ0]);
goto err_irq0;
}
spec->gpiod[GN4124_GPIO_IRQ1] = gpiod_get_index(&spec->dev,
"irq", 1,
GPIOD_IN);
"irq", 1,
GPIOD_IN);
if (IS_ERR(spec->gpiod[GN4124_GPIO_IRQ1])) {
err = PTR_ERR(spec->gpiod[GN4124_GPIO_IRQ1]);
goto err_irq1;
......@@ -128,8 +128,6 @@ int spec_gpio_init(struct spec_dev *spec)
if (err)
goto err_in1;
gn412x_int_gpio_enable(&spec->gn412x, 0);
return 0;
err_in1:
......@@ -156,13 +154,10 @@ err_dup:
void spec_gpio_exit(struct spec_dev *spec)
{
gn412x_int_gpio_disable(&spec->gn412x);
gpiod_put(spec->gpiod[GN4124_GPIO_IRQ0]);
gpiod_put(spec->gpiod[GN4124_GPIO_IRQ1]);
gpiod_put(spec->gpiod[GN4124_GPIO_BOOTSEL0]);
gpiod_put(spec->gpiod[GN4124_GPIO_IRQ0]);
gpiod_put(spec->gpiod[GN4124_GPIO_BOOTSEL1]);
gpiod_put(spec->gpiod[GN4124_GPIO_BOOTSEL0]);
gpiod_remove_lookup_table(spec->gpiod_table);
kfree(spec->gpiod_table->dev_id);
}
......@@ -34,7 +34,7 @@
#define SPEC_MINOR_MAX (64)
#define SPEC_FLAG_BITS (8)
#define SPEC_FLAG_UNLOCK BIT(0)
#define SPEC_FLAG_THERM_BIT 0
#define GN4124_GPIO_MAX 16
#define GN4124_GPIO_BOOTSEL0 15
......@@ -118,12 +118,51 @@ enum {
PCI_SYS_CFG_SYSTEM = 0x800
};
enum {
/* Metadata */
SPEC_CORE_FPGA = 0x0,
SPEC_META_BASE = SPEC_CORE_FPGA + 0x00,
SPEC_META_VENDOR = SPEC_META_BASE + 0x00,
SPEC_META_DEVICE = SPEC_META_BASE + 0x04,
SPEC_META_VERSION = SPEC_META_BASE + 0x08,
SPEC_META_BOM = SPEC_META_BASE + 0x0C,
SPEC_META_SRC = SPEC_META_BASE + 0x10,
SPEC_META_CAP = SPEC_META_BASE + 0x20,
SPEC_META_UUID = SPEC_META_BASE + 0x30,
};
#define SPEC_META_VENDOR_ID PCI_VENDOR_ID_CERN
#define SPEC_META_DEVICE_ID 0x53504543
#define SPEC_META_BOM_LE 0xFFFE0000
#define SPEC_META_BOM_END_MASK 0xFFFF0000
#define SPEC_META_BOM_VER_MASK 0x0000FFFF
#define SPEC_META_VERSION_1_4 0x01040000
#define SPEC_META_CAP_VIC BIT(0)
#define SPEC_META_CAP_THERM BIT(0)
#define SPEC_META_CAP_SPI BIT(0)
#define SPEC_META_CAP_DMA BIT(0)
#define SPEC_META_CAP_WR BIT(0)
/**
* struct spec_meta_id Metadata
*/
struct spec_meta_id {
uint32_t vendor;
uint32_t device;
uint32_t version;
uint32_t bom;
uint32_t src[4];
uint32_t cap;
uint32_t uuid[4];
};
#define GNINT_STAT_GPIO BIT(15)
#define GNINT_STAT_SW0 BIT(2)
#define GNINT_STAT_SW1 BIT(3)
#define GNINT_STAT_SW_ALL (GNINT_STAT_SW0 | GNINT_STAT_SW1)
/**
* struct gn412x_dev GN412X device descriptor
* @compl: for IRQ testing
......@@ -159,9 +198,13 @@ struct spec_dev {
DECLARE_BITMAP(flags, SPEC_FLAG_BITS);
void __iomem *remap[3]; /* ioremap of bar 0, 2, 4 */
void __iomem *fpga;
struct spec_meta_id __iomem *meta;
struct platform_device *i2c_pdev;
struct i2c_adapter *i2c_adapter;
struct platform_device *vic_pdev;
struct platform_device *app_pdev;
struct fmc_slot_info slot_info;
struct dentry *dbg_dir;
......@@ -169,6 +212,8 @@ struct spec_dev {
struct dentry *dbg_info;
#define SPEC_DBG_FW_NAME "fpga_firmware"
struct dentry *dbg_fw;
#define SPEC_DBG_META_NAME "fpga_device_metadata"
struct dentry *dbg_meta;
struct gn412x_dev gn412x;
......@@ -245,4 +290,7 @@ extern void spec_gpio_fpga_select(struct spec_dev *spec,
extern int spec_gpio_init(struct spec_dev *spec);
extern void spec_gpio_exit(struct spec_dev *spec);
extern int spec_core_fpga_init(struct spec_dev *spec);
extern void spec_core_fpga_exit(struct spec_dev *spec);
#endif /* __SPEC_H__ */
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