Linux Audio

Check our new training course

Loading...
v4.17
  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_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	index = fmc_validate(fmc, &t_drv);
 
 50	if (index < 0)
 51		return -EINVAL; /* not our device: invalid */
 52
 53	ret = fmc_irq_request(fmc, t_handler, "fmc-trivial", IRQF_SHARED);
 54	if (ret < 0)
 55		return ret;
 56	/* ignore error code of call below, we really don't care */
 57	fmc_gpio_config(fmc, t_gpio, ARRAY_SIZE(t_gpio));
 58
 59	ret = fmc_reprogram(fmc, &t_drv, "", 0);
 60	if (ret == -EPERM) /* programming not supported */
 
 
 
 61		ret = 0;
 62	if (ret < 0)
 63		fmc_irq_free(fmc);
 64
 65	/* FIXME: reprogram LM32 too */
 66	return ret;
 67}
 68
 69static int t_remove(struct fmc_device *fmc)
 70{
 71	fmc_irq_free(fmc);
 72	return 0;
 73}
 74
 75static struct fmc_driver t_drv = {
 76	.version = FMC_VERSION,
 77	.driver.name = KBUILD_MODNAME,
 78	.probe = t_probe,
 79	.remove = t_remove,
 80	/* no table, as the current match just matches everything */
 81};
 82
 83 /* We accept the generic parameters */
 84FMC_PARAM_BUSID(t_drv);
 85FMC_PARAM_GATEWARE(t_drv);
 86
 87static int t_init(void)
 88{
 89	int ret;
 90
 91	ret = fmc_driver_register(&t_drv);
 92	return ret;
 93}
 94
 95static void t_exit(void)
 96{
 97	fmc_driver_unregister(&t_drv);
 98}
 99
100module_init(t_init);
101module_exit(t_exit);
102
103MODULE_LICENSE("Dual BSD/GPL");
v4.10.11
  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");