Skip to content
Snippets Groups Projects
wr-nic-gpio.c 2.49 KiB
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/version.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/fmc.h>
#include "spec-nic.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
	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)
	gc->dev = &fmc->dev;
#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?) */
	return 0;

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);