Commit 0b27a3f7 authored by Federico Vaga's avatar Federico Vaga

import htvic 1.3.0

Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent 62f22c5f
......@@ -7,6 +7,7 @@ REPO_PARENT ?= $(shell /bin/pwd)/..
DIRS := i2c-ocores
DIRS += spi-ocores
DIRS += htvic
.PHONY: all clean modules install modules_install $(DIRS)
......
# SPDX-License-Identifier: CC0-1.0
#
# SPDX-FileCopyrightText: 2019 CERN
all: modules
install: modules_install
clean modules modules_install:
@$(MAKE) -C drivers/ $@
gtags:
git ls-tree -r --name-only HEAD | grep -E '.*\.(c|h)$$' | gtags -f -
.PHONY: modules modules_install clean all gtags
HT Vector Interrupt Controller
==============================
This is the driver for the Vector Interrupt Controller HDL component
developed in BE-CO-HT (CERN).
::
CARRIER
.------------------------------.
| FPGA |
| .----------------------. |
| | .--------. | |
| | .------| core-1 | | |
| | v '--------' | |
.-------------. | | .-----. .--------. | |
| motherboard |<-------------------------| vic |<--| core-2 | | |
'-------------' | | '-----' '--------' | |
| | ^ .--------. | |
| | '------| core-N | | |
| | '--------' | |
| '----------------------' |
'------------------------------'
Driver
------
The driver is a platform driver that registers an irq chip for the
correspondent IP core present on the FPGA (the vic). The driver for
the IRQ chip will be connected in cascade to the IRQ controller
assigned to the FPGA carrier by the operating system.
From the electrical point of view, when one of the cores rise an
interrupt line the VIC will keep track of it; the VIC rises
the carrier interrupt line that will, finally, arrive to the
motherboard. This will trigger the operating system, which will
try to handle the interrupt by calling the IRQ handler associated
to the carrier interrupt line. The carrier interrupt line has been
connected directly to the VIC, so the control passes to the VIC
driver which will call the IRQ handler associated to the risen
interrupt line.
The purpose of the VIC driver (IRQ controller) is to configure the VIC
IP core and, dispatch the control to IRQ handlers that belong to it and
to acknowledge the IRQ lines when the interrupt has been handled.
The driver uses the standard Linux interface, this means that any driver
can map an IRQ handler using ``request_irq``. In principle all the Linux IRQ
API should work.
The HTVIC uses the IRQ domain concept, so each HTVIC instance has its own
IRQ domain. Any driver who wants to retrieve the Linux IRQ number
associated to an HTVIC can use the IRQ domain.
::
irqdomain = irq_find_host((struct device_node *)irqdomain_name);
linux_irq_number = irq_find_mapping(irqdomain, HW_IRQ_NUMBER);
request_irq(linux_irq_number, ...);
A non trivial problem can be the detection of the correct domain name.
The source of this information can only be the FPGA carrier, or an user
space process but there is not an unique solution neither a standard one.
All the IRQs handled by the VIC IRQ controller will be visible as any
other IRQ from the operating system. By doing ``cat /proc/interrupts``,
among the other IRQ handlers, you will get the ones belonging to the VIC
IRQ controller. You can identify them because of the prefix "HT-VIC"
::
CPU0 CPU1
[...]
281: 0 0 HT-VIC fmc-tdc-svec.0
282: 0 0 HT-VIC fdelay-tdc-svec.0
283: 2 0 HT-VIC mock-turtle-svec.57005
284: 4 0 HT-VIC mock-turtle-svec.57005
313: 0 0 HT-VIC fmc-tdc-svec.1
314: 0 0 HT-VIC fdelay-tdc-svec.1
315: 2 0 HT-VIC mock-turtle-svec.48879
316: 4 0 HT-VIC mock-turtle-svec.48879
345: 5 0 HT-VIC adc-100m-svec.0
346: 0 0 HT-VIC adc-100m-svec.1
[...]
Debug
-----
This driver has a *debugfs* interface. This means that you need the debug
file-system mounted first::
mount -t debugfs none /sys/kernel/debug
The driver exports two read-only files:
info
It contains a YAML file with general information about the device instance
reg
It shows the VIC memory dump
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Copyright (C) 2019 CERN
ifdef CONFIG_SUPER_REPO
ifdef CONFIG_SUPER_REPO_VERSION
SUBMODULE_VERSIONS-y += MODULE_INFO(version_$(CONFIG_SUPER_REPO),\"$(CONFIG_SUPER_REPO_VERSION)\");
endif
endif
ccflags-y += -DADDITIONAL_VERSIONS="$(SUBMODULE_VERSIONS-y)"
ccflags-y += -Werror
obj-m := htvic.o
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Copyright (C) 2019 CERN
-include Makefile.specific
REPO_PARENT ?= $(shell /bin/pwd)/../..
-include $(REPO_PARENT)/parent_common.mk
LINUX ?= /lib/modules/$(shell uname -r)/build
all: modules
clean modules help modules_install:
$(MAKE) -C $(LINUX) M=$(shell /bin/pwd) $@
.PHONY: all modules clean help install modules_install
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (c) 2016 CERN
* Author: Federico Vaga <federico.vaga@cern.ch>
*/
#ifndef __HTVIC_H__
#define __HTVIC_H__
#include <linux/debugfs.h>
#include "htvic_regs.h"
#define VIC_MAX_VECTORS 32
#define VIC_SDB_VENDOR 0xce42
#define VIC_SDB_DEVICE 0x0013
#define VIC_IRQ_BASE_NUMBER 0
enum htvic_versions {
HTVIC_VER_SPEC = 0,
HTVIC_VER_SVEC,
HTVIC_VER_WRSWI,
};
enum htvic_mem_resources {
HTVIC_MEM_BASE = 0,
};
struct htvic_data {
uint32_t is_edge; /* 1 edge, 0 level */
uint32_t is_raising; /* 1 raising, 0 falling */
uint32_t pulse_len;
};
struct memory_ops {
u32 (*read)(void *addr);
void (*write)(u32 value, void *addr);
};
struct htvic_device {
struct platform_device *pdev;
struct irq_domain *domain;
unsigned int hwid[VIC_MAX_VECTORS]; /**> original ID from FPGA */
struct htvic_data *data;
void __iomem *kernel_va;
struct memory_ops memop;
int irq;
irq_flow_handler_t platform_handle_irq;
void *platform_handler_data;
struct dentry *dbg_dir;
#define HTVIC_DBG_INFO_NAME "info"
struct dentry *dbg_info;
#define HTVIC_DBG_REG_NAME "reg"
struct dentry *dbg_reg;
#define HTVIC_DBG_SWIRQ_NAME "swirq"
struct dentry *dbg_swirq;
};
static inline u32 htvic_ioread(struct htvic_device *htvic, void __iomem *addr)
{
return htvic->memop.read(addr);
}
static inline void htvic_iowrite(struct htvic_device *htvic,
u32 value, void __iomem *addr)
{
return htvic->memop.write(value, addr);
}
static inline u32 __htvic_ioread32(void *addr)
{
return ioread32(addr);
}
static inline u32 __htvic_ioread32be(void *addr)
{
return ioread32be(addr);
}
static inline void __htvic_iowrite32(u32 value,void __iomem *addr)
{
iowrite32(value, addr);
}
static inline void __htvic_iowrite32be(u32 value, void __iomem *addr)
{
iowrite32be(value, addr);
}
#endif
/*
Register definitions for slave core: Vectored Interrupt Controller (VIC)
* File : here.h
* Author : auto-generated by wbgen2 from wb_slave_vic.wb
* Created : Thu Jul 14 15:43:13 2016
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE wb_slave_vic.wb
DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
*/
#ifndef __WBGEN2_REGDEFS_WB_SLAVE_VIC_WB
#define __WBGEN2_REGDEFS_WB_SLAVE_VIC_WB
#ifdef __KERNEL__
#include <linux/types.h>
#else
#include <inttypes.h>
#endif
#if defined( __GNUC__)
#define PACKED __attribute__ ((packed))
#else
#error "Unsupported compiler?"
#endif
#ifndef __WBGEN2_MACROS_DEFINED__
#define __WBGEN2_MACROS_DEFINED__
#define WBGEN2_GEN_MASK(offset, size) (((1<<(size))-1) << (offset))
#define WBGEN2_GEN_WRITE(value, offset, size) (((value) & ((1<<(size))-1)) << (offset))
#define WBGEN2_GEN_READ(reg, offset, size) (((reg) >> (offset)) & ((1<<(size))-1))
#define WBGEN2_SIGN_EXTEND(value, bits) (((value) & (1<<bits) ? ~((1<<(bits))-1): 0 ) | (value))
#endif
/* definitions for register: VIC Control Register */
/* definitions for field: VIC Enable in reg: VIC Control Register */
#define VIC_CTL_ENABLE WBGEN2_GEN_MASK(0, 1)
/* definitions for field: VIC output polarity in reg: VIC Control Register */
#define VIC_CTL_POL WBGEN2_GEN_MASK(1, 1)
/* definitions for field: Emulate Edge sensitive output in reg: VIC Control Register */
#define VIC_CTL_EMU_EDGE WBGEN2_GEN_MASK(2, 1)
/* definitions for field: Emulated Edge pulse timer in reg: VIC Control Register */
#define VIC_CTL_EMU_LEN_MASK WBGEN2_GEN_MASK(3, 16)
#define VIC_CTL_EMU_LEN_SHIFT 3
#define VIC_CTL_EMU_LEN_W(value) WBGEN2_GEN_WRITE(value, 3, 16)
#define VIC_CTL_EMU_LEN_R(reg) WBGEN2_GEN_READ(reg, 3, 16)
/* definitions for register: Raw Interrupt Status Register */
/* definitions for register: Interrupt Enable Register */
/* definitions for register: Interrupt Disable Register */
/* definitions for register: Interrupt Mask Register */
/* definitions for register: Vector Address Register */
/* definitions for register: Software Interrupt Register */
/* definitions for register: End Of Interrupt Acknowledge Register */
/* definitions for RAM: Interrupt Vector Table */
#define VIC_IVT_RAM_BASE 0x00000080 /* base address */
#define VIC_IVT_RAM_BYTES 0x00000080 /* size in bytes */
#define VIC_IVT_RAM_WORDS 0x00000020 /* size in 32-bit words, 32-bit aligned */
/* [0x0]: REG VIC Control Register */
#define VIC_REG_CTL 0x00000000
/* [0x4]: REG Raw Interrupt Status Register */
#define VIC_REG_RISR 0x00000004
/* [0x8]: REG Interrupt Enable Register */
#define VIC_REG_IER 0x00000008
/* [0xc]: REG Interrupt Disable Register */
#define VIC_REG_IDR 0x0000000c
/* [0x10]: REG Interrupt Mask Register */
#define VIC_REG_IMR 0x00000010
/* [0x14]: REG Vector Address Register */
#define VIC_REG_VAR 0x00000014
/* [0x18]: REG Software Interrupt Register */
#define VIC_REG_SWIR 0x00000018
/* [0x1c]: REG End Of Interrupt Acknowledge Register */
#define VIC_REG_EOIR 0x0000001c
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment