fmc-dio.h 4.95 KB
Newer Older
1
/*
2
 * Copyright (C) 2019 CERN (www.cern.ch)
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 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
 * Author: Miguel Jimenez Lopez <miguel.jimenez@sevensols.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.
 */

#ifdef __KERNEL__
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <linux/irqreturn.h>
#include <linux/fmc.h>
//FIXME: Back hack to maintain the IOCTL command numbers
#include <linux/sockios.h>

#include "hw/wr-dio-regs.h"
#include "hw/ppsg-regs.h"

/* Forward declaration */
struct fmc_dio;

/* This is somehow generic, but I find no better place at this time */
#ifndef SET_HI32
#  if BITS_PER_LONG > 32
#    define SET_HI32(var, value)	((var) |= (long)(value) << 32)
#    define GET_HI32(var)		((var) >> 32)
#  else
#    define SET_HI32(var, value)	((var) |= 0)
#    define GET_HI32(var)		0
#  endif
#endif

/* For GPIO we have no wb-gen header */
struct fmc_dio_gpio_block {
	uint32_t	clear;
	uint32_t	set;
	uint32_t	dir;
	uint32_t	status;
};

/* And this is our bit mapping */
#define FMC_DIO_GPIO_VALUE(bit)	(1 << ((4 * (bit)) + 0))

/* FMC DIO name string pattern */
#define FMC_DIO_NAME_PATTERN "fmc-dio-%d:%d"
/* Size of the name field of the fmc_dio structure */
#define FMC_DIO_NAME_MAX 20

/* Board constants */
#define FMC_DIO_BOARD_SPEC 0
55
#define FMC_DIOv2_BOARD_SPEC 1
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77

/**
 * @brief FMC DIO structure
 *
 * This contains information regarding FMC DIO.
 */
struct fmc_dio {
	char name[FMC_DIO_NAME_MAX]; /**< Name of the FMC DIO */
	struct miscdevice mdev; /**< Linux Miscdevice for the FMC DIO */
	struct platform_device *pdev; /**< Linux platform_device for the FMC DIO */
	struct fmc_device *fmc; /** FMC device for the FMC DIO */
	struct gpio_chip *gc; /**< Linux GPIO chip */

	void __iomem *dio; /**< DIO IP block pointer */
	void __iomem *gpio; /**< GPIO IP block pointer */
	void __iomem *ppsg; /**< PPSG IP block pointer */

	const char *irqdomain_name; /**< IRQ domain name */
	int irq; /**< IRQ number for DIO FMC */

	int board; /**< Board info */

78 79
	int version; //*< HDL version */

80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
	void *priv; /**< Private data for FMC DIO */
};

// From fmc-dio-internal.c
extern irqreturn_t fmc_dio_int_interrupt(struct fmc_dio *dev);
extern int fmc_dio_int_ioctl(struct fmc_dio *dev, unsigned int ioctlcmd,
		unsigned long arg);
extern int fmc_dio_internal_create(struct fmc_dio *dev);
extern void fmc_dio_internal_destroy(struct fmc_dio *dev);

// From fmc-dio-mdev.c
extern int fmc_dio_mdev_create(struct fmc_dio *dio);
extern void fmc_dio_mdev_destroy(struct fmc_dio *dio);

// From fmc-dio-gpio.c
extern int fmc_dio_gpio_init(struct fmc_dio *dev);
extern void fmc_dio_gpio_exit(struct fmc_dio *dev);

#endif /* __KERNEL__ */

// FIXME: Move IOCTL command numbers?
#define PRIV_MEZZANINE_ID	(SIOCDEVPRIVATE + 14)
#define PRIV_MEZZANINE_CMD	(SIOCDEVPRIVATE + 15)

// FMC DIO Commands
enum wr_dio_cmd_name {
	WR_DIO_CMD_PULSE,
	WR_DIO_CMD_STAMP,
	WR_DIO_CMD_DAC,
	WR_DIO_CMD_INOUT,
110
	WR_DIO_CMD_IRQ,
111
	WR_DIO_CMD_UPDATE_WIDTH,
Jorge Machado's avatar
Jorge Machado committed
112
	WR_DIO_CMD_MASK_IRQ,
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
};

/*
 * This is how parameters are used (K == reply from kernel):
 *
 *  CMD_PULSE:
 *     cmd->flags: F_NOW, F_REL, F_LOOP
 *     cmd->channel: the channel or the mask
 *     cmd->t[]: either 2 or 3 values (start, duration, loop)
 *     cmd->value: count of loops (0 to turn off)
 *
 *  CMD_STAMP:
 *     cmd->flags: F_MASK, F_WAIT
 *     cmd->channel: the channel or the mask
 *     K: cmd->channel: the channel where we had stamps
 *     K: cmd->nstamp: number of valid stamps
 *     K: cmd->t[]: the stamps
 *
 *  CMD_DAC:
 *     cmd->flags: none
 *     cmd->channel: which one
 *     cmd->value: the value
 *
 *  CMD_INOUT:
 *     cmd->flags: F_MASK
 *     cmd->channel: the channel or the mask
 *     cmd->value: bits 0..4: WR-DIO, 8..12 value, 16..20 OEN, 24..28 term
 *
 */

#define WR_DIO_INOUT_DIO	(1 << 0)
#define WR_DIO_INOUT_VALUE	(1 << 8)
#define WR_DIO_INOUT_OUTPUT	(1 << 16)
#define WR_DIO_INOUT_TERM	(1 << 24)

#define WR_DIO_N_STAMP  16 /* At least 5 * 3 */

150 151 152 153 154 155 156
struct wr_timestamp_info {
   uint16_t leap_second;
   int leap_second_valid;
   int flag59;
   int flag61;
};

157 158 159 160 161 162
struct wr_dio_cmd {
	uint16_t command;	/* from user */
	uint16_t channel;	/* 0..4 or mask from user */
	uint32_t value;		/* for DAC or I/O */
	uint32_t flags;
	uint32_t nstamp;	/* from kernel, if IN_STAMP */
163 164
	struct timespec t[WR_DIO_N_STAMP];
	struct wr_timestamp_info wr_ts_info_buf[WR_DIO_N_STAMP];
165 166
	uint32_t wait_mode_flags;
	struct timespec wait_mode_timeout;
167 168 169 170 171 172 173
};

#define WR_DIO_F_NOW	0x01	/* Output is now, t[0] ignored */
#define WR_DIO_F_REL	0x02	/* t[0].tv_sec is relative */
#define WR_DIO_F_MASK	0x04	/* Channel is 0x00..0x1f */
#define WR_DIO_F_LOOP	0x08	/* Output should loop: t[2] is  looping*/
#define WR_DIO_F_WAIT	0x10	/* Wait for event */
Jorge Machado's avatar
Jorge Machado committed
174 175
#define WR_DIO_F_MASK_READ_IRQ		0x20
#define WR_DIO_F_MASK_ENABLE_IRQ	0x40
176 177 178
#define WR_DIO_F_MASK_DISABLE_IRQ	0x80
#define WR_DIO_F_WAIT_MODE_NORM	0x00
#define WR_DIO_F_WAIT_MODE_TIMEOUT	0x01