aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/fmc
diff options
context:
space:
mode:
authorAlessandro Rubini <rubini@gnudd.com>2013-06-18 17:47:46 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-06-18 18:41:04 -0400
commit056d83f3c30c398f14eb879f1d1707e3a7808f4a (patch)
tree44c3883a0cd722472b9888b2a50ce2ac761a9373 /drivers/fmc
parent6c62a895e572145f8aa24f2040d1bb8eff473313 (diff)
FMC: add a software mezzanine driver
This simple do-nothing mezzanine driver shows how to write a mezzanine driver, that can also handle interrupts reported by the carrier. Signed-off-by: Alessandro Rubini <rubini@gnudd.com> Acked-by: Juan David Gonzalez Cobas <dcobas@cern.ch> Acked-by: Emilio G. Cota <cota@braap.org> Acked-by: Samuel Iglesias Gonsalvez <siglesias@igalia.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/fmc')
-rw-r--r--drivers/fmc/Kconfig7
-rw-r--r--drivers/fmc/Makefile1
-rw-r--r--drivers/fmc/fmc-trivial.c107
3 files changed, 115 insertions, 0 deletions
diff --git a/drivers/fmc/Kconfig b/drivers/fmc/Kconfig
index 505e96b02a93..7eacef990be8 100644
--- a/drivers/fmc/Kconfig
+++ b/drivers/fmc/Kconfig
@@ -25,4 +25,11 @@ config FMC_FAKEDEV
25 that can be rewritten at run time and usef for matching 25 that can be rewritten at run time and usef for matching
26 mezzanines. 26 mezzanines.
27 27
28config FMC_TRIVIAL
29 tristate "FMC trivial mezzanine driver (software testing)"
30 help
31 This is a fake mezzanine driver, to show how FMC works and test it.
32 The driver also handles interrupts (we used it with a real carrier
33 before the mezzanines were produced)
34
28endif # FMC 35endif # FMC
diff --git a/drivers/fmc/Makefile b/drivers/fmc/Makefile
index 9832b79976b1..52624e6c0b1f 100644
--- a/drivers/fmc/Makefile
+++ b/drivers/fmc/Makefile
@@ -8,3 +8,4 @@ fmc-y += fru-parse.o
8fmc-y += fmc-dump.o 8fmc-y += fmc-dump.o
9 9
10obj-$(CONFIG_FMC_FAKEDEV) += fmc-fakedev.o 10obj-$(CONFIG_FMC_FAKEDEV) += fmc-fakedev.o
11obj-$(CONFIG_FMC_TRIVIAL) += fmc-trivial.o
diff --git a/drivers/fmc/fmc-trivial.c b/drivers/fmc/fmc-trivial.c
new file mode 100644
index 000000000000..6c590f54c79d
--- /dev/null
+++ b/drivers/fmc/fmc-trivial.c
@@ -0,0 +1,107 @@
1/*
2 * Copyright (C) 2012 CERN (www.cern.ch)
3 * Author: Alessandro Rubini <rubini@gnudd.com>
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * The software is provided "as is"; the copyright holders disclaim
10 * all warranties and liabilities, to the extent permitted by
11 * applicable law.
12 */
13
14/* A trivial fmc driver that can load a gateware file and reports interrupts */
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/interrupt.h>
18#include <linux/gpio.h>
19#include <linux/fmc.h>
20
21static struct fmc_driver t_drv; /* initialized later */
22
23static irqreturn_t t_handler(int irq, void *dev_id)
24{
25 struct fmc_device *fmc = dev_id;
26
27 fmc->op->irq_ack(fmc);
28 dev_info(&fmc->dev, "received irq %i\n", irq);
29 return IRQ_HANDLED;
30}
31
32static struct fmc_gpio t_gpio[] = {
33 {
34 .gpio = FMC_GPIO_IRQ(0),
35 .mode = GPIOF_DIR_IN,
36 .irqmode = IRQF_TRIGGER_RISING,
37 }, {
38 .gpio = FMC_GPIO_IRQ(1),
39 .mode = GPIOF_DIR_IN,
40 .irqmode = IRQF_TRIGGER_RISING,
41 }
42};
43
44static int t_probe(struct fmc_device *fmc)
45{
46 int ret;
47 int index = 0;
48
49 if (fmc->op->validate)
50 index = fmc->op->validate(fmc, &t_drv);
51 if (index < 0)
52 return -EINVAL; /* not our device: invalid */
53
54 ret = fmc->op->irq_request(fmc, t_handler, "fmc-trivial", IRQF_SHARED);
55 if (ret < 0)
56 return ret;
57 /* ignore error code of call below, we really don't care */
58 fmc->op->gpio_config(fmc, t_gpio, ARRAY_SIZE(t_gpio));
59
60 /* Reprogram, if asked to. ESRCH == no filename specified */
61 ret = -ESRCH;
62 if (fmc->op->reprogram)
63 ret = fmc->op->reprogram(fmc, &t_drv, "");
64 if (ret == -ESRCH)
65 ret = 0;
66 if (ret < 0)
67 fmc->op->irq_free(fmc);
68
69 /* FIXME: reprogram LM32 too */
70 return ret;
71}
72
73static int t_remove(struct fmc_device *fmc)
74{
75 fmc->op->irq_free(fmc);
76 return 0;
77}
78
79static struct fmc_driver t_drv = {
80 .version = FMC_VERSION,
81 .driver.name = KBUILD_MODNAME,
82 .probe = t_probe,
83 .remove = t_remove,
84 /* no table, as the current match just matches everything */
85};
86
87 /* We accept the generic parameters */
88FMC_PARAM_BUSID(t_drv);
89FMC_PARAM_GATEWARE(t_drv);
90
91static int t_init(void)
92{
93 int ret;
94
95 ret = fmc_driver_register(&t_drv);
96 return ret;
97}
98
99static void t_exit(void)
100{
101 fmc_driver_unregister(&t_drv);
102}
103
104module_init(t_init);
105module_exit(t_exit);
106
107MODULE_LICENSE("Dual BSD/GPL");