Newer
Older
/*
* Copyright (C) 2012 CERN (www.cern.ch)
* Author: Alessandro Rubini <rubini@gnudd.com>
*
* Released according to the GNU GPL, version 2 or any later version.
*
* This work is part of the White Rabbit project, a research effort led
* by CERN, the European Institute for Nuclear Research.
*/
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/fmc.h>
static inline struct fmc_device *gc_to_fmc(struct gpio_chip *gc)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0)
struct device *dev = gc->dev;
#else
struct device *dev = gc->parent;
#endif
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
return container_of(dev, struct fmc_device, dev);
}
static int wrn_gpio_input(struct gpio_chip *chip, unsigned offset)
{
//struct fmc_device *fmc = gc_to_fmc(chip);
//struct wrn_drvdata *dd = fmc_get_drvdata(fmc);
//fmc_writel(fmc, ...); /* FIXME */
return -EAGAIN;
}
static int wrn_gpio_output(struct gpio_chip *chip, unsigned offset, int value)
{
return -EAGAIN;
}
int wrn_gpio_get(struct gpio_chip *chip, unsigned offset)
{
return -EAGAIN;
}
void wrn_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
return;
}
static const char *wrn_gpio_names[] = {
"dire", "fare", "baciare", "lettera", "testamento"
};
static struct gpio_chip wrn_gpio_template = {
.label = "wr-nic",
.owner = THIS_MODULE,
/* FIXME: request, free, for multi-function operation */
.direction_input = wrn_gpio_input,
.direction_output = wrn_gpio_output,
.get = wrn_gpio_get,
.set = wrn_gpio_set,
.base = -1, /* request dynamic */
.ngpio = 5,
.names = wrn_gpio_names,
};
int wrn_gpio_init(struct fmc_device *fmc)
{
struct wrn_drvdata *dd = fmc_get_drvdata(fmc);
struct gpio_chip *gc;
int ret;
gc = devm_kzalloc(&fmc->dev, sizeof(*gc), GFP_KERNEL);
if (!gc)
return -ENOMEM;
*gc = wrn_gpio_template;
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0)
#else
gc->parent = &fmc->dev;
#endif
ret = gpiochip_add(gc);
if (ret < 0)
goto out_free;
dd->gc = gc;
/* FIXME: program the DAC for each port (sysfs attributes?) */
out_free:
kfree(gc);
return ret;
}
void wrn_gpio_exit(struct fmc_device *fmc)
{
struct wrn_drvdata *dd = fmc_get_drvdata(fmc);
struct gpio_chip *gc = dd->gc;
#if LINUX_VERSION_CODE > KERNEL_VERSION(3,17,0)
gpiochip_remove(gc);
#else
int ret;
ret = gpiochip_remove(gc);
if (ret)
dev_err(fmc->hwdev, "DANGER %i! gpio chip can't be removed\n",
ret);