Commit 90ac8d89 authored by Tristan Gingold's avatar Tristan Gingold

Add driver for fd-x2

parent 8ab4d249
......@@ -14,7 +14,9 @@ ccflags-y += -Wall -Werror
obj-m := wrtd-ref-spec150t-adc.o
obj-m += wrtd-ref-svec-tdc-fd.o
obj-m += wrtd-ref-svec-tdc-x2.o
obj-m += wrtd-ref-svec-fd-x2.o
wrtd-ref-spec150t-adc-objs := wrtd-ref-spec150t-adc-core.o
wrtd-ref-svec-tdc-fd-objs := wrtd-ref-svec-tdc-fd-core.o
wrtd-ref-svec-tdc-x2-objs := wrtd-ref-svec-tdc-x2-core.o
wrtd-ref-svec-fd-x2-objs := wrtd-ref-svec-fd-x2-core.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/module.h>
#include<linux/moduleparam.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include <linux/mod_devicetable.h>
static char *drivers = "";
module_param(drivers, charp, 0444);
MODULE_PARM_DESC(drivers,
"Extra drivers to load: fd (fmc-fine-delay)\n");
enum wrtd_fdx2_dev_offsets {
WRTD_FDX2_FD0_MEM_START = 0x0000C000,
WRTD_FDX2_FD0_MEM_END = 0x0000C1FF,
WRTD_FDX2_FD1_MEM_START = 0x00014000,
WRTD_FDX2_FD1_MEM_END = 0x000141FF,
WRTD_FDX2_TRTL_MEM_START = 0x0001C000,
WRTD_FDX2_TRTL_MEM_END = 0x0003C000,
};
/* MFD devices */
static struct resource wrtd_fdx2_fd0_res[] = {
{
.name = "fmc-fdelay0-mem",
.flags = IORESOURCE_MEM,
.start = WRTD_FDX2_FD0_MEM_START,
.end = WRTD_FDX2_FD0_MEM_END,
}, {
.name = "fmc-fdelay0-irq",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 0,
.end = 0,
},
};
static struct resource wrtd_fdx2_fd1_res[] = {
{
.name = "fmc-fdelay1-mem",
.flags = IORESOURCE_MEM,
.start = WRTD_FDX2_FD1_MEM_START,
.end = WRTD_FDX2_FD1_MEM_END,
}, {
.name = "fmc-fdelay1-irq",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 1,
.end = 1,
},
};
static struct resource wrtd_fdx2_trtl_res[] = {
{
.name = "mock-turtle-mem",
.flags = IORESOURCE_MEM,
.start = WRTD_FDX2_TRTL_MEM_START,
.end = WRTD_FDX2_TRTL_MEM_END,
}, {
.name = "mock-turtle-irq_in",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 2,
}, {
.name = "mock-turtle-irq_out",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 3,
}, {
.name = "mock-turtle-irq_con",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 4,
}, {
.name = "mock-turtle-irq_not",
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
.start = 5,
},
};
#define MFD_CELL_TRTL { \
.name = "mock-turtle", \
.platform_data = NULL, \
.pdata_size = 0, \
.num_resources = ARRAY_SIZE(wrtd_fdx2_trtl_res), \
.resources = wrtd_fdx2_trtl_res, \
}
#define MFD_CELL_FD0 { \
.name = "fmc-fdelay0", \
.platform_data = NULL, \
.pdata_size = 0, \
.num_resources = ARRAY_SIZE(wrtd_fdx2_fd0_res), \
.resources = wrtd_fdx2_fd0_res, \
}
#define MFD_CELL_FD1 { \
.name = "fmc-fdelay1", \
.platform_data = NULL, \
.pdata_size = 0, \
.num_resources = ARRAY_SIZE(wrtd_fdx2_fd1_res), \
.resources = wrtd_fdx2_fd1_res, \
}
static const struct mfd_cell __wrtd_fdx2_mfd_devs_base[] = {
MFD_CELL_TRTL,
};
static const struct mfd_cell __wrtd_fdx2_mfd_devs_fdt[] = {
MFD_CELL_TRTL,
MFD_CELL_FD0,
MFD_CELL_FD1,
};
static const struct mfd_cell *wrtd_fdx2_mfd_cells(const char *extra)
{
if (strncmp("fd", extra, 2) == 0)
return __wrtd_fdx2_mfd_devs_fdt;
else
return __wrtd_fdx2_mfd_devs_base;
}
static unsigned int wrtd_fdx2_mfd_count(const char *extra)
{
if (strncmp("fd", extra, 2) == 0)
return 3;
else
return 1;
}
static int wrtd_fdx2_probe(struct platform_device *pdev)
{
struct resource *rmem;
int irq;
rmem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!rmem) {
dev_err(&pdev->dev, "Missing memory resource\n");
return -EINVAL;
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "Missing IRQ number\n");
return -EINVAL;
}
/*
* We know that this design uses the HTVIC IRQ controller.
* This IRQ controller has a linear mapping, so it is enough
* to give the first one as input
*/
return mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO,
wrtd_fdx2_mfd_cells(drivers),
wrtd_fdx2_mfd_count(drivers),
rmem, irq, NULL);
}
static int wrtd_fdx2_remove(struct platform_device *pdev)
{
mfd_remove_devices(&pdev->dev);
return 0;
}
/**
* List of supported platform
*/
enum wrtd_fdx2_version {
WRTD_FDX2_VER = 0,
};
static const struct platform_device_id wrtd_fdx2_id_table[] = {
{
.name = "wrtd-fdx2",
.driver_data = WRTD_FDX2_VER,
}, {
.name = "id:000010DC57544E04",
.driver_data = WRTD_FDX2_VER,
}, {
.name = "id:000010dc57544e04",
.driver_data = WRTD_FDX2_VER,
},
{},
};
static struct platform_driver wrtd_fdx2_driver = {
.driver = {
.name = "wrtd-fdx2",
.owner = THIS_MODULE,
},
.id_table = wrtd_fdx2_id_table,
.probe = wrtd_fdx2_probe,
.remove = wrtd_fdx2_remove,
};
module_platform_driver(wrtd_fdx2_driver);
MODULE_AUTHOR("Federico Vaga <federico.vaga@cern.ch>");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
MODULE_DESCRIPTION("Driver for the WRTD SVEC Fine-Delay x2");
MODULE_DEVICE_TABLE(platform, wrtd_fdx2_id_table);
MODULE_SOFTDEP("pre: svec_fmc_carrier mockturtle");
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