forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <[email protected]> Acked-by: Juan David Gonzalez Cobas <[email protected]> Acked-by: Emilio G. Cota <[email protected]> Acked-by: Samuel Iglesias Gonsalvez <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
- Loading branch information
Showing
5 changed files
with
135 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
fmc-trivial | ||
=========== | ||
|
||
The simple module fmc-trivial is just a simple client that registers an | ||
interrupt handler. I used it to verify the basic mechanism of the FMC | ||
bus and how interrupts worked. | ||
|
||
The module implements the generic FMC parameters, so it can program a | ||
different gateware file in each card. The whole list of parameters it | ||
accepts are: | ||
|
||
`busid=' | ||
`gateware=' | ||
Generic parameters. See mezzanine.txt | ||
|
||
|
||
This driver is worth reading, in my opinion. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
/* | ||
* Copyright (C) 2012 CERN (www.cern.ch) | ||
* Author: Alessandro Rubini <[email protected]> | ||
* | ||
* Permission to use, copy, modify, and/or distribute this software for any | ||
* purpose with or without fee is hereby granted, provided that the above | ||
* copyright notice and this permission notice appear in all copies. | ||
* | ||
* The software is provided "as is"; the copyright holders disclaim | ||
* all warranties and liabilities, to the extent permitted by | ||
* applicable law. | ||
*/ | ||
|
||
/* A trivial fmc driver that can load a gateware file and reports interrupts */ | ||
#include <linux/module.h> | ||
#include <linux/init.h> | ||
#include <linux/interrupt.h> | ||
#include <linux/gpio.h> | ||
#include <linux/fmc.h> | ||
|
||
static struct fmc_driver t_drv; /* initialized later */ | ||
|
||
static irqreturn_t t_handler(int irq, void *dev_id) | ||
{ | ||
struct fmc_device *fmc = dev_id; | ||
|
||
fmc->op->irq_ack(fmc); | ||
dev_info(&fmc->dev, "received irq %i\n", irq); | ||
return IRQ_HANDLED; | ||
} | ||
|
||
static struct fmc_gpio t_gpio[] = { | ||
{ | ||
.gpio = FMC_GPIO_IRQ(0), | ||
.mode = GPIOF_DIR_IN, | ||
.irqmode = IRQF_TRIGGER_RISING, | ||
}, { | ||
.gpio = FMC_GPIO_IRQ(1), | ||
.mode = GPIOF_DIR_IN, | ||
.irqmode = IRQF_TRIGGER_RISING, | ||
} | ||
}; | ||
|
||
static int t_probe(struct fmc_device *fmc) | ||
{ | ||
int ret; | ||
int index = 0; | ||
|
||
if (fmc->op->validate) | ||
index = fmc->op->validate(fmc, &t_drv); | ||
if (index < 0) | ||
return -EINVAL; /* not our device: invalid */ | ||
|
||
ret = fmc->op->irq_request(fmc, t_handler, "fmc-trivial", IRQF_SHARED); | ||
if (ret < 0) | ||
return ret; | ||
/* ignore error code of call below, we really don't care */ | ||
fmc->op->gpio_config(fmc, t_gpio, ARRAY_SIZE(t_gpio)); | ||
|
||
/* Reprogram, if asked to. ESRCH == no filename specified */ | ||
ret = -ESRCH; | ||
if (fmc->op->reprogram) | ||
ret = fmc->op->reprogram(fmc, &t_drv, ""); | ||
if (ret == -ESRCH) | ||
ret = 0; | ||
if (ret < 0) | ||
fmc->op->irq_free(fmc); | ||
|
||
/* FIXME: reprogram LM32 too */ | ||
return ret; | ||
} | ||
|
||
static int t_remove(struct fmc_device *fmc) | ||
{ | ||
fmc->op->irq_free(fmc); | ||
return 0; | ||
} | ||
|
||
static struct fmc_driver t_drv = { | ||
.version = FMC_VERSION, | ||
.driver.name = KBUILD_MODNAME, | ||
.probe = t_probe, | ||
.remove = t_remove, | ||
/* no table, as the current match just matches everything */ | ||
}; | ||
|
||
/* We accept the generic parameters */ | ||
FMC_PARAM_BUSID(t_drv); | ||
FMC_PARAM_GATEWARE(t_drv); | ||
|
||
static int t_init(void) | ||
{ | ||
int ret; | ||
|
||
ret = fmc_driver_register(&t_drv); | ||
return ret; | ||
} | ||
|
||
static void t_exit(void) | ||
{ | ||
fmc_driver_unregister(&t_drv); | ||
} | ||
|
||
module_init(t_init); | ||
module_exit(t_exit); | ||
|
||
MODULE_LICENSE("Dual BSD/GPL"); |