Commit 51bcb55c authored by ghaddab's avatar ghaddab

new driver for exmimo3

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@5596 818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent 03f1e6fd
CCC = gcc
KERNEL_MAIN_TYPE=$(shell echo `uname -r | cut -d. -f-2 | tr "." "_"`)
export KERNEL_MAIN_TYPE
SUBVERSION=$(shell echo `grep '^SUBLEVEL =' /usr/src/linux/Makefile | sed -e 's, ,,g' | sed -e 's/SUBLEVEL=//'`)
IS_KERNEL_SUBVERSION_GREATER_THAN_20=$(shell if [ $(SUBVERSION) -ge 20 ] ; then echo true ; fi)
EXTRA_CFLAGS = -ggdb -D__KERNEL__ -DMODULE -D_LOOSE_KERNEL_NAMES -I/lib/modules/$(shell uname -r)/build/include -I/lib/modules/$(shell uname -r)/build/include/asm/mach-default -include /lib/modules/$(shell uname -r)/build/include/linux/autoconf.h
EXTRA_CFLAGS += -I$(PWD)/../../DEFS
obj-m += openair_rf.o
openair_rf-objs += module_main.o irq.o fileops.o exmimo_fw.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
rm -rf *.o
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
echo "Hint: this may not work if /usr/src/linux is not set to currently booted kernel."
echo "Try 'make' instead."
make -C /usr/src/linux V=1 M=`pwd`
#ifndef __DEFS_H__
#define __DEFS_H__
#include <asm/io.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <asm/segment.h>
#include <asm/page.h>
#include <asm/delay.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/slab.h>
//#include <linux/config.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h>
#ifdef KERNEL2_6
#include <linux/slab.h>
#endif
#include "openair_device.h"
#include "linux/moduleparam.h"
/*------------------------------------------------*/
/* Prototypes */
/*------------------------------------------------*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
long openair_device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
#else
int openair_device_ioctl(struct inode *inode,struct file *filp, unsigned int cmd, unsigned long arg);
#endif
int openair_device_open (struct inode *inode,struct file *filp);
int openair_device_release (struct inode *inode,struct file *filp);
int openair_device_mmap (struct file *filp, struct vm_area_struct *vma);
int exmimo_memory_alloc(int card);
int exmimo_firmware_init(int card);
int exmimo_firmware_cleanup(int card_id);
int exmimo_send_pccmd(int card_id, unsigned int cmd);
#endif
#!/bin/sh
# Re-Enumerate FPGA card
# After resetting or powering up the card or after reloading the FPGA bitstream,
# run this script to re-enumerate the PCIe device in Linux.
# You may need to change the device path. Check lspci output for this.
# You need to run this as root:
# sudo ./do_reenumerate_expressmimo.sh
# Matthias <ihmig@eurecom.fr>, 2013
rmmod openair_rf
echo 1 > /sys/bus/pci/devices/0000\:01\:00.0/remove
echo 1 > /sys/bus/pci/devices/0000\:05\:00.0/remove
echo 1 > /sys/bus/pci/rescan
insmod openair_rf.ko
rmmod openair_rf && sleep 1 ; insmod openair_rf.ko
This diff is collapsed.
#ifndef __EXTERN_H__
#define __EXTERN_H__
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pci.h>
#ifdef KERNEL2_6
#include <linux/slab.h>
#endif
#include "defs.h"
#include "pcie_interface.h"
extern char number_of_cards;
extern int major;
extern struct pci_dev *pdev[MAX_CARDS];
extern void __iomem *bar[MAX_CARDS];
extern void *bigshm_head[MAX_CARDS];
extern void *bigshm_currentptr[MAX_CARDS];
extern dma_addr_t bigshm_head_phys[MAX_CARDS];
extern dma_addr_t pphys_exmimo_pci_phys[MAX_CARDS];
extern exmimo_pci_interface_bot_t *p_exmimo_pci_phys[MAX_CARDS];
extern exmimo_pci_interface_bot_virtual_t exmimo_pci_kvirt[MAX_CARDS];
#endif // __EXTERN_H__
This diff is collapsed.
/** irq.c
- IRQ Handler: IRQ from Leon to PCIe/Kernel: exmimo_irq_handler
- sends received packets to userspace
- send command from PC to Leon and trigger IRQ on Leon using CONTROL1 register
- commands are defined in $OPENAIR0/express-mimo/software/pcie_interface.h
- added: pass card_id as parameter to tasklet and irq handler
Authors:
Raymond Knopp <raymond.knopp@eurecom.fr>
Matthias Ihmig <matthias.ihmig@mytum.de>, 2011, 2013
*/
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/swab.h>
#include "openair_device.h"
#include "extern.h"
unsigned int openair_bh_cnt;
int get_frame_done = 0;
void pcie_printk(int card_id);
void openair_do_tasklet (unsigned long card_id);
DECLARE_TASKLET (openair_tasklet, openair_do_tasklet, 0);
irqreturn_t openair_irq_handler(int irq, void *cookie)
{
unsigned int irqval;
unsigned int irqcmd = EXMIMO_NOP;
unsigned long card_id; // = (unsigned long) cookie;
unsigned int pcie_control = PCIE_CONTROL2;
// check interrupt status register
//pci_read_config_word(pdev[0],6 , &irqval);
// find card_id. cookie is set by request_irq and static, so we will always find it
for (card_id=0; card_id<MAX_CARDS; card_id++)
if ( pdev[card_id] == cookie )
break;
if (exmimo_pci_kvirt[card_id].exmimo_id_ptr->board_swrev == BOARD_SWREV_LEGACY)
pcie_control = PCIE_CONTROL1;
else
pcie_control = PCIE_CONTROL2;
//printk("irq hndl called: card_id=%i, irqval=%i\n", card_id, irqval);
// get AHBPCIE interrupt line (bit 7) to determine if IRQ was for us from ExMIMO card, or from a different device
// reading CONTROL0 will also clear this bit and the LEON-to-PC IRQ line
irqval = ioread32(bar[card_id]+PCIE_CONTROL0);
irqcmd = ioread32(bar[card_id]+pcie_control);
//printk("IRQ handler: ctrl0: %08x, ctrl1: %08x, ctrl2: %08x, status: %08x\n", irqval, ioread32(bar[card_id]+PCIE_CONTROL1), ioread32(bar[card_id]+PCIE_CONTROL2), ioread32(bar[card_id]+PCIE_STATUS));
if ( (irqval & 0x80) == 0 ) { // CTRL0.bit7 is no set -> IRQ is not from ExMIMO i.e. not for us
if (exmimo_pci_kvirt[card_id].exmimo_id_ptr->board_swrev == BOARD_SWREV_CMDREGISTERS){
if (irqcmd != EXMIMO_NOP && irqcmd != EXMIMO_CONTROL2_COOKIE) {
if (irqcmd == GET_FRAME_DONE)
{
get_frame_done = 1;
}
openair_tasklet.data = card_id;
tasklet_schedule(&openair_tasklet);
openair_bh_cnt++;
return IRQ_HANDLED;
}
else
{
return IRQ_NONE;
}
}
else
return IRQ_NONE;
}
else
{
if (exmimo_pci_kvirt[card_id].exmimo_id_ptr->board_swrev == BOARD_SWREV_LEGACY){
// clear PCIE interrupt (bit 7 of register 0x0)
iowrite32(irqval&0xffffff7f,bar[card_id]+PCIE_CONTROL0);
}
if (irqcmd == GET_FRAME_DONE)
{
get_frame_done = 1;
}
openair_tasklet.data = card_id;
tasklet_schedule(&openair_tasklet);
openair_bh_cnt++;
return IRQ_HANDLED;
}
}
void openair_do_tasklet (unsigned long card_id)
{
int save_irq_cnt = openair_bh_cnt;
unsigned int irqcmd;
unsigned int pcie_control = PCIE_CONTROL2;
openair_bh_cnt = 0;
if (exmimo_pci_kvirt[card_id].exmimo_id_ptr->board_swrev == BOARD_SWREV_LEGACY)
pcie_control = PCIE_CONTROL1;
else
pcie_control = PCIE_CONTROL2;
irqcmd = ioread32(bar[card_id]+pcie_control);
if (save_irq_cnt > 1)
printk("[openair][IRQ tasklet(%ld)]: Warning: received more than 1 PCIE IRQ (openair_bh_cnt=%i), only the last one is acted upon(irqcmd= %i (0x%X)\n", card_id, openair_bh_cnt, irqcmd, irqcmd);
switch( irqcmd )
{
case PCI_PRINTK:
// printk("Got PCIe interrupt for printk ...\n");
pcie_printk((int) card_id);
break;
case GET_FRAME_DONE:
printk("[openair][IRQ tasklet] : Got PCIe interrupt for GET_FRAME_DONE ...\n");
break;
case EXMIMO_NOP:
printk("[openair][IRQ tasklet] : Received IRQ, with CONTROL0.bit7(IRQ Leon2PC) set, but irqcmd = EXMIMO_NOP. This should not happen with bitstreams built after June 3rd 2013.\n");
break;
default:
printk("[openair][IRQ tasklet] : Got unknown PCIe cmd: card_id = %li, irqcmd(CONTROL1) = %i (0x%X)\n", card_id, irqcmd, irqcmd);
}
iowrite32(EXMIMO_NOP, bar[card_id]+pcie_control);
}
void pcie_printk(int card_id)
{
char *buffer = exmimo_pci_kvirt[card_id].printk_buffer_ptr;
unsigned int len = ((unsigned int *)buffer)[0];
unsigned int off=0,i;
unsigned char *dword;
unsigned char tmp;
//printk("In pci_fifo_printk : buffer %p, len %d: \n",buffer,len);
printk("[LEON card%d]: ", card_id);
if (len<1024)
{
if ( (len&3) >0 )
off=1;
for (i=0; i<(off+(len>>2)); i++)
{
dword = &((unsigned char *)buffer)[(1+i)<<2];
tmp = dword[3];
dword[3] = dword[0];
dword[0] = tmp;
tmp = dword[2];
dword[2] = dword[1];
dword[1] = tmp;
}
for (i=0; i<len; i++)
printk("%c",((char*)&buffer[4])[i]);
}
}
This diff is collapsed.
kernel//homes/ghaddab/riadh/openair4G/trunk/targets/ARCH/EXMIMO/DRIVER/eurecom/openair_rf.ko
#include <linux/module.h>
#include <linux/vermagic.h>
#include <linux/compiler.h>
MODULE_INFO(vermagic, VERMAGIC_STRING);
struct module __this_module
__attribute__((section(".gnu.linkonce.this_module"))) = {
.name = KBUILD_MODNAME,
.init = init_module,
#ifdef CONFIG_MODULE_UNLOAD
.exit = cleanup_module,
#endif
.arch = MODULE_ARCH_INIT,
};
static const struct modversion_info ____versions[]
__used
__attribute__((section("__versions"))) = {
{ 0x4d6582e4, "module_layout" },
{ 0x6bc3fbc0, "__unregister_chrdev" },
{ 0x1fedf0f4, "__request_region" },
{ 0x12da5bb2, "__kmalloc" },
{ 0xf9a482f9, "msleep" },
{ 0xb8957094, "mem_map" },
{ 0x15692c87, "param_ops_int" },
{ 0x69a358a6, "iomem_resource" },
{ 0x763c5db, "dma_set_mask" },
{ 0x184a8a78, "pci_disable_device" },
{ 0x38620fb, "__register_chrdev" },
{ 0x3573f04f, "x86_dma_fallback_dev" },
{ 0xeae3dfd6, "__const_udelay" },
{ 0xb74d03f5, "pci_set_master" },
{ 0x2bc95bd4, "memset" },
{ 0x50eedeb8, "printk" },
{ 0xae88b44d, "ipipe_percpu" },
{ 0xfaef0ed, "__tasklet_schedule" },
{ 0x2f287f0d, "copy_to_user" },
{ 0xb4390f9a, "mcount" },
{ 0x16305289, "warn_slowpath_null" },
{ 0x7e61808f, "dma_release_from_coherent" },
{ 0x2072ee9b, "request_threaded_irq" },
{ 0x98fb1f75, "dma_alloc_from_coherent" },
{ 0xa8a6f639, "__check_region" },
{ 0x19c39034, "pci_bus_read_config_word" },
{ 0x7c61340c, "__release_region" },
{ 0x37a0cba, "kfree" },
{ 0xf85828f1, "remap_pfn_range" },
{ 0xec591975, "dma_supported" },
{ 0xedc03953, "iounmap" },
{ 0x7628f3c7, "this_cpu_off" },
{ 0x94828082, "pci_get_device" },
{ 0x471d2cd9, "pci_iomap" },
{ 0x436c2179, "iowrite32" },
{ 0xc1a6619, "pci_enable_device" },
{ 0x362ef408, "_copy_from_user" },
{ 0xf358d5ac, "dma_ops" },
{ 0xe484e35f, "ioread32" },
{ 0xf20dabd8, "free_irq" },
};
static const char __module_depends[]
__used
__attribute__((section(".modinfo"))) =
"depends=";
MODULE_INFO(srcversion, "BAA63F2436D299D87A90400");
#!/bin/bash
PCI=`lspci -m | grep Xilinx`
if [ -z "$PCI" ]; then
echo "No card found. Stopping!"
return
fi
SLOT_NUMBER=`echo $PCI | awk -F\" '{print $1}'`
setpci -s $SLOT_NUMBER 60.b=10
#ifndef __VARS_H__
#define __VARS_H__
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pci.h>
#ifdef KERNEL2_6
#include <linux/slab.h>
#endif
#include "defs.h"
#include "pcie_interface.h"
unsigned int openair_irq_enabled[MAX_CARDS] = INIT_ZEROS;
unsigned int openair_chrdev_registered = 0;
unsigned int openair_pci_device_enabled[MAX_CARDS] = INIT_ZEROS;
struct pci_dev *pdev[MAX_CARDS] = INIT_ZEROS;
void __iomem *bar[MAX_CARDS] = INIT_ZEROS;
resource_size_t mmio_start[MAX_CARDS] = INIT_ZEROS;
resource_size_t mmio_length[MAX_CARDS];
unsigned int mmio_flags[MAX_CARDS];
int major;
char number_of_cards;
// bigshm allocs a single larger block, used for shared structures and pointers
dma_addr_t bigshm_head_phys[MAX_CARDS] = INIT_ZEROS;
void *bigshm_head[MAX_CARDS] = INIT_ZEROS;
void *bigshm_currentptr[MAX_CARDS];
dma_addr_t pphys_exmimo_pci_phys[MAX_CARDS]; // phys pointer to pci_bot structure in shared mem
exmimo_pci_interface_bot_t *p_exmimo_pci_phys[MAX_CARDS] = INIT_ZEROS; // inside struct has physical (DMA) pointers to pci_bot memory blocks
exmimo_pci_interface_bot_virtual_t exmimo_pci_kvirt[MAX_CARDS]; // has virtual pointers to pci_bot memory blocks
#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